D_liangcheng
D_liangcheng
2017-10-24 07:55

C++ core audio api怎么播放pcm格式的文件

3
  • c++
  • audio

自己改的代码播放不了,应该是怎样的
#include "stdafx.h"
#include
#include

#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000

#define EXIT_ON_ERROR(hres) \
if (FAILED(hres)) { printf("error\n");goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);

class MyAudioSource {
public:
//WAVEFORMATEX *pwfx = NULL;
int SetFormat(WAVEFORMATEX *pwfx);

int     LoadData(UINT32 num, BYTE * pData, DWORD *flags);

};

int MyAudioSource::SetFormat(WAVEFORMATEX *pwfx)
{
printf("wFormatTag is %x\n", pwfx->wFormatTag); //格式类型
printf("nChannels is %x\n", pwfx->nChannels); //声道数(即单声道,立体声)
printf("nSamplesPerSec is %d\n", pwfx->nSamplesPerSec); //采样率
printf("nAvgBytesPerSec is %d\n", pwfx->nAvgBytesPerSec); //用于缓冲区估计
printf("wBitsPerSample is %d\n", pwfx->wBitsPerSample); //单声道数据样本的位数

BOOL bRet(FALSE);

if (pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
{
    printf("WAVE_FORMAT_IEEE_FLOAT\n");
    pwfx->wFormatTag = WAVE_FORMAT_PCM;
    pwfx->wBitsPerSample = 16;
    pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;     
    pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;

    bRet = TRUE;
}
else if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
{
    printf("WAVE_FORMAT_EXTENSIBLE\n");
    PWAVEFORMATEXTENSIBLE pEx = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(pwfx);
    if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pEx->SubFormat))
    {
        pEx->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
        pEx->Samples.wValidBitsPerSample = 16;   //位精度
        pwfx->wBitsPerSample = 16;
        pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;     //数据块大小
        pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;   //用于缓冲区估计

        bRet = TRUE;
    }
}

return bRet;

}

int MyAudioSource::LoadData(UINT32 num, BYTE * pData, DWORD *flags)
{
char *fBuffer = new char[num];
FILE *fp;
fp = fopen("paomo.pcm", "r");
if (fp == NULL)
{
printf("文件打开失败");
return 0;
}

if (pData != NULL)
{
    fread(fBuffer, num, 1, fp);
    memcpy(pData, fBuffer, num);
    printf("num:%d\n", num);

}
return 0;

}

HRESULT PlayAudioStream(MyAudioSource *pMySource)
{
HRESULT hr;
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
REFERENCE_TIME hnsActualDuration;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
IAudioClient *pAudioClient = NULL;
IAudioRenderClient *pRenderClient = NULL;
WAVEFORMATEX *pwfx = NULL;
UINT32 bufferFrameCount;
UINT32 numFramesAvailable;
UINT32 numFramesPadding;
BYTE *pData;
DWORD flags = 0;

hr = CoCreateInstance(
    CLSID_MMDeviceEnumerator, NULL,
    CLSCTX_ALL, IID_IMMDeviceEnumerator,
    (void**)&pEnumerator);
EXIT_ON_ERROR(hr)

    hr = pEnumerator->GetDefaultAudioEndpoint(
        eRender, 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)

    // Tell the audio source which format to use.
    hr = pMySource->SetFormat(pwfx);
EXIT_ON_ERROR(hr)

    // Get the actual size of the allocated buffer.
    hr = pAudioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr)

    hr = pAudioClient->GetService(
        IID_IAudioRenderClient,
        (void**)&pRenderClient);
EXIT_ON_ERROR(hr)

    // Grab the entire buffer for the initial fill operation.
    hr = pRenderClient->GetBuffer(bufferFrameCount, &pData);
EXIT_ON_ERROR(hr)

    // Load the initial data into the shared buffer.
    hr = pMySource->LoadData(bufferFrameCount, pData, &flags);
EXIT_ON_ERROR(hr)

    hr = pRenderClient->ReleaseBuffer(bufferFrameCount, flags);
EXIT_ON_ERROR(hr)

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

hr = pAudioClient->Start();  // Start playing.
EXIT_ON_ERROR(hr)

    // Each loop fills about half of the shared buffer.
    while (flags != AUDCLNT_BUFFERFLAGS_SILENT)
    {
        // Sleep for half the buffer duration.
        Sleep((DWORD)(hnsActualDuration / REFTIMES_PER_MILLISEC / 2));

        // See how much buffer space is available.
        hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
        EXIT_ON_ERROR(hr)

            numFramesAvailable = bufferFrameCount - numFramesPadding;

        // Grab all the available space in the shared buffer.
        hr = pRenderClient->GetBuffer(numFramesAvailable, &pData);
        EXIT_ON_ERROR(hr)

            // Get next 1/2-second of data from the audio source.
            hr = pMySource->LoadData(numFramesAvailable, pData, &flags);
        EXIT_ON_ERROR(hr)

            hr = pRenderClient->ReleaseBuffer(numFramesAvailable, flags);
        EXIT_ON_ERROR(hr)
    }

// Wait for last data in buffer to play before stopping.
Sleep((DWORD)(hnsActualDuration / REFTIMES_PER_MILLISEC / 2));

hr = pAudioClient->Stop();  // Stop playing.
EXIT_ON_ERROR(hr)

    Exit:
CoTaskMemFree(pwfx);
SAFE_RELEASE(pEnumerator)
    SAFE_RELEASE(pDevice)
    SAFE_RELEASE(pAudioClient)
    SAFE_RELEASE(pRenderClient)

    return hr;

}

int main()
{
CoInitialize(NULL);
MyAudioSource test;

PlayAudioStream(&test);
return 0;

}

  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

0条回答