10 #include <QAudioDevice>
18 using namespace swift::misc::audio;
19 using namespace swift::sound;
21 namespace swift::core::afv::audio
23 CAudioInputBuffer::CAudioInputBuffer(QObject *parent) : QIODevice(parent)
25 this->setObjectName(
"CAudioInputBuffer");
32 if (!this->isOpen()) { open(QIODevice::WriteOnly | QIODevice::Unbuffered); }
46 m_buffer.append(data,
static_cast<int>(len));
47 const int byteCount = 1920 * m_format.channelCount();
48 while (m_buffer.size() > byteCount)
51 m_buffer.remove(0, byteCount);
57 : QObject(parent), m_sampleRate(sampleRate), m_encoder(sampleRate, 1, OPUS_APPLICATION_VOIP)
59 this->setObjectName(
"CInput");
65 if (qFuzzyCompare(m_gainRatio, gainRatio)) {
return false; }
66 m_gainRatio = gainRatio;
88 if (m_started) {
return; }
91 m_device = inputDevice;
93 QAudioFormat inputFormat;
94 inputFormat.setSampleRate(m_sampleRate);
95 inputFormat.setChannelCount(1);
96 inputFormat.setSampleFormat(QAudioFormat::Int16);
98 QAudioDevice selectedDevice = getLowestLatencyDevice(inputDevice, inputFormat);
99 m_inputFormat = inputFormat;
100 m_audioInput.reset(
new QAudioSource(selectedDevice, m_inputFormat));
102 else { m_audioInputBuffer->disconnect(); }
103 m_audioInputBuffer->
start(m_inputFormat);
104 const QString format = toQString(m_inputFormat);
105 CLogMessage(
this).
info(u
"Starting: '%1' with: %2") << selectedDevice.description() << format;
108 this->initMicrophoneMacOS();
110 this->initMicrophone();
115 void CInput::initMicrophoneMacOS()
118 if (status == CMacOSMicrophoneAccess::Authorized) { this->initMicrophone(); }
119 else if (status == CMacOSMicrophoneAccess::NotDetermined)
122 m_micAccess.requestAccess();
125 else {
CLogMessage(
this).
error(u
"Microphone access not granted. Voice input will not work."); }
131 if (!m_started) {
return; }
133 if (m_audioInput) { m_audioInput->stop(); }
134 m_audioInput.reset();
135 if (m_audioInputBuffer)
137 m_audioInputBuffer->
stop();
138 m_audioInputBuffer->deleteLater();
139 m_audioInputBuffer =
nullptr;
143 void CInput::audioInDataAvailable(
const QByteArray &frame)
145 static_assert(Q_BYTE_ORDER == Q_LITTLE_ENDIAN);
146 QVector<qint16> samples = convertBytesTo16BitPCM(frame);
148 if (m_inputFormat.channelCount() == 2) { samples = convertFromStereoToMono(samples); }
150 const double volume = m_gainRatio;
151 for (qint16 &sample : samples)
153 int value = qRound(sample * volume);
154 if (value > std::numeric_limits<qint16>::max()) value = std::numeric_limits<qint16>::max();
155 if (value < std::numeric_limits<qint16>::min()) value = std::numeric_limits<qint16>::min();
156 sample =
static_cast<qint16
>(value);
158 qint16 sampleInput = qAbs(sample);
159 m_maxSampleInput = qMax(qAbs(sampleInput), m_maxSampleInput);
163 const QByteArray encodedBuffer = m_encoder.
encode(samples, samples.size(), &length);
164 m_opusBytesEncoded += length;
166 m_sampleCount += samples.size();
167 if (m_sampleCount >= SampleCountPerEvent)
169 InputVolumeStreamArgs inputVolumeStreamArgs;
170 qint16 maxInt = std::numeric_limits<qint16>::max();
171 inputVolumeStreamArgs.PeakRaw =
static_cast<float>(m_maxSampleInput) / maxInt;
172 inputVolumeStreamArgs.PeakDB =
static_cast<float>(20 * std::log10(inputVolumeStreamArgs.PeakRaw));
173 double db = qBound(minDb, inputVolumeStreamArgs.PeakDB, maxDb);
174 double ratio = (db - minDb) / (maxDb - minDb);
175 if (ratio < 0.30) { ratio = 0.0; }
176 if (ratio > 1.0) { ratio = 1.0; }
177 inputVolumeStreamArgs.PeakVU = ratio;
180 m_maxSampleInput = 0;
183 OpusDataAvailableArgs opusDataAvailableArgs = { m_audioSequenceCounter++, encodedBuffer };
187 void CInput::initMicrophone()
189 m_audioInput->start(m_audioInputBuffer);
Class for emitting a log message.
void permissionRequestAnswered(bool granted)
User has answered the permission request popup.
AuthorizationStatus
Authorization status.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Value object encapsulating information of a audio device.
bool isInputDevice() const
Input device.
bool isValid() const
Valid audio device object?
QByteArray encode(const QVector< qint16 > &pcmSamples, int samplesLength, int *encodedLength)
Encode.
void setBitRate(int bitRate)
Bit rate.
Free functions in swift::misc.
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.