ISource2ModSounds

Interface for playing, stopping and rewriting sound events.

A sound event reaches a client as one network message (CMsgSosStartSoundEvent): the hash of its name, the entity it plays from, a guid and a packed block of parameters. This interface builds and sends that message itself instead of going through an entity on the server, which is what makes the rest possible:

  • a sound goes to exactly the players you pick -- nobody else receives it, so there is nothing for them to hear;
  • Emit() hands back the guid, and the guid stops the sound at once or changes its parameters while it plays;
  • volume channels: a player's own volume for "music", "effects" or whatever a plugin names is applied per recipient, so a player turns the server's music down in a menu instead of fighting snd_musicvolume;
  • every sound the game itself starts passes through HookSound(), where it can be blocked, renamed, re-parametrised or re-addressed.
Everything here belongs on the main thread.

Interface id ISource2ModSounds002 (SOURCE2MOD_SOUNDS_INTERFACE) · Global g_pSource2ModSounds · Header source2mod/ISource2ModSounds.h

Types

Source2ModSoundHookId

using Source2ModSoundHookId = Source2ModHookId;

A sound hook (HookSound).

SoundGuid

using SoundGuid = uint32_t;

Identifies one playing sound on the clients it was sent to.

Taken from the engine's own counter, so it never collides with a sound the game started. 0 means "nothing was sent".

SoundRecipients

using SoundRecipients = uint64_t;

Recipient set, one bit per player slot (bit N = slot N).

SoundHook

using SoundHook = Source2ModCallback<Action(ISource2ModSound* sound)>;

Hook called for every sound the game is about to send to clients.

Sounds sent through this interface do not come back through the hook.

The server only knows about the sounds it sends. What a client predicts for itself -- its own weapon fire, its own knife swing, its own footsteps -- is played locally and never passes through here; the copy of those sounds that goes to everybody else does.

Methods

CreateSound

virtual ISource2ModSound* CreateSound(PluginId owner, const char* name = nullptr) = 0;

Creates a sound: listener-sourced, volume and pitch 1, no recipients.

ISource2ModSound::New() is the usual way in. Release with delete or DestroySound(); whatever a plugin leaves behind goes when it unloads.

ParameterTypeDefaultDescription
ownerPluginIdPlugin ID that owns the sound
nameconst char*nullptrSound event name, may be set later

DestroySound

virtual void DestroySound(ISource2ModSound* sound) = 0;
ParameterType
soundISource2ModSound*

EmitSoundToPlayer

virtual SoundGuid EmitSoundToPlayer(CPlayerSlot slot, const char* name, float volume = 1.0f, float pitch = 1.0f, const char* channel = nullptr) = 0;

Plays a sound for one player only, at the listener.

ParameterTypeDefault
slotCPlayerSlot
nameconst char*
volumefloat1.0f
pitchfloat1.0f
channelconst char*nullptr

EmitSoundToPlayers

virtual SoundGuid EmitSoundToPlayers(SoundRecipients recipients, const char* name, float volume = 1.0f, float pitch = 1.0f, const char* channel = nullptr) = 0;

Plays a sound for a set of players, at each listener.

ParameterTypeDefault
recipientsSoundRecipients
nameconst char*
volumefloat1.0f
pitchfloat1.0f
channelconst char*nullptr

EmitSoundToAll

virtual SoundGuid EmitSoundToAll(const char* name, float volume = 1.0f, float pitch = 1.0f, const char* channel = nullptr) = 0;

Plays a sound for everybody, at each listener.

ParameterTypeDefault
nameconst char*
volumefloat1.0f
pitchfloat1.0f
channelconst char*nullptr

EmitSoundFromEntity

virtual SoundGuid EmitSoundFromEntity(CEntityInstance* entity, const char* name, float volume = 1.0f, float pitch = 1.0f, SoundRecipients recipients = ~SoundRecipients(0), const char* channel = nullptr) = 0;

Plays a sound from an entity, for @p recipients (everybody by default).

ParameterTypeDefault
entityCEntityInstance*
nameconst char*
volumefloat1.0f
pitchfloat1.0f
recipientsSoundRecipients~SoundRecipients(0)
channelconst char*nullptr

StopSound

