找回密码
 注册
搜索
查看: 4289|回复: 0

简单录、放音并保存为wav文件程序

[复制链接]
发表于 2007-11-30 13:43:24 | 显示全部楼层 |阅读模式
作者:任雪景、文娟

9 D+ ]# n3 X& a1 P+ p5 Q; q4 |      下载源代码3 W8 u5 v% |. p9 A
        4 i  `( F% }% J: Z5 ]
        引言
; ]! ~- t: c* Y: Q1 x9 T+ k        我是C++的初学者,入门都要靠VCKBASE,好在里面有很多适合于初学者的例子,让我少走了很多弯路,为了回馈大家,我也把我最近刚完成的一个简单的小程序提供给大家,让那些曾经和我一样徘徊在C++大门之外的人能快些掌握要领,大家不妨看一看。
2 C/ u* Y4 I  V3 ]% H2 o        本文以VC知识库第26期 栾义明 先生的《基于API的录音机程序》为基础的,在此深表感谢!相同之处不再重复,我在此基础上增加了将录音保存为wav文件的格式,便于大家参考。
4 \8 J& z: I' Q1 j- Q& u) F基本步骤及思想:设定音频采集参数(采样率、声道等),打开音频设备、准备wave数据头和开辟缓存,操作采集的数据并保存为wav文件。设定音频回放参数,打开回放设备、准备wave数据头和写wave数据。另外样本程序需包含#include <mmsystem.h>和#pragmacomment(lib,"WINMM.LIB")多媒体支持。
  o7 b3 H" p8 |- g# `. X        在介绍程序前,需要你对wave文件的格式和相关一些基础概念有所了解,这些均可以在msdn中查找,为方便理解,我们将其整理,如果对这些基础知识已有所了解,可以跳过。
5 n  {4 ~) K) V5 X8 j& W        
; n& R5 c; e: R# n5 W# I      概念1、定义波形数据格式
7 o$ M" k6 ~6 I& g" f$ F3 N      typedef struct{WORD  wFormatTag;
" p5 C. X! C2 {          WORD nChannels; 9 s/ |7 O* R) B
          DWORD nSamplesPerSec;
3 V/ G  @+ X6 ]( C9 W          DWORD nAvgBytesPerSec;
$ _" {: u0 e% D# {& K* a' ~8 X          WORD  nBlockAlign;
3 w0 [3 }: i  ^          WORD wBitsPerSample;
& B1 T2 M+ G! d0 V  ]/ `          WORD  cbSize; } WAVEFORMATEX;      具体参数解释如下:7 ?! v. c& K  R0 {
      wFormatTag:波形数据的格式,定义在MMREG.H文件中6 P8 k% f( I* V0 o( m
      nChannels:波形数据的通道数:单声道或立体声$ s, R# z8 a. Y  Q+ u: s0 E
      nSamplesPerSec:采样率,对于PCM格式的波形数据,采样率有8.0 kHz,11.025kHz,22.05 kHz,44.1 kHz等
) D8 ^- l: n; r7 c  f% Z8 S4 T; a      nAvgBytesPerSec:数据率,对于PCM格式的波形数据,数据率等于采样率乘以每样点字节数/ o" C& ^+ h" p2 C# p4 m8 |
      nBlockAlign:每个样点字节数! V1 w5 ]- i4 C" I  G/ v. ?$ s
      wBitsPerSample:采样精度,对于PCM格式的波形数据,采样精度为8或160 x1 X& Q. S9 Y+ j/ J
      cbSize:附加格式信息的数据块大小! k- u$ [! a3 l& P3 V
      概念2、定义设备头结构% D3 ?! V7 U& Z) i( c0 V& H
    WAVEHDR定义了指向波形数据缓冲区的设备头。typedef struct { LPSTR lpData;
) V, B0 e4 a1 [( a/ U, W5 [5 ~" c        DWORD dwBufferLength;
2 v+ T6 C% E( F* a7 K. H) K7 ?        DWORD dwBytesRecorded;
  Y( `  |; ^* |1 |        DWORD dwUser;
) f$ D- S2 Z2 Z# h8 J) X7 J        DWORD dwFlags;
* S) I; d& A- S1 A! Y# u        DWORD dwLoops; : v) m: }. O* a* c0 X
        struct wavehdr_tag * lpNext;
