• 💀 Happy Halloween! 💀 It's time to vote for the best terrain! Check out the entries to Hive's HD Terrain Contest #2 - Vampire Folklore.❗️Poll closes on November 14, 2023. 🔗Click here to cast your vote!
  • 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 HD Level Design Contest #1 is OPEN! Contestants must create a maze with at least one entry point, and at least one exit point. The map should be made in HD mode, and should not be openable in SD. Only custom models from Hive's HD model and texture sections are allowed. The only exceptions are DNC models and omnilights. This is mainly a visual and design oriented contest, not technical. The UI and video walkthrough rules are there to give everyone an equal shot at victory by standardizing how viewers see the terrain. 🔗Click here to enter!

Quirks of sounds

Not open for further replies.
Level 26
Aug 18, 2009
Now and then, sounds in Wc3 keep raising problems for me. Sometimes they work, sometimes not, sometimes not on the first play or you need other settings in sound options ingame. That is because of the different formats of the sound files and whether they are set up as 3D. Additionally, there are natives and settings, which of I do not know their meaning. That is why I would like to solve these riddles and compile an overview. I am aware of the existence of the SoundUtils library, though it does not deal with everything either, yet alone explains it. Maybe sounds would get more significance/customization in the future.

Jass functions:
native NewSoundEnvironment takes string environmentName returns nothing
-->from UI\Sounds\EnvironmentSounds.slk, as far as I have understood/guessed from the property names, they influence the (3D-)sounds by reverb, damping and such, no idea whether you can actually exchange the sound environment ingame, more below

native CreateSound takes string fileName, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string eaxSetting returns sound

-->allocates a new sound handle
fileName: path of the file
looping: repeats the play again and again when started, until you finally stop the sound again/destroy it
is3D: if used as 3D-sound, e.g. needs a position then to play and depends on the player's position whether how there is something audible
stopwhenoutofrange: sounds have a cutoff-distance, afaik this ends the sound when the player gets too far away, should be only for 3D-sounds
fadeInRate: how fast it fades to the volume at beginning of play, range is 0 to 127, whereas 127 should be instant but I believe there is a min limit, else it would not be hearable with a rate of 0 at all, nor was 1 as slow
fadeOutRate: how fast volume fades out
eaxSetting: there are different eax settings (see below)

native CreateSoundFilenameWithLabel takes string fileName, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate, string SLKEntryName returns sound

-->same as CreateSound but applies default options from UI\SoundInfo\AbilitySounds.slk, AmbienceSounds.slk, AnimSounds.slk, DialogSounds.slk, UISounds.slk, UnitAckSounds.slk or UnitCombatSounds.slk
SLKEntryName: the label out of one of the SLK-files, whose settings should be used, e.g. values like volume, pitch, pitch variance, priority, channel, min distance, max distance, distance cutoff or eax. That is why you do not need to set an eax on this constructor

native CreateSoundFromLabel takes string soundLabel, boolean looping, boolean is3D, boolean stopwhenoutofrange, integer fadeInRate, integer fadeOutRate returns sound

-->same as CreateSoundFilenameWithLabel, only that you do not need to specify a file path because these labels in the SLK actually also hold an array of paths, so the first or a random one of these should be chosen

native CreateMIDISound takes string soundLabel, integer fadeInRate, integer fadeOutRate returns sound

-->another SLK UI\SoundInfo\MIDISounds.slk, no 3D sound flag here, so guess cannot be used for such, the day/night ambients are midis

native SetSoundParamsFromLabel takes sound soundHandle, string soundLabel returns nothing

-->applies default settings to the sound, which are found under the label from SLK-files like in CreateSoundFilenameWithLabel but is not merged with the constructor, so can be done later on on the sound handle

native SetSoundDistanceCutoff takes sound soundHandle, real cutoff returns nothing

-->guess from what range 3D-sounds are stopped and that stopwhenoutofrange has to be set to true for that

native SetSoundChannel takes sound soundHandle, integer channel returns nothing

-->there are different sound channels (see below)

native SetSoundVolume takes sound soundHandle, integer volume returns nothing

-->setting the volume of the sound, range 0 to 127, e.g. can be locally set to 0 for some players, so they cannot hear it but the sound internally still plays, which is safer to avoid desyncs with things like KillSoundWhenDone

native SetSoundPitch takes sound soundHandle, real pitch returns nothing

