1

我正在尝试从磁盘播放一个 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)
}
4

1 回答 1

1

...总是每秒接收四次 44100 字节数据,我想将回调速率更改为每秒 10 次...

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

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

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

于 2021-05-25T15:36:29.273 回答