xAudio2 - Wie mehrer Sounds abspielen?
-
Hi,
habe früher in meinen Projekten DirectSound verwendet, aber dies wird ja nun abgelöst von xAduio2. Habe mir dann das Sample aus der SDK angeschaut und als Klasse in mein Projekt mit eingebaut. Allerdings gibt es da ein großes Problem:
In dem Beispielprogramm wird nur eine Datei wiedergegeben und das Programm "wartet" solange bis die Datei wiedergegeben wurde bevor es mit seinen nächsten Aufgaben forführt. Diese Tatsache ist natürlich inakzeptabel für mein Programm und daher wollte ich wissen, ob es ein gutes xAudio2 Tutorial / Sample gibt, indem erklärt oder veranschaulicht wird, wie man verschiedenen Sounds parallel und vor allem im Hintergrund abspielen kann, ohne dass das Programm blockiert wird.
Danke schonmalFür die Leute, die das SDK Sample nicht kennen, habe ich es hier mal als Klasse meines Projekts angefügt:
#include "XAudioSystem.h" CXAudioSystem::CXAudioSystem(void) { } CXAudioSystem::~CXAudioSystem(void) { CleanUp(); } BOOL CXAudioSystem::Init(void) { // XAudio2 initialisieren CoInitializeEx(NULL, COINIT_MULTITHREADED); UINT32 flags = 0; #ifdef _DEBUG flags |= XAUDIO2_DEBUG_ENGINE; #endif if (FAILED(XAudio2Create(&m_pXAudio2, flags))) { CoUninitialize(); return FALSE; } if (FAILED(m_pXAudio2->CreateMasteringVoice(&m_pMasteringVoice))) { SAFE_RELEASE(m_pXAudio2); CoUninitialize(); return FALSE; } return TRUE; } HRESULT CXAudioSystem::PlayPCM(LPCWSTR szFilename) { // Wave Datei finden WCHAR strFilePath[MAX_PATH]; if(FAILED(FindMediaFileCch(strFilePath, MAX_PATH, szFilename))) { return FALSE; } // Wave Datei lesen CWaveFile wav; if(FAILED(wav.Open(strFilePath, NULL, WAVEFILE_READ))) { return FALSE; } // Wave Format einlesen WAVEFORMATEX* pwfx = wav.GetFormat(); // Anzahl der Bytes und Sampels in der Wave berechnen DWORD cbWaveSize = wav.GetSize(); // Sampel Daten in den Speicher lesen BYTE* pbWaveData = new BYTE[ cbWaveSize ]; if(FAILED(wav.Read(pbWaveData, cbWaveSize, &cbWaveSize ) ) ) { SAFE_DELETE_ARRAY( pbWaveData ); return FALSE; } // Wave Datei mit XAudio2SourceVoice abspielen // Voice erzeugen IXAudio2SourceVoice* pSourceVoice; if(FAILED(m_pXAudio2->CreateSourceVoice(&pSourceVoice, pwfx))) { return FALSE; } // Übertragen der Wave Sample Daten an die XAUDIO2_BUFFER Struktur XAUDIO2_BUFFER buffer = {0}; buffer.pAudioData = pbWaveData; buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer buffer.AudioBytes = cbWaveSize; if(FAILED(pSourceVoice->SubmitSourceBuffer(&buffer))) { pSourceVoice->DestroyVoice(); SAFE_DELETE_ARRAY( pbWaveData ); return FALSE; } pSourceVoice->Start(0); // Sound abspielen BOOL isRunning = TRUE; while(isRunning) { XAUDIO2_VOICE_STATE state; pSourceVoice->GetState( &state ); isRunning = (state.BuffersQueued > 0) != 0; // Wait till the escape key is pressed if (GetAsyncKeyState(VK_ESCAPE)) break; Sleep(10); } // Wait till the escape key is released while( GetAsyncKeyState( VK_ESCAPE ) ) Sleep(10); pSourceVoice->DestroyVoice(); SAFE_DELETE_ARRAY(pbWaveData); return TRUE; } void CXAudioSystem::CleanUp(void) { m_pMasteringVoice->DestroyVoice(); SAFE_RELEASE(m_pXAudio2); CoUninitialize(); } HRESULT CXAudioSystem::FindMediaFileCch(WCHAR* strDestPath, int cchDest, LPCWSTR strFilename) { bool bFound = false; if( NULL==strFilename || strFilename[0] == 0 || NULL==strDestPath || cchDest < 10 ) return E_INVALIDARG; // Get the exe name, and exe path WCHAR strExePath[MAX_PATH] = {0}; WCHAR strExeName[MAX_PATH] = {0}; WCHAR* strLastSlash = NULL; GetModuleFileName( NULL, strExePath, MAX_PATH ); strExePath[MAX_PATH-1]=0; strLastSlash = wcsrchr( strExePath, TEXT('\\') ); if( strLastSlash ) { StringCchCopy( strExeName, MAX_PATH, &strLastSlash[1] ); // Chop the exe name from the exe path *strLastSlash = 0; // Chop the .exe from the exe name strLastSlash = wcsrchr( strExeName, TEXT('.') ); if( strLastSlash ) *strLastSlash = 0; } StringCchCopy( strDestPath, cchDest, strFilename ); if( GetFileAttributes( strDestPath ) != 0xFFFFFFFF ) return true; // Search all parent directories starting at .\ and using strFilename as the leaf name WCHAR strLeafName[MAX_PATH] = {0}; StringCchCopy( strLeafName, MAX_PATH, strFilename ); WCHAR strFullPath[MAX_PATH] = {0}; WCHAR strFullFileName[MAX_PATH] = {0}; WCHAR strSearch[MAX_PATH] = {0}; WCHAR* strFilePart = NULL; GetFullPathName( L".", MAX_PATH, strFullPath, &strFilePart ); if( strFilePart == NULL ) return false; while( strFilePart != NULL && *strFilePart != '\0' ) { StringCchPrintf( strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName ); if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF ) { StringCchCopy( strDestPath, cchDest, strFullFileName ); bFound = true; break; } StringCchPrintf( strFullFileName, MAX_PATH, L"%s\\%s\\%s", strFullPath, strExeName, strLeafName ); if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF ) { StringCchCopy( strDestPath, cchDest, strFullFileName ); bFound = true; break; } StringCchPrintf( strSearch, MAX_PATH, L"%s\\..", strFullPath ); GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart ); } if( bFound ) return S_OK; // On failure, return the file as the path but also return an error code StringCchCopy( strDestPath, cchDest, strFilename ); return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); }
#pragma once #define _WIN32_DCOM #define _CRT_SECURE_NO_DEPRECATE #ifndef SAFE_DELETE_ARRAY #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } #endif #ifndef SAFE_RELEASE #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #endif #include <windows.h> #include <xaudio2.h> #include <strsafe.h> #include <shellapi.h> #include <mmsystem.h> #include <conio.h> #include "SDKwavefile.h" class CXAudioSystem { public: CXAudioSystem(void); ~CXAudioSystem(void); BOOL Init(void); HRESULT PlayPCM(LPCWSTR szFilename); protected: void CleanUp(void); private: IXAudio2* m_pXAudio2; IXAudio2MasteringVoice* m_pMasteringVoice; HRESULT FindMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename); };