all repos — mgba @ 19b164d560f6382b2e8ee55cc8a6eec22951ae29

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