搞了很久的程序,都是做业务系统之类的,还没有搞过多媒体方面的编程,今天动手做个录音机,了解一下声音相关的API,
window下面声音的编程主要有三种方式,
- MCI,这种方式很简单,但是不够灵活
- waveXXXX等低阶的声音API
- 还有就是DirectSound
个人感觉使用waveXXX函数应该是最方便和最灵活的,也是比较简单的,
随便创建一个MFC基于对话框的工程,在窗口类里面增加几个成员
在构造函数对成员进行初始化
m_nRecordState = RECORD_STATE_INIT;
m_dwDataLength = 0;
//open waveform audo for input
//为声音输入设置格式
m_waveform.wFormatTag=WAVE_FORMAT_PCM;
m_waveform.nChannels=1;
m_waveform.nSamplesPerSec=11025;
m_waveform.nAvgBytesPerSec=11025;
m_waveform.nBlockAlign=1;
m_waveform.wBitsPerSample=8;
m_waveform.cbSize=0;
m_pSaveBuffer = NULL;
看看我的窗体
录音的处理函数
然后增加三个消息进行处理
对录音处理的基本原理简单的谈一下,
先调用waveInOpen打开声音设备,设置WAVEHDR类型的缓冲区,其中lpData成员指向缓冲区的内存块,
可以分配动态内存也可以像我这里一样,分配在栈区的内存。接着就可以调用waveInPrepareHeader以及waveInAddBuffer,
调用 waveInStart开始录音,然后会发出消息MM_WIM_OPEN,如果一人缓冲区满了以后就会发出消息MM_WIM_DATA,
我们就可以在这个消息处理函数将声音内容拷到我们自己内存块保存起来,以及增加m_dwDataLength的长度,如果要停止录音,
只要调用一下waveInReset,然后会发出消息MM_WIM_DATA作最后处理,并且发出消息OnMM_WIM_CLOSE作点善后工作,
如在这里调用waveInUnprepareHeader去掉缓冲区,并且设置按钮的状态,lpData指向的是动态内存也可以在这里释放。
注:这里用了两个缓冲区,可以使声音连续,如果只使用一个缓冲区会导致声音有顿
现在看看声音播放,先看代码
声音的播放相对简单一点,在这里这种情况不需要用到双缓存技术,只要调用 waveOutOpen打开声音播放句柄,
然后响应 MM_WON_OPEN消息,设置缓冲区,就可以了
当然,如果是网络聊天的时候发出来的声音包应该不是这样一大块的内存,而是一小块一小块就得用到双缓存技术,
需要处理MM_WOM_DONE,以便重新加入声音包,可以顺畅的播放;在这里只是简单的去掉缓冲区
然后现在就剩下保存成wav,以后读取wav文件了
首先看一下wav文件的格式,以下内容部分摘自window程序设计
| 表22-1 .WAV档案格式 |
| 偏移量 | 位元组 | 资料 |
|---|---|---|
| 0000 | 4 | 「RIFF」 |
| 0004 | 4 | 波形块的大小(档案大小减8) |
| 0008 | 4 | 「WAVE」 |
| 000C | 4 | 「fmt 」 |
| 0010 | 4 | 格式块的大小(16位元组) |
| 0014 | 2 | wf.wFormatTag = WAVE_FORMAT_PCM = 1 |
| 0016 | 2 | wf.nChannels |
| 0018 | 4 | wf.nSamplesPerSec |
| 001C | 4 | wf.nAvgBytesPerSec |
| 0020 | 2 | wf.nBlockAlign |
| 0022 | 2 | wf.wBitsPerSample |
| 0024 | 4 | 「data」 |
| 0028 | 4 | 波形资料的大小 |
| 002C | 波形资料 |
波形声音档案以文字字串「RIFF」开始,用来标识这是一个RIFF档案。字串後面是一个32位元的资料块大小,表示档案其余部分的大小,或者是小於8位元组的档案大小。
--------------------------------
基于上面的了解,就可以写一个读取wav包头的函数了
以及写wav头媒体信息
现在还有一点,就是 这个录音机还没有加入声音的压缩,算了,等有时间再弄吧
这样用waveXXX函数播录放声音的用法基本上描述清楚了,不得不再次感叹,真后悔当初语文不好好学,现在连个简单
的东西都说不明白,真是抱歉,高中的时候上语文就相当于上睡觉课,不过想起来,也确实睡得很爽!
如果你觉得弄这些太没有意思,想要工程的话,那就直接留下地址吧
直接下载吧,大家看样子比较不喜欢整工程,有邮件我没有回的同志们,对不住了,工作太忙,没有维护blog了
http://git.oschina.net/linbc/WaveRecordLite.git