Adding Audio Compression with DSAudioCapCom

Adding Audio Compression with DSAudioCapCom

The sound that s captured by DSAudioCap is uncompressed, so file sizes build very quickly, at just about the same rate they do on a standard audio CD about 700 MB per hour. However, numerous transform filters are available to DirectShow that can compress audio to a fraction of its uncompressed size. We ve already covered everything you need to know to add a compressor filter to the filter graph. Like audio input devices, audio compressor filters must be enumerated and selected from a list.

The only major difference between DSAudioCap and DSAudioCapCom (the version with compression) is the addition of one function, Enumerate AudioCompressorFilters, as shown in the following code:

// Enumerate all of the audio compressors. // Return the one with the matching name to the caller. HRESULT EnumerateAudioCompressorFilters(void** gottaCompressor, wchar_t* matchName) { // Once again, code stolen from the DX9 SDK. // Create the System Device Enumerator. ICreateDevEnum *pSysDevEnum = NULL; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); if (FAILED(hr)) { return hr; } // Obtain a class enumerator for the audio input category. IEnumMoniker *pEnumCat = NULL; hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioCompressorCategory, &pEnumCat, 0); if (hr == S_OK) { // Enumerate the monikers. IMoniker *pMoniker = NULL; ULONG cFetched; BOOL done = false; while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (!done)) { // Bind the first moniker to an object. IPropertyBag *pPropBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); if (SUCCEEDED(hr)) { // Retrieve the filter's friendly name. VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (SUCCEEDED(hr)) { wprintf(L"Testing Audio Compressor: %s\n", varName.bstrVal); // Is it the right one? if (wcsncmp(varName.bstrVal, matchName, wcslen(matchName)) == 0) { // We found it; send it back to the caller hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, gottaCompressor); done = true; } } VariantClear(&varName); pPropBag->Release(); } pMoniker->Release(); } pEnumCat->Release(); } pSysDevEnum->Release(); return hr; }

To add an audio compressor to this filter graph, begin by enumerating all of the CLSID_AudioCompressorCategory filters in a method call to CreateClass Enumerator. You do this because DirectShow treats the audio compressors as individual objects with their own class IDs. However, we have no way of knowing the class ID of a given audio compressor something we ll need to instantiate a DirectShow filter. In this case, we use the call to CreateClassEnumerator as a way of learning the class IDs of all audio compressors available to DirectShow.

Once we have the enumerated list, we step through it using the Next method, until we find an audio compressor whose FriendlyName property matches the name we re looking for. In this program, we re matching the name Windows Media Audio V2, a codec that should be included on your system. (If it s not, use GraphEdit to list the audio compressors installed on your system see Figure 4-6 and change the string to match one of those entries.)

figure 4-6 locating the friendlyname property for an audio compressor in graphedit s insert filters dialog box

Figure 4-6. Locating the FriendlyName property for an audio compressor in GraphEdit s Insert Filters dialog box

When the matching object is found, it s instantiated and returned to the caller. This function is nearly identical to EnumerateAudioInputFilters, so you can begin to see how these functions can easily be repurposed for your own application needs.

The only major difference in this version of the main function is that the returned audio compressor filter is added to the filter graph using AddFilter and ConnectFilter, as shown here:

// Now, enumerate the audio compressors. // Look for a match, which we'll return. hr = EnumerateAudioCompressorFilters((void**) &pAudioCompressor, L"Windows Media Audio V2"); // Then add it to the filter graph. hr = pGraph->AddFilter(pAudioCompressor, L"Windows Media Audio V2"); // Connect it to the audio input filter. hr = ConnectFilters(pGraph, (IBaseFilter*) pAudioInputFilter, pAudioCompressor);

We ve also added a bit of substance to the File Writer filter. The File Writer filter exposes a number of interfaces, including IFileSink, which can be used to set the name of the file, and IFileSink2, which can be used to set the mode parameter for the File Writer filter. If the mode is AM_FILE_OVERWRITE, the file will be deleted and re-created every time the filter graph begins execution. That s the behavior we want, so we ve included a few extra lines of code:

// And we'll also destroy any existing file. hr = pFileWriter->QueryInterface(IID_IFileSinkFilter2, (void**)&pSink2); pSink2->SetMode(AM_FILE_OVERWRITE);

After you ve run DSAudioCapCom, you ll see that its file sizes increase much more slowly than DSAudioCap because the files are compressed. As you become familiar with the different types of audio compression some are better for voice, others for music you might consider modifying the compression filters used in your DirectShow programs on a task-dependent basis: different compression for different sounds.



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