Using an Audio Delay DMO Within a DirectShow Application

Using an Audio Delay DMO Within a DirectShow Application

Before we explore the implementation specifics of a DMO, it ll be useful to examine how a DMO is instantiated, connected, and executed within a DirectShow filter graph. In this chapter, we ll be working with a very simple audio DMO, SimpleDelay, which adds a measured audio delay to an audio stream passed through it. The duration of the delay, 2000 milliseconds, is hard-coded into the DMO, as is the wet/dry mix (the mix ratio between the delayed signal and the original signal), which is set at 25 percent. A full-featured DMO would have COM interfaces to allow you to change these parameters in real time, but SimpleDelay doesn t have them. (At this point, you should compile the SimpleDelay sample DMO, along with the DShowDemo application that s supplied with it.)

When you launch the DShowDemo (which uses the DMO), the application will allow you to select a valid WAV file. After a WAV file has been located, the Play button will be enabled, as shown in Figure 13-1.

figure 13-1 the dshowdemo application that uses the simpledelay dmo

Figure 13-1. The DShowDemo application that uses the SimpleDelay DMO

During WAV playback, you ll be able to hear the delayed audio signal, mixed in with the main audio signal. It ll be somewhat faint because the wet/dry mix is set at 25 percent. You can change that value by opening the Delay.h file and recompiling the SimpleDelay DMO. You can also do the same thing with the delay time. It s not real-time adjustment, but it s better than nothing.

The source code for DShowDemo is very brief. It does little more than manage the dialog box and build the filter graph. The filter graph building takes place in the LoadWavFile function, as shown here:

HRESULT LoadWavFile(HWND hwnd, LPTSTR szFileName) { IBaseFilter *pDmoFilter = NULL; HRESULT hr; CleanUp(); // Restore to original state // Create the Filter Graph Manager and query for interfaces. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&g_pGraph); if (FAILED(hr)) { return hr; } g_pGraph->QueryInterface(IID_IMediaControl, (void **)&g_pMediaControl); g_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&g_pEvent); g_pEvent->SetNotifyWindow((OAHWND)hwnd, WM_GRAPHNOTIFY, 0); // Create the DMO Wrapper filter. hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&pDmoFilter); if (FAILED(hr)) { return hr; } IDMOWrapperFilter *pWrap; pDmoFilter->QueryInterface(IID_IDMOWrapperFilter, (void **)&pWrap); hr = pWrap->Init(CLSID_Delay, DMOCATEGORY_AUDIO_EFFECT); pWrap->Release(); if (SUCCEEDED(hr)) { hr = g_pGraph->AddFilter(pDmoFilter, L"SimpleDelay DMO ); #ifdef _UNICODE hr = g_pGraph->RenderFile(szFileName, NULL); #else WCHAR wszFile[MAX_PATH]; int result = MultiByteToWideChar(CP_ACP, 0, szFileName, -1, wszFile, MAX_PATH); if (result == 0) { hr = E_FAIL; } else { hr = g_pGraph->RenderFile(wszFile, NULL); } #endif } pDmoFilter->Release(); return hr; }

In this function, a filter graph builder object is instantiated, and its media control and event interfaces are queried. Once that overhead is complete, the function makes a CoCreateInstance call with a class ID of CLSID_DMO WrapperFilter. This call instantiates a DMO wrapper filter, the generic wrapper for all DMO objects. Once the function has queried for the IDMOWrapperFilter interface, it invokes the interface s Init method, passing the GUID of the requested DMO. This operation assigns the appropriate DMO to the DirectShow wrapper filter. The second parameter on the Init call is a category identifier used by DirectShow when it enumerates the DMOs looking for one that matches the passed GUID.

At this point, the DMO is treated like any other DirectShow filter. It s added to the filter graph with a call to AddFilter, and it s put into the render path as a transform filter when the RenderFile method is executed, resulting in a filter graph that looks like Figure 13-2.

figure 13-2 the simpledelay dmo, which looks like any other directshow filter when invisibly wrapped inside the directshow wrapper filter

Figure 13-2. The SimpleDelay DMO, which looks like any other DirectShow filter when invisibly wrapped inside the DirectShow Wrapper filter

Although this is a very simple exploration of an audio DMO inside a filter graph, this code contains everything you ll need to use DMOs within your own DirectShow applications. If you need to learn which DMOs are available for use, you can enumerate them using the System Device Enumerator, which was explored in Chapter 4. (There s also a DMOEnum sample program in the DirectX SDK that does much the same thing.) Instead of passing the GUID for classes of DirectShow filters in the call, pass a DMO enumerator. The DMO audio effects can be enumerated with the value DMOCATEGORY_AUDIO_EFFECT, while video effects can be enumerated with the value DMOCATEGORY_ VIDEO_EFFECT. Table 13-1 lists the DMO enumerators.

Table 13-1. DMO Enumerator GUIDs

GUID

Description

DMOCATEGORY_AUDIO_DECODER

Audio decoder

DMOCATEGORY_AUDIO_EFFECT

Audio effect

DMOCATEGORY_AUDIO_ENCODER

Audio encoder

DMOCATEGORY_VIDEO_DECODER

Video decoder

DMOCATEGORY_VIDEO_EFFECT

Video effect

DMOCATEGORY_VIDEO_ENCODER

Video encoder

DMOCATEGORY_AUDIO_CAPTURE_EFFECT

Audio capture effect



Programming Microsoft DirectShow for Digital Video and Television
Programming Microsoft DirectShow for Digital Video and Television (Pro-Developer)
ISBN: 0735618216
EAN: 2147483647
Year: 2002
Pages: 108
Authors: Mark D. Pesce

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net