DirectSound的音頻捕獲原理和播放原理差很少,內部在一個緩衝區上循環寫入捕獲到的數據,而且提供notify通知功能。git
由於捕獲流程和播放流程相似,咱們就不在這裏贅述了,只給出簡單的函數引用和圖示:github
最後兩個是音效捕獲接口,用來控制Aec(回聲消除)、Noise Fill(噪音填充)、Ns(噪音壓制)的開啓與關閉:函數
HRESULT DirectSoundCaptureEnumerate(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext)
HRESULT DirectSoundCaptureCreate8(LPCGUID lpcGUID, LPDIRECTSOUNDCAPTURE8 * lplpDSC, LPUNKNOWN pUnkOuter)
IDirectSoundCapture8::GetCaps(LPDSCCAPS pDSCCaps)
HRESULT IDirectSoundCapture8::CreateCaptureBuffer(LPCDSCBUFFERDESC pcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER * ppDSCBuffer, LPUNKNOWN pUnkOuter)
HRESULT IDirectSoundBuffer8::GetObjectInPath(REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID * ppObject)
IDirectSoundCaptureFXAec8
IDirectSoundCaptureFXNoiseSuppress8ui
流程圖以下:code
寫入Wav文件,咱們可使用微軟自帶的mmio系列函數,可是切記不能與本身讀寫內存位置混用操做,否則會出各類無腦問題。對象
HMMIO mmioOpen(LPTSTR szFilename, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags);
MMRESULT mmioCreateChunk(HMMIO hmmio, LPMMCKINFO lpck, UINT wFlag);
LONG mmioWrite(HMMIO hmmio, char _huge *pch, LONG cch);
MMRESULT mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT wFlags);
MMRESULT mmioClose(HMMIO hmmio, UINT wFlags);blog
此次我嘗試使用了Qml來進行界面繪製,怎麼說呢:數據綁定確實很好用,許多僅停留在UI層的相互邏輯能夠直接在UI代碼上解決,不用深刻到C++邏輯代碼;可是C++數據類型轉換到Qml不是很方便,且二者的類型系統銜接不天然(例如在Qml中使用C++類型的時候,須要register,額外操做太多)。繼承
在Qml中私用C++類型,必需要藉助Qt的元對象系統,所以咱們須要:接口
在這個例子中,我須要傳給Qml一個設備列表,可是Qml的list在Qt/C++中並無直接對應的類型,這裏須要用到Qt的QVariantList,在C++傳給Qml時QVariantList會被直接轉換成list。此外i,QVariantMap能夠在Qml中能夠被隱式轉換成JavaScript的Array,可是不是那麼天然。
ip
例子中用到的大概就是這樣:
class CppDsCapture : public QObject { Q_OBJECT Q_PROPERTY(QVariantList avaiableDeviceNames READ avaiableDeviceNames) public: enum EffectType { AcousticEchoCancellationMicrosoft, AcousticEchoCancellationSystem, NoiseSuppressionMicrosoft, NoiseSuppressionSystem, None }; Q_ENUM(EffectType) ... ////////////////////////////////////////////////////////////// // QML functions Q_INVOKABLE void openDevice(unsigned deviceIndex); ... }
完整代碼見連接。