我正在尝试使用XAudio2(在C++中,但这个问题似乎与语言无关)流式传输MS ADPCM文件。
该文件使用ADPCMEncode.exe进行编码,这将提供一个WAV文件,其格式标记为WAVE_format_ADCPM。
像任何流一样,我创建了一个IXAudio2SourceVoice(从文件开始使用完整的ADPCMWAVEFORMAT),并在它请求时向它提供块对齐的缓冲区。数据似乎播放得很好,直到时间循环。
循环读取器正如您所期望的:如果发生短读取,请将偏移量返回到起始位置,然后再进行一次读取以填充缓冲区的其余部分。PCM很好,但对于MS ADPCM,有时语音会停止。它似乎不再要求更多的缓冲区了,所以用完了就停了下来。
错误发生的时间各不相同。有时数据一循环就会发生这种情况,有时是在循环几次之后。很明显,我需要通过XAUDIO2_BUFFER传递一些额外的信息,但我找不到任何文档告诉我什么。
有人能给我指正确的方向吗?
再一次,对互联网尊严的牺牲结出了果实。)
我意识到我错误地将采样环路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一样),你就不需要了,提交的压缩数据的块对齐就足够了。