From ef15a753de4ccf969236ecaa15559e834598b208 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Sun, 25 Aug 2019 22:42:34 +0200 Subject: [PATCH] Added controls to change various parameters --- main.cpp | 33 +--------- mainwindow.cpp | 92 +++++++++++++++++++++++++++ mainwindow.h | 35 +++++++++++ mainwindow.ui | 159 +++++++++++++++++++++++++++++++++++++++++++++++ oscilloscope.pro | 5 ++ osciwidget.cpp | 93 ++++++++++++++++++++------- osciwidget.h | 20 ++++-- 7 files changed, 380 insertions(+), 57 deletions(-) create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui diff --git a/main.cpp b/main.cpp index 5574b20..b6a0e60 100644 --- a/main.cpp +++ b/main.cpp @@ -1,40 +1,13 @@ #include -#include -#include "device.h" -#include "osciwidget.h" +#include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); - const auto info = []() -> const QAudioDeviceInfo { - for (const auto &info : QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) - if (info.deviceName() == "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor") - return info; - Q_UNREACHABLE(); - }(); - - QAudioFormat format; - format.setSampleRate(44100); - format.setChannelCount(2); - format.setSampleSize(16); - format.setSampleType(QAudioFormat::SignedInt); - format.setCodec("audio/pcm"); - format.setByteOrder(QAudioFormat::LittleEndian); - - QAudioInput input(info, format); - input.setBufferSize(44100/60*4); - - OsciWidget widget; - widget.show(); - - Device device; - input.start(&device); - QObject::connect(&device, &Device::samplesReceived, &widget, &OsciWidget::samplesReceived); - - //FakeDevice fake; - //QObject::connect(&fake, &FakeDevice::samplesReceived, &widget, &OsciWidget::samplesReceived); + MainWindow mainWindow; + mainWindow.show(); return a.exec(); } diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..6209e75 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,92 @@ +#include "mainwindow.h" + +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + m_audioDevices(QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) +{ + m_ui.setupUi(this); + + connect(&m_device, &Device::samplesReceived, m_ui.widget, &OsciWidget::renderSamples); + + //connect(&m_fakeDevice, &FakeDevice::samplesReceived, m_ui.widget, &OsciWidget::samplesReceived); + + for (const auto &device : m_audioDevices) + m_ui.comboBoxDevices->addItem(device.deviceName()); + + for (const auto samplerate : { 44100, 48000, 96000, 192000 }) + m_ui.comboBoxSamplerate->addItem(tr("%0").arg(samplerate), samplerate); + + connect(m_ui.pushButtonToggle, &QAbstractButton::pressed, this, &MainWindow::toggle); + + for (const auto framerate : {15, 30, 50, 60}) + m_ui.comboBoxFps->addItem(tr("%0 FPS").arg(framerate), framerate); + + m_ui.comboBoxFps->setCurrentIndex(m_ui.comboBoxFps->findData(m_ui.widget->framerate())); + + connect(m_ui.comboBoxFps, &QComboBox::currentIndexChanged, this, [&combobox=*m_ui.comboBoxFps,&widget=*m_ui.widget](){ + widget.setFramerate(combobox.currentData().toInt()); + }); + + m_ui.spinBoxBlend->setValue(m_ui.widget->blend()); + + connect(m_ui.spinBoxBlend, qOverload(&QSpinBox::valueChanged), m_ui.widget, &OsciWidget::setBlend); + + auto buttonGroup = new QButtonGroup; + buttonGroup->setExclusive(true); + buttonGroup->addButton(m_ui.radioButtonScale50, 0); + buttonGroup->addButton(m_ui.radioButtonScale100, 1); + buttonGroup->addButton(m_ui.radioButtonScale200, 2); + buttonGroup->addButton(m_ui.radioButtonScale400, 3); + + connect(buttonGroup, qOverload(&QButtonGroup::buttonClicked), this, [&widget=*m_ui.widget](int index){ + float factor; + + switch (index) + { + case 0: factor = .5f; break; + case 1: factor = 1.f; break; + case 2: factor = 2.f; break; + case 3: factor = 4.f; break; + default: Q_UNREACHABLE(); + } + + widget.setFactor(factor); + }); + + toggle(); +} + +void MainWindow::toggle() +{ + if (m_input) + { + m_input = nullptr; + m_ui.comboBoxDevices->setEnabled(true); + m_ui.comboBoxSamplerate->setEnabled(true); + m_ui.pushButtonToggle->setText("▶"); + } + else + { + QAudioFormat format; + format.setSampleRate(m_ui.comboBoxSamplerate->currentData().toInt()); + format.setChannelCount(2); + format.setSampleSize(16); + format.setSampleType(QAudioFormat::SignedInt); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + + m_input = std::make_unique(m_audioDevices.at(m_ui.comboBoxDevices->currentIndex()), format); + m_input->start(&m_device); + m_input->setBufferSize(format.sampleRate()/60*sizeof(qint16)*2); + m_ui.comboBoxDevices->setEnabled(false); + m_ui.comboBoxSamplerate->setEnabled(false); + m_ui.pushButtonToggle->setText("▮▮"); + } +} + +MainWindow::~MainWindow() = default; diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..b05d94b --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include + +#include "device.h" +#include "ui_mainwindow.h" + +class QAudioInput; +class QAudioFormat; +class QAudioDeviceInfo; +namespace Ui { class MainWindow; } + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; + +private slots: + void toggle(); + +private: + Ui::MainWindow m_ui; + + std::unique_ptr m_input; + + Device m_device; + //FakeDevice m_fakeDevice; + + const QList m_audioDevices; +}; diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..3e89a73 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,159 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Device: + + + + + + + + + + + + + PushButton + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + blend + + + 255 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + X.5 + + + + + + + X1 + + + + + + + X2 + + + + + + + X4 + + + + + + + + + + + + + + 0 + 0 + 800 + 20 + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + OsciWidget + QWidget +
osciwidget.h
+ 1 +
+
+ + +
diff --git a/oscilloscope.pro b/oscilloscope.pro index 76a90fa..a812fec 100644 --- a/oscilloscope.pro +++ b/oscilloscope.pro @@ -6,10 +6,15 @@ DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000 SOURCES += \ device.cpp \ main.cpp \ + mainwindow.cpp \ osciwidget.cpp HEADERS += \ device.h \ + mainwindow.h \ osciwidget.h STATECHARTS += + +FORMS += \ + mainwindow.ui diff --git a/osciwidget.cpp b/osciwidget.cpp index 0b1d4e7..c7ffd10 100644 --- a/osciwidget.cpp +++ b/osciwidget.cpp @@ -5,10 +5,6 @@ #include namespace { -constexpr auto framerate = 60; -constexpr auto blend = 190; -} - template auto pythagoras(const T &dx, const T &dy) { @@ -19,15 +15,60 @@ auto pythagoras(const QLine &line) { return pythagoras(line.dx(), line.dy()); } - -OsciWidget::OsciWidget(QWidget *parent) : - QWidget(parent), m_timerId(startTimer(1000/framerate)) -{ - resizePixmap(); - m_timer.start(); } -void OsciWidget::samplesReceived(const SamplePair *begin, const SamplePair *end) +OsciWidget::OsciWidget(QWidget *parent) : + QWidget(parent) +{ + restartTimer(); + resizePixmap(); + createBlendPixmap(); +} + +int OsciWidget::framerate() const +{ + return m_framerate; +} + +int OsciWidget::blend() const +{ + return m_blend; +} + +float OsciWidget::factor() const +{ + return m_factor; +} + +void OsciWidget::setFramerate(int framerate) +{ + if (framerate == m_framerate) + return; + + qDebug() << "change framerate to" << framerate; + + m_framerate = framerate; + + restartTimer(); +} + +void OsciWidget::setBlend(int blend) +{ + if (blend == m_blend) + return; + + qDebug() << "change blend to" << blend; + + m_blend = blend; + createBlendPixmap(); +} + +void OsciWidget::setFactor(float factor) +{ + m_factor = factor; +} + +void OsciWidget::renderSamples(const SamplePair *begin, const SamplePair *end) { QPainter painter; painter.begin(&m_pixmap); @@ -38,8 +79,8 @@ void OsciWidget::samplesReceived(const SamplePair *begin, const SamplePair *end) for (auto i = begin; i < end; i++) { - const qint32 x = (float(i->x) / std::numeric_limits::max() / 2 * width() * 2) + (width() / 2); - const qint32 y = (float(-i->y) / std::numeric_limits::max() / 2 * height() * 2) + (height() / 2); + const qint32 x = (float(i->x) / std::numeric_limits::max() / 2 * width() / 2 * m_factor) + (width() / 2); + const qint32 y = (float(-i->y) / std::numeric_limits::max() / 2 * height() / 2 * m_factor) + (height() / 2); const QPoint p{x,y}; if (Q_LIKELY(m_lastPoint.has_value())) @@ -58,12 +99,6 @@ void OsciWidget::samplesReceived(const SamplePair *begin, const SamplePair *end) } painter.end(); - - if (m_timer.hasExpired(1000/framerate)) - { - repaint(); - m_timer.restart(); - } } void OsciWidget::paintEvent(QPaintEvent *event) @@ -85,7 +120,7 @@ void OsciWidget::timerEvent(QTimerEvent *event) { if (event->timerId() == m_timerId) { - //repaint(); + repaint(); } else QWidget::timerEvent(event); @@ -96,13 +131,25 @@ void OsciWidget::resizeEvent(QResizeEvent *event) Q_UNUSED(event) resizePixmap(); + createBlendPixmap(); +} + +void OsciWidget::restartTimer() +{ + if (m_timerId != -1) + killTimer(m_timerId); + + m_timerId = startTimer(1000/m_framerate); } void OsciWidget::resizePixmap() { m_pixmap = QPixmap(size()); m_pixmap.fill(QColor()); - - m_fadeoutPixmap = QPixmap(size()); - m_fadeoutPixmap.fill(QColor(blend, blend, blend)); +} + +void OsciWidget::createBlendPixmap() +{ + m_fadeoutPixmap = QPixmap(size()); + m_fadeoutPixmap.fill(QColor(m_blend, m_blend, m_blend)); } diff --git a/osciwidget.h b/osciwidget.h index 8c5f59b..64d2ab0 100644 --- a/osciwidget.h +++ b/osciwidget.h @@ -19,8 +19,16 @@ class OsciWidget : public QWidget public: explicit OsciWidget(QWidget *parent = nullptr); + int framerate() const; + int blend() const; + float factor() const; + public slots: - void samplesReceived(const SamplePair *begin, const SamplePair *end); + void setFramerate(int framerate); + void setBlend(int blend); + void setFactor(float factor); + + void renderSamples(const SamplePair *begin, const SamplePair *end); protected: void paintEvent(QPaintEvent *event) override; @@ -28,13 +36,17 @@ protected: void resizeEvent(QResizeEvent *event) override; private: + void restartTimer(); void resizePixmap(); + void createBlendPixmap(); + + int m_timerId{-1}; + int m_framerate{15}; + int m_blend{190}; + float m_factor{4.f}; - const int m_timerId; QPixmap m_pixmap; QPixmap m_fadeoutPixmap; std::optional m_lastPoint; - - QElapsedTimer m_timer; };