Portaudio + Opus: ужасное качество звука

Я в настоящее время разрабатываю приложение 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), но это не работает вообще: качество звука все еще дерьмовое.

Даже если я изменю SAMPLE_RATE или FRAME_PER_BUFFER, качество звука не улучшится …

Я что-то пропустил относительно PortAudio / Opus?

3

Решение

Я наконец-то нашел решение.

Проблема не в Опусе, а в главном …

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

Здесь я передаю локальную переменную в мой поток вывода. Но выходной поток работает асинхронно: моя переменная была уничтожена до воспроизведения упакованного звука.

Использование указателей — это самый простой способ решения проблемы. Я лично решил немного изменить свой код.

3

Другие решения


По вопросам рекламы [email protected]