Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Poznámka
Tento obsah platí jenom pro desktopové aplikace (a aby fungoval v aplikaci pro UPW), vyžadoval by revizi. Projděte si dokumentaci k CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerExa GetOverlappedResultEx. Podívejte se na ukázkovou aplikaci "XAudio2 audio stream effect" systému Windows 8 z nyní archivované Galerie ukázek sady Windows SDK.
V XAudio2 můžete streamovat zvuková data tím, že vytvoříte samostatné vlákno pro čtení vyrovnávací paměti zvukových dat přímo ve streamovacím vlákně a poté použijete zpětná volání pro ovládání tohoto vlákna.
Provádění čtení vyrovnávací paměti ve vlákně pro streamování
Chcete-li provádět čtení vyrovnávací paměti ve vlákně streamování, postupujte takto:
Vytvořte pole vyrovnávacích pamětí pro čtení.
#define STREAMING_BUFFER_SIZE 65536 #define MAX_BUFFER_COUNT 3 BYTE buffers[MAX_BUFFER_COUNT][STREAMING_BUFFER_SIZE];
Inicializace překrývající se struktury
Struktura se používá ke kontrole dokončení asynchronního čtení disku.
OVERLAPPED Overlapped = {0}; Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
Zavolejte funkci Start na zdrojový hlas, který bude přehrávat streamované audio.
hr = pSourceVoice->Start( 0, 0 );
Opakujte, dokud aktuální pozice čtení nepřekročí konec zvukového souboru.
CurrentDiskReadBuffer = 0; CurrentPosition = 0; while ( CurrentPosition < cbWaveSize ) { ... }
Ve smyčce udělejte toto:
Načtěte blok dat z disku do aktuální vyrovnávací paměti pro čtení.
DWORD dwRead; if( SUCCEEDED(hr) && 0 == ReadFile( hFile, pData, dwDataSize, &dwRead, pOverlapped ) ) hr = HRESULT_FROM_WIN32( GetLastError() ); DWORD cbValid = min( STREAMING_BUFFER_SIZE, cbWaveSize - CurrentPosition ); DWORD dwRead; if( 0 == ReadFile( hFile, buffers[CurrentDiskReadBuffer], STREAMING_BUFFER_SIZE, &dwRead, &Overlapped ) ) hr = HRESULT_FROM_WIN32( GetLastError() ); Overlapped.Offset += cbValid; //update the file position to where it will be once the read finishes CurrentPosition += cbValid;
Pomocí funkce GetOverlappedResult počkejte na událost, která signalizuje dokončení čtení.
DWORD NumberBytesTransferred; ::GetOverlappedResult(hFile,&Overlapped,&NumberBytesTransferred, TRUE);
Počkejte, než bude počet vyrovnávacích pamětí zařazených do fronty na hlasovém zdroji menší než počet vyrovnávacích pamětí určených pro čtení.
Stav zdrojového hlasu je zkontrolován pomocí funkce GetState.
XAUDIO2_VOICE_STATE state; while( pSourceVoice->GetState( &state ), state.BuffersQueued >= MAX_BUFFER_COUNT - 1) { WaitForSingleObject( Context.hBufferEndEvent, INFINITE ); }
Pomocí funkce SubmitSourceBuffer odešlete aktuální vyrovnávací paměti pro čtení do zvukového zdroje .
XAUDIO2_BUFFER buf = {0}; buf.AudioBytes = cbValid; buf.pAudioData = buffers[CurrentDiskReadBuffer]; if( CurrentPosition >= cbWaveSize ) { buf.Flags = XAUDIO2_END_OF_STREAM; } pSourceVoice->SubmitSourceBuffer( &buf );
Nastavte aktuální index vyrovnávací paměti pro čtení na další vyrovnávací paměť.
CurrentDiskReadBuffer++; CurrentDiskReadBuffer %= MAX_BUFFER_COUNT;
Po dokončení smyčky počkejte na přehrání zbývajících bufferů, které jsou ve frontě.
Po dokončení přehrávání zbývajících vyrovnávacích pamětí se zvuk zastaví a vlákno může být ukončeno nebo znovu použito ke streamování jiného zvuku.
XAUDIO2_VOICE_STATE state; while( pSourceVoice->GetState( &state ), state.BuffersQueued > 0 ) { WaitForSingleObjectEx( Context.hBufferEndEvent, INFINITE, TRUE ); }
Vytvoření třídy zpětného volání
Chcete-li vytvořit třídu pro zpětné volání, vytvořte třídu, která dědí z rozhraní IXAudio2VoiceCallback.
Třída by měla nastavit událost ve své metodě OnBufferEnd. To umožňuje, aby vlákno streamování přešlo do režimu spánku, dokud mu událost nesignalizuje, že XAudio2 dokončil čtení ze zvukové vyrovnávací paměti. Další informace o použití zpětných volání s XAudio2 naleznete v tématu Postupy: Použití zpětného volání zdrojového hlasu.
struct StreamingVoiceContext : public IXAudio2VoiceCallback
{
HANDLE hBufferEndEvent;
StreamingVoiceContext(): hBufferEndEvent( CreateEvent( NULL, FALSE, FALSE, NULL ) ){}
~StreamingVoiceContext(){ CloseHandle( hBufferEndEvent ); }
void OnBufferEnd( void* ){ SetEvent( hBufferEndEvent ); }
...
};
Související témata
-
Postupy: Vytvoření grafu základního zpracování zvuku
-
Jak na to: Použití callbacků ve zdrojových hlasových voláních