Reuse an audio thread instead of shutting it down and making a new one
Jeffrey Pfau jeffrey@endrift.com
Mon, 03 Feb 2014 01:13:52 -0800
5 files changed,
52 insertions(+),
26 deletions(-)
M
src/platform/qt/AudioDevice.cpp
→
src/platform/qt/AudioDevice.cpp
@@ -53,6 +53,14 @@ m_audioOutput->stop();
quit(); } +void AudioThread::pause() { + m_audioOutput->stop(); +} + +void AudioThread::resume() { + m_audioOutput->start(m_device); +} + void AudioThread::run() { QAudioFormat format; format.setSampleRate(44100);@@ -62,11 +70,11 @@ format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt); - AudioDevice device(m_input); + m_device = new AudioDevice(m_input); m_audioOutput = new QAudioOutput(format); m_audioOutput->setBufferSize(1024); - device.setFormat(m_audioOutput->format()); - m_audioOutput->start(&device); + m_device->setFormat(m_audioOutput->format()); + m_audioOutput->start(m_device); exec(); }
M
src/platform/qt/AudioDevice.h
→
src/platform/qt/AudioDevice.h
@@ -10,41 +10,44 @@ struct GBAThread;
namespace QGBA { -class AudioThread : public QThread { +class AudioDevice : public QIODevice { Q_OBJECT public: - AudioThread(QObject* parent = nullptr); - - void setInput(GBAThread* input); + AudioDevice(GBAThread* threadContext, QObject* parent = nullptr); -public slots: - void shutdown(); + void setFormat(const QAudioFormat& format); protected: - void run(); + virtual qint64 readData(char* data, qint64 maxSize) override; + virtual qint64 writeData(const char* data, qint64 maxSize) override; private: - GBAThread* m_input; - QAudioOutput* m_audioOutput; + GBAThread* m_context; + float m_drift; + float m_ratio; }; -class AudioDevice : public QIODevice { +class AudioThread : public QThread { Q_OBJECT public: - AudioDevice(GBAThread* threadContext, QObject* parent = nullptr); + AudioThread(QObject* parent = nullptr); + + void setInput(GBAThread* input); - void setFormat(const QAudioFormat& format); +public slots: + void shutdown(); + void pause(); + void resume(); protected: - virtual qint64 readData(char* data, qint64 maxSize) override; - virtual qint64 writeData(const char* data, qint64 maxSize) override; + void run(); private: - GBAThread* m_context; - float m_drift; - float m_ratio; + GBAThread* m_input; + QAudioOutput* m_audioOutput; + AudioDevice* m_device; }; }
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -18,6 +18,7 @@ GBAVideoSoftwareRendererCreate(m_renderer);
m_renderer->outputBuffer = (color_t*) m_drawContext; m_renderer->outputBufferStride = 256; m_threadContext = { + .state = THREAD_INITIALIZED, .debugger = 0, .frameskip = 0, .biosFd = -1,@@ -92,7 +93,7 @@ }
void GameController::closeGame() { // TODO: Make this threadsafe - if (m_threadContext.state >= THREAD_EXITING) { + if (m_threadContext.state >= THREAD_EXITING || m_threadContext.state <= THREAD_INITIALIZED) { return; } GBAThreadEnd(&m_threadContext);
M
src/platform/qt/Window.cpp
→
src/platform/qt/Window.cpp
@@ -12,6 +12,7 @@ using namespace QGBA;
Window::Window(QWidget* parent) : QMainWindow(parent) + , m_audioThread(nullptr) #ifdef USE_GDB_STUB , m_gdbController(nullptr) #endif@@ -24,6 +25,7 @@ m_display = new Display();
setCentralWidget(m_display); connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*))); connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing())); + connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped())); connect(this, SIGNAL(startDrawing(const uint32_t*, GBAThread*)), m_display, SLOT(startDrawing(const uint32_t*, GBAThread*)), Qt::QueuedConnection); connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing()));@@ -122,11 +124,21 @@ emit startDrawing(m_controller->drawContext(), context);
foreach (QAction* action, m_gameActions) { action->setDisabled(false); } - AudioThread* thread = new AudioThread(this); - thread->setInput(context); - thread->start(QThread::HighPriority); - connect(this, SIGNAL(shutdown()), thread, SLOT(shutdown())); - connect(m_controller, SIGNAL(gameStopped(GBAThread*)), thread, SLOT(shutdown())); + if (!m_audioThread) { + m_audioThread = new AudioThread(this); + connect(this, SIGNAL(shutdown()), m_audioThread, SLOT(shutdown())); + m_audioThread->setInput(context); + m_audioThread->start(QThread::HighPriority); + } else { + m_audioThread->resume(); + } +} + +void Window::gameStopped() { + foreach (QAction* action, m_gameActions) { + action->setDisabled(true); + } + m_audioThread->pause(); } void Window::setupMenu(QMenuBar* menubar) {
M
src/platform/qt/Window.h
→
src/platform/qt/Window.h
@@ -40,11 +40,13 @@ virtual void closeEvent(QCloseEvent*) override;
private slots: void gameStarted(GBAThread*); + void gameStopped(); private: void setupMenu(QMenuBar*); GameController* m_controller; Display* m_display; + AudioThread* m_audioThread; QList<QAction*> m_gameActions; #ifdef USE_GDB_STUB