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#define FPS_TARGET 60.f
8
9static void _GBASDLAudioCallback(void* context, Uint8* data, int len);
10
11int GBASDLInitAudio(struct GBASDLAudio* context) {
12 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
13 GBALog(0, GBA_LOG_ERROR, "Could not initialize SDL sound system");
14 return 0;
15 }
16
17 context->desiredSpec.freq = 44100;
18 context->desiredSpec.format = AUDIO_S16SYS;
19 context->desiredSpec.channels = 2;
20 context->desiredSpec.samples = GBA_AUDIO_SAMPLES;
21 context->desiredSpec.callback = _GBASDLAudioCallback;
22 context->desiredSpec.userdata = context;
23 context->audio = 0;
24 context->drift = 0.f;
25 if (SDL_OpenAudio(&context->desiredSpec, &context->obtainedSpec) < 0) {
26 GBALog(0, GBA_LOG_ERROR, "Could not open SDL sound system");
27 return 0;
28 }
29 SDL_PauseAudio(0);
30 return 1;
31}
32
33void GBASDLDeinitAudio(struct GBASDLAudio* context) {
34 UNUSED(context);
35 SDL_PauseAudio(1);
36 SDL_CloseAudio();
37 SDL_QuitSubSystem(SDL_INIT_AUDIO);
38}
39
40static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
41 struct GBASDLAudio* audioContext = context;
42 if (!context || !audioContext->audio) {
43 memset(data, 0, len);
44 return;
45 }
46 float ratio = 280896.0f * FPS_TARGET / GBA_ARM7TDMI_FREQUENCY;
47 audioContext->ratio = audioContext->obtainedSpec.freq / ratio / (float) audioContext->audio->sampleRate;
48 struct GBAStereoSample* ssamples = (struct GBAStereoSample*) data;
49 len /= 2 * audioContext->obtainedSpec.channels;
50 if (audioContext->obtainedSpec.channels == 2) {
51 GBAAudioResampleNN(audioContext->audio, audioContext->ratio, &audioContext->drift, ssamples, len);
52 }
53}