【XAuido2】播放wav和ogg格式音频文件
生活随笔
收集整理的這篇文章主要介紹了
【XAuido2】播放wav和ogg格式音频文件
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
通過MSDN的文檔可以知道,XAuido2出了最新的再發(fā)行版本,可以兼容win7。而DirectX SDK的XAudio2.7版本已經是2010年的產物了。需要下載庫的我有上傳資源在CSDN~
封裝之后,不僅可播放wav文件,也可以播放ogg文件。不過解析ogg格式需要配置libogg、libvorbis、libvorbisfile三個庫,在ogg的官網(wǎng)下載配置即可。
https://xiph.org/downloads/
并且我分為音樂和音效兩個混音,可以分別控制音量大小,符合一般游戲的需求。
并且我還是用X3DAudio實現(xiàn)了簡單的3D音效封裝,代碼如下:
標頭DNDSound:
// //name: DNDSound //author: Lveyou //date: 17-11-11//other: //17-11-11: 簡單封裝zplaylib庫 - Lveyou //18-08-09: 改為 XAudio2 播放 wav文件 - Lveyou //#ifndef _DND_SOUND_H_ #define _DND_SOUND_H_#include "DNDDLL.h" #include "DNDTypedef.h" #include "DNDString.h" #include "DNDGame.h" #include "DNDDebug.h"namespace DND {class DLL_API Voice{friend class Voice_imp;public:virtual void Play() = 0;//傳入256無限循環(huán)virtual void PlayLoop(UINT32 num = 256) = 0;virtual void Pause() = 0;virtual void SetVolume(float volume) = 0;virtual void SetFrequencyRatio(float ratio) = 0;//是否沒有播放virtual bool IsEnd() = 0;//設置是否播放完成后再刪除,默認為truevirtual void SetDeleteWaitEnd(bool delete_wait_end) = 0;private:virtual ~Voice() {}};class DLL_API Sound{public:virtual void SetOpen(bool open = true) = 0;virtual bool IsOpen() = 0;virtual void Load(const String& name, const String& path) = 0;//0為音效、1為音樂(group id)virtual Voice* Create(const String& name,UINT32 group_id = 0, bool dsp = false, float scaler = 64.0f) = 0;//刪除音效virtual void Delete(Voice* voice) = 0;//傳入-1代表總音量,0為音效、1為音樂(group id)virtual void SetVolume(float v, UINT32 group_id = -1) = 0;virtual float GetVolume(UINT32 group_id = -1) = 0;//此方法返//virtual Voice* GetVoice(const String& name) = 0;//請判斷是播放狀態(tài)再調用virtual void UpdateDSP(Voice* voice,Vector3 voice_pos, Vector3 listener_pos,Vector3 voice_v = Vector3(), Vector3 listener_v = Vector3()) = 0;};inline void snd_play(const String& name, UINT32 group_id = 0, float volume = 1.0f){if (name.IsEmpty())return;//auto* voice = Game::Get()->sound->Create(name, group_id);if (voice){if (volume != 1.0f)voice->SetVolume(volume);voice->Play();}else{debug_err(String(L"DND: 音效獲取失敗") + name);return;}Game::Get()->sound->Delete(voice);} }#endif?實現(xiàn)標頭:
// //name: DNDSound imp //author: Lveyou //date: 18-08-09//other: //18-08-09: 實現(xiàn) - Lveyou //20-12-28: 使用XAuido2.9再發(fā)行版本,兼容win7 - Lveyou //#ifndef _DND_SOUND_IMP_H_ #define _DND_SOUND_IMP_H_//#ifdef USE_DX_SDK //#include <..\dx11_sdk\include\XAudio2.h> //#include <..\dx11_sdk\include\X3DAudio.h> //#else //#include <XAudio2.h> //#include <X3DAudio.h> //#endif #include <..\XAudio2.9Redist\include\XAudio2.h> #include <..\XAudio2.9Redist\include\X3DAudio.h>#include <map> #include <list> using namespace std;#include "DNDSound.h" #include "DNDThread.h"namespace DND {class VoiceData{public: WAVEFORMATEXTENSIBLE _wfx;XAUDIO2_BUFFER _buffer;VoiceData(){ZeroMemory(&_wfx, sizeof(_wfx));ZeroMemory(&_buffer, sizeof(_buffer));}};class VoiceCallback;class Voice_imp : public Voice//, public Thread{public:virtual void Play() override;virtual void PlayLoop(UINT32 num) override;virtual void Pause() override;virtual void SetVolume(float volume) override;virtual void SetFrequencyRatio(float ratio) override;virtual bool IsEnd() override;virtual void SetDeleteWaitEnd(bool delete_wait_end) override;//virtual void _run() override;bool _is_valid(){return _sourceVoice;}IXAudio2SourceVoice* _sourceVoice;VoiceCallback* _voiceCallBack;bool _end;//為true代表需要提交bool _deleteWaitEnd;//等待結束再刪除UINT32 _groupID;//XAUDIO2_BUFFER* _bufferRef;//X3DAUDIO_EMITTER* _emitter;Voice_imp();~Voice_imp();};//回調class VoiceCallback : public IXAudio2VoiceCallback{public:Voice_imp* _voice;HANDLE hBufferEndEvent;VoiceCallback() : hBufferEndEvent(CreateEvent(NULL, FALSE, FALSE, NULL)) {}~VoiceCallback() { CloseHandle(hBufferEndEvent); }//Called when the voice has just finished playing a contiguous audio stream.void STDMETHODCALLTYPE OnStreamEnd(){SetEvent(hBufferEndEvent);}//Unused methods are stubsvoid STDMETHODCALLTYPE OnVoiceProcessingPassEnd() { }void STDMETHODCALLTYPE OnVoiceProcessingPassStart(UINT32 SamplesRequired) { }void STDMETHODCALLTYPE OnBufferEnd(void * pBufferContext) { //debug_err(L"DND: VoiceCallback: OnBufferEnd "); /*_voice->_sourceVoice->Stop(0);if (FAILED(_voice->_sourceVoice->SubmitSourceBuffer(_voice->_bufferRef))){debug_err(L"DND: VoiceCallback: 提交SourceBuffer失敗: ");}else*///直接標記為播放結束_voice->_end = true;}void STDMETHODCALLTYPE OnBufferStart(void * pBufferContext) { }void STDMETHODCALLTYPE OnLoopEnd(void * pBufferContext) { 停止循環(huán)//_voice->_sourceVoice->Stop(XAUDIO2_PLAY_TAILS);指明它已經播放結束了//_voice->_ready = true;//debug_err(L"DND: VoiceCallback: OnLoopEnd ");}void STDMETHODCALLTYPE OnVoiceError(void * pBufferContext, HRESULT Error) { }};class Sound_imp : public Sound{public:virtual void SetOpen(bool open = true) override;virtual bool IsOpen() override;virtual void Load(const String& name, const String& path) override;virtual Voice* Create(const String& name, UINT32 group_id = 0, bool dsp = false, float scaler = 64.0f) override;virtual void Delete(Voice* voice) override;virtual void SetVolume(float v, UINT32 group_id = -1) override;virtual float GetVolume(UINT32 group_id = -1) override;//virtual Voice* GetVoice(const String& name) override;virtual void UpdateDSP(Voice* voice,Vector3 voice_pos, Vector3 listener_pos, Vector3 voice_v = Vector3(), Vector3 listener_v = Vector3()) override;void _init();//失敗返回一個空Voice,防止指針操作崩潰Voice* _get_voice_invalid();bool _is_voice_valid(Voice* v);Sound_imp(){_xaudio2 = NULL;_masterVoice = NULL;_open = false;_inited = false;}public:IXAudio2* _xaudio2;IXAudio2MasteringVoice* _masterVoice;//子混音IXAudio2SubmixVoice * _submixVoice[2];//0為音效、1為音樂(group id)XAUDIO2_SEND_DESCRIPTOR _sendArray0[1];XAUDIO2_SEND_DESCRIPTOR _sendArray1[1];XAUDIO2_VOICE_SENDS _voiceSends[2];//設備信息//UINT32 _cannelMask;//主混音X3DAUDIO_HANDLE _x3dInstance;XAUDIO2_VOICE_DETAILS _voiceDetails;//name -> datamap<String, VoiceData*> _mapVoiceData;//所有音頻//map<String, list<Voice_imp*>> _mapAllVoice;//刪除列表list<Voice_imp*> _listDelete;//聽者信息X3DAUDIO_LISTENER _listener;X3DAUDIO_DSP_SETTINGS _dsp;bool _open;bool _inited;}; }#endif?源:
#include "DNDSound_imp.h" #include "DNDDebug.h" #include "DNDStreamOutput.h" #include "DNDSystem.h"#include "vorbis\codec.h" #include "vorbis\vorbisfile.h"//#ifdef _WIN32 //#include <io.h> //#include <fcntl.h> //#endif//#include <fstream> #include <io.h>namespace DND { #ifdef _XBOX //Big-Endian #define fourccRIFF 'RIFF' #define fourccDATA 'data' #define fourccFMT 'fmt ' #define fourccWAVE 'WAVE' #define fourccXWMA 'XWMA' #define fourccDPDS 'dpds' #endif#ifndef _XBOX //Little-Endian #define fourccRIFF 'FFIR' #define fourccDATA 'atad' #define fourccFMT ' tmf' #define fourccWAVE 'EVAW' #define fourccXWMA 'AMWX' #define fourccDPDS 'sdpd' #endifHRESULT FindChunk(FILE* fp, DWORD fourcc, DWORD & dwChunkSize, DWORD & dwChunkDataPosition){HRESULT hr = S_OK;/*if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_BEGIN))return HRESULT_FROM_WIN32(GetLastError());*/if (0 != fseek(fp, 0, SEEK_SET))return S_FALSE;DWORD dwChunkType;DWORD dwChunkDataSize;DWORD dwRIFFDataSize = 0;DWORD dwFileType;DWORD bytesRead = 0;DWORD dwOffset = 0;while (hr == S_OK){DWORD dwRead;/*if (0 == ReadFile(hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL))hr = HRESULT_FROM_WIN32(GetLastError());if (0 == ReadFile(hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL))hr = HRESULT_FROM_WIN32(GetLastError());*/dwRead = fread(&dwChunkType, sizeof(DWORD), 1, fp);dwRead = fread(&dwChunkDataSize, sizeof(DWORD), 1, fp);switch (dwChunkType){case fourccRIFF:dwRIFFDataSize = dwChunkDataSize;dwChunkDataSize = 4;/*if (0 == ReadFile(hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL))hr = HRESULT_FROM_WIN32(GetLastError());*/dwRead = fread(&dwFileType, sizeof(DWORD), 1, fp);break;default:/*if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, dwChunkDataSize, NULL, FILE_CURRENT))return HRESULT_FROM_WIN32(GetLastError());*/if (0 != fseek(fp, dwChunkDataSize, SEEK_CUR))return S_FALSE;break;}dwOffset += sizeof(DWORD) * 2;if (dwChunkType == fourcc){dwChunkSize = dwChunkDataSize;dwChunkDataPosition = dwOffset;return S_OK;}dwOffset += dwChunkDataSize;if (bytesRead >= dwRIFFDataSize) return S_FALSE;}return S_OK;}HRESULT ReadChunkData(FILE* fp, void * buffer, DWORD buffersize, DWORD bufferoffset){HRESULT hr = S_OK;/* if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, bufferoffset, NULL, FILE_BEGIN))return HRESULT_FROM_WIN32(GetLastError());*/if (0 != fseek(fp, bufferoffset, SEEK_SET))return S_FALSE;//DWORD dwRead;/*if (0 == ReadFile(hFile, buffer, buffersize, &dwRead, NULL))hr = HRESULT_FROM_WIN32(GetLastError());*/fread(buffer, buffersize, 1, fp);return hr;}void Sound_imp::SetOpen(bool open /*= true*/){_open = open;if(_open)_init();}bool Sound_imp::IsOpen(){return _open;}////以上代碼copy自dx sdk文檔void Sound_imp::Load(const String& name, const String& path){if (!_open)return;String name_format = path;int index = name_format.FindEnd(L'.');if(index != -1)name_format.CutHead(index);int file_type = 0;if (name_format == L".wav")file_type = 1;else if (name_format == L".ogg")file_type = 2;if (file_type == 1){FILE* file = NULL;if (Game::Get()->sys->GetFile(path, file) == -1){debug_err(String(L"DND: wav文件加載失敗: ") + path);return;}//HANDLE hFile = (HANDLE)_get_osfhandle((int)file);/*HANDLE hFile = CreateFile(file,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);*//*if (INVALID_HANDLE_VALUE == hFile){debug_err(String(L"DND: wav文件獲取文件句柄失敗: ") + path);return;}*/if (0 != fseek(file, 0, SEEK_SET))//INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_BEGIN)){debug_err(String(L"DND: wav文件加載失敗2: ") + path);fclose(file);return;}DWORD dwChunkSize;DWORD dwChunkPosition;//check the file type, should be fourccWAVE or 'XWMA'FindChunk(file, fourccRIFF, dwChunkSize, dwChunkPosition);DWORD filetype;ReadChunkData(file, &filetype, sizeof(DWORD), dwChunkPosition);if (filetype != fourccWAVE){debug_err(String(L"DND: 音效文件加載失敗,不是wav文件: ") + path);fclose(file);return;}VoiceData* ret = new VoiceData;if (S_OK != FindChunk(file, fourccFMT, dwChunkSize, dwChunkPosition)){debug_err(String(L"DND: 加載wav文件fourccFMT失敗: ") + path);fclose(file);return;}if (S_OK != ReadChunkData(file, &(ret->_wfx), dwChunkSize, dwChunkPosition)){debug_err(String(L"DND: 加載wav文件_wfx失敗: ") + path);fclose(file);return;};//fill out the audio data buffer with the contents of the fourccDATA chunkif (S_OK != FindChunk(file, fourccDATA, dwChunkSize, dwChunkPosition)){debug_err(String(L"DND: 加載wav文件fourccDATA失敗: ") + path);fclose(file);return;};BYTE * pDataBuffer = new BYTE[dwChunkSize];if (S_OK != ReadChunkData(file, pDataBuffer, dwChunkSize, dwChunkPosition)){debug_err(String(L"DND: 加載wav文件pDataBuffer失敗: ") + path);fclose(file);return;};(ret->_buffer).AudioBytes = dwChunkSize; //buffer containing audio data(ret->_buffer).pAudioData = pDataBuffer; //size of the audio buffer in bytes(ret->_buffer).Flags = 0;// XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer(ret->_buffer).LoopCount = 0;// XAUDIO2_LOOP_INFINITE_mapVoiceData[name] = ret;//至少一個準備播放//_mapAllVoice[name].push_back((Voice_imp*)Create(name));//CloseHandle(hFile);fclose(file);}else if(file_type == 2){FILE* file = NULL;if(Game::Get()->sys->GetFile(path, file) == -1){debug_err(String(L"DND: ogg文件加載失敗: ") + path);return;}/*char temp[1024] = {0};name.GetMultiByteStr(temp, 1024);if (fopen_s(&file, temp, "rb") == NULL){debug_err(String(L"DND: ogg文件加載失敗: ") + path);return;}*/OggVorbis_File vf;int eof = 0;int current_section;//#ifdef _WIN32 // _setmode(_fileno(stdin), _O_BINARY); // _setmode(_fileno(stdout), _O_BINARY); //#endifint ov_ret = ov_open_callbacks(file, &vf, NULL, 0, OV_CALLBACKS_NOCLOSE);if (ov_ret < 0){debug_err(String(L"DND: 音效文件加載失敗,不是ogg文件: ") + path);fclose(file);return;}VoiceData* ret = new VoiceData;//寫入wfx{vorbis_info *vi = ov_info(&vf, -1);//只需要填充Foramt這一個結構,其他被截斷了ret->_wfx.Format.cbSize = 0;ret->_wfx.Format.wFormatTag = WAVE_FORMAT_PCM;ret->_wfx.Format.nChannels = vi->channels;//聲道數(shù)ret->_wfx.Format.nSamplesPerSec = vi->rate;//采樣率ret->_wfx.Format.wBitsPerSample = 16; //msdn: 如果wFormatTag是WAVE_FORMAT_PCM,則wBitsPerSample應該等于8或16ret->_wfx.Format.nBlockAlign = ret->_wfx.Format.nChannels * ret->_wfx.Format.wBitsPerSample / 8;//msdn: 如果wFormatTag是WAVE_FORMAT_PCM或WAVE_FORMAT_EXTENSIBLE,則nBlockAlign必須等于nChannels和wBitsPerSample的乘積除以8(每字節(jié)位數(shù))ret->_wfx.Format.nAvgBytesPerSec = ret->_wfx.Format.nSamplesPerSec * ret->_wfx.Format.nBlockAlign;//msdn: 如果wFormatTag是WAVE_FORMAT_PCM,則nAvgBytesPerSec應該等于nSamplesPerSec和nBlockAlign的乘積}//寫入bufferchar pcmout[4096];StreamOutput o;o.SetDelete(false);while (!eof) {long ret = ov_read(&vf, pcmout, sizeof(pcmout), 0, 2, 1, ¤t_section);if (ret == 0) {/* EOF */eof = 1;}else if (ret < 0) {/* error in the stream. Not a problem, just reporting it incase we (the app) cares. In this case, we don't. */}else {/* we don't bother dealing with sample rate changes, etc, butyou'll have to*/o.Write(pcmout, ret);//fwrite(pcmout, 1, ret, stdout);}}(ret->_buffer).AudioBytes = o.GetLength(); //buffer containing audio data(ret->_buffer).pAudioData = o.GetBuffer(); //size of the audio buffer in bytes(ret->_buffer).Flags = 0;// XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer(ret->_buffer).LoopCount = 0;_mapVoiceData[name] = ret;//至少一個準備播放//_mapAllVoice[name].push_back((Voice_imp*)Create(name));ov_clear(&vf);fclose(file);}else{debug_err(String(L"DND: 音效文件加載失敗,不支持的格式: ") + name_format);return;}}DND::Voice* Sound_imp::Create(const String& name, UINT32 group_id, bool dsp, float scaler){if (!_open)return _get_voice_invalid();Voice_imp* ret = new Voice_imp;ret->_voiceCallBack = new VoiceCallback; ret->_voiceCallBack->_voice = ret;ret->_groupID = group_id;auto& iter = _mapVoiceData.find(name);if (iter == _mapVoiceData.end()){debug_err(String(L"DND: Sound::Create: 音頻沒有加載: ") + name);delete ret;return _get_voice_invalid();}if (FAILED(_xaudio2->CreateSourceVoice(&(ret->_sourceVoice), (WAVEFORMATEX*)&(iter->second->_wfx),0, XAUDIO2_DEFAULT_FREQ_RATIO, ret->_voiceCallBack, &_voiceSends[group_id], NULL))){debug_err(String(L"DND: Sound::Create: 創(chuàng)建SourceVoice失敗: ") + name);delete ret;return _get_voice_invalid();}ret->_bufferRef = &(iter->second->_buffer);/*if (FAILED(ret->_sourceVoice->SubmitSourceBuffer(ret->_bufferRef))){debug_err(String(L"DND: Sound::Create: 提交SourceBuffer失敗: ") + name);delete ret;return NULL;}*///dspif (dsp){XAUDIO2_VOICE_DETAILS voice_detail;ret->_sourceVoice->GetVoiceDetails(&voice_detail);if (voice_detail.InputChannels != 2){debug_err(String(L"DND: Sound::Create: 音頻文件通道數(shù)不為2,不能創(chuàng)建DSP效果: ") + name);return ret;}ret->_emitter = new X3DAUDIO_EMITTER;ZeroMemory(ret->_emitter, sizeof(X3DAUDIO_EMITTER));ret->_emitter->ChannelCount = 2;ret->_emitter->CurveDistanceScaler = scaler;FLOAT32* p_cas = new FLOAT32[2];for (UINT32 i = 0; i != 2; ++i)p_cas[i] = 0;ret->_emitter->pChannelAzimuths = p_cas;ret->_emitter->OrientFront = {0.0f, 0.0f, 1.0f};ret->_emitter->OrientTop = { 0.0f, -1.0f, 0.0f };}return ret;}void Sound_imp::SetVolume(float v, UINT32 group_id){if (!_open)return;//_masterVoice->SetVolume(v);if (group_id == -1)_masterVoice->SetVolume(v);else_submixVoice[group_id]->SetVolume(v);}float Sound_imp::GetVolume(UINT32 group_id){if (!_open)return 0;float ret;if(group_id == -1)_masterVoice->GetVolume(&ret);else_submixVoice[group_id]->GetVolume(&ret);//_masterVoice->GetVolume(&ret);return ret;}//DND::Voice* Sound_imp::GetVoice(const String& name)//{// auto& iter = _mapAllVoice.find(name);// if (iter == _mapAllVoice.end())// return NULL;// for (auto& iter2 : iter->second)// {// if (iter2->_ready)// return iter2;// }// Voice* ret = Create(name);// iter->second.push_back((Voice_imp*)ret);// return ret;//}void Sound_imp::UpdateDSP(Voice* voice, Vector3 voice_pos, Vector3 listener_pos, Vector3 voice_v /*= Vector3()*/, Vector3 listener_v /*= Vector3()*/){if (!_is_voice_valid(voice))return;Voice_imp* p = (Voice_imp*)voice;if (p && p->_emitter){//設置速度與位置p->_emitter->Position.x = voice_pos.a;p->_emitter->Position.y = voice_pos.b;p->_emitter->Position.z = voice_pos.c;p->_emitter->Velocity.x = voice_v.a;p->_emitter->Velocity.y = voice_v.b;p->_emitter->Velocity.z = voice_v.c;_listener.Position.x = listener_pos.a;_listener.Position.y = listener_pos.b;_listener.Position.z = listener_pos.c;_listener.Velocity.x = listener_v.a;_listener.Velocity.y = listener_v.b;_listener.Velocity.z = listener_v.c;//計算X3DAudioCalculate(_x3dInstance, &_listener, p->_emitter,X3DAUDIO_CALCULATE_MATRIX//| X3DAUDIO_CALCULATE_DOPPLER/*| X3DAUDIO_CALCULATE_LPF_DIRECT| X3DAUDIO_CALCULATE_REVERB*/,&_dsp);//應用效果p->_sourceVoice->SetOutputMatrix(_submixVoice[p->_groupID], 2, _voiceDetails.InputChannels, _dsp.pMatrixCoefficients);//p->_sourceVoice->SetFrequencyRatio(_dsp.DopplerFactor);/*p->_sourceVoice->SetOutputMatrix(_submixVoice[p->_groupID], 2, _voiceDetails.InputChannels, &_dsp.ReverbLevel);*//*XAUDIO2_FILTER_PARAMETERS FilterParameters = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI / 6.0f * _dsp.LPFDirectCoefficient), 1.0f };p->_sourceVoice->SetFilterParameters(&FilterParameters);*/}}void Sound_imp::_init(){if (_inited)return;_inited = true;#ifndef _XBOXCoInitializeEx(NULL, COINIT_MULTITHREADED); #endifHRESULT hr;if (FAILED(hr = XAudio2Create(&_xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR))){dnd_assert(L"DND: XAudio2 初始化失敗!");return;}//#define USE_DX_SDK_SND#ifdef USE_DX_SDK_SND//獲取設備詳情XAUDIO2_DEVICE_DETAILS device_details;_xaudio2->GetDeviceDetails(0, &device_details);debug_msg(String::Format(L"DND: 音頻設備: %ws-%ws", device_details.DisplayName, device_details.DeviceID)); #endif//直接使用0,全局音頻設備if (FAILED(hr = _xaudio2->CreateMasteringVoice(&_masterVoice, XAUDIO2_DEFAULT_CHANNELS,XAUDIO2_DEFAULT_SAMPLERATE, 0, 0, NULL))){dnd_assert(L"DND: XAudio2 創(chuàng)建 MasterVoice 失敗!");return;}//獲取主控詳情_masterVoice->GetVoiceDetails(&_voiceDetails);//子混音(應和主混音通道數(shù)一致)if (FAILED(hr = _xaudio2->CreateSubmixVoice(&(_submixVoice[0]),_voiceDetails.InputChannels,_voiceDetails.InputSampleRate, 0, 0, 0))){dnd_assert(L"DND: XAudio2 創(chuàng)建 SubmixVoice0 失敗!");return;}if (FAILED(hr = _xaudio2->CreateSubmixVoice(&(_submixVoice[1]), _voiceDetails.InputChannels,_voiceDetails.InputSampleRate, 0, 0, 0))){dnd_assert(L"DND: XAudio2 創(chuàng)建 SubmixVoice1 失敗!");return;}_sendArray0[0] = { 0, _submixVoice[0] };_sendArray1[0] = { 0, _submixVoice[1] };_voiceSends[0] = { 1, _sendArray0 };_voiceSends[1] = { 1, _sendArray1 };//初始化X3DAudioDWORD dwChannelMask; #ifdef USE_DX_SDK_SNDdwChannelMask = device_details.OutputFormat.dwChannelMask; #else_masterVoice->GetChannelMask(&dwChannelMask); #endifX3DAudioInitialize(dwChannelMask, X3DAUDIO_SPEED_OF_SOUND, _x3dInstance);//聽者只有一個ZeroMemory(&_listener, sizeof(X3DAUDIO_LISTENER));_listener.OrientFront = { 0.0f,0.0f,-1.0f };_listener.OrientTop = { 0.0f,-1.0f,0.0f };//dspZeroMemory(&_dsp, sizeof(X3DAUDIO_DSP_SETTINGS));FLOAT32 * matrix = new FLOAT32[2 * _voiceDetails.InputChannels];FLOAT32* dtimes = new FLOAT32[_voiceDetails.InputChannels];_dsp.SrcChannelCount = 2;_dsp.DstChannelCount = _voiceDetails.InputChannels;_dsp.pMatrixCoefficients = matrix;_dsp.pDelayTimes = dtimes;/*_dsp.EmitterToListenerDistance = 1.0f / 64.0f;_dsp.EmitterVelocityComponent = 1.0f / 64.0f;_dsp.ListenerVelocityComponent = 1.0f / 64.0f;*/}void Sound_imp::Delete(Voice* voice){if (!voice)return;Voice_imp* p = (Voice_imp*)voice;if (p->_sourceVoice == NULL){delete p;return;}if (!p->_deleteWaitEnd || p->_end){p->_sourceVoice->Stop();delete p;}else{_listDelete.push_back(p);}}DND::Voice* Sound_imp::_get_voice_invalid(){Voice_imp* ret = new Voice_imp();return ret;}bool Sound_imp::_is_voice_valid(Voice* v){return v && ((Voice_imp*)v)->_sourceVoice;}void Voice_imp::Play(){if (!_is_valid())return;if (_end){_bufferRef->LoopCount = 0;if (FAILED(_sourceVoice->SubmitSourceBuffer(_bufferRef))){debug_err(String(L"DND: Voice::Play: 提交SourceBuffer失敗: "));return;}_sourceVoice->Start(0, XAUDIO2_COMMIT_NOW);_end = false;}/*WaitForSingleObject(_voiceCallBack->hBufferEndEvent, INFINITE);Thread::Start();*///_sourceVoice->SetChannelVolumes(,)}void Voice_imp::PlayLoop(UINT32 num){if (!_is_valid())return;if (_end){//結束了則重新提交_bufferRef->LoopCount = num - 1;if (FAILED(_sourceVoice->SubmitSourceBuffer(_bufferRef))){debug_err(String(L"DND: Voice::PlayLoop: 提交SourceBuffer失敗: "));return;}_sourceVoice->Start(0, XAUDIO2_COMMIT_NOW);_end = false;}}void Voice_imp::Pause(){if (!_is_valid())return;_sourceVoice->Stop(0, XAUDIO2_COMMIT_NOW);}void Voice_imp::SetVolume(float volume){if (!_is_valid())return;_sourceVoice->SetVolume(volume);}bool Voice_imp::IsEnd(){return _end;}void Voice_imp::SetDeleteWaitEnd(bool delete_wait_end){_deleteWaitEnd = delete_wait_end;}Voice_imp::Voice_imp(){_sourceVoice = NULL;_voiceCallBack = NULL;_end = true;_deleteWaitEnd = true;_groupID = 0;_emitter = NULL;_bufferRef = NULL;}Voice_imp::~Voice_imp(){if (_sourceVoice)_sourceVoice->DestroyVoice();//先于_sourceVoice釋放會導致深不可測的bugdelete _voiceCallBack;if (_emitter)delete[] _emitter->pChannelAzimuths;delete _emitter;}void Voice_imp::SetFrequencyRatio(float ratio){if (!_is_valid())return;_sourceVoice->SetFrequencyRatio(ratio);//_sourceVoice->}/*void Voice_imp::_run(){}*/}?
總結
以上是生活随笔為你收集整理的【XAuido2】播放wav和ogg格式音频文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【pnglib】解析png格式的图像
- 下一篇: 【DirectX12】2.示例三角形绘制