代码之家  ›  专栏  ›  技术社区  ›  dotminic

speex解码出错

  •  2
  • dotminic  · 技术社区  · 14 年前

    我正在使用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网站的示例编码/解码示例。 我不知道我错过了什么。

    3 回复  |  直到 14 年前
        1
  •  1
  •   dotminic    14 年前

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

        2
  •  1
  •   Thilo Köhler    12 年前

    实际上,语音会给音频数据带来额外的延迟,我通过逆向工程发现:

    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
    

    因为lookahead是用zereos初始化的,所以您观察到前几个样本是“接近于零”。

    要获得正确的计时,必须先跳过这些示例,然后才能将实际的音频数据馈送到编解码器中。为什么,我不知道。可能speex的作者从来都不关心这个问题,因为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
    
        3
  •  0
  •   dmck    14 年前

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

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