virtual void StopSound(SoundGuid guid) = 0;

Stops a sound at once, for everybody it was sent to.

ParameterType
guidSoundGuid

StopSoundForPlayers

virtual void StopSoundForPlayers(SoundGuid guid, SoundRecipients recipients) = 0;

Stops a sound for some of its recipients; it keeps playing for the rest.

ParameterType
guidSoundGuid
recipientsSoundRecipients

StopSoundByName

virtual void StopSoundByName(const char* name, int sourceEntityIndex = SOUND_SOURCE_LISTENER, SoundRecipients recipients = ~SoundRecipients(0)) = 0;

Stops a sound by name, including one the game started.

ParameterTypeDefaultDescription
nameconst char*Sound event name
sourceEntityIndexintSOUND_SOURCE_LISTENEREntity the sound plays from, SOUND_SOURCE_LISTENER for sounds without one
recipientsSoundRecipients~SoundRecipients(0)Who to stop it for, everybody by default

SetSoundVolume

virtual void SetSoundVolume(SoundGuid guid, float volume) = 0;

Changes the volume of a playing sound. Channel volumes still apply.

ParameterType
guidSoundGuid
volumefloat

UpdateSoundParams

virtual void UpdateSoundParams(SoundGuid guid, const ISource2ModSound* params, SoundRecipients recipients = SOUND_RECIPIENTS_NONE) = 0;

Sends the parameters of @p params to a playing sound.

Only the parameters set on @p params are sent; its name, source and recipients are ignored.

ParameterTypeDefaultDescription
guidSoundGuid
paramsconst ISource2ModSound*
recipientsSoundRecipientsSOUND_RECIPIENTS_NONEWho to send to, 0 for everybody the sound went to

SetPlayerVolume

virtual void SetPlayerVolume(CPlayerSlot slot, const char* channel, float volume) = 0;

Sets one player's volume for a channel (0 mutes, 1 is unchanged).

A channel is just a name sounds are emitted under ("music", "effects", ...). Applies to every later sound on the channel, and straight away to the ones this player is still hearing: they get louder, quieter, or stop. Forgotten when the player disconnects -- Source2Mod keeps nothing on disk, load it from wherever the plugin stores preferences.

ParameterType
slotCPlayerSlot
channelconst char*
volumefloat

GetPlayerVolume

virtual float GetPlayerVolume(CPlayerSlot slot, const char* channel) = 0;

A player's volume for a channel, 1.0 when never set.

ParameterType
slotCPlayerSlot
channelconst char*

ResetPlayerVolumes

virtual void ResetPlayerVolumes(CPlayerSlot slot) = 0;

Puts all of a player's channels back to 1.0.

ParameterType
slotCPlayerSlot

HashSoundName

virtual uint32_t HashSoundName(const char* name) = 0;

Hash a sound event name travels as, for matching a hooked sound:

static const uint32_t knifeHit = g_pSource2ModSounds->HashSoundName("Weapon_Knife.Hit"); if (sound->GetNameHash() == knifeHit) ...

The name is remembered, so ISource2ModSound::GetName() and LookupSoundName() resolve it from then on.

ParameterType
nameconst char*

LookupSoundName

virtual const char* LookupSoundName(uint32_t hash) = 0;

Name for a hash, nullptr when Source2Mod has not seen it.

ParameterType
hashuint32_t

HookSound

virtual Source2ModSoundHookId HookSound(SoundHook handler) = 0;

Hooks the sounds the game sends to clients.

A plugin may hook as often as it likes; each handler runs.

Whose it is, the core reads off the handler (see Source2ModCallback); what a plugin still holds at unload the core drops for it.

ParameterTypeDescription
handlerSoundHookA function, an object and a method, or a lambda

Returns Source2ModSoundHookId — The id UnhookSound(id) takes

UnhookSound

virtual bool UnhookSound(const SoundHook& handler) = 0;
virtual bool UnhookSound(Source2ModSoundHookId id) = 0;

Drops the hook with this handler -- a function or an object and a method; a lambda goes by its id.

Drops the hook HookSound() returned the id for.

Returns bool — true when one was found

ISource2ModSound

One sound event: what to play, from where, how, and for whom.

