依赖条件:1 #pragma comment ( lib, "winmm.lib" )

音频的输入大体分三步

1 打开设备 -----waveInOpen(打开一个音频输入设备)、

2 开始录音------waveInStart开始录音

3关闭设备-------waveInClose关闭录音。之前调用一下waveInReset,这样可以清掉尚在等待录音的缓冲区

常用的相关API为:

waveInOpen(打开一个音频输入设备)

waveInPrepareHeader(为一个即将在waveInAddBuffer中调用的输入缓冲区准备头部)

waveInAddBuffer(添加一个输入用的数据缓冲区)

waveInStart(开始录音)

waveInClose(关闭音频输入设备)等几个,以及需要在waveInOpen中指定的一个回调函数或者线程,其作用是在一个数据缓冲区被录满后被调用,以对这些数据进行处理,和其他一些相关的操作。注意这里的一个数据缓冲区。

下面详细说明他们相对应的关系。

1---------------waveInOpen

MMRESULT waveInOpen( LPHWAVEIN phwi,  //phwi是返回的句柄存放地址
UINT uDeviceID,   // uDeviceID是要打开的音频设备ID号,一般都指定为WAVE_MAPPER
LPWAVEFORMATEX pwfx,
DWORD dwCallback,  //dwCallback则为指定的回调函数或线程,窗口等的地址
DWORD dwCallbackInstance,   // dwCallbackInstance为需要向回调函数或线程送入的用户参数
DWORD fdwOpen  // fdwOpen指定回调方式:CALLBACK_FUNCTION, CALLBACK_THREAD和CALLBACK_WINDOW
);
  至于pwfx,则比较关键,它指定了要以什么音频格式打开音频输入设备, 它是一个结构WAVEFORMATEX:
typedef struct { WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
    可以在wFormatTag中指定一些压缩的音频格式,如G723.1,TURE DSP,等之类。不过一般都是选用WAVEFORMAT_PCM格式,即未压缩的音频格式,至于压缩,可以在录完后调用下面将要谈到的ACM单独进行。
  nChannels为声道数,1或者2。

nSamplesPerSec为每秒采样数,8000、11025、22050、44100为几个标准值。

nAvgBytesPerSec为每秒平均的字节数,在PCM方式中就等于nChannels*nSamplesPerSec*wBitsPerSample/8,但对于其它的压缩的音频格式,由于很多压缩方式是按时间片进行的,如G723.1,就是以30ms为一个压缩单位,这样,nAvgBytesPerSec只是一个大概的数字,并不准确,程序中的计算是不应该以这个量为准的。这一点在下面的压缩音频输出和ACM音频压缩中非常重要。

nBlockAlign是一个比较特殊的值,表示对音频处理时的最小处理单位,对于PCM非压缩,它就是wBitsPerSample*nChannels/8,而对于非压缩格式,则表示压缩/解压处理的最小单位了,如G723.1,就是30ms的数据大小(20bytes或者24bytes)。

wBitsPerSample就是每采样值的位数,8或者16。

cbSize则是表示该WAVEFORMATEX的结构在标准的头部之后还有多少字节数,对于很多非PCM的音频格式,有一些自己的定义格式参数,这些就紧跟在标准的WAVEFORMATEX后面,其大小就由cbSize指定。对于PCM格式而言,为0,或者忽略不检查。
  这样,指定了这些参数后,你应该就能够打开音频输入设备了。下面要做的事情就是准备几个用做录音的缓冲区。常准备多个缓冲区,并在回调中循环使用。对于缓冲区,得使用waveInPerpareHeader准备一下头部,这个API比较简单,如果你是循环使用缓冲区,对每个缓冲区也只需要调用一次waveInPrepareHeader。为什么要使用一次就可以。参看waveInPerpareHeader说明就明白。此函数功能就是定位缓冲区的数据区地址,和数据大小。以便为系统所用。
  A)

首先得确定一下需要用什么回调方式,即在某个时间片的音频数据被录完后,Windows将通过这个回调来激活对这些数据的处理过程,一般用到的无非是FUNCTION、THREAD和EVENT这几类,而比较方便简单的就是FUNCTION和THREAD了。FUNCTION方式是指Windows会调用你这个函数,而THREAD则是由 Windows来激活你所指定的线程。这些都在waveInOpen中指定。
   b)
  一切准备好之后,就可以调用waveInAddBuffer和waveInStart开始录音了,只要你一调用这个waveInStart,录音就开始了,即使这个缓冲区录满之后你没有加入新的缓冲区进去,录音也不会停,只是这中间的语音数据全都丢了。当通过 waveInAddBuffer送入的缓冲区被录满后,Windows就会通过你在waveInOpen中指定的方式进行回调,在回调中把录好的语音数据取出来,并且,如果还想继续录音的话,得将下一个缓冲区添加进去。考虑到这个处理是有时间延迟的,而且音频对时间很敏感,

