S
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 schonmal
Fü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);
};