windows音频处理

 

WINDOWS下对音频的处理过程

WINDOWS 下对音频的处理,大致可分为两部分,即音频的输入、输出,和 ACM 压缩处理。

  一般情况下在 WINDOWS 下可以调用诸如 sndPlaySound API(MCI) 来播放一个 WAV 文件,但那显然不是我们需要做的。必须能够直接对音频数据流进行处理。在 WINDOWS 下,也为之提供了一系列的 API ,以 waveIn waveOut 开头的一组 API 就是干这个的。

  先说输入吧。常用的相关 API waveInOpen (打开一个音频输入设备)、 waveInPrepareHeader (为一个即将在 waveInAddBuffer 中调用的输入缓冲区准备头部)、 waveInAddBuffer (添加一个输入用的数据缓冲区)、 waveInStart (开始录音)、 waveInClose (关闭音频输入设备)等几个,以及需要在 waveInOpen 中指定的一个回调函数或者线程,其作用是在一个数据缓冲区被录满后被调用,以对这些数据进行处理,和其他一些相关的操作。

  首先你得确定一下需要用什么回调方式,即在某个时间片的音频数据被录完后, Windows 将通过这个回调来激活对这些数据的处理过程,一般用到的无非是 FUNCTION THREAD EVENT 这几类,而比较方便简单的就是 FUNCTION THREAD 了。 FUNCTION 方式是指 Windows 会调用你这个函数,而 THREAD 则是由 Windows 来激活你所指定的线程。这些都在 waveInOpen 中指定。其函数原型为:

MMRESULT waveInOpen( LPHWAVEIN phwi,
UINT uDeviceID,
LPWAVEFORMATEX pwfx,
DWORD dwCallback,
DWORD dwCallbackInstance,
DWORD fdwOpen
);

  其中: phwi 是返回的句柄存放地址, uDeviceID 是要打开的音频设备 ID 号,一般都指定为 WAVE_MAPPER dwCallback 则为指定的回调函数或线程等的地址, fdwOpen 指定回调方式, dwCallbackInstance 为需要向回调 函数或线程送入的用户参数。至于那个 pwfx ,则比较关键,它指定了要以什么音频格式打开音频输入设备, 它是一个结构 WAVEFORMATEX
typedef struct { WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
  机器上的 WIN9X 安装时选择了音频压缩,可以在 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

  一切准备好之后,就可以调用 waveInAddBuffer waveInStart 开始录音了,只要你一调用这个 waveInStart ,录音就开始了,即使这个缓冲区录满之后你没有加入新的缓冲区进去,录音也不会停,只是这中间的语音数据全都丢了。当通过 waveInAddBuffer 送入的缓冲区被录满后, Windows 就会通过你在 waveInOpen 中指定的方式进行回调,在回调中把录好的语音数据取出来,并且,如果还想继续录音的话,得将下一个缓冲区添加进去。考虑到这个处理是有时间延迟的,而且音频对时间很敏感,一般都要先预加入若干个缓冲区,比如,一共定义了 8 个缓冲区,而为了保险起见,最好保证任一时刻至少有 3 个缓冲区可被录音使用,那么在开始录音时,则先加入 4 个缓冲区,然后在回调中,如果当前录好的缓冲区第 n 个,则对第 (n+4)%8 调用 waveInAddBuffer ,这时,还有第 (n+1)%8,(n+2)%8, (n+3)%8 这三个缓冲区可用,即基本上就可以保证所录得音频中不会有断开的间隔。

  想结束录音时,最好在 waveInClose 之前调用一下 waveInReset ,这样可以清掉尚在等待录音的缓冲区,同时在回调中还必须注意一下送入参数中的消息种类。

  音频输出部分相对简单一点。对应的 API waveOutOpen waveOutPrepareHeader waveOutWrite 以及 waveOutClose 。如果希望直接输出压缩格式的音频的话,必须注意 waveOutOpen 中指定的音频格式参数。你必须很清楚这类格式的具体参数及其含义。不过,你可以通过下面说到的 ACM Audio Compress Manager )得到你需要的音频格式的具体参数,这个格式参数可以直接用于 waveOutOpen 。如同音频的输入, waveOutPrepareHeader 也是必需的。 waveOutWrite 则是填入输出缓冲区,为了避免间断,也应该保证某一时刻缓冲区队列中数目足够。



  如果安装 WIN98 时在附件中选择了音频压缩,那么机器上的 ACM 就可用了。 ACM Audio Compress Manager WIN98 提供了一些常用的音频压缩算法程序包,供用户调用。可以通过 ACM 获得本机上所有的音频压缩驱动及其所支持的音频格式。不过,似乎不是每种 ACM 格式都能被调用来进行压缩 , 不过 ACM 中的压缩驱动大多都是针对语音频段,如果用来压缩频带较宽的音频,如音乐,则效果很差 .
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值