音频采集的疑惑,求解
通过directshow进行音频采集,集采到的数据格式如下
WAVEFORMATEX *
wFormatTag1unsigned short
nChannels 2unsigned short
nSamplesPerSec44100unsigned long
nAvgBytesPerSec176400unsigned long
nBlockAlign4unsigned short
wBitsPerSample16unsigned short
cbSize0unsigned short
但有一点很不解的就是,每采集到一个样本的大小是88200,而上的格显示nAvgBytesPerSec=176400
每个样本的计算方式不是 nSamplesPerSec * (wBitsPerSample/8)* nChannels 吗?44100 * (16/8)* 2 = 176400
但集采到的数据每个样本的大小却是88200,难道是半秒采集的数据吗?还是?本人初接触音频编程,很多不懂的地方,求高手指点一二
[解决办法]
是的,采集Filter每次采集出来的数据长度是不一定的,具体看驱动了,播放文件的时候根据文件不同,解析Filter和解码Filter不同,输出长度都不一样,对于设备采集。可以查询设备输出Pin上的借口进行设置,让它输出固定大小的数据。
以下代码以32000Hz 1Channel为例 每次采集输出LIBCODEC_PREPROCESS_SAMPLE_DUR毫秒,20毫秒为640字节,m_IACap是采集Filter
HRESULT CAVCaptureManager::SetAudioFormat(void)
{
if (!m_IACap)
return E_FAIL;
HRESULT hr=0;
IPin *pPin=0;
IAMBufferNegotiation *pNeg=0;
IAMStreamConfig *pCfg=0;
for (int i=0; i<2; i++)
{
hr = DSF::GetPin(m_IACap, PINDIR_OUTPUT, i, &pPin);
if (SUCCEEDED(hr))
{
// Get buffer negotiation interface
hr = pPin->QueryInterface(IID_IAMBufferNegotiation, (void **)&pNeg);
if (FAILED(hr))
{
pPin->Release();
break;
}
// Set the buffer size based on selected settings
ALLOCATOR_PROPERTIES prop={0};
prop.cbBuffer = 32000 * LIBCODEC_PREPROCESS_SAMPLE_DUR / 1000; // 每个sample的长度20ms 32000*20/1000 = 640
prop.cBuffers = 6;//分配6个Sample对象
prop.cbAlign = 2 ; //2Byte*1Channel 字节对齐 一个Hz的字节
//prop.cbBuffer = 1600; // 每个sample的长度100ms 16000 / 10
//prop.cBuffers = 6;//分配6个Sample对象
//prop.cbAlign = 2 ; //2Byte*1Channel 字节对齐 一个Hz的字节
hr = pNeg->SuggestAllocatorProperties(&prop);
pNeg->Release();
// Now set the actual format of the audio data
hr = pPin->QueryInterface(IID_IAMStreamConfig, (void **)&pCfg);
if (FAILED(hr))
{
pPin->Release();
break;
}
// Read current media type/format
AM_MEDIA_TYPE *pmt={0};
hr = pCfg->GetFormat(&pmt);
if (SUCCEEDED(hr))
{
// Fill in values for the new format
WAVEFORMATEX *pWF = (WAVEFORMATEX *) pmt->pbFormat;
pWF->wFormatTag = WAVE_FORMAT_PCM;
pWF->nChannels = 1;//1Chanel
pWF->nSamplesPerSec = 16000;//16KHz
pWF->nAvgBytesPerSec = 32000; //16000Hz*2Byte*1Channel
pWF->wBitsPerSample = 16;//16bit
pWF->nBlockAlign = 2;//2字节对齐
// Set the new formattype for the output pin
hr = pCfg->SetFormat(pmt);
DeleteMediaType(pmt);
}
else
{
return hr;
}
// Release interfaces
pCfg->Release();
pPin->Release();
}
// No more output pins on this filter
else
break;
}
return S_OK;
}