[wdmaudiodev] Filter Mode AEC problem in Vista.

  • From: "Nagarathnam, Venkataraman" <Venkataraman.Nagarathnam@xxxxxxxxxxx>
  • To: <wdmaudiodev@xxxxxxxxxxxxx>
  • Date: Mon, 7 Apr 2008 17:26:19 +0800

Hi All,

We have a USB based Speaker and microphone device which already supports
Windows XP. We have our 

own driver for AEC for XP. Now we need to support the device for Windows
Vista. We initially 

tried to use Sysfx APOs and that did not work out since the support team
at Microsoft itself were 

not clear as to how it was implemented and how we need to make use of
it. We waited for the SP1 

for Vista hoping that it would fix a lot of issues around audio related
stuff. Meanwhile we have 

started to explore using Microsoft built in AEC for our device. We have
implemented the 

AECMicArray example from the Microsoft SDK in Source mode. But the audio
quality does not seem to 

be upto the mark. So, we need help on 2 things to improve this:
1 - See what are the tunable parameters in the Source Mode.
2 - Implement the Filter Mode AEC.
    For the first issue, i browsed the Microsoft forums for help and the
conclusion is we 

need to use the AecQualityMetrics_Struct structure. But i am not able to
print out the 

parameters. The piece of code for this is :

 PROPVARIANT pvAECStats;
    PropVariantInit(&pvAECStats);
    pvAECStats.vt = VT_BLOB;
    //pvAECStats.lVal=1;
    CHECKHR(pPS->SetValue(MFPKEY_WMAAECMA_RETRIEVE_TS_STATS,
pvAECStats));
    CHECKHR(pPS->GetValue(MFPKEY_WMAAECMA_RETRIEVE_TS_STATS,
&pvAECStats));

#if 0
    AecQualityMetrics_Struct sAEC;
    CHECKHR(pPS->SetValue(MFPKEY_WMAAECMA_RETRIEVE_TS_STATS,
(PROPVARIANT &)sAEC));
    CHECKHR(pPS->GetValue(MFPKEY_WMAAECMA_RETRIEVE_TS_STATS,
(PROPVARIANT *)&sAEC));
    //MFPKEY_WMAAECMA_QUALITY_METRICS. TODO : have to see how to use
this :(
    printf("%20s %5d \n", "ConvergenceFlag is ", sAEC.ConvergenceFlag);
    printf("%20s %5d \n", "MicClippedFlag is ", sAEC.MicClippedFlag);
    printf("%20s %5d \n", "MicSilenceFlag is ", sAEC.MicSilenceFlag);
    printf("%20s %5d \n", "PstvFeadbackFlag is ",
sAEC.PstvFeadbackFlag);
    printf("%20s %5d \n", "SpkClippedFlag is ", sAEC.SpkClippedFlag);
    printf("%20s %5d \n", "SpkMuteFlag is ", sAEC.SpkMuteFlag);
    printf("%20s %5d \n", "GlitchFlag is ", sAEC.GlitchFlag);
    printf("%20s %5d \n", "DoubleTalkFlag is ", sAEC.DoubleTalkFlag);

    printf("%20s %5f \n", "fDuration is ", sAEC.fDuration);
    printf("%20s %5f \n", "fTSVariance is ", sAEC.fTSVariance);
    printf("%20s %5f \n", "fTSDriftRate is ", sAEC.fTSDriftRate);
    printf("%20s %5f \n", "fVoiceLevel is ", sAEC.fVoiceLevel);
    printf("%20s %5f \n", "fNoiseLevel is ", sAEC.fNoiseLevel);
    printf("%20s %5f \n", "fERLE is ", sAEC.fERLE);
    printf("%20s %5f \n", "fAvgERLE is ", sAEC.fAvgERLE);
    PropVariantClear(&pvAECStats);
#endif 

    This code prints out 0 for all the values during recording to PCM
file.
Can anyone please correct me in the code if i am going wrong anywhere???

2 - Coming to the Filter mode, the AECMicArray code was modified as
follows: 

#include <windows.h>
#include <dmo.h>
#include <Mmsystem.h>
#include <objbase.h>
#include <mediaobj.h>
#include <uuids.h>
#include <propidl.h>
#include <wmcodecdsp.h>

#include <atlbase.h>
#include <ATLComCli.h>
#include <audioclient.h>
#include <MMDeviceApi.h>
#include <AudioEngineEndPoint.h>
#include <DeviceTopology.h>
#include <propkey.h>
#include <strsafe.h>
#include <conio.h>
#include <Dmodshow.h> // added by Venkat.R.N.
#include <DshowUtil.h> // added by Venkat.R.N.
#include <AudioClient.h> // added by Venkat.R.N.
#include <FunctionDiscoveryKeys_devpkey.h> // added by Venkat.R.N.

#include "mediabuf.h"
#include "AecKsBinder.h"

void OutputUsage();
//HRESULT Stream( BYTE **ppbOutData, ULONG *pbDataSize, LPWAVEFORMATEX
*ppwfx );

