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