Made with ISource2ModSound::New(), released with delete, and reusable in between -- Emit() may be called any number of times, each call is a new sound with a new guid. The same type is what a HookSound() handler receives for a sound the game is about to send.

Parameter names are the sound event's public fields ("public.volume", "public.pitch", "public.position", or whatever a custom .vsndevts declares). They travel as hashes, so a name cannot be listed back, only asked for.

SetName

virtual void SetName(const char* name) = 0;

Sets the sound event to play, e.g. "Weapon_AK47.Single".

ParameterType
nameconst char*

GetName

virtual const char* GetName() const = 0;

Sound event name, or "" when only its hash is known.

A hooked game sound arrives as a hash, and a hash cannot be turned back into a name. Source2Mod resolves it against the names it has been given so far -- everything emitted through this interface and everything passed to ISource2ModSounds::HashSoundName() -- so the sounds a plugin looks for come out named, the rest as "".

SetNameHash

virtual void SetNameHash(uint32_t hash) = 0;
ParameterType
hashuint32_t

GetNameHash

virtual uint32_t GetNameHash() const = 0;

GetGuid

virtual SoundGuid GetGuid() const = 0;

Guid of the sound. Assigned by the engine for a hooked sound, by the last Emit() otherwise (0 before the first one).

SetSourceEntityIndex

virtual void SetSourceEntityIndex(int index) = 0;

Entity index the sound plays from and follows, or SOUND_SOURCE_LISTENER (default) / SOUND_SOURCE_WORLD.

ParameterType
indexint

GetSourceEntityIndex

virtual int GetSourceEntityIndex() const = 0;

SetSourceEntity

virtual void SetSourceEntity(CEntityInstance* entity) = 0;

Plays the sound from an entity. nullptr is SOUND_SOURCE_LISTENER.

ParameterType
entityCEntityInstance*

SetPosition

virtual void SetPosition(const Vector& position) = 0;

Plays the sound at a point in the world: SOUND_SOURCE_WORLD plus "public.position".

ParameterType
positionconst Vector&

SetVolume

virtual void SetVolume(float volume) = 0;

"public.volume". 1.0 is the sound event's own volume.

With a channel set, each recipient gets this multiplied by their own volume for that channel.

ParameterType
volumefloat

GetVolume

virtual float GetVolume() const = 0;

SetPitch

virtual void SetPitch(float pitch) = 0;

"public.pitch". 1.0 is unchanged.

ParameterType
pitchfloat

GetPitch

virtual float GetPitch() const = 0;

SetChannel

virtual void SetChannel(const char* channel) = 0;

Volume channel this sound belongs to, or nullptr/"" for none.

See ISource2ModSounds::SetPlayerVolume(). A recipient whose volume for the channel is 0 is not sent the sound at all.

ParameterType
channelconst char*

GetChannel

virtual const char* GetChannel() const = 0;

HasParam

virtual bool HasParam(const char* name) const = 0;
ParameterType
nameconst char*

GetParamType

virtual SoundParamType GetParamType(const char* name) const = 0;
ParameterType
nameconst char*

RemoveParam

virtual void RemoveParam(const char* name) = 0;
ParameterType
nameconst char*

ClearParams

virtual void ClearParams() = 0;

SetBool

virtual void SetBool(const char* name, bool value) = 0;
ParameterType
nameconst char*
valuebool

SetInt32

virtual void SetInt32(const char* name, int32_t value) = 0;
ParameterType
nameconst char*
valueint32_t

SetUInt32

virtual void SetUInt32(const char* name, uint32_t value) = 0;
ParameterType
nameconst char*
valueuint32_t

SetUInt64

virtual void SetUInt64(const char* name, uint64_t value) = 0;
ParameterType
nameconst char*
valueuint64_t

SetFloat

virtual void SetFloat(const char* name, float value) = 0;
ParameterType
nameconst char*
valuefloat

SetFloat3

virtual void SetFloat3(const char* name, const Vector& value) = 0;
ParameterType
nameconst char*
valueconst Vector&

GetBool

virtual bool GetBool(const char* name, bool def = false) const = 0;

Typed getters. @p def comes back when the parameter is missing or of another type.

ParameterTypeDefault
nameconst char*
defboolfalse