#define SAFE_ARRAYDELETE(p) {if (p) delete[] (p); (p) = NULL;}
#define SAFE_RELEASE(p) {if (NULL != p) {(p)->Release(); (p) = NULL;}}

#define VBFALSE (VARIANT_BOOL)0
#define VBTRUE  (VARIANT_BOOL)-1

#define STREAM_BUFFER_LENGTH 0.1f  //streaming buffer is 0.1 second
long.

#define CHECK_RET(hr, message) if (FAILED(hr)) { puts(message); goto
exit;}
#define CHECKHR(x) hr = x; if (FAILED(hr)) {printf("%d: %08X\n",
__LINE__, hr); goto exit;}
#define CHECK_ALLOC(pb, message) if (NULL == pb) { puts(message); goto
exit;}

class CStaticMediaBuffer : public CBaseMediaBuffer {
public:
    STDMETHODIMP_(ULONG) AddRef() {return 2;}
    STDMETHODIMP_(ULONG) Release() {return 1;}
    void Init(BYTE *pData, ULONG ulSize, ULONG ulData) {
        m_pData = pData;
        m_ulSize = ulSize;
        m_ulData = ulData;
    }
};

int __cdecl _tmain(int argc, const TCHAR ** argv)
{
    HRESULT hr = S_OK;
    CoInitialize(NULL);

    ULONG cbProduced = 0;
    DWORD dwStatus;

    IMediaObject* m_pObject = NULL;    
    IPropertyStore* pPS = NULL;
    IMediaObjectInPlace *m_pObjectInPlace = NULL;

    FILE * pfMicOutPCM;  // dump output signal using PCM format

    DWORD cOutputBufLen = 0;
    BYTE *pbOutputBuffer = NULL;

    //LPWAVEFORMATEX      m_pwfx;         // pointer to input/output
waveformatex structure.
    DMO_MEDIA_TYPE m_mt = {0};
    DMO_MEDIA_TYPE m_mt1 = {0};
    WAVEFORMATEX wfxIn = {WAVE_FORMAT_PCM, 1, 16000, 32000, 2, 16, 0};

    
    CStaticMediaBuffer outputBuffer;
    DMO_OUTPUT_DATA_BUFFER OutputBufferStruct = {0};
    OutputBufferStruct.pBuffer = &outputBuffer;
    DMO_MEDIA_TYPE inputmt = {0}; // added by Venkat.R.N.

    // Parameters to config DMO
    int  iDuration = 60;                // seconds
    int  iSystemMode = MODE_NOT_SET;    // AEC-MicArray DMO system mode
    int  iOutFileIdx = -1;              // argument index for otuput
file name
    int  iMicDevIdx = -2;               // microphone device index
    int  iSpkDevIdx = -2;               // speaker device index
    BOOL bFeatrModeOn = 0;              // turn feature mode on/off
    BOOL bNoiseSup = 1;                 // turn noise suppression on/off
    BOOL bAGC = 0;                      // turn digital auto gain
control on/off
    BOOL bCntrClip = 0;                 // turn center clippng on/off

    // control how long the Demo runs
    //int  iDuration = 60;   // seconds
    int  cTtlToGo = 0;

    AUDIO_DEVICE_INFO *pCaptureDeviceInfo = NULL, *pRenderDeviceInfo =
NULL;

    int i;
    for ( i = 1; i < argc-1; i++ )
    {
        if (argv[i][0] == '-') 
        {
            if ( !_tcscmp (_T("-micdev"), argv[i]))
            {   // microphone device index. The valid range is -1, 0~N-1
                // where N is the number of capture device. Use -1 if
                // you want to use the default device.
                iMicDevIdx = _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-spkdev"), argv[i]))
            {   // speaker device index. The valid values are -1, 0~N-1
                // where N is the number of capture device. Use -1 if
                // you want to use the default device.
                iSpkDevIdx = _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-out"), argv[i]))
            {   // output file name
                iOutFileIdx = i + 1; i++;
            }
            else if ( !_tcscmp (_T("-mod"), argv[i]))
            {   // AEC-MicArray system mode. The valid modes are
                //   SINGLE_CHANNEL_AEC = 0
                //   OPTIBEAM_ARRAY_ONLY = 2
                //   OPTIBEAM_ARRAY_AND_AEC = 4
                //   SINGLE_CHANNEL_NSAGC = 5
                //
                // Mode 1 and 3 are reserved for future features.
                iSystemMode = _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-feat"), argv[i]))
            {   // turn feature mode on/off. The valid values are 0 or 1
                // The feature mode must be turned on in order to config
                // noise suppression, AGC, centerclip, and other AEC
features.
                bFeatrModeOn = _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-ns"), argv[i]))
            {   // turn noise suppression on/off. The valid values are 0
or 1
                // Feature mode must be on in order to set noise
suppression
                bNoiseSup = _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-agc"), argv[i]))
            {   // turn digital AGC on/off. The valid values are 0 or 1
                // Feature mode must be on in order to set digital AGC
                bAGC = _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-cntrclip"), argv[i]))
            {   // turn center clipping on/off. The valid values are 0
or 1
                // Center clipping is an post process to remove small
echo residuals 
                // which are not completely cancelled. Comfort noise
with a same level
                // of background noise will be filled after the removal.
                // Feature mode must be on in order to set center
clipping
                bCntrClip = (BOOL) _ttoi ( argv[i+1] ); i++;
            }
            else if ( !_tcscmp (_T("-duration"), argv[i]))
            {   // control program running duration in seconds. The
default 
                // value is 60 seconds.
                iDuration =  _ttoi ( argv[i+1] ); i++;
            }
            else
            {
                OutputUsage();
                goto exit;
            }
        }
    }

    HANDLE currThread;
    HANDLE currProcess;
    BOOL iRet;
    currProcess = GetCurrentProcess ();
    currThread = GetCurrentThread ();

    iRet = SetPriorityClass (currProcess, HIGH_PRIORITY_CLASS);
    if ( 0 == iRet )
    {
        // call getLastError.
        puts("failed to set process priority\n");
        goto exit;
    }

    // create DMO
    hr = CoCreateInstance(CLSID_CWMAudioAEC,
                         NULL,
                         CLSCTX_INPROC,
                         IID_IMediaObject,
                         (void **) &m_pObject);
    CHECK_RET(hr,"CoCreateInstance() failed!!!!!!!!!");

    //hr = m_pObject->QueryInterface(IID_IMediaObjectInPlace,
(void**)&m_pObjectInPlace);
    CHECKHR(m_pObject->QueryInterface(IID_IPropertyStore,
(void**)&pPS));
    CHECK_RET(hr,"QueryInterface() failed!!!!!!!!!");

    /////////////////////////////////// start of code for selecting 

device...//////////////////////////////////

    // Select capture device
    UINT uCapDevCount = 0;
    UINT uRenDevCount = 0;
    char  pcScanBuf[256]= {0};

    hr = GetCaptureDeviceNum(uCapDevCount);
    CHECK_RET(hr, "GetCaptureDeviceNum failed");

    pCaptureDeviceInfo = new AUDIO_DEVICE_INFO[uCapDevCount];
    hr = EnumCaptureDevice(uCapDevCount, pCaptureDeviceInfo);
    CHECK_RET(hr, "EnumCaptureDevice failed");

    printf("\nSystem has totally %d capture devices\n", uCapDevCount);
    for (i=0; i<(int)uCapDevCount; i++)
    {
        _tprintf(_T("Device %d is %s"), i,
pCaptureDeviceInfo[i].szDeviceName);
        if (pCaptureDeviceInfo[i].bIsMicArrayDevice)
            _tprintf(_T(" -- Mic Array Device \n"));
        else
            _tprintf(_T("\n"));
    }

    if (iMicDevIdx<-1 || iMicDevIdx>=(int)uCapDevCount)
    {
        do{
            printf("Select device ");
            scanf_s("%255s", pcScanBuf, 255); 
            iMicDevIdx = atoi(pcScanBuf);
            if (iMicDevIdx < -1 || iMicDevIdx >= (int)uCapDevCount)
                printf("Invalid Capture Device ID \n");
            else
                break;
        }while(1);
    }
    if (iMicDevIdx == -1)
        _tprintf(_T("\n Default device will be used for capturing \n"));
    else
        _tprintf(_T("\n %s is selected for capturing\n"),
pCaptureDeviceInfo

[iMicDevIdx].szDeviceName);
    SAFE_ARRAYDELETE(pCaptureDeviceInfo);
    

    // Select render device
    if( iSystemMode == SINGLE_CHANNEL_AEC ||
        iSystemMode == ADAPTIVE_ARRAY_AND_AEC ||
        iSystemMode == OPTIBEAM_ARRAY_AND_AEC )
    {
        hr = GetRenderDeviceNum(uRenDevCount);
        CHECK_RET(hr, "GetRenderDeviceNum failed");

        pRenderDeviceInfo = new AUDIO_DEVICE_INFO[uRenDevCount];
        hr = EnumRenderDevice(uRenDevCount, pRenderDeviceInfo);
        CHECK_RET(hr, "EnumRenderDevice failed");

        printf("\nSystem has totally %d render devices\n",
uRenDevCount);
        for (i=0; i<(int)uRenDevCount; i++)
        {
            _tprintf(_T("Device %d is %s \n"), i,
pRenderDeviceInfo[i].szDeviceName);
        }

        if (iSpkDevIdx<-1 || iSpkDevIdx>=(int)uRenDevCount)
        {
            do{
                printf("Select device ");
                scanf_s("%255s", pcScanBuf, 255); 
                iSpkDevIdx = atoi(pcScanBuf);
                if (iSpkDevIdx < -1 || iSpkDevIdx >= (int)uRenDevCount)
                    printf("Invalid Render Device ID \n");
                else
                    break;
            }while(1);
        }
        if (iSpkDevIdx == -1)
            _tprintf(_T("\n Default device will be used for rendering
\n"));
        else
            _tprintf(_T("\n %s is selected for rendering \n"),
pRenderDeviceInfo

[iSpkDevIdx].szDeviceName);
    }else{
    iSpkDevIdx = -1;
    }

    SAFE_ARRAYDELETE(pRenderDeviceInfo);

     // --- PREPARE OUTPUT --- //
    if (NULL != _tfopen_s(&pfMicOutPCM, argv[iOutFileIdx], _T("wb")))
    { 
        puts("cannot open file for output.\n"); 
        goto exit; 
    }

    m_mt.majortype  = MEDIATYPE_Audio;
    m_mt.subtype    = MEDIASUBTYPE_PCM;
    m_mt.formattype = FORMAT_WaveFormatEx;
    m_mt.cbFormat   = sizeof(WAVEFORMATEX);
    m_mt.pbFormat   = (BYTE*) &wfxIn;
    m_mt.pUnk = NULL;       // CopyMediaType will crash if we don't
intialize this

    hr = MoInitMediaType(&m_mt, sizeof(WAVEFORMATEX));
    CHECK_RET(hr, "MoInitMediaType(m_mt) failed");

    memcpy(m_mt.pbFormat, &wfxIn, sizeof(WAVEFORMATEX));

    /* hr = m_pObject->SetInputType( 0,    //Input Stream index
                                  &m_mt,
                                  0 );  */  // No flags specified
    //CHECK_RET(hr,"SetInputType() failed!!!!!!!!!");

    m_mt1.majortype  = MEDIATYPE_Audio;
    m_mt1.subtype    = MEDIASUBTYPE_PCM;
    m_mt1.formattype = FORMAT_WaveFormatEx;
    m_mt1.cbFormat   = sizeof(WAVEFORMATEX);
    m_mt1.pbFormat   = (BYTE*) &wfxIn;
    m_mt1.pUnk = NULL;       // CopyMediaType will crash if we don't
intialize this

    hr = MoInitMediaType(&m_mt1, sizeof(WAVEFORMATEX));
    CHECK_RET(hr, "MoInitMediaType(m_mt1) failed");

    memcpy(m_mt1.pbFormat, &wfxIn, sizeof(WAVEFORMATEX));

    hr = m_pObject->SetOutputType( 0,       // Output Stream Index
                                   &m_mt1,
                                   0);  // No flags specified
    CHECK_RET(hr,"SetOutputType() failed!!!!!!!!!");

    hr = m_pObject->AllocateStreamingResources();
    CHECK_RET(hr, "AllocateStreamingResources failed");

      /////////////////set feature mode/////////////////////
     PROPVARIANT pvFeatrModeOn;
     PropVariantInit(&pvFeatrModeOn);
     pvFeatrModeOn.vt = VT_BOOL;
     pvFeatrModeOn.boolVal = VBTRUE;
     pPS->SetValue(MFPKEY_WMAAECMA_FEATURE_MODE, pvFeatrModeOn);
     pPS->GetValue(MFPKEY_WMAAECMA_FEATURE_MODE, &pvFeatrModeOn);
     PropVariantClear(&pvFeatrModeOn); // critical feature mode
uncomment working!!! :)

     /////////////////set system mode//////////////////////
     LONG system_mode = SINGLE_CHANNEL_AEC; // changed
OPTIBEAM_ARRAY_ONLY to 

SINGLE_CHANNEL_AEC...
     // AllocateStreamingResources() failed for OPTIBEAM_ARRAY_ONLY!!!!
     PROPVARIANT pvSysMode;
     PropVariantInit(&pvSysMode);
     pvSysMode.vt = VT_I4;
     pvSysMode.lVal = (LONG)(system_mode);
     hr = pPS->SetValue(MFPKEY_WMAAECMA_SYSTEM_MODE, pvSysMode);
     hr =pPS->GetValue(MFPKEY_WMAAECMA_SYSTEM_MODE, &pvSysMode);
     PropVariantClear(&pvSysMode);  

      ///////////////set filter mode////////////////////////
     PROPVARIANT pvSystemMode;
     PropVariantInit(&pvSystemMode);
     pvSystemMode.vt = VT_BOOL;
     pvSystemMode.boolVal = VARIANT_FALSE; // comment by Venkat.R.N -->
: VBFALSE tells that it 

is FILTER MODE!!! :)
     // VBTRUE is source mode and hence it is working... :(
     hr = pPS->SetValue(MFPKEY_WMAAECMA_DMO_SOURCE_MODE, pvSystemMode);
     hr = pPS->GetValue(MFPKEY_WMAAECMA_DMO_SOURCE_MODE, &pvSystemMode);
     PropVariantClear(&pvSystemMode);   //very very critical comment!!! 
     // AllocateStreamingResources() failed if SetInputType() is
there... :(
     // ProcessOutput() failed if SetInputType() is commented... :(

    // allocate output buffer
    cOutputBufLen = wfxIn.nSamplesPerSec * wfxIn.nBlockAlign;
    pbOutputBuffer = new BYTE[cOutputBufLen];
    CHECK_ALLOC (pbOutputBuffer, "out of memory.\n");

    
   // number of frames to play
    cTtlToGo = iDuration * 100;

    // main loop to get mic output from the DMO
    puts("\nAEC-MicArray is running ... Press \"s\" to stop");
    while (1)
    {
        Sleep(10); //sleep 10ms

        if (cTtlToGo--<=0)
            break;

        do{
            outputBuffer.Init((byte*)pbOutputBuffer, cOutputBufLen, 0);
            OutputBufferStruct.dwStatus = 0;
            hr = m_pObject->ProcessOutput(0, 1, &OutputBufferStruct,
&dwStatus);
            CHECK_RET (hr, "ProcessOutput failed");

            if (hr == S_FALSE) {
                cbProduced = 0;
            } else {
                hr = outputBuffer.GetBufferAndLength(NULL, &cbProduced);
                CHECK_RET (hr, "GetBufferAndLength failed");
            }
            //printf("%d \n", "cbProduced is ", cbProduced);
            // dump output data into a file with PCM format.
            if (fwrite(pbOutputBuffer, 1, cbProduced, pfMicOutPCM) !=
cbProduced) 
            { 
                puts("write error"); 
                goto exit; 
            }
        } while (OutputBufferStruct.dwStatus &
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE);

        // check keyboard input to stop
        if (_kbhit())
        {
            int ch = _getch();
            if (ch == 's' || ch == 'S')
                break;
        }
    }

    exit:

    //SAFE_ARRAYDELETE(pbOutputBuffer);
    //SAFE_ARRAYDELETE(pCaptureDeviceInfo);
    //SAFE_ARRAYDELETE(pRenderDeviceInfo);

    SAFE_RELEASE(m_pObject);
    SAFE_RELEASE(pPS);

    CoUninitialize();
    return hr;
}

void OutputUsage()
{
    printf("MFWMAAEC (Aec-MicArray DMO) Demo. \n");
    printf("Copyright (c) 2004-2006, Microsoft Corporation. All rights
reserved. \n\n");
    printf("Usage: AecSDKDemo.exe -out mic_out.pcm -mod 0 [-feat 1] [-ns
1] [-agc 0] \n");
    printf("       [-cntrclip 0] [-micdev 0] [-spkdev 0] [-duration
60]\n");
    return;
}

/* HRESULT Stream( BYTE **ppbOutData, ULONG *pbDataSize, LPWAVEFORMATEX
*ppwfx )
{
    HRESULT         hr = S_OK;
    BYTE            *pOut;
    ULONG               m_uDataSize;    // Size of input data buffer.
    LPWAVEFORMATEX      m_pwfx;         // pointer to input/output
waveformatex structure.

    BYTE            *pbOutData=0;
    ULONG           uDataSize =0 ;
    LPWAVEFORMATEX  pwfx = NULL;        // pointer to waveformatex
structure.

    *pbDataSize     = m_uDataSize;
    *ppwfx          = m_pwfx; */

    /* if ( m_pObjectInPlace ){

        pOut = new BYTE [m_uDataSize];

         if( pOut == 0 ){
            return E_OUTOFMEMORY;
        }
        CopyMemory(pOut, m_pbInData, m_uDataSize);

        // pass the number of samples to Process()
        hr = m_pObjectInPlace->Process( m_uDataSize,
                                        pOut,
                                        0,
                                        DMO_INPLACE_NORMAL);
        if( FAILED( hr ) ){
            return hr;
        }
        *ppbOutData = pOut;
        SAFE_RELEASE( m_pObjectInPlace );
    } */ 
    //else
    //{
       /* CMediaBuffer            *pInputBuffer;
        const REFERENCE_TIME    rtStart     = 0;
        const REFERENCE_TIME    rtStop      = 0;
        BYTE*                   pBuffer;
        DWORD                   dwLength;

        // create and fill CMediaBuffer
        hr = CreateBuffer(m_uDataSize, &pInputBuffer);
        if( FAILED( hr ) ){
            return hr;
        }

        hr = pInputBuffer->GetBufferAndLength( &pBuffer, &dwLength );
        if( FAILED( hr ) ){
            return hr;
        }
        CopyMemory(pBuffer, m_pbInData, m_uDataSize);

        hr = pInputBuffer->SetLength( m_uDataSize );
        if( FAILED( hr ) ){
            return hr;
        }

        // call processInput
        hr = m_pObject->ProcessInput( 0,
                                pInputBuffer,
                                DMO_INPUT_DATA_BUFFERF_SYNCPOINT,
                                rtStart,
                                rtStop - rtStart);
        if( FAILED( hr ) ){
            return hr;
        }

        //release input buffer
        SAFE_RELEASE( pInputBuffer );

        // retrieve the output data from DMO and put into pOut
        if(S_FALSE == hr){
            return E_FAIL;
        } else {
            pOut = NULL;
            hr = ProcessOutputs( &pOut );
            if( FAILED( hr ) ){
                delete [] pOut;
                return hr;
            }
        }

        *ppbOutData = pOut;
        SAFE_RELEASE( m_pObject );
    //}

    return S_OK;
} */ 

On setting to Filter mode, the AllocateStreamingResources() fails. I am
not able to go into the 

depth of problem. No help from any of the forums too. Can someone
suggest what might be the 

possible causes for failure???
Thanks in advance.
 

Other related posts:

  • » [wdmaudiodev] Filter Mode AEC problem in Vista.