Windows C++ 使用Core-audio捕获本地扬声器设备或者麦克风设备(提供源码)

捕获本地扬声器设备/麦克风的pcm数据,方案还是很多的,而且也比较简单,这个就直接上代码,有不懂的可以私信,相互交流

#include <mmdeviceapi.h>
#include <Audioclient.h>
#include <stdio.h>
#include <mmsystem.h>

int main(int argc, char* argv[])
{
    IMMDeviceEnumerator *pMMDeviceEnumerator = NULL;
    IAudioCaptureClient *pAudioCaptureClient = NULL;
    IAudioClient *pAudioClient = NULL;
    WAVEFORMATEX *pwfx = NULL;
    IMMDevice* pDevice = NULL;
    BYTE *pData(NULL);
    DWORD dwFlags(0);

    FILE *fp = fopen("test.pcm", "wb+");
    if (!fp)
        return -1;

    //使用COM库,必须调用CoInitialize/CoInitializeEx
    CoInitialize(NULL);
    //获取枚举音频设备的对象
    HRESULT hr = CoCreateInstance(
        __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL,
        __uuidof(IMMDeviceEnumerator),
        (void**)&pMMDeviceEnumerator);
    if (FAILED(hr)) return -1;
    //获取默认的扬声器设备 eRender:播放设备  eCapture:麦克风设备

     //hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);
    hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
    pMMDeviceEnumerator->Release();
    if (FAILED(hr)) return -1;

    do
    {
        //获取IAudioClient对象,用来获取音频数据格式等
        hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient);
        if (FAILED(hr)) break;
        //获取该音频设备的默认混音格式,当然大多数人会去尝试一下48K-2通道-16位能否获取,这边略过了,直接获取默认的格式
        hr = pAudioClient->GetMixFormat(&pwfx);
        if (FAILED(hr)) break;

        printf("WAVEFORMATEX {%dHz %d channels %d bit}\r\n", pwfx->nSamplesPerSec, pwfx->nChannels, pwfx->wBitsPerSample);

        //设置缓存长度为10ms数据

        //这个写法是获取扬声器设备的数据
        hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK, 10*1000, 0, pwfx, NULL);

