Praat notes
Initial Praat setup
Installing Praat
Praat is a single executable.
In principle, you can download it, put it wherever, and run it.
There is no data kept alongside it that can get lost -- because instead of that, your personal data goes into your specific user account instead.
See #The_Praat_preferences_folder, except you often don't need to think about that until #Tweaking_and_extending_praat)
"The phonetic font is not available" (maybe optional)
Praat wants there to be a font that covers all IPA characters in Unicode, so it can show them when you annotate those.
Praat comes from a time where you likely needed to install the fonts called SIL Doulos and/or SIL Charis to get IPA characters to display.
These days there are other fonts that cover most of IPA already, so it may work without these fonts, and if it works without doing that, you can ignore the warning.
Yet it's not a guarantee, so Praat still plays safe and still complains if you don't have those fonts installed. If it doesn't work, or you just want it to be quiet, you could install those fonts. (See also: how to install fonts (in general))
Everyday Praat
How Praat thinks: The list
The main praat window, a.k.a. the object window, primarily shows you the list of objects.
Things become objects in that lest when you
- record sound (see New menu)
- load files
- create new list items based on existing list items (via some action or command)
You would be forgiven to think this is a project, where you can save the collection of everything you see.
You cannot. The list it will not be remembered between runs of Praat.
Instead, it is intended purely as scratch space. You can save items on the list, but not save the list itself.
Objects and object combinations
We often work thinking in terms of Objects - the things already in the main window's list.
- A Sound is an object that contains audio.
- A TextGrid is an object that contains text over time.
- ...and so on
For many objects, when you select just that object, you will get a View & Edit button.
- That button would open a window for it to, well, view and possibly edit it.
- e.g. try View & Edit on a Sound
Also, specific combinations of objects
- brings up some specific new buttons
- hides buttons that do not apply to this combination
For example, select a Sound 'and a TextGrid.
- You will now get a View & Edit that is different: it happens to combines the sound view and the textgrid view -- meant for annotating sounds
- and yes, it allows you to do that for any Sound-Textgrid combination, but it only makes sense when they are related, e.g. when you created such a TextGrid from the Sound:
- select the Sound, then click Annotate → To Textgrid...
Notes:
- Sometimes nothing makes sense for the combination you have selected
- There are also hints -- e.g. when you select only a TextGrid, there is a button named View & Edit with Sound? which, if clicked, just tells you to select both.
- there are many possible combinations not hinted at -- just some of the most common ones
Object types
There are quite a few object types.
Many of which you may never use.
You do not need to know this yes -- you'll learn them as you use them -- but roughly in order of how quickly you will probably see or need it:
Some more commonly used object types:
Sound

