Windows下Core Audio APIs音频应用开发

   对于一个音频应用程序,最基本也是最重要的两点就是:音频数据的采集;音频数据的播放。首先我们来了解下面几个概念:

   ·IMMDevice:创建音频设备终端,我们可以把它简单的理解为设备对象;

   ·IAudioClient:创建一个用来管理音频数据流的对象,应用程序通过这个对象可以获取的音频设备里的数据,我们可以把它想象成一个大水池,里面都是一些数据。

   ·IAudioCaptureClient:很明显,专用于获取采集数据的对象,它还有个兄弟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)
    代码就这么多,这是官网给出的最简单的一个关于获取音频数据的示例,这里面取到的数据是最原始的,我们可以对这些数据进行任何处理,达到我们需要的效果。

 

   音频数据量的计算:数据量(字节/秒)=(采样频率(HZ)*采样位数(bit)*声道数)/8

   在代码中,创建完管理对象后,我们就可以获取到当前设备的音频数据的格式,然后对pMySink设置了数据格式

  • hr = pAudioClient->GetMixFormat(&pwfx);//这里就可以获取数据格式:频率、采集位数、声道数
  • hr = pMySink->SetFormat(pwfx); //设置数据格式,计算数据量

  这就决定了pMySink每次读取数据量的大小,保证我们在获取的每一帧数据都是正确的

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

   这里就是简单的拷贝数据了。

 

参考:

https://www.yuque.com/docs/share/43b77776-da76-4fdd-b597-563436b57275

你可能感兴趣的:(音频,windows)