Improve sound

This commit is contained in:
Miloslav Číž 2020-02-06 16:39:25 +01:00
parent f71479e5ec
commit 63319b72bf
2 changed files with 51 additions and 21 deletions

30
main.c
View File

@ -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)
{

View File

@ -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);