all repos — mgba @ 4edd7286f39fe940a890394626567211e072badb

mGBA Game Boy Advance Emulator

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}