Added controls to change various parameters

This commit is contained in:
2019-08-25 22:42:34 +02:00
parent c9ddad8e21
commit ef15a753de
7 changed files with 380 additions and 57 deletions

View File

@@ -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
View 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
View 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
View 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>

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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;
};