scope checkpoint

This commit is contained in:
2026-06-13 16:36:33 -05:00
parent fcc24c5e3e
commit dbc1db37e1
4 changed files with 99 additions and 7 deletions

View File

@@ -10,7 +10,7 @@
#include "ConfigService.hpp" #include "ConfigService.hpp"
#include "synth/AudioEngine.hpp" #include "synth/AudioEngine.hpp"
#include "synth/KeyboardController.hpp" #include "synth/KeyboardController.hpp"
//#include "synth/ScopeBuffer.hpp" #include "synth/Scope.hpp"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
@@ -22,7 +22,7 @@ int main(int argc, char* argv[]) {
ConfigService config = ConfigService("config/sonobulus.cfg"); ConfigService config = ConfigService("config/sonobulus.cfg");
LoggerService logger = LoggerService(&config, "Engine"); LoggerService logger = LoggerService(&config, "Engine");
NoteQueue queue = NoteQueue(); NoteQueue queue = NoteQueue();
//ScopeBuffer scope = ScopeBuffer(); ScopeBuffer scopeBuffer = ScopeBuffer(512);
KeyboardController keyboard(&config, &logger, &queue); KeyboardController keyboard(&config, &logger, &queue);
Synth synth(&config, &logger, nullptr, &queue); Synth synth(&config, &logger, nullptr, &queue);
@@ -31,9 +31,11 @@ int main(int argc, char* argv[]) {
audioEngine.start(); audioEngine.start();
// attach backend gui components // attach backend gui components
//Scope scope; //scope.setBuffer(&scopeBuffer);
qmlRegisterType<TimerComponent>("AppDemo", 1, 0, "TimerComponent"); qmlRegisterType<TimerComponent>("AppDemo", 1, 0, "TimerComponent");
//qmlRegisterSingletonInstance("AppDemo", 1, 0, "Scope", &scope);
qmlRegisterType<Scope>("AppDemo", 1, 0, "Scope");
engine.rootContext()->setContextProperty("keyboardController", &keyboard); engine.rootContext()->setContextProperty("keyboardController", &keyboard);
// adds the TimerComponent type (exposed in qml as "TimerComponent") to the module named"AppDemo" (numbers mean version 1.0)
// load qml // load qml
//engine.loadFromModule("sonobulus", "Main"); //engine.loadFromModule("sonobulus", "Main");

View File

@@ -0,0 +1,47 @@
#include "Scope.hpp"
#include <iostream>
ScopeBuffer::ScopeBuffer(size_t size) : 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::paint(QPainter *painter) {
//std::cout << "onPaint" << std::endl;
static float phase = 0.0f;
phase += 0.1f;
float sample = sin(phase);
QPen pen(Qt::blue, 4);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing);
painter->drawRect(10, 10, width() - 20*sample, height() - 20*sample);
painter->setPen(QPen(Qt::red, 2));
painter->drawLine(0, 0, width(), height());
}

View File

@@ -1,6 +1,10 @@
#pragma once #pragma once
#include <QObject>
#include <QtQuick/QQuickPaintedItem>
#include <QtGui/QPainter>
#include <vector> #include <vector>
#include <atomic> #include <atomic>
@@ -14,14 +18,37 @@ public:
void push(float sample); void push(float sample);
void read(std::vector<float>& out); void read(std::vector<float>& out);
void setTrigger(size_t trigger) { trigger_ = trigger; }
void setWavelength(size_t wavelength) { wavelength_ = wavelength; }
size_t trigger() { return trigger_; }
size_t wavelength() { return wavelength_; }
void spinlock(bool lock) { spinlock_ = lock; }
size_t size() { return buffer_.size(); }
private: private:
std::vector<float> buffer_; std::vector<float> buffer_;
std::atomic<size_t> writeIndex_{0}; std::atomic<size_t> writeIndex_{0};
size_t trigger_ = 0; size_t trigger_ = 0;
uint32_t wavelgnth = 400; size_t wavelength_ = 400;
bool spinLock_ = false; bool spinlock_ = false;
};
class Scope : public QQuickPaintedItem {
Q_OBJECT
QML_ELEMENT
public:
explicit Scope(QQuickItem* parent = nullptr);
void paint(QPainter* painter) override;
void setBuffer(ScopeBuffer* scopeBuffer) { scopeBuffer_ = scopeBuffer; }
std::vector<float> buffer_;
ScopeBuffer* scopeBuffer_;
}; };

View File

@@ -6,8 +6,8 @@ import AppDemo
ApplicationWindow { ApplicationWindow {
visible: true visible: true
width: 600 width: 1200
height: 400 height: 800
title: "sonobulus" title: "sonobulus"
TimerComponent { TimerComponent {
@@ -49,4 +49,20 @@ ApplicationWindow {
} }
} }
Scope {
id: scope
width: 600
height: 300
// this timer triggers a constant update on the scope's canvas, calls its draw() each time
Timer {
id: updateTimer
interval: 16 // ~60 fps
running: true
repeat: true
onTriggered: scope.update()
}
}
} }