From cf6d60348ec61b3a4d3bf5706677469303cd4e88 Mon Sep 17 00:00:00 2001 From: Roland Rossgotterer Date: Fri, 20 Sep 2019 21:17:26 +0200 Subject: [PATCH] Decouple QAudioDevice buffer size from AFV 20 ms frame size Different QAudioDevice plugins have different default buffer sizes. In order to cope with bigger buffer sizes than the expected 20 ms, let the buffer be filled and push from it every 20 ms via timer. --- src/blackcore/afv/audio/input.cpp | 33 ++++++++++++++++++++----------- src/blackcore/afv/audio/input.h | 8 ++++++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/blackcore/afv/audio/input.cpp b/src/blackcore/afv/audio/input.cpp index e94f5a61f..8c08a23c1 100644 --- a/src/blackcore/afv/audio/input.cpp +++ b/src/blackcore/afv/audio/input.cpp @@ -21,13 +21,23 @@ namespace BlackCore { namespace Audio { + AudioInputBuffer::AudioInputBuffer(QObject *parent) : + QIODevice(parent) + {} + void AudioInputBuffer::start() { - open(QIODevice::WriteOnly); + open(QIODevice::WriteOnly | QIODevice::Unbuffered); + m_timerId = startTimer(20, Qt::PreciseTimer); } void AudioInputBuffer::stop() { + if (m_timerId > 0) + { + killTimer(m_timerId); + m_timerId = 0; + } close(); } @@ -43,14 +53,18 @@ namespace BlackCore { QByteArray buffer(data, static_cast(len)); m_buffer.append(buffer); + return len; + } + + void AudioInputBuffer::timerEvent(QTimerEvent *event) + { + Q_UNUSED(event); // 20 ms = 960 samples * 2 bytes = 1920 Bytes if (m_buffer.size() >= 1920) { emit frameAvailable(m_buffer.left(1920)); m_buffer.remove(0, 1920); } - - return len; } Input::Input(int sampleRate, QObject *parent) : @@ -107,11 +121,8 @@ namespace BlackCore } m_audioInput.reset(new QAudioInput(inputDevice, inputFormat)); - // We want 20 ms of buffer size - // 20 ms * nSamplesPerSec × nChannels × wBitsPerSample / 8 x 1000 - int bufferSize = 20 * inputFormat.sampleRate() * inputFormat.channelCount() * inputFormat.sampleSize() / (8 * 1000); - m_audioInput->setBufferSize(bufferSize); m_audioInputBuffer.start(); + m_audioInput->start(&m_audioInputBuffer); connect(&m_audioInputBuffer, &AudioInputBuffer::frameAvailable, this, &Input::audioInDataAvailable); @@ -130,7 +141,7 @@ namespace BlackCore void Input::audioInDataAvailable(const QByteArray &frame) { - const QVector samples = convertBytesTo16BitPCM(frame); + QVector samples = convertBytesTo16BitPCM(frame); int value = 0; for (qint16 &sample : samples) @@ -140,9 +151,9 @@ namespace BlackCore value = std::numeric_limits::max(); if (value < std::numeric_limits::min()) value = std::numeric_limits::min(); - samples = static_cast(value); + sample = static_cast(value); - sampleInput = qAbs(sampleInput); + qint16 sampleInput = qAbs(sample); m_maxSampleInput = qMax(qAbs(sampleInput), m_maxSampleInput); } @@ -155,7 +166,7 @@ namespace BlackCore { InputVolumeStreamArgs inputVolumeStreamArgs; qint16 maxInt = std::numeric_limits::max(); - inputVolumeStreamArgs.PeakRaw = m_maxSampleInput / maxInt; + inputVolumeStreamArgs.PeakRaw = static_cast(m_maxSampleInput) / maxInt; inputVolumeStreamArgs.PeakDB = (float)(20 * std::log10(inputVolumeStreamArgs.PeakRaw)); float db = qBound(minDb, inputVolumeStreamArgs.PeakDB, maxDb); float ratio = (db - minDb) / (maxDb - minDb); diff --git a/src/blackcore/afv/audio/input.h b/src/blackcore/afv/audio/input.h index 9e1ad1981..792017a16 100644 --- a/src/blackcore/afv/audio/input.h +++ b/src/blackcore/afv/audio/input.h @@ -32,7 +32,7 @@ namespace BlackCore Q_OBJECT public: - AudioInputBuffer() {} + AudioInputBuffer(QObject *parent = nullptr); void start(); void stop(); @@ -43,9 +43,13 @@ namespace BlackCore signals: void frameAvailable(const QByteArray &frame); + protected: + void timerEvent(QTimerEvent *event) override; + private: static constexpr qint64 frameSize = 960; QByteArray m_buffer; + int m_timerId = 0; }; struct OpusDataAvailableArgs @@ -97,7 +101,7 @@ namespace BlackCore int m_opusBytesEncoded = 0; double m_volume = 1.0; int m_sampleCount = 0; - qint16 m_maxSampleInput = 0; + qint16 m_maxSampleInput = 0.0; const int c_sampleCountPerEvent = 4800; const float maxDb = 0;