all repos — mgba @ 0dd69e827325a28b74f2a2d997bae7eb7ae48db3

mGBA Game Boy Advance Emulator

src/sdl/sdl-audio.c (view raw)

 1#include "sdl-audio.h"
 2
 3#include "gba.h"
 4
 5static void _GBASDLAudioCallback(void* context, Uint8* data, int len);
 6
 7int GBASDLInitAudio(struct GBASDLAudio* context) {
 8	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
 9		GBALog(0, GBA_LOG_ERROR, "Could not initialize SDL sound system");
10		return 0;
11	}
12
13	context->desiredSpec.freq = 44100;
14	context->desiredSpec.format = AUDIO_S16SYS;
15	context->desiredSpec.channels = 2;
16	context->desiredSpec.samples = GBA_AUDIO_SAMPLES >> 1;
17	context->desiredSpec.callback = _GBASDLAudioCallback;
18	context->desiredSpec.userdata = context;
19	context->audio = 0;
20	context->drift = 0.f;
21	if (SDL_OpenAudio(&context->desiredSpec, &context->obtainedSpec) < 0) {
22		GBALog(0, GBA_LOG_ERROR, "Could not open SDL sound system");
23		return 0;
24	}
25	SDL_PauseAudio(0);
26	return 1;
27}
28
29void GBASDLDeinitAudio(struct GBASDLAudio* context) {
30	(void)(context);
31	SDL_CloseAudio();
32	SDL_QuitSubSystem(SDL_INIT_AUDIO);
33}
34
35static void _pulldownResample(struct GBASDLAudio* context) {
36	int32_t value;
37	if (CircleBufferRead32(&context->audio->left, &value)) {
38		context->currentSample.left = value << 7;
39	} else {
40		context->currentSample.left = 0;
41	}
42	if (CircleBufferRead32(&context->audio->right, &value)) {
43		context->currentSample.right = value << 7;
44	} else {
45		context->currentSample.right = 0;
46	}
47}
48
49static void _GBASDLAudioCallback(void* context, Uint8* data, int len) {
50	struct GBASDLAudio* audioContext = context;
51	int i;
52	if (!context || !audioContext->audio) {
53		for (i = 0; i < len; ++i) {
54			data[i] = 0;
55		}
56		return;
57	}
58	struct StereoSample* ssamples = (struct StereoSample*) data;
59	len /= 2 * audioContext->obtainedSpec.channels;
60	if (audioContext->obtainedSpec.channels == 2) {
61		for (i = 0; i < len; ++i) {
62			audioContext->drift += audioContext->audio->sampleRate / (float) audioContext->obtainedSpec.freq;
63			while (audioContext->drift >= 0) {
64				_pulldownResample(audioContext);
65				audioContext->drift -= 1.f;
66			}
67			ssamples[i] = audioContext->currentSample;
68		}
69	}
70}