all repos — mgba @ 9c92a29b28d1f81224ba28d5fc83a9481eccd5eb

mGBA Game Boy Advance Emulator

src/platform/sdl/sdl-audio.c (view raw)

 1/* Copyright (c) 2013-2014 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 "sdl-audio.h"
 7
 8#include "gba.h"
 9#include "gba-thread.h"
10
11#define BUFFER_SIZE (GBA_AUDIO_SAMPLES >> 2)
12
13static void _GBASDLAudioCallback(void* context, Uint8* data, int len);
14
15bool GBASDLInitAudio(struct GBASDLAudio* context, struct GBAThread* threadContext) {
16	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
17		GBALog(0, GBA_LOG_ERROR, "Could not initialize SDL sound system");
18		return false;
19	}
20
21	context->desiredSpec.freq = 44100;
22	context->desiredSpec.format = AUDIO_S16SYS;
23	context->desiredSpec.channels = 2;
24	context->desiredSpec.samples = context->samples;
25	context->desiredSpec.callback = _GBASDLAudioCallback;
26	context->desiredSpec.userdata = context;
27	context->drift = 0.f;
28	if (SDL_OpenAudio(&context->desiredSpec, &context->obtainedSpec) < 0) {
29		GBALog(0, GBA_LOG_ERROR, "Could not open SDL sound system");
30		return false;
31	}
32	context->thread = threadContext;
33	context->samples = context->obtainedSpec.samples;
34	if (context->samples > threadContext->audioBuffers) {
35		threadContext->audioBuffers = context->samples * 2;
36	}
37
38	SDL_PauseAudio(0);
39	return true;
40}
41
42void GBASDLDeinitAudio(struct GBASDLAudio* context) {
43	UNUSED(context);
44	SDL_PauseAudio(1);
45	SDL_CloseAudio();
46	SDL_QuitSubSystem(SDL_INIT_AUDIO);
47}
48
49void GBASDLPauseAudio(struct GBASDLAudio* context) {
50	UNUSED(context);
51	SDL_PauseAudio(1);
52}
53
54void GBASDLResumeAudio(struct GBASDLAudio* context) {
55	UNUSED(context);
56	SDL_PauseAudio(0);
57}
58
59static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
60	struct GBASDLAudio* audioContext = context;
61	if (!context || !audioContext->thread || !audioContext->thread->gba) {
62		memset(data, 0, len);
63		return;
64	}
65	audioContext->ratio = GBAAudioCalculateRatio(&audioContext->thread->gba->audio, audioContext->thread->fpsTarget, audioContext->obtainedSpec.freq);
66	if (audioContext->ratio == INFINITY) {
67		memset(data, 0, len);
68		return;
69	}
70	struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data;
71	len /= 2 * audioContext->obtainedSpec.channels;
72	if (audioContext->obtainedSpec.channels == 2) {
73		GBAAudioResampleNN(&audioContext->thread->gba->audio, audioContext->ratio, &audioContext->drift, ssamples, len);
74	}
75}