diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 6b590a69de..adc05559f1 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,18 @@ +March 20, 2008 +- Removed some debug output from SBarInfo::ParseSBarInfo(). +- Fixed: Heretic linetype translations included the wrong file. +- Removed all 2D sound positioning code from s_sound.cpp. Everything uses + FMOD's 3D engine now. +- Removed all the channel selection code from s_sound.cpp. FMOD has code to + handle this sort of thing, so let's use it. +- Replaced S_StopSoundID() with S_CheckSingular(). There is no longer a limit + on the number of copies of a particular sound that can be playing at once, + aside from Strife's special singular sounds. (Sorry, Heretic and Hexen.) + Consequently, the SNDINFO $limit command is now ignored. +- Removed ATTN_SURROUND, since FMOD Ex doesn't exactly support it, and it + only worked as intended on stereo speakers anyway. +- Cleaned out ancient crud from i_sound.cpp. + March 20, 2008 (Changes by Graf Zahl) - Fixed: A_CustomMissile with aimmode 2 ignored spawnofs_xy. - Changed savegame versioning so that the written version is never lower diff --git a/src/actor.h b/src/actor.h index e6e3d9c51c..eb95c0bbd7 100644 --- a/src/actor.h +++ b/src/actor.h @@ -662,6 +662,7 @@ public: TObjPtr master; // Thing which spawned this one (prevents mutual attacks) fixed_t floorclip; // value to use for floor clipping SWORD tid; // thing identifier + BYTE SoundChans; // Bitfield indicating which sound channels are playing. BYTE special; // special int args[5]; // special arguments diff --git a/src/bbannouncer.cpp b/src/bbannouncer.cpp index eb4b075724..1c2ba7923a 100644 --- a/src/bbannouncer.cpp +++ b/src/bbannouncer.cpp @@ -186,7 +186,7 @@ void DoVoiceAnnounce (const char *sound) if (LastAnnounceTime == 0 || LastAnnounceTime <= level.time-5) { LastAnnounceTime = level.time; - S_Sound (CHAN_VOICE, sound, 1, ATTN_SURROUND); + S_Sound (CHAN_VOICE, sound, 1, ATTN_NONE); } } diff --git a/src/f_finale.cpp b/src/f_finale.cpp index c1ed7aee27..a41ead5e39 100644 --- a/src/f_finale.cpp +++ b/src/f_finale.cpp @@ -599,8 +599,6 @@ void F_StartCast (void) // void F_CastTicker (void) { - int atten; - if (--casttics > 0 && caststate != NULL) return; // not time to change state yet @@ -615,11 +613,7 @@ void F_CastTicker (void) castnum = 0; if (castorder[castnum].info->SeeSound) { - if (castorder[castnum].info->flags2 & MF2_BOSS) - atten = ATTN_SURROUND; - else - atten = ATTN_NONE; - S_SoundID (CHAN_VOICE, castorder[castnum].info->SeeSound, 1, atten); + S_SoundID (CHAN_VOICE, castorder[castnum].info->SeeSound, 1, ATTN_NONE); } caststate = castorder[castnum].info->SeeState; // [RH] Skip monsters that have been hacked to no longer have attack states @@ -736,8 +730,7 @@ bool F_CastResponder (event_t* ev) } else if (castorder[castnum].info->DeathSound) { - S_SoundID (CHAN_VOICE, castorder[castnum].info->DeathSound, 1, - castnum == 15 || castnum == 14 ? ATTN_SURROUND : ATTN_NONE); + S_SoundID (CHAN_VOICE, castorder[castnum].info->DeathSound, 1, ATTN_NONE); } } diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 4ad3ae2121..b8e33a44a8 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -174,12 +174,12 @@ END_DEFAULTS void A_BrainAwake (AActor *self) { // killough 3/26/98: only generates sound now - S_Sound (self, CHAN_VOICE, "brain/sight", 1, ATTN_SURROUND); + S_Sound (self, CHAN_VOICE, "brain/sight", 1, ATTN_NONE); } void A_BrainPain (AActor *self) { - S_Sound (self, CHAN_VOICE, "brain/pain", 1, ATTN_SURROUND); + S_Sound (self, CHAN_VOICE, "brain/pain", 1, ATTN_NONE); } static void BrainishExplosion (fixed_t x, fixed_t y, fixed_t z) @@ -206,7 +206,7 @@ void A_BrainScream (AActor *self) BrainishExplosion (x, self->y - 320*FRACUNIT, 128 + (pr_brainscream() << (FRACBITS + 1))); } - S_Sound (self, CHAN_VOICE, "brain/death", 1, ATTN_SURROUND); + S_Sound (self, CHAN_VOICE, "brain/death", 1, ATTN_NONE); } void A_BrainExplode (AActor *self) @@ -264,7 +264,7 @@ void A_BrainSpit (AActor *self) spit->reactiontime /= spit->state->GetTics(); } - S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_SURROUND); + S_Sound (self, CHAN_WEAPON, "brain/spit", 1, ATTN_NONE); } } diff --git a/src/g_hexen/a_weaponpieces.cpp b/src/g_hexen/a_weaponpieces.cpp index 8e6cf44653..47896f9d79 100644 --- a/src/g_hexen/a_weaponpieces.cpp +++ b/src/g_hexen/a_weaponpieces.cpp @@ -49,7 +49,7 @@ void AFourthWeaponPiece::PlayPickupSound (AActor *toucher) if (TempFourthWeapon != NULL) { // Play the build-sound full volume for all players - S_Sound (toucher, CHAN_ITEM, "WeaponBuild", 1, ATTN_SURROUND); + S_Sound (toucher, CHAN_ITEM, "WeaponBuild", 1, ATTN_NONE); } else { diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index ff64b44f4a..dcb926d9d1 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1497,7 +1497,7 @@ END_DEFAULTS void APowerDamage::InitEffect( ) { // Use sound channel 5 to avoid interference with other actions. - if (Owner != NULL) S_SoundID(Owner, 5, SeeSound, 1.0f, ATTN_SURROUND); + if (Owner != NULL) S_SoundID(Owner, 5, SeeSound, 1.0f, ATTN_NONE); } //=========================================================================== @@ -1509,7 +1509,7 @@ void APowerDamage::InitEffect( ) void APowerDamage::EndEffect( ) { // Use sound channel 5 to avoid interference with other actions. - if (Owner != NULL) S_SoundID(Owner, 5, DeathSound, 1.0f, ATTN_SURROUND); + if (Owner != NULL) S_SoundID(Owner, 5, DeathSound, 1.0f, ATTN_NONE); } //=========================================================================== @@ -1532,7 +1532,7 @@ void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bo damage = newdamage = FixedMul(damage, *pdf); if (*pdf > 0 && damage == 0) damage = newdamage = 1; // don't allow zero damage as result of an underflow - if (Owner != NULL && *pdf > FRACUNIT) S_SoundID(Owner, 5, ActiveSound, 1.0f, ATTN_SURROUND); + if (Owner != NULL && *pdf > FRACUNIT) S_SoundID(Owner, 5, ActiveSound, 1.0f, ATTN_NONE); } } if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive); @@ -1553,7 +1553,7 @@ END_DEFAULTS void APowerProtection::InitEffect( ) { // Use sound channel 5 to avoid interference with other actions. - if (Owner != NULL) S_SoundID(Owner, 5, SeeSound, 1.0f, ATTN_SURROUND); + if (Owner != NULL) S_SoundID(Owner, 5, SeeSound, 1.0f, ATTN_NONE); } //=========================================================================== @@ -1565,7 +1565,7 @@ void APowerProtection::InitEffect( ) void APowerProtection::EndEffect( ) { // Use sound channel 5 to avoid interference with other actions. - if (Owner != NULL) S_SoundID(Owner, 5, DeathSound, 1.0f, ATTN_SURROUND); + if (Owner != NULL) S_SoundID(Owner, 5, DeathSound, 1.0f, ATTN_NONE); } //=========================================================================== @@ -1587,7 +1587,7 @@ void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage if (pdf == NULL) pdf = &def; damage = newdamage = FixedMul(damage, *pdf); - if (Owner != NULL && *pdf < FRACUNIT) S_SoundID(Owner, 5, ActiveSound, 1.0f, ATTN_SURROUND); + if (Owner != NULL && *pdf < FRACUNIT) S_SoundID(Owner, 5, ActiveSound, 1.0f, ATTN_NONE); } } if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index a85f022bef..9ab08281c3 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -998,7 +998,7 @@ void AInventory::PlayPickupSound (AActor *toucher) S_SoundID (toucher, CHAN_PICKUP, PickupSound, 1, (ItemFlags & IF_FANCYPICKUPSOUND) && (toucher == NULL || toucher->CheckLocalView (consoleplayer)) - ? ATTN_SURROUND : ATTN_NORM); + ? ATTN_NONE : ATTN_NORM); } //=========================================================================== diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp index d1b80cd983..4c0531be52 100644 --- a/src/g_shared/sbarinfo_parser.cpp +++ b/src/g_shared/sbarinfo_parser.cpp @@ -87,7 +87,6 @@ void SBarInfo::Load() void SBarInfo::ParseSBarInfo(int lump) { gameType = gameinfo.gametype; - Printf("%d=%d", gameinfo.gametype, GAME_Any); bool baseSet = false; FScanner sc(lump, Wads.GetLumpFullName(lump)); sc.SetCMode(true); diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 6c1574f65c..fbb271cbcb 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -1951,7 +1951,7 @@ void M_QuitResponse(int ch) { if (gameinfo.quitSound) { - S_Sound (CHAN_VOICE, gameinfo.quitSound, 1, ATTN_SURROUND); + S_Sound (CHAN_VOICE, gameinfo.quitSound, 1, ATTN_NONE); I_WaitVBL (105); } } diff --git a/src/m_options.cpp b/src/m_options.cpp index c0dec0f850..0941cfa61b 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -102,7 +102,6 @@ EXTERN_CVAR (Int, crosshair) EXTERN_CVAR (Bool, freelook) EXTERN_CVAR (Int, snd_buffersize) EXTERN_CVAR (Int, snd_samplerate) -EXTERN_CVAR (Bool, snd_3d) EXTERN_CVAR (Bool, snd_waterreverb) EXTERN_CVAR (Int, sv_smartaim) @@ -1143,7 +1142,7 @@ static value_t SampleRates[] = { 32000.f, "32000 Hz" }, { 44100.f, "44100 Hz" }, { 48000.f, "48000 Hz" }, - { 65535.f, "65535 Hz" } + { 96000.f, "96000 Hz" } }; static value_t BufferSizes[] = @@ -1175,11 +1174,10 @@ static menuitem_t SoundItems[] = { discrete, "Flip Stereo Channels", {&snd_flipstereo}, {2.0}, {0.0}, {0.0}, {OnOff} }, { discrete, "Random Pitch Variations", {&snd_pitched}, {2.0}, {0.0}, {0.0}, {OnOff} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, - { more, "Activate below settings", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} }, + { more, "Activate below settings", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)MakeSoundChanges} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { discrete, "Sample Rate", {&snd_samplerate}, {8.0}, {0.0}, {0.0}, {SampleRates} }, { discrete, "Buffer Size", {&snd_buffersize}, {11.0}, {0.0}, {0.0}, {BufferSizes} }, - { discrete, "3D Sound", {&snd_3d}, {2.0}, {0.0}, {0.0}, {OnOff} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { more, "Advanced Options", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t *)AdvSoundOptions} }, diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 974987e45c..ec8c5c2658 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1642,7 +1642,7 @@ void A_Look (AActor *actor) { if (actor->flags2 & MF2_BOSS) { // full volume - S_SoundID (actor, CHAN_VOICE, actor->SeeSound, 1, ATTN_SURROUND); + S_SoundID (actor, CHAN_VOICE, actor->SeeSound, 1, ATTN_NONE); } else { @@ -2396,7 +2396,7 @@ void A_Scream (AActor *actor) if (actor->flags2 & MF2_BOSS) { // full volume - S_SoundID (actor, CHAN_VOICE, actor->DeathSound, 1, ATTN_SURROUND); + S_SoundID (actor, CHAN_VOICE, actor->DeathSound, 1, ATTN_NONE); } else { diff --git a/src/p_enemy_a_lookex.cpp b/src/p_enemy_a_lookex.cpp index 3a5e4b6a57..5ea1f434a2 100644 --- a/src/p_enemy_a_lookex.cpp +++ b/src/p_enemy_a_lookex.cpp @@ -867,7 +867,7 @@ void A_LookEx (AActor *actor) { if (flags & LOF_FULLVOLSEESOUND) { // full volume - S_SoundID (actor, CHAN_VOICE, actor->SeeSound, 1, ATTN_SURROUND); + S_SoundID (actor, CHAN_VOICE, actor->SeeSound, 1, ATTN_NONE); } else { diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 110d5b423c..793ec37067 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -433,12 +433,25 @@ int S_AddSoundLump (const char *logicalname, int lump) { sfxinfo_t newsfx; - memset (&newsfx.lumpnum, 0, sizeof(newsfx)-sizeof(newsfx.name)); + newsfx.data = NULL; newsfx.name = logicalname; newsfx.lumpnum = lump; - newsfx.link = sfxinfo_t::NO_LINK; + newsfx.next = 0; + newsfx.index = 0; + newsfx.frequency = 0; newsfx.PitchMask = CurrentPitchMask; - newsfx.MaxChannels = 2; + newsfx.bRandomHeader = false; + newsfx.bPlayerReserve = false; + newsfx.bForce11025 = false; + newsfx.bForce22050 = false; + newsfx.bLoadRAW = false; + newsfx.bPlayerCompat = false; + newsfx.b16bit = false; + newsfx.bUsed = false; + newsfx.bSingular = false; + newsfx.bTentative = false; + newsfx.link = sfxinfo_t::NO_LINK; + return (int)S_sfx.Push (newsfx); } @@ -758,10 +771,10 @@ static void S_ClearSoundData() if (GSnd != NULL) { - GSnd->StopAllChannels(); + S_StopAllChannels(); for (i = 0; i < S_sfx.Size(); ++i) { - GSnd->UnloadSound (&S_sfx[i]); + GSnd->UnloadSound(&S_sfx[i]); } } S_sfx.Clear(); @@ -1087,15 +1100,12 @@ static void S_AddSNDINFO (int lump) break; case SI_Limit: { - // $limit + // $limit -- deprecated and ignored int sfx; sc.MustGetString (); sfx = S_FindSoundTentative (sc.String); sc.MustGetNumber (); - //S_sfx[sfx].MaxChannels = clamp (sc.Number, 0, 255); - //Can't use clamp because of GCC bugs - S_sfx[sfx].MaxChannels = MIN (MAX (sc.Number, 0), 255); } break; @@ -1858,20 +1868,15 @@ void AAmbientSound::Activate (AActor *activator) if (!bActive) { - if (!(amb->type & 3) && !amb->periodmin) + if ((amb->type & 3) == 0 && amb->periodmin == 0) { - int sndnum = S_FindSound (amb->sound); + int sndnum = S_FindSound(amb->sound); if (sndnum == 0) { Destroy (); return; } - sfxinfo_t *sfx = &S_sfx[sndnum]; - - // Make sure the sound has been loaded so we know how long it is - if (!sfx->data && GSnd != NULL) - GSnd->LoadSound (sfx); - amb->periodmin = (sfx->ms * TICRATE) / 1000; + amb->periodmin = Scale(GSnd->GetMSLength(&S_sfx[sndnum]), TICRATE, 1000); } NextCheck = gametic; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 4b6aee2533..4258267919 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -62,15 +62,11 @@ #define O_BINARY 0 #endif -#define SELECT_ATTEN(a) ((a)==ATTN_NONE ? 0 : (a)==ATTN_SURROUND ? -1 : \ - (a)==ATTN_STATIC ? 3 : 1) +#define SELECT_ATTEN(a) ((a)==ATTN_NONE ? 0 : (a)==ATTN_STATIC ? 3 : 1) #ifndef FIXED2FLOAT #define FIXED2FLOAT(f) (((float)(f))/(float)65536) #endif -#define PRIORITY_MAX_ADJUST 10 -#define DIST_ADJUST (MAX_SND_DIST/PRIORITY_MAX_ADJUST) - #define NORM_PITCH 128 #define NORM_PRIORITY 64 #define NORM_SEP 0 @@ -91,27 +87,6 @@ const float S_ATTENUATOR = S_CLIPPING_DIST - S_CLOSE_DIST; // TYPES ------------------------------------------------------------------- -typedef struct -{ - AActor *mover; // Used for velocity - fixed_t *pt; // origin of sound - fixed_t x,y,z; // Origin if pt is NULL - sfxinfo_t* sfxinfo; // sound information (if null, channel avail.) - long handle; // handle of the sound being played - int sound_id; // sound id of playing sound - int org_id; // sound id of sound used to start this channel - int entchannel; // entity's sound channel - int basepriority; - float attenuation; - float volume; - int pitch; - int priority; - bool loop; - bool is3d; - bool constz; - int time; // time when sound started playing -} channel_t; - struct MusPlayingInfo { FString name; @@ -129,7 +104,6 @@ extern float S_GetMusicVolume (const char *music); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static fixed_t P_AproxDistance2 (fixed_t *listener, fixed_t x, fixed_t y); -static void S_StopChannel (int cnum); static void S_StartSound (fixed_t *pt, AActor *mover, int channel, int sound_id, float volume, float attenuation, bool looping); static void S_ActivatePlayList (bool goBack); @@ -139,20 +113,19 @@ static void CalcPosVel (fixed_t *pt, AActor *mover, int constz, float pos[3], // PRIVATE DATA DEFINITIONS ------------------------------------------------ int MAX_SND_DIST; -static channel_t *Channel; // the set of channels available static bool SoundPaused; // whether sound effects are paused static bool MusicPaused; // whether music is paused static MusPlayingInfo mus_playing; // music currently being played static FString LastSong; // last music that was played static float *SoundCurve; -static int nextcleanup; static FPlayList *PlayList; // PUBLIC DATA DEFINITIONS ------------------------------------------------- int sfx_empty; -int numChannels; +FSoundChan *Channels; +FSoundChan *FreeChannels; CVAR (Bool, snd_surround, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // [RH] Use surround sounds? FBoolCVar noisedebug ("noise", false, 0); // [RH] Print sound debugging info? @@ -196,8 +169,9 @@ static fixed_t P_AproxDistance2 (AActor *listener, fixed_t x, fixed_t y) void S_NoiseDebug (void) { + FSoundChan *chan; fixed_t ox, oy; - int i, y, color; + int y, color; y = 32 * CleanYfac; screen->DrawText (CR_YELLOW, 0, y, "*** SOUND DEBUG INFO ***", TAG_DONE); @@ -207,54 +181,58 @@ void S_NoiseDebug (void) screen->DrawText (CR_GOLD, 70, y, "x", TAG_DONE); screen->DrawText (CR_GOLD, 120, y, "y", TAG_DONE); screen->DrawText (CR_GOLD, 170, y, "vol", TAG_DONE); - screen->DrawText (CR_GOLD, 200, y, "pri", TAG_DONE); - screen->DrawText (CR_GOLD, 240, y, "dist", TAG_DONE); - screen->DrawText (CR_GOLD, 280, y, "chan", TAG_DONE); + screen->DrawText (CR_GOLD, 200, y, "dist", TAG_DONE); + screen->DrawText (CR_GOLD, 240, y, "chan", TAG_DONE); y += 8; - for (i = 0; i < numChannels && y < SCREENHEIGHT - 16; i++, y += 8) + if (Channels == NULL) { - if (Channel[i].sfxinfo) - { - char temp[16]; - fixed_t *origin = Channel[i].pt; + return; + } - if (Channel[i].attenuation <= 0) - { - ox = players[consoleplayer].camera->x; - oy = players[consoleplayer].camera->y; - } - else if (origin) - { - ox = origin[0]; - oy = origin[1]; - } - else - { - ox = Channel[i].x; - oy = Channel[i].y; - } - color = Channel[i].loop ? CR_BROWN : CR_GREY; - Wads.GetLumpName (temp, Channel[i].sfxinfo->lumpnum); - temp[8] = 0; - screen->DrawText (color, 0, y, temp, TAG_DONE); - sprintf (temp, "%d", ox >> FRACBITS); - screen->DrawText (color, 70, y, temp, TAG_DONE); - sprintf (temp, "%d", oy >> FRACBITS); - screen->DrawText (color, 120, y, temp, TAG_DONE); - sprintf (temp, "%g", Channel[i].volume); - screen->DrawText (color, 170, y, temp, TAG_DONE); - sprintf (temp, "%d", Channel[i].priority); - screen->DrawText (color, 200, y, temp, TAG_DONE); - sprintf (temp, "%d", P_AproxDistance2 (players[consoleplayer].camera, ox, oy) / FRACUNIT); - screen->DrawText (color, 240, y, temp, TAG_DONE); - sprintf (temp, "%d", Channel[i].entchannel); - screen->DrawText (color, 280, y, temp, TAG_DONE); + // Display the last channel first. + for (chan = Channels; chan->NextChan != NULL; chan = chan->NextChan) + { } + while (y < SCREENHEIGHT - 16) + { + char temp[16]; + fixed_t *origin = chan->Pt; + + if (!chan->Is3D) + { + ox = players[consoleplayer].camera->x; + oy = players[consoleplayer].camera->y; + } + else if (origin) + { + ox = origin[0]; + oy = origin[1]; } else { - screen->DrawText (CR_GREY, 0, y, "------", TAG_DONE); + ox = chan->X; + oy = chan->Y; } + color = chan->Loop ? CR_BROWN : CR_GREY; + Wads.GetLumpName (temp, chan->SfxInfo->lumpnum); + temp[8] = 0; + screen->DrawText (color, 0, y, temp, TAG_DONE); + sprintf (temp, "%d", ox >> FRACBITS); + screen->DrawText (color, 70, y, temp, TAG_DONE); + sprintf (temp, "%d", oy >> FRACBITS); + screen->DrawText (color, 120, y, temp, TAG_DONE); + sprintf (temp, "%g", chan->Volume); + screen->DrawText (color, 170, y, temp, TAG_DONE); + sprintf (temp, "%d", P_AproxDistance2 (players[consoleplayer].camera, ox, oy) / FRACUNIT); + screen->DrawText (color, 200, y, temp, TAG_DONE); + sprintf (temp, "%d", chan->EntChannel); + screen->DrawText (color, 240, y, temp, TAG_DONE); + y += 8; + if (chan->PrevChan == &Channels) + { + break; + } + chan = (FSoundChan *)((size_t)chan->PrevChan - myoffsetof(FSoundChan, NextChan)); } BorderNeedRefresh = screen->GetPageCount (); } @@ -312,31 +290,15 @@ void S_Init () } } - // Allocating the virtual channels - numChannels = GSnd ? GSnd->GetNumChannels() : 0; - if (Channel != NULL) + // Free all channels for use. + while (Channels != NULL) { - delete[] Channel; - } - Channel = new channel_t[numChannels]; - - // Free all channels for use - for (i = 0; i < numChannels; i++) - { - Channel[i].pt = NULL; - Channel[i].handle = 0; - Channel[i].sound_id = -1; - Channel[i].priority = 0; - Channel[i].sfxinfo = 0; + S_ReturnChannel(Channels); } // no sounds are playing, and they are not paused MusicPaused = false; SoundPaused = false; - - // Note that sounds have not been cached (yet). -// for (i=1; (size_t)i < S_sfx.Size (); i++) -// S_sfx[i].usefulness = -1; } //========================================================================== @@ -361,12 +323,31 @@ void S_InitData () void S_Shutdown () { - if (Channel != NULL) + FSoundChan *chan, *next; + + if (GSnd != NULL) { - delete[] Channel; - Channel = NULL; - numChannels = 0; + while (Channels != NULL) + { + GSnd->StopSound(Channels); + } } + else + { + for (chan = Channels; chan != NULL; chan = next) + { + next = chan->NextChan; + delete chan; + } + Channels = NULL; + } + for (chan = FreeChannels; chan != NULL; chan = next) + { + next = chan->NextChan; + delete chan; + } + FreeChannels = NULL; + if (SoundCurve != NULL) { delete[] SoundCurve; @@ -389,32 +370,24 @@ void S_Shutdown () void S_Start () { - int cnum; - if (GSnd) { // kill all playing sounds at start of level (trust me - a good idea) - for (cnum = 0; cnum < numChannels; cnum++) - { - if (Channel[cnum].sfxinfo) - { - S_StopChannel (cnum); - } - } + S_StopAllChannels(); // Check for local sound definitions. Only reload if they differ // from the previous ones. // To be certain better check whether level is valid! - char * LocalSndInfo= level.info? level.info->soundinfo : (char*)""; - char * LocalSndSeq = level.info? level.info->sndseq : (char*)""; - bool parse_ss=false; + char *LocalSndInfo = level.info ? level.info->soundinfo : (char*)""; + char *LocalSndSeq = level.info ? level.info->sndseq : (char*)""; + bool parse_ss = false; // This level uses a different local SNDINFO if (LastLocalSndInfo.CompareNoCase(LocalSndInfo) != 0 || !level.info) { // First delete the old sound list - for(unsigned i=1;iUnloadSound(&S_sfx[i]); } @@ -462,8 +435,6 @@ void S_Start () if (level.cdtrack == 0 || !S_ChangeCDMusic (level.cdtrack, level.cdid)) S_ChangeMusic (level.music, level.musicorder); } - - nextcleanup = 15; } //========================================================================== @@ -545,6 +516,84 @@ void S_CacheSound (sfxinfo_t *sfx) } } +//========================================================================== +// +// S_GetChannel +// +// Returns a free channel for the system sound interface. +// +//========================================================================== + +FSoundChan *S_GetChannel(void *syschan) +{ + FSoundChan *chan; + + if (FreeChannels != NULL) + { + chan = FreeChannels; + S_UnlinkChannel(chan); + } + else + { + chan = new FSoundChan; + memset(chan, 0, sizeof(*chan)); + } + S_LinkChannel(chan, &Channels); + chan->SysChannel = syschan; + return chan; +} + +//========================================================================== +// +// S_ReturnChannel +// +// Returns a channel to the free pool. +// +//========================================================================== + +void S_ReturnChannel(FSoundChan *chan) +{ + if (chan->Mover != NULL) + { + chan->Mover->SoundChans &= ~(1 << chan->EntChannel); + } + S_UnlinkChannel(chan); + memset(chan, 0, sizeof(*chan)); + S_LinkChannel(chan, &FreeChannels); +} + +//========================================================================== +// +// S_UnlinkChannel +// +//========================================================================== + +void S_UnlinkChannel(FSoundChan *chan) +{ + *(chan->PrevChan) = chan->NextChan; + if (chan->NextChan != NULL) + { + chan->NextChan->PrevChan = chan->PrevChan; + } +} + +//========================================================================== +// +// S_LinkChannel +// +//========================================================================== + +void S_LinkChannel(FSoundChan *chan, FSoundChan **head) +{ + chan->NextChan = *head; + if (chan->NextChan != NULL) + { + chan->NextChan->PrevChan = &chan->NextChan; + } + *head = chan; + chan->PrevChan = head; +} + // [RH] Split S_StartSoundAtVolume into multiple parts so that sounds can // be specified both by id and by name. Also borrowed some stuff from // Hexen and parameters from Quake. @@ -553,7 +602,7 @@ void S_CacheSound (sfxinfo_t *sfx) // // CalcPosVel // -// Calculates a sounds position and velocity for 3D sounds. +// Calculates a sound's position and velocity for 3D sounds. //========================================================================= void CalcPosVel (fixed_t *pt, AActor *mover, int constz, @@ -588,7 +637,6 @@ void CalcPosVel (fixed_t *pt, AActor *mover, int constz, // S_StartSound // // 0 attenuation means full volume over whole level -// -1 attenuation means full volume in surround over whole level // 0 0) - attenuation = 0; + attenuation = 0; // Give these variables values, although they don't really matter x = y = z = 0; } @@ -635,47 +679,28 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel, } if (i_compatflags & COMPATF_MAGICSILENCE) { // For people who just can't play without a silent BFG. - channel = 1; + channel = CHAN_WEAPON; } else { if ((channel & CHAN_MAYBE_LOCAL) && (i_compatflags & COMPATF_SILENTPICKUP)) { - if (mover != 0 && mover != players[consoleplayer].camera) + if (mover != NULL && mover != players[consoleplayer].camera) { return; } } channel &= 7; } - if (volume > 1) - volume = 1; - if (attenuation <= 0) - { - sep = NORM_SEP; - dist = 0; - } - else - { - // calculate the distance before other stuff so we can throw out - // sounds that are beyond the hearing range. - dist = (int)(FIXED2FLOAT - (P_AproxDistance2 (players[consoleplayer].camera, x, y)) - * attenuation); - if (dist >= MAX_SND_DIST) - { - return; // sound is beyond the hearing range... - } - else if (dist < 0) - { - dist = 0; - } - sep = -3; // Calculate separation later on - } + volume = clamp(volume, 0.f, 1.f); sfx = &S_sfx[sound_id]; + // If this is a singular sound, don't play it if it's already playing. + if (pt != NULL && sfx->bSingular && S_CheckSingular(sound_id)) + return; + // Resolve player sounds, random sounds, and aliases while (sfx->link != sfxinfo_t::NO_LINK) { @@ -693,8 +718,9 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel, } sfx = &S_sfx[sound_id]; } - - if (!sfx->data) + + // Make sure the sound is loaded. + if (sfx->data == NULL) { GSnd->LoadSound (sfx); if (sfx->link != sfxinfo_t::NO_LINK) @@ -703,12 +729,13 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel, } } + // The empty sound never plays. if (sfx->lumpnum == sfx_empty) { - basepriority = -1000; return; } - else if (attenuation <= 0) + // Select priority. + if (attenuation <= 0) { basepriority = 200; } @@ -732,136 +759,61 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel, } if (attenuation == 1) basepriority += 50; - if (dist == 0) - basepriority += 30; - } - priority = basepriority * (PRIORITY_MAX_ADJUST - (dist/DIST_ADJUST)); - - if (pt != NULL && !S_StopSoundID (sound_id, priority, sfx->MaxChannels, sfx->bSingular, x, y)) - return; // other sounds have greater priority - - if (pt) - { - for (i = 0; i < numChannels; i++) - { - if (Channel[i].sfxinfo && - pt == Channel[i].pt && - Channel[i].entchannel == channel) - { - break; - } - } - if (i < numChannels && channel != CHAN_AUTO) - { - S_StopChannel (i); - } - else if (channel == CHAN_AUTO) - { - int chansused[8], freechan; - - memset (chansused, 0, sizeof(chansused)); - freechan = numChannels; - - for (i = 0; i < numChannels; i++) - { - if (!Channel[i].sfxinfo) - { - freechan = i; - } - else if (pt == Channel[i].pt) - { - chansused[Channel[i].entchannel] = 1; - } - } - for (i = 7; i >= 0; i--) - { - if (!chansused[i]) - break; - } - if (i < 0) - return; // entity has no free channels - channel = i; - i = freechan; - } - } - else - { - i = numChannels; } - if (i >= numChannels) + if (mover != NULL) { - for (i = 0; i < numChannels; i++) - { - if (Channel[i].sfxinfo == NULL) + if (channel == CHAN_AUTO) + { // Select a channel that isn't already playing something. + BYTE mask = mover->SoundChans; + + // Try channel 0 first, then travel from channel 7 down. + if ((mask & 1) == 0) { - break; - } - } - if (i >= numChannels) - { - // look for a lower priority sound to replace. - sndcount++; - if (sndcount >= numChannels) - sndcount = 0; - for (chan = 0; chan < numChannels; chan++) - { - i = (sndcount + chan) % numChannels; - if (priority > Channel[i].priority) - { - chan = -1; //denote that sound should be replaced. - break; - } - } - if (chan != -1) - { - return; // no free channels. + channel = 0; } else { - // replace the lower priority sound. - S_StopChannel (i); + for (channel = 7; channel > 0; --channel, mask <<= 1) + { + if ((mask & 0x80) == 0) + { + break; + } + } + if (channel == 0) + { // Crap. No free channels. + return; + } + } + } + + + // If this actor is already playing something on the selected channel, stop it. + if (mover->SoundChans & (1 << channel)) + { + for (chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->Mover == mover && chan->EntChannel == channel) + { + GSnd->StopSound(chan); + break; + } } } } - vol = SoundCurve[dist] * volume; - if (sep == -3) - { - AActor *listener = players[consoleplayer].camera; - if (listener == NULL || dist == 0) - { - sep = NORM_SEP; - } - else - { - double angle = atan2(double(y - listener->y), double(x - listener->x)); - double listener_angle = (listener->angle >> 1) * (M_PI / 1073741824.0); - - if (angle <= listener_angle) - { - angle += 2*M_PI; - } - angle -= listener_angle; - sep = -S_STEREO_SWING * sin(angle); - if (snd_flipstereo) - { - sep = -sep; - } - } - } - - // vary the sfx pitches + // Vary the sfx pitches. if (sfx->PitchMask != 0) { - Channel[i].pitch = NORM_PITCH-(M_Random()&sfx->PitchMask)+(M_Random()&sfx->PitchMask); + pitch = NORM_PITCH - (M_Random()&sfx->PitchMask) + (M_Random()&sfx->PitchMask); } else { - Channel[i].pitch = NORM_PITCH; + pitch = NORM_PITCH; } - if (GSnd->Sound3D && attenuation > 0) + if (attenuation > 0) { float pos[3]; float vel[3]; @@ -878,36 +830,38 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel, pt2[2] = z; CalcPosVel (pt2, mover, chanflags & CHAN_LISTENERZ, pos, vel); } - Channel[i].handle = GSnd->StartSound3D (sfx, volume, Channel[i].pitch, i, looping, pos, vel, !(chanflags & CHAN_NOPAUSE)); - Channel[i].is3d = true; - Channel[i].constz = !!(chanflags & CHAN_LISTENERZ); + chan = GSnd->StartSound3D (sfx, volume, pitch, looping, pos, vel, !(chanflags & CHAN_NOPAUSE)); + if (chan != NULL) + { + chan->ConstZ = !!(chanflags & CHAN_LISTENERZ); + } } else { - Channel[i].handle = GSnd->StartSound (sfx, vol, sep, Channel[i].pitch, i, looping, !(chanflags & CHAN_NOPAUSE)); - Channel[i].is3d = false; - Channel[i].constz = true; + chan = GSnd->StartSound (sfx, volume, pitch, looping, !(chanflags & CHAN_NOPAUSE)); + if (chan != NULL) + { + chan->ConstZ = true; + } + } + if (chan != NULL) + { + chan->SoundID = sound_id; + chan->OrgID = org_id; + chan->Mover = mover; + chan->Pt = pt != NULL ? pt : &chan->X; + chan->SfxInfo = sfx; + chan->EntChannel = channel; + chan->Volume = volume; + chan->X = x; + chan->Y = y; + chan->Z = z; + chan->Loop = looping; + if (mover != NULL) + { + mover->SoundChans |= 1 << channel; + } } - Channel[i].sound_id = sound_id; - Channel[i].org_id = org_id; - Channel[i].mover = mover; - Channel[i].pt = pt ? pt : &Channel[i].x; - Channel[i].sfxinfo = sfx; - Channel[i].priority = priority; - Channel[i].basepriority = basepriority; - Channel[i].entchannel = channel; - Channel[i].attenuation = attenuation; - Channel[i].volume = volume; - Channel[i].x = x; - Channel[i].y = y; - Channel[i].z = z; - Channel[i].loop = looping ? true : false; - Channel[i].time = gametic; - -// if (sfx->usefulness < 0) -// sfx->usefulness = 1; -// else -// sfx->usefulness++; } //========================================================================== @@ -1030,59 +984,22 @@ void S_LoopedSound (AActor *ent, int channel, const char *name, float volume, in //========================================================================== // -// S_StopSoundID +// S_CheckSingular +// +// Returns true if a copy of this sound is already playing. // -// from Hexen (albeit, modified a bit) -// Stops more than copies of the sound from playing at once. //========================================================================== -bool S_StopSoundID (int sound_id, int priority, int limit, bool singular, fixed_t x, fixed_t y) +bool S_CheckSingular(int sound_id) { - int i; - int lp; //least priority - int found; - - if (limit <= 0) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - return true; - } - - lp = -1; - found = 0; - for (i = 0; i < numChannels; i++) - { - if (Channel[i].sound_id == sound_id) + if (chan->OrgID == sound_id) { - if (singular) - { - // This sound is already playing, so don't start it again. - return false; - } - if (Channel[i].sfxinfo && - P_AproxDistance (Channel[i].pt[0] - x, Channel[i].pt[1] - y) < 256*FRACUNIT) - { - found++; //found one. Now, should we replace it?? - if (priority > Channel[i].priority) - { // if we're gonna kill one, then this'll be it - lp = i; - priority = Channel[i].priority; - } - } + return true; } } - if (found < limit) - { - return true; - } - if (lp == -1) - { - return false; // don't replace any sounds - } - if (Channel[lp].handle) - { - S_StopChannel (lp); - } - return true; + return false; } //========================================================================== @@ -1094,22 +1011,23 @@ bool S_StopSoundID (int sound_id, int priority, int limit, bool singular, fixed_ void S_StopSound (fixed_t *pt, int channel) { - int i; - - for (i = 0; i < numChannels; ++i) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - if (Channel[i].sfxinfo && - ((pt == NULL && Channel[i].pt == &Channel[i].x) || Channel[i].pt == pt) && - ((i_compatflags & COMPATF_MAGICSILENCE) || Channel[i].entchannel == channel)) + if (((pt == NULL && chan->Pt == &chan->X) || chan->Pt == pt) && + ((i_compatflags & COMPATF_MAGICSILENCE) || chan->EntChannel == channel)) { - S_StopChannel (i); + GSnd->StopSound(chan); } } } void S_StopSound (AActor *ent, int channel) { - S_StopSound (&ent->x, channel); + // No need to search every channel if we know it's not playing anything. + if (ent->SoundChans & (1 << channel)) + { + S_StopSound (&ent->x, channel); + } } //========================================================================== @@ -1120,10 +1038,15 @@ void S_StopSound (AActor *ent, int channel) void S_StopAllChannels () { - SN_StopAllSequences (); - for (int i = 0; i < numChannels; i++) - if (Channel[i].sfxinfo) - S_StopChannel (i); + if (GSnd == NULL) + { + return; + } + SN_StopAllSequences(); + while (Channels != NULL) + { + GSnd->StopSound(Channels); + } } //========================================================================== @@ -1136,28 +1059,27 @@ void S_StopAllChannels () void S_RelinkSound (AActor *from, AActor *to) { - int i; - - if (!from) + if (from == NULL || GSnd == NULL) return; fixed_t *frompt = &from->x; fixed_t *topt = to ? &to->x : NULL; - for (i = 0; i < numChannels; i++) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - if (Channel[i].pt == frompt) + if (chan->Pt == frompt) { - if (to != NULL || !Channel[i].loop) + if (to != NULL || !chan->Loop) { - Channel[i].pt = topt ? topt : &Channel[i].x; - Channel[i].x = frompt[0]; - Channel[i].y = frompt[1]; - Channel[i].z = frompt[2]; + chan->Pt = topt ? topt : &chan->X; + chan->X = frompt[0]; + chan->Y = frompt[1]; + chan->Z = frompt[2]; + chan->Mover = to; } else { - S_StopChannel (i); + GSnd->StopSound(chan); } } } @@ -1172,13 +1094,11 @@ void S_RelinkSound (AActor *from, AActor *to) bool S_GetSoundPlayingInfo (fixed_t *pt, int sound_id) { - int i; - if (sound_id > 0) { - for (i = 0; i < numChannels; i++) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - if (Channel[i].pt == pt && Channel[i].org_id == sound_id) + if (chan->Pt == pt && chan->OrgID == sound_id) return true; } } @@ -1198,43 +1118,23 @@ bool S_GetSoundPlayingInfo (AActor *ent, int sound_id) bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) { - int i; + if (actor->SoundChans == 0) + { + return false; + } if (i_compatflags & COMPATF_MAGICSILENCE) { channel = 0; } - // Resolve player sounds, random sounds, and aliases - if (sound_id > 0) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - while (S_sfx[sound_id].link != sfxinfo_t::NO_LINK) + if (chan->Pt == &actor->x) { - if (S_sfx[sound_id].bPlayerReserve) + if (channel == 0 || chan->EntChannel == channel) { - sound_id = S_FindSkinnedSound (actor, sound_id); - } - else if (S_sfx[sound_id].bRandomHeader) - { - // This can't really be checked properly - // so return true if the channel is playing something, no matter what. - sound_id = -1; - break; - } - else - { - sound_id = S_sfx[sound_id].link; - } - } - } - - for (i = 0; i < numChannels; ++i) - { - if (Channel[i].pt == &actor->x) - { - if (channel == 0 || Channel[i].entchannel == channel) - { - return sound_id < 0 || Channel[i].sound_id == sound_id; + return sound_id <= 0 || chan->OrgID == sound_id; } } } @@ -1292,108 +1192,35 @@ void S_ResumeSound () void S_UpdateSounds (void *listener_p) { - fixed_t *listener; - fixed_t x, y; - int i, dist; - float vol, sep; + float pos[3], vel[3]; I_UpdateMusic(); if (GSnd == NULL) return; - listener = listener_p ? &((AActor *)listener_p)->x : NULL; - // [RH] Update playlist if (PlayList && mus_playing.handle && - !I_QrySongPlaying (mus_playing.handle)) + !I_QrySongPlaying(mus_playing.handle)) { - PlayList->Advance (); - S_ActivatePlayList (false); + PlayList->Advance(); + S_ActivatePlayList(false); } - for (i = 0; i < numChannels; ++i) + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) { - if (!Channel[i].sfxinfo) - continue; - - if (!GSnd->IsPlayingSound (Channel[i].handle)) + if (chan->Is3D) { - S_StopChannel (i); - } - if (Channel[i].sound_id == -1 || - (Channel[i].pt == listener && !GSnd->Sound3D) || - Channel[i].attenuation <= 0) - { - continue; - } - else - { - if (!Channel[i].pt) - { - x = Channel[i].x; - y = Channel[i].y; - } - else - { - x = Channel[i].pt[0]; - y = Channel[i].pt[1]; - } - dist = (int)(FIXED2FLOAT(P_AproxDistance2 (listener, x, y)) - * Channel[i].attenuation); - if (dist >= MAX_SND_DIST) - { - S_StopChannel (i); - continue; - } - else if (dist < 0) - { - dist = 0; - } - vol = SoundCurve[dist] * Channel[i].volume; - if (dist > 0) - { - double angle = atan2(double(y - listener[1]), double(x - listener[0])); - double listener_angle = (players[consoleplayer].camera->angle >> 1) * (M_PI / 1073741824.0); - - if (angle <= listener_angle) - { - angle += 2*M_PI; - } - angle -= listener_angle; - sep = -S_STEREO_SWING * sin(angle); - if (snd_flipstereo) - { - sep = -sep; - } - } - else - { - sep = NORM_SEP; - } - if (!Channel[i].is3d) - { - GSnd->UpdateSoundParams (Channel[i].handle, vol, sep, Channel[i].pitch); - } - else - { - float pos[3], vel[3]; - CalcPosVel (Channel[i].pt, Channel[i].mover, Channel[i].constz, pos, vel); - GSnd->UpdateSoundParams3D (Channel[i].handle, pos, vel); - } - Channel[i].priority = Channel[i].basepriority * (PRIORITY_MAX_ADJUST-(dist/DIST_ADJUST)); + CalcPosVel(chan->Pt, chan->Mover, chan->ConstZ, pos, vel); + GSnd->UpdateSoundParams3D(chan, pos, vel); } } - SN_UpdateActiveSequences (); + SN_UpdateActiveSequences(); - if (GSnd->Sound3D && players[consoleplayer].camera) - { - GSnd->UpdateListener (players[consoleplayer].camera); - } - - GSnd->UpdateSounds (); + GSnd->UpdateListener(); + GSnd->UpdateSounds(); } //========================================================================== @@ -1662,43 +1489,6 @@ void S_StopMusic (bool force) } } -//========================================================================== -// -// S_StopChannel -// -//========================================================================== - -static void S_StopChannel (int cnum) -{ - -// int i; - channel_t* c = &Channel[cnum]; - - if (c->sfxinfo) - { - // stop the sound playing - if (GSnd != NULL) GSnd->StopSound (c->handle); - - // check to see - // if other channels are playing the sound -/* for (i = 0; i < numChannels; i++) - { - if (cnum != i && c->sfxinfo == Channel[i].sfxinfo) - { - break; - } - } -*/ - // degrade usefulness of sound data -// c->sfxinfo->usefulness--; - - c->sfxinfo = NULL; - c->handle = 0; - c->sound_id = -1; - c->pt = NULL; - } -} - //========================================================================== // // CCMD playsound diff --git a/src/s_sound.h b/src/s_sound.h index 23e5aa68fa..19de23cb67 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -32,15 +32,17 @@ class FScanner; // struct sfxinfo_t { - FString name; // [RH] Sound name defined in SNDINFO - short lumpnum; // lump number of sfx - - BYTE PitchMask; - BYTE MaxChannels; - // Next field is for use by the system sound interface. // A non-null data means the sound has been loaded. - void* data; + void *data; + + FString name; // [RH] Sound name defined in SNDINFO + int lumpnum; // lump number of sfx + + unsigned int next, index; // [RH] For hashing + unsigned int frequency; // [RH] Preferred playback rate + + BYTE PitchMask; WORD bRandomHeader:1; WORD bPlayerReserve:1; @@ -54,18 +56,37 @@ struct sfxinfo_t WORD bTentative:1; WORD link; - enum { NO_LINK = 0xffff }; - - unsigned int ms; // [RH] length of sfx in milliseconds - unsigned int next, index; // [RH] For hashing - unsigned int frequency; // [RH] Preferred playback rate - unsigned int length; // [RH] Length of the sound in samples }; // the complete set of sound effects extern TArray S_sfx; +// Information about one playing sound. +struct FSoundChan +{ + void *SysChannel;// Channel information from the system interface. + FSoundChan *NextChan; // Next channel in this list. + FSoundChan **PrevChan; // Previous channel in this list. + AActor *Mover; // Used for velocity. + fixed_t *Pt; // Origin of sound. + sfxinfo_t *SfxInfo; // Sound information. + fixed_t X,Y,Z; // Origin if Mover is NULL. + int SoundID; // Sound ID of playing sound + int OrgID; // Sound ID of sound used to start this channel + float Volume; + BYTE EntChannel; // Actor's sound channel. + bool Loop; + bool Is3D; + bool ConstZ; +}; + +FSoundChan *S_GetChannel(void *syschan); +void S_ReturnChannel(FSoundChan *chan); + +void S_LinkChannel(FSoundChan *chan, FSoundChan **head); +void S_UnlinkChannel(FSoundChan *chan); + // Initializes sound stuff, including volume // Sets channels, SFX and music volume, // allocates channel buffer, sets S_sfx lookup. @@ -108,7 +129,7 @@ void S_LoopedSoundID (fixed_t *pt, int channel, int sfxid, float volume, int att // CHAN_VOICE is for oof, sight, or other voice sounds // CHAN_ITEM is for small things and item pickup // CHAN_BODY is for generic body sounds -// CHAN_PICKUP is can optionally be set as a local sound only for "compatibility" +// CHAN_PICKUP can optionally be set as a local sound only for "compatibility" #define CHAN_AUTO 0 #define CHAN_WEAPON 1 @@ -127,14 +148,12 @@ void S_LoopedSoundID (fixed_t *pt, int channel, int sfxid, float volume, int att #define ATTN_NORM 1 #define ATTN_IDLE 2 #define ATTN_STATIC 3 // diminish very rapidly with distance -#define ATTN_SURROUND 4 // like ATTN_NONE, but plays in surround sound int S_PickReplacement (int refid); void S_CacheRandomSound (sfxinfo_t *sfx); -// [RH] From Hexen. -// Prevents too many of the same sound from playing simultaneously. -bool S_StopSoundID (int sound_id, int priority, int limit, bool singular, fixed_t x, fixed_t y); +// Checks if a copy of this sound is already playing. +bool S_CheckSingular (int sound_id); // Stops a sound emanating from one of an entity's channels void S_StopSound (AActor *ent, int channel); diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 6718c3e5de..cd608aa458 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -64,7 +64,11 @@ extern HWND Window; #define PITCH(freq,pitch) (snd_pitched ? ((freq)*(pitch))/128.f : float(freq)) // Just some extra for music and whatever -#define NUM_EXTRA_SOFTWARE_CHANNELS 8 +#define NUM_EXTRA_SOFTWARE_CHANNELS 1 + +#define FIXED2FLOAT(x) ((x)/65536.f) + +#define MAX_CHANNELS 256 #define ERRCHECK(x) @@ -104,7 +108,6 @@ EXTERN_CVAR (Int, snd_channels) ReverbContainer *ForcedEnvironment; CVAR (Int, snd_driver, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR (Bool, snd_3d, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, snd_waterreverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_resampler, "Linear", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_speakermode, "Auto", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -244,9 +247,11 @@ class FMODStreamCapsule : public SoundStream { public: FMODStreamCapsule(FMOD::Sound *stream, FMODSoundRenderer *owner) - : Owner(owner), Stream(stream), Channel(NULL), DSP(NULL), + : Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL), UserData(NULL), Callback(NULL) - {} + { + SetStream(stream); + } FMODStreamCapsule(void *udata, SoundStreamCallback callback, FMODSoundRenderer *owner) : Owner(owner), Stream(NULL), Channel(NULL), DSP(NULL), @@ -263,7 +268,15 @@ public: void SetStream(FMOD::Sound *stream) { + float frequency; + Stream = stream; + + // As this interface is for music, make it super-high priority. + if (FMOD_OK == stream->getDefaults(&frequency, NULL, NULL, NULL)) + { + stream->setDefaults(frequency, 1, 0, 0); + } } bool Play(bool looping, float volume, bool normalize) @@ -278,14 +291,12 @@ public: } Channel->setChannelGroup(Owner->MusicGroup); Channel->setVolume(volume); - if (Owner->Sound3D) - { // Ensure reverb is disabled when using 3D sound. - FMOD_REVERB_CHANNELPROPERTIES reverb; - if (FMOD_OK == Channel->getReverbProperties(&reverb)) - { - reverb.Room = -10000; - Channel->setReverbProperties(&reverb); - } + // Ensure reverb is disabled. + FMOD_REVERB_CHANNELPROPERTIES reverb; + if (FMOD_OK == Channel->getReverbProperties(&reverb)) + { + reverb.Room = -10000; + Channel->setReverbProperties(&reverb); } if (normalize) { // Attach a normalizer DSP unit to the channel. @@ -402,7 +413,7 @@ private: FMODSoundRenderer::FMODSoundRenderer() { - Init(); + InitSuccess = Init(); } FMODSoundRenderer::~FMODSoundRenderer() @@ -412,9 +423,15 @@ FMODSoundRenderer::~FMODSoundRenderer() bool FMODSoundRenderer::IsValid() { - return Sys != NULL; + return InitSuccess; } +//========================================================================== +// +// FMODSoundRenderer :: Init +// +//========================================================================== + bool FMODSoundRenderer::Init() { FMOD_RESULT result; @@ -426,8 +443,6 @@ bool FMODSoundRenderer::Init() int eval; - ChannelMap = NULL; - NumChannels = 0; SFXPaused = false; MusicGroup = NULL; SfxGroup = NULL; @@ -445,8 +460,10 @@ bool FMODSoundRenderer::Init() if (version < FMOD_VERSION) { - Printf ("Error! You are using an old version of FMOD %08x.\n" - "This program requires %08x\n", version, FMOD_VERSION); + Printf (" "TEXTCOLOR_ORANGE"Error! You are using an old version of FMOD (%x.%02x.%02x).\n" + " "TEXTCOLOR_ORANGE"This program requires version %x.%02x.%02x\n", + version >> 16, (version >> 8) & 255, version & 255, + FMOD_VERSION >> 16, (FMOD_VERSION >> 8) & 255, FMOD_VERSION & 255); return false; } @@ -534,13 +551,13 @@ bool FMODSoundRenderer::Init() { initflags |= FMOD_INIT_ENABLE_DSPNET; } - result = Sys->init(100, initflags, 0); + result = Sys->init(MAX_CHANNELS, initflags, 0); if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) { // The speaker mode selected isn't supported by this soundcard. Switch it back to stereo. result = Sys->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); ERRCHECK(result); - result = Sys->init(100, FMOD_INIT_NORMAL, 0); + result = Sys->init(MAX_CHANNELS, initflags, 0); ERRCHECK(result); } if (result != FMOD_OK) @@ -563,39 +580,39 @@ bool FMODSoundRenderer::Init() result = SPC_CreateCodec(Sys); - if (snd_3d) - { - float rolloff_factor; + float rolloff_factor; - Sound3D = true; - if (gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Strife) - { - rolloff_factor = 1.7f; - } - else if (gameinfo.gametype == GAME_Heretic) - { - rolloff_factor = 1.24f; - } - else - { - rolloff_factor = 0.96f; - } - Sys->set3DSettings(1.f, 100.f, rolloff_factor); + if (gameinfo.gametype == GAME_Doom || gameinfo.gametype == GAME_Strife) + { + rolloff_factor = 1.7f; + } + else if (gameinfo.gametype == GAME_Heretic) + { + rolloff_factor = 1.24f; } else { - Sound3D = false; + rolloff_factor = 0.96f; } + Sys->set3DSettings(1.f, 100.f, rolloff_factor); snd_sfxvolume.Callback (); return true; } +//========================================================================== +// +// FMODSoundRenderer :: Shutdown +// +//========================================================================== + void FMODSoundRenderer::Shutdown() { if (Sys != NULL) { unsigned int i; + S_StopAllChannels(); + if (MusicGroup != NULL) { MusicGroup->release(); @@ -611,15 +628,9 @@ void FMODSoundRenderer::Shutdown() SfxGroup->release(); SfxGroup = NULL; } - if (ChannelMap) - { - delete[] ChannelMap; - ChannelMap = NULL; - } - NumChannels = 0; // Free all loaded samples - for (i = 0; i < S_sfx.Size (); i++) + for (i = 0; i < S_sfx.Size(); i++) { if (S_sfx[i].data != NULL) { @@ -633,6 +644,12 @@ void FMODSoundRenderer::Shutdown() } } +//========================================================================== +// +// FMODSoundRenderer :: PrintStatus +// +//========================================================================== + void FMODSoundRenderer::PrintStatus() { FMOD_OUTPUTTYPE output; @@ -675,9 +692,14 @@ void FMODSoundRenderer::PrintStatus() Printf (TEXTCOLOR_LIGHTBLUE "Software mixer channels: "TEXTCOLOR_GREEN"%d\n", numoutputchannels); Printf (TEXTCOLOR_LIGHTBLUE "Software mixer resampler: "TEXTCOLOR_GREEN"%s\n", Enum_NameForNum(ResamplerNames, resampler)); } - Printf("Using 3D sound: "TEXTCOLOR_GREEN"%s\n", Sound3D ? "yes" : "no"); } +//========================================================================== +// +// FMODSoundRenderer :: DumpDriverCaps +// +//========================================================================== + void FMODSoundRenderer::DumpDriverCaps(FMOD_CAPS caps, int minfrequency, int maxfrequency) { Printf (TEXTCOLOR_OLIVE " Min. frequency: "TEXTCOLOR_GREEN"%d\n", minfrequency); @@ -708,6 +730,12 @@ void FMODSoundRenderer::DumpDriverCaps(FMOD_CAPS caps, int minfrequency, int max if (caps & FMOD_CAPS_REVERB_LIMITED) Printf("TEXTCOLOR_OLIVE Limited reverb\n"); } +//========================================================================== +// +// FMODSoundRenderer :: PrintDriversList +// +//========================================================================== + void FMODSoundRenderer::PrintDriversList() { int numdrivers; @@ -726,6 +754,12 @@ void FMODSoundRenderer::PrintDriversList() } } +//========================================================================== +// +// FMODSoundRenderer :: GatherStats +// +//========================================================================== + FString FMODSoundRenderer::GatherStats() { int channels; @@ -742,12 +776,24 @@ FString FMODSoundRenderer::GatherStats() return out; } +//========================================================================== +// +// FMODSoundRenderer :: MovieDisableSound +// +//========================================================================== + void FMODSoundRenderer::MovieDisableSound() { I_ShutdownMusic(); Shutdown(); } +//========================================================================== +// +// FMODSoundRenderer :: MovieResumeSound +// +//========================================================================== + void FMODSoundRenderer::MovieResumeSound() { Init(); @@ -755,34 +801,35 @@ void FMODSoundRenderer::MovieResumeSound() S_RestartMusic(); } +//========================================================================== +// +// FMODSoundRenderer :: SetSfxVolume +// +//========================================================================== + void FMODSoundRenderer::SetSfxVolume(float volume) { SfxGroup->setVolume(volume); } +//========================================================================== +// +// FMODSoundRenderer :: SetMusicVolume +// +//========================================================================== + void FMODSoundRenderer::SetMusicVolume(float volume) { MusicGroup->setVolume(volume); } -int FMODSoundRenderer::GetNumChannels() -{ - int chancount; - - if (FMOD_OK == Sys->getSoftwareChannels(&chancount)) - { - chancount = MIN(snd_channels, chancount - NUM_EXTRA_SOFTWARE_CHANNELS); - } - - ChannelMap = new ChanMap[chancount]; - for (int i = 0; i < chancount; i++) - { - ChannelMap[i].soundID = -1; - } - - NumChannels = chancount; - return chancount; -} +//========================================================================== +// +// FMODSoundRenderer :: CreateStream +// +// Creates a streaming sound that receives PCM data through a callback. +// +//========================================================================== SoundStream *FMODSoundRenderer::CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) { @@ -836,6 +883,14 @@ SoundStream *FMODSoundRenderer::CreateStream (SoundStreamCallback callback, int return capsule; } +//========================================================================== +// +// FMODSoundRenderer :: OpenStream +// +// Creates a streaming sound from a file on disk. +// +//========================================================================== + SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int flags, int offset, int length) { FMOD_MODE mode; @@ -862,15 +917,14 @@ SoundStream *FMODSoundRenderer::OpenStream(const char *filename_or_data, int fla return NULL; } +//========================================================================== // -// vol range is 0-255 -// sep range is 0-255, -1 for surround, -2 for full vol middle +// FMODSoundRenderer :: StartSound // -long FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, float sep, int pitch, int channel, bool looping, bool pausable) -{ - if (!ChannelMap) - return 0; +//========================================================================== +FSoundChan *FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, int pitch, bool looping, bool pausable) +{ int id = int(sfx - &S_sfx[0]); FMOD_RESULT result; FMOD_MODE mode; @@ -884,43 +938,38 @@ long FMODSoundRenderer::StartSound(sfxinfo_t *sfx, float vol, float sep, int pit { result = chan->getMode(&mode); - if (Sound3D) - { // Make 2D sounds head relative. - FMOD_VECTOR zero = { 0, 0, 0 }; - mode = (mode & ~FMOD_3D_WORLDRELATIVE) | (FMOD_3D_HEADRELATIVE); - chan->set3DAttributes(&zero, &zero); + if (result != FMOD_OK) + { + assert(0); + mode = FMOD_SOFTWARE; } + mode = (mode & ~FMOD_3D) | FMOD_2D; if (looping) { - mode |= FMOD_LOOP_NORMAL; - } - if (result == FMOD_OK) - { - chan->setMode(mode); + mode = (mode & ~FMOD_LOOP_OFF) | FMOD_LOOP_NORMAL; } + chan->setMode(mode); chan->setChannelGroup((pausable && !SFXPaused) ? PausableSfx : SfxGroup); chan->setFrequency(freq); chan->setVolume(vol); - chan->setPan(sep); - chan->setPaused(false); - ChannelMap[channel].channelID = chan; - ChannelMap[channel].soundID = id; - ChannelMap[channel].bIsLooping = looping; - return channel + 1; + return CommonChannelSetup(chan, false); } DPrintf ("Sound %s failed to play: %d\n", sfx->name.GetChars(), result); return 0; } -long FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, int pitch, int channel, +//========================================================================== +// +// FMODSoundRenderer :: StartSound3D +// +//========================================================================== + +FSoundChan *FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, int pitch, bool looping, float pos[3], float vel[3], bool pausable) { - if (!Sound3D || !ChannelMap) - return 0; - int id = int(sfx - &S_sfx[0]); FMOD_RESULT result; FMOD_MODE mode; @@ -932,51 +981,110 @@ long FMODSoundRenderer::StartSound3D(sfxinfo_t *sfx, float vol, int pitch, int c result = Sys->playSound(FMOD_CHANNEL_FREE, (FMOD::Sound *)sfx->data, true, &chan); if (FMOD_OK == result) { + result = chan->getMode(&mode); + if (result != FMOD_OK) + { + mode = FMOD_3D | FMOD_SOFTWARE; + } if (looping) { - result = chan->getMode(&mode); - if (result == FMOD_OK) + mode = (mode & ~FMOD_LOOP_OFF) | FMOD_LOOP_NORMAL; + } + // If this sound is played at the same coordinates as the listener, + // make it head relative. + if (players[consoleplayer].camera != NULL) + { + float cpos[3]; + + cpos[0] = FIXED2FLOAT(players[consoleplayer].camera->x); + cpos[2] = FIXED2FLOAT(players[consoleplayer].camera->y); + cpos[1] = FIXED2FLOAT(players[consoleplayer].camera->z); + if (cpos[0] == pos[0] && cpos[1] == pos[1] && cpos[2] == pos[2]) { - mode |= FMOD_LOOP_NORMAL; - chan->setMode(mode); + mode = (mode & ~FMOD_3D_WORLDRELATIVE) | FMOD_3D_HEADRELATIVE; + pos[0] = 0; + pos[1] = 0; + pos[2] = 0; } } + chan->setMode(mode); chan->setChannelGroup((pausable && !SFXPaused) ? PausableSfx : SfxGroup); chan->setFrequency(freq); chan->setVolume(vol); chan->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel); chan->setPaused(false); - ChannelMap[channel].channelID = chan; - ChannelMap[channel].soundID = id; - ChannelMap[channel].bIsLooping = looping; - return channel + 1; + return CommonChannelSetup(chan, true); } DPrintf ("Sound %s failed to play: %d\n", sfx->name.GetChars(), result); return 0; } -void FMODSoundRenderer::StopSound(long handle) +//========================================================================== +// +// FMODSoundRenderer :: CommonChannelSetup +// +// Assign an end callback to the channel and allocates a game channel for +// it. +// +//========================================================================== + +FSoundChan *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, bool is3d) { - if (!handle || !ChannelMap) + FSoundChan *schan = S_GetChannel(chan); + chan->setUserData(schan); + chan->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, ChannelEndCallback, 0); + schan->Is3D = is3d; + return schan; +} + +//========================================================================== +// +// FMODSoundRenderer :: StopSound +// +//========================================================================== + +void FMODSoundRenderer::StopSound(FSoundChan *chan) +{ + if (chan == NULL) return; - handle--; - if (ChannelMap[handle].soundID != -1) + if (chan->SysChannel != NULL) { - ChannelMap[handle].channelID->stop(); - ChannelMap[handle].soundID = -1; + ((FMOD::Channel *)chan->SysChannel)->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, 0, 0); + ((FMOD::Channel *)chan->SysChannel)->stop(); } + S_ReturnChannel(chan); } -void FMODSoundRenderer::StopAllChannels() +//========================================================================== +// +// FMODSoundRenderer :: ChannelEndCallback static +// +// Called when the channel finishes playing. +// +//========================================================================== + +FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelEndCallback + (FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, + int cmd, unsigned int data1, unsigned int data2) { - for (int i = 1; i <= NumChannels; ++i) + assert(type == FMOD_CHANNEL_CALLBACKTYPE_END); + FMOD::Channel *chan = (FMOD::Channel *)channel; + FSoundChan *schan; + + if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL) { - StopSound(i); + S_ReturnChannel(schan); } + return FMOD_OK; } +//========================================================================== +// +// FMODSoundRenderer :: SetSfxPaused +// +//========================================================================== void FMODSoundRenderer::SetSfxPaused(bool paused) { @@ -987,119 +1095,151 @@ void FMODSoundRenderer::SetSfxPaused(bool paused) } } -bool FMODSoundRenderer::IsPlayingSound(long handle) +//========================================================================== +// +// FMODSoundRenderer :: UpdateSoundParams3D +// +//========================================================================== + +void FMODSoundRenderer::UpdateSoundParams3D(FSoundChan *chan, float pos[3], float vel[3]) { - if (!handle || !ChannelMap) - return false; + if (chan == NULL || chan->SysChannel == NULL) + return; - handle--; - if (ChannelMap[handle].channelID != NULL) + FMOD::Channel *fchan = (FMOD::Channel *)chan->SysChannel; + + // Sounds at the same location as the listener should be head relative, others + // should be world relative. + if (players[consoleplayer].camera != NULL) { - bool is; + FMOD_MODE oldmode, mode; + float cpos[3]; - if (FMOD_OK == ChannelMap[handle].channelID->isPlaying(&is)) + cpos[0] = FIXED2FLOAT(players[consoleplayer].camera->x); + cpos[2] = FIXED2FLOAT(players[consoleplayer].camera->y); + cpos[1] = FIXED2FLOAT(players[consoleplayer].camera->z); + if (FMOD_OK != fchan->getMode(&oldmode)) { - return is; + oldmode = FMOD_3D | FMOD_SOFTWARE; + } + if (cpos[0] == pos[0] && cpos[1] == pos[1] && cpos[2] == pos[2]) + { + mode = (oldmode & ~FMOD_3D_WORLDRELATIVE) | FMOD_3D_HEADRELATIVE; + pos[0] = 0; + pos[1] = 0; + pos[2] = 0; + } + else + { + mode = (oldmode & ~FMOD_3D_HEADRELATIVE) | FMOD_3D_WORLDRELATIVE; + } + // Only set the mode if it changed. + if (((mode ^ oldmode) & (FMOD_3D_WORLDRELATIVE | FMOD_3D_HEADRELATIVE)) == 0) + { + fchan->setMode(mode); } } - return false; + + fchan->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel); } -void FMODSoundRenderer::UpdateSoundParams(long handle, float vol, float sep, int pitch) -{ - if (!handle || !ChannelMap) - return; - - handle--; - if (ChannelMap[handle].soundID == -1 || ChannelMap[handle].channelID == NULL) - return; - - float freq = PITCH(S_sfx[ChannelMap[handle].soundID].frequency, pitch); - FMOD::Channel *chan = ChannelMap[handle].channelID; - - chan->setPan(sep); - chan->setVolume(vol); - chan->setFrequency(freq); -} - -void FMODSoundRenderer::UpdateSoundParams3D(long handle, float pos[3], float vel[3]) -{ - if (!handle || !ChannelMap) - return; - - handle--; - if (ChannelMap[handle].soundID == -1 || ChannelMap[handle].channelID == NULL) - return; - - ChannelMap[handle].channelID->set3DAttributes((FMOD_VECTOR *)pos, (FMOD_VECTOR *)vel); -} +//========================================================================== +// +// FMODSoundRenderer :: ResetEnvironment +// +//========================================================================== void FMODSoundRenderer::ResetEnvironment() { PrevEnvironment = NULL; } -void FMODSoundRenderer::UpdateListener(AActor *listener) +//========================================================================== +// +// FMODSoundRenderer :: UpdateListener +// +//========================================================================== + +void FMODSoundRenderer::UpdateListener() { + AActor *listener = players[consoleplayer].camera; float angle; FMOD_VECTOR pos, vel; FMOD_VECTOR forward; FMOD_VECTOR up; - if(Sound3D && ChannelMap) + if (listener == NULL) { - vel.x = listener->momx * (TICRATE/65536.f); - vel.y = listener->momz * (TICRATE/65536.f); - vel.z = listener->momy * (TICRATE/65536.f); - pos.x = listener->x / 65536.f; - pos.y = listener->z / 65536.f; - pos.z = listener->y / 65536.f; + return; + } - angle = (float)(listener->angle) * ((float)PI / 2147483648.f); + vel.x = listener->momx * (TICRATE/65536.f); + vel.y = listener->momz * (TICRATE/65536.f); + vel.z = listener->momy * (TICRATE/65536.f); + pos.x = listener->x / 65536.f; + pos.y = listener->z / 65536.f; + pos.z = listener->y / 65536.f; - forward.x = cosf(angle); - forward.y = 0; - forward.z = sinf(angle); + angle = (float)(listener->angle) * ((float)PI / 2147483648.f); - up.x = 0; - up.y = 1; - up.z = 0; + forward.x = cosf(angle); + forward.y = 0; + forward.z = sinf(angle); - Sys->set3DListenerAttributes(0, &pos, &vel, &forward, &up); + up.x = 0; + up.y = 1; + up.z = 0; - bool underwater = false; - const ReverbContainer *env; + Sys->set3DListenerAttributes(0, &pos, &vel, &forward, &up); - if (ForcedEnvironment) + bool underwater = false; + const ReverbContainer *env; + + if (ForcedEnvironment) + { + env = ForcedEnvironment; + } + else + { + underwater = (listener->waterlevel == 3 && snd_waterreverb); + assert (zones != NULL); + env = zones[listener->Sector->ZoneNumber].Environment; + if (env == NULL) { - env = ForcedEnvironment; + env = DefaultEnvironments[0]; } - else + if (env == DefaultEnvironments[0] && underwater) { - underwater = (listener->waterlevel == 3 && snd_waterreverb); - assert (zones != NULL); - env = zones[listener->Sector->ZoneNumber].Environment; - if (env == NULL) - { - env = DefaultEnvironments[0]; - } - if (env == DefaultEnvironments[0] && underwater) - { - env = DefaultEnvironments[22]; - } - } - if (env != PrevEnvironment || env->Modified) - { - DPrintf ("Reverb Environment %s\n", env->Name); - const_cast(env)->Modified = false; - Sys->setReverbProperties((FMOD_REVERB_PROPERTIES *)(&env->Properties)); - PausableSfx->setPitch(underwater ? 0.64171f : 1); - PrevEnvironment = env; + env = DefaultEnvironments[22]; } } + if (env != PrevEnvironment || env->Modified) + { + DPrintf ("Reverb Environment %s\n", env->Name); + const_cast(env)->Modified = false; + Sys->setReverbProperties((FMOD_REVERB_PROPERTIES *)(&env->Properties)); + PausableSfx->setPitch(underwater ? 0.64171f : 1); + PrevEnvironment = env; + } +} + +//========================================================================== +// +// FMODSoundRenderer :: UpdateSounds +// +//========================================================================== + +void FMODSoundRenderer::UpdateSounds() +{ Sys->update(); } +//========================================================================== +// +// FMODSoundRenderer :: LoadSound +// +//========================================================================== + void FMODSoundRenderer::LoadSound(sfxinfo_t *sfx) { if (sfx->data == NULL) @@ -1109,6 +1249,12 @@ void FMODSoundRenderer::LoadSound(sfxinfo_t *sfx) } } +//========================================================================== +// +// FMODSoundRenderer :: UnloadSound +// +//========================================================================== + void FMODSoundRenderer::UnloadSound(sfxinfo_t *sfx) { if (sfx->data != NULL) @@ -1119,6 +1265,36 @@ void FMODSoundRenderer::UnloadSound(sfxinfo_t *sfx) } } +//========================================================================== +// +// FMODSoundRenderer :: GetMSLength +// +//========================================================================== + +unsigned int FMODSoundRenderer::GetMSLength(sfxinfo_t *sfx) +{ + if (sfx->data == NULL) + { + LoadSound(sfx); + } + if (sfx->data != NULL) + { + unsigned int length; + + if (((FMOD::Sound *)sfx->data)->getLength(&length, FMOD_TIMEUNIT_MS) == FMOD_OK) + { + return length; + } + } + return 0; // Don't know. +} + +//========================================================================== +// +// FMODSoundRenderer :: DoLoad +// +//========================================================================== + void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx) { BYTE *sfxdata; @@ -1130,7 +1306,7 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx) FMOD_CREATESOUNDEXINFO exinfo = { sizeof(exinfo), }; FMOD::Sound *sample; - samplemode = (Sound3D ? FMOD_3D : FMOD_2D) | FMOD_OPENMEMORY | FMOD_SOFTWARE; + samplemode = FMOD_3D | FMOD_OPENMEMORY | FMOD_SOFTWARE; sfxdata = NULL; errcount = 0; @@ -1177,7 +1353,6 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx) } sfxstart = sfxdata + 8; } - sfx->length = len; exinfo.length = len; exinfo.numchannels = 1; @@ -1222,32 +1397,15 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx) freq = 11025; } sfx->frequency = (unsigned int)freq; - - result = sample->getLength(&sfx->length, FMOD_TIMEUNIT_PCM); - if (result != FMOD_OK) - { - DPrintf("Failed getting sample length\n"); - } - } - - // Get sample length in milliseconds. I think this is only used for ambient sounds? - if (FMOD_OK != sample->getLength(&sfx->ms, FMOD_TIMEUNIT_MS)) - { - sfx->ms = (sfx->length * 1000) / sfx->frequency; } break; } if (sfx->data) { - DPrintf ("[%d Hz %d samples]\n", sfx->frequency, sfx->length); - - if (Sound3D) - { - // Match s_sound.cpp min distance. - // Max distance is irrelevant. - sample->set3DMinMaxDistance(float(S_CLOSE_DIST), float(MAX_SND_DIST)*2); - } + // Match s_sound.cpp min distance. + // Max distance is irrelevant. + sample->set3DMinMaxDistance(float(S_CLOSE_DIST), 10000.f); } if (sfxdata != NULL) @@ -1256,29 +1414,34 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx) } } +//========================================================================== +// +// FMODSoundRenderer :: getsfx +// +// Get the sound data from the WAD and register it with sound library +// +//========================================================================== + void FMODSoundRenderer::getsfx(sfxinfo_t *sfx) { unsigned int i; - // Get the sound data from the WAD and register it with sound library - // If the sound doesn't exist, replace it with the empty sound. if (sfx->lumpnum == -1) { - sfx->lumpnum = Wads.GetNumForName ("dsempty", ns_sounds); + sfx->lumpnum = Wads.GetNumForName("dsempty", ns_sounds); } // See if there is another sound already initialized with this lump. If so, // then set this one up as a link, and don't load the sound again. - for (i = 0; i < S_sfx.Size (); i++) + for (i = 0; i < S_sfx.Size(); i++) { if (S_sfx[i].data && S_sfx[i].link == sfxinfo_t::NO_LINK && S_sfx[i].lumpnum == sfx->lumpnum) { DPrintf ("Linked to %s (%d)\n", S_sfx[i].name.GetChars(), i); sfx->link = i; - sfx->ms = S_sfx[i].ms; return; } } - DoLoad (&sfx->data, sfx); + DoLoad(&sfx->data, sfx); } diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 6139835474..968c59ae5a 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -13,41 +13,35 @@ public: void SetSfxVolume (float volume); void SetMusicVolume (float volume); - int GetNumChannels (); void LoadSound (sfxinfo_t *sfx); void UnloadSound (sfxinfo_t *sfx); + unsigned int GetMSLength(sfxinfo_t *sfx); - // Streaming sounds. PlayStream returns a channel handle that can be used with StopSound. + // Streaming sounds. SoundStream *CreateStream (SoundStreamCallback callback, int buffsamples, int flags, int samplerate, void *userdata); SoundStream *OpenStream (const char *filename, int flags, int offset, int length); long PlayStream (SoundStream *stream, int volume); void StopStream (SoundStream *stream); - // Starts a sound in a particular sound channel. - long StartSound (sfxinfo_t *sfx, float vol, float sep, int pitch, int channel, bool looping, bool pauseable); - long StartSound3D (sfxinfo_t *sfx, float vol, int pitch, int channel, bool looping, float pos[3], float vel[3], bool pauseable); + // Starts a sound. + FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, bool looping, bool pauseable); + FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, int pitch, bool looping, float pos[3], float vel[3], bool pauseable); // Stops a sound channel. - void StopSound (long handle); - - // Stops all sounds. - void StopAllChannels (); + void StopSound (FSoundChan *chan); // Pauses or resumes all sound effect channels. void SetSfxPaused (bool paused); - // Returns true if the channel is still playing a sound. - bool IsPlayingSound (long handle); - - // Updates the volume, separation, and pitch of a sound channel. - void UpdateSoundParams (long handle, float vol, float sep, int pitch); - void UpdateSoundParams3D (long handle, float pos[3], float vel[3]); + // Updates the position of a sound channel. + void UpdateSoundParams3D (FSoundChan *chan, float pos[3], float vel[3]); // For use by I_PlayMovie void MovieDisableSound (); void MovieResumeSound (); - void UpdateListener (AActor *listener); + void UpdateListener (); + void UpdateSounds (); void PrintStatus (); void PrintDriversList (); @@ -55,19 +49,15 @@ public: void ResetEnvironment (); private: - // Maps sfx channels onto FMOD channels - struct ChanMap - { - int soundID; // sfx playing on this channel - FMOD::Channel *channelID; - bool bIsLooping; - } *ChannelMap; - - int NumChannels; unsigned int DriverCaps; int OutputType; bool SFXPaused; + bool InitSuccess; + static FMOD_RESULT F_CALLBACK ChannelEndCallback + (FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, int cmd, unsigned int data1, unsigned int data2); + + FSoundChan *CommonChannelSetup(FMOD::Channel *chan, bool is3d); void DoLoad (void **slot, sfxinfo_t *sfx); void getsfx (sfxinfo_t *sfx); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 6e836a1bc9..03e2ee3c6d 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -1,6 +1,6 @@ /* ** i_sound.cpp -** System interface for sound; uses fmod.dll +** Stubs for sound interfaces. ** **--------------------------------------------------------------------------- ** Copyright 1998-2006 Randy Heit @@ -80,49 +80,8 @@ CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // killough 2/21/98: optionally use varying pitched sounds CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE) -// Maps sfx channels onto FMOD channels -static struct ChanMap -{ - int soundID; // sfx playing on this channel - long channelID; - bool bIsLooping; - bool bIs3D; - unsigned int lastPos; -} *ChannelMap; - SoundRenderer *GSnd; -static int numChannels; -static unsigned int DriverCaps; -static int OutputType; - -static bool SoundDown = true; - -#if 0 -static const char *FmodErrors[] = -{ - "No errors", - "Cannot call this command after FSOUND_Init. Call FSOUND_Close first.", - "This command failed because FSOUND_Init was not called", - "Error initializing output device.", - "Error initializing output device, but more specifically, the output device is already in use and cannot be reused.", - "Playing the sound failed.", - "Soundcard does not support the features needed for this soundsystem (16bit stereo output)", - "Error setting cooperative level for hardware.", - "Error creating hardware sound buffer.", - "File not found", - "Unknown file format", - "Error loading file", - "Not enough memory ", - "The version number of this file format is not supported", - "Incorrect mixer selected", - "An invalid parameter was passed to this function", - "Tried to use a3d and not an a3d hardware card, or dll didnt exist, try another output type.", - "Tried to use an EAX command on a non EAX enabled channel or output.", - "Failed to allocate a new channel" -}; -#endif - // // SFX API @@ -159,16 +118,6 @@ void I_InitSound () return; } - // clamp snd_samplerate to FMOD's limits - if (snd_samplerate < 4000) - { - snd_samplerate = 4000; - } - else if (snd_samplerate > 65535) - { - snd_samplerate = 65535; - } - GSnd = new FMODSoundRenderer; if (!GSnd->IsValid ()) @@ -237,12 +186,11 @@ ADD_STAT (sound) } else { - return "no sound"; + return "No sound"; } } SoundRenderer::SoundRenderer () -: Sound3D (false) { } @@ -250,23 +198,6 @@ SoundRenderer::~SoundRenderer () { } -long SoundRenderer::StartSound3D (sfxinfo_t *sfx, float vol, int pitch, int channel, bool looping, float pos[3], float vel[3], bool pauseable) -{ - return 0; -} - -void SoundRenderer::UpdateSoundParams3D (long handle, float pos[3], float vel[3]) -{ -} - -void SoundRenderer::UpdateListener (AActor *listener) -{ -} - -void SoundRenderer::UpdateSounds () -{ -} - FString SoundRenderer::GatherStats () { return "No stats for this sound renderer."; diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 996f9910d1..fd62b77a9f 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -69,48 +69,39 @@ public: virtual void SetSfxVolume (float volume) = 0; virtual void SetMusicVolume (float volume) = 0; - virtual int GetNumChannels () = 0; // Initialize channels virtual void LoadSound (sfxinfo_t *sfx) = 0; // load a sound from disk virtual void UnloadSound (sfxinfo_t *sfx) = 0; // unloads a sound from memory + virtual unsigned int GetMSLength(sfxinfo_t *sfx) = 0; // Gets the length of a sound at its default frequency - // Streaming sounds. PlayStream returns a channel handle that can be used with StopSound. + // Streaming sounds. virtual SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) = 0; virtual SoundStream *OpenStream (const char *filename, int flags, int offset, int length) = 0; - // Starts a sound in a particular sound channel. - virtual long StartSound (sfxinfo_t *sfx, float vol, float sep, int pitch, int channel, bool looping, bool pauseable) = 0; - virtual long StartSound3D (sfxinfo_t *sfx, float vol, int pitch, int channel, bool looping, float pos[3], float vel[3], bool pauseable); + // Starts a sound. + virtual FSoundChan *StartSound (sfxinfo_t *sfx, float vol, int pitch, bool looping, bool pauseable) = 0; + virtual FSoundChan *StartSound3D (sfxinfo_t *sfx, float vol, int pitch, bool looping, float pos[3], float vel[3], bool pauseable) = 0; // Stops a sound channel. - virtual void StopSound (long handle) = 0; - - // Stops all sounds. - virtual void StopAllChannels () = 0; + virtual void StopSound (FSoundChan *chan) = 0; // Pauses or resumes all sound effect channels. virtual void SetSfxPaused (bool paused) = 0; - // Returns true if the channel is still playing a sound. - virtual bool IsPlayingSound (long handle) = 0; - // Updates the volume, separation, and pitch of a sound channel. - virtual void UpdateSoundParams (long handle, float vol, float sep, int pitch) = 0; - virtual void UpdateSoundParams3D (long handle, float pos[3], float vel[3]); + virtual void UpdateSoundParams3D (FSoundChan *chan, float pos[3], float vel[3]) = 0; // For use by I_PlayMovie virtual void MovieDisableSound () = 0; virtual void MovieResumeSound () = 0; - virtual void UpdateListener (AActor *listener); - virtual void UpdateSounds (); + virtual void UpdateListener () = 0; + virtual void UpdateSounds () = 0; virtual bool IsValid () = 0; virtual void PrintStatus () = 0; virtual void PrintDriversList () = 0; virtual FString GatherStats (); virtual void ResetEnvironment (); - - bool Sound3D; }; extern SoundRenderer *GSnd; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 87f1bc568d..37e4a9210d 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -319,11 +319,11 @@ void A_PlaySoundEx (AActor *self) int attenuation; switch (attenuation_raw) { - case -1: attenuation=ATTN_STATIC; break; // drop off rapidly + case -1: attenuation = ATTN_STATIC; break; // drop off rapidly default: - case 0: attenuation=ATTN_NORM; break; // normal - case 1: attenuation=ATTN_NONE; break; // full volume - case 2: attenuation=ATTN_SURROUND; break; // full volume surround + case 0: attenuation = ATTN_NORM; break; // normal + case 1: + case 2: attenuation = ATTN_NONE; break; // full volume } if (channel < NAME_Auto || channel > NAME_SoundSlot7) diff --git a/tools/dehsupp/parse.c b/tools/dehsupp/parse.c index 93a50ab962..29fc39603e 100644 --- a/tools/dehsupp/parse.c +++ b/tools/dehsupp/parse.c @@ -6,11 +6,18 @@ #include #include #include + +#ifdef _MSC_VER +#define CDECL __cdecl +#else +#define CDECL +#endif + #line 1 "parse.y" #include #include "dehsupp.h" -#line 14 "parse.c" +#line 21 "parse.c" /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ @@ -461,7 +468,7 @@ static void yyGrowStack(yyParser *p){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -void *ParseAlloc(void *(*mallocProc)(size_t)){ +void *ParseAlloc(void *(CDECL *mallocProc)(size_t)){ yyParser *pParser; pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ @@ -525,7 +532,7 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ case 33: /* RenderStyles */ #line 10 "parse.y" { if ((yypminor->yy0).string) free((yypminor->yy0).string); } -#line 529 "parse.c" +#line 536 "parse.c" break; default: break; /* If no destructor action specified: do nothing */ } @@ -571,7 +578,7 @@ static int yy_pop_parser_stack(yyParser *pParser){ */ void ParseFree( void *p, /* The parser to be deleted */ - void (*freeProc)(void*) /* Function used to reclaim memory */ + void (CDECL *freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; if( pParser==0 ) return; @@ -903,7 +910,7 @@ static void yy_reduce( #line 21 "parse.y" { } -#line 907 "parse.c" +#line 914 "parse.c" break; case 14: /* print_statement ::= PRINT LPAREN print_list RPAREN */ #line 39 "parse.y" @@ -913,7 +920,7 @@ static void yy_reduce( yy_destructor(11,&yymsp[-2].minor); yy_destructor(12,&yymsp[0].minor); } -#line 917 "parse.c" +#line 924 "parse.c" break; case 17: /* print_list ::= print_item COMMA print_list */ case 60: /*state_map_list ::= state_map_list COMMA state_map_entry */ @@ -923,83 +930,83 @@ static void yy_reduce( { yy_destructor(13,&yymsp[-1].minor); } -#line 927 "parse.c" +#line 934 "parse.c" break; case 18: /* print_item ::= STRING */ #line 47 "parse.y" { printf ("%s", yymsp[0].minor.yy0.string); } -#line 932 "parse.c" +#line 939 "parse.c" break; case 19: /* print_item ::= exp */ #line 48 "parse.y" { printf ("%d", yymsp[0].minor.yy64); } -#line 937 "parse.c" +#line 944 "parse.c" break; case 20: /* print_item ::= ENDL */ #line 49 "parse.y" { printf ("\n"); yy_destructor(15,&yymsp[0].minor); } -#line 943 "parse.c" +#line 950 "parse.c" break; case 21: /* exp ::= NUM */ #line 52 "parse.y" { yygotominor.yy64 = yymsp[0].minor.yy0.val; } -#line 948 "parse.c" +#line 955 "parse.c" break; case 22: /* exp ::= exp PLUS exp */ #line 53 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 + yymsp[0].minor.yy64; yy_destructor(5,&yymsp[-1].minor); } -#line 954 "parse.c" +#line 961 "parse.c" break; case 23: /* exp ::= exp MINUS exp */ #line 54 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 - yymsp[0].minor.yy64; yy_destructor(4,&yymsp[-1].minor); } -#line 960 "parse.c" +#line 967 "parse.c" break; case 24: /* exp ::= exp MULTIPLY exp */ #line 55 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 * yymsp[0].minor.yy64; yy_destructor(6,&yymsp[-1].minor); } -#line 966 "parse.c" +#line 973 "parse.c" break; case 25: /* exp ::= exp DIVIDE exp */ #line 56 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 / yymsp[0].minor.yy64; yy_destructor(7,&yymsp[-1].minor); } -#line 972 "parse.c" +#line 979 "parse.c" break; case 26: /* exp ::= exp OR exp */ #line 57 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 | yymsp[0].minor.yy64; yy_destructor(1,&yymsp[-1].minor); } -#line 978 "parse.c" +#line 985 "parse.c" break; case 27: /* exp ::= exp AND exp */ #line 58 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 & yymsp[0].minor.yy64; yy_destructor(3,&yymsp[-1].minor); } -#line 984 "parse.c" +#line 991 "parse.c" break; case 28: /* exp ::= exp XOR exp */ #line 59 "parse.y" { yygotominor.yy64 = yymsp[-2].minor.yy64 ^ yymsp[0].minor.yy64; yy_destructor(2,&yymsp[-1].minor); } -#line 990 "parse.c" +#line 997 "parse.c" break; case 29: /* exp ::= MINUS exp */ #line 60 "parse.y" { yygotominor.yy64 = -yymsp[0].minor.yy64; yy_destructor(4,&yymsp[-1].minor); } -#line 996 "parse.c" +#line 1003 "parse.c" break; case 30: /* exp ::= LPAREN exp RPAREN */ #line 61 "parse.y" { yygotominor.yy64 = yymsp[-1].minor.yy64; yy_destructor(11,&yymsp[-2].minor); yy_destructor(12,&yymsp[0].minor); } -#line 1003 "parse.c" +#line 1010 "parse.c" break; case 31: /* actions_def ::= Actions LBRACE actions_list RBRACE SEMICOLON */ case 32: /*actions_def ::= Actions LBRACE error RBRACE SEMICOLON */ @@ -1010,18 +1017,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1014 "parse.c" +#line 1021 "parse.c" break; case 34: /* actions_list ::= SYM */ #line 68 "parse.y" { AddAction (yymsp[0].minor.yy0.string); } -#line 1019 "parse.c" +#line 1026 "parse.c" break; case 35: /* actions_list ::= actions_list COMMA SYM */ #line 69 "parse.y" { AddAction (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 1025 "parse.c" +#line 1032 "parse.c" break; case 36: /* org_heights_def ::= OrgHeights LBRACE org_heights_list RBRACE SEMICOLON */ case 37: /*org_heights_def ::= OrgHeights LBRACE error RBRACE SEMICOLON */ @@ -1032,18 +1039,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1036 "parse.c" +#line 1043 "parse.c" break; case 39: /* org_heights_list ::= exp */ #line 76 "parse.y" { AddHeight (yymsp[0].minor.yy64); } -#line 1041 "parse.c" +#line 1048 "parse.c" break; case 40: /* org_heights_list ::= org_heights_list COMMA exp */ #line 77 "parse.y" { AddHeight (yymsp[0].minor.yy64); yy_destructor(13,&yymsp[-1].minor); } -#line 1047 "parse.c" +#line 1054 "parse.c" break; case 41: /* action_list_def ::= ActionList LBRACE action_list_list RBRACE SEMICOLON */ case 42: /*action_list_def ::= ActionList LBRACE error RBRACE SEMICOLON */ @@ -1054,18 +1061,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1058 "parse.c" +#line 1065 "parse.c" break; case 44: /* action_list_list ::= SYM */ #line 84 "parse.y" { AddActionMap (yymsp[0].minor.yy0.string); } -#line 1063 "parse.c" +#line 1070 "parse.c" break; case 45: /* action_list_list ::= action_list_list COMMA SYM */ #line 85 "parse.y" { AddActionMap (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 1069 "parse.c" +#line 1076 "parse.c" break; case 46: /* codep_conv_def ::= CodePConv LBRACE codep_conv_list RBRACE SEMICOLON */ case 47: /*codep_conv_def ::= CodePConv LBRACE error RBRACE SEMICOLON */ @@ -1076,18 +1083,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1080 "parse.c" +#line 1087 "parse.c" break; case 49: /* codep_conv_list ::= exp */ #line 92 "parse.y" { AddCodeP (yymsp[0].minor.yy64); } -#line 1085 "parse.c" +#line 1092 "parse.c" break; case 50: /* codep_conv_list ::= codep_conv_list COMMA exp */ #line 93 "parse.y" { AddCodeP (yymsp[0].minor.yy64); yy_destructor(13,&yymsp[-1].minor); } -#line 1091 "parse.c" +#line 1098 "parse.c" break; case 51: /* org_spr_names_def ::= OrgSprNames LBRACE org_spr_names_list RBRACE SEMICOLON */ case 52: /*org_spr_names_def ::= OrgSprNames LBRACE error RBRACE SEMICOLON */ @@ -1098,18 +1105,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1102 "parse.c" +#line 1109 "parse.c" break; case 54: /* org_spr_names_list ::= SYM */ #line 100 "parse.y" { AddSpriteName (yymsp[0].minor.yy0.string); } -#line 1107 "parse.c" +#line 1114 "parse.c" break; case 55: /* org_spr_names_list ::= org_spr_names_list COMMA SYM */ #line 101 "parse.y" { AddSpriteName (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 1113 "parse.c" +#line 1120 "parse.c" break; case 56: /* state_map_def ::= StateMap LBRACE state_map_list RBRACE SEMICOLON */ case 57: /*state_map_def ::= StateMap LBRACE error RBRACE SEMICOLON */ @@ -1120,32 +1127,32 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1124 "parse.c" +#line 1131 "parse.c" break; case 61: /* state_map_entry ::= SYM COMMA state_type COMMA exp */ #line 111 "parse.y" { AddStateMap (yymsp[-4].minor.yy0.string, yymsp[-2].minor.yy64, yymsp[0].minor.yy64); yy_destructor(13,&yymsp[-3].minor); yy_destructor(13,&yymsp[-1].minor); } -#line 1131 "parse.c" +#line 1138 "parse.c" break; case 62: /* state_type ::= FirstState */ #line 114 "parse.y" { yygotominor.yy64 = 0; yy_destructor(27,&yymsp[0].minor); } -#line 1137 "parse.c" +#line 1144 "parse.c" break; case 63: /* state_type ::= SpawnState */ #line 115 "parse.y" { yygotominor.yy64 = 1; yy_destructor(28,&yymsp[0].minor); } -#line 1143 "parse.c" +#line 1150 "parse.c" break; case 64: /* state_type ::= DeathState */ #line 116 "parse.y" { yygotominor.yy64 = 2; yy_destructor(29,&yymsp[0].minor); } -#line 1149 "parse.c" +#line 1156 "parse.c" break; case 65: /* sound_map_def ::= SoundMap LBRACE sound_map_list RBRACE SEMICOLON */ case 66: /*sound_map_def ::= SoundMap LBRACE error RBRACE SEMICOLON */ @@ -1156,18 +1163,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1160 "parse.c" +#line 1167 "parse.c" break; case 68: /* sound_map_list ::= STRING */ #line 123 "parse.y" { AddSoundMap (yymsp[0].minor.yy0.string); } -#line 1165 "parse.c" +#line 1172 "parse.c" break; case 69: /* sound_map_list ::= sound_map_list COMMA STRING */ #line 124 "parse.y" { AddSoundMap (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 1171 "parse.c" +#line 1178 "parse.c" break; case 70: /* info_names_def ::= InfoNames LBRACE info_names_list RBRACE SEMICOLON */ case 71: /*info_names_def ::= InfoNames LBRACE error RBRACE SEMICOLON */ @@ -1178,18 +1185,18 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1182 "parse.c" +#line 1189 "parse.c" break; case 73: /* info_names_list ::= SYM */ #line 131 "parse.y" { AddInfoName (yymsp[0].minor.yy0.string); } -#line 1187 "parse.c" +#line 1194 "parse.c" break; case 74: /* info_names_list ::= info_names_list COMMA SYM */ #line 132 "parse.y" { AddInfoName (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 1193 "parse.c" +#line 1200 "parse.c" break; case 75: /* thing_bits_def ::= ThingBits LBRACE thing_bits_list RBRACE SEMICOLON */ case 76: /*thing_bits_def ::= ThingBits LBRACE error RBRACE SEMICOLON */ @@ -1200,14 +1207,14 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1204 "parse.c" +#line 1211 "parse.c" break; case 80: /* thing_bits_entry ::= exp COMMA exp COMMA SYM */ #line 142 "parse.y" { AddThingBits (yymsp[0].minor.yy0.string, yymsp[-4].minor.yy64, yymsp[-2].minor.yy64); yy_destructor(13,&yymsp[-3].minor); yy_destructor(13,&yymsp[-1].minor); } -#line 1211 "parse.c" +#line 1218 "parse.c" break; case 81: /* render_styles_def ::= RenderStyles LBRACE render_styles_list RBRACE SEMICOLON */ case 82: /*render_styles_def ::= RenderStyles LBRACE error RBRACE SEMICOLON */ @@ -1218,13 +1225,13 @@ static void yy_reduce( yy_destructor(19,&yymsp[-1].minor); yy_destructor(20,&yymsp[0].minor); } -#line 1222 "parse.c" +#line 1229 "parse.c" break; case 86: /* render_styles_entry ::= exp COMMA SYM */ #line 152 "parse.y" { AddRenderStyle (yymsp[0].minor.yy0.string, yymsp[-2].minor.yy64); yy_destructor(13,&yymsp[-1].minor); } -#line 1228 "parse.c" +#line 1235 "parse.c" break; }; yygoto = yyRuleInfo[yyruleno].lhs; @@ -1284,7 +1291,7 @@ static void yy_syntax_error( #define TOKEN (yyminor.yy0) #line 8 "parse.y" yyerror("Syntax error"); -#line 1288 "parse.c" +#line 1295 "parse.c" ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } diff --git a/tools/updaterevision/updaterevision.vcproj b/tools/updaterevision/updaterevision.vcproj index f39914dcac..202c9d042b 100644 --- a/tools/updaterevision/updaterevision.vcproj +++ b/tools/updaterevision/updaterevision.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - -