• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

SetSoundPitch Weirdness

Status
Not open for further replies.
For some reason, the SetSoundPitch() native seems to be bugged.

Let's look at some code here:
JASS:
    local sound s1 = CreateSound("war3mapImported\\PiccoloA5.mp3", false, false, false, 10, 10, "")
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1.301)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1.302)
The first sound has the correct pitch of 1.
The second sound has the correct pitch of 1.3
The third sound has a pitch of 1.3^2
The fourth sound has a pitch of 1.3^2

JASS:
local sound s1 = CreateSound("war3mapImported\\PiccoloA5.mp3", false, false, false, 10, 10, "")
call StartSound(s1)
call SetSoundPitch(s1, 1)
call TriggerSleepAction(3)
call SetSoundPitch(s1, 1.3)
call StartSound(s1)
call TriggerSleepAction(3)
call StartSound(s1)
call SetSoundPitch(s1, 1.3)
call TriggerSleepAction(3)
call StartSound(s1)
call SetSoundPitch(s1, 1.302)
First Sound: 1.0
Second Sound: 1.3
Third Sound: 1.3
Fourth Sound: 1.3^2

Now that this wasn't weird enough, there is more:
JASS:
    local sound s1 = CreateSound("war3mapImported\\PiccoloA5.mp3", false, false, false, 10, 10, "")
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1.3)
Real pitch values:
First Sound: Pitch 1
Second Sound: Pitch 1.3
Third Sound: Pitch 1.3 (??)
Fourth Sound: Pitch 1.3 (????)

Same goes for
JASS:
    local sound s1 = CreateSound("war3mapImported\\PiccoloA5.mp3", false, false, false, 10, 10, "")
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1.001)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1.301)
Real pitches:
1.0
1.3
1.3 (???)
1.3

And now to make it even more weird:
JASS:
    local sound s1 = CreateSound("war3mapImported\\PiccoloA5.mp3", false, false, false, 10, 10, "")
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1.301)
    call TriggerSleepAction(3)
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
1.0
1.3
1.3^2
1.3 (?????)

I give up ... I can not find ANY logical pattern here. Someone please help; am I missing something? If someone can give me a reason for this weird behaviour, please help!
I want to write a SetSoundPitchEx function, but without a logical pattern, there's nothing I can do about it.

PS: Changing the Length of the TriggerSleepAction or Starting the Sound after or before setting the sound pitch does not make any difference.
 
I know of some weirdness with SetSoundPitch
What it does is only accept values and perform correctly if those values have only one decimal digit.
Can't be true.

Because this doesn't work:
JASS:
    call SetSoundPitch(s1, 1.0)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.0)
    call StartSound(s1)
The third will play like the second sound.

However, this does work:
JASS:
    call SetSoundPitch(s1, 1.0)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.001)
    call StartSound(s1)
 
Also, using the note conversion base (1.05965) returns exact in-tune notes. I checked it with a chromatic tuner, so 1 digit-only can't be true.

EDIT:

JASS:
    local sound s1 = CreateSound("war3mapImported\\PiccoloA5.mp3", false, false, false, 10, 10, "")
    call StartSound(s1)
    call SetSoundPitch(s1, 1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.3)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1.301)
    call StartSound(s1)
    call TriggerSleepAction(3)
    call SetSoundPitch(s1, 1)
    call StartSound(s1)
It seems to make a difference wether you pitch before or after starting the sound. In this example, the third sound is still at 1.3. If I put the pitch behind starting the third sound, it is at like 1.66. However, if I alter the third pitch to 1.3 instead of 1.301, even after starting the sound, the pitch remains at 1.3. It's totally fucked up. There is no obvious rule to this shit.
 
Okay, after further testing I think I found the rules here, even if they don't really make much sense.

Prepitching:
There is a difference between pre- and post-pitching (pitching before the sound starts playing or after). Pre-pitching seems to always overwrite the old pitch value and seems to be pretty relyable, except when you want to pitch back to 1.

examples:
JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call TriggerSleepAction(Time_Until_Sound_Stopped)
call SetSoundPitch(s, 1.1)
call StartSound(s)
Returned pitch: 1.1

--------------------------------------------

Backpitching:
Setting the pitch value back to 1 will simply not work. Instead, you must set it to a small offset of 1, in order to pitch it back (1.0001 works) before the sound started.
If you want to pitch the sound back to 1 after the sound started, you need to divide through the old pitch value.

examples:
JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call TriggerSleepAction(Time_Until_Sound_Stopped)
call SetSoundPitch(s, 1.0)
call StartSound(s)
Returned pitch: 1.3

JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call TriggerSleepAction(Time_Until_Sound_Stopped)
call SetSoundPitch(s, 1.0001)
call StartSound(s)
Returned pitch: 1.0

JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call SetSoundPitch(s, 1/1.3)
Returned pitch: 1.0

--------------------------------------------

Postpitching:
In case you postpitch a sound (for example if you want to change the pitch value while the sound is running or in case you want to start the sound again by using SetSoundPlayPosition()), the game will always take the last pitch value as a base and pitches from this value to the new pitch.
Means if you want to postpitch, you need to first pitch back to 1 (divide through the old value; see above!), then pitch to your desired value.

examples:
JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call SetSoundPitch(s, 1.2)
Returned pitch: 1.56

JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call SetSoundPitch(s, 1/1.3)
call SetSoundPitch(s, 1.2)
Returned pitch: 1.2

--------------------------------------------

Pitching the same value twice:
In case you put in the same value twice in a row, the game engine will always ignore the second pitching. Means even if you pitch after the sound started, which would normally result in a different pitch (see postpitching rule), the pitch will still remain the same. However, even the slightest difference in pitch will be enough to apply the postpitch rule here.

examples:
JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call SetSoundPitch(s, 1.3)
Returned pitch: 1.3

JASS:
call SetSoundPitch(s, 1.3)
call StartSound(s)
call SetSoundPitch(s, 1.301)
Returned pitch: 1.66



This is all I've found out so far. It all seems to boil down into this little snippet:
JASS:
    function SetSoundPitchEx takes sound s, real pitch, real lastpitch returns nothing
        if not GetSoundIsPlaying(s) then
            if pitch == 1 then
                call SetSoundPitch(s, 1.0001)
            else
                call SetSoundPitch(s, pitch)
            endif
        else
            call SetSoundPitch(s, 1/lastpitch)
            call SetSoundPitch(s, pitch)
        endif
    endfunction
 
Status
Not open for further replies.
Top