/* praat_Fon.c
 *
 * Copyright (C) 1992-2006 Paul Boersma
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * pb 2006/04/16
 */

#include "praat.h"

#include "AmplitudeTier.h"
#include "AmplitudeTierEditor.h"
#include "Cochleagram_and_Excitation.h"
#include "Distributions_and_Strings.h"
#include "Distributions_and_Transition.h"
#include "DurationTierEditor.h"
#include "Excitation_to_Formant.h"
#include "FormantTier.h"
#include "Harmonicity.h"
#include "IntensityTier.h"
#include "IntensityTierEditor.h"
#include "LongSound.h"
#include "Ltas.h"
#include "ManipulationEditor.h"
#include "Matrix_and_Pitch.h"
#include "Matrix_and_PointProcess.h"
#include "Matrix_and_Polygon.h"
#include "PairDistribution.h"
#include "ParamCurve.h"
#include "Pitch_Intensity.h"
#include "Pitch_to_PitchTier.h"
#include "Pitch_to_PointProcess.h"
#include "Pitch_to_Sound.h"
#include "PitchEditor.h"
#include "PitchTier_to_PointProcess.h"
#include "PitchTier_to_Sound.h"
#include "PitchTierEditor.h"
#include "PointEditor.h"
#include "PointProcess_and_Sound.h"
#include "Praat_tests.h"
#include "Sound_and_Spectrogram.h"
#include "Sound_and_Spectrum.h"
#include "SpectrogramEditor.h"
#include "Spectrum_and_Spectrogram.h"
#include "Spectrum_to_Excitation.h"
#include "Spectrum_to_Formant.h"
#include "SpectrumEditor.h"
#include "SpellingChecker.h"
#include "Table.h"
#include "TextGrid.h"
#include "VocalTract.h"
#include "VoiceAnalysis.h"
#include "WordList.h"

static const char *STRING_FROM_TIME_SECONDS = "left Time range (s)";
static const char *STRING_TO_TIME_SECONDS = "right Time range (s)";
static const char *STRING_FROM_TIME = "left Time range";
static const char *STRING_TO_TIME = "right Time range";
static const char *STRING_FROM_FREQUENCY_HZ = "left Frequency range (Hz)";
static const char *STRING_TO_FREQUENCY_HZ = "right Frequency range (Hz)";
static const char *STRING_FROM_FREQUENCY = "left Frequency range";
static const char *STRING_TO_FREQUENCY = "right Frequency range";

/***** Common dialog contents. *****/

void praat_dia_timeRange (Any dia);
void praat_dia_timeRange (Any dia) {
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
}
void praat_get_timeRange (Any dia, double *tmin, double *tmax);
void praat_get_timeRange (Any dia, double *tmin, double *tmax) {
	*tmin = GET_REAL (STRING_FROM_TIME);
	*tmax = GET_REAL (STRING_TO_TIME);
}
int praat_get_frequencyRange (Any dia, double *fmin, double *fmax);
int praat_get_frequencyRange (Any dia, double *fmin, double *fmax) {
	*fmin = GET_REAL (STRING_FROM_FREQUENCY);
	*fmax = GET_REAL (STRING_TO_FREQUENCY);
	REQUIRE (*fmax > *fmin, "Maximum frequency must be greater than minimum frequency.")
	return 1;
}
static void dia_Vector_getExtremum (Any dia) {
	Any radio;
	praat_dia_timeRange (dia);
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
}
static void dia_Vector_getValue (Any dia) {
	Any radio;
	REAL ("Time (s)", "0.5")
	RADIO ("Interpolation", 3)
	RADIOBUTTON ("Nearest")
	RADIOBUTTON ("Linear")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
}
static void dia_pitchUnits (Any dia) {
	Any radio;
	OPTIONMENU ("Unit", 1)
		OPTIONS_ENUM (ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, itext, Function_UNIT_TEXT_MENU),
			Pitch_UNIT_min, Pitch_UNIT_max)
}

static int getTminTmaxFminFmax (Any dia, double *tmin, double *tmax, double *fmin, double *fmax) {
	*tmin = GET_REAL (STRING_FROM_TIME);
	*tmax = GET_REAL (STRING_TO_TIME);
	*fmin = GET_REAL (STRING_FROM_FREQUENCY);
	*fmax = GET_REAL (STRING_TO_FREQUENCY);
	REQUIRE (*fmax > *fmin, "Maximum frequency must be greater than minimum frequency.")
	return 1;
}
#define GET_TMIN_TMAX_FMIN_FMAX \
	double tmin, tmax, fmin, fmax; \
	if (! getTminTmaxFminFmax (dia, & tmin, & tmax, & fmin, & fmax)) return 0;

/***** Two auxiliary routines, exported. *****/

