2.2 用window API捕获麦克风数据并加入队列备用

33 篇文章 3 订阅
31 篇文章 4 订阅

本课对应源文件下载链接:

https://download.csdn.net/download/XiBuQiuChong/88802175

 今天是2024年1月1日,新年的第一缕阳光已经普照大地,祝愿看到这篇文章的所有程序员或程序爱好者都能在新的一年里持之以恒,事业有成。

今天也是我加入CSDN的第4100天,但回过头看一看,这么长的时间也没有在CSDN写下几篇文章,真是一种遗憾。为了弥补这个遗憾,我会继续坚持把这套教程写完。目前的教程总体而言写的还比较粗略,很多细节没有展开写,后面找时间再继续优化,现在主要是梳理一下整体思路,先搞个框架出来。

一、最终实现的效果

本课实现的效果与上节课类似,只不过增加了麦克风数据的捕获,源文件的下载地址与上节课也是共用的。

二、使用Windows API捕获麦克风数据的原理

1.捕获麦克风数据入队列备用

要捕获麦克风数据,就要先打开麦克风,打开麦克风的方法与《第3课 使用FFmpeg获取并播放音频流》中打开扬声器的方法差不多,只不过一个是打开输出设备,一个是打开输入设备。打开麦克风后同样通过回调函数获取到pcm原始数据,有了原始数据就可以进行后续的编码操作了。

三、捕获麦克风数据的具体实现

//打开麦克风

void fmle::openMic(){

int nIndex = 0;

inWaveform.wFormatTag = WAVE_FORMAT_PCM;

inWaveform.nSamplesPerSec = 44100;

inWaveform.wBitsPerSample = 16;

inWaveform.nChannels = 2;

inWaveform.nBlockAlign = (inWaveform.wBitsPerSample * inWaveform.nChannels) / 8;

inWaveform.nAvgBytesPerSec = inWaveform.nBlockAlign * inWaveform.nSamplesPerSec;

inWaveform.cbSize = 0;

waveInOpen(&hWaveIn, nIndex, &inWaveform, (DWORD)micCallback, 0L, CALLBACK_FUNCTION);

waveHdrArr = new WAVEHDR[audioDataArrNum];

for (int i = 0; i < audioDataArrNum; i++)

{

          waveHdrArr[i].lpData = new char[audioDataSize];

          waveHdrArr[i].dwBufferLength = audioDataSize;

          waveHdrArr[i].dwBytesRecorded = 0;

          waveHdrArr[i].dwUser = NULL;

          waveHdrArr[i].dwFlags = 0;

          waveHdrArr[i].dwLoops = 1;

          waveHdrArr[i].lpNext = NULL;

          waveHdrArr[i].reserved = 0;

          waveInPrepareHeader(hWaveIn, &waveHdrArr[i], sizeof(WAVEHDR));

          waveInAddBuffer(hWaveIn, &waveHdrArr[i], sizeof(WAVEHDR));

}

waveInStart(hWaveIn);

}



DWORD CALLBACK fmle::micCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)

{



switch (uMsg)

{

case WIM_OPEN:

          TRACE("WIM_OPEN\n");

         break;



case WIM_DATA:





{

                                     //TRACE("WIM_DATA\n");

                                     LPWAVEHDR pwh = (LPWAVEHDR)dwParam1;

                                     if (pwh->dwBytesRecorded > 0){

                                              EnterCriticalSection(&pThis->queLock);

                                              pThis->tmpAudioQueObj.type = 0;

                                              pThis->tmpAudioQueObj.dataArr = pwh->lpData;

                                              pThis->tmpAudioQueObj.dataLen = pwh->dwBytesRecorded;

                                              pThis->inAudioQue.push(pThis->tmpAudioQueObj);

                                              if (pThis->inAudioQue.size() > pThis->audioDataArrNum){

                                                       pThis->inAudioQue.front().dataLen = 0;

                                                       pThis->inAudioQue.front().dataArr = NULL;

                                                       pThis->inAudioQue.front().dataLen = NULL;

                                                       delete[]pThis->inAudioQue.front().dataArr;

                                                       pThis->inAudioQue.pop();

                                              }

                                              LeaveCriticalSection(&pThis->queLock);

                                     }

                                     waveInAddBuffer(pThis->hWaveIn, pwh, sizeof(WAVEHDR));

                                     TRACE("pThis->inAudioQue.size():%d\n", pThis->inAudioQue.size());

}



          break;



case WIM_CLOSE:

          TRACE("WIM_CLOSE\n");

          waveInStop(pThis->hWaveIn);

          waveInReset(pThis->hWaveIn);

          waveInClose(pThis->hWaveIn);

          break;

default:

          break;

}

return 0;

}

四、将麦克风数据存成文件检测是否正常

上述方法虽然可以将麦克风数据存入队列备用,但我们如何知道它是否正确捕获了呢?我们可以把捕获的pcm数据先存入文件:

FILE *pcmFile;

fopen_s(&pcmFile, "rec.pcm", "wb");

fwrite(pwh->lpData, 1, pwh->dwBytesRecorded, pcmFile);

想一想,上述代码应该分别加在什么地方呢?

录制pcm文件后可以使用Audacity来导入pcm文件测试录制数据是否正确。

  • 31
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西部秋虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值