Files
sonobulus/src/synth/Scope.cpp

77 lines
1.9 KiB
C++

#include "Scope.hpp"
#include <iostream>
ScopeBuffer::ScopeBuffer(QObject *parent) : QObject(parent) {
// timer is set in qml
}
ScopeBuffer::ScopeBuffer(ConfigService* config, LoggerService* logger, size_t size) :
config_(config), logger_(logger), buffer_(size) {
}
void ScopeBuffer::push(float sample) {
size_t w = writeIndex_.fetch_add(1, std::memory_order_relaxed);
buffer_[w % buffer_.size()] = sample;
}
void ScopeBuffer::read(std::vector<float>& out) {
size_t w = writeIndex_.load(std::memory_order_relaxed);
for(size_t i = 0; i < buffer_.size(); i++) {
size_t idx = (w + trigger_ + i * wavelength_ / out.size()) % buffer_.size();
out[i] = buffer_[idx];
}
}
Scope::Scope(QQuickItem *parent) : QQuickPaintedItem(parent) {
setAntialiasing(true);
}
void Scope::setBuffer(ScopeBuffer* scopeBuffer) {
scopeBuffer_ = scopeBuffer;
buffer_ = std::vector<float>(scopeBuffer_->size());
}
void Scope::paint(QPainter *painter) {
while(scopeBuffer_->spinlock()) {
// wait
}
if(scopeBuffer_ != nullptr) scopeBuffer_->read(buffer_);
// TODO: scale to max amplitude ? probably make it configurable if you want to make scope options
float maxAmp = 1.0f;
/*
for(float s : buffer_) {
maxAmp = std::max(maxAmp, std::abs(s));
}
*/
float scaleY = (height() * 0.45f) / maxAmp;
float midY = height() / 2.0f;
painter->fillRect(0, 0, width(), height(), QColor(20, 20, 20));
QPen pen;
pen.setWidthF(3.0f);
QColor green(50, 255, 70);
pen.setColor(green);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing);
for(size_t i = 1; i < buffer_.size(); i++) {
painter->drawLine(
i * width() / buffer_.size(),
midY + buffer_[i-1] * scaleY,
i * width() / buffer_.size(),
midY + buffer_[i] * scaleY
);
}
}