From 63319b72bf385b0c0badf7bf9ce0674309e6234e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 6 Feb 2020 16:39:25 +0100 Subject: [PATCH] Improve sound --- main.c | 30 +++++++++++++++++++++++++----- platform_sdl.h | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/main.c b/main.c index 7539bc8..c81c73b 100755 --- a/main.c +++ b/main.c @@ -94,7 +94,9 @@ static inline void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex); samples provided in sounds.h, and it may or may not ignore the volume parameter (which is 0 to 255). Depending on the platform the function can play completely different samples or even e.g. just beeps. If the platform can't - play sounds, this function implementation can simply be left empty. + play sounds, this function implementation can simply be left empty. This + function doesn't have to implement safety measures, the back end takes cares + of them. */ void SFG_playSound(uint8_t soundIndex, uint8_t volume); @@ -248,6 +250,9 @@ struct for mouse control. */ } SFG_player; +uint8_t SFG_explosionSoundPlayed; /**< Prevents playing too many explosion + sounds at once */ + RCL_RayConstraints SFG_rayConstraints; /** @@ -350,6 +355,19 @@ uint8_t SFG_random() return SFG_currentRandom; } +void SFG_playSoundSafe(uint8_t soundIndex, uint8_t volume) +{ + if (soundIndex == 2) // explosion? + { + if (!SFG_explosionSoundPlayed) + SFG_playSound(soundIndex,volume); + + SFG_explosionSoundPlayed = 1; + } + else + SFG_playSound(soundIndex,volume); +} + /** Returns a damage value for specific attack type (SFG_WEAPON_FIRE_TYPE_...), with added randomness (so the values will differe). For explosion pass @@ -1772,6 +1790,8 @@ static inline uint8_t SFG_elementCollides( */ void SFG_gameStep() { + SFG_explosionSoundPlayed = 0; + for (uint8_t i = 0; i < SFG_KEY_COUNT; ++i) SFG_keyStates[i] = (SFG_keyStates[i] << 1) | SFG_keyPressed(i); @@ -1812,7 +1832,7 @@ void SFG_gameStep() if (canShoot) { - SFG_playSound(0,255); + SFG_playSoundSafe(0,255); if (ammo != SFG_AMMO_NONE) SFG_player.ammo[ammo] -= projectileCount; @@ -2184,7 +2204,7 @@ void SFG_gameStep() SFG_removeItem(i); SFG_player.lastItemTakenFrame = SFG_gameFrame; i--; - SFG_playSound(3,255); + SFG_playSoundSafe(3,255); #endif } else // collide @@ -2407,7 +2427,7 @@ void SFG_gameStep() SFG_DOOR_UP_DOWN_MASK : 0x00; if (upDownState != newUpDownState) - SFG_playSound(1,255); + SFG_playSoundSafe(1,255); door->state = (door->state & ~SFG_DOOR_UP_DOWN_MASK) | newUpDownState; @@ -2533,7 +2553,7 @@ void SFG_gameStep() else if (monster->health == 0) { monster->stateType = SFG_MR_TYPE(*monster) | SFG_MONSTER_STATE_DYING; - SFG_playSound(2,255); + SFG_playSoundSafe(2,255); } else if (state != SFG_MONSTER_STATE_INACTIVE) { diff --git a/platform_sdl.h b/platform_sdl.h index d55d938..66d297a 100644 --- a/platform_sdl.h +++ b/platform_sdl.h @@ -173,33 +173,37 @@ void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infin #endif uint8_t audioBuff[SFG_SFX_SAMPLE_COUNT]; -uint32_t audioPos = 0; +uint16_t audioPos = 0; void audioFillCallback(void *userdata, uint8_t *s, int l) { - if (audioPos >= SFG_SFX_SAMPLE_COUNT) - SDL_PauseAudio(1); - for (int i = 0; i < l; ++i) - if (audioPos < SFG_SFX_SAMPLE_COUNT) - { - s[i] = audioBuff[audioPos]; - audioPos++; - } - else - s[i] = 127; + { + s[i] = audioBuff[audioPos]; + + audioBuff[audioPos] = 127; + + audioPos = (audioPos < SFG_SFX_SAMPLE_COUNT - 1) ? (audioPos + 1) : 0; + } } void SFG_playSound(uint8_t soundIndex, uint8_t volume) { uint8_t volumeStep = volume / 16; - for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i) - audioBuff[i] = SFG_GET_SFX_SAMPLE(soundIndex,i) * volumeStep; + uint16_t pos = audioPos; - audioPos = 0; - - SDL_PauseAudio(0); + for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i) + { + int16_t mixedValue = + audioBuff[pos] - 127 + SFG_GET_SFX_SAMPLE(soundIndex,i) * volumeStep; + + mixedValue = (mixedValue > 0) ? ((mixedValue < 255) ? mixedValue : 255) : 0; + + audioBuff[pos] = mixedValue; + + pos = (pos < SFG_SFX_SAMPLE_COUNT - 1) ? (pos + 1) : 0; + } } int main(int argc, char *argv[]) @@ -278,6 +282,11 @@ int main(int argc, char *argv[]) if (SDL_OpenAudio(&audioSpec, NULL) < 0) printf("SDL: could not initialize audio\n"); + for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i) + audioBuff[i] = 127; + + SDL_PauseAudio(0); + running = 1; #ifdef __EMSCRIPTEN__ @@ -289,6 +298,7 @@ int main(int argc, char *argv[]) printf("SDL: freeing SDL\n"); + SDL_PauseAudio(1); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window);