diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 84d65ea23b1..f13b3ae3db2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1227,6 +1227,7 @@ set (PCH_SOURCES sound/music/i_music.cpp sound/music/i_soundfont.cpp sound/backend/i_sound.cpp + sound/backend/i_channellist.cpp sound/mididevices/music_adlmidi_mididevice.cpp sound/mididevices/music_opldumper_mididevice.cpp sound/mididevices/music_opl_mididevice.cpp diff --git a/src/sound/backend/i_channellist.cpp b/src/sound/backend/i_channellist.cpp new file mode 100644 index 00000000000..ab1e5ae4ab6 --- /dev/null +++ b/src/sound/backend/i_channellist.cpp @@ -0,0 +1,346 @@ +//----------------------------------------------------------------------------- +// +// Copyright 1993-1996 id Software +// Copyright 1999-2016 Randy Heit +// Copyright 2002-2016 Christoph Oelckers +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//----------------------------------------------------------------------------- +// +// DESCRIPTION: Sound channel list +// +//----------------------------------------------------------------------------- + + +#include +#include "i_sound.h" +#include "i_channellist.h" + + +//========================================================================== +// +// S_GetChannel +// +// Returns a free channel for the system sound interface. +// +//========================================================================== + +FISoundChannel *FIChannelList::GetChannel(void *syschan) +{ + FISoundChannel *chan; + + if (FreeChannels != nullptr) + { + chan = FreeChannels; + UnlinkChannel(chan); + return chan; + } + else + { + chan = (FISoundChannel *)malloc(ChannelStructSize); + } + memset(chan, 0, ChannelStructSize); + LinkChannel(chan, &Channels); + chan->SysChannel = syschan; + return chan; +} + +//========================================================================== +// +// S_ReturnChannel +// +// Returns a channel to the free pool. +// +//========================================================================== + +void FIChannelList::ReturnChannel(FISoundChannel *chan) +{ + UnlinkChannel(chan); + LinkChannel(chan, &FreeChannels); +} + +//========================================================================== +// +// S_UnlinkChannel +// +//========================================================================== + +void FIChannelList::UnlinkChannel(FISoundChannel *chan) +{ + *(chan->PrevChan) = chan->NextChan; + if (chan->NextChan != nullptr) + { + chan->NextChan->PrevChan = chan->PrevChan; + } +} + +//========================================================================== +// +// S_LinkChannel +// +//========================================================================== + +void FIChannelList::LinkChannel(FISoundChannel *chan, FISoundChannel **head) +{ + chan->NextChan = *head; + if (chan->NextChan != nullptr) + { + chan->NextChan->PrevChan = &chan->NextChan; + } + *head = chan; + chan->PrevChan = head; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FIChannelList::ReturnAllChannels() +{ + while (Channels != nullptr) + { + ReturnChannel(Channels); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FIChannelList::StopAllChannels() +{ + auto chan = Channels; + while (chan != nullptr) + { + auto next = chan->NextChan; + StopChannel(chan); + chan = next; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FIChannelList::FreeChannelList() +{ + // This should only be called when all sounds have been stopped. + assert(Channels == nullptr); + for(auto p = FreeChannels; p; p = p->NextChan) + { + free(p); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FIChannelList::SetPitch(FISoundChannel *chan, float pitch) +{ + GSnd->ChannelPitch(chan, std::max(0.0001f, pitch)); + chan->Pitch = std::max(1, int(float(NORM_PITCH) * pitch)); +} + + +//========================================================================== +// +// S_ChannelEnded (callback for sound interface code) +// +//========================================================================== + +void FIChannelList::ChannelEnded(FISoundChannel *schan) +{ + bool evicted; + + if (schan != NULL) + { + // If the sound was stopped with GSnd->StopSound(), then we know + // it wasn't evicted. Otherwise, if it's looping, it must have + // been evicted. If it's not looping, then it was evicted if it + // didn't reach the end of its playback. + if (schan->ChanFlags & CHAN_FORGETTABLE) + { + evicted = false; + } + else if (schan->ChanFlags & (CHAN_LOOP | CHAN_EVICTED)) + { + evicted = true; + } + else + { + unsigned int pos = GSnd->GetPosition(schan); + unsigned int len = GSnd->GetSampleLength(SoundData(schan)); + if (pos == 0) + { + evicted = !!(schan->ChanFlags & CHAN_JUSTSTARTED); + } + else + { + evicted = (pos < len); + } + } + if (!evicted) + { + ReturnChannel(schan); + } + else + { + schan->ChanFlags |= CHAN_EVICTED; + schan->SysChannel = nullptr; + } + } +} + +//========================================================================== +// +// S_ChannelVirtualChanged (callback for sound interface code) +// +//========================================================================== + +void FIChannelList::ChannelVirtualChanged(FISoundChannel *schan, bool is_virtual) +{ + if (is_virtual) + { + schan->ChanFlags |= CHAN_VIRTUAL; + } + else + { + schan->ChanFlags &= ~CHAN_VIRTUAL; + } +} + +//========================================================================== +// +// S_StopChannel +// +//========================================================================== + +void FIChannelList::StopChannel(FISoundChannel *chan) +{ + if (chan == NULL) + return; + + if (chan->SysChannel != NULL) + { + // S_EvictAllChannels() will set the CHAN_EVICTED flag to indicate + // that it wants to keep all the channel information around. + if (!(chan->ChanFlags & CHAN_EVICTED)) + { + chan->ChanFlags |= CHAN_FORGETTABLE; + ChannelStopped(chan); + + } + GSnd->StopChannel(chan); + } + else + { + ReturnChannel(chan); + } +} + + +//========================================================================== +// +// S_EvictAllChannels +// +// Forcibly evicts all channels so that there are none playing, but all +// information needed to restart them is retained. +// +//========================================================================== + +void FIChannelList::EvictAllChannels() +{ + FISoundChannel *chan, *next; + + for (chan = Channels; chan != nullptr; chan = next) + { + next = chan->NextChan; + + if (!(chan->ChanFlags & CHAN_EVICTED)) + { + chan->ChanFlags |= CHAN_EVICTED; + if (chan->SysChannel != nullptr) + { + if (!(chan->ChanFlags & CHAN_ABSTIME)) + { + chan->StartTime = GSnd ? GSnd->GetPosition(chan) : 0; + chan->ChanFlags |= CHAN_ABSTIME; + } + StopChannel(chan); + } + } + } +} + +//========================================================================== +// +// S_RestoreEvictedChannel +// +// Recursive helper for S_RestoreEvictedChannels(). +// +//========================================================================== + +void FIChannelList::RestoreEvictedChannel(FISoundChannel *chan) +{ + if (chan == NULL) + { + return; + } + RestoreEvictedChannel(chan->NextChan); + if (chan->ChanFlags & CHAN_EVICTED) + { + RestartSound(chan); + if (!(chan->ChanFlags & CHAN_LOOP)) + { + if (chan->ChanFlags & CHAN_EVICTED) + { // Still evicted and not looping? Forget about it. + ReturnChannel(chan); + } + else if (!(chan->ChanFlags & CHAN_JUSTSTARTED)) + { // Should this sound become evicted again, it's okay to forget about it. + chan->ChanFlags |= CHAN_FORGETTABLE; + } + } + } + else if (chan->SysChannel == NULL && (chan->ChanFlags & (CHAN_FORGETTABLE | CHAN_LOOP)) == CHAN_FORGETTABLE) + { + ReturnChannel(chan); + } +} + +//========================================================================== +// +// S_RestoreEvictedChannels +// +// Restarts as many evicted channels as possible. Any channels that could +// not be started and are not looping are moved to the free pool. +// +//========================================================================== + +void FIChannelList::RestoreEvictedChannels() +{ + // Restart channels in the same order they were originally played. + RestoreEvictedChannel(Channels); +} + diff --git a/src/sound/backend/i_channellist.h b/src/sound/backend/i_channellist.h new file mode 100644 index 00000000000..a2b68ab6751 --- /dev/null +++ b/src/sound/backend/i_channellist.h @@ -0,0 +1,97 @@ +#pragma once + +#include +#include + +// Note that at the moment these are shared with the sound playing interface. This should probably be changed! +enum ESoundChannelFlags +{ + // modifier flags + CHAN_LISTENERZ = 8, + CHAN_MAYBE_LOCAL = 16, + CHAN_UI = 32, // Do not record sound in savegames. + CHAN_NOPAUSE = 64, // Do not pause this sound in menus. + CHAN_AREA = 128, // Sound plays from all around. Only valid with sector sounds. + CHAN_LOOP = 256, + + CHAN_IS3D = 1, // internal: Sound is 3D. + CHAN_EVICTED = 2, // internal: Sound was evicted. + CHAN_FORGETTABLE = 4, // internal: Forget channel data when sound stops. + CHAN_JUSTSTARTED = 512, // internal: Sound has not been updated yet. + CHAN_ABSTIME = 1024, // internal: Start time is absolute and does not depend on current time. + CHAN_VIRTUAL = 2048, // internal: Channel is currently virtual +}; + +// Default rolloff information. +struct FRolloffInfo +{ + int RolloffType; + float MinDistance; + union { float MaxDistance; float RolloffFactor; }; +}; + +struct FISoundChannel +{ + void *SysChannel; // Channel information from the system interface. + FISoundChannel *NextChan; // Next channel in this list. + FISoundChannel **PrevChan; // Previous channel in this list. + + uint64_t StartTime; // Sound start time in DSP clocks. + + // The sound interface doesn't use these directly but it needs to pass them to a + // callback that can't be passed a sound channel pointer + FRolloffInfo Rolloff; + float DistanceScale; + float DistanceSqr; + float Volume; + int16_t Pitch; // Pitch variation. + int8_t Priority; + bool ManualRolloff; + int ChanFlags; +}; + + +class FIChannelList +{ +protected: + const size_t ChannelStructSize; + FISoundChannel *Channels = nullptr; + FISoundChannel *FreeChannels = nullptr; + + FIChannelList(size_t size) : ChannelStructSize(size) {} + void LinkChannel(FISoundChannel *chan, FISoundChannel **list); + +public: + + enum + { + NORM_PITCH = 128 + }; + + FISoundChannel *GetChannel(void *syschan); + void ReturnChannel(FISoundChannel *chan); + void UnlinkChannel(FISoundChannel *chan); + void FreeChannelList(); + void ChannelEnded(FISoundChannel *schan); + void ChannelVirtualChanged(FISoundChannel *ichan, bool is_virtual); + void StopChannel(FISoundChannel *chan); + void EvictAllChannels(); + void RestoreEvictedChannel(FISoundChannel *chan); + void RestoreEvictedChannels(); + void ReturnAllChannels(); + void StopAllChannels(); + void SetPitch(FISoundChannel *chan, float dpitch); + + FISoundChannel *FirstChannel() const + { + return Channels; + } + + + + virtual SoundHandle &SoundData(FISoundChannel *chan) = 0; // Only the implementor knows this. + virtual void ChannelStopped(FISoundChannel *chan) {} // Give the implementor a chance for custom, actions; optional. + virtual void RestartSound(FISoundChannel *chan) = 0; // Only the implementor can do this. + + ~FIChannelList() { FreeChannelList(); } +}; diff --git a/src/sound/backend/i_sound.cpp b/src/sound/backend/i_sound.cpp index c7aae60ec23..afabf5cf9a4 100644 --- a/src/sound/backend/i_sound.cpp +++ b/src/sound/backend/i_sound.cpp @@ -346,12 +346,14 @@ CCMD (snd_status) CCMD (snd_reset) { + auto channels = GSnd? GSnd->Channels : nullptr; I_ShutdownMusic(); - S_EvictAllChannels(); + if (channels) channels->EvictAllChannels(); I_CloseSound(); I_InitSound(); + GSnd->Channels = channels; S_RestartMusic(); - S_RestoreEvictedChannels(); + if (channels) channels->RestoreEvictedChannels(); } CCMD (snd_listdrivers) diff --git a/src/sound/backend/i_sound.h b/src/sound/backend/i_sound.h index 6323e361db0..12df51be55f 100644 --- a/src/sound/backend/i_sound.h +++ b/src/sound/backend/i_sound.h @@ -36,9 +36,10 @@ #define __I_SOUND__ #include "i_soundinternal.h" - +#include "i_channellist.h" class FileReader; -struct FSoundChan; + + enum ECodecType { @@ -172,6 +173,8 @@ class SoundRenderer virtual void DrawWaveDebug(int mode); static SoundDecoder *CreateDecoder(FileReader &reader); + + FIChannelList *Channels = nullptr; }; extern SoundRenderer *GSnd; @@ -181,13 +184,9 @@ extern bool nosound; void I_InitSound (); void I_ShutdownSound (); -void S_ChannelEnded(FISoundChannel *schan); -void S_ChannelVirtualChanged(FISoundChannel *schan, bool is_virtual); -float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic); -FISoundChannel *S_GetChannel(void *syschan); - extern ReverbContainer *DefaultEnvironments[26]; bool IsOpenALPresent(); + #endif diff --git a/src/sound/backend/i_soundinternal.h b/src/sound/backend/i_soundinternal.h index 18259c1be39..369d453f00c 100644 --- a/src/sound/backend/i_soundinternal.h +++ b/src/sound/backend/i_soundinternal.h @@ -8,6 +8,7 @@ #include "tarray.h" class FileReader; +struct FISoundChannel; // For convenience, this structure matches FMOD_REVERB_PROPERTIES. // Since I can't very well #include system-specific stuff in the @@ -77,13 +78,6 @@ struct SoundListener ReverbContainer *Environment; }; -// Default rolloff information. -struct FRolloffInfo -{ - int RolloffType; - float MinDistance; - union { float MaxDistance; float RolloffFactor; }; -}; struct SoundHandle { @@ -98,20 +92,6 @@ struct SoundHandle { return !(*this == rhs); } }; -struct FISoundChannel -{ - void *SysChannel; // Channel information from the system interface. - uint64_t StartTime; // Sound start time in DSP clocks. - - // The sound interface doesn't use these directly but it needs to pass them to a - // callback that can't be passed a sound channel pointer - FRolloffInfo Rolloff; - float DistanceScale; - float DistanceSqr; - bool ManualRolloff; - int ChanFlags; -}; - void FindLoopTags(FileReader &fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass); diff --git a/src/sound/backend/oalsound.cpp b/src/sound/backend/oalsound.cpp index 12860b8e672..840cfdfe88a 100644 --- a/src/sound/backend/oalsound.cpp +++ b/src/sound/backend/oalsound.cpp @@ -24,7 +24,7 @@ ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** DATA, OR PROFITS; OR BUSINESS NTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @@ -45,6 +45,7 @@ #include "i_musicinterns.h" #include "cmdlib.h" #include "menu/menu.h" +#include "i_channellist.h" FModule OpenALModule{"OpenAL"}; @@ -254,7 +255,7 @@ class OpenALSoundStream : public SoundStream /* Get a source, killing the farthest, lowest-priority sound if needed */ if(Renderer->FreeSfx.Size() == 0) { - FSoundChan *lowest = Renderer->FindLowestChannel(); + FISoundChannel *lowest = Renderer->FindLowestChannel(); if(lowest) Renderer->ForceStopChannel(lowest); if(Renderer->FreeSfx.Size() == 0) @@ -1115,7 +1116,7 @@ void OpenALSoundRenderer::SetSfxVolume(float volume) { SfxVolume = volume; - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while(schan) { if(schan->SysChannel != NULL) @@ -1489,7 +1490,7 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) return; ALuint buffer = GET_PTRID(sfx.data); - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while(schan) { if(schan->SysChannel) @@ -1498,7 +1499,7 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) alGetSourcei(GET_PTRID(schan->SysChannel), AL_BUFFER, &bufID); if((ALuint)bufID == buffer) { - FSoundChan *next = schan->NextChan; + FISoundChannel *next = schan->NextChan; ForceStopChannel(schan); schan = next; continue; @@ -1556,7 +1557,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int { if(FreeSfx.Size() == 0) { - FSoundChan *lowest = FindLowestChannel(); + FISoundChannel *lowest = FindLowestChannel(); if(lowest) ForceStopChannel(lowest); if(FreeSfx.Size() == 0) @@ -1638,7 +1639,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int FreeSfx.Pop(); FISoundChannel *chan = reuse_chan; - if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); + if(!chan) chan = Channels->GetChannel(MAKE_PTRID(source)); else chan->SysChannel = MAKE_PTRID(source); chan->Rolloff.RolloffType = ROLLOFF_Log; @@ -1658,7 +1659,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener if(FreeSfx.Size() == 0) { - FSoundChan *lowest = FindLowestChannel(); + FISoundChannel *lowest = FindLowestChannel(); if(lowest) { if(lowest->Priority < priority || (lowest->Priority == priority && @@ -1849,7 +1850,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener FreeSfx.Pop(); FISoundChannel *chan = reuse_chan; - if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); + if(!chan) chan = Channels->GetChannel(MAKE_PTRID(source)); else chan->SysChannel = MAKE_PTRID(source); chan->Rolloff = *rolloff; @@ -1908,7 +1909,7 @@ void OpenALSoundRenderer::StopChannel(FISoundChannel *chan) ALuint source = GET_PTRID(chan->SysChannel); // Release first, so it can be properly marked as evicted if it's being killed - S_ChannelEnded(chan); + Channels->ChannelEnded(chan); ALint state = AL_INITIAL; alGetSourcei(source, AL_SOURCE_STATE, &state); @@ -1932,7 +1933,7 @@ void OpenALSoundRenderer::ForceStopChannel(FISoundChannel *chan) ALuint source = GET_PTRID(chan->SysChannel); if(!source) return; - S_ChannelEnded(chan); + Channels->ChannelEnded(chan); FreeSource(source); } @@ -2152,7 +2153,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); // Apply the updated filters on the sources - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); @@ -2165,7 +2166,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) } } - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); @@ -2190,7 +2191,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); @@ -2203,7 +2204,7 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) } } - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); @@ -2379,7 +2380,7 @@ void OpenALSoundRenderer::PurgeStoppedSources() if(state == AL_INITIAL || state == AL_PLAYING || state == AL_PAUSED) continue; - FSoundChan *schan = Channels; + FISoundChannel *schan = Channels->FirstChannel(); while(schan) { if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) @@ -2499,10 +2500,10 @@ void OpenALSoundRenderer::LoadReverb(const ReverbContainer *env) getALError(); } -FSoundChan *OpenALSoundRenderer::FindLowestChannel() +FISoundChannel *OpenALSoundRenderer::FindLowestChannel() { - FSoundChan *schan = Channels; - FSoundChan *lowest = NULL; + FISoundChannel *schan = Channels->FirstChannel(); + FISoundChannel *lowest = NULL; while(schan) { if(schan->SysChannel != NULL) diff --git a/src/sound/backend/oalsound.h b/src/sound/backend/oalsound.h index 2b1a50fd4a7..c2e33731385 100644 --- a/src/sound/backend/oalsound.h +++ b/src/sound/backend/oalsound.h @@ -248,7 +248,7 @@ class OpenALSoundRenderer : public SoundRenderer void LoadReverb(const ReverbContainer *env); void FreeSource(ALuint source); void PurgeStoppedSources(); - static FSoundChan *FindLowestChannel(); + FISoundChannel *FindLowestChannel(); void ForceStopChannel(FISoundChannel *chan); std::thread StreamThread; diff --git a/src/sound/s_sound.cpp b/src/sound/s_sound.cpp index 16a47bd8f61..4a70696ad24 100644 --- a/src/sound/s_sound.cpp +++ b/src/sound/s_sound.cpp @@ -84,6 +84,7 @@ #include "vm.h" #include "g_game.h" #include "atterm.h" +#include "i_channellist.h" // MACROS ------------------------------------------------------------------ @@ -96,9 +97,6 @@ #define O_BINARY 0 #endif -#define NORM_PITCH 128 -#define NORM_PRIORITY 64 -#define NORM_SEP 0 #define S_PITCH_PERTURB 1 #define S_STEREO_SWING 0.75 @@ -134,6 +132,7 @@ static void CalcPolyobjSoundOrg(const DVector3 &listenpos, const FPolyObj *poly, static FSoundChan *S_StartSound(AActor *mover, const sector_t *sec, const FPolyObj *poly, const FVector3 *pt, int channel, FSoundID sound_id, float volume, float attenuation, FRolloffInfo *rolloff, float spitch); static void S_SetListener(SoundListener &listener, AActor *listenactor); +static void S_RestartSound(FSoundChan *chan); // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -144,6 +143,41 @@ static FString LastSong; // last music that was played static FPlayList *PlayList; static int RestartEvictionsAt; // do not restart evicted channels before this time +class FSoundChannelList : public FIChannelList +{ +public: + FSoundChannelList() : FIChannelList(sizeof(FSoundChan)) + { + } + virtual SoundHandle &SoundData(FISoundChannel *chan) override + { + auto schan = static_cast(chan); + return S_sfx[schan->SoundID].data; + } + + virtual void ChannelStopped(FISoundChannel *chan) + { + auto schan = static_cast(chan); + if (schan->SourceType == SOURCE_Actor) + { + schan->Actor = nullptr; + } + + } + + void RestartSound(FISoundChannel *chan) + { + S_RestartSound(static_cast(chan)); + } + + FSoundChan *Channels() const + { + return static_cast(FirstChannel()); + } +}; + +static FSoundChannelList ChannelList; + DEFINE_GLOBAL_NAMED(mus_playing, musplaying); DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name); DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder); @@ -153,7 +187,6 @@ DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, loop); int sfx_empty; -FSoundChan *Channels; FSoundChan *FreeChannels; FRolloffInfo S_Rolloff; @@ -199,7 +232,7 @@ void S_NoiseDebug (void) screen->DrawText (NewConsoleFont, CR_GOLD, 520, y, "pos", TAG_DONE); y += NewConsoleFont->GetHeight(); - if (Channels == NULL) + if (ChannelList.Channels() == nullptr) { return; } @@ -208,7 +241,7 @@ void S_NoiseDebug (void) listener = players[consoleplayer].camera->SoundPos(); // Display the oldest channel first. - for (chan = Channels; chan->NextChan != NULL; chan = chan->NextChan) + for (chan = ChannelList.Channels(); chan->Next() != NULL; chan = chan->Next()) { } while (y < SCREENHEIGHT - 16) { @@ -290,11 +323,16 @@ void S_NoiseDebug (void) y += NewConsoleFont->GetHeight(); - if (chan->PrevChan == &Channels) +#if 0 + // OMG! This godawful hackery needs to be fixed before this can be reactivated. + if (chan->PrevChan == &ChannelList.Channels()) { break; } chan = (FSoundChan *)((size_t)chan->PrevChan - myoffsetof(FSoundChan, NextChan)); +#else + break; +#endif } } @@ -315,6 +353,7 @@ void S_Init () int curvelump; atterm (S_Shutdown); + if (GSnd) GSnd->Channels = &ChannelList; // Heretic and Hexen have sound curve lookup tables. Doom does not. curvelump = Wads.CheckNumForName ("SNDCURVE"); @@ -329,10 +368,7 @@ void S_Init () } // Free all channels for use. - while (Channels != NULL) - { - S_ReturnChannel(Channels); - } + ChannelList.ReturnAllChannels(); // no sounds are playing, and they are not paused MusicPaused = false; @@ -361,18 +397,12 @@ void S_Shutdown () { FSoundChan *chan, *next; - chan = Channels; - while (chan != NULL) - { - next = chan->NextChan; - S_StopChannel(chan); - chan = next; - } + ChannelList.StopAllChannels(); GSnd->UpdateSounds(); for (chan = FreeChannels; chan != NULL; chan = next) { - next = chan->NextChan; + next = chan->Next(); delete chan; } FreeChannels = NULL; @@ -509,7 +539,7 @@ void S_PrecacheLevel (FLevelLocals *Level) FSoundID(snd).MarkUsed(); } // Don't unload sounds that are playing right now. - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { chan->SoundID.MarkUsed(); } @@ -583,79 +613,6 @@ void S_UnloadSound (sfxinfo_t *sfx) sfx->data3d.Clear(); } -//========================================================================== -// -// S_GetChannel -// -// Returns a free channel for the system sound interface. -// -//========================================================================== - -FISoundChannel *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) -{ - 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 @@ -1135,7 +1092,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO // If this actor is already playing something on the selected channel, stop it. if (type != SOURCE_None && ((actor == NULL && channel != CHAN_AUTO) || (actor != NULL && S_IsChannelUsed(actor, channel, &seen)))) { - for (chan = Channels; chan != NULL; chan = chan->NextChan) + for (chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->SourceType == type && chan->EntChannel == channel) { @@ -1151,7 +1108,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO } if (foundit) { - S_StopChannel(chan); + ChannelList.StopChannel(chan); break; } } @@ -1168,11 +1125,11 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO // Vary the sfx pitches. if (pitchmask != 0) { - pitch = NORM_PITCH - (M_Random() & pitchmask) + (M_Random() & pitchmask); + pitch = FIChannelList::NORM_PITCH - (M_Random() & pitchmask) + (M_Random() & pitchmask); } else { - pitch = NORM_PITCH; + pitch = FIChannelList::NORM_PITCH; } if (chanflags & CHAN_EVICTED) @@ -1201,7 +1158,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO } if (chan == NULL && (chanflags & CHAN_LOOP)) { - chan = (FSoundChan*)S_GetChannel(NULL); + chan = (FSoundChan*)ChannelList.GetChannel(NULL); GSnd->MarkStartTime(chan); chanflags |= CHAN_EVICTED; } @@ -1237,7 +1194,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO } if (spitch > 0.0) - S_SetPitch(chan, spitch); + ChannelList.SetPitch(chan, spitch); return chan; } @@ -1250,7 +1207,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO // //========================================================================== -void S_RestartSound(FSoundChan *chan) +static void S_RestartSound(FSoundChan *chan) { assert(chan->ChanFlags & CHAN_EVICTED); @@ -1617,7 +1574,7 @@ static void S_LoadSound3D(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) bool S_CheckSingular(int sound_id) { - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->OrgID == sound_id) { @@ -1650,7 +1607,7 @@ bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, floa FSoundChan *chan; int count; - for (chan = Channels, count = 0; chan != NULL && count < near_limit; chan = chan->NextChan) + for (chan = ChannelList.Channels(), count = 0; chan != NULL && count < near_limit; chan = chan->Next()) { if (!(chan->ChanFlags & CHAN_EVICTED) && &S_sfx[chan->SoundID] == sfx) { @@ -1682,14 +1639,14 @@ bool S_CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, floa void S_StopSound (int channel) { - FSoundChan *chan = Channels; + FSoundChan *chan = ChannelList.Channels(); while (chan != NULL) { - FSoundChan *next = chan->NextChan; + FSoundChan *next = chan->Next(); if (chan->SourceType == SOURCE_None && (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { - S_StopChannel(chan); + ChannelList.StopChannel(chan); } chan = next; } @@ -1705,15 +1662,15 @@ void S_StopSound (int channel) void S_StopSound (AActor *actor, int channel) { - FSoundChan *chan = Channels; + FSoundChan *chan = ChannelList.Channels(); while (chan != NULL) { - FSoundChan *next = chan->NextChan; + FSoundChan *next = chan->Next(); if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { - S_StopChannel(chan); + ChannelList.StopChannel(chan); } chan = next; } @@ -1729,15 +1686,15 @@ void S_StopSound (AActor *actor, int channel) void S_StopSound (const sector_t *sec, int channel) { - FSoundChan *chan = Channels; + FSoundChan *chan = ChannelList.Channels(); while (chan != NULL) { - FSoundChan *next = chan->NextChan; + FSoundChan *next = chan->Next(); if (chan->SourceType == SOURCE_Sector && chan->Sector == sec && (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { - S_StopChannel(chan); + ChannelList.StopChannel(chan); } chan = next; } @@ -1753,15 +1710,15 @@ void S_StopSound (const sector_t *sec, int channel) void S_StopSound (const FPolyObj *poly, int channel) { - FSoundChan *chan = Channels; + FSoundChan *chan = ChannelList.Channels(); while (chan != NULL) { - FSoundChan *next = chan->NextChan; + FSoundChan *next = chan->Next(); if (chan->SourceType == SOURCE_Polyobj && chan->Poly == poly && (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { - S_StopChannel(chan); + ChannelList.StopChannel(chan); } chan = next; } @@ -1780,13 +1737,8 @@ void S_StopAllChannels () SN_StopAllSequences(Level); } - FSoundChan *chan = Channels; - while (chan != NULL) - { - FSoundChan *next = chan->NextChan; - S_StopChannel(chan); - chan = next; - } + ChannelList.StopAllChannels(); + GSnd->UpdateSounds(); } @@ -1803,10 +1755,10 @@ void S_RelinkSound (AActor *from, AActor *to) if (from == NULL) return; - FSoundChan *chan = Channels; + FSoundChan *chan = ChannelList.Channels(); while (chan != NULL) { - FSoundChan *next = chan->NextChan; + FSoundChan *next = chan->Next(); if (chan->SourceType == SOURCE_Actor && chan->Actor == from) { if (to != NULL) @@ -1824,7 +1776,7 @@ void S_RelinkSound (AActor *from, AActor *to) } else { - S_StopChannel(chan); + ChannelList.StopChannel(chan); } } chan = next; @@ -1847,7 +1799,7 @@ void S_ChangeSoundVolume(AActor *actor, int channel, double dvolume) else if (volume > 1.0) volume = 1.0; - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && @@ -1869,25 +1821,19 @@ void S_ChangeSoundVolume(AActor *actor, int channel, double dvolume) void S_ChangeSoundPitch(AActor *actor, int channel, double pitch) { - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && chan->EntChannel == channel) { - S_SetPitch(chan, (float)pitch); + ChannelList.SetPitch(chan, (float)pitch); return; } } return; } -void S_SetPitch(FSoundChan *chan, float pitch) -{ - GSnd->ChannelPitch(chan, MAX(0.0001f, pitch)); - chan->Pitch = MAX(1, int(float(NORM_PITCH) * pitch)); -} - //========================================================================== // // S_GetSoundPlayingInfo @@ -1899,7 +1845,7 @@ bool S_GetSoundPlayingInfo (const AActor *actor, int sound_id) { if (sound_id > 0) { - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->OrgID == sound_id && chan->SourceType == SOURCE_Actor && @@ -1916,7 +1862,7 @@ bool S_GetSoundPlayingInfo (const sector_t *sec, int sound_id) { if (sound_id > 0) { - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->OrgID == sound_id && chan->SourceType == SOURCE_Sector && @@ -1933,7 +1879,7 @@ bool S_GetSoundPlayingInfo (const FPolyObj *poly, int sound_id) { if (sound_id > 0) { - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->OrgID == sound_id && chan->SourceType == SOURCE_Polyobj && @@ -1962,7 +1908,7 @@ static bool S_IsChannelUsed(AActor *actor, int channel, int *seen) { return true; } - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->SourceType == SOURCE_Actor && chan->Actor == actor) { @@ -1989,7 +1935,7 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) channel = 0; } - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (chan->SourceType == SOURCE_Actor && chan->Actor == actor) { @@ -2105,91 +2051,6 @@ void S_SetSoundPaused (int state) } } -//========================================================================== -// -// S_EvictAllChannels -// -// Forcibly evicts all channels so that there are none playing, but all -// information needed to restart them is retained. -// -//========================================================================== - -void S_EvictAllChannels() -{ - FSoundChan *chan, *next; - - for (chan = Channels; chan != NULL; chan = next) - { - next = chan->NextChan; - - if (!(chan->ChanFlags & CHAN_EVICTED)) - { - chan->ChanFlags |= CHAN_EVICTED; - if (chan->SysChannel != NULL) - { - if (!(chan->ChanFlags & CHAN_ABSTIME)) - { - chan->StartTime = GSnd ? GSnd->GetPosition(chan) : 0; - chan->ChanFlags |= CHAN_ABSTIME; - } - S_StopChannel(chan); - } -// assert(chan->NextChan == next); - } - } -} - -//========================================================================== -// -// S_RestoreEvictedChannel -// -// Recursive helper for S_RestoreEvictedChannels(). -// -//========================================================================== - -void S_RestoreEvictedChannel(FSoundChan *chan) -{ - if (chan == NULL) - { - return; - } - S_RestoreEvictedChannel(chan->NextChan); - if (chan->ChanFlags & CHAN_EVICTED) - { - S_RestartSound(chan); - if (!(chan->ChanFlags & CHAN_LOOP)) - { - if (chan->ChanFlags & CHAN_EVICTED) - { // Still evicted and not looping? Forget about it. - S_ReturnChannel(chan); - } - else if (!(chan->ChanFlags & CHAN_JUSTSTARTED)) - { // Should this sound become evicted again, it's okay to forget about it. - chan->ChanFlags |= CHAN_FORGETTABLE; - } - } - } - else if (chan->SysChannel == NULL && (chan->ChanFlags & (CHAN_FORGETTABLE | CHAN_LOOP)) == CHAN_FORGETTABLE) - { - S_ReturnChannel(chan); - } -} - -//========================================================================== -// -// S_RestoreEvictedChannels -// -// Restarts as many evicted channels as possible. Any channels that could -// not be started and are not looping are moved to the free pool. -// -//========================================================================== - -void S_RestoreEvictedChannels() -{ - // Restart channels in the same order they were originally played. - S_RestoreEvictedChannel(Channels); -} - //========================================================================== // // S_UpdateSounds @@ -2218,7 +2079,7 @@ void S_UpdateSounds (AActor *listenactor) // should never happen S_SetListener(listener, listenactor); - for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + for (FSoundChan *chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if ((chan->ChanFlags & (CHAN_EVICTED | CHAN_IS3D)) == CHAN_IS3D) { @@ -2243,7 +2104,7 @@ void S_UpdateSounds (AActor *listenactor) if (primaryLevel->time >= RestartEvictionsAt) { RestartEvictionsAt = 0; - S_RestoreEvictedChannels(); + ChannelList.RestoreEvictedChannels(); } } @@ -2282,163 +2143,6 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor) } - -//========================================================================== -// -// S_GetRolloff -// -//========================================================================== - -float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic) -{ - if (rolloff == NULL) - { - return 0; - } - - if (distance <= rolloff->MinDistance) - { - return 1; - } - if (rolloff->RolloffType == ROLLOFF_Log) - { // Logarithmic rolloff has no max distance where it goes silent. - return rolloff->MinDistance / (rolloff->MinDistance + rolloff->RolloffFactor * (distance - rolloff->MinDistance)); - } - if (distance >= rolloff->MaxDistance) - { - return 0; - } - - float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); - if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0) - { - volume = S_SoundCurve[int(S_SoundCurve.Size() * (1 - volume))] / 127.f; - } - if (logarithmic) - { - if (rolloff->RolloffType == ROLLOFF_Linear) - { - return volume; - } - else - { - return float((powf(10.f, volume) - 1.) / 9.); - } - } - else - { - if (rolloff->RolloffType == ROLLOFF_Linear) - { - return float(log10(9. * volume + 1.)); - } - else - { - return volume; - } - } -} - - -//========================================================================== -// -// S_ChannelEnded (callback for sound interface code) -// -//========================================================================== - -void S_ChannelEnded(FISoundChannel *ichan) -{ - FSoundChan *schan = static_cast(ichan); - bool evicted; - - if (schan != NULL) - { - // If the sound was stopped with GSnd->StopSound(), then we know - // it wasn't evicted. Otherwise, if it's looping, it must have - // been evicted. If it's not looping, then it was evicted if it - // didn't reach the end of its playback. - if (schan->ChanFlags & CHAN_FORGETTABLE) - { - evicted = false; - } - else if (schan->ChanFlags & (CHAN_LOOP | CHAN_EVICTED)) - { - evicted = true; - } - else - { - unsigned int pos = GSnd->GetPosition(schan); - unsigned int len = GSnd->GetSampleLength(S_sfx[schan->SoundID].data); - if (pos == 0) - { - evicted = !!(schan->ChanFlags & CHAN_JUSTSTARTED); - } - else - { - evicted = (pos < len); - } - } - if (!evicted) - { - S_ReturnChannel(schan); - } - else - { - schan->ChanFlags |= CHAN_EVICTED; - schan->SysChannel = NULL; - } - } -} - -//========================================================================== -// -// S_ChannelVirtualChanged (callback for sound interface code) -// -//========================================================================== - -void S_ChannelVirtualChanged(FISoundChannel *ichan, bool is_virtual) -{ - FSoundChan *schan = static_cast(ichan); - if (is_virtual) - { - schan->ChanFlags |= CHAN_VIRTUAL; - } - else - { - schan->ChanFlags &= ~CHAN_VIRTUAL; - } -} - -//========================================================================== -// -// S_StopChannel -// -//========================================================================== - -void S_StopChannel(FSoundChan *chan) -{ - if (chan == NULL) - return; - - if (chan->SysChannel != NULL) - { - // S_EvictAllChannels() will set the CHAN_EVICTED flag to indicate - // that it wants to keep all the channel information around. - if (!(chan->ChanFlags & CHAN_EVICTED)) - { - chan->ChanFlags |= CHAN_FORGETTABLE; - if (chan->SourceType == SOURCE_Actor) - { - chan->Actor = NULL; - } - } - GSnd->StopChannel(chan); - } - else - { - S_ReturnChannel(chan); - } -} - //========================================================================== // // @@ -2498,7 +2202,7 @@ void S_SerializeSounds(FSerializer &arc) // Count channels and accumulate them so we can store them in // reverse order. That way, they will be in the same order when // reloaded later as they are now. - for (chan = Channels; chan != NULL; chan = chan->NextChan) + for (chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { // If the sound is forgettable, this is as good a time as // any to forget about it. And if it's a UI sound, it shouldn't @@ -2531,7 +2235,7 @@ void S_SerializeSounds(FSerializer &arc) count = arc.ArraySize(); for (unsigned int i = 0; i < count; ++i) { - chan = (FSoundChan*)S_GetChannel(NULL); + chan = static_cast(ChannelList.GetChannel(NULL)); arc(nullptr, *chan); // Sounds always start out evicted when restored from a save. chan->ChanFlags |= CHAN_EVICTED | CHAN_ABSTIME; @@ -3250,7 +2954,7 @@ CCMD(listsoundchannels) { FSoundChan *chan; int count = 0; - for (chan = Channels; chan != NULL; chan = chan->NextChan) + for (chan = ChannelList.Channels(); chan != NULL; chan = chan->Next()) { if (!(chan->ChanFlags & CHAN_EVICTED)) { diff --git a/src/sound/s_sound.h b/src/sound/s_sound.h index 795a8b338f4..a44f37fdbe6 100644 --- a/src/sound/s_sound.h +++ b/src/sound/s_sound.h @@ -30,6 +30,7 @@ #include "doomtype.h" #include "i_soundinternal.h" +#include "i_channellist.h" class AActor; class FScanner; @@ -174,14 +175,10 @@ struct sector_t; struct FPolyObj; struct FSoundChan : public FISoundChannel { - FSoundChan *NextChan; // Next channel in this list. - FSoundChan **PrevChan; // Previous channel in this list. + FSoundID SoundID; // Sound ID of playing sound. 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. - int8_t Priority; int16_t NearLimit; uint8_t SourceType; float LimitRange; @@ -192,17 +189,13 @@ struct FSoundChan : public FISoundChannel const FPolyObj *Poly; // Polyobject sound source. float Point[3]; // Sound is not attached to any source. }; + + FSoundChan *Next() const + { + return static_cast(NextChan); + } }; -extern FSoundChan *Channels; - -void S_ReturnChannel(FSoundChan *chan); -void S_EvictAllChannels(); - -void S_StopChannel(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. @@ -260,25 +253,11 @@ void S_PlaySoundPitch(AActor *a, int chan, FSoundID sid, float vol, float atten, #define CHAN_CEILING 2 // Sound comes from the ceiling. #define CHAN_FULLHEIGHT 3 // Sound comes entire height of the sector. #define CHAN_INTERIOR 4 // Sound comes height between floor and ceiling. +#define CHAN_NOSTOP 4096// only for A_PlaySound. Does not start if channel is playing something. -// modifier flags -#define CHAN_LISTENERZ 8 -#define CHAN_MAYBE_LOCAL 16 -#define CHAN_UI 32 // Do not record sound in savegames. -#define CHAN_NOPAUSE 64 // Do not pause this sound in menus. -#define CHAN_AREA 128 // Sound plays from all around. Only valid with sector sounds. -#define CHAN_LOOP 256 - + #define CHAN_PICKUP (CHAN_ITEM|CHAN_MAYBE_LOCAL) -#define CHAN_IS3D 1 // internal: Sound is 3D. -#define CHAN_EVICTED 2 // internal: Sound was evicted. -#define CHAN_FORGETTABLE 4 // internal: Forget channel data when sound stops. -#define CHAN_JUSTSTARTED 512 // internal: Sound has not been updated yet. -#define CHAN_ABSTIME 1024// internal: Start time is absolute and does not depend on current time. -#define CHAN_VIRTUAL 2048// internal: Channel is currently virtual -#define CHAN_NOSTOP 4096// only for A_PlaySound. Does not start if channel is playing something. - // sound attenuation values #define ATTN_NONE 0.f // full volume the entire level #define ATTN_NORM 1.f @@ -315,7 +294,6 @@ void S_ChangeSoundVolume(AActor *actor, int channel, double volume); // Change a playing sound's pitch void S_ChangeSoundPitch(AActor *actor, int channel, double pitch); -void S_SetPitch(FSoundChan *chan, float dpitch); // Moves all sounds from one mobj to another void S_RelinkSound (AActor *from, AActor *to); @@ -351,8 +329,6 @@ void S_SetSoundPaused (int state); // void S_UpdateSounds (AActor *listener); -void S_RestoreEvictedChannels(); - // [RH] S_sfx "maintenance" routines void S_ParseSndInfo (bool redefine); void S_ParseReverbDef ();