使用Core Audio實現對聲卡輸出的捕捉

https://www.cnblogs.com/poissonnotes/p/7479570.html

涉及的接口有:

  • IMMDeviceEnumerator
  • IMMDevice
  • IAudioClient
  • IAudioCaptureClient

主要過程:

  • 創建多媒體設備枚舉器(IMMDeviceEnumerator)
  • 通過多媒體設備枚舉器獲取聲卡接口(IMMDevice)
  • 通過聲卡接口獲取聲卡客戶端接口(IAudioClient)
  • 通過聲卡客戶端接口(IAudioClient)可獲取聲卡輸出的音頻參數、初始化聲卡、獲取聲卡輸出緩衝區的大小、開啓/停止對聲卡輸出的採集
  • 通過聲卡採集客戶端接口(IAudioCaptureClient)可獲取採集的聲卡輸出數據,並對內部緩衝區進行控制
  • 通過聲卡輸出客戶端接口(IAudioRenderClient)可將採集的聲音數據寫入聲音輸出設備的緩存單元,輸出設備可以通過IAudioClient::GetService函數獲取 IAudioRenderClient 接口。

     

代碼示例:

   

//首先枚舉你的音頻設備,你可以在這個時候獲取到你機器上所有可用的設備,並指定你需要用到的那個設備

hr = CoCreateInstance(

                    CLSID_MMDeviceEnumerator, NULL,
                    CLSCTX_ALL, IID_IMMDeviceEnumerator,
                    (void**)&pEnumerator);

EXIT_ON_ERROR(hr)

   

hr = pEnumerator->GetDefaultAudioEndpoint(

                    eCapture, eConsole, &pDevice);

EXIT_ON_ERROR(hr)

   

   

//創建一個管理對象,通過它可以獲取到你需要的一切數據
hr = pDevice->Activate(
                    IID_IAudioClient, CLSCTX_ALL,
                    NULL, (void**)&pAudioClient);
EXIT_ON_ERROR(hr)

   

hr = pAudioClient->GetMixFormat(&pwfx);
EXIT_ON_ERROR(hr)

   

//初始化管理對象,在這裏,你可以指定它的最大緩衝區長度,這個很重要,應用程序控制數據塊的大小以及延時長短都靠這裏的初始化,具體參數大家看看文檔解釋
hr = pAudioClient->Initialize(
                         AUDCLNT_SHAREMODE_SHARED,
                         0,
                         hnsRequestedDuration,
                         0,
                         pwfx,
                         NULL);
EXIT_ON_ERROR(hr)

   

//這個buffersize,指的是緩衝區最多可以存放多少幀的數據量
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr)

 

//創建採集管理接口,這個接口很簡單,沒什麼重要的東西
hr = pAudioClient->GetService(
                         IID_IAudioCaptureClient,
                         (void**)&pCaptureClient);
EXIT_ON_ERROR(hr)

 

// Notify the audio sink which format to use.
hr = pMySink->SetFormat(pwfx);
EXIT_ON_ERROR(hr)

   

// Calculate the actual duration of the allocated buffer.
hnsActualDuration = (double)REFTIMES_PER_SEC *
                     bufferFrameCount / pwfx->nSamplesPerSec;

   

hr = pAudioClient->Start();  // Start recording.

EXIT_ON_ERROR(hr)

   

   

// Each loop fills about half of the shared buffer.
while (bDone == FALSE)
{
    //讓程序暫停運行一段時間,緩衝區裏在這段時間會被填充數據                        
        Sleep(hnsActualDuration/REFTIMES_PER_MILLISEC/2);

   

        hr = pCaptureClient->GetNextPacketSize(&packetLength);
        EXIT_ON_ERROR(hr)

   

    while (packetLength != 0)
        {
        //鎖定緩衝區,獲取數據
        hr = pCaptureClient->GetBuffer(
                                   &pData,
                                   &numFramesAvailable,
                                   &flags, NULL, NULL);
                EXIT_ON_ERROR(hr)

   

      if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
           {
                pData = NULL;  
           }

     

            hr = pMySink->CopyData(
                              pData, numFramesAvailable, &bDone);
            EXIT_ON_ERROR(hr)

     

            hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
            EXIT_ON_ERROR(hr)

     

            hr = pCaptureClient->GetNextPacketSize(&packetLength);
            EXIT_ON_ERROR(hr)
        }
    }

   

hr = pAudioClient->Stop(); 
EXIT_ON_ERROR(hr)


查看錄製的音頻可以用 audacity 這個軟件
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章