Hello,
I am fairly new to using NAudio and I'm currently trying to build a program, that can record for a few seconds after the microphone detects a sound level that exceeds a threshold I've set.
Currently, I'm checking the sound level (Root-mean squared) and writing to a WAV in the WaveIn EventHandler called source_DataAvailable and I have a flag called recordedFlag that is set to false.
Right now there is an 'if' statement that checks if the flag is false and if it is then there will be another 'if' statement inside that checks the RMS. If it exceeds the RMS set, then it will write to a WaveFileWriter object then sets the flag to true.
Since the EventHandler is constantly checking when the microphone is listening, the next time the 'if' statement checks the flag (it will be true), it will display a MessageBox and then dispose the WaveFileWriter, setting it to null and then changing the flag back to false, so the process can repeat.
I'm currently facing a few problems:
1) I can only get the 1 sound that exceeds the RMS (I know with the way I've set things up it only does this, but what I want to be able to write to a WAV for
a few seconds instead of writing 1 byte that was recorded, when the threshold exceeds and I do not know how)
2) I want the same WAV file to be overwritten with every successful recording, but I've noticed that there are 3 processor threads, so whenever I've written data to a WAV. There will be 3 different writes to the same waveWriter instance, causing the end WAV to be empty, due to the way I set up the flags
private void btnRecordEverything_Click(object sender, EventArgs e)
{
// Checks to see if any device was selected
if (lvSource.SelectedItems.Count == 0) return;
// Obtain device number from the index of the first selected item
int deviceNumber = lvSource.SelectedItems[0].Index;
// Inititalise the source stream
sourceStream = new NAudio.Wave.WaveIn();
// Set the device number to the source stream
sourceStream.DeviceNumber = deviceNumber;
// Assign a wave format with the standard 44.1kHz and the device number's channel
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(deviceNumber).Channels);
// source stream will want a new event when there is data available
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(source_DataAvailable);
// Inititalise WaveWriter
// Enter file location and make sure the format saved is the same as the source stream
waveWriter = new NAudio.Wave.WaveFileWriter("aaa.wav", sourceStream.WaveFormat);
sourceStream.StartRecording();
}
private bool recordedFlag = false;
private void source_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
// Checks if wave writer exists
if (waveWriter == null)
{
waveWriter = new NAudio.Wave.WaveFileWriter("aaa.wav", sourceStream.WaveFormat);
}
double rms = calculateDBinRMS(e);
string rmsFormatted = string.Format("{0:0.00}", rms); // Just formats the RMS value
int seconds = (int)(waveWriter.Length / waveWriter.WaveFormat.AverageBytesPerSecond); // Calculates the length of the WAV file
rbSoundLevel.AppendText(rmsFormatted + "\n"); // Writes RMS to the rich text box
if (recordedFlag == false)
{
if (rms > 800)
{
// Write data to the waveWriter
// Data is a byte array
// Offset set to 0 to write the whole array of data
// Count is the bytes recorded
waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
// Ensure wave file is written by flushing the data out with each write
// Prevent RAM from being held
waveWriter.Flush();
recordedFlag = true;
}
else
{
MessageBox.Show("Record success!");
waveWriter.Dispose();
waveWriter = null;
recordedFlag = false;
}
}
}
Here's the code and a link to the
pastebin code
In short, I just want to get my program to start writing to a WAV
for a few seconds when the mic picks up an audio level that exceeds the set threshold.