git.y1.nz

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.