2

我正在使用 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 网站的示例编码/解码示例。我不确定我在这里缺少什么。

4

3 回答 3

1

我找到了编码数据如此不同的原因。事实上,正如 Paulo Scardine 所说,这是一种有损压缩,而且 speex 仅适用于 160 帧,因此当从 portaudio 获取数据到 speex 时,它需要通过 160 帧的“数据包”。

于 2010-11-30T20:43:57.327 回答
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

由于前瞻是用零初始化的,因此您观察到前几个样本“接近零”。

为了获得正确的时间,您必须在获得输入编解码器的实际音频数据之前跳过这些样本。为什么会这样,我不知道。speex 的作者 Probalby 从未关心过这一点,因为 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
于 2012-04-06T20:14:53.500 回答
0

您可能想在这里查看一些简单的编码/解码: http ://www.speex.org/docs/manual/speex-manual/node13.html#SECTION001310000000000000000

由于您使用的是 UDP,您还可以使用抖动缓冲区来重新排序数据包和内容。

于 2010-11-25T20:34:31.070 回答