我正在使用speex对某些音频数据进行编码并通过UDP发送,并在另一侧对其进行解码。 我用speex运行了一些测试,并注意到如果我在编码后直接对数据包进行解码,则解码数据绝不会接近原始数据。缓冲区开头的大多数字节都是0。 因此,当我解码通过UDP发送的音频时,我得到的只是噪音。 这就是我编码音频的方式:
bool AudioEncoder::encode( float *raw, char *encoded_bits )
{
for ( size_t i = 0; i < 256; i++ )
this->_rfdata[i] = raw[i];
speex_bits_reset(&this->_bits);
speex_encode(this->_state, this->_rfdata, &this->_bits);
int bytesWritten = speex_bits_write(&this->_bits, encoded_bits, 512);
if (bytesWritten)
return true;
return false;
}
这就是我解码音频的方式:
float *f = new float[256];
// recvbuf is the buffer I pass to my recv function on the socket
speex_bits_read_from(&this->_bits, recvbuf, 512);
speex_decode(this->state, &this->_bits, f);
我查看了文档,我的大部分代码都来自speex网站的示例编码/解码示例。 我不确定我在这里缺少什么。
答案 0 :(得分:1)
我发现编码数据如此不同的原因。事实上,正如Paulo Scardine所说,它是一种有损压缩,并且该speex仅适用于160帧,所以当从portaudio获取数据到speex时,它需要是160帧的“数据包”。
答案 1 :(得分:1)
实际上讲话引入了音频数据的额外延迟,我通过反向工程发现:
narrow band : delay = 200 - framesize + lookahead = 200 - 160 + 40 = 80 samples
wide band : delay = 400 - framesize + lookahead = 400 - 320 + 143 = 223 samples
uwide band : delay = 800 - framesize + lookahead = 800 - 640 + 349 = 509 samples
由于前瞻用zereos初始化,你会发现前几个样本“接近零”。
要获得正确的时间,您必须先跳过这些样本,然后才能获得已经输入编解码器的实际音频数据。为什么会这样,我不知道。 speex的作者probal从不关心这个,因为speex用于流式传输,主要不是用于存储和恢复音频数据。 另一种解决方法(不浪费空间)是,在输入实际音频数据之前,将(帧延迟)零提供给编解码器,然后丢弃整个第一个speex帧。
我希望这能澄清一切。如果熟悉Speex的人读到这个,如果我错了,请随时纠正我。
编辑:实际上,解码器和编码器都具有前瞻性的时间。延迟的实际公式是:narrow band : delay = decoder_lh + encoder_lh = 40 + 40 = 80 samples
wide band : delay = decoder_lh + encoder_lh = 80 + 143 = 223 samples
uwide band : delay = decoder_lh + encoder_lh = 160 + 349 = 509 samples
答案 2 :(得分:0)
您可能希望在这里查看一些简单的编码/解码: http://www.speex.org/docs/manual/speex-manual/node13.html#SECTION001310000000000000000
由于您使用的是UDP,因此您也可以使用抖动缓冲区来重新排序数据包和内容。