Week 2: for loops and conditions

Dr. Fernanda Barrientos

November 8, 2022

1 What’s a for loop?

A for loop is a procedure that allows you to repeat the same operation over a set of elements. Last week we created the following script:

sound_directory$ = "/home/fernanda/Desktop/palabras/"
Create Strings as file list: "fileList", sound_directory$ + "*.wav"
anumber=3
thisfile$ = Get string: anumber
Read from file: sound_directory$ + thisfile$
Play

With this script we were able to open just one file out of a bunch of files (i.e. only file number three). This is not very helpful, especially considering that we can do this using the Object window and clicking along. We will learn how to open all the files at once with a script by the end of this tutorial.

2 A simple for loop

for i from 2 to 10
appendInfoLine: "This is number ", i
endfor

This small script has told Praat to take all numbers from 2 to 10 and for each one of them, to write a line on the Info window. Note that i means here ”a given number”, but you could also replace it with blah, x, etc.

The syntax is always the same: for i from x to y and then the following line declares what you want Praat to do with every element defined by i (in the case of the script above, i means "every number from 2 to 10"). Then, we close the loop with endfor.

If you want Praat to start counting from 1, then you don’t need to write for i from 1 to x. You can simply write for i to x, since 1 is the default starting number for the iteration.

3 Create a set of sounds

A for loop can also create sounds. This can be done manually by going to New >> Sound >> Create Sound from formula. The arguments taken by this command can be seen in the dialog window, which are: 1) Name of the sound, 2) Number of channels (mono or stereo: we want mono, so there is a 1), 3) Start time, 4) End time, 5) Sampling frequency, and finally 5) A formula, which in this particular case creates a sine wave with random noise. Unless you are interested in sounds that are not very speech-like, we will rarely use this command (BUT you can create a silence by putting a 0 in the formula field!).

Hence, this script will create 5 sine waves with random noise, which will be increasingly long (the first one will be 1 second long, the following 2 seconds long, and so on).

for i to 5
Create Sound from formula: "sineWithNoise" + string$(i), 1, 0, i, 44100, "1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)"
endfor

The sound is not very interesting in this case: it's just like picking up a landline phone without doing anything. We will build more interesting sounds in the following weeks.

4 Drawing elements

A for loop can also draw to the Picture window.

num= 0.1
for i from 0 to 10
Text: i*num, "left", i*num, "Half", "a"
endfor

Here we have asked Praat to draw a diagonal line of a’s in the pink (or blue) box. Since Praat assumes that this box is 1 unit long on each side, we will have to use decimal numbers (otherwise it will draw beyond the box). In order to do this we had to ask Praat to take the numbers from 1 to 10 and divide them by 10 (or more specifically, multiply it by 0.1; you can also write i/10 in the for loop but I wanted you to create a numeric variable). If you’d like to know what the other parameters are, you may simply go to the Picture window, choose Text... and look at the dialogue window. What the script did was simply to write these parameters down and allow you to use the for loop instead of opening this dialogue box 10 times.

5 A for loop for strings

We will create a for loop that iterates through a series of strings. First, we need to create a string list. But we will use a different option this time. Instead of the Create Strings as file list option that we used last week, we will use Create Strings as tokens. This command does not require us to specify a path to any file since it’s just a list of strings that we have come up with.

friends= Create Strings as tokens: "Rachel Monica Phoebe Chandler Ross Joey", " ,"
numOfFriends = Get number of strings
for iString to numOfFriends
friend$=Get string: iString
appendInfoLine: friend$ + " is a fictional character"
endfor

After creating the string list, we ask Praat to give us the total number of strings in our list, this way we can tell Praat when to stop iterating as the for loop goes through the strings (you can also count them yourself, but this might not be an option if you have a VERY LONG string list!).

Then we start the for loop. After this, we told Praat two things: (a) we created a string variable friend$, which will give you the string corresponding to the number that Praat is at as it goes through the loop. And then (b) we told Praat to write an Info line. After that we closed the loop.

6 Embedding a condition in your for loop

Likewise, we can embed a condition in your for loop. The syntax is quite simple:

if [condition]
[execute action]
endif

