一、数字音频基础知识

Fourier级数:

任何周期的波形可以分解成多个正弦波,这些正弦波的频率都是整数倍。级数中其他正线波的频率是基础频率的整数倍。基础频率称为一级谐波。

PCM:

pulse code modulation,脉冲编码调制,即对波形按照固定周期频率采样。为了保证采样后数据质量,采样频率必须是样本声音最高频率的两倍,这就是Nyquist频率。

样本大小:采样后用于存储振幅级的位数,实际就是脉冲编码的阶梯数,位数越大表明精度越高,这一点学过数字逻辑电路的应该清楚。

声音强度:

波形振幅的平方。两个声音强度上的差常以分贝(db)为单位来度量,

计算公式如下:

20*log(A1/A2)分贝。A1,A2为两个声音的振幅。如果采样大小为8位,则采样的动态范围为20*log(256)分贝=48db。如果样本大小为16位,则采样动态范围为20*log(65536)大约是96分贝,接近了人听觉极限和痛苦极限,是再线音乐的理想范围。windows同时支持8位和16位的采样大小。

二、相关API函数,结构,消息

对于录音设备来说,windows 提供了一组wave***的函数,比较重要的有以下几个:

打开录音设备函数

1.MMRESULT waveInOpen(
2.LPHWAVEIN phwi,            //输入设备句柄
3.UINT uDeviceID,            //输入设备ID
4.LPWAVEFORMATEX pwfx,       //录音格式指针
5.DWORD dwCallback,          //处理MM_WIM_***消息的回调函数或窗口句柄,线程ID
6.DWORD dwCallbackInstance, 
7.DWORD fdwOpen              //处理消息方式的符号位
8.);

为录音设备准备缓存函数

1.MMRESULT waveInPrepareHeader(  HWAVEIN hwi,  LPWAVEHDR pwh, UINT bwh );

给输入设备增加一个缓存

1.MMRESULT waveInAddBuffer(  HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh );

开始录音

1.MMRESULT waveInStart(  HWAVEIN hwi  );

清除缓存

1.MMRESULT waveInUnprepareHeader( HWAVEIN hwi,LPWAVEHDR pwh, UINT cbwh);

停止录音

1.MMRESULT waveInReset( HWAVEIN hwi );

关闭录音设备

1.MMRESULT waveInClose( HWAVEIN hwi );

Wave_audio数据格式

01.typedef struct {
02.WORD  wFormatTag; //数据格式,一般为WAVE_FORMAT_PCM即脉冲编码
03.WORD  nChannels; //声道
04.DWORD nSamplesPerSec; //采样频率
05.DWORD nAvgBytesPerSec; //每秒数据量
06.WORD  nBlockAlign;
07.WORD  wBitsPerSample;//样本大小
08.WORD  cbSize;
09.} WAVEFORMATEX;

waveform-audio 缓存格式 

01.typedef struct {
02.LPSTR  lpData; //内存指针
03.DWORD  dwBufferLength;//长度
04.DWORD  dwBytesRecorded; //已录音的字节长度
05.DWORD  dwUser;
06.DWORD  dwFlags;
07.DWORD  dwLoops; //循环次数
08.struct wavehdr_tag * lpNext;
09.DWORD  reserved;
10.} WAVEHDR;

相关消息 

1.MM_WIM_OPEN:打开设备时消息,在此期间我们可以进行一些初始化工作
2.MM_WIM_DATA:当缓存已满或者停止录音时的消息,处理这个消息可以对缓存进行重新分配,实现不限长度录音
3.MM_WIM_CLOSE:关闭录音设备时的消息。

相对于录音来说,回放就简单的多了,用到的函数主要有以下几个:

打开回放设备 

1.MMRESULT waveOutOpen(
2.LPHWAVEOUT phwo,          
3.UINT uDeviceID,           
4.LPWAVEFORMATEX pwfx,      
5.DWORD dwCallback,         
6.DWORD dwCallbackInstance, 
7.DWORD fdwOpen             
8.);

为回放设备准备内存块 

1.MMRESULT waveOutPrepareHeader(
2.HWAVEOUT hwo, 
3.LPWAVEHDR pwh,
4.UINT cbwh     
5.);

写数据(放音) 

1.MMRESULT waveOutWrite(
2.HWAVEOUT hwo, 
3.LPWAVEHDR pwh,
4.UINT cbwh     
5.);

相应的也有三个消息,用法跟录音的类似:

三、程序设计

一个录音程序的简单流程:

打开录音设备waveInOpen===>准备wave数据头waveInPrepareHeader===>

准备数据块waveInAddBuffer===>开始录音waveInStart===>停止录音(waveInReset) ===>

关闭录音设备(waveInClose)

当开始录音后当buffer已满时,将收到MM_WIM_DATA消息,处理该消息可以保存已录好数据。

回放程序比这个要简单的多: 

打开回放设备waveOutOpen===>准备wave数据头waveOutPrepareHeader===>写wave数据waveOutWrite===>停止放音(waveOutRest) ===>关闭回放设备(waveOutClose)

如何处理MM消息:

MSDN告诉我们主要有 CALLBACK_FUNCTION、CALL_BACKTHREAD、CALLBACK_WINDOW 三种方式,常用的是
Thread,window方式。

