/// <summary> /// Utility class to intercept audio from an IWaveProvider and /// save it to disk /// </summary> public class WaveRecorder : IWaveProvider, IDisposable { private WaveFileWriter writer; private IWaveProvider source; /// <summary> /// Constructs a new WaveRecorder /// </summary> /// <param name="destination">The location to write the WAV file to</param> /// <param name="source">The source Wave Provider</param> public WaveRecorder(IWaveProvider source, string destination) { this.source = source; this.writer = new WaveFileWriter(destination, source.WaveFormat); } /// <summary> /// Read simply returns what the source returns, but writes to disk along the way /// </summary> public int Read(byte[] buffer, int offset, int count) { int bytesRead = source.Read(buffer, offset, count); writer.WriteData(buffer, offset, bytesRead); return bytesRead; } /// <summary> /// The WaveFormat /// </summary> public WaveFormat WaveFormat { get { return source.WaveFormat; } } /// <summary> /// Closes the WAV file /// </summary> public void Dispose() { if (writer != null) { writer.Dispose(); writer = null; } } }
Now we have our WaveRecorder, we can insert it anywhere in the chain we like. The most obvious place is right at the end of the chain. So we wrap the WaveStream or WaveProvider we would normally pass to the Init method of our IWavePlayer with the WaveRecorder class. To demonstrate, I will extend the sine wave generating code I created recently, to save the sine wave you are playing to disk. Only three extra lines of code are required:
IWavePlayer waveOut; WaveRecorder recorder; private void button1_Click(object sender, EventArgs e) { StartStopSineWave(); } void StartStopSineWave() { if (waveOut == null) { var sineWaveProvider = new SineWaveProvider16(); sineWaveProvider.SetWaveFormat(16000, 1); // 16kHz mono sineWaveProvider.Frequency = 500; sineWaveProvider.Amplitude = 0.1f; recorder = new WaveRecorder(sineWaveProvider, @"C:\Users\Mark\Documents\sine.wav"); waveOut = new WaveOut(); waveOut.Init(recorder); waveOut.Play(); } else { waveOut.Stop(); waveOut.Dispose(); waveOut = null; recorder.Dispose(); recorder = null; } }
24 comments:
I have a problem with this.
"LineOutRecorder.WaveRecorder' does not implement interface member 'NAudio.Wave.IWaveProvider.Read(NAudio.Wave.IWaveBuffer)"
Source:
http://www.paste.lt/paste/879522bf8c12bb7e6c6a7ab7eaad9d22
Sollution explorer screenshot:
http://i647.photobucket.com/albums/uu198/n2oo/sollution.png
hi n20,
have you got the very latest NAudio source code out from Codeplex?
Version that I tried I downloaded today from Codeplex.
You need to go to the source code tab and download the latest and build it. NAudio 1.3 has not yet been released yet.
Here's the code for the latest IWaveProvider:
http://naudio.codeplex.com/sourcecontrol/changeset/view/28979?projectName=naudio#258022
Hi Mark,
I would like to record only the audio from one single application that plays music. is that possible with the NAUDIO lib ?
thanks!
Jelle
Thank You for replay Mark,
Here I found nice recording application example:
http://opensebj.blogspot.com/2009/04/naudio-tutorial-5-recording-audio.html
Is it possible to programmicaly select the recording device? (choose between mic, line-in and wave etc.)
BTW I am using XP, seems that newest NAudio Demo has that function but as exeption said "This functionality is only supported on Windows Vista or newer."
One more question about recorder buffer, it contais bytes, so each audio sample is 8bit or divided into several array elements?
hi n2o, you can't use WASAPI capture on XP. Use WaveIn instead. See my voice recorder article on the Coding4Fun website to learn more about recording audio in NAudio.
http://blogs.msdn.com/coding4fun/archive/2009/10/08/9905168.aspx
Hi Mark! I'm on Windows 7 and am struggling to get NAudio to record the stereo mix - is this possible, maybe using WASAPI as opposed to WaveIn? I'm not sure how to do this with NAudio if it is.
I've used the tutorial example 5 from Codeplex and clicked the "Record all output from my soundcard" button, but it only records what is coming in from the microphone. Any pointers would be greatly appreciated!! Many thanks.
hi JC, it probably depends on your sound-card drivers whether any of the WaveIn options can do this programatically. You might need to get the windows mixer up to select your recording source to make it work.
HI,
Now i am able to capture sound and at the same time i send it over network like this
private void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
byte[] buffer = e.Buffer;
byte[] dataToWrite = ALawEncoder.ALawEncode(buffer);
if (socket_Audio != null)
socket_Audio.SendTo(dataToWrite, new IPEndPoint(IPAddress.Parse(RemoteIpv6), SoundPort));
}
Now the problem that i am facing is how to get back this audio at receiving end and and send it to the speaker of the system
I am just starting a new thread for rxving data from network
myAudioThread = new Thread(new ThreadStart(AudioListener));
myAudioThread.Start();
And in the AudioListener() i use the following code
#region for Audio socket Its rxving audio always
try
{
socket_Audio = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
socket_Audio.Bind(new IPEndPoint(IPAddress.IPv6Any, SoundPort));
IPEndPoint remoteEP = new IPEndPoint(IPAddress.IPv6Any, SoundPort);
//Receive data.
byte[] byteData;
while (true)
{
byteData = new byte[2048];
//Receive data.
socket_Audio.Receive(byteData);
//G711 compresses the data by 50%, so we allocate a buffer of double
//the size to store the decompressed data.
byte[] byteDecodedData = new byte[byteData.Length * 2];
//Decompress data using the proper vocoder.
ALawDecoder.ALawDecode(byteData, out byteDecodedData);
}
Now the decoded audio is in the byte array byteDecodedData.How i send it to speaker of that system.
I found only waveOut.Play() and
public override int Read(byte[] buffer, int offset, int count)
{
//code to process data
}
in the examples
Pls guide me to the next step....Pls let me know if i am in wrong path.
Thanks
JIbin
jibin.mn@hotmail.com
@Jlbin - have a look at the BufferedWaveProvider in the latest code. This can be used to buffer up your data read from the network and can be used to feed the soundcard
Hi Mark,
Great lib by the way.
I just want to ask if you have any ideas about recording conversations?
Is it possible to capture it using WASAPI or, in my case since I'm using win XP, WaveIn? Or do you know any alternatives to that?
seemenomore1987@gmail.com
@Seingalt what do you mean by conversations? conversations on what program? if you mean skype, then you could look into using the Skype4Com object
Hi Mark,
I'd take a look at skype4com objects.
Basically, I have a web application that should allow the user to call (for example a Call Center Rep.) from that page and record that conversation.
I have done some research on skype4com already but somehow I'm still having a hard time on how I could use it on my application.
If you know or have any articles about it just post it here. Like "Using skype4com objects in your web application for biginners"
Thanks!
@Seingalt - check my Coding4Fun article and project - SkypeFx
Thanks for the great example. I already noticed it at NAudio but since it was not actually used in tehir code, the sample was very helpful.
One question: I would like to use the WaveRecorder combined with the ASIO4All. The NADIO Asio only has AsioOut.cs. Is there a sample of how the Wave Recorder is used for ASIO?
Thanks
HM
sadly NAudio ASIO support is very basic and doesn't work with all soundcards at the moment
Thanks Mark. I'm still hopefull, and struggeling with adding the ASIO-in interface by myself. I'm trying to figure out where to fit the WaveRecorder class.
Since WaveRecorder is actually an IWaveProvider, I plan to add AsioIn.cs which has "recordStream" of class WaveRecord (similar to AsioOut). I'm jyust confused wehther or not I need to add IWaveRecorder, similar to IWavePlayer.
Thanks you very much!
HM
@HM, an AsioIn class should implement IWaveIn
Can I use that source code on windows mobile? Or do you have a code that record a wave file format on windows mobile? (records in a wave file format ..)
I want to change the frequency of this sinus wave without interrupting it and quite quickly . You said in your previous posts that I need to do it smoothly , how can I do that ? Sorry but I'm a beginner
Post a Comment