This playback process once was not very understanding, make a record, the Chinese part of the code, the original document is explained:
To move a stream of rendering data through the endpoint buffer, the client alternately calls theIaudiorenderclient::getbufferMethod and theIaudiorenderclient::releasebufferMethod. The client accesses the data in the endpoint buffer as a series of data packets. TheGetBufferCall retrieves, the next packet so, the client can fill it with rendering data. After writing the data to the packet, the client callsReleaseBufferTo add the completed packet to the rendering queue.
In the last sentence, the client can append the completed packets to the render queue by executing the ReleaseBuffer, but I expect to do some realse work, such as modifying a state.
-----------------------------------------------------------//Play a audio stream on the default audio rendering// Device. The Playaudiostream function allocates a shared//buffer big enough to hold one second of PCM audio data.//the function u Ses this buffer to the stream data to the//rendering device. The inner loop runs every second.//-----------------------------------------------------------//Reference_time Time units per second and per Millisecond#define reftimes_per_sec 10000000#define reftimes_per_millisec 10000#define EXI T_on_error (hres) if (FAILED (hres)) {goto Exit;} #define SAFE_RELEASE (Punk) if ((Punk)! = NULL) {(punk)->release (); (punk) = NULL; }const CLSID clsid_mmdeviceenumerator = __uuidof (mmdeviceenumerator); const IID Iid_immdeviceenumerator = __uuidof ( Immdeviceenumerator); Const IID iid_iaudioclient = __uuidof (iaudioclient); const IID iid_iaudiorenderclient = __uuidof ( Iaudiorenderclient); HRESULT Playaudiostream(Myaudiosource *pmysource) {HRESULT hr; Reference_time hnsrequestedduration = reftimes_per_sec; Reference_time hnsactualduration; Immdeviceenumerator *penumerator = NULL; Immdevice *pdevice = NULL; Iaudioclient *paudioclient = NULL; Iaudiorenderclient *prenderclient = NULL; WaveFormatEx *pwfx = NULL; UINT32 Bufferframecount; UINT32 numframesavailable; UINT32 numframespadding; BYTE *pdata; DWORD flags = 0; hr = CoCreateInstance (Clsid_mmdeviceenumerator, NULL, Clsctx_all, Iid_immdeviceenumerator, (void**) &penumerator); Exit_on_error (hr) hr = Penumerator->getdefaultaudioendpoint (Erender, Econsole, &pdevice) ; Exit_on_error (hr) hr = Pdevice->activate (iid_iaudioclient, Clsctx_all, NULL, (void**) &paudioclient); Exit_on_error (hr) hr = Paudioclient->getmixformat (&PWFX); Exit_on_error (hr) hr = Paudioclient->iniTialize (audclnt_sharemode_shared, 0, hnsrequested Duration, 0, PWFX, NULL); Exit_on_error (HR)//Tell the audio source which format to use. hr = Pmysource->setformat (PWFX); Exit_on_error (HR)//Get The actual size of the allocated buffer. hr = Paudioclient->getbuffersize (&bufferframecount); Exit_on_error (hr) hr = Paudioclient->getservice (iid_iaudiorenderclient, (void**) &prenderclient); Exit_on_error (HR)//////from this until the end, actually found, but also to modify the playback buffer, you have to fix the need for three steps, mainly here to analyze why he did so, in fact, this is his fixed process//Grab the entire Buffer for the initial fill operation. hr = Prenderclient->getbuffer (Bufferframecount, &pdata); Exit_on_error (HR)//Load The initial data into the shared buffer. hr = Pmysource->loaddata (Bufferframecount, PData, &flags); Exit_on_erROR (hr) hr = Prenderclient->releasebuffer (bufferframecount, flags); Exit_on_error (HR)//////end//Calculate The actual duration of the allocated buffer. Hnsactualduration = (double) reftimes_per_sec * bufferframecount/pwfx->nsamplespersec; hr = Paudioclient->start (); Start playing. Exit_on_error (HR)//Each loop fills about half of the shared buffer. while (flags! = audclnt_bufferflags_silent) {//Sleep for half the buffer duration. Sleep ((DWORD) (HNSACTUALDURATION/REFTIMES_PER_MILLISEC/2)); See how much buffer space is available. hr = paudioclient->getcurrentpadding (&numframespadding); Exit_on_error (hr) numframesavailable = bufferframecount-numframespadding; Grab all the available space in the shared buffer. hr = Prenderclient->getbuffer (numframesavailable, &pdata); Exit_on_error (HR)//Get next 1/2-second of data from the audio souRce. hr = Pmysource->loaddata (numframesavailable, PData, &flags); Exit_on_error (hr) hr = Prenderclient->releasebuffer (numframesavailable, flags); Exit_on_error (HR)}//Wait for the last data in the buffer to play before stopping. Sleep ((DWORD) (HNSACTUALDURATION/REFTIMES_PER_MILLISEC/2)); hr = Paudioclient->stop (); Stop playing. Exit_on_error (HR) Exit:cotaskmemfree (PWFX); Safe_release (Penumerator) safe_release (pdevice) safe_release (paudioclient) safe_release (pRenderClient) return HR;}
Windows Core Audio APIs