all repos — mgba @ c5d243fca282cf11d7f2c38010fce18361babdc2

mGBA Game Boy Advance Emulator

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	(void)(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}