一般都要先预加入若干个缓冲区,有人提出:比如,一共定义了8个缓冲区,而为了保险起见,最好保证任一时刻至少有3个缓冲区可被录音使用,那么在开始录音时,则先加入4个缓冲区,然后在回调中,如果当前录好的缓冲区第n个,则对第(n+4)%8调用waveInAddBuffer,这时,还有第(n+1)%8,(n+2)%8, (n+3)%8这三个缓冲区可用,即基本上就可以保证所录得音频中不会有断开的间隔。比如0,1,2,3这些个先加入,当0好的时候对4,5 ,6 ,7调用waveInAddBuffer。

如此这样何不:开始的时候把8个全部放入缓冲区,当一个缓冲区满后调用回调,处理后立即把这个缓冲区重用,继续添加到缓冲区队列中。不更简单明了。如下

mmReturn = ::waveInPrepareHeader ( m_hRecord, pHdr, sizeof(WAVEHDR) ); //准备

mmReturn = ::waveInAddBuffer ( m_hRecord, pHdr, sizeof(WAVEHDR) );//添加

注意这两步都是在回调,或者线程中处理的。

c)

想结束录音时,最好在waveInClose之前调用一下waveInReset,这样可以清掉尚在等待录音的缓冲区,这里常见的问题是等待的缓冲区清理了,可是正在用的缓冲区怎么办?如果这个时候就用waveInClose,那么系统会出错。解决方法一:在回调函数中注意,一个缓冲区满后,不要再用waveInAddBuffer增加缓存,当缓冲区用到1的时候调用waveInReset清掉尚在等待录音的缓冲区继续waveInClose。

总结上面的注意3点:回调的选取,注意缓冲区的原理,注意结束的处理

windows waveform方式实现录音要通过这么几步:(注意顺序!!)

一、打开录音设备

waveinopen()函数

注意,调用之前要填写好wav头信息(包含采样率、采样位数等);还要定义好回调函数等,回调函数的解释后面讲。

二、准备好录音缓存空间

waveinprepareheader()函数

这一步为了准备好将要送入录音设备的缓存,以便之后可以供之使用。

一般至少需要准备两块缓存。因为录音不能间断,当一块填满时没有时间等待你去送入下一块缓存,所以必须提前就准备好。

三、将缓存送入录音设备

waveinaddbuffer()函数

将缓存送入录音设备,供之存入已录下的音频。开始录音时,应至少送入两块不同的缓存,即调用两次这个函数。之后为了不致录音产生间断,应保证至少有一块缓存在录音时为空,以备衔接。

四、开始录音

waveinstart()函数

当以上的工作都准备好时,便可调用此函数开始录音了。一旦调用,录音设备便立即录音并存入已经送来的缓存块内,当被送来的有多个缓存块时,按照FIFO的原则向缓存块内存入录音数据。此函数执行之后可以执行一个while()循环,来等待录音设备录音。为了减少cpu使用率,可以在循环中加人sleepex(x,TRUE),x单位ms,TRUE必须要有。

每个缓冲块存满时,会产生一个回调信号,并调用回调函数(或回调窗口等,具体定义在waveinopen函数内,这里只讲回调函数的情况);回调信号自动被回调函数接收,回调函数根据回调信号来执行各种相应的操作。回调函数执行完后,程序跳回到原来执行位置继续执行。回调函数的具体如下:

回调信号一般有三个,对应着三种回调函数被调用的情况:

1、  WIM_OPEN

当执行waveinopen()函数时,会调用回调函数,并产生这个回调信号。代表录音设备已经打开。在这次回调函数的调用中,可以自己设定一些操作,也可以没有操作。

2、  WIM_DATA

当每块缓存块填满时,产生这个回调信号,并调用回调函数。在这次调用中,回调函数应当完成这样的工作,以便录音连续进行:

将存满的缓存块处理,例如存入文件,或送入其他设备;

向录音设备送入新的缓存块;录音设备任何时刻应当拥有不少于2个的缓存块,以保证录音不间断性。

3、  WIM_CLOSE

当调用waveinclose函数时,会产生这个回调信号,代表录音设备关闭成功。这次回调函数调用中,可以执行相应的一些关闭文件保存信息等等的操作,自定义。

五、停止录音,关闭设备

waveinstop()停止录音

waveinreset()复位

waveinclose()关闭设备

依次调用这些函数,来结束录音。

最后,注意在代码开头要包含windows.h和mmsystem.h两个头文件,还要加人库winmm.lib,用#pragma comment(lib,”winmm.lib”)即可。

主要顺序就是这些,注意每一步要完成的工作,一旦没有按顺序执行或者没有把每步应当完成的工作做完,录音是不能够启动的

