Sound tweaks (#2215)

* Remove unused idnum tracking

* Seamlessly pause and resume sounds

Side effect: No more chainsaw "rev up" sound when pausing game.

* Update listener before updating sound sources

Make sure the sound sources are fed the latest listener data. This shouldn't matter with the call to I_DeferSoundUpdates, but just in case.

* Skip unnecessary listener calculations

No need to constantly update the listener when the menu is open (single player only), the game is paused, or no game is being played.

* Fix initial mobj->oldz when spawning mobj

mobj->oldz should be set after mobj->z is initialized. See Crispy Doom.

* Improve doppler effect for listener

Uses the correct velocity calculation.

* Improve doppler effect for sources

Uses the correct velocity calculation.

* Adjust doppler effect scaling range

With the changes made to the velocity calculations, the doppler effect thermo should be linear (0.0 to 2.0, 0.2 steps).

* Defer doppler effect thermo action

Resetting the OpenAL 3D sound module is slow.

* Use a standard map units to meters conversion factor

16 map units per foot or 0.01905 meters per map unit (https://www.doomworld.com/idgames/docs/editing/metrics). Same as the speedometer widget.

* Misc. sound refactoring

* Use parameters structure for sound functions

* Improve sound curve

Sound attenuation over distance is now more gradual when using the OpenAL 3D sound module. Previously, there was a more pronounced drop off near the sound distance limit. This uses a different roll-off factor, so the air absorption factor has been adjusted to preserve the same effect as before.

* Reduce PC speaker square wave amplitude

It was way too loud in comparison to the other sound modules.
This commit is contained in:
ceski 2025-03-02 07:45:30 -08:00 committed by GitHub
parent 4681e5aeb2
commit 4fcf30323d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 373 additions and 222 deletions

View File

@ -1321,9 +1321,15 @@ boolean G_Responder(event_t* ev)
if (M_InputActivated(input_pause)) if (M_InputActivated(input_pause))
{ {
if (paused ^= 2) if (paused ^= 2)
{
S_PauseSound(); S_PauseSound();
S_PauseMusic();
}
else else
{
S_ResumeSound(); S_ResumeSound();
S_ResumeMusic();
}
return true; return true;
} }
@ -1343,7 +1349,6 @@ boolean G_Responder(event_t* ev)
((ev->type == ev_keydown) || ((ev->type == ev_keydown) ||
(ev->type == ev_mouseb_down) || (ev->type == ev_mouseb_down) ||
(ev->type == ev_joyb_down)) ? (ev->type == ev_joyb_down)) ?
(!menuactive ? S_StartSound(NULL,sfx_swtchn) : true),
MN_StartControlPanel(), true : false; MN_StartControlPanel(), true : false;
} }
@ -2992,9 +2997,15 @@ void G_Ticker(void)
case BTS_PAUSE: case BTS_PAUSE:
if ((paused ^= 1)) if ((paused ^= 1))
S_PauseSound(); {
S_PauseSound();
S_PauseMusic();
}
else else
S_ResumeSound(); {
S_ResumeSound();
S_ResumeMusic();
}
break; break;
case BTS_SAVEGAME: case BTS_SAVEGAME:
@ -3892,7 +3903,7 @@ void G_InitNew(skill_t skill, int episode, int map)
if (paused) if (paused)
{ {
paused = false; paused = false;
S_ResumeSound(); S_ResumeMusic();
} }
if (skill > sk_nightmare) if (skill > sk_nightmare)

View File

