Fluidization is a process in which we only need to maintain a small chunk of memory in memory to play audio files. This allows us to use very large audio files as background music without taking up a lot of memory. When we stream an audio file, the audio data is read from a piece of hard disk, rather than loading the entire file all at once. Streaming is done by asynchronously reading the audio data to the hard disk buffer queue. When a buffer is populated with data, it is submitted to source voice. When source voice plays a buffer, the buffer can be used again to read the data in the file. Looping through buffers in this way allows us to play back a large audio file by loading only a portion of the file's data. The streaming code should be placed in a separate thread so that you can sleep when you need to wait for a long time to read or to play an audio playback operation. When the audio playback is complete, we can use a callback to trigger the event to wake the thread.
Create a class that inherits the Ixaudio2voicecallback interface and implements it. in void Onbufferend (void*) {SetEvent (hbufferendevent);} The SetEvent method sets an event that, when the audio playback needs to wait, the thread will automatically go to sleep, and when the current buffer playback is complete, the event is triggered to wake the thread.
The main implementation of the example is to complete the COM initialization in the main thread, create the XAudio2 engine and ixaudio2masteringvoice, create the thread, pass the callback function of the streaming file to the thread, and pass the file name through the thread to the callback. Starts the thread, enters the callback function to parse the file, reads the file data, and plays it.
The buffers in the example are recycled so that the requirement to play a large audio file is met by maintaining only a small chunk of memory.
The size of each buffer is set to 10240, a total of 5 buffers, inside an array. By maintaining the array's index for recycling, the wait queue is guaranteed to be no more than 5 by Ixaudio2voicecallback, which guarantees that the data in the wait queue is not overwritten until the playback is complete. If the data is not played before it is finished, it will cause XAudio2 to crash.
DirectX provides an example of Streamaudios, but I didn't take it, and the code was re-implemented by myself. DirectX Example: http://download.csdn.net/detail/u011417605/9484060
Full code:
#pragma once#include "WaveFile.h" #include "XAudio2.h" #include <thread> #define Streambuffersize 10240//per buffer size # Define Buffernum 5//buffer count byte streambuffers[buffernum][streambuffersize];//buffer array class Streamingvoicecontext:public Ixaudio2voicecallback{public:handle hbufferendevent; Streamingvoicecontext (): hbufferendevent (CreateEvent (null, FALSE, FALSE, null)) {}~streamingvoicecontext () { CloseHandle (hbufferendevent); }void Onstreamend () {/*setevent (hbufferendevent); */}void Onvoiceprocessingpassend () {}void Onvoiceprocessingpassstart (UINT32 samplesrequired) {}//called When the voice had just finished playing an audio buffer . void Onbufferend (void * pbuffercontext) {SetEvent (hbufferendevent);} void Onbufferstart (void * pbuffercontext) {}void onloopend (void * pbuffercontext) {/*setevent (hbufferendevent); */}vo ID onvoiceerror (void * pbuffercontext, HRESULT Error) {}};ixaudio2 *pengine = null;int Currentbufferindex = 0;void Stream AudioFile (LPWSTR fileName)//thread callback {CwavefileWavefile; HRESULT hr = Wavefile.open (FileName, NULL, wavefile_read);//Load file if (FAILED (HR)) return; WaveFormatEx *waveformat = Wavefile.getformat ();//Get file format streamingvoicecontext Pcallback;ixaudio2sourcevoice * Psourcevoice = NULL;HR = Pengine->createsourcevoice (&psourcevoice, Waveformat, 0, 1.0f, &pCallBack);//Create Source Sound , which is used to submit data if (FAILED (HR)) Return;int fileSize = Wavefile.getsize ();//Gets the size of the file int currentpos = 0;while (Currentpos < FileSize) {DWORD size = Streambuffersize;hr = Wavefile.read (Streambuffers[currentbufferindex], size, &size);// Read the file contents if (FAILED (HR)) Break;currentpos + = size;//the size of the data that has been played xaudio2_buffer BUFFER = {0};//will read the file data, assign the value xaudio2_ Bufferbuffer.audiobytes = Size;buffer.paudiodata = STREAMBUFFERS[CURRENTBUFFERINDEX];HR = pSourceVoice-> Submitsourcebuffer (&buffer);//Commit memory Data if (FAILED (hr)) Break;hr = Psourcevoice->start (Xaudio2_commit_now);// Start source Sound if (FAILED (HR)) break; Xaudio2_voice_state state;psourcevoice->getstate (&state);//Gets the status while (state. Buffersqueued > BUFFERNUM-1)//Do not let the buffer's audio data overwrite {WaitForSingleObject (pcallback.hbufferendevent, INFINITE);p sourcevoice->getstate ( &state);} currentbufferindex++;//Cyclic utilization buffer currentbufferindex%= buffernum;} Xaudio2_voice_state State;while (Psourcevoice->getstate (&state), state. buffersqueued > 0)//wait for the data in the queue to complete, exit thread {WaitForSingleObject (pcallback.hbufferendevent, INFINITE);} Psourcevoice->destroyvoice ();//release resource} int main (int argc, char *argv[]) {HRESULT hr = CoInitializeEx (NULL, Coinit_multi threaded);;/ /com Initialize if (FAILED (HR)) return 0; hr = Xaudio2create (&pengine);//Create Engine if (FAILED (HR)) return 0; Ixaudio2masteringvoice *pmastervoice = NULL; hr = Pengine->createmasteringvoice (&pmastervoice);//Create Master sound, default is output current speaker if (FAILED (HR)) return 0; LPWSTR filename = l "f:\\ desktop \\TestSong.wav"; Std::thread t (streamaudiofile, filename); T.join (); fileName = l "f:\\ desktop \ \ Example2.wav "; Std::thread p (streamaudiofile, FileName);p. Join (); Pmastervoice->destroyvoice ();//Release Resources pengine->release ();//Release Resources CounInitialize ();//Release the resource return 0; }
AC qq:1245178753
SOURCE Download: http://download.csdn.net/detail/u011417605/9484075
This address: http://blog.csdn.net/u011417605/article/details/51087826
XAudio2 Learning to stream audio files