mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-16 18:35:35 +08:00
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.
This commit is contained in:
committed by
Mat Sutcliffe
parent
1deaf1ca8b
commit
cf6d60348e
@@ -21,13 +21,23 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
namespace Audio
|
namespace Audio
|
||||||
{
|
{
|
||||||
|
AudioInputBuffer::AudioInputBuffer(QObject *parent) :
|
||||||
|
QIODevice(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
void AudioInputBuffer::start()
|
void AudioInputBuffer::start()
|
||||||
{
|
{
|
||||||
open(QIODevice::WriteOnly);
|
open(QIODevice::WriteOnly | QIODevice::Unbuffered);
|
||||||
|
m_timerId = startTimer(20, Qt::PreciseTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioInputBuffer::stop()
|
void AudioInputBuffer::stop()
|
||||||
{
|
{
|
||||||
|
if (m_timerId > 0)
|
||||||
|
{
|
||||||
|
killTimer(m_timerId);
|
||||||
|
m_timerId = 0;
|
||||||
|
}
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,14 +53,18 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
QByteArray buffer(data, static_cast<int>(len));
|
QByteArray buffer(data, static_cast<int>(len));
|
||||||
m_buffer.append(buffer);
|
m_buffer.append(buffer);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioInputBuffer::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
// 20 ms = 960 samples * 2 bytes = 1920 Bytes
|
// 20 ms = 960 samples * 2 bytes = 1920 Bytes
|
||||||
if (m_buffer.size() >= 1920)
|
if (m_buffer.size() >= 1920)
|
||||||
{
|
{
|
||||||
emit frameAvailable(m_buffer.left(1920));
|
emit frameAvailable(m_buffer.left(1920));
|
||||||
m_buffer.remove(0, 1920);
|
m_buffer.remove(0, 1920);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Input::Input(int sampleRate, QObject *parent) :
|
Input::Input(int sampleRate, QObject *parent) :
|
||||||
@@ -107,11 +121,8 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_audioInput.reset(new QAudioInput(inputDevice, inputFormat));
|
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_audioInputBuffer.start();
|
||||||
|
|
||||||
m_audioInput->start(&m_audioInputBuffer);
|
m_audioInput->start(&m_audioInputBuffer);
|
||||||
connect(&m_audioInputBuffer, &AudioInputBuffer::frameAvailable, this, &Input::audioInDataAvailable);
|
connect(&m_audioInputBuffer, &AudioInputBuffer::frameAvailable, this, &Input::audioInDataAvailable);
|
||||||
|
|
||||||
@@ -130,7 +141,7 @@ namespace BlackCore
|
|||||||
|
|
||||||
void Input::audioInDataAvailable(const QByteArray &frame)
|
void Input::audioInDataAvailable(const QByteArray &frame)
|
||||||
{
|
{
|
||||||
const QVector<qint16> samples = convertBytesTo16BitPCM(frame);
|
QVector<qint16> samples = convertBytesTo16BitPCM(frame);
|
||||||
|
|
||||||
int value = 0;
|
int value = 0;
|
||||||
for (qint16 &sample : samples)
|
for (qint16 &sample : samples)
|
||||||
@@ -140,9 +151,9 @@ namespace BlackCore
|
|||||||
value = std::numeric_limits<qint16>::max();
|
value = std::numeric_limits<qint16>::max();
|
||||||
if (value < std::numeric_limits<qint16>::min())
|
if (value < std::numeric_limits<qint16>::min())
|
||||||
value = std::numeric_limits<qint16>::min();
|
value = std::numeric_limits<qint16>::min();
|
||||||
samples = static_cast<qint16>(value);
|
sample = static_cast<qint16>(value);
|
||||||
|
|
||||||
sampleInput = qAbs(sampleInput);
|
qint16 sampleInput = qAbs(sample);
|
||||||
m_maxSampleInput = qMax(qAbs(sampleInput), m_maxSampleInput);
|
m_maxSampleInput = qMax(qAbs(sampleInput), m_maxSampleInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +166,7 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
InputVolumeStreamArgs inputVolumeStreamArgs;
|
InputVolumeStreamArgs inputVolumeStreamArgs;
|
||||||
qint16 maxInt = std::numeric_limits<qint16>::max();
|
qint16 maxInt = std::numeric_limits<qint16>::max();
|
||||||
inputVolumeStreamArgs.PeakRaw = m_maxSampleInput / maxInt;
|
inputVolumeStreamArgs.PeakRaw = static_cast<float>(m_maxSampleInput) / maxInt;
|
||||||
inputVolumeStreamArgs.PeakDB = (float)(20 * std::log10(inputVolumeStreamArgs.PeakRaw));
|
inputVolumeStreamArgs.PeakDB = (float)(20 * std::log10(inputVolumeStreamArgs.PeakRaw));
|
||||||
float db = qBound(minDb, inputVolumeStreamArgs.PeakDB, maxDb);
|
float db = qBound(minDb, inputVolumeStreamArgs.PeakDB, maxDb);
|
||||||
float ratio = (db - minDb) / (maxDb - minDb);
|
float ratio = (db - minDb) / (maxDb - minDb);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace BlackCore
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioInputBuffer() {}
|
AudioInputBuffer(QObject *parent = nullptr);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
@@ -43,9 +43,13 @@ namespace BlackCore
|
|||||||
signals:
|
signals:
|
||||||
void frameAvailable(const QByteArray &frame);
|
void frameAvailable(const QByteArray &frame);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr qint64 frameSize = 960;
|
static constexpr qint64 frameSize = 960;
|
||||||
QByteArray m_buffer;
|
QByteArray m_buffer;
|
||||||
|
int m_timerId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OpusDataAvailableArgs
|
struct OpusDataAvailableArgs
|
||||||
@@ -97,7 +101,7 @@ namespace BlackCore
|
|||||||
int m_opusBytesEncoded = 0;
|
int m_opusBytesEncoded = 0;
|
||||||
double m_volume = 1.0;
|
double m_volume = 1.0;
|
||||||
int m_sampleCount = 0;
|
int m_sampleCount = 0;
|
||||||
qint16 m_maxSampleInput = 0;
|
qint16 m_maxSampleInput = 0.0;
|
||||||
|
|
||||||
const int c_sampleCountPerEvent = 4800;
|
const int c_sampleCountPerEvent = 4800;
|
||||||
const float maxDb = 0;
|
const float maxDb = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user