src/platform/qt/AudioDevice.cpp (view raw)
1#include "AudioDevice.h"
2
3extern "C" {
4#include "gba.h"
5#include "gba-audio.h"
6#include "gba-thread.h"
7}
8
9using namespace QGBA;
10
11AudioDevice::AudioDevice(GBAThread* threadContext, QObject* parent)
12 : QIODevice(parent)
13 , m_context(threadContext)
14{
15 setOpenMode(ReadOnly);
16}
17
18void AudioDevice::setFormat(const QAudioFormat& format) {
19 // TODO: merge where the fudge rate exists
20 float fudgeRate = 16853760.0f / GBA_ARM7TDMI_FREQUENCY;
21 m_ratio = format.sampleRate() / (float) (m_context->gba->audio.sampleRate * fudgeRate);
22}
23
24qint64 AudioDevice::readData(char* data, qint64 maxSize) {
25 if (maxSize > 0xFFFFFFFF) {
26 maxSize = 0xFFFFFFFF;
27 }
28
29 if (!m_context->gba) {
30 return 0;
31 }
32
33 return GBAAudioResampleNN(&m_context->gba->audio, m_ratio, &m_drift, reinterpret_cast<GBAStereoSample*>(data), maxSize / sizeof(GBAStereoSample)) * sizeof(GBAStereoSample);
34}
35
36qint64 AudioDevice::writeData(const char*, qint64) {
37 return 0;
38}
39
40AudioThread::AudioThread(QObject* parent)
41 : QThread(parent)
42{
43 // Nothing to do
44}
45
46void AudioThread::setInput(GBAThread* input) {
47 m_input = input;
48}
49
50void AudioThread::shutdown() {
51 disconnect();
52 if (m_audioOutput) {
53 m_audioOutput->stop();
54 delete m_audioOutput;
55 m_audioOutput = nullptr;
56 }
57 if (m_device) {
58 delete m_device;
59 m_device = nullptr;
60 }
61 quit();
62}
63
64void AudioThread::pause() {
65 m_audioOutput->stop();
66}
67
68void AudioThread::resume() {
69 m_audioOutput->start(m_device);
70}
71
72void AudioThread::run() {
73 QAudioFormat format;
74 format.setSampleRate(44100);
75 format.setChannelCount(2);
76 format.setSampleSize(16);
77 format.setCodec("audio/pcm");
78 format.setByteOrder(QAudioFormat::LittleEndian);
79 format.setSampleType(QAudioFormat::SignedInt);
80
81 m_device = new AudioDevice(m_input);
82 m_audioOutput = new QAudioOutput(format);
83 m_audioOutput->setBufferSize(1024);
84 m_device->setFormat(m_audioOutput->format());
85 m_audioOutput->start(m_device);
86
87 exec();
88}