windows录音教程
来源:互联网 发布:js实现word预览 编辑:程序博客网 时间:2024/06/07 02:28
一、录音的基本流程:
这个流程图可能不太准确,具体的看下面的分析吧
二、具体步骤
1.使用waveInOpen()函数打开一个音频设备:
HWAVEIN hWavein;WAVEFORMATEX waveFormat; //音频格式waveFormat.wFormatTag = WAVE_FORMAT_PCM;waveFormat.nChannels = 1; //单声道waveFormat.nSamplesPerSec = SAMPLESPERSEC; //采样率waveFormat.nAvgBytesPerSec = SAMPLESPERSEC * 2;waveFormat.nBlockAlign = 2; //最小的块大小waveFormat.wBitsPerSample = BITSPERSAMPLE; //采样精度DWORD nThreadID;HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)waveInProc, NULL, 0, &nThreadID);if (hThread == INVALID_HANDLE_VALUE){printf("创建线程失败!\n");longjmp(jmpBuf, GetLastError());}MMRESULT ret = waveInOpen(&hWavein, 0, &waveFormat, nThreadID, 0, CALLBACK_THREAD); //这里我们采用线程回调的方式
我们需要在waveInOpen()函数的第二个参数中指定设备的ID,这里我们给了0表示打开系统中第一个麦克风
2.使用waveInPrepareHeader()和waveInAddBuffer()添加缓冲区:
for (int i = 0; i < 4; ++i) //这里我们初始化4块缓冲区{WAVEHDR* pWaveHdr = malloc(sizeof(WAVEHDR));RtlZeroMemory(pWaveHdr, sizeof(WAVEHDR));pWaveHdr->lpData = malloc(DATASIZE);pWaveHdr->dwBufferLength = DATASIZE;pWaveHdr->dwFlags = 0;ret = waveInPrepareHeader(hWavein, pWaveHdr, sizeof(WAVEHDR));if (ret != MMSYSERR_NOERROR){printf("准备缓冲区失败!\n");longjmp(jmpBuf, GetLastError());}ret = waveInAddBuffer(hWavein, pWaveHdr, sizeof(WAVEHDR));if (ret != MMSYSERR_NOERROR){printf("加入缓冲区失败!\n");longjmp(jmpBuf, GetLastError());}}
建议在这里至少添加4块缓冲区,注意结构体WAVEHDR中有三个参数是需要我们进行初始化的,lpData表示存放音频块的大小,这里我们给的是6400个字节,dwBufferLength表示lpData的大小,dwFlags给0即可,之后即可将该结构体添加进去。注意:这里的结构体需要在堆上申请内存,不要在这里使用局部变量。
3.使用waveInStart()
waveInStart()之后,程序就开始录音了,当一块音频区满后,会产生MM_WIM_DATA消息(如果你在waveInOpen那里使用的是回调函数,这个消息是WIM_DATA),在这个消息中我们将音频块的内容取出,并重新将这个音频块加入到设备中。
case MM_WIM_DATA: //缓冲区录满的消息,在这里取数据,并重新添加缓冲区hWavein = (HWAVEIN)msg.wParam;pWavehdr = (WAVEHDR*)msg.lParam;int nWrite = fwrite(pWavehdr->lpData, 1,pWavehdr->dwBytesRecorded, g_pFile);printf("dwBytesRecorded:%d, dwBufferLength: %d\n", pWavehdr->dwBytesRecorded, pWavehdr->dwBufferLength);if (g_bWaveStatus){ret = waveInAddBuffer(hWavein, pWavehdr, sizeof(WAVEHDR));if (ret != MMSYSERR_NOERROR){printf("再次加入缓冲区失败!\n");longjmp(callBackJmp, GetLastError());}}
这样我们就可以源源不断的一直在录音了,那么如何结束录音并释放缓冲区昵,下面开始进行结束录音:
4.使用waveInStop()、waveInReset()和waveInUnprepareHeader()
先使用waveInStop(),它会立即停止录音,停止录音的同时,肯定有一块缓冲区正在被使用,它不管这块缓冲区有没有满,直接将这块缓冲区发送给相应的接收程序(就是我们可以在MM_WIM_DATA中收到这块缓冲区),那么我们如何知道这块缓冲区到底被使用了多少昵?在WAVEHDR结构体中,有一个dwBytesRecorded变量会指示这块缓冲区被使用了多少,一般这个值是等于dwBufferLength的,但是当我们使用waveInStop()后,我们可以通过dwBytesRecorded了解缓冲区被使用的大小,所以我们应该尽量以dwBytesRecorded为准。之后我们就可以使用waveInUnprepareHeader()来释放掉这块缓冲区,也不要在把这块缓冲区加入进去了。
这样我们就释放掉一块缓冲区了,但是我们在开始的时候一共申请了4块缓冲区,还有3块怎么办昵?
这时我们需要使用waveInReset()将其他没有被使用的缓冲区直接发送给接收程序(就是我们可以在MM_WIM_DATA中收到这些缓冲区),之后在调用waveInUnprepareHeader()。
下面这张图充分的说明了这一切:
5.使用waveInClose()结束一切。
0 0
- windows录音教程
- 基于red5录音教程
- windows录音程序原理
- windows录音程序原理
- windows录音程序原理
- windows录音程序原理
- windows录音程序原理
- iOS录音的伪教程
- windows phone开发学习--录音
- windows phone开发学习--录音
- windows录音程序简单解析
- VoiceNotes录音软件简明使用教程
- Android设备功能之录音教程篇
- 录音
- 录音
- 录音
- 录音
- 录音
- MVC框架自己封装开启超神之路(上) 3-1配置加载类
- Android学习之路--四大组件--Service
- Spring ConcurrentReferenceHashMap简单测试
- 数据结构::线索化二叉树
- Spring MVC 跳转(1)-转发
- windows录音教程
- 30、(知识篇)SpringMVC07 Spring 自定义视图
- Hadoop之MapReduce
- C、C++不定参数的使用
- docker安装教程
- redis的五种数据类型---hash类型
- 面试小技巧
- DM9000 驱动移植
- 指令周期、机器周期、’时钟周期