在 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 打开选项
waveInOpen 打开波形输入设备
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_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_pSaveBuffer = (PBYTE)realloc (m_pSaveBuffer, 1) ;
// Add the buffers
waveInAddBuffer 为输入设备增加缓存
waveInAddBuffer
// Begin sampling
m_bRecording = TRUE ;
m_bEnding = FALSE ;
m_dwDataLength = 0 ;
waveInStart 启动录音
}
2 、停止录音
void CRecorderDlg::OnRecStop()
{
// TODO: Add your control notification handler code here
m_bEnding=TRUE;
waveInReset 停止录音
waveInClose 关闭录音设备
}
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;
waveOutOpen 打开输出设备
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 停止输出
waveOutClose 关闭输出设备
}
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
{
// 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
{
// 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
{
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
{
AfxMessageBox((CString)"OnMM_WOM_CLOSE called!");
}
// 缓冲播放完或停止输出消息
void CRecorderDlg::OnMM_WOM_DONE
{
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 向指定的波形输出设备发送一个数据块
Android audiorecord蓝牙录音 蓝牙设备录音
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
OpenHarmony 4.1 蓝牙组件说明
Open Harmony4.1 蓝牙组件框架层和服务层介绍
2d 系统框架 蓝牙协议