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 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);
    };
    

Log in to reply