src/platform/qt/AudioDevice.cpp (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "AudioDevice.h"
7
8#include "LogController.h"
9
10extern "C" {
11#include "gba/gba.h"
12#include "gba/audio.h"
13#include "gba/supervisor/thread.h"
14}
15
16using namespace QGBA;
17
18AudioDevice::AudioDevice(QObject* parent)
19 : QIODevice(parent)
20 , m_context(nullptr)
21 , m_drift(0)
22 , m_ratio(1.f)
23{
24 setOpenMode(ReadOnly);
25}
26
27void AudioDevice::setFormat(const QAudioFormat& format) {
28 if (!m_context || !GBAThreadIsActive(m_context)) {
29 LOG(INFO) << tr("Can't set format of context-less audio device");
30 return;
31 }
32#if RESAMPLE_LIBRARY == RESAMPLE_NN
33 GBAThreadInterrupt(m_context);
34 m_ratio = GBAAudioCalculateRatio(m_context->gba->audio.sampleRate, m_context->fpsTarget, format.sampleRate());
35 GBAThreadContinue(m_context);
36#elif RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
37 double fauxClock = GBAAudioCalculateRatio(1, m_context->fpsTarget, 1);
38 mCoreSyncLockAudio(&m_context->sync);
39 blip_set_rates(m_context->gba->audio.left, GBA_ARM7TDMI_FREQUENCY, format.sampleRate() * fauxClock);
40 blip_set_rates(m_context->gba->audio.right, GBA_ARM7TDMI_FREQUENCY, format.sampleRate() * fauxClock);
41 mCoreSyncUnlockAudio(&m_context->sync);
42#endif
43}
44
45void AudioDevice::setInput(GBAThread* input) {
46 m_context = input;
47}
48
49qint64 AudioDevice::readData(char* data, qint64 maxSize) {
50 if (maxSize > 0xFFFFFFFF) {
51 maxSize = 0xFFFFFFFF;
52 }
53
54 if (!m_context->gba) {
55 LOG(WARN) << tr("Audio device is missing its GBA");
56 return 0;
57 }
58
59#if RESAMPLE_LIBRARY == RESAMPLE_NN
60 return GBAAudioResampleNN(&m_context->gba->audio, m_ratio, &m_drift, reinterpret_cast<GBAStereoSample*>(data), maxSize / sizeof(GBAStereoSample)) * sizeof(GBAStereoSample);
61#elif RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
62 mCoreSyncLockAudio(&m_context->sync);
63 int available = blip_samples_avail(m_context->gba->audio.left);
64 if (available > maxSize / sizeof(GBAStereoSample)) {
65 available = maxSize / sizeof(GBAStereoSample);
66 }
67 blip_read_samples(m_context->gba->audio.left, &reinterpret_cast<GBAStereoSample*>(data)->left, available, true);
68 blip_read_samples(m_context->gba->audio.right, &reinterpret_cast<GBAStereoSample*>(data)->right, available, true);
69 mCoreSyncConsumeAudio(&m_context->sync);
70 return available * sizeof(GBAStereoSample);
71#endif
72}
73
74qint64 AudioDevice::writeData(const char*, qint64) {
75 LOG(WARN) << tr("Writing data to read-only audio device");
76 return 0;
77}