# Why does GetSoundDuration() always return the same wrong value in my Portal 2 Vscript?

I am trying to write a Vscript for an instance in Portal 2; the goal of which is to play ambient_generic entities directly after one-another in sequence.

To do this, I need to have the script figure out the length of the audio files. But for some reason, it always returns 2.24426 regardless of which sound path I put into GetSoundDuration(). Is this a bug in the source engine or is this something I'm doing wrong?

I have several PATH_# variables that I've already verified are set correctly to the paths of the audio files.

(4_PATH <- "vo/david/placeholder/crash_intro_04.wav"; for example)

This is the code I am running which produces the incorrect result:

PATH_1 <- "";
PATH_2 <- "";
PATH_3 <- "";
PATH_4 <- "";
PATH_5 <- "";
PATH_6 <- "";
PATH_7 <- "";
PATH_8 <- "";
PATH_9 <- "";
PATH_10 <- "";
SPACING <- 0.5;

sound1dur <- 0;
sound2dur <- 0;
sound3dur <- 0;
sound4dur <- 0;
sound5dur <- 0;
sound6dur <- 0;
sound7dur <- 0;
sound8dur <- 0;
sound9dur <- 0;
sound10dur <- 0;

//this is the function I use to play the stuff with
function Play(){

//its stupid beyond belief that i have to surround string variables with quotes so they'll be recognized as strings, but its source engine, so what did i expect?
sound1dur = Entities.FindByName(null,self.GetName() + "_sound_1").GetSoundDuration("\"" + PATH_1 + "\"","")
sound2dur = Entities.FindByName(null,self.GetName() + "_sound_2").GetSoundDuration("\"" + PATH_2 + "\"","")
sound3dur = Entities.FindByName(null,self.GetName() + "_sound_3").GetSoundDuration("\"" + PATH_3 + "\"","")
sound4dur = Entities.FindByName(null,self.GetName() + "_sound_4").GetSoundDuration("\"" + PATH_4 + "\"","")
sound5dur = Entities.FindByName(null,self.GetName() + "_sound_5").GetSoundDuration("\"" + PATH_5 + "\"","")
sound6dur = Entities.FindByName(null,self.GetName() + "_sound_6").GetSoundDuration("\"" + PATH_6 + "\"","")
sound7dur = Entities.FindByName(null,self.GetName() + "_sound_7").GetSoundDuration("\"" + PATH_7 + "\"","")
sound8dur = Entities.FindByName(null,self.GetName() + "_sound_8").GetSoundDuration("\"" + PATH_8 + "\"","")
sound9dur = Entities.FindByName(null,self.GetName() + "_sound_9").GetSoundDuration("\"" + PATH_9 + "\"","")
sound10dur = Entities.FindByName(null,self.GetName() + "_sound_10").GetSoundDuration("\"" + PATH_10 + "\"","")

printl(sound1dur + " is sound 1's duration even though its really supposed to be 5.84")
printl(sound2dur + " is sound 2's duration even though its really supposed to be 2.13")
printl(sound3dur + " is sound 3's duration even though its really supposed to be 9.59")
printl(sound4dur + " is sound 3's duration even though its really supposed to be 8.88")
printl(sound5dur + " is sound 3's duration even though its really supposed to be 9.86")

EntFire(self.GetName() + "_sound_1","PlaySound","",0)
EntFire(self.GetName() + "_sound_2","PlaySound","",sound1dur + SPACING)
EntFire(self.GetName() + "_sound_3","PlaySound","",sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_4","PlaySound","",sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_5","PlaySound","",sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_6","PlaySound","",sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_7","PlaySound","",sound6dur + sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_8","PlaySound","",sound7dur + sound6dur + sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_9","PlaySound","",sound8dur + sound7dur + sound6dur + sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
}

//the following gets appended to the script during the compilation //process of the map; via Teamspen210's hammer addons.

8_PATH <- "common/null.wav";
3_PATH <- "vo/david/placeholder/crash_intro_03.wav";
4_PATH <- "vo/david/placeholder/crash_intro_04.wav";
10_PATH <- "vo/david/placeholder/crash_intro_01.wav0";
5_PATH <- "vo/david/placeholder/crash_intro_05.wav";
2_PATH <- "vo/david/placeholder/crash_intro_02.wav";
6_PATH <- "common/null.wav";
1_PATH <- "vo/david/placeholder/crash_intro_01.wav";
7_PATH <- "common/null.wav";



The output (the "supposed to be" numbers are the actual length of the audio files in question, measured using Adobe Audition):

2.24426 is sound 1's duration even though it's really supposed to be 5.84
2.24426 is sound 2's duration even though it's really supposed to be 2.13
2.24426 is sound 3's duration even though it's really supposed to be 9.59
2.24426 is sound 3's duration even though it's really supposed to be 8.88
2.24426 is sound 3's duration even though it's really supposed to be 9.86


For a minimal example that has the same issue, try:


sound1dur = self.GetSoundDuration("error.wav","")

printl(sound1dur + " is sound 1's duration even though its really supposed to be 2.24")


note that while creating this example, I realized a part of the problem: getsoundlength seems to be getting the length of error.wav no matter the path it is fed. error.wav being the engine's fallback when it can't find something.

• It would help if you created a minimum complete verifiable example. Lacking that, just to verify, when you use PATH_1 with a call to EmitSound(...), does it play as expected? Aug 4 at 20:03
• @Pikalek the sounds play just fine but not with the right timing; though the way I'm timing them is through a lot of delayed EntFires. I'll update the example a little to try to make the code more understandable (I'm not sure how I'd make a minimal complete verifiable example other than what I've already done. ) the audio length is what I'm trying to use for calculating the delays. Aug 4 at 23:36

the answer was unfortunately just as complex as the question and came down to bad logic in my scripts and a few typos. my working full script:

SPACING <- 0;

sound1dur <- 0;
sound2dur <- 0;
sound3dur <- 0;
sound4dur <- 0;
sound5dur <- 0;
sound6dur <- 0;
sound7dur <- 0;
sound8dur <- 0;
sound9dur <- 0;
sound10dur <- 0;

function Init(){

}

function Stop(){
EntFire(self.GetName() + "_sound_*","StopSound","",0);
}

function Play(){

sound1dur = self.GetSoundDuration(PATH_1,"")
sound2dur = self.GetSoundDuration(PATH_2,"")
sound3dur = self.GetSoundDuration(PATH_3,"")
sound4dur = self.GetSoundDuration(PATH_4,"")
sound5dur = self.GetSoundDuration(PATH_5,"")
sound6dur = self.GetSoundDuration(PATH_6,"")
sound7dur = self.GetSoundDuration(PATH_7,"")
sound8dur = self.GetSoundDuration(PATH_8,"")
sound9dur = self.GetSoundDuration(PATH_9,"")
sound10dur = self.GetSoundDuration(PATH_10,"")

EntFire(self.GetName() + "_sound_1","PlaySound","",0)
EntFire(self.GetName() + "_sound_2","PlaySound","",sound1dur + SPACING)
EntFire(self.GetName() + "_sound_3","PlaySound","",sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_4","PlaySound","",sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_5","PlaySound","",sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_6","PlaySound","",sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_7","PlaySound","",sound6dur + sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_8","PlaySound","",sound7dur + sound6dur + sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
EntFire(self.GetName() + "_sound_9","PlaySound","",sound8dur + sound7dur + sound6dur + sound5dur + sound4dur + sound3dur + sound2dur + sound1dur + SPACING)
}

PATH_1 <- "common/null.wav";
PATH_2 <-"common/null.wav";
PATH_3 <-"common/null.wav";
PATH_4 <-"common/null.wav";
PATH_5 <-"common/null.wav";
PATH_6 <-"common/null.wav";
PATH_7 <-"common/null.wav";
PATH_8 <-"common/null.wav";
PATH_9 <-"common/null.wav";
PATH_10 <-"common/null.wav";


note that the PATH_# vars are set in-map via hammer logic