我尝试使用XAudio2流式传输MS ADPCM文件(在C ++中,但这个问题似乎与语言无关)。
该文件使用ADPCMEncode.exe进行编码,这将提供格式标记为WAVE_FORMAT_ADPCM的WAV文件。
与任何流一样,我创建一个IXAudio2SourceVoice(从文件的开头使用完整的ADPCMWAVEFORMAT)并在它请求时提供块对齐的缓冲区。数据似乎正常,直到循环时间。
循环读取器正如您所期望的那样:如果发生短读取,则将偏移量返回到开始并执行另一次读取以填充缓冲区的其余部分。适用于PCM,但对于MS ADPCM,有时语音会停止。它似乎停止要求更多缓冲区,因此耗尽并停止。
错误的时间有所不同。有时它会在数据循环后立即发生,有时在循环几次后发生。显然我需要通过XAUDIO2_BUFFER传递一些其他信息,但我找不到任何文档告诉我什么。
有人能指出我正确的方向吗?
答案 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的任何其他风格,那么提交压缩数据的块对齐就足够了。