【问题标题】:Directshow CLSID_AsyncReader:how to set the Output Pin sample size?Directshow CLSID_AsyncReader:如何设置输出引脚样本大小?
【发布时间】:2021-08-13 11:27:42
【问题描述】:

我正在尝试从磁盘播放一个 wav 文件(44100sr 16bits 2 通道),我需要在 SampleGrabber 过滤器回调中处理音频数据,但它总是每秒接收四次 44100 字节数据,我想要将回调速率更改为每秒 10 次(音频样本大小:每次回调 17640 字节),而不是四次(每次 44100 字节),如何使其按预期工作?

hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pBgmAudioGrabber);
BREAK_IF_FAILED(hr);
        
hr = m_pGraph->AddFilter((IBaseFilter*)m_pBgmAudioGrabber, L"Bgm Audio Mix");
BREAK_IF_FAILED(hr);

hr = InitBgmAudioGrabble();
BREAK_IF_FAILED(hr);

CComPtr<IPin> pAudioMixInputPin;
hr = g_DSHelper.GetPin(m_pBgmAudioGrabber, PINDIR_INPUT, 0, &pAudioMixInputPin);
g_DSHelper.SetAudioFilterBuffer(pAudioMixInputPin);
BREAK_IF_FAILED(hr);

CComPtr<IPin> pAudioMixOutputPin;
hr = g_DSHelper.GetPin(m_pBgmAudioGrabber, PINDIR_OUTPUT, 0, &pAudioMixOutputPin);
g_DSHelper.SetAudioFilterBuffer(pAudioMixOutputPin);

BREAK_IF_FAILED(hr);
        
hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_pBGMAudioSrcFilter);
RETURN_IF_FAILED(hr, hr);
InfoLog(_T("Create BGM source filter CLSID_AsyncReader OK!"));

hr = CoCreateInstance(CLSID_WavParser, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_pWaveParserFilter);
RETURN_IF_FAILED(hr, hr)
InfoLog(_T("Create CLSID_WavParser OK!"));
hr = m_pGraph->AddFilter(m_pWaveParserFilter, L"Wav Parser");
RETURN_IF_FAILED(hr, hr)
InfoLog(_T("AddFilter CLSID_WavParser OK!"));
        
        
CComPtr<IFileSourceFilter> pSourceFilter;
hr = m_pBGMAudioSrcFilter->QueryInterface(IID_IFileSourceFilter, (void**)&pSourceFilter);
RETURN_IF_FAILED(hr, hr)
InfoLog(_T("QueryInterface IID_IFileSourceFilter OK!"));
        
HRESULT hr = pSourceFilter->Load(m_strBkgMusicPath,NULL );
        
RETURN_IF_FAILED(hr, hr)
InfoLog(_T("Load %s OK!"), m_strBkgMusicPath);

hr = m_pGraph->AddFilter(m_pBGMAudioSrcFilter, L"Async Source");
RETURN_IF_FAILED(hr, hr)
InfoLog(_T("AddFilter AsyncSource OK!"));

CComPtr<IPin> pWavParseInputPin;
hr = g_DSHelper.GetPin(m_pWaveParserFilter, PINDIR_INPUT, 0, &pWavParseInputPin);
g_DSHelper.SetAudioFilterBuffer(pWavParseInputPin);

RETURN_IF_FAILED(hr, hr)
        
CComPtr<IPin> pAudioBGMOutputPin;
        
hr = g_DSHelper.GetPin(m_pBGMAudioSrcFilter, PINDIR_OUTPUT, 0, &pAudioBGMOutputPin);
g_DSHelper.SetAudioFilterBuffer(pAudioBGMOutputPin);

RETURN_IF_FAILED(hr, hr)

hr = m_pGraph->ConnectDirect(pAudioBGMOutputPin, pWavParseInputPin, NULL);
RETURN_IF_FAILED(hr, hr)
InfoLog(_T("Connect of pBkgAudioPathOutputPin and pWavParseInputPin OK!"));

CComPtr<IPin> pWavParseOutputPin;
hr = g_DSHelper.GetPin(m_pWaveParserFilter, PINDIR_OUTPUT, 0, &pWavParseOutputPin);
g_DSHelper.SetAudioFilterBuffer(pWavParseOutputPin);
RETURN_IF_FAILED(hr, hr)

hr = m_BgmAudioRenderDevice.Create(m_strAudioRenderDeviceID);
RETURN_IF_FAILED(hr, hr);
        
hr = m_BgmAudioRenderDevice.SetAudioRenderFormat(g_RecordingConfig.AudioSamplePerSecond(), g_RecordingConfig.AudioBitsPerSample(), g_RecordingConfig.AudioChannels());
RETURN_IF_FAILED(hr, hr);
        
hr = m_pGraph->AddFilter(m_BgmAudioRenderDevice.GetBaseFilter(), L"BGM Audio Render");
RETURN_IF_FAILED(hr, hr);

CComPtr<IPin> pBgmRenderPin  = m_BgmAudioRenderDevice.GetInputPin();
hr = m_pGraph->ConnectDirect(pWavParseOutputPin, pAudioMixInputPin,NULL);
RETURN_IF_FAILED(hr, hr)
g_DSHelper.SetAudioFilterBuffer(pBgmRenderPin);
        

hr = m_pGraph->ConnectDirect(pAudioMixOutputPin, pBgmRenderPin,NULL);
RETURN_IF_FAILED(hr, hr)

if (m_pMC)
{
    hr = m_pMC->StopWhenReady();
    BREAK_IF_FAILED(hr)
}

【问题讨论】:

    标签: windows audio filter directshow samplegrabber


    【解决方案1】:

    ...总是每秒接收4次44100字节的数据,我想把回调速率改成每秒10次...

    你不能拥有这个。当您将其设置为以适合您需要的合适格式流式传输数据时,您的任务就是从那里分解适合您处理的流。

    当您从文件播放时,源过滤器会以对阅读器、解复用器、解码器有意义的块以最大速率推送数据。您几乎永远不会(如果有的话)在此过程中拥有灵活性,并且与实时音频捕获相反,您无法请求特定的数据粒度。

    只需以这种速率消耗数据并将其拆分为您自己内部处理所需的部分,这是一项相对容易的任务。

    【讨论】:

    • 感谢您的帮助。实际上,我的要求是实时处理和播放PCM,但是固定的样本量会带来很大的延迟。大约2.5s,我希望减少每个样本的大小优化延迟,比如切换效果时立即播放,而不是等待2.5s。音频数据可以从文件和内存中加载。看来我无法使用 DirectShow 实现这一点?我可以使用 DirectSound 之类的吗?我需要兼容 Windows XP
    • Async Sample 的 Memfile 可以做到吗?我需要每次渲染 17640 字节的 PCM 数据(每秒处理和渲染 10 次),所以当我更改音频效果时,我只需要等待 1/10 秒即可听到新效果,而不是 1/4 秒潜伏。如果 DirectShow 不能做到这一点,还有其他方法吗?我需要兼容 Windows XP
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    相关资源
    最近更新 更多