我想制作低延迟的流音频。为此,我使用带有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;
}
谢谢。