From a087d566ee7b000caf3c93a37bf024dbe1d406d4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 Dec 2019 19:17:37 +0100 Subject: [PATCH] - more refactoring on SW's sound system: * removed all cases of getting a sound handle and checking it later. * In particular, refactor the cases where the handle is stored in a static local variable. These are fundamentally unsafe because nothing maintains these local variables. * finished rewriting the PlaySound function. Let's hope this is what was intended, the entire coding here was not particularly good, mixing high and low level sound handling all on the same level. * call the update routine each tic and not merely every 4th or 8th one, this kind of granularity was ok in 1997 but not with a modern sound engine. --- source/common/gamecvars.cpp | 4 +- source/common/sound/backend/i_soundinternal.h | 2 +- source/common/sound/s_sound.cpp | 16 +- source/common/sound/s_soundinternal.h | 3 +- source/sw/src/d_menu.cpp | 17 +- source/sw/src/game.cpp | 23 +- source/sw/src/game.h | 37 +- source/sw/src/jsector.cpp | 18 +- source/sw/src/miscactr.cpp | 155 +++-- source/sw/src/ninja.cpp | 2 - source/sw/src/panel.cpp | 20 +- source/sw/src/player.cpp | 4 +- source/sw/src/ripper2.cpp | 5 +- source/sw/src/save.cpp | 2 - source/sw/src/sector.cpp | 1 - source/sw/src/sounds.cpp | 542 ++++++++---------- source/sw/src/sounds.h | 2 +- source/sw/src/zilla.cpp | 11 +- 18 files changed, 373 insertions(+), 491 deletions(-) diff --git a/source/common/gamecvars.cpp b/source/common/gamecvars.cpp index 65c8be757..2e2892ee9 100644 --- a/source/common/gamecvars.cpp +++ b/source/common/gamecvars.cpp @@ -96,7 +96,7 @@ CUSTOM_CVARD(Int, cl_crosshairscale, 50, CVAR_ARCHIVE, "changes the size of the CUSTOM_CVARD(Int, cl_autoaim, 1, CVAR_ARCHIVE|CVAR_USERINFO, "enable/disable weapon autoaim") { - if (self < 0 || self > (playing_blood? 2 : 3)) self = 1; // The Shadow Warrior backend only has a bool for this. + if (self < 0 || self > ((g_gameType & GAMEFLAG_BLOOD)? 2 : 3)) self = 1; // The Shadow Warrior backend only has a bool for this. //UpdatePlayerFromMenu(); todo: networking (only operational in EDuke32 frontend anyway.) }; @@ -104,7 +104,7 @@ CUSTOM_CVARD(Int, cl_weaponswitch, 3, CVAR_ARCHIVE|CVAR_USERINFO, "enable/disabl { if (self < 0) self = 0; - if (self > 3 && playing_blood) self = 3; + if (self > 3 && (g_gameType & GAMEFLAG_BLOOD)) self = 3; if (self > 7) self = 7; //UpdatePlayerFromMenu(); todo: networking (only operational in EDuke32 frontend anyway.) } diff --git a/source/common/sound/backend/i_soundinternal.h b/source/common/sound/backend/i_soundinternal.h index 08dd311a2..a2bdf81e2 100644 --- a/source/common/sound/backend/i_soundinternal.h +++ b/source/common/sound/backend/i_soundinternal.h @@ -28,7 +28,7 @@ enum EChanFlag CHANF_FORGETTABLE = 4, // internal: Forget channel data when sound stops. CHANF_JUSTSTARTED = 512, // internal: Sound has not been updated yet. CHANF_ABSTIME = 1024, // internal: Start time is absolute and does not depend on current time. - CHANF_VIRTUAL = 2048, // internal: Channel is currently virtual + CHANF_VIRTUAL = 2048, // Channel only plays on demand but won't get deleted automatically. CHANF_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something. CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them. }; diff --git a/source/common/sound/s_sound.cpp b/source/common/sound/s_sound.cpp index c9b011d40..c7ca5f9c1 100644 --- a/source/common/sound/s_sound.cpp +++ b/source/common/sound/s_sound.cpp @@ -479,7 +479,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, // If the sound is blocked and not looped, return now. If the sound // is blocked and looped, pretend to play it so that it can // eventually play for real. - if ((chanflags & (CHANF_EVICTED | CHANF_LOOP)) == CHANF_EVICTED) + if ((chanflags & (CHANF_EVICTED | CHANF_LOOP | CHANF_VIRTUAL)) == CHANF_EVICTED) { return NULL; } @@ -550,7 +550,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, // sound is paused and a non-looped sound is being started. // Such a sound would play right after unpausing which wouldn't sound right. - if (!(chanflags & CHANF_LOOP) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE)) && SoundPaused) + if (!(chanflags & (CHANF_LOOP|CHANF_VIRTUAL)) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE)) && SoundPaused) { return NULL; } @@ -587,7 +587,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL); } } - if (chan == NULL && (chanflags & CHANF_LOOP)) + if (chan == NULL && (chanflags & CHANF_LOOP|CHANF_VIRTUAL)) { chan = (FSoundChan*)GetChannel(NULL); GSnd->MarkStartTime(chan); @@ -1014,7 +1014,7 @@ void SoundEngine::RelinkSound (int sourcetype, const void *from, const void *to, { chan->Source = to; } - else if (!(chan->ChanFlags & CHANF_LOOP) && optpos) + else if (!(chan->ChanFlags & (CHANF_LOOP|CHANF_VIRTUAL)) && optpos) { chan->Source = NULL; chan->SourceType = SOURCE_Unattached; @@ -1154,7 +1154,7 @@ bool SoundEngine::IsSourcePlayingSomething (int sourcetype, const void *actor, i { for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - if (chan->SourceType == sourcetype && chan->Source == actor) + if (chan->SourceType == sourcetype && (sourcetype == SOURCE_None || sourcetype == SOURCE_Unattached || chan->Source == actor)) { if (channel == 0 || chan->EntChannel == channel) { @@ -1217,7 +1217,7 @@ void SoundEngine::RestoreEvictedChannel(FSoundChan *chan) if (chan->ChanFlags & CHANF_EVICTED) { RestartChannel(chan); - if (!(chan->ChanFlags & CHANF_LOOP)) + if (!(chan->ChanFlags & (CHANF_LOOP|CHANF_VIRTUAL))) { if (chan->ChanFlags & CHANF_EVICTED) { // Still evicted and not looping? Forget about it. @@ -1229,7 +1229,7 @@ void SoundEngine::RestoreEvictedChannel(FSoundChan *chan) } } } - else if (chan->SysChannel == NULL && (chan->ChanFlags & (CHANF_FORGETTABLE | CHANF_LOOP)) == CHANF_FORGETTABLE) + else if (chan->SysChannel == NULL && (chan->ChanFlags & (CHANF_FORGETTABLE | CHANF_LOOP | CHANF_VIRTUAL)) == CHANF_FORGETTABLE) { ReturnChannel(chan); } @@ -1345,7 +1345,7 @@ void SoundEngine::ChannelEnded(FISoundChannel *ichan) { evicted = false; } - else if (schan->ChanFlags & (CHANF_LOOP | CHANF_EVICTED)) + else if (schan->ChanFlags & (CHANF_LOOP | CHANF_VIRTUAL | CHANF_EVICTED)) { evicted = true; } diff --git a/source/common/sound/s_soundinternal.h b/source/common/sound/s_soundinternal.h index c16451aa6..0941ea768 100644 --- a/source/common/sound/s_soundinternal.h +++ b/source/common/sound/s_soundinternal.h @@ -168,13 +168,14 @@ struct FSoundChan : public FISoundChannel FSoundID OrgID; // Sound ID of sound used to start this channel. float Volume; int16_t Pitch; // Pitch variation. - uint8_t EntChannel; // Actor's sound channel. + int32_t EntChannel; // Actor's sound channel. int8_t Priority; int16_t NearLimit; uint8_t SourceType; float LimitRange; const void *Source; float Point[3]; // Sound is not attached to any source. + int UserData; // One word of data for user-specific data }; diff --git a/source/sw/src/d_menu.cpp b/source/sw/src/d_menu.cpp index 5fbe45dab..79834fc65 100644 --- a/source/sw/src/d_menu.cpp +++ b/source/sw/src/d_menu.cpp @@ -52,6 +52,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "colormap.h" #include "config.h" #include "menu/menu.h" +#include "sound/s_soundinternal.h" +#include "sounds.h" #include "../../glbackend/glbackend.h" @@ -237,17 +239,20 @@ void GameInterface::StartGame(FGameStartup& gs) //InitNewGame(); if (Skill == 0) - handle = PlaySound(DIGI_TAUNTAI3, v3df_none); + PlaySound(DIGI_TAUNTAI3, v3df_none, CHAN_VOICE); else if (Skill == 1) - handle = PlaySound(DIGI_NOFEAR, v3df_none); + PlaySound(DIGI_NOFEAR, v3df_none, CHAN_VOICE); else if (Skill == 2) - handle = PlaySound(DIGI_WHOWANTSWANG, v3df_none); + PlaySound(DIGI_WHOWANTSWANG, v3df_none, CHAN_VOICE); else if (Skill == 3) - handle = PlaySound(DIGI_NOPAIN, v3df_none); + PlaySound(DIGI_NOPAIN, v3df_none, CHAN_VOICE); if (handle > FX_Ok) - while (FX_SoundActive(handle)) - handleevents(); + while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) + { + DoUpdateSounds(); + handleevents(); + } } FSavegameInfo GameInterface::GetSaveSig() diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp index 489b073eb..90c341a5c 100644 --- a/source/sw/src/game.cpp +++ b/source/sw/src/game.cpp @@ -98,6 +98,7 @@ Things required to make savegames work: #include "statistics.h" #include "gstrings.h" #include "mapinfo.h" +#include "sound/s_soundinternal.h" //#include "crc32.h" @@ -1309,7 +1310,6 @@ TerminateLevel(void) memset(Track, 0, sizeof(Track)); StopSound(); - Terminate3DSounds(); // Kill the 3d sounds linked list // Clear all anims and any memory associated with them // Clear before killing sprites - save a little time @@ -1604,19 +1604,24 @@ void CreditsLevel(void) videoNextPage(); // Lo Wang feel like singing! - handle = PlaySound(DIGI_JG95012, v3df_none); - - if (handle > 0) - while (FX_SoundActive(handle)) ; + PlaySound(DIGI_JG95012, v3df_none, CHAN_VOICE); + while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) + { + DoUpdateSounds(); + handleevents(); + } // try 14 then 2 then quit if (!PlaySong(nullptr, ThemeSongs[5], ThemeTrack[5], true)) { if (!PlaySong(nullptr, nullptr, 2, true)) { - handle = PlaySound(DIGI_NOLIKEMUSIC, v3df_none); - if (handle > 0) - while (FX_SoundActive(handle)) handleevents(); + PlaySound(DIGI_NOLIKEMUSIC, v3df_none, CHAN_VOICE); + while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) + { + DoUpdateSounds(); + handleevents(); + } return; } } @@ -2255,7 +2260,6 @@ void BonusScreen(PLAYERp pp) } StopSound(); - Terminate3DSounds(); } void EndGameSequence(void) @@ -2471,7 +2475,6 @@ void StatScreen(PLAYERp mpp) } StopSound(); - Terminate3DSounds(); } void GameIntro(void) diff --git a/source/sw/src/game.h b/source/sw/src/game.h index 3de794794..2ee384cc3 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -1210,7 +1210,6 @@ struct PLAYERstruct unsigned char WpnShotgunLastShell; // Number of last shell fired unsigned char WpnRailType; // Normal Rail Gun or EMP Burst Mode SWBOOL Bloody; // Is player gooey from the slaughter? - int nukevochandle; // Stuff for the Nuke SWBOOL InitingNuke; SWBOOL TestNukeInit; SWBOOL NukeInitialized; // Nuke already has counted down @@ -2067,30 +2066,48 @@ short ActorFindTrack(short SpriteNum, int8_t player_dir, int track_type, short * SECT_USERp GetSectUser(short sectnum); +// Some sounds were checked by storing handles in static local variables. +// Problems with this design: +// 1. The variables were unmaintained and could refer to handles that had been reused already. +// 2. No proper sound ownership tracking. +// 3. In some cases items that were supposed to use the same check referred to different handle variables. +// In short: I was very broken. This is a list of all sound items used this way, now each one gets a dedicated channel +// so that proper checks can be performed and sound ownership be tracked. + +enum +{ + CHAN_ToiletFart = 1000, + CHAN_AnimeMad = 1001, + CHAN_AnimeSing = 1002, + CHAN_CoyHandle = 1003, + CHAN_RipHeart = 1004, +}; + short SoundDist(int x, int y, int z, int basedist); short SoundAngle(int x, int y); //void PlaySound(int num, short angle, short vol); -int _PlaySound(int num, SPRITEp sprite, PLAYERp player, vec3_t *pos, Voc3D_Flags flags); -inline int PlaySound(int num, SPRITEp sprite, Voc3D_Flags flags) +int _PlaySound(int num, SPRITEp sprite, PLAYERp player, vec3_t *pos, Voc3D_Flags flags, int channel); +inline void PlaySound(int num, SPRITEp sprite, Voc3D_Flags flags, int channel = 8) { - return _PlaySound(num, sprite, nullptr, nullptr, flags); + _PlaySound(num, sprite, nullptr, nullptr, flags, channel); } -inline int PlaySound(int num, PLAYERp player, Voc3D_Flags flags) +inline void PlaySound(int num, PLAYERp player, Voc3D_Flags flags, int channel = 8) { - return _PlaySound(num, nullptr, player, nullptr, flags); + _PlaySound(num, nullptr, player, nullptr, flags, channel); } -inline int PlaySound(int num, Voc3D_Flags flags) +inline void PlaySound(int num, Voc3D_Flags flags, int channel = 8) { - return _PlaySound(num, nullptr, nullptr, nullptr, flags); + _PlaySound(num, nullptr, nullptr, nullptr, flags, channel); } -inline int PlaySound(int num, vec3_t *pos, Voc3D_Flags flags) +inline void PlaySound(int num, vec3_t *pos, Voc3D_Flags flags, int channel = 8) { - return _PlaySound(num, nullptr, nullptr, pos, flags); + _PlaySound(num, nullptr, nullptr, pos, flags, channel); } int _PlayerSound(int num, PLAYERp pp); inline int PlayerSound(int num, int flags, PLAYERp pp) { return _PlayerSound(num, pp); } void StopPlayerSound(PLAYERp pp); +bool SoundValidAndActive(SPRITEp spr, int channel); ANIMATOR DoActorBeginJump,DoActorJump,DoActorBeginFall,DoActorFall,DoActorDeathMove; diff --git a/source/sw/src/jsector.cpp b/source/sw/src/jsector.cpp index a440b5ba9..65d8793ce 100644 --- a/source/sw/src/jsector.cpp +++ b/source/sw/src/jsector.cpp @@ -83,7 +83,6 @@ void SpawnWallSound(short sndnum, short i) short SpriteNum; vec3_t mid; SPRITEp sp; - int handle; SpriteNum = COVERinsertsprite(0, STAT_DEFAULT); if (SpriteNum < 0) @@ -99,9 +98,7 @@ void SpawnWallSound(short sndnum, short i) setspritez(SpriteNum, &mid); sp = &sprite[SpriteNum]; - handle = PlaySound(sndnum, sp, v3df_dontpan | v3df_doppler); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + PlaySound(sndnum, sp, v3df_dontpan | v3df_doppler); } short @@ -179,7 +176,6 @@ JS_SpriteSetup(void) short SpriteNum = 0, NextSprite, ndx; USERp u; short i, num; - int handle; TRAVERSE_SPRITE_STAT(headspritestat[0], SpriteNum, NextSprite) @@ -250,21 +246,15 @@ JS_SpriteSetup(void) case 2720: case 3143: case 3157: - handle = PlaySound(DIGI_FIRE1, sp, v3df_follow|v3df_dontpan|v3df_doppler); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + PlaySound(DIGI_FIRE1, sp, v3df_follow|v3df_dontpan|v3df_doppler); break; case 795: case 880: - handle = PlaySound(DIGI_WATERFLOW1, sp, v3df_follow|v3df_dontpan|v3df_doppler); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + PlaySound(DIGI_WATERFLOW1, sp, v3df_follow|v3df_dontpan|v3df_doppler); break; case 460: // Wind Chimes - handle = PlaySound(79, sp, v3df_ambient | v3df_init + PlaySound(79, sp, v3df_ambient | v3df_init | v3df_doppler | v3df_follow); - if (handle != -1) - Set3DSoundOwner(SpriteNum); break; } diff --git a/source/sw/src/miscactr.cpp b/source/sw/src/miscactr.cpp index 86f47f723..016e4715d 100644 --- a/source/sw/src/miscactr.cpp +++ b/source/sw/src/miscactr.cpp @@ -168,32 +168,29 @@ int DoToiletGirl(short SpriteNum) { if (RANDOM_RANGE(1000) > 980) { - static int handle; short choose_snd; choose_snd = RANDOM_P2(1024<<4)>>4; - if (!FX_SoundValidAndActive(handle)) + if (!SoundValidAndActive(sp, CHAN_ToiletFart)) { if (choose_snd > 750) - handle = PlaySound(DIGI_TOILETGIRLFART1, sp, v3df_dontpan); + PlaySound(DIGI_TOILETGIRLFART1, sp, v3df_dontpan, CHAN_ToiletFart); else if (choose_snd > 350) - handle = PlaySound(DIGI_TOILETGIRLFART2, sp, v3df_dontpan); + PlaySound(DIGI_TOILETGIRLFART2, sp, v3df_dontpan, CHAN_ToiletFart); else - handle = PlaySound(DIGI_TOILETGIRLFART3, sp, v3df_dontpan); + PlaySound(DIGI_TOILETGIRLFART3, sp, v3df_dontpan, CHAN_ToiletFart); } } } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_ToiletGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -233,14 +230,12 @@ int NullToiletGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_ToiletGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -406,7 +401,6 @@ int DoWashGirl(short SpriteNum) USERp u = User[SpriteNum]; SPRITEp sp = User[SpriteNum]->SpriteP; short rnd_range = 0; - static int handle=0; SWBOOL ICanSee = FALSE; DoActorPickClosePlayer(SpriteNum); @@ -414,14 +408,12 @@ int DoWashGirl(short SpriteNum) if (RANDOM_RANGE(1000) > 980 && u->ShellNum <= 0) { - static int handle; - - if (!FX_SoundValidAndActive(handle)) + if (!SoundValidAndActive(sp, CHAN_AnimeSing)) { if (RANDOM_P2(1024<<4)>>4 > 500) - handle = PlaySound(DIGI_ANIMESING1, sp, v3df_dontpan); + PlaySound(DIGI_ANIMESING1, sp, v3df_dontpan, CHAN_AnimeSing); else - handle = PlaySound(DIGI_ANIMESING2, sp, v3df_dontpan); + PlaySound(DIGI_ANIMESING2, sp, v3df_dontpan, CHAN_AnimeSing); } ChangeState(SpriteNum,s_WashGirlStandScrub); @@ -444,14 +436,12 @@ int DoWashGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_WashGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -488,14 +478,12 @@ int NullWashGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_WashGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -1303,21 +1291,19 @@ int DoCarGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI049, sp, v3df_dontpan); + PlaySound(DIGI_LANI049, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI051, sp, v3df_dontpan); + PlaySound(DIGI_LANI051, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI052, sp, v3df_dontpan); + PlaySound(DIGI_LANI052, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI054, sp, v3df_dontpan); + PlaySound(DIGI_LANI054, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_CarGirlUzi); u->WaitTics = SEC(3)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1358,21 +1344,19 @@ int NullCarGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI049, sp, v3df_dontpan); + PlaySound(DIGI_LANI049, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI051, sp, v3df_dontpan); + PlaySound(DIGI_LANI051, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI052, sp, v3df_dontpan); + PlaySound(DIGI_LANI052, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI054, sp, v3df_dontpan); + PlaySound(DIGI_LANI054, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_CarGirlUzi); u->WaitTics = SEC(3)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1530,21 +1514,19 @@ int DoMechanicGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI073, sp, v3df_dontpan); + PlaySound(DIGI_LANI073, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI075, sp, v3df_dontpan); + PlaySound(DIGI_LANI075, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI077, sp, v3df_dontpan); + PlaySound(DIGI_LANI077, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI079, sp, v3df_dontpan); + PlaySound(DIGI_LANI079, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_MechanicGirlDrill); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1585,21 +1567,19 @@ int NullMechanicGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI073, sp, v3df_dontpan); + PlaySound(DIGI_LANI073, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI075, sp, v3df_dontpan); + PlaySound(DIGI_LANI075, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI077, sp, v3df_dontpan); + PlaySound(DIGI_LANI077, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI079, sp, v3df_dontpan); + PlaySound(DIGI_LANI079, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_MechanicGirlDrill); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1758,9 +1738,7 @@ int DoSailorGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); @@ -1769,14 +1747,14 @@ int DoSailorGirl(short SpriteNum) { ActorCoughItem(SpriteNum); alreadythrew++; - madhandle = PlaySound(DIGI_LANI060, sp, v3df_dontpan); + PlaySound(DIGI_LANI060, sp, v3df_dontpan, CHAN_AnimeMad); } else if (choose > 500) - madhandle = PlaySound(DIGI_LANI063, sp, v3df_dontpan); + PlaySound(DIGI_LANI063, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI065, sp, v3df_dontpan); + PlaySound(DIGI_LANI065, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI066, sp, v3df_dontpan); + PlaySound(DIGI_LANI066, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_SailorGirlThrow); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -1818,9 +1796,7 @@ int NullSailorGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); @@ -1829,14 +1805,14 @@ int NullSailorGirl(short SpriteNum) { ActorCoughItem(SpriteNum); alreadythrew++; - madhandle = PlaySound(DIGI_LANI060, sp, v3df_dontpan); + PlaySound(DIGI_LANI060, sp, v3df_dontpan, CHAN_AnimeMad); } else if (choose > 500) - madhandle = PlaySound(DIGI_LANI063, sp, v3df_dontpan); + PlaySound(DIGI_LANI063, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI065, sp, v3df_dontpan); + PlaySound(DIGI_LANI065, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI066, sp, v3df_dontpan); + PlaySound(DIGI_LANI066, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_SailorGirlThrow); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -1968,7 +1944,6 @@ int DoPruneGirl(short SpriteNum) USERp u = User[SpriteNum]; SPRITEp sp = User[SpriteNum]->SpriteP; short rnd_range = 0; - static int madhandle, coyhandle; SWBOOL ICanSee = FALSE; DoActorPickClosePlayer(SpriteNum); @@ -1978,19 +1953,19 @@ int DoPruneGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = STD_RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI089, sp, v3df_dontpan); + PlaySound(DIGI_LANI089, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI091, sp, v3df_dontpan); + PlaySound(DIGI_LANI091, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI093, sp, v3df_dontpan); + PlaySound(DIGI_LANI093, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI095, sp, v3df_dontpan); + PlaySound(DIGI_LANI095, sp, v3df_dontpan, CHAN_AnimeMad); } u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); u->FlagOwner = 0; @@ -1998,19 +1973,19 @@ int DoPruneGirl(short SpriteNum) } else { - if (!FX_SoundValidAndActive(coyhandle)) + if (!SoundValidAndActive(sp, CHAN_CoyHandle)) { short choose; choose = STD_RANDOM_RANGE(1000); if (choose > 990) - coyhandle = PlaySound(DIGI_PRUNECACKLE, sp, v3df_dontpan); + PlaySound(DIGI_PRUNECACKLE, sp, v3df_dontpan, CHAN_CoyHandle); else if (choose > 985) - coyhandle = PlaySound(DIGI_PRUNECACKLE2, sp, v3df_dontpan); + PlaySound(DIGI_PRUNECACKLE2, sp, v3df_dontpan, CHAN_CoyHandle); else if (choose > 980) - coyhandle = PlaySound(DIGI_PRUNECACKLE3, sp, v3df_dontpan); + PlaySound(DIGI_PRUNECACKLE3, sp, v3df_dontpan, CHAN_CoyHandle); else if (choose > 975) - coyhandle = PlaySound(DIGI_LANI091, sp, v3df_dontpan); + PlaySound(DIGI_LANI091, sp, v3df_dontpan, CHAN_CoyHandle); } } @@ -2047,21 +2022,19 @@ int NullPruneGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI089, sp, v3df_dontpan); + PlaySound(DIGI_LANI089, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI091, sp, v3df_dontpan); + PlaySound(DIGI_LANI091, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI093, sp, v3df_dontpan); + PlaySound(DIGI_LANI093, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI095, sp, v3df_dontpan); + PlaySound(DIGI_LANI095, sp, v3df_dontpan, CHAN_AnimeMad); } u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); u->FlagOwner = 0; diff --git a/source/sw/src/ninja.cpp b/source/sw/src/ninja.cpp index 5a711fc44..22a2938db 100644 --- a/source/sw/src/ninja.cpp +++ b/source/sw/src/ninja.cpp @@ -2258,7 +2258,6 @@ PlayerDeathReset(PLAYERp pp) pp->Bloody = FALSE; pp->TestNukeInit = FALSE; pp->InitingNuke = FALSE; - pp->nukevochandle = 0; pp->NukeInitialized = FALSE; pp->BunnyMode = FALSE; @@ -2348,7 +2347,6 @@ PlayerGameReset(PLAYERp pp) pp->Bloody = FALSE; pp->TestNukeInit = FALSE; pp->InitingNuke = FALSE; - pp->nukevochandle = 0; pp->NukeInitialized = FALSE; pp->BunnyMode = FALSE; pp->SecretsFound = 0; diff --git a/source/sw/src/panel.cpp b/source/sw/src/panel.cpp index bc308300e..699f7f553 100644 --- a/source/sw/src/panel.cpp +++ b/source/sw/src/panel.cpp @@ -46,6 +46,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "fx_man.h" #include "menu/menu.h" #include "swcvar.h" +#include "sound/s_soundinternal.h" BEGIN_SW_NS @@ -996,11 +997,7 @@ int WeaponOperate(PLAYERp pp) if (pp->WpnRocketType != 2 || pp->CurWpn != pp->Wpn[WPN_MICRO]) { pp->InitingNuke = FALSE; - if (pp->nukevochandle > 0) - { - FX_StopSound(pp->nukevochandle); - pp->nukevochandle = 0; - } + soundEngine->StopSound(SOURCE_Player, pp, CHAN_WEAPON); } return 0; @@ -3694,8 +3691,6 @@ PANEL_STATE ps_RetractRail[] = //#define RAIL_XOFF (160+60) #define RAIL_XOFF (160+6) -static int railvochandle=0; - void InitWeaponRail(PLAYERp pp) { @@ -3740,7 +3735,7 @@ InitWeaponRail(PLAYERp pp) pSetState(psp, psp->PresentState); PlaySound(DIGI_RAIL_UP, pp, v3df_follow); - railvochandle = PlaySound(DIGI_RAILREADY, pp, v3df_follow|v3df_dontpan); + PlaySound(DIGI_RAILREADY, pp, v3df_follow|v3df_dontpan); Set3DSoundOwner(psp->PlayerP->PlayerSprite); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); @@ -5007,8 +5002,7 @@ pMicroStandBy(PANEL_SPRITEp psp) PLAYERp pp = psp->PlayerP; pMicroOverlays(psp); - pp->nukevochandle = - PlaySound(DIGI_NUKESTDBY, psp->PlayerP, v3df_follow|v3df_dontpan); + PlaySound(DIGI_NUKESTDBY, pp, v3df_follow|v3df_dontpan, CHAN_WEAPON); } void @@ -5016,8 +5010,7 @@ pMicroCount(PANEL_SPRITEp psp) { PLAYERp pp = psp->PlayerP; - pp->nukevochandle = - PlaySound(DIGI_NUKECDOWN, pp, v3df_follow|v3df_dontpan); + PlaySound(DIGI_NUKECDOWN, pp, v3df_follow|v3df_dontpan, CHAN_WEAPON); } void @@ -5025,8 +5018,7 @@ pMicroReady(PANEL_SPRITEp psp) { PLAYERp pp = psp->PlayerP; - pp->nukevochandle = - PlaySound(DIGI_NUKEREADY, pp, v3df_follow|v3df_dontpan); + PlaySound(DIGI_NUKEREADY, pp, v3df_follow|v3df_dontpan, CHAN_WEAPON); pp->NukeInitialized = TRUE; } diff --git a/source/sw/src/player.cpp b/source/sw/src/player.cpp index 65911f530..d4d881632 100644 --- a/source/sw/src/player.cpp +++ b/source/sw/src/player.cpp @@ -8069,8 +8069,8 @@ domovethings(void) MultiPlayLimits(); - if (MoveSkip8 == 0) // 8=5x 4=10x, 2=20x, 0=40x per second - DoUpdateSounds3D(); + //if (MoveSkip8 == 0) // 8=5x 4=10x, 2=20x, 0=40x per second + DoUpdateSounds(); CorrectPrediction(movefifoplc - 1); diff --git a/source/sw/src/ripper2.cpp b/source/sw/src/ripper2.cpp index 57708c100..11699f604 100644 --- a/source/sw/src/ripper2.cpp +++ b/source/sw/src/ripper2.cpp @@ -1246,12 +1246,11 @@ int DoRipper2StandHeart(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - static int riphearthandle; NullRipper2(SpriteNum); - if (!FX_SoundValidAndActive(riphearthandle)) - riphearthandle = PlaySound(DIGI_RIPPER2HEARTOUT, sp, v3df_none); + if (!SoundValidAndActive(sp, CHAN_RipHeart)) + PlaySound(DIGI_RIPPER2HEARTOUT, sp, v3df_none, CHAN_RipHeart); if ((u->WaitTics -= ACTORMOVETICS) <= 0) NewStateGroup(SpriteNum, sg_Ripper2Run); diff --git a/source/sw/src/save.cpp b/source/sw/src/save.cpp index 2a9ab55ec..b59811e6c 100644 --- a/source/sw/src/save.cpp +++ b/source/sw/src/save.cpp @@ -748,8 +748,6 @@ bool GameInterface::LoadGame(FSaveGameNode* sv) TerminateLevel(); Terminate3DSounds(); - Terminate3DSounds(); - MREAD(&Level,sizeof(Level),1,fil); MREAD(&Skill,sizeof(Skill),1,fil); diff --git a/source/sw/src/sector.cpp b/source/sw/src/sector.cpp index 833ccf04d..f6e0d58f8 100644 --- a/source/sw/src/sector.cpp +++ b/source/sw/src/sector.cpp @@ -1242,7 +1242,6 @@ DoSoundSpotMatch(short match, short sound_num, short sound_type) if (TEST_BOOL2(sp)) flags = v3df_follow|v3df_nolookup|v3df_init; - //flags = v3df_follow|v3df_ambient|v3df_nolookup; // play once and only once if (TEST_BOOL1(sp)) diff --git a/source/sw/src/sounds.cpp b/source/sw/src/sounds.cpp index 33811db9f..3fbca7eb4 100644 --- a/source/sw/src/sounds.cpp +++ b/source/sw/src/sounds.cpp @@ -60,6 +60,10 @@ BEGIN_SW_NS enum EChanExFlags { CHANEXF_AMBIENT = 0x40000000, + CHANEXF_NODOPPLER = 0x20000000, + CHANEXF_DONTPAN = 0x10000000, + CHANEXF_INTERMIT = 0x08000000, + }; // Parentally locked sounds list @@ -118,9 +122,6 @@ void InitFX(void) newsfx.name = entry.name; newsfx.lumpnum = lump; newsfx.NearLimit = 6; - newsfx.UserData.Resize(sizeof(void*)); - auto p = (VOC_INFOp *)newsfx.UserData.Data(); - *p = &entry; // store a link to the static data. } } soundEngine->HashSounds(); @@ -133,10 +134,90 @@ void InitFX(void) //========================================================================== // -// +// Sound Distance Calculation // //========================================================================== +enum +{ + MAXLEVLDIST = 19000, // The higher the number, the further away you can hear sound + DECAY_CONST = 4000 +}; + +short SoundDist(int x, int y, int z, int basedist) +{ + double tx, ty, tz; + double sqrdist, retval; + extern short screenpeek; + + tx = fabs(Player[screenpeek].posx - x); + ty = fabs(Player[screenpeek].posy - y); + tz = fabs((Player[screenpeek].posz - z) >> 4); + + // Use the Pythagreon Theorem to compute the magnitude of a 3D vector + sqrdist = fabs(tx * tx + ty * ty + tz * tz); + retval = sqrt(sqrdist); + + if (basedist < 0) // if basedist is negative + { + double decayshift = 2; + int decay = labs(basedist) / DECAY_CONST; + + for (int i = 0; i < decay; i++) + decayshift *= 2; + + if (fabs(double(basedist) / decayshift) >= retval) + retval = 0; + else + retval *= decay; + } + else + { + if (basedist > retval) + retval = 0; + else + retval -= basedist; + } + + retval = retval * 256 / MAXLEVLDIST; + + if (retval < 0) retval = 0; + if (retval > 255) retval = 255; + + return retval; +} + +//========================================================================== +// +// Calculate rolloff info. +// +//========================================================================== + +FRolloffInfo GetRolloff(int basedist) +{ + FRolloffInfo info; + + if (basedist < 0) // if basedist is negative + { + double decayshift = 2; + int decay = labs(basedist) / DECAY_CONST; + + for (int i = 0; i < decay; i++) + decayshift *= 2; + + info.RolloffType = ROLLOFF_Doom; + info.MinDistance = (float)(-basedist / decayshift / 16.); + info.MaxDistance = MAXLEVLDIST / 16.f / decay; + } + else + { + info.RolloffType = ROLLOFF_Doom; + info.MinDistance = basedist / 16.f; + info.MaxDistance = info.MinDistance + MAXLEVLDIST / 16.f; + } + return info; +} + @@ -151,35 +232,6 @@ void DumpSounds(void); SWBOOL Use_SoundSpriteNum = FALSE; int16_t SoundSpriteNum = -1; // Always set this back to -1 for proper validity checking! -SWBOOL FxInitialized = FALSE; - -void SoundCallBack(unsigned int num); - -#define MUSIC_ID -65536 - -#define NUM_SAMPLES 10 - -int music; -int soundfx; -int num_voices; - -int NumSounds = 0; - -int angle; -int distance; -int voice; - -int loopflag; - -extern SWBOOL DemoMode; - -SWBOOL OpenSound(VOC_INFOp vp, FileReader &handle, int *length); -int ReadSound(FileReader & handle, VOC_INFOp vp, int length); - - -// -// Routine called when a sound is finished playing -// //////////////////////////////////////////////////////////////////////////// // Play a sound @@ -250,7 +302,7 @@ typedef struct } TVOC_INFO, * TVOC_INFOp; void -DoUpdateSounds3D(void) +DoUpdateSounds(void) { VOC3D_INFOp p; SWBOOL looping; @@ -262,8 +314,7 @@ DoUpdateSounds3D(void) TVOC_INFO TmpVocArray[32]; int i; - if (M_Active()) return; - + // Zero out the temporary array // Zero out the temporary array //memset(&TmpVocArray[0],0,sizeof(TmpVocArray)); for (i = 0; i < 32; i++) @@ -500,222 +551,8 @@ DoUpdateSounds3D(void) } -void -StopFX(void) -{ - FX_StopAllSounds_(); -} +/* -void -StopSound(void) -{ - StopFX(); - Mus_Stop(); -} - -// -// Sound Distance Calculation -// - -#define MAXLEVLDIST 19000 // The higher the number, the further away you can hear sound - -short SoundDist(int x, int y, int z, int basedist) -{ - double tx, ty, tz; - double sqrdist,retval; - double decay,decayshift; - extern short screenpeek; - -#define DECAY_CONST 4000 - - - tx = fabs(Player[screenpeek].posx - x); - ty = fabs(Player[screenpeek].posy - y); - tz = fabs((Player[screenpeek].posz - z) >> 4); - - // Use the Pythagreon Theorem to compute the magnitude of a 3D vector - sqrdist = fabs(tx*tx + ty*ty + tz*tz); - retval = sqrt(sqrdist); - - if (basedist < 0) // if basedist is negative - { - short i; - - decayshift=2; - decay = labs(basedist) / DECAY_CONST; - - for (i=0; i= retval) - retval = 0; - else - retval *= decay; - } - else - { - if (basedist > retval) - retval = 0; - else - retval -= basedist; - } - - retval = retval * 256 / MAXLEVLDIST; - - if (retval < 0) retval = 0; - if (retval > 255) retval = 255; - - return retval; -} - -// -// Angle calcuations - may need to be checked to make sure they are right -// - -short SoundAngle(int x, int y) -{ - extern short screenpeek; - - short angle, delta_angle; - - angle = getangle(x - Player[screenpeek].posx, y - Player[screenpeek].posy); - - delta_angle = GetDeltaAngle(angle, Player[screenpeek].pang); - - // convert a delta_angle to a real angle if negative - if (delta_angle < 0) - delta_angle = NORM_ANGLE((1024 + delta_angle) + 1024); - - // convert 2048 degree angle to 128 degree angle - return delta_angle >> 4; -} - -//////////////////////////////////////////////////////////////////////////// -// Play a sound -//////////////////////////////////////////////////////////////////////////// - -#define SOUND_UNIT MAXLEVLDIST/255 -// NOTE: If v3df_follow == 1, x,y,z are considered literal coordinates -int _PlaySound(int num, SPRITEp sp, PLAYERp pp, vec3_t *pos, Voc3D_Flags flags) -{ - VOC_INFOp vp; - VOC3D_INFOp v3p; - int pitch = 0; - short angle, sound_dist; - int tx, ty, tz; - uint8_t priority; - - // Weed out parental lock sounds if PLock is active - if (adult_lockout || Global_PLock) - { - unsigned i; - - for (i=0; i= DIGI_MAX) - return -1; - - if (TEST(flags,v3df_ambient) && !TEST(flags,v3df_nolookup)) // Look for invalid ambient numbers - { - if (!snd_ambience) return -1; - if (num < 0 || num > MAX_AMBIENT_SOUNDS) - { - sprintf(ds,"Invalid or out of range ambient sound number %d\n",num); - PutStringInfo(Player+screenpeek, ds); - return -1; - } - v3p->maxtics = STD_RANDOM_RANGE(ambarray[num].maxtics); - - // If the ambient flag is set, do a name conversion to point to actual - // digital sound entry. - flags |= ambarray[num].ambient_flags; // Add to flags if any - num = ambarray[num].diginame; - if (num < 0 || num >= DIGI_MAX) - { - return -1; - } - } - - //auto chan = soundEngine->StartSound() - - - v3p->num = num; - v3p->priority = 0; - v3p->FX_Ok = FALSE; // Hasn't played yet - // Reset voice - voice = -1; - - // Assign voc to voc pointer - vp = &voc[num]; - if (M_Active() && sp == nullptr && pp == nullptr) // Menus sound outdo everything - priority = 100; - else - priority = vp->priority; - v3p->vp = vp; - - // Assign voc info to 3d struct for future reference - /* - v3p->x = x; - v3p->y = y; - v3p->z = z; - v3p->fx = *x; - v3p->fy = *y; - v3p->fz = *z; - */ - v3p->flags = flags; - - /* - if (flags & v3df_follow) - { - tx = *x; - ty = *y; - if (!z) - tz = 0; // Some sound calls don't have a z - // value - else - tz = *z; - } - else - { - // Don't use pointers to coordinate values. - tx = v3p->fx; - ty = v3p->fy; - tz = v3p->fz; - } - */ - - // Special case stuff for sounds being played in a level - /* - if (*x==0 && *y==0 && *z==0) - tx = ty = tz = 0; - */ - - if ((vp->voc_flags & vf_loop) && Use_SoundSpriteNum && SoundSpriteNum >= 0 && sp) - { - tx=sp->x; - ty=sp->y; - tz=sp->z; - } - - // Calculate sound angle - if (flags & v3df_dontpan) // If true, don't do panning - angle = 0; - else - angle = SoundAngle(tx, ty); - - // Calculate sound distance - if (tx == 0 && ty == 0 && tz == 0) - sound_dist = 255; // Special case for menus sounds,etc. - else - sound_dist = SoundDist(tx, ty, tz, vp->voc_distance); - - v3p->doplr_delta = sound_dist; // Save of distance for doppler - // effect // Can the ambient sound see the player? If not, tone it down some. if ((vp->voc_flags & vf_loop) && Use_SoundSpriteNum && SoundSpriteNum >= 0) @@ -733,88 +570,148 @@ int _PlaySound(int num, SPRITEp sp, PLAYERp pp, vec3_t *pos, Voc3D_Flags flags) if (num == DIGI_WHIPME) sound_dist = 255; } } +*/ - // Assign ambient priorities based on distance - if (snd_ambience && TEST(flags, v3df_ambient)) + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +float S_ConvertPitch(int lpitch) +{ + return pow(2, lpitch / 1200.); +} + +//========================================================================== +// +// Play a sound +// +//========================================================================== + +int _PlaySound(int num, SPRITEp sp, PLAYERp pp, vec3_t *pos, Voc3D_Flags flags, int channel) +{ + VOC_INFOp vp; + VOC3D_INFOp v3p; + int pitch = 0; + short angle, sound_dist; + int tx, ty, tz; + uint8_t priority; + int maxtics = 0; + EChanFlags cflags = channel == 8 ?CHANF_OVERLAP : CHANF_NONE; // for the default channel we do not want to have sounds stopping each other. + + // Weed out parental lock sounds if PLock is active + if (adult_lockout || Global_PLock) { - v3p->priority = v3p->vp->priority - (sound_dist / 26); - priority = v3p->priority; + unsigned i; + + for (i=0; iflags = v3df_kill; - v3p->handle = -1; - v3p->dist = 0; - v3p->deleted = TRUE; // Sound init failed, remove it! + if (Prediction || !SoundEnabled()) return -1; - }*/ - if (sound_dist < 5) - angle = 0; - - // Check for pitch bending - if (vp->pitch_lo > vp->pitch_hi) - ASSERT(vp->pitch_lo <= vp->pitch_hi); - - if (vp->pitch_hi == vp->pitch_lo) - pitch = vp->pitch_lo; - else if (vp->pitch_hi != vp->pitch_lo) - pitch = vp->pitch_lo + (STD_RANDOM_RANGE(vp->pitch_hi - vp->pitch_lo)); - - // Request playback and play it as a looping sound if flag is set. - if (vp->voc_flags & vf_loop) + if (TEST(flags,v3df_ambient) && !TEST(flags,v3df_nolookup)) // Look for invalid ambient numbers { - short loopvol=0; - - if ((loopvol = 255-sound_dist) <= 0) - loopvol = 0; - - if (sound_dist < 255 || (flags & v3df_init)) + // Ambient sounds need special treatment + if (!snd_ambience) return -1; + if (num < 0 || num > MAX_AMBIENT_SOUNDS) { - voice = FX_Play((char *)vp->data, vp->datalen, 0, 0, - pitch, loopvol, loopvol, loopvol, priority, 1.f, num); // [JM] Should probably utilize floating point volume. !CHECKME! + sprintf(ds,"Invalid or out of range ambient sound number %d\n",num); + PutStringInfo(Player+screenpeek, ds); + return -1; } - else - voice = -1; + maxtics = STD_RANDOM_RANGE(ambarray[num].maxtics); + // If the ambient flag is set, do a name conversion to point to actual + // digital sound entry. + flags |= ambarray[num].ambient_flags; // Add to flags if any + num = ambarray[num].diginame; + cflags |= EChanFlags::FromInt(CHANEXF_AMBIENT); // flag the sound as being an ambient sound. } - else - //if(!flags & v3df_init) // If not initing sound, play it - if (tx==0 && ty==0 && tz==0) // It's a non-inlevel sound + //else { - voice = FX_Play((char *)vp->data, vp->datalen, -1, -1, pitch, 255, 255, 255, priority, 1.f, num); // [JM] And here !CHECKME! - } - else // It's a 3d sound - { - if (sound_dist < 255) + if (!soundEngine->isValidSoundId(num)) { - voice = FX_Play3D((char *)vp->data, vp->datalen, FX_ONESHOT, pitch, angle, sound_dist, priority, 1.f, num); // [JM] And here !CHECKME! + return -1; + } + + vp = &voc[num]; + int sourcetype = SOURCE_None; + void* source = nullptr; + // If the sound is not supposd to be positioned, it may not be linked to the launching actor. + if (!(flags & v3df_follow)) + { + if (sp && !pos) + { + pos = &sp->pos; + sp = nullptr; + } + else if (pp && !pos) + { + pos = (vec3_t*)&pp->posx; + pp = nullptr; + } + } + + if (pos != nullptr) + { + sourcetype = SOURCE_Unattached; + } + else if (sp != nullptr) + { + source = sp; + sourcetype = SOURCE_Actor; + } + else if (pp != nullptr) + { + source = pp; + sourcetype = SOURCE_Player; + } + // Otherwise it's an unpositioned sound. + + if (!(flags & v3df_doppler)) + { + cflags |= EChanFlags::FromInt(CHANEXF_NODOPPLER); // this must ensure that CalcPosVel always zeros the velocity. + } + if (flags & v3df_dontpan) + { + cflags |= EChanFlags::FromInt(CHANEXF_DONTPAN); // beware of hackery to emulate this. + } + if (flags & v3df_init) + { + cflags |= CHANF_VIRTUAL; // don't start right away but keep the channel around until explicitly deleted. + } + if (vp->voc_flags & vf_loop) + { + cflags |= CHANF_LOOP; // with the new sound engine these can just be started and don't have to be stopped ever. + } + + if (vp->pitch_hi <= vp->pitch_lo) + pitch = vp->pitch_lo; + else if (vp->pitch_hi != vp->pitch_lo) + pitch = vp->pitch_lo + (STD_RANDOM_RANGE(vp->pitch_hi - vp->pitch_lo)); + + float fpitch = S_ConvertPitch(pitch); + + auto rolloff = GetRolloff(vp->voc_distance); + auto spos = GetSoundPos(pos); + auto chan = soundEngine->StartSound(sourcetype, source, &spos, CHAN_BODY, cflags, num, 1.f, ATTN_NORM, &rolloff, fpitch); + if (chan) + { + if (flags & v3df_intermit) + { + chan->ChanFlags |= CHANF_VIRTUAL | EChanFlags::FromInt(CHANEXF_INTERMIT); // for intermittent sounds this must be set after starting the sound so that it actually plays. + } + chan->UserData = maxtics; // counter for intermittent delay. } - else - voice = -1; } - // If sound played, update our counter - if (voice > FX_Ok) - { - //vp->playing++; - v3p->FX_Ok = TRUE; - } - else - { - vp->lock--; - } - - // Assign voc info to 3d struct for future reference - v3p->handle = voice; // Save the current voc handle in struct - v3p->dist = sound_dist; - v3p->tics = 0; // Reset tics - if (flags & v3df_init) - v3p->flags ^= v3df_init; // Turn init off now - - return voice; + return 1; } //========================================================================== @@ -1012,6 +909,11 @@ void StopPlayerSound(PLAYERp pp) soundEngine->StopSound(SOURCE_Player, pp, CHAN_VOICE); } +bool SoundValidAndActive(SPRITEp spr, int channel) +{ + return soundEngine->IsSourcePlayingSomething(SOURCE_Actor, spr, channel); +} + /* ============================================================================ @@ -1123,5 +1025,11 @@ SWBOOL PlaySong(const char* mapname, const char* song_file_name, int cdaudio_tra return Mus_Play(nullptr, song_file_name, true); } +void StopSound(void) +{ + soundEngine->StopAllChannels(); + Mus_Stop(); +} + END_SW_NS diff --git a/source/sw/src/sounds.h b/source/sw/src/sounds.h index 77b15abfd..7927287be 100644 --- a/source/sw/src/sounds.h +++ b/source/sw/src/sounds.h @@ -73,7 +73,7 @@ typedef struct ambientstruct AMB_INFO, *AMB_INFOp; extern VOC3D_INFOp voc3dstart; extern VOC3D_INFOp voc3dend; -void DoUpdateSounds3D(void); +void DoUpdateSounds(void); void Terminate3DSounds(void); void Set3DSoundOwner(short spritenum); diff --git a/source/sw/src/zilla.cpp b/source/sw/src/zilla.cpp index 5683532be..4c628e752 100644 --- a/source/sw/src/zilla.cpp +++ b/source/sw/src/zilla.cpp @@ -719,23 +719,22 @@ int DoZillaMove(short SpriteNum) SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; short choose; - static int handle; //if (TEST(u->Flags,SPR_SLIDING)) //DoActorSlide(SpriteNum); // Random Zilla taunts - if (!FX_SoundValidAndActive(handle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { choose = STD_RANDOM_RANGE(1000); if (choose > 990) - handle = PlaySound(DIGI_Z16004, sp, v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); else if (choose > 985) - handle = PlaySound(DIGI_Z16004, sp, v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); else if (choose > 980) - handle = PlaySound(DIGI_Z16004, sp, v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); else if (choose > 975) - handle = PlaySound(DIGI_Z16004, sp, v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); }