First try
This commit is contained in:
73
.gitignore
vendored
Normal file
73
.gitignore
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
47
device.cpp
Normal file
47
device.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QTimerEvent>
|
||||||
|
|
||||||
|
Device::Device(QObject *parent) :
|
||||||
|
QIODevice(parent)
|
||||||
|
{
|
||||||
|
setOpenMode(QIODevice::WriteOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 Device::readData(char *data, qint64 maxlen)
|
||||||
|
{
|
||||||
|
qFatal("oida");
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 Device::writeData(const char *data, qint64 len)
|
||||||
|
{
|
||||||
|
Q_ASSERT(len % sizeof(SamplePair) == 0);
|
||||||
|
emit samplesReceived(reinterpret_cast<const SamplePair*>(data),
|
||||||
|
reinterpret_cast<const SamplePair*>(data + (len/sizeof(SamplePair))));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
FakeDevice::FakeDevice(QObject *parent) :
|
||||||
|
QObject(parent), m_timerId(startTimer(1000/60))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeDevice::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
if (event->timerId() == m_timerId)
|
||||||
|
{
|
||||||
|
std::array<SamplePair, 44100/60> samples;
|
||||||
|
for (SamplePair &pair : samples)
|
||||||
|
{
|
||||||
|
pair.x = std::sin(m_dingsDesHaltHochZaehlt) * std::numeric_limits<qint16>::max();
|
||||||
|
pair.y = std::cos(m_dingsDesHaltHochZaehlt) * std::numeric_limits<qint16>::max();
|
||||||
|
m_dingsDesHaltHochZaehlt += 0.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit samplesReceived(samples.begin(), samples.end());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QObject::timerEvent(event);
|
||||||
|
}
|
43
device.h
Normal file
43
device.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#define qvoid void
|
||||||
|
|
||||||
|
struct SamplePair {
|
||||||
|
qint16 x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Device : public QIODevice
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Device(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void samplesReceived(const SamplePair *begin, const SamplePair *end);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
qint64 readData(char *data, qint64 maxlen) override;
|
||||||
|
qint64 writeData(const char *data, qint64 len) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FakeDevice : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FakeDevice(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void samplesReceived(const SamplePair *begin, const SamplePair *end);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
qvoid timerEvent(QTimerEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_dingsDesHaltHochZaehlt;
|
||||||
|
const int m_timerId;
|
||||||
|
};
|
40
main.cpp
Normal file
40
main.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <QApplication>
|
||||||
|
#include <QAudioInput>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "osciwidget.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);
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
15
oscilloscope.pro
Normal file
15
oscilloscope.pro
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
QT = core gui widgets multimedia
|
||||||
|
|
||||||
|
CONFIG += c++17
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
device.cpp \
|
||||||
|
main.cpp \
|
||||||
|
osciwidget.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
device.h \
|
||||||
|
osciwidget.h
|
||||||
|
|
||||||
|
STATECHARTS +=
|
108
osciwidget.cpp
Normal file
108
osciwidget.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#include "osciwidget.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <QLine>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr auto framerate = 60;
|
||||||
|
constexpr auto blend = 190;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto pythagoras(const T &dx, const T &dy)
|
||||||
|
{
|
||||||
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
QPainter painter;
|
||||||
|
painter.begin(&m_pixmap);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Plus);
|
||||||
|
|
||||||
|
QPen pen;
|
||||||
|
pen.setWidth(2);
|
||||||
|
|
||||||
|
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 QPoint p{x,y};
|
||||||
|
|
||||||
|
if (Q_LIKELY(m_lastPoint.has_value()))
|
||||||
|
{
|
||||||
|
auto dist = pythagoras(QLine(*m_lastPoint, p));
|
||||||
|
if (dist < 1)
|
||||||
|
dist = 1;
|
||||||
|
|
||||||
|
pen.setColor(QColor(0, 1./dist*255, 0));
|
||||||
|
painter.setPen(pen);
|
||||||
|
|
||||||
|
painter.drawLine(*m_lastPoint, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastPoint = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
if (m_timer.hasExpired(1000/framerate))
|
||||||
|
{
|
||||||
|
repaint();
|
||||||
|
m_timer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsciWidget::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event)
|
||||||
|
|
||||||
|
QPainter painter;
|
||||||
|
painter.begin(this);
|
||||||
|
painter.drawPixmap(0, 0, m_pixmap);
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
painter.begin(&m_pixmap);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||||
|
painter.drawPixmap(0, 0, m_fadeoutPixmap);
|
||||||
|
painter.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsciWidget::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
if (event->timerId() == m_timerId)
|
||||||
|
{
|
||||||
|
//repaint();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QWidget::timerEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsciWidget::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event)
|
||||||
|
|
||||||
|
resizePixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsciWidget::resizePixmap()
|
||||||
|
{
|
||||||
|
m_pixmap = QPixmap(size());
|
||||||
|
m_pixmap.fill(QColor());
|
||||||
|
|
||||||
|
m_fadeoutPixmap = QPixmap(size());
|
||||||
|
m_fadeoutPixmap.fill(QColor(blend, blend, blend));
|
||||||
|
}
|
40
osciwidget.h
Normal file
40
osciwidget.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QTimerEvent>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
class OsciWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OsciWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void samplesReceived(const SamplePair *begin, const SamplePair *end);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resizePixmap();
|
||||||
|
|
||||||
|
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