DirectSound 的音频捕获原理和播放原理差不多, 内部在一个缓冲区上循环写入捕获到的数据, 并且提供 notify 通知功能
1. 音频捕获
因为捕获流程和播放流程类似, 我们就不在这里赘述了, 只给出简单的函数引用和图示:
最后两个是音效捕获接口, 用来控制 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
- IDirectSoundCaptureFXNoiseSuppress8
流程图如下:
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);
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, 但是不是那么自然
例子中用到的大概就是这样:
- 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. 运行结果
完整代码见链接 https://github.com/lgxZJ/Miscellaneous/tree/master/Audio/QmlDirectSoundCapture
来源: https://www.cnblogs.com/lgxZJ/p/8681577.html