使用方法:從磁碟串流處理音效
注意
此內容僅適用于傳統型應用程式,且需要修訂才能在 Windows 市集應用程式中運作。 請參閱 CreateFile2、 CreateEventEx、 WaitForSingleObjectEx、 SetFilePointerEx和 GetOverlappedResultEx的檔。 請參閱Windows SDK範例庫中的 StreamEffect Windows 8範例。
您可以在 XAudio2 中串流音訊資料,方法是建立個別的執行緒,並在串流執行緒中執行音訊資料的緩衝區讀取,然後使用回呼來控制該執行緒。
在串流執行緒中執行緩衝區讀取
若要在串流執行緒中執行緩衝區讀取,請遵循下列步驟:
建立讀取緩衝區的陣列。
#define STREAMING_BUFFER_SIZE 65536 #define MAX_BUFFER_COUNT 3 BYTE buffers[MAX_BUFFER_COUNT][STREAMING_BUFFER_SIZE];
初始化重迭結構。
結構可用來檢查非同步磁片讀取何時完成。
OVERLAPPED Overlapped = {0}; Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
-
hr = pSourceVoice->Start( 0, 0 );
當目前的讀取位置未通過音訊檔案的結尾時迴圈。
CurrentDiskReadBuffer = 0; CurrentPosition = 0; while ( CurrentPosition < cbWaveSize ) { ... }
在 迴圈中,執行下列動作:
將磁片中的資料區塊讀取至目前的讀取緩衝區。
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;
使用 GetOverlappedResult 函式等候發出讀取完成訊號的事件。
DWORD NumberBytesTransferred; ::GetOverlappedResult(hFile,&Overlapped,&NumberBytesTransferred, TRUE);
等候 在來源語音 上排入佇列的緩衝區數目小於讀取緩衝區的數目。
XAUDIO2_VOICE_STATE state; while( pSourceVoice->GetState( &state ), state.BuffersQueued >= MAX_BUFFER_COUNT - 1) { WaitForSingleObject( Context.hBufferEndEvent, INFINITE ); }
使用SubmitSourceBuffer函式,將目前的讀取緩衝區提交至來源語音。
XAUDIO2_BUFFER buf = {0}; buf.AudioBytes = cbValid; buf.pAudioData = buffers[CurrentDiskReadBuffer]; if( CurrentPosition >= cbWaveSize ) { buf.Flags = XAUDIO2_END_OF_STREAM; } pSourceVoice->SubmitSourceBuffer( &buf );
將目前的讀取緩衝區索引設定為下一個緩衝區。
CurrentDiskReadBuffer++; CurrentDiskReadBuffer %= MAX_BUFFER_COUNT;
迴圈完成之後,請等候其餘的佇列緩衝區完成播放。
當其餘緩衝區完成播放時,音效會停止,而且執行緒可以結束或重複使用來串流另一個音效。
XAUDIO2_VOICE_STATE state; while( pSourceVoice->GetState( &state ), state.BuffersQueued > 0 ) { WaitForSingleObjectEx( Context.hBufferEndEvent, INFINITE, TRUE ); }
建立回呼類別
若要建立回呼類別,請建立繼承自 IXAudio2VoiceCallback 介面的類別。
類別應該在其 OnBufferEnd 方法中設定事件。 這可讓串流執行緒自行進入睡眠狀態,直到事件發出 XAudio2 從音訊緩衝區讀取完成的訊號為止。 如需搭配 XAudio2 使用回呼的詳細資訊,請參閱 如何:使用來源語音回呼。
struct StreamingVoiceContext : public IXAudio2VoiceCallback
{
HANDLE hBufferEndEvent;
StreamingVoiceContext(): hBufferEndEvent( CreateEvent( NULL, FALSE, FALSE, NULL ) ){}
~StreamingVoiceContext(){ CloseHandle( hBufferEndEvent ); }
void OnBufferEnd( void* ){ SetEvent( hBufferEndEvent ); }
...
};
相關主題
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應