线程模式

waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,m_ThreadID,NULL,CALLBACK_THREAD),我们可以继承MFC的CwinThread类,只要相应的处理线程消息即可。

MFC线程消息的宏为:

1.ON_THREAD_MESSAGE,

可以这样添加消息映射:

1.ON_THREAD_MESSAGE(MM_WIM_CLOSE, OnMM_WIM_CLOSE)

窗口模式

类似于线程模式,参见源程序即可。

【转】http://www.lihuasoft.net/article/show.php?id=124

http://www.vckbase.com/index.php/wv/664

【转】vc api 录音的更多相关文章

  1. 小程序API录音后Silk格式转码MP3

    问题 客户端使用小程序,需要录音功能然后到后台页面播放,由于微信提供的录音API压缩后的格式为 .silk格式的,但是这个格式其他播放器都是播放不了的,更何况html页面的audio标签更是不可能播放 ...

  2. VC API常用函数简单例子大全(1-89)

    第一个:FindWindow根据窗口类名或窗口标题名来获得窗口的句柄,该函数返回窗口的句柄 函数的定义:HWND WINAPI FindWindow(LPCSTR lpClassName ,LPCST ...

  3. (转载博文)VC++API速查

    窗口处理 2.1 窗口简介 2.2.1 创建普通窗口(CreateWindow.CreateWindowEx) 2.2.2 关闭窗口(CloseWindow) 2.2.3 销毁窗口(DestroyWi ...

  4. 小程序API录音 微信录音后 Silk格式转码MP3

    http://www.cnblogs.com/wqh17/p/6911748.html

  5. VC/MFC 编程技巧大总结

    1 toolbar默认位图左上角那个点的颜色是透明色,不喜欢的话可以自己改. 2 VC++中 WM_QUERYENDSESSION WM_ENDSESSION 为系统关机消息. 3 Java学习书推荐 ...

  6. 【微信JSSDK】PHP版微信录音文件下载

    微信的录音文件上传到微信服务器上,只能保存三天. 因此需要做一个转存到自己服务器,或者七牛云的操作. 转存到自己服务器 调用微信JSSDK API 录音, 录音结束,上传到微信服务器,获取录音文件的 ...

  7. gcc编译器基本命令

    1 unix操作系统 ubuntu 12版本Unix内核0.5天 常用命令2 c语言:标准c 十天主要练习动手能力 小案例水平高的 自己去写案例水平低的 理解并跟着写3 c++:5天高级语言的特点:面 ...

  8. Gdi+实用入门

    大部分是参照其它资料,然后加以自己的理解,那是什么,总结.算不得什么教程.......汗,自己看着就行了..如果别人能看那就更好了. 首先下载GDI+文件包,一个动态链接库,使用GDI+就是调用那个动 ...

  9. 微信小程序:将中文语音直接转化成英文语音

    作者:瘟小驹    文章来源<微信小程序个人开发全过程> 准备工作: 准备工具:Eclipse.FileZilla.微信开发者工具.一个配置好SSL证书(https)的有域名的服务器 所需 ...

随机推荐

  1. 【转】每天一个linux命令(56):netstat命令

    原文网址:http://www.cnblogs.com/peida/archive/2013/03/08/2949194.html netstat命令用于显示与IP.TCP.UDP和ICMP协议相关的 ...

  2. spark数据倾斜

    数据倾斜的主要问题在于,某个分区数量很巨大,在做map运算的时候,将会发生别的分区task很快计算完成,但是某几个分区task的计算成为了系统的瓶颈,明显超过其他分区时间:   1.方案:Kafka的 ...

  3. javascript 变量定义

    一.javascript中,变量定义的位置与写在哪个<script></script>标签对内无关,只分前后顺序,写在前面的后面就能够访问,写在后面的前面会提示“未定义”. 例 ...

  4. 实际用户ID和有效用户ID (一) *****

    在Unix进程中涉及多个用户ID和用户组ID,包括如下: 1.实际用户ID和实际用户组ID:标识我是谁.也就是登录用户的uid和gid,比如我的Linux以simon登录,在Linux运行的所有的命令 ...

  5. 【ActiveMQ入门-9】ActiveMQ学习-与Spring集成2

    概述: 下面将介绍如何在Spring下集成ActiveMQ. 消费者:同步接收: 目的地:Queue 环境: 共5个文件 Receiver.java ReceiverTest.java Sender. ...

  6. 显式等待大结局___封装成API方便控制层调用

    控制层 测试用例层: 控制层示例代码: #coding=utf-8from selenium.webdriver.common.by import Byfrom selenium.webdriver. ...

  7. [转][html][jquery]

    <!-- 强行修改 CSS --> $('a').css("cssText","background:#fff !important;color:#2d6dc ...

  8. 每秒查询率QPS

    每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量. 原理:每天80%的访问集中在20%的时间里,这20%时 ...

  9. Lua C++互传结构体实例

    转自:http://bbs.csdn.net/topics/350261649 =====main.cpp======= #include "stdio.h" extern &qu ...

  10. Spring bean注解配置(1)

    Spring自带的@Component注解及扩展@Repository.@Service.@Controller,如图 在使用注解方式配置bean时,需要引进一个包: 使用方法: 1.为需要使用注解方 ...