Click here to Skip to main content
13,148,573 members (54,263 online)
Click here to Skip to main content
Add your own
alternative version


39 bookmarked
Posted 16 Dec 2008

Audio Capture with DirectShow - Part 2

, 10 Feb 2009
Rate this:
Please Sign up or sign in to vote.
A console program that captures audio and saves it.


This is the second part of a two part tutorial on capturing audio via DirectShow. The first part shows how to connect an input device with an output device. This part shows how the captured audio can be saved to a file. This program does not provide functionality for simultaneous preview of audio capture while saving it to the disk.

What you should know first

I have written two small tutorials on how to read audio/video devices installed on a system. For those who do not know how to get hold of such devices, please take a look at these articles:

This would make it easier for you to understand this tutorial which uses a function that is explained in the previous two tutorials and which I will not be explaining here. Plus, a bit of understanding of COM programming is always helpful. The first part of the tutorial is available at the following link:

WAV format file being written

I am trying to access a "wav" file to write the audio data. I have tried to use the simplest of filters in order to do so. The GraphEdit image below clearly indicates the three different filters that are going to be used. The order of connection does matter, and programmatically, the orders are being followed. You should first try GraphEdit, and then try out the sample code.


Before using the code - The output file, "test.wav"

Before the code can be successfully compiled, you need to make sure you first have an audio file called "test.wav". The default location where the program looks for this file is "..\\test.wav". So, please make sure you have created a file with the Windows Sound Recorder, or use the one provided with this tutorial.

What has changed from the previous code

A lot has been changed from the first tutorial. So, to go with the flow, I will explain what has changed and what has been added in the new program.

Functions from the previous tutorial

//Function to initialize Input/Output devices
IBaseFilter* Device_Init(IMoniker*,IBaseFilter*);
//Function to add device to graph
void Device_Addition(IGraphBuilder*,IBaseFilter*,BSTR);
//Function to connect the two devices, in this case input and output
void Device_Connect(IBaseFilter*,IBaseFilter*);
//Function to run the graph
void Run_Graph(IMediaControl*); 
//Function to compare BSTR strings
bool Bstr_Compare(BSTR,BSTR);

Functions in this tutorial (including new and changed)

//Function to connect the two devices
void Device_Connect(IBaseFilter*,IBaseFilter*,BSTR,BSTR);
//Function to access default WAV file
IFileSinkFilter* Add_File(IGraphBuilder*,IBaseFilter*,IFileSinkFilter*,BSTR);

As you can see, the function Device_Connect(...) has been changed and two BSTR strings were added to the argument list. The two strings represent the FriendlyNames of the two pins that are going to be connected to. In the previous tutorial, the two pins that were being connected (and ultimately, the two devices from which the two pins were to be connected) were the mic and the output device, i.e., speaker, headphone, or whatever the strings represented. This time, however, since there are three filters that need to be connected, each filter has its own specific pin with a specific FriendlyName; so, the devices (i.e., filters) that are being connected must be distinguished via these two BSTR strings. Therefore, the code from Part 1 and Part 2 of the tutorial follows.

Device_Connect(...) from Part 1

void Device_Connect(IBaseFilter* pInputDevice,IBaseFilter* pOutputDevice)
    HRESULT hr;
    IEnumPins *pInputPin = NULL,*pOutputPin  = NULL;// Pin enumeration
    IPin *pIn = NULL, *pOut = NULL;// Pins

    hr = pInputDevice->EnumPins(&pInputPin);// Enumerate the pin
        cout<<"Input Pin Enumeration successful..."<<endl;
               //Get hold of the pin "Capture", as seen in GraphEdit
        hr = pInputDevice->FindPin(L"Capture",&pIn);
         cout<<"Capture pin found"<<endl;    
        else HR_Failed(hr);
    else HR_Failed(hr);
    hr = pOutputDevice->EnumPins(&pOutputPin);//Enumerate the pin
        cout<<"Output Pin Enumeration successful..."<<endl;
        hr = pOutputDevice->FindPin(L"Audio Input pin (rendered)",&pOut);
            cout<<"Audio Input Pin (rendered) found"<<endl;
        else HR_Failed(hr);

    else HR_Failed(hr);
    hr = pIn->Connect(pOut,NULL);    //Connect the input pin to output pin
            cout<<"Pin connection successful..."<<endl;
    else HR_Failed(hr);