- waveform
- typically mono, but can be multi-channel
- (PCM data, though you don't often get its values directly)
- View & Edit shows waveform and spectrogram
- as the legend hints:
- blue trace is pitch (note it's on a different Y axes from the shown spectrogram, because it'd otherwise be at the bottom)
- red dots are formant places
- green/yellow is intensity
- pulses are shown in the waveform
- https://www.fon.hum.uva.nl/praat/manual/Sound.html
There is also a LongSound[1], for things that won't necessarily fit in fast memory, but this is usually no concern these day
TextGrid


- lets you annotate text
- usually shown together with the Sound it is annotating
- either annotating text with
- a time range - start and end time
- a point in time
- https://www.fon.hum.uva.nl/praat/manual/TextGrid.html
Strings
- ordered list of strings
- https://www.fon.hum.uva.nl/praat/manual/Strings.html
Table
Table[2]
Matrix
Matrix[3]
Pitch

- periodicity candidates over time, with relative certainty
- in regularly spaced frames (...unlike the evidence it draws from - so each frame's estimate may come from varying amount of pulses. Pitch objects show it regular, PitchTiers do not(verify))
- may be analyzed separately, from Sound objects; there are varied methods (the one shown here is intentionally a messier variant)
- https://www.fon.hum.uva.nl/praat/manual/Pitch.html
PitchTier

- basically a set of (timestamp, pitch_in_hz)
- probably extracted via a Manipulation object
- Praat itself, if asked about pitch at a point, interpolates between these points (and extends outwards before the first and after the last value)
- can also be altered (and drawn) to resynthesize LPC/PSOLA type things with different vocal pitch
- https://www.fon.hum.uva.nl/praat/manual/PitchTier.html
Manipulation

- LPC/PSOLA style speech analysis of Sound object (a specific model which happens to e.g. separate pitch, duration)
- View & Edit shows
- pulses (if you extract this, it becomes a PointProcess)
- estimated pitch (extracted as PitchTier)
- duration (extracted as DurationTier)
- contains a little more
- in particular the original Sound, e.g. for comparison's sake
- https://www.fon.hum.uva.nl/praat/manual/Manipulation.html
More specific and/or lesser-used object types
Window grouping
The praat picture window

Mainly used for making plots from data.
You won't need this until you do, so can close it.
- I've seen people making startup scripts to immediately close it
- You can also start Praat with --hide-picture (which seems to do the same)
Automation and scripting
As hinted at above, you can automate Praat.
- The most basic form of this is to
- do what you want to automate in the graphical interface (which Praat itself records as commands),
- tell it to paste that sequence of things into a script.
- That script is now equivalent to that series of graphical interface interactions, like a recipe that should be repeated exactly.
- On top of that, there is a scripting language that lets you write more complex thing in.
For more on both, see #Praat_scripting_notes below.
Common tasks
Recording sound
Usually: New → Record Mono Sound
You can record one or more fragments, and Save it to the List.
Most microphones are mono, and a lot of sound analysis works on mono.
Stereo has directional effects when you listen to both at once. This absolutely has its uses -- in particular, if you are recording less for sound analysis, and more for a person to transcribe it to text later, know that a lifetime of having two ears makes people decent at separating multiple voices from any sound recorded in any vaguely spatial way. This is part of why many portable recorders have two mics mounted on them.
Also, it is good science to only vary the things you intend to study, and stereo effects can boost or suppress frequencies, and will sound different in speaker versus headphones, and other such details. This is easily overstated, as the comb/filtering effects usually amount to at most a few decibels, but mono will make your life slightly simpler, so is generally preferred.
"Recording interfaces tend to have two input channels. What happens when you ask for mono?"
Turns out this depends on the driver/sound system and the recording software. You may just get the first/left, you may get a mix of both, Praat in the cross-OS sense cannot guarantee just one, so be sure to turn down any channels you are not using, to avoid their noise.
Big aside: On levels/gain, noise, and scaling
tl;dr:
- Praat scales spectrogram intensities and waveform amplitudes to whatever is loudest
- great for visibility of what is there
- bad for an indication of actual levels
- not great for an indication of present noise
Hit record in Praat, tell your subject to talk at reasonably loud levels, and look at the green/yellow/red indicator

If
- it doesnt move, increase the input/mic sensitivity until it does
- if it barely noves, probably still increase it a little more
- it frequently gets into yellow, probably also lower it a bit
- it goes into the red, certainly lower it because it's going to distort
- for a quick setup, the aim is to get it to be middling, not to get it to be the loudest (in that this way you're leaving space for people to be a little louder than planned, without it necessarily distorting)
A little more technically: this scale is linear with pressure (not logarithmic/decibel as many other things do).
- This means half the meter is -6dB below the max, quarter is -12dB, and (at the regular window size) ten pixels is -30dB, and one pixel is -50dB
Aside from hardware reasons, also very pragmatic details such as people focusing on a test, then comfortably re-settling (further away) for the real thing.
So when doing serious recording, consider starting with a sanity check: make a quick recording and listen to it (headphones are often better than speakers), and check the waveform for flat, clipped tops.
...because one annoying footnote is sometimes, some part of the chain reduces volume -- and might do so after clipping has happened.
- This is annoying in that it invalidates simple "red means bad, below is all good" advice, and gives you one more thing to check
- If you can't get Praat to extend over roughly halfway no matter what you do, then maybe something in your setup is trying to be smart ...after the signal had already distorted. The only way to be entirely sure is to record something very loud (e.g. blow into the mic) and inspect whether the waveform clips.
Mainly because whenever your recording levels were much lower than they could be, the noise is higher.
If this comes from a limitation of hardware or situation, so be it - work with what you have.
If this can be improved by your attention and turning one knob before hitting record time, it is worth that attention.

- All four of these sections apply helpful scaling -- meaning none of them compare directly.
- if there is stronger difference between signal and background noise, Praat can more easily ignore it in analysis
When Praat visualizes audio, as a waveform or as a spectrogram, it will scale up whatever you already recorded. Praat effectively hides this difference.
Which is great in that once you have settled your recording, then you will always see a waveform and spectrogram with whatever is the strongest signal, regardless of exactly how strong it is.
But which is terrible in that these displays become a bad way to judge how strong or noisy a recording is, and whether you might want to re-record it.
In a perfect world, it wouldn't. But even the fanciest of recorders have an imperfection we call a 'noise floor': noise that is always there, and at a fixed level, no matter what you do.
Very quiet, but still there.
We can talk about engineering details of how and why all day, but much more practically: The moment you press "record" you accepted that blend of input signal and noise. While you can amplify what you have afterwards, that noise comes up right along with the signal -- noise is by nature inseparable.
It turns out that because this floor happens to be fixed, you can make it less relevant before hitting record: Your job is to ensure that microphone's level is well above that noise floor before it is digitised -- but not so high that the signal distorts (It's actually even more complex than that. Audio nerds get the gritty details sort of wrong all the time, but for a given setup, doing the bet you can is fairly easy)
The image on the right has two recordings of the same sound (two identical mics, same recording interface), but one had approximately 45dB less input gain.
What is clearly clearly signal in one, starts falling into the background noise in the other. This recording is actually still viable, but it is recognizably noisier, and the analysis is starting to get distracted by the noise.
...but as mentioned, Praat's "let's do the best with what you have" stance
ends up putting wildly different scaling on all these waveform and spectrogram views.

- record some gentle taps on the microphone but otherwise be quiet.
- View & Edit the sound
- you should see only the taps, and an otherwise quiet waveform
- remove the taps from the sound: select with mouse, Sound → Set selection to zero
- it will suddenly show loud everywhere that isn't the zeroed-out reasons

- undo that, then go to Sound → Sound Scaling, and in particular compare 'by whole' (the default) and 'fixed range'
- 'by whole' (the detault) - looks for the loudest sample in the whole sound
- 'by window' - looks for the loudest part within the currentlyzoomed area (if stereo: max of both channels)
- 'by window and channel' - by maximum used range (if stereo: individually)
- 'fixed height' - seems to be "amount around calculated average", (so if you say 2 you basically see the whole thing - but might hide a DC offset - not that you generally care about that)
- 'fixed range' - seems to be "give min and max (average implied)", (so if you say -1 and 1, you see the whole thing)
If you set Sound → Sound Scaling to "by window", and then scroll around, you will get an effect like the image on the right: no matter how quiet, it will show it in full view. If you move around, it will change the scale as you scroll. The spectrogram does something similar, though is configured separately.
Viewing your recording

Select the Sound, press the View & Edit button.
More basic things you may want to do is zooming in and out, scrolling around, cutting pieces off the edge - mainly see the Edit and Time menus (and maybe learn the keyboard shortcuts)
The green, blue, and red lines and dots on the spectrogram are basic analysis of speech intensity, pitch, and formants.
Spectrogram → Spectrogram settings
- View Range - Normally 0Hz to 5kHz (even when you recorded more) - there's almost nothing interesting to show speech-wise above that, and zooming down to this range makes the pitch movement more visible.
- Window length is about the tradeoff between frequency resolution and time resolution (read up on STFT if you care). The default (0.005s) is a good tradeoff for many tasks.
Higher (0.015s) may sometimes make e.g. separate formants more visible -- yet makes them harder to place in time precisely.
- Dynamic range as a concept relates the loudest to the softest levels. Here, it means "Praat determines the maximum in a recording, and this settles how much lower considered quiet enough to not be worth showing". The default 70dB usually shows most signal and some of the background noise, lowering to 50 will remove noise but also quieter signal, 30 does so fairly aggressively.
Spectrogram → Spectrogram advanced settings
- Maximum is the energy level (you can ignore the units) to treat as the loudest to show (black). By default this field is ignored, because autoscaling handles this (...within a zoom level, so scrolling will make it vary - if you want to inspect in detail, you might care to turn off autoscaling).
- Pre-emphasis considers that the loudness of speech's components (vowels mostly) typically falls approximately -6 dB per increasing octave. If we amplify higher frequencies, just for the visualisation, we can show a wider frequency range with roughly equal visibility. The default is +6dB per octave. Higher than that puts more focus on higher sounds. (identity-gain point at 1000 Hz?)
- Dynamic compression you can think of as someone turning up a volume knob whenever the recording gets quiet.
- this has use if, say, one speaker is significantly quieter than another; chances this will put them at more similar levels
- but if you have strong recordings already, all this really does is around the silences between words - i.e. taking the background noise and making it louder.
- The setting is a fraction, how much to amplify any part towards the level of everything else. You rarely want to make this higher than 0.5 or so (because that's often around 20dB).
https://www.fon.hum.uva.nl/praat/manual/Advanced_spectrogram_settings___.html
Annotating your recording
Create a TextGrid to put useful things on
To create an empty TextGrid of the same length as a given Sound:
- Select Sound
- Find the Button: Annotate → To TextGrid
You can always add tiers later, so you might start with just one:
All tier names: MyName Which of these are point tiers:
All tier names: Mary John bell Which of these are point tiers: bell
...actually mean, read on:
You can have multiple, independent 'tracks' of information, called tiers.
Having is very useful when there distinct things worth noting, e.g. what one speaker says as plain , what another speaker says as plain text, and a beep that they use to alternate speaking. (And later probably also one speaker's phonetic transcription, another's transcription, and so on)
Some of those pieces of information are marked as taking some time (e.g. each word), and sometimes we mark things that are a point in time (e.g. the beep/bell), which is why each tier can be either an
- interval tier
- consists of segments that always covers the whole recording (but many are unlabeled and thereby considered empty)
- inserting something at a time will split the segment that is currently there into two
- you can optionally label each segment (you might e.g. start by marking the silences)
- you can select the segments
- point tier (sometimes 'text tier')
- inserting a point adds a specific points in time
- you can optionally label each point
- you can select the labels
Now that we grasp that, let's say we know there are two people speaking in our recording, and a beep at the start of each response.
Now look at that form again.
- Tier names - space-separated list. Settles the amount of tiers and their tiers at the same time
- Which of these are point tiers? - repeat the names of tiers you want to be point tiers. Any not mentioned will become interval tiers
And we can figure that:
All tier names: Mary John bell Which of these are point tiers: bell
actually means:
- create Mary as an interval tier
- create John as an interval tier
- create bell as a point tier
Editing TextGrid
If you did the above, you have a Sound and a TextGrid of the same time length.
Viewing and editing:
- zooming (CtrlI and CtrlO)
- scrolling (PgUp and PgDn) (...if not zoomed out to be looking at everything)
Editing those annotations
Once it it your task to do more than a little annotation work, it helps to get comfortable with Praat key shortcuts.
A mix of keyboard and mouse seems to be most convenient in that you can click in waveform or spectrogram:
- mouse-click chooses a point in time,
- mouse-drag lets you move an interval or point
...you can do a lot with keyboard only.
See the menu, but some if it includes:
- The selection is a not-yet recorded interval which can be useful
- Up and Down to move the whole thing left or right
- ShiftUp and ShiftDown to move its start
- CtrlUp anbd CtrlDown to move its start
- ...or, in a point tier, you just move a single point, which you can make a real marker with Enter
- AltUp and AltDown base selection on previous or next interval/point in tier
- and then
- Enter to split in current tier
- in an interval tier, we split the current interval at selection start and end (whichever didn't exist already, and can't split two at once)
- in a point tier, makes point at current position
- Ctrl1, Ctrl2 - like Enter, but in specific/other tiers - first tier, second tier, etc...
- Enter to split in current tier
- Altbackspace - remove point / merge interval with previous
Other views/editors
Pitch editor
https://www.fon.hum.uva.nl/praat/manual/PitchEditor.html
How do I...
How do I shorten the length of a textgrid?
Less everyday
What are pulses
Praat scripting notes
Starting from history mechanism
A note on syntax changes
Praat's scripting language has seen changes over the last decades (mostly shifts around the early 2000s and 2010s; since 2015ish or so it has been quite stable), both to add features, but also alter things to increase consistency.
In general, you will probably be happier writing your scripts in the newer style (and scripts generated from history will do this automatically), and the documentation will primarily mention the new style.
...there are many scripts and various tutorials out there written for the older style - or some mix, and because Praat cares specifically about not breaking old scripts, it tends to leaves in whatever old behaviour doesn't conflict with new behaviour.
This is great for old scripts -- but also leads to confusion.
Point is, if you find examples that are not written like you have learned, this is probably the reason.
And if they do not work at all, that is often not your fault -- though it should be pointed out that Praat cares about backwards compatibility a lot, to not break older scripts. Which is exactly why older style still tend to work perfectly fine.
And once you dig into scripting more, you may wish to know about these changes to be able to understand scripts and/or rewrite them.
On ..., :, and nothing
single quotes
Older scripting styles relied more heavily on single quotes (') to do variable substitution and more - basically meaning "don't just hand along the variable, act as if its contents are right here".
Say, if tier is a numeric value containing 1, then
tierNames'tier'$ = "test"
is entirely equivalent to writing
tierNames1$ = "test"
In fact, that particular case let us imitate a dictionary(/associative array) before Praat introduced its own, in that you could do:
for tier from 1 to 5 tierNames'tier'$ = "test" endfor appendInfoLine( tierNames3$ )
In modern praat, we have the functionally equivalent, and somewhat easier to explain:
for tier from 1 to 5 tierNames$[tier] = "test" endfor appendInfoLine( tierNames$[3] )
In modern praat, singlequotes are still there, but you often just see them pasting together strings, e.g.
"'temporaryDirectory$'\test.txt"
but note that this usually is equivalent to a "add strings together" style
temporaryDirectory$+"\test.txt"
Since you can usually do something equivalent, and similarly readable, you don't need them, and if they seem confusing, you can probably avoid them completely.
Deprecated commands
There are some newer commands, where older ones still work (to not break old scripts), but are no longer documented (to not encourage use anymore)
For example appendFile, deleteFile replacing the older fileappend, filedelete (which had some confusing variants)
Data types and structures
Basic types
There are two basic types:
string
- variable names that end with a $ are strings, e.g. test$ = "foo"
- Strings meant literally should be in doublequotes (") (singlequotes are also a thing, but mean something else that you probably can avoid completely in modern praat)
numeric
- floating point (double precision)
- variable with no symbol at the end can be numeric, e.g. test = 4 (or object; see also #Also_reference-able)
- (there is no integer type, but due to the way floating point works, integers store fine up to a very large number)
Structures involving basic types
array structures
- you can mix numeric and string in a single array (yet it is usually less confusing to have it contain just one type)
for i from 1 to 3
square [i] = i * i
endfor
- note that for numeric things, you may prefer vector. (one reason is that the above seems implemented using an associative array, not a list. That is, it in essence declared the three variables square[1], square[2], square[3], and square does not exist. Or rather it can, as a different, unrelated (numeric) variable)
dictionary/hash structures
- which praat seems to consider as pretty similar to arrays, but
- which allows strings for indexing instead of numbers
- created via individual assignment (lists)
- which praat seems to consider as pretty similar to arrays, but
age ["John"] = 36
age ["Babs"] = 39
numeric vectors
- numeric-only, with a fixed size (that you can fetch with size())
- variables that end with a # are (numeric) vectors; functions that end with # return them
- can create e.g. with zero# (10) or e.g. some random numbers
string vectors
- string-only, with a fixed size (that you can fetch with size())
- variables that end with a $# are string vectors vectors, functions that end with $# return them
- can create e.g. with empty$# (10)
- probably less useful and common than numeric vectors
matrices
- two-indexed array of numbers, often thought of as a 2D thing, like a table but that may only contain numbers.
- variables ending with ## are treated with matrices
- can create e.g. with zero## (3,3)
- size cannot be fetched, you have to remember it (verify)
See also:
- https://www.fon.hum.uva.nl/praat/manual/Scripting_5_6__Arrays_and_dictionaries.html
- https://www.fon.hum.uva.nl/praat/manual/Scripting_5_7__Vectors_and_matrices.html
Also reference-able
String operations
Type conversion and formatting
More on vectors
String vectors
More on matrices
On paths
Control, and reuse
Conditions
if i < 20 and word$ = "STIM"
; do this
elsif i = 20 and not word$ = "STIM"
; do that
else
; do this
endif
For numbers: Operators:
a < b less than a > b greater than a <= b less than or equal a >= b greater than or equal a = b equal (== also works, meant for programmers with that habit) a <> b not equal
For strings,
- equal is "same string", not equal is "not same string"
- the others basically answer questions like "if I were to sort these in a per-charcter alphabetic list, would it come before or after"
- e.g. a$ < b$ will tell you if a would precede b
- e.g. a$ >= b$ will tell you if a would come after b or is the same value.
you can use and, or, and not
If you use more than one and/or, and do not immediately understand what operator precedence is, it is recommended you use brackets to make it unambiguous to you and to praat which grouping/order of evaluation you intend.
For example, you would write
(a or b) and c
; or
a or (b and c)
; ...instead of
a or b and c
Repeating things - for, while, and repeat
To repeat for all numbers in a series you can use for:
numFiles = 10 ; often actually read out from somwhere
for n from 1 to numFiles
appendInfoLine: n
endfor
Often more flexibly, you can repeat until a condition is met. There is both:
Loops made from while and repeat (...and note that the only real difference between these two is that repeat always does it at least once (because its condition is at the end, not the start), and while wouldn't)
repeat [statements] until [condition]
and
while [condition] [statements] endwhile
Example: numbers with steps
n = 1
repeat
appendInfoLine: n
n = n + 2
until n > 10
or
n = 10
while n >= 0
appendInfoLine: n
n = n - 3 ; or, slightly shorter: n -= 3
endwhile
Slightly more interesting example(from docs): "roll two six-sided sice until it's two sixes, counting how many rolls that took":
throws = 0
repeat
eyes = randomInteger(1, 6) + randomInteger(1, 6)
throws = throws + 1
until eyes = 12
writeInfoLine: "It took me ", throws, " trials to throw 12 with two dice."
A slightly more applied example: "on an assumed-to-be-interval tier (here 2, you might make it a parameter), given a start position (here 1), keep looking at the next interval until the interval's label is a period", intended as a "skip to end of sentence"
tiernum = 2
i = 1
repeat
label$ = Get label of interval: tiernum, i
appendInfoLine(label$)
i = i + 1
until label$ = "."
See also:
built-in functions
You may find use in some of the built-in functions
Callings things
Functions
Is there a list?
"Is there a list of commands?"
Sort of.
As to functions, most helper functions are listed here
- ...but there are a bunch of further that exist, and are only mentioned in a "relevant to only this part" way (TODO: examples)
As to commands, menu item or object based, are listed in the documentation. (Not always equally helpfully -- say, the documentation for Create Sound as pure tone doesn't tell you about the parameters, but they're obvious if you run it from the UI once (in New → Sound)
For menu commands, there is Praat → Settings → Buttons.
- this lists all visible menu items
- this lists menu commands that are hidden (currently, which starts with those that are hidden by default until you start editing this)
- this also has all your custom additions
However, as mentioned in the : and ... section there are only mostly, not fully the same
(more technically: this is the combination of Praat's default state, plus whatever your Buttons file changes)
For actions commands on Objects, pretty much everything you can do is in the buttons.
Say, how would you know know how to find the label in a tier?
- You would know to look under Query that appears when you select any TextGrid - and e.g. this page lists most of what can appear there, based on the type of object
- It may not be immediatelly clear that for interval tier it's Get label of interval and for point tiers it's the combination of Get nearest index from and Get label of point, but you'll probably manage.
There isn't a single list of just every one of these that exists, though(verify)
Notes:
- Some commands will, when not assigned, output to the info window.
- this is mainly for historical reasons, such as testing that same thing via the UI.
As just mentioned, there are commands that are not anywhere in the UI (hidden commands)
This seems to be done for a mix of reasons, such as
- some things intended to be used by startup scripts, e.g. add/show/hide commands.
- backwards compatibility
- For example, there are now six specific "To Pitch (methodname)..." flavours in the UI which map to same-named column commands, but there is a "To Pitch:" that is hidden because today you would use a specific method, but it's kept around to not break old scripts.(verify)
- not clutter with rarely used things
To see which of the registered actions are shown or hidden, go File → Setting → Buttons
-->
Procedures
Defining procedures
Try something like:
procedure getFormants: formantNum
; get formant Hz value at equally spaced points (timewise)
steps = 10
start = 0.1 ; try to avoid undefined at the start
dur = Get end time
dur = dur - 0.2 ; try to avoid undefined at the end (0.1 from start + 0.1 from end)
# get formants at each timewise quartile (including start and end)
for f from 0 to steps
val = Get value at time: formantNum, start + f*(dur/steps), "hertz", "Linear"
appendInfoLine: formantNum, tab$, fixed$(start + f*(dur/steps), 3), tab$, fixed$(val, 2), tab$
endfor
endproc
Assuming you've created a Formant object from a Sound object, you can now:
clearinfo
appendInfoLine: "frmnt#", tab$, "time" , tab$, "Hz", tab$
@getFormants: 1
@getFormants: 2
@getFormants: 3
@getFormants: 4
(in a real example, you might make more of those things parameters to make the procedure more flexible)
"Do I have to pass arguments?"
Consider the difference between:
procedure playChromatic
semi_mult = 2^(1/12)
freq = frequency
for i in 0 to 12
freq *= semi_mult
Create Sound as pure tone: "note", 1, 0, 0.2, 44100, freq, 0.2, 0.01, 0.01
Play
Remove
endfor
endproc
frequency = 440
@playChromatic
frequency = 416
@playChromatic
|
procedure playChromatic: frequency
semi_mult = 2^(1/12)
freq = frequency
for i in 0 to 12
freq *= semi_mult
Create Sound as pure tone: "note", 1, 0, 0.2, 44100, freq, 0.2, 0.01, 0.01
Play
Remove
endfor
endproc
@playChromatic: 440
@playChromatic: 416
|
Since variables are available everywhere anyway, frequency is also available to it in the first example.
So there is very little functional difference -- it's just that the second makes it a lot clearer which variables are relevant to that procedure call.
For the same "available everywhere" reason, it is easy to leave a variable altered, not like you found it.
The freq = frequency specifically copies the value into another variable (even better would be a local variable, as explained below), to avoid altering the first. Say, had we written it like:
procedure playChromatic
semi_mult = 2^(1/12)
for i in 0 to 12
frequency *= semi_mult
Create Sound as pure tone: "note", 1, 0, 0.2, 44100, freq, 0.2, 0.01, 0.01
Play
Remove
endfor
endproc
frequency = 440
@playChromatic
...then a writeInfoLine( frequency ) after all that would write 880 (plus rounding error), not 440.
-->
Returning stuff?
On scope, and returning, and including
External things
Forms (and script parameters)
Here there is a choice of "do we explain from the perspective of how you use it" or "do we explain it from how praat thinks about it", because both are potentially useful, but they are different stories.
Script form
Script pause
either way: describing individual items
Those lines inside form or beginPause will specify:
- the field name
- controls what is shown
- controls what the variable will be called
- field type
- controls the type that is stored
- may further restrict that value
- default value
Field types
Returns string:
word - string without spaces sentence - string with spaces text - string with spaces (full width with its label on a previous line) infile outfile folder
Returns number
real positive real > 0 integer natural integer >= 1 boolean choice option
Returns numeric vectors:
realvector positivevector integervector naturalvector
Returns nothing:
- comment
Aside from what they return, they also change the way the form presents each item.
The translation from the field name to the variable it will store in is something like:
- seems to preserve only alphanumeric, and remove anything else (notably symbols)
- underscores instead of spaces
- lowercased the first letter (but none of the others)
- removed final parenthesized parts (and spaces that leaves)
Most of them take two variables: variable name and a default value.
Exceptions include option, and the vectors
If you want to see most of them at once, try:
clearinfo
beginPause: "testing all"
comment: "only shown"
real: "rl", "-1.2"
positive: "ps", "1.2"
integer: "int", "0"
natural: "nat", "1"
word: "wrd", "word"
sentence: "snt", "sentence"
text: "txt", "text"
boolean: "bl", 0
choice: "ch", 1
option: "one"
option: "two"
optionmenu: "om", 1
option: "one"
option: "two"
infile: "inf", "in.txt"
outfile: "outf", "out.txt"
folder: "fld", "."
realvector: "rv", "(whitespace-separated)", "1 1.2 1.4"
; commented out because they're the same idea
; and would make the dialog very high:
; positivevector: "pv", "(formula)", "{1,2,3}"
; integervector: "iv", "(whitespace-separated)", "1,2,3"
; naturalvector: "nv", "(formula)", "{1,2,3}"
clicked = endPause: "No", "Button 2", "Yes", 3, 1
appendInfoLine: "clicked: ", clicked
appendInfoLine: ""
appendInfoLine: rl
appendInfoLine: ps
appendInfoLine: int
appendInfoLine: nat
appendInfoLine: ""
appendInfoLine: wrd$
appendInfoLine: snt$
appendInfoLine: txt$
appendInfoLine: ""
appendInfoLine: bl
appendInfoLine: ch
appendInfoLine: ""
appendInfoLine: inf$
appendInfoLine: outf$
appendInfoLine: fld$
appendInfoLine: ""
appendInfoLine: rv#
; appendInfoLine: pv#
; appendInfoLine: iv#
; appendInfoLine: nv#
See also:
https://www.fon.hum.uva.nl/praat/manual/Scripting_6_1__Arguments_to_the_script.html
runScript and forms
If you mention a form in a script, then aside from saying how to presenting a GUI window when run directly), it also defines the way it takes parameters (without a GUI window) if run by something else.
For example, if a script contains:
form FormTitle
real: "x", "1.0"
real: "y", "2.0"
endform
writeInfoLine: x + y
Then running it interactively will pop up that form, while a
runScript: "thatscript.praat", 1.0, 2.0
would put those arguments into x and y (because that is the order of declarations in that form), skip presenting the form, and run the rest of the script.
See also:
Other praat scripts
Differences between using procedures, forms, objects, and scripts
Objects, the list, and selections
Common functions and approaches
Processing a bunch of files
Writing cleaner scripts - style
Comment librally
Indent to guide the eye
Name things well
Avoid long lines
Files
Text files, short text files, binary files
Many data-style objects (including some cases you may never use, like Sound objects) have a structured representation that can be saved as
- a text file
- which contains a little more than necessary but is human-readable.
- a short text file, which basically omits the variable names,
- but is stable enough that parsers should have no trouble (no idea if there were breaking changes over time)
- a binary format, which is a little more compact.
Some thing have futher forms, e.g.
- PitchTier and DurationTier has
- PitchTier/DurationTier Spreadsheet file (not unlike their short text form)
- headerless spreadsheet file (basically TSV)
While the text formats look parseable by yourself, try to avoid that when it is easy because the format has changed. Praat will know how to handle that, but your or other's libraries may break over time.
Logging to the info window
We generally use appendInfo, appendInfoLine - add to window content, without or with going to the next line
- useful if you want to build up a single line of output from distinct parts of your code
People may well clear the info window at the start of a script, often using clearinfo
- (if scripts write out useful things to check later, clearing is not always ideal if you script may ever be called by other scripts, but you/others can worry about that at that time. For quick scripts it can keep the output clean, though.).
There is also writeInfo, writeInfoLine which 'replaces all info window content with this (again, without or with going to the next line)
- (again, overwriting might be more annoying than useful for debug reasons)
You can hand in multiple things to be printed.
For example:
appendInfoLine: minimum, tab$, maximum
is equivalent to:
appendInfo: minimum, tab$, maximum, newline$
See also:
Interactions outside of praat
Running Praat scripts from Praat
Praat running external commands
You running praat commands or praat scripts from the UI or CLI
Other things telling Praat to do things
Things that work on the same files, but do not interact
praatio
parselmouth
How do I use my scripts in praat?
If you want
How do I get those every time I run Praat?
Scripts run from other scripts?
}}
-->
More notes on extending praat
Because history can stand some disentangling
- Manually adding a script in te GUI in a way that shows up in the buttons file
- creating a plugin that contains your stuff
Also, let's try to avoid some relevant confusion.
- This page tries to separate the term 'buttons' (to the right of the object list) from 'menu' (above)
- but keep in mind Praat refers to the buttons to the right of the object lists as a "dynamic menu" (and the buttons to be part of that dynamic menu) (this seems to be part of a history of some confusing naming)
- also note that "action command" is also used for the buttons (especially in that the way for plugins to add buttons is "Add action command")
- Praat uses the term 'dynamic' to mean 'varies with the object selection', and 'fixed' to mean things that do not.
- You might then think that 'dynamic' means 'is a button', and 'fixed' means 'is in the menus',
- and yes, mostly -- except that (only) the Save menu is actually dynamic (and uses a different command to items to it).
- You might then think that 'dynamic' means 'is a button', and 'fixed' means 'is in the menus',
There are some commands that add menu items / action buttons.
Keeping in mind the menu/button and dynamic/fixed details:
| Script command to register this | UI-only near-equivalent | where does it add | comments |
|---|---|---|---|
| Add action command: | Script window, File menu, Add to dynamic menu... -- but note this is permanent | main praat window's buttons | Button can be hidden or grayed out (see details below). |
| Add menu command: | Script-window, File menu, Add to fixed menu... -- but note this is permanent | Existing menus of the main praat window (or Picture window), menus of object-specific editor windows (for TextGrid, Sound, etc)(verify) |
Example: Add action command
For example, make a playreverse.praat containing:
;Play ; remove comment for forward _and_ backward Reverse ; note this alters the existing sound Play Reverse ; two reverses put it back to normal
Now, doing this to to a selection of multiple Sound objects might do something, but not what you intended,
so you decide to require a selection of a single sound:
Add action command: "Sound", 1, "", 0, "", 0, "Reverse play", "Play", 0, "C:\path\to\that\playreverse.praat"
The "Play" in there is the argument for 'After command', which places that button more sensibly: after the existing "Play" button.
This
For example, say we create simplersine.praat just to have fewer fields to fill in:
form: "Simpler sine"
natural: "Hz", "220"
endform
# named variables help clarify what we're doing but aren't necessary
name$ = "sine_'hz'Hz"
channels = 1
start_time = 0
end_time = 1
sine_frequency = 220
sample_rate = 44100
Create Sound from formula: name$, channels, start_time, end_time, sample_rate, "1/2 * sin(2*pi*'hz'*x)"
Then we can add that like:
Add menu command: "Objects", "New", "Create SimplerSine...", "Sound", 1, "C:\path\to\that\simplersine.praat"
(that "Sound",1 tell it to go to the right menu. If we specified "", 0 it would go within New directly which works fine but is a little less organized)
The documentation describes those arguments as roughly:
- Window - "Objects" or "Picture"
- Menu
- for Window="Objects", one of: "Praat", "New", "Open", "Help", (or "Goodies", "Settings", or "Technical", which are now positioned as submenus of Praat) menu (for Objects → Save menu, you need to use Add action command instead, because (only) this menu acually depends on the current selection)
- for Windw="Picture", one of: the "File", "Edit", "Margins", "World", "Select", "Pen", "Font", or "Help".
- Command - label for the menu item
- (you can also add a separator instead of an actual menu item)
- After command - lets you place it in relation to an existing menu item
- Depth - lets you nest menus
- Script - absolute path to the script to run
The Praat preferences folder
Praat's interface starts with some defaults, and can be altered and extended, in a way that is specific to your own user account, because that customization is stored in your own account.
The directory containing that configuration and plugins is at:
- In Windows: %USERPROFILE%\Praat
- In OSX: ~/Library/Preferences/Praat Prefs/
- In Linux: ~/.praat-dir/
This contains:
- Preferences file[4] (exact filename varies between operating systems)
- mostly contains a whole bunch of defaults
- Buttons file[5] (exact filename varies between operating systems)
- Most Praat menu items and buttons are can be hidden (or shown if they are hidden by default), and this is stored here
- You can register new buttons in a way that gets recorded here -- but a lot of the time, the plugin way is cleaner.
- possible plugins, in directories -- see also #Praat_plugin_notes
https://www.fon.hum.uva.nl/praat/manual/preferences_folder.html
Praat plugin notes
Praat plugin
At a lower level, if
- navigate to your praat preferences folder,
- create a directory plugins_name
- with a file named setup.praat
...then that praat script will get run at Praat startup.
For example, if I put the following
beginPause: "This is an annoying window" clicked = endPause: "Okay", "Well done", 2
...inside such a setup.praat, then I will get an annoying startup window every time I start Praat.
In most cases, that setup script only contains commands that add buttons and menus.
(pointing at specific praat scripts to run when clicked, that praat won't touch until you do)
The point would be that these get included at startup
See also:
Plugin manager?
Writing cleaner scripts - structure
Consider "return" values
Consider working on object copies
Fine tuning feedback
Giving useful error messages
Sometimes you expect to occasionally be asked weird things that could lead praat to complain.
You can either work around such a case, or just give a more useful error message, by testing for it.
For example, you can test for a thing you know would go wrong, and stop:
starting_time = 0.23
finishing_time = 0.2
if finishing_time <= starting_time
; stop just as hard as before, but now tell the user _why_
exitScript: "The starting time (", starting_time, ") has to be before the finishing time (", finishing_time, ")"
; (alternatively, you could swap the values and continue)
endif
Checking absolutely everything may be more work than it's worth, but it's often worth if for the more likely mistakes (and for things that do weird things instead of failing).
On undefined
Numeric values can take one special value, that of undefined, and there are cases where
- expressions would evaluate to something that is a problem, e.g. dividing by 0
- commands would reasonably answer that,
- e.g. you querying for values outside the timespan of the object
- e.g. you asking for values only exist for parts, e.g. when you ask a Pitch object for mean frequency in a small timeslice where it did not detect any (e.g. Get mean: 0.0, 0.1, "Hertz")
Sometimes undefined is the sensible answer. Writing out a pitch over time as a table in 0.2sec freagments? Then yes, there are plenty of slices where there is no pitch, so it answering undefined (which prints out as --undefined--) is just correct (though if you're writing out a csv/tsv then maybe you want it to be numeric, e.g. 0 or -1, so that whatever you load that into won't complain)
In other cases, e.g. when you feed values into an expression, this is something it would soon trip over, and you might want to test specifically for undefined (which is itself a special value that you can directly compare against).
selectObject: "Pitch hallo"
meanPitch = Get mean: 0.0, 0.2, "Hertz"
if meanPitch = undefined
; complain about lack of initial pitch, or do nothing, or itentionally replace it with -1
else
; process as usual
endif
(programmers: it's NaN, though in binary files it might be written as infinity)
See also https://www.fon.hum.uva.nl/praat/manual/undefined.html
Removing feedback
While you generally want to see warnings and errors, if you are building a complex interface you might want it to not randomly pop up things.
Say, instead of
Remove
...which would fail if there is nothing to remove, you can write:
nocheck Remove
Instead of
Save as WAV file: "hello.wav"
...which might warn about clipping, you can suppress that warning by writing:
nowarn Save as WAV file: "hello.wav"
Instead of
pitch = To Pitch (raw cc): 0, 75, 600, 15, "no", 0.03, 0.45, 0.01, 0.35, 0.14
...which will pop up a progress window, however brief the work, you can write:
pitch = noprogress To Pitch (raw cc): 0, 75, 600, 15, "no", 0.03, 0.45, 0.01, 0.35, 0.14
https://www.fon.hum.uva.nl/praat/manual/Scripting_6_8__Messages_to_the_user.html
Writing portable scripts
Consider putting useful function in a file you can include
Debugging - when scripts don't do the right thing
You can stare at the entirety of your script for a long time, and not see what's wrong.
Instead, we recommend narrowing it down.
Chances are good that there is a a single step that does something you were not expecting - a variable (or file) will not contain what you think it should. Often, subsequent evaluation will still work, but probably on strange and meaningless values.
So you want the find the first occurence of weirdness.
This still involves some guesswork, but making it a puzzle is often a less frustrating approach.
Think of a particular variable whose value (or expression of values) might be a good indicator of something relevant and wrong. (this may take some experimenting, as the problem may not be exactly the one you hypothesized).
Now appendInfoLine that out.
At multiple spots, e.g. after every time a line alters its contents.
Just printing out a lot of things may feel dumb, but chances are that this will let you quickly narrow down the place it starts to go weird, and chances are the line right above that might lead you to an "ohhhhh."
If you found a problem, know it is very subtle, and anticipate it happening again when working on this script in the future, you could consider putting in little "please check my assumption about the value in this variable".
Assertions in general programming mean "if this evaluates as true, do nothing; if this evaluates as false, complain and stop" (in this case also testing for both false and undefined - see also notes on undefined).
Assertions are little typing. But they do not add a useful message. But they are fairly little typing.
Say, a sound shouldn't ever be completely zero, but if it is it might lead to some weird behaviour, can you can stop that right at the start:
power = Get power assert power > 0
If you also want to test for either 0 or undefined (which can't happen for Get power(verify) but ignore that),
it seems that you may need to write:
assert power != undefined and power > 0
Drawing
Technical notes
Praat and decibels
For almost any hardware recording setup, you cannot know the mic sensitivity sensitivities and all the applied gains and volumes, meaning that you can rarely relate a recorded sound to how the original absolute recording level in dB SPL.
You can only ensure it's at a reasonable level. And often do.
Praat seems to take the approach that "since you ensured a gain for a reasonable level, and that this is a recording of people talking, we're assuming it's at roughly this absolute level".
This is wrong almost by definition.
...but probably by at most 20dB in most voiced speech in most recordings.
Which makes it useful if you have a roughly sense for decibels SPL -- if it reports around 70dB you know it's probably talking, and if you see 30dB it's probably not.
But please be aware that as a result, any measurement (e.g. a third of a Sound's Query > menu) involving Pascals or decibels are somewhat wrong by default.
If you want to know what it corresponds to, you have to do a real-world measurement to correct it by. Using something that reports in absolute units, and in practice the only device you'll find that does so (has been calibrated against something absolute) is a sound pressure level meter (...most phone apps are wrong. Some only a little, but how could you tell?).
(other Praat fields pretend less - e.g. Annotate > To TextGrid (silences)... ask for a negative, "below maximum" dB (so dBFS). For you as the end user this is just as much guessing in the end, but when you gained to -10..-20dB, its default -25dB is not unreasonable, though a little lower may work better)
Plugin and toolkit examples
Praat 'toolkits' aren't really special, but we tend to call plugins that if they are a more interesting, coherent collection of tools.
...which may not always be installed as plugins, just "does a useful thing when you run this .praat"
Praat vocal toolkit
Praat Vocal Toolkit [6]
ProsodyPro notes
http://www.homepages.ucl.ac.uk/~uclyyix/ProsodyPro/
Not a plugin in the sense of 'adds buttons to the interface', more of a script that when run, initiates a semi-automated annotation.