流和循环MS ADPCM(WAVE_FORMAT_ADPCM)

时间:2015-06-24 14:47:34

标签: c++ audio-streaming xaudio2 adpcm

我尝试使用XAudio2流式传输MS ADPCM文件(在C ++中,但这个问题似乎与语言无关)。

该文件使用ADPCMEncode.exe进行编码,这将提供格式标记为WAVE_FORMAT_ADPCM的WAV文件。

与任何流一样,我创建一个IXAudio2SourceVoice(从文件的开头使用完整的ADPCMWAVEFORMAT)并在它请求时提供块对齐的缓冲区。数据似乎正常,直到循环时间。

循环读取器正如您所期望的那样:如果发生短读取,则将偏移量返回到开始并执行另一次读取以填充缓冲区的其余部分。适用于PCM,但对于MS ADPCM,有时语音会停止。它似乎停止要求更多缓冲区,因此耗尽并停止。

错误的时间有所不同。有时它会在数据循环后立即发生,有时在循环几次后发生。显然我需要通过XAUDIO2_BUFFER传递一些其他信息,但我找不到任何文档告诉我什么。

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

再一次,对互联网的尊严牺牲成果。 ;)

我意识到我错误地将样本循环WAV段用于ADPCM。它仍然在SAMPLES而不是字节,所以它需要转换成字节(因为ADPCM大约是25%的压缩,立体声样本是4个字节,这两个值是相似的,这就是欺骗我的原因> __< )。

每个块的样本很容易从块对齐中得出:

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;

如果循环点没有完全对齐,可以使用XAUDIO2_BUFFER的Play / LoopBegin / Length成员进行一些额外的摆弄,但只要你在原始WAV中正确对齐它们(如如果您不想要ADPCM的任何其他风格,那么提交压缩数据的块对齐就足够了。