Stream and loop MS ADPCM (WAVE_FORMAT_ADPCM)

926 views Asked by At

I'm trying to stream an MS ADPCM file using XAudio2 (in C++, but this problem doesn't appear to be language related).

The file is encoded with ADPCMEncode.exe, this gives a WAV file with a format tag of WAVE_FORMAT_ADPCM.

Like any stream, I create a IXAudio2SourceVoice (with the full ADPCMWAVEFORMAT from the start of the file) and feed it block-aligned buffers as it requests them. The data appears to be playing fine, until the time comes to loop.

The looping reader is as you would expect: If a short read happens, return the offset to the start and do another read to fill up the rest of the buffer. Fine for PCM, but for MS ADPCM sometimes the voice will stop. It appears to stop asking for more buffers, and so runs out and stops.

The timing of the error varies. Sometimes it happens as soon as the data loops, sometimes after looping several times. There's obviously some additional information I need to pass via the XAUDIO2_BUFFER, but I can't find any docs telling me what.

Can anybody point me in the right direction?

1

There are 1 answers

0
subi211 On

Once again, the sacrifice of dignity to the internet bears fruit. ;)

I realised I was using the sample loop WAV segment wrongly for ADPCM. It's still in SAMPLES not bytes, so it needs converting into bytes (as ADPCM is roughly 25% compression and a stereo sample is 4 bytes the two values are similar and that's what fooled me >__<).

Samples per block are easily worked out from the block align:

unsigned int samplesPerBlock = m_format.nBlockAlign - 12;

unsigned int startBlock = sampleLoop.start / samplesPerBlock;
unsigned int startBlockOffset = sampleLoop.start % samplesPerBlock;

unsigned int endBlock = sampleLoop.end / samplesPerBlock;
unsigned int endBlockOffset = sampleLoop.end % samplesPerBlock;

unsigned int loopStart = startBlock * m_format.nBlockAlign;
unsigned int loopLength = (endBlock - startBlock) * m_format.nBlockAlign;

There's some extra fiddling you can do with the Play/LoopBegin/Length members of XAUDIO2_BUFFER if the loop points don't exactly align, but as long as you properly align them in the original WAV (like you would for any other flavour of ADPCM) you won't need that, block alignment of the submitted compressed data will be enough.