Device_Connect(...) from Part 2

void Device_Connect(IBaseFilter* pInputDevice,IBaseFilter* pOutputDevice,
                    BSTR bstrInputPin,BSTR bstrOutputPin)
    HRESULT hr;
    IEnumPins *pInputPin = NULL,*pOutputPin  = NULL;// Pin enumeration
    IPin *pIn = NULL, *pOut = NULL;// Pins

    hr = pInputDevice->EnumPins(&pInputPin);// Enumerate the pin
        cout<<"Input Pin Enumeration successful..."<<endl;
        //Get hold of the pin as seen in GraphEdit
        hr = pInputDevice->FindPin(bstrInputPin,&pIn);
         wcout<<bstrInputPin<<" Input pin found"<<endl;    
        else HR_Failed(hr);
    else HR_Failed(hr);
    hr = pOutputDevice->EnumPins(&pOutputPin);//Enumerate the pin
        cout<<"Output Pin Enumeration successful..."<<endl;
        hr = pOutputDevice->FindPin(bstrOutputPin,&pOut);
            wcout<<bstrOutputPin<<" Output pin found"<<endl;
        else HR_Failed(hr);

    else HR_Failed(hr);

    hr = pIn->Connect(pOut,NULL);    //Connect the input pin to output pin
            cout<<"Pin connection successful..."<<endl;
    else HR_Failed(hr);

As you can clearly see, the code in the second part handles the BSTR strings to connect the different pins. The function Device_Connect(...) with the BSTR string values is called from the main().

//Connect input to output, AudioRecoder WAV
//Dest filter to test.wav i.e. File writer filter
//Input pin name, as seen in GraphEdit
bstrInPinName = SysAllocString(L"Out");
//Output pin name, this one will be input for File writer filter
bstrOutPinName = SysAllocString(L"in");

//connect Device_Connect(pWAVRecorder,pFileWriter,bstrInPinName,bstrOutPinName);

In the above code, the "AudioRecoder WAV Dest" filter represented by pWAVRecorder is being connected to the "File Writer" filter represented by pFileWriter. The pins' successful connection allows the program to proceed next.

Add_File (...) function

IFileSinkFilter* Add_File(IGraphBuilder *pGraph,IBaseFilter* pDevice, 
                          IFileSinkFilter* pFile,BSTR bstrName)
    HRESULT hr;
    // pointer to filter that allows data writing
    IFileSinkFilter *pFileSink= NULL;
    hr = pDevice->QueryInterface(IID_IFileSinkFilter, (void**)&pFile);
        wcout<<"Querying of IFileSinkFilter "<<bstrName<<" successful..."<<endl;
    else HR_Failed(hr);
    //setting the name of the file
    hr = pFile->SetFileName(bstrName,NULL);
        wcout<<"Setting name to "<<bstrName<<" successful..."<<endl;
    else HR_Failed(hr);
return pFileSink = pFile;

The Add_File(...) function adds the file "test.wav" to the filter. This function uses the IFileSinkFilter interface to access the Wav file "test.wav", and returns the pointers after a successful access. This function is very important in the order in which it is being called. If we try to add a pFileWriter filter to the graph prior to calling the Add_File(...) function, an error shall occur and the program will not work. This is best explained when we use the FileWriter filter in GraphEdit. When we try to add this filter to the graph from GraphEdit, the first thing that happens is that we are presented with a dialog box from which we must select the output file. Only after the file selection is the filter added to the graph. It is the same way here. We first access the default output file "test.wav" and then add it to the graph.

The line of code setting the file name is where we define the file to access.

hr = pFile->SetFileName(bstrName,NULL);

