4

我目前正在开发一个 VOIP 应用程序。为此,我使用 PortAudio 库来检索和播放声音,并使用 Opus 库来编码和解码声音包。

目前,我成功地使用了 PortAudio。我的程序只是做:

  1. 从麦克风获取声音
  2. 播放声音

音质绝对好。

我现在正在尝试对声音数据包进行编码和解码。我编写了一个 EncodeManagerClass 来做到这一点,我的程序现在这样做:

  1. 从麦克风获取声音
  2. 编码声音
  3. 解码它
  4. 回放

但是现在,音质绝对是可怕的(而且在 VOIP 应用程序中显然是有问题的)。

这是我的EncodeManager课:

class EncodeManager {

    // ctor - dtor
    public:
        EncodeManager(void);
        ~EncodeManager(void);

    // coplien form
    private:
        EncodeManager(const EncodeManager &) {}
        const EncodeManager &operator=(const EncodeManager &) { return *this; }

    // encode - decode
    public:
        Sound::Encoded  encode(const Sound::Decoded &sound);
        Sound::Decoded  decode(const Sound::Encoded &sound);

    // attributes
    private:
        OpusEncoder *mEncoder;
        OpusDecoder *mDecoder;

};

这是源文件:

EncodeManager::EncodeManager(void) {
    int error;

    mEncoder = opus_encoder_create(Sound::SAMPLE_RATE, Sound::NB_CHANNELS, OPUS_APPLICATION_VOIP, &error);
    if (error != OPUS_OK)
        throw new SoundException("fail opus_encoder_create");

    mDecoder = opus_decoder_create(Sound::SAMPLE_RATE, Sound::NB_CHANNELS, &error);
    if (error != OPUS_OK)
        throw new SoundException("fail opus_decoder_create");
}

EncodeManager::~EncodeManager(void) {
    if (mEncoder)
        opus_encoder_destroy(mEncoder);

    if (mDecoder)
        opus_decoder_destroy(mDecoder);
}

Sound::Encoded  EncodeManager::encode(const Sound::Decoded &sound) {
    Sound::Encoded encoded;

    encoded.buffer = new unsigned char[sound.size];
    encoded.size = opus_encode_float(mEncoder, sound.buffer, Sound::FRAMES_PER_BUFFER, encoded.buffer, sound.size);

    if (encoded.size < 0)
        throw new SoundException("fail opus_encode_float");

    return encoded;
}

Sound::Decoded  EncodeManager::decode(const Sound::Encoded &sound) {
    Sound::Decoded decoded;

    decoded.buffer = new float[Sound::FRAMES_PER_BUFFER * Sound::NB_CHANNELS];
    decoded.size = opus_decode_float(mDecoder, sound.buffer, sound.size, decoded.buffer, Sound::FRAMES_PER_BUFFER, 0);

    if (decoded.size < 0)
        throw new SoundException("fail opus_decode_float");

    return decoded;
}

这是我的主要内容:

int main(void) {
    SoundInputDevice input;
    SoundOutputDevice output;
    EncodeManager encodeManager;

    input.startStream();
    output.startStream();

    while (true) {
        Sound::Decoded *sound;

        input >> sound;
        if (sound) {
            Sound::Encoded encodedSound = encodeManager.encode(*sound);
            Sound::Decoded decodedSound = encodeManager.decode(encodedSound);
            output << &decodedSound;
        }
    }

    return 0;
}

附加信息:

const int   SAMPLE_RATE = 48000;
const int   NB_CHANNELS = 2;
const int   FRAMES_PER_BUFFER = 480;

我尝试使用opus_encode_ctl(带宽、比特率、VBR)配置 opus 编码器,但它根本不起作用:音质仍然很糟糕。

即使我更改了 SAMPLE_RATE 或 FRAME_PER_BUFFER,音质也不会提高...

我是否错过了有关 PortAudio/Opus 的内容?

4

1 回答 1

3

我终于找到了解决办法。

问题不是来自 Opus,而是来自主要...

if (sound) {
  Sound::Encoded encodedSound = encodeManager.encode(*sound);
  Sound::Decoded decodedSound = encodeManager.decode(encodedSound);
  output << &decodedSound;
 }

在这里,我将一个局部变量传递给我的输出流。但是输出流是异步工作的:所以我的变量在播放声音之前就被销毁了。

使用指针是解决问题的最简单方法。我个人决定重构一点我的代码。

于 2014-10-19T14:21:32.550 回答