The previous script printed all the names of the string list. But let’s exclude someone (we will exclude Joey, for he was a very weird character).

Create Strings as tokens: "Rachel Monica Phoebe Chandler Ross Joey", " ,"
numOfFriends = Get number of strings
for iString to numOfFriends
friend$=Get string: iString
if friend$ != "Joey"
appendInfoLine: friend$, " is a credible fictional character"
endif
endfor

Here we embedded the condition friend$ !="Joey", with which we have excluded Joey from the appendInfoLine action; hence it was not printed.

You may have noticed a couple of things:

1.
The ”is not equal to” symbol is != (common to many computer languages). For other operators and symbols, check the Praat manual as they sometimes change.
2.
At this point your Info window must be a bit cluttered. Try adding the clearinfo command before every script; that will wipe out the previous lines.
3.
If you want to save your script, you can simply go to the menu on the script window and select Save as... Make sure that the extension of your file is .praat or Praat won’t read it when you open it the next time!
4.
Your variables CANNOT start with a capital letter!
5.
You can also make these conditions a bit more complex by adding "and" or "or" statements. Use the ampersand (&) for the former; use the pipe bar (|) for the latter. Can you now modify the script so as to exclude Phoebe as well?

We can also print something different for Joey and Phoebe. In that case, we add another line, else and then yet another line with the action that we want for the elements that do not evaluate to TRUE in the if statement.

The syntax, then, is as follows:

if [condition]
[execute action 1]
else
[execute action 2]
endif

Can you do it yourself? Give it a try! The answer will be after this puppy.

Create Strings as tokens: "Rachel Monica Phoebe Chandler Ross Joey", " ,"
numOfFriends = Get number of strings
for iString to numOfFriends
friend$=Get string: iString
if friend$ != "Joey" 
appendInfoLine: friend$ + " is a credible fictional character"
else
appendInfoLine: "But " + friend$ + " is not a very credible character."
endif
endfor

6 Open files

Now, you should be able to create a script that opens all the files in your palabras folder, except causa.wav. Try the following:

sound_directory$ = "/home/fernanda/Desktop/palabras/"
Create Strings as file list: "fileList", sound_directory$ + "*.wav"
numOfFiles= Get number of strings
for ifile to numOfFiles
thisfile$ = Get string: ifile
if thisfile$ != "causa.wav"
Read from file: sound_directory$ + thisfile$
endif
selectObject: "Strings fileList"
endfor

Here we had to resort to a little trick. It turns out that Praat runs the for loop as long as the cursor is selecting the Object containing the relevant elements (in this case, the Strings Object, which contains the strings). If in your for loop you asked Praat to read a file, Praat will be selecting this opened file; thus, we need to ask him to return to the Strings element. If you look at the loop, you may notice that the last line before closing the loop is selectObject: "Strings fileList". This line takes Praat back to the Strings element after each iteration.

PRO TIP: Objects can be refered to as numeric variables

Praat basically has two different ways to use the selectObject command:

Basically, Praat assigns an individual number to each object that is opened or created in a session. It's the number that we see to the left of the object name in the object window. In order to use the selectObject command (and other similar commands) with the object number, we can just create a new numeric variable when we create/open this object and then later use this variable with the selectObject command. For the script above it would look something like this (pay attention to lines 2 and 9):

sound_directory$ = "/home/fernanda/Desktop/palabras/"
fileList = Create Strings as file list: "fileList", sound_directory$ + "*.wav"
numOfFiles= Get number of strings
for ifile to numOfFiles
thisfile$ = Get string: ifile
if thisfile$ != "causa.wav"
Read from file: sound_directory$ + thisfile$
endif
selectObject: fileList
endfor

Here we see that the Strings list created in line 2 was stored as a numeric variable whose name is fileList. There are a couple of reasons why this is a better approach:

  1. It's less error prone: if you refer to the file by name, you have to know which object type it is (Strings, Sound, TextGrid, etc.) and you have to know the name of the file and also there is always typos.
  2. If for some reason you want to select an object in a for loop that changes with every iteration (e.g. a soundfile), this can easily be done with using the object number but it's a bit more complicated if you want to use the object name.

7 Homework

Can you modify this script so that: