I'm learning C# and Winforms with SharpDevelop and trying to do a very bare-bones synth. I just want a sine wave to play when the button is pressed and for the sine wave to stop when it's released. Here is the relevant code:
public class SharpSynth : Form
{
Timer myTimer = new Timer();
public SharpSynth()
{
myTimer.Interval = 500;
myTimer.Start();
Button SineButton = new Button();
SineButton.MouseDown += new EventHandler(ButtonDown);
SineButton.MouseUp += new EventHandler(ButtonUp);
Controls.Add(SineButton);
}
private void ButtonDown(object sender, System.EventArgs e)
{
myTimer.Tick += new EventHandler(WriteSine);
}
private void ButtonUp(object sender, System.EventArgs e)
{
myTimer.Tick -= EventHandler(WriteSine);
}
private void WriteSine()
{}
}
I've seen wave files written to a stream with MemoryStream and SoundPlayer, but it seems like these need wave headers, one of which is the number of samples and another is the file size. I need to be able to write raw audio of arbitrary length. Or should each chunk for each tick have its own wave headers? I'm really just wondering what to put in the WriteSine function to make this work. I've seen NAudio recommended, but I'd like to learn the pure .NET libraries first.
Edit: I have some relevant questions and research here
Creating sine or square wave in C#
Best way to use the System.Media.Soundplayer class
I'm just not sure how to use them.
Related
I am developing a real-time computer vision application using C#. But I am not able to optimize Emgucv decoding. I have 800-millisecond delay from the ground truth and 600-millisecond delay from the Ip camera provider application AXIS.
How can I optimize the code that I can have at-most 250-milliseconds delay?
Here is code for grabbing an image.
capture1 = new Capture(IpFirstCamTxt.Text); //create a camera captue from RTSP Stream
capture2 = new Capture(Ip2ndCamTxt.Text);
capture3 = new Capture(Ip3rdCamTxt.Text);
capture4 = new Capture(Ip4thCamTxt.Text);
capture1.Start();
capture2.Start();
capture3.Start();
capture4.Start();
capture1.ImageGrabbed += ProcessFrame1;
capture2.ImageGrabbed += ProcessFrame2;
capture3.ImageGrabbed += ProcessFrame3;
capture4.ImageGrabbed += ProcessFrame4;
private void ProcessFrame1(object sender, EventArgs arg)
{
_capture.RetrieveBgrFrame().ToBitmap());
capture1.Retrieve(img1, 3);
pictureBox1.Image = img1.ToBitmap();
}
private void ProcessFrame2(object sender, EventArgs arg)
{
capture2.Retrieve(img2, 3);
pictureBox3.Image = img2.ToBitmap();
}
private void ProcessFrame3(object sender, EventArgs arg)
{
capture3.Retrieve(img3, 3);
pictureBox4.Image = img3.ToBitmap();
}
private void ProcessFrame4(object sender, EventArgs arg)
{
capture4.Retrieve(img4, 3);
pictureBox5.Image = img4.ToBitmap();
}
Stopwatch results of my application comparing with camera provider application:
The above-mentioned problem has been solved using one of the real-time RTSP stream capturing library named as LIVE555. I have used it in C++ and shared the memory of images with C#.
The delay is reduced up to round about 200 milliseconds only.
If anyone wants real-time video streaming then LIVE555 is the best.
I will upload the project to my Github.
Source Real-time RTSP Stream Decoding
Problem:
As a part of school project, I attempt to build an application that provides a guitar AMP using the NAudio library.
When i plug in the guitar it recognizes it, and everything is working properly, but there is a huge delay between the input and the output from the speakers.
Here is my source code:
private void button2_Click(object sender, EventArgs e)
{
if (sourceList.SelectedItems.Count == 0) return;
int deviceNumber = sourceList.SelectedItems[0].Index;
sourceStream = new WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(deviceNumber).Channels);
sourceStream.StartRecording();
WaveInProvider waveIn = new WaveInProvider(sourceStream);
waveOut = new DirectSoundOut();
waveOut.Init(waveIn);
waveOut.Play();
}
in this code I catch an event of a button click that uses the selected input (microphone/guitar) and converts the sound it recieves to output.
The delay between the input and the output is around ~1sec and it's a deal breaker.
How do I improve the delay, to make the application more responsive?
DirectSoundOut and WaveIn are not particularly low-latency audio APIs. For something like this, ASIO is preferable. AsioOut is unfortunately a bit more complicated to work with, but it should allow you to get much lower latencies.
I downloaded the Vlc.DotNet project from Github and have been adding more functionalities to its Sample Forms application. Everything goes fine, except on thing: I noticed that every time I start the application and play an audio, the audio sounds like its volume is 100% (or something around that) - even after I set it to a lower value.
I tried setting the volume before playing the audio, but it didn't work.
If I debug the code, I see that the volume is always set to -1.
For instance, if I execute the following lines of code, after setting the volume to 40, when I debug it, the volume is still -1:
myVlcControl.Play(new FileInfo(FileName));
myVlcControl.Audio.Volume = 40;
Change the order of the lines above also doesn't work.
The funny thing is, when the audio is already playing and I change the volume,it is successfully changed to the select value on the NumericUpDown. The code below is the event where this happens:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
myVlcControl.Audio.Volume = (int)numericUpDown1.Value;
}
I've been trying to solve this problem for two days now. Unfortunately, my coding skills are not even close the people behind this project. I have already posted this problem on their Issues page on Github, but since there are questions since November without replies, I decided to try the StackOverflow. Hopefully someone here uses Vlc.DotNet and have a solution for my problem.
That being said:
Does anyone have the same problem?
Does anyone know how to solve it?
Any suggestions?
Thanks!
[EDIT on Jan 8, 2016, 11:50 AM GMT-2]
The user higankanshi on Github answered me the following:
I have found the problem.
You should use LibVlc 2.2.0(or later).
Vlc.DotNet is using LibVlc 2.1.5
Then, I executed some tests and came to the following conclusions:
You're right. Using the LibVlc 2.2.0 I'm able to set the Volume before playing.
Unfortunately, for some reason, setting the volume before playing the audio only works on the first time the application is opened. After stopping the audio, changing the volume, and playing it again, the volume doesn't change anymore - only changes while playing.
Here are the steps with results:
Execute the application;
Change the volume at run time before playing an audio file;
Play the audio file;
RESULT: the audio plays at the specified volume, successfully! =)
Press Stop;
Change the volume again;
Press Play again (at this point, the implementation inside the play method should get the new volume information);
RESULT: the audio plays again at the same volume it played before. Setting the volume doesn't work anymore.
I'm doing my tests on the Vlc.DotNet.Forms.Samples - CLR 4 - .Net 4.5 project. The changes I've made to the project were:
Added a NumericUpDown control, so that I could change the volume at run time;
Associated the ValueChanged event to the NumericUpDown control, so that every time it changes the value, the new value is passed to the VlcControl;
Created a Play() function that always gets the last volume value before playing the audio;
My code is below:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
myVlcControl.Audio.Volume = (int)numericUpDown1.Value;
}
private void Play()
{
myVlcControl.Audio.Volume = (int)numericUpDown1.Value;
myVlcControl.Play(new FileInfo(FileName));
}
private void OnButtonPlayClicked(object sender, EventArgs e)
{
Play();
}
private void OnButtonStopClicked(object sender, EventArgs e)
{
myVlcControl.Stop();
}
private void OnButtonPauseClicked(object sender, EventArgs e)
{
myVlcControl.Pause();
}
Any ideas?
I have found working solution:
int volume { get; set; }
public Constructor(){
InitializeComponent();
myVlcControl.VideoOutChanged += myVlcControl_VideoOutChanged;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
this.volume = (int)numericUpDown1.Value;
myVlcControl.Audio.Volume = volume;
}
void vlcPlayer_VideoOutChanged(object sender, VlcMediaPlayerVideoOutChangedEventArgs e)
{
myVlcControl.Audio.Volume = volume;
}
This seems to work for both file and stream.
How would this work. Default 40, if you need volume changed at start of playback:
myVlcControl.Audio.Volume = volume;
and add basic function to MediaChanged event to verify that volume is always correct. Also, might be good idea to add slider from 0-200 and default is to 40 -> ValueChanged event -> volume = volumeSlider.Value;
private static int volume = 40;
private void volume_changer(int vol)
{
volume = vol;
}
private void preview_Player_MediaChanged(object sender, Vlc.DotNet.Core.VlcMediaPlayerMediaChangedEventArgs e)
{
preview_Player.Audio.Volume = volume;
}
My working solution is same as Marcin Bigorge explained above.
vlcControl.TimeChanged += vlcControl_VideoOutChanged;
private void vlcControl_VideoOutChanged(object sender, VlcMediaPlayerTimeChangedEventArgs e)
{
vlcControl.Audio.Volume = volume;
}
Im new to using Wasapi in Naudio and Im having n issue with the sound quality. About 1/10 times the audio will sound perfect when I record and the other 9 times it will be fuzzy. I was wondering if there is any reason for this.
Here is my code i'm using to record the audio:
public void CaptureAudio(String Name)
{
capture = new WasapiLoopbackCapture();
capture.Initialize();
w = new WaveWriter(Name, capture.WaveFormat);
capture.DataAvailable += (s, capData) =>
{
w.Write(capData.Data, capData.Offset, capData.ByteCount);
};
capture.Start();
}
public void StartRecording(String Name)
{
new Thread(delegate(){CaptureAudio(Name); }).Start();
}
public void StopCapture()
{
capture.Stop();
capture.Dispose();
w.Dispose();
}
First of all. As Mark already said, your code does not look like NAudio. It looks like CSCore. If you are using CSCore please create a new console application and copy paste the following code (I've modified your code). I just tried out that code on three different systems without any bugs and all 20 files were ok without beeing fuzzy.
private static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
Console.WriteLine(i);
Capture(i);
}
}
private static void Capture(int index)
{
string Name = String.Format("dump-{0}.wav", index);
using (WasapiCapture capture = new WasapiLoopbackCapture())
{
capture.Initialize();
using (var w = new WaveWriter(Name, capture.WaveFormat))
{
capture.DataAvailable += (s, capData) => w.Write(capData.Data, capData.Offset, capData.ByteCount);
capture.Start();
Thread.Sleep(10000);
capture.Stop();
}
}
}
The problem turned out to be xbox music or windows media player running in the background, apparently they hog all the sound cards resources.
A few comments on your code:
First, have you modified WasapiLoopbackCapture in some way? The WaveInEventArgs on DataAvailable does not have the properties shown in your code. I'd expect you have some kind of block alignment error going on, so that your fuzzy sound is not reading on exact sample boundaries. Also NAudio does not have a class called WaveWriter - it's WaveFileWriter. Are you sure you are using NAudio?
Second, there is no need to start a new thread in StartRecording. WasapiLoopbackCapture will be using a background thread already.
So I'm trying to use a soundplayer to load a wav file, and then fire an event after it's done loading it. Reason being is that I don't want my program to continue on until the WAV is fully loaded and ready to go (if there's another way to do this, let me know).
But unfortunately the LoadCompleted event is never firing!
Here's the last of what I tried. What am I doing wrong?
this.audio = new SoundPlayer();
audio.SoundLocation = "songs\\" + songname + ".wav";
audio.LoadAsync();
that belongs to the songdata object. Then I have this is the main class main method:
this.songdata.audio.LoadCompleted += new AsyncCompletedEventHandler(audio_LoadCompleted);
this.songdata.audio.Play();
lastly inside the main class:
void audio_LoadCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("aaa");
}
The file starts playing, but the message box never appears. BTW I'm using Visual Studio 2010 and .NET 4.0.
I got the following code to send me a LoadCompleted event, I had, however, the "event callback function" in the same class as the SoundPlayer object.
class MediaPlayer{
System.Media.SoundPlayer soundPlayer;
public MediaPlayer(MemoryStream stream){
soundPlayer = new System.Media.SoundPlayer(stream);
soundPlayer.LoadCompleted += new AsyncCompletedEventHandler(player_LoadCompleted);
soundPlayer.Load();
}
public void Play(){
soundPlayer.Play();
}
// Handler for the LoadCompleted event.
private void player_LoadCompleted(object sender, AsyncCompletedEventArgs e){
Console.WriteLine("LoadCompleted");
}
}