A suite of Praat scripts to determine the open quotient (Oq) and fundamental frequency (f0) based on the EGG waveform.
This set of scripts was originally inspired by my attempts to use the peakdet tools developed by Nathalie Henrich, Cédric Grendrot, and Alexis Michaud. In the course of modifying their code to batch-process large numbers of files, I found myself wishing for a number of other modifications to the general peakdet workflow. Eventually I decided that the easiest solution would be try and implement something similar myself. I chose to work in Praat primarily because it provides a relatively intuitive and easy-to-use graphical interface for editing pulse trains. Praat comes with its own set of problems and I in no way claim it is superior to Matlab for this purpose; however, I have learned a great deal about working with EGG signals in the process of developing these tools.
Update January 2020:
As of version 6.1.04, Praat now includes built-in functionality for working with EGG signals. I haven't looked carefully at it, but it is no doubt worth exploring if you are interested in EGG.
I make no claims that the implementations here are correct, or that they will give the same results as some other set of EGG tools, etc. I developed them primarily for my own use case, and in order to gain a better appreciation for the issues involved.
That having been said, the inverse of the
degg_oq measure computed by praatdet is usually more or less identical to the
CQ_PM measure output by EGGWorks, while the inverse of the
howard_oq measure is typically comparable to the EGGWorks
CQ measure, depending somewhat on the threshold settings. The measures all appear to be highly correlated, so for within-language comparisons, the exact choice is maybe not so critical (as long as it is constant over all items in your analysis).
Comments, suggestions, etc.
Please use the issue tracker.
Praatdet can be cited as follows:
Kirby, James. 2020. Praatdet: Praat-based tools for EGG analysis (v0.3). Retrieved on (date) from https://github.com/kirbyj/praatdet.
praatdet assumes that the user has a number of EGG recordings for which s/he would like to obtain Oq estimates. These recordings may either be part of a stereo file (with e.g. a microphone recording on the other channel) or could be mono EGG files. praatdet determines opening and closing peaks using the dEGG signal, allows the user to add and delete points, permits the user to disregard particular periods (e.g., due to the presence of multiple opening peaks), and writes the output to a comma-delimited text file. Information about the peaks themselves is also saved in the form of a Praat
Presently, Oq is determined using two methods:
- detection of the opening and closing peaks on the derivative of the EGG signal ("dEGG method"), and
- detection of the closing peak using the dEGG signal, and detection of the opening peak using an EGG-based threshold method ("Howard's method").
The physiological correlates of peaks in the dEGG signal were studied extensively by Donald Childers and colleagues (e.g. Childers et al. 1986, 1990). Closing peaks are generally easily identified from the dEGG signal, but opening peaks may be indeterminate (Henrich et al. 2004, Michaud 2004). For this reason, while the maximum positive peak in the dEGG is usually used as an indicator the closing instant, an EGG-based threshold method may be used to determine the opening instant. Howard (1995), following Davies et al. (1986) and others, suggest a point where the negative-going Lx cross an amplitude threshold of 3:7 of that cycle's peak-to-peak amplitude. These are the two methods currently implemented in praatdet, although the choice of the threshold, which is arbitrary, is controlled by the user.
The user may or may not have accompying TextGrids where regions of interest have been indicated. In the interest of file management simplicity, praatdet keeps just one (potentially user-corrected) PointProcess per file, but permits the user to only annotate/display Oq values for a particular region. For example, you may have a file containing a single word, segmented into onset, nucleus, and coda. In the first instance you may just want to determine Oq for the nucleus, but perhaps later you decide you are interested in the nasal coda as well. Since a single PointProcess object is associated with each EGG file, you can edit the detected peaks for the coda region while retaining your previous edits of the nucleus. For more details, see the EXAMPLES document.
From the user's perspective, the most important script is
praatdet.praat. All other scripts simply encapsulate different aspects of the workflow.
praatdet assumes your filenames contain useful metadata about the token (e.g. speaker code, gender, token number, etc.). These will be parsed based on a user-defined delimiter and included in the output file as generic columns named var1, var2....
It is assumed that tasks such as normalization will happen in a different environment (e.g. R). praatdet is narrowly focused on annotating/editing a pulse train object, and extracting Oq values based on it.
praatdet requires Praat 6 or later. It has been tested with 6.0.24 on both macOS 10.12.3 and Windows 7. Find the latest version at http://www.praat.org.
praatdet.praatscript from within Praat. This will bring up a dialog window prompting you for
- the location of your EGG files
- the name of your output file
- the channel of your audio files containing the EGG signal
- which file in the list you wish to begin processing from
- a delimiter separating meaningful elements of your filenames
If you are using an existing TextGrid to process just a portion of your files, you can also specify
- a tier of interest
- a label of interest on this tier
- an interval number of interest
If you specify both an interval label and an interval number, the number will take precedence, unless it is left as 0 (zero), the default. To process the entire file, set
intervalLabelto be blank and
The next options screen prompts you for
- the minimum and maximum f0 thresholds used by Praat's autocorrelation-based pitch analysis algorithm
- a parameter
kwhich determines the size of the smoothing window (see Smoothing below)
- a threshold for Howard's method (default: 3/7ths)
- the pass frequency for the high-pass filter to remove the Gx signal component (default: 75 Hz)
- the filter cutoff smooth (default: 20 Hz)
- an option to manually edit points and periods
manualCheckis left unchecked, praatdet will simply parse all files in the directory, find Oq values, and write them to an output file. This means that semi-automatic, hand-corrected pitch period detection can be performed, possibly for the entire file, and then Oq values can be extracted for different subsets of each file.
If manually checking points and periods, praatdet will now present the user with a plot of the Oq values for the region of interest, estimated using both the dEGG and Howard methods, and a prompt asking "Do you want to manually add/delete any points?"
In general, the dEGG and Howard estimates of Oq should be similar. If they are not, or if the values are extremely close to 0 or 1, this usually means that either the first or the last peak detected was not a closing peak. To check this, click
Continuein the Pause: Manual check options box. This will bring up an
Editwindow showing the dEGG signal and the detected points. The first and last points should both be positive peaks! This is because praatdet measures periods from closing peak to closing peak. It could have been done the other way, but it wasn't. UPDATE AUGUST 2020: some new logic has been added to version 0.3 which should avoid this problem in most cases, and make automated processing safer.
Note that the
Editwindow will automatically zoom in to the region of interest, and that this corresponds to the plot in the
To add a point, put your cursor where you would like to add a point and select Add point at cursor from the Point menu (or use the keyboard shortcut). To delete a point or points, select them using the mouse, then choose Remove point(s) from the Point menu (or use the keyboard shortcut).
When you are finished, click
Continuein the Pause: stop or continue dialog box.
The Oq estimates will now be re-drawn in the
Picturewindow, and you will have the option to repeat step 3. If the estimates still look incorrect or differ wildly from one another, you may have missed a point or points; repeat step 3. If the estimates look OK, enter 0 as the value for
You will now have the opportunity to remove individual periods (not points) from consideration, à la peakdet. You may wish to do this if, for example, you decide that the values at the edges of the utterance are invalid, or if you noticed periods containing double peaks in steps 3-4. I recommend inserting points (or leaving the ones that Praat finds) for double peaks, and then removing the entire period at this step. The advantage of this workflow is that the output file will record the time and location of this period, but will not record Oq values for it. This is a simple way of indicating the existence of a double peak.
To remove periods, enter the period numbers, separated by spaces, in the dialog box. The
Picturedisplay will then update to reflect your changes. Be careful; there is no 'undo' for this procedure, short of processing the file all over again! When you are finished, or if you do not wish to remove any periods, leave the dialog box blank, and click
The Oq values as determined by both methods will now be appended to the output file, and steps 1-6 will be repeated for the next EGG file in the directory.
For more details and examples of common issues, see the EXAMPLES document.
Output file format
The output file (named
egg_out.txt by default) is a comma-delimted text file with a header row plus one row per period per file. Since at present praatdet only computes two Oq measures (dEGG and Howard's method), the header looks like
var1,var2... columns represent variables parsed from your filename. The remaining rows of the output file will look like
Columns 2-5 contain the delimited information contained in the filename. In this example, these columns contain the word token, the context (isolation), the repetition (1), and the speaker code. The next column contains the TextGrid interval label; if the entire file was processed, this will be empty. Following this is the period number (starting at 1, relative to the region specified by the interval label), the start and end times of the period and the f0 (as determined from the location of the dEGG closing peaks), and the Oq measurements. Other measures, such as speed quotient, could be added and appended in a similar fashion.
Behind the scenes
Peak detection proceeds in three stages:
First, take the derivative and use this to find closing peaks:
Formula... self [col+1] - self [col] To PointProcess (periodic, peaks)... min max Yes No
with user-defined min and max. This includes maxima, but not minima, and so finds the closing peaks. These are the most reliable. We could do this on the raw signal or on a smoothed signal; for more on smoothing see here.
Next, try to find the opening peaks:
To PointProcess (periodic, peaks)... min max No Yes
For more details of Praat's
To PointProcess (periodic, peaks)....algorithm, see here.
In order to ensure that the first peak is always a closing peak, the times of the first points in each PointProcess are compared, and the first point of the
openingPointProcess is deleted if it occurs before the first point in the
These are then combined into a single PointProcess object:
select PointProcess 'name$'_degg_opening plus PointProcess 'name$'_degg_closing Union
which is then used to subsequent analysis; this is also the object that is ultimately saved.
One issue with using the Praat
PointProcess is that the time window within which points are searched for is fixed. If this were modified, it could potentially lead to a reduction in errors involving multiple opening peaks. As of version 0.3, praatdet attempts to mitigate this by the inclusion of some logic to remove orphan peaks, so that before the user see the PointProcess, it should consist exclusively of positive-negative peak pairs that are not too temporally distant.
Both the Lx and dEGG signals can be smoothed by calculating a linearly weighted symmetric moving average
The smoothed value for a particular time point
It is possible to efficiently compute these as convolutions but here I just do it the clunky way, constructing an equation like the above based on the user-defined value of
Both the Lx and dEGG signals are smoothed using the same function with the same window.
Howard's method (encapsulated in the file
howard.praat) determines the glottal opening instant by means of a thresholding method.
First we delimit the period of interest, found using the dEGG closing peaks:
select PointProcess 'name$'_degg_both .period_start = Get time from index... .i .period_end = Get time from index... .i+2
Then, each period is extracted and normalized:
Extract part... .period_start .period_end rectangular 1 yes # normalize this period .min = Get minimum... 0 0 Sinc70 .max = Get maximum... 0 0 Sinc70 Formula... (self[col]-.min) / (.max-.min)
Next, loop through the sample, setting values below the threshold to zero:
.nsamp = Get number of samples for .k from 1 to .nsamp .si = Get value at sample number... eggChan .k if .si < threshold ## set all values below threshold to zero Set value at sample number... 1 .k 0 endif endfor
The open period will necessarily start at a point following the peak. We can find this by first determining the peak
.local_maxand find the time of the
.first_zerothat follows it, determine the sample number
.zero_sampcorresponding to the preceding timepoint:
.local_max = Get time of maximum... 0 0 Sinc70 .first_zero = Get time of minimum... .local_max 0 Sinc70 # back up one sample for maxmimum explicitness .zero_samp = Get sample number from time... .first_zero .open_start = Get time from sample number... .zero_samp-1
Calling from the command line
If you would like to script praatdet from the shell, use
shelldet.praat, which collapses both argument windows into a single window. (If all arguments are included in a single form, which is what is needed for Praat to process all command line arguments when called from the shell due to the single form requirement, the resulting form window will be too big for most screens (since resizing the window is not possible).
In the Oq plot, the first and last values overlap with the plot border. I'm not sure how to fix this beyond padding the matrices on either end, which means copying the matrices, etc.
In the Oq plot, the x axis becomes unreadble for large files, and is uninformative for small files, due to the fixed value for distance of
Marks bottom every...
Unlike peakdet, praatdet has nothing intelligent to say about multiple peaks.
I have tried to encapsulate different components of the script as functions (procedures). Praat does not have 'real' functions, so be aware that local variables (e.g.
.formula$) are globally available.
Childers, D. G., Hicks, D. M., Moore, G. P., and Alsaka, Y. A. (1986). “A model for vocal fold vibratory motion, contact area, and the electroglottogram,” J. Acous. Soc. Am. 80, 1309–1320.
Childers, D. G., Hicks, D. M., Moore, G. P., Eskenazi, L., and Lalwani, A. L. (1990). “Electroglottography and vocal fold physiology,” J. Speech Hear. Res. 33, 245–254.
Henrich N., d'Alessandro C., Castellengo M. and Doval B.. (2004). "On the use of the derivative of electroglottographic signals for characterization of nonpathological voice phonation", J. Acous. Soc. Am. 115(3), 1321-1332.
Michaud, A. (2004). “Final consonants and glottalization: new perspectives from Hanoi Vietnamese,” Phonetica 61, 119–146.