1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-26 10:29:31 +00:00

Makes sure the timer really, really is on a different thread.

Thereby allows me substantially to reduce audio latency.
This commit is contained in:
Thomas Harte 2020-06-14 23:22:00 -04:00
parent 530ff7471d
commit d08ffd6c8b
5 changed files with 102 additions and 25 deletions

73
OSBindings/Qt/.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

View File

@ -1,4 +1,4 @@
QT += core gui multimedia quickwidgets
QT += core gui multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

View File

@ -63,7 +63,15 @@ void MainWindow::open() {
}
MainWindow::~MainWindow() {
// Stop the timer
// Stop the audio output, and its thread.
if(audioOutput) {
audioOutput->stop();
audioThread.quit();
while(audioThread.isRunning());
}
// Stop the timer.
timer.reset();
}
@ -142,7 +150,7 @@ void MainWindow::launchMachine() {
// Install audio output if required.
const auto audio_producer = machine->audio_producer();
if(audio_producer) {
static constexpr size_t samplesPerBuffer = 2048; // TODO: select this dynamically; it's very high.
static constexpr size_t samplesPerBuffer = 256; // TODO: select this dynamically.
const auto speaker = audio_producer->get_speaker();
if(speaker) {
const QAudioDeviceInfo &defaultDeviceInfo = QAudioDeviceInfo::defaultOutputDevice();
@ -175,8 +183,7 @@ void MainWindow::launchMachine() {
// If this is a timed machine, start up the timer.
const auto timedMachine = machine->timed_machine();
if(timedMachine) {
timer->setMachine(timedMachine, &machineMutex);
timer->start();
timer->startWithMachine(timedMachine, &machineMutex);
}
} break;

View File

@ -6,21 +6,23 @@
#include <QDebug>
Timer::Timer(QObject *parent) : QObject(parent) {
// Set up the emulation timer. Bluffer's guide: the QTimer will post an
// event to an event loop. QThread is a thread with an event loop.
// My class, Timer, will be wired up to receive the QTimer's events.
timer = std::make_unique<QTimer>(this);
timer->setInterval(1);
thread.setFunction([this] {
// Set up the emulation timer. Bluffer's guide: the QTimer will post an
// event to an event loop. QThread is a thread with an event loop.
// My class, Timer, will be wired up to receive the QTimer's events.
timer = std::make_unique<QTimer>(&thread);
timer->setInterval(1);
thread = std::make_unique<QThread>(this);
moveToThread(thread.get());
connect(timer.get(), SIGNAL(timeout()), this, SLOT(tick()));
connect(timer.get(), SIGNAL(timeout()), this, SLOT(tick()), Qt::DirectConnection);
timer->start();
});
}
void Timer::setMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex) {
void Timer::startWithMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex) {
this->machine = machine;
this->machineMutex = machineMutex;
thread.start();
}
void Timer::tick() {
@ -33,14 +35,9 @@ void Timer::tick() {
machine->run_for(double(duration) / 1e9);
}
void Timer::start() {
thread->start();
timer->start();
}
Timer::~Timer() {
// Stop the timer, then ask the QThread to exit and wait for it to do so.
timer->stop();
thread->exit();
while(thread->isRunning());
thread.exit();
while(thread.isRunning());
}

View File

@ -8,6 +8,7 @@
#include <QTimer>
#include "../../Machines/Utility/MachineForTarget.hpp"
#include "functionthread.h"
class Timer : public QObject
{
@ -17,8 +18,7 @@ class Timer : public QObject
explicit Timer(QObject *parent = nullptr);
~Timer();
void setMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex);
void start();
void startWithMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex);
public slots:
void tick();
@ -27,7 +27,7 @@ class Timer : public QObject
MachineTypes::TimedMachine *machine = nullptr;
std::mutex *machineMutex = nullptr;
int64_t lastTickNanos = 0;
std::unique_ptr<QThread> thread;
FunctionThread thread;
std::unique_ptr<QTimer> timer;
};