windows录音程序原理相关推荐

  1. 【系统篇】从int 3探索Windows应用程序调试原理

    http://www.cnblogs.com/xuanyuan/p/3998408.html 探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令--in ...

  2. 比较windows phone程序启动和android程序启动原理

    windows phone 程序是如何启动的了,他和android程序有什么区别,我们重点从native code 层面来分析 在windows phone 程序启动的时候是: 在XAML中使用应用程 ...

  3. [视频]用SQL Server Compact创建简单的Windows应用程序

    今天下午录制了一段 SQL Server Compact 应用程序开发的入门视频,帮助园子里的朋友打开 SQL Server Compact 开发的大门. 技术等级:100 准备环境:Visual S ...

  4. 用vc++穷举windows应用程序密码

    一.引言 随着计算机信息技术的发展,人们越来越重视信息的安全性,信息数据的安全保密已经成为影响计算机发展的一个重要课题.机密文件.商业情报.银行账号.网络密码.科技成果.包括私人信件等等,都成了用户为 ...

  5. 用vc++穷举windows应用程序密码(上)

    2007年10月12日 02:14:00 一.引言 随着计算机信息技术的发展,人们越来越重视信息的安全性,信息数据的安全保密已经成为影响计算机发展的一个重要课题.机密文件.商业情报.银行账号.网络密码 ...

  6. 提高微信小程序的应用速度的常见方式有哪些? 小程序怎么实现下拉刷新? 简述微信小程序原理? 小程序的发布流程(开发流程)分析下微信小程序的优劣势?小程序授权登录流程? 小程序支付如何实现

    小程序部分常见面试题 提高微信小程序的应用速度的常见方式有哪些? 提高页面加载速度 用户行为预测 减少默认data的大小 组件化方案 分包预下载 小程序与原生App相比优缺点? 优点: 基于微信平台开 ...

  7. XMLHTTP小偷程序原理

    小偷程序原理和简单示例 发表:2004-4-13 164720 出处:你的博客网(yourblog.org) 现在网上流行的小偷程序比较多,有新闻类小偷,音乐小偷,下载小偷,那么它们是如何做的呢,下面 ...

  8. (转)Windows应用程序中动态的控制输入法

    在Windows系统中一般都安装了至少三种输入法,在输入数据时常常会切换输入法,虽然Windows系统提供了切换快捷健,但对输入工作还是带来了不少麻烦.如果在应用程序中为用户提供智能输入法自动切换,那 ...

  9. 基于ALSA的WAV播放和录音程序

    本文转载博客:http://blog.csdn.net/azloong/article/details/6140824 ---------------------------------------- ...

最新文章

  1. 微信公共平台消息回复类
  2. 委托、事件的个人理解
  3. SharePoint关于publish page, WiKi page, Web part page区别
  4. c语言传入的指针无返回值,c语言 关于指针注意事项
  5. 前端学HTTP之客户端识别和cookie
  6. 南阳oj-----懒省事的小明(set)
  7. 查看linux系统语言并修改
  8. 51单片机c语言算法大全,C语言实现51单片机中的PID算法
  9. SoC,SiP,IP和Chiplet的区别
  10. excel 删除大量空白行
  11. 长假之后,Scrum团队应该修改Sprint的结束时间吗?
  12. 在Status状态栏中的出现Out of date shapes问题解决方式
  13. win10无法防问其他计算机没有权限,win10系统访问磁盘共享没有权限的解决方案...
  14. 如何将ANSYS19 Structural 图形界面背景底色更改为白色
  15. Global Sensing and Measurements Reuse for Image Compressed Sensing
  16. 班级网站(网页设计实验)
  17. 艾永亮:B站破壁出圈,同是弹幕视频网站,为什么倒下的是A站?
  18. css动画中文字慢慢显示,利用定时器和css3动画制作文字依次渐变显示的效果
  19. java反射字段6,java反射判断字段类型
  20. 区块链蕴含的变革力量

热门文章

  1. 图片复制word java_java poi实现word导出(包括word模板的使用、复制表格、复制行、插入图片的使用)...
  2. C语言斐波那切数列数列求和
  3. wegame显示不出区服务器,wegame无法显示网页怎么办?腾讯wegame无法显示网页的三种解决方法...
  4. 适合苹果的蓝牙耳机推荐,音质超好的蓝牙耳机推荐
  5. 哪种蓝牙耳机比较好?2022TWS耳机推荐
  6. C和C++的区别点汇总
  7. php药膳 源码,5款药膳方治疗关节炎
  8. python人像精细分割_基于UNet网络实现的人像分割 | 附数据集
  9. 和在java和c语言中的那些事
  10. 朴素贝叶斯分类(python实现)