summaryrefslogtreecommitdiff
path: root/plugin/src
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-09-08 23:12:25 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-09-08 23:12:25 +1000
commitdc42e4f38e731cda0651540b4629f3e196792a85 (patch)
tree944904da920a152c4203528e3e08b1df2ee891d0 /plugin/src
parentnix: remove cava dep (diff)
downloadcaelestia-shell-dc42e4f38e731cda0651540b4629f3e196792a85.tar.gz
caelestia-shell-dc42e4f38e731cda0651540b4629f3e196792a85.tar.bz2
caelestia-shell-dc42e4f38e731cda0651540b4629f3e196792a85.zip
plugin/ac: use double buffer
Double buffer instead of circular buffer
Diffstat (limited to '')
-rw-r--r--plugin/src/Caelestia/audiocollector.cpp80
-rw-r--r--plugin/src/Caelestia/audiocollector.hpp14
-rw-r--r--plugin/src/Caelestia/audioprovider.cpp8
-rw-r--r--plugin/src/Caelestia/audioprovider.hpp6
4 files changed, 36 insertions, 72 deletions
diff --git a/plugin/src/Caelestia/audiocollector.cpp b/plugin/src/Caelestia/audiocollector.cpp
index cf3a673..036a383 100644
--- a/plugin/src/Caelestia/audiocollector.cpp
+++ b/plugin/src/Caelestia/audiocollector.cpp
@@ -2,12 +2,10 @@
#include "service.hpp"
#include <QDebug>
-#include <QVector>
#include <algorithm>
#include <cstdint>
#include <mutex>
#include <pipewire/pipewire.h>
-#include <qmutex.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/latency-utils.h>
#include <stop_token>
@@ -157,13 +155,14 @@ unsigned int PipeWireWorker::nextPowerOf2(unsigned int n) {
return n;
}
-AudioCollector::AudioCollector(uint32_t sampleRate, uint32_t chunkSize, uint32_t bufferSize, QObject* parent)
+AudioCollector::AudioCollector(uint32_t sampleRate, uint32_t chunkSize, QObject* parent)
: Service(parent)
- , m_buffer(bufferSize, 0.0f)
- , m_bufferIndex(bufferSize)
+ , m_buffer1(chunkSize)
+ , m_buffer2(chunkSize)
+ , m_readBuffer(&m_buffer1)
+ , m_writeBuffer(&m_buffer2)
, m_sampleRate(sampleRate)
- , m_chunkSize(chunkSize)
- , m_bufferSize(bufferSize) {}
+ , m_chunkSize(chunkSize) {}
AudioCollector::~AudioCollector() {
stop();
@@ -185,72 +184,49 @@ uint32_t AudioCollector::chunkSize() const {
return m_chunkSize;
}
-uint32_t AudioCollector::bufferSize() const {
- return m_bufferSize;
-}
-
void AudioCollector::clearBuffer() {
- std::lock_guard<std::mutex> lock(m_bufferMutex);
- std::fill(m_buffer.begin(), m_buffer.end(), 0.0f);
- m_bufferIndex = m_bufferSize;
+ auto* writeBuffer = m_writeBuffer.load(std::memory_order_relaxed);
+ std::fill(writeBuffer->begin(), writeBuffer->end(), 0.0f);
+
+ auto* oldRead = m_readBuffer.exchange(writeBuffer, std::memory_order_acq_rel);
+ m_writeBuffer.store(oldRead, std::memory_order_release);
}
void AudioCollector::loadChunk(const int16_t* samples, uint32_t count) {
- std::lock_guard<std::mutex> lock(m_bufferMutex);
-
- while (count > 0) {
- const auto spaceToEnd = m_bufferSize - m_bufferIndex;
- const auto toCopy = (count < spaceToEnd) ? count : spaceToEnd;
+ if (count > m_chunkSize) {
+ count = m_chunkSize;
+ }
- std::transform(samples, samples + toCopy, m_buffer.begin() + m_bufferIndex, [](int16_t sample) {
- return sample / 32768.0f;
- });
+ auto* writeBuffer = m_writeBuffer.load(std::memory_order_relaxed);
+ std::transform(samples, samples + count, writeBuffer->begin(), [](int16_t sample) {
+ return sample / 32768.0f;
+ });
- m_bufferIndex = (m_bufferIndex + toCopy) % m_bufferSize;
- samples += toCopy;
- count -= toCopy;
- }
+ auto* oldRead = m_readBuffer.exchange(writeBuffer, std::memory_order_acq_rel);
+ m_writeBuffer.store(oldRead, std::memory_order_release);
}
uint32_t AudioCollector::readChunk(float* out, uint32_t count) {
- std::lock_guard<std::mutex> lock(m_bufferMutex);
-
- if (count == 0 || count > m_bufferSize) {
- count = m_bufferSize;
+ if (count == 0 || count > m_chunkSize) {
+ count = m_chunkSize;
}
- const auto start = (m_bufferIndex + m_bufferSize - count) % m_bufferSize;
- const auto firstChunk = std::min(count, m_bufferSize - start);
-
- std::copy(m_buffer.begin() + start, m_buffer.begin() + start + firstChunk, out);
-
- if (firstChunk < count) {
- std::copy(m_buffer.begin(), m_buffer.begin() + (count - firstChunk), out + firstChunk);
- }
+ auto* readBuffer = m_readBuffer.load(std::memory_order_acquire);
+ std::memcpy(out, readBuffer->data(), count * sizeof(float));
return count;
}
uint32_t AudioCollector::readChunk(double* out, uint32_t count) {
- std::lock_guard<std::mutex> lock(m_bufferMutex);
-
- if (count == 0 || count > m_bufferSize) {
- count = m_bufferSize;
+ if (count == 0 || count > m_chunkSize) {
+ count = m_chunkSize;
}
- const auto start = (m_bufferIndex + m_bufferSize - count) % m_bufferSize;
- const auto firstChunk = std::min(count, m_bufferSize - start);
-
- std::transform(m_buffer.begin() + start, m_buffer.begin() + start + firstChunk, out, [](float sample) {
+ auto* readBuffer = m_readBuffer.load(std::memory_order_acquire);
+ std::transform(readBuffer->begin(), readBuffer->begin() + count, out, [](float sample) {
return static_cast<double>(sample);
});
- if (firstChunk < count) {
- std::transform(m_buffer.begin(), m_buffer.begin() + (count - firstChunk), out + firstChunk, [](float sample) {
- return static_cast<double>(sample);
- });
- }
-
return count;
}
diff --git a/plugin/src/Caelestia/audiocollector.hpp b/plugin/src/Caelestia/audiocollector.hpp
index d60736f..420452c 100644
--- a/plugin/src/Caelestia/audiocollector.hpp
+++ b/plugin/src/Caelestia/audiocollector.hpp
@@ -2,6 +2,7 @@
#include "service.hpp"
#include <QObject>
+#include <atomic>
#include <cstdint>
#include <mutex>
#include <pipewire/pipewire.h>
@@ -43,15 +44,13 @@ class AudioCollector : public Service {
Q_OBJECT
public:
- explicit AudioCollector(
- uint32_t sampleRate = 44100, uint32_t chunkSize = 512, uint32_t bufferSize = 512, QObject* parent = nullptr);
+ explicit AudioCollector(uint32_t sampleRate = 44100, uint32_t chunkSize = 512, QObject* parent = nullptr);
~AudioCollector();
static AudioCollector* instance();
[[nodiscard]] uint32_t sampleRate() const;
[[nodiscard]] uint32_t chunkSize() const;
- [[nodiscard]] uint32_t bufferSize() const;
void clearBuffer();
void loadChunk(const int16_t* samples, uint32_t count);
@@ -63,13 +62,14 @@ private:
inline static std::mutex s_mutex;
std::jthread m_thread;
- std::vector<float> m_buffer;
- uint32_t m_bufferIndex;
- std::mutex m_bufferMutex;
+ std::vector<float> m_buffer1;
+ std::vector<float> m_buffer2;
+ std::atomic<std::vector<float>*> m_readBuffer;
+ std::atomic<std::vector<float>*> m_writeBuffer;
+ uint32_t m_sampleCount;
const uint32_t m_sampleRate;
const uint32_t m_chunkSize;
- const uint32_t m_bufferSize;
void start() override;
void stop() override;
diff --git a/plugin/src/Caelestia/audioprovider.cpp b/plugin/src/Caelestia/audioprovider.cpp
index 008e360..1b0eed3 100644
--- a/plugin/src/Caelestia/audioprovider.cpp
+++ b/plugin/src/Caelestia/audioprovider.cpp
@@ -2,22 +2,16 @@
#include "audiocollector.hpp"
#include "service.hpp"
-#include <QAudioSource>
#include <QDebug>
-#include <QIODevice>
-#include <QMediaDevices>
-#include <QMutexLocker>
#include <QObject>
#include <QThread>
-#include <QVector>
namespace caelestia {
AudioProcessor::AudioProcessor(QObject* parent)
: QObject(parent)
, m_sampleRate(AudioCollector::instance()->sampleRate())
- , m_chunkSize(AudioCollector::instance()->chunkSize())
- , m_bufferSize(AudioCollector::instance()->bufferSize()) {}
+ , m_chunkSize(AudioCollector::instance()->chunkSize()) {}
AudioProcessor::~AudioProcessor() {
stop();
diff --git a/plugin/src/Caelestia/audioprovider.hpp b/plugin/src/Caelestia/audioprovider.hpp
index 51ee930..1edefff 100644
--- a/plugin/src/Caelestia/audioprovider.hpp
+++ b/plugin/src/Caelestia/audioprovider.hpp
@@ -1,14 +1,9 @@
#pragma once
#include "service.hpp"
-#include <QAudioSource>
-#include <QIODevice>
-#include <QMutex>
#include <QObject>
-#include <QQueue>
#include <QThread>
#include <QTimer>
-#include <QVector>
#include <cstdint>
#include <qqmlintegration.h>
@@ -26,7 +21,6 @@ public:
protected:
uint32_t m_sampleRate;
uint32_t m_chunkSize;
- uint32_t m_bufferSize;
private:
QTimer* m_timer;