From af43c1166e8ace50954dd1c6ac86769810104b53 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 6 Sep 2025 16:57:40 +1000 Subject: plugin: abstract audioprovider --- plugin/src/Caelestia/audioprovider.cpp | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 plugin/src/Caelestia/audioprovider.cpp (limited to 'plugin/src/Caelestia/audioprovider.cpp') diff --git a/plugin/src/Caelestia/audioprovider.cpp b/plugin/src/Caelestia/audioprovider.cpp new file mode 100644 index 0000000..0c6f4fd --- /dev/null +++ b/plugin/src/Caelestia/audioprovider.cpp @@ -0,0 +1,78 @@ +#include "audioprovider.hpp" + +#include "service.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace caelestia { + +AudioProvider::AudioProvider(int sampleRate, int hopSize, QObject* parent) + : Service(parent) + , m_hopSize(hopSize) { + QAudioFormat format; + format.setSampleRate(sampleRate); + format.setChannelCount(1); + format.setSampleFormat(QAudioFormat::Int16); + + m_source = new QAudioSource(QMediaDevices::defaultAudioInput(), format, this); + connect(m_source, &QAudioSource::stateChanged, this, &AudioProvider::handleStateChanged); +}; + +AudioProvider::~AudioProvider() { + m_source->stop(); + delete m_source; +} + +void AudioProvider::start() { + m_device = m_source->start(); + connect(m_device, &QIODevice::readyRead, this, &AudioProvider::processData); +} + +void AudioProvider::stop() { + m_source->stop(); + m_device = nullptr; +} + +template void AudioProvider::process(T* outBuf) { + const QByteArray data = m_device->readAll(); + const int16_t* samples = reinterpret_cast(data.constData()); + const size_t count = static_cast(data.size()) / sizeof(int16_t); + const size_t hopSize = static_cast(m_hopSize); + + for (size_t i = 0; i < count; ++i) { + outBuf[i % hopSize] = static_cast(samples[i] / 32768.0); + if ((i + 1) % hopSize == 0) { + consumeData(); + } + } +} +template void AudioProvider::process(float* outBuf); +template void AudioProvider::process(double* outBuf); + +void AudioProvider::handleStateChanged(QtAudio::State state) const { + if (state == QtAudio::StoppedState && m_source->error() != QtAudio::NoError) { + switch (m_source->error()) { + case QtAudio::OpenError: + qWarning() << "AudioProvider: failed to open audio device"; + break; + case QtAudio::IOError: + qWarning() << "AudioProvider: an error occurred during read/write of audio device"; + break; + case QtAudio::UnderrunError: + qWarning() << "AudioProvider: audio data is not being fed to audio device fast enough"; + break; + case QtAudio::FatalError: + qCritical() << "AudioProvider: fatal error in audio device"; + break; + default: + break; + } + } +} + +} // namespace caelestia -- cgit v1.2.3-freya