SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
SDL/audio/sdl.c
1 #include "audio.h"
2 #include <SDL.h>
3
4 #ifndef _WIN32
5 #define AUDIO_FREQUENCY 96000
6 #include <unistd.h>
7 #else
8 #include <Windows.h>
9 /* Windows (well, at least my VM) can't handle 96KHz sound well :( */
10
11 /* felsqualle says: For SDL 2.0.6+ using the WASAPI driver, the highest freq.
12 we can get is 48000. 96000 also works, but always has some faint crackling in
13 the audio, no matter how high or low I set the buffer length...
14 Not quite satisfied with that solution, because acc. to SDL2 docs,
15 96k + WASAPI *should* work. */
16
17 #define AUDIO_FREQUENCY 48000
18 #endif
19
20 /* Compatibility with older SDL versions */
21 #ifndef SDL_AUDIO_ALLOW_SAMPLES_CHANGE
22 #define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0
23 #endif
24
25 static SDL_AudioDeviceID device_id;
26 static SDL_AudioSpec want_aspec, have_aspec;
27
28 #define AUDIO_BUFFER_SIZE 512
29 static unsigned buffer_pos = 0;
30 static GB_sample_t audio_buffer[AUDIO_BUFFER_SIZE];
31
32 static bool _audio_is_playing(void)
33 {
34 return SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING;
35 }
36
37 static void _audio_clear_queue(void)
38 {
39 SDL_ClearQueuedAudio(device_id);
40 }
41
42 static void _audio_set_paused(bool paused)
43 {
44 _audio_clear_queue();
45 SDL_PauseAudioDevice(device_id, paused);
46 }
47
48 static unsigned _audio_get_frequency(void)
49 {
50 return have_aspec.freq;
51 }
52
53 static size_t _audio_get_queue_length(void)
54 {
55 return SDL_GetQueuedAudioSize(device_id) / sizeof(GB_sample_t);
56 }
57
58 static void _audio_queue_sample(GB_sample_t *sample)
59 {
60 audio_buffer[buffer_pos++] = *sample;
61
62 if (buffer_pos == AUDIO_BUFFER_SIZE) {
63 buffer_pos = 0;
64 SDL_QueueAudio(device_id, (const void *)audio_buffer, sizeof(audio_buffer));
65 }
66 }
67
68 static bool _audio_init(void)
69 {
70 if (SDL_Init(SDL_INIT_AUDIO) != 0) {
71 printf("Failed to initialize SDL audio: %s", SDL_GetError());
72 return false;
73 }
74
75 /* Configure Audio */
76 memset(&want_aspec, 0, sizeof(want_aspec));
77 want_aspec.freq = AUDIO_FREQUENCY;
78 want_aspec.format = AUDIO_S16SYS;
79 want_aspec.channels = 2;
80 want_aspec.samples = 512;
81
82 SDL_version _sdl_version;
83 SDL_GetVersion(&_sdl_version);
84 unsigned sdl_version = _sdl_version.major * 1000 + _sdl_version.minor * 100 + _sdl_version.patch;
85
86 #ifndef _WIN32
87 /* SDL 2.0.5 on macOS and Linux introduced a bug where certain combinations of buffer lengths and frequencies
88 fail to produce audio correctly. */
89 if (sdl_version >= 2005) {
90 want_aspec.samples = 2048;
91 }
92 #else
93 if (sdl_version < 2006) {
94 /* Since WASAPI audio was introduced in SDL 2.0.6, we have to lower the audio frequency
95 to 44100 because otherwise we would get garbled audio output.*/
96 want_aspec.freq = 44100;
97 }
98 #endif
99
100 device_id = SDL_OpenAudioDevice(0, 0, &want_aspec, &have_aspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
101
102 return true;
103 }
104
105 static void _audio_deinit(void)
106 {
107 _audio_set_paused(true);
108 SDL_CloseAudioDevice(device_id);
109 }
110
111 GB_AUDIO_DRIVER(SDL);
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.