From d91c1e9bdc01912fbdd8e6786fd3c837d89dafac Mon Sep 17 00:00:00 2001 From: Clownacy Date: Tue, 31 Mar 2020 12:19:44 +0100 Subject: [PATCH] Update the SDL2 audio backend Now uses the shared software mixer --- CMakeLists.txt | 2 +- src/Backends/Audio/SDL2.cpp | 169 ++++-------------------------------- 2 files changed, 16 insertions(+), 155 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4547a3ca..2da54233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,7 +294,7 @@ else() endif() if(BACKEND_AUDIO MATCHES "SDL2") - target_sources(CSE2 PRIVATE "src/Backends/Audio/SDL2.cpp") + target_sources(CSE2 PRIVATE "src/Backends/Audio/SDL2.cpp" "src/Backends/Audio/SoftwareMixer.cpp") elseif(BACKEND_AUDIO MATCHES "miniaudio") target_sources(CSE2 PRIVATE "src/Backends/Audio/miniaudio.cpp" "src/Backends/Audio/SoftwareMixer.cpp") diff --git a/src/Backends/Audio/SDL2.cpp b/src/Backends/Audio/SDL2.cpp index 88d6a0c8..bbe2dcb3 100644 --- a/src/Backends/Audio/SDL2.cpp +++ b/src/Backends/Audio/SDL2.cpp @@ -1,122 +1,20 @@ #include "../Audio.h" -#include -#include -#include -#include -#include - #include "SDL.h" #include "../../Organya.h" #include "../../WindowsWrapper.h" +#include "SoftwareMixer.h" + #define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define CLAMP(x, y, z) MIN(MAX((x), (y)), (z)) -#ifdef __GNUC__ -#define ATTR_HOT __attribute__((hot)) -#else -#define ATTR_HOT -#endif - -struct AudioBackend_Sound -{ - unsigned char *samples; - size_t frames; - double position; - double advance_delta; - BOOL playing; - BOOL looping; - unsigned int frequency; - float volume; - float pan_l; - float pan_r; - float volume_l; - float volume_r; - - struct AudioBackend_Sound *next; -}; - -static AudioBackend_Sound *sound_list_head; static SDL_AudioDeviceID device_id; static unsigned long output_frequency; static unsigned short organya_timer; -static double MillibelToScale(long volume) -{ - // Volume is in hundredths of decibels, from 0 to -10000 - volume = CLAMP(volume, -10000, 0); - return pow(10.0, volume / 2000.0); -} - -static void SetSoundFrequency(AudioBackend_Sound *sound, unsigned int frequency) -{ - sound->frequency = frequency; - sound->advance_delta = (double)frequency / (double)output_frequency; -} - -static void SetSoundVolume(AudioBackend_Sound *sound, long volume) -{ - sound->volume = (float)MillibelToScale(volume); - - sound->volume_l = sound->pan_l * sound->volume; - sound->volume_r = sound->pan_r * sound->volume; -} - -static void SetSoundPan(AudioBackend_Sound *sound, long pan) -{ - sound->pan_l = (float)MillibelToScale(-pan); - sound->pan_r = (float)MillibelToScale(pan); - - sound->volume_l = sound->pan_l * sound->volume; - sound->volume_r = sound->pan_r * sound->volume; -} - -// Most CPU-intensive function in the game (2/3rd CPU time consumption in my experience), so marked with attrHot so the compiler considers it a hot spot (as it is) when optimizing -ATTR_HOT static void MixSounds(float *stream, unsigned int frames_total) -{ - for (AudioBackend_Sound *sound = sound_list_head; sound != NULL; sound = sound->next) - { - if (sound->playing) - { - float *steam_pointer = stream; - - for (unsigned int frames_done = 0; frames_done < frames_total; ++frames_done) - { - // Get two samples, and normalise them to 0-1 - const float sample1 = (sound->samples[(size_t)sound->position] - 128.0f) / 128.0f; - const float sample2 = (sound->samples[(size_t)sound->position + 1] - 128.0f) / 128.0f; - - // Perform linear interpolation - const float interpolated_sample = sample1 + ((sample2 - sample1) * fmod((float)sound->position, 1.0f)); - - *steam_pointer++ += interpolated_sample * sound->volume_l; - *steam_pointer++ += interpolated_sample * sound->volume_r; - - sound->position += sound->advance_delta; - - if (sound->position >= sound->frames) - { - if (sound->looping) - { - sound->position = fmod(sound->position, (double)sound->frames); - } - else - { - sound->playing = FALSE; - sound->position = 0.0; - break; - } - } - } - } - } -} - static void Callback(void *user_data, Uint8 *stream_uint8, int len) { (void)user_data; @@ -129,7 +27,7 @@ static void Callback(void *user_data, Uint8 *stream_uint8, int len) if (organya_timer == 0) { - MixSounds(stream, frames_total); + Mixer_MixSounds(stream, frames_total); } else { @@ -152,7 +50,7 @@ static void Callback(void *user_data, Uint8 *stream_uint8, int len) const unsigned int frames_to_do = MIN(organya_countdown, frames_total - frames_done); - MixSounds(stream + frames_done * 2, frames_to_do); + Mixer_MixSounds(stream + frames_done * 2, frames_to_do); frames_done += frames_to_do; organya_countdown -= frames_to_do; @@ -184,6 +82,7 @@ BOOL AudioBackend_Init(void) SDL_AudioSpec obtained_specification; device_id = SDL_OpenAudioDevice(NULL, 0, &specification, &obtained_specification, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); output_frequency = obtained_specification.freq; + Mixer_Init(obtained_specification.freq); if (device_id == 0) { @@ -207,35 +106,13 @@ void AudioBackend_Deinit(void) AudioBackend_Sound* AudioBackend_CreateSound(unsigned int frequency, size_t frames) { - AudioBackend_Sound *sound = (AudioBackend_Sound*)malloc(sizeof(AudioBackend_Sound)); - - if (sound == NULL) - return NULL; - - sound->samples = (unsigned char*)malloc(frames + 1); - - if (sound->samples == NULL) - { - free(sound); - return NULL; - } - - sound->frames = frames; - sound->playing = FALSE; - sound->position = 0.0; - - SetSoundFrequency(sound, frequency); - SetSoundVolume(sound, 0); - SetSoundPan(sound, 0); - SDL_LockAudioDevice(device_id); - sound->next = sound_list_head; - sound_list_head = sound; + Mixer_Sound *sound = Mixer_CreateSound(frequency, frames); SDL_UnlockAudioDevice(device_id); - return sound; + return (AudioBackend_Sound*)sound; } void AudioBackend_DestroySound(AudioBackend_Sound *sound) @@ -245,16 +122,7 @@ void AudioBackend_DestroySound(AudioBackend_Sound *sound) SDL_LockAudioDevice(device_id); - for (AudioBackend_Sound **sound_pointer = &sound_list_head; *sound_pointer != NULL; sound_pointer = &(*sound_pointer)->next) - { - if (*sound_pointer == sound) - { - *sound_pointer = sound->next; - free(sound->samples); - free(sound); - break; - } - } + Mixer_DestroySound((Mixer_Sound*)sound); SDL_UnlockAudioDevice(device_id); } @@ -266,10 +134,7 @@ unsigned char* AudioBackend_LockSound(AudioBackend_Sound *sound, size_t *size) SDL_LockAudioDevice(device_id); - if (size != NULL) - *size = sound->frames; - - return sound->samples; + return Mixer_LockSound((Mixer_Sound*)sound, size); } void AudioBackend_UnlockSound(AudioBackend_Sound *sound) @@ -287,10 +152,7 @@ void AudioBackend_PlaySound(AudioBackend_Sound *sound, BOOL looping) SDL_LockAudioDevice(device_id); - sound->playing = TRUE; - sound->looping = looping; - - sound->samples[sound->frames] = looping ? sound->samples[0] : 0x80; // For the linear interpolator + Mixer_PlaySound((Mixer_Sound*)sound, looping); SDL_UnlockAudioDevice(device_id); } @@ -302,8 +164,7 @@ void AudioBackend_StopSound(AudioBackend_Sound *sound) SDL_LockAudioDevice(device_id); - sound->playing = FALSE; - sound->position = 0.0; + Mixer_StopSound((Mixer_Sound*)sound); SDL_UnlockAudioDevice(device_id); } @@ -315,7 +176,7 @@ void AudioBackend_RewindSound(AudioBackend_Sound *sound) SDL_LockAudioDevice(device_id); - sound->position = 0.0; + Mixer_RewindSound((Mixer_Sound*)sound); SDL_UnlockAudioDevice(device_id); } @@ -327,7 +188,7 @@ void AudioBackend_SetSoundFrequency(AudioBackend_Sound *sound, unsigned int freq SDL_LockAudioDevice(device_id); - SetSoundFrequency(sound, frequency); + Mixer_SetSoundFrequency((Mixer_Sound*)sound, frequency); SDL_UnlockAudioDevice(device_id); } @@ -339,7 +200,7 @@ void AudioBackend_SetSoundVolume(AudioBackend_Sound *sound, long volume) SDL_LockAudioDevice(device_id); - SetSoundVolume(sound, volume); + Mixer_SetSoundVolume((Mixer_Sound*)sound, volume); SDL_UnlockAudioDevice(device_id); } @@ -351,7 +212,7 @@ void AudioBackend_SetSoundPan(AudioBackend_Sound *sound, long pan) SDL_LockAudioDevice(device_id); - SetSoundPan(sound, pan); + Mixer_SetSoundPan((Mixer_Sound*)sound, pan); SDL_UnlockAudioDevice(device_id); }