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}