带Opus lib的Qt音频输入/输出

时间:2020-10-01 18:30:04

标签: c++ qt opus

我想制作低延迟的流音频。为此,我使用带有opus API的QAudioInput和QAudioOutput作为压缩库。现在,我通过写入输出驱动程序进行简单测试。

问题是我听到杂音,不知道问题出在哪里。我对Opus使用了很多测试。

我受到这个项目的启发:https://github.com/antonypro/AudioStreaming

main.cpp

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QIODevice* device { nullptr };
QBuffer buffer;

EncodeManager* encode = new EncodeManager(&a);

QAudioFormat format;
format.setSampleRate(48000);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);

QAudioDeviceInfo infoIn(QAudioDeviceInfo::defaultInputDevice());
qDebug() << infoIn.deviceName();
if (!infoIn.isFormatSupported(format)) {
    qWarning() << "Raw audio format not supported by backend, cannot play audio.";
    a.quit();
}

QAudioDeviceInfo infoOut(QAudioDeviceInfo::defaultOutputDevice());
qDebug() << infoOut.deviceName();
if (!infoOut.isFormatSupported(format)) {
    qWarning() << "Raw audio format not supported by backend, cannot play audio.";
    a.quit();
}

QAudioInput* audio_in = new QAudioInput(infoIn, format, &a);
QAudioOutput* audio_out = new QAudioOutput(infoOut, format, &a);

audio_in->setBufferSize(3000);
audio_out->setBufferSize(3000);

audio_in->setNotifyInterval(40);
audio_out->setNotifyInterval(40);

audio_in->start(&buffer);
device = audio_out->start();

device->open(QIODevice::ReadWrite);
buffer.open(QIODevice::WriteOnly);

auto consumAudio = [&](){
    auto len = buffer.buffer().size();

    qInfo()<< "Len: " << len;

    QMutex mutex;
    mutex.lock();

    if(len > 0) {
        QByteArray data_encoded = encode->encodeAudio(buffer.buffer());
        QByteArray  data_decoded =  encode->decodeAudio(data_encoded);

        device->write(data_decoded);

        buffer.buffer().clear();
        buffer.reset();
    }

    mutex.unlock();
};

QObject::connect(audio_in, &QAudioInput::notify, [&]() {consumAudio();});

return a.exec();
}

EncodeManager.h

class EncodeManager : public QObject
{
Q_OBJECT

public:
explicit EncodeManager(QObject *parent = nullptr);
~EncodeManager();

QByteArray encodeAudio(const QByteArray &pcm);
QByteArray decodeAudio(const QByteArray &data);

private:
int const m_buffer_size {480};
int const m_max_packet {1276};
int const m_channel {2};

OpusEncoder* m_encoder = nullptr;
OpusDecoder* m_decoder = nullptr;
};

EncodeManager.cpp

EncodeManager::EncodeManager(QObject *parent) : QObject(parent)
{
int error_encode {0};
int error_decode {0};

m_encoder = opus_encoder_create(48000, m_channel, OPUS_APPLICATION_AUDIO, &error_encode);
m_decoder = opus_decoder_create(48000, m_channel, &error_decode);
}

QByteArray EncodeManager::encodeAudio(const QByteArray &pcm)
{
QByteArray compressed_frame { m_max_packet, char(0) };

int compressed_size = opus_encode(m_encoder, reinterpret_cast<const opus_int16 *>(pcm.constData()), m_buffer_size, reinterpret_cast<unsigned char*> (compressed_frame.data()), m_max_packet);

compressed_frame.resize(compressed_size);

return compressed_frame;
}

QByteArray EncodeManager::decodeAudio(const QByteArray &data)
{
QByteArray decompressed_frame { int(sizeof(opus_int16)) * m_channel * m_buffer_size, char(0) };

opus_int32  decompressed_size = opus_decode(m_decoder, reinterpret_cast<const unsigned char*> (data.constData()), m_buffer_size, reinterpret_cast<opus_int16 *>(decompressed_frame.data()),  m_max_packet, 0);

int size = int(sizeof(opus_int16)) * m_channel * decompressed_size;

decompressed_frame.resize(size);

return decompressed_frame;
}

谢谢。

0 个答案:

没有答案
相关问题