Hmm... to err on the side of caution, let me make sure I understand correctly. The following is a naïve approach: APOProcess call You are handed You do You output 1 448 samples Append 448 samples to incoming queue Incoming queue now has 448 samples Outgoing queue is empty 448 samples of silence 2 448 samples Append 448 samples to incoming queue Process 768 samples Output 448 samples Incoming queue now has 128 samples Outgoing queue now has 320 samples 448 samples of data 3 448 samples Append 448 samples to incoming queue Incoming queue now has 576 samples Outgoing queue now has 320 samples 448 samples of silence 4 448 samples Append 448 samples to incoming queue Process 768 samples Output 448 samples Incoming queue now has 256 samples Outgoing queue now has 640 samples 448 samples of data This approach won't work; you're alternating between outputting data and silence, which will cause glitchiness. Instead, adopt a fixed delay equal to your internal processing buffer size by pre-filling your output queue with 768 samples of silence. APOProcess call You are handed You do You output 1 448 samples Append 448 samples to incoming queue Incoming queue now has 448 samples Output 448 samples of silence Outgoing queue now has 320 samples of silence 448 samples of silence 2 448 samples Append 448 samples to incoming queue Process 768 samples Output 448 samples 320 of silence 128 of processed data Incoming queue now has 128 samples Outgoing queue now has 640 samples 320 samples of silence 128 of processed data 3 448 samples Append 448 samples to incoming queue Incoming queue now has 576 samples Output 448 samples Outgoing queue now has 192 samples 448 samples of processed data 4 448 samples Append 448 samples to incoming queue Process 768 samples Output 448 samples Incoming queue now has 256 samples Outgoing queue now has 512 samples 448 samples of processed data Eventually you will get a final APOProcess call (though you won't know it at the time.) Your incoming queue and your outgoing queue will still have data in them. That's fine; the APO is under no obligation to flush its internal queues, or to let Windows know what the state of its internal queues are, other than by implementing IAudioProcessingObject::GetLatency(). Since your latency is 768 samples, your GetLatency implementation should return 1.0 * 768 * HNS_PER_SECOND / WAVEFORMATEX.nSamplesPerSec; for 44.1 data, this is 174150 hundred-nanoseconds, or 17.4 ms. From: wdmaudiodev-bounce@xxxxxxxxxxxxx [mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx] On Behalf Of Abhinav Singh Sent: Wednesday, December 17, 2014 10:41 AM To: wdmaudiodev@xxxxxxxxxxxxx Subject: [wdmaudiodev] Re: buffering samples in an APO I totally forgot to implement GetLatency(..)..will add it to the APO. However, my problem is slightly different. I have tried to explain it clearer with an example below: * I am maintaining my own internal input and output buffer(separate from the FLOAT32 buffer point passed to the APOProcess(..) function. * At 44.1 kHz, I will get 448 samples per call to APOProcess(). * However, since my DSP algorithm only works with say exactly 768 samples, i will internally buffer the input received from APOProcess(...) until i have enough samples to process. I am also maintaining an internal output buffer where i will store the processed audio samples. * I process audio samples when the samples count in my internal buffer exceeds 767 and store the processed audio stream in my internal output buffer. * If i have enough samples in my internal output buffer(>=448),i will copy to APOProcess(..)'s output buffer otherwise i just set the first 448 samples in the APOProcess(..)'s output buffer with zero. * So the very first call to APOProces(...), i will just buffer the input and send zeros as the output. * However during the second call to APOProcess(..) i will have enough data to process and also send valid output(not zeros). * Now, at the very end , my own internal input and output buffer might have some samples leftover and i was wondering if there are any workaround around this buffering problem without changing the DSP algorithm. ________________________________ From: soccerl@xxxxxxxxxxxxx<mailto:soccerl@xxxxxxxxxxxxx> To: wdmaudiodev@xxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxx> Subject: [wdmaudiodev] Re: buffering samples in an APO Date: Tue, 16 Dec 2014 00:13:35 +0000 Is this a 100% repro? Which OS version is it? An APO has no idea on when the stream will end. If an audio application stops its streaming before the end of stream, I am not sure whether APO could do anything with this situation. From: wdmaudiodev-bounce@xxxxxxxxxxxxx<mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx> [mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx] On Behalf Of Matthew van Eerde Sent: Monday, December 15, 2014 10:23 AM To: wdmaudiodev@xxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxx> Subject: [wdmaudiodev] Re: buffering samples in an APO Make sure you implement IAudioProcessingObject::GetLatency(...), and report the delay between your input and output. If an app cares about its sound playing all the way through to the very last byte, the design is for the IAudioClient to pad silence onto the end of the stream, and keep pumping silence until IAudioClock indicates that the very last byte has made it all the way through the speaker. From: wdmaudiodev-bounce@xxxxxxxxxxxxx<mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx> [mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx] On Behalf Of Abhinav Singh Sent: Monday, December 15, 2014 10:12 AM To: wdmaudiodev@xxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxx> Subject: [wdmaudiodev] buffering samples in an APO I am trying to integrate a DSP algorithm with my GFX APO which requires a fixed number of samples greater than the number of samples i get every time the Audio Engine calls the APOProcess() function of my APO. So i buffer the samples until i have the required number of samples and feed the audio engine zeros until i have valid output to feed to the engine. This works but there is a loss of few samples at the very end(some samples remain unprocessed in the input buffer while some are left over in the output buffer ). Is there any workaround to this problem?