Session 5
Variables
Numeric Variables
Variables are containers for dynamic content, typically numbers and strings. You can create as much containers as you need and fill them with varying content as often as needed. A variable is created when filled with content the first time:
a = 7
This statement creates a variable called a and fills it with the number 7. Each variable in a given script must be given a unique name. The name must start with a lowercase letter [a-z] and may continue with a sequence of lowercase or uppercase letters [a-zA-Z], digits [0-9], and underscores [_]. Some permitted variable names:
a = 7
theNumber = 7
the_number = 7
number1 = 7
Some prohibited variable names:
# must start with lowercase letter
_a = 7
Number = 7
1number = 7
# only letters, digits, and underscores are allowed
number-1 = 7
the.number = 7
number 1 = 7
BTW
Not only variables begin with a lowercase letter, but also all script-specific commands. Script-specific commands exist only to be used in scripts, you won't find these commands in any GUI menus and you can't paste them using the history. You already know the script-specific commands editor
and endeditor
as well as the output commands (writeInfo
etc.).
All button commands, on the other hand, begin with an uppercase letter. Button commands are those commands that represent GUI actions (e.g. Create Sound as pure tone:
or Play
). And button commands are those commands that are collected in the history.
It is good practice to give variables informative names. Advantages: Variables are easier to memorize and scripts are easier to read and understand. Two styles are popular, in accordance with the Praat naming requirements: lower case words separated by underscores (the_number) or 'WikiWords', i.e. word sequences with initial capitals—except the first character of course (theNumber). In contrast to standard variables, auxiliary variables (e.g. counters in loops (cf. for-Loops) are usually kept simple (i is the most popular name for a counter).
Variable assignment
Filling a variable with content is called assigning a value to that variable. Above, we've assigned the value 7 to the variable a. In this context the symbol '=' is an assignment operator. It assigns the value on the right side to the variable on the left side. In the simplest case the assigned value is a literal value, i.e. a literal number like above or a literal string. But there are other (more interesting) possibilities as you'll see in a minute.
Once a value is assigned to a variable we can use that variable in a statement. This is as simple as replacing a literal value with the variable's name. When a script runs, a variable's name is always substituted with its assigned value (the one exception to this rule is assignment: obviously, a variable on the left of the assignment operator is not substituted).
To Pitch: 0, 60, 250
is equivalent to
floor = 60
ceiling = 250
To Pitch: 0, floor, ceiling
You are not allowed to use unassigned variables. If you forget to assign some value to a variable before using it, like in the following example, Praat protests with an error message: Unknown variable: ceiling.
floor = 60
To Pitch: 0, floor, ceiling
Variables are helpful, for example, if you want to declare some standard parameters at the beginning of a script and use them later in the script for analyses. With the pitch range declared at the beginning of the script, it's easy to adopt the script to a female voice: just assign values such as 100 to floor and 400 to ceiling. This is especially helpful if the same parameter is used more than once in the script:
floor = 60
ceiling = 250
.
.
.
To Pitch: 0, floor, ceiling
.
.
.
To Intensity: floor, 0, "yes"
Assigning a new value once at the beginning of the script adopts the entire script reliably to the new situation without searching through the whole script for relevant statements and replacing literal values. (This is the moment when the container/content analogy dissipates: Once filled, the content of a variable may be used as often as needed—it's not 'empty' after the first use.)
Variable substitution
In case you wonder why variable names are not enclosed in double quotes: You are partially right, variable names are strings, obviously, and string arguments must be enclosed in quotes. But it's not the variable's name that counts, it's the content! The name is just a placeholder which is not interpreted. If you put double quotes around a variable's name the Praat scripting engine interprets it as a literal string not as a variable. Hence, no substitution takes place. In the example above the script would terminate with an error message because To Pitch...
only requires numerical arguments, not strings.
Variables are called variables because they can contain varying values. If a new value is assigned to an existing variable the old value disappears and is replaced by the new value. After
a = 7
a = 9
the variable a contains the value 9. This seems pointless at the moment but as you'll see later it's an important property of variables.
Until now we've assigned only literal values to variables. But there are much more powerful possibilities, namely formulas and queries. Let's start with formulas. A formula on the right side of the assignment operator is evaluated and the result is assigned to the variable:
a = 3 + 4
This assigns the value 7 to the variable. As mentioned above, the only place where variables are not substituted is left of the assignment operator, everywhere else variables are replaced by their value at runtime. So this statement assigns 7 to a as well:
x = 3
a = x + 4
As you know from the previous session, the basic arithmetic operators for formulas are
a = 3 + 4
a = 9 - 2
a = 3.5 * 2
a = 21 / 3
Remember the script below? We discussed it in the session on command history because it didn't write the pitch maximum to Praat Info like the
Create Sound as pure tone: "tone", 1, 0, 0.4, 44100, 440, 0.2, 0.01, 0.01
Play
To Pitch: 0, 75, 600
Hum
Get maximum: 0, 0, "Hertz", "Parabolic"
As I said before, this is because the Praat scripting engine assumes that you want to handle the query result inside the script. This is true for all query commands and the way to handle queries inside a script is to assign the query result to a variable:
pitchMax = Get maximum: 0, 0, "Hertz", "Parabolic"
Now pitchMax contains the pitch maximum and can be used for instance to set the pitch range for the pitch display in a sound editor (of course, as you know by now, there has to be some environment switching involved…):
Pitch settings: 75, pitchMax, "Hertz", "autocorrelation", "automatic"
You can even add 20 Hz to the maximum to give the pitch contour some air:
Pitch settings: 75, pitchMax + 20, "Hertz", "autocorrelation", "automatic"
To replicate the GUI behavior, i.e. to write the query result to Praat Info, do just that: Write the content of the variable to Praat Info:
pitchMax = Get maximum: 0, 0, "Hertz", "Parabolic"
writeInfoLine: pitchMax
# or more verbose:
appendInfoLine: "Maximum pitch: ", pitchMax, " Hz"
With a pitch maximum of 187.375 Hz this produces:
187.375
Maximum pitch: 187.375 Hz
Practical example
The script examples in this session were pretty abstract so far. Their only purpose was to illustrate assignment and usage of numeric variables. To conclude this session, let's have a look at a simple but more practical example. Suppose you have a sound object and you want to add 1 second of silence at the end. To achieve this, you must create a new sound object (the silence) before concatenating the two sounds. A prerequisite for concatenation is that both sounds have the same sampling frequency. The following script takes the sampling frequency from the selected sound to create a compatible sound object containing silence:
sampl_freq = Get sampling frequency
Create Sound from formula: "silence", 1, 0, 1, sampl_freq, "0"
Of course it would be possible and worthwhile to include the concatenation in the script, but before we can do this we need to cover the next session on object selection. But there's another refinement we can add. Suppose you need to attach silence of varying duration. In the current script you must identify the correct parameter and edit it. If you have to do this often, it's safer and more convenient to declare the silence duration at the beginning of the script:
sil_dur = 1
sampl_freq = Get sampling frequency
Create Sound from formula: "silence", 1, 0, sil_dur, sampl_freq, "0"
Finally, suppose you want to add silence to a bunch of sounds so that the concatenation result is always 3 seconds long. For instance, if a sound has a duration of 2 sec you'll add 1 sec of silence, if a sound has a duration of 1.8 sec you'll add 1.2 sec and so on. To accomplish this you must query the duration of each sound before creating silence that lasts exactly as long as the difference between the sound's duration and the target duration of 3 seconds. Voilà:
# Get sampling frequency of selected sound
sampl_freq = Get sampling frequency
# Get duration of selected sound
snd_dur = Get total duration
# calculate difference between target duration and actual duration
sil_dur = 3 - snd_dur
# create silent sound with necessary duration
Create Sound from formula "silence", 1, 0, sil_dur, sampl_freq, "0"
Ok, nice script with a tad of practical relevance. But it's still far from perfect. Of course, we would want the script to accomplish the actual concatenation job for us (see next session on Object Selection). Next, we would want the script to process all relevant (=selected) sounds in one run rather than launching it separately for each sound (this requires Loops). Finally, we would want the script to quietly skip sounds with a duration > 3 sec rather than to just terminate with a nasty error message (understandably enough, Create Sound from formula
doesn't accept a negative duration) (possible with Conditionals).