DirectSound---捕获音频、Qml/C++ 集成交互

摘要:
DirectSound的音频捕获原理与回放原理相似。它在内部将捕获的数据循环写入缓冲区,并提供通知通知功能。HMMIOmmioOpen;MMRESULTmmioCreateChunk;LONGmmioWrite;MMRESULTmmioAscend;MMRESULTmmioClose;3.Qml/C++集成交互这次我尝试使用Qml绘制界面。我能说什么?数据绑定非常好。许多只停留在UI层的相互逻辑可以直接在UI代码中解决,而不是深入到C++逻辑代码中;然而,将C++数据类型转换为Qml并不是很方便,两者的类型系统也不是自然连接的。此外,QVariantMap可以在Qml中隐式转换为JavaScript数组,但这不是那么自然。

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

流程图如下:

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);

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,但是不是那么自然。

例子中用到的大概就是这样:

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-pic1result-pic2result-pic3

完整代码见链接

免责声明:文章转载自《DirectSound---捕获音频、Qml/C++ 集成交互》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle ADG环境搭建filebeat v6.3 多行合并的步骤 多个表达式同时匹配下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

WINDOWS7(vs2012+wdk7.6) 配置驱动开发环境

合肥程序员群:49313181。    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com 1.新建C++Win32控制台空项目 2.  新建项目Driver”配置“ ,点击下拉按钮-点击(配置管理器) 3.输入名称(Driver),其他的不需要任何修改...

iOS ---不一样的NSLog打印(精准打印)

  在iOS开发过程中,调试是很重要的过程,而除了各种断点调试(普通断点、条件断点、全局断点)之外,似乎NSLog是我们调试最常用的方法,当然,也是最简单朴素的寻debug方法。   在项目中,我们常使用的NSLog的语句无外乎以下一种:    NSLog(@"打印字符串:%@",name); NSLog(@"打印整形:%i",number);//或...

【转帖】C++编译原理 资料

转自:http://blog.csdn.net/shiwenbin333/article/details/5157797 首先是预编译,这一步可以粗略的认为只做了一件事情,那就是“宏展开”,也就是对那些#***的命令的一种展开。       例如define MAX 1000就是建立起MAX和1000之间的对等关系,好在编译阶段进行替换。       例如...

c++ 开源日志库选择

liblogger 待选为 glog、log4cplus、log4cpp、log4cxx 目前准备使用glog,使用方便,性能也不错,待进一步试验,如果有不能满足的功能就转用 log4cplus,功能很全面,不过稍复杂些。 其它两个都是三年前就没更新,没好感,暂不准备使用。 1.log4cplus 最新版本:1.1.0 2012-03-11 下载地址:ht...

聚合类型与POD类型

Lippman在《深度探索C++对象模型》的前言中写道: I have heard a number of people over the years voice opinions similar to those of your colleagues. In every case, those opinions could be attributed...

__cplusplus的用法(转)

经常在/usr/include目录下看到这种字句: #ifdef __cplusplusextern "C" {#endif...#ifdef __cplusplus}#endif 不太明白是怎么用的。今天阅读autobook,在第53页看到了作者的解释:C/C++编译器对函数和变量名的命名方法不一样(例如C++中重载的函数有多个名字,而C的函数只有一个...