add scope widget

This commit is contained in:
2025-12-26 20:30:41 -06:00
parent cc11cfe63a
commit 6b52f8fa4f
10 changed files with 194 additions and 13 deletions

View File

@@ -16,7 +16,7 @@ MainWindow::MainWindow(QWidget *parent) :
setFocusPolicy(Qt::StrongFocus);
// connect scope
ui_->scopeWidget->setScopeBuffer(&audioEngine_->scopeBuffer());
ui_->scope->setScopeBuffer(&audio_->scopeBuffer());
// Connect buttons to slots
connect(ui_->buttonReset, &QPushButton::clicked, this, &MainWindow::onResetClicked);

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>800</height>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
@@ -39,7 +39,7 @@
<property name="geometry">
<rect>
<x>150</x>
<y>130</y>
<y>230</y>
<width>500</width>
<height>360</height>
</rect>
@@ -55,7 +55,7 @@
<property name="geometry">
<rect>
<x>200</x>
<y>540</y>
<y>20</y>
<width>400</width>
<height>200</height>
</rect>

View File

@@ -0,0 +1,62 @@
#include "Scope.h"
#include "ui_Scope.h"
#include "../../../synth/ScopeBuffer.h"
#include <QPainter>
#include <iostream>
Scope::Scope(QWidget* parent) : QWidget(parent), ui_(new Ui::Scope), samples_(512) {
timer_.setInterval(16); // ~60 hz
connect(&timer_, &QTimer::timeout, this, QOverload<>::of(&Scope::update));
timer_.start();
}
Scope::~Scope() {
delete ui_;
}
void Scope::setScopeBuffer(ScopeBuffer* buffer) {
buffer_ = buffer;
}
void Scope::paintEvent(QPaintEvent*) {
if (!buffer_) return;
int32_t wavelength = buffer_->wavelength();
int32_t trigger = buffer_->trigger();
buffer_->read(samples_);
// auto scale amplitude. disabled because it hides the envelope effects
float maxAmp = 1.0f;
//for (float s : samples_) {
// maxAmp = std::max(maxAmp, std::abs(s));
//}
// TODO: if you get really bored you can start adding scope display options
float scaleY = (height() * 0.45f) / maxAmp;
float midY = height() / 2.0f;
QPainter p(this);
QColor gray(20, 20, 20);
p.fillRect(rect(), gray);
// got caught playing around
QPen pen;
pen.setWidthF(2.0f);
QColor green(50, 255, 70);
pen.setColor(green);
p.setPen(pen);
for (int32_t i = 1; i < samples_.size(); i++) {
p.drawLine(
(i - 1) * width() / samples_.size(),
midY - samples_[i - 1] * scaleY,
i * width() / samples_.size(),
midY - samples_[i] * scaleY
);
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <QWidget>
#include <QTimer>
#include <vector>
// forward declaration
class ScopeBuffer;
QT_BEGIN_NAMESPACE
namespace Ui { class Scope; }
QT_END_NAMESPACE
class Scope : public QWidget {
Q_OBJECT
public:
explicit Scope(QWidget* parent = nullptr);
~Scope();
void setScopeBuffer(ScopeBuffer* buffer);
protected:
// autocalled on QT's refresh loop
// scope drawing happens here
void paintEvent(QPaintEvent*) override;
private:
Ui::Scope* ui_;
ScopeBuffer* buffer_ = nullptr;
std::vector<float> samples_;
QTimer timer_;
};

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Scope</class>
<widget class="QWidget" name="Scope">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>200</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</widget>
<resources/>
<connections/>
</ui>