all repos — mgba @ 38ab86fdcb6140fa8e90c2f891bcebd5aade233c

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
 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}