@ -45,7 +45,7 @@ typedef struct oal_source_params_s
{ {
ALfloat position[3]; ALfloat position[3];
ALfloat velocity[3]; ALfloat velocity[3];
boolean use_3d; boolean positional;
boolean point_source; boolean point_source;
fixed_t z; fixed_t z;
} oal_source_params_t; } 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[1] = FIXED_TO_ALFLOAT(player->viewz);
lis->position[2] = FIXED_TO_ALFLOAT(-listener->y); 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[0] =
lis->velocity[1] = FIXED_TO_ALFLOAT(listener->momz) * TICRATE; FIXED_TO_ALFLOAT(listener->x - listener->oldx) * TICRATE;
lis->velocity[2] = FIXED_TO_ALFLOAT(-listener->momy) * TICRATE; lis->velocity[1] =
FIXED_TO_ALFLOAT(listener->z - listener->oldz) * TICRATE;
lis->velocity[2] =
FIXED_TO_ALFLOAT(listener->oldy - listener->y) * TICRATE;
} }
else 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[1] = FIXED_TO_ALFLOAT(src->z);
src->position[2] = FIXED_TO_ALFLOAT(-source->y); src->position[2] = FIXED_TO_ALFLOAT(-source->y);
// Doppler effect only applies to monsters and projectiles. // Doppler effect only applies to projectiles and other players.
if (oal_use_doppler && src->point_source) 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[0] = FIXED_TO_ALFLOAT(source->x - source->oldx) * TICRATE;
src->velocity[1] = FIXED_TO_ALFLOAT(source->momz) * TICRATE; src->velocity[1] = FIXED_TO_ALFLOAT(source->z - source->oldz) * TICRATE;
src->velocity[2] = FIXED_TO_ALFLOAT(-source->momy) * TICRATE; src->velocity[2] = FIXED_TO_ALFLOAT(source->oldy - source->y) * TICRATE;
} }
else 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) if (ady > adx)
{ {
const fixed_t temp = adx; const int temp = adx;
adx = ady; adx = ady;
ady = temp; 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, 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 = const int adx = abs((listener->x >> FRACBITS) - (source->x >> FRACBITS));
abs((listener->x >> FRACBITS) - (source->x >> FRACBITS)); const int ady = abs((listener->y >> FRACBITS) - (source->y >> FRACBITS));
const fixed_t ady = int distxy;
abs((listener->y >> FRACBITS) - (source->y >> FRACBITS));
fixed_t distxy;
CalcHypotenuse(adx, ady, &distxy); CalcHypotenuse(adx, ady, &distxy);
// Treat monsters and projectiles as point sources. // Treat monsters, projectiles, and other players as point sources.
src->point_source = src->point_source =
(source->thinker.function.p1 != (actionf_p1)P_DegenMobjThinker (source->thinker.function.p1 != (actionf_p1)P_DegenMobjThinker
&& source->info && source->actualheight); && source->info && source->actualheight);
if (src->point_source) if (src->point_source)
{ {
fixed_t adz; int adz;
// Vertical distance is from player's view to middle of source's sprite. // Vertical distance is from player's view to middle of source's sprite.
src->z = source->z + (source->actualheight >> 1); src->z = source->z + (source->actualheight >> 1);
adz = abs((listener->player->viewz >> FRACBITS) - (src->z >> FRACBITS)); 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) if (dist == 0)
{ {
return true; return true;
} }
else if (dist >= (S_CLIPPING_DIST >> FRACBITS)) else if (dist >= S_CLIPPING_DIST)
{ {
return false; return false;
} }
else if (dist <= (S_CLOSE_DIST >> FRACBITS)) else if (dist > S_CLOSE_DIST)
{
pri_volume = *vol;
}
else if (dist > S_ATTENUATOR)
{ {
// OpenAL inverse distance model never reaches zero volume. Gradually // OpenAL inverse distance model never reaches zero volume. Gradually
// ramp down the volume as the distance approaches the limit. // ramp down the volume as the distance approaches the limit.
pri_volume = *vol * ((S_CLIPPING_DIST >> FRACBITS) - dist) params->volume =
/ (S_CLOSE_DIST >> FRACBITS); params->volume * (S_CLIPPING_DIST - dist) / S_ATTENUATOR;
*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;
} }
// Decrease priority with volume attenuation. // 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); return (params->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;
} }
static boolean I_3D_AdjustSoundParams(const mobj_t *listener, static boolean I_3D_AdjustSoundParams(const mobj_t *listener,
const mobj_t *source, int chanvol, const mobj_t *source, sfxparams_t *params)
int *vol, int *sep, int *pri)
{ {
fixed_t dist; int dist;
if (!ScaleVolume(chanvol, vol)) params->volume = snd_SfxVolume * params->volume_scale / 15;
if (params->volume < 1)
{ {
return false; return false;
} }
else if (params->volume > 127)
{
params->volume = 127;
}
if (!source || source == players[displayplayer].mo || !listener if (!source || source == players[displayplayer].mo || !listener
|| !listener->player) || !listener->player)
{ {
src.use_3d = false; src.positional = false;
return true; return true;
} }
CalcDistance(listener, source, &src, &dist); CalcDistance(listener, source, &src, &dist);
if (!CalcVolumePriority(dist, vol, pri)) if (!CalcVolumePriority(dist, params))
{ {
return false; return false;
} }
src.use_3d = true; src.positional = true;
CalcSourceParams(source, &src); CalcSourceParams(source, &src);
return true; 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_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) static void I_3D_UpdateListenerParams(const mobj_t *listener)
@ -315,13 +293,20 @@ static void I_3D_UpdateListenerParams(const mobj_t *listener)
return; return;
} }
// Only update when listener is moving.
if ((menuactive && !netgame && !demoplayback) || paused
|| gamestate != GS_LEVEL)
{
return;
}
CalcListenerParams(listener, &lis); CalcListenerParams(listener, &lis);
I_OAL_UpdateListenerParams(lis.position, lis.velocity, lis.orientation); I_OAL_UpdateListenerParams(lis.position, lis.velocity, lis.orientation);
} }
static boolean I_3D_StartSound(int channel, sfxinfo_t *sfx, float pitch) 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); I_OAL_ResetSource3D(channel, src.point_source);
} }
@ -354,7 +339,10 @@ const sound_module_t sound_3d_module =
I_3D_UpdateListenerParams, I_3D_UpdateListenerParams,
I_3D_StartSound, I_3D_StartSound,
I_OAL_StopSound, I_OAL_StopSound,
I_OAL_PauseSound,
I_OAL_ResumeSound,
I_OAL_SoundIsPlaying, I_OAL_SoundIsPlaying,
I_OAL_SoundIsPaused,
I_OAL_ShutdownSound, I_OAL_ShutdownSound,
I_OAL_ShutdownModule, I_OAL_ShutdownModule,
I_OAL_DeferUpdates, I_OAL_DeferUpdates,