int praat_Fon_formula (Any dia);
int praat_Fon_formula (Any dia) {
	int IOBJECT;
	WHERE_DOWN (SELECTED) {
		Matrix_formula (OBJECT, GET_STRING ("formula"), NULL);
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
	return 1;
}

Graphics Movie_create (const char *title, int width, int height);
Graphics Movie_create (const char *title, int width, int height) {
	static Graphics graphics;
	static Widget shell, dialog, drawingArea;
	if (! graphics) {
		dialog = XmCreateFormDialog (praat.topShell, "Movie", NULL, 0);
		shell = XtParent (dialog);
		drawingArea = XmCreateDrawingArea (dialog, "movingArea", NULL, 0);
		XtVaSetValues (shell, XmNx, 100, XmNy, 100, XmNtitle, title, XmNwidth, width + 2, XmNheight, height + 2,
			XmNdeleteResponse, XmUNMAP, NULL);
		XtVaSetValues (drawingArea, XmNwidth, width, XmNheight, height, NULL);
		XtManageChild (drawingArea);
		XtManageChild (dialog);
		graphics = Graphics_create_xmdrawingarea (drawingArea);
	}
	XtVaSetValues (XtParent (dialog), XmNtitle, title, XmNwidth, width + 2, XmNheight, height + 2, NULL);
	XtVaSetValues (drawingArea, XmNwidth, width, XmNheight, height, NULL);
	XtManageChild (dialog);
	XMapRaised (XtDisplay (shell), XtWindow (shell));
	return graphics;
}

/***** AMPLITUDETIER *****/

FORM (AmplitudeTier_addPoint, "Add one point", "AmplitudeTier: Add point...")
	REAL ("Time (s)", "0.5")
	REAL ("Sound pressure (Pa)", "0.8")
	OK
DO
	WHERE (SELECTED) {
		if (! RealTier_addPoint (OBJECT, GET_REAL ("Time"), GET_REAL ("Sound pressure"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (AmplitudeTier_create, "Create empty AmplitudeTier", NULL)
	WORD ("Name", "empty")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	OK
DO
	double startTime = GET_REAL ("Start time"), endTime = GET_REAL ("End time");
	REQUIRE (endTime > startTime, "End time must be greater than start time.")
	if (! praat_new (AmplitudeTier_create (startTime, endTime), GET_STRING ("Name"))) return 0;
END

DIRECT (AmplitudeTier_downto_PointProcess)
	EVERY_TO (AnyTier_downto_PointProcess (OBJECT))
END

DIRECT (AmplitudeTier_downto_TableOfReal)
	EVERY_TO (AmplitudeTier_downto_TableOfReal (OBJECT))
END

DIRECT (AmplitudeTier_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit an AmplitudeTier from batch.");
	} else {
		Sound sound = NULL;
		WHERE (SELECTED)
			if (CLASS == classSound) sound = OBJECT;
		WHERE (SELECTED && CLASS == classAmplitudeTier)
			if (! praat_installEditor (AmplitudeTierEditor_create (praat.topShell, FULL_NAME,
				OBJECT, sound, TRUE), IOBJECT)) return 0;
	}
END

FORM (AmplitudeTier_formula, "AmplitudeTier: Formula", "AmplitudeTier: Formula...")
	LABEL ("", "# ncol = the number of points")
	LABEL ("", "for col from 1 to ncol")
	LABEL ("", "   # x = the time of the colth point, in seconds")
	LABEL ("", "   # self = the value of the colth point, in Pascal")
	LABEL ("", "   self = `formula'")
	LABEL ("", "endfor")
	TEXTFIELD ("formula", "- self ; upside down")
	OK
DO
	WHERE_DOWN (SELECTED) {
		RealTier_formula (OBJECT, GET_STRING ("formula"), NULL);
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

static void dia_AmplitudeTier_getRangeProperty (Any dia) {
	REAL ("Shortest period (s)", "0.0001")
	REAL ("Longest period (s)", "0.02")
	POSITIVE ("Maximum amplitude factor", "1.6")
}

FORM (AmplitudeTier_getShimmer_local, "AmplitudeTier: Get shimmer (local)", "AmplitudeTier: Get shimmer (local)...")
	dia_AmplitudeTier_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (AmplitudeTier_getShimmer_local (ONLY (classAmplitudeTier),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (AmplitudeTier_getShimmer_local_dB, "AmplitudeTier: Get shimmer (local, dB)", "AmplitudeTier: Get shimmer (local, dB)...")
	dia_AmplitudeTier_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (AmplitudeTier_getShimmer_local_dB (ONLY (classAmplitudeTier),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (AmplitudeTier_getShimmer_apq3, "AmplitudeTier: Get shimmer (apq3)", "AmplitudeTier: Get shimmer (apq3)...")
	dia_AmplitudeTier_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (AmplitudeTier_getShimmer_apq3 (ONLY (classAmplitudeTier),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (AmplitudeTier_getShimmer_apq5, "AmplitudeTier: Get shimmer (apq5)", "AmplitudeTier: Get shimmer (apq5)...")
	dia_AmplitudeTier_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (AmplitudeTier_getShimmer_apq5 (ONLY (classAmplitudeTier),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (AmplitudeTier_getShimmer_apq11, "AmplitudeTier: Get shimmer (apq11)", "AmplitudeTier: Get shimmer (apq11)...")
	dia_AmplitudeTier_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (AmplitudeTier_getShimmer_apq11 (ONLY (classAmplitudeTier),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (AmplitudeTier_getShimmer_dda, "AmplitudeTier: Get shimmer (dda)", "AmplitudeTier: Get shimmer (dda)...")
	dia_AmplitudeTier_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (AmplitudeTier_getShimmer_dda (ONLY (classAmplitudeTier),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum amplitude factor")), NULL);
END

/*FORM (AmplitudeTier_getValueAtTime, "Get AmplitudeTier value", "AmplitudeTier: Get value at time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (RealTier_getValueAtTime (ONLY_OBJECT, GET_REAL ("Time")), "Pa");
END
	
FORM (AmplitudeTier_getValueAtIndex, "Get AmplitudeTier value", "AmplitudeTier: Get value at index...")
	INTEGER ("Point number", "10")
	OK
DO
	Melder_informationReal (RealTier_getValueAtIndex (ONLY_OBJECT, GET_INTEGER ("Point number")), "Pa");
END*/

DIRECT (AmplitudeTier_help) Melder_help ("AmplitudeTier"); END

FORM (AmplitudeTier_to_IntensityTier, "AmplitudeTier: To IntensityTier", "AmplitudeTier: To IntensityTier...")
	REAL ("Threshold (dB)", "-10000.0")
	OK
DO
	EVERY_TO (AmplitudeTier_to_IntensityTier (OBJECT, GET_REAL ("Threshold")))
END

FORM (AmplitudeTier_to_Sound, "AmplitudeTier: To Sound (pulse train)", "AmplitudeTier: To Sound (pulse train)...")
	POSITIVE ("Sampling frequency (Hz)", "44100")
	NATURAL ("Interpolation depth (samples)", "2000")
	OK
DO
	EVERY_TO (AmplitudeTier_to_Sound (OBJECT, GET_REAL ("Sampling frequency"), GET_INTEGER ("Interpolation depth")))
END

DIRECT (info_AmplitudeTier_Sound_edit)
	Melder_information ("To include a copy of a Sound in your AmplitudeTier editor:\n"
		"   select an AmplitudeTier and a Sound, and click \"Edit\".");
END

/***** AMPLITUDETIER & SOUND *****/

DIRECT (Sound_AmplitudeTier_multiply)
	Sound sound = ONLY (classSound);
	if (! praat_new (Sound_AmplitudeTier_multiply (sound, ONLY (classAmplitudeTier)), "%s_amp", sound -> name)) return 0;
END

/***** COCHLEAGRAM *****/

FORM (Cochleagram_difference, "Cochleagram difference", 0)
	praat_dia_timeRange (dia);
	OK
DO
	Data coch1 = NULL, coch2 = NULL;
	WHERE (SELECTED && CLASS == classCochleagram) { if (coch1) coch2 = OBJECT; else coch1 = OBJECT; }
	Melder_informationReal (Cochleagram_difference ((Cochleagram) coch1, (Cochleagram) coch2,
			GET_REAL ("left Time range"), GET_REAL ("right Time range")), "Hertz (root-mean-square)");
END

FORM (Cochleagram_formula, "Cochleagram Formula", "Cochleagram: Formula...")
	LABEL ("label", "`x' is time in seconds, `y' is place in Bark")
	LABEL ("label", "y := y1; for row := 1 to nrow do { x := x1; "
		"for col := 1 to ncol do { self [row, col] := `formula' ; x := x + dx } y := y + dy }")
	TEXTFIELD ("formula", "self")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

DIRECT (Cochleagram_help) Melder_help ("Cochleagram"); END

DIRECT (Cochleagram_movie)
	Graphics g = Movie_create ("Cochleagram movie", 300, 300);
	WHERE (SELECTED) Matrix_movie (OBJECT, g);
END

FORM (Cochleagram_paint, "Paint Cochleagram", 0)
	praat_dia_timeRange (dia);
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Cochleagram_paint (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Garnish")))
END

FORM (Cochleagram_to_Excitation, "From Cochleagram to Excitation", 0)
	REAL ("Time (s)", "0.0")
	OK
DO
	EVERY_TO (Cochleagram_to_Excitation (OBJECT, GET_REAL ("Time")))
END

DIRECT (Cochleagram_to_Matrix)
	EVERY_TO (Cochleagram_to_Matrix (OBJECT))
END

/***** DISTRIBUTIONS *****/

DIRECT (Distributionses_add)
	Collection me = Collection_create (classDistributions, 10);
	if (! me) return 0;
	WHERE (SELECTED)
		if (! Collection_addItem (me, OBJECT)) { my size = 0; forget (me); return 0; }
	if (! praat_new (Distributions_addMany (me), "added")) {
		my size = 0; forget (me); return 0;
	}
	my size = 0; forget (me);
END

FORM (Distributionses_getMeanAbsoluteDifference, "Get mean difference", 0)
	NATURAL ("Column number", "1")
	OK
DO
	Distributions me = NULL, thee = NULL;
	WHERE (SELECTED) { if (me) thee = OBJECT; else me = OBJECT; }
	Melder_informationReal (Distributionses_getMeanAbsoluteDifference (me, thee, GET_INTEGER ("Column number")), NULL);
END

FORM (Distributions_getProbability, "Get probability", 0)
	NATURAL ("Column number", "1")
	SENTENCE ("String", "")
	OK
DO
	Melder_informationReal (Distributions_getProbability (ONLY_OBJECT,
		GET_STRING ("String"), GET_INTEGER ("Column number")), NULL);
END

DIRECT (Distributions_help) Melder_help ("Distributions"); END

FORM (Distributions_to_Strings, "To Strings", 0)
	NATURAL ("Column number", "1")
	NATURAL ("Number of strings", "1000")
	OK
DO
	EVERY_TO (Distributions_to_Strings (OBJECT, GET_INTEGER ("Column number"), GET_INTEGER ("Number of strings")))
END

FORM (Distributions_to_Strings_exact, "To Strings (exact)", 0)
	NATURAL ("Column number", "1")
	OK
DO
	EVERY_TO (Distributions_to_Strings_exact (OBJECT, GET_INTEGER ("Column number")))
END

FORM (Distributions_to_Transition, "To Transition", 0)
	NATURAL ("Environment", "1")
	BOOLEAN ("Greedy", 1)
	OK
DO
	if (! praat_new (Distributions_to_Transition (ONLY_OBJECT, NULL, GET_INTEGER ("Environment"),
		NULL, GET_INTEGER ("Greedy")), NULL)) return 0;
END

FORM (Distributions_to_Transition_adj, "To Transition", 0)
	NATURAL ("Environment", "1")
	BOOLEAN ("Greedy", 1)
	OK
DO
	if (! praat_new (Distributions_to_Transition (ONLY (classDistributions), NULL,
		GET_INTEGER ("Environment"), ONLY (classTransition), GET_INTEGER ("Greedy")), NULL)) return 0;
END

FORM (Distributions_to_Transition_noise, "To Transition (noise)", 0)
	NATURAL ("Environment", "1")
	BOOLEAN ("Greedy", 1)
	OK
DO
	Distributions underlying = NULL, surface = NULL;
	WHERE (SELECTED) { if (underlying) surface = OBJECT; else underlying = OBJECT; }
	if (! praat_new (Distributions_to_Transition (underlying, surface, GET_INTEGER ("Environment"),
		NULL, GET_INTEGER ("Greedy")), NULL)) return 0;
END

FORM (Distributions_to_Transition_noise_adj, "To Transition (noise)", 0)
	NATURAL ("Environment", "1")
	BOOLEAN ("Greedy", 1)
	OK
DO
	Distributions underlying = NULL, surface = NULL;
	WHERE (SELECTED && CLASS == classDistributions) { if (underlying) surface = OBJECT; else underlying = OBJECT; }
	if (! praat_new (Distributions_to_Transition (underlying, surface, GET_INTEGER ("Environment"),
		ONLY (classTransition), GET_INTEGER ("Greedy")), NULL)) return 0;
END

/***** DISTRIBUTIONS & TRANSITION *****/

DIRECT (Distributions_Transition_map)
	if (! praat_new (Distributions_Transition_map (ONLY (classDistributions), ONLY (classTransition)),
		"surface")) return 0;
END

/***** DURATIONTIER *****/

FORM (DurationTier_addPoint, "Add one point to DurationTier", "DurationTier: Add point...")
	REAL ("Time (s)", "0.5")
	REAL ("Relative duration", "1.5")
	OK
DO
	WHERE (SELECTED) {
		if (! RealTier_addPoint (OBJECT, GET_REAL ("Time"), GET_REAL ("Relative duration"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (DurationTier_create, "Create empty DurationTier", "Create DurationTier...")
	WORD ("Name", "empty")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	OK
DO
	double startTime = GET_REAL ("Start time"), endTime = GET_REAL ("End time");
	REQUIRE (endTime > startTime, "End time must be greater than start time.")
	if (! praat_new (DurationTier_create (startTime, endTime), GET_STRING ("Name"))) return 0;
END

DIRECT (DurationTier_downto_PointProcess)
	EVERY_TO (AnyTier_downto_PointProcess (OBJECT))
END

DIRECT (DurationTier_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit a DurationTier from batch.");
	} else {
		Sound sound = NULL;
		WHERE (SELECTED)
			if (CLASS == classSound) sound = OBJECT;
		WHERE (SELECTED && CLASS == classDurationTier)
			if (! praat_installEditor (DurationTierEditor_create (praat.topShell, FULL_NAME,
				OBJECT, sound, TRUE), IOBJECT)) return 0;
	}
END

FORM (DurationTier_formula, "DurationTier: Formula", "DurationTier: Formula...")
	LABEL ("", "# ncol = the number of points")
	LABEL ("", "for col from 1 to ncol")
	LABEL ("", "   # x = the time of the colth point, in seconds")
	LABEL ("", "   # self = the value of the colth point, in relative units")
	LABEL ("", "   self = `formula'")
	LABEL ("", "endfor")
	TEXTFIELD ("formula", "self * 1.5 ; slow down")
	OK
DO
	WHERE_DOWN (SELECTED) {
		RealTier_formula (OBJECT, GET_STRING ("formula"), NULL);
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (DurationTier_getTargetDuration, "Get target duration", 0)
	REAL ("left Time range (s)", "0.0")
	REAL ("right Time range (s)", "1.0")
	OK
DO
	Melder_informationReal (RealTier_getArea (ONLY_OBJECT,
		GET_REAL ("left Time range"), GET_REAL ("right Time range")), "seconds");
END

FORM (DurationTier_getValueAtTime, "Get DurationTier value", "DurationTier: Get value at time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (RealTier_getValueAtTime (ONLY_OBJECT, GET_REAL ("Time")), NULL);
END
	
FORM (DurationTier_getValueAtIndex, "Get DurationTier value", "Duration: Get value at index...")
	INTEGER ("Point number", "10")
	OK
DO
	Melder_informationReal (RealTier_getValueAtIndex (ONLY_OBJECT, GET_INTEGER ("Point number")), NULL);
END

DIRECT (DurationTier_help) Melder_help ("DurationTier"); END

DIRECT (info_DurationTier_Sound_edit)
	Melder_information ("To include a copy of a Sound in your DurationTier editor:\n"
		"   select a DurationTier and a Sound, and click \"Edit\".");
END

/***** EXCITATION *****/

FORM (Excitation_draw, "Draw Excitation", 0)
	REAL ("From frequency (Bark)", "0")
	REAL ("To frequency (Bark)", "25.6")
	REAL ("Minimum (phon)", "0")
	REAL ("Maximum (phon)", "100")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Excitation_draw (OBJECT, GRAPHICS,
		GET_REAL ("From frequency"), GET_REAL ("To frequency"),
		GET_REAL ("Minimum"), GET_REAL ("Maximum"), GET_INTEGER ("Garnish")))
END

FORM (Excitation_formula, "Excitation Formula", "Excitation: Formula...")
	LABEL ("label", "`x' is the place in Bark, `col' is the bin number")
	LABEL ("label", "x := 0;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
	TEXTFIELD ("formula", "self")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

DIRECT (Excitation_getLoudness)
	Melder_informationReal (Excitation_getLoudness (ONLY (classExcitation)), "sones");
END

DIRECT (Excitation_help) Melder_help ("Excitation"); END

FORM (Excitation_to_Formant, "From Excitation to Formant", 0)
	NATURAL ("Maximum number of formants", "20")
	OK
DO
	EVERY_TO (Excitation_to_Formant (OBJECT, GET_INTEGER ("Maximum number of formants")))
END

DIRECT (Excitation_to_Matrix)
	EVERY_TO (Excitation_to_Matrix (OBJECT))
END

/***** FORMANT *****/

DIRECT (Formant_downto_FormantTier)
	EVERY_TO (Formant_downto_FormantTier (OBJECT))
END

FORM (Formant_drawSpeckles, "Draw Formant", "Formant: Draw speckles...")
	praat_dia_timeRange (dia);
	POSITIVE ("Maximum frequency (Hz)", "5500.0")
	REAL ("Dynamic range (dB)", "30.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Formant_drawSpeckles (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_REAL ("Maximum frequency"),
		GET_REAL ("Dynamic range"), GET_INTEGER ("Garnish")))
END

FORM (Formant_drawTracks, "Draw formant tracks", "Formant: Draw tracks...")
	praat_dia_timeRange (dia);
	POSITIVE ("Maximum frequency (Hz)", "5500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Formant_drawTracks (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_REAL ("Maximum frequency"),
		GET_INTEGER ("Garnish")))
END

FORM (Formant_formula_bandwidths, "Formant: Formula (bandwidths)", "Formant: Formula (bandwidths)...")
	LABEL ("", "row is formant number, col is frame number: for row from 1 to nrow do for col from 1 to ncol do B (row, col) :=")
	TEXTFIELD ("formula", "self / 2 ; sharpen all peaks")
	OK
DO
	WHERE (SELECTED) {
		if (! Formant_formula_bandwidths (OBJECT, GET_STRING ("formula"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (Formant_formula_frequencies, "Formant: Formula (frequencies)", "Formant: Formula (frequencies)...")
	LABEL ("", "row is formant number, col is frame number: for row from 1 to nrow do for col from 1 to ncol do F (row, col) :=")
	TEXTFIELD ("formula", "if row = 2 then self + 200 else self fi")
	OK
DO
	WHERE (SELECTED) {
		if (! Formant_formula_frequencies (OBJECT, GET_STRING ("formula"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (Formant_getBandwidthAtTime, "Formant: Get bandwidth", "Formant: Get bandwidth at time...")
	NATURAL ("Formant number", "1")
	REAL ("Time (s)", "0.5")
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("Linear")
	OK
DO
	Melder_informationReal (Formant_getBandwidthAtTime (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("Time"), GET_INTEGER ("Unit") - 1), GET_STRING ("Unit"));
END
	
FORM (Formant_getMaximum, "Formant: Get maximum", "Formant: Get maximum...")
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	Melder_informationReal (Formant_getMaximum (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Unit") - 1,
		GET_INTEGER ("Interpolation") - 1), GET_STRING ("Unit"));
END

DIRECT (Formant_getMaximumNumberOfFormants)
	Melder_information ("%s (there are at most this many formants in every frame)",
		Melder_integer (Formant_getMaxNumFormants (ONLY_OBJECT)));
END

FORM (Formant_getMean, "Formant: Get mean", "Formant: Get mean...")
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	OK
DO
	Melder_informationReal (Formant_getMean (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Unit") - 1), GET_STRING ("Unit"));
END

FORM (Formant_getMinimum, "Formant: Get minimum", "Formant: Get minimum...")
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	Melder_informationReal (Formant_getMinimum (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Unit") - 1,
		GET_INTEGER ("Interpolation") - 1), GET_STRING ("Unit"));
END

DIRECT (Formant_getMinimumNumberOfFormants)
	Melder_information ("%s (at least this many formants in every frame)",
		Melder_integer (Formant_getMinNumFormants (ONLY_OBJECT)));
END

FORM (Formant_getNumberOfFormants, "Formant: Get number of formants", "Formant: Get number of formants...")
	NATURAL ("Frame number", "1")
	OK
DO
	long frame = GET_INTEGER ("Frame number");
	Formant me = ONLY_OBJECT;
	if (frame > my nx) return Melder_error ("There is no frame %ld in a Formant with only %ld frames.", frame, my nx);
	Melder_information ("%d formants", (int) my frame [frame]. nFormants);
END

FORM (Formant_getQuantile, "Formant: Get quantile", 0)
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	REAL ("Quantile", "0.50 (= median)")
	OK
DO
	Melder_informationReal (Formant_getQuantile (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("Quantile"), GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Unit") - 1), GET_STRING ("Unit"));
END

FORM (Formant_getQuantileOfBandwidth, "Formant: Get quantile of bandwidth", 0)
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	REAL ("Quantile", "0.50 (= median)")
	OK
DO
	Melder_informationReal (Formant_getQuantileOfBandwidth (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("Quantile"), GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Unit") - 1), GET_STRING ("Unit"));
END

FORM (Formant_getStandardDeviation, "Formant: Get standard deviation", 0)
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	OK
DO
	Melder_informationReal (Formant_getStandardDeviation (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Unit") - 1), GET_STRING ("Unit"));
END

FORM (Formant_getTimeOfMaximum, "Formant: Get time of maximum", "Formant: Get time of maximum...")
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	Melder_informationReal (Formant_getTimeOfMaximum (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_INTEGER ("Unit") - 1, GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Formant_getTimeOfMinimum, "Formant: Get time of minimum", "Formant: Get time of minimum...")
	NATURAL ("Formant number", "1")
	praat_dia_timeRange (dia);
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	Melder_informationReal (Formant_getTimeOfMinimum (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_INTEGER ("Unit") - 1, GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Formant_getValueAtTime, "Formant: Get value", "Formant: Get value at time...")
	NATURAL ("Formant number", "1")
	REAL ("Time (s)", "0.5")
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Bark")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("Linear")
	OK
DO
	Melder_informationReal (Formant_getValueAtTime (ONLY (classFormant), GET_INTEGER ("Formant number"),
		GET_REAL ("Time"), GET_INTEGER ("Unit") - 1), GET_STRING ("Unit"));
END
	
DIRECT (Formant_help) Melder_help ("Formant"); END

FORM (Formant_scatterPlot, "Formant: Scatter plot", 0)
	praat_dia_timeRange (dia);
	NATURAL ("Horizontal formant number", "2")
	REAL ("left Horizontal range (Hz)", "3000")
	REAL ("right Horizontal range (Hz)", "400")
	NATURAL ("Vertical formant number", "1")
	REAL ("left Vertical range (Hz)", "1500")
	REAL ("right Vertical range (Hz)", "100")
	POSITIVE ("Mark size (mm)", "1.0")
	BOOLEAN ("Garnish", 1)
	SENTENCE ("Mark string (+xo.)", "+")
	OK
DO
	EVERY_DRAW (Formant_scatterPlot (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_INTEGER ("Horizontal formant number"),
		GET_REAL ("left Horizontal range"), GET_REAL ("right Horizontal range"),
		GET_INTEGER ("Vertical formant number"),
		GET_REAL ("left Vertical range"), GET_REAL ("right Vertical range"),
		GET_REAL ("Mark size"), GET_STRING ("Mark string"), GET_INTEGER ("Garnish")))
END

DIRECT (Formant_sort)
	WHERE (SELECTED) {
		Formant_sort (OBJECT);
		praat_dataChanged (OBJECT);
	}
END

FORM (Formant_to_Matrix, "From Formant to Matrix", 0)
	INTEGER ("Formant", "1")
	OK
DO
	EVERY_TO (Formant_to_Matrix (OBJECT, GET_INTEGER ("Formant")))
END

FORM (Formant_tracker, "Formant tracker", "Formant: Track...")
	NATURAL ("Number of tracks", "3")
	REAL ("Reference F1 (Hz)", "550")
	REAL ("Reference F2 (Hz)", "1650")
	REAL ("Reference F3 (Hz)", "2750")
	REAL ("Reference F4 (Hz)", "3850")
	REAL ("Reference F5 (Hz)", "4950")
	REAL ("Frequency cost (/kHz)", "1.0")
	REAL ("Bandwidth cost", "1.0")
	REAL ("Transition cost (/octave)", "1.0")
	OK
DO
	EVERY_TO (Formant_tracker (OBJECT, GET_INTEGER ("Number of tracks"),
		GET_REAL ("Reference F1"), GET_REAL ("Reference F2"),
		GET_REAL ("Reference F3"), GET_REAL ("Reference F4"),
		GET_REAL ("Reference F5"), GET_REAL ("Frequency cost"),
		GET_REAL ("Bandwidth cost"), GET_REAL ("Transition cost")))
END

/***** FORMANT & POINTPROCESS *****/

DIRECT (Formant_PointProcess_to_FormantTier)
	Formant formant = ONLY (classFormant);
	PointProcess point = ONLY (classPointProcess);
	if (! praat_new (Formant_PointProcess_to_FormantTier (formant, point),
		"%s %s", formant -> name, point -> name)) return 0;
END

/***** FORMANT & SOUND *****/

DIRECT (Sound_Formant_filter)
	Sound me = ONLY (classSound);
	if (! praat_new (Sound_Formant_filter (me, ONLY (classFormant)), "%s_filt", my name)) return 0;
END

DIRECT (Sound_Formant_filter_noscale)
	Sound me = ONLY (classSound);
	if (! praat_new (Sound_Formant_filter_noscale (me, ONLY (classFormant)), "%s_filt", my name)) return 0;
END

/***** FORMANTTIER *****/

FORM (FormantTier_addPoint, "Add one point", "FormantTier: Add point...")
	REAL ("Time (s)", "0.5")
	LABEL ("", "Frequencies and bandwidths (Hz):")
	TEXTFIELD ("fb pairs", "500 50 1500 100 2500 150 3500 200 4500 300")
	OK
DO
	char *fbpairs = GET_STRING ("fb pairs");
	FormantPoint point = FormantPoint_create (GET_REAL ("Time"));
	double *f = point -> formant, *b = point -> bandwidth;
	int numberOfFormants = sscanf (fbpairs, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
		f, b, f+1, b+1, f+2, b+2, f+3, b+3, f+4, b+4, f+5, b+5, f+6, b+6, f+7, b+7, f+8, b+8, f+9, b+9) / 2;
	if (numberOfFormants < 1) {
		forget (point);
		return Melder_error ("Number of formant-bandwidth pairs must be at least 1.");
	}
	point -> numberOfFormants = numberOfFormants;
	WHERE (SELECTED) {
		if (! AnyTier_addPoint (OBJECT, Data_copy (point))) { forget (point); return 0; }
		praat_dataChanged (OBJECT);
	}
	forget (point);
END

FORM (FormantTier_create, "Create empty FormantTier", NULL)
	WORD ("Name", "empty")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	OK
DO
	double startTime = GET_REAL ("Start time"), endTime = GET_REAL ("End time");
	REQUIRE (endTime > startTime, "End time must be greater than start time.")
	if (! praat_new (FormantTier_create (startTime, endTime), GET_STRING ("Name"))) return 0;
END

FORM (FormantTier_downto_TableOfReal, "Down to TableOfReal", 0)
	BOOLEAN ("Include formants", 1)
	BOOLEAN ("Include bandwidths", 0)
	OK
DO
	EVERY_TO (FormantTier_downto_TableOfReal (OBJECT, GET_INTEGER ("Include formants"), GET_INTEGER ("Include bandwidths")))
END

FORM (FormantTier_getBandwidthAtTime, "FormantTier: Get bandwidth", "FormantTier: Get bandwidth at time...")
	NATURAL ("Formant number", "1")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (FormantTier_getBandwidthAtTime (ONLY (classFormantTier), GET_INTEGER ("Formant number"),
		GET_REAL ("Time")), "Hertz");
END
	
FORM (FormantTier_getValueAtTime, "FormantTier: Get value", "FormantTier: Get value at time...")
	NATURAL ("Formant number", "1")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (FormantTier_getValueAtTime (ONLY (classFormantTier), GET_INTEGER ("Formant number"),
		GET_REAL ("Time")), "Hertz");
END
	
DIRECT (FormantTier_help) Melder_help ("FormantTier"); END

FORM (FormantTier_speckle, "Draw FormantTier", 0)
	praat_dia_timeRange (dia);
	POSITIVE ("Maximum frequency (Hz)", "5500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (FormantTier_speckle (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_REAL ("Maximum frequency"), GET_INTEGER ("Garnish")))
END

/***** FORMANTTIER & SOUND *****/

DIRECT (Sound_FormantTier_filter)
	Sound me = ONLY (classSound);
	if (! praat_new (Sound_FormantTier_filter (me, ONLY (classFormantTier)), "%s_filt", my name)) return 0;
END

DIRECT (Sound_FormantTier_filter_noscale)
	Sound me = ONLY (classSound);
	if (! praat_new (Sound_FormantTier_filter_noscale (me, ONLY (classFormantTier)), "%s_filt", my name)) return 0;
END

/***** HARMONICITY *****/

FORM (Harmonicity_draw, "Draw harmonicity", 0)
	praat_dia_timeRange (dia);
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0 (= auto)")
	OK
DO
	EVERY_DRAW (Matrix_drawRows (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), 0.0, 0.0,
		GET_REAL ("Minimum"), GET_REAL ("Maximum")))
END

FORM (Harmonicity_formula, "Harmonicity Formula", "Harmonicity: Formula...")
	LABEL ("label", "x is time")
	LABEL ("label", "for col := 1 to ncol do { self [col] := `formula' ; x := x + dx }")
	TEXTFIELD ("formula", "self")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

FORM (Harmonicity_getMaximum, "Harmonicity: Get maximum", "Harmonicity: Get maximum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getMaximum (ONLY (classHarmonicity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "dB");
END

FORM (Harmonicity_getMean, "Harmonicity: Get mean", "Harmonicity: Get mean...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (Harmonicity_getMean (ONLY (classHarmonicity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range")), "dB");
END

FORM (Harmonicity_getMinimum, "Harmonicity: Get minimum", "Harmonicity: Get minimum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getMinimum (ONLY (classHarmonicity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "dB");
END

FORM (Harmonicity_getStandardDeviation, "Harmonicity: Get standard deviation", "Harmonicity: Get standard deviation...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (Harmonicity_getStandardDeviation (ONLY (classHarmonicity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range")), "dB");
END

FORM (Harmonicity_getTimeOfMaximum, "Harmonicity: Get time of maximum", "Harmonicity: Get time of maximum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getXOfMaximum (ONLY (classHarmonicity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Harmonicity_getTimeOfMinimum, "Harmonicity: Get time of minimum", "Harmonicity: Get time of minimum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getXOfMinimum (ONLY (classHarmonicity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Harmonicity_getValueAtTime, "Harmonicity: Get value", "Harmonicity: Get value at time...")
	dia_Vector_getValue (dia);
	OK
DO
	Melder_informationReal (Vector_getValueAtX (ONLY (classHarmonicity), GET_REAL ("Time"), GET_INTEGER ("Interpolation") - 1), "dB");
END
	
FORM (Harmonicity_getValueInFrame, "Get value in frame", "Harmonicity: Get value in frame...")
	INTEGER ("Frame number", "10")
	OK
DO
	Harmonicity me = ONLY (classHarmonicity);
	long frameNumber = GET_INTEGER ("Frame number");
	Melder_informationReal (frameNumber < 1 || frameNumber > my nx ? NUMundefined : my z [1] [frameNumber], "dB");
END

DIRECT (Harmonicity_help) Melder_help ("Harmonicity"); END

DIRECT (Harmonicity_to_Matrix)
	EVERY_TO (Harmonicity_to_Matrix (OBJECT))
END

/***** INTENSITY *****/

FORM (Intensity_draw, "Draw Intensity", 0)
	praat_dia_timeRange (dia);
	REAL ("Minimum (dB)", "0.0")
	REAL ("Maximum (dB)", "0.0 (= auto)")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Intensity_draw (OBJECT, GRAPHICS, GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Minimum"), GET_REAL ("Maximum"), GET_INTEGER ("Garnish")))
END

DIRECT (Intensity_downto_IntensityTier)
	EVERY_TO (Intensity_downto_IntensityTier (OBJECT))
END

DIRECT (Intensity_downto_Matrix)
	EVERY_TO (Intensity_to_Matrix (OBJECT))
END

FORM (Intensity_formula, "Intensity Formula", 0)
	LABEL ("label", "`x' is the time in seconds, `col' is the frame number, `self' is in dB")
	LABEL ("label", "x := x1;   for col := 1 to ncol do { self [col] := `formula' ; x := x + dx }")
	TEXTFIELD ("formula", "0")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

FORM (Intensity_getMaximum, "Intensity: Get maximum", "Intensity: Get maximum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getMaximum (ONLY (classIntensity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "dB");
END

FORM (old_Intensity_getMean, "Intensity: Get mean", "Intensity: Get mean...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (Sampled_getMean_standardUnit (ONLY (classIntensity), GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		0, 0, TRUE), "dB");
END

FORM (Intensity_getMean, "Intensity: Get mean", "Intensity: Get mean...")
	praat_dia_timeRange (dia);
	RADIO ("Averaging method", 1)
		RADIOBUTTON ("energy")
		RADIOBUTTON ("sones")
		RADIOBUTTON ("dB")
	OK
DO_ALTERNATIVE (old_Intensity_getMean)
	Melder_informationReal (Sampled_getMean_standardUnit (ONLY (classIntensity), GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		0, GET_INTEGER ("Averaging method"), TRUE), "dB");
END

FORM (Intensity_getMinimum, "Intensity: Get minimum", "Intensity: Get minimum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getMinimum (ONLY (classIntensity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "dB");
END

FORM (Intensity_getQuantile, "Intensity: Get quantile", 0)
	praat_dia_timeRange (dia);
	REAL ("Quantile (0-1)", "0.50")
	OK
DO
	Melder_informationReal (Intensity_getQuantile (ONLY (classIntensity), GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Quantile")), "dB");
END

FORM (Intensity_getStandardDeviation, "Intensity: Get standard deviation", "Intensity: Get standard deviation...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (Vector_getStandardDeviation (ONLY (classIntensity), GET_REAL ("left Time range"), GET_REAL ("right Time range")), "dB");
END

FORM (Intensity_getTimeOfMaximum, "Intensity: Get time of maximum", "Intensity: Get time of maximum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getXOfMaximum (ONLY (classIntensity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Intensity_getTimeOfMinimum, "Intensity: Get time of minimum", "Intensity: Get time of minimum...")
	dia_Vector_getExtremum (dia);
	OK
DO
	Melder_informationReal (Vector_getXOfMinimum (ONLY (classIntensity),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Intensity_getValueAtTime, "Intensity: Get value", "Intensity: Get value at time...")
	dia_Vector_getValue (dia);
	OK
DO
	Melder_informationReal (Vector_getValueAtX (ONLY (classIntensity), GET_REAL ("Time"), GET_INTEGER ("Interpolation") - 1), "dB");
END
	
FORM (Intensity_getValueInFrame, "Get value in frame", "Intensity: Get value in frame...")
	INTEGER ("Frame number", "10")
	OK
DO
	Intensity me = ONLY (classIntensity);
	long frameNumber = GET_INTEGER ("Frame number");
	Melder_informationReal (frameNumber < 1 || frameNumber > my nx ? NUMundefined : my z [1] [frameNumber], "dB");
END

DIRECT (Intensity_help) Melder_help ("Intensity"); END

DIRECT (Intensity_to_IntensityTier_peaks)
	EVERY_TO (Intensity_to_IntensityTier_peaks (OBJECT))
END

DIRECT (Intensity_to_IntensityTier_valleys)
	EVERY_TO (Intensity_to_IntensityTier_valleys (OBJECT))
END

/***** INTENSITY & PITCH *****/

FORM (Pitch_Intensity_draw, "Plot intensity by pitch", 0)
	REAL ("From frequency (Hertz)", "0.0")
	REAL ("To frequency (Hertz)", "0.0 (= auto)")
	REAL ("From intensity (dB)", "0.0")
	REAL ("To intensity (dB)", "100.0")
	BOOLEAN ("Garnish", 1)
	RADIO ("Drawing method", 1)
	RADIOBUTTON ("Speckles")
	RADIOBUTTON ("Curve")
	RADIOBUTTON ("Speckles and curve")
	OK
DO
	EVERY_DRAW (Pitch_Intensity_draw (ONLY (classPitch), ONLY (classIntensity), GRAPHICS,
		GET_REAL ("From frequency"), GET_REAL ("To frequency"),
		GET_REAL ("From intensity"), GET_REAL ("To intensity"), GET_INTEGER ("Garnish"), GET_INTEGER ("Drawing method")))
END

FORM (Pitch_Intensity_speckle, "Plot intensity by pitch", 0)
	REAL ("From frequency (Hertz)", "0.0")
	REAL ("To frequency (Hertz)", "0.0 (= auto)")
	REAL ("From intensity (dB)", "0.0")
	REAL ("To intensity (dB)", "100.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Pitch_Intensity_draw (ONLY (classPitch), ONLY (classIntensity), GRAPHICS,
		GET_REAL ("From frequency"), GET_REAL ("To frequency"),
		GET_REAL ("From intensity"), GET_REAL ("To intensity"), GET_INTEGER ("Garnish"), 1))
END

/***** INTENSITY & POINTPROCESS *****/

DIRECT (Intensity_PointProcess_to_IntensityTier)
	Intensity intensity = ONLY (classIntensity);
	if (! praat_new (Intensity_PointProcess_to_IntensityTier (intensity, ONLY (classPointProcess)),
		intensity -> name)) return 0;
END

/***** INTENSITYTIER *****/

FORM (IntensityTier_addPoint, "Add one point", "IntensityTier: Add point...")
	REAL ("Time (s)", "0.5")
	REAL ("Intensity (dB)", "75")
	OK
DO
	WHERE (SELECTED) {
		if (! RealTier_addPoint (OBJECT, GET_REAL ("Time"), GET_REAL ("Intensity"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (IntensityTier_create, "Create empty IntensityTier", NULL)
	WORD ("Name", "empty")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	OK
DO
	double startTime = GET_REAL ("Start time"), endTime = GET_REAL ("End time");
	REQUIRE (endTime > startTime, "End time must be greater than start time.")
	if (! praat_new (IntensityTier_create (startTime, endTime), GET_STRING ("Name"))) return 0;
END

DIRECT (IntensityTier_downto_PointProcess)
	EVERY_TO (AnyTier_downto_PointProcess (OBJECT))
END

DIRECT (IntensityTier_downto_TableOfReal)
	EVERY_TO (IntensityTier_downto_TableOfReal (OBJECT))
END

DIRECT (IntensityTier_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit an IntensityTier from batch.");
	} else {
		Sound sound = NULL;
		WHERE (SELECTED)
			if (CLASS == classSound) sound = OBJECT;
		WHERE (SELECTED && CLASS == classIntensityTier)
			if (! praat_installEditor (IntensityTierEditor_create (praat.topShell, FULL_NAME,
				OBJECT, sound, TRUE), IOBJECT)) return 0;
	}
END

FORM (IntensityTier_formula, "IntensityTier: Formula", "IntensityTier: Formula...")
	LABEL ("", "# ncol = the number of points")
	LABEL ("", "for col from 1 to ncol")
	LABEL ("", "   # x = the time of the colth point, in seconds")
	LABEL ("", "   # self = the value of the colth point, in dB")
	LABEL ("", "   self = `formula'")
	LABEL ("", "endfor")
	TEXTFIELD ("formula", "self + 3.0")
	OK
DO
	WHERE_DOWN (SELECTED) {
		RealTier_formula (OBJECT, GET_STRING ("formula"), NULL);
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (IntensityTier_getValueAtTime, "Get IntensityTier value", "IntensityTier: Get value at time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (RealTier_getValueAtTime (ONLY_OBJECT, GET_REAL ("Time")), "dB");
END
	
FORM (IntensityTier_getValueAtIndex, "Get IntensityTier value", "IntensityTier: Get value at index...")
	INTEGER ("Point number", "10")
	OK
DO
	Melder_informationReal (RealTier_getValueAtIndex (ONLY_OBJECT, GET_INTEGER ("Point number")), "dB");
END

DIRECT (IntensityTier_help) Melder_help ("IntensityTier"); END

DIRECT (IntensityTier_to_AmplitudeTier)
	EVERY_TO (IntensityTier_to_AmplitudeTier (OBJECT))
END

DIRECT (info_IntensityTier_Sound_edit)
	Melder_information ("To include a copy of a Sound in your IntensityTier editor:\n"
		"   select an IntensityTier and a Sound, and click \"Edit\".");
END

/***** INTENSITYTIER & POINTPROCESS *****/

DIRECT (IntensityTier_PointProcess_to_IntensityTier)
	IntensityTier intensity = ONLY (classIntensityTier);
	if (! praat_new (IntensityTier_PointProcess_to_IntensityTier (intensity, ONLY (classPointProcess)), intensity -> name)) return 0;
END

/***** INTENSITYTIER & SOUND *****/

DIRECT (Sound_IntensityTier_multiply_old)
	Sound sound = ONLY (classSound);
	if (! praat_new (Sound_IntensityTier_multiply (sound, ONLY (classIntensityTier), TRUE), "%s_int", sound -> name)) return 0;
END

FORM (Sound_IntensityTier_multiply, "Sound & IntervalTier: Multiply", 0)
	BOOLEAN ("Scale to 0.9", 1)
	OK
DO
	Sound sound = ONLY (classSound);
	if (! praat_new (Sound_IntensityTier_multiply (sound, ONLY (classIntensityTier), GET_INTEGER ("Scale to 0.9")), "%s_int", sound -> name)) return 0;
END

/***** INTERVALTIER, rest in praat_TextGrid_init.c *****/

FORM_READ (IntervalTier_readFromXwaves, "Read IntervalTier from Xwaves", 0)
	if (! praat_new (IntervalTier_readFromXwaves (file), MelderFile_name (file))) return 0;
END

/***** LTAS *****/

DIRECT (Ltases_average)
	Collection ltases;
	int n = 0;
	WHERE (SELECTED) n ++;
	ltases = Collection_create (classLtas, n);
	WHERE (SELECTED) Collection_addItem (ltases, OBJECT);
	if (! praat_new (Ltases_average (ltases), "averaged")) {
		ltases -> size = 0;   /* Undangle. */
		forget (ltases);
		return 0;
	}
	ltases -> size = 0;   /* Undangle. */
	forget (ltases);
END

FORM (Ltas_computeTrendLine, "Ltas: Compute trend line", "Ltas: Compute trend line...")
	REAL ("left Frequency range (Hz)", "600.0")
	POSITIVE ("right Frequency range (Hz)", "4000.0")
	OK
DO
	WHERE (SELECTED) {
		if (! praat_new (Ltas_computeTrendLine (OBJECT, GET_REAL ("left Frequency range"), GET_REAL ("right Frequency range")),
			"%s_trend", NAME)) return 0;
	}
END

FORM (old_Ltas_draw, "Ltas: Draw", 0)
	REAL ("left Frequency range (Hz)", "0.0")
	REAL ("right Frequency range (Hz)", "0.0 (= all)")
	REAL ("left Power range (dB/Hz)", "-20.0")
	REAL ("right Power range (dB/Hz)", "80.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Ltas_draw (OBJECT, GRAPHICS, GET_REAL ("left Frequency range"), GET_REAL ("right Frequency range"),
		GET_REAL ("left Power range"), GET_REAL ("right Power range"), GET_INTEGER ("Garnish"), "bars"))
END

FORM (Ltas_draw, "Ltas: Draw", 0)
	REAL ("left Frequency range (Hz)", "0.0")
	REAL ("right Frequency range (Hz)", "0.0 (= all)")
	REAL ("left Power range (dB/Hz)", "-20.0")
	REAL ("right Power range (dB/Hz)", "80.0")
	BOOLEAN ("Garnish", 1)
	LABEL ("", "")
	OPTIONMENU ("Drawing method", 2)
		OPTION ("curve")
		OPTION ("bars")
		OPTION ("poles")
		OPTION ("speckles")
	OK
DO_ALTERNATIVE (old_Ltas_draw)
	EVERY_DRAW (Ltas_draw (OBJECT, GRAPHICS, GET_REAL ("left Frequency range"), GET_REAL ("right Frequency range"),
		GET_REAL ("left Power range"), GET_REAL ("right Power range"), GET_INTEGER ("Garnish"), GET_STRING ("Drawing method")))
END

FORM (Ltas_formula, "Ltas Formula", 0)
	LABEL ("label", "`x' is the frequency in Hertz, `col' is the bin number")
	LABEL ("label", "x := x1;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
	TEXTFIELD ("formula", "0")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

FORM (Ltas_getBinNumberFromFrequency, "Ltas: Get band from frequency", "Ltas: Get band from frequency...")
	REAL ("Frequency (Hz)", "2000")
	OK
DO
	Melder_informationReal (Sampled_xToIndex (ONLY (classLtas), GET_REAL ("Frequency")), NULL);
END

DIRECT (Ltas_getBinWidth)
	Ltas me = ONLY (classLtas);
	Melder_informationReal (my dx, "Hertz");
END

FORM (Ltas_getFrequencyFromBinNumber, "Ltas: Get frequency from bin number", "Ltas: Get frequency from bin number...")
	NATURAL ("Bin number", "1")
	OK
DO
	Melder_informationReal (Sampled_indexToX (ONLY (classLtas), GET_INTEGER ("Bin number")), "Hertz");
END

FORM (Ltas_getFrequencyOfMaximum, "Ltas: Get frequency of maximum", "Ltas: Get frequency of maximum...")
	REAL ("From frequency (Hz)", "0.0")
	REAL ("To frequency (Hz)", "0.0 (= all)")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
	OK
DO
	Melder_informationReal (Vector_getXOfMaximum (ONLY (classLtas),
		GET_REAL ("From frequency"), GET_REAL ("To frequency"), GET_INTEGER ("Interpolation") - 1), "Hertz");
END

FORM (Ltas_getFrequencyOfMinimum, "Ltas: Get frequency of minimum", "Ltas: Get frequency of minimum...")
	REAL ("From frequency (s)", "0.0")
	REAL ("To frequency (s)", "0.0 (= all)")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
	OK
DO
	Melder_informationReal (Vector_getXOfMinimum (ONLY (classLtas),
		GET_REAL ("From frequency"), GET_REAL ("To frequency"), GET_INTEGER ("Interpolation") - 1), "Hertz");
END

DIRECT (Ltas_getFrequencyRange)
	Ltas me = ONLY (classLtas);
	Melder_informationReal (my xmax - my xmin, "Hertz");
END

DIRECT (Ltas_getHighestFrequency)
	Ltas me = ONLY (classLtas);
	Melder_informationReal (my xmax, "Hertz");
END

FORM (Ltas_getLocalPeakHeight, "Ltas: Get local peak height", 0)
	REAL ("left Environment (Hz)", "1700.0")
	REAL ("right Environment (Hz)", "4200.0")
	REAL ("left Peak (Hz)", "2400.0")
	REAL ("right Peak (Hz)", "3200.0")
	RADIO ("Averaging method", 1)
		RADIOBUTTON ("energy")
		RADIOBUTTON ("sones")
		RADIOBUTTON ("dB")
	OK
DO
	double environmentMin = GET_REAL ("left Environment"), environmentMax = GET_REAL ("right Environment");
	double peakMin = GET_REAL ("left Peak"), peakMax = GET_REAL ("right Peak");
	REQUIRE (environmentMin < peakMin, "The beginning of the environment must lie before the peak.")
	REQUIRE (peakMin < peakMax, "The end of the peak must lie after its beginning.")
	REQUIRE (environmentMax > peakMax, "The end of the environment must lie after the peak.")
	Melder_informationReal (Ltas_getLocalPeakHeight (ONLY (classLtas), environmentMin, environmentMax,
		peakMin, peakMax, GET_INTEGER ("Averaging method")), "dB");
END

DIRECT (Ltas_getLowestFrequency)
	Ltas me = ONLY (classLtas);
	Melder_informationReal (my xmin, "Hertz");
END

FORM (Ltas_getMaximum, "Ltas: Get maximum", "Ltas: Get maximum...")
	REAL ("From frequency (Hz)", "0.0")
	REAL ("To frequency (Hz)", "0.0 (= all)")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
	OK
DO
	Melder_informationReal (Vector_getMaximum (ONLY (classLtas),
		GET_REAL ("From frequency"), GET_REAL ("To frequency"), GET_INTEGER ("Interpolation") - 1), "dB");
END

FORM (Ltas_getMean, "Ltas: Get mean", "Ltas: Get mean...")
	REAL ("From frequency (Hz)", "0.0")
	REAL ("To frequency (Hz)", "0.0 (= all)")
	RADIO ("Averaging method", 1)
		RADIOBUTTON ("energy")
		RADIOBUTTON ("sones")
		RADIOBUTTON ("dB")
	OK
DO
	Melder_informationReal (Sampled_getMean_standardUnit (ONLY (classLtas), GET_REAL ("From frequency"), GET_REAL ("To frequency"),
		0, GET_INTEGER ("Averaging method"), FALSE), "dB");
END

FORM (Ltas_getMinimum, "Ltas: Get minimum", "Ltas: Get minimum...")
	REAL ("From frequency (Hz)", "0.0")
	REAL ("To frequency (Hz)", "0.0 (= all)")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
	OK
DO
	Melder_informationReal (Vector_getMinimum (ONLY (classLtas),
		GET_REAL ("From frequency"), GET_REAL ("To frequency"), GET_INTEGER ("Interpolation") - 1), "dB");
END

DIRECT (Ltas_getNumberOfBins)
	Ltas me = ONLY (classLtas);
	Melder_information ("%ld bins", my nx);
END

FORM (Ltas_getSlope, "Ltas: Get slope", 0)
	REAL ("left Low band (Hz)", "0.0")
	REAL ("right Low band (Hz)", "1000.0")
	REAL ("left High band (Hz)", "1000.0")
	REAL ("right High band (Hz)", "4000.0")
	RADIO ("Averaging method", 1)
		RADIOBUTTON ("energy")
		RADIOBUTTON ("sones")
		RADIOBUTTON ("dB")
	OK
DO
	Melder_informationReal (Ltas_getSlope (ONLY (classLtas), GET_REAL ("left Low band"), GET_REAL ("right Low band"),
		GET_REAL ("left High band"), GET_REAL ("right High band"), GET_INTEGER ("Averaging method")), "dB");
END

FORM (Ltas_getStandardDeviation, "Ltas: Get standard deviation", "Ltas: Get standard deviation...")
	REAL ("From frequency (Hz)", "0.0")
	REAL ("To frequency (Hz)", "0.0 (= all)")
	RADIO ("Averaging method", 1)
		RADIOBUTTON ("energy")
		RADIOBUTTON ("sones")
		RADIOBUTTON ("dB")
	OK
DO
	Melder_informationReal (Sampled_getStandardDeviation_standardUnit (ONLY (classLtas), GET_REAL ("From frequency"), GET_REAL ("To frequency"),
		0, GET_INTEGER ("Averaging method"), FALSE), "dB");
END

FORM (Ltas_getValueAtFrequency, "Ltas: Get value", "Ltas: Get value at frequency...")
	REAL ("Frequency (Hertz)", "1500")
	RADIO ("Interpolation", 1)
	RADIOBUTTON ("Nearest")
	RADIOBUTTON ("Linear")
	RADIOBUTTON ("Cubic")
	RADIOBUTTON ("Sinc70")
	RADIOBUTTON ("Sinc700")
	OK
DO
	Melder_informationReal (Vector_getValueAtX (ONLY (classLtas), GET_REAL ("Frequency"), GET_INTEGER ("Interpolation") - 1), "dB");
END
	
FORM (Ltas_getValueInBin, "Get value in bin", "Ltas: Get value in bin...")
	INTEGER ("Bin number", "100")
	OK
DO
	Ltas me = ONLY (classLtas);
	long binNumber = GET_INTEGER ("Bin number");
	Melder_informationReal (binNumber < 1 || binNumber > my nx ? NUMundefined : my z [1] [binNumber], "dB");
END

DIRECT (Ltas_help) Melder_help ("Ltas"); END

DIRECT (Ltases_merge)
	Collection ltases;
	int n = 0;
	WHERE (SELECTED) n ++;
	ltases = Collection_create (classLtas, n);
	WHERE (SELECTED) Collection_addItem (ltases, OBJECT);
	if (! praat_new (Ltases_merge (ltases), "merged")) {
		ltases -> size = 0;   /* Undangle. */
		forget (ltases);
		return 0;
	}
	ltases -> size = 0;   /* Undangle. */
	forget (ltases);
END

FORM (Ltas_subtractTrendLine, "Ltas: Subtract trend line", "Ltas: Subtract trend line...")
	REAL ("left Frequency range (Hertz)", "600.0")
	POSITIVE ("right Frequency range (Hertz)", "4000.0")
	OK
DO
	WHERE (SELECTED) {
		if (! praat_new (Ltas_subtractTrendLine (OBJECT, GET_REAL ("left Frequency range"), GET_REAL ("right Frequency range")),
			"%s_fit", NAME)) return 0;
	}
END

DIRECT (Ltas_to_Matrix)
	EVERY_TO (Ltas_to_Matrix (OBJECT))
END

/***** MANIPULATION *****/

static void cb_ManipulationEditor_publish (Any editor, void *closure, Any publish) {
	(void) editor;
	(void) closure;
	if (! praat_new (publish, "fromManipulationEditor")) { Melder_flushError (NULL); return; }
	praat_updateSelection ();
}
DIRECT (Manipulation_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit a Manipulation from batch.");
	} else {
		WHERE (SELECTED) {
			ManipulationEditor editor = ManipulationEditor_create (praat.topShell, FULL_NAME, OBJECT);
			if (! praat_installEditor (editor, IOBJECT)) return 0;
			Editor_setPublishCallback (editor, cb_ManipulationEditor_publish, NULL);
		}
	}
END

DIRECT (Manipulation_extractDurationTier)
	WHERE (SELECTED) {
		Manipulation ana = OBJECT;
		if (ana -> duration) {
			if (! praat_new (Data_copy (ana -> duration), NULL)) return 0;
		} else {
			return Melder_error ("Manipulation does not contain a DurationTier.");
		}
	}
END

DIRECT (Manipulation_extractOriginalSound)
	WHERE (SELECTED) {
		Manipulation ana = OBJECT;
		if (ana -> sound) {
			if (! praat_new (Data_copy (ana -> sound), NULL)) return 0;
		} else {
			return Melder_error ("Manipulation does not contain a Sound.");
		}
	}
END

DIRECT (Manipulation_extractPitchTier)
	WHERE (SELECTED) {
		Manipulation ana = OBJECT;
		if (ana -> pitch) {
			if (! praat_new (Data_copy (ana -> pitch), NULL)) return 0;
		} else {
			return Melder_error ("Manipulation does not contain a PitchTier.");
		}
	}
END

DIRECT (Manipulation_extractPulses)
	WHERE (SELECTED) {
		Manipulation ana = OBJECT;
		if (ana -> pulses) {
			if (! praat_new (Data_copy (ana -> pulses), NULL)) return 0;
		} else {
			return Melder_error ("Manipulation does not contain a PointProcess.");
		}
	}
END

DIRECT (Manipulation_getResynthesis_psola)
	EVERY_TO (Manipulation_to_Sound (OBJECT, Manipulation_PSOLA))
END

DIRECT (Manipulation_getResynthesis_lpc)
	EVERY_TO (Manipulation_to_Sound (OBJECT, Manipulation_PITCH_LPC))
END

DIRECT (Manipulation_help) Melder_help ("Manipulation"); END

DIRECT (Manipulation_play_psola)
	EVERY_CHECK (Manipulation_play (OBJECT, Manipulation_PSOLA))
END

DIRECT (Manipulation_play_lpc)
	EVERY_CHECK (Manipulation_play (OBJECT, Manipulation_PITCH_LPC))
END

DIRECT (Manipulation_removeDuration)
	WHERE (SELECTED) {
		Manipulation ana = OBJECT;
		forget (ana -> duration);
		praat_dataChanged (ana);
	}
END

DIRECT (Manipulation_removeOriginalSound)
	WHERE (SELECTED) {
		Manipulation ana = OBJECT;
		forget (ana -> sound);
		praat_dataChanged (ana);
	}
END

FORM_WRITE (Manipulation_writeToBinaryFileWithoutSound, "Binary file without Sound", 0, 0)
	if (! Manipulation_writeToBinaryFileWithoutSound (ONLY_OBJECT, file)) return 0;
END

FORM_WRITE (Manipulation_writeToTextFileWithoutSound, "Text file without Sound", 0, 0)
	if (! Manipulation_writeToTextFileWithoutSound (ONLY_OBJECT, file)) return 0;
END

DIRECT (info_DurationTier_Manipulation_replace)
	Melder_information ("To replace the DurationTier in a Manipulation object,\n"
		"select a DurationTier object and a Manipulation object\nand choose \"Replace duration\".");
END

DIRECT (info_PitchTier_Manipulation_replace)
	Melder_information ("To replace the PitchTier in a Manipulation object,\n"
		"select a PitchTier object and a Manipulation object\nand choose \"Replace pitch\".");
END

/***** MANIPULATION & DURATIONTIER *****/

DIRECT (Manipulation_replaceDurationTier)
	Manipulation ana = ONLY (classManipulation);
	if (! Manipulation_replaceDurationTier (ana, ONLY (classDurationTier))) return 0;
	praat_dataChanged (ana);
END

DIRECT (Manipulation_replaceDurationTier_help) Melder_help ("Manipulation: Replace duration tier"); END

/***** MANIPULATION & PITCHTIER *****/

DIRECT (Manipulation_replacePitchTier)
	Manipulation ana = ONLY (classManipulation);
	if (! Manipulation_replacePitchTier (ana, ONLY (classPitchTier))) return 0;
	praat_dataChanged (ana);
END

DIRECT (Manipulation_replacePitchTier_help) Melder_help ("Manipulation: Replace pitch tier"); END

/***** MANIPULATION & POINTPROCESS *****/

DIRECT (Manipulation_replacePulses)
	Manipulation ana = ONLY (classManipulation);
	if (! Manipulation_replacePulses (ana, ONLY (classPointProcess))) return 0;
	praat_dataChanged (ana);
END

/***** MANIPULATION & SOUND *****/

DIRECT (Manipulation_replaceOriginalSound)
	Manipulation ana = ONLY (classManipulation);
	if (! Manipulation_replaceOriginalSound (ana, ONLY (classSound))) return 0;
	praat_dataChanged (ana);
END

/***** MANIPULATION & TEXTTIER *****/

DIRECT (Manipulation_TextTier_to_Manipulation)
	if (! praat_new (Manipulation_AnyTier_to_Manipulation (ONLY (classManipulation), ONLY (classTextTier)),
		((Manipulation) (ONLY (classManipulation))) -> name)) return 0;	
END

/***** MATRIX *****/

DIRECT (Matrix_appendRows)
	Matrix m1 = NULL, m2 = NULL;
	WHERE (SELECTED) { if (m1) m2 = OBJECT; else m1 = OBJECT; }
	if (! praat_new (Matrix_appendRows (m1, m2), "%s_%s", m1 -> name, m2 -> name)) return 0;
END

FORM (Matrix_create, "Create Matrix", "Create Matrix...")
	WORD ("Name", "xy")
	REAL ("xmin", "1.0")
	REAL ("xmax", "1.0")
	NATURAL ("Number of columns", "1")
	POSITIVE ("dx", "1.0")
	REAL ("x1", "1.0")
	REAL ("ymin", "1.0")
	REAL ("ymax", "1.0")
	NATURAL ("Number of rows", "1")
	POSITIVE ("dy", "1.0")
	REAL ("y1", "1.0")
	LABEL ("", "Formula:")
	TEXTFIELD ("formula", "x*y")
	OK
DO
	double xmin = GET_REAL ("xmin"), xmax = GET_REAL ("xmax");
	double ymin = GET_REAL ("ymin"), ymax = GET_REAL ("ymax");
	if (xmax < xmin)
		return Melder_error ("xmax (%.8g) should not be less than xmin (%.8g).", xmax, xmin);
	if (ymax < ymin)
		return Melder_error ("ymax (%.8g) should not be less than ymin (%.8g).", ymax, ymin);
	if (! praat_new (Matrix_create (
		xmin, xmax, GET_INTEGER ("Number of columns"), GET_REAL ("dx"), GET_REAL ("x1"),
		ymin, ymax, GET_INTEGER ("Number of rows"), GET_REAL ("dy"), GET_REAL ("y1")),
		"%s", GET_STRING ("Name"))) return 0;
	praat_updateSelection ();
	return praat_Fon_formula (dia);
END

FORM (Matrix_createSimple, "Create simple Matrix", "Create simple Matrix...")
	WORD ("Name", "xy")
	NATURAL ("Number of rows", "10")
	NATURAL ("Number of columns", "10")
	LABEL ("", "Formula:")
	TEXTFIELD ("formula", "x*y")
	OK
DO
	if (! praat_new (Matrix_createSimple (
		GET_INTEGER ("Number of rows"), GET_INTEGER ("Number of columns")),
		"%s", GET_STRING ("Name"))) return 0;
	praat_updateSelection ();
	return praat_Fon_formula (dia);
END

FORM (Matrix_drawOneContour, "Draw one altitude contour", 0)
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Height", "0.5")
	OK
DO
	EVERY_DRAW (Matrix_drawOneContour (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="), GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Height")))
END

FORM (Matrix_drawContours, "Draw altitude contours", 0)
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0")
	OK
DO
	EVERY_DRAW (Matrix_drawContours (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="), GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Minimum"), GET_REAL ("Maximum")))
END

FORM (Matrix_drawRows, "Draw rows", 0)
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0")
	OK
DO
	EVERY_DRAW (Matrix_drawRows (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="),
		GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Minimum"), GET_REAL ("Maximum")))
END

DIRECT (Matrix_eigen)
	WHERE (SELECTED) {
		Matrix vec, val;
		if (! Matrix_eigen (OBJECT, & vec, & val)) return 0;
		if (! praat_new (vec, "eigenvectors")) return 0;
		if (! praat_new (val, "eigenvalues")) return 0;
	}
END

FORM (Matrix_formula, "Matrix Formula", "Formula...")
	LABEL ("label", "y := y1; for row := 1 to nrow do { x := x1; "
		"for col := 1 to ncol do { self [row, col] := `formula' ; x := x + dx } y := y + dy }")
	TEXTFIELD ("formula", "self")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

DIRECT (Matrix_getHighestX) Matrix me = ONLY_OBJECT; Melder_informationReal (my xmax, NULL); END
DIRECT (Matrix_getHighestY) Matrix me = ONLY_OBJECT; Melder_informationReal (my ymax, NULL); END
DIRECT (Matrix_getLowestX) Matrix me = ONLY_OBJECT; Melder_informationReal (my xmin, NULL); END
DIRECT (Matrix_getLowestY) Matrix me = ONLY_OBJECT; Melder_informationReal (my ymin, NULL); END
DIRECT (Matrix_getNumberOfColumns) Matrix me = ONLY_OBJECT; Melder_information ("%ld", my nx); END
DIRECT (Matrix_getNumberOfRows) Matrix me = ONLY_OBJECT; Melder_information ("%ld", my ny); END
DIRECT (Matrix_getColumnDistance) Matrix me = ONLY_OBJECT; Melder_informationReal (my dx, NULL); END
DIRECT (Matrix_getRowDistance) Matrix me = ONLY_OBJECT; Melder_informationReal (my dy, NULL); END
DIRECT (Matrix_getSum) Matrix me = ONLY_OBJECT; Melder_informationReal (Matrix_getSum (me), NULL); END

FORM (Matrix_getValueAtXY, "Matrix: Get value at xy", 0)
	REAL ("X", "0")
	REAL ("Y", "0")
	OK
DO
	Matrix me = ONLY_OBJECT;
	double x = GET_REAL ("X"), y = GET_REAL ("Y");
	MelderInfo_open ();
	MelderInfo_write1 (Melder_double (Matrix_getValueAtXY (me, x, y)));
	MelderInfo_write5 (" (at x = ", Melder_double (x), " and y = ", Melder_double (y), ")");
	MelderInfo_close ();
END

FORM (Matrix_getValueInCell, "Matrix: Get value in cell", 0)
	NATURAL ("Row number", "1") NATURAL ("Column number", "1") OK DO Matrix me = ONLY_OBJECT;
	long row = GET_INTEGER ("Row number"), column = GET_INTEGER ("Column number");
	REQUIRE (row <= my ny, "Row number must not exceed number of rows.")
	REQUIRE (column <= my nx, "Column number must not exceed number of columns.")
	Melder_informationReal (my z [row] [column], NULL); END
FORM (Matrix_getXofColumn, "Matrix: Get x of column", 0)
	NATURAL ("Column number", "1") OK DO
	Melder_informationReal (Matrix_columnToX (ONLY_OBJECT, GET_INTEGER ("Column number")), NULL); END
FORM (Matrix_getYofRow, "Matrix: Get y of row", 0)
	NATURAL ("Row number", "1") OK DO
	Melder_informationReal (Matrix_rowToY (ONLY_OBJECT, GET_INTEGER ("Row number")), NULL); END

DIRECT (Matrix_help) Melder_help ("Matrix"); END

DIRECT (Matrix_movie)
	Graphics g = Movie_create ("Matrix movie", 300, 300);
	WHERE (SELECTED) Matrix_movie (OBJECT, g);
END

FORM (Matrix_paintCells, "Matrix: Paint cells with greys", "Matrix: Paint cells...")
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0")
	OK
DO
	EVERY_DRAW (Matrix_paintCells (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="), GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Minimum"), GET_REAL ("Maximum")))
END

FORM (Matrix_paintContours, "Matrix: Paint altitude contours with greys", 0)
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0")
	OK
DO
	EVERY_DRAW (Matrix_paintContours (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="), GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Minimum"), GET_REAL ("Maximum")))
END

FORM (Matrix_paintImage, "Matrix: Paint grey image", 0)
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0")
	OK
DO
	EVERY_DRAW (Matrix_paintImage (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="), GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Minimum"), GET_REAL ("Maximum")))
END

FORM (Matrix_paintSurface, "Matrix: Paint 3-D surface plot", 0)
	REAL ("From x =", "0.0")
	REAL ("To x =", "0.0")
	REAL ("From y =", "0.0")
	REAL ("To y =", "0.0")
	REAL ("Minimum", "0.0")
	REAL ("Maximum", "0.0")
	OK
DO
	EVERY_DRAW (Matrix_paintSurface (OBJECT, GRAPHICS,
		GET_REAL ("From x ="), GET_REAL ("To x ="), GET_REAL ("From y ="), GET_REAL ("To y ="),
		GET_REAL ("Minimum"), GET_REAL ("Maximum"), 30, 45))
END

FORM (Matrix_power, "Matrix: Power...", 0)
	NATURAL ("Power", "2")
	OK
DO
	EVERY_TO (Matrix_power (OBJECT, GET_INTEGER ("Power")))
END

FORM_READ (Matrix_readFromRawTextFile, "Read Matrix from raw text file", 0)
	if (! praat_new (Matrix_readFromRawTextFile (file), MelderFile_name (file))) return 0;
END

FORM_READ (Matrix_readAP, "Read Matrix from LVS AP file", 0)
	if (! praat_new (Matrix_readAP (file), MelderFile_name (file))) return 0;
END

FORM (Matrix_setValue, "Matrix: Set value", "Matrix: Set value...")
	NATURAL ("Row number", "1")
	NATURAL ("Column number", "1")
	REAL ("New value", "0.0")
	OK
DO
	WHERE (SELECTED) {
		Matrix me = OBJECT;
		long row = GET_INTEGER ("Row number"), column = GET_INTEGER ("Column number");
		REQUIRE (row <= my ny, "Row number must not be greater than number of rows.")
		REQUIRE (column <= my nx, "Column number must not be greater than number of columns.")
		my z [row] [column] = GET_REAL ("New value");
		praat_dataChanged (me);
	}
END

DIRECT (Matrix_to_Cochleagram)
	EVERY_TO (Matrix_to_Cochleagram (OBJECT))
END

DIRECT (Matrix_to_Excitation)
	EVERY_TO (Matrix_to_Excitation (OBJECT))
END

DIRECT (Matrix_to_Harmonicity)
	EVERY_TO (Matrix_to_Harmonicity (OBJECT))
END

DIRECT (Matrix_to_Intensity)
	EVERY_TO (Matrix_to_Intensity (OBJECT))
END

DIRECT (Matrix_to_Pitch)
	EVERY_TO (Matrix_to_Pitch (OBJECT))
END

DIRECT (Matrix_to_Spectrogram)
	EVERY_TO (Matrix_to_Spectrogram (OBJECT))
END

DIRECT (Matrix_to_Spectrum)
	EVERY_TO (Matrix_to_Spectrum (OBJECT))
END

DIRECT (Matrix_to_Ltas)
	EVERY_TO (Matrix_to_Ltas (OBJECT))
END

DIRECT (Matrix_to_ParamCurve)
	Matrix m1 = NULL, m2 = NULL;
	WHERE (SELECTED) { if (m1) m2 = OBJECT; else m1 = OBJECT; }
	if (! praat_new (ParamCurve_create (m1, m2), "%s_%s", m1 -> name, m2 -> name)) return 0;
END

DIRECT (Matrix_to_PointProcess)
	EVERY_TO (Matrix_to_PointProcess (OBJECT))
END

DIRECT (Matrix_to_Polygon)
	EVERY_TO (Matrix_to_Polygon (OBJECT))
END

FORM (Matrix_to_Sound, "Matrix: To Sound", 0)
	INTEGER ("Row", "1")
	LABEL ("", "(negative values count from last row)")
	OK
DO
	EVERY_TO (Matrix_to_Sound (OBJECT, GET_INTEGER ("Row")))
END

DIRECT (Matrix_to_TableOfReal)
	EVERY_TO (Matrix_to_TableOfReal (OBJECT))
END

DIRECT (Matrix_to_Transition)
	EVERY_TO (Matrix_to_Transition (OBJECT))
END

DIRECT (Matrix_to_VocalTract)
	EVERY_TO (Matrix_to_VocalTract (OBJECT))
END

FORM_WRITE (Matrix_writeToMatrixTextFile, "Write Matrix to matrix text file", 0, "mat")
	if (! Matrix_writeToMatrixTextFile (ONLY_OBJECT, file)) return 0;
END

FORM_WRITE (Matrix_writeToHeaderlessSpreadsheetFile, "Write Matrix to spreadsheet", 0, "txt")
	if (! Matrix_writeToHeaderlessSpreadsheetFile (ONLY_OBJECT, file)) return 0;
END

/***** PAIRDISTRIBUTION *****/

DIRECT (PairDistribution_getFractionCorrect_maximumLikelihood)
	Melder_informationReal (PairDistribution_getFractionCorrect_maximumLikelihood (ONLY_OBJECT), NULL);
	iferror return 0;
END

DIRECT (PairDistribution_getFractionCorrect_probabilityMatching)
	Melder_informationReal (PairDistribution_getFractionCorrect_probabilityMatching (ONLY_OBJECT), NULL);
	iferror return 0;
END

DIRECT (PairDistribution_help) Melder_help ("PairDistribution"); END

DIRECT (PairDistribution_removeZeroWeights)
	EVERY (PairDistribution_removeZeroWeights (OBJECT))
END

FORM (PairDistribution_to_Stringses, "Generate two Strings objects", 0)
	NATURAL ("Number", "1000")
	SENTENCE ("Name of first Strings", "input")
	SENTENCE ("Name of second Strings", "output")
	OK
DO
	Strings strings1, strings2;
	if (! PairDistribution_to_Stringses (ONLY (classPairDistribution), GET_INTEGER ("Number"), & strings1, & strings2)) return 0;
	if (! praat_new (strings1, "%s", GET_STRING ("Name of first Strings"))) { forget (strings2); return 0; }
	if (! praat_new (strings2, "%s", GET_STRING ("Name of second Strings"))) return 0;
END
	
/***** PAIRDISTRIBUTION & DISTRIBUTIONS *****/

FORM (PairDistribution_Distributions_getFractionCorrect, "PairDistribution & Distributions: Get fraction correct", 0)
	NATURAL ("Column", "1")
	OK
DO
	Melder_informationReal (PairDistribution_Distributions_getFractionCorrect
		(ONLY (classPairDistribution), ONLY (classDistributions), GET_INTEGER ("Column")), NULL);
END

/***** PARAMCURVE *****/

FORM (ParamCurve_draw, "Draw parametrized curve", 0)
	REAL ("Tmin", "0.0")
	REAL ("Tmax", "0.0")
	REAL ("Step", "0.0")
	REAL ("Xmin", "0.0")
	REAL ("Xmax", "0.0")
	REAL ("Ymin", "0.0")
	REAL ("Ymax", "0.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (ParamCurve_draw (OBJECT, GRAPHICS,
		GET_REAL ("Tmin"), GET_REAL ("Tmax"), GET_REAL ("Step"),
		GET_REAL ("Xmin"), GET_REAL ("Xmax"), GET_REAL ("Ymin"), GET_REAL ("Ymax"),
		GET_INTEGER ("Garnish")))
END

DIRECT (ParamCurve_help) Melder_help ("ParamCurve"); END

/***** PITCH *****/

DIRECT (Pitch_getNumberOfVoicedFrames)
	Pitch me = ONLY (classPitch);
	Melder_information ("%ld voiced frames", Pitch_countVoicedFrames (me));
END

DIRECT (Pitch_difference)
	Pitch pit1 = NULL, pit2 = NULL;
	WHERE (SELECTED && CLASS == classPitch) { if (pit1) pit2 = OBJECT; else pit1 = OBJECT; }
	Pitch_difference (pit1, pit2);
END

FORM (Pitch_draw, "Pitch: Draw", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	REAL (STRING_FROM_FREQUENCY_HZ, "0.0")
	POSITIVE (STRING_TO_FREQUENCY_HZ, "500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_NO, Pitch_UNIT_HERTZ))
END

FORM (Pitch_drawErb, "Pitch: Draw erb", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	REAL ("left Frequency range (ERB)", "0")
	REAL ("right Frequency range (ERB)", "10.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_NO, Pitch_UNIT_ERB))
END

FORM (Pitch_drawLogarithmic, "Pitch: Draw logarithmic", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	POSITIVE (STRING_FROM_FREQUENCY_HZ, "50.0")
	POSITIVE (STRING_TO_FREQUENCY_HZ, "500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_NO, Pitch_UNIT_HERTZ_LOGARITHMIC))
END

FORM (Pitch_drawMel, "Pitch: Draw mel", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	REAL ("left Frequency range (mel)", "0.0")
	REAL ("right Frequency range (mel)", "500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_NO, Pitch_UNIT_MEL))
END

FORM (Pitch_drawSemitones, "Pitch: Draw semitones", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	LABEL ("", "Range in semitones re 100 Hertz:")
	REAL ("left Frequency range (st)", "-12.0")
	REAL ("right Frequency range (st)", "30.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_NO, Pitch_UNIT_SEMITONES_100))
END

DIRECT (Pitch_edit)
	if (praat.batch)
		return Melder_error ("Cannot edit a Pitch from batch.");
	else
		WHERE (SELECTED)
			if (! praat_installEditor (PitchEditor_create (praat.topShell, FULL_NAME, OBJECT), IOBJECT))
				return 0;
END

FORM (Pitch_formula, "Pitch: Formula", "Formula...")
	LABEL ("", "x = time; col = frame; row = candidate (1 = current path); frequency (time, candidate) :=")
	TEXTFIELD ("formula", "self*2; Example: octave jump up")
	OK
DO
	WHERE (SELECTED) {
		if (! Pitch_formula (OBJECT, GET_STRING ("formula"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (Pitch_getMaximum, "Pitch: Get maximum", 0)
	praat_dia_timeRange (dia);
	dia_pitchUnits (dia);
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	int unit = GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min;
	double value = Pitch_getMaximum (ONLY (classPitch), GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		unit, GET_INTEGER ("Interpolation") - 1);
	value = ClassFunction_convertToNonlogarithmic (classPitch, value, Pitch_LEVEL_FREQUENCY, unit);
	Melder_information ("%s %s", Melder_double (value), ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, unit, 0));
END

FORM (Pitch_getMean, "Pitch: Get mean", 0)
	praat_dia_timeRange (dia);
	dia_pitchUnits (dia);
	OK
DO
	int unit = GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min;
	double value = Pitch_getMean (ONLY (classPitch), GET_REAL ("left Time range"), GET_REAL ("right Time range"), unit);
	value = ClassFunction_convertToNonlogarithmic (classPitch, value, Pitch_LEVEL_FREQUENCY, unit);
	Melder_information ("%s %s", Melder_double (value), ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, unit, 0));
END

FORM (Pitch_getMeanAbsoluteSlope, "Pitch: Get mean absolute slope", 0)
	RADIO ("Unit", 1)
		RADIOBUTTON ("Hertz")
		RADIOBUTTON ("Mel")
		RADIOBUTTON ("Semitones")
		RADIOBUTTON ("ERB")
	OK
DO
	int unit = GET_INTEGER ("Unit");
	double slope;
	long nVoiced = (unit == 1 ? Pitch_getMeanAbsSlope_hertz : unit == 2 ? Pitch_getMeanAbsSlope_mel : unit == 3 ? Pitch_getMeanAbsSlope_semitones : Pitch_getMeanAbsSlope_erb)
		(ONLY (classPitch), & slope);
	Melder_information (nVoiced < 2 ? "--undefined--" : "%.17g %s/s", slope, GET_STRING ("Unit"));
END

DIRECT (Pitch_getMeanAbsSlope_noOctave)
	double slope;
	long nVoiced = Pitch_getMeanAbsSlope_noOctave (ONLY (classPitch), & slope);
	Melder_information (nVoiced < 2 ? "--undefined--" : "%.17g Semitones/s", slope);
END

FORM (Pitch_getMinimum, "Pitch: Get minimum", 0)
	praat_dia_timeRange (dia);
	dia_pitchUnits (dia);
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	int unit = GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min;
	double value = Sampled_getMinimum (ONLY (classPitch), GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		Pitch_LEVEL_FREQUENCY, unit, GET_INTEGER ("Interpolation") - 1);
	value = ClassFunction_convertToNonlogarithmic (classPitch, value, Pitch_LEVEL_FREQUENCY, unit);
	Melder_information ("%s %s", Melder_double (value), ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, unit, 0));
END

FORM (Pitch_getQuantile, "Pitch: Get quantile", 0)
	praat_dia_timeRange (dia);
	REAL ("Quantile", "0.50 (= median)")
	dia_pitchUnits (dia);
	OK
DO
	int unit = GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min;
	double value = Sampled_getQuantile (ONLY (classPitch), GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Quantile"), Pitch_LEVEL_FREQUENCY, unit);
	value = ClassFunction_convertToNonlogarithmic (classPitch, value, Pitch_LEVEL_FREQUENCY, unit);
	Melder_information ("%s %s", Melder_double (value), ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, unit, 0));
END

FORM (Pitch_getStandardDeviation, "Pitch: Get standard deviation", 0)
	praat_dia_timeRange (dia);
	OPTIONMENU ("Unit", 1)
		OPTION ("Hertz")
		OPTION ("mel")
		OPTION ("logHertz")
		OPTION ("semitones")
		OPTION ("ERB")
	OK
DO
	int unit = GET_INTEGER ("Unit");
	double value;
	const char *unitText;
	unit =
		unit == 1 ? Pitch_UNIT_HERTZ :
		unit == 2 ? Pitch_UNIT_MEL :
		unit == 3 ? Pitch_UNIT_LOG_HERTZ :
		unit == 4 ? Pitch_UNIT_SEMITONES_1 :
		Pitch_UNIT_ERB;
	value = Pitch_getStandardDeviation (ONLY (classPitch), GET_REAL ("left Time range"), GET_REAL ("right Time range"), unit);
	unitText =
		unit == Pitch_UNIT_HERTZ ? "Hz" :
		unit == Pitch_UNIT_MEL ? "mel" :
		unit == Pitch_UNIT_LOG_HERTZ ? "logHz" :
		unit == Pitch_UNIT_SEMITONES_1 ? "semitones" :
		"ERB";
	Melder_information ("%s %s", Melder_double (value), unitText);
END

FORM (Pitch_getTimeOfMaximum, "Pitch: Get time of maximum", 0)
	praat_dia_timeRange (dia);
	dia_pitchUnits (dia);
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	Melder_informationReal (Pitch_getTimeOfMaximum (ONLY (classPitch),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min, GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Pitch_getTimeOfMinimum, "Pitch: Get time of minimum", 0)
	praat_dia_timeRange (dia);
	dia_pitchUnits (dia);
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("None")
	RADIOBUTTON ("Parabolic")
	OK
DO
	Melder_informationReal (Pitch_getTimeOfMinimum (ONLY (classPitch),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min, GET_INTEGER ("Interpolation") - 1), "seconds");
END

FORM (Pitch_getValueAtTime, "Pitch: Get value at time", "Pitch: Get value at time...")
	REAL ("Time (s)", "0.5")
	dia_pitchUnits (dia);
	RADIO ("Interpolation", 2)
	RADIOBUTTON ("Nearest")
	RADIOBUTTON ("Linear")
	OK
DO
	int unit = GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min;
	double value = Sampled_getValueAtX (ONLY (classPitch), GET_REAL ("Time"), Pitch_LEVEL_FREQUENCY, unit, GET_INTEGER ("Interpolation") - 1);
	value = ClassFunction_convertToNonlogarithmic (classPitch, value, Pitch_LEVEL_FREQUENCY, unit);
	Melder_information ("%s %s", Melder_double (value), ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, unit, 0));
END
	
FORM (Pitch_getValueInFrame, "Pitch: Get value in frame", "Pitch: Get value in frame...")
	INTEGER ("Frame number", "10")
	dia_pitchUnits (dia);
	OK
DO
	int unit = GET_INTEGER ("Unit") - 1 + Pitch_UNIT_min;
	double value = Sampled_getValueAtSample (ONLY (classPitch), GET_INTEGER ("Frame number"), Pitch_LEVEL_FREQUENCY, unit);
	value = ClassFunction_convertToNonlogarithmic (classPitch, value, Pitch_LEVEL_FREQUENCY, unit);
	Melder_information ("%s %s", Melder_double (value), ClassFunction_getUnitText (classPitch, Pitch_LEVEL_FREQUENCY, unit, 0));
END

DIRECT (Pitch_help) Melder_help ("Pitch"); END

DIRECT (Pitch_hum)
	EVERY_CHECK (Pitch_hum (OBJECT, 0, 0))
END

DIRECT (Pitch_interpolate)
	EVERY_TO (Pitch_interpolate (OBJECT))
END

DIRECT (Pitch_killOctaveJumps)
	EVERY_TO (Pitch_killOctaveJumps (OBJECT))
END

DIRECT (Pitch_play)
	EVERY_CHECK (Pitch_play (OBJECT, 0, 0))
END

FORM (Pitch_smooth, "Pitch: Smooth", "Pitch: Smooth...")
	REAL ("Bandwidth (Hertz)", "10.0")
	OK
DO
	EVERY_TO (Pitch_smooth (OBJECT, GET_REAL ("Bandwidth")))
END

FORM (Pitch_speckle, "Pitch: Speckle", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	REAL (STRING_FROM_FREQUENCY_HZ, "0.0")
	POSITIVE (STRING_TO_FREQUENCY_HZ, "500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_YES, Pitch_UNIT_HERTZ))
END

FORM (Pitch_speckleErb, "Pitch: Speckle erb", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	REAL ("left Frequency range (ERB)", "0")
	REAL ("right Frequency range (ERB)", "10.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_YES, Pitch_UNIT_ERB))
END

FORM (Pitch_speckleLogarithmic, "Pitch: Speckle logarithmic", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	POSITIVE (STRING_FROM_FREQUENCY_HZ, "50.0")
	POSITIVE (STRING_TO_FREQUENCY_HZ, "500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_YES, Pitch_UNIT_HERTZ_LOGARITHMIC))
END

FORM (Pitch_speckleMel, "Pitch: Speckle mel", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	REAL ("left Frequency range (mel)", "0")
	REAL ("right Frequency range (mel)", "500")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_YES, Pitch_UNIT_MEL))
END

FORM (Pitch_speckleSemitones, "Pitch: Speckle semitones", "Pitch: Draw...")
	REAL (STRING_FROM_TIME_SECONDS, "0.0")
	REAL (STRING_TO_TIME_SECONDS, "0.0 (= all)")
	LABEL ("", "Range in semitones re 100 Hertz:")
	REAL ("left Frequency range (st)", "-12.0")
	REAL ("right Frequency range (st)", "30.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	GET_TMIN_TMAX_FMIN_FMAX
	EVERY_DRAW (Pitch_draw (OBJECT, GRAPHICS, tmin, tmax, fmin, fmax,
		GET_INTEGER ("Garnish"), Pitch_speckle_YES, Pitch_UNIT_SEMITONES_100))
END

FORM (Pitch_subtractLinearFit, "Pitch: subtract linear fit", 0)
	RADIO ("Unit", 1)
		RADIOBUTTON ("Hertz")
		RADIOBUTTON ("Hertz (logarithmic)")
		RADIOBUTTON ("Mel")
		RADIOBUTTON ("Semitones")
		RADIOBUTTON ("ERB")
	OK
DO
	EVERY_TO (Pitch_subtractLinearFit (OBJECT, GET_INTEGER ("Unit") - 1))
END

DIRECT (Pitch_to_IntervalTier)
	EVERY_TO (IntervalTier_create (((Pitch) OBJECT) -> xmin, ((Pitch) OBJECT) -> xmax))
END

DIRECT (Pitch_to_Matrix)
	EVERY_TO (Pitch_to_Matrix (OBJECT))
END

DIRECT (Pitch_to_PitchTier)
	EVERY_TO (Pitch_to_PitchTier (OBJECT))
END

DIRECT (Pitch_to_PointProcess)
	EVERY_TO (Pitch_to_PointProcess (OBJECT))
END

DIRECT (Pitch_to_Sound_pulses)
	EVERY_TO (Pitch_to_Sound (OBJECT, 0, 0, FALSE))
END

DIRECT (Pitch_to_Sound_hum)
	EVERY_TO (Pitch_to_Sound (OBJECT, 0, 0, TRUE))
END

FORM (Pitch_to_Sound_sine, "Pitch: To Sound (sine)", 0)
	POSITIVE ("Sampling frequency (Hz)", "44100")
	RADIO ("Cut voiceless stretches", 2)
		OPTION ("exactly")
		OPTION ("at nearest zero crossings")
	OK
DO
	EVERY_TO (Pitch_to_Sound_sine (OBJECT, 0, 0, GET_REAL ("Sampling frequency"), GET_INTEGER ("Cut voiceless stretches") - 1))
END

FORM (Pitch_to_TextGrid, "To TextGrid...", "Pitch: To TextGrid...")
	SENTENCE ("Tier names", "Mary John bell")
	SENTENCE ("Point tiers", "bell")
	OK
DO
	EVERY_TO (TextGrid_create (((Pitch) OBJECT) -> xmin, ((Pitch) OBJECT) -> xmax,
		GET_STRING ("Tier names"), GET_STRING ("Point tiers")))
END

DIRECT (Pitch_to_TextTier)
	EVERY_TO (TextTier_create (((Pitch) OBJECT) -> xmin, ((Pitch) OBJECT) -> xmax))
END

/***** PITCH & PITCHTIER *****/

FORM (PitchTier_Pitch_draw, "PitchTier & Pitch: Draw", 0)
	praat_dia_timeRange (dia);
	REAL ("From frequency (Hz)", "0.0")
	REAL ("To frequency (Hz)", "500.0")
	RADIO ("Line type for non-periodic intervals", 2)
		RADIOBUTTON ("Normal")
		RADIOBUTTON ("Dotted")
		RADIOBUTTON ("Blank")
	BOOLEAN ("Garnish", 1)
	OK
DO
	praat_picture_open ();
	PitchTier_Pitch_draw (ONLY (classPitchTier), ONLY (classPitch), GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("From frequency"), GET_REAL ("To frequency"),
		GET_INTEGER ("Line type for non-periodic intervals") - 1,
		GET_INTEGER ("Garnish"));
	praat_picture_close ();
END

DIRECT (Pitch_PitchTier_to_Pitch)
	Pitch pitch = ONLY (classPitch);
	PitchTier tier = ONLY (classPitchTier);
	if (! praat_new (Pitch_PitchTier_to_Pitch (pitch, tier),
		"%s_stylized", pitch -> name)) return 0;
END

/***** PITCH & POINTPROCESS *****/

DIRECT (Pitch_PointProcess_to_PitchTier)
	Pitch pitch = ONLY (classPitch);
	if (! praat_new (Pitch_PointProcess_to_PitchTier (pitch, ONLY (classPointProcess)), pitch -> name)) return 0;
END

/***** PITCH & SOUND *****/

DIRECT (Sound_Pitch_to_Manipulation)
	Pitch pitch = ONLY (classPitch);
	if (! praat_new (Sound_Pitch_to_Manipulation (ONLY (classSound), pitch), pitch -> name)) return 0;
END

DIRECT (Sound_Pitch_to_PointProcess_cc)
	char name [200];
	praat_name2 (name, classSound, classPitch);
	if (! praat_new (Sound_Pitch_to_PointProcess_cc (ONLY (classSound), ONLY (classPitch)), name)) return 0;
END

FORM (Sound_Pitch_to_PointProcess_peaks, "Sound & Pitch: To PointProcess (peaks)", 0)
	BOOLEAN ("Include maxima", 1)
	BOOLEAN ("Include minima", 0)
	OK
DO
	char name [200];
	praat_name2 (name, classSound, classPitch);
	if (! praat_new (Sound_Pitch_to_PointProcess_peaks (ONLY (classSound), ONLY (classPitch),
		GET_INTEGER ("Include maxima"), GET_INTEGER ("Include minima")), name)) return 0;
END

/***** PITCHTIER *****/

FORM (PitchTier_addPoint, "PitchTier: Add point", "PitchTier: Add point...")
	REAL ("Time (s)", "0.5")
	REAL ("Pitch (Hz)", "200")
	OK
DO
	WHERE (SELECTED) {
		if (! RealTier_addPoint (OBJECT, GET_REAL ("Time"), GET_REAL ("Pitch"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (PitchTier_create, "Create empty PitchTier", NULL)
	WORD ("Name", "empty")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	OK
DO
	double startTime = GET_REAL ("Start time"), endTime = GET_REAL ("End time");
	REQUIRE (endTime > startTime, "End time must be greater than start time.")
	if (! praat_new (PitchTier_create (startTime, endTime), GET_STRING ("Name"))) return 0;
END

DIRECT (PitchTier_downto_PointProcess)
	EVERY_TO (AnyTier_downto_PointProcess (OBJECT))
END

FORM (PitchTier_downto_TableOfReal, "PitchTier: Down to TableOfReal", NULL)
	RADIO ("Unit", 1)
	RADIOBUTTON ("Hertz")
	RADIOBUTTON ("Semitones")
	OK
DO
	EVERY_TO (PitchTier_downto_TableOfReal (OBJECT, GET_INTEGER ("Unit") - 1))
END

FORM (PitchTier_draw, "PitchTier: Draw", 0)
	praat_dia_timeRange (dia);
	REAL ("Minimum frequency (Hz)", "0.0")
	POSITIVE ("Maximum frequency (Hz)", "500.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	double minimumFrequency = GET_REAL ("Minimum frequency");
	double maximumFrequency = GET_REAL ("Maximum frequency");
	REQUIRE (maximumFrequency > minimumFrequency,
		"Maximum frequency must be greater than minimum frequency.")
	EVERY_DRAW (PitchTier_draw (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), minimumFrequency, maximumFrequency,
		GET_INTEGER ("Garnish")))
END

DIRECT (PitchTier_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit a PitchTier from batch.");
	} else {
		Sound sound = NULL;
		WHERE (SELECTED)
			if (CLASS == classSound) sound = OBJECT;
		WHERE (SELECTED && CLASS == classPitchTier)
			if (! praat_installEditor (PitchTierEditor_create (praat.topShell, FULL_NAME,
				OBJECT, sound, TRUE), IOBJECT)) return 0;
	}
END

FORM (PitchTier_formula, "PitchTier: Formula", "PitchTier: Formula...")
	LABEL ("", "# ncol = the number of points")
	LABEL ("", "for col from 1 to ncol")
	LABEL ("", "   # x = the time of the colth point, in seconds")
	LABEL ("", "   # self = the value of the colth point, in Hertz")
	LABEL ("", "   self = `formula'")
	LABEL ("", "endfor")
	TEXTFIELD ("formula", "self * 2 ; one octave up")
	OK
DO
	WHERE_DOWN (SELECTED) {
		RealTier_formula (OBJECT, GET_STRING ("formula"), NULL);
		praat_dataChanged (OBJECT);
		iferror return 0;
	}
END

FORM (PitchTier_getMean_curve, "PitchTier: Get mean (curve)", "PitchTier: Get mean (curve)...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (RealTier_getMean_curve (ONLY_OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range")), "Hz");
END
	
FORM (PitchTier_getMean_points, "PitchTier: Get mean (points)", "PitchTier: Get mean (points)...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (RealTier_getMean_points (ONLY_OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range")), "Hz");
END
	
FORM (PitchTier_getStandardDeviation_curve, "PitchTier: Get standard deviation (curve)", "PitchTier: Get standard deviation (curve)...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (RealTier_getStandardDeviation_curve (ONLY_OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range")), "Hz");
END
	
FORM (PitchTier_getStandardDeviation_points, "PitchTier: Get standard deviation (points)", "PitchTier: Get standard deviation (points)...")
	praat_dia_timeRange (dia);
	OK
DO
	Melder_informationReal (RealTier_getStandardDeviation_points (ONLY_OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range")), "Hz");
END
	
FORM (PitchTier_getValueAtTime, "PitchTier: Get value at time", "PitchTier: Get value at time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (RealTier_getValueAtTime (ONLY_OBJECT, GET_REAL ("Time")), "Hz");
END
	
FORM (PitchTier_getValueAtIndex, "PitchTier: Get value at index", "PitchTier: Get value at index...")
	INTEGER ("Point number", "10")
	OK
DO
	Melder_informationReal (RealTier_getValueAtIndex (ONLY_OBJECT, GET_INTEGER ("Point number")), "Hz");
END

DIRECT (PitchTier_help) Melder_help ("PitchTier"); END

DIRECT (PitchTier_hum)
	EVERY_CHECK (PitchTier_hum (OBJECT))
END

FORM (PitchTier_interpolateQuadratically, "PitchTier: Interpolate quadratically", 0)
	NATURAL ("Number of points per parabola", "4")
	RADIO ("Unit", 2)
	RADIOBUTTON ("Hz")
	RADIOBUTTON ("Semitones")
	OK
DO
	WHERE (SELECTED) {
		RealTier_interpolateQuadratically (OBJECT, GET_INTEGER ("Number of points per parabola"), GET_INTEGER ("Unit") - 1);
		praat_dataChanged (OBJECT);
	}
END

DIRECT (PitchTier_play)
	EVERY_CHECK (PitchTier_play (OBJECT))
END

DIRECT (PitchTier_playSine)
	EVERY_CHECK (PitchTier_playPart_sine (OBJECT, 0.0, 0.0))
END

FORM (PitchTier_shiftFrequencies, "PitchTier: Shift frequencies", 0)
	REAL ("left Time range (s)", "0.0")
	REAL ("right Time range (s)", "1000.0")
	REAL ("Frequency shift", "-20.0")
	OPTIONMENU ("Unit", 1)
		OPTION ("Hertz")
		OPTION ("mel")
		OPTION ("logHertz")
		OPTION ("semitones")
		OPTION ("ERB")
	OK
DO
	int unit = GET_INTEGER ("Unit");
	unit =
		unit == 1 ? Pitch_UNIT_HERTZ :
		unit == 2 ? Pitch_UNIT_MEL :
		unit == 3 ? Pitch_UNIT_LOG_HERTZ :
		unit == 4 ? Pitch_UNIT_SEMITONES_1 :
		Pitch_UNIT_ERB;
	WHERE (SELECTED) {
		PitchTier_shiftFrequencies (OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_REAL ("Frequency shift"), unit);
		iferror return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (PitchTier_multiplyFrequencies, "PitchTier: Multiply frequencies", 0)
	REAL ("left Time range (s)", "0.0")
	REAL ("right Time range (s)", "1000.0")
	POSITIVE ("Factor", "1.2")
	OK
DO
	WHERE (SELECTED) {
		PitchTier_multiplyFrequencies (OBJECT,
			GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_REAL ("Factor"));
		praat_dataChanged (OBJECT);
	}
END

FORM (PitchTier_stylize, "PitchTier: Stylize", "PitchTier: Stylize...")
	REAL ("Frequency resolution", "4.0")
	RADIO ("Unit", 2)
	RADIOBUTTON ("Hz")
	RADIOBUTTON ("Semitones")
	OK
DO
	WHERE (SELECTED) {
		PitchTier_stylize (OBJECT, GET_REAL ("Frequency resolution"), GET_INTEGER ("Unit") - 1);
		praat_dataChanged (OBJECT);
	}
END

DIRECT (PitchTier_to_PointProcess)
	EVERY_TO (PitchTier_to_PointProcess (OBJECT))
END

FORM (PitchTier_to_Sound_phonation, "PitchTier: To Sound (phonation)", 0)
	POSITIVE ("Sampling frequency (Hz)", "44100")
	POSITIVE ("Adaptation factor", "1.0")
	POSITIVE ("Maximum period (s)", "0.05")
	POSITIVE ("Open phase", "0.7")
	REAL ("Collision phase", "0.03")
	POSITIVE ("Power 1", "3.0")
	POSITIVE ("Power 2", "4.0")
	BOOLEAN ("Hum", 0)
	OK
DO
	EVERY_TO (PitchTier_to_Sound_phonation (OBJECT, GET_REAL ("Sampling frequency"),
		GET_REAL ("Adaptation factor"), GET_REAL ("Maximum period"),
		GET_REAL ("Open phase"), GET_REAL ("Collision phase"), GET_REAL ("Power 1"), GET_REAL ("Power 2"), GET_INTEGER ("Hum")))
END

FORM (PitchTier_to_Sound_pulseTrain, "PitchTier: To Sound (pulse train)", 0)
	POSITIVE ("Sampling frequency (Hz)", "44100")
	POSITIVE ("Adaptation factor", "1.0")
	POSITIVE ("Adaptation time", "0.05")
	NATURAL ("Interpolation depth (samples)", "2000")
	BOOLEAN ("Hum", 0)
	OK
DO
	EVERY_TO (PitchTier_to_Sound_pulseTrain (OBJECT, GET_REAL ("Sampling frequency"),
		GET_REAL ("Adaptation factor"), GET_REAL ("Adaptation time"),
		GET_INTEGER ("Interpolation depth"), GET_INTEGER ("Hum")))
END

FORM (PitchTier_to_Sound_sine, "PitchTier: To Sound (sine)", 0)
	POSITIVE ("Sampling frequency (Hz)", "44100")
	OK
DO
	EVERY_TO (PitchTier_to_Sound_sine (OBJECT, 0.0, 0.0, GET_REAL ("Sampling frequency")))
END

DIRECT (info_PitchTier_Sound_edit)
	Melder_information ("To include a copy of a Sound in your PitchTier editor:\n"
		"   select a PitchTier and a Sound, and click \"Edit\".");
END

FORM_WRITE (PitchTier_writeToPitchTierSpreadsheetFile, "Write PitchTier to spreadsheet", 0, "PitchTier")
	if (! PitchTier_writeToPitchTierSpreadsheetFile (ONLY_OBJECT, file)) return 0;
END

FORM_WRITE (PitchTier_writeToHeaderlessSpreadsheetFile, "Write PitchTier to spreadsheet", 0, "txt")
	if (! PitchTier_writeToHeaderlessSpreadsheetFile (ONLY_OBJECT, file)) return 0;
END

/***** PITCHTIER & POINTPROCESS *****/

DIRECT (PitchTier_PointProcess_to_PitchTier)
	PitchTier pitch = ONLY (classPitchTier);
	if (! praat_new (PitchTier_PointProcess_to_PitchTier (pitch, ONLY (classPointProcess)), pitch -> name)) return 0;
END

/***** POINTPROCESS *****/

FORM (PointProcess_addPoint, "PointProcess: Add point", "PointProcess: Add point...")
	REAL ("Time (s)", "0.5")
	OK
DO
	WHERE (SELECTED) {
		if (! PointProcess_addPoint (OBJECT, GET_REAL ("Time"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (PointProcess_createEmpty, "Create an empty PointProcess", "Create empty PointProcess...")
	WORD ("Name", "empty")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	OK
DO
	double tmin = GET_REAL ("Start time"), tmax = GET_REAL ("End time");
	if (tmax < tmin)
		return Melder_error ("End time (%.8g) should not be less than start time (%.8g).", tmax, tmin);
	if (! praat_new (PointProcess_create (tmin, tmax, 0), GET_STRING ("Name"))) return 0;
END

FORM (PointProcess_createPoissonProcess, "Create Poisson process", "Create Poisson process...")
	WORD ("Name", "poisson")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	POSITIVE ("Density (/s)", "100.0")
	OK
DO
	double tmin = GET_REAL ("Start time"), tmax = GET_REAL ("End time");
	if (tmax < tmin)
		return Melder_error ("End time (%.8g) should not be less than start time (%.8g).", tmax, tmin);
	if (! praat_new (PointProcess_createPoissonProcess (tmin, tmax, GET_REAL ("Density")), GET_STRING ("Name"))) return 0;
END

DIRECT (PointProcess_difference)
	PointProcess point1 = NULL, point2 = NULL;
	WHERE (SELECTED) { if (point1) point2 = OBJECT; else point1 = OBJECT; }
	if (! praat_new (PointProcesses_difference (point1, point2), "difference")) return 0;
END

FORM (PointProcess_draw, "PointProcess: Draw", 0)
	praat_dia_timeRange (dia);
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (PointProcess_draw (OBJECT, GRAPHICS,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_INTEGER ("Garnish")))
END

DIRECT (PointProcess_edit)
	if (praat.batch) {
		return Melder_error ("Cannot edit a PointProcess from batch.");
	} else {
		Sound sound = NULL;
		WHERE (SELECTED)
			if (CLASS == classSound) sound = OBJECT;
		WHERE (SELECTED && CLASS == classPointProcess)
			if (! praat_installEditor (PointEditor_create (praat.topShell, FULL_NAME,
				OBJECT, sound, TRUE), IOBJECT)) return 0;
	}
END

FORM (PointProcess_fill, "PointProcess: Fill", 0)
	praat_dia_timeRange (dia);
	POSITIVE ("Period (s)", "0.01")
	OK
DO
	WHERE (SELECTED) {
		int status = PointProcess_fill (OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range"), GET_REAL ("Period"));
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

FORM (PointProcess_getInterval, "PointProcess: Get interval", "PointProcess: Get interval...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (PointProcess_getInterval (ONLY (classPointProcess), GET_REAL ("Time")), "seconds");
END

static void dia_PointProcess_getRangeProperty (Any dia) {
	praat_dia_timeRange (dia);
	REAL ("Shortest period (s)", "0.0001")
	REAL ("Longest period (s)", "0.02")
	POSITIVE ("Maximum period factor", "1.3")
}

FORM (PointProcess_getJitter_local, "PointProcess: Get jitter (local)", "PointProcess: Get jitter (local)...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getJitter_local (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), NULL);
END

FORM (PointProcess_getJitter_local_absolute, "PointProcess: Get jitter (local, absolute)", "PointProcess: Get jitter (local, absolute)...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getJitter_local_absolute (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), " seconds");
END

FORM (PointProcess_getJitter_rap, "PointProcess: Get jitter (rap)", "PointProcess: Get jitter (rap)...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getJitter_rap (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), NULL);
END

FORM (PointProcess_getJitter_ppq5, "PointProcess: Get jitter (ppq5)", "PointProcess: Get jitter (ppq5)...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getJitter_ppq5 (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), NULL);
END

FORM (PointProcess_getJitter_ddp, "PointProcess: Get jitter (ddp)", "PointProcess: Get jitter (ddp)...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getJitter_ddp (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), NULL);
END

FORM (PointProcess_getMeanPeriod, "PointProcess: Get mean period", "PointProcess: Get mean period...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getMeanPeriod (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), "seconds");
END

FORM (PointProcess_getStdevPeriod, "PointProcess: Get stdev period", "PointProcess: Get stdev period...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_informationReal (PointProcess_getStdevPeriod (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), "seconds");
END

FORM (PointProcess_getLowIndex, "PointProcess: Get low index", "PointProcess: Get low index...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_information ("%ld", PointProcess_getLowIndex (ONLY_OBJECT, GET_REAL ("Time")));
END

FORM (PointProcess_getHighIndex, "PointProcess: Get high index", "PointProcess: Get high index...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_information ("%ld", PointProcess_getHighIndex (ONLY_OBJECT, GET_REAL ("Time")));
END

FORM (PointProcess_getNearestIndex, "PointProcess: Get nearest index", "PointProcess: Get nearest index...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_information ("%ld", PointProcess_getNearestIndex (ONLY_OBJECT, GET_REAL ("Time")));
END

DIRECT (PointProcess_getNumberOfPoints)
	PointProcess me = ONLY_OBJECT;
	Melder_information ("%ld", my nt);
END

FORM (PointProcess_getNumberOfPeriods, "PointProcess: Get number of periods", "PointProcess: Get number of periods...")
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	Melder_information ("%ld", PointProcess_getNumberOfPeriods (ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")));
END

FORM (PointProcess_getTimeFromIndex, "Get time", 0 /*"PointProcess: Get time from index..."*/)
	NATURAL ("Point number", "10")
	OK
DO
	PointProcess me = ONLY_OBJECT;
	long i = GET_INTEGER ("Point number");
	if (i > my nt) Melder_information ("--undefined--");
	else Melder_informationReal (my t [i], "seconds");
END

DIRECT (PointProcess_help) Melder_help ("PointProcess"); END

DIRECT (PointProcess_hum)
	EVERY_CHECK (PointProcess_hum (OBJECT,
		((PointProcess) OBJECT) -> xmin, ((PointProcess) OBJECT) -> xmax))
END

DIRECT (PointProcess_intersection)
	PointProcess point1 = NULL, point2 = NULL;
	WHERE (SELECTED) { if (point1) point2 = OBJECT; else point1 = OBJECT; }
	if (! praat_new (PointProcesses_intersection (point1, point2), "intersection")) return 0;
END

DIRECT (PointProcess_play)
	EVERY_CHECK (PointProcess_play (OBJECT))
END

FORM (PointProcess_removePoint, "PointProcess: Remove point", "PointProcess: Remove point...")
	NATURAL ("Index", "1")
	OK
DO
	WHERE (SELECTED) {
		PointProcess_removePoint (OBJECT, GET_INTEGER ("Index"));
		praat_dataChanged (OBJECT);
	}
END

FORM (PointProcess_removePointNear, "PointProcess: Remove point near", "PointProcess: Remove point near...")
	REAL ("Time (s)", "0.5")
	OK
DO
	WHERE (SELECTED) {
		PointProcess_removePointNear (OBJECT, GET_REAL ("Time"));
		praat_dataChanged (OBJECT);
	}
END

FORM (PointProcess_removePoints, "PointProcess: Remove points", "PointProcess: Remove points...")
	NATURAL ("From index", "1")
	NATURAL ("To index", "10")
	OK
DO
	WHERE (SELECTED) {
		PointProcess_removePoints (OBJECT, GET_INTEGER ("From index"), GET_INTEGER ("To index"));
		praat_dataChanged (OBJECT);
	}
END

FORM (PointProcess_removePointsBetween, "PointProcess: Remove points between", "PointProcess: Remove points between...")
	REAL ("left Time range (s)", "0.3")
	REAL ("right Time range (s)", "0.7")
	OK
DO
	WHERE (SELECTED) {
		PointProcess_removePointsBetween (OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range"));
		praat_dataChanged (OBJECT);
	}
END

DIRECT (PointProcess_to_IntervalTier)
	EVERY_TO (IntervalTier_create (((PointProcess) OBJECT) -> xmin, ((PointProcess) OBJECT) -> xmax))
END

DIRECT (PointProcess_to_Matrix)
	EVERY_TO (PointProcess_to_Matrix (OBJECT))
END

FORM (PointProcess_to_PitchTier, "PointProcess: To PitchTier", "PointProcess: To PitchTier...")
	POSITIVE ("Maximum interval (s)", "0.02")
	OK
DO
	EVERY_TO (PointProcess_to_PitchTier (OBJECT, GET_REAL ("Maximum interval")))
END

FORM (PointProcess_to_TextGrid, "PointProcess: To TextGrid...", "PointProcess: To TextGrid...")
	SENTENCE ("Tier names", "Mary John bell")
	SENTENCE ("Point tiers", "bell")
	OK
DO
	EVERY_TO (TextGrid_create (((PointProcess) OBJECT) -> xmin, ((PointProcess) OBJECT) -> xmax,
		GET_STRING ("Tier names"), GET_STRING ("Point tiers")))
END

FORM (PointProcess_to_TextGrid_vuv, "PointProcess: To TextGrid (vuv)...", "PointProcess: To TextGrid (vuv)...")
	POSITIVE ("Maximum period (s)", "0.02")
	REAL ("Mean period (s)", "0.01")
	OK
DO
	EVERY_TO (PointProcess_to_TextGrid_vuv (OBJECT, GET_REAL ("Maximum period"),
		GET_REAL ("Mean period")))
END

DIRECT (PointProcess_to_TextTier)
	EVERY_TO (TextTier_create (((PointProcess) OBJECT) -> xmin, ((PointProcess) OBJECT) -> xmax))
END

FORM (PointProcess_to_Sound_phonation, "PointProcess: To Sound (phonation)", "PointProcess: To Sound (phonation)...")
	POSITIVE ("Sampling frequency (Hz)", "44100")
	POSITIVE ("Adaptation factor", "1.0")
	POSITIVE ("Maximum period (s)", "0.05")
	POSITIVE ("Open phase", "0.7")
	REAL ("Collision phase", "0.03")
	POSITIVE ("Power 1", "3.0")
	POSITIVE ("Power 2", "4.0")
	OK
DO
	EVERY_TO (PointProcess_to_Sound_phonation (OBJECT, GET_REAL ("Sampling frequency"),
		GET_REAL ("Adaptation factor"), GET_REAL ("Maximum period"),
		GET_REAL ("Open phase"), GET_REAL ("Collision phase"), GET_REAL ("Power 1"), GET_REAL ("Power 2")))
END

FORM (PointProcess_to_Sound_pulseTrain, "PointProcess: To Sound (pulse train)", "PointProcess: To Sound (pulse train)...")
	POSITIVE ("Sampling frequency (Hz)", "44100")
	POSITIVE ("Adaptation factor", "1.0")
	POSITIVE ("Adaptation time (s)", "0.05")
	NATURAL ("Interpolation depth (samples)", "2000")
	OK
DO
	EVERY_TO (PointProcess_to_Sound_pulseTrain (OBJECT, GET_REAL ("Sampling frequency"),
		GET_REAL ("Adaptation factor"), GET_REAL ("Adaptation time"),
		GET_INTEGER ("Interpolation depth")))
END

DIRECT (PointProcess_to_Sound_hum)
	EVERY_TO (PointProcess_to_Sound_hum (OBJECT))
END

DIRECT (PointProcess_union)
	PointProcess point1 = NULL, point2 = NULL;
	WHERE (SELECTED) { if (point1) point2 = OBJECT; else point1 = OBJECT; }
	if (! praat_new (PointProcesses_union (point1, point2), "union")) return 0;
END

FORM (PointProcess_upto_IntensityTier, "PointProcess: Up to IntensityTier", "PointProcess: Up to IntensityTier...")
	POSITIVE ("Intensity (dB)", "70.0")
	OK
DO
	EVERY_TO (PointProcess_upto_IntensityTier (OBJECT, GET_REAL ("Intensity")))
END

FORM (PointProcess_upto_PitchTier, "PointProcess: Up to PitchTier", "PointProcess: Up to PitchTier...")
	POSITIVE ("Frequency (Hz)", "190.0")
	OK
DO
	EVERY_TO (PointProcess_upto_PitchTier (OBJECT, GET_REAL ("Frequency")))
END

FORM (PointProcess_upto_TextTier, "PointProcess: Up to TextTier", "PointProcess: Up to TextTier...")
	SENTENCE ("Text", "")
	OK
DO
	EVERY_TO (PointProcess_upto_TextTier (OBJECT, GET_STRING ("Text")))
END

FORM (PointProcess_voice, "PointProcess: Fill unvoiced parts", 0)
	POSITIVE ("Period (s)", "0.01")
	POSITIVE ("Maximum voiced period (s)", "0.02000000001")
	OK
DO
	WHERE (SELECTED) {
		int status = PointProcess_voice (OBJECT, GET_REAL ("Period"), GET_REAL ("Maximum voiced period"));
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

DIRECT (info_PointProcess_Sound_edit)
	Melder_information ("To include a copy of a Sound in your PointProcess editor:\n"
		"   select a PointProcess and a Sound, and click \"Edit\".");
END

/***** POINTPROCESS & SOUND *****/

/*DIRECT (Sound_PointProcess_to_Manipulation)
	Sound sound = ONLY (classSound);
	PointProcess point = ONLY (classPointProcess);
	if (! praat_new (Sound_PointProcess_to_Manipulation (sound, point), point -> name)) return 0;
END*/

DIRECT (Point_Sound_transplantDomain)
	PointProcess point = ONLY (classPointProcess);
	Sound sound = ONLY (classSound);
	point -> xmin = sound -> xmin;
	point -> xmax = sound -> xmax;
	praat_dataChanged (point);
END

FORM (Point_Sound_getShimmer_local, "PointProcess & Sound: Get shimmer (local)", "PointProcess & Sound: Get shimmer (local)...")
	dia_PointProcess_getRangeProperty (dia);
	POSITIVE ("Maximum amplitude factor", "1.6")
	OK
DO
	Melder_informationReal (PointProcess_Sound_getShimmer_local (ONLY (classPointProcess), ONLY (classSound),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (Point_Sound_getShimmer_local_dB, "PointProcess & Sound: Get shimmer (local, dB)", "PointProcess & Sound: Get shimmer (local, dB)...")
	dia_PointProcess_getRangeProperty (dia);
	POSITIVE ("Maximum amplitude factor", "1.6")
	OK
DO
	Melder_informationReal (PointProcess_Sound_getShimmer_local_dB (ONLY (classPointProcess), ONLY (classSound),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (Point_Sound_getShimmer_apq3, "PointProcess & Sound: Get shimmer (apq3)", "PointProcess & Sound: Get shimmer (apq3)...")
	dia_PointProcess_getRangeProperty (dia);
	POSITIVE ("Maximum amplitude factor", "1.6")
	OK
DO
	Melder_informationReal (PointProcess_Sound_getShimmer_apq3 (ONLY (classPointProcess), ONLY (classSound),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (Point_Sound_getShimmer_apq5, "PointProcess & Sound: Get shimmer (apq)", "PointProcess & Sound: Get shimmer (apq5)...")
	dia_PointProcess_getRangeProperty (dia);
	POSITIVE ("Maximum amplitude factor", "1.6")
	OK
DO
	Melder_informationReal (PointProcess_Sound_getShimmer_apq5 (ONLY (classPointProcess), ONLY (classSound),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (Point_Sound_getShimmer_apq11, "PointProcess & Sound: Get shimmer (apq11)", "PointProcess & Sound: Get shimmer (apq11)...")
	dia_PointProcess_getRangeProperty (dia);
	POSITIVE ("Maximum amplitude factor", "1.6")
	OK
DO
	Melder_informationReal (PointProcess_Sound_getShimmer_apq11 (ONLY (classPointProcess), ONLY (classSound),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (Point_Sound_getShimmer_dda, "PointProcess & Sound: Get shimmer (dda)", "PointProcess & Sound: Get shimmer (dda)...")
	dia_PointProcess_getRangeProperty (dia);
	POSITIVE ("Maximum amplitude factor", "1.6")
	OK
DO
	Melder_informationReal (PointProcess_Sound_getShimmer_dda (ONLY (classPointProcess), ONLY (classSound),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor")), NULL);
END

FORM (PointProcess_Sound_to_AmplitudeTier_period, "PointProcess & Sound: To AmplitudeTier (period)", 0)
	dia_PointProcess_getRangeProperty (dia);
	OK
DO
	PointProcess point = ONLY (classPointProcess);
	Sound sound = ONLY (classSound);
	if (! praat_new (PointProcess_Sound_to_AmplitudeTier_period (point, sound,
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), "%s_%s", sound -> name, point -> name)) return 0;
END

DIRECT (PointProcess_Sound_to_AmplitudeTier_point)
	PointProcess point = ONLY (classPointProcess);
	Sound sound = ONLY (classSound);
	if (! praat_new (PointProcess_Sound_to_AmplitudeTier_point (point, sound), "%s_%s", sound -> name, point -> name)) return 0;
END

FORM (PointProcess_Sound_to_Ltas, "PointProcess & Sound: To Ltas", 0)
	POSITIVE ("Maximum frequency (Hz)", "5000")
	POSITIVE ("Band width (Hz)", "100")
	REAL ("Shortest period (s)", "0.0001")
	REAL ("Longest period (s)", "0.02")
	POSITIVE ("Maximum period factor", "1.3")
	OK
DO
	PointProcess point = ONLY (classPointProcess);
	Sound sound = ONLY (classSound);
	if (! praat_new (PointProcess_Sound_to_Ltas (point, sound,
		GET_REAL ("Maximum frequency"), GET_REAL ("Band width"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), "%s", sound -> name)) return 0;
END

FORM (PointProcess_Sound_to_Ltas_harmonics, "PointProcess & Sound: To Ltas (harmonics", 0)
	NATURAL ("Maximum harmonic", "20")
	REAL ("Shortest period (s)", "0.0001")
	REAL ("Longest period (s)", "0.02")
	POSITIVE ("Maximum period factor", "1.3")
	OK
DO
	PointProcess point = ONLY (classPointProcess);
	Sound sound = ONLY (classSound);
	if (! praat_new (PointProcess_Sound_to_Ltas_harmonics (point, sound,
		GET_INTEGER ("Maximum harmonic"),
		GET_REAL ("Shortest period"), GET_REAL ("Longest period"), GET_REAL ("Maximum period factor")), "%s", sound -> name)) return 0;
END

/***** POLYGON *****/

FORM (Polygon_draw, "Polygon: Draw", 0)
	REAL ("Xmin", "0.0")
	REAL ("Xmax", "0.0")
	REAL ("Ymin", "0.0")
	REAL ("Ymax", "0.0")
	OK
DO
	EVERY_DRAW (Polygon_draw (OBJECT, GRAPHICS, GET_REAL ("Xmin"), GET_REAL ("Xmax"),
		GET_REAL ("Ymin"), GET_REAL ("Ymax")))
END

FORM (Polygon_drawCircles, "Polygon: Draw circles", 0)
	REAL ("Xmin", "0.0")
	REAL ("Xmax", "0.0 (= all)")
	REAL ("Ymin", "0.0")
	REAL ("Ymax", "0.0 (= all)")
	POSITIVE ("Diameter (mm)", "3")
	OK
DO
	EVERY_DRAW (Polygon_drawCircles (OBJECT, GRAPHICS,
		GET_REAL ("Xmin"), GET_REAL ("Xmax"), GET_REAL ("Ymin"), GET_REAL ("Ymax"),
		GET_REAL ("Diameter")))
END

FORM (Polygons_drawConnection, "Polygons: Draw connection", 0)
	REAL ("Xmin", "0.0")
	REAL ("Xmax", "0.0 (= all)")
	REAL ("Ymin", "0.0")
	REAL ("Ymax", "0.0 (= all)")
	BOOLEAN ("Arrow", 0)
	POSITIVE ("Relative length", "0.9")
	OK
DO
	Polygon polygon1 = NULL, polygon2 = NULL;
	WHERE (SELECTED) { if (polygon1) polygon2 = OBJECT; else polygon1 = OBJECT; }
	EVERY_DRAW (Polygons_drawConnection (polygon1, polygon2, GRAPHICS,
		GET_REAL ("Xmin"), GET_REAL ("Xmax"), GET_REAL ("Ymin"), GET_REAL ("Ymax"),
		GET_INTEGER ("Arrow"), GET_REAL ("Relative length")))
END

DIRECT (Polygon_help) Melder_help ("Polygon"); END

FORM (Polygon_paint, "Polygon: Paint", 0)
	COLOUR ("Colour (0-1 or name)", "0.5")
	REAL ("Xmin", "0.0")
	REAL ("Xmax", "0.0 (= all)")
	REAL ("Ymin", "0.0")
	REAL ("Ymax", "0.0 (= all)")
	OK
DO
	EVERY_DRAW (Polygon_paint (OBJECT, GRAPHICS, GET_REAL ("Colour"),
		GET_REAL ("Xmin"), GET_REAL ("Xmax"), GET_REAL ("Ymin"), GET_REAL ("Ymax")))
END

FORM (Polygon_paintCircles, "Polygon: Paint circles", 0)
	REAL ("Xmin", "0.0")
	REAL ("Xmax", "0.0 (= all)")
	REAL ("Ymin", "0.0")
	REAL ("Ymax", "0.0 (= all)")
	POSITIVE ("Diameter (mm)", "3")
	OK
DO
	EVERY_DRAW (Polygon_paintCircles (OBJECT, GRAPHICS,
		GET_REAL ("Xmin"), GET_REAL ("Xmax"), GET_REAL ("Ymin"), GET_REAL ("Ymax"),
		GET_REAL ("Diameter")))
END

DIRECT (Polygon_randomize)
	EVERY (Polygon_randomize (OBJECT))
END

FORM (Polygon_salesperson, "Polygon: Find shortest path", 0)
	NATURAL ("Number of iterations", "1")
	OK
DO
	EVERY (Polygon_salesperson (OBJECT, GET_INTEGER ("Number of iterations")))
END

DIRECT (Polygon_to_Matrix)
	EVERY_TO (Polygon_to_Matrix (OBJECT))
END

/***** SOUND & PITCH & POINTPROCESS *****/

FORM (Sound_Pitch_PointProcess_voiceReport, "Voice report", "Voice")
	praat_dia_timeRange (dia);
	POSITIVE ("left Pitch range (Hz)", "75.0")
	POSITIVE ("right Pitch range (Hz)", "600.0")
	POSITIVE ("Maximum period factor", "1.3")
	POSITIVE ("Maximum amplitude factor", "1.6")
	REAL ("Silence threshold", "0.03")
	REAL ("Voicing threshold", "0.45")
	OK
DO
	MelderInfo_open ();
	Sound_Pitch_PointProcess_voiceReport (ONLY (classSound), ONLY (classPitch), ONLY (classPointProcess),
		GET_REAL ("left Time range"), GET_REAL ("right Time range"),
		GET_REAL ("left Pitch range"), GET_REAL ("right Pitch range"),
		GET_REAL ("Maximum period factor"), GET_REAL ("Maximum amplitude factor"),
		GET_REAL ("Silence threshold"), GET_REAL ("Voicing threshold"));
	MelderInfo_close ();
END

/***** SOUND & POINTPROCESS & PITCHTIER & DURATIONTIER *****/

FORM (Sound_Point_Pitch_Duration_to_Sound, "To Sound", 0)
	POSITIVE ("Longest period (s)", "0.02")
	OK
DO
	if (! praat_new (Sound_Point_Pitch_Duration_to_Sound (ONLY (classSound), ONLY (classPointProcess),
		ONLY (classPitchTier), ONLY (classDurationTier), GET_REAL ("Longest period")), "manip")) return 0;
END

/***** SPECTROGRAM *****/

FORM (Spectrogram_paint, "Spectrogram: Paint", "Spectrogram: Paint...")
	praat_dia_timeRange (dia);
	REAL ("left Frequency range (Hz)", "0.0")
	REAL ("right Frequency range (Hz)", "0.0 (= all)")
	REAL ("Maximum (dB/Hz)", "100.0")
	BOOLEAN ("Autoscaling", 1)
	POSITIVE ("Dynamic range (dB)", "50.0")
	REAL ("Pre-emphasis (dB/oct)", "6.0")
	REAL ("Dynamic compression (0-1)", "0.0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Spectrogram_paint (OBJECT, GRAPHICS, GET_REAL ("left Time range"),
		GET_REAL ("right Time range"), GET_REAL ("left Frequency range"), GET_REAL ("right Frequency range"),
		GET_REAL ("Maximum"), GET_INTEGER ("Autoscaling"),
		GET_REAL ("Dynamic range"), GET_REAL ("Pre-emphasis"),
		GET_REAL ("Dynamic compression"), GET_INTEGER ("Garnish")))
END

FORM (Spectrogram_formula, "Spectrogram: Formula", "Spectrogram: Formula...")
	LABEL ("label", "Do for all times and frequencies:")
	LABEL ("label", "   `x' is the time in seconds")
	LABEL ("label", "   `y' is the frequency in Hertz")
	LABEL ("label", "   `self' is the current value in Pa^2/Hz")
	LABEL ("label", "   Replace all values with:")
	TEXTFIELD ("formula", "self * exp (- x / 0.1)")
	OK
DO
	return praat_Fon_formula (dia);
END

FORM (Spectrogram_getPowerAt, "Spectrogram: Get power at (time, frequency)", 0)
	REAL ("Time (s)", "0.5")
	REAL ("Frequency (Hz)", "1000")
	OK
DO
	Spectrogram me = ONLY_OBJECT;
	double time = GET_REAL ("Time"), frequency = GET_REAL ("Frequency");
	MelderInfo_open ();
	MelderInfo_write1 (Melder_double (Matrix_getValueAtXY (me, time, frequency)));
	MelderInfo_write5 (" Pa2/Hz (at time = ", Melder_double (time), " seconds and frequency = ", Melder_double (frequency), " Hz)");
	MelderInfo_close ();
END

DIRECT (Spectrogram_help) Melder_help ("Spectrogram"); END

DIRECT (Spectrogram_movie)
	Graphics g = Movie_create ("Spectrogram movie", 300, 300);
	WHERE (SELECTED) Matrix_movie (OBJECT, g);
END

DIRECT (Spectrogram_to_Matrix)
	EVERY_TO (Spectrogram_to_Matrix (OBJECT))
END

FORM (Spectrogram_to_Sound, "Spectrogram: To Sound", 0)
	REAL ("Sampling frequency (Hz)", "44100")
	OK
DO
	EVERY_TO (Spectrogram_to_Sound (OBJECT, GET_REAL ("Sampling frequency")))
END

FORM (Spectrogram_to_Spectrum, "Spectrogram: To Spectrum (slice)", 0)
	REAL ("Time (seconds)", "0.0")
	OK
DO
	EVERY_TO (Spectrogram_to_Spectrum (OBJECT, GET_REAL ("Time")))
END

DIRECT (Spectrogram_view)
	if (praat.batch)
		return Melder_error ("Cannot view a Spectrogram from batch.");
	else
		WHERE (SELECTED)
			if (! praat_installEditor
				(SpectrogramEditor_create (praat.topShell, FULL_NAME, OBJECT), IOBJECT))
					return 0;
END

/***** SPECTRUM *****/

FORM (Spectrum_cepstralSmoothing, "Spectrum: Cepstral smoothing", 0)
	POSITIVE ("Bandwidth (Hz)", "500.0")
	OK
DO
	EVERY_TO (Spectrum_cepstralSmoothing (OBJECT, GET_REAL ("Bandwidth")))
END

FORM (Spectrum_draw, "Spectrum: Draw", 0)
	REAL ("left Frequency range (Hz)", "0.0")
	REAL ("right Frequency range (Hz)", "0.0 (= all)")
	REAL ("Minimum power (dB/Hz)", "0 (= auto)")
	REAL ("Maximum power (dB/Hz)", "0 (= auto)")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Spectrum_draw (OBJECT, GRAPHICS, GET_REAL ("left Frequency range"),
		GET_REAL ("right Frequency range"), GET_REAL ("Minimum power"), GET_REAL ("Maximum power"),
		GET_INTEGER ("Garnish")))
END

FORM (Spectrum_drawLogFreq, "Spectrum: Draw (log freq)", 0)
	POSITIVE ("left Frequency range (Hz)", "10.0")
	POSITIVE ("right Frequency range (Hz)", "10000.0")
	REAL ("Minimum power (dB/Hz)", "0 (= auto)")
	REAL ("Maximum power (dB/Hz)", "0 (= auto)")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (Spectrum_drawLogFreq (OBJECT, GRAPHICS, GET_REAL ("left Frequency range"),
		GET_REAL ("right Frequency range"), GET_REAL ("Minimum power"), GET_REAL ("Maximum power"),
		GET_INTEGER ("Garnish")))
END

DIRECT (Spectrum_edit)
	if (praat.batch) return Melder_error ("Cannot edit a Spectrum from batch.");
	else WHERE (SELECTED)
		if (! praat_installEditor (SpectrumEditor_create (praat.topShell, FULL_NAME, OBJECT), IOBJECT)) return 0;
END

FORM (Spectrum_formula, "Spectrum: Formula", "Spectrum: Formula...")
	LABEL ("label", "`x' is the frequency in Hertz, `col' is the bin number;   "
		"`y' = `row' is 1 (real part) or 2 (imaginary part)")
	LABEL ("label", "y := 1;   row := 1;   "
		"x := 0;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
	LABEL ("label", "y := 2;   row := 2;   "
		"x := 0;   for col := 1 to ncol do { self [2, col] := `formula' ; x := x + dx }")
	TEXTFIELD ("formula", "0")
	OK
DO
	if (! praat_Fon_formula (dia)) return 0;
END

FORM (Spectrum_getBandDensity, "Spectrum: Get band density", 0)
	REAL ("Band floor (Hz)", "200.0") REAL ("Band ceiling (Hz)", "1000") OK DO
	Melder_informationReal (Spectrum_getBandDensity (ONLY_OBJECT,
		GET_REAL ("Band floor"), GET_REAL ("Band ceiling")), " Pa2 / Hz2"); END
FORM (Spectrum_getBandDensityDifference, "Spectrum: Get band density difference", 0)
	REAL ("Low band floor (Hz)", "0") REAL ("Low band ceiling (Hz)", "500")
	REAL ("High band floor (Hz)", "500") REAL ("High band ceiling (Hz)", "4000") OK DO
	Melder_informationReal (Spectrum_getBandDensityDifference (ONLY_OBJECT,
		GET_REAL ("Low band floor"), GET_REAL ("Low band ceiling"), GET_REAL ("High band floor"), GET_REAL ("High band ceiling")), "dB"); END
FORM (Spectrum_getBandEnergy, "Spectrum: Get band energy", 0)
	REAL ("Band floor (Hz)", "200.0") REAL ("Band ceiling (Hz)", "1000") OK DO
	Melder_informationReal (Spectrum_getBandEnergy (ONLY_OBJECT, GET_REAL ("Band floor"), GET_REAL ("Band ceiling")), "Pa2 sec"); END
FORM (Spectrum_getBandEnergyDifference, "Spectrum: Get band energy difference", 0)
	REAL ("Low band floor (Hz)", "0") REAL ("Low band ceiling (Hz)", "500")
	REAL ("High band floor (Hz)", "500") REAL ("High band ceiling (Hz)", "4000") OK DO
	Melder_informationReal (Spectrum_getBandEnergyDifference (ONLY_OBJECT,
		GET_REAL ("Low band floor"), GET_REAL ("Low band ceiling"), GET_REAL ("High band floor"), GET_REAL ("High band ceiling")), "dB"); END	
FORM (Spectrum_getBinFromFrequency, "Spectrum: Get bin from frequency", 0)
	REAL ("Frequency (Hz)", "2000") OK DO
	Melder_informationReal (Sampled_xToIndex (ONLY_OBJECT, GET_REAL ("Frequency")), NULL); END
DIRECT (Spectrum_getBinWidth) Spectrum me = ONLY_OBJECT; Melder_informationReal (my dx, "Hertz"); END
FORM (Spectrum_getCentralMoment, "Spectrum: Get central moment", "Spectrum: Get central moment...")
	POSITIVE ("Moment", "3.0")
	POSITIVE ("Power", "2.0") OK DO
	Melder_informationReal (Spectrum_getCentralMoment (ONLY_OBJECT,
	GET_REAL ("Moment"), GET_REAL ("Power")), "Hertz to the power 'moment'"); END
FORM (Spectrum_getCentreOfGravity, "Spectrum: Get centre of gravity", "Spectrum: Get centre of gravity...")
	POSITIVE ("Power", "2.0") OK DO
	Melder_informationReal (Spectrum_getCentreOfGravity (ONLY_OBJECT, GET_REAL ("Power")), "Hertz"); END
FORM (Spectrum_getFrequencyFromBin, "Spectrum: Get frequency from bin", 0)
	NATURAL ("Band number", "1") OK DO
	Melder_informationReal (Sampled_indexToX (ONLY_OBJECT, GET_INTEGER ("Band number")), "Hertz"); END
DIRECT (Spectrum_getHighestFrequency) Spectrum me = ONLY_OBJECT; Melder_informationReal (my xmax, "Hertz"); END
FORM (Spectrum_getImaginaryValueInBin, "Spectrum: Get imaginary value in bin", 0)
	NATURAL ("Bin number", "100") OK DO Spectrum me = ONLY_OBJECT;
	long binNumber = GET_INTEGER ("Bin number");
	REQUIRE (binNumber <= my nx, "Bin number must not exceed number of bins.");
	Melder_informationReal (my z [2] [binNumber], NULL); END
FORM (Spectrum_getKurtosis, "Spectrum: Get kurtosis", "Spectrum: Get kurtosis...")
	POSITIVE ("Power", "2.0") OK DO
	Melder_informationReal (Spectrum_getKurtosis (ONLY_OBJECT, GET_REAL ("Power")), NULL); END
DIRECT (Spectrum_getLowestFrequency) Spectrum me = ONLY_OBJECT; Melder_informationReal (my xmin, "Hertz"); END
DIRECT (Spectrum_getNumberOfBins) Spectrum me = ONLY_OBJECT; Melder_information ("%ld bins", my nx); END
FORM (Spectrum_getRealValueInBin, "Spectrum: Get real value in bin", 0)
	NATURAL ("Bin number", "100") OK DO Spectrum me = ONLY_OBJECT;
	long binNumber = GET_INTEGER ("Bin number");
	REQUIRE (binNumber <= my nx, "Bin number must not exceed number of bins.");
	Melder_informationReal (my z [1] [binNumber], NULL); END
FORM (Spectrum_getSkewness, "Spectrum: Get skewness", "Spectrum: Get skewness...")
	POSITIVE ("Power", "2.0") OK DO
	Melder_informationReal (Spectrum_getSkewness (ONLY_OBJECT, GET_REAL ("Power")), NULL); END
FORM (Spectrum_getStandardDeviation, "Spectrum: Get standard deviation", "Spectrum: Get standard deviation...")
	POSITIVE ("Power", "2.0") OK DO
	Melder_informationReal (Spectrum_getStandardDeviation (ONLY_OBJECT, GET_REAL ("Power")), "Hertz"); END

DIRECT (Spectrum_help) Melder_help ("Spectrum"); END

FORM (Spectrum_lpcSmoothing, "Spectrum: LPC smoothing", 0)
	NATURAL ("Number of peaks", "5")
	POSITIVE ("Pre-emphasis from (Hz)", "50.0")
	OK
DO
	EVERY_TO (Spectrum_lpcSmoothing (OBJECT, GET_INTEGER ("Number of peaks"), GET_REAL ("Pre-emphasis from")))
END

FORM (Spectrum_passHannBand, "Spectrum: Filter (pass Hann band)", "Spectrum: Filter (pass Hann band)...")
	REAL ("From frequency (Hz)", "500")
	REAL ("To frequency (Hz)", "1000")
	POSITIVE ("Smoothing (Hz)", "100")
	OK
DO
	EVERY (Spectrum_passHannBand (OBJECT, GET_REAL ("From frequency"), GET_REAL ("To frequency"), GET_REAL ("Smoothing")))
END

FORM (Spectrum_stopHannBand, "Spectrum: Filter (stop Hann band)", "Spectrum: Filter (stop Hann band)...")
	REAL ("From frequency (Hz)", "500")
	REAL ("To frequency (Hz)", "1000")
	POSITIVE ("Smoothing (Hz)", "100")
	OK
DO
	EVERY (Spectrum_stopHannBand (OBJECT, GET_REAL ("From frequency"), GET_REAL ("To frequency"), GET_REAL ("Smoothing")))
END

FORM (Spectrum_to_Excitation, "Spectrum: To Excitation", 0)
	POSITIVE ("Frequency resolution (Bark)", "0.1")
	OK
DO
	EVERY_TO (Spectrum_to_Excitation (OBJECT, GET_REAL ("Frequency resolution")))
END

FORM (Spectrum_to_Formant_peaks, "Spectrum: To Formant (peaks)", 0)
	LABEL ("", "Warning: this simply picks peaks from 0 Hz up!")
	NATURAL ("Maximum number of formants", "1000")
	OK
DO
	EVERY_TO (Spectrum_to_Formant (OBJECT, GET_INTEGER ("Maximum number of formants")))
END

FORM (Spectrum_to_Ltas, "Spectrum: To Long-term average spectrum", 0)
	POSITIVE ("Bandwidth (Hz)", "1000")
	OK
DO
	EVERY_TO (Spectrum_to_Ltas (OBJECT, GET_REAL ("Bandwidth")))
END

DIRECT (Spectrum_to_Ltas_1to1)
	EVERY_TO (Spectrum_to_Ltas_1to1 (OBJECT))
END

DIRECT (Spectrum_to_Matrix)
	EVERY_TO (Spectrum_to_Matrix (OBJECT))
END

DIRECT (Spectrum_to_Sound)
	EVERY_TO (Spectrum_to_Sound (OBJECT))
END

DIRECT (Spectrum_to_Spectrogram)
	EVERY_TO (Spectrum_to_Spectrogram (OBJECT))
END

/***** STRINGS *****/

FORM (Strings_createAsFileList, "Create Strings as file list", "Create Strings as file list...")
	SENTENCE ("Name", "fileList")
	LABEL ("", "Path:")
	TEXTFIELD ("path", "/people/Miep/*.aifc")
	OK
static int inited;
if (! inited) {
	structMelderDir defaultDir;
	char *workingDirectory, path [300];
	Melder_getDefaultDir (& defaultDir);
	workingDirectory = Melder_dirToPath (& defaultDir);
	#if defined (UNIX)
		sprintf (path, "%s/*.aifc", workingDirectory);
	#elif defined (_WIN32)
	{
		int len = strlen (workingDirectory);
		sprintf (path, "%s%s*.wav", workingDirectory, len == 0 || workingDirectory [len - 1] != '\\' ? "\\" : "");
	}
	#else
		sprintf (path, "%s*.aifc", workingDirectory);
	#endif
	SET_STRING ("path", path);
	inited = TRUE;
}
DO
	if (! praat_new (Strings_createAsFileList (GET_STRING ("path")), GET_STRING ("Name"))) return 0;
END

FORM (Strings_createAsDirectoryList, "Create Strings as directory list", "Create Strings as file list...")
	SENTENCE ("Name", "directoryList")
	LABEL ("", "Path:")
	TEXTFIELD ("path", "/people/Miep/*")
	OK
static int inited;
if (! inited) {
	structMelderDir defaultDir;
	char *workingDirectory, path [300];
	Melder_getDefaultDir (& defaultDir);
	workingDirectory = Melder_dirToPath (& defaultDir);
	#if defined (UNIX)
		sprintf (path, "%s/*", workingDirectory);
	#elif defined (_WIN32)
	{
		int len = strlen (workingDirectory);
		sprintf (path, "%s%s*", workingDirectory, len == 0 || workingDirectory [len - 1] != '\\' ? "\\" : "");
	}
	#else
		sprintf (path, "%s*", workingDirectory);
	#endif
	SET_STRING ("path", path);
	inited = TRUE;
}
DO
	if (! praat_new (Strings_createAsDirectoryList (GET_STRING ("path")), GET_STRING ("Name"))) return 0;
END

DIRECT (Strings_equal)
	Strings s1 = NULL, s2 = NULL;
	WHERE (SELECTED) { if (s1) s2 = OBJECT; else s1 = OBJECT; }
	Melder_information ("%d", Data_equal (s1, s2));
END

DIRECT (Strings_genericize)
	WHERE (SELECTED) {
		int status = Strings_genericize (OBJECT);
		praat_dataChanged (OBJECT);
		if (! status) return 0;
	}
END

DIRECT (Strings_getNumberOfStrings)
	Strings me = ONLY_OBJECT;
	Melder_information ("%ld", my numberOfStrings);
END

FORM (Strings_getString, "Get string", 0)
	NATURAL ("Index", "1")
	OK
DO
	Strings me = ONLY_OBJECT;
	long index = GET_INTEGER ("Index");
	Melder_information ("%s", index > my numberOfStrings ? "" : my strings [index]);
END

DIRECT (Strings_help) Melder_help ("Strings"); END

DIRECT (Strings_randomize)
	WHERE (SELECTED) {
		Strings_randomize (OBJECT);
		praat_dataChanged (OBJECT);
	}
END

FORM_READ (Strings_readFromRawTextFile, "Read Strings from raw text file", 0)
	if (! praat_new (Strings_readFromRawTextFile (file), MelderFile_name (file))) return 0;
END

DIRECT (Strings_sort)
	WHERE (SELECTED) {
		Strings_sort (OBJECT);
		praat_dataChanged (OBJECT);
	}
END

DIRECT (Strings_to_Distributions)
	EVERY_TO (Strings_to_Distributions (OBJECT))
END

DIRECT (Strings_to_WordList)
	EVERY_TO (Strings_to_WordList (OBJECT))
END

FORM_WRITE (Strings_writeToRawTextFile, "Write Strings to text file", 0, "txt")
	if (! Strings_writeToRawTextFile (ONLY_OBJECT, file)) return 0;
END

/***** TABLE, rest in praat_Stat.c *****/

FORM (Table_createWithColumnNames, "Create Table with column names", 0)
	WORD ("Name", "table")
	INTEGER ("Number of rows", "10")
	LABEL ("", "Column names:")
	TEXTFIELD ("columnNames", "speaker dialect age vowel F0 F1 F2")
	OK
DO
	if (! praat_new (Table_createWithColumnNames
		(GET_INTEGER ("Number of rows"), GET_STRING ("columnNames")),
		GET_STRING ("Name"))) return 0;
END

FORM (Table_createWithoutColumnNames, "Create Table without column names", 0)
	WORD ("Name", "table")
	INTEGER ("Number of rows", "10")
	NATURAL ("Number of columns", "3")
	OK
DO
	if (! praat_new (Table_createWithoutColumnNames
		(GET_INTEGER ("Number of rows"), GET_INTEGER ("Number of columns")),
		GET_STRING ("Name"))) return 0;
END

FORM_READ (Table_readFromTableFile, "Read Table from table file", 0)
	if (! praat_new (Table_readFromTableFile (file), MelderFile_name (file))) return 0;
END

FORM_READ (Table_readFromCommaSeparatedFile, "Read Table from comma-separated file", 0)
	if (! praat_new (Table_readFromCharacterSeparatedTextFile (file, ','), MelderFile_name (file))) return 0;
END

FORM_READ (Table_readFromTabSeparatedFile, "Read Table from tab-separated file", 0)
	if (! praat_new (Table_readFromCharacterSeparatedTextFile (file, '\t'), MelderFile_name (file))) return 0;
END

/***** TABLEOFREAL *****/

DIRECT (TablesOfReal_append)
	Collection me = Collection_create (classTableOfReal, 10);
	if (! me) return 0;
	WHERE (SELECTED)
		if (! Collection_addItem (me, OBJECT)) { my size = 0; forget (me); return 0; }
	if (! praat_new (TablesOfReal_appendMany (me), "appended")) {
		my size = 0; forget (me); return 0;
	}
	my size = 0; forget (me);
END

FORM (TableOfReal_create, "Create TableOfReal", 0)
	WORD ("Name", "table")
	NATURAL ("Number of rows", "10")
	NATURAL ("Number of columns", "3")
	OK
DO
	if (! praat_new (TableOfReal_create (GET_INTEGER ("Number of rows"), GET_INTEGER ("Number of columns")),
		GET_STRING ("Name"))) return 0;
END

FORM (TableOfReal_drawAsNumbers, "Draw as numbers", 0)
	NATURAL ("From row", "1")
	INTEGER ("To row", "0 (= all)")
	RADIO ("Format", 3)
	RADIOBUTTON ("decimal")
	RADIOBUTTON ("exponential")
	RADIOBUTTON ("free")
	RADIOBUTTON ("rational")
	NATURAL ("Precision", "5")
	OK
DO
	EVERY_DRAW (TableOfReal_drawAsNumbers (OBJECT, GRAPHICS,
		GET_INTEGER ("From row"), GET_INTEGER ("To row"),
		GET_INTEGER ("Format"), GET_INTEGER ("Precision")))
END

FORM (TableOfReal_drawAsNumbers_if, "Draw as numbers if...", 0)
	NATURAL ("From row", "1")
	INTEGER ("To row", "0 (= all)")
	RADIO ("Format", 3)
	RADIOBUTTON ("decimal")
	RADIOBUTTON ("exponential")
	RADIOBUTTON ("free")
	RADIOBUTTON ("rational")
	NATURAL ("Precision", "5")
	LABEL ("", "Condition:")
	TEXTFIELD ("condition", "self <> 0")
	OK
DO
	EVERY_DRAW (TableOfReal_drawAsNumbers_if (OBJECT, GRAPHICS,
		GET_INTEGER ("From row"), GET_INTEGER ("To row"),
		GET_INTEGER ("Format"), GET_INTEGER ("Precision"), GET_STRING ("condition")))
END

FORM (TableOfReal_drawAsSquares, "Draw table as squares", 0)
	INTEGER ("From row", "1")
	INTEGER ("To row", "0")
	INTEGER ("From column", "1")
	INTEGER ("To column", "0")
	BOOLEAN ("Garnish", 1)
	OK
DO
	EVERY_DRAW (TableOfReal_drawAsSquares (OBJECT, GRAPHICS, 
		GET_INTEGER ("From row"), GET_INTEGER ("To row"),
		GET_INTEGER ("From column"), GET_INTEGER ("To column"),
		GET_INTEGER ("Garnish")))
END

FORM (TableOfReal_drawHorizontalLines, "Draw horizontal lines", 0)
	NATURAL ("From row", "1") INTEGER ("To row", "0 (= all)") OK DO
	EVERY_DRAW (TableOfReal_drawHorizontalLines (OBJECT, GRAPHICS, GET_INTEGER ("From row"), GET_INTEGER ("To row"))) END
FORM (TableOfReal_drawLeftAndRightLines, "Draw left and right lines", 0)
	NATURAL ("From row", "1") INTEGER ("To row", "0 (= all)") OK DO
	EVERY_DRAW (TableOfReal_drawLeftAndRightLines (OBJECT, GRAPHICS, GET_INTEGER ("From row"), GET_INTEGER ("To row"))) END
FORM (TableOfReal_drawTopAndBottomLines, "Draw top and bottom lines", 0)
	NATURAL ("From row", "1") INTEGER ("To row", "0 (= all)") OK DO
	EVERY_DRAW (TableOfReal_drawTopAndBottomLines (OBJECT, GRAPHICS, GET_INTEGER ("From row"), GET_INTEGER ("To row"))) END
FORM (TableOfReal_drawVerticalLines, "Draw vertical lines", 0)
	NATURAL ("From row", "1") INTEGER ("To row", "0 (= all)") OK DO
	EVERY_DRAW (TableOfReal_drawVerticalLines (OBJECT, GRAPHICS, GET_INTEGER ("From row"), GET_INTEGER ("To row"))) END

DIRECT (TableOfReal_extractColumnLabelsAsStrings)
	EVERY_TO (TableOfReal_extractColumnLabelsAsStrings (OBJECT))
END

FORM (TableOfReal_extractColumnRanges, "Extract column ranges", 0)
	LABEL ("", "Create a new TableOfReal from the following columns:")
	TEXTFIELD ("ranges", "1 2")
	LABEL ("", "To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
	OK
DO
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractColumnRanges (OBJECT, GET_STRING ("ranges")), "%s_cols", NAME)) return 0;
	}
END

FORM (TableOfReal_extractColumnsWhere, "Extract columns where", 0)
	LABEL ("", "Extract all columns with at least one cell where:")
	TEXTFIELD ("condition", "col mod 3 = 0 ; this example extracts every third column")
	OK
DO
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractColumnsWhere (OBJECT, GET_STRING ("condition")), "%s_cols", NAME)) return 0;
	}
END

FORM (TableOfReal_extractColumnsWhereLabel, "Extract column where label", 0)
	OPTIONMENU ("Extract all columns whose label...", 1)
	OPTIONS_ENUM (Melder_STRING_text_finiteVerb (itext), Melder_STRING_min, Melder_STRING_max)
	SENTENCE ("...the text", "a")
	OK
DO
	const char *text = GET_STRING ("...the text");
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractColumnsWhereLabel (OBJECT,
			GET_INTEGER ("Extract all columns whose label...") - 1 + Melder_STRING_min, text),
			"%s_%s", NAME, text)) return 0;
	}
END

FORM (TableOfReal_extractColumnsWhereRow, "Extract columns where row", 0)
	NATURAL ("Extract all columns where row...", "1")
	OPTIONMENU ("...is...", 1)
	OPTIONS_ENUM (Melder_NUMBER_text_adjective (itext), Melder_NUMBER_min, Melder_NUMBER_max)
	REAL ("...the value", "0.0")
	OK
DO
	long row = GET_INTEGER ("Extract all columns where row...");
	double value = GET_REAL ("...the value");
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractColumnsWhereRow (OBJECT,
			row, GET_INTEGER ("...is...") - 1 + Melder_NUMBER_min, value),
			"%s_%ld_%ld", NAME, row, (long) floor (value+0.5))) return 0;
	}
END

DIRECT (TableOfReal_extractRowLabelsAsStrings)
	EVERY_TO (TableOfReal_extractRowLabelsAsStrings (OBJECT))
END

FORM (TableOfReal_extractRowRanges, "Extract row ranges", 0)
	LABEL ("", "Create a new TableOfReal from the following rows:")
	TEXTFIELD ("ranges", "1 2")
	LABEL ("", "To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
	OK
DO
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractRowRanges (OBJECT, GET_STRING ("ranges")), "%s_rows", NAME)) return 0;
	}
END

FORM (TableOfReal_extractRowsWhere, "Extract rows where", 0)
	LABEL ("", "Extract all rows with at least one cell where:")
	TEXTFIELD ("condition", "row mod 3 = 0 ; this example extracts every third row")
	OK
DO
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractRowsWhere (OBJECT, GET_STRING ("condition")), "%s_rows", NAME)) return 0;
	}
END

FORM (TableOfReal_extractRowsWhereColumn, "Extract rows where column", 0)
	NATURAL ("Extract all rows where column...", "1")
	OPTIONMENU ("...is...", 1)
	OPTIONS_ENUM (Melder_NUMBER_text_adjective (itext), Melder_NUMBER_min, Melder_NUMBER_max)
	REAL ("...the value", "0.0")
	OK
DO
	long column = GET_INTEGER ("Extract all rows where column...");
	double value = GET_REAL ("...the value");
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractRowsWhereColumn (OBJECT,
			column, GET_INTEGER ("...is...") - 1 + Melder_NUMBER_min, value),
			"%s_%ld_%ld", NAME, column, (long) floor (value+0.5))) return 0;
	}
END

FORM (TableOfReal_extractRowsWhereLabel, "Extract rows where label", 0)
	OPTIONMENU ("Extract all rows whose label...", 1)
	OPTIONS_ENUM (Melder_STRING_text_finiteVerb (itext), Melder_STRING_min, Melder_STRING_max)
	SENTENCE ("...the text", "a")
	OK
DO
	const char *text = GET_STRING ("...the text");
	WHERE (SELECTED) {
		if (! praat_new (TableOfReal_extractRowsWhereLabel (OBJECT,
			GET_INTEGER ("Extract all rows whose label...") - 1 + Melder_STRING_min, text),
			"%s_%s", NAME, text)) return 0;
	}
END

FORM (TableOfReal_formula, "TableOfReal: Formula", "Formula...")
	LABEL ("", "for row from 1 to nrow do for col from 1 to ncol do self [row, col] = ...")
	TEXTFIELD ("formula", "if col = 5 then self + self [6] else self fi")
	OK
DO
	WHERE (SELECTED) {
		if (! TableOfReal_formula (OBJECT, GET_STRING ("formula"), NULL)) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_getColumnIndex, "Get column index", 0)
	SENTENCE ("Column label", "")
	OK
DO
	Melder_information ("%ld", TableOfReal_columnLabelToIndex (ONLY_OBJECT, GET_STRING ("Column label")));
END
	
FORM (TableOfReal_getColumnLabel, "Get column label", 0)
	NATURAL ("Column number", "1")
	OK
DO
	TableOfReal table = ONLY_OBJECT;
	long columnNumber = GET_INTEGER ("Column number");
	REQUIRE (columnNumber <= table -> numberOfColumns, "Column number must not be greater than number of columns.")
	Melder_information ("%s", ! table -> columnLabels || ! table -> columnLabels [columnNumber] ? "" :
		table -> columnLabels [columnNumber]);
END
	
FORM (TableOfReal_getColumnMean_index, "Get column mean", 0)
	NATURAL ("Column number", "1")
	OK
DO
	TableOfReal table = ONLY_OBJECT;
	long columnNumber = GET_INTEGER ("Column number");
	REQUIRE (columnNumber <= table -> numberOfColumns, "Column number must not be greater than number of columns.")
	Melder_informationReal (TableOfReal_getColumnMean (table, columnNumber), NULL);
END
	
FORM (TableOfReal_getColumnMean_label, "Get column mean", 0)
	SENTENCE ("Column label", "")
	OK
DO
	TableOfReal table = ONLY_OBJECT;
	long columnNumber = TableOfReal_columnLabelToIndex (table, GET_STRING ("Column label"));
	REQUIRE (columnNumber > 0, "Column label does not exist.")
	Melder_informationReal (TableOfReal_getColumnMean (table, columnNumber), NULL);
END
	
FORM (TableOfReal_getColumnStdev_index, "Get column standard deviation", 0)
	NATURAL ("Column number", "1")
	OK
DO
	Melder_informationReal (TableOfReal_getColumnStdev (ONLY_OBJECT, GET_INTEGER ("Column number")), NULL);
END
	
FORM (TableOfReal_getColumnStdev_label, "Get column standard deviation", 0)
	SENTENCE ("Column label", "1")
	OK
DO
	TableOfReal table = ONLY_OBJECT;
	long columnNumber = TableOfReal_columnLabelToIndex (table, GET_STRING ("Column label"));
	REQUIRE (columnNumber > 0, "Column label does not exist.")
	Melder_informationReal (TableOfReal_getColumnStdev (table, columnNumber), NULL);
END

DIRECT (TableOfReal_getNumberOfColumns) TableOfReal me = ONLY_OBJECT; Melder_information ("%ld", my numberOfColumns); END
DIRECT (TableOfReal_getNumberOfRows) TableOfReal me = ONLY_OBJECT; Melder_information ("%ld", my numberOfRows); END

FORM (TableOfReal_getRowIndex, "Get row index", 0)
	SENTENCE ("Row label", "")
	OK
DO
	Melder_information ("%ld", TableOfReal_rowLabelToIndex (ONLY_OBJECT, GET_STRING ("Row label")));
END
	
FORM (TableOfReal_getRowLabel, "Get row label", 0)
	NATURAL ("Row number", "1")
	OK
DO
	TableOfReal table = ONLY_OBJECT;
	long rowNumber = GET_INTEGER ("Row number");
	REQUIRE (rowNumber <= table -> numberOfRows, "Row number must not be greater than number of rows.")
	Melder_information ("%s", ! table -> rowLabels || ! table -> rowLabels [rowNumber] ? "" :
		table -> rowLabels [rowNumber]);
END

FORM (TableOfReal_getValue, "Get value", 0)
	NATURAL ("Row number", "1") NATURAL ("Column number", "1") OK DO TableOfReal me = ONLY_OBJECT;
	long row = GET_INTEGER ("Row number"), column = GET_INTEGER ("Column number");
	REQUIRE (row <= my numberOfRows, "Row number must not exceed number of rows.")
	REQUIRE (column <= my numberOfColumns, "Column number must not exceed number of columns.")
	Melder_informationReal (my data [row] [column], NULL); END

DIRECT (TableOfReal_help) Melder_help ("TableOfReal"); END

FORM (TableOfReal_insertColumn, "Insert column", 0)
	NATURAL ("Column number", "1")
	OK
DO
	WHERE (SELECTED) {
		if (! TableOfReal_insertColumn (OBJECT, GET_INTEGER ("Column number"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_insertRow, "Insert row", 0)
	NATURAL ("Row number", "1")
	OK
DO
	WHERE (SELECTED) {
		if (! TableOfReal_insertRow (OBJECT, GET_INTEGER ("Row number"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM_READ (TableOfReal_readFromHeaderlessSpreadsheetFile, "Read TableOfReal from headerless spreadsheet file", 0)
	if (! praat_new (TableOfReal_readFromHeaderlessSpreadsheetFile (file), MelderFile_name (file))) return 0;
END

FORM (TableOfReal_removeColumn, "Remove column", 0)
	NATURAL ("Column number", "1")
	OK
DO
	WHERE (SELECTED) {
		if (! TableOfReal_removeColumn (OBJECT, GET_INTEGER ("Column number"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_removeRow, "Remove row", 0)
	NATURAL ("Row number", "1")
	OK
DO
	WHERE (SELECTED) {
		if (! TableOfReal_removeRow (OBJECT, GET_INTEGER ("Row number"))) return 0;
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_setColumnLabel_index, "Set column label", 0)
	NATURAL ("Column number", "1")
	SENTENCE ("Label", "")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal_setColumnLabel (OBJECT, GET_INTEGER ("Column number"), GET_STRING ("Label"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_setColumnLabel_label, "Set column label", 0)
	SENTENCE ("Old label", "")
	SENTENCE ("New label", "")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal_setColumnLabel (OBJECT, TableOfReal_columnLabelToIndex (OBJECT, GET_STRING ("Old label")),
			GET_STRING ("New label"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_setRowLabel_index, "Set row label", 0)
	NATURAL ("Row number", "1")
	SENTENCE ("Label", "")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal_setRowLabel (OBJECT, GET_INTEGER ("Row number"), GET_STRING ("Label"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_setValue, "Set value", "TableOfReal: Set value...")
	NATURAL ("Row number", "1")
	NATURAL ("Column number", "1")
	REAL ("New value", "0.0")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal me = OBJECT;
		long irow = GET_INTEGER ("Row number"), icol = GET_INTEGER ("Column number");
		REQUIRE (irow <= my numberOfRows, "Row number too large.")
		REQUIRE (icol <= my numberOfColumns, "Column number too large.")
		my data [irow] [icol] = GET_REAL ("New value");
		praat_dataChanged (me);
	}
END

FORM (TableOfReal_setRowLabel_label, "Set row label", 0)
	SENTENCE ("Old label", "")
	SENTENCE ("New label", "")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal_setRowLabel (OBJECT, TableOfReal_rowLabelToIndex (OBJECT, GET_STRING ("Old label")),
			GET_STRING ("New label"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_sortByColumn, "Sort rows by column", 0)
	INTEGER ("Column", "1")
	INTEGER ("Secondary column", "0")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal_sortByColumn (OBJECT, GET_INTEGER ("Column"), GET_INTEGER ("Secondary column"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TableOfReal_sortByLabel, "Sort rows by label", 0)
	LABEL ("", "Secondary sorting keys:")
	INTEGER ("Column1", "1")
	INTEGER ("Column2", "0")
	OK
DO
	WHERE (SELECTED) {
		TableOfReal_sortByLabel (OBJECT, GET_INTEGER ("Column1"), GET_INTEGER ("Column2"));
		praat_dataChanged (OBJECT);
	}
END

DIRECT (TableOfReal_to_Matrix)
	EVERY_TO (TableOfReal_to_Matrix (OBJECT))
END

FORM_WRITE (TableOfReal_writeToHeaderlessSpreadsheetFile, "Write TableOfReal to spreadsheet", 0, "txt")
	if (! TableOfReal_writeToHeaderlessSpreadsheetFile (ONLY_OBJECT, file)) return 0;
END

/***** TEXTGRID, rest in praat_TextGrid_init.c *****/

FORM (TextGrid_create, "Create TextGrid", "Create TextGrid...")
	LABEL ("", "Hint: to label or segment an existing Sound,")
	LABEL ("", "select that Sound and choose \"To TextGrid...\".")
	REAL ("Start time (s)", "0.0")
	REAL ("End time (s)", "1.0")
	SENTENCE ("All tier names", "Mary John bell")
	SENTENCE ("Which of these are point tiers?", "bell")
	OK
DO
	double tmin = GET_REAL ("Start time"), tmax = GET_REAL ("End time");
	REQUIRE (tmax > tmin, "End time should be greater than start time")
	if (! praat_new (TextGrid_create (tmin, tmax, GET_STRING ("All tier names"), GET_STRING ("Which of these are point tiers?")),
		GET_STRING ("All tier names"))) return 0;
END

/***** TEXTTIER, rest in praat_TextGrid_init.c *****/

FORM_READ (TextTier_readFromXwaves, "Read TextTier from Xwaves", 0)
	if (! praat_new (TextTier_readFromXwaves (file), MelderFile_name (file))) return 0;
END

/***** TIMEFRAMESAMPLED *****/

DIRECT (TimeFrameSampled_getNumberOfFrames)
	Sampled me = ONLY_OBJECT;
	Melder_information ("%ld frames", my nx);
END

FORM (TimeFrameSampled_getFrameFromTime, "Get frame number from time", "Get frame number from time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	Melder_informationReal (Sampled_xToIndex (ONLY_OBJECT, GET_REAL ("Time")), NULL);
END

DIRECT (TimeFrameSampled_getFrameLength)
	Sampled me = ONLY_OBJECT;
	Melder_informationReal (my dx, "seconds");
END

FORM (TimeFrameSampled_getTimeFromFrame, "Get time from frame number", "Get time from frame number...")
	NATURAL ("Frame number", "1")
	OK
DO
	Melder_informationReal (Sampled_indexToX (ONLY_OBJECT, GET_INTEGER ("Frame number")), "seconds");
END

/***** TIMEFUNCTION *****/

DIRECT (TimeFunction_getDuration)
	Function me = ONLY_OBJECT;
	Melder_informationReal (my xmax - my xmin, "seconds");
END

DIRECT (TimeFunction_getEndTime)
	Function me = ONLY_OBJECT;
	Melder_informationReal (my xmax, "seconds");
END

DIRECT (TimeFunction_getStartTime)
	Function me = ONLY_OBJECT;
	Melder_informationReal (my xmin, "seconds");
END

/***** TIMETIER *****/

FORM (TimeTier_getHighIndexFromTime, "Get high index", "AnyTier: Get high index from time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	AnyTier me = ONLY_OBJECT;
	Melder_information (my points -> size ? "%ld" : "--undefined--", AnyTier_timeToHighIndex (me, GET_REAL ("Time")));
END

FORM (TimeTier_getLowIndexFromTime, "Get low index", "AnyTier: Get low index from time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	AnyTier me = ONLY_OBJECT;
	Melder_information (my points -> size ? "%ld" : "--undefined--", AnyTier_timeToLowIndex (me, GET_REAL ("Time")));
END

FORM (TimeTier_getNearestIndexFromTime, "Get nearest index", "AnyTier: Get nearest index from time...")
	REAL ("Time (s)", "0.5")
	OK
DO
	AnyTier me = ONLY_OBJECT;
	Melder_information (my points -> size ? "%ld" : "--undefined--", AnyTier_timeToNearestIndex (me, GET_REAL ("Time")));
END

DIRECT (TimeTier_getNumberOfPoints)
	AnyTier me = ONLY_OBJECT;
	Melder_information ("%ld points", my points -> size);
END

FORM (TimeTier_getTimeFromIndex, "Get time", 0 /*"AnyTier: Get time from index..."*/)
	NATURAL ("Point number", "10")
	OK
DO
	AnyTier me = ONLY_OBJECT;
	long i = GET_INTEGER ("Point number");
	if (i > my points -> size) Melder_information ("--undefined--");
	else Melder_informationReal (((AnyPoint) my points -> item [i]) -> time, "seconds");
END

FORM (TimeTier_removePoint, "Remove one point", "AnyTier: Remove point...")
	NATURAL ("Point number", "1")
	OK
DO
	WHERE (SELECTED) {
		AnyTier_removePoint (OBJECT, GET_INTEGER ("Point number"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TimeTier_removePointNear, "Remove one point", "AnyTier: Remove point near...")
	REAL ("Time (s)", "0.5")
	OK
DO
	WHERE (SELECTED) {
		AnyTier_removePointNear (OBJECT, GET_REAL ("Time"));
		praat_dataChanged (OBJECT);
	}
END

FORM (TimeTier_removePointsBetween, "Remove points", "AnyTier: Remove points between...")
	REAL ("left Time range (s)", "0.0")
	REAL ("right Time range (s)", "1.0")
	OK
DO
	WHERE (SELECTED) {
		AnyTier_removePointsBetween (OBJECT, GET_REAL ("left Time range"), GET_REAL ("right Time range"));
		praat_dataChanged (OBJECT);
	}
END

/***** TRANSITION *****/

DIRECT (Transition_conflate)
	EVERY_TO (Transition_to_Distributions_conflate (OBJECT))
END

FORM (Transition_drawAsNumbers, "Draw as numbers", 0)
	RADIO ("Format", 1)
	RADIOBUTTON ("decimal")
	RADIOBUTTON ("exponential")
	RADIOBUTTON ("free")
	RADIOBUTTON ("rational")
	NATURAL ("Precision", "2")
	OK
DO
	EVERY_DRAW (Transition_drawAsNumbers (OBJECT, GRAPHICS,
		GET_INTEGER ("Format"), GET_INTEGER ("Precision")))
END

DIRECT (Transition_eigen)
	WHERE (SELECTED) {
		Matrix vec, val;
		if (! Transition_eigen (OBJECT, & vec, & val)) return 0;
		if (! praat_new (vec, "eigenvectors")) return 0;
		if (! praat_new (val, "eigenvalues")) return 0;
	}
END

DIRECT (Transition_help) Melder_help ("Transition"); END

FORM (Transition_power, "Transition: Power...", 0)
	NATURAL ("Power", "2")
	OK
DO
	EVERY_TO (Transition_power (OBJECT, GET_INTEGER ("Power")))
END

DIRECT (Transition_to_Matrix)
	EVERY_TO (Transition_to_Matrix (OBJECT))
END

/***** Praat menu *****/

FORM (Praat_test, "Praat test", 0)
	ENUM ("Test", PraatTests, 1)
	SENTENCE ("arg1", "1000000")
	SENTENCE ("arg2", "")
	SENTENCE ("arg3", "")
	SENTENCE ("arg4", "")
	OK
DO
	Praat_tests (GET_INTEGER ("Test"), GET_STRING ("arg1"),
		GET_STRING ("arg2"), GET_STRING ("arg3"), GET_STRING ("arg4"));
END

/***** Help menu *****/

DIRECT (ObjectWindow) Melder_help ("Object window"); END
DIRECT (Intro) Melder_help ("Intro"); END
DIRECT (WhatsNew) Melder_help ("What's new?"); END
DIRECT (TypesOfObjects) Melder_help ("Types of objects"); END
DIRECT (Editors) Melder_help ("Editors"); END
DIRECT (FrequentlyAskedQuestions) Melder_help ("FAQ (Frequently Asked Questions)"); END
DIRECT (Acknowledgments) Melder_help ("Acknowledgments"); END
DIRECT (FormulasTutorial) Melder_help ("Formulas"); END
DIRECT (ScriptingTutorial) Melder_help ("Scripting"); END
DIRECT (StatisticsTutorial) Melder_help ("Statistics"); END
DIRECT (Programming) Melder_help ("Programming with Praat"); END
DIRECT (SearchManual) Melder_search (); END

/***** file recognizers *****/

static Any cgnSyntaxFileRecognizer (int nread, const char *header, MelderFile file) {
	if (nread < 57) return NULL;
	if (! strnequ (& header [0], "<?xml version=\"1.0\"?>", 21) ||
	    (! strnequ (& header [22], "<!DOCTYPE ttext SYSTEM \"ttext.dtd\">", 35) &&
	     ! strnequ (& header [23], "<!DOCTYPE ttext SYSTEM \"ttext.dtd\">", 35))) return NULL;
	return TextGrid_readFromCgnSyntaxFile (file);
}

static Any chronologicalTextGridTextFileRecognizer (int nread, const char *header, MelderFile file) {
	if (nread < 100) return NULL;
	if (! strnequ (& header [0], "\"Praat chronological TextGrid text file\"", 40)) return NULL;
	return TextGrid_readFromChronologicalTextFile (file);
}

/***** buttons *****/

void praat_TableOfReal_init (void *klas);   /* Buttons for TableOfReal and for its subclasses. */
void praat_TableOfReal_init (void *klas) {
	praat_addAction1 (klas, 1, "Write to headerless spreadsheet file...", 0, 0, DO_TableOfReal_writeToHeaderlessSpreadsheetFile);
	praat_addAction1 (klas, 0, "Draw -                 ", 0, 0, 0);
		praat_addAction1 (klas, 0, "Draw as numbers...", 0, 1, DO_TableOfReal_drawAsNumbers);
		praat_addAction1 (klas, 0, "Draw as numbers if...", 0, 1, DO_TableOfReal_drawAsNumbers_if);
		praat_addAction1 (klas, 0, "Draw as squares...", 0, 1, DO_TableOfReal_drawAsSquares);	
		praat_addAction1 (klas, 0, "-- draw lines --", 0, 1, 0);
		praat_addAction1 (klas, 0, "Draw vertical lines...", 0, 1, DO_TableOfReal_drawVerticalLines);
		praat_addAction1 (klas, 0, "Draw horizontal lines...", 0, 1, DO_TableOfReal_drawHorizontalLines);
		praat_addAction1 (klas, 0, "Draw left and right lines...", 0, 1, DO_TableOfReal_drawLeftAndRightLines);
		praat_addAction1 (klas, 0, "Draw top and bottom lines...", 0, 1, DO_TableOfReal_drawTopAndBottomLines);
	praat_addAction1 (klas, 0, "Query -                ", 0, 0, 0);
		praat_addAction1 (klas, 1, "Get number of rows", 0, 1, DO_TableOfReal_getNumberOfRows);
		praat_addAction1 (klas, 1, "Get number of columns", 0, 1, DO_TableOfReal_getNumberOfColumns);
		praat_addAction1 (klas, 1, "Get row label...", 0, 1, DO_TableOfReal_getRowLabel);
		praat_addAction1 (klas, 1, "Get column label...", 0, 1, DO_TableOfReal_getColumnLabel);
		praat_addAction1 (klas, 1, "Get row index...", 0, 1, DO_TableOfReal_getRowIndex);
		praat_addAction1 (klas, 1, "Get column index...", 0, 1, DO_TableOfReal_getColumnIndex);
		praat_addAction1 (klas, 1, "-- get value --", 0, 1, 0);
		praat_addAction1 (klas, 1, "Get value...", 0, 1, DO_TableOfReal_getValue);
		if (klas == classTableOfReal) {
			praat_addAction1 (klas, 1, "-- get statistics --", 0, 1, 0);
			praat_addAction1 (klas, 1, "Get column mean (index)...", 0, 1, DO_TableOfReal_getColumnMean_index);
			praat_addAction1 (klas, 1, "Get column mean (label)...", 0, 1, DO_TableOfReal_getColumnMean_label);
			praat_addAction1 (klas, 1, "Get column stdev (index)...", 0, 1, DO_TableOfReal_getColumnStdev_index);
			praat_addAction1 (klas, 1, "Get column stdev (label)...", 0, 1, DO_TableOfReal_getColumnStdev_label);
		}
	praat_addAction1 (klas, 0, "Modify -               ", 0, 0, 0);
		praat_addAction1 (klas, 0, "Formula...", 0, 1, DO_TableOfReal_formula);
		praat_addAction1 (klas, 0, "Set value...", 0, 1, DO_TableOfReal_setValue);
		praat_addAction1 (klas, 0, "Sort by label...", 0, 1, DO_TableOfReal_sortByLabel);
		praat_addAction1 (klas, 0, "Sort by column...", 0, 1, DO_TableOfReal_sortByColumn);
		praat_addAction1 (klas, 0, "-- structure --", 0, 1, 0);
		praat_addAction1 (klas, 0, "Remove row (index)...", 0, 1, DO_TableOfReal_removeRow);
		praat_addAction1 (klas, 0, "Remove column (index)...", 0, 1, DO_TableOfReal_removeColumn);
		praat_addAction1 (klas, 0, "Insert row (index)...", 0, 1, DO_TableOfReal_insertRow);
		praat_addAction1 (klas, 0, "Insert column (index)...", 0, 1, DO_TableOfReal_insertColumn);
		praat_addAction1 (klas, 0, "-- set --", 0, 1, 0);
		praat_addAction1 (klas, 0, "Set row label (index)...", 0, 1, DO_TableOfReal_setRowLabel_index);
		praat_addAction1 (klas, 0, "Set row label (label)...", 0, 1, DO_TableOfReal_setRowLabel_label);
		praat_addAction1 (klas, 0, "Set column label (index)...", 0, 1, DO_TableOfReal_setColumnLabel_index);
		praat_addAction1 (klas, 0, "Set column label (label)...", 0, 1, DO_TableOfReal_setColumnLabel_label);
	praat_addAction1 (klas, 0, "Synthesize -     ", 0, 0, 0);
		praat_addAction1 (klas, 0, "Append", 0, 1, DO_TablesOfReal_append);
	praat_addAction1 (klas, 0, "Extract part -", 0, 0, 0);
		praat_addAction1 (klas, 0, "Extract row ranges...", 0, 1, DO_TableOfReal_extractRowRanges);
		praat_addAction1 (klas, 0, "Extract rows where column...", 0, 1, DO_TableOfReal_extractRowsWhereColumn);
		praat_addAction1 (klas, 0, "Extract rows where label...", 0, 1, DO_TableOfReal_extractRowsWhereLabel);
		praat_addAction1 (klas, 0, "Extract rows where...", 0, 1, DO_TableOfReal_extractRowsWhere);
		praat_addAction1 (klas, 0, "Extract column ranges...", 0, 1, DO_TableOfReal_extractColumnRanges);
		praat_addAction1 (klas, 0, "Extract columns where row...", 0, 1, DO_TableOfReal_extractColumnsWhereRow);
		praat_addAction1 (klas, 0, "Extract columns where label...", 0, 1, DO_TableOfReal_extractColumnsWhereLabel);
		praat_addAction1 (klas, 0, "Extract columns where...", 0, 1, DO_TableOfReal_extractColumnsWhere);
	praat_addAction1 (klas, 0, "Extract -", 0, 0, 0);
		praat_addAction1 (klas, 0, "Extract row labels as Strings", 0, 1, DO_TableOfReal_extractRowLabelsAsStrings);
		praat_addAction1 (klas, 0, "Extract column labels as Strings", 0, 1, DO_TableOfReal_extractColumnLabelsAsStrings);
	praat_addAction1 (klas, 0, "Convert -     ", 0, 0, 0);
		praat_addAction1 (klas, 0, "To Matrix", 0, 1, DO_TableOfReal_to_Matrix);
}

void praat_TimeFunction_query_init (void *klas);   /* Query buttons for time-based subclasses of Function. */
void praat_TimeFunction_query_init (void *klas) {
	praat_addAction1 (klas, 1, "Time domain", 0, 1, 0);
	praat_addAction1 (klas, 1, "Get start time", 0, 2, DO_TimeFunction_getStartTime);
						praat_addAction1 (klas, 1, "Get starting time", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_getStartTime);
	praat_addAction1 (klas, 1, "Get end time", 0, 2, DO_TimeFunction_getEndTime);
						praat_addAction1 (klas, 1, "Get finishing time", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_getEndTime);
	praat_addAction1 (klas, 1, "Get total duration", 0, 2, DO_TimeFunction_getDuration);
						praat_addAction1 (klas, 1, "Get duration", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_getDuration);
}

void praat_TimeFrameSampled_query_init (void *klas);   /* Query buttons for frame-based time-based subclasses of Sampled. */
void praat_TimeFrameSampled_query_init (void *klas) {
	praat_TimeFunction_query_init (klas);
	praat_addAction1 (klas, 1, "Time sampling", 0, 1, 0);
	praat_addAction1 (klas, 1, "Get number of frames", 0, 2, DO_TimeFrameSampled_getNumberOfFrames);
	praat_addAction1 (klas, 1, "Get time step", 0, 2, DO_TimeFrameSampled_getFrameLength);
						praat_addAction1 (klas, 1, "Get frame length", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getFrameLength);
						praat_addAction1 (klas, 1, "Get frame duration", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getFrameLength);
	praat_addAction1 (klas, 1, "Get time from frame number...", 0, 2, DO_TimeFrameSampled_getTimeFromFrame);
						praat_addAction1 (klas, 1, "Get time from frame...", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getTimeFromFrame);
	praat_addAction1 (klas, 1, "Get frame number from time...", 0, 2, DO_TimeFrameSampled_getFrameFromTime);
						praat_addAction1 (klas, 1, "Get frame from time...", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getFrameFromTime);
}

void praat_TimeTier_query_init (void *klas);   /* Query buttons for time-based subclasses of AnyTier. */
void praat_TimeTier_query_init (void *klas) {
	praat_TimeFunction_query_init (klas);
	praat_addAction1 (klas, 1, "Get number of points", 0, 1, DO_TimeTier_getNumberOfPoints);
	praat_addAction1 (klas, 1, "Get low index from time...", 0, 1, DO_TimeTier_getLowIndexFromTime);
	praat_addAction1 (klas, 1, "Get high index from time...", 0, 1, DO_TimeTier_getHighIndexFromTime);
	praat_addAction1 (klas, 1, "Get nearest index from time...", 0, 1, DO_TimeTier_getNearestIndexFromTime);
	praat_addAction1 (klas, 1, "Get time from index...", 0, 1, DO_TimeTier_getTimeFromIndex);
}

void praat_TimeTier_modify_init (void *klas);   /* Modification buttons for time-based subclasses of AnyTier. */
void praat_TimeTier_modify_init (void *klas) {
	praat_addAction1 (klas, 0, "Remove point...", 0, 1, DO_TimeTier_removePoint);
	praat_addAction1 (klas, 0, "Remove point near...", 0, 1, DO_TimeTier_removePointNear);
	praat_addAction1 (klas, 0, "Remove points between...", 0, 1, DO_TimeTier_removePointsBetween);
}

void praat_uvafon_init (void);
void praat_uvafon_init (void) {
	Thing_recognizeClassesByName (classSound, classMatrix, classPolygon, classPointProcess, classParamCurve,
		classSpectrum, classLtas, classSpectrogram, classFormant,
		classExcitation, classCochleagram, classVocalTract, classFormantPoint, classFormantTier,
		classLabel, classTier, classAutosegment,   /* Three obsolete classes. */
		classIntensity, classPitch, classHarmonicity,
		classStrings,
		classTableOfReal, classDistributions, classTransition, classPairDistribution,
		classRealPoint, classRealTier, classPitchTier, classIntensityTier, classDurationTier, classAmplitudeTier,
		classManipulation, classTextPoint, classTextInterval, classTextTier,
		classIntervalTier, classTextGrid, classLongSound, classWordList, classSpellingChecker,
		NULL);
	Thing_recognizeClassByOtherName (classManipulation, "Psola");
	Thing_recognizeClassByOtherName (classManipulation, "Analysis");
	Thing_recognizeClassByOtherName (classPitchTier, "StylPitch");

	Data_recognizeFileType (cgnSyntaxFileRecognizer);
	Data_recognizeFileType (chronologicalTextGridTextFileRecognizer);

	ManipulationEditor_prefs ();
	SpectrumEditor_prefs ();

	INCLUDE_LIBRARY (praat_uvafon_Sound_init)
	INCLUDE_LIBRARY (praat_uvafon_TextGrid_init)

	praat_addMenuCommand ("Objects", "Praat", "Praat test...", 0, praat_HIDDEN, DO_Praat_test);

	praat_addMenuCommand ("Objects", "New", "-- new numerics --", 0, 0, 0);
	praat_addMenuCommand ("Objects", "New", "Matrix", 0, 0, 0);
		praat_addMenuCommand ("Objects", "New", "Create Matrix...", 0, 1, DO_Matrix_create);
		praat_addMenuCommand ("Objects", "New", "Create simple Matrix...", 0, 1, DO_Matrix_createSimple);
	praat_addMenuCommand ("Objects", "New", "Tables", 0, 0, 0);
		praat_addMenuCommand ("Objects", "New", "Create Table with column names...", 0, 1, DO_Table_createWithColumnNames);
		praat_addMenuCommand ("Objects", "New", "Create Table without column names...", 0, 1, DO_Table_createWithoutColumnNames);
		praat_addMenuCommand ("Objects", "New", "Create Table...", 0, praat_DEPTH_1 + praat_HIDDEN, DO_Table_createWithoutColumnNames);
		praat_addMenuCommand ("Objects", "New", "Create TableOfReal...", 0, 1, DO_TableOfReal_create);
	praat_addMenuCommand ("Objects", "New", "Tiers", 0, 0, 0);
		praat_addMenuCommand ("Objects", "New", "Create empty PointProcess...", 0, 1, DO_PointProcess_createEmpty);
		praat_addMenuCommand ("Objects", "New", "Create Poisson process...", 0, 1, DO_PointProcess_createPoissonProcess);
		praat_addMenuCommand ("Objects", "New", "-- new tiers ---", 0, 1, 0);
		praat_addMenuCommand ("Objects", "New", "Create PitchTier...", 0, 1, DO_PitchTier_create);
		praat_addMenuCommand ("Objects", "New", "Create FormantTier...", 0, 1, DO_FormantTier_create);
		praat_addMenuCommand ("Objects", "New", "Create IntensityTier...", 0, 1, DO_IntensityTier_create);
		praat_addMenuCommand ("Objects", "New", "Create DurationTier...", 0, 1, DO_DurationTier_create);
		praat_addMenuCommand ("Objects", "New", "Create AmplitudeTier...", 0, 1, DO_AmplitudeTier_create);
	praat_addMenuCommand ("Objects", "New", "-- new textgrid --", 0, 0, 0);
	praat_addMenuCommand ("Objects", "New", "Create TextGrid...", 0, 0, DO_TextGrid_create);
	praat_addMenuCommand ("Objects", "New", "Create Strings as file list...", 0, 0, DO_Strings_createAsFileList);
	#ifdef _WIN32
	praat_addMenuCommand ("Objects", "New", "Create Strings as directory list...", 0, 0, DO_Strings_createAsDirectoryList);
	#endif

	praat_addMenuCommand ("Objects", "Read", "-- read raw --", 0, 0, 0);
	praat_addMenuCommand ("Objects", "Read", "Read Matrix from raw text file...", 0, 0, DO_Matrix_readFromRawTextFile);
	praat_addMenuCommand ("Objects", "Read", "Read Matrix from LVS AP file...", 0, praat_HIDDEN, DO_Matrix_readAP);
	praat_addMenuCommand ("Objects", "Read", "Read Strings from raw text file...", 0, 0, DO_Strings_readFromRawTextFile);
	praat_addMenuCommand ("Objects", "Read", "Read TableOfReal from headerless spreadsheet file...", 0, 0, DO_TableOfReal_readFromHeaderlessSpreadsheetFile);
	praat_addMenuCommand ("Objects", "Read", "Read Table from table file...", 0, 0, DO_Table_readFromTableFile);
	praat_addMenuCommand ("Objects", "Read", "Read Table from comma-separated file...", 0, 0, DO_Table_readFromCommaSeparatedFile);
	praat_addMenuCommand ("Objects", "Read", "Read Table from tab-separated file...", 0, 0, DO_Table_readFromTabSeparatedFile);

	praat_addMenuCommand ("Objects", "Read", "-- read tier --", 0, 0, 0);
	praat_addMenuCommand ("Objects", "Read", "Read from special tier file...", 0, 0, 0);
		praat_addMenuCommand ("Objects", "Read", "Read TextTier from Xwaves...", 0, 1, DO_TextTier_readFromXwaves);
		praat_addMenuCommand ("Objects", "Read", "Read IntervalTier from Xwaves...", 0, 1, DO_IntervalTier_readFromXwaves);

	praat_addMenuCommand ("Objects", "ApplicationHelp", "Praat Intro", 0, '?', DO_Intro);
	#ifndef macintosh
		praat_addMenuCommand ("Objects", "Help", "Object window", 0, 0, DO_ObjectWindow);
	#endif
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Frequently asked questions", 0, 0, DO_FrequentlyAskedQuestions);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "What's new?", 0, 0, DO_WhatsNew);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Types of objects", 0, 0, DO_TypesOfObjects);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Editors", 0, 0, DO_Editors);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Acknowledgments", 0, 0, DO_Acknowledgments);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "-- shell help --", 0, 0, 0);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Formulas tutorial", 0, 0, DO_FormulasTutorial);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Scripting tutorial", 0, 0, DO_ScriptingTutorial);
	praat_addMenuCommand ("Objects", "ApplicationHelp", "Programming", 0, 0, DO_Programming);
	#ifdef macintosh
		praat_addMenuCommand ("Objects", "Help", "Praat Intro", 0, '?', DO_Intro);
		praat_addMenuCommand ("Objects", "Help", "Object window help", 0, 0, DO_ObjectWindow);
		praat_addMenuCommand ("Objects", "Help", "-- manual --", 0, 0, 0);
		praat_addMenuCommand ("Objects", "Help", "Search Praat manual...", 0, 'M', DO_SearchManual);
	#endif

	praat_addAction1 (classAmplitudeTier, 0, "AmplitudeTier help", 0, 0, DO_AmplitudeTier_help);
	praat_addAction1 (classAmplitudeTier, 1, "Edit", 0, 0, DO_AmplitudeTier_edit);
	praat_addAction1 (classAmplitudeTier, 0, "Edit with Sound?", 0, 0, DO_info_AmplitudeTier_Sound_edit);
	praat_addAction1 (classAmplitudeTier, 0, "Query -          ", 0, 0, 0);
		praat_TimeTier_query_init (classAmplitudeTier);
		praat_addAction1 (classAmplitudeTier, 1, "Get shimmer (local)...", 0, 1, DO_AmplitudeTier_getShimmer_local);
		praat_addAction1 (classAmplitudeTier, 1, "Get shimmer (local_dB)...", 0, 1, DO_AmplitudeTier_getShimmer_local_dB);
		praat_addAction1 (classAmplitudeTier, 1, "Get shimmer (apq3)...", 0, 1, DO_AmplitudeTier_getShimmer_apq3);
		praat_addAction1 (classAmplitudeTier, 1, "Get shimmer (apq5)...", 0, 1, DO_AmplitudeTier_getShimmer_apq5);
		praat_addAction1 (classAmplitudeTier, 1, "Get shimmer (apq11)...", 0, 1, DO_AmplitudeTier_getShimmer_apq11);
		praat_addAction1 (classAmplitudeTier, 1, "Get shimmer (dda)...", 0, 1, DO_AmplitudeTier_getShimmer_dda);
	praat_addAction1 (classAmplitudeTier, 0, "Modify -          ", 0, 0, 0);
		praat_TimeTier_modify_init (classAmplitudeTier);
		praat_addAction1 (classAmplitudeTier, 0, "Add point...", 0, 1, DO_AmplitudeTier_addPoint);
		praat_addAction1 (classAmplitudeTier, 0, "Formula...", 0, 1, DO_AmplitudeTier_formula);
praat_addAction1 (classAmplitudeTier, 0, "Synthesize", 0, 0, 0);
	praat_addAction1 (classAmplitudeTier, 0, "To Sound (pulse train)...", 0, 0, DO_AmplitudeTier_to_Sound);
praat_addAction1 (classAmplitudeTier, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classAmplitudeTier, 0, "To IntensityTier...", 0, 0, DO_AmplitudeTier_to_IntensityTier);
	praat_addAction1 (classAmplitudeTier, 0, "Down to PointProcess", 0, 0, DO_AmplitudeTier_downto_PointProcess);
	praat_addAction1 (classAmplitudeTier, 0, "Down to TableOfReal", 0, 0, DO_AmplitudeTier_downto_TableOfReal);

	praat_addAction1 (classCochleagram, 0, "Cochleagram help", 0, 0, DO_Cochleagram_help);
	praat_addAction1 (classCochleagram, 1, "Movie", 0, 0, DO_Cochleagram_movie);
praat_addAction1 (classCochleagram, 0, "Info", 0, 0, 0);
	praat_addAction1 (classCochleagram, 2, "Difference...", 0, 0, DO_Cochleagram_difference);
praat_addAction1 (classCochleagram, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classCochleagram, 0, "Paint...", 0, 0, DO_Cochleagram_paint);
praat_addAction1 (classCochleagram, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classCochleagram, 0, "Formula...", 0, 0, DO_Cochleagram_formula);
praat_addAction1 (classCochleagram, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classCochleagram, 0, "To Excitation (slice)...", 0, 0, DO_Cochleagram_to_Excitation);
praat_addAction1 (classCochleagram, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classCochleagram, 0, "To Matrix", 0, 0, DO_Cochleagram_to_Matrix);

	praat_addAction1 (classDistributions, 0, "Distributions help", 0, 0, DO_Distributions_help);
	praat_TableOfReal_init (classDistributions);
	praat_addAction1 (classDistributions, 1, "Get probability (label)...", "Get value...", 1, DO_Distributions_getProbability);
	praat_addAction1 (classDistributions, 0, "-- get from two --", "Get probability (label)...", 1, 0);
	praat_addAction1 (classDistributions, 2, "Get mean absolute difference...", "-- get from two --", 1, DO_Distributionses_getMeanAbsoluteDifference);
	praat_addAction1 (classDistributions, 0, "-- add --", "Append", 1, 0);
	praat_addAction1 (classDistributions, 0, "Add", "-- add --", 1, DO_Distributionses_add);
praat_addAction1 (classDistributions, 0, "Generate", 0, 0, 0);
	praat_addAction1 (classDistributions, 0, "To Strings...", 0, 0, DO_Distributions_to_Strings);
	praat_addAction1 (classDistributions, 0, "To Strings (exact)...", 0, 0, DO_Distributions_to_Strings_exact);
praat_addAction1 (classDistributions, 0, "Learn", 0, 0, 0);
	praat_addAction1 (classDistributions, 1, "To Transition...", 0, 0, DO_Distributions_to_Transition);
	praat_addAction1 (classDistributions, 2, "To Transition (noise)...", 0, 0, DO_Distributions_to_Transition_noise);

	praat_addAction1 (classDurationTier, 0, "DurationTier help", 0, 0, DO_DurationTier_help);
	praat_addAction1 (classDurationTier, 1, "Edit", 0, 0, DO_DurationTier_edit);
	praat_addAction1 (classDurationTier, 0, "Edit with Sound?", 0, 0, DO_info_DurationTier_Sound_edit);
	praat_addAction1 (classDurationTier, 0, "& Manipulation: Replace?", 0, 0, DO_info_DurationTier_Manipulation_replace);
	praat_addAction1 (classDurationTier, 0, "Query -          ", 0, 0, 0);
		praat_TimeTier_query_init (classDurationTier);
		praat_addAction1 (classDurationTier, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classDurationTier, 1, "Get target duration...", 0, 1, DO_DurationTier_getTargetDuration);
	praat_addAction1 (classDurationTier, 0, "Modify -          ", 0, 0, 0);
		praat_TimeTier_modify_init (classDurationTier);
		praat_addAction1 (classDurationTier, 0, "Add point...", 0, 1, DO_DurationTier_addPoint);
		praat_addAction1 (classDurationTier, 0, "Formula...", 0, 1, DO_DurationTier_formula);
praat_addAction1 (classDurationTier, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classDurationTier, 0, "Down to PointProcess", 0, 0, DO_DurationTier_downto_PointProcess);

	praat_addAction1 (classExcitation, 0, "Excitation help", 0, 0, DO_Excitation_help);
praat_addAction1 (classExcitation, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classExcitation, 0, "Draw...", 0, 0, DO_Excitation_draw);
praat_addAction1 (classExcitation, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classExcitation, 0, "To Formant...", 0, 0, DO_Excitation_to_Formant);
praat_addAction1 (classExcitation, 1, "Query -          ", 0, 0, 0);
	praat_addAction1 (classExcitation, 1, "Get loudness", 0, 0, DO_Excitation_getLoudness);
praat_addAction1 (classExcitation, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classExcitation, 0, "Formula...", 0, 0, DO_Excitation_formula);
praat_addAction1 (classExcitation, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classExcitation, 0, "To Matrix", 0, 0, DO_Excitation_to_Matrix);

	praat_addAction1 (classFormant, 0, "Formant help", 0, 0, DO_Formant_help);
	praat_addAction1 (classFormant, 0, "Draw -          ", 0, 0, 0);
		praat_addAction1 (classFormant, 0, "Speckle...", 0, 1, DO_Formant_drawSpeckles);
		praat_addAction1 (classFormant, 0, "Draw tracks...", 0, 1, DO_Formant_drawTracks);
		praat_addAction1 (classFormant, 0, "Scatter plot...", 0, 1, DO_Formant_scatterPlot);
	praat_addAction1 (classFormant, 0, "Query -          ", 0, 0, 0);
		praat_TimeFrameSampled_query_init (classFormant);
		praat_addAction1 (classFormant, 1, "Get number of formants...", 0, 1, DO_Formant_getNumberOfFormants);
		praat_addAction1 (classFormant, 1, "Get minimum number of formants", 0, 1, DO_Formant_getMinimumNumberOfFormants);
		praat_addAction1 (classFormant, 1, "Get maximum number of formants", 0, 1, DO_Formant_getMaximumNumberOfFormants);
		praat_addAction1 (classFormant, 1, "-- get value --", 0, 1, 0);
		praat_addAction1 (classFormant, 1, "Get value at time...", 0, 1, DO_Formant_getValueAtTime);
		praat_addAction1 (classFormant, 1, "Get bandwidth at time...", 0, 1, DO_Formant_getBandwidthAtTime);
		praat_addAction1 (classFormant, 1, "-- get extreme --", 0, 1, 0);
		praat_addAction1 (classFormant, 1, "Get minimum...", 0, 1, DO_Formant_getMinimum);
		praat_addAction1 (classFormant, 1, "Get time of minimum...", 0, 1, DO_Formant_getTimeOfMinimum);
		praat_addAction1 (classFormant, 1, "Get maximum...", 0, 1, DO_Formant_getMaximum);
		praat_addAction1 (classFormant, 1, "Get time of maximum...", 0, 1, DO_Formant_getTimeOfMaximum);
		praat_addAction1 (classFormant, 1, "-- get distribution --", 0, 1, 0);
		praat_addAction1 (classFormant, 1, "Get quantile...", 0, 1, DO_Formant_getQuantile);
		praat_addAction1 (classFormant, 1, "Get quantile of bandwidth...", 0, 1, DO_Formant_getQuantileOfBandwidth);
		praat_addAction1 (classFormant, 1, "Get mean...", 0, 1, DO_Formant_getMean);
		praat_addAction1 (classFormant, 1, "Get standard deviation...", 0, 1, DO_Formant_getStandardDeviation);
	praat_addAction1 (classFormant, 0, "Modify -          ", 0, 0, 0);
		praat_addAction1 (classFormant, 0, "Sort", 0, 1, DO_Formant_sort);
		praat_addAction1 (classFormant, 0, "Formula (frequencies)...", 0, 1, DO_Formant_formula_frequencies);
		praat_addAction1 (classFormant, 0, "Formula (bandwidths)...", 0, 1, DO_Formant_formula_bandwidths);
praat_addAction1 (classFormant, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classFormant, 0, "Track...", 0, 0, DO_Formant_tracker);
	praat_addAction1 (classFormant, 0, "Down to FormantTier", 0, 0, DO_Formant_downto_FormantTier);
praat_addAction1 (classFormant, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classFormant, 0, "To Matrix...", 0, 0, DO_Formant_to_Matrix);

	praat_addAction1 (classFormantTier, 0, "FormantTier help", 0, 0, DO_FormantTier_help);
	praat_addAction1 (classFormantTier, 0, "Draw -          ", 0, 0, 0);
		praat_addAction1 (classFormantTier, 0, "Speckle...", 0, 1, DO_FormantTier_speckle);
	praat_addAction1 (classFormantTier, 0, "Query -          ", 0, 0, 0);
		praat_TimeTier_query_init (classFormantTier);
		praat_addAction1 (classFormantTier, 1, "-- get value --", 0, 1, 0);
		praat_addAction1 (classFormantTier, 1, "Get value at time...", 0, 1, DO_FormantTier_getValueAtTime);
		praat_addAction1 (classFormantTier, 1, "Get bandwidth at time...", 0, 1, DO_FormantTier_getBandwidthAtTime);
	praat_addAction1 (classFormantTier, 0, "Modify -          ", 0, 0, 0);
		praat_TimeTier_modify_init (classFormantTier);
		praat_addAction1 (classFormantTier, 0, "Add point...", 0, 1, DO_FormantTier_addPoint);
praat_addAction1 (classFormantTier, 0, "Down", 0, 0, 0);
	praat_addAction1 (classFormantTier, 0, "Down to TableOfReal...", 0, 0, DO_FormantTier_downto_TableOfReal);

	praat_addAction1 (classHarmonicity, 0, "Harmonicity help", 0, 0, DO_Harmonicity_help);
praat_addAction1 (classHarmonicity, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classHarmonicity, 0, "Draw...", 0, 0, DO_Harmonicity_draw);
	praat_addAction1 (classHarmonicity, 1, "Query -          ", 0, 0, 0);
		praat_TimeFrameSampled_query_init (classHarmonicity);
		praat_addAction1 (classHarmonicity, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classHarmonicity, 1, "Get value at time...", 0, 1, DO_Harmonicity_getValueAtTime);
		praat_addAction1 (classHarmonicity, 1, "Get value in frame...", 0, 1, DO_Harmonicity_getValueInFrame);
		praat_addAction1 (classHarmonicity, 1, "-- get extreme --", 0, 1, 0);
		praat_addAction1 (classHarmonicity, 1, "Get minimum...", 0, 1, DO_Harmonicity_getMinimum);
		praat_addAction1 (classHarmonicity, 1, "Get time of minimum...", 0, 1, DO_Harmonicity_getTimeOfMinimum);
		praat_addAction1 (classHarmonicity, 1, "Get maximum...", 0, 1, DO_Harmonicity_getMaximum);
		praat_addAction1 (classHarmonicity, 1, "Get time of maximum...", 0, 1, DO_Harmonicity_getTimeOfMaximum);
		praat_addAction1 (classHarmonicity, 1, "-- get statistics --", 0, 1, 0);
		praat_addAction1 (classHarmonicity, 1, "Get mean...", 0, 1, DO_Harmonicity_getMean);
		praat_addAction1 (classHarmonicity, 1, "Get standard deviation...", 0, 1, DO_Harmonicity_getStandardDeviation);
praat_addAction1 (classHarmonicity, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classHarmonicity, 0, "Formula...", 0, 0, DO_Harmonicity_formula);
praat_addAction1 (classHarmonicity, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classHarmonicity, 0, "To Matrix", 0, 0, DO_Harmonicity_to_Matrix);

	praat_addAction1 (classIntensity, 0, "Intensity help", 0, 0, DO_Intensity_help);
	praat_addAction1 (classIntensity, 0, "Draw...", 0, 0, DO_Intensity_draw);
	praat_addAction1 (classIntensity, 1, "Query -          ", 0, 0, 0);
		praat_TimeFrameSampled_query_init (classIntensity);
		praat_addAction1 (classIntensity, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classIntensity, 1, "Get value at time...", 0, 1, DO_Intensity_getValueAtTime);
		praat_addAction1 (classIntensity, 1, "Get value in frame...", 0, 1, DO_Intensity_getValueInFrame);
		praat_addAction1 (classIntensity, 1, "-- get extreme --", 0, 1, 0);
		praat_addAction1 (classIntensity, 1, "Get minimum...", 0, 1, DO_Intensity_getMinimum);
		praat_addAction1 (classIntensity, 1, "Get time of minimum...", 0, 1, DO_Intensity_getTimeOfMinimum);
		praat_addAction1 (classIntensity, 1, "Get maximum...", 0, 1, DO_Intensity_getMaximum);
		praat_addAction1 (classIntensity, 1, "Get time of maximum...", 0, 1, DO_Intensity_getTimeOfMaximum);
		praat_addAction1 (classIntensity, 1, "-- get statistics --", 0, 1, 0);
		praat_addAction1 (classIntensity, 1, "Get quantile...", 0, 1, DO_Intensity_getQuantile);
		praat_addAction1 (classIntensity, 1, "Get mean...", 0, 1, DO_Intensity_getMean);
		praat_addAction1 (classIntensity, 1, "Get standard deviation...", 0, 1, DO_Intensity_getStandardDeviation);
	praat_addAction1 (classIntensity, 0, "Modify", 0, 0, 0);
		praat_addAction1 (classIntensity, 0, "Formula...", 0, 0, DO_Intensity_formula);
	praat_addAction1 (classIntensity, 0, "Analyse", 0, 0, 0);
		praat_addAction1 (classIntensity, 0, "To IntensityTier (peaks)", 0, 0, DO_Intensity_to_IntensityTier_peaks);
		praat_addAction1 (classIntensity, 0, "To IntensityTier (valleys)", 0, 0, DO_Intensity_to_IntensityTier_valleys);
	praat_addAction1 (classIntensity, 0, "Convert", 0, 0, 0);
		praat_addAction1 (classIntensity, 0, "Down to IntensityTier", 0, 0, DO_Intensity_downto_IntensityTier);
		praat_addAction1 (classIntensity, 0, "Down to Matrix", 0, 0, DO_Intensity_downto_Matrix);

	praat_addAction1 (classIntensityTier, 0, "IntensityTier help", 0, 0, DO_IntensityTier_help);
	praat_addAction1 (classIntensityTier, 1, "Edit", 0, 0, DO_IntensityTier_edit);
	praat_addAction1 (classIntensityTier, 0, "Edit with Sound?", 0, 0, DO_info_IntensityTier_Sound_edit);
	praat_addAction1 (classIntensityTier, 0, "Query -          ", 0, 0, 0);
		praat_TimeTier_query_init (classIntensityTier);
	praat_addAction1 (classIntensityTier, 0, "Modify -          ", 0, 0, 0);
		praat_TimeTier_modify_init (classIntensityTier);
		praat_addAction1 (classIntensityTier, 0, "Add point...", 0, 1, DO_IntensityTier_addPoint);
		praat_addAction1 (classIntensityTier, 0, "Formula...", 0, 1, DO_IntensityTier_formula);
praat_addAction1 (classIntensityTier, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classIntensityTier, 0, "To AmplitudeTier", 0, 0, DO_IntensityTier_to_AmplitudeTier);
	praat_addAction1 (classIntensityTier, 0, "Down to PointProcess", 0, 0, DO_IntensityTier_downto_PointProcess);
	praat_addAction1 (classIntensityTier, 0, "Down to TableOfReal", 0, 0, DO_IntensityTier_downto_TableOfReal);

	praat_addAction1 (classLtas, 0, "Ltas help", 0, 0, DO_Ltas_help);
	praat_addAction1 (classLtas, 0, "Draw...", 0, 0, DO_Ltas_draw);
	praat_addAction1 (classLtas, 1, "Query -          ", 0, 0, 0);
		praat_addAction1 (classLtas, 1, "Frequency domain", 0, 1, 0);
		praat_addAction1 (classLtas, 1, "Get lowest frequency", 0, 2, DO_Ltas_getLowestFrequency);
		praat_addAction1 (classLtas, 1, "Get highest frequency", 0, 2, DO_Ltas_getHighestFrequency);
		praat_addAction1 (classLtas, 1, "Frequency sampling", 0, 1, 0);
		praat_addAction1 (classLtas, 1, "Get number of bins", 0, 2, DO_Ltas_getNumberOfBins);
			praat_addAction1 (classLtas, 1, "Get number of bands", 0, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getNumberOfBins);
		praat_addAction1 (classLtas, 1, "Get bin width", 0, 2, DO_Ltas_getBinWidth);
			praat_addAction1 (classLtas, 1, "Get band width", 0, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getBinWidth);
		praat_addAction1 (classLtas, 1, "Get frequency from bin number...", 0, 2, DO_Ltas_getFrequencyFromBinNumber);
			praat_addAction1 (classLtas, 1, "Get frequency from band...", 0, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getFrequencyFromBinNumber);
		praat_addAction1 (classLtas, 1, "Get bin number from frequency...", 0, 2, DO_Ltas_getBinNumberFromFrequency);
			praat_addAction1 (classLtas, 1, "Get band from frequency...", 0, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getBinNumberFromFrequency);
		praat_addAction1 (classLtas, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classLtas, 1, "Get value at frequency...", 0, 1, DO_Ltas_getValueAtFrequency);
		praat_addAction1 (classLtas, 1, "Get value in bin...", 0, 1, DO_Ltas_getValueInBin);
			praat_addAction1 (classLtas, 1, "Get value in band...", 0, praat_HIDDEN + praat_DEPTH_1, DO_Ltas_getValueInBin);
		praat_addAction1 (classLtas, 1, "-- get extreme --", 0, 1, 0);
		praat_addAction1 (classLtas, 1, "Get minimum...", 0, 1, DO_Ltas_getMinimum);
		praat_addAction1 (classLtas, 1, "Get frequency of minimum...", 0, 1, DO_Ltas_getFrequencyOfMinimum);
		praat_addAction1 (classLtas, 1, "Get maximum...", 0, 1, DO_Ltas_getMaximum);
		praat_addAction1 (classLtas, 1, "Get frequency of maximum...", 0, 1, DO_Ltas_getFrequencyOfMaximum);
		praat_addAction1 (classLtas, 1, "-- get statistics --", 0, 1, 0);
		praat_addAction1 (classLtas, 1, "Get mean...", 0, 1, DO_Ltas_getMean);
		praat_addAction1 (classLtas, 1, "Get slope...", 0, 1, DO_Ltas_getSlope);
		praat_addAction1 (classLtas, 1, "Get local peak height...", 0, 1, DO_Ltas_getLocalPeakHeight);
		praat_addAction1 (classLtas, 1, "Get standard deviation...", 0, 1, DO_Ltas_getStandardDeviation);
	praat_addAction1 (classLtas, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classLtas, 0, "Formula...", 0, 0, DO_Ltas_formula);
	praat_addAction1 (classLtas, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classLtas, 0, "Compute trend line...", 0, 0, DO_Ltas_computeTrendLine);
	praat_addAction1 (classLtas, 0, "Subtract trend line...", 0, 0, DO_Ltas_subtractTrendLine);
	praat_addAction1 (classLtas, 0, "Combine", 0, 0, 0);
	praat_addAction1 (classLtas, 0, "Merge", 0, praat_HIDDEN, DO_Ltases_merge);
	praat_addAction1 (classLtas, 0, "Average", 0, 0, DO_Ltases_average);
	praat_addAction1 (classLtas, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classLtas, 0, "To Matrix", 0, 0, DO_Ltas_to_Matrix);

	praat_addAction1 (classManipulation, 0, "Manipulation help", 0, 0, DO_Manipulation_help);
	praat_addAction1 (classManipulation, 1, "Edit", 0, 0, DO_Manipulation_edit);
	praat_addAction1 (classManipulation, 0, "Play (PSOLA)", 0, 0, DO_Manipulation_play_psola);
	praat_addAction1 (classManipulation, 0, "Play (LPC)", 0, 0, DO_Manipulation_play_lpc);
	praat_addAction1 (classManipulation, 0, "Get resynthesis (PSOLA)", 0, 0, DO_Manipulation_getResynthesis_psola);
	praat_addAction1 (classManipulation, 0, "Get resynthesis (LPC)", 0, 0, DO_Manipulation_getResynthesis_lpc);
	praat_addAction1 (classManipulation, 0, "Extract original sound", 0, 0, DO_Manipulation_extractOriginalSound);
	praat_addAction1 (classManipulation, 0, "Extract pulses", 0, 0, DO_Manipulation_extractPulses);
	praat_addAction1 (classManipulation, 0, "Extract pitch tier", 0, 0, DO_Manipulation_extractPitchTier);
	praat_addAction1 (classManipulation, 0, "Extract duration tier", 0, 0, DO_Manipulation_extractDurationTier);
	praat_addAction1 (classManipulation, 0, "Replace pitch tier?", 0, 0, DO_Manipulation_replacePitchTier_help);
	praat_addAction1 (classManipulation, 0, "Replace duration tier?", 0, 0, DO_Manipulation_replaceDurationTier_help);
	praat_addAction1 (classManipulation, 1, "Write to text file without Sound...", 0, 0, DO_Manipulation_writeToTextFileWithoutSound);
	praat_addAction1 (classManipulation, 1, "Write to binary file without Sound...", 0, 0, DO_Manipulation_writeToBinaryFileWithoutSound);

	praat_addAction1 (classMatrix, 0, "Matrix help", 0, 0, DO_Matrix_help);
	praat_addAction1 (classMatrix, 1, "Write to matrix text file...", 0, 0, DO_Matrix_writeToMatrixTextFile);
	praat_addAction1 (classMatrix, 1, "Write to headerless spreadsheet file...", 0, 0, DO_Matrix_writeToHeaderlessSpreadsheetFile);
	praat_addAction1 (classMatrix, 1, "Play movie", 0, 0, DO_Matrix_movie);
	praat_addAction1 (classMatrix, 0, "Draw -          ", 0, 0, 0);
		praat_addAction1 (classMatrix, 0, "Draw rows...", 0, 1, DO_Matrix_drawRows);
		praat_addAction1 (classMatrix, 0, "Draw one contour...", 0, 1, DO_Matrix_drawOneContour);
		praat_addAction1 (classMatrix, 0, "Draw contours...", 0, 1, DO_Matrix_drawContours);
		praat_addAction1 (classMatrix, 0, "Paint image...", 0, 1, DO_Matrix_paintImage);
		praat_addAction1 (classMatrix, 0, "Paint contours...", 0, 1, DO_Matrix_paintContours);
		praat_addAction1 (classMatrix, 0, "Paint cells...", 0, 1, DO_Matrix_paintCells);
		praat_addAction1 (classMatrix, 0, "Paint surface...", 0, 1, DO_Matrix_paintSurface);
	praat_addAction1 (classMatrix, 1, "Query -          ", 0, 0, 0);
		praat_addAction1 (classMatrix, 1, "Get lowest x", 0, 1, DO_Matrix_getLowestX);
		praat_addAction1 (classMatrix, 1, "Get highest x", 0, 1, DO_Matrix_getHighestX);
		praat_addAction1 (classMatrix, 1, "Get lowest y", 0, 1, DO_Matrix_getLowestY);
		praat_addAction1 (classMatrix, 1, "Get highest y", 0, 1, DO_Matrix_getHighestY);
		praat_addAction1 (classMatrix, 1, "-- get structure --", 0, 1, 0);
		praat_addAction1 (classMatrix, 1, "Get number of rows", 0, 1, DO_Matrix_getNumberOfRows);
		praat_addAction1 (classMatrix, 1, "Get number of columns", 0, 1, DO_Matrix_getNumberOfColumns);
		praat_addAction1 (classMatrix, 1, "Get row distance", 0, 1, DO_Matrix_getRowDistance);
		praat_addAction1 (classMatrix, 1, "Get column distance", 0, 1, DO_Matrix_getColumnDistance);
		praat_addAction1 (classMatrix, 1, "Get y of row...", 0, 1, DO_Matrix_getYofRow);
		praat_addAction1 (classMatrix, 1, "Get x of column...", 0, 1, DO_Matrix_getXofColumn);
		praat_addAction1 (classMatrix, 1, "-- get value --", 0, 1, 0);
		praat_addAction1 (classMatrix, 1, "Get value in cell...", 0, 1, DO_Matrix_getValueInCell);
		praat_addAction1 (classMatrix, 1, "Get value at xy...", 0, 1, DO_Matrix_getValueAtXY);
		praat_addAction1 (classMatrix, 1, "Get sum", 0, 1, DO_Matrix_getSum);
	praat_addAction1 (classMatrix, 0, "Modify -          ", 0, 0, 0);
		praat_addAction1 (classMatrix, 0, "Formula...", 0, 1, DO_Matrix_formula);
		praat_addAction1 (classMatrix, 0, "Set value...", 0, 1, DO_Matrix_setValue);
praat_addAction1 (classMatrix, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classMatrix, 0, "Eigen", 0, 0, DO_Matrix_eigen);
	praat_addAction1 (classMatrix, 0, "Synthesize", 0, 0, 0);
	praat_addAction1 (classMatrix, 0, "Power...", 0, 0, DO_Matrix_power);
	praat_addAction1 (classMatrix, 0, "Combine two Matrices -", 0, 0, 0);
		praat_addAction1 (classMatrix, 2, "Merge (append rows)", 0, 1, DO_Matrix_appendRows);
		praat_addAction1 (classMatrix, 2, "To ParamCurve", 0, 1, DO_Matrix_to_ParamCurve);
	praat_addAction1 (classMatrix, 0, "Cast -", 0, 0, 0);
		praat_addAction1 (classMatrix, 0, "To Cochleagram", 0, 1, DO_Matrix_to_Cochleagram);
		praat_addAction1 (classMatrix, 0, "To Excitation", 0, 1, DO_Matrix_to_Excitation);
		praat_addAction1 (classMatrix, 0, "To Harmonicity", 0, 1, DO_Matrix_to_Harmonicity);
		praat_addAction1 (classMatrix, 0, "To Intensity", 0, 1, DO_Matrix_to_Intensity);
		praat_addAction1 (classMatrix, 0, "To Ltas", 0, 1, DO_Matrix_to_Ltas);
		praat_addAction1 (classMatrix, 0, "To Pitch", 0, 1, DO_Matrix_to_Pitch);
		praat_addAction1 (classMatrix, 0, "To PointProcess", 0, 1, DO_Matrix_to_PointProcess);
		praat_addAction1 (classMatrix, 0, "To Polygon", 0, 1, DO_Matrix_to_Polygon);
		praat_addAction1 (classMatrix, 0, "To Sound (slice)...", 0, 1, DO_Matrix_to_Sound);
		praat_addAction1 (classMatrix, 0, "To Spectrogram", 0, 1, DO_Matrix_to_Spectrogram);
		praat_addAction1 (classMatrix, 0, "To TableOfReal", 0, 1, DO_Matrix_to_TableOfReal);
		praat_addAction1 (classMatrix, 0, "To Spectrum", 0, 1, DO_Matrix_to_Spectrum);
		praat_addAction1 (classMatrix, 0, "To Transition", 0, 1, DO_Matrix_to_Transition);
		praat_addAction1 (classMatrix, 0, "To VocalTract", 0, 1, DO_Matrix_to_VocalTract);

	praat_addAction1 (classPairDistribution, 0, "PairDistribution help", 0, 0, DO_PairDistribution_help);
	praat_addAction1 (classPairDistribution, 1, "To Stringses...", 0, 0, DO_PairDistribution_to_Stringses);
	praat_addAction1 (classPairDistribution, 0, "Query -          ", 0, 0, 0);
	praat_addAction1 (classPairDistribution, 1, "Get fraction correct (maximum likelihood)", 0, 1, DO_PairDistribution_getFractionCorrect_maximumLikelihood);
	praat_addAction1 (classPairDistribution, 1, "Get fraction correct (probability matching)", 0, 1, DO_PairDistribution_getFractionCorrect_probabilityMatching);
	praat_addAction1 (classPairDistribution, 0, "Modify -          ", 0, 0, 0);
	praat_addAction1 (classPairDistribution, 1, "Remove zero weights", 0, 0, DO_PairDistribution_removeZeroWeights);

	praat_addAction1 (classParamCurve, 0, "ParamCurve help", 0, 0, DO_ParamCurve_help);
	praat_addAction1 (classParamCurve, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classParamCurve, 0, "Draw...", 0, 0, DO_ParamCurve_draw);

	praat_addAction1 (classPitch, 0, "Pitch help", 0, 0, DO_Pitch_help);
	praat_addAction1 (classPitch, 1, "Edit", 0, 0, DO_Pitch_edit);
	praat_addAction1 (classPitch, 0, "Play -           ", 0, 0, 0);
		praat_addAction1 (classPitch, 0, "Play pulses", 0, 1, DO_Pitch_play);
		praat_addAction1 (classPitch, 0, "Hum", 0, 1, DO_Pitch_hum);
	praat_addAction1 (classPitch, 0, "Draw -           ", 0, 0, 0);
		praat_addAction1 (classPitch, 0, "Draw...", 0, 1, DO_Pitch_draw);
		praat_addAction1 (classPitch, 0, "Draw logarithmic...", 0, 1, DO_Pitch_drawLogarithmic);
		praat_addAction1 (classPitch, 0, "Draw semitones...", 0, 1, DO_Pitch_drawSemitones);
		praat_addAction1 (classPitch, 0, "Draw mel...", 0, 1, DO_Pitch_drawMel);
		praat_addAction1 (classPitch, 0, "Draw erb...", 0, 1, DO_Pitch_drawErb);
		praat_addAction1 (classPitch, 0, "Speckle...", 0, 1, DO_Pitch_speckle);
		praat_addAction1 (classPitch, 0, "Speckle logarithmic...", 0, 1, DO_Pitch_speckleLogarithmic);
		praat_addAction1 (classPitch, 0, "Speckle semitones...", 0, 1, DO_Pitch_speckleSemitones);
		praat_addAction1 (classPitch, 0, "Speckle mel...", 0, 1, DO_Pitch_speckleMel);
		praat_addAction1 (classPitch, 0, "Speckle erb...", 0, 1, DO_Pitch_speckleErb);
	praat_addAction1 (classPitch, 0, "Query -          ", 0, 0, 0);
		praat_TimeFrameSampled_query_init (classPitch);
		praat_addAction1 (classPitch, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classPitch, 1, "Count voiced frames", 0, 1, DO_Pitch_getNumberOfVoicedFrames);
		praat_addAction1 (classPitch, 1, "Get value at time...", 0, 1, DO_Pitch_getValueAtTime);
		praat_addAction1 (classPitch, 1, "Get value in frame...", 0, 1, DO_Pitch_getValueInFrame);
		praat_addAction1 (classPitch, 1, "-- get extreme --", 0, 1, 0);
		praat_addAction1 (classPitch, 1, "Get minimum...", 0, 1, DO_Pitch_getMinimum);
		praat_addAction1 (classPitch, 1, "Get time of minimum...", 0, 1, DO_Pitch_getTimeOfMinimum);
		praat_addAction1 (classPitch, 1, "Get maximum...", 0, 1, DO_Pitch_getMaximum);
		praat_addAction1 (classPitch, 1, "Get time of maximum...", 0, 1, DO_Pitch_getTimeOfMaximum);
		praat_addAction1 (classPitch, 1, "-- get statistics --", 0, 1, 0);
		praat_addAction1 (classPitch, 1, "Get quantile...", 0, 1, DO_Pitch_getQuantile);
		/*praat_addAction1 (classPitch, 1, "Get spreading...", 0, 1, DO_Pitch_getSpreading);*/
		praat_addAction1 (classPitch, 1, "Get mean...", 0, 1, DO_Pitch_getMean);
		praat_addAction1 (classPitch, 1, "Get standard deviation...", 0, 1, DO_Pitch_getStandardDeviation);
		praat_addAction1 (classPitch, 1, "-- get slope --", 0, 1, 0);
		praat_addAction1 (classPitch, 1, "Get mean absolute slope...", 0, 1, DO_Pitch_getMeanAbsoluteSlope);
		praat_addAction1 (classPitch, 1, "Get slope without octave jumps", 0, 1, DO_Pitch_getMeanAbsSlope_noOctave);
		praat_addAction1 (classPitch, 2, "-- query two --", 0, 1, 0);
		praat_addAction1 (classPitch, 2, "Count differences", 0, 1, DO_Pitch_difference);
	praat_addAction1 (classPitch, 0, "Modify -          ", 0, 0, 0);
		praat_addAction1 (classPitch, 0, "Formula...", 0, 1, DO_Pitch_formula);
	praat_addAction1 (classPitch, 0, "Annotate -   ", 0, 0, 0);
		praat_addAction1 (classPitch, 0, "To TextGrid...", 0, 1, DO_Pitch_to_TextGrid);
		praat_addAction1 (classPitch, 0, "-- to single tier --", 0, 1, 0);
		praat_addAction1 (classPitch, 0, "To TextTier", 0, 1, DO_Pitch_to_TextTier);
		praat_addAction1 (classPitch, 0, "To IntervalTier", 0, 1, DO_Pitch_to_IntervalTier);
praat_addAction1 (classPitch, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classPitch, 0, "To PointProcess", 0, 0, DO_Pitch_to_PointProcess);
praat_addAction1 (classPitch, 0, "Synthesize", 0, 0, 0);
	praat_addAction1 (classPitch, 0, "To Sound (pulses)", 0, 0, DO_Pitch_to_Sound_pulses);
	praat_addAction1 (classPitch, 0, "To Sound (hum)", 0, 0, DO_Pitch_to_Sound_hum);
	praat_addAction1 (classPitch, 0, "To Sound (sine)...", 0, 1, DO_Pitch_to_Sound_sine);
praat_addAction1 (classPitch, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classPitch, 0, "Kill octave jumps", 0, 0, DO_Pitch_killOctaveJumps);
	praat_addAction1 (classPitch, 0, "Interpolate", 0, 0, DO_Pitch_interpolate);
	praat_addAction1 (classPitch, 0, "Smooth...", 0, 0, DO_Pitch_smooth);
	praat_addAction1 (classPitch, 0, "Subtract linear fit...", 0, 0, DO_Pitch_subtractLinearFit);
	praat_addAction1 (classPitch, 0, "Down to PitchTier", 0, 0, DO_Pitch_to_PitchTier);
	praat_addAction1 (classPitch, 0, "To Matrix", 0, 0, DO_Pitch_to_Matrix);

	praat_addAction1 (classPitchTier, 1, "Write to PitchTier spreadsheet file...", 0, 0, DO_PitchTier_writeToPitchTierSpreadsheetFile);
	praat_addAction1 (classPitchTier, 1, "Write to headerless spreadsheet file...", 0, 0, DO_PitchTier_writeToHeaderlessSpreadsheetFile);
	praat_addAction1 (classPitchTier, 0, "PitchTier help", 0, 0, DO_PitchTier_help);
	praat_addAction1 (classPitchTier, 1, "Edit", 0, 0, DO_PitchTier_edit);
	praat_addAction1 (classPitchTier, 0, "Edit with Sound?", 0, 0, DO_info_PitchTier_Sound_edit);
	praat_addAction1 (classPitchTier, 0, "Play pulses", 0, 0, DO_PitchTier_play);
	praat_addAction1 (classPitchTier, 0, "Hum", 0, 0, DO_PitchTier_hum);
	praat_addAction1 (classPitchTier, 0, "Play sine", 0, 0, DO_PitchTier_playSine);
	praat_addAction1 (classPitchTier, 0, "Draw...", 0, 0, DO_PitchTier_draw);
	praat_addAction1 (classPitchTier, 0, "& Manipulation: Replace?", 0, 0, DO_info_PitchTier_Manipulation_replace);
	praat_addAction1 (classPitchTier, 0, "Query -          ", 0, 0, 0);
		praat_TimeTier_query_init (classPitchTier);
		praat_addAction1 (classPitchTier, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classPitchTier, 1, "Get value at time...", 0, 1, DO_PitchTier_getValueAtTime);
		praat_addAction1 (classPitchTier, 1, "Get value at index...", 0, 1, DO_PitchTier_getValueAtIndex);
		praat_addAction1 (classPitchTier, 1, "-- get statistics --", 0, 1, 0);
		praat_addAction1 (classPitchTier, 1, "Get mean (curve)...", 0, 1, DO_PitchTier_getMean_curve);
		praat_addAction1 (classPitchTier, 1, "Get mean (points)...", 0, 1, DO_PitchTier_getMean_points);
		praat_addAction1 (classPitchTier, 1, "Get standard deviation (curve)...", 0, 1, DO_PitchTier_getStandardDeviation_curve);
		praat_addAction1 (classPitchTier, 1, "Get standard deviation (points)...", 0, 1, DO_PitchTier_getStandardDeviation_points);
	praat_addAction1 (classPitchTier, 0, "Modify -          ", 0, 0, 0);
		praat_TimeTier_modify_init (classPitchTier);
		praat_addAction1 (classPitchTier, 0, "Add point...", 0, 1, DO_PitchTier_addPoint);
		praat_addAction1 (classPitchTier, 0, "Formula...", 0, 1, DO_PitchTier_formula);
		praat_addAction1 (classPitchTier, 0, "-- stylize --", 0, 1, 0);
		praat_addAction1 (classPitchTier, 0, "Stylize...", 0, 1, DO_PitchTier_stylize);
		praat_addAction1 (classPitchTier, 0, "Interpolate quadratically...", 0, 1, DO_PitchTier_interpolateQuadratically);
		praat_addAction1 (classPitchTier, 0, "-- modify frequencies --", 0, 1, 0);
		praat_addAction1 (classPitchTier, 0, "Shift frequencies...", 0, 1, DO_PitchTier_shiftFrequencies);
		praat_addAction1 (classPitchTier, 0, "Multiply frequencies...", 0, 1, DO_PitchTier_multiplyFrequencies);
	praat_addAction1 (classPitchTier, 0, "Synthesize -", 0, 0, 0);
		praat_addAction1 (classPitchTier, 0, "To PointProcess", 0, 1, DO_PitchTier_to_PointProcess);
		praat_addAction1 (classPitchTier, 0, "To Sound (pulse train)...", 0, 1, DO_PitchTier_to_Sound_pulseTrain);
		praat_addAction1 (classPitchTier, 0, "To Sound (phonation)...", 0, 1, DO_PitchTier_to_Sound_phonation);
		praat_addAction1 (classPitchTier, 0, "To Sound (sine)...", 0, 1, DO_PitchTier_to_Sound_sine);
	praat_addAction1 (classPitchTier, 0, "Convert -", 0, 0, 0);
		praat_addAction1 (classPitchTier, 0, "Down to PointProcess", 0, 1, DO_PitchTier_downto_PointProcess);
		praat_addAction1 (classPitchTier, 0, "Down to TableOfReal...", 0, 1, DO_PitchTier_downto_TableOfReal);

	praat_addAction1 (classPointProcess, 0, "PointProcess help", 0, 0, DO_PointProcess_help);
	praat_addAction1 (classPointProcess, 0, "Edit -          ", 0, 0, 0);
		praat_addAction1 (classPointProcess, 1, "Edit alone", 0, 1, DO_PointProcess_edit);
		praat_addAction1 (classPointProcess, 0, "Edit with Sound?", 0, 1, DO_info_PointProcess_Sound_edit);
	praat_addAction1 (classPointProcess, 0, "Play -          ", 0, 0, 0);
		praat_addAction1 (classPointProcess, 0, "Play as pulse train", 0, 1, DO_PointProcess_play);
		praat_addAction1 (classPointProcess, 0, "Hum", 0, 1, DO_PointProcess_hum);
	praat_addAction1 (classPointProcess, 0, "Draw...", 0, 0, DO_PointProcess_draw);
	praat_addAction1 (classPointProcess, 0, "Query -          ", 0, 0, 0);
		praat_TimeFunction_query_init (classPointProcess);
		praat_addAction1 (classPointProcess, 1, "-- script get --", 0, 1, 0);
		praat_addAction1 (classPointProcess, 1, "Get number of points", 0, 1, DO_PointProcess_getNumberOfPoints);
		praat_addAction1 (classPointProcess, 1, "Get low index...", 0, 1, DO_PointProcess_getLowIndex);
		praat_addAction1 (classPointProcess, 1, "Get high index...", 0, 1, DO_PointProcess_getHighIndex);
		praat_addAction1 (classPointProcess, 1, "Get nearest index...", 0, 1, DO_PointProcess_getNearestIndex);
		praat_addAction1 (classPointProcess, 1, "Get time from index...", 0, 1, DO_PointProcess_getTimeFromIndex);
		praat_addAction1 (classPointProcess, 1, "Get interval...", 0, 1, DO_PointProcess_getInterval);
		praat_addAction1 (classPointProcess, 1, "-- periods --", 0, 1, 0);
		praat_addAction1 (classPointProcess, 1, "Get number of periods...", 0, 1, DO_PointProcess_getNumberOfPeriods);
		praat_addAction1 (classPointProcess, 1, "Get mean period...", 0, 1, DO_PointProcess_getMeanPeriod);
		praat_addAction1 (classPointProcess, 1, "Get stdev period...", 0, 1, DO_PointProcess_getStdevPeriod);
		praat_addAction1 (classPointProcess, 1, "Get jitter (local)...", 0, 1, DO_PointProcess_getJitter_local);
		praat_addAction1 (classPointProcess, 1, "Get jitter (local, absolute)...", 0, 1, DO_PointProcess_getJitter_local_absolute);
		praat_addAction1 (classPointProcess, 1, "Get jitter (rap)...", 0, 1, DO_PointProcess_getJitter_rap);
		praat_addAction1 (classPointProcess, 1, "Get jitter (ppq5)...", 0, 1, DO_PointProcess_getJitter_ppq5);
		praat_addAction1 (classPointProcess, 1, "Get jitter (ddp)...", 0, 1, DO_PointProcess_getJitter_ddp);
	praat_addAction1 (classPointProcess, 0, "Modify -          ", 0, 0, 0);
		praat_addAction1 (classPointProcess, 0, "Add point...", 0, 1, DO_PointProcess_addPoint);
		praat_addAction1 (classPointProcess, 0, "Remove point...", 0, 1, DO_PointProcess_removePoint);
		praat_addAction1 (classPointProcess, 0, "Remove point near...", 0, 1, DO_PointProcess_removePointNear);
		praat_addAction1 (classPointProcess, 0, "Remove points...", 0, 1, DO_PointProcess_removePoints);
		praat_addAction1 (classPointProcess, 0, "Remove points between...", 0, 1, DO_PointProcess_removePointsBetween);
		praat_addAction1 (classPointProcess, 0, "-- voice --", 0, 1, 0);
		praat_addAction1 (classPointProcess, 0, "Fill...", 0, 1, DO_PointProcess_fill);
		praat_addAction1 (classPointProcess, 0, "Voice...", 0, 1, DO_PointProcess_voice);
	praat_addAction1 (classPointProcess, 0, "Annotate -   ", 0, 0, 0);
		praat_addAction1 (classPointProcess, 0, "To TextGrid...", 0, 1, DO_PointProcess_to_TextGrid);
		praat_addAction1 (classPointProcess, 0, "-- to single tier --", 0, 1, 0);
		praat_addAction1 (classPointProcess, 0, "To TextTier", 0, 1, DO_PointProcess_to_TextTier);
		praat_addAction1 (classPointProcess, 0, "To IntervalTier", 0, 1, DO_PointProcess_to_IntervalTier);
praat_addAction1 (classPointProcess, 0, "Set calculus", 0, 0, 0);
	praat_addAction1 (classPointProcess, 2, "Union", 0, 0, DO_PointProcess_union);
	praat_addAction1 (classPointProcess, 2, "Intersection", 0, 0, DO_PointProcess_intersection);
	praat_addAction1 (classPointProcess, 2, "Difference", 0, 0, DO_PointProcess_difference);
praat_addAction1 (classPointProcess, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classPointProcess, 0, "To PitchTier...", 0, 0, DO_PointProcess_to_PitchTier);
	praat_addAction1 (classPointProcess, 0, "To TextGrid (vuv)...", 0, 0, DO_PointProcess_to_TextGrid_vuv);
praat_addAction1 (classPointProcess, 0, "Synthesize", 0, 0, 0);
	praat_addAction1 (classPointProcess, 0, "To Sound (pulse train)...", 0, 0, DO_PointProcess_to_Sound_pulseTrain);
	praat_addAction1 (classPointProcess, 0, "To Sound (phonation)...", 0, 0, DO_PointProcess_to_Sound_phonation);
	praat_addAction1 (classPointProcess, 0, "To Sound (hum)...", 0, 0, DO_PointProcess_to_Sound_hum);
praat_addAction1 (classPointProcess, 0, "Convert", 0, 0, 0);
	praat_addAction1 (classPointProcess, 0, "To Matrix", 0, 0, DO_PointProcess_to_Matrix);
	praat_addAction1 (classPointProcess, 0, "Up to TextTier...", 0, 0, DO_PointProcess_upto_TextTier);
	praat_addAction1 (classPointProcess, 0, "Up to PitchTier...", 0, 0, DO_PointProcess_upto_PitchTier);
	praat_addAction1 (classPointProcess, 0, "Up to IntensityTier...", 0, 0, DO_PointProcess_upto_IntensityTier);

	praat_addAction1 (classPolygon, 0, "Polygon help", 0, 0, DO_Polygon_help);
praat_addAction1 (classPolygon, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classPolygon, 0, "Draw...", 0, 0, DO_Polygon_draw);
	praat_addAction1 (classPolygon, 0, "Paint...", 0, 0, DO_Polygon_paint);
	praat_addAction1 (classPolygon, 0, "Draw circles...", 0, 0, DO_Polygon_drawCircles);
	praat_addAction1 (classPolygon, 0, "Paint circles...", 0, 0, DO_Polygon_paintCircles);
	praat_addAction1 (classPolygon, 2, "Draw connection...", 0, 0, DO_Polygons_drawConnection);
praat_addAction1 (classPolygon, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classPolygon, 0, "Randomize", 0, 0, DO_Polygon_randomize);
	praat_addAction1 (classPolygon, 0, "Salesperson...", 0, 0, DO_Polygon_salesperson);
praat_addAction1 (classPolygon, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classPolygon, 0, "To Matrix", 0, 0, DO_Polygon_to_Matrix);

	praat_addAction1 (classSpectrogram, 0, "Spectrogram help", 0, 0, DO_Spectrogram_help);
	praat_addAction1 (classSpectrogram, 1, "View", 0, 0, DO_Spectrogram_view);
	praat_addAction1 (classSpectrogram, 1, "Movie", 0, 0, DO_Spectrogram_movie);
praat_addAction1 (classSpectrogram, 0, "Query -          ", 0, 0, 0);
		praat_TimeFrameSampled_query_init (classSpectrogram);
	praat_addAction1 (classSpectrogram, 1, "Get power at...", 0, 1, DO_Spectrogram_getPowerAt);
praat_addAction1 (classSpectrogram, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classSpectrogram, 0, "Paint...", 0, 0, DO_Spectrogram_paint);
praat_addAction1 (classSpectrogram, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classSpectrogram, 0, "To Spectrum (slice)...", 0, 0, DO_Spectrogram_to_Spectrum);
praat_addAction1 (classSpectrogram, 0, "Synthesize", 0, 0, 0);
	praat_addAction1 (classSpectrogram, 0, "To Sound...", 0, 0, DO_Spectrogram_to_Sound);
praat_addAction1 (classSpectrogram, 0, "Modify", 0, 0, 0);
	praat_addAction1 (classSpectrogram, 0, "Formula...", 0, 0, DO_Spectrogram_formula);
praat_addAction1 (classSpectrogram, 0, "Hack", 0, 0, 0);
	praat_addAction1 (classSpectrogram, 0, "To Matrix", 0, 0, DO_Spectrogram_to_Matrix);

	praat_addAction1 (classSpectrum, 0, "Spectrum help", 0, 0, DO_Spectrum_help);
	praat_addAction1 (classSpectrum, 1, "Edit", 0, 0, DO_Spectrum_edit);
	praat_addAction1 (classSpectrum, 0, "Draw -          ", 0, 0, 0);
		praat_addAction1 (classSpectrum, 0, "Draw...", 0, 1, DO_Spectrum_draw);
		praat_addAction1 (classSpectrum, 0, "Draw (log freq)...", 0, 1, DO_Spectrum_drawLogFreq);
	praat_addAction1 (classSpectrum, 1, "Query -          ", 0, 0, 0);
		praat_addAction1 (classSpectrum, 1, "Frequency domain", 0, 1, 0);
			praat_addAction1 (classSpectrum, 1, "Get lowest frequency", 0, 2, DO_Spectrum_getLowestFrequency);
			praat_addAction1 (classSpectrum, 1, "Get highest frequency", 0, 2, DO_Spectrum_getHighestFrequency);
		praat_addAction1 (classSpectrum, 1, "Frequency sampling", 0, 1, 0);
			praat_addAction1 (classSpectrum, 1, "Get number of bins", 0, 2, DO_Spectrum_getNumberOfBins);
			praat_addAction1 (classSpectrum, 1, "Get bin width", 0, 2, DO_Spectrum_getBinWidth);
			praat_addAction1 (classSpectrum, 1, "Get frequency from bin number...", 0, 2, DO_Spectrum_getFrequencyFromBin);
						praat_addAction1 (classSpectrum, 1, "Get frequency from bin...", 0, praat_HIDDEN + praat_DEPTH_2, DO_Spectrum_getFrequencyFromBin);
			praat_addAction1 (classSpectrum, 1, "Get bin number from frequency...", 0, 2, DO_Spectrum_getBinFromFrequency);
						praat_addAction1 (classSpectrum, 1, "Get bin from frequency...", 0, praat_HIDDEN + praat_DEPTH_2, DO_Spectrum_getBinFromFrequency);
		praat_addAction1 (classSpectrum, 1, "-- get content --", 0, 1, 0);
		praat_addAction1 (classSpectrum, 1, "Get real value in bin...", 0, 1, DO_Spectrum_getRealValueInBin);
		praat_addAction1 (classSpectrum, 1, "Get imaginary value in bin...", 0, 1, DO_Spectrum_getImaginaryValueInBin);
		praat_addAction1 (classSpectrum, 1, "-- get energy --", 0, 1, 0);
		praat_addAction1 (classSpectrum, 1, "Get band energy...", 0, 1, DO_Spectrum_getBandEnergy);
		praat_addAction1 (classSpectrum, 1, "Get band density...", 0, 1, DO_Spectrum_getBandDensity);
		praat_addAction1 (classSpectrum, 1, "Get band energy difference...", 0, 1, DO_Spectrum_getBandEnergyDifference);
		praat_addAction1 (classSpectrum, 1, "Get band density difference...", 0, 1, DO_Spectrum_getBandDensityDifference);
		praat_addAction1 (classSpectrum, 1, "-- get moments --", 0, 1, 0);
		praat_addAction1 (classSpectrum, 1, "Get centre of gravity...", 0, 1, DO_Spectrum_getCentreOfGravity);
		praat_addAction1 (classSpectrum, 1, "Get standard deviation...", 0, 1, DO_Spectrum_getStandardDeviation);
		praat_addAction1 (classSpectrum, 1, "Get skewness...", 0, 1, DO_Spectrum_getSkewness);
		praat_addAction1 (classSpectrum, 1, "Get kurtosis...", 0, 1, DO_Spectrum_getKurtosis);
		praat_addAction1 (classSpectrum, 1, "Get central moment...", 0, 1, DO_Spectrum_getCentralMoment);
	praat_addAction1 (classSpectrum, 0, "Modify -          ", 0, 0, 0);
		praat_addAction1 (classSpectrum, 0, "Formula...", 0, 1, DO_Spectrum_formula);
		praat_addAction1 (classSpectrum, 0, "Filter (pass Hann band)...", 0, 1, DO_Spectrum_passHannBand);
		praat_addAction1 (classSpectrum, 0, "Filter (stop Hann band)...", 0, 1, DO_Spectrum_stopHannBand);
	praat_addAction1 (classSpectrum, 0, "Analyse", 0, 0, 0);
		praat_addAction1 (classSpectrum, 0, "To Excitation...", 0, 0, DO_Spectrum_to_Excitation);
		praat_addAction1 (classSpectrum, 0, "To Formant (peaks)...", 0, 0, DO_Spectrum_to_Formant_peaks);
		praat_addAction1 (classSpectrum, 0, "To Ltas...", 0, 0, DO_Spectrum_to_Ltas);
		praat_addAction1 (classSpectrum, 0, "To Ltas (1-to-1)", 0, 0, DO_Spectrum_to_Ltas_1to1);
		praat_addAction1 (classSpectrum, 0, "To Spectrogram", 0, 0, DO_Spectrum_to_Spectrogram);
	praat_addAction1 (classSpectrum, 0, "Convert", 0, 0, 0);
		praat_addAction1 (classSpectrum, 0, "Cepstral smoothing...", 0, 0, DO_Spectrum_cepstralSmoothing);
		praat_addAction1 (classSpectrum, 0, "LPC smoothing...", 0, 0, DO_Spectrum_lpcSmoothing);
	praat_addAction1 (classSpectrum, 0, "Synthesize", 0, 0, 0);
		praat_addAction1 (classSpectrum, 0, "To Sound", 0, 0, DO_Spectrum_to_Sound);
						praat_addAction1 (classSpectrum, 0, "To Sound (fft)", 0, praat_HIDDEN, DO_Spectrum_to_Sound);
	praat_addAction1 (classSpectrum, 0, "Hack", 0, 0, 0);
		praat_addAction1 (classSpectrum, 0, "To Matrix", 0, 0, DO_Spectrum_to_Matrix);

	praat_addAction1 (classStrings, 0, "Strings help", 0, 0, DO_Strings_help);
	praat_addAction1 (classStrings, 1, "Write to raw text file...", 0, 0, DO_Strings_writeToRawTextFile);
	praat_addAction1 (classStrings, 0, "Query", 0, 0, 0);
		praat_addAction1 (classStrings, 2, "Equal?", 0, 0, DO_Strings_equal);
		praat_addAction1 (classStrings, 1, "Get number of strings", 0, 0, DO_Strings_getNumberOfStrings);
		praat_addAction1 (classStrings, 1, "Get string...", 0, 0, DO_Strings_getString);
	praat_addAction1 (classStrings, 0, "Modify", 0, 0, 0);
		praat_addAction1 (classStrings, 0, "Randomize", 0, 0, DO_Strings_randomize);
		praat_addAction1 (classStrings, 0, "Sort", 0, 0, DO_Strings_sort);
		praat_addAction1 (classStrings, 0, "Genericize", 0, 0, DO_Strings_genericize);
	praat_addAction1 (classStrings, 0, "Analyze", 0, 0, 0);
		praat_addAction1 (classStrings, 0, "To Distributions", 0, 0, DO_Strings_to_Distributions);
	praat_addAction1 (classStrings, 0, "Synthesize", 0, 0, 0);
		praat_addAction1 (classStrings, 0, "To WordList", 0, 0, DO_Strings_to_WordList);

	praat_addAction1 (classTableOfReal, 0, "TableOfReal help", 0, 0, DO_TableOfReal_help);
	praat_TableOfReal_init (classTableOfReal);

	praat_addAction1 (classTransition, 0, "Transition help", 0, 0, DO_Transition_help);
praat_addAction1 (classTransition, 0, "Draw", 0, 0, 0);
	praat_addAction1 (classTransition, 0, "Draw as numbers...", 0, 0, DO_Transition_drawAsNumbers);
praat_addAction1 (classTransition, 0, "Analyse", 0, 0, 0);
	praat_addAction1 (classTransition, 0, "Eigen", 0, 0, DO_Transition_eigen);
	praat_addAction1 (classTransition, 0, "Conflate", 0, 0, DO_Transition_conflate);
praat_addAction1 (classTransition, 0, "Synthesize", 0, 0, 0);
	praat_addAction1 (classTransition, 0, "Power...", 0, 0, DO_Transition_power);
praat_addAction1 (classTransition, 0, "Cast", 0, 0, 0);
	praat_addAction1 (classTransition, 0, "To Matrix", 0, 0, DO_Transition_to_Matrix);

	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, "Edit", 0, 0, DO_AmplitudeTier_edit);
	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, "Multiply", 0, 0, DO_Sound_AmplitudeTier_multiply);
	praat_addAction2 (classDistributions, 1, classTransition, 1, "Map", 0, 0, DO_Distributions_Transition_map);
	praat_addAction2 (classDistributions, 1, classTransition, 1, "To Transition...", 0, 0, DO_Distributions_to_Transition_adj);
	praat_addAction2 (classDistributions, 2, classTransition, 1, "To Transition (noise)...", 0, 0, DO_Distributions_to_Transition_noise_adj);
	praat_addAction2 (classDurationTier, 1, classSound, 1, "Edit", 0, 0, DO_DurationTier_edit);
	praat_addAction2 (classFormant, 1, classPointProcess, 1, "To FormantTier", 0, 0, DO_Formant_PointProcess_to_FormantTier);
	praat_addAction2 (classFormant, 1, classSound, 1, "Filter", 0, 0, DO_Sound_Formant_filter);
	praat_addAction2 (classFormant, 1, classSound, 1, "Filter (no scale)", 0, 0, DO_Sound_Formant_filter_noscale);
	praat_addAction2 (classFormantTier, 1, classSound, 1, "Filter", 0, 0, DO_Sound_FormantTier_filter);
	praat_addAction2 (classFormantTier, 1, classSound, 1, "Filter (no scale)", 0, 0, DO_Sound_FormantTier_filter_noscale);
	praat_addAction2 (classIntensity, 1, classPitch, 1, "Draw", 0, 0, 0);
	praat_addAction2 (classIntensity, 1, classPitch, 1, "Draw (phonetogram)...", 0, 0, DO_Pitch_Intensity_draw);
	praat_addAction2 (classIntensity, 1, classPitch, 1, "Speckle (phonetogram)...", 0, praat_HIDDEN, DO_Pitch_Intensity_speckle);   /* grandfathered 2005 */
	praat_addAction2 (classIntensity, 1, classPointProcess, 1, "To IntensityTier", 0, 0, DO_Intensity_PointProcess_to_IntensityTier);
	praat_addAction2 (classIntensityTier, 1, classPointProcess, 1, "To IntensityTier", 0, 0, DO_IntensityTier_PointProcess_to_IntensityTier);
	praat_addAction2 (classIntensityTier, 1, classSound, 1, "Edit", 0, 0, DO_IntensityTier_edit);
	praat_addAction2 (classIntensityTier, 1, classSound, 1, "Multiply", 0, praat_HIDDEN, DO_Sound_IntensityTier_multiply_old);
	praat_addAction2 (classIntensityTier, 1, classSound, 1, "Multiply...", 0, 0, DO_Sound_IntensityTier_multiply);
	praat_addAction2 (classManipulation, 1, classSound, 1, "Replace original sound", 0, 0, DO_Manipulation_replaceOriginalSound);
	praat_addAction2 (classManipulation, 1, classPointProcess, 1, "Replace pulses", 0, 0, DO_Manipulation_replacePulses);
	praat_addAction2 (classManipulation, 1, classPitchTier, 1, "Replace pitch tier", 0, 0, DO_Manipulation_replacePitchTier);
	praat_addAction2 (classManipulation, 1, classDurationTier, 1, "Replace duration tier", 0, 0, DO_Manipulation_replaceDurationTier);
	praat_addAction2 (classManipulation, 1, classTextTier, 1, "To Manipulation", 0, 0, DO_Manipulation_TextTier_to_Manipulation);
	praat_addAction2 (classMatrix, 1, classSound, 1, "To ParamCurve", 0, 0, DO_Matrix_to_ParamCurve);
	praat_addAction2 (classPairDistribution, 1, classDistributions, 1, "Get fraction correct...", 0, 0, DO_PairDistribution_Distributions_getFractionCorrect);
	praat_addAction2 (classPitch, 1, classPitchTier, 1, "Draw...", 0, 0, DO_PitchTier_Pitch_draw);
	praat_addAction2 (classPitch, 1, classPitchTier, 1, "To Pitch", 0, 0, DO_Pitch_PitchTier_to_Pitch);
	praat_addAction2 (classPitch, 1, classPointProcess, 1, "To PitchTier", 0, 0, DO_Pitch_PointProcess_to_PitchTier);
	praat_addAction3 (classPitch, 1, classPointProcess, 1, classSound, 1, "Voice report...", 0, 0, DO_Sound_Pitch_PointProcess_voiceReport);
	praat_addAction2 (classPitch, 1, classSound, 1, "To PointProcess (cc)", 0, 0, DO_Sound_Pitch_to_PointProcess_cc);
	praat_addAction2 (classPitch, 1, classSound, 1, "To PointProcess (peaks)...", 0, 0, DO_Sound_Pitch_to_PointProcess_peaks);
	praat_addAction2 (classPitch, 1, classSound, 1, "To Manipulation", 0, 0, DO_Sound_Pitch_to_Manipulation);
	praat_addAction2 (classPitchTier, 1, classPointProcess, 1, "To PitchTier", 0, 0, DO_PitchTier_PointProcess_to_PitchTier);
	praat_addAction2 (classPitchTier, 1, classSound, 1, "Edit", 0, 0, DO_PitchTier_edit);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Edit", 0, 0, DO_PointProcess_edit);
praat_addAction2 (classPointProcess, 1, classSound, 1, "Query", 0, 0, 0);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Get shimmer (local)...", 0, 0, DO_Point_Sound_getShimmer_local);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Get shimmer (local_dB)...", 0, 0, DO_Point_Sound_getShimmer_local_dB);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Get shimmer (apq3)...", 0, 0, DO_Point_Sound_getShimmer_apq3);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Get shimmer (apq5)...", 0, 0, DO_Point_Sound_getShimmer_apq5);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Get shimmer (apq11)...", 0, 0, DO_Point_Sound_getShimmer_apq11);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Get shimmer (dda)...", 0, 0, DO_Point_Sound_getShimmer_dda);
praat_addAction2 (classPointProcess, 1, classSound, 1, "Modify", 0, 0, 0);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "Transplant time domain", 0, 0, DO_Point_Sound_transplantDomain);
praat_addAction2 (classPointProcess, 1, classSound, 1, "Analyse", 0, 0, 0);
	/*praat_addAction2 (classPointProcess, 1, classSound, 1, "To Manipulation", 0, 0, DO_Sound_PointProcess_to_Manipulation);*/
	praat_addAction2 (classPointProcess, 1, classSound, 1, "To AmplitudeTier (point)", 0, 0, DO_PointProcess_Sound_to_AmplitudeTier_point);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "To AmplitudeTier (period)...", 0, 0, DO_PointProcess_Sound_to_AmplitudeTier_period);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "To Ltas...", 0, 0, DO_PointProcess_Sound_to_Ltas);
	praat_addAction2 (classPointProcess, 1, classSound, 1, "To Ltas (only harmonics)...", 0, 0, DO_PointProcess_Sound_to_Ltas_harmonics);

	praat_addAction4 (classDurationTier, 1, classPitchTier, 1, classPointProcess, 1, classSound, 1, "To Sound...", 0, 0, DO_Sound_Point_Pitch_Duration_to_Sound);

	INCLUDE_MANPAGES (manual_Manual_init)
	INCLUDE_MANPAGES (manual_Script_init)
	INCLUDE_MANPAGES (manual_Picture_init)

	INCLUDE_MANPAGES (manual_Fon_init)
	INCLUDE_MANPAGES (manual_tutorials_init)
	INCLUDE_MANPAGES (manual_glossary_init)
	INCLUDE_MANPAGES (manual_references_init)
	INCLUDE_MANPAGES (manual_soundFiles_init)
	INCLUDE_MANPAGES (manual_statistics_init)
	INCLUDE_MANPAGES (manual_voice_init)
	INCLUDE_MANPAGES (manual_programming_init)
	INCLUDE_MANPAGES (manual_OT_init)
	INCLUDE_MANPAGES (manual_Exp_init)

	INCLUDE_LIBRARY (praat_uvafon_OT_init)
	INCLUDE_LIBRARY (praat_uvafon_Artsynth_init)
	INCLUDE_LIBRARY (praat_uvafon_David_init)
	INCLUDE_LIBRARY (praat_uvafon_FFNet_init)
	INCLUDE_LIBRARY (praat_uvafon_LPC_init)
	INCLUDE_LIBRARY (praat_uvafon_Stat_init)
	INCLUDE_LIBRARY (praat_uvafon_Exp_init)
}

/* End of file praat_Fon.c */
