Perhaps you've tried it in GraphEdit, or perhaps even your own code but couldn't get it work? The following will illustrate the requirements so that you can understand what is required and why it doesn't work in GraphEdit.
#1: Extensible or not extensible?
They are 2 variants of file storage for your source .WAV files. Most of the audio editors out there, especially the cross
platform ones, do not use the WAVEFORMATEXTENSIBLE structure but rather the traditional WAVEFORMATEX. Conversely, most Microsoft
components insist on the usage of WAVEFORMATEXTENSIBLE and will reject WAVEFORMATEX if one of the following is true:
- Sample rate exeeds 48kHz
- Channel count is greater than 2
- Bit depth is greater than 16
Try the simple test of playing back a 24-bit or 96kHz WAV file created with your favorite audio editor, such as Audacity, in Windows Media Player and see what happens. Does it play? If it doesn't, install the Legacy HD Audio filter from the main page and try again. If it plays now that is because the filter is converting the format definition from WAVEFORMATEX to WAVEFORMATEXTENSIBLE, all without changing a single bit of data.
#2: WM ASF Writer
The v9 DirectShow WM ASF Writer (from the WMF 9.0 Runtime) does not support WAVEFORMATEXTENSIBLE. As you might know, the DirectShow WM ASF Writer is basically just
a light DirectShow wrapper over the actual writer which is implemented in the Format SDK. The filter does some sanity checking
before passing requests through. Is this case the sanity check goes horribly wrong as the filter checks to see if the format
TagID is 1. For WAVEFORMATEXTENSIBLE the TagID is not 1, it is 0xFFFE, so the connection is rejected before the actual writer
even gets to get a look at it. So how do you write to the actual writer in DirectShow without either re-writing the wrapper or
using the Format SDK directly?
NOTE: The v11 WMF Runtime seems to have fixed this limitation.
#3: Workaround - Compress First
The WM ASF Writer will also allow compressed connections provided an appropriate profile is set. This means that you can
compress the data using the WMA Audio DMO, connect the DMO to the writer and you're good to go. Well, almost. The ASF Writer
property page doesn't have an option of loading a profile, only of selecting one of the old v8 profiles, so there is no
HD audio choice for you to make in GraphEdit. To do this in code you have to do the following:
- Create an instance of the profile manager IWMProfileManager with
hr = WMCreateProfileManager(&pProfileManager);
- Create the profile instance with the manager giving it the profile in text form, returning an IWMProfile object.
hr = pProfileManager->LoadProfileByData(szProfile, &pProfile);
- Get the IConfigASFWriter interface and set the writer to receive compressed samples
pConfigWriter = asfWriter;
hr = pConfigWriter->SetParam(AM_CONFIGASFWRITER_PARAM_DONTCOMPRESS, TRUE, 0);
- Use the IConfigASFWriter interface to set the profile
hr = pConfigWriter->ConfigureFilterUsingProfile(pProfile);
The filters will now connect using a media type derived from the profile.
#4: Putting it all together
You will need an encoding graph that looks similar to this.
There's a code sample for an encoding graph available here, but without much in the way of error checking.
Sample 6-channel 24-bit WAV file made up of tone, clicks and a pluck, made with Audacity
Sample WMA/ASF Profile to use with this sample. (text version)
Note that the sample presented here does not work with the WMF v11 Runtime. There seems to be a currently unknown bug that causes a NULL pointer pin reference to accessed.