//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //===========================================================================// #ifndef ISOUNDEMITTERSYSTEMBASE_H #define ISOUNDEMITTERSYSTEMBASE_H #ifdef _WIN32 #pragma once #endif #include "appframework/IAppSystem.h" #include "mathlib/compressed_vector.h" #include "soundflags.h" #include "tier1/utldict.h" #include "vstdlib/random.h" #define SOUNDEMITTERSYSTEM_INTERFACE_VERSION "VSoundEmitter002" #define SOUNDGENDER_MACRO "$gender" #define SOUNDGENDER_MACRO_LENGTH 7 // Length of above including $ typedef short HSOUNDSCRIPTHANDLE; #define SOUNDEMITTER_INVALID_HANDLE (HSOUNDSCRIPTHANDLE) - 1 class IFileList; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- struct CSoundParameters { CSoundParameters() { channel = CHAN_AUTO; // 0 volume = VOL_NORM; // 1.0f pitch = PITCH_NORM; // 100 pitchlow = PITCH_NORM; pitchhigh = PITCH_NORM; soundlevel = SNDLVL_NORM; // 75dB soundname[0] = 0; play_to_owner_only = false; count = 0; delay_msec = 0; } int channel; float volume; int pitch; int pitchlow, pitchhigh; soundlevel_t soundlevel; // For weapon sounds... bool play_to_owner_only; int count; char soundname[128]; int delay_msec; }; // A bit of a hack, but these are just utility function which are implemented in // the SouneParametersInternal.cpp file which all users of this lib also compile const char *SoundLevelToString(soundlevel_t level); const char *ChannelToString(int channel); const char *VolumeToString(float volume); const char *PitchToString(float pitch); soundlevel_t TextToSoundLevel(const char *key); int TextToChannel(const char *name); enum gender_t { GENDER_NONE = 0, GENDER_MALE, GENDER_FEMALE, }; #pragma pack(1) struct SoundFile { SoundFile() { symbol = UTL_INVAL_SYMBOL; gender = GENDER_NONE; available = true; COMPILE_TIME_ASSERT(sizeof(SoundFile) == 4); } CUtlSymbol symbol; byte gender; byte available; }; #pragma pack() #pragma pack(1) template struct sound_interval_t { T start; T range; interval_t &ToInterval(interval_t &dest) const { dest.start = start; dest.range = range; return dest; } void FromInterval(const interval_t &from) { start = from.start; range = from.range; } float Random() const { return RandomFloat(start, start + range); } }; #pragma pack() typedef sound_interval_t volume_interval_t; typedef sound_interval_t soundlevel_interval_t; typedef sound_interval_t pitch_interval_t; #pragma pack(1) struct CSoundParametersInternal { CSoundParametersInternal(); ~CSoundParametersInternal(); void CopyFrom(const CSoundParametersInternal &src); bool operator==(const CSoundParametersInternal &other) const; const char *VolumeToString(void) const; const char *ChannelToString(void) const; const char *SoundLevelToString(void) const; const char *PitchToString(void) const; void VolumeFromString(const char *sz); void ChannelFromString(const char *sz); void PitchFromString(const char *sz); void SoundLevelFromString(const char *sz); int GetChannel() const { return channel; } const volume_interval_t &GetVolume() const { return volume; } const pitch_interval_t &GetPitch() const { return pitch; } const soundlevel_interval_t &GetSoundLevel() const { return soundlevel; } int GetDelayMsec() const { return delay_msec; } bool OnlyPlayToOwner() const { return play_to_owner_only; } bool HadMissingWaveFiles() const { return had_missing_wave_files; } bool UsesGenderToken() const { return uses_gender_token; } bool ShouldPreload() const { return m_bShouldPreload; } void SetChannel(int newChannel) { channel = newChannel; } void SetVolume(float start, float range = 0.0) { volume.start = start; volume.range = range; } void SetPitch(float start, float range = 0.0) { pitch.start = start; pitch.range = range; } void SetSoundLevel(float start, float range = 0.0) { soundlevel.start = start; soundlevel.range = range; } void SetDelayMsec(int delay) { delay_msec = delay; } void SetShouldPreload(bool bShouldPreload) { m_bShouldPreload = bShouldPreload; } void SetOnlyPlayToOwner(bool b) { play_to_owner_only = b; } void SetHadMissingWaveFiles(bool b) { had_missing_wave_files = b; } void SetUsesGenderToken(bool b) { uses_gender_token = b; } void AddSoundName(const SoundFile &soundFile) { AddToTail(&m_pSoundNames, &m_nSoundNames, soundFile); } int NumSoundNames() const { return m_nSoundNames; } SoundFile *GetSoundNames() { return (m_nSoundNames == 1) ? (SoundFile *)&m_pSoundNames : m_pSoundNames; } const SoundFile *GetSoundNames() const { return (m_nSoundNames == 1) ? (SoundFile *)&m_pSoundNames : m_pSoundNames; } void AddConvertedName(const SoundFile &soundFile) { AddToTail(&m_pConvertedNames, &m_nConvertedNames, soundFile); } int NumConvertedNames() const { return m_nConvertedNames; } SoundFile *GetConvertedNames() { return (m_nConvertedNames == 1) ? (SoundFile *)&m_pConvertedNames : m_pConvertedNames; } const SoundFile *GetConvertedNames() const { return (m_nConvertedNames == 1) ? (SoundFile *)&m_pConvertedNames : m_pConvertedNames; } private: void operator=( const CSoundParametersInternal &src); // disallow implicit copies CSoundParametersInternal(const CSoundParametersInternal &src); void AddToTail(SoundFile **pDest, uint16 *pDestCount, const SoundFile &source); SoundFile *m_pSoundNames; // 4 SoundFile *m_pConvertedNames; // 8 uint16 m_nSoundNames; // 10 uint16 m_nConvertedNames; // 12 volume_interval_t volume; // 16 soundlevel_interval_t soundlevel; // 20 pitch_interval_t pitch; // 22 uint16 channel; // 24 uint16 delay_msec; // 26 bool play_to_owner_only : 1; // For weapon sounds... // 27 // Internal use, for warning about missing .wav files bool had_missing_wave_files : 1; bool uses_gender_token : 1; bool m_bShouldPreload : 1; byte reserved; // 28 }; #pragma pack() //----------------------------------------------------------------------------- // Purpose: Base class for sound emitter system handling (can be used by tools) //----------------------------------------------------------------------------- abstract_class ISoundEmitterSystemBase : public IAppSystem { public: // Init, shutdown called after we know what mod is running virtual bool ModInit() = 0; virtual void ModShutdown() = 0; virtual int GetSoundIndex(const char *pName) const = 0; virtual bool IsValidIndex(int index) = 0; virtual int GetSoundCount(void) = 0; virtual const char *GetSoundName(int index) = 0; virtual bool GetParametersForSound( const char *soundname, CSoundParameters ¶ms, gender_t gender, bool isbeingemitted = false) = 0; virtual const char *GetWaveName(CUtlSymbol & sym) = 0; virtual CUtlSymbol AddWaveName(const char *name) = 0; virtual soundlevel_t LookupSoundLevel(const char *soundname) = 0; virtual const char *GetWavFileForSound(const char *soundname, char const *actormodel) = 0; virtual const char *GetWavFileForSound(const char *soundname, gender_t gender) = 0; virtual int CheckForMissingWavFiles(bool verbose) = 0; virtual const char *GetSourceFileForSound(int index) const = 0; // Iteration methods virtual int First() const = 0; virtual int Next(int i) const = 0; virtual int InvalidIndex() const = 0; virtual CSoundParametersInternal *InternalGetParametersForSound( int index) = 0; // The host application is responsible for dealing with dirty sound scripts, // etc. virtual bool AddSound(const char *soundname, const char *scriptfile, const CSoundParametersInternal ¶ms) = 0; virtual void RemoveSound(const char *soundname) = 0; virtual void MoveSound(const char *soundname, const char *newscript) = 0; virtual void RenameSound(const char *soundname, const char *newname) = 0; virtual void UpdateSoundParameters( const char *soundname, const CSoundParametersInternal ¶ms) = 0; virtual int GetNumSoundScripts() const = 0; virtual char const *GetSoundScriptName(int index) const = 0; virtual bool IsSoundScriptDirty(int index) const = 0; virtual int FindSoundScript(const char *name) const = 0; virtual void SaveChangesToSoundScript(int scriptindex) = 0; virtual void ExpandSoundNameMacros(CSoundParametersInternal & params, char const *wavename) = 0; virtual gender_t GetActorGender(char const *actormodel) = 0; virtual void GenderExpandString(char const *actormodel, char const *in, char *out, int maxlen) = 0; virtual void GenderExpandString(gender_t gender, char const *in, char *out, int maxlen) = 0; virtual bool IsUsingGenderToken(char const *soundname) = 0; // For blowing away caches based on filetimstamps of the manifest, or of any // of the // .txt files that are read into the sound emitter system virtual unsigned int GetManifestFileTimeChecksum() = 0; // Called from both client and server (single player) or just one (server // only in dedicated server and client only if connected to a remote server) // Called by LevelInitPreEntity to override sound scripts for the mod with // level specific overrides based on custom mapnames, etc. virtual void AddSoundOverrides(char const *scriptfile, bool bPreload = false) = 0; // Called by either client or server in LevelShutdown to clear out custom // overrides virtual void ClearSoundOverrides() = 0; virtual bool GetParametersForSoundEx( const char *soundname, HSOUNDSCRIPTHANDLE &handle, CSoundParameters ¶ms, gender_t gender, bool isbeingemitted = false) = 0; virtual soundlevel_t LookupSoundLevelByHandle( char const *soundname, HSOUNDSCRIPTHANDLE &handle) = 0; virtual void ReloadSoundEntriesInList(IFileList * pFilesToReload) = 0; // Called by either client or server to force ModShutdown and ModInit virtual void Flush() = 0; }; #endif // ISOUNDEMITTERSYSTEMBASE_H