summaryrefslogtreecommitdiff
path: root/plugin/src/Caelestia/audioprovider.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plugin/src/Caelestia/audioprovider.cpp176
1 files changed, 20 insertions, 156 deletions
diff --git a/plugin/src/Caelestia/audioprovider.cpp b/plugin/src/Caelestia/audioprovider.cpp
index becfb63..008e360 100644
--- a/plugin/src/Caelestia/audioprovider.cpp
+++ b/plugin/src/Caelestia/audioprovider.cpp
@@ -1,5 +1,6 @@
#include "audioprovider.hpp"
+#include "audiocollector.hpp"
#include "service.hpp"
#include <QAudioSource>
#include <QDebug>
@@ -9,121 +10,27 @@
#include <QObject>
#include <QThread>
#include <QVector>
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
namespace caelestia {
-AudioCollector::AudioCollector(AudioProvider* provider, QObject* parent)
+AudioProcessor::AudioProcessor(QObject* parent)
: QObject(parent)
- , m_source(nullptr)
- , m_device(nullptr)
- , m_provider(provider)
- , m_sampleRate(provider->sampleRate())
- , m_chunkSize(provider->chunkSize())
- , m_chunk(m_chunkSize)
- , m_chunkOffset(0) {}
-
-AudioCollector::~AudioCollector() {
- m_source->stop();
-}
-
-void AudioCollector::init() {
- QAudioFormat format;
- format.setSampleRate(m_sampleRate);
- format.setChannelCount(1);
- format.setSampleFormat(QAudioFormat::Int16);
-
- m_source = new QAudioSource(QMediaDevices::defaultAudioInput(), format, this);
- connect(m_source, &QAudioSource::stateChanged, this, &AudioCollector::handleStateChanged);
-};
-
-void AudioCollector::start() {
- if (!m_source) {
- return;
- }
-
- m_device = m_source->start();
- connect(m_device, &QIODevice::readyRead, this, &AudioCollector::loadChunk);
-}
-
-void AudioCollector::stop() {
- if (m_source) {
- m_source->stop();
- m_device = nullptr;
- }
-}
-
-void AudioCollector::loadChunk() {
- const QByteArray data = m_device->readAll();
- const int16_t* samples = reinterpret_cast<const int16_t*>(data.constData());
- const size_t count = static_cast<size_t>(data.size()) / sizeof(int16_t);
-
- size_t i = 0;
- while (i < count) {
- const int spaceLeft = m_chunkSize - m_chunkOffset;
- const auto toCopy = std::min<size_t>(static_cast<size_t>(spaceLeft), count - i);
-
- std::transform(samples + i, samples + i + toCopy, m_chunk.begin() + m_chunkOffset, [](int16_t sample) {
- return sample / 32768.0;
- });
-
- m_chunkOffset += toCopy;
- i += toCopy;
-
- if (m_chunkOffset == m_chunkSize) {
- if (std::any_of(m_chunk.constBegin(), m_chunk.constEnd(), [](double d) {
- return std::abs(d) > 1e-6;
- })) {
- m_provider->loadChunk(m_chunk);
- }
- m_chunkOffset = 0;
- }
- }
-}
-
-void AudioCollector::handleStateChanged(QtAudio::State state) const {
- if (state == QtAudio::StoppedState && m_source->error() != QtAudio::NoError) {
- switch (m_source->error()) {
- case QtAudio::OpenError:
- qWarning() << "AudioWorker: failed to open audio device";
- break;
- case QtAudio::IOError:
- qWarning() << "AudioWorker: an error occurred during read/write of audio device";
- break;
- case QtAudio::UnderrunError:
- qWarning() << "AudioWorker: audio data is not being fed to audio device fast enough";
- break;
- case QtAudio::FatalError:
- qCritical() << "AudioWorker: fatal error in audio device";
- break;
- default:
- break;
- }
- }
-}
-
-AudioProcessor::AudioProcessor(AudioProvider* provider, QObject* parent)
- : QObject(parent)
- , m_sampleRate(provider->sampleRate())
- , m_chunkSize(provider->chunkSize())
- , m_provider(provider) {}
+ , m_sampleRate(AudioCollector::instance()->sampleRate())
+ , m_chunkSize(AudioCollector::instance()->chunkSize())
+ , m_bufferSize(AudioCollector::instance()->bufferSize()) {}
AudioProcessor::~AudioProcessor() {
- if (m_timer) {
- m_timer->stop();
- }
+ stop();
}
void AudioProcessor::init() {
m_timer = new QTimer(this);
m_timer->setInterval(static_cast<int>(m_chunkSize * 1000.0 / m_sampleRate));
- connect(m_timer, &QTimer::timeout, this, &AudioProcessor::handleTimeout);
+ connect(m_timer, &QTimer::timeout, this, &AudioProcessor::process);
}
void AudioProcessor::start() {
+ AudioCollector::instance()->ref();
if (m_timer) {
m_timer->start();
}
@@ -133,60 +40,19 @@ void AudioProcessor::stop() {
if (m_timer) {
m_timer->stop();
}
+ AudioCollector::instance()->unref();
}
-void AudioProcessor::handleTimeout() {
- const QVector<double> chunk = m_provider->nextChunk();
- if (!chunk.isEmpty()) {
- processChunk(chunk);
- }
-}
-
-AudioProvider::AudioProvider(int sampleRate, int chunkSize, QObject* parent)
+AudioProvider::AudioProvider(QObject* parent)
: Service(parent)
- , m_sampleRate(sampleRate)
- , m_chunkSize(chunkSize)
- , m_collector(new AudioCollector(this))
, m_processor(nullptr)
- , m_collectorThread(new QThread(this))
- , m_processorThread(nullptr) {
- m_collector->moveToThread(m_collectorThread);
-
- connect(m_collectorThread, &QThread::started, m_collector, &AudioCollector::init);
- connect(m_collectorThread, &QThread::finished, m_collector, &AudioCollector::deleteLater);
- connect(m_collectorThread, &QThread::finished, m_collectorThread, &QThread::deleteLater);
-
- m_collectorThread->start();
-}
+ , m_thread(nullptr) {}
AudioProvider::~AudioProvider() {
- m_collectorThread->quit();
- if (m_processorThread) {
- m_processorThread->quit();
- m_processorThread->wait();
- }
- m_collectorThread->wait();
-}
-
-int AudioProvider::sampleRate() const {
- return m_sampleRate;
-}
-
-int AudioProvider::chunkSize() const {
- return m_chunkSize;
-}
-
-QVector<double> AudioProvider::nextChunk() {
- QMutexLocker lock(&m_mutex);
- if (m_chunks.isEmpty()) {
- return {};
+ if (m_thread) {
+ m_thread->quit();
+ m_thread->wait();
}
- return m_chunks.dequeue();
-}
-
-void AudioProvider::loadChunk(const QVector<double>& chunk) {
- QMutexLocker lock(&m_mutex);
- m_chunks.enqueue(chunk);
}
void AudioProvider::init() {
@@ -195,25 +61,23 @@ void AudioProvider::init() {
return;
}
- m_processorThread = new QThread(this);
- m_processor->moveToThread(m_processorThread);
+ m_thread = new QThread(this);
+ m_processor->moveToThread(m_thread);
- connect(m_processorThread, &QThread::started, m_processor, &AudioProcessor::init);
- connect(m_processorThread, &QThread::finished, m_processor, &AudioProcessor::deleteLater);
- connect(m_processorThread, &QThread::finished, m_processorThread, &QThread::deleteLater);
+ connect(m_thread, &QThread::started, m_processor, &AudioProcessor::init);
+ connect(m_thread, &QThread::finished, m_processor, &AudioProcessor::deleteLater);
+ connect(m_thread, &QThread::finished, m_thread, &QThread::deleteLater);
- m_processorThread->start();
+ m_thread->start();
}
void AudioProvider::start() {
- QMetaObject::invokeMethod(m_collector, "start", Qt::QueuedConnection);
if (m_processor) {
QMetaObject::invokeMethod(m_processor, "start", Qt::QueuedConnection);
}
}
void AudioProvider::stop() {
- QMetaObject::invokeMethod(m_collector, "stop", Qt::QueuedConnection);
if (m_processor) {
QMetaObject::invokeMethod(m_processor, "stop", Qt::QueuedConnection);
}