diff --git a/src/g_game.c b/src/g_game.c index 8766d92d..c05d7f78 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1321,9 +1321,15 @@ boolean G_Responder(event_t* ev) if (M_InputActivated(input_pause)) { if (paused ^= 2) + { S_PauseSound(); + S_PauseMusic(); + } else + { S_ResumeSound(); + S_ResumeMusic(); + } return true; } @@ -1343,7 +1349,6 @@ boolean G_Responder(event_t* ev) ((ev->type == ev_keydown) || (ev->type == ev_mouseb_down) || (ev->type == ev_joyb_down)) ? - (!menuactive ? S_StartSound(NULL,sfx_swtchn) : true), MN_StartControlPanel(), true : false; } @@ -2992,9 +2997,15 @@ void G_Ticker(void) case BTS_PAUSE: if ((paused ^= 1)) - S_PauseSound(); + { + S_PauseSound(); + S_PauseMusic(); + } else - S_ResumeSound(); + { + S_ResumeSound(); + S_ResumeMusic(); + } break; case BTS_SAVEGAME: @@ -3892,7 +3903,7 @@ void G_InitNew(skill_t skill, int episode, int map) if (paused) { paused = false; - S_ResumeSound(); + S_ResumeMusic(); } if (skill > sk_nightmare) diff --git a/src/i_3dsound.c b/src/i_3dsound.c index 151cae10..3d349902 100644 --- a/src/i_3dsound.c +++ b/src/i_3dsound.c @@ -45,7 +45,7 @@ typedef struct oal_source_params_s { ALfloat position[3]; ALfloat velocity[3]; - boolean use_3d; + boolean positional; boolean point_source; fixed_t z; } oal_source_params_t; @@ -86,11 +86,14 @@ static void CalcListenerParams(const mobj_t *listener, lis->position[1] = FIXED_TO_ALFLOAT(player->viewz); lis->position[2] = FIXED_TO_ALFLOAT(-listener->y); - if (oal_use_doppler) + if (oal_use_doppler && listener->interp == true) { - lis->velocity[0] = FIXED_TO_ALFLOAT(listener->momx) * TICRATE; - lis->velocity[1] = FIXED_TO_ALFLOAT(listener->momz) * TICRATE; - lis->velocity[2] = FIXED_TO_ALFLOAT(-listener->momy) * TICRATE; + lis->velocity[0] = + FIXED_TO_ALFLOAT(listener->x - listener->oldx) * TICRATE; + lis->velocity[1] = + FIXED_TO_ALFLOAT(listener->z - listener->oldz) * TICRATE; + lis->velocity[2] = + FIXED_TO_ALFLOAT(listener->oldy - listener->y) * TICRATE; } else { @@ -137,12 +140,14 @@ static void CalcSourceParams(const mobj_t *source, oal_source_params_t *src) src->position[1] = FIXED_TO_ALFLOAT(src->z); src->position[2] = FIXED_TO_ALFLOAT(-source->y); - // Doppler effect only applies to monsters and projectiles. - if (oal_use_doppler && src->point_source) + // Doppler effect only applies to projectiles and other players. + if (oal_use_doppler && src->point_source && source->interp == true + && (source->flags & (MF_MISSILE | MF_SKULLFLY) + || source->type == MT_PLAYER)) { - src->velocity[0] = FIXED_TO_ALFLOAT(source->momx) * TICRATE; - src->velocity[1] = FIXED_TO_ALFLOAT(source->momz) * TICRATE; - src->velocity[2] = FIXED_TO_ALFLOAT(-source->momy) * TICRATE; + src->velocity[0] = FIXED_TO_ALFLOAT(source->x - source->oldx) * TICRATE; + src->velocity[1] = FIXED_TO_ALFLOAT(source->z - source->oldz) * TICRATE; + src->velocity[2] = FIXED_TO_ALFLOAT(source->oldy - source->y) * TICRATE; } else { @@ -152,11 +157,11 @@ static void CalcSourceParams(const mobj_t *source, oal_source_params_t *src) } } -static void CalcHypotenuse(fixed_t adx, fixed_t ady, fixed_t *dist) +static void CalcHypotenuse(int adx, int ady, int *dist) { if (ady > adx) { - const fixed_t temp = adx; + const int temp = adx; adx = ady; ady = temp; } @@ -174,24 +179,22 @@ static void CalcHypotenuse(fixed_t adx, fixed_t ady, fixed_t *dist) } static void CalcDistance(const mobj_t *listener, const mobj_t *source, - oal_source_params_t *src, fixed_t *dist) + oal_source_params_t *src, int *dist) { - const fixed_t adx = - abs((listener->x >> FRACBITS) - (source->x >> FRACBITS)); - const fixed_t ady = - abs((listener->y >> FRACBITS) - (source->y >> FRACBITS)); - fixed_t distxy; + const int adx = abs((listener->x >> FRACBITS) - (source->x >> FRACBITS)); + const int ady = abs((listener->y >> FRACBITS) - (source->y >> FRACBITS)); + int distxy; CalcHypotenuse(adx, ady, &distxy); - // Treat monsters and projectiles as point sources. + // Treat monsters, projectiles, and other players as point sources. src->point_source = (source->thinker.function.p1 != (actionf_p1)P_DegenMobjThinker && source->info && source->actualheight); if (src->point_source) { - fixed_t adz; + int adz; // Vertical distance is from player's view to middle of source's sprite. src->z = source->z + (source->actualheight >> 1); adz = abs((listener->player->viewz >> FRACBITS) - (src->z >> FRACBITS)); @@ -206,104 +209,79 @@ static void CalcDistance(const mobj_t *listener, const mobj_t *source, } } -static boolean CalcVolumePriority(fixed_t dist, int *vol, int *pri) +static boolean CalcVolumePriority(int dist, sfxparams_t *params) { - int pri_volume; - if (dist == 0) { return true; } - else if (dist >= (S_CLIPPING_DIST >> FRACBITS)) + else if (dist >= S_CLIPPING_DIST) { return false; } - else if (dist <= (S_CLOSE_DIST >> FRACBITS)) - { - pri_volume = *vol; - } - else if (dist > S_ATTENUATOR) + else if (dist > S_CLOSE_DIST) { // OpenAL inverse distance model never reaches zero volume. Gradually // ramp down the volume as the distance approaches the limit. - pri_volume = *vol * ((S_CLIPPING_DIST >> FRACBITS) - dist) - / (S_CLOSE_DIST >> FRACBITS); - *vol = pri_volume; - } - else - { - // Range where OpenAL inverse distance model applies. Calculate volume - // for priority bookkeeping but let OpenAL handle the real volume. - // Simplify formula for OAL_ROLLOFF_FACTOR = 1: - pri_volume = *vol * (S_CLOSE_DIST >> FRACBITS) / dist; + params->volume = + params->volume * (S_CLIPPING_DIST - dist) / S_ATTENUATOR; } // Decrease priority with volume attenuation. - *pri += (127 - pri_volume); + params->priority += (127 - params->volume); - if (*pri > 255) + if (params->priority > 255) { - *pri = 255; + params->priority = 255; } - return (pri_volume > 0); -} - -static boolean ScaleVolume(int chanvol, int *vol) -{ - *vol = (snd_SfxVolume * chanvol) / 15; - - if (*vol < 1) - { - return false; - } - else if (*vol > 127) - { - *vol = 127; - } - - return true; + return (params->volume > 0); } static boolean I_3D_AdjustSoundParams(const mobj_t *listener, - const mobj_t *source, int chanvol, - int *vol, int *sep, int *pri) + const mobj_t *source, sfxparams_t *params) { - fixed_t dist; + int dist; - if (!ScaleVolume(chanvol, vol)) + params->volume = snd_SfxVolume * params->volume_scale / 15; + + if (params->volume < 1) { return false; } + else if (params->volume > 127) + { + params->volume = 127; + } if (!source || source == players[displayplayer].mo || !listener || !listener->player) { - src.use_3d = false; + src.positional = false; return true; } CalcDistance(listener, source, &src, &dist); - if (!CalcVolumePriority(dist, vol, pri)) + if (!CalcVolumePriority(dist, params)) { return false; } - src.use_3d = true; + src.positional = true; CalcSourceParams(source, &src); return true; } -static void I_3D_UpdateSoundParams(int channel, int volume, int separation) +static void I_3D_UpdateSoundParams(int channel, const sfxparams_t *params) { - if (src.use_3d) + if (src.positional) { I_OAL_UpdateSourceParams(channel, src.position, src.velocity); } - I_OAL_SetVolume(channel, volume); + I_OAL_SetVolume(channel, params->volume); } static void I_3D_UpdateListenerParams(const mobj_t *listener) @@ -315,13 +293,20 @@ static void I_3D_UpdateListenerParams(const mobj_t *listener) return; } + // Only update when listener is moving. + if ((menuactive && !netgame && !demoplayback) || paused + || gamestate != GS_LEVEL) + { + return; + } + CalcListenerParams(listener, &lis); I_OAL_UpdateListenerParams(lis.position, lis.velocity, lis.orientation); } static boolean I_3D_StartSound(int channel, sfxinfo_t *sfx, float pitch) { - if (src.use_3d) + if (src.positional) { I_OAL_ResetSource3D(channel, src.point_source); } @@ -354,7 +339,10 @@ const sound_module_t sound_3d_module = I_3D_UpdateListenerParams, I_3D_StartSound, I_OAL_StopSound, + I_OAL_PauseSound, + I_OAL_ResumeSound, I_OAL_SoundIsPlaying, + I_OAL_SoundIsPaused, I_OAL_ShutdownSound, I_OAL_ShutdownModule, I_OAL_DeferUpdates, diff --git a/src/i_mbfsound.c b/src/i_mbfsound.c index 8a49cfbd..11c97fc4 100644 --- a/src/i_mbfsound.c +++ b/src/i_mbfsound.c @@ -28,30 +28,31 @@ #include "m_fixed.h" #include "p_mobj.h" #include "r_main.h" +#include "sounds.h" #include "tables.h" static boolean force_flip_pan; static boolean I_MBF_AdjustSoundParams(const mobj_t *listener, - const mobj_t *source, int chanvol, - int *vol, int *sep, int *pri) + const mobj_t *source, + sfxparams_t *params) { - fixed_t adx, ady, dist; + int adx, ady, dist; angle_t angle; // haleyjd 05/29/06: allow per-channel volume scaling - *vol = (snd_SfxVolume * chanvol) / 15; + params->volume = snd_SfxVolume * params->volume_scale / 15; - if (*vol < 1) + if (params->volume < 1) { return false; } - else if (*vol > 127) + else if (params->volume > 127) { - *vol = 127; + params->volume = 127; } - *sep = NORM_SEP; + params->separation = NORM_SEP; if (!source || source == players[displayplayer].mo) { @@ -75,20 +76,28 @@ static boolean I_MBF_AdjustSoundParams(const mobj_t *listener, if (ady > adx) { - dist = adx, adx = ady, ady = dist; + const int temp = adx; + adx = ady; + ady = temp; } - dist = adx ? FixedDiv( - adx, finesine[(tantoangle[FixedDiv(ady, adx) >> DBITS] + ANG90) - >> ANGLETOFINESHIFT]) - : 0; + if (adx) + { + const int slope = FixedDiv(ady, adx) >> DBITS; + const int angle = tantoangle[slope] >> ANGLETOFINESHIFT; + dist = FixedDiv(adx, finecosine[angle]); + } + else + { + dist = 0; + } if (!dist) // killough 11/98: handle zero-distance as special case { return true; } - if (dist > S_CLIPPING_DIST >> FRACBITS) + if (dist >= S_CLIPPING_DIST) { return false; } @@ -107,35 +116,38 @@ static boolean I_MBF_AdjustSoundParams(const mobj_t *listener, angle >>= ANGLETOFINESHIFT; // stereo separation - *sep = NORM_SEP - FixedMul(S_STEREO_SWING >> FRACBITS, finesine[angle]); + params->separation -= FixedMul(S_STEREO_SWING, finesine[angle]); } // volume calculation - if (dist > S_CLOSE_DIST >> FRACBITS) + if (dist > S_CLOSE_DIST) { - *vol = *vol * ((S_CLIPPING_DIST >> FRACBITS) - dist) / S_ATTENUATOR; + params->volume = + params->volume * (S_CLIPPING_DIST - dist) / S_ATTENUATOR; } // haleyjd 09/27/06: decrease priority with volume attenuation - *pri = *pri + (127 - *vol); + params->priority += (127 - params->volume); - if (*pri > 255) // cap to 255 + if (params->priority > 255) // cap to 255 { - *pri = 255; + params->priority = 255; } - return (*vol > 0); + return (params->volume > 0); } -void I_MBF_UpdateSoundParams(int channel, int volume, int separation) +static void I_MBF_UpdateSoundParams(int channel, const sfxparams_t *params) { + int separation = params->separation; + // SoM 7/1/02: forceFlipPan accounted for here if (force_flip_pan) { separation = 254 - separation; } - I_OAL_SetVolume(channel, volume); + I_OAL_SetVolume(channel, params->volume); I_OAL_SetPan(channel, separation); } @@ -165,7 +177,10 @@ const sound_module_t sound_mbf_module = NULL, I_OAL_StartSound, I_OAL_StopSound, + I_OAL_PauseSound, + I_OAL_ResumeSound, I_OAL_SoundIsPlaying, + I_OAL_SoundIsPaused, I_OAL_ShutdownSound, I_OAL_ShutdownModule, I_OAL_DeferUpdates, diff --git a/src/i_oalsound.c b/src/i_oalsound.c index 832827a0..611696d1 100644 --- a/src/i_oalsound.c +++ b/src/i_oalsound.c @@ -39,10 +39,10 @@ #include "w_wad.h" #include "z_zone.h" -#define OAL_ROLLOFF_FACTOR 1 +#define OAL_ROLLOFF_FACTOR 0.5f #define OAL_SPEED_OF_SOUND 343.3f -// 128 map units per 3 meters (https://doomwiki.org/wiki/Map_unit). -#define OAL_MAP_UNITS_PER_METER (128.0f / 3.0f) +// 16 mu/ft (https://www.doomworld.com/idgames/docs/editing/metrics) +#define OAL_METERS_PER_MAP_UNIT 0.01905f #define OAL_SOURCE_RADIUS 32.0f #define OAL_DEFAULT_PITCH 1.0f @@ -248,8 +248,7 @@ void I_OAL_ResetSource2D(int channel) alSource3f(oal->sources[channel], AL_POSITION, 0.0f, 0.0f, 0.0f); alSource3f(oal->sources[channel], AL_VELOCITY, 0.0f, 0.0f, 0.0f); - - alSourcei(oal->sources[channel], AL_ROLLOFF_FACTOR, 0); + alSourcef(oal->sources[channel], AL_ROLLOFF_FACTOR, 0.0f); alSourcei(oal->sources[channel], AL_SOURCE_RELATIVE, AL_TRUE); } @@ -272,7 +271,7 @@ void I_OAL_ResetSource3D(int channel, boolean point_source) point_source ? 0.0f : OAL_SOURCE_RADIUS); } - alSourcei(oal->sources[channel], AL_ROLLOFF_FACTOR, OAL_ROLLOFF_FACTOR); + alSourcef(oal->sources[channel], AL_ROLLOFF_FACTOR, OAL_ROLLOFF_FACTOR); alSourcei(oal->sources[channel], AL_SOURCE_RELATIVE, AL_FALSE); } @@ -337,8 +336,8 @@ static void UpdateUserSoundSettings(void) if (oal_snd_module == SND_MODULE_3D) { - oal->absorption = (ALfloat)snd_absorption / 2.0f; - alDopplerFactor((ALfloat)snd_doppler * snd_doppler / 100.0f); + oal->absorption = (ALfloat)snd_absorption; + alDopplerFactor((ALfloat)snd_doppler / 5.0f); oal_use_doppler = (snd_doppler > 0); } else @@ -359,9 +358,8 @@ static void ResetParams(void) { I_OAL_ResetSource2D(i); alSource3i(oal->sources[i], AL_DIRECTION, 0, 0, 0); - alSourcei(oal->sources[i], AL_MAX_DISTANCE, S_ATTENUATOR); - alSourcei(oal->sources[i], AL_REFERENCE_DISTANCE, - S_CLOSE_DIST >> FRACBITS); + alSourcei(oal->sources[i], AL_REFERENCE_DISTANCE, S_CLOSE_DIST); + alSourcei(oal->sources[i], AL_MAX_DISTANCE, S_CLIPPING_DIST); } // Spatialization is required even for 2D panning emulation. if (oal->SOFT_source_spatialize) @@ -378,12 +376,12 @@ static void ResetParams(void) alListeneriv(AL_ORIENTATION, default_orientation); if (oal->EXT_EFX) { - alListenerf(AL_METERS_PER_UNIT, 1.0f / OAL_MAP_UNITS_PER_METER); + alListenerf(AL_METERS_PER_UNIT, OAL_METERS_PER_MAP_UNIT); } // Context state parameters. alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // OpenAL 1.1 Specs, 3.4.2. - alSpeedOfSound(OAL_SPEED_OF_SOUND * OAL_MAP_UNITS_PER_METER); + alSpeedOfSound(OAL_SPEED_OF_SOUND / OAL_METERS_PER_MAP_UNIT); UpdateUserSoundSettings(); } @@ -735,6 +733,33 @@ void I_OAL_StopSound(int channel) alSourceStop(oal->sources[channel]); } +void I_OAL_PauseSound(int channel) +{ + if (!oal) + { + return; + } + + alSourcePause(oal->sources[channel]); +} + +void I_OAL_ResumeSound(int channel) +{ + ALint state; + + if (!oal) + { + return; + } + + alGetSourcei(oal->sources[channel], AL_SOURCE_STATE, &state); + + if (state == AL_PAUSED) + { + alSourcePlay(oal->sources[channel]); + } +} + boolean I_OAL_SoundIsPlaying(int channel) { ALint state; @@ -749,6 +774,20 @@ boolean I_OAL_SoundIsPlaying(int channel) return (state == AL_PLAYING); } +boolean I_OAL_SoundIsPaused(int channel) +{ + ALint state; + + if (!oal) + { + return false; + } + + alGetSourcei(oal->sources[channel], AL_SOURCE_STATE, &state); + + return (state == AL_PAUSED); +} + void I_OAL_SetVolume(int channel, int volume) { if (!oal) diff --git a/src/i_oalsound.h b/src/i_oalsound.h index 87ff237f..7da5f3d6 100644 --- a/src/i_oalsound.h +++ b/src/i_oalsound.h @@ -62,8 +62,14 @@ boolean I_OAL_StartSound(int channel, struct sfxinfo_s *sfx, float pitch); void I_OAL_StopSound(int channel); +void I_OAL_PauseSound(int channel); + +void I_OAL_ResumeSound(int channel); + boolean I_OAL_SoundIsPlaying(int channel); +boolean I_OAL_SoundIsPaused(int channel); + void I_OAL_SetVolume(int channel, int volume); void I_OAL_SetPan(int channel, int separation); diff --git a/src/i_pcsound.c b/src/i_pcsound.c index bb747edb..8ff987a8 100644 --- a/src/i_pcsound.c +++ b/src/i_pcsound.c @@ -38,7 +38,7 @@ static LPALBUFFERCALLBACKSOFT alBufferCallbackSOFT; static ALuint callback_buffer; static ALuint callback_source; -#define SQUARE_WAVE_AMP 0x2000 +#define SQUARE_WAVE_AMP 0x1000 // Chocolate Doom: 0x2000 static SDL_mutex *sound_lock; static int mixing_freq; @@ -381,10 +381,11 @@ static boolean I_PCS_CacheSound(sfxinfo_t *sfx) } static boolean I_PCS_AdjustSoundParams(const mobj_t *listener, - const mobj_t *source, int chanvol, - int *vol, int *sep, int *pri) + const mobj_t *source, + sfxparams_t *params) { - fixed_t adx, ady, approx_dist; + fixed_t adx, ady; + int approx_dist; if (!source || source == players[displayplayer].mo) { @@ -403,9 +404,9 @@ static boolean I_PCS_AdjustSoundParams(const mobj_t *listener, ady = abs(listener->y - source->y); // From _GG1_ p.428. Appox. eucledian distance fast. - approx_dist = adx + ady - ((adx < ady ? adx : ady) >> 1); + approx_dist = (adx + ady - ((adx < ady ? adx : ady) >> 1)) >> FRACBITS; - if (approx_dist > S_CLIPPING_DIST) + if (approx_dist >= S_CLIPPING_DIST) { return false; } @@ -413,19 +414,19 @@ static boolean I_PCS_AdjustSoundParams(const mobj_t *listener, // volume calculation if (approx_dist < S_CLOSE_DIST) { - *vol = snd_SfxVolume; + params->volume = snd_SfxVolume; } else { // distance effect - *vol = (snd_SfxVolume * ((S_CLIPPING_DIST - approx_dist) >> FRACBITS)) - / S_ATTENUATOR; + params->volume = + snd_SfxVolume * (S_CLIPPING_DIST - approx_dist) / S_ATTENUATOR; } - return (*vol > 0); + return (params->volume > 0); } -static void I_PCS_UpdateSoundParams(int channel, int volume, int separation) +static void I_PCS_UpdateSoundParams(int channel, const sfxparams_t *params) { // adjust PC Speaker volume alSourcef(callback_source, AL_GAIN, (float)snd_SfxVolume / 15); @@ -502,7 +503,10 @@ const sound_module_t sound_pcs_module = NULL, I_PCS_StartSound, I_PCS_StopSound, + NULL, + NULL, I_PCS_SoundIsPlaying, + NULL, I_PCS_ShutdownSound, I_PCS_ShutdownModule, I_OAL_DeferUpdates, diff --git a/src/i_sound.c b/src/i_sound.c index ed3fead7..d22107cb 100644 --- a/src/i_sound.c +++ b/src/i_sound.c @@ -78,8 +78,6 @@ typedef struct sfxinfo_t *sfx; boolean enabled; - // haleyjd 06/16/08: unique id number - int idnum; } channel_info_t; static channel_info_t channelinfo[MAX_CHANNELS]; @@ -123,14 +121,14 @@ static void StopChannel(int channel) // Returns false if no sound should be played. // boolean I_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, - int chanvol, int *vol, int *sep, int *pri) + sfxparams_t *params) { if (!snd_init) { return false; } - return sound_module->AdjustSoundParams(listener, source, chanvol, vol, sep, pri); + return sound_module->AdjustSoundParams(listener, source, params); } // @@ -139,7 +137,7 @@ boolean I_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, // Changes sound parameters in response to stereo panning and relative location // change. // -void I_UpdateSoundParams(int channel, int volume, int separation) +void I_UpdateSoundParams(int channel, const sfxparams_t *params) { if (!snd_init) { @@ -153,7 +151,7 @@ void I_UpdateSoundParams(int channel, int volume, int separation) } #endif - sound_module->UpdateSoundParams(channel, volume, separation); + sound_module->UpdateSoundParams(channel, params); } void I_UpdateListenerParams(const mobj_t *listener) @@ -262,9 +260,8 @@ int I_GetSfxLumpNum(sfxinfo_t *sfx) // active sounds, which is maintained as a given number // of internal channels. Returns a free channel. // -int I_StartSound(sfxinfo_t *sfx, int vol, int sep, int pitch) +int I_StartSound(sfxinfo_t *sfx, const sfxparams_t *params, int pitch) { - static unsigned int id = 0; int channel; if (!snd_init) @@ -297,9 +294,8 @@ int I_StartSound(sfxinfo_t *sfx, int vol, int sep, int pitch) channelinfo[channel].sfx = sfx; channelinfo[channel].enabled = true; - channelinfo[channel].idnum = id++; // give the sound a unique id - I_UpdateSoundParams(channel, vol, sep); + I_UpdateSoundParams(channel, params); float step = (pitch == NORM_PITCH) ? 1.0f : steptable[pitch]; @@ -336,6 +332,46 @@ void I_StopSound(int channel) StopChannel(channel); } +void I_PauseSound(int channel) +{ + if (!snd_init || !sound_module->PauseSound) + { + return; + } + +#ifdef RANGECHECK + if (channel < 0 || channel >= MAX_CHANNELS) + { + I_Error("I_PauseSound: channel out of range"); + } +#endif + + if (channelinfo[channel].enabled) + { + sound_module->PauseSound(channel); + } +} + +void I_ResumeSound(int channel) +{ + if (!snd_init || !sound_module->ResumeSound) + { + return; + } + +#ifdef RANGECHECK + if (channel < 0 || channel >= MAX_CHANNELS) + { + I_Error("I_ResumeSound: channel out of range"); + } +#endif + + if (channelinfo[channel].enabled) + { + sound_module->ResumeSound(channel); + } +} + // // I_SoundIsPlaying // @@ -358,29 +394,21 @@ boolean I_SoundIsPlaying(int channel) return sound_module->SoundIsPlaying(channel); } -// -// I_SoundID -// -// haleyjd: returns the unique id number assigned to a specific instance -// of a sound playing on a given channel. This is required to make sure -// that the higher-level sound code doesn't start updating sounds that have -// been displaced without it noticing. -// -int I_SoundID(int channel) +boolean I_SoundIsPaused(int channel) { - if (!snd_init) + if (!snd_init || !sound_module->SoundIsPaused) { - return 0; + return false; } #ifdef RANGECHECK if (channel < 0 || channel >= MAX_CHANNELS) { - I_Error("I_SoundID: channel out of range\n"); + I_Error("I_SoundIsPaused: channel out of range"); } #endif - return channelinfo[channel].idnum; + return sound_module->SoundIsPaused(channel); } // diff --git a/src/i_sound.h b/src/i_sound.h index f1784895..0a909738 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -29,7 +29,7 @@ // when to clip out sounds // Does not fit the large outdoor areas. -#define S_CLIPPING_DIST (1200 << FRACBITS) +#define S_CLIPPING_DIST 1200 // Distance to origin when sounds should be maxed out. // This should relate to movement clipping resolution @@ -39,9 +39,9 @@ // killough 12/98: restore original // #define S_CLOSE_DIST (160<> FRACBITS) +#define S_ATTENUATOR (S_CLIPPING_DIST - S_CLOSE_DIST) // Adjustable by menu. // [FG] moved here from i_sound.c @@ -50,7 +50,7 @@ #define NORM_PITCH 128 #define NORM_PRIORITY 64 #define NORM_SEP 128 -#define S_STEREO_SWING (96 << FRACBITS) +#define S_STEREO_SWING 96 #define SND_SAMPLERATE 44100 @@ -65,8 +65,8 @@ void I_ShutdownSound(void); // struct mobj_s; - struct sfxinfo_s; +struct sfxparams_s; typedef struct sound_module_s { @@ -75,13 +75,16 @@ typedef struct sound_module_s boolean (*AllowReinitSound)(void); boolean (*CacheSound)(struct sfxinfo_s *sfx); boolean (*AdjustSoundParams)(const struct mobj_s *listener, - const struct mobj_s *source, int chanvol, - int *vol, int *sep, int *pri); - void (*UpdateSoundParams)(int channel, int vol, int sep); + const struct mobj_s *source, + struct sfxparams_s *params); + void (*UpdateSoundParams)(int channel, const struct sfxparams_s *params); void (*UpdateListenerParams)(const struct mobj_s *listener); boolean (*StartSound)(int channel, struct sfxinfo_s *sfx, float pitch); void (*StopSound)(int channel); + void (*PauseSound)(int channel); + void (*ResumeSound)(int channel); boolean (*SoundIsPlaying)(int channel); + boolean (*SoundIsPaused)(int channel); void (*ShutdownSound)(void); void (*ShutdownModule)(void); void (*DeferUpdates)(void); @@ -113,32 +116,34 @@ void I_SetChannels(void); int I_GetSfxLumpNum(struct sfxinfo_s *sfxinfo); // Starts a sound in a particular sound channel. -int I_StartSound(struct sfxinfo_s *sound, int vol, int sep, int pitch); +int I_StartSound(struct sfxinfo_s *sound, const struct sfxparams_s *params, + int pitch); // Stops a sound channel. void I_StopSound(int handle); +void I_PauseSound(int handle); +void I_ResumeSound(int handle); + // Called by S_*() functions // to see if a channel is still playing. // Returns 0 if no longer playing, 1 if playing. boolean I_SoundIsPlaying(int handle); +boolean I_SoundIsPaused(int handle); // Outputs adjusted volume, separation, and priority from the sound module. // Returns false if no sound should be played. boolean I_AdjustSoundParams(const struct mobj_s *listener, - const struct mobj_s *source, int chanvol, int *vol, - int *sep, int *pri); + const struct mobj_s *source, + struct sfxparams_s *params); // Updates the volume, separation, // and pitch of a sound channel. -void I_UpdateSoundParams(int handle, int vol, int sep); +void I_UpdateSoundParams(int handle, const struct sfxparams_s *params); void I_UpdateListenerParams(const struct mobj_s *listener); void I_DeferSoundUpdates(void); void I_ProcessSoundUpdates(void); -// haleyjds -int I_SoundID(int handle); - // // MUSIC I/O // diff --git a/src/mn_menu.c b/src/mn_menu.c index 4323fe2f..3ab9c033 100644 --- a/src/mn_menu.c +++ b/src/mn_menu.c @@ -253,6 +253,22 @@ static void M_ExtHelpNextScreen(int choice); static void M_ExtHelp(int choice); static void M_DrawExtHelp(void); +static void M_PauseSound(void) +{ + if (!paused && gamestate == GS_LEVEL && !demoplayback && !netgame) + { + S_PauseSound(); + } +} + +static void M_ResumeSound(void) +{ + if (!paused && gamestate == GS_LEVEL && !demoplayback && !netgame) + { + S_ResumeSound(); + } +} + // // SetNextMenu // @@ -1700,12 +1716,14 @@ static void M_QuickLoad(void) { if (netgame && !demoplayback) // killough 5/26/98: add !demoplayback { + M_StartSound(sfx_swtchn); M_StartMessage(s_QLOADNET, NULL, false); // Ty 03/27/98 - externalized return; } if (demorecording) // killough 5/26/98: exclude during demo recordings { + M_StartSound(sfx_swtchn); M_StartMessage("you can't quickload\n" "while recording a demo!\n\n" PRESSKEY, NULL, false); // killough 5/26/98: not externalized @@ -1746,6 +1764,7 @@ static void M_EndGameResponse(int ch) quickSaveSlot = -1; currentMenu->lastOn = itemOn; + S_StopChannels(); MN_ClearMenus(); D_StartTitle(); } @@ -2168,6 +2187,7 @@ void MN_ClearMenus(void) I_SetSensorEventState(false); G_ClearInput(); + M_ResumeSound(); } static boolean MenuBack(void) @@ -2437,19 +2457,15 @@ boolean M_ShortcutResponder(const event_t *ev) if (M_InputActivated(input_help)) // Help key { MN_StartControlPanel(); - currentMenu = &HelpDef; // killough 10/98: new help screen - currentMenu->prevMenu = NULL; itemOn = 0; - M_StartSound(sfx_swtchn); return true; } if (M_InputActivated(input_savegame)) // Save Game { MN_StartControlPanel(); - M_StartSound(sfx_swtchn); M_SaveGame(0); return true; } @@ -2457,7 +2473,6 @@ boolean M_ShortcutResponder(const event_t *ev) if (M_InputActivated(input_loadgame)) // Load Game { MN_StartControlPanel(); - M_StartSound(sfx_swtchn); M_LoadGame(0); return true; } @@ -2467,19 +2482,18 @@ boolean M_ShortcutResponder(const event_t *ev) MN_StartControlPanel(); currentMenu = &SoundDef; itemOn = currentMenu->lastOn; - M_StartSound(sfx_swtchn); return true; } if (M_InputActivated(input_quicksave)) // Quicksave { - M_StartSound(sfx_swtchn); M_QuickSave(); return true; } if (M_InputActivated(input_endgame)) // End game { + M_PauseSound(); M_StartSound(sfx_swtchn); M_EndGame(0); return true; @@ -2494,13 +2508,13 @@ boolean M_ShortcutResponder(const event_t *ev) if (M_InputActivated(input_quickload)) // Quickload { - M_StartSound(sfx_swtchn); M_QuickLoad(); return true; } if (M_InputActivated(input_quit)) // Quit DOOM { + M_PauseSound(); M_StartSound(sfx_swtchn); M_QuitDOOM(0); return true; @@ -3088,6 +3102,7 @@ boolean M_Responder(event_t *ev) I_SetSensorEventState(false); G_ClearInput(); menuactive = false; + M_ResumeSound(); M_StartSound(sfx_swtchx); return true; } @@ -3117,7 +3132,6 @@ boolean M_Responder(event_t *ev) { I_ShowMouseCursor(menu_input != pad_mode); MN_StartControlPanel(); - M_StartSound(sfx_swtchn); return true; } return false; @@ -3372,6 +3386,9 @@ void MN_StartControlPanel(void) I_SetSensorEventState(true); G_ClearInput(); + + M_PauseSound(); + M_StartSound(sfx_swtchn); } // diff --git a/src/mn_setup.c b/src/mn_setup.c index f767cd1b..9bb354d0 100644 --- a/src/mn_setup.c +++ b/src/mn_setup.c @@ -2588,7 +2588,7 @@ static setup_menu_t sfx_settings1[] = { MI_GAP, - {"Doppler Effect", S_THERMO, CNTR_X, M_THRM_SPC, {"snd_doppler"}, + {"Doppler Effect", S_THERMO | S_ACTION, CNTR_X, M_THRM_SPC, {"snd_doppler"}, .strings_id = str_percent, .action = SetSoundModule}, MI_END diff --git a/src/p_mobj.c b/src/p_mobj.c index 9fd4d11c..5e925094 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -870,15 +870,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // NULL head of sector list // phares 3/13/98 mobj->touching_sectorlist = NULL; - // [AM] Do not interpolate on spawn. - mobj->interp = false; - - // [AM] Just in case interpolation is attempted... - mobj->oldx = mobj->x; - mobj->oldy = mobj->y; - mobj->oldz = mobj->z; - mobj->oldangle = mobj->angle; - // set subsector and/or block links P_SetThingPosition(mobj); @@ -890,6 +881,15 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->z = z == ONFLOORZ ? mobj->floorz : z == ONCEILINGZ ? mobj->ceilingz - mobj->height : z; + // [AM] Do not interpolate on spawn. + mobj->interp = false; + + // [AM] Just in case interpolation is attempted... + mobj->oldx = mobj->x; + mobj->oldy = mobj->y; + mobj->oldz = mobj->z; + mobj->oldangle = mobj->angle; + mobj->thinker.function.p1 = (actionf_p1)P_MobjThinker; mobj->above_thing = mobj->below_thing = 0; // phares diff --git a/src/s_sound.c b/src/s_sound.c index 52a33f71..77044e36 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -46,12 +46,11 @@ typedef struct channel_s { sfxinfo_t *sfxinfo; // sound information (if null, channel avail.) const mobj_t *origin; // origin of sound - int volume; // volume scale value for effect -- haleyjd 05/29/06 + int volume_scale; // volume scale value for effect -- haleyjd 05/29/06 int handle; // handle of the sound being played int o_priority; // haleyjd 09/27/06: stored priority value int priority; // current priority value int singularity; // haleyjd 09/27/06: stored singularity value - int idnum; // haleyjd 09/30/06: unique id num for sound event } channel_t; // the set of channels available @@ -129,9 +128,9 @@ void S_StopChannels(void) // haleyjd: added priority scaling // static int S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, - int chanvol, int *vol, int *sep, int *pri) + sfxparams_t *params) { - return I_AdjustSoundParams(listener, source, chanvol, vol, sep, pri); + return I_AdjustSoundParams(listener, source, params); } // @@ -141,8 +140,7 @@ static int S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, // haleyjd 09/27/06: fixed priority/singularity bugs // Note that a higher priority number means lower priority! // -static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo, int priority, - int singularity) +static int S_getChannel(const mobj_t *origin, int priority, int singularity) { // channel number to use int cnum; @@ -213,9 +211,8 @@ static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo, int priority, static void StartSound(const mobj_t *origin, int sfx_id, pitchrange_t pitch_range, rumble_type_t rumble_type) { - int sep, pitch, o_priority, priority, singularity, cnum, handle; - int volumeScale = 127; - int volume = snd_SfxVolume; + int pitch, o_priority, singularity, cnum, handle; + sfxparams_t params; sfxinfo_t *sfx; // jff 1/22/98 return if sound is not enabled @@ -242,17 +239,17 @@ static void StartSound(const mobj_t *origin, int sfx_id, // Initialize sound parameters pitch = NORM_PITCH; + params.volume_scale = 127; // haleyjd: modified so that priority value is always used // haleyjd: also modified to get and store proper singularity value - o_priority = priority = sfx->priority; + o_priority = params.priority = sfx->priority; singularity = sfx->singularity; // Check to see if it is audible, modify the params // killough 3/7/98, 4/25/98: code rearranged slightly - if (!S_AdjustSoundParams(players[displayplayer].mo, origin, volumeScale, - &volume, &sep, &priority)) + if (!S_AdjustSoundParams(players[displayplayer].mo, origin, ¶ms)) { return; } @@ -281,7 +278,7 @@ static void StartSound(const mobj_t *origin, int sfx_id, } // try to find a channel - if ((cnum = S_getChannel(origin, sfx, priority, singularity)) < 0) + if ((cnum = S_getChannel(origin, params.priority, singularity)) < 0) { return; } @@ -294,7 +291,6 @@ static void StartSound(const mobj_t *origin, int sfx_id, #endif channels[cnum].sfxinfo = sfx; - channels[cnum].origin = origin; while (sfx->link) { @@ -302,20 +298,19 @@ static void StartSound(const mobj_t *origin, int sfx_id, } // Assigns the handle to one of the channels in the mix/output buffer. - handle = I_StartSound(sfx, volume, sep, pitch); + handle = I_StartSound(sfx, ¶ms, pitch); // haleyjd: check to see if the sound was started if (handle >= 0) { - channels[cnum].handle = handle; - // haleyjd 05/29/06: record volume scale value // haleyjd 09/27/06: store priority and singularity values (!!!) - channels[cnum].volume = volumeScale; - channels[cnum].o_priority = o_priority; // original priority - channels[cnum].priority = priority; // scaled priority + channels[cnum].origin = origin; + channels[cnum].handle = handle; + channels[cnum].volume_scale = params.volume_scale; + channels[cnum].o_priority = o_priority; // original priority + channels[cnum].priority = params.priority; // scaled priority channels[cnum].singularity = singularity; - channels[cnum].idnum = I_SoundID(handle); // unique instance id if (rumble_type != RUMBLE_NONE) { @@ -505,11 +500,51 @@ void S_UnlinkSound(mobj_t *origin) } } +void S_PauseSound(void) +{ + if (nosfxparm) + { + return; + } + + I_DeferSoundUpdates(); + + for (int cnum = 0; cnum < snd_channels; cnum++) + { + if (channels[cnum].sfxinfo) + { + I_PauseSound(channels[cnum].handle); + } + } + + I_ProcessSoundUpdates(); +} + +void S_ResumeSound(void) +{ + if (nosfxparm) + { + return; + } + + I_DeferSoundUpdates(); + + for (int cnum = 0; cnum < snd_channels; cnum++) + { + if (channels[cnum].sfxinfo) + { + I_ResumeSound(channels[cnum].handle); + } + } + + I_ProcessSoundUpdates(); +} + // // Stop and resume music, during game PAUSE. // -void S_PauseSound(void) +void S_PauseMusic(void) { if (mus_playing && !mus_paused) { @@ -518,7 +553,7 @@ void S_PauseSound(void) } } -void S_ResumeSound(void) +void S_ResumeMusic(void) { if (mus_playing && mus_paused) { @@ -554,56 +589,48 @@ void S_UpdateSounds(const mobj_t *listener) } I_DeferSoundUpdates(); + I_UpdateListenerParams(listener); for (cnum = 0; cnum < snd_channels; ++cnum) { channel_t *c = &channels[cnum]; sfxinfo_t *sfx = c->sfxinfo; - // haleyjd: has this software channel lost its hardware channel? - if (c->idnum != I_SoundID(c->handle)) - { - // clear the channel and keep going - memset(c, 0, sizeof(channel_t)); - continue; - } - if (sfx) { if (I_SoundIsPlaying(c->handle)) { - // initialize parameters - int volume = snd_SfxVolume; - int sep = NORM_SEP; - int pri = c->o_priority; // haleyjd 09/27/06: priority - // check non-local sounds for distance clipping // or modify their params if (c->origin && listener != c->origin) // killough 3/20/98 { - if (!S_AdjustSoundParams(listener, c->origin, c->volume, - &volume, &sep, &pri)) + // initialize parameters + sfxparams_t params; + params.volume_scale = c->volume_scale; + params.priority = c->o_priority; // haleyjd 09/27/06: priority + + if (S_AdjustSoundParams(listener, c->origin, ¶ms)) { - S_StopChannel(cnum); + I_UpdateSoundParams(c->handle, ¶ms); + c->priority = params.priority; // haleyjd } else { - I_UpdateSoundParams(c->handle, volume, sep); - c->priority = pri; // haleyjd + S_StopChannel(cnum); } } I_UpdateRumbleParams(listener, c->origin, c->handle); } - else // if channel is allocated but sound has stopped, free it + else if (!I_SoundIsPaused(c->handle)) { + // if channel is allocated but sound has stopped, free it S_StopChannel(cnum); } } } - I_UpdateListenerParams(listener); I_ProcessSoundUpdates(); I_UpdateRumble(); } diff --git a/src/s_sound.h b/src/s_sound.h index 5dd53a78..8593399c 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -102,10 +102,13 @@ void S_ChangeMusInfoMusic(int lumpnum, int looping); // Stops the music fer sure. void S_StopMusic(void); -// Stop and resume music, during game PAUSE. void S_PauseSound(void); void S_ResumeSound(void); +// Stop and resume music, during game PAUSE. +void S_PauseMusic(void); +void S_ResumeMusic(void); + void S_RestartMusic(void); // diff --git a/src/sounds.h b/src/sounds.h index 2439646e..c3155d93 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -23,6 +23,14 @@ #include "doomtype.h" +typedef struct sfxparams_s +{ + int volume_scale; + int volume; + int separation; + int priority; +} sfxparams_t; + // // SoundFX struct. //