Recording audio in C#
You will need the following requirements to complete this tutorial:
Recording from the Microphone
Recording: the process of capturing data or translating information to a format stored on a storage medium (or record). Lucky for us, analog-to-digital converters (ADC) take care of the translation for recording devices like a microphone. The only catch for us is providing a sampling rate against the analog wave. We used sampling when we streamed audio in our previous tutorial and we'll use it again here. The only difference about sampling from a recording device is that we are working with a different device. The code looks just about the same.
Setup a quick project that you can use for this tutorial. I created a new Windows Form project. You can create a whatever you like to complete the tutorial. Next, add a utility class called "RecordUtil.cs". Then add all the necessary references, make sure you set the Copy to Output Directory to "Copy if newer".
Add references
Taking a look at the left. Your solution explorer should contain the additions I mentioned before. That is:
- bass.dll
- bassenc.dll
- lame.exe
Having those in your project and output directory allows the final executing code to reference them without any issues running on different machines.
Next, we need to initialize the actual recording device. In the constructor of the RecordUtil place the following code snippet.
By initializing with the device 0, we will use the first recording device found by the Bass api.
Next, we're going to create the recording stream. You will need to set the sampling rate, the number of channels, BASSRecord flags, a callback function, and a user. The following code accomplishes this.
The first parameter is the sampling rate. This is the rate at which the analog wave is sampled (41000 times per second). The second parameter is the number of channels: 1 is mono, 2 is stereo. The third parameter is either the resolution (BASS_DEFAULT 16-bits, BASS_SAMPLE_8BITS 8-bit, BASS_SAMPLE_FLOAT - all of these choices will start the recording) BASS_RECORD_PAUSE starts the recording paused. Lastly, the fourth parameter is the callback function on each sample and the last parameter is the user associated with the recording.
Automatic versus manual recording
BASS has two methods of recording audio. When you do not specify null for the RECORDPROC callback function you must obtain the actual channel data using the BASS_ChannelGetData method. This is known as manual recording. Manual recording allows lower latency for full-duplex recording (i.e. playing the data as it's being recorded).
In an overloaded method for the BASS_RecordStart function, the third parameter is actually the period. The period defines the interval (in milliseconds) between calls to the callback function. The default is 100ms. (Minimum is 10ms, Maximum is 500ms).
If you do specify a callback to the RECORDPROC parameter, you are implementing automatic recording. All the data is obtained for you.
Then create the callback function and within the method you can simply return true. For the sake of this tutorial I will go into detail at a later post to explain the neat things you can access with the data.
LAME Encoder
In order to start recording with the parameter we chose, we need to use Channel_Play. But before we do that we are going to use the LAME encoder to stream the recording to an output file. Add the following code snippet:
I have added a field in the class called encoder. The EncoderLame class is in the Un4seen.Bass.Misc namespace. The first line simply constructs the encoder with the streaming channel (in our case the recording stream). Next, we set the OutputFile to the given path denoted output. The last lines of code are LAME specific variable configurations.
Aside from the bitrate and sample rate, Mode defines the encoding channel mode as in mono, stereo, join stereo.. etc. There are plenty of variables that you can configure, I have just configured the basics in this example. We want to sample at the same rate we created our recording channel at, use the default mode, encode according to quality, and have our bitrate at 192kbps (kilobits/sec).
Next, I have added four methods to handle different states in our recording program. They start out as the following:
The code here is pretty straight forward. When we call encoder.Start(null, 0) we are passing it a callback function and the associated user. The callback function allows us to work the encoding byte stream at each interval ourselves. This is very useful for us when we want to send the stream elsewhere like over a network.
The only thing left for us to do in this class is add the code for the Bass.Channel functions like we did in the previous tutorial on streaming audio. When you have that part done the final code should look like the following.
And there you go, the only missing piece is creating an interface the utilize this nice little recording utility. I've thrown a simple interface together to demonstrate this. When you're done with yours simply call the appropriate functions in the order: constructor, Initialize, Encode (with the output file), and setup a play, pause, and stop function.
Once you have your interface ready, you can make the calls to the functions you just created. When you're done your code should look something like the following code snippet.
Source code
Comments
hi,
the article is very nice... but there is some problem with the source code u provided..
well im totally a newbie in this field..
so i needed it for better understanding.
hi,this is usefull ,just i have problem with finding 3 reftrence that u told , i mean i can't find Bass.dll , bassenc.dll and lame.exe , i will so glad if u can help me because i nedd it so much for our project ( i want to record sound with mp3 format in c# )
thanks a million
You can download bass.dll by going here and clicking on the download link at the top for Windows.
Lastly, on this page you should see that the sixth add-on is Bassenc. Click the Windows download link there. Hope this helps :)
Thanks Again
public bool MyRecording(int handle, IntPtr buffer, int length, int user)
in second parameter is the buffer of the sound so how to convert intprt to bytes
Hello, thanks for the nice lesson. This is a helpful tutorial. I’m new to C# and recording audio. I hope me question don’t bother you. If I want to extend this tutorial to deal with multiple microphones, what are things that I have to do? I believe I have to initialize all devices in constructor “RecordUtil”. If I want to record all the input from different microphone into one file, how can I do that? And if I want to save then in different file is that possible. if you can guide me to a tutorial or your advice I will appreciate it. Thank you.
Hi Thomas. I'm trying to sort of do the opposite of this tutorial in that I want to
Thanks to you for this nice article. It seems very helpful.
However some
Thanks to you for this nice article. It seems very helpful.
However some problems occur because of the version differences I guess. I have 2 errors
1st one is about System.IntPtr casting. In the initialize function the last parameter "0" gives error since its type is int. So I cast it like "(System.IntPtr) 0"
2nd one is about Start functions argument list. In your code, it gets 2 parameters however it needs 3. The last parameter is "bool paused" so I added "false" parameter.
Then I succesfully compiled, When I start recording and stop it creates a file in the size of 1 or 2 kbs. But I guess there is a mistake, I can't play that file in winamp. How can I test it ? Can you explain to use this program also.
Waiting for your answer.
Thank you
Tuna
Hello Thomas,
Thanks to you for this nice article. It seems very helpful.
I need your help. Suppose if i want to capture audio from
Head phone. what should i do?
I am very eagerly expecting your mail.