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;

(帯域幅、ビットレート、VBR)を使用して opus エンコーダーを構成しようとしましたopus_encode_ctlが、まったく機能しません。音質は依然としてひどいものです。

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 に答える