编码 Opus 时,Encoded Sound 会丢失数据

Posted

技术标签:

【中文标题】编码 Opus 时,Encoded Sound 会丢失数据【英文标题】:Encoded Sound loses data when encoding Opus 【发布时间】:2021-12-02 16:40:33 【问题描述】:

我正在尝试使用 Opus 对通过 PortAudio 记录的一些数据进行编码,因此每当我尝试对数据进行编码时,写入的数据都会丢失,因为 unsigned char 向量对于向量的每次迭代最终都是空的,原始数据是从 PortAudio 录制

这是我的结构:

typedef struct 
    int size;
    std::vector<unsigned char> *sound;
 AudioEnc;

typedef struct 
    int size;
    std::vector<float> sound;
 AudioData;

这是我的编码:

#define SAMPLE_RATE (48000)
#define FRAMES_PER_BUFFER (1920)
#define NUM_SECONDS (1)

    AudioEnc Opus::Encode(AudioData data)
    
        AudioEnc enc = .size = 0, .sound = new std::vector<unsigned char>;
        unsigned int max_size =  NUM_SECONDS * SAMPLE_RATE;
        float sound[max_size];
    
        enc.sound->resize(max_size);
        if (data.size == 0)
            enc.size = opus_encode_float(_encode, sound, FRAMES_PER_BUFFER, enc.sound->data(), max_size);
        else
            enc.size = opus_encode_float(_encode, data.sound.data(), FRAMES_PER_BUFFER, enc.sound->data(), max_size);
        return (enc);
    
    
    AudioData Opus::Decode(AudioEnc data)
    
        AudioData dec;
        dec.sound.resize(NUM_SECONDS * SAMPLE_RATE * 2);
        dec.size = opus_decode_float(_decode, data.sound->data(), data.size, dec.sound.data(), FRAMES_PER_BUFFER, 0) * 2;
        return (dec);
     

在 opus_encode_float 方法之后遍历 enc 时,sound 的所有值都是空的。

你们有什么想法吗?

【问题讨论】:

通常不需要动态分配std::vectors。在内部,它已经动态分配存储。还通过引用而不是副本传递您的变量 - 这实际上甚至可能导致问题,即AudioEnc Opus::Encode(const AudioData&amp; data) ... float sound[max_size]; 在技术上是非法的 - 只需将 max_size 设为 const 即可修复它。 另外,AudioEnc enc = .size = 0, .sound = new std::vector&lt;unsigned char&gt;; 正在混合 C 和 C++ 代码。 好的,所以根据大家的 cmets,我会尝试删除我的结构,所以我只能保留我的向量,我也会尝试通过引用传递所有内容。 【参考方案1】:

看起来问题在于您保留了两种尺寸。您正在混合 C 和 C++ 风格,这可能解释了 std::vector&lt;unsigned char&gt; *。但更重要的是,std::vector&lt;unsigned char&gt; 存储自己的大小,但您也存储单独的大小。而且看起来他们不同意。

修复很简单。不要将 .size 存储在 AudioEnc 和 AudioData 中。相反,请在向量上调用 .resize 以记住从 Opus 返回的大小。这将丢弃未使用的条目。

【讨论】:

所以它应该看起来像这样:enc.sound-&gt;resize(opus_encode_float(_encode, data.sound.data(), FRAMES_PER_BUFFER, enc.sound-&gt;data(), max_size)); ? @Diamonddedo:我觉得不错。

以上是关于编码 Opus 时,Encoded Sound 会丢失数据的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法比 DTX 更好地优化 Opus 中的静音期?

如何在 Java 中播放 Opus 编码的音频?

实时音频编解码之十二Opus编码-SILK编码-基频估计

实时音频编解码之十二Opus编码-SILK编码-基频估计

实时音频编解码之十一Opus编码

实时音频编解码之十五 Opus编码-CELT编码