View File

@ -28,30 +28,31 @@
#include "m_fixed.h" #include "m_fixed.h"
#include "p_mobj.h" #include "p_mobj.h"
#include "r_main.h" #include "r_main.h"
#include "sounds.h"
#include "tables.h" #include "tables.h"
static boolean force_flip_pan; static boolean force_flip_pan;
static boolean I_MBF_AdjustSoundParams(const mobj_t *listener, static boolean I_MBF_AdjustSoundParams(const mobj_t *listener,
const mobj_t *source, int chanvol, const mobj_t *source,
int *vol, int *sep, int *pri) sfxparams_t *params)
{ {
fixed_t adx, ady, dist; int adx, ady, dist;
angle_t angle; angle_t angle;
// haleyjd 05/29/06: allow per-channel volume scaling // 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; 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) if (!source || source == players[displayplayer].mo)
{ {
@ -75,20 +76,28 @@ static boolean I_MBF_AdjustSoundParams(const mobj_t *listener,
if (ady > adx) if (ady > adx)
{ {
dist = adx, adx = ady, ady = dist; const int temp = adx;
adx = ady;
ady = temp;
} }
dist = adx ? FixedDiv( if (adx)
adx, finesine[(tantoangle[FixedDiv(ady, adx) >> DBITS] + ANG90) {
>> ANGLETOFINESHIFT]) const int slope = FixedDiv(ady, adx) >> DBITS;
: 0; 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 if (!dist) // killough 11/98: handle zero-distance as special case
{ {
return true; return true;
} }
if (dist > S_CLIPPING_DIST >> FRACBITS) if (dist >= S_CLIPPING_DIST)
{ {
return false; return false;
} }
@ -107,35 +116,38 @@ static boolean I_MBF_AdjustSoundParams(const mobj_t *listener,
angle >>= ANGLETOFINESHIFT; angle >>= ANGLETOFINESHIFT;
// stereo separation // stereo separation
*sep = NORM_SEP - FixedMul(S_STEREO_SWING >> FRACBITS, finesine[angle]); params->separation -= FixedMul(S_STEREO_SWING, finesine[angle]);
} }
// volume calculation // 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 // 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 // SoM 7/1/02: forceFlipPan accounted for here
if (force_flip_pan) if (force_flip_pan)
{ {
separation = 254 - separation; separation = 254 - separation;
} }
I_OAL_SetVolume(channel, volume); I_OAL_SetVolume(channel, params->volume);
I_OAL_SetPan(channel, separation); I_OAL_SetPan(channel, separation);
} }
@ -165,7 +177,10 @@ const sound_module_t sound_mbf_module =
NULL, NULL,
I_OAL_StartSound, I_OAL_StartSound,
I_OAL_StopSound, I_OAL_StopSound,
I_OAL_PauseSound,
I_OAL_ResumeSound,
I_OAL_SoundIsPlaying, I_OAL_SoundIsPlaying,
I_OAL_SoundIsPaused,
I_OAL_ShutdownSound, I_OAL_ShutdownSound,
I_OAL_ShutdownModule, I_OAL_ShutdownModule,
I_OAL_DeferUpdates, I_OAL_DeferUpdates,

View File

@ -39,10 +39,10 @@
#include "w_wad.h" #include "w_wad.h"
#include "z_zone.h" #include "z_zone.h"
#define OAL_ROLLOFF_FACTOR 1 #define OAL_ROLLOFF_FACTOR 0.5f
#define OAL_SPEED_OF_SOUND 343.3f #define OAL_SPEED_OF_SOUND 343.3f
// 128 map units per 3 meters (https://doomwiki.org/wiki/Map_unit). // 16 mu/ft (https://www.doomworld.com/idgames/docs/editing/metrics)
#define OAL_MAP_UNITS_PER_METER (128.0f / 3.0f) #define OAL_METERS_PER_MAP_UNIT 0.01905f
#define OAL_SOURCE_RADIUS 32.0f #define OAL_SOURCE_RADIUS 32.0f
#define OAL_DEFAULT_PITCH 1.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_POSITION, 0.0f, 0.0f, 0.0f);
alSource3f(oal->sources[channel], AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSource3f(oal->sources[channel], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
alSourcef(oal->sources[channel], AL_ROLLOFF_FACTOR, 0.0f);
alSourcei(oal->sources[channel], AL_ROLLOFF_FACTOR, 0);
alSourcei(oal->sources[channel], AL_SOURCE_RELATIVE, AL_TRUE); 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); 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); alSourcei(oal->sources[channel], AL_SOURCE_RELATIVE, AL_FALSE);
} }
@ -337,8 +336,8 @@ static void UpdateUserSoundSettings(void)
if (oal_snd_module == SND_MODULE_3D) if (oal_snd_module == SND_MODULE_3D)
{ {
oal->absorption = (ALfloat)snd_absorption / 2.0f; oal->absorption = (ALfloat)snd_absorption;
alDopplerFactor((ALfloat)snd_doppler * snd_doppler / 100.0f); alDopplerFactor((ALfloat)snd_doppler / 5.0f);
oal_use_doppler = (snd_doppler > 0); oal_use_doppler = (snd_doppler > 0);
} }
else else
@ -359,9 +358,8 @@ static void ResetParams(void)
{ {
I_OAL_ResetSource2D(i); I_OAL_ResetSource2D(i);
alSource3i(oal->sources[i], AL_DIRECTION, 0, 0, 0); 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);
alSourcei(oal->sources[i], AL_REFERENCE_DISTANCE, alSourcei(oal->sources[i], AL_MAX_DISTANCE, S_CLIPPING_DIST);
S_CLOSE_DIST >> FRACBITS);
} }
// Spatialization is required even for 2D panning emulation. // Spatialization is required even for 2D panning emulation.
if (oal->SOFT_source_spatialize) if (oal->SOFT_source_spatialize)
@ -378,12 +376,12 @@ static void ResetParams(void)
alListeneriv(AL_ORIENTATION, default_orientation); alListeneriv(AL_ORIENTATION, default_orientation);
if (oal->EXT_EFX) 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. // Context state parameters.
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // OpenAL 1.1 Specs, 3.4.2. 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(); UpdateUserSoundSettings();
} }
@ -735,6 +733,33 @@ void I_OAL_StopSound(int channel)
alSourceStop(oal->sources[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) boolean I_OAL_SoundIsPlaying(int channel)
{ {
ALint state; ALint state;
@ -749,6 +774,20 @@ boolean I_OAL_SoundIsPlaying(int channel)
return (state == AL_PLAYING); 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) void I_OAL_SetVolume(int channel, int volume)
{ {
if (!oal) if (!oal)

View File

@ -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_StopSound(int channel);
void I_OAL_PauseSound(int channel);
void I_OAL_ResumeSound(int channel);
boolean I_OAL_SoundIsPlaying(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_SetVolume(int channel, int volume);
void I_OAL_SetPan(int channel, int separation); void I_OAL_SetPan(int channel, int separation);

View File

@ -38,7 +38,7 @@ static LPALBUFFERCALLBACKSOFT alBufferCallbackSOFT;
static ALuint callback_buffer; static ALuint callback_buffer;
static ALuint callback_source; static ALuint callback_source;
#define SQUARE_WAVE_AMP 0x2000 #define SQUARE_WAVE_AMP 0x1000 // Chocolate Doom: 0x2000
static SDL_mutex *sound_lock; static SDL_mutex *sound_lock;
static int mixing_freq; 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, static boolean I_PCS_AdjustSoundParams(const mobj_t *listener,
const mobj_t *source, int chanvol, const mobj_t *source,
int *vol, int *sep, int *pri) sfxparams_t *params)
{ {
fixed_t adx, ady, approx_dist; fixed_t adx, ady;
int approx_dist;
if (!source || source == players[displayplayer].mo) 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); ady = abs(listener->y - source->y);
// From _GG1_ p.428. Appox. eucledian distance fast. // 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; return false;
} }
@ -413,19 +414,19 @@ static boolean I_PCS_AdjustSoundParams(const mobj_t *listener,
// volume calculation // volume calculation
if (approx_dist < S_CLOSE_DIST) if (approx_dist < S_CLOSE_DIST)
{ {
*vol = snd_SfxVolume; params->volume = snd_SfxVolume;
} }
else else
{ {
// distance effect // distance effect
*vol = (snd_SfxVolume * ((S_CLIPPING_DIST - approx_dist) >> FRACBITS)) params->volume =
/ S_ATTENUATOR; 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 // adjust PC Speaker volume
alSourcef(callback_source, AL_GAIN, (float)snd_SfxVolume / 15); alSourcef(callback_source, AL_GAIN, (float)snd_SfxVolume / 15);
@ -502,7 +503,10 @@ const sound_module_t sound_pcs_module =
NULL, NULL,
I_PCS_StartSound, I_PCS_StartSound,
I_PCS_StopSound, I_PCS_StopSound,
NULL,
NULL,
I_PCS_SoundIsPlaying, I_PCS_SoundIsPlaying,
NULL,
I_PCS_ShutdownSound, I_PCS_ShutdownSound,
I_PCS_ShutdownModule, I_PCS_ShutdownModule,
I_OAL_DeferUpdates, I_OAL_DeferUpdates,

View File

@ -78,8 +78,6 @@ typedef struct
sfxinfo_t *sfx; sfxinfo_t *sfx;
boolean enabled; boolean enabled;
// haleyjd 06/16/08: unique id number
int idnum;
} channel_info_t; } channel_info_t;
static channel_info_t channelinfo[MAX_CHANNELS]; static channel_info_t channelinfo[MAX_CHANNELS];
@ -123,14 +121,14 @@ static void StopChannel(int channel)
// Returns false if no sound should be played. // Returns false if no sound should be played.
// //
boolean I_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, 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) if (!snd_init)
{ {
return false; 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 // Changes sound parameters in response to stereo panning and relative location
// change. // change.
// //
void I_UpdateSoundParams(int channel, int volume, int separation) void I_UpdateSoundParams(int channel, const sfxparams_t *params)
{ {
if (!snd_init) if (!snd_init)
{ {
@ -153,7 +151,7 @@ void I_UpdateSoundParams(int channel, int volume, int separation)
} }
#endif #endif
sound_module->UpdateSoundParams(channel, volume, separation); sound_module->UpdateSoundParams(channel, params);
} }
void I_UpdateListenerParams(const mobj_t *listener) 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 // active sounds, which is maintained as a given number
// of internal channels. Returns a free channel. // 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; int channel;
if (!snd_init) 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].sfx = sfx;
channelinfo[channel].enabled = true; 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]; float step = (pitch == NORM_PITCH) ? 1.0f : steptable[pitch];
@ -336,6 +332,46 @@ void I_StopSound(int channel)
StopChannel(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 // I_SoundIsPlaying
// //
@ -358,29 +394,21 @@ boolean I_SoundIsPlaying(int channel)
return sound_module->SoundIsPlaying(channel); return sound_module->SoundIsPlaying(channel);
} }
// boolean I_SoundIsPaused(int 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)
{ {
if (!snd_init) if (!snd_init || !sound_module->SoundIsPaused)
{ {
return 0; return false;
} }
#ifdef RANGECHECK #ifdef RANGECHECK
if (channel < 0 || channel >= MAX_CHANNELS) if (channel < 0 || channel >= MAX_CHANNELS)
{ {
I_Error("I_SoundID: channel out of range\n"); I_Error("I_SoundIsPaused: channel out of range");
} }
#endif #endif
return channelinfo[channel].idnum; return sound_module->SoundIsPaused(channel);
} }
// //

View File

@ -29,7 +29,7 @@
// when to clip out sounds // when to clip out sounds
// Does not fit the large outdoor areas. // 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. // Distance to origin when sounds should be maxed out.
// This should relate to movement clipping resolution // This should relate to movement clipping resolution
@ -39,9 +39,9 @@
// killough 12/98: restore original // killough 12/98: restore original
// #define S_CLOSE_DIST (160<<FRACBITS) // #define S_CLOSE_DIST (160<<FRACBITS)
#define S_CLOSE_DIST (200 << FRACBITS) #define S_CLOSE_DIST 200
#define S_ATTENUATOR ((S_CLIPPING_DIST - S_CLOSE_DIST) >> FRACBITS) #define S_ATTENUATOR (S_CLIPPING_DIST - S_CLOSE_DIST)
// Adjustable by menu. // Adjustable by menu.
// [FG] moved here from i_sound.c // [FG] moved here from i_sound.c
@ -50,7 +50,7 @@
#define NORM_PITCH 128 #define NORM_PITCH 128
#define NORM_PRIORITY 64 #define NORM_PRIORITY 64
#define NORM_SEP 128 #define NORM_SEP 128
#define S_STEREO_SWING (96 << FRACBITS) #define S_STEREO_SWING 96
#define SND_SAMPLERATE 44100 #define SND_SAMPLERATE 44100
@ -65,8 +65,8 @@ void I_ShutdownSound(void);
// //
struct mobj_s; struct mobj_s;
struct sfxinfo_s; struct sfxinfo_s;
struct sfxparams_s;
typedef struct sound_module_s typedef struct sound_module_s
{ {
@ -75,13 +75,16 @@ typedef struct sound_module_s
boolean (*AllowReinitSound)(void); boolean (*AllowReinitSound)(void);
boolean (*CacheSound)(struct sfxinfo_s *sfx); boolean (*CacheSound)(struct sfxinfo_s *sfx);
boolean (*AdjustSoundParams)(const struct mobj_s *listener, boolean (*AdjustSoundParams)(const struct mobj_s *listener,
const struct mobj_s *source, int chanvol, const struct mobj_s *source,
int *vol, int *sep, int *pri); struct sfxparams_s *params);
void (*UpdateSoundParams)(int channel, int vol, int sep); void (*UpdateSoundParams)(int channel, const struct sfxparams_s *params);
void (*UpdateListenerParams)(const struct mobj_s *listener); void (*UpdateListenerParams)(const struct mobj_s *listener);
boolean (*StartSound)(int channel, struct sfxinfo_s *sfx, float pitch); boolean (*StartSound)(int channel, struct sfxinfo_s *sfx, float pitch);
void (*StopSound)(int channel); void (*StopSound)(int channel);
void (*PauseSound)(int channel);
void (*ResumeSound)(int channel);
boolean (*SoundIsPlaying)(int channel); boolean (*SoundIsPlaying)(int channel);
boolean (*SoundIsPaused)(int channel);
void (*ShutdownSound)(void); void (*ShutdownSound)(void);
void (*ShutdownModule)(void); void (*ShutdownModule)(void);
void (*DeferUpdates)(void); void (*DeferUpdates)(void);
@ -113,32 +116,34 @@ void I_SetChannels(void);
int I_GetSfxLumpNum(struct sfxinfo_s *sfxinfo); int I_GetSfxLumpNum(struct sfxinfo_s *sfxinfo);
// Starts a sound in a particular sound channel. // 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. // Stops a sound channel.
void I_StopSound(int handle); void I_StopSound(int handle);
void I_PauseSound(int handle);
void I_ResumeSound(int handle);
// Called by S_*() functions // Called by S_*() functions
// to see if a channel is still playing. // to see if a channel is still playing.
// Returns 0 if no longer playing, 1 if playing. // Returns 0 if no longer playing, 1 if playing.
boolean I_SoundIsPlaying(int handle); boolean I_SoundIsPlaying(int handle);
boolean I_SoundIsPaused(int handle);
// Outputs adjusted volume, separation, and priority from the sound module. // Outputs adjusted volume, separation, and priority from the sound module.
// Returns false if no sound should be played. // Returns false if no sound should be played.
boolean I_AdjustSoundParams(const struct mobj_s *listener, boolean I_AdjustSoundParams(const struct mobj_s *listener,
const struct mobj_s *source, int chanvol, int *vol, const struct mobj_s *source,
int *sep, int *pri); struct sfxparams_s *params);
// Updates the volume, separation, // Updates the volume, separation,
// and pitch of a sound channel. // 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_UpdateListenerParams(const struct mobj_s *listener);
void I_DeferSoundUpdates(void); void I_DeferSoundUpdates(void);
void I_ProcessSoundUpdates(void); void I_ProcessSoundUpdates(void);
// haleyjds
int I_SoundID(int handle);
// //
// MUSIC I/O // MUSIC I/O
// //

View File

@ -253,6 +253,22 @@ static void M_ExtHelpNextScreen(int choice);
static void M_ExtHelp(int choice); static void M_ExtHelp(int choice);
static void M_DrawExtHelp(void); 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 // SetNextMenu
// //
@ -1700,12 +1716,14 @@ static void M_QuickLoad(void)
{ {
if (netgame && !demoplayback) // killough 5/26/98: add !demoplayback if (netgame && !demoplayback) // killough 5/26/98: add !demoplayback
{ {
M_StartSound(sfx_swtchn);
M_StartMessage(s_QLOADNET, NULL, false); // Ty 03/27/98 - externalized M_StartMessage(s_QLOADNET, NULL, false); // Ty 03/27/98 - externalized
return; return;
} }
if (demorecording) // killough 5/26/98: exclude during demo recordings if (demorecording) // killough 5/26/98: exclude during demo recordings
{ {
M_StartSound(sfx_swtchn);
M_StartMessage("you can't quickload\n" M_StartMessage("you can't quickload\n"
"while recording a demo!\n\n" PRESSKEY, "while recording a demo!\n\n" PRESSKEY,
NULL, false); // killough 5/26/98: not externalized NULL, false); // killough 5/26/98: not externalized
@ -1746,6 +1764,7 @@ static void M_EndGameResponse(int ch)
quickSaveSlot = -1; quickSaveSlot = -1;
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
S_StopChannels();
MN_ClearMenus(); MN_ClearMenus();
D_StartTitle(); D_StartTitle();
} }
@ -2168,6 +2187,7 @@ void MN_ClearMenus(void)
I_SetSensorEventState(false); I_SetSensorEventState(false);
G_ClearInput(); G_ClearInput();
M_ResumeSound();
} }
static boolean MenuBack(void) static boolean MenuBack(void)
@ -2437,19 +2457,15 @@ boolean M_ShortcutResponder(const event_t *ev)
if (M_InputActivated(input_help)) // Help key if (M_InputActivated(input_help)) // Help key
{ {
MN_StartControlPanel(); MN_StartControlPanel();
currentMenu = &HelpDef; // killough 10/98: new help screen currentMenu = &HelpDef; // killough 10/98: new help screen
currentMenu->prevMenu = NULL; currentMenu->prevMenu = NULL;
itemOn = 0; itemOn = 0;
M_StartSound(sfx_swtchn);
return true; return true;
} }
if (M_InputActivated(input_savegame)) // Save Game if (M_InputActivated(input_savegame)) // Save Game
{ {
MN_StartControlPanel(); MN_StartControlPanel();
M_StartSound(sfx_swtchn);
M_SaveGame(0); M_SaveGame(0);
return true; return true;
} }
@ -2457,7 +2473,6 @@ boolean M_ShortcutResponder(const event_t *ev)
if (M_InputActivated(input_loadgame)) // Load Game if (M_InputActivated(input_loadgame)) // Load Game
{ {
MN_StartControlPanel(); MN_StartControlPanel();
M_StartSound(sfx_swtchn);
M_LoadGame(0); M_LoadGame(0);
return true; return true;
} }
@ -2467,19 +2482,18 @@ boolean M_ShortcutResponder(const event_t *ev)
MN_StartControlPanel(); MN_StartControlPanel();
currentMenu = &SoundDef; currentMenu = &SoundDef;
itemOn = currentMenu->lastOn; itemOn = currentMenu->lastOn;
M_StartSound(sfx_swtchn);
return true; return true;
} }
if (M_InputActivated(input_quicksave)) // Quicksave if (M_InputActivated(input_quicksave)) // Quicksave
{ {
M_StartSound(sfx_swtchn);
M_QuickSave(); M_QuickSave();
return true; return true;
} }
if (M_InputActivated(input_endgame)) // End game if (M_InputActivated(input_endgame)) // End game
{ {
M_PauseSound();
M_StartSound(sfx_swtchn); M_StartSound(sfx_swtchn);
M_EndGame(0); M_EndGame(0);
return true; return true;
@ -2494,13 +2508,13 @@ boolean M_ShortcutResponder(const event_t *ev)
if (M_InputActivated(input_quickload)) // Quickload if (M_InputActivated(input_quickload)) // Quickload
{ {
M_StartSound(sfx_swtchn);
M_QuickLoad(); M_QuickLoad();
return true; return true;
} }
if (M_InputActivated(input_quit)) // Quit DOOM if (M_InputActivated(input_quit)) // Quit DOOM
{ {
M_PauseSound();
M_StartSound(sfx_swtchn); M_StartSound(sfx_swtchn);
M_QuitDOOM(0); M_QuitDOOM(0);
return true; return true;
@ -3088,6 +3102,7 @@ boolean M_Responder(event_t *ev)
I_SetSensorEventState(false); I_SetSensorEventState(false);
G_ClearInput(); G_ClearInput();
menuactive = false; menuactive = false;
M_ResumeSound();
M_StartSound(sfx_swtchx); M_StartSound(sfx_swtchx);
return true; return true;
} }
@ -3117,7 +3132,6 @@ boolean M_Responder(event_t *ev)
{ {
I_ShowMouseCursor(menu_input != pad_mode); I_ShowMouseCursor(menu_input != pad_mode);
MN_StartControlPanel(); MN_StartControlPanel();
M_StartSound(sfx_swtchn);
return true; return true;
} }
return false; return false;
@ -3372,6 +3386,9 @@ void MN_StartControlPanel(void)
I_SetSensorEventState(true); I_SetSensorEventState(true);
G_ClearInput(); G_ClearInput();
M_PauseSound();
M_StartSound(sfx_swtchn);
} }
// //

View File

@ -2588,7 +2588,7 @@ static setup_menu_t sfx_settings1[] = {
MI_GAP, 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}, .strings_id = str_percent, .action = SetSoundModule},
MI_END MI_END

View File

@ -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 // NULL head of sector list // phares 3/13/98
mobj->touching_sectorlist = NULL; 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 // set subsector and/or block links
P_SetThingPosition(mobj); 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->z = z == ONFLOORZ ? mobj->floorz : z == ONCEILINGZ ?
mobj->ceilingz - mobj->height : z; 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->thinker.function.p1 = (actionf_p1)P_MobjThinker;
mobj->above_thing = mobj->below_thing = 0; // phares mobj->above_thing = mobj->below_thing = 0; // phares

View File

@ -46,12 +46,11 @@ typedef struct channel_s
{ {
sfxinfo_t *sfxinfo; // sound information (if null, channel avail.) sfxinfo_t *sfxinfo; // sound information (if null, channel avail.)
const mobj_t *origin; // origin of sound 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 handle; // handle of the sound being played
int o_priority; // haleyjd 09/27/06: stored priority value int o_priority; // haleyjd 09/27/06: stored priority value
int priority; // current priority value int priority; // current priority value
int singularity; // haleyjd 09/27/06: stored singularity value int singularity; // haleyjd 09/27/06: stored singularity value
int idnum; // haleyjd 09/30/06: unique id num for sound event
} channel_t; } channel_t;
// the set of channels available // the set of channels available
@ -129,9 +128,9 @@ void S_StopChannels(void)
// haleyjd: added priority scaling // haleyjd: added priority scaling
// //
static int S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, 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 // haleyjd 09/27/06: fixed priority/singularity bugs
// Note that a higher priority number means lower priority! // Note that a higher priority number means lower priority!
// //
static int S_getChannel(const mobj_t *origin, sfxinfo_t *sfxinfo, int priority, static int S_getChannel(const mobj_t *origin, int priority, int singularity)
int singularity)
{ {
// channel number to use // channel number to use
int cnum; 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, static void StartSound(const mobj_t *origin, int sfx_id,
pitchrange_t pitch_range, rumble_type_t rumble_type) pitchrange_t pitch_range, rumble_type_t rumble_type)
{ {
int sep, pitch, o_priority, priority, singularity, cnum, handle; int pitch, o_priority, singularity, cnum, handle;
int volumeScale = 127; sfxparams_t params;
int volume = snd_SfxVolume;
sfxinfo_t *sfx; sfxinfo_t *sfx;
// jff 1/22/98 return if sound is not enabled // 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 // Initialize sound parameters
pitch = NORM_PITCH; pitch = NORM_PITCH;
params.volume_scale = 127;
// haleyjd: modified so that priority value is always used // haleyjd: modified so that priority value is always used
// haleyjd: also modified to get and store proper singularity value // haleyjd: also modified to get and store proper singularity value
o_priority = priority = sfx->priority; o_priority = params.priority = sfx->priority;
singularity = sfx->singularity; singularity = sfx->singularity;
// Check to see if it is audible, modify the params // Check to see if it is audible, modify the params
// killough 3/7/98, 4/25/98: code rearranged slightly // killough 3/7/98, 4/25/98: code rearranged slightly
if (!S_AdjustSoundParams(players[displayplayer].mo, origin, volumeScale, if (!S_AdjustSoundParams(players[displayplayer].mo, origin, &params))
&volume, &sep, &priority))
{ {
return; return;
} }
@ -281,7 +278,7 @@ static void StartSound(const mobj_t *origin, int sfx_id,
} }
// try to find a channel // try to find a channel
if ((cnum = S_getChannel(origin, sfx, priority, singularity)) < 0) if ((cnum = S_getChannel(origin, params.priority, singularity)) < 0)
{ {
return; return;
} }
@ -294,7 +291,6 @@ static void StartSound(const mobj_t *origin, int sfx_id,
#endif #endif
channels[cnum].sfxinfo = sfx; channels[cnum].sfxinfo = sfx;
channels[cnum].origin = origin;
while (sfx->link) 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. // Assigns the handle to one of the channels in the mix/output buffer.
handle = I_StartSound(sfx, volume, sep, pitch); handle = I_StartSound(sfx, &params, pitch);
// haleyjd: check to see if the sound was started // haleyjd: check to see if the sound was started
if (handle >= 0) if (handle >= 0)
{ {
channels[cnum].handle = handle;
// haleyjd 05/29/06: record volume scale value // haleyjd 05/29/06: record volume scale value
// haleyjd 09/27/06: store priority and singularity values (!!!) // haleyjd 09/27/06: store priority and singularity values (!!!)
channels[cnum].volume = volumeScale; channels[cnum].origin = origin;
channels[cnum].o_priority = o_priority; // original priority channels[cnum].handle = handle;
channels[cnum].priority = priority; // scaled priority 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].singularity = singularity;
channels[cnum].idnum = I_SoundID(handle); // unique instance id
if (rumble_type != RUMBLE_NONE) 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. // Stop and resume music, during game PAUSE.
// //
void S_PauseSound(void) void S_PauseMusic(void)
{ {
if (mus_playing && !mus_paused) 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) if (mus_playing && mus_paused)
{ {
@ -554,56 +589,48 @@ void S_UpdateSounds(const mobj_t *listener)
} }
I_DeferSoundUpdates(); I_DeferSoundUpdates();
I_UpdateListenerParams(listener);
for (cnum = 0; cnum < snd_channels; ++cnum) for (cnum = 0; cnum < snd_channels; ++cnum)
{ {
channel_t *c = &channels[cnum]; channel_t *c = &channels[cnum];
sfxinfo_t *sfx = c->sfxinfo; 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 (sfx)
{ {
if (I_SoundIsPlaying(c->handle)) 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 // check non-local sounds for distance clipping
// or modify their params // or modify their params
if (c->origin && listener != c->origin) // killough 3/20/98 if (c->origin && listener != c->origin) // killough 3/20/98
{ {
if (!S_AdjustSoundParams(listener, c->origin, c->volume, // initialize parameters
&volume, &sep, &pri)) 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, &params))
{ {
S_StopChannel(cnum); I_UpdateSoundParams(c->handle, &params);
c->priority = params.priority; // haleyjd
} }
else else
{ {
I_UpdateSoundParams(c->handle, volume, sep); S_StopChannel(cnum);
c->priority = pri; // haleyjd
} }
} }
I_UpdateRumbleParams(listener, c->origin, c->handle); 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); S_StopChannel(cnum);
} }
} }
} }
I_UpdateListenerParams(listener);
I_ProcessSoundUpdates(); I_ProcessSoundUpdates();
I_UpdateRumble(); I_UpdateRumble();
} }

View File

@ -102,10 +102,13 @@ void S_ChangeMusInfoMusic(int lumpnum, int looping);
// Stops the music fer sure. // Stops the music fer sure.
void S_StopMusic(void); void S_StopMusic(void);
// Stop and resume music, during game PAUSE.
void S_PauseSound(void); void S_PauseSound(void);
void S_ResumeSound(void); void S_ResumeSound(void);
// Stop and resume music, during game PAUSE.
void S_PauseMusic(void);
void S_ResumeMusic(void);
void S_RestartMusic(void); void S_RestartMusic(void);
// //

View File

@ -23,6 +23,14 @@
#include "doomtype.h" #include "doomtype.h"
typedef struct sfxparams_s
{
int volume_scale;
int volume;
int separation;
int priority;
} sfxparams_t;
// //
// SoundFX struct. // SoundFX struct.
// //