all repos — mgba @ c4b38790f211b65cb15af26cebe9fc25e3c19914

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
10#include <mgba/core/blip_buf.h>
11#include <mgba/core/core.h>
12#include <mgba/core/thread.h>
13#include <mgba/internal/gba/audio.h>
14
15using namespace QGBA;
16
17AudioDevice::AudioDevice(QObject* parent)
18	: QIODevice(parent)
19	, m_context(nullptr)
20{
21	setOpenMode(ReadOnly);
22}
23
24void AudioDevice::setFormat(const QAudioFormat& format) {
25	if (!m_context || !mCoreThreadIsActive(m_context)) {
26		LOG(QT, INFO) << tr("Can't set format of context-less audio device");
27		return;
28	}
29	double fauxClock = GBAAudioCalculateRatio(1, m_context->impl->sync.fpsTarget, 1);
30	mCoreSyncLockAudio(&m_context->impl->sync);
31	blip_set_rates(m_context->core->getAudioChannel(m_context->core, 0),
32		           m_context->core->frequency(m_context->core), format.sampleRate() * fauxClock);
33	blip_set_rates(m_context->core->getAudioChannel(m_context->core, 1),
34		           m_context->core->frequency(m_context->core), format.sampleRate() * fauxClock);
35	mCoreSyncUnlockAudio(&m_context->impl->sync);
36}
37
38void AudioDevice::setInput(mCoreThread* input) {
39	m_context = input;
40}
41
42qint64 AudioDevice::readData(char* data, qint64 maxSize) {
43	if (!m_context->core) {
44		LOG(QT, WARN) << tr("Audio device is missing its core");
45		return 0;
46	}
47
48	maxSize /= sizeof(GBAStereoSample);
49	mCoreSyncLockAudio(&m_context->impl->sync);
50	int available = std::min<qint64>({
51		blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)),
52		maxSize,
53		std::numeric_limits<int>::max()
54	});
55	blip_read_samples(m_context->core->getAudioChannel(m_context->core, 0), &reinterpret_cast<GBAStereoSample*>(data)->left, available, true);
56	blip_read_samples(m_context->core->getAudioChannel(m_context->core, 1), &reinterpret_cast<GBAStereoSample*>(data)->right, available, true);
57	mCoreSyncConsumeAudio(&m_context->impl->sync);
58	return available * sizeof(GBAStereoSample);
59}
60
61qint64 AudioDevice::writeData(const char*, qint64) {
62	LOG(QT, WARN) << tr("Writing data to read-only audio device");
63	return 0;
64}