Portaudio + Opus:糟糕的音质

时间:2014-10-16 10:14:24

标签: c++ audio voip portaudio opus

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

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

  1. 从麦克风中获取声音
  2. 播放声音
  3. 声音质量非常好。

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

    1. 从麦克风获取声音
    2. 对声音进行编码
    3. 解码
    4. 播放
    5. 但是现在,声音质量绝对可怕(在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的内容?

1 个答案:

答案 0 :(得分:3)

我终于找到了解决方案。

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

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

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

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