, V/ ?) [! d9 Z4 W! ?! @        DWORD reserved; } WAVEHDR;     lpData:波形数据的缓冲区地址- V( d0 N+ a6 P8 q# z/ `# _! @) {
    dwBufferLength:波形数据的缓冲区地址的长度
6 p5 |" l# K6 p, i+ r$ d    dwBytesRecorded:当设备用于录音时,标志已经录入的数据长度
; |# h* Q6 y, L( B$ B1 i! V    dwUser:用户数据: E, {4 q1 q! v- c8 Z; o
    dwFlags:波形数据的缓冲区的属性
! g2 G$ U# f* U  S1 A    dwLoops:播放循环的次数,仅用于播放控制中
: X/ L' L: T( K9 x# e    lpNext和reserved均为保留值7 Z1 h, |3 E8 q7 h8 y  Y1 @
    注意:上述结构体以及我们在程序中所使用到的“HWAVEIN””HWAVEOUT”结构体均是系统已经存在的,我们只需要对其进行赋值即可。
% {5 h" G# L3 b3 u' N$ U; B3 ~    概念3、消息处理函数; V  N) L8 V4 q( {6 {6 ?. M
    MM_WIM_OPEN    //设备的打开4 @' H# o, j" g) d) x# h
    MM_WIM_DATA    //设备数据的采集及操作
0 J3 C# Y, i1 q    MM_WIM_CLOSE   //设备的关闭( [6 s0 x$ z! n3 H; S( ^4 @
    相应回放设备的消息分别为MM_WOM_OPEN,MM_WOM_DATA,MM_WOM_CLOSE.& x0 d/ I0 S  O' l8 G
    注意:消息处理函数是消息自我驱动的,不需要我们的人为干预。比如:当我们打开设备时,系统会自动调用MM_WIM_OPEN,当我们将数据添加到缓冲区,而缓冲区满时,系统会自动调用MM_WIM_DATA,我们所需要做的,就是对该函数编好相应的源代码。
: {/ g: p! r# Z" N2 v; w( w    现在,我们进入正题:如何实现一个录音机。
+ Y" W# V, L) @  r7 X8 ]" s    * {' I7 I+ h: _3 s8 [# u
    ⑴先对WAVEFORMATEX结构体进行赋值,然后为缓冲区分配内存pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE);
5 J3 H/ H" \9 Y" z, a  ^pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE);
3 ?: w! I  _0 Y; ~4 L3 Z对设备头结构体分配内存pWaveHdr1=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));
/ C9 R8 G: ?3 u8 P/ jpWaveHdr2=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));
/ \, ^7 c) G' N* Z/ M& J4 x. g然后使用wave音频相关函数对输入数据进行操作:
4 q0 h: O( `: g5 U
8 L; F/ p3 i* _0 |①为波形输入设备准备缓冲区waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));2 p1 X8 b4 n" @
waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));$ F. E; A6 w1 W4 c9 w* L0 Z
②为波形输入设备添加缓冲区waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;: @& c/ a: F0 Y9 U( u1 |
waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;: o  m- K* K* z, p& V$ a/ k4 I' o7 n2 w
③启动声音输入设备,将输入数据写入内存waveInStart (hWaveIn) ;⑵编写消息处理函数,其中,MM_WIM_DATA函数是本程序的核心。其主要作用是将输入数据另行保存在一缓冲区内(pSaveBuffer),该缓冲区的长度将随着已录入数据的大小而增加,从而实现保存输入话音数据的功能。同时,可将缓冲区内数据保存为wav文件。其具体实现如下:CFile m_file;3 o& I8 [! z7 M. f2 v
CFileException fileException;
0 W# W2 p0 @* H6 XCString m_csFileName= "F:\\audio.wav";//保存路径
" l/ @0 J: y/ n6 z% |) Nm_file.Open(m_csFileName,CFile::modeCreate|CFile::modeReadWrite, &fileException);4 F' V5 l) }4 O; W1 j3 z: @" `
DWORD m_WaveHeaderSize = 38;
0 h: k3 r2 Z7 t% c. O5 xDWORD m_WaveFormatSize = 18;
9 R1 y8 e) n& x' c6 `; mm_file.SeekToBegin();' v0 C; G8 `' v7 W, x
m_file.Write("RIFF",4);
; s2 \/ [9 @0 c4 T+ Punsigned int Sec=(sizeof pSaveBuffer + m_WaveHeaderSize);
: [7 b( f- W5 g8 M6 C' ]0 {% O/ _m_file.Write(&Sec,sizeof(Sec));  J3 B7 \7 g* Q' k# `3 j$ K
m_file.Write("WAVE",4);; C( h1 a  f0 O9 K  ?
m_file.Write("fmt ",4);
. K8 q3 U- ?6 [m_file.Write(&m_WaveFormatSize,sizeof(m_WaveFormatSize));
; C/ x7 K7 U6 `m_file.Write(&waveform.wFormatTag,sizeof(waveform.wFormatTag));1 b, _1 o$ p* G, M
m_file.Write(&waveform.nChannels,sizeof(waveform.nChannels));
8 A1 L# w% j* p# {" W5 ]/ O8 w0 wm_file.Write(&waveform.nSamplesPerSec,sizeof(waveform.nSamplesPerSec));, s! A& j/ @' x9 C4 v: b
m_file.Write(&waveform.nAvgBytesPerSec,sizeof(waveform.nAvgBytesPerSec));4 q# F: f9 b% ^
m_file.Write(&waveform.nBlockAlign,sizeof(waveform.nBlockAlign));7 C- O1 c( N/ Q+ h0 w$ o
m_file.Write(&waveform.wBitsPerSample,sizeof(waveform.wBitsPerSample));
# I$ G$ y, f% c% U* Im_file.Write(&waveform.cbSize,sizeof(waveform.cbSize));3 V, Z* O7 Q) }" V3 a
m_file.Write("data",4);
0 b' E" n1 U  Xm_file.Write(&dwDataLength,sizeof(dwDataLength));, ?; x' U! a( E1 {2 c7 Q
m_file.Write(pSaveBuffer,dwDataLength);8 L1 d9 F2 b  `: O
m_file.Seek(dwDataLength,CFile::begin);7 |# ~- \( _2 _  x5 ?
m_file.Close();
. M6 O' ?5 k+ v& e7 K* r存在的问题:: I2 G! Z4 Y1 Q. f7 K  v
我们也才开始vc学习,只是将自己了解的知识与和我们水平相当的新手们分享,希望一起提高。本程序有时不稳定,但音质很好,可能还有尚未暴露的错误,恳请广大高手们不吝赐教。E-mail: xuejing0103@126.comsmilewenjuan@yahoo.com.cn
3 d# l% M; ]+ j9 `& e$ N) k# S& g# H! X8 E
原文:http://www.vckbase.com/document/viewdoc/?id=1800
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2025-8-9 06:21 , Processed in 0.034866 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表