From 408eba40e453a558f84d614d10e51828c8325c83 Mon Sep 17 00:00:00 2001 From: Andrettin Date: Fri, 1 Jan 2016 16:03:49 +0100 Subject: [PATCH] sound_server.cpp patch by marcelofg55 --- src/sound/sound_server.cpp | 112 +++++++++++++++++++++++++++---------- src/video/font.cpp | 2 +- 2 files changed, 82 insertions(+), 32 deletions(-) diff --git a/src/sound/sound_server.cpp b/src/sound/sound_server.cpp index 5bc5854bf..1bf103537 100644 --- a/src/sound/sound_server.cpp +++ b/src/sound/sound_server.cpp @@ -89,8 +89,17 @@ static struct { } MusicChannel; static void ChannelFinished(int channel); -static int *MixerBuffer; -static int MixerBufferSize; + +static struct { + SDL_AudioSpec Format; + SDL_mutex *Lock; + SDL_cond *Cond; + SDL_Thread *Thread; + + int *MixerBuffer; + Uint8 *Buffer; + bool Running; +} Audio; /*---------------------------------------------------------------------------- @@ -285,24 +294,18 @@ static void ClipMixToStereo16(const int *mix, int size, short *output) */ static void MixIntoBuffer(void *buffer, int samples) { - if (samples > MixerBufferSize) { - delete[] MixerBuffer; - MixerBuffer = new int[samples]; - MixerBufferSize = samples; - } - // FIXME: can save the memset here, if first channel sets the values - memset(MixerBuffer, 0, samples * sizeof(*MixerBuffer)); + memset(Audio.MixerBuffer, 0, samples * sizeof(*Audio.MixerBuffer)); if (EffectsEnabled) { // Add channels to mixer buffer - MixChannelsToStereo32(MixerBuffer, samples); + MixChannelsToStereo32(Audio.MixerBuffer, samples); } if (MusicEnabled) { // Add music to mixer buffer - MixMusicToStereo32(MixerBuffer, samples); + MixMusicToStereo32(Audio.MixerBuffer, samples); } - ClipMixToStereo16(MixerBuffer, samples, (short *)buffer); + ClipMixToStereo16(Audio.MixerBuffer, samples, (short *)buffer); } /** @@ -316,8 +319,35 @@ static void MixIntoBuffer(void *buffer, int samples) */ static void FillAudio(void *, Uint8 *stream, int len) { - len >>= 1; - MixIntoBuffer(stream, len); + Assert((len/2) != Audio.Format.size); + + if (Audio.Running == false) + return; + + SDL_memset(stream, 0, len); + + SDL_LockMutex(Audio.Lock); + SDL_MixAudio(stream, Audio.Buffer, len, SDL_MIX_MAXVOLUME); + + // Signal our FillThread, we can fill the Audio.Buffer again + SDL_CondSignal(Audio.Cond); + SDL_UnlockMutex(Audio.Lock); +} + +/** +** Fill audio thread. +*/ +static int FillThread(void *) +{ + while (Audio.Running == true) { + int status = SDL_LockMutex(Audio.Lock); + if (SDL_CondWaitTimeout(Audio.Cond, Audio.Lock, 100) == 0) { + MixIntoBuffer(Audio.Buffer, Audio.Format.samples * Audio.Format.channels); + } + SDL_UnlockMutex(Audio.Lock); + } + + return 0; } /*---------------------------------------------------------------------------- @@ -414,12 +444,12 @@ int SetChannelVolume(int channel, int volume) if (volume < 0) { volume = Channels[channel].Volume; } else { - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); volume = std::min(MaxVolume, volume); Channels[channel].Volume = volume; - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); } return volume; } @@ -444,9 +474,9 @@ int SetChannelStereo(int channel, int stereo) if (stereo < -128 || stereo > 127) { stereo = Channels[channel].Stereo; } else { - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); Channels[channel].Stereo = stereo; - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); } return stereo; } @@ -465,9 +495,9 @@ int SetChannelVoiceGroup(int channel, UnitVoiceGroup voice) return -1; } - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); Channels[channel].Voice = voice; - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); return voice; } @@ -505,13 +535,13 @@ CSample *GetChannelSample(int channel) */ void StopChannel(int channel) { - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); if (channel >= 0 && channel < MaxChannels) { if (Channels[channel].Playing) { ChannelFinished(channel); } } - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); } /** @@ -519,13 +549,13 @@ void StopChannel(int channel) */ void StopAllChannels() { - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); for (int i = 0; i < MaxChannels; ++i) { if (Channels[i].Playing) { ChannelFinished(i); } } - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); } static CSample *LoadSample(const char *name, enum _play_audio_flags_ flag) @@ -588,11 +618,11 @@ int PlaySample(CSample *sample, Origin *origin) { int channel = -1; - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); if (SoundEnabled() && EffectsEnabled && sample && NextFreeChannel != MaxChannels) { channel = FillChannel(sample, EffectsVolume, 0, origin); } - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); return channel; } @@ -714,10 +744,10 @@ void StopMusic() if (MusicPlaying) { MusicPlaying = false; if (MusicChannel.Sample) { - SDL_LockAudio(); + SDL_LockMutex(Audio.Lock); delete MusicChannel.Sample; MusicChannel.Sample = NULL; - SDL_UnlockAudio(); + SDL_UnlockMutex(Audio.Lock); } } } @@ -809,7 +839,7 @@ static int InitSdlSound(int freq, int size) wanted.userdata = NULL; // Open the audio device, forcing the desired format - if (SDL_OpenAudio(&wanted, NULL) < 0) { + if (SDL_OpenAudio(&wanted, &Audio.Format) < 0) { fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); return -1; } @@ -839,6 +869,18 @@ int InitSound() for (int i = 0; i < MaxChannels; ++i) { Channels[i].Point = i + 1; } + + // Create mutex and cond for FillThread + Audio.MixerBuffer = new int[Audio.Format.samples * Audio.Format.channels]; + memset(Audio.MixerBuffer, 0, Audio.Format.samples * Audio.Format.channels * sizeof(int)); + Audio.Buffer = new Uint8[Audio.Format.size]; + memset(Audio.Buffer, 0, Audio.Format.size); + Audio.Lock = SDL_CreateMutex(); + Audio.Cond = SDL_CreateCond(); + Audio.Running = true; + + // Create thread to fill sdl audio buffer + Audio.Thread = SDL_CreateThread(FillThread, NULL); return 0; } @@ -847,10 +889,18 @@ int InitSound() */ void QuitSound() { + Audio.Running = false; + SDL_WaitThread(Audio.Thread, NULL); + + SDL_DestroyCond(Audio.Cond); + SDL_DestroyMutex(Audio.Lock); + SDL_CloseAudio(); SoundInitialized = false; - delete[] MixerBuffer; - MixerBuffer = NULL; + delete[] Audio.MixerBuffer; + Audio.MixerBuffer = NULL; + delete[] Audio.Buffer; + Audio.Buffer = NULL; #ifdef USE_FLUIDSYNTH CleanFluidSynth(); #endif diff --git a/src/video/font.cpp b/src/video/font.cpp index ad8939caf..d88d569f6 100644 --- a/src/video/font.cpp +++ b/src/video/font.cpp @@ -472,7 +472,7 @@ CGraphic *CFont::GetFontColorGraphic(const CFontColor &fontColor) const CGraphic* fontColorG = FontColorGraphics[this][&fontColor]; if (!fontColorG) { #ifdef DEBUG - fprintf(stderr, "Could not load font color %s for font %s\n", fontColor.Ident, this->Ident); + fprintf(stderr, "Could not load font color %s for font %s\n", fontColor.Ident.c_str(), this->Ident.c_str()); #endif return this->G; }