-->tone pitch of the sound, default value is 1, increasing it you get the chipmunk version and the sound becomes shorter, when decremented the sound becomes low-pitched and longer

// the following method must be called immediately after calling "StartSound" 
native SetSoundPlayPosition         takes sound soundHandle, integer millisecs returns nothing

-->fast-forwards to start by an offset inside the play, according to the comment, you can only do this in the beginning, therefore no gaps or rewinding possible

// these calls are only valid if the sound was created with 3d enabled
native SetSoundDistances            takes sound soundHandle, real minDist, real maxDist returns nothing

-->3D-only, no idea, probably the sound is completely hearable to maxDist or there is a transition to minDist

native SetSoundConeAngles takes sound soundHandle, real inside, real outside, integer outsideVolume returns nothing

-->3D-only, no idea

native SetSoundConeOrientation takes sound soundHandle, real x, real y, real z returns nothing

-->3D-only, no idea

native SetSoundPosition takes sound soundHandle, real x, real y, real z returns nothing

-->3D-only, the coordinates of the sound, its origin

native SetSoundVelocity takes sound soundHandle, real x, real y, real z returns nothing

-->3D-only, probably by which amount the coordinates are shifted per second, no idea whether the sound steadily changes position or is set to start location when being played and then moves around

native AttachSoundToUnit takes sound soundHandle, unit whichUnit returns nothing

-->3D-only, sound clings to a unit, maybe gets deleted/inaudible when the unit is removed

native StartSound takes sound soundHandle returns nothing

-->starts the sound, do all options have to be finished before?

native StopSound takes sound soundHandle, boolean killWhenDone, boolean fadeOut returns nothing

-->stops the sound, afterwards gets destroyed if killWhenDone is true, as for fadeOut, in the past, I used to think, the sound is still being played to the end in full volume but no, it turns down the volume with fadeOutRate as stated in constructor

native KillSoundWhenDone takes sound soundHandle returns nothing

-->destroys the handle when the sound has finished playing

// Music Interface. Note that if music is disabled, these calls do nothing
native SetMapMusic                  takes string musicName, boolean random, integer index returns nothing
native ClearMapMusic                takes nothing returns nothing

-->testing, more later

native PlayMusic takes string musicName returns nothing

-->plays music, only one at a time, in case one is already running, this one gets cancelled, the play is infinitely iterated, musicName is the path from root, mp3s, wavs and mids worked for me

native PlayMusicEx takes string musicName, integer frommsecs, integer fadeinmsecs returns nothing

-->same as PlayMMusic but you may set a start offset and fade in time in milliseconds

native StopMusic takes boolean fadeOut returns nothing

-->stops current music

native ResumeMusic takes nothing returns nothing

-->resumes music

native PlayThematicMusic takes string musicFileName returns nothing

-->the thematic music does not play repeatedly, but interrupts the PlayMusic-music meanwhile, probably meant for boss fights and similar where the sound should go in foreground, again only one thematic music at a time, cancels the previous one

native PlayThematicMusicEx takes string musicFileName, integer frommsecs returns nothing

-->same as PlayThematicMusic, only with start offset in milliseconds

native EndThematicMusic takes nothing returns nothing

-->stops thematic music

native SetMusicVolume takes integer volume returns nothing

-->music volume, 0 to 127

native SetMusicPlayPosition takes integer millisecs returns nothing

-->according to my test, rewinding/fast-forwarding works here while playing

native SetThematicMusicPlayPosition takes integer millisecs returns nothing


// other music and sound calls
native SetSoundDuration             takes sound soundHandle, integer duration returns nothing

-->no idea why you need to set this, GetSoundDuration even returns the right value without it and does not return anything else, even when I try to change it with this manually

native GetSoundDuration takes sound soundHandle returns integer

-->returns sound length in milliseconds

native GetSoundFileDuration takes string musicFileName returns integer

-->returns length of the sound file under the path in milliseconds

native VolumeGroupSetVolume takes volumegroup vgroup, real scale returns nothing

-->sounds/music belongs to different volume groups, so you can shut off a part of them in cinematics for example, so dialogs are clearly understood rather than being annoyed by combat sounds, I believe different channels belong to one volume group each (see below)

native VolumeGroupReset takes nothing returns nothing

-->resets volume groups

native GetSoundIsPlaying takes sound soundHandle returns boolean

-->whether the sound currently plays, is this function async?

native GetSoundIsLoading takes sound soundHandle returns boolean