Ready to run

And finally, a call to Run_Graph(...) kick starts the whole graph. And, you should see the following screen. This is a screenshot of the program running on my system.


A note on the Wav file

Remember, we are accessing the output file without knowing or altering the attributes of the file. So, whenever you record using this program, the data is written from the start of the file, and the file is neither truncated, nor is any previous recording fully erased. So, a portion of the old recording will still remain if your record time is lesser than the original time length of test.wav.

Code bugs

The code is not professional by any means, and should be optimized whenever there is a need for a professional approach. The task was to explain the code in the simplest possible way, and to cater for very limited errors. The error handling part is very basic, and should not be used for professional applications as it just displays an error text. I expect bugs to appear, and will highly appreciate changes to the code itself!

The Code is Built with the Following

  • Windows Server 2008
  • Microsoft Visual Studio 2008
  • DirectX 10.1
  • Microsoft Windows SDK 6.1



  • 08/02/2008: Article updated.

    Fixed Bstr_Compare(...) that correctly compares two BSTR type strings.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Engineer -
Pakistan Pakistan
-I am a die hard fan of C/C++ programming. It is poetry and I love the poems of C++.
-I tell people that C# is "NOTHING" compared to C++ and I always say that!

My interest lie in Signal Processing, Image Processing,Video Processing, Pattern Recognition, DSP, Communications. Though I have no ONE stop in terms of interests.

You may also be interested in...

Comments and Discussions

QuestionFantastic! Pin
noiti6-Jun-16 6:26
membernoiti6-Jun-16 6:26 
AnswerRe: Fantastic! Pin
noiti6-Jun-16 17:33
membernoiti6-Jun-16 17:33 
Questionselect output device Pin
kinani2-Aug-11 16:28
memberkinani2-Aug-11 16:28 
AnswerRe: select output device Pin
wajih_ullah2-Aug-11 19:41
memberwajih_ullah2-Aug-11 19:41 
GeneralRe: select output device Pin
kinani6-Aug-11 15:29
memberkinani6-Aug-11 15:29 
AnswerRe: select output device Pin
kinani16-Aug-11 0:02
memberkinani16-Aug-11 0:02 
GeneralRe: select output device Pin
wajih_ullah16-Aug-11 5:42
memberwajih_ullah16-Aug-11 5:42 
QuestionAny alternative to 'AudioRecorder WAV Dest' Pin
Rick204724-Jun-09 21:01
memberRick204724-Jun-09 21:01 
I can't find anything like 'AudioRecorder WAV Dest'. Is there any alternative for this as in my PC graphEdit shows these: (Part 1 n related has worked nicely.)

WM Speech Encoder DMO
WMAudio Encoder DMO
Microsoft ADPCM
DSP Group TrueSpeech(TM)
Windows Media Audio V1
Windows Media Audio V2
GSM 6.10
Microsoft G.723.1
MPEG Layer-3
Realtek HD Audio output
Default DirectSound Device
Default WaveOut Device
DirectSound: Realtek HD Audio output
WMAudio Decoder DMO
WMSpeech Decoder DMO
Mpeg4s Decoder DMO
WMV Screen decoder DMO
WMVideo Decoder DMO
Mpeg43 Decoder DMO
Mpeg4 Decoder DMO
WMT MuxDeMux Filter
Full Screen Renderer
DV Muxer
Color Space Converter
WM ASF Reader
AVI Splitter
WMT AudioAnalyzer
VGA 16 Color Ditherer
Indeo® video 5.10 Compression Filter
Windows Media Audio Decoder
VideoSync Extended Filter for OpenCV
AC3 Parser Filter
WMT Format Conversion
WMT Black Frame Generator
MJPEG Decompressor
Indeo® video 5.10 Decompression Filter
WMT Screen Capture filter
Microsoft Screen Video Decompressor
MPEG-I Stream Splitter
SAMI (CC) Parser
MPEG Layer-3 Decoder
MPEG-2 Splitter Sipro Lab Audio Decoder
Internal Script Command Renderer
MPEG Audio Decoder
File Source (Netshow URL)
WMT Import Filter
DV Splitter
Bitmap Generate
Windows Media Video Decoder
Video Mixing Renderer 9
Windows Media Video Decoder
Record Queue
Windows Media Multiplexer
ASX file Parser
ASX v.2 file Parser
NSC file Parser
ACM Wrapper
Windows Media source filter
Video Renderer
Frame Eater
MPEG-2 Video Stream Analyzer
Line 21 Decoder
Video Port Manager
WST Decoder
Video Renderer
WM ASF Writer
WMT Sample Information Filter
VBI Surface Allocator
Microsoft MPEG-4 Video Decompressor
File writer
WMT Log Filter
WMT Virtual Renderer
DVD Navigator
Overlay Mixer2
AVI Draw
.RAM file Parser
WMT DirectX Transform Wrapper
G.711 Codec
MPEG-2 Demultiplexer
DV Video Decoder
Indeo® audio software
Windows Media Update Filter
ASF DIB Handler
ASF ACM Handler
ASF ICM Handler
ASF URL Handler
ASF JPEG Handler
ASF embedded stuff Handler
WIA Stream Snapshot Filter
Allocator Fix
Null Renderer
WMT Virtual Source
WMT Interlacer
Smart Tee
Overlay Mixer
AVI Decompressor
Uncompressed Domain Shot Detection Filter
AVI/WAV File Source
QuickTime Movie Parser
Wave Parser
MIDI Parser
Multi-file Parser
File stream renderer
XML Playlist
Line 21 Decoder 2
File Source (Async.)
File Source (URL)
WMT DV Extract
WMT Switch Filter
WMT Volume
Stretch Video
Infinite Pin Tee Filter
QT Decompressor
MPEG Video Decoder
Indeo® video 4.4 Decompression Filter
Indeo® video 4.4 Compression Filter
Default MidiOut Device
Microsoft GS Wavetable SW Synth
MSScreen encoder DMO
WMVideo9 Encoder DMO
MSScreen 9 encoder DMO
DV Video Encoder
Indeo® video 5.10 Compression Filter
MJPEG Compressor
Cinepak Codec by Radius
Intel 4:2Blush | :O Video V2.50
Intel Indeo(R) Video R3.2
Intel Indeo® Video 4.5
Indeo® video 5.10
Intel IYUV codec
Microsoft H.261 Video Codec
Microsoft H.263 Video Codec
Microsoft RLE
Microsoft Video 1

Realtek HD Digital input
Realtek HD Audio Input.

And which one is the common Name exists in almost all windows PC to save a wave file.For now for WinXPSP2+.


nothin is imposible.

AnswerRe: Any alternative to 'AudioRecorder WAV Dest' Pin
wajih_ullah26-Jun-09 5:43
memberwajih_ullah26-Jun-09 5:43 
Generalbuild errors (and resolution?) Pin
essetesse31-Mar-09 15:52
memberessetesse31-Mar-09 15:52 
GeneralWhy recording length is less...... Pin
RichardWdy2-Mar-09 22:50
memberRichardWdy2-Mar-09 22:50 
GeneralRe: Why recording length is less...... Pin
wajih_ullah3-Mar-09 3:56
memberwajih_ullah3-Mar-09 3:56 
GeneralRe: Why recording length is less...... Pin
RichardWdy3-Mar-09 15:32
memberRichardWdy3-Mar-09 15:32 
GeneralRe: Why recording length is less...... Pin
cocla15-Apr-09 15:13
membercocla15-Apr-09 15:13 
GeneralRe: Why recording length is less...... Pin
RichardWdy18-Apr-09 5:14
memberRichardWdy18-Apr-09 5:14 
GeneralRe: Why recording length is less...... Pin
cocla18-Apr-09 22:34
membercocla18-Apr-09 22:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170924.2 | Last Updated 10 Feb 2009
Article Copyright 2008 by wajih_ullah
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid