Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to record any PC sound through WASAPI and Audio Sound Recorder for .NET

9 May 2014 1  
How to programmatically start, on Windows Vista and higher versions, a recording session of any sound being played through a specific output device by third-party applications like Windows Media Player or YouTube, by leveraging the WASAPI sub-system through Audio Sound Recorder for .NET.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

Introduction

Starting from Windows Vista, Microsoft has rewritten the multimedia sub-system of the Windows operating system from the ground-up; at the same time Microsoft introduced a new API named Core Audio API which allows interacting with the multimedia sub-system and with audio endpoint devices (sound cards). One of the new Core Audio APIs is the Windows Audio Session API (also known as WASAPI) which can manage three different types of devices:

  • Render devices are playback devices where audio data flows from the application to the audio endpoint device, which renders the audio stream.
  • Capture devices are recording devices where audio data flows from the audio endpoint device, that captures the audio stream, to the application.
  • Loopback devices are recording devices that capture the mixing of all of the audio streams being rendered by a specific render device, also if audio streams are being played by third-party multimedia application like Windows Media Player: each render device always has a corresponding loopback device.

How Audio Sound Recorder for .NET can be of help in managing WASAPI easily

As seen for most of the APIs developed by Microsoft, WASAPI consists of a combination of several COM interfaces whose usage is not always straightforward: Audio Sound Recorder for .NET allows developers leveraging in a easy way a subset of WASAPI features in order to create and manage audio streams to and from audio endpoint devices inside their applications.

The main points related to the usage of WASAPI features through the Audio Sound Recorder for .NET component are the following:

  • Initializing the WASAPI subsystem
  • Enumerating various types of audio endpoint devices (render, capture and loopback)
  • Starting the specific endpoint device and recording its data flow
  • Stopping the recording session and the specific audio endpoint device

In this tutorial we want to see how to start a recording session, from a capture device or from a loopback device, in order to store incoming audio data into an output sound file of a specific audio format with the possibility to playback the same file once the recording session is stopped.

The user interface of our sample application will look like this:

Initializing the WASAPI subsystem and the component’s recording system

By default Audio Sound Recorder for .NET accesses audio devices through DirectSound and WDM drivers so, in order to leverage WASAPI, we need to specify to the component that we want to use a different kind of drivers through the InitDriversType method, then we can initialize the component through the mandatory call to the InitRecordingSystem method:

private void Form1_Load(object sender, EventArgs e)
{
       // initialize usage of WASAPI audio drivers
       enumErrorCodes nReturn = audioSoundRecorder1.InitDriversType (enumDriverTypes.DRIVER_TYPE_WASAPI);
       if (nReturn == enumErrorCodes.ERR_INVALID_PLATFORM)
       {
             MessageBox.Show("This sample can only work on Windows Vista or higher versions.
                           The program will now close.");
             Close();
             return;
       }
 
       // init the control
       audioSoundRecorder1.InitRecordingSystem();
 
       // do other initialization stuffs
       ...

Enumerating various types of audio endpoint devices (render, capture and loopback)

After the drivers initialization we can enumerate available audio endpoint devices through the combination of WASAPI.DeviceGetCount and WASAPI.DeviceGetDesc methods that will also allow to fill a couple of combo boxes on the user interface; due to the fact that we will use this sample as a recording system, we are mainly interested in enumerating capture and loopback devices while for playback we will use the system default device:

       // enumerate audio input devices
       int nCaptureDevices = 0;
       audioSoundRecorder1.WASAPI.DeviceGetCount (enumWasapiDeviceTypes.WASAPI_DEVICE_TYPE_CAPTURE,
                                        ref nCaptureDevices);
       for (int i = 0; i < nCaptureDevices; i++)
       {
             string strCaptureDevice = audioSoundRecorder1.WASAPI.DeviceGetDesc (i,
                                        enumWasapiDeviceTypes.WASAPI_DEVICE_TYPE_CAPTURE);
             comboCaptureDevices.Items.Add(strCaptureDevice);
       }
 
       // enumerate loopback devices
       int nLoopbackDevices = 0;
       audioSoundRecorder1.WASAPI.DeviceGetCount (enumWasapiDeviceTypes.WASAPI_DEVICE_TYPE_LOOPBACK,
                                        ref nLoopbackDevices);
       for (int i = 0; i < nLoopbackDevices; i++)
       {
             string strLoopbackDevice = audioSoundRecorder1.WASAPI.DeviceGetDesc (i,
                                        enumWasapiDeviceTypes.WASAPI_DEVICE_TYPE_LOOPBACK);
             comboLoopbackDevices.Items.Add(strLoopbackDevice);
       }
 
       if (nCaptureDevices == 0 && nLoopbackDevices == 0)
       {
             MessageBox.Show("No capture device detected and/or connected");
             Close();
             return;
       }
 
       // do other stuffs
       ...

Starting the specific endpoint device and recording its data flow

We can now decide to start recording and saving on a sound file what Windows Media Player or YouTube are currently playing on our system: for their playback, usually these desktop or web applications make use of the system default render device so we should identify inside the combo box which loopback device corresponds to the system default render device: the first device listed on the combo box is the right one.

When pressing the "Start recording” button our sample’s code will start the loopback device through the StartWasapiDevice function (see below its detail) and the recording session through the StartFromWasapiLoopbackDevice method

private void buttonStartRecordingLoopback_Click(object sender, EventArgs e)
{
       // set the recording format
       ...
 
       // start the loopback device in shared mode
       if (!StartWasapiDevice(comboLoopbackDevices.SelectedIndex,
             enumWasapiDeviceTypes.WASAPI_DEVICE_TYPE_LOOPBACK))
             return;
 
       // start the recording session from the selected loopback device
       enumErrorCodes nResult = audioSoundRecorder1.StartFromWasapiLoopbackDevice
             (comboLoopbackDevices.SelectedIndex, m_strOutputPathname);
       if (nResult != enumErrorCodes.ERR_NOERROR)+
             MessageBox.Show("Cannot start recording due to error " + nResult.ToString());
}

Internally to the StartWasapiDevice function we verify if the chosen audio endpoint device is already started through the WASAPI.DeviceIsStarted method and, if not, we start it in shared mode through the WASAPI.DeviceStartShared method:

 
private bool StartWasapiDevice(int nDeviceIndex, enumWasapiDeviceTypes nDeviceType)
{
       // check if the given device is already started
       if (audioSoundRecorder1.WASAPI.DeviceIsStarted(nDeviceIndex, nDeviceType))
             // the device is already started
             return true;
 
       // start the device in shared mode
       enumErrorCodes nResult = audioSoundRecorder1.WASAPI.DeviceStartShared(nDeviceIndex,
             nDeviceType, enumWasapiChannelModes.WASAPI_CHANNEL_MODE_STEREO, 0, 0);
       if (nResult != enumErrorCodes.ERR_NOERROR)
       {
             // manage the error
             ...
 
             return false;
       }
 
       return true;
}

As mentioned, the call to the StartFromWasapiLoopbackDevice method will start recording anything being played through the chosen audio endpoint device and all incoming audio data will be stored inside an output file of a chosen format.

Stopping the recording session and the specific audio endpoint device

Once our recording session has enough audio data, we can stop the recording session through a call to the Stop method and, due to the fact that we no more need accessing the audio endpoint device, we can stop it as well through the WASAPI.DeviceStop method:

private void buttonStopRecordingLoopback_Click(object sender, EventArgs e)
{
       // stop the recording session
       audioSoundRecorder1.Stop();
 
       // stop the device
       audioSoundRecorder1.WASAPI.DeviceStop(comboLoopbackDevices.SelectedIndex,
                           enumWasapiDeviceTypes.WASAPI_DEVICE_TYPE_LOOPBACK, true);
}

Download the full WASAPI recorder example

You can download a fully functional demo which includes the features discussed above in both VB.NET and C#. To run these examples you will need the following:

  • Install Audio
    Sound Suite for .NET (fully functional trial version) http://www.multimediasoft.com/bins/asostnet_t.exe
  • Browse to "C:\Program Files\Audio Sound Suite for .NET\Audio Sound Recorder for .NET\Samples\[C#.NET or VB.NET] \WasapiRecorder" and compile the project

Support

Need help getting this sample up and going? Contact our support team for free technical support! For pricing or licensing questions, you can contact our sales team.

http://www.multimediasoft.com/contact

Company website http://www.multimediasoft.com

Follow on Facebook (https://www.facebook.com/MultiMediaSoft) or Twitter (https://twitter.com/MultiMediaSoft)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here