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

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

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

  \% i% ?6 I  T- Z5 R      下载源代码& [) {+ b2 P% C
        
8 b0 Z" V$ A8 n/ L, h) o1 O        引言. L" h5 b. B( ?( S
        我是C++的初学者,入门都要靠VCKBASE,好在里面有很多适合于初学者的例子,让我少走了很多弯路,为了回馈大家,我也把我最近刚完成的一个简单的小程序提供给大家,让那些曾经和我一样徘徊在C++大门之外的人能快些掌握要领,大家不妨看一看。4 T0 [0 l7 [: v. L+ ^# ]
        本文以VC知识库第26期 栾义明 先生的《基于API的录音机程序》为基础的,在此深表感谢!相同之处不再重复,我在此基础上增加了将录音保存为wav文件的格式,便于大家参考。
! M2 ]$ o1 _; e$ d  H0 z. @' i基本步骤及思想:设定音频采集参数(采样率、声道等),打开音频设备、准备wave数据头和开辟缓存,操作采集的数据并保存为wav文件。设定音频回放参数,打开回放设备、准备wave数据头和写wave数据。另外样本程序需包含#include <mmsystem.h>和#pragmacomment(lib,"WINMM.LIB")多媒体支持。
" Y, z. @2 s: x3 o! G        在介绍程序前,需要你对wave文件的格式和相关一些基础概念有所了解,这些均可以在msdn中查找,为方便理解,我们将其整理,如果对这些基础知识已有所了解,可以跳过。
/ `& o; {: _) m        
! ~5 U9 a, c/ b( {1 a      概念1、定义波形数据格式
4 c( r$ [  |/ o% X4 }# X      typedef struct{WORD  wFormatTag;
3 a7 F% x/ P+ h6 y6 f( J% H          WORD nChannels;
9 b6 ^! I& {3 g" y/ T( G4 V          DWORD nSamplesPerSec; 1 I1 \, b5 G* I, {! l! C, K5 L0 Q
          DWORD nAvgBytesPerSec;
1 z" m( D; Z8 W3 n9 _+ ^4 Y6 f          WORD  nBlockAlign; ' o# p' k; i+ `" k, M: b1 `
          WORD wBitsPerSample; * l0 h5 n4 s8 j
          WORD  cbSize; } WAVEFORMATEX;      具体参数解释如下:$ \' a' Q5 x4 f4 m
      wFormatTag:波形数据的格式,定义在MMREG.H文件中
: s" t6 K7 v" J$ y$ K- @      nChannels:波形数据的通道数:单声道或立体声
$ p/ R5 R  I. A6 w  X6 u! X1 `- H* I      nSamplesPerSec:采样率,对于PCM格式的波形数据,采样率有8.0 kHz,11.025kHz,22.05 kHz,44.1 kHz等' M- I/ N$ o" B6 z: s$ c
      nAvgBytesPerSec:数据率,对于PCM格式的波形数据,数据率等于采样率乘以每样点字节数* r* x0 m6 Q  c
      nBlockAlign:每个样点字节数6 J1 @* K4 Z) N7 W$ M( Y7 O
      wBitsPerSample:采样精度,对于PCM格式的波形数据,采样精度为8或16
+ e' X* \9 Q) A      cbSize:附加格式信息的数据块大小6 e8 x+ s8 O1 l8 t0 d2 F
      概念2、定义设备头结构
7 ~) c; Q, E: t0 F    WAVEHDR定义了指向波形数据缓冲区的设备头。typedef struct { LPSTR lpData; 1 m& s" l# R" s7 R" a3 B
        DWORD dwBufferLength;   }; X* Z  W2 `2 \3 c( U
        DWORD dwBytesRecorded; * \7 I" |" K4 `9 m! g( \
        DWORD dwUser; 3 N. X7 H) N& ^! Q
        DWORD dwFlags; ' D+ F& J7 L+ |2 K0 D; F3 [
        DWORD dwLoops; 8 Z8 {7 N' i) a6 p; f* _& E
        struct wavehdr_tag * lpNext;
" {, l; y7 f6 }# I8 k; a        DWORD reserved; } WAVEHDR;     lpData:波形数据的缓冲区地址
4 ?( `" K- d/ `  t    dwBufferLength:波形数据的缓冲区地址的长度
  _3 E# z& G$ K8 M5 s* N- U    dwBytesRecorded:当设备用于录音时,标志已经录入的数据长度: u9 R/ g' U% L' s  s/ g
    dwUser:用户数据
2 H' ]' J) J. G" c6 @4 @1 X+ ^    dwFlags:波形数据的缓冲区的属性+ l) `7 G* ~$ s- f' [
    dwLoops:播放循环的次数,仅用于播放控制中
' `; u% q8 ~  s+ L    lpNext和reserved均为保留值
! @2 j7 [. c7 L" [' [    注意:上述结构体以及我们在程序中所使用到的“HWAVEIN””HWAVEOUT”结构体均是系统已经存在的,我们只需要对其进行赋值即可。
( S% H% D) f' ?1 B* |. d7 _, z    概念3、消息处理函数' o1 B; C9 C/ E+ i6 b$ \
    MM_WIM_OPEN    //设备的打开
7 T5 d/ x3 p) f7 `, Z    MM_WIM_DATA    //设备数据的采集及操作
+ C, k% M% e+ k, `; s0 z7 c    MM_WIM_CLOSE   //设备的关闭
% {7 @- ^' M& C: H# X    相应回放设备的消息分别为MM_WOM_OPEN,MM_WOM_DATA,MM_WOM_CLOSE.
2 D" j' i. `- K1 w- ^8 j- H    注意:消息处理函数是消息自我驱动的,不需要我们的人为干预。比如:当我们打开设备时,系统会自动调用MM_WIM_OPEN,当我们将数据添加到缓冲区,而缓冲区满时,系统会自动调用MM_WIM_DATA,我们所需要做的,就是对该函数编好相应的源代码。5 Z& ]5 Q: Z3 b9 K" `+ v' h
    现在,我们进入正题:如何实现一个录音机。7 b; ?1 Y  r+ P  _/ o& C
    2 u2 E' l1 e+ E* M" D7 i( J4 z  c
    ⑴先对WAVEFORMATEX结构体进行赋值,然后为缓冲区分配内存pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE);  u: f  V2 M( m; ~5 [7 n$ _
pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE);# P- i. o. ]% c
对设备头结构体分配内存pWaveHdr1=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));, x- P4 q4 V. f' B
pWaveHdr2=reinterpret_cast<PWAVEHDR>(malloc(sizeof(WAVEHDR)));
$ U, H, R) _& N- G2 S8 C然后使用wave音频相关函数对输入数据进行操作:7 e% _  n+ D: v1 P5 n+ J' d
. [2 r, X5 @" Z6 J8 t
①为波形输入设备准备缓冲区waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));7 {. p0 Y" x) U) p1 z/ i# ~
waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
- o6 @  F8 h2 j8 o/ C9 O②为波形输入设备添加缓冲区waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
2 h5 T6 j3 ?1 c4 v1 m& vwaveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;; G/ j# K. q& o+ G; u
③启动声音输入设备,将输入数据写入内存waveInStart (hWaveIn) ;⑵编写消息处理函数,其中,MM_WIM_DATA函数是本程序的核心。其主要作用是将输入数据另行保存在一缓冲区内(pSaveBuffer),该缓冲区的长度将随着已录入数据的大小而增加,从而实现保存输入话音数据的功能。同时,可将缓冲区内数据保存为wav文件。其具体实现如下:CFile m_file;
' z- V& o( d3 ^3 b+ n# `CFileException fileException;* a& }6 x9 R; j( S
CString m_csFileName= "F:\\audio.wav";//保存路径
, x7 j+ P( c! S" E  B1 O9 ~m_file.Open(m_csFileName,CFile::modeCreate|CFile::modeReadWrite, &fileException);% ]% |3 z& B+ t' Q# A& O
DWORD m_WaveHeaderSize = 38;
3 U. E4 e9 e+ a; @. C8 ~+ J; xDWORD m_WaveFormatSize = 18;
2 t; ~" G* ~' @% Z6 ^- Fm_file.SeekToBegin();+ u$ x, @3 ]( a0 @' j
m_file.Write("RIFF",4);
+ D9 P% Y% y" U. G$ y4 Funsigned int Sec=(sizeof pSaveBuffer + m_WaveHeaderSize);
9 B9 ^  _& U7 B; r5 a* u7 Am_file.Write(&Sec,sizeof(Sec));; E3 n. |4 o7 L
m_file.Write("WAVE",4);2 x9 K% p2 p% |
m_file.Write("fmt ",4);
, A' @6 ^0 K/ K: U6 W! `m_file.Write(&m_WaveFormatSize,sizeof(m_WaveFormatSize));
; P' r- Z1 e2 A1 |+ om_file.Write(&waveform.wFormatTag,sizeof(waveform.wFormatTag));4 Q! ^9 e' K/ _: N% Z
m_file.Write(&waveform.nChannels,sizeof(waveform.nChannels));
4 I" D/ M. ]' Am_file.Write(&waveform.nSamplesPerSec,sizeof(waveform.nSamplesPerSec));
) u- _% p) G6 s+ a$ L( Hm_file.Write(&waveform.nAvgBytesPerSec,sizeof(waveform.nAvgBytesPerSec));  H) V3 G& c$ r* a4 r6 r' g
m_file.Write(&waveform.nBlockAlign,sizeof(waveform.nBlockAlign));3 t1 J7 H* O; x
m_file.Write(&waveform.wBitsPerSample,sizeof(waveform.wBitsPerSample));
% ^% t9 z! o( |4 H4 E; v7 km_file.Write(&waveform.cbSize,sizeof(waveform.cbSize));4 `8 a: ^& N: U8 f
m_file.Write("data",4);2 p9 V4 {* D% ^( H0 q3 m# Y4 z" H
m_file.Write(&dwDataLength,sizeof(dwDataLength));
, n' _! c" w1 x" W' m) mm_file.Write(pSaveBuffer,dwDataLength);
$ B. V" V# ?* W4 hm_file.Seek(dwDataLength,CFile::begin);
! l: L. n% N2 x2 j4 V' Nm_file.Close();
1 n; a3 J: J2 K4 X存在的问题:) U! S$ @1 A. d2 r! I
我们也才开始vc学习,只是将自己了解的知识与和我们水平相当的新手们分享,希望一起提高。本程序有时不稳定,但音质很好,可能还有尚未暴露的错误,恳请广大高手们不吝赐教。E-mail: xuejing0103@126.comsmilewenjuan@yahoo.com.cn
. B) q; ?4 T, |  H! A" O& t! b) `, N" u) o6 [1 {4 ]' z1 t
原文:http://www.vckbase.com/document/viewdoc/?id=1800
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 10:20 , Processed in 0.019117 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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