- 首先包含头文件以及库目录
#include <mmsystem.h> #pragma comment(lib, "winmm.lib")
- 初始化录音所需变量
WAVEHDR wHdr1[4]; // 采集音频时包括数据缓存的结构体 HWAVEIN hWaveIn; // 输入设备句柄 hWaveIn = NULL; // 录音设备句柄初始化
- 设置音频采集所需参数,具体包括声音格式、采样率、声道等
// *************** 录音参数设置 ******************** WAVEFORMATEX waveform; // 采集音频的格式,结构体 waveform.wFormatTag = WAVE_FORMAT_PCM; // 声音格式为PCM waveform.nSamplesPerSec = 16000; // 采样率,16000 waveform.wBitsPerSample = 16; // 采样比特(即采样深度),16bits waveform.nChannels = 1; // 采样声道数,2声道 waveform.nAvgBytesPerSec = 32000; // 每秒的数据率,就是每秒能采集多少字节的数据 waveform.nBlockAlign = 2; // 一个块的大小,采样bit的字节数*声道数 waveform.cbSize = 0; // 一般为0
- 打开音频采集设备
//使用waveInOpen函数开启音频采集 waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD_PTR)AudioRecodeProc, (DWORD_PTR)this, CALLBACK_FUNCTION); /* MMRESULT waveInOpen( LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwCallbackInstance, DWORD fdwOpen ); 参数phwi :指向一个句柄,作为其他函数的调用参数 参数uDeviceID:录音设备ID号,用来辨别已经打开的录音设备 参数pwfx:音频采集格式结构体 参数dwCallback:回调函数或者线程函数等 参数dwCallbackInstance:传入回调函数的参数 参数fdwOpen:决定dwCallback回调函数的类型,主要类型如下 Value Meaning CALLBACK_EVENT The dwCallback parameter is an event handle. CALLBACK_FUNCTION The dwCallback parameter is a callback procedure address. CALLBACK_NULL No callback mechanism. This is the default setting. CALLBACK_THREAD The dwCallback parameter is a thread identifier. CALLBACK_WINDOW The dwCallback parameter is a window handle. */
- 建立音频缓存并初始化
//建立两个数组(这里能够建立多个数组)用来缓冲音频数据, //这里每次开辟SAMPLENUMS Byte的缓存存储录音数据 for (int i = 0; i<4; i++) { wHdr1[i].lpData = new char[SAMPLENUMS]; wHdr1[i].dwBufferLength = SAMPLENUMS; wHdr1[i].dwBytesRecorded = 0; wHdr1[i].dwUser = NULL; wHdr1[i].dwFlags = 0; wHdr1[i].dwLoops = 1; wHdr1[i].lpNext = NULL; wHdr1[i].reserved = 0; //为录音设备准备缓存函数(为音频输入设备准备一个缓冲区): //MMRESULT waveInPrepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT bwh ); waveInPrepareHeader(hWaveIn, &wHdr1[i], sizeof(WAVEHDR)); //给输入设备增加一个缓存(将缓冲区发送给设备,若缓冲区填满,则不起作用): //MMRESULT waveInAddBuffer( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh ); waveInAddBuffer(hWaveIn, &wHdr1[i], sizeof(WAVEHDR)); } /* MMRESULT waveInPrepareHeader( HWAVEIN hwi, //音频输入设备句柄 LPWAVEHDR pwh, //指向WAVEHDR结构的指针,标识准备的缓冲区 UINT cbwh //WAVEHDR结构的大小,使用sizeof即可 ); typedef struct wavehdr_tag { LPSTR lpData; //指向波形格式的缓冲区 DWORD dwBufferLength; //缓冲区的大小 DWORD dwBytesRecorded;//当前存储了多少数据 DWORD_PTR dwUser; //用户数据 DWORD dwFlags; //为缓冲区提供的信息,在waveInPrepareHeader函数中使用WHDR_PREPARED DWORD dwLoops; //输出时使用,标识播放次数 struct wavehdr_tag * lpNext;//reserved DWORD_PTR reserved; //reserved } WAVEHDR, *LPWAVEHDR; */
- 开始录音
waveInStart(hWaveIn); //开始录音
- 关闭录音
//关闭录音设备函数: waveInClose(hWaveIn);
- 最重要的函数是回调函数,即waveInOpen()函数中注册的回调函数,从中可接收到采集到的音频数据并进行音频处理
void CALLBACK CAudioTestDomeDlg::AudioRecodeProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { LPWAVEHDR pwh = (LPWAVEHDR)dwParam1; CAudioTestDomeDlg* pObj = (CAudioTestDomeDlg*)dwInstance; short buffer[SAMPLENUMS]; if (pObj->m_bIsRun_Recode && WIM_DATA == uMsg) { memcpy(buffer, pwh->lpData, SAMPLES_BYTES); // 录制按钮对应处理 if (pObj->m_nRecode && pObj->pfRecodePC) { int write_length = 0; write_length = fwrite(buffer, 1, SAMPLES_BYTES, pObj->pfRecodePC); // 写入原始音频数据 } // 波形显示按钮对应处理 if (pObj->m_nShowWave || pObj->m_nPlay) { memcpy(pObj->m_nzValues, buffer, SAMPLES_BYTES); } // 波形显示按钮对应处理 if (pObj->m_nShowWave) { // 获取绘图控件的客户区坐标 // (客户区坐标以窗口的左上角为原点,这区别于以屏幕左上角为原点的屏幕坐标) pObj->m_picDraw.GetClientRect(&pObj->rectPicture); CDC *pDC = pObj->m_picDraw.GetDC(); // 绘制波形图 if (!pDC) return; pObj->DrawWave(pDC, pObj->rectPicture); pObj->m_picDraw.ReleaseDC(pDC); } // 播放按钮对应处理 if (pObj->m_nPlay) { LPVOID buf = NULL; DWORD buf_len11 = 0; static DWORD offset = BUFFERNOTIFYSIZE; pObj->m_pDSBuffer8->Lock(offset, BUFFERNOTIFYSIZE, &buf, &buf_len11, NULL, NULL, 0); // 如果是实时音频播放,那么下面的数据就可以把内存中buf_len大小的数据复制到buf指向的地址即可 memcpy(buf, pObj->m_nzValues, buf_len11); offset += buf_len11; offset %= (BUFFERNOTIFYSIZE * MAX_AUDIO_BUF); pObj->m_pDSBuffer8->Unlock(buf, buf_len11, NULL, 0); } waveInAddBuffer(hwi, pwh, sizeof(WAVEHDR)); //给输入设备增加一个缓存 } else Sleep(10); }
至此,完整的windows下使用winmm.lib库采集音频数据的过程就结束了。
使用winmm.lib库对windows录音设备采集录音数据
猜你喜欢
转载自blog.csdn.net/lifei092/article/details/81355384
今日推荐
周排行