First try

This commit is contained in:
2019-08-25 18:22:31 +02:00
parent a0545d8fd6
commit c9ddad8e21
7 changed files with 366 additions and 0 deletions

73
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
};