最简单的WASAPI播放音乐代码

​
#include "framework.h"
#include <mmreg.h>
#include <mmdeviceapi.h>
#include <Audioclient.h>
#include <iostream>
#include <iomanip>
#include <chrono>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <commdlg.h>
#include <CommCtrl.h>
#include <combaseapi.h>
#include <ShObjIdl_core.h>
#include "Shlwapi.h"
#include <Shlobj.h>



#define REFTIMES_PER_SEC  5000000
#define REFTIMES_PER_MILLISEC  10000

#define EXIT_ON_ERROR(hres) if (FAILED(hres)) {MessageBox(NULL,L"失败",L"fail",MB_OK); 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);

extern bool audio_play;
extern HANDLE pause_music;
extern HANDLE pauseEvent;
extern BYTE* PCM;

HRESULT PlayAudio(INT16 *wav_buf, LONG64  dataSize)
{
	int sk = 0;
	HRESULT hr;
	IMMDevice* pDevice;
	IMMDeviceEnumerator* pEnumerator = NULL;
	IAudioClient* pAudioClient = NULL;
	IAudioRenderClient* pRenderClient = NULL;
	REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;

	UINT32 bufferSizeInFrames;
	DWORD initStreamFlags = (AUDCLNT_STREAMFLAGS_RATEADJUST | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
	WAVEFORMATEX pwfx;
	INT16* pData = NULL;

	IAudioClock* audioClock;
	UINT64 audioPlaybackFreq;
	UINT64 audioPlaybackPos;
	UINT64 audioPlaybackPosInSeconds;
	UINT64 audioPlaybackPosInSamples;
	UINT32 wavPlaybackSample = 0;
	UINT32 bufferPadding;
	UINT32 soundBufferLatency;
	UINT32 numFramesToWrite;
	int read = 0, n = 0;

	UINT32 numWavSamples = dataSize / (2 * sizeof(UINT16));
	DWORD num = 0;
	//申请内存
	
	UINT16* dataCache = new UINT16[dataSize / 2];
	CopyMemory(dataCache,wav_buf, dataSize );
	free(wav_buf);

	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 = SetFormat(&pwfx);
	EXIT_ON_ERROR(hr);
	hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, initStreamFlags, hnsRequestedDuration * 40, 0, &pwfx, NULL);
	EXIT_ON_ERROR(hr);
	hr = pAudioClient->GetService(__uuidof(IAudioRenderClient), (LPVOID*)(&pRenderClient));
	EXIT_ON_ERROR(hr);
	hr = pAudioClient->GetBufferSize(&bufferSizeInFrames);
	EXIT_ON_ERROR(hr);
	hr = pAudioClient->Start();
	EXIT_ON_ERROR(hr);

	while(read < dataSize/2)
	{		
		hr = pAudioClient->GetCurrentPadding(&bufferPadding);
		EXIT_ON_ERROR(hr);
		soundBufferLatency = bufferSizeInFrames / 50;
		numFramesToWrite = soundBufferLatency - bufferPadding;
		hr = pRenderClient->GetBuffer(numFramesToWrite, (BYTE**)(&pData));
		EXIT_ON_ERROR(hr);
		for (int i = 0; i < numFramesToWrite; i++)
		{
			pData[2 * i] = dataCache[sk++];
			pData[2 * i + 1] = dataCache[sk++];		
			read = read + 2;
		}
		hr = pRenderClient->ReleaseBuffer(numFramesToWrite, 0);
		EXIT_ON_ERROR(hr);
		hr = pAudioClient->GetService(__uuidof(IAudioClock), (LPVOID*)(&audioClock));
		EXIT_ON_ERROR(hr);
		audioClock->GetFrequency(&audioPlaybackFreq);
		audioClock->GetPosition(&audioPlaybackPos, 0);
		audioClock->Release();
		audioPlaybackPosInSeconds = audioPlaybackPos / audioPlaybackFreq;
		audioPlaybackPosInSamples = audioPlaybackPosInSeconds * 44100;
	}

Exit:	pAudioClient->Stop();
	pAudioClient->Release();
	pRenderClient->Release();
	delete[]dataCache;

	return 0;
}

int SetFormat(WAVEFORMATEX* wfex)
{
	wfex->wFormatTag = 1;
	wfex->nChannels = 2;
	wfex->cbSize = 0;
	wfex->nSamplesPerSec = 44100;
	wfex->nAvgBytesPerSec = 44100 * 2 * 2;
	wfex->wBitsPerSample = 16;
	wfex->nBlockAlign = 4;
	return 0;
}

​

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值