//这个写法是获取麦克风设备的数据

         //hr= pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK| AUDCLNT_STREAMFLAGS_NOPERSIST,10*1000,pwfx,NULL);

        if (FAILED(hr)) break;
        //获取捕获对象
        hr = pAudioClient->GetService(__uuidof(IAudioCaptureClient), (void**)&pAudioCaptureClient);
        if (FAILED(hr)) break;
        //开始捕获
        hr = pAudioClient->Start();
        if (FAILED(hr)) break;

        UINT32 nNextPacketSize = 0;
        UINT32 nNumFramesToRead = 0;
        int nFrameSize = (pwfx->wBitsPerSample / 8) * pwfx->nChannels;//一帧的数据大小
        while (true)
        {
            //获取是否有包数据到来
            hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize);
            if (FAILED(hr))
            {
                Sleep(1);
                continue;
            }
            //可获取的包数据=0,继续循环等待,这边其实可以事件等待的
            if (nNextPacketSize == 0)
            {
                Sleep(1);
                continue;
            }
            //获取pcm数据
            dwFlags = 0;
            hr = pAudioCaptureClient->GetBuffer(
                &pData,
                &nNumFramesToRead,
                &dwFlags,
                NULL,
                NULL
            );
            if (FAILED(hr))
            {
                break;
            }
            //判断是否是静音包
            if (dwFlags & AUDCLNT_BUFFERFLAGS_SILENT)
                printf("Get AUDCLNT_BUFFERFLAGS_SILENT\r\n");

            //获取到音频数据大小
            if (nNumFramesToRead > 0)
            {
                if (fp)
                {
                    fwrite(pData,1, nFrameSize * nNumFramesToRead,fp);
                }
                pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
            }
        }
    } while (true);
    //释放各资源
    fclose(fp);
    if (pAudioCaptureClient != NULL)
    {
        pAudioCaptureClient->Release();
        pAudioCaptureClient = NULL;
    }

    if (pwfx != NULL)
    {
        CoTaskMemFree(pwfx);
        pwfx = NULL;
    }

    if (pAudioClient != NULL)
    {
        pAudioClient->Stop();
        pAudioClient->Release();
        pAudioClient = NULL;
    }

    if (pDevice)
    {
        pDevice->Release();
        pDevice = NULL;
    }
    return 0;
}
 

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在C++中拦截扬声器的输出音频二进制流,可以使用操作系统提供的音频API,例如在Windows操作系统中,可以使用MMSystem库中的waveInOpen()函数打开音频输入设备,然后使用waveInAddBuffer()函数将音频数据缓冲区添加到输入缓冲队列中,最后使用waveInStart()函数开始音频输入捕获。以下是一个简单的示例代码: ```c++ #include <iostream> #include <Windows.h> #include <Mmsystem.h> #pragma comment(lib, "Winmm.lib") #define BUF_SIZE 4096 void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2); int main() { // 打开音频输入设备 HWAVEIN hWaveIn = NULL; WAVEFORMATEX wfx = { 0 }; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 44100; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; MMRESULT mmr = waveInOpen(&hWaveIn, WAVE_MAPPER, &wfx, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInOpen failed with error code " << mmr << std::endl; return 1; } // 创建音频输入缓冲区 char* pBuf = new char[BUF_SIZE]; WAVEHDR* pWaveHdr = new WAVEHDR; pWaveHdr->lpData = pBuf; pWaveHdr->dwBufferLength = BUF_SIZE; pWaveHdr->dwBytesRecorded = 0; pWaveHdr->dwUser = 0; pWaveHdr->dwFlags = 0; pWaveHdr->dwLoops = 0; mmr = waveInPrepareHeader(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInPrepareHeader failed with error code " << mmr << std::endl; return 1; } // 添加音频输入缓冲区到输入缓冲队列中 mmr = waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInAddBuffer failed with error code " << mmr << std::endl; return 1; } // 开始音频输入捕获 mmr = waveInStart(hWaveIn); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInStart failed with error code " << mmr << std::endl; return 1; } // 等待音频输入完成 Sleep(5000); // 停止音频输入捕获 mmr = waveInStop(hWaveIn); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInStop failed with error code " << mmr << std::endl; return 1; } // 关闭音频输入设备 mmr = waveInClose(hWaveIn); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInClose failed with error code " << mmr << std::endl; return 1; } // 释放音频输入缓冲区 delete[] pBuf; delete pWaveHdr; return 0; } // 音频输入回调函数 void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { if (uMsg == WIM_DATA) { WAVEHDR* pWaveHdr = (WAVEHDR*)dwParam1; char* pData = pWaveHdr->lpData; DWORD dwDataSize = pWaveHdr->dwBytesRecorded; // 在这里可以对音频数据进行处理,例如输出到文件或网络等 // ... // 重新添加音频输入缓冲区到输入缓冲队列中 MMRESULT mmr = waveInAddBuffer(hwi, pWaveHdr, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { std::cerr << "waveInAddBuffer failed with error code " << mmr << std::endl; } } } ``` 在这个示例代码中,我们使用了waveInOpen()函数打开了音频输入设备(默认为麦克风),然后使用了waveInAddBuffer()函数将音频数据缓冲区添加到输入缓冲队列中,并使用了waveInStart()函数开始音频输入捕获。在音频输入回调函数waveInProc()中,我们可以对音频数据进行处理(例如输出到文件或网络等),然后使用waveInAddBuffer()函数重新添加音频输入缓冲区到输入缓冲队列中,以继续捕获音频数据。最后,我们使用waveInStop()函数停止音频输入捕获,然后使用waveInClose()函数关闭音频输入设备,并释放音频输入缓冲区。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值