-->think that the sound loads on the first play

native RegisterStackedSound takes sound soundHandle, boolean byPosition, real rectwidth, real rectheight returns nothing

-->3D-only, grants the sound a height and width (x/y), probably axisymmetric like jass rects, no idea what the byPosition parameter is good for

native UnregisterStackedSound takes sound soundHandle, boolean byPosition, real rectwidth, real rectheight returns nothing

-->3D-only, for deleting the region sound, why do you provide dimensions here? Can you just cut out a bit like with jass regions?


SoundEAX are defined in UI\SoundInfo\EAXDefs.slk
They contain following fields:
EffectsLevel: no idea
EAX2Direct: no idea
EAX2DirectHF: no idea
EAX2Room: no idea
EAX2RoomHF: no idea
EAX2Obstruction: no idea
EAX2ObstructionLFRatio: no idea
EAX2Occlusion: no idea
EAX2OcclusionLFRatio: no idea
EAX2OcclusionRoomRatio: no idea
EAX2RoomRolloff: no idea
EAX2AirAbsorption: no idea
EAX2OutsideVolumeHF: no idea
EAX2AutoRoomLevels: no idea
Fast2DPredelayTime: no idea
Fast2DDamping: no idea
Fast2DReverbTime: no idea
Fast2DReverbQuality: no idea
Fast2DOcclusionScale: no idea

the standard eax objects have a 0 in most fields and they only differ in EAX2Room and Fast2DOcclusionScale. There are DefaultEAXON, CombatSoundsEAX, KotoDrumsEAX, SpellsEAX, MissilesEAX, HeroAcksEAX sowie DoodadsEAX. Now, the precise differences, how it affects the sound what eax you assign it to, I do not know. They are selectable in sound editor and are captioned as "Effect" there (at least in my language).

SoundEnviroments are defined in UI\SoundInfo\EnvironmentSounds.slk
Sie haben folgende Felder:
RoomType: no idea
EffectVolume: no idea
DecayTime: no idea
Damping: no idea
Size: no idea
Diffusion: no idea
Room: no idea
RoomHF: no idea
DecayHFRatio: no idea
Reflections: no idea
ReflectionsDelay: no idea
Reverb: no idea
ReverbDelay: no idea
RoomRolloff: no idea
AirAbsorption: no idea

SoundChannels are indicated by numbers in the SLK-files, so they do not have an own type. The jass function above also works with integer. In the WE's sound editor, however, they were given fancy names, so here is a translation:
0 --> General
1 --> Unit Selection
2 --> Unit Confirmation
3 --> Unit Movement
4 --> Unit Ready
5 --> Combat
6 --> Error
7 --> Music
8 --> User Interface
9 --> Movement Loops
10 --> Environment Noise Loops
11 --> Animations
12 --> Building
13 --> Birth
14 --> Fire

Certainly, these channels have to do with assigning sounds volume groups or priorities but could not verify it yet.

VolumeGroups are defined in jass
    constant volumegroup        SOUND_VOLUMEGROUP_UNITMOVEMENT      = ConvertVolumeGroup(0)
    constant volumegroup        SOUND_VOLUMEGROUP_UNITSOUNDS        = ConvertVolumeGroup(1)
    constant volumegroup        SOUND_VOLUMEGROUP_COMBAT            = ConvertVolumeGroup(2)
    constant volumegroup        SOUND_VOLUMEGROUP_SPELLS            = ConvertVolumeGroup(3)
    constant volumegroup        SOUND_VOLUMEGROUP_UI                = ConvertVolumeGroup(4)
    constant volumegroup        SOUND_VOLUMEGROUP_MUSIC             = ConvertVolumeGroup(5)
    constant volumegroup        SOUND_VOLUMEGROUP_AMBIENTSOUNDS     = ConvertVolumeGroup(6)
    constant volumegroup        SOUND_VOLUMEGROUP_FIRE              = ConvertVolumeGroup(7)

Just by the names you could think they are related to sound channels and different channels can be sum up under a volume group. Ingame, in sound options, there are checkboxes for "Environment Noises", "Movement Noises", "Unit Replies", "Subtitles/Dialogs" and "Environment Effects", so would guess you could turn off some channels/volume groups.

So far for introductions, listing up the basic tools without striking up all of the kinks. Hope, you have some complements or can clear up my mistakes. I will add update using these hints then. Some more things are already in my mind but need to do tests/by the time.
Not open for further replies.