windows下的录放音

 2440 win-ce5.0 下实现,录音、播放录音

一、要用到得数据结构

1 、

       typedef struct tWAVEFORMATEX

{

    WORD        wFormatTag;         // format type

    WORD        nChannels;          // number of channels (i.e. mono, stereo...)

    DWORD       nSamplesPerSec;     // sample rate

    DWORD       nAvgBytesPerSec;    // for buffer estimation

    WORD        nBlockAlign;        /* block size of data

    WORD        wBitsPerSample;     // number of bits per sample of mono data

    WORD        cbSize;             // the count in bytes of the size of

                     /* extra information (after cbSize)

} WAVEFORMATEX, *PWAVEFORMATEX, NEAR *NPWAVEFORMATEX, FAR *LPWAVEFORMATEX;

参数说明:

wFormatTag 是音频格式类型

nChannels 是声道数

nSamplesPerSec 是采样频率

nAvgBytesPerSec 是每秒钟的字节数

nBlockAlign 是每个样本的 字节数

wBitsPerSample 是每个样本的量化位数

cbSize 是附加信息的字节大小。

2 、

wave data block header

typedef struct wavehdr_tag {

    LPSTR       lpData;                 // pointer to locked data buffer

    DWORD       dwBufferLength;         // length of data buffer

    DWORD       dwBytesRecorded;        // used for input only

    DWORD       dwUser;                 // for client's use

    DWORD       dwFlags;                // assorted flags (see defines)

    DWORD       dwLoops;                // loop control counter

    struct wavehdr_tag FAR *lpNext;     // reserved for driver

    DWORD       reserved;               // reserved for driver

} WAVEHDR, *PWAVEHDR, NEAR *NPWAVEHDR, FAR *LPWAVEHDR;

参数说明:

lpData 是指定的缓冲块地址

dwBufferLength 是指定的缓冲块大小

dwBytesRecorded 是已录音数据大小

dwUser 是用户数据

dwFlags 是控制标志表明缓冲的使用状态

dwLoops 是音频输出时缓冲数据块循环的次数

lpNext 是系统保留数据

reserved 是系统保留数据

 

 

二、基本操作流程:

1、 录音流程

(1)       打开录音设备: waveInOpen

(2)       为录音设备准备缓存: waveInPrepareHeader

(3)       为输入设备增加缓存: waveInAddBuffer

(4)       启动录音: waveInStart

(5)       清除缓存: waveInUnprepareHeader

(6)       停止录音: waveInReset

(7)       关闭录音设备: waveInClose

 

2、 声音输出流程

(1) 打开输出设备: waveOutOpen

(2) 为输出设备准备缓存: waveOutPrepareHeader

(3) 写数据导输出设备缓存: waveOutWrite

(4) 清除输出缓存: waveOutUnprepareHeader

(5) 停止输出: waveOutReset

(6) 关闭输出设备: waveOutClose

 

三、消息及处理

在录音,声音输出过程中,会产生很多 WM_WIM_*** 格式的 WINDOWS 消息。程序通过捕获 这些消息对缓存,数据和设备进行处理

1、 录音过程消息

(1)       WM_WIM_OPEN  音频输入 设备打开消息

(2)       WM_WIM_DATA    缓冲录满或停止录音消息

(3)       WM_WIM_CLOSE 音频输入 设备关闭消息

2、  播放过程消息

(1)       WM_WOM_OPEN 音频输出 设备打开消息

(2)       WM_WOM_DONE 缓冲播放完或停止输出消息

(3)       WM_WOM_CLOSE 音频输出 设备关闭消息

 

四、程序设计

 

1 、开始录音

void CRecorderDlg::OnRecStart()

{

       // TODO: Add your control notification handler code here

 

       m_pBuffer1=(PBYTE)malloc(INP_BUFFER_SIZE);

       m_pBuffer2=(PBYTE)malloc(INP_BUFFER_SIZE);

       if (!m_pBuffer1 || !m_pBuffer2) {// 判断是否为空

              if (m_pBuffer1) free(m_pBuffer1);//

              if (m_pBuffer2) free(m_pBuffer2);

              MessageBeep(MB_ICONEXCLAMATION);// 发出声音

              AfxMessageBox((CString)"Memory error!");

              return ;

       }

      

       MessageBeep(MB_OK);

 

       // WAVEFORMATEX 结构体,声音在采集(录音)和播放的时需要有一些统一的格式,包括音频格式类型,声道,采样率等信息

       //open waveform audo for input

       m_waveform.wFormatTag=WAVE_FORMAT_PCM;//PCM 脉冲编码调制(指定格式类型 ; 默认WAVE_FORMAT_PCM = 1 )

       m_waveform.nChannels=1;// 单声道

       m_waveform.nSamplesPerSec=11025;11.025kHz (抽样率)

       m_waveform.nAvgBytesPerSec=11025;// 指定数据传输的传输速率 ( 每秒的字节数

       m_waveform.nBlockAlign=1;// 指定块对齐 ( 每个样本的字节数 ), 块对齐是数据的最小单位 }

       m_waveform.wBitsPerSample=8;//8 bit (抽样编码比特数)采样大小 ( 字节 ), 每个样本的量化位数

       m_waveform.cbSize=0;//{ 附加信息的字节大小 }

 

MMRESULT WINAPI waveInOpen(LPHWAVEIN phwi,

  UINT uDeviceID,

LPCWAVEFORMATEX pwfx,

DWORD dwCallback,

DWORD dwInstance,

DWORD fdwOpen);

参数说明:

LPHWAVEIN phwi 用于返回设备句柄的指针

UINT uDeviceID 设备 ID

LPCWAVEFORMATEX pwfx     TWaveFormat 结构的指针

DWORD dwCallback 回调函数地址或窗口句柄

DWORD dwInstance 给回调函数的实例数据、

DWORD fdwOpen 打开选项

 

       if(waveInOpen (&m_hWaveIn,WAVE_MAPPER,&m_waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) {// 打开波形输入设备

              free(m_pBuffer1);

              free(m_pBuffer2);

              MessageBeep(MB_ICONEXCLAMATION);

              AfxMessageBox((CString)"Audio can not be open!");

       }

 

// WAVEHDR 结构体,结构包含了音频数据缓冲的地址,大小,已录音数据大小等信息和其他各种控制标志

       m_pWaveHdr1->lpData=(LPSTR)m_pBuffer1;// 指定缓冲的地址

       m_pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE;// 指定缓冲的大小 ;

       m_pWaveHdr1->dwBytesRecorded=0;// 若 TWaveHdr 用于输入 , 指出缓冲区中的数据量

       m_pWaveHdr1->dwUser=0;// 指定用户的 32 位数据

       m_pWaveHdr1->dwFlags=0;// 缓冲区标志

       m_pWaveHdr1->dwLoops=1;// 循环播放次数 , 仅用于输出缓冲区

       m_pWaveHdr1->lpNext=NULL;// 保留

       m_pWaveHdr1->reserved=0;// 保留

       waveInPrepareHeader (m_hWaveIn,m_pWaveHdr1,sizeof(WAVEHDR));// 为录音设备准备缓存

 

       m_pWaveHdr2->lpData=(LPSTR)m_pBuffer2;

       m_pWaveHdr2->dwBufferLength=INP_BUFFER_SIZE;

       m_pWaveHdr2->dwBytesRecorded=0;

       m_pWaveHdr2->dwUser=0;

       m_pWaveHdr2->dwFlags=0;

       m_pWaveHdr2->dwLoops=1;

       m_pWaveHdr2->lpNext=NULL;

       m_pWaveHdr2->reserved=0;

       waveInPrepareHeader (m_hWaveIn,m_pWaveHdr2,sizeof(WAVEHDR));

      

              m_pSaveBuffer = (PBYTE)realloc (m_pSaveBuffer, 1) ;

 

       // Add the buffers

       waveInAddBuffer (m_hWaveIn, m_pWaveHdr1, sizeof (WAVEHDR)) ;// 为输入设备增加缓存

       waveInAddBuffer (m_hWaveIn, m_pWaveHdr2, sizeof (WAVEHDR)) ;

      

       // Begin sampling

      

       m_bRecording = TRUE ;

       m_bEnding = FALSE ;

       m_dwDataLength = 0 ;

       waveInStart (m_hWaveIn) ;// 启动录音

}

2 、停止录音

void CRecorderDlg::OnRecStop()

{

       // TODO: Add your control notification handler code here

       m_bEnding=TRUE;

       waveInReset (m_hWaveIn);// 停止录音

       waveInClose (m_hWaveIn);// 关闭录音设备

}

3 、开始播放

void CRecorderDlg::OnPlayStart()

{

       // TODO: Add your control notification handler code here

              if (m_bPlaying)

       {

              waveOutReset(m_hWaveOut);

       }

// WAVEFORMATEX 结构体             

       //open waveform audio for output

       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;

 

       if(waveOutOpen (&m_hWaveOut,WAVE_MAPPER,&m_waveform,(DWORD)this->m_hWnd,NULL,CALLBACK_WINDOW)) {// 打开输出设备

              MessageBeep(MB_ICONEXCLAMATION);

              AfxMessageBox((CString)"Audio output error");

              return;

       }

 

       m_bEnding = FALSE ;

       m_bPlaying=TRUE;

}

4 、停止播放

void CRecorderDlg::OnPlayStop()

{

       // TODO: Add your control notification handler code here

       m_bPlaying=FALSE;

       waveOutReset (m_hWaveOut);// 停止输出

       waveOutClose (m_hWaveOut);// 关闭输出设备

}

5 、消息函数

       ON_MESSAGE(MM_WIM_DATA,OnMM_WIM_DATA)

       ON_MESSAGE(MM_WIM_CLOSE,OnMM_WIM_CLOSE)

       ON_MESSAGE(MM_WOM_OPEN,OnMM_WOM_OPEN)

       ON_MESSAGE(MM_WOM_CLOSE,OnMM_WOM_CLOSE)

       ON_MESSAGE(MM_WOM_DONE,OnMM_WOM_DONE)

 

// 缓冲录满或停止录音消息

void CRecorderDlg::OnMM_WIM_DATA (UINT wParam, LONG lParam)

{

       // TODO: Add your message handler code here and/or call default

       // Reallocate save buffer memory

       MessageBeep(MB_OK);

             

       m_pNewBuffer = (PBYTE)realloc (m_pSaveBuffer, m_dwDataLength +

              ((PWAVEHDR) lParam)->dwBytesRecorded) ;

 

 

       if (m_pNewBuffer == NULL)

       {

              waveInClose (m_hWaveIn) ;

              MessageBeep (MB_ICONEXCLAMATION) ;

              AfxMessageBox((CString)"error memory");

              return ;

       }

 

      

       m_pSaveBuffer = m_pNewBuffer ;

             

       CopyMemory (m_pSaveBuffer + m_dwDataLength, ((PWAVEHDR) lParam)->lpData,

              ((PWAVEHDR) lParam)->dwBytesRecorded) ;

      

       m_dwDataLength += ((PWAVEHDR) lParam)->dwBytesRecorded ;

      

       if (m_bEnding)

       {

              waveInClose (m_hWaveIn) ;

              return ;

       }

 

      

       // Send out a new buffer

      

       waveInAddBuffer (m_hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;// 向波形输入设备添加一个输入缓冲区

       return ;

}

// 音频输入设备关闭消息

void CRecorderDlg::OnMM_WIM_CLOSE (UINT wParam, LONG lParam)

{

       // TODO: Add your message handler code here and/or call default

 

       if (0==m_dwDataLength) {

              return;

       }

              waveInUnprepareHeader (m_hWaveIn, m_pWaveHdr1, sizeof (WAVEHDR)) ;// 清除输出缓存

       waveInUnprepareHeader (m_hWaveIn, m_pWaveHdr2, sizeof (WAVEHDR)) ;

      

       free (m_pBuffer1) ;

       free (m_pBuffer2) ;

      

       if (m_dwDataLength > 0)

       {

              //enable play

 

       }

       m_bRecording = FALSE ;

 

}

 

// 音频输出 设备打开消息

void CRecorderDlg::OnMM_WOM_OPEN (UINT wParam, LONG lParam)

{

 

       AfxMessageBox((CString)"OnMM_WOM_OPEN called!");

       m_pWaveHdr1->lpData          = (LPSTR)m_pSaveBuffer ;

       m_pWaveHdr1->dwBufferLength  = m_dwDataLength ;

       m_pWaveHdr1->dwBytesRecorded = 0 ;

       m_pWaveHdr1->dwUser          = 0 ;

       m_pWaveHdr1->dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP ;

       m_pWaveHdr1->dwLoops         = m_dwRepetitions ;

       m_pWaveHdr1->lpNext          = NULL ;

       m_pWaveHdr1->reserved        = 0 ;

 

       // Prepare and write

      

       waveOutPrepareHeader (m_hWaveOut, m_pWaveHdr1, sizeof (WAVEHDR)) ;// 为输出设备准备缓存

       waveOutWrite (m_hWaveOut, m_pWaveHdr1, sizeof (WAVEHDR)) ;// 写数据导输出设备缓存

      

}

// 音频输出设备关闭消息

void CRecorderDlg::OnMM_WOM_CLOSE (UINT wParam, LONG lParam)

{

       AfxMessageBox((CString)"OnMM_WOM_CLOSE called!");

}

 

// 缓冲播放完或停止输出消息

void CRecorderDlg::OnMM_WOM_DONE (UINT wParam, LONG lParam)

{

       AfxMessageBox((CString)"OnMM_WOM_DONE called!");

 

 

}

五、音频 API

waveInGetNumDevs 返回系统中存在的波形输入设备的数量

  waveInAddBuffer 向波形输入设备添加一个输入缓冲区

waveInGetDevCaps 查询指定的波形输入设备以确定其性能

  waveInGetErrorText 检取由指定的错误代码标识的文本说明

waveInGetID 获取指定的波形输入设备的标识符

  waveInGetPosition 检取指定波形输入设备的当前位置

waveInMessage 发送一条消息给波形输入设备的驱动器

waveInOpen 为录音而打开一个波形输入设备

waveInPrepareHeader 为波形输入准备一个输入缓冲区

waveInStart 启动在指定的波形输入设备的输入

waveInReset 停止给定的波形输入设备的输入,且将当前位置清零

  waveInStop 停止在指定的波形输入设备上的输入

waveInUnprepareHeader 清除由 waveInPrepareHeader 函数实现的准备

  WaveInClose 关闭指定的波形输入设置

waveOutBreakLoop 中断给定的波形输出设备上一个循环,并允许播放驱动取列表中的下一个块

waveOutClose 关闭指定的波形输出设备

waveOutGetDevCaps 查询一个指定的波形输出设备以确定其性能 waveOutGetErrorText 检取由指定的错误代码标识的文本说明

waveOutGetID 检取指定的波形输出设备的标识符

waveOutGetNumDevs 检取系统中存在的波形输出设备的数量

waveOutGetPitch 查询一个波形输出设备的当前音调设置

waveOutGetPlaybackRate 查询一个波形输出设备当前播放的速度

waveOutGetPosition 检取指定波形输出设备的当前播放位置

waveOutGetVolume 查询指定波形输出设备的当前音量设置

  waveOutMessage 发送一条消息给一个波形输出设备的驱动器

waveOutOpen 为播放打开一个波形输出设备

  waveOutPause 暂停指定波形输出设备上的播放

waveOutPrepareHeader 为播放准备一个波形缓冲区

waveOutRestart 重新启动一个被暂停的波形输出设备

waveOutSetPitch 设置一个波形输出设备的音调

waveOutSetPlaybackRate 设置指定波形输出设备的速度

waveOutSetVolume 设置指定的波形输出设备的音量

waveOutUnprepareHeader 清除由 waveOutPrepareHeader 函 数实现的准备

waveOutWrite 向指定的波形输出设备发送一个数据块

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值