Added controls to change various parameters
This commit is contained in:
33
main.cpp
33
main.cpp
@@ -1,40 +1,13 @@
|
||||
#include <QApplication>
|
||||
#include <QAudioInput>
|
||||
|
||||
#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();
|
||||
}
|
||||
|
92
mainwindow.cpp
Normal file
92
mainwindow.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QAudioInput>
|
||||
#include <QAudioFormat>
|
||||
#include <QAudioDeviceInfo>
|
||||
#include <QButtonGroup>
|
||||
|
||||
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<int>(&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<int>(&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<QAudioInput>(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;
|
35
mainwindow.h
Normal file
35
mainwindow.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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<QAudioInput> m_input;
|
||||
|
||||
Device m_device;
|
||||
//FakeDevice m_fakeDevice;
|
||||
|
||||
const QList<QAudioDeviceInfo> m_audioDevices;
|
||||
};
|
159
mainwindow.ui
Normal file
159
mainwindow.ui
Normal file
@@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDevice">
|
||||
<property name="text">
|
||||
<string>Device:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxDevices"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxSamplerate"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonToggle">
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxFps"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxBlend">
|
||||
<property name="suffix">
|
||||
<string> blend</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonScale50">
|
||||
<property name="text">
|
||||
<string>X.5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonScale100">
|
||||
<property name="text">
|
||||
<string>X1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonScale200">
|
||||
<property name="text">
|
||||
<string>X2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonScale400">
|
||||
<property name="text">
|
||||
<string>X4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="OsciWidget" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>OsciWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>osciwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@@ -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
|
||||
|
@@ -5,10 +5,6 @@
|
||||
#include <QLine>
|
||||
|
||||
namespace {
|
||||
constexpr auto framerate = 60;
|
||||
constexpr auto blend = 190;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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<qint16>::max() / 2 * width() * 2) + (width() / 2);
|
||||
const qint32 y = (float(-i->y) / std::numeric_limits<qint16>::max() / 2 * height() * 2) + (height() / 2);
|
||||
const qint32 x = (float(i->x) / std::numeric_limits<qint16>::max() / 2 * width() / 2 * m_factor) + (width() / 2);
|
||||
const qint32 y = (float(-i->y) / std::numeric_limits<qint16>::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));
|
||||
}
|
||||
|
20
osciwidget.h
20
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<QPoint> m_lastPoint;
|
||||
|
||||
QElapsedTimer m_timer;
|
||||
};
|
||||
|
Reference in New Issue
Block a user