1. AGC(Automatic Gain Control)
即自动增益控制; 对一个输入信号进行放大,为了方便处理,应该保证输出有一定的幅度同时又不会饱和,但是由于输入信号的幅度通常变化很大,所以不能采用一个简单的单一放大倍数,AGC就是根据输入信号调整放大倍数,是输出信号幅度一致。
2. 音频数据的格式WAVE_FORMAT
音频格式包括Sample rate,Mono/Stereo等内容,具体的类型包括下面的几种:
#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ #define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ #define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ #define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ #define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ #define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ #define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ #define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ #define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ #define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ #define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ #define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ |
通过Wave API waveInGetDevCaps()可以获取Audio驱动所支持的音频格式,如下所示:
mmRtn=waveInGetDevCaps(g_dwDeviceNum-1,&woc,sizeof(woc)); CheckMMRESULT(mmRtn,"ERROR: Failed to get device caps. waveInGetDevCaps",TPR_FAIL,"Driver responded incorrectly"); |
WinCE下面标准的Audio驱动中采样率为48000(48K),软件上在通过插值运算来支持各个各样的采样率,这部分实现可以在类StreamContext的继承类诸如OutputStreamContext1M8/OutputStreamContext1M16等中的方法Rend2中实现。
当我们使用Wave API waveInOpen来创建音频Stream的时候,需要通过实参向驱动传送结构体WAVEFORMATEX以告知驱动待创建的Stream的种类,如下:
WAVEFORMATEX wfx; WAVEHDR wh; ZeroMemory( &wfx, sizeof( wfx ) );
wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = 11025; wfx.wBitsPerSample = 8; wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.cbSize = 0;
//---- Open the Wave Input Stream mmRtn = waveInOpen( &hwi, g_dwDeviceNum-1, &wfx, NULL, 0, NULL ); if( MMSYSERR_NOERROR != mmRtn ) { LOG( TEXT( "FAIL in %s @ line %u:" ), TEXT( __FILE__ ), __LINE__ ); LOG( TEXT( "/twaveInOpen returned error code, #%d." ), mmRtn ); return TPR_FAIL; } |
驱动中会依次调用WAV_IOControlà HandleWaveMessageà DeviceContext::OpenStream()来创建音频流。在函数DeviceContext::OpenStream的实现过程中,首先会去调用DeviceContext::IsSupportedFormat()来判断是否为支持的音频格式流,如果不支持的话则创建失败,这部分代码如下:
BOOL DeviceContext::IsSupportedFormat(LPWAVEFORMATEX lpFormat) { if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) return FALSE;
if ( (lpFormat->nChannels!=1) && (lpFormat->nChannels!=2) ) return FALSE;
if ( (lpFormat->wBitsPerSample!=8) && (lpFormat->wBitsPerSample!=16) ) return FALSE;
if (lpFormat->nSamplesPerSec < 100 || lpFormat->nSamplesPerSec > 192000) return FALSE;
return TRUE; } |
对于支持的音频流格式,则会调用虚函数CreateStream()来创建对应的流,具体的实现将在类DeviceContext的继承中找到,以继承类OutputDeviceContext的实现为例,代码如下:
StreamContext *OutputDeviceContext::CreateStream(LPWAVEOPENDESC lpWOD) { LPWAVEFORMATEX lpFormat = lpWOD->lpFormat;
#if ENABLE_MIDI
if (lpFormat->wFormatTag == WAVE_FORMAT_MIDI) { return new CMidiStream; }
#endif
// 应用层可以通过api的参数来告诉driver有几个channel // 下面会根据具体的通道数和采样来决定创建什么样的output device stream 类实例 switch (lpFormat->nChannels) { case 1:
switch (g_pHWContext->m_dwWavOutChnum) { case 1: return (lpFormat->wBitsPerSample == 8) ? (StreamContext *)new OutputStreamContext1M8 : (StreamContext *)new OutputStreamContext1M16;
case 2: return (lpFormat->wBitsPerSample == 8) ? (StreamContext *)new OutputStreamContext2M8 : (StreamContext *)new OutputStreamContext2M16; case 6: return (lpFormat->wBitsPerSample == 8) ? (StreamContext *)new OutputStreamContext6M8 : (StreamContext *)new OutputStreamContext6M16; default: break; }
break;
case 2:
switch (g_pHWContext->m_dwWavOutChnum) { case 1: return (lpFormat->wBitsPerSample == 8) ? (StreamContext *)new OutputStreamContext1S8 : (StreamContext *)new OutputStreamContext1S16;
case 2: return (lpFormat->wBitsPerSample == 8) ? (StreamContext *)new OutputStreamContext2S8 : (StreamContext *)new OutputStreamContext2S16; case 6: return (lpFormat->wBitsPerSample == 8) ? (StreamContext *)new OutputStreamContext6S8 : (StreamContext *)new OutputStreamContext6S16; default: break; }
break;
default:
switch (g_pHWContext->m_dwWavOutChnum) { case 6: return new OutputStreamContext6X16; }
break; }
return NULL; } |
其实,驱动中可以选择去支持那些格式,没有必要去支持每一种音频Stream格式。