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}