DirectSound---捕獲音頻、Qml/C++ 集成交互

DirectSound的音頻捕獲原理和播放原理差很少,內部在一個緩衝區上循環寫入捕獲到的數據,而且提供notify通知功能。git

1. 音頻捕獲

由於捕獲流程和播放流程相似,咱們就不在這裏贅述了,只給出簡單的函數引用和圖示: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

capture-pic

2. 寫入Wav

寫入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

wav-pic

3. Qml/C++ 集成交互

此次我嘗試使用了Qml來進行界面繪製,怎麼說呢:數據綁定確實很好用,許多僅停留在UI層的相互邏輯能夠直接在UI代碼上解決,不用深刻到C++邏輯代碼;可是C++數據類型轉換到Qml不是很方便,且二者的類型系統銜接不天然(例如在Qml中使用C++類型的時候,須要register,額外操做太多)。繼承

在Qml中私用C++類型,必需要藉助Qt的元對象系統,所以咱們須要:接口

  • 繼承自QObject而且帶上Q_OBJECT宏。
  • 屬性用Q_PROPERTY聲明。
  • 枚舉用Q_ENUM描述。
  • 信號、槽是默認支持的,其餘的函數須要用Q_INVOKABLE聲明。

在這個例子中,我須要傳給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);

    ...
}

4. 運行結果

result-pic1 result-pic2 result-pic3

完整代碼見連接

相關文章
相關標籤/搜索