GetInt32

virtual int32_t GetInt32(const char* name, int32_t def = 0) const = 0;
ParameterTypeDefault
nameconst char*
defint32_t0

GetUInt32

virtual uint32_t GetUInt32(const char* name, uint32_t def = 0) const = 0;
ParameterTypeDefault
nameconst char*
defuint32_t0

GetUInt64

virtual uint64_t GetUInt64(const char* name, uint64_t def = 0) const = 0;
ParameterTypeDefault
nameconst char*
defuint64_t0

GetFloat

virtual float GetFloat(const char* name, float def = 0.0f) const = 0;
ParameterTypeDefault
nameconst char*
deffloat0.0f

GetFloat3

virtual Vector GetFloat3(const char* name, const Vector& def = Vector(0, 0, 0)) const = 0;
ParameterTypeDefault
nameconst char*
defconst Vector&Vector(0, 0, 0)

AddRecipient

virtual void AddRecipient(CPlayerSlot slot) = 0;
ParameterType
slotCPlayerSlot

RemoveRecipient

virtual void RemoveRecipient(CPlayerSlot slot) = 0;
ParameterType
slotCPlayerSlot

HasRecipient

virtual bool HasRecipient(CPlayerSlot slot) const = 0;
ParameterType
slotCPlayerSlot

AddAllRecipients

virtual void AddAllRecipients() = 0;

Every player connected at the moment of the call -- the ones with a net channel, so bots are left out (a sound cannot reach them).

ClearRecipients

virtual void ClearRecipients() = 0;

SetRecipients

virtual void SetRecipients(SoundRecipients mask) = 0;
ParameterType
maskSoundRecipients

GetRecipients

virtual SoundRecipients GetRecipients() const = 0;

Recipient set, one bit per player slot (bit N = slot N).

Emit

virtual SoundGuid Emit() = 0;

Sends the sound to its recipients.

Not available inside a HookSound() handler -- the sound there is already on its way; change it and return Action::Override.

Returns SoundGuid — Guid of the new sound, 0 when there was nobody to send it to.

New

static ISource2ModSound* New(const char* name = nullptr);

Creates a sound: listener-sourced, volume and pitch 1, no recipients.

Equivalent to g_pSource2ModSounds->CreateSound(g_PluginID, name). Release with delete or g_pSource2ModSounds->DestroySound().

ISource2ModSound* music = ISource2ModSound::New("jb.duel"); music->SetChannel("music"); music->AddAllRecipients(); SoundGuid guid = music->Emit(); delete music;

ParameterTypeDefaultDescription
nameconst char*nullptrSound event name, may be set later with SetName().

Enums

SoundParamType

enum class SoundParamType : uint8_t

Wire type of a packed sound parameter.

The engine knows more than these; they are the ones whose layout is known, and every public parameter of the stock sound events is one of them. Parameters of any other type on a hooked sound are carried through untouched.

NameValue
Invalid0
Bool1
Int322
UInt323
UInt644
Float8
Float310

Functions

SoundRecipientOf

inline SoundRecipients SoundRecipientOf(CPlayerSlot slot);

Recipient mask of one slot.

ParameterType
slotCPlayerSlot

Macros

SOUND_EMIT_TO_PLAYER

#define SOUND_EMIT_TO_PLAYER(slot, ...) g_pSource2ModSounds->EmitSoundToPlayer(slot, __VA_ARGS__)

Shorthand accessors via g_pSource2ModSounds.

Other macros

MacroExpands to
SOUND_EMIT_TO_PLAYERS(mask, ...)g_pSource2ModSounds->EmitSoundToPlayers(mask, __VA_ARGS__)
SOUND_EMIT_TO_ALL(...)g_pSource2ModSounds->EmitSoundToAll(__VA_ARGS__)
SOUND_EMIT_FROM_ENTITY(entity, ...)g_pSource2ModSounds->EmitSoundFromEntity(entity, __VA_ARGS__)
SOUND_STOP(guid)g_pSource2ModSounds->StopSound(guid)
HOOK_SOUND(handler)g_pSource2ModSounds->HookSound(handler)
UNHOOK_SOUND(handler)g_pSource2ModSounds->UnhookSound(handler)

On this page