[med-svn] [praat] 01/08: New upstream version 6.0.23

Rafael Laboissiere rafael at debian.org
Sat Jan 14 23:46:44 UTC 2017


This is an automated email from the git hooks/post-receive script.

rafael pushed a commit to branch master
in repository praat.

commit 6b42da16aaa85432d107908702c7771542aa69a7
Author: Rafael Laboissiere <rafael at debian.org>
Date:   Sat Jan 14 16:46:49 2017 -0200

    New upstream version 6.0.23
---
 EEG/praat_EEG.cpp                                  |  1266 +-
 FFNet/FFNet.cpp                                    |    40 +
 FFNet/FFNet.h                                      |     9 +-
 artsynth/Speaker.h => FFNet/praat_FFNet.h          |    29 +-
 FFNet/praat_FFNet_init.cpp                         |  1074 +-
 LPC/Cepstrogram.cpp                                |     4 +-
 LPC/Cepstrogram.h                                  |     2 +-
 LPC/Cepstrum.cpp                                   |    18 +-
 LPC/LPC_and_LineSpectralFrequencies.cpp            |     4 +-
 LPC/LPC_and_LineSpectralFrequencies.h              |     2 +-
 LPC/LPC_and_Polynomial.cpp                         |     8 +-
 LPC/LineSpectralFrequencies.cpp                    |     2 +-
 LPC/manual_LPC.cpp                                 |     5 +
 LPC/praat_LPC_init.cpp                             |  1982 +-
 artsynth/Artword.cpp                               |     4 +-
 artsynth/Artword.h                                 |     4 +-
 artsynth/Speaker.cpp                               |     4 +-
 artsynth/Speaker.h                                 |     4 +-
 artsynth/praat_Artsynth.cpp                        |   513 +-
 contrib/ola/Makefile                               |     6 +-
 contrib/ola/praat_contrib_Ola_KNN.cpp              |  1290 +-
 dwsys/Eigen.cpp                                    |     2 +-
 dwsys/Index.cpp                                    |    59 +-
 dwsys/Index.h                                      |    22 +-
 dwsys/Index_def.h                                  |     4 +-
 dwsys/Makefile                                     |     2 +-
 dwsys/NUMstring.cpp                                |    20 +-
 dwsys/Permutation_and_Index.cpp                    |     6 +-
 dwtest/old_type.MelFilter                          | 29349 +++++++++++++++++++
 dwtest/polynomial_formatVersion0.Polynomial        |    11 +
 dwtest/test_DataModeler.praat                      |   101 +
 dwtest/test_Eigen.praat                            |    50 +
 dwtest/test_FFNet.praat                            |    65 +
 dwtest/test_KlattGrid.praat                        |     6 +-
 dwtest/test_LPC.praat                              |    78 +-
 dwtest/test_MDS.praat                              |   357 +-
 dwtest/test_angle_between_planes.praat             |     9 +-
 dwtest/test_spectrogramTypes.praat                 |    82 +
 dwtools/ActivationList.cpp                         |     2 +-
 dwtools/ClassificationTable.cpp                    |     2 +-
 dwtools/Confusion.cpp                              |    16 +-
 dwtools/DTW.cpp                                    |     1 -
 dwtools/DTW.h                                      |     2 +
 dwtools/DataModeler.cpp                            |    74 +-
 dwtools/DataModeler.h                              |    17 +-
 dwtools/Excitations.cpp                            |    64 +-
 dwtools/Excitations.h                              |    11 +-
 dwtools/HMM.cpp                                    |     6 +-
 dwtools/ICA.cpp                                    |    23 +
 dwtools/ICA.h                                      |     3 +-
 dwtools/LongSound_extensions.cpp                   |     2 +-
 dwtools/MDS.cpp                                    |   170 +-
 dwtools/MDS.h                                      |    87 +-
 dwtools/OptimalCeilingTierEditor.h                 |     2 +-
 dwtools/PCA.cpp                                    |    11 +
 dwtools/PCA.h                                      |     2 +
 dwtools/Polygon_extensions.cpp                     |     2 +-
 dwtools/Polygon_extensions.h                       |     4 +-
 dwtools/Polynomial_def.h                           |     4 +-
 dwtools/SpeechSynthesizer.cpp                      |     3 +-
 dwtools/Strings_extensions.cpp                     |     2 +-
 dwtools/TableOfReal_extensions.cpp                 |    10 +-
 dwtools/TableOfReal_extensions.h                   |     6 +-
 dwtools/Table_extensions.cpp                       |    10 +-
 dwtools/Table_extensions.h                         |    10 +-
 dwtools/TextGrid_extensions.cpp                    |    12 +-
 dwtools/VowelEditor.cpp                            |     6 +-
 dwtools/manual_dwtools.cpp                         |    47 +-
 dwtools/praat_BSS_init.cpp                         |   814 +-
 dwtools/praat_DataModeler_init.cpp                 |  1949 +-
 dwtools/praat_David_init.cpp                       | 12932 ++++----
 dwtools/praat_HMM_init.cpp                         |  1433 +-
 dwtools/praat_KlattGrid_init.cpp                   |  1406 +-
 dwtools/praat_MDS_init.cpp                         |  2663 +-
 external/espeak/READ_ME.TXT                        |     3 +
 external/espeak/synthdata.cpp                      |     4 +-
 external/espeak/voices.cpp                         |    34 +-
 external/gsl/gsl__config.h                         |     4 +-
 external/gsl/gsl_eigen__gen.c                      |     2 +-
 external/gsl/gsl_eigen__genherm.c                  |     2 +-
 external/gsl/gsl_eigen__genhermv.c                 |     2 +-
 external/gsl/gsl_eigen__gensymm.c                  |     2 +-
 external/gsl/gsl_eigen__gensymmv.c                 |     2 +-
 external/gsl/gsl_eigen__genv.c                     |     2 +-
 fon/AmplitudeTier.cpp                              |    10 +-
 fon/ExperimentMFC.cpp                              |     2 +-
 fon/Formant.cpp                                    |     9 +-
 fon/FormantGridEditor.cpp                          |     4 +-
 fon/FunctionEditor.cpp                             |    10 +-
 fon/Harmonicity.cpp                                |    14 +-
 fon/LongSound.cpp                                  |     4 +-
 fon/LongSound.h                                    |     6 +-
 fon/Makefile                                       |     7 +-
 fon/ManipulationEditor.cpp                         |     6 +-
 fon/ParamCurve.cpp                                 |    24 +-
 fon/PointEditor.cpp                                |     2 +-
 fon/PointProcess.cpp                               |    10 +-
 fon/Praat_tests.cpp                                |    66 +
 fon/RealTier.cpp                                   |     2 +-
 fon/RealTier.h                                     |     4 +-
 fon/RealTierEditor.cpp                             |     8 +-
 fon/RealTier_def.h                                 |    13 +-
 fon/Sampled.cpp                                    |     2 +-
 fon/Sound.cpp                                      |    19 +-
 fon/Sound.h                                        |    14 +-
 fon/SoundRecorder.cpp                              |    22 +-
 fon/SoundRecorder.h                                |    12 +-
 fon/Sound_audio.cpp                                |    27 +-
 fon/Sound_files.cpp                                |    12 +-
 fon/TextGrid.cpp                                   |     8 +-
 fon/TextGrid.h                                     |     4 +-
 fon/TextGridEditor.cpp                             |    20 +-
 fon/TimeSoundAnalysisEditor.cpp                    |    42 +-
 fon/TimeSoundEditor.cpp                            |    36 +-
 fon/{manual_Exp.cpp => manual_ExperimentMFC.cpp}   |    10 +-
 fon/manual_Script.cpp                              |    23 +-
 fon/manual_sound.cpp                               |    16 +-
 fon/manual_tutorials.cpp                           |    16 +-
 fon/praat_Exp.cpp                                  |   170 -
 fon/praat_ExperimentMFC.cpp                        |   158 +
 sys/InfoEditor.h => fon/praat_ExperimentMFC.h      |    29 +-
 fon/praat_Fon.cpp                                  |  8974 ++----
 fon/praat_Matrix.cpp                               |   927 +
 artsynth/Speaker.h => fon/praat_Matrix.h           |    30 +-
 fon/praat_Sound.cpp                                |  2407 ++
 sys/InfoEditor.h => fon/praat_Sound.h              |    29 +-
 fon/praat_Sound_init.cpp                           |  2738 --
 fon/praat_TextGrid_init.cpp                        |  2966 +-
 fon/praat_Tiers.cpp                                |  1890 ++
 artsynth/Speaker.h => fon/praat_Tiers.h            |    29 +-
 fon/praat_TimeFrameSampled.cpp                     |    68 +
 sys/InfoEditor.h => fon/praat_TimeFrameSampled.h   |    24 +-
 fon/praat_TimeFunction.cpp                         |   115 +
 fon/praat_TimeFunction.h                           |    42 +
 fon/praat_TimeTier.cpp                             |   116 +
 artsynth/Speaker.h => fon/praat_TimeTier.h         |    27 +-
 fon/praat_TimeVector.h                             |    51 +
 sys/InfoEditor.h => fon/praat_uvafon.h             |    24 +-
 gram/Network.cpp                                   |    10 +-
 gram/OTGrammar.cpp                                 |    10 +-
 gram/OTGrammar.h                                   |     8 +-
 gram/OTGrammar_def.h                               |     2 +-
 gram/manual_gram.cpp                               |     7 +-
 gram/praat_gram.cpp                                |  3255 +-
 kar/longchar.cpp                                   |    18 +-
 kar/longchar.h                                     |     3 +-
 main/{praat_cocoa.plist => praat.plist}            |     0
 makefile                                           |     7 +-
 makefiles/makefile.defs.linux.barren               |     4 +-
 makefiles/makefile.defs.linux.pulse                |     4 +-
 stat/Makefile                                      |     5 +-
 stat/Regression_def.h                              |     3 +-
 stat/Table_def.h                                   |     9 +-
 stat/praat_Stat.cpp                                |  2490 +-
 stat/praat_TableOfReal.cpp                         |   553 +
 sys/InfoEditor.h => stat/praat_TableOfReal.h       |    31 +-
 sys/Collection.cpp                                 |    14 +-
 sys/Collection.h                                   |     4 +-
 sys/DataEditor.cpp                                 |     4 +-
 sys/DemoEditor.cpp                                 |     2 +-
 sys/EditorM.h                                      |    17 +-
 sys/Formula.cpp                                    |    86 +-
 sys/Gui.h                                          |     6 +-
 sys/GuiButton.cpp                                  |     3 +-
 sys/GuiMenu.cpp                                    |     2 +
 sys/InfoEditor.cpp                                 |    33 +-
 sys/InfoEditor.h                                   |     4 +-
 sys/Makefile                                       |     7 +-
 sys/Manual.cpp                                     |     4 +-
 sys/MelderGui.cpp                                  |   379 +
 sys/Strings.cpp                                    |    18 +-
 sys/TextEditor.cpp                                 |    67 +-
 sys/TextEditor.h                                   |     4 +-
 sys/Thing.cpp                                      |     6 +-
 sys/Thing.h                                        |    22 +-
 sys/Ui.cpp                                         |   297 +-
 sys/Ui.h                                           |    34 +-
 sys/melder.cpp                                     |   375 +-
 sys/melder.h                                       |     6 +-
 sys/melder_audio.cpp                               |   212 +-
 sys/melder_audiofiles.cpp                          |     2 +-
 sys/melder_debug.cpp                               |     2 +-
 sys/melder_info.cpp                                |    11 +-
 sys/praat.cpp                                      |    80 +-
 sys/praat.h                                        |   513 +-
 sys/praatP.h                                       |    29 +-
 sys/praat_actions.cpp                              |    39 +-
 sys/praat_library.cpp                              |    54 +
 sys/praat_menuCommands.cpp                         |   105 +-
 sys/praat_objectMenus.cpp                          |   531 +-
 sys/praat_picture.cpp                              |  1576 +-
 sys/praat_statistics.cpp                           |     2 +-
 sys/praat_version.h                                |     8 +-
 test/contrib/kNN.praat                             |     8 +-
 .../Sounds/M1F1-float32-AFsp.wav                   |   Bin
 .../Sounds/again.wav                               |   Bin
 .../{fon Exp => fon ExperimentMFC}/Sounds/heed.wav |   Bin
 test/{fon Exp => fon ExperimentMFC}/Sounds/hid.wav |   Bin
 .../{fon Exp => fon ExperimentMFC}/Sounds/hood.wav |   Bin
 test/{fon Exp => fon ExperimentMFC}/Sounds/hud.wav |   Bin
 .../Sounds/weSayTheWord.wav                        |   Bin
 .../continuousGoodness.ExperimentMFC               |     0
 .../csl.ExperimentMFC                              |     0
 .../experimentMFC.praat                            |     0
 .../hoofdletters.ExperimentMFC                     |     0
 .../pictures.ExperimentMFC                         |     0
 .../pictures/paul.jpg                              |   Bin
 .../pictures/silke.jpg                             |   Bin
 .../simplest.ExperimentMFC                         |     0
 .../simplest_broken.ExperimentMFC                  |     0
 .../simplest_missing.ExperimentMFC                 |     0
 .../stereo.ExperimentMFC                           |     0
 .../test.ExperimentMFC                             |     0
 .../version3.ExperimentMFC                         |     0
 .../version4.ExperimentMFC                         |     0
 .../version6.ExperimentMFC                         |     0
 216 files changed, 58458 insertions(+), 32183 deletions(-)

diff --git a/EEG/praat_EEG.cpp b/EEG/praat_EEG.cpp
index b169f22..e32961d 100644
--- a/EEG/praat_EEG.cpp
+++ b/EEG/praat_EEG.cpp
@@ -16,293 +16,300 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "praat.h"
-
 #include "EEGWindow.h"
 #include "ERPWindow.h"
 #include "ERPTier.h"
 #include "SpectrumEditor.h"
 
-#undef iam
-#define iam iam_LOOP
+#include "praat_TimeTier.h"
 
-/***** EEG *****/
+// MARK: - EEG
 
-DIRECT2 (EEGs_concatenate) {
-	OrderedOf<structEEG> eegs;
-	LOOP {
-		iam (EEG);
-		eegs. addItem_ref (me);
-	}
-	autoEEG thee = EEGs_concatenate (& eegs);
-	praat_new (thee.move(), U"chain");
-END2 }
+// MARK: Help
 
-DIRECT2 (EEG_detrend) {
-	LOOP {
-		iam (EEG);
-		EEG_detrend (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (EEG_editExternalElectrodeNames, U"Edit external electrode names", nullptr) {
-	WORD (U"External electrode 1", U"EXG1")
-	WORD (U"External electrode 2", U"EXG2")
-	WORD (U"External electrode 3", U"EXG3")
-	WORD (U"External electrode 4", U"EXG4")
-	WORD (U"External electrode 5", U"EXG5")
-	WORD (U"External electrode 6", U"EXG6")
-	WORD (U"External electrode 7", U"EXG7")
-	WORD (U"External electrode 8", U"EXG8")
-	OK2
-int IOBJECT;
-LOOP {
-	iam (EEG);
-	if (EEG_getNumberOfExternalElectrodes (me) == 8) {
-		const long offsetExternalElectrode = EEG_getNumberOfCapElectrodes (me);
-		SET_STRING (U"External electrode 1", my channelNames [offsetExternalElectrode + 1])
-		SET_STRING (U"External electrode 2", my channelNames [offsetExternalElectrode + 2])
-		SET_STRING (U"External electrode 3", my channelNames [offsetExternalElectrode + 3])
-		SET_STRING (U"External electrode 4", my channelNames [offsetExternalElectrode + 4])
-		SET_STRING (U"External electrode 5", my channelNames [offsetExternalElectrode + 5])
-		SET_STRING (U"External electrode 6", my channelNames [offsetExternalElectrode + 6])
-		SET_STRING (U"External electrode 7", my channelNames [offsetExternalElectrode + 7])
-		SET_STRING (U"External electrode 8", my channelNames [offsetExternalElectrode + 8])
-	}
+DIRECT (HELP_EEG_help) {
+	HELP (U"EEG")
 }
-DO
-	LOOP {
-		iam (EEG);
-		if (EEG_getNumberOfExternalElectrodes (me) != 8)
-			Melder_throw (U"You can do this only if there are 8 external electrodes.");
-		EEG_setExternalElectrodeNames (me, GET_STRING (U"External electrode 1"), GET_STRING (U"External electrode 2"), GET_STRING (U"External electrode 3"),
-			GET_STRING (U"External electrode 4"), GET_STRING (U"External electrode 5"), GET_STRING (U"External electrode 6"),
-			GET_STRING (U"External electrode 7"), GET_STRING (U"External electrode 8"));
-		praat_dataChanged (me);
-	}
-END2 }
 
-FORM (EEG_extractChannel, U"EEG: Extract channel", nullptr) {
-	SENTENCE (U"Channel name", U"Cz")
-	OK2
-DO
-	LOOP {
-		iam (EEG);
-		const char32 *channelName = GET_STRING (U"Channel name");
-		autoEEG thee = EEG_extractChannel (me, channelName);
-		praat_new (thee.move(), my name, U"_", channelName);
-	}
-END2 }
+// MARK: View & Edit
 
-FORM (EEG_extractPart, U"EEG: Extract part", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1.0")
-	BOOLEAN (U"Preserve times", false)
-	OK2
-DO
-	LOOP {
-		iam (EEG);
-		autoEEG thee = EEG_extractPart (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Preserve times"));
-		praat_new (thee.move(), my name, U"_part");
-	}
-END2 }
-
-DIRECT2 (EEG_extractSound) {
-	LOOP {
-		iam (EEG);
-		if (! my sound) Melder_throw (me, U": I don't contain a waveform.");
-		autoSound thee = EEG_extractSound (me);
-		praat_new (thee.move());
+static void cb_EEGWindow_publication (Editor /* editor */, autoDaata publication) {
+	/*
+	 * Keep the gate for error handling.
+	 */
+	try {
+		bool isaSpectralSlice = Thing_isa (publication.get(), classSpectrum) && str32equ (Thing_getName (publication.get()), U"slice");
+		praat_new (publication.move());
+		praat_updateSelection ();
+		if (isaSpectralSlice) {
+			int IOBJECT;
+			LOOP {
+				iam_LOOP (Spectrum);
+				autoSpectrumEditor editor2 = SpectrumEditor_create (ID_AND_FULL_NAME, me);
+				praat_installEditor (editor2.get(), IOBJECT);
+				editor2.releaseToUser();
+			}
+		}
+	} catch (MelderError) {
+		Melder_flushError ();
 	}
-END2 }
-
-DIRECT2 (EEG_extractTextGrid) {
+}
+DIRECT (WINDOW_EEG_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an EEG from batch.");
 	LOOP {
-		iam (EEG);
-		if (! my textgrid) Melder_throw (me, U": I don't contain marks.");
-		autoTextGrid thee = EEG_extractTextGrid (me);
-		praat_new (thee.move());
+		iam_LOOP (EEG);
+		autoEEGWindow editor = EEGWindow_create (ID_AND_FULL_NAME, me);
+		Editor_setPublicationCallback (editor.get(), cb_EEGWindow_publication);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM (EEG_filter, U"Filter", nullptr) {
-	REAL (U"Low frequency (Hz)", U"1.0")
-	REAL (U"Low width (Hz)", U"0.5")
-	REAL (U"High frequency (Hz)", U"25.0")
-	REAL (U"High width (Hz)", U"12.5")
-	BOOLEAN (U"Notch at 50 Hz", true)
-	OK2
-DO
-	LOOP {
-		iam (EEG);
-		EEG_filter (me, GET_REAL (U"Low frequency"), GET_REAL (U"Low width"), GET_REAL (U"High frequency"), GET_REAL (U"High width"), GET_INTEGER (U"Notch at 50 Hz"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: Query
 
-FORM (EEG_getChannelName, U"Get channel name", nullptr) {
-	NATURAL (U"Channel number", U"1")
-	OK2
+FORM (STRING_EEG_getChannelName, U"Get channel name", nullptr) {
+	NATURALVAR (channelNumber, U"Channel number", U"1")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		long channelNumber = GET_INTEGER (U"Channel number");
+	STRING_ONE (EEG)
 		if (channelNumber > my numberOfChannels)
 			Melder_throw (me, U": there are only ", my numberOfChannels, U" channels.");
-		Melder_information (my channelNames [channelNumber]);
-	}
-END2 }
+		const char32 *result = my channelNames [channelNumber];
+	STRING_ONE_END
+}
 
-FORM (EEG_getChannelNumber, U"Get channel number", nullptr) {
-	WORD (U"Channel name", U"Cz")
-	OK2
+FORM (INTEGER_EEG_getChannelNumber, U"Get channel number", nullptr) {
+	WORDVAR (channelName, U"Channel name", U"Cz")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		Melder_information (EEG_getChannelNumber (me, GET_STRING (U"Channel name")));
-	}
-END2 }
+	NUMBER_ONE (EEG)
+		long result = EEG_getChannelNumber (me, channelName);
+	NUMBER_ONE_END (U"")
+}
+
+// MARK: Modify
 
-FORM (EEG_removeTriggers, U"Remove triggers", nullptr) {
-	OPTIONMENU_ENUM (U"Remove every trigger that...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+DIRECT (MODIFY_EEG_detrend) {
+	MODIFY_EACH (EEG)
+		EEG_detrend (me);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_EEG_editExternalElectrodeNames, U"Edit external electrode names", nullptr) {
+	WORD4 (externalElectrode1, U"External electrode 1", U"EXG1")
+	WORD4 (externalElectrode2, U"External electrode 2", U"EXG2")
+	WORD4 (externalElectrode3, U"External electrode 3", U"EXG3")
+	WORD4 (externalElectrode4, U"External electrode 4", U"EXG4")
+	WORD4 (externalElectrode5, U"External electrode 5", U"EXG5")
+	WORD4 (externalElectrode6, U"External electrode 6", U"EXG6")
+	WORD4 (externalElectrode7, U"External electrode 7", U"EXG7")
+	WORD4 (externalElectrode8, U"External electrode 8", U"EXG8")
+OK
+	FIND_ONE (EEG)
+		if (EEG_getNumberOfExternalElectrodes (me) == 8) {
+			const long offsetExternalElectrode = EEG_getNumberOfCapElectrodes (me);
+			SET_STRING (U"External electrode 1", my channelNames [offsetExternalElectrode + 1])
+			SET_STRING (U"External electrode 2", my channelNames [offsetExternalElectrode + 2])
+			SET_STRING (U"External electrode 3", my channelNames [offsetExternalElectrode + 3])
+			SET_STRING (U"External electrode 4", my channelNames [offsetExternalElectrode + 4])
+			SET_STRING (U"External electrode 5", my channelNames [offsetExternalElectrode + 5])
+			SET_STRING (U"External electrode 6", my channelNames [offsetExternalElectrode + 6])
+			SET_STRING (U"External electrode 7", my channelNames [offsetExternalElectrode + 7])
+			SET_STRING (U"External electrode 8", my channelNames [offsetExternalElectrode + 8])
+		}
 DO
-	LOOP {
-		iam (EEG);
-		EEG_removeTriggers (me, GET_ENUM (kMelder_string, U"Remove every trigger that..."), GET_STRING (U"...the text"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (EEG)
+		if (EEG_getNumberOfExternalElectrodes (me) != 8)
+			Melder_throw (U"You can do this only if there are 8 external electrodes.");
+		EEG_setExternalElectrodeNames (me, externalElectrode1, externalElectrode2, externalElectrode3,
+			externalElectrode4, externalElectrode5, externalElectrode6,
+			externalElectrode7, externalElectrode8);
+	MODIFY_EACH_END
+}
 
-FORM (EEG_setChannelName, U"Set channel name", nullptr) {
-	NATURAL (U"Channel number", U"1")
-	WORD (U"New name", U"BLA")
-	OK2
+FORM (MODIFY_EEG_removeTriggers, U"Remove triggers", nullptr) {
+	OPTIONMENU_ENUM4 (removeEveryTriggerThat___, U"Remove every trigger that...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		EEG_setChannelName (me, GET_INTEGER (U"Channel number"), GET_STRING (U"New name"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (EEG)
+		EEG_removeTriggers (me, removeEveryTriggerThat___, ___theText);
+	MODIFY_EACH_END
+}
 
-FORM (EEG_setChannelToZero, U"Set channel to zero", nullptr) {
+FORM (MODIFY_EEG_setChannelName, U"Set channel name", nullptr) {
+	NATURALVAR (channelNumber, U"Channel number", U"1")
+	WORDVAR (newName, U"New name", U"BLA")
+	OK
+DO
+	MODIFY_EACH (EEG)
+		EEG_setChannelName (me, channelNumber, newName);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_EEG_setChannelToZero, U"Set channel to zero", nullptr) {
 	SENTENCE (U"Channel", U"Iz")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (EEG);
+	MODIFY_EACH (EEG)
 		EEG_setChannelToZero (me, GET_STRING (U"Channel"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (EEG_subtractMeanChannel, U"Subtract mean channel", nullptr) {
+FORM (MODIFY_EEG_subtractMeanChannel, U"Subtract mean channel", nullptr) {
 	LABEL (U"label", U"Range of reference channels:")
-	NATURAL (U"From channel", U"1")
-	NATURAL (U"To channel", U"32")
-	OK2
+	NATURALVAR (fromChannel, U"From channel", U"1")
+	NATURALVAR (toChannel, U"To channel", U"32")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		EEG_subtractMeanChannel (me, GET_INTEGER (U"From channel"), GET_INTEGER (U"To channel"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (EEG)
+		EEG_subtractMeanChannel (me, fromChannel, toChannel);
+	MODIFY_EACH_END
+}
 
-FORM (EEG_subtractReference, U"Subtract reference", nullptr) {
-	WORD (U"Reference channel 1", U"MASL")
-	WORD (U"Reference channel 2 (optional)", U"MASR")
-	OK2
+FORM (MODIFY_EEG_subtractReference, U"Subtract reference", nullptr) {
+	WORDVAR (referenceChannel1, U"Reference channel 1", U"MASL")
+	WORDVAR (referenceChannel2, U"Reference channel 2 (optional)", U"MASR")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		EEG_subtractReference (me, GET_STRING (U"Reference channel 1"), GET_STRING (U"Reference channel 2"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (EEG)
+		EEG_subtractReference (me, referenceChannel1, referenceChannel2);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_EEG_filter, U"Filter", nullptr) {
+	REALVAR (lowFrequency, U"Low frequency (Hz)", U"1.0")
+	REALVAR (lowWidth, U"Low width (Hz)", U"0.5")
+	REALVAR (highFrequency, U"High frequency (Hz)", U"25.0")
+	REALVAR (highWidth, U"High width (Hz)", U"12.5")
+	BOOLEANVAR (notchAt50Hz, U"Notch at 50 Hz", true)
+	OK
+DO
+	MODIFY_EACH (EEG)
+		EEG_filter (me, lowFrequency, lowWidth, highFrequency, highWidth, notchAt50Hz);
+	MODIFY_EACH_END
+}
+
+// MARK: Extract
 
-FORM (EEG_to_ERPTier_bit, U"To ERPTier (bit)", nullptr) {
-	REAL (U"From time (s)", U"-0.11")
-	REAL (U"To time (s)", U"0.39")
-	NATURAL (U"Marker bit", U"8")
-	OK2
+FORM (NEW_EEG_extractChannel, U"EEG: Extract channel", nullptr) {
+	SENTENCEVAR (channelName, U"Channel name", U"Cz")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		int markerBit = GET_INTEGER (U"Marker bit");
-		autoERPTier thee = EEG_to_ERPTier_bit (me, GET_REAL (U"From time"), GET_REAL (U"To time"), markerBit);
-		praat_new (thee.move(), my name, U"_bit", markerBit);
-	}
-END2 }
+	CONVERT_EACH (EEG)
+		autoEEG result = EEG_extractChannel (me, channelName);
+	CONVERT_EACH_END (my name, U"_", channelName)
+}
 
-FORM (EEG_to_ERPTier_marker, U"To ERPTier (marker)", nullptr) {
-	REAL (U"From time (s)", U"-0.11")
-	REAL (U"To time (s)", U"0.39")
-	NATURAL (U"Marker number", U"12")
-	OK2
+FORM (NEW_EEG_extractPart, U"EEG: Extract part", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"1.0")
+	BOOLEANVAR (preserveTimes, U"Preserve times", false)
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		uint16 markerNumber = GET_INTEGER (U"Marker number");
-		autoERPTier thee = EEG_to_ERPTier_marker (me, GET_REAL (U"From time"), GET_REAL (U"To time"), markerNumber);
-		praat_new (thee.move(), my name, U"_", markerNumber);
-	}
-END2 }
+	CONVERT_EACH (EEG)
+		autoEEG result = EEG_extractPart (me, fromTime, toTime, preserveTimes);
+	CONVERT_EACH_END (my name, U"_part")
+}
 
-FORM (EEG_to_ERPTier_triggers, U"To ERPTier (triggers)", nullptr) {
-	REAL (U"From time (s)", U"-0.11")
-	REAL (U"To time (s)", U"0.39")
-	OPTIONMENU_ENUM (U"Get every event with a trigger that", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"1")
-	OK2
+DIRECT (NEW_EEG_extractSound) {
+	CONVERT_EACH (EEG)
+		if (! my sound) Melder_throw (me, U": I don't contain a waveform.");
+		autoSound result = EEG_extractSound (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_EEG_extractTextGrid) {
+	CONVERT_EACH (EEG)
+		if (! my textgrid) Melder_throw (me, U": I don't contain marks.");
+		autoTextGrid result = EEG_extractTextGrid (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_EEG_to_ERPTier_bit, U"To ERPTier (bit)", nullptr) {
+	REALVAR (fromTime, U"From time (s)", U"-0.11")
+	REALVAR (toTime, U"To time (s)", U"0.39")
+	NATURALVAR (markerBit, U"Marker bit", U"8")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		autoERPTier thee = EEG_to_ERPTier_triggers (me, GET_REAL (U"From time"), GET_REAL (U"To time"),
-			GET_ENUM (kMelder_string, U"Get every event with a trigger that"), GET_STRING (U"...the text"));
-		praat_new (thee.move(), my name, U"_trigger", GET_STRING (U"...the text"));
-	}
-END2 }
+	CONVERT_EACH (EEG)
+		autoERPTier result = EEG_to_ERPTier_bit (me, fromTime, toTime, markerBit);
+	CONVERT_EACH_END (my name, U"_bit", markerBit)
+}
 
-FORM (EEG_to_ERPTier_triggers_preceded, U"To ERPTier (triggers, preceded)", nullptr) {
-	REAL (U"From time (s)", U"-0.11")
-	REAL (U"To time (s)", U"0.39")
-	OPTIONMENU_ENUM (U"Get every event with a trigger that", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"1")
-	OPTIONMENU_ENUM (U"and is preceded by a trigger that", kMelder_string, DEFAULT)
-	SENTENCE (U" ...the text", U"4")
-	OK2
+FORM (NEW_EEG_to_ERPTier_marker, U"To ERPTier (marker)", nullptr) {
+	REALVAR (fromTime, U"From time (s)", U"-0.11")
+	REALVAR (toTime, U"To time (s)", U"0.39")
+	NATURALVAR (markerNumber, U"Marker number", U"12")
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		autoERPTier thee = EEG_to_ERPTier_triggers_preceded (me, GET_REAL (U"From time"), GET_REAL (U"To time"),
-			GET_ENUM (kMelder_string, U"Get every event with a trigger that"), GET_STRING (U"...the text"),
-			GET_ENUM (kMelder_string, U"and is preceded by a trigger that"), GET_STRING (U" ...the text"));
-		praat_new (thee.move(), my name, U"_trigger", GET_STRING (U" ...the text"));
-	}
-END2 }
+	CONVERT_EACH (EEG)
+		autoERPTier result = EEG_to_ERPTier_marker (me, fromTime, toTime, (uint16) markerNumber);
+	CONVERT_EACH_END (my name, U"_", markerNumber)
+}
+
+FORM (NEW_EEG_to_ERPTier_triggers, U"To ERPTier (triggers)", nullptr) {
+	REALVAR (fromTime, U"From time (s)", U"-0.11")
+	REALVAR (toTime, U"To time (s)", U"0.39")
+	OPTIONMENU_ENUMVAR (getEveryEventWithATriggerThat, U"Get every event with a trigger that", kMelder_string, DEFAULT)
+	SENTENCEVAR (theText, U"...the text", U"1")
+	OK
+DO
+	CONVERT_EACH (EEG)
+		autoERPTier result = EEG_to_ERPTier_triggers (me, fromTime, toTime, getEveryEventWithATriggerThat, theText);
+	CONVERT_EACH_END (my name, U"_trigger", theText)
+}
+
+FORM (NEW_EEG_to_ERPTier_triggers_preceded, U"To ERPTier (triggers, preceded)", nullptr) {
+	REALVAR (fromTime, U"From time (s)", U"-0.11")
+	REALVAR (toTime, U"To time (s)", U"0.39")
+	OPTIONMENU_ENUMVAR (getEveryEventWithATriggerThat, U"Get every event with a trigger that", kMelder_string, DEFAULT)
+	SENTENCEVAR (text1, U"...the text", U"1")
+	OPTIONMENU_ENUMVAR (andIsPrecededByATriggerThat, U"and is preceded by a trigger that", kMelder_string, DEFAULT)
+	SENTENCEVAR (text2, U" ...the text", U"4")
+	OK
+DO
+	CONVERT_EACH (EEG)
+		autoERPTier result = EEG_to_ERPTier_triggers_preceded (me, fromTime, toTime,
+			getEveryEventWithATriggerThat, text1, andIsPrecededByATriggerThat, text2);
+	CONVERT_EACH_END (my name, U"_trigger", text2)
+}
+
+// MARK: Convert
 
-FORM (EEG_to_MixingMatrix, U"To MixingMatrix", nullptr) {
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
+DIRECT (NEW1_EEGs_concatenate) {
+	CONVERT_LIST (EEG)
+		autoEEG result = EEGs_concatenate (& list);
+	CONVERT_LIST_END (U"chain")
+}
+
+FORM (NEW_EEG_to_MixingMatrix, U"To MixingMatrix", nullptr) {
+	NATURAL4 (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVE4 (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENU4x (diagonalizationMethod, U"Diagonalization method", 2, 1)
 		OPTION (U"qdiag")
 		OPTION (U"ffdiag")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (EEG);
-		autoMixingMatrix thee = EEG_to_MixingMatrix (me,
-			GET_INTEGER (U"Maximum number of iterations"), GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Diagonalization method"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (EEG)
+		autoMixingMatrix result = EEG_to_MixingMatrix (me,
+			maximumNumberOfIterations, tolerance, diagonalizationMethod);
+	CONVERT_EACH_END (my name)
+}
 
-static void cb_EEGWindow_publication (Editor /* editor */, autoDaata publication) {
+// MARK: - EEG & TextGrid
+
+DIRECT (MODIFY_EEG_TextGrid_replaceTextGrid) {
+	MODIFY_FIRST_OF_TWO (EEG, TextGrid)
+		EEG_replaceTextGrid (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+// MARK: - ERP
+
+// MARK: View & Edit
+
+static void cb_ERPWindow_publication (Editor /* editor */, autoDaata publication) {
 	/*
 	 * Keep the gate for error handling.
 	 */
@@ -313,7 +320,7 @@ static void cb_EEGWindow_publication (Editor /* editor */, autoDaata publication
 		if (isaSpectralSlice) {
 			int IOBJECT;
 			LOOP {
-				iam (Spectrum);
+				iam_LOOP (Spectrum);
 				autoSpectrumEditor editor2 = SpectrumEditor_create (ID_AND_FULL_NAME, me);
 				praat_installEditor (editor2.get(), IOBJECT);
 				editor2.releaseToUser();
@@ -323,468 +330,375 @@ static void cb_EEGWindow_publication (Editor /* editor */, autoDaata publication
 		Melder_flushError ();
 	}
 }
-DIRECT2 (EEG_viewAndEdit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an EEG from batch.");
+DIRECT (WINDOW_ERP_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an ERP from batch.");
 	LOOP {
-		iam (EEG);
-		autoEEGWindow editor = EEGWindow_create (ID_AND_FULL_NAME, me);
-		Editor_setPublicationCallback (editor.get(), cb_EEGWindow_publication);
+		iam_LOOP (ERP);
+		autoERPWindow editor = ERPWindow_create (ID_AND_FULL_NAME, me);
+		Editor_setPublicationCallback (editor.get(), cb_ERPWindow_publication);
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
-
-#pragma mark EEG & TextGrid
+END }
 
-DIRECT2 (EEG_TextGrid_replaceTextGrid) {
-	EEG me = FIRST (EEG);
-	EEG_replaceTextGrid (me, FIRST (TextGrid));
-	praat_dataChanged (me);
-END2 }
+// MARK: Tabulate
 
-#pragma mark ERP
-
-DIRECT2 (ERP_downto_Sound) {
-	LOOP {
-		iam (ERP);
-		autoSound thee = ERP_downto_Sound (me);
-		praat_new (thee.move());
-	}
-END2 }
-
-FORM (ERP_downto_Table, U"ERP: Down to Table", nullptr) {
-	BOOLEAN (U"Include sample number", false)
-	BOOLEAN (U"Include time", true)
-	NATURAL (U"Time decimals", U"6")
-	NATURAL (U"Voltage decimals", U"12")
-	RADIO (U"Voltage units", 1)
+FORM (NEW_ERP_downto_Table, U"ERP: Down to Table", nullptr) {
+	BOOLEAN4 (includeSampleNumber, U"Include sample number", false)
+	BOOLEAN4 (includeTime, U"Include time", true)
+	NATURAL4 (timeDecimals, U"Time decimals", U"6")
+	NATURAL4 (voltageDecimals, U"Voltage decimals", U"12")
+	RADIO4x (voltageUnits, U"Voltage units", 1, 1)
 		OPTION (U"volt")
 		OPTION (U"microvolt")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		autoTable thee = ERP_tabulate (me, GET_INTEGER (U"Include sample number"),
-			GET_INTEGER (U"Include time"), GET_INTEGER (U"Time decimals"), GET_INTEGER (U"Voltage decimals"), GET_INTEGER (U"Voltage units"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (ERP_draw, U"ERP: Draw", nullptr) {
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range", U"0.0 (= all)")
-	REAL (U"left Voltage range (V)", U"10e-6")
-	REAL (U"right Voltage range", U"-10e-6")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (ERP);
-		ERP_drawChannel_name (me, GRAPHICS, GET_STRING (U"Channel name"), GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Voltage range"), GET_REAL (U"right Voltage range"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+	CONVERT_EACH (ERP)
+		autoTable result = ERP_tabulate (me, includeSampleNumber,
+			includeTime, timeDecimals, voltageDecimals, voltageUnits);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (ERP_drawScalp, U"ERP: Draw scalp", nullptr) {
-	REAL (U"left Time range (s)", U"0.1")
-	REAL (U"right Time range", U"0.2")
-	REAL (U"left Voltage range (V)", U"10e-6")
-	REAL (U"right Voltage range", U"-10e-6")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (ERP);
-		ERP_drawScalp (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Voltage range"), GET_REAL (U"right Voltage range"), kGraphics_colourScale_GREY, GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-FORM (ERP_drawScalp_colour, U"ERP: Draw scalp (colour)", nullptr) {
-	REAL (U"left Time range (s)", U"0.1")
-	REAL (U"right Time range", U"0.2")
-	REAL (U"left Voltage range (V)", U"10e-6")
-	REAL (U"right Voltage range", U"-10e-6")
-	RADIO_ENUM (U"Colour scale", kGraphics_colourScale, BLUE_TO_RED)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (ERP);
-		ERP_drawScalp (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Voltage range"), GET_REAL (U"right Voltage range"), GET_ENUM (kGraphics_colourScale, U"Colour scale"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+// MARK: Draw
 
-FORM (ERP_drawScalp_garnish, U"ERP: Draw scalp (garnish)", nullptr) {
-	REAL (U"left Voltage range (V)", U"10e-6")
-	REAL (U"right Voltage range", U"-10e-6")
-	RADIO_ENUM (U"Colour scale", kGraphics_colourScale, BLUE_TO_RED)
-	OK2
+FORM (GRAPHICS_ERP_draw, U"ERP: Draw", nullptr) {
+	SENTENCE4 (channelName, U"Channel name", U"Cz")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range", U"0.0 (= all)")
+	REAL4 (fromVoltage, U"left Voltage range (V)", U"10e-6")
+	REAL4 (toVoltage, U"right Voltage range", U"-10e-6")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	autoPraatPicture picture;
-	ERP_drawScalp_garnish (GRAPHICS,
-		GET_REAL (U"left Voltage range"), GET_REAL (U"right Voltage range"), GET_ENUM (kGraphics_colourScale, U"Colour scale"));
-END2 }
+	GRAPHICS_EACH (ERP)
+		ERP_drawChannel_name (me, GRAPHICS, channelName, fromTime, toTime, fromVoltage, toVoltage, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (ERP_extractOneChannelAsSound, U"ERP: Extract one channel as Sound", nullptr) {
-	WORD (U"Channel name", U"Cz")
-	OK2
-DO
-	LOOP {
-		iam (ERP);
-		const char32 *channelName = GET_STRING (U"Channel name");
-		long channelNumber = ERP_getChannelNumber (me, channelName);
-		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
-		autoSound thee = Sound_extractChannel (me, channelNumber);
-		praat_new (thee.move(), my name, U"_", channelName);
-	}
-END2 }
+FORM (GRAPHICS_ERP_drawScalp, U"ERP: Draw scalp", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.1")
+	REAL4 (toTime, U"right Time range", U"0.2")
+	REAL4 (fromVoltage, U"left Voltage range (V)", U"10e-6")
+	REAL4 (toVoltage, U"right Voltage range", U"-10e-6")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (ERP)
+		ERP_drawScalp (me, GRAPHICS, fromTime, toTime,
+			fromVoltage, toVoltage, kGraphics_colourScale_GREY, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (ERP_formula, U"ERP: Formula", U"ERP: Formula...") {
-	LABEL (U"label1", U"! `x' is the time in seconds, `col' is the sample number.")
-	LABEL (U"label2", U"x = x1   ! time associated with first sample")
-	LABEL (U"label3", U"for col from 1 to ncol")
-	LABEL (U"label4", U"   self [col] = ...")
-	TEXTFIELD (U"formula", U"self")
-	LABEL (U"label5", U"   x = x + dx")
-	LABEL (U"label6", U"endfor")
-	OK2
-DO
-	LOOP {
-		iam (ERP);
-		try {
-			Matrix_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the ERP may have partially changed
-			throw;
-		}
-	}
-END2 }
+FORM (GRAPHICS_ERP_drawScalp_colour, U"ERP: Draw scalp (colour)", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.1")
+	REAL4 (toTime, U"right Time range", U"0.2")
+	REAL4 (fromVoltage, U"left Voltage range (V)", U"10e-6")
+	REAL4 (toVoltage, U"right Voltage range", U"-10e-6")
+	RADIO_ENUM4 (colourScale, U"Colour scale", kGraphics_colourScale, BLUE_TO_RED)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (ERP)
+		ERP_drawScalp (me, GRAPHICS, fromTime, toTime,
+			fromVoltage, toVoltage, (kGraphics_colourScale) colourScale, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (ERP_formula_part, U"ERP: Formula (part)", U"ERP: Formula...") {
-	REAL (U"From time", U"0.0")
-	REAL (U"To time", U"0.0 (= all)")
-	NATURAL (U"From channel", U"1")
-	NATURAL (U"To channel", U"2")
-	TEXTFIELD (U"formula", U"2 * self")
-	OK2
+FORM (GRAPHICS_ERP_drawScalp_garnish, U"ERP: Draw scalp (garnish)", nullptr) {
+	REAL4 (fromVoltage, U"left Voltage range (V)", U"10e-6")
+	REAL4 (toVoltage, U"right Voltage range", U"-10e-6")
+	RADIO_ENUM4 (colourScale, U"Colour scale", kGraphics_colourScale, BLUE_TO_RED)
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		try {
-			Matrix_formula_part (me,
-				GET_REAL (U"From time"), GET_REAL (U"To time"),
-				GET_INTEGER (U"From channel") - 0.5, GET_INTEGER (U"To channel") + 0.5,
-				GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the ERP may have partially changed
-			throw;
-		}
-	}
-END2 }
+	GRAPHICS_NONE
+		ERP_drawScalp_garnish (GRAPHICS, fromVoltage, toVoltage, (kGraphics_colourScale) colourScale);
+	GRAPHICS_NONE_END
+}
+
+// MARK: Query
 
-FORM (ERP_getChannelName, U"Get channel name", nullptr) {
-	NATURAL (U"Channel number", U"1")
-	OK2
+FORM (STRING_ERP_getChannelName, U"Get channel name", nullptr) {
+	NATURAL4 (channelNumber, U"Channel number", U"1")
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		long channelNumber = GET_INTEGER (U"Channel number");
+	STRING_ONE (ERP)
 		if (channelNumber > my ny)
 			Melder_throw (me, U": there are only ", my ny, U" channels.");
-		Melder_information (my channelNames [channelNumber]);
-	}
-END2 }
+		const char32 *result = my channelNames [channelNumber];
+	STRING_ONE_END
+}
 
-FORM (ERP_getChannelNumber, U"Get channel number", nullptr) {
-	WORD (U"Channel name", U"Cz")
-	OK2
+FORM (INTEGER_ERP_getChannelNumber, U"Get channel number", nullptr) {
+	WORD4 (channelName, U"Channel name", U"Cz")
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		Melder_information (ERP_getChannelNumber (me, GET_STRING (U"Channel name")));
-	}
-END2 }
+	NUMBER_ONE (ERP)
+		long result = ERP_getChannelNumber (me, channelName);
+	NUMBER_ONE_END (U" (number of channel ", channelName, U")")
+}
 
-FORM (ERP_getMaximum, U"ERP: Get maximum", U"Sound: Get maximum...") {
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
+FORM (REAL_ERP_getMinimum, U"ERP: Get minimum", U"Sound: Get minimum...") {
+	SENTENCE4 (channelName, U"Channel name", U"Cz")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (ERP);
-		const char32 *channelName = GET_STRING (U"Channel name");
-		long channelNumber = ERP_getChannelNumber (me, channelName);
-		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
-		double maximum;
-		Vector_getMaximumAndX (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channelNumber, GET_INTEGER (U"Interpolation") - 1, & maximum, nullptr);
-		Melder_informationReal (maximum, U"Volt");
-	}
-END2 }
-
-FORM (ERP_getMean, U"ERP: Get mean", U"ERP: Get mean...") {
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		const char32 *channelName = GET_STRING (U"Channel name");
+	NUMBER_ONE (ERP)
 		long channelNumber = ERP_getChannelNumber (me, channelName);
 		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
-		double mean = Vector_getMean (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channelNumber);
-		Melder_informationReal (mean, U"Volt");
-	}
-END2 }
+		double result;
+		Vector_getMinimumAndX (me, fromTime, toTime, channelNumber, interpolation, & result, nullptr);
+	NUMBER_ONE_END (U" Volt")
+}
 
-FORM (ERP_getMinimum, U"ERP: Get minimum", U"Sound: Get minimum...") {
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
+FORM (REAL_ERP_getTimeOfMinimum, U"ERP: Get time of minimum", U"Sound: Get time of minimum...") {
+	SENTENCE4 (channelName, U"Channel name", U"Cz")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		const char32 *channelName = GET_STRING (U"Channel name");
+	NUMBER_ONE (ERP)
 		long channelNumber = ERP_getChannelNumber (me, channelName);
 		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
-		double minimum;
-		Vector_getMinimumAndX (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channelNumber, GET_INTEGER (U"Interpolation") - 1, & minimum, nullptr);
-		Melder_informationReal (minimum, U"Volt");
-	}
-END2 }
+		double result;
+		Vector_getMinimumAndX (me, fromTime, toTime, channelNumber, interpolation, nullptr, & result);
+	NUMBER_ONE_END (U" seconds")
+}
 
-FORM (ERP_getTimeOfMaximum, U"ERP: Get time of maximum", U"Sound: Get time of maximum...") {
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
+FORM (REAL_ERP_getMaximum, U"ERP: Get maximum", U"Sound: Get maximum...") {
+	SENTENCE4 (channelName, U"Channel name", U"Cz")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		const char32 *channelName = GET_STRING (U"Channel name");
+	NUMBER_ONE (ERP)
 		long channelNumber = ERP_getChannelNumber (me, channelName);
 		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
-		double timeOfMaximum;
-		Vector_getMaximumAndX (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channelNumber, GET_INTEGER (U"Interpolation") - 1, nullptr, & timeOfMaximum);
-		Melder_informationReal (timeOfMaximum, U"seconds");
-	}
-END2 }
+		double result;
+		Vector_getMaximumAndX (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channelNumber, GET_INTEGER (U"Interpolation") - 1, & result, nullptr);
+	NUMBER_ONE_END (U" Volt")
+}
 
-FORM (ERP_getTimeOfMinimum, U"ERP: Get time of minimum", U"Sound: Get time of minimum...") {
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
+FORM (REAL_ERP_getTimeOfMaximum, U"ERP: Get time of maximum", U"Sound: Get time of maximum...") {
+	SENTENCE4 (channelName, U"Channel name", U"Cz")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (ERP);
-		const char32 *channelName = GET_STRING (U"Channel name");
+	NUMBER_ONE (ERP)
 		long channelNumber = ERP_getChannelNumber (me, channelName);
 		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
-		double timeOfMinimum;
-		Vector_getMinimumAndX (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channelNumber, GET_INTEGER (U"Interpolation") - 1, nullptr, & timeOfMinimum);
-		Melder_informationReal (timeOfMinimum, U"seconds");
-	}
-END2 }
+		double result;
+		Vector_getMaximumAndX (me, fromTime, toTime, channelNumber, interpolation, nullptr, & result);
+	NUMBER_ONE_END (U" seconds")
+}
 
-static void cb_ERPWindow_publication (Editor /* editor */, autoDaata publication) {
-	/*
-	 * Keep the gate for error handling.
-	 */
-	try {
-		bool isaSpectralSlice = Thing_isa (publication.get(), classSpectrum) && str32equ (Thing_getName (publication.get()), U"slice");
-		praat_new (publication.move());
-		praat_updateSelection ();
-		if (isaSpectralSlice) {
-			int IOBJECT;
-			LOOP {
-				iam (Spectrum);
-				autoSpectrumEditor editor2 = SpectrumEditor_create (ID_AND_FULL_NAME, me);
-				praat_installEditor (editor2.get(), IOBJECT);
-				editor2.releaseToUser();
-			}
-		}
-	} catch (MelderError) {
-		Melder_flushError ();
-	}
+FORM (REAL_ERP_getMean, U"ERP: Get mean", U"ERP: Get mean...") {
+	SENTENCE4 (channelName, U"Channel name", U"Cz")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO
+	NUMBER_ONE (ERP)
+		long channelNumber = ERP_getChannelNumber (me, channelName);
+		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
+		double result = Vector_getMean (me, fromTime, toTime, channelNumber);
+	NUMBER_ONE_END (U" Volt")
 }
-DIRECT2 (ERP_viewAndEdit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an ERP from batch.");
-	LOOP {
-		iam (ERP);
-		autoERPWindow editor = ERPWindow_create (ID_AND_FULL_NAME, me);
-		Editor_setPublicationCallback (editor.get(), cb_ERPWindow_publication);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
 
-/***** ERPTier *****/
+// MARK: Modify
 
-FORM (ERPTier_getChannelName, U"Get channel name", nullptr) {
-	NATURAL (U"Channel number", U"1")
-	OK2
+FORM (MODIFY_ERP_formula, U"ERP: Formula", U"ERP: Formula...") {
+	LABEL (U"label1", U"! `x' is the time in seconds, `col' is the sample number.")
+	LABEL (U"label2", U"x = x1   ! time associated with first sample")
+	LABEL (U"label3", U"for col from 1 to ncol")
+	LABEL (U"label4", U"   self [col] = ...")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	LABEL (U"label5", U"   x = x + dx")
+	LABEL (U"label6", U"endfor")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		long channelNumber = GET_INTEGER (U"Channel number");
-		if (channelNumber > my numberOfChannels)
-			Melder_throw (me, U": there are only ", my numberOfChannels, U" channels.");
-		Melder_information (my channelNames [channelNumber]);
-	}
-END2 }
+	MODIFY_EACH_WEAK (ERP)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM (ERPTier_getChannelNumber, U"Get channel number", nullptr) {
-	WORD (U"Channel name", U"Cz")
-	OK2
+FORM (MODIFY_ERP_formula_part, U"ERP: Formula (part)", U"ERP: Formula...") {
+	REAL4 (fromTime, U"From time", U"0.0")
+	REAL4 (toTime, U"To time", U"0.0 (= all)")
+	NATURAL4 (fromChannel, U"From channel", U"1")
+	NATURAL4 (toChannel, U"To channel", U"2")
+	TEXTFIELD4 (formula, U"formula", U"2 * self")
+	OK
+DO
+	MODIFY_EACH_WEAK (ERP)
+		Matrix_formula_part (me, fromTime, toTime,
+			fromChannel - 0.5, toChannel + 0.5, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+// MARK: Extract
+
+FORM (NEW_ERP_extractOneChannelAsSound, U"ERP: Extract one channel as Sound", nullptr) {
+	WORDVAR (channelName, U"Channel name", U"Cz")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		Melder_information (ERPTier_getChannelNumber (me, GET_STRING (U"Channel name")));
-	}
-END2 }
+	CONVERT_EACH (ERP)
+		long channelNumber = ERP_getChannelNumber (me, channelName);
+		if (channelNumber == 0) Melder_throw (me, U": no channel named \"", channelName, U"\".");
+		autoSound result = Sound_extractChannel (me, channelNumber);
+	CONVERT_EACH_END (my name, U"_", channelName)
+}
+
+// MARK: Convert
+
+DIRECT (NEW_ERP_downto_Sound) {
+	CONVERT_EACH (ERP)
+		autoSound result = ERP_downto_Sound (me);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - ERPTIER
 
-FORM (ERPTier_getMean, U"ERPTier: Get mean", U"ERPTier: Get mean...") {
-	NATURAL (U"Point number", U"1")
-	SENTENCE (U"Channel name", U"Cz")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
+// MARK: Help
+
+DIRECT (HELP_ERPTier_help) {
+	HELP (U"ERPTier")
+}
+
+// MARK: Query
+
+FORM (STRING_ERPTier_getChannelName, U"Get channel name", nullptr) {
+	NATURALVAR (channelNumber, U"Channel number", U"1")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		double mean = ERPTier_getMean (me, GET_INTEGER (U"Point number"), GET_STRING (U"Channel name"), GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (mean, U"Volt");
-	}
-END2 }
+	STRING_ONE (ERPTier)
+		if (channelNumber > my numberOfChannels)
+			Melder_throw (me, U": there are only ", my numberOfChannels, U" channels.");
+		const char32 *result = my channelNames [channelNumber];
+	STRING_ONE_END
+}
 
-FORM (ERPTier_rejectArtefacts, U"Reject artefacts", nullptr) {
-	POSITIVE (U"Threshold (V)", U"75e-6")
-	OK2
+FORM (INTEGER_ERPTier_getChannelNumber, U"Get channel number", nullptr) {
+	WORDVAR (channelName, U"Channel name", U"Cz")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		ERPTier_rejectArtefacts (me, GET_REAL (U"Threshold"));
-		praat_dataChanged (me);
-	}
-END2 }
+	NUMBER_ONE (ERPTier)
+		long result = ERPTier_getChannelNumber (me, channelName);
+	NUMBER_ONE_END (U" (number of channel ", channelName, U")")
+}
 
-FORM (ERPTier_removeEventsBetween, U"Remove events", U"ERPTier: Remove events between...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1.0")
-	OK2
+FORM (REAL_ERPTier_getMean, U"ERPTier: Get mean", U"ERPTier: Get mean...") {
+	NATURALVAR (pointNumber, U"Point number", U"1")
+	SENTENCEVAR (channelName, U"Channel name", U"Cz")
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		AnyTier_removePointsBetween (me->asAnyTier(), GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		praat_dataChanged (me);
-	}
-END2 }
+	NUMBER_ONE (ERPTier)
+		double result = ERPTier_getMean (me, pointNumber, channelName, fromTime, toTime);
+	NUMBER_ONE_END (U" Volt")
+}
 
-FORM (ERPTier_subtractBaseline, U"Subtract baseline", nullptr) {
-	REAL (U"From time (s)", U"-0.11")
-	REAL (U"To time (s)", U"0.0")
-	OK2
+// MARK: Modify
+
+FORM (MODIFY_ERPTier_rejectArtefacts, U"Reject artefacts", nullptr) {
+	POSITIVEVAR (threshold, U"Threshold (V)", U"75e-6")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		ERPTier_subtractBaseline (me, GET_REAL (U"From time"), GET_REAL (U"To time"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (ERPTier)
+		ERPTier_rejectArtefacts (me, threshold);
+	MODIFY_EACH_END
+}
 
-FORM (ERPTier_to_ERP, U"ERPTier: To ERP", nullptr) {
-	NATURAL (U"Event number", U"1")
-	OK2
+FORM (MODIFY_ERPTier_removeEventsBetween, U"Remove events", U"ERPTier: Remove events between...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"1.0")
+	OK
 DO
-	LOOP {
-		iam (ERPTier);
-		autoERP thee = ERPTier_extractERP (me, GET_INTEGER (U"Event number"));
-		praat_new (thee.move(), my name, U"_mean");
-	}
-END2 }
+	MODIFY_EACH (ERPTier)
+		AnyTier_removePointsBetween (me->asAnyTier(), fromTime, toTime);
+	MODIFY_EACH_END
+}
 
-DIRECT2 (ERPTier_to_ERP_mean) {
-	LOOP {
-		iam (ERPTier);
-		autoERP thee = ERPTier_to_ERP_mean (me);
-		praat_new (thee.move(), my name, U"_mean");
-	}
-END2 }
+FORM (MODIFY_ERPTier_subtractBaseline, U"Subtract baseline", nullptr) {
+	REAL4 (baselineStartTime, U"Baseline start time (s)", U"-0.11")
+	REAL4 (baselineEndTime, U"Baseline end time (s)", U"0.0")
+	OK
+DO
+	MODIFY_EACH (ERPTier)
+		ERPTier_subtractBaseline (me, baselineStartTime, baselineEndTime);
+	MODIFY_EACH_END
+}
 
-/***** ERPTier & Table *****/
+// MARK: Analyse
 
-FORM (ERPTier_Table_extractEventsWhereColumn_number, U"Extract events where column (number)", nullptr) {
-	WORD (U"Extract all events where column...", U"")
-	RADIO_ENUM (U"...is...", kMelder_number, DEFAULT)
-	REAL (U"...the number", U"0.0")
-	OK2
+FORM (NEW_ERPTier_to_ERP, U"ERPTier: To ERP", nullptr) {
+	NATURAL4 (eventNumber, U"Event number", U"1")
+	OK
 DO
-	ERPTier erpTier = FIRST (ERPTier);
-	Table table = FIRST (Table);
-	long columnNumber = Table_getColumnIndexFromColumnLabel (table, GET_STRING (U"Extract all events where column..."));
-	autoERPTier thee = ERPTier_extractEventsWhereColumn_number (erpTier, table, columnNumber, GET_ENUM (kMelder_number, U"...is..."), GET_REAL (U"...the number"));
-	praat_new (thee.move(), erpTier -> name);
-END2 }
+	CONVERT_EACH (ERPTier)
+		autoERP result = ERPTier_extractERP (me, eventNumber);
+	CONVERT_EACH_END (my name, U"_", eventNumber)
+}
 
-FORM (ERPTier_Table_extractEventsWhereColumn_text, U"Extract events where column (text)", 0) {
-	WORD (U"Extract all events where column...", U"")
-	OPTIONMENU_ENUM (U"...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
-DO
-	ERPTier erpTier = FIRST (ERPTier);
-	Table table = FIRST (Table);
-	long columnNumber = Table_getColumnIndexFromColumnLabel (table, GET_STRING (U"Extract all events where column..."));
-	autoERPTier thee = ERPTier_extractEventsWhereColumn_string (erpTier, table, columnNumber, GET_ENUM (kMelder_string, U"..."), GET_STRING (U"...the text"));
-	praat_new (thee.move(), erpTier -> name);
-END2 }
+DIRECT (NEW_ERPTier_to_ERP_mean) {
+	CONVERT_EACH (ERPTier)
+		autoERP result = ERPTier_to_ERP_mean (me);
+	CONVERT_EACH_END (my name, U"_mean")
+}
 
-/***** Help menus *****/
+// MARK: - ERPTIER & TABLE
 
-DIRECT2 (EEG_help) {
-	Melder_help (U"EEG");
-END2 }
+FORM (NEW1_ERPTier_Table_extractEventsWhereColumn_number, U"Extract events where column (number)", nullptr) {
+	WORD4 (extractAllEventsWhereColumn___, U"Extract all events where column...", U"")
+	RADIO_ENUM4 (___is___, U"...is...", kMelder_number, DEFAULT)
+	REAL4 (___theNumber, U"...the number", U"0.0")
+	OK
+DO
+	CONVERT_TWO (ERPTier, Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (you, extractAllEventsWhereColumn___);
+		autoERPTier result = ERPTier_extractEventsWhereColumn_number (me, you, columnNumber, ___is___, ___theNumber);
+	CONVERT_TWO_END (my name)
+}
 
-DIRECT2 (ERPTier_help) {
-	Melder_help (U"ERPTier");
-END2 }
+FORM (NEW1_ERPTier_Table_extractEventsWhereColumn_text, U"Extract events where column (text)", nullptr) {
+	WORD4 (extractAllEventsWhereColumn___, U"Extract all events where column...", U"")
+	OPTIONMENU_ENUM4 (___, U"...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
+DO
+	CONVERT_TWO (ERPTier, Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (you, extractAllEventsWhereColumn___);
+		autoERPTier result = ERPTier_extractEventsWhereColumn_string (me, you, columnNumber, ___, ___theText);
+	CONVERT_TWO_END (my name)
+}
 
-/***** file recognizers *****/
+// MARK: - file recognizers
 
 static autoDaata bdfFileRecognizer (int nread, const char * /* header */, MelderFile file) {
 	const char32 *fileName = MelderFile_name (file);
@@ -796,9 +710,7 @@ static autoDaata bdfFileRecognizer (int nread, const char * /* header */, Melder
 	return EEG_readFromBdfFile (file);
 }
 
-/***** buttons *****/
-
-void praat_TimeTier_query_init (ClassInfo klas);   // Query buttons for time-based subclasses of AnyTier.
+// MARK: - buttons
 
 void praat_EEG_init ();
 void praat_EEG_init () {
@@ -807,87 +719,87 @@ void praat_EEG_init () {
 
 	Data_recognizeFileType (bdfFileRecognizer);
 
-	praat_addAction1 (classEEG, 0, U"EEG help", nullptr, 0, DO_EEG_help);
-	praat_addAction1 (classEEG, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_EEG_viewAndEdit);
+	praat_addAction1 (classEEG, 0, U"EEG help", nullptr, 0, HELP_EEG_help);
+	praat_addAction1 (classEEG, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_EEG_viewAndEdit);
 	praat_addAction1 (classEEG, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classEEG, 0, U"Get channel name...", nullptr, 1, DO_EEG_getChannelName);
-		praat_addAction1 (classEEG, 0, U"Get channel number...", nullptr, 1, DO_EEG_getChannelNumber);
+		praat_addAction1 (classEEG, 1, U"Get channel name...", nullptr, 1, STRING_EEG_getChannelName);
+		praat_addAction1 (classEEG, 1, U"Get channel number...", nullptr, 1, INTEGER_EEG_getChannelNumber);
 	praat_addAction1 (classEEG, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classEEG, 0, U"Set channel name...", nullptr, 1, DO_EEG_setChannelName);
-		praat_addAction1 (classEEG, 1, U"Edit external electrode names...", nullptr, 1, DO_EEG_editExternalElectrodeNames);
+		praat_addAction1 (classEEG, 0, U"Set channel name...", nullptr, 1, MODIFY_EEG_setChannelName);
+		praat_addAction1 (classEEG, 1, U"Edit external electrode names...", nullptr, 1, MODIFY_EEG_editExternalElectrodeNames);
 		praat_addAction1 (classEEG, 0, U"-- processing --", nullptr, 1, nullptr);
-		praat_addAction1 (classEEG, 0, U"Subtract reference...", nullptr, 1, DO_EEG_subtractReference);
-		praat_addAction1 (classEEG, 0, U"Subtract mean channel...", nullptr, 1, DO_EEG_subtractMeanChannel);
-		praat_addAction1 (classEEG, 0, U"Detrend", nullptr, 1, DO_EEG_detrend);
-		praat_addAction1 (classEEG, 0, U"Filter...", nullptr, 1, DO_EEG_filter);
-		praat_addAction1 (classEEG, 0, U"Remove triggers...", nullptr, 1, DO_EEG_removeTriggers);
-		praat_addAction1 (classEEG, 0, U"Set channel to zero...", nullptr, 1, DO_EEG_setChannelToZero);
+		praat_addAction1 (classEEG, 0, U"Subtract reference...", nullptr, 1, MODIFY_EEG_subtractReference);
+		praat_addAction1 (classEEG, 0, U"Subtract mean channel...", nullptr, 1, MODIFY_EEG_subtractMeanChannel);
+		praat_addAction1 (classEEG, 0, U"Detrend", nullptr, 1, MODIFY_EEG_detrend);
+		praat_addAction1 (classEEG, 0, U"Filter...", nullptr, 1, MODIFY_EEG_filter);
+		praat_addAction1 (classEEG, 0, U"Remove triggers...", nullptr, 1, MODIFY_EEG_removeTriggers);
+		praat_addAction1 (classEEG, 0, U"Set channel to zero...", nullptr, 1, MODIFY_EEG_setChannelToZero);
 	praat_addAction1 (classEEG, 0, U"Analyse", nullptr, 0, nullptr);
-		praat_addAction1 (classEEG, 0, U"Extract channel...", nullptr, 0, DO_EEG_extractChannel);
-		praat_addAction1 (classEEG, 1, U"Extract part...", nullptr, 0, DO_EEG_extractPart);
+		praat_addAction1 (classEEG, 0, U"Extract channel...", nullptr, 0, NEW_EEG_extractChannel);
+		praat_addAction1 (classEEG, 0, U"Extract part...", nullptr, 0, NEW_EEG_extractPart);
 		praat_addAction1 (classEEG, 0, U"To ERPTier -", nullptr, 0, nullptr);
-		praat_addAction1 (classEEG, 0, U"To ERPTier (bit)...", nullptr, 1, DO_EEG_to_ERPTier_bit);
-		praat_addAction1 (classEEG, 0, U"To ERPTier (marker)...", nullptr, 1, DO_EEG_to_ERPTier_marker);
-		praat_addAction1 (classEEG, 0, U"To ERPTier (triggers)...", nullptr, 1, DO_EEG_to_ERPTier_triggers);
-		praat_addAction1 (classEEG, 0, U"To ERPTier (triggers, preceded)...", nullptr, 1, DO_EEG_to_ERPTier_triggers_preceded);
-		praat_addAction1 (classEEG, 0, U"To ERPTier...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_EEG_to_ERPTier_bit);
-		praat_addAction1 (classEEG, 0, U"To MixingMatrix...", nullptr, 0, DO_EEG_to_MixingMatrix);
+		praat_addAction1 (classEEG, 0, U"To ERPTier (bit)...", nullptr, 1, NEW_EEG_to_ERPTier_bit);
+		praat_addAction1 (classEEG, 0, U"To ERPTier (marker)...", nullptr, 1, NEW_EEG_to_ERPTier_marker);
+		praat_addAction1 (classEEG, 0, U"To ERPTier (triggers)...", nullptr, 1, NEW_EEG_to_ERPTier_triggers);
+		praat_addAction1 (classEEG, 0, U"To ERPTier (triggers, preceded)...", nullptr, 1, NEW_EEG_to_ERPTier_triggers_preceded);
+		praat_addAction1 (classEEG, 0, U"To ERPTier...", nullptr, praat_DEPTH_1 + praat_HIDDEN, NEW_EEG_to_ERPTier_bit);
+		praat_addAction1 (classEEG, 0, U"To MixingMatrix...", nullptr, 0, NEW_EEG_to_MixingMatrix);
 	praat_addAction1 (classEEG, 0, U"Synthesize", nullptr, 0, nullptr);
-		praat_addAction1 (classEEG, 0, U"Concatenate", nullptr, 0, DO_EEGs_concatenate);
+		praat_addAction1 (classEEG, 0, U"Concatenate", nullptr, 0, NEW1_EEGs_concatenate);
 	praat_addAction1 (classEEG, 0, U"Hack -", nullptr, 0, nullptr);
-		praat_addAction1 (classEEG, 0, U"Extract waveforms as Sound", nullptr, 1, DO_EEG_extractSound);
-		praat_addAction1 (classEEG, 0, U"Extract marks as TextGrid", nullptr, 1, DO_EEG_extractTextGrid);
+		praat_addAction1 (classEEG, 0, U"Extract waveforms as Sound", nullptr, 1, NEW_EEG_extractSound);
+		praat_addAction1 (classEEG, 0, U"Extract marks as TextGrid", nullptr, 1, NEW_EEG_extractTextGrid);
 
-	praat_addAction1 (classERP, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_ERP_viewAndEdit);
+	praat_addAction1 (classERP, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_ERP_viewAndEdit);
 	praat_addAction1 (classERP, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classERP, 0, U"Draw...", nullptr, 1, DO_ERP_draw);
-		praat_addAction1 (classERP, 0, U"Draw scalp...", nullptr, 1, DO_ERP_drawScalp);
-		praat_addAction1 (classERP, 0, U"Draw scalp (colour)...", nullptr, 1, DO_ERP_drawScalp_colour);
-		praat_addAction1 (classERP, 0, U"Draw scalp (garnish)...", nullptr, 1, DO_ERP_drawScalp_garnish);
+		praat_addAction1 (classERP, 0, U"Draw...", nullptr, 1, GRAPHICS_ERP_draw);
+		praat_addAction1 (classERP, 0, U"Draw scalp...", nullptr, 1, GRAPHICS_ERP_drawScalp);
+		praat_addAction1 (classERP, 0, U"Draw scalp (colour)...", nullptr, 1, GRAPHICS_ERP_drawScalp_colour);
+		praat_addAction1 (classERP, 0, U"Draw scalp (garnish)...", nullptr, 1, GRAPHICS_ERP_drawScalp_garnish);
 	praat_addAction1 (classERP, 0, U"Tabulate -", nullptr, 0, nullptr);
-		praat_addAction1 (classERP, 0, U"Down to Table...", nullptr, 1, DO_ERP_downto_Table);
+		praat_addAction1 (classERP, 0, U"Down to Table...", nullptr, 1, NEW_ERP_downto_Table);
 	praat_addAction1 (classERP, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classERP, 0, U"Get channel name...", nullptr, 1, DO_ERP_getChannelName);
-		praat_addAction1 (classERP, 0, U"Get channel number...", nullptr, 1, DO_ERP_getChannelNumber);
+		praat_addAction1 (classERP, 0, U"Get channel name...", nullptr, 1, STRING_ERP_getChannelName);
+		praat_addAction1 (classERP, 0, U"Get channel number...", nullptr, 1, INTEGER_ERP_getChannelNumber);
 		praat_addAction1 (classERP, 0, U"-- get shape --", nullptr, 1, nullptr);
-		praat_addAction1 (classERP, 0, U"Get minimum...", nullptr, 1, DO_ERP_getMinimum);
-		praat_addAction1 (classERP, 0, U"Get time of minimum...", nullptr, 1, DO_ERP_getTimeOfMinimum);
-		praat_addAction1 (classERP, 0, U"Get maximum...", nullptr, 1, DO_ERP_getMaximum);
-		praat_addAction1 (classERP, 0, U"Get time of maximum...", nullptr, 1, DO_ERP_getTimeOfMaximum);
+		praat_addAction1 (classERP, 0, U"Get minimum...", nullptr, 1, REAL_ERP_getMinimum);
+		praat_addAction1 (classERP, 0, U"Get time of minimum...", nullptr, 1, REAL_ERP_getTimeOfMinimum);
+		praat_addAction1 (classERP, 0, U"Get maximum...", nullptr, 1, REAL_ERP_getMaximum);
+		praat_addAction1 (classERP, 0, U"Get time of maximum...", nullptr, 1, REAL_ERP_getTimeOfMaximum);
 		praat_addAction1 (classERP, 0, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classERP, 0, U"Get mean...", nullptr, 1, DO_ERP_getMean);
+		praat_addAction1 (classERP, 0, U"Get mean...", nullptr, 1, REAL_ERP_getMean);
 	praat_addAction1 (classERP, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classERP, 0, U"Formula...", nullptr, 1, DO_ERP_formula);
-		praat_addAction1 (classERP, 0, U"Formula (part)...", nullptr, 1, DO_ERP_formula_part);
+		praat_addAction1 (classERP, 0, U"Formula...", nullptr, 1, MODIFY_ERP_formula);
+		praat_addAction1 (classERP, 0, U"Formula (part)...", nullptr, 1, MODIFY_ERP_formula_part);
 	// praat_addAction1 (classERP, 0, U"Analyse -", nullptr, 0, nullptr);
-		// praat_addAction1 (classERP, 0, U"To ERP (difference)", nullptr, 1, DO_ERP_to_ERP_difference);
-		// praat_addAction1 (classERP, 0, U"To ERP (mean)", nullptr, 1, DO_ERP_to_ERP_mean);
+		// praat_addAction1 (classERP, 0, U"To ERP (difference)", nullptr, 1, NEW_ERP_to_ERP_difference);
+		// praat_addAction1 (classERP, 0, U"To ERP (mean)", nullptr, 1, NEW_ERP_to_ERP_mean);
 	praat_addAction1 (classERP, 0, U"Hack -", nullptr, 0, nullptr);
-		praat_addAction1 (classERP, 0, U"Down to Sound", nullptr, 1, DO_ERP_downto_Sound);
-		praat_addAction1 (classERP, 0, U"Extract one channel as Sound...", nullptr, 1, DO_ERP_extractOneChannelAsSound);
+		praat_addAction1 (classERP, 0, U"Down to Sound", nullptr, 1, NEW_ERP_downto_Sound);
+		praat_addAction1 (classERP, 0, U"Extract one channel as Sound...", nullptr, 1, NEW_ERP_extractOneChannelAsSound);
 
-	praat_addAction1 (classERPTier, 0, U"ERPTier help", nullptr, 0, DO_ERPTier_help);
-	// praat_addAction1 (classERPTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_ERPTier_viewAndEdit);
+	praat_addAction1 (classERPTier, 0, U"ERPTier help", nullptr, 0, HELP_ERPTier_help);
+	// praat_addAction1 (classERPTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_ERPTier_viewAndEdit);
 	praat_addAction1 (classERPTier, 0, U"Query -", nullptr, 0, nullptr);
 		praat_TimeTier_query_init (classERPTier);
 		praat_addAction1 (classERPTier, 0, U"-- channel names --", nullptr, 1, nullptr);
-		praat_addAction1 (classERPTier, 0, U"Get channel name...", nullptr, 1, DO_ERPTier_getChannelName);
-		praat_addAction1 (classERPTier, 0, U"Get channel number...", nullptr, 1, DO_ERPTier_getChannelNumber);
+		praat_addAction1 (classERPTier, 0, U"Get channel name...", nullptr, 1, STRING_ERPTier_getChannelName);
+		praat_addAction1 (classERPTier, 0, U"Get channel number...", nullptr, 1, INTEGER_ERPTier_getChannelNumber);
 		praat_addAction1 (classERPTier, 0, U"-- erp --", nullptr, 1, nullptr);
-		praat_addAction1 (classERPTier, 0, U"Get mean...", nullptr, 1, DO_ERPTier_getMean);
+		praat_addAction1 (classERPTier, 0, U"Get mean...", nullptr, 1, REAL_ERPTier_getMean);
 	praat_addAction1 (classERPTier, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classERPTier, 0, U"Subtract baseline...", nullptr, 1, DO_ERPTier_subtractBaseline);
-		praat_addAction1 (classERPTier, 0, U"Reject artefacts...", nullptr, 1, DO_ERPTier_rejectArtefacts);
+		praat_addAction1 (classERPTier, 0, U"Subtract baseline...", nullptr, 1, MODIFY_ERPTier_subtractBaseline);
+		praat_addAction1 (classERPTier, 0, U"Reject artefacts...", nullptr, 1, MODIFY_ERPTier_rejectArtefacts);
 		praat_addAction1 (classERPTier, 0, U"-- structure --", nullptr, 1, nullptr);
-		praat_addAction1 (classERPTier, 0, U"Remove events between...", nullptr, 1, DO_ERPTier_removeEventsBetween);
+		praat_addAction1 (classERPTier, 0, U"Remove events between...", nullptr, 1, MODIFY_ERPTier_removeEventsBetween);
 	praat_addAction1 (classERPTier, 0, U"Analyse", nullptr, 0, nullptr);
-		praat_addAction1 (classERPTier, 0, U"Extract ERP...", nullptr, 0, DO_ERPTier_to_ERP);
-		praat_addAction1 (classERPTier, 0, U"To ERP (mean)", nullptr, 0, DO_ERPTier_to_ERP_mean);
+		praat_addAction1 (classERPTier, 0, U"Extract ERP...", nullptr, 0, NEW_ERPTier_to_ERP);
+		praat_addAction1 (classERPTier, 0, U"To ERP (mean)", nullptr, 0, NEW_ERPTier_to_ERP_mean);
 
-	praat_addAction2 (classEEG, 1, classTextGrid, 1, U"Replace TextGrid", nullptr, 0, DO_EEG_TextGrid_replaceTextGrid);
+	praat_addAction2 (classEEG, 1, classTextGrid, 1, U"Replace TextGrid", nullptr, 0, MODIFY_EEG_TextGrid_replaceTextGrid);
 	praat_addAction2 (classERPTier, 1, classTable, 1, U"Extract -", nullptr, 0, nullptr);
-	praat_addAction2 (classERPTier, 1, classTable, 1, U"Extract events where column (number)...", nullptr, 1, DO_ERPTier_Table_extractEventsWhereColumn_number);
-	praat_addAction2 (classERPTier, 1, classTable, 1, U"Extract events where column (text)...", nullptr, 1, DO_ERPTier_Table_extractEventsWhereColumn_text);
+	praat_addAction2 (classERPTier, 1, classTable, 1, U"Extract events where column (number)...", nullptr, 1, NEW1_ERPTier_Table_extractEventsWhereColumn_number);
+	praat_addAction2 (classERPTier, 1, classTable, 1, U"Extract events where column (text)...", nullptr, 1, NEW1_ERPTier_Table_extractEventsWhereColumn_text);
 
 	structEEGWindow :: f_preferences ();
 	structERPWindow :: f_preferences ();
diff --git a/FFNet/FFNet.cpp b/FFNet/FFNet.cpp
index cf9127e..096dca9 100644
--- a/FFNet/FFNet.cpp
+++ b/FFNet/FFNet.cpp
@@ -340,6 +340,28 @@ void FFNet_reset (FFNet me, double weightRange) {
 	my minimizer.reset();
 }
 
+const char32* FFNet_getCategoryOfOutputUnit (FFNet me, long outputUnit) {
+	const char32 *result = U"-- undefined --";
+	if (my outputCategories && outputUnit <= my outputCategories -> size) {
+		SimpleString ss = my outputCategories->at [outputUnit];
+		result = ss -> string;
+	}
+	return result;
+}
+
+long FFNet_getOutputUnitOfCategory (FFNet me, const char32* category) {
+	long result = 0;
+	if (my outputCategories) {
+		for (long i = 1; i <= my outputCategories -> size; i ++) {
+			SimpleString s = my outputCategories->at [i];
+			if (Melder_equ (s -> string, category)) {
+				result = i;
+				break;
+			}
+		}
+	}
+	return result;
+}
 
 /***** OPERATION: ***********************************************************/
 /* step 1 */
@@ -839,4 +861,22 @@ autoFFNet FFNet_and_TabelOfReal_to_FFNet (FFNet me, TableOfReal him, long layer)
 	}
 }
 
+autoFFNet PatternList_Categories_to_FFNet (PatternList me, Categories you, long numberOfUnits1, long numberOfUnits2) {
+	try {
+		numberOfUnits1 = numberOfUnits1 > 0 ? numberOfUnits1 : 0;
+		numberOfUnits2 = numberOfUnits2 > 0 ? numberOfUnits2 : 0;
+		autoCategories uniq = Categories_selectUniqueItems (you);
+		long numberOfOutputs = uniq -> size;
+		if (numberOfOutputs < 1) {
+			Melder_throw (U"There are no categories in the Categories.");
+		}
+		autoFFNet result = FFNet_create (my nx, numberOfUnits1, numberOfUnits2, numberOfOutputs, false);
+		FFNet_setOutputCategories (result.get(), uniq.get());
+		autostring32 ffnetName = FFNet_createNameFromTopology (result.get());
+		Thing_setName (result.get(), ffnetName.peek());
+		return result;
+	} catch (MelderError) {
+		Melder_throw (me, you, U": no FFNet created.");
+	}
+}
 /* End of file FFNet.cpp */
diff --git a/FFNet/FFNet.h b/FFNet/FFNet.h
index 5b5f71b..43f37c2 100644
--- a/FFNet/FFNet.h
+++ b/FFNet/FFNet.h
@@ -2,7 +2,7 @@
 #define _FFNet_h_
 /* FFNet.h
  *
- * Copyright (C) 1997-2011, 2015 David Weenink
+ * Copyright (C) 1997-2011, 2015-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
 #include "Data.h"
 #include "Categories.h"
 #include "Minimizers.h"
+#include "PatternList.h"
 #include "TableOfReal.h"
 
 #include "FFNet_def.h"
@@ -151,6 +152,10 @@ void FFNet_reset (FFNet me, double wrange);
  *   forget links with minimizer.
  */
 
+const char32* FFNet_getCategoryOfOutputUnit (FFNet me, long outputUnit);
+
+long FFNet_getOutputUnitOfCategory (FFNet me, const char32* category);
+
 void FFNet_propagateToLayer (FFNet me, const double input[], double activity[], long layer);
 /* propagate the input through the net to layer and calculate the activities */
 
@@ -225,4 +230,6 @@ void FFNet_drawWeights (FFNet me, Graphics g, long layer, int garnish);
 
 autoFFNet FFNet_and_TabelOfReal_to_FFNet (FFNet me, TableOfReal him, long layer);
 
+autoFFNet PatternList_Categories_to_FFNet (PatternList me, Categories you, long numberOfUnits1, long numberOfUnits2);
+
 #endif /* _FFNet_h_ */
diff --git a/artsynth/Speaker.h b/FFNet/praat_FFNet.h
similarity index 56%
copy from artsynth/Speaker.h
copy to FFNet/praat_FFNet.h
index e3c6992..9f155f7 100644
--- a/artsynth/Speaker.h
+++ b/FFNet/praat_FFNet.h
@@ -1,8 +1,8 @@
-#ifndef _Speaker_h_
-#define _Speaker_h_
-/* Speaker.h
+#ifndef _praat_FFNet_h_
+#define _praat_FFNet_h_
+/* praat_FFNet.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 2016 David Weenink & Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,15 +18,20 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "Data.h"
+/*
+	Interface functions for time-based subclasses of Function.
+*/
 
-#include "Speaker_def.h"
+#include "FFNet.h"
+#include "praat.h"
 
-autoSpeaker Speaker_create (char32 *kindOfSpeaker, int numberOfVocalCordMasses);
-	/* Preconditions:								*/
-	/*    1 <= numberOfVocalCordMasses <= 2;					*/
-	/* Failures:									*/
-	/*    Kind of speaker is not one of "Female", "Male", or "Child".		*/
+void praat_uvafon_FFNet_init ();
 
-/* End of file Speaker.h */
+/*
+	Special request from contrib/Ola, who wants to include these commands in the KNN menu.
+*/
+extern "C" void NEW1_PatternList_create (UiCallback_ARGS);
+extern "C" void NEW1_Categories_create (UiCallback_ARGS);
+
+/* End of file praat_FFNet.h */
 #endif
diff --git a/FFNet/praat_FFNet_init.cpp b/FFNet/praat_FFNet_init.cpp
index 9c26798..e526ee5 100644
--- a/FFNet/praat_FFNet_init.cpp
+++ b/FFNet/praat_FFNet_init.cpp
@@ -30,7 +30,6 @@
 */
 
 #include <math.h>
-#include "praat.h"
 #include "Discriminant.h"
 #include "PCA.h"
 #include "Minimizers.h"
@@ -42,6 +41,8 @@
 #include "FFNet_PatternList_Categories.h"
 #include "RBM_extensions.h"
 
+#include "praat_FFNet.h"
+
 /* Routines to be removed sometime in the future:
 20040422, 2.4.04: FFNet_drawWeightsToLayer  use FFNet_drawWeights
 20040422, 2.4.04: FFNet_weightsToMatrix use FFNet_extractWeights
@@ -57,719 +58,590 @@ static char32 const *EXTRACT_BUTTON = U"Extract -";
 
 /**************** New FFNet ***************************/
 
-static void FFNet_create_addCommonFields_inputOutput (UiForm dia) {
-	NATURAL (U"Number of inputs", U"4")
-	NATURAL (U"Number of outputs", U"3")
+FORM (NEW1_FFNet_create, U"Create FFNet", U"Create FFNet...") {
+	WORDVAR (name, U"Name", U"4-3")
+	NATURALVAR (numberOfInputs, U"Number of inputs", U"4")
+	NATURALVAR (numberOfOutputs, U"Number of outputs", U"3")
+	INTEGERVAR (numberOfUnits1, U"Number of units in hidden layer 1", U"0")
+	INTEGERVAR (numberOfUnits2, U"Number of units in hidden layer 2", U"0")
+	OK
+DO
+	CREATE_ONE
+		autoFFNet result = FFNet_create (numberOfInputs, numberOfUnits1, numberOfUnits2, numberOfOutputs, false);
+	CREATE_ONE_END (name);
+}
+
+FORM (NEWMANY_FFNet_createIrisExample, U"Create iris example", U"Create iris example...") {
+	LABEL (U"", U"For the feedforward neural net we need to know the:")
+	INTEGERVAR (numberOfUnits1, U"Number of units in hidden layer 1", U"0")
+	INTEGERVAR (numberOfUnits2, U"Number of units in hidden layer 2", U"0")
+	OK
+DO
+	autoCollection result = FFNet_createIrisExample (numberOfUnits1, numberOfUnits2);
+	praat_new (result.move());
+END }
+
+FORM (NEW1_FFNet_create_linearOutputs, U"Create FFNet", U"Create FFNet (linear outputs)...") {
+	WORDVAR (name, U"Name", U"4-3")
+	NATURALVAR (numberOfInputs, U"Number of inputs", U"4")
+	NATURALVAR (numberOfOutputs, U"Number of outputs", U"3")
+	INTEGERVAR (numberOfUnits1, U"Number of units in hidden layer 1", U"0")
+	INTEGERVAR (numberOfUnits2, U"Number of units in hidden layer 2", U"0")
+	OK
+DO
+	CREATE_ONE
+		autoFFNet result = FFNet_create (numberOfInputs, numberOfUnits1, numberOfUnits2, numberOfOutputs, true);
+	CREATE_ONE_END (name);
+}
+
+/**************** New PatternList ***************************/
+
+FORM (NEW1_PatternList_create, U"Create PatternList", nullptr) {
+	WORDVAR (name, U"Name", U"1x1")
+	NATURALVAR (patternDimension, U"Dimension of a pattern", U"1")
+	NATURALVAR (numberOfPatterns, U"Number of patterns", U"1")
+	OK
+DO
+	CREATE_ONE
+		autoPatternList result = PatternList_create (numberOfPatterns, patternDimension);
+	CREATE_ONE_END (name);
+}
+	
+/**************** New Categories ***************************/
+	
+FORM (NEW1_Categories_create, U"Create Categories", nullptr) {
+	WORDVAR (name, U"Name", U"empty")
+	OK
+DO
+	CREATE_ONE
+		autoCategories result = Categories_create ();
+	CREATE_ONE_END (name);
+}
+
+DIRECT (HELP_FFNet_help)  {
+	HELP (U"Feedforward neural networks")
+}
+		
+
+DIRECT (GRAPHICS_FFNet_drawTopology) {
+	GRAPHICS_EACH (FFNet)
+		FFNet_drawTopology (me, GRAPHICS);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_FFNet_drawWeights, U"FFNet: Draw weights", U"FFNet: Draw weights...") {
+	NATURALVAR (layer, U"Layer number", U"1")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (FFNet)
+		FFNet_drawWeights (me, GRAPHICS, layer, garnish);
+	GRAPHICS_EACH_END
+}
+	
+FORM (GRAPHICS_FFNet_drawWeightsToLayer, U"FFNet: Draw weights to layer", nullptr) {
+	LABEL (U"", U"Warning: Disapproved. Use \"Draw weights..\" instead.")
+	NATURALVAR (layer, U"Layer number", U"1")
+	RADIOVAR (scale, U"Scale", 1)
+		RADIOBUTTON (U"by maximum of all weights to layer")
+		RADIOBUTTON (U"by maximum weight from 'from-unit'")
+		RADIOBUTTON (U"by maximum weight to 'to-unit'")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (FFNet)
+		FFNet_drawWeightsToLayer (me, GRAPHICS, layer, scale, garnish);
+	GRAPHICS_EACH_END
 }
 
-static void FFNet_create_checkCommonFields_inputOutput (UiForm dia, long *numberOfInputs, long *numberOfOutputs) {
-	*numberOfInputs = GET_INTEGER (U"Number of inputs");
-	*numberOfOutputs = GET_INTEGER (U"Number of outputs");
+FORM (GRAPHICS_FFNet_drawCostHistory, U"FFNet: Draw cost history", U"FFNet: Draw cost history...") {
+	INTEGERVAR (fromIteration, U"left Iteration_range", U"0")
+	INTEGERVAR (toIteration, U"right Iteration_range", U"0")
+	REALVAR (fromCost, U"left Cost_range", U"0.0")
+	REALVAR (toCost, U"right Cost_range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (FFNet)
+		FFNet_drawCostHistory (me, GRAPHICS, fromIteration, toIteration, fromCost, toCost, garnish);
+	GRAPHICS_EACH_END
 }
 
-static void FFNet_create_addCommonFields_hidden (UiForm dia) {
-	INTEGER (U"Number of units in hidden layer 1", U"0")
-	INTEGER (U"Number of units in hidden layer 2", U"0")
+DIRECT (INTEGER_FFNet_getNumberOfLayers) {
+	INTEGER_ONE (FFNet)
+		long result = my nLayers;
+	INTEGER_ONE_END (U" layer", (my nLayers > 1 ? U"s" : U""))
 }
 
-static void FFNet_create_checkCommonFields_hidden (UiForm dia, 	long *numberOfHidden1, long *numberOfHidden2) {
-	*numberOfHidden1 = GET_INTEGER (U"Number of units in hidden layer 1");
-	*numberOfHidden2 = GET_INTEGER (U"Number of units in hidden layer 2");
-	if (*numberOfHidden1 < 0 || *numberOfHidden2 < 0) {
-		Melder_throw (U"The number of units in a hidden layer must be geater equal zero");
-	}
+DIRECT (INTEGER_FFNet_getNumberOfOutputs) {
+	INTEGER_ONE (FFNet)
+		long result = my nUnitsInLayer[my nLayers];
+	INTEGER_ONE_END (U" units")
 }
 
-static void FFNet_create_addCommonFields (UiForm dia) {
-	FFNet_create_addCommonFields_inputOutput (dia);
-	FFNet_create_addCommonFields_hidden (dia);
+
+FORM (INTEGER_FFNet_getNumberOfHiddenUnits, U"FFNet: Get number of hidden units", U"FFNet: Get number of hidden units...") {
+	NATURALVAR (layer, U"Hidden layer number", U"1")
+	OK
+DO
+	INTEGER_ONE (FFNet)
+		long result = layer > 0 && layer <= my nLayers - 1 ? my nUnitsInLayer[layer] : 0;
+	INTEGER_ONE_END (U" units")
 }
 
-static void FFNet_create_checkCommonFields (UiForm dia, long *numberOfInputs, long *numberOfOutputs,
-        long *numberOfHidden1, long *numberOfHidden2) {
-	FFNet_create_checkCommonFields_inputOutput (dia, numberOfInputs, numberOfOutputs);
-	FFNet_create_checkCommonFields_hidden (dia, numberOfHidden1, numberOfHidden2);
+DIRECT (INTEGER_FFNet_getNumberOfInputs) {
+	INTEGER_ONE (FFNet)
+		long result = my nUnitsInLayer[0];
+	INTEGER_ONE_END (U" units")
 }
 
-FORM (FFNet_create, U"Create FFNet", U"Create FFNet...")
-	WORD (U"Name", U"4-3")
-	FFNet_create_addCommonFields (dia);
+FORM (INTEGER_FFNet_getNumberOfHiddenWeights, U"FFNet: Get number of hidden weights", U"FFNet: Get number of hidden weights...") {
+	NATURALVAR (layer, U"Hidden layer number", U"1")
 	OK
 DO
-	long numberOfInputs, numberOfOutputs, numberOfHidden1, numberOfHidden2;
-	FFNet_create_checkCommonFields (dia, &numberOfInputs, &numberOfOutputs, &numberOfHidden1, &numberOfHidden2);
-	autoFFNet thee = FFNet_create (numberOfInputs, numberOfHidden1, numberOfHidden2, numberOfOutputs, false);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	INTEGER_ONE (FFNet)
+		long result = (layer > 0 && layer <= my nLayers - 1) ? (my nUnitsInLayer[layer] * (my nUnitsInLayer[layer - 1] + 1)) : 0;
+	INTEGER_ONE_END (U" weights (including biases)")
+}
+	
+DIRECT (INTEGER_FFNet_getNumberOfOutputWeights) {
+	INTEGER_ONE (FFNet)
+		long result = my nUnitsInLayer[my nLayers] * (my nUnitsInLayer[my nLayers - 1] + 1);
+	INTEGER_ONE_END (U" weights");
+}
 
-FORM (FFNet_create_linearOutputs, U"Create FFNet", U"Create FFNet (linear outputs)...")
-	WORD (U"Name", U"4-3L")
-	FFNet_create_addCommonFields (dia);
+FORM (INFO_FFNet_getCategoryOfOutputUnit, U"FFNet: Get category of output unit", nullptr) {
+	NATURALVAR (outputUnit, U"Output unit", U"1")
 	OK
 DO
-	long numberOfInputs, numberOfOutputs, numberOfHidden1, numberOfHidden2;
-	FFNet_create_checkCommonFields (dia, &numberOfInputs, &numberOfOutputs, &numberOfHidden1, &numberOfHidden2);
-	autoFFNet thee = FFNet_create (numberOfInputs, numberOfHidden1, numberOfHidden2, numberOfOutputs, true);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	STRING_ONE (FFNet)
+		const char32 *result = FFNet_getCategoryOfOutputUnit (me, outputUnit);
+	STRING_ONE_END
+}
 
-FORM (FFNet_createIrisExample, U"Create iris example", U"Create iris example...")
-	LABEL (U"", U"For the feedforward neural net we need to know the:")
-	FFNet_create_addCommonFields_hidden (dia);
-	OK
-DO
-	long numberOfHidden1, numberOfHidden2;
-	FFNet_create_checkCommonFields_hidden (dia, &numberOfHidden1, &numberOfHidden2);
-	autoCollection thee = FFNet_createIrisExample (numberOfHidden1, numberOfHidden2);
-	praat_new (thee.move());
-END
-
-DIRECT (FFNet_getNumberOfInputs)
-	LOOP {
-		iam (FFNet);
-		Melder_information (my nUnitsInLayer[0], U" units");
-	}
-END
-
-DIRECT (FFNet_getNumberOfOutputs)
-	LOOP {
-		iam (FFNet);
-		Melder_information (my nUnitsInLayer[my nLayers], U" units");
-	}
-END
-
-FORM (FFNet_getNumberOfHiddenUnits, U"FFNet: Get number of hidden units", U"FFNet: Get number of hidden units...")
-	NATURAL (U"Hidden layer number", U"1")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		long layerNumber = GET_INTEGER (U"Hidden layer number");
-		long numberOfUnits = 0;
-		if (layerNumber > 0 && layerNumber <= my nLayers - 1) {
-			numberOfUnits = my nUnitsInLayer[layerNumber];
-		}
-		Melder_information (numberOfUnits, U" units");
-	}
-END
-
-FORM (FFNet_getCategoryOfOutputUnit, U"FFNet: Get category of output unit", nullptr)
-	NATURAL (U"Output unit", U"1")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		long unit = GET_INTEGER (U"Output unit");
-		if (unit > my outputCategories->size) {
-			Melder_throw (U"Output unit cannot be larger than ", my outputCategories->size, U".");
-		}
-		SimpleString ss = my outputCategories->at [unit];
-		Melder_information (ss -> string);
-	}
-END
-
-FORM (FFNet_getOutputUnitOfCategory, U"FFNet: Get output unit of category", nullptr)
-	SENTENCE (U"Category", U"u")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		char32 *category = GET_STRING (U"Category");
-		long index = 0;
-		for (long i = 1; i <= my outputCategories->size; i ++) {
-			SimpleString s = my outputCategories->at [i];
-			if (Melder_equ (s -> string, category)) {
-				index = i;
-				break;
-			}
-		}
-		Melder_information (index);
-	}
-END
-
-FORM (FFNet_getBias, U"FFNet: Get bias", nullptr)
-	NATURAL (U"Layer", U"1")
-	NATURAL (U"Unit", U"1")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		long layer = GET_INTEGER (U"Layer");
-		long unit = GET_INTEGER (U"Unit");
-		double bias = FFNet_getBias (me, layer, unit);
-		Melder_information (bias, U"(bias for unit ", unit, U"in layer ", layer, U").");
-	}
-END
-
-FORM (FFNet_setBias, U"FFNet: Set bias", nullptr)
-	NATURAL (U"Layer", U"1")
-	NATURAL (U"Unit", U"1")
-	REAL (U"Value", U"0.0")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		FFNet_setBias (me, GET_INTEGER (U"Layer"), GET_INTEGER (U"Unit"), GET_REAL (U"Value"));
-	}
-END
-
-FORM (FFNet_getWeight, U"FFNet: Get weight", nullptr)
-	NATURAL (U"Layer", U"1")
-	NATURAL (U"Unit", U"1")
-	NATURAL (U"Unit from", U"1")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		long layer = GET_INTEGER (U"Layer");
-		long unit = GET_INTEGER (U"Unit");
-		long unitf = GET_INTEGER (U"Unit from");
-		double w = FFNet_getWeight (me, layer, unit, unitf);
-		Melder_information (w, U"(weight between unit ", unit,
-			U" in layer ", layer, U", and unit ", unitf, U"in layer ",
-			layer - 1);
-	}
-END
-
-FORM (FFNet_setWeight, U"FFNet: Set weight", nullptr)
-	NATURAL (U"Layer", U"1")
-	NATURAL (U"Unit", U"1")
-	NATURAL (U"Unit (from)", U"1")
-	REAL (U"Value", U"0.0")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		long layer = GET_INTEGER (U"Layer");
-		long unit = GET_INTEGER (U"Unit");
-		long unitf = GET_INTEGER (U"Unit (from)");
-		FFNet_setWeight (me, layer, unit, unitf, GET_REAL (U"Value"));
-	}
-END
-
-FORM (FFNet_getNumberOfHiddenWeights, U"FFNet: Get number of hidden weights", U"FFNet: Get number of hidden weights...")
-	NATURAL (U"Hidden layer number", U"1")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		long layerNumber = GET_INTEGER (U"Hidden layer number");
-		long numberOfWeights = 0;
-		if (layerNumber > 0 && layerNumber <= my nLayers - 1) {
-			numberOfWeights = my nUnitsInLayer[layerNumber] * (my nUnitsInLayer[layerNumber - 1] + 1);
-		}
-		Melder_information (numberOfWeights, U" weights (including biases)");
-	}
-END
-
-DIRECT (FFNet_getNumberOfOutputWeights)
-	LOOP {
-		iam (FFNet);
-		Melder_information (my nUnitsInLayer[my nLayers] * (my nUnitsInLayer[my nLayers - 1] + 1),
-		U" weights");
-	}
-END
+FORM (INTEGER_FFNet_getOutputUnitOfCategory, U"FFNet: Get output unit of category", nullptr) {
+	SENTENCEVAR (category, U"Category", U"u")
+	OK
+DO
+	INTEGER_ONE (FFNet)
+		long result = FFNet_getOutputUnitOfCategory (me, category);
+	INTEGER_ONE_END (U" (output unit)")
+}
 
-/**************** New PatternList ***************************/
 
-FORM (PatternList_create, U"Create PatternList", nullptr)
-	WORD (U"Name", U"1x1")
-	NATURAL (U"Dimension of a pattern", U"1")
-	NATURAL (U"Number of patterns", U"1")
+FORM (REAL_FFNet_getBias, U"FFNet: Get bias", nullptr) {
+	NATURALVAR (layer, U"Layer", U"1")
+	NATURALVAR (unit, U"Unit", U"1")
 	OK
 DO
-	praat_new (PatternList_create (GET_INTEGER (U"Number of patterns"),
-		GET_INTEGER (U"Dimension of a pattern")), GET_STRING (U"Name"));
-END
+	NUMBER_ONE (FFNet)
+		double result = FFNet_getBias (me, layer, unit);
+	NUMBER_ONE_END (U" (bias)")
+}
 
-/**************** New Categories ***************************/
 
-FORM (Categories_create, U"Create Categories", nullptr)
-	WORD (U"Name", U"empty")
+FORM (REAL_FFNet_getWeight, U"FFNet: Get weight", nullptr) {
+	NATURALVAR (layer, U"Layer", U"1")
+	NATURALVAR (unitTo, U"Unit", U"1")
+	NATURALVAR (unitFrom, U"Unit from", U"1")
 	OK
 DO
-	autoCategories thee = Categories_create ();
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	NUMBER_ONE (FFNet)
+		double result = FFNet_getWeight (me, layer, unitTo, unitFrom);
+	NUMBER_ONE_END (U"(weight between unit ", unitTo, U" in layer ", layer, U", and unit ", unitFrom, U"in layer ", layer - 1, U")")
+}
 
-DIRECT (FFNet_help) Melder_help (U"Feedforward neural networks"); END
+DIRECT (REAL_FFNet_getMinimum) {
+	NUMBER_ONE (FFNet)
+		double result = FFNet_getMinimum (me);
+	NUMBER_ONE_END (U" (minimum)");
+}
 
-DIRECT (FFNet_getMinimum)
-	LOOP {
-		iam (FFNet);
-		Melder_information (FFNet_getMinimum (me));
-	}
-END
+FORM (MODIFY_FFNet_setBias, U"FFNet: Set bias", nullptr) {
+	NATURALVAR (layer, U"Layer", U"1")
+	NATURALVAR (unit, U"Unit", U"1")
+	REALVAR (value, U"Value", U"0.0")
+	OK
+DO
+	MODIFY_EACH (FFNet)
+		FFNet_setBias (me, layer, unit, value);
+	MODIFY_EACH_END 
+}
+
+FORM (MODIFY_FFNet_setWeight, U"FFNet: Set weight", nullptr) {
+	NATURALVAR (layer, U"Layer", U"1")
+	NATURALVAR (unitTo, U"Unit", U"1")
+	NATURALVAR (unitFrom, U"Unit (from)", U"1")
+	REALVAR (value, U"Value", U"0.0")
+	OK
+DO
+	MODIFY_EACH (FFNet)
+		FFNet_setWeight (me, layer, unitTo, unitFrom, value);
+	MODIFY_EACH_END
+}
 
-FORM (FFNet_reset, U"FFNet: Reset", U"FFNet: Reset...")
+FORM (MODIFY_FFNet_reset, U"FFNet: Reset", U"FFNet: Reset...") {
 	LABEL (U"", U"Warning: this command destroys all previous learning.")
 	LABEL (U"", U"New weights will be randomly chosen from the interval [-range, +range].")
-	POSITIVE (U"Range", U"0.1")
+	POSITIVEVAR (range, U"Range", U"0.1")
 	OK
 DO
-	LOOP {
-		iam (FFNet);
-		FFNet_reset (me, GET_REAL (U"Range"));
-		praat_dataChanged (OBJECT);
-	}
-END
-
-FORM (FFNet_selectBiasesInLayer, U"FFNet: Select biases", U"FFNet: Select biases...")
+	MODIFY_EACH (FFNet)
+		FFNet_reset (me, range);
+	MODIFY_EACH_END
+}
+	
+FORM (MODIFY_FFNet_selectBiasesInLayer, U"FFNet: Select biases", U"FFNet: Select biases...") {
 	LABEL (U"", U"WARNING: This command induces very specific behaviour ")
 	LABEL (U"", U"during a following learning phase.")
-	NATURAL (U"Layer number", U"1")
+	NATURALVAR (layer, U"Layer number", U"1")
 	OK
 DO
-	LOOP {
-		iam (FFNet);
-		FFNet_selectBiasesInLayer (me, GET_INTEGER (U"Layer number"));
-		praat_dataChanged (OBJECT);
-	}
-END
-
-DIRECT (FFNet_selectAllWeights)
-	LOOP {
-		iam (FFNet);
+	MODIFY_EACH (FFNet)
+		FFNet_selectBiasesInLayer (me, layer);
+	MODIFY_EACH_END
+}
+	
+DIRECT (MODIFY_FFNet_selectAllWeights) {
+	MODIFY_EACH (FFNet)
 		FFNet_selectAllWeights (me);
-		praat_dataChanged (me);
-	}
-END
-
-DIRECT (FFNet_drawTopology)
-	autoPraatPicture picture;
-	LOOP {
-		iam (FFNet);
-		FFNet_drawTopology (me, GRAPHICS);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (FFNet_drawWeightsToLayer, U"FFNet: Draw weights to layer", nullptr)
-	LABEL (U"", U"Warning: Disapproved. Use \"Draw weights..\" instead.")
-	NATURAL (U"Layer number", U"1")
-	RADIO (U"Scale", 1)
-		RADIOBUTTON (U"by maximum of all weights to layer")
-		RADIOBUTTON (U"by maximum weight from 'from-unit'")
-		RADIOBUTTON (U"by maximum weight to 'to-unit'")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FFNet);
-		FFNet_drawWeightsToLayer (me, GRAPHICS, GET_INTEGER (U"Layer number"),
-			GET_INTEGER (U"Scale"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (FFNet_drawWeights, U"FFNet: Draw weights", U"FFNet: Draw weights...")
-	NATURAL (U"Layer number", U"1")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FFNet);
-		FFNet_drawWeights (me, GRAPHICS, GET_INTEGER (U"Layer number"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (FFNet_drawCostHistory, U"FFNet: Draw cost history", U"FFNet: Draw cost history...")
-	INTEGER (U"left Iteration_range", U"0")
-	INTEGER (U"right Iteration_range", U"0")
-	REAL (U"left Cost_range", U"0.0")
-	REAL (U"right Cost_range", U"0.0")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FFNet);
-		FFNet_drawCostHistory (me, GRAPHICS, GET_INTEGER (U"left Iteration_range"),
-			GET_INTEGER (U"right Iteration_range"), GET_REAL (U"left Cost_range"), GET_REAL (U"right Cost_range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (FFNet_extractWeights, U"FFNet: Extract weights", U"FFNet: Extract weights...")
-	NATURAL (U"Layer number", U"1")
-	OK
-DO
-	LOOP {
-		iam (FFNet);
-		autoTableOfReal thee = FFNet_extractWeights (me, GET_INTEGER (U"Layer number"));
-		praat_new (thee.move());
-	}
-END
-
-FORM (FFNet_weightsToMatrix, U"FFNet: Weights to Matrix ", nullptr)
+FORM (NEW_FFNet_extractWeights, U"FFNet: Extract weights", U"FFNet: Extract weights...") {
+	NATURALVAR (layer, U"Layer number", U"1")
+	OK
+DO
+	CONVERT_EACH (FFNet)
+		autoTableOfReal result = FFNet_extractWeights (me, layer);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_FFNet_weightsToMatrix, U"FFNet: Weights to Matrix ", nullptr) {
 	LABEL (U"", U"Warning: Use \"Extract weights..\" instead.")
-	NATURAL (U"Layer number", U"1")
+	NATURALVAR (layer, U"Layer number", U"1")
 	OK
 DO
-	LOOP {
-		iam (FFNet);
-		autoMatrix thee = FFNet_weightsToMatrix (me, GET_INTEGER (U"Layer number"), false);
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (FFNet)
+		autoMatrix result = FFNet_weightsToMatrix (me, layer, false);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (HINT_hint_FFNet_and_PatternList_classify) {
+	Melder_information (U"You can use the FFNet as a classifier by selecting a\n"
+	"FFNet and a PatternList together and choosing \"To Categories...\".");
+END }
+	
+DIRECT (HINT_hint_FFNet_and_PatternList_and_Categories_learn) {
+	Melder_information (U"You can teach a FFNet to classify by selecting a\n"
+	"FFNet, a PatternList and a Categories together and choosing \"Learn...\".");
+END }
 
-/******************* FFNet && ActivationList *************************************/
+/******************* FFNet && ActivationList ******************************************/
 
-FORM (FFNet_ActivationList_to_Categories, U"FFNet & ActivationList: To Categories", 0)
-	RADIO (U"Kind of labeling", 1)
-	RADIOBUTTON (U"Winner-takes-all")
-	RADIOBUTTON (U"Stochastic")
+FORM (NEW1_FFNet_ActivationList_to_Categories, U"FFNet & ActivationList: To Categories", 0) {
+	RADIOVAR (categorizationgMethod, U"Categorization method", 1)
+		RADIOBUTTON (U"Winner-takes-all")
+		RADIOBUTTON (U"Stochastic")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	ActivationList thee = FIRST (ActivationList);
-	autoCategories him = FFNet_ActivationList_to_Categories (me, thee, GET_INTEGER (U"Kind of labeling"));
-	praat_new (him.move(), my name, U"_", thy name);
-END
+	CONVERT_TWO (FFNet, ActivationList)
+		autoCategories result = FFNet_ActivationList_to_Categories (me, you, categorizationgMethod);
+	CONVERT_TWO_END (my name, U"_", you -> name)
+}
 
 /******************* FFNet && Eigen ******************************************/
 
-FORM (FFNet_Eigen_drawIntersection, U"FFnet & Eigen: Draw intersection", 0)
-	INTEGER (U"X-component", U"1")
-	INTEGER (U"Y-component", U"2")
-	REAL (U"xmin", U"0.0")
-	REAL (U"xmax", U"0.0")
-	REAL (U"ymin", U"0.0")
-	REAL (U"ymax", U"0.0")
-	OK
-DO
-	FFNet me = FIRST (FFNet);
-	Eigen thee = FIRST (Eigen);
-	autoPraatPicture picture;
-	long pcx = GET_INTEGER (U"X-component");
-	long pcy = GET_INTEGER (U"Y-component");
-	REQUIRE (pcx != 0 && pcy != 0, U"X and Y component must differ from 0.")
-	FFNet_Eigen_drawIntersection (me, thee, GRAPHICS, pcx, pcy, GET_REAL (U"xmin"), GET_REAL (U"xmax"),
-		GET_REAL (U"ymin"), GET_REAL (U"ymax"));
-END
-
-FORM (FFNet_PCA_drawDecisionPlaneInEigenspace, U"FFNet & PCA: Draw decision plane", U"")
-	NATURAL (U"Unit number", U"1")
-	NATURAL (U"Layer number", U"1")
-	NATURAL (U"Horizontal eigenvector number", U"1")
-	NATURAL (U"Vertical eigenvector number", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	OK
-DO
-	autoPraatPicture picture;
-	FFNet me = FIRST (FFNet);
-	PCA thee = FIRST (PCA);
-	FFNet_Eigen_drawDecisionPlaneInEigenspace (me, thee,
-		GRAPHICS, GET_INTEGER (U"Unit number"), GET_INTEGER (U"Layer number"),
-		GET_INTEGER (U"Horizontal eigenvector number"),
-		GET_INTEGER (U"Vertical eigenvector number"), GET_REAL (U"left Horizontal range"),
-		GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"),
-		GET_REAL (U"right Vertical range"));
-END
+FORM (GRAPHICS_FFNet_Eigen_drawIntersection, U"FFnet & Eigen: Draw intersection", 0) {
+	NATURALVAR (pcx, U"X-component", U"1")
+	NATURALVAR (pcy, U"Y-component", U"2")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0")
+	OK
+DO
+	GRAPHICS_TWO (FFNet, Eigen)
+		FFNet_Eigen_drawIntersection (me, you, GRAPHICS, pcx, pcy, xmin, xmax, ymin, ymax);
+	GRAPHICS_TWO_END
+} 
 
 /************************* FFNet && Categories **********************************/
 
-DIRECT (FFNet_Categories_to_ActivationList)
-	FFNet me = FIRST (FFNet);
-	Categories thee = FIRST (Categories);
-	autoActivationList him = FFNet_Categories_to_ActivationList (me, thee);
-	praat_new (him.move(), my name);
-END
+DIRECT (NEW1_FFNet_Categories_to_ActivationList) {
+	CONVERT_TWO (FFNet, Categories)
+		autoActivationList result = FFNet_Categories_to_ActivationList (me, you);
+	CONVERT_TWO_END (my name);
+}
 
 /************************* FFNet && Matrix **********************************/
 
-FORM (FFNet_weightsFromMatrix, U"Replace weights by values from Matrix", 0)
-	NATURAL (U"Layer", U"1")
+FORM (NEW1_FFNet_weightsFromMatrix, U"Replace weights by values from Matrix", nullptr) {
+	NATURALVAR (layer, U"Layer", U"1")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	Matrix thee = FIRST (Matrix);
-	autoFFNet him = FFNet_weightsFromMatrix (me, thee, GET_INTEGER (U"Layer"));
-	praat_new (him.move(), my name);
-END
+	CONVERT_TWO (FFNet, Matrix)
+		autoFFNet result = FFNet_weightsFromMatrix (me, you, layer);
+	CONVERT_TWO_END (my name);
+}
 
 /************************* FFNet && PatternList **********************************/
 
-FORM (FFNet_PatternList_drawActivation, U"Draw an activation", 0)
-	NATURAL (U"PatternList (row) number", U"1");
+FORM (GRAPHICS_FFNet_PatternList_drawActivation, U"Draw an activation", nullptr) {
+	NATURALVAR (row, U"PatternList (row) number", U"1");
 	OK
 DO
-	autoPraatPicture picture;
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	FFNet_PatternList_drawActivation (me, thee, GRAPHICS, GET_INTEGER (U"PatternList"));
-END
+	GRAPHICS_TWO (FFNet, PatternList)
+		FFNet_PatternList_drawActivation (me, you, GRAPHICS, row);
+	GRAPHICS_TWO_END
+}
 
-FORM (FFNet_PatternList_to_ActivationList, U"To activations in layer", 0)
-	NATURAL (U"Layer", U"1")
+FORM (NEW1_FFNet_PatternList_to_Categories, U"FFNet & PatternList: To Categories", U"FFNet & PatternList: To Categories...") {
+	RADIOVAR (categorizationgMethod, U"Categorization method", 1)
+		RADIOBUTTON (U"Winner-takes-all")
+		RADIOBUTTON (U"Stochastic")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	autoActivationList him = FFNet_PatternList_to_ActivationList (me, thee, GET_INTEGER (U"Layer"));
-	praat_new (him.move(), my name, U"_", thy name);
-END
-
-DIRECT (hint_FFNet_and_PatternList_classify)
-	Melder_information (U"You can use the FFNet as a classifier by selecting a\n"
-		"FFNet and a PatternList together and choosing \"To Categories...\".");
-END
-
-DIRECT (hint_FFNet_and_PatternList_and_Categories_learn)
-	Melder_information (U"You can teach a FFNet to classify by selecting a\n"
-		"FFNet, a PatternList and a Categories together and choosing \"Learn...\".");
-END
+	GRAPHICS_TWO (FFNet, PatternList)
+		autoCategories result = FFNet_PatternList_to_Categories (me, you, categorizationgMethod);
+	CONVERT_TWO_END (my name, U"_", you -> name)
+}
 
-FORM (FFNet_PatternList_to_Categories, U"FFNet & PatternList: To Categories", U"FFNet & PatternList: To Categories...")
-	RADIO (U"Determine output category as", 1)
-		RADIOBUTTON (U"Winner-takes-all")
-		RADIOBUTTON (U"Stochastic")
+FORM (NEW1_FFNet_PatternList_to_ActivationList, U"To activations in layer", nullptr) {
+	NATURALVAR (layer, U"Layer", U"1")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	autoCategories him = FFNet_PatternList_to_Categories (me, thee, GET_INTEGER (U"Determine output category as"));
-	praat_new (him.move(), my name, U"_", thy name);
-END
+	GRAPHICS_TWO (FFNet, PatternList)
+		autoActivationList result = FFNet_PatternList_to_ActivationList (me, you, layer);
+	CONVERT_TWO_END (my name, U"_", you -> name)
+}
 
-/*********** FFNet PatternList ActivationList **********************************/
+/*********** FFNet & PatternList & ActivationList **********************************/
 
-FORM (FFNet_PatternList_ActivationList_getCosts_total, U"FFNet & PatternList & ActivationList: Get total costs", U"FFNet & PatternList & ActivationList: Get total costs...")
-	RADIO (U"Cost function", 1)
-	RADIOBUTTON (U"Minimum-squared-error")
-	RADIOBUTTON (U"Minimum-cross-entropy")
+FORM (REAL_FFNet_PatternList_ActivationList_getTotalCosts, U"FFNet & PatternList & ActivationList: Get total costs", U"FFNet & PatternList & ActivationList: Get total costs...") {
+	RADIOVAR (costFunctionType, U"Cost function", 1)
+		RADIOBUTTON (U"Minimum-squared-error")
+		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	ActivationList him = FIRST (ActivationList);
-	Melder_information (FFNet_PatternList_ActivationList_getCosts_total (me, thee, him, GET_INTEGER (U"Cost function")));
-END
+	NUMBER_THREE (FFNet, PatternList, ActivationList)
+		double result = FFNet_PatternList_ActivationList_getCosts_total (me, you, him, costFunctionType);
+	NUMBER_THREE_END (U"")
+}
 
-FORM (FFNet_PatternList_ActivationList_getCosts_average, U"FFNet & PatternList & ActivationList: Get average costs", U"FFNet & PatternList & ActivationList: Get average costs...")
-	RADIO (U"Cost function", 1)
-	RADIOBUTTON (U"Minimum-squared-error")
-	RADIOBUTTON (U"Minimum-cross-entropy")
+FORM (REAL_FFNet_PatternList_ActivationList_getAverageCosts, U"FFNet & PatternList & ActivationList: Get average costs", U"FFNet & PatternList & ActivationList: Get average costs...") {
+	RADIOVAR (costFunctionType, U"Cost function", 1)
+		RADIOBUTTON (U"Minimum-squared-error")
+		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	ActivationList him = FIRST (ActivationList);
-	Melder_information (FFNet_PatternList_ActivationList_getCosts_average (me, thee, him, GET_INTEGER (U"Cost function")));
-END
+	NUMBER_THREE (FFNet, PatternList, ActivationList)
+		double result = FFNet_PatternList_ActivationList_getCosts_average (me, you, him, costFunctionType);
+	NUMBER_THREE_END (U"")
+}
 
-FORM (FFNet_PatternList_ActivationList_learnSD, U"FFNet & PatternList & ActivationList: Learn slow", 0)
-	NATURAL (U"Maximum number of epochs", U"100")
-	POSITIVE (U"Tolerance of minimizer", U"1e-7")
-	LABEL (U"Specifics", U"Specific for this minimization")
-	POSITIVE (U"Learning rate", U"0.1")
-	REAL (U"Momentum", U"0.9")
-	RADIO (U"Cost function", 1)
+FORM (MODIFY_FFNet_PatternList_ActivationList_learn, U"FFNet & PatternList & ActivationList: Learn", nullptr) {
+	// NATURAL (U"Layer", U"1")
+	NATURALVAR (maximumNumberOfEpochs, U"Maximum number of epochs", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"1e-7")
+	RADIOVAR (costFunctionType, U"Cost function", 1)
 		RADIOBUTTON (U"Minimum-squared-error")
 		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	ActivationList him = FIRST (ActivationList);
-	return FFNet_PatternList_ActivationList_learnSD (me, thee, him, GET_INTEGER (U"Maximum number of epochs"),
-			GET_REAL (U"Tolerance of minimizer"), GET_REAL (U"Learning rate"), GET_REAL (U"Momentum"), GET_INTEGER (U"Cost function"));
-END
+	MODIFY_FIRST_OF_THREE (FFNet, PatternList, ActivationList)
+		FFNet_PatternList_ActivationList_learnSM (me, you, him, maximumNumberOfEpochs, tolerance, costFunctionType);
+	MODIFY_FIRST_OF_THREE_END	
+}
+	
 
-FORM (FFNet_PatternList_ActivationList_learnSM, U"FFNet & PatternList & ActivationList: Learn", 0)
-	NATURAL (U"Maximum number of epochs", U"100")
-	POSITIVE (U"Tolerance of minimizer", U"1e-7")
-	RADIO (U"Cost function", 1)
+FORM (MODIFY_FFNet_PatternList_ActivationList_learnSlow, U"FFNet & PatternList & ActivationList: Learn slow", nullptr) {
+	// NATURAL (U"Layer", U"1")
+	NATURALVAR (maximumNumberOfEpochs, U"Maximum number of epochs", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"1e-7")
+	LABEL (U"Specifics", U"Specific for this minimization")
+	POSITIVEVAR (learningRate, U"Learning rate", U"0.1")
+	REALVAR (momentum, U"Momentum", U"0.9")
+	RADIOVAR (costFunctionType, U"Cost function", 1)
 		RADIOBUTTON (U"Minimum-squared-error")
 		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	ActivationList him = FIRST (ActivationList);
-	return FFNet_PatternList_ActivationList_learnSM (me, thee, him, GET_INTEGER (U"Maximum number of epochs"),
-		GET_REAL (U"Tolerance of minimizer"), GET_INTEGER (U"Cost function"));
-END
+	MODIFY_FIRST_OF_THREE (FFNet, PatternList, ActivationList)
+		FFNet_PatternList_ActivationList_learnSD (me, you, him, maximumNumberOfEpochs, tolerance, learningRate, momentum, costFunctionType);
+	MODIFY_FIRST_OF_THREE_END	
+}
 
-/*********** FFNet PatternList Categories **********************************/
+/*********** FFNet & PatternList & Categories **********************************/
 
-FORM (FFNet_PatternList_Categories_getCosts_total, U"FFNet & PatternList & Categories: Get total costs", U"FFNet & PatternList & Categories: Get total costs...")
-	RADIO (U"Cost function", 1)
+FORM (REAL_FFNet_PatternList_Categories_getTotalCosts, U"FFNet & PatternList & Categories: Get total costs", U"FFNet & PatternList & Categories: Get total costs...") {
+	RADIOVAR (costFunctionType, U"Cost function", 1)
 		RADIOBUTTON (U"Minimum-squared-error")
 		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	Categories him = FIRST (Categories);
-	Melder_information (FFNet_PatternList_Categories_getCosts_total (me, thee, him,
-		GET_INTEGER (U"Cost function")));
-END
+	NUMBER_THREE (FFNet, PatternList, Categories)
+		double result = FFNet_PatternList_Categories_getCosts_total (me, you, him, costFunctionType);
+	NUMBER_THREE_END (U" (total costs)")
+}
 
-FORM (FFNet_PatternList_Categories_getCosts_average, U"FFNet & PatternList & Categories: Get average costs", U"FFNet & PatternList & Categories: Get average costs...")
-	RADIO (U"Cost function", 1)
+FORM (REAL_FFNet_PatternList_Categories_getAverageCosts, U"FFNet & PatternList & Categories: Get average costs", U"FFNet & PatternList & Categories: Get average costs...") {
+	RADIOVAR (costFunctionType, U"Cost function", 1)
 		RADIOBUTTON (U"Minimum-squared-error")
 		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	Categories him = FIRST (Categories);
-	Melder_information (FFNet_PatternList_Categories_getCosts_average (me, thee, him,
-		GET_INTEGER (U"Cost function")));
-END
-
-FORM (PatternList_Categories_to_FFNet, U"PatternList & Categories: To FFNet", U"PatternList & Categories: To FFNet...")
-	INTEGER (U"Number of units in hidden layer 1", U"0")
-	INTEGER (U"Number of units in hidden layer 2", U"0")
-	OK
-DO
-	PatternList me = FIRST (PatternList);
-	Categories thee = FIRST (Categories);
-	long nHidden1 = GET_INTEGER (U"Number of units in hidden layer 1");
-	long nHidden2 = GET_INTEGER (U"Number of units in hidden layer 2");
-
-	if (nHidden1 < 1) {
-		nHidden1 = 0;
-	}
-	if (nHidden2 < 1) {
-		nHidden2 = 0;
-	}
-	autoCategories uniq = Categories_selectUniqueItems (thee);
-	long numberOfOutputs = uniq->size;
-	if (numberOfOutputs < 1) Melder_throw (U"There are not enough categories in the Categories.\n"
-		U"Please try again with more categories in the Categories.");
-
-	autoFFNet ffnet = FFNet_create (my nx, nHidden1, nHidden2, numberOfOutputs, false);
-	FFNet_setOutputCategories (ffnet.get(), uniq.get());
-	autostring32 ffnetName = FFNet_createNameFromTopology (ffnet.get());
-	praat_new (ffnet.move(), ffnetName.peek());
-END
-
-FORM (FFNet_PatternList_Categories_learnSM, U"FFNet & PatternList & Categories: Learn", U"FFNet & PatternList & Categories: Learn...")
-	NATURAL (U"Maximum number of epochs", U"100")
-	POSITIVE (U"Tolerance of minimizer", U"1e-7")
-	RADIO (U"Cost function", 1)
+	NUMBER_THREE (FFNet, PatternList, Categories)
+		double result = FFNet_PatternList_Categories_getCosts_average (me, you, him, costFunctionType);
+	NUMBER_THREE_END (U" (average costs)")
+}
+
+FORM (MODIFY_FFNet_PatternList_Categories_learn, U"FFNet & PatternList & Categories: Learn", U"FFNet & PatternList & Categories: Learn...") {
+	NATURALVAR (maximumNumberOfEpochs, U"Maximum number of epochs", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"1e-7")
+	RADIOVAR (costFunctionType, U"Cost function", 1)
 		RADIOBUTTON (U"Minimum-squared-error")
 		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	Categories him = FIRST (Categories);
-	FFNet_PatternList_Categories_learnSM (me, thee, him, GET_INTEGER (U"Maximum number of epochs"),
-		GET_REAL (U"Tolerance of minimizer"), GET_INTEGER (U"Cost function"));
-END
+	MODIFY_FIRST_OF_THREE (FFNet, PatternList, Categories)
+		FFNet_PatternList_Categories_learnSM (me, you, him, maximumNumberOfEpochs, tolerance, costFunctionType);
+	MODIFY_FIRST_OF_THREE_END
+}
 
-FORM (FFNet_PatternList_Categories_learnSD, U"FFNet & PatternList & Categories: Learn slow", U"FFNet & PatternList & Categories: Learn slow...")
-	NATURAL (U"Maximum number of epochs", U"100")
-	POSITIVE (U"Tolerance of minimizer", U"1e-7")
+FORM (MODIFY_FFNet_PatternList_Categories_learnSlow, U"FFNet & PatternList & Categories: Learn slow", U"FFNet & PatternList & Categories: Learn slow...") {
+	NATURALVAR (maximumNumberOfEpochs, U"Maximum number of epochs", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"1e-7")
 	LABEL (U"Specifics", U"Specific for this minimization")
-	POSITIVE (U"Learning rate", U"0.1")
-	REAL (U"Momentum", U"0.9")
-	RADIO (U"Cost function", 1)
+	POSITIVEVAR (learningRate, U"Learning rate", U"0.1")
+	REALVAR (momentum, U"Momentum", U"0.9")
+	RADIOVAR (costFunctionType, U"Cost function", 1)
 		RADIOBUTTON (U"Minimum-squared-error")
 		RADIOBUTTON (U"Minimum-cross-entropy")
 	OK
 DO
-	FFNet me = FIRST (FFNet);
-	PatternList thee = FIRST (PatternList);
-	Categories him = FIRST (Categories);
-	FFNet_PatternList_Categories_learnSD (me, thee, him, GET_INTEGER (U"Maximum number of epochs"),
-		GET_REAL (U"Tolerance of minimizer"), GET_REAL (U"Learning rate"), GET_REAL (U"Momentum"), GET_INTEGER (U"Cost function"));
-END
+	MODIFY_FIRST_OF_THREE (FFNet, PatternList, Categories)
+		FFNet_PatternList_Categories_learnSD (me, you, him, maximumNumberOfEpochs,tolerance, learningRate, momentum, costFunctionType);
+	MODIFY_FIRST_OF_THREE_END
+}
 
-DIRECT (RBM_PatternList_to_ActivationList)
-	iam_ONLY (RBM);
-	thouart_ONLY (PatternList);
-	autoActivationList him = RBM_PatternList_to_ActivationList (me, thee);
-	praat_new (him.move(), my name, U"_", thy name);
-END
+/*********** FFNet & PCA **********************************/
 
-void praat_uvafon_FFNet_init ();
-void praat_uvafon_FFNet_init () {
-	Thing_recognizeClassesByName (classFFNet, NULL);
+FORM (GRAPHICS_FFNet_PCA_drawDecisionPlaneInEigenspace, U"FFNet & PCA: Draw decision plane", nullptr) {
+	NATURALVAR (unitNumber, U"Unit number", U"1")
+	NATURALVAR (layer, U"Layer number", U"1")
+	NATURALVAR (horizontalEigenvectorNumber, U"Horizontal eigenvector number", U"1")
+	NATURALVAR (verticalEigenvectorNumber, U"Vertical eigenvector number", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	OK
+DO
+	GRAPHICS_TWO (FFNet, PCA)
+		FFNet_Eigen_drawDecisionPlaneInEigenspace (me, you, GRAPHICS, unitNumber, layer, horizontalEigenvectorNumber, verticalEigenvectorNumber, xmin, xmax, ymin, ymax);
+	GRAPHICS_TWO_END
+}
 
-	praat_addMenuCommand (U"Objects", U"New", U"Feedforward neural networks", 0, 0, 0);
-	praat_addMenuCommand (U"Objects", U"New", U"Feedforward neural networks", 0, 1, DO_FFNet_help);
-	praat_addMenuCommand (U"Objects", U"New", U"-- FFNet --", 0, 1, 0);
-	praat_addMenuCommand (U"Objects", U"New", U"Create iris example...", 0, 1, DO_FFNet_createIrisExample);
-	praat_addMenuCommand (U"Objects", U"New", U"Create FFNet...", 0, 1, DO_FFNet_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Advanced", 0, 1, 0);
-	praat_addMenuCommand (U"Objects", U"New", U"Create PatternList...", 0, 2, DO_PatternList_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Categories...", 0, 2, DO_Categories_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create FFNet (linear outputs)...", 0, 2, DO_FFNet_create_linearOutputs);
-
-	praat_addAction1 (classFFNet, 0, U"FFNet help", 0, 0, DO_FFNet_help);
-	praat_addAction1 (classFFNet, 0, DRAW_BUTTON, 0, 0, 0);
-	praat_addAction1 (classFFNet, 0, U"Draw topology", 0, 1, DO_FFNet_drawTopology);
-	praat_addAction1 (classFFNet, 0, U"Draw weights...", 0, 1, DO_FFNet_drawWeights);
-	praat_addAction1 (classFFNet, 0, U"Draw weights to layer...", 0,  praat_DEPTH_1 | praat_HIDDEN, DO_FFNet_drawWeightsToLayer);
-	praat_addAction1 (classFFNet, 0, U"Draw cost history...", 0, 1, DO_FFNet_drawCostHistory);
-	praat_addAction1 (classFFNet, 0, QUERY_BUTTON, 0, 0, 0);
-	praat_addAction1 (classFFNet, 0, U"Query structure", 0, 1, 0);
-	praat_addAction1 (classFFNet, 1, U"Get number of outputs", 0, 2, DO_FFNet_getNumberOfOutputs);
-	praat_addAction1 (classFFNet, 1, U"Get number of hidden units...", 0, 2, DO_FFNet_getNumberOfHiddenUnits);
-	praat_addAction1 (classFFNet, 1, U"Get number of inputs", 0, 2, DO_FFNet_getNumberOfInputs);
-	praat_addAction1 (classFFNet, 1, U"Get number of hidden weights...", 0, 2, DO_FFNet_getNumberOfHiddenWeights);
-	praat_addAction1 (classFFNet, 1, U"Get number of output weights", 0, 2, DO_FFNet_getNumberOfOutputWeights);
-	praat_addAction1 (classFFNet, 1, U"Get category of output unit...", 0, 2, DO_FFNet_getCategoryOfOutputUnit);
-	praat_addAction1 (classFFNet, 1, U"Get output unit of category...", 0, 2, DO_FFNet_getOutputUnitOfCategory);
-	praat_addAction1 (classFFNet, 0, U"-- FFNet weights --", 0, 1, 0);
-	praat_addAction1 (classFFNet, 1, U"Get bias...", 0, 1, DO_FFNet_getBias);
-	praat_addAction1 (classFFNet, 1, U"Get weight...", 0, 1, DO_FFNet_getWeight);
-	praat_addAction1 (classFFNet, 1, U"Get minimum", 0, 1, DO_FFNet_getMinimum);
-	praat_addAction1 (classFFNet, 0, MODIFY_BUTTON, 0, 0, 0);
-	praat_addAction1 (classFFNet, 1, U"Set bias...", 0, 1, DO_FFNet_setBias);
-	praat_addAction1 (classFFNet, 1, U"Set weight...", 0, 1, DO_FFNet_setWeight);
-	praat_addAction1 (classFFNet, 1, U"Reset...", 0, 1, DO_FFNet_reset);
-	praat_addAction1 (classFFNet, 0, U"Select biases...", 0, 1, DO_FFNet_selectBiasesInLayer);
-	praat_addAction1 (classFFNet, 0, U"Select all weights", 0, 1, DO_FFNet_selectAllWeights);
-	praat_addAction1 (classFFNet, 0, EXTRACT_BUTTON, 0, 0, 0);
-	praat_addAction1 (classFFNet, 0, U"Extract weights...", 0, 1, DO_FFNet_extractWeights);
-	praat_addAction1 (classFFNet, 0, U"Weights to Matrix...", 0, praat_DEPTH_1 | praat_HIDDEN, DO_FFNet_weightsToMatrix);
-	praat_addAction1 (classFFNet, 0, U"& PatternList: Classify?", 0, 0, DO_hint_FFNet_and_PatternList_classify);
-	praat_addAction1 (classFFNet, 0, U"& PatternList & Categories: Learn?", 0, 0, DO_hint_FFNet_and_PatternList_and_Categories_learn);
-
-	praat_addAction2 (classFFNet, 1, classActivationList, 1, U"Analyse", 0, 0, 0);
-	praat_addAction2 (classFFNet, 1, classActivationList, 1, U"To Categories...", 0, 0, DO_FFNet_ActivationList_to_Categories);
-
-	praat_addAction2 (classFFNet, 1, classEigen, 1, U"Draw", 0, 0, 0);
-	praat_addAction2 (classFFNet, 1, classEigen, 1, U"Draw hyperplane intersections", 0, 0, DO_FFNet_Eigen_drawIntersection);
-
-	praat_addAction2 (classFFNet, 1, classCategories, 1, U"Analyse", 0, 0, 0);
-	praat_addAction2 (classFFNet, 1, classCategories, 1, U"To ActivationList", 0, 0, DO_FFNet_Categories_to_ActivationList);
-
-	praat_addAction2 (classFFNet, 1, classMatrix, 1, U"Modify", 0, 0, 0);
-	praat_addAction2 (classFFNet, 1, classMatrix, 1, U"Weights from Matrix...", 0, 0, DO_FFNet_weightsFromMatrix);
-
-	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"Draw", 0, 0, 0);
-	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"Draw activation...", 0, 0, DO_FFNet_PatternList_drawActivation);
-	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"Analyse", 0, 0, 0);
-	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"To Categories...", 0, 0, DO_FFNet_PatternList_to_Categories);
-	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"To ActivationList...", 0, 0, DO_FFNet_PatternList_to_ActivationList);
-
-	praat_addAction2 (classFFNet, 1, classPCA, 1, U"Draw decision plane...", 0, 0, DO_FFNet_PCA_drawDecisionPlaneInEigenspace);
-	
-	praat_addAction2 (classRBM, 1, classPatternList, 1, U"To ActivationList", 0, 0, DO_RBM_PatternList_to_ActivationList);
+/*********** PatternList & Categories **********************************/
 
-	praat_addAction2 (classPatternList, 1, classCategories, 1, U"To FFNet...", 0, 0, DO_PatternList_Categories_to_FFNet);
+FORM (NEW1_PatternList_Categories_to_FFNet, U"PatternList & Categories: To FFNet", U"PatternList & Categories: To FFNet...") {
+	INTEGERVAR (numberOfUnitsInHiddenLayer1, U"Number of units in hidden layer 1", U"0")
+	INTEGERVAR (numberOfUnitsInHiddenLayer2, U"Number of units in hidden layer 2", U"0")
+	OK
+DO
+	CONVERT_TWO (PatternList, Categories)
+		autoFFNet result = PatternList_Categories_to_FFNet (me, you, numberOfUnitsInHiddenLayer1, numberOfUnitsInHiddenLayer2);
+	CONVERT_TWO_END (result -> name)
+}
+
+/*********** RBM & PatternList **********************************/
 
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Get total costs...", 0, 0, DO_FFNet_PatternList_ActivationList_getCosts_total);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Get average costs...", 0, 0, DO_FFNet_PatternList_ActivationList_getCosts_average);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Learn", 0, 0, 0);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Learn...", 0, 0, DO_FFNet_PatternList_ActivationList_learnSM);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Learn slow...", 0, 0, DO_FFNet_PatternList_ActivationList_learnSD);
+DIRECT (NEW1_RBM_PatternList_to_ActivationList) {
+	CONVERT_TWO (RBM, PatternList)
+		autoActivationList result = RBM_PatternList_to_ActivationList (me, you);
+	CONVERT_TWO_END (my name, U"_", you -> name)
+}
 
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Get total costs...", 0, 0, DO_FFNet_PatternList_Categories_getCosts_total);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Get average costs...", 0, 0, DO_FFNet_PatternList_Categories_getCosts_average);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Learn", 0, 0, 0);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Learn...", 0, 0, DO_FFNet_PatternList_Categories_learnSM);
-	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Learn slow...", 0, 0, DO_FFNet_PatternList_Categories_learnSD);
+void praat_uvafon_FFNet_init () {
+	Thing_recognizeClassesByName (classFFNet, NULL);
 
+	praat_addMenuCommand (U"Objects", U"New", U"Feedforward neural networks", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Objects", U"New", U"Create FFNet...", nullptr, 1, NEW1_FFNet_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create iris example...", nullptr, 1, NEWMANY_FFNet_createIrisExample);
+	praat_addMenuCommand (U"Objects", U"New", U"Advanced", nullptr, 1, nullptr);
+	praat_addMenuCommand (U"Objects", U"New", U"Create FFNet (linear outputs)...", nullptr, 2, NEW1_FFNet_create_linearOutputs);
+	praat_addMenuCommand (U"Objects", U"New", U"Create PatternList...", nullptr, 2, NEW1_PatternList_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Categories...", nullptr, 2, NEW1_Categories_create);
+
+	praat_addAction1 (classFFNet, 0, U"FFNet help", nullptr, 0, HELP_FFNet_help);
+	praat_addAction1 (classFFNet, 0, DRAW_BUTTON, nullptr, 0, nullptr);
+	praat_addAction1 (classFFNet, 0, U"Draw topology", nullptr, 1, GRAPHICS_FFNet_drawTopology);
+	praat_addAction1 (classFFNet, 0, U"Draw weights...", nullptr, 1, GRAPHICS_FFNet_drawWeights);
+	praat_addAction1 (classFFNet, 0, U"Draw weights to layer...", nullptr, praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_FFNet_drawWeightsToLayer);
+	praat_addAction1 (classFFNet, 0, U"Draw cost history...", nullptr, 1, GRAPHICS_FFNet_drawCostHistory);
+	praat_addAction1 (classFFNet, 0, QUERY_BUTTON, nullptr, 0, nullptr);
+	praat_addAction1 (classFFNet, 0, U"Query structure", nullptr, 1, nullptr);
+	praat_addAction1 (classFFNet, 1, U"Get number of layers", nullptr, 2, INTEGER_FFNet_getNumberOfLayers);
+	praat_addAction1 (classFFNet, 1, U"Get number of outputs", nullptr, 2, INTEGER_FFNet_getNumberOfOutputs);
+	praat_addAction1 (classFFNet, 1, U"Get number of hidden units...", nullptr, 2, INTEGER_FFNet_getNumberOfHiddenUnits);
+	praat_addAction1 (classFFNet, 1, U"Get number of inputs", nullptr, 2, INTEGER_FFNet_getNumberOfInputs);
+	praat_addAction1 (classFFNet, 1, U"Get number of hidden weights...", nullptr, 2, INTEGER_FFNet_getNumberOfHiddenWeights);
+	praat_addAction1 (classFFNet, 1, U"Get number of output weights", nullptr, 2, INTEGER_FFNet_getNumberOfOutputWeights);
+	praat_addAction1 (classFFNet, 1, U"Get category of output unit...", nullptr, 2, INFO_FFNet_getCategoryOfOutputUnit);
+	praat_addAction1 (classFFNet, 1, U"Get output unit of category...", nullptr, 2, INTEGER_FFNet_getOutputUnitOfCategory);
+	praat_addAction1 (classFFNet, 0, U"-- FFNet weights --", nullptr, 1, nullptr);
+	praat_addAction1 (classFFNet, 1, U"Get bias...", nullptr, 1, REAL_FFNet_getBias);
+	praat_addAction1 (classFFNet, 1, U"Get weight...", nullptr, 1, REAL_FFNet_getWeight);
+	praat_addAction1 (classFFNet, 1, U"Get minimum", nullptr, 1, REAL_FFNet_getMinimum);
+	praat_addAction1 (classFFNet, 0, MODIFY_BUTTON, nullptr, 0, nullptr);
+	praat_addAction1 (classFFNet, 0, U"Set bias...", nullptr, 1, MODIFY_FFNet_setBias);
+	praat_addAction1 (classFFNet, 0, U"Set weight...", nullptr, 1, MODIFY_FFNet_setWeight);
+	praat_addAction1 (classFFNet, 0, U"Reset...", nullptr, 1, MODIFY_FFNet_reset);
+	praat_addAction1 (classFFNet, 0, U"Select biases...", nullptr, 1, MODIFY_FFNet_selectBiasesInLayer);
+	praat_addAction1 (classFFNet, 0, U"Select all weights", nullptr, 1, MODIFY_FFNet_selectAllWeights);
+	praat_addAction1 (classFFNet, 0, EXTRACT_BUTTON, nullptr, 0, nullptr);
+	praat_addAction1 (classFFNet, 0, U"Extract weights...", nullptr, 1, NEW_FFNet_extractWeights);
+	praat_addAction1 (classFFNet, 0, U"Weights to Matrix...", nullptr, praat_DEPTH_1 | praat_HIDDEN, NEW_FFNet_weightsToMatrix);
+	praat_addAction1 (classFFNet, 0, U"& PatternList: Classify?", nullptr, 0, HINT_hint_FFNet_and_PatternList_classify);
+	praat_addAction1 (classFFNet, 0, U"& PatternList & Categories: Learn?", nullptr, 0, HINT_hint_FFNet_and_PatternList_and_Categories_learn);
+
+	praat_addAction2 (classFFNet, 1, classActivationList, 1, U"Analyse", nullptr, 0, nullptr);
+	praat_addAction2 (classFFNet, 1, classActivationList, 1, U"To Categories...", nullptr, 0, NEW1_FFNet_ActivationList_to_Categories);
+
+	praat_addAction2 (classFFNet, 1, classEigen, 1, U"Draw", nullptr, 0, nullptr);
+	praat_addAction2 (classFFNet, 1, classEigen, 1, U"Draw hyperplane intersections", nullptr, 0, GRAPHICS_FFNet_Eigen_drawIntersection);
+
+	praat_addAction2 (classFFNet, 1, classCategories, 1, U"Analyse", nullptr, 0, nullptr);
+	praat_addAction2 (classFFNet, 1, classCategories, 1, U"To ActivationList", nullptr, 0, NEW1_FFNet_Categories_to_ActivationList);
+
+	praat_addAction2 (classFFNet, 1, classMatrix, 1, U"Modify", nullptr, 0, nullptr);
+	praat_addAction2 (classFFNet, 1, classMatrix, 1, U"Weights from Matrix...", nullptr, 0, NEW1_FFNet_weightsFromMatrix);
+
+	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"Draw", nullptr, 0, nullptr);
+	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"Draw activation...", nullptr, 0, GRAPHICS_FFNet_PatternList_drawActivation);
+	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"Analyse", nullptr, 0, nullptr);
+	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"To Categories...", nullptr, 0, NEW1_FFNet_PatternList_to_Categories);
+	praat_addAction2 (classFFNet, 1, classPatternList, 1, U"To ActivationList...", nullptr, 0, NEW1_FFNet_PatternList_to_ActivationList);
+
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Get total costs...", nullptr, 0, REAL_FFNet_PatternList_ActivationList_getTotalCosts);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Get average costs...", nullptr, 0, REAL_FFNet_PatternList_ActivationList_getAverageCosts);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Learn", nullptr, 0, nullptr);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Learn...", nullptr, 0, MODIFY_FFNet_PatternList_ActivationList_learn);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classActivationList, 1, U"Learn slow...", nullptr, 0, MODIFY_FFNet_PatternList_ActivationList_learnSlow);
+
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Get total costs...", nullptr, 0, REAL_FFNet_PatternList_Categories_getTotalCosts);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Get average costs...", nullptr, 0, REAL_FFNet_PatternList_Categories_getAverageCosts);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Learn", nullptr, 0, nullptr);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Learn...", nullptr, 0, MODIFY_FFNet_PatternList_Categories_learn);
+	praat_addAction3 (classFFNet, 1, classPatternList, 1, classCategories, 1, U"Learn slow...", nullptr, 0, MODIFY_FFNet_PatternList_Categories_learnSlow);
+	
+	praat_addAction2 (classFFNet, 1, classPCA, 1, U"Draw decision plane...", nullptr, 0, GRAPHICS_FFNet_PCA_drawDecisionPlaneInEigenspace);
+	
+	praat_addAction2 (classPatternList, 1, classCategories, 1, U"To FFNet...", nullptr, 0, NEW1_PatternList_Categories_to_FFNet);
+	
+	praat_addAction2 (classRBM, 1, classPatternList, 1, U"To ActivationList", nullptr, 0, NEW1_RBM_PatternList_to_ActivationList);
+		
 	INCLUDE_MANPAGES (manual_FFNet_init)
 }
 
diff --git a/LPC/Cepstrogram.cpp b/LPC/Cepstrogram.cpp
index 7f7ad57..9117d60 100644
--- a/LPC/Cepstrogram.cpp
+++ b/LPC/Cepstrogram.cpp
@@ -362,10 +362,10 @@ static void complexfftoutput_to_power (double *fft, long nfft, double *dbs, bool
 	}
 }
 
-autoPowerCepstrogram Sound_to_PowerCepstrogram_hillenbrand (Sound me, double minimumPitch, double dt) {
+autoPowerCepstrogram Sound_to_PowerCepstrogram_hillenbrand (Sound me, double pitchFloor, double dt) {
 	try {
 		// minimum analysis window has 3 periods of lowest pitch
-		double analysisWidth = 3  / minimumPitch;
+		double analysisWidth = 3  / pitchFloor;
 		if (analysisWidth > my dx * my nx) {
 			analysisWidth = my dx * my nx;
 		}
diff --git a/LPC/Cepstrogram.h b/LPC/Cepstrogram.h
index aba399e..68d3ac3 100644
--- a/LPC/Cepstrogram.h
+++ b/LPC/Cepstrogram.h
@@ -56,7 +56,7 @@ void PowerCepstrogram_paint (PowerCepstrogram me, Graphics g, double tmin, doubl
 
 autoPowerCepstrogram PowerCepstrogram_smooth (PowerCepstrogram me, double timeAveragingWindow, double quefrencyAveragingWindow);
 
-autoPowerCepstrogram Sound_to_PowerCepstrogram (Sound me, double analysisWidth, double dt, double maximumFrequency, double preEmphasisFrequency);
+autoPowerCepstrogram Sound_to_PowerCepstrogram (Sound me, double pitchFloor, double dt, double maximumFrequency, double preEmphasisFrequency);
 
 autoPowerCepstrogram Sound_to_PowerCepstrogram_hillenbrand (Sound me, double analysisWidth, double dt);
 
diff --git a/LPC/Cepstrum.cpp b/LPC/Cepstrum.cpp
index b689a5d..109b5d3 100644
--- a/LPC/Cepstrum.cpp
+++ b/LPC/Cepstrum.cpp
@@ -215,8 +215,9 @@ void PowerCepstrum_drawTiltLine (PowerCepstrum me, Graphics g, double qmin, doub
  * method == 1 : Least squares fit
  * method == 2 : Theil's partial robust fit
  */
-void PowerCepstrum_fitTiltLine (PowerCepstrum me, double qmin, double qmax, double *a, double *intercept, int lineType, int method) {
+void PowerCepstrum_fitTiltLine (PowerCepstrum me, double qmin, double qmax, double *p_a, double *p_intercept, int lineType, int method) {
 	try {
+		double a, intercept;
 		if (qmax <= qmin) {
 			qmin = my xmin; qmax = my xmax;
 		}
@@ -260,7 +261,9 @@ void PowerCepstrum_fitTiltLine (PowerCepstrum me, double qmin, double qmax, doub
 			method = 2; // robust fit of peaks
 		}
 		// fit a straight line through (x,y)'s
-		NUMlineFit (x.peek(), y.peek(), numberOfPoints, a, intercept, method);
+		NUMlineFit (x.peek(), y.peek(), numberOfPoints, & a, & intercept, method);
+		if (p_intercept) { *p_intercept = intercept; }
+		if (p_a) { *p_a = a; }
 	} catch (MelderError) {
 		Melder_throw (me, U": couldn't fit a line.");
 	}
@@ -344,13 +347,20 @@ autoPowerCepstrum PowerCepstrum_smooth (PowerCepstrum me, double quefrencyAverag
 	return thee;
 }
 
-void PowerCepstrum_getMaximumAndQuefrency (PowerCepstrum me, double pitchFloor, double pitchCeiling, int interpolation, double *peakdB, double *quefrency) {
+void PowerCepstrum_getMaximumAndQuefrency (PowerCepstrum me, double pitchFloor, double pitchCeiling, int interpolation, double *p_peakdB, double *p_quefrency) {
+	double peakdB, quefrency;
 	autoPowerCepstrum thee = Data_copy (me);
 	double lowestQuefrency = 1.0 / pitchCeiling, highestQuefrency = 1.0 / pitchFloor;
 	for (long i = 1; i <= my nx; i ++) {
 		thy z[1][i] = my v_getValueAtSample (i, 1, 0); // 10 log val^2
 	}
-	Vector_getMaximumAndX ((Vector) thee.get(), lowestQuefrency, highestQuefrency, 1, interpolation, peakdB, quefrency);   // FIXME cast
+	Vector_getMaximumAndX ((Vector) thee.get(), lowestQuefrency, highestQuefrency, 1, interpolation, & peakdB, & quefrency);   // FIXME cast
+	if (p_peakdB) {
+		*p_peakdB = peakdB;
+	}
+	if (p_quefrency) {
+		*p_quefrency = quefrency;
+	}
 }
 
 #if 0
diff --git a/LPC/LPC_and_LineSpectralFrequencies.cpp b/LPC/LPC_and_LineSpectralFrequencies.cpp
index 0858259..4bb89f9 100644
--- a/LPC/LPC_and_LineSpectralFrequencies.cpp
+++ b/LPC/LPC_and_LineSpectralFrequencies.cpp
@@ -187,7 +187,7 @@ static long Roots_fromPolynomial_grid (Roots me, Polynomial thee, double gridSiz
 	return numberOfRootsFound;
 }
 
-void LineSpectralFrequencies_Frame_initFromLPC_Frame_grid (LineSpectralFrequencies_Frame me, LPC_Frame thee, Polynomial g1, Polynomial g2, Roots roots, double gridSize, double maximumFrequency) {
+static void LineSpectralFrequencies_Frame_initFromLPC_Frame_grid (LineSpectralFrequencies_Frame me, LPC_Frame thee, Polynomial g1, Polynomial g2, Roots roots, double gridSize, double maximumFrequency) {
 	/* Construct Fs and Fa
 		* divide out the zeros
 		* transform to polynomial equations g1 and g2 of half the order
@@ -250,7 +250,7 @@ autoLineSpectralFrequencies LPC_to_LineSpectralFrequencies (LPC me, double gridS
 	}
 }
 
-void LPC_Frame_initFromLineSpectralFrequencies_Frame (LPC_Frame me, LineSpectralFrequencies_Frame thee, Polynomial fs, Polynomial fa, double maximumFrequency) {
+static void LPC_Frame_initFromLineSpectralFrequencies_Frame (LPC_Frame me, LineSpectralFrequencies_Frame thee, Polynomial fs, Polynomial fa, double maximumFrequency) {
 	LPC_Frame_init (me, thy numberOfFrequencies);
 
 	/* Reconstruct Fs (z) */
diff --git a/LPC/LPC_and_LineSpectralFrequencies.h b/LPC/LPC_and_LineSpectralFrequencies.h
index 820a4f2..859e266 100644
--- a/LPC/LPC_and_LineSpectralFrequencies.h
+++ b/LPC/LPC_and_LineSpectralFrequencies.h
@@ -1,5 +1,5 @@
 #ifndef _LPC_and_LineSpectralFrequencies_h_
-#define _LPC_and_LineLineSpectralFrequencies_h_
+#define _LPC_and_LineSpectralFrequencies_h_
 /* LPC_and_LineLineSpectralFrequencies.h
  *
  * Copyright (C) 2016 David Weenink
diff --git a/LPC/LPC_and_Polynomial.cpp b/LPC/LPC_and_Polynomial.cpp
index 4b69ea0..277280c 100644
--- a/LPC/LPC_and_Polynomial.cpp
+++ b/LPC/LPC_and_Polynomial.cpp
@@ -35,9 +35,11 @@ autoPolynomial LPC_Frame_to_Polynomial (LPC_Frame me) {
 autoPolynomial LPC_to_Polynomial (LPC me, double time) {
 	try {
 		long iFrame = Sampled_xToIndex (me, time);
-
-		if (iFrame < 1 || iFrame > my nx) {
-			Melder_throw (U"invalid frame number.");
+		if (iFrame < 1) {
+			iFrame = 1;
+		}
+		if (iFrame > my nx) {
+			iFrame = my nx;
 		}
 		autoPolynomial thee = LPC_Frame_to_Polynomial (&my d_frames[iFrame]);
 		return thee;
diff --git a/LPC/LineSpectralFrequencies.cpp b/LPC/LineSpectralFrequencies.cpp
index 6dd0302..bc40069 100644
--- a/LPC/LineSpectralFrequencies.cpp
+++ b/LPC/LineSpectralFrequencies.cpp
@@ -59,7 +59,7 @@ void LineSpectralFrequencies_Frame_init (LineSpectralFrequencies_Frame me, int n
 	my numberOfFrequencies = numberOfFrequencies;
 }
 
-void LineSpectralFrequencies_init (LineSpectralFrequencies me, double tmin, double tmax, long nt, double dt, double t1, int numberOfFrequencies, double maximumFrequency) {
+static void LineSpectralFrequencies_init (LineSpectralFrequencies me, double tmin, double tmax, long nt, double dt, double t1, int numberOfFrequencies, double maximumFrequency) {
 	my maximumFrequency = maximumFrequency;
 	my maximumNumberOfFrequencies = numberOfFrequencies;
 	Sampled_init (me, tmin, tmax, nt, dt, t1);
diff --git a/LPC/manual_LPC.cpp b/LPC/manual_LPC.cpp
index 2eb3327..c7f9d0e 100644
--- a/LPC/manual_LPC.cpp
+++ b/LPC/manual_LPC.cpp
@@ -625,6 +625,11 @@ LIST_ITEM (U"2.  We convert the melspectrogram values to mel frequency cepstral
 	"coefficients (see @@MelSpectrogram: To MFCC...@ for details).")
 MAN_END
 
+MAN_BEGIN (U"Spectrum: To PowerCepstrum", U"djmw", 20160909)
+INTRO (U"A command to create a @PowerCepstrum from every selected @Spectrum.")
+ENTRY (U"Mathematical procedure")
+MAN_END
+
 MAN_BEGIN (U"VocalTractTier", U"djmw", 20120423)
 INTRO (U"One of the @@types of objects@ in Praat. A VocalTractTier objects contains a number of (%time, %VocalTract) points, where a @@VocalTract@ represents the area function of the vocal tract expressed as m^^2^, running from the glottis to the lips.")
 MAN_END
diff --git a/LPC/praat_LPC_init.cpp b/LPC/praat_LPC_init.cpp
index 31c1985..987f7e4 100644
--- a/LPC/praat_LPC_init.cpp
+++ b/LPC/praat_LPC_init.cpp
@@ -1,6 +1,6 @@
 /* praat_LPC_init.cpp
  *
- * Copyright (C) 1994-2014 David Weenink
+ * Copyright (C) 1994-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -46,15 +46,18 @@
 #include "LPC_to_Spectrogram.h"
 #include "LPC_to_Spectrum.h"
 #include "NUM2.h"
-#include "praatP.h"
 #include "Sound_and_LPC.h"
 #include "Sound_and_LPC_robust.h"
 #include "Sound_and_Cepstrum.h"
 #include "Sound_to_MFCC.h"
 #include "VocalTractTier.h"
 
-#undef iam
-#define iam iam_LOOP
+#include "praat_TimeFunction.h"
+#include "praat_Matrix.h"
+
+#define praat_Quefrency_RANGE(fromQuefrency,toQuefrency) \
+	REALVAR (fromQuefrency, U"left Quefrency range (s)", U"0.0") \
+	REALVAR (toQuefrency, U"right Quefrency range (s)", U"0.0 (= all)")
 
 static const char32 *DRAW_BUTTON    = U"Draw -";
 static const char32 *QUERY_BUTTON   = U"Query -";
@@ -62,1207 +65,966 @@ static const char32 *MODIFY_BUTTON   = U"Modify -";
 
 void praat_CC_init (ClassInfo klas);
 void praat_TimeFrameSampled_query_init (ClassInfo klas);
-void praat_TimeFunction_modify_init (ClassInfo klas);
-int praat_Fon_formula (UiForm dia, Interpreter interpreter);
 
 /********************** Cepstrum  ****************************************/
 
-DIRECT (Cepstrum_downto_PowerCepstrum)
-	LOOP {
-		iam (Cepstrum);
-		autoPowerCepstrum thee = Cepstrum_downto_PowerCepstrum (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (PowerCepstrum_help)
-	Melder_help (U"PowerCepstrum");
-END
-
-FORM (Cepstrum_drawLinear, U"Cepstrum: Draw linear", U"Cepstrum: Draw (linear)...")
-	REAL (U"left Quefrency range (s)", U"0.0")
-	REAL (U"right Quefrency range (s)", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	BOOLEAN (U"Garnish", true)
+DIRECT (NEW_Cepstrum_downto_PowerCepstrum) {
+	CONVERT_EACH (Cepstrum)
+		autoPowerCepstrum result = Cepstrum_downto_PowerCepstrum (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (HELP_PowerCepstrum_help) {
+	HELP (U"PowerCepstrum")
+}
+
+FORM (GRAPHICS_Cepstrum_drawLinear, U"Cepstrum: Draw linear", U"Cepstrum: Draw (linear)...") {
+	praat_Quefrency_RANGE(fromQuefrency,toQuefrency)
+	REALVAR (ymin, U"Minimum", U"0.0")
+	REALVAR (ymax, U"Maximum", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Cepstrum);
-		Cepstrum_drawLinear (me, GRAPHICS, GET_REAL (U"left Quefrency range"), GET_REAL (U"right Quefrency range"),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (PowerCepstrum_draw, U"PowerCepstrum: Draw", U"PowerCepstrum: Draw...")
-	REAL (U"left Quefrency range (s)", U"0.0")
-	REAL (U"right Quefrency range (s)", U"0.0")
-	REAL (U"Minimum (dB)", U"0.0")
-	REAL (U"Maximum (dB)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	GRAPHICS_EACH (Cepstrum)
+		Cepstrum_drawLinear (me, GRAPHICS, fromQuefrency, toQuefrency, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_PowerCepstrum_draw, U"PowerCepstrum: Draw", U"PowerCepstrum: Draw...") {
+	praat_Quefrency_RANGE(fromQuefrency,toQuefrency)
+	REALVAR (ymin, U"Minimum (dB)", U"0.0")
+	REALVAR (ymax, U"Maximum (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (PowerCepstrum);
-		PowerCepstrum_draw (me, GRAPHICS, GET_REAL (U"left Quefrency range"), GET_REAL (U"right Quefrency range"),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (PowerCepstrum_drawTiltLine, U"PowerCepstrum: Draw tilt line", U"PowerCepstrum: Draw tilt line...")
-	REAL (U"left Quefrency range (s)", U"0.0")
-	REAL (U"right Quefrency range (s)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
+	GRAPHICS_EACH (PowerCepstrum)
+		PowerCepstrum_draw (me, GRAPHICS, fromQuefrency, toQuefrency, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_PowerCepstrum_drawTiltLine, U"PowerCepstrum: Draw tilt line", U"PowerCepstrum: Draw tilt line...") {
+	praat_Quefrency_RANGE(fromQuefrency,toQuefrency)
+	REALVAR (fromAmplitude_dB, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude_dB, U"right Amplitude range (dB)", U"0.0")
 	LABEL (U"", U"Parameters for the tilt line fit")
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 1)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 1)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (PowerCepstrum);
-		PowerCepstrum_drawTiltLine (me, GRAPHICS, GET_REAL (U"left Quefrency range"), GET_REAL (U"right Quefrency range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),
-			GET_REAL (U"left Tilt line quefrency range"), GET_REAL (U"right Tilt line quefrency range"), 
-			GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-	}
-END
-
-FORM (PowerCepstrum_formula, U"PowerCepstrum: Formula...", U"PowerCepstrum: Formula...")
+	GRAPHICS_EACH (PowerCepstrum)
+		PowerCepstrum_drawTiltLine (me, GRAPHICS, fromQuefrency, toQuefrency,fromAmplitude_dB,toAmplitude_dB, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	GRAPHICS_EACH_END
+}
+
+FORM (MODIFY_PowerCepstrum_formula, U"PowerCepstrum: Formula...", U"PowerCepstrum: Formula...") {
 	LABEL (U"label", U"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 (U"formula", U"self")
+	TEXTVAR (formula, U"formula", U"self")
 	OK
 DO
-	praat_Fon_formula (dia, interpreter);
-END
-
-FORM (PowerCepstrum_getPeak, U"PowerCepstrum: Get peak", 0)
-	REAL (U"left Search peak in pitch range (Hz)", U"60.0")
-	REAL (U"right Search peak in pitch range (Hz)", U"333.3")
-	RADIO (U"Interpolation", 2)
-	RADIOBUTTON (U"None")
-	RADIOBUTTON (U"Parabolic")
-	RADIOBUTTON (U"Cubic")
-	RADIOBUTTON (U"Sinc70")
+	MODIFY_EACH (PowerCepstrum)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_END
+}
+
+FORM (REAL_PowerCepstrum_getPeak, U"PowerCepstrum: Get peak", nullptr) {
+	REALVAR (fromPitch, U"left Search peak in pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Search peak in pitch range (Hz)", U"333.3")
+	RADIOVAR (interpolationMethod, U"Interpolation", 2)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double peakdB, quefrency;
-		PowerCepstrum_getMaximumAndQuefrency (me, GET_REAL (U"left Search peak in pitch range"), GET_REAL (U"right Search peak in pitch range"), GET_INTEGER (U"Interpolation") - 1, &peakdB, &quefrency);
-		Melder_informationReal (peakdB, U" dB");
-	}
-END
-
-FORM (PowerCepstrum_getQuefrencyOfPeak, U"PowerCepstrum: Get quefrency of peak", 0)
-	REAL (U"left Search peak in pitch range (Hz)", U"60.0")
-	REAL (U"right Search peak in pitch range (Hz)", U"333.3")
-	RADIO (U"Interpolation", 2)
-	RADIOBUTTON (U"None")
-	RADIOBUTTON (U"Parabolic")
-	RADIOBUTTON (U"Cubic")
-	RADIOBUTTON (U"Sinc70")
+	NUMBER_ONE (PowerCepstrum)
+		double result;
+		PowerCepstrum_getMaximumAndQuefrency (me, fromPitch, toPitch, interpolationMethod - 1, & result, nullptr);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_PowerCepstrum_getQuefrencyOfPeak, U"PowerCepstrum: Get quefrency of peak", nullptr) {
+	REALVAR (fromPitch, U"left Search peak in pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Search peak in pitch range (Hz)", U"333.3")
+	RADIOVAR (interpolationMethod, U"Interpolation", 2)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double peakdB, quefrency;
-		PowerCepstrum_getMaximumAndQuefrency (me, GET_REAL (U"left Search peak in pitch range"), GET_REAL (U"right Search peak in pitch range"), GET_INTEGER (U"Interpolation") - 1, &peakdB, &quefrency);
+	NUMBER_ONE (PowerCepstrum)
+		double result, quefrency;
+		PowerCepstrum_getMaximumAndQuefrency (me, fromPitch, toPitch, interpolationMethod - 1, & quefrency, & result);
 		double f = 1.0 / quefrency;
-		Melder_information (quefrency, U" s (f =", f, U" Hz)");
-	}
-END
-
-FORM (PowerCepstrum_getRNR, U"PowerCepstrum: Get rhamonics to noise ration", 0)
-	REAL (U"left Pitch range (Hz)", U"60.0")
-	REAL (U"right Pitch range (Hz)", U"333.3")
-	POSITIVE (U"Fractional width (0-1)", U"0.05")
+	NUMBER_ONE_END (U" s (f =", f, U" Hz)")
+}
+
+FORM (REAL_PowerCepstrum_getRNR, U"PowerCepstrum: Get rhamonics to noise ration", nullptr) {
+	REALVAR (fromPitch, U"left Pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Pitch range (Hz)", U"333.3")
+	POSITIVEVAR (fractionalWIdth, U"Fractional width (0-1)", U"0.05")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double rnr = PowerCepstrum_getRNR (me, GET_REAL (U"left Pitch range"), GET_REAL (U"right Pitch range"), GET_REAL (U"Fractional width"));
-		Melder_information (rnr, U" (rnr)");
-	}
-END
-
-FORM (PowerCepstrum_getPeakProminence_hillenbrand, U"PowerCepstrum: Get peak prominence (hillenbrand)", U"PowerCepstrum: Get peak prominence (hillenbrand)...")
-	REAL (U"left Search peak in pitch range (Hz)", U"60.0")
-	REAL (U"right Search peak in pitch range (Hz)", U"333.3")
+	NUMBER_ONE (PowerCepstrum)
+		double result = PowerCepstrum_getRNR (me, fromPitch, toPitch, fractionalWIdth);
+	NUMBER_ONE_END (U" (rnr)")
+}
+
+FORM (REAL_PowerCepstrum_getPeakProminence_hillenbrand, U"PowerCepstrum: Get peak prominence (hillenbrand)", U"PowerCepstrum: Get peak prominence (hillenbrand)...") {
+	REALVAR (fromPitch, U"left Search peak in pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Search peak in pitch range (Hz)", U"333.3")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double qpeak, cpp = PowerCepstrum_getPeakProminence_hillenbrand (me,
-			GET_REAL (U"left Search peak in pitch range"), GET_REAL (U"right Search peak in pitch range"), &qpeak);
-		Melder_information (cpp, U" dB; quefrency=", qpeak, U" s (f=",
-			1.0 / qpeak, U" Hz).");
-	}
-END
-
-FORM (PowerCepstrum_getTiltLineSlope, U"PowerCepstrum: Get tilt line slope", 0)
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 1)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	NUMBER_ONE (PowerCepstrum)
+		double qpeak, result = PowerCepstrum_getPeakProminence_hillenbrand (me, fromPitch, toPitch, & qpeak);
+	NUMBER_ONE_END (U" dB; quefrency=", qpeak, U" s (f=", 1.0 / qpeak, U" Hz).")
+}
+
+FORM (REAL_PowerCepstrum_getTiltLineSlope, U"PowerCepstrum: Get tilt line slope", nullptr) {
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 1)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double a, intercept;
-		int lineType = GET_INTEGER (U"Line type");
-		PowerCepstrum_fitTiltLine (me, GET_REAL (U"left Tilt line quefrency range"), GET_REAL (U"right Tilt line quefrency range"), 
-			  &a, &intercept, lineType, GET_INTEGER (U"Fit method"));
-		Melder_information (a, U" dB / ", lineType == 1 ? U"s" : U"ln (s)");
-	}
-END
-
-
-FORM (PowerCepstrum_getTiltLineIntercept, U"PowerCepstrum: Get tilt line intercept", 0)
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 1)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
+	NUMBER_ONE (PowerCepstrum)
+		double result;
+		PowerCepstrum_fitTiltLine (me, fromQuefrency_tiltLine, toQuefrency_tiltLine, & result, nullptr, lineType, fitMethod);
+	NUMBER_ONE_END (U" dB / ", lineType == 1 ? U"s" : U"ln (s)");
+}
+
+
+FORM (REAL_PowerCepstrum_getTiltLineIntercept, U"PowerCepstrum: Get tilt line intercept", nullptr) {
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 1)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
 	OPTION (U"Least squares")
 	OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double a, intercept;
-		int lineType = GET_INTEGER (U"Line type");
-		PowerCepstrum_fitTiltLine (me, GET_REAL (U"left Tilt line quefrency range"), GET_REAL (U"right Tilt line quefrency range"), 
-			  &a, &intercept, lineType, GET_INTEGER (U"Fit method"));
-		Melder_information (intercept, U" dB");
-	}
-END
-
-FORM (PowerCepstrum_getPeakProminence, U"PowerCepstrum: Get peak prominence", U"PowerCepstrum: Get peak prominence...")
-	REAL (U"left Search peak in pitch range (Hz)", U"60.0")
-	REAL (U"right Search peak in pitch range (Hz)", U"333.3")
-	RADIO (U"Interpolation", 2)
-	RADIOBUTTON (U"None")
-	RADIOBUTTON (U"Parabolic")
-	RADIOBUTTON (U"Cubic")
-	RADIOBUTTON (U"Sinc70")
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 1)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	NUMBER_ONE (PowerCepstrum)
+		double result;
+		PowerCepstrum_fitTiltLine (me, fromQuefrency_tiltLine, toQuefrency_tiltLine, nullptr, & result, lineType, fitMethod);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_PowerCepstrum_getPeakProminence, U"PowerCepstrum: Get peak prominence", U"PowerCepstrum: Get peak prominence...") {
+	REALVAR (fromPitch, U"left Search peak in pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Search peak in pitch range (Hz)", U"333.3")
+	RADIOVAR (interpolationMethod, U"Interpolation", 2)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 1)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		double qpeak, cpp = PowerCepstrum_getPeakProminence (me,
-			GET_REAL (U"left Search peak in pitch range"), GET_REAL (U"right Search peak in pitch range"),
-			GET_INTEGER (U"Interpolation") - 1,
-			GET_REAL (U"left Tilt line quefrency range"), GET_REAL (U"right Tilt line quefrency range"),
-			GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"), &qpeak);
-		Melder_information (cpp, U" dB; quefrency=", qpeak, U" s (f=",
-			1.0 / qpeak, U" Hz).");
-	}
-END
-
-FORM (PowerCepstrum_subtractTilt_inline, U"PowerCepstrum: Subtract tilt (in-line)", 0)
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 1)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	NUMBER_ONE (PowerCepstrum)
+		double qpeak, result = PowerCepstrum_getPeakProminence (me, fromPitch, toPitch, interpolationMethod - 1, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod, & qpeak);
+	NUMBER_ONE_END (U" dB; quefrency=", qpeak, U" s (f=", 1.0 / qpeak, U" Hz).");
+}
+
+FORM (MODIFY_PowerCepstrum_subtractTilt_inline, U"PowerCepstrum: Subtract tilt (in-line)", nullptr) {
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 1)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		PowerCepstrum_subtractTilt_inline (me, GET_REAL (U"left Tilt line quefrency range"), 
-			GET_REAL (U"right Tilt line quefrency range"), GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-	}
-END
-
-FORM (PowerCepstrum_smooth_inline, U"PowerCepstrum: Smooth (in-line)", 0)
-	REAL (U"Quefrency averaging window (s)", U"0.0005")
-	NATURAL (U"Number of iterations", U"1");
+	MODIFY_EACH (PowerCepstrum)
+		PowerCepstrum_subtractTilt_inline (me, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_PowerCepstrum_smooth_inline, U"PowerCepstrum: Smooth (in-line)", nullptr) {
+	REALVAR (quefrencySmoothingWindowDuration, U"Quefrency averaging window (s)", U"0.0005")
+	NATURALVAR (numberOfIterations, U"Number of iterations", U"1");
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		PowerCepstrum_smooth_inline (me, GET_REAL (U"Quefrency averaging window"), GET_INTEGER (U"Number of iterations"));
-	}
-END
-
-FORM (PowerCepstrum_smooth, U"PowerCepstrum: Smooth", 0)
-	REAL (U"Quefrency averaging window (s)", U"0.0005")
-	NATURAL (U"Number of iterations", U"1");
+	MODIFY_EACH (PowerCepstrum)
+		PowerCepstrum_smooth_inline (me, quefrencySmoothingWindowDuration, numberOfIterations);
+	MODIFY_EACH_END
+}
+
+FORM (NEW_PowerCepstrum_smooth, U"PowerCepstrum: Smooth", nullptr) {
+	REALVAR (quefrencySmoothingWindowDuration, U"Quefrency averaging window (s)", U"0.0005")
+	NATURALVAR (numberOfIterations, U"Number of iterations", U"1");
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		autoPowerCepstrum thee = PowerCepstrum_smooth (me, GET_REAL (U"Quefrency averaging window"), GET_INTEGER (U"Number of iterations"));
-		praat_new (thee.move(), my name, U"_smooth");
-	}
-END
-
-FORM (PowerCepstrum_subtractTilt, U"PowerCepstrum: Subtract tilt", 0)
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 1)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	CONVERT_EACH (PowerCepstrum)
+		autoPowerCepstrum result = PowerCepstrum_smooth (me, quefrencySmoothingWindowDuration, numberOfIterations);
+	CONVERT_EACH_END (my name, U"_smooth")
+}
+
+FORM (NEW_PowerCepstrum_subtractTilt, U"PowerCepstrum: Subtract tilt", nullptr) {
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 1)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrum);
-		autoPowerCepstrum thee = PowerCepstrum_subtractTilt (me, GET_REAL (U"left Tilt line quefrency range"), 
-			GET_REAL (U"right Tilt line quefrency range"), GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-		praat_new (thee.move(), my name, U"minusTilt");
-	}
-END
-
-DIRECT (Cepstrum_to_Spectrum)
-	LOOP {
-		iam (Cepstrum);
-		autoSpectrum thee = Cepstrum_to_Spectrum (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (PowerCepstrum_to_Matrix)
-	LOOP {
-		iam (PowerCepstrum);
-		autoMatrix thee = PowerCepstrum_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (PowerCepstrum)
+		autoPowerCepstrum result = PowerCepstrum_subtractTilt (me, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	CONVERT_EACH_END (my name, U"_minusTilt")
+}
+
+DIRECT (NEW_Cepstrum_to_Spectrum) {
+	CONVERT_EACH (Cepstrum)
+		autoSpectrum result = Cepstrum_to_Spectrum (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_PowerCepstrum_to_Matrix) {
+	CONVERT_EACH (PowerCepstrum)
+		autoMatrix result = PowerCepstrum_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** Cepstrogram  ****************************************/
 
-DIRECT (PowerCepstrogram_help)
-	Melder_help (U"PowerCepstrogram");
-END
-
-FORM (old_PowerCepstrogram_paint, U"PowerCepstrogram: Paint", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Quefrency range (s)", U"0.0")
-	REAL (U"right Quefrency range (s)", U"0.0")
-	REAL (U"Minimum (dB)", U"0.0")
-	REAL (U"Maximum (dB)", U"0.0")
-	BOOLEAN (U"Garnish", true);
+DIRECT (HELP_PowerCepstrogram_help) {
+	HELP (U"PowerCepstrogram")
+}
+
+FORM (GRAPHICS_old_PowerCepstrogram_paint, U"PowerCepstrogram: Paint", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	praat_Quefrency_RANGE(fromQuefrency,toQuefrency)
+	REALVAR (minimum_dB, U"Minimum (dB)", U"0.0")
+	REALVAR (maximum_dB, U"Maximum (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (PowerCepstrogram);
-		PowerCepstrogram_paint (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Quefrency range"), GET_REAL (U"right Quefrency range"),
-			GET_REAL (U"Maximum"), false, GET_REAL (U"Maximum") - GET_REAL (U"Minimum"),
-			0.0, GET_INTEGER (U"Garnish"));
-        }
-END
-
-FORM (PowerCepstrogram_paint, U"PowerCepstrogram: Paint", U"PowerCepstrogram: Paint...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Quefrency range (s)", U"0.0")
-	REAL (U"right Quefrency range (s)", U"0.0")
-	REAL (U"Maximum (dB)", U"80.0")
-	BOOLEAN (U"Autoscaling", false);
-	REAL (U"Dynamic range (dB)", U"30.0");
-	REAL (U"Dynamic compression (0-1)", U"0.0");
-	BOOLEAN (U"Garnish", true);
+	GRAPHICS_EACH (PowerCepstrogram)
+		PowerCepstrogram_paint (me, GRAPHICS, fromTime, toTime, fromQuefrency, toQuefrency, maximum_dB, false, maximum_dB - minimum_dB, 0.0, garnish);
+    GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_PowerCepstrogram_paint, U"PowerCepstrogram: Paint", U"PowerCepstrogram: Paint...") {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	praat_Quefrency_RANGE(fromQuefrency,toQuefrency)
+	REALVAR (maximum_dB, U"Maximum (dB)", U"80.0")
+	BOOLEANVAR (autoscaling, U"Autoscaling", false);
+	REALVAR (dynamicRange_dB, U"Dynamic range (dB)", U"30.0");
+	REALVAR (compression, U"Dynamic compression (0-1)", U"0.0");
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
-DO_ALTERNATIVE (old_PowerCepstrogram_paint)
-	autoPraatPicture picture;
-	LOOP {
-		iam (PowerCepstrogram);
-		PowerCepstrogram_paint (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Quefrency range"), GET_REAL (U"right Quefrency range"),
-		GET_REAL (U"Maximum"), GET_INTEGER (U"Autoscaling"), GET_REAL (U"Dynamic range"),
-		GET_REAL (U"Dynamic compression"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (PowerCepstrogram_smooth, U"PowerCepstrogram: Smooth", U"PowerCepstrogram: Smooth...")
-	REAL (U"Time averaging window (s)", U"0.02")
-	REAL (U"Quefrency averaging window (s)", U"0.0005")
+DO_ALTERNATIVE (GRAPHICS_old_PowerCepstrogram_paint)
+	GRAPHICS_EACH (PowerCepstrogram)
+		PowerCepstrogram_paint (me, GRAPHICS, fromTime, toTime, fromQuefrency, toQuefrency, maximum_dB, autoscaling, dynamicRange_dB, compression, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (NEW_PowerCepstrogram_smooth, U"PowerCepstrogram: Smooth", U"PowerCepstrogram: Smooth...") {
+	REALVAR (smoothingWindowDuration, U"Time averaging window (s)", U"0.02")
+	REALVAR (quefrencySmoothingWindowDuration, U"Quefrency averaging window (s)", U"0.0005")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		autoPowerCepstrogram thee = PowerCepstrogram_smooth (me, GET_REAL (U"Time averaging window"), GET_REAL (U"Quefrency averaging window"));
-		praat_new (thee.move(), my name, U"_smoothed");
-	}
-END
-
-DIRECT (PowerCepstrogram_getStartQuefrency)
-	LOOP {
-		iam (PowerCepstrogram);
-		Melder_informationReal (my ymin, U" (s)");
-	}
-END
-
-DIRECT (PowerCepstrogram_getEndQuefrency)
-	LOOP {
-		iam (PowerCepstrogram);
-		Melder_informationReal (my ymax, U" (s)");
-	}
-END
-
-DIRECT (PowerCepstrogram_getNumberOfQuefrencyBins)
-	LOOP {
-		iam (PowerCepstrogram);
-		Melder_informationReal (my ny, U" quefrency bins");
-	}
-END
-
-DIRECT (PowerCepstrogram_getQuefrencyStep)
-	LOOP {
-		iam (PowerCepstrogram);
-		Melder_informationReal (my dy, U" quefrency step (s)");
-	}
-END
-
-FORM (PowerCepstrogram_subtractTilt, U"PowerCepstrogram: Subtract tilt", 0)
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 2)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	CONVERT_EACH (PowerCepstrogram)
+		autoPowerCepstrogram result = PowerCepstrogram_smooth (me, smoothingWindowDuration, quefrencySmoothingWindowDuration);
+	CONVERT_EACH_END (my name, U"_smoothed")
+}
+
+DIRECT (REAL_PowerCepstrogram_getStartQuefrency) {
+	NUMBER_ONE (PowerCepstrogram)
+		double result = my ymin;
+	NUMBER_ONE_END (U" (s)")
+}
+
+DIRECT (REAL_PowerCepstrogram_getEndQuefrency) {
+	NUMBER_ONE (PowerCepstrogram)
+		double result = my ymax;
+	NUMBER_ONE_END (U" (s)")
+}
+
+DIRECT (INTEGER_PowerCepstrogram_getNumberOfQuefrencyBins) {
+	INTEGER_ONE (PowerCepstrogram)
+		long result = my ny;
+	INTEGER_ONE_END (U" quefrency bins")
+}
+
+DIRECT (REAL_PowerCepstrogram_getQuefrencyStep) {
+	NUMBER_ONE (PowerCepstrogram)
+		double result = my dy;
+	NUMBER_ONE_END (U" s (quefrency step)")
+}
+
+FORM (NEW_PowerCepstrogram_subtractTilt, U"PowerCepstrogram: Subtract tilt", nullptr) {
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 2)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		autoPowerCepstrogram thee = PowerCepstrogram_subtractTilt (me, GET_REAL (U"left Tilt line quefrency range"), 
-			GET_REAL (U"right Tilt line quefrency range"), GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-		praat_new (thee.move(), my name, U"_minusTilt");
-	}
-END
-
-FORM (PowerCepstrogram_subtractTilt_inline, U"PowerCepstrogram: Subtract tilt (in-line)", nullptr)
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 2)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	CONVERT_EACH (PowerCepstrogram)
+		autoPowerCepstrogram result = PowerCepstrogram_subtractTilt (me, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	CONVERT_EACH_END (my name, U"_minusTilt")
+}
+
+FORM (MODIFY_PowerCepstrogram_subtractTilt_inline, U"PowerCepstrogram: Subtract tilt (in-line)", nullptr) {
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 2)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		PowerCepstrogram_subtractTilt_inline (me, GET_REAL (U"left Tilt line quefrency range"), 
-			GET_REAL (U"right Tilt line quefrency range"), GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-	}
-END
-
-FORM (PowerCepstrogram_getCPPS_hillenbrand, U"PowerCepstrogram: Get CPPS", nullptr)
+	MODIFY_EACH (PowerCepstrogram)
+		PowerCepstrogram_subtractTilt_inline (me, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	MODIFY_EACH_END
+}
+
+FORM (REAL_PowerCepstrogram_getCPPS_hillenbrand, U"PowerCepstrogram: Get CPPS", nullptr) {
 	LABEL (U"", U"Smoothing:")
-	BOOLEAN (U"Subtract tilt before smoothing", true)
-	REAL (U"Time averaging window (s)", U"0.001")
-	REAL (U"Quefrency averaging window (s)", U"0.00005")
+	BOOLEANVAR (subtractTiltBeforeSmoothing, U"Subtract tilt before smoothing", true)
+	REALVAR (smoothinWindowDuration, U"Time averaging window (s)", U"0.001")
+	REALVAR (quefrencySmoothinWindowDuration, U"Quefrency averaging window (s)", U"0.00005")
 	LABEL (U"", U"Peak search:")
-	REAL (U"left Peak search pitch range (Hz)", U"60.0")
-	REAL (U"right Peak search pitch range (Hz)", U"330.0")
+	REALVAR (fromPitch, U"left Peak search pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Peak search pitch range (Hz)", U"330.0")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		double cpps = PowerCepstrogram_getCPPS_hillenbrand (me, GET_INTEGER (U"Subtract tilt before smoothing"), GET_REAL (U"Time averaging window"), GET_REAL (U"Quefrency averaging window"),
-			GET_REAL (U"left Peak search pitch range"), GET_REAL (U"right Peak search pitch range"));
-		Melder_informationReal (cpps, U" dB");
-	}
-END
-
+	NUMBER_ONE (PowerCepstrogram)
+		double result = PowerCepstrogram_getCPPS_hillenbrand (me, subtractTiltBeforeSmoothing, smoothinWindowDuration, quefrencySmoothinWindowDuration, fromPitch, toPitch);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (PowerCepstrogram_getCPPS, U"PowerCepstrogram: Get CPPS", nullptr)
+FORM (REAL_PowerCepstrogram_getCPPS, U"PowerCepstrogram: Get CPPS", nullptr) {
 	LABEL (U"", U"Smoothing:")
-	BOOLEAN (U"Subtract tilt before smoothing", true)
-	REAL (U"Time averaging window (s)", U"0.001")
-	REAL (U"Quefrency averaging window (s)", U"0.00005")
+	BOOLEANVAR (subtractTiltBeforeSmoothing, U"Subtract tilt before smoothing", true)
+	REALVAR (smoothingWindowDuration, U"Time averaging window (s)", U"0.02")
+	REALVAR (quefrencySmoothingWindowDuration, U"Quefrency averaging window (s)", U"0.0005")
 	LABEL (U"", U"Peak search:")
-	REAL (U"left Peak search pitch range (Hz)", U"60.0")
-	REAL (U"right Peak search pitch range (Hz)", U"330.0")
-	POSITIVE (U"Tolerance (0-1)", U"0.05")
-	RADIO (U"Interpolation", 2)
-	RADIOBUTTON (U"None")
-	RADIOBUTTON (U"Parabolic")
-	RADIOBUTTON (U"Cubic")
-	RADIOBUTTON (U"Sinc70")
+	REALVAR (fromPitch, U"left Peak search pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Peak search pitch range (Hz)", U"330.0")
+	POSITIVEVAR (tolerance, U"Tolerance (0-1)", U"0.05")
+	RADIOVAR (interpolationMethod, U"Interpolation", 2)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
 	LABEL (U"", U"Tilt line:")
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 2)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 2)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		double cpps = PowerCepstrogram_getCPPS (me, GET_INTEGER (U"Subtract tilt before smoothing"), GET_REAL (U"Time averaging window"), 
-			GET_REAL (U"Quefrency averaging window"),
-			GET_REAL (U"left Peak search pitch range"), GET_REAL (U"right Peak search pitch range"), GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Interpolation") - 1, GET_REAL (U"left Tilt line quefrency range"), GET_REAL (U"right Tilt line quefrency range"),
-			GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-		Melder_informationReal (cpps, U" dB");
-	}
-END
-
-FORM (PowerCepstrogram_formula, U"PowerCepstrogram: Formula", nullptr)
+	NUMBER_ONE (PowerCepstrogram)
+		double result = PowerCepstrogram_getCPPS (me, subtractTiltBeforeSmoothing, smoothingWindowDuration, quefrencySmoothingWindowDuration, fromPitch, toPitch, tolerance, interpolationMethod - 1, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	NUMBER_ONE_END (U" dB");
+}
+
+FORM (MODIFY_PowerCepstrogram_formula, U"PowerCepstrogram: Formula", nullptr) {
 	LABEL (U"label", U"Do for all times and quefrencies:")
 	LABEL (U"label", U"   `x' is the time in seconds")
 	LABEL (U"label", U"   `y' is the quefrency in seconds")
 	LABEL (U"label", U"   `self' is the current value")
 	LABEL (U"label", U"   Replace all values with:")
-	TEXTFIELD (U"formula", U"sqrt(self)")
+	TEXTVAR (formula, U"formula", U"sqrt(self)")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		try {
-			Matrix_formula ((Matrix) me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the PowerCepstrogram may have partially changed
-			throw;
-		}
-	}
-END
-
-FORM (PowerCepstrogram_to_PowerCepstrum_slice, U"PowerCepstrogram: To PowerCepstrum (slice)", nullptr)
-	REAL (U"Time (s)", U"0.1")
+	MODIFY_EACH_WEAK (PowerCepstrogram)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (NEW_PowerCepstrogram_to_PowerCepstrum_slice, U"PowerCepstrogram: To PowerCepstrum (slice)", nullptr) {
+	REALVAR (time, U"Time (s)", U"0.1")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		double time = GET_REAL (U"Time");
-		autoPowerCepstrum thee = PowerCepstrogram_to_PowerCepstrum_slice (me, time);
-		praat_new (thee.move(), my name, NUMstring_timeNoDot (time));
-	}
-END
-
-FORM (PowerCepstrogram_to_Table_cpp, U"PowerCepstrogram: To Table (peak prominence)", U"PowerCepstrogram: To Table (peak prominence)...")
-	REAL (U"left Peak search pitch range (Hz)", U"60.0")
-	REAL (U"right Peak search pitch range (Hz)", U"330.0")
-	POSITIVE (U"Tolerance (0-1)", U"0.05")
-	RADIO (U"Interpolation", 2)
-	RADIOBUTTON (U"None")
-	RADIOBUTTON (U"Parabolic")
-	RADIOBUTTON (U"Cubic")
-	RADIOBUTTON (U"Sinc70")
-	REAL (U"left Tilt line quefrency range (s)", U"0.001")
-	REAL (U"right Tilt line quefrency range (s)", U"0.0 (= end)")
-	OPTIONMENU (U"Line type", 2)
-	OPTION (U"Straight")
-	OPTION (U"Exponential decay")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
+	CONVERT_EACH (PowerCepstrogram)
+		autoPowerCepstrum result = PowerCepstrogram_to_PowerCepstrum_slice (me, time);
+	CONVERT_EACH_END (my name, NUMstring_timeNoDot (time));
+}
+
+FORM (NEW_PowerCepstrogram_to_Table_cpp, U"PowerCepstrogram: To Table (peak prominence)", U"PowerCepstrogram: To Table (peak prominence)...") {
+	REALVAR (fromPitch, U"left Peak search pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Peak search pitch range (Hz)", U"330.0")
+	POSITIVEVAR (tolerance, U"Tolerance (0-1)", U"0.05")
+	RADIOVAR (interpolationMethod, U"Interpolation", 2)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+	REALVAR (fromQuefrency_tiltLine, U"left Tilt line quefrency range (s)", U"0.001")
+	REALVAR (toQuefrency_tiltLine, U"right Tilt line quefrency range (s)", U"0.0 (= end)")
+	OPTIONMENUVAR (lineType, U"Line type", 2)
+		OPTION (U"Straight")
+		OPTION (U"Exponential decay")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		autoTable thee = PowerCepstrogram_to_Table_cpp (me,
-			GET_REAL (U"left Peak search pitch range"), GET_REAL (U"right Peak search pitch range"), GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Interpolation") - 1,
-			GET_REAL (U"left Tilt line quefrency range"), GET_REAL (U"right Tilt line quefrency range"),
-			GET_INTEGER (U"Line type"), GET_INTEGER (U"Fit method"));
-		praat_new (thee.move(), my name, U"_cpp");
-	}
-END
-
-FORM (PowerCepstrogram_to_Table_hillenbrand, U"PowerCepstrogram: To Table (hillenbrand)", U"PowerCepstrogram: To Table (peak prominence...")
-	REAL (U"left Peak search pitch range (Hz)", U"60.0")
-	REAL (U"right Peak search pitch range (Hz)", U"330.0")
+	CONVERT_EACH (PowerCepstrogram)
+		autoTable result = PowerCepstrogram_to_Table_cpp (me, fromPitch, toPitch, tolerance, interpolationMethod - 1, fromQuefrency_tiltLine, toQuefrency_tiltLine, lineType, fitMethod);
+	CONVERT_EACH_END (my name, U"_cpp");
+}
+
+FORM (NEW_PowerCepstrogram_to_Table_hillenbrand, U"PowerCepstrogram: To Table (hillenbrand)", U"PowerCepstrogram: To Table (peak prominence...") {
+	REALVAR (fromPitch, U"left Peak search pitch range (Hz)", U"60.0")
+	REALVAR (toPitch, U"right Peak search pitch range (Hz)", U"330.0")
 	OK
 DO
-	LOOP {
-		iam (PowerCepstrogram);
-		autoTable thee = PowerCepstrogram_to_Table_hillenbrand (me,
-			GET_REAL (U"left Peak search pitch range"), GET_REAL (U"right Peak search pitch range"));
-		praat_new (thee.move(), my name, U"_cpp");
-	}
-END
-
-DIRECT (PowerCepstrogram_to_Matrix)
-	LOOP {
-		iam (PowerCepstrogram);
-		autoMatrix thee = PowerCepstrogram_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (PowerCepstrogram)
+		autoTable result = PowerCepstrogram_to_Table_hillenbrand (me,fromPitch, toPitch);
+	CONVERT_EACH_END (my name, U"_cpp")
+}
+
+DIRECT (NEW_PowerCepstrogram_to_Matrix) {
+	CONVERT_EACH (PowerCepstrogram)
+		autoMatrix result = PowerCepstrogram_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** Cepstrumc  ****************************************/
 
-DIRECT (Cepstrumc_to_LPC)
-	LOOP {
-		iam (Cepstrumc);
-		autoLPC thee = Cepstrumc_to_LPC (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Cepstrumc_to_LPC) {
+	CONVERT_EACH (Cepstrumc)
+		autoLPC result = Cepstrumc_to_LPC (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Cepstrumc_to_DTW, U"Cepstrumc: To DTW", U"Cepstrumc: To DTW...")
+FORM (NEW1_Cepstrumc_to_DTW, U"Cepstrumc: To DTW", U"Cepstrumc: To DTW...") {
 	LABEL (U"", U"Distance calculation between Cepstra")
-	REAL (U"Cepstral weight", U"1.0")
-	REAL (U"Log energy weight", U"0.0")
-	REAL (U"Regression weight", U"0.0")
-	REAL (U"Regression weight log energy", U"0.0")
-	REAL (U"Window for regression coefficients (seconds)", U"0.056")
+	REALVAR (cepstralWeight, U"Cepstral weight", U"1.0")
+	REALVAR (logEnergyWeight, U"Log energy weight", U"0.0")
+	REALVAR (regressionWeight, U"Regression weight", U"0.0")
+	REALVAR (regressionLogEnergyWeight, U"Regression weight log energy", U"0.0")
+	REALVAR (windowDuration, U"Window for regression coefficients (seconds)", U"0.056")
 	LABEL (U"", U"Boundary conditions for time warp")
-	BOOLEAN (U"Match begin positions", false)
-	BOOLEAN (U"Match end positions", false)
-	RADIO (U"Slope constraints", 1)
-	RADIOBUTTON (U"no restriction")
-	RADIOBUTTON (U"1/3 < slope < 3")
-	RADIOBUTTON (U"1/2 < slope < 2")
-	RADIOBUTTON (U"2/3 < slope < 3/2")
+	BOOLEANVAR (matchBeginPositions, U"Match begin positions", false)
+	BOOLEANVAR (matchEndPositions, U"Match end positions", false)
+	RADIOVAR (slopeConstraintType, U"Slope constraints", 1)
+		RADIOBUTTON (U"no restriction")
+		RADIOBUTTON (U"1/3 < slope < 3")
+		RADIOBUTTON (U"1/2 < slope < 2")
+		RADIOBUTTON (U"2/3 < slope < 3/2")
 	OK
 DO
-	Cepstrumc c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Cepstrumc);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	autoDTW thee = Cepstrumc_to_DTW (c1, c2, GET_REAL (U"Cepstral weight"),
-		GET_REAL (U"Log energy weight"), GET_REAL (U"Regression weight"),
-		GET_REAL (U"Regression weight log energy"), GET_REAL (U"Window for regression coefficients"),
-		GET_INTEGER (U"Match begin positions"), GET_INTEGER (U"Match end positions"),
-		GET_INTEGER (U"Slope constraints"));
-	praat_new (thee.move(), c1 -> name, U"_", c2 -> name);
-END
-
-DIRECT (Cepstrumc_to_Matrix)
-	LOOP {
-		iam (Cepstrumc);
-		autoMatrix thee = Cepstrumc_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_COUPLE (Cepstrumc)
+		autoDTW result = Cepstrumc_to_DTW (me, you, cepstralWeight, logEnergyWeight, regressionWeight, regressionLogEnergyWeight, windowDuration, matchBeginPositions, matchEndPositions, slopeConstraintType);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
+
+DIRECT (NEW_Cepstrumc_to_Matrix) {
+	CONVERT_EACH (Cepstrumc)
+		autoMatrix result = Cepstrumc_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
 /******************** Formant ********************************************/
 
-FORM (Formant_to_LPC, U"Formant: To LPC", nullptr)
-	POSITIVE (U"Sampling frequency (Hz)", U"16000.0")
+FORM (NEW_Formant_to_LPC, U"Formant: To LPC", nullptr) {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"16000.0")
 	OK
 DO
-	LOOP {
-		iam (Formant);
-		autoLPC thee = Formant_to_LPC (me, 1.0 / GET_REAL (U"Sampling frequency"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Formant_formula, U"Formant: Formula", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	NATURAL (U"left Formant range", U"1")
-	NATURAL (U"right Formant range", U"5")
+	CONVERT_EACH (Formant)
+		autoLPC result = Formant_to_LPC (me, 1.0 / samplingFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (MODIFY_Formant_formula, U"Formant: Formula", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	NATURALVAR (fromFormant, U"left Formant range", U"1")
+	NATURALVAR (toFormant, U"right Formant range", U"5")
 	LABEL (U"", U"Formant frequencies in odd numbered rows")
 	LABEL (U"", U"Formant bandwidths in even numbered rows")
-	SENTENCE (U"Formula", U"if row mod 2 = 1 and self[row,col]/self[row+1,col] < 5 then 0 else self fi")
+	SENTENCEVAR (formula, U"Formula", U"if row mod 2 = 1 and self[row,col]/self[row+1,col] < 5 then 0 else self fi")
 	OK
 DO
-	char32 *expression = GET_STRING (U"Formula");
-	LOOP {
-		iam (Formant);
-		Formant_formula (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"), interpreter, expression);
-	}
-END
+	MODIFY_EACH_WEAK (Formant)
+		Formant_formula (me, fromTime, toTime, fromFormant, toFormant, interpreter, formula);
+	MODIFY_EACH_WEAK_END
+}
 
 /******************** Formant & Spectrogram ************************************/
 
-FORM (Formant_and_Spectrogram_to_IntensityTier, U"Formant & Spectrogram: To IntensityTier", U"Formant & Spectrogram: To IntensityTier...")
-	NATURAL (U"Formant number", U"1")
+FORM (NEW1_Formant_and_Spectrogram_to_IntensityTier, U"Formant & Spectrogram: To IntensityTier", U"Formant & Spectrogram: To IntensityTier...") {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	Formant me = FIRST (Formant);
-	long iformant = GET_INTEGER (U"Formant number");
-	Spectrogram thee = FIRST (Spectrogram);
-	autoIntensityTier him = Formant_and_Spectrogram_to_IntensityTier (me, thee, iformant);
-	praat_new (him.move(), my name, U"_", GET_INTEGER (U"Formant number"));
-END
+	CONVERT_TWO (Formant, Spectrogram)
+		autoIntensityTier result = Formant_and_Spectrogram_to_IntensityTier (me, you, formantNumber);
+	CONVERT_TWO_END (my name, U"_", formantNumber)
+}
 
 /********************LFCC ********************************************/
 
-DIRECT (LFCC_help)
-	Melder_help (U"LFCC");
-END
+DIRECT (HELP_LFCC_help) {
+	HELP (U"LFCC")
+}
 
-FORM (LFCC_to_LPC, U"LFCC: To LPC", U"LFCC: To LPC...")
-	INTEGER (U"Number of coefficients", U"0")
+FORM (NEW_LFCC_to_LPC, U"LFCC: To LPC", U"LFCC: To LPC...") {
+	INTEGERVAR (numberOfCoefficients, U"Number of coefficients", U"0")
 	OK
 DO
-	long ncof = GET_INTEGER (U"Number of coefficients");
-	if (ncof < 0) {
-		Melder_throw (U"Number of coefficients must be greater or equal zero.");
-	}
-	LOOP {
-		iam (LFCC);
-		autoLPC thee = LFCC_to_LPC (me, ncof);
-		praat_new (thee.move(), my name);
-	}
-END
+	REQUIRE (numberOfCoefficients >= 0, U"Number of coefficients must be greater or equal zero.")
+	CONVERT_EACH (LFCC)
+		autoLPC result = LFCC_to_LPC (me, numberOfCoefficients);
+	CONVERT_EACH_END (my name);
+}
 
 /********************LineSpectralFrequencies ********************************************/
 
-DIRECT (LineSpectralFrequencies_help) Melder_help (U"LineSpectralFrequencies"); END
+DIRECT (HELP_LineSpectralFrequencies_help) {
+	HELP (U"LineSpectralFrequencies")
+}
 
-FORM (LineSpectralFrequencies_drawFrequencies, U"LineSpectralFrequencies: Draw frequencies", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"5000.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_LineSpectralFrequencies_drawFrequencies, U"LineSpectralFrequencies: Draw frequencies", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"5000.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (LineSpectralFrequencies);
-		LineSpectralFrequencies_drawFrequencies (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-DIRECT (LineSpectralFrequencies_to_LPC)
-	LOOP {
-		iam (LineSpectralFrequencies);
-		autoLPC thee = LineSpectralFrequencies_to_LPC (me);
-		praat_new (thee.move(), my name);
-	}
-END
+	GRAPHICS_EACH (LineSpectralFrequencies)
+		LineSpectralFrequencies_drawFrequencies (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (NEW_LineSpectralFrequencies_to_LPC) {
+	CONVERT_EACH (LineSpectralFrequencies)
+		autoLPC result = LineSpectralFrequencies_to_LPC (me);
+	CONVERT_EACH_END (my name);
+}
 
 /********************LPC ********************************************/
 
-DIRECT (LPC_help) Melder_help (U"LPC"); END
+DIRECT (HELP_LPC_help) {
+	HELP (U"LPC")
+}
 
-FORM (LPC_drawGain, U"LPC: Draw gain", U"LPC: Draw gain...")
-	REAL (U"From time (seconds)", U"0.0")
-	REAL (U"To time (seconds)", U"0.0 (= all)")
-	REAL (U"Minimum gain", U"0.0")
-	REAL (U"Maximum gain", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_LPC_drawGain, U"LPC: Draw gain", U"LPC: Draw gain...") {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (minimumGain, U"Minimum gain", U"0.0")
+	REALVAR (maximumGain, U"Maximum gain", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (LPC);
-		LPC_drawGain (me, GRAPHICS, GET_REAL (U"From time"), GET_REAL (U"To time"),
-			GET_REAL (U"Minimum gain"), GET_REAL (U"Maximum gain"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-DIRECT (LPC_getSamplingInterval)
-	LOOP {
-		iam (LPC);
-		Melder_information (my samplingPeriod, U" seconds");
-	}
-END
-
-FORM (LPC_getNumberOfCoefficients, U"LPC: Get number of coefficients", U"LPC: Get number of coefficients...")
-	NATURAL (U"Frame number", U"1")
+	GRAPHICS_EACH (LPC)
+		LPC_drawGain (me, GRAPHICS, fromTime, toTime, minimumGain, maximumGain, garnish);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (REAL_LPC_getSamplingInterval) {
+	NUMBER_ONE (LPC)
+		double result = my samplingPeriod;
+	NUMBER_ONE_END (U" s");
+}
+
+FORM (INTEGER_LPC_getNumberOfCoefficients, U"LPC: Get number of coefficients", U"LPC: Get number of coefficients...") {
+	NATURALVAR (frameNumber, U"Frame number", U"1")
 	OK
 DO
-	long iframe = GET_INTEGER (U"Frame number");
-	LOOP {
-		iam (LPC);
-		if (iframe > my nx) {
-			Melder_throw (U"Frame number is too large.\n\nPlease choose a number between 1 and ", my nx);
-		}
-		Melder_information (my d_frames[iframe].nCoefficients, U" coefficients");
-	}
-END
-
-FORM (LPC_drawPoles, U"LPC: Draw poles", U"LPC: Draw poles...")
-	REAL (U"Time (seconds)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	INTEGER_ONE (LPC)
+		REQUIRE (frameNumber <= my nx, Melder_cat (U"Frame number is too large.\n\nPlease choose a number between 1 and ", my nx))
+		long result = my d_frames[frameNumber].nCoefficients;
+	INTEGER_ONE_END (U" coefficients")
+}
+
+FORM (GRAPHICS_LPC_drawPoles, U"LPC: Draw poles", U"LPC: Draw poles...") {
+	REALVAR (time, U"Time (seconds)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (LPC);
-		LPC_drawPoles (me, GRAPHICS, GET_REAL (U"Time"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-DIRECT (LPC_to_Formant)
-	LOOP {
-		iam (LPC);
-		autoFormant thee = LPC_to_Formant (me, 50.0);
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (LPC_to_Formant_keep_all)
-	LOOP {
-		iam (LPC);
-		autoFormant thee = LPC_to_Formant (me, 0.0);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (LPC_to_LFCC, U"LPC: To LFCC", U"LPC: To LFCC...")
-	INTEGER (U"Number of coefficients", U"0")
+	GRAPHICS_EACH (LPC)
+		LPC_drawPoles (me, GRAPHICS, time, garnish);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (NEW_LPC_to_Formant) {
+	CONVERT_EACH (LPC)
+		autoFormant result = LPC_to_Formant (me, 50.0);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_LPC_to_Formant_keep_all) {
+	CONVERT_EACH (LPC)
+		autoFormant result = LPC_to_Formant (me, 0.0);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_LPC_to_LFCC, U"LPC: To LFCC", U"LPC: To LFCC...") {
+	INTEGERVAR (numberOfCoefficients, U"Number of coefficients", U"0")
 	OK
 DO
-	long ncof = GET_INTEGER (U"Number of coefficients");
-	if (ncof < 0) {
-		Melder_throw (U"Number of coefficients must be greater or equal zero.");
-	}
-	LOOP {
-		iam (LPC);
-		autoLFCC thee = LPC_to_LFCC (me, ncof);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (LPC_to_LineSpectralFrequencies, U"LPC: To LineSpectralFrequencies", nullptr)
-	REAL (U"Grid size", U"0.0")
+	REQUIRE (numberOfCoefficients >= 0, U"The number of coefficients should be greater than or equal to zero.")
+	CONVERT_EACH (LPC)
+		autoLFCC result = LPC_to_LFCC (me, numberOfCoefficients);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_LPC_to_LineSpectralFrequencies, U"LPC: To LineSpectralFrequencies", nullptr) {
+	REALVAR (gridSize, U"Grid size", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (LPC);
-		autoLineSpectralFrequencies thee = LPC_to_LineSpectralFrequencies (me, GET_REAL (U"Grid size"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (LPC_to_Polynomial, U"LPC: To Polynomial", U"LPC: To Polynomial (slice)...")
-	REAL (U"Time (seconds)", U"0.0")
+	CONVERT_EACH (LPC)
+		autoLineSpectralFrequencies result = LPC_to_LineSpectralFrequencies (me, gridSize);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_LPC_to_Polynomial, U"LPC: To Polynomial", U"LPC: To Polynomial (slice)...") {
+	REALVAR (time, U"Time (s)", U"0.0")
 	OK
 DO
-	double time = GET_REAL (U"Time");
-	LOOP {
-		iam (LPC);
-		autoPolynomial thee = LPC_to_Polynomial (me, time);
-		praat_new (thee.move(), my name, NUMstring_timeNoDot (time));
-	}
-END
-
-FORM (LPC_to_Spectrum, U"LPC: To Spectrum", U"LPC: To Spectrum (slice)...")
-	REAL (U"Time (seconds)", U"0.0")
-	REAL (U"Minimum frequency resolution (Hz)", U"20.0")
-	REAL (U"Bandwidth reduction (Hz)", U"0.0")
-	REAL (U"De-emphasis frequency (Hz)", U"50.0")
+	CONVERT_EACH (LPC)
+		autoPolynomial result = LPC_to_Polynomial (me, time);
+	CONVERT_EACH_END (my name, NUMstring_timeNoDot (time))
+}
+
+FORM (NEW_LPC_to_Spectrum, U"LPC: To Spectrum", U"LPC: To Spectrum (slice)...") {
+	REALVAR (time, U"Time (seconds)", U"0.0")
+	REALVAR (minimumFrequencyResolution, U"Minimum frequency resolution (Hz)", U"20.0")
+	REALVAR (bandwidthReduction, U"Bandwidth reduction (Hz)", U"0.0")
+	REALVAR (deemphasisFrequency, U"De-emphasis frequency (Hz)", U"50.0")
 	OK
 DO
-	LOOP {
-		iam (LPC);
-		double time = GET_REAL (U"Time");
-		autoSpectrum thee = LPC_to_Spectrum (me, time, GET_REAL (U"Minimum frequency resolution"),
-		GET_REAL (U"Bandwidth reduction"), GET_REAL (U"De-emphasis frequency"));
-		praat_new (thee.move(), my name, NUMstring_timeNoDot (time));
-	}
-END
-
-FORM (LPC_to_Spectrogram, U"LPC: To Spectrogram", U"LPC: To Spectrogram...")
-	REAL (U"Minimum frequency resolution (Hz)", U"20.0")
-	REAL (U"Bandwidth reduction (Hz)", U"0.0")
-	REAL (U"De-emphasis frequency (Hz)", U"50.0")
+	CONVERT_EACH (LPC)
+		autoSpectrum result = LPC_to_Spectrum (me, time, minimumFrequencyResolution, bandwidthReduction, deemphasisFrequency);
+	CONVERT_EACH_END (my name, NUMstring_timeNoDot (time))
+}
+
+FORM (NEW_LPC_to_Spectrogram, U"LPC: To Spectrogram", U"LPC: To Spectrogram...") {
+	REALVAR (minimumFrequencyResolution, U"Minimum frequency resolution (Hz)", U"20.0")
+	REALVAR (bandwidthReduction, U"Bandwidth reduction (Hz)", U"0.0")
+	REALVAR (deemphasisFrequency, U"De-emphasis frequency (Hz)", U"50.0")
 	OK
 DO
-	LOOP {
-		iam (LPC);
-		autoSpectrogram thee = LPC_to_Spectrogram (me, GET_REAL (U"Minimum frequency resolution"), GET_REAL (U"Bandwidth reduction"), GET_REAL (U"De-emphasis frequency"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (LPC_to_VocalTract_special, U"LPC: To VocalTract", U"LPC: To VocalTract (slice, special)...")
-	REAL (U"Time (s)", U"0.0")
-	REAL (U"Glottal damping", U"0.1")
-	BOOLEAN (U"Radiation damping", true)
-	BOOLEAN (U"Internal damping", true)
+	CONVERT_EACH (LPC)
+		autoSpectrogram result = LPC_to_Spectrogram (me, minimumFrequencyResolution, bandwidthReduction, deemphasisFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_LPC_to_VocalTract_special, U"LPC: To VocalTract", U"LPC: To VocalTract (slice, special)...") {
+	REALVAR (time, U"Time (s)", U"0.0")
+	REALVAR (glottalDamping, U"Glottal damping", U"0.1")
+	BOOLEANVAR (radiationDamping, U"Radiation damping", true)
+	BOOLEANVAR (internalDamping, U"Internal damping", true)
 	OK
 DO
-	double glottalDamping = GET_REAL (U"Glottal damping");
-	bool radiationDamping = GET_INTEGER (U"Radiation damping");
-	bool internalDamping = GET_INTEGER (U"Internal damping");
-	LOOP {
-		iam (LPC);
-		double time = GET_REAL (U"Time");
-		autoVocalTract thee = LPC_to_VocalTract (me, time, glottalDamping, radiationDamping, internalDamping);
-		praat_new (thee.move(), my name, NUMstring_timeNoDot (time));
-	}
-END
-
-FORM (LPC_to_VocalTract, U"LPC: To VocalTract", U"LPC: To VocalTract (slice)...")
-	REAL (U"Time (s)", U"0.0")
-	POSITIVE (U"Length (m)", U"0.17")
+	CONVERT_EACH (LPC)
+		autoVocalTract result = LPC_to_VocalTract (me, time, glottalDamping, radiationDamping, internalDamping);
+	CONVERT_EACH_END (my name, NUMstring_timeNoDot (time))
+}
+
+FORM (NEW_LPC_to_VocalTract, U"LPC: To VocalTract", U"LPC: To VocalTract (slice)...") {
+	REALVAR (time, U"Time (s)", U"0.0")
+	POSITIVEVAR (lenght, U"Length (m)", U"0.17")
 	OK
 DO
-	double time = GET_REAL (U"Time");
-	LOOP {
-		iam (LPC);
-		autoVocalTract thee = LPC_to_VocalTract (me, time, GET_REAL (U"Length"));
-		praat_new (thee.move(), my name, NUMstring_timeNoDot (time));
-	}
-END
-
-DIRECT (LPC_downto_Matrix_lpc)
-	LOOP {
-		iam (LPC);
-		autoMatrix thee = LPC_downto_Matrix_lpc (me);
-		praat_new (thee.move(), my name, U"_lpc");
-	}
-END
-
-DIRECT (LPC_downto_Matrix_rc)
-	LOOP {
-		iam (LPC);
-		autoMatrix thee = LPC_downto_Matrix_rc (me);
-		praat_new (thee.move(), my name, U"_rc");
-	}
-END
-
-DIRECT (LPC_downto_Matrix_area)
-	LOOP {
-		iam (LPC);
-		autoMatrix thee = LPC_downto_Matrix_area (me);
-		praat_new (thee.move(), my name, U"_area");
-	}
-END
+	CONVERT_EACH (LPC)
+		autoVocalTract result = LPC_to_VocalTract (me, time, lenght);
+	CONVERT_EACH_END (my name, NUMstring_timeNoDot (time))
+}
+
+DIRECT (NEW_LPC_downto_Matrix_lpc) {
+	CONVERT_EACH (LPC)
+		autoMatrix result = LPC_downto_Matrix_lpc (me);
+	CONVERT_EACH_END (my name, U"_lpc")
+}
+
+DIRECT (NEW_LPC_downto_Matrix_rc) {
+	CONVERT_EACH (LPC)
+		autoMatrix result = LPC_downto_Matrix_rc (me);
+	CONVERT_EACH_END (my name, U"_rc");
+}
+
+DIRECT (NEW_LPC_downto_Matrix_area) {
+	CONVERT_EACH (LPC)
+		autoMatrix result = LPC_downto_Matrix_area (me);
+	CONVERT_EACH_END (my name, U"_area");
+}
 
 /********************** Sound *******************************************/
 
-FORM (Sound_to_PowerCepstrogram, U"Sound: To PowerCepstrogram", U"Sound: To PowerCepstrogram...")
-	POSITIVE (U"Pitch floor (Hz)", U"60.0")
-	POSITIVE (U"Time step (s)", U"0.002")
-	POSITIVE (U"Maximum frequency (Hz)", U"5000.0")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50")
+FORM (NEW_Sound_to_PowerCepstrogram, U"Sound: To PowerCepstrogram", U"Sound: To PowerCepstrogram...") {
+	POSITIVEVAR (pitchFloor, U"Pitch floor (Hz)", U"60.0")
+	POSITIVEVAR (timeStep,U"Time step (s)", U"0.002")
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoPowerCepstrogram thee = Sound_to_PowerCepstrogram (me, GET_REAL (U"Pitch floor"), GET_REAL (U"Time step"), GET_REAL(U"Maximum frequency"),
-			 GET_REAL (U"Pre-emphasis from"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-
-FORM (Sound_to_PowerCepstrogram_hillenbrand, U"Sound: To PowerCepstrogram (hillenbrand)", U"Sound: To PowerCepstrogram...")
-	POSITIVE (U"Pitch floor (Hz)", U"60.0")
-	POSITIVE (U"Time step (s)", U"0.002")
+	CONVERT_EACH (Sound)
+		autoPowerCepstrogram result = Sound_to_PowerCepstrogram (me, pitchFloor, timeStep, maximumFrequency, preEmphasisFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+
+FORM (NEW_Sound_to_PowerCepstrogram_hillenbrand, U"Sound: To PowerCepstrogram (hillenbrand)", U"Sound: To PowerCepstrogram...") {
+	POSITIVEVAR (pitchFloor, U"Pitch floor (Hz)", U"60.0")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.002")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoPowerCepstrogram thee = Sound_to_PowerCepstrogram_hillenbrand (me, GET_REAL (U"Pitch floor"), GET_REAL (U"Time step"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoPowerCepstrogram result = Sound_to_PowerCepstrogram_hillenbrand (me, pitchFloor, timeStep);
+	CONVERT_EACH_END (my name)
+}
 	
-FORM (Sound_to_Formant_robust, U"Sound: To Formant (robust)", U"Sound: To Formant (robust)...")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Max. number of formants", U"5.0")
-	REAL (U"Maximum formant (Hz)", U"5500 (= adult female)")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50")
-	POSITIVE (U"Number of std. dev.", U"1.5")
-	NATURAL (U"Maximum number of iterations", U"5")
-	REAL (U"Tolerance", U"0.000001")
+FORM (NEW_Sound_to_Formant_robust, U"Sound: To Formant (robust)", U"Sound: To Formant (robust)...") {
+	REALVAR (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVEVAR (maximumNumberOfFormants, U"Max. number of formants", U"5.0")
+	REALVAR (maximumFormantFrequency, U"Maximum formant (Hz)", U"5500.0 (= adult female)")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
+	POSITIVEVAR (numberOfStandardDeviations, U"Number of std. dev.", U"1.5")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"5")
+	REALVAR (tolerance, U"Tolerance", U"0.000001")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		praat_new (Sound_to_Formant_robust (me, GET_REAL (U"Time step"), GET_REAL (U"Max. number of formants"),
-			GET_REAL (U"Maximum formant"), GET_REAL (U"Window length"), GET_REAL (U"Pre-emphasis from"), 50.0,
-			GET_REAL (U"Number of std. dev."), GET_INTEGER (U"Maximum number of iterations"),
-			GET_REAL (U"Tolerance"), 1), my name);
-	}
-END
-
-static void Sound_to_LPC_addCommonFields (UiForm dia) {
+	CONVERT_EACH (Sound)
+		autoFormant result = Sound_to_Formant_robust (me, timeStep, maximumNumberOfFormants, maximumFormantFrequency, windowLength, preEmphasisFrequency, 50.0, numberOfStandardDeviations, maximumNumberOfIterations, tolerance, 1);
+	CONVERT_EACH_END (my name)
+}
+
+static void Sound_to_LPC_addWarning (UiForm dia) {
 	LABEL (U"", U"Warning 1:  for formant analysis, use \"To Formant\" instead.")
 	LABEL (U"", U"Warning 2:  if you do use \"To LPC\", you may want to resample first.")
 	LABEL (U"", U"Click Help for more details.")
 	LABEL (U"", U"")
-	NATURAL (U"Prediction order", U"16")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Time step (s)", U"0.005")
-	REAL (U"Pre-emphasis frequency (Hz)", U"50.0")
 }
 
-static void Sound_to_LPC_checkCommonFields (UiForm dia, long *predictionOrder, double *analysisWindowDuration,
-        double *timeStep, double *preemphasisFrequency) {
-	*predictionOrder = GET_INTEGER (U"Prediction order");
-	*analysisWindowDuration = GET_REAL (U"Window length");
-	*timeStep = GET_REAL (U"Time step");
-	*preemphasisFrequency = GET_REAL (U"Pre-emphasis frequency");
-	if (*preemphasisFrequency < 0.0) {
-		Melder_throw (U"Pre-emphasis frequencies cannot be negative.");
-	}
-}
-
-FORM (Sound_to_LPC_auto, U"Sound: To LPC (autocorrelation)", U"Sound: To LPC (autocorrelation)...")
-	Sound_to_LPC_addCommonFields (dia);
+FORM (NEW_Sound_to_LPC_auto, U"Sound: To LPC (autocorrelation)", U"Sound: To LPC (autocorrelation)...") {
+	Sound_to_LPC_addWarning (dia);
+	NATURALVAR (predictionOrder, U"Prediction order", U"16")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
+	REALVAR (preEmphasisFrequency, U"Pre-emphasis frequency (Hz)", U"50.0")
 	OK
 DO
-	long numberOfPoles;
-	double analysisWindowDuration, timeStep, preemphasisFrequency;
-	Sound_to_LPC_checkCommonFields (dia, & numberOfPoles, & analysisWindowDuration, & timeStep, &preemphasisFrequency);
-	LOOP {
-		iam (Sound);
-		autoLPC thee = Sound_to_LPC_auto (me, numberOfPoles, analysisWindowDuration, timeStep, preemphasisFrequency);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_LPC_covar, U"Sound: To LPC (covariance)", U"Sound: To LPC (covariance)...")
-	Sound_to_LPC_addCommonFields (dia);
+	preEmphasisFrequency = preEmphasisFrequency < 0.0 ? 0.0 : preEmphasisFrequency;
+	CONVERT_EACH (Sound)
+		autoLPC result = Sound_to_LPC_auto (me, predictionOrder, windowLength, timeStep, preEmphasisFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_LPC_covar, U"Sound: To LPC (covariance)", U"Sound: To LPC (covariance)...") {
+	Sound_to_LPC_addWarning (dia);
+	NATURALVAR (predictionOrder, U"Prediction order", U"16")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
+	REALVAR (preEmphasisFrequency, U"Pre-emphasis frequency (Hz)", U"50.0")
 	OK
 DO
-	long numberOfPoles;
-	double analysisWindowDuration, timeStep, preemphasisFrequency;
-	Sound_to_LPC_checkCommonFields (dia, & numberOfPoles, & analysisWindowDuration, & timeStep, & preemphasisFrequency);
-	LOOP {
-		iam (Sound);
-		autoLPC thee = Sound_to_LPC_covar (me, numberOfPoles, analysisWindowDuration, timeStep, preemphasisFrequency);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_LPC_burg, U"Sound: To LPC (burg)", U"Sound: To LPC (burg)...")
-	Sound_to_LPC_addCommonFields (dia);
+	preEmphasisFrequency = preEmphasisFrequency < 0.0 ? 0.0 : preEmphasisFrequency;
+	CONVERT_EACH (Sound)
+		autoLPC result = Sound_to_LPC_covar (me, predictionOrder, windowLength, timeStep, preEmphasisFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_LPC_burg, U"Sound: To LPC (burg)", U"Sound: To LPC (burg)...") {
+	Sound_to_LPC_addWarning (dia);
+	NATURALVAR (predictionOrder, U"Prediction order", U"16")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
+	REALVAR (preEmphasisFrequency, U"Pre-emphasis frequency (Hz)", U"50.0")
 	OK
 DO
-	long numberOfPoles;
-	double analysisWindowDuration, timeStep, preemphasisFrequency;
-	Sound_to_LPC_checkCommonFields (dia, & numberOfPoles, & analysisWindowDuration, & timeStep, & preemphasisFrequency);
-	LOOP {
-		iam (Sound);
-		autoLPC thee = Sound_to_LPC_burg (me, numberOfPoles, analysisWindowDuration, timeStep, preemphasisFrequency);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_LPC_marple, U"Sound: To LPC (marple)", U"Sound: To LPC (marple)...")
-	Sound_to_LPC_addCommonFields (dia);
-	POSITIVE (U"Tolerance 1", U"1e-6")
-	POSITIVE (U"Tolerance 2", U"1e-6")
+	preEmphasisFrequency = preEmphasisFrequency < 0.0 ? 0.0 : preEmphasisFrequency;
+	CONVERT_EACH (Sound)
+		autoLPC result = Sound_to_LPC_burg (me, predictionOrder, windowLength, timeStep, preEmphasisFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_LPC_marple, U"Sound: To LPC (marple)", U"Sound: To LPC (marple)...") {
+	Sound_to_LPC_addWarning (dia);
+	NATURALVAR (predictionOrder, U"Prediction order", U"16")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
+	REALVAR (preEmphasisFrequency, U"Pre-emphasis frequency (Hz)", U"50.0")
+	POSITIVEVAR (tolerance1, U"Tolerance 1", U"1e-6")
+	POSITIVEVAR (tolerance2, U"Tolerance 2", U"1e-6")
 	OK
 DO
-	long numberOfPoles;
-	double analysisWindowDuration, timeStep, preemphasisFrequency;
-	Sound_to_LPC_checkCommonFields (dia, & numberOfPoles, & analysisWindowDuration, &timeStep, & preemphasisFrequency);
-	LOOP {
-		iam (Sound);
-		autoLPC thee = Sound_to_LPC_marple (me, numberOfPoles, analysisWindowDuration, timeStep, preemphasisFrequency, GET_REAL (U"Tolerance 1"), GET_REAL (U"Tolerance 2"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_MFCC, U"Sound: To MFCC", U"Sound: To MFCC...")
-	NATURAL (U"Number of coefficients", U"12")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+	preEmphasisFrequency = preEmphasisFrequency < 0.0 ? 0.0 : preEmphasisFrequency;
+	CONVERT_EACH (Sound)
+		autoLPC result = Sound_to_LPC_marple (me, predictionOrder, windowLength, timeStep, preEmphasisFrequency, tolerance1, tolerance2);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_MFCC, U"Sound: To MFCC", U"Sound: To MFCC...") {
+	NATURALVAR (numberOfCoefficients, U"Number of coefficients", U"12")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (mel)", U"100.0")
-	POSITIVE (U"Distance between filters (mel)", U"100.0")
-	REAL (U"Maximum frequency (mel)", U"0.0");
+	POSITIVEVAR (firstFilterFrequency, U"First filter frequency (mel)", U"100.0")
+	POSITIVEVAR (distancBetweenFilters, U"Distance between filters (mel)", U"100.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (mel)", U"0.0");
 	OK
 DO
-	long p = GET_INTEGER (U"Number of coefficients");
-	if (p > 24) {
-		Melder_throw (U"Number of coefficients must be < 25.");
-	}
-	LOOP {
-		iam (Sound);
-		praat_new (Sound_to_MFCC (me, p, GET_REAL (U"Window length"),
-			GET_REAL (U"Time step"), GET_REAL (U"Position of first filter"),
-			GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters")), my name);
-	}
-END
-
-FORM (VocalTract_drawSegments, U"VocalTract: Draw segments", nullptr)
-	POSITIVE (U"Maximum length (cm)", U"20.0")
-	POSITIVE (U"Maximum area (cm^2)", U"90.0")
-	BOOLEAN (U"Closed at glottis", true)
+	REQUIRE (numberOfCoefficients < 25, U"The number of coefficients should be less than 25.")
+	CONVERT_EACH (Sound)
+		autoMFCC result = Sound_to_MFCC (me, numberOfCoefficients, windowLength, timeStep, firstFilterFrequency, maximumFrequency, distancBetweenFilters);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (GRAPHICS_VocalTract_drawSegments, U"VocalTract: Draw segments", nullptr) {
+	POSITIVEVAR (maximumLength, U"Maximum length (cm)", U"20.0")
+	POSITIVEVAR (maximumArea, U"Maximum area (cm^2)", U"90.0")
+	BOOLEANVAR (glottisClosed, U"Closed at glottis", true)
 	OK
 DO
-	autoPraatPicture picture;
-	double maxLength = GET_REAL (U"Maximum length") / 100.0;
-	double maxArea = GET_REAL (U"Maximum area") / 10000.0;
-	bool closedAtGlottis = GET_INTEGER (U"Closed at glottis");
-	LOOP {
-		iam (VocalTract);
-		VocalTract_drawSegments (me, GRAPHICS, maxLength, maxArea, closedAtGlottis);
-	}
-END
-
-DIRECT (VocalTract_getLength)
-	LOOP {
-		iam (VocalTract);
-		Melder_information (my xmax - my xmin, U" m");
-	}
-END
-
-FORM (VocalTract_setLength, U"", nullptr)
-	POSITIVE (U"New length (m)", U"0.17")
+	GRAPHICS_EACH (VocalTract)
+		VocalTract_drawSegments (me, GRAPHICS, maximumLength, maximumArea, glottisClosed);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (REAL_VocalTract_getLength) {
+	NUMBER_ONE (VocalTract)
+		double result = my xmax - my xmin;
+	NUMBER_ONE_END (U" metres")
+}
+
+FORM (MODIFY_VocalTract_setLength, U"", nullptr) {
+	POSITIVEVAR (length, U"New length (m)", U"0.17")
 	OK
 DO
-	double newLength = GET_REAL (U"New length");
-	LOOP {
-		iam (VocalTract);
-		VocalTract_setLength (me, newLength);
-	}
-END
-
-FORM (VocalTract_to_VocalTractTier, U"VocalTract: To VocalTractTier", nullptr)
-	REAL (U"Tier start time (s)", U"0.0")
-	REAL (U"Tier end time (s)", U"1.0")
-	REAL (U"Insert at time (s)", U"0.5")
+	MODIFY_EACH (VocalTract)
+		VocalTract_setLength (me, length);
+	MODIFY_EACH_END
+}
+
+FORM (NEW_VocalTract_to_VocalTractTier, U"VocalTract: To VocalTractTier", nullptr) {
+	REALVAR (fromTime, U"Tier start time (s)", U"0.0")
+	REALVAR (toTime, U"Tier end time (s)", U"1.0")
+	REALVAR (time, U"Insert at time (s)", U"0.5")
 	OK
 DO
-	double xmin = GET_REAL (U"Tier start time");
-	double xmax = GET_REAL (U"Tier end time");
-	double time = GET_REAL (U"Insert at time");
-	REQUIRE (xmin < xmax, U"The start time must be before the end time.")
-	REQUIRE (time >= xmin and time <= xmax, U"The insert time must be between start en end time.")
-	LOOP {
-		iam (VocalTract);
-		autoVocalTractTier thee = VocalTract_to_VocalTractTier (me, xmin, xmax, time);
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (VocalTractTier_help)
-	Melder_help (U"VocalTractTier");
-END
-
-FORM (VocalTractTier_to_LPC, U"VocalTractTier: To LPC", nullptr)
-	POSITIVE (U"Time step", U"0.005")
+	REQUIRE (fromTime < toTime, U"The start time must be before the end time.")
+	REQUIRE (time >= fromTime && time <= toTime, U"The insert time must be between start and end time.")
+	CONVERT_EACH (VocalTract)
+		autoVocalTractTier result = VocalTract_to_VocalTractTier (me, fromTime, toTime, time);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (HELP_VocalTractTier_help) {
+	HELP (U"VocalTractTier")
+}
+
+FORM (NEW_VocalTractTier_to_LPC, U"VocalTractTier: To LPC", nullptr) {
+	POSITIVEVAR (timeStep, U"Time step", U"0.005")
 	OK
 DO
-	LOOP {
-		iam (VocalTractTier);
-		autoLPC thee = VocalTractTier_to_LPC (me, GET_REAL (U"Time step"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (VocalTractTier_to_VocalTract, U"", nullptr)
-	REAL (U"Time (s)", U"0.1")
+	CONVERT_EACH (VocalTractTier)
+		autoLPC result = VocalTractTier_to_LPC (me, timeStep);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_VocalTractTier_to_VocalTract, U"", nullptr) {
+	REALVAR (time, U"Time (s)", U"0.1")
 	OK
 DO
-	double time = GET_REAL (U"Time");
-	LOOP {
-		iam (VocalTractTier);
-		autoVocalTract thee = VocalTractTier_to_VocalTract (me, time);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (VocalTractTier_addVocalTract, U"VocalTractTier: Add VocalTract", nullptr)
-	REAL (U"Time", U"0.1")
+	CONVERT_EACH (VocalTractTier)
+		autoVocalTract result = VocalTractTier_to_VocalTract (me, time);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (MODIFY_VocalTractTier_addVocalTract, U"VocalTractTier: Add VocalTract", nullptr) {
+	REALVAR (time, U"Time (s)", U"0.1")
 	OK
 DO
-	VocalTractTier me = FIRST (VocalTractTier);
-	VocalTract thee = FIRST (VocalTract);
-	VocalTractTier_addVocalTract_copy (me, GET_REAL (U"Time"), thee);
-	praat_dataChanged (me);
-END
+	MODIFY_FIRST_OF_TWO (VocalTractTier, VocalTract)
+		VocalTractTier_addVocalTract_copy (me, time, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
 /******************* LPC & Sound *************************************/
 
-FORM (LPC_and_Sound_filter, U"LPC & Sound: Filter", U"LPC & Sound: Filter...")
-	BOOLEAN (U"Use LPC gain", false)
+FORM (NEW1_LPC_and_Sound_filter, U"LPC & Sound: Filter", U"LPC & Sound: Filter...") {
+	BOOLEANVAR (useGain, U"Use LPC gain", false)
 	OK
 DO
-	LPC me = FIRST (LPC);
-	Sound s = FIRST (Sound);
-	autoSound thee = LPC_and_Sound_filter (me , s, GET_INTEGER (U"Use LPC gain"));
-	praat_new (thee.move(), my name);
-END
-
-FORM (LPC_and_Sound_filterWithFilterAtTime, U"LPC & Sound: Filter with one filter at time",
-      U"LPC & Sound: Filter with filter at time...")
-	OPTIONMENU (U"Channel", 2)
-	OPTION (U"Both")
-	OPTION (U"Left")
-	OPTION (U"Right")
-	REAL (U"Use filter at time (s)", U"0.0")
+	CONVERT_TWO (LPC, Sound)
+		autoSound result = LPC_and_Sound_filter (me , you, useGain);
+	CONVERT_TWO_END (my name)
+}
+
+FORM (NEW1_LPC_and_Sound_filterWithFilterAtTime, U"LPC & Sound: Filter with one filter at time", U"LPC & Sound: Filter with filter at time...") {
+	OPTIONMENUVAR (channel, U"Channel", 2)
+		OPTION (U"Both")
+		OPTION (U"Left")
+		OPTION (U"Right")
+	REALVAR (time, U"Use filter at time (s)", U"0.0")
 	OK
 DO
-	LPC me = FIRST (LPC);
-	Sound s = FIRST (Sound);
-	long channel = GET_INTEGER (U"Channel") - 1;
-	autoSound thee = LPC_and_Sound_filterWithFilterAtTime (me , s, channel, GET_REAL (U"Use filter at time"));
-	praat_new (thee.move(), my name);
-END
-
-DIRECT (LPC_and_Sound_filterInverse)
-	LPC me = FIRST (LPC);
-	Sound s = FIRST (Sound);
-	autoSound thee = LPC_and_Sound_filterInverse (me , s);
-	praat_new (thee.move(), my name);
-END
-
-FORM (LPC_and_Sound_filterInverseWithFilterAtTime, U"LPC & Sound: Filter (inverse) with filter at time",
-      U"LPC & Sound: Filter (inverse) with filter at time...")
-	OPTIONMENU (U"Channel", 2)
-	OPTION (U"Both")
-	OPTION (U"Left")
-	OPTION (U"Right")
-	REAL (U"Use filter at time (s)", U"0.0")
+	CONVERT_TWO (LPC, Sound)
+		autoSound result = LPC_and_Sound_filterWithFilterAtTime (me , you, channel - 1, time);
+	CONVERT_TWO_END (my name)
+}
+
+DIRECT (NEW1_LPC_and_Sound_filterInverse) {
+	CONVERT_TWO (LPC, Sound)
+		autoSound result = LPC_and_Sound_filterInverse (me , you);
+	CONVERT_TWO_END (my name)
+}
+
+FORM (NEW1_LPC_and_Sound_filterInverseWithFilterAtTime, U"LPC & Sound: Filter (inverse) with filter at time",
+      U"LPC & Sound: Filter (inverse) with filter at time...") {
+	OPTIONMENUVAR (channel, U"Channel", 2)
+		OPTION (U"Both")
+		OPTION (U"Left")
+		OPTION (U"Right")
+	REALVAR (time, U"Use filter at time (s)", U"0.0")
 	OK
 DO
-	LPC me = FIRST (LPC);
-	Sound s = FIRST (Sound);
-	long channel = GET_INTEGER (U"Channel") - 1;
-	autoSound thee = LPC_and_Sound_filterInverseWithFilterAtTime (me , s, channel, GET_REAL (U"Use filter at time"));
-	praat_new (thee.move(), my name);
-END
-
-FORM (LPC_and_Sound_to_LPC_robust, U"Robust LPC analysis", U"LPC & Sound: To LPC (robust)...")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Pre-emphasis frequency (Hz)", U"50.0")
-	POSITIVE (U"Number of std. dev.", U"1.5")
-	NATURAL (U"Maximum number of iterations", U"5")
-	REAL (U"Tolerance", U"0.000001")
-	BOOLEAN (U"Variable location", false)
+	CONVERT_TWO (LPC, Sound)
+		autoSound result = LPC_and_Sound_filterInverseWithFilterAtTime (me , you, channel - 1, time);
+	CONVERT_TWO_END (my name)
+}
+
+FORM (NEW1_LPC_and_Sound_to_LPC_robust, U"Robust LPC analysis", U"LPC & Sound: To LPC (robust)...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis frequency (Hz)", U"50.0")
+	POSITIVEVAR (numberOfStandardDeviations, U"Number of std. dev.", U"1.5")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"5")
+	REALVAR (tolerance, U"Tolerance", U"0.000001")
+	BOOLEANVAR (locationVariable, U"Variable location", false)
 	OK
 DO
-	LPC me = FIRST (LPC);
-	Sound s = FIRST (Sound);
-	praat_new (LPC_and_Sound_to_LPC_robust (me, s, GET_REAL (U"Window length"), GET_REAL (U"Pre-emphasis frequency"),
-		GET_REAL (U"Number of std. dev."), GET_INTEGER (U"Maximum number of iterations"),
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Variable location")), my name, U"_r");
-END
+	CONVERT_TWO (LPC, Sound)
+		autoLPC result = LPC_and_Sound_to_LPC_robust (me, you, windowLength, preEmphasisFrequency, numberOfStandardDeviations, maximumNumberOfIterations, tolerance, locationVariable);
+	CONVERT_TWO_END (my name, U"_r");
+}
 
 extern void praat_TimeTier_query_init (ClassInfo klas);
 extern void praat_TimeTier_modify_init (ClassInfo klas);
@@ -1270,129 +1032,129 @@ void praat_uvafon_LPC_init ();
 void praat_uvafon_LPC_init () {
 	Thing_recognizeClassesByName (classCepstrumc, classPowerCepstrum, classCepstrogram, classPowerCepstrogram, classLPC, classLFCC, classLineSpectralFrequencies, classMFCC, classVocalTractTier, nullptr);
 
-	praat_addAction1 (classPowerCepstrum, 0, U"PowerCepstrum help", 0, 0, DO_PowerCepstrum_help);
-	praat_addAction1 (classPowerCepstrum, 0, U"Draw...", 0, 0, DO_PowerCepstrum_draw);
-	praat_addAction1 (classPowerCepstrum, 0, U"Draw tilt line...", 0, 0, DO_PowerCepstrum_drawTiltLine);
-	praat_addAction1 (classCepstrum, 0, U"Draw (linear)...", 0, praat_HIDDEN, DO_Cepstrum_drawLinear);
-	praat_addAction1 (classCepstrum, 0, U"Down to PowerCepstrum", 0, 0, DO_Cepstrum_downto_PowerCepstrum);
+	praat_addAction1 (classPowerCepstrum, 0, U"PowerCepstrum help", 0, 0, HELP_PowerCepstrum_help);
+	praat_addAction1 (classPowerCepstrum, 0, U"Draw...", 0, 0, GRAPHICS_PowerCepstrum_draw);
+	praat_addAction1 (classPowerCepstrum, 0, U"Draw tilt line...", 0, 0, GRAPHICS_PowerCepstrum_drawTiltLine);
+	praat_addAction1 (classCepstrum, 0, U"Draw (linear)...", 0, praat_HIDDEN, GRAPHICS_Cepstrum_drawLinear);
+	praat_addAction1 (classCepstrum, 0, U"Down to PowerCepstrum", 0, 0, NEW_Cepstrum_downto_PowerCepstrum);
 	
 	praat_addAction1 (classPowerCepstrum, 1, U"Query -", 0, 0, 0);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get peak...", 0, 1, DO_PowerCepstrum_getPeak);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get quefrency of peak...", 0, 1, DO_PowerCepstrum_getQuefrencyOfPeak);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get peak prominence (hillenbrand)...", 0, praat_DEPTH_1 + praat_HIDDEN, DO_PowerCepstrum_getPeakProminence_hillenbrand);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get peak prominence...", 0, 1, DO_PowerCepstrum_getPeakProminence);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get tilt line slope...", 0, 1, DO_PowerCepstrum_getTiltLineSlope);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get tilt line intercept...", 0, 1, DO_PowerCepstrum_getTiltLineIntercept);
-		praat_addAction1 (classPowerCepstrum, 0, U"Get rhamonics to noise ratio...", 0, 1, DO_PowerCepstrum_getRNR);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get peak...", 0, 1, REAL_PowerCepstrum_getPeak);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get quefrency of peak...", 0, 1, REAL_PowerCepstrum_getQuefrencyOfPeak);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get peak prominence (hillenbrand)...", 0, praat_DEPTH_1 + praat_HIDDEN, REAL_PowerCepstrum_getPeakProminence_hillenbrand);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get peak prominence...", 0, 1, REAL_PowerCepstrum_getPeakProminence);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get tilt line slope...", 0, 1, REAL_PowerCepstrum_getTiltLineSlope);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get tilt line intercept...", 0, 1, REAL_PowerCepstrum_getTiltLineIntercept);
+		praat_addAction1 (classPowerCepstrum, 0, U"Get rhamonics to noise ratio...", 0, 1, REAL_PowerCepstrum_getRNR);
 	praat_addAction1 (classPowerCepstrum, 1, U"Modify -", 0, 0, 0);
-		praat_addAction1 (classPowerCepstrum, 0, U"Formula...", 0, 1, DO_PowerCepstrum_formula);
-		praat_addAction1 (classPowerCepstrum, 0, U"Subtract tilt (in-line)...", 0, 1, DO_PowerCepstrum_subtractTilt_inline);
-		praat_addAction1 (classPowerCepstrum, 0, U"Smooth (in-line)...", 0, 1, DO_PowerCepstrum_smooth_inline);
+		praat_addAction1 (classPowerCepstrum, 0, U"Formula...", 0, 1, MODIFY_PowerCepstrum_formula);
+		praat_addAction1 (classPowerCepstrum, 0, U"Subtract tilt (in-line)...", 0, 1, MODIFY_PowerCepstrum_subtractTilt_inline);
+		praat_addAction1 (classPowerCepstrum, 0, U"Smooth (in-line)...", 0, 1, MODIFY_PowerCepstrum_smooth_inline);
 
-	praat_addAction1 (classPowerCepstrum, 0, U"Subtract tilt...", 0, 0, DO_PowerCepstrum_subtractTilt);
-	praat_addAction1 (classPowerCepstrum, 0, U"Smooth...", 0, 0, DO_PowerCepstrum_smooth);
-	praat_addAction1 (classCepstrum, 0, U"To Spectrum", 0, praat_HIDDEN, DO_Cepstrum_to_Spectrum);
-	praat_addAction1 (classPowerCepstrum, 0, U"To Matrix", 0, 0, DO_PowerCepstrum_to_Matrix);
+	praat_addAction1 (classPowerCepstrum, 0, U"Subtract tilt...", 0, 0, NEW_PowerCepstrum_subtractTilt);
+	praat_addAction1 (classPowerCepstrum, 0, U"Smooth...", 0, 0, NEW_PowerCepstrum_smooth);
+	praat_addAction1 (classCepstrum, 0, U"To Spectrum", 0, praat_HIDDEN, NEW_Cepstrum_to_Spectrum);
+	praat_addAction1 (classPowerCepstrum, 0, U"To Matrix", 0, 0, NEW_PowerCepstrum_to_Matrix);
 
-	praat_addAction1 (classPowerCepstrogram, 0, U"PowerCepstrogram help", 0, 0, DO_PowerCepstrogram_help);
-	praat_addAction1 (classPowerCepstrogram, 0, U"Paint...", 0, 0, DO_PowerCepstrogram_paint);
+	praat_addAction1 (classPowerCepstrogram, 0, U"PowerCepstrogram help", 0, 0, HELP_PowerCepstrogram_help);
+	praat_addAction1 (classPowerCepstrogram, 0, U"Paint...", 0, 0, GRAPHICS_PowerCepstrogram_paint);
 	praat_addAction1 (classPowerCepstrogram, 1, U"Query -", 0, 0, 0);
 		praat_TimeFrameSampled_query_init (classPowerCepstrogram);
 		praat_addAction1 (classPowerCepstrogram, 1, U"Query quefrency domain", 0, 1, 0);
-			praat_addAction1 (classPowerCepstrogram, 1, U"Get start quefrency", 0, 2, DO_PowerCepstrogram_getStartQuefrency);
-			praat_addAction1 (classPowerCepstrogram, 1, U"Get end quefrency", 0, 2, DO_PowerCepstrogram_getEndQuefrency);
+			praat_addAction1 (classPowerCepstrogram, 1, U"Get start quefrency", 0, 2, REAL_PowerCepstrogram_getStartQuefrency);
+			praat_addAction1 (classPowerCepstrogram, 1, U"Get end quefrency", 0, 2, REAL_PowerCepstrogram_getEndQuefrency);
 		praat_addAction1 (classPowerCepstrogram, 1, U"Query quefrency sampling", 0, 1, 0);
-			praat_addAction1 (classPowerCepstrogram, 1, U"Get number of quefrency bins", 0, 2, DO_PowerCepstrogram_getNumberOfQuefrencyBins);
-			praat_addAction1 (classPowerCepstrogram, 1, U"Get quefrency step", 0, 2, DO_PowerCepstrogram_getQuefrencyStep);
-		praat_addAction1 (classPowerCepstrogram, 0, U"Get CPPS (hillenbrand)...", 0, praat_DEPTH_1 + praat_HIDDEN, DO_PowerCepstrogram_getCPPS_hillenbrand);
-		praat_addAction1 (classPowerCepstrogram, 0, U"Get CPPS...", 0, 1, DO_PowerCepstrogram_getCPPS);
-	praat_addAction1 (classPowerCepstrogram, 0, U"Modify -", 0, 0, 0);
+			praat_addAction1 (classPowerCepstrogram, 1, U"Get number of quefrency bins", 0, 2, INTEGER_PowerCepstrogram_getNumberOfQuefrencyBins);
+			praat_addAction1 (classPowerCepstrogram, 1, U"Get quefrency step", 0, 2, REAL_PowerCepstrogram_getQuefrencyStep);
+		praat_addAction1 (classPowerCepstrogram, 0, U"Get CPPS (hillenbrand)...", 0, praat_DEPTH_1 + praat_HIDDEN, REAL_PowerCepstrogram_getCPPS_hillenbrand);
+		praat_addAction1 (classPowerCepstrogram, 0, U"Get CPPS...", 0, 1, REAL_PowerCepstrogram_getCPPS);
+	praat_addAction1 (classPowerCepstrogram, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classPowerCepstrogram);
-		praat_addAction1 (classPowerCepstrogram, 0, U"Formula...", 0, 1, DO_PowerCepstrogram_formula);
-		praat_addAction1 (classPowerCepstrogram, 0, U"Subtract tilt (in-line)...", 0, 1, DO_PowerCepstrogram_subtractTilt_inline);
-	praat_addAction1 (classPowerCepstrogram, 0, U"To PowerCepstrum (slice)...", 0, 0, DO_PowerCepstrogram_to_PowerCepstrum_slice);
-	praat_addAction1 (classPowerCepstrogram, 0, U"Smooth...", 0, 0, DO_PowerCepstrogram_smooth);
-	praat_addAction1 (classPowerCepstrogram, 0, U"Subtract tilt...", 0, 0, DO_PowerCepstrogram_subtractTilt);
-	praat_addAction1 (classPowerCepstrogram, 0, U"To Table (hillenbrand)...", 0, praat_HIDDEN, DO_PowerCepstrogram_to_Table_hillenbrand);
-	praat_addAction1 (classPowerCepstrogram, 0, U"To Table (peak prominence)...", 0, praat_HIDDEN, DO_PowerCepstrogram_to_Table_cpp);
-	praat_addAction1 (classPowerCepstrogram, 0, U"To Matrix", 0, 0, DO_PowerCepstrogram_to_Matrix);
+		praat_addAction1 (classPowerCepstrogram, 0, U"Formula...", 0, 1, MODIFY_PowerCepstrogram_formula);
+		praat_addAction1 (classPowerCepstrogram, 0, U"Subtract tilt (in-line)...", 0, 1, MODIFY_PowerCepstrogram_subtractTilt_inline);
+	praat_addAction1 (classPowerCepstrogram, 0, U"To PowerCepstrum (slice)...", 0, 0, NEW_PowerCepstrogram_to_PowerCepstrum_slice);
+	praat_addAction1 (classPowerCepstrogram, 0, U"Smooth...", 0, 0, NEW_PowerCepstrogram_smooth);
+	praat_addAction1 (classPowerCepstrogram, 0, U"Subtract tilt...", 0, 0, NEW_PowerCepstrogram_subtractTilt);
+	praat_addAction1 (classPowerCepstrogram, 0, U"To Table (hillenbrand)...", 0, praat_HIDDEN, NEW_PowerCepstrogram_to_Table_hillenbrand);
+	praat_addAction1 (classPowerCepstrogram, 0, U"To Table (peak prominence)...", 0, praat_HIDDEN, NEW_PowerCepstrogram_to_Table_cpp);
+	praat_addAction1 (classPowerCepstrogram, 0, U"To Matrix", 0, 0, NEW_PowerCepstrogram_to_Matrix);
 
 	praat_addAction1 (classCepstrumc, 0, U"Analyse", 0, 0, 0);
-	praat_addAction1 (classCepstrumc, 0, U"To LPC", 0, 0, DO_Cepstrumc_to_LPC);
-	praat_addAction1 (classCepstrumc, 2, U"To DTW...", 0, 0, DO_Cepstrumc_to_DTW);
+	praat_addAction1 (classCepstrumc, 0, U"To LPC", 0, 0, NEW_Cepstrumc_to_LPC);
+	praat_addAction1 (classCepstrumc, 2, U"To DTW...", 0, 0, NEW1_Cepstrumc_to_DTW);
 	praat_addAction1 (classCepstrumc, 0, U"Hack", 0, 0, 0);
-	praat_addAction1 (classCepstrumc, 0, U"To Matrix", 0, 0, DO_Cepstrumc_to_Matrix);
+	praat_addAction1 (classCepstrumc, 0, U"To Matrix", 0, 0, NEW_Cepstrumc_to_Matrix);
 
 	praat_addAction1 (classFormant, 0, U"Analyse", 0, 0, 0);
-	praat_addAction1 (classFormant, 0, U"To LPC...", 0, 0, DO_Formant_to_LPC);
-	praat_addAction1 (classFormant, 0, U"Formula...", U"Formula (bandwidths)...", 1, DO_Formant_formula);
-	praat_addAction2 (classFormant, 1, classSpectrogram, 1, U"To IntensityTier...", 0, 0, DO_Formant_and_Spectrogram_to_IntensityTier);
+	praat_addAction1 (classFormant, 0, U"To LPC...", 0, 0, NEW_Formant_to_LPC);
+	praat_addAction1 (classFormant, 0, U"Formula...", U"Formula (bandwidths)...", 1, MODIFY_Formant_formula);
+	praat_addAction2 (classFormant, 1, classSpectrogram, 1, U"To IntensityTier...", 0, 0, NEW1_Formant_and_Spectrogram_to_IntensityTier);
 
 	
 	
-	praat_addAction1 (classLFCC, 0, U"LFCC help", 0, 0, DO_LFCC_help);
+	praat_addAction1 (classLFCC, 0, U"LFCC help", 0, 0, HELP_LFCC_help);
 	praat_CC_init (classLFCC);
-	praat_addAction1 (classLFCC, 0, U"To LPC...", 0, 0, DO_LFCC_to_LPC);
+	praat_addAction1 (classLFCC, 0, U"To LPC...", 0, 0, NEW_LFCC_to_LPC);
 
-	praat_addAction1 (classLineSpectralFrequencies, 0, U"LineSpectralFrequencies help", 0, 0, DO_LineSpectralFrequencies_help);
-	praat_addAction1 (classLineSpectralFrequencies, 0, U"Draw frequencies...", 0, 0, DO_LineSpectralFrequencies_drawFrequencies);
-	praat_addAction1 (classLineSpectralFrequencies, 0, U"To LPC", 0, 0, DO_LineSpectralFrequencies_to_LPC);
+	praat_addAction1 (classLineSpectralFrequencies, 0, U"LineSpectralFrequencies help", 0, 0, HELP_LineSpectralFrequencies_help);
+	praat_addAction1 (classLineSpectralFrequencies, 0, U"Draw frequencies...", 0, 0, GRAPHICS_LineSpectralFrequencies_drawFrequencies);
+	praat_addAction1 (classLineSpectralFrequencies, 0, U"To LPC", 0, 0, NEW_LineSpectralFrequencies_to_LPC);
 	
-	praat_addAction1 (classLPC, 0, U"LPC help", 0, 0, DO_LPC_help);
+	praat_addAction1 (classLPC, 0, U"LPC help", 0, 0, HELP_LPC_help);
 	praat_addAction1 (classLPC, 0, DRAW_BUTTON, 0, 0, 0);
-	praat_addAction1 (classLPC, 0, U"Draw gain...", 0, 1, DO_LPC_drawGain);
-	praat_addAction1 (classLPC, 0, U"Draw poles...", 0, 1, DO_LPC_drawPoles);
+	praat_addAction1 (classLPC, 0, U"Draw gain...", 0, 1, GRAPHICS_LPC_drawGain);
+	praat_addAction1 (classLPC, 0, U"Draw poles...", 0, 1, GRAPHICS_LPC_drawPoles);
 	praat_addAction1 (classLPC, 0, QUERY_BUTTON, 0, 0, 0);
 		praat_TimeFrameSampled_query_init (classLPC);
-		praat_addAction1 (classLPC, 1, U"Get sampling interval", 0, 1, DO_LPC_getSamplingInterval);
-		praat_addAction1 (classLPC, 1, U"Get number of coefficients...", 0, 1, DO_LPC_getNumberOfCoefficients);
+		praat_addAction1 (classLPC, 1, U"Get sampling interval", 0, 1, REAL_LPC_getSamplingInterval);
+		praat_addAction1 (classLPC, 1, U"Get number of coefficients...", 0, 1, INTEGER_LPC_getNumberOfCoefficients);
 	praat_addAction1 (classLPC, 0, MODIFY_BUTTON, 0, 0, 0);
 		praat_TimeFunction_modify_init (classLPC);
 	praat_addAction1 (classLPC, 0, U"Extract", 0, 0, 0);
 
-	praat_addAction1 (classLPC, 0, U"To Spectrum (slice)...", 0, 0, DO_LPC_to_Spectrum);
-	praat_addAction1 (classLPC, 0, U"To VocalTract (slice)...", 0, 0, DO_LPC_to_VocalTract);
-	praat_addAction1 (classLPC, 0, U"To VocalTract (slice, special)...", 0, 0, DO_LPC_to_VocalTract_special);
-	praat_addAction1 (classLPC, 0, U"To Polynomial (slice)...", 0, 0, DO_LPC_to_Polynomial);
-	praat_addAction1 (classLPC, 0, U"Down to Matrix (lpc)", 0, 0, DO_LPC_downto_Matrix_lpc);
-	praat_addAction1 (classLPC, 0, U"Down to Matrix (rc)", 0, praat_HIDDEN, DO_LPC_downto_Matrix_rc);
-	praat_addAction1 (classLPC, 0, U"Down to Matrix (area)", 0, praat_HIDDEN, DO_LPC_downto_Matrix_area);
+	praat_addAction1 (classLPC, 0, U"To Spectrum (slice)...", 0, 0, NEW_LPC_to_Spectrum);
+	praat_addAction1 (classLPC, 0, U"To VocalTract (slice)...", 0, 0, NEW_LPC_to_VocalTract);
+	praat_addAction1 (classLPC, 0, U"To VocalTract (slice, special)...", 0, 0, NEW_LPC_to_VocalTract_special);
+	praat_addAction1 (classLPC, 0, U"To Polynomial (slice)...", 0, 0, NEW_LPC_to_Polynomial);
+	praat_addAction1 (classLPC, 0, U"Down to Matrix (lpc)", 0, 0, NEW_LPC_downto_Matrix_lpc);
+	praat_addAction1 (classLPC, 0, U"Down to Matrix (rc)", 0, praat_HIDDEN, NEW_LPC_downto_Matrix_rc);
+	praat_addAction1 (classLPC, 0, U"Down to Matrix (area)", 0, praat_HIDDEN, NEW_LPC_downto_Matrix_area);
 	praat_addAction1 (classLPC, 0, U"Analyse", 0, 0, 0);
-	praat_addAction1 (classLPC, 0, U"To Formant", 0, 0, DO_LPC_to_Formant);
-	praat_addAction1 (classLPC, 0, U"To Formant (keep all)", 0, 0, DO_LPC_to_Formant_keep_all);
-	praat_addAction1 (classLPC, 0, U"To LFCC...", 0, 0, DO_LPC_to_LFCC);
-	praat_addAction1 (classLPC, 0, U"To Spectrogram...", 0, 0, DO_LPC_to_Spectrogram);
-	praat_addAction1 (classLPC, 0, U"To LineSpectralFrequencies...", 0, 0, DO_LPC_to_LineSpectralFrequencies);
+	praat_addAction1 (classLPC, 0, U"To Formant", 0, 0, NEW_LPC_to_Formant);
+	praat_addAction1 (classLPC, 0, U"To Formant (keep all)", 0, 0, NEW_LPC_to_Formant_keep_all);
+	praat_addAction1 (classLPC, 0, U"To LFCC...", 0, 0, NEW_LPC_to_LFCC);
+	praat_addAction1 (classLPC, 0, U"To Spectrogram...", 0, 0, NEW_LPC_to_Spectrogram);
+	praat_addAction1 (classLPC, 0, U"To LineSpectralFrequencies...", 0, 0, NEW_LPC_to_LineSpectralFrequencies);
 
 	praat_addAction2 (classLPC, 1, classSound, 1, U"Analyse", 0, 0, 0);
-	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter...", 0, 0, DO_LPC_and_Sound_filter);
-	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter (inverse)", 0, 0, DO_LPC_and_Sound_filterInverse);
-	praat_addAction2 (classLPC, 1, classSound, 1, U"To LPC (robust)...", 0, praat_HIDDEN + praat_DEPTH_1, DO_LPC_and_Sound_to_LPC_robust);
-	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter with filter at time...", 0, 0, DO_LPC_and_Sound_filterWithFilterAtTime);
-	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter (inverse) with filter at time...", 0, 0, DO_LPC_and_Sound_filterInverseWithFilterAtTime);
-
-
-	praat_addAction1 (classSound, 0, U"To LPC (autocorrelation)...", U"To Formant (sl)...", 1, DO_Sound_to_LPC_auto);
-	praat_addAction1 (classSound, 0, U"To LPC (covariance)...", U"To LPC (autocorrelation)...", 1, DO_Sound_to_LPC_covar);
-	praat_addAction1 (classSound, 0, U"To LPC (burg)...", U"To LPC (covariance)...", 1, DO_Sound_to_LPC_burg);
-	praat_addAction1 (classSound, 0, U"To LPC (marple)...", U"To LPC (burg)...", 1, DO_Sound_to_LPC_marple);
-	praat_addAction1 (classSound, 0, U"To MFCC...", U"To LPC (marple)...", 1, DO_Sound_to_MFCC);
-	praat_addAction1 (classSound, 0, U"To Formant (robust)...", U"To Formant (sl)...", 2, DO_Sound_to_Formant_robust);
-	praat_addAction1 (classSound, 0, U"To PowerCepstrogram...", U"To Harmonicity (gne)...", 1, DO_Sound_to_PowerCepstrogram);
-	praat_addAction1 (classSound, 0, U"To PowerCepstrogram (hillenbrand)...", U"To Harmonicity (gne)...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_PowerCepstrogram_hillenbrand);
+	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter...", 0, 0, NEW1_LPC_and_Sound_filter);
+	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter (inverse)", 0, 0, NEW1_LPC_and_Sound_filterInverse);
+	praat_addAction2 (classLPC, 1, classSound, 1, U"To LPC (robust)...", 0, praat_HIDDEN + praat_DEPTH_1, NEW1_LPC_and_Sound_to_LPC_robust);
+	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter with filter at time...", 0, 0, NEW1_LPC_and_Sound_filterWithFilterAtTime);
+	praat_addAction2 (classLPC, 1, classSound, 1, U"Filter (inverse) with filter at time...", 0, 0, NEW1_LPC_and_Sound_filterInverseWithFilterAtTime);
+
+
+	praat_addAction1 (classSound, 0, U"To LPC (autocorrelation)...", U"To Formant (sl)...", 1, NEW_Sound_to_LPC_auto);
+	praat_addAction1 (classSound, 0, U"To LPC (covariance)...", U"To LPC (autocorrelation)...", 1, NEW_Sound_to_LPC_covar);
+	praat_addAction1 (classSound, 0, U"To LPC (burg)...", U"To LPC (covariance)...", 1, NEW_Sound_to_LPC_burg);
+	praat_addAction1 (classSound, 0, U"To LPC (marple)...", U"To LPC (burg)...", 1, NEW_Sound_to_LPC_marple);
+	praat_addAction1 (classSound, 0, U"To MFCC...", U"To LPC (marple)...", 1, NEW_Sound_to_MFCC);
+	praat_addAction1 (classSound, 0, U"To Formant (robust)...", U"To Formant (sl)...", 2, NEW_Sound_to_Formant_robust);
+	praat_addAction1 (classSound, 0, U"To PowerCepstrogram...", U"To Harmonicity (gne)...", 1, NEW_Sound_to_PowerCepstrogram);
+	praat_addAction1 (classSound, 0, U"To PowerCepstrogram (hillenbrand)...", U"To Harmonicity (gne)...", praat_HIDDEN + praat_DEPTH_1, NEW_Sound_to_PowerCepstrogram_hillenbrand);
 	
-	praat_addAction1 (classVocalTract, 0, U"Draw segments...", U"Draw", 0, DO_VocalTract_drawSegments);
-	praat_addAction1 (classVocalTract, 1, U"Get length", U"Draw segments...", 0, DO_VocalTract_getLength);
-	praat_addAction1 (classVocalTract, 1, U"Set length", U"Formula...", 0, DO_VocalTract_getLength);
-	praat_addAction1 (classVocalTract, 0, U"To VocalTractTier...", U"To Spectrum...", 0, DO_VocalTract_to_VocalTractTier);
-	praat_addAction1 (classVocalTractTier, 0, U"VocalTractTier help", 0, 0, DO_VocalTractTier_help);
+	praat_addAction1 (classVocalTract, 0, U"Draw segments...", U"Draw", 0, GRAPHICS_VocalTract_drawSegments);
+	praat_addAction1 (classVocalTract, 1, U"Get length", U"Draw segments...", 0, REAL_VocalTract_getLength);
+	praat_addAction1 (classVocalTract, 1, U"Set length", U"Formula...", 0, MODIFY_VocalTract_setLength);
+	praat_addAction1 (classVocalTract, 0, U"To VocalTractTier...", U"To Spectrum...", 0, NEW_VocalTract_to_VocalTractTier);
+	praat_addAction1 (classVocalTractTier, 0, U"VocalTractTier help", 0, 0, HELP_VocalTractTier_help);
 	praat_addAction1 (classVocalTractTier, 0, U"Query -", 0, 0, 0);
 		praat_TimeTier_query_init (classVocalTractTier);
 	praat_addAction1 (classVocalTractTier, 0, U"Modify -", 0, 0, 0);
 		praat_TimeTier_modify_init (classVocalTractTier);
-	praat_addAction1 (classVocalTractTier, 0, U"To LPC...", 0, 0, DO_VocalTractTier_to_LPC);
-	praat_addAction1 (classVocalTractTier, 0, U"To VocalTract...", 0, 0, DO_VocalTractTier_to_VocalTract);
-	praat_addAction2 (classVocalTractTier, 1, classVocalTract, 1, U"Add VocalTract...", 0, 0, DO_VocalTractTier_addVocalTract);
+	praat_addAction1 (classVocalTractTier, 0, U"To LPC...", 0, 0, NEW_VocalTractTier_to_LPC);
+	praat_addAction1 (classVocalTractTier, 0, U"To VocalTract...", 0, 0, NEW_VocalTractTier_to_VocalTract);
+	praat_addAction2 (classVocalTractTier, 1, classVocalTract, 1, U"Add VocalTract...", 0, 0, MODIFY_VocalTractTier_addVocalTract);
 
 	INCLUDE_MANPAGES (manual_LPC)
 	INCLUDE_MANPAGES (manual_DataModeler)
diff --git a/artsynth/Artword.cpp b/artsynth/Artword.cpp
index 06920d4..6ccd08a 100644
--- a/artsynth/Artword.cpp
+++ b/artsynth/Artword.cpp
@@ -1,6 +1,6 @@
 /* Artword.cpp
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -127,7 +127,7 @@ void Artword_intoArt (Artword me, Art art, double time) {
 	}
 }
 
-void Artword_draw (Artword me, Graphics g, int feature, int garnish) {
+void Artword_draw (Artword me, Graphics g, int feature, bool garnish) {
 	long numberOfTargets = my data [feature]. numberOfTargets;
 	if (numberOfTargets > 0) {
 		autoNUMvector <double> x (1, numberOfTargets);
diff --git a/artsynth/Artword.h b/artsynth/Artword.h
index b3a49d8..6d37d8b 100644
--- a/artsynth/Artword.h
+++ b/artsynth/Artword.h
@@ -2,7 +2,7 @@
 #define _Artword_h_
 /* Artword.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@ void Artword_intoArt (Artword me, Art art, double tim);
 		art != nullptr;
 */
 	
-void Artword_draw (Artword me, Graphics graphics, int feature, int garnish);
+void Artword_draw (Artword me, Graphics graphics, int feature, bool garnish);
 
 /* End of file Artword.h */
 #endif
diff --git a/artsynth/Speaker.cpp b/artsynth/Speaker.cpp
index 831e8f6..d6d960a 100644
--- a/artsynth/Speaker.cpp
+++ b/artsynth/Speaker.cpp
@@ -1,6 +1,6 @@
 /* Speaker.cpp
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@
 
 Thing_implement (Speaker, Daata, 0);
 
-autoSpeaker Speaker_create (char32 *kindOfSpeaker, int numberOfVocalCordMasses) {
+autoSpeaker Speaker_create (const char32 *kindOfSpeaker, int numberOfVocalCordMasses) {
 	autoSpeaker me = Thing_new (Speaker);
 
 	/* Supralaryngeal dimensions are taken from P. Mermelstein (1973):		*/
diff --git a/artsynth/Speaker.h b/artsynth/Speaker.h
index e3c6992..c86484a 100644
--- a/artsynth/Speaker.h
+++ b/artsynth/Speaker.h
@@ -2,7 +2,7 @@
 #define _Speaker_h_
 /* Speaker.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
 
 #include "Speaker_def.h"
 
-autoSpeaker Speaker_create (char32 *kindOfSpeaker, int numberOfVocalCordMasses);
+autoSpeaker Speaker_create (const char32 *kindOfSpeaker, int numberOfVocalCordMasses);
 	/* Preconditions:								*/
 	/*    1 <= numberOfVocalCordMasses <= 2;					*/
 	/* Failures:									*/
diff --git a/artsynth/praat_Artsynth.cpp b/artsynth/praat_Artsynth.cpp
index 86528ce..799c561 100644
--- a/artsynth/praat_Artsynth.cpp
+++ b/artsynth/praat_Artsynth.cpp
@@ -24,66 +24,61 @@
 #include "Artword_to_Art.h"
 #include "ArtwordEditor.h"
 #include "VocalTract_to_Spectrum.h"
-#include "praat.h"
 
-extern "C" Graphics Movie_create (const char32 *title, int width, int height);
+#include "praat_Matrix.h"
 
-#undef iam
-#define iam iam_LOOP
+// MARK: - ART
 
-/***** ART *****/
-
-FORM (Art_create, U"Create a default Articulation", U"Articulatory synthesis") {
-	WORD (U"Name", U"articulation")
-	OK2
+FORM (NEW1_Art_create, U"Create a default Articulation", U"Articulatory synthesis") {
+	WORDVAR (name, U"Name", U"articulation")
+	OK
 DO
-	autoArt me = Art_create ();
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
+	CREATE_ONE
+		autoArt result = Art_create ();
+	CREATE_ONE_END (name);
+}
 
-FORM (Art_edit, U"View & Edit Articulation", nullptr) {
+FORM (WINDOW_Art_viewAndEdit, U"View & Edit Articulation", nullptr) {
 	for (int i = 1; i <= kArt_muscle_MAX; i ++)
 		REAL (kArt_muscle_getText (i), U"0.0")
-	OK2
-{
-	Art object = (Art) ONLY_OBJECT;
+OK
+	FIND_ONE (Art)
 	for (int i = 1; i <= kArt_muscle_MAX; i ++)
-		SET_REAL (kArt_muscle_getText (i), object -> art [i]);
-}
+		SET_REAL (kArt_muscle_getText (i), my art [i]);
 DO
-	Art object = (Art) ONLY_OBJECT;
-	if (theCurrentPraatApplication -> batch)
-		Melder_throw (U"Cannot edit an Art from batch.");
-	for (int i = 1; i <= kArt_muscle_MAX; i ++)
-		object -> art [i] = GET_REAL (kArt_muscle_getText (i));
-END2 }
+	FIND_ONE (Art)
+		if (theCurrentPraatApplication -> batch)
+			Melder_throw (U"Cannot edit an Art from batch.");
+		for (int i = 1; i <= kArt_muscle_MAX; i ++)
+			my art [i] = GET_REAL (kArt_muscle_getText (i));
+	END
+}
 
-/***** ARTWORD *****/
+// MARK: - ARTWORD
 
-FORM (Artword_create, U"Create an empty Artword", U"Create Artword...") {
-	WORD (U"Name", U"hallo")
-	POSITIVE (U"Duration (seconds)", U"1.0")
-	OK2
+FORM (NEW1_Artword_create, U"Create an empty Artword", U"Create Artword...") {
+	WORDVAR (name, U"Name", U"hallo")
+	POSITIVEVAR (duration, U"Duration (seconds)", U"1.0")
+	OK
 DO
-	praat_new (Artword_create (GET_REAL (U"Duration")), GET_STRING (U"Name"));
-END2 }
+	CREATE_ONE
+		autoArtword result = Artword_create (duration);
+	CREATE_ONE_END (name)
+}
 
-FORM (Artword_draw, U"Draw one Artword tier", nullptr) {
-	OPTIONMENU (U"Muscle", kArt_muscle_LUNGS)
+FORM (GRAPHICS_Artword_draw, U"Draw one Artword tier", nullptr) {
+	OPTIONMENUVAR (muscle, U"Muscle", kArt_muscle_LUNGS)
 	for (int ienum = 1; ienum <= kArt_muscle_MAX; ienum ++)
 		OPTION (kArt_muscle_getText (ienum))
-	BOOLEAN (U"Garnish", true)
-	OK2
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
 DO
-	
-	autoPraatPicture picture;
-	LOOP {
-		iam (Artword);
-		Artword_draw (me, GRAPHICS, GET_INTEGER (U"Muscle"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+	GRAPHICS_EACH (Artword)
+		Artword_draw (me, GRAPHICS, muscle, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Artword_edit) {
+DIRECT (WINDOW_Artword_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an Artword from batch.");
 	WHERE (SELECTED) {
 		iam_LOOP (Artword);
@@ -91,182 +86,159 @@ DIRECT2 (Artword_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM (Artword_getTarget, U"Get one Artword target", nullptr) {
-	REAL (U"Time (seconds)", U"0.0")
-	OPTIONMENU (U"Muscle", kArt_muscle_LUNGS)
+FORM (REAL_Artword_getTarget, U"Get one Artword target", nullptr) {
+	REALVAR (time, U"Time (seconds)", U"0.0")
+	OPTIONMENUVAR (muscle, U"Muscle", kArt_muscle_LUNGS)
 	for (int ienum = 1; ienum <= kArt_muscle_MAX; ienum ++)
 		OPTION (kArt_muscle_getText (ienum))
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Artword);
-		double target = Artword_getTarget (me, GET_INTEGER (U"Muscle"), GET_REAL (U"Time"));
-		Melder_information (target);
-	}
-END2 }
+	NUMBER_ONE (Artword)
+		double result = Artword_getTarget (me, muscle, time);
+	NUMBER_ONE_END (U"")
+}
 
-DIRECT2 (Artword_help) {
-	Melder_help (U"Artword");
-END2 }
+DIRECT (HELP_Artword_help) {
+	HELP (U"Artword")
+}
 
-FORM (Artword_setTarget, U"Set one Artword target", nullptr) {
-	REAL (U"Time (seconds)", U"0.0")
-	REAL (U"Target value (0-1)", U"0.0")
-	OPTIONMENU (U"Muscle", kArt_muscle_LUNGS)
+FORM (MODIFY_Artword_setTarget, U"Set one Artword target", nullptr) {
+	REALVAR (time, U"Time (seconds)", U"0.0")
+	REALVAR (targetValue, U"Target value (0-1)", U"0.0")
+	OPTIONMENUVAR (muscle, U"Muscle", kArt_muscle_LUNGS)
 	for (int ienum = 1; ienum <= kArt_muscle_MAX; ienum ++)
 		OPTION (kArt_muscle_getText (ienum))
-	OK2
+	OK
 DO
-	double time = GET_REAL (U"Time");
-	if (time < 0.0) Melder_throw (U"Specified time should not be less than 0.");
-	LOOP {
-		iam (Artword);
-		Artword_setTarget (me, GET_INTEGER (U"Muscle"), time, GET_REAL (U"Target value"));
-		praat_dataChanged (me);
-	}
-END2 }
+	if (time < 0.0) Melder_throw (U"The specified time should not be less than 0.");
+	MODIFY_EACH (Artword)
+		Artword_setTarget (me, muscle, time, targetValue);
+	MODIFY_EACH_END
+}
 
-FORM (Artword_to_Art, U"From Artword to Art", nullptr) {
-	REAL (U"Time (seconds)", U"0.0")
-	OK2
+FORM (NEW_Artword_to_Art, U"From Artword to Art", nullptr) {
+	REALVAR (time, U"Time (seconds)", U"0.0")
+	OK
 DO
-	LOOP {
-		iam (Artword);
-		autoArt thee = Artword_to_Art (me, GET_REAL (U"Time"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-/***** ART & SPEAKER *****/
-
-DIRECT2 (Art_Speaker_draw) {
-	autoPraatPicture picture;
-	iam_ONLY (Art);
-	thouart_ONLY (Speaker);
-	Art_Speaker_draw (me, thee, GRAPHICS);
-END2 }
-
-DIRECT2 (Art_Speaker_fillInnerContour) {
-	autoPraatPicture picture;
-	iam_ONLY (Art);
-	thouart_ONLY (Speaker);
-	Art_Speaker_fillInnerContour (me, thee, GRAPHICS);
-END2 }
-
-DIRECT2 (Art_Speaker_drawMesh) {
-	autoPraatPicture picture;
-	iam_ONLY (Art);
-	thouart_ONLY (Speaker);
-	Art_Speaker_drawMesh (me, thee, GRAPHICS);
-END2 }
-
-DIRECT2 (Art_Speaker_to_VocalTract) {
-	iam_ONLY (Art);
-	thouart_ONLY (Speaker);
-	autoVocalTract him = Art_Speaker_to_VocalTract (me, thee);
-	praat_new (him.move(), my name, U"_", thy name);
-END2 }
-
-/***** ARTWORD & SPEAKER *****/
-
-FORM (Artword_Speaker_draw, U"Draw Artword & Speaker", nullptr) {
-	NATURAL (U"Number of steps", U"5")
-	OK2
+	CONVERT_EACH (Artword)
+		autoArt result = Artword_to_Art (me, time);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - ART & SPEAKER
+
+DIRECT (GRAPHICS_Art_Speaker_draw) {
+	GRAPHICS_TWO (Art, Speaker)
+		Art_Speaker_draw (me, you, GRAPHICS);
+	GRAPHICS_TWO_END
+}
+
+DIRECT (GRAPHICS_Art_Speaker_fillInnerContour) {
+	GRAPHICS_TWO (Art, Speaker)
+		Art_Speaker_fillInnerContour (me, you, GRAPHICS);
+	GRAPHICS_TWO_END
+}
+
+DIRECT (GRAPHICS_Art_Speaker_drawMesh) {
+	GRAPHICS_TWO (Art, Speaker)
+		Art_Speaker_drawMesh (me, you, GRAPHICS);
+	GRAPHICS_TWO_END
+}
+
+DIRECT (NEW1_Art_Speaker_to_VocalTract) {
+	CONVERT_TWO (Art, Speaker)
+		autoVocalTract result = Art_Speaker_to_VocalTract (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+// MARK: - ARTWORD & SPEAKER
+
+FORM (GRAPHICS_Artword_Speaker_draw, U"Draw Artword & Speaker", nullptr) {
+	NATURALVAR (numberOfSteps, U"Number of steps", U"5")
+	OK
 DO
-	autoPraatPicture picture;
-	iam_ONLY (Artword);
-	thouart_ONLY (Speaker);
-	Artword_Speaker_draw (me, thee, GRAPHICS, GET_INTEGER (U"Number of steps"));
-END2 }
-
-FORM (Artword_Speaker_to_Sound, U"Articulatory synthesizer", U"Artword & Speaker: To Sound...") {
-	POSITIVE (U"Sampling frequency (Hz)", U"22050.0")
-	NATURAL (U"Oversampling factor", U"25")
-	INTEGER (U"Width 1", U"0")
-	INTEGER (U"Width 2", U"0")
-	INTEGER (U"Width 3", U"0")
-	INTEGER (U"Pressure 1", U"0")
-	INTEGER (U"Pressure 2", U"0")
-	INTEGER (U"Pressure 3", U"0")
-	INTEGER (U"Velocity 1", U"0")
-	INTEGER (U"Velocity 2", U"0")
-	INTEGER (U"Velocity 3", U"0")
-	OK2
+	GRAPHICS_TWO (Artword, Speaker)
+		Artword_Speaker_draw (me, you, GRAPHICS, numberOfSteps);
+	GRAPHICS_TWO_END
+}
+
+FORM (NEW1_Artword_Speaker_to_Sound, U"Articulatory synthesizer", U"Artword & Speaker: To Sound...") {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"22050.0")
+	NATURALVAR (oversamplingFactor, U"Oversampling factor", U"25")
+	INTEGERVAR (width1, U"Width 1", U"0")
+	INTEGERVAR (width2, U"Width 2", U"0")
+	INTEGERVAR (width3, U"Width 3", U"0")
+	INTEGERVAR (pressure1, U"Pressure 1", U"0")
+	INTEGERVAR (pressure2, U"Pressure 2", U"0")
+	INTEGERVAR (pressure3, U"Pressure 3", U"0")
+	INTEGERVAR (velocity1, U"Velocity 1", U"0")
+	INTEGERVAR (velocity2, U"Velocity 2", U"0")
+	INTEGERVAR (velocity3, U"Velocity 3", U"0")
+	OK
 DO
-	autoSound w1, w2, w3, p1, p2, p3, v1, v2, v3;
-	int iw1 = GET_INTEGER (U"Width 1");
-	int iw2 = GET_INTEGER (U"Width 2");
-	int iw3 = GET_INTEGER (U"Width 3");
-	int ip1 = GET_INTEGER (U"Pressure 1");
-	int ip2 = GET_INTEGER (U"Pressure 2");
-	int ip3 = GET_INTEGER (U"Pressure 3");
-	int iv1 = GET_INTEGER (U"Velocity 1");
-	int iv2 = GET_INTEGER (U"Velocity 2");
-	int iv3 = GET_INTEGER (U"Velocity 3");
-	iam_ONLY (Artword);
-	thouart_ONLY (Speaker);
-	autoSound him = Artword_Speaker_to_Sound (me, thee,
-			GET_REAL (U"Sampling frequency"), GET_INTEGER (U"Oversampling factor"),
-			& w1, iw1, & w2, iw2, & w3, iw3,
-			& p1, ip1, & p2, ip2, & p3, ip3,
-			& v1, iv1, & v2, iv2, & v3, iv3);
-	praat_new (him.move(), my name, U"_", thy name);
-	if (iw1) praat_new (w1.move(), U"width", iw1);
-	if (iw2) praat_new (w2.move(), U"width", iw2);
-	if (iw3) praat_new (w3.move(), U"width", iw3);
-	if (ip1) praat_new (p1.move(), U"pressure", ip1);
-	if (ip2) praat_new (p2.move(), U"pressure", ip2);
-	if (ip3) praat_new (p3.move(), U"pressure", ip3);
-	if (iv1) praat_new (v1.move(), U"velocity", iv1);
-	if (iv2) praat_new (v2.move(), U"velocity", iv2);
-	if (iv3) praat_new (v3.move(), U"velocity", iv3);
-END2 }
-
-DIRECT2 (Artword_Speaker_movie) {
-	Graphics graphics = Movie_create (U"Artword & Speaker movie", 300, 300);
-	iam_ONLY (Artword);
-	thouart_ONLY (Speaker);
-	Artword_Speaker_movie (me, thee, graphics);
-END2 }
-
-/***** ARTWORD & SPEAKER [ & SOUND ] *****/
-
-DIRECT2 (Artword_Speaker_Sound_movie) {
-	Graphics graphics = Movie_create (U"Artword & Speaker & Sound movie", 300, 300);
-	iam_ONLY (Artword);
-	thouart_ONLY (Speaker);
-	heis_ONLY (Sound);   // can be null
-	Artword_Speaker_Sound_movie (me, thee, him, graphics);
-END2 }
-
-/***** SPEAKER *****/
-
-FORM (Speaker_create, U"Create a Speaker", U"Create Speaker...") {
-	WORD (U"Name", U"speaker")
-	OPTIONMENU (U"Kind of speaker", 1)
+	FIND_TWO (Artword, Speaker)
+		autoSound w1, w2, w3, p1, p2, p3, v1, v2, v3;
+		autoSound result = Artword_Speaker_to_Sound (me, you,
+			samplingFrequency, oversamplingFactor,
+			& w1, width1, & w2, width2, & w3, width3,
+			& p1, pressure1, & p2, pressure2, & p3, pressure3,
+			& v1, velocity1, & v2, velocity2, & v3, velocity3);
+		praat_new (result.move(), my name, U"_", your name);
+		if (width1) praat_new (w1.move(), U"width", width1);
+		if (width2) praat_new (w2.move(), U"width", width2);
+		if (width3) praat_new (w3.move(), U"width", width3);
+		if (pressure1) praat_new (p1.move(), U"pressure", pressure1);
+		if (pressure2) praat_new (p2.move(), U"pressure", pressure2);
+		if (pressure3) praat_new (p3.move(), U"pressure", pressure3);
+		if (velocity1) praat_new (v1.move(), U"velocity", velocity1);
+		if (velocity2) praat_new (v2.move(), U"velocity", velocity2);
+		if (velocity3) praat_new (v3.move(), U"velocity", velocity3);
+	END
+}
+
+DIRECT (MOVIE_Artword_Speaker_movie) {
+	MOVIE_TWO (Artword, Speaker, U"Artword & Speaker movie", 300, 300)
+		Artword_Speaker_movie (me, you, graphics);
+	MOVIE_TWO_END
+}
+
+// MARK: - ARTWORD & SPEAKER & SOUND
+
+DIRECT (MOVIE_Artword_Speaker_Sound_movie) {
+	MOVIE_THREE (Artword, Speaker, Sound, U"Artword & Speaker & Sound movie", 300, 300)
+		Artword_Speaker_Sound_movie (me, you, him, graphics);
+	MOVIE_THREE_END
+}
+
+// MARK: - SPEAKER
+
+FORM (NEW1_Speaker_create, U"Create a Speaker", U"Create Speaker...") {
+	WORDVAR (name, U"Name", U"speaker")
+	OPTIONMENUSTRVAR (kindOfSpeaker, U"Kind of speaker", 1)
 		OPTION (U"Female")
 		OPTION (U"Male")
 		OPTION (U"Child")
-	OPTIONMENU (U"Number of tubes in glottis", 2)
+	OPTIONMENUSTRVAR (numberOfTubesInGlottis, U"Number of tubes in glottis", 2)
 		OPTION (U"1")
 		OPTION (U"2")
 		OPTION (U"10")
-	OK2
+	OK
 DO
-	autoSpeaker me = Speaker_create (GET_STRING (U"Kind of speaker"), Melder_atoi (GET_STRING (U"Number of tubes in glottis")));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
+	CREATE_ONE
+		autoSpeaker result = Speaker_create (kindOfSpeaker, Melder_atoi (numberOfTubesInGlottis));
+	CREATE_ONE_END (name)
+}
 
-DIRECT2 (Speaker_help) {
-	Melder_help (U"Speaker");
-END2 }
+DIRECT (HELP_Speaker_help) {
+	HELP (U"Speaker")
+}
 
-/***** VOCAL TRACT *****/
+// MARK: - VOCALTRACT
 
-FORM (VocalTract_createFromPhone, U"Create Vocal Tract from phone", U"Create Vocal Tract from phone...") {
-	OPTIONMENU (U"Phone", 1)
+FORM (NEW1_VocalTract_createFromPhone, U"Create Vocal Tract from phone", U"Create Vocal Tract from phone...") {
+	OPTIONMENUSTRVAR (phone, U"Phone", 1)
 		OPTION (U"a")
 		OPTION (U"e")
 		OPTION (U"i")
@@ -289,128 +261,117 @@ FORM (VocalTract_createFromPhone, U"Create Vocal Tract from phone", U"Create Voc
 		OPTION (U"pu")
 		OPTION (U"tu")
 		OPTION (U"ku")
-	OK2
+	OK
 DO
-	autoVocalTract me = VocalTract_createFromPhone (GET_STRING (U"Phone"));
-	praat_new (me.move(), GET_STRING (U"Phone"));
-END2 }
+	CREATE_ONE
+		autoVocalTract result = VocalTract_createFromPhone (phone);
+	CREATE_ONE_END (phone)
+}
 
-DIRECT2 (VocalTract_draw) {
-	autoPraatPicture picture;
-	WHERE (SELECTED) {
-		iam_LOOP (VocalTract);
+DIRECT (GRAPHICS_VocalTract_draw) {
+	GRAPHICS_EACH (VocalTract)
 		VocalTract_draw (me, GRAPHICS);
-	}
-END2 }
+	GRAPHICS_EACH_END
+}
 
-FORM (VocalTract_formula, U"VocalTract Formula", U"Matrix: Formula...") {
+FORM (MODIFY_VocalTract_formula, U"VocalTract Formula", U"Matrix: Formula...") {
 	LABEL (U"label", U"`x' is the distance form the glottis in metres, `col' is the section number, `self' is in m\u00B2")
 	LABEL (U"label", U"x := x1;   for col := 1 to ncol do { self [col] := `formula' ; x := x + dx }")
-	TEXTFIELD (U"formula", U"0")
-	OK2
+	TEXTVAR (formula, U"formula", U"0")
+	OK
 DO
-	LOOP {
-		iam (VocalTract);
-		try {
-			Matrix_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-END2 }
+	MODIFY_EACH_WEAK (VocalTract)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (VocalTract_help) {
-	Melder_help (U"VocalTract");
-END2 }
+DIRECT (HELP_VocalTract_help) {
+	HELP (U"VocalTract")
+}
 
-DIRECT2 (VocalTract_to_Matrix) {
-	WHERE (SELECTED) {
-		iam_LOOP (VocalTract);
-		autoMatrix thee = VocalTract_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_VocalTract_to_Matrix) {
+	CONVERT_EACH (VocalTract)
+		autoMatrix result = VocalTract_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (VocalTract_to_Spectrum, U"From Vocal Tract to Spectrum", nullptr) {
+FORM (NEW_VocalTract_to_Spectrum, U"From Vocal Tract to Spectrum", nullptr) {
 	LABEL (U"", U"Compute transfer function")
-	NATURAL (U"Number of frequencies", U"4097")
-	POSITIVE (U"Maximum frequency (Hz)", U"5000")
-	REAL (U"Glottal damping", U"0.1")
-	BOOLEAN (U"Radiation damping", true)
-	BOOLEAN (U"Internal damping", true)
-	OK2
+	NATURALVAR (numberOfFequencies, U"Number of frequencies", U"4097")
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	REALVAR (glottalDamping, U"Glottal damping", U"0.1")
+	BOOLEANVAR (radiationDamping, U"Radiation damping", true)
+	BOOLEANVAR (internalDamping, U"Internal damping", true)
+	OK
 DO
-	LOOP {
-		iam (VocalTract);
-		autoSpectrum thee = VocalTract_to_Spectrum (me, GET_INTEGER (U"Number of frequencies"),
-			GET_REAL (U"Maximum frequency"), GET_REAL (U"Glottal damping"),
-			GET_INTEGER (U"Radiation damping"), GET_INTEGER (U"Internal damping"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (VocalTract)
+		autoSpectrum result = VocalTract_to_Spectrum (me, numberOfFequencies,
+			maximumFrequency, glottalDamping, radiationDamping, internalDamping);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (ArticulatorySynthesisTutorial) {
-	Melder_help (U"Articulatory synthesis");
-END2 }
+DIRECT (HELP_ArticulatorySynthesisTutorial) {
+	HELP (U"Articulatory synthesis")
+}
 
 void manual_Artsynth_init (ManPages me);
 
+// MARK: - buttons
+
 void praat_uvafon_Artsynth_init ();
 void praat_uvafon_Artsynth_init () {
 	Thing_recognizeClassesByName (classArt, classArtword, classSpeaker, nullptr);
 
 	praat_addMenuCommand (U"Objects", U"New", U"Articulatory synthesis", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Articulatory synthesis tutorial", nullptr, 1, DO_ArticulatorySynthesisTutorial);
+	praat_addMenuCommand (U"Objects", U"New", U"Articulatory synthesis tutorial", nullptr, praat_DEPTH_1, HELP_ArticulatorySynthesisTutorial);
 	praat_addMenuCommand (U"Objects", U"New", U"-- new articulatory synthesis -- ", nullptr, 1, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Articulation...", nullptr, 1, DO_Art_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Speaker...", nullptr, 1, DO_Speaker_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Artword...", nullptr, 1, DO_Artword_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Articulation...", nullptr, 1, NEW1_Art_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Speaker...", nullptr, 1, NEW1_Speaker_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Artword...", nullptr, 1, NEW1_Artword_create);
 	praat_addMenuCommand (U"Objects", U"New", U"-- new vocal tract --", nullptr, 1, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Vocal Tract from phone...", nullptr, 1, DO_VocalTract_createFromPhone);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Vocal Tract from phone...", nullptr, 1, NEW1_VocalTract_createFromPhone);
 
-	praat_addAction1 (classArt, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Art_edit);
-	praat_addAction1 (classArt, 1, U"Edit", nullptr, praat_HIDDEN, DO_Art_edit);
+	praat_addAction1 (classArt, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Art_viewAndEdit);
+	praat_addAction1 (classArt, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_Art_viewAndEdit);
 
-	praat_addAction1 (classArtword, 0, U"Artword help", nullptr, 0, DO_Artword_help);
-	praat_addAction1 (classArtword, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Artword_edit);
-	praat_addAction1 (classArtword, 1, U"Edit", nullptr, praat_HIDDEN, DO_Artword_edit);
+	praat_addAction1 (classArtword, 0, U"Artword help", nullptr, 0, HELP_Artword_help);
+	praat_addAction1 (classArtword, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Artword_viewAndEdit);
+	praat_addAction1 (classArtword, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_Artword_viewAndEdit);
 	praat_addAction1 (classArtword, 0, U"Info", nullptr, 0, nullptr);
-	praat_addAction1 (classArtword, 1, U"Get target...", nullptr, 0, DO_Artword_getTarget);
+	praat_addAction1 (classArtword, 1, U"Get target...", nullptr, 0, REAL_Artword_getTarget);
 	praat_addAction1 (classArtword, 0, U"Draw", nullptr, 0, nullptr);
-	praat_addAction1 (classArtword, 0, U"Draw...", nullptr, 0, DO_Artword_draw);
+	praat_addAction1 (classArtword, 0, U"Draw...", nullptr, 0, GRAPHICS_Artword_draw);
 	praat_addAction1 (classArtword, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classArtword, 1, U"Set target...", nullptr, 0, DO_Artword_setTarget);
+	praat_addAction1 (classArtword, 1, U"Set target...", nullptr, 0, MODIFY_Artword_setTarget);
 	praat_addAction1 (classArtword, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classArtword, 0, U"To Art (slice)...", nullptr, 0, DO_Artword_to_Art);
+	praat_addAction1 (classArtword, 0, U"To Art (slice)...", nullptr, 0, NEW_Artword_to_Art);
 
 	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Draw", nullptr, 0, nullptr);
-	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Draw", nullptr, 0, DO_Art_Speaker_draw);
-	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Fill inner contour", nullptr, 0, DO_Art_Speaker_fillInnerContour);
-	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Draw mesh", nullptr, 0, DO_Art_Speaker_drawMesh);
+	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Draw", nullptr, 0, GRAPHICS_Art_Speaker_draw);
+	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Fill inner contour", nullptr, 0, GRAPHICS_Art_Speaker_fillInnerContour);
+	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Draw mesh", nullptr, 0, GRAPHICS_Art_Speaker_drawMesh);
 	praat_addAction2 (classArt, 1, classSpeaker, 1, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction2 (classArt, 1, classSpeaker, 1, U"To VocalTract", nullptr, 0, DO_Art_Speaker_to_VocalTract);
+	praat_addAction2 (classArt, 1, classSpeaker, 1, U"To VocalTract", nullptr, 0, NEW1_Art_Speaker_to_VocalTract);
 
-	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"Movie", nullptr, 0, DO_Artword_Speaker_movie);
+	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"Movie", nullptr, 0, MOVIE_Artword_Speaker_movie);
 	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"Draw", nullptr, 0, nullptr);
-	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"Draw...", nullptr, 0, DO_Artword_Speaker_draw);
+	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"Draw...", nullptr, 0, GRAPHICS_Artword_Speaker_draw);
 	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"To Sound...", nullptr, 0, DO_Artword_Speaker_to_Sound);
+	praat_addAction2 (classArtword, 1, classSpeaker, 1, U"To Sound...", nullptr, 0, NEW1_Artword_Speaker_to_Sound);
 
-	praat_addAction3 (classArtword, 1, classSpeaker, 1, classSound, 1, U"Movie", nullptr, 0, DO_Artword_Speaker_Sound_movie);
+	praat_addAction3 (classArtword, 1, classSpeaker, 1, classSound, 1, U"Movie", nullptr, 0, MOVIE_Artword_Speaker_Sound_movie);
 
-	praat_addAction1 (classSpeaker, 0, U"Speaker help", nullptr, 0, DO_Speaker_help);
+	praat_addAction1 (classSpeaker, 0, U"Speaker help", nullptr, 0, HELP_Speaker_help);
 
-	praat_addAction1 (classVocalTract, 0, U"VocalTract help", nullptr, 0, DO_VocalTract_help);
+	praat_addAction1 (classVocalTract, 0, U"VocalTract help", nullptr, 0, HELP_VocalTract_help);
 	praat_addAction1 (classVocalTract, 0, U"Draw", nullptr, 0, nullptr);
-	praat_addAction1 (classVocalTract, 0, U"Draw", nullptr, 0, DO_VocalTract_draw);
+	praat_addAction1 (classVocalTract, 0, U"Draw", nullptr, 0, GRAPHICS_VocalTract_draw);
 	praat_addAction1 (classVocalTract, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classVocalTract, 0, U"To Spectrum...", nullptr, 0, DO_VocalTract_to_Spectrum);
+	praat_addAction1 (classVocalTract, 0, U"To Spectrum...", nullptr, 0, NEW_VocalTract_to_Spectrum);
 	praat_addAction1 (classVocalTract, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classVocalTract, 0, U"Formula...", nullptr, 0, DO_VocalTract_formula);
+	praat_addAction1 (classVocalTract, 0, U"Formula...", nullptr, 0, MODIFY_VocalTract_formula);
 	praat_addAction1 (classVocalTract, 0, U"Hack", nullptr, 0, nullptr);
-	praat_addAction1 (classVocalTract, 0, U"To Matrix", nullptr, 0, DO_VocalTract_to_Matrix);
+	praat_addAction1 (classVocalTract, 0, U"To Matrix", nullptr, 0, NEW_VocalTract_to_Matrix);
 
 	manual_Artsynth_init (theCurrentPraatApplication -> manPages);
 }
diff --git a/contrib/ola/Makefile b/contrib/ola/Makefile
index a583cd7..2c1d666 100644
--- a/contrib/ola/Makefile
+++ b/contrib/ola/Makefile
@@ -1,10 +1,10 @@
 # Makefile of the library "contrib/ola"
 # Ola So"der 19 January 2008
-# Paul Boersma, 24 August 2013
+# Paul Boersma, 22 October 2016
 
 include ../../makefile.defs
 
-CPPFLAGS = -I ../../dwtools -I ../../fon -I ../../sys -I ../../dwsys -I ../../stat -I ../../num -I ../../external/gsl -D_DEBUG -D_REENTRANT
+CPPFLAGS = -I ../../sys -I ../../FFNet -I ../../dwtools -I ../../fon -I ../../dwsys -I ../../stat -I ../../num -I ../../external/gsl -D_DEBUG -D_REENTRANT
 
 OBJECTS = KNN.o \
    KNN_threads.o Pattern_to_Categories_cluster.o KNN_prune.o FeatureWeights.o praat_contrib_Ola_KNN.o manual_KNN.o
@@ -23,4 +23,4 @@ libOla.a: $(OBJECTS)
 	$(AR) cq libOla.a $(OBJECTS)
 	$(RANLIB) libOla.a
 
-$(OBJECTS): *.h ../../sys/*.h ../../dwtools/*.h ../../fon/*.h ../../dwsys/*.h ../../stat/*.h ../../num/*.h ../../external/gsl/*.h
+$(OBJECTS): *.h ../../sys/*.h ../../FFNet/*.h ../../dwtools/*.h ../../fon/*.h ../../dwsys/*.h ../../stat/*.h ../../num/*.h ../../external/gsl/*.h
diff --git a/contrib/ola/praat_contrib_Ola_KNN.cpp b/contrib/ola/praat_contrib_Ola_KNN.cpp
index bda1feb..0e38d81 100644
--- a/contrib/ola/praat_contrib_Ola_KNN.cpp
+++ b/contrib/ola/praat_contrib_Ola_KNN.cpp
@@ -22,6 +22,7 @@
  * pb 2010/12/28 in messages: typos, English, interpunction
  * pb 2011/07/12 C++ and removed several errors
  * pb 2011/09/18 made a start with handling dataChanged at all
+ * pb 2016/10/19 loops, dataChanged, Praat idiom for names, English
  */
 
 #include "KNN.h"
@@ -29,7 +30,11 @@
 #include "KNN_prune.h"
 #include "Pattern_to_Categories_cluster.h"
 #include "FeatureWeights.h"
-#include "praat.h"
+
+#include "praat_FFNet.h"
+
+#undef iam
+#define iam iam_LOOP
 
 static const char32 *QUERY_BUTTON   = U"Query -";
 static const char32 *MODIFY_BUTTON  = U"Modify -";
@@ -39,584 +44,591 @@ static const char32 *EXTRACT_BUTTON = U"Extract -";
 // KNN creations                                                                      //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (KNN_create, U"Create kNN Classifier", U"kNN classifiers 1. What is a kNN classifier?") {
+FORM (NEW1_KNN_create, U"Create kNN Classifier", U"kNN classifiers 1. What is a kNN classifier?") {
 	WORD (U"Name", U"Classifier")
-	OK2
+	OK
 DO
 	autoKNN knn = KNN_create ();
 	praat_new (knn.move(), GET_STRING (U"Name"));
-END2 }
+END }
 
-FORM (KNN_Pattern_Categories_to_KNN, U"Create kNN classifier", U"kNN classifiers 1. What is a kNN classifier?") {
+FORM (NEW1_PatternList_Categories_to_KNN, U"Create kNN classifier", U"kNN classifiers 1. What is a kNN classifier?") {
 	WORD (U"Name", U"Classifier")
 	RADIO (U"Ordering", 1)
-	RADIOBUTTON (U"Random")
-	RADIOBUTTON (U"Sequential")
-	OK2
+		RADIOBUTTON (U"Random")
+		RADIOBUTTON (U"Sequential")
+	OK
 DO
-	iam_ONLY (PatternList);
-	thouart_ONLY (Categories);
-	int ordering = GET_INTEGER (U"Ordering");
-	autoKNN knn = KNN_create ();
-	switch (ordering) {
-		case 1:
-			ordering = kOla_SHUFFLE;
-			break;
-		case 2:
-			ordering = kOla_SEQUENTIAL;
-	}
-	int result = KNN_learn (knn.get(), me, thee, kOla_REPLACE, ordering);
-	switch (result) {
-		case kOla_PATTERN_CATEGORIES_MISMATCH:
-			Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
-		case kOla_DIMENSIONALITY_MISMATCH:
-			Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
-		default:
-			praat_new (knn.move(), GET_STRING(U"Name"));
-	}
-END2 }
+	FIND_TWO (PatternList, Categories)
+		int ordering = GET_INTEGER (U"Ordering");
+		autoKNN knn = KNN_create ();
+		switch (ordering) {
+			case 1:
+				ordering = kOla_SHUFFLE;
+				break;
+			case 2:
+				ordering = kOla_SEQUENTIAL;
+		}
+		int result = KNN_learn (knn.get(), me, you, kOla_REPLACE, ordering);
+		switch (result) {
+			case kOla_PATTERN_CATEGORIES_MISMATCH:
+				Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
+			case kOla_DIMENSIONALITY_MISMATCH:
+				Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
+			default:
+				praat_new (knn.move(), GET_STRING (U"Name"));
+		}
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // KNN extractions, queries and modifications                                         //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-DIRECT2 (KNN_getNumberOfInstances) {
-    iam_ONLY (KNN);
-    Melder_information (my nInstances, U" units");
-END2 }
+DIRECT (INTEGER_KNN_getNumberOfInstances) {
+    NUMBER_ONE (KNN)
+		long result = my nInstances;
+	NUMBER_ONE_END (U" units")
+}
 
-FORM (KNN_getOptimumModel, U"kNN model selection", U"kNN classifiers 1.1.2. Model selection") {
+FORM (INTEGER_KNN_getOptimumModel, U"kNN model selection", U"kNN classifiers 1.1.2. Model selection") {
 	RADIO (U"Evaluation method", 1)
-	RADIOBUTTON (U"Leave one out")
-	RADIOBUTTON (U"10-fold cross-validation")
+		RADIOBUTTON (U"Leave one out")
+		RADIOBUTTON (U"10-fold cross-validation")
 	INTEGER (U"k max", U"50")
 	INTEGER (U"Number of seeds", U"10")
 	POSITIVE (U"Learning rate", U"0.2")
-	OK2
+	OK
 DO
-	iam_ONLY (KNN);
-	long k = GET_INTEGER (U"k max");
-	double lrate = GET_REAL (U"Learning rate");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k max such that 0 < k max < ", my nInstances + 1, U".");
-	long nseeds = GET_INTEGER (U"Number of seeds");
-	if (nseeds < 1)
-		Melder_throw (U"The number of seeds should exceed 1.");
-	int mode = GET_INTEGER (U"Evaluation method");
-	switch (mode) {
-		case 2:
-			mode = kOla_TEN_FOLD_CROSS_VALIDATION;
-			break;
-		case 1:
-			mode = kOla_LEAVE_ONE_OUT;
-			break;
-	}
-	autoFeatureWeights fws = FeatureWeights_create ((my input) -> nx);
-	int dist;
-	KNN_modelSearch (me, fws.get(), &k, &dist, mode, lrate, nseeds);
-	switch (dist) {
-		case kOla_SQUARED_DISTANCE_WEIGHTED_VOTING:
-			Melder_information (U"Vote weighting: Inversed squared distance\n", U"k: ", k);
-			break;
-		case kOla_DISTANCE_WEIGHTED_VOTING:
-			Melder_information (U"Vote weighting: Inversed distance\n", U"k: ", k);
-			break;
-		case kOla_FLAT_VOTING:
-			Melder_information (U"Vote weighting: Flat\n", U"k: ", k);
-			break;
-	}
-END2 }
+	FIND_ONE (KNN)
+		long k = GET_INTEGER (U"k max");
+		double lrate = GET_REAL (U"Learning rate");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k max such that 0 < k max < ", my nInstances + 1, U".");
+		long nseeds = GET_INTEGER (U"Number of seeds");
+		if (nseeds < 1)
+			Melder_throw (U"The number of seeds should exceed 1.");
+		int mode = GET_INTEGER (U"Evaluation method");
+		switch (mode) {
+			case 1:
+				mode = kOla_LEAVE_ONE_OUT;
+				break;
+			case 2:
+				mode = kOla_TEN_FOLD_CROSS_VALIDATION;
+				break;
+		}
+		autoFeatureWeights fws = FeatureWeights_create (my input -> nx);
+		int dist;
+		KNN_modelSearch (me, fws.get(), & k, & dist, mode, lrate, nseeds);
+		switch (dist) {
+			case kOla_SQUARED_DISTANCE_WEIGHTED_VOTING:
+				Melder_information (k, U" (vote weighting: inversed squared distance)");
+				break;
+			case kOla_DISTANCE_WEIGHTED_VOTING:
+				Melder_information (k, U" (vote weighting: inversed distance)");
+				break;
+			case kOla_FLAT_VOTING:
+				Melder_information (k, U" (vote weighting: flat)");
+				break;
+		}
+	END
+}
 
-FORM (KNN_evaluate, U"Evaluation", U"KNN: Get accuracy estimate...") {
+FORM (REAL_KNN_evaluate, U"Evaluation", U"KNN: Get accuracy estimate...") {
 	RADIO (U"Evaluation method", 1)
-	RADIOBUTTON (U"Leave one out")
-	RADIOBUTTON (U"10-fold cross-validation")
+		RADIOBUTTON (U"Leave one out")
+		RADIOBUTTON (U"10-fold cross-validation")
 	INTEGER (U"k neighbours", U"1")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances < 1)
-		Melder_throw (U"Instance base is empty.");
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	int mode = GET_INTEGER (U"Evaluation method");
-	switch (mode) {
-		case 2:
-			mode = kOla_TEN_FOLD_CROSS_VALIDATION;
-			break;
-		case 1: 
-			mode = kOla_LEAVE_ONE_OUT;
-			break;
-	}
-	autoFeatureWeights fws = FeatureWeights_create (my input -> nx);
-	double result = KNN_evaluate (me, fws.get(), k, vt, mode);
-	if (lround (result) == kOla_FWEIGHTS_MISMATCH)
-		Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
-	Melder_information (100 * result, U" percent of the instances correctly classified.");   // BUG: use Melder_percent
-END2 }
-
-FORM (KNN_evaluateWithFeatureWeights, U"Evaluation", U"KNN & FeatureWeights: Get accuracy estimate...") {
+	FIND_ONE (KNN)
+		if (my nInstances < 1)
+			Melder_throw (U"Instance base is empty.");
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		int vt = GET_INTEGER (U"Vote weighting");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}
+		int mode = GET_INTEGER (U"Evaluation method");
+		switch (mode) {
+			case 2:
+				mode = kOla_TEN_FOLD_CROSS_VALIDATION;
+				break;
+			case 1: 
+				mode = kOla_LEAVE_ONE_OUT;
+				break;
+		}
+		autoFeatureWeights fws = FeatureWeights_create (my input -> nx);
+		double result = KNN_evaluate (me, fws.get(), k, vt, mode);
+		if (lround (result) == kOla_FWEIGHTS_MISMATCH)
+			Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
+		Melder_information (100 * result, U" percent of the instances correctly classified.");   // BUG: use Melder_percent
+	END
+}
+
+FORM (REAL_KNN_FeatureWeights_evaluate, U"Evaluation", U"KNN & FeatureWeights: Get accuracy estimate...") {
 	RADIO (U"Evaluation method", 1)
-	RADIOBUTTON (U"Leave one out")
-	RADIOBUTTON (U"10-fold cross-validation")
+		RADIOBUTTON (U"Leave one out")
+		RADIOBUTTON (U"10-fold cross-validation")
 	INTEGER (U"k neighbours", U"1")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances < 1)
-		Melder_throw (U"Instance base is empty");
-	thouart_ONLY (FeatureWeights);
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}   
-	int mode = GET_INTEGER (U"Evaluation method");
-	switch (mode) {
-		case 2:
-			mode = kOla_TEN_FOLD_CROSS_VALIDATION;
-			break;
-		case 1:
-			mode = kOla_LEAVE_ONE_OUT;
-			break;
+	FIND_TWO (KNN, FeatureWeights)
+		if (my nInstances < 1)
+			Melder_throw (U"Instance base is empty");
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		int vt = GET_INTEGER (U"Vote weighting");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}   
+		int mode = GET_INTEGER (U"Evaluation method");
+		switch (mode) {
+			case 2:
+				mode = kOla_TEN_FOLD_CROSS_VALIDATION;
+				break;
+			case 1:
+				mode = kOla_LEAVE_ONE_OUT;
+				break;
+		}
+		double result = KNN_evaluate (me, you, k, vt, mode);
+		if (lround (result) == kOla_FWEIGHTS_MISMATCH)
+			Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
+		Melder_information (100 * result, U" percent of the instances correctly classified.");   // BUG: never report a percentage; always report a fraction
+	END
+}
+
+DIRECT (NEW_KNN_extractInputPatterns) {
+	LOOP {
+		iam (KNN);
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		autoPatternList input = Data_copy (my input.get());
+		praat_new (input.move(), my name, U"_input");
+	}
+END }
+
+DIRECT (NEW_KNN_extractOutputCategories) {
+	LOOP {
+		iam (KNN);
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		autoCategories output = Data_copy (my output.get());
+		praat_new (output.move(), my name, U"_output");
 	}
-	double result = KNN_evaluate (me, thee, k, vt, mode);
-	if (lround (result) == kOla_FWEIGHTS_MISMATCH)
-		Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
-	Melder_information (100 * result, U" percent of the instances correctly classified.");
-END2 }
-
-DIRECT2 (KNN_extractInputPatterns) {
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	autoPatternList input = Data_copy (my input.get());
-	praat_new (input.move(), U"Input Patterns");
-END2 }
-
-DIRECT2 (KNN_extractOutputCategories) {
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	autoCategories output = Data_copy (my output.get());
-	praat_new (output.move(), U"Output Categories");
-END2 }
-
-FORM (KNN_reset, U"Reset", U"KNN: Reset...") {
+END }
+
+FORM (MODIFY_KNN_reset, U"Reset", U"KNN: Reset...") {
     LABEL (U"", U"Warning: this command destroys all previous learning.")
-    OK2
+    OK
 DO
-	iam_ONLY (KNN);
-	my input.reset();
-	my output.reset();
-	my nInstances = 0;
-	praat_dataChanged (me);   // BUG: this should be inserted much more often
-END2 }
-
-DIRECT2 (KNN_shuffle) {
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	KNN_shuffleInstances (me);
-END2 }
-
-FORM (KNN_prune, U"Pruning", U"KNN: Prune...") {
+	LOOP {
+		iam (KNN);
+		my input.reset();
+		my output.reset();
+		my nInstances = 0;
+		praat_dataChanged (me);   // BUG: this should be inserted much more often
+	}
+END }
+
+DIRECT (MODIFY_KNN_shuffle) {
+	LOOP {
+		iam (KNN);
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		KNN_shuffleInstances (me);
+		praat_dataChanged (me);
+	}
+END }
+
+FORM (INFO_MODIFY_KNN_prune, U"Pruning", U"KNN: Prune...") {
 	POSITIVE (U"Noise pruning degree", U"1")
 	POSITIVE (U"Redundancy pruning degree", U"1")
 	INTEGER (U"k neighbours", U"1")
-	OK2
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	long oldn = my nInstances;   // save before it changes!
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	double n = GET_REAL (U"Noise pruning degree");
-	double r = GET_REAL (U"Redundancy pruning degree");
-	if (n <= 0 || n > 1 || r <= 0 || r > 1)
-		Melder_throw (U"Please select a pruning degree d such that 0 < d <= 1.");
-	long npruned = KNN_prune_prune (me, n, r, k);
-	Melder_information (npruned, U" instances discarded. \n", U"Size of new instance base: ", oldn - npruned);
-END2 }
+	FIND_ONE (KNN)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		long oldn = my nInstances;   // save before it changes!
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		double n = GET_REAL (U"Noise pruning degree");
+		double r = GET_REAL (U"Redundancy pruning degree");
+		if (n <= 0 || n > 1 || r <= 0 || r > 1)
+			Melder_throw (U"Please select a pruning degree d such that 0 < d <= 1.");
+		long npruned = KNN_prune_prune (me, n, r, k);
+		Melder_information (npruned, U" instances discarded. \n", U"Size of new instance base: ", oldn - npruned);
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Learning                                                                            //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (KNN_learn, U"Learning", U"kNN classifiers 1. What is a kNN classifier?") {
+FORM (MODIFY_KNN_PatternList_Categories_learn, U"Learning", U"kNN classifiers 1. What is a kNN classifier?") {
 	RADIO (U"Learning method", 1)
-	RADIOBUTTON (U"Append new information")
-	RADIOBUTTON (U"Replace current intancebase")
+		RADIOBUTTON (U"Append new information")
+		RADIOBUTTON (U"Replace current instance base")
 	RADIO (U"Ordering", 1)
-	RADIOBUTTON (U"Random")
-	RADIOBUTTON (U"Sequential")
-	OK2
+		RADIOBUTTON (U"Random")
+		RADIOBUTTON (U"Sequential")
+	OK
 DO
-	iam_ONLY (KNN);
-	thouart_ONLY (PatternList);
-	heis_ONLY (Categories);
-	int ordering = GET_INTEGER (U"Ordering");
-	switch (ordering) {
-		case 1:
-			ordering = kOla_SHUFFLE;
-			break;
-		case 2:
-			ordering = kOla_SEQUENTIAL;
-	}
-	int method = GET_INTEGER (U"Learning method");
-	int result = kOla_ERROR;
-	switch (method) {
-		case 1:
-			result = KNN_learn (me, thee, him, my nInstances == 0 ? kOla_REPLACE : kOla_APPEND, ordering);
-			break;
-		case 2:
-			result = KNN_learn (me, thee, him, kOla_REPLACE, ordering);
-			break;
-	}
-	switch (result) {
-		case kOla_PATTERN_CATEGORIES_MISMATCH:  
-			Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
-		case kOla_DIMENSIONALITY_MISMATCH:
-			Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
-	}
-END2 }
+	FIND_THREE (KNN, PatternList, Categories)
+		int ordering = GET_INTEGER (U"Ordering");
+		switch (ordering) {
+			case 1:
+				ordering = kOla_SHUFFLE;
+				break;
+			case 2:
+				ordering = kOla_SEQUENTIAL;
+		}
+		int method = GET_INTEGER (U"Learning method");
+		int result = kOla_ERROR;
+		switch (method) {
+			case 1:
+				result = KNN_learn (me, you, him, my nInstances == 0 ? kOla_REPLACE : kOla_APPEND, ordering);
+				break;
+			case 2:
+				result = KNN_learn (me, you, him, kOla_REPLACE, ordering);
+				break;
+		}
+		switch (result) {
+			case kOla_PATTERN_CATEGORIES_MISMATCH:  
+				Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
+			case kOla_DIMENSIONALITY_MISMATCH:
+				Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
+		}
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Evaluation                                                                          //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (KNN_evaluateWithTestSet, U"Evaluation", U"KNN & PatternList & Categories: Evaluate...") {
+FORM (BUG_KNN_evaluateWithTestSet, U"Evaluation", U"KNN & PatternList & Categories: Evaluate...") {
 	INTEGER (U"k neighbours", U"1")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty");
-	thouart_ONLY (PatternList);
-	heis_ONLY (Categories);
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	if (thy ny != his size)
-		Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
-	if (thy nx != (my input)->nx)
-		Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
-	autoFeatureWeights fws = FeatureWeights_create (thy nx);
-	double result = KNN_evaluateWithTestSet (me, thee, him, fws.get(), k, vt);
-	Melder_information (100 * result, U" percent of the instances correctly classified.");
-END2 }
-
-FORM (KNN_evaluateWithTestSetAndFeatureWeights, U"Evaluation", U"KNN & PatternList & Categories & FeatureWeights: Evaluate...") {
-	INTEGER (U"k neighbours", U"1")
-	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+	FIND_THREE (KNN, PatternList, Categories)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty");
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		int vt = GET_INTEGER (U"Vote weighting");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}
+		if (your ny != his size)
+			Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
+		if (your nx != my input -> nx)
+			Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
+		autoFeatureWeights fws = FeatureWeights_create (your nx);
+		double result = KNN_evaluateWithTestSet (me, you, him, fws.get(), k, vt);
+		Melder_information (100 * result, U" percent of the instances correctly classified.");
+	END
+}
+
+FORM (BUG_KNN_evaluateWithTestSetAndFeatureWeights, U"Evaluation", U"KNN & PatternList & Categories & FeatureWeights: Evaluate...") {
+	INTEGER4 (kNeighbours, U"k neighbours", U"1")
+	RADIO4 (voteWeighting, U"Vote weighting", 1)
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty");
-	PatternList p = (PatternList) ONLY (classPatternList);
-	Categories c = (Categories) ONLY (classCategories);
-	FeatureWeights fws = (FeatureWeights) ONLY (classFeatureWeights);
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	if (p -> ny != c->size)
-		Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
-	if (p -> nx != my input -> nx)
-		Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
-	if (p->nx != fws -> fweights -> numberOfColumns)
-		Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
-	double result = KNN_evaluateWithTestSet (me, p, c, fws, k, vt);
-	Melder_information (100 * result, U" percent of the instances correctly classified.");
-END2 }
+	FIND_FOUR (KNN, PatternList, Categories, FeatureWeights)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty");
+		if (kNeighbours < 1 || kNeighbours > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		switch (voteWeighting) {
+			case 1:
+				voteWeighting = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				voteWeighting = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				voteWeighting = kOla_FLAT_VOTING;
+				break;
+		}
+		if (your ny != his size)
+			Melder_throw (U"The number of Categories should be equal to the number of rows in PatternList.");
+		if (your nx != my input -> nx)
+			Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
+		if (your nx != her fweights -> numberOfColumns)
+			Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
+		double result = KNN_evaluateWithTestSet (me, you, him, she, kNeighbours, voteWeighting);
+		Melder_information (100 * result, U" percent of the instances correctly classified.");
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Classification                                                                      //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (KNN_toCategories, U"Classification", U"KNN & PatternList: To Categories...") {
+FORM (NEW1_KNN_PatternList_to_Categories, U"Classification", U"KNN & PatternList: To Categories...") {
 	INTEGER (U"k neighbours", U"1")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	thouart_ONLY (PatternList);
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	if (thy nx != my input -> nx)
-		Melder_throw (U"The dimensionality of PatternList should match that of the instance base.");
-	autoFeatureWeights fws = FeatureWeights_create (thy nx);
-	autoCategories result = KNN_classifyToCategories (me, thee, fws.get(), k, vt);
-	praat_new (result.move(), U"Output");
-END2 }
-
-FORM (KNN_toTableOfReal, U"Classification", U"KNN & PatternList: To TabelOfReal...") {
+	FIND_TWO (KNN, PatternList)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		int vt = GET_INTEGER (U"Vote weighting");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}
+		if (your nx != my input -> nx)
+			Melder_throw (U"The dimensionality of PatternList should match that of the instance base.");
+		autoFeatureWeights fws = FeatureWeights_create (your nx);
+		autoCategories result = KNN_classifyToCategories (me, you, fws.get(), k, vt);
+		praat_new (result.move(), my name, U"_", your name);
+	END
+}
+
+FORM (NEW1_KNN_PatternList_to_TableOfReal, U"Classification", U"KNN & PatternList: To TabelOfReal...") {
 	INTEGER (U"k neighbours", U"1")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	thouart_ONLY (PatternList);
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	autoFeatureWeights fws = FeatureWeights_create(thy nx);
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	if (thy nx != my input -> nx)
-		Melder_throw (U"The dimensionality of PatternList should match that of the instance base.");
-	autoTableOfReal result = KNN_classifyToTableOfReal (me, thee, fws.get(), k, vt);
-	praat_new (result.move(), U"Output");
-END2 }
+	FIND_TWO (KNN, PatternList)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		autoFeatureWeights fws = FeatureWeights_create (your nx);
+		int vt = GET_INTEGER (U"Vote weighting");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}
+		if (your nx != my input -> nx)
+			Melder_throw (U"The dimensionality of PatternList should match that of the instance base.");
+		autoTableOfReal result = KNN_classifyToTableOfReal (me, you, fws.get(), k, vt);
+		praat_new (result.move(), U"Output");
+	END
+}
 
-FORM (KNN_toCategoriesWithFeatureWeights, U"Classification", U"KNN & PatternList & FeatureWeights: To Categories...") {
+FORM (NEW1_KNN_PatternList_FeatureWeights_to_Categories, U"Classification", U"KNN & PatternList & FeatureWeights: To Categories...") {
 	INTEGER (U"k neighbours", U"KNN & PatternList & FeatureWeights: To Categories...")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")  
-	RADIOBUTTON (U"Inversed distance")
-	RADIOBUTTON (U"Flat")
-	OK2
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
+		RADIOBUTTON (U"Flat")
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	thouart_ONLY (PatternList);
-	heis_ONLY (FeatureWeights);
-	int vt = GET_INTEGER (U"Vote weighting");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;  
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	if (thy nx != (my input)->nx)
-		Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
-	if (thy nx != his fweights -> numberOfColumns)
-		Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
-	autoCategories result = KNN_classifyToCategories (me, thee, him, k, vt);
-	praat_new (result.move(), U"Output");
-END2 }
-
-FORM (KNN_toTableOfRealWithFeatureWeights, U"Classification", U"KNN & PatternList & FeatureWeights: To TableOfReal...") {
+	FIND_THREE (KNN, PatternList, FeatureWeights)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		int vt = GET_INTEGER (U"Vote weighting");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;  
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		if (your nx != my input -> nx)
+			Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
+		if (your nx != his fweights -> numberOfColumns)
+			Melder_throw (U"The number of feature weights should be equal to the dimensionality of the PatternList.");
+		autoCategories result = KNN_classifyToCategories (me, you, him, k, vt);
+		praat_new (result.move(), U"Output");
+	END
+}
+
+FORM (NEW1_KNN_PatternList_FeatureWeights_to_TableOfReal, U"Classification", U"KNN & PatternList & FeatureWeights: To TableOfReal...") {
 	INTEGER (U"k neighbours", U"1")
 	RADIO (U"Vote weighting", 1)
-	RADIOBUTTON (U"Inversed squared distance")
-	RADIOBUTTON (U"Inversed distance")
+		RADIOBUTTON (U"Inverse squared distance")
+		RADIOBUTTON (U"Inverse distance")
 	RADIOBUTTON (U"Flat")
-	OK2
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty.");
-	thouart_ONLY (PatternList);
-	heis_ONLY (FeatureWeights);
-	long k = GET_INTEGER (U"k neighbours");
-	int vt = GET_INTEGER (U"Vote weighting");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U"\n");
-	if (thy nx != his fweights -> numberOfColumns)
-		Melder_throw (U"The number of features and the number of feature weights should be equal.");
-	switch (vt) {
-		case 1:
-			vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			vt = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			vt = kOla_FLAT_VOTING;
-			break;
-	}
-	autoTableOfReal result = KNN_classifyToTableOfReal (me, thee, him, k, vt);
-	praat_new (result.move(), U"Output");
-END2 }
+	FIND_THREE (KNN, PatternList, FeatureWeights)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty.");
+		long k = GET_INTEGER (U"k neighbours");
+		int vt = GET_INTEGER (U"Vote weighting");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U"\n");
+		if (your nx != his fweights -> numberOfColumns)
+			Melder_throw (U"The number of features and the number of feature weights should be equal.");
+		switch (vt) {
+			case 1:
+				vt = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				vt = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				vt = kOla_FLAT_VOTING;
+				break;
+		}
+		autoTableOfReal result = KNN_classifyToTableOfReal (me, you, him, k, vt);
+		praat_new (result.move(), U"Output");
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Clustering                                                                          //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (Pattern_to_Categories_cluster, U"k-means clustering", U"PatternList: To Categories...") {
+FORM (NEW_PatternList_to_Categories_cluster, U"k-means clustering", U"PatternList: To Categories...") {
 	INTEGER (U"k clusters", U"1")
-	POSITIVE (U"Cluster size ratio constraint", U"0.0000001");
+	POSITIVE (U"Cluster size ratio constraint", U"1e-7");
 	INTEGER (U"Maximum number of reseeds", U"1000")
-	OK2
+	OK
 DO
-	iam_ONLY (PatternList);
-	if (my nx > 0 && my ny > 0) {
-		long k = GET_INTEGER (U"k clusters");
-		if (k < 1 || k > my ny)
-			Melder_throw (U"Please select a value of k such that 0 < k <= ", my ny, U".");
-		long rs =  GET_INTEGER (U"Maximum number of reseeds");
-		if (rs < 0)
-			Melder_throw (U"The maximum number of reseeds should not be negative.");
-		double rc =  GET_REAL (U"Cluster size ratio constraint");
-		if (rc > 1 || rc <= 0)
-			Melder_throw (U"Please select a value of the cluster size ratio constraint c such that 0 < c <= 1.");
-		autoFeatureWeights fws = FeatureWeights_create (my nx);
-		autoCategories result = PatternList_to_Categories_cluster (me, fws.get(), k, rc, rs);
-		praat_new (result.move(), U"Output");
-	} else {
-		Melder_throw (U"PatternList is empty.");
+	LOOP {
+		iam (PatternList);
+		if (my nx > 0 && my ny > 0) {
+			long k = GET_INTEGER (U"k clusters");
+			if (k < 1 || k > my ny)
+				Melder_throw (U"Please select a value of k such that 0 < k <= ", my ny, U".");
+			long rs =  GET_INTEGER (U"Maximum number of reseeds");
+			if (rs < 0)
+				Melder_throw (U"The maximum number of reseeds should not be negative.");
+			double rc =  GET_REAL (U"Cluster size ratio constraint");
+			if (rc > 1 || rc <= 0)
+				Melder_throw (U"Please select a value of the cluster size ratio constraint c such that 0 < c <= 1.");
+			autoFeatureWeights fws = FeatureWeights_create (my nx);
+			autoCategories result = PatternList_to_Categories_cluster (me, fws.get(), k, rc, rs);
+			praat_new (result.move(), U"Output");
+		} else {
+			Melder_throw (U"PatternList is empty.");
+		}
 	}
-END2 }
+END }
 
-FORM (Pattern_to_Categories_clusterWithFeatureWeights, U"k-means clustering", U"PatternList & FeatureWeights: To Categories...") {
+FORM (NEW1_PatternList_FeatureWeights_to_Categories_cluster, U"k-means clustering", U"PatternList & FeatureWeights: To Categories...") {
 	INTEGER (U"k clusters", U"1")
-	POSITIVE (U"Cluster size ratio constraint", U"0.0000001");
+	POSITIVE (U"Cluster size ratio constraint", U"1e-7");
 	INTEGER (U"Maximum number of reseeds", U"1000")
-	OK2
+	OK
 DO
-	iam_ONLY (PatternList);
-	if (my nx > 0 && my ny > 0) {
-		thouart_ONLY (FeatureWeights); 
-		if (my nx != thy fweights -> numberOfColumns)
+	FIND_TWO (PatternList, FeatureWeights)
+		if (my nx <= 0 || my ny <= 0)
+			Melder_throw (U"PatternList is empty.");
+		if (my nx != your fweights -> numberOfColumns)
 			Melder_throw (U"The number of features and the number of feature weights should be equal.");
-		long k = GET_INTEGER(U"k clusters");
+		long k = GET_INTEGER (U"k clusters");
 		if (k < 1 || k > my ny)
 			Melder_throw (U"Please select a value of k such that 0 < k <= ", my ny, U".");
-		long rs =  GET_INTEGER(U"Maximum number of reseeds");
+		long rs =  GET_INTEGER (U"Maximum number of reseeds");
 		if (rs < 0)
 			Melder_throw (U"The maximum number of reseeds should not be negative.");
-		double rc =  GET_REAL(U"Cluster size ratio constraint");
+		double rc =  GET_REAL (U"Cluster size ratio constraint");
 		if (rc > 1 || rc <= 0)
 			Melder_throw (U"Please select a value of the cluster size ratio constraint c such that 0 < c <= 1.");
-		autoCategories result = PatternList_to_Categories_cluster (me, thee, k, rc, rs);
+		autoCategories result = PatternList_to_Categories_cluster (me, you, k, rc, rs);
 		praat_new (result.move(), U"Output");
-	} else {
-		Melder_throw (U"PatternList is empty.");
-	}
-END2 }
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Dissimilarity computations                                                          //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-DIRECT2 (KNN_patternToDissimilarity) {
-	iam_ONLY (PatternList);
-	autoFeatureWeights fws = FeatureWeights_create (my nx);
-	autoDissimilarity result = KNN_patternToDissimilarity (me, fws.get());
-	praat_new (result.move(), U"Output");
-END2 }
-
-DIRECT2 (KNN_patternToDissimilarityWithFeatureWeights) {
-	iam_ONLY (PatternList);
-	thouart_ONLY (FeatureWeights);  
-	if (my nx != thy fweights -> numberOfColumns)
-		Melder_throw (U"The number of features and the number of feature weights should be equal.");
-	autoDissimilarity result = KNN_patternToDissimilarity (me, thee);
-	praat_new (result.move(), U"Output");
-END2 }
+DIRECT (NEW_PatternList_to_Dissimilarity) {
+	LOOP {
+		iam (PatternList);
+		autoFeatureWeights fws = FeatureWeights_create (my nx);
+		autoDissimilarity result = KNN_patternToDissimilarity (me, fws.get());
+		praat_new (result.move(), my name);
+	}
+END }
+
+DIRECT (NEW1_PatternList_FeatureWeights_to_Dissimilarity) {
+	FIND_TWO (PatternList, FeatureWeights)
+		if (my nx != your fweights -> numberOfColumns)
+			Melder_throw (U"The number of features and the number of feature weights should be equal.");
+		autoDissimilarity result = KNN_patternToDissimilarity (me, you);
+		praat_new (result.move(), U"Output");
+	END
+}
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Computation of permutation                                                          //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (KNN_SA_computePermutation, U"To Permutation...", U"PatternList & Categories: To FeatureWeights...") {
+FORM (NEW_KNN_to_Permutation_annealing, U"KNN: To Permutation", U"PatternList & Categories: To FeatureWeights...") {
 	NATURAL (U"Tries per step", U"200")
 	NATURAL (U"Iterations", U"10")
 	POSITIVE (U"Step size", U"10")
@@ -624,39 +636,41 @@ FORM (KNN_SA_computePermutation, U"To Permutation...", U"PatternList & Categorie
 	POSITIVE (U"Initial temperature", U"0.002")
 	POSITIVE (U"Damping factor", U"1.005")
 	POSITIVE (U"Final temperature", U"0.000002")
-	OK2
+	OK
 DO
-	iam_ONLY (KNN);
-	long tries = GET_INTEGER (U"Tries per step");
-	long iterations = GET_INTEGER (U"Iterations");
-	double step_size = GET_REAL (U"Step size");
-	double bolzmann_c = GET_REAL (U"Boltzmann constant");
-	double temp_start = GET_REAL (U"Initial temperature");
-	double temp_damp = GET_REAL (U"Damping factor");
-	double temp_stop = GET_REAL (U"Final temperature");
-	autoPermutation result = KNN_SA_ToPermutation (me, tries, iterations, step_size, bolzmann_c, temp_start, temp_damp, temp_stop);
-	praat_new (result.move(), U"Output");
-END2 }
+	LOOP {
+		iam (KNN);
+		long tries = GET_INTEGER (U"Tries per step");
+		long iterations = GET_INTEGER (U"Iterations");
+		double step_size = GET_REAL (U"Step size");
+		double bolzmann_c = GET_REAL (U"Boltzmann constant");
+		double temp_start = GET_REAL (U"Initial temperature");
+		double temp_damp = GET_REAL (U"Damping factor");
+		double temp_stop = GET_REAL (U"Final temperature");
+		autoPermutation result = KNN_SA_ToPermutation (me, tries, iterations, step_size, bolzmann_c, temp_start, temp_damp, temp_stop);
+		praat_new (result.move(), my name);
+	}
+END }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Computation of feature weights                                                      //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (FeatureWeights_computeRELIEF, U"Feature weights", U"PatternList & Categories: To FeatureWeights...") {
+FORM (NEW1_PatternList_Categories_to_FeatureWeights_relief, U"Feature weights", U"PatternList & Categories: To FeatureWeights...") {
 	INTEGER (U"Number of neighbours", U"1")
-	OK2
+	OK
 DO
-	iam_ONLY (PatternList);
-	thouart_ONLY (Categories);
-	if (my ny < 2)
-		Melder_throw (U"The PatternList object should contain at least two rows.");
-	if (my ny != thy size)
-		Melder_throw (U"The number of rows in the PatternList object should equal the number of categories in the Categories object.");
-	autoFeatureWeights result = FeatureWeights_compute (me, thee, GET_INTEGER (U"Number of neighbours"));
-	praat_new (result.move(), U"Output");
-END2 }
-
-FORM (FeatureWeights_computeWrapperExt, U"Feature weights", U"KNN & PatternList & Categories: To FeatureWeights..") {
+	FIND_TWO (PatternList, Categories)
+		if (my ny < 2)
+			Melder_throw (U"The PatternList object should contain at least two rows.");
+		if (my ny != your size)
+			Melder_throw (U"The number of rows in the PatternList object should equal the number of categories in the Categories object.");
+		autoFeatureWeights result = FeatureWeights_compute (me, you, GET_INTEGER (U"Number of neighbours"));
+		praat_new (result.move(), U"Output");
+	END
+}
+
+FORM (NEW1_KNN_PatternList_Categories_to_FeatureWeights_wrapperExt, U"Feature weights", U"KNN & PatternList & Categories: To FeatureWeights..") {
 	POSITIVE (U"Learning rate", U"0.02")
 	NATURAL (U"Number of seeds", U"20")
 	POSITIVE (U"Stop at", U"1")
@@ -668,36 +682,35 @@ FORM (FeatureWeights_computeWrapperExt, U"Feature weights", U"KNN & PatternList
 		RADIOBUTTON (U"Inversed squared distance")
 		RADIOBUTTON (U"Inversed distance")
 		RADIOBUTTON (U"Flat")
-	OK2
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances <= 0)
-		Melder_throw (U"Instance base is empty");
-	thouart_ONLY (PatternList);
-	heis_ONLY (Categories);
-	int mode = GET_INTEGER (U"Vote weighting");
-	switch (mode) {
-		case 1:
-			mode = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 2:
-			mode = kOla_DISTANCE_WEIGHTED_VOTING;
-			break;
-		case 3:
-			mode = kOla_FLAT_VOTING;
-			break;
-	}
-	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	if (thy nx != my input -> nx)
-		Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
-	autoFeatureWeights result = FeatureWeights_computeWrapperExt (me, thee, him, k, mode, GET_INTEGER (U"Number of seeds"),
-		GET_REAL (U"Learning rate"), GET_REAL (U"Stop at"), (int) GET_INTEGER (U"Optimization"));
-	praat_new (result.move(), U"Output");
-END2 }
-
-FORM (FeatureWeights_computeWrapperInt, U"Feature weights", U"KNN: To FeatureWeights...") {
+	FIND_THREE (KNN, PatternList, Categories)
+		if (my nInstances <= 0)
+			Melder_throw (U"Instance base is empty");
+		int mode = GET_INTEGER (U"Vote weighting");
+		switch (mode) {
+			case 1:
+				mode = kOla_SQUARED_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 2:
+				mode = kOla_DISTANCE_WEIGHTED_VOTING;
+				break;
+			case 3:
+				mode = kOla_FLAT_VOTING;
+				break;
+		}
+		long k = GET_INTEGER (U"k neighbours");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		if (your nx != my input -> nx)
+			Melder_throw (U"The dimensionality of PatternList should be equal to that of the instance base.");
+		autoFeatureWeights result = FeatureWeights_computeWrapperExt (me, you, him, k, mode, GET_INTEGER (U"Number of seeds"),
+			GET_REAL (U"Learning rate"), GET_REAL (U"Stop at"), (int) GET_INTEGER (U"Optimization"));
+		praat_new (result.move(), U"Output");
+	END
+}
+
+FORM (NEW_KNN_to_FeatureWeights_wrapperInt, U"Feature weights", U"KNN: To FeatureWeights...") {
 	POSITIVE (U"Learning rate", U"0.02")
 	NATURAL (U"Number of seeds", U"10")
 	POSITIVE (U"Stop at", U"1")
@@ -712,19 +725,16 @@ FORM (FeatureWeights_computeWrapperInt, U"Feature weights", U"KNN: To FeatureWei
 		RADIOBUTTON (U"Inversed squared distance")
 		RADIOBUTTON (U"Inversed distance")
 		RADIOBUTTON (U"Flat")
-	OK2
+	OK
 DO
-	iam_ONLY (KNN);
-	if (my nInstances < 1)
-		Melder_throw (U"Instance base is empty");
 	int emode = GET_INTEGER (U"Evaluation method");
 	switch (emode) {
-		case 2:
-			emode = kOla_TEN_FOLD_CROSS_VALIDATION;
-			break;
 		case 1:
 			emode = kOla_LEAVE_ONE_OUT;
 			break;
+		case 2:
+			emode = kOla_TEN_FOLD_CROSS_VALIDATION;
+			break;
 	}
 	int mode = GET_INTEGER (U"Vote weighting");
 	switch (mode) {
@@ -739,43 +749,30 @@ DO
 			break;
 	}
 	long k = GET_INTEGER (U"k neighbours");
-	if (k < 1 || k > my nInstances)
-		Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
-	autoFeatureWeights result = FeatureWeights_computeWrapperInt (me, k, mode, GET_INTEGER (U"Number of seeds"), GET_REAL (U"Learning rate"),
-		GET_REAL (U"Stop at"), (int) GET_INTEGER (U"Optimization"), emode);
-	praat_new (result.move(), U"Output");
-END2 }
+	LOOP {
+		iam (KNN);
+		if (my nInstances < 1)
+			Melder_throw (U"Instance base is empty");
+		if (k < 1 || k > my nInstances)
+			Melder_throw (U"Please select a value of k such that 0 < k < ", my nInstances + 1, U".");
+		autoFeatureWeights result = FeatureWeights_computeWrapperInt (me, k, mode, GET_INTEGER (U"Number of seeds"), GET_REAL (U"Learning rate"),
+			GET_REAL (U"Stop at"), (int) GET_INTEGER (U"Optimization"), emode);
+		praat_new (result.move(), my name, U"_output");
+	}
+END }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Creation and processing of auxiliary datatypes                                      //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-FORM (Pattern_create, U"Create PatternList", 0) {
-	WORD (U"Name", U"1x1")
-	NATURAL (U"Dimension of a pattern", U"1")
-	NATURAL (U"Number of patterns", U"1")
-	OK2
-DO
-	autoPatternList result = PatternList_create (GET_INTEGER (U"Number of patterns"), GET_INTEGER (U"Dimension of a pattern"));
-	praat_new (result.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Categories_create, U"Create Categories", 0) {
-	WORD (U"Name", U"empty")
-	OK2
-DO
-	autoCategories result = Categories_create ();
-	praat_new (result.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (FeatureWeights_create, U"Create FeatureWeights", 0) {
+FORM (NEW1_FeatureWeights_create, U"Create FeatureWeights", nullptr) {
 	WORD (U"Name", U"empty")
 	NATURAL (U"Number of weights", U"1")
-	OK2
+	OK
 DO
 	autoFeatureWeights result = FeatureWeights_create (GET_INTEGER (U"Number of weights"));
 	praat_new (result.move(), GET_STRING (U"Name"));
-END2 }
+END }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // DEBUG                                                                               //
@@ -785,32 +782,30 @@ END2 }
 /*
 #ifdef _DEBUG
 
-DIRECT (KNN_debug_KNN_SA_partition)
-    PatternList p = ONLY (classPatternList);
-    autoPatternList output = PatternList_create (p->ny, p->nx);
-    autoNUMvector <long> result (0, p->ny);
-    KNN_SA_partition (p, 1, p->ny, result);
-
-    for (long k = 1, c = 1; k <= output->ny; ++k, ++c)
-        for (long i = 1; i <= p->ny && k <= output->ny; ++i)
-            if(result [i] == c)
-            {
-                for(long j = 1; j <= output->nx; ++j)
-                    output->z[k][j] = p->z[i][j];
-                ++k;
-            }
-
-    praat_new (output.move(), U"Output");
-
-END
+DIRECT (KNN_debug_KNN_SA_partition) {
+    FIND_ONE (PatternList)
+		autoPatternList output = PatternList_create (my ny, my nx);
+		autoNUMvector <long> result (0, my ny);
+		KNN_SA_partition (me, 1, my ny, result);
+
+		for (long k = 1, c = 1; k <= output -> ny; k ++, c ++)
+			for (long i = 1; i <= my ny && k <= output -> ny; i ++)
+				if (result [i] == c) {
+					for(long j = 1; j <= output -> nx; ++j)
+						output -> z [k] [j] = my z [i] [j];
+					k ++;
+				}
+		praat_new (output.move(), U"Output");
+	END
+}
 
-DIRECT (KNN_debug_KNN_getNumberOfCPUs)
+DIRECT (KNN_debug_KNN_getNumberOfCPUs) {
     Melder_information (KNN_getNumberOfCPUs(), U" CPUs available");
-END
+END }
 
-DIRECT (KNN_debug_KNN_threadTest)
+DIRECT (KNN_debug_KNN_threadTest) {
     KNN_threadTest();
-END
+END }
 
 #endif
 */
@@ -819,41 +814,41 @@ END
 // Help                                                                                //
 /////////////////////////////////////////////////////////////////////////////////////////
 
-DIRECT2 (KNN_help) {
+DIRECT (HELP_KNN_help) {
 	Melder_help (U"KNN classifiers");
-END2 }
+END }
 
-DIRECT2 (hint_KNN_and_FeatureWeights_evaluate) {
+DIRECT (HINT_KNN_and_FeatureWeights_evaluate) {
 	Melder_information (U"The accuracy of a KNN can be estimated by selecting a KNN and a FeatureWeights object and choosing \"Evaluate...\".");
-END2 }
+END }
 
-DIRECT2 (hint_KNN_and_Pattern_classify) {
+DIRECT (HINT_KNN_and_Pattern_classify) {
 	Melder_information (U"You can use the KNN as a classifier by selecting a KNN and a PatternList and choosing \"To Categories...\" or \"To TableOfReal...\".");
-END2 }
+END }
 
-DIRECT2 (hint_KNN_and_Pattern_and_FeatureWeights_classify) {
+DIRECT (HINT_KNN_and_Pattern_and_FeatureWeights_classify) {
 	Melder_information (U"You can use the KNN as a classifier by selecting a KNN, a PatternList and an FeatureWeights object and choosing \"To Categories...\" or \"To TableOfReal...\".");
-END2 }
+END }
 
-DIRECT2 (hint_KNN_and_Pattern_and_Categories_learn) {
+DIRECT (HINT_KNN_and_Pattern_and_Categories_learn) {
 	Melder_information (U"You can train a KNN by selecting a KNN, a PatternList and a Categories object together and choosing \"Learn...\".");
-END2 }
+END }
 
-DIRECT2 (hint_KNN_and_Pattern_and_Categories_evaluate) {
+DIRECT (HINT_KNN_and_Pattern_and_Categories_evaluate) {
 	Melder_information (U"The accuracy of a KNN can be estimated by selecting a KNN, a test PatternList and the corresponding Categories object and choosing \"Evaluate...\".");
-END2 }
+END }
 
-DIRECT2 (hint_KNN_and_Pattern_and_Categories_and_FeatureWeights_evaluate) {
+DIRECT (HINT_KNN_and_Pattern_and_Categories_and_FeatureWeights_evaluate) {
 	Melder_information (U"The accuracy of a KNN can be estimated by selecting a KNN, a test PatternList, an FeatureWeights object, and the corresponding Categories object and choosing \"Evaluate...\".");
-END2 }
+END }
 
-DIRECT2 (hint_Pattern_and_FeatureWeights_to_Categories) {
+DIRECT (HINT_Pattern_and_FeatureWeights_to_Categories) {
 	Melder_information (U"A PatternList object and a FeatureWeights object can be used to compute a fixed number of clusters using the k-means clustering clustering algorithm.");
-END2 }
+END }
 
-DIRECT2 (hint_Pattern_and_FeatureWeights_to_Dissimilarity) {
+DIRECT (HINT_Pattern_and_FeatureWeights_to_Dissimilarity) {
 	Melder_information (U"A Dissimilarity matrix can be generated from a PatternList and a FeatureWeights object.");
-END2 }
+END }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // Setting callbacks                                                                   //
@@ -870,57 +865,60 @@ void praat_contrib_Ola_KNN_init ()
 
     praat_addMenuCommand (U"Objects", U"New", U"kNN classifiers", nullptr, 0, nullptr);
 
-    praat_addMenuCommand (U"Objects", U"New", U"kNN classifiers", nullptr, 1, DO_KNN_help);
+    praat_addMenuCommand (U"Objects", U"New", U"kNN classifiers", nullptr, praat_DEPTH_1, HELP_KNN_help);
     praat_addMenuCommand (U"Objects", U"New", U"-- KNN --", nullptr, 1, nullptr);
 
-    praat_addMenuCommand (U"Objects", U"New", U"Create kNN classifier...", nullptr, 1, DO_KNN_create);
+    praat_addMenuCommand (U"Objects", U"New", U"Create kNN classifier...", nullptr, 1, NEW1_KNN_create);
 
     praat_addMenuCommand (U"Objects", U"New", U"Advanced", nullptr, 1, nullptr);
-    praat_addMenuCommand (U"Objects", U"New", U"Create Pattern...", nullptr, 2, DO_Pattern_create);
-    praat_addMenuCommand (U"Objects", U"New", U"Create Categories...", nullptr, 2, DO_Categories_create);
-    praat_addMenuCommand (U"Objects", U"New", U"Create FeatureWeights...", nullptr, 2, DO_FeatureWeights_create);
+    praat_addMenuCommand (U"Objects", U"New", U"Create PatternList...", nullptr, 2, NEW1_PatternList_create);
+    praat_addMenuCommand (U"Objects", U"New", U"Create Categories...", nullptr, 2, NEW1_Categories_create);
+    praat_addMenuCommand (U"Objects", U"New", U"Create FeatureWeights...", nullptr, 2, NEW1_FeatureWeights_create);
 
 /////////////
 // Actions //
 /////////////
 
-    praat_addAction1 (classKNN, 0, U"kNN help", nullptr, 0, DO_KNN_help);
+    praat_addAction1 (classKNN, 0, U"kNN help", nullptr, 0, HELP_KNN_help);
     praat_addAction1 (classKNN, 0, QUERY_BUTTON, nullptr, 0, nullptr);
-    praat_addAction1 (classKNN, 1, U"Get optimized parameters...", nullptr, 2, DO_KNN_getOptimumModel);
-    praat_addAction1 (classKNN, 1, U"Get accuracy estimate...", nullptr, 2, DO_KNN_evaluate);
-    praat_addAction1 (classKNN, 1, U"Get size of instancebase", nullptr, 2, DO_KNN_getNumberOfInstances);
+    praat_addAction1 (classKNN, 1, U"Get optimized parameters...", nullptr, 2, INTEGER_KNN_getOptimumModel);
+    praat_addAction1 (classKNN, 1, U"Get accuracy estimate...", nullptr, 2, REAL_KNN_evaluate);
+    praat_addAction1 (classKNN, 1, U"Get size of instancebase", nullptr, 2, INTEGER_KNN_getNumberOfInstances);
 
     praat_addAction1 (classKNN, 0, MODIFY_BUTTON, nullptr, 0, nullptr);
-    praat_addAction1 (classKNN, 1, U"Shuffle", nullptr, 1, DO_KNN_shuffle);
-    praat_addAction1 (classKNN, 1, U"Prune...", nullptr, 1, DO_KNN_prune);
-    praat_addAction1 (classKNN, 1, U"Reset...", nullptr, 1, DO_KNN_reset);
+    praat_addAction1 (classKNN, 0, U"Shuffle", nullptr, 1, MODIFY_KNN_shuffle);
+    praat_addAction1 (classKNN, 1, U"Prune...", nullptr, 1, INFO_MODIFY_KNN_prune);
+    praat_addAction1 (classKNN, 0, U"Reset...", nullptr, 1, MODIFY_KNN_reset);
     praat_addAction1 (classKNN, 0, EXTRACT_BUTTON, nullptr, 0, nullptr);
-    praat_addAction1 (classKNN, 0, U"Extract input Patterns", nullptr, 1, DO_KNN_extractInputPatterns);
-    praat_addAction1 (classKNN, 0, U"Extract output Categories", nullptr, 1, DO_KNN_extractOutputCategories);
+    praat_addAction1 (classKNN, 0, U"Extract input Patterns", nullptr, 1, NEW_KNN_extractInputPatterns);
+    praat_addAction1 (classKNN, 0, U"Extract output Categories", nullptr, 1, NEW_KNN_extractOutputCategories);
 
-    praat_addAction1 (classKNN, 0, U"To FeatureWeights...", nullptr, 0, DO_FeatureWeights_computeWrapperInt);
+    praat_addAction1 (classKNN, 0, U"To FeatureWeights...", nullptr, 0, NEW_KNN_to_FeatureWeights_wrapperInt);
 
- // praat_addAction1 (classKNN, 0, U"To Permutation...", nullptr, 0, DO_KNN_SA_computePermutation);
- // praat_addAction2 (classKNN, 1, classFeatureWeights, 1, U"To Permutation...", nullptr, 0, DO_KNN_evaluateWithFeatureWeights);
+ // praat_addAction1 (classKNN, 0, U"To Permutation (annealing)...", nullptr, 0, NEW_KNN_to_Permutation_annealing);
+ // praat_addAction2 (classKNN, 1, classFeatureWeights, 1, U"To Permutation...", nullptr, 0, NEW1_KNN_FeatureWeights_to_Permutation);
 
-    praat_addAction (classKNN, 1, classPatternList, 1, classCategories, 1, U"Learn...", nullptr, 0, DO_KNN_learn);
-    praat_addAction2 (classKNN, 1, classFeatureWeights, 1, U"Evaluate...", nullptr, 0, DO_KNN_evaluateWithFeatureWeights);
-    praat_addAction (classKNN, 1, classPatternList, 1, classCategories, 1, U"Evaluate...", nullptr, 0, DO_KNN_evaluateWithTestSet);
-    praat_addAction4 (classKNN, 1, classPatternList, 1, classCategories, 1, classFeatureWeights, 1, U"Evaluate...", nullptr, 0, DO_KNN_evaluateWithTestSetAndFeatureWeights);
-    praat_addAction (classKNN, 1, classPatternList, 1, classCategories, 1, U"To FeatureWeights...", nullptr, 0, DO_FeatureWeights_computeWrapperExt);
-    praat_addAction2 (classKNN, 1, classPatternList, 1, U"To Categories...", nullptr, 0, DO_KNN_toCategories);
-    praat_addAction2 (classKNN, 1, classPatternList, 1, U"To TableOfReal...", nullptr, 0, DO_KNN_toTableOfReal);
+    praat_addAction3 (classKNN, 1, classPatternList, 1, classCategories, 1, U"Learn...", nullptr, 0, MODIFY_KNN_PatternList_Categories_learn);
+    praat_addAction2 (classKNN, 1, classFeatureWeights, 1, U"Evaluate...", nullptr, 0, REAL_KNN_FeatureWeights_evaluate);
+    praat_addAction3 (classKNN, 1, classPatternList, 1, classCategories, 1, U"Evaluate...", nullptr, 0, BUG_KNN_evaluateWithTestSet);
+    praat_addAction4 (classKNN, 1, classPatternList, 1, classCategories, 1, classFeatureWeights, 1, U"Evaluate...", nullptr, 0, BUG_KNN_evaluateWithTestSetAndFeatureWeights);
+    praat_addAction3 (classKNN, 1, classPatternList, 1, classCategories, 1, U"To FeatureWeights...", nullptr, 0,
+		NEW1_KNN_PatternList_Categories_to_FeatureWeights_wrapperExt);
+    praat_addAction2 (classKNN, 1, classPatternList, 1, U"To Categories...", nullptr, 0, NEW1_KNN_PatternList_to_Categories);
+    praat_addAction2 (classKNN, 1, classPatternList, 1, U"To TableOfReal...", nullptr, 0, NEW1_KNN_PatternList_to_TableOfReal);
 
-    praat_addAction (classKNN, 1, classPatternList, 1, classFeatureWeights, 1, U"To Categories...", nullptr, 0, DO_KNN_toCategoriesWithFeatureWeights);
-    praat_addAction (classKNN, 1, classPatternList, 1, classFeatureWeights, 1, U"To TableOfReal...", nullptr, 0, DO_KNN_toTableOfRealWithFeatureWeights);
+    praat_addAction3 (classKNN, 1, classPatternList, 1, classFeatureWeights, 1, U"To Categories...", nullptr, 0,
+		NEW1_KNN_PatternList_FeatureWeights_to_Categories);
+    praat_addAction3 (classKNN, 1, classPatternList, 1, classFeatureWeights, 1, U"To TableOfReal...", nullptr, 0,
+		NEW1_KNN_PatternList_FeatureWeights_to_TableOfReal);
 
-    praat_addAction1 (classPatternList, 1, U"To Dissimilarity", nullptr, 1, DO_KNN_patternToDissimilarity);
-    praat_addAction1 (classPatternList, 1, U"To Categories...", nullptr, 1, DO_Pattern_to_Categories_cluster);
-    praat_addAction2 (classPatternList, 1, classFeatureWeights, 1, U"To Dissimilarity", nullptr, 0, DO_KNN_patternToDissimilarityWithFeatureWeights);
-    praat_addAction2 (classPatternList, 1, classFeatureWeights, 1, U"To Categories...", nullptr, 0, DO_Pattern_to_Categories_clusterWithFeatureWeights);
+    praat_addAction1 (classPatternList, 0, U"To Dissimilarity", nullptr, 1, NEW_PatternList_to_Dissimilarity);
+    praat_addAction1 (classPatternList, 0, U"To Categories (cluster)...", nullptr, 1, NEW_PatternList_to_Categories_cluster);
+    praat_addAction2 (classPatternList, 1, classFeatureWeights, 1, U"To Dissimilarity", nullptr, 0, NEW1_PatternList_FeatureWeights_to_Dissimilarity);
+    praat_addAction2 (classPatternList, 1, classFeatureWeights, 1, U"To Categories (cluster)...", nullptr, 0, NEW1_PatternList_FeatureWeights_to_Categories_cluster);
 
-    praat_addAction2 (classPatternList, 1, classCategories, 1, U"To FeatureWeights...", nullptr, 0, DO_FeatureWeights_computeRELIEF);
-    praat_addAction2 (classPatternList, 1, classCategories, 1, U"To KNN Classifier...", nullptr, 0, DO_KNN_Pattern_Categories_to_KNN);
+    praat_addAction2 (classPatternList, 1, classCategories, 1, U"To FeatureWeights (relief)...", nullptr, 0, NEW1_PatternList_Categories_to_FeatureWeights_relief);
+    praat_addAction2 (classPatternList, 1, classCategories, 1, U"To KNN Classifier...", nullptr, 0, NEW1_PatternList_Categories_to_KNN);
 
 ///////////
 // DEBUG //
@@ -940,16 +938,16 @@ void praat_contrib_Ola_KNN_init ()
 // Hints //
 ///////////
 
-    praat_addAction1 (classPatternList, 0, U"& FeatureWeights: To Categories?", nullptr, 0, DO_hint_Pattern_and_FeatureWeights_to_Categories);
-    praat_addAction1 (classPatternList, 0, U"& FeatureWeights: To Dissimilarity?", nullptr, 0, DO_hint_Pattern_and_FeatureWeights_to_Dissimilarity);
+    praat_addAction1 (classPatternList, 0, U"& FeatureWeights: To Categories?", nullptr, 0, HINT_Pattern_and_FeatureWeights_to_Categories);
+    praat_addAction1 (classPatternList, 0, U"& FeatureWeights: To Dissimilarity?", nullptr, 0, HINT_Pattern_and_FeatureWeights_to_Dissimilarity);
 
-    praat_addAction1 (classKNN, 0, U"& FeatureWeights: Evaluate?", nullptr, 0, DO_hint_KNN_and_FeatureWeights_evaluate);
-//  praat_addAction1 (classKNN, 0, U"& FeatureWeights: To Permutation?", nullptr, 0, DO_hint_Pattern_and_FeatureWeights_to_Dissimilarity);
-    praat_addAction1 (classKNN, 0, U"& Pattern: Classify?", nullptr, 0, DO_hint_KNN_and_Pattern_classify);
-    praat_addAction1 (classKNN, 0, U"& Pattern & FeatureWeights: Classify?", nullptr, 0, DO_hint_KNN_and_Pattern_and_FeatureWeights_classify);
-    praat_addAction1 (classKNN, 0, U"& Pattern & Categories: Learn?", nullptr, 0, DO_hint_KNN_and_Pattern_and_Categories_learn);
-    praat_addAction1 (classKNN, 0, U"& Pattern & Categories: Evaluate?", nullptr, 0, DO_hint_KNN_and_Pattern_and_Categories_evaluate);
-    praat_addAction1 (classKNN, 0, U"& Pattern & Categories & FeatureWeights: Evaluate?", nullptr, 0, DO_hint_KNN_and_Pattern_and_Categories_and_FeatureWeights_evaluate);
+    praat_addAction1 (classKNN, 0, U"& FeatureWeights: Evaluate?", nullptr, 0, HINT_KNN_and_FeatureWeights_evaluate);
+//  praat_addAction1 (classKNN, 0, U"& FeatureWeights: To Permutation?", nullptr, 0, HINT_Pattern_and_FeatureWeights_to_Dissimilarity);
+    praat_addAction1 (classKNN, 0, U"& Pattern: Classify?", nullptr, 0, HINT_KNN_and_Pattern_classify);
+    praat_addAction1 (classKNN, 0, U"& Pattern & FeatureWeights: Classify?", nullptr, 0, HINT_KNN_and_Pattern_and_FeatureWeights_classify);
+    praat_addAction1 (classKNN, 0, U"& Pattern & Categories: Learn?", nullptr, 0, HINT_KNN_and_Pattern_and_Categories_learn);
+    praat_addAction1 (classKNN, 0, U"& Pattern & Categories: Evaluate?", nullptr, 0, HINT_KNN_and_Pattern_and_Categories_evaluate);
+    praat_addAction1 (classKNN, 0, U"& Pattern & Categories & FeatureWeights: Evaluate?", nullptr, 0, HINT_KNN_and_Pattern_and_Categories_and_FeatureWeights_evaluate);
 
     INCLUDE_MANPAGES (manual_KNN_init)
 }
diff --git a/dwsys/Eigen.cpp b/dwsys/Eigen.cpp
index cd53710..f03a6f0 100644
--- a/dwsys/Eigen.cpp
+++ b/dwsys/Eigen.cpp
@@ -401,7 +401,7 @@ void Eigen_drawEigenvalues (Eigen me, Graphics g, long first, long last, double
 	Graphics_setInner (g);
 	Graphics_setWindow (g, xmin, xmax, ymin, ymax);
 	for (long i = first; i <= last; i ++) {
-		double accu = Eigen_getSumOfEigenvalues (me, ( cumulative ? 1 : i ), i);
+		double accu = Eigen_getSumOfEigenvalues (me, (cumulative ? 1 : i), i);
 		Graphics_mark (g, i, accu / scale, size_mm, mark);
 	}
 	Graphics_unsetInner (g);
diff --git a/dwsys/Index.cpp b/dwsys/Index.cpp
index 8832d69..58f8977 100644
--- a/dwsys/Index.cpp
+++ b/dwsys/Index.cpp
@@ -47,21 +47,21 @@
 #include "oo_DESCRIPTION.h"
 #include "Index_def.h"
 
-
+const char32 *undefinedClassLabel = U"";
 Thing_implement (Index, Daata, 0);
 
 void structIndex :: v_info () {
 	structDaata :: v_info ();
-	MelderInfo_writeLine (U"Number of elements: ", our numberOfElements);
+	MelderInfo_writeLine (U"Number of items: ", our numberOfItems);
 }
 
-void Index_init (Index me, long numberOfElements) {
-	if (numberOfElements < 1) {
-		Melder_throw (U"Cannot create index without elements.");
+void Index_init (Index me, long numberOfItems) {
+	if (numberOfItems < 1) {
+		Melder_throw (U"Cannot create index without items.");
 	}
 	my classes = Ordered_create ();
-	my numberOfElements = numberOfElements;
-	my classIndex = NUMvector<long> (1, numberOfElements);
+	my numberOfItems = numberOfItems;
+	my classIndex = NUMvector<long> (1, numberOfItems);
 }
 
 autoIndex Index_extractPart (Index me, long from, long to) {
@@ -70,15 +70,15 @@ autoIndex Index_extractPart (Index me, long from, long to) {
 			from = 1;
 		}
 		if (to == 0) {
-			to = my numberOfElements;
+			to = my numberOfItems;
 		}
-		if (to < from || from < 1 || to > my numberOfElements) {
-			Melder_throw (U"Range should be in interval [1,", my numberOfElements, U"].");
+		if (to < from || from < 1 || to > my numberOfItems) {
+			Melder_throw (U"Range should be in interval [1,", my numberOfItems, U"].");
 		}
 		autoIndex thee = Data_copy (me);
-		thy numberOfElements = to - from + 1;
+		thy numberOfItems = to - from + 1;
 		
-		for (long i = 1; i <= thy numberOfElements; i ++) {
+		for (long i = 1; i <= thy numberOfItems; i ++) {
 			thy classIndex [i] = my classIndex [from + i - 1];
 		}
 		return thee;
@@ -89,17 +89,25 @@ autoIndex Index_extractPart (Index me, long from, long to) {
 
 Thing_implement (StringsIndex, Index, 0);
 
-autoStringsIndex StringsIndex_create (long numberOfElements) {
+autoStringsIndex StringsIndex_create (long numberOfItems) {
 	try {
 		autoStringsIndex me = Thing_new (StringsIndex);
-		Index_init (me.get(), numberOfElements);
+		Index_init (me.get(), numberOfItems);
 		return me;
 	} catch (MelderError) {
 		Melder_throw (U"StringsIndex not created.");
 	}
 }
 
-int StringsIndex_getClass (StringsIndex me, char32 *klasLabel) {
+long Index_getClassIndexFromItemIndex (Index me, long itemIndex) {
+	long result = 0;
+	if (itemIndex >= 0 && itemIndex <= my numberOfItems) {
+		result = my classIndex [itemIndex];
+	}
+	return result;
+}
+
+int StringsIndex_getClassIndexFromClassLabel (StringsIndex me, char32 *klasLabel) {
 	for (long i = 1; i <= my classes->size; i ++) {
 		SimpleString ss = (SimpleString) my classes->at [i];   // FIXME cast
 		if (Melder_equ (ss -> string, klasLabel)) {
@@ -109,9 +117,28 @@ int StringsIndex_getClass (StringsIndex me, char32 *klasLabel) {
 	return 0;
 }
 
+const char32 *StringsIndex_getClassLabelFromClassIndex (StringsIndex me, long klasIndex) {
+	const char32 *result = undefinedClassLabel;
+	if (klasIndex > 0 && klasIndex <= my classes -> size) {
+		SimpleString ss = (SimpleString) my classes->at [klasIndex];   // FIXME cast
+		result = ss -> string;
+	}
+	return result;
+}
+
+const char32 *StringsIndex_getItemLabelFromItemIndex (StringsIndex me, long itemNumber) {
+	const char32 *result = undefinedClassLabel;
+	if (itemNumber > 0 && itemNumber <= my numberOfItems) {
+		long klas = my classIndex [itemNumber];
+		SimpleString ss = (SimpleString) my classes->at [klas];   // FIXME cast
+		result = ss -> string;
+	}
+	return result;
+}
+
 long StringsIndex_countItems (StringsIndex me, int iclass) {
 	long sum = 0;
-	for (long i = 1; i <= my numberOfElements; i ++) {
+	for (long i = 1; i <= my numberOfItems; i ++) {
 		if (my classIndex [i] == iclass) {
 			sum ++;
 		}
diff --git a/dwsys/Index.h b/dwsys/Index.h
index a9cefad..204ec56 100644
--- a/dwsys/Index.h
+++ b/dwsys/Index.h
@@ -2,7 +2,7 @@
 #define _Index_h_
 /* Index.h
  *
- * Copyright (C) 2005-2011 David Weenink
+ * Copyright (C) 2005-2011, 2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,13 +22,29 @@
 
 #include "Index_def.h"
 
+/*
+ * An Index is a summary of an array of strings. 
+ * It has two parts: 
+ * 1 an OrderedSet of the different strings that occur 
+ * 2 an item array with indexes in this OrderedSet
+ * Example:
+ * Suppose we have a Strings with 7 elements/items "u", "o", "a", "u", "u", "o", "a"
+ * The Index derived from this Strings will have 3 elements in its sorted set "a", "o" and "u"
+ * The item array with indices will have the following content: 3, 2, 1, 3, 3, 2, 1
+ */
 void Index_init (Index me, long numberOfElements);
 
 autoIndex Index_extractPart (Index me, long from, long to);
 
-autoStringsIndex StringsIndex_create (long numberOfElements);
+long Index_getClassIndexFromItemIndex (Index me, long itemIndex);
+
+autoStringsIndex StringsIndex_create (long numberOfItems);
+
+int StringsIndex_getClassIndexFromClassLabel (StringsIndex me, char32 *classLabel);
+
+const char32 *StringsIndex_getClassLabelFromClassIndex (StringsIndex me, long classNumber);
 
-int StringsIndex_getClass (StringsIndex me, char32 *classLabel);
+const char32 *StringsIndex_getItemLabelFromItemIndex (StringsIndex me, long itemNumber);
 
 long StringsIndex_countItems (StringsIndex me, int iclas);
 
diff --git a/dwsys/Index_def.h b/dwsys/Index_def.h
index 52c9e1c..49d52cb 100644
--- a/dwsys/Index_def.h
+++ b/dwsys/Index_def.h
@@ -25,8 +25,8 @@
 oo_DEFINE_CLASS (Index, Daata)
 
 	oo_AUTO_OBJECT (Ordered, 0, classes)
-	oo_LONG (numberOfElements)
-	oo_LONG_VECTOR (classIndex, numberOfElements)
+	oo_LONG (numberOfItems)
+	oo_LONG_VECTOR (classIndex, numberOfItems)
 
 	#if oo_DECLARING
 		void v_info ()
diff --git a/dwsys/Makefile b/dwsys/Makefile
index 2e71955..b6e35ce 100644
--- a/dwsys/Makefile
+++ b/dwsys/Makefile
@@ -3,7 +3,7 @@
 
 include ../makefile.defs
 
-CPPFLAGS =  -I ../stat -I ../num -I ../sys -I dwsys -I ../external/gsl -I ../kar
+CPPFLAGS =  -I ../stat -I ../num -I ../sys -I ../external/gsl -I ../kar
 
 all: libdwsys.a
 
diff --git a/dwsys/NUMstring.cpp b/dwsys/NUMstring.cpp
index 0f67c54..d1d871b 100644
--- a/dwsys/NUMstring.cpp
+++ b/dwsys/NUMstring.cpp
@@ -60,8 +60,8 @@ double *NUMstring_to_numbers (const char32 *s, long *p_numbers_found) {
 	}
 	autoNUMvector<double> numbers (1, numbers_found);
 	long inum = 1;
-	for (char32 *token = Melder_firstToken (s); token != 0; token = Melder_nextToken (), inum++) {
-		Interpreter_numericExpression (0, token, &numbers[inum]);
+	for (char32 *token = Melder_firstToken (s); token; token = Melder_nextToken (), inum++) {
+		Interpreter_numericExpression (0, token, & numbers [inum]);
 	}
 	if (p_numbers_found) {
 		*p_numbers_found = numbers_found;
@@ -71,25 +71,25 @@ double *NUMstring_to_numbers (const char32 *s, long *p_numbers_found) {
 
 void NUMstrings_copyElements (char32 **from, char32 **to, long lo, long hi) {
 	for (long i = lo; i <= hi; i++) {
-		Melder_free (to[i]);
-		if (from[i]) {
-			to[i] = Melder_dup (from[i]);
+		Melder_free (to [i]);
+		if (from [i]) {
+			to [i] = Melder_dup (from [i]);
 		}
 	}
 }
 
 void NUMstrings_free (char32 **s, long lo, long hi) {
-	if (s == NULL) {
+	if (! s) {
 		return;
 	}
 	for (long i = lo; i <= hi; i++) {
-		Melder_free (s[i]);
+		Melder_free (s [i]);
 	}
-	NUMvector_free<char32 *> (s, lo);
+	NUMvector_free <char32 *> (s, lo);
 }
 
 char32 **NUMstrings_copy (char32 **from, long lo, long hi) {
-	autoNUMvector<char32 *> to (lo, hi);
+	autoNUMvector <char32 *> to (lo, hi);
 	NUMstrings_copyElements (from, to.peek(), lo, hi);
 	return to.transfer();
 }
@@ -233,7 +233,7 @@ char32 *str_replace_regexp (const char32 *string, regexp *compiledSearchRE,
 	int gap_copied = 0;
 	int nchar, reverse = 0;
 	int errorType;
-	char32 prev_char = '\0';
+	char32 prev_char = U'\0';
 	const char32 *pos; 	/* current position in 'string' / start of current match */
 	const char32 *posp; /* end of previous match */
 	autostring32 buf;
diff --git a/dwsys/Permutation_and_Index.cpp b/dwsys/Permutation_and_Index.cpp
index 1e1b3bf..c1282da 100644
--- a/dwsys/Permutation_and_Index.cpp
+++ b/dwsys/Permutation_and_Index.cpp
@@ -28,13 +28,13 @@ autoPermutation Index_to_Permutation_permuteRandomly (Index me, int permuteWithi
 	try {
 		long numberOfClasses = my classes->size;
 
-		autoPermutation thee = Permutation_create (my numberOfElements);
+		autoPermutation thee = Permutation_create (my numberOfItems);
 		autoPermutation classes = Permutation_create (numberOfClasses);
 		Permutation_permuteRandomly_inline (classes.get(), 0, 0);
 		autoPermutation classesinv = Permutation_invert (classes.get());
 		autoNUMmatrix<long> indices (0, numberOfClasses, 1, 4);
 
-		for (long i = 1; i <= my numberOfElements; i++) {
+		for (long i = 1; i <= my numberOfItems; i++) {
 			indices[my classIndex[i]][2]++; /* col 2: number of elements in class */
 		}
 		/* Get some other indices ready */
@@ -44,7 +44,7 @@ autoPermutation Index_to_Permutation_permuteRandomly (Index me, int permuteWithi
 			indices[i][3] = indices[i - 1][3] + indices[i - 1][2]; /* col 3: index at start of class */
 		}
 
-		for (long i = 1; i <= my numberOfElements; i++) {
+		for (long i = 1; i <= my numberOfItems; i++) {
 			long klass = my classIndex[i];
 			long newindex = classesinv -> p[klass];
 			indices[newindex][4]++; /* col 4: number of elements processed for class */
diff --git a/dwtest/old_type.MelFilter b/dwtest/old_type.MelFilter
new file mode 100644
index 0000000..1c9a4fb
--- /dev/null
+++ b/dwtest/old_type.MelFilter
@@ -0,0 +1,29349 @@
+File type = "ooTextFile"
+Object class = "MelFilter 2"
+
+0
+3.8857142857142857
+772
+0.005
+0.0153571428571429
+0
+3900
+38
+100
+100
+41.79076424999626
+30.99288232722725
+36.01136594770968
+37.078790498359695
+28.704882360253748
+38.586435898771946
+34.18761895393881
+41.827199943723414
+40.55052450483839
+33.46503733163409
+42.81018946652721
+43.86072659281918
+40.494605445206886
+36.23575677875429
+46.278076729975425
+47.53358020031171
+42.20849848141493
+40.79269794864592
+36.20945952604096
+32.09331245598233
+36.29351218541332
+29.685580145129506
+34.513324528929914
+36.55840265340905
+31.922252848803367
+37.556813519102825
+42.817633862256784
+45.04450665937713
+39.13395780750231
+39.81761288075593
+43.43054931905196
+41.078565109133564
+40.10791306735496
+36.23480214892008
+46.24096931786034
+45.60328297503452
+48.864165524786635
+44.401006298741805
+48.17916992698392
+42.185258035682295
+32.65296155707924
+39.95538724144964
+39.31591078336359
+34.6686719085435
+41.10677635518164
+45.65640331275215
+46.451741027276
+43.89276244667466
+39.16300309315534
+38.21882781771579
+40.78755344260068
+42.0408055178928
+30.843822050906013
+43.51541115737196
+43.47017455486901
+52.561580180291564
+54.47138363585372
+57.33083487798209
+58.14169953064208
+60.05543311217571
+60.14093326523262
+61.37563171571218
+61.95454154060072
+63.20994283455055
+63.033249306295424
+63.93428645545304
+63.922432171196064
+64.4937119464729
+64.5380633556584
+64.67938018311972
+65.19285319474872
+65.08348255669429
+66.02823761821787
+65.31873519191227
+65.06264026455645
+64.88448786905715
+63.99225656076155
+64.22245678097205
+63.36035757604303
+63.84030372678676
+62.78285257752852
+62.06655491824713
+62.51804505408259
+60.747275446229054
+60.80406590038356
+59.81213762743903
+59.62090106143539
+59.22893800130197
+60.10363177541156
+59.46645028244033
+59.339382301864006
+59.51175344856607
+58.24638273329201
+58.88468118299454
+59.226996082118205
+57.334873531075466
+56.29441677918271
+55.61604756320889
+56.798394617127556
+56.59517850328416
+55.804699875668405
+54.099837599749804
+52.51721007753025
+54.72831166077245
+53.1122268467408
+55.588718961522616
+57.02373928827346
+53.32851711038662
+47.04112742771521
+41.068237596166895
+42.58553643004361
+37.620918309196966
+30.127230265090617
+38.8255558193503
+43.224126014200685
+45.88442618619115
+38.553581097883765
+35.4527102682693
+40.6408701293103
+33.24428313925199
+41.43396719867921
+45.76121483491332
+50.793109765793304
+46.82390651167425
+47.934565214998464
+54.527977155274904
+56.20649812926987
+56.03945792260343
+57.52195943536212
+57.567146060159956
+56.55784671295693
+56.14967253530404
+57.47706886015602
+56.065434994696076
+57.19796931145906
+58.28327370080467
+57.44361246737739
+57.62032900598237
+57.124878960515176
+57.60981823179745
+57.76788541170984
+57.62067640036098
+58.31826866691952
+57.920615198252364
+58.18643802248178
+57.68995083559045
+58.18198204844437
+57.50486586621854
+56.86624958870574
+56.68974299755492
+57.67163491314537
+57.04972069027376
+55.692941345910164
+52.09489623481142
+55.34293241398352
+53.0145308451226
+55.77228959315013
+53.11924222081667
+57.285511446531174
+52.75205070883845
+54.94676984310708
+51.44100065038691
+54.86923361427912
+53.30832689451922
+56.16164421625915
+53.67821506384037
+53.661140052545996
+54.28912960873062
+50.21146716540328
+50.9444143302411
+48.72072861122197
+45.43842977394604
+42.24927794314153
+39.13348111416187
+35.93249514355098
+43.021612036078054
+44.16549110531657
+44.28711776148069
+42.70343966438166
+42.455693528941175
+41.40517947117655
+35.61967797894151
+44.6491974316482
+41.62230277807062
+37.19771555101043
+41.27050240720877
+36.4104496223372
+44.45278530470004
+43.56481400698473
+44.18923303197251
+47.822271997594996
+48.644469414372715
+53.99048016499893
+54.08866165064934
+54.82904705203983
+55.86255044764932
+53.37079669429705
+54.03966477636881
+54.57195181345883
+54.78393619874493
+55.43764514427496
+54.38904573418798
+54.12337664645084
+53.4789230106842
+55.28087275801742
+54.094612175483384
+55.81520164493807
+55.063024275372804
+54.36457579206823
+54.663305839662
+53.95013821559681
+55.53858416287687
+54.63821091598665
+55.11705435774287
+54.28122693282967
+55.485963311138235
+54.76930272864642
+56.599106526255
+54.24635460593399
+54.47790035124291
+55.17583874419481
+56.50976617404265
+54.44855912443484
+56.05091237638763
+55.301173352353544
+56.31395197799814
+55.81314562407097
+57.236908281846745
+56.48446078818239
+56.58774603530205
+56.27603341730624
+56.85776424220518
+58.98919506769953
+55.90066834311129
+58.27300676573311
+57.683120286370816
+58.60227855591846
+58.64450778491227
+57.9732483376497
+57.6374992644393
+59.18059429684372
+59.206688555078216
+60.80485760442904
+60.349481995283824
+60.72258498840179
+62.11004450091163
+60.99472063594149
+61.753707781922735
+61.706067744720855
+62.75921455114464
+61.421456723166266
+63.74268626392714
+62.05215648694582
+61.824878736704015
+62.22086608708026
+59.85213028372799
+62.72075361103524
+59.14072475690092
+62.35752513995762
+59.72157408581002
+59.24188967224336
+60.23358471615494
+57.179131377253114
+61.7464294236783
+57.123728212564174
+63.56231650551631
+58.22844962033093
+60.66499909705777
+58.87609188960709
+61.05432669716857
+57.403641879955686
+61.163118952570215
+59.08621296175268
+60.401995710228306
+58.73417626231798
+60.72352434360282
+59.02033166393683
+57.472060823725634
+57.51588869827847
+55.60331382771396
+59.75578442989752
+58.17772851996443
+57.219293445425656
+58.48920830269019
+58.012042033042796
+54.79471280793177
+54.02806413580433
+52.55482300529762
+49.31151547383752
+40.09617650987094
+47.12143427067075
+49.38043877208362
+41.261315821918814
+44.85177295094386
+41.59741617748752
+38.80947587829971
+38.61153112567696
+30.512760671532746
+41.26764201744511
+40.69634660280255
+46.575202963954226
+48.09509616429307
+43.76178621198607
+45.913178858265155
+45.90665642632763
+41.40905490986429
+43.13017364440823
+40.30705499688199
+29.812524027720315
+37.85264568245315
+40.00307663752816
+36.916790140213905
+37.460162953332386
+44.06291190522248
+44.5019148424044
+36.73317880039012
+33.73598997428449
+31.389844625900977
+33.577857806705225
+41.56905326888273
+44.08955973330078
+46.474446004829716
+40.102378128072885
+31.08223623732607
+36.86567698182131
+38.214853171174354
+42.59480449307175
+38.950018576524265
+40.828899016183684
+42.11402354684671
+42.3449300195625
+34.61238050377587
+38.781960305642784
+44.90349291440806
+42.230074849651956
+41.051641730348535
+28.650874686505233
+38.7783224880868
+42.20133533789502
+36.419300748141225
+41.94877641304748
+45.423303584721694
+39.32266319349591
+38.094932893436265
+44.52830171945114
+43.737544925173765
+35.01048931769243
+37.99209295214669
+25.056665886235507
+40.666758719794174
+43.21781430896746
+34.36668645887069
+35.16314495255118
+37.77597551927647
+44.283955255169985
+40.537992206746765
+40.30077881601564
+40.2224929776225
+42.28772243164762
+34.83218814190232
+36.025772410507116
+42.30125287454724
+41.89694911633198
+36.15681696218459
+36.321797464498914
+36.91863314828997
+37.15366310033542
+32.18088555340867
+37.54029703570161
+39.33556120430111
+41.9820222481249
+31.226181348789922
+31.97417446009854
+28.473129317942366
+39.17504440350688
+43.41460317335196
+43.06252583780413
+42.6254166427753
+43.44649388510731
+43.84516406386668
+39.64191369484381
+40.01457327523382
+44.620332953143176
+44.401979048094105
+40.842502010238256
+40.19739043585633
+46.830105602870226
+48.04542951010736
+40.83437507990168
+43.452417307167664
+46.21638312293257
+47.94880861293916
+44.798803136425455
+39.257675385137176
+44.70458863199019
+47.41242301452286
+41.62376700857307
+33.180967091695365
+44.173115289688496
+47.69962611437357
+36.07366965508358
+40.173544107852535
+41.23439374355456
+42.91007675337423
+41.54681723451499
+41.42501928405167
+47.1677671380782
+46.01026046789769
+48.8999324030177
+35.51710193052753
+40.255577654125844
+45.58954650847823
+40.84852142377982
+30.598950428565146
+41.01468803416288
+45.41448278513243
+47.98212302963857
+45.493139251016906
+48.39279835784881
+37.53918111923697
+43.25738442805848
+39.66054060269539
+42.126524545943184
+45.75448029844636
+44.40289919065779
+46.31443699814601
+50.214745571106384
+49.29155612346248
+44.70742154804301
+44.235371816632615
+44.7579469580674
+49.54750856313517
+49.851486620641325
+43.229033383725564
+46.52080251883347
+49.92899892906344
+41.47431532019077
+40.03243761586069
+48.45028565721115
+48.5245406654885
+40.39391513162771
+43.19665946374392
+44.032301100324375
+47.84720210549996
+51.92177347046785
+43.59627284314505
+43.00902508526575
+38.10596309643723
+47.42769128672077
+39.7688631586179
+42.4464493853664
+43.659750683197856
+42.966341806670414
+41.84418488807404
+41.27508524029266
+44.00136565846154
+43.84002867251967
+46.631116409120125
+39.8805344368786
+39.67270149138544
+46.32994640850576
+44.5021013688839
+32.69080474109056
+37.328431151156764
+42.45568827113802
+50.54639285254497
+43.80996060833896
+41.74636149018298
+46.47212025151261
+40.63383429540296
+40.76810106294414
+42.83355966686943
+48.34153532181814
+44.233056153222584
+36.506364164349165
+38.61402146570462
+42.65839096133783
+46.40264719922237
+54.6066823643409
+54.49574626567639
+58.43242669771676
+59.42763391811613
+57.66444592619235
+59.76649610358222
+61.42252245809754
+60.968606234558415
+62.356759530409654
+63.08656892531706
+62.68807479763661
+62.40801180794859
+63.01797018974602
+62.08191317799994
+61.459661493042596
+61.18002724767035
+59.938211229188006
+60.39904490722781
+59.64764285178035
+55.43095993942582
+58.01249615440165
+55.31834660191833
+58.21598765644642
+56.50233029776783
+57.00709971389939
+57.25824944654254
+56.88335696523646
+57.51211218665571
+55.193316112011686
+58.25002584098459
+58.12953756735448
+58.47569813807435
+58.087219468141285
+55.3406597421975
+50.83552193058533
+46.615646839324455
+47.74303027083478
+51.385936101721796
+44.945527945100764
+46.24273775466948
+47.44148931325347
+42.390984637731535
+39.914755677286486
+36.500101894691824
+42.564363169433705
+42.382375361840744
+49.2231792747023
+45.54431459693527
+53.090588591493685
+48.51272333371156
+50.234845876689015
+56.04450816561139
+57.564874445922236
+56.91337426248748
+57.155213783959645
+59.22543031859048
+56.61291788193333
+59.50399289721703
+57.70657098903786
+58.78313405745034
+57.55027864456413
+59.20525914749355
+60.44529433784005
+59.85454906279207
+60.691629999423625
+61.351713061273465
+61.37546473898894
+60.94928828117327
+61.00085174796708
+62.726893601056204
+63.60227916502949
+62.43371124361737
+62.61085191559586
+63.04222771764363
+62.560950265017915
+63.19378949394004
+62.53290002315452
+61.70477409764774
+62.69693461521598
+58.65321227590355
+62.90177995186434
+59.07345876432101
+61.389654991495206
+60.36450429147196
+58.27422715008342
+62.229370786805234
+58.29313705573102
+62.758115154916084
+57.83096638790871
+62.16874604529671
+57.01499454382335
+61.95349833646574
+56.50174174690967
+60.25730956402923
+55.98116765931846
+59.32909189506462
+58.89743322270461
+62.01810732495008
+61.41705109459849
+62.65925525192435
+59.39253382218183
+59.25151955891742
+59.34749246495584
+56.77607289310366
+54.728115845926496
+57.25499195256709
+49.229642770859265
+49.24801759382836
+45.172600657724956
+42.885117934056105
+44.33571636033785
+33.39296610198015
+37.07669853911824
+45.507247137992145
+44.63620468497806
+41.024404563286204
+45.25883277254424
+43.07553023510833
+45.40351493323113
+46.57436990980595
+48.46529293285401
+46.52085699978811
+43.4204620269623
+47.41419786690648
+47.9437040192111
+47.85023984896599
+46.82965022527047
+43.02374375018253
+43.4365495703125
+45.835154844318055
+45.62716991937797
+40.915310793519694
+48.61758559730424
+47.918951735070664
+43.93453531271091
+43.68020063348243
+32.45806161492692
+36.15767722350205
+35.32108551873284
+38.09837249338261
+40.97396536332539
+44.17502107080527
+38.01764636409906
+32.098512844145546
+35.44348662885545
+36.888733134379535
+35.34916900751604
+43.18705108382505
+42.818304165547566
+42.830310375011734
+42.0113184123312
+39.08378971433573
+43.448242151619965
+40.36709520681178
+37.27925921761913
+39.14681296889418
+41.61263640307702
+43.338859835727945
+40.724926114946385
+37.13221076151031
+41.80255410098074
+40.512927100298995
+39.41900631621986
+38.205326738468464
+33.202475039422126
+32.011361715775166
+39.6432102906738
+40.98209933035285
+37.220464634583266
+44.25514256281651
+41.878837822067766
+36.60599611472986
+43.085782695360486
+44.634748922861384
+33.87385206483556
+37.88802282044988
+33.49820766404497
+44.01207497289863
+47.6875095697985
+36.2535565066179
+25.22809141386095
+37.46921539031061
+37.95500623591664
+42.701482207761146
+43.73429755722461
+44.01163037671187
+38.70293190889796
+35.56739592451699
+41.19693077269244
+40.686326286776065
+39.986176685653646
+30.605835781259543
+38.046916422195125
+39.30509694800314
+29.699782116668104
+41.50685450322405
+45.90475504044622
+46.59948514340084
+46.2155698149695
+40.05832909054957
+44.32888632325033
+43.435026022832425
+32.12001096006115
+40.77651359821972
+37.96822629957324
+36.37601381664635
+38.421659180362056
+33.381709780277134
+41.854472403164095
+42.71549524339595
+37.963443336594864
+43.584966099902786
+35.890581306178035
+41.69196804773561
+36.545811028448995
+32.304203066245634
+27.52482636235112
+37.995091223310595
+40.8807895058617
+44.550522225296824
+43.69485557067885
+44.47032004421343
+43.54956028830144
+41.04217968025678
+43.664871856270196
+45.31052735680494
+45.74849788126994
+41.54821667441529
+36.28144338894057
+46.634443970672905
+49.34328901968151
+44.632765064693366
+35.03308954269987
+35.27102566569911
+36.466295690890576
+34.421603211958455
+43.30655385958435
+45.35887027449656
+45.68000989236182
+37.521301998654835
+39.30531290827558
+45.7250391313751
+44.401327045619425
+43.211740504542846
+47.10275994750337
+44.15133636784542
+39.91265919210981
+44.30695694063497
+40.26830766589318
+41.50656437516375
+39.04185706368542
+42.785846763433995
+46.607219955580256
+38.171929225601694
+46.32022492893405
+43.26641244294228
+43.507136368138454
+47.10967488242791
+44.31869523148775
+45.84806318437619
+41.15594710836393
+33.3782644859684
+38.62621949344791
+46.903732374160306
+43.356391632871606
+40.901899276031465
+41.626090406483755
+39.865007415582994
+40.34322747332434
+37.342995763864664
+42.47136774892263
+42.20773624125824
+43.61707387864037
+37.8427659439443
+38.461801075454346
+37.20377626698179
+41.88662946320792
+42.12237180237619
+45.520258062252026
+35.88570737654206
+32.227020332131914
+35.33983174393863
+33.56028003879571
+38.104073025871855
+43.049220766290404
+40.183746465378526
+41.02860328815596
+39.25603501683769
+38.29462420664617
+39.919692904010226
+51.568270671803944
+50.01519826796096
+46.03355120449509
+35.51823881129074
+33.126031464200736
+37.37104912624612
+36.16452717825224
+30.985565642253817
+32.47052139036332
+40.00327913199313
+37.17922544652693
+35.52037407966726
+38.60211818565773
+34.27078710309881
+38.869085325733415
+33.438157098429485
+33.87563819523447
+37.58686128734628
+39.81135668628745
+38.52064370382776
+36.68394794413037
+30.797168247502867
+28.183491409708196
+36.85730487652788
+35.27327676399818
+34.95366611960392
+33.8050345039601
+33.33370620558911
+27.36861713229814
+32.688800191973044
+39.42872077004958
+40.286866046071864
+31.492264586927163
+38.974871948811746
+38.15066551698158
+35.51130744832959
+37.72143425258149
+32.21372416522108
+41.23469885196101
+33.82802045344599
+40.307879860769944
+37.7312673995773
+42.351068373586564
+40.710102517890846
+32.41959954319046
+30.086266251687732
+34.32711297255085
+33.08471545957437
+38.23811958830374
+36.461013282172246
+38.06688819114337
+34.22218112591918
+35.058622433898094
+32.62245204270167
+30.55418423614097
+37.567921735121764
+28.49132979841481
+46.55539326315887
+52.27976059132462
+58.952388963787904
+63.302472990380984
+65.89580349701487
+65.91186434785673
+65.25129654679091
+63.63563759612372
+67.60944898076426
+66.9710007187409
+68.03775041980822
+68.34865530311711
+69.52627614123449
+68.90810863051135
+69.39177209137073
+70.1208197862459
+70.05182364473185
+70.04521866419356
+70.84873663453295
+71.17971680799951
+70.79630366100479
+70.7052368108698
+70.76375575749714
+70.12139513517332
+69.95557858990709
+69.8897883954024
+69.86065316189503
+69.38396496214698
+69.34395148739566
+69.23558362509553
+68.46117287470906
+67.95411777332451
+67.60303022025181
+67.82938183833605
+68.18993473992387
+68.43917289527442
+68.77061134782086
+69.5076440097387
+69.92884736346898
+70.06859223504975
+70.66388162193141
+71.28766165846602
+70.94457351179543
+70.28594352770223
+70.17434846500132
+71.10048879495372
+71.58245848210856
+71.0136632503093
+69.76105100804759
+68.08434768941436
+65.00339050413785
+63.87422435403861
+68.05762271043596
+68.48826606297139
+64.64020724092475
+54.75420716833667
+50.79538499034716
+45.15697476360318
+47.718179917272266
+47.43565513289023
+50.20506128024861
+51.22939320351551
+50.24521458351979
+37.613692663567754
+32.10947306918172
+42.67036273746186
+42.02288531734757
+39.2812405134072
+42.77752101231682
+53.182538426362555
+52.59398806921473
+55.02343410734039
+64.6565074063027
+70.08856665002119
+71.80266724835239
+72.1960317253793
+71.78014358461702
+70.55343531200742
+69.53016866014099
+69.53762303934455
+69.93901065166287
+70.61189179884799
+71.33826206510855
+71.54068587798282
+71.52748014537558
+71.13640284058903
+70.94768482492209
+70.80370182321289
+70.7646195231174
+70.31593614502015
+68.05877894517916
+67.59164662532305
+68.93631293373267
+68.85935586752761
+67.45344627695275
+66.49725331988097
+66.94429113353999
+67.44957580901698
+66.9595061642662
+66.15138482028836
+66.50510273674823
+68.420613715586
+68.51512638740624
+69.1912759571617
+68.68322039810415
+69.17204200426694
+67.24932710833234
+67.21537105539902
+65.76096708638872
+66.93610336991364
+66.7056423797165
+68.15138494044436
+67.38218330167865
+67.43962587206566
+62.39897572387953
+59.764066564108155
+61.81938957641696
+60.57827504362633
+54.34781128094906
+50.25816156457043
+47.521814215906744
+38.1939435238463
+43.076545874400175
+40.94199838052226
+46.432277594197856
+44.262795907991816
+44.270187821422255
+39.43705351322213
+38.57595025153604
+40.380165000904064
+38.38837646323856
+34.4504630052251
+38.02140203603128
+38.610943627921365
+46.34279449594913
+50.295642615139705
+54.1389254139875
+60.39707615654831
+65.76216951027695
+68.20707115992893
+68.1805447172012
+66.88713446593472
+65.46084292887755
+65.49812851207932
+66.97709722059389
+67.63971964196499
+67.40568243315096
+67.29717623434888
+66.5028031672049
+66.28285363678876
+66.5068539207482
+67.23978662267062
+67.1828340134337
+67.35693859106298
+67.22873869884636
+67.20070903826368
+67.03926914775614
+66.95326923978288
+67.21341703809114
+66.96962769443901
+67.03484400332219
+66.66691889875095
+66.67444826760999
+66.75401387743383
+66.79788279961559
+65.97838128712422
+66.07639340142742
+66.24494877700585
+66.68831537865023
+66.10824475950591
+66.21479411952438
+66.21568884055934
+66.26879243602039
+66.24535267673203
+66.04775826877476
+66.33277363984817
+66.01849922191535
+65.22335014220258
+65.89829523212306
+65.5064333488829
+64.8843878689056
+65.93839256548937
+66.18159292742175
+65.91646623141926
+64.66541159147697
+64.84572356015468
+64.53699831495292
+64.09349833069427
+64.26608195583145
+66.89483182343709
+67.12348104814998
+64.93535835067124
+67.84947505124038
+67.35433112069907
+64.25595963249243
+67.34555093610965
+67.99423650118959
+64.53608925711353
+69.56840968020109
+66.30933549010639
+67.78066388124097
+68.61621287048035
+63.55074643884436
+69.03829471226379
+64.44394813566085
+70.0268961908512
+67.9807304541591
+69.32744079553422
+69.96663729949066
+67.9262462077427
+70.5926444330307
+67.04864325037339
+70.76359133884384
+66.20695907835004
+68.08193225792692
+61.00191945589024
+63.54333281348849
+57.38181598293521
+63.9665903994835
+62.82874252840755
+65.53935674752061
+62.43837020775542
+63.89109376898828
+60.29325817268969
+57.181277911301244
+59.99182426611655
+56.52204058946363
+60.76229582511544
+55.97015254133801
+58.16236055325724
+57.44410366194805
+56.961811722501295
+54.003534479324195
+54.8677456148623
+47.8161877676357
+44.870194399932856
+45.64777829511129
+46.71210752860654
+44.74376350688067
+45.32474503277108
+38.43221724607844
+34.02839246709695
+40.96881373119506
+38.77495895883041
+32.28852289624314
+39.606847292764535
+39.647546299896305
+40.82352608853645
+39.44046325550684
+39.81680385819376
+39.80687866095124
+36.687784853255664
+26.908733384661005
+33.828883295128875
+35.61809087109768
+33.869184703954446
+41.50620735027674
+38.34555605358448
+36.20679982808636
+36.25836772940822
+40.003853982272844
+39.161498162069485
+31.494665629417284
+36.751698237696885
+31.57883001953195
+33.160998225633136
+39.67359455688125
+39.38388014085095
+41.48739245414307
+32.40139975268396
+29.97103521620977
+30.436216699094402
+30.45573885466017
+39.35043158298117
+38.73885186654621
+39.8144818461587
+41.82222146524636
+37.428048424348624
+32.0026508194624
+32.71251127025319
+38.89965602604474
+38.81744664964403
+37.57109284689334
+28.168352664416545
+29.690815120232486
+34.060180076181126
+27.32031322144944
+40.66201137064295
+44.838618449268274
+42.13386436283025
+33.49028075413375
+41.397145963121055
+39.66026921039548
+34.407629276943055
+40.452628519490254
+33.328723753832634
+41.73078420650084
+41.67930022005429
+36.51814215649202
+38.3552378872208
+39.21844884765191
+38.87905395325198
+34.329316875969454
+38.33346746485232
+32.72420102935946
+34.749935421566974
+34.00879926292866
+34.11758626105521
+41.003225520426184
+40.32684042540195
+41.777934350235284
+40.55980330376735
+40.49006669046982
+39.46367484204565
+33.53486121009648
+32.54045722333784
+36.29654416617471
+40.971478979004644
+34.32397428403907
+30.69271358574143
+32.65923065507923
+36.57603547659117
+37.88924654566814
+41.83257009157434
+39.45232201005467
+36.2436107871345
+39.45812136020906
+32.78915454986961
+40.70913112917391
+41.901146337140844
+40.211462530247026
+38.09152158892853
+36.366225345633026
+43.45091092631553
+46.2837502111496
+38.14423620136997
+39.69721568770632
+39.9194992015769
+43.28180277565791
+41.58203034692818
+40.82741995337108
+41.65329652486519
+38.9752585043978
+40.202463561118904
+33.343852645157554
+39.662767798610915
+43.98205331491196
+39.65898134318734
+38.90456895940934
+37.33369580103509
+36.37115703663838
+41.68063396864379
+45.023048337475274
+45.30991375966344
+44.222194409472735
+46.59594398938049
+36.15413027195673
+35.682143122148446
+38.71327995093904
+36.73424623529861
+31.177050867924493
+35.2018719114226
+38.485820707737076
+45.77730799742069
+48.40050240453545
+48.80648860843805
+41.015577478680896
+40.61698124117884
+34.39856965347141
+41.39869920303311
+45.23723459135971
+41.44426761186527
+47.413240370798775
+49.79820532647364
+44.66455735036244
+35.088126342859
+40.158179948251124
+44.95439372263998
+47.10914855845225
+43.22343221798425
+42.36086168719454
+43.98552893306653
+47.87715154766691
+40.97933029970716
+42.549978800057474
+42.46292057599871
+43.76399479954121
+39.079083914556534
+43.009255035613776
+39.56472203636861
+43.55479187220427
+47.84866990946236
+36.307602722751355
+41.82533059205291
+38.81290594664707
+45.60277017698494
+39.59900847964495
+39.41064193528162
+43.745393948110106
+45.26810682277451
+42.96214775949351
+39.0124738072505
+37.74840574080666
+39.9640904960625
+39.89845153536241
+41.22329102539232
+37.77433335251821
+42.86706522598004
+41.62322730162502
+25.295000129291395
+37.51179740807421
+46.053202592626974
+49.07870326441413
+44.15170980044594
+41.842314181524586
+42.17937641910465
+38.91657858217779
+38.40673586205604
+38.31528283798815
+42.86742800760201
+41.29151472581611
+37.230230005557885
+36.3468040804986
+34.999208953830774
+51.217745760806174
+60.63202387151565
+64.48825488534985
+66.96057687474236
+63.38219660981617
+64.84001480989792
+65.31769021364296
+65.90240370355612
+67.10515024086894
+67.08147812253904
+68.22839922426303
+68.16492014619824
+67.95078561789188
+68.057493935898
+67.4042576513711
+67.16217047916801
+66.67399576326581
+66.04679317896532
+66.80214843823997
+66.55758031871223
+64.76755573689346
+65.58448243030112
+65.61559552234957
+66.63397513141048
+66.51012796608029
+66.82098505944231
+67.36374005122256
+66.86351578302575
+67.15908229489773
+65.17333272059787
+63.994549810586435
+66.75094241792635
+67.58311060847004
+65.07267133371131
+63.40334694920274
+61.358609665910585
+55.60904480845856
+45.181759627393674
+48.7808054212554
+53.78041972549421
+53.27811401812632
+51.29794144382845
+48.598083392336946
+46.348479985205046
+39.79460050497084
+40.00907444870001
+42.81258373601275
+47.552773261001846
+38.304069609325126
+52.77397347527317
+53.453892780129465
+61.91158515849072
+67.18029574887166
+67.12397131670565
+65.17696697033504
+67.77489119899458
+62.749779980241065
+67.51787429957042
+67.04187691249413
+63.83659636827936
+66.81610949131263
+63.27362624560956
+66.89077658839608
+65.56726539123684
+63.25634251645841
+68.68730441114312
+66.87789162099955
+64.34515964168796
+68.51950254209581
+67.2401019301856
+65.15707900769954
+69.80618835831783
+67.63638817901165
+67.96561181656031
+71.00580414328024
+65.72754411589253
+70.22271301785622
+68.5175266985976
+67.97358880682944
+70.35989980394748
+66.81341429430023
+71.46539968773709
+68.67825625999716
+71.55432481414272
+71.04503654272548
+70.52792908465187
+71.8922317952291
+68.95783958330907
+72.26242125439207
+69.15014716933624
+71.4852558531647
+67.74951867866926
+69.63440042245755
+65.13797474948288
+65.27991289342275
+56.58389929470246
+63.61838184348291
+57.56546446931575
+64.99442556402819
+61.251078947675296
+65.11253076390707
+57.84908070588931
+60.63922786284796
+58.23914630784722
+57.61877061532908
+53.07563032517573
+54.657406717562964
+48.344576827280534
+48.535826477571135
+43.49267965137406
+38.31378153838202
+43.499191101247774
+43.85496422646284
+40.77749699260113
+48.71688917877836
+43.26915278099335
+44.573338323609114
+43.138225786271626
+39.26306500410078
+45.59638112794441
+40.885877080416094
+37.40999994893835
+36.68634298144134
+37.45982640792721
+40.3536034050244
+35.6787033490473
+41.019972083010124
+41.29228500701004
+41.47905229046327
+39.71725649598091
+44.0808194849084
+35.266169775402986
+37.08973864906072
+46.27146956466226
+45.23485195101464
+37.885470980669965
+36.86550744271899
+34.497981130341984
+38.73590853881062
+34.515058382620666
+27.82390041316914
+35.34104187328482
+40.527159677778684
+40.09114743481818
+37.58048989459829
+36.7343707620643
+38.623172883689826
+36.71852797378128
+42.044812200801246
+38.46719362157585
+37.7681921470922
+41.15261069159068
+40.485143584097216
+43.95926326031004
+40.506078706859796
+35.73431783782209
+35.78722447201663
+39.418550462188335
+41.91939199346654
+41.22193870941075
+35.907090640551246
+40.98510019655547
+37.22989827017051
+38.51107784994723
+39.40571210557148
+37.92809523352207
+34.553820620352425
+38.79260026175549
+39.69460124796467
+40.9984674091138
+42.951370932028254
+42.44835134896309
+38.74246424798865
+34.690845974854014
+39.44190229692085
+27.502234788926486
+33.015777097762864
+32.351674737765094
+43.81723759289561
+42.890317355467424
+33.293535274806985
+26.398824588706162
+37.23333905323081
+37.581105745232406
+39.21621226414909
+40.77869353917549
+38.97995971405867
+38.5934528056148
+37.55488627242213
+39.270593868657784
+34.35027638717682
+35.721697582826124
+28.531824904518814
+36.027527181277975
+32.35107169688993
+30.604824788916517
+32.95361622264544
+37.48388529779232
+42.192451601651314
+41.894295349867214
+38.4055383373866
+43.056759488307726
+36.96543363241024
+30.43321404447269
+34.79195172595807
+28.748006738187954
+29.64996123451337
+35.288317609442245
+37.50439367442107
+36.77161960785152
+38.51697411847526
+37.97448914806565
+38.29302928609702
+36.32315647032178
+39.03499135316764
+37.21966407012205
+31.830519548032157
+31.219893124246312
+36.9628400336282
+30.223928220305098
+37.17501481231871
+39.414393494375354
+40.41912262458774
+39.59599993701945
+38.39753211970382
+41.333773868074914
+40.20027031699857
+36.5955086740733
+35.20710137357682
+32.74918658851533
+43.19558408927587
+46.17707948668658
+39.74023289124939
+30.669032133984544
+34.422856350945565
+29.07357280492448
+34.17000399146997
+36.582790886848045
+42.80314348014753
+42.32059309332095
+40.5169056210311
+36.0342682108285
+36.36477581049728
+33.84501600393418
+36.33121724114564
+36.82251353987358
+36.22528625278579
+33.634683482831065
+40.773252870171675
+34.673265364411876
+40.4398380389638
+41.034406876199114
+33.09860849434564
+39.476251641090535
+40.58344103345918
+39.26639200551053
+38.870327638843676
+40.35629054980637
+38.22618643034872
+37.66089127549338
+42.57198693108189
+35.7295861562023
+35.38600721825847
+36.74742235944825
+39.97375517429225
+32.19019765780071
+34.393724510541404
+40.169949902697965
+34.01036817576117
+36.68398386842482
+38.97341679192682
+33.543183953725574
+34.2444398993031
+37.33134698088429
+31.910561589090477
+31.666156346536496
+39.21375335637933
+37.32449585283675
+40.24419590254007
+41.35369924648936
+28.756527295251928
+26.852337562366145
+36.780531101185474
+35.14236524977085
+37.13414574604322
+36.10598082321749
+34.343414588465436
+35.22177819937842
+35.08410081246812
+40.63453309292025
+42.88697256854704
+47.219351819233914
+44.62405771863301
+41.17530168755678
+32.54118099559585
+37.244254485385994
+40.42102191999143
+32.57511813201948
+39.46112398414632
+42.36866108655128
+37.712550746193344
+42.06763916102725
+35.51295660852118
+34.73432135875652
+37.6880906578633
+41.086876946563905
+38.62139392783269
+32.30234770664549
+37.917692544006925
+36.60737578111532
+29.306586991513427
+31.89499282465907
+33.69361488028588
+38.11007349509092
+39.361708237491484
+35.06968005687183
+37.277892589973305
+32.59601207706963
+26.92975412307561
+26.245192617058166
+27.894957524082997
+28.40602892184654
+31.704148495789
+23.440547434691652
+38.80062806043365
+38.508259988085904
+34.64950843884337
+37.227628897670726
+29.34412974573928
+36.18677823544881
+32.98867589500992
+36.36068078722562
+38.84009056568053
+31.65564719865803
+35.51990197235067
+29.84316811228271
+28.810050111575876
+29.379365421573922
+33.488589768693316
+36.69766487050735
+31.41901834175094
+37.947133783121785
+37.68324305113921
+33.40691201943173
+28.083182148582182
+35.29513338190414
+34.905926469089366
+32.820237780321506
+47.11348217583785
+50.625115968298665
+57.07420236710499
+62.69831519446221
+64.63262707192581
+64.17647109237399
+65.56521734784923
+67.6236903896038
+68.88095630211659
+66.09875422440052
+64.91140208238446
+66.87650432350733
+69.37894196405551
+65.61482188403687
+65.57589778128906
+68.49171935508986
+67.37773927930789
+65.14403232602218
+68.5528714763213
+68.90974765387654
+66.71019881365675
+67.61667907510625
+69.27370125809097
+67.61330451957409
+65.92450222687059
+68.3558086811675
+68.44532863042755
+66.0194373522958
+66.56871516637509
+67.29856001111514
+66.09816084495094
+65.00771649203676
+64.83418658261147
+65.9803627658205
+67.94983417259654
+67.36756141280131
+67.4442839349831
+69.14185320094766
+70.13831119437015
+71.47105469538151
+72.30133174715189
+73.12009727953632
+73.49094574104615
+73.64422558943706
+73.97802322209702
+74.89736173777221
+75.43211014061976
+75.2381106436405
+74.4868633513428
+72.60983073771614
+66.572029852544
+64.29912838213652
+70.70625731588078
+71.13327994232148
+67.6027879738033
+61.09810243099298
+55.32835052173778
+43.269665689467715
+50.35935956142689
+52.724052151473884
+54.46461046380361
+55.5401288285212
+51.91536108956909
+43.83800024636947
+36.793876052930315
+42.305617740504545
+43.40628467462933
+40.96989827281001
+44.417601943349034
+54.640323040328425
+55.249230471076416
+57.58272617230626
+70.01846897521864
+75.80168316929331
+76.62226412398385
+76.04267689465473
+75.35168266962754
+73.24388179010019
+71.62348370756985
+71.27914150519136
+72.66536659570532
+73.17882355021486
+74.1917491630343
+74.44578317155487
+74.55189257264118
+73.82785014106429
+73.48800861153612
+73.14330723257177
+73.06311590724076
+72.23050969364246
+67.75567147488255
+66.5081725100398
+70.00306735175963
+69.56659583270519
+66.97702660063266
+65.25414440784704
+66.74950275390631
+67.50910479831671
+66.8038791400198
+66.13374103825115
+68.94888170799413
+72.12170457539254
+72.05298643709459
+73.15879764513127
+72.24351843165755
+72.81062685813737
+70.5507026317483
+70.53423714354246
+69.2498895643659
+70.43331938245781
+69.63449546823455
+71.87150229218685
+69.37467723785934
+72.25821800224236
+64.4466597132918
+60.70956108006908
+62.52317745437369
+64.27132681675707
+57.055966151642494
+57.20590756751737
+53.22040259151859
+45.28967537295957
+44.82469884877618
+46.76374994307665
+46.98093346448241
+48.452508846233755
+47.369142143637106
+42.27855590138889
+38.69921636959335
+36.23635152118361
+39.864649468690416
+36.61315640525693
+42.84065516003896
+46.66591515238024
+53.005604994844255
+53.733782197421235
+55.774303812141234
+64.52804181898964
+71.95486365042287
+72.41219891360257
+71.47638268825249
+69.36393563929222
+65.96806997598108
+67.08937070073071
+69.68783364904047
+70.21674443004328
+69.45034287710338
+69.42466302208163
+67.87441086114092
+67.5338478730751
+68.02016464725398
+68.84495628803799
+68.97120590287795
+69.05668976822689
+69.1555233155982
+69.0828235662692
+68.90368497991442
+69.13389683218018
+69.15631682268389
+69.21537220633587
+68.78730735208042
+68.35827775310722
+68.06647386355678
+67.93105684706556
+67.2660071223435
+66.66035689687367
+66.72068689931002
+67.62034766927955
+68.15127347293824
+68.36345377819069
+68.19309364932096
+67.82566628711899
+67.1303122910727
+66.6497906713359
+67.20488914093434
+68.256345428882
+69.6632165186873
+68.34583894331158
+67.84862411613756
+66.87999643261082
+67.54633773516863
+69.75883107574992
+70.67927028280921
+69.09604712539746
+69.23832762850414
+70.70733988767742
+71.24929936683216
+71.7154991893018
+71.4495013597365
+72.8252842925181
+73.15590746931696
+72.2360431712708
+73.90271826839528
+73.95467116955123
+72.92425312766989
+72.97764937906095
+72.15280480945647
+71.67086127656191
+74.97642464138988
+74.3495331112167
+75.29282497727776
+73.81094706309707
+72.2635495116605
+73.01200608851886
+72.70520565963363
+75.74447424878504
+74.00252079286767
+76.38526551276925
+74.89489891312941
+75.23808597518835
+73.90104140698503
+74.50464508611745
+72.97946846334094
+73.81896953703269
+69.3001918554473
+68.16039021733867
+60.52920132132291
+61.50472732429673
+62.04300156061497
+67.56036396929926
+65.77317896791273
+64.41529395300343
+64.67660140762949
+58.08503830286929
+53.225249642223446
+58.35871070317046
+59.20141688956005
+61.14243359574227
+50.43130600891667
+56.58024129350417
+53.672283614589894
+47.34968607545016
+47.97805397102421
+50.979689294424546
+44.534804499063355
+48.33509820402506
+49.517137420861054
+39.80108307804122
+41.373669107567636
+44.38636862563435
+41.07152310708317
+28.805523944158878
+42.2662549205178
+37.84646239735087
+39.83408450427143
+43.869024246816885
+41.65535997243964
+32.60672442249114
+32.59110321963492
+39.91986302329315
+32.03570658789266
+37.328141076847615
+34.9498501367886
+31.525753896297644
+36.06726267437996
+41.410634453255554
+39.44840882412476
+36.83390865265268
+32.55094977623433
+33.426349055527965
+40.14155456974182
+41.27374944282033
+37.663720455585114
+41.184436339651754
+37.47536758684991
+28.8692139093547
+34.019144148673746
+34.10516827622391
+32.583660012946396
+29.684349083773085
+32.365058126288474
+20.921889893166323
+31.476330726456283
+35.48802338382731
+30.6823418488176
+31.594824171980235
+41.22288585360799
+37.0386013514848
+28.997159922541712
+33.5396451909164
+37.20404785074861
+31.80086589262899
+35.97986775546889
+32.84465770825565
+26.798257835278363
+33.11709162031728
+26.895435508040052
+37.13667129444036
+38.99102278742115
+36.26559786713152
+33.499407348261954
+33.73425085069151
+33.161356652183386
+33.18411527836575
+41.87232510488013
+36.37103973185971
+39.57909399432132
+35.7943634918432
+32.28916282987956
+33.99988267432306
+34.711323447257044
+34.59947269994821
+34.82712009453762
+37.59817067177108
+35.7526886754966
+28.181630843225093
+32.31554746460691
+30.15135981861677
+37.321621170319034
+34.43538358392023
+39.77092263438139
+36.18253258897347
+37.66848970928997
+38.7352012172659
+32.43057782524561
+34.322683604813605
+34.99845871939894
+34.41749140856375
+34.86162804214648
+24.91995321742344
+34.0394710431889
+33.90868337830641
+35.57636575309964
+38.66785774438189
+35.77977142737382
+32.722332112460904
+30.561173454527264
+29.81435111906964
+33.556649865900496
+34.55882550793977
+34.93744405982402
+32.6454723467681
+32.28342060104542
+37.57960727785011
+37.13451853864693
+33.91386503577638
+41.115525777594634
+34.55125101337977
+33.627948655354984
+31.71878749171148
+37.303238926644696
+34.43277770756626
+33.463593342587615
+36.84494280746297
+32.28739483159515
+32.48484426980103
+36.98251768871428
+33.92938540957523
+34.07554970040967
+40.404419423930634
+38.760802945434826
+35.89479453961734
+41.8672062125935
+37.45239896486512
+36.36024419456447
+41.97885619849282
+33.83092480855531
+35.61762639418181
+34.89553801395675
+33.37794493235137
+36.61191258752825
+34.18216061067055
+33.57419042577132
+42.42421111305548
+40.79583030042689
+42.834394105798225
+41.24689357281093
+36.53248255574238
+36.20939042841293
+39.987296465036096
+40.23172490573765
+40.863086588888166
+39.25754006514771
+43.881463978038354
+31.581219495616793
+32.91121375122995
+28.180799071110684
+37.23027838694411
+37.34410765844797
+36.33520050437632
+41.0416253077677
+41.78741806056746
+38.15755388108217
+39.73985788396251
+43.019161882109344
+32.738404118451214
+35.679528120458244
+38.776775325816345
+40.26589637854265
+25.69830431415437
+38.296723955787016
+43.27328175079924
+35.34636700881383
+40.50861948498897
+39.497491654867765
+40.68041687036458
+37.58193804443699
+35.24612121806409
+39.54200084899367
+38.551027386783346
+42.99645037851177
+37.48182557199014
+31.584429785776152
+34.15847621896914
+36.052522290625575
+37.212779757941135
+32.73897085739979
+37.88121531645817
+36.29500105874783
+31.506396399813568
+34.15517652053383
+42.64983168684711
+41.605967592964745
+35.93380356299015
+31.737001044319868
+32.430297630344
+34.89431648988615
+34.52929025296382
+37.89115999718947
+34.93169607429191
+38.10691050627546
+39.04668303326019
+39.764278546312
+41.20968038157288
+51.2598044920133
+58.79142455987747
+64.50675594997222
+66.90832334015306
+63.2642145407946
+65.75348581323814
+60.71562001907734
+60.30732297596778
+65.1543716417274
+62.665867794452595
+63.56184456153476
+64.68847474675474
+64.9465009746865
+63.742235828942476
+63.32963642097481
+64.99622518381646
+63.82340310783071
+62.412115246161974
+65.5366260495569
+66.79140410581516
+65.19224247980264
+64.04333509110354
+65.36014583787463
+67.50029919416528
+68.75045284569217
+68.0544719805672
+67.97144866189072
+66.95934542793344
+67.62932709948112
+68.38325663978051
+60.03652995613059
+65.937804454036
+67.50188977210524
+62.15459275527889
+62.14308288583033
+62.290519864577334
+56.905922126651255
+44.44465423619923
+48.198915260429644
+52.94183257818149
+52.28366787129967
+47.1875191603185
+48.176864293938756
+47.60873584318472
+41.90030469052792
+40.969036596105454
+41.99287332141246
+46.081052999005884
+45.12235914430966
+56.909983394780184
+54.13456267331942
+64.29230789257336
+69.81215146582319
+68.30409167064798
+64.04301360174689
+70.14832884963354
+70.36392247385174
+71.49448472786979
+69.85866020035752
+71.92285958921536
+68.59016306393521
+71.67811831056413
+74.32141554841549
+70.42421988407729
+72.90278780501077
+75.76038796428726
+74.61485341012272
+75.05165000739113
+76.75640498099943
+76.03345081651317
+74.0462030844237
+75.2654663039106
+75.56315655223783
+77.19376346761769
+78.00890029721194
+76.53749439513513
+76.2553374569328
+74.87277882915883
+75.00507493764323
+75.65581266467183
+75.90794697692209
+77.04977211823393
+77.20709708801384
+77.9599504968954
+77.3274322427262
+77.56819078165712
+76.65764063924388
+75.94900145778836
+75.8356842443319
+76.3287581305419
+74.93991355823337
+74.36755569757304
+71.67501272665201
+71.87619025050871
+66.19479271084299
+60.283804495045864
+61.354972792992434
+62.85658700748454
+61.25184338687575
+65.38167645171872
+64.59692254090962
+57.45015233658743
+60.74402407774501
+54.58486449705859
+53.40335703220489
+53.80136411508192
+52.48725430721476
+45.960986123687334
+46.69007391667115
+42.8509359473086
+41.89296977926114
+44.11926847466174
+47.291416550818376
+49.23282452466021
+52.19747053169354
+47.42034884588425
+44.341039137998216
+44.218911323911755
+43.77004283664826
+46.58310216323375
+44.20048189143115
+41.21931755246744
+39.38355918786835
+42.239244920574826
+39.94606214591863
+35.11762497980129
+30.69424444725756
+32.17721158959188
+34.59756196981276
+34.15999217862837
+36.28903855853723
+35.88079822065052
+29.338269866372144
+42.294863170019596
+38.729338406793865
+36.18263650509354
+34.50800549910832
+35.670841195046435
+38.18485305922525
+35.58600842589057
+32.28705398307679
+26.12755953489058
+33.09472533422024
+38.30607018554812
+34.72254265100176
+32.628841458020304
+39.46842623035246
+40.46710444985504
+39.4157258527246
+32.246124217549195
+36.353254794146395
+37.60232152371379
+34.95738269431992
+38.188146294040976
+35.456439202870115
+36.41978449117002
+36.71526838383309
+37.13912839864712
+30.776174617895364
+38.97001267476132
+31.602574484962688
+37.65752744612368
+40.87961841239114
+39.77836567421319
+39.92815955910546
+33.57586684648105
+33.3980909150322
+32.18955665341109
+30.19504108472674
+36.67760233450893
+33.90845818127893
+35.12449867360829
+33.091276222700444
+33.94780501236859
+37.47042238384215
+29.958719796111154
+24.38104789815182
+26.475161230813427
+39.882963532035724
+38.66807366286167
+34.039635276826544
+33.48362830115316
+37.649278361273936
+30.534727253144396
+28.7950759057441
+36.34720453755341
+38.26995182375134
+37.84402890087499
+38.679849656243775
+36.62507320033809
+31.216428597078774
+35.0376181736129
+33.84398101592666
+35.374291804791184
+38.29805519756204
+39.07251277846344
+32.07075451583172
+29.15932717272335
+34.91669987707333
+34.53073026881512
+33.170675320081955
+38.88608149615729
+25.07333478605827
+33.05214830531101
+32.34730007316166
+29.184501226387297
+31.33990999508036
+31.425611486649387
+37.43844403345127
+29.990793335109103
+35.92206444882808
+32.937598739304235
+33.270290616148614
+37.37650411464405
+33.79139206541659
+38.68657748255583
+36.70730263006472
+29.221777359513467
+36.842191032622665
+33.57405262204419
+31.92349299828031
+35.99478566734264
+39.7171187603719
+36.52228072979683
+39.268307873454496
+40.371303189627824
+33.15065134855793
+31.6188770640876
+37.27211063667946
+30.348600360574935
+36.051833100956756
+39.07433865789481
+30.57148827772167
+34.89005425041975
+35.887448422456515
+22.855000054417175
+33.99502083508659
+26.923189793354553
+37.097396465405424
+32.3367284301722
+35.95545565160715
+31.34090647012424
+33.653656836307675
+31.180952788584293
+28.264978486111616
+35.7031753542697
+39.24688415225533
+27.78456605905751
+37.08796355247458
+35.67007666163208
+33.78545052136887
+38.50000194055775
+29.652627055622276
+30.358428429089884
+36.66009546890497
+41.199407577199224
+36.23066008085014
+40.66031796310336
+28.92194425551739
+33.034383199262294
+32.17411535894513
+27.292520406929142
+38.795232197621964
+40.36125447009897
+35.341479906950056
+30.569545271706602
+28.045795834089432
+34.3298057597421
+34.79016138559241
+36.071467085095236
+37.144329262170544
+35.41110988483835
+33.845569974338105
+35.375004319310904
+36.473296563620934
+32.858289726849165
+40.36388416645465
+33.374033747973044
+33.851948153421475
+37.71124213753898
+24.2141646852845
+29.314481159376015
+33.86751826319336
+31.686264232558074
+30.87950497043238
+31.956892719373087
+30.16681584194302
+33.03392865709634
+37.09026509629237
+39.42244794016706
+38.32853792900562
+38.91639229545012
+35.79173962112537
+32.52993592688129
+36.69905353233186
+34.12436855808268
+40.46461935492482
+33.37042617200302
+40.09019698939911
+43.57182929639033
+38.963500497825365
+42.99302020134258
+37.282717413287315
+40.60897640841833
+37.57377813394867
+39.17446580457993
+37.115364411916985
+25.881567242177667
+34.01775087560638
+33.44873370245368
+29.680753240908203
+37.245900499900856
+36.85460509873154
+39.828437529403566
+34.46010462283614
+35.210832780095316
+35.543631769111926
+29.80963617774148
+30.384645385210433
+31.51562469461537
+31.640270978204327
+24.536146197516544
+24.2344077201938
+24.674996564084267
+37.401369561023095
+39.70974883878151
+31.527596006854992
+34.271614918099544
+30.850125667602654
+31.648013066161
+35.79314209670227
+37.05852407314954
+36.89655183729438
+30.733039938168318
+30.14312324214569
+27.86725405950149
+26.662557627473404
+30.85300134760608
+36.69882929752903
+36.69870385056025
+31.8637754037981
+34.29045900497697
+34.32984164456023
+22.906648791057236
+33.508049145049625
+39.124160964751105
+35.8785976375473
+35.082304187929296
+41.2892233893148
+43.04497298380913
+51.768322961255016
+57.100718504247105
+58.130268700949685
+61.80167591592934
+65.68759820564543
+66.7862921003906
+67.72215224131381
+66.70419257210042
+65.9736356384503
+67.57511643048366
+68.3593851540476
+66.77193009243233
+66.02309801202087
+66.70843581877959
+66.18644839751167
+65.5567512025211
+66.55593285747872
+67.12982584222358
+66.45280016708054
+67.10557618239557
+67.90545000037916
+67.1947256930651
+66.5430103851848
+67.72406370752542
+67.56130627668492
+65.81522922311063
+64.36405309982312
+63.56174745600879
+61.46136273621078
+59.140199517160795
+59.47984380045166
+62.823381638407106
+65.99694150100521
+66.69735723256707
+67.43830372742462
+67.39714227342824
+66.8644120037624
+69.84380826843466
+69.805452836259
+68.8419974177673
+69.5002112552022
+67.59194633061223
+68.76219916011425
+68.94689491516417
+68.85409984950634
+68.85549897816631
+69.00739133229683
+67.6783591139735
+61.24183477177039
+59.986281167087704
+63.20033387303157
+63.498707540258565
+60.13007003618303
+55.17189643689145
+51.33499973398145
+41.16822397522397
+45.57746927237565
+48.62753016338252
+49.90613490926995
+51.13320586102903
+45.22523108847224
+39.27578181485905
+35.42649222380774
+38.68105585964848
+40.40945237504632
+39.368496724508105
+37.185490533194
+50.934099236752196
+51.81023169773643
+50.050744325783846
+66.3128923425804
+71.82737591036832
+70.67669477487844
+68.80948550580317
+68.66334750453242
+65.30345075103902
+64.1721763980706
+63.90026808006929
+65.56938757792689
+65.05788407899075
+66.57021464602484
+66.28591107394668
+66.60986141100089
+65.55210039897841
+65.1670492111542
+64.72851573105682
+64.6738457305494
+64.26824027204933
+61.584528517656935
+55.34880432595925
+60.76508957626076
+60.11824718620356
+55.809320112376284
+50.68908825412181
+55.05547775906775
+55.964762771893376
+54.877324574774185
+54.10137735540596
+60.2865150459906
+67.61859973914831
+65.8242204115798
+69.43062086027722
+70.76241586970994
+71.30473296665934
+72.55734561221504
+68.32473629290394
+72.6046640079024
+68.3595628235966
+72.63576429279459
+68.6677960176899
+71.39458869107317
+68.94137996490326
+65.74591515175139
+55.60156693033801
+54.70946406323909
+60.01906964626988
+55.06633940505542
+56.47700987718208
+52.66667354802534
+52.26717865423758
+46.17077157919389
+50.880969854403375
+42.33706214494116
+48.66597679689898
+46.62626426880976
+43.07015184391658
+46.03391274500398
+42.934148730843
+41.30814868372072
+42.36979611984434
+49.11521753402494
+47.602224262672244
+52.077201739971414
+50.92514400487464
+52.312013650262074
+57.6578597909441
+69.36805008864113
+68.33675291681811
+71.13219193983778
+73.23673409001302
+73.81986162195216
+73.37455479122639
+72.86134153670469
+72.57112957306411
+72.1055387663398
+71.65046494224623
+71.19151523668074
+70.80348577306532
+70.90766913459376
+70.41183680678213
+70.42080726517239
+70.89243718545049
+71.30472076361544
+71.39051033037384
+71.6838589861682
+71.95552919199869
+72.17702954368502
+72.68209125235224
+72.3689238479539
+72.50012351995834
+72.7690251813616
+72.66072340208483
+73.0730264311006
+73.49257526391008
+74.12723281442419
+74.83058515161561
+75.04715296689784
+75.73722259734862
+75.94828474063935
+76.01890259425778
+76.37717938758414
+76.9783048691547
+77.86712633289382
+77.12330147202714
+77.09498950196085
+75.94569876504997
+75.5866929942101
+76.20620317605247
+75.77377836373881
+76.15334679389889
+76.46233007047661
+76.22411167011289
+75.52723419482047
+75.0249970396654
+75.48977884297219
+76.14536171212644
+76.17124461347251
+75.14241928892527
+75.39719320370106
+75.88516736278645
+75.13861353153766
+75.16382364636813
+75.86895696591209
+73.28836703562932
+70.03414368113467
+72.12213621875202
+74.08248820592539
+73.2559980010984
+75.33007703595628
+69.93237557722259
+72.16171693151313
+70.72144699549527
+69.92547261696947
+74.78648412664492
+69.65876220416615
+75.26044875843644
+68.65459204661514
+73.02141992029615
+66.92789725701971
+72.6161854117818
+66.51819379967532
+72.30374461233274
+62.05793495029325
+67.23380256061063
+62.953934826552846
+62.90171796723073
+58.98449940600564
+64.34024937380082
+56.92952196493086
+57.89951089562139
+57.537491931866946
+54.25371502360143
+52.912701556383055
+52.58769756940177
+53.695557016434414
+59.05458236814456
+55.397262386544575
+53.962382837312845
+52.06090072200442
+45.43574862091127
+45.96905948136905
+45.31078691478281
+48.03773278770758
+48.50318976966079
+48.43438734705309
+42.04769909698943
+42.06511903896319
+37.53069257711419
+37.629984524850144
+39.420270247923526
+44.29833930257195
+35.64827773648216
+38.94860686912933
+40.80292798013801
+37.89769525261059
+32.99385063355267
+36.14000217984206
+38.37711997245978
+35.21227154977147
+35.76485031123522
+35.50686178253274
+37.42048656820849
+38.01797957837172
+38.68606494377074
+37.91118526079775
+38.005211614204285
+38.32660224915261
+35.96372640886983
+32.70070951422346
+37.78684550210797
+36.98312175656251
+40.856641343259696
+40.21490528984124
+34.62364972373096
+33.05335467119666
+36.726095298708415
+32.891698149744755
+34.56905415962805
+35.54478536838232
+23.872768457904627
+32.06934628500265
+35.432014178481296
+21.820932526278284
+32.476777566994556
+36.892914371581796
+34.18324689811199
+24.65361697012139
+33.33619700200582
+35.466392168923775
+31.452171521849365
+37.21999548488445
+35.44450170944616
+29.30132565576264
+33.99161384293919
+33.25576457260077
+34.60564191515782
+37.72668504512437
+32.68721762153346
+33.81541372717042
+32.55497155929817
+35.355847097083895
+31.902147339129343
+37.83850841315815
+34.273514226844455
+38.15698994901033
+36.285932744275314
+32.38803207872279
+29.691240750904157
+27.28112074313431
+35.95233951811973
+30.974202573097003
+35.06659050321365
+34.68095496341799
+22.246781117519348
+31.63557868304254
+33.27149894437585
+36.790635367322835
+35.693747351614874
+33.261055109745584
+32.09066264555716
+28.22687612233767
+31.712370878401103
+33.526457280962276
+35.73101970327315
+36.98058843980456
+34.02062346270296
+33.098558069988556
+26.45436018528335
+34.11667591548604
+33.35244716884415
+27.004786240127984
+33.69941052888976
+32.99057821749767
+32.14350684661957
+26.72430521369121
+25.8517282849333
+30.347880201545223
+36.6664880583446
+35.51784995783949
+33.46344283019957
+33.14450760286229
+33.14465677451146
+30.602955509161816
+34.46815205626025
+38.37979982386665
+35.66921230672271
+26.272474396073818
+27.570577493497368
+35.40015572176843
+32.41877806670513
+33.41089581835824
+34.716253198171685
+34.4222239283378
+28.34101569557427
+34.7797903398192
+29.02136096646626
+34.3258500777347
+39.00437237449883
+37.75878862272479
+33.9065315362776
+31.06913405430707
+37.2541118182138
+38.29092729042988
+36.46637608949065
+28.741342702556594
+26.627063045644107
+30.01083505751879
+30.245837560283917
+32.72324420025707
+27.54756142241139
+33.60789907791245
+38.71162817537422
+35.29492829488328
+31.760532003524702
+37.053492609670016
+35.62817077637679
+31.89356400994967
+37.98232082535579
+35.955824567940766
+29.376383062856604
+32.65366606053253
+36.45202533027401
+31.7520067138081
+28.05529437560294
+27.205931228897867
+24.448550243038355
+28.887340711802096
+34.069493100935745
+35.987233189638445
+35.16857664895531
+20.944226958470423
+32.543248689024125
+39.8390776061652
+36.41840161108708
+27.13339662928837
+34.33499614502695
+37.129561405452634
+33.27836683155917
+33.40784727672997
+37.12878088345154
+36.299712303092505
+37.98362652578952
+37.5481482337779
+28.265568958062104
+32.24342546696229
+34.336303046354146
+30.542213080382226
+36.8540194440788
+39.356411595431645
+34.955590002412436
+28.409736402077584
+30.122994670658002
+38.76728640919699
+39.14693173862921
+36.095167665057716
+34.015030079101905
+28.49159561738898
+34.16331010764151
+38.14488427167677
+40.44805842626769
+39.107450827785556
+37.59520608732372
+31.96181876926684
+23.149466911616585
+35.205110166912306
+36.65703441253129
+37.980299463548334
+34.275389914151404
+31.51593088440235
+35.03944513531668
+39.8110555225833
+40.9815447278914
+40.868760651803
+46.56082336412125
+55.947324713054385
+56.927583193241446
+63.309216578642406
+63.63393833599511
+59.293833587236826
+59.48571122511469
+61.4696881351169
+59.351003382469926
+57.97617557552068
+60.01858517034508
+60.978166644345094
+61.000280727596376
+61.27340643784569
+62.52012790482924
+62.93878324747905
+64.08534881781185
+66.60506856748344
+68.47416871603836
+69.34216968613418
+69.66702428102005
+71.08993326576265
+73.36293636587283
+75.00675660304447
+75.42872454079578
+75.88808220749779
+76.76443094700994
+76.29219477199787
+75.27110193066738
+67.27262185231574
+59.33316762628232
+60.28864876894985
+55.730295012999335
+54.01806352571552
+56.834624728431876
+54.84199590791625
+52.86970867805659
+53.96501082413117
+49.565819071595875
+48.455472220271844
+43.06709184387887
+47.63962808331645
+46.98616300484206
+40.75949222690501
+39.10273470718042
+38.955305458268846
+40.045691055876986
+43.659710520387016
+57.62953900690411
+55.23235769809392
+58.337179682902985
+66.84056913144266
+67.32027078617574
+68.87664934678531
+66.86888004245168
+73.59566592151896
+72.46942606644018
+72.06343654344433
+74.95495269507059
+73.99983960545201
+75.60182585010044
+76.65498132739518
+76.03554675034717
+76.76007959453736
+77.35310136749068
+77.26246442035425
+77.55319009310503
+77.59299055850761
+76.82446990996633
+74.89325432766668
+73.37035531671944
+75.00395935834491
+77.16728927758544
+76.40980069654455
+75.64439962018403
+73.37149953720734
+70.95049233050578
+72.28607005440496
+70.98513425155309
+73.1456594891817
+72.8797360878012
+73.62267286412617
+74.33500355897948
+71.9849070620082
+74.10866133680082
+70.40142906642933
+71.80728068131877
+68.06349166972902
+72.93931942129302
+67.01593161036791
+71.09223028983641
+63.4519380079536
+69.59142155056168
+64.13011540988
+60.464334248611664
+56.64181900236345
+61.43650709983251
+54.84675541061711
+62.702290438790435
+56.974158200395934
+52.430724906220284
+59.45509258439406
+51.66347579699939
+49.83483218611584
+55.50599956772748
+50.417671269608775
+43.64388076251218
+44.73783987969976
+42.081771648231125
+35.87069368688563
+41.381374276049385
+43.712369512914286
+45.627943064348614
+47.72460289355649
+46.4246403877557
+39.15677030943648
+41.414331214463516
+40.96661686952909
+41.65288146862383
+39.47779170160748
+39.76652320506718
+34.33718071713774
+41.14447273568999
+31.842904229342082
+32.23983313304336
+27.01472203130146
+34.58211101882078
+32.98611028593923
+36.00163773113485
+34.60667788111455
+31.499443718317465
+27.09416238485585
+36.469276629603684
+39.511837846031526
+31.679437464027103
+37.25205416871958
+39.314675542092345
+34.48807024738471
+32.37855393518544
+32.19770980857707
+32.159225215219394
+36.787481852298924
+39.23089605214737
+34.26175812986676
+24.708199374666137
+38.1166467019883
+41.166825307423686
+35.96494993389443
+30.23755648565883
+29.678872190455976
+31.569226487354996
+34.95950127021605
+35.552526742246854
+37.29302956709516
+36.182484773297645
+37.56767624000874
+36.597317223120385
+23.225551151158513
+35.62119869386696
+35.342886072946385
+37.38379216321796
+39.27740477346182
+33.08441147030476
+33.80431381629914
+33.541425766564004
+35.973832028170946
+30.540762318587696
+29.53862640963031
+32.98441958822555
+27.77527799839919
+29.40063062097434
+35.69018158842404
+37.03222270584955
+36.94495465722781
+29.802028138441898
+24.830889239169352
+20.66454402613124
+34.7784276090339
+37.717843371144184
+31.75280260593418
+31.408992155586247
+35.71671210123
+30.08827763496329
+31.086106092428764
+37.313561493150445
+38.24219116406552
+31.494348717004385
+37.14300998984264
+35.38495570637993
+33.06292184894998
+37.54812318086818
+37.0028150436673
+34.999023722359055
+38.9966901400801
+37.89298130707761
+32.37282548202667
+25.101042503214373
+31.007906371339587
+33.591445943190266
+36.208816550882716
+37.0372179575556
+28.30583613586073
+32.13705473614844
+35.72281076487337
+33.729595079980484
+30.84010744858088
+35.754937762778354
+34.9084803303013
+24.607798966887273
+36.02842148035364
+30.438273914371308
+33.374347972130465
+37.46832418519643
+34.398903574085125
+37.465760237474555
+36.59432689979981
+26.70133506921009
+35.51208538078147
+35.18210434337986
+33.55024714140815
+37.25388868884306
+40.386569674419945
+34.346877717122254
+38.35134471463426
+38.39368567292374
+27.95570662937557
+32.51408462931032
+36.33163861519792
+32.56912454304147
+34.34280900136454
+35.784088127537885
+26.914917765669585
+33.26233313612413
+32.1680539384556
+26.75694334282693
+33.35419056767425
+23.883940458210233
+35.12388355627216
+30.655281773220523
+32.090489999587916
+32.15409804371383
+33.524384886478586
+35.02600540968086
+30.76740019801393
+36.44981000912182
+40.19572659898785
+30.640167082972397
+31.80541682802543
+36.582675006158354
+36.56695936691479
+36.69388539983058
+32.44414543975023
+35.00425146078355
+38.204718290255954
+39.46480809726458
+38.8383992005348
+40.274329993526365
+34.33732301541019
+33.23354051429088
+29.37993132296434
+28.931341035597313
+39.954457418351865
+41.11453335815426
+36.14711921099345
+26.330586037073274
+26.48125673916229
+33.79533963061037
+38.3348210125858
+38.80238418594607
+39.167790764459056
+34.97592723708722
+27.07938012366334
+34.229536944592354
+35.48075679384722
+35.27197850610975
+38.49295843676046
+36.3607082957584
+35.344057984944286
+35.23342736658027
+28.042376692850226
+30.611665760720612
+35.003889390484375
+33.71665961877926
+30.281018763777737
+26.294926049255523
+28.261103870636887
+27.514385776179978
+36.90892836060182
+39.256488720710124
+35.92809392735397
+28.325564134209017
+33.77072096638709
+32.94371782329421
+38.46721020250703
+33.799897387455786
+35.335717860240266
+38.39646867228971
+36.932694760811415
+42.70784178470893
+39.774943372682316
+37.98875313574589
+34.842962175993534
+38.72372812346073
+40.85063666826256
+33.8431578401935
+29.811468244659395
+27.49680904204571
+37.171161327350916
+34.068506573929284
+34.14878867179948
+39.8165165583656
+39.33057566883287
+37.81254275524811
+32.63611543061596
+28.982906697419892
+29.276074420729202
+20.69423754031483
+29.913499474838858
+30.646043032737452
+28.958905646559757
+28.162000179270024
+28.052994215778142
+24.81250983065506
+27.426140210466386
+32.26260067909452
+26.568506928147684
+27.482001885559995
+29.223213177873276
+29.213423075697108
+30.784916549561558
+25.531463338104118
+26.31852208999547
+30.030015356534747
+24.91601750957645
+22.57670101418907
+23.941571607746354
+27.26714548440549
+31.51894761366546
+27.394463615169514
+26.130947301775734
+27.02392215094352
+26.42842389393654
+25.793687503132276
+31.42358346381259
+33.120380870430736
+30.918608452488428
+26.928838504011892
+26.972854035262387
+38.44290716166056
+47.436305369497724
+51.01430653650572
+53.268503648779486
+56.015618615536894
+59.3350159400203
+53.15604189518863
+57.5953674359719
+58.35084757528914
+56.6081587570541
+57.88690942948369
+59.81103604026373
+58.300985677895895
+56.852920773347485
+58.644222619750145
+58.32561479924545
+56.22238522121491
+58.20034138734494
+60.161171308414204
+58.05740732264217
+59.082520893124865
+60.976287971296856
+59.68314598834817
+59.03256641524883
+60.25358904676666
+60.45469817539884
+59.33813944387276
+57.35503723646222
+57.08842396675993
+57.10908866948258
+55.51560306000697
+55.321298443025015
+58.39431277147425
+61.06704866024438
+63.542174140685454
+65.59769297017799
+66.24847017414356
+67.46225835973326
+69.72037651043868
+70.77022229506669
+71.22732260765822
+71.83794203667213
+71.04438951904419
+71.66893185769797
+71.79102882028012
+71.02449420078744
+70.28275938611499
+69.926457545977
+68.73299336734206
+61.47155182935472
+53.99650959252291
+51.33028859841677
+44.87418555289332
+42.61711633384721
+41.317725186936066
+41.98762345300813
+41.749007636783254
+47.14247742243918
+50.59626426200552
+51.79978926724827
+51.34408816619059
+47.64495768037782
+41.284963738159554
+34.18273449020664
+34.834764778682185
+38.662571701426955
+39.380488871053075
+39.72696384469192
+42.60964771758242
+46.46378784623721
+43.4624152935215
+52.439225615524585
+61.14314948497198
+63.39802174573809
+65.01632144054409
+65.8286341460809
+66.1868008934153
+66.22312144395661
+66.24672230281811
+65.98278449935954
+66.02295248348997
+66.0480461303217
+66.25026397404908
+65.78916538598372
+66.28442218256511
+65.75355291335478
+65.66215848266648
+64.75294540121759
+62.81980388347356
+59.59267980854598
+54.700761295024535
+53.99750137930353
+52.77842910535517
+48.98628187145336
+41.19009692084318
+40.96213991630215
+46.01831068367866
+48.80088737880732
+43.61037193893627
+50.278200184813116
+63.266065353894
+66.0819784764584
+67.71677671096305
+71.4031409936388
+68.53616012765895
+73.528487910994
+73.3983899588641
+75.07038660959626
+74.28051189913297
+75.14774794119514
+73.6363434360803
+73.51014575903336
+68.62694102356326
+63.93065116748008
+55.499562118485485
+56.553617684056114
+49.75004987801758
+53.15719536779378
+48.5936825502615
+42.91734295724334
+51.2010143478178
+49.25566403270129
+51.92142510865422
+50.089043289865984
+51.712532362859164
+51.43495476247864
+50.163344878416524
+50.1572818682866
+47.53205067380313
+44.915445328391655
+48.456007388685734
+50.447109198345075
+48.861496445291465
+47.49927527409827
+53.53237805382223
+53.2859406108913
+52.180569167275756
+62.96120244413649
+69.08505988801909
+75.89273053283344
+78.536927610873
+78.73703446653684
+77.1063413104289
+75.62735827229778
+76.01527154648386
+75.67642514514978
+75.32583840403211
+75.04629775393009
+74.87118502294413
+74.97942284949805
+74.6079905211892
+74.56869831985239
+75.11491924850216
+75.3202234740616
+75.49342121693473
+75.49657651070962
+75.19697594357702
+75.24576475884633
+75.55031857832469
+74.83510909215447
+75.23331643504741
+75.61106829726857
+75.39928759653466
+75.67664872051873
+75.93614785107309
+76.39256486303886
+76.71475320863408
+76.31219093127771
+76.94392672748516
+76.63160897102442
+76.54304141860737
+76.67691327871404
+77.19851939095506
+77.64183719930026
+76.06650388901653
+75.2620009388415
+73.19797322150461
+72.70506671861962
+73.82203333556814
+72.34639397305314
+71.93005347913356
+71.5553716946699
+72.11073508302466
+70.19780619306344
+68.47860304040341
+68.0463373130736
+69.4210816353775
+70.42385008335643
+66.52476148887642
+66.45714162547009
+69.76607271904712
+66.90194050443716
+65.14311833954733
+69.8424230193094
+65.23438237124856
+64.492043766123
+65.68830588880166
+67.06332612343988
+66.15290568149723
+69.70867826184939
+66.88631853598673
+68.66532984638093
+67.57883820182597
+66.89102478143175
+69.44872599599456
+67.10158301987653
+68.45623042071063
+62.86276022569262
+64.85044516375733
+61.842947748817615
+64.98413691785574
+61.448383580282794
+64.36346389425839
+57.1326132815785
+60.04347420775666
+55.363364844245474
+58.46047049489816
+56.018769961969085
+57.75072062391803
+55.11613832654552
+55.50199924926479
+54.00670338330437
+55.38953134884689
+54.027249430400076
+48.0444041977092
+43.107967879381036
+48.88976985302036
+49.65039632020695
+47.80750834528901
+49.050057568578346
+46.76879064613962
+41.42426357302575
+39.21899685679119
+41.19357306611195
+37.55065231464498
+41.564492745382665
+42.58355520890567
+38.32181701356276
+37.81310955984695
+32.965387524753794
+41.724960017244555
+45.37835298941409
+37.01268142604886
+30.95885212486573
+29.250324307126277
+29.277912838296032
+28.258496526212
+30.125842137674994
+38.08889511668775
+34.35888990181151
+30.996383091174977
+32.53119922782422
+31.57663836735921
+30.23559770309616
+26.76638797546518
+32.81632615631429
+30.76149218080215
+35.08449935998755
+29.031088390346156
+22.60948460290767
+28.55063534158579
+28.292105568121258
+29.332890379945695
+34.46929193940841
+30.509636565633357
+20.41378883267666
+31.145292939610414
+29.40154396650064
+32.76548407913744
+33.76052709124592
+23.648628101284146
+29.039566607644886
+32.03154329291105
+23.65820566537377
+28.92559184906635
+25.79430365152352
+31.431777160497475
+27.742223010027672
+27.169629531740085
+28.574186175024437
+24.599421857338143
+29.60606468369913
+28.77196825377891
+24.927028766299273
+26.454242142017534
+27.07520908719782
+24.277663296956106
+32.23220291123262
+27.516125744420734
+28.671412842154567
+25.10994650221312
+28.868934027414923
+25.821353015378833
+27.693513196433656
+28.586102234539837
+31.68337510235726
+30.609471885460138
+22.400624502566032
+22.838727627206453
+25.541550626270748
+31.56584098161862
+21.24485138736877
+32.19575770038591
+30.02598666120626
+20.953612421368305
+22.068736848150948
+23.760026188407693
+27.44963267969976
+31.23896635179922
+27.49382081639169
+23.778409562780624
+27.87094198042992
+26.646272924613882
+25.0661488961303
+26.699742931178548
+30.423590201121314
+28.51588046984608
+24.571385921837916
+21.303098195018862
+28.361937074006477
+25.7963493653248
+23.394111798729668
+21.425851532622005
+25.948210165514865
+27.009355781521975
+26.92143718638519
+22.27203595336438
+28.609255217347823
+30.504343708589303
+27.35226136659638
+25.81499934844679
+29.21539451454369
+26.242851860763366
+28.533684625308922
+29.035437989311347
+25.634804791870465
+30.600182070264992
+23.48372578195638
+27.785939605279722
+32.424164130580095
+27.48259187872516
+29.82586342707407
+27.716744571847087
+29.994048565029914
+25.611609000906455
+28.372353330088032
+27.005150197482706
+26.112989118630168
+31.06711905347659
+25.945443832828474
+24.65272905242071
+25.744646462778647
+31.09334999177058
+31.920081201694714
+26.027622463546834
+24.480426884722576
+19.86947126891131
+20.515989997803786
+24.28092073119541
+24.40140474802459
+23.000795343193715
+25.73282525290817
+27.52056512385647
+28.303247060870362
+25.48381695924614
+25.575407728398616
+26.457727149363066
+28.049872903865023
+30.057892129937812
+23.632532173060625
+21.9831112600059
+26.645266084549647
+28.685421492540385
+34.09641057272093
+29.39469858890797
+28.7504816066282
+21.49568144782525
+23.873366968646053
+28.812966855569343
+29.2776199111227
+22.436595133005156
+19.970560560211723
+25.46289016265142
+29.991200110826526
+31.42559114337682
+23.58128522785843
+19.20315189261825
+27.74608376124492
+33.476206587462784
+28.410928188367876
+31.567977554017276
+33.26547224366247
+24.427708243352583
+26.246797974358415
+21.541453333338254
+24.633831912356143
+29.299294537871333
+26.14711977188712
+29.46972810825936
+26.625701611537863
+27.495235363410913
+23.093779290574574
+21.711150259346653
+32.520532042982694
+32.65301654690087
+29.345374119989145
+26.342636576216464
+29.371426740145225
+28.20073338378873
+31.786666817437748
+32.563310439434446
+32.045706963698066
+31.536121312999228
+31.492993343008777
+28.438134420366623
+28.68772539460838
+28.552786506609507
+30.506065220407237
+25.763578022661292
+17.737246515165168
+25.67770393731888
+29.001116469515736
+29.54577430571787
+28.59278805676928
+33.24117569739833
+47.14493141443
+52.601153288500626
+53.94087807231765
+53.334093825746024
+53.628012985016966
+51.36253796457164
+52.41719066936781
+53.813357018522176
+51.70046461875144
+51.2900111189027
+54.307015068364514
+55.147543686206205
+52.46207113789036
+55.20268036112957
+56.874324432952875
+56.57987130941582
+59.78990485472693
+62.933565559795674
+64.76028964649083
+66.71194412500239
+69.14226592478806
+71.75834807622232
+73.7399613161006
+74.92737693902149
+76.15650245266349
+76.74684460261587
+76.69148670681317
+75.29371565550724
+68.62470214157099
+60.090549607697476
+57.293359978688116
+53.18304473542196
+52.60385604069767
+53.531285838439594
+54.06076260499641
+52.59875477837734
+50.6664290992046
+48.144065284510575
+46.03857844476006
+43.92218520517273
+46.78614396447399
+43.619200249348225
+39.35693647788997
+36.87337801194667
+31.779004319759395
+32.08272088011178
+38.90560802878274
+54.07098402195261
+48.94249253643749
+48.05231191698169
+62.331229948799624
+65.88124108900189
+65.7497116076434
+67.06692665731383
+66.34909548465703
+66.81925736180743
+68.46358023978826
+66.44711140755084
+68.18807365748916
+68.7587267430828
+67.94526081356142
+68.48995631221017
+68.36485712608336
+67.58933891141416
+67.1284020759701
+67.80882872021868
+66.75435886979781
+65.0673217100394
+64.2810508032674
+60.2595945121506
+60.77113989953344
+66.63534079732159
+61.986618754359796
+64.46104591702513
+61.749538124632075
+58.33189024642142
+62.243616842902654
+59.538656084997726
+62.13741626262387
+62.46801919922753
+59.868869088463384
+63.50081978459632
+56.33070637573596
+63.40472735177026
+56.83648684101214
+61.542542470529256
+56.283770865742724
+62.59620846645978
+56.42851178924202
+61.767142695561404
+57.662234530745714
+60.26702505959801
+55.78064192945368
+55.91571118194532
+51.082837286697426
+54.49775183320009
+44.77475305978081
+53.293002194490455
+48.209394735233865
+51.467630383506574
+52.19565139337592
+44.63325458853101
+41.15530129504262
+48.796024147633986
+46.861180830718816
+44.237857957665646
+41.28808528896275
+31.535519801071928
+32.38446954726217
+37.92610693883062
+39.49255463705351
+33.81756157626218
+33.625975833754424
+37.73983341430996
+39.018244624580404
+34.31615448595015
+31.794611621766762
+25.93246118337315
+27.20431990697128
+32.20291247106485
+29.39070128718427
+33.417301474735524
+28.484243350702315
+23.836230797362106
+19.412243513007596
+31.937537189605337
+25.674191643021672
+28.230797309280774
+33.07854562495335
+25.534187198039973
+28.911081098886953
+27.979999443760647
+32.057462959015126
+27.293532927793805
+31.992772192187076
+33.41939007475371
+23.292146850279465
+28.985550499309582
+26.418615025695118
+25.357431510063023
+29.471721889216496
+33.52560043575495
+29.673184336956766
+22.8998444847101
+28.275021325979793
+32.115762897033036
+25.88990472464495
+25.0772141496292
+27.632580873750214
+21.835417410794093
+27.88575368895347
+30.578104980448657
+32.23274243267693
+25.742652104088407
+29.187712525988417
+30.97023348309628
+22.217113030496378
+29.555450014625677
+27.59683150671404
+27.95850016510026
+29.928437588209235
+22.49245124230545
+20.29508187382369
+26.175593982636315
+29.950488842483537
+28.40440058162676
+20.467718409509743
+32.01164892612486
+28.780309590969722
+27.796374842098402
+31.580144440571587
+32.8267748535861
+29.606528917355504
+21.917376560950927
+18.830639516819573
+19.11013917049077
+24.226848958769224
+26.639750971575936
+25.43935021431612
+25.476587782284028
+27.150704204810154
+19.76987728138161
+27.320721555125218
+28.61720005056044
+29.85622681434829
+28.099895027987245
+27.961980130552462
+27.176085566713766
+28.138387954403825
+31.4934272872015
+32.26786027267808
+28.29172399603118
+28.05130150304963
+26.37452945457045
+25.124193910468193
+23.34148350790052
+20.725513817741714
+30.19171518247242
+30.648246015386604
+29.395365850883735
+24.84707656500892
+21.577600082886292
+30.346883067896655
+29.410483182149832
+25.364540415951794
+32.18766849753668
+33.64690219979691
+27.222828008319297
+30.77254614202903
+29.642675849039094
+24.550366619208148
+28.090456546063052
+28.2080928064249
+30.228029012211664
+29.227045612434978
+27.00321303310119
+26.6593274414069
+28.45286683118401
+28.322114554756084
+26.631986618876923
+33.914048448311576
+27.065647229219365
+28.66041523337401
+30.573722065352584
+25.264261499089358
+23.040704146471967
+30.106999375357347
+23.687585048543937
+29.42011534303188
+29.976074235977535
+23.654429321621393
+23.621981916188105
+28.128602385236064
+28.185498997814506
+32.48293019732971
+28.679339643630158
+29.46533425734799
+26.559587044463072
+27.152795042419584
+25.880938960093417
+23.130559119149012
+28.36811164679763
+31.034627998872182
+30.652835236493303
+34.20477659106885
+26.425355460836826
+24.85500913758409
+32.570527058978215
+31.785163738022547
+27.922292619834522
+26.559316290507766
+29.627801525809687
+32.865711863124474
+28.247133076378034
+31.3481175803243
+32.12141172123704
+31.598111950073616
+28.695898957402463
+26.799209607932994
+23.870511793115526
+33.57754586947938
+32.32402218001121
+25.835665639320595
+27.278878463324887
+16.069440574713028
+27.608435610036693
+31.73883219094145
+30.634062662242982
+32.426150719383315
+28.688535336856674
+16.713736512349826
+23.783471945690422
+28.09083380589793
+34.390221300112856
+30.12291589479527
+30.241542998348393
+29.88326268914311
+26.168712289628942
+25.52583413350493
+24.675371755884868
+31.048194660845567
+27.56002556401839
+27.433841262155212
+24.860712661494873
+24.258370212176857
+24.364329878513246
+30.840679415150106
+30.82288463074555
+28.57266016368108
+24.842471362325313
+23.826208246370626
+24.88038331262034
+32.31181886171815
+26.694781876773803
+26.646251351655238
+34.08943101883271
+34.3739722271976
+38.74503891079526
+36.15900754220931
+25.913175207602066
+27.66178445955235
+31.098086200826046
+37.079142734041
+30.760914397754988
+24.197257544455212
+30.285890778133194
+36.475497716212075
+33.208529768578856
+31.131143990190694
+34.54096143141851
+35.017348698647424
+29.21655164002992
+32.09533197525997
+26.131261806242577
+29.596913504713854
+22.326332544622417
+26.34928859540561
+29.671192970427683
+31.27246233442365
+27.777802743492245
+27.2710391748074
+22.352328856380197
+24.08140062119928
+27.705136387631683
+20.196650036215473
+25.85509293294014
+27.35005304440736
+30.89423322321197
+22.37171077223769
+22.70882917730033
+24.076268381436094
+24.27522657200467
+21.77198074096964
+20.835331224621584
+19.307844670437348
+28.896110474746834
+24.054336576791172
+25.5426066578177
+27.40212208392684
+22.73368386299184
+23.69302606860036
+24.271666161948957
+27.245207974157964
+25.716255650057093
+29.67654581608454
+23.89547775024259
+24.224804390744964
+31.13736364557259
+36.34081990719878
+37.66872445689344
+34.88249401282191
+35.23155852281242
+43.283463113476614
+41.73131686561973
+45.741872019466804
+46.82932315051828
+44.72214446039532
+45.67606223498216
+48.273251656069974
+46.72786056886272
+46.58406107157366
+47.73243703548562
+47.83155553816476
+46.13613950533759
+49.53953345397963
+49.825590198838654
+49.048237482837955
+50.25485391952127
+51.49036553959425
+50.41026127274799
+48.10494477188139
+48.789537678836744
+48.435078770413696
+46.339786775249735
+47.08732420031142
+48.36420093549688
+49.7966053649454
+48.62396871424634
+46.96806295171774
+48.26525161735441
+49.87918237771498
+51.932456100769556
+51.52457544581379
+51.10648147172941
+54.20444671250422
+57.24488742568687
+60.22736207617535
+62.307327704385386
+63.67027273221884
+64.64026811927206
+65.47194887188999
+66.44699931347026
+66.70993753225758
+66.43979778327332
+65.99613175939994
+64.22679021794914
+58.60186784032876
+50.96801375058368
+46.585745054770385
+38.4694907438563
+39.754133470706265
+34.78842327873738
+31.42231750176802
+37.210936111549316
+42.428639005292105
+45.54507918868701
+46.119879453471626
+44.6111417732705
+41.61437075165915
+35.808514513843306
+33.45463830281376
+27.573621402525603
+33.49246737369363
+30.652541285350352
+35.38418003104377
+41.767754919741904
+38.645988298559274
+33.51252788960039
+38.35419104782781
+52.89415253621823
+58.20488654849014
+58.989309191634504
+59.11266042044661
+59.03706027589264
+58.419859820819184
+58.276021428418495
+58.417724630275806
+58.438865514572385
+58.74091522344143
+58.64148377663204
+58.562678289875976
+58.8360145492318
+58.39483028742954
+58.17977329339818
+57.17974167265112
+55.44960008459085
+49.769058887557975
+45.374464156354925
+46.97656799706851
+43.32630579937744
+40.28023548547364
+42.60481279879921
+42.073308095672104
+40.83740184521558
+44.989230793162946
+41.44491341187094
+45.65123455616056
+54.58321136882233
+59.36544645171679
+62.39309642554202
+63.95826226570248
+65.26310419445896
+64.37127404854458
+68.19544876091372
+66.05634052615517
+68.71905717900637
+65.73052314630804
+67.41982132383015
+63.567036760663505
+62.83856658787971
+54.93605225039404
+46.1734163081794
+49.786836881767286
+43.30365935356388
+41.84463392029953
+34.13860525122476
+34.54969790683202
+41.40526910470384
+43.82779338802457
+43.09205827187071
+44.022695312559094
+44.18593148251611
+44.70058103561096
+43.603899412398
+42.07177746046257
+39.848411435491066
+36.02474506939244
+43.5917328369851
+44.523913971627344
+46.68014608593863
+49.19455714149704
+47.63150488695834
+48.39812966555402
+42.7516993617243
+59.40549696165496
+64.91336740050619
+69.69924247573951
+71.99786597585577
+70.94854817360405
+67.84139329360625
+66.14604668505459
+67.45289445469676
+67.4438345838841
+67.24694406123201
+67.56401557746929
+67.70310269677998
+68.18678230427335
+67.90151492548839
+67.64442809532419
+68.25355403707412
+67.8072904279243
+67.94187788999076
+67.46782597757417
+66.65687174307212
+66.44091232600148
+66.63706954557402
+65.88529841053732
+66.09920930568234
+66.98115077031096
+66.48516933114837
+66.84023490536896
+66.84137910930983
+66.81867116625435
+66.93414039685909
+65.05605108105125
+65.47818119543837
+64.10274067025874
+63.765596751042374
+64.49177411331766
+64.94432820023577
+66.10291169176836
+62.66990435059625
+61.69895450211717
+62.420811996766325
+60.09850652090732
+63.07268933029954
+60.92033767893982
+59.29034005640602
+60.06688681986186
+62.511253070519636
+61.122848989383364
+62.19542424693083
+61.81687484520012
+60.84550581099753
+61.779866685621805
+61.52232857570795
+59.63797576990081
+60.76701450593506
+61.10440465518081
+58.94229966889563
+59.81411231431209
+60.03470454672302
+56.813770641029066
+57.23135657390576
+58.70280459783852
+55.289756292507086
+58.45136027634877
+55.00934179046644
+56.70634463161938
+53.83279661667481
+51.9727253064851
+55.467353102347644
+50.287427674598234
+53.009900363151246
+48.41022207564367
+48.87479430623624
+46.89381866319442
+49.37953648445673
+46.88738846198501
+48.691028396507306
+50.83215495212937
+47.65910572035504
+47.28308901865442
+47.385702261923655
+46.695672195565066
+48.25221444448845
+45.82285168060395
+47.084190633496924
+45.64537278498821
+45.307391020025555
+42.84268894682145
+35.47233532693953
+36.40072372390365
+27.66050664183632
+28.56282870927015
+35.79750299938743
+39.51889540471031
+36.37240620003767
+28.065763053737
+35.00892946490244
+31.046458191813983
+33.24350497794647
+36.55927944549218
+32.07555551965309
+30.29498430004739
+30.56012592300219
+24.948585981564108
+36.40302426108833
+38.618788643466004
+30.36605756185969
+28.269197268194603
+28.394930338036076
+27.434163033656304
+25.77199456289766
+32.7665665629397
+33.69819863715962
+27.933386800449725
+25.821798975781988
+27.631181390968337
+30.06001721443333
+30.148377448241135
+20.970926969050524
+28.244514027193375
+24.12182157658968
+26.93654899322125
+22.66810591120239
+24.9158800184762
+28.230646569731476
+22.327317269121963
+19.681874587578235
+27.810576832758812
+27.277030348792735
+19.278009055460473
+18.220675443985556
+22.88409536939531
+23.886699092149613
+31.775032711029112
+28.858375872618424
+25.49966887811405
+25.31588069964444
+28.27180742606454
+25.09628019078677
+22.465632624769924
+27.73635039928105
+30.126727156961664
+24.112779821833584
+24.670292328169268
+22.848870231377518
+22.61033536423797
+23.3568531667498
+18.206601136331628
+24.026878654095086
+23.486168013702226
+21.75241214001518
+26.629686503423457
+29.024552823896173
+26.513209979123715
+23.433089964183424
+19.24885258767239
+23.869646263385462
+21.1208515282172
+23.801861032774795
+27.732608801226505
+17.532675828118542
+13.985831062595281
+10.606764921021309
+17.533576232641636
+28.560109640217476
+24.956811288363525
+21.148045102836917
+19.398792407342185
+18.870810595302046
+16.84261316779147
+19.807746598408826
+23.865884091232488
+27.36644131710584
+27.052680420478666
+23.091864217926556
+29.054150915295295
+26.629612270540036
+24.638748364058486
+21.956193229031143
+23.439119426515845
+22.068096677738865
+25.4118958851721
+22.976336720516315
+22.87041854354183
+28.09277108223432
+28.253299717180923
+25.388482254499436
+30.048604599190696
+26.72918461439859
+25.673417897605432
+21.29316085042457
+23.375186932405924
+26.862503912176848
+23.735406099934238
+23.12846489347426
+18.767134785966036
+22.741144913512144
+28.378197158401164
+24.689230384075927
+21.472610213932455
+21.710452001839997
+18.491076112725906
+18.246626779002924
+29.763312832167273
+24.569413614620245
+26.972898028202124
+23.980581766958807
+20.80638525801568
+26.096069959660056
+19.096775620572885
+17.161107922952837
+21.18167662597388
+27.324635634985796
+20.080386152370565
+22.731497444769104
+22.250723739244293
+18.845658122890796
+23.887846899299817
+22.146314991625047
+23.8212309658946
+24.320038721420687
+18.053638845991088
+23.611700001584765
+17.93942506928981
+25.008792989583966
+19.836576283781653
+23.15877029206591
+23.950437549199933
+21.735205464081275
+26.58898878459216
+20.844294538984244
+26.957564892034753
+22.912067712851368
+17.65679961897665
+19.407283493155077
+22.132409265164085
+25.66007708158996
+28.7294522364771
+20.753609383167202
+26.03156374639711
+22.3406509090171
+22.932955778670816
+27.866814331717492
+26.453474617270317
+26.609074120351863
+24.053325806581313
+24.18807418277879
+28.822797387053086
+23.40403751869495
+17.87958593722236
+25.4873890338485
+25.924160508105643
+28.68429326367223
+27.9409766316481
+25.019252291944966
+23.864929655064884
+20.63544691671386
+20.63302339935433
+23.947217476118738
+22.830279301996185
+24.619093411731768
+21.05751096899705
+20.298417632150134
+20.80937435610855
+24.634772750347437
+24.42290775679841
+20.271914161703805
+25.760689835498795
+25.229546068154363
+18.034090191745292
+21.541809191933524
+28.847221303603348
+25.75145586653248
+24.552818819915814
+24.458693661238016
+25.922036636799817
+26.609919560283117
+24.684549869112956
+23.829911692194344
+22.598722281333224
+30.6247381664775
+25.261448929961176
+18.15520119433252
+19.439197405846343
+16.945408901588436
+25.186184322841555
+20.233421915698244
+21.097558119634712
+28.977582067208814
+33.881317547733474
+41.29082692941571
+42.0438461242144
+42.755270354017796
+43.06990748923818
+42.218303288892855
+45.16028666706674
+46.17044675701278
+46.04781146128454
+46.91915759037732
+47.27378382774835
+47.85977759992086
+46.599282405521286
+48.23472038233476
+47.489373457074365
+45.58505249991408
+46.66389285702459
+49.350564205749926
+49.7913591738761
+49.751542320394336
+52.50117647501539
+56.70951598723121
+59.02855475925959
+60.127069521352816
+62.01290488376097
+62.28374580135401
+63.016285252367446
+63.81828216679224
+56.45965405105011
+46.81166762565787
+47.603209425700115
+38.069542019504496
+42.0713306730861
+39.803037202734814
+41.51195197101589
+36.79799165277349
+36.083885004195665
+33.06503234268338
+31.34380022846146
+29.221248650883396
+34.748120848350226
+30.395476146305242
+28.783202657126722
+28.17948481749447
+23.706917656692497
+22.56346411782617
+36.45321519005482
+48.83174956737008
+39.03743336471301
+37.359009162999826
+49.00538473066571
+54.833849899163255
+50.14879257266614
+56.21593293680138
+52.09841399891386
+50.25902588453339
+55.534418292677096
+47.22990829961086
+49.722543632190295
+53.03938221440971
+50.89417773308246
+46.836985260769374
+49.169673029418405
+51.31487625638614
+49.179779975631334
+50.78997131032546
+53.480681016879444
+50.87688038711333
+51.464896521824805
+54.844209886506675
+53.121405404480996
+54.5538288071471
+55.6255831819441
+51.02947902874716
+55.720144922690125
+51.9051173580346
+54.157510176676006
+54.786725389580106
+52.43509966126501
+55.37282587761119
+50.34500859385927
+54.82663192677433
+49.26866895425674
+52.937460723782465
+48.82889681763283
+50.04380340451436
+49.94310664080298
+49.02991069159105
+47.49149929414611
+47.016512849107016
+49.21715594229111
+46.98559296783893
+44.61046689577606
+44.41821133328553
+34.008421347491634
+41.19436315247572
+35.604593304572234
+39.058069000011194
+39.19001069086007
+40.56303047373141
+34.76726266033772
+28.423138494107107
+32.40193775417731
+33.16484728728338
+33.66063914582942
+33.668225234347474
+28.360450448682258
+26.370373683254556
+32.63625776378716
+30.993348562899726
+27.39271661121579
+29.392113407231903
+26.57384580333894
+31.173980378308045
+31.88788741102873
+26.502749891180954
+26.371613664993944
+21.919818247960535
+25.532379610483645
+27.373330812513885
+27.396232735481448
+22.26562546892613
+22.268313591921256
+20.41113463627464
+23.107712943959626
+31.10035834457277
+25.99430511006038
+22.979091958853942
+28.74376338353362
+23.912188586276827
+26.117114986277116
+25.960512214761522
+24.47920807819507
+19.082518935383675
+26.116236261879877
+21.866540782853804
+17.461631321650756
+21.188241556438754
+29.928528344573024
+23.60705967719305
+20.3348741907009
+25.27683730339234
+18.602600718094763
+22.12373099954212
+13.96651163975686
+22.409488654213604
+20.777222087608365
+27.12888590818956
+19.54702757568252
+20.372860119494334
+18.719761721096305
+19.515472982217332
+23.849964008889955
+18.405894429986688
+18.786379599085265
+26.994944244323534
+20.848298602027995
+24.022520457759285
+22.632299099813295
+23.164974009898316
+21.138335816890276
+25.624848323510577
+22.002368421454875
+24.419117857076415
+24.4511200999071
+24.249056673503773
+21.087035648830536
+27.624323940374197
+22.30527357316315
+21.446950369666823
+20.9063226856628
+24.420770743349124
+22.268286920372447
+19.707041724052843
+22.24838771910173
+18.204049852261406
+17.185815621315157
+23.51466807037764
+24.976964229089447
+25.1528280569202
+24.715066543875324
+19.23165703522085
+24.92975430683032
+22.921428552760133
+20.064940069490376
+20.081837826330116
+23.6407503272342
+20.784846892010947
+27.685743762532965
+27.706430177512686
+24.073268083033213
+26.626829634575486
+22.95656067111466
+25.056443900835518
+26.59127703426641
+22.685971299834492
+25.16797650446172
+24.335785929168892
+27.217307945735854
+15.47829050572183
+26.207967266924314
+23.759842476819713
+23.253891343863685
+27.62940688349059
+22.685672246541955
+22.69442838610354
+25.339458772320242
+20.594922957062764
+22.64692130435654
+24.120764453713875
+21.604234228583948
+19.176499287685317
+23.502055805705453
+27.940408186066435
+21.287124593072946
+27.308431361827203
+21.849750049710607
+25.220319297704705
+24.617965872898765
+22.793231401402892
+26.043348802956686
+21.569143456817315
+24.73564687888009
+26.960632278765118
+20.086366621453735
+22.41622921631857
+23.925973817342495
+25.11142498609081
+18.84079494035575
+25.176451133717364
+23.069830775354106
+19.848566393987753
+24.78044380135809
+21.321892208365142
+27.400602029033536
+26.91164355392938
+17.088372987377127
+13.68403651056758
+24.3343765443431
+26.387942278727124
+18.24453122988031
+10.94052126286121
+25.58014692387951
+26.635319740238373
+20.857271415768395
+25.59439146829793
+26.653394701474568
+23.474505527961824
+21.98415643670519
+22.27027890571013
+23.25509219592999
+22.22591745961452
+17.87674001883417
+19.850071429108326
+24.220563831677666
+28.40686111799866
+26.100341257957226
+23.16321594814839
+29.644094697336456
+24.194617366142026
+23.254866928152097
+22.16732404408303
+20.688272847609156
+27.2670252476985
+18.91172370502757
+26.629225011010746
+24.99487010853531
+15.555012296885636
+21.23061021320649
+22.26683113535809
+24.910758235127133
+24.94702794761902
+26.174859248690368
+33.14667629628666
+30.481853062307536
+22.33572483748121
+25.912553713092393
+28.324274217076564
+23.411612503771224
+25.062741702921656
+23.550073188744506
+23.58326522725004
+22.229639357939533
+25.56051943612205
+26.917512499201095
+26.21813990844298
+21.519158341585225
+25.78751850681418
+25.223641869837337
+26.25084110995948
+17.70907050066043
+21.58883183282863
+27.352918771195874
+25.747020726603154
+26.224428693343754
+28.6739226632519
+28.38596803127166
+25.153483336223346
+23.01833315461647
+25.19348505756416
+27.577788374110284
+25.32436216763621
+32.43390117928118
+31.12265773084772
+28.560479316133822
+24.441051719658617
+29.487031153184873
+27.580304699567606
+27.568022123183468
+28.235133765855167
+31.475656014066786
+29.501862556834453
+29.090602310225222
+24.180519030825806
+24.47389373805494
+27.28598673604499
+27.922424391012513
+29.922222635347026
+32.22834666204538
+26.331887318483027
+25.67145492929609
+26.698067481577127
+22.35286411285408
+25.341090444524852
+22.628249701749567
+26.824804029737052
+30.218201999205974
+26.737392157961395
+11.650725157887905
+24.12804193496727
+21.427643205905483
+28.48501328756751
+25.068530874145523
+23.897520404861666
+26.332209150118373
+26.724944559445888
+26.324660878859845
+28.651213334310256
+27.112303567623712
+23.364902963023596
+24.15424053614518
+25.52163651771511
+19.85257209469239
+26.89831687241339
+26.758548548104045
+23.167939313725086
+24.055715210229323
+28.841212933719916
+26.01019825521857
+28.537548075483343
+24.293382160427583
+25.302270335528988
+26.040198778897903
+34.8235267624559
+35.53660029177131
+34.71059075577722
+33.46147575949094
+35.932882632811626
+37.116046160314056
+34.0088124410628
+33.377451938856964
+33.87104017943119
+31.757474848330517
+32.57144317222094
+36.81488006587223
+33.49900351951676
+32.197321036391074
+34.83940594982238
+36.98321424980331
+35.11619529768922
+33.4597758584532
+38.87648654459582
+39.15996025421082
+37.33520568791509
+35.12104245234376
+37.795660215283135
+40.33973378639217
+38.5621244066057
+37.60617980301733
+39.91661378982708
+39.243282981107
+42.593876484423035
+42.58527798189002
+41.54945395566462
+43.53032811395337
+44.38958362402042
+44.87144067889007
+45.253254348322734
+44.8911649014221
+46.54756431467097
+44.983636543875036
+45.66608548662273
+47.80713809768633
+48.72550258753181
+48.509710384917064
+45.60583695182579
+40.331197797172514
+37.18935219454406
+37.67578769566628
+29.748074011634827
+27.26957406592885
+26.498888743055247
+27.751332284878032
+23.620336462001077
+23.88285750040221
+24.942096767000606
+26.519702872953715
+24.594388026049728
+26.87027169180638
+28.574461323342135
+26.615296915138032
+25.482626146494297
+22.523742744983352
+19.499140787538195
+21.506107728261938
+35.544680681662626
+33.097100147666936
+23.13209499570054
+33.74252240179915
+37.6768194592767
+42.97231184081425
+41.851947981596425
+40.54156412441705
+40.407153633902254
+40.027212823996564
+42.460635253569706
+41.92514439373501
+41.099340738213684
+41.464029046915016
+39.88360353250003
+38.131693942630676
+38.409934441882
+38.42201794626004
+38.168591604383735
+39.55276209679103
+39.033637421259236
+43.22714284940004
+40.44307536107732
+36.77719337433929
+35.784438855233375
+34.732223932923404
+37.69404246014775
+37.54987533961184
+35.88953452958191
+37.63364721146152
+37.70153789539447
+37.92304939819618
+38.04807847095622
+38.54718191987351
+46.95353899141073
+45.30057539688477
+51.54736858449144
+47.367468129890064
+50.78889398581071
+46.531762165963094
+49.51109705354097
+47.22745175265838
+47.85867655923444
+43.09596826732821
+46.586699376425784
+40.1360304726727
+32.562926233654494
+35.21169693847342
+28.34714618772989
+27.381740376689393
+25.603943480309397
+20.73420921206882
+21.506823310256777
+26.70126705749358
+22.900579499975578
+24.840047862897606
+21.155284399198948
+28.59520510825476
+25.530739905797162
+19.393820328911247
+26.01552886593558
+23.89288026368898
+35.64758567720946
+36.59769180059523
+40.975107214809576
+41.34387590784746
+45.52792856555412
+42.50217494003029
+29.438653024455633
+47.4668178529148
+50.489144322023066
+53.8531818006661
+57.73200974520075
+60.13541373515473
+61.99205736609632
+62.91447104705024
+63.18820679203037
+64.22004609929172
+64.47897230516799
+64.99307455326223
+65.07882332116866
+65.3072579610434
+65.18773835740393
+65.05287751417126
+64.84792192402601
+64.45045953421825
+64.22108407646971
+63.876943442371136
+63.828857426499546
+63.53445643125865
+63.36197144313844
+63.59152061155768
+63.112966456017034
+62.91583570273299
+62.42977571597639
+61.766202530007035
+61.07944890911454
+60.23100151910562
+60.05594504897916
+59.05883050459006
+58.01416739055325
+57.305852015741884
+55.874557405369316
+55.43746582010158
+55.41152133116831
+55.025481717370695
+55.71066826062425
+55.21112024873466
+54.29837481950604
+53.90226130178115
+51.67138447182163
+51.45693589968795
+51.57293594452193
+51.977580695041944
+50.010247093045045
+48.672166480373306
+50.98292466536344
+51.47953313224761
+48.029341788082355
+48.00920177272339
+50.21407608434813
+49.31169602914704
+50.096991698016524
+52.2496475448566
+51.034932209030046
+48.2478034271723
+48.66335729898222
+47.093983173862306
+47.0657534242458
+47.2174927594821
+42.40759784249059
+44.165032849138036
+41.28975644737821
+39.71082445903574
+40.50935078640765
+39.266237954893
+41.834185854835184
+39.60869014463975
+41.970744438748824
+40.33745584640857
+40.96916386982038
+38.98577018352876
+40.68431313637272
+38.96609170142875
+37.888484949297585
+40.087988556331254
+37.58327193239824
+33.64101212028491
+36.76219588632837
+34.64926696390425
+37.543426612874875
+36.236805951194
+34.52671812818487
+35.90494669980572
+37.141424520876754
+31.632502638893882
+31.00143624986046
+30.386480251398012
+26.566739330464344
+22.796044182284632
+27.602473254218864
+26.420187733701084
+18.52538424096292
+25.786350009736452
+24.9373941887269
+28.03764092261082
+28.213674157264478
+26.52872095719495
+23.840023892494614
+29.846427042309713
+25.364201288202707
+20.6418331132639
+27.375693624351996
+25.49593767542892
+26.994971787954555
+29.775534916487203
+26.983037103165103
+29.25151229397116
+29.533241020386455
+31.519322481997904
+26.10610703915438
+29.293022939066788
+29.02500566395561
+27.960813785972377
+30.719407733843852
+24.752028717986022
+21.93503729368878
+27.18802655332422
+26.647333145494443
+23.444342268800085
+19.20481662652095
+22.690807555497756
+27.089301252440706
+22.462467878248304
+26.590093382882145
+26.711770856868526
+27.77847624225724
+23.724887882340965
+16.575611174707362
+22.76334967543231
+28.16313774208193
+32.73531170612547
+32.215877397557435
+23.104155996118237
+22.174784686525626
+29.1367748924298
+22.747025423884438
+24.476616125037822
+30.617380687023015
+27.81274125456605
+24.62725193479224
+23.626049962467633
+24.659485467473786
+22.775755131331977
+25.037416612131693
+21.080927065609387
+23.745287065594468
+25.455255046963075
+24.201202033177793
+25.083034357316535
+25.907254880535632
+20.51874359813621
+22.795016604249483
+20.712120854695684
+24.226543089023068
+20.610990307130535
+24.861253482755217
+28.361974962769878
+19.16377339860486
+21.375571386002406
+16.149042785807822
+20.215209085963195
+22.439017656945126
+25.278171472873908
+15.037673556004705
+12.01720540842426
+16.680072471385614
+16.839203313190453
+25.244069272985143
+29.257314841414413
+30.143635124018246
+26.201682129533665
+26.295717761400127
+26.29588949822991
+23.07750424195008
+26.441760119235482
+27.105394501098445
+21.753530808059452
+19.785665230441012
+24.786537554841956
+23.935434773781694
+27.253360987354768
+25.103804460204614
+24.61104400981796
+29.86260358343047
+25.517153364442493
+25.94349671150691
+22.297787915820578
+21.732812654111356
+24.37235777933151
+25.27769591606652
+20.175338264292904
+25.778152918363475
+20.460676189999475
+18.2889234224145
+26.18026005361189
+28.014334203358345
+23.64358454135278
+24.57251562959175
+26.051721588601282
+18.52071405622904
+22.875304487786167
+23.013760153712823
+27.73157042287754
+22.429130987098702
+23.273055916193158
+26.46155099455872
+21.280811956988586
+23.08692755689492
+20.21860325796864
+24.360871837097164
+21.20122576575382
+22.80063194745783
+20.629530708100233
+17.521083050053207
+26.371344217244797
+25.033836766497004
+24.469100413647183
+24.1797809941813
+20.57728224740245
+26.178925845378785
+24.40960031242615
+25.45749299736667
+23.731365895497518
+20.25640819965885
+19.308918901447484
+20.900232218017152
+25.170217513779562
+23.604900186015044
+27.504407027334636
+27.96041197404979
+23.5903978221762
+20.413193922705915
+18.901362675067773
+23.207610319483166
+26.59094292864009
+25.508450870709368
+25.221782253864617
+25.34935092139824
+25.579675617209077
+28.217202542235015
+28.678244534617463
+29.748269517138255
+24.093347663092118
+23.039486513475666
+29.505253124103675
+26.5411432243731
+25.08494124058288
+26.79135021831644
+28.06499554973034
+25.325715194894016
+26.231934631288752
+28.791133405706788
+24.067714937093285
+19.416277005376955
+18.41366694952562
+21.819938100282727
+23.684836243273352
+30.31957053972664
+26.26937552744856
+22.13295052223515
+25.719561936541254
+21.784828154404565
+23.738716461688597
+26.64514750636225
+25.616779349038268
+23.997087356173225
+27.016800166932924
+28.32448249953029
+29.756403799422117
+23.75134131465488
+22.908573019308292
+24.829856279552203
+29.038217751140238
+24.30695546329322
+24.02453486515806
+22.09173172187687
+23.71399220929004
+29.050726851128744
+23.206661197234524
+19.953721016856946
+19.47716937912891
+17.059225901696635
+24.473549555789404
+23.45171778582238
+22.309314283986836
+29.76642108663495
+28.558450460772747
+34.95152497331884
+34.76383190783153
+35.794385178888746
+33.88048342195539
+30.183640339601155
+34.34667061302787
+33.14519067156277
+32.51767807011311
+35.914345150232634
+33.30648852139221
+31.441998758733277
+25.313439988924003
+33.9961295183906
+32.28730778070026
+30.581343341810168
+35.61247584180914
+35.547481510724495
+34.28580112658098
+40.123212605612004
+39.686236480082954
+40.652666265531586
+41.670692187473406
+43.63156537392865
+45.61094603510365
+45.48632615468537
+42.58177977492055
+43.3818517133902
+44.087877251727534
+33.83471751246988
+30.624010615953964
+29.39580546015374
+28.569288529790285
+25.467124995017812
+25.205526016019874
+22.235378288852118
+29.707378859157643
+24.154191883547043
+19.276755354866125
+22.64226361922745
+27.72185095774107
+30.016912298207288
+27.388815745791263
+26.602912531341445
+21.271145385109506
+24.064070595068003
+30.946911664703336
+41.955621988290034
+33.76493180159433
+33.164621210612
+38.27881630003448
+43.33867083793715
+39.97326377500058
+44.84345145873726
+42.259302195467185
+43.24100412902892
+45.682337112317725
+40.59761705837707
+40.560439949142456
+42.01948658903359
+42.794437416229265
+36.667924407007376
+41.92033509930022
+46.01211859627267
+45.61712116407212
+47.06891823848329
+47.24343425885394
+45.52292023635777
+46.09730343775709
+47.60716018041747
+47.387234980251705
+47.10715309102921
+45.475341390683234
+41.62054375541975
+44.64266846452696
+41.86110570205754
+41.719278490480704
+42.69379311469591
+38.91346717704443
+42.33858691025012
+36.61795774805972
+43.09650241129884
+40.097817895356435
+42.53562745125644
+39.64910439926063
+39.62092514654115
+40.49465601902594
+38.900729065338695
+39.31646621839326
+37.324876955201034
+40.87542346725451
+41.36963367205444
+34.02907609642665
+29.77456687684399
+29.83241647327911
+25.914586086017707
+31.204207183041603
+27.09896309414981
+26.921155713732574
+31.68571803850159
+26.553420100299945
+26.17806290113056
+23.91947953820086
+23.800216330900312
+19.998910437319793
+22.25768802992681
+19.467075033723205
+26.439361077105175
+31.97811315336142
+28.772382202077864
+22.12979690763946
+25.870977645647415
+25.58880525095907
+28.678158683901714
+23.975185689656684
+22.64453535697568
+25.883402204885684
+27.481795390535666
+27.22938623985202
+27.604545126953397
+25.89953792940588
+22.911799071688534
+20.953376138932768
+17.648901873779906
+19.53842861120171
+25.307629097998486
+26.31751449428957
+23.49893117845646
+23.31702236078499
+29.872692085083372
+29.75424637519494
+22.599740189121434
+24.331010984421226
+19.513038749705174
+19.82214944846865
+24.258698367357383
+22.82073595799784
+24.071487811096546
+25.85454782676149
+24.633239235420405
+24.403985365332773
+28.435058184841495
+22.90654851589433
+23.905455817528065
+23.028547335401413
+22.043498337871696
+19.744950520577532
+25.610002140862477
+15.59067919814241
+15.44258881364722
+18.620908027923676
+22.901084181156918
+24.548331826249353
+20.0007052567001
+22.655601598640516
+22.30457748102195
+20.755795276753304
+23.63578397761067
+21.346498058909276
+26.113414824688007
+21.91164410906208
+25.131007360693445
+27.86336620863686
+27.25528824748507
+26.951001801769124
+25.517639918811
+14.189587490204005
+16.946984583788378
+21.853413566611522
+20.70326448892034
+28.121641534018906
+24.723370670217136
+27.385928383599747
+26.609092739023623
+25.639153747657915
+23.391081828694155
+16.06688488123919
+21.596585856032107
+26.382584430817005
+27.358251716814834
+29.138398315620023
+23.122409731620124
+26.58894071754088
+28.43314395814197
+24.62469447671505
+22.995590073603395
+22.160815569836984
+21.536880490532013
+23.738525392370065
+25.941089973403905
+23.12112044201325
+28.673641985231157
+27.021924272823668
+26.80258349534408
+25.708997805456775
+21.308663840289626
+25.09028776352629
+21.52845118228754
+26.187431856259778
+19.45048125879869
+28.385053587067887
+26.363237549931895
+22.57164096315958
+26.065888721513502
+21.98874913602944
+16.999156398267317
+21.62198667178633
+18.4514275669342
+20.433503752443286
+22.4019752266408
+23.201665722095072
+19.926298529845752
+19.83296746446196
+25.20036221110901
+22.834977192692918
+25.38772548443717
+20.317971433829456
+24.427041621066607
+24.44336741572036
+28.437442480003966
+24.899168708951905
+20.214888290552025
+25.84366647222332
+27.852708119694498
+22.187704462142406
+26.142800331292904
+27.466860192524862
+22.80148432935465
+23.32740645031859
+26.88251015626912
+25.932481797226146
+14.934320901892875
+26.15219632489513
+27.161841545935204
+23.90337227761249
+16.99958756640214
+20.280291964466926
+16.425663081734044
+24.89912065459977
+26.573795996473578
+17.00760911954893
+11.799116490249318
+18.57914962398793
+28.07584408186385
+24.819279427034928
+25.655428783932564
+19.679528353852305
+22.185754975055133
+25.301845255298375
+22.547327671175438
+19.500012828626254
+25.790071567321917
+19.81945895299546
+17.902046761713066
+26.771024899808793
+35.25351388851871
+27.409475383649067
+23.504628784947997
+24.95074590953675
+26.513246385277682
+27.330342219023294
+20.516716429220423
+27.05981705692288
+27.94576331962513
+21.564182307148812
+25.174106190462894
+17.928193954821054
+15.40859266646838
+14.685444037454673
+25.267099761372236
+30.57677494879212
+26.39693609253723
+24.404689052980757
+28.198963490435432
+26.218996033860734
+22.213995956821265
+24.2478410274545
+28.332806000094877
+15.1486240503924
+21.756885442228324
+22.660273215055582
+14.723021191900997
+17.646894865423477
+21.45067643021875
+22.407673891001025
+29.202737691998635
+24.117286664542448
+33.11039074875802
+28.99721482596614
+27.804834660772713
+24.953440867846368
+26.821502976480517
+28.007247249531744
+24.035874616584394
+20.94136437258659
+27.02149729124791
+23.012671634365404
+20.699058124774112
+22.458770253951954
+22.838072755475636
+23.746548425837418
+21.38637241681286
+25.220351072685546
+25.69109230787717
+22.532693859907965
+21.1415712968777
+20.95730889473961
+22.214014861526763
+26.531319754654305
+26.479740495443195
+26.316080476767013
+25.311633455609652
+24.107151792646775
+27.702007978320268
+20.79049198881347
+23.0729266599226
+24.99121476740683
+22.621333109435383
+26.35577258545851
+28.08181445578971
+21.53501087104145
+26.130699008646886
+22.929332705154565
+18.614849405596885
+22.691445472929757
+18.236372403471933
+23.929967568679487
+18.266970053766272
+17.98505693404671
+24.264668737208595
+22.248133684108225
+23.63424459767019
+26.045942428481553
+26.728831371950818
+26.64080066866859
+24.228445458692477
+28.575728521678215
+22.98001522081394
+19.77673796151349
+20.547575252838485
+24.28360187615303
+19.70175368530876
+21.473983068387696
+28.727713221991934
+25.749580000439167
+20.768171499759447
+21.204545328429575
+25.451170781436574
+22.674457147156915
+24.745770231839998
+27.756169114826733
+21.48532960729844
+26.329569894537684
+26.76620962698722
+26.983838592877106
+22.198234238341925
+23.433926358620212
+25.91096874856234
+26.792325380631155
+29.17564072320097
+29.964239323609164
+23.823433807003298
+26.95185747011189
+27.602661344405092
+28.164158890952677
+25.37803184785875
+25.996909307198976
+23.421016583071136
+28.495681903460508
+26.093329158962533
+26.450310374268284
+28.148107938622587
+28.06886256018373
+31.144242891863897
+26.99660619797679
+26.745290692636544
+31.02536075301846
+30.467184535349304
+31.258026708755366
+27.266823133618715
+32.46548887588959
+32.573549788287764
+31.085108499303118
+30.33317052342686
+32.63567758553195
+27.85414072840433
+30.46553850046446
+34.63375734989319
+35.58208740757625
+37.4265111233053
+37.23183362796331
+38.19014619666096
+37.458065319720504
+40.58128940652243
+37.94881261290035
+37.40211914374742
+28.318818970004216
+25.945108379128513
+26.329391922335148
+21.760016907223473
+22.951360800989207
+22.931174446088505
+22.26769111730981
+18.522113606752825
+20.014897660581354
+23.528729265601598
+22.3946344914162
+21.7706686776651
+22.216592523238063
+26.82973910378969
+24.399679550390132
+25.22911652461967
+18.99872205509864
+17.683382647928426
+19.657126393994986
+27.25881375631822
+21.95864213722399
+27.353417260945832
+31.578855973149018
+31.489210185032988
+32.49829652960295
+31.88127495795797
+33.21251957962214
+32.12579855368335
+32.740125363848094
+33.64962396340512
+32.781543703882306
+33.54990996274675
+33.97086763534229
+30.67240390845855
+27.437433147045695
+31.676317167377462
+25.63030321105046
+29.247350933458875
+31.70088482311793
+28.370991140647973
+26.97386727222552
+25.2167531603411
+23.0118323808545
+30.481171894976427
+25.74725156913641
+25.23193916098529
+21.13833356129888
+26.99336195051488
+21.876717836406627
+29.213881920513202
+27.90834792751042
+31.884637036285966
+35.44319396701526
+34.96985466869708
+34.65553064864051
+36.212206568640994
+38.505455145426
+35.997854270240566
+40.45913953960337
+37.10518486012951
+41.09287336693266
+34.562602825971226
+36.70756577750167
+32.20415789026396
+32.61875030076588
+23.666364440406184
+24.517038288307518
+20.217055156686627
+24.663966146857106
+21.320373940117108
+22.89389898659924
+18.52184125759868
+16.21726063097347
+23.546573558403324
+23.593948564544192
+21.32328046179275
+28.373210855025334
+26.0690379080428
+25.57318558842867
+28.601764492757056
+25.464485074991302
+29.92046109345928
+28.718543547104474
+39.38435116904528
+38.88507378857541
+41.04848915091446
+33.86723461194546
+26.241885896173685
+29.64093312835054
+35.652894410676154
+39.55194169126392
+44.769275724075754
+48.36413070797929
+49.77535285289796
+49.01134359633984
+50.479115715018686
+50.694693990619854
+51.31918352734061
+50.51201830368327
+50.271205299068264
+50.99970202329729
+50.1044915872305
+50.34734648657836
+49.76941807034726
+49.87420071406165
+50.11230257370502
+49.95342392588849
+49.73791219475692
+49.862385289980395
+50.516349219216316
+48.75420365522909
+48.68955537090237
+47.63888500351857
+47.671484364361326
+46.61728700702127
+45.56380186964894
+46.67303450432789
+46.04053890862498
+45.16463130136865
+44.62383230224064
+42.80350614916765
+42.432145052470524
+41.834700405365524
+45.18546838535457
+46.33863067059716
+47.874795506035404
+46.86305503761939
+44.85826712738374
+42.253709381010246
+46.161845786062294
+44.61952236107755
+42.19873572584447
+41.30260647555059
+35.96816053219297
+40.087176386168196
+40.54055456285775
+35.27474953176683
+38.66710345154828
+32.73653241853671
+35.760678920792344
+38.96854693249766
+34.287840377687104
+39.152222057957644
+37.96618542347976
+34.463909272443715
+38.44659657629556
+33.8449095229295
+32.893819905485586
+33.64047049428103
+30.969481280241467
+29.561885402184828
+29.86857890140685
+22.7851410204391
+30.010544878980767
+28.112620569968286
+26.47513702512076
+26.627961525662485
+30.26152581096882
+28.647878684060103
+27.029667125110123
+31.17376215908304
+26.28945886619114
+29.431806553913603
+23.012197687008978
+25.973214676688457
+29.193528483284624
+29.59295646798263
+28.647817791746917
+27.675540715114764
+29.607463461204972
+26.6827967658551
+29.191653095054633
+28.441993397274118
+26.62160475042988
+25.5155851682659
+25.430608208910044
+24.619049606117073
+24.194841522736013
+21.7203549334413
+22.787643986419383
+23.497816587496715
+19.445014382049806
+22.934107452924835
+20.848592956155358
+26.15484912893227
+21.524122040272715
+23.423982540308103
+21.44300539379462
+22.544918016464564
+23.637097059303443
+21.403987896197222
+23.280404132124374
+18.924236453534306
+28.39551294415621
+24.05667013374287
+25.992285600267607
+30.48481914838179
+25.70105014675326
+25.675831501949787
+22.041911164381787
+26.458635664662182
+25.23596634442437
+23.266308030585293
+27.6850169918838
+24.269153999534254
+23.875521150446033
+25.229429532440065
+26.12509647620918
+22.29406623349969
+17.92862281691481
+20.134849243433308
+20.915074911667332
+24.126770224777047
+24.146526841744574
+28.00211132369415
+28.760531244906375
+23.693744902663312
+24.549094899970314
+21.659543327699936
+21.649196918905744
+22.140930610372152
+23.415172013692754
+18.689002941644034
+14.536036088922373
+20.018744406376697
+22.238082900442578
+24.234332448232863
+24.103770589262908
+21.692226770792942
+23.71266753098361
+29.26944911446023
+25.92440532806806
+25.541741891708668
+23.789105573285482
+19.175667033947548
+19.345567214015674
+23.776879164198476
+25.354250787611093
+18.34908137307508
+17.117113757872374
+19.41341637364657
+27.836976130771305
+22.896010272273102
+23.139857360146536
+20.485289015807297
+28.137510559521118
+28.572220683348263
+20.47937297409301
+26.832121480227457
+24.702335545838523
+21.27040460216533
+23.530313526224504
+24.112837686760827
+14.428835079104275
+23.88209184964252
+26.768265522896655
+23.439890646527672
+19.500107461023916
+23.447560843717312
+25.515015542602768
+25.45103224660849
+25.49533263793475
+22.925938803906277
+22.982714020727187
+23.939952525705493
+27.693401642453153
+27.17798355395891
+16.262247226281644
+19.407501921420973
+18.048536049221738
+22.81139144841633
+21.12254066956183
+24.614941801291195
+25.42644746506413
+22.104997814829616
+28.82170182036309
+23.14031207260318
+26.149503669983005
+19.467715015721595
+18.176251217557393
+20.88458965938449
+21.44949584221574
+22.972368024586387
+22.797048043035915
+27.03685981943498
+28.205306302096176
+26.067359322374458
+22.367458850754005
+24.396571029577075
+24.461356538421597
+25.717759258547304
+25.24436857326738
+24.00401141318227
+23.85602234933434
+23.079157805406368
+25.185190743406835
+22.90293899727935
+25.662515883535093
+20.6336976227402
+24.73683962192321
+20.88814953521465
+15.943667447334278
+14.24533791050763
+14.487658937261145
+20.140317816609652
+22.92491797851146
+24.808168003055826
+23.95795585705733
+22.955298427085808
+19.994798983512453
+22.547345594921964
+17.4229760133191
+24.88724961438028
+26.632750311235995
+17.228046890542572
+21.66445347185936
+24.1717046157881
+20.2139569111945
+20.930743639785177
+25.35515619512003
+22.427290618093238
+22.424118810827707
+20.14095605842037
+20.68862941851114
+21.433518073681157
+18.048037668205254
+16.89580585941951
+25.621270601310286
+22.338204947809487
+24.02688203709407
+22.662329201547635
+24.203150613966315
+23.89482166135089
+21.414746929481083
+25.351611803473844
+25.871315692022776
+24.325316479896728
+25.17855104752134
+23.061488406411968
+27.54596018277347
+25.833521957464427
+23.808871131743928
+21.247913053031212
+22.435239372211555
+24.10001648620444
+21.5076376883204
+22.357363901843883
+28.543126887889613
+24.74247268989727
+25.589918577830005
+24.2526395440471
+16.369365392222164
+20.80617125476276
+25.860086760165473
+23.822554552258268
+18.83875101671663
+23.668049845418267
+22.577708933138894
+25.467409262749314
+22.233165592770632
+18.29231091934055
+21.228297073753495
+24.092736304162685
+24.77555283346551
+21.349807433881338
+21.070428378273462
+23.83391892153638
+21.299393521797384
+18.376901173326573
+22.837338885525483
+21.059863902376364
+17.675096363061698
+25.92573763866592
+25.565882855079153
+20.85212493550445
+26.083589108274722
+26.147260263918128
+21.947350285268854
+22.008327685491736
+21.403172124672764
+25.865140527091498
+26.615389166242963
+26.177480378616778
+26.062492835409998
+23.1338314683277
+22.61228354200341
+22.521604809115146
+21.75368635981961
+21.31013908781493
+23.703433271237316
+24.833784620303803
+19.114910713281276
+27.73651835092174
+30.16625656674617
+29.507933546340297
+30.563811148948588
+29.808870583336756
+30.664389335232485
+31.825940600000465
+34.656947954029604
+38.579526268183955
+37.65196220055086
+36.36256567899325
+37.24256053764849
+37.2448140074719
+25.778067493532305
+19.91277878475212
+26.24963855492669
+20.40387115174194
+25.692593388859763
+25.080362536468883
+23.32728189323616
+27.312475212393608
+28.650210445100086
+20.697662663681598
+20.376569916546984
+26.85627625091506
+26.293775554738076
+28.37972069405909
+26.44920572723953
+23.370921448547406
+18.52691138262975
+20.087744045196104
+32.12014092076679
+27.7257906765565
+29.043785456908708
+28.460542639132242
+29.406566032563134
+27.830781452057607
+33.34072251821411
+25.667071429846686
+30.194193389257364
+30.484328000117074
+26.814596187796226
+27.421808342037068
+30.330283179764706
+33.11801876368146
+27.024496914747402
+28.280400709016533
+32.70194518610879
+29.184430741377412
+28.691469978737445
+31.834165734253588
+29.31088913956748
+30.22561800299222
+34.57732871423606
+31.121225717447274
+30.201113779178826
+32.14308381217704
+28.869063617564265
+31.29421547387433
+24.047571224752502
+27.745823798285002
+31.26728130032923
+30.665086873263178
+29.074394170205665
+26.675282607007986
+30.178991499820327
+25.902794254542655
+27.70396662210844
+29.434519291514007
+28.735188583358678
+32.61008134570032
+28.803622821630526
+27.681494426869165
+30.7215583737608
+29.955463971030838
+24.182511615973795
+29.010549776443753
+22.608374236988112
+26.79131215060916
+22.150607119817607
+21.432868904985483
+21.37815851529166
+25.293461223536
+21.7487267338646
+26.216621763729947
+23.169892356128727
+23.55837071133368
+24.651958640865658
+20.712428929885988
+20.97401712724293
+26.903941892686788
+22.59720585552938
+25.908693980732693
+24.396711263798736
+21.149984548692515
+20.89396540234786
+23.814806399475856
+23.02850137827913
+21.238522420205953
+20.99786432608218
+19.302692761113335
+24.731965945873142
+23.900202604313066
+24.755310404517715
+23.509479847481572
+18.499193590477518
+17.777851020660293
+16.404127697578403
+18.608781684571454
+20.800477784901688
+22.829957713004603
+21.93516127975795
+23.112375300996604
+28.79545312581982
+28.342342622454353
+18.259222748160184
+20.297633158586848
+21.193752799249097
+19.60409048543481
+25.423647517854192
+21.95409936956358
+18.330793807242827
+17.814880057904006
+25.045723729939482
+22.85718445643421
+23.888653488753405
+22.503511595076702
+22.055302551842843
+26.89672766836557
+23.883064455981753
+21.810488269184887
+25.211821582534085
+24.061652082475717
+19.77993474806705
+22.760885427360904
+24.391799492617963
+19.32991423679367
+23.29621515478219
+23.040002980498898
+23.21470307390271
+21.15090214042621
+21.833950089136593
+24.842858349332218
+24.68835710544812
+18.408178686686853
+20.364050577787282
+21.573606073116892
+24.84121862264533
+24.217846780751188
+19.176347635573364
+14.863106215275636
+17.750016002074872
+23.717344472335284
+26.41262744955789
+25.606753375091074
+25.240974445526703
+26.493032740275837
+30.689116084933517
+23.694348329051238
+23.97860484419455
+16.299086697498765
+15.00687730245123
+22.8101477267861
+21.935480264767847
+24.079433164377434
+15.966425611594971
+16.272007357825075
+26.598049455869145
+24.57777187478068
+21.473179835799357
+22.72206472096198
+22.15997060038977
+19.151427311268407
+16.72222525167858
+22.588099642380286
+25.80590463599016
+20.52251583938788
+24.358084318155306
+18.750844657273404
+18.21467337088346
+25.598379111695394
+23.352882437847995
+20.734520387679694
+23.21902729509422
+23.7253735217884
+20.47444036282964
+24.429354972059656
+23.954504251991906
+23.423076380245092
+16.094473655862018
+19.07431848227884
+18.75805679769968
+21.677885539464285
+24.924990723287124
+21.561528427279555
+24.87646742822453
+21.0190947312351
+15.663352138600672
+14.663626919222338
+23.78692642240364
+23.04976178714945
+21.95524133466168
+20.655370782105805
+28.420080350450704
+20.457392885399116
+20.915367542032953
+16.718070975157815
+24.781187153861907
+24.286001187679247
+26.209090994573543
+26.930342052265885
+19.818235173160886
+24.38862142693928
+21.4241010657328
+24.59309917392666
+21.693785064287496
+25.09612986087376
+29.365864842522356
+21.913864139809448
+21.29478360841246
+21.832617240423403
+19.916097982534396
+21.530741871457877
+20.313487013299195
+22.301750061692232
+18.891894030806057
+18.91759723043775
+24.424901735813265
+22.98375386078061
+17.457029266327098
+18.456449315147836
+18.058681899545704
+26.942370084742976
+21.780974838368152
+17.55029665152439
+20.339194741461938
+19.572888700478003
+22.526439676181525
+27.111274823676254
+39.54987673480033
+31.398942186347043
+30.628758171484705
+23.7148172027389
+26.125632407969647
+26.685921414701255
+22.974451527123875
+21.52007749618862
+24.085007967503884
+28.02551209730599
+22.60959005566022
+18.171295733557244
+12.732373082050302
+15.18563385975304
+22.04315142233476
+25.609336675702764
+23.378526719555325
+24.96619277026508
+18.156094292189252
+23.774187078417555
+23.20555422870001
+26.726847710198214
+26.103165777228526
+20.325968375774252
+19.64817168819563
+25.109847136063962
+20.871729689166003
+19.347546780852696
+23.33173711921127
+21.319680781187017
+31.5722138358001
+32.77724119635607
+41.65639473945393
+33.88905271338548
+29.528086001376977
+29.488981836226515
+31.035797391818477
+25.468903511403525
+26.569123036198803
+24.081828656457702
+22.810573361915374
+23.789804399875223
+21.57492525128781
+24.431916310582565
+22.648472920337596
+25.311060094667354
+24.09944991241187
+17.716756487255466
+20.384194310579588
+20.135098691576516
+20.601470487979796
+19.384972882389732
+21.008876478052628
+25.535175809059695
+27.418954801230072
+25.390657767376155
+22.834651652454795
+24.040524477170564
+27.594508405042546
+20.13863798983293
+23.07368732842943
+27.401481273988225
+26.496295249953036
+26.34811956454594
+30.220067507482668
+22.44835441051373
+24.863771209833644
+28.240075924503103
+21.320974932583127
+22.890947880033735
+21.1643667312961
+18.285169606283546
+21.690522533346325
+23.51086658857831
+18.8754492963878
+24.294622349799326
+24.319743480478976
+26.69561875242917
+27.297186363043338
+18.89373696009173
+19.138632018504936
+24.797703942941922
+19.6758714468766
+20.3985760840783
+23.604015838149422
+24.914077468953295
+18.802141234618475
+21.893881361542356
+24.41029734850585
+23.613311429543913
+24.048849844099195
+19.93759540494281
+18.60874075514556
+21.656811413188436
+23.63513508298942
+25.293768932113906
+23.660265448895757
+27.122393288310988
+25.946141308486162
+27.05696561029515
+24.011519254423277
+20.53192463683648
+20.823176832836396
+21.15347934530827
+24.82007859907479
+27.95860948988168
+23.12323066539666
+28.870399336150854
+18.847104136954158
+24.49748506174403
+25.255555483192907
+23.450993046710636
+23.067718096318032
+20.46773180566187
+20.159286527375258
+23.940116180494925
+28.646407164527417
+22.95415181727448
+26.567832294168582
+24.143700376534085
+16.801338547398373
+16.776168416755596
+24.73992522896883
+19.888548916895658
+22.782181650177975
+26.671427789365495
+25.100621236202016
+20.387796745854033
+25.250343206875016
+27.20710549983184
+25.47775580642697
+28.23960876795732
+32.13753484101082
+32.78403235412192
+32.137952997981586
+35.572070074630844
+32.827217967162525
+33.6652344321414
+35.55853857092768
+34.14249328473761
+36.05459329963729
+30.729889492375904
+21.485335159158055
+23.49562622601944
+18.005827661520627
+24.742543371033292
+23.361658053439925
+24.995280827443864
+20.534908866200112
+19.895025550100044
+24.01460325691322
+19.9991922593822
+23.426312240659655
+20.915494288966883
+24.92141425206475
+24.231256013230563
+21.638578204302604
+17.896805754124657
+18.333927957495163
+20.148901925424852
+30.028893031768078
+22.91319426327786
+23.86599785964843
+24.601976702901155
+25.29878264201865
+29.204905146161323
+30.249965423320134
+33.19492660348399
+31.219301258653914
+28.28353164274938
+30.596360789429085
+29.924749318848328
+32.80035977673646
+31.45277755210232
+25.34469811076967
+24.361754483731403
+25.47044603541032
+17.913375469002162
+22.102573069386878
+29.203310963445873
+28.131025470297644
+18.535693832349082
+25.239961286076664
+23.36207952963072
+26.11234938009912
+25.775931206363197
+25.3438593427513
+23.69798722203342
+23.01035900500051
+24.70141857794229
+28.16856969986516
+25.765730250167067
+30.44257491270335
+30.51354257632768
+26.131800436644156
+32.267446105651075
+28.418783822666967
+34.249440053904166
+30.012317069283185
+33.830604481462984
+28.178429318774548
+33.438567653512905
+27.792807906084647
+34.69467676554356
+29.92073163132909
+28.428280589157126
+16.847575594593295
+22.055694671432732
+23.031480966549537
+21.798983052626625
+23.363678406782043
+17.362018567213624
+21.178100426967816
+18.928978611013278
+24.570945208159273
+26.795806922542383
+24.38835942104535
+20.80606647219726
+28.311061681189855
+28.80835555334987
+24.277887780750135
+25.588230715983727
+33.52993847805125
+31.04777023512797
+35.96237103901656
+36.5656849183045
+36.403707348451704
+30.256606941701563
+27.706209644332503
+29.609657670841955
+31.612839006921945
+35.727867190228
+39.43301307773454
+42.663926826019384
+41.61670973077021
+41.71551839098467
+40.19215737391597
+41.164576298922235
+41.7237431727906
+39.432398527524526
+38.95096528504913
+39.916820089864885
+39.41099495746823
+39.399600589998386
+38.89450642316396
+40.19312908158495
+41.63672323281306
+42.52296210788349
+41.517188069200884
+42.0148426668203
+40.43449102010894
+38.30675379027798
+35.845859937360274
+36.15282074521549
+38.50902999642831
+39.49082392065932
+38.41547737563563
+39.89665134853817
+37.34009177512796
+35.946762268879596
+34.96155521339708
+37.92106011188186
+36.658565680269604
+33.988254408664645
+33.73283048732405
+34.685070904304666
+39.32768431487115
+33.93340449297166
+31.296287428999435
+32.32293150079077
+33.06188660586612
+28.279105611313625
+30.338568783505906
+29.63618968113863
+31.652631107852116
+26.760667245816308
+35.16961198616487
+29.777300298804832
+30.021869185072944
+25.360393730030083
+30.039705250271524
+28.954842527881098
+25.931572893441455
+29.36641352620073
+30.462612700770123
+27.770675562097665
+32.47258020253689
+26.805430803235254
+27.562526710884086
+31.76428855077816
+26.89194596240388
+21.085577251279446
+24.958270799534787
+19.369701934124905
+27.34090441980156
+26.35416618897908
+19.82205961991572
+25.840947901426787
+27.364007447716162
+25.39668222595381
+25.61333194500206
+28.74468417353917
+22.470231949189966
+25.384067570509842
+21.791780437623643
+16.920554221873203
+21.702762391493607
+29.546815306608934
+27.652752967449615
+24.460186804888153
+27.63337550124956
+21.276817160928914
+28.73249615508807
+24.713508678448292
+18.72315353619838
+25.91454916794663
+22.5059615467042
+22.79510277218631
+22.97062359531978
+23.270734633043546
+25.217724775710806
+24.780099380933493
+21.245321899775433
+24.381535689917868
+21.190681938219043
+20.967595494359912
+21.127934059530105
+21.11950241386117
+15.98364137596036
+23.358178942769598
+22.099812194495755
+21.35150771698673
+22.752080965569476
+18.983912977486753
+28.156251588564842
+23.282689632111826
+21.944679444801622
+24.786731212813166
+21.146054338543777
+26.534893123457522
+21.306759421495414
+27.587578465106304
+26.07633200396866
+20.14978500012259
+24.059724099715837
+21.931515702027284
+25.860368573281107
+25.01457637139245
+21.488154245460365
+20.27951948250127
+17.501362427782468
+17.005346014022663
+20.10446781408217
+26.418430279469035
+17.810444100126546
+24.040683348002403
+23.62868706733066
+23.333861409743847
+26.663639375315213
+19.488034132332643
+19.43478891052206
+27.152178912806036
+28.290610331340417
+19.864937692827127
+20.869365225482397
+22.21282185136114
+20.122853451413604
+23.71982501462479
+18.012352347922302
+17.54503940547282
+22.927016253729306
+24.000149271705013
+24.07288321742658
+26.397774242105967
+25.469182405722094
+19.42794616897426
+15.387636685803699
+22.396198618248647
+24.704488993281515
+18.934981353009377
+23.86669789660968
+22.890644525900683
+28.290908263603683
+23.65558854339463
+23.329306162902995
+20.99059985890348
+24.71997399593218
+20.401844500288163
+14.690421523186032
+23.765953635493076
+21.574089542397985
+22.09138177078681
+28.13125067800179
+23.571758606300662
+19.064811453879187
+27.161167965105975
+26.035879521448436
+26.521538039093514
+18.546698971683426
+21.92760680487727
+25.67813689307205
+24.417511664338335
+22.62322525125603
+25.708334864668302
+22.650856361822505
+22.351044846223374
+22.681118676893462
+28.53806593502135
+23.42607019222183
+18.369037648693194
+25.048495404527543
+23.644220852758835
+17.806380608198168
+22.571975374772563
+23.078681196232736
+24.906424090755493
+28.489149125930453
+27.49202223027524
+25.338950320282734
+23.666922973317526
+22.98131783391048
+26.35140052723189
+20.209690111840033
+20.10639608032602
+21.545155132139627
+22.623671827945415
+23.613398053965255
+25.199622027986678
+23.343478961141628
+20.83205330500789
+19.417727797686695
+23.061437936206772
+19.427628723838964
+24.89357213561908
+20.59094065856297
+23.608939151158253
+26.115389735900905
+28.07710213299039
+28.538473019150302
+21.57601509004708
+25.828001167466866
+20.827510641768
+19.159924781860568
+19.55792357034308
+13.01509942134274
+10.137734755503757
+24.815980373349717
+27.10093177859649
+21.942209898252045
+22.723964464841828
+23.918965242574487
+19.52725128115513
+21.312277007842894
+27.15610585999883
+28.541018074428635
+22.056274494795503
+24.185827086027075
+19.54249733237286
+23.792252571487964
+25.971566257517296
+25.339433394931163
+18.435528350461155
+20.108768912706395
+22.129528618768674
+18.881383041112045
+16.856247610675567
+17.16855116753321
+23.67298942484102
+28.51707190654048
+24.4008541937837
+24.566910133213895
+25.683304663417957
+22.902046395604955
+23.370396952052914
+20.41642916715159
+25.25965580513268
+24.459695129021142
+25.551064640595072
+28.560222998200004
+26.78233890803942
+26.360151882329788
+29.724180121313637
+21.741881393272152
+21.012946412808162
+26.096692515682363
+23.948825912783008
+26.287091483988362
+21.295649615459965
+22.87298167131422
+26.4680688812294
+22.31338860849435
+23.19760359853032
+22.69690789315476
+25.27527296259514
+26.03436088547599
+23.558941656815975
+20.766243174920476
+17.856597507181732
+21.651128510971873
+27.63783222468639
+23.76888494702709
+19.20603224308428
+23.285104188315316
+20.827604648280598
+26.899589317130832
+19.0552109636927
+22.850238909230185
+27.01834156522618
+23.605255527108724
+24.554654530506397
+23.83558682469362
+20.91115840607152
+20.331352545162773
+22.875186953523368
+26.87116829364848
+22.933471299455462
+19.330705259406145
+21.790499997994203
+18.81588681533613
+19.733765700300594
+16.451565482692402
+15.12827378521014
+23.93993938307095
+21.947518129239185
+27.813929090486354
+28.96909213822248
+20.152415950359995
+20.87253729437262
+18.243786877222988
+19.74514797377425
+23.061309940700312
+23.77008321409562
+16.483769347468282
+25.49724763765839
+27.41671765282672
+27.30476017516297
+21.804068890162768
+25.70613270056495
+28.439600700774406
+28.418167614432306
+31.96417226306086
+32.3849352241361
+31.310511831869505
+36.213591102014206
+35.93383827661633
+34.66024910238313
+26.153475974854658
+27.82968487250436
+26.72338641805848
+22.531653911059294
+17.00560864285829
+19.776234354097326
+21.353050419326664
+25.737227987786255
+26.03963084740947
+22.850634457726798
+21.97323315196259
+24.3614922660241
+25.799756347909536
+22.666643246110823
+24.998781375676387
+25.675050996337774
+22.620954000452926
+24.14375234465507
+24.769047168699203
+19.097122947213563
+21.299307151910384
+26.75573636859437
+26.18647456709236
+28.61993987431204
+26.862850787092043
+28.937241969639956
+26.671723779056492
+26.59572411426072
+28.152601555159805
+24.855095805354935
+29.405055951615367
+28.026034669321135
+22.260150805567235
+24.612831668930554
+23.07327699860518
+25.74901249442945
+29.597511102266182
+28.368066671991528
+27.98609731694573
+29.842794201066326
+30.269615120202175
+26.380934613911506
+25.74205012302751
+28.901379705427928
+32.03413766068098
+27.38257118011974
+22.960537824504726
+28.513147454729904
+28.893673361872956
+25.945365972043277
+26.48519131476924
+28.719328604929686
+28.566035909451145
+23.00462687400548
+28.946293196817706
+25.614373957956644
+21.700131794786927
+28.643556540654743
+31.259183481522612
+28.368297265071817
+25.483583767064317
+24.070643302076377
+20.445961275318595
+22.226160120086405
+29.16385998996411
+19.79055633184535
+14.902781359460946
+18.256297603795275
+25.7561839120214
+25.314383464774153
+26.52644649790416
+28.20305096404448
+26.670339768278353
+22.908567313499034
+24.580916750238472
+20.5169748674373
+22.16336264440615
+26.977442276978408
+20.305921683273326
+23.194738709932423
+18.68266803974244
+18.08322852781444
+22.959795442379928
+24.97257772740214
+23.234569975715132
+18.46719677597453
+19.27847882253465
+16.814515225021296
+25.439637398625578
+22.556118902578334
+19.62767607454485
+23.711649782153714
+18.863097914055658
+20.61001319603581
+20.185000355777746
+22.340139422867523
+25.125161163624455
+28.46256017961089
+24.430453464882888
+23.832969698206313
+23.34296654019174
+21.948072640420705
+18.72388632383685
+16.31440757545184
+21.005770371812588
+18.457240758832896
+24.291557863589304
+20.284613697980802
+16.58153346656688
+21.26806620059071
+22.741479158031765
+24.358859301699496
+22.7525066924685
+26.79952749373578
+23.191065189238117
+21.526770184741224
+22.11262240894719
+24.430405911312604
+21.72158480134918
+25.964137966344097
+22.908722157043655
+21.366874079525843
+19.138709250778163
+23.735562701659646
+27.09767810868732
+28.861045065522887
+29.033571636527682
+21.252752483190136
+21.054232043889968
+23.09813401445085
+27.494133004393944
+21.32057726544501
+22.847520891283395
+20.852737464386323
+25.80207941388194
+22.623764185906012
+20.521999580932558
+18.50600617002739
+21.29915049846913
+23.00150591007339
+25.396449106572703
+22.881986731992697
+23.900144740141414
+14.986969775829238
+26.54465750370862
+19.1057755282077
+23.548688102797442
+18.740137397234804
+21.88092271967308
+24.352589387429404
+16.217048610595256
+18.6564059662539
+18.506258271371294
+17.032499042325966
+26.73068167536819
+27.317390307058147
+22.728099597197556
+23.561067785272016
+18.635030182630658
+22.211568629638776
+19.57188259936912
+21.293797330662073
+18.588360035728144
+19.04279826927916
+17.157563631852824
+23.58374002107871
+22.29780119701698
+26.153664367261555
+26.451360159898982
+22.309337506655766
+28.050101238481346
+23.019358081337188
+17.88569860990947
+20.526043352580643
+21.602061043551416
+26.110295534996453
+23.922487885361036
+20.13805008429837
+19.295293406174764
+17.916024625809655
+22.690961713831072
+17.338937106662783
+20.45591842988938
+17.664442686446776
+18.21499833523339
+14.129280027820172
+18.50117007977336
+21.35175554483766
+24.286797574710107
+24.503057418714434
+26.988163579820082
+24.08962567981392
+20.68295190801038
+22.666640395169125
+25.277173443237345
+22.697179195925727
+28.27988278794068
+23.925804794645103
+15.63505532972674
+19.645632760193166
+22.12425806948839
+26.834082638650727
+25.5109088569843
+23.188265543083332
+24.019677313244898
+23.02220211913172
+22.865894185415826
+25.06222981102171
+27.20529707234074
+25.84551864906058
+21.30932695426685
+20.467566561187127
+18.842617043860216
+23.891202068977535
+24.67175933314718
+19.699366139303763
+14.101444462580787
+22.615682141473002
+17.494245034108204
+22.5441013093548
+19.219864835003776
+18.923519569857987
+23.524616799828863
+21.576483209892274
+26.75229017599915
+29.090055125770036
+42.55445521861094
+41.20324783874482
+33.42852404675948
+28.87245378596704
+27.4316954093142
+27.365554183491014
+23.461613801959516
+25.999225637058856
+26.48156856059697
+30.772532567065852
+25.287993132129444
+21.09214145965828
+22.004228278763392
+24.72483380690204
+24.371880334543874
+16.722482728026407
+21.915969093824145
+23.47989230504291
+20.42023223062742
+23.09389846671857
+20.746936167426853
+25.154562248716815
+28.044690889012614
+23.48197136210237
+23.301855410090724
+26.954053428018625
+19.30729111700343
+22.194399711692654
+27.033781026322657
+23.47206378138698
+28.945183583844567
+31.499595641564866
+43.017399619741525
+38.33146739526518
+30.517119120900148
+31.460521856492548
+30.313633990203442
+27.492185316709765
+26.233577853750035
+28.420201752522445
+22.230462404009515
+25.218239885961722
+25.060121333333953
+30.07391916468795
+27.06708440429172
+30.108779782106353
+29.294182707274643
+23.581298790403807
+21.588037396309332
+23.948837431326226
+19.817734479403228
+27.21339360747625
+26.95594999620988
+22.704329847995282
+28.17650741695215
+25.85174167640588
+23.5742651317195
+24.003123438155328
+28.886976450445744
+26.47954495645064
+24.20436601002362
+27.337511507107536
+23.82792490752584
+25.947204386271196
+26.138360195650776
+22.301239133857337
+22.022506331085836
+26.302912832061295
+23.55007398409228
+18.423410301681344
+22.817248145964868
+23.195194468856684
+25.61865991803593
+27.42867013541155
+25.87683027717992
+26.95783442637307
+24.19596403744204
+22.134760456590385
+22.633332651672944
+17.78586272109031
+20.40977236166269
+24.0344555330027
+23.316529884471862
+24.55596581951562
+21.89750908482314
+20.381751675497853
+21.73510614747194
+20.85533585250559
+23.10311479067944
+23.205851011730672
+24.16903718796563
+24.725412438347888
+23.50150575949229
+20.910333211630387
+20.64512406649017
+22.794899299615565
+27.36938319747364
+25.874211161530795
+28.39535115835028
+22.62488025109505
+23.68471499500734
+25.78517913449329
+22.400620235661833
+20.662703777116235
+22.710433676590995
+25.969623369058993
+27.10716680014245
+23.525789492484506
+14.150256186501778
+15.642547640660922
+15.914126581932734
+15.60104341065228
+20.408169631983796
+19.057909354163982
+21.58950711688803
+22.629232702098832
+26.48849915414027
+27.1091398387329
+23.69835011713694
+23.137464326046597
+24.1808372348318
+19.489781933245254
+22.58414810932831
+22.97328114095552
+21.17525569848985
+25.98070283966196
+25.874504649404955
+26.407279211398745
+28.442848398392428
+29.282992395576954
+31.14982914402657
+30.563432477753977
+30.146209201406762
+34.027735223361645
+35.34379403190215
+37.34615826257756
+38.39393714299731
+42.91515290469995
+46.249184820869274
+47.01117838941286
+49.30720960366472
+43.40975710339653
+35.60594560845574
+31.49607624082556
+24.863062879361365
+26.540675888477395
+19.542127541477583
+30.318732451606536
+29.4341778760472
+26.871546437851237
+27.443159683284605
+26.554332865968917
+26.73918907792155
+20.816564485581125
+19.43828481532313
+19.085312365977387
+22.640962963698655
+24.01639682353992
+25.595757847096948
+23.1810561130051
+32.4742392000979
+35.83003632890116
+28.865356808065926
+30.07861233843454
+29.091374595440968
+27.13687952039767
+34.34486454954822
+28.782252779454012
+26.494128390781313
+30.03118817959441
+29.982511589851
+29.13502374022991
+32.95867273004541
+30.395463292653915
+20.880438946998055
+22.955343469684735
+28.855541423242244
+27.800689169691665
+25.83150039496772
+28.729510243545775
+26.15547273706224
+23.266823162789308
+22.590384761551462
+21.916295221089754
+19.359028306416818
+15.09642235409089
+17.904821003772625
+23.219700285125853
+23.681206168166867
+26.243958645982957
+28.995572025445583
+31.801466313255787
+28.45612688869072
+30.224174835760778
+29.52080303497081
+32.677979487573865
+33.48912578817199
+34.871347660835326
+36.84109736174244
+38.21965715402466
+35.216458000706865
+35.45571126225717
+36.372970078189056
+30.80372635851306
+29.839754240141417
+27.153772700144827
+26.890844593048456
+24.734696089940243
+24.04385394405766
+21.37436961441577
+21.120917215506253
+22.309299506487378
+23.398192618194045
+20.494382912837935
+23.852281556388164
+22.737233875836623
+23.962017878889753
+25.24878958177176
+23.305427690427777
+24.013990569021473
+20.493188295503572
+24.255972404957376
+34.99288862793492
+35.66772427034962
+38.070827486470215
+43.52548242754922
+39.93485798383676
+33.71076840956371
+33.638974491065014
+28.33534918218946
+32.619628907923754
+36.055948987865264
+34.092532664264255
+38.85712675492731
+40.6259321867486
+38.18836764406396
+40.40577777078787
+41.40141534997438
+42.4058757594617
+40.2036685747581
+41.58685851296267
+41.6548062913016
+40.843029150180094
+39.6732652277827
+39.933208088966
+41.00742581701726
+39.51520059230276
+41.45893381124684
+42.11834776267478
+42.36780626823765
+42.37453982961232
+38.05714566057012
+38.19105501903378
+37.525636973248396
+37.480074514771616
+38.98951898395963
+36.44816268797351
+38.86470837002852
+39.287457741870135
+37.579736272016206
+36.37131818824139
+37.827277492631524
+37.33421575040536
+38.59695623339344
+42.923804074798355
+41.46407811230789
+40.04219171271894
+37.56398584119395
+33.29852986023174
+33.99903941685196
+34.51269542785968
+34.372962706436226
+29.618279090226693
+34.4303268272492
+29.599629423207446
+28.517518498559426
+30.78539114341929
+35.179933429751955
+37.487649140127374
+32.89536317764525
+26.92115444966828
+22.54047686597346
+18.117419049975766
+27.25563558494798
+30.165367735464216
+26.24262597168469
+31.43887832304786
+24.657361342865016
+30.563012706255066
+32.98023003621351
+27.691193076396402
+26.83074080252004
+27.146830671164338
+28.30257876357895
+26.24605776608847
+25.480736407339336
+25.98671029372821
+27.46057123103462
+28.341562978309142
+20.602100561505907
+26.388484789332793
+29.676362652859567
+24.45393022988992
+26.745138820481657
+24.479725431700032
+22.719464905840866
+19.498208228780385
+26.81060921203448
+24.788638365812034
+25.860448838088416
+27.30308205573145
+25.542250797160122
+30.945620474080485
+24.42177194664717
+16.877182135888233
+17.75673197953283
+20.8960755342153
+22.37334457939876
+22.46072365155429
+23.88698308684522
+26.630956194737053
+26.281141822511074
+22.423327406061603
+21.106131174131804
+18.639867167552737
+20.571470742711213
+19.74949522504096
+24.20965860506385
+22.412520958763494
+23.195504845462366
+24.582080343881117
+27.153010666384873
+18.994879981808367
+16.258926902710286
+24.838149864061947
+26.080152059944822
+22.634760956230465
+20.95656496949239
+23.748589371158417
+27.839043472434653
+20.77233444299482
+24.156011000987135
+23.89743985526792
+22.456378419137096
+21.060163351766775
+24.200516510621227
+22.82264380152617
+20.3386853735136
+27.05293745213058
+23.71158053155439
+13.701761874968057
+16.43100254917981
+24.470200103690985
+24.52333105118528
+17.36879814788297
+21.21607707776981
+20.60842529969952
+18.94760554424643
+23.847387508162754
+20.591788232699002
+21.051445501866056
+26.426560772600297
+29.81046872345985
+23.456033353696952
+25.300627583719574
+20.19659862430258
+20.81049574525484
+20.242506646932995
+21.606217724905292
+17.29318935222328
+21.381943745113205
+21.79223551841433
+19.539691739190886
+20.6834196754952
+26.073800703010264
+23.90531154793011
+22.359214395320066
+23.42548789254859
+24.553237348488963
+22.482581160419386
+24.822535375880733
+25.589500209084633
+19.15485677173031
+21.129145914920713
+18.867454067714107
+19.023757046945207
+19.36902749052804
+15.678404843311014
+12.762450762400277
+18.246170769784086
+21.35938231798623
+21.659466102774942
+25.10966380477049
+24.103635912332564
+21.696742163491336
+26.752919040485097
+24.002086401014466
+25.947478308045547
+20.262969195568544
+24.95647750523058
+18.776809006468525
+19.815922409985646
+20.55526154934539
+26.631261226703415
+18.066591833588177
+16.527754034859115
+14.760784879550783
+23.331822293327946
+26.008574140646942
+23.67211009035738
+25.78926022425287
+21.692107405979854
+18.07657072226459
+22.443919651826832
+25.860725372228003
+25.795218265990385
+20.41542930270137
+23.43608663215089
+21.931261382354748
+23.835083007334774
+27.011225345746297
+22.61130331737668
+21.904823247070112
+27.156234634442768
+25.762992466722665
+20.125352798745993
+21.054119342729905
+21.048796921891338
+20.433598614772947
+17.939632864543825
+14.78946975191728
+24.133480157918683
+17.555612662747407
+23.639490187819007
+24.605564772190817
+23.352935171071422
+27.68848163568262
+30.381222046995518
+25.393977372827905
+23.309752011559198
+22.26064455428704
+24.073931951237128
+26.515032481224893
+21.835397100612298
+21.915222496426054
+18.667101096928434
+20.299064802790255
+17.767877533737945
+21.110969453520212
+27.560578428838383
+25.864937059289133
+19.394380389979418
+19.813226618129747
+19.68245318923762
+23.05048485882112
+23.33393415395848
+28.22908646806482
+21.645265885318437
+24.929701204467108
+23.910270764433463
+23.107353854181085
+20.30919611613278
+18.570964113143503
+20.91010110495074
+21.81182627195166
+19.0871917014928
+20.070865685196964
+27.088797066838353
+26.039361357893682
+22.010392619703552
+19.890710861899393
+19.822504024280363
+18.849406549667407
+23.708387959617383
+19.16861668047933
+20.97831529901694
+17.827201764811875
+20.17876165732295
+19.05643906936517
+18.45340277711051
+18.272599759303944
+26.592242743242323
+22.965516057569403
+25.101250925383553
+23.964437333826368
+25.24638058604127
+29.513548279551998
+26.947247650991315
+23.937510605082153
+25.64371007659709
+19.207871877745745
+22.82321522219378
+23.14540929655044
+24.329451511475142
+23.77004063876349
+20.078846317750205
+22.295450102221125
+25.133804110735
+27.243434609037195
+22.379421160103774
+19.795010202421537
+26.07550873585403
+25.286334145640254
+20.085994199150534
+19.933555107381892
+16.368774543888776
+22.15207654988602
+21.05176657122165
+21.831052119363406
+25.226690691733296
+18.17954061524837
+23.307169440494775
+22.204085088314088
+23.92280296231607
+22.513600502473423
+22.03926064109237
+15.212854332121864
+21.581587943020182
+21.82560169348865
+19.18645849774876
+22.434963025892472
+23.307789983576967
+24.830459914616014
+26.897803919318434
+25.191411461244698
+28.226745073481823
+28.130408246337808
+19.895590459787755
+28.157612658321668
+29.07323070502912
+26.607745745015606
+23.47485160989585
+16.484605199862443
+22.448460508423807
+28.006473587308662
+29.79216147838123
+26.54848362165903
+30.281863307359245
+33.6831996807245
+35.74808120889806
+38.33998833427023
+40.87923896684245
+42.03235664178904
+42.61777568133434
+41.23384729991217
+43.29820111526255
+35.35616355808219
+35.006769371226596
+33.49795120768816
+30.94463963887334
+28.749513592278063
+24.297804099323628
+26.113933377145756
+23.922476645956763
+26.276437040762843
+26.47458925468051
+25.903418691105003
+25.94950261070231
+27.299916602013923
+22.718717819755867
+19.87412190529092
+25.40692290151061
+22.643445892357164
+24.595592632970806
+28.4632977580618
+26.860773495165276
+30.10772213898032
+24.70928516594627
+28.0883483034479
+28.20212683322974
+29.88305895265816
+29.30541792935182
+29.195902684462723
+29.493413190189656
+29.435025829818855
+27.071268414214288
+29.39222930633879
+27.103601882376765
+28.32453170099832
+32.527991194971335
+26.75880442123014
+27.559198843356498
+28.631293017812993
+33.9985567381821
+30.597425799088725
+27.337591169698683
+31.412099970737273
+30.83084803877199
+32.040230773387705
+24.360392024452935
+26.02116263071612
+25.122664719847933
+22.05979459589595
+23.314436795461845
+27.388035224989423
+31.044035057340764
+30.99941452491683
+31.157790428882976
+31.677647815555687
+28.908865240876665
+31.358900628548597
+25.637247288725575
+26.471404470459092
+30.748034987087422
+32.470853054403236
+29.564107062329967
+28.90841761386713
+27.36947791989259
+28.1217007974781
+28.23932084391059
+31.47269158882925
+28.247695747665645
+23.485821074331085
+25.055966217807025
+23.039890493052866
+21.37570352061128
+26.982368999505724
+24.842438472637042
+25.850726834991136
+25.297518581239373
+22.667252486612995
+21.50958807430638
+21.71627713554284
+22.173357996168946
+18.449306564240942
+22.238364229905613
+21.99899135073889
+24.147053761185646
+14.23099301985016
+20.893847155688604
+23.937195740871474
+24.984377186178605
+20.58054401931102
+25.85736097327826
+25.419007178734248
+24.473378450428854
+22.403418760964044
+17.62927788689359
+20.72955748877999
+19.703605099040544
+19.174657306606278
+24.524565389681513
+25.23880483718952
+24.317950107397863
+24.88185484240971
+19.845373474109678
+21.44446778776596
+21.72931392929908
+24.475773828395248
+24.326522870297055
+24.25729367089174
+23.41083477126213
+26.281501234074867
+19.03407213061041
+11.816387380274705
+22.253412211528826
+23.7645419848039
+30.376570924256512
+25.345315375270616
+25.015737298208933
+18.960277613880237
+15.730613004056451
+24.166309359316188
+24.040159060229456
+24.407547692387723
+22.328194422735578
+21.515679776493954
+24.344427965030718
+19.929671078323807
+24.50307555148737
+26.764501850379105
+26.866350095277483
+24.517886958536295
+18.85654242049509
+22.86508735297825
+23.54433613572266
+29.17391130822594
+26.8285368409543
+17.573313915504613
+17.444436114417712
+23.49839565869121
+22.619219168371927
+18.19324548466024
+21.60548268212098
+23.305506706827302
+21.75179135120129
+26.77687391694316
+22.922973961469708
+21.796725960647876
+16.804000512416266
+27.162728801350426
+23.735333244301458
+23.04462025715263
+24.442278728169597
+21.670839591617394
+24.414005442850993
+21.450689106808838
+20.11212383560425
+22.12948799465464
+20.642710378796608
+23.642730448382352
+20.74956668991318
+23.15504082588687
+21.842256245242467
+19.707378086064352
+21.113354845547107
+21.188612808645075
+25.718010083664026
+23.488295471520658
+22.317056707985117
+20.3333200112245
+23.179487027561905
+19.494199615958067
+24.33006515682726
+24.189213893824245
+23.96411434890109
+27.549493855650752
+24.50705962217168
+20.48292962884969
+23.885524431091497
+25.63802285061935
+27.95136200676876
+23.891845859320014
+26.996192264517504
+22.867392173252924
+22.012255450981186
+22.079783532789705
+23.630750277577093
+26.685796239848145
+21.885065544063593
+24.625485641092936
+16.080786743303193
+17.973583422316707
+22.068672318319898
+19.741809449593077
+25.613003833886026
+25.15461612252774
+24.293152246737208
+20.84782201069966
+24.339447848708758
+25.153888375023868
+22.810630775388788
+23.230034990027093
+21.955363177075952
+16.585031315697364
+16.58535747881207
+23.798078879233742
+24.450228866760014
+26.29694150216922
+24.57718571036051
+21.539072165621135
+24.835218482849612
+22.070820689425815
+24.391816807697452
+25.93804983341407
+21.478482139005067
+21.167890184101566
+17.845308043740985
+21.754806440701742
+21.47011758407244
+23.867465745030344
+25.629410445872153
+24.113962309780092
+23.745572108360307
+22.330509219379806
+22.73259827945678
+20.019142313192404
+16.93147513352102
+20.047656192179915
+21.41114690554045
+22.265120997562775
+25.196850699433853
+36.61826267565158
+36.47202128881122
+30.287683810544777
+23.112501611636958
+20.422764801133695
+23.77627923122658
+14.051715581440675
+21.05911029867913
+16.1091964283914
+25.145509609069606
+28.357289900018642
+17.775247921240137
+22.423494094022104
+26.644598422407498
+22.974476937205964
+16.213128637977974
+18.022263506737772
+28.189437972053497
+22.505634146163686
+21.914483989172922
+21.940141437953258
+18.217069311338008
+21.625365460027623
+22.374420550161076
+18.54624415417679
+19.718184750395622
+16.152793900423475
+22.068496473199744
+25.719534811666094
+23.243967732893665
+26.719967795040816
+32.241763860438795
+36.89358478129542
+33.70820755218193
+28.752652036048246
+26.355622550835278
+28.372156862250122
+25.65829228583624
+24.780815500981788
+27.37727710451979
+19.50996531025318
+25.073066723314383
+29.672173450353895
+30.704338000242345
+30.93274877181763
+28.290242825889507
+32.306324110549085
+26.058638306668087
+24.63904014727538
+24.32662960623348
+23.626938548045686
+26.009100239871316
+27.322166429551572
+25.026353039070514
+29.157382942390896
+24.968969983676587
+23.960376934894768
+27.526711914876657
+28.16320389395925
+24.453697980112835
+21.03170316190203
+26.32123377082881
+21.82694609728979
+22.481119948841126
+21.392823909180663
+23.262175939192886
+18.111734741811787
+21.426203603991468
+24.42498068038661
+23.759124933527787
+24.41100687621274
+24.381743330528394
+29.303129052688774
+23.870429021055543
+22.70727918626973
+24.948817896532873
+26.858306100785697
+21.858991131211795
+23.87665290889572
+17.181077029628497
+18.686832693999534
+21.53833260860563
+23.592567774546097
+20.332416264655592
+21.812657066471743
+26.466462082276408
+24.701951008798517
+25.130080647187214
+26.734437235946714
+23.68273809974157
+22.50044655564686
+24.16384606869191
+22.257625437473223
+24.26985187605267
+26.004000380651092
+21.12649074496899
+21.38141038505772
+22.04721713678549
+25.060317252812453
+24.466124842926448
+23.831556424022338
+24.16962368401728
+23.287469447528338
+23.16389477340283
+25.34500238519074
+19.497173569250904
+26.590960963829062
+19.41067737146234
+23.969940882525734
+24.589606362463016
+23.46303870581302
+21.053026181638373
+30.30509338290382
+27.632144655006655
+19.143392701755985
+17.981142747535642
+22.427287164372245
+22.976136510325674
+24.80423503760089
+19.929386459857895
+22.672190841628932
+21.51113853303478
+24.287587566342538
+25.00978620695379
+24.06815939202791
+28.400010833190777
+26.465760906532495
+30.19869711784824
+34.73993817629332
+32.399172801855414
+33.20040210072001
+33.97317972369953
+35.783602513420405
+36.79066524248604
+38.008284219153296
+41.28500066596476
+44.42277293543094
+47.23646627438241
+50.60047580327273
+54.151342568092346
+55.33391375214521
+49.5344965550492
+38.7260889938984
+32.96680067297886
+31.970463588877422
+27.242515409818722
+27.07238989689172
+30.490736434844166
+33.085217529708444
+24.09160050964583
+24.01919318131185
+29.82620369755304
+26.495275234492198
+20.860356656699835
+24.56886300020372
+26.855590474657163
+30.5758219295125
+28.794093733252495
+22.606698913603154
+28.23636792254102
+41.70051680087204
+45.56931137261171
+35.24477612392164
+30.978011359909218
+34.92827962127092
+30.77256011676893
+32.22445584544809
+28.343830925722685
+31.479207718672058
+32.74292253304566
+33.76483756765482
+32.19181674773212
+31.19329346103804
+32.59783629114881
+28.16645851612556
+26.990344975889883
+29.5514528777217
+34.197492030239474
+31.64384721181065
+29.318611777056987
+28.49642719579353
+22.575087933598823
+29.85187390833471
+29.193576868445078
+23.059514122746947
+19.180325524774744
+16.592359129888337
+25.313207461906032
+27.883642616920255
+29.43254909391696
+32.20331508747421
+35.65210017467915
+35.205166486999275
+35.45274050568156
+30.909880117086956
+36.240133213851706
+37.939853059436
+37.54872801406769
+39.40076615773806
+40.13296010520466
+38.02869088282111
+38.911821343800334
+38.9402396009252
+36.28304077815689
+33.10562169080062
+32.127526812194986
+32.01679282766462
+28.000602164384773
+26.724252558845933
+19.65275938434428
+28.631306611094658
+27.190125757200704
+25.916851951886812
+21.814989733723365
+21.07149495807984
+25.297028203895323
+18.87925182418026
+21.917906072316313
+24.297824099149366
+24.395908485000703
+20.48648438323852
+21.7837296424825
+36.88308499245181
+38.949704642673574
+43.57009127944077
+51.129044562056535
+45.92079754315425
+36.461363126981894
+36.81022158035681
+31.722448864648584
+37.78774051797129
+40.493962183628575
+41.41847329867498
+45.83228924326531
+45.50464971193259
+45.96050466204056
+46.17168744287175
+46.88114333368537
+46.499341059966625
+45.64936927747524
+46.63230123718596
+47.27632173267894
+47.08743331951884
+46.90174972286654
+46.72368461734012
+46.33479125951409
+46.84708242601111
+46.978587683516785
+47.2332393064603
+47.862138521966024
+45.95049237998898
+44.662326995205405
+44.804304645680645
+44.376656256856954
+43.22396379198203
+42.600596555135496
+40.502068547763514
+41.64475161083113
+41.961645344493846
+40.831191845004845
+38.56824540327877
+39.63582442728565
+39.216764115700485
+37.60460227705157
+40.32576362623868
+36.676652104147834
+38.52302419541762
+31.555869756362156
+38.511109031481766
+32.4426854082334
+35.30808468195771
+36.13465714238821
+35.38282603555837
+37.2111283465067
+32.810557813343436
+35.37255604386796
+36.10426190740168
+29.518961406249716
+36.16771652400861
+33.11598983699888
+33.70121347393987
+32.03167666513022
+32.225837185080294
+32.922946586373556
+31.426423916560395
+28.776669556294877
+30.766541325513643
+32.510283422678526
+33.97303903903709
+36.20432738307825
+31.211235154176464
+31.386005120315602
+29.737375716531133
+29.606417250586944
+32.43007753451447
+28.94323476698291
+31.85060572957248
+28.645423486195128
+30.95709442117537
+24.801629533753953
+27.648874896334135
+29.698125404611034
+29.705230048509534
+27.739304238903742
+26.693285012192888
+24.923397440010874
+26.766689195482016
+23.956807375541175
+23.967748630886533
+26.37879796443555
+22.937775021364388
+27.22808745773945
+28.35128504587496
+24.932957457527237
+14.071307736264743
+17.153845181979662
+24.612811045230472
+25.417194238185516
+24.508700488309813
+27.022744480544816
+23.820399380414116
+23.26681184770611
+22.13465237325451
+23.852117539495822
+23.13683255091668
+23.42529933785032
+17.069827342711363
+25.31406360980715
+25.609733766812667
+23.803796911945554
+25.99605792509128
+22.468100304220627
+21.016333841266047
+22.843228035942786
+16.811653235141378
+17.626093665448437
+14.887608260890389
+17.744201304378706
+17.142325724573197
+25.74362764568407
+26.078591149713546
+25.348919988816974
+23.699291621816897
+20.19695875201114
+21.184090073535785
+28.472669848909973
+28.969531464654324
+24.386754998680246
+27.023551723861615
+24.60146731609538
+20.42552990907349
+22.25187328701665
+25.718324310410267
+23.31970097486648
+18.97893029983193
+21.01329388898165
+22.88721045370457
+24.780000646376465
+20.856886082007236
+16.610177984249177
+19.7395808332395
+25.839551920178607
+26.240743402532487
+23.42824459427814
+24.524616367970452
+20.262505114047826
+23.997644599489888
+24.95318078722576
+19.710623577879062
+17.703654690609895
+17.325250003507378
+22.118383467775473
+23.466516894200623
+18.48578173820475
+22.80946055305614
+24.122008774646716
+26.24102868307625
+25.088477883557644
+26.700096010765307
+22.89453638926912
+23.296899943420655
+28.586495800463283
+20.700050062022157
+17.38064841864481
+22.822968702233638
+22.606872104267353
+20.95369925606387
+21.154991815351565
+23.030320043344304
+27.177713306998058
+24.46697357063111
+20.664007995184477
+22.75243792580828
+21.623876817800223
+22.098355390723796
+23.774086783729217
+22.726103722783535
+23.017004141940106
+21.243681318872902
+21.952324776446304
+15.237735476114835
+16.124386267391273
+24.31673518171381
+23.05969248537548
+14.938219868003458
+12.370178779041083
+17.63300499317971
+22.92152156164296
+25.816904477693853
+26.14477445407445
+18.428108008838663
+21.233188276235268
+27.133326214082246
+21.16793706307284
+18.679546415891267
+17.302277141758296
+18.045900752387325
+24.819555897489394
+22.204200689913975
+25.64868634122982
+25.381674505205012
+18.869801445748763
+22.466336240950028
+30.260885359425572
+26.325278997415992
+28.34406311435231
+21.714263342870098
+22.16735923626257
+14.798056346852789
+21.014921114354436
+23.188816035152854
+25.604495170133106
+18.178241093721127
+23.58299161214049
+24.64597727957141
+24.088255745798435
+24.163905348143032
+29.593079509496135
+25.137871649902124
+24.43791024143725
+22.812517605221842
+26.138035346096444
+28.11603817452003
+27.096211821528783
+25.786930437092636
+21.838283804674603
+24.3848120217081
+24.735128599150627
+20.814942261857823
+24.123255703940643
+23.50519480674329
+22.285765113504368
+21.311518067573687
+14.856673071197534
+21.31319035412656
+23.682748083824848
+29.197747301709853
+24.175538276213658
+26.636549455392895
+26.56046952399575
+23.285293854112496
+19.464768123122752
+17.645661274360336
+19.38387632192854
+24.38348945567128
+20.863526094251498
+18.229557250536956
+22.171485506652132
+23.060913218883613
+22.40774137391331
+19.665878845038876
+19.595499728750113
+18.105099805656195
+20.751240497453708
+16.783901949772357
+14.59344966192424
+24.12973905653388
+24.546921108339973
+23.315738387874532
+20.049878488420347
+14.555412181404321
+18.537624847308493
+19.653438203213582
+19.43816764652813
+23.222711231800773
+28.86062532696414
+25.7050783044141
+23.964163798567952
+22.529206728022288
+21.774085688926206
+22.09599832141359
+25.316091995042356
+24.366788595638525
+24.077133665614255
+23.67316137526582
+19.52670416476711
+18.93664121561973
+20.894038358544734
+24.913530048637895
+21.243354329236993
+21.77906795360974
+26.479311783316703
+25.18229973355554
+24.714447425168487
+21.50273565934104
+21.113354098927758
+20.99537151832864
+24.63702468940629
+27.398686727982778
+25.735225146707734
+16.509104361096192
+20.626545166455287
+24.656943662040874
+26.627792828711918
+23.234888160959002
+18.733092899832542
+22.954839109236886
+23.40191431624494
+26.07216064276618
+30.427901436499084
+28.598695672232026
+26.02121500950723
+27.80151807262328
+23.414312377669802
+21.30501842698746
+26.71904700414987
+27.056768290162452
+24.319098299916888
+29.553108290609913
+24.93405432074762
+21.932202404676502
+23.436756180620463
+20.000146216049487
+20.354343058860763
+28.506662999198767
+33.814759823483655
+36.27311013556222
+36.960015522476496
+37.546564824525746
+40.5551381216469
+42.755847501672925
+43.61729053532055
+47.83706778435028
+48.858746138457434
+50.13334593751732
+45.957276062282
+38.22856611316671
+32.781473209693814
+33.442829356569774
+29.449111939624615
+30.870875177521995
+24.251117402227038
+29.300985929816093
+29.122348569615085
+25.089572491070484
+22.51657860184072
+23.771951315946083
+23.268880172006433
+24.318579989140176
+19.813530945021213
+24.282645834173948
+28.949892544243923
+26.487240877807096
+24.07170523910729
+35.46358631967793
+33.89192643165789
+34.198301943408254
+29.543329876783204
+31.395315508930707
+32.91536467436647
+33.523425401611064
+31.558383793441465
+33.29571040173259
+26.96743271115818
+30.200992968053285
+26.97995953898281
+27.88244560725215
+34.02037581107969
+28.988672718876742
+31.058328747503666
+29.634586919644335
+30.236388236644885
+29.956023724008887
+33.86812620155216
+29.874283071370698
+27.713176082557894
+35.06926982604698
+30.433555936830103
+31.42411526221899
+28.042627327596847
+24.755220387634907
+29.691409020556705
+29.095144972823235
+27.924059308319087
+29.2205708626378
+30.605533893101466
+31.967880257196313
+31.94494583154392
+34.22941290159909
+30.46233051118331
+30.3212289834961
+29.13481867144027
+30.478078015411555
+30.56634449938329
+29.952639442064864
+28.940761713732613
+26.47704187929031
+30.809813967882178
+27.490265944254844
+30.930947793562424
+27.681256204907086
+27.28958761225917
+22.480332843721214
+22.549856273244828
+22.17229998810687
+20.20517357453251
+21.969603353657902
+26.28716308290163
+26.730839906222897
+20.82247089745968
+22.380778053475368
+14.828631439655993
+21.768314592264787
+27.161528696050866
+22.141851816812135
+22.764726050647923
+22.70166023975247
+25.621095260847397
+20.373375981214352
+18.97997014424125
+21.48963281465329
+25.73400737780348
+21.717766351598257
+24.11770257115323
+20.321114259061815
+19.24551405155873
+19.49288687691127
+25.563369840432088
+28.518489612413546
+23.103732901021345
+19.25644478665835
+20.33634018600746
+23.466046874729102
+22.439907825566692
+23.33254697824725
+24.802923281969584
+16.27785907152213
+21.28804871188285
+26.564072035506
+23.482999296584325
+19.554326547714126
+22.95660176778317
+24.479608112045668
+23.764184751922954
+24.99644683277299
+25.841294258346466
+24.732925256584096
+29.64791133743107
+18.947528919669097
+22.526695832963625
+17.32471688382296
+17.97137849546688
+20.47597755848254
+20.0038882032931
+24.8034323800874
+25.02753659915517
+24.750526290128406
+22.68134399412888
+18.338923403063703
+22.724156606398523
+23.51533822184139
+22.86302380077568
+26.68873726077007
+22.059191285431538
+25.53016825994348
+19.908026980809424
+19.881634166516022
+22.18956655310187
+18.876986888175352
+17.915476909863784
+18.450039023515927
+19.22471356692374
+21.748966051785402
+24.202386448812135
+22.07344298202368
+22.9254230356609
+25.987637054342898
+24.034919838579768
+16.794486820459127
+18.994413077236302
+26.700496155638504
+27.076612292519613
+25.109968015298733
+24.504585519707348
+23.73742195054902
+27.577634090642576
+23.983771350318378
+24.103188002524234
+22.677582352527267
+22.33831640617737
+24.861235026484067
+18.892617385941932
+23.73604891746838
+23.13927068073984
+20.86001034394269
+18.92737147204251
+20.738283241531306
+22.63781565815482
+27.48744928000046
+26.3045888069868
+25.599427795999773
+22.650950323591886
+22.58802203608387
+23.95779528447285
+23.321622656928625
+26.65011489300764
+23.950685979740342
+23.37324187177515
+22.72926869916587
+22.70260584885652
+22.982745945620778
+24.788412600072206
+20.96578287012497
+25.749601853186718
+25.12070465586652
+27.648163465595985
+25.40346550051126
+20.94622517155848
+24.71005870950401
+22.47774346130406
+22.71841585782569
+21.38521960390794
+24.291306532861242
+22.0278485178157
+16.96430790908157
+25.426295036589636
+21.11145220760021
+20.944312997596825
+26.80167014791182
+25.73588668856756
+22.51191566238802
+25.29884648339292
+25.0101967752953
+24.767535277498084
+26.062363733333243
+23.162471296071175
+24.350884570125928
+22.288702945872856
+21.51965363080707
+24.153947294173136
+24.20482625739332
+24.94389269615344
+23.086460503658813
+17.568150665537857
+22.62913629925329
+24.92100055890178
+23.466353993032442
+26.245441575040005
+24.014256766765058
+21.886082024674764
+22.69813839137487
+23.372721123419495
+19.677169332723096
+23.513741000886853
+27.21149810435496
+20.780610812258047
+17.3548647854099
+22.20654741169082
+23.006939365733857
+20.41333094351684
+23.46485707435896
+25.44683748367838
+32.6517532966883
+30.92739793226609
+30.089695212266705
+25.619176009667385
+24.67336809353516
+23.575406437362886
+15.163546269741829
+15.035083806961566
+18.308491107137243
+25.845582976101156
+30.350831277620372
+21.116001593578673
+17.280777503450082
+22.496122282541748
+20.752359421129682
+17.613119162906614
+21.358160574741575
+29.214065020444465
+26.40932000628065
+19.9253906430729
+17.980634903916282
+18.509256929022413
+19.116078294877
+21.86258282241981
+20.700520074555627
+20.58181067041515
+21.520914135573463
+24.818200442402343
+24.445720152098687
+19.253432537127637
+18.48711490868378
+25.274779483553516
+29.494309850559503
+25.086352238838103
+23.6872859948504
+22.995783515392688
+26.219611840751654
+22.678397486245217
+23.694591560148467
+28.00796792472623
+24.653389927305156
+28.515173885092295
+33.28174154366165
+28.199690030536587
+29.04367944660116
+31.401725640430598
+33.57402918917579
+25.705591574596184
+27.190732235233313
+29.649768214384736
+31.593435839111947
+31.722414895062457
+29.324127668336743
+26.340062051161127
+29.785983610342512
+26.484934051386873
+25.18626835880866
+25.610861773322014
+25.61350173202699
+25.509955031953282
+22.881551084723085
+18.69910115354601
+17.09877498480553
+25.008215533410265
+23.5776488764363
+24.526977489427537
+19.257867340311307
+22.042957836509316
+20.29059384392653
+23.09567878722457
+23.577897032204234
+22.392320717193172
+27.907619651501832
+25.155109235523355
+18.92269075337387
+20.15859310859689
+21.95438951854669
+17.128902259622194
+18.664111825210924
+20.267529635032233
+22.194996301992973
+20.58179663832614
+19.221543321490728
+18.080597546397158
+16.351242884602968
+21.00439474855534
+21.416024494877846
+26.269632838644455
+25.302843647226766
+20.87565157559972
+19.90961169517169
+22.974668872195707
+20.57317527606341
+26.068237048977792
+25.280454952949015
+24.499849875180374
+18.899952947823394
+19.252462380370687
+22.302515414012944
+20.844127785271084
+19.02851440512319
+16.699501867986555
+24.34357301553743
+24.952477539477954
+24.27811131003493
+22.187731249646944
+27.020071616939518
+27.887454611517796
+26.589437426996383
+24.42407285067499
+24.45309787331138
+20.12674947895796
+27.8102632819774
+27.25758502886987
+21.04436688799879
+23.58374160744387
+22.84508024699562
+25.358751108181806
+27.102152659499794
+24.325105500646927
+24.87837737708604
+26.470508326443394
+21.1897588434024
+24.103912577567968
+26.31390341213954
+30.478722360386442
+28.984509074654753
+23.47883278732094
+32.8455968043819
+32.81719783445794
+33.16511463831378
+38.41854939993404
+39.8721453958237
+45.79248345848235
+45.85888720615033
+46.19034974299382
+51.81792427292589
+54.0856858059606
+56.270399398534344
+53.55645812544494
+49.55791545564412
+45.53439372842773
+38.637638198093754
+33.020876107927236
+34.54234840359855
+29.972261597441445
+32.327702483649205
+30.33535803540302
+32.484239904873036
+24.9324735586478
+22.533517676916603
+29.084272686932493
+29.840915327643387
+30.91339730803398
+28.940791129984817
+27.133823129164796
+29.552107649530242
+27.497780095951143
+20.56836358281626
+28.867078547782683
+47.87326014840372
+50.727082383871526
+42.36371290256973
+39.054029434873094
+42.403435953805214
+36.729532538052055
+34.66142755500438
+35.210127151981055
+36.95877314746333
+37.821364833163905
+37.048804833583006
+35.765052030877214
+37.89960172573893
+35.91577363376011
+33.480073346592576
+34.105044209711494
+33.70405471243539
+37.15751113563941
+35.721725018895754
+34.72513182767817
+32.79243276522419
+26.853170476979372
+28.84407893493021
+26.279081197869274
+23.74250629465641
+23.14268059089514
+25.883919013528953
+24.258830898954088
+27.44167075173239
+27.218065151909386
+35.32093960134728
+37.509676627894514
+34.69741195126454
+38.934138352558826
+34.44891068672162
+40.001828813338584
+43.19142485039356
+41.34791527005691
+42.93209419073924
+42.34355800004048
+41.12827051484944
+39.65091517514682
+40.76555116946136
+38.096284650906995
+39.8983677773638
+35.91041634614756
+30.259979676577032
+30.288019390507984
+29.97831527682736
+21.93746058961328
+29.275429663609586
+27.84745994456135
+24.05650633454316
+21.525336461492145
+21.14074421318348
+23.731745526847362
+20.041969412472568
+21.31050602745347
+26.352421955436526
+21.578339269711293
+22.687540207595987
+23.13681615051111
+38.67070881923346
+41.288827017739884
+44.19825630534833
+54.41206499486532
+54.14041367423733
+43.20103328078316
+38.411951294254074
+37.16729755059849
+39.871095223499296
+42.01618827257758
+46.1861615299854
+48.4271402680564
+50.895969425166705
+49.157757910064525
+50.29024970931713
+50.29427052569598
+51.2140124996317
+49.99090210841328
+50.82002351999509
+50.45302520352612
+50.75600406160274
+51.35997131661123
+50.973586874672584
+51.323466016409085
+50.29610433402979
+50.41060760214775
+49.52379840139933
+47.74811613136527
+48.14504316358521
+47.291856762258945
+47.261752391782345
+47.27407715077326
+45.588180314507575
+44.379140853087854
+41.782557778716246
+42.00499718221268
+44.57420743905166
+40.19148238946421
+42.94712731895315
+38.252871122551305
+41.155013120939614
+40.04551863153051
+45.78204613098167
+44.61369249116761
+44.24327975573054
+37.95016188192125
+42.42428919125004
+38.21818865357094
+39.149554193916984
+40.110244328752955
+35.02013873465326
+41.576516805300365
+37.66419272354443
+35.07760042968923
+36.745456562755706
+32.78476295583695
+38.08055125472873
+34.08711384532036
+34.331980001010834
+35.49800147348003
+32.92540579339558
+33.2691754577812
+33.67259927454876
+33.53972105763505
+31.517453806593906
+32.51963008230905
+31.899665460368297
+33.8765142534873
+33.51221090142869
+31.192388081753293
+34.40627725500788
+32.915407826441324
+33.946304116635574
+31.23062826197385
+33.90124267990451
+29.859144656024228
+32.56474221478838
+28.618323776960054
+29.916415504760423
+32.068971522535435
+30.86471314746116
+27.142651497726504
+26.20993679487414
+30.884956240204062
+30.143836073037818
+28.946643528471455
+25.36145084942305
+20.633979770725446
+22.41565439076018
+29.446126394814087
+23.807301290941965
+25.780010178637085
+24.89450365010751
+22.105592400494388
+22.937989786022868
+24.64769755741726
+21.953710162091355
+23.54078607585616
+23.989822299090775
+25.838159073416122
+24.433768871988903
+24.106550523878695
+25.745375487858553
+25.31290239793624
+24.082372012127266
+26.605767575960854
+24.81989617698305
+22.02461119572874
+19.863797669771245
+24.920192375162316
+21.442899440335054
+27.136383771978004
+19.620058833023094
+21.160863852936032
+21.585494699826853
+21.61654711730891
+17.00622974179784
+21.297600318372403
+23.18723038606035
+24.001354940458555
+24.725106042902723
+21.15092237546412
+23.162737562992703
+25.91961822673329
+24.97327614759601
+22.016698255869528
+25.887378094814153
+26.106199368612877
+19.807424590925663
+19.07271538456449
+25.324268628272733
+23.306745587694536
+25.608355621236953
+22.729751890937322
+24.332953495896945
+24.240245086079454
+25.65655218457816
+21.626863745452624
+21.452138783676318
+17.38642206955852
+20.34934320136179
+23.23650391498316
+17.61041992662453
+20.589827825305832
+20.054231595560694
+23.28866414527363
+19.62524952826645
+20.540683201520466
+20.630565035782368
+23.14282934571378
+20.773964869366935
+23.880224924866155
+18.105585141379052
+20.480423065590273
+22.748815016040183
+20.79990275630948
+17.03992100615382
+22.779440647313294
+24.0648991642922
+26.894851342341383
+24.418768444843337
+17.79987232496373
+17.049358538349324
+19.802289157426927
+25.388103468359944
+24.822745616198418
+19.78272876030863
+23.187689476776114
+19.725502696998717
+21.26966466090296
+23.14629316873895
+24.284636206257986
+16.774814718424665
+18.290009985110885
+19.26964849454636
+24.284912183859575
+20.316473524100445
+22.275841208690068
+22.293567504907813
+16.47232443678226
+22.03001006300981
+17.395235389756508
+18.837955556472366
+16.757112669680524
+18.141473192349878
+19.337431670383978
+20.694456821910734
+23.720098064131108
+22.910130722121878
+19.012600835455203
+23.89104475014375
+21.456223571257382
+18.329859514934853
+18.57049691656296
+22.22566244897064
+25.296786573495226
+17.70957745417992
+21.667739216973672
+25.116959308506836
+20.54198424681067
+21.171437289455795
+27.10261735516322
+23.51865889271646
+26.664053660529603
+20.59871661439435
+19.591327486307094
+19.545889184176758
+18.07242020738383
+20.982547372861788
+22.35137204867226
+14.955790693642328
+19.787409844520425
+24.957112689301653
+25.021430105425736
+24.03761432302538
+26.21116308693054
+22.298856386386916
+21.40551551391654
+25.890184270238535
+23.73165579986413
+22.409152602516997
+28.192350697095208
+19.69223951354992
+22.40679810193626
+20.47078036522349
+19.128610384413676
+15.960117275661432
+17.896587887164102
+24.233768902812642
+23.747090991780155
+18.669193124349647
+20.638221865272087
+20.948997471437906
+19.59718886125448
+21.843204164605808
+22.368477928561816
+25.935964402632848
+23.43580403915597
+21.769272497011244
+20.36181670621734
+21.297468045046216
+19.769680849222922
+21.253480932664445
+21.78135869651082
+14.45702569048116
+14.557157680919701
+20.264978936208536
+25.459594623036807
+23.40693721914576
+19.35311192156503
+19.410633468174453
+12.277259533974629
+15.416745615429306
+20.300436711307185
+24.526555063225317
+20.8687001986128
+19.036053646675768
+18.773843144076608
+20.15371029524529
+17.834594078019705
+14.92538107268706
+21.33469868665017
+24.218813946318477
+24.23725231524645
+24.925147230391687
+27.121129224263882
+23.56418925036519
+19.71409107960592
+22.332349592799986
+23.431155285403108
+22.262469321445863
+22.646052650307567
+23.314395972817792
+15.641404730195632
+17.72020383763173
+19.299408006078366
+18.933294524093824
+18.37803826263432
+25.884595718470862
+23.732488698410677
+20.14604455937088
+22.28784873033584
+24.50716451963119
+24.813384626224604
+20.698437747495504
+24.639394555368682
+26.572334308279792
+17.753754769812346
+14.7110071345938
+19.79428672432519
+21.863749347971122
+23.11646739675237
+22.830740860301546
+20.0700832690615
+22.421705831590046
+25.191691022993723
+25.214865844218835
+27.771419031564193
+22.810401520315196
+20.371822382960687
+24.160900710573017
+23.65384264536712
+18.425658839774115
+23.141508236755683
+28.876433386579663
+23.252732973736755
+24.0794653181203
+19.3928055510183
+18.40165096756263
+27.871987990604808
+29.027604110121928
+30.644076186845083
+33.055377708489814
+37.97267520607098
+38.84620606293758
+40.318819221953845
+42.748353237155925
+47.03878777670041
+51.049071538054484
+53.791973276554614
+56.3446361777266
+60.89356470459862
+57.85194354339036
+49.645580661887855
+42.97484936692055
+40.70354031838221
+37.63559614873752
+32.2064297421265
+34.218127629275585
+34.51154024805466
+34.7642235357543
+30.715465065265093
+26.76641353592403
+26.442046339628547
+29.674847105680428
+27.888849111444145
+34.627681191307616
+33.28264751572041
+27.057214800458638
+25.745120373299045
+27.32170418838608
+29.058804962451106
+44.757415387278854
+42.61841394619665
+35.62064263480643
+37.65834394145459
+31.842353012806797
+37.23288272493673
+32.47947867193419
+31.19799426018308
+35.729631069887986
+29.400927348034443
+35.09461515885508
+34.745244916346934
+28.506703376768243
+36.13564677163653
+34.386663352754354
+33.535349223785545
+34.78770500945875
+32.17421833266823
+31.685056102281536
+36.8929588075964
+35.23308119304285
+32.46105275171098
+35.05557039950433
+33.08572395736128
+33.81483797326142
+32.964680548406434
+30.190231784840094
+35.50325021213931
+32.23898421188373
+30.759411400841074
+31.832484427368698
+29.69491691714674
+31.840171152456534
+30.420006553105623
+31.55574410206698
+30.59648781709484
+31.830328911427515
+30.78252998303013
+33.5486544661113
+31.63979865414136
+30.792904748662878
+29.61993275150236
+29.349208137410045
+29.64640156911402
+27.285833849065966
+32.81231738654344
+31.533337053040313
+27.150145245103502
+24.542683088554256
+21.143088439977205
+20.679911271151923
+18.847280865761505
+23.651629820688072
+23.41636277555598
+19.436262319589005
+21.08780494297808
+21.905977607473872
+20.42532839148788
+20.220644933577375
+19.371218777336523
+18.479657047684455
+23.649042689787663
+23.287569405102303
+25.026973708780844
+18.611643832098366
+24.931381671669627
+28.918326243578747
+25.006803298101275
+21.592554554240877
+17.23496810576364
+19.172143395126184
+21.608065539120275
+21.293038611020464
+24.716590942945942
+21.888326358258354
+16.177091050783673
+18.501570489353654
+17.211031636361867
+19.68995702633758
+21.066233215204647
+23.67094587262909
+22.479541400343336
+22.081886474233244
+22.791058253018065
+21.958797447347735
+13.877534620920073
+14.96888723560076
+17.211878040567598
+19.540875881585478
+24.958579779607547
+21.70809497353318
+21.99121241343194
+20.125965828077042
+21.74022672200951
+17.915436935962006
+23.66246935189571
+20.808780154193087
+21.41297001579342
+24.487108135562934
+22.178446727600132
+19.783739894466066
+22.49235774033285
+24.04971975386978
+21.60301516374396
+15.955758959581345
+16.326105968504038
+23.40043033003937
+25.138518972020123
+24.22584562792312
+24.30748807489654
+23.98622974480385
+23.107747530024568
+23.896022454372357
+18.886874685119082
+21.607405966713387
+26.824491875473925
+20.962558428668174
+14.955623541345446
+22.318611865205483
+22.896693266532097
+23.48559149497781
+21.10229782033879
+18.65106935597977
+18.353570450395708
+14.05065005187899
+20.602798935912645
+23.749630171571553
+23.44881364433226
+21.977799875748005
+19.826506140993004
+24.261522867250008
+29.03771529640001
+26.643375395282234
+18.672652761247974
+24.759306705850832
+22.07237976504986
+22.003660171795445
+21.192451103703988
+19.76760350533108
+21.66933900560231
+19.032208291670386
+16.41559754567696
+17.405189649762164
+15.501525345643799
+24.362067227662266
+23.4736064514842
+24.531805869804657
+25.085289480090253
+17.072079185813735
+20.244676921189907
+11.57832712977121
+18.129946273292447
+25.174408842456728
+22.426412050031843
+22.307356513145265
+20.993042244952264
+23.445450136762517
+22.515578251917034
+19.708108308646544
+25.372326032578172
+21.58713672668526
+22.311246929767364
+21.067667717046135
+18.521024247532992
+27.31047160638498
+25.58649970865656
+22.67313509771496
+22.734759658749013
+22.38344811460273
+18.248219271739217
+15.326056947642769
+23.033713809140195
+23.047858113878775
+19.77874997660949
+25.544090138540156
+23.917216534997863
+19.90536640843885
+20.141487999333876
+18.8812537333134
+23.43357870509277
+26.209333365330423
+18.901642409133686
+21.4612708200858
+21.726373508881338
+21.397834535090112
+20.784748264880193
+25.022620709613577
+21.822519736927532
+19.82901210327735
+21.224555738854818
+26.61570958690315
+24.83322684489538
+21.19113267487512
+26.895322007954988
+25.061790824026446
+25.304879657988167
+19.829825666461502
+19.644407467587016
+18.918315375963658
+23.8702934229576
+24.703480666290574
+20.10054391568248
+22.21574444576926
+21.47351816175309
+22.11311015352979
+24.987034103800994
+26.258419702484886
+24.863356806964006
+32.37768855001161
+31.24507911090491
+31.15260959324506
+29.140433031961066
+24.442014890918145
+23.298592949329063
+19.436934479041398
+24.589629048606852
+26.145481159876084
+22.18502837972261
+26.002280535023175
+19.372992135928385
+16.12780739413907
+23.094575391030332
+19.30654389254805
+20.339001537335406
+25.7602392670248
+26.65608798070842
+28.031998701546783
+21.34592160751184
+21.755287811610486
+21.775699058828664
+21.74843143767093
+23.3074597727571
+21.875075778782048
+19.308666166208383
+22.305682631795392
+21.439635778550226
+20.055333097901965
+17.136091850051955
+21.433951949507318
+29.26110453575238
+26.853014542698006
+26.702433748879713
+24.199160617690268
+25.992440815793216
+28.408947347681718
+23.330207526097766
+22.331721925754465
+27.294539397877102
+27.32221432031203
+29.108372770126962
+27.387033404340215
+22.152038712176363
+25.288760639564174
+28.197435277282494
+27.140791750832562
+24.604957700118035
+29.238425744125777
+27.601528230793647
+28.023160831013456
+30.45338352766497
+25.28017453595895
+26.674796553263434
+30.868789146144877
+24.411602288142177
+26.244775151840216
+24.283179509742027
+31.148663710370144
+24.584000618206687
+20.304360606078134
+23.991378362133204
+23.433696145048373
+25.032368287313645
+19.689429279133947
+21.028928511264667
+21.03661416115881
+20.2003041620994
+21.57825111894806
+18.13261785052842
+22.267395283268115
+14.208973885320674
+18.45156247555478
+20.401718932771743
+22.696470613977354
+22.298475987089617
+15.722939742468
+11.333987201229547
+13.708060721915004
+21.403825586036334
+22.798646390820522
+21.586813938118397
+17.211340271147705
+16.24323207312443
+15.480146296251135
+15.214912189665952
+19.47842274721549
+26.557965079350524
+21.553500173097007
+18.103161616841376
+18.28970203603309
+21.303790914281777
+17.14958398016482
+21.51751063044337
+24.12524264257003
+23.217582334448252
+23.43993397110026
+20.991793807692346
+21.723547863970865
+23.212899283928053
+21.415385005944813
+13.073999626487947
+21.542502672164332
+23.500981410651107
+23.4752117447173
+22.126637300279583
+25.36087159190697
+23.58382489307428
+21.895630601500358
+22.725730119871542
+23.02240168666441
+21.74344115241783
+27.75661473765487
+21.742364178188325
+21.254464780903632
+24.94590137540125
+26.623565264527272
+25.256244948078745
+28.061401169562586
+26.317515210637353
+28.67233560918764
+29.73373415808969
+25.69424455636907
+25.47369889762618
+24.974153885614015
+25.938136217733472
+27.897619903890643
+30.384249907457033
+29.962980644243387
+30.124218623082086
+35.59308674998644
+40.723646841803166
+44.97524244495227
+50.46144172470291
+57.103237028170184
+56.358842556939024
+59.06895563560279
+52.312988819952885
+53.54731361198483
+48.186902003293916
+44.23717322253075
+46.36489622468914
+40.890428287256114
+32.27648505494102
+37.34673705910531
+36.760394206538834
+29.22145604425917
+31.32573784491295
+31.364031607926293
+29.629021399552244
+30.15520735985585
+29.433083716126987
+31.119375776943727
+28.808713638522292
+26.214199282055844
+28.32906043150966
+29.355906827084794
+23.07745958623198
+23.194223225342313
+23.86394895307042
+46.17328362242619
+48.91171590068502
+41.16017429817484
+40.73762231845603
+44.272544160911735
+40.04330150234507
+33.85601140443829
+36.64127513906335
+37.032251575634874
+35.03083106896078
+33.79610374559293
+33.6276270655861
+37.79927091366268
+35.783081783505665
+34.206248755735885
+35.18834121914847
+32.905309187953634
+35.47022774465948
+34.205939400198716
+34.48566825798619
+31.371411908526994
+29.668315241716
+25.327496133271268
+25.93238096968716
+19.85294188872625
+23.846543707190506
+23.554315674341083
+21.008667558418793
+28.642562001940505
+29.570499360214384
+34.94966750132481
+33.22223675392064
+32.20380141438102
+38.844234691683276
+41.518891432271495
+41.35993245410363
+44.83591411661353
+42.69890490883449
+44.87664545333141
+43.11760981790068
+45.28297907768343
+39.19201205034575
+43.102513009197516
+36.00049513253896
+41.14591808964098
+34.56780399596242
+32.348104430465995
+29.419823737601135
+30.792924426143784
+25.63413772066953
+27.806130729897376
+24.30706397271163
+25.484809015191246
+23.55421632150359
+22.84642850421588
+21.046367207169112
+18.937673470800647
+21.9571707014984
+25.89282850009333
+19.216184626816002
+22.881994096881925
+21.15813600961549
+36.71491351036484
+39.80570686746068
+43.98402044938839
+52.77499508238702
+50.95803489933252
+42.843838596072864
+37.41808047835954
+37.508354119767866
+42.096488309302174
+45.2808047728392
+47.122594831753446
+49.88580511434553
+50.547228195672766
+51.27636336435201
+51.61224740001292
+52.385242298662774
+52.551626290577516
+52.6436419611414
+52.73259691309232
+53.13257270269298
+53.180217460171704
+53.35899854128667
+53.529797171957135
+53.330685045380186
+53.07429385352002
+53.26104274078353
+53.61308507817606
+53.801846204444885
+52.4290375963676
+51.56838151571813
+49.36253027368529
+48.28895506267626
+47.59335447079353
+46.5579276736023
+43.449387795818616
+45.10725641002837
+44.603751982860395
+44.00587816198596
+46.87906788704812
+45.63091099538062
+44.007143352129695
+45.787334159839304
+47.06897541980095
+45.68290894050501
+46.339217438757714
+45.91930109839254
+43.92960574581678
+40.37287139094016
+37.7661827957916
+37.32922674788661
+41.36689036758776
+41.30937317749909
+33.689717855895466
+39.351748719620446
+36.799478500265195
+33.77179717626467
+36.60672873942464
+33.1926280022403
+37.500234730737986
+33.28365508786739
+36.80774559219971
+35.45215223514937
+36.36468179523928
+35.377179057203136
+38.5307850314537
+34.37737641241846
+29.939759484601794
+36.71924123755481
+35.84137741976032
+36.65619940461508
+36.8767509172274
+35.63294219250476
+36.21695844945458
+30.716276664054206
+35.55766991683262
+30.188040038181853
+31.29788961364426
+29.69778995430987
+30.149254404855128
+34.04316754353323
+32.213567968822446
+29.523707509164566
+24.795601461207013
+31.41299836914837
+29.024475463710587
+23.336892489681503
+24.356893807466733
+24.68466687788957
+24.92647911673025
+25.803435932179923
+25.687588715065075
+27.992819842735997
+22.621915187272876
+25.16383210204789
+24.431732869921404
+24.184264578999617
+19.82007954749264
+19.319918937021257
+20.115300194130967
+20.806441412418437
+24.33239197999596
+19.673128051764607
+20.633122383908372
+23.256961130228078
+22.331337739721988
+20.766155553662003
+20.490532575168075
+19.249038012045276
+19.878858723981168
+24.0285657577122
+22.202448517832707
+27.09248828445098
+25.990321846670426
+23.649103886558393
+20.58780935024619
+24.622224258578328
+25.295148363902697
+23.887168078159377
+20.904694923580777
+19.122698849964635
+23.321580197153267
+22.659543926255324
+20.507289360354164
+22.53388402592367
+22.056893187298584
+21.429499926067834
+22.833955840181346
+26.14063550412496
+20.452814685226983
+17.958998999412543
+24.59424112696871
+22.785795540469493
+19.587540155161406
+22.145963504389755
+24.429068238926845
+22.37778377440962
+18.24747799669501
+19.65045821024978
+21.838761548990036
+21.32812526007112
+22.48525735648805
+18.798539468971413
+19.953050629357378
+16.1571416287954
+17.766278505164806
+14.303247279442232
+18.981771626318718
+16.685303704124465
+17.17579256475294
+24.695354690081828
+21.18862084877638
+23.04551620180507
+24.684976462417666
+19.181449354467333
+19.790647170268556
+20.136700080668305
+16.752170401108657
+20.083890853898907
+20.211554427930523
+20.755659043195948
+21.481422166754953
+20.152679947530217
+16.96839917661613
+16.887212814547453
+19.01334041910063
+19.527167616392347
+16.322863711668745
+18.084339696780305
+19.049847755746825
+16.438066874686214
+14.817955724066678
+24.132917711639564
+19.416342403379517
+18.58898101796443
+20.656491103130506
+22.407829943604852
+17.943917143034696
+17.922424347190827
+18.46954022115584
+21.928076290238266
+19.017164313635874
+19.666593374699502
+19.117712744013232
+18.414152522960222
+19.943869707073205
+16.78937149462577
+18.716941981750338
+20.9323096068279
+22.06103661107167
+22.334526296084576
+20.094614935836404
+13.306915689836245
+17.115714240808884
+20.45728636162164
+24.658577857348575
+21.07009652259164
+17.02822108886086
+15.427403152583437
+19.902640894643383
+19.48943828558309
+20.581453156263294
+21.525514882306098
+19.331785618363142
+21.66054348151306
+24.802374095164993
+24.381336656446535
+21.34948156483462
+18.068716033296468
+19.03969765142483
+22.525693197986442
+19.606747945739812
+17.967937647641165
+22.340350056866185
+24.405677156161985
+21.361018499298737
+23.98624859830801
+20.196885946197668
+19.58071495413961
+22.995255423121222
+19.158539045140643
+15.337999707685
+22.87521538367733
+20.095799458940732
+21.61381416266417
+21.19804291176696
+19.015250679248936
+16.408712144220928
+16.080713175553328
+21.666628154271493
+19.298328652408088
+19.22801119006199
+19.253944175114597
+22.972451570205166
+22.441873404578956
+18.31115339262557
+20.719871609595785
+17.79873922887846
+20.951319687829752
+17.836922001506267
+18.388545444731548
+23.468033464843828
+18.188029758220907
+20.0514379606673
+16.404000251682035
+15.76213671185377
+13.824739043937754
+23.140196251019688
+24.509150722721458
+19.594966016716356
+21.055056385087724
+15.495037594256715
+16.578569433981855
+18.17412197831544
+19.094975596002556
+20.98294793950383
+17.0183386922357
+16.75521432521157
+18.332348615573764
+18.902653460355822
+17.208046654085862
+16.86470376276391
+22.322847919719933
+19.603668730428282
+20.389960286895487
+18.70389807229553
+21.623478602499475
+22.686527639302554
+16.438240742789304
+18.603829010966436
+17.947299986902593
+20.31000164159515
+20.574597182822714
+23.409703898967933
+13.145748699322311
+19.08821852966794
+17.63562891402229
+19.89493953186995
+19.601074071337237
+19.76978393959284
+17.43558998021362
+20.79798012884966
+20.276068663020425
+21.088772059637137
+22.502008461573226
+19.865227573427788
+21.54575021536219
+24.545623082076077
+20.376627936012724
+25.801520066380775
+22.7455178214134
+21.34161356765064
+20.766836332355155
+23.541855150652324
+24.364307564775316
+20.40927155828105
+19.18225403456681
+21.685774184792464
+18.714273724035237
+21.02534382018969
+25.97737033785255
+23.547954786806443
+19.85863754109367
+21.944266431555974
+21.47798386514357
+26.436485902941627
+21.631373188592818
+23.677048171005865
+20.892497253927544
+21.816656435042944
+29.05479483455366
+32.995561325825236
+31.863706425455405
+36.67694589221895
+42.02995163658299
+42.57332474247616
+43.4985298199706
+48.46836373505121
+50.933437665901295
+58.769447433884444
+59.27106986082875
+59.59360660646247
+58.92741467077125
+50.86033206237592
+47.3636050658311
+44.884798292951274
+41.59368270697487
+39.3346086562277
+36.486243541028855
+39.1650206517417
+35.359493778118875
+33.884486975667826
+31.814460693155908
+32.266894174575484
+31.08163798452938
+31.060826519437654
+31.13763092439045
+33.29849991617671
+32.06090530150942
+25.471893496363975
+23.10577931852795
+24.50742617470273
+30.88588922931511
+46.123533567320166
+40.32174942712116
+36.23184493960018
+36.131728405181505
+29.076595516143414
+37.6907215765459
+31.411886085381084
+33.907997312319296
+35.93245483289583
+27.179741441415047
+35.379103287238365
+32.36619182653787
+30.844361339751757
+36.6473280196162
+30.03026366968065
+30.653728499583067
+36.69698850992886
+34.4739657987338
+34.1222699185882
+38.04224272958862
+34.34599983915983
+33.02983832902571
+36.48705297297458
+32.93086622748653
+31.57977751508541
+35.635216102819825
+30.895553911050584
+33.538619141719295
+31.847479119528558
+32.157052433302354
+34.48494055493339
+31.403087832820347
+36.17186297487109
+33.45801437093239
+34.831369263508506
+31.9808827664003
+29.914536854884048
+31.232543866198952
+31.93811908130951
+35.52134173143138
+29.95943059347799
+27.438731952956886
+27.987067898596365
+31.681812615075813
+26.896798749421876
+29.006013945010622
+28.652858856289484
+29.027494601475723
+26.665972140808435
+21.57145346970492
+22.38563600171588
+20.82302630978795
+21.707074699890896
+19.33042502709054
+17.510665992331482
+21.45906613912608
+24.44793330984514
+23.07904762152043
+21.511411283360317
+17.46147588057653
+20.81883554706512
+25.43556020187785
+25.22075129755143
+21.636614777508285
+17.781649747536065
+23.54230660189107
+27.207356914148065
+22.58442807215748
+15.929259043467184
+23.301498531346397
+22.570053484376203
+16.252690421712842
+20.76739469636904
+17.943179990695626
+17.35994893057436
+12.230582769671713
+21.158978918065955
+19.742522221102064
+16.04475987523969
+17.714150312309584
+21.251652377034176
+20.47880797989761
+20.535991939419915
+20.023731333263868
+16.650079353274435
+16.529142508006785
+19.238825776070925
+15.807205787512842
+20.35555720602551
+19.945189952826368
+15.245665415069993
+15.679099909072079
+19.71837606729207
+18.56280782319091
+17.48102087811266
+17.682797618869714
+18.398374793722738
+19.20453801786418
+19.806590807034866
+20.935018154295477
+23.497342072606116
+21.07508165094474
+19.2127847951853
+19.288308471072497
+18.71167338772831
+14.288164607806905
+20.133323786422963
+19.72420608905189
+21.309740469990118
+19.571881165458507
+18.34120903273734
+24.771978832556428
+21.219514433379402
+23.68983134614554
+20.31801739886346
+25.464607649550814
+19.81248943341363
+17.95505422946873
+18.739976307387963
+20.41811463665914
+22.285038249552457
+20.568322166738128
+16.964645693050144
+14.520645405641659
+18.047797516730228
+19.169283798684376
+20.16674910127226
+19.048685841797422
+21.8654678625753
+18.68574879876431
+21.743051746564134
+21.29090828395762
+24.632229781290008
+19.811725084617734
+21.301024923726217
+18.202571052942744
+24.404132301538652
+21.838950761752088
+22.748592945435178
+18.872348246389578
+16.423281451694166
+19.9981080271573
+12.825567635501443
+18.745229462071407
+17.398400389129236
+20.06334481733458
+22.810278248811684
+23.326569151359564
+18.33538281501771
+20.77489315110357
+15.710352338270866
+14.16721796267862
+22.54562427898577
+21.522084867063896
+19.278276439773165
+22.107925607991675
+23.335833169359645
+20.671836616376538
+16.21869496476687
+20.441424795506165
+22.747694956228628
+21.35974159472714
+20.792140552042653
+23.661679485773902
+24.928455390147136
+23.08857416728857
+21.735526377229846
+18.84711398283868
+18.682938154745287
+19.279490937168447
+17.59060273435118
+23.91290922305504
+22.69775669846142
+22.340712176366367
+22.4801216070189
+20.981239597413122
+21.54446358836121
+22.103525466428707
+24.728852547216007
+22.188787030726573
+16.904303209825187
+14.283614813833267
+24.216602141091983
+22.08634831921414
+18.87163489533313
+18.312120697268853
+14.28569067386131
+22.660654484001526
+17.43678670884087
+17.239510367254965
+22.905213329428648
+24.385706448394473
+17.68692756444868
+20.98252994506194
+19.55207401352375
+18.732166343221763
+18.879292519810065
+18.988176196044932
+20.92625421316704
+25.8084829296226
+21.723368098228093
+20.360243173168016
+23.168487201416212
+16.866403587151083
+17.743903244180046
+19.91922339351966
+24.5495425095135
+21.12533243421474
+27.858649912280853
+27.167018624602974
+27.79361919035712
+22.799669956799917
+19.72856762469597
+20.850711089140944
+18.211766371641446
+22.594504196304925
+18.311017522180478
+22.39473903259251
+18.970989171780147
+16.72710481650489
+19.263096248669143
+24.578159100238864
+15.605836335384666
+16.911293670514212
+18.04482500468842
+25.0486478173098
+23.4216920111391
+22.436376980801583
+16.953107854058302
+18.587262836577736
+19.756437503096393
+21.943057117344836
+22.182614705624005
+20.645489902048666
+19.91052721236059
+17.257506570333916
+13.351081404607143
+14.696658466071156
+18.48617801760639
+26.10706126872192
+26.049118906726974
+23.976540156384274
+22.40812516392421
+21.585351800348874
+26.68613850696967
+24.034834719923523
+26.140184289724516
+25.820773024847384
+28.694971850495776
+29.7832749538226
+29.464908959683925
+26.246531776627506
+30.402255494925228
+31.017645773703677
+31.22313787510896
+31.149083153426474
+35.39038920684402
+29.937714903381902
+26.445955750253006
+27.150437550066258
+29.822253259360323
+30.803275343140953
+35.21529379434209
+31.45480644718252
+30.259158514430723
+27.817224195897893
+35.9524288431828
+30.870129438061397
+22.97356682234887
+24.515149311409445
+22.79345400734364
+28.163594321705446
+22.48496261154287
+21.241359347721414
+20.11358779485046
+21.648590539248858
+16.035847183115294
+14.605655817857112
+15.462288860981403
+15.607226330819245
+23.065225915718443
+18.815844746480636
+18.891765802747557
+21.906266315833108
+18.545447251895425
+16.44803740001386
+14.18742578460477
+17.439767111568116
+24.153097276513975
+24.265791888686337
+23.078366415953937
+16.933471616266715
+16.620862147281954
+21.930379618704137
+19.528647118136988
+19.17610980445251
+20.301813666846485
+14.902912850434618
+21.356122881602275
+18.089719216288174
+21.088716768398385
+20.923848676465838
+29.44902025367216
+25.205080245651885
+29.471043780646752
+29.803360238604924
+34.80801421236694
+37.57616847600433
+29.546918648451552
+25.36901158144954
+25.69116500846782
+28.4710995444825
+27.77735709831454
+29.960168056178645
+35.76134408934503
+33.55248655792077
+32.90973483184733
+36.0490948437142
+34.67604487579028
+32.45991200407521
+33.8756208718888
+34.09018676230788
+27.40413153964407
+32.47167193787671
+36.522549118057555
+35.56575116792523
+31.36494791172686
+28.185357436005745
+32.63256696228137
+33.243586228943485
+37.18576284607428
+36.67788397324979
+37.44022410356812
+38.233409285436835
+40.322713610736066
+44.129999672259956
+44.9262421856927
+40.113785789977754
+49.480057175280045
+53.38516146368609
+58.66021179829883
+58.29335512649777
+63.77709982919126
+60.44836245489155
+56.06406904578239
+51.14238573638772
+46.17071591763103
+40.622777436985544
+41.596342850536615
+42.080483001670125
+35.546984196349456
+33.336942867975566
+40.60619883958387
+38.44032205987964
+34.50340481641808
+32.207483369330774
+36.96219814333166
+34.75383505972205
+34.48359201656757
+30.958936433834836
+29.628827121819725
+25.604535720709478
+26.685948866411337
+25.569143957049747
+21.23800360454885
+23.082999526410518
+23.961943703630624
+25.920738519540663
+44.910970613468486
+44.58878902391278
+47.255923762555156
+53.67847195823908
+51.940412917592894
+52.714734378046856
+47.735780548561635
+47.81756410428655
+46.59412366703802
+44.922505980711904
+44.681671103864645
+42.30538489422083
+42.55613951222597
+42.636520827188875
+43.87356970669721
+44.34037929514143
+42.93770194541586
+44.36278246653641
+44.73302734587163
+43.56355185419214
+41.07756334342435
+36.050429119335675
+36.44794924720128
+35.29985010055523
+25.8405847841112
+28.10191513180257
+27.36477350431751
+29.921278442637046
+29.493177791777086
+27.49319708423225
+35.48030361871909
+37.06651708936555
+39.97855030809132
+45.277567286414055
+51.20737213298232
+48.565465454842624
+54.69407424246039
+53.54564093003917
+54.81609470524538
+52.769599097278785
+54.43817593114622
+51.3455692402168
+51.67618945567439
+47.844492561490476
+49.82342234481068
+43.9239086318248
+33.544332053048606
+32.68252738046192
+37.20207082684007
+34.695271914741795
+38.36141283766269
+31.953695415312893
+34.384747915604436
+29.654966652661585
+28.912857887144696
+31.556605145214675
+27.80474001837166
+25.57926255398408
+27.298323848547284
+26.4902363382774
+27.810172947065112
+28.366618673183012
+37.93693185606961
+40.96069249475113
+46.45557558805896
+50.800416378374095
+52.61797925651957
+43.09926037922693
+37.462107933564305
+41.58523185926156
+48.37881146262608
+51.15397322726216
+54.16001223686471
+54.74275073051655
+57.45772608844909
+57.49195344722054
+57.30931126230262
+58.4238996230589
+59.170063319276785
+60.613089453739924
+61.364271913322504
+61.706724558186146
+61.68953572503256
+61.817344046796336
+61.44726889501799
+61.89600498368255
+61.23802070918316
+59.9745123926119
+60.13984416501034
+58.85380396691396
+59.33787226971726
+56.30107742812387
+54.339945943229914
+52.411242210538994
+51.533003630457614
+52.67861913722814
+52.94853780619183
+53.10351105769578
+54.37678833438211
+54.39312942741097
+55.5733511955538
+52.083985782459095
+50.35174613024486
+51.085585669983246
+53.21261480680653
+52.034487299345756
+54.022111059433314
+50.86710855927556
+46.33871329621134
+48.34530678776061
+46.68882345298594
+46.992382317304674
+48.07466708300089
+45.8493853322459
+41.21758011453399
+45.20442367790664
+39.7327102552839
+39.022598191333614
+40.19927098066208
+38.41357745545193
+42.80222465387209
+40.33146677677829
+43.18688746288831
+42.15509758239803
+41.53657481902103
+37.60918564555872
+39.561134476133255
+36.663598037221604
+36.36333196876518
+42.242694681542474
+40.80939964416283
+43.13410408308994
+44.783030694102116
+42.63288168959089
+39.44025243907928
+36.6132700670222
+41.88911640159991
+38.742343280044224
+38.694829481368046
+35.96667127440253
+37.673721332263824
+39.8563241009157
+38.394330377956805
+38.06126124533956
+35.776393394775894
+35.99017049315583
+33.67202904497083
+31.349765657890828
+31.947116669053017
+28.87186479511209
+30.581310696792855
+28.468620673809696
+28.34879793490066
+35.22632767044814
+27.543454996736656
+25.647846371817423
+26.13862732233426
+23.681608732332364
+17.936407214137475
+24.79950154196746
+19.335979990059386
+21.795928969836964
+26.440970915212674
+22.136182106438312
+24.153003978026348
+27.18679740668172
+22.156307709393516
+22.045774952277995
+20.473799419091335
+22.24627413610041
+19.237321007838645
+17.621981611942957
+24.50487442954632
+21.909555883041023
+22.720175916763523
+24.987853513158882
+21.091265838745088
+23.943109888029667
+29.00499442923362
+25.998310697585737
+21.619187417503127
+18.287766996100174
+24.68991094987028
+25.90837726206857
+25.711504717495373
+23.367567522174653
+23.745071150538948
+25.61843453420657
+21.39835395125779
+26.94671067227516
+23.098865808462747
+21.777747872999768
+20.93645836447338
+19.65950356055187
+17.14297578271092
+22.483154868832898
+19.80632184257057
+21.64714277818969
+23.07240986952729
+27.781837963927615
+24.07177941862048
+23.209878025440645
+21.14004911742829
+22.605431940322234
+24.435693251831978
+19.40017587460784
+20.54887459804003
+25.03633693689747
+24.555034264482615
+20.189733364740192
+16.940364082681455
+18.36830819512869
+20.342661579886524
+24.173166148650367
+24.534050682042178
+21.04193224186257
+19.924018767608672
+13.007856384517979
+17.96885098294031
+20.800289531835247
+22.68037376305341
+17.959502423824503
+21.151307913035694
+24.08195561197452
+19.179137430916427
+18.950386709051216
+20.281924015848233
+18.960417886579023
+15.49029129235204
+18.074143648246192
+16.528087101600022
+16.791329125378496
+19.240846906449235
+20.75013848856264
+21.168969022233014
+18.63022620133374
+19.445613553490375
+18.5945135748249
+23.940492103352184
+22.93437600059042
+21.460316018195243
+21.14177539187746
+18.894832477700035
+20.9886168993809
+17.545140665578842
+15.989746982586766
+18.14142394589622
+18.817490860683932
+18.295748710035866
+20.237542435535786
+17.271928953287528
+16.674550393651046
+17.292567390391156
+15.156127237504947
+19.6947806000923
+16.419061564459128
+15.157218694310231
+16.704625375591192
+19.01567700902062
+22.013554200702444
+22.08145781263883
+21.62621316529318
+18.977710726296678
+17.289261202501237
+14.895750350690989
+17.69060474889001
+21.19028320899055
+21.012467030919225
+22.24053078163888
+19.40870028907952
+21.908072108218462
+19.716065340254076
+20.101795272086108
+19.936063291527745
+17.836990467356642
+23.271192116480975
+24.067334825057202
+22.092536143824844
+17.15526360912085
+21.57748989076171
+16.161496421222992
+14.978586744424476
+15.561536182328666
+19.73835978025052
+18.793750751766225
+18.009588120739338
+20.68342814032364
+20.690491003768642
+17.11705892122437
+19.87915363580646
+20.211626770495883
+19.616370709985034
+20.079446474568712
+18.781955039731784
+20.198335079508567
+23.77076845847266
+23.907120039203306
+19.305938391806805
+17.066183552205985
+20.69516750801735
+18.681551773801417
+18.639554950604477
+22.327047745607018
+17.34407744118134
+18.17286559236875
+17.8786429158269
+18.028763950668477
+19.610537938044672
+20.86912839738865
+22.298595422184192
+20.2215675436573
+21.24640698587659
+17.463944865023578
+18.620848159275354
+15.400223352188831
+18.671330833465063
+19.52684990274092
+23.6632454344833
+17.94787729402755
+16.383766811657992
+16.790702157225823
+18.16362927356448
+17.040015055350082
+19.555493214688838
+20.524054150831063
+22.483618330216018
+15.51506515948968
+15.812489079892032
+24.54272604968503
+19.51577241639312
+18.138097120764215
+17.068464944233867
+18.93294861614305
+18.359177226152468
+21.32189083418757
+14.935356313039748
+16.347677866927015
+15.557582592817695
+21.07566804976696
+18.761662812090066
+23.852296102878526
+22.188065832916877
+19.53943656325798
+21.737267077909408
+19.3641275164416
+17.701394412237477
+20.131341317166317
+12.452057826643838
+15.914500135047334
+20.8425295910546
+29.884576887918897
+21.5027638543701
+18.578556320241177
+20.87841787384353
+20.483720426862348
+25.83751530988262
+20.368071291388603
+22.196823769257122
+22.534428261183294
+23.322238503173125
+24.45569852153416
+23.397020523391447
+22.234335117537768
+22.673447980443015
+28.79488138851724
+24.893285671484207
+26.282411453588978
+30.404435119043157
+30.269596774632546
+31.43520398897219
+33.6939365852642
+37.050894523259885
+42.5743588948787
+47.28430205297212
+48.16870480670154
+53.792159796860446
+54.83996725043909
+58.46010409599393
+62.63453501292845
+62.24564575356922
+59.1768869320112
+57.10451953487945
+54.0847209087193
+49.52947478953648
+41.08116250919773
+38.07655939228928
+38.40523955114281
+37.17072176931195
+34.8731267707911
+36.23483389572969
+42.96007009128344
+38.653603827489796
+33.24147480736714
+33.22228302411898
+29.81851767468008
+29.38824102275764
+35.444487807334326
+31.604186743350695
+29.39275517435145
+25.676079867272108
+27.296965332158834
+26.568607791937993
+29.548384045619784
+32.84132257956749
+45.58516486674432
+42.189898040732956
+45.20837783655471
+43.29942959247835
+38.44535566128605
+46.085074199454105
+45.05745859755724
+43.58853248587954
+43.753791892304804
+38.21650075380708
+43.50713670014665
+41.04129652159868
+37.758083348791274
+44.535068951864616
+40.36076341658396
+40.97843259583067
+45.7037345662623
+42.21378863890339
+41.42258997645848
+44.499440525210375
+39.73617720037118
+39.997918302337325
+45.222566239755984
+38.57656926671564
+39.3684750732947
+40.320369501833305
+37.854116101770664
+42.92081986795519
+38.88887463885314
+41.032153397037725
+41.25582590633828
+39.754291901485374
+42.95240001477855
+39.74652808672559
+43.34177128008157
+38.6841138384329
+40.36316901246927
+39.651401329733574
+40.17377356024428
+41.98538079465702
+40.32009938245555
+39.321865738596316
+38.210218063640156
+38.7043789719695
+35.72404972693431
+34.93227694980938
+35.26285470755171
+30.55735752083406
+25.40510489859865
+23.708743613369677
+25.179040474055498
+23.120160308027863
+23.733863539220295
+27.08439661782552
+27.44564917487172
+20.889679167869147
+23.387090025414892
+25.43227938778169
+27.34324898722386
+23.225198360053255
+23.23667633203526
+25.943156058130953
+29.049589785269035
+24.84698671041788
+20.04773982547114
+20.490750570541792
+19.59600353891075
+17.809333897264338
+20.004284881932634
+21.008097519238177
+24.196980085988855
+19.53827515874592
+22.53123049214662
+20.635206199752034
+19.627429087565446
+20.058613110279325
+19.49671574029604
+19.28761368593011
+22.435477202193937
+21.987801320274414
+21.05636012905184
+19.994803310726056
+25.91209204307006
+19.682570781450565
+15.139645363444814
+18.305942198969618
+22.372883638581385
+20.814593867132842
+23.898290212353757
+19.186286031615936
+15.128078452118302
+18.188903830661815
+18.942412805159492
+21.596995293345287
+19.51105770931342
+18.61243909093261
+18.8247820038858
+22.014141881792952
+17.767993972542158
+18.171881622128012
+22.667339549871727
+22.417427247069853
+20.554140907373352
+18.198171523601147
+20.48743277470419
+17.310831420598348
+18.651895977323036
+20.146846961834484
+23.091847584553577
+17.945950325996307
+16.91139412176331
+19.69293464201472
+18.279208064011797
+23.05691546772708
+14.403907032481413
+19.371110684033383
+19.679492301206096
+17.650874570527506
+13.353416210467017
+20.466231950801642
+19.676171892759044
+21.813858763128167
+14.662035121661319
+19.730662945215443
+17.610836050572928
+20.188835132132652
+20.24494581017592
+20.745216904292093
+20.795455951038775
+14.830655221504543
+22.548126548439882
+21.17637981586992
+21.981109037536612
+23.74980355258856
+14.843420858344885
+21.235628806196274
+22.095895401399687
+23.7810303073464
+23.25419261453196
+22.370953742156047
+19.765081721257488
+21.676774380532237
+18.282237724188306
+18.509737528031053
+17.480813299171004
+19.09727453226847
+20.824172593658517
+19.20542199909987
+15.107916963165948
+17.22242083343845
+20.072063582408916
+20.09999935219095
+19.062934318100105
+19.21535321554549
+19.982504729943727
+16.936335652786298
+23.080845913168247
+20.681676601761268
+16.999006972998203
+21.278351712321566
+23.17395793775097
+23.993415779078177
+20.415466414482708
+22.313399355141712
+19.026708888192644
+19.185771503401412
+23.95798684225217
+19.01645820879186
+18.916186656094254
+19.797680731401314
+16.44513638070748
+18.985303421308117
+21.523038109133253
+19.763859540786996
+22.179795130484294
+20.411651560973596
+22.393833103133332
+16.116347322816083
+20.223208655001827
+19.98279669082642
+18.151002947008536
+21.52723704067597
+21.729348128394378
+21.697423084770904
+22.264987911829436
+20.598181602479187
+19.17109869318996
+20.9486582987808
+18.0205472037876
+20.06584527898856
+23.821255505873083
+19.998779302529655
+18.451609046452177
+21.279050866288785
+15.468358341369438
+15.547583317686772
+21.27614047085008
+20.71219997039931
+20.0168618920938
+23.52609848199303
+17.979650959014904
+17.664223470683694
+20.954769259035615
+19.38302723643517
+16.29504555289401
+20.528980654008876
+24.847413954764377
+21.417169502415106
+20.660630014073476
+21.867343226991167
+20.68300735565124
+16.253936342977383
+12.26100277844175
+20.364517232814208
+21.654092377372777
+19.004246064175092
+17.388620486979264
+18.794604218447745
+22.340278603818618
+17.42307364285756
+18.79249537237979
+19.427391908049756
+18.208541333711153
+20.064905092036057
+17.55423327838855
+19.261047855120566
+14.519393963463457
+22.47930537374573
+19.309708162761723
+20.966256880453912
+24.850007563363263
+19.849972311542317
+21.435642092052717
+22.24384157472518
+20.019478852968362
+14.269739164373291
+17.568926078539945
+19.895598916109208
+22.54564810697822
+16.687235475483604
+16.678950603122814
+20.280248186455026
+16.58112006725206
+19.345931048548678
+24.928998212319655
+23.387880849469738
+27.787992445647077
+27.809607297203556
+30.010390254174666
+29.56010394648702
+28.43907335118287
+28.85009316405906
+32.30257399131551
+34.31016246203713
+31.424859246416162
+29.366341900885217
+31.29315933890291
+31.40818397968563
+29.290554846744897
+23.974652014787452
+27.55445045305443
+25.236217760322546
+32.0629152131107
+30.50947123563462
+24.15174979625401
+27.666804375449033
+27.828782965055552
+23.23093253839488
+24.06681725461739
+20.9846865080938
+21.782402904875937
+25.426221294219317
+19.73059365740643
+22.316995258517537
+19.314788485363152
+19.12079315245535
+19.5550422803677
+17.635876756672502
+22.00658750639279
+15.667912903635383
+16.84836441215805
+17.953895325816248
+21.02737372486824
+23.63185030436823
+21.093422057286006
+19.224569681409108
+21.008707785891502
+17.873230638688824
+20.12604699030733
+20.44061434031397
+20.49317666162186
+17.11353243253916
+19.363566489910042
+23.556178754571576
+19.128322250484445
+16.212813676664183
+21.945457104994276
+23.120608743491317
+23.622871270883905
+23.774864226067308
+24.338433418295736
+25.657758919891577
+27.471693306896995
+27.59948296543378
+33.55498361684283
+35.85605324812289
+39.407107660286144
+42.69285835143202
+38.80727651219381
+31.5046045597786
+30.728845383085826
+34.65782673818006
+35.9390174045176
+39.222714078782175
+43.98298989824889
+44.46272253770239
+44.95588857541564
+46.00036326889025
+45.50468079182514
+45.299732712186
+42.51711177551526
+40.66728598419621
+40.529529554526626
+41.6433843034339
+41.06092147228655
+39.927118893643154
+35.71059625241615
+30.150003668593655
+34.13136415256112
+37.771057579028614
+45.790316725075826
+45.92713992312719
+44.12284267434114
+44.11727491388002
+47.21624437182148
+54.05566390840675
+54.280822331968565
+50.82120961669886
+54.879135537480316
+53.77422477750318
+59.77600622466518
+56.27599693973387
+59.46383485640595
+58.85351932593123
+54.72228649889017
+50.02659264550224
+44.92582135011159
+42.232808222251414
+42.15633614947576
+36.22818398712397
+34.395649458385805
+34.843711200371075
+34.376238995192395
+33.316804629049656
+35.39833736115371
+31.969191153972417
+33.27438851641358
+29.644181277940348
+32.123548812419074
+30.62478197178504
+31.9619723081109
+27.166151941783525
+24.519907465552038
+28.5290579854954
+27.64583296134863
+26.966249961711583
+26.5807634038069
+27.53956079171428
+43.066637800307205
+40.072107829219036
+45.50394070406992
+53.234641051126616
+58.80928746611064
+60.495863122476315
+59.49456157971496
+56.6239738706017
+53.53679083998412
+50.7100071168414
+51.834822782126224
+50.44113009482187
+48.31576086420173
+47.743400775740184
+49.627572249719
+49.92121149679919
+51.21701051795528
+50.26498381469827
+52.435674050707654
+47.55112724813365
+49.318318273321665
+38.5989656944186
+37.52029858781708
+38.206514585679344
+31.88637108087424
+30.827914136129635
+32.429627895623085
+36.145072199941865
+32.357909336718336
+27.762428165352375
+39.558178347184494
+42.90010955776877
+41.810212281235856
+47.28700434900641
+53.964966547705366
+50.0678744204919
+56.89459878297748
+58.267447046583584
+59.686301876604034
+59.01917973504879
+60.0883670425361
+58.352851303040666
+56.80331632785342
+54.65445406165573
+53.41157133106171
+47.2490196051241
+36.12338040174606
+38.91758050882201
+38.53587907403592
+38.57841184775501
+41.21108894367017
+35.80177963421718
+33.38490146323022
+27.95947594921313
+24.41675562886664
+29.071456736104878
+30.533150478104574
+29.860750512555555
+30.143828227775174
+31.254261061819363
+33.99026205780173
+34.13677339261618
+37.38296849551236
+43.587363773001215
+45.91457503655077
+46.11979285333955
+48.360296916538786
+37.01709134371377
+39.8287396853761
+50.62552642590458
+58.021444844369604
+61.81086623262032
+65.35256275962473
+67.37742048645752
+65.58843476179365
+62.0224693882924
+62.70791903530903
+61.65675058199312
+61.31442819273237
+61.50418841399246
+62.6400327316145
+63.01194370306996
+63.005507532821824
+63.25976348956734
+63.51312485224841
+63.245012985040276
+63.18298376105453
+61.82150114792463
+61.984507015789205
+63.19191712875859
+62.09518473909927
+60.61880561969444
+59.393282051651774
+60.7908931457695
+63.12415556967593
+63.19655492656128
+62.506041289043274
+61.5947604724971
+61.52088542968115
+60.291891608251944
+62.2822723551324
+59.43276406544365
+58.823757520247526
+57.55636934244705
+61.41430671618445
+61.82466383411268
+59.86729344750049
+56.06797681155369
+55.18550474884742
+55.24714480114126
+54.59281768177388
+53.47007121072844
+57.481219881794054
+57.19361368407916
+51.34295138137706
+58.117985669064296
+57.086370170100324
+53.88961267941342
+53.87379602856816
+54.29169418905684
+53.055637500389636
+50.60472808810624
+51.14687644601641
+52.39497055741212
+52.58117421178376
+51.501897683525016
+48.344069987344696
+50.72690826933849
+47.55069623015514
+46.647577067090886
+49.86812200568932
+50.33057682852852
+49.72354534322145
+51.25588083948865
+47.1980122395053
+48.27706577218033
+50.011643951669924
+48.579227962359276
+48.94255074236247
+47.54216200430458
+45.01319114311064
+48.64401569383207
+47.88188988224071
+45.20763601752096
+42.78246210711513
+44.646069831525985
+40.0399881328556
+37.07152407435075
+39.91937810109175
+35.52296869711169
+32.0371540115772
+34.68620659802596
+33.66490928285354
+38.25518788568722
+35.18044090640076
+35.66128337546998
+31.715957819580808
+31.125044140514163
+33.607382717145214
+34.3729635405535
+31.004821750721902
+26.82039388025383
+28.03058146500949
+27.637708462242443
+30.625031468445087
+32.808295660051286
+31.85344774041792
+29.367190806925876
+27.26966711972969
+30.984349567702438
+28.732407810874193
+28.663987632485757
+24.94723976311728
+23.4448870499385
+25.318086506090978
+30.603660556810368
+26.768696406897007
+24.06212981096793
+26.852829300677314
+31.692336782551422
+29.47766332539331
+28.295218537826344
+26.010297231734867
+27.611780913914544
+30.516595040045516
+27.178106928586303
+25.149834864024072
+25.731488998856875
+25.625273209205588
+28.28919186754183
+20.888005489563525
+12.741838070552703
+24.519422748930282
+22.91523360347506
+21.111560908339882
+22.96112597449533
+21.56154725366629
+21.39092704376297
+22.7125414468328
+25.08835744321736
+23.00526213946435
+26.634506942061705
+20.62774060866404
+24.651492379111502
+24.287986056182362
+22.125377314876943
+21.03503804858704
+21.292266111037847
+21.3501285354389
+23.775537224988284
+21.992225642821055
+17.004938958561766
+18.295645553380254
+13.923979969090652
+22.73537433661015
+22.999534762671672
+20.989736559083582
+14.87875455911518
+17.785443168053646
+16.27397525234487
+18.839955067771868
+20.608087837523456
+22.388889736423053
+20.615151911803167
+18.679449100719708
+19.839332038282294
+13.037691823697074
+15.211482402909027
+16.189571636961062
+16.756301293409294
+17.984621586981987
+21.476885332031557
+20.0004710336259
+18.482860211627113
+23.762068228835048
+17.881009008350432
+18.511380510053613
+18.65375757135601
+18.78010288587872
+19.13662241016388
+19.90818652242649
+19.359082111340015
+19.20488341706725
+22.84011608407191
+17.15314510321093
+16.526930229936383
+19.86125044498864
+23.327054319820846
+17.913572024335082
+20.311859775847765
+18.668946283992753
+19.2613685851707
+18.013169837011958
+19.865271819199293
+19.174015044223907
+12.761875196843718
+17.60192391215101
+18.395392309494895
+18.191983798076436
+21.841771891416897
+18.34047365961426
+15.991851025415087
+20.51752739264903
+18.92439716249909
+16.122604336618267
+17.24455266010905
+21.299678157548854
+17.091964975151726
+17.655338426319076
+18.456246439203994
+19.792431733582703
+20.388905784093467
+22.40835479189265
+18.43511950917599
+15.57038588527233
+24.66967881663703
+25.370733190116354
+21.038440392629965
+17.101952649150135
+21.21288579849393
+18.12016184067319
+16.83236933773732
+15.748613837664607
+18.759153248608882
+18.72761516171107
+21.38129707785957
+20.67358071589753
+21.34965996998565
+21.68829458510173
+19.57784589859739
+15.56820854804539
+18.431117374082802
+17.26192140638642
+21.289927159336813
+19.73786926600397
+19.85528495664512
+19.509087831505113
+19.10363686518096
+17.820961380473804
+19.07672273509492
+17.151322349677955
+19.069059466174608
+17.80542338904735
+15.003574570399351
+15.922317510806892
+18.6675414882569
+16.764009472038666
+19.39738171611225
+16.604034738128973
+16.017134117324687
+16.660506110439414
+19.48722004107715
+18.417896899695847
+20.688184201727665
+15.754593199421976
+18.539097497976897
+23.07631537228187
+24.0853675989417
+20.012248624313415
+19.563307529253507
+13.172361719780284
+17.103885754663253
+20.40046672637513
+16.24028309317606
+20.320464030977064
+24.073885658416273
+18.021078500525604
+20.14400901998438
+21.463998490832424
+23.90022937981506
+19.619873072560765
+18.016122794584305
+20.99843740104707
+18.142483298977638
+18.603081784476146
+22.205088739030586
+19.763212313687006
+18.446901368158066
+18.02384118852673
+19.333772130951857
+22.76766484895903
+22.13228230692107
+17.429192295653323
+22.388852110238517
+20.01967350375857
+20.439251269688143
+19.50878975929031
+11.926559809571145
+12.339535218748026
+21.86596820554685
+28.00831316984781
+19.95093115186043
+15.81659271489805
+19.788762254594545
+22.876906872854804
+22.980040936392953
+18.55690557284838
+21.64982813886496
+23.492707430043097
+25.435095320244315
+26.67748771657213
+23.03680966964211
+24.84304528940062
+25.178908991454065
+25.133710991866934
+25.741046973211297
+25.840328690468922
+31.8000623633759
+31.245359525194814
+33.273194028483886
+33.74234315788813
+38.75329805779531
+43.72954714541606
+50.291346286604565
+52.14723602425231
+53.407770057589644
+57.011740286893605
+57.03571659684331
+59.00633862263928
+59.20250646050566
+54.6490845239533
+52.86991055134497
+49.84099854598273
+49.21180642830206
+47.196843498282874
+41.52886375940787
+38.538468925517634
+36.137778324113555
+38.03543738268628
+35.970015599985445
+39.039279897323965
+35.156207365706166
+33.616828791832376
+32.63677962152846
+30.507097546097484
+30.38035590231101
+32.58628602166898
+31.481743165441614
+27.213559551720905
+26.708355481015886
+26.734256373914278
+25.63489115781546
+29.018313221592607
+33.85005021727886
+46.13596301494999
+43.88041158153811
+47.563746143543625
+50.92239463833542
+50.01343805941604
+53.00937747526416
+54.20714143766453
+53.47466368756755
+55.53444949398129
+53.629497915868974
+53.11426988991802
+56.01498737362382
+52.8302205306535
+54.632298270238195
+54.21511959715923
+53.11016613862901
+54.97310013408087
+52.33118977887804
+52.71270415103965
+55.44853218414871
+52.88290289621079
+47.748026502300604
+53.74730689280959
+50.854135166316894
+52.503696098917615
+50.19690352747131
+52.246458276755135
+54.51988175269121
+53.57079726444808
+51.98409093304765
+50.05211637798766
+50.86503711583396
+51.82992584251624
+51.46167842825557
+51.80918638154224
+48.365626836164026
+52.963012745772545
+49.47086479946071
+53.01592369685811
+53.59139500719198
+55.138595194086705
+49.80374909497895
+48.017793299299385
+47.128776142807354
+49.93911277285339
+47.53429349521783
+47.35069843499727
+36.779704262191345
+35.46063574815386
+31.220475352815626
+29.96877917605049
+28.482598838529043
+32.33082837925545
+38.47808242689673
+31.79806118604114
+24.910253890443215
+28.556111791380914
+21.947266434375763
+26.518186085200142
+26.643477395637788
+24.885525331933906
+20.33882569206503
+26.998902120345733
+24.516525966488274
+22.055588403278207
+22.46258455932218
+25.116851090378944
+22.272869523288975
+19.4478217435272
+14.423654976613435
+18.890824562029636
+21.812466813107505
+22.605028688833073
+25.578431163319706
+22.18415180082569
+21.402037626548903
+19.1432141852806
+22.12642094683953
+23.50203483614156
+20.341903750849156
+18.77884663207928
+22.70468728640239
+26.755915433808113
+20.958188410636026
+17.03070464997799
+23.835501520520424
+19.600295830960548
+18.43127174805315
+20.813365511607472
+17.973305984341934
+15.598665210539352
+19.31323673910049
+17.642140025801424
+21.52117153790941
+21.39088037617954
+23.614240703590042
+21.4142567375754
+17.91541424521749
+19.92193512455036
+21.902467841776456
+19.877035218648885
+20.032932991509114
+21.601207303155647
+18.142999889088586
+19.122782551682718
+17.991677689403772
+19.732752419350476
+22.51718954104014
+25.392075158620855
+21.977078864618633
+17.040049396397364
+15.57705635849014
+15.798975133566515
+15.427042557896357
+17.058831925362725
+16.78915281610648
+19.988510362404355
+19.3178169261423
+15.766981003459563
+19.933306555474886
+19.90040776035768
+25.266209295126828
+17.879938683271348
+21.788629272327725
+17.21548137315908
+19.355475648470318
+18.331905015406036
+19.53122512648804
+21.54334944875879
+19.059581744433814
+15.47141076873423
+13.801751651740489
+19.907053350928905
+22.59368590498474
+14.30930154638672
+19.13490035539185
+21.919421864479006
+22.41680500719039
+20.75756374280961
+23.418962050103048
+21.68904514320684
+20.062093469266642
+17.09509454003991
+15.987067583487871
+20.086180543331707
+21.169593770098402
+16.484088102849213
+18.21434346949043
+16.042837987937503
+13.771424625246866
+18.343759466766826
+15.561032147925829
+15.385288456013043
+17.68884101443075
+17.809352036609127
+19.74783320437578
+19.356910431618815
+20.278839794156724
+18.47618250114688
+21.97321793485675
+20.27531808478888
+22.66743604390382
+21.81539382752412
+19.840659917682586
+21.622891100576226
+19.467068642084584
+21.641847453747843
+15.709121482454819
+18.88045797712833
+17.001589233338038
+18.77130834383057
+20.298273786551206
+21.60728302777899
+18.047508717411816
+17.512901835884932
+20.206058070354757
+19.36310688241616
+16.59489546851971
+16.679875531559517
+20.855827672717282
+22.800881627703163
+23.326979085542447
+18.432728498393786
+16.016472220783456
+20.302528224248718
+24.3032303044198
+22.366946408205905
+16.16797334374209
+18.76051460790228
+20.74924200985224
+23.396665514785454
+17.520781010609866
+21.616574047272692
+17.888439399621618
+17.09467060273697
+17.59681024407122
+22.105003795604787
+17.962637855571273
+20.275641039851408
+19.04158608858097
+16.92570404971643
+14.82045282745078
+20.083467679715582
+18.094716314978243
+20.87294485164449
+22.42461862956779
+22.608537161859687
+17.223549698210704
+25.417820500237397
+24.512130516656853
+23.014500297091303
+16.926025655111758
+18.639258183566255
+23.142838718386358
+21.330143171143348
+20.57070174223064
+19.293295912525522
+18.019302167861582
+23.140791364393152
+16.820332182022796
+17.905019023207913
+19.275107935135765
+21.743636485996433
+21.990785595398734
+21.403782470004288
+19.593990402556955
+16.54480974762066
+17.695046830490128
+17.025597806831954
+17.99853950193973
+19.610608330207356
+16.12127937676665
+23.064100465050416
+23.734773892575546
+18.10937680853972
+16.105464169875248
+18.595445728538138
+20.830128412320335
+20.280583471863068
+20.156140249064947
+28.793096068123234
+25.075264295453934
+21.620841142080508
+19.546156176290438
+20.036368505767243
+24.05374593288596
+26.054558019692777
+29.146433597836307
+28.68366804146376
+29.858315088929913
+33.60928537964436
+29.174209333432657
+29.66104693862566
+29.833363237912067
+29.706905765094774
+32.82816864202475
+29.194337072303682
+29.852205152706702
+28.8957824196101
+23.91871829936214
+28.240870739686713
+27.374904061073636
+28.43552288380512
+28.872066711011016
+23.44172496678739
+29.429025625362755
+31.616921393062782
+24.431782088351
+26.487319621851427
+26.113666308096796
+23.1329134762328
+19.823830866179364
+21.59659285269892
+23.633962887132
+20.09282116126596
+17.42610033408738
+20.456781924792736
+19.415390444754692
+19.759050626259807
+18.03909249967424
+16.328170425314
+21.66839027955244
+19.99069436434951
+21.70502924331217
+21.252261882162372
+16.320289042050774
+20.05730248547728
+20.064174449317377
+21.83267593816832
+21.593885723083943
+19.02144915379533
+15.286675534283404
+18.998641198201184
+16.95215874996478
+19.418992276541942
+20.35065829518976
+18.021990019870685
+20.46915981377292
+21.019514545040394
+21.98942442099589
+22.067584471442274
+20.81077079350362
+24.18819957221679
+23.56289213681724
+26.692224846590847
+32.81888991152866
+35.66656574429216
+35.15035880254554
+34.56098659234698
+29.0619407028167
+28.301462870248542
+31.302503653997817
+29.89713752386851
+31.89593098830457
+35.50992186145547
+35.71330000230955
+36.21930211986694
+37.37880949247747
+36.9474139881699
+38.36796222128533
+36.50604967350452
+35.360241039961295
+36.13554789860906
+33.72338325923471
+35.63684637120528
+35.3137075178319
+36.02259253427506
+31.052030935431105
+29.330457469816892
+32.82123049915957
+37.21588649021034
+38.276020392676045
+36.615496649947275
+41.67901951875362
+47.35801823350227
+46.44742367682535
+48.0253458228326
+51.079349871409995
+55.09469315553313
+58.54651940350108
+62.90986608410804
+60.832622972711754
+61.99550208567589
+62.306815695216486
+62.980434180392265
+58.79936368392387
+54.332711732482466
+51.89900462624246
+45.06981448453894
+43.15645130473152
+41.477332669567254
+43.1598513171303
+38.97474866485781
+36.425264602329136
+34.67687107276224
+36.76293343437028
+35.81429260976209
+32.01990411527646
+36.98615054513958
+34.61326765659476
+36.65091395460922
+30.840509134288837
+31.58266410873577
+32.401777768330646
+33.14689746206925
+25.567877994793236
+28.609400008748338
+29.06922438499059
+40.92045757094401
+41.51078279601518
+43.40943876974551
+43.79802314095995
+54.88249882643816
+56.043360660260106
+55.54657757702502
+55.782977409539555
+52.90252018880736
+54.21437837085209
+51.02282317675881
+51.06848206242756
+50.217293177236684
+47.71756774503163
+48.111850199391306
+46.10704359926699
+47.84483924963483
+48.55809079056061
+50.1521598662655
+45.03317351022643
+46.13521138495403
+39.62749310051255
+28.870467837679044
+33.13728622459158
+31.991501470608142
+31.97526595264776
+30.905839192037476
+24.64095590934086
+27.438619621554665
+28.955068093063176
+33.57912808492124
+33.985822704409145
+36.95961230305839
+43.3881297525306
+47.4674107605181
+44.73853581828086
+50.077992133240684
+47.89633265640606
+51.697407735206134
+50.93838870938477
+53.53365105030887
+52.47970909219265
+56.66616414100174
+54.17570595422324
+56.86159024656212
+53.33529447023605
+39.32727495708944
+41.104079721479025
+36.13080755149967
+29.050305487060044
+33.761327397429056
+36.25721090474009
+35.10973238491519
+30.121108555776985
+32.138315731812426
+33.857432938227916
+29.44898668362154
+29.208308405238938
+27.55735393579552
+26.41595047800564
+27.880676160965223
+29.131782648714918
+34.517144435635515
+43.01424194827272
+47.5788950432513
+54.36542567885736
+56.00601090190814
+45.26289330521251
+45.15545207340385
+53.990637710680005
+60.7445514575108
+64.1991382325485
+66.98064690752773
+65.06728229653302
+64.33700050925015
+62.34473441473193
+62.04335298651055
+60.42977914982074
+60.06029267176087
+58.935593966661756
+58.910671211957656
+59.82637598167493
+59.653968353592376
+60.38032378128743
+60.61013623963809
+59.59187819684182
+60.54867738786138
+60.536121994093556
+60.67689357134258
+60.50792798603927
+62.43740855697282
+60.36382870630088
+59.38599664977523
+59.92327438311217
+59.72976981828864
+59.489803276367944
+60.127955400733406
+60.86158575575559
+59.776358052987554
+59.54994667776811
+59.922699328973785
+61.29006055283327
+60.22991364552985
+57.37713202828593
+62.10610557429933
+61.354226082510465
+61.24973692585125
+60.321425758904304
+58.87541921788801
+59.0725566745418
+57.93510688895931
+53.36943994956149
+59.51523671367495
+62.74516603521485
+55.86139035679733
+59.55077889195549
+59.72682702936466
+55.673553241319006
+59.920744920777864
+59.55798513905868
+58.0972098767329
+53.946952880511766
+55.95711405861644
+56.56550899448123
+58.72277279706152
+56.57994096593859
+52.19630319572106
+53.66333440311633
+48.921063625895556
+51.75607436794715
+52.651734396254334
+52.92068014728428
+52.744176631260515
+54.34106427458895
+52.20930725990292
+52.34344247030665
+55.50645802596631
+50.69784486627216
+49.87472253444298
+52.37763059198426
+51.731198576749385
+53.3495536101208
+50.99706894554209
+50.80303966248516
+47.186841005588136
+49.554714125041365
+43.10920315353637
+39.45499968940756
+41.874962654712334
+36.19821454819446
+33.668723204389806
+39.85930690991987
+39.11212149470897
+43.14372592538969
+39.15237914588355
+35.861952967781406
+33.11855649732753
+33.31546801129349
+32.04364190639974
+28.924576297844396
+29.1373925718284
+26.747282571651567
+26.956816254527567
+27.64445082578665
+30.36171152908281
+34.322045229666585
+31.526794060901338
+32.446403803870595
+30.27434016896119
+33.22325967521441
+34.45419062807137
+34.70414578517196
+28.2409276181141
+26.562434711314822
+31.301261975047183
+30.50970875970137
+29.9670149857282
+24.78397161705935
+27.29344476855077
+28.998204115302684
+28.283679686688103
+30.13195405224728
+26.85677115495932
+24.40150311830503
+28.589523796395
+26.14636613431763
+19.656240376438845
+22.087033162622305
+21.73512698145835
+22.872636165051887
+22.417788032692357
+16.968045518257753
+18.631567807760902
+15.466181653858769
+20.915211243496955
+23.423976262089965
+26.157371901226213
+23.38695271978621
+23.079990153269065
+22.59949784542529
+21.81513862317061
+21.445018882754326
+20.152160381761362
+19.6532988933064
+17.492998711050717
+19.10760923890591
+23.217263235951293
+19.06609578760343
+17.17403980931138
+18.526235743546934
+20.68102830983804
+20.39044197145951
+23.121292970261266
+19.994637605106945
+18.158594914183155
+18.184575424701194
+23.258688857558212
+18.387249582130735
+19.306661339064902
+22.243591637908622
+22.477938760258468
+20.72828726041655
+22.38623896815919
+19.60844326308259
+19.385780554268848
+18.296047768028288
+18.341961155500258
+17.145454242933354
+18.012885474800456
+14.988316046202655
+16.780881874414845
+17.795136040383554
+14.680130701564295
+13.676941301126817
+21.981015324457786
+18.164480692704032
+21.4071768598576
+19.420835769886352
+13.162728099578274
+14.623043210899226
+15.690041797808107
+18.54209334474602
+18.118657313215365
+18.147156687001285
+17.124045998822297
+15.684497521096134
+15.567042751942836
+15.600452249718685
+17.529395034742436
+18.658357776930558
+20.82888182909842
+19.12881439998644
+19.925059273257475
+18.96582400203951
+20.50208655913103
+14.528765455751412
+17.432516849118898
+19.119356057410215
+13.861698281597995
+17.084188339920942
+19.263379064519114
+15.212256246892437
+19.182026756394833
+18.811685673159573
+20.404012383145115
+18.639441056763374
+20.397380201744113
+22.532871749393863
+17.344920970192234
+20.93138216483706
+20.968422433074977
+18.91196172208977
+16.18140513914821
+16.8940464539687
+14.329582220935464
+13.245134724111693
+12.237945418111067
+19.90417991999371
+18.362580960276475
+19.484106710480816
+19.082524908528868
+17.94477482809134
+16.350467708172545
+16.22766069511539
+19.26880677672618
+18.155819219536752
+15.662663278837712
+17.087958027859017
+17.48364924692723
+20.559634160980394
+17.02253322282317
+15.886550475826823
+13.630774089247822
+17.90158549035877
+21.07241086455356
+16.550148634858232
+15.307791328904699
+16.441491913723695
+18.547692436553618
+16.810583508882075
+16.646279611556977
+15.000675663675807
+16.41597371054054
+16.14886992076866
+12.581027931780241
+18.448804353482643
+14.647702715925774
+13.030687123523776
+16.130084929004298
+16.72475586678209
+19.406105737121877
+22.55935234643313
+18.030337813085268
+15.59978546006549
+19.734885326557702
+20.294413469107127
+20.00077158654119
+17.472764285574527
+19.64427918173982
+19.70225495083743
+14.65564069568886
+18.69678742826308
+19.356029610269076
+19.442577618898227
+21.634866426619865
+20.189686914126938
+17.899033136043798
+19.296296682961
+21.713768726083103
+17.628434810978334
+13.776446302194287
+17.580570381297207
+19.889195365061795
+15.799011177413774
+22.258628916311338
+21.634830073380314
+17.178216025552885
+17.168231262882458
+15.853517260076487
+17.50878429446891
+17.84991396729093
+18.726182275838298
+17.386304414327824
+20.639069484332154
+19.812697440852148
+16.3853932298603
+16.027097638962076
+17.929928370156702
+16.196390828290816
+22.4303483598477
+27.475190540186958
+16.226144521599707
+20.68612841589534
+19.94541524286369
+16.03323184404158
+18.571193664220814
+17.150976988346017
+22.40480056496608
+18.73323997491663
+16.875858763549274
+22.895301389442267
+20.743162065870905
+20.83003616913649
+21.055010480280757
+21.332333088321036
+26.508556010117218
+28.605477651554196
+28.04059902806516
+25.312445333727865
+24.994702122352223
+28.80889049159846
+36.77752423690792
+41.117911203218085
+41.777670250703636
+45.99663898244428
+49.79015511874286
+51.692955339091824
+55.60570800280831
+58.76161751237011
+55.03353170126625
+56.96262580217246
+54.43618213506225
+50.441721784842294
+51.876445734996125
+48.0915969720047
+45.8836341653768
+38.04236007470651
+36.1826275502477
+40.67360718541922
+35.92187491169854
+35.76708523234679
+34.51434447883055
+36.124002434635855
+28.1825976951161
+31.844268910994458
+32.97853578337123
+29.200259707917212
+29.79704512722155
+24.46040183242252
+24.386824087678903
+25.156470396049187
+23.18876907927087
+28.691960722097278
+36.06789373544569
+48.76556260086415
+44.099178404735746
+52.14254354917368
+49.825206014571584
+47.42411776529788
+47.84756247405023
+47.94700450878531
+48.85087558418895
+52.8602361462732
+49.76674277801189
+52.152211236196806
+52.376581083232146
+49.13829673182374
+52.0961437783941
+50.7850719605539
+50.02249752300471
+53.620190924791494
+50.942037180969535
+50.6735528284212
+53.672682063231335
+51.49153708331418
+45.7927600209954
+51.18726973384092
+49.50840844325435
+50.19094541525339
+51.27071794789851
+50.192667914630576
+51.60992930197557
+51.46868126346712
+48.6771378237101
+49.29257230063555
+49.77989953716073
+50.52936724510365
+50.68945365191762
+49.16774410683716
+44.74618549802126
+49.37322569925136
+47.587245476857504
+49.617508197258076
+50.80925204221532
+50.31885528136388
+49.02654262709905
+44.994557560975096
+43.34166397581706
+45.678959238919276
+46.0189958318014
+44.542342993323366
+36.82221520390135
+33.4997825120508
+30.819133513139164
+29.294546286583838
+30.847089977098506
+36.488551056229966
+36.55792254937734
+29.953649465407622
+28.32057766991997
+31.97523592842944
+24.176375003938787
+25.156564793244755
+20.53803654702905
+25.479045513128042
+26.24109992267755
+29.39545912922381
+25.600114469106188
+22.567721566971457
+22.755411635805558
+27.462378572718578
+23.448931483173936
+18.532422908815093
+22.260578258628485
+20.709321600504282
+21.143203962768453
+22.873533900515795
+23.12560001442027
+19.560540748617896
+18.636958738640757
+21.62341549055678
+18.908589610316824
+16.354835387040055
+21.28410419729903
+20.751387525775996
+20.733154999562814
+20.742347073333875
+24.53251165210247
+18.525723509260004
+22.63932764632642
+19.07179445074904
+20.06119974637653
+17.140831016749175
+17.59172007359676
+17.711241353386683
+15.549340349056152
+17.90630608061724
+19.528327954330067
+21.243037389483845
+16.137791554951534
+18.06095011382321
+17.094055251307168
+18.02636715383734
+21.04838805681051
+22.994445414590288
+19.3346482325898
+15.706510317541955
+15.817933198043903
+20.120366057776593
+17.52056662793494
+16.115736882103405
+15.13445683193514
+17.06399875027627
+18.874160143186074
+20.017805269870735
+16.104603496157637
+14.939414812107245
+16.528326457068715
+19.086457414161274
+20.65312335130767
+19.36834618883323
+17.893987772883136
+22.291632521019224
+20.020884804499403
+18.262407664172926
+19.763020739916385
+19.64123214133737
+19.589765635550364
+20.915871633942757
+18.28267329798237
+19.250705573056933
+20.291185551662963
+16.32169129760281
+17.64221792146904
+16.729239374284987
+16.30687462935967
+20.10332046111634
+18.708088361773733
+11.47751725082604
+17.779616556703488
+18.223220612194908
+19.169085970874946
+21.2877439139113
+16.982760157691715
+17.159284633299748
+13.103880783399944
+18.2970009309023
+16.48116345868314
+16.726391254069142
+14.169724096811294
+11.75932597853351
+14.828905980437085
+21.078521310993082
+19.776788361106753
+17.275059566476457
+18.14692091497824
+13.982129117432692
+17.154907992986935
+19.08098550195234
+19.251393312551926
+18.09750733503455
+17.76738349870638
+19.4463560807513
+20.869018420114145
+20.224993485940516
+19.57156802893384
+17.802640055967487
+18.01187981279496
+23.39208779897659
+19.331699703161448
+15.694906321519255
+16.39252029074177
+16.552975906540027
+14.563616149672924
+15.018868660869188
+18.18834408505947
+18.738361581026766
+18.87983569382405
+16.65365471067507
+21.144791786075857
+18.38283222217335
+20.114989250630288
+16.167849534760137
+17.191292577002727
+14.013126997694215
+16.62576394314995
+17.94924870677265
+15.953774437491262
+10.257145508639866
+12.591105694887702
+17.586639760801418
+16.954413086175805
+17.212769718683845
+20.670291229817522
+18.533953589469803
+17.187121853439535
+22.40041169359604
+17.770833854615248
+17.79826881455604
+16.553365379261606
+19.096914521029518
+21.052773862360468
+14.087047679191443
+15.7281638450482
+16.413772801021466
+16.24133244006636
+20.116691625876697
+17.80902633653153
+18.131642673643498
+20.127618364247
+17.214303671863533
+21.725800924956616
+33.66816652899608
+26.45719334088372
+23.551328338941644
+17.286256805312576
+20.103782384146783
+20.59806146655312
+17.143727805327416
+19.678272100908018
+17.07885438464966
+18.188613660174767
+21.607401338488614
+15.682609187447838
+18.487940497477013
+19.2349143728337
+14.315803667880687
+17.620493791190214
+21.400035076991557
+21.259601400444936
+16.373411464673268
+19.881888044415405
+21.346492924248523
+18.339902786493383
+18.661414594402004
+17.87018887949081
+18.340380682459653
+17.333931020767906
+20.643102506723622
+16.617933572167374
+17.03413397579979
+20.185157846359274
+19.082201475712296
+24.39044141192511
+34.06176433983397
+25.74654576239898
+21.188222081389327
+22.71007198916338
+22.31260935049916
+23.088876586143442
+24.907969731050528
+21.993428275029288
+26.084319427441855
+29.134465266236916
+29.875849615866017
+27.506933348685408
+31.355071583875315
+30.556191826789387
+30.670840972605376
+34.11539770572871
+31.16275063775433
+33.169486057820734
+31.823933920879853
+28.833516116020817
+32.59139215263869
+29.736290765930875
+27.830854810337584
+24.844654893109208
+26.107230786269128
+30.609419349336164
+33.326857003060326
+29.39689447860104
+27.420112237697793
+26.13647044005478
+25.05351796019167
+24.87942269182726
+19.67347868904487
+20.498135527036524
+21.941498300387792
+20.25343610615981
+19.735216539584286
+14.315264510009612
+16.578300226165524
+18.621961053908123
+19.032300681908893
+19.10943177998837
+16.398768349449867
+19.406743260969947
+18.615807721784947
+20.66216297265632
+18.472427716381475
+20.364045110732263
+21.758945883551746
+20.857537326655503
+19.854268036728428
+18.04814848243943
+17.13580612480162
+16.679760126292535
+20.77011058175917
+23.112893407991166
+22.793055534453643
+23.056153376989627
+21.92171331589583
+23.72316144700386
+27.203575240144488
+31.04659526266883
+40.385756146350204
+36.03068454783026
+31.652511689143097
+40.47941728784349
+41.66401627777368
+45.214097449379224
+42.92650766140642
+39.740230346774084
+39.56031594840057
+37.569171403078435
+37.210083037977356
+35.65212160977528
+39.681595019908954
+37.796340203283066
+38.150212155647466
+38.11995665042866
+40.944581777422314
+36.989232766200246
+35.76423470682536
+39.978715852661196
+36.56290073192402
+36.014108313355095
+38.80010141153773
+39.972985037472256
+37.69711963373743
+37.27830571053926
+37.759623694058504
+37.84122295938227
+41.04068875967324
+41.41251374605185
+40.18481602070341
+43.24876852793823
+55.147065103961694
+52.74948474989462
+51.16591215078691
+53.19728670755228
+53.32929660631687
+52.45188629860159
+53.40324871883714
+53.5699347553891
+49.70716952200424
+48.24681216352677
+50.79992583739862
+50.19373672239354
+48.428984040534914
+45.76561062866472
+41.399439939580205
+39.20442298919041
+34.025328195419746
+34.334361302539165
+31.858564345338124
+33.06388217736644
+34.26589168169518
+31.265326043827656
+32.092445017357605
+31.918122331979575
+28.168847271417306
+27.737768420965168
+28.737919391870463
+24.862761235083966
+25.36636930953071
+19.989832030644337
+23.889464947864667
+21.17236018209023
+21.298350243843885
+22.528813272698557
+35.79695354140323
+35.31562887743273
+37.01511208451862
+37.896917787312475
+48.487043803347376
+51.6799699352705
+53.53200449910854
+57.84749301093264
+57.72688935048327
+56.2389687428857
+52.068082752280276
+53.677465168569015
+53.044476688776214
+51.71479248267898
+51.30458290057208
+50.62706246435186
+50.113908787122085
+49.55951527952329
+49.524530155658596
+50.13698880715428
+49.50374633253216
+45.37545609331087
+34.62416568820545
+35.99722474155101
+35.095640503526525
+34.97993726687028
+38.68769241458929
+30.993663238395044
+32.45193786842165
+35.99544104760291
+39.2082044807958
+49.770871175185434
+50.117450564219034
+47.71213605276567
+50.21041183658773
+48.9268030002796
+55.20505897934902
+51.17119039723518
+58.28826390148433
+55.02549057129188
+58.80078574423152
+57.20183526362821
+60.531974947736046
+57.77272024860376
+57.739143861326305
+51.94246801876835
+40.97019493728958
+42.517536044286764
+39.84323744596227
+35.24395162722192
+38.19648239773268
+34.856487671613294
+39.091615065319864
+36.468938236632795
+35.90169322655443
+35.55000519063978
+35.56958491548521
+33.29106484992977
+28.093674512840607
+31.07978486252979
+27.94886150662856
+28.795050840507628
+39.06723304688266
+49.040030169773175
+57.07969375384161
+62.07453937212859
+61.7763214019232
+50.854633283886855
+48.38543773288788
+52.97695246755222
+59.85267610458606
+62.679467536287845
+66.37122343104534
+63.69193522668197
+62.79442179371117
+64.60993021502905
+64.69281236732799
+64.20966257377322
+63.41527491743297
+63.824224658940565
+64.0546836900603
+63.70245230602371
+64.37607099071442
+64.2947191011043
+64.79472234461475
+62.116221247743795
+65.30152185799281
+63.99124658782327
+63.52406410179749
+64.5625768753452
+66.1864307774816
+65.2930757244745
+64.03222719240519
+65.13655818013794
+64.67164273962638
+62.483930344796775
+63.2474236813311
+64.26803738801631
+61.64475217019929
+62.89062828974387
+63.2149776908218
+63.95890990706153
+64.076180555029
+61.51369650358264
+60.68019418908548
+63.34229012570899
+60.58137312327011
+58.812778243645646
+56.076097255285276
+56.07339411797794
+55.64746583325193
+55.687763087646495
+56.38292062698957
+59.68237084679968
+54.15211708258411
+57.228814357781374
+54.90090389711152
+54.84726498524982
+56.28922410733156
+53.63908061887774
+55.16163327020284
+52.56045929252433
+55.51223602503837
+55.174957806396606
+54.0753915513866
+52.47752816682913
+54.634768819718595
+52.72333715411513
+51.27765945394669
+51.092014481023845
+51.802549862446
+52.84247708800831
+53.39593458744043
+50.98402972025467
+49.339915332540706
+50.07675506769319
+49.726465772739516
+50.20923901418543
+48.21109587007202
+50.15286647532412
+47.4430159365591
+47.88099552333756
+43.9686750448581
+44.021309086639555
+42.89847373188072
+45.846077013905315
+40.02124408409308
+41.715183974907355
+38.861323764897115
+38.74161546877988
+36.68062550231626
+40.31128805152576
+38.009416694935254
+41.74946823513183
+33.739765842504866
+37.77586251852874
+34.77408906629361
+30.595606983964288
+28.188516409553813
+27.8947556868834
+26.177694543163085
+26.581129248752262
+33.09519816828002
+31.13498819920477
+27.813424211587417
+34.211747672600595
+33.93432707178242
+31.67774246084987
+30.942862058569162
+29.98543922052427
+27.24782063030007
+27.47056057222494
+30.764076551044425
+34.033625600374336
+33.365253160340856
+31.295045052013023
+32.513196811759144
+32.62055916956203
+31.262657817510046
+25.77354180981527
+28.080814233764073
+27.04160514730701
+23.329120773846114
+22.806730265307365
+28.21830293123395
+28.274859233332165
+27.233117351142127
+27.667500219378184
+22.99696538757395
+26.150585413168955
+29.457629433367643
+26.379498900032033
+22.1656432864486
+17.24559916289563
+24.829543598111513
+25.73808143725539
+23.520279922923265
+21.886564087637524
+23.392916247831224
+22.858141178191488
+17.813914882451442
+20.57528412122258
+22.596606211206662
+26.17457930500545
+26.864422372189566
+26.889726259653926
+22.79225387590536
+20.25618083755917
+21.345697595975224
+19.506846323706952
+23.27287229133141
+23.102489377252553
+20.541068855618192
+21.073460832248443
+21.036853840333038
+18.772183095458686
+20.284186264176768
+19.235530086361322
+22.189145387227754
+22.448279931081856
+22.701874871973615
+21.25716029518115
+20.23495575187195
+20.736119067169838
+20.933621945044834
+20.36509448746135
+19.837136258100756
+18.661568793684097
+17.703750330546256
+17.53933484897756
+18.237234498583902
+15.381644543415561
+17.50905870074638
+15.741034788113055
+20.997911256973055
+22.345892917836807
+20.34189482644929
+16.557121643048916
+17.364606017051585
+18.303889014032734
+18.343614460164076
+16.968774723909533
+19.80210352657258
+18.5619978365727
+17.84881858408781
+15.541837569713167
+15.019744834484783
+14.292134047614823
+17.193852333044134
+16.30754432392986
+19.15234595361936
+18.913414376852145
+17.581393190841652
+16.483135031777948
+20.851948087891827
+15.513017531210906
+21.74773157038385
+22.995785602749635
+17.215116257799096
+19.805938182998588
+19.223111315065225
+16.565985543384684
+21.33799039889621
+17.939476419924574
+20.712977635535097
+20.38703346264107
+18.201326391892863
+21.035837324218633
+16.318017158022187
+21.78103296068373
+22.603966790813175
+14.897634894951764
+14.651922220250526
+18.459417369682427
+18.592918826342427
+16.98050986604794
+19.59302014739235
+17.61243081359197
+18.11652087306561
+20.45547662122165
+20.690523370467574
+20.85469394246502
+16.724407488031247
+15.331563503333143
+16.83705537617645
+19.908180949319544
+18.149127825464873
+14.741809250707334
+18.089172568650483
+21.129805171791304
+20.51658521360868
+17.945733447788797
+16.949407877895126
+17.36536044256907
+16.999479312844286
+20.20526840363486
+16.604761276319962
+14.444748161849759
+17.749406360345844
+18.54550215946375
+21.94843576498073
+18.914446949189085
+19.65705974265022
+18.64704132701253
+13.853659498854697
+18.636889514772264
+17.866013006221905
+17.545332661632216
+17.386315870170094
+18.00087055381111
+22.17338748202397
+22.522798726513116
+19.073027149056813
+11.6815431529092
+18.803799113554234
+22.817584729122203
+21.116962059007435
+18.689962305237884
+19.335741721369402
+21.63592719392561
+18.074728271055278
+18.96954972702531
+19.112902571808803
+17.497999079146737
+17.901918056111214
+14.600010748874567
+17.92416935363498
+14.690223757183233
+13.45033471117766
+18.133594630482733
+19.164433346914663
+20.417661754468156
+21.081690754111676
+20.21198878481782
+18.884737125209597
+15.639158936009409
+14.129565023592505
+19.124064897554703
+22.71712128600801
+15.52409736573101
+18.46187735191606
+18.451791072667376
+20.04756486480629
+17.433935395846703
+18.991966031286537
+20.633479988252645
+21.458895994147127
+18.873641439965425
+15.609863546797754
+28.413715791646155
+36.19091885529065
+26.459106516253584
+22.909411775917164
+19.67148929556744
+19.100140271807476
+21.909626604082064
+21.04416646769691
+19.695654753197132
+27.136215473914405
+27.95773654596482
+28.377469925031633
+31.723605277095928
+30.87905202591412
+31.127278485931328
+31.95180755928061
+33.80721473769307
+34.679284132281154
+34.89330350649192
+33.77871627369805
+33.72559538154073
+36.94573673468385
+38.34513524628617
+43.91711672855874
+47.56000595488797
+53.41577730250482
+51.37726924537591
+49.93210555007119
+50.996449606453346
+51.654915582133206
+45.921471524455754
+46.362873807733436
+44.58279068468242
+42.801171362122844
+40.81087532492714
+36.754096911530226
+35.97464768390245
+34.05568384211411
+32.86781903412874
+33.90127128263376
+28.076614166733762
+30.899824704746607
+32.16356323271154
+27.610874711138308
+24.30328591299869
+23.790629491242584
+28.49778633298766
+24.915897456849493
+27.662526059765568
+25.924736676529676
+22.236632060423858
+26.85483407646366
+23.06223309949128
+26.528380571522362
+31.72414250800631
+44.457164208519245
+38.280357574258396
+46.55092909764723
+44.94205946485453
+46.99599459341509
+48.62619693208136
+50.16083163909947
+50.44675533236143
+55.68317862154691
+49.868206722485404
+54.15318691989707
+52.80755084475792
+49.97544856200611
+54.526594993739344
+50.288312816093686
+47.6923168093429
+54.25082519902445
+49.48838978965282
+48.13207568837963
+52.792342520919036
+46.99566865341356
+45.32238729335525
+50.04401145076119
+47.549006017132925
+48.873310125444924
+49.37510504311386
+45.26443747540219
+48.858629474433194
+47.53714386888349
+48.16526327889804
+48.96602793750985
+48.27684643235678
+50.25750157536214
+48.80308172707784
+47.04960296466774
+41.58205738009893
+44.943547460874264
+44.56015932918179
+46.27955594670069
+46.19201057193597
+43.01163313429579
+44.30508710850543
+42.75722978330995
+42.84129464226562
+37.923346472624814
+38.339713292443776
+36.26142535098822
+33.48196260190508
+27.65346307825459
+25.382159151738747
+25.667180141631732
+32.4889134281438
+36.91434540330039
+33.11845730225633
+33.13448679967712
+29.602310683098523
+31.810794105922312
+35.07530643199705
+30.320883378107624
+29.269949837823688
+31.221974073856842
+29.353533215558443
+30.793668688546504
+26.061313001749753
+25.99171618580496
+25.448000026525804
+27.515465431577013
+28.439677876817072
+29.259114643961624
+28.382630885226604
+27.501435876049058
+29.70212581886517
+25.915854049598863
+21.945011455450967
+21.029600467019023
+22.405085337799605
+21.006553760427238
+22.10446142457097
+23.07513430101403
+22.669473159969442
+20.876682075127164
+22.574278942823412
+22.55265810663603
+29.0945824776705
+23.161675183048786
+21.70980750594707
+21.328526731504937
+21.130993612139093
+15.597538404770702
+18.377845201568633
+20.087841069301433
+15.986648801578752
+16.878453266616063
+20.086971086949532
+22.410622152400038
+19.772792641752147
+19.926511730564172
+17.404868179474335
+19.371289963793913
+19.775366653183895
+18.366530695762393
+14.626558729517157
+15.18531152611672
+17.62064098380229
+21.16387578973469
+19.448721326444883
+15.655392701908013
+15.382452128176482
+20.108872783602877
+21.298223789909215
+19.214669624969375
+17.697614057566497
+13.590744903886744
+12.320231069835046
+19.164806663098275
+20.82329780357982
+17.981024483477555
+20.774288643827916
+22.79554519430492
+20.573520348972636
+16.091622156642615
+15.199814068307347
+18.800564516112175
+17.045541383974694
+20.52994832385984
+17.249522017873574
+19.724499112104183
+19.301240247560827
+11.907402767722616
+19.15218963602078
+18.951999506689504
+17.093380722835832
+19.020422859365283
+16.86322046705955
+17.14926721164528
+19.47422392128975
+24.06853757410542
+19.031250848822836
+22.157160354921828
+19.847896275084736
+17.36915830009103
+14.000690272507711
+21.536175406188036
+19.381399243735657
+18.232533539288525
+8.877130559438257
+9.5680702534505
+13.44838795210164
+18.15379633655479
+15.042650413265008
+21.402756509867388
+19.42527733261035
+16.48268897045692
+19.886984406236508
+20.636045753366673
+17.435693115876404
+16.60718670540105
+16.22528696821135
+15.789086908154644
+14.695748336996246
+13.625162284845928
+17.867671470760243
+18.101268481093456
+17.825671635854533
+16.94504745042235
+18.818179074890338
+15.761662212681458
+17.924073722439573
+15.69435904548098
+14.920692700888267
+16.044885734557013
+20.924686484188598
+18.0630476422088
+17.641377834822393
+17.81249785452296
+21.48512992386857
+16.54997760277851
+19.29995377757116
+18.603289044406907
+18.079619724081084
+18.57404108988952
+19.768775339232974
+23.7065299398635
+20.873069348674903
+14.220410558728645
+12.81570706769726
+15.629321828907095
+16.695477305376457
+16.56561309618877
+16.315925333027778
+18.287338584751396
+19.56940758587082
+20.336868267269168
+20.024524783383995
+20.672240832443165
+13.73987259326104
+15.281429875042463
+17.438284867243553
+14.571790969724233
+14.97687372242757
+19.815401979725195
+16.5823175130824
+18.32460718947729
+20.499930437254662
+21.525424162935664
+18.52666188442747
+19.09453685981586
+21.72493188697632
+31.437009560489315
+25.37669959022608
+22.568754505044026
+21.272099852382496
+20.94310190547688
+18.614709420799628
+18.685774047961615
+18.818440049997477
+15.828105664218342
+24.306518183503314
+19.526921035622706
+17.64466363898022
+19.517725744436774
+19.640754306689487
+13.374034796578414
+14.223923266548255
+22.314287549218108
+23.56612585398517
+21.42613234684572
+18.918341645569924
+23.62537015146465
+21.70881687482722
+21.72238770853096
+21.111589773838617
+20.524738917860404
+20.628709703797554
+19.370503260676585
+18.687761649541613
+17.45520619571535
+15.480381407584204
+16.555081976419473
+22.64780068373622
+30.701430288122694
+21.22067422591762
+17.33355633876421
+19.34225955214201
+13.482659902388264
+13.612799035564137
+28.1666645347633
+25.14865375329849
+27.90109071045525
+31.263438113148496
+31.395590614934733
+29.799307080393646
+30.086538104652348
+32.60969021177458
+35.99327454106955
+34.69307899068011
+36.970320652370404
+36.343018165456144
+36.27523261839531
+30.079727152715265
+33.92937391586433
+33.68914378662613
+35.1408334522697
+29.129319340307816
+28.099463241897453
+31.9997671433282
+31.563376945061023
+30.421074232517242
+27.8994897703719
+30.359602102778382
+24.383173581785528
+21.028416796994307
+19.324859669837963
+20.004166784165804
+19.848138091976537
+19.667075024668378
+21.725474104104805
+21.52942651011419
+20.494797059136943
+23.46699309408021
+21.379204261079607
+22.317681161132427
+23.39895011956135
+20.537360227832934
+22.910514236913627
+24.345602389630514
+16.12193339811114
+22.826432995739125
+24.612663136084734
+24.688321959636895
+21.002133050163593
+19.88965879457386
+21.03373110452378
+21.18170582523348
+20.75519589549762
+24.8487189551618
+21.235459715429357
+26.004302650196777
+25.38317116178196
+24.446672214982044
+30.413452001655003
+36.66029311339912
+46.94523222963918
+40.00998766629675
+37.42206435237951
+42.87203213523178
+45.17944272692494
+50.05601893597502
+47.57345240284157
+46.958206135336575
+49.75884655394585
+49.73935113294955
+49.332007293231136
+48.794216188449425
+50.31379221869196
+48.98065432806884
+49.16659161055287
+48.55489290290442
+50.104343928536665
+48.60529839417666
+49.49279933778119
+46.81976843895811
+45.70088872203934
+50.553344759647395
+50.08423028371976
+52.19703139313743
+46.86900981133504
+46.67137613470262
+47.72781956208184
+46.503037028064526
+50.13926385332361
+50.173401104049674
+49.79382210707859
+48.028740018320185
+57.92946312685116
+54.98847742899156
+54.16680182750919
+54.294319191255525
+53.817309902772564
+53.7045964080391
+53.81285802336157
+52.783724396562256
+50.16259714315579
+45.55727992670583
+44.895180960164055
+44.62217136766091
+42.01642481938196
+43.54039886569653
+41.44750544629123
+35.67613942210399
+32.5329234387862
+30.08894575643879
+32.39910467813378
+26.74300090259821
+27.91354322961682
+29.243125697496183
+29.94693956011713
+27.746223128145047
+29.00022092194655
+27.642676904383094
+28.11428772557339
+24.305313931222216
+19.99301353001256
+22.369384244647506
+21.6298300385769
+19.36174841892425
+18.93491575326803
+25.114326115386845
+38.12058275704163
+35.586340691980325
+34.8510792666619
+37.01058957860123
+44.40533322261564
+48.25599438695585
+50.700712668712875
+55.87516561931916
+55.469774845388955
+57.3650835455327
+58.11535291002867
+58.33074343827121
+55.711828368024655
+57.89835607849106
+57.413419407022246
+56.923202125978264
+56.68586397339559
+55.15659810625324
+56.34663519075739
+54.42056966716121
+54.324822317129865
+47.76242950464424
+40.35757651011223
+39.04569386161971
+38.15110383145273
+37.701090810997584
+38.51344145123349
+37.93627882744244
+35.38630286864098
+38.278657707218976
+46.744693157181786
+54.15917232767704
+54.728512673552615
+55.25316210283242
+54.26786766463839
+54.381103444475556
+59.26157318741571
+60.42254170467726
+62.57696496852679
+61.137510898711795
+62.68956310839794
+60.42148117761168
+60.34098531473394
+57.767681642282604
+53.3178751999587
+47.825777788914124
+42.48072981454205
+43.186498771054666
+42.23588671518827
+41.0229983027588
+42.156281019193955
+40.87591038328432
+39.848311807194506
+34.694235993881094
+35.49712533626406
+34.01046417086907
+30.899505851495974
+30.06033403354317
+28.285511314076004
+29.965409061152755
+31.317571995847302
+25.548565224919315
+39.6804443800517
+50.06135429495437
+55.82452324678072
+60.740057816960714
+62.61203924556125
+52.60723533561337
+49.38543807189879
+50.10035953554453
+56.10588687687975
+60.12503762419098
+63.710786387611826
+65.7143946525087
+63.47422090127347
+63.251213156472296
+64.24094538749677
+63.119664943165716
+63.38248212118738
+63.692049378306876
+63.70576445982416
+63.949086363139166
+63.986035503078945
+64.64937500961909
+64.78576461915574
+63.81934671164741
+65.44888107455249
+65.32386474059427
+64.73413207507853
+66.04015947321786
+65.68942252753791
+64.55247455306645
+63.60870206680575
+64.19179361834355
+64.84120197403932
+65.71656759928568
+65.20364815251205
+64.888513878223
+62.99920551858681
+64.55030878387112
+65.02927093819244
+64.35610575759857
+65.24506742041146
+63.46063525129272
+63.79104339769858
+65.18942408270486
+61.90629433812598
+59.20634363129632
+58.235851181425886
+57.78028618276757
+57.90605527285838
+59.1808607344751
+60.63279440112609
+63.33703530929561
+59.29854421961506
+60.660908919563695
+62.328062216109316
+59.56799301895154
+61.37764425131936
+60.55790817329688
+61.48306528311494
+61.669874807666694
+62.888780124389314
+62.65893731477492
+61.37619374786992
+61.01190573204057
+61.582174144210555
+59.64753220078204
+57.82879797066576
+59.025838559456595
+56.6514382012412
+59.43105229106905
+57.58600207982506
+58.90815126698664
+51.16576661395501
+56.709515409892056
+59.21273190350279
+58.66428708967482
+57.99156573821769
+58.52124841571252
+57.230805540529126
+52.650659192315786
+50.03694591497738
+49.82891622458031
+51.44759860321774
+56.90874794261151
+52.051354229537644
+53.57366346111251
+46.53796874074162
+48.49791873144089
+47.99435512223279
+49.35232074543899
+43.28877831877515
+48.967490927455515
+42.860456656168886
+47.192408423554525
+43.50332931703484
+41.07221235545809
+42.09188286933865
+40.0830218846817
+42.85572235770924
+38.58208827118003
+40.750649280672086
+41.73733024398373
+38.177218349280984
+41.44608287522608
+36.243032883677586
+35.78898881471014
+35.77284904925315
+36.6602943557761
+33.423611089476694
+36.6782732960813
+40.81301390754324
+40.9861177829323
+39.47338545090507
+39.25499778616284
+40.653372028654765
+36.59417641372208
+36.757442422422045
+34.000044430544165
+32.04190780606844
+32.69514459130349
+28.380189316986872
+32.23672075862932
+32.335017561636434
+31.970248362529333
+32.30596695459691
+32.37283927459809
+25.678806901312257
+31.041075464438194
+32.986311209494446
+31.43774040986871
+26.927321753034732
+20.55411616833213
+28.536584906330376
+29.458205295225596
+28.447983777775477
+26.196898465642278
+26.089621601505158
+26.72204470376198
+30.391595652493407
+28.37910065992179
+26.107600759920658
+27.76462921888192
+28.47845936751864
+28.469239183152055
+27.604072173837338
+25.90860093599315
+27.520806362833582
+24.532287032325414
+22.61308379183474
+26.028923496639536
+25.492440862747614
+25.997089368864962
+25.481756940060166
+22.718131009581796
+24.22321783263915
+27.02275570581753
+25.857129573218444
+20.921371708983443
+23.800196778879112
+25.28004614947436
+20.37901802535093
+22.181683276350185
+21.755397318937128
+21.0276126407593
+22.58016064845971
+22.38582779280776
+21.646683384400887
+25.023267214392106
+22.48727618835673
+22.29306878132715
+24.36140809514633
+21.52693346087949
+17.46909008470962
+21.285515608513478
+25.166211684002207
+24.934901090545424
+21.27347286208014
+22.177827468721077
+20.24197164061931
+22.566711449681165
+24.246865389293177
+26.67497787739991
+26.775116115553672
+20.27507299325488
+22.43124307400231
+24.067021249121723
+20.921179304233135
+23.746935374258157
+21.972310567097153
+22.494316298072718
+19.31675522727309
+19.562227537977293
+21.09422145365349
+22.60871711582027
+21.403625295201692
+23.338034572070654
+23.79348591251751
+21.477389853786676
+22.98371897840535
+24.403334818713972
+24.663149245954173
+22.28168254955014
+21.826867511111587
+23.181902780671038
+24.165049043164046
+23.73907433294383
+20.3406158963827
+18.52956739935408
+20.47781673249844
+22.85181310957148
+23.701855353423625
+26.749906279724073
+21.953335776893127
+20.55077273959523
+21.48309870292131
+22.27039905912237
+20.447764631780018
+21.726690014136636
+23.152094043624146
+19.267803243689414
+21.95504162062005
+22.672772001203825
+21.44481947213653
+20.850911116213624
+23.47470701161916
+25.86289225668328
+20.714431166129103
+22.633013332915056
+18.817745651617813
+20.44280819983723
+18.847024503663775
+25.44081143312748
+22.830548826969817
+25.989049729501403
+17.971023970943165
+20.946605021305245
+18.750407054037964
+22.056470255037624
+25.5214909645578
+22.614268326307624
+21.5260729948524
+22.2797049886331
+19.079246725813633
+18.21948711150958
+17.4396919831904
+21.733993684977307
+18.2873491134347
+19.490197357444472
+22.486085570109296
+24.62064365734446
+19.832309747070397
+24.11397825631029
+22.723111375052255
+21.31626493934526
+26.836266083769402
+23.416799384308973
+20.87577844580514
+25.759011825579776
+22.67370227556374
+24.064975017288575
+22.0774181502848
+21.132616388442088
+21.792681642604606
+18.73975251710219
+23.246758208197036
+23.324529937943296
+20.636784070913095
+22.27826496498392
+24.16276439633765
+24.94188468149578
+21.344589280016848
+23.46402354403395
+24.725748196421847
+23.473527856979743
+21.905230320249842
+21.529318976405804
+20.696002086498865
+19.03052463731602
+21.44526196682837
+21.947681429584335
+26.847202163436705
+22.7554047960174
+25.124242303935205
+23.540072988980796
+23.08158285502465
+21.488416481146658
+23.85932151342341
+31.738536246085275
+40.99209006610723
+32.87743440776808
+24.343509922968153
+25.997266226131828
+27.050622727184887
+27.262970901206515
+31.90366081527496
+31.203112956131335
+39.42159157514143
+43.547316083185045
+44.1119058531776
+44.9690906904412
+44.92943092932992
+47.91993083814957
+46.58450734211196
+48.60255984357531
+49.739531250533204
+50.80229581111818
+51.72613695471482
+51.5446814907809
+49.64643368223824
+46.85985049152636
+48.20213882320799
+53.26633264158703
+54.21768117690375
+52.067701452877465
+50.457702017826236
+49.636514072946554
+51.33180385506927
+47.81695492628552
+46.15040414925267
+45.27055037678681
+46.72498869511722
+46.71858851046156
+42.84382298248161
+39.18528857474074
+32.542494646549784
+30.41539273423588
+27.179749721676117
+26.773917463416083
+29.4179275839314
+30.25841638426708
+30.994401883234715
+25.3856859026192
+25.399616745038728
+24.598196960010696
+23.487341964907728
+21.697637606285426
+22.879587653340906
+21.20684474080278
+25.808450673999772
+23.100620640756162
+21.2145511116249
+29.74439260508352
+39.41379971539464
+32.56727516091473
+39.47344626396386
+43.38878032354065
+50.070443912644066
+50.23724369378562
+51.20942317611569
+53.72448491918113
+58.64473863352056
+55.7222744183981
+60.35371189676768
+61.12081040377353
+58.9574315101456
+62.36334167623141
+59.8938796149042
+58.279663967359305
+62.936316625444405
+58.73385824207118
+58.206256113441086
+63.47867462193457
+57.85283158120964
+56.221241665564534
+60.764281397249775
+59.52755538119756
+61.312767028432916
+57.64269822309828
+57.57949269642765
+58.7837825338063
+57.76654065794214
+60.74449985919261
+59.02774657753186
+56.72173410414271
+58.15391492865042
+57.472215438420136
+58.54639590068023
+52.970859734432764
+56.151861778411984
+53.3787094088939
+59.39901235510603
+59.668529882320826
+58.87324955211197
+55.47817157720876
+57.35404552337946
+54.1132024279453
+51.90432551629428
+50.301946087071116
+51.73108757003445
+48.1600095076639
+37.92205605400207
+31.556282562206775
+37.83002955356606
+44.2937592998644
+44.131420442082046
+42.44584318254879
+38.59091964099389
+38.74710660026922
+42.93586538980483
+45.616427079129686
+42.187570063768774
+39.836684617348745
+37.008693242666254
+39.60706851664281
+39.129184108977626
+30.627387638065642
+30.042412938279554
+34.64295756252679
+34.25151126374182
+35.84409944572877
+31.536219514121242
+33.46816267149417
+34.22910019485737
+33.28380888899163
+30.17666268181398
+25.269736338461215
+26.866221995926452
+25.31889856682045
+17.186074461536933
+24.003550444806976
+27.134212115199233
+23.667971965110738
+21.550143021036064
+22.279621295338018
+25.91178390970559
+28.90127318586819
+25.77373261032973
+23.283445175637482
+22.944999268747324
+24.927162199570205
+25.122159803071767
+18.451522042992323
+24.943723449832063
+23.075633073092675
+21.145311912389232
+23.66628916625693
+24.2318319244865
+23.994566303769844
+25.722999496921418
+19.63810378753611
+21.40641045373509
+20.88766253852461
+20.47053234934245
+20.51644273452611
+19.969238738541264
+21.488423165122953
+24.54212730498726
+22.366410161358615
+23.811724230944037
+23.9998628585833
+22.317086322722176
+22.663606521396076
+24.447041848109322
+22.515782907418853
+22.763571570150788
+20.20205671821803
+19.0560475701174
+20.399637621893007
+22.23736090116381
+19.500012850185215
+21.489208455145345
+22.22536010575621
+24.61936335386177
+22.601573145910393
+20.694676642242825
+20.526114857053244
+18.849820960055027
+21.429065561550246
+25.75994533057927
+21.256030217644522
+23.686090531956694
+24.25930463859575
+24.22493444044332
+18.92559927971375
+21.67017026179073
+22.81875649019743
+26.25302410394309
+25.840642235394228
+23.282272486429306
+21.10494105831802
+20.216372749463332
+21.94782697094685
+20.646131297602324
+19.399872525180157
+20.739582770752605
+22.01859806043163
+19.393571284440767
+24.104536650552006
+23.377339444176883
+23.186194040839794
+25.170424571519007
+24.405846235424733
+24.344839718429668
+19.986632087472074
+21.410968054733715
+20.285812279295982
+21.922866581768233
+22.054800915152512
+15.185828289704915
+20.688022098204826
+25.551270097497834
+23.866649233275268
+21.316270376594844
+23.5549950247497
+24.780915266176265
+23.222569171370893
+22.99170101590559
+25.275294889659435
+21.77706244372075
+19.203916922176774
+19.64738141485394
+18.968962800999506
+20.37449165390808
+21.93045181839595
+26.24698462764927
+20.00833060413278
+15.470088254352234
+18.834132619008656
+21.749973711005822
+20.554328588988014
+21.178455267723905
+23.405813616595992
+24.376474926910518
+21.975575907876006
+23.805314607173315
+24.275780949894823
+21.31364533221118
+23.686834488475867
+25.11377916248236
+24.348283154118846
+23.595396403761455
+20.39501165531864
+20.044623695643153
+22.29388137423787
+25.475733863862715
+25.942515789420113
+23.158709360894477
+22.014102284747395
+18.426355525396573
+22.054967073490943
+22.3250491757603
+20.77095584169355
+19.216696126547532
+17.480113392149676
+23.790425624146863
+24.599755447883354
+20.011287707402772
+21.508429598355406
+24.12412430985009
+19.58307252468238
+21.6810826285719
+20.675808804072275
+25.680585730955144
+26.153991360350474
+19.03688895827814
+15.360038680973432
+15.631908647142282
+20.07475991472434
+24.647198199292376
+24.65891186192941
+24.535204690678867
+22.90647546942587
+22.22820487916792
+26.45887018114223
+24.69382110257331
+23.53537841158662
+24.65738683565675
+27.249772158757224
+27.100112362407998
+20.58431374227203
+21.991446277576046
+19.802999678729094
+22.185981733209175
+21.32029067677125
+21.842547635674606
+24.823689304953845
+26.717496400284745
+23.113523014840695
+21.493810170038515
+17.424088982248648
+22.55276454021623
+20.928595840202846
+24.563394434962007
+23.18451911596793
+24.519679346278295
+23.746954802354594
+22.851228806181
+25.468678968974885
+29.537466332912743
+29.276532093878174
+29.686061671244616
+31.54683980893266
+33.29762461239018
+31.105766710922722
+33.663023377821844
+32.86424186766072
+36.036255679665885
+33.98318004847032
+32.961418435018345
+35.34766002807048
+31.87743833187257
+29.725296818025697
+30.46734776770795
+30.838644871938598
+31.429193867699013
+31.755278047372514
+33.91959680126769
+31.556102820350418
+32.03942496390219
+30.655886171609097
+32.69294735278599
+28.417823721329995
+26.037208216524803
+25.18889848993716
+25.776388628350745
+25.820146258884378
+23.88642483956035
+25.117253579347164
+25.772557147670582
+24.484609278902496
+28.26911604404394
+28.453358101472745
+27.289320195112694
+30.44522980145763
+30.233421549458683
+22.82513060533293
+22.175998062418742
+27.358718217322206
+29.405442798980218
+26.606945450429293
+30.34725575895142
+31.025771678377595
+27.989363926698672
+30.20507938407441
+26.984465351317937
+23.999435741964945
+22.896979772880044
+27.98634935668794
+28.466347243993653
+30.408359729360328
+28.778314931487813
+27.18779770657953
+34.89070673456821
+39.67586469020978
+48.79167239331922
+39.42533785537081
+41.863154039993155
+44.08565782708156
+44.46865395501198
+49.40414704941762
+48.48650566233607
+48.982998975458344
+50.855027738787825
+49.84424230153069
+47.682186468064806
+48.746800817224546
+49.505562350138085
+50.14707119957946
+48.58849624443113
+48.59440809533807
+50.51056413499241
+48.98763992353788
+49.341127285152304
+48.03320675032512
+46.22491845490238
+47.04795688321203
+42.47514203760711
+47.725564082148665
+46.927570476591306
+43.50885215875136
+44.10962777550308
+43.24626521971437
+47.9047476545693
+47.16769505640896
+48.76323425613935
+48.545795004199135
+53.282608643567706
+51.9411636884648
+50.9816673809098
+50.71212689480792
+51.37620626481718
+51.72349380706012
+52.500367322572444
+48.96779566608694
+45.75271792228148
+44.43807322145034
+41.69107853062279
+42.827691374441336
+40.71673415781959
+39.557591836950145
+36.85282736074946
+37.46133409325623
+31.668347968997935
+30.473563314436646
+34.526161216771314
+30.447867003897542
+29.180924737604485
+28.6405021650327
+29.41787628630469
+28.18632623395584
+28.45652552658909
+23.888699043055198
+28.682468626774792
+27.85103957302833
+22.977907573078085
+25.907759644887804
+25.560388988488754
+25.938390368393826
+25.02006353867344
+29.95773568842486
+39.45096291334626
+35.71402889602621
+35.81578313744514
+40.75607312105311
+44.204829302002054
+47.757571223996486
+51.860242424797235
+53.90407805445754
+54.54229084211195
+57.630413182135904
+57.50113985230178
+56.76690393781729
+54.98590346084237
+55.405071116011
+55.72778675780911
+55.053192415774056
+53.135234131724516
+51.71116578143027
+52.88191795296927
+47.759148911509726
+46.22861511983792
+43.05419676590053
+37.482499739435745
+38.80967649227931
+40.80564369196096
+38.8514710843481
+36.90168094353116
+38.14073226174567
+35.327172602105364
+35.1674737363759
+46.67020788489796
+47.170283738314055
+47.316106562103265
+47.01913976406327
+43.42508315155034
+46.060882557898616
+50.741388870572
+53.447223367604636
+55.52782342535815
+54.79566689282838
+56.80279567675832
+55.05038221555162
+56.239718042891404
+53.70019773163369
+52.33355933618325
+47.42752694435565
+43.3589861926962
+42.411603189089234
+37.75471643758321
+33.98939397857947
+37.94247287033102
+35.96028506652681
+33.420721408633526
+32.453197541281526
+30.09838351059817
+31.28293441673705
+33.602587534389826
+29.200099720870313
+29.698390641315584
+27.64542901340367
+27.408279828269997
+23.80084992747726
+37.043818571258356
+45.23644027508621
+49.57082391767824
+55.293057279630474
+59.06349778192565
+50.516701993941055
+46.74437642520452
+49.34414687423035
+55.37403279580906
+57.83646890141863
+61.17663572794217
+62.88566700284829
+60.14219940564643
+58.92866088580142
+58.65921932317518
+56.14313234830837
+56.97414939550964
+57.42182964513805
+56.06060128961629
+56.84959893584154
+56.78092561790289
+58.59545413300195
+58.22495432334621
+58.257051311978415
+59.612496035186055
+60.14943702837057
+59.027954006781684
+58.328096177781745
+59.83239974586955
+58.849501540491886
+60.66898271386434
+61.37732789145542
+61.13164106092904
+60.872913302067616
+59.89318081974218
+59.27885414426221
+58.41442099970112
+61.67278332354259
+62.235732116159944
+61.01719985025836
+60.24494549897132
+58.10691728435709
+59.88033373026247
+61.22138941349305
+59.12249878452744
+58.280620142403144
+56.20227817420988
+56.85485941101129
+57.31304758757658
+57.155463711723
+58.97850133907369
+60.0860274534286
+56.46312877445287
+59.08649176080007
+58.53576697656584
+55.96765887363583
+58.13547068841371
+57.323454501753496
+56.519321814797934
+57.0581439485427
+59.84199499758432
+60.55446239165279
+58.167619365934556
+57.70984383550429
+59.119867160694064
+59.44489579367317
+57.96661277041475
+57.64068278366132
+55.21183260189113
+58.30407388285607
+57.12501987945645
+56.79929025253523
+52.871949759552834
+57.048654184109466
+56.74425102645645
+56.70366663139079
+55.935064788552204
+56.50424631347934
+55.38100668566091
+51.38577590846473
+49.74073477479665
+51.2237125494652
+52.15195960182674
+56.33257110564358
+50.755828581902755
+53.649093756776736
+45.4397963117744
+46.6665459145989
+45.30376839261931
+49.28092294962513
+42.06506363978278
+48.09030657274201
+42.989036408372996
+46.21398436739265
+41.90000721987298
+42.970037631061885
+44.342868994585764
+41.10460048848914
+42.080933858147404
+37.782847975476834
+39.957787548628566
+40.324071635025184
+36.588107338926335
+39.17334263284751
+37.43852526906775
+37.26527540130479
+37.33380743448424
+40.218779929926114
+37.108568283865324
+35.10640472282458
+35.048934862911935
+34.72994215011559
+34.02313638543167
+36.73264549039574
+33.98979257595572
+34.160767319020636
+33.66434787330168
+35.334372800602196
+32.699718374783245
+32.451409180889684
+29.67331706696534
+31.64064412896205
+36.50552033931764
+31.69762914178868
+25.26320900061222
+27.478211419465282
+28.60600667610342
+28.429108154091082
+25.796910388062372
+32.14122037021983
+27.53300525798204
+28.26189210079791
+26.21529620948563
+28.00825152227337
+30.9384046148554
+27.938434798814
+27.48699201386249
+32.2074468311458
+34.04585276532906
+29.689663149964943
+31.40381491895114
+31.722440948335546
+27.708834013685077
+28.15577563101934
+24.276734025984226
+28.70024815242904
+32.747282257999586
+29.095979460199885
+27.877793683995122
+30.5486932745457
+29.357629288665493
+27.959115865536077
+31.329190009489338
+27.74409712980301
+29.283619922602753
+29.242997801142238
+28.525909977490613
+30.19035782128182
+28.800866993317655
+25.021675103419156
+27.587501829926964
+27.173626213465212
+26.353595173662782
+22.95745703366147
+26.174067740792708
+26.71882857179415
+24.345446158541264
+27.344212732003783
+27.178778016084706
+27.622915634669326
+30.021211260877777
+26.58078383786011
+26.21415039792521
+28.666768565705894
+27.04802278513843
+28.158010353541727
+29.938743990883708
+29.002446141244448
+29.185605446895664
+30.630313882498996
+32.722642192278585
+28.02442039064995
+29.72667242063065
+31.229554768155808
+28.15065432070425
+30.075691165817588
+26.809953813595584
+25.820693122623936
+28.228929855013305
+28.785447417810488
+26.744663523772374
+29.804794947104057
+29.43525949867859
+25.772839832572956
+27.563552903672175
+25.756984783495795
+31.445979418877457
+28.514667947139273
+24.75917825431135
+25.880546016825193
+27.54187874516741
+24.68049739940558
+21.927625562999523
+29.95824183236782
+33.783816124564666
+29.29741884497895
+27.93319606035358
+27.57614218201749
+26.864870591405563
+28.68746760708848
+28.76127248377226
+30.3524461991731
+25.338364770116485
+26.001462466931784
+26.193739463023604
+32.942887389225746
+29.721495385223236
+28.83686271459922
+29.188814968579024
+25.82848086125253
+26.367660680822397
+27.811836834864707
+27.443018640673742
+27.177383630677667
+31.30548635070177
+31.24198669641089
+27.743438658338818
+30.693275685940947
+25.96826735843281
+27.49163664512166
+25.839136174590138
+31.064280121013326
+31.065775052847656
+29.994885005110476
+23.68469398533263
+27.06834931427794
+27.07255598589687
+29.362540855113295
+24.87537935441547
+26.574874458005596
+25.534981101868723
+28.881360142781134
+26.430566260916578
+26.913894602571673
+26.365092755889464
+22.717812078523593
+20.960542690999006
+23.063276166973154
+31.060614924136217
+28.031630352540176
+24.310705960127095
+28.884258357655483
+26.208102908413522
+23.091342234494093
+28.84208384517163
+30.601586458854896
+24.596343608640908
+30.536842725155836
+23.958717738585378
+25.59716604929666
+26.802267789060565
+27.656932827943706
+24.37275419221905
+24.368794672378428
+30.17885354886576
+26.293056998659594
+25.58029788290372
+27.2998264439599
+28.888687158396394
+26.33436125221091
+25.36108119759801
+27.81379209029828
+30.466559967996815
+26.234269557386398
+29.001153051737333
+25.933216644142405
+23.544047072894188
+22.02801622893962
+25.648605139774233
+24.956570376982057
+27.93180345725021
+26.80151175197983
+29.127419975812145
+29.75076371214041
+25.780344732365677
+24.71300970847919
+26.063604095879896
+33.641400225430516
+40.1131975045853
+29.26923644532191
+24.667556797957786
+29.200880476998066
+29.84360150565807
+28.965316793800838
+32.63072433010338
+29.122699722775423
+37.06144027628976
+41.579701288681164
+45.032617176351394
+46.880263334115185
+45.83613378736365
+47.86170526646884
+47.39135713338425
+46.83380543979061
+48.44483623018163
+49.380743108108966
+52.15400004866612
+50.611911081761065
+49.97430404527857
+46.29292524372294
+50.304406131338745
+53.453060890240934
+54.24423717093928
+51.9583679906735
+52.444828098213875
+51.48806112497145
+51.884737765523425
+50.80449630373823
+45.68267187794035
+45.334791326810496
+44.60278809799547
+45.46316281583948
+42.94584351882164
+37.325745010209104
+33.57862787544444
+35.43278615445658
+31.221583296611385
+29.83079722238942
+31.648830269705073
+32.2704253266141
+32.850478593357764
+27.15398857427232
+27.027274932776933
+29.102490070359295
+28.44704570140675
+28.399919284041218
+27.313831199583248
+26.268567892140737
+26.130363137034806
+29.766756829166752
+22.413748194262908
+32.319608331610496
+42.092237689894176
+34.42284552255667
+37.03224268722397
+44.42580633348865
+53.68270874172281
+51.7558730969678
+53.0825287081617
+53.99465939815071
+57.1032877771622
+56.14394348692369
+59.42883303533739
+57.833362353058575
+57.05304935872485
+60.800321749808205
+57.084049604758036
+58.39363965348389
+62.27575064742368
+58.352648823003435
+58.61557410521104
+62.1045570634795
+58.63205717180977
+58.15023515683402
+59.61865375875685
+58.64408042003197
+61.31761571873223
+57.21452137009105
+55.978563679434096
+58.51979018245706
+57.3071959065993
+57.84033905180474
+56.65647493184072
+56.68335704992477
+57.57608580473237
+57.58639022447271
+58.19771280777128
+52.43318968476251
+54.08187414424875
+53.538023377530564
+57.68024052995422
+57.62624391495
+55.49415652203224
+53.98962913288275
+55.44035396542422
+51.560241102540864
+48.74771514909192
+49.63009551021775
+48.680387235716736
+42.08179578577862
+38.12972421678881
+35.035431149009284
+38.340210965955656
+43.24806055256109
+42.808687042395036
+41.79613527357069
+38.44257457822385
+36.71906732231116
+40.38877680899216
+40.50619322057663
+37.89984920146385
+38.4279780261014
+34.790066616911744
+36.39571153234937
+34.47146832008495
+30.790572471273705
+32.05184989078582
+32.00815275068814
+33.45393559631013
+31.767933150892716
+28.04349518309739
+28.83132079996092
+29.807806939319235
+31.979050775963188
+28.85845300197508
+26.498797001067402
+29.063895954417134
+27.421355717857907
+26.530191062293127
+26.557431720911964
+26.092638537447954
+25.389431301298913
+21.253048898366245
+24.345157536641878
+31.419542017822906
+33.94202669160609
+26.469867233755025
+30.562026672200247
+28.461479149851925
+27.56631939744689
+31.855612668785042
+26.19432417153085
+28.07691047227084
+30.281026439805004
+28.840974130542733
+28.410618279998573
+27.17352821919178
+29.18113479516137
+30.011687072016784
+28.500277060641835
+31.989857114560067
+30.485242493048972
+27.520782847298577
+27.603176572762436
+28.95456420248344
+29.96376092023185
+31.593983049194776
+25.720995451303565
+29.416886240712273
+31.252086529569524
+28.765754741988374
+30.442729622830754
+30.46463696879225
+27.176128875517264
+31.000244208105528
+29.077286059525008
+24.530650507513442
+25.541605868199966
+22.925010012705272
+18.540891409552586
+24.485169992302417
+24.926829556507812
+30.471535899770032
+27.855325679922586
+23.637492503792842
+25.47025194819095
+28.642726588273263
+27.706546822655127
+31.275932439386054
+24.780185912076746
+28.638069497189505
+33.21347225537481
+32.38620863216444
+27.26186219215397
+27.246111618202235
+26.17536964549545
+28.067776904753856
+26.226521167287714
+28.58515144874498
+24.774170577763
+27.302711945693076
+31.201637341024394
+27.90548315813143
+28.135515863038364
+29.16182343401995
+28.892181611392274
+28.66762966874134
+29.814572532434553
+29.12281976714597
+29.22457692790441
+26.630350178122455
+27.402283510033143
+27.37119778304772
+26.830458550978918
+28.527555622061016
+26.667947122903385
+30.747379806732454
+28.9275128033604
+25.054877579108535
+29.198160689753465
+30.06001800889004
+28.797054528553062
+29.623471247618056
+28.258702782171824
+31.430678478474235
+31.7156553377567
+25.942908377946452
+29.607745205139622
+29.219407054831905
+26.721879630416964
+23.493923276645717
+27.532017807635967
+26.413475739999555
+31.266686083149168
+30.98419293584135
+31.51154254801922
+22.32647849007077
+27.841595249490865
+25.95405728257063
+21.893813296643742
+24.92012798037051
+26.045482049844637
+28.33821707793537
+29.104700205250737
+28.130616527107506
+27.32670267341109
+27.677477424775844
+26.40671658706826
+29.697694578225082
+28.901648902551386
+30.476702996143487
+24.062762891712737
+24.343493816044415
+22.936150643468622
+29.049816576861687
+25.975023093479308
+25.55745597591067
+27.085425507368882
+27.485780990744345
+28.255447519326154
+24.636800294013838
+27.256091203296947
+26.288674428487454
+29.888822954015794
+30.802733582946473
+29.1739133389773
+27.86504979998527
+25.348020757756373
+23.39079652469347
+23.83976566441997
+30.96516032409214
+28.12157034159513
+33.66597588338348
+29.383217812837543
+26.30429334435604
+22.93438837034877
+24.543740698052588
+27.882729481865496
+30.54327082235119
+28.352677233411683
+28.522063598845406
+28.575583096252302
+30.15961263283988
+26.35563830109855
+25.84951749943191
+26.685233575589265
+29.1632163761102
+29.490102840929524
+31.68599732614834
+26.25326845491496
+26.53943145347459
+23.64649229185791
+22.800066292188745
+25.321985343303666
+24.403494686589568
+26.721572074168137
+27.085540102116113
+25.641774264163388
+22.40475596581298
+22.964055089401313
+27.425056651406905
+26.631349757901546
+25.04689924383287
+28.10231182880841
+31.496952149636712
+28.60148466634456
+29.877320518137253
+27.532737271586285
+29.827511496521254
+30.89098683345874
+34.382598483963505
+35.685777350822036
+35.31537648072867
+32.68801707385832
+35.40231635589164
+32.940883413211395
+31.324927580752146
+31.82304500344894
+31.74644458280777
+33.885502010413404
+32.878077464388156
+30.43952286762581
+30.180547311738053
+30.187696953858648
+30.455244779436285
+27.85521969325822
+31.208435877040515
+29.66420907601507
+30.23010595766702
+33.261464794940494
+32.45246433579703
+29.56188829732936
+27.776862259146796
+27.377027400359353
+26.82710246734591
+26.233592640301424
+26.882238471422085
+28.16971591660429
+27.2714810377566
+27.73836884927823
+28.103825117251915
+29.590685109038503
+29.048368706852656
+31.378309358621152
+28.3031004263393
+25.587079501022032
+28.245331745463332
+25.623494763409568
+29.985390544378376
+27.677927028290654
+31.869011149174895
+28.02640530081736
+27.50564134575569
+30.189405915217336
+27.32723344998668
+22.435667612888352
+26.65500869473243
+27.82608579389735
+32.061395250131795
+29.76374612676507
+27.238091155028783
+24.96201788345286
+29.063410558983136
+37.796696335566786
+45.852628978900356
+36.4170253131568
+37.10533497667389
+44.86894278071422
+45.49516260922736
+50.616131938685356
+49.82291849202506
+50.36964651725664
+53.01176420785156
+51.01250810802777
+51.76920332168413
+54.00668696515859
+55.19283477125714
+54.055224187566424
+53.92069238175571
+54.69685606955572
+55.63544281997106
+56.620955162921895
+56.870505736340434
+52.97531627935082
+52.68017640822626
+51.47317936797498
+47.53694691565402
+48.300082902474266
+47.00046960474738
+47.65908007082412
+46.197657693326846
+45.784806959338354
+42.761474867282686
+43.44356008691202
+43.00339813933145
+43.839717717123165
+44.78998681180726
+43.96440807655447
+43.23759503835322
+44.866163726122565
+48.46068441424573
+50.97052866508462
+50.28974495886326
+51.04840887782548
+54.765057537067236
+54.50014039110243
+49.81017806492477
+52.94836739911107
+53.08434941405134
+48.59330488355581
+45.48690253170131
+42.33120372889307
+38.807136427332296
+30.368023504694946
+30.57086839184231
+33.07685857877421
+36.13560345887251
+31.50084205751726
+30.780476491067375
+32.12378223907571
+30.799387880154242
+32.15903431393092
+31.412799884829838
+29.866786074503594
+26.666989672439414
+31.516971637245234
+30.94498321543712
+29.932796097599493
+25.3547137102845
+29.425629212756604
+37.684260177048586
+33.798804126441
+34.96122329511935
+35.399380499532754
+36.19908270860236
+42.03615617043934
+44.54425265575449
+45.36078639471124
+46.94355887281321
+47.1803716892129
+48.51461618850278
+48.51278513876851
+46.26369505564858
+46.82469003319227
+46.98692017674877
+47.691190873103864
+46.85677672722169
+47.08509603788207
+45.60194812392827
+43.131024268138916
+39.65002459944638
+40.521780753716264
+37.66336331622258
+32.82599916772948
+34.4497016251717
+29.240361394542916
+29.20847352064463
+31.08706206490936
+29.261043736743275
+27.854943523518614
+44.95138105240062
+44.59252466856671
+39.11191446779053
+41.794211639051184
+41.698384581139535
+46.615058025233886
+49.83184027010256
+46.683383403916636
+47.66618830310078
+45.1465869968852
+46.2808029579309
+46.035628444458276
+47.33811616739463
+45.95120685132874
+46.545722657320496
+43.1028751267185
+40.871664175450654
+41.578067531900466
+36.771434868952966
+31.07930172127935
+34.44939206105474
+32.5314181647618
+33.43949775690392
+30.750169565824095
+29.891564726293183
+33.561237352632006
+30.808815111051203
+30.70564098383649
+29.661517742415484
+30.134915343169553
+29.905816057438102
+27.429750182503014
+33.99408970441472
+43.36345228047455
+45.54153107123547
+54.97599626399456
+59.207564577010814
+49.63641030361243
+50.72809725229346
+46.639609364814476
+50.60331205964091
+54.336550860434514
+58.04009272800958
+59.08803147099763
+54.495088753586664
+57.739332635678004
+58.57454227665861
+55.18101880848289
+55.265647889129085
+54.94705028747046
+53.958642405005534
+53.345788861836084
+53.738778902856644
+56.92194097310869
+56.416212134032065
+54.89844621213443
+56.80939130136926
+57.95215664905496
+55.6622125838849
+53.46738527926343
+56.075083002186915
+56.7888888498632
+59.07372710698769
+59.702603973651684
+58.648699317331676
+57.680791859321516
+57.10113939534732
+57.77171589548662
+56.963214778021275
+60.427758188836975
+59.137573315498685
+57.41337207921953
+57.751122080663386
+57.07625893431191
+59.76516944758965
+56.61305605534092
+55.584891743947814
+55.271738443076735
+57.06109175231982
+56.266187880540386
+52.018302038641316
+53.5803318304519
+55.44274883698645
+55.938862086692566
+55.76275403401995
+56.657383947016385
+56.25047880226502
+54.86506017179342
+53.86693836853479
+51.01258485540903
+52.547443120278025
+51.00053265433059
+55.05619718093784
+59.597840517716755
+57.93321353059226
+56.74439765714431
+55.65418581858871
+54.466435443986086
+53.43585428373683
+52.7072660711233
+53.885657213037895
+54.83165862642619
+53.01641935296547
+53.762936413389106
+52.31385839425289
+52.676033792857
+53.03056399618342
+49.74235861851513
+49.888599428036095
+51.103604619811655
+47.742338287038606
+44.79150684928442
+47.280483843250096
+48.03884510653196
+48.07478826261121
+47.122420410189434
+45.1065216526193
+47.88819315384009
+36.76764658143151
+37.26446238250135
+37.91158042503418
+43.710396764926216
+36.39358339979161
+41.86435392575947
+37.08276338846498
+35.08466232923334
+32.15153121000189
+37.41136334769363
+38.16616415201217
+35.23841089409531
+33.59259637015205
+32.34443122446427
+33.108236150308315
+34.864052362381614
+31.003888130657984
+31.442541018043187
+31.76287829790961
+36.73127330931875
+36.25336392251026
+34.612457337363
+32.768226326366275
+31.833120085821534
+30.9949355339037
+36.850875531155125
+33.838072899380876
+34.49324364210558
+31.79799897953366
+35.1333979592236
+32.784381994380524
+29.180101147723335
+33.07017077612237
+33.110769118785086
+29.479919934425524
+31.03690733244953
+37.98360267522594
+32.78656570882623
+33.40431349096089
+32.24360816366958
+29.24542752760621
+31.597883930729267
+30.474331741122313
+28.683843907791797
+26.76841249709686
+31.159579954573772
+31.248250274435406
+27.34454282135782
+27.229312187774866
+27.846132748437384
+27.77961043033035
+28.335651851531452
+30.49378711888258
+25.89807874356211
+31.786968008254533
+30.247643868382383
+27.961327658074737
+29.742758243157013
+28.188367445267247
+28.74525893277476
+29.11544641390823
+27.92988217001465
+29.523548774482975
+28.150696269701754
+27.60815971502595
+28.62871477781316
+28.216912694969537
+28.863048956408306
+26.199238649061
+27.659959060254238
+29.28399150866717
+31.616458142206383
+29.721591206056445
+28.33913146020764
+29.514075220193092
+27.685999940799505
+27.587807295524485
+28.362765121242788
+30.353491487975447
+24.564367930335763
+25.303950854876348
+26.22130654539805
+28.006212452192955
+26.513351440437702
+30.745290695592658
+31.18849073319886
+32.2356695617477
+30.593628604898655
+28.572001164480454
+27.70551160950741
+30.010620531551595
+29.7516997252107
+29.848221937667134
+31.425783323283625
+31.68809966277591
+27.634314579351567
+32.25284475140731
+32.228580499472855
+25.9892883607682
+27.06331388852577
+26.172580453071575
+27.12435908791889
+30.242368803225418
+28.065304427564357
+26.759244007235054
+30.058470733556547
+30.649077237804548
+23.70022408120495
+28.91452846680859
+32.18885936170449
+30.186799054208677
+30.732065947894
+25.503650663756787
+24.999700544397285
+27.323301925463042
+30.26078393537034
+23.235779926236717
+25.082752528000967
+29.42632077420022
+27.319724419545977
+29.824904898514177
+27.53934922077005
+26.79550717338489
+30.28069397348264
+27.331108547185835
+26.509436078377135
+24.91623615783692
+25.891044692839188
+24.477003728123776
+30.148357822450976
+32.18348952314503
+30.470390084400364
+28.317880212676627
+27.15604913600636
+27.93078957045168
+29.88888158499182
+26.552648595078935
+28.073117908610158
+28.578490071195162
+28.766606134399836
+29.398690728285345
+30.67829937078662
+29.708960164241233
+28.253690315111072
+28.734291212589483
+26.266062942361998
+27.812900320844093
+32.24361037445955
+32.92532154768463
+31.9225166298626
+32.58295491603029
+30.968627138235703
+28.148906657889256
+25.494626994284957
+28.88251010781876
+31.057551832405125
+31.879517594091766
+32.908305578487955
+27.504200818245238
+28.51094969897936
+29.39626390420426
+32.54363892380724
+29.3770027255987
+26.14309312707185
+26.162588228343253
+30.76951798047405
+26.129943770262983
+28.542110492512577
+31.045181769127893
+33.05834645176209
+26.0249430922656
+27.33239110743321
+31.142952310463627
+29.85541541790532
+28.771228908208855
+27.96927229002189
+25.885519953396113
+26.016711773220166
+29.40050448624858
+25.155572207205324
+23.431096730562913
+28.66677483385928
+28.072764623188604
+28.034977349791887
+30.689855082664607
+31.311839590765757
+25.9283189257023
+23.785815202797565
+29.117269287252597
+27.317728295626495
+29.139535528909732
+27.11558763831708
+25.785150483310005
+27.70008612040334
+27.613284377202717
+30.35955877711939
+27.156283616202003
+28.82916322195078
+28.71848839885142
+26.453627774305744
+24.04454321324225
+31.358346313565917
+38.87230601108454
+29.792356108918014
+28.63055223339863
+31.87467190506335
+32.4389158073034
+28.316113736186495
+29.677606152220022
+26.846486925304532
+35.439973520657134
+39.63571299399172
+44.52701917710641
+46.82457347027375
+46.62849577637873
+48.53394475384071
+46.7234820267808
+44.56787846056164
+45.168750563002696
+44.57564075031166
+44.511440190237835
+44.922686600861326
+46.465175392530554
+41.24082798214341
+46.90080442095779
+49.67295548132578
+49.80388499651529
+48.484408258153216
+46.64801198208865
+46.67942543588884
+43.87249090600091
+45.16464704090447
+42.81458845865719
+39.492232618229764
+36.333797682478775
+35.09729365892589
+35.79845498539437
+33.60071558071344
+30.14308831443664
+33.69151139183616
+29.068172048688567
+25.669787681452874
+25.55668590091811
+25.726511855991376
+28.6864935365558
+28.44246531293878
+27.31572303574434
+29.876601248374328
+28.191433923822544
+30.414473470028085
+29.53806702790098
+31.187323109293217
+26.208794272565456
+28.404707758128623
+27.110468276890288
+32.42195940623132
+42.04356861930509
+35.146802620084884
+38.17475369876962
+42.46043762271981
+47.903397095916674
+47.50904079894232
+52.257600086762835
+51.6391053614088
+56.09814437612042
+53.74752273028415
+58.830104590314384
+58.59128186439693
+55.98739163445155
+60.63745585034134
+57.47593968955397
+58.339916571936996
+62.10049374968608
+59.31454659370506
+59.76486748012258
+61.65476767212394
+59.08067555384667
+60.61460847891476
+59.787444274186655
+57.67283934422316
+61.62931906799892
+58.31932577316645
+57.14328001283645
+57.76772648128177
+54.693613276856794
+59.24918509152782
+54.7301523369267
+54.67774015682833
+56.9821888113226
+54.26905226330372
+55.36344277854887
+51.855264262242166
+56.28064314559934
+53.030104602517035
+55.2546549222226
+54.4197465462606
+55.491792051319024
+53.90911001366837
+55.33741311427995
+48.7695354664875
+47.01686858538944
+43.19487305246737
+43.192169562403876
+34.457566572548615
+37.79088091567144
+36.20710126308501
+37.058258534138346
+36.12938835336652
+39.28577759261953
+36.24792540778036
+36.57547794914717
+35.49362444088668
+36.386594988629085
+35.97265202232876
+32.784667617231804
+35.84187413078334
+35.6372452444091
+34.61173183578477
+36.218977318372296
+31.208364043120895
+34.579766150168666
+33.1749284666908
+32.10199206571926
+30.188707216429833
+26.14120785735912
+27.850507052081696
+27.911494535250768
+31.688537752821972
+32.49718081291235
+30.72121188668747
+31.516815640911872
+27.713958084989386
+31.860026289399997
+29.06908692963853
+28.37707932988735
+26.44804776042075
+24.2380689991719
+29.602268394824208
+33.15324893324872
+33.15288606967633
+29.371979101572236
+31.97273150961412
+27.021448597086163
+25.05358462579865
+28.830609607927897
+24.519345495382368
+29.09025214591351
+31.373087951400578
+30.84111511321855
+27.844128871317793
+28.54454685433565
+30.018191855932884
+27.515597075460477
+25.376246407360725
+26.78251404250618
+26.969289739430238
+30.19089299845487
+31.02510226256952
+27.730149744955128
+28.534134392953376
+29.685721354427898
+25.82448015593667
+27.96909598322054
+31.398558126955407
+28.611126114582973
+30.35861705792273
+29.5951730948197
+28.269152149647198
+28.92079573768936
+28.247239136337427
+27.8010398783684
+28.218652363879258
+29.80860250838441
+26.953566492615607
+24.495561081275255
+29.1293543911938
+28.22741659442795
+28.193233228285337
+29.337190115828477
+27.286761888405934
+29.6912664982475
+30.2699160447538
+33.00822832152397
+31.56291484554005
+32.320934721847706
+33.040166644805936
+28.92492272203087
+29.799086367787183
+31.75891712195927
+28.73607164237096
+25.297447379738813
+26.183731434900082
+28.128582705989245
+25.82076227840787
+28.228520979961004
+30.04488439006475
+28.612667063277613
+27.024550647575296
+26.5230522182396
+31.14256791854605
+28.32385895322227
+31.32560297852963
+30.3261276859116
+29.528135728366607
+27.617126930052535
+24.419376998863086
+23.336430455840713
+27.74692802485275
+28.033814199991667
+27.89118277579722
+31.12875379722486
+28.88376428856313
+27.423244038948454
+26.786911890249144
+26.203997966528803
+26.527591847943455
+29.759896078831744
+28.449344360132926
+31.1683163290854
+30.635995615964873
+28.772921217360576
+29.675065615375118
+31.42463994041593
+28.52077642984578
+26.634687532556725
+29.971015260871297
+25.404927461956376
+30.02894952088714
+31.297391348353756
+31.718505825822206
+24.149815724317776
+25.129988948604833
+25.04537586858268
+32.745145008107855
+30.61070178039273
+24.78665951192545
+27.570534357460986
+28.074262427138464
+27.57593388709509
+28.860310460606883
+30.61928592391591
+24.14714641793266
+28.596193418471188
+30.55289460102661
+28.167271326832193
+28.831844806493166
+27.360044019565336
+29.891007809265744
+25.70906720225274
+31.686319953953543
+29.21747229593707
+30.69994349677266
+32.1023776644045
+27.32509280296054
+25.778777811141637
+29.744384098363355
+27.896825770866556
+27.478908985014627
+25.366025094661396
+28.430950037821276
+32.98963856894616
+33.1946126868541
+33.47507653012069
+30.892743835356498
+39.45876303499176
+35.096624867198756
+33.08875580289681
+28.949000807799266
+33.26627339542286
+30.228162836213357
+31.50774028788244
+29.349143923930328
+29.15594452966525
+34.27750020875942
+32.346544788992546
+28.97532129803095
+27.506667889297944
+31.093987295373253
+27.773648777434772
+29.042840981403344
+27.985213361449752
+25.365410500239392
+30.17826085163304
+28.98898031969317
+30.052293620442327
+27.1881432368083
+25.399958724064334
+26.349173474415508
+30.316011510152876
+28.76660278311938
+29.561709244533418
+30.521515309155575
+32.370062408439736
+28.645006454357073
+29.108886087077437
+29.47854724201018
+36.47311542058925
+34.09488875260355
+35.45738047579083
+29.070780582220053
+28.974822217702766
+30.295755800685114
+35.528615189941135
+33.80761288478
+38.057053640541284
+39.251110754537514
+38.480592406590986
+38.610581779278974
+35.188917078573795
+38.43908552254959
+38.40042868887877
+41.33438358163748
+42.301131232384414
+41.840296040363
+39.9530095775202
+38.123168753649196
+33.36775998719135
+35.79759538362171
+36.347327093886875
+35.147004281201475
+32.06220808006748
+34.86119731043013
+36.171287228088545
+39.38611247959161
+35.273443989622194
+32.43772825114196
+29.23847097699445
+28.961945236060345
+32.216655774696065
+30.574127101972735
+29.035056839800603
+33.02018736919635
+35.23250421011916
+32.386564608258865
+32.68978625622928
+32.16533742327273
+31.604454879780093
+33.94947913728326
+27.93715187944241
+29.10624170233163
+31.469703691403637
+26.929148914533684
+29.718754080671616
+27.682101018970968
+30.565466853002476
+28.744692191473717
+29.547076490970454
+31.886703316161345
+29.69372212613075
+26.487123240296555
+28.40039825937785
+31.670818048389265
+33.14900995172671
+32.3650890732379
+33.81714900044102
+33.77725390790562
+29.709379483555125
+35.477512798100264
+42.86972195011965
+37.5736685611079
+37.14513069668641
+39.63570625179466
+36.794426007069305
+44.23202952495977
+41.36155525146874
+41.664477605516126
+42.46435243248508
+43.12587359904334
+44.296396918582296
+45.66685433107918
+46.27008839119525
+46.31097784856055
+46.8565639451669
+45.516287130160194
+45.98351854586035
+45.27904800097346
+45.05208959097721
+43.37131034572782
+44.16423565514135
+41.18805541670275
+39.16410962146401
+39.930749885579566
+45.01741417189494
+43.656730828235574
+42.62003555974363
+41.67528538300385
+43.45779673660434
+44.213949095603326
+44.964514145472734
+47.379693020372905
+48.851859959874865
+48.04358904301424
+51.9651300674151
+54.23705769392154
+52.53660020563295
+56.89184678750024
+60.5336968612484
+57.941766175488354
+59.23305561220554
+60.08519571299082
+57.7881245525271
+51.220340746477376
+50.5768166879982
+50.1627595681226
+44.7049954197566
+40.14812256058269
+38.12274404553966
+34.41095339715967
+34.308246028211784
+35.102768439279686
+37.24657172693587
+32.11933285816477
+29.438272056567598
+32.106621050532524
+33.196421391784824
+31.47735278147644
+28.440158491424896
+30.609098115437263
+32.838918911246836
+34.42161015871585
+30.39893818360227
+31.35195743221074
+28.364388706662325
+29.694372786618402
+42.36590994447243
+43.284229091372325
+35.87715209816892
+39.26836307744144
+45.39810556256917
+50.63782368362605
+57.359085527016404
+57.527191980256084
+59.55563711492509
+62.379664889764804
+62.862165826306295
+64.32908454794766
+64.1775806879219
+67.00179794698056
+67.66945180782972
+67.61356849726714
+67.39837395311856
+67.06027689004162
+67.37874025996686
+66.96643686250286
+66.76601849728314
+63.13795335452182
+52.987573269220675
+43.91460681608332
+42.02085267945825
+41.4205469249619
+39.85129600078611
+35.338672549714644
+37.29825515923976
+39.96209577450626
+48.83949866898912
+51.54114136969413
+57.64804781371525
+62.72469765473569
+65.39891606120514
+65.24358035399128
+68.48951500928945
+69.82275004784476
+67.1359253820124
+67.82251312993648
+66.13901315138013
+65.49771420950565
+65.4294263735891
+63.50612196208695
+58.078954106079316
+57.558260814045354
+49.388410183427624
+44.48032586027383
+37.90793622594527
+41.07581669222721
+41.74559324592231
+37.00106561427063
+36.106399618929146
+35.95098681266761
+37.6987187795187
+37.037516753242386
+33.03575008635269
+32.36272323503444
+32.41842791827476
+29.84752404008077
+30.34942853156791
+36.07758153367858
+43.45488433588187
+50.56134413321935
+54.46707433718804
+59.27489084220082
+62.570554350049335
+56.98924281537159
+49.541004133375125
+47.93354726224338
+53.05700301569853
+56.57286743093556
+57.240169460950426
+53.94006688532738
+54.727919120620186
+53.98603900681839
+53.185483898261836
+53.37207877351308
+56.004101250835745
+53.91402174192627
+57.68085558968598
+57.56659241642491
+55.48648400814953
+56.68783415804585
+59.55632274249217
+58.53243116098751
+59.922985103164045
+58.687899232599165
+57.38952194444534
+56.39677826645759
+57.65222313875642
+58.00849596080716
+59.5866407339623
+59.775754029722435
+60.094601985713744
+60.32524245122866
+57.348435332785336
+57.0759397918834
+54.20164978428693
+54.02734694503246
+55.368716141256584
+56.796271948942646
+56.76269998519777
+54.93693089591902
+55.26172854949609
+55.341814204591984
+52.66445132425952
+51.16530748488226
+52.583852651780155
+53.50979361688718
+51.12369492166598
+52.400054141391706
+50.23933674747917
+55.56481731617572
+51.13923673952523
+47.01435058573913
+49.838377761910216
+49.41337096814144
+47.897736376005966
+47.094030146011164
+46.85346087778102
+47.22575800696137
+50.59138882047818
+51.04996409001514
+50.60702068745192
+53.142756753948646
+52.70303657021415
+52.346419350347354
+54.330033751615
+53.456849748813646
+52.33488573283786
+54.945007588414605
+51.81958009476036
+54.40326082857227
+52.961998202736474
+53.942671802161954
+55.40030314790866
+52.60942480696265
+53.30202767424109
+49.6901432423172
+52.545310666694064
+49.46222775961175
+54.54962768129285
+50.645958211363144
+53.92175933639179
+48.89686468993726
+51.33225689680059
+45.60737182815834
+43.67794547529366
+41.59494416778982
+36.181362872715326
+31.185627506577745
+35.706830850396
+43.932367460818696
+38.7088115424737
+44.50588317659017
+40.70545086520613
+34.64775506467478
+32.750455674792434
+33.45471368835622
+34.47408867510639
+34.37225974703851
+32.04356869690223
+33.69111442971246
+33.05951888406025
+34.02123710122204
+31.837190752107404
+31.696333722980455
+37.34117570579916
+36.2597997013542
+38.94240725390967
+39.68590943404082
+32.27303601362057
+35.37124551177199
+36.78312644112778
+38.30361807968724
+36.66090069579529
+38.943680886604554
+39.00840228296674
+34.57201898332049
+34.60872900189794
+29.969500912096436
+27.716550429536085
+35.02592298373726
+46.920930587483284
+42.53777408521458
+38.25293874569135
+36.67639754552964
+32.5435025157789
+33.60681917310825
+33.70338602745737
+29.327522351362177
+31.432129287901404
+34.07256612553037
+34.234148800963624
+29.605153557572493
+31.712949921591772
+30.187610345200866
+32.18345184572519
+31.51130844874993
+30.73162973521559
+26.295046776267483
+31.64030864964633
+32.9040340665554
+29.492694252802906
+30.906789353997723
+28.771414234459527
+29.50833108002051
+30.115996139328914
+29.627052708422752
+30.825402027921925
+32.57498243375552
+33.87862863680134
+30.478502067538074
+26.38556263494533
+27.063103598819154
+23.461821249985206
+27.955022249836617
+27.403944471044028
+33.456614292569
+31.595014960520587
+26.92533702314283
+31.616157944751606
+31.060256742900606
+29.55259260716295
+29.78454659905448
+32.571533659466525
+29.146640007458032
+26.532945213534262
+30.095137330395048
+30.115488955130232
+30.631014567095804
+30.45970325066162
+31.067434875249035
+34.308029326824865
+32.1491059235411
+28.219554144072347
+28.8216506670219
+30.59091170220114
+31.170587919392162
+29.383561864139338
+31.497387257946627
+31.896776198719195
+29.602159499558766
+33.63504307959593
+30.043457901308855
+29.083941152843934
+31.491049187012166
+26.309177413652378
+26.535368419557315
+29.56443216767248
+27.652276990441322
+30.650790253440846
+31.434841939785116
+32.19850115704968
+27.309582461166087
+30.270158967785363
+34.321242665426595
+28.767667072895293
+31.47798268005259
+28.174674030471394
+25.49443966527984
+24.85934151462969
+34.706366420046166
+31.725988404276166
+27.700645233211517
+31.058004303503708
+28.435669991846368
+32.065453015389835
+31.483683317660592
+27.877815039953674
+29.584180667149198
+26.786980021875735
+29.60309005828117
+29.855221088627246
+28.892814315276098
+26.3379119663726
+31.115720110110303
+33.1503366765357
+32.104598610208825
+29.036655180332744
+31.517953318748425
+30.238062937696924
+29.21526363964513
+29.865889429774
+24.44148531939703
+29.029782165866393
+29.20669554369509
+31.024189979210632
+32.421535294200865
+33.70210283318511
+31.667555872040182
+27.39869733462048
+27.808593982070846
+28.28372645789696
+33.81334281548146
+34.022072496106915
+33.91213875599054
+34.318783101749034
+31.872259789107787
+31.71912067444292
+29.628832143674046
+28.3176628970771
+33.5270194915383
+31.85725359188305
+33.440482459008265
+28.588386521313083
+30.318623349925673
+28.33347270592948
+34.78790654736524
+33.016495647643254
+28.844496892402972
+29.81457169344364
+31.302948392631023
+26.332947165800178
+27.680195239642885
+29.097103294616616
+27.21524963584899
+29.651112925217518
+30.897219946953626
+33.36680891738747
+31.810005560848538
+29.745040865922363
+27.972503462862903
+28.66363882610861
+29.342473599923082
+27.792509564973827
+30.23154320513126
+30.512652731817113
+33.44002125238893
+29.57946904362423
+30.091572900964763
+32.35019851323325
+31.057027509514185
+29.074100239327905
+27.702337842258913
+27.719878302660675
+27.68658711764644
+31.756271250770354
+27.27807271934141
+26.971999068958866
+30.214396754083708
+30.642515023742206
+30.379850717933095
+30.4765733052091
+34.57461506377946
+35.119400081407704
+34.94168060234709
+28.50364187401692
+26.339148435145958
+35.237978145806494
+32.756383369369985
+29.6347862200724
+29.75918905171409
+34.010142322840935
+31.801345428301957
+31.963472985369364
+32.83086510395658
+31.88300212897161
+35.6049817748691
+36.5841781527983
+39.59764976732117
+39.55641733724077
+40.13113925260802
+38.3273662924245
+36.17080153378133
+36.898186909414946
+33.443853006715884
+34.91002068910875
+35.38385890159694
+36.15182473945309
+36.837045976771606
+36.36740994143092
+40.78377968604883
+44.55425312784092
+39.49327246691517
+46.04901095525603
+52.596834453618754
+45.0344759871114
+43.457282657312085
+48.796439117652454
+40.445020411766045
+41.71459818684345
+42.65326244303782
+37.82674075514455
+34.39301122168882
+31.15117026794026
+36.962966339533764
+35.66771897615759
+33.465388579654245
+31.4362873785101
+31.194473163786114
+29.366808852112896
+27.899220891769332
+29.262558075387332
+29.266368878387368
+33.07069391537368
+28.588633720087657
+27.912590544435304
+28.605915571931646
+31.178116049424005
+24.976026388038477
+27.145310657336452
+34.52221665675073
+45.3763053718099
+38.001639392767586
+39.07880523544018
+40.03036427698061
+43.632162425697615
+43.23120248199302
+44.86111252962385
+47.00856379565366
+51.01343911712951
+49.852744691643665
+53.9028204668423
+55.00217973572404
+49.93990624692818
+53.40596077014218
+51.49101557090814
+50.296720316224956
+53.34673085183604
+51.93287588580699
+51.68237791509753
+52.25643664703438
+49.51865316165085
+50.82263358214365
+49.837828178781926
+50.61129769541866
+53.625360600717535
+49.375476803103055
+48.021876889832306
+49.087113559814576
+48.0356230985509
+49.54913352179011
+46.85789922920349
+44.605934736688525
+48.02924493792174
+44.98908215137291
+47.92048700032481
+42.77740448520437
+45.16743720390983
+43.8912429642196
+47.55326150470366
+44.58761490943512
+47.725177574172164
+46.031317024443496
+46.60100828860156
+44.76463615112406
+43.60017024047467
+40.67286297940468
+38.58833775602181
+33.182751779601105
+34.87127505489346
+35.0198154889931
+34.84590467662633
+31.960877680930395
+33.63603780055472
+33.73472484011337
+32.848120588116075
+31.4122047302845
+37.591106919669926
+37.61174174945434
+35.439676376631326
+39.39756275162418
+40.410371311255616
+39.181372228658404
+38.365759864163465
+40.309788842618936
+40.51442491538975
+36.013210378533955
+38.291845822777006
+34.219810635118336
+34.6369785636375
+33.18350373819467
+32.299245302178235
+32.98730763334069
+35.05800208680573
+35.714947341962
+32.165280017858706
+29.39644862560354
+31.73836397653382
+30.792782293726688
+30.725414843521335
+30.14003092631576
+27.163088250899904
+30.53137413430416
+35.472129028901705
+44.47250068907016
+37.05180487954803
+33.537710002745385
+30.364964884989774
+28.331966576013414
+28.476677872202856
+25.62113640073494
+31.29762407221824
+31.90776055550863
+30.33862422662675
+28.91075029445186
+32.23545476347441
+28.233476620673557
+28.217513831791592
+25.056064435721424
+26.26633804822167
+29.746096386294113
+36.38482467900768
+31.685717431092968
+28.543136768491564
+31.187230097997627
+31.12656165240689
+26.306713134638713
+31.306703137791303
+34.04127211423534
+28.176218128829973
+30.746359599495875
+29.032664441914676
+28.319740398029936
+24.80972229646642
+25.07209675603025
+29.858354572735905
+28.922153092859432
+34.110685684680604
+31.487660622078693
+26.941441948091708
+30.00301209399032
+28.70320954278904
+31.498912044717287
+31.515936551582627
+27.061380085244167
+29.077249464853935
+31.72737389031127
+32.131256618274804
+31.640299155910824
+32.78480365858425
+33.75480187686142
+33.12096610113507
+33.38194659126901
+33.836418063027
+33.374854570861075
+31.29553278209599
+28.45096179727217
+24.815330968472793
+26.163147451629627
+30.010956553234976
+29.49920268499369
+30.196773985243524
+27.549902955587015
+28.17400008409895
+31.214965721181443
+31.340563095938833
+31.023548556417637
+33.247242009591616
+31.913630536057923
+31.556699263070556
+27.89058010835862
+25.81051610289566
+28.041834872291147
+28.356601678267467
+30.499499117002145
+30.14490187964158
+30.799114783761937
+29.01705905798096
+30.3014975861756
+28.11637014348625
+26.670701917348552
+28.586235159006506
+27.99939229244714
+29.491979990101356
+29.821773159126337
+29.17457000675597
+30.71313591321514
+30.993492531333914
+27.821749270756413
+26.987713444934954
+28.044001687672207
+30.53149928577902
+34.24461333784804
+33.394446485971145
+30.77393571615744
+27.51041784779062
+24.9232542756597
+30.236467817850226
+35.14791464434715
+33.399813926174176
+25.954065715417556
+21.30190134808673
+28.711462675780055
+29.215600435230925
+30.52307048533511
+32.643516912119594
+27.371036525668302
+29.388925690459672
+30.214622591878495
+28.833853520771598
+30.40881482011804
+30.08803068536774
+29.336723698330857
+27.076773648049468
+33.343669634206705
+29.757929833837437
+31.227515825097825
+34.93855329690477
+28.69257159485312
+28.78317722315795
+32.9693316980087
+27.307329319891807
+27.45652707518559
+23.760981185919974
+30.61221994702653
+34.211248643879955
+35.711491919246896
+34.29450287811959
+32.9730240577485
+40.524781476626664
+39.025492017880886
+31.207077793264105
+32.6731418385359
+30.966674730002595
+32.08184519839037
+33.486081477476006
+29.005557938902157
+28.899200310399223
+33.627320288305114
+34.53785308052349
+34.35101528664704
+33.859316361170045
+34.19357902549372
+29.64304831003426
+29.651526213769614
+28.87972272900933
+27.113867156988917
+25.504972985139645
+29.924831096703514
+33.19298445680582
+33.92145788545537
+31.291839889293456
+27.970043855587164
+31.064983324279922
+29.808196786905896
+33.074418748411816
+33.67193239639879
+34.70081751569542
+28.929811365923328
+32.023241975134354
+33.98620160808807
+34.03978895505172
+34.21858001113252
+33.20569368847535
+30.265451336763036
+32.730354830965624
+35.19343094555205
+32.794355965886254
+36.41242381474885
+39.79080547112017
+37.6371030911371
+36.498811142879006
+38.970127107150624
+37.700049541295684
+39.734300766631065
+40.45109063550164
+43.4986786364001
+38.67855806486381
+38.59061460249204
+39.063526314226756
+33.31162700144439
+29.993774569888885
+30.4451401020999
+33.76466169850556
+34.435315673123185
+31.995074028342813
+32.797615255565304
+36.00475353192061
+35.86854419340993
+36.0532963085041
+27.47208122193689
+26.63630661480211
+26.440438323142843
+30.674934901561244
+29.22395234833151
+25.29467052178262
+34.72327751979823
+38.078800434764
+28.239937347243938
+29.48658450429734
+30.843306203134347
+28.07190226284837
+26.677379668899718
+26.581141315967088
+29.362500718874813
+26.902533469770177
+25.289703521489713
+30.862402498787475
+29.94898780533005
+32.124653788616826
+29.490454571529767
+27.77973298385855
+28.092185340040317
+29.63571365881262
+28.890593850293243
+27.830770789577457
+30.92196525731937
+35.39308836278305
+38.232714940153855
+33.77572689764757
+32.1588225237345
+31.704482121893804
+34.488360842654615
+41.89171078106599
+36.325836386390236
+35.406105150512474
+35.52793147141897
+33.90058375348319
+40.2653897248848
+40.71156796199068
+38.40685190461213
+35.84301192165694
+37.43253300045649
+41.213496836151634
+42.70877540801132
+39.76383726033317
+40.98302380153885
+43.77129704754823
+37.18611443229581
+39.39266038231213
+39.769601775717824
+39.87718305743189
+38.3442605777459
+41.85112547270516
+45.61891933778449
+41.49465145852808
+44.358590598879545
+50.61819794306463
+45.659689991070124
+42.50780391065354
+43.40842262017022
+44.69562910918843
+48.39883009277684
+48.81316541603222
+50.92822390267879
+53.364544565302644
+51.36218889577965
+55.837802356901875
+57.9761868390991
+56.02153669697661
+59.65835782306944
+64.62493246307399
+62.66199315161228
+62.540009839308304
+63.331660907324085
+63.736498193884245
+55.479017251086205
+51.37374039682996
+51.779664093929036
+46.319691642806546
+43.86243283199913
+39.67229139046916
+39.69789151270864
+37.96098975244227
+37.416016668192015
+39.04770167150177
+32.639711605041214
+30.205446393999196
+33.15363369707808
+30.192980449771596
+29.336586853072504
+28.032136080157912
+31.995300774505324
+27.73755043685759
+29.796771983942392
+32.09081986743681
+27.50813380486231
+29.350187911310442
+35.007627005899735
+50.92010126185942
+48.34155653066729
+38.08038628459111
+42.09770127745219
+49.88874399645754
+52.29355886661945
+58.156528871014814
+59.24609677251278
+63.21394733468719
+64.591705922882
+63.73735362952121
+65.91783563327178
+65.3054178469257
+68.69051442650579
+69.30426945582775
+69.28085265745622
+68.97657384798362
+68.38636580829828
+68.38585172037108
+67.85285331219173
+67.26744124854181
+64.906359468983
+55.52391727906886
+45.2420536247547
+44.54982231647189
+43.522030477538586
+42.23315254338158
+38.81318907451948
+40.28113980201114
+38.73468195947445
+48.836415998833104
+51.116648053586744
+57.70627160180949
+62.318368781302866
+65.57640137190135
+66.13238777169003
+67.66643791355885
+69.5057322388181
+68.39949366539707
+68.8160335049275
+67.87712149802647
+66.85766200947992
+66.99626436232384
+65.28737925038703
+60.033204915886266
+57.90914310200341
+49.315816485011155
+39.70469893056443
+36.49988171537309
+38.906811264369
+39.2292539374366
+35.79116207967651
+35.50262004045369
+35.68707427718802
+37.996933883960224
+37.0181718575529
+34.23133162430976
+31.261943680599302
+27.60318916642369
+29.032383927672598
+29.11887726444398
+36.28614796422275
+44.51857030159173
+52.22615915097469
+57.12406572125935
+64.47287664018751
+65.2350357029647
+60.177672763946376
+50.794352143495225
+49.9152069760593
+55.38568522535368
+59.94673153123825
+61.60641226949553
+62.47261930097119
+62.396656122271175
+56.68226128268931
+54.212070955783844
+57.04015635111714
+57.53543333007194
+57.02047718038246
+59.080117069192795
+59.579267416494964
+57.05345981174451
+58.78872531269962
+59.341409464363664
+59.24034018400507
+58.347377738429365
+57.064158172641754
+57.483961489774316
+59.09555028122148
+59.21750554722199
+58.359576877342164
+61.03685287263883
+61.17050689720081
+60.63702538460627
+60.99106719673953
+58.3926607018132
+58.04866220018576
+52.32126453937541
+54.604396516717195
+58.82149039493267
+59.20880176527692
+58.29580771350133
+56.8679248871275
+59.60394477460182
+61.06696113828898
+61.33997326946906
+58.08608353833494
+60.77742237209357
+60.47553164214056
+59.04746435585336
+58.311647763144435
+59.919657366088046
+66.69891192696
+63.4599354315765
+60.697779147393945
+60.22822377221558
+61.08606952848937
+60.78684755317545
+58.436400792189076
+54.008629543392956
+55.68482102769212
+61.712412163956884
+65.68532201035146
+61.59263166706076
+58.4900699856108
+61.08854581302465
+61.5991684223559
+59.70989809543346
+54.70231102835166
+55.15789114982267
+54.406241821217726
+52.33785847282853
+52.49677572386864
+52.053421479553705
+54.155695729863666
+55.307926260547475
+52.72463596530693
+54.143556915369146
+51.98999576178044
+54.6882313039078
+52.231028252249324
+57.60376676010845
+54.68147468268748
+58.29879774749377
+53.13990905006199
+57.17393748593584
+53.609176080184426
+51.94856759155888
+48.528288173614285
+42.848527012633554
+36.484673367114866
+43.914502612436216
+50.95202865832614
+47.13460187207509
+49.57698816938725
+45.69762004264371
+36.92240463018804
+37.30897668388447
+36.51126098927482
+37.87725184830093
+40.40782087824402
+33.352824052131595
+36.12651953886804
+36.202314760719716
+36.76947213518285
+36.0152886382276
+34.17887833685572
+39.88937605710077
+38.27534505331198
+37.307173283990636
+37.37854956395964
+34.1778711911748
+37.36885018091574
+40.00453422586384
+38.49271369480974
+38.135871289430675
+36.80359410162784
+36.555388077926125
+35.985310264713306
+29.222874942710703
+25.703916715640034
+32.348866140186445
+38.26796885993907
+53.29287855228247
+48.58100247002715
+36.911013157735326
+35.05836721677909
+32.98461206664774
+31.221040529556774
+32.85663431891791
+31.56928878754961
+29.529251518331492
+28.0488605955059
+31.081757210436862
+28.131519821668746
+29.628720932897366
+30.9628132927091
+29.91837867989716
+30.71244596375358
+30.708895065416513
+30.479778732476717
+33.56503024178967
+30.647300306360123
+29.90178340751706
+26.91247365804763
+26.722675896330855
+27.499611267228545
+30.835762300114524
+29.16344546950903
+29.918083160230367
+28.591079928506815
+29.844050843885654
+29.15172491188835
+31.635536436028232
+28.28247648438048
+24.474710354645993
+24.967059260195157
+26.05725154471851
+29.407135788837067
+28.671421089248057
+22.55092577662022
+26.79397499820304
+28.483675518430744
+29.665789503610583
+27.703595050154604
+27.7921893422225
+28.77691223240039
+24.78959721057052
+28.292220123255163
+29.878430802888232
+27.01035433537932
+28.71894623645734
+30.607892330065383
+27.8996891021971
+23.830138973931142
+26.59663696902784
+28.031023641846687
+25.442274949797408
+28.269845069169875
+31.943909833291585
+29.778149398580354
+24.90228069701986
+26.34801360068772
+28.457811520110496
+28.33501107647487
+27.425731024181147
+28.704257131556858
+27.8450957214351
+25.892163534847725
+28.23826430758119
+25.39057611228648
+29.262734095593984
+27.109432682684783
+27.602129172491985
+26.43356940650709
+26.298002603274824
+28.80937717394376
+26.350582546688074
+29.362461865624226
+28.290873334506827
+28.180998916058726
+26.250652840273574
+26.46015703566198
+25.134543510773014
+27.334258322037456
+27.39042747002601
+24.690183256657832
+28.159783751177187
+29.67454942273193
+31.125359516519225
+28.90649914023379
+30.51111316222125
+28.603009105051783
+30.03393782135265
+27.307342551067038
+25.373865973572492
+26.70526262770494
+26.41256064296728
+25.69100035777656
+25.039617606201546
+23.550212867472567
+28.79253456003424
+27.891581517769282
+26.84022078485488
+28.182711546932254
+29.56844067428348
+21.6590414386868
+26.889979859405358
+28.689912867153097
+28.224848370266272
+31.570330147002778
+25.427929825261458
+27.4996776232269
+26.90844581305629
+27.320305355807093
+27.41252657061628
+29.54789789958032
+26.401535958368527
+31.665525293096962
+30.032004280220974
+28.880794565043715
+26.64384444557011
+27.867719933391328
+28.97040193366942
+27.49019717117251
+28.728724246277025
+26.71347692231234
+24.191108022533953
+30.239433365312564
+29.087464999631734
+27.10254511651533
+28.044444630014553
+26.76888354771721
+20.992642801695084
+27.966950377706027
+29.23870007638935
+29.962012196539405
+27.279872869060725
+26.597559719875477
+28.872001716120238
+31.325997857737278
+30.626156494054797
+24.191186565978
+26.778462601210137
+30.067388422412833
+27.725971682212403
+28.928035085200804
+26.47113063545865
+29.84767867621042
+28.127723949653074
+26.16305254173524
+26.636276069271275
+24.725124979344642
+25.227758184244223
+26.346490264586762
+26.818403848102363
+23.815491330819754
+29.145535164319824
+26.630541590381213
+25.276476464590687
+26.83952531440754
+26.54292216545727
+26.952848936762308
+26.884595573410735
+31.77639537544097
+28.499626184367557
+31.965141158165054
+29.948972105309196
+29.24621714517444
+32.88053187736456
+26.35171713411708
+25.38349093845845
+24.089900770989587
+25.3957942997166
+30.845036705564084
+26.691489324259976
+25.96967739622488
+25.51761052438519
+29.25665749134464
+28.644697310149226
+32.216155817502525
+30.59710465191131
+29.409245383475678
+29.89158327853464
+29.706129619967967
+34.08299794272237
+33.65788352353782
+35.651303862752115
+32.62867131746951
+32.78327486862679
+41.81253841649195
+39.88866358896876
+40.72070365630483
+45.08615220056567
+45.93983234722296
+47.63188431936906
+53.07766595102895
+47.78065147793008
+47.27326792702419
+53.64698844234027
+48.58844806579881
+46.05614589831989
+48.19887877266544
+43.75963643620023
+37.95027278056255
+32.630197416897644
+34.53941901356821
+31.567562715461023
+28.74978493889232
+27.513977391536486
+28.064633071894463
+28.67584148382487
+27.29882050194597
+28.264603970290878
+27.99863907975842
+28.42088035586842
+30.09924731571968
+26.87283631607336
+24.090385550465882
+25.590616922698842
+28.056706416453167
+27.35471750798753
+35.08798128467245
+46.78516852795925
+40.01549687612942
+40.3610506886905
+38.91418829438771
+43.912363754738166
+46.562885746290334
+50.938891500914394
+48.34390349753818
+54.07906993184733
+55.75953387962191
+50.75129881020972
+51.17349953046923
+51.36046449045297
+48.08303552440796
+53.99242748676412
+50.18787013100338
+52.01575275126124
+57.55811666944287
+57.873868515670324
+55.59854230798898
+54.57052567790134
+50.27256415493888
+53.19057390552066
+50.05252094914392
+50.92598824682747
+48.88980975499467
+52.617179929955945
+51.092532837660436
+55.121980725052865
+54.912225876635674
+56.035913941193215
+52.439024891647946
+50.281621026724174
+47.57124727144951
+48.5553458708443
+50.62237155773251
+46.702713695819455
+46.03823811161689
+45.060184058764804
+52.27701631324495
+48.38835973275472
+45.74141057887705
+42.347531837997124
+46.01300569001528
+42.6902087798745
+42.09204677003448
+39.050877827898645
+39.330591801654926
+37.14154185455709
+35.568235959303465
+36.396527829832735
+35.16057576790185
+40.33643327996649
+35.806626963566984
+35.96735938837931
+32.508070786451626
+37.430628617007876
+35.03813114502404
+38.01300869933838
+39.88993762066928
+37.41835744157929
+37.72703002219742
+35.57799245962883
+39.864312949185134
+36.50155454631154
+36.68228725165601
+37.54755897177403
+35.0265768822408
+33.211705834147836
+30.860278433085952
+32.429498302426055
+31.481561456968237
+31.94599390982397
+33.724318740135075
+32.85991169738227
+30.91043363849991
+28.944380959057483
+27.651919634354414
+27.95143497495701
+29.39945782798415
+25.760877079526836
+26.2435333292144
+37.246993729895834
+46.22938241553749
+36.45048615640388
+27.72267286006624
+28.402094694389035
+30.831204200187344
+25.86230717822545
+28.036687845444774
+28.688621069645208
+26.838181945686117
+28.11777739332453
+29.147908324256022
+29.703287822671456
+23.872447559673205
+23.462542210359786
+27.598372985805966
+26.88006760668337
+30.116036622005268
+36.58899273538793
+32.89268280673075
+25.836829596637514
+29.48577744041853
+29.813311435483214
+30.140476078102395
+30.006572066923496
+30.589687543126686
+29.060964433761967
+27.26146681435381
+28.715496201766342
+29.457845302619432
+29.438936581359144
+24.873999679769994
+27.329568750291884
+22.813489916302345
+25.252871488622574
+29.30564516447849
+26.85092929069917
+28.169255906193925
+26.496262717334915
+23.943963973327712
+28.128017539662196
+27.846185638371736
+28.14004151075359
+28.87977408494457
+23.832529725092797
+24.546975499192527
+26.783218878657294
+31.065252060222832
+28.465034527300915
+25.84963267344824
+28.12971065301427
+28.331991462747283
+30.194506032785284
+27.94882227046253
+26.464517820798932
+29.51340269670746
+27.875672979867517
+26.28819797283711
+28.02089228025126
+25.14299023976075
+27.512602423748092
+28.766798761285216
+30.915940158577314
+30.364856960539626
+28.817697275439045
+30.69816751819542
+29.458107977711393
+28.04435782324255
+28.629098288909745
+26.834235299428016
+30.144062444061817
+30.436210954663636
+28.887191877279832
+23.912799691113776
+28.239140571719133
+29.652080041622256
+26.435109332411358
+24.886783830231465
+26.172480861785075
+30.455993916030465
+27.559808466087503
+24.537412520605542
+25.1661260877801
+25.43587144272496
+25.070022121615764
+30.156358308614713
+28.44671026127837
+26.49757320237262
+27.66829732222608
+32.493996048797854
+29.30930732618134
+29.960128266727494
+28.083903208389756
+25.179650871290875
+28.047211386510057
+28.141831474043215
+25.720907383536783
+24.65393979101532
+27.948771902587453
+20.660457368725105
+26.64397839720239
+28.484934269298634
+25.550722288077154
+22.929916266372743
+24.90513266172931
+28.85852367138621
+30.250623435766656
+31.123750243612022
+29.69321945147786
+28.46718019194232
+26.858375129379226
+26.91738334670542
+26.34836606647302
+32.68958308398976
+29.648703416745278
+28.988020847504558
+29.574344465690544
+28.23909979528618
+26.479307535456826
+25.373558709828885
+30.35046559369806
+27.67617011600531
+27.565890310897572
+26.73386373783923
+28.52391967148246
+28.4644627640305
+37.86649443880054
+32.78893783702168
+33.915160523282566
+32.18206849169668
+33.06224447980179
+31.650559404568767
+27.25307174143218
+30.509171467375353
+26.36317767613872
+25.48695832535043
+27.722561366332712
+28.394655916803103
+27.722667237539454
+26.46421002663736
+25.012895131765873
+22.339317456744112
+32.279678593051116
+33.92459668474406
+26.769865273995563
+26.88303867198222
+29.79790059451578
+30.5229796684484
+30.75003299929439
+30.685605634536657
+28.069405396683578
+28.41299512996744
+27.357834257398693
+30.684718972903312
+30.304683334703768
+29.421594867492004
+31.732469295642815
+34.714110261156335
+35.10319907526309
+37.03924166382825
+33.61872367997677
+33.499828898260034
+35.809214535497276
+29.99277818718113
+37.732831408214146
+34.46345411478411
+32.40487282563768
+33.747197281218476
+33.9602967053589
+34.66444291809924
+33.39174608070326
+34.70571557044836
+37.81623544490244
+43.907230027140024
+38.474572191039634
+32.570683043464655
+34.0408400106363
+30.864712887995537
+29.722367045320894
+32.321657809119415
+32.06196061228543
+30.81575871547622
+30.91464713468345
+30.817103949967432
+29.45313678638051
+30.525141209857736
+32.15481607691869
+25.213788653235298
+26.28497755687779
+28.008922408397098
+28.134635345174118
+27.76358024885657
+26.952472450052724
+33.130611237037286
+34.750040273517655
+28.687570622194542
+29.05347125934648
+31.619471204333863
+29.92107111551327
+26.79696766094675
+27.877277103582017
+27.870704179045404
+28.320912295115477
+25.82844199307327
+30.227123372728357
+27.921028973898913
+27.179000639794765
+28.090151015103885
+28.118714200531812
+27.831394478918384
+25.565773694631943
+30.316570369600058
+25.29612700861749
+29.578752309013836
+29.157165326848073
+30.926912337465097
+28.330072279839428
+27.736456083996714
+27.042962127355892
+31.737786297931095
+32.60581996092061
+30.59462024884313
+28.984183354271536
+24.6308460232775
+28.428730963918312
+30.423025719324826
+30.721993600234455
+33.995193307748536
+30.787467341670137
+30.396306054337515
+29.823302438254203
+31.212618244336667
+32.89852081884236
+37.70098002395743
+37.935080250707955
+35.83924898225028
+37.21632680743872
+37.09696251940866
+39.900275941162874
+39.868322017079954
+39.66263467111086
+41.932322442823676
+38.21862560644463
+41.03106739151913
+47.731713474120326
+40.11376487029412
+32.310464103064575
+34.73601052345097
+41.204022026786916
+39.96766190092605
+42.72899356051364
+45.82025551772071
+42.538398129240086
+39.87409854497692
+46.52377648465506
+50.37988537988626
+49.47974437437166
+53.063579061370966
+52.29542249275783
+52.141901552094296
+50.74224285703778
+51.648607276326345
+51.15896842671484
+47.750353647510615
+45.93679864041441
+43.24791613080542
+39.313288165848824
+36.984318532543284
+29.92708554021702
+32.78088407449242
+27.61813360375885
+28.14117544180121
+29.19127455795136
+26.95209004172976
+26.162494837655288
+27.958181380883104
+24.57180764488048
+26.87977558094923
+26.52246034053779
+28.74720337663912
+25.589049477799932
+25.71929420885182
+28.549643682826286
+28.625868406642653
+31.063234161363724
+32.262595489524315
+46.73824082000797
+43.59342763312538
+37.631461334562445
+39.44851013294145
+42.050111182176714
+43.67962120368759
+47.04922200270415
+51.363032352042616
+51.83195702117098
+49.44967099861967
+50.61289552549851
+51.358330177548616
+52.92349332735841
+54.9101965515661
+56.31382590173379
+56.09642894781056
+54.31763863639446
+54.855316411457686
+53.331789656546476
+52.73890300903389
+49.51155854292308
+58.8508423960898
+51.7655669813213
+35.62548336581786
+36.96142113251199
+36.35074688066166
+36.35950862592354
+34.669919115863976
+36.7582574112251
+34.118624661913046
+41.23767628399446
+42.48073680093334
+41.21079208541474
+39.441216342544216
+43.60545045019854
+46.108516373119016
+50.189257025753044
+47.76302766195082
+53.31599244359615
+50.18379200594433
+51.93077076203714
+49.070338178269964
+51.45412047870044
+47.1754004189656
+48.45795050092517
+42.043900369787224
+34.60066054125993
+30.93630024811013
+31.022869574570038
+32.64756726788043
+33.41983329782114
+31.41105714392269
+28.73944869412091
+28.979667216093034
+29.552831615216604
+28.072210076860813
+26.694102953149624
+27.548198913350106
+30.748840856661104
+25.32738204025003
+27.83678153727243
+25.685403187836428
+33.59568203086553
+43.03949584161518
+49.4443216402375
+56.86162595943208
+55.49468463068961
+49.906339368208684
+40.541980340003924
+45.93997031790725
+49.95396801074148
+52.757485087893826
+57.37273420933259
+61.23619443671518
+60.874225301397175
+55.00420413437629
+52.23609413551351
+56.189370422245304
+55.475846089742916
+52.32815320717726
+54.06065469206185
+55.5146557206629
+54.82144262689303
+57.9880891449888
+54.74277169772952
+54.52575758512573
+54.049109171969704
+55.56417897268707
+55.48708178715428
+57.49329276581071
+58.11996605076724
+54.999327471134194
+55.863097976365935
+57.0933724214744
+55.603399013189176
+54.31533016561223
+57.06652935988498
+56.43199212881874
+53.353958084293154
+55.50919213848286
+55.33662450502803
+53.30579103492917
+54.59826206435902
+55.478588614167556
+56.346723481818756
+57.5508789137516
+56.92261658747319
+54.84122169146497
+55.31471128421151
+52.50352637881333
+50.529731650685875
+49.91734359332893
+52.598778558768146
+56.18773532630102
+52.57389997845455
+55.291019723500604
+54.698993874322376
+51.91457712721197
+54.006365628381815
+54.59675223339315
+48.86205984524142
+53.206470956353705
+58.93494268521768
+61.101519491203746
+57.437897983962806
+54.945363959358524
+57.372612093230344
+60.09025063755453
+58.4313729561558
+54.93369198909924
+55.296138419683764
+53.46620203427621
+50.13025921242518
+44.588101079581435
+50.70258197051929
+51.44281223476499
+51.998041546797374
+53.168164671744265
+49.16618443480283
+48.84245954099375
+45.86106520032581
+48.8032445205634
+46.49140911367054
+48.3526675908295
+45.95152825138675
+43.7216234506185
+44.478720684520155
+44.26249236197894
+40.66334402308915
+37.84607419468268
+36.28128268411179
+36.19333963504971
+38.51917954494155
+42.35059816228762
+39.334927052321206
+39.554346827621025
+34.85933760285624
+34.48828128001705
+37.05828721668905
+34.75987569330697
+32.21238973403567
+34.33746986928199
+32.45031306013273
+33.22906847739455
+30.7967889081563
+35.85784904774148
+32.45153051922246
+28.675468055827835
+31.13984942209308
+33.59493432772926
+32.20879288446572
+33.58305843525028
+33.21641836011834
+35.727352040207336
+36.56679014797754
+34.71209818656746
+31.897295698871048
+34.91565100555253
+33.270821306817524
+34.22646408953108
+27.89611936000712
+24.644727947810352
+28.453295535906022
+39.12303442645178
+57.002544408014955
+53.3431199987934
+39.12517877713108
+36.72810051955484
+35.37858939002032
+33.19139789290621
+33.82367731963592
+34.207465335334305
+34.435073073067926
+23.708302801531644
+28.054111929305847
+28.36273924064176
+27.066114668224074
+28.142459148410936
+30.609491953840447
+28.34222211719191
+30.322681961571263
+30.127296965813187
+31.29808489002079
+28.764269515957466
+29.633569702698395
+24.17019270117143
+28.108823625983632
+25.835673870892464
+28.507780048503236
+28.200050696466093
+28.4664048034264
+27.31071949795343
+27.558834581118532
+30.264837376980793
+29.342241844857625
+27.657210876621534
+25.630509192959323
+25.23458145168142
+25.14222751542536
+29.809820993879853
+28.5348719265955
+27.051886087986418
+28.11414562611074
+27.458434151087104
+29.944022314620923
+27.347199916488137
+26.734316501965296
+26.628267968227107
+29.268569475501394
+28.225429430364883
+28.709256315322705
+25.417808354602556
+25.97949914307945
+26.557007362142485
+26.863419209185224
+28.156701362252605
+28.17775743627037
+25.794784596592592
+24.78043949662559
+24.757770311427976
+30.801702614378215
+28.667114706383657
+27.449664644143937
+25.853895090746306
+27.520885097309915
+26.342294924923237
+26.939128766521193
+30.620235056343546
+30.510579716839572
+26.282895007288744
+27.84701528768032
+28.288821305315523
+28.862387972987108
+25.179697077966665
+26.49306835460773
+27.641228809223065
+25.205764616373273
+27.33556310393584
+26.420341113785796
+30.31183083137671
+25.91247391814845
+27.740079499122047
+25.64710975458118
+25.888249994476098
+29.264067614338032
+27.97543556300313
+29.019241291148816
+28.266458458219617
+28.925412408767713
+28.744758207596533
+27.304460348887005
+27.336737125086856
+27.50243216835581
+27.402136086430247
+25.370538448725554
+22.933426795488828
+28.24551280004978
+28.115994457735994
+25.006865046816202
+24.79709933818644
+25.665571389465896
+23.521950062867177
+28.949731842763157
+28.458241672974864
+23.956129943880498
+25.15335952967608
+27.593167491887257
+20.368081555094008
+25.070144771733098
+25.265933581817677
+26.47618864365694
+30.879037279612163
+28.165857571994863
+27.547711498070512
+25.32154738268443
+25.005155025171604
+29.002252710804953
+29.328961514533447
+23.921666139079008
+31.343549913631264
+32.913830128794956
+29.668872189847775
+25.841586954294527
+30.827521839381163
+30.84709500916476
+26.103472874292123
+28.88203878125772
+27.66646014678024
+25.30263752567518
+30.40804480246689
+30.303381886847475
+27.384343136004176
+27.489621751928055
+27.65405953672949
+25.183364298697413
+29.6719991961086
+27.612722555475884
+26.670220132882037
+25.016637968595845
+24.998444180955502
+26.48421498471457
+28.802903460819934
+28.56948328036367
+24.907559128827373
+22.482279717299917
+23.87825296876329
+28.70130035465887
+28.206632683773847
+25.67196991114642
+29.023389876417454
+22.723773010522862
+26.792366366106933
+28.918579002608936
+31.246220084970716
+28.240704259283447
+28.520610748802184
+26.192275388848103
+28.44507066658757
+26.046236930656335
+27.530300899862596
+25.446320091826877
+31.312780341972157
+28.371254753008714
+27.289079254752508
+26.700135677188
+30.57593018366039
+29.795461522435517
+33.91683750797827
+30.852810316841612
+29.20904083794626
+39.1672120050299
+33.89651016325675
+27.568961927777266
+23.55350818549458
+24.689900097415006
+25.25317882381941
+25.875031112840887
+26.850940084205064
+27.337089399255916
+26.15560313846825
+31.116431117581
+28.453100067503073
+28.557915757943803
+30.011311466645353
+27.81352740606657
+28.35971168322824
+28.88455254564815
+27.126608893144947
+33.145835619376086
+30.814683690787902
+32.79825934121703
+37.17452429490673
+37.41851104763565
+37.8469738952264
+36.03943942478956
+43.42298283568349
+48.7919128228979
+53.45704116731106
+44.8650669788193
+44.47485015874793
+45.36695647464159
+42.34082524040843
+41.4604824103929
+41.40453290662021
+36.64472570910499
+34.079675366425846
+29.443291349218214
+28.217673315666843
+30.021267308966742
+30.122490787529387
+24.79888390818617
+25.471180602059476
+24.19666076606714
+25.074181915402647
+28.103348901763354
+29.045762114722564
+26.707329851965326
+26.941293696644564
+25.205904492167008
+24.786201204205867
+24.97160658167681
+26.57047562547092
+25.143067454289863
+33.35902066751784
+43.91759186914795
+36.55464438510724
+33.14487426471963
+37.6809577174001
+32.524268224125194
+37.945192894444226
+43.21294082178774
+44.58220063424834
+48.94802778985656
+47.55334975603026
+46.7393399621045
+45.74342135072777
+43.121873944051586
+45.57736751088547
+46.619585377950315
+43.19800086811708
+44.974164128804404
+47.75432760583499
+47.40054113979922
+46.579756228227964
+47.97381403363355
+47.06737078746545
+48.76369434923393
+46.58775801640472
+49.56028870846475
+47.50973647171539
+52.19552528495943
+48.06765784710802
+53.995463301778884
+55.43326759588018
+56.760740736431345
+52.34347455245919
+51.45650012523705
+48.788868361035036
+49.723026723122715
+53.87050985820094
+50.00036926950304
+51.145871196885885
+49.32364109744248
+56.44824134943045
+51.65062652153226
+52.60205465364777
+47.86234989771588
+51.90963393214325
+47.78700201737836
+48.5629302699241
+42.497716028877875
+39.225230987837016
+37.92852346782077
+40.33571520693754
+36.550117934939905
+38.105727973028166
+44.538025510751865
+38.044968446611534
+36.04662116497154
+34.24867387092313
+37.33552056867069
+35.568189573325085
+36.37592327863446
+33.861199494684385
+35.327235031615174
+32.10983283700919
+35.2778626048087
+36.20557150835667
+33.37578356452913
+33.441880817457346
+30.268343520806596
+28.479417678957404
+26.450501165067635
+29.46902996772711
+28.75200189058937
+33.39326155498108
+37.011049690564334
+32.377172252603685
+28.23989595463152
+28.126337820378893
+28.5914547777667
+26.83026227619328
+24.080639655888845
+25.222869653281506
+25.94390921864718
+27.002124525836038
+36.88319615923017
+44.75377127158637
+35.090480852158706
+29.27406519657208
+27.966334773506148
+28.361560465630944
+26.367939179092545
+27.942826058283245
+26.588737237760583
+27.426204834180368
+29.375573777972434
+27.896241661902323
+29.549778996658375
+27.700036713654868
+28.96660736320885
+27.04521363216257
+26.79803621693206
+32.15451531451326
+30.840785403279938
+29.736448568920906
+27.800882661040546
+25.621034846584138
+27.746996517048444
+30.724685763868678
+28.369883544311662
+27.89527754797443
+28.561112604699076
+31.245420549751728
+28.40346689825863
+25.639099942228256
+26.916976207824277
+25.304802018650633
+25.471130312609574
+24.751620816961704
+29.160987306318432
+29.251638424141305
+27.490494177872236
+25.982701054377657
+23.943919360541486
+23.316535533946578
+25.727014262107772
+26.68512024939082
+25.612282630039843
+26.217840426393764
+29.97389415384997
+27.385292833821254
+27.982177234335424
+26.175579223786116
+26.138179969323872
+26.39495851742322
+29.892201047264592
+29.047851505991318
+32.047638518018374
+28.696354114572287
+29.16024049568223
+29.64480675174532
+24.33991407958645
+24.546980072900197
+28.97486785139691
+29.394602731227224
+28.361131477792497
+23.33676181802062
+27.798147643644043
+26.98725377128943
+24.99413337879318
+29.89702736275818
+29.909277266027104
+24.643655285798715
+26.4992411273505
+26.132089829042172
+29.384172832220216
+28.99385914807131
+27.68710529590271
+22.89712986553768
+24.65385982026008
+30.118583871335147
+26.321729204461292
+25.9676011884211
+25.371057913916175
+28.315183297823708
+27.69020696379164
+26.579130814328764
+31.083760546257338
+30.092956981064987
+28.91392845446535
+28.25529668386524
+26.751507458664904
+24.863095258420614
+24.81488086204675
+27.26493200352978
+28.233384381258958
+29.80986700737681
+27.749045921541722
+25.904113988844387
+29.21231118207328
+30.514569835668368
+29.292909829904332
+26.10976065779701
+25.355596070312586
+25.290953123231574
+25.38990016957112
+25.2639602832988
+25.34897149168515
+25.16169788650076
+28.056981814843326
+28.3582452940189
+25.755493423687213
+24.802209284414232
+26.75083391915105
+28.040008218705694
+27.145123565454654
+24.47036627330594
+27.274528479206666
+28.105545402656105
+23.73806995817101
+23.51712524763282
+29.04286022741114
+28.26688706151434
+25.38414142769544
+26.514637572688954
+26.988693481748385
+26.099374793649886
+26.281597322896374
+27.954097430761735
+27.818967676527677
+27.751355710752108
+36.47286342786445
+29.527312058472333
+29.71466515067212
+28.678298091343706
+30.94003217795219
+29.518776243038516
+25.04246986794817
+27.413360010925757
+26.458191499794737
+28.818782418187197
+30.89742712831803
+29.325475812220816
+23.310568204603868
+25.482507583360544
+25.33028429073336
+25.301321051801082
+33.45998695222541
+32.40322122836329
+26.772416120079797
+27.82112547143427
+28.11049987930069
+27.7324439396764
+25.495098730767907
+31.08830800823951
+25.17734011562729
+29.09947872671043
+28.212813089585822
+31.448719570114775
+33.02055425144219
+31.820517807577374
+32.520073430521535
+33.846234321682346
+33.941801311125076
+31.94205007543907
+34.688227696858874
+37.33987352461311
+34.94853672430699
+27.327392787238196
+36.263352863943595
+27.426831067140085
+23.315924282289515
+25.22635251197441
+28.31788794277975
+27.68052195265642
+27.789780021737073
+28.723769427217448
+25.955681711983104
+27.833968812521178
+26.726674793235375
+27.57016381997005
+24.061539531179378
+25.630277512320276
+25.10039469998263
+25.468206165638918
+24.389085063702822
+22.78599605527701
+21.84214073256743
+22.442872667681726
+24.16808779330738
+26.316101032777013
+25.153388644014683
+22.43754555250551
+23.16884708216415
+22.319321317312955
+21.362539087261894
+21.182404621435666
+20.210474130750356
+29.623112806265596
+31.198315353902046
+24.31038313260352
+22.898609917418085
+22.864150357467935
+22.243391905603445
+21.687843582837274
+19.631356293256886
+22.225127927291737
+21.728279911946913
+21.384657222340707
+24.543633160771876
+20.207594194044617
+20.344675862194208
+20.126389434453955
+22.732924117068123
+23.169311674142918
+21.90457048703435
+23.13514405853094
+21.480404549209695
+25.90114770413429
+23.970015761413748
+27.56338392530293
+25.120668932911855
+21.4013056162527
+23.988444424167184
+28.190578785967375
+30.328612752135427
+29.353315777398706
+28.920347267142915
+29.638413796111365
+30.633903145067904
+29.257801234356876
+29.299522083404
+32.53217956164329
+31.511882964052575
+32.5071341908787
+28.82240090960893
+28.182087623162346
+34.09476777727278
+36.71704959725575
+33.25685810205509
+33.310406378229914
+34.50424231108542
+37.927768699998964
+35.57849370187439
+37.13295065900803
+37.56945107823859
+33.61528412409562
+30.813883968613865
+36.29043842311444
+38.56992155457777
+32.94731310464529
+31.04064908750169
+34.69404948876688
+34.76729489589441
+39.65653378341939
+39.28326004894316
+42.34819864910292
+41.01829048802911
+42.72290150125306
+42.54159024985422
+45.18307331166234
+45.85624930762218
+46.111536052748576
+51.028174643462194
+49.12938278970253
+49.5645465506061
+48.524246382268835
+46.36896101969561
+44.34988430002275
+42.93167748642392
+39.38366386124594
+33.08211511747275
+30.11633835507206
+27.72271096803884
+25.60857647088575
+25.067632067630782
+28.237888674944458
+25.441374394229783
+23.441941011360697
+25.200508733641286
+25.07892924704062
+24.12289537074585
+22.148440174466757
+24.52326777038408
+21.362571349441026
+23.078177127076657
+22.396073170780724
+24.680384472340748
+25.16928311846776
+25.32634001232293
+26.04451692840034
+37.97120721311093
+32.749822548431624
+27.405831258215457
+27.393800198693327
+34.57883691977911
+38.30476440529206
+43.30192360808773
+45.561963058628976
+46.382396215699956
+46.108876247613495
+46.503510684314044
+48.53288159338319
+49.531003430260796
+46.217813365739936
+44.58838510297062
+47.733711534034406
+48.04723868817904
+48.426967341208844
+45.98557344857798
+45.92415039206263
+43.348943601503606
+50.189318702276495
+42.13637962203653
+31.01233166502368
+31.56790480640079
+27.172434473171492
+31.026659836532772
+27.73842564855957
+25.946333143533025
+27.441586902285167
+37.49817199074755
+37.504071896183945
+37.514454207185054
+37.36511117304819
+38.81490818703011
+37.394033354741225
+42.71561067970906
+42.78639178646492
+45.465202724516175
+42.83881515827454
+45.85634024986393
+42.78101916456109
+44.1927009982222
+41.23717219520776
+41.629086251029634
+38.739047600301284
+30.327741274778646
+29.389283616533973
+25.28758623375937
+22.866618768728998
+28.565136451664188
+24.75585767903941
+20.47595650782688
+23.542285335551483
+23.69502588462298
+23.31009782629019
+22.23462340669539
+21.862149046710897
+24.25636422283648
+18.99569461099047
+23.598320660572057
+21.186020540618145
+27.625885387747644
+37.35254294309843
+42.46837198837234
+44.95945390195921
+47.20510056475014
+40.08948610922557
+32.430657812149875
+40.91068160870957
+47.02401703725625
+52.78530469833489
+54.24072655004352
+56.428115112455444
+56.223427328489116
+50.452891487113064
+51.49752590000143
+53.762649866922295
+52.587458460585935
+47.142020532723606
+49.42251532192097
+51.55692620614352
+51.90303229043325
+52.302855618673306
+51.07145423785658
+50.771379495402535
+52.76083388581119
+53.54242062537348
+53.79667305131203
+53.5524060598905
+52.56872675872794
+52.476306757180474
+53.25812833930705
+53.843480192827876
+54.17464425531898
+52.895483404956394
+54.808525645442195
+53.43270716908336
+51.9328624126925
+53.503963148358736
+52.86136557358616
+53.665534574945255
+53.36830826955671
+52.74445839376041
+52.64052037249381
+54.9670774359207
+54.25345215305497
+51.18423186734431
+51.18955577538875
+50.42279159210436
+49.41698641821185
+48.59987655331898
+48.19874099214769
+50.28758084407861
+45.98780634953121
+45.84717935655553
+43.94903112292556
+45.08632247595775
+48.97042424713814
+45.699478613934275
+46.58603068014621
+48.24519940554349
+52.23968560633121
+50.252880744114975
+45.78658870330817
+47.37026856819219
+46.5390720333198
+50.70625321819527
+44.951014792591266
+46.3273154862908
+43.5981866434867
+44.2869974888184
+43.24605145972352
+41.424564524814755
+42.63819533167417
+44.32175800781744
+43.15477923626839
+45.49289027354232
+42.072584923041646
+46.39713935621972
+44.75125831164341
+48.33576984033067
+44.284046879513404
+47.8527173328022
+43.13750099118512
+43.56090906246099
+41.40679604009686
+46.14617833022358
+39.397578046505956
+33.67964004516452
+36.47126111290983
+44.79793652991671
+38.88547913541143
+46.074468326564855
+41.7598197296023
+37.4423626435267
+36.099338031474545
+35.510001257647815
+33.904189311556124
+33.66751690527501
+28.23570740019828
+31.759511304784837
+29.17749582598765
+27.334349555681314
+27.403658010668934
+29.729440010792658
+27.442134662605326
+27.435912436666456
+28.8751813885077
+27.54381012461789
+28.464715603509816
+25.98022795859241
+24.80382524160116
+30.38064615788329
+30.01422521699058
+26.76857030022947
+28.931691067282614
+27.130014737008736
+24.274040773959513
+25.27352332137852
+24.834589359210923
+28.465670315173924
+24.94524177434087
+32.71842273529552
+48.97450693263237
+44.49412823849646
+32.48970568734063
+32.34417119415593
+26.85798169852187
+28.21955977093083
+25.361163046361952
+26.229288856952763
+28.447227518081306
+23.872924724286605
+22.86668056917759
+20.597469946356043
+19.765657303215832
+23.525446844998797
+26.29023364503
+23.719848249651335
+23.71137686379039
+24.119436777786376
+22.500590570173458
+20.77336351384301
+21.24788552495457
+21.039914574857676
+21.392042500324706
+19.168847222359602
+19.874810696755233
+18.34968590052452
+20.27509951298846
+21.684863684857802
+22.821838155809843
+22.492099922017147
+21.252798844487486
+23.00649402371056
+21.23629749055233
+20.52386403763434
+21.063258661703102
+22.378258118620423
+22.45383443458536
+19.72467955601276
+23.57219744427853
+23.11471620687992
+23.83005638647323
+21.734317278295137
+20.611256484343983
+23.48750921193117
+24.038386566713655
+22.72341130429072
+22.631505691798182
+22.237396328393245
+20.64587044891384
+19.309641620415874
+19.27140702821586
+20.88285858085851
+22.104789748694074
+21.38293310469639
+22.772762170258474
+20.742017417766547
+20.25847372923026
+21.026171222025667
+24.1556851968174
+20.323263043819637
+19.436128173352643
+18.819714014057197
+20.795545704998517
+22.97077704512766
+24.402784974290554
+22.734741730208114
+20.91189847866542
+21.650706882202513
+22.116315639320135
+16.252887614666776
+19.00803586853968
+20.953288027527222
+22.419133104661356
+21.552604299749916
+21.963486728344435
+24.121170596653386
+22.138020607338547
+24.11629544549818
+20.633836713693242
+21.75764946366823
+22.312935483583445
+22.017644970299642
+24.072912921198935
+21.662793499823366
+23.39979144764537
+21.598464433746628
+20.535777007500357
+20.195834272166692
+20.088655550115718
+22.660652743376588
+20.253904897219
+16.06954838633969
+20.262176439065612
+22.656341210519287
+21.772297755932897
+23.73573544067395
+21.65888335808286
+18.22110438010948
+20.919333761846985
+21.958977022552276
+20.543624180600503
+19.210387737488375
+18.661950572511145
+17.48306484190111
+19.81394846445032
+18.21740820187081
+18.34836163187019
+20.024522260648965
+23.719460581371692
+21.382686883682467
+20.143252312767643
+24.670157988683414
+22.977594635359054
+23.004070862896256
+19.87756099741081
+24.497662239794934
+26.378988740241454
+23.430750229751055
+19.108065597144403
+21.111868571222345
+22.732763805280683
+19.908780121890118
+22.548173448815774
+22.98624663306518
+23.603517749769892
+23.693653786211073
+23.316238497423072
+21.326957893614846
+23.99301887630334
+23.06310285599399
+20.952640328130542
+21.09035741006413
+20.63479565454041
+22.808469952931105
+22.345827217991214
+22.298317471411252
+20.794498826338014
+20.39105905361278
+18.259045163020176
+19.64929092662939
+17.022044685788316
+20.153897372265476
+23.801636062934875
+22.834814790374438
+20.378249010864167
+20.912798770238524
+19.56842777041342
+19.81322105939391
+17.917514844350464
+21.36984433045116
+19.80103662278664
+19.63938183427551
+20.046681648492225
+20.542128127976085
+20.937770200700143
+21.70684976178201
+20.643862216795455
+25.551746397665866
+22.488460633520944
+21.457995289894924
+21.42695108533904
+21.571309488764967
+25.168491526665036
+27.492420575418024
+26.413123726757277
+24.64084864172331
+34.29164304654246
+30.242062804600607
+23.30551945235824
+23.318051736110604
+22.923784985898877
+20.741408106129313
+22.17002726240534
+21.121391245045942
+26.946099365101873
+26.962319063327953
+26.35785333268936
+28.8246501396344
+28.484847215778814
+29.417310636745214
+22.927859702712226
+21.247599546319535
+22.806416078642584
+27.370982602939662
+31.273986507751104
+32.61665281073283
+34.72889269634035
+32.182572258175995
+36.21955079459755
+37.686822762582935
+35.907230968958785
+39.196371942099205
+41.50531436713917
+43.606921238305276
+41.234263963777735
+42.024306879808265
+42.49668725886434
+44.11167609961473
+41.51584291502054
+38.946937948151664
+31.89333476640151
+30.17762981539363
+27.439158432828748
+23.537183048639434
+24.48015729910206
+25.402864976908404
+23.370128771855335
+24.61135073847956
+22.361486577157592
+22.99007122698073
+24.74886927223814
+22.122285671988635
+23.731398704322984
+22.53379180571517
+20.13207107082671
+22.0945275848769
+23.39530137451061
+23.66820391030693
+19.80158733985367
+32.210993115214535
+43.402938670385275
+33.924628518705006
+31.917651286990832
+33.238534739585404
+36.111647873318304
+33.50517750429043
+40.12398850535646
+39.369711057361485
+40.614374186463685
+37.96429312551257
+45.77026415850112
+44.84762235601499
+41.26479646278548
+43.17704972843191
+40.69995991388502
+38.451706696281406
+44.130696649256706
+46.65533443557628
+41.15924801430146
+44.409862883213144
+43.53288568471874
+41.99860497675911
+46.844297095183805
+44.24609062708695
+45.67235602409504
+45.24187395850108
+44.95190098575804
+47.21630647599812
+46.594070637814895
+45.29566906855597
+45.260983441333565
+46.25563086539794
+43.538068969107314
+39.59079915465166
+43.99252853585681
+46.640302622283684
+45.47142891154311
+47.2327903038416
+44.25749696374587
+48.64522762495122
+43.78592031578412
+42.86432851882089
+42.447858431991094
+44.95950107914687
+40.0474731883664
+42.767844784296756
+36.3480032468362
+35.9545008561207
+36.461048965752525
+41.0537445663589
+36.10377435707572
+37.474115109572345
+40.408403236153795
+34.22815909151406
+31.8788021216221
+28.86414329750093
+29.656145255118687
+32.47627830849048
+30.472466056944896
+28.787392677693816
+28.912487301514147
+26.773880959138594
+25.198634096670602
+27.320768904829904
+27.412687838633474
+24.190711814837314
+21.66341268423335
+21.453819817388137
+20.866419208351445
+21.46995300299278
+23.17733876677788
+27.126720110043593
+27.410286581977985
+24.76648485413618
+24.221912414429525
+22.677561727345747
+24.175809843612427
+23.890070540773692
+19.0814592925379
+20.109259682279344
+20.43841276149513
+20.718848749137734
+35.244795394722004
+42.129033056114295
+28.77833477353029
+24.375665760630355
+21.64458233634349
+20.46418524302372
+23.259456649939153
+23.45762055337218
+22.538866493238956
+23.354021110003316
+22.49983357445346
+22.48428767853393
+22.925007750249804
+22.89702592284401
+22.567530927425423
+18.716202176391775
+21.625948667891194
+25.853512008848483
+24.87791326067513
+22.232874430924824
+19.84871198837196
+19.19465433904027
+21.235087621398407
+25.8269272447816
+24.375435052999492
+21.021261987496885
+21.457307796182775
+23.130871270514746
+23.12366006503983
+20.699310328211283
+19.870830247018873
+20.57140553457485
+23.0742381895289
+21.248757034176634
+23.336865115034485
+21.792767150576537
+21.95072533392701
+22.136413873541372
+20.671620425862045
+18.103540970319685
+18.252623176027512
+19.071326117726073
+22.711898717415934
+21.427142719630396
+23.51900191846792
+23.531285528437678
+25.113356681468588
+20.037503319335656
+19.77408261881625
+20.210884106940327
+23.30077801519124
+24.89943261380793
+24.29288620769792
+22.05224614983436
+22.158647608125833
+23.761886873801473
+23.530730606143678
+22.993437306341647
+22.047886043991
+23.800623638699676
+19.452725531476446
+17.6326111266322
+19.354170513244227
+19.366416323606657
+21.512860879441035
+23.96416122788709
+23.71933475726881
+22.95964941629562
+21.27601230222085
+22.008258023684846
+20.104217130820004
+20.967777525367225
+22.97936603688231
+20.776845225246348
+21.381283485987566
+23.293804111567468
+20.536305996845783
+20.490373738478922
+19.363524159115983
+22.117075413635007
+19.995654996435334
+21.43764784377288
+26.324767363303252
+25.407124722205566
+23.166383743765365
+19.694082283620702
+19.330464873508348
+19.377616548153682
+20.583503505533074
+19.92717161421227
+19.04900440458482
+23.080975759323138
+23.937314554516817
+22.50451793488095
+24.73466720866226
+24.934413977079927
+24.44202578688804
+23.84083283037735
+19.35369618660806
+21.819888427855105
+24.296936108619107
+22.877186705767954
+20.486070836205826
+21.82426444101654
+23.965142776830916
+23.91371077408178
+20.15410873835883
+19.529551485144765
+18.91895297413795
+22.42363149334878
+19.890919800272584
+17.196553205520942
+20.596903869679863
+19.09869137744562
+20.836990857028866
+21.863251329867268
+20.845977885850004
+23.251438850094985
+20.33529453636723
+22.60212542266555
+20.86399300799691
+20.039585227637673
+20.49166113035143
+20.852404842285566
+21.073615319106523
+21.896916965117754
+32.32862289215335
+28.090317630617477
+26.88079550361391
+26.787412159976114
+22.272469939792416
+23.687097980579892
+21.845725008399086
+23.585447470349095
+23.45176764708718
+24.436661787141148
+25.859664844498127
+22.468677980069984
+20.292824682064477
+20.02191231135157
+21.39250567051066
+22.36377690979684
+27.698073891860915
+24.216230594671913
+21.455547954287184
+23.327613179174264
+21.653621534920177
+18.599439063039824
+23.950630338374808
+21.38123324275864
+20.269119042467366
+22.518270551974496
+21.371774151182805
+22.543732130715128
+26.178798147882006
+23.783009904803933
+24.801321630483898
+24.241711973817118
+30.2761917628402
+27.929474447130673
+28.01505879832665
+28.469803863337432
+26.671957637263077
+21.312326516871337
+23.154169471671324
+17.85297222856569
+19.73605772403188
+20.662394669986867
+24.854291259897295
+22.30899971490004
+24.105122434820075
+24.37961099228086
+24.717692681521683
+23.56652256809808
+28.888433922936045
+28.637958024156163
+23.838948789413394
+24.943642548500378
+24.831119030028262
+24.618920374383663
+20.905707447000367
+19.608847398852646
+20.974779239909196
+22.02264788145368
+24.46240757957547
+25.889712611588422
+23.95532911450526
+19.14665782915408
+15.544325944431236
+18.296901052667494
+17.22740906108534
+18.517190106183406
+18.8615082919014
+25.719975709395655
+29.14464495626082
+17.179979398836892
+17.70716668161097
+15.863886527878108
+19.35480204761089
+19.854149668963586
+18.48615681294453
+18.426169998682468
+19.660583906304424
+22.144544035090732
+26.446906321760835
+19.615821610618525
+15.860205771869843
+14.994093308224748
+19.60675043402516
+19.632911750009626
+19.09319936926849
+21.465904889159006
+21.854182379679344
+22.82248111323483
+26.838671640514377
+27.897316837490678
+23.149603102722224
+23.222944454348635
+24.328718043723683
+28.783021515310836
+29.67781714853139
+28.064289701985928
+29.41771315762739
+31.209511001277136
+32.81870941743084
+34.85543866972921
+29.855253465789517
+31.580934855333922
+33.219470468683454
+32.091072753178025
+28.138812120207817
+30.26416971983275
+32.39836395312513
+35.72546576145244
+31.556900350147345
+35.95424163845422
+37.50785382959948
+37.9847792084298
+34.451981308820294
+33.51349773207019
+34.066407846950014
+29.765030453016408
+28.214066237693928
+34.649116540921995
+35.52275392548198
+29.77520113328481
+31.16462100040789
+33.9432242129989
+31.983847548325357
+43.98289659529243
+46.29233547266333
+42.728878391673106
+39.90555352969031
+41.41873323035808
+41.66096598929999
+39.373515341291416
+42.77488042412547
+45.215431587239955
+49.71529242517145
+48.38424681768548
+46.91695923735466
+44.68665614292573
+44.12220435964913
+42.32767780338456
+44.13569717782659
+40.461530746133526
+34.848065444939394
+26.841365823590664
+25.93715267040065
+22.810890006181083
+21.25496140051908
+23.84014663447782
+22.917921798383205
+19.931888934209056
+22.10676766144107
+19.888756690594377
+19.28696629545111
+22.434464236246555
+22.85002114354417
+21.27452004895636
+20.036927866336
+20.3397606207552
+19.766364485522374
+21.20841652301725
+18.885536897637877
+21.839278112721004
+31.551120906361277
+27.15018017666658
+27.933054532575042
+29.693305154284687
+32.66580393426598
+35.22583239977345
+40.15652539331835
+43.39386799011825
+43.54929780624619
+44.37333050740704
+44.18295257036326
+46.345164399766844
+47.63844775441737
+44.36995957845314
+43.098969999092766
+45.51651658362361
+45.68278574442817
+46.68978658585717
+43.58014453956196
+42.755016268406216
+41.26996756874043
+41.715178235794724
+32.27917173876169
+24.948959551207793
+27.220913616798114
+20.9415622295963
+25.544460479204076
+22.655273757434585
+22.79204034896962
+21.442719797538345
+36.5670479849736
+37.743173508093264
+39.47695812097722
+39.36746641123365
+37.50349527464953
+38.92436071716598
+45.74100791262053
+44.57133395752672
+48.22116230480755
+44.90107152274659
+45.718328668900654
+44.47381279364744
+44.13770950347709
+41.59873453817303
+42.49098224092392
+37.98007117451401
+27.090766553025674
+24.051877409937617
+23.418751807397655
+20.561894541484477
+24.90514809252963
+21.138703536428423
+22.018980746130723
+20.699853725970584
+19.534506969217773
+19.807344781981854
+20.441541642012098
+21.044486460701208
+17.58000744920382
+16.610341244982052
+16.688060986211568
+18.00347228425335
+26.513406141619697
+35.11287848030079
+39.52980703424559
+39.60099326767667
+44.16335072520626
+36.546102643933395
+29.6103588555673
+37.800077269782705
+43.85805308424413
+48.90693673227488
+51.83497863776604
+55.67580997694692
+56.265542355068256
+49.98098294522661
+50.81639673163467
+52.62620704452321
+52.33434833626801
+47.025095391707
+47.149063534915086
+50.218561655450664
+50.98719466706878
+51.86351583889333
+52.23757449966711
+49.96597991815835
+52.9351677404932
+53.60723259898002
+54.58141289141859
+51.148109634384596
+49.04586668941808
+50.858353572413066
+52.57131175920044
+52.66950874935342
+52.81492202440719
+52.370883987860054
+52.60407297405723
+52.22262876943232
+50.81073838643163
+51.341916627392045
+50.077839036214506
+51.22017147686611
+51.453116211593894
+49.199409427189934
+48.866079890159824
+52.10839794498852
+51.759790444475044
+48.40283522873754
+48.30412969270524
+47.70952273690983
+46.964719361479645
+47.22457330646004
+46.27075732917987
+47.98370922119692
+44.18268744944746
+45.210620143406004
+45.74455254998092
+45.49302992067676
+49.028908214581485
+44.63071544672026
+44.89641676917056
+47.30917050153329
+50.764966795891574
+49.44728086975314
+45.04612512509473
+46.01992343332027
+46.35115642767376
+50.517852398489346
+44.153943387501116
+44.765509614968025
+42.44928271495698
+43.89116133470854
+45.009452287607395
+41.61249140736308
+42.635864687979335
+44.77927581617874
+42.53497097449727
+41.38271795315545
+41.58461328660791
+44.56671935068346
+43.307839025051585
+47.87816904889016
+41.30537455529263
+45.32641511239908
+41.04586110541193
+44.22186828652793
+39.07453733734961
+44.547628058156775
+37.340395440600346
+34.10229461193322
+39.04908026841109
+48.63096692042548
+40.00056314842562
+50.28777604443714
+43.6620627465049
+41.387032803510394
+40.9232030041975
+38.69146367797072
+35.61765352454924
+29.26923003921047
+27.801186370197172
+29.649819104145607
+25.91277943263897
+26.798306249312674
+26.54988528849175
+25.929439637160783
+21.97205951869317
+26.10249818426496
+29.327060177109388
+27.177941559288385
+26.793823895166213
+23.981475626486528
+22.95461758861643
+26.713985686883817
+25.562562614782777
+22.265826138140284
+24.676585515202348
+21.307423310486058
+19.482334986309667
+20.296904469477667
+20.45046816101278
+22.45416880688937
+20.54935201737699
+27.63747559314477
+43.60594062724622
+38.05110803071974
+27.95193435153618
+27.837274820597145
+23.6460731488026
+23.78879152789584
+21.132179240914255
+22.63044466677789
+21.15633524021642
+20.87330124963485
+20.25963602688809
+18.159365055542764
+24.60418740560199
+22.823506581358814
+22.402635009865676
+19.551196251231303
+21.025820775213802
+21.00595528370789
+17.94977378402602
+18.011194162031288
+17.89497245322741
+19.158097213586913
+16.92944237590619
+21.44836821331924
+20.761175112927518
+19.17907890731695
+18.136978076705645
+18.49098930074335
+17.316672110595746
+19.571541255073456
+17.202183457145765
+14.75238216992679
+18.94702614769875
+18.306284240890832
+21.696085934430272
+20.17481168297732
+22.12896303979278
+18.41202010314396
+15.814911349094984
+17.82134185687353
+18.26310992442373
+16.85965362999808
+17.407703982020166
+18.762954812862958
+17.952851933138362
+17.25571886131496
+18.735303615214676
+16.654982667388367
+16.52229382105095
+18.124036633842167
+16.8497013065638
+20.44101924287243
+18.22636912519738
+18.03934639580885
+12.88757320870134
+13.926421442565967
+18.047914288032885
+19.627105469886814
+19.185882166693688
+19.273374208291486
+17.222931894733378
+21.155409230929436
+17.487814235650063
+18.199455386017632
+16.104186013336502
+15.009624613550912
+17.271544464392875
+19.827103290978812
+17.07816335916918
+13.030338010952178
+19.01453837258596
+16.34710691957882
+18.4026994346995
+20.162242894723533
+16.64021277639283
+17.353751199809125
+18.1215166035373
+17.3947441891807
+14.728964136618572
+19.382711371087538
+18.88675370218759
+18.675116813890284
+16.460508919035107
+17.53641441488405
+14.32440870282825
+16.955436306605066
+16.4767271359637
+19.92229198194167
+18.83439710484525
+17.299122058659407
+18.988227845941097
+18.81067497047195
+20.56050067223346
+15.32761175808821
+14.98396708997872
+17.784043701002815
+19.62712210836044
+16.118554191687778
+14.014482005535186
+17.675926705814476
+18.641131529982474
+17.48100626125934
+15.491073933685257
+16.20426208559465
+19.091082827234786
+18.379206956454695
+19.776528157795596
+20.494682027924313
+18.5330841150827
+14.356099467456588
+19.409326077128682
+16.489314907515578
+15.957346690240868
+19.009590067321895
+18.036995365673036
+21.517172873036714
+20.93810535486095
+15.84605607084167
+18.379330600913633
+18.5139344924512
+21.656097734586893
+17.806423334494937
+17.226291090154533
+19.225462433501747
+22.75042986890935
+19.24936385659977
+18.378753170680923
+19.7716200177034
+18.137266951893935
+18.80265902275319
+18.846607790547893
+19.461176632588234
+20.19194777126657
+20.10573353851241
+19.765587293402902
+16.759819239725218
+21.29451159629936
+20.60854338640283
+17.055638886543264
+16.895157107150823
+18.054972397300446
+18.000378127855257
+18.83376206679847
+20.289386456216178
+18.363936017498318
+19.71797509431596
+18.766264898452278
+17.524512746519648
+15.83667224810766
+18.53858680139558
+22.989851614064648
+20.482971439674273
+20.87716566992539
+17.317858815432146
+17.888024182146594
+13.904566812471941
+17.349738390644106
+15.321676345233854
+16.52103669785977
+15.858291348242787
+20.901927400019872
+17.882589418449513
+19.552653335338775
+23.751056587426916
+21.72070435905522
+24.378412593700318
+28.650431843767123
+22.128158215789938
+19.860209129121017
+20.187142826654778
+22.56942671861556
+22.617469238201735
+19.20396173850716
+21.589729606580804
+21.396688946603433
+22.17692468063963
+20.624994327475363
+24.673296864452638
+24.26596694454325
+24.168015716768252
+26.490905478985795
+26.281229118027028
+26.173965783525546
+23.900386883928846
+23.840823542202628
+32.00045837319195
+35.006657000558405
+35.66178477037998
+36.58061082350626
+36.40516143536253
+39.83731183696631
+34.76400679128989
+38.13802517453523
+38.82075493649999
+38.5760418383271
+38.858941006831
+42.1976921664537
+42.4664362515147
+41.736535561432916
+39.72832016068047
+35.059703753556875
+29.274691472398686
+26.045254953338628
+20.155998976195065
+19.17948753934411
+18.876166706543742
+17.90286153167122
+20.733362300237943
+20.552989610066973
+22.603928966555813
+23.05284689894407
+19.371190004830694
+18.39391058293883
+17.70834435000819
+17.54802970322926
+17.654204665872413
+21.076003379504172
+20.143679003200916
+19.493375106387404
+26.327891287876184
+37.12157543897287
+28.994672348012898
+27.78816339102758
+29.234711000744454
+32.28018068277973
+28.25986757288939
+33.06146434688162
+33.74915336389968
+36.97529503010068
+35.32633591848116
+37.7491089459099
+39.75605476116462
+37.97673926098156
+39.7948050464471
+37.58106841686294
+37.37260787816689
+39.31038113580072
+40.11634151878138
+34.36936054468147
+37.102115124594874
+36.636480717996136
+35.069017133248224
+40.28937600822566
+38.295477706357055
+38.715854878143055
+41.07343747663475
+39.14926190546209
+40.923719590911794
+40.89481905049516
+40.04029045788328
+40.465742100555815
+42.022478818792855
+41.04238514054169
+34.621548018381745
+39.659030375803624
+41.510238732620046
+40.42239337312506
+41.92823203282401
+40.086473318887656
+45.05390984296253
+38.445973887042776
+36.49277164823491
+37.88616234017494
+40.8228692417823
+36.356120291989484
+38.31978999749767
+30.9222064999869
+31.767498094994835
+32.24751463861902
+37.060183192707285
+33.56430510713763
+35.724909476371465
+34.59522329785183
+31.09422278737793
+25.404249501918343
+22.36476252433981
+25.99757000753287
+27.659331497099984
+25.438916140039595
+26.857787119156555
+24.622404270212087
+25.718410444212452
+21.14254210330894
+21.957271930795727
+24.23836029201165
+19.697183914992976
+16.84734966703816
+19.333094358835197
+20.113281837191636
+17.755516985023874
+16.459438946793924
+18.364036599401004
+20.508528487098772
+18.9492174482168
+19.872339024597537
+19.702683619267802
+20.687350113215288
+19.69336477352016
+18.629580043295476
+17.19132574605615
+16.164807863898616
+17.59892625749869
+38.539824674762315
+47.26085803316512
+33.8519004796361
+26.615753376160114
+23.57414258581663
+24.405398671466273
+25.010869895781184
+23.114340664900908
+19.370005644272794
+21.253448504388786
+21.06818694768421
+17.49612313688523
+19.591511505062485
+17.36152501641139
+15.538568340800936
+17.99148575555604
+21.48433274142714
+19.321459367728565
+22.662956688383048
+20.00208670742181
+18.944171655570827
+19.044294236464893
+18.12550487405609
+17.286957145525832
+18.29039396892952
+19.045847380092013
+18.86446482557045
+16.53726954831886
+17.330233398423587
+19.509181071188095
+18.862126794681643
+17.826383493170653
+19.98792643451756
+20.53450720722681
+17.40475123998172
+18.989818433403414
+15.55999715514578
+18.143699346339986
+18.201079502317654
+19.432328841639475
+19.222941283075983
+16.777146292457687
+19.050897875161425
+21.522483611432165
+18.135524425967176
+17.325415874079326
+12.80050473553868
+17.089499167048388
+19.47440079485159
+17.972371686583415
+19.362987170751808
+18.791204505569354
+16.06242014374321
+16.941267254931333
+18.255553756775285
+20.571376930894345
+22.130795430087474
+21.634762984128685
+17.93607042133938
+16.681799001853904
+16.088747005113035
+16.314369811526333
+19.152730104514447
+17.17063581635928
+17.778602053950053
+19.665148083074158
+19.245986385234502
+19.379647664057615
+18.639340815604697
+17.771414552194912
+15.644229459319092
+19.5577113356493
+21.411991519139335
+17.0639787994308
+16.524069064642077
+19.717004088116212
+20.79769437566246
+18.270485779370745
+16.86143841203709
+18.317880242731334
+13.906375932237935
+16.446478356918774
+18.360799053808208
+16.54401801487562
+17.273222839783074
+18.102413278574232
+17.291007933510187
+17.85141092773675
+18.346510413321212
+19.22678760186301
+17.376245995455378
+18.89019920232876
+17.946927336423855
+18.061662687767182
+21.92629367805938
+19.301087616534417
+19.91527690796778
+18.55384104136178
+18.423341932329507
+18.192371588763976
+19.54582028551954
+20.61871892567686
+15.992773894488394
+17.07377708758152
+21.133474514663092
+21.112510054377836
+19.98672746280296
+19.061326749068527
+15.870747798163478
+19.329303523780183
+16.36556382097146
+17.859617737332357
+17.832994479884107
+19.28852719395219
+16.522264926468054
+18.2065332026459
+18.78820895633379
+19.290660881041376
+17.123422694004375
+17.64510518418163
+15.25912556656776
+15.685841776715463
+17.875457501871935
+17.28601409273918
+17.121204380613875
+20.257112341321232
+28.839148321869956
+24.779541283775046
+21.72165395780813
+21.707456664743916
+21.9481455598211
+18.479945017926312
+16.697922650880926
+20.48278648273856
+19.370050620970446
+21.108510180243357
+19.40326345123323
+19.564204637533095
+20.148967776773745
+20.241466869808008
+20.166223524409602
+15.050467865222245
+18.664335246067694
+17.32780856761819
+17.84576623755447
+21.061135482261292
+17.799199263958897
+20.06331532455728
+15.792383089115901
+16.45327439624657
+18.443116772441314
+19.23410584333311
+17.822411614742677
+19.247897431632495
+20.4732120831291
+17.908837822373215
+19.13758867523218
+22.477897696533148
+26.825057397300682
+25.696746704980953
+23.989235033717108
+23.34566873089838
+19.213528605061455
+19.24504955528478
+20.909737621745236
+16.647694118683546
+20.45139543415992
+20.948729658762105
+21.69946745649881
+19.112440456845604
+17.776435182673353
+20.642410128381968
+20.763623857492476
+18.909469762295842
+17.82394052924606
+19.27814088558705
+16.789516527224933
+17.335874232264075
+18.455106675407606
+18.72319139774227
+18.877789141399447
+19.74558123538563
+15.501439282358504
+18.731424506566455
+24.230062351883078
+25.73224246820527
+23.918345093298896
+18.88380250412702
+16.433260030435676
+16.19971036478688
+18.292104094739543
+18.342472357718876
+19.753234778139486
+19.720517890905754
+21.042081646632212
+15.37378531889911
+17.153475998271333
+19.33716852836426
+16.3051022599101
+19.467123941808026
+19.459545443802966
+18.360497955172306
+17.003871392115343
+18.666564902134056
+20.56890608462757
+16.703042723991032
+14.57567760968088
+17.13516886261276
+16.958581031096145
+15.502452581050946
+17.524827577522316
+19.10130993467496
+19.538906917721306
+19.282614573388983
+24.592235537974048
+25.69710866609877
+23.362325926863875
+22.717157400000303
+22.517745890638594
+19.883053529117646
+26.811316456541604
+25.442100801032225
+26.86027515286999
+27.25309717541745
+29.609299315347656
+31.26194508764013
+25.974778368990386
+26.25342199789924
+27.274274586544635
+27.330538605205433
+23.330032903160244
+24.795453439700736
+25.59108800073244
+27.151023765503254
+24.296699322326276
+32.06708361939704
+30.935875213032062
+30.761336236365793
+29.127228079979773
+28.460468607357512
+30.179273644522326
+28.424020380231767
+25.48611296644556
+26.82240888449934
+30.2713530976162
+24.940454525227736
+28.740843956391075
+33.958730822296374
+29.99814538579251
+40.1105962865108
+42.76998121246419
+37.320319914331535
+33.461561745219214
+30.733069956678563
+30.426213856426344
+31.371331555006023
+36.655123618383826
+34.47999001882377
+33.93138819744827
+34.6500126392078
+31.851350932396684
+31.542517716073036
+30.68088780230879
+29.30575157966713
+27.69951218249129
+29.764504382873554
+27.45671287602437
+23.11588706474606
+18.14931119714464
+18.876227297681723
+18.432746279378932
+20.156733964062283
+17.333328989826285
+17.576024583844188
+19.635805365704996
+17.17361396902173
+17.09388051235834
+18.818856883808877
+17.89177944333565
+19.20107362473688
+18.111104840831572
+18.808658822028647
+17.996676518422845
+20.25221288788238
+17.639180525252527
+18.104362267904648
+27.426711256408623
+26.77323667096823
+24.16693365171757
+27.01482879187077
+30.71717729326656
+34.275995943622746
+36.57048569010705
+39.44093548184987
+40.12107576693107
+39.81855323633538
+40.917180778654014
+42.17047442730786
+42.23801589246342
+43.10715583950868
+42.306401488835675
+41.148213192324526
+40.44098966194418
+39.85821784622504
+40.58529183820928
+40.42635302947535
+38.03532449040032
+35.496997067673206
+27.339083605578395
+22.587845973325344
+21.55440954696779
+19.317865516248972
+20.470141354429785
+21.30214907480483
+22.076171978749343
+19.58376837799503
+34.8122201608669
+36.59150139163681
+38.3011247335896
+39.83369612419113
+37.075533793770035
+37.38780803333256
+43.84427106853951
+40.64260310655266
+43.144534389363926
+40.81226668574565
+41.58592634396486
+39.33468631939496
+36.84566372411534
+32.9643151085054
+33.1757657467589
+28.969531407962663
+24.69225759660921
+23.11799481426371
+18.521989230984047
+19.272334346916196
+19.230895832531573
+17.642215637761012
+16.897419897085157
+17.8425859059018
+16.650417296615302
+16.398998125374177
+17.06792772122178
+18.16457740837849
+17.97012578091973
+16.73442101382399
+17.71271934116794
+16.281814794826744
+21.92483587724449
+27.801579288004547
+34.86138420176344
+33.66826543002138
+31.865335967331518
+26.978249681398566
+23.18277293215111
+30.628536814315197
+37.758797007319586
+40.574066198376975
+42.456882099339
+45.50328897543752
+45.84466380288271
+43.65019402970949
+43.11935147959984
+43.83570159954037
+46.371240451843946
+44.578728239951865
+42.90285371410906
+42.558874065520115
+41.70674038036594
+42.87088705066203
+42.64981936786453
+42.05069604417649
+42.334812140072835
+43.646657928497554
+41.776147749562696
+37.973325776051894
+38.638628166803734
+41.36009094205206
+39.61371405698251
+40.29705103635552
+38.56827017422381
+38.899440448486374
+38.76709333748272
+40.07486286416635
+40.22440380182931
+41.15315060708591
+39.93023337736764
+38.898982785933526
+41.1916040437598
+38.69861813905965
+38.7896308974604
+41.87580586084245
+40.98082525304983
+39.56482821717102
+40.29112344028703
+38.41509363041443
+35.33565163205081
+33.592461262513055
+37.49759537958374
+40.39267487632071
+34.46677903723891
+37.84661334451177
+39.24223953486452
+37.018253174608276
+40.452445673417394
+36.03246513579481
+36.7393613398244
+40.781618520512666
+42.2475366192868
+39.77961388488082
+35.60253392766958
+37.6749690610294
+37.83448004760113
+42.5292978299492
+37.07449985117617
+33.874982111448006
+30.978296567612816
+35.50085040782061
+41.087663405697576
+36.182536651746915
+33.23141486361685
+39.570026592427766
+37.70959029458552
+32.62924238174581
+31.554968930654
+29.380262637734276
+34.297826502175724
+39.432604274683925
+34.54938533064072
+31.771753876514154
+34.372516066948364
+37.88607742393836
+32.392786822528294
+30.666272979118617
+31.665142907965148
+36.30815148717019
+35.66720976547698
+43.67050646676702
+35.78107950424614
+43.870889604622576
+35.62243055350005
+34.492375331706526
+36.152271534820116
+32.649725397570066
+29.835506626477894
+26.703661750556833
+30.000200229863054
+28.389661105404087
+24.83774327281661
+25.811443866565682
+26.235884188081926
+26.303652127719573
+22.449477253923135
+22.006125886865746
+23.06648126129592
+21.578355479479967
+20.427479048536057
+20.275166430016967
+19.284308370554925
+20.64624167141021
+19.437580346534915
+17.869166805468666
+21.267956009372185
+20.359449597948384
+20.74543316202498
+18.648328809306307
+18.523242867060617
+17.466894150032175
+16.722770966274126
+20.994130887655643
+35.134257527917484
+29.107763704280927
+21.064443193731393
+21.35935138681488
+16.4456267997749
+17.460199162614643
+16.459975698273496
+18.23840067840578
+14.284311041521022
+16.765827406872702
+16.759637298932134
+15.75214318513764
+18.402365261377795
+19.181135666581852
+17.421463185055828
+13.360340854434256
+19.238785073495393
+19.161794553548802
+18.09766786925509
+16.908497220540795
+15.423096969869164
+17.134716751945362
+15.67359358107835
+16.733417507053474
+20.725771568353935
+19.54632532683901
+17.40149186949131
+16.93730271716926
+17.65616831954314
+17.277095711257402
+15.678701050518853
+16.581603075294154
+17.82738512567947
+14.10920284195818
+16.456397501037188
+17.306829844317818
+19.180591160568383
+15.745133960989634
+14.259007932261753
+18.091017528257098
+16.144413957015956
+15.408736887430308
+17.241953551133022
+16.14205141203645
+15.140883204516129
+16.31845238165802
+18.2789089014437
+15.841342203192625
+14.413620027204743
+14.515449835811296
+15.334697094470343
+16.08717758381286
+16.01510866222071
+15.181270021534274
+14.864669572389943
+16.16698650459999
+17.405152937454304
+16.983287946651828
+17.7281262248343
+14.277464588260628
+12.57559875979635
+18.594289952225566
+15.868942588372164
+15.904233253651427
+14.376744591542007
+16.416669322295135
+18.381524615391527
+16.53840606299393
+20.197541106961523
+15.002958828945623
+15.470653719549205
+15.705160509480308
+17.309944950343052
+16.437394139301446
+14.844376090138425
+16.463556744086105
+14.629847469829699
+15.896551831269775
+17.179007173963953
+18.07262578927798
+18.502936191244203
+17.57657592064575
+15.417562765813585
+17.411339198798004
+17.802097144629528
+14.702024966963165
+14.847311458007269
+16.335175248342253
+15.16358470613703
+17.675755100947512
+17.683650067437824
+15.04245851833872
+16.355225423607934
+18.466894848165694
+15.55264095459404
+18.020777527904343
+17.205820868740233
+14.341499028775686
+16.96212138664778
+20.122082207524514
+17.910846330981016
+15.841405422916552
+15.547748771125654
+17.526877905773944
+19.12323970789508
+18.026499144538903
+19.252841025304676
+18.378418775258325
+16.13580605517396
+16.629746490628506
+16.982476144419266
+17.332549772842796
+17.66880104406772
+15.682038646458423
+18.054493965613247
+17.420654436161342
+18.957061857603534
+17.19496312109773
+14.73900542413081
+15.27046444486615
+17.24496674471098
+16.701850834440805
+15.36689646937107
+16.037449120128116
+17.880231133746875
+17.440440063951712
+15.48990446967592
+17.92990216053464
+19.163184119282718
+19.103416540717305
+17.939465325851174
+15.378935530483673
+18.34979041522233
+17.821584738328283
+18.894327281776597
+17.991176705195414
+18.761824455787405
+17.011555019925837
+16.63699809529794
+16.730291732685075
+18.029577175816826
+17.31352698900089
+15.348685362795422
+15.726240038324946
+17.694060640111374
+18.658920059875115
+16.4872928886831
+17.757789681861013
+19.11411437543987
+14.676276111902382
+16.22437603245905
+17.582979628852925
+17.145244710775117
+15.695630406947217
+17.688708084633518
+14.52699121890518
+19.794950373652227
+18.035240367411447
+16.494965147384505
+17.041699071955037
+20.188260949287567
+16.538532308478565
+19.374277833571327
+23.72409579589082
+16.746214954792848
+20.61962462385644
+26.463258762798176
+20.394691730117387
+19.18391833034417
+16.337933118033973
+21.151181012764226
+23.341434421935602
+20.45663218298776
+20.313489542099248
+20.148838164349925
+21.72739151443554
+22.084729711119294
+27.444589173453224
+24.95240322794639
+25.455696734603734
+27.662948834751504
+28.278334918990694
+27.760148720058353
+24.82720858634569
+25.777543163391044
+30.46315755967875
+34.42364671671368
+33.5880456655518
+31.500276285432122
+31.31323841361049
+35.616279238052655
+30.627407420909776
+33.3616592003584
+34.54688849722139
+31.408996704803087
+34.680796328991235
+35.78122808344902
+35.254779737020556
+36.41195514072034
+37.61374710385922
+39.10382318439524
+34.004492670694205
+27.036337532705346
+24.388225778278738
+23.443235846854478
+21.742015939367334
+19.958633924436995
+18.664051869161298
+20.09417177447304
+18.078448571662875
+20.096175910610157
+17.69345515262937
+17.090627940300706
+18.022531900071343
+17.099129989092518
+15.843727123487199
+19.32439585413448
+16.729264048475727
+18.42500475171998
+22.884741209850006
+34.52460045740956
+31.235548106798788
+27.19836642310129
+29.544201600545975
+33.584807179140384
+30.233111092425816
+35.29284066144025
+36.811665005497076
+36.313723543689605
+34.04395821830745
+34.880578310553716
+34.137793001746005
+33.24606029478315
+34.14064669702397
+33.747694097109644
+33.866708180081005
+32.16772063880978
+32.10097425817058
+30.55680468870476
+37.893444316652094
+36.242147649633196
+35.5036156465201
+35.995576650487706
+32.65045066449112
+32.40758863253227
+35.325645624787114
+30.95825821751575
+33.33481350903671
+37.222697760139454
+32.920928253183774
+34.67944055619624
+35.19850934182034
+37.18150736394777
+31.66930973710251
+37.429638124181594
+35.49462835249767
+37.6728314743564
+33.80276570217832
+35.811701458998854
+38.79660013560003
+33.03261909139739
+31.390356694190913
+32.22598949432279
+33.51420466245014
+31.788712590421994
+34.255417031687045
+31.165263835644808
+28.62790495139994
+27.082207041224038
+29.75683964605416
+24.37177547005244
+28.31635803215856
+33.30661081560886
+30.595765392736652
+30.222914388957136
+22.636654124077978
+26.877998404620783
+25.840350145515174
+21.870295764873276
+23.854995771151053
+22.395760013126804
+22.671343796494156
+20.90714586016587
+18.72038179743531
+14.909288241348904
+18.05206991724006
+17.713120788137118
+18.192129121497615
+18.753612101264693
+19.249276471568933
+19.731154049242363
+20.001603192729647
+19.65061727764271
+17.607917752157775
+15.776500161696092
+16.632738458459983
+19.086932755264144
+16.603630218711075
+14.110938800844806
+15.22063138935178
+17.33392175264254
+17.87833459222199
+33.45663230686684
+41.90145403965803
+28.740102913695793
+23.981630772218068
+22.01067884883767
+20.771033141682878
+19.79543742127359
+18.67019181471774
+17.439379687754126
+20.155009023684443
+21.899664890023757
+19.503996018699254
+19.99298637986233
+16.61898408040237
+14.814779995938906
+17.001813754997954
+19.649149725688602
+17.11391523922653
+20.450043945229964
+20.030936939980037
+18.40233405342771
+17.299945702672872
+17.548021696619728
+18.342988799420226
+17.38492390949432
+18.12062911940619
+17.886071451961712
+16.412165869257137
+16.11026462866441
+17.915973678727212
+17.909407936006247
+19.92879824841988
+17.661171441290747
+17.402890730760404
+15.41091819853142
+19.28579300225313
+16.909704079051934
+19.135201014518472
+18.935235277227733
+16.322269629812396
+17.806919777278907
+18.832280159061995
+18.553683190871297
+17.565454557699113
+18.27459691016341
+16.16713236382543
+14.36012887043097
+18.29362768307979
+17.45027230631564
+18.134478319016978
+16.58112203601921
+17.916106426808128
+14.745437236949883
+18.011350558750053
+18.4433048710912
+18.333578504939112
+19.606286221732475
+14.240380507685586
+15.308764816895192
+15.977986493265263
+16.44947453319078
+14.351967207347428
+16.410958948316846
+15.926358909701108
+18.645587090446597
+18.55409782085063
+18.319718592037063
+17.691305372917498
+16.520207973702853
+14.574354222470348
+16.518167474264445
+17.751693187019626
+15.290535610824563
+17.778979403695672
+17.42525322233945
+17.75412047731001
+18.99916715237549
+18.074534240931897
+17.613288764811685
+18.14792561390979
+14.692389372327384
+15.101778492238793
+15.145780515247012
+14.41854849425772
+16.583197993412497
+17.977036047193465
+16.28794933338422
+15.946557893423815
+14.994124764988612
+15.768086468394117
+15.605154944364799
+18.360410549924822
+13.804115099303502
+14.814242476655835
+16.061927859375245
+15.722255302728144
+19.665162546730215
+17.784398142647902
+17.45859572261392
+15.324367716949425
+15.014135179767024
+17.246076626889504
+14.976463212206866
+17.307878142802778
+16.187394465000438
+16.592559763667722
+17.495622319195675
+18.09395452208004
+16.734736720997148
+15.947595623329889
+16.343560207477026
+18.329513617280313
+19.465728207747304
+16.194356724719015
+14.463608871216863
+17.68826112285764
+17.85475365011952
+18.694758404802442
+16.044413406995062
+15.766201976089931
+17.71817480828645
+19.047476900786265
+17.632564715307453
+16.173224912870396
+15.85331564820946
+16.89608210351814
+20.274638219442807
+18.89264683150718
+15.47083032492138
+17.873632534776405
+17.34802379284038
+17.539828032043715
+15.367730052653997
+16.88843494409558
+17.63787203815488
+17.869207084204874
+18.483051969100202
+19.366386909990467
+19.364307238006887
+17.624065904898416
+19.04674146745549
+18.462262360187992
+19.242671214698632
+17.42728800010208
+14.111206440801908
+19.735530338579352
+18.15494668973065
+18.359714059016284
+16.6305450073188
+16.26784322572017
+16.59800469609145
+15.735553555512112
+19.518865729867443
+20.859607971386325
+17.489761899652308
+17.66251146121496
+20.313252762855385
+23.461568666925203
+28.389430197426364
+23.445883285425154
+21.660836332140676
+22.756729885718812
+23.510628152667536
+20.571897941470354
+20.113459627727693
+19.439681966261546
+17.834069901305355
+17.132822113656133
+19.978576931293887
+17.634395144174192
+17.70906766343485
+18.692135844142555
+17.39722475697377
+17.50095735000042
+18.616017027697467
+18.72891568593768
+18.115597648659545
+17.020156856496754
+17.59315950942485
+19.71014163202598
+17.76881792159365
+19.379604316248404
+18.656152758990956
+16.4893728353762
+21.963558682930937
+23.973759386229247
+19.635791605631525
+16.80461372926588
+19.2469366083439
+16.2806353256462
+18.837670459931545
+17.363354026910926
+18.195124220797013
+17.98237425129237
+17.990246120780782
+15.988349939303603
+15.74051811423466
+17.689286947842803
+19.109268147352097
+18.909463626012183
+18.038323521546715
+17.883701967013494
+17.594176036499704
+16.599202205448037
+18.41160062218343
+19.516123173859626
+16.390081605812227
+17.820000791803622
+17.372480522889475
+15.246642593349932
+16.898023020532165
+14.638511851610588
+15.12177184049689
+16.382358678553558
+18.969900679430282
+21.235485640872298
+18.258213527052334
+18.645056737610844
+15.983124938180808
+17.206640488306718
+14.3042534289403
+19.771706473163633
+19.618819009621987
+20.648306651153376
+17.379023112213233
+18.611329632700077
+20.31721948482368
+23.037733002667082
+23.05845772461251
+20.274298567093396
+20.09897935472263
+21.57829520589388
+21.317068607776278
+24.54656970660237
+23.550442125977142
+29.46062916010338
+26.55789648611311
+25.531348681536244
+26.402891336197982
+26.37801014131459
+26.345853398497326
+23.260923647327914
+23.497114697325443
+23.963126756118243
+25.766536813661048
+23.315886044656153
+25.942716048132866
+26.69292106258297
+23.474914804423022
+28.768382214871323
+30.776184544010192
+30.801601270666623
+30.09019284296359
+25.689901868723908
+24.772020665285552
+26.41713695426148
+29.90241158223408
+28.501760725552984
+28.499715326163084
+25.90773359692858
+26.302207067477312
+23.818396673807783
+23.223875832110437
+23.370047412616643
+26.090315864417605
+28.402452561984177
+24.778330885138985
+21.40684521016388
+15.72858155326746
+16.069942128026156
+19.35018527595976
+17.988132663059332
+17.40436146161568
+19.5321923968191
+17.576557857432505
+17.99070798817435
+15.015568819989142
+15.946402165426505
+15.874583954294096
+16.009334440722498
+15.39813458967842
+13.969489320228817
+16.935604411060112
+18.16962774386461
+14.608692098540857
+17.177779933729127
+26.430226922046074
+27.596572474903382
+26.212105764081002
+24.877432629995084
+28.292481527219167
+27.556312564810725
+33.34381287213088
+35.88620817624273
+36.781996797614
+34.89132177496482
+35.17773097698246
+36.039452511860034
+34.60191352330058
+36.666212288217565
+36.346291543055926
+36.43260335003454
+35.785969321161346
+35.676652187854515
+34.72064007008804
+35.52514589003894
+31.244648586414456
+25.350454319838164
+19.61390700371487
+22.364526898297214
+21.689499618321904
+16.126524122122902
+20.049942611462328
+19.01559025579978
+19.355898725732075
+18.275586267080726
+24.03400708564409
+25.384669578673993
+23.96634237291903
+28.941509724929986
+27.487243083915274
+26.66418466631039
+34.068598577000955
+35.22333288971048
+38.81852345213429
+34.027672547688894
+35.50038248012133
+31.94174309835897
+31.623577215632707
+32.96908684438115
+33.951665579979476
+29.84842069932779
+25.17754539582232
+21.411123972098622
+17.861513930915834
+18.165492018722205
+17.582035227046376
+16.81039608789162
+15.679340373247953
+17.48009759882568
+16.866851283908204
+17.330097856258917
+16.284112857307562
+14.118466228862928
+16.906609427064936
+15.383024330803323
+17.797153823231724
+18.18356509419489
+19.754646134739886
+22.583641937520014
+28.953410789274997
+29.162581448542852
+30.152318907516815
+22.62691965736687
+21.96954237656665
+21.287961175727943
+28.001618540345774
+33.21020148793306
+34.199808754473125
+35.84996925759302
+35.708027358713096
+33.8114826552907
+32.974052732034465
+34.75838698193044
+37.85122573851309
+37.21157930106072
+33.972665985986964
+35.51141481323367
+33.64593771930559
+33.586504923642465
+34.8584595889147
+34.4997426784758
+33.88228991330064
+33.249478828557784
+33.19889976421341
+34.52230404282453
+33.70974676778566
+33.08187462808591
+32.78964766078626
+34.501925284616604
+31.322510051378416
+32.76843649542627
+34.83246824048467
+33.9771294256761
+31.5708501500375
+33.17843206729874
+32.93825846984518
+32.84519836800695
+34.36521365880374
+35.03487109319077
+32.89265116462734
+36.13171528375801
+35.800871931946716
+33.552052398828636
+30.158006192804905
+32.429868398908184
+31.47420301047478
+30.182001229438328
+28.673714699009537
+30.784043167525752
+28.171533820931757
+33.2146447759483
+29.941029572794463
+29.902053271183618
+33.790091126032095
+28.23141116711423
+28.031940554311248
+33.674677540684
+36.707159743914545
+34.294525774310586
+30.804963362909987
+32.315457068914924
+32.20222845956776
+34.98386132209822
+29.478245416153044
+27.550118657683058
+26.115716727931797
+27.601438469328727
+32.37284141107021
+28.46427745290066
+27.789984420985093
+33.44390664770329
+29.734530764808326
+29.054075287135092
+26.934954163344997
+30.494932262656846
+30.491756412048986
+33.47077569515814
+28.69011112586081
+27.912702305548933
+29.1542327292169
+31.739952025511414
+25.652751157214254
+27.261905251362847
+27.16827441344391
+30.00458915959399
+27.668508797610485
+35.30183190802384
+26.54916022576809
+33.335918768538065
+27.346212551418958
+31.235110965241432
+29.467138817457354
+28.505586617121864
+27.58503917669462
+23.78891924072758
+23.260949433334304
+23.811081799457384
+23.15573789112257
+26.351956335471655
+19.49396334131464
+19.55378187121829
+19.23001040443353
+19.351407826220807
+22.14254414378665
+18.382455542622452
+17.96450196861889
+19.680332631814494
+18.172739447904505
+16.96378880889806
+16.230702736246784
+15.98839888731041
+18.5675232200271
+18.5994049868804
+17.1449596860016
+15.409407595789986
+16.352070332100553
+16.998522326122355
+16.68550575998694
+15.791468874841911
+25.152575471403452
+20.80520723374765
+15.656052807973055
+17.4975105827032
+17.5485876577401
+16.20008349699708
+16.34758256123446
+16.764881023580458
+15.43073105985519
+16.424698972236115
+17.18501044083213
+18.219549996220067
+15.891412342841889
+14.513066667219434
+15.384543100876058
+16.271776596233423
+14.545342442086707
+18.46046108664578
+16.972130519073872
+14.413614037828324
+17.858803600302252
+17.02171413458977
+13.86412568134854
+15.39451060052879
+17.32208127576068
+15.874312739267012
+17.199198946270215
+16.59039981943181
+17.96118876458702
+16.156314398312688
+17.88189674782545
+14.01093663112276
+15.261999907835829
+14.107760515745596
+18.2272873335164
+15.94815911378349
+15.729643658273233
+13.876541120874279
+14.444289903663602
+17.62663804017525
+17.569752231745184
+16.971271102319164
+16.788758590819768
+16.32837910759342
+15.125813573563534
+14.827199867292805
+15.852778835741375
+18.03440474299201
+15.294547027654104
+15.45513924177537
+15.814945359089606
+16.09172247705976
+15.255947650242192
+16.538739387640263
+15.880212100394914
+13.792914577646343
+16.49289419343104
+16.327234499529695
+18.808852384076914
+16.969844808193372
+13.71479919876532
+16.682744941550183
+15.253208818858951
+15.035360775806751
+14.635489378940221
+16.236138995561618
+14.937115433416537
+13.820566762048443
+15.37030856778884
+14.448366485942032
+19.42953437483439
+17.08134216293628
+18.08315008724567
+17.353831782376943
+16.5283590557317
+15.066136429112902
+16.46691797311658
+13.667119963126083
+14.393875451008142
+16.996881307522997
+16.737477694382775
+16.555489195385945
+15.63455586014824
+17.98232394012804
+17.54980657605259
+17.620976349673228
+15.292325515653246
+17.28000586433302
+16.629587070561897
+15.89212397146433
+17.626347915680867
+16.432032165072698
+15.372110912845685
+13.846797998496854
+14.599820746983326
+18.62353506489454
+16.932625745674812
+17.652152331977703
+15.362453848583598
+17.495501436334962
+16.47172654061417
+14.133532294675874
+17.731600589284582
+17.9445929803002
+17.94733586648573
+16.78707152594268
+17.463144343523723
+15.446579273850318
+15.058595336710553
+18.216346877024463
+16.720879288352236
+17.220322159556474
+19.371755111439555
+19.65678560672316
+15.64375576889718
+17.024194631716185
+17.960852089955054
+17.975868254689672
+15.473089573305217
+15.050667819159443
+13.81763483865329
+16.957691511778435
+16.04972671367024
+14.242442901766495
+16.882524029388392
+17.511941376589604
+15.608666056055085
+17.611178751966804
+17.69244097119494
+17.48503235968272
+17.036660840360696
+14.164936298363202
+18.538179675518236
+17.87359903058079
+17.894387664236348
+17.36690524377761
+18.19620532084471
+15.200628985646844
+16.232608318185527
+17.34601541299176
+16.485871158484017
+16.854486603180646
+14.955849183329164
+18.694819197773256
+16.196952942572906
+17.870006505326714
+18.820213683919803
+15.610646747856265
+17.24816829993931
+16.145890095889953
+14.061129406889236
+14.202083083369942
+11.912723600151452
+15.786771600040211
+16.429083658879634
+16.944742582040405
+19.128947066461535
+17.066846983786476
+17.5292556919387
+17.55677086436613
+18.231908953637642
+17.342793406851044
+20.751984530577786
+24.419764652435532
+16.703156125628453
+20.57081439507796
+25.146982303263343
+19.91031614077299
+16.88611696197195
+20.439888237040606
+20.723714884144727
+18.03302346985383
+17.807544443573462
+16.662144682834963
+17.588142568122365
+20.280580257880032
+20.40562502507987
+23.59365373509341
+22.069326322186967
+19.709347533697027
+20.233376982003378
+19.762954804230517
+19.148197371434435
+21.511634058738693
+25.15021128931103
+22.43108797229307
+24.011782359569636
+23.456001500239623
+24.377095470613014
+24.623596174926647
+25.944130619686803
+24.604568116922934
+23.723626638538093
+25.31670045478505
+23.52380666506147
+26.908705490396073
+26.486632920166002
+25.036817115419524
+22.470518116551048
+21.647292337108226
+23.63602829012845
+19.14849899061987
+17.910755386713404
+17.778044014001324
+14.00327829846816
+15.770401199521999
+13.039966306095081
+17.20162515132587
+17.319311790390273
+16.764762991677074
+17.97081365933508
+17.392333882867163
+16.198514817627185
+16.755506590821824
+16.306066708718348
+15.134319746731308
+17.844243604094416
+16.481991640703214
+17.46777928514733
+20.501378360934183
+29.11075174036968
+28.767977727064903
+22.226328574290406
+22.16354618386451
+27.365309867776418
+23.30817413248259
+27.502406572181016
+27.543481237670605
+29.904485310330926
+30.826941922464613
+27.7010768904575
+27.60434046957687
+26.18647236238907
+28.25275449045307
+30.064988568664646
+26.021536947561728
+28.523282916917296
+29.37999924953884
+29.561129744527435
+32.69255032909557
+30.850613753044584
+28.81810294971875
+29.26515057820285
+30.46687102645282
+29.236337404999816
+27.364200362348157
+24.090189985534394
+27.582173075443734
+32.38472059026459
+26.33999896854803
+30.202617728236092
+27.71312155334273
+31.55365715810997
+29.27843403262736
+33.953854786545534
+29.217523158383884
+32.24647594609239
+30.751995411343344
+31.320261321139398
+32.70016237257033
+26.640380247865423
+29.3081111516926
+28.15077180915445
+26.754679832305257
+26.189347488666726
+31.270126124345566
+28.72353650416487
+24.650902581833606
+21.614335303471123
+24.571370754172563
+22.370579298547867
+26.78048256848554
+29.232319433603223
+24.856217909144917
+25.711806805226175
+21.242515577806373
+22.738517905712982
+21.303957038470415
+19.936844999352047
+20.40993453283626
+21.132478694581124
+18.418552064264503
+19.74117682451758
+16.070137837468806
+13.168820919035369
+17.543624644449622
+17.637477659216344
+15.054857609970966
+17.144017260051783
+16.066694347283445
+18.019223612848208
+17.843172305169205
+18.62048317577579
+19.873449177228977
+18.927405875475543
+18.486517041928465
+18.524575290759557
+17.242934521021326
+15.33156753178541
+17.89019432000417
+16.48984068555427
+14.768838236761823
+19.83100622292835
+26.529054282259025
+20.706076251840514
+16.35820666573865
+17.630074606024024
+20.146092349683585
+15.774408774664167
+16.612234601419786
+17.34437929103646
+16.2838064891
+17.678151876270462
+17.205420067448358
+20.97634279770523
+17.338831170914943
+16.288105855201067
+17.513133027665887
+15.306229925992625
+18.817154448615312
+18.25070535720984
+15.184822461541458
+15.352817224540317
+15.13178606373387
+13.469629846562114
+15.673868754469197
+18.95534584247369
+16.92362146995086
+17.204991053159446
+17.601635989327207
+18.93547451383239
+16.384262372692717
+16.415623956814613
+15.386551228196893
+16.70052319278716
+17.395507429740363
+15.276976082383669
+13.807417370833832
+16.3330960057108
+16.394443151772222
+16.861071518201058
+14.055761487699485
+16.518148988606
+16.630229545690057
+17.791522136483465
+18.03054111242912
+18.81127652397751
+17.050617732202298
+17.346888338299166
+17.586495341152514
+16.347850954956485
+13.726234621418186
+16.477309273076358
+18.224562613318696
+16.8169880571635
+17.88218325228742
+17.885345612698544
+14.03188302268238
+13.971917878924671
+15.645088816761685
+16.449813372367387
+15.027555543454568
+17.523929168230595
+15.954542140973587
+13.987959109541706
+14.470200771532163
+17.39260839037864
+17.783715399110307
+18.18790742773497
+17.141419875130282
+16.151409356941954
+13.694129690281528
+12.83749224204442
+16.506704488004445
+16.370716595231457
+17.747640096425428
+17.010372243208067
+13.974329303068828
+17.03952653813046
+16.346716954164847
+19.402454576198096
+20.87334996471212
+16.32543723828752
+15.473659903161717
+17.37970755193085
+15.95453613920867
+18.237889857393682
+16.191423219753048
+16.183377874150878
+15.76119317092882
+16.10886011099126
+16.364986123490567
+17.99404298389703
+18.81077062707729
+14.087695425268379
+16.1578228166819
+14.558357248388788
+16.375383454109496
+15.530581107509548
+14.72861671487125
+16.272763048393983
+15.565094813673127
+14.538639084533628
+13.500185536188013
+16.17248724212091
+18.011941272138827
+16.83939224940373
+15.306736165212243
+12.597694839585927
+14.080917099434416
+15.510098987670787
+18.283257714170034
+19.63074169094274
+18.78125838439361
+19.17516870715734
+17.649626726819562
+13.928675114949243
+16.753597439545402
+16.92828571094813
+17.784866783292543
+15.683654429335519
+13.561838190015592
+14.955208450837418
+14.00733899876208
+15.934769458764094
+17.834202199350088
+16.87260991337415
+21.44065947636183
+32.62927339066789
+26.342015212108606
+25.33977681659863
+20.71425986815234
+22.105095436935656
+21.1478780735642
+17.74253956464584
+15.433489682078132
+15.520034994856829
+17.646905607017416
+16.899499785300534
+18.21809705936515
+16.38393534486417
+16.73149744674282
+19.21688990971019
+18.582312268255635
+22.00972323983636
+16.104078493141117
+14.663566891749198
+17.210472035951582
+16.85893273122528
+15.764961767633807
+14.597405819510797
+15.258176127485939
+13.725953929316077
+15.823137334029369
+17.826210217095735
+17.037815751911822
+17.693766827590352
+15.322022271449114
+18.21708237948951
+24.851368754377376
+29.366984458549027
+24.59222072601368
+23.229668432008893
+20.039895917258818
+22.445471509048076
+19.765458669791627
+21.364074643485125
+19.196680447578416
+18.749324128694596
+16.983831963530335
+17.66643176729815
+16.266229104038118
+15.726311148722928
+16.39454307943855
+16.434103053012038
+15.723862864042175
+14.985113169176387
+15.427455458025946
+15.945856138380748
+17.16807719334004
+17.533042584632327
+19.416969080845945
+17.97829661443984
+17.377287879784248
+16.99108656623632
+14.41446464371127
+21.934488822382804
+24.283515829383475
+15.940929295507658
+15.590698206383536
+15.881240034486126
+15.93822007244276
+16.9199892709656
+16.635798700159043
+13.113881764898395
+16.76270172323096
+17.652310991815384
+14.932463286887398
+14.351573054242081
+13.963224391486321
+18.891877110960678
+16.150619401321947
+16.468873607503753
+14.454774019534113
+16.03084753641963
+15.363315789827269
+14.991530079085862
+15.308100448377715
+15.748301556434924
+14.037329953122068
+14.05438827384512
+14.447183262958333
+16.82605235319194
+17.913594032533
+16.50033995150605
+18.18206074774031
+18.044479762460668
+19.530354937279768
+18.064880074616227
+17.889627144916005
+15.593080871794655
+14.235523471547737
+14.6364953628795
+16.104875830353038
+16.235754790350214
+18.114475571702187
+17.672832627454184
+14.700430164497334
+17.4446535753666
+19.61885319072428
+20.91990400367675
+18.616143165394973
+20.465017574377242
+19.133405573887046
+18.953149584802034
+20.888630122133023
+21.402450116141935
+24.375998111447473
+20.7618495829267
+22.111334093303753
+22.9920491936508
+23.752922813313617
+21.356459968329588
+21.31373676238664
+22.80577234620658
+22.67562116611724
+20.784871997597307
+19.663026542801603
+19.06844879643792
+18.89238746892663
+18.42687530536608
+19.976726500072147
+24.317943918794498
+21.182882520887816
+20.590923646680963
+22.93058715214798
+19.758561108799697
+20.917251483108203
+21.67041330668178
+22.277361025317376
+22.370176056439846
+17.994137342693406
+20.332585929308877
+19.448991441088282
+18.933832317574115
+18.390256294940997
+18.542998929317875
+20.21248733333347
+20.466332282089382
+18.360609505299834
+18.02557928010414
+14.952247143681248
+14.146813085796424
+13.795652748267472
+13.405751318857398
+12.971682470366616
+13.354691940820103
+16.121444248403847
+15.054315508710289
+15.564566543588583
+13.521234647784496
+13.247092818763008
+13.165358796093145
+14.741096009867363
+14.233805499285623
+12.192939067748924
+15.137149994297303
+18.163953064583367
+23.621011664647725
+22.393043555430864
+22.996367935930394
+21.84751570209147
+24.875268230422236
+23.60322058039661
+30.660011698164254
+32.14837712403765
+31.7930033788019
+32.246630404659456
+31.142511455788593
+29.562475591412948
+30.03818678840463
+29.678434438551747
+31.682838240309692
+32.27791063279612
+30.577092239422797
+31.30718817435529
+30.871969714517277
+29.619537466798036
+26.673957817924375
+18.732755841956106
+17.39070569948977
+18.942669685176
+18.190209457511557
+16.285690743374047
+18.95649619259963
+17.097598770308068
+15.989695385665456
+13.778237906584437
+19.524943294367134
+20.48398499657621
+19.751750568326116
+21.531849934463594
+19.749249898303944
+21.127898839687802
+24.31516501902702
+28.012894434333333
+30.93220606475613
+24.753205103399267
+26.87435408759704
+26.518395707075925
+28.0495810257774
+27.852948726827734
+25.302036537192507
+23.31585567500092
+22.01717617733877
+17.61659430532798
+16.218372936747997
+17.23489011361785
+16.468322593593683
+16.944022449809935
+15.478938271268547
+16.096876769578586
+16.50229300650662
+17.434502619260968
+15.707364141392063
+15.894809661783498
+16.31998219922953
+16.21316539428547
+14.323566378608874
+14.846149821194174
+22.62111926827933
+25.393860941806793
+23.154084367860534
+30.053603150593403
+33.859434491965445
+24.09166335661621
+23.229353103823286
+21.877337791752637
+22.728025582556583
+30.420565060261495
+31.829283111433853
+31.012441615011923
+31.704327758266885
+29.61897674051201
+28.3329394313199
+31.002212142548927
+33.50150184523436
+33.33532287675679
+29.236456195661134
+28.735399632254314
+27.68147239093925
+30.100868159884698
+28.720218796060664
+30.816344240840678
+27.670756622797043
+26.903907748115145
+28.191034550347823
+27.250818934498355
+26.19036203783311
+27.86128204825509
+27.729153489829244
+27.714071445055524
+26.56298792285139
+27.188058618403375
+27.0683289211198
+26.24319022380105
+26.93147264131835
+27.606212847598584
+29.18060371443353
+28.569856653123765
+29.876125141865174
+30.66200862433591
+26.646718512739398
+29.406222918258862
+30.142674715845118
+27.278628167820997
+24.30944313234346
+28.16537455769644
+26.714339322328485
+25.534114716023822
+24.36358191457549
+24.02246523460225
+26.203820382919076
+25.239437248170532
+24.54497874795038
+26.98178438509578
+30.41358629144294
+25.643668458743207
+24.230563402810944
+28.799950644122887
+31.47262721726264
+30.27581579223144
+24.868997069907962
+26.98918287845366
+26.334759232677783
+30.487106142730994
+27.393220983365538
+26.625804597460856
+25.539101508417673
+25.02808461014972
+29.07566182979987
+25.935334589986738
+26.286354886758446
+25.681279648771223
+21.769431146595636
+24.84339342875019
+24.637186713119235
+27.483489812419478
+26.189990262104573
+29.86374362429447
+25.78532004364328
+27.362502198092415
+23.961294976511454
+26.995001295267087
+21.211066548845963
+23.74495251959435
+23.03104189101083
+24.725715619202532
+21.223947025904593
+26.644815732144238
+20.14615975873241
+23.517743306633463
+21.66619266756632
+25.927314768201967
+22.27022310246754
+19.173340418801814
+21.80516806237634
+20.067180130647657
+19.089166658618964
+18.93728858901936
+17.554967165350845
+18.464621156734026
+17.096571183024167
+16.638731657605035
+17.315797709064796
+18.333377808943652
+17.063524249662848
+15.25537925990875
+18.0429126665406
+16.764691455560666
+16.724865678373533
+16.308077983837777
+14.077008783941707
+14.044223263395324
+15.686519677870578
+14.204743768971568
+14.512415286428663
+13.682644299244998
+15.226210987331868
+15.241877806731182
+15.832525982151466
+14.871647168487257
+19.192141166132586
+17.086049295705052
+16.182071013517188
+14.374285585955121
+14.888304300337978
+14.045194529013557
+14.976163230682758
+18.1855198002568
+16.55010658155291
+15.073151719695417
+12.328495471845699
+17.39110060523369
+15.339346088256676
+13.826767312352786
+15.168411659342098
+15.363491689703807
+11.859206502166842
+14.297680377176377
+10.031696185160357
+15.79274736675977
+17.363143862736862
+16.843633326852796
+13.803242698885995
+14.229664719071437
+14.3491572672214
+12.96533535576377
+13.409611626676607
+13.171811968647077
+14.76978299829581
+16.486299431324724
+17.32124365332878
+13.33175263957601
+12.785595941209962
+16.235763211688834
+15.929870682575427
+13.801343777461426
+16.276563880496965
+14.055721902752765
+14.697828884728551
+16.74226527577423
+14.562511877250714
+18.681179341120327
+17.593875404170447
+17.269007030641376
+16.472191939892966
+11.977121368959786
+12.514010102992117
+14.929461432971934
+16.408884493633607
+15.08495902381874
+15.191226665303006
+14.616551400207825
+15.34152815801184
+15.371626461574166
+14.785328771309295
+17.080124155060034
+14.523408870026955
+11.68984172363983
+14.0918717612427
+15.972320119598194
+16.20988242530231
+15.42759680896323
+14.540585488105407
+16.727607220382524
+16.034531190559093
+15.478779850033106
+14.779709724216517
+13.356665603352766
+13.626883760085065
+11.90945842161652
+13.336866377393463
+16.709143911546406
+15.862271086189182
+14.965638712863537
+17.15849512527845
+16.579122843636114
+18.724913720153282
+15.337252302427999
+17.098474276619427
+17.405260705302183
+16.274609364413934
+18.476798087049872
+15.473214462689683
+15.045184175025767
+14.688527875904086
+14.574109123978346
+13.68924109983952
+17.57178036176211
+18.366206238305026
+18.538122605218916
+16.32226980981575
+17.074082640953137
+16.268824608193412
+16.049426944976062
+14.541905490667304
+15.118596056306458
+17.406816401720832
+17.32244835207969
+16.35790772011559
+14.147917238276321
+16.96275395916757
+14.204605270443409
+15.951080956828719
+18.266986193363735
+15.966619714307157
+18.442821540785047
+16.428002485597773
+14.298800762393498
+16.739702571337887
+16.301890856992827
+15.971090051164637
+16.06876304272859
+16.747136943003284
+16.551878581187424
+15.261812482000181
+16.14317867971036
+15.67992037357888
+16.4455407770745
+17.335487253258293
+16.749291784026994
+16.14668344397583
+17.241339198015154
+16.253456118401573
+16.303535673403417
+14.336077874799471
+16.421685019022576
+15.355279958230852
+16.76059299815408
+16.312320531123518
+15.99424774959023
+15.66160996978411
+15.893095205624732
+14.87754572926687
+15.757446554157426
+15.54198015518314
+17.46819513096314
+15.289062072625569
+16.219677518091373
+15.098562729794253
+14.41184484021774
+18.97312078694948
+15.335080431179236
+17.66023768838842
+16.032046891940794
+14.067252944995843
+17.46767273848353
+16.59300673701891
+15.333955709854038
+15.854009406092999
+14.932277284748608
+15.416102573460904
+16.60628908206546
+15.793080335183276
+17.139833014528847
+16.083973563111797
+15.899230571680064
+16.749273376143407
+14.927825745284437
+14.03574544259935
+16.018522018752037
+15.610171639810261
+12.973959018656316
+19.213665141636838
+23.132225127583396
+16.886359032491356
+17.698848879363922
+18.67679414274832
+17.510731925283068
+16.91696414456142
+17.461259983141233
+19.781747004645993
+18.397842921586175
+18.824176319215894
+19.3381669293086
+19.1811240378522
+17.070916193589213
+17.667121655374885
+16.363079492504482
+16.2198805180618
+20.482249741817128
+18.88900297968779
+19.78580683693032
+15.887500401955165
+16.09094265912806
+19.54346666529159
+16.721184621837168
+17.13155748750401
+19.65469440612391
+17.806456725953424
+17.66173759356296
+20.380624260705602
+21.752933336345208
+19.819305715161406
+21.68376049156953
+24.247322106935158
+25.05317859047925
+22.578355396709455
+20.36075043263338
+14.027696614483276
+15.967764056786976
+17.652899579937483
+15.758787592578429
+15.480457878002397
+15.304380192559023
+15.342810703344483
+16.01507164174903
+14.078860110572933
+16.38032975804896
+15.265574115449255
+15.812694078608175
+16.771564963789103
+17.83532821381614
+14.821861989810955
+17.384783740423586
+17.804891953630516
+16.239249335867683
+14.529755120492283
+16.950791179953328
+14.295659159402518
+19.793056058534418
+30.963766837121554
+24.592625984325252
+19.42815743365118
+19.970021868273122
+21.535774324564983
+23.344647950050017
+23.30678500284148
+25.329609498262172
+29.072758521091046
+28.794073144250376
+24.307709369310132
+21.502722118513134
+21.132920792116153
+27.862801726676864
+30.49146365478022
+24.48265737724246
+25.971219086226128
+23.816699536242524
+26.93420909202399
+30.34059215680773
+24.77903520006356
+24.838057028573942
+22.543382929164082
+24.570952093538025
+23.957050663749968
+19.9014828826477
+21.17601001328339
+24.385831107116815
+27.100778678528272
+21.835455299239968
+22.334507607562003
+23.271311873678158
+28.178058438998093
+26.020020230778087
+24.996738534795128
+22.874545417471197
+23.657941305577893
+22.985532013379313
+24.620922313540248
+28.06497888745467
+25.346288226641136
+25.812680388097206
+25.069858407351617
+20.879823477855098
+19.9150555068789
+25.363198106975176
+24.89482170266764
+22.389082951843875
+20.23183843504323
+21.987442019830326
+18.540702995612392
+19.65862784755174
+22.650536669646712
+18.334053329961037
+20.527057434239808
+19.057637712635355
+17.13242692254805
+17.18499808751143
+18.12365193159023
+16.180367236139787
+16.91710231369477
+19.238112141725807
+15.993692826712305
+17.38650041937818
+14.63696916549651
+15.36558108754609
+16.957071637405946
+16.174910317381034
+19.262576226829665
+16.88443208266925
+20.06100856157026
+16.92574400523091
+13.51897231509075
+16.15832139596
+18.61653636083004
+18.801776193254355
+18.47486252798059
+17.18561491859589
+17.62068139063969
+18.077988989841046
+17.739278073549613
+16.4879260906297
+17.542895131180117
+20.081578577788093
+17.18796023881073
+17.013503986478653
+17.559701813010776
+16.945857980009933
+13.875754458222474
+15.013983370204855
+13.340897798520558
+10.933910651018508
+14.371354287077637
+16.878661254348657
+17.176629211834623
+16.982660446285152
+16.00659455444658
+17.714527275208766
+15.69028112963285
+17.348523758969222
+15.082618881078304
+12.910579352670155
+13.91852086139221
+16.809108988875053
+15.06092730101362
+16.351662561048357
+19.716537531276657
+16.854059888979265
+16.000279469046248
+14.510323904223512
+14.263454823545445
+15.463558420391834
+15.11255060381356
+13.990326751412823
+12.416853255668983
+11.270457883021535
+12.977952468193436
+17.106295269610868
+18.73380564096945
+16.589974640105638
+13.637266155896967
+16.07194583506852
+15.601903379403197
+15.17690053297359
+17.706755637297746
+15.611113880365778
+12.981105850913707
+15.355013344447755
+17.26778700883358
+16.06558562917529
+16.269647909311928
+13.962751647961042
+14.877056019784817
+16.890643895117194
+15.407769499437961
+17.52996908831014
+16.77064117632844
+15.685713237581837
+16.68619361965105
+16.714406629974746
+16.51538409390723
+15.28009839694802
+16.70341121044872
+16.23572452507854
+15.76178347972261
+16.640793632128222
+16.7074159306179
+17.983721819155292
+15.949119860408999
+13.994492242880398
+13.707171933723544
+14.78211417990633
+16.499907794900068
+15.927948846620907
+17.76240579653566
+17.01085998414443
+15.573692760411546
+16.664986313863622
+18.927202049945905
+18.023980517642485
+16.620193246430404
+17.98180481545515
+14.893628601950596
+14.2529048532205
+17.096540774716686
+17.457741568303362
+16.374374843694113
+15.725909620018243
+17.35975866546474
+13.088950367268453
+13.26390520906341
+13.61180679176023
+16.20043761124569
+18.37026066609927
+16.701408678401677
+14.454520870094584
+14.01575681659152
+16.316699323060107
+15.398958733296112
+16.110027685680436
+17.145510604340444
+14.487190202169103
+16.16971349388517
+16.419504363931225
+14.412715405180862
+14.438395960477777
+16.034242141496833
+16.035064688455094
+13.49381251610609
+14.496197534780663
+14.038157485718543
+15.951866892586722
+14.836338375579984
+16.705324206544603
+16.797518136628668
+16.539245613066086
+14.596887382299812
+14.88291005619341
+14.354264515767994
+15.017257445669316
+14.242879058685773
+14.725582906126888
+17.16785004447128
+19.441187877596732
+15.639442875870785
+16.196918756986392
+15.997136889485603
+22.648293042347717
+33.271602185841985
+25.738499497171418
+24.828071384578877
+20.72930364757744
+22.564020775804252
+21.425804846146875
+18.147311055169197
+16.678330574892712
+18.82194566976662
+18.94366048166728
+17.308636641098374
+18.29790283952562
+15.734762313238221
+17.513301060635484
+17.402374213103073
+16.84059723525769
+20.72854869087749
+17.953791426149976
+13.758805689924287
+16.732473589639383
+17.327788263956094
+15.383743420923878
+17.51343600674697
+17.453094291980307
+16.73404465438388
+16.283111422008787
+15.430459387753402
+18.369877296562166
+19.96344782249372
+15.341775785573404
+17.17461680983064
+27.73551491194013
+36.6494562676223
+28.249382550602462
+25.9406287539897
+22.11529351760447
+25.643632318921547
+24.21446586569779
+16.16708139641959
+16.609779192526716
+18.198629016725036
+17.431729768155407
+16.169340861224597
+16.157884375679117
+17.193710831036967
+18.048527979003993
+16.510335302896863
+13.817474526316403
+16.87480726978906
+15.73020663854129
+15.596666052728636
+13.458889863723797
+16.139985625307816
+14.795334779080278
+16.05822744223819
+14.896556818506326
+15.895027302279559
+15.2980072645163
+14.554626993900072
+17.30890016341324
+14.210212986891122
+13.754826735679657
+17.64839236731224
+16.930461688807824
+17.265915764424065
+16.805817231707053
+15.375116258163857
+15.772975673674196
+16.13721295063837
+15.625161106687926
+18.787668190709
+15.628789562583464
+16.76217909216807
+15.572200769880695
+17.290404278801773
+18.404690380339915
+15.532413060538644
+15.053223536074512
+16.434441728904474
+14.519332909410622
+17.073200004109125
+16.413156233995082
+16.636424703092857
+18.291580793716477
+15.061308552020208
+14.338643374661316
+18.168300827280433
+14.420938496591162
+15.143704632552115
+18.523495311039085
+14.859200486994283
+17.952584544335892
+18.945584480557713
+17.41724184940223
+18.075016052091357
+15.961242727762354
+18.32742804346954
+19.164939332990656
+18.67495264372762
+15.298274926233901
+16.93972732115664
+19.49089783359061
+18.175869084216927
+17.539524702513816
+19.075296446907018
+16.2551751500517
+18.23802135984083
+17.432251270587827
+17.942267294655466
+18.268409126563228
+18.473417140955917
+16.656160926999135
+20.735414883210368
+19.383870143040667
+19.646265729168974
+16.769742832188513
+14.833450939022356
+15.798680373179863
+15.99064016491127
+16.71335144643797
+17.191375193279654
+14.510315972360218
+15.33682703668623
+13.879022866420229
+13.92322970495077
+15.166867980655056
+17.0804688027619
+17.36249577868857
+13.853469965864122
+15.291554203056492
+14.424420800108933
+14.642104904967297
+17.413184249084253
+16.446064443984767
+18.00732470531237
+17.167500280976057
+16.825357782432974
+15.722451321767593
+18.772361182715045
+18.054314996649808
+18.18348667254
+15.351387666841518
+17.157436207366374
+15.979442495059146
+15.253570345863338
+15.363378042330893
+13.689441665813007
+13.765815078222616
+12.635023119746307
+15.633164040696101
+15.482121383054633
+17.86615978201887
+17.004785969182038
+12.305880197978738
+12.48789691396749
+14.254280370411209
+15.60119532216433
+13.160628928812699
+15.376884508980723
+17.97254830633632
+21.997916046371884
+20.522853676394234
+18.17827416657336
+16.001958988072303
+18.426406606211827
+20.04394857356928
+21.829067568772373
+23.866444210636928
+24.11298675795119
+24.886782437222408
+24.2052067184445
+21.771944502486207
+22.131953509803665
+20.866110220212065
+21.39643932069731
+19.310759132112068
+18.54934772858269
+21.03465449354492
+20.65807502091785
+17.88568804292585
+19.333542493732935
+16.72143767146585
+15.732513848166192
+17.531288190092837
+16.215323656418036
+14.87662774753106
+14.651937580811321
+16.98016467906882
+19.003352993164967
+16.825594266452853
+16.93485540309335
+18.65969795885026
+17.527122839325315
+17.894252260829845
+17.425303836298028
+16.955451689476888
+19.51959579248215
+21.179240460872407
+24.519338003888464
+22.036749042903338
+22.67239990191466
+21.680291174804793
+23.281594661348933
+21.47711685085497
+20.12250928708231
+16.488593229456043
+15.160569046441552
+15.172725349209458
+16.570928600786786
+14.672038645036835
+15.76341543894047
+14.849647675290612
+17.040225637351625
+15.075389781344029
+14.185734868856784
+14.951105011218857
+17.100957921189817
+17.040346433888473
+15.528698687538864
+15.84950063311706
+14.594099453449232
+15.270225002578556
+23.072777424739996
+24.962774001649464
+23.74921905630164
+26.165769304695047
+29.734304796685507
+20.639720163169926
+17.262928475870808
+18.150479455053556
+18.555183837977864
+23.094190624179518
+26.934322608366216
+27.175541077482805
+25.15302224324236
+22.718040389099812
+25.49563255499963
+25.355305199628205
+29.056182118372377
+28.11642989562783
+26.610165380698774
+27.414569285358994
+26.134164215342366
+26.475528927357075
+28.262105642612553
+26.818702246804335
+26.768685081601078
+26.884195267904857
+28.195758551672412
+27.211704338143434
+25.905802849329987
+24.80825042974712
+26.004798661840837
+24.72651015326896
+25.20688054204929
+25.440465811249666
+25.384172001416815
+27.290578461884152
+24.786009576757678
+24.986921018807777
+26.509420205826345
+26.768526636331956
+27.285302029950785
+26.24310829622418
+25.1032585505006
+27.047286969825493
+25.59499378867656
+23.291218864231737
+20.810994525851626
+20.015428535458497
+18.35832488538186
+21.3520261061971
+22.141295057101473
+23.093910831028253
+23.81783252514998
+23.585219015636156
+21.3761141971504
+21.512399035771935
+21.119910966409307
+18.95323796044711
+18.598920179425917
+23.07207024677716
+23.20706333796778
+19.56864736395238
+20.404000905007265
+20.931672711489497
+19.9006803610625
+18.772982824552486
+18.348259124860363
+18.444680497651092
+18.32018165331671
+18.57769725806868
+18.10972555492323
+16.904003800523114
+14.948815442473645
+17.682939076974762
+15.211752458426687
+16.66784597351129
+17.42707060165293
+19.329952462540575
+17.558985811466286
+22.663061653975348
+19.478027181383695
+21.848692613335473
+21.357887933473563
+22.171732425800016
+19.03062754681916
+19.327464883664476
+17.993646971512376
+20.632131633445823
+19.446404076081976
+18.318779583578603
+17.486683773707682
+17.04735570576102
+17.593983009252952
+20.467735562390445
+19.200531030529575
+18.19822410273656
+18.21956031535335
+15.693800870645731
+15.351340086972101
+17.26503300568254
+16.023531137282546
+16.114611061188825
+16.923522930561987
+18.388136497094834
+18.48209512952006
+14.99825459400445
+16.842474583155294
+14.866375351895357
+17.426368776239087
+16.12947894974114
+15.030844254211075
+16.441348092594396
+15.51197259831531
+17.33718259875849
+15.38003887401139
+15.396971074429544
+16.896778838015194
+16.759484587640046
+13.565715777451501
+17.33027889614901
+17.38953208261664
+18.233962232574825
+16.765001755310948
+16.116497837524122
+14.875831252234562
+14.950167935004956
+15.257977184445124
+15.843005657327225
+15.576726564010968
+16.210472603145902
+18.681839908277894
+16.51360152372021
+14.590773039411829
+13.876158924209179
+13.215641543384763
+16.542062291954082
+15.612196441942231
+14.450743821001737
+15.830703964241295
+15.01148706990152
+15.789843169221157
+13.925890586082133
+17.114057723618572
+17.028573375693483
+14.569852625492118
+16.286721822045322
+16.426591231891123
+17.505086487040458
+16.190291645985283
+14.611250622886445
+14.78481493151888
+13.826864897587214
+14.08251425930571
+14.255900302391964
+13.83466419205972
+16.218064950231508
+17.559518896121062
+16.76806403407069
+15.5773671952319
+14.519278048740901
+17.18757388280447
+17.64871891367605
+15.29901857460321
+16.427155272156952
+14.500119738397828
+17.584067061565605
+17.206381970426847
+17.064008255176944
+17.5557451342042
+16.5931754577215
+16.627012042810335
+14.184079668836688
+14.85307520069783
+16.87779663905691
+15.535352070279771
+15.342961709925191
+15.62203734398166
+14.211676402954666
+16.04612800575204
+13.856577198537082
+13.145248845563444
+12.346948083953862
+14.775600455764064
+17.45884111245509
+15.782008068453848
+15.952305320366989
+14.606828006602484
+15.118211571532697
+13.006293248831568
+14.008148699985199
+15.949869745358
+14.734673285094757
+15.113317757699676
+17.413217381372633
+14.730322114221195
+15.878970171319466
+16.507192318760517
+14.545338408280358
+12.867053244754445
+13.225989593347037
+17.240442768508657
+15.393542035164785
+14.542278702205593
+16.489793480996994
+15.687445522340553
+14.244899030888547
+17.389067422322285
+16.44367333949728
+18.577607143444013
+17.072855359722226
+16.5643750748427
+16.011850389750606
+15.91977373561005
+14.534571783678388
+15.077210803196138
+13.467742998395536
+13.939287460610004
+13.913682119316931
+16.166184595029975
+14.829828284353383
+13.962669225811325
+16.433123958562547
+15.664274882209156
+13.729777714956143
+15.922791019701961
+15.688920466147252
+15.400567179940154
+18.140970066825503
+16.634654498783163
+15.368996142909793
+17.68265018882171
+17.265034482521898
+15.735586509371359
+17.388541932156173
+19.50635308068088
+16.803745080604173
+18.316842607754026
+16.18684044148023
+14.84176843393611
+15.426175444063034
+16.737479173525216
+18.319411891642588
+15.0313009702502
+18.28447121040803
+16.724206543893345
+15.709477813761524
+15.693668463879078
+14.756461785916144
+18.141355644273887
+16.683398958670608
+15.84450090965764
+11.702882984859613
+15.436270699749727
+16.243895078893246
+14.942475642097193
+15.958990054872174
+15.493041841762604
+16.373020067436457
+15.15318494225886
+16.600977662658963
+15.75397461530521
+14.662093073306337
+17.581735518031493
+14.617903438220722
+16.71208946218313
+16.625173703565835
+14.937740109308322
+16.56369952783207
+17.461641057302074
+14.772840959922235
+17.554566360085218
+17.996898004655307
+14.672069808806995
+15.595104721378775
+18.3269853529941
+17.445679175600375
+16.887072882241185
+16.328169194818727
+15.303970014358825
+17.87245708272529
+18.679148347992907
+15.910715432033413
+16.351609605568015
+13.547545781180602
+15.440780819580183
+19.06927491197591
+15.461265254203752
+15.102880542481927
+17.27273986198152
+15.76737713644117
+18.731531613703638
+15.577065236577269
+15.563661220668521
+17.02830008333946
+16.362947622767294
+16.098365155818968
+15.028666658826054
+14.664165830547574
+16.525350935789206
+17.147422141954067
+17.419485956648558
+16.42413049087962
+16.162351585684533
+17.990162771131878
+15.951388308059421
+16.703202001346312
+14.871611494553989
+17.01799753076682
+15.923407345500905
+16.915445425575328
+14.708434520413078
+15.460464990041643
+17.05605640884211
+15.974774774602594
+16.36724563620581
+17.0804528668651
+14.906480862181311
+17.85261058082878
+17.15404451903865
+16.05509839691365
+18.104962548328274
+16.426577520074304
+17.049826261635246
+15.837764922863997
+16.3031538475703
+14.241818624546553
+14.062225086527576
+13.680556078375531
+14.058387996168705
+15.850429742525776
+14.720695631127029
+15.002967234422158
+16.097121150215358
+16.569482448082297
+18.382411314253602
+17.041518594675622
+14.258528921405045
+15.483708628908744
+15.813753935582753
+13.69223388109964
+15.25112248266116
+16.810781637742167
+25.991879350719586
+18.873035906189344
+14.692070357710449
+14.685347706923636
+14.27169210433432
+16.778073870090523
+17.287836665171753
+18.200462353867522
+20.27406966535561
+19.619331916695543
+19.20812195830527
+16.377597010023635
+18.0998044523525
+19.405285390270606
+21.94089747496325
+18.410663137220396
+21.17649243436047
+18.651212163871364
+17.062648274907716
+18.01795913331661
+18.26155925262057
+17.92684046393505
+20.822960819168188
+19.153682395546966
+20.497661279724426
+18.008116824472467
+18.161231999818895
+20.94987826883333
+18.951068545006535
+17.27919163817296
+19.04594332937107
+17.412737554896196
+20.250861603857444
+15.038638180045908
+18.1582678207657
+19.250969186495965
+20.58716273948987
+18.021619888703867
+17.797626013342537
+21.044831058102744
+20.143375944590233
+23.23788719299067
+21.551059947414203
+16.45366245270573
+16.95315340265131
+19.883967117026117
+19.81735647191961
+20.142480336967807
+18.562058093115283
+17.868393072458815
+13.558362147326392
+16.22403343074599
+19.77144694822387
+14.482161139502011
+17.624754299179713
+17.65056524504611
+16.292369172963546
+16.791657479418205
+18.329325894929113
+17.142095732111073
+17.2772123428379
+17.197347553577757
+15.623427864147743
+18.50615320678554
+15.070978638167603
+15.271147668185392
+17.150326823696446
+15.716858784181724
+17.23458519704205
+16.609965100324203
+17.293037314423643
+17.1775629953018
+15.70778537056664
+13.987873252947196
+15.249526285005118
+15.247359047448427
+14.804068831752915
+17.23128617569057
+15.291133387277455
+16.68669407032749
+17.202765590972533
+14.301384610909011
+18.031738029667324
+17.47104179200946
+17.775319427920067
+16.945652022956935
+17.332759112300963
+14.905444783020627
+14.30822490285577
+14.652566081948592
+15.085421849335148
+15.19186503283747
+15.671306193843833
+15.815299241166471
+14.349659556681388
+14.89297601838122
+16.169290713299745
+16.767048785805628
+15.644687881080444
+16.429344797019965
+16.62340694289408
+14.489528720815159
+12.86466683291006
+16.131736577425457
+14.943146674021236
+16.72261244573143
+15.176928328881715
+15.623683765234858
+16.413439557287433
+16.188674612527834
+14.546813805369865
+15.835851097063383
+14.275046615243056
+15.348634569709645
+15.00167499269898
+15.715736901301781
+16.641580899498194
+16.466722968585387
+15.864387956464881
+14.12745764090728
+13.291909610853011
+16.671797310274002
+14.961352460381235
+13.11597278382817
+14.10302866361559
+16.236929650422354
+14.500993554578358
+15.948346255973291
+15.555806953393713
+13.501990446920288
+15.217327366353828
+15.134769008548943
+17.108008031106493
+16.146985801830837
+15.344771049406162
+16.303342921545024
+16.51855446512063
+18.526603111707942
+16.241421172954162
+14.85839012014766
+13.78333504305327
+14.087106076654806
+15.933570154973893
+17.364720380531267
+15.736463492989017
+16.87196487348939
+14.319583326118064
+16.112239237594977
+14.456149423569983
+15.286264307272205
+12.57188839244904
+14.169468006632172
+15.655967070471476
+16.14188111258055
+17.065681842260247
+15.755271375346226
+14.877377208408447
+18.438540947193303
+19.277055905608663
+15.929211619490374
+13.505361978714987
+14.672065008250712
+15.614898230847658
+14.53737661292051
+16.348283934589503
+18.42529934250271
+14.60047268429446
+13.60503276741862
+13.868469154240131
+16.606919060334903
+15.03387151621827
+15.58544651647287
+17.37588527213724
+17.864663828403124
+14.715528038960016
+16.624216958318655
+16.461327919402805
+15.988604810320624
+15.611734010001058
+15.746814038356689
+15.62891418607667
+14.751613033470889
+16.469518045896777
+17.158521272186448
+16.634909817371252
+16.380738949420362
+17.155103578093076
+14.5235816459315
+16.40921143658275
+16.49411063360408
+16.007603286210028
+16.15936369061164
+16.63595046948582
+13.652037681952166
+16.879691503653888
+16.255874282653522
+17.40696847966028
+14.37209883900907
+14.026724618415429
+14.352688059438975
+15.616290824115183
+15.940825249930953
+15.690324653833358
+14.244573150828387
+17.009284467976087
+17.091042675415395
+15.685311024519422
+21.785040461262426
+30.721678312066956
+23.52735999244372
+18.420043847447943
+19.209665435857673
+19.70157818808437
+20.084285484791607
+17.82635950221359
+18.03821520645947
+18.206672926342108
+16.866865894327148
+15.158132289422127
+13.996870436549713
+14.281611191291674
+15.216283778255558
+16.510304322516504
+14.715730733535864
+22.008802977910563
+19.84300651576895
+15.90016838676388
+17.33901512647607
+14.997976593154604
+15.198784336005176
+19.359839893146983
+16.769264515868528
+15.441453299473267
+16.645643892596212
+16.57421312390956
+19.900415385830414
+22.084919416763427
+16.847233533371096
+18.008427093387226
+29.156141923578545
+37.333280588284055
+28.866163835217094
+25.13184274326609
+23.190848058080817
+24.092847349622488
+22.79203714052848
+14.522389341480036
+12.615209453029749
+15.502258345947482
+17.76981123399827
+16.830044952003234
+12.842023980642082
+16.498145636620876
+16.381439144577584
+14.829590754257396
+16.381779997221514
+16.166109759744316
+13.24485336872776
+13.15021249248268
+14.97524045800408
+13.152483280202418
+12.418576377491988
+13.616087035917559
+15.16785279842145
+15.914368281812685
+14.303854650297154
+15.600588913687815
+15.491717298295725
+15.417700315204002
+14.154385889181398
+16.011432765308555
+17.543866945536493
+18.330897686832614
+15.954545443938429
+16.0952894187419
+17.177471845212622
+14.227437607658814
+13.131749756363433
+17.47096453217044
+16.063167054938603
+16.67269866006744
+13.286070235896688
+15.110292417068464
+17.06954410744207
+16.642382138429497
+14.375732062796274
+17.049648667581252
+16.350498558334422
+15.397255852037276
+14.58125033952659
+17.475347495141747
+17.482751117077115
+13.989014448685609
+16.424634881110308
+17.064151806965796
+15.968807835741131
+12.602517553863692
+11.738161008644354
+12.615073478796049
+14.942896524709155
+17.47058337942748
+14.383897037997613
+16.668412433497423
+16.521427880587964
+15.65437456202612
+13.77893378291813
+12.9775380399671
+16.688648353229624
+16.175383652426987
+14.035842211848049
+15.387362901673924
+16.947057594380766
+18.28075018345001
+16.543022460098626
+15.15364971059121
+14.837993018974245
+15.988638533933354
+15.988664360911017
+14.607517446610345
+15.417727887011083
+16.605400294892448
+15.445841945831816
+16.415455299758833
+14.341565696632017
+13.482067874307845
+15.094832154749582
+14.086078305548568
+14.681308301715362
+16.466220028904587
+13.687966355331369
+16.21467921226622
+16.348545224965264
+14.44887880184747
+13.402564207360811
+17.92124099714566
+18.697190724978682
+16.04354485607756
+13.833037009277106
+14.87967938712653
+15.318827386415663
+16.787120834007553
+17.804725198438803
+18.14808671966101
+16.913311464186606
+18.936424388153583
+16.46322606935567
+16.796045327922215
+15.095657019296212
+15.492038066576825
+12.89349688699211
+14.50976615390563
+14.743270237734393
+14.91758751395129
+16.43180419851467
+14.521075014171743
+15.806256330402135
+16.54035467542539
+16.289101977031223
+16.426995211068828
+14.7852646756334
+15.087839086290103
+16.130230190628225
+18.450495802878564
+17.119944665323388
+13.600739831384445
+14.930128909993584
+16.870515429482637
+16.562386572644854
+19.746806497448233
+16.896641663001233
+16.54665423093212
+16.312793409769384
+15.012565087111938
+17.672887473960415
+19.94628229081262
+16.435184466171336
+19.309354504470917
+16.489719842020676
+17.124307157329994
+16.491807585875392
+19.12609704448151
+18.223534887239538
+15.120441043335504
+14.195515669747309
+13.19225525950074
+13.119199875282817
+16.250956718996775
+16.274859652558646
+17.026898188627385
+17.464597197681314
+17.879963103631994
+18.487014220507504
+16.81496204259531
+15.94711199922206
+14.288995270862145
+15.054054255573973
+16.626136722059172
+16.232254125840967
+18.50397701648258
+18.882082734405472
+16.850124904544046
+16.39442946217126
+16.059012045277186
+16.65989884552441
+18.352471834860964
+16.633912473491264
+19.081750312541246
+17.540470883379456
+17.003140332445938
+16.627101637204746
+18.96387898712227
+18.519251842030116
+16.593326499758135
+15.77377788151719
+15.206050421618116
+16.878227122712516
+15.908789879768491
+13.160117422410778
+14.779068218562216
+12.801377646143095
+16.400776504776317
+14.818844364157087
+14.331748725655487
+13.685459428473763
+16.03827427544418
+16.46805265148113
+14.454760307136468
+12.790748485029482
+13.96355216137205
+15.852089089775461
+19.96619172498056
+23.212055511501447
+21.224335612587083
+20.34057734137953
+21.814380094054442
+18.19690973204392
+18.174942459499206
+17.306381810401504
+17.065874790007868
+18.964777712039435
+21.840731451400544
+19.64444560789498
+20.333152422811864
+21.003636408018806
+20.21241800568822
+20.80468061001646
+23.475463847846925
+22.204117588746612
+21.010622373697473
+21.1572639193151
+20.627795623383307
+19.681385994011052
+22.215008414908297
+20.5622789606398
+20.225370170939684
+20.702697871994545
+20.192867365030523
+19.82363901432997
+19.252336305462066
+18.69358361053078
+17.24552916328723
+17.399936194777908
+16.386213654256068
+17.132375374057375
+17.8853551122168
+18.002672976096562
+18.712450035333674
+18.470903667524667
+17.490856164055813
+17.711710924122784
+18.66555478811327
+19.25776880998977
+17.798808779968937
+19.8648147194194
+16.765521067730702
+14.863166785050467
+14.767124611872148
+15.972224748529769
+15.52384295759309
+16.0224604024732
+15.54652617461197
+16.05713440262747
+16.85676496638557
+16.034095562925756
+14.63670329274919
+14.94934365424433
+14.582293719317292
+14.472960135695388
+15.560284460968518
+17.187149249298386
+15.34487659365756
+15.12632684674314
+15.858389009470343
+16.80121612947812
+17.030783320910317
+15.092500357653819
+18.11245421039669
+17.230461400024424
+11.980065560563517
+16.020288408265912
+18.44178558698529
+16.342694707538215
+14.296847241204759
+15.932433719772291
+16.909355904129583
+15.389729642311494
+16.50230915899762
+16.825369621251696
+15.385728047186447
+17.939583598145163
+17.1881870185251
+19.871026344097757
+18.6228243965313
+22.083837132430773
+18.93601019399297
+17.807490499854794
+16.154317344251055
+20.929524861787044
+18.074403860774595
+17.95731988835439
+15.982774152898614
+19.80317317935065
+18.311969361936903
+20.654112922371766
+18.841028305368027
+17.540800066647193
+17.039019146549606
+14.884554484713007
+16.956663708939217
+17.4986398777193
+16.400035113746696
+14.865846102243708
+17.00212731692268
+17.47005788346297
+16.465237284439112
+15.960500092002931
+17.09918232789299
+15.603851213945575
+14.351387794531831
+15.710255822051252
+14.904785805149444
+14.370003448212913
+11.468003574393222
+13.874272566887285
+15.236140582766637
+13.670891401823553
+15.541905519426606
+14.736672940715735
+15.539131952119874
+16.443180501375053
+15.724518091277062
+14.951510999428777
+18.26300891274265
+16.622647591729972
+13.59237633308048
+14.017309060613755
+14.961675716075987
+16.866535072951947
+17.20618370291217
+17.14197897131767
+16.524696316343906
+16.675822832554246
+17.498627725525864
+14.827592697604047
+14.660042569144082
+17.124619724750502
+14.785940805478901
+14.283236540790483
+15.013399458021027
+16.873215694833732
+15.800484760944471
+12.76737500718285
+16.156989294007786
+16.29888870525984
+16.136358426951332
+15.932705085022448
+16.706601967008652
+15.474309879666407
+15.316231838795517
+14.46703602952455
+16.997450208415344
+15.478680834860668
+14.197361772777796
+16.266039775784535
+13.782265005526142
+14.706064448828315
+16.43947419927595
+16.0779806142357
+11.864627944947145
+16.44273577746536
+16.119448110692275
+16.048390430011338
+15.187870475435744
+16.478727312679283
+15.014179515667095
+16.92322582810212
+14.514878331055456
+15.325461974568782
+15.91108910813007
+18.04312604807599
+16.00443679222313
+13.564690104196174
+12.204646668487385
+16.891199078495447
+14.693298579256165
+15.133595893930888
+16.114637924665786
+13.432830052597708
+11.700738596938862
+12.076784977309003
+14.369148509347838
+13.667297238745633
+14.038350227211751
+14.637902843087431
+13.877936211703727
+15.985037361233864
+15.898239192314819
+16.254795330562075
+15.837250665948062
+16.024001277204675
+14.405330910351623
+14.701297295407286
+16.661502721430963
+17.36885665205915
+15.170759439734141
+15.802690813908882
+15.7439016709953
+15.887822741441127
+14.575592216491358
+14.29313451774469
+16.68572720420093
+14.874121813181645
+15.737554440752177
+17.799099333173814
+17.311672968959385
+16.35026405952138
+17.395120395981394
+15.405772316816382
+17.921185700069813
+15.625313244638107
+14.87058052561467
+13.856206105331722
+16.032338553156947
+14.413774642419227
+15.220916830468923
+11.814427104046231
+13.92049318231804
+16.65945028332574
+18.83704579192593
+17.769530333619457
+13.737357586901751
+17.190856049682864
+16.472207124492186
+17.082066034286484
+17.49457524187001
+15.009585219537783
+14.200280187306632
+14.324944232674909
+14.304696889309696
+17.52420628984848
+15.710266692675575
+14.509203484102287
+17.465342186054386
+17.633187151886716
+19.474181844467523
+16.899520712858063
+15.928927964534338
+17.340906757167673
+15.157600007394066
+14.01015886028695
+14.547654968901085
+16.226058070650012
+17.26475443065914
+17.783891761852573
+15.5836795821686
+16.26952071330534
+16.545594048140487
+17.08586362565866
+18.643198129813698
+16.99658242308952
+16.967588966319838
+16.611283508826816
+14.624543535785406
+14.55704965045878
+15.963033526895359
+16.302050940396114
+14.868103982046676
+15.930665638988515
+18.672735102485817
+17.130607775395873
+16.47499997268764
+14.386666568604298
+14.955984734587034
+14.76288489216931
+12.87920056845887
+17.529119829136448
+17.169991155559174
+15.380413907630953
+16.24060516490715
+16.09761111451951
+17.958050902821398
+19.1418323051809
+17.497483738659227
+15.113883049987507
+13.853077633373573
+15.335904367541033
+16.13583755038667
+16.240543267121552
+15.409660966746102
+14.119988259878284
+13.889227509362556
+15.053285804462732
+15.387719505373482
+15.131350257578859
+15.708434815797673
+17.475155838907497
+16.428646264829467
+14.042926637690428
+15.610139129478156
+14.980388574801353
+15.626440910967062
+14.737959772615142
+14.68194491213643
+15.396156709416331
+14.971153000903215
+14.668882834770685
+13.03679389483979
+14.368383439307692
+16.816486233160717
+15.142430432361735
+17.59967651149458
+14.242950994694198
+15.167565694026806
+16.77520615423623
+14.709441620175355
+14.875679088692905
+14.062602210203323
+15.849072932340732
+14.124212002704311
+15.64250410838298
+15.491315018556605
+15.232310327201404
+16.723920900305288
+16.844487873230364
+16.424650543357572
+16.460880051426486
+15.356907793513713
+15.838251513860442
+15.700862291932012
+15.672293806766149
+16.39641170188355
+15.55833505694821
+14.777782869693297
+13.91803414946017
+14.516934185543107
+16.135889362902418
+16.11299470496617
+13.51996658866949
+11.856815879109845
+14.851374389063082
+14.933524895141673
+13.863667161153884
+13.017586910017798
+16.347705921126348
+19.62029572830825
+17.16683659088396
+14.707502922145878
+16.750515655018503
+16.650153401316956
+13.664044196104626
+12.58164804555399
+14.77881637275884
+21.373716947271745
+17.625988238954037
+14.89167907491695
+16.949636186654445
+14.141095236345066
+15.658722119579139
+16.393517399184674
+18.688852323799367
+18.364998759920724
+16.776455585344763
+15.86897712358163
+15.266779632053314
+16.681905094530705
+16.29711976992607
+17.283415514263453
+18.080593200181738
+19.501243367606378
+16.55452986312028
+15.995936622161864
+16.376467965275722
+17.043993141446137
+17.01967211913454
+16.766223900908344
+14.421238082187315
+13.128396041962063
+15.810578737240931
+16.136943821134707
+15.524370028355989
+18.808527132036858
+17.243891185133535
+16.20518645813496
+14.422365626809238
+16.281526928901087
+15.463066259259037
+15.748850323021259
+15.256483980096505
+15.329147837426035
+15.255767661908209
+14.081475058124639
+15.929713038224946
+15.974471545335959
+15.772441074469882
+14.903022030107294
+16.852166313292074
+14.21454155287121
+15.466650897459303
+16.58282562144292
+16.747635414058863
+15.704741514322833
+16.061577006830717
+18.19095128340136
+15.991352985476837
+18.352045696665158
+15.562728339557282
+18.08627159649899
+17.132600475254677
+15.108273416898442
+15.609447456037785
+13.86612857562423
+14.347075116968867
+15.718134314053884
+14.080664349929847
+13.930461455488043
+16.119036946053384
+16.38227522075067
+16.543741085793457
+14.389028729104155
+13.929564293619691
+12.702839973493724
+14.668020519544527
+16.110106051089986
+16.155516569013187
+16.610474581181265
+12.180434592128904
+14.351870957836667
+14.58665982848781
+16.122508806275334
+17.11141043241986
+14.669506563533389
+14.86285462245553
+15.38133902345318
+14.969035888239233
+17.680177751083974
+15.819044660969055
+16.47260988104729
+16.400297396744747
+15.097213800242017
+14.253453516913112
+16.923896198695743
+15.845298952048964
+13.711160379682894
+13.854739269872454
+15.977442750453818
+16.50604918431381
+16.18953078123397
+15.63241502048784
+16.47228920449355
+15.099604972186995
+13.546136331604089
+15.99634198325559
+17.744630413525798
+15.730169705372688
+16.789901125559425
+13.923972066657768
+15.394473961166696
+15.883640875506444
+13.469716865568529
+13.728818862517102
+16.314066543831657
+17.664580875876098
+16.841331550201303
+14.717247247749768
+14.489789176432296
+15.398744379186695
+15.805945538165872
+16.385445068406298
+15.773785827200626
+15.177066516518849
+14.665816538266427
+14.359023505090363
+15.649929356465023
+16.72100640708227
+15.148205984724555
+14.659710984244114
+15.948546983029217
+16.417873708978263
+15.692101167265392
+15.936629236305905
+15.009941263018547
+13.980782103689918
+15.61157648372695
+14.854044514675877
+17.514759803695057
+16.648817173388593
+15.558262332861233
+15.963305638367984
+14.532697595750662
+16.43697488155516
+18.48797567778071
+16.58390615032772
+17.211164970161178
+14.449960520395948
+14.768791640168473
+16.204377386616315
+14.181625183720541
+15.838561619047113
+13.499049118544917
+13.848115824099494
+14.52974871888442
+16.7642895190761
+14.55032713946835
+10.742689003706758
+11.608454374053068
+14.458562360360034
+15.121901355794748
+14.631224883257431
+13.87416378490768
+16.253083567855796
+16.662672964315718
+13.29767965723859
+14.269098687222126
+14.68311733021784
+15.834046567623659
+14.764082260234389
+17.39626804373863
+18.25239468454143
+15.584023782874539
+12.349348837730929
+13.364747467759486
+19.56277378438547
+16.201652008950518
+15.175423047709032
+14.476512976530742
+16.77780101781788
+14.880031925472437
+13.961322281812699
+13.072654878187521
+15.85794988322644
+14.837150532219809
+15.44897839393444
+15.91983206398605
+16.618518060306698
+16.561658054331744
+16.58278250145004
+13.823963148499573
+15.083233210848519
+16.89407769983694
+14.320055307381992
+17.719636805345615
+16.021187983009142
+15.810659982906358
+16.970644174378265
+16.286721782490943
+16.857732144618197
+16.124047792101337
+15.372306065506478
+16.186602833334888
+14.382793355485859
+12.719796754828792
+15.966017943727735
+13.848103471787894
+13.635087767551155
+15.78516765246738
+15.205042694807261
+16.641934922773643
+14.760193748205367
+14.466703020475776
+18.762541386089495
+24.652057835405586
+19.847107744612202
+18.171046998367615
+14.800085931626512
+16.483387042894364
+16.519932889561034
+15.164099425976204
+16.3172536541921
+13.27007132377939
+12.25883225297774
+14.621996996922647
+16.579053926363912
+15.27346907533169
+17.404863711826977
+18.336642163888015
+14.770915361366932
+20.32071327553848
+20.85999217693589
+16.613678637869896
+17.55809510803593
+16.647765639742204
+15.486558243879202
+17.131302987453466
+14.2247049547925
+15.99886029723912
+18.33978696632127
+15.909708695129368
+16.86794508337624
+20.31708556657911
+16.810700270195568
+18.315650577930384
+23.499506384412783
+28.305634313277267
+22.715331067386018
+19.487212341357036
+17.011489517689185
+18.791830982159325
+17.258329885396293
+14.190257514289854
+14.209513195247808
+15.063919854725384
+14.818839284630613
+15.017012618398994
+13.345641244659959
+13.958201791074558
+14.404047448818517
+13.226729624409344
+12.33122018947256
+13.117485041447281
+14.699186384703893
+13.91269787736259
+15.674486965087581
+17.766409136340073
+14.60321436722407
+12.994051750153204
+16.3704561244097
+16.823095812747013
+12.611853705948846
+14.646263656902718
+14.836785128917015
+14.987732894863626
+15.592218769526298
+16.362401358721286
+14.709417255342075
+14.84634783543693
+16.08620701286715
+14.657103923098859
+16.578026722498265
+13.123218842780474
+15.967102663182615
+15.013437977423933
+15.149618534480382
+15.8510410975056
+13.48285947437013
+14.48053637676145
+14.839479485625063
+17.223925393287274
+15.290860823988837
+15.497671467679723
+13.238198999626277
+13.73907386523527
+12.973792250874823
+17.62624100850924
+17.763764347818096
+15.388622945723668
+15.870944473713067
+15.230495158152152
+15.434664479702008
+15.003046389174045
+14.1548994440452
+12.458364552773261
+12.775060441014901
+12.698447822888966
+13.939888407087821
+18.094395056660872
+15.80917452924568
+14.399474221168376
+16.357295702284404
+16.014608490904422
+17.111226338040595
+15.825788302282277
+14.006340967377298
+15.768371021110752
+15.759445602439754
+13.797215664454384
+16.626208191920156
+15.575554120567048
+15.204990625295082
+15.719522791449293
+16.761312338973198
+16.286308468898582
+14.20346390184605
+12.10937375894244
+14.668147656059531
+14.682294241165792
+14.013675479221163
+14.990683506816069
+14.61263570693741
+13.913908091305245
+14.528900290395896
+14.98390618340646
+14.072093288773047
+14.04136283434228
+14.871189321364596
+16.1293954993764
+15.31201992844285
+15.610177594685126
+15.894993514519982
+13.863674482448673
+14.705906381448486
+14.672925455525828
+15.65719355404525
+14.272969078679665
+15.118395938967623
+14.209664596367489
+15.461462776047412
+14.237271047644484
+16.708086221484805
+13.517314078510495
+14.2915537159667
+14.86367832185654
+14.295406134539931
+14.723863768295104
+13.60800634532194
+14.328415162618228
+13.784083997375134
+14.781597620941128
+14.289942661489036
+16.514368455059937
+15.467631905866952
+15.123708107650259
+12.24315564630426
+12.96940758825221
+13.53380781845054
+15.472434619131676
+16.9346010950636
+15.511142041503149
+15.672894283262238
+15.821628563947428
+14.632071015059253
+18.175643895612666
+15.09632796235887
+16.820062282710623
+14.619228337233565
+14.973023539797751
+15.207263961640152
+16.285074173115362
+15.07803423255524
+17.33205562063688
+14.42453779711532
+16.494337238161563
+16.01358198144709
+16.142256551433647
+17.13861427623023
+16.603801652989333
+14.969296629483964
+12.921064167922012
+13.374250413795565
+14.73036502041812
+16.429892893213108
+16.247042614707226
+15.650576369275015
+12.166369320462337
+15.058642926925785
+14.605977279513809
+13.822719774086465
+14.69816798709924
+14.477440769547698
+15.83305651858582
+13.427323523076424
+14.260824236106558
+16.814730284550862
+14.520492786898402
+13.704311705598599
+15.711355231072702
+16.09668174735424
+18.13173978479135
+15.705836047291655
+15.8439534580681
+15.936923093006769
+15.153653507061861
+14.976013013308247
+14.439934124684967
+15.764296211418852
+14.725726913715675
+15.549007457180565
+15.038687782831971
+15.687031389992839
+16.60400075671889
+15.864089017688059
+16.54952494136883
+14.996899819884206
+15.424577648245716
+14.033249880984755
+13.593218507618133
+15.182430706224366
+13.949248369338974
+16.479366301432478
+14.783621650432423
+11.54178995923327
+13.08370381665408
+15.832415144945372
+18.419489071429027
+22.66372329660291
+17.35793783689813
+15.725830365750227
+18.33556298439092
+16.472851915085684
+15.675491706283452
+17.17695794407203
+16.48066362977083
+16.25227606855765
+14.988715852771648
+15.709638917985146
+15.903828485899126
+16.757855230988966
+15.340631781860864
+16.476910039174683
+18.19944302845134
+17.43000524721417
+15.118146435995982
+16.94880111626955
+15.81720287715325
+16.171134984962563
+15.699384088239029
+14.624679996304948
+14.26376841953585
+14.490844638470591
+12.5294786974504
+13.570616955538298
+15.85831653492447
+14.293472509122864
+13.975255404105653
+16.36754392094683
+13.467863254099782
+13.631058140838988
+13.953724930555936
+14.738558744225301
+15.720453806040638
+14.055780988102512
+10.380457275255537
+15.21670393039335
+16.033535352096393
+16.399267178961935
+14.599850550198767
+12.11295849073774
+13.480936899316717
+12.346453382897877
+12.920842152537901
+14.233235417425888
+13.452908119384901
+16.673751043485098
+15.076630658034091
+15.639239632078258
+14.140569463491843
+16.073997363217003
+14.950249310883024
+12.840771684776698
+12.656499122680572
+17.17492271500096
+15.909559221353916
+17.276600037278783
+17.423601648418654
+15.991398574530933
+17.02011775994606
+16.042168619928944
+14.279211832254148
+14.532276053445841
+16.067835206751937
+16.08543308301377
+12.31275170697046
+15.889184255056605
+17.452412783118717
+15.98797584824483
+13.22196548131852
+14.166916895013216
+15.184178349809372
+14.956347734635216
+16.673115282383435
+16.244619169190813
+13.51193786118499
+15.516959443988213
+15.208227778733445
+17.800993247502518
+17.4090777605997
+20.19300344542698
+18.563335908874933
+18.714840465920304
+14.721869217703315
+18.95770281565757
+16.8503112429768
+14.327526745065754
+14.267803424392554
+17.478134020497507
+16.21572599175103
+17.06072460352351
+15.20916839534398
+14.575575008392079
+15.607613861120669
+17.211356493653085
+17.588332896218574
+15.686110902660147
+15.888398075934077
+14.419680554691467
+14.512616672946208
+15.018567614409577
+16.690620849554136
+14.933200655999102
+15.41903728681892
+18.37067486179805
+15.001452963126255
+15.27549555428915
+15.638315635609061
+14.461651964625233
+11.53144095245662
+12.004707458675867
+14.69670268352833
+14.640520811076584
+15.076960388462723
+14.682007001596276
+16.36027770687882
+14.830226570996885
+13.005474880704796
+12.427841528475582
+15.770182939802979
+15.483501376632631
+15.031295362825958
+15.97857908923072
+13.29524198171788
+12.450288283930234
+13.140305627317545
+14.02726896302444
+16.821287392933016
+16.791908784744706
+15.47651996346228
+14.367500529649107
+13.752308026995124
+17.032916267552324
+16.786179352030516
+14.014930105531462
+13.938226017361757
+14.51939225079984
+12.630385105486951
+14.939544169669986
+13.4575381605257
+14.023668559513482
+14.613835968806185
+14.950048227993236
+14.314108640811568
+11.101607701618093
+13.321610755166617
+13.179998406470688
+15.975424585171595
+13.644495938000617
+16.580741678150886
+16.817794727090373
+15.36763452702003
+15.118664884108597
+14.57110677361355
+14.821344506958482
+13.780907461328255
+15.723875646445265
+14.992885379448268
+13.800476159513195
+13.6716505003901
+14.022059179486703
+15.475175705573477
+16.048173054328885
+15.723494610607219
+14.356658685730679
+14.5303971302246
+14.360008962534025
+17.466341353629858
+15.333367690640827
+14.477570263070646
+16.322462301152825
+14.832772886703566
+14.277261578813423
+12.540287463498359
+12.93160216421795
+14.765199814761559
+14.491910627111082
+14.404465563557167
+13.990640809350879
+15.288756907241549
+15.40671663275539
+13.850465317381747
+13.48340547766935
+13.743698125136461
+13.048124804382198
+17.39235335881672
+16.09283839265487
+15.413339002345666
+12.531281652371419
+15.174757969149624
+14.888177641245264
+14.75760878369131
+17.175211997288358
+13.584246716954297
+15.452981606123174
+13.73349880816913
+15.690059157480718
+13.295922636975746
+14.680640859471666
+14.261654936340406
+16.081273996003986
+16.36089327593396
+16.256465037478037
+15.133845415819692
+13.15908364244352
+12.092427732695128
+13.729705172714887
+15.457812633113448
+16.8686066965346
+14.662588595964948
+15.541527509627016
+12.965176182743292
+14.910056027506457
+13.096084499268514
+15.465237657375326
+14.402514901439787
+15.151467268882158
+12.33524272822065
+14.797522964115203
+12.955824592609517
+14.180918580522345
+16.2434575151877
+14.746154722852054
+15.190727969126485
+13.77858590430209
+13.807720036510148
+14.80561635789634
+16.685600299987343
+14.642785569720886
+15.728504024533393
+15.347508705343543
+15.031114234344187
+13.825968439564548
+14.068153533076895
+14.701436055520205
+13.397729115107879
+13.41891446602527
+12.7743031908185
+13.869421921052762
+15.542034965616324
+15.872786507266298
+14.502307463377562
+14.253821472430005
+14.08588227115392
+16.317187050914583
+18.742619686425016
+16.023098044491192
+16.638929646474296
+18.125296172885513
+13.66747744703737
+15.473083259986268
+15.454457203359212
+14.611735462478507
+12.53749920346469
+12.86740589782994
+13.058919674656593
+15.716184436492256
+16.29818575071711
+15.474545344728043
+13.474313597512264
+15.316908606199092
+17.03302933073779
+16.298474253488337
+14.815938631359714
+16.178962093937727
+16.833323235760034
+14.290881070106849
+14.63143034818387
+16.344843417182346
+15.308404466701333
+15.654033725038062
+14.79763264750082
+14.924503320086643
+14.796388233248678
+16.649531064102476
+16.10652725959352
+15.807184402125984
+14.762164558087733
+13.251096424535604
+13.798459065865828
+14.745294544558718
+13.753917883175276
+14.631992498574306
+14.056146868468076
+12.221940786798541
+14.700537252458716
+13.515308134886283
+14.037587583927731
+14.41373490367296
+15.180320397843929
+16.4113278426927
+12.797258954890324
+14.768915748575509
+12.334590174921658
+12.600850321295539
+13.440962596228218
+14.382989059398014
+15.872219372238263
+12.125397143233798
+13.11912527480844
+14.273514675215665
+14.329124796505681
+13.524890960636228
+13.84160779704986
+12.746522349481992
+14.60438973048879
+15.985525997888033
+16.29872662432585
+13.948750865511158
+14.680544999641498
+15.395573587762073
+16.826482711550582
+16.56010978350635
+15.108988068084813
+16.629656657011637
+16.585758620071815
+15.512551096728217
+16.785449096114235
+14.667982528179422
+16.277901264177046
+17.151111857298858
+13.88403805416938
+14.898764344653571
+16.07567906472589
+14.821130213613415
+11.099886272773134
+16.459467969548896
+12.947880883319712
+14.479807784834534
+13.025921109958148
+13.973927735015494
+15.079519751425167
+15.916435224341654
+12.723747130177316
+16.191569423152586
+15.990828901465832
+14.202788620457824
+11.342771610452246
+14.462245486434057
+16.649635116831817
+15.681937482446017
+14.075806759453172
+15.600603397913474
+13.815617013009685
+13.398451961904513
+13.824553126090947
+16.38530303712909
+17.181655266383146
+15.873505019480916
+14.54591274236958
+14.742793323252442
+17.111870876224955
+15.297987910921663
+15.851624346771217
+13.921176100441912
+15.28693382318157
+14.731533989359022
+15.581116397738057
+15.200678018008077
+13.927894971631645
+14.056578098273505
+15.986721093351164
+16.27983659213021
+15.743911438595873
+16.320673867386787
+16.64863671503757
+13.047371196225996
+17.818787550927055
+16.24798962953662
+14.442870383741393
+13.878256823503207
+15.35062318204109
+15.81470938578589
+15.99561254891043
+15.290015795601064
+14.929651203917743
+13.724858788069426
+17.3660381277181
+16.52277368806004
+16.642658977220222
+14.764139278349617
+14.06254814149257
+15.920103086436427
+17.534377060194757
+15.8225008199462
+14.274649021273191
+12.589502010940095
+15.628011045695743
+15.946432104214992
+14.140663994605234
+14.016880015150818
+15.552288719798995
+15.899387126456162
+14.663239894550102
+14.602373980335429
+16.056436506122267
+16.373753334070713
+15.239677550353278
+14.97410799263021
+16.91370839372071
+17.854808756976823
+15.30146077832461
+14.818902009085491
+16.092245427510917
+15.19630628346998
+13.285614850437852
+14.048533815416846
+16.285430029606957
+12.81319422362337
+13.919801096332705
+15.917611990286957
+16.32339503313129
+14.218064381312331
+14.523601435555562
+15.685849073197176
+13.554012228125089
+14.312845314833922
+15.126644475317093
+15.794279641719953
+13.774170868868936
+14.269055429802606
+17.4382194685993
+16.064511645659152
+13.602402193436092
+16.12614026965332
+14.867769645789352
+14.010293471635151
+14.146080540333287
+14.527811493812138
+15.801120340330613
+13.826684133943004
+16.51598386801237
+16.185644254574072
+13.307744994144372
+14.40598482737414
+14.526396071381953
+15.06953118195787
+13.551290132184803
+13.300818197635962
+13.696475951951399
+13.73458996323275
+14.442161387741066
+13.45297082481106
+14.234484343536039
+12.223688207070282
+13.742672399029829
+12.916857708285079
+12.347374244138862
+14.489316111644555
+16.42217936531246
+13.935662668396063
+16.15931734319095
+15.711918433269716
+15.068404323962383
+15.228376721966256
+14.262642977369225
+17.606945348530715
+14.775826533766207
+16.258117197656347
+15.018995491210902
+14.01283518307335
+14.652636234403715
+16.059106438440395
+16.90524570215564
+14.397171431425221
+14.536408042500241
+13.414910898435977
+12.913044411660394
+15.902734750759649
+15.815929649168524
+13.663479495880438
+14.131828613072457
+15.218413578557247
+14.360808759120403
+11.864779590975914
+12.70417424567323
+14.13272431039239
+14.771959747180816
+13.152468327788085
+13.279231356913783
+13.148343913442972
+17.87984387871468
+16.156181465339017
+15.288178649796208
+14.859455685959588
+13.033081174142012
+14.551857472129157
+14.672063405864492
+15.023201694943467
+13.273886147523058
+14.601543924332944
+15.581510315864406
+13.290100593670289
+16.2094447340874
+12.962531056249858
+13.358634320124068
+14.808906644898471
+15.214121602791337
+12.783446419488456
+15.808572972097238
+13.803155985876927
+9.300449456694992
+13.289531485127739
+14.400922207805124
+17.25037666576948
+14.614232877265437
+15.158637425513334
+15.594675205935161
+16.391153094683517
+16.048019280248184
+15.812224085434607
+16.947233905122914
+15.902510018613285
+15.619942271695905
+14.354649494492804
+14.573694909389687
+14.920266219915462
+15.22813866839364
+15.303504269210478
+15.530626871747401
+16.587304718372224
+17.332090157699625
+15.542664716134581
+12.654240209458209
+16.212178512273496
+16.81229835784177
+13.06728673657851
+16.237261182888446
+16.06876335030306
+15.013641169502193
+17.225759125843012
+16.118410556011256
+15.82895479272463
+18.46825559866599
+16.494562740243126
+16.795422867093748
+15.22037922532813
+12.709423789425287
+15.710736814122583
+14.303049551996494
+15.579011481679998
+14.7635035910167
+12.658994380664183
+12.523591142891206
+14.583847761368887
+15.163877539841394
+17.863915895041643
+23.792485991734438
+17.035397463540292
+16.113073467516216
+15.319130567115494
+15.243244992918093
+13.790984150649365
+12.738948313046095
+15.194796677598063
+15.305821402411013
+13.797168108723625
+14.878329916153788
+16.254184381064206
+13.3696306624865
+17.526068006216548
+15.976799074843385
+12.72506679523839
+13.977598686820855
+13.74098811798767
+12.509601041988262
+14.23796216773782
+13.153412465677363
+15.00246285297139
+12.87351632738826
+12.826901264419135
+14.590968907631506
+14.132350409466838
+14.472708389464103
+15.393759176166455
+15.787432646200429
+15.5988053151723
+15.909717993324975
+17.67842025706456
+24.982697145771724
+19.82856980123924
+16.331703696311934
+13.954583040421298
+13.784913664034903
+14.971549414629905
+15.411322233791651
+15.884074454415511
+13.847342155588095
+14.64527229445018
+16.836635955830005
+13.623810564671487
+13.38478311257559
+16.64738331360553
+15.92792816401844
+13.99893091639909
+14.248385860779692
+13.188908315320589
+14.684493118149888
+16.2773120887757
+15.408054537513237
+16.241386471856714
+14.523169930656692
+14.738574229806915
+15.857373288928883
+14.828339845511692
+14.329380017988882
+12.771596132081342
+13.232335882097075
+15.521541023752619
+16.47129073618757
+15.696985329727767
+14.371935177423708
+15.897067404179822
+14.957476638162092
+15.913552710926297
+12.961656382925938
+14.717036433006967
+17.304109636329812
+15.2467151832073
+16.012541736128867
+15.396875151300165
+15.8358396273766
+15.902848437458502
+15.927952013699212
+14.954518765542716
+15.728342993026061
+15.120016051717514
+15.721088998677075
+13.406670969447205
+14.547294102089268
+15.699606076510179
+16.66774146473928
+15.557530242417485
+14.756709492813087
+13.78167906926511
+13.590553840201025
+12.196871319089468
+13.72899413446278
+12.664177151228841
+13.102370489851111
+15.122845333024244
+17.45574501890559
+15.672698659246151
+16.026172472179994
+15.563790885175564
+13.814160973804448
+16.926895074007447
+16.19297080781398
+12.379197641707805
+15.063555828756236
+17.106889544271453
+14.310393162813128
+15.459048710474136
+15.714272616486241
+13.9792499526706
+14.52573252177281
+14.91416751847487
+13.261093100163961
+15.426836415449955
+16.395578763722696
+17.91166542430919
+14.999632642924851
+15.523171192839968
+14.479459685879746
+14.48471388042573
+16.293304304364796
+17.109542572644997
+15.558772835558372
+12.486498110812178
+15.360408225289817
+15.229022332492093
+14.718375524379823
+17.369517696032148
+17.27898046688732
+14.349773191834515
+12.984908495788758
+15.987034750168945
+15.268991320605764
+15.801673720524533
+16.398031012044115
+16.34852571220972
+14.732869593504674
+15.399860148698536
+13.281135608014907
+13.854172658483037
+15.14248723987113
+15.602236082946021
+13.847509690154567
+13.761985283866508
+14.296698561466997
+15.825003043260438
+14.970039536472896
+16.21034401576742
+15.72519549043946
+15.965014058759138
+14.09433372468665
+15.494960460082197
+17.313172911184907
+15.861822772284924
+16.72201650304011
+15.178730330172343
+14.844845524548845
+13.899905684211788
+17.513362211612815
+16.717857914725684
+14.596493359706685
+15.024652387426258
+13.96458303117248
+13.767737184973313
+14.42407669271941
+13.63287110431817
+16.871850924797016
+16.636113063988276
+15.96641123282403
+15.857347034829886
+15.092588219359996
+12.542630942842521
+13.901469310213926
+15.110062988438855
+15.239246723977104
+15.644145296864949
+15.72424219065853
+17.008382696435106
+13.89972300614754
+15.052356557943497
+14.114669457758694
+16.168065064008218
+14.380909641527921
+12.968565509240236
+12.481990487095999
+15.12510103190776
+14.92504489018917
+16.37856425151338
+15.726747043212725
+15.72087479683367
+13.717456820907543
+14.066569673140961
+14.640409756551023
+12.596769875732448
+13.703840485562054
+13.078259056714458
+16.869789276769765
+16.756504956753943
+16.9168731881867
+15.929653577913342
+14.057431336959482
+14.834658823719778
+15.325079552805846
+15.448519902998456
+15.44505774375736
+13.255478988293703
+11.504085799348019
+12.58083141830015
+12.734150122651059
+13.948739875175661
+13.81410801179554
+13.913098281935234
+18.935959536556012
+14.083927719753248
+14.887268768350665
+12.800838510120471
+14.859008084036802
+15.37498146342638
+13.592301692953157
+15.46668506645419
+14.513569371402227
+13.179396270513408
+13.788386127553153
+17.946431175321734
+16.5820594331405
+18.566104719900494
+16.11547921239638
+15.496956879999786
+14.995997861032848
+15.37173900805979
+15.160334162233525
+12.688745645549332
+16.93186658373854
+14.740219510549835
+17.097927894216113
+15.367384065684703
+16.061356883792214
+14.74077707748198
+16.95639865761906
+16.383228000586655
+14.989959544323284
+14.484954691978501
+14.90527301827693
+15.889460638670897
+13.960316926646627
+14.957147102198107
+12.939548119448773
+12.785803440237004
+14.188015806898804
+13.024780032074503
+13.030646977407642
+15.499273542443234
+14.849686854821442
+13.511707953354744
+15.51680054760331
+14.870342384162996
+15.23921500790911
+16.09311246400911
+14.526524230130349
+16.26255516034219
+14.694009791939052
+11.107419147371857
+11.616429337580271
+15.433093859068293
+15.677953963846662
+15.370386738219182
+15.816759973512163
+14.657107133125166
+12.879982916575514
+12.238550887245964
+13.131670959431958
+15.379156578688807
+15.578873617355427
+16.481259061249503
+15.107718850444485
+16.56979265406747
+15.553322469406154
+15.197036246317865
+15.21613435303584
+12.600889994916855
+13.985121065438463
+17.085591286773948
+16.317724980379396
+14.71626792799178
+13.685695740368615
+13.390881579116254
+14.78186353666878
+13.520715173913771
+15.299404939934064
+15.325052009455135
+15.226893658819805
+15.167354600359587
+14.454252608879514
+15.782495741082386
+15.873896849918196
+15.982032714872275
+13.410932302445673
+12.375169607421554
+15.176997013405881
+16.190924637067653
+17.749839594991315
+17.96273589397086
+16.825129497390392
+15.48668722288042
+17.48827040569836
+14.050979429384313
+14.887236883197062
+16.480904280931256
+17.10189169608519
+17.058291284185543
+13.844880073683669
+18.08852743784975
+14.420804484530024
+12.445370584513412
+13.78269888958171
+13.175106909235055
+14.22382806125978
+16.492452944880725
+15.750273907896442
+16.72911673511986
+15.690567953957867
+14.716805241035829
+15.808816928854625
+13.512081492822688
+14.824504192643602
+15.59075929995582
+13.937901043459533
+13.862590713507998
+15.009170315405825
+14.93827041592597
+14.657721249383982
+14.281389036704795
+13.44166907930152
+17.09917115100083
+14.26850124057961
+14.945186646934232
+14.325881574061285
+13.511676581272354
+15.987862955446133
+16.78802839109224
+15.427479103322298
+13.391353990368842
+13.684097181920094
+13.592329118672993
+14.186068615048256
+14.437059600237063
+14.878830301611686
+14.433677181136503
+15.39533456395786
+15.603741291356386
+15.335062670199122
+14.47784882498081
+12.813046935092913
+14.65894052263748
+15.300022167352623
+16.7407469940686
+15.954002604478958
+13.506236629387487
+13.836035121864072
+16.952348114191253
+15.129605369464642
+14.812095656161816
+13.819850228015909
+12.21081996723754
+13.031020167656024
+13.297507158250696
+13.968098053020967
+14.500610400005783
+11.601687728935545
+12.667492565507828
+14.590572397841058
+14.308226655541802
+13.25916771086736
+13.82288280097238
+15.298327145471319
+14.733520170559544
+13.966342374010523
+14.913846603079278
+13.171885806796965
+14.852441497545414
+15.979826488574574
+17.1148494934542
+16.219780390502294
+15.586729072371398
+15.619625157934749
+15.806013431429292
+14.752716823174879
+12.096562006744733
+16.259679423003902
+15.657518330910491
+15.998058364727314
+15.754640795293838
+11.288531057283407
+12.120423420928262
+16.107477049091116
+15.972813894314285
+15.782209545034704
+15.709415515422535
+15.49084300709363
+14.76483479990489
+13.234672015090766
+16.05175592882118
+13.004143647192521
+13.798862408044585
+15.779036199398078
+14.920785141949708
+14.99705027322348
+15.25614824312126
+13.64575531153504
+13.915444989810098
+14.34750087799847
+15.724293314833304
+14.796535672523248
+14.456635384764525
+14.435709508522976
+15.280353035408382
+16.446160680094835
+14.899832932139574
+13.655806177089545
+13.17215319489155
+15.002278790704352
+14.781546002603676
+14.789802803500635
+16.20480828305992
+12.000131457582299
+12.162201940762642
+13.742801139897622
+14.55861045573134
+15.894250248163829
+15.777616404057412
+13.28211455534283
+13.882850165021765
+14.571908800711014
+15.399171344806334
+15.479495139003205
+14.026248211470701
+14.312242857281348
+14.091637763316484
+15.868627525044545
+13.793142032736483
+11.146510368025403
+13.131206514434709
+12.826400760783926
+14.779258882052787
+15.627359409810381
+16.122769911259397
+15.539883939289467
+14.709580758329537
+13.898926082549522
+15.3888289218784
+15.824830506220266
+14.413457650289033
+12.762607459356374
+14.835544573707864
+15.898353272824124
+14.896055806715921
+13.798833933295455
+16.19861398326421
+17.210291467848677
+14.145946390902722
+15.340358159985286
+16.759249670359438
+13.269201788247216
+15.409434641595894
+15.274761180567722
+13.85109869491923
+14.364930726363966
+13.135029669766965
+14.903412054251149
+13.705466949387926
+14.37611652429024
+15.133801310799342
+15.724686638481487
+14.207962141389032
+14.716788818049011
+14.888582388282757
+15.61263134491658
+15.622461897315944
+13.786017673391584
+13.688617676922618
+14.395429098534365
+13.707230926585893
+14.319267202442134
+15.807781496078107
+16.326889559349667
+16.46409743915035
+14.044706099589163
+16.053727983046954
+16.751303552316173
+15.183757179167728
+12.502258274632155
+13.463907924100639
+15.137558150345342
+16.2434401218204
+15.07738565425906
+16.780905619030122
+14.41584214307251
+15.189690982765953
+15.280093990397134
+12.778349430351327
+14.85281793824339
+14.884945788706077
+16.097898111365993
+16.542839581021596
+15.686598661370596
+13.952496406026285
+15.556607314875066
+16.72184985777183
+14.887366496437252
+15.893951138810252
+14.185474342107199
+15.969812171669318
+18.430350090629318
+15.944655018100462
+14.162631142638105
+13.156196440475227
+13.272927275161905
+13.579270969212416
+13.051308120407597
+13.028121643131797
+14.108224656520306
+15.426462823107897
+15.271355395441091
+15.631466546062668
+14.919776836269548
+13.574619282445681
+15.010022704915457
+15.544859321112867
+15.87983777532584
+15.53738413565948
+16.54055015976138
+14.659500779206255
+15.570148391768
+11.469723145984588
+13.984596311740475
+13.542788064815042
+16.280976461055445
+16.095300851272597
+16.51740276138412
+16.396776952889823
+15.255602071665393
+15.668310636420088
+15.324526406632373
+14.97576558651626
+13.349317040016103
+15.156900311332876
+15.04030469066025
+14.658050898315395
+13.585249139780487
+11.91399056152052
+14.516305581472679
+14.838919563657655
+15.297189855977862
+16.863860936854465
+15.10335298634213
+14.277989222131993
+13.506748627013437
+15.469486491550597
+15.95649496659992
+14.53353745673816
+11.848182622749434
+15.011571948342919
+15.537413308037515
+14.366332854238237
+15.822295538206802
+16.654418302357698
+15.16387834910006
+13.888282410639817
+15.606763674309732
+16.098917225425325
+14.686984423464693
+14.317475742108428
+14.164954757711072
+13.888343520010096
+17.955575886375826
+17.24590207305745
+15.366594469880084
+14.788848848519052
+15.036428044011302
+15.148360008194771
+14.846680628131182
+14.895406232468673
+14.610821931458716
+16.05139916580545
+14.882021564439754
+14.01473371916336
+16.118411856469805
+17.184712232209563
+15.520789961279363
+12.813588817207034
+15.374119361280279
+15.180539928584338
+13.262665512068196
+13.934803948541713
+16.336011410910785
+15.903912171428303
+16.93238003645547
+14.360919908334964
+13.948844904335658
+14.569041087361214
+16.609769334802337
+17.350962992475644
+15.177173244545557
+14.336777067078643
+14.911670526320947
+13.789914044790876
+16.92272864773203
+17.070629003610563
+16.637279619044605
+15.66594194747428
+18.401061526294328
+15.437534406974635
+17.691034924956284
+16.622069326778387
+17.532832651445645
+16.42080203584571
+13.369453193084368
+14.18139704929331
+15.220258078314686
+14.984620492634775
+13.938699924060856
+16.089501432315117
+17.061234471141375
+16.377198772354234
+14.685389891676465
+16.558675548444924
+17.580641967024476
+16.021919348233737
+16.580721360209168
+15.525214192172967
+12.928557073040253
+13.58431149955021
+15.319524746359008
+14.592443983822719
+16.66353537377239
+15.822898874495266
+16.49926740975947
+14.883180535902952
+16.37604764135419
+15.776689846041975
+15.380805876536371
+16.81878698732403
+15.806613761279507
+16.064871310352956
+18.170496252445517
+16.195550542888796
+13.408583630011606
+12.880737762788357
+14.064249996653615
+14.178184192122316
+13.930440067431434
+13.778126827559603
+15.469474518357217
+15.936993528565438
+13.879454887881039
+13.570653059632193
+15.516022436932971
+12.862765184697295
+15.168749285494712
+15.840331849845612
+14.496660961487223
+12.01283179153593
+13.981604452994773
+11.35197332706774
+14.64957689832569
+14.86389996251566
+14.77386073543984
+14.783318310785646
+15.207827374252886
+13.871389962682926
+15.132778860597554
+14.355039121452037
+15.912449557560919
+15.375566089531674
+14.764448436174987
+14.243656837451269
+14.318336690772881
+14.936960872780077
+15.905743872283082
+13.918959797579006
+15.27304160880523
+16.316768487812098
+12.107697691069461
+15.229017894113184
+16.629188975550093
+16.16181562730476
+15.012760784497033
+15.341397734063762
+16.588638021910057
+14.635457795487397
+14.104029950774319
+14.58055813593215
+15.789898781562883
+14.662491106051249
+13.942688623700988
+15.713501396500746
+18.2895810910193
+16.404304935065696
+13.98885234119274
+13.08180138421865
+15.958325910554052
+15.615045770331008
+16.161756193125626
+15.210449620363661
+16.362511812295537
+15.967396584791373
+13.358865918908478
+13.546788052657192
+16.490873289412704
+17.245829633363783
+15.154968605904287
+14.987628603517678
+15.346437756723432
+15.808346862309222
+16.671752293662266
+17.37451626821597
+16.692075775251197
+16.24278768111482
+15.27629976663762
+14.915834709811833
+17.313261993599525
+17.111798439271908
+14.506143510000243
+16.468455069180308
+16.90151156784549
+15.588843454092327
+15.636770080320602
+15.12397742630425
+12.807343759169697
+14.296761354174109
+15.561123583321418
+14.472004988875256
+15.370646774660074
+14.898463184479724
+17.14832479798598
+14.816246027973918
+17.28709541919808
+16.043283497799337
+15.764830952368285
+14.41996137332633
+15.453254753253248
+12.726263901035793
+15.022016464476977
+15.064303808342743
+15.819182211695662
+17.7689759065767
+14.922243913889787
+16.361353582375344
+17.552429637761946
+14.367735590536157
+14.66233154411269
+14.77876474884495
+13.062590354992935
+16.501199253844234
+17.034799800757384
+14.236805515951929
+14.299258765040207
+13.310179183936981
+14.60492662362553
+17.19174517140631
+17.038819240540448
+15.356065292750287
+17.245343710763237
+14.401866112370215
+15.152679008796227
+14.169073053855172
+14.428063639503861
+15.862625636525664
+15.986609975673375
+12.854657652293739
+15.766386828822021
+16.61093479384533
+16.406674162468462
+16.888927477459163
+18.314104752873135
+15.500783571486565
+17.118192544440248
+13.585717197957521
+15.458869449477547
+14.76823080474901
+15.940551457200328
+15.580150689802792
+13.803865035488485
+12.428052103677217
+14.515105337896486
+15.854815632787208
+14.671480448438246
+12.989214621381109
+15.081220838841375
+16.360841326548766
+13.674917186063169
+14.82252155283959
+14.092968938183333
+12.811462797650876
+11.652854824139965
+14.877351645688464
+16.005347322212103
+15.178124511300126
+15.907415039659824
+13.754711442712548
+15.087398332917417
+14.366358432771833
+12.783918913481557
+15.658065795341784
+17.08328343428441
+15.624745220474452
+20.459247221113017
+15.28284853731661
+17.362013847355485
+16.07683336406444
+14.305380235974269
+13.919937869833262
+15.985340712275288
+17.22550046678468
+15.35231914928137
+13.532506758866958
+15.927628101685656
+16.084481464389782
+14.342903776698321
+15.473261483430164
+15.599074789030666
+15.051001570300997
+14.488084780963163
+15.76858781314344
+14.058843266681365
+14.724349070252273
+13.972873261356355
+16.08198530066666
+15.059012537319688
+11.98607731358166
+15.683385109847308
+15.60244167809806
+12.920396685068923
+14.697764723618988
+15.329307051195585
+15.984661367343165
+15.07006277396566
+15.693012295869693
+13.847725445054053
+14.621069684080325
+13.355684807287034
+14.571124992638218
+13.391322579080722
+14.248102149201529
+15.62116263567647
+15.377070290887943
+17.470002659816558
+15.468847293435871
+14.432444381279097
+14.217046555721112
+15.162066747496894
+14.769962130221515
+15.412451256192185
+15.446867787833085
+16.49015507741335
+15.38188661856482
+16.19978004189221
+15.858646773274643
+16.49164029278046
+16.761555309732515
+16.3682503018822
+15.49059369478131
+14.97879572721915
+14.63638864217998
+15.993314935669375
+12.423152091754645
+14.938318824336065
+16.125500716784373
+14.003183403333438
+15.042235854265769
+15.060765589426765
+15.97852749677817
+14.90176290258276
+16.277338850312944
+16.611409042829294
+15.486349658465429
+14.52930457834539
+15.821293587684195
+14.864231982238024
+15.7360864913595
+13.741945581047162
+15.591681850552106
+13.79278669529647
+16.974640803309995
+16.540046078899522
+16.373666003658926
+14.29995875281061
+16.421620065194375
+15.804074074656143
+14.240697962767499
+14.947900889599467
+14.76628552811168
+15.042721322028058
+16.474557711032006
+15.2016503780942
+15.628981797416557
+15.01375785188388
+14.438662752406898
+13.619688549062303
+16.77616840852059
+16.23344925261108
+15.770186269888754
+16.098811773279053
+16.33713047063671
+14.84028081536195
+15.767369743239371
+16.970650128530437
+16.479147610659766
+15.865165157490736
+15.211617760045968
+15.564031963267055
+15.049049196607214
+16.939211766005116
+15.827727894121296
+16.24354428989865
+15.570564762898968
+14.92819558843405
+13.617036837581125
+13.264945633807159
+13.460490342089713
+15.672990156180248
+15.180197115976995
+15.023054288003237
+15.777452298269893
+16.36286199576854
+15.90868393231699
+14.507106163221266
+15.059164434294388
+14.145214490452773
+13.53653519397389
+14.792640740289485
+15.120860182890837
+13.119471174790647
+12.604637509427121
+14.472489221313054
+13.458907871852759
+15.281297386116648
+14.499295344863157
+13.87678848713064
+15.370622428007849
+17.53177944936006
+17.965494337690345
+14.849795270877607
+13.909120316470009
+15.919606325753037
+16.44629950149536
+15.608473654648193
+15.230717640969786
+16.16574854434323
+15.31529406227176
+16.995672116255832
+15.533743117645784
+14.950607270554144
+14.716986805269045
+12.426275643640679
+13.4077030655845
+13.74482144592848
+16.070883023250246
+14.505320525335392
+15.749020732286667
+15.965092315909075
+19.02622082769294
+15.676162218728521
+16.12456183013164
+14.68635901658861
+15.449983769959417
+15.556321976908308
+13.221488013390186
+15.305058254455659
+14.978642117429061
+15.888303331566235
+14.97569032546025
+14.581528905593828
+15.123384737836687
+14.579090119636007
+15.022162910920613
+15.215586300945787
+13.201093732425548
+15.495049359224637
+14.268037561243432
+14.151589538129016
+16.27687148268285
+15.009262027280016
+14.556860812861231
+15.340364109979575
+14.279351032489373
+14.835920261744405
+12.917164561924281
+14.902206476206317
+14.360481321306807
+11.516946244235982
+14.144590393598804
+14.289328128176749
+15.790747367294713
+13.352356702833717
+14.887860015835017
+14.436523309846606
+15.399067417911922
+16.718394674612085
+14.116044796552202
+16.09853644096603
+15.49069480264474
+15.393159351716292
+14.79914361873341
+14.785214033905945
+16.515941940496987
+16.460050273674042
+16.61869987460932
+15.932202915920513
+14.524369070725484
+17.44303237740928
+15.932985503425442
+11.749718147083328
+14.121735465558501
+16.43147986648796
+17.22575652922032
+14.57764982524074
+14.844022887303893
+14.525859697968045
+17.056212051730455
+17.025745679909548
+15.056516092919694
+16.437421343832597
+15.60143674513725
+14.351168461035869
+13.313710884995274
+12.840710569727605
+15.310482002298897
+15.218124732346112
+14.093781814715541
+14.054305584937183
+15.576510200547673
+15.781026449865692
+13.529979247911356
+15.464233615060053
+16.573958138187095
+15.395599966052245
+13.22271415274109
+15.365353900549792
+15.597289666296064
+14.321818068247069
+14.55942323591718
+14.195395343976102
+16.06794747193915
+15.192551697647474
+15.977526029114344
+15.94324163233108
+15.37060943437767
+15.167345608915468
+15.854821426392093
+15.890408038221778
+15.014261873339166
+13.199313543747465
+14.568079767318096
+15.271254047648227
+14.62278899335233
+15.237177892906246
+16.339232164859794
+14.132652569186163
+14.225955124905298
+16.208835908257797
+16.745774602689025
+16.11900332356865
+14.266995497905185
+16.403165841998486
+16.09824922092328
+15.334866348243239
+14.458820101798565
+14.323541600684038
+13.852377203226126
+14.809156460421704
+15.119279615880387
+13.46936985550606
+13.863978602135603
+15.644538406847644
+14.52336658854432
+16.539706684177673
+14.818587954658739
+13.575206593710831
+13.622015846040554
+16.422780922790835
+15.841700126558862
+14.964628519281405
+16.89132055494322
+16.164126833851114
+17.17259855888456
+14.915887447241886
+14.871876771806427
+16.427834188940764
+16.59273118182189
+15.444578873356775
+15.813424716097217
+15.800412578785199
+15.722904688796191
+16.923083965002988
+14.84923230792893
+15.451071309330189
+17.095502710609182
+14.495196759330298
+17.459808723423535
+17.05903119383379
+15.257930580391431
+14.727450354904775
+14.90849525798619
+15.324757943155262
+15.198800030901552
+14.124745514560544
+13.307036788825556
+14.78119688220869
+14.952107533255415
+15.265327806613897
+16.610530786923192
+14.296939142372551
+14.006245800531872
+16.43189464248549
+14.254016727000334
+14.236765482418122
+15.020702308122296
+15.758379348574167
+15.029037625059928
+15.009677751308288
+16.275207038868004
+17.06940967199442
+12.56098617080525
+13.73240461704178
+14.070024707524937
+14.675298963708826
+15.926232523721112
+17.857706106431905
+16.445025395724954
+15.70516013973922
+14.765264815021496
+12.59496620501423
+16.347104381410176
+15.655742956155592
+13.748986906810714
+12.727664528941276
+13.093198145433476
+15.902523692709494
+13.762679494365642
+13.82552399095836
+14.538783698838856
+15.676193034388362
+14.532652560957061
+15.246373659176768
+15.000939550796815
+16.356668560285115
+14.654826687029995
+14.84027817089509
+16.06617230694728
+15.50495746313699
+16.62039106031662
+14.267972600542535
+16.14760280612363
+15.162607046337655
+15.876227559054925
+14.19373633130617
+14.742657846137206
+14.03354936021104
+14.449756083761926
+15.894294452270074
+15.558724121644659
+15.587452717589997
+16.245118652067816
+14.514203915394631
+13.826134631792897
+16.130835645023723
+15.681393913884918
+15.899501436246666
+16.847670376178087
+13.738817212687096
+14.232520369377227
+14.697546094522153
+13.409860749834252
+14.782675765381939
+14.274722135619527
+14.703545377229048
+16.141033706326738
+14.639720744180437
+14.215839712849444
+12.829617409163063
+13.869130465193408
+16.093333594808158
+15.149994205966252
+16.08981944606083
+16.254720373855207
+15.41961158184175
+16.785889113057493
+17.718192127922734
+16.011193957862957
+14.108149726885756
+14.088390247905963
+14.478488709709623
+16.346507653725894
+14.658202613246516
+15.37364216727154
+13.65203241801757
+13.73215023981119
+16.17075883983898
+16.462918603280357
+17.33194062429125
+16.624482345951094
+16.569799598841087
+16.591682952531173
+15.32082526871686
+15.711121919676401
+16.18182243845459
+17.454330037106317
+16.555670202678925
+13.872859324955073
+17.426757252719696
+15.886887338492826
+12.90778097289406
+13.454098900896824
+14.755555630771084
+16.792490710193945
+15.701117260150951
+15.593315444378774
+15.693856265551744
+15.195716254308522
+14.652952199298554
+15.325441770897541
+13.722655891477359
+16.694590279093447
+15.825582189885367
+13.953565653896902
+14.890403229253167
+14.840059622327473
+13.556477551043471
+15.46384150666168
+14.94467667779351
+13.319913904823508
+14.684593454179819
+17.037437379389416
+16.457164631105726
+16.5376021715319
+17.044052771377537
+14.751985084565845
+15.320728962403365
+16.08200104080595
+15.21128764360239
+14.602720524956183
+14.676846750171961
+14.15974680360263
+15.751881750898391
+17.140044577026927
+15.00318348179347
+15.094057335335037
+14.22007850620912
+14.740856803227501
+14.239376650699782
+16.047504658412407
+14.773577211327861
+14.48828712692675
+15.515725715508708
+15.788384526278548
+15.439196072379602
+15.621628634452094
+14.844469963942657
+15.412700457030908
+17.433137100994216
+15.897760208596466
+14.3696248560491
+13.725817342901209
+13.81945664008812
+15.315100232685083
+15.01259988664691
+16.98638084174452
+16.006384103653758
+15.170870093270054
+15.282454158110411
+14.67747534664042
+15.287592484167007
+14.207302263963697
+14.943689666547343
+17.934398827552656
+16.34032708268218
+14.441783798043247
+15.53596439606892
+15.557466698909906
+15.475243736936235
+17.135925451555394
+16.012600987379003
+17.054677705798582
+15.308358489503604
+15.648962185737517
+15.5756623467053
+16.185984313454085
+16.346193303011873
+14.980438255410277
+16.009710288741474
+14.832073100878162
+14.96118803218964
+15.539739768856066
+15.507439228964174
+16.299468146912517
+15.349438962718594
+15.592929426253946
+16.01668446599956
+15.491259623082385
+16.395075033358196
+17.011354486179187
+15.03082335446102
+14.927595896463316
+16.356073913419024
+13.402261938258519
+11.496904155547355
+14.289151512681855
+14.828534049252838
+14.485633161848753
+15.833332372919358
+15.78571724657364
+16.9761114639186
+15.323577221064667
+15.877202112911348
+14.718187357894251
+15.19978709303912
+17.246151824490155
+15.607887461699065
+16.75209409699859
+14.780397957760883
+13.333816519876407
+13.115751064730759
+13.35030745261497
+15.376727928327085
+14.592030638921614
+14.068429713571689
+13.36764332050852
+14.218523682680924
+15.236536897367372
+15.379799271171052
+14.095897745373861
+13.812398777229689
+15.526122894259217
+16.567057049217112
+16.343298319209467
+14.876265369069728
+14.345183342575723
+15.926820765182356
+14.858491303938834
+16.098522989356624
+17.053210372234233
+15.097345034311374
+15.21231982676666
+15.50879855598869
+14.243565033683822
+13.509419221477259
+15.989943214696112
+17.334512740648194
+16.590080319833305
+16.75533987794111
+14.820503712431531
+14.272828187454166
+15.499144619388503
+15.398525888212177
+16.149180982132094
+14.944387420096064
+14.45688256051885
+14.945842563229334
+16.309232857270658
+15.70742400343947
+16.517745838793928
+14.564190030233547
+13.523223786757342
+12.43841538783525
+14.445437185444149
+15.918406693429205
+15.96315497016765
+15.398895126573962
+14.299806137478498
+14.35618054013888
+15.243873467968825
+15.545282169098584
+16.470434414625302
+15.214871564282575
+17.342499140909993
+17.22050386689402
+14.344690278401501
+16.49904489046982
+14.728208446119211
+15.536991067687467
+15.863499955100451
+15.485000153130287
+16.81024605450841
+16.76804835385174
+16.014274454822086
+15.530318736560432
+14.614433197830763
+14.326400334033423
+14.806076735121437
+12.923901203511363
+15.979478000143445
+13.752261191667742
+14.347124469978922
+16.213174017699473
+15.254101820469458
+15.217636589753852
+15.86764799541163
+16.038618127662048
+14.63773374895068
+17.308495121967752
+15.069845621660917
+13.174583145736008
+15.765777305731845
+15.078206198183622
+15.513196361646052
+15.783783022119778
+14.55730418437578
+14.929536950236653
+14.678598379712199
+16.16656538864875
+14.530846009288865
+13.688260842001654
+16.857688672956712
+17.06819826632878
+15.182922570979244
+17.53569666420333
+16.379918763332952
+15.75680768603084
+15.595701004632062
+14.938845490819133
+14.48569355153576
+14.876927810873966
+16.23138240448185
+14.839684303898068
+15.075208517708845
+14.964882014401567
+16.53051465692107
+15.11480733573687
+12.621273797424138
+16.30559620720608
+14.075719667102206
+13.87732397762369
+14.927714283376858
+15.786022147313773
+15.922245893284085
+16.35245601410635
+15.421173390091866
+14.487664844684048
+14.018334574059011
+15.406031872910447
+14.931317169448803
+16.40398910934759
+16.16659671484929
+15.831927062937723
+15.523583569515822
+16.00571988783996
+15.270380987619731
+17.538460777211768
+16.941947351839488
+15.195652883075141
+14.640645201358765
+13.577422872413322
+15.108240871793797
+14.256973023723901
+15.973529199771278
+15.82291342279241
+15.036401178836073
+13.166794036983205
+14.159820748803938
+13.01147780757482
+14.54735162361267
+15.523684906197914
+14.77889205522952
+15.342962183325426
+13.836624619428406
+16.509881857824382
+16.313800306611896
+16.795420116569247
+14.136235857303788
+13.55077339587389
+15.814886440753753
+17.247387221371667
+15.856856111770057
+14.921461924074293
+14.114353432105688
+14.387144162808866
+13.927621440426194
+15.724962750683048
+16.193156506512025
+16.94675015523356
+14.857974812689562
+14.933246004198011
+14.655691260082406
+15.190009941053177
+15.908173672234994
+16.93437795876703
+17.6994563739306
+15.77191368381149
+14.218068720619485
+12.119785730523773
+13.720397433363502
+14.121234698885232
+15.083116796273927
+16.289324040456037
+14.514244160981562
+16.24475567334612
+13.983013632921782
+16.389343419943984
+17.041855901190146
+15.05652821317048
+16.00415720859384
+15.108506954153967
+15.692480169532232
+15.964902280218084
+16.986172753087473
+17.344351876006428
+16.065972361394742
+14.357754996502607
+15.167539928047205
+14.249850623452218
+16.032334901208003
+16.35143550502049
+14.779357939205639
+14.184614075847932
+14.426274200514058
+14.78806210325736
+14.406869640974307
+14.350551059768279
+16.451782806866632
+16.621253546683306
+16.536598285944606
+15.896533080543477
+16.653427971600237
+16.589211637768955
+14.804937209039323
+13.56095673615512
+13.401149074353455
+13.937592275920437
+13.46898333535323
+15.65321702437764
+15.956190134116056
+14.736713928744265
+12.400770456178222
+16.39167400506203
+14.715184597956664
+15.823786554217776
+14.02058560309591
+14.050370221602918
+15.026255688801697
+15.133751281250966
+14.838699881316586
+16.544625141601855
+15.3319433211243
+15.421430980098492
+14.3089014528923
+15.750086945240412
+14.658020014938714
+14.27717496921096
+14.288147090120233
+14.092036887290078
+16.59047572191467
+14.723694487406362
+14.140237283615178
+13.023850440843319
+12.775302120828485
+14.614689910260097
+16.438288669757355
+17.18588320009418
+15.219940265977229
+16.188907391015405
+15.381538568902954
+16.163573036205577
+14.980353529990325
+14.750897819488742
+15.669807616339398
+14.696519737788392
+12.9571714280155
+16.018932843270804
+15.256587571576844
+15.349560371535247
+14.717756732443803
+15.952867868128493
+14.962371667269409
+14.778495147824472
+16.107261125783495
+14.512555330137658
+14.479997735047306
+16.003324189455938
+13.416054895724514
+15.123930195826901
+16.01550527615686
+14.053881742787766
+14.759561296858024
+16.601785193878115
+15.952080347666751
+16.575163564918668
+16.315089809734417
+16.528463769882052
+15.584521408321152
+15.044359370294515
+16.208580762574584
+17.68324713085643
+17.592114466796843
+15.392885947773735
+16.302305099250432
+16.100759279832815
+16.179517192680706
+13.59150359265719
+17.572106904470104
+16.265341088615628
+14.223467317224006
+16.308213832890985
+15.724409513603419
+14.52724895415669
+14.750150418367738
+14.538018153795619
+14.333512107733767
+15.694665191633405
+16.913199675543623
+15.27158391206676
+13.789713884763415
+14.539841006204043
+15.06235643586892
+15.246959046297334
+15.52426378446441
+17.05284983781422
+16.568808560797365
+15.15383946461256
+16.753076431035325
+15.778220079050342
+16.473719340284887
+15.691781162848145
+15.467712318700308
+15.245730084237195
+15.272410779317724
+16.467007104213423
+15.940781700372213
+15.727258520991214
+15.047530192727905
+15.369517741032482
+15.766890151612316
+16.959510985680993
+15.078490865126327
+14.565670288700304
+15.193683484023666
+17.434632776097743
+14.722477554616475
+14.490955007664795
+15.10162383063657
+14.643120529974397
+17.200044494804573
+15.113286185511654
+15.156109853343636
+15.585523910969215
+16.469876627585478
+15.223205957867066
+14.778862331087197
+14.057277244001327
+14.476103210525082
+15.712593396165317
+15.393289784954334
+15.404402213564751
+15.508641869394651
+14.938710180984671
+16.41214043056432
+15.66555499506461
+16.305263289406
+15.403668785016592
+14.954676639118588
+14.609036898911043
+15.422469447685216
+16.027688910565757
+16.37504334420177
+15.629355135122424
+14.232286177914062
+13.973042427331407
+15.689482906084365
+15.262806866585777
+15.508682791433742
+17.512630760575462
+17.24795010762341
+16.26199044278613
+15.335335826748818
+14.398360491442205
+13.315323394532598
+14.628309621696971
+16.21147382543377
+15.416857407799128
+16.522962805455492
+17.090906641547917
+16.326591244168938
+15.95733672588544
+16.62299566147155
+16.36571152852669
+13.979835387272658
+14.648570940978644
+16.574476582585305
+16.362597515947613
+15.301658041444853
+15.279201892950695
+15.070985115933027
+15.504663861347694
+13.973294711626835
+15.163393762442311
+15.615562586879633
+16.455022229510533
+17.142829819170103
+16.680044902081235
+15.412358833987597
+15.349027113427113
+15.54662364148129
+14.73690109013637
+16.219438631409403
+17.459397227680753
+16.258155666888157
+15.53187751586053
+15.124081486228803
+14.272234525118833
+15.314231454403469
+15.531982088171787
+16.352038373926206
+14.371486168560551
+15.144112568191886
+15.592947842820976
+15.199936473956186
+18.091009660538006
+17.81924457033078
+17.0773951461381
+16.681811242962695
+17.270502139020095
+17.18135651812237
+17.037919047162376
+14.513647671619196
+14.927083292741415
+13.793550695238778
+13.36119033625721
+15.931261155948548
+15.891487153907107
+15.714475640835474
+15.236201964721644
+14.999653474827525
+16.071734370092145
+17.63347577839086
+16.080950401608234
+15.675464648089545
+16.325940373656394
+15.597491949071028
+15.612211625978091
+15.105262539893118
+15.504674595470789
+15.691210844896531
+15.906405777141018
+14.66961438743705
+16.59971062240217
+15.623234786402705
+16.809395717289064
+15.412489026567528
+14.619342170521392
+13.423541275743716
+13.866667749206101
+15.2267647633291
+13.447028627259826
+15.451092827048384
+16.623099281838407
+16.00813665242562
+17.490496019984363
+17.88814561820901
+16.81237232774727
+15.277269628196564
+14.39968077271152
+13.842761227150646
+14.97183841638686
+12.558226064540662
+13.912200286692922
+18.34863306177668
+15.145883215987794
+13.920775255317338
+17.087252874361482
+19.295272114912024
+18.253007135668753
+16.41099380210038
+17.887806880171
+13.937000476668189
+15.384965062846433
+15.410263101773253
+14.23037181535905
+14.90232862462517
+13.590175851921217
+14.950689211579103
+14.764601275374488
+15.591499425556137
+16.172211212698173
+14.359851379688322
+14.04242526962662
+13.558315202075022
+17.1054548193907
+17.60045987857444
+15.447929672599983
+16.50430320805522
+17.50338467274716
+16.509221106696515
+18.945437294088094
+16.134888524380315
+14.859923750341679
+14.494527088739744
+14.748450795396536
+13.230328114451808
+15.801876993591307
+15.327036555119761
+16.084594015531835
+16.484706222756586
+16.245652846493215
+13.388059076153539
+15.886429347125016
+17.099028852857828
+17.979308340254846
+17.33764366700261
+17.65006603470654
+13.989744870803762
+15.865411150435548
+14.697797547990064
+15.429763294224514
+14.628130084713561
+16.05862885023879
+16.303962264603044
+18.294660141693626
+17.261445782093446
+16.056111065104275
+13.026692669824058
+14.457400028607495
+15.566533665124126
+16.009476859147085
+15.380846959401538
+15.388214844821889
+16.62481454991095
+15.934016983913025
+13.561399918807382
+14.71264809651764
+16.51328163024985
+16.018375161309137
+15.805436689214943
+17.080091423002244
+16.577193007991454
+16.319966057850976
+14.270806423114095
+15.93903755243376
+15.60773055595881
+14.097946403873394
+14.733955269761523
+15.427214086981252
+15.360161274023952
+15.308541497185146
+15.220797430118992
+14.548234204004586
+15.726879251132559
+15.003532185348789
+13.960839889201822
+16.40205868442375
+17.615949702934714
+16.93484105434024
+15.692201115265547
+15.122153761450136
+16.31668902043144
+16.495258280653744
+15.859428809913595
+16.010426792350614
+14.800155237051953
+15.60119167912201
+15.100306213312692
+15.423661227227399
+15.588705636320611
+14.621064645581058
+15.039163549337133
+16.732743856890963
+15.156826517366156
+13.471265569080359
+14.132941348762088
+16.726390415503516
+17.589145794011486
+16.68321252058665
+16.123551363271005
+17.871212328383564
+17.010462617202336
+15.097308945441725
+15.059629312348292
+16.15309762099612
+15.764818695578242
+15.1496588807602
+16.44419035191386
+15.630006303117057
+15.330315460935495
+14.534743106150358
+15.370590842308616
+14.998177348857311
+14.973432154957763
+15.86430902965624
+14.820050012279296
+15.812484485966692
+14.783801510720451
+15.041929351094197
+14.322564983361346
+15.474166098457985
+16.204022344117988
+15.432669501077896
+14.157613606058703
+14.994778597641329
+15.063378843991828
+15.254392807353568
+15.96906506096488
+16.998957482644713
+15.360436954265438
+13.274130320357997
+14.346028134091128
+14.93673186907749
+15.090880812553948
+14.4244298422324
+14.44482977005886
+15.322258693263635
+15.735207382546776
+15.846722824295355
+15.5912797677709
+16.820126649238873
+13.968028595992692
+15.44561359404723
+15.566324759244267
+17.062539827510847
+15.019534303726559
+16.909736305994016
+16.085807773188307
+14.560055438629007
+15.830530085505416
+13.34506300204562
+15.996046288540029
+15.080289838572583
+15.322700455781444
+14.559400395507154
+15.816342677932013
+15.10634366392621
+17.579026409411526
+16.982414955188403
+14.378092531151921
+14.71457174683124
+16.45444887181209
+14.060957149381252
+15.619146281638308
+16.835263521751898
+13.749385649598523
+15.84271978393133
+16.466956760439203
+14.698119699202053
+17.279766859029365
+14.445293265671594
+14.75907402532205
+15.054945406418398
+14.743022935416732
+13.28638226672426
+15.268158020973985
+15.338405252485657
+15.513920057415959
+16.988167101843644
+16.90080016624465
+15.068838229668259
+13.071839453984737
+16.003939656844395
+15.169124191788157
+16.585113178992742
+14.183367576562745
+16.97440381715971
+16.14919469690743
+17.161111470454813
+13.706169364873475
+14.031099583109224
+17.311156245332285
+17.289912086822014
+16.45522039553252
+16.518407147147954
+17.40875297654148
+14.608950390727344
+15.337618705973696
+14.648284954587083
+16.69665095148727
+14.819968312427747
+14.655780467855777
+15.429314561465802
+15.763614618889946
+14.380766755048555
+15.070980277710333
+15.994200444171227
+17.73106585196271
+14.821673987536556
+14.045885170818408
+15.575315228840381
+17.267025162130963
+15.270005997617687
+15.97620609119167
+14.969744841986781
+15.095977379507175
+14.629865671432995
+15.776553475001236
+16.104842164445685
+15.614657187653663
+14.546071236535184
+13.980579297794591
+13.708249507362709
+15.441315119354655
+15.554339644020814
+15.191542154894037
+15.600727300595551
+17.42919949361243
+15.4862715917602
+14.33027196629233
+14.493358052396559
+16.232091933348997
+15.135286539665998
+16.45954526714945
+15.991857492378756
+16.38868963673457
+15.081289692937887
+14.878810871588584
+15.061011332883098
+16.740044738808407
+16.884278983267322
+15.026213802314189
+15.51272918914161
+14.422267112752948
+16.58310900224933
+16.779082212320915
+16.869972942689543
+17.58889125735938
+15.6277767031104
+15.14970970673528
+15.098219993047394
+16.559025346592776
+14.018238163687045
+15.050429202938801
+14.765107642062972
+14.134774529057722
+13.925951977509598
+17.30579196196284
+14.885534566429953
+14.228207798074664
+14.127710606756779
+13.660780717120545
+14.588281500569607
+15.73374255395295
+13.332050932692525
+15.24369311744563
+14.653275879536167
+15.953069083408735
+16.44261938146211
+16.266347057608343
+15.105106422698654
+14.113983783638332
+16.807911804747107
+16.14333530436933
+16.774783221576612
+15.936496818886837
+14.83513376759565
+15.122046723133508
+13.03268474500959
+13.36594117619039
+13.850546370165986
+15.300941098099926
+17.47511062209412
+15.91631734551197
+14.782096219060648
+14.869984941788914
+15.710611819129355
+16.300324215238604
+16.28447862460004
+16.073752373458305
+17.045282891352898
+16.20103042163477
+14.210975163363102
+15.516115166893556
+16.177043447652792
+15.694491076094494
+14.543027199781434
+15.30646596989861
+16.37209168455273
+14.93235198227515
+15.158671209628949
+14.237592578811743
+17.001363692698817
+14.92142721211097
+16.049440575003345
+13.84340558492866
+15.113281202047673
+16.09569961495926
+17.13262569490108
+16.34782432901315
+17.194977921808373
+16.163797853137552
+14.877697556039905
+13.639290399806313
+14.442221340259607
+15.808107357083841
+16.122512755996198
+16.389336419755836
+14.441591108329192
+15.896984658599436
+14.844282278034441
+16.584246265935207
+15.64835926001517
+14.649586201230491
+16.585871053123768
+15.785256719433235
+14.08023373647913
+15.858762714363579
+17.098711078548206
+14.686134406961514
+14.741229235787515
+14.216008339776124
+15.439137399501718
+15.509888483414827
+15.025502741646804
+17.353968822173826
+14.94710344126382
+14.351356418294515
+15.353151004566499
+16.299936448739743
+17.43530519094888
+16.535674820339565
+16.723371306740333
+17.346825055807315
+15.515734398376637
+16.76796162197367
+15.775884507123848
+14.857431604968312
+17.094231518665694
+15.686995389414562
+14.996649653304146
+15.793526652573618
+15.494288482061492
+16.533289236882624
+16.360817435773214
+14.665076839416187
+16.710928731473032
+14.647344642942869
+15.369666914133418
+15.146016761072758
+15.597381853552676
+15.914689452236956
+16.46042070200963
+16.276580537530364
+16.038046667185412
+16.208578540525465
+15.434724792341896
+14.929176808267627
+16.295129075765075
+14.475829212528126
+16.680695056857076
+15.405615933759563
+12.861769371118143
+14.61729001420045
+15.870823937593073
+16.64245859085716
+17.77810634893214
+16.606898138382093
+13.95388292621287
+14.803397225890919
+16.521560098303794
+14.750921008904825
+15.293263426818854
+15.056013314687874
+14.543523811630749
+15.693395718114047
+17.2871465281478
+15.956202789199708
+14.962851279429472
+13.068266976525678
+10.800597431447855
+15.980461234703611
+16.764457667432097
+14.258826861996923
+14.18425613785621
+16.724826997900863
+15.970235402694101
+15.40169765615643
+16.661731306229953
+15.766744713303893
+16.497115918427312
+16.551238464235823
+13.98563006721649
+15.143334646944695
+14.797184613527193
+15.493699300213436
+17.90240828462869
+16.73272042879495
+16.155067880530297
+15.563975437542794
+15.786490405105283
+14.675810964681077
+15.21607669654334
+14.926185166489375
+15.776942596894557
+15.241872147272886
+17.069567854411204
+17.491414158454248
+17.521746849499607
+16.19840457024962
+16.059227936616026
+15.073588386918289
+13.282959191484721
+15.980006025977346
+15.23322659297203
+15.148455880437126
+15.659844639390187
+14.973688762969147
+14.914118202717603
+14.92072407093103
+16.77372482492602
+15.686980172691435
+15.015951872769492
+14.999655708236403
+14.949449766452616
+16.23296835200479
+16.918925940826284
+15.143762939490813
+15.476621568575666
+16.34149815937245
+16.179489853647254
+14.477662266565176
+13.787272929649376
+15.747180389970183
+15.165691314657977
+15.380713864654851
+15.152044676364426
+15.109259955098466
+16.44876842213654
+16.708556154710692
+14.30394093005006
+15.058667014516274
+15.700172105731198
+14.639598126334008
+16.17805237716003
+15.477645848241949
+13.760074282247345
+14.680874872352135
+13.766835276757817
+14.156405594808462
+15.21081030647025
+14.48255386262224
+15.20997068434373
+14.156831412926508
+14.541793060942027
+15.126459306243703
+15.690584002886823
+16.25547962246526
+17.232555465464372
+15.487822212737257
+14.027526710313566
+15.826453249826372
+15.253298507674188
+14.543760482213742
+14.423140417897415
+15.93251645251975
+14.151388507222165
+15.2580751657311
+15.52006759626478
+15.098486769275155
+15.201886264225436
+14.740382819219889
+15.485008639044437
+14.026828362887187
+15.035318983150304
+15.36302861754369
+15.895063801483047
+16.664498655738996
+16.02933420753925
+14.135504494154773
+13.14178979181105
+13.755904229511401
+16.84856686336144
+17.398658858406208
+17.0045538343103
+15.77769280146272
+16.685290508513916
+16.461235161900078
+15.063103192384574
+15.495495124613598
+16.62468380280093
+14.975580305266448
+16.312666483447472
+16.099840517727714
+15.399697000515403
+16.110794897384878
+15.280740498695849
+16.685598239377086
+14.570660837370198
+14.817386877574293
+14.895891661266532
+15.521182425375784
+14.570506003852927
+13.913370399072377
+15.290964935889065
+16.301368626668562
+15.399897198786604
+13.018196049360697
+13.926126235995739
+15.917244036402977
+14.190725827930834
+16.26534849558351
+16.332171943974586
+15.316397282508817
+17.469093602594697
+15.676131903017435
+13.857043670900893
+15.952836550075162
+14.258536614522612
+16.452575668629493
+15.570545861647261
+13.299560151250049
+14.900762981887155
+12.832732153626452
+15.22129337895258
+17.270698487642292
+16.54109959243604
+15.386843729182587
+16.581217573855824
+13.63425842551392
+14.3449034571846
+14.52460180025659
+15.27950811000747
+15.00733017120875
+16.425278600127044
+14.62143227966412
+17.331697320549253
+15.690523699749463
+15.453255051317853
+15.428719698005281
+16.630796255773035
+17.64172426349971
+14.483462076694522
+14.506375148665285
+14.42996298030414
+14.795976188786426
+14.728330453351006
+15.569516761112268
+13.72367072294712
+14.951554109296893
+15.149405484447485
+14.54112214711057
+13.810298614397695
+13.309144545821894
+14.311776593954008
+15.829037038728586
+14.705858742452648
+14.00105631281454
+16.614927509923632
+16.886852511433304
+16.379305129155227
+14.65475140943829
+15.643644331021179
+15.97538457303088
+14.742787604408377
+14.435586740208961
+14.782392337187602
+15.628957397839955
+18.109297011259827
+16.0012676598504
+13.916528072254252
+14.963973394155673
+14.370759819753246
+14.666952175352165
+17.18928665535948
+15.079538983836443
+17.126995754293745
+17.453594953739085
+17.380103744931333
+16.7449483011346
+15.211092551342418
+17.41677963695095
+15.752796531289917
+14.691658412994911
+15.489072696474693
+16.56898918763801
+16.393318553553442
+17.357256815759158
+16.085175989141177
+15.755699083752418
+15.004232554097385
+15.175077560369601
+15.675528658290688
+13.616273849879036
+13.788271821711149
+14.949632371774001
+14.418533721806455
+14.490791350431621
+15.241918383397277
+15.708032062496784
+13.348498728427685
+14.929568600046949
+16.548575501973176
+14.170754203470537
+16.680073675370167
+17.42305811498234
+15.960790972086428
+15.287006433922627
+16.76083602329642
+17.601602384065714
+15.087655812163135
+16.189512809886025
+16.463467380213743
+15.811419395337282
+15.463082140803706
+15.84502148697537
+17.170755597038863
+15.888648315443888
+17.366705028057495
+16.959248653742108
+16.28431268137713
+14.21652610880983
+15.365151093116197
+15.113294142413451
+15.913407000025728
+16.12918049499676
+16.37638530480767
+14.945900509238598
+16.02083503390621
+14.492863146614823
+16.18015144101848
+14.783307685379981
+15.45015882779856
+14.094324030726568
+13.57017591401896
+14.685699272665346
+17.538912641516177
+17.05288395448538
+15.481006634569184
+14.707684444955433
+13.986567404242024
+14.9269100378567
+16.396834088389312
+15.887273506505835
+15.032459618578159
+15.888111099416221
+16.201182133540172
+16.9741420655603
+14.135565749283515
+16.95927312532885
+15.038221743682968
+16.93428306337087
+15.467551567126591
+16.756882916889623
+16.02300555021199
+14.79781322497108
+16.41144828414251
+16.311437792560042
+14.259523570619365
+16.665266159935527
+17.086064777011075
+16.209187948814517
+16.60915830368259
+15.073386876863921
+13.90943529440149
+16.40729824564302
+16.284074869394374
+17.55743686340969
+15.923598542429104
+16.915927789828956
+18.40809939829579
+16.26279036173291
+14.68844142357753
+15.014429678009762
+16.84424870902376
+16.603608549801905
+15.258254529644645
+16.803236742786353
+16.796363747716867
+15.893972176378284
+15.694131848223876
+14.854731262687082
+16.29105058628025
+15.29070248363459
+15.006990911724486
+15.136615712581019
+14.91115931191176
+14.786765924867112
+15.478132571589782
+16.01725478039991
+15.142240756869967
+14.080907578424785
+14.589419085300221
+16.32484516108211
+17.451888815108177
+17.037657216981756
+15.929290837686949
+15.55246931523449
+15.809787156788687
+17.08118594793993
+17.654769248920957
+14.187731860559936
+15.644635448389138
+16.553899980485212
+18.97060852276735
+16.338695472972518
+15.59915092469879
+15.219091632417232
+18.17886966570056
+16.40001584223171
+16.66596233014843
+17.562289725970587
+15.15118767681534
+13.757318070641745
+15.384156992066934
+14.837272657414431
+15.288395892498002
+15.434992304334372
+14.11575153262261
+16.33554187864624
+17.45805467304504
+16.952974505738197
+15.411899197618254
+16.21056585584425
+13.980701073058711
+15.322198366368838
+16.786261619443266
+17.503810636272718
+17.027432260110075
+15.585020372063497
+16.102814101063785
+15.866533328884941
+16.061281878585717
+16.71446646623025
+16.518962876487123
+16.627027144686693
+15.31752208097123
+16.625614214436112
+15.610086138823561
+16.551481188721326
+15.348215724700893
+16.744913642377952
+14.126946865674697
+14.850569249349007
+16.505570715356356
+15.777246871958098
+16.540766217013854
+15.120990549175943
+16.00321833949765
+15.870885091093356
+16.38795878994968
+16.03148289275957
+15.805058684312954
+14.94354886713407
+15.458036024868278
+13.505955174423619
+14.962015146527406
+15.19081276924436
+15.668921634018815
+21.754184713796406
+19.501288111934898
+17.836557902170497
+19.974775402213254
+14.689083226211594
+15.794608885862687
+16.673593712812774
+16.62983451456816
+15.80023102220565
+15.49557497188313
+15.4308540423025
+15.481979940636066
+15.441635270546755
+15.982617356531605
+15.047025360182914
+14.407068878443539
+17.28288645809066
+18.083425358162074
+15.123529199967692
+15.415539683048067
+16.72292986286105
+15.879024135309805
+16.21456371531636
+16.64234351506134
+16.06056780366228
+16.072918923906897
+15.663594249551394
+15.757432564865624
+15.532699243218175
+15.308560326001839
+16.48897969263713
+15.154719046237162
+15.563847516998294
+15.197024549616998
+13.302205895747093
+15.902652050991776
+14.262316075845945
+15.268350800825402
+17.452160343607645
+15.993780019088007
+15.729534465416421
+14.747166348557684
+16.59180745869058
+16.68843206139907
+14.428976905492263
+15.350296783120484
+17.111711940784446
+14.477199893244233
+17.98975868437779
+17.068370355754993
+16.15413510216959
+16.294657852105246
+15.288565705681918
+15.020770182373155
+14.579379929464693
+15.898760463517036
+17.033839099798726
+15.315819947909361
+12.812686104430455
+14.261647468701057
+15.915068372656364
+15.579207603235076
+15.63084624872998
+16.974274115227516
+16.022738259794338
+16.586149731389526
+16.458126628862416
+14.42857285382486
+14.674836980987237
+15.362387224923253
+15.583969009082267
+16.054382581375464
+15.131606588618752
+15.320704876160718
+14.462080576584299
+15.933957888191188
+16.965826369661002
+17.444072977698966
+17.107447822044847
+17.039960061688276
+15.314915187178016
+15.919178876047141
+14.116929166392026
+15.466862887740547
+16.253469997334506
+15.925144339904634
+16.23373980079333
+16.761992430436464
+17.348011874021523
+14.761779148950794
+16.417323944997364
+15.97203966513068
+17.28663971763146
+16.53572427790091
+15.756118491016409
+16.711583478577026
+14.463155719761673
+16.520670997356504
+16.198627566837118
+17.879098984152435
+16.229680762152427
+17.713820704151246
+16.234350320443127
+15.256669734800582
+14.994456992397787
+14.701780775340907
+16.974797419920975
+14.923770940751396
+13.779612284943724
+15.256543654501755
+17.008404178666723
+15.525117223223987
+15.62627517205506
+15.94982994754109
+17.26445517226591
+14.371243440122754
+14.94753290465141
+15.448489949330906
+13.845714396075053
+14.684851404015305
+14.565580479876118
+13.058921041436378
+13.772209491561938
+14.961749921193686
+15.485143389650702
+15.602063617907689
+14.8658246675069
+15.987144564115908
+17.708344227352242
+15.671819359062397
+14.177516211812375
+16.743011870661206
+15.55195422096621
+14.55500363230071
+16.23524921413518
+15.823127648220677
+16.098254704545383
+12.059461270419646
+12.832858768979975
+13.90117160711523
+14.54425747272876
+17.057018748699463
+17.308567312088414
+17.09085368260702
+15.12040316360357
+14.653269709283293
+15.385656437585936
+16.41765184965719
+14.685095014077945
+14.80735109229937
+15.763972278268298
+16.64583463679422
+16.796950351222264
+14.871934732306087
+16.39707545915992
+15.080757853252152
+15.346841601322822
+16.99298875124792
+15.964576679785964
+16.78695619620484
+16.50509560046261
+15.397073139994617
+16.344840846061274
+15.470146864167702
+15.706654892196326
+13.99373034336638
+16.33140998860536
+17.154921598889402
+15.523382696380992
+14.971487613878821
+15.609720988984222
+14.331940919868984
+17.56772463445222
+15.091126213882802
+15.317680380935471
+14.440749465370018
+13.624112644935778
+13.977858495746602
+15.049055741779654
+15.26876046536789
+15.18055545082781
+16.7034149975798
+16.597830303472293
+16.3353869343954
+16.236963261055976
+16.378982827676154
+16.53401333289267
+15.836919441578559
+13.349251135181362
+15.086355421604452
+15.371993580835522
+18.109813404497615
+16.120432936363116
+14.87825366328174
+15.47891851955778
+17.803118164290694
+16.903922401617322
+16.909097569484544
+14.18312036004798
+14.057937637382565
+15.58638499389032
+16.712751693723888
+16.14320172560531
+16.34418346012211
+16.543824369092036
+15.278486756904186
+16.376414136257452
+15.815841754815864
+14.587197379420175
+16.20528801966732
+15.216965184046202
+14.009970367470927
+13.79776488309102
+15.06098251023154
+14.856576302620397
+16.244842903102494
+15.903633664571231
+15.849009114281287
+15.876360953552421
+14.888733481733297
+16.10083253715719
+17.503668235623365
+14.724454109714983
+13.8319480597372
+15.938293818260846
+15.757528791390854
+16.120209438393275
+15.596360351239682
+16.082796760850655
+16.295019614740013
+17.9431536040547
+15.674974516496306
+16.126650635577775
+15.307824261662617
+16.021242319557985
+15.043259527531887
+15.657852416569966
+14.732284965940906
+15.460319556982697
+14.458302233567423
+15.862417323135546
+15.524392102884846
+16.204804499085768
+15.602953301737259
+16.130582967024722
+15.498414422808892
+15.106272845403751
+16.85231134224003
+16.78603507979112
+15.899293822839965
+15.467563073019733
+14.869958911535122
+15.14941734043579
+15.865399277783084
+16.723037041725192
+15.454170807767738
+15.75951164151617
+15.302239421893617
+15.115110506751947
+15.079340746350084
+15.766418113693462
+16.07198386841445
+16.461141452276763
+16.323654818520637
+15.600524441580745
+15.413096748891988
+14.873789185570985
+15.871410846439588
+13.3311735394892
+16.282717534552532
+15.773028466983163
+14.875719965174994
+16.817013385418704
+15.329584139860799
+14.724879104746336
+15.600911117381727
+15.099552326394772
+15.427498997539843
+17.22388551455748
+14.203392183117586
+14.259979495261547
+14.215646290776661
+15.882936546836035
+15.239033435638376
+17.120630234875208
+17.177918811356122
+17.106207950391777
+17.301581958361226
+15.980909164601997
+16.07823307196857
+17.235201584954623
+15.248216030554218
+15.896278893659613
+16.262279852379933
+14.744199572871437
+15.627712340945322
+17.133322273143662
+16.059579368879326
+15.451675401829448
+16.7629238639647
+16.779253536858988
+16.793693979885703
+15.513025511608234
+14.292385891467461
+14.359161268137143
+16.629320954932965
+14.606503669394542
+15.250521657370868
+15.679194120871117
+17.704155349972567
+15.449971202172733
+15.45634090333806
+15.014431129120325
+15.898177384542507
+15.348807374912553
+17.154544500035044
+16.31850607636116
+15.75089546988869
+14.761616601124786
+16.33027169144347
+16.941619004347217
+16.00926050091877
+16.324963776024617
+16.312627989912926
+15.549788137122263
+17.11454916562012
+14.353422477656721
+16.2156884666462
+16.401244440321435
+14.442367750320642
+15.720831849291827
+17.056794918157536
+15.33846226808491
+15.508555581655713
+17.096936076977798
+16.611824434056544
+17.16704234877433
+15.100351831818429
+14.844359793831927
+16.6823706057625
+15.744740988773728
+13.102796018484256
+15.748486280986256
+16.281898164183133
+15.863270722886725
+18.1981560915559
+16.388558736387523
+14.98144479504451
+16.015372380919942
+15.121301334874758
+15.821283194595424
+13.200916155964364
+15.267122586425941
+15.895208777347008
+17.084825906468794
+16.25434730649657
+15.569825313523452
+16.212974363692197
+14.642233560528567
+15.396630297869862
+14.148087357517468
+14.851777932871073
+16.299138008026674
+17.52319265682563
+17.136112943371046
+17.689200300856243
+17.044950360208517
+18.0408972674892
+16.51202044876723
+14.605900056700676
+13.83073982505121
+17.103221953817396
+15.610607786823152
+16.980141070175094
+17.644688860972963
+14.554703100377509
+13.893987252830257
+16.132554141521084
+17.47269483491975
+17.31639538918823
+15.682281094793694
+13.165304159955312
+13.78434231050268
+13.102356463664364
+14.282906744138032
+17.39429261599517
+15.378766596993174
+14.796207591964901
+17.019564269787594
+17.369763517138608
+16.82504966397528
+16.604072258088294
+15.66501433128849
+14.093705964063687
+14.292191962658777
+16.403475743786572
+15.22271583237493
+14.840227027392444
+16.11490095941312
+17.736267361547263
+16.018347444629754
+14.528173272971586
+16.898960830388233
+16.488691475044405
+15.227949495609565
+13.507114650893854
+15.52221668431227
+14.183106133118429
+15.81011488493796
+15.356195816645666
+14.997447612294408
+13.46847626772167
+16.485304031794
+15.219775458579406
+16.027739050467815
+15.01006908661661
+15.12598174135644
+15.436627810061069
+15.703595736451135
+16.86133553662519
+17.354554317200453
+16.159148754478693
+14.705846505452328
+16.059338655088155
+15.97295989592756
+15.029926967114008
+14.552527177751855
+16.759684823982226
+16.259492399729865
+15.240715958505149
+14.610360306603113
+15.450016635921784
+16.040539497437877
+15.746084503175595
+16.305398265578717
+16.255975492383655
+15.278211118438705
+15.979790467855182
+15.043859434153205
+15.757586807298892
+17.25564578912497
+14.786262535637931
+15.794823407943838
+15.734970363583201
+16.079776314256222
+16.1635391489078
+17.114923614667404
+17.477743867332393
+16.781677907398816
+18.028610181030842
+16.4658409889621
+15.37697276943014
+14.16680686933951
+15.296976123597645
+17.23464099553148
+17.527215414028333
+16.202691807304475
+14.080845786857083
+15.250689676212872
+13.635191515362095
+15.497514048875459
+15.80232046705207
+15.144527760639377
+16.33168390765759
+16.23021573009781
+17.510127942440818
+15.516072221188523
+16.14709415318825
+17.4333162556631
+15.717021707068483
+15.275123128808914
+16.138393002759287
+15.969166286908305
+15.727834194135866
+15.209971809922024
+16.868523250342108
+15.694525304214778
+16.221686679417573
+16.0953088244178
+16.02385956340339
+14.85751088746251
+16.119984580987378
+15.705955127187451
+16.581261709972182
+16.957021804800107
+14.77192172740017
+15.23444829981257
+14.905317536328567
+16.051752069418043
+17.150942715020946
+15.562872805456948
+17.04773281705998
+15.769103990135662
+16.14185713871707
+15.72728670697515
+17.207657643099523
+15.816139824388358
+15.868837318032845
+17.017585483323614
+15.592262468220781
+15.722331073569478
+14.533097589018311
+15.576592190821827
+16.231133129863437
+15.529108731110313
+15.097845226003201
+15.488205962554446
+15.151428464535698
+16.60593048041403
+15.45451849652747
+14.96770575273743
+15.923599328310345
+16.06293029757903
+15.404871025902025
+15.902951645575314
+14.862275017814582
+15.804086755595236
+15.246330154815084
+14.617464581359542
+15.372602013894053
+15.628762954940214
+14.442511242689562
+16.324187025590035
+15.94857013486724
+16.72846471455415
+16.878093652403194
+15.292722372867473
+15.071827084467103
+15.135594327790798
+14.783735323128965
+13.707988930952311
+16.181937471633816
+16.217326488030892
+17.41765586703265
+15.842887085770329
+14.717017926349584
+14.971960791880932
+16.226370205048596
+16.626069212117443
+16.689042646173235
+16.506860027197703
+14.88335066009661
+14.245843140243252
+14.998467997702065
+15.674496260090208
+15.826239497662868
+16.183848888127145
+15.487822880398951
+16.738742206767625
+19.01432883946903
+16.318383982548212
+15.555569139210348
+14.640667207075495
+14.927193414419463
+15.310325591162979
+15.612163798815757
+15.158992228133584
+15.881530570998706
+16.892066809495503
+14.254384466977214
+15.034436370727775
+14.94089462528406
+13.237751553547625
+14.543091150305841
+15.870780630261024
+14.794611761026786
+15.588307785942845
+15.870232114415828
+15.22827300174491
+14.395522304662322
+15.18951015119248
+17.154643189507894
+17.688334904098653
+16.66539850278498
+14.987935163357392
+15.51180933880265
+16.74778729017936
+16.13615219073499
+16.364528624128283
+15.892500432869141
+17.24755521423978
+25.80019862135522
+18.851425210265944
+16.844914133845677
+17.05681468837976
+16.434892543628607
+16.780971792100416
+17.601316449697805
+14.164281481828937
+15.452190538871704
+16.46417684493987
+14.804313521014379
+14.557400006821425
+16.95316579265561
+18.361228413745707
+17.32075533482454
+14.26669632507432
+16.514374798147983
+15.593401491060476
+16.30800542713726
+17.119574263239784
+16.13950624405092
+15.954756683955637
+16.34858863178006
+16.25325937980689
+15.05386480145522
+15.0076819689139
+15.262082734866937
+17.319152700397225
+16.20424834608538
+16.960901276797358
+16.89787178837689
+16.709757644098232
+15.251201114408843
+15.4427838692106
+15.94779558910021
+14.925946623167889
+13.785126422347545
+15.680938955101027
+16.33519142071222
+16.337002932124463
+16.913206138922988
+17.67240609645232
+17.454991447889725
+17.243470550163707
+17.319679974393836
+16.237821021072122
+15.911075937249848
+16.622401552549846
+16.18297528805114
+16.4223771822206
+16.213269724258197
+15.137073255366303
+17.14902084030271
+15.436264570758269
+14.770315958896092
+16.07380823136937
+15.282355409197919
+15.101436796135104
+15.581578069570142
+14.750833031763861
+14.79900509264607
+16.264928747144495
+15.630123560621172
+12.532611585853317
+14.7132685447812
+15.460938605419585
+17.07042405890293
+15.00680769733249
+17.226629516366216
+17.114792162401656
+16.497829856545067
+16.84211437465318
+16.471988393122487
+17.99522790473084
+17.480154810252984
+16.83511839010606
+17.30091718379134
+17.142776395769957
+17.688803268525945
+17.253225699011622
+16.652390852732708
+17.576793843467883
+17.262936961572805
+17.678456335562245
+15.810105344812897
+16.838524156616515
+16.566437058108008
+17.446322545813658
+19.00259293642158
+16.018966288657225
+16.559613087581923
+16.839317608567555
+15.210023208748282
+16.702958822995484
+17.018568160642758
+16.68855522857423
+18.142606632313957
+16.97567515999218
+16.04612601250676
+18.338816720645326
+17.00347597367717
+15.920190083072953
+16.429779448722982
+14.116588171096325
+16.12779028561603
+16.53041483870912
+17.374417936637556
+17.44931565050497
+16.613619416316098
+15.526888074672058
+15.695896563932493
+16.962832205495673
+16.566786393755237
+17.833209267396754
+15.66298004660139
+16.537115724943092
+16.807063929683096
+14.906743346257102
+15.775066097449852
+15.50786440042313
+16.851988586645987
+16.15619991000581
+16.393795031369777
+17.334895071364315
+15.204797943406135
+15.795134456512258
+15.622764289835345
+16.064900344795646
+16.18126806938203
+17.6306287865403
+17.483840754939806
+16.006747624702186
+16.647568836149418
+14.47695890454267
+15.56805852353989
+17.323151679475743
+17.234559558095953
+16.354423341307154
+17.359966255005858
+15.296877051887023
+17.300264276542535
+16.698738498042474
+15.086671602788428
+17.1264371436839
+17.78587455721859
+16.752013424747716
+16.167456241428866
+16.68750423914402
+16.111379100274775
+15.344843722015653
+15.078261957360496
+16.301564264850057
+17.185711715222183
+18.6867788393791
+17.600069181694664
+16.584896912730258
+16.171316299225595
+16.047951211658685
+17.385019483881578
+17.395690258414177
+17.511907396870896
+17.23139125219241
+16.74610386497318
+16.717155287638505
+15.512316936325774
+15.427354776629343
+15.419255946173081
+16.558721293227777
+15.316770009709742
+17.792310391664316
+16.472398291769167
+15.973284644527354
+15.649534477869636
+17.48679958014236
+16.02808679436812
+14.73797133324581
+17.489340924539505
+17.020467474985992
+17.57661159278456
+17.464232527987264
+14.05400987886459
+16.68836584631289
+14.864248936984708
+15.483151700946578
+15.276019882729841
+18.15904362867353
+16.09349285600706
+15.27198821698336
+15.669128849972097
+16.10298650168636
+16.376875354151153
+16.36813726686792
+16.10913160444295
+17.552740499924084
+18.701761541477694
+15.47708457838074
+15.809535132264031
+17.992388386471106
+16.66127207911738
+15.673962262033143
+15.764446517082447
+15.954811107127796
+14.3779776578874
+15.13114068009763
+15.786564750442224
+15.833414062052498
+17.020203527199826
+16.39457718924767
+17.082061504899244
+16.256873113721397
+15.391683629319587
+15.71857824324836
+16.042473842808633
+17.525365835361654
+16.887612404520155
+16.222918160076247
+15.457560631928175
+15.962893656501663
+16.416485181077192
+15.112870217824607
+14.68127257900683
+15.380708111392465
+16.700992315164157
+18.068413030752865
+15.94742070473373
+16.553705837840397
+15.817205190527218
+16.292206619716964
+15.789243674131853
+16.99177472015127
+14.919328162936893
+14.673325951066886
+16.65033322211768
+17.838619821899115
+16.917940726576646
+15.236927519556275
+16.132188130626915
+16.17672690510429
+16.1064508001931
+16.549776550910153
+16.55984791178149
+16.40792597658418
+16.008596208902816
+18.040266751539846
+15.854290146124058
+15.780463722968776
+16.715581248200678
+17.2387146956453
+16.105479802902337
+15.774318793842284
+16.671240355394147
+16.809150125522464
+17.695444510514506
+16.431607545590964
+17.876034956927086
+15.442252738019036
+16.065029521732
+16.701137396490452
+16.53191171271679
+16.731488797370318
+18.16129341240601
+15.27009561739031
+17.605563144695694
+17.2241161918258
+16.396991411485075
+16.42208802144303
+17.331257381221306
+16.437467057510887
+15.168328682864157
+18.179823385194908
+17.58175935720527
+15.063303231553093
+15.841072456270481
+15.037443180804743
+16.286811984908937
+15.28517757656688
+14.985063361027372
+14.490372751492941
+17.325432423159185
+18.346437111373376
+16.25912483709432
+17.012790653178968
+15.671703571456959
+15.35048479008671
+17.20155161979774
+15.513792755279823
+15.288806084779765
+15.639142351327294
+17.77784504368219
+16.675385810664906
+17.452241443058895
+16.54108948783484
+15.714075303007988
+15.901499272594862
+15.722749439322428
+15.629064719167687
+17.39138620232663
+15.185839919694857
+17.02449332674402
+15.682937624762204
+14.436070100830463
+16.458843754294605
+17.79280805764141
+16.751911779639883
+15.934844943944384
+16.547960407175808
+16.095707483931022
+15.492490366142405
+15.485861950078672
+13.226049699740713
+13.924755597989787
+14.84660703140436
+16.93986706342598
+16.337006153105264
+14.634304385271165
+15.254420896518155
+15.63998355889288
+17.44560070375583
+17.807358498658843
+16.544195397836006
+14.573721615789424
+15.01904147654362
+17.38880871396971
+14.266257382012398
+14.664360949588158
+16.384492020681122
+17.16046281227588
+15.926320514377323
+17.06321603830905
+15.747220640869912
+14.906648165991115
+17.703671436965294
+16.50475848066327
+16.479748087066653
+15.83586727068996
+15.401199291463243
+14.14108988496831
+15.7627191521958
+17.5261166888653
+16.711700255204747
+16.157660868097693
+15.45417145833639
+17.332272507984484
+17.138052623329656
+15.366277263189275
+16.999525691435977
+16.983209868141202
+16.552649843011963
+16.98194049534706
+13.748534523239869
+14.6897167513321
+15.850315104914444
+16.60573976985937
+16.809321926574043
+14.827702430624257
+16.394045555117145
+15.763388829562217
+16.624747936350275
+15.885614443587755
+16.617100669952933
+14.44706044162534
+16.113764591561946
+16.65559855909926
+15.989484666901419
+15.046670237294265
+15.686204629072407
+16.289203261098976
+16.305165612765094
+16.935679718309913
+16.074877098206088
+15.760439679580728
+16.24879010879276
+16.03595528782462
+15.398459686345092
+14.620516867085414
+16.15742305788379
+17.281058534949935
+15.06334436451057
+16.311615598524583
+16.08455751092599
+15.991744664119565
+15.829056422212588
+17.575133684124097
+15.856884009500831
+15.659864186035676
+15.343620549768573
+17.325622694525578
+17.25686924176142
+15.943524626453723
+14.773641274058818
+17.21917573213092
+16.737391405406996
+15.78327479051687
+15.212818735789668
+17.87559301541164
+16.457699174867088
+15.742574854617246
+15.911950805439972
+15.699361238225194
+15.091760625116379
+15.304476444289563
+16.228188595607236
+14.475332785258999
+14.655187855423065
+15.421079302708577
+15.452505069096361
+15.912245726705706
+15.716627631222437
+16.730263117493365
+17.143905986067026
+15.85384643465531
+17.928901808993345
+16.76320356093126
+16.245612881690832
+15.314051205761075
+17.941387833961187
+15.781331198606509
+15.423051144327545
+14.704192895024022
+17.13881773154469
+15.776477152507766
+15.749902899740505
+15.242278729301816
+15.918572129934887
+14.549066836345432
+15.474744733739598
+15.59910811859919
+17.10859338373281
+15.620314476160516
+17.339922437435817
+15.414569126883663
+15.769787962076407
+15.472510919650077
+16.553324382600536
+16.70658461349585
+15.84789698973097
+14.543286327588206
+16.886835627504794
+17.752645717821494
+17.239590952833723
+16.464734486554974
+15.786496174923556
+17.829723854301065
+16.87421284369121
+16.089141435403377
+17.274412276394216
+14.970632754398522
+15.03966256021043
+16.34837659456747
+16.623480173008716
+14.551142051468062
+14.024880113856568
+17.883617571370664
+17.52639119723169
+15.928217270632217
+17.390332938607898
+15.065865885661623
+16.026239558332364
+15.948539272247771
+15.692938307920471
+16.027165600971855
+17.091053782287332
+15.709113158292226
+15.63106416093926
+15.483960458854696
+15.812256414419508
+15.481580653925903
+14.318146308474255
+13.82059634681299
+17.00718076992115
+15.898115707164223
+15.88688405919575
+16.197827402208716
+17.393988485372248
+16.268861595343353
+16.229161982379864
+17.414609876976613
+16.32102871645047
+15.961383165016102
+15.779674724381238
+18.68638070763808
+15.9483960012885
+15.36091086513072
+16.26001660253536
+17.556660899799155
+16.48813004111092
+15.998287466993546
+17.63501317548736
+18.396105837586575
+16.094897105333573
+16.891657030295647
+17.66786019392849
+15.990367039924266
+15.797206307428851
+15.966517006156963
+17.1711856067558
+14.920431342851074
+15.321335816818916
+14.662926254958577
+16.638959674083708
+18.514670598150175
+16.025178669388694
+16.057173073814113
+16.44668438252701
+16.570527513907038
+15.908703721487697
+16.804583691319607
+14.942448503591933
+17.193786414941783
+17.57293953060389
+17.261330283027903
+18.179005557794355
+16.509934653505923
+15.432927718804493
+18.672214561202892
+17.11352026056572
+15.498881643675176
+15.894001832696432
+16.083243767906325
+16.171141816492423
+16.959675287519758
+16.32287070964827
+16.09472574595847
+14.684034941891198
+16.007333110117187
+16.995335108079644
+15.953248879813103
+16.66761311247774
+15.949884846644025
+18.04901329498945
+16.72735384925602
+16.37195313019822
+16.624768152501375
+14.22985013020704
+17.008975453839298
+16.959010343395235
+16.100795656739905
+15.07193059808715
+16.520650745533132
+15.872577322919213
+16.628581971530465
+16.689353257309037
+15.925434519897081
+16.06398486046814
+14.237834305120174
+15.068108417873887
+18.045743004500807
+17.390269050750888
+17.531048158723337
+18.06273983952987
+16.880338269710947
+17.414482306976424
+17.13245201606263
+15.70922051236333
+15.166395235948528
+16.389289953523033
+16.410330053167968
+15.645610845254808
+16.39618669286986
+15.537377211669394
+14.748947079318029
+15.980366414657922
+15.544291227916588
+17.034947567281876
+18.314336285821256
+17.52315168248508
+16.66458566097714
+15.003915665317706
+15.947203345022004
+17.034454269209505
+15.850256222423681
+16.33242785961629
+16.773603250317493
+16.258739162611292
+16.342220249933547
+16.069331922061068
+17.247795238019435
+16.454532024391426
+17.100425396752755
+18.935743073399223
+17.162320150257088
+15.99013789433883
+16.67698392602979
+15.692777202799476
+17.41799400069138
+16.60398744648684
+16.273784031055143
+17.119068630551112
+15.803383957150757
+15.735678420315054
+15.90405290154348
+15.351009326939987
+15.555075032726293
+16.995965032870032
+16.628756182790937
+15.262351708105754
+14.110852571725644
+15.533862600620253
+15.925969084574348
+15.96889943282497
+13.532097635972079
+16.44659397817189
+13.68821244600801
+16.287223890858925
+17.13847795668066
+14.663708933900466
+13.959209673157275
+16.248537906919722
+16.173859573700184
+16.547211154303454
+16.886418462037014
+17.123455553031064
+15.934829107188463
+16.503630378281116
+16.620468406976713
+16.97094118240554
+17.705757475748683
+15.461313327436514
+12.176190384878893
+15.071787678230933
+16.25055210564581
+16.075989252109125
+16.11861793575703
+16.893223860189252
+16.81940009352877
+17.076227782304272
+15.424838873173172
+16.622055703812705
+15.416951475687384
+15.9002787387751
+15.250372956025203
+16.527556257062074
+14.691762596272042
+14.472104142831697
+15.417026180991954
+15.388059705334555
+15.179780978858503
+16.74105736387783
+16.061482300774045
+15.444100865686039
+16.92214000874172
+15.948668828925861
+15.989645842521568
+16.889925373563116
+16.53504757657342
+16.469932401699836
+17.968700042355763
+16.863658034068777
+14.582355789469787
+13.906793567504167
+14.13553534161477
+15.158815921209907
+15.4064073482228
+16.194444062299993
+16.333535801896403
+15.58429710083091
+17.053997496609682
+15.576071212117043
+15.732200113725611
+17.211715607577972
+15.334512600382894
+14.756124861657256
+15.574639665725243
+16.58380515144843
+15.387720813254745
+15.652836059998208
+15.723109028094768
+16.347076725117248
+14.666985205457536
+16.67360987007332
+15.935579689715667
+15.815104086619101
+18.366336998297427
+17.145651010370813
+17.197190548204702
+16.92859994102254
+15.089293815169938
+15.530594556885376
+13.73007223045009
+16.90475594249996
+16.622413773006386
+15.084166979772007
+15.82230836155243
+15.718934073541362
+17.679696447253107
+17.042538033688558
+17.434761047986584
+15.25420949170983
+17.011096021484846
+14.632892850266913
+15.684301589643042
+16.503274693116524
+17.45024088243224
+16.528476839833345
+17.11766983923961
+18.06056951686223
+16.330929668826727
+14.837002785457614
+14.845060192945922
+17.07368179630504
+16.7445783864098
+17.413431820933084
+16.265487566839937
+17.410895528205174
+15.441972525308643
+16.276239116228012
+16.88946447698021
+16.113750993631996
+15.40222500100441
+15.363228583854593
+18.010659889062993
+17.32867976612438
+17.398940351550223
+17.35611913522827
+17.599242951343868
+16.021643945721124
+15.750694799710601
+16.02192979696028
+15.411210036351264
+14.853563302896575
+16.19736609225049
+15.31988061239197
+16.86530908525772
+16.521670478734038
+15.525104348738765
+14.315369165889464
+15.894505492132112
+15.849620128910757
+16.256835853010443
+16.868936296581538
+17.649558092408526
+16.2376853388094
+14.707820732977538
+15.618863903342529
+15.92597024333206
+15.9787765580718
+14.654524815598975
+16.428909995889256
+15.586336964667979
+16.11669635982615
+18.419015121144938
+17.92497311814448
+18.884878518404804
+16.12478588355539
+15.835273067434116
+15.752856286197968
+16.254083446021497
+16.029462435224957
+17.42806644575714
+15.879386201080905
+13.546882447276218
+15.879860055368823
+16.819398578608457
+16.288690458920314
+16.030317649083187
+16.570313230102485
+17.52514414146482
+17.148032876400563
+15.494441483370267
+13.941018335488977
+16.55462123155492
+15.603650493834934
+16.320678544759076
+14.993833491217387
+15.601540622203188
+16.023822565389608
+15.281043177314714
+16.351351975563077
+15.964125179477548
+14.905479163430158
+16.335904738640366
+17.595246742062656
+25.750744171744913
+20.180185246871133
+19.360406132014035
+18.847888207021896
+17.724313590115784
+17.838611639675065
+16.831149444312217
+15.258387505504743
+16.57140475539532
+18.281172995222732
+15.389080558647024
+16.654510138866158
+15.697895536049359
+17.613681946458556
+17.075196536927464
+15.362198809017016
+16.26301273385684
+14.792810761060323
+16.52152382463983
+16.080343907090523
+16.87793743554171
+15.911516761953948
+16.286987189898213
+16.089688389160088
+15.142377747343133
+15.589930828182958
+15.121008178567052
+16.86373985313979
+16.60422313491877
+18.587001415945736
+16.591346795749615
+16.26386212317371
+18.176992861085324
+15.379229930867709
+15.94511315800031
+16.384239784209598
+15.552368579654967
+15.479705969272018
+17.234462754781205
+18.26254089833631
+16.945457227107568
+17.551142709478356
+16.552650174663057
+17.007160220107664
+16.50773805502091
+15.493690125241159
+15.89863574331575
+14.147543329164549
+15.081478015001679
+15.842464582721476
+16.235612543930856
+16.993234104053656
+17.89300223269845
+17.07255422634681
+16.462123236151328
+15.565932528394725
+16.060919827909558
+16.66624609178055
+14.956388720764608
+14.501148809619579
+16.50225387966678
+17.472849669094856
+16.97400924348166
+14.741285247165095
+15.114834598965672
+15.902336660030159
+16.103853054404894
+16.10484387815717
+15.563956055846191
+16.458904892594774
+17.06908057687923
+17.85967716951272
+18.360033011548936
+18.10036422389824
+16.692573108679312
+17.010821703336887
+15.655237257700648
+15.755522521073189
+17.134468355691013
+17.02750228508664
+15.770717256693231
+17.53286468707141
+18.97389262999026
+18.592618387888265
+16.062185985177578
+15.205463249658564
+16.478480942464998
+16.05575270484114
+18.8969331167563
+16.96602877728894
+17.273144279500627
+18.66818829789011
+15.640971417642632
+17.693025488697927
+16.915356101355883
+16.33530575738544
+16.769126952349865
+17.215125396325845
+16.772664087922536
+18.468240766649274
+17.60186749675276
+16.387430893429354
+17.32665636008744
+17.051189748660775
+16.91880063760111
+17.22097194391823
+17.805098568916506
+16.808444660232425
+16.523364752259923
+16.48586185440122
+17.536096291739867
+16.273246162390336
+16.503696577960184
+16.67079361148153
+15.831551028050427
+18.095060453512716
+17.862371859577564
+17.31793131777708
+17.851408726551128
+16.440547001531954
+19.594086535480386
+18.61927779325815
+17.01914985727825
+16.4525162910097
+17.032406598598698
+17.581224530773014
+16.85439258101043
+16.47159448669295
+16.783826393630804
+17.870541126674055
+17.706544357269365
+17.088298893601532
+17.005902204366777
+15.215509227876979
+16.764868256597367
+16.524491409825742
+16.750480741287802
+17.55002562496557
+16.48780325996097
+16.46778483128641
+18.268969548281262
+16.465906947015966
+15.134873959430891
+17.12706603442693
+17.400216596945384
+17.35777747036863
+16.14771179812378
+17.078841149684507
+18.298898455173045
+15.166358694836703
+17.394070143615295
+17.590422889785955
+17.187171042871725
+16.427517403620584
+16.351253899684608
+15.880716747845781
+17.004622871590044
+15.513289929900665
+17.41226521026772
+17.768090718279552
+17.399681465611366
+16.12832414537739
+16.433203688978764
+16.46149951224048
+18.803290153090657
+15.096244575617533
+16.83051829685786
+16.6588881624928
+17.07393130568832
+16.38868757460439
+17.069928202697056
+17.956270122130164
+18.022139630849495
+17.951653153082745
+15.703512618818436
+15.802642129634663
+17.16636028118252
+16.24156393369627
+15.716623723946597
+17.396429088043377
+17.161746714337895
+17.612450942955178
+15.287029943210428
+15.83728904453288
+16.700510957375272
+15.840546817230532
+15.770953318107303
+15.809233770023937
+15.197105564756342
+17.215119947893086
+16.744132637854463
+18.06233028165414
+18.471035613602766
+18.458349006841388
+16.899041723235868
+18.14684416272958
+16.1009075054953
+17.956866109244245
+17.783361964579242
+15.646226993013727
+17.70392351499956
+16.679392161264417
+16.870079514939505
+17.588776066375743
+18.751208288216688
+16.865408088512737
+16.61202872527744
+17.51420746565391
+15.323083068508353
+17.222939269433766
+15.400390783676286
+15.025354792823933
+16.25608241309199
+16.70470911296269
+17.144210424354853
+19.30713900511489
+18.346975300971863
+17.959876281493663
+18.015568574942094
+16.919692739053616
+18.082457858921245
+18.198821681739446
+17.736613734597
+18.667611406851904
+17.571221888263835
+15.959265748942684
+16.785467552227672
+16.02631185558988
+17.519303376148642
+18.58018685007977
+14.687267592757394
+16.798059804037294
+18.76202277042458
+17.495019955951022
+16.948152422734466
+17.708095115897308
+17.686610262456938
+17.9100516521909
+17.56008168343648
+18.09796196648331
+17.759472513322194
+14.358399638324428
+16.231981643800438
+16.817141390310553
+15.79994778157122
+15.968267629929429
+16.33655644548864
+16.554380596628462
+15.686761478465101
+17.84616491582871
+17.774802835762443
+19.072867304577343
+17.623623880374936
+17.51659200329746
+17.254909495440316
+17.13696315424447
+18.28182802229709
+18.23052920731881
+18.257371595944036
+17.659064837621898
+18.510889855127417
+17.29500287174882
+17.4546125783032
+20.077749599940717
+17.457858160183264
+17.453987308056966
+17.538554694642542
+17.21637553463792
+15.617608688826394
+18.862037816130098
+18.59783776035414
+18.067712908940408
+16.321450832323976
+16.44959438135257
+17.50423536859003
+17.200857850108136
+15.775224783727154
+16.333328311158155
+17.32652491503714
+15.652744839618578
+17.161964788960987
+17.78972652976033
+16.88711393121504
+16.77464779725753
+15.859882117104448
+16.10896476196318
+16.38244642673753
+17.028884627525983
+17.44469080996592
+14.694654703903183
+15.183293153703701
+16.56222194799608
+17.002889768794773
+16.329324137468163
+15.353655277023208
+15.966059484068197
+18.01193242701885
+17.643676030187706
+17.355380197757214
+17.470951713385148
+15.0916301257908
+16.143633382228344
+15.989006812499909
+15.310676725505772
+15.247003023672718
+16.401633948466625
+16.41130725640079
+16.48477138473463
+15.708452303458685
+16.82707671301924
+14.783238316447253
+17.266400907679767
+17.468141937499
+17.94119455995711
+16.831591283447267
+17.032306090017755
+17.636179062534026
+18.32870021382739
+16.72730418933706
+15.010742916145873
+15.743055314300179
+16.813271414249016
+16.97897231582698
+15.543544140757163
+15.59956387331863
+16.744471383199468
+16.530586922586025
+14.494518252921253
+16.766370251871734
+17.124853867504513
+15.275998564492923
+16.329206661178333
+15.403771422307969
+15.577602737884447
+17.595243081552084
+16.970377792558423
+17.366651352512818
+16.592128144386294
+17.5995720748963
+17.035830666946907
+14.870912819251842
+14.936943096149705
+16.83880407170028
+17.73502074905663
+15.748621930423909
+14.49098095881591
+16.025259460875958
+17.932710778811554
+16.413335178074107
+15.878869342500863
+16.392673041498867
+18.728891867793678
+18.118604475576532
+16.937152744292092
+16.040484636555362
+16.799911307130117
+14.906030515604456
+16.01762298819817
+15.140993591183829
+16.057489642871502
+15.824702279568157
+17.92358178661516
+17.156559635490467
+16.146777455105124
+14.215594459650177
+14.49629753056307
+16.83124607425802
+17.741506405157523
+18.74398739346624
+17.10173317862511
+16.14780667480005
+16.49616365473861
+16.015140453111215
+16.240943494537433
+15.610665521938472
+15.900075933040782
+15.842220101490781
+17.188722479610732
+17.306101055233384
+17.581975584977485
+17.8155722742805
+17.583691999053187
+16.867481043928393
+16.453933910205265
+18.09141361167316
+17.449468636707152
+16.31441474405412
+15.474563911751744
+16.594237986637907
+15.932253161224608
+17.32566095236585
+18.20085594386758
+17.323985165909477
+14.93870988389547
+18.370939705530958
+19.04266323711171
+17.31951329225207
+17.510189351452155
+16.951829889505703
+16.5803104592015
+16.04023227810974
+16.696689685343244
+17.538145482567145
+17.38467608829781
+18.223913900232148
+16.809142048861176
+16.767462710412858
+14.134675886938055
+16.81182630327332
+16.449812512484343
+17.48728470463398
+18.03404909943275
+15.92312275965007
+16.60023577134254
+17.457498477862472
+17.040700487734426
+16.292902356860907
+16.723074881171527
+16.754102322751365
+17.76449366236743
+17.189869961690633
+16.42487577848115
+17.384554928726644
+16.23161469088477
+16.20322302597394
+14.901482760188387
+15.666847593040231
+17.351920012406538
+17.379684646920353
+17.700640128233474
+15.978275471861465
+16.701981630727687
+15.322186749604938
+15.826678655809218
+18.170322301948133
+16.324447921781612
+15.756748446538964
+15.280182052115762
+17.506605548398014
+15.472090049456966
+16.61824225016629
+17.530686710387528
+16.875863415544003
+15.224917727276008
+15.865454080155715
+17.463036151512924
+15.585260962543245
+16.08062422178297
+17.694114619169497
+16.497257406409943
+18.564221239724574
+17.95476661456958
+17.379516684164543
+14.518086758960791
+16.528967996185244
+15.8182097981217
+16.330997907855973
+18.19584108098678
+14.88412015278277
+16.606514698231408
+18.436359018841003
+17.387018410120632
+15.09781303576112
+17.66336201423539
+18.705009049105257
+16.940891595516533
+15.633846972392291
+16.329586642572295
+15.66875135078837
+16.865141619776978
+15.444663509636001
+16.821536150823093
+16.2653925437143
+15.723884705064933
+15.744557650432938
+15.61120388251814
+17.071080109350916
+17.44177377251303
+16.128724290455338
+15.583383123817896
+16.76526901156049
+16.188152969010886
+16.995003433770833
+15.787000901497393
+17.346041018975882
+17.129768149751115
+17.111466288671394
+16.895697871867256
+16.63691011906414
+17.195839953375497
+17.046869263372457
+17.914429990753575
+16.678510006680668
+17.45121596926326
+18.894783753552375
+18.425920507538095
+16.08477286722885
+17.295728066178796
+17.759669602079086
+18.561101778995635
+18.02485157536212
+15.831857781378574
+15.551603533627642
+16.159015942152237
+18.48710782361546
+16.1535962836454
+16.87264021324941
+17.361386291461884
+17.498857268893275
+18.322026934696794
+15.345353158808436
+17.006614714773534
+17.2496387735561
+16.215333603209444
+18.09879702676126
+16.78484962626382
+14.674672947474946
+15.549562186783106
+17.240804239318194
+16.651815998478938
+16.95192848633927
+18.64482258383991
+17.568432262302437
+16.791406401618048
+16.894363644834314
+17.61416467251503
+15.27912514491085
+15.980173740933594
+16.538237357038966
+16.411936155601467
+16.53156660079081
+17.220783972067053
+16.72824593501609
+14.574061239715391
+17.074587739308924
+17.483247041494607
+16.716946056269933
+16.873372955083894
+18.376149440630897
+17.236082705441106
+15.956996967029042
+16.32511355781915
+17.778772352183523
+17.56311790191934
+16.197966879805804
+16.95590597330181
+17.254724831964282
+18.37853695391337
+17.742398274875725
+16.984497874734828
+16.691587823871856
+16.659363437601755
+16.284382665949423
+17.334107257979497
+16.107722165967573
+16.641576865920683
+15.640200314682588
+17.427879069766433
+16.701533126775203
+15.184822281312023
+14.894430346560185
+16.550928667346298
+16.404594106180852
+17.21291434355892
+15.032045674305024
+15.422508857539512
+15.953427784223905
+16.536489720260178
+16.03395619940953
+16.108268542551144
+15.42570275532971
+17.672438533341634
+17.74390716587793
+17.462186298382974
+16.266174625165604
+17.276715177611763
+18.183870206496877
+17.084285084659015
+18.12292306056999
+18.691306704101223
+18.40911803093674
+18.117255889496917
+15.274282099678786
+14.643995572179804
+16.96561814923861
+17.84824670533824
+17.88233434944911
+17.56620324600304
+15.640983756751055
+16.33442410522042
+17.290052143670223
+17.946007815345595
+16.11178238056921
+16.971292110397798
+16.580428275397992
+15.933110865786333
+17.023150451747398
+15.811179220889258
+14.554939016354766
+15.138844322409469
+15.490234994920769
+16.83118442215664
+15.88863695617519
+16.56201536815321
+15.413619120060105
+15.677330594779605
+16.51214257711146
+15.255182895438466
+14.725266421742731
+16.850298884474157
+18.463190050431038
+18.255907777485547
+16.05548309597539
+17.637478975715496
+18.602928951332856
+18.60876953280227
+16.55182321946205
+15.893850804522472
+16.366985378492657
+14.555243199882625
+17.744976179125416
+16.249548187112524
+17.217293287854247
+16.701069658667492
+16.467202412597842
+16.799912970874743
+14.672604174788802
+16.16112763531177
+16.482027408728655
+16.761768432584304
+15.724873903572814
+15.950745165504472
+17.38809939296455
+16.86425633006418
+16.738671870343367
+17.86355768351902
+15.694333051556569
+15.156885515121147
+15.924692573821446
+17.66829792113603
+17.694663200035876
+17.18220601753545
+17.78197621288527
+17.582584828859353
+18.25001726783816
+16.96664628926233
+16.756644782637707
+17.541137931921398
+14.233211507837254
+14.27919744667156
+15.076982303926215
+15.714365145727385
+17.680383418560027
+16.58553417929224
+16.183392308545166
+15.537657767389959
+15.158046253733616
+15.60283964721664
+17.216137798406223
+15.922749488227808
+16.45612413104375
+14.879197702184783
+15.428472194371551
+16.680787809276637
+15.24986160732304
+16.491680794460038
+16.252982458049246
+16.24171949093939
+15.340946431958685
+15.524755844421975
+15.467595785750163
+15.660860739812023
+18.052764895268368
+18.4272257609491
+16.76655859171609
+17.92449388758851
+15.960178001507572
+16.107838354743336
+13.313760065819963
+17.263053540088308
+16.717540553326657
+16.257369572688106
+17.220926867662413
+16.880523095929462
+16.93224963043488
+16.968411893041008
+17.278909319775465
+15.497314702851426
+17.028010187204288
+17.46832834953608
+15.971331405289547
+15.583178488584494
+16.472848088635956
+17.259704740787413
+15.94324324968305
+16.53711457948802
+16.215633081548887
+17.408717342281122
+17.23318733121144
+15.639122302278267
+14.731996550290674
+16.742280636198743
+17.37577773206543
+17.34354883566843
+16.373477135283636
+17.73600638367772
+16.490485269114785
+16.797202300842216
+17.072296061553672
+16.43199480613852
+17.2835550457918
+15.960898890768206
+16.29741464286313
+17.641404535743376
+17.06026069409944
+15.654847828251363
+16.365375804799925
+17.011715867692445
+15.963254615117023
+15.55777196245468
+16.235680043395988
+17.65114201025142
+18.049934014748928
+20.05084043508178
+17.90405499805445
+17.358538094867853
+17.565119610074007
+16.71566170708921
+16.79397596580877
+18.704763701543328
+17.13206287714719
+15.240234010735065
+16.853856659440652
+18.08758629076415
+16.149463536661614
+16.663310723624008
+16.501686378039167
+17.358629198065543
+16.570799435448578
+16.867776190122854
+16.248233905735532
+15.980457794224918
+17.18504029280649
+17.19053565620011
+16.972662018573672
+17.53704663992238
+17.454958728154082
+16.73784995552724
+17.00572249751373
+16.16636816722088
+17.048550728782388
+15.469971911768425
+16.815297534331663
+16.636977312553526
+16.6978390458557
+16.54710455738197
+15.98954256423147
+16.723711037675713
+15.586166666971877
+15.82235170150362
+17.280519848846367
+17.671561208965556
+16.594316742055597
+15.72232617021173
+16.035619587116997
+16.316361067776384
+17.253984390553825
+17.9783236884559
+16.900060086342663
+15.942718707922936
+18.350674330793893
+17.032679596125234
+20.655742202691883
+17.934030592974935
+18.28150022781476
+17.626077199900365
+16.40943649364762
+16.83362455135159
+16.786806121758715
+18.666511895641733
+18.313424260745947
+17.574019709559124
+16.546466411254627
+18.077784894302624
+17.085537128768706
+16.345545499535035
+16.051673326662666
+17.172754951858266
+18.450580636818728
+18.12779181877802
+16.910499499390923
+17.7727954252814
+17.63125752263099
+16.2830255633547
+17.062837982747183
+16.00898078347069
+17.003331090560295
+17.340905588507724
+16.60530229165684
+17.489419981417385
+16.129032856250248
+17.25654280765822
+17.35092320291797
+17.60226490106558
+17.636580541752224
+17.905643338430238
+17.569272536861774
+16.647591654513263
+17.425678353007285
+17.889934651148153
+17.54343229938594
+16.757121884311303
+16.092127426797134
+16.058809966654906
+17.465470259773085
+16.53970473022339
+17.57389801959907
+17.372147108606555
+16.655331958618532
+16.133722078195092
+17.902751890162804
+15.972246731154442
+18.003193570969017
+16.44651812202882
+17.098775567683205
+16.194895345803403
+15.416754519594903
+16.851926766897364
+17.534608620794913
+17.4918962426067
+16.00768624579287
+15.900700952801543
+17.455719527604245
+16.18664193326174
+16.260986788196718
+15.573555048809666
+14.628544074950867
+17.892934976304076
+17.0657002768194
+17.530438261414986
+16.67278038291869
+15.849912369132923
+17.81650879683417
+18.869821491441613
+17.87289716736231
+17.260695743956347
+15.801875724653158
+15.121309637939802
+16.28967208830541
+17.269367987850586
+17.55722834819352
+17.45811770509681
+18.042900359426923
+17.70946833285933
+17.788496716094414
+17.43790494430425
+17.886191069465454
+16.122638280463107
+17.45240453373374
+16.90615371447656
+18.03639531185634
+18.041518033893723
+16.972192066033998
+17.37715348419745
+17.75273126461387
+16.642717420999816
+15.614387397932674
+16.592416343646008
+15.859240912073432
+16.26647112283574
+15.934954179750704
+18.13529905065961
+18.820723045142515
+16.660220437967823
+16.480457893866244
+17.512880115151347
+17.07040570702499
+16.939362398844366
+17.567367127249398
+17.061390405395457
+17.09368927356722
+17.375769927602448
+16.536740760812293
+17.18686728114659
+17.85489936164781
+17.503694739213387
+17.123394351393387
+17.70589707591469
+17.04057153391112
+17.502251958629643
+17.987143455203963
+16.14770249681726
+17.82818428325102
+16.71812422239651
+16.826305821361032
+17.75973476069123
+16.87765311954213
+17.25008734896612
+16.688487067492687
+17.635038166403845
+18.45288072708918
+19.381291671894786
+17.3938265528012
+16.71187894341871
+16.962721845146362
+17.280343594574802
+16.70630389090435
+16.095204194944444
+15.910501511358461
+17.298713074824533
+16.639041694708595
+17.59714211339839
+16.81369808403565
+15.621370028920964
+16.75118306410799
+15.490165030901352
+17.68127580140478
+18.18199616740118
+17.743264678282856
+15.934467918705579
+15.276811900426495
+16.867551102000675
+16.785727676097665
+16.01760419499371
+15.178222610462583
+16.973641369573144
+17.374626158651708
+16.567312808729042
+17.799693056973453
+16.86105735622985
+16.843180210501387
+16.398135151645533
+16.75428172104118
+16.404521875919656
+17.92213255991267
+18.84770187462233
+18.624461475919873
+16.1460115931837
+17.55349189518826
+16.120157244638975
+17.201320447153677
+15.147485664821161
+15.67970546499464
+16.66784348020319
+17.514739466489388
+16.115033588102733
+15.38812792235359
+17.159673481813343
+17.746698503340227
+17.60552524016083
+17.5823739773154
+17.228196917654074
+17.504327814962778
+18.52561726924732
+17.417155434042414
+17.21810759817818
+17.25640728707333
+17.759871993119404
+17.20715585125589
+16.84562127868864
+15.709661391794427
+17.340343209795194
+15.920760920937838
+17.26256040385057
+17.771793989376377
+18.491078617612274
+16.779683205115234
+16.251073661090757
+17.586072431178096
+16.763052404972782
+16.771188046726422
+17.49151982709246
+18.567099392746158
+16.8439513851592
+16.067099118590406
+17.88106093653502
+17.773014250973546
+17.99370003335423
+18.34257302131155
+19.375239186147653
+18.190734258263802
+17.962689010321085
+16.911428356746654
+16.897720735623636
+16.619433676727837
+16.06608265737222
+15.753493876912145
+16.277770839879835
+17.189925964678707
+17.613864303549335
+16.13714503803739
+17.784624085587453
+19.16549473345225
+17.866902610153275
+17.339781523783742
+16.38662617723105
+17.228928242771772
+16.689900908406145
+16.254144959563405
+17.539773568649835
+18.242190122361706
+17.317729016380312
+17.02019549586292
+17.013044282785117
+16.61592242419401
+16.128974169765343
+14.975616023422987
+15.31637331707715
+17.399035779923977
+18.197013087541862
+18.42434860535512
+18.07055702682875
+17.131606928432703
+16.59195250993136
+17.151567224155627
+18.006689602253388
+16.779387345162178
+15.850225393819855
+15.977224659509048
+15.108165887520258
+16.54295510619525
+18.534514694251627
+18.429926804489867
+17.30620715273146
+18.150084303469214
+18.446056907557946
+16.98680133907304
+18.273000646092257
+17.231041606537318
+17.811833106644798
+16.437498523266783
+18.595207767645903
+17.948744862970514
+16.7345710995545
+16.573601999001966
+19.144760451617913
+18.858468198934787
+18.623531340757737
+17.042205986626342
+17.64778624466247
+17.00802175052081
+15.776385484567086
+17.175284848098045
+16.765146620339394
+15.718159773029527
+16.68454115375114
+17.07321115528208
+18.46959011429071
+16.352210228105818
+16.006078861023866
+17.493558841742043
+18.414828877583275
+17.85420009636475
+17.240405671270594
+17.52714526197495
+16.759381214416564
+17.11612096610459
+16.39356330864493
+17.008607658165687
+15.615760466203582
+17.14261606645435
+17.347485117791166
+16.377759224569687
+17.036724683113164
+17.509758365025064
+17.003852467652507
+14.948307158471735
+16.146347797083635
+16.56683907194416
+16.968334028834207
+17.155160344742555
+18.803564332398025
+17.431552542204898
+17.11608169751142
+16.077564014938574
+16.42935648807041
+16.325704701656804
+16.570079641627927
+16.732617820016145
+16.167320552301575
+17.100855802803338
+16.495526300677994
+17.157943450853338
+16.397639198003702
+16.628199115990256
+15.705389051325838
+16.775325752570055
+17.06700089489503
+16.83681806077159
+16.816217321984865
+17.75602048101979
+16.855827833408156
+17.638908901082274
+19.660316737417574
+18.870210983211848
+18.200158766418397
+17.369025674910688
+17.50837254671886
+16.587670574968186
+15.528654760794907
+16.909013854770166
+16.871328430694746
+16.573348642714194
+17.705983641426357
+16.13345079725589
+16.185477694995527
+16.96449978122756
+16.852123093575628
+17.825197677326813
+18.261374134349353
+16.677371175584
+15.68122224697548
+14.927300171968355
+16.51904902761366
+16.35776742151286
+17.187957624068403
+17.168025970129293
+17.503967878771178
+15.508235009707846
+18.53240666681127
+17.788121271547993
+17.230234618566968
+17.8607181576443
+17.63827024379934
+17.387999866053974
+16.62181983419994
+15.838203996612478
+16.33473810829983
+17.232556051247187
+17.559518798508748
+17.2192561650928
+17.55188204763259
+18.408474830120994
+18.583695486938353
+18.346537897556416
+15.82385901862689
+17.390525864193435
+17.2607238884233
+16.134996102558958
+17.420453654012178
+17.543037414295213
+15.716361700462144
+17.36160342976254
+17.444098813493
+16.93403647481543
+16.934148383865704
+15.396822331362031
+16.477819610498173
+16.389008891364142
+16.15889546612756
+16.869829022792047
+15.985846050986439
+16.478597532819506
+17.566469363718042
+16.5056293529652
+15.677839738984957
+18.75349830923895
+17.49788504715815
+17.178251058130627
+15.99075840198752
+15.587528232149452
+17.137437248612386
+16.198364810411547
+16.622753116450326
+16.704389278961898
+17.500318665445874
+17.770170224948956
+18.291674268139516
+17.69211967625033
+18.21379686043359
+17.083548012460597
+17.036903810180277
+16.636019971214438
+16.919259601898204
+15.90786228963637
+17.395272300565793
+15.596491197572647
+16.568526253994804
+15.898234577149466
+16.938380271932104
+17.247024906524715
+18.310389343471414
+17.36273621631777
+16.319901677207454
+16.153206011571427
+17.2098331611289
+16.570520771899297
+16.495481009828552
+16.222069840924334
+17.36786225110278
+17.85802590472754
+17.54338880226608
+15.201583477256662
+16.501296119462936
+18.54781551969586
+16.244185839208484
+16.651444406292214
+16.469859389623608
+16.60079231790027
+16.911612772090663
+17.047309724182384
+17.473461144251146
+17.1583917724586
+16.931801196395625
+17.361303262168676
+18.624742392248663
+18.57737252523951
+17.04425258796924
+15.167132417844996
+15.846515250826101
+15.745654161399543
+14.383998846586977
+17.045243136221558
+16.750772572288966
+16.04595308766183
+14.826506148906986
+15.333709691995082
+17.62621289883967
+16.678152979839794
+17.099143500947733
+18.314084797785654
+16.344774679363823
+18.83155296940066
+18.52722643442307
+18.75595616528811
+14.682256776395576
+16.436680232196537
+16.364968590702702
+15.904558309769783
+17.408597053403753
+15.823382265677111
+18.75643591338833
+17.046971078496398
+16.262813017377482
+17.407891140343978
+18.97094317350546
+18.073547906135644
+16.19906736899641
+17.326785353580163
+16.033881828720368
+17.050765424408482
+17.72325198175082
+16.746820775469374
+16.046969416211013
+16.290860727671813
+16.963340860003825
+17.25600629009591
+17.645636766405744
+17.28145647806575
+16.61604937245724
+16.79592662318366
+17.5945033822735
+17.66432550792061
+16.252855374249222
+17.106459725966246
+16.314349854150137
+17.765993952610913
+16.898565524559032
+19.357457011476484
+17.43756722487153
+17.98956291646823
+16.692136634429872
+18.14896950843017
+18.718785252062005
+17.262444788808992
+16.9172539219622
+17.009475758069485
+16.932919975230163
+15.61479419111113
+17.907114013461282
+16.84586631359322
+17.820642197565064
+15.560595249822853
+16.131235542034588
+15.99480935603539
+17.38465293348564
+19.02656745978723
+16.839001045383625
+17.349631591274132
+18.739135617395007
+17.595938195218366
+18.14492491443488
+15.995449192701699
+16.695291548416833
+18.569839732360464
+18.603185687944418
+17.67404023906478
+16.189159346387257
+17.77675362592487
+17.15046388245058
+19.011289159321606
+18.90309366546579
+16.78255384024048
+17.452159422550068
+16.687139732687044
+15.190651908970622
+14.757065575678112
+16.712439421020946
+15.970645634259427
+16.040283726522418
+18.19804967986117
+16.622998436596774
+18.406858588453545
+18.058261377665602
+17.16175868378251
+18.091704951095707
+19.100879530553968
+17.90189611371757
+16.495681794386996
+15.928750169139633
+16.647486974441236
+17.920104849195937
+16.553863523330918
+16.364603068887092
+16.820260864049388
+16.463282553334537
+18.778363633811978
+18.860103657814292
+17.94496606576452
+17.00930828515861
+15.677743769539873
+16.51923646668223
+17.239598954993582
+16.39749674552094
+16.07509776071042
+17.15827341265451
+18.205412534471392
+16.431049081980845
+17.772716395343323
+17.472761852877582
+18.10672239191601
+17.066091225490126
+17.24947733249617
+16.754931023144636
+17.32180699182358
+16.091668112213426
+15.649395820180331
+16.14604662040989
+16.4903047086908
+15.893229746688746
+17.15029806350782
+16.943263892603014
+17.107593544125223
+18.51661808434862
+18.138436878955005
+18.108919646922217
+16.43131915673736
+17.386286035230455
+18.15907631799263
+17.890750718451315
+18.764395907807895
+16.40768293787302
+17.861207074779244
+17.382001113708768
+16.00868649737366
+16.543819482164537
+16.65872689968147
+18.755557123669135
+17.59883677044202
+16.222975780043924
+16.686420907695904
+16.746010879929642
+17.65937017039805
+15.611090216330425
+17.22750016345185
+17.0701827957663
+16.886394656953925
+16.81291880276126
+16.349071741839865
+17.543021741854275
+15.88627696583346
+15.979124135709881
+16.54248133257275
+16.992078510530945
+16.290004852438685
+16.848755862860827
+15.879834471728103
+16.42291296485932
+15.14524127610936
+16.100796080556208
+17.041266714500566
+17.120103819090176
+17.53625134240002
+16.76419064569241
+15.842624761530502
+16.849495970436507
+17.084156523314775
+17.583979431448626
+17.168989348230227
+17.79312420796289
+17.966422759545267
+16.70360464898542
+16.73079622074296
+16.327547606648167
+17.151113772624328
+17.672236374688154
+15.677534208361322
+17.586323428397463
+17.16378652298758
+16.00665062146112
+18.20786987921757
+16.108148354004115
+15.96768465175974
+17.30693178880854
+16.44946318020557
+15.944269733982111
+14.646773285376156
+18.189490743144873
+17.28214953626106
+17.722227807317253
+16.05899632996858
+17.400533448964865
+16.844235300522612
+16.468051299149877
+17.61328948236259
+17.97360044237351
+19.12367285271624
+18.658711999982714
+18.522370382793525
+17.010583757397413
+16.30780149523528
+16.7963288022642
+16.90068113546654
+17.047090311189905
+17.960846293657468
+17.054657868680593
+18.742255994411195
+17.03467580415959
+15.641128501064117
+16.756644671946205
+19.049307895415453
+19.622542774952592
+19.390516610635117
+16.29206413102908
+15.566239809215688
+15.931551167965026
+18.329004060011314
+17.68076581504708
+17.10076394476964
+18.204196545688248
+16.608615485519678
+15.629635079462716
+17.153422953565453
+17.8113338260586
+17.111137957769927
+18.815792593018713
+18.267052281797163
+18.178116290222633
+18.273056000426678
+18.19599354253485
+13.421716729459447
+15.434554235503711
+16.074999702864673
+18.341495413892446
+17.148952452338946
+17.108586683110175
+16.617625627423294
+17.308555599714296
+16.416696471311596
+17.00184410744538
+16.621321288657228
+19.312155892955545
+16.707950038953783
+17.25348690726986
+17.640441609621874
+18.022594182421983
+17.28776161560755
+16.776103342374626
+14.70620804103126
+16.065784275572113
+17.857973041460866
+16.82705732639448
+17.366487735412434
+16.387267082676615
+15.261653267484562
+17.784177179654748
+17.06297687280214
+17.017586985604098
+17.162601689900583
+17.194089754617863
+16.783910593011598
+17.102578680452112
+16.194370085554567
+15.477930580889492
+16.612996866228414
+16.625092326040985
+16.71884000401927
+15.934359905431677
+16.41900725804824
+16.447083181726825
+17.237742348903723
+16.087372016268958
+16.24000809276687
+16.16928477172671
+18.4567469076579
+18.862274200167434
+16.69053989690937
+18.38004455282615
+16.667890848841935
+17.046516874267965
+16.127944427556983
+17.938813545706054
+18.221412551343477
+15.656851892688152
+16.81670948880766
+16.58869811392988
+17.420126644419028
+17.015615656138735
+17.38446270504899
+17.69419437225865
+17.588752979642678
+17.49704227452976
+18.746252661644306
+17.233478129522055
+17.17015019913272
+16.775414049865574
+18.06452036192688
+17.24045358652016
+17.085279790549194
+16.560513475536723
+17.482960435615666
+17.582560903623957
+16.721648284940542
+16.549034437340353
+17.45356678646037
+17.144104209517067
+17.48509891890336
+17.77832733619762
+16.864679408774066
+18.117035654168603
+17.82899813951356
+16.498934838124953
+17.977868329495607
+17.884355170952333
+17.584188155002707
+16.379296327635743
+17.303573416443612
+17.35471923580691
+17.19936854059395
+17.53064190571618
+17.344396105534898
+16.84828552324457
+18.45485717450721
+19.59218441119708
+24.71534708355462
+17.57562356067207
+19.026966024992433
+17.494869515674722
+17.21200137909655
+18.33893535166999
diff --git a/dwtest/polynomial_formatVersion0.Polynomial b/dwtest/polynomial_formatVersion0.Polynomial
new file mode 100644
index 0000000..e9aa9ce
--- /dev/null
+++ b/dwtest/polynomial_formatVersion0.Polynomial
@@ -0,0 +1,11 @@
+File type = "ooTextFile"
+Object class = "Polynomial"
+
+xmin = -3 
+xmax = 4 
+numberOfCoefficients = 4 
+coefficients []: 
+    coefficients [1] = 2 
+    coefficients [2] = -1 
+    coefficients [3] = -2 
+    coefficients [4] = 1 
diff --git a/dwtest/test_DataModeler.praat b/dwtest/test_DataModeler.praat
new file mode 100644
index 0000000..b48aba0
--- /dev/null
+++ b/dwtest/test_DataModeler.praat
@@ -0,0 +1,101 @@
+# test_DataModeler.praat
+# djmw 20161011
+
+appendInfoLine: "test_DataModeler.praat"
+
+
+ at testDataModelerInterface
+
+appendInfoLine: "test_DataModeler.praat OK"
+
+procedure testDataModelerInterface
+	# create a table for model y = 2x +3
+	.xmin = -1
+	.xmax = 3
+	.nx = 100
+	@createData: .xmin, .xmax, .nx, 0
+	.table = selected ("Table")
+	.maximumPolynomialOrder = 3
+	.dm = To DataModeler: .xmin, .xmax, "x", "y", "", "Legendre polynomials", .maximumPolynomialOrder
+	#
+	# Query -
+	#
+	.numberOfParameters = Get number of parameters
+	assert .numberOfParameters = .maximumPolynomialOrder + 1
+	.numberOfFixedParameters = Get number of fixed parameters
+	assert .numberOfFixedParameters = 0
+	for .ipar to .numberOfParameters
+		.value = Get parameter value: .ipar
+		.stdev = Get parameter standard deviation: .ipar
+		.status$ = Get parameter status: .ipar
+		.status$ = mid$ (.status$, 1, 4)
+		assert .status$ = "Free"
+		Set parameter value: .ipar, .value, .status$
+		.value2 = Get parameter value: .ipar
+		assert .value = .value2
+		for .ipar2 from .ipar to .numberOfParameters
+			.var = Get variance of parameters: .ipar, .ipar2
+		endfor
+	endfor
+	.valxmin = Get model value at x: .xmin
+	.valxmax = Get model value at x: .xmax
+	.numberOfDataPoints = Get number of data points
+	.numberOfInvalidDataPoints = Get number of invalid data points
+	for .idata to .numberOfDataPoints
+		.statusdata$ = Get data point status: .idata
+		assert mid$ (.statusdata$, 1, 5) = "Valid"
+
+		.savex = Get data point x value: .idata
+		.set = randomUniform (.xmin, .xmin)
+		Set data point x value: .idata, .set
+		.get = Get data point x value: .idata
+		assert .set = .get; ['.idata'] '.set' = '.get'
+		Set data point x value: .idata, .savex
+
+		.savey = Get data point y value: .idata
+		.set = randomUniform (.xmin, .xmin)
+		Set data point y value: .idata, .set
+		.get = Get data point y value: .idata
+		assert .set = .get; ['.idata'] '.set' = '.get'
+		Set data point y value: .idata, .savey
+
+		.saves = Get data point y sigma: .idata
+		.set = randomUniform (1, 10)
+		Set data point y sigma: .idata, .set
+		.get = Get data point y sigma: .idata
+		assert .set = .get; ['.idata'] '.set' = '.get'
+		Set data point y sigma: .idata, .saves
+		
+	endfor
+	.sumOfSquares_res = Get residual sum of squares
+	.dataStdDev = Get data standard deviation
+	.coef = Get coefficient of determination
+	.chiSqReport$ = Report chi squared: "Equally"
+	.ndf = Get degrees of freedom
+	#
+	# Modify -
+	#
+	Set data weighing: "Equally"
+	Set tolerance: 1e-5
+	# Set parameter value: see query part
+	Set parameter free: 0, 0
+	#
+	Fit model
+	.covar = To Covariance (parameters)
+	selectObject: .dm
+	.zscores = To Table (z-scores): "yes"
+	removeObject: .zscores, .covar, .table, .dm
+endproc
+
+procedure createData: .xmin, .xmax, .nx, .ynoise_stdev
+	.model = Create Table with column names: "table", .nx, "x y"
+	# linear
+	.dx = (.xmax -.xmin) / (.nx - 1)
+	for .row to .nx
+		.x = .xmin + (.row -1) * .dx
+		.y = 2 * .x + 3 + randomGauss (0, .ynoise_stdev)
+		Set numeric value: .row, "x", .x
+		Set numeric value: .row, "y", .y
+	endfor
+endproc
+
diff --git a/dwtest/test_Eigen.praat b/dwtest/test_Eigen.praat
new file mode 100644
index 0000000..5187df6
--- /dev/null
+++ b/dwtest/test_Eigen.praat
@@ -0,0 +1,50 @@
+# test_Eigen.praat
+# djmw 20161116
+
+appendInfoLine: "test_Eigen.praat"
+
+ at testInterface
+
+procedure testInterface
+	for .i to 5
+		.numberOfColumns = randomInteger (3, 12)
+		.tableofreal = Create TableOfReal: "t", 100, .numberOfColumns
+		Formula: "randomGauss (0, 1)"
+		.pca = To PCA
+		.eigen = Extract Eigen
+		.numberOfEigenvalues = Get number of eigenvalues
+		assert .numberOfEigenvalues == .numberOfColumns
+		.dimension = Get eigenvector dimension
+		assert .dimension == .numberOfColumns
+		for .j to .numberOfEigenvalues
+			.eigenvalue [.j] = Get eigenvalue: .j
+		endfor
+		for .j to .numberOfEigenvalues
+			.sump = Get eigenvalue: .j
+			for .k from .j to .numberOfEigenvalues
+				.sum = Get sum of eigenvalues: .j, .k
+				assert .sum >= .eigenvalue [.j]
+			endfor
+		endfor
+
+		for .j to .numberOfEigenvalues
+			for .k from .j to .dimension
+				.val[.j,.k] = Get eigenvector element: .j, .k
+			endfor
+		endfor
+		for .j to .numberOfEigenvalues
+			for .k to .dimension
+				.val[.k] = Get eigenvector element: .j, .k
+			endfor
+			Invert eigenvector: .j
+			for .k to .dimension
+				.valk = Get eigenvector element: .j, .k
+				assert .valk == - .val[.k]
+			endfor	
+		endfor
+		removeObject: .tableofreal, .pca, .eigen
+	endfor
+endproc
+	
+appendInfoLine: "test_Eigen.praat OK"	
+
diff --git a/dwtest/test_FFNet.praat b/dwtest/test_FFNet.praat
index ee2058d..23601c5 100644
--- a/dwtest/test_FFNet.praat
+++ b/dwtest/test_FFNet.praat
@@ -8,6 +8,11 @@ ffnet = selected ("FFNet")
 pattern = selected ("Pattern")
 cat = selected ("Categories")
 
+selectObject: ffnet
+ at testInterface: 0
+ at testInterface: 1
+ at testInterface: 2
+
 selectObject: pattern, cat
 tab = To TableOfReal
 To Pattern and Categories: 0, 0, 0, 0
@@ -75,4 +80,64 @@ procedure test_openSave
 	removeObject: 	.ffnet, .ffnet_read, .ffnet_read2, .pattern, .categories
 endproc
 
+procedure testInterface: .numberOfHiddenLayers
+	.numberOfInputs_set = randomInteger (2, 5)
+	.numberOfOutputs_set = randomInteger (2, 5)
+	.name$ = string$ (.numberOfInputs_set)
+	for .layer to 2
+		.numberOfHiddenUnits_set [.layer] = 0
+		.numberOfUnits = randomInteger (2, 10)
+		if .layer <= .numberOfHiddenLayers
+			.numberOfHiddenUnits_set [.layer] = .numberOfUnits
+			.name$ = .name$ + "-" + string$ (.numberOfUnits)
+		endif
+	endfor
+	.name$ = .name$ + "-" + string$ (.numberOfOutputs_set)
+	.ffnet = Create FFNet: .name$, .numberOfInputs_set, .numberOfOutputs_set, .numberOfHiddenUnits_set [1], .numberOfHiddenUnits_set [2]
+	
+	appendInfoLine: tab$, "interface test for topology " + .name$
+	appendInfoLine: tab$, tab$, "Query & Modify"
+
+	.numberOfLayers = Get number of layers
+	appendInfoLine: .numberOfLayers
+	.numberOfOutputs = Get number of outputs
+	.numberOfUnitsInPreviousLayer = Get number of inputs
+	for .ilayer to .numberOfLayers - 1
+		.numberOfHiddenUnits = Get number of hidden units: .ilayer
+		assert .numberOfHiddenUnits == .numberOfHiddenUnits_set [.ilayer]; "layer = "'.ilayer'
+		for .iunit to .numberOfHiddenUnits
+			.value_set = randomUniform (-0.1, 0.1)
+			Set bias: .ilayer, .iunit, .value_set
+			.value_get = Get bias: .ilayer, .iunit
+			assert .value_get == .value_set; bias '.ilayer', '.iunit', '.value_set'
+			for .punit to .numberOfUnitsInPreviousLayer
+				.value_set = randomUniform (-0.1, 0.1)
+				Set weight: .ilayer, .iunit, .punit, .value_set
+				.value_get = Get weight: .ilayer, .iunit, .punit
+				assert .value_get == .value_set; '.ilayer', '.iunit', '.punit', '.value_set'
+			endfor
+		endfor
+		.numberOfUnitsInPreviousLayer = .numberOfHiddenUnits
+		.numberOfHiddenWeights = Get number of hidden weights: .ilayer
+		Select biases: .ilayer
+		Select all weights
+	endfor
+	.numberOfOutputWeights = Get number of output weights
+	for .iunit to .numberOfOutputs
+		.outputCategory$ = Get category of output unit: .iunit
+		.outputUnit = Get output unit of category: "xpiepeledokie"
+		assert .outputUnit == 0; '.outputUnit'
+	endfor
+	.minimum = Get minimum
+
+	appendInfoLine: tab$, tab$, "Extract"
+
+	for .ilayer to .numberOfLayers - 1
+		selectObject: .ffnet
+		.tableOfReal = Extract weights: .ilayer
+		removeObject: .tableOfReal
+	endfor
+	removeObject: .ffnet
+endproc
+
 
diff --git a/dwtest/test_KlattGrid.praat b/dwtest/test_KlattGrid.praat
index 7f07893..407ca10 100644
--- a/dwtest/test_KlattGrid.praat
+++ b/dwtest/test_KlattGrid.praat
@@ -123,7 +123,7 @@ for i to nPhonationTiers
 
 	tier = Extract 'tier$' tier
 	Remove
-	printline ... 'tier$'
+	printline 'tab$'... 'tier$'
 endfor
 
 for i from nPhonationTiers+1 to 25
@@ -132,7 +132,7 @@ for i from nPhonationTiers+1 to 25
 	vmin =  Object_'t' [i, "min"]
 	vmax =  Object_'t' [i, "max"]
 	nf = Object_'t' [i, "nf"]
-	print ... 'tier$'
+	print 'tab$'... 'tier$'
 	for ifor from 1 to nf
 		select kg
 		for itime to ntimes
@@ -150,7 +150,7 @@ for i from nPhonationTiers+1 to 25
 		grid$ = replace$ (tier$, " frequency", "", 1)
 		grid$ = replace$ (grid$, " bandwidth", "", 1)
 		grid = Extract 'grid$' grid
-		print  'ifor'
+		print  'tab$''ifor'
 		Remove
 	endfor
 	print 'newline$'
diff --git a/dwtest/test_LPC.praat b/dwtest/test_LPC.praat
index ba2778d..b4a6782 100644
--- a/dwtest/test_LPC.praat
+++ b/dwtest/test_LPC.praat
@@ -3,6 +3,8 @@
 
 printline test_LPC
 
+ at testLPCInterface
+
 # formants of straigth tube
 
 for i to 5
@@ -67,7 +69,7 @@ printline test_LPC OK
 
 procedure get_formants .lpc .method$
 	select .lpc
-	.f = To Formant (keep all)
+	.formant = To Formant (keep all)
 	deltaf = 0
 	deltab = 0
 	for .nf to 5
@@ -80,8 +82,76 @@ procedure get_formants .lpc .method$
 	endfor
 	deltaf /= 3
 	deltab /= 3
-	printline deltaf = 'deltaf:4' deltab = 'deltab:4' '.f[1]:0' '.b[1]:0' '.f[2]:0' '.b[2]:0' '.f[3]:0' '.b[3]:0' '.f[4]:0' '.b[4]:0' '.f[5]:0' '.b]5:0' ('.method$')
-	select .f
-	Remove
+	appendInfoLine: tab$, .method$,  " deltaf = ", fixed$ (deltaf, 4), " deltab = ", fixed$ (deltab, 4), 
+	... 	" ", fixed$ (.f[1], 0), " ", fixed$ (.b[1], 0), " ", fixed$ (.f[2], 0), " ", fixed$ (.b[2], 0),
+	...	" ", fixed$ (.f[3], 0), " ", fixed$ (.b[3], 0), " ", fixed$ (.f[4], 0), " ", fixed$ (.b[4], 0), 
+	...	" ", fixed$ (.f[5], 0), " ", fixed$ (.b[5], 0)
+	removeObject: .formant
 endproc
 
+procedure testLPCInterface
+	.sound = Create Sound from formula: "noise", 1, 0, 1, 10000, "randomGauss(0,0.1)"
+	.lpc = To LPC (autocorrelation): 10, 0.025, 0.005, 50
+
+	appendInfoLine: tab$, "test LPC interface"
+	appendInfoLine: tab$, tab$, "Query"
+	.startTime = Get start time
+
+	.t1 = Get time from frame number: 1
+	.endTime = Get end time
+	.totalDuration = Get total duration
+	.numberOfFrames = Get number of frames
+	.timeStep = Get time step
+	for .iframe to .numberOfFrames
+		.time = Get time from frame number: .iframe
+		.frameNumber = Get frame number from time: .time
+		.numberOfCoefficients = Get number of coefficients: .iframe
+	endfor
+	.samplingInterval = Get sampling interval
+
+	appendInfoLine: tab$, tab$, "Modify"
+	Shift times by: randomUniform (0.1, 0.9)
+	Shift times to: "start time", .startTime
+	Shift times to: "centre time", .startTime
+	Shift times to: "end time", .endTime
+	Scale times by: randomUniform (0.5, 2.5)
+	Scale times to: .startTime, .endTime
+
+	appendInfoLine: tab$, tab$, "Extract"
+	for .i to 10
+		selectObject: .lpc
+		.bandwidthReduction = randomUniform (0, 200)
+		.time = randomUniform (.startTime, .endTime)
+		.spectrum = To Spectrum (slice): .time, 20, .bandwidthReduction, 50
+		selectObject: .lpc
+		.vocalTract1 = To VocalTract (slice): .time, 17.0
+		selectObject: .lpc
+		.glottalDamping = randomUniform (0.01, 0.4)
+		.radiationDamping$ = if randomUniform (0,1) > 0.5 then "yes" else "no" fi
+		.internalDamping$ = if randomUniform (0,1) > 0.5 then "yes" else "no" fi
+		.vocalTract2 = To VocalTract (slice, special): .time, .glottalDamping, .radiationDamping$, .internalDamping$
+		selectObject: .lpc
+		.polynomial = To Polynomial (slice): .time
+		removeObject: .spectrum, .vocalTract1, .vocalTract2, .polynomial
+	endfor
+	selectObject: .lpc
+	.matrix = Down to Matrix (lpc)
+	removeObject: .matrix
+
+	appendInfoLine: tab$, tab$, "Analyse"
+	selectObject: .lpc
+	.formant1 = To Formant
+	selectObject: .lpc
+	.formant2 = To Formant (keep all)
+	for .numberOfCoefficients to 12
+		selectObject: .lpc
+		.lfcc = To LFCC: .numberOfCoefficients
+		removeObject: .lfcc
+	endfor
+	selectObject: .lpc
+	.spectrogram = To Spectrogram: 20, 0, 50
+	selectObject: .lpc
+	.lineSpectralFrequencies = To LineSpectralFrequencies: 0.0
+	removeObject: .spectrogram, .formant1, .formant2, .lineSpectralFrequencies, .sound, .lpc
+endproc
+	
diff --git a/dwtest/test_MDS.praat b/dwtest/test_MDS.praat
index 37daa6b..23e452f 100644
--- a/dwtest/test_MDS.praat
+++ b/dwtest/test_MDS.praat
@@ -1,112 +1,283 @@
 # test_MDS.praat
 
-printline test MDS
-
-dr = Create letter R example... 0
-
-c[1] = To Configuration (monotone mds)... 2 "Primary approach" 1e-05 50 1
-select dr
-c[2] = To Configuration (i-spline mds)... 2 1 1 1e-05 50 1
-select dr
-c[3] = To Configuration (interval mds)... 2 1e-05 50 1
-select dr
-c[4] = To Configuration (ratio mds)... 2 1e-05 50 1
-select dr
-c[5] = To Configuration (absolute mds)... 2 1e-05 50 1
-select dr
-c[6] = To Configuration (kruskal)... 2 2 "Primary approach" Formula1 1e-05 50 1
-
-selectObject: dr, c[1]
-c[6+1]= To Configuration (monotone mds): "Primary approach", 1e-7, 50, 1
-
-selectObject: dr, c[2]
-c[6+2] = To Configuration (i-spline mds): 1, 1, 1e-07, 50, 1
-selectObject: dr, c[3]
-c[6+3] = To Configuration (interval mds): 1e-05, 50, 1
-selectObject: dr, c[4]
-c[6+4] = To Configuration (ratio mds): 1e-05, 50, 1
-selectObject: dr, c[5]
-c[6+5] = To Configuration (absolute mds): 1e-05, 50, 1
-selectObject: dr, c[6]
-c[6+6] = To Configuration (kruskal): "Primary approach", "Formula1", 1e-05, 50, 1
-
-
-printline ... comparing configurations
-for i from 2 to  6
-	select c[1]
-	plus c[i]
-	p1 = To Procrustes... no
-	plus c[i]
-	ct[i] = To Configuration
-	plus c[1]
-	p2 = To Procrustes... no
-	call check_if_identity_transform  p2
-	plus p1
-	Remove
-endfor
-ct[1] = c[1]
-printline .... INDSCAL
-select c[1]
-for i from 2 to 6
-	plus ct[i]
-endfor
-To Distance
-for i to 6
-	dist[i] = selected ("Distance", i)
-endfor
+appendInfoLine: "test_MDS.praat"
 
-To Configuration (indscal)... 2 yes 1e-5 100 1
-ic[1] = selected ("Configuration")
-is[1] = selected ("Salience")
+ at testDissimilarityInterface
+# side effect: 6 configurations in the list of obects: configuration[1]...configuration[6]
+# testINDSCAL uses these 6 configurations
+ at testINDSCAL
+ at testProcrustus
 
-selectObject: ic[1]
 for i to 6
-	plusObject: dist[i]
+	removeObject: configuration [i]
 endfor
 
-To Configuration (indscal): "yes", 1e-5, 100
-ic[2] = selected ("Configuration")
-is[2] = selected ("Salience")
-
-select c[1]
-plus ic[1]
-p3 = To Procrustes... no
-plus ic[1]
-cp3 = To Configuration
-plus c[1]
-p4 = To Procrustes... no
-call check_if_identity_transform  p4
-
-select dr
-plusObject: ic[1], ic[2]
-plusObject: is[1], is[2]
-plus p3
-plus p4
-plus cp3
-for i to 6
-	plus c[i]
-	plus c[i+6]
-	plus ct[i]
-	plus dist[i]
-endfor
-Remove
-printline test MDS ok
+appendInfoLine: "test_MDS.praat OK"
 
-procedure check_if_identity_transform  .p
-	select .p
+procedure testProcrustus
+	appendInfoLine: tab$,  tab$, "Configuration & Configuration"
+	for .i from 2 to  6
+		selectObject: configuration [1]
+		plusObject: configuration [.i]
+		.procrustus [1] = To Procrustes: "no"
+		plusObject: configuration [.i]
+		.ct [.i] = To Configuration
+		plusObject: configuration [1]
+		.procrustus [2] = To Procrustes... no
+		@check_if_identity_transform: .procrustus [2]
+		removeObject: .procrustus [1], .procrustus [2]
+	endfor
+	for .i from 2 to 6
+		removeObject: .ct [.i]
+	endfor
+endproc
+
+procedure check_if_identity_transform:  .p
+	selectObject: .p
 	.scale = Get scale
 	assert .scale > 1 - 1e-4
 	for .j to 2
-		tj = Get translation element... .j
-		assert abs(tj) < 1e-6
+		.tj = Get translation element: .j
+		assert abs(.tj) < 1e-6
 		for .k to 2
-			tjk = Get transformation element... .j .k
+			.tjk = Get transformation element: .j, .k
 			if .j = .k
-				assert tjk > 1 - 1e-4
+				assert .tjk > 1 - 1e-4
 			else
-				assert abs(tjk) < 1e-6
+				assert abs(.tjk) < 1e-6
 			endif
 		endfor
 	endfor
 endproc
 
+procedure testDissimilarityInterface
+	appendInfoLine: tab$, "test interface"
+	appendInfoLine: tab$, tab$, "Query"
+	.dissimilarity = Create letter R example: 0
+	.numberOfRows = Get number of rows
+	.numberOfColumns = Get number of columns
+	for .irow to .numberOfRows
+		.rowLabel$ = Get row label: .irow
+		.rowIndex = Get row index: .rowLabel$
+		assert .irow = .rowIndex; '.irow' '.rowIndex'
+	endfor
+	for .icol to .numberOfColumns
+		.columnLabel$ = Get column label: .icol
+		.columnIndex = Get column index: .columnLabel$
+		assert .icol = .columnIndex; '.icol' '.columnIndex'
+	endfor
+	for .irow to .numberOfRows
+		for .icol to .numberOfColumns
+			val = Get value: .irow, .icol
+		endfor
+	endfor
+	.norm = Get table norm
+	.additiveConstant = Get additive constant
+
+	appendInfoLine: tab$, tab$, "Modify: skipped"
+	appendInfoLine: tab$, tab$, "Synthesize: skipped"
+
+	appendInfoLine: tab$, tab$, "Extract part"
+	selectObject: .dissimilarity
+	.tmp1 = Extract row ranges: "1 2"
+	.numberOfRows1 = Get number of rows
+	assert .numberOfRows1 == 2; '.numberOfRows1' "= 2"
+	selectObject: .dissimilarity
+	.tmp2 = Extract rows where: "1"
+	.numberOfRows2 = Get number of rows
+	.numberOfColumns2 = Get number of columns
+	assert .numberOfRows2 == .numberOfRows; '.numberOfRows2' "==" '.numberOfRows'
+	assert .numberOfColumns2 == .numberOfColumns; '.numberOfColumns2' "==" '.numberOfColumns'
+	selectObject: .dissimilarity
+	.tmp3 = Extract column ranges: "1 2"
+	.numberOfColumns3 = Get number of columns
+	assert .numberOfColumns3 == 2; '.numberOfColumns3' "= 2"
+	selectObject: .dissimilarity
+	.tmp4 = Extract columns where: "1"
+	.numberOfRows4 = Get number of rows
+	.numberOfColumns4 = Get number of columns
+	assert .numberOfRows4 == .numberOfRows; '.numberOfRows4' "==" '.numberOfRows'
+	assert .numberOfColumns4 == .numberOfColumns; '.numberOfColumns4' "==" '.numberOfColumns'
+	removeObject: .tmp1, .tmp2, .tmp3, .tmp4
+	for .irow to .numberOfRows
+		selectObject: .dissimilarity
+		.rowLabel$ = Get row label: .irow
+		.tmpi = Extract rows where label: "is equal to", .rowLabel$
+		.numberOfRows5 = Get number of rows
+		assert .numberOfRows5 >= 1
+		removeObject: .tmpi
+	endfor
+	for .icol to .numberOfColumns
+		selectObject: .dissimilarity
+		.columnLabel$ = Get column label: .icol
+		.tmpi = Extract columns where label: "is equal to", .columnLabel$
+		.numberOfColumns6 = Get number of columns
+		assert .numberOfColumns6 >= 1
+		removeObject: .tmpi
+	endfor
+
+	appendInfoLine: tab$, tab$, "Extract"
+	selectObject: .dissimilarity
+	.strings1 = Extract row labels as Strings
+	.numberOfStrings = Get number of strings
+	assert .numberOfStrings == .numberOfRows
+	selectObject: .dissimilarity
+	.strings2 = Extract column labels as Strings
+	.numberOfStrings = Get number of strings
+	assert .numberOfStrings == .numberOfColumns
+	removeObject: .strings1, .strings2
+
+	appendInfoLine: tab$, tab$, "Convert"
+	selectObject: .dissimilarity
+	.table = To Table: "col1"
+	.numberOfColumnsT = Get number of columns
+	assert .numberOfColumnsT = .numberOfColumns + 1
+	selectObject: .dissimilarity
+	.matrix = To Matrix
+	.numberOfRowsM = Get number of rows
+	.numberOfColumnsM = Get number of columns
+	assert .numberOfRowsM == .numberOfRows
+	assert .numberOfColumnsM == .numberOfColumns
+	selectObject: .dissimilarity
+	.tableOfReal = To TableOfReal
+	.numberOfRowsT = Get number of rows
+	.numberOfColumnsT = Get number of columns
+	assert .numberOfRowsT == .numberOfRows
+	assert .numberOfColumnsT == .numberOfColumns
+	removeObject: .table, .matrix, .tableOfReal
+
+	appendInfoLine: tab$, tab$, "To Configuration"
+	selectObject: .dissimilarity
+	for .ipar to 6
+		.numberOfDimensions$ [.ipar] = "2, "
+	endfor
+	.numberOfDimensions$[6] = "2, 2, "
+	.minimizationParameters$ = "1e-05, 10, 1"
+	.mdsCommand$ [1] = "To Configuration (monotone mds): "
+	.extraParameters$ [1] = """Primary approach"", "
+	.mdsCommand$ [2] = "To Configuration (i-spline mds): "
+	.extraParameters$ [2] = "1, 1, "
+	.mdsCommand$ [3] = "To Configuration (interval mds): "
+	.extraParameters$ [3] = ""
+	.mdsCommand$ [4] = "To Configuration (ratio mds): "
+	.extraParameters$ [4] = ""
+	.mdsCommand$ [5] = "To Configuration (absolute mds): "
+	.extraParameters$ [5] = ""
+	.mdsCommand$ [6] = "To Configuration (kruskal): "
+	.extraParameters$ [6] = """Primary approach"", ""Formula1"", "
+	
+	# Create a random configuration
+	.command$ = .mdsCommand$ [1] + .numberOfDimensions$ [1] + .extraParameters$ [1] + .minimizationParameters$
+	.randomConfiguration = '.command$'
+	Formula: "randomUniform (-1,1)"
+
+	for .itype to 6
+		selectObject: .dissimilarity
+		.command$ = .mdsCommand$ [.itype] + .numberOfDimensions$ [.itype] + .extraParameters$ [.itype] + .minimizationParameters$
+		configuration[.itype] = '.command$'
+	endfor
+
+	appendInfoLine: tab$, tab$, "Dissimilarity & Configuration"
+	.minimizationParameters$ = "1e-08, 50, 1"
+	for .itype to 6
+		selectObject: .dissimilarity, configuration[.itype]
+		.command$ = .mdsCommand$ [.itype] + .extraParameters$ [.itype] + .minimizationParameters$
+		.configuration [.itype] = '.command$'
+	endfor
+
+	.stressMeasure$ [1] = "Normalized"
+	.stressMeasure$ [2] = "Kruskal's stress-1"
+	.stressMeasure$ [3] = "Kruskal's stress-2"
+	.stressMeasure$ [4] = "Raw"
+	.tiesHandling$[1] = "Primary approach"
+	.tiesHandling$[2] = "Secondary approach"
+	.stressCalculation$ [1] = "Formula1"
+	.stressCalculation$ [2] = "Formula2"
+	for .i to 2
+		for .k to 2
+			selectObject: .dissimilarity, .randomConfiguration
+			.stress0 = Get stress (monotone mds): .tiesHandling$[.i], .stressMeasure$ [.k]
+			selectObject: .dissimilarity, configuration [1]
+			.stress1 = Get stress (monotone mds): .tiesHandling$[.i], .stressMeasure$ [.k]
+			assert .stress1 <= .stress0
+			selectObject: .dissimilarity, .configuration [1]
+			.stress2 = Get stress (monotone mds): .tiesHandling$[.i], .stressMeasure$ [.k]
+			assert .stress2 <= .stress1
+		endfor
+	endfor
+	for .k to 4
+		selectObject: .dissimilarity, .randomConfiguration
+		.stress0 = Get stress (i-spline mds): 1, 3, .stressMeasure$ [.k]
+		selectObject: .dissimilarity, configuration [2]
+		.stress1 = Get stress (i-spline mds): 1, 3, .stressMeasure$ [.k]
+		assert .stress1 <= .stress0
+		selectObject: .dissimilarity, .configuration [2]
+		.stress2 = Get stress (i-spline mds): 1, 3, .stressMeasure$ [.k]
+		assert .stress2 <= .stress1; '.stress2' '.stress1' '.k'
+	endfor
+	for .k from 1 to 4
+		selectObject: .dissimilarity, .randomConfiguration
+		.stress10 = Get stress (interval mds): .stressMeasure$ [.k]
+		selectObject: .dissimilarity, configuration [3]
+		.stress11 = Get stress (interval mds): .stressMeasure$ [.k]
+		assert .stress11 <= .stress10
+		selectObject: .dissimilarity, .configuration [3]
+		.stress12 = Get stress (interval mds): .stressMeasure$ [.k]
+		assert .stress12 <= .stress11
+		selectObject: .dissimilarity, .randomConfiguration
+		.stress20 = Get stress (ratio mds): .stressMeasure$ [.k]
+		selectObject: .dissimilarity, configuration [4]
+		.stress21 = Get stress (ratio mds): .stressMeasure$ [.k]
+		assert .stress21 <= .stress20
+		selectObject: .dissimilarity, .configuration [4]
+		.stress22 = Get stress (ratio mds): .stressMeasure$ [.k]
+		assert .stress22 <= .stress21
+		selectObject: .dissimilarity, .randomConfiguration
+		.stress30 = Get stress (absolute mds): .stressMeasure$ [.k]
+		selectObject: .dissimilarity, configuration [5]
+		.stress31 = Get stress (absolute mds): .stressMeasure$ [.k]
+		assert .stress31 <= .stress30
+		selectObject: .dissimilarity, .configuration [5]
+		.stress32 = Get stress (absolute mds): .stressMeasure$ [.k]
+		assert .stress32 <= .stress31
+	endfor
+
+
+	for .itype to 6
+		removeObject: .configuration[.itype]
+	endfor
+
+	removeObject: .dissimilarity, .randomConfiguration
+endproc
+
+procedure dissimilarity_to_Configurations: .dissimilarity
+
+endproc
+
+procedure testINDSCAL
+	for .i  to 6
+		selectObject: configuration [.i]
+		.distance [.i] = To Distance
+	endfor
+
+	selectObject: .distance [1]
+	for .i from 2 to 6
+		plusObject: .distance [.i]
+	endfor
+
+	To Configuration (indscal): 2, "no", 1e-5, 10, 1, "yes", "no"
+	.configuration = selected ("Configuration")
+	.salience = selected ("Salience")
+
+	# test old interface
+	;To Configuration (indscal): "no", 1e-5, 10
+	;.configuration2 = selected ("Configuration")
+	;.salience2 = selected ("Salience")
+	;removeObject: .configuration2, .salience2
+
+	for .i from 1 to 6
+		removeObject: .distance[.i]
+	endfor
+
+	removeObject: .configuration, .salience
+endproc
diff --git a/dwtest/test_angle_between_planes.praat b/dwtest/test_angle_between_planes.praat
index 6b29d8b..9155f24 100644
--- a/dwtest/test_angle_between_planes.praat
+++ b/dwtest/test_angle_between_planes.praat
@@ -1,13 +1,14 @@
 # test_angle_between_planes
 # djmw 20041021, 20070820 
 
-printline ----- test_angle_between_planes -----
+printline test_angle_between_planes.praat
 for i to 200
 	 hoek = randomInteger (0,90)
  	 nrow = randomInteger (10,1000)
  	 call test hoek nrow 3
 endfor
-printline ----- succeeded:  test_angle_between_planes -----
+
+printline test_angle_between_planes.praat OK
 
 procedure test degrees nrow ncol
 	  idt1 = Create TableOfReal... t nrow ncol
@@ -27,8 +28,8 @@ procedure test degrees nrow ncol
 	pc2 = To PCA
  	 plus pc1
 	  degrees_found = Get angle between pc1-pc2 planes
-# 	 assert abs(degrees-degrees_found) < 2e-6; 'nrow' 'degrees' 'degrees_found'
-	  printline 'nrow' 'degrees' 'degrees_found'
+ 	 assert abs(degrees-degrees_found) < 2e-6; 'nrow' 'degrees' 'degrees_found'
+	 # printline 'nrow' 'degrees' 'degrees_found'
 	 plus idt1
 	  plus idt2
  	 plus idt3
diff --git a/dwtest/test_spectrogramTypes.praat b/dwtest/test_spectrogramTypes.praat
new file mode 100644
index 0000000..3fabdcd
--- /dev/null
+++ b/dwtest/test_spectrogramTypes.praat
@@ -0,0 +1,82 @@
+# test_spectrogramTypes.praat
+# djmw 20161014
+
+appendInfoLine: "test_spectrogramTypes.praat"
+appendInfoLine: tab$ + "read old type ""MelFilter"" and convert"
+melf = Read from file: "old_type.MelFilter"
+mels = To MelSpectrogram
+removeObject: melf, mels
+
+startTime = 0
+endTime = 0.5
+
+ at testMelSpectrogramInterface
+
+appendInfoLine: "test test_spectrogramTypes.praat OK"
+
+procedure testMelSpectrogramInterface
+	.tone = Create Sound as pure tone: "t", 1, startTime, endTime, 44100, 440, 0.5, 0.01, 0.01
+	.mels = To MelSpectrogram: 0.015, 0.005, 100, 100, 0
+	# 
+	# Draw
+	#
+	Erase all
+	Select outer viewport: 0, 4, 0, 3
+	Draw frequency scale: 0, 0, 0, 0, "yes"
+	Select outer viewport: 4, 8, 0, 3
+	Paint image: 0, 0, 0, 0, 0, 0, "yes"
+	Select outer viewport: 0, 4, 3, 6
+	Draw triangular filter functions: 0, 0, "Mel", 0, 0, "no", 0, 0, "yes"
+	Select outer viewport: 4, 8, 3, 6
+	Draw spectrum at nearest time slice: (startTime + endTime)/2, 0, 0, 0, 0, "yes"
+	#
+	# query
+	#
+	@queryTimeDomain
+	@queryTimeSampling
+	@queryCommons
+	Equalize intensities: 80
+	.mfcc = To MFCC: 12
+	selectObject: .mels
+	.intensity = To Intensity
+	selectObject: .mels
+	.matrix = To Matrix: "yes"
+	removeObject: .matrix, .intensity, .mfcc, .mels, .tone
+endproc
+
+procedure queryCommons
+	.lowestFrequency = Get lowest frequency
+	.highestFrequency = Get highest frequency
+	assert .lowestFrequency < .highestFrequency; '.lowestFrequency' < '.highestFrequency'
+	.numberOfFrequencies = Get number of frequencies
+	.frequencyDistance = Get frequency distance
+	.fim1 = 0
+	for .i to .numberOfFrequencies
+		.fi = Get frequency from row: .i
+		assert .fim1 < .fi; '.fim1' < '.fi'
+		.fim1 = .fi
+	endfor
+	for .i to 100
+		.value = Get value in cell: randomUniform (startTime, endTime), randomInteger (1, .numberOfFrequencies)
+	endfor
+endproc
+
+procedure queryTimeDomain
+	.startTime = Get start time
+	.endTime = Get end time
+	.duration = Get total duration
+endproc
+
+procedure queryTimeSampling
+	.numberOfFrames = Get number of frames
+	.timeStep = Get time step
+	.previousTime = startTime
+	for .i to .numberOfFrames
+		.time = Get time from frame number: .i
+		assert .time > .previousTime; '.time' > '.previousTime'  
+		.previousTime = .time
+	endfor
+	for .i to .numberOfFrames / 10
+		.frameNumber = Get frame number from time: randomUniform (startTime, endTime)
+	endfor
+endproc
diff --git a/dwtools/ActivationList.cpp b/dwtools/ActivationList.cpp
index 3d73c86..23bca63 100644
--- a/dwtools/ActivationList.cpp
+++ b/dwtools/ActivationList.cpp
@@ -72,4 +72,4 @@ autoMatrix ActivationList_to_Matrix (ActivationList me) {
 	}
 }
 
-/* End of file Activation.cpp */
+/* End of file ActivationList.cpp */
diff --git a/dwtools/ClassificationTable.cpp b/dwtools/ClassificationTable.cpp
index 1657194..a0bc397 100644
--- a/dwtools/ClassificationTable.cpp
+++ b/dwtools/ClassificationTable.cpp
@@ -49,7 +49,7 @@ autoConfusion ClassificationTable_to_Confusion (ClassificationTable me, bool onl
 		autoStrings s2 = TableOfReal_extractRowLabelsAsStrings (me);
 		autoDistributions d2 = Strings_to_Distributions (s2.get());
 		autoStrings stimuli = TableOfReal_extractRowLabelsAsStrings (d2.get());
-		autoConfusion thee = Confusion_createFromStringses (( onlyClassLabels ? responses.get() : stimuli.get() ), responses.get());
+		autoConfusion thee = Confusion_createFromStringses ((onlyClassLabels ? responses.get() : stimuli.get() ), responses.get());
 		Confusion_and_ClassificationTable_increase (thee.get(), me);
 		return thee;
 	} catch (MelderError) {
diff --git a/dwtools/Confusion.cpp b/dwtools/Confusion.cpp
index e48095e..b6fe037 100644
--- a/dwtools/Confusion.cpp
+++ b/dwtools/Confusion.cpp
@@ -233,9 +233,9 @@ double Confusion_getValue (Confusion me, const char32 *stim, const char32 *resp)
 	return my data[stimIndex][respIndex];
 }
 
-void Confusion_getFractionCorrect (Confusion me, double *fraction, long *numberOfCorrect) {
-	*fraction = NUMundefined;
-	*numberOfCorrect = -1;
+void Confusion_getFractionCorrect (Confusion me, double *p_fraction, long *p_numberOfCorrect) {
+	double fraction = NUMundefined;
+	long numberOfCorrect = -1;
 
 	double c = 0.0, ct = 0.0;
 	for (long i = 1; i <= my numberOfRows; i++) {
@@ -251,9 +251,15 @@ void Confusion_getFractionCorrect (Confusion me, double *fraction, long *numberO
 	}
 
 	if (ct != 0.0) {
-		*fraction = c / ct;
+		fraction = c / ct;
+	}
+	if (p_fraction) {
+		*p_fraction = fraction;
+	}
+	numberOfCorrect = (long) floor (c);
+	if (p_numberOfCorrect) {
+		*p_numberOfCorrect = numberOfCorrect;
 	}
-	*numberOfCorrect = (long) floor (c);
 }
 
 /*************** Confusion_Matrix_draw ****************************************/
diff --git a/dwtools/DTW.cpp b/dwtools/DTW.cpp
index d6c4fa6..04896d7 100644
--- a/dwtools/DTW.cpp
+++ b/dwtools/DTW.cpp
@@ -82,7 +82,6 @@ void structDTW :: v_info () {
 	}
 }
 
-static void DTW_drawWarpX_raw (DTW me, Graphics g, double xmin, double xmax, double ymin, double ymax, double tx, int garnish, int inset);
 static void DTW_paintDistances_raw (DTW me, Graphics g, double xmin, double xmax, double ymin,
                                     double ymax, double minimum, double maximum, int garnish, int inset);
 static void DTW_drawPath_raw (DTW me, Graphics g, double xmin, double xmax, double ymin, double ymax, int garnish, int inset);
diff --git a/dwtools/DTW.h b/dwtools/DTW.h
index 98d81ed..e7eeb3d 100644
--- a/dwtools/DTW.h
+++ b/dwtools/DTW.h
@@ -78,6 +78,8 @@ double DTW_getYTimeFromXTime (DTW me, double tx);
 
 double DTW_getXTimeFromYTime (DTW me, double ty);
 
+double DTW_getPathY (DTW me, double tx);
+
 long DTW_getMaximumConsecutiveSteps (DTW me, int direction);
 
 void DTW_paintDistances (DTW me, Graphics g, double xmin, double xmax, double ymin,
diff --git a/dwtools/DataModeler.cpp b/dwtools/DataModeler.cpp
index 0b401d2..ea94ef4 100644
--- a/dwtools/DataModeler.cpp
+++ b/dwtools/DataModeler.cpp
@@ -197,7 +197,7 @@ void DataModeler_getExtremaY (DataModeler me, double *p_ymin, double *p_ymax) {
 	}
 }
 
-double DataModeler_getDataPointValue (DataModeler me, long index) {
+double DataModeler_getDataPointYValue (DataModeler me, long index) {
 	double value = NUMundefined;
 	if (index > 0 && index <= my numberOfDataPoints && my dataPointStatus[index] != DataModeler_DATA_INVALID) {
 		value = my y[index];
@@ -205,19 +205,40 @@ double DataModeler_getDataPointValue (DataModeler me, long index) {
 	return value;
 }
 
-void DataModeler_setDataPointValue (DataModeler me, long index, double value) {
+double DataModeler_getDataPointXValue (DataModeler me, long index) {
+	double value = NUMundefined;
+	if (index > 0 && index <= my numberOfDataPoints && my dataPointStatus[index] != DataModeler_DATA_INVALID) {
+		value = my x[index];
+	}
+	return value;
+}
+
+void DataModeler_setDataPointYValue (DataModeler me, long index, double value) {
 	if (index > 0 && index <= my numberOfDataPoints) {
 		my y[index] = value;
 	}
 }
 
-void DataModeler_setDataPointSigma (DataModeler me, long index, double sigma) {
+void DataModeler_setDataPointXValue (DataModeler me, long index, double value) {
+	if (index > 0 && index <= my numberOfDataPoints) {
+		my x[index] = value;
+	}
+}
+
+void DataModeler_setDataPointValues (DataModeler me, long index, double xvalue, double yvalue) {
+	if (index > 0 && index <= my numberOfDataPoints) {
+		my x[index] = xvalue;
+		my y[index] = yvalue;
+	}
+}
+
+void DataModeler_setDataPointYSigma (DataModeler me, long index, double sigma) {
 	if (index > 0 && index <= my numberOfDataPoints) {
 		my sigmaY[index] = sigma;
 	}
 }
 
-double DataModeler_getDataPointSigma (DataModeler me, long index) {
+double DataModeler_getDataPointYSigma (DataModeler me, long index) {
 	double sigma = NUMundefined;
 	if (index > 0 && index <= my numberOfDataPoints) {
 		sigma = my sigmaY[index];
@@ -979,6 +1000,19 @@ double DataModeler_getResidualSumOfSquares (DataModeler me, long *numberOfDataPo
 	return n > 0 ? rss : NUMundefined;
 }
 
+void DataModeler_reportChiSquared (DataModeler me, int weighDataType) {
+	int useSigmaY = weighDataType - 1;
+	MelderInfo_writeLine (U"Chi squared test:");
+	MelderInfo_writeLine (useSigmaY == DataModeler_DATA_WEIGH_EQUAL ? U"Standard deviation is estimated from the data." :
+		useSigmaY == DataModeler_DATA_WEIGH_SIGMA ? U"Sigmas are used as estimate for local standard deviations." : 
+		useSigmaY == DataModeler_DATA_WEIGH_RELATIVE ? U"1/Q's are used as estimate for local standard deviations." :
+		U"Sqrt sigmas are used as estimate for local standard deviations.");
+	double ndf, probability, chisq = DataModeler_getChiSquaredQ (me, useSigmaY, &probability, &ndf);
+	MelderInfo_writeLine (U"Chi squared = ", chisq);
+	MelderInfo_writeLine (U"Probability = ", probability);
+	MelderInfo_writeLine (U"Number of degrees of freedom = ", ndf);	
+}
+
 double DataModeler_estimateSigmaY (DataModeler me) {
 	try {
 		long numberOfDataPoints = 0;
@@ -1010,7 +1044,7 @@ double FormantModeler_getDataPointValue (FormantModeler me, long iformant, long
 	double value = NUMundefined;
 	if (iformant > 0 && iformant <= my trackmodelers.size) {
 		DataModeler ff = my trackmodelers.at [iformant];
-		value = DataModeler_getDataPointValue (ff, index);
+		value = DataModeler_getDataPointYValue (ff, index);
 	}
 	return value;
 }
@@ -1018,7 +1052,7 @@ double FormantModeler_getDataPointValue (FormantModeler me, long iformant, long
 void FormantModeler_setDataPointValue (FormantModeler me, long iformant, long index, double value) {
 	if (iformant > 0 && iformant <= my trackmodelers.size) {
 		DataModeler ff = my trackmodelers.at [iformant];
- 		DataModeler_setDataPointValue (ff, index, value);
+ 		DataModeler_setDataPointYValue (ff, index, value);
 	}
 }
 
@@ -1026,7 +1060,7 @@ double FormantModeler_getDataPointSigma (FormantModeler me, long iformant, long
 	double sigma = NUMundefined;
 	if (iformant > 0 && iformant <= my trackmodelers.size) {
 		DataModeler ff = (DataModeler) my trackmodelers.at [iformant];
-		sigma = DataModeler_getDataPointSigma (ff, index);
+		sigma = DataModeler_getDataPointYSigma (ff, index);
 	}
 	return sigma;
 }
@@ -1034,7 +1068,7 @@ double FormantModeler_getDataPointSigma (FormantModeler me, long iformant, long
 void FormantModeler_setDataPointSigma (FormantModeler me, long iformant, long index, double sigma) {
 	if (iformant > 0 && iformant <= my trackmodelers.size) {
 		DataModeler ff = my trackmodelers.at [iformant];
- 		DataModeler_setDataPointSigma (ff, index, sigma);
+ 		DataModeler_setDataPointYSigma (ff, index, sigma);
 	}
 }
 
@@ -1854,6 +1888,30 @@ double FormantModeler_getFormantsConstraintsFactor (FormantModeler me, double mi
 	return minF1Factor * maxF1Factor * minF2Factor * maxF2Factor * minF3Factor;
 }
 
+
+void FormantModeler_reportChiSquared (FormantModeler me, int weighDataType) {
+	long numberOfFormants = my trackmodelers.size;
+	int useSigmaY = weighDataType - 1;
+	double chisq = 0, ndf = 0, probability;
+	MelderInfo_writeLine (U"Chi squared tests for individual models of each of ", numberOfFormants, U" formant track:");
+	MelderInfo_writeLine (useSigmaY == DataModeler_DATA_WEIGH_EQUAL ? U"Standard deviation is estimated from the data." :
+		useSigmaY == DataModeler_DATA_WEIGH_SIGMA ? U"\tBandwidths are used as estimate for local standard deviations." : 
+		useSigmaY == DataModeler_DATA_WEIGH_RELATIVE ? U"\t1/Q's are used as estimate for local standard deviations." :
+		U"\tSqrt bandwidths are used as estimate for local standard deviations.");
+	for (long iformant = 1; iformant <= numberOfFormants; iformant ++) {
+		chisq = FormantModeler_getChiSquaredQ (me, iformant, iformant, useSigmaY, &probability, &ndf);
+		MelderInfo_writeLine (U"Formant track ", iformant, U":");
+		MelderInfo_writeLine (U"\tChi squared (F", iformant, U") = ", chisq);
+		MelderInfo_writeLine (U"\tProbability (F", iformant, U") = ", probability);
+		MelderInfo_writeLine (U"\tNumber of degrees of freedom (F", iformant, U") = ", ndf);
+	}
+	chisq = FormantModeler_getChiSquaredQ (me, 1, numberOfFormants, useSigmaY, & probability, & ndf);
+	MelderInfo_writeLine (U"Chi squared test for the complete model with ", numberOfFormants, U" formants:");
+	MelderInfo_writeLine (U"\tChi squared = ", chisq);
+	MelderInfo_writeLine (U"\tProbability = ", probability);
+	MelderInfo_writeLine (U"\tNumber of degrees of freedom = ", ndf);
+}
+
 long Formants_getSmoothestInInterval (CollectionOf<structFormant>* me, double tmin, double tmax, long numberOfFormantTracks, long numberOfParametersPerTrack,
 	int useBandWidthsForTrackEstimation, int useConstraints, double numberOfSigmas, double power,
 	double minF1, double maxF1, double minF2, double maxF2, double minF3)
diff --git a/dwtools/DataModeler.h b/dwtools/DataModeler.h
index b28d039..3bd97b3 100644
--- a/dwtools/DataModeler.h
+++ b/dwtools/DataModeler.h
@@ -2,7 +2,7 @@
 #define _DataModeler_h_
 /* DataModeler.h
  *
- * Copyright (C) 2014-2015 David Weenink
+ * Copyright (C) 2014-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -123,17 +123,20 @@ double DataModeler_getWeightedMean (DataModeler me);
 
 long DataModeler_getNumberOfInvalidDataPoints (DataModeler me);
 
-double DataModeler_getDataPointValue (DataModeler me, long index);
+double DataModeler_getDataPointXValue (DataModeler me, long index);
+double DataModeler_getDataPointYValue (DataModeler me, long index);
 
-void DataModeler_setDataPointValue (DataModeler me, long index, double value);
+void DataModeler_setDataPointXValue (DataModeler me, long index, double value);
+void DataModeler_setDataPointYValue (DataModeler me, long index, double value);
+void DataModeler_setDataPointValues (DataModeler me, long index, double xvalue, double yvalue);
 
 int DataModeler_getDataPointStatus (DataModeler me, long index);
 
 void DataModeler_setDataPointStatus (DataModeler me, long index, int status);
 
-void DataModeler_setDataPointSigma (DataModeler me, long index, double sigma);
+void DataModeler_setDataPointYSigma (DataModeler me, long index, double sigma);
 
-double DataModeler_getDataPointSigma (DataModeler me, long index);
+double DataModeler_getDataPointYSigma (DataModeler me, long index);
 double DataModeler_getResidualSumOfSquares (DataModeler me, long *numberOfDataPoints);
 
 void DataModeler_getZScores (DataModeler me, int useSigmaY, double zscores[]);
@@ -144,6 +147,8 @@ double DataModeler_getChiSquaredQ (DataModeler me, int useSigmaY, double *probab
 
 double DataModeler_getCoefficientOfDetermination (DataModeler me, double *ssreg, double *sstot);
 
+void DataModeler_reportChiSquared (DataModeler me, int weighDataType);
+
 autoFormant Formant_extractPart (Formant me, double tmin, double tmax);
 
 autoCovariance DataModeler_to_Covariance_parameters (DataModeler me);
@@ -243,6 +248,8 @@ double FormantModeler_getSmoothnessValue (FormantModeler me, long fromFormant, l
 
 double FormantModeler_getAverageDistanceBetweenTracks (FormantModeler me, long track1, long track2, int type);
 
+void FormantModeler_reportChiSquared (FormantModeler me, int weighDataType);
+
 long Formants_getSmoothestInInterval (CollectionOf<structFormant>* me, double tmin, double tmax, long numberOfFormantTracks, long numberOfParametersPerTrack, int useBandWidthsForTrackEstimation, int useConstraints, double numberOfSigmas, double power, double minF1, double maxF1, double minF2, double maxF2, double minF3);
 
 double FormantModeler_getFormantsConstraintsFactor (FormantModeler me, double minF1, double maxF1, double minF2, double maxF2, double minF3);
diff --git a/dwtools/Excitations.cpp b/dwtools/Excitations.cpp
index 65f97ce..cbbc9e9 100644
--- a/dwtools/Excitations.cpp
+++ b/dwtools/Excitations.cpp
@@ -1,6 +1,6 @@
 /* Excitations.cpp
  *
- * Copyright (C) 1993-2011, 2015 David Weenink
+ * Copyright (C) 1993-2011, 2015-2016 David Weenink, 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,29 +16,51 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-/*
- djmw 20020813 GPL header
- djmw 20071009 wchar
- djmw 20071017 Melder_error<n>
- djmw 20090914 getItem modified
- djmw 20110304 Thing_new
-*/
-
 #include "Excitations.h"
 
 Thing_implement (ExcitationList, Ordered, 0);
 
+void ExcitationList_addItem_copy (ExcitationList me, Excitation you) {
+	try {
+		if (my size > 0) {
+			if (your nx != my at [1] -> nx) { // may test more dx, xmin, xmax?
+				Melder_throw (U"Dimension of ", you, U" differs from the rest.");
+			}
+		}
+		autoExcitation newItem = Data_copy (you);
+		my addItem_move (newItem.move());
+	} catch (MelderError) {
+		Melder_throw (me, U": item not added.");
+	}
+}
+
+void ExcitationList_addItems (ExcitationList me, OrderedOf <structExcitation> * list) {
+	for (long i = 1; i <= list -> size; i ++) {
+		ExcitationList_addItem_copy (me, list -> at [i]);
+	}
+}
+
+autoExcitationList Excitations_to_ExcitationList (OrderedOf <structExcitation> * me) {
+	try {
+		autoExcitationList you = ExcitationList_create ();
+		ExcitationList_addItems (you.get(), me);
+		return you;
+	} catch (MelderError) {
+		Melder_throw (U"No ExcitationList created from Excitation(s).");
+	}
+}
+
 autoPatternList ExcitationList_to_PatternList (ExcitationList me, long join) {
 	try {
 		Melder_assert (my size > 0);
-		Matrix m = my at [1];
+		Excitation excitation = my at [1];
 		if (join < 1) {
 			join = 1;
 		}
-		if ( (my size % join) != 0) {
+		if (my size % join != 0) {
 			Melder_throw (U"Number of rows is not a multiple of join.");
 		}
-		autoPatternList thee = PatternList_create (my size / join, join * m -> nx);
+		autoPatternList thee = PatternList_create (my size / join, join * excitation -> nx);
 		long r = 0, c = 1;
 		for (long i = 1; i <= my size; i ++) {
 			double *z = my at [i] -> z [1];
@@ -46,7 +68,7 @@ autoPatternList ExcitationList_to_PatternList (ExcitationList me, long join) {
 				r ++;
 				c = 1;
 			}
-			for (long j = 1; j <= m -> nx; j ++) {
+			for (long j = 1; j <= excitation -> nx; j ++) {
 				thy z [r] [c ++] = z [j];
 			}
 		}
@@ -59,21 +81,21 @@ autoPatternList ExcitationList_to_PatternList (ExcitationList me, long join) {
 autoTableOfReal ExcitationList_to_TableOfReal (ExcitationList me) {
 	try {
 		Melder_assert (my size > 0);
-		Matrix m = my at [1];
-		autoTableOfReal thee = TableOfReal_create (my size, m -> nx);
-		for (long i = 1;  i <= my size; i ++) {
+		Excitation excitation = my at [1];
+		autoTableOfReal thee = TableOfReal_create (my size, excitation -> nx);
+		for (long i = 1; i <= my size; i ++) {
 			double *z = my at [i] -> z [1];
-			for (long j = 1; j <= m -> nx; j ++) {
-				thy data[i][j] = z[j];
+			for (long j = 1; j <= excitation -> nx; j ++) {
+				thy data [i] [j] = z [j];
 			}
 		}
 		return thee;
 	} catch (MelderError) {
-		Melder_throw (me, U": no TableOfReal created.");
+		Melder_throw (me, U": TableOfReal not created.");
 	}
 }
 
-autoExcitation ExcitationList_getItem (ExcitationList me, long item) {
+autoExcitation ExcitationList_extractItem (ExcitationList me, long item) {
 	try {
 		if (item < 1 || item > my size) {
 			Melder_throw (U"Not a valid element number.");
@@ -82,7 +104,7 @@ autoExcitation ExcitationList_getItem (ExcitationList me, long item) {
 		Thing_setName (thee.get(), Thing_getName (my at [item]));
 		return thee;
 	} catch (MelderError) {
-		Melder_throw (me, U": no Excitation created.");
+		Melder_throw (me, U": Excitation not extracted.");
 	}
 }
 
diff --git a/dwtools/Excitations.h b/dwtools/Excitations.h
index 2d002f6..87141a4 100644
--- a/dwtools/Excitations.h
+++ b/dwtools/Excitations.h
@@ -2,7 +2,7 @@
 #define _Excitations_h_
 /* Excitations.h
  *
- * Copyright (C) 1993-2011,2015 David Weenink, 2015 Paul Boersma
+ * Copyright (C) 1993-2011,2015-2016 David Weenink, 2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,14 +29,19 @@
 Collection_define (ExcitationList, OrderedOf, Excitation) {
 };
 
+void ExcitationList_addItem_copy (ExcitationList me, Excitation you);
+
+void ExcitationList_addItems (ExcitationList me, OrderedOf <structExcitation> * list);
+
+autoExcitationList Excitations_to_ExcitationList (OrderedOf <structExcitation> * me);
+
 autoPatternList ExcitationList_to_PatternList (ExcitationList me, long join);
 /* Precondition: my size >= 1, all items have same dimension */
 
 autoTableOfReal ExcitationList_to_TableOfReal (ExcitationList me);
 /* Precondition: my size >= 1, all items have same dimension */
 
-autoExcitation ExcitationList_getItem (ExcitationList m, long item);
-
+autoExcitation ExcitationList_extractItem (ExcitationList m, long item);
 
 /* End of file Excitations.h */
 #endif
diff --git a/dwtools/HMM.cpp b/dwtools/HMM.cpp
index 33e4bbb..e369e39 100644
--- a/dwtools/HMM.cpp
+++ b/dwtools/HMM.cpp
@@ -185,7 +185,7 @@ long Strings_getLongestSequence (Strings me, char32 *string, long *pos) {
 
 long StringsIndex_getLongestSequence (StringsIndex me, long index, long *pos) {
 	long length = 0, longest = 0, lpos = 0;
-	for (long i = 1; i <= my numberOfElements; i++) {
+	for (long i = 1; i <= my numberOfItems; i++) {
 		if (my classIndex[i] == index) {
 			if (length == 0) {
 				lpos = i;
@@ -888,7 +888,7 @@ void HMM_and_HMMObservationSequenceBag_learn (HMM me, HMMObservationSequenceBag
 			for (long ios = 1; ios <= thy size; ios ++) {
 				HMMObservationSequence hmm_os = thy at [ios];
 				autoStringsIndex si = HMM_and_HMMObservationSequence_to_StringsIndex (me, hmm_os); // TODO outside the loop or more efficiently
-				long *obs = si -> classIndex, nobs = si -> numberOfElements; // convenience
+				long *obs = si -> classIndex, nobs = si -> numberOfItems; // convenience
 
 				// Interpretation of unknowns: end of sequence
 
@@ -1615,7 +1615,7 @@ autoTableOfReal StringsIndex_to_TableOfReal_transitions (StringsIndex me, int pr
 			TableOfReal_setRowLabel (thee.get(), i, s -> string);
 			TableOfReal_setColumnLabel (thee.get(), i, s -> string);
 		}
-		for (long i = 2; i <= my numberOfElements; i ++) {
+		for (long i = 2; i <= my numberOfItems; i ++) {
 			if (my classIndex [i - 1] > 0 && my classIndex [i] > 0) { // a zero is a restart!
 				thy data [my classIndex [i-1]] [my classIndex [i]] ++;
 			}
diff --git a/dwtools/ICA.cpp b/dwtools/ICA.cpp
index ae22dde..e704886 100644
--- a/dwtools/ICA.cpp
+++ b/dwtools/ICA.cpp
@@ -837,6 +837,29 @@ void structCrossCorrelationTableList :: v_info () {
 	}
 }
 
+autoCrossCorrelationTableList CrossCorrelationTables_to_CrossCorrelationTableList (OrderedOf<structCrossCorrelationTable> *me) {
+	try {
+		autoCrossCorrelationTableList thee = CrossCorrelationTableList_create ();
+		long numberOfRows = 0, numberOfColumns = 0, numberOfSelected = 0;
+		for (long i = 1; i <= my size; i++) {
+			CrossCorrelationTable item = my at [i];
+			numberOfSelected++;
+			if (numberOfSelected == 1) {
+				numberOfRows = item -> numberOfRows;
+				numberOfColumns = item -> numberOfColumns;
+			}
+			if (item -> numberOfRows != numberOfRows || item -> numberOfColumns != numberOfColumns) {
+				Melder_throw (U"Dimensions of table ", i, U" differs from the rest.");
+			}
+			autoCrossCorrelationTable myc = Data_copy (item);
+			thy addItem_move (myc.move());
+		}
+		return thee;
+	} catch (MelderError) {
+		Melder_throw (U"No CrossCorrelationTableList created from CrossCorrelationTable(s)");
+	}
+}
+
 Thing_implement (CrossCorrelationTableList, SSCPList, 0);
 
 double CrossCorrelationTableList_getDiagonalityMeasure (CrossCorrelationTableList me, double *w, long start, long end) {
diff --git a/dwtools/ICA.h b/dwtools/ICA.h
index c77f735..9a0a243 100644
--- a/dwtools/ICA.h
+++ b/dwtools/ICA.h
@@ -2,7 +2,7 @@
 #define _ICA_h_
 /* ICA.h
  *
- * Copyright (C) 2010-2014,2015 David Weenink, 2015 Paul Boersma
+ * Copyright (C) 2010-2016 David Weenink, 2015 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -97,6 +97,7 @@ autoDiagonalizer CrossCorrelationTableList_to_Diagonalizer (CrossCorrelationTabl
 
 void Diagonalizer_and_CrossCorrelationTableList_improveDiagonality (Diagonalizer me, CrossCorrelationTableList thee, long maxNumberOfIterations, double tol, int method);
 
+autoCrossCorrelationTableList CrossCorrelationTables_to_CrossCorrelationTableList (OrderedOf<structCrossCorrelationTable> *me);
 /*
 	Determine V*C[k]*V' for k=1..n, where V is the diagonalizer matrix and C[k} the k-th CrossCorrelationTable.
 */
diff --git a/dwtools/LongSound_extensions.cpp b/dwtools/LongSound_extensions.cpp
index 50f9c47..dd7b0fa 100644
--- a/dwtools/LongSound_extensions.cpp
+++ b/dwtools/LongSound_extensions.cpp
@@ -206,7 +206,7 @@ void LongSounds_appendToExistingSoundFile (OrderedOf<structSampled>* me, MelderF
 			Melder_throw (U"Not a sound file.");
 		}
 
-		// Check whether all the sample rates and channels match.
+		// Check whether all the sampling frequencies and channels match.
 
 		long sampleRate = (long) floor (sampleRate_d);
 		for (long i = 1; i <= my size; i ++) {
diff --git a/dwtools/MDS.cpp b/dwtools/MDS.cpp
index 04d7bf4..b9894b8 100644
--- a/dwtools/MDS.cpp
+++ b/dwtools/MDS.cpp
@@ -169,7 +169,7 @@ autoDistanceList ConfigurationList_to_DistanceList (ConfigurationList me) {
 		}
 		return thee;
 	} catch (MelderError) {
-		Melder_throw (U"Distances not created form Configurations.");
+		Melder_throw (U"DistanceList not created form Configurations.");
 	}
 }
 
@@ -186,7 +186,7 @@ autoSimilarity ConfigurationList_to_Similarity_cc (ConfigurationList me, Weight
 autoSimilarity DistanceList_to_Similarity_cc (DistanceList me, Weight w) {
 	try {
 		if (my size == 0) {
-			Melder_throw (U"Distances is empty.");
+			Melder_throw (U"DistanceList is empty.");
 		}
 		if (! TableOfRealList_haveIdenticalDimensions (my asTableOfRealList())) {
 			Melder_throw (U"All matrices must have the same dimensions.");
@@ -212,7 +212,7 @@ autoSimilarity DistanceList_to_Similarity_cc (DistanceList me, Weight w) {
 		}
 		return thee;
 	} catch (MelderError) {
-		Melder_throw (U"Similarity not created form Distancess.");
+		Melder_throw (U"Similarity not created from DistanceList.");
 	}
 }
 
@@ -312,7 +312,7 @@ autoRatioTransformator RatioTransformator_create (long numberOfPoints) {
 
 autoDistance structMonotoneTransformator :: v_transform (MDSVec vec, Distance d, Weight w) {
 	try {
-		autoDistance thee = MDSVec_Distance_monotoneRegression (vec, d, tiesProcessing);
+		autoDistance thee = MDSVec_Distance_monotoneRegression (vec, d, tiesHandling);
 		if (normalization) {
 			Distance_Weight_smacofNormalize (thee.get(), w);
 		}
@@ -326,15 +326,15 @@ autoMonotoneTransformator MonotoneTransformator_create (long numberOfPoints) {
 	try {
 		autoMonotoneTransformator me = Thing_new (MonotoneTransformator);
 		Transformator_init (me.get(), numberOfPoints);
-		my tiesProcessing = MDS_PRIMARY_APPROACH;
+		my tiesHandling = MDS_PRIMARY_APPROACH;
 		return me;
 	} catch (MelderError) {
 		Melder_throw (U"MonotoneTransformator not created.");
 	}
 }
 
-void MonotoneTransformator_setTiesProcessing (MonotoneTransformator me, int tiesProcessing) {
-	my tiesProcessing = tiesProcessing;
+void MonotoneTransformator_setTiesProcessing (MonotoneTransformator me, int tiesHandling) {
+	my tiesHandling = tiesHandling;
 }
 
 void structISplineTransformator :: v_destroy () noexcept {
@@ -1183,7 +1183,7 @@ autoScalarProduct Distance_to_ScalarProduct (Distance me, bool normalize) {
 			Thing_setName (thee.get(), my name);
 		}
 		if (normalize) {
-			TableOfReal_normalizeTable (thee.get(), 1);
+			TableOfReal_normalizeTable (thee.get(), 1.0);
 		}
 		return thee;
 	} catch (MelderError) {
@@ -1284,7 +1284,7 @@ void Proximity_Distance_drawScatterDiagram (Proximity me, Distance thee, Graphic
 	}
 }
 
-autoDistanceList MDSVecList_Distance_monotoneRegression (MDSVecList me, Distance thee, int tiesProcessing) {
+autoDistanceList MDSVecList_Distance_monotoneRegression (MDSVecList me, Distance thee, int tiesHandling) {
 	try {
 		autoDistanceList him = DistanceList_create ();
 		for (long i = 1; i <= my size; i ++) {
@@ -1292,16 +1292,16 @@ autoDistanceList MDSVecList_Distance_monotoneRegression (MDSVecList me, Distance
 			if (vec -> nPoints != thy numberOfRows) {
 				Melder_throw (U"Dimension of MDSVec and Distance must be equal.");
 			}
-			autoDistance fit = MDSVec_Distance_monotoneRegression (vec, thee, tiesProcessing);
+			autoDistance fit = MDSVec_Distance_monotoneRegression (vec, thee, tiesHandling);
 			his addItem_move (fit.move());
 		}
 		return him;
 	} catch (MelderError) {
-		Melder_throw (U"No Distances created from MDSVecs & Distance.");
+		Melder_throw (U"No DistanceList created from MDSVecList and Distance.");
 	}
 }
 
-autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int tiesProcessing) {
+autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int tiesHandling) {
 	try {
 		long nProximities = my nProximities;
 		if (thy numberOfRows != my nPoints) {
@@ -1317,7 +1317,7 @@ autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int t
 			distance[i] = thy data[iPoint[i]][jPoint[i]];
 		}
 
-		if (tiesProcessing == MDS_PRIMARY_APPROACH || tiesProcessing == MDS_SECONDARY_APPROACH) {
+		if (tiesHandling == MDS_PRIMARY_APPROACH || tiesHandling == MDS_SECONDARY_APPROACH) {
 			/*
 				Kruskal's primary approach to tie-blocks:
 					Sort corresponding distances, with iPoint, and jPoint.
@@ -1326,20 +1326,20 @@ autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int t
 			*/
 			long ib = 1;
 			for (long i = 2; i <= nProximities; i++) {
-				if (my proximity[i] == my proximity[i - 1]) {
+				if (my proximity [i] == my proximity [i - 1]) {
 					continue;
 				}
 				if (i - ib > 1) {
-					if (tiesProcessing == MDS_PRIMARY_APPROACH) {
+					if (tiesHandling == MDS_PRIMARY_APPROACH) {
 						NUMsort3 (distance.peek(), iPoint, jPoint, ib, i - 1, 1); // sort ascending
-					} else if (tiesProcessing == MDS_SECONDARY_APPROACH) {
+					} else if (tiesHandling == MDS_SECONDARY_APPROACH) {
 						double mean = 0.0;
 						for (long j = ib; j <= i - 1; j++) {
-							mean += distance[j];
+							mean += distance [j];
 						}
 						mean /= (i - ib);
 						for (long j = ib; j <= i - 1; j++) {
-							distance[j] = mean;
+							distance [j] = mean;
 						}
 					}
 				}
@@ -1372,13 +1372,13 @@ autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int t
 }
 
 
-autoDistance Dissimilarity_Distance_monotoneRegression (Dissimilarity me, Distance thee, int tiesProcessing) {
+autoDistance Dissimilarity_Distance_monotoneRegression (Dissimilarity me, Distance thee, int tiesHandling) {
 	try {
 		if (thy numberOfRows != my numberOfRows) {
 			Melder_throw (U"Dimensions do not agree.");
 		}
 		autoMDSVec vec = Dissimilarity_to_MDSVec (me);
-		autoDistance him = MDSVec_Distance_monotoneRegression (vec.get(), thee, tiesProcessing);
+		autoDistance him = MDSVec_Distance_monotoneRegression (vec.get(), thee, tiesHandling);
 		return him;
 	} catch (MelderError) {
 		Melder_throw (U"Distance not created.");
@@ -1581,7 +1581,7 @@ autoDistanceList DissimilarityList_to_DistanceList (DissimilarityList me, int me
 		}
 		return thee;
 	} catch (MelderError) {
-		Melder_throw (me, U": no Distances created.");
+		Melder_throw (me, U": no DistanceList created.");
 	}
 }
 
@@ -1624,7 +1624,7 @@ static void smacof_guttmanTransform (Configuration cx, Configuration cz, Distanc
 	}
 }
 
-double Distance_Weight_stress (Distance fit, Distance conf, Weight weight, int type) {
+double Distance_Weight_stress (Distance fit, Distance conf, Weight weight, int stressMeasure) {
 	double eta_fit, eta_conf, rho, stress = NUMundefined, denum, tmp;
 
 	Distance_Weight_rawStressComponents (fit, conf, weight, &eta_fit, &eta_conf, &rho);
@@ -1632,12 +1632,12 @@ double Distance_Weight_stress (Distance fit, Distance conf, Weight weight, int t
 	// All formula's for stress, except for raw stress, are independent of the
 	// scale of the configuration, i.e., the distances conf[i][j].
 
-	if (type == MDS_NORMALIZED_STRESS) {
+	if (stressMeasure == MDS_NORMALIZED_STRESS) {
 		denum = eta_fit * eta_conf;
 		if (denum > 0.0) {
 			stress = 1.0 - rho * rho / denum;
 		}
-	} else if (type == MDS_STRESS_1) {
+	} else if (stressMeasure == MDS_STRESS_1) {
 		denum = eta_fit * eta_conf;
 		if (denum > 0.0) {
 			tmp = 1.0 - rho * rho / denum;
@@ -1645,7 +1645,7 @@ double Distance_Weight_stress (Distance fit, Distance conf, Weight weight, int t
 				stress = sqrt (tmp);
 			}
 		}
-	} else if (type == MDS_STRESS_2) {
+	} else if (stressMeasure == MDS_STRESS_2) {
 		double m = 0.0, wsum = 0.0, var = 0.0, **w = weight -> data;
 		double **c = conf -> data;
 		long nPoints = conf -> numberOfRows;
@@ -1673,7 +1673,7 @@ double Distance_Weight_stress (Distance fit, Distance conf, Weight weight, int t
 				stress = sqrt ( (eta_fit * eta_conf - rho * rho) / denum);
 			}
 		}
-	} else if (type == MDS_RAW_STRESS) {
+	} else if (stressMeasure == MDS_RAW_STRESS) {
 		stress = eta_fit + eta_conf - 2.0 * rho ;
 	}
 	return stress;
@@ -1707,7 +1707,7 @@ void Distance_Weight_rawStressComponents (Distance fit, Distance conf, Weight we
 	}
 }
 
-double Dissimilarity_Configuration_Transformator_Weight_stress (Dissimilarity d, Configuration c, Transformator t, Weight w, int type) {
+double Dissimilarity_Configuration_Transformator_Weight_stress (Dissimilarity d, Configuration c, Transformator t, Weight w, int stressMeasure) {
 	long nPoints = d -> numberOfRows;
 	double stress = NUMundefined;
 
@@ -1723,38 +1723,38 @@ double Dissimilarity_Configuration_Transformator_Weight_stress (Dissimilarity d,
 	autoMDSVec vec = Dissimilarity_to_MDSVec (d);
 	autoDistance fit = Transformator_transform (t, vec.get(), cdist.get(), w);
 
-	stress = Distance_Weight_stress (fit.get(), cdist.get(), w, type);
+	stress = Distance_Weight_stress (fit.get(), cdist.get(), w, stressMeasure);
 	return stress;
 }
 
-double Dissimilarity_Configuration_Weight_absolute_stress (Dissimilarity d, Configuration c, Weight w, int type) {
+double Dissimilarity_Configuration_Weight_absolute_stress (Dissimilarity d, Configuration c, Weight w, int stressMeasure) {
 	autoTransformator t = Transformator_create (d -> numberOfRows);
-	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, type);
+	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, stressMeasure);
 	return stress;
 }
 
-double Dissimilarity_Configuration_Weight_ratio_stress (Dissimilarity d, Configuration c, Weight w, int type) {
+double Dissimilarity_Configuration_Weight_ratio_stress (Dissimilarity d, Configuration c, Weight w, int stressMeasure) {
 	autoRatioTransformator t = RatioTransformator_create (d -> numberOfRows);
-	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, type);
+	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, stressMeasure);
 	return stress;
 }
 
-double Dissimilarity_Configuration_Weight_interval_stress (Dissimilarity d, Configuration c, Weight w, int type) {
+double Dissimilarity_Configuration_Weight_interval_stress (Dissimilarity d, Configuration c, Weight w, int stressMeasure) {
 	autoISplineTransformator t = ISplineTransformator_create (d -> numberOfRows, 0, 1);
-	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, type);
+	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, stressMeasure);
 	return stress;
 }
 
-double Dissimilarity_Configuration_Weight_monotone_stress (Dissimilarity d, Configuration c, Weight w, int tiesProcessing, int type) {
+double Dissimilarity_Configuration_Weight_monotone_stress (Dissimilarity d, Configuration c, Weight w, int tiesHandling, int stressMeasure) {
 	autoMonotoneTransformator t = MonotoneTransformator_create (d -> numberOfRows);
-	MonotoneTransformator_setTiesProcessing (t.get(), tiesProcessing);
-	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, type);
+	MonotoneTransformator_setTiesProcessing (t.get(), tiesHandling);
+	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, stressMeasure);
 	return stress;
 }
 
-double Dissimilarity_Configuration_Weight_ispline_stress (Dissimilarity d, Configuration c, Weight w, long numberOfInteriorKnots, long order, int type) {
+double Dissimilarity_Configuration_Weight_ispline_stress (Dissimilarity d, Configuration c, Weight w, long numberOfInteriorKnots, long order, int stressMeasure) {
 	autoISplineTransformator t = ISplineTransformator_create (d -> numberOfRows, numberOfInteriorKnots, order);
-	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, type);
+	double stress = Dissimilarity_Configuration_Transformator_Weight_stress (d, c, t.get(), w, stressMeasure);
 	return stress;
 }
 
@@ -1954,10 +1954,10 @@ autoConfiguration Dissimilarity_Configuration_Weight_interval_mds (Dissimilarity
 	}
 }
 
-autoConfiguration Dissimilarity_Configuration_Weight_monotone_mds (Dissimilarity me, Configuration cstart, Weight w, int tiesProcessing, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress) {
+autoConfiguration Dissimilarity_Configuration_Weight_monotone_mds (Dissimilarity me, Configuration cstart, Weight w, int tiesHandling, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress) {
 	try {
 		autoMonotoneTransformator t = MonotoneTransformator_create (my numberOfRows);
-		MonotoneTransformator_setTiesProcessing (t.get(), tiesProcessing);
+		MonotoneTransformator_setTiesProcessing (t.get(), tiesHandling);
 		autoConfiguration c = Dissimilarity_Configuration_Weight_Transformator_multiSmacof (me, cstart, w, t.get(), tolerance, numberOfIterations, numberOfRepetitions, showProgress);
 		return c;
 	} catch (MelderError) {
@@ -1997,11 +1997,11 @@ autoConfiguration Dissimilarity_Weight_interval_mds (Dissimilarity me, Weight w,
 	}
 }
 
-autoConfiguration Dissimilarity_Weight_monotone_mds (Dissimilarity me, Weight w, long numberOfDimensions, int tiesProcessing, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress) {
+autoConfiguration Dissimilarity_Weight_monotone_mds (Dissimilarity me, Weight w, long numberOfDimensions, int tiesHandling, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress) {
 	try {
 		autoDistance d = Dissimilarity_to_Distance (me, MDS_ORDINAL);
 		autoConfiguration cstart = Distance_to_Configuration_torsca (d.get(), numberOfDimensions);
-		autoConfiguration c = Dissimilarity_Configuration_Weight_monotone_mds (me, cstart.get(), w, tiesProcessing, tolerance, numberOfIterations, numberOfRepetitions, showProgress);
+		autoConfiguration c = Dissimilarity_Configuration_Weight_monotone_mds (me, cstart.get(), w, tiesHandling, tolerance, numberOfIterations, numberOfRepetitions, showProgress);
 		return c;
 	} catch (MelderError) {
 		Melder_throw (me, U": no Configuration created (monotone mds method).");
@@ -2065,7 +2065,7 @@ static double func (Daata object, const double p[]) {
 	double metric = my configuration -> metric;
 	long numberOfDimensions = my configuration -> numberOfColumns;
 	long numberOfPoints = my configuration -> numberOfRows;
-	int tiesProcessing = my process == MDS_CONTINUOUS ? 1 : 0;
+	int tiesHandling = my process == MDS_CONTINUOUS ? 1 : 0;
 
 	// Substitute results of minimizer into configuration and
 	// normalize the configuration
@@ -2083,7 +2083,7 @@ static double func (Daata object, const double p[]) {
 
 	// Monotone regression
 
-	autoDistance fit = MDSVec_Distance_monotoneRegression (my vec.get(), dist.get(), tiesProcessing);
+	autoDistance fit = MDSVec_Distance_monotoneRegression (my vec.get(), dist.get(), tiesHandling);
 
 	// Get numerator and denominator of stress
 
@@ -2152,13 +2152,13 @@ autoKruskal Kruskal_create (long numberOfPoints, long numberOfDimensions) {
 	}
 }
 
-autoConfiguration Dissimilarity_kruskal (Dissimilarity me, long numberOfDimensions, long /* metric */, int tiesProcessing, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions) {
+autoConfiguration Dissimilarity_to_Configuration_kruskal (Dissimilarity me, long numberOfDimensions, long /* metric */, int tiesHandling, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions) {
 	try {
 		int scale = 1;
 		autoDistance d = Dissimilarity_to_Distance (me, scale);
 		autoConfiguration c = Distance_to_Configuration_torsca (d.get(), numberOfDimensions);
 		Configuration_normalize (c.get(), 1.0, false);
-		autoConfiguration thee = Dissimilarity_Configuration_kruskal (me, c.get(), tiesProcessing, stress_formula, tolerance, numberOfIterations, numberOfRepetitions);
+		autoConfiguration thee = Dissimilarity_Configuration_kruskal (me, c.get(), tiesHandling, stress_formula, tolerance, numberOfIterations, numberOfRepetitions);
 		return thee;
 	} catch (MelderError) {
 		Melder_throw (me, U": no Configuration created (kruskal method).");
@@ -2170,33 +2170,33 @@ void Dissimilarity_Configuration_drawShepardDiagram (Dissimilarity me, Configura
 	Proximity_Distance_drawScatterDiagram (me, dist.get(), g, xmin, xmax, ymin, ymax, size_mm, mark, garnish);
 }
 
-autoDistance Dissimilarity_Configuration_monotoneRegression (Dissimilarity dissimilarity, Configuration configuration, int tiesProcessing) {
+autoDistance Dissimilarity_Configuration_monotoneRegression (Dissimilarity dissimilarity, Configuration configuration, int tiesHandling) {
 	try {
 		autoDistance dist = Configuration_to_Distance (configuration);
-		autoDistance result = Dissimilarity_Distance_monotoneRegression (dissimilarity, dist.get(), tiesProcessing);
+		autoDistance result = Dissimilarity_Distance_monotoneRegression (dissimilarity, dist.get(), tiesHandling);
 		return result;
 	} catch (MelderError) {
 		Melder_throw (U"No Distance created (monotone regression).");
 	}
 }
 
-autoDistanceList DissimilarityList_Configuration_monotoneRegression (DissimilarityList me, Configuration configuration, int tiesProcessing) {
+autoDistanceList DissimilarityList_Configuration_monotoneRegression (DissimilarityList me, Configuration configuration, int tiesHandling) {
 	try {
 		autoDistanceList thee = DistanceList_create ();
 		autoDistance dist = Configuration_to_Distance (configuration);
 		for (long i = 1; i <= my size; i ++) {
-			autoDistance d = Dissimilarity_Distance_monotoneRegression (my at [i], dist.get(), tiesProcessing);
+			autoDistance d = Dissimilarity_Distance_monotoneRegression (my at [i], dist.get(), tiesHandling);
 			thy addItem_move (d.move());
 		}
 		return thee;
 	} catch (MelderError) {
-		Melder_throw (U"No Distances created (monotone regression).");
+		Melder_throw (U"No DistanceList created (monotone regression).");
 	}
 }
 
-void Dissimilarity_Configuration_drawMonotoneRegression (Dissimilarity me, Configuration him, Graphics g, int tiesProcessing, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish) {
+void Dissimilarity_Configuration_drawMonotoneRegression (Dissimilarity me, Configuration him, Graphics g, int tiesHandling, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish) {
 	/* obsolete replace by transformator */
-	autoDistance fit = Dissimilarity_Configuration_monotoneRegression (me, him, tiesProcessing);
+	autoDistance fit = Dissimilarity_Configuration_monotoneRegression (me, him, tiesHandling);
 	Proximity_Distance_drawScatterDiagram (me, fit.get(), g, xmin, xmax, ymin, ymax, size_mm, mark, garnish);
 }
 
@@ -2216,9 +2216,9 @@ void Dissimilarity_Configuration_Weight_drawIntervalRegression (Dissimilarity d,
 	Dissimilarity_Configuration_Weight_drawISplineRegression (d, c, w, g, 0.0, 1.0, xmin, xmax, ymin, ymax, size_mm, mark, garnish);
 }
 
-void Dissimilarity_Configuration_Weight_drawMonotoneRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, int tiesProcessing, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish) {
+void Dissimilarity_Configuration_Weight_drawMonotoneRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, int tiesHandling, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish) {
 	autoMonotoneTransformator t = MonotoneTransformator_create (d->numberOfRows);
-	MonotoneTransformator_setTiesProcessing (t.get(), tiesProcessing);
+	MonotoneTransformator_setTiesProcessing (t.get(), tiesHandling);
 	autoDistance fit = Dissimilarity_Configuration_Transformator_Weight_transform (d, c, t.get(), w);
 	Proximity_Distance_drawScatterDiagram (d, fit.get(), g, xmin, xmax, ymin, ymax, size_mm, mark, garnish);
 }
@@ -2253,16 +2253,16 @@ double Dissimilarity_Configuration_Weight_Transformator_normalizedStress (Dissim
 	return stress;
 }
 
-double Dissimilarity_Configuration_getStress (Dissimilarity me, Configuration him, int tiesProcessing, int stress_formula) {
+double Dissimilarity_Configuration_getStress (Dissimilarity me, Configuration him, int tiesHandling, int stress_formula) {
 	autoDistance dist = Configuration_to_Distance (him);
 	autoMDSVec vec = Dissimilarity_to_MDSVec (me);
-	autoDistance fit = MDSVec_Distance_monotoneRegression (vec.get(), dist.get(), tiesProcessing);
+	autoDistance fit = MDSVec_Distance_monotoneRegression (vec.get(), dist.get(), tiesHandling);
 	double s, t, dbar, stress;
 	MDSVec_Distances_getStressValues (vec.get(), dist.get(), fit.get(), stress_formula, &stress, &s, &t, &dbar);
 	return stress;
 }
 
-autoConfiguration Dissimilarity_Configuration_kruskal (Dissimilarity me, Configuration him, int tiesProcessing, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions) {
+autoConfiguration Dissimilarity_Configuration_kruskal (Dissimilarity me, Configuration him, int tiesHandling, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions) {
 	try {
 		// The Configuration is normalized: each dimension centred +
 		//	total variance set
@@ -2286,7 +2286,7 @@ autoConfiguration Dissimilarity_Configuration_kruskal (Dissimilarity me, Configu
 		NUMdmatrix_into_vector (his data, thy minimizer -> p, 1, his numberOfRows, 1, his numberOfColumns);
 
 		thy stress_formula = stress_formula;
-		thy process = tiesProcessing;
+		thy process = tiesHandling;
 		Configuration_setMetric (thy configuration.get(), his metric);
 
 		Minimizer_minimizeManyTimes (thy minimizer.get(), numberOfRepetitions, numberOfIterations, tolerance);
@@ -2450,7 +2450,7 @@ void ScalarProductList_Configuration_Salience_indscal (ScalarProductList sp, Con
 			*p_varianceAccountedFor = varianceAccountedFor;
 		}
 		if (showProgress) {
-			MelderInfo_writeLine (U"**************** INDSCAL results on Distances *******************\n\n", 
+			MelderInfo_writeLine (U"**************** INDSCAL results on Distances *******************\n\n",
 				Thing_className (sp), U"number of objects: ", nSources);
 			for (long i = 1; i <= nSources; i ++) {
 				MelderInfo_writeLine (U"  ", Thing_getName (sp->at [i]));
@@ -2481,7 +2481,7 @@ void DistanceList_Configuration_Salience_indscal (DistanceList distances, Config
 	}
 }
 
-void DissimilarityList_Configuration_Salience_indscal (DissimilarityList dissims, Configuration conf, Salience weights, int tiesProcessing, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *p_configuration, autoSalience *p_salience, double *varianceAccountedFor) {
+void DissimilarityList_Configuration_Salience_indscal (DissimilarityList dissims, Configuration conf, Salience weights, int tiesHandling, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *p_configuration, autoSalience *p_salience, double *varianceAccountedFor) {
 	try {
 		double tol = 1e-6, vafp = 0.0, vaf;
 		long iter, nSources = dissims->size;
@@ -2494,7 +2494,7 @@ void DissimilarityList_Configuration_Salience_indscal (DissimilarityList dissims
 		}
 
 		for (iter = 1; iter <= numberOfIterations; iter++) {
-			autoDistanceList distances = MDSVecList_Configuration_Salience_monotoneRegression (mdsveclist.get(), configuration.get(), salience.get(), tiesProcessing);
+			autoDistanceList distances = MDSVecList_Configuration_Salience_monotoneRegression (mdsveclist.get(), configuration.get(), salience.get(), tiesHandling);
 			autoScalarProductList sp = DistanceList_to_ScalarProductList (distances.get(), normalizeScalarProducts);
 
 			indscal_iteration_tenBerge (sp.get(), configuration.get(), salience.get());
@@ -2554,7 +2554,7 @@ void DissimilarityList_Configuration_Salience_indscal (DissimilarityList dissims
 		if (showProgress) {
 			Melder_progress (1.0);
 		}
-		Melder_throw (U"no inscal configuration calculated.");
+		Melder_throw (U"No inscal configuration calculated.");
 	}
 }
 
@@ -2568,7 +2568,7 @@ void DistanceList_Configuration_indscal (DistanceList dists, Configuration conf,
 	}
 }
 
-autoDistanceList MDSVecList_Configuration_Salience_monotoneRegression (MDSVecList vecs, Configuration conf, Salience weights, int tiesProcessing) {
+autoDistanceList MDSVecList_Configuration_Salience_monotoneRegression (MDSVecList vecs, Configuration conf, Salience weights, int tiesHandling) {
 	try {
 		long nDimensions = conf -> numberOfColumns;
 		autoNUMvector<double> w (NUMvector_copy (conf -> w, 1, nDimensions), 1);
@@ -2576,13 +2576,13 @@ autoDistanceList MDSVecList_Configuration_Salience_monotoneRegression (MDSVecLis
 		for (long i = 1; i <= vecs->size; i ++) {
 			NUMvector_copyElements (weights -> data[i], conf -> w, 1, nDimensions);
 			autoDistance dc = Configuration_to_Distance (conf);
-			autoDistance dist = MDSVec_Distance_monotoneRegression (vecs->at [i], dc.get(), tiesProcessing);
+			autoDistance dist = MDSVec_Distance_monotoneRegression (vecs->at [i], dc.get(), tiesHandling);
 			distances -> addItem_move (dist.move());
 		}
 		Configuration_setDefaultWeights (conf);
 		return distances;
 	} catch (MelderError) {
-		Melder_throw (U"No Distances created.");
+		Melder_throw (U"No DistanceList created.");
 	}
 }
 
@@ -2607,9 +2607,9 @@ autoSalience ScalarProductList_Configuration_to_Salience (ScalarProductList me,
 	}
 }
 
-autoSalience DissimilarityList_Configuration_to_Salience (DissimilarityList me, Configuration him, int tiesProcessing, bool normalizeScalarProducts) {
+autoSalience DissimilarityList_Configuration_to_Salience (DissimilarityList me, Configuration him, int tiesHandling, bool normalizeScalarProducts) {
 	try {
-		autoDistanceList distances = DissimilarityList_Configuration_monotoneRegression (me, him, tiesProcessing);
+		autoDistanceList distances = DissimilarityList_Configuration_monotoneRegression (me, him, tiesHandling);
 		autoSalience w = DistanceList_Configuration_to_Salience (distances.get(), him, normalizeScalarProducts);
 		return w;
 	} catch (MelderError) {
@@ -2617,18 +2617,18 @@ autoSalience DissimilarityList_Configuration_to_Salience (DissimilarityList me,
 	}
 }
 
-void DissimilarityList_Configuration_indscal (DissimilarityList dissims, Configuration conf, int tiesProcessing, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *out1, autoSalience *out2) {
+void DissimilarityList_Configuration_indscal (DissimilarityList dissims, Configuration conf, int tiesHandling, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *out1, autoSalience *out2) {
 	try {
-		autoDistanceList distances = DissimilarityList_Configuration_monotoneRegression (dissims, conf, tiesProcessing);
+		autoDistanceList distances = DissimilarityList_Configuration_monotoneRegression (dissims, conf, tiesHandling);
 		autoSalience weights = DistanceList_Configuration_to_Salience (distances.get(), conf, normalizeScalarProducts);
 		double vaf;
-		DissimilarityList_Configuration_Salience_indscal (dissims, conf, weights.get(), tiesProcessing, normalizeScalarProducts, tolerance, numberOfIterations, showProgress, out1, out2, & vaf);
+		DissimilarityList_Configuration_Salience_indscal (dissims, conf, weights.get(), tiesHandling, normalizeScalarProducts, tolerance, numberOfIterations, showProgress, out1, out2, & vaf);
 	} catch (MelderError) {
 		Melder_throw (U"No indscal performed.");
 	}
 }
 
-void DissimilarityList_indscal (DissimilarityList me, long numberOfDimensions, int tiesProcessing, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *p_conf, autoSalience *p_sal) {
+void DissimilarityList_indscal (DissimilarityList me, long numberOfDimensions, int tiesHandling, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *p_conf, autoSalience *p_sal) {
 	int showMulti = showProgress && numberOfRepetitions > 1;
 	try {
 		bool showSingle = (showProgress && numberOfRepetitions == 1);
@@ -2647,7 +2647,7 @@ void DissimilarityList_indscal (DissimilarityList me, long numberOfDimensions, i
 		for (long iter = 1; iter <= numberOfRepetitions; iter ++) {
 			autoConfiguration cresult; 
 			autoSalience wresult;
-			DissimilarityList_Configuration_Salience_indscal (me, cstart.get(), wstart.get(), tiesProcessing,
+			DissimilarityList_Configuration_Salience_indscal (me, cstart.get(), wstart.get(), tiesHandling,
 				normalizeScalarProducts, tolerance, numberOfIterations, showSingle, & cresult, & wresult, & vaf);
 			if (vaf > vafmin) {
 				vafmin = vaf;
@@ -2680,7 +2680,7 @@ void DissimilarityList_indscal (DissimilarityList me, long numberOfDimensions, i
 	}
 }
 
-void DistanceList_indscal (DistanceList distances, long numberOfDimensions, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *p_conf, autoSalience *p_sal) {
+void DistanceList_to_Configuration_indscal (DistanceList distances, long numberOfDimensions, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *p_conf, autoSalience *p_sal) {
 	int showMulti = showProgress && numberOfRepetitions > 1;
 	try {
 		bool showSingle = ( showProgress && numberOfRepetitions == 1 );
@@ -2731,8 +2731,8 @@ void DistanceList_indscal (DistanceList distances, long numberOfDimensions, bool
 	}
 }
 
-void DissimilarityList_Configuration_Salience_vaf (DissimilarityList me, Configuration thee, Salience him, int tiesProcessing, bool normalizeScalarProducts, double *vaf) {
-	autoDistanceList distances = DissimilarityList_Configuration_monotoneRegression (me, thee, tiesProcessing);
+void DissimilarityList_Configuration_Salience_vaf (DissimilarityList me, Configuration thee, Salience him, int tiesHandling, bool normalizeScalarProducts, double *vaf) {
+	autoDistanceList distances = DissimilarityList_Configuration_monotoneRegression (me, thee, tiesHandling);
 	DistanceList_Configuration_Salience_vaf (distances.get(), thee, him, normalizeScalarProducts, vaf);
 }
 
@@ -2741,9 +2741,9 @@ void DistanceList_Configuration_vaf (DistanceList me, Configuration thee, bool n
 	DistanceList_Configuration_Salience_vaf (me, thee, w.get(), normalizeScalarProducts, vaf);
 }
 
-void DissimilarityList_Configuration_vaf (DissimilarityList me, Configuration thee, int tiesProcessing, bool normalizeScalarProducts, double *vaf) {
-	autoSalience w = DissimilarityList_Configuration_to_Salience (me, thee, tiesProcessing, normalizeScalarProducts);
-	DissimilarityList_Configuration_Salience_vaf (me, thee, w.get(), tiesProcessing, normalizeScalarProducts, vaf);
+void DissimilarityList_Configuration_vaf (DissimilarityList me, Configuration thee, int tiesHandling, bool normalizeScalarProducts, double *vaf) {
+	autoSalience w = DissimilarityList_Configuration_to_Salience (me, thee, tiesHandling, normalizeScalarProducts);
+	DissimilarityList_Configuration_Salience_vaf (me, thee, w.get(), tiesHandling, normalizeScalarProducts, vaf);
 }
 
 void DistanceList_Configuration_Salience_vaf (DistanceList me, Configuration thee, Salience him, bool normalizeScalarProducts, double *vaf) {
@@ -2881,12 +2881,12 @@ autoCollection INDSCAL_createCarrollWishExample (double noiseRange) {
 	}
 }
 
-void drawSplines (Graphics g, double low, double high, double ymin, double ymax, int type, long order, const char32 *interiorKnots, int garnish) {
+void drawSplines (Graphics g, double low, double high, double ymin, double ymax, int splineType, long order, const char32 *interiorKnots, int garnish) {
 	long k = order, numberOfKnots, numberOfInteriorKnots = 0;
 	long nSplines, n = 1000;
 	double knot[101], y[1001];
 
-	if (type == MDS_ISPLINE) {
+	if (splineType == MDS_ISPLINE) {
 		k++;
 	}
 	for (long i = 1; i <= k; i++) {
@@ -2928,7 +2928,7 @@ void drawSplines (Graphics g, double low, double high, double ymin, double ymax,
 		double x, yx, dx = (high - low) / (n - 1);
 		for (long j = 1; j <= n; j++) {
 			x = low + dx * (j - 1);
-			if (type == MDS_MSPLINE) {
+			if (splineType == MDS_MSPLINE) {
 				(void) NUMmspline (knot, numberOfKnots, order, i, x, &yx);
 			} else {
 				(void) NUMispline (knot, numberOfKnots, order, i, x, &yx);
@@ -2940,9 +2940,9 @@ void drawSplines (Graphics g, double low, double high, double ymin, double ymax,
 	Graphics_unsetInner (g);
 	if (garnish) {
 		static MelderString ts { 0 };
-		long lastKnot = type == MDS_ISPLINE ? numberOfKnots - 2 : numberOfKnots;
+		long lastKnot = splineType == MDS_ISPLINE ? numberOfKnots - 2 : numberOfKnots;
 		Graphics_drawInnerBox (g);
-		Graphics_textLeft (g, false, type == MDS_MSPLINE ? U"\\s{M}\\--spline" : U"\\s{I}\\--spline");
+		Graphics_textLeft (g, false, splineType == MDS_MSPLINE ? U"\\s{M}\\--spline" : U"\\s{I}\\--spline");
 		Graphics_marksTop (g, 2, true, true, false);
 		Graphics_marksLeft (g, 2, true, true, false);
 		if (low <= knot[order]) {
diff --git a/dwtools/MDS.h b/dwtools/MDS.h
index 01899a1..19c16f7 100644
--- a/dwtools/MDS.h
+++ b/dwtools/MDS.h
@@ -214,7 +214,7 @@ Thing_define (RatioTransformator, Transformator) {
 autoRatioTransformator RatioTransformator_create (long numberOfPoints);
 
 Thing_define (MonotoneTransformator, Transformator) {
-	int tiesProcessing;
+	int tiesHandling;
 
 	autoDistance v_transform (MDSVec vec, Distance dist, Weight w)
 		override;
@@ -222,8 +222,7 @@ Thing_define (MonotoneTransformator, Transformator) {
 
 autoMonotoneTransformator MonotoneTransformator_create (long numberPoints);
 
-void MonotoneTransformator_setTiesProcessing (MonotoneTransformator,
-	int tiesProcessing);
+void MonotoneTransformator_setTiesProcessing (MonotoneTransformator, int tiesHandling);
 
 
 /*************** class DissimilyList ****************************/
@@ -265,8 +264,7 @@ Thing_define (Kruskal, Thing) {
 
 autoKruskal Kruskal_create (long numberOfpoints, long numberOfDimensions);
 
-double Dissimilarity_Configuration_Weight_Transformator_normalizedStress
-	(Dissimilarity me, Configuration conf, Weight weight, Transformator t);
+double Dissimilarity_Configuration_Weight_Transformator_normalizedStress (Dissimilarity me, Configuration conf, Weight weight, Transformator t);
 
 double Distance_Weight_stress (Distance fit, Distance c, Weight w, int type);
 /*
@@ -291,17 +289,17 @@ void Distance_Weight_rawStressComponents (Distance fit, Distance conf, Weight we
 		conf[i][j] = distance between x[i] and x[j] (in the configuration)
 */
 
-double Dissimilarity_Configuration_Transformator_Weight_stress (Dissimilarity d, Configuration c, Transformator t, Weight w, int type);
+double Dissimilarity_Configuration_Transformator_Weight_stress (Dissimilarity d, Configuration c, Transformator t, Weight w, int stressMeasure);
 
-double Dissimilarity_Configuration_Weight_absolute_stress (Dissimilarity d, Configuration c, Weight w, int type);
+double Dissimilarity_Configuration_Weight_absolute_stress (Dissimilarity d, Configuration c, Weight w, int stressMeasure);
 
-double Dissimilarity_Configuration_Weight_ratio_stress (Dissimilarity d, Configuration c, Weight w, int type);
+double Dissimilarity_Configuration_Weight_ratio_stress (Dissimilarity d, Configuration c, Weight w, int stressMeasure);
 
-double Dissimilarity_Configuration_Weight_interval_stress (Dissimilarity d, Configuration c, Weight w, int type);
+double Dissimilarity_Configuration_Weight_interval_stress (Dissimilarity d, Configuration c, Weight w, int stressMeasure);
 
-double Dissimilarity_Configuration_Weight_monotone_stress (Dissimilarity d, Configuration c, Weight w, int tiesProcessing, int type);
+double Dissimilarity_Configuration_Weight_monotone_stress (Dissimilarity d, Configuration c, Weight w, int tiesHandling, int stressMeasure);
 
-double Dissimilarity_Configuration_Weight_ispline_stress (Dissimilarity d, Configuration c, Weight w, long numberOfInteriorKnots, long order, int type);
+double Dissimilarity_Configuration_Weight_ispline_stress (Dissimilarity d, Configuration c, Weight w, long numberOfInteriorKnots, long order, int stressMeasure);
 
 void Distance_Weight_smacofNormalize (Distance d, Weight w);
 
@@ -315,42 +313,31 @@ autoConfiguration Dissimilarity_Configuration_Weight_ratio_mds (Dissimilarity di
 
 autoConfiguration Dissimilarity_Configuration_Weight_interval_mds (Dissimilarity dis, Configuration cstart, Weight w, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
-autoConfiguration Dissimilarity_Configuration_Weight_monotone_mds (Dissimilarity dis, Configuration cstart, Weight w, int tiesProcessing, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
+autoConfiguration Dissimilarity_Configuration_Weight_monotone_mds (Dissimilarity dis, Configuration cstart, Weight w, int tiesHandling, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
-autoConfiguration Dissimilarity_Configuration_Weight_ispline_mds (Dissimilarity me, Configuration cstart, Weight w,
-	long numberOfInteriorKnots, long order, double tolerance,
-	long numberOfIterations, long numberOfRepetitions, bool showProgress);
+autoConfiguration Dissimilarity_Configuration_Weight_ispline_mds (Dissimilarity me, Configuration cstart, Weight w, long numberOfInteriorKnots, long order, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
-autoConfiguration Dissimilarity_Weight_absolute_mds (Dissimilarity me, Weight w, long numberOfDimensions, double tolerance,
-	long numberOfIterations, long numberOfRepetitions, bool showProgress);
+autoConfiguration Dissimilarity_Weight_absolute_mds (Dissimilarity me, Weight w, long numberOfDimensions, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
-autoConfiguration Dissimilarity_Weight_ratio_mds (Dissimilarity dis, Weight w, long numberOfDimensions, double tolerance,
-	long numberOfIterations, long numberOfRepetitions, bool showProgress);
+autoConfiguration Dissimilarity_Weight_ratio_mds (Dissimilarity dis, Weight w, long numberOfDimensions, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
 
-autoConfiguration Dissimilarity_Weight_interval_mds (Dissimilarity dis, Weight w, long numberOfDimensions, double tolerance,
-	long numberOfIterations, long numberOfRepetitions, bool showProgress);
+autoConfiguration Dissimilarity_Weight_interval_mds (Dissimilarity dis, Weight w, long numberOfDimensions, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
-autoConfiguration Dissimilarity_Weight_monotone_mds (Dissimilarity me, Weight w, long numberOfDimensions, int tiesProcessing,
-	double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
+autoConfiguration Dissimilarity_Weight_monotone_mds(Dissimilarity me, Weight w, long int numberOfDimensions, int tiesHandling, double tolerance, long int numberOfIterations, long int numberOfRepetitions, bool showProgress);
 
 autoConfiguration Dissimilarity_Weight_ispline_mds (Dissimilarity me, Weight weight, long numberOfDimensions,
 	long numberOfInteriorKnots, long order, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress);
 
-void Dissimilarity_Configuration_Weight_drawAbsoluteRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, double xmin,
-	double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
+void Dissimilarity_Configuration_Weight_drawAbsoluteRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
-void Dissimilarity_Configuration_Weight_drawRatioRegression (Dissimilarity d, Configuration c, Weight w, Graphics g,
-	double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
+void Dissimilarity_Configuration_Weight_drawRatioRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
-void Dissimilarity_Configuration_Weight_drawIntervalRegression (Dissimilarity d, Configuration c, Weight w, Graphics g,
-	double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
+void Dissimilarity_Configuration_Weight_drawIntervalRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
-void Dissimilarity_Configuration_Weight_drawMonotoneRegression (Dissimilarity d, Configuration c, Weight w, Graphics g,
-	int tiesProcessing, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
+void Dissimilarity_Configuration_Weight_drawMonotoneRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, int tiesHandling, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
-void Dissimilarity_Configuration_Weight_drawISplineRegression (Dissimilarity d, Configuration c, Weight w, Graphics g,
-	long numberOfInternalKnots, long order, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
+void Dissimilarity_Configuration_Weight_drawISplineRegression (Dissimilarity d, Configuration c, Weight w, Graphics g, long numberOfInternalKnots, long order, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
 autoDistance Dissimilarity_Configuration_Transformator_Weight_transform (Dissimilarity d, Configuration c, Transformator t, Weight w);
 
@@ -389,19 +376,19 @@ autoConfiguration Distance_to_Configuration_torsca (Distance me, int numberOfDim
 
 /************** DISSIMILARITY & CONFIGURATION ************************/
 
-autoConfiguration Dissimilarity_kruskal (Dissimilarity me, long numberOfDimensions, long metric, int processTies, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions);
+autoConfiguration Dissimilarity_to_Configuration_kruskal (Dissimilarity me, long numberOfDimensions, long metric, int tiesHandling, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions);
 
-autoConfiguration Dissimilarity_Configuration_kruskal (Dissimilarity me, Configuration him, int processTies, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions);
+autoConfiguration Dissimilarity_Configuration_kruskal (Dissimilarity me, Configuration him, int tiesHandling, int stress_formula, double tolerance, long numberOfIterations, long numberOfRepetitions);
 
-double Dissimilarity_Configuration_getStress (Dissimilarity me, Configuration him, int processTies, int stress_formula);
+double Dissimilarity_Configuration_getStress (Dissimilarity me, Configuration him, int tiesHandling, int stress_formula);
 
 void Dissimilarity_Configuration_drawShepardDiagram (Dissimilarity me, Configuration him, Graphics g, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
-autoDistance Dissimilarity_Configuration_monotoneRegression (Dissimilarity dis, Configuration conf, int processTies);
+autoDistance Dissimilarity_Configuration_monotoneRegression (Dissimilarity dis, Configuration conf, int tiesHandling);
 
-autoDistanceList DissimilarityList_Configuration_monotoneRegression (DissimilarityList dissims, Configuration conf, int processTies);
+autoDistanceList DissimilarityList_Configuration_monotoneRegression (DissimilarityList dissims, Configuration conf, int tiesHandling);
 
-void Dissimilarity_Configuration_drawMonotoneRegression	(Dissimilarity me, Configuration him, Graphics g, int processTies, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
+void Dissimilarity_Configuration_drawMonotoneRegression	(Dissimilarity me, Configuration him, Graphics g, int tiesHandling, double xmin, double xmax, double ymin, double ymax, double size_mm, const char32 *mark, int garnish);
 
 
 /************** SIMILARITY & TABLESOFREAL ********************************/
@@ -418,7 +405,7 @@ autoDistance Dissimilarity_to_Distance (Dissimilarity me, int scale);
 
 autoDissimilarity Distance_to_Dissimilarity (Distance me);
 
-autoDistance Dissimilarity_Distance_monotoneRegression (Dissimilarity me, Distance thee, int tiesProcessingMethod);
+autoDistance Dissimilarity_Distance_monotoneRegression (Dissimilarity me, Distance thee, int tiesHandling);
 
 
 /************** DISSIMILARITY & CONFUSION ************************************/
@@ -470,9 +457,9 @@ autoDistanceList ConfigurationList_to_DistanceList (ConfigurationList me);
 
 /************** MDSVec(Lists)  & Distance(List) **********************************/
 
-autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int tiesProcessingMethod);
+autoDistance MDSVec_Distance_monotoneRegression (MDSVec me, Distance thee, int tiesHandlingMethod);
 
-autoDistanceList MDSVecList_Distance_monotoneRegression (MDSVecList me, Distance thee, int tiesProcessingMethod);
+autoDistanceList MDSVecList_Distance_monotoneRegression (MDSVecList me, Distance thee, int tiesHandlingMethod);
 
 
 /************** ScalarProduct(List) & ...... **********************************/
@@ -490,36 +477,36 @@ void ScalarProductList_Configuration_Salience_indscal (ScalarProductList sp, Con
 
 /************** INDSCAL & ....... ***********************************/
 
-void DissimilarityList_indscal (DissimilarityList me, long numberOfDimensions, int tiesProcessingMethod, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *out1, autoSalience *out2);
+void DissimilarityList_indscal (DissimilarityList me, long numberOfDimensions, int tiesHandlingMethod, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *out1, autoSalience *out2);
 
-void DistanceList_indscal (DistanceList me, long numberOfDimensions, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *out1, autoSalience *out2);
+void DistanceList_to_Configuration_indscal (DistanceList me, long numberOfDimensions, bool normalizeScalarProducts, double tolerance, long numberOfIterations, long numberOfRepetitions, bool showProgress, autoConfiguration *out1, autoSalience *out2);
 
-void DissimilarityList_Configuration_indscal (DissimilarityList me, Configuration conf, int tiesProcessingMethod, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *out1, autoSalience *out2);
+void DissimilarityList_Configuration_indscal (DissimilarityList me, Configuration conf, int tiesHandlingMethod, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *out1, autoSalience *out2);
 
 void DistanceList_Configuration_indscal (DistanceList dists, Configuration conf, bool normalizeScalarProducts, double tolerance, long numberOfIterations,
 	bool showProgress, autoConfiguration *out1, autoSalience *out2);
 
-void DissimilarityList_Configuration_Salience_indscal (DissimilarityList dissims, Configuration conf, Salience w, int tiesProcessingMethod,
+void DissimilarityList_Configuration_Salience_indscal (DissimilarityList dissims, Configuration conf, Salience w, int tiesHandlingMethod,
 	bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *out1, autoSalience *out2, double *vaf);
 
-autoDistanceList MDSVecList_Configuration_Salience_monotoneRegression (MDSVecList vecs, Configuration conf, Salience weights, int tiesProcessingMethod);
+autoDistanceList MDSVecList_Configuration_Salience_monotoneRegression (MDSVecList vecs, Configuration conf, Salience weights, int tiesHandlingMethod);
 
 void DistanceList_Configuration_Salience_indscal (DistanceList dists, Configuration conf, Salience weights, bool normalizeScalarProducts, double tolerance, long numberOfIterations, bool showProgress, autoConfiguration *out1, autoSalience *out2, double *vaf);
 
 void DistanceList_Configuration_Salience_vaf (DistanceList me, Configuration thee, Salience him, bool normalizeScalarProducts, double *vaf);
 
 void DissimilarityList_Configuration_Salience_vaf (DissimilarityList me, Configuration thee,
-	Salience him, int tiesProcessingMethod, bool normalizeScalarProducts, double *vaf);
+	Salience him, int tiesHandlingMethod, bool normalizeScalarProducts, double *vaf);
 
 void DistanceList_Configuration_vaf (DistanceList me, Configuration thee, bool normalizeScalarProducts, double *vaf);
 
-void DissimilarityList_Configuration_vaf (DissimilarityList me, Configuration thee, int tiesProcessingMethod, bool normalizeScalarProducts, double *vaf);
+void DissimilarityList_Configuration_vaf (DissimilarityList me, Configuration thee, int tiesHandlingMethod, bool normalizeScalarProducts, double *vaf);
 
 autoSalience ScalarProductList_Configuration_to_Salience (ScalarProductList me, Configuration him);
 
 autoSalience DistanceList_Configuration_to_Salience (DistanceList me, Configuration him, bool normalizeScalarProducts);
 
-autoSalience DissimilarityList_Configuration_to_Salience (DissimilarityList me, Configuration him, int processTies, bool normalizeScalarProducts);
+autoSalience DissimilarityList_Configuration_to_Salience (DissimilarityList me, Configuration him, int tiesHandling, bool normalizeScalarProducts);
 
 
 /********* Conversions from & to TableOfReal *****************************/
diff --git a/dwtools/OptimalCeilingTierEditor.h b/dwtools/OptimalCeilingTierEditor.h
index 3b20836..a2a0a9a 100644
--- a/dwtools/OptimalCeilingTierEditor.h
+++ b/dwtools/OptimalCeilingTierEditor.h
@@ -1,4 +1,4 @@
-#ifndef _AmplitudeTierEditor_h_
+#ifndef _OptimalCeilingTierEditor_h_
 #define _OptimalCeilingTierEditor_h_
 /* OptimalCeilingTierEditor.h
  *
diff --git a/dwtools/PCA.cpp b/dwtools/PCA.cpp
index 1208dfa..0a40d26 100644
--- a/dwtools/PCA.cpp
+++ b/dwtools/PCA.cpp
@@ -137,6 +137,17 @@ void PCA_getEqualityOfEigenvalues (PCA me, long from, long to, int conservative,
  * 
  */
 
+autoEigen PCA_to_Eigen (PCA me) {
+	try {
+		autoEigen thee = Eigen_create (my numberOfEigenvalues, my dimension);
+		NUMmatrix_copyElements <double>(my eigenvectors, thy eigenvectors, 1, my numberOfEigenvalues, 1, my dimension);
+		NUMvector_copyElements<double>(my eigenvalues, thy eigenvalues, 1, my numberOfEigenvalues);
+		return thee;
+	} catch (MelderError) {
+		Melder_throw (me, U": no Eigen created.");
+	}
+}
+
 static autoPCA NUMdmatrix_to_PCA (double **m, long numberOfRows, long numberOfColumns, bool byColumns) {
 	try {
 		if (! NUMdmatrix_hasFiniteElements(m, 1, numberOfRows, 1, numberOfColumns)) {
diff --git a/dwtools/PCA.h b/dwtools/PCA.h
index b3aede7..a290312 100644
--- a/dwtools/PCA.h
+++ b/dwtools/PCA.h
@@ -41,6 +41,8 @@ long PCA_getNumberOfObservations (PCA me);
 
 autoPCA TableOfReal_to_PCA_byRows (TableOfReal me);
 
+autoEigen PCA_to_Eigen (PCA me);
+
 /* Calculate PCA of M'M */
 
 autoPCA Matrix_to_PCA_byRows (Matrix me);
diff --git a/dwtools/Polygon_extensions.cpp b/dwtools/Polygon_extensions.cpp
index 0db8752..51158ed 100644
--- a/dwtools/Polygon_extensions.cpp
+++ b/dwtools/Polygon_extensions.cpp
@@ -95,7 +95,7 @@ autoPolygon Polygon_createSimple (char32 *xystring) {
 	}
 }
 
-autoPolygon Polygon_createFromRandomVertices (long numberOfVertices, double xmin, double xmax, double ymin, double ymax) {
+autoPolygon Polygon_createFromRandomPoints (long numberOfVertices, double xmin, double xmax, double ymin, double ymax) {
 	try {
 		autoPolygon me = Polygon_create (numberOfVertices);
 		for (long i = 1; i <= numberOfVertices; i++) {
diff --git a/dwtools/Polygon_extensions.h b/dwtools/Polygon_extensions.h
index 98a9b68..ec30842 100644
--- a/dwtools/Polygon_extensions.h
+++ b/dwtools/Polygon_extensions.h
@@ -2,7 +2,7 @@
 #define _Polygon_extensions_h_
 /* Polygon_extensions.h
  *
- * Copyright (C) 1993-2012, 2014, 2015 David Weenink
+ * Copyright (C) 1993-2012, 2014, 2015-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@ void Polygon_getExtrema (Polygon me, double *xmin, double *xmax, double *ymin, d
 
 autoPolygon Polygon_createSimple (char32 *xystring);
 
-autoPolygon Polygon_createFromRandomVertices (long numberOfVertices, double xmin, double xmax, double ymin, double ymax);
+autoPolygon Polygon_createFromRandomPoints (long numberOfVertices, double xmin, double xmax, double ymin, double ymax);
 
 autoPolygon Polygon_simplify (Polygon me);
 
diff --git a/dwtools/Polynomial_def.h b/dwtools/Polynomial_def.h
index 775a709..3609185 100644
--- a/dwtools/Polynomial_def.h
+++ b/dwtools/Polynomial_def.h
@@ -57,8 +57,8 @@ oo_DEFINE_CLASS (Spline, FunctionTerms)
 	
 	#if oo_DECLARING
 		// overridden methods:
-			virtual double v_evaluate (double x);
-			virtual long v_getDegree ();
+			virtual double v_evaluate (double x) override;
+			virtual long v_getDegree () override;
 		// new methods:
 			virtual long v_getOrder ();
 	#endif
diff --git a/dwtools/SpeechSynthesizer.cpp b/dwtools/SpeechSynthesizer.cpp
index 2d0c48b..394efbe 100644
--- a/dwtools/SpeechSynthesizer.cpp
+++ b/dwtools/SpeechSynthesizer.cpp
@@ -392,6 +392,7 @@ static void IntervalTier_mergeSpecialIntervals (IntervalTier me) {
 	}
 }
 
+#if 0
 /* insert boundary at time t and merge/delete intervals after this time */
 static void IntervalTier_insertBoundaryAndMergeIntervalsAfter (IntervalTier me, double t) {
 	if (t <= my xmin || t >= my xmax) {
@@ -418,7 +419,7 @@ static void IntervalTier_insertBoundaryAndMergeIntervalsAfter (IntervalTier me,
 		TextInterval_setText (last, U"");
 	}
 }
-
+#endif
 
 static bool almost_equal (double t1, double t2) {
 	// the "=" sign is essential for a difference of zero if t1 == 0
diff --git a/dwtools/Strings_extensions.cpp b/dwtools/Strings_extensions.cpp
index 0b8c907..cc88dd7 100644
--- a/dwtools/Strings_extensions.cpp
+++ b/dwtools/Strings_extensions.cpp
@@ -243,7 +243,7 @@ autoStringsIndex Strings_to_StringsIndex (Strings me) {
 
 autoStrings StringsIndex_to_Strings (StringsIndex me) {
 	try {
-		autoStrings thee = Strings_createFixedLength (my numberOfElements);
+		autoStrings thee = Strings_createFixedLength (my numberOfItems);
 		for (long i = 1; i <= thy numberOfStrings; i ++) {
 			SimpleString s = (SimpleString) my classes->at [my classIndex [i]];   // FIXME cast, FIXME classIndex
 			thy strings [i] = Melder_dup (s -> string);
diff --git a/dwtools/TableOfReal_extensions.cpp b/dwtools/TableOfReal_extensions.cpp
index e0d85db..0102372 100644
--- a/dwtools/TableOfReal_extensions.cpp
+++ b/dwtools/TableOfReal_extensions.cpp
@@ -1000,7 +1000,7 @@ double TableOfReal_getColumnQuantile (TableOfReal me, long col, double quantile)
 
 static autoTableOfReal TableOfReal_createPolsVanNieropData (int choice, bool include_levels) {
 	try {
-		autoTable table = Table_createFromPolsVanNieropData ();
+		autoTable table = Table_create_polsVanNierop1973 ();
 
 		// Default: Pols 50 males, first part of the table.
 
@@ -1039,19 +1039,19 @@ static autoTableOfReal TableOfReal_createPolsVanNieropData (int choice, bool inc
 	}
 }
 
-autoTableOfReal TableOfReal_createFromPolsData_50males (bool include_levels) {
+autoTableOfReal TableOfReal_create_pols1973 (bool include_levels) {
 	return TableOfReal_createPolsVanNieropData (1, include_levels);
 }
 
-autoTableOfReal TableOfReal_createFromVanNieropData_25females (bool include_levels) {
+autoTableOfReal TableOfReal_create_vanNierop1973 (bool include_levels) {
 	return TableOfReal_createPolsVanNieropData (2, include_levels);
 }
 
-autoTableOfReal TableOfReal_createFromWeeninkData (int option) {
+autoTableOfReal TableOfReal_create_weenink1983 (int option) {
 	try {
 		long nvowels = 12, ncols = 3, nrows = 10 * nvowels;
 
-		autoTable table = Table_createFromWeeninkData ();
+		autoTable table = Table_create_weenink1983 ();
 
 		long ib = ( option == 1 ? 1 : option == 2 ? 11 : 21 ); /* m f c*/
 		ib = (ib - 1) * nvowels + 1;
diff --git a/dwtools/TableOfReal_extensions.h b/dwtools/TableOfReal_extensions.h
index 9edfc76..35d50e1 100644
--- a/dwtools/TableOfReal_extensions.h
+++ b/dwtools/TableOfReal_extensions.h
@@ -46,11 +46,11 @@ autoTableOfReal TableOfReal_sortRowsByIndex (TableOfReal me, long index[], int r
 
 autoTableOfReal TableOfReal_createIrisDataset ();
 
-autoTableOfReal TableOfReal_createFromPolsData_50males (bool include_levels);
+autoTableOfReal TableOfReal_create_pols1973 (bool include_levels);
 
-autoTableOfReal TableOfReal_createFromVanNieropData_25females (bool include_levels);
+autoTableOfReal TableOfReal_create_vanNierop1973 (bool include_levels);
 
-autoTableOfReal TableOfReal_createFromWeeninkData (int option); /* M W C */
+autoTableOfReal TableOfReal_create_weenink1983 (int option); /* M W C */
 
 void TableOfReal_getColumnExtrema (TableOfReal me, long col, double *min, double *max);
 
diff --git a/dwtools/Table_extensions.cpp b/dwtools/Table_extensions.cpp
index f4ec585..d50aef1 100644
--- a/dwtools/Table_extensions.cpp
+++ b/dwtools/Table_extensions.cpp
@@ -88,7 +88,7 @@ Phoneme Number, Phoneme Label, F0, F1, F2 and F3. The speaker types
 are type 1 (men), type 2 (women) and type 3 (children)."
 */
 
-autoTable Table_createFromPetersonBarneyData () {
+autoTable Table_create_petersonBarney1952 () {
 	long nrows = 1520, ncols = 9;
 	const char32 *columnLabels[9] = {U"Type", U"Sex", U"Speaker", U"Vowel", U"IPA", U"F0", U"F1", U"F2", U"F3"};
 	const char32 *type[3] = {U"m", U"w", U"c"};
@@ -1669,7 +1669,7 @@ autoTable Table_createFromPetersonBarneyData () {
 	}
 }
 
-autoTable Table_createFromPolsVanNieropData () {
+autoTable Table_create_polsVanNierop1973 () {
 	long nrows = 900, ncols = 10;
 	const char32 *columnLabels[10] = {U"Sex", U"Speaker", U"Vowel", U"IPA", U"F1", U"F2", U"F3", U"L1", U"L2", U"L3"};
 	const char32 *vowel[12] = {U"oe", U"aa", U"oo", U"a", U"eu", U"ie", U"uu", U"ee", U"u", U"e", U"o", U"i"};
@@ -2685,7 +2685,7 @@ autoTable Table_createFromPolsVanNieropData () {
 	}
 }
 
-autoTable Table_createFromWeeninkData () {
+autoTable Table_create_weenink1983 () {
 	long nrows = 360, ncols = 9;
 	const char32 *columnLabels[9] = {U"Type", U"Sex", U"Speaker", U"Vowel", U"IPA", U"F0", U"F1", U"F2", U"F3"};
 	const char32 *type[3] = {U"m", U"w", U"c"};
@@ -3128,7 +3128,7 @@ autoTable Table_createFromWeeninkData () {
 }
 
 // Keating&Esposito (2006), 
-autoTable Table_createFromEspositoData () {
+autoTable Table_create_esposito2006 () {
 	try {
 		autoTable me = Table_createWithColumnNames (10, U"Language Modal Breathy");
 		Table_setStringValue (me.get(), 1, 1, U"Chong");
@@ -3167,7 +3167,7 @@ autoTable Table_createFromEspositoData () {
 	}
 }
 
-autoTable Table_createFromGanongData () {
+autoTable Table_create_ganong1980 () {
 	try {
 		autoTable me = Table_createWithColumnNames (6, U"VOT dash-tash dask-task");
 		Table_setNumericValue (me.get(), 1, 1, -17.5);
diff --git a/dwtools/Table_extensions.h b/dwtools/Table_extensions.h
index af77c8c..3a866b8 100644
--- a/dwtools/Table_extensions.h
+++ b/dwtools/Table_extensions.h
@@ -34,15 +34,15 @@ long Table_getNumberOfRowsWhere (Table me, const char32 *formula, Interpreter in
 
 long *Table_findRowsMatchingCriterion (Table me, const char32 *formula, Interpreter interpreter, long *numberOfMatches);
 
-autoTable Table_createFromPetersonBarneyData ();
+autoTable Table_create_petersonBarney1952 ();
 
-autoTable Table_createFromPolsVanNieropData ();
+autoTable Table_create_polsVanNierop1973 ();
 
-autoTable Table_createFromWeeninkData ();
+autoTable Table_create_weenink1983 ();
 
-autoTable Table_createFromEspositoData ();
+autoTable Table_create_esposito2006 ();
 
-autoTable Table_createFromGanongData ();
+autoTable Table_create_ganong1980 ();
 
 double Table_getMedianAbsoluteDeviation (Table me, long columnNumber);
 
diff --git a/dwtools/TextGrid_extensions.cpp b/dwtools/TextGrid_extensions.cpp
index c11317c..2ebb671 100644
--- a/dwtools/TextGrid_extensions.cpp
+++ b/dwtools/TextGrid_extensions.cpp
@@ -149,8 +149,8 @@ autoDaata TextGrid_TIMITLabelFileRecognizer (int nread, const char *header, Meld
 	char hkruis[3] = "h#", label1[512], label2[512];
 	int length, phnFile = 0;
 	long it[5]; 
-	if (nread < 12 || sscanf (header, "%ld%ld%s%n\n", &it[1], &it[2], label1, &length) != 3 ||
-		it[1] < 0 || it[2] <= it[1] || sscanf (&header[length], "%ld%ld%s\n", &it[3], &it[4], label2) != 3 || it[4] <= it[3]) {
+	if (nread < 12 || sscanf (header, "%ld%ld%511s%n\n", &it[1], &it[2], label1, &length) != 3 ||
+		it[1] < 0 || it[2] <= it[1] || sscanf (&header[length], "%ld%ld%511s\n", &it[3], &it[4], label2) != 3 || it[4] <= it[3]) {
 		// 20120512 djmw removed the extra "it[3] < it[2]" check, because otherwise train/dr7/mdlm0/si1864.wrd cannot be read
 		return autoDaata ();
 	}
@@ -214,7 +214,7 @@ autoTextGrid TextGrid_readFromTIMITLabelFile (MelderFile file, int phnFile) {
 		while (fgets (line, 199, f)) {
 			long it1, it2;
 			linesRead++;
-			if (sscanf (line, "%ld%ld%s", &it1, &it2, label) != 3) {
+			if (sscanf (line, "%ld%ld%199s", &it1, &it2, label) != 3) {
 				Melder_throw (U"Incorrect number of items.");
 			}
 			if (it1 < 0 || it2 <= it1) {
@@ -450,12 +450,12 @@ void TextGrid_extendTime (TextGrid me, double extra_time, int position) {
 	autoTextGrid thee;
 	try {
 		double xmax = my xmax, xmin = my xmin;
-		int at_end = position == 0;
+		bool at_end = ( position == 0 );
 
-		if (extra_time == 0) {
+		if (extra_time == 0.0) {
 			return;
 		}
-		extra_time = fabs (extra_time); // Just in case...
+		extra_time = fabs (extra_time);   // just in case
 		thee = Data_copy (me);
 
 		if (at_end) {
diff --git a/dwtools/VowelEditor.cpp b/dwtools/VowelEditor.cpp
index 41761f7..4ac3488 100644
--- a/dwtools/VowelEditor.cpp
+++ b/dwtools/VowelEditor.cpp
@@ -655,14 +655,14 @@ static void VowelEditor_setMarks (VowelEditor me, int marksDataset, int speakerT
 	const char32 *Type[4] = { U"", U"m", U"w", U"c" };
 	const char32 *Sex[3] = { U"", U"m", U"f"};
 	if (marksDataset == 1) {   // American-English
-		autoTable thee = Table_createFromPetersonBarneyData ();
+		autoTable thee = Table_create_petersonBarney1952 ();
 		te = Table_extractRowsWhereColumn_string (thee.get(), 1, kMelder_string_EQUAL_TO, Type[speakerType]);
 	} else if (marksDataset == 2) {   // Dutch
 		if (speakerType == 1 || speakerType == 2) {   // male + female from Pols van Nierop
-			autoTable thee = Table_createFromPolsVanNieropData ();
+			autoTable thee = Table_create_polsVanNierop1973 ();
 			te = Table_extractRowsWhereColumn_string (thee.get(), 1, kMelder_string_EQUAL_TO, Sex[speakerType]);
 		} else {
-			autoTable thee = Table_createFromWeeninkData ();
+			autoTable thee = Table_create_weenink1983 ();
 			te = Table_extractRowsWhereColumn_string (thee.get(), 1, kMelder_string_EQUAL_TO, Type[speakerType]);
 		}
 	} else if (marksDataset == 3) {   // none
diff --git a/dwtools/manual_dwtools.cpp b/dwtools/manual_dwtools.cpp
index f645f1c..1118ba3 100644
--- a/dwtools/manual_dwtools.cpp
+++ b/dwtools/manual_dwtools.cpp
@@ -30,7 +30,7 @@
 
 
 static autoTableOfReal getStandardizedLogFrequencyPolsData (bool includeLevels) {
-	autoTableOfReal me = TableOfReal_createFromPolsData_50males (includeLevels);
+	autoTableOfReal me = TableOfReal_create_pols1973 (includeLevels);
 	for (long i = 1; i <= my numberOfRows; i++) {
 		for (long j = 1; j <= 3; j++) {
 			my data[i][j] = log10 (my data[i][j]);
@@ -1300,7 +1300,7 @@ DEFINITION (U"define the coefficients of each @@Legendre polynomials|Legendre po
 	"The coefficient of the polynomial with the highest degree comes last.")
 MAN_END
 
-MAN_BEGIN (U"Create Sound from gammatone...", U"djmw", 20100517)
+MAN_BEGIN (U"Create Sound as gammatone...", U"djmw", 20161013)
 INTRO (U"A command to create a @Sound as a @@gammatone at .")
 ENTRY (U"Settings")
 TAG (U"##Name")
@@ -1342,7 +1342,7 @@ NORMAL (U"To avoid @aliasing in the chirp sound, a sound is only generated durin
 	"instantaneous frequency is greater than zero and smaller than the @@Nyquist frequency at .")
 MAN_END
 
-MAN_BEGIN (U"Create Sound from Shepard tone...", U"djmw", 20140117)
+MAN_BEGIN (U"Create Sound as Shepard tone...", U"djmw", 20161013)
 INTRO (U"One of the commands that create a @Sound.")
 ENTRY (U"Settings")
 TAG (U"##Name")
@@ -1393,7 +1393,7 @@ NORMAL (U"The following script generates 12 static Shepard tone complexes, 1 sem
 CODE (U"fadeTime = 0.010")
 CODE (U"for i to 12")
 CODE1 (U"fraction = (i-1)/12")
-CODE1 (U"Create Sound from Shepard tone: \"s\" + string\\$  (i), 0, 0.1, 22050, 4.863, 10, 0, 34, fraction")
+CODE1 (U"Create Sound as Shepard tone: \"s\" + string\\$  (i), 0, 0.1, 22050, 4.863, 10, 0, 34, fraction")
 CODE1 (U"Fade in: 0, 0, fadeTime, \"no\"")
 CODE1 (U"Fade out: 0, 0.1, -fadeTime, \"no\"")
 CODE (U"endfor")
@@ -2203,6 +2203,33 @@ INTRO (U"A command to query the selected @Eigen for the %j^^th^ element of the "
 	"%i^^th^ eigenvector.")
 MAN_END
 
+MAN_BEGIN (U"Eigen: Extract eigenvector...", U"djmw", 20160617)
+INTRO (U"Extract a specified eigenvector from the @Eigen as a @Matrix.")
+ENTRY (U"Settings")
+TAG (U"##Eigenvector number")
+DEFINITION (U"determines the eigenvector.")
+TAG (U"##Number of rows")
+DEFINITION (U"determines the number of rows of the newly created Matrix. If left 0, the number of rows is determined from the dimension, i.e. the number of elements, of the eigenvector and the #numberOfColumns argument as the %dimension / %numberOfColumns, rounded to the next larger integer.")
+TAG (U"##Number of columns")
+DEFINITION (U"determines the number of columns of the newly created Matrix. If left 0, the number of columns is determined by from the dimension, i.e. the number of elements, of the eigenvector and the #numberOfRows argument as  %dimension / %numberOfRows, rounded to the next larger integer.\nIf both ##Number of rows# and ##Number of columns# are zero, a Matrix with only one row and %dimension columns will be created.")
+ENTRY (U"Examples")
+NORMAL (U"Suppose we have an eigenvector of dimension 3 with elements {0.705, 0.424, 0.566}, then the newly created Matrix will depend on the ##Number of rows# and ##Number of columns# argument as follows:")
+NORMAL (U"If %numberOfRows=0 and %numberOfColumns=0, then the Matrix will have 1 row and 3 columns:")
+CODE (U"0.705 0.424 0.566")
+NORMAL (U"If %numberOfRows=3 and %numberOfColumns=0, then the Matrix will have 3 rows and 1 column:")
+CODE (U"0.705")
+CODE (U"0.424")
+CODE (U"0.566")
+NORMAL (U"If %numberOfRows=2 and %numberOfColumns=2, then the Matrix will have 2 rows and 2 columns:")
+CODE (U"0.705 0.424")
+CODE (U"0.566 0.0")
+NORMAL (U"If %numberOfRows=4 and %numberOfColumns=3, then the we get:")
+CODE (U"0.705 0.424 0.566")
+CODE (U"0.0   0.0   0.0 ")
+CODE (U"0.0   0.0   0.0 ")
+CODE (U"0.0   0.0   0.0 ")
+MAN_END
+
 MAN_BEGIN (U"Eigen & Matrix: To Matrix (project columns)...", U"djmw", 20160223)
 INTRO (U"A command to project the columns of the @Matrix object onto the "
 	"eigenspace of the @Eigen object.")
@@ -3484,7 +3511,7 @@ SCRIPT (5.4, Manual_SETTINGS_WINDOW_HEIGHT (5), U""
 	Manual_DRAW_SETTINGS_WINDOW ("Sound: Draw where...", 5)
 	Manual_DRAW_SETTINGS_WINDOW_RANGE("Time range (s)", "0.0", "0.0 (= all)")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Vertical range", "0.0", "0.0 (= all)")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", true)
 	Manual_DRAW_SETTINGS_WINDOW_OPTIONMENU("Drawing method", "Curve")
 	Manual_DRAW_SETTINGS_WINDOW_TEXT ("Draw only those parts where the following condition holds",
 		"x < xmin + (xmax - xmin) / 2; first half")
@@ -3642,7 +3669,7 @@ SCRIPT (5.4, Manual_SETTINGS_WINDOW_HEIGHT (6), U""
 	Manual_DRAW_SETTINGS_WINDOW_RANGE("Time range (s)", "0.0", "0.0 (= all)")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Vertical range", "0.0", "0.0 (= all)")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Fill from level", "0")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", true)
 	Manual_DRAW_SETTINGS_WINDOW_TEXT ("Paint only those parts where the following condition holds",
 		"1; always")
 )
@@ -3709,7 +3736,7 @@ SCRIPT (5.4, Manual_SETTINGS_WINDOW_HEIGHT (4), U""
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Colour (0-1, name, {r,g,b})", "0.5")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE("Time range (s)", "0.0", "0.0 (= all)")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Vertical range", "0.0", "0.0 (= all)")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", true)
 )
 TAG (U"##Colour")
 DEFINITION (U"defines the @@Colour|colour@ of the paint.")
@@ -4203,7 +4230,7 @@ SCRIPT (6, Manual_SETTINGS_WINDOW_HEIGHT (10), U""
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Distance between bars within group", "0.0")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Colours (0-1, name, {r,g,b})", "Grey")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Label text angle (degrees)", "0.0")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", true)
 	Manual_DRAW_SETTINGS_WINDOW_TEXT("Formula:", "row>1 and row < 10")
 )
 TAG (U"##Vertical column(s)")
@@ -4293,7 +4320,7 @@ SCRIPT (7, Manual_SETTINGS_WINDOW_HEIGHT (8), U""
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Horizontal range", "0.0", "0.0 (= autoscaling)")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Text", "+")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Label text angle (degrees)", "0.0")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", true)
 	Manual_DRAW_SETTINGS_WINDOW_TEXT("Formula:", "1; (= everything)")
 )
 TAG (U"##Vertical column")
@@ -4397,7 +4424,7 @@ SCRIPT (6, Manual_SETTINGS_WINDOW_HEIGHT (9), U""
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Lower error value column", "")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Upper error value column", "")
 	Manual_DRAW_SETTINGS_WINDOW_FIELD ("Bar size (mm)", "1.0")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN("Garnish", true)
 	Manual_DRAW_SETTINGS_WINDOW_TEXT("Formula", "1; (= everything)")
 )
 TAG (U"##Horizontal column")
diff --git a/dwtools/praat_BSS_init.cpp b/dwtools/praat_BSS_init.cpp
index 7ae0a20..31058ec 100644
--- a/dwtools/praat_BSS_init.cpp
+++ b/dwtools/praat_BSS_init.cpp
@@ -1,6 +1,6 @@
 /* praat_BSS_init.cpp
  *
- * Copyright (C) 2010-2014,2015 David Weenink, 2015 Paul Boersma
+ * Copyright (C) 2010-2016 David Weenink, 2015 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,535 +16,400 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-/*
-	djmw 20101003
-	djmw 20110101 Latest modification
-*/
-
 #include "praat.h"
+#include "praat_TimeFunction.h"
 
 #include "EEG_extensions.h"
 #include "ICA.h"
+#include "praat_TimeFunction.h"
 #include "Sound_and_PCA.h"
 
-#undef iam
-#define iam iam_LOOP
-
 void praat_SSCP_as_TableOfReal_init (ClassInfo klas);
-void praat_TableOfReal_init (ClassInfo klas);
 void praat_TableOfReal_init3 (ClassInfo klas);
 
 
 /******************** EEG ********************************************/
 
-FORM (EEG_to_CrossCorrelationTable, U"EEG: To CrossCorrelationTable", U"EEG: To CrossCorrelationTable...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	REAL (U"Lag step (s)", U"0.05")
-	TEXTFIELD (U"Channel ranges", U"1:64")
+FORM (NEW_EEG_to_CrossCorrelationTable, U"EEG: To CrossCorrelationTable", U"EEG: To CrossCorrelationTable...") {
+	praat_TimeFunction_RANGE (fromTime,toTime)
+	REALVAR (lagTime, U"Lag step (s)", U"0.05")
+	TEXTVAR (channelRanges, U"Channel ranges", U"1:64")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
 	OK
 DO
-	double startTime = GET_REAL (U"left Time range"), endTime = GET_REAL (U"right Time range");
-	double lagTime = GET_REAL (U"Lag step");
-	const char32 *channelRanges = GET_STRING (U"Channel ranges");
-	LOOP {
-		iam (EEG);
-		autoCrossCorrelationTable cct = EEG_to_CrossCorrelationTable (me, startTime, endTime, lagTime, channelRanges);
-		praat_new (cct.move(), my name, U"_", (long) floor (lagTime*1000)); // lagTime to ms   ppgb: geeft afrondingsfouten; waarom niet round?
-	}
-END
-
-FORM (EEG_to_Covariance, U"EEG: To Covariance", U"EEG: To Covariance...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	TEXTFIELD (U"Channel ranges", U"1:64")
+	CONVERT_EACH (EEG)
+		autoCrossCorrelationTable result = EEG_to_CrossCorrelationTable (me, fromTime, toTime, lagTime, channelRanges);
+	CONVERT_EACH_END (my name, U"_", round (lagTime * 1000.0))
+}
+
+FORM (NEW_EEG_to_Covariance, U"EEG: To Covariance", U"EEG: To Covariance...") {
+	praat_TimeFunction_RANGE (fromTime,toTime)
+	TEXTVAR (channelRanges, U"Channel ranges", U"1:64")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
 	OK
 DO
-	double startTime = GET_REAL (U"left Time range"), endTime = GET_REAL (U"right Time range");
-	const char32 *channelRanges = GET_STRING (U"Channel ranges");
-	LOOP {
-		iam (EEG);
-		autoCovariance cov = EEG_to_Covariance (me, startTime, endTime, channelRanges);
-		praat_new (cov.move(), my name);
-	}
-END
-
-FORM (EEG_to_CrossCorrelationTableList, U"EEG: To CrossCorrelationTableList", U"EEG: To CrossCorrelationTableList...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	POSITIVE (U"Lag step (s)", U"0.02")
-	NATURAL (U"Number of cross-correlations", U"40")
+	CONVERT_EACH (EEG)
+		autoCovariance result = EEG_to_Covariance (me, fromTime, toTime, channelRanges);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_EEG_to_CrossCorrelationTableList, U"EEG: To CrossCorrelationTableList", U"EEG: To CrossCorrelationTableList...") {
+	praat_TimeFunction_RANGE (fromTime,toTime)
+	POSITIVEVAR (lagTime, U"Lag step (s)", U"0.02")
+	NATURALVAR (numberOfCrossCorrelations, U"Number of cross-correlations", U"40")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
-	TEXTFIELD (U"Channel ranges", U"1:64")
+	TEXTVAR (channelRanges, U"Channel ranges", U"1:64")
 	OK
 DO
-	LOOP {
-		iam (EEG);
-		autoCrossCorrelationTableList thee = EEG_to_CrossCorrelationTableList (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Lag step"), GET_INTEGER (U"Number of cross-correlations"), GET_STRING (U"Channel ranges"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (EEG_to_EEG_bss, U"EEG: To EEG (bss)", U"EEG: To EEG (bss)...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	NATURAL (U"Number of cross-correlations", U"40")
-	POSITIVE (U"Lag step (s)", U"0.002")
+	CONVERT_EACH (EEG)
+		autoCrossCorrelationTableList result = EEG_to_CrossCorrelationTableList (me, fromTime, toTime,
+			lagTime, numberOfCrossCorrelations, channelRanges);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_EEG_to_EEG_bss, U"EEG: To EEG (bss)", U"EEG: To EEG (bss)...") {
+	praat_TimeFunction_RANGE (fromTime,toTime)
+	NATURALVAR (numberOfCrossCorrelations, U"Number of cross-correlations", U"40")
+	POSITIVEVAR (lagTime, U"Lag step (s)", U"0.002")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
-	TEXTFIELD (U"Channel ranges", U"1:64")
+	TEXTVAR (channels, U"Channel ranges", U"1:64")
 	LABEL (U"", U"Pre-whitening parameters")
-	OPTIONMENU (U"Whitening method", 1)
+	OPTIONMENUVAR (whiteningMethod, U"Whitening method", 1)
 		OPTION (U"No whitening")
 		OPTION (U"Covariance")
 		OPTION (U"Correlation")
 	LABEL (U"", U"Iteration parameters")
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
-	OPTION (U"qdiag")
-	OPTION (U"ffdiag")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENUVAR (diagonalizationMethod, U"Diagonalization method", 2)
+		OPTION (U"qdiag")
+		OPTION (U"ffdiag")
 	OK
 DO
-	int whiteningMethod = GET_INTEGER (U"Whitening method") - 1;
-	LOOP {
-		iam (EEG);
-		autoEEG thee = EEG_to_EEG_bss (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"Number of cross-correlations"), GET_REAL (U"Lag step"), GET_STRING (U"Channel ranges"),
-			whiteningMethod, GET_INTEGER (U"Diagonalization method"),
-			GET_INTEGER (U"Maximum number of iterations"), GET_REAL (U"Tolerance"));
-		praat_new (thee.move(), my name, U"_bss");
-	}
-END
-
-FORM (EEG_to_PCA, U"EEG: To PCA", U"EEG: To PCA...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	TEXTFIELD (U"Channel ranges", U"1:64")
+	CONVERT_EACH (EEG)
+		autoEEG result = EEG_to_EEG_bss (me, fromTime, toTime, numberOfCrossCorrelations, lagTime, channels, whiteningMethod - 1, diagonalizationMethod, maximumNumberOfIterations, tolerance);
+	CONVERT_EACH_END (my name, U"_bss")
+}
+
+
+FORM (NEW_EEG_to_PCA, U"EEG: To PCA", U"EEG: To PCA...") {
+	praat_TimeFunction_RANGE (fromTime,toTime)
+	TEXTVAR (channelRanges, U"Channel ranges", U"1:64")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
-	OPTIONMENU (U"Use", 1)
+	OPTIONMENUVAR (method, U"Method", 1)
 		OPTION (U"Covariance")
 		OPTION (U"Correlation")
 	OK
 DO
-	double startTime = GET_REAL (U"left Time range"), endTime = GET_REAL (U"right Time range");
-	const char32 *channelRanges = GET_STRING (U"Channel ranges");
-	bool useCorrelation = GET_INTEGER (U"Use") == 2;
-	LOOP {
-		iam (EEG);
-		autoPCA pca = EEG_to_PCA (me, startTime, endTime, channelRanges, useCorrelation);
-		praat_new (pca.move(), my name);
-	}
-END
-
-FORM (EEG_and_PCA_to_EEG_principalComponents, U"EEG & PCA: To EEG (principal components)", U"EEG & PCA: To EEG (principal components)...")
-	INTEGER (U"Number of components", U"0 (= all)")
+	CONVERT_EACH (EEG)
+		autoPCA result = EEG_to_PCA (me, fromTime, toTime, channelRanges, (method == 2));
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW1_EEG_and_PCA_to_EEG_principalComponents, U"EEG & PCA: To EEG (principal components)", U"EEG & PCA: To EEG (principal components)...") {
+	INTEGERVAR (numberOfComponents, U"Number of components", U"0 (= all)")
 	OK
 DO
-	EEG me = FIRST (EEG);
-	PCA thee = FIRST (PCA);
-	autoEEG him = EEG_and_PCA_to_EEG_principalComponents (me, thee, GET_INTEGER (U"Number of components"));
-	praat_new (him.move(), my name, U"_pc");
-END
-
-FORM (EEG_and_PCA_to_EEG_whiten, U"EEG & PCA: To EEG (whiten)", U"EEG & PCA: To EEG (whiten)...")
-	INTEGER (U"Number of components", U"0 (= all)")
+	CONVERT_TWO (EEG, PCA)
+		autoEEG result = EEG_and_PCA_to_EEG_principalComponents (me, you, numberOfComponents);
+	CONVERT_TWO_END (my name, U"_pc")
+}
+
+FORM (NEW1_EEG_and_PCA_to_EEG_whiten, U"EEG & PCA: To EEG (whiten)", U"EEG & PCA: To EEG (whiten)...") {
+	INTEGERVAR (numberOfComponents, U"Number of components", U"0 (= all)")
 	OK
 DO
-	EEG me = FIRST (EEG);
-	PCA thee = FIRST (PCA);
-	autoEEG him = EEG_and_PCA_to_EEG_whiten (me, thee, GET_INTEGER (U"Number of components"));
-	praat_new (him.move(), my name, U"_white");
-END
-
-FORM (EEG_to_Sound_modulated, U"EEG: To Sound (modulated)", 0)
-	POSITIVE (U"Start frequency (Hz)", U"100.0")
-	POSITIVE (U"Channel bandwidth (Hz)", U"100.0")
-	TEXTFIELD (U"Channel ranges", U"1:64")
+	CONVERT_TWO (EEG, PCA)
+		autoEEG result = EEG_and_PCA_to_EEG_whiten (me, you, numberOfComponents);
+	CONVERT_TWO_END (my name, U"_white");
+}
+
+FORM (NEW_EEG_to_Sound_modulated, U"EEG: To Sound (modulated)", nullptr) {
+	POSITIVEVAR (baseFrequency, U"Base frequency (Hz)", U"100.0")
+	POSITIVEVAR (channelBandwidth, U"Channel bandwidth (Hz)", U"100.0")
+	TEXTVAR (channelRanges, U"Channel ranges", U"1:64")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
 	OK
 DO
-	LOOP {
-		iam (EEG);
-		autoSound thee = EEG_to_Sound_modulated (me, GET_REAL (U"Start frequency"), GET_REAL (U"Channel bandwidth"),
-			GET_STRING (U"Channel ranges"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (EEG_to_Sound_frequencyShifted, U"EEG: To Sound (frequency shifted)", 0)
-	NATURAL (U"Channel", U"1")
-	POSITIVE (U"Frequency shift (Hz)", U"100.0")
-	POSITIVE (U"Sampling frequecy (Hz)", U"11025.0")
-	REAL (U"Maximum amplitude", U"0.99")
+	CONVERT_EACH (EEG)
+		autoSound result = EEG_to_Sound_modulated (me, baseFrequency, channelBandwidth, channelRanges);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_EEG_to_Sound_frequencyShifted, U"EEG: To Sound (frequency shifted)", 0) {
+	NATURALVAR (channel, U"Channel", U"1")
+	POSITIVEVAR (frequencyShift, U"Frequency shift (Hz)", U"100.0")
+	POSITIVEVAR (samplingFrequency, U"Sampling frequecy (Hz)", U"11025.0")
+	REALVAR (maximumAmplitude, U"Maximum amplitude", U"0.99")
 	OK
 DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (EEG);
-		autoSound thee = EEG_to_Sound_frequencyShifted (me, channel, GET_REAL (U"Frequency shift"),
-			GET_REAL (U"Sampling frequecy"), GET_REAL (U"Maximum amplitude"));
-		praat_new (thee.move(), my name, U"_ch", channel);
-	}
-END
+	CONVERT_EACH (EEG)
+		autoSound result = EEG_to_Sound_frequencyShifted (me, channel, frequencyShift, samplingFrequency, maximumAmplitude);
+	CONVERT_EACH_END (my name, U"_ch", channel)
+}
 
 /********************** CrossCorrelationTable(s) ******************/
 
-FORM (CrossCorrelationTableList_createTestSet, U"CrossCorrelationTableList: Create test set", U"CrossCorrelationTableList: Create test set...")
-	WORD (U"Name", U"5x5")
-	NATURAL (U"Matrix dimension", U"5")
-	NATURAL (U"Number of matrices", U"20")
-	BOOLEAN (U"First is positive definite", 1)
-	REAL (U"Sigma", U"0.02")
+FORM (NEW1_CrossCorrelationTableList_createTestSet, U"CrossCorrelationTableList: Create test set", U"CrossCorrelationTableList: Create test set...") {
+	WORDVAR (name, U"Name", U"5x5")
+	NATURALVAR (matrixDimension, U"Matrix dimension", U"5")
+	NATURALVAR (numberOfMatrices, U"Number of matrices", U"20")
+	BOOLEANVAR (firstIsPositiveDefinite, U"First is positive definite", true)
+	REALVAR (sigma, U"Sigma", U"0.02")
 	OK
 DO
-	autoCrossCorrelationTableList thee = CrossCorrelationTableList_createTestSet (GET_INTEGER (U"Matrix dimension"),
-		GET_INTEGER (U"Number of matrices"), GET_INTEGER (U"First is positive definite"), GET_REAL (U"Sigma"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
-
-FORM (CrossCorrelationTable_createSimple, U"Create simple CrossCorrelationTable", 0)
-	WORD (U"Name", U"ct")
-	SENTENCE (U"Cross correlations", U"1.0 0.0 1.0")
-	SENTENCE (U"Centroid", U"0.0 0.0")
-	NATURAL (U"Number of samples", U"100")
+	CREATE_ONE
+		autoCrossCorrelationTableList result = CrossCorrelationTableList_createTestSet (matrixDimension, numberOfMatrices, firstIsPositiveDefinite, sigma);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_CrossCorrelationTable_createSimple, U"Create simple CrossCorrelationTable", nullptr) {
+	WORDVAR (name, U"Name", U"ct")
+	SENTENCEVAR (crosscorrelations_string, U"Cross correlations", U"1.0 0.0 1.0")
+	SENTENCEVAR (centroid_string, U"Centroid", U"0.0 0.0")
+	NATURALVAR (numberOfSamples, U"Number of samples", U"100")
 	OK
 DO
-	autoCrossCorrelationTable thee = CrossCorrelationTable_createSimple (GET_STRING (U"Cross correlations"), GET_STRING (U"Centroid"),
-		GET_INTEGER (U"Number of samples"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
-
-FORM (MixingMatrix_createSimple, U"Create simple MixingMatrix", 0)
-	WORD (U"Name", U"mm")
-	NATURAL (U"Number of channels", U"2")
-	NATURAL (U"Number of components", U"2")
-	SENTENCE (U"Mixing coefficients", U"1.0 1.0 1.0 1.0")
+	CREATE_ONE
+		autoCrossCorrelationTable result = CrossCorrelationTable_createSimple (crosscorrelations_string, centroid_string, numberOfSamples);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_MixingMatrix_createSimple, U"Create simple MixingMatrix", nullptr) {
+	WORDVAR (name, U"Name", U"mm")
+	NATURALVAR (numberOfChannels, U"Number of channels", U"2")
+	NATURALVAR (numberOfComponents, U"Number of components", U"2")
+	SENTENCEVAR (mixinCoefficients_string, U"Mixing coefficients", U"1.0 1.0 1.0 1.0")
 	OK
 DO
-	autoMixingMatrix thee = MixingMatrix_createSimple (GET_INTEGER (U"Number of channels"), GET_INTEGER (U"Number of components"),
-		GET_STRING (U"Mixing coefficients"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoMixingMatrix result = MixingMatrix_createSimple (numberOfChannels, numberOfComponents, mixinCoefficients_string);
+	CREATE_ONE_END (name)
+}
 
-DIRECT (CrossCorrelationTable_help)
-	Melder_help (U"CrossCorrelationTable");
-END
+DIRECT (HELP_CrossCorrelationTable_help) {
+	HELP (U"CrossCorrelationTable");
+}
 
-FORM (Sound_and_PCA_principalComponents, U"Sound & PCA: To Sound (principal components)", 0)
-	NATURAL (U"Number of components", U"10")
+FORM (NEW1_Sound_and_PCA_principalComponents, U"Sound & PCA: To Sound (principal components)", nullptr) {
+	NATURALVAR (numberOfComponents, U"Number of components", U"10")
 	OK
 DO
-	Sound me = FIRST (Sound);
-	PCA thee = FIRST (PCA);
-	autoSound him = Sound_and_PCA_principalComponents (me, thee, GET_INTEGER (U"Number of components"));
-	praat_new (him.move(), my name, U"_pc");
-END
-
-FORM (Sound_and_PCA_whitenChannels, U"Sound & PCA: To Sound (white channels)", 0)
-	NATURAL (U"Number of components", U"10")
+	CONVERT_TWO (Sound, PCA)
+		autoSound result = Sound_and_PCA_principalComponents (me, you, numberOfComponents);
+	CONVERT_TWO_END (my name, U"_pc")
+}
+
+FORM (NEW1_Sound_and_PCA_whitenChannels, U"Sound & PCA: To Sound (white channels)", nullptr) {
+	NATURALVAR (numberOfComponents, U"Number of components", U"10")
 	OK
 DO
-	Sound me = FIRST (Sound);
-	PCA thee = FIRST (PCA);
-	autoSound him = Sound_and_PCA_whitenChannels (me, thee, GET_INTEGER (U"Number of components"));
-	praat_new (him.move(), my name, U"_white");
-END
-
-DIRECT (CrossCorrelationTable_to_CrossCorrelationTableList)
-	autoCrossCorrelationTableList thee = CrossCorrelationTableList_create ();
-	long nrows = 0, ncols = 0, nselected = 0;
-	LOOP {
-		iam (CrossCorrelationTable);
-		nselected++;
-		if (nselected == 1) {
-			nrows = my numberOfRows;
-			ncols = my numberOfColumns;
-		}
-		if (my numberOfRows != nrows || my numberOfColumns != ncols) {
-			Melder_throw (U"Dimensions of table ", IOBJECT, U" differs from the rest.");
-		}
-		autoCrossCorrelationTable myc = Data_copy (me);
-		thy addItem_move (myc.move());
-	}
-	praat_new (thee.move(), U"ct_", nselected);
-END
-
-FORM (Sound_to_Covariance_channels, U"Sound: To Covariance (channels)", U"Sound: To Covariance (channels)...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
+	CONVERT_TWO (Sound, PCA)
+		autoSound result = Sound_and_PCA_whitenChannels (me, you, numberOfComponents);
+	CONVERT_TWO_END (my name, U"_white")
+}
+
+DIRECT (NEW1_CrossCorrelationTables_to_CrossCorrelationTableList) {
+	CONVERT_LIST (CrossCorrelationTable)
+		autoCrossCorrelationTableList result = CrossCorrelationTables_to_CrossCorrelationTableList (& list);
+	CONVERT_LIST_END (U"ct_", result -> size)
+}
+
+FORM (NEW_Sound_to_Covariance_channels, U"Sound: To Covariance (channels)", U"Sound: To Covariance (channels)...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoCovariance thee = Sound_to_Covariance_channels (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_CrossCorrelationTable, U"Sound: To CrossCorrelationTable", U"Sound: To CrossCorrelationTable...")
-    REAL (U"left Time range (s)", U"0.0")
-    REAL (U"right Time range (s)", U"10.0")
-    REAL (U"Lag step (s)", U"0.0")
+	CONVERT_EACH (Sound)
+		autoCovariance result = Sound_to_Covariance_channels (me, fromTime, toTime);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_CrossCorrelationTable, U"Sound: To CrossCorrelationTable", U"Sound: To CrossCorrelationTable...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (lagStep, U"Lag step (s)", U"0.0")
     OK
 DO
-	double lagTime = fabs (GET_REAL (U"Lag step"));
-    LOOP {
-        iam (Sound);
-		autoCrossCorrelationTable thee = Sound_to_CrossCorrelationTable (me, GET_REAL (U"left Time range"),
-        GET_REAL (U"right Time range"), lagTime);
-        praat_new (thee.move(), my name);
-    }
-END
-
-FORM (Sounds_to_CrossCorrelationTable_combined, U"Sound: To CrossCorrelationTable (combined)", 0)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	REAL (U"Lag step (s)", U"0.0")
+    CONVERT_EACH (Sound)
+		autoCrossCorrelationTable result = Sound_to_CrossCorrelationTable (me, fromTime, toTime, lagStep);
+    CONVERT_EACH_END (my name)
+}
+
+FORM (NEW1_Sounds_to_CrossCorrelationTable_combined, U"Sound: To CrossCorrelationTable (combined)", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (lagStep, U"Lag step (s)", U"0.0")
 	OK
 DO
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoCrossCorrelationTable thee = Sounds_to_CrossCorrelationTable_combined (s1, s2, GET_REAL (U"left Time range"),
-		GET_REAL (U"right Time range"), GET_REAL (U"Lag step"));
-	praat_new (thee.move(), s1 -> name, U"_", s2 -> name, U"_cc");
-END
-
-DIRECT (CrossCorrelationTableList_help)
-Melder_help (U"CrossCorrelationTableList");
-	END
-
-FORM (CrossCorrelationTableList_getDiagonalityMeasure, U"CrossCorrelationTableList: Get diagonality measure", U"CrossCorrelationTableList: Get diagonality measure...")
-	NATURAL (U"First table", U"1")
-	NATURAL (U"Last table", U"100")
+	CONVERT_COUPLE (Sound)
+		autoCrossCorrelationTable result = Sounds_to_CrossCorrelationTable_combined (me, you, fromTime, toTime, lagStep);
+	CONVERT_COUPLE_END (my name, U"_", your name, U"_cc")
+}
+
+DIRECT (HELP_CrossCorrelationTableList_help) {
+	HELP (U"CrossCorrelationTableList")
+}
+
+FORM (REAL_CrossCorrelationTableList_getDiagonalityMeasure, U"CrossCorrelationTableList: Get diagonality measure", U"CrossCorrelationTableList: Get diagonality measure...") {
+	NATURALVAR (fromTable, U"First table", U"1")
+	NATURALVAR (toTable, U"Last table", U"100")
 	OK
 DO
-	LOOP {
-		iam (CrossCorrelationTableList);
-		double dm = CrossCorrelationTableList_getDiagonalityMeasure (me, 0, GET_INTEGER (U"First table"),
-		GET_INTEGER (U"Last table"));
-		Melder_information (dm, U" (= average sum of squared off-diagonal elements)");
-	}
-END
-
-FORM (CrossCorrelationTableList_extractCrossCorrelationTable, U"CrossCorrelationTableList: Extract one CrossCorrelationTable", nullptr)
-	NATURAL (U"Index", U"1")
+	NUMBER_ONE (CrossCorrelationTableList)
+		double result = CrossCorrelationTableList_getDiagonalityMeasure (me, 0, fromTable, toTable);
+	NUMBER_ONE_END (U" (= average sum of squared off-diagonal elements)")
+}
+
+FORM (NEW_CrossCorrelationTableList_extractCrossCorrelationTable, U"CrossCorrelationTableList: Extract one CrossCorrelationTable", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (CrossCorrelationTableList);
+	CONVERT_EACH (CrossCorrelationTableList)
 		if (index > my size) {
 			Melder_throw (U"Index too large.");
 		}
-		autoCrossCorrelationTable thee = Data_copy (my at [index]);
-		praat_new (thee.move(), Thing_getName (me), U"_", index);
-	}
-END
-
-FORM (CrossCorrelationTableList_to_Diagonalizer, U"CrossCorrelationTableList: To Diagonalizer", nullptr)
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
-	OPTION (U"qdiag")
-	OPTION (U"ffdiag")
+		autoCrossCorrelationTable result = Data_copy (my at [index]);
+	CONVERT_EACH_END (my name, U"_", index)
+}
+
+FORM (NEW_CrossCorrelationTableList_to_Diagonalizer, U"CrossCorrelationTableList: To Diagonalizer", nullptr) {
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENUVAR (diagonalizationMethod, U"Diagonalization method", 2)
+		OPTION (U"qdiag")
+		OPTION (U"ffdiag")
 	OK
 DO
-	LOOP {
-		iam (CrossCorrelationTableList);
-		autoDiagonalizer thee = CrossCorrelationTableList_to_Diagonalizer (me, GET_INTEGER (U"Maximum number of iterations"),
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Diagonalization method"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Diagonalizer_and_CrossCorrelationTableList_improveDiagonality, U"Diagonalizer & CrossCorrelationTableList: Improve diagonality", nullptr)
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
-	OPTION (U"qdiag")
-	OPTION (U"ffdiag")
+	CONVERT_EACH (CrossCorrelationTableList)
+		autoDiagonalizer result = CrossCorrelationTableList_to_Diagonalizer (me, maximumNumberOfIterations, tolerance, diagonalizationMethod);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (MODIFY_Diagonalizer_and_CrossCorrelationTableList_improveDiagonality, U"Diagonalizer & CrossCorrelationTableList: Improve diagonality", nullptr) {
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENUVAR (diagonalizationMethod, U"Diagonalization method", 2)
+		OPTION (U"qdiag")
+		OPTION (U"ffdiag")
 	OK
 DO
-	Diagonalizer d = FIRST (Diagonalizer);
-	CrossCorrelationTableList ccts = FIRST (CrossCorrelationTableList);
-	Diagonalizer_and_CrossCorrelationTableList_improveDiagonality (d, ccts, GET_INTEGER (U"Maximum number of iterations"),
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Diagonalization method"));
-END
-
-FORM (CrossCorrelationTableList_and_Diagonalizer_getDiagonalityMeasure, U"CrossCorrelationTableList & Diagonalizer: Get diagonality measure", nullptr)
-	NATURAL (U"First table", U"1")
-	NATURAL (U"Last table", U"100")
+	MODIFY_FIRST_OF_TWO (Diagonalizer, CrossCorrelationTableList)
+		Diagonalizer_and_CrossCorrelationTableList_improveDiagonality (me, you, maximumNumberOfIterations, tolerance, diagonalizationMethod);
+	MODIFY_FIRST_OF_TWO_END	
+}
+
+FORM (REAL_CrossCorrelationTableList_and_Diagonalizer_getDiagonalityMeasure, U"CrossCorrelationTableList & Diagonalizer: Get diagonality measure", nullptr) {
+	NATURALVAR (fromTable, U"First table", U"1")
+	NATURALVAR (toTable, U"Last table", U"100")
 	OK
 DO
-	CrossCorrelationTableList ccts = FIRST (CrossCorrelationTableList);
-	Diagonalizer d = FIRST (Diagonalizer);
-	double dm = CrossCorrelationTableList_and_Diagonalizer_getDiagonalityMeasure (ccts, d, 0, GET_INTEGER (U"First table"),
-		GET_INTEGER (U"Last table"));
-	Melder_information (dm, U" (= average sum of squared off-diagonal elements)");
-END
-
-DIRECT (CrossCorrelationTable_and_Diagonalizer_diagonalize)
-	CrossCorrelationTable cct = FIRST (CrossCorrelationTable);
-	Diagonalizer d = FIRST (Diagonalizer);
-	autoCrossCorrelationTable thee = CrossCorrelationTable_and_Diagonalizer_diagonalize (cct, d);
-	praat_new (thee.move(), cct -> name, U"_", d -> name);
-END
-
-DIRECT (CrossCorrelationTableList_and_Diagonalizer_diagonalize)
-	CrossCorrelationTableList ccts = FIRST (CrossCorrelationTableList);
-	Diagonalizer d = FIRST (Diagonalizer);
-	autoCrossCorrelationTableList thee = CrossCorrelationTableList_and_Diagonalizer_diagonalize (ccts, d);
-	praat_new (thee.move(), ccts->name, U"_", d->name);
-END
-
-FORM (CrossCorrelationTableList_and_MixingMatrix_improveUnmixing, U"", nullptr)
+	NUMBER_TWO (CrossCorrelationTableList, Diagonalizer)
+		double result = CrossCorrelationTableList_and_Diagonalizer_getDiagonalityMeasure (me, you, nullptr, fromTable, toTable);
+	NUMBER_TWO_END (U" (= average sum of squared off-diagonal elements)")
+}
+
+DIRECT (NEW1_CrossCorrelationTable_and_Diagonalizer_diagonalize) {
+	CONVERT_TWO (CrossCorrelationTable, Diagonalizer)
+		autoCrossCorrelationTable result = CrossCorrelationTable_and_Diagonalizer_diagonalize (me, you);
+	CONVERT_TWO_END (me -> name, U"_", you -> name)
+}
+
+DIRECT (NEW1_CrossCorrelationTableList_and_Diagonalizer_diagonalize) {
+	CONVERT_TWO (CrossCorrelationTableList, Diagonalizer)
+		autoCrossCorrelationTableList result = CrossCorrelationTableList_and_Diagonalizer_diagonalize (me, you);
+	CONVERT_TWO_END (me -> name, U"_", you -> name);
+}
+
+FORM (MODIFY_CrossCorrelationTableList_and_MixingMatrix_improveUnmixing, U"", nullptr) {
 	LABEL (U"", U"Iteration parameters")
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
-	OPTION (U"qdiag")
-	OPTION (U"ffdiag")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENUVAR (diagonalizationMethod, U"Diagonalization method", 2)
+		OPTION (U"qdiag")
+		OPTION (U"ffdiag")
 	OK
 DO
-	MixingMatrix mm = FIRST (MixingMatrix);
-	CrossCorrelationTableList ccts = FIRST (CrossCorrelationTableList);
-	MixingMatrix_and_CrossCorrelationTableList_improveUnmixing (mm, ccts,
-		GET_INTEGER (U"Maximum number of iterations"), GET_REAL (U"Tolerance"), GET_INTEGER (U"Diagonalization method"));
-END
-
-DIRECT (Diagonalizer_to_MixingMatrix)
-	LOOP {
-		iam (Diagonalizer);
-		autoMixingMatrix thee = Diagonalizer_to_MixingMatrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_MixingMatrix, U"Sound: To MixingMatrix", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	NATURAL (U"Number of cross-correlations", U"40")
-	POSITIVE (U"Lag step (s)", U"0.002")
+	MODIFY_FIRST_OF_TWO (MixingMatrix, CrossCorrelationTableList)
+		MixingMatrix_and_CrossCorrelationTableList_improveUnmixing (me, you, maximumNumberOfIterations, tolerance, diagonalizationMethod);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+DIRECT (NEW_Diagonalizer_to_MixingMatrix) {
+	CONVERT_EACH (Diagonalizer)
+		autoMixingMatrix result = Diagonalizer_to_MixingMatrix (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_MixingMatrix, U"Sound: To MixingMatrix", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	NATURALVAR (numberOfCrossCorrelations, U"Number of cross-correlations", U"40")
+	POSITIVEVAR (lagTime, U"Lag step (s)", U"0.002")
 	LABEL (U"", U"Iteration parameters")
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENUVAR (diagonalizationMethod, U"Diagonalization method", 2)
 		OPTION (U"qdiag")
 		OPTION (U"ffdiag")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoMixingMatrix thee = Sound_to_MixingMatrix (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_INTEGER (U"Number of cross-correlations"), GET_REAL (U"Lag step"), GET_INTEGER (U"Maximum number of iterations"),
-			GET_REAL (U"Tolerance"), GET_INTEGER (U"Diagonalization method"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_CrossCorrelationTableList, U"Sound: To CrossCorrelationTableList", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	NATURAL (U"Number of cross-correlations", U"40")
-	POSITIVE (U"Lag step (s)", U"0.002")
+	CONVERT_EACH (Sound)
+		autoMixingMatrix result = Sound_to_MixingMatrix (me, fromTime, toTime, numberOfCrossCorrelations, lagTime, maximumNumberOfIterations, tolerance, diagonalizationMethod);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_CrossCorrelationTableList, U"Sound: To CrossCorrelationTableList", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	NATURALVAR (numberOfCrossCorrelations, U"Number of cross-correlations", U"40")
+	POSITIVEVAR (lagTime, U"Lag step (s)", U"0.002")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoCrossCorrelationTableList thee = Sound_to_CrossCorrelationTableList (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Lag step"), GET_INTEGER (U"Number of cross-correlations"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (Sound_to_Sound_bss, U"Sound: To Sound (blind source separation)", U"Sound: To Sound (blind source separation)...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	NATURAL (U"Number of cross-correlations", U"40")
-	POSITIVE (U"Lag step (s)", U"0.002")
+	CONVERT_EACH (Sound)
+		autoCrossCorrelationTableList result = Sound_to_CrossCorrelationTableList (me, fromTime, toTime, lagTime, numberOfCrossCorrelations);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Sound_bss, U"Sound: To Sound (blind source separation)", U"Sound: To Sound (blind source separation)...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	NATURALVAR (numberOfCrossCorrelations, U"Number of cross-correlations", U"40")
+	POSITIVEVAR (lagStep, U"Lag step (s)", U"0.002")
 	LABEL (U"", U"Iteration parameters")
-	NATURAL (U"Maximum number of iterations", U"100")
-	POSITIVE (U"Tolerance", U"0.001")
-	OPTIONMENU (U"Diagonalization method", 2)
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
+	POSITIVEVAR (tolerance, U"Tolerance", U"0.001")
+	OPTIONMENUVAR (diagonalizationMethod, U"Diagonalization method", 2)
 		OPTION (U"qdiag")
 		OPTION (U"ffdiag")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_to_Sound_BSS (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"Number of cross-correlations"), GET_REAL (U"Lag step"),
-			GET_INTEGER (U"Maximum number of iterations"), GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Diagonalization method"));
-		praat_new (thee.move(), my name, U"_bss");
-	}
-END
-
-FORM (Sound_to_Sound_whiteChannels, U"Sound: To Sound (white channels)", U"Sound: To Sound (white channels)...")
-    POSITIVE (U"Variance fraction to keep", U"0.99")
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_to_Sound_BSS (me, fromTime, toTime, numberOfCrossCorrelations, lagStep, maximumNumberOfIterations, tolerance, diagonalizationMethod);
+	CONVERT_EACH_END (my name, U"_bss")
+}
+
+FORM (NEW_Sound_to_Sound_whiteChannels, U"Sound: To Sound (white channels)", U"Sound: To Sound (white channels)...") {
+	POSITIVEVAR (varianceFraction, U"Variance fraction to keep", U"0.99")
     OK
 DO
-    double varianceFraction = GET_REAL (U"Variance fraction to keep");
-    if (varianceFraction > 1) varianceFraction = 1;
+    if (varianceFraction > 1.0) varianceFraction = 1.0;
     long permille = (long) floor (varianceFraction * 1000.0);
-    LOOP {
-        iam (Sound);
-		autoSound thee = Sound_whitenChannels (me, varianceFraction);
-        praat_new (thee.move(), my name, U"_", permille);
-    }
-END
-
-DIRECT (Sound_and_MixingMatrix_mix)
-	Sound s = FIRST (Sound);
-	MixingMatrix mm = FIRST (MixingMatrix);
-	autoSound thee = Sound_and_MixingMatrix_mix (s, mm);
-	praat_new (thee.move(), Thing_getName (s), U"_mixed");
-END
-
-DIRECT (Sound_and_MixingMatrix_unmix)
-	Sound s = FIRST (Sound);
-	MixingMatrix mm = FIRST (MixingMatrix);
-	autoSound thee = Sound_and_MixingMatrix_unmix (s, mm);
-	praat_new (thee.move(), Thing_getName (s), U"_unmixed");
-END
-
-DIRECT (TableOfReal_to_MixingMatrix)
-	LOOP {
-		iam (TableOfReal);
-		autoMixingMatrix thee = TableOfReal_to_MixingMatrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (TableOfReal_and_TableOfReal_crossCorrelations, U"TableOfReal & TableOfReal: Cross-correlations", 0)
-	OPTIONMENU (U"Correlations between", 1)
-		OPTION (U"Rows")
-		OPTION (U"Columns")
-	BOOLEAN (U"Center", false)
-	BOOLEAN (U"Normalize", false)
-	OK
-DO
-	TableOfReal t1 = nullptr, t2 = nullptr;
-	LOOP {
-		iam (TableOfReal);
-		(t1 ? t2 : t1) = me;
-	}
-	Melder_assert (t1 && t2);
-	int by_columns = GET_INTEGER (U"Correlations between") - 1;
-	autoTableOfReal thee = TableOfReal_and_TableOfReal_crossCorrelations (t1, t2, by_columns,
-		GET_INTEGER (U"Center"), GET_INTEGER (U"Normalize"));
-	praat_new (thee.move(), ( by_columns ? U"by_columns" : U"by_rows" ));
-END
-
-void praat_TableOfReal_init3 (ClassInfo klas) {
-	praat_TableOfReal_init (klas);
-	praat_addAction1 (klas, 2, U"To TableOfReal (cross-correlations)...", 0, 0, DO_TableOfReal_and_TableOfReal_crossCorrelations);
+    CONVERT_EACH (Sound)
+		autoSound result = Sound_whitenChannels (me, varianceFraction);
+    CONVERT_EACH_END (my name, U"_", permille);
+}
+
+DIRECT (NEW1_Sound_and_MixingMatrix_mix) {
+	CONVERT_TWO (Sound, MixingMatrix)
+		autoSound result = Sound_and_MixingMatrix_mix (me, you);
+	CONVERT_TWO_END (my name, U"_mixed")
+}
+
+DIRECT (NEW1_Sound_and_MixingMatrix_unmix) {
+	CONVERT_TWO (Sound, MixingMatrix)
+		autoSound result = Sound_and_MixingMatrix_unmix (me, you);
+	CONVERT_TWO_END (my name, U"_unmixed");
+}
+
+DIRECT (NEW_TableOfReal_to_MixingMatrix) {
+	CONVERT_EACH (TableOfReal)
+		autoMixingMatrix result = TableOfReal_to_MixingMatrix (me);
+	CONVERT_EACH_END (my name)
 }
 
 void praat_BSS_init ();
@@ -552,65 +417,64 @@ void praat_BSS_init () {
 	Thing_recognizeClassesByName (classDiagonalizer, classMixingMatrix, classCrossCorrelationTable, classCrossCorrelationTableList, nullptr);
 	Thing_recognizeClassByOtherName (classCrossCorrelationTableList, U"CrossCorrelationTables");
 
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple CrossCorrelationTable...", U"Create simple Covariance...", praat_HIDDEN + praat_DEPTH_1, DO_CrossCorrelationTable_createSimple);
-	praat_addMenuCommand (U"Objects", U"New", U"Create test CrossCorrelationTableList...", U"Create simple CrossCorrelationTable...", praat_HIDDEN + praat_DEPTH_1, DO_CrossCorrelationTableList_createTestSet);
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple MixingMatrix...", U"Create test CrossCorrelationTableList...", praat_HIDDEN + praat_DEPTH_1, DO_MixingMatrix_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple CrossCorrelationTable...", U"Create simple Covariance...", praat_HIDDEN + praat_DEPTH_1, NEW1_CrossCorrelationTable_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create test CrossCorrelationTableList...", U"Create simple CrossCorrelationTable...", praat_HIDDEN + praat_DEPTH_1, NEW1_CrossCorrelationTableList_createTestSet);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple MixingMatrix...", U"Create test CrossCorrelationTableList...", praat_HIDDEN + praat_DEPTH_1, NEW1_MixingMatrix_createSimple);
 
-	praat_addAction1 (classCrossCorrelationTable, 0, U"CrossCorrelationTable help", 0, 0, DO_CrossCorrelationTable_help);
+	praat_addAction1 (classCrossCorrelationTable, 0, U"CrossCorrelationTable help", 0, 0, HELP_CrossCorrelationTable_help);
 	praat_SSCP_as_TableOfReal_init (classCrossCorrelationTable);
 
-	praat_addAction1 (classCrossCorrelationTable, 0, U"To CrossCorrelationTableList", nullptr, 0, DO_CrossCorrelationTable_to_CrossCorrelationTableList);
-	praat_addAction1 (classCrossCorrelationTable, 0, U"To CrossCorrelationTables", nullptr, praat_HIDDEN, DO_CrossCorrelationTable_to_CrossCorrelationTableList);
+	praat_addAction1 (classCrossCorrelationTable, 0, U"To CrossCorrelationTableList", nullptr, 0, NEW1_CrossCorrelationTables_to_CrossCorrelationTableList);
+	praat_addAction1 (classCrossCorrelationTable, 0, U"To CrossCorrelationTables", U"*To CrossCorrelationTableList", praat_DEPRECATED_2015, NEW1_CrossCorrelationTables_to_CrossCorrelationTableList);
 
-	praat_addAction1 (classCrossCorrelationTableList, 0, U"CrossCorrelationTableList help", 0, 0, DO_CrossCorrelationTableList_help);
-	praat_addAction1 (classCrossCorrelationTableList, 1, U"Extract CrossCorrelationTable...", 0, 0, DO_CrossCorrelationTableList_extractCrossCorrelationTable);
-	praat_addAction1 (classCrossCorrelationTableList, 1, U"Get diagonality measure...", 0, 0, DO_CrossCorrelationTableList_getDiagonalityMeasure);
-	praat_addAction1 (classCrossCorrelationTableList, 0, U"To Diagonalizer...", 0, 0, DO_CrossCorrelationTableList_to_Diagonalizer);
+	praat_addAction1 (classCrossCorrelationTableList, 0, U"CrossCorrelationTableList help", 0, 0, HELP_CrossCorrelationTableList_help);
+	praat_addAction1 (classCrossCorrelationTableList, 1, U"Extract CrossCorrelationTable...", 0, 0, NEW_CrossCorrelationTableList_extractCrossCorrelationTable);
+	praat_addAction1 (classCrossCorrelationTableList, 1, U"Get diagonality measure...", 0, 0, REAL_CrossCorrelationTableList_getDiagonalityMeasure);
+	praat_addAction1 (classCrossCorrelationTableList, 0, U"To Diagonalizer...", 0, 0, NEW_CrossCorrelationTableList_to_Diagonalizer);
 
 	praat_TableOfReal_init3 (classDiagonalizer);
-	praat_addAction1 (classDiagonalizer, 0, U"To MixingMatrix", 0, 0, DO_Diagonalizer_to_MixingMatrix);
-
-	praat_addAction1 (classEEG, 0, U"To Sound (mc modulated)...", U"To ERPTier...", praat_HIDDEN, DO_EEG_to_Sound_modulated);
-	praat_addAction1 (classEEG, 0, U"To Sound (frequency shifted)...", U"To ERPTier...", 0, DO_EEG_to_Sound_frequencyShifted);
-	praat_addAction1 (classEEG, 0, U"To PCA...", U"To ERPTier...", 0, DO_EEG_to_PCA);
-	praat_addAction1 (classEEG, 0, U"To CrossCorrelationTable...", U"To PCA...", praat_HIDDEN, DO_EEG_to_CrossCorrelationTable);
-	praat_addAction1 (classEEG, 0, U"To CrossCorrelationTables...", U"To PCA...", praat_HIDDEN, DO_EEG_to_CrossCorrelationTableList);
-	praat_addAction1 (classEEG, 0, U"To CrossCorrelationTableList...", U"To PCA...", praat_HIDDEN, DO_EEG_to_CrossCorrelationTableList);
+	praat_addAction1 (classDiagonalizer, 0, U"To MixingMatrix", 0, 0,NEW_Diagonalizer_to_MixingMatrix);
 
-	praat_addAction1 (classEEG, 0, U"To Covariance...", U"To CrossCorrelationTable...", praat_HIDDEN, DO_EEG_to_Covariance);
-	praat_addAction1 (classEEG, 0, U"To EEG (bss)...", U"To CrossCorrelationTable...", praat_HIDDEN, DO_EEG_to_EEG_bss);
+	praat_addAction1 (classEEG, 0, U"To Sound (mc modulated)...", U"To ERPTier...", praat_HIDDEN, NEW_EEG_to_Sound_modulated);
+	praat_addAction1 (classEEG, 0, U"To Sound (frequency shifted)...", U"To ERPTier...", 0, NEW_EEG_to_Sound_frequencyShifted);
+	praat_addAction1 (classEEG, 0, U"To PCA...", U"To ERPTier...", 0, NEW_EEG_to_PCA);
+	praat_addAction1 (classEEG, 0, U"To CrossCorrelationTable...", U"To PCA...", praat_HIDDEN, NEW_EEG_to_CrossCorrelationTable);
+	praat_addAction1 (classEEG, 0, U"To CrossCorrelationTables...", U"To PCA...", praat_HIDDEN, NEW_EEG_to_CrossCorrelationTableList);
+	praat_addAction1 (classEEG, 0, U"To CrossCorrelationTableList...", U"To PCA...", praat_HIDDEN, NEW_EEG_to_CrossCorrelationTableList);
 
-	praat_addAction2 (classEEG, 1, classPCA, 1, U"To EEG (principal components)...", 0, 0, DO_EEG_and_PCA_to_EEG_principalComponents);
-	praat_addAction2 (classEEG, 1, classPCA, 1, U"To EEG (whiten)...", 0, 0, DO_EEG_and_PCA_to_EEG_whiten);
+	praat_addAction1 (classEEG, 0, U"To Covariance...", U"To CrossCorrelationTable...", praat_HIDDEN, NEW_EEG_to_Covariance);
+	praat_addAction1 (classEEG, 0, U"To EEG (bss)...", U"To CrossCorrelationTable...", praat_HIDDEN, NEW_EEG_to_EEG_bss);
 
+	praat_addAction2 (classEEG, 1, classPCA, 1, U"To EEG (principal components)...", 0, 0, NEW1_EEG_and_PCA_to_EEG_principalComponents);
+	praat_addAction2 (classEEG, 1, classPCA, 1, U"To EEG (whiten)...", 0, 0, NEW1_EEG_and_PCA_to_EEG_whiten);
 
 	praat_TableOfReal_init3 (classMixingMatrix);
 
-	praat_addAction1 (classSound, 0, U"To MixingMatrix...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_MixingMatrix);
-    praat_addAction1 (classSound, 0, U"To CrossCorrelationTable...",  U"Resample...", 1, DO_Sound_to_CrossCorrelationTable);
-    praat_addAction1 (classSound, 0, U"To Covariance (channels)...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_Covariance_channels);
-	praat_addAction1 (classSound, 0, U"To CrossCorrelationTables...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_CrossCorrelationTableList);
-	praat_addAction1 (classSound, 0, U"To CrossCorrelationTableList...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_CrossCorrelationTableList);
+	praat_addAction1 (classSound, 0, U"To MixingMatrix...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, NEW_Sound_to_MixingMatrix);
+    praat_addAction1 (classSound, 0, U"To CrossCorrelationTable...",  U"Resample...", 1, NEW_Sound_to_CrossCorrelationTable);
+    praat_addAction1 (classSound, 0, U"To Covariance (channels)...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, NEW_Sound_to_Covariance_channels);
+	praat_addAction1 (classSound, 0, U"To CrossCorrelationTables...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, NEW_Sound_to_CrossCorrelationTableList);
+	praat_addAction1 (classSound, 0, U"To CrossCorrelationTableList...",  U"Resample...", praat_HIDDEN + praat_DEPTH_1, NEW_Sound_to_CrossCorrelationTableList);
 
-	praat_addAction1 (classSound, 0, U"To Sound (bss)...", U"Resample...", 1, DO_Sound_to_Sound_bss);
-    praat_addAction1 (classSound, 0, U"To Sound (white channels)...", U"Resample...", 1, DO_Sound_to_Sound_whiteChannels);
-    praat_addAction1 (classSound, 2, U"To CrossCorrelationTable (combined)...",  U"Cross-correlate...", 1, DO_Sounds_to_CrossCorrelationTable_combined);
+	praat_addAction1 (classSound, 0, U"To Sound (bss)...", U"Resample...", 1, NEW_Sound_to_Sound_bss);
+    praat_addAction1 (classSound, 0, U"To Sound (white channels)...", U"Resample...", 1, NEW_Sound_to_Sound_whiteChannels);
+    praat_addAction1 (classSound, 2, U"To CrossCorrelationTable (combined)...",  U"Cross-correlate...", 1, NEW1_Sounds_to_CrossCorrelationTable_combined);
 
-	praat_addAction1 (classTableOfReal, 0, U"To MixingMatrix", U"To Configuration", praat_HIDDEN, DO_TableOfReal_to_MixingMatrix);
+	praat_addAction1 (classTableOfReal, 0, U"To MixingMatrix", U"To Configuration", praat_HIDDEN, NEW_TableOfReal_to_MixingMatrix);
 
-	praat_addAction2 (classSound, 1, classMixingMatrix, 1, U"Mix", 0, 0, DO_Sound_and_MixingMatrix_mix);
-	praat_addAction2 (classSound, 1, classMixingMatrix, 1, U"Unmix", 0, 0, DO_Sound_and_MixingMatrix_unmix);
+	praat_addAction2 (classSound, 1, classMixingMatrix, 1, U"Mix", 0, 0, NEW1_Sound_and_MixingMatrix_mix);
+	praat_addAction2 (classSound, 1, classMixingMatrix, 1, U"Unmix", 0, 0, NEW1_Sound_and_MixingMatrix_unmix);
 
-	praat_addAction2 (classSound, 1, classPCA, 1, U"To Sound (white channels)...", 0 , 0, DO_Sound_and_PCA_whitenChannels);
-	praat_addAction2 (classSound, 1, classPCA, 1, U"To Sound (principal components)...", 0 , 0, DO_Sound_and_PCA_principalComponents);
+	praat_addAction2 (classSound, 1, classPCA, 1, U"To Sound (white channels)...", 0 , 0, NEW1_Sound_and_PCA_whitenChannels);
+	praat_addAction2 (classSound, 1, classPCA, 1, U"To Sound (principal components)...", 0 , 0, NEW1_Sound_and_PCA_principalComponents);
 
-	praat_addAction2 (classCrossCorrelationTable, 1, classDiagonalizer, 1, U"Diagonalize", 0 , 0, DO_CrossCorrelationTable_and_Diagonalizer_diagonalize);
+	praat_addAction2 (classCrossCorrelationTable, 1, classDiagonalizer, 1, U"Diagonalize", 0 , 0, NEW1_CrossCorrelationTable_and_Diagonalizer_diagonalize);
 
-	praat_addAction2 (classCrossCorrelationTableList, 1, classDiagonalizer, 1, U"Get diagonality measure...", 0 , 0, DO_CrossCorrelationTableList_and_Diagonalizer_getDiagonalityMeasure);
-	praat_addAction2 (classCrossCorrelationTableList, 1, classDiagonalizer, 1, U"Diagonalize", 0 , 0, DO_CrossCorrelationTableList_and_Diagonalizer_diagonalize);
-	praat_addAction2 (classCrossCorrelationTableList, 1, classDiagonalizer, 1, U"Improve diagonality...", 0 , 0, DO_Diagonalizer_and_CrossCorrelationTableList_improveDiagonality);
+	praat_addAction2 (classCrossCorrelationTableList, 1, classDiagonalizer, 1, U"Get diagonality measure...", 0 , 0, REAL_CrossCorrelationTableList_and_Diagonalizer_getDiagonalityMeasure);
+	praat_addAction2 (classCrossCorrelationTableList, 1, classDiagonalizer, 1, U"Diagonalize", 0 , 0, NEW1_CrossCorrelationTableList_and_Diagonalizer_diagonalize);
+	praat_addAction2 (classCrossCorrelationTableList, 1, classDiagonalizer, 1, U"Improve diagonality...", 0 , 0, MODIFY_Diagonalizer_and_CrossCorrelationTableList_improveDiagonality);
 
-	praat_addAction2 (classCrossCorrelationTableList, 1, classMixingMatrix, 1, U"Improve unmixing...", 0 , 0, DO_CrossCorrelationTableList_and_MixingMatrix_improveUnmixing);
+	praat_addAction2 (classCrossCorrelationTableList, 1, classMixingMatrix, 1, U"Improve unmixing...", 0 , 0, MODIFY_CrossCorrelationTableList_and_MixingMatrix_improveUnmixing);
 
 	INCLUDE_MANPAGES (manual_BSS)
 }
diff --git a/dwtools/praat_DataModeler_init.cpp b/dwtools/praat_DataModeler_init.cpp
index df490d5..1cc801a 100644
--- a/dwtools/praat_DataModeler_init.cpp
+++ b/dwtools/praat_DataModeler_init.cpp
@@ -1,6 +1,6 @@
 /* praat_DataModeler_init.cpp
  *
- * Copyright (C) 2014 David Weenink
+ * Copyright (C) 2014,2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,410 +29,374 @@
 
 /* DataModeler */
 
-FORM (DataModeler_createSimple, U"Create simple DataModeler", 0)
-	WORD (U"Name", U"dm")
-	REAL (U"left X range", U"0.0")
-	REAL (U"right X range", U"1.0")
-	NATURAL (U"Number of data points", U"20")
-	SENTENCE (U"Parameters", U"0.0 1.0 1.0")
-	POSITIVE (U"Gaussian noise stdev", U"0.2")
-	OPTIONMENU (U"Basis functions", 2)
+FORM (NEW1_DataModeler_createSimple, U"Create simple DataModeler", nullptr) {
+	WORDVAR (name, U"Name", U"dm")
+	REALVAR (xmin, U"left X range", U"0.0")
+	REALVAR (xmax, U"right X range", U"1.0")
+	NATURALVAR (numberOfDataPoints, U"Number of data points", U"20")
+	SENTENCEVAR (parameter_string, U"Parameters", U"0.0 1.0 1.0")
+	POSITIVEVAR (standardDeviation, U"Gaussian noise stdev", U"0.2")
+	OPTIONMENUVAR (functionType, U"Basis functions", 2)
 		OPTION (U"Polynomial")
 		OPTION (U"Legendre")
 		
 	OK
 DO
-	autoDataModeler thee = DataModeler_createSimple (GET_REAL (U"left X range"), GET_REAL (U"right X range"),
-		GET_INTEGER (U"Number of data points"), GET_STRING (U"Parameters"), GET_REAL (U"Gaussian noise stdev"),
-		GET_INTEGER (U"Basis functions") - 1);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoDataModeler result = DataModeler_createSimple (xmin, xmax, numberOfDataPoints, parameter_string, standardDeviation, functionType - 1);
+	CREATE_ONE_END (name)
+}
 
-FORM (DataModeler_speckle, U"DataModeler: Speckle", 0)
-	REAL (U"left X range", U"0.0")
-	REAL (U"right X range", U"0.0")
-	REAL (U"left Y range", U"0.0")
-	REAL (U"right Y range", U"0.0")
-	BOOLEAN (U"Draw error bars", 1)
-	REAL (U"Bar width (mm)", U"1.0")
-	REAL (U"Horizontal offset (mm)", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_DataModeler_speckle, U"DataModeler: Speckle", nullptr) {
+	REALVAR (xmin, U"left X range", U"0.0")
+	REALVAR (xmax, U"right X range", U"0.0")
+	REALVAR (ymin, U"left Y range", U"0.0")
+	REALVAR (ymax, U"right Y range", U"0.0")
+	BOOLEANVAR (errorBars, U"Draw error bars", 1)
+	REALVAR (barWidth_mm, U"Bar width (mm)", U"1.0")
+	REALVAR (xOffset_mm, U"Horizontal offset (mm)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
 	long order = 6;
-	LOOP {
-		iam (DataModeler);
-		DataModeler_speckle (me, GRAPHICS, GET_REAL (U"left X range"), GET_REAL (U"right X range"),
-			GET_REAL (U"left Y range"), GET_REAL (U"right Y range"),
-			0, order + 1, GET_INTEGER (U"Draw error bars"), GET_REAL (U"Bar width"), GET_REAL (U"Horizontal offset"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DataModeler)
+		DataModeler_speckle (me, GRAPHICS, xmin, xmax,ymin, ymax, 0, order + 1, errorBars, barWidth_mm, xOffset_mm, garnish);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (DataModeler_drawEstimatedTrack, U"DataModeler: Draw estimated track", 0)
-	REAL (U"left X range", U"0.0")
-	REAL (U"right X range", U"0.0")
-	REAL (U"left Y range", U"0.0")
-	REAL (U"right Y range", U"0.0")
-	INTEGER (U"Order of polynomials for estimation", U"3")
-	REAL (U"Horizontal offset (mm)", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_DataModeler_drawEstimatedTrack, U"DataModeler: Draw estimated track", nullptr) {
+	REALVAR (xmin, U"left X range", U"0.0")
+	REALVAR (xmax, U"right X range", U"0.0")
+	REALVAR (ymin, U"left Y range", U"0.0")
+	REALVAR (ymax, U"right Y range", U"0.0")
+	INTEGERVAR (order, U"Order of polynomials for estimation", U"3")
+	REALVAR (xOffset, U"Horizontal offset (mm)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	long order = GET_INTEGER (U"Order of polynomials for estimation");
 	REQUIRE (order >= 0, U"The order must be greater than or equal to zero.")
-	LOOP {
-		iam (DataModeler);
-		DataModeler_drawTrack (me, GRAPHICS, GET_REAL (U"left X range"), GET_REAL (U"right X range"),
-			GET_REAL (U"left Y range"), GET_REAL (U"right Y range"), 1, order + 1, GET_REAL (U"Horizontal offset"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DataModeler)
+		DataModeler_drawTrack (me, GRAPHICS, xmin, xmax, ymin, ymax, 1, order + 1, xOffset, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (DataModeler_getNumberOfParameters)
-	LOOP {
-		iam (DataModeler);
-		Melder_information (my numberOfParameters, U" (= number of parameters)");
-	}
-END
+DIRECT (INTEGER_DataModeler_getNumberOfParameters) {
+	INTEGER_ONE (DataModeler)
+		long result = my numberOfParameters;
+	INTEGER_ONE_END (U" (= number of parameters)")
+}
 
-DIRECT (DataModeler_getNumberOfFixedParameters)
-	LOOP {
-		iam (DataModeler);
-		Melder_information (DataModeler_getNumberOfFixedParameters (me), U" (= number of parameters)");
-	}
-END
+DIRECT (INTEGER_DataModeler_getNumberOfFixedParameters) {
+	INTEGER_ONE (DataModeler)
+		long result = DataModeler_getNumberOfFixedParameters (me);
+	INTEGER_ONE_END (U"(= number of parameters)")
+}
 
-FORM (DataModeler_getParameterValue, U"DataModeler: Get parameter value", 0)
-	NATURAL (U"Parameter number", U"1")
+FORM (REAL_DataModeler_getParameterValue, U"DataModeler: Get parameter value", nullptr) {
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
 	OK
 DO
-	long iparameter = GET_INTEGER (U"Parameter number");
-	LOOP {
-		iam (DataModeler);
-		double parameter = DataModeler_getParameterValue (me, iparameter);
-		Melder_information (parameter, U" (= parameter[", iparameter, U"])");
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getParameterValue (me, parameterNumber);
+	NUMBER_ONE_END (U" (= parameter[", parameterNumber, U"])")
+}
 
-FORM (DataModeler_getParameterStatus, U"DataModeler: Get parameter status", 0)
-	NATURAL (U"Parameter number", U"1")
+FORM (INFO_DataModeler_getParameterStatus, U"DataModeler: Get parameter status", nullptr) {
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
 	OK
 DO
-	long iparameter = GET_INTEGER (U"Parameter number");
-	LOOP {
-		iam (DataModeler);
-		int status = DataModeler_getParameterStatus (me, iparameter);
-		Melder_information (status == DataModeler_PARAMETER_FREE ? U"Free" : (status == DataModeler_PARAMETER_FIXED ? U"Fixed" :
-			U"Undefined"), U" (= parameter[", iparameter, U"])");
-	}
-END
+	STRING_ONE (DataModeler)
+		int status = DataModeler_getParameterStatus (me, parameterNumber);
+		const char32 *result = status == DataModeler_PARAMETER_FREE ? U"Free" : (status == DataModeler_PARAMETER_FIXED ? U"Fixed" :
+		U"Undefined");
+	STRING_ONE_END
+}
 
-FORM (DataModeler_getParameterStandardDeviation, U"DataModeler: Get parameter standard deviation", 0)
-	NATURAL (U"Parameter number", U"1")
+FORM (REAL_DataModeler_getParameterStandardDeviation, U"DataModeler: Get parameter standard deviation", nullptr) {
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
 	OK
 DO
-	long iparameter = GET_INTEGER (U"Parameter number");
-	LOOP {
-		iam (DataModeler);
-		double sigma = DataModeler_getParameterStandardDeviation (me, iparameter);
-		Melder_information (sigma, U" (= parameter[", iparameter, U"])");
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getParameterStandardDeviation (me, parameterNumber);
+	NUMBER_ONE_END (U" (= parameter[", parameterNumber, U"])")
+}
 
-FORM (DataModeler_getVarianceOfParameters, U"DataModeler: Get variance of parameters", 0)
-	INTEGER (U"left Parameter range", U"0")
-	INTEGER (U"right Parameter range", U"0")
+FORM (REAL_DataModeler_getVarianceOfParameters, U"DataModeler: Get variance of parameters", nullptr) {
+	INTEGERVAR (fromParameter, U"left Parameter range", U"0")
+	INTEGERVAR (toParameter, U"right Parameter range", U"0")
 	OK
 DO
 	long nofp;
-	LOOP {
-		iam (DataModeler);
-		double var = DataModeler_getVarianceOfParameters (me, GET_INTEGER (U"left Parameter range"), GET_INTEGER (U"right Parameter range"), &nofp);
-		Melder_information (var, U" (for ", nofp, U" free parameters)");
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getVarianceOfParameters (me, fromParameter, toParameter, &nofp);
+	NUMBER_ONE_END (U" (for ", nofp, U" free parameters)")
+}
 
-DIRECT (DataModeler_getNumberOfDataPoints)
-	LOOP {
-		iam (DataModeler);
-		Melder_information (my numberOfDataPoints, U" (= number of data points)");
-	}
-END
+DIRECT (INTEGER_DataModeler_getNumberOfDataPoints) {
+	INTEGER_ONE (DataModeler)
+		long result = my numberOfDataPoints;
+	INTEGER_ONE_END (U" (= number of data points)")
+}
 
-DIRECT (DataModeler_getNumberOfInvalidDataPoints)
-	LOOP {
-		iam (DataModeler);
-		Melder_information (DataModeler_getNumberOfInvalidDataPoints (me), U" (= number of invalid data points)");
-	}
-END
+DIRECT (INTEGER_DataModeler_getNumberOfInvalidDataPoints) {
+	INTEGER_ONE (DataModeler)
+		long result = DataModeler_getNumberOfInvalidDataPoints (me);
+	INTEGER_ONE_END (U" (= number of invalid data points)")
+}
 
-FORM (DataModeler_getModelValueAtX, U"DataModeler: Get model value at x", 0)
-	REAL (U"X", U"0.1")
+FORM (REAL_DataModeler_getModelValueAtX, U"DataModeler: Get model value at x", nullptr) {
+	REALVAR (x, U"X", U"0.1")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		double y = DataModeler_getModelValueAtX (me, GET_REAL (U"X"));
-		Melder_informationReal (y, nullptr);
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getModelValueAtX (me, x);
+	NUMBER_ONE_END (U"")
+}
 
 
-DIRECT (DataModeler_getResidualSumOfSquares)
-	LOOP {
+
+DIRECT (REAL_DataModeler_getResidualSumOfSquares) {
+	NUMBER_ONE (DataModeler)
 		long n;
-		iam (DataModeler);
-		double rss = DataModeler_getResidualSumOfSquares (me, &n);
-		Melder_information (rss, U"  (for ", n, U" datapoints)");
-	}
-END
+		double result = DataModeler_getResidualSumOfSquares (me, &n);
+	NUMBER_ONE_END (U"  (for ", n, U" datapoints)")
+}
 
-DIRECT (DataModeler_getStandardDeviation)
-	LOOP {
-		iam (DataModeler);
-		double sigma = DataModeler_estimateSigmaY (me);
-		Melder_information (sigma);
-	}
-END
+DIRECT (REAL_DataModeler_getStandardDeviation) {
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_estimateSigmaY (me);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (DataModeler_getDataPointValue, U"DataModeler: Get data point value", 0)
-	NATURAL (U"Index", U"1")
+FORM (REAL_DataModeler_getDataPointXValue, U"DataModeler: Get data point x value", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (DataModeler);
-		double value = DataModeler_getDataPointValue (me, index);
-		Melder_information (value, U" (= value at point ", index, U")");
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getDataPointXValue (me, index);
+	NUMBER_ONE_END (U" (= value at point ", index, U")")
+}
 
-FORM (DataModeler_getDataPointSigma, U"DataModeler: Get data point sigma", 0)
-	NATURAL (U"Index", U"1")
+FORM (REAL_DataModeler_getDataPointYValue, U"DataModeler: Get data point y value", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (DataModeler);
-		double sigma = DataModeler_getDataPointSigma (me, index);
-		Melder_information (sigma, U" (= sigma at point ", index, U")");
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getDataPointYValue (me, index);
+	NUMBER_ONE_END (U" (= value at point ", index, U")")
+}
 
-FORM (DataModeler_getDataPointStatus, U"DataModeler: Get data point status", 0)
-	NATURAL (U"Index", U"1")
+FORM (REAL_DataModeler_getDataPointYSigma, U"DataModeler: Get data point y sigma", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		int status = DataModeler_getDataPointStatus (me, GET_INTEGER (U"Index"));
-		Melder_information (status == DataModeler_DATA_INVALID ? U"Invalid" : U"Valid");
-	}
-END
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getDataPointYSigma (me, index);
+	NUMBER_ONE_END (U" (= sigma at point ", index, U")")
+}
+
+FORM (INFO_DataModeler_getDataPointStatus, U"DataModeler: Get data point status", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	OK
+DO
+	STRING_ONE (DataModeler)
+		int status = DataModeler_getDataPointStatus (me, index);
+		const char32 *result = status == DataModeler_DATA_INVALID ? U"Invalid" : U"Valid";
+	STRING_ONE_END
+}
+
+DIRECT (REAL_DataModeler_getCoefficientOfDetermination) {
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getCoefficientOfDetermination (me, nullptr, nullptr);
+	NUMBER_ONE_END (U" (= R^2)");
+}
 
-DIRECT (DataModeler_getCoefficientOfDetermination)
-	LOOP {
-		iam (DataModeler);
-		double rSquared = DataModeler_getCoefficientOfDetermination (me, nullptr, nullptr);
-		Melder_informationReal (rSquared, U" (= R^2)");
-	}
-END
 
-FORM (DataModeler_reportChiSquared, U"DataModeler: Report chi squared", 0)
-	OPTIONMENU (U"Weigh data", 2)
+FORM (INFO_DataModeler_reportChiSquared, U"DataModeler: Report chi squared", nullptr) {
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Sigma")
 		OPTION (U"Relative")
 		OPTION (U"Sqrt sigma")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		int useSigmaY = GET_INTEGER (U"Weigh data") - 1;
-		MelderInfo_open ();
-		MelderInfo_writeLine (U"Chi squared test:");
-		MelderInfo_writeLine (useSigmaY == DataModeler_DATA_WEIGH_EQUAL ? U"Standard deviation is estimated from the data." :
-			useSigmaY == DataModeler_DATA_WEIGH_SIGMA ? U"Sigmas are used as estimate for local standard deviations." : 
-			useSigmaY == DataModeler_DATA_WEIGH_RELATIVE ? U"1/Q's are used as estimate for local standard deviations." :
-			U"Sqrt sigmas are used as estimate for local standard deviations.");
-		double ndf, probability, chisq = DataModeler_getChiSquaredQ (me, useSigmaY, &probability, &ndf);
-		MelderInfo_writeLine (U"Chi squared = ", chisq);
-		MelderInfo_writeLine (U"Probability = ", probability);
-		MelderInfo_writeLine (U"Number of degrees of freedom = ", ndf);
-		MelderInfo_close ();
-	}
-END
+	INFO_ONE (DataModeler)
+		MelderInfo_open();
+		DataModeler_reportChiSquared (me, weighDataType);
+		MelderInfo_close();
+	INFO_ONE_END
+}
 
-DIRECT (DataModeler_getDegreesOfFreedom)
-	LOOP {
-		iam (DataModeler);
-		double dof = DataModeler_getDegreesOfFreedom (me);
-		Melder_informationReal (dof, U" (= degrees of freedom)");
-	}
-END
+DIRECT (REAL_DataModeler_getDegreesOfFreedom) {
+	NUMBER_ONE (DataModeler)
+		double result = DataModeler_getDegreesOfFreedom (me);
+	NUMBER_ONE_END (U" (= degrees of freedom)")
+}
 
-FORM (DataModeler_setDataWeighing, U"DataModeler: Set data weighing", 0)
-	OPTIONMENU (U"Weigh data", 1)
+
+FORM (MODIFY_DataModeler_setDataWeighing, U"DataModeler: Set data weighing", nullptr) {
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 1)
 		OPTION (U"Equally")
 		OPTION (U"Sigma")
 		OPTION (U"Relative")
 		OPTION (U"Sqrt sigma")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setDataWeighing (me, GET_INTEGER (U"Weigh data") - 1);
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setDataWeighing (me, weighDataType - 1);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setTolerance, U"DataModeler: Set tolerance", 0)
-	REAL (U"Tolerance", U"1e-5")
+FORM (MODIFY_DataModeler_setTolerance, U"DataModeler: Set tolerance", nullptr) {
+	REALVAR (tolerance, U"Tolerance", U"1e-5")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setTolerance (me, GET_REAL (U"Tolerance"));
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setTolerance (me, tolerance);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setParameterValue, U"DataModeler: Set parameter value", 0)
-	NATURAL (U"Parameter number", U"1")
-	REAL (U"Value", U"0.0")
-	OPTIONMENU (U"Status", 1)
+FORM (MODIFY_DataModeler_setParameterValue, U"DataModeler: Set parameter value", nullptr) {
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
+	REALVAR (value, U"Value", U"0.0")
+	OPTIONMENUVAR (parameterStatus, U"Status", 1)
 		OPTION (U"Free")
 		OPTION (U"Fixed")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setParameterValue (me, GET_INTEGER (U"Parameter number"), GET_REAL (U"Value"), GET_INTEGER (U"Status") - 1);
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setParameterValue (me, parameterNumber, value, parameterStatus - 1);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setParameterFree, U"DataModeler: Set parameter free", 0)
-	INTEGER (U"left Parameter range", U"0")
-	INTEGER (U"right Parameter range", U"0")
+FORM (MODIFY_DataModeler_setParameterFree, U"DataModeler: Set parameter free", nullptr) {
+	INTEGERVAR (fromParameter, U"left Parameter range", U"0")
+	INTEGERVAR (toParameter, U"right Parameter range", U"0")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setParametersFree (me, GET_INTEGER (U"left Parameter range"), GET_INTEGER (U"right Parameter range"));
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setParametersFree (me, fromParameter, toParameter);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setParameterValuesToZero, U"DataModeler: Set parameter values to zero", 0)
-	REAL (U"Number of sigmas", U"1.0")
+FORM (MODIFY_DataModeler_setParameterValuesToZero, U"DataModeler: Set parameter values to zero", nullptr) {
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setParameterValuesToZero (me, GET_REAL (U"Number of sigmas"));
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setParameterValuesToZero (me, numberOfSigmas);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setDataPointStatus, U"DataModeler: Set data point status", 0)
-	NATURAL (U"Index", U"1")
-	OPTIONMENU (U"Status", 1)
+FORM (MODIFY_DataModeler_setDataPointStatus, U"DataModeler: Set data point status", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	OPTIONMENUVAR (dataStatus, U"Status", 1)
 		OPTION (U"Valid")
 		OPTION (U"Invalid")
 	OK
 DO
-	int menustatus = GET_INTEGER (U"Status");
-	int status = menustatus == 2 ? DataModeler_DATA_INVALID : DataModeler_DATA_VALID;
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setDataPointStatus (me, GET_INTEGER (U"Index"), status);
-	}
-END
+	int status = dataStatus == 2 ? DataModeler_DATA_INVALID : DataModeler_DATA_VALID;
+	MODIFY_EACH (DataModeler)
+		DataModeler_setDataPointStatus (me, index, status);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setDataPointValue, U"DataModeler: Set data point value", 0)
-	NATURAL (U"Index", U"1")
-	REAL (U"Value", U"0.0")
+FORM (MODIFY_DataModeler_setDataPointXValue, U"DataModeler: Set data point x value", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	REALVAR (x, U"X", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setDataPointValue (me, GET_INTEGER (U"Index"), GET_REAL (U"Value"));
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setDataPointXValue (me, index, x);
+	MODIFY_EACH_END
+}
 
-FORM (DataModeler_setDataPointSigma, U"DataModeler: Set data point sigma", 0)
-	NATURAL (U"Index", U"1")
-	REAL (U"Sigma", U"10.0")
+FORM (MODIFY_DataModeler_setDataPointYValue, U"DataModeler: Set data point y value", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	REALVAR (y, U"Y", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		DataModeler_setDataPointSigma (me, GET_INTEGER (U"Index"), GET_REAL (U"Sigma"));
-	}
-END
+	MODIFY_EACH (DataModeler)
+		DataModeler_setDataPointYValue (me, index, y);
+	MODIFY_EACH_END
+}
 
-DIRECT (DataModeler_fitModel)
-	LOOP {
-		iam (DataModeler);
+FORM (MODIFY_DataModeler_setDataPointValues, U"DataModeler: Set data point values", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	REALVAR (x, U"X", U"0.0")
+	REALVAR (y, U"Y", U"0.0")
+	OK
+DO
+	MODIFY_EACH (DataModeler)
+		DataModeler_setDataPointValues (me, index, x, y);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_DataModeler_setDataPointYSigma, U"DataModeler: Set data point y sigma", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	REALVAR (sigma, U"Sigma", U"10.0")
+	OK
+DO
+	MODIFY_EACH (DataModeler)
+		DataModeler_setDataPointYSigma (me, index, sigma);
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_DataModeler_fitModel) {
+	MODIFY_EACH (DataModeler)
 		DataModeler_fit (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (DataModeler_to_Covariance_parameters)
-	LOOP {
-		iam (DataModeler);
-		autoCovariance thee = DataModeler_to_Covariance_parameters (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_DataModeler_to_Covariance_parameters) {
+	CONVERT_EACH (DataModeler)
+		autoCovariance result = DataModeler_to_Covariance_parameters (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (DataModeler_to_Table_zscores, U"DataModeler: To Table (z-scores)", 0)
-	BOOLEAN (U"Use sigmas on y-values", 1)
+FORM (NEW_DataModeler_to_Table_zscores, U"DataModeler: To Table (z-scores)", nullptr) {
+	BOOLEANVAR (useSigmaY, U"Use sigmas on y-values", 1)
 	OK
 DO
-	LOOP {
-		iam (DataModeler);
-		autoTable thee = DataModeler_to_Table_zscores (me, GET_INTEGER (U"Use sigmas on y-values"));
-		praat_new (thee.move(), my name, U"_z");
-	}
-END
+	CONVERT_EACH (DataModeler)
+		autoTable result = DataModeler_to_Table_zscores (me, useSigmaY);
+	CONVERT_EACH_END (my name, U"_z");
+}
 
-FORM (Formant_to_FormantModeler, U"Formant: To FormantModeler", 0)
+FORM (NEW_Formant_to_FormantModeler, U"Formant: To FormantModeler", nullptr) {
 //double tmin, double tmax, long numberOfFormants, long numberOfParametersPerTrack
-	REAL (U"left Start time", U"0.0")
-	REAL (U"right End time", U"0.1")
-	NATURAL (U"Number of formants", U"3")
-	INTEGER (U"Order of polynomials", U"3")
-	OPTIONMENU (U"Weigh data", 2)
+	REALVAR (fromTime, U"left Start time", U"0.0")
+	REALVAR (toTime, U"right End time", U"0.1")
+	NATURALVAR (numberOfFormants, U"Number of formants", U"3")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	OK
 DO
-	long order = GET_INTEGER (U"Order of polynomials");
 	REQUIRE (order >= 0, U"The order must be greater than or equal to zero.")
-	LOOP {
-		iam (Formant);
-		autoFormantModeler thee = Formant_to_FormantModeler (me, GET_REAL (U"left Start time"), 
-			GET_REAL (U"right End time"), GET_INTEGER (U"Number of formants"), order + 1, GET_INTEGER (U"Weigh data") - 1);
-		praat_new (thee.move(), my name, U"_o", order);
-	}
-END
+	CONVERT_EACH (Formant)
+		autoFormantModeler result = Formant_to_FormantModeler (me, fromTime, toTime, numberOfFormants, order + 1, weighDataType - 1);
+	CONVERT_EACH_END (my name, U"_o", order);
+}
 
-FORM (Formants_extractSmoothestPart, U"Formants: Extract smoothest part", U"Formants: Extract smoothest part")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	NATURAL (U"Number of formant tracks", U"4")
-	INTEGER (U"Order of polynomials", U"3")
+FORM (NEW1_Formants_extractSmoothestPart, U"Formants: Extract smoothest part", U"Formants: Extract smoothest part") {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
 	LABEL (U"", U"Use bandwidths to model the formant tracks:")
-	OPTIONMENU (U"Weigh data", 2)
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Zero parameter values whose range include zero:")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	OK
 DO
 	OrderedOf<structFormant> formants;
@@ -440,9 +404,7 @@ DO
 		iam (Formant);
 		formants. addItem_ref (me);
 	}
-	double tmin = GET_REAL (U"left Time range"), tmax = GET_REAL (U"right Time range");
-	long index = Formants_getSmoothestInInterval (& formants, tmin, tmax, GET_INTEGER (U"Number of formant tracks"), GET_INTEGER (U"Order of polynomials") + 1,
-		GET_INTEGER (U"Weigh data") - 1, 0, GET_REAL (U"Number of sigmas"), GET_REAL (U"Parameter variance power"), 1.0, 1.0, 1.0, 1.0, 1.0);
+	long index = Formants_getSmoothestInInterval (& formants, fromTime, toTime, numberOfFormantTracks, order + 1, weighDataType - 1, 0, numberOfSigmas, power, 1.0, 1.0, 1.0, 1.0, 1.0);
 	// next code is necessary to get the Formant at postion index selected and to get its name
 	long iselected = 0;
 	Formant him = nullptr;
@@ -453,30 +415,30 @@ DO
 		}
 	}
 	Melder_assert (him);
-	autoFormant thee = Formant_extractPart (him, tmin, tmax);
+	autoFormant thee = Formant_extractPart (him, fromTime, toTime);
 	praat_new (thee.move(), his name, U"_part");
-END
+END }
 
-FORM (Formants_extractSmoothestPart_constrained, U"Formants: Extract smoothest part (constrained)", U"Formants: Extract smoothest part (constrained)...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	NATURAL (U"Number of formant tracks", U"4")
-	INTEGER (U"Order of polynomials", U"3")
+FORM (NEW1_Formants_extractSmoothestPart_constrained, U"Formants: Extract smoothest part (constrained)", U"Formants: Extract smoothest part (constrained)...") {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
 	LABEL (U"", U"Use bandwidths to model the formant tracks:")
-	OPTIONMENU (U"Weigh data", 2)
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Zero parameter values whose range include zero:")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	LABEL (U"", U"The constraints on the formants:")
-	REAL (U"Minimum F1 (Hz)", U"100.0")
-	REAL (U"Maximum F1 (Hz)", U"1200.0")
-	REAL (U"Minimum F2 (Hz)", U"0.0")
-	POSITIVE (U"Maximum F2 (Hz)", U"5000.0")
-	POSITIVE (U"Minimum F3 (Hz)", U"1500.0")
+	REALVAR (minimumF1, U"Minimum F1 (Hz)", U"100.0")
+	REALVAR (maximumF1, U"Maximum F1 (Hz)", U"1200.0")
+	REALVAR (minimumF2, U"Minimum F2 (Hz)", U"0.0")
+	POSITIVEVAR (maximumF2, U"Maximum F2 (Hz)", U"5000.0")
+	POSITIVEVAR (minimumF3, U"Minimum F3 (Hz)", U"1500.0")
 	OK
 DO
 	OrderedOf<structFormant> formants;
@@ -484,10 +446,7 @@ DO
 		iam (Formant);
 		formants. addItem_ref (me);
 	}
-	double tmin = GET_REAL (U"left Time range"), tmax = GET_REAL (U"right Time range");
-	long index = Formants_getSmoothestInInterval (& formants, tmin, tmax, GET_INTEGER (U"Number of formant tracks"), GET_INTEGER (U"Order of polynomials") + 1,
-		GET_INTEGER (U"Weigh data") - 1, 1, GET_REAL (U"Number of sigmas"), GET_REAL (U"Parameter variance power"),
-		GET_REAL (U"Minimum F1"), GET_REAL (U"Maximum F1"), GET_REAL (U"Minimum F2"), GET_REAL (U"Maximum F2"), GET_REAL (U"Minimum F3"));
+	long index = Formants_getSmoothestInInterval (& formants, fromTime, toTime, numberOfFormantTracks, order + 1, weighDataType - 1, 1, numberOfSigmas, power, minimumF1, maximumF1, minimumF2, maximumF2, minimumF3);
 	// next code is necessary to get the Formant at postion index selected and to get its name
 	long iselected = 0;
 	Formant him = nullptr;
@@ -498,653 +457,523 @@ DO
 		}
 	}
 	Melder_assert (him);
-	autoFormant thee = Formant_extractPart (him, tmin, tmax);
+	autoFormant thee = Formant_extractPart (him, fromTime, toTime);
 	praat_new (thee.move(), his name, U"_part");
-END
+END }
 
 /********************** FormantModeler ******************************/
 
-FORM (FormantModeler_drawEstimatedTracks, U"FormantModeler: Draw estimated tracks", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"Maximum frequency (Hz)", U"5500.0")
-	NATURAL (U"left Formant range", U"1")
-	NATURAL (U"right Formant range", U"3")
-	INTEGER (U"Order of polynomials for estimation", U"3")
-	REAL (U"Horizontal offset (mm)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_FormantModeler_drawEstimatedTracks, U"FormantModeler: Draw estimated tracks", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	NATURALVAR (fromFormant, U"left Formant range", U"1")
+	NATURALVAR (toFormant, U"right Formant range", U"3")
+	INTEGERVAR (order, U"Order of polynomials for estimation", U"3")
+	REALVAR (xOffset_mm, U"Horizontal offset (mm)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	long order = GET_INTEGER (U"Order of polynomials for estimation");
 	REQUIRE (order >= 0, U"The order must be greater than or equal to zero.")
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_drawTracks (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_REAL (U"Maximum frequency"), GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"), 1, order + 1, 
-			GET_REAL (U"Horizontal offset"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_drawTracks (me, GRAPHICS, fromTime, toTime, maximumFrequency, fromFormant, toFormant, 1, order + 1, xOffset_mm, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FormantModeler_drawTracks, U"FormantModeler: Draw tracks", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"Maximum frequency (Hz)", U"5500.0")
-	NATURAL (U"left Formant range", U"1")
-	NATURAL (U"right Formant range", U"3")
-	REAL (U"Horizontal offset (mm)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_FormantModeler_drawTracks, U"FormantModeler: Draw tracks", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	NATURALVAR (fromFormant, U"left Formant range", U"1")
+	NATURALVAR (toFormant, U"right Formant range", U"3")
+	REALVAR (xOffset_mm, U"Horizontal offset (mm)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
 	long order = 6;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_drawTracks (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_REAL (U"Maximum frequency"), GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"),
-			0, order + 1, GET_REAL (U"Horizontal offset"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_drawTracks (me, GRAPHICS, fromTime, toTime, maximumFrequency, fromFormant, toFormant, 0, order + 1, xOffset_mm, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FormantModeler_speckle, U"FormantModeler: Speckle", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"Maximum frequency (Hz)", U"5500.0")
-	NATURAL (U"left Formant range", U"1")
-	NATURAL (U"right Formant range", U"3")
-	BOOLEAN (U"Draw error bars", true)
-	REAL (U"Bar width (mm)", U"1.0")
-	REAL (U"Horizontal offset (mm)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_FormantModeler_speckle, U"FormantModeler: Speckle", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	NATURALVAR (fromFormant, U"left Formant range", U"1")
+	NATURALVAR (toFormant, U"right Formant range", U"3")
+	BOOLEANVAR (errorBars, U"Draw error bars", true)
+	REALVAR (barWidth_mm, U"Bar width (mm)", U"1.0")
+	REALVAR (xOffset_mm, U"Horizontal offset (mm)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
 	long order = 6;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_speckle (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_REAL (U"Maximum frequency"), GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"),
-			0, order + 1, GET_INTEGER (U"Draw error bars"), GET_REAL (U"Bar width"), GET_REAL (U"Horizontal offset"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (FormantModeler_drawOutliersMarked, U"FormantModeler: Draw outliers marked", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"Maximum frequency (Hz)", U"5500.0")
-	NATURAL (U"left Formant range", U"1")
-	NATURAL (U"right Formant range", U"3")
-	POSITIVE (U"Number of sigmas", U"3.0")
-	OPTIONMENU (U"Weigh data", 2)
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_speckle (me, GRAPHICS, fromTime, toTime, maximumFrequency, fromFormant, toFormant, 0, order + 1, errorBars, barWidth_mm, xOffset_mm, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_FormantModeler_drawOutliersMarked, U"FormantModeler: Draw outliers marked", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	NATURALVAR (fromFormant, U"left Formant range", U"1")
+	NATURALVAR (toFormant, U"right Formant range", U"3")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"3.0")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
-	WORD (U"Mark", U"o")
-	NATURAL (U"Mark font size", U"12")
-	REAL (U"Horizontal offset (mm)", U"0.0")
-	BOOLEAN (U"Garnish", false)
+	WORDVAR (mark_string, U"Mark", U"o")
+	NATURALVAR (fontSize, U"Mark font size", U"12")
+	REALVAR (xOffset_mm, U"Horizontal offset (mm)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", false)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_drawOutliersMarked (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Maximum frequency"), GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"),
-			GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Weigh data") - 1, GET_STRING (U"Mark"),
-			GET_INTEGER (U"Mark font size"), GET_REAL (U"Horizontal offset"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (FormantModeler_drawVariancesOfShiftedTracks, U"FormantModeler: Draw variances of shifted tracks", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range", U"0.0")
-	REAL (U"left Variance range", U"0.0")
-	REAL (U"right Variance range", U"0.0")
-	OPTIONMENU (U"Shift tracks", 1)
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_drawOutliersMarked (me, GRAPHICS, fromTime, toTime, maximumFrequency, fromFormant, toFormant, numberOfSigmas, weighDataType - 1, mark_string, fontSize, xOffset_mm, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_FormantModeler_drawVariancesOfShiftedTracks, U"FormantModeler: Draw variances of shifted tracks", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (fromVariance, U"left Variance range", U"0.0")
+	REALVAR (toVariance, U"right Variance range", U"0.0")
+	OPTIONMENUVAR (shiftTracks, U"Shift tracks", 1)
 		OPTION (U"No")
 		OPTION (U"Up")
 		OPTION (U"Down")
-	NATURAL (U"left Formant range", U"1")
-	NATURAL (U"right Formant range", U"4")
-	BOOLEAN (U"Garnish", true)
+	NATURALVAR (fromFormant, U"left Formant range", U"1")
+	NATURALVAR (toFormant, U"right Formant range", U"4")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_drawVariancesOfShiftedTracks (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Variance range"), GET_REAL (U"right Variance range"), GET_INTEGER (U"Shift tracks"), 
-			GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (FormantModeler_drawCumulativeChiScores, U"FormantModeler: Draw cumulative chi scores", nullptr)
-	REAL (U"left Time range", U"0.0")
-	REAL (U"right Time range", U"0.0")
-	REAL (U"left Chisq range", U"0.0")
-	REAL (U"right Chisq range", U"0.0")
-	OPTIONMENU (U"Weigh data", 2)
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_drawVariancesOfShiftedTracks (me, GRAPHICS, fromTime, toTime, fromVariance, toVariance, shiftTracks, fromFormant, toFormant, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_FormantModeler_drawCumulativeChiScores, U"FormantModeler: Draw cumulative chi scores", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (fromChisq, U"left Chisq range", U"0.0")
+	REALVAR (toChisq, U"right Chisq range", U"0.0")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
-	BOOLEAN (U"Garnish", true)
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_drawCumulativeChiScores (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_REAL (U"left Chisq range"), GET_REAL (U"right Chisq range"), GET_INTEGER (U"Weigh data"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_drawCumulativeChiScores (me, GRAPHICS, fromTime, toTime, fromChisq, toChisq, weighDataType, garnish);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (FormantModeler_normalProbabilityPlot, U"FormantModeler: Normal probability plot", nullptr)
-	NATURAL (U"Formant number", U"1")
-	OPTIONMENU (U"Weigh data", 2)
+FORM (GRAPHICS_FormantModeler_normalProbabilityPlot, U"FormantModeler: Normal probability plot", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
-	NATURAL (U"Number of quantiles", U"100")
-	REAL (U"Number of sigmas", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", true);
+	NATURALVAR (numberOfQuantiles, U"Number of quantiles", U"100")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"0.0")
+	NATURALVAR (fontSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_normalProbabilityPlot (me, GRAPHICS, GET_INTEGER (U"Formant number"), GET_INTEGER (U"Weigh data") - 1,
-			GET_INTEGER (U"Number of quantiles"),
-			GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Label size"), GET_STRING (U"Label"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_normalProbabilityPlot (me, GRAPHICS, formantNumber, weighDataType - 1, numberOfQuantiles, numberOfSigmas, fontSize, label, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FormantModeler_drawBasisFunction, U"FormantModeler: Draw basis function", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Amplitude range (Hz)", U"0.0")
-	REAL (U"right Amplitude range (Hz)", U"5500.0")
+FORM (GRAPHICS_FormantModeler_drawBasisFunction, U"FormantModeler: Draw basis function", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (ymin, U"left Amplitude range (Hz)", U"0.0")
+	REALVAR (ymax, U"right Amplitude range (Hz)", U"5500.0")
 	//long iterm, bool scaled, long numberOfPoints, int garnish
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Basis function", U"2")
-	BOOLEAN (U"Scale function with parameter value", false)
-	NATURAL (U"Number of points", U"200")
-	BOOLEAN (U"Garnish", true)
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (basisFunctionIndex, U"Basis function", U"2")
+	BOOLEANVAR (scale, U"Scale function with parameter value", false)
+	NATURALVAR (numberOfPoints, U"Number of points", U"200")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_drawBasisFunction (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),GET_INTEGER (U"Formant number"),
- 			GET_INTEGER (U"Basis function"), GET_INTEGER (U"Scale function with parameter value"),
-			GET_INTEGER (U"Number of points"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FormantModeler)
+		FormantModeler_drawBasisFunction (me, GRAPHICS, fromTime, toTime, ymin, ymax, formantNumber, basisFunctionIndex, scale, numberOfPoints, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FormantModeler_getModelValueAtTime, U"", nullptr)
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.1")
+FORM (REAL_FormantModeler_getModelValueAtTime, U"", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	REALVAR (time, U"Time (s)", U"0.1")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		double y = FormantModeler_getModelValueAtTime (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"));
-		Melder_informationReal (y, U"Hertz");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getModelValueAtTime (me, formantNumber, time);
+	NUMBER_ONE_END (U"Hertz")
+}
+
 
-FORM (FormantModeler_getDataPointValue, U"FormantModeler: Get data point value", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Index", U"1")
+FORM (REAL_FormantModeler_getDataPointValue, U"FormantModeler: Get data point value", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (FormantModeler);
-		double value = FormantModeler_getDataPointValue (me, iformant, index);
-		Melder_information (value, U" (= value of point ", index, U" in track F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getDataPointValue (me, formantNumber, index);
+	NUMBER_ONE_END (U" (= value of point ", index, U" in track F", formantNumber, U")")
+}
 
-FORM (FormantModeler_getDataPointSigma, U"FormantModeler: Get data point sigma", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Index", U"1")
+FORM (REAL_FormantModeler_getDataPointSigma, U"FormantModeler: Get data point sigma", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (FormantModeler);
-		double value = FormantModeler_getDataPointSigma (me, iformant, index);
-		Melder_information (value, U" (= sigma of point ", index, U" in track F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getDataPointSigma (me, formantNumber, index);
+	NUMBER_ONE_END (U" (= sigma of point ", index, U" in track F", formantNumber, U")")
+}
+
 
-FORM (FormantModeler_getDataPointStatus, U"FormantModeler: Get data point status", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Index", U"1")
+FORM (INFO_FormantModeler_getDataPointStatus, U"FormantModeler: Get data point status", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (FormantModeler);
-		int status = FormantModeler_getDataPointStatus (me, iformant, index);
-		Melder_information (status == DataModeler_DATA_INVALID ? U"Invalid" : U"Valid");
-	}
-END
+	INTEGER_ONE (FormantModeler)
+		int status = FormantModeler_getDataPointStatus (me, formantNumber, index);
+		const char32 *result = status == DataModeler_DATA_INVALID ? U"Invalid" : U"Valid";
+	INTEGER_ONE_END (U"")
+}
+
+DIRECT (INTEGER_FormantModeler_getNumberOfTracks) {
+	INTEGER_ONE (FormantModeler)
+		long result = FormantModeler_getNumberOfTracks (me);
+	INTEGER_ONE_END (U" (= number of formants)")
+}
 
-DIRECT (FormantModeler_getNumberOfTracks)
-	LOOP {
-		iam (FormantModeler);
-		long nop = FormantModeler_getNumberOfTracks (me);
-		Melder_information (nop, U" (= number of formants)");
-	}
-END
 
-FORM (FormantModeler_getNumberOfParameters, U"FormantModeler: Get number of parameters", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (INTEGER_FormantModeler_getNumberOfParameters, U"FormantModeler: Get number of parameters", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		long nop = FormantModeler_getNumberOfParameters (me, iformant);
-		Melder_information (nop, U" (= number of parameters for F", iformant, U")");
-	}
-END
+	INTEGER_ONE (FormantModeler)
+		long result = FormantModeler_getNumberOfParameters (me, formantNumber);
+	INTEGER_ONE_END (U" (= number of parameters for F", formantNumber, U")")
+}
+
 
-FORM (FormantModeler_getNumberOfFixedParameters, U"FormantModeler: Get number of fixed parameters", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (INTEGER_FormantModeler_getNumberOfFixedParameters, U"FormantModeler: Get number of fixed parameters", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		long nop = FormantModeler_getNumberOfFixedParameters (me, iformant);
-		Melder_information (nop, U" (= number of fixed parameters for F", iformant, U")");
-	}
-END
+	INTEGER_ONE (FormantModeler)
+		long result = FormantModeler_getNumberOfFixedParameters (me, formantNumber);
+	INTEGER_ONE_END (U" (= number of fixed parameters for F", formantNumber, U")")
+}
 
-DIRECT (FormantModeler_getNumberOfDataPoints)
-	LOOP {
-		iam (FormantModeler);
-		long numberOfDataPoints = FormantModeler_getNumberOfDataPoints (me);
-		Melder_information (numberOfDataPoints);
-	}
-END
+DIRECT (INTEGER_FormantModeler_getNumberOfDataPoints) {
+	INTEGER_ONE (FormantModeler)
+		long result = FormantModeler_getNumberOfDataPoints (me);
+	INTEGER_ONE_END (U"")
+}
 
-FORM (FormantModeler_getNumberOfInvalidDataPoints, U"FormantModeler: Get number of invalid data points", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (INTEGER_FormantModeler_getNumberOfInvalidDataPoints, U"FormantModeler: Get number of invalid data points", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		long numberOfInvalidDataPoints = FormantModeler_getNumberOfInvalidDataPoints (me, iformant);
-		Melder_information (numberOfInvalidDataPoints, U" (= number of invalid data points for F", iformant, U")");
-	}
-END
+	INTEGER_ONE (FormantModeler)
+		long result = FormantModeler_getNumberOfInvalidDataPoints (me, formantNumber);
+	INTEGER_ONE_END (U" (= number of invalid data points for F", formantNumber, U")")
+}
 
-FORM (FormantModeler_getParameterValue, U"FormantModeler: Get parameter value", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Parameter number", U"1")
+FORM (REAL_FormantModeler_getParameterValue, U"FormantModeler: Get parameter value", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number"), iparameter = GET_INTEGER (U"Parameter number");
-	LOOP {
-		iam (FormantModeler);
-		double parameter = FormantModeler_getParameterValue (me, iformant, iparameter);
-		Melder_information (parameter, U" (= parameter[", iparameter, U"] for F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getParameterValue (me, formantNumber, parameterNumber);
+	NUMBER_ONE_END (U" (= parameter[", parameterNumber, U"] for F", formantNumber, U")")
+}
 
-FORM (FormantModeler_getParameterStatus, U"FormantModeler: Get parameter status", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Parameter number", U"1")
+FORM (INFO_FormantModeler_getParameterStatus, U"FormantModeler: Get parameter status", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number"), iparameter = GET_INTEGER (U"Parameter number");
-	LOOP {
-		iam (FormantModeler);
-		int status = FormantModeler_getParameterStatus (me, iformant, iparameter);
-		Melder_information (status == DataModeler_PARAMETER_FREE ? U"Free" : (status == DataModeler_PARAMETER_FIXED ? U"Fixed" :
-			U"Undefined"), U" (= parameter[", iparameter, U"] for F", iformant, U")");
-	}
-END
+	STRING_ONE (FormantModeler)
+		int status = FormantModeler_getParameterStatus (me, formantNumber, parameterNumber);
+		const char32 *result = Melder_cat (status == DataModeler_PARAMETER_FREE ? U"Free" : (status == DataModeler_PARAMETER_FIXED ? U"Fixed" :
+		U"Undefined"), U" (= parameter[", parameterNumber, U"] for F", formantNumber, U")");
+	STRING_ONE_END
+}
 
-FORM (FormantModeler_getParameterStandardDeviation, U"FormantModeler: Get parameter standard deviatio", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Parameter number", U"1")
+FORM (REAL_FormantModeler_getParameterStandardDeviation, U"FormantModeler: Get parameter standard deviatio", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number"), iparameter = GET_INTEGER (U"Parameter number");
-	LOOP {
-		iam (FormantModeler);
-		double sigma = FormantModeler_getParameterStandardDeviation (me, iformant, iparameter);
-		Melder_information (sigma, U" (= parameter[", iparameter, U"] for F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getParameterStandardDeviation (me, formantNumber, parameterNumber);
+	NUMBER_ONE_END (U" (= parameter[", parameterNumber, U"] for F", formantNumber, U")")
+}
 
-FORM (FormantModeler_getVarianceOfParameters, U"FormantModeler: Get variance of parameters", nullptr)
-	INTEGER (U"left Formant range", U"0")
-	INTEGER (U"right Formant range", U"0")
-	INTEGER (U"left Parameter range", U"0")
-	INTEGER (U"right Parameter range", U"0")
+
+FORM (REAL_FormantModeler_getVarianceOfParameters, U"FormantModeler: Get variance of parameters", nullptr) {
+	INTEGERVAR (fromFormant, U"left Formant range", U"0")
+	INTEGERVAR (toFormant, U"right Formant range", U"0")
+	INTEGERVAR (fromParameter, U"left Parameter range", U"0")
+	INTEGERVAR (toParameter, U"right Parameter range", U"0")
 	OK
 DO
 	long nofp;
-	LOOP {
-		iam (FormantModeler);
-		double var = FormantModeler_getVarianceOfParameters (me, GET_INTEGER (U"left Formant range"), 
-			GET_INTEGER (U"right Formant range"), GET_INTEGER (U"left Parameter range"), GET_INTEGER (U"right Parameter range"), &nofp);
-		Melder_information (var, U" (for ", nofp, U" free parameters.)");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getVarianceOfParameters (me, fromFormant, toFormant, fromParameter, toParameter, &nofp);
+	NUMBER_ONE_END (U" (for ", nofp, U" free parameters.)")
+}
 
-FORM (FormantModeler_getCoefficientOfDetermination, U"FormantModeler: Get coefficient of determination", nullptr)
-	INTEGER (U"left Formant range", U"0")
-	INTEGER (U"right Formant range", U"0")
+
+FORM (REAL_FormantModeler_getCoefficientOfDetermination, U"FormantModeler: Get coefficient of determination", nullptr) {
+	INTEGERVAR (fromFormant, U"left Formant range", U"0")
+	INTEGERVAR (toFormant, U"right Formant range", U"0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		double rSquared = FormantModeler_getCoefficientOfDetermination (me, GET_INTEGER (U"left Formant range"), 
-			GET_INTEGER (U"right Formant range"));
-		Melder_informationReal (rSquared, U" (= R^2)");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getCoefficientOfDetermination (me, fromFormant, toFormant);
+	NUMBER_ONE_END (U" (= R^2)");
+}
+
 
-FORM (FormantModeler_getResidualSumOfSquares, U"FormantModeler: Get residual sum of squares", U"FormantModeler: Get residual sum of squares...")
-	NATURAL (U"Formant number", U"1")
+FORM (REAL_FormantModeler_getResidualSumOfSquares, U"FormantModeler: Get residual sum of squares", U"FormantModeler: Get residual sum of squares...") {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long n, iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		double rss = FormantModeler_getResidualSumOfSquares (me, iformant, &n);
-		Melder_information (rss, U" Hz^2,  (= RSS of F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getResidualSumOfSquares (me, formantNumber, nullptr);
+	NUMBER_ONE_END (U" Hz^2,  (= RSS of F", formantNumber, U")")
+}
 
-FORM (FormantModeler_getStandardDeviation, U"FormantModeler: Get formant standard deviation", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (REAL_FormantModeler_getStandardDeviation, U"FormantModeler: Get formant standard deviation", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		double sigma = FormantModeler_getStandardDeviation (me, iformant);
-		Melder_information (sigma, U" Hz (= std. dev. of F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getStandardDeviation (me, formantNumber);
+	NUMBER_ONE_END (U" Hz (= std. dev. of F", formantNumber, U")")
+}
 
-FORM (FormantModeler_reportChiSquared, U"FormantModeler: Report chi squared", nullptr)
-	OPTIONMENU (U"Weigh data", 2)
+FORM (INFO_FormantModeler_reportChiSquared, U"FormantModeler: Report chi squared", nullptr) {
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		long numberOfFormants = my trackmodelers.size;
-		int useSigmaY = GET_INTEGER (U"Weigh data") - 1;
-		double chisq = 0, ndf = 0, probability;
-		MelderInfo_open ();
-		MelderInfo_writeLine (U"Chi squared tests for individual models of each of ", numberOfFormants, U" formant track:");
-		MelderInfo_writeLine (useSigmaY == DataModeler_DATA_WEIGH_EQUAL ? U"Standard deviation is estimated from the data." :
-			useSigmaY == DataModeler_DATA_WEIGH_SIGMA ? U"\tBandwidths are used as estimate for local standard deviations." : 
-			useSigmaY == DataModeler_DATA_WEIGH_RELATIVE ? U"\t1/Q's are used as estimate for local standard deviations." :
-			U"\tSqrt bandwidths are used as estimate for local standard deviations.");
-		for (long iformant = 1; iformant <= numberOfFormants; iformant ++) {
-			chisq = FormantModeler_getChiSquaredQ (me, iformant, iformant, useSigmaY, &probability, &ndf);
-			MelderInfo_writeLine (U"Formant track ", iformant, U":");
-			MelderInfo_writeLine (U"\tChi squared (F", iformant, U") = ", chisq);
-			MelderInfo_writeLine (U"\tProbability (F", iformant, U") = ", probability);
-			MelderInfo_writeLine (U"\tNumber of degrees of freedom (F", iformant, U") = ", ndf);
-		}
-		chisq = FormantModeler_getChiSquaredQ (me, 1, numberOfFormants, useSigmaY, & probability, & ndf);
-		MelderInfo_writeLine (U"Chi squared test for the complete model with ", numberOfFormants, U" formants:");
-		MelderInfo_writeLine (U"\tChi squared = ", chisq);
-		MelderInfo_writeLine (U"\tProbability = ", probability);
-		MelderInfo_writeLine (U"\tNumber of degrees of freedom = ", ndf);
-		MelderInfo_close ();
-	}
-END
+	INFO_ONE (FormantModeler)
+		MelderInfo_open();
+		FormantModeler_reportChiSquared (me, weighDataType);
+		MelderInfo_close();
+	INFO_ONE_END
+}
 
-FORM (FormantModeler_getDegreesOfFreedom, U"FormantModeler: Get degrees of freedom", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (REAL_FormantModeler_getDegreesOfFreedom, U"FormantModeler: Get degrees of freedom", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		double sigma = FormantModeler_getDegreesOfFreedom (me, iformant);
-		Melder_information (sigma, U" (= degrees of freedom of F", iformant, U")");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getDegreesOfFreedom (me, formantNumber);
+	NUMBER_ONE_END (U" (= degrees of freedom of F", formantNumber, U")")
+}
 
-FORM (FormantModeler_getSmoothnessValue, U"FormantModeler: Get smoothness value", nullptr)
-	INTEGER (U"left Formant range", U"0")
-	INTEGER (U"right Formant range", U"0")
-	INTEGER (U"Order of polynomials", U"3")
-	REAL (U"Parameter variance power", U"1.5")
+FORM (REAL_FormantModeler_getSmoothnessValue, U"FormantModeler: Get smoothness value", nullptr) {
+	INTEGERVAR (fromFormant, U"left Formant range", U"0")
+	INTEGERVAR (toFormant, U"right Formant range", U"0")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		double smoothness = FormantModeler_getSmoothnessValue (me, GET_INTEGER (U"left Formant range"), 
-			GET_INTEGER (U"right Formant range"), GET_INTEGER (U"Order of polynomials"), GET_REAL (U"Parameter variance power"));
-		Melder_information (smoothness, U" (= smoothness)");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getSmoothnessValue (me, fromFormant, toFormant, order, power);
+	NUMBER_ONE_END (U" (= smoothness)")
+}
 
-FORM (FormantModeler_getAverageDistanceBetweenTracks, U"FormantModeler: Get average distance between tracks", nullptr)
-	NATURAL (U"Track 1", U"2")
-	NATURAL (U"Track 2", U"3")
-	OPTIONMENU (U"Type of data", 1)
+FORM (REAL_FormantModeler_getAverageDistanceBetweenTracks, U"FormantModeler: Get average distance between tracks", nullptr) {
+	NATURALVAR (track1, U"Track 1", U"2")
+	NATURALVAR (track2, U"Track 2", U"3")
+	OPTIONMENUVAR (typeOfData, U"Type of data", 1)
 		OPTION (U"Data points")
 		OPTION (U"Modeled")
 	OK
 DO
-	long track1 = GET_INTEGER (U"Track 1"), track2 = GET_INTEGER (U"Track 2");
-	LOOP {
-		iam (FormantModeler);
-		double distance = FormantModeler_getAverageDistanceBetweenTracks (me, track1, track2, GET_INTEGER (U"Type of data") - 1);
-		Melder_information (distance, U" (= average |F", track1, U" - F", track2, U"|)");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getAverageDistanceBetweenTracks (me, track1, track2, typeOfData - 1);
+	NUMBER_ONE_END (U" (= average |F", track1, U" - F", track2, U"|)")
+}
 
-FORM (FormantModeler_getFormantsConstraintsFactor, U"FormantModeler: Get formants constraints factor", nullptr)
-	REAL (U"Minimum F1 (Hz)", U"100.0")
-	REAL (U"Maximum F1 (Hz)", U"1200.0")
-	REAL (U"Minimum F2 (Hz)", U"0.0")
-	POSITIVE (U"Maximum F2 (Hz)", U"5000.0")
-	POSITIVE (U"Minimum F3 (Hz)", U"1500.0")
+FORM (REAL_FormantModeler_getFormantsConstraintsFactor, U"FormantModeler: Get formants constraints factor", nullptr) {
+	REALVAR (minimumF1, U"Minimum F1 (Hz)", U"100.0")
+	REALVAR (maximumF1, U"Maximum F1 (Hz)", U"1200.0")
+	REALVAR (minimumF2, U"Minimum F2 (Hz)", U"0.0")
+	POSITIVEVAR (maximumF2, U"Maximum F2 (Hz)", U"5000.0")
+	POSITIVEVAR (minimumF3, U"Minimum F3 (Hz)", U"1500.0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		double fc = FormantModeler_getFormantsConstraintsFactor (me, GET_REAL (U"Minimum F1"), GET_REAL (U"Maximum F1"),
-		GET_REAL (U"Minimum F2"), GET_REAL (U"Maximum F2"), GET_REAL (U"Minimum F3"));
-		Melder_information (fc, U" (= formants constraints factor)");
-	}
-END
+	NUMBER_ONE (FormantModeler)
+		double result = FormantModeler_getFormantsConstraintsFactor (me, minimumF1, maximumF1, minimumF2, maximumF2, minimumF3);
+	NUMBER_ONE_END (U" (= formants constraints factor)");
+}
 
-FORM (FormantModeler_setDataWeighing, U"FormantModeler: Set data weighing", nullptr)
-	INTEGER (U"left Formant range", U"0")
-	INTEGER (U"right Formant range", U"0")
-	OPTIONMENU (U"Weigh data", 2)
+FORM (MODIFY_FormantModeler_setDataWeighing, U"FormantModeler: Set data weighing", nullptr) {
+	INTEGERVAR (fromFormant, U"left Formant range", U"0")
+	INTEGERVAR (toFormant, U"right Formant range", U"0")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setDataWeighing (me, GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"), 
-			GET_INTEGER (U"Weigh data") - 1);
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setDataWeighing (me, fromFormant, toFormant, weighDataType - 1);
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_setTolerance, U"FormantModeler: Set tolerance", nullptr)
-	REAL (U"Tolerance", U"1e-5")
+FORM (MODIFY_FormantModeler_setTolerance, U"FormantModeler: Set tolerance", nullptr) {
+	REALVAR (tolerance, U"Tolerance", U"1e-5")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setTolerance (me, GET_REAL (U"Tolerance"));
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setTolerance (me, tolerance);
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_setParameterValueFixed, U"FormantModeler: Set parameter value fixed", nullptr)
-	NATURAL (U"Formant number", U"1")
-	NATURAL (U"Parameter number", U"1")
-	REAL (U"Value", U"0.0")
+FORM (MODIFY_FormantModeler_setParameterValueFixed, U"FormantModeler: Set parameter value fixed", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	NATURALVAR (parameterNumber, U"Parameter number", U"1")
+	REALVAR (parameterValue, U"Value", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setParameterValueFixed (me, GET_INTEGER (U"Formant number"), GET_INTEGER (U"Parameter number"), GET_REAL (U"Value"));
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setParameterValueFixed (me, formantNumber, parameterNumber, parameterValue);
+	MODIFY_EACH_END
+}
 
 
-FORM (FormantModeler_setParameterFree, U"FormantModeler: Set parameter free", nullptr)
-	INTEGER (U"left Formant range", U"0")
-	INTEGER (U"right Formant range", U"0")
-	INTEGER (U"left Parameter range", U"0")
-	INTEGER (U"right Parameter range", U"0")
+FORM (MODIFY_FormantModeler_setParameterFree, U"FormantModeler: Set parameter free", nullptr) {
+	INTEGERVAR (fromFormant, U"left Formant range", U"0")
+	INTEGERVAR (toFormant, U"right Formant range", U"0")
+	INTEGERVAR (fromParameter, U"left Parameter range", U"0")
+	INTEGERVAR (toParameter, U"right Parameter range", U"0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setParametersFree (me, GET_INTEGER (U"left Formant range"), GET_INTEGER (U"right Formant range"),
-			GET_INTEGER (U"left Parameter range"), GET_INTEGER (U"right Parameter range"));
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setParametersFree (me, fromFormant, toFormant, fromParameter, toParameter);
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_setParameterValuesToZero, U"FormantModeler: Set parameter values to zero", nullptr)
-	INTEGER (U"left Formant range", U"0")
-	INTEGER (U"right Formant range", U"0")
-	REAL (U"Number of sigmas", U"1.0")
+FORM (MODIFY_FormantModeler_setParameterValuesToZero, U"FormantModeler: Set parameter values to zero", nullptr) {
+	INTEGERVAR (fromFormant, U"left Formant range", U"0")
+	INTEGERVAR (toFormant, U"right Formant range", U"0")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setParameterValuesToZero (me, GET_INTEGER (U"left Formant range"),  GET_INTEGER (U"right Formant range"),
-			 GET_REAL (U"Number of sigmas"));
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setParameterValuesToZero (me, fromFormant,  toFormant, numberOfSigmas);
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_setDataPointValue, U"FormantModeler: Set data point value", nullptr)
-	NATURAL (U"Formant index", U"1")
-	NATURAL (U"Data index", U"1")
-	REAL (U"Value", U"1.0")
+FORM (MODIFY_FormantModeler_setDataPointValue, U"FormantModeler: Set data point value", nullptr) {
+	NATURALVAR (formantNumber, U"Formant index", U"1")
+	NATURALVAR (dataNumber, U"Data index", U"1")
+	REALVAR (value, U"Value", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setDataPointValue (me, GET_INTEGER (U"Formant index"),  GET_INTEGER (U"Data index"),
-			 GET_REAL (U"Value"));
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setDataPointValue (me, formantNumber,  dataNumber, value);
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_setDataPointSigma, U"FormantModeler: Set data point sigma", nullptr)
-	NATURAL (U"Formant index", U"1")
-	NATURAL (U"Data index", U"1")
-	REAL (U"Sigma", U"10.0")
+FORM (MODIFY_FormantModeler_setDataPointSigma, U"FormantModeler: Set data point sigma", nullptr) {
+	NATURALVAR (formantNumber, U"Formant index", U"1")
+	NATURALVAR (dataNumber, U"Data index", U"1")
+	REALVAR (sigma, U"Sigma", U"10.0")
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setDataPointSigma (me, GET_INTEGER (U"Formant index"),  GET_INTEGER (U"Data index"),
-			 GET_REAL (U"Sigma"));
-	}
-END
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setDataPointSigma (me, formantNumber,  dataNumber, sigma);
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_setDataPointStatus, U"FormantModeler: Set data point status", nullptr)
-	NATURAL (U"Formant index", U"1")
-	NATURAL (U"Data index", U"1")
-	OPTIONMENU (U"Status", 1)
+FORM (MODIFY_FormantModeler_setDataPointStatus, U"FormantModeler: Set data point status", nullptr) {
+	NATURALVAR (formantNumber, U"Formant index", U"1")
+	NATURALVAR (dataNumber, U"Data index", U"1")
+	OPTIONMENUVAR (dataStatus, U"Status", 1)
 		OPTION (U"Valid")
 		OPTION (U"Invalid")
 	OK
 DO
-	int menustatus = GET_INTEGER (U"Status");
-	int status = menustatus == 2 ? DataModeler_DATA_INVALID : DataModeler_DATA_VALID;
-	LOOP {
-		iam (FormantModeler);
-		FormantModeler_setDataPointStatus (me, GET_INTEGER (U"Formant index"),  GET_INTEGER (U"Data index"), status);
-	}
-END
+	int status = dataStatus == 2 ? DataModeler_DATA_INVALID : DataModeler_DATA_VALID;
+	MODIFY_EACH (FormantModeler)
+		FormantModeler_setDataPointStatus (me, formantNumber,  dataNumber, status);
+	MODIFY_EACH_END
+}
 
-DIRECT (FormantModeler_fitModel)
-	LOOP {
-		iam (FormantModeler);
+DIRECT (MODIFY_FormantModeler_fitModel) {
+	MODIFY_EACH (FormantModeler)
 		FormantModeler_fit (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (FormantModeler_to_Covariance_parameters, U"", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (NEW_FormantModeler_to_Covariance_parameters, U"", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		autoCovariance thee = FormantModeler_to_Covariance_parameters (me, iformant);
-		praat_new (thee.move(), my name, U"_", iformant);
-	}
-END
+	CONVERT_EACH (FormantModeler)
+		autoCovariance result = FormantModeler_to_Covariance_parameters (me, formantNumber);
+	CONVERT_EACH_END (my name, U"_", formantNumber);
+}
 
-FORM (FormantModeler_extractDataModeler, U"FormantModeler: Extract DataModeler", nullptr)
-	NATURAL (U"Formant number", U"1")
+FORM (NEW_FormantModeler_extractDataModeler, U"FormantModeler: Extract DataModeler", nullptr) {
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	long iformant = GET_INTEGER (U"Formant number");
-	LOOP {
-		iam (FormantModeler);
-		autoDataModeler thee = FormantModeler_extractDataModeler (me, iformant);
-		praat_new (thee.move(), my name, U"_", iformant);
-	}
-END
+	CONVERT_EACH (FormantModeler)
+		autoDataModeler result = FormantModeler_extractDataModeler (me, formantNumber);
+	CONVERT_EACH_END (my name, U"_", formantNumber)
+}
 
-FORM (FormantModeler_to_Table_zscores, U"", nullptr)
-	BOOLEAN (U"Bandwidths as standard deviation", true)
+FORM (NEW_FormantModeler_to_Table_zscores, U"", nullptr) {
+	BOOLEANVAR (useBandwidth, U"Bandwidths as standard deviation", true)
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		autoTable thee = FormantModeler_to_Table_zscores (me, GET_INTEGER (U"Bandwidths as standard deviation"));
-		praat_new (thee.move(), my name, U"_z");
-	}
-END
+	CONVERT_EACH (FormantModeler)
+		autoTable result = FormantModeler_to_Table_zscores (me, useBandwidth);
+	CONVERT_EACH_END (my name, U"_z")
+}
 
-FORM (FormantModeler_processOutliers, U"", nullptr)
-	POSITIVE (U"Number of sigmas", U"3.0")
-	BOOLEAN (U"Bandwidths as standard deviation", true)
+FORM (NEW_FormantModeler_processOutliers, U"", nullptr) {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"3.0")
+	BOOLEANVAR (useBandwidth, U"Bandwidths as standard deviation", true)
 	OK
 DO
-	LOOP {
-		iam (FormantModeler);
-		autoFormantModeler thee = FormantModeler_processOutliers (me, GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Bandwidths as standard deviation"));
-		praat_new (thee.move(), my name, U"_outliers");
-	}
-END
+	CONVERT_EACH (FormantModeler)
+		autoFormantModeler result = FormantModeler_processOutliers (me, numberOfSigmas, useBandwidth);
+	CONVERT_EACH_END (my name, U"_outliers");
+}
 
 
-DIRECT (OptimalCeilingTier_edit)
+DIRECT (WINDOW_OptimalCeilingTier_edit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an OptimalCeilingTier from batch.");
 	Sound sound = nullptr;
 	LOOP {
@@ -1158,372 +987,326 @@ DIRECT (OptimalCeilingTier_edit)
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END
+END }
 
 
 /*************************** PitchModeler *************************************/
 
-FORM (Pitch_to_PitchModeler, U"Pitch: To PitchModeler", nullptr)
-	REAL (U"left Start time (s)", U"0.0")
-	REAL (U"right End time (s)", U"0.1")
-	INTEGER (U"Order of polynomials", U"2")
+FORM (NEW_Pitch_to_PitchModeler, U"Pitch: To PitchModeler", nullptr) {
+	REALVAR (fromTime, U"left Start time (s)", U"0.0")
+	REALVAR (toTime, U"right End time (s)", U"0.1")
+	INTEGERVAR (order, U"Order of polynomials", U"2")
 	OK
 DO
-	LOOP {
-		iam (Pitch);
-		autoPitchModeler thee = Pitch_to_PitchModeler (me, GET_REAL (U"left Start time"), GET_REAL (U"right End time"), 
-			GET_INTEGER (U"Order of polynomials") + 1);
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Pitch)
+		autoPitchModeler result = Pitch_to_PitchModeler (me, fromTime, toTime, order + 1);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (PitchModeler_draw, U"PitchModeler: Draw", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"500.0")
-	INTEGER (U"Order of polynomial for estimation", U"2")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_PitchModeler_draw, U"PitchModeler: Draw", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"0.0")
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"500.0")
+	INTEGERVAR (order, U"Order of polynomial for estimation", U"2")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (PitchModeler);
-		PitchModeler_draw (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"), GET_INTEGER (U"Order of polynomial for estimation") + 1,  GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Sound_getOptimalFormantCeiling, U"Sound: Get optimal formant ceiling", nullptr)
-	REAL (U"left Time range (s)", U"0.1")
-	REAL (U"right Time range (s)", U"0.15")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.0025")
-	POSITIVE (U"left Maximum frequency range (Hz)", U"4500.0")
-	POSITIVE (U"right Maximum frequency range (Hz)", U"6500.0")
-	NATURAL (U"Number of frequency steps", U"11")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	NATURAL (U"Number of formant tracks in model", U"4")
-	INTEGER (U"Order of polynomials", U"3")
-	OPTIONMENU (U"Weigh data", 2)
+	GRAPHICS_EACH (PitchModeler)
+		PitchModeler_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, order + 1,  garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (REAL_Sound_getOptimalFormantCeiling, U"Sound: Get optimal formant ceiling", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.1")
+	REALVAR (toTime, U"right Time range (s)", U"0.15")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.0025")
+	POSITIVEVAR (fromFrequency, U"left Maximum frequency range (Hz)", U"4500.0")
+	POSITIVEVAR (toFrequency, U"right Maximum frequency range (Hz)", U"6500.0")
+	NATURALVAR (numberOfFrequencySteps, U"Number of frequency steps", U"11")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks in model", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Make parameters that include zero in their confidence region zero")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		double ceiling = Sound_getOptimalFormantCeiling (me, 
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Window length"), GET_REAL (U"Time step"), GET_REAL (U"left Maximum frequency range"), 
-			GET_REAL (U"right Maximum frequency range"), GET_INTEGER (U"Number of frequency steps"), 
-			GET_REAL (U"Pre-emphasis from"), 
-			GET_INTEGER (U"Number of formant tracks in model"), GET_INTEGER (U"Order of polynomials") + 1,
-			GET_INTEGER (U"Weigh data") - 1, GET_REAL (U"Number of sigmas"), GET_REAL (U"Parameter variance power"));
-	Melder_informationReal (ceiling, U" Hz");
-	}
-END
-
-FORM (Sound_to_Formant_interval, U"Sound: To Formant (interval)", nullptr)
-	REAL (U"left Time range (s)", U"0.1")
-	REAL (U"right Time range (s)", U"0.15")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.0025")
-	POSITIVE (U"left Maximum frequency range (Hz)", U"4500.0")
-	POSITIVE (U"right Maximum frequency range (Hz)", U"6500.0")
-	NATURAL (U"Number of frequency steps", U"11")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	NATURAL (U"Number of formant tracks in model", U"4")
-	INTEGER (U"Order of polynomials", U"3")
-	OPTIONMENU (U"Weigh data", 2)
+	NUMBER_ONE (Sound)
+		double result = Sound_getOptimalFormantCeiling (me, fromTime, toTime, windowLength, timeStep, fromFrequency, toFrequency, numberOfFrequencySteps, preEmphasisFrequency, numberOfFormantTracks, order + 1, weighDataType - 1, numberOfSigmas, power);
+	NUMBER_ONE_END (U" Hz");
+}
+
+FORM (NEW_Sound_to_Formant_interval, U"Sound: To Formant (interval)", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.1")
+	REALVAR (toTime, U"right Time range (s)", U"0.15")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.0025")
+	POSITIVEVAR (fromFrequency, U"left Maximum frequency range (Hz)", U"4500.0")
+	POSITIVEVAR (toFrequency, U"right Maximum frequency range (Hz)", U"6500.0")
+	NATURALVAR (numberOfFrequencySteps, U"Number of frequency steps", U"11")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks in model", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Make parameters that include zero in their confidence region zero")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	OK
 DO
-	LOOP {
-		iam (Sound);
+	CONVERT_EACH (Sound)
 		double ceiling;
-		autoFormant formant = Sound_to_Formant_interval (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Window length"), GET_REAL (U"Time step"), GET_REAL (U"left Maximum frequency range"), 
-			GET_REAL (U"right Maximum frequency range"), GET_INTEGER (U"Number of frequency steps"), 
-			GET_REAL (U"Pre-emphasis from"), 
-			GET_INTEGER (U"Number of formant tracks in model"), GET_INTEGER (U"Order of polynomials") + 1,
-			GET_INTEGER (U"Weigh data") - 1, GET_REAL (U"Number of sigmas"), GET_REAL (U"Parameter variance power"),
-			0, 1, 1, 1, 1, 1, &ceiling);
-		praat_new (formant.move(), my name, U"_", Melder_fixed (ceiling, 0));
-	}
-END
-
-FORM (Sound_to_Formant_interval_constrained, U"Sound: To Formant (interval, constrained)", nullptr)
-	REAL (U"left Time range (s)", U"0.1")
-	REAL (U"right Time range (s)", U"0.15")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.0025")
-	POSITIVE (U"left Maximum frequency range (Hz)", U"4500.0")
-	POSITIVE (U"right Maximum frequency range (Hz)", U"6500.0")
-	NATURAL (U"Number of frequency steps", U"11")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	NATURAL (U"Number of formant tracks in model", U"4")
-	INTEGER (U"Order of polynomials", U"3")
-	OPTIONMENU (U"Weigh data", 2)
+		autoFormant result = Sound_to_Formant_interval (me, fromTime, toTime, windowLength, timeStep, fromFrequency, toFrequency, numberOfFrequencySteps, preEmphasisFrequency, numberOfFormantTracks, order + 1, weighDataType - 1, numberOfSigmas, power, 0, 1, 1, 1, 1, 1, &ceiling);
+	CONVERT_EACH_END (my name, U"_", Melder_fixed (ceiling, 0))
+}
+
+FORM (NEW_Sound_to_Formant_interval_constrained, U"Sound: To Formant (interval, constrained)", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.1")
+	REALVAR (toTime, U"right Time range (s)", U"0.15")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.0025")
+	POSITIVEVAR (fromFrequency, U"left Maximum frequency range (Hz)", U"4500.0")
+	POSITIVEVAR (toFrequency, U"right Maximum frequency range (Hz)", U"6500.0")
+	NATURALVAR (numberOfFrequencySteps, U"Number of frequency steps", U"11")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks in model", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Make parameters that include zero in their confidence region zero")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	LABEL (U"", U"Formant frequency constraints")
-	REAL (U"Minimum F1 (Hz)", U"100.0")
-	REAL (U"Maximum F1 (Hz)", U"1200.0")
-	REAL (U"Minimum F2 (Hz)", U"0.0")
-	POSITIVE (U"Maximum F2 (Hz)", U"5000.0")
-	POSITIVE (U"Minimum F3 (Hz)", U"1000.0")
+	REALVAR (minimumF1, U"Minimum F1 (Hz)", U"100.0")
+	REALVAR (maximumF1, U"Maximum F1 (Hz)", U"1200.0")
+	REALVAR (minimumF2, U"Minimum F2 (Hz)", U"0.0")
+	POSITIVEVAR (maximumF2, U"Maximum F2 (Hz)", U"5000.0")
+	POSITIVEVAR (minimumF3, U"Minimum F3 (Hz)", U"1000.0")
 	OK
 DO
-	LOOP {
-		iam (Sound);
+	CONVERT_EACH (Sound)
 		double ceiling;
-		autoFormant formant = Sound_to_Formant_interval (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Window length"), GET_REAL (U"Time step"), GET_REAL (U"left Maximum frequency range"), 
-			GET_REAL (U"right Maximum frequency range"), GET_INTEGER (U"Number of frequency steps"),
-			GET_REAL (U"Pre-emphasis from"), GET_INTEGER (U"Number of formant tracks in model"), 
-			GET_INTEGER (U"Order of polynomials") + 1, GET_INTEGER (U"Weigh data") - 1, GET_REAL (U"Number of sigmas"),
-			GET_REAL (U"Parameter variance power"), 1,
-			GET_REAL (U"Minimum F1"), GET_REAL (U"Maximum F1"), GET_REAL (U"Minimum F2"), 
-			GET_REAL (U"Maximum F2"), GET_REAL (U"Minimum F3"), &ceiling);
-		praat_new (formant.move(), my name, U"_", Melder_fixed (ceiling, 0));
-	}
-END
-
-FORM (Sound_to_Formant_interval_constrained_robust, U"Sound: To Formant (interval, constrained, robust)", nullptr)
-	REAL (U"left Time range (s)", U"0.1")
-	REAL (U"right Time range (s)", U"0.15")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.0025")
-	POSITIVE (U"left Maximum frequency range (Hz)", U"4500.0")
-	POSITIVE (U"right Maximum frequency range (Hz)", U"6500.0")
-	NATURAL (U"Number of frequency steps", U"11")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	NATURAL (U"Number of formant tracks in model", U"4")
-	INTEGER (U"Order of polynomials", U"3")
-	OPTIONMENU (U"Weigh data", 2)
+		autoFormant result = Sound_to_Formant_interval (me, fromTime, toTime, windowLength, timeStep, fromFrequency,  toFrequency, numberOfFrequencySteps, preEmphasisFrequency, numberOfFormantTracks, order + 1, weighDataType - 1, numberOfSigmas, power, 1, minimumF1, maximumF1, minimumF2, maximumF2, minimumF3, & ceiling);
+	CONVERT_EACH_END (my name, U"_", Melder_fixed (ceiling, 0));
+}
+
+FORM (NEW_Sound_to_Formant_interval_constrained_robust, U"Sound: To Formant (interval, constrained, robust)", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.1")
+	REALVAR (toTime, U"right Time range (s)", U"0.15")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.0025")
+	POSITIVEVAR (fromFrequency, U"left Maximum frequency range (Hz)", U"4500.0")
+	POSITIVEVAR (toFrequency, U"right Maximum frequency range (Hz)", U"6500.0")
+	NATURALVAR (numberOfFrequencySteps, U"Number of frequency steps", U"11")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks in model", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"3")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Make parameters that include zero in their confidence region zero")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	LABEL (U"", U"Formant frequency constraints")
-	REAL (U"Minimum F1 (Hz)", U"100.0")
-	REAL (U"Maximum F1 (Hz)", U"1200.0")
-	REAL (U"Minimum F2 (Hz)", U"0.0")
-	POSITIVE (U"Maximum F2 (Hz)", U"5000.0")
-	POSITIVE (U"Minimum F3 (Hz)", U"1000.0")
+	REALVAR (minimumF1, U"Minimum F1 (Hz)", U"100.0")
+	REALVAR (maximumF1, U"Maximum F1 (Hz)", U"1200.0")
+	REALVAR (minimumF2, U"Minimum F2 (Hz)", U"0.0")
+	POSITIVEVAR (maximumF2, U"Maximum F2 (Hz)", U"5000.0")
+	POSITIVEVAR (minimumF3, U"Minimum F3 (Hz)", U"1000.0")
 	OK
 DO
-	LOOP {
-		iam (Sound);
+	CONVERT_EACH (Sound)
 		double ceiling;
-		autoFormant formant = Sound_to_Formant_interval_robust (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Window length"), GET_REAL (U"Time step"), GET_REAL (U"left Maximum frequency range"), 
-			GET_REAL (U"right Maximum frequency range"), GET_INTEGER (U"Number of frequency steps"),
-			GET_REAL (U"Pre-emphasis from"), GET_INTEGER (U"Number of formant tracks in model"), 
-			GET_INTEGER (U"Order of polynomials") + 1, GET_INTEGER (U"Weigh data") - 1, GET_REAL (U"Number of sigmas"),
-			GET_REAL (U"Parameter variance power"), 1,
-			GET_REAL (U"Minimum F1"), GET_REAL (U"Maximum F1"), GET_REAL (U"Minimum F2"), 
-			GET_REAL (U"Maximum F2"), GET_REAL (U"Minimum F3"), &ceiling);
-		praat_new (formant.move(), my name, U"_", Melder_fixed (ceiling, 0));
-	}
-END
-
-FORM (Sound_to_OptimalCeilingTier, U"", nullptr)
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.0025")
-	POSITIVE (U"left Maximum frequency range (Hz)", U"4500.0")
-	POSITIVE (U"right Maximum frequency range (Hz)", U"6500.0")
-	NATURAL (U"Number of frequency steps", U"11")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	REAL (U"Formant smoothing window (s)", U"0.05")
-	NATURAL (U"Number of formant tracks in model", U"4")
-	INTEGER (U"Order of polynomials", U"2")
-	OPTIONMENU (U"Weigh data", 2)
+		autoFormant result = Sound_to_Formant_interval_robust (me, fromTime, toTime, windowLength, timeStep, fromFrequency, fromFrequency, numberOfFrequencySteps, preEmphasisFrequency, numberOfFormantTracks, order + 1, weighDataType - 1, numberOfSigmas, power, 1, minimumF1, maximumF1, minimumF2, minimumF2, minimumF3, &ceiling);
+	CONVERT_EACH_END (my name, U"_", Melder_fixed (ceiling, 0))
+}
+
+FORM (NEW_Sound_to_OptimalCeilingTier, U"", nullptr) {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.0025")
+	POSITIVEVAR (fromFrequency, U"left Maximum frequency range (Hz)", U"4500.0")
+	POSITIVEVAR (toFrequency, U"right Maximum frequency range (Hz)", U"6500.0")
+	NATURALVAR (numberOfFrequencySteps, U"Number of frequency steps", U"11")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
+	REALVAR (smoothingWindow_s, U"Formant smoothing window (s)", U"0.05")
+	NATURALVAR (numberOfFormantTracks, U"Number of formant tracks in model", U"4")
+	INTEGERVAR (order, U"Order of polynomials", U"2")
+	OPTIONMENUVAR (weighDataType, U"Weigh data", 2)
 		OPTION (U"Equally")
 		OPTION (U"Bandwidth")
 		OPTION (U"Bandwidth / frequency")
 		OPTION (U"Sqrt bandwidth")
 	LABEL (U"", U"Make parameters that include zero in their confidence region zero")
-	REAL (U"Number of sigmas", U"1.0")
-	REAL (U"Parameter variance power", U"1.5")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	REALVAR (power, U"Parameter variance power", U"1.5")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoOptimalCeilingTier octier = Sound_to_OptimalCeilingTier (me, GET_REAL (U"Window length"), GET_REAL (U"Time step"), 
-			GET_REAL (U"left Maximum frequency range"), GET_REAL (U"right Maximum frequency range"), GET_INTEGER (U"Number of frequency steps"),
-			GET_REAL (U"Pre-emphasis from"), GET_REAL (U"Formant smoothing window"), GET_INTEGER (U"Number of formant tracks in model"),
-			GET_INTEGER (U"Order of polynomials") + 1, GET_INTEGER (U"Weigh data") - 1, GET_REAL (U"Number of sigmas"), GET_REAL (U"Parameter variance power"));
-		praat_new (octier.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoOptimalCeilingTier result = Sound_to_OptimalCeilingTier (me, windowLength, timeStep, fromFrequency, toFrequency, numberOfFrequencySteps, preEmphasisFrequency, smoothingWindow_s, numberOfFormantTracks, order + 1, weighDataType - 1, numberOfSigmas, power);
+	CONVERT_EACH_END (my name);
+}
 
-FORM (Table_to_DataModeler, U"", nullptr)
-	REAL (U"left X range", U"0.0")
-	REAL (U"right X range", U"0.0 (= auto)")
-	WORD (U"Column with X data", U"")
-	WORD (U"Column with Y data", U"")
-	WORD (U"Column with sigmas", U"")
-	OPTIONMENU (U"Model functions", 1)
-	OPTION (U"Legendre polynomials")
-	INTEGER (U"Maximum order", U"3")
-	OK
-DO
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column with X data"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column with Y data"));
-		long scolumn = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Column with sigmas"));
-		autoDataModeler thee = Table_to_DataModeler (me, GET_REAL (U"left X range"), GET_REAL (U"right X range"),
-			xcolumn, ycolumn, scolumn, GET_INTEGER (U"Maximum order") + 1, GET_INTEGER (U"Model functions"));
-		praat_new (thee.move(), my name);
-	}
-END
+FORM (NEW_Table_to_DataModeler, U"", nullptr) {
+	REALVAR (xmin, U"left X range", U"0.0")
+	REALVAR (xmax, U"right X range", U"0.0 (= auto)")
+	WORDVAR (columnWithX_string, U"Column with X data", U"")
+	WORDVAR (columnWithY_string, U"Column with Y data", U"")
+	WORDVAR (columnEithSigma_string, U"Column with sigmas", U"")
+	OPTIONMENUVAR (functionType, U"Model functions", 1)
+		OPTION (U"Legendre polynomials")
+	INTEGERVAR (maximumOrder, U"Maximum order", U"3")
+	OK
+DO
+	CONVERT_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, columnWithX_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, columnWithY_string);
+		long scolumn = Table_findColumnIndexFromColumnLabel (me, columnEithSigma_string);
+		autoDataModeler result = Table_to_DataModeler (me, xmin, xmax, xcolumn, ycolumn, scolumn, maximumOrder + 1, functionType);
+	CONVERT_EACH_END (my name)
+}
 
 void praat_DataModeler_init ();
 void praat_DataModeler_init () {
 	Thing_recognizeClassesByName (classDataModeler, classFormantModeler, classOptimalCeilingTier, classOptimalCeilingTierEditor, classPitchModeler, nullptr);
 
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple DataModeler...", U"Create ISpline...", praat_HIDDEN + praat_DEPTH_1, DO_DataModeler_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple DataModeler...", U"Create ISpline...", praat_HIDDEN + praat_DEPTH_1, NEW1_DataModeler_createSimple);
 
-	praat_addAction1 (classDataModeler, 0, U"Speckle...", 0, 0, DO_DataModeler_speckle);
-	praat_addAction1 (classDataModeler, 0, U"Draw estimated track...", 0, 0, DO_DataModeler_drawEstimatedTrack);
+	praat_addAction1 (classDataModeler, 0, U"Speckle...", 0, 0, GRAPHICS_DataModeler_speckle);
+	praat_addAction1 (classDataModeler, 0, U"Draw estimated track...", 0, 0, GRAPHICS_DataModeler_drawEstimatedTrack);
 
 	praat_addAction1 (classDataModeler, 1, U"Query -", 0, 0, 0);
-		praat_addAction1 (classDataModeler, 0, U"Get number of parameters", 0, 1, DO_DataModeler_getNumberOfParameters);
-		praat_addAction1 (classDataModeler, 0, U"Get number of fixed parameters", 0, 1, DO_DataModeler_getNumberOfFixedParameters);
-		praat_addAction1 (classDataModeler, 0, U"Get parameter value...", 0, 1, DO_DataModeler_getParameterValue);
-		praat_addAction1 (classDataModeler, 0, U"Get parameter status...", 0, 1, DO_DataModeler_getParameterStatus);
-		praat_addAction1 (classDataModeler, 0, U"Get parameter standard deviation...", 0, 1, DO_DataModeler_getParameterStandardDeviation);
-		praat_addAction1 (classDataModeler, 0, U"Get variance of parameters...", 0, 1, DO_DataModeler_getVarianceOfParameters);
+		praat_addAction1 (classDataModeler, 0, U"Get number of parameters", 0, 1, INTEGER_DataModeler_getNumberOfParameters);
+		praat_addAction1 (classDataModeler, 0, U"Get number of fixed parameters", 0, 1, INTEGER_DataModeler_getNumberOfFixedParameters);
+		praat_addAction1 (classDataModeler, 0, U"Get parameter value...", 0, 1, REAL_DataModeler_getParameterValue);
+		praat_addAction1 (classDataModeler, 0, U"Get parameter status...", 0, 1, INFO_DataModeler_getParameterStatus);
+		praat_addAction1 (classDataModeler, 0, U"Get parameter standard deviation...", 0, 1, REAL_DataModeler_getParameterStandardDeviation);
+		praat_addAction1 (classDataModeler, 0, U"Get variance of parameters...", 0, 1, REAL_DataModeler_getVarianceOfParameters);
 		praat_addAction1 (classDataModeler, 1, U"-- get data points info --", 0, 1, 0);
-		praat_addAction1 (classDataModeler, 0, U"Get model value at x...", 0, 1, DO_DataModeler_getModelValueAtX);
-		praat_addAction1 (classDataModeler, 0, U"Get number of data points", 0, 1, DO_DataModeler_getNumberOfDataPoints);
-		praat_addAction1 (classDataModeler, 0, U"Get number of invalid data points", 0, 1, DO_DataModeler_getNumberOfInvalidDataPoints);
-		praat_addAction1 (classDataModeler, 0, U"Get data point value...", 0, 1, DO_DataModeler_getDataPointValue);
-		praat_addAction1 (classDataModeler, 0, U"Get data point sigma...", 0, 1, DO_DataModeler_getDataPointSigma);
-		praat_addAction1 (classDataModeler, 0, U"Get data point status...", 0, 1, DO_DataModeler_getDataPointStatus);
+		praat_addAction1 (classDataModeler, 0, U"Get model value at x...", 0, 1, REAL_DataModeler_getModelValueAtX);
+		praat_addAction1 (classDataModeler, 0, U"Get number of data points", 0, 1, INTEGER_DataModeler_getNumberOfDataPoints);
+		praat_addAction1 (classDataModeler, 0, U"Get number of invalid data points", 0, 1, INTEGER_DataModeler_getNumberOfInvalidDataPoints);
+		praat_addAction1 (classDataModeler, 0, U"Get data point y value...", 0, 1, REAL_DataModeler_getDataPointYValue);
+		praat_addAction1 (classDataModeler, 0, U"Get data point x value...", 0, 1, REAL_DataModeler_getDataPointXValue);
+		praat_addAction1 (classDataModeler, 0, U"Get data point y sigma...", 0, 1, REAL_DataModeler_getDataPointYSigma);
+		praat_addAction1 (classDataModeler, 0, U"Get data point status...", 0, 1, INFO_DataModeler_getDataPointStatus);
 		praat_addAction1 (classDataModeler, 1, U"-- get statistics info --", 0, 1, 0);
 		
-		praat_addAction1 (classDataModeler, 0, U"Get residual sum of squares", 0, 1, DO_DataModeler_getResidualSumOfSquares);
-		praat_addAction1 (classDataModeler, 0, U"Get data standard deviation", 0, 1, DO_DataModeler_getStandardDeviation);
-		praat_addAction1 (classDataModeler, 0, U"Get coefficient of determination", 0, 1, DO_DataModeler_getCoefficientOfDetermination);
-		praat_addAction1 (classDataModeler, 0, U"Report chi squared...", 0, 1, DO_DataModeler_reportChiSquared);
-		praat_addAction1 (classDataModeler, 0, U"Get degrees of freedom", 0, 1, DO_DataModeler_getDegreesOfFreedom);
+		praat_addAction1 (classDataModeler, 0, U"Get residual sum of squares", 0, 1, REAL_DataModeler_getResidualSumOfSquares);
+		praat_addAction1 (classDataModeler, 0, U"Get data standard deviation", 0, 1, REAL_DataModeler_getStandardDeviation);
+		praat_addAction1 (classDataModeler, 0, U"Get coefficient of determination", 0, 1, REAL_DataModeler_getCoefficientOfDetermination);
+		praat_addAction1 (classDataModeler, 0, U"Report chi squared...", 0, 1, INFO_DataModeler_reportChiSquared);
+		praat_addAction1 (classDataModeler, 0, U"Get degrees of freedom", 0, 1, REAL_DataModeler_getDegreesOfFreedom);
 
 	praat_addAction1 (classDataModeler, 1, U"Modify -", 0, 0, 0);
-		praat_addAction1 (classDataModeler, 0, U"Set data weighing...", 0, 1, DO_DataModeler_setDataWeighing);
-		praat_addAction1 (classDataModeler, 0, U"Set tolerance...", 0, 1, DO_DataModeler_setTolerance);
+		praat_addAction1 (classDataModeler, 0, U"Set data weighing...", 0, 1, MODIFY_DataModeler_setDataWeighing);
+		praat_addAction1 (classDataModeler, 0, U"Set tolerance...", 0, 1, MODIFY_DataModeler_setTolerance);
 		praat_addAction1 (classDataModeler, 1, U"-- set parameter values --", 0, 1, 0);
-		praat_addAction1 (classDataModeler, 0, U"Set parameter value...", 0, 1, DO_DataModeler_setParameterValue);
-		praat_addAction1 (classDataModeler, 0, U"Set parameter free...", 0, 1, DO_DataModeler_setParameterFree);
-		praat_addAction1 (classDataModeler, 0, U"Set parameter values to zero...", 0, 1, DO_DataModeler_setParameterValuesToZero);
+		praat_addAction1 (classDataModeler, 0, U"Set parameter value...", 0, 1, MODIFY_DataModeler_setParameterValue);
+		praat_addAction1 (classDataModeler, 0, U"Set parameter free...", 0, 1, MODIFY_DataModeler_setParameterFree);
+		praat_addAction1 (classDataModeler, 0, U"Set parameter values to zero...", 0, 1, MODIFY_DataModeler_setParameterValuesToZero);
 		praat_addAction1 (classDataModeler, 1, U"-- set data values --", 0, 1, 0);
-		praat_addAction1 (classDataModeler, 0, U"Set data point status...", 0, 1, DO_DataModeler_setDataPointStatus);
-		praat_addAction1 (classDataModeler, 0, U"Set data point value...", 0, 1, DO_DataModeler_setDataPointValue);
-		praat_addAction1 (classDataModeler, 0, U"Set data point sigma...", 0, 1, DO_DataModeler_setDataPointSigma);
+		praat_addAction1 (classDataModeler, 0, U"Set data point y value...", 0, 1, MODIFY_DataModeler_setDataPointYValue);
+		praat_addAction1 (classDataModeler, 0, U"Set data point x value...", 0, 1, MODIFY_DataModeler_setDataPointXValue);
+		praat_addAction1 (classDataModeler, 0, U"Set data point y sigma...", 0, 1, MODIFY_DataModeler_setDataPointYSigma);
+		praat_addAction1 (classDataModeler, 0, U"Set data point status...", 0, 1, MODIFY_DataModeler_setDataPointStatus);
 		
-	praat_addAction1 (classDataModeler, 0, U"Fit model", 0, 0, DO_DataModeler_fitModel);
+	praat_addAction1 (classDataModeler, 0, U"Fit model", 0, 0, MODIFY_DataModeler_fitModel);
 	
-	praat_addAction1 (classDataModeler, 0, U"To Covariance (parameters)...", 0, 0, DO_DataModeler_to_Covariance_parameters);
-	praat_addAction1 (classDataModeler, 0, U"To Table (z-scores)...", 0, 0, DO_DataModeler_to_Table_zscores);
+	praat_addAction1 (classDataModeler, 0, U"To Covariance (parameters)", 0, 0, NEW_DataModeler_to_Covariance_parameters);
+	praat_addAction1 (classDataModeler, 0, U"To Table (z-scores)...", 0, 0, NEW_DataModeler_to_Table_zscores);
 
-	praat_addAction1 (classFormant, 0, U"To FormantModeler...", U"To LPC...", praat_HIDDEN, DO_Formant_to_FormantModeler);
-	praat_addAction1 (classFormant, 0, U"Extract smoothest part...", 0, praat_HIDDEN, DO_Formants_extractSmoothestPart);
-	praat_addAction1 (classFormant, 0, U"Extract smoothest part (constrained)...", 0, praat_HIDDEN, DO_Formants_extractSmoothestPart_constrained);
+	praat_addAction1 (classFormant, 0, U"To FormantModeler...", U"To LPC...", praat_HIDDEN, NEW_Formant_to_FormantModeler);
+	praat_addAction1 (classFormant, 0, U"Extract smoothest part...", 0, praat_HIDDEN, NEW1_Formants_extractSmoothestPart);
+	praat_addAction1 (classFormant, 0, U"Extract smoothest part (constrained)...", 0, praat_HIDDEN, NEW1_Formants_extractSmoothestPart_constrained);
 
 	praat_addAction1 (classFormantModeler, 0, U"Draw -", 0, 0, 0);
-	praat_addAction1 (classFormantModeler, 0, U"Speckle...", 0, 1, DO_FormantModeler_speckle);
-	praat_addAction1 (classFormantModeler, 0, U"Draw tracks...", 0, 1, DO_FormantModeler_drawTracks);
-	praat_addAction1 (classFormantModeler, 0, U"Draw estimated tracks...", 0, 1, DO_FormantModeler_drawEstimatedTracks);
-	praat_addAction1 (classFormantModeler, 0, U"Draw variances of shifted tracks...", 0, 1, DO_FormantModeler_drawVariancesOfShiftedTracks);
-	praat_addAction1 (classFormantModeler, 0, U"Draw outliers marked...", 0, 1, DO_FormantModeler_drawOutliersMarked);
-	praat_addAction1 (classFormantModeler, 0, U"Draw cumulative chisq scores...", 0, 1, DO_FormantModeler_drawCumulativeChiScores);
-	praat_addAction1 (classFormantModeler, 0, U"Normal probability plot...", 0, 1, DO_FormantModeler_normalProbabilityPlot);
-	praat_addAction1 (classFormantModeler, 0, U"Draw basis function...", 0, 1, DO_FormantModeler_drawBasisFunction);
+	praat_addAction1 (classFormantModeler, 0, U"Speckle...", 0, 1, GRAPHICS_FormantModeler_speckle);
+	praat_addAction1 (classFormantModeler, 0, U"Draw tracks...", 0, 1, GRAPHICS_FormantModeler_drawTracks);
+	praat_addAction1 (classFormantModeler, 0, U"Draw estimated tracks...", 0, 1, GRAPHICS_FormantModeler_drawEstimatedTracks);
+	praat_addAction1 (classFormantModeler, 0, U"Draw variances of shifted tracks...", 0, 1, GRAPHICS_FormantModeler_drawVariancesOfShiftedTracks);
+	praat_addAction1 (classFormantModeler, 0, U"Draw outliers marked...", 0, 1, GRAPHICS_FormantModeler_drawOutliersMarked);
+	praat_addAction1 (classFormantModeler, 0, U"Draw cumulative chisq scores...", 0, 1, GRAPHICS_FormantModeler_drawCumulativeChiScores);
+	praat_addAction1 (classFormantModeler, 0, U"Normal probability plot...", 0, 1, GRAPHICS_FormantModeler_normalProbabilityPlot);
+	praat_addAction1 (classFormantModeler, 0, U"Draw basis function...", 0, 1, GRAPHICS_FormantModeler_drawBasisFunction);
 	
 	praat_addAction1 (classFormantModeler, 1, U"Query -", 0, 0, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Get number of tracks", 0, 1, DO_FormantModeler_getNumberOfTracks);
+		praat_addAction1 (classFormantModeler, 0, U"Get number of tracks", 0, 1, INTEGER_FormantModeler_getNumberOfTracks);
 		praat_addAction1 (classFormantModeler, 1, U"-- get parameter info --", 0, 1, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Get number of parameters...", 0, 1, DO_FormantModeler_getNumberOfParameters);
-		praat_addAction1 (classFormantModeler, 0, U"Get number of fixed parameters...", 0, 1, DO_FormantModeler_getNumberOfFixedParameters);
-		praat_addAction1 (classFormantModeler, 0, U"Get parameter value...", 0, 1, DO_FormantModeler_getParameterValue);
-		praat_addAction1 (classFormantModeler, 0, U"Get parameter status...", 0, 1, DO_FormantModeler_getParameterStatus);
-		praat_addAction1 (classFormantModeler, 0, U"Get parameter standard deviation...", 0, 1, DO_FormantModeler_getParameterStandardDeviation);
-		praat_addAction1 (classFormantModeler, 0, U"Get variance of parameters...", 0, 1, DO_FormantModeler_getVarianceOfParameters);
+		praat_addAction1 (classFormantModeler, 0, U"Get number of parameters...", 0, 1, INTEGER_FormantModeler_getNumberOfParameters);
+		praat_addAction1 (classFormantModeler, 0, U"Get number of fixed parameters...", 0, 1, INTEGER_FormantModeler_getNumberOfFixedParameters);
+		praat_addAction1 (classFormantModeler, 0, U"Get parameter value...", 0, 1, REAL_FormantModeler_getParameterValue);
+		praat_addAction1 (classFormantModeler, 0, U"Get parameter status...", 0, 1, INFO_FormantModeler_getParameterStatus);
+		praat_addAction1 (classFormantModeler, 0, U"Get parameter standard deviation...", 0, 1, REAL_FormantModeler_getParameterStandardDeviation);
+		praat_addAction1 (classFormantModeler, 0, U"Get variance of parameters...", 0, 1, REAL_FormantModeler_getVarianceOfParameters);
 		praat_addAction1 (classFormantModeler, 1, U"-- get data points info --", 0, 1, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Get number of data points", 0, 1, DO_FormantModeler_getNumberOfDataPoints);
-		praat_addAction1 (classFormantModeler, 0, U"Get number of invalid data points...", 0, praat_DEPTH_1 + praat_HIDDEN, DO_FormantModeler_getNumberOfInvalidDataPoints);
-		praat_addAction1 (classFormantModeler, 0, U"Get model value at time...", 0, 1, DO_FormantModeler_getModelValueAtTime);
-		praat_addAction1 (classFormantModeler, 0, U"Get data point value...", 0, 1, DO_FormantModeler_getDataPointValue);
-		praat_addAction1 (classFormantModeler, 0, U"Get data point sigma...", 0, 1, DO_FormantModeler_getDataPointSigma);
-		praat_addAction1 (classFormantModeler, 0, U"Get data point status...", 0, 1, DO_FormantModeler_getDataPointStatus);
+		praat_addAction1 (classFormantModeler, 0, U"Get number of data points", 0, 1, INTEGER_FormantModeler_getNumberOfDataPoints);
+		praat_addAction1 (classFormantModeler, 0, U"Get number of invalid data points...", 0, praat_DEPTH_1 + praat_HIDDEN, INTEGER_FormantModeler_getNumberOfInvalidDataPoints);
+		praat_addAction1 (classFormantModeler, 0, U"Get model value at time...", 0, 1, REAL_FormantModeler_getModelValueAtTime);
+		praat_addAction1 (classFormantModeler, 0, U"Get data point value...", 0, 1, REAL_FormantModeler_getDataPointValue);
+		praat_addAction1 (classFormantModeler, 0, U"Get data point sigma...", 0, 1, REAL_FormantModeler_getDataPointSigma);
+		praat_addAction1 (classFormantModeler, 0, U"Get data point status...", 0, 1, INFO_FormantModeler_getDataPointStatus);
 
 		praat_addAction1 (classFormantModeler, 1, U"-- get statistics info --", 0, 1, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Get residual sum of squares...", 0, 1, DO_FormantModeler_getResidualSumOfSquares);
-		praat_addAction1 (classFormantModeler, 0, U"Get formant standard deviation...", 0, 1, DO_FormantModeler_getStandardDeviation);
-		praat_addAction1 (classFormantModeler, 0, U"Get coefficient of determination...", 0, 1, DO_FormantModeler_getCoefficientOfDetermination);
-		praat_addAction1 (classFormantModeler, 0, U"Report chi squared...", 0, 1, DO_FormantModeler_reportChiSquared);
-		praat_addAction1 (classFormantModeler, 0, U"Get degrees of freedom...", 0, 1, DO_FormantModeler_getDegreesOfFreedom);
-		praat_addAction1 (classFormantModeler, 0, U"Get smoothness value...", 0, 1, DO_FormantModeler_getSmoothnessValue);
-		praat_addAction1 (classFormantModeler, 0, U"Get average distance between tracks...", 0, 1, DO_FormantModeler_getAverageDistanceBetweenTracks);
-		praat_addAction1 (classFormantModeler, 0, U"Get formants constraints factor...", 0, 1, DO_FormantModeler_getFormantsConstraintsFactor);
+		praat_addAction1 (classFormantModeler, 0, U"Get residual sum of squares...", 0, 1, REAL_FormantModeler_getResidualSumOfSquares);
+		praat_addAction1 (classFormantModeler, 0, U"Get formant standard deviation...", 0, 1, REAL_FormantModeler_getStandardDeviation);
+		praat_addAction1 (classFormantModeler, 0, U"Get coefficient of determination...", 0, 1, REAL_FormantModeler_getCoefficientOfDetermination);
+		praat_addAction1 (classFormantModeler, 0, U"Report chi squared...", 0, 1, INFO_FormantModeler_reportChiSquared);
+		praat_addAction1 (classFormantModeler, 0, U"Get degrees of freedom...", 0, 1, REAL_FormantModeler_getDegreesOfFreedom);
+		praat_addAction1 (classFormantModeler, 0, U"Get smoothness value...", 0, 1, REAL_FormantModeler_getSmoothnessValue);
+		praat_addAction1 (classFormantModeler, 0, U"Get average distance between tracks...", 0, 1, REAL_FormantModeler_getAverageDistanceBetweenTracks);
+		praat_addAction1 (classFormantModeler, 0, U"Get formants constraints factor...", 0, 1, REAL_FormantModeler_getFormantsConstraintsFactor);
 
 	praat_addAction1 (classFormantModeler, 1, U"Modify -", 0, 0, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Set data weighing...", 0, 1, DO_FormantModeler_setDataWeighing);
-		praat_addAction1 (classFormantModeler, 0, U"Set tolerance...", 0, 1, DO_FormantModeler_setTolerance);
+		praat_addAction1 (classFormantModeler, 0, U"Set data weighing...", 0, 1, MODIFY_FormantModeler_setDataWeighing);
+		praat_addAction1 (classFormantModeler, 0, U"Set tolerance...", 0, 1, MODIFY_FormantModeler_setTolerance);
 		praat_addAction1 (classFormantModeler, 1, U"-- set parameter values --", 0, 1, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Set parameter value fixed...", 0, 1, DO_FormantModeler_setParameterValueFixed);
-		praat_addAction1 (classFormantModeler, 0, U"Set parameter free...", 0, 1, DO_FormantModeler_setParameterFree);
-		praat_addAction1 (classFormantModeler, 0, U"Set parameter values to zero...", 0, 1, DO_FormantModeler_setParameterValuesToZero);
+		praat_addAction1 (classFormantModeler, 0, U"Set parameter value fixed...", 0, 1, MODIFY_FormantModeler_setParameterValueFixed);
+		praat_addAction1 (classFormantModeler, 0, U"Set parameter free...", 0, 1, MODIFY_FormantModeler_setParameterFree);
+		praat_addAction1 (classFormantModeler, 0, U"Set parameter values to zero...", 0, 1, MODIFY_FormantModeler_setParameterValuesToZero);
 		praat_addAction1 (classFormantModeler, 1, U"-- set data points --", 0, 1, 0);
-		praat_addAction1 (classFormantModeler, 0, U"Set data point value...", 0, 1, DO_FormantModeler_setDataPointValue);
-		praat_addAction1 (classFormantModeler, 0, U"Set data point sigma...", 0, 1, DO_FormantModeler_setDataPointSigma);
-		praat_addAction1 (classFormantModeler, 0, U"Set data point status...", 0, 1, DO_FormantModeler_setDataPointStatus);
+		praat_addAction1 (classFormantModeler, 0, U"Set data point value...", 0, 1, MODIFY_FormantModeler_setDataPointValue);
+		praat_addAction1 (classFormantModeler, 0, U"Set data point sigma...", 0, 1, MODIFY_FormantModeler_setDataPointSigma);
+		praat_addAction1 (classFormantModeler, 0, U"Set data point status...", 0, 1, MODIFY_FormantModeler_setDataPointStatus);
 			
-	praat_addAction1 (classFormantModeler, 0, U"Fit model", 0, 0, DO_FormantModeler_fitModel);
+	praat_addAction1 (classFormantModeler, 0, U"Fit model", 0, 0, MODIFY_FormantModeler_fitModel);
 	
 	
-	praat_addAction1 (classFormantModeler, 0, U"To Covariance (parameters)...", 0, 0, DO_FormantModeler_to_Covariance_parameters);
-	praat_addAction1 (classFormantModeler, 0, U"To Table (z-scores)...", 0, 0, DO_FormantModeler_to_Table_zscores);
-	praat_addAction1 (classFormantModeler, 0, U"To FormantModeler (process outliers)...", 0, 0, DO_FormantModeler_processOutliers);
-	praat_addAction1 (classFormantModeler, 0, U"Extract DataModeler...", 0, 0, DO_FormantModeler_extractDataModeler);
+	praat_addAction1 (classFormantModeler, 0, U"To Covariance (parameters)...", 0, 0, NEW_FormantModeler_to_Covariance_parameters);
+	praat_addAction1 (classFormantModeler, 0, U"To Table (z-scores)...", 0, 0, NEW_FormantModeler_to_Table_zscores);
+	praat_addAction1 (classFormantModeler, 0, U"To FormantModeler (process outliers)...", 0, 0, NEW_FormantModeler_processOutliers);
+	praat_addAction1 (classFormantModeler, 0, U"Extract DataModeler...", 0, 0, NEW_FormantModeler_extractDataModeler);
 
-	praat_addAction1 (classOptimalCeilingTier, 1, U"View & Edit", 0, praat_ATTRACTIVE, DO_OptimalCeilingTier_edit);
+	praat_addAction1 (classOptimalCeilingTier, 1, U"View & Edit", 0, praat_ATTRACTIVE | praat_NO_API, WINDOW_OptimalCeilingTier_edit);
 	
-	praat_addAction1 (classPitch, 0, U"To PitchModeler...", U"To PointProcess", praat_HIDDEN, DO_Pitch_to_PitchModeler);
+	praat_addAction1 (classPitch, 0, U"To PitchModeler...", U"To PointProcess", praat_HIDDEN, NEW_Pitch_to_PitchModeler);
 
-	praat_addAction1 (classPitchModeler, 0, U"Draw...", 0, 0, DO_PitchModeler_draw);
+	praat_addAction1 (classPitchModeler, 0, U"Draw...", 0, 0, GRAPHICS_PitchModeler_draw);
 
-	praat_addAction1 (classSound, 0, U"Get optimal formant ceiling...", U"Get intensity (dB)", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_getOptimalFormantCeiling);
-	praat_addAction1 (classSound, 0, U"To Formant (interval)...", U"To Formant (robust)...", praat_DEPTH_2 | praat_HIDDEN, DO_Sound_to_Formant_interval);
+	praat_addAction1 (classSound, 0, U"Get optimal formant ceiling...", U"Get intensity (dB)", praat_DEPTH_1 | praat_HIDDEN, REAL_Sound_getOptimalFormantCeiling);
+	praat_addAction1 (classSound, 0, U"To Formant (interval)...", U"To Formant (robust)...", praat_DEPTH_2 | praat_HIDDEN, NEW_Sound_to_Formant_interval);
 	praat_addAction1 (classSound, 0, U"To Formant (interval, constrained)...", U"To Formant (interval)...",
-		praat_DEPTH_2 | praat_HIDDEN, DO_Sound_to_Formant_interval_constrained);
+		praat_DEPTH_2 | praat_HIDDEN, NEW_Sound_to_Formant_interval_constrained);
 
-	praat_addAction1 (classSound, 0, U"To OptimalCeilingTier...", U"To Formant (interval, constrained)...", praat_DEPTH_2 | praat_HIDDEN, DO_Sound_to_OptimalCeilingTier);
+	praat_addAction1 (classSound, 0, U"To OptimalCeilingTier...", U"To Formant (interval, constrained)...", praat_DEPTH_2 | praat_HIDDEN, NEW_Sound_to_OptimalCeilingTier);
 	
 	praat_addAction1 (classSound, 0, U"To Formant (interval, constrained, robust)...", U"To Formant (interval, constrained)...", 
-		praat_DEPTH_2 | praat_HIDDEN, DO_Sound_to_Formant_interval_constrained_robust);
-	praat_addAction1 (classTable, 0, U"To DataModeler...", U"To logistic regression...", praat_DEPTH_1 + praat_HIDDEN, DO_Table_to_DataModeler);
+		praat_DEPTH_2 | praat_HIDDEN, NEW_Sound_to_Formant_interval_constrained_robust);
+	praat_addAction1 (classTable, 0, U"To DataModeler...", U"To logistic regression...", praat_DEPTH_1 + praat_HIDDEN, NEW_Table_to_DataModeler);
 }
 
-/* End of file praat_DataModeler_init.cpp */
+/* End of file praat_DataModeler_init.cpp 1566*/
diff --git a/dwtools/praat_David_init.cpp b/dwtools/praat_David_init.cpp
index 7b5294f..b37462e 100644
--- a/dwtools/praat_David_init.cpp
+++ b/dwtools/praat_David_init.cpp
@@ -63,7 +63,6 @@
  djmw 20120813 Latest modification.
 */
 
-#include "praat.h"
 #include "NUM2.h"
 #include "NUMlapack.h"
 #include "NUMmachar.h"
@@ -132,6 +131,11 @@
 #include "TableOfReal_and_SVD.h"
 #include "VowelEditor.h"
 
+#include "praat_TimeFrameSampled.h"
+#include "praat_Matrix.h"
+#include "praat_TableOfReal.h"
+#include "praat_uvafon.h"
+
 #undef iam
 #define iam iam_LOOP
 
@@ -140,200 +144,182 @@ static const char32 *DRAW_BUTTON    = U"Draw -";
 static const char32 *MODIFY_BUTTON  = U"Modify -";
 static const char32 *EXTRACT_BUTTON = U"Extract -";
 
-void praat_TimeFunction_query_init (ClassInfo klas);
-void praat_TimeFrameSampled_query_init (ClassInfo klas);
-void praat_TableOfReal_init (ClassInfo klas);
 void praat_TableOfReal_init2 (ClassInfo klas);
 void praat_SSCP_as_TableOfReal_init (ClassInfo klas);
 
 void praat_CC_init (ClassInfo klas);
-void DTW_constraints_addCommonFields (UiForm dia);
-void DTW_constraints_getCommonFields (UiForm dia, int *begin, int *end, int *slope);
 void praat_BandFilterSpectrogram_query_init (ClassInfo klas);
-int praat_Fon_formula (UiForm dia, Interpreter interpreter);
 void praat_EditDistanceTable_as_TableOfReal_init (ClassInfo klas);
 
+#define DTW_constraints_addCommonFields(matchStart,matchEnd,slopeConstraint) \
+	LABEL (U"", U"Boundary conditions") \
+	BOOLEANVAR (matchStart, U"Match begin positions", false) \
+	BOOLEANVAR (matchEnd, U"Match end positions", false) \
+	RADIOVAR (slopeConstraint, U"Slope constraint", 1) \
+		RADIOBUTTON (U"no restriction") \
+		RADIOBUTTON (U"1/3 < slope < 3") \
+		RADIOBUTTON (U"1/2 < slope < 2") \
+		RADIOBUTTON (U"2/3 < slope < 3/2")
+
 #undef INCLUDE_DTW_SLOPES
 
+#define FIND_ONE_AND_GENERIC(klas1,klas2) \
+	klas1 me = nullptr; klas2 you = nullptr; \
+	LOOP { if (CLASS == class##klas1) me = (klas1) OBJECT; \
+	else if (Thing_isSubclass (CLASS, class##klas2)) { you = (klas2) OBJECT; } } \
+	Melder_assert (me && you);
+
+#define CONVERT_ONE_AND_GENERIC(klas1,klas2) FIND_ONE_AND_GENERIC(klas1,klas2)
+#define CONVERT_ONE_AND_GENERIC_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+	
 /********************** Activation *******************************************/
 
-FORM (ActivationList_formula, U"ActivationList: Formula", nullptr)
+FORM (MODIFY_ActivationList_formula, U"ActivationList: Formula", nullptr) {
 	LABEL (U"label", U"for col := 1 to ncol do { self [row, col] := `formula' ; x := x + dx } y := y + dy }}")
-	TEXTFIELD (U"formula", U"self")
+	TEXTVAR (formula, U"formula", U"self")
 	OK
 DO
-	praat_Fon_formula (dia, interpreter);
-END
+	MODIFY_EACH (ActivationList)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_END
+}
 
-DIRECT (ActivationList_to_Matrix)
-	LOOP {
-		iam (ActivationList);
-		autoMatrix thee = ActivationList_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_ActivationList_to_Matrix) {
+	CONVERT_EACH (ActivationList)
+		autoMatrix result = ActivationList_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (ActivationList_to_PatternList)
-	LOOP {
-		iam (ActivationList);
-		autoPatternList thee = ActivationList_to_PatternList (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_ActivationList_to_PatternList) {
+	CONVERT_EACH (ActivationList)
+		autoPatternList result = ActivationList_to_PatternList (me);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** BandFilterSpectrogram *******************************************/
 
-FORM (BandFilterSpectrogram_drawFrequencyScale, U"", U"")
-	REAL (U"left Horizontal frequency range (Hz)", U"0.0")
-	REAL (U"right Horizontal frequency range (Hz)", U"0.0")
-	REAL (U"left Vertical frequency range (mel)", U"0.0")
-	REAL (U"right Vertical frequency range (mel)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_BandFilterSpectrogram_drawFrequencyScale, U"", U"") {
+	REALVAR (fromFrequency, U"left Horizontal frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Horizontal frequency range (Hz)", U"0.0")
+	REALVAR (yFromFrequency, U"left Vertical frequency range (mel)", U"0.0")
+	REALVAR (yToFrequency, U"right Vertical frequency range (mel)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (BandFilterSpectrogram);
-		BandFilterSpectrogram_drawFrequencyScale (me, GRAPHICS, GET_REAL (U"left Horizontal frequency range"), 
-			GET_REAL (U"right Horizontal frequency range"),
-			GET_REAL (U"left Vertical frequency range"), GET_REAL (U"right Vertical frequency range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (BandFilterSpectrogram)
+		BandFilterSpectrogram_drawFrequencyScale (me, GRAPHICS, fromFrequency, toFrequency, yFromFrequency, yToFrequency, garnish);
+	GRAPHICS_EACH_END
+}
 
 /********************** BarkFilter *******************************************/
 
-DIRECT (BarkFilter_help)
-	Melder_help (U"BarkFilter");
-END
+DIRECT (HELP_BarkFilter_help) {
+	HELP (U"BarkFilter")
+}
 
-DIRECT (BarkSpectrogram_help)
-	Melder_help (U"BarkSpectrogram");
-END
+DIRECT (HELP_BarkSpectrogram_help) {
+	HELP (U"BarkSpectrogram")
+}
 
-FORM (BarkFilter_drawSpectrum, U"BarkFilter: Draw spectrum (slice)", U"FilterBank: Draw spectrum (slice)...")
-	POSITIVE (U"Time (s)", U"0.1")
-	REAL (U"left Frequency range (Bark)", U"0.0")
-	REAL (U"right Frequency range (Bark)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_BarkFilter_drawSpectrum, U"BarkFilter: Draw spectrum (slice)", U"FilterBank: Draw spectrum (slice)...") {
+	REALVAR (time, U"Time (s)", U"0.1")
+	REALVAR (fromFrequency, U"left Frequency range (Bark)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Bark)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (BarkFilter);
-		FilterBank_drawTimeSlice (me, GRAPHICS, GET_REAL (U"Time"), GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), U"Barks", GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (BarkFilter)
+		FilterBank_drawTimeSlice (me, GRAPHICS, time, fromFrequency, toFrequency, fromAmplitude, toAmplitude, U"Barks", garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (BarkFilter_drawSekeyHansonFilterFunctions, U"BarkFilter: Draw filter functions", U"FilterBank: Draw filter functions...")
-	INTEGER (U"left Filter range", U"0")
-	INTEGER (U"right Filter range", U"0")
-	RADIO (U"Frequency scale", 1)
+FORM (GRAPHICS_BarkFilter_drawSekeyHansonFilterFunctions, U"BarkFilter: Draw filter functions", U"FilterBank: Draw filter functions...") {
+	INTEGERVAR (fromFilter, U"left Filter range", U"0")
+	INTEGERVAR (toFilter, U"right Filter range", U"0")
+	RADIOVAR (frequencyScale, U"Frequency scale", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
 		RADIOBUTTON (U"mel")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	BOOLEAN (U"Amplitude scale in dB", true)
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	BOOLEANVAR (amplitudeScale_dB, U"Amplitude scale in dB", true)
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (BarkFilter);
-		BarkFilter_drawSekeyHansonFilterFunctions (me, GRAPHICS, GET_INTEGER (U"Frequency scale"),
-			GET_INTEGER (U"left Filter range"), GET_INTEGER (U"right Filter range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Amplitude scale in dB"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (BarkFilter)
+		BarkFilter_drawSekeyHansonFilterFunctions (me, GRAPHICS, frequencyScale, fromFilter, toFilter, fromFrequency, toFrequency, amplitudeScale_dB, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (BarkSpectrogram_drawSekeyHansonAuditoryFilters, U"BarkSpectrogram: Draw Sekey-Hanson auditory filters", U"BarkSpectrogram: Draw Sekey-Hanson auditory filters...")
-	INTEGER (U"left Filter range", U"0")
-	INTEGER (U"right Filter range", U"0")
-	RADIO (U"Frequency scale", 2)
+FORM (GRAPHICS_BarkSpectrogram_drawSekeyHansonAuditoryFilters, U"BarkSpectrogram: Draw Sekey-Hanson auditory filters", U"BarkSpectrogram: Draw Sekey-Hanson auditory filters...") {
+	INTEGERVAR (fromFilter, U"left Filter range", U"0")
+	INTEGERVAR (toFilter, U"right Filter range", U"0")
+	RADIOVAR (frequencyScale, U"Frequency scale", 2)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	BOOLEAN (U"Amplitude scale in dB", 1)
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (BarkSpectrogram);
-		bool xIsHertz = ( GET_INTEGER (U"Frequency scale") == 1 );
-		BarkSpectrogram_drawSekeyHansonFilterFunctions (me, GRAPHICS, xIsHertz,
-			GET_INTEGER (U"left Filter range"), GET_INTEGER (U"right Filter range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Amplitude scale in dB"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	BOOLEANVAR (amplitudeScale_dB, U"Amplitude scale in dB", 1)
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (BarkSpectrogram)
+		bool xIsHertz = (frequencyScale == 1);
+		BarkSpectrogram_drawSekeyHansonFilterFunctions (me, GRAPHICS, xIsHertz, fromFilter, toFilter, fromFrequency, toFrequency, amplitudeScale_dB, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (BarkFilter_paint, U"FilterBank: Paint", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range (bark)", U"0.0")
-	REAL (U"right Frequency range (bark)", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", false)
+FORM (GRAPHICS_BarkFilter_paint, U"FilterBank: Paint", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (bark)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (bark)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", false)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		FilterBank_paint ((FilterBank) me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-		GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (BarkFilter)
+		FilterBank_paint ((FilterBank) me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (BarkFilter_to_BarkSpectrogram)
-	LOOP {
-		iam (BarkFilter);
-		praat_new (BarkFilter_to_BarkSpectrogram (me), my name);
-	}
-END
+DIRECT (NEW_BarkFilter_to_BarkSpectrogram) {
+	CONVERT_EACH (BarkFilter)
+		autoBarkSpectrogram result = BarkFilter_to_BarkSpectrogram (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (MelFilter_to_MelSpectrogram)
-	LOOP {
-		iam (MelFilter);
-		praat_new (MelFilter_to_MelSpectrogram (me), my name);
-	}
-END
+DIRECT (NEW_MelFilter_to_MelSpectrogram) {
+	CONVERT_EACH (MelFilter)
+		autoMelSpectrogram result = MelFilter_to_MelSpectrogram (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (FormantFilter_to_Spectrogram)
-	LOOP {
-		iam (FormantFilter);
-		praat_new (FormantFilter_to_Spectrogram (me), my name);
-	}
-END
+DIRECT (NEW_FormantFilter_to_Spectrogram) {
+	CONVERT_EACH (FormantFilter);
+		autoSpectrogram result = FormantFilter_to_Spectrogram (me);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** Categories  ****************************************/
 
-FORM (Categories_append, U"Categories: Append 1 category", U"Categories: Append 1 category...")
+FORM (MODIFY_Categories_append, U"Categories: Append 1 category", U"Categories: Append 1 category...") {
 	SENTENCE (U"Category", U"")
 	OK
 DO
-	LOOP {
-		iam (Categories);
+	MODIFY_EACH (Categories)
 		OrderedOfString_append (me, GET_STRING (U"Category"));
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (Categories_edit)
+DIRECT (WINDOW_Categories_edit) {
 	if (theCurrentPraatApplication -> batch) {
 		Melder_throw (U"Cannot edit a Categories from batch.");
 	} else {
@@ -344,906 +330,742 @@ DIRECT (Categories_edit)
 			editor.releaseToUser();
 		}
 	}
-END
+END }
 
-DIRECT (Categories_getNumberOfCategories)
-	LOOP {
-		iam (Categories);
-		Melder_information (my size, U" categories");
-	}
-END
-
-DIRECT (Categories_getNumberOfDifferences)
-	Categories c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Categories);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
+DIRECT (INTEGER_Categories_getNumberOfCategories) {
+	INTEGER_ONE (Categories)
+		long result = my size;
+	INTEGER_ONE_END (U" categories")
+}
 
-	long numberOfDifferences = OrderedOfString_getNumberOfDifferences (c1, c2);
-	if (numberOfDifferences < 0) {
-		Melder_information (U"-1 (undefined: number of elements differ!)");
-	} else {
-		Melder_information (numberOfDifferences, U" differences");
-	}
-END
+DIRECT (INTEGER_Categories_getNumberOfDifferences) {
+	NUMBER_COUPLE (Categories)
+		long result = OrderedOfString_getNumberOfDifferences (me, you);
+	NUMBER_COUPLE_END (U" differences")
+}
+DIRECT (REAL_Categories_getFractionDifferent) {
+	NUMBER_COUPLE (Categories)
+		double result = OrderedOfString_getFractionDifferent (me, you);
+	NUMBER_COUPLE_END (U" (fraction different)")
+}
 
-DIRECT (Categories_getFractionDifferent)
-	Categories c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Categories);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	Melder_information (OrderedOfString_getFractionDifferent (c1, c2));
-END
+DIRECT (INTEGER_Categories_difference) {
+	NUMBER_COUPLE (Categories)
+		long result;
+		double fraction;
+		OrderedOfString_difference (me, you, & result, &fraction);
+	NUMBER_COUPLE_END (U" (difference)")
+}
 
-DIRECT (Categories_difference)
-	Categories c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Categories);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	long n;
-	double fraction;
-	OrderedOfString_difference (c1, c2, &n, &fraction);
-	Melder_information (n, U" differences");
-END
-
-DIRECT (Categories_selectUniqueItems)
-	LOOP {
-		iam (Categories);
-		autoCategories thee = Categories_selectUniqueItems (me);
-		praat_new (thee.move(), my name, U"_uniq");
-	}
-END
+DIRECT (NEW_Categories_selectUniqueItems) {
+	CONVERT_EACH (Categories)
+		autoCategories result = Categories_selectUniqueItems (me);
+	CONVERT_EACH_END (my name, U"_uniq")
+}
 
-DIRECT (Categories_to_Confusion)
-	Categories c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Categories);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	autoConfusion thee = Categories_to_Confusion (c1, c2);
-	praat_new (thee.move(), Thing_getName (c1), U"_", Thing_getName (c2));
-END
+DIRECT (NEW_Categories_to_Confusion) {
+	CONVERT_COUPLE (Categories)
+		autoConfusion result = Categories_to_Confusion (me, you);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-DIRECT (Categories_to_Strings)
-	LOOP {
-		iam (Categories);
-		autoStrings thee = Categories_to_Strings (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Categories_to_Strings) {
+	CONVERT_EACH (Categories)
+		autoStrings result = Categories_to_Strings (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Categories_join)
-	Categories c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Categories);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	autoOrderedOfString thee = OrderedOfString_joinItems (c1, c2);
-	praat_new (thee.move(), c1 -> name, U"_", c2 -> name);
-END
+DIRECT (NEW1_Categories_join) {
+	CONVERT_COUPLE (Categories)
+		autoOrderedOfString result = OrderedOfString_joinItems (me, you);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-DIRECT (Categories_permuteItems)
-	LOOP {
-		iam (Collection);
-		autoCollection thee = Collection_permuteItems (me);
-		praat_new (thee.move(), my name, U"_perm");
-	}
-END
+DIRECT (NEW_Categories_permuteItems) {
+	CONVERT_EACH (Collection)
+		autoCollection result = Collection_permuteItems (me);
+	CONVERT_EACH_END (my name, U"_perm")
+}
 
 /***************** CC ****************************************/
 
-FORM (CC_getNumberOfCoefficients, U"Get number of coefficients", nullptr)
-	NATURAL (U"Frame number", U"1")
+FORM (INTEGER_CC_getNumberOfCoefficients, U"Get number of coefficients", nullptr) {
+	NATURALVAR (frameNumber, U"Frame number", U"1")
 	OK
 DO
-	LOOP {
-		iam (CC);
-		long numberOfCoefficients = CC_getNumberOfCoefficients (me, GET_INTEGER (U"Frame number"));
-		Melder_information (numberOfCoefficients);
-	}
-END
+	INTEGER_ONE (CC)
+		long result = CC_getNumberOfCoefficients (me, frameNumber);
+	INTEGER_ONE_END (U" (number of coefficients)")
+}
 
-FORM (CC_getValue, U"CC: Get value", U"CC: Get value...")
-	REAL (U"Time (s)", U"0.1")
-	NATURAL (U"Index", U"1")
+FORM (REAL_CC_getValue, U"CC: Get value", U"CC: Get value...") {
+	REALVAR (time, U"Time (s)", U"0.1")
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	LOOP {
-		iam (CC); // ?? generic
-		Melder_informationReal (CC_getValue (me, GET_REAL (U"Time"), GET_INTEGER (U"Index")), nullptr);
-	}
-END
+	NUMBER_ONE (CC)
+		double result = CC_getValue (me, time, index);
+	NUMBER_ONE_END (U" value")
+}
 
-FORM (CC_getValueInFrame, U"CC: Get value in frame", U"CC: Get value in frame...")
-	NATURAL (U"Frame number", U"1")
-	NATURAL (U"Index", U"1")
+FORM (REAL_CC_getValueInFrame, U"CC: Get value in frame", U"CC: Get value in frame...") {
+	NATURALVAR (frameNumber, U"Frame number", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	LOOP {
-		iam (CC); // ?? generic
-		Melder_informationReal (CC_getValueInFrame (me, GET_INTEGER (U"Frame number"), GET_INTEGER (U"Index")), nullptr);
-	}
-END
+	NUMBER_ONE (CC)
+		double result = CC_getValueInFrame (me, frameNumber, index);
+	NUMBER_ONE_END (U" value")
+}
 
-FORM (CC_getC0ValueInFrame, U"CC: Get c0 value in frame", U"CC: Get c0 value in frame...")
-	NATURAL (U"Frame number", U"1")
+FORM (REAL_CC_getC0ValueInFrame, U"CC: Get c0 value in frame", U"CC: Get c0 value in frame...") {
+	NATURALVAR (frameNumber, U"Frame number", U"1")
 	OK
 DO
-	LOOP {
-		iam (CC); // ?? generic
-		Melder_informationReal (CC_getC0ValueInFrame (me, GET_INTEGER (U"Frame number")), nullptr);
-	}
-END
+	NUMBER_ONE (CC)
+		double result = CC_getC0ValueInFrame (me, frameNumber);
+	NUMBER_ONE_END (U" value")
+}
 
-FORM (CC_paint, U"CC: Paint", U"CC: Paint...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	INTEGER (U"From coefficient", U"0")
-	INTEGER (U"To coefficient", U"0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_CC_paint, U"CC: Paint", U"CC: Paint...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	INTEGERVAR (fromCoefficient, U"From coefficient", U"0")
+	INTEGERVAR (toCoefficient, U"To coefficient", U"0")
+	REALVAR (minimum, U"Minimum", U"0.0")
+	REALVAR (maximum, U"Maximum", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (CC);
-		CC_paint (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"From coefficient"), GET_INTEGER (U"To coefficient"),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (CC)
+		CC_paint (me, GRAPHICS, fromTime, toTime, fromCoefficient, toCoefficient, minimum, maximum, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (CC_drawC0, U"CC: Draw c0", U"CC: Draw c0...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_CC_drawC0, U"CC: Draw c0", U"CC: Draw c0...") {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (CC);
-		CC_drawC0 (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (CC)
+		CC_drawC0 (me, GRAPHICS, fromTime, toTime,fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (CCs_to_DTW, U"CC: To DTW", U"CC: To DTW...")
+FORM (NEW1_CCs_to_DTW, U"CC: To DTW", U"CC: To DTW...") {
 	LABEL (U"", U"Distance  between cepstral coefficients")
-	REAL (U"Cepstral weight", U"1.0")
-	REAL (U"Log energy weight", U"0.0")
-	REAL (U"Regression weight", U"0.0")
-	REAL (U"Regression weight log energy", U"0.0")
-	REAL (U"Regression coefficients window (s)", U"0.056")
-	DTW_constraints_addCommonFields (dia);
-	OK
-DO
-	CC c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (CC);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	int begin, end, slope;
-	DTW_constraints_getCommonFields (dia, &begin, &end, &slope);
-    autoDTW thee = CCs_to_DTW (c1, c2, GET_REAL (U"Cepstral weight"), GET_REAL (U"Log energy weight"),
-        GET_REAL (U"Regression weight"), GET_REAL (U"Regression weight log energy"),
-        GET_REAL (U"Regression coefficients window"));
-    DTW_findPath (thee.get(), begin, end, slope);
-	praat_new (thee.move(), U"");
-END
-
-DIRECT (CC_to_Matrix)
-	LOOP {
-		iam (CC);
-		autoMatrix thee = CC_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+	REALVAR (cepstralWeight, U"Cepstral weight", U"1.0")
+	REALVAR (logEnergyWeight, U"Log energy weight", U"0.0")
+	REALVAR (regressionWeight, U"Regression weight", U"0.0")
+	REALVAR (regressionLogEnergyWeight, U"Regression log energy weight", U"0.0")
+	REALVAR (regressionWindowLength, U"Regression window length (s)", U"0.056")
+	DTW_constraints_addCommonFields (matchStart, matchEnd, slopeConstraint)
+	OK
+DO
+	CONVERT_COUPLE (CC)
+		autoDTW result = CCs_to_DTW (me, you, cepstralWeight, logEnergyWeight, regressionWeight, regressionLogEnergyWeight, regressionWindowLength);
+		DTW_findPath (result.get(), matchStart, matchEnd, slopeConstraint);
+	CONVERT_COUPLE_END (my name, U"_", your name);
+}
+
+DIRECT (NEW_CC_to_Matrix) {
+	CONVERT_EACH (CC)
+		autoMatrix result = CC_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
 /******************* class CCA ********************************/
 
-FORM (CCA_drawEigenvector, U"CCA: Draw eigenvector", U"Eigen: Draw eigenvector...")
-	OPTIONMENU (U"X or Y", 1)
+DIRECT (HELP_CCA_help) {
+	HELP (U"CCA")
+}
+
+FORM (GRAPHICS_CCA_drawEigenvector, U"CCA: Draw eigenvector", U"Eigen: Draw eigenvector...") {
+	OPTIONMENUVAR (xOrY, U"X or Y", 1)
 		OPTION (U"y")
 		OPTION (U"x")
-	INTEGER (U"Eigenvector number", U"1")
+	INTEGERVAR (eigenVectorNumber, U"Eigenvector number", U"1")
 	LABEL (U"", U"Multiply by eigenvalue?")
-	BOOLEAN (U"Component loadings", false)
+	BOOLEANVAR (useComponentLoadings, U"Component loadings", false)
 	LABEL (U"", U"Select part of the eigenvector:")
-	INTEGER (U"left Element range", U"0")
-	INTEGER (U"right Element range", U"0")
-	REAL (U"left Amplitude range", U"-1.0")
-	REAL (U"right Amplitude range", U"1.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Connect points", true)
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (CCA);
-		CCA_drawEigenvector (me, GRAPHICS, GET_INTEGER (U"X or Y"), GET_INTEGER (U"Eigenvector number"),
-			GET_INTEGER (U"left Element range"), GET_INTEGER (U"right Element range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Component loadings"), GET_REAL (U"Mark size"),
-			GET_STRING (U"Mark string"), GET_INTEGER (U"Connect points"), GET_INTEGER (U"Garnish"));
-	}
-END
+	INTEGERVAR (fromElement, U"left Element range", U"0")
+	INTEGERVAR (toElement, U"right Element range", U"0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"-1.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"1.0")
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (connectPoints, U"Connect points", true)
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (CCA)
+		CCA_drawEigenvector (me, GRAPHICS, xOrY, eigenVectorNumber, fromElement, toElement, fromAmplitude, toAmplitude, useComponentLoadings, markSize_mm, mark_string, connectPoints, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (CCA_getNumberOfCorrelations)
-	LOOP {
-		iam (CCA);
-		Melder_information (my numberOfCoefficients);
-	}
-END
+DIRECT (INTEGER_CCA_getNumberOfCorrelations) {
+	INTEGER_ONE (CCA)
+		long result = my numberOfCoefficients;
+	INTEGER_ONE_END (U"")
+}
 
-FORM (CCA_getCorrelationCoefficient, U"CCA: Get canonical correlation coefficient", U"CCA: Get canonical correlation coefficient")
-	NATURAL (U"Coefficient number", U"1")
+FORM (REAL_CCA_getCorrelationCoefficient, U"CCA: Get canonical correlation coefficient", U"CCA: Get canonical correlation coefficient") {
+	NATURALVAR (coefficientNuber, U"Coefficient number", U"1")
 	OK
 DO
-	LOOP {
-		iam (CCA);
-		Melder_information (CCA_getCorrelationCoefficient (me, GET_INTEGER (U"Coefficient number")));
-	}
-END
+	NUMBER_ONE (CCA)
+		double result = CCA_getCorrelationCoefficient (me, coefficientNuber);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (CCA_getEigenvectorElement, U"CCA: Get eigenvector element", U"Eigen: Get eigenvector element...")
-	OPTIONMENU (U"X or Y", 1)
+FORM (REAL_CCA_getEigenvectorElement, U"CCA: Get eigenvector element", U"Eigen: Get eigenvector element...") {
+	OPTIONMENUVAR (xOrY, U"X or Y", 1)
 		OPTION (U"y")
 		OPTION (U"x")
-	NATURAL (U"Eigenvector number", U"1")
-	NATURAL (U"Element number", U"1")
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
+	NATURALVAR (elementNumber, U"Element number", U"1")
 	OK
 DO
-	LOOP {
-		iam (CCA);
-		Melder_information (CCA_getEigenvectorElement (me, GET_INTEGER (U"X or Y"),
-			GET_INTEGER (U"Eigenvector number"), GET_INTEGER (U"Element number")));
-	}
-END
+	NUMBER_ONE (CCA)
+		double result = CCA_getEigenvectorElement (me, xOrY, eigenvectorNumber, elementNumber);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (CCA_getZeroCorrelationProbability, U"CCA: Get zero correlation probability", U"CCA: Get zero correlation probability...")
-	NATURAL (U"Coefficient number", U"1")
+FORM (REAL_CCA_getZeroCorrelationProbability, U"CCA: Get zero correlation probability", U"CCA: Get zero correlation probability...") {
+	NATURALVAR (coefficientNumber, U"Coefficient number", U"1")
 	OK
 DO
-	LOOP {
-		iam (CCA);
-		double p, chisq, df;
-		CCA_getZeroCorrelationProbability (me, GET_INTEGER (U"Coefficient number"), & p, & chisq, & df);
-		Melder_information (p, U" (= probability for chisq = ", chisq,
-			U" and ndf = ", df, U")");
-	}
-END
+	NUMBER_ONE (CCA)
+		double result, chisq, df;
+		CCA_getZeroCorrelationProbability (me, coefficientNumber, & result, & chisq, & df);
+	NUMBER_ONE_END (U" (= probability for chisq = ", chisq, U" and ndf = ", df, U")");
+}
 
-DIRECT (CCA_and_Correlation_factorLoadings)
-	CCA me = FIRST (CCA);
-	Correlation thee = FIRST (Correlation);
-	autoTableOfReal result = CCA_and_Correlation_factorLoadings (me, thee);
-	praat_new (result.move(), Thing_getName (me), U"_loadings");
-END
+DIRECT (NEW1_CCA_and_Correlation_factorLoadings) {
+	CONVERT_TWO (CCA, Correlation)
+		autoTableOfReal result = CCA_and_Correlation_factorLoadings (me, you);
+	CONVERT_TWO_END (my name, U"_loadings")
+}
 
-FORM (CCA_and_Correlation_getVarianceFraction, U"CCA & Correlation: Get variance fraction", U"CCA & Correlation: Get variance fraction...")
+FORM (REAL_CCA_and_Correlation_getVarianceFraction, U"CCA & Correlation: Get variance fraction", U"CCA & Correlation: Get variance fraction...") {
 	LABEL (U"", U"Get the fraction of variance from the data in set...")
-	OPTIONMENU (U"X or Y", 1)
+	OPTIONMENUVAR (xOrY, U"X or Y", 1)
 		OPTION (U"y")
 		OPTION (U"x")
 	LABEL (U"", U"extracted by...")
-	NATURAL (U"left Canonical variate range", U"1")
-	NATURAL (U"right Canonical variate range", U"1")
+	NATURALVAR (fromCanonicalVariate, U"left Canonical variate range", U"1")
+	NATURALVAR (toCanonicalVariate, U"right Canonical variate range", U"1")
 	OK
 DO
-	CCA me = FIRST (CCA);
-	Correlation thee = FIRST (Correlation);
-	int x_or_y = GET_INTEGER (U"X or Y");
-	int cv_from = GET_INTEGER (U"left Canonical variate range");
-	int cv_to = GET_INTEGER (U"right Canonical variate range");
-	Melder_information (CCA_and_Correlation_getVarianceFraction (me, thee, x_or_y, cv_from, cv_to),
-		U" (fraction variance from ", (x_or_y == 1 ? U"y" : U"x"), U", extracted by canonical variates ",
-		cv_from, U" to ", cv_to, U")");
-END
+	NUMBER_TWO (CCA, Correlation)
+		double result = CCA_and_Correlation_getVarianceFraction (me, you, xOrY, fromCanonicalVariate, toCanonicalVariate);
+	NUMBER_TWO_END (U" (fraction variance from ", (xOrY == 1 ? U"y" : U"x"), U", extracted by canonical variates ", fromCanonicalVariate, U" to ", toCanonicalVariate, U")")
+}
 
-FORM (CCA_and_Correlation_getRedundancy_sl, U"CCA & Correlation: Get Stewart-Love redundancy", U"CCA & Correlation: Get redundancy (sl)...")
+FORM (REAL_CCA_and_Correlation_getRedundancy_sl, U"CCA & Correlation: Get Stewart-Love redundancy", U"CCA & Correlation: Get redundancy (sl)...") {
 	LABEL (U"", U"Get the redundancy of the data in set...")
-	OPTIONMENU (U"X or Y", 1)
+	OPTIONMENUVAR (xOrY, U"X or Y", 1)
 		OPTION (U"y")
 		OPTION (U"x")
 	LABEL (U"", U"extracted by...")
-	NATURAL (U"left Canonical variate range", U"1")
-	NATURAL (U"right Canonical variate range", U"1")
+	NATURALVAR (fromCanonicalVariate, U"left Canonical variate range", U"1")
+	NATURALVAR (toCanonicalVariate, U"right Canonical variate range", U"1")
 	LABEL (U"", U"...given the availability of the data in the other set.")
 	OK
 DO
-	CCA me = FIRST (CCA);
-	Correlation thee = FIRST (Correlation);
-	int x_or_y = GET_INTEGER (U"X or Y");
-	int cv_from = GET_INTEGER (U"left Canonical variate range");
-	int cv_to = GET_INTEGER (U"right Canonical variate range");
-	Melder_information (CCA_and_Correlation_getRedundancy_sl (me, thee, x_or_y, cv_from, cv_to),
-		U" (redundancy from ", (x_or_y == 1 ? U"y" : U"x"), U" extracted by canonical variates ",
-		cv_from, U" to ", cv_to, U")");
-END
+	NUMBER_TWO (CCA, Correlation)
+		double result = CCA_and_Correlation_getRedundancy_sl (me, you, xOrY, fromCanonicalVariate, toCanonicalVariate);
+	NUMBER_TWO_END (U" (redundancy from ", (xOrY == 1 ? U"y" : U"x"), U" extracted by canonical variates ", fromCanonicalVariate, U" to ", toCanonicalVariate, U")")
+}
 
-DIRECT (CCA_and_TableOfReal_factorLoadings)
-	CCA me = FIRST (CCA);
-	TableOfReal thee = FIRST (TableOfReal);
-	autoTableOfReal result = CCA_and_TableOfReal_factorLoadings (me, thee);
-	praat_new (result.move(), Thing_getName (me), U"_loadings");
-END
+DIRECT (NEW_CCA_and_TableOfReal_factorLoadings) {
+	CONVERT_TWO (CCA, TableOfReal)
+		autoTableOfReal result = CCA_and_TableOfReal_factorLoadings (me, you);
+	CONVERT_TWO_END (my name, U"_loadings")
+}
 
-FORM (CCA_and_TableOfReal_scores, U"CCA & TableOfReal: To TableOfReal (scores)", U"CCA & TableOfReal: To TableOfReal (scores)...")
-	INTEGER (U"Number of canonical correlations", U"0 (= all)")
+FORM (NEW_CCA_and_TableOfReal_scores, U"CCA & TableOfReal: To TableOfReal (scores)", U"CCA & TableOfReal: To TableOfReal (scores)...") {
+	INTEGERVAR (numberOfCanonicalVariates, U"Number of canonical correlations", U"0 (= all)")
 	OK
 DO
-	CCA me = FIRST (CCA);
-	TableOfReal thee = FIRST (TableOfReal);
-	autoTableOfReal result = CCA_and_TableOfReal_scores (me, thee, GET_INTEGER (U"Number of canonical correlations"));
-	praat_new (result.move(), Thing_getName (me), U"_scores");
-END
+	CONVERT_TWO (CCA, TableOfReal)
+		autoTableOfReal result = CCA_and_TableOfReal_scores (me, you, numberOfCanonicalVariates);
+	CONVERT_TWO_END (my name, U"_scores");
+}
 
-FORM (CCA_and_TableOfReal_predict, U"CCA & TableOfReal: Predict", U"CCA & TableOfReal: Predict...")
+FORM (NEW1_CCA_and_TableOfReal_predict, U"CCA & TableOfReal: Predict", U"CCA & TableOfReal: Predict...") {
 	LABEL (U"", U"The data set from which to predict starts at...")
-	INTEGER (U"Column number", U"1")
+	INTEGERVAR (columnNumber, U"Column number", U"1")
+	OK
+DO
+	CONVERT_TWO (CCA, TableOfReal)
+		autoTableOfReal result = CCA_and_TableOfReal_predict (me, you, columnNumber);
+	CONVERT_TWO_END (your name, U"_", my name)
+}
+
+FORM (NEW_CCA_extractEigen, U"CCA: Exxtract Eigen", nullptr) {
+	OPTIONMENUVAR (choice, U"variablesType", 1)
+		OPTION (U"Dependent")
+		OPTION (U"Independent")
 	OK
 DO
-	CCA me = FIRST (CCA);
-	TableOfReal thee = FIRST (TableOfReal);
-	autoTableOfReal result = CCA_and_TableOfReal_predict (me, thee, GET_INTEGER (U"Column number"));
-	praat_new (result.move(), thy name, U"_", my name);
-END
+		CONVERT_EACH (CCA)
+			autoEigen result = choice == 1 ? Data_copy (my y.get()) : Data_copy (my x.get());
+		CONVERT_EACH_END (my name, (choice == 1 ? U"_y" : U"_x"))
+}
 
 /***************** ChebyshevSeries ****************************************/
 
-DIRECT (ChebyshevSeries_help)
-	Melder_help (U"ChebyshevSeries");
-END
+DIRECT (HELP_ChebyshevSeries_help) {
+	HELP (U"ChebyshevSeries")
+}
 
-FORM (ChebyshevSeries_create, U"Create ChebyshevSeries", U"Create ChebyshevSeries...")
-	WORD (U"Name", U"cs")
+FORM (NEW1_ChebyshevSeries_create, U"Create ChebyshevSeries", U"Create ChebyshevSeries...") {
+	WORDVAR (name, U"Name", U"cs")
 	LABEL (U"", U"Domain")
-	REAL (U"Xmin", U"-1")
-	REAL (U"Xmax", U"1")
+	REALVAR (xmin, U"Xmin", U"-1")
+	REALVAR (xmax, U"Xmax", U"1")
 	LABEL (U"", U"ChebyshevSeries(x) = c[1] T[0](x) + c[2] T[1](x) + ... c[n+1] T[n](x)")
 	LABEL (U"", U"T[k] is a Chebyshev polynomial of degree k")
-	SENTENCE (U"Coefficients (c[k])", U"0 0 1.0")
+	SENTENCEVAR (coefficients_string, U"Coefficients (c[k])", U"0 0 1.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
 	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
-	autoChebyshevSeries me = ChebyshevSeries_createFromString (xmin, xmax, GET_STRING (U"Coefficients"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoChebyshevSeries result = ChebyshevSeries_createFromString (xmin, xmax, coefficients_string);
+	CREATE_ONE_END (name)
+}
 
-DIRECT (ChebyshevSeries_to_Polynomial)
-	LOOP {
-		iam (ChebyshevSeries);
-		autoPolynomial thee = ChebyshevSeries_to_Polynomial (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_ChebyshevSeries_to_Polynomial) {
+	CONVERT_EACH (ChebyshevSeries)
+		autoPolynomial result = ChebyshevSeries_to_Polynomial (me);
+	CONVERT_EACH_END (my name);
+}
 
 /***************** ClassificationTable ****************************************/
 
-DIRECT (ClassificationTable_help)
-	Melder_help (U"ClassificationTable");
-END
+DIRECT (HELP_ClassificationTable_help) {
+	HELP (U"ClassificationTable")
+}
 
-FORM (ClassificationTable_getClassIndexAtMaximumInRow, U"ClassificationTable: Get class index at maximum in row", nullptr)
-	NATURAL (U"Row number", U"1")
+FORM (INTEGER_ClassificationTable_getClassIndexAtMaximumInRow, U"ClassificationTable: Get class index at maximum in row", nullptr) {
+	NATURALVAR (rowNumber, U"Row number", U"1")
 	OK
 DO
-	LOOP {
-		iam (ClassificationTable);
-		long klasIndex = TableOfReal_getColumnIndexAtMaximumInRow (me, GET_INTEGER (U"Row number"));
-		Melder_information (klasIndex);
-	}
-END
+	INTEGER_ONE (ClassificationTable)
+		long result = TableOfReal_getColumnIndexAtMaximumInRow (me, rowNumber);
+	INTEGER_ONE_END (U" class index at maximum in row")
+}
 
-FORM (ClassificationTable_getClassLabelAtMaximumInRow, U"ClassificationTable: Get class label at maximum in row", nullptr)
-	NATURAL (U"Row number", U"1")
+FORM (INTEGER_ClassificationTable_getClassLabelAtMaximumInRow, U"ClassificationTable: Get class label at maximum in row", nullptr) {
+	NATURALVAR (rowNumber, U"Row number", U"1")
 	OK
 DO
-	LOOP {
-		iam (ClassificationTable);
-		const char32 *klasLabel = TableOfReal_getColumnLabelAtMaximumInRow (me, GET_INTEGER (U"Row number"));
-		Melder_information (klasLabel);
-	}
-END
+	STRING_ONE (ClassificationTable)
+		const char32 *result = TableOfReal_getColumnLabelAtMaximumInRow (me, rowNumber);
+	STRING_ONE_END
+}
 
 // deprecated 2014
-DIRECT (ClassificationTable_to_Confusion_old)
-	LOOP {
-		iam (ClassificationTable);
-		autoConfusion thee = ClassificationTable_to_Confusion (me, false);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_ClassificationTable_to_Confusion_old) {
+	CONVERT_EACH (ClassificationTable)
+		autoConfusion result = ClassificationTable_to_Confusion (me, false);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (ClassificationTable_to_Confusion, U"ClassificationTable: To Confusion", U"ClassificationTable: To Confusion...")
-	BOOLEAN (U"Only class labels", true)
+FORM (NEW_ClassificationTable_to_Confusion, U"ClassificationTable: To Confusion", U"ClassificationTable: To Confusion...") {
+	BOOLEAN4 (onlyClassLabels, U"Only class labels", true)
 	OK
 DO
-	LOOP {
-		iam (ClassificationTable);
-		autoConfusion thee = ClassificationTable_to_Confusion (me, GET_INTEGER (U"Only class labels"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (ClassificationTable)
+		autoConfusion result = ClassificationTable_to_Confusion (me, onlyClassLabels);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (ClassificationTable_to_Correlation_columns)
-	LOOP {
-		iam (ClassificationTable);
-		autoCorrelation thee = ClassificationTable_to_Correlation_columns (me);
-		praat_new (thee.move(), my name, U"_col");
-	}
-END
+DIRECT (NEW_ClassificationTable_to_Correlation_columns) {
+	CONVERT_EACH (ClassificationTable)
+		autoCorrelation result = ClassificationTable_to_Correlation_columns (me);
+	CONVERT_EACH_END (my name, U"_col")
+}
 
-DIRECT (ClassificationTable_to_Strings_maximumProbability)
-	LOOP {
-		iam (ClassificationTable);
-		autoStrings thee = ClassificationTable_to_Strings_maximumProbability (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_ClassificationTable_to_Strings_maximumProbability) {
+	CONVERT_EACH (ClassificationTable)
+		autoStrings result = ClassificationTable_to_Strings_maximumProbability (me);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** Confusion *******************************************/
 
-DIRECT (Confusion_help)
-	Melder_help (U"Confusion");
-END
+DIRECT (HELP_Confusion_help) {
+	HELP (U"Confusion")
+}
 
-FORM (Confusion_createSimple, U"Create simple Confusion", U"Create simple Confusion...")
-	WORD (U"Name", U"simple")
-	SENTENCE (U"Labels", U"u i a")
+FORM (NEW1_Confusion_createSimple, U"Create simple Confusion", U"Create simple Confusion...") {
+	WORDVAR (name, U"Name", U"simple")
+	SENTENCEVAR (labels, U"Labels", U"u i a")
 	OK
 DO
-	autoConfusion thee = Confusion_createSimple (GET_STRING (U"Labels"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoConfusion result = Confusion_createSimple (labels);
+	CREATE_ONE_END (name)
+}
 
-FORM (Confusion_increase, U"Confusion: Increase", U"Confusion: Increase...")
-	WORD (U"Stimulus", U"u")
-	WORD (U"Response", U"i")
+FORM (MODIFY_Confusion_increase, U"Confusion: Increase", U"Confusion: Increase...") {
+	WORDVAR (stimulus, U"Stimulus", U"u")
+	WORDVAR (response, U"Response", U"i")
 	OK
 DO
-	LOOP {
-		iam (Confusion);
-		Confusion_increase (me, GET_STRING (U"Stimulus"), GET_STRING (U"Response"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Confusion)
+		Confusion_increase (me, stimulus, response);
+	MODIFY_EACH_END
+}
 
-FORM (Confusion_getValue, U"Confusion: Get value", nullptr)
-	WORD (U"Stimulus", U"u")
-	WORD (U"Response", U"i")
+FORM (REAL_Confusion_getValue, U"Confusion: Get value", nullptr) {
+	WORDVAR (stimulus, U"Stimulus", U"u")
+	WORDVAR (response, U"Response", U"i")
 	OK
 DO
-	char32 *stim = GET_STRING (U"Stimulus");
-	char32 *resp = GET_STRING (U"Response");
-	LOOP {
-		iam (Confusion);
-		Melder_information (Confusion_getValue (me, stim, resp),
-		U" ( [\"", stim, U"\", \"",  resp, U"\"] )");
-	}
-END
+	NUMBER_ONE (Confusion)
+		double result = Confusion_getValue (me, stimulus, response);
+	NUMBER_ONE_END (U" ([\"", stimulus, U"\", \"",  response, U"\"])")
+}
 
-FORM (Confusion_getResponseSum, U"Confusion: Get response sum", U"Confusion: Get response sum...")
-	WORD (U"Response", U"u")
+FORM (REAL_Confusion_getResponseSum, U"Confusion: Get response sum", U"Confusion: Get response sum...") {
+	WORDVAR (response, U"Response", U"u")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (TableOfReal_getColumnSumByLabel (me, GET_STRING (U"Response")));
-	}
-END
+	NUMBER_ONE (TableOfReal)
+		double result = TableOfReal_getColumnSumByLabel (me, response);
+	NUMBER_ONE_END (U" (response sum)")
+}
 
-FORM (Confusion_getStimulusSum, U"Confusion: Get stimulus sum", U"Confusion: Get stimulus sum...")
-	WORD (U"Stimulus", U"u")
+FORM (REAL_Confusion_getStimulusSum, U"Confusion: Get stimulus sum", U"Confusion: Get stimulus sum...") {
+	WORDVAR (stimulus, U"Stimulus", U"u")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (TableOfReal_getRowSumByLabel (me, GET_STRING (U"Stimulus")));
-	}
-END
+	NUMBER_ONE (TableOfReal)
+		double result = TableOfReal_getRowSumByLabel (me, stimulus);
+	NUMBER_ONE_END (U" (stimulus sum)")
+}
 
-DIRECT (Confusion_to_TableOfReal_marginals)
-	LOOP {
-		iam (Confusion);
-		autoTableOfReal thee = Confusion_to_TableOfReal_marginals (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Confusion_to_TableOfReal_marginals) {
+	CONVERT_EACH (Confusion)
+		autoTableOfReal result = Confusion_to_TableOfReal_marginals (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Confusion_difference)
-	Confusion c1 = nullptr, c2 = nullptr;
-	LOOP {
-		iam (Confusion);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	autoMatrix thee = Confusion_difference (c1, c2);
-	praat_new (thee.move(), U"diffs");
-END
-
-FORM (Confusion_condense, U"Confusion: Condense", U"Confusion: Condense...")
-	SENTENCE (U"Search", U"^(u|i)$")
-	SENTENCE (U"Replace", U"high")
-	INTEGER (U"Replace limit", U"0 (= unlimited)")
-	RADIO (U"Search and replace are", 2)
-	RADIOBUTTON (U"Literals")
-	RADIOBUTTON (U"Regular Expressions")
+DIRECT (NEW1_Confusion_difference) {
+	CONVERT_COUPLE (Confusion)
+		autoMatrix result = Confusion_difference (me, you);
+	CONVERT_COUPLE_END (U"diffs")
+}
+
+FORM (NEW_Confusion_condense, U"Confusion: Condense", U"Confusion: Condense...") {
+	SENTENCEVAR (search_string, U"Search", U"^(u|i)$")
+	SENTENCEVAR (replace_string, U"Replace", U"high")
+	INTEGERVAR (replaceLimit, U"Replace limit", U"0 (= unlimited)")
+	RADIOVARx (matchType, U"Search and replace are", 2, 0)
+		RADIOBUTTON (U"Literals")
+		RADIOBUTTON (U"Regular Expressions")
 	OK
 DO
-	LOOP {
-		iam (Confusion);
-		autoConfusion thee = Confusion_condense (me, GET_STRING (U"Search"), GET_STRING (U"Replace"),
-			GET_INTEGER (U"Replace limit"), GET_INTEGER (U"Search and replace are") - 1);
-		praat_new (thee.move(), my name, U"_cnd");
-	}
-END
+	CONVERT_EACH (Confusion)
+		autoConfusion result = Confusion_condense (me, search_string, replace_string, replaceLimit, matchType);
+	CONVERT_EACH_END (my name, U"_cnd")
+}
 
-FORM (Confusion_group, U"Confusion: Group stimuli & responses", U"Confusion: Group...")
-	SENTENCE (U"Stimuli & Responses", U"u i")
-	SENTENCE (U"New label", U"high")
-	INTEGER (U"New label position", U"0 (= at start)")
+FORM (NEW_Confusion_group, U"Confusion: Group stimuli & responses", U"Confusion: Group...") {
+	SENTENCEVAR (labels, U"Stimuli & Responses", U"u i")
+	SENTENCEVAR (newLabel, U"New label", U"high")
+	INTEGERVAR (newPosition, U"New label position", U"0 (= at start)")
 	OK
 DO
-	const char32 *newlabel = GET_STRING (U"New label");
-	LOOP {
-		iam (Confusion);
-		autoConfusion thee = Confusion_group (me, GET_STRING (U"Stimuli & Responses"), newlabel,
-			GET_INTEGER (U"New label position"));
-		praat_new (thee.move(), my name, U"_sr", newlabel);
-	}
-END
+	CONVERT_EACH (Confusion)
+		autoConfusion result = Confusion_group (me, labels, newLabel, newPosition);
+	CONVERT_EACH_END (my name, U"_sr", newLabel)
+}
 
-FORM (Confusion_groupStimuli, U"Confusion: Group stimuli", U"Confusion: Group stimuli...")
-	SENTENCE (U"Stimuli", U"u i")
-	SENTENCE (U"New label", U"high")
-	INTEGER (U"New label position", U"0")
+FORM (NEW_Confusion_groupStimuli, U"Confusion: Group stimuli", U"Confusion: Group stimuli...") {
+	SENTENCEVAR (stimuli_string, U"Stimuli", U"u i")
+	SENTENCEVAR (newLabel, U"New label", U"high")
+	INTEGERVAR (newPosition, U"New label position", U"0")
 	OK
 DO
-	const char32 *newlabel = GET_STRING (U"New label");
-	LOOP {
-		iam (Confusion);
-		autoConfusion thee = Confusion_groupStimuli (me, GET_STRING (U"Stimuli"), newlabel,
-			GET_INTEGER (U"New label position"));
-		praat_new (thee.move(), my name, U"_s", newlabel);
-	}
-END
+	CONVERT_EACH (Confusion)
+		autoConfusion result = Confusion_groupStimuli (me,stimuli_string, newLabel, newPosition);
+	CONVERT_EACH_END (my name, U"_s", newLabel);
+}
 
-FORM (Confusion_groupResponses, U"Confusion: Group responses", U"Confusion: Group responses...")
-	SENTENCE (U"Responses", U"a i")
-	SENTENCE (U"New label", U"front")
-	INTEGER (U"New label position", U"0")
+FORM (NEW_Confusion_groupResponses, U"Confusion: Group responses", U"Confusion: Group responses...") {
+	SENTENCEVAR (responses_string, U"Responses", U"a i")
+	SENTENCEVAR (newLabel, U"New label", U"front")
+	INTEGERVAR (newPosition, U"New label position", U"0")
 	OK
 DO
-	const char32 *newlabel = GET_STRING (U"New label");
-	LOOP {
-		iam (Confusion);
-		autoConfusion thee = Confusion_groupResponses (me, GET_STRING (U"Responses"), newlabel,
-			GET_INTEGER (U"New label position"));
-		praat_new (thee.move(), my name, U"_s", newlabel);
-	}
-END
+	CONVERT_EACH (Confusion)
+		autoConfusion result = Confusion_groupResponses (me, responses_string, newLabel, newPosition);
+	CONVERT_EACH_END (my name, U"_s", newLabel);
+}
 
-FORM (Confusion_drawAsNumbers, U"", U"")
-	BOOLEAN (U"Draw marginals", true)
-	RADIO (U"Format", 3)
+FORM (GRAPHICS_Confusion_drawAsNumbers, U"Confusion: Draw as numbers", nullptr) {
+	BOOLEANVAR (drawMarginals, U"Draw marginals", true)
+	RADIOVAR (format, U"Format", 3)
 		RADIOBUTTON (U"decimal")
 		RADIOBUTTON (U"exponential")
 		RADIOBUTTON (U"free")
 		RADIOBUTTON (U"rational")
-	NATURAL (U"Precision", U"5")
+	NATURALVAR (precision, U"Precision", U"5")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Confusion);
-		Confusion_drawAsNumbers (me, GRAPHICS, GET_INTEGER (U"Draw marginals"),
-			GET_INTEGER (U"Format"), GET_INTEGER (U"Precision"));
-	}
-END
+	GRAPHICS_EACH (Confusion)
+		Confusion_drawAsNumbers (me, GRAPHICS, drawMarginals, format, precision);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Confusion_getFractionCorrect)
-	LOOP {
-		iam (Confusion);
-		double f;
-		long n;
-		Confusion_getFractionCorrect (me, &f, &n);
-		Melder_information (f, U" (fraction correct)");
-	}
-END
+DIRECT (REAL_Confusion_getFractionCorrect) {
+	NUMBER_ONE (Confusion)
+		double result;
+		Confusion_getFractionCorrect (me, & result, nullptr);
+	NUMBER_ONE_END (U" (fraction correct)")
+}
 
-DIRECT (Confusion_and_ClassificationTable_increase)
-	Confusion me = FIRST (Confusion);
-	ClassificationTable thee = FIRST (ClassificationTable);
-	Confusion_and_ClassificationTable_increase (me, thee);
-END
+DIRECT (MODIFY_Confusion_and_ClassificationTable_increase) {
+	MODIFY_FIRST_OF_TWO (Confusion, ClassificationTable)
+		Confusion_and_ClassificationTable_increase (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
 /******************* Confusion & Matrix *************************************/
 
-FORM (Confusion_Matrix_draw, U"Confusion & Matrix: Draw confusions with arrows", nullptr)
-	INTEGER (U"Category position", U"0 (= all)")
-	REAL (U"Lower level (%)", U"0")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Confusion_Matrix_draw, U"Confusion & Matrix: Draw confusions with arrows", nullptr) {
+	INTEGERVAR (categoryPosition, U"Category position", U"0 (= all)")
+	REALVAR (lowerLevel, U"Lower level (%)", U"0")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	long categoryPosition = GET_INTEGER (U"Category position");
 	REQUIRE (categoryPosition >= 0, U"Category position must be >= 0")
-	Confusion conf = FIRST (Confusion);
-	Matrix mat = FIRST (Matrix);
-	Confusion_Matrix_draw (conf, mat, GRAPHICS, categoryPosition, GET_REAL (U"Lower level"),
-		GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-END
+	GRAPHICS_TWO (Confusion, Matrix)
+		Confusion_Matrix_draw (me, you, GRAPHICS, categoryPosition, lowerLevel, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_TWO_END
+}
 
 /********************** ComplexSpectrogram *******************************************/
 
-DIRECT (ComplexSpectrogram_help)
-	Melder_help (U"ComplexSpectrogram_help");
-END
+DIRECT (HELP_ComplexSpectrogram_help) {
+	HELP (U"ComplexSpectrogram_help")
+}
 
-FORM (ComplexSpectrogram_to_Sound, U"ComplexSpectrogram: To Sound", nullptr)
-	POSITIVE (U"Duration factor", U"1.0")
+FORM (NEW_ComplexSpectrogram_to_Sound, U"ComplexSpectrogram: To Sound", nullptr) {
+	POSITIVEVAR (durationFactor, U"Duration factor", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (ComplexSpectrogram);
-		autoSound thee = ComplexSpectrogram_to_Sound (me, GET_REAL (U"Duration factor"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (ComplexSpectrogram)
+		autoSound result = ComplexSpectrogram_to_Sound (me, durationFactor);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (ComplexSpectrogram_to_Spectrogram)
-	LOOP {
-		iam (ComplexSpectrogram);
-		autoSpectrogram thee = ComplexSpectrogram_to_Spectrogram (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_ComplexSpectrogram_to_Spectrogram) {
+	CONVERT_EACH (ComplexSpectrogram)
+		autoSpectrogram result = ComplexSpectrogram_to_Spectrogram (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (ComplexSpectrogram_to_Spectrum, U"ComplexSpectrogram: To Spectrum (slice)", nullptr)
-	REAL (U"Time (s)", U"0.0")
+FORM (NEW_ComplexSpectrogram_to_Spectrum, U"ComplexSpectrogram: To Spectrum (slice)", nullptr) {
+	REALVAR (time, U"Time (s)", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (ComplexSpectrogram);
-		autoSpectrum thee = ComplexSpectrogram_to_Spectrum (me, GET_REAL (U"Time"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (ComplexSpectrogram)
+		autoSpectrum result = ComplexSpectrogram_to_Spectrum (me, time);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** Correlation *******************************************/
 
-FORM (Correlation_createSimple, U"Create simple Correlation", U"Create simple Correlation...")
-	WORD (U"Name", U"correlation")
-	SENTENCE (U"Correlations", U"1.0 0.5 1.0")
-	SENTENCE (U"Centroid", U"0.0 0.0")
-	NATURAL (U"Number of observations", U"100")
+FORM (NEW1_Correlation_createSimple, U"Create simple Correlation", U"Create simple Correlation...") {
+	WORDVAR (name, U"Name", U"correlation")
+	SENTENCEVAR (correlations_string, U"Correlations", U"1.0 0.5 1.0")
+	SENTENCEVAR (centroid_string, U"Centroid", U"0.0 0.0")
+	NATURALVAR (numberOfObservations, U"Number of observations", U"100")
 	OK
 DO
-	autoCorrelation me = Correlation_createSimple (GET_STRING (U"Correlations"), GET_STRING (U"Centroid"),
-		GET_INTEGER (U"Number of observations"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoCorrelation result = Correlation_createSimple (correlations_string, centroid_string, numberOfObservations);
+	CREATE_ONE_END (name)
+}
 
-DIRECT (Correlation_help)
-	Melder_help (U"Correlation");
-END
+DIRECT (HELP_Correlation_help) {
+	HELP (U"Correlation")
+}
 
-FORM (Correlation_confidenceIntervals, U"Correlation: Confidence intervals...", U"Correlation: Confidence intervals...")
-	POSITIVE (U"Confidence level (0-1)", U"0.95")
-	INTEGER (U"Number of tests (Bonferroni correction)", U"0")
-	RADIO (U"Approximation", 1)
+FORM (NEW_Correlation_confidenceIntervals, U"Correlation: Confidence intervals...", U"Correlation: Confidence intervals...") {
+	POSITIVEVAR (confidenceLevel, U"Confidence level (0-1)", U"0.95")
+	INTEGERVAR (numberOfTests, U"Number of tests (Bonferroni correction)", U"0")
+	RADIOVAR (approximation, U"Approximation", 1)
 		RADIOBUTTON (U"Ruben")
 		RADIOBUTTON (U"Fisher")
 	OK
 DO
-	double cl = GET_REAL (U"Confidence level");
-	long numberOfTests = GET_INTEGER (U"Number of tests");
-	LOOP {
-		iam (Correlation);
-		autoTableOfReal thee = Correlation_confidenceIntervals (me, cl, numberOfTests, GET_INTEGER (U"Approximation"));
-		praat_new (thee.move(), U"conf_intervals");
-	}
-END
+	CONVERT_EACH (Correlation)
+		autoTableOfReal result = Correlation_confidenceIntervals (me, confidenceLevel, numberOfTests, approximation);
+	CONVERT_EACH_END (my name, U"_conf_intervals")
+}
 
-FORM (Correlation_testDiagonality_bartlett, U"Correlation: Get diagonality (bartlett)", U"SSCP: Get diagonality (bartlett)...")
-	NATURAL (U"Number of contraints", U"1")
+FORM (REAL_Correlation_testDiagonality_bartlett, U"Correlation: Get diagonality (bartlett)", U"SSCP: Get diagonality (bartlett)...") {
+	NATURALVAR (numberOfConstraints, U"Number of constraints", U"1")
 	OK
 DO
-	long nc = GET_INTEGER (U"Number of contraints");
-	LOOP {
-		iam (Correlation);
-		double chisq, p, df;
-		Correlation_testDiagonality_bartlett (me, nc, & chisq, & p, & df);
-		Melder_information (p, U" (= probability, based on chisq = ", chisq, U" and ndf = ", df, U")");
-	}
-END
+	NUMBER_ONE (Correlation)
+		double chisq, result, df;
+		Correlation_testDiagonality_bartlett (me, numberOfConstraints, & chisq, & result, & df);
+	NUMBER_ONE_END (U" (= probability, based on chisq = ", chisq, U" and ndf = ", df, U")")
+}
 
-DIRECT (Correlation_to_PCA)
-	LOOP {
-		iam (Correlation);
-		autoPCA thee = SSCP_to_PCA (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Correlation_to_PCA) {
+	CONVERT_EACH (Correlation)
+		autoPCA result = SSCP_to_PCA (me);
+	CONVERT_EACH_END (my name)
+}
 
 /********************** Covariance *******************************************/
 
-DIRECT (Covariance_help)
-	Melder_help (U"Covariance");
-END
+DIRECT (HELP_Covariance_help) {
+	HELP (U"Covariance")
+}
 
-FORM (Covariance_createSimple, U"Create simple Covariance", U"Create simple Covariance...")
-	WORD (U"Name", U"c")
-	SENTENCE (U"Covariances", U"1.0 0.0 1.0")
-	SENTENCE (U"Centroid", U"0.0 0.0")
-	NATURAL (U"Number of observations", U"100")
+FORM (NEW1_Covariance_createSimple, U"Create simple Covariance", U"Create simple Covariance...") {
+	WORDVAR (name, U"Name", U"c")
+	SENTENCEVAR (covariances_string, U"Covariances", U"1.0 0.0 1.0")
+	SENTENCEVAR (centroid_string, U"Centroid", U"0.0 0.0")
+	NATURALVAR (numberOfObservations, U"Number of observations", U"100")
 	OK
 DO
-	autoCovariance me = Covariance_createSimple (GET_STRING (U"Covariances"), GET_STRING (U"Centroid"),
-		GET_INTEGER (U"Number of observations"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoCovariance result = Covariance_createSimple (covariances_string, centroid_string, numberOfObservations);
+	CREATE_ONE_END (name)
+}
 
-FORM (Covariance_getProbabilityAtPosition, U"Covariance: Get probability at position", nullptr)
-	SENTENCE (U"Position", U"10.0 20.0")
+FORM (REAL_Covariance_getProbabilityAtPosition, U"Covariance: Get probability at position", nullptr) {
+	SENTENCEVAR (position_string, U"Position", U"10.0 20.0")
 	OK
 DO
-	char32 *position = GET_STRING (U"Position");
-	LOOP {
-		iam (Covariance);
-		double p = Covariance_getProbabilityAtPosition_string (me, position);
-		Melder_information (p, U" (= probability at position ", position, U")");
-	}
-END
+	NUMBER_ONE (Covariance)
+		double result = Covariance_getProbabilityAtPosition_string (me, position_string);
+	NUMBER_ONE_END (U" (= probability at position ", position_string, U")")
+}
 
-FORM (Covariance_getSignificanceOfOneMean, U"Covariance: Get significance of one mean", U"Covariance: Get significance of one mean...")
+FORM (REAL_Covariance_getSignificanceOfOneMean, U"Covariance: Get significance of one mean", U"Covariance: Get significance of one mean...") {
 	LABEL (U"", U"Get probability that the estimated mean for")
-	NATURAL (U"Index", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	LABEL (U"", U"(or an estimated mean even further away)")
 	LABEL (U"", U"could arise if the true mean were")
-	REAL (U"Value", U"0.0")
+	REALVAR (value, U"Value", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Covariance);
-		double p, t, ndf;
-		Covariance_getSignificanceOfOneMean (me, GET_INTEGER (U"Index"), GET_REAL (U"Value"), & p, & t, & ndf);
-		Melder_information (p, U" (= probability, based on t = ", t, U" and ndf = ", ndf);
-	}
-END
+	NUMBER_ONE (Covariance)
+		double result, t, ndf;
+		Covariance_getSignificanceOfOneMean (me, index, value, & result, & t, & ndf);
+	NUMBER_ONE_END (U" (= probability, based on t = ", t, U" and ndf = ", ndf)
+}
 
-FORM (Covariance_getSignificanceOfMeansDifference, U"Covariance: Get significance of means difference", U"Covariance: Get significance of means difference...")
+FORM (REAL_Covariance_getSignificanceOfMeansDifference, U"Covariance: Get significance of means difference", U"Covariance: Get significance of means difference...") {
 	LABEL (U"", U"Get probability that the estimated difference between the means for")
-	NATURAL (U"Index1", U"1")
-	NATURAL (U"Index2", U"2")
+	NATURALVAR (index1, U"Index1", U"1")
+	NATURALVAR (index2, U"Index2", U"2")
 	LABEL (U"", U"could arise if the true mean were")
-	REAL (U"Value", U"0.0")
+	REALVAR (value, U"Value", U"0.0")
 	LABEL (U"", U"Assume the means are ")
-	BOOLEAN (U"Paired", true)
+	BOOLEANVAR (paired, U"Paired", true)
 	LABEL (U"", U"and have")
-	BOOLEAN (U"Equal variances", true)
+	BOOLEANVAR (equalVariances, U"Equal variances", true)
 	OK
 DO
-	LOOP {
-		iam (Covariance);
-		double p, t, ndf;
-		Covariance_getSignificanceOfMeansDifference (me, GET_INTEGER (U"Index1"), GET_INTEGER (U"Index2"),
-			GET_REAL (U"Value"), GET_INTEGER (U"Paired"), GET_INTEGER (U"Equal variances"), & p, & t, & ndf);
-		Melder_information (p, U" (= probability, based on t = ",
-			t, U"and ndf = ", ndf, U")");
-	}
-END
+	NUMBER_ONE (Covariance)
+		double result, t, ndf;
+		Covariance_getSignificanceOfMeansDifference (me, index1, index2, value, paired, equalVariances, & result, & t, & ndf);
+	NUMBER_ONE_END (U" (= probability, based on t = ", t, U"and ndf = ", ndf, U")")
+}
 
-FORM (Covariance_getSignificanceOfOneVariance, U"Covariance: Get significance of one variance", U"Covariance: Get significance of one variance...")
+FORM (REAL_Covariance_getSignificanceOfOneVariance, U"Covariance: Get significance of one variance", U"Covariance: Get significance of one variance...") {
 	LABEL (U"", U"Get the probability that the estimated variance for")
-	NATURAL (U"Index", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	LABEL (U"", U"(or an even larger estimated variance)")
 	LABEL (U"", U"could arise if the true variance were")
-	REAL (U"Value", U"0.0")
+	REALVAR (value, U"Value", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Covariance);
-		double p, chisq; long ndf;
-		Covariance_getSignificanceOfOneVariance (me, GET_INTEGER (U"Index"), GET_REAL (U"Value"), & p, & chisq, & ndf);
-		Melder_information (p, U" (= probability, based on chisq = ", chisq, U" and ndf = ", ndf);
-	}
-END
+	NUMBER_ONE (Covariance)
+		double result, chisq; long ndf;
+		Covariance_getSignificanceOfOneVariance (me, index, value, & result, & chisq, & ndf);
+	NUMBER_ONE_END (U" (= probability, based on chisq = ", chisq, U" and ndf = ", ndf)
+}
 
-FORM (Covariance_getSignificanceOfVariancesRatio, U"Covariance: Get significance of variances ratio", nullptr)
+FORM (REAL_Covariance_getSignificanceOfVariancesRatio, U"Covariance: Get significance of variances ratio", nullptr) {
 	LABEL (U"", U"Get the probability that the estimated variance ratio observed for")
-	NATURAL (U"Index1", U"1")
-	NATURAL (U"Index2", U"2")
+	NATURALVAR (index1, U"Index1", U"1")
+	NATURALVAR (index2, U"Index2", U"2")
 	LABEL (U"", U"(or an estimated ratio even further away)")
 	LABEL (U"", U"could arise if the true ratio were")
-	REAL (U"Value", U"1.0")
+	REALVAR (value, U"Value", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (Covariance);
-		double p, f, df;
-		Covariance_getSignificanceOfVariancesRatio (me, GET_INTEGER (U"Index1"), GET_INTEGER (U"Index2"),
-			GET_REAL (U"Value"), & p, & f , & df);
-		Melder_information (p, U" (= probability, based on F = ", f, U" and ndf1 = ", df, U" and ndf2 = ", df);
-
-	}
-END
+	NUMBER_ONE (Covariance)
+		double result, f, df;
+		Covariance_getSignificanceOfVariancesRatio (me, index1, index2, value, & result, & f , & df);
+	NUMBER_ONE_END (U" (= probability, based on F = ", f, U" and ndf1 = ", df, U" and ndf2 = ", df)
+}
 
-FORM (Covariance_getFractionVariance, U"Covariance: Get fraction variance", U"Covariance: Get fraction variance...")
-	NATURAL (U"From dimension", U"1")
-	NATURAL (U"To dimension", U"1")
+FORM (REAL_Covariance_getFractionVariance, U"Covariance: Get fraction variance", U"Covariance: Get fraction variance...") {
+	NATURALVAR (fromDimension, U"From dimension", U"1")
+	NATURALVAR (toDimension, U"To dimension", U"1")
 	OK
 DO
-	LOOP {
-		iam (Covariance);
-		Melder_information (SSCP_getFractionVariation (me, GET_INTEGER (U"From dimension"), GET_INTEGER (U"To dimension")));
-	}
-END
+	NUMBER_ONE (Covariance)
+		double result = SSCP_getFractionVariation (me, fromDimension, toDimension);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (Covariances_reportMultivariateMeanDifference, U"Covariances: Report multivariate mean difference", U"Covariances: Report multivariate mean difference...")
+FORM (INFO_Covariances_reportMultivariateMeanDifference, U"Covariances: Report multivariate mean difference", U"Covariances: Report multivariate mean difference...") {
 	LABEL (U"", U"Get probability that the estimated multivariate means difference could arise ")
 	LABEL (U"", U"if the actual means were equal.")
 	LABEL (U"", U"")
 	LABEL (U"", U"Assume for both means we have")
-	BOOLEAN (U"Equal covariances", true)
+	BOOLEANVAR (covariancesAreEqual, U"Equal covariances", true)
+	OK
+DO
+	INFO_COUPLE (Covariance)
+		double prob, fisher, df1, df2, difference;
+		MelderInfo_open ();
+		difference = Covariances_getMultivariateCentroidDifference (me, you, covariancesAreEqual, & prob, & fisher, & df1, & df2);
+		MelderInfo_writeLine (U"Under the assumption that the two covariances are", (covariancesAreEqual ? U" " : U" not "), U"equal:");
+		MelderInfo_writeLine (U"Difference between multivariate means = ", difference);
+		MelderInfo_writeLine (U"Fisher's F = ", fisher);
+		MelderInfo_writeLine (U"Significance from zero = ", prob);
+		MelderInfo_writeLine (U"Degrees of freedom = ", df1, U", ", df2);
+		MelderInfo_writeLine (U"(Number of observations = ", me -> numberOfObservations, U", ", you -> numberOfObservations);
+		MelderInfo_writeLine (U"Dimension of covariance matrices = ", me -> numberOfRows, U")");
+		MelderInfo_close ();
+	INFO_COUPLE_END
+}
+
+FORM (NEW_Covariance_to_TableOfReal_randomSampling, U"Covariance: To TableOfReal (random sampling)", U"Covariance: To TableOfReal (random sampling)...") {
+	INTEGERVAR (numberOfDataPoints, U"Number of data points", U"0")
 	OK
 DO
-	Covariance c1 = nullptr, c2 = nullptr;
+	CONVERT_EACH (Covariance)
+		autoTableOfReal result = Covariance_to_TableOfReal_randomSampling (me, numberOfDataPoints);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (INFO_Covariances_reportEquality) {
+	autoCovarianceList covariances = CovarianceList_create ();
 	LOOP {
 		iam (Covariance);
-		(c1 ? c2 : c1) = me;
-	}
-	Melder_assert (c1 && c2);
-	double prob, fisher, df1, df2, difference;
-	bool equalCovariances = GET_INTEGER (U"Equal covariances");
-	MelderInfo_open ();
-	difference = Covariances_getMultivariateCentroidDifference (c1, c2, equalCovariances, & prob, & fisher, & df1, & df2);
-	MelderInfo_writeLine (U"Under the assumption that the two covariances are", (equalCovariances ? U" " : U" not "), U"equal:");
-	MelderInfo_writeLine (U"Difference between multivariate means = ", difference);
-	MelderInfo_writeLine (U"Fisher's F = ", fisher);
-	MelderInfo_writeLine (U"Significance from zero = ", prob);
-	MelderInfo_writeLine (U"Degrees of freedom = ", df1, U", ", df2);
-	MelderInfo_writeLine (U"(Number of observations = ", c1->numberOfObservations, U", ", c2->numberOfObservations);
-	MelderInfo_writeLine (U"Dimension of covariance matrices = ", c1-> numberOfRows, U")");
-	MelderInfo_close ();
-END
-
-FORM (Covariance_to_TableOfReal_randomSampling, U"Covariance: To TableOfReal (random sampling)", U"Covariance: To TableOfReal (random sampling)...")
-	INTEGER (U"Number of data points", U"0")
-	OK
-DO
-	LOOP {
-		iam (Covariance);
-		autoTableOfReal thee = Covariance_to_TableOfReal_randomSampling (me, GET_INTEGER (U"Number of data points"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (Covariances_reportEquality)
-	autoCovarianceList covariances = CovarianceList_create ();
-	LOOP {
-		iam (Covariance);
-		covariances -> addItem_ref (me);
+		covariances -> addItem_ref (me);
 	}
 	MelderInfo_open ();
 	double p, chisq, df;
@@ -1258,209 +1080,178 @@ DIRECT (Covariances_reportEquality)
 	MelderInfo_writeLine (U"Chi-squared (wald) = ", chisq);
 	MelderInfo_writeLine (U"Degrees of freedom (wald) = ", df);
 	MelderInfo_close ();
-END
+END }
 
-DIRECT (Covariance_to_Correlation)
-	LOOP {
-		iam (Covariance);
-		autoCorrelation thee = SSCP_to_Correlation (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Covariance_to_Correlation) {
+	CONVERT_EACH (Covariance)
+		autoCorrelation result = SSCP_to_Correlation (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Covariance_to_PCA)
-	LOOP {
-		iam (Covariance);
-		autoPCA thee = SSCP_to_PCA (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Covariance_to_PCA) {
+	CONVERT_EACH (Covariance)
+		autoPCA result = SSCP_to_PCA (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Covariances_pool)
-	autoCovarianceList covariances = CovarianceList_create ();
-	LOOP {
-		iam (Covariance);
-		covariances -> addItem_ref (me);
-	}
-	autoCovariance thee = CovarianceList_to_Covariance_pool (covariances.get());
-	praat_new (thee.move(), U"pool");
-END
+DIRECT (NEW1_Covariances_pool) {
+	CONVERT_TYPED_LIST (Covariance, CovarianceList)
+		autoCovariance result = CovarianceList_to_Covariance_pool (list.get());
+	CONVERT_TYPED_LIST_END (U"pool")
+}
 
-FORM (Covariance_and_TableOfReal_mahalanobis, U"Covariance & TableOfReal: To TableOfReal (mahalanobis)", U"Covariance & TableOfReal: To TableOfReal (mahalanobis)...")
-	BOOLEAN (U"Centroid from table", 0)
+FORM (NEW1_Covariance_and_TableOfReal_mahalanobis, U"Covariance & TableOfReal: To TableOfReal (mahalanobis)", U"Covariance & TableOfReal: To TableOfReal (mahalanobis)...") {
+	BOOLEANVAR (centroidFromTable, U"Centroid from table", 0)
 	OK
 DO
-	Covariance me = FIRST (Covariance);
-	TableOfReal thee = FIRST (TableOfReal);
-	praat_new (Covariance_and_TableOfReal_mahalanobis (me, thee, GET_INTEGER (U"Centroid from table")), U"mahalanobis");
-END
+	CONVERT_TWO (Covariance, TableOfReal)
+		autoTableOfReal result = Covariance_and_TableOfReal_mahalanobis (me, you, centroidFromTable);
+	CONVERT_TWO_END (U"mahalanobis")
+}
 
 /********************** Discriminant **********************************/
 
-DIRECT (Discriminant_help)
-	Melder_help (U"Discriminant");
-END
+DIRECT (HELP_Discriminant_help) {
+	HELP (U"Discriminant")
+}
 
-DIRECT (Discriminant_setGroupLabels)
-	Discriminant me = FIRST (Discriminant);
-	Strings ss = FIRST (Strings);
-	Discriminant_setGroupLabels (me, ss);
-	praat_dataChanged (me);
-END
+DIRECT (MODIFY_Discriminant_setGroupLabels) {
+	MODIFY_FIRST_OF_TWO (Discriminant, Strings)
+		Discriminant_setGroupLabels (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (Discriminant_and_PatternList_to_Categories, U"Discriminant & PatternList: To Categories", U"Discriminant & PatternList: To Categories...")
-	BOOLEAN (U"Pool covariance matrices", true)
-	BOOLEAN (U"Use apriori probabilities", true)
+FORM (NEW1_Discriminant_and_PatternList_to_Categories, U"Discriminant & PatternList: To Categories", U"Discriminant & PatternList: To Categories...") {
+	BOOLEANVAR (poolCovariances, U"Pool covariance matrices", true)
+	BOOLEANVAR (useAPrioriProbabilities, U"Use apriori probabilities", true)
 	OK
 DO
-	Discriminant me = FIRST (Discriminant);
-	PatternList pat = FIRST (PatternList);
-	autoCategories thee = Discriminant_and_PatternList_to_Categories (me, pat, GET_INTEGER (U"Pool covariance matrices"), GET_INTEGER (U"Use apriori probabilities"));
-	praat_new (thee.move(), my name, U"_", pat->name);
-END
+	CONVERT_TWO (Discriminant, PatternList)
+		autoCategories result = Discriminant_and_PatternList_to_Categories (me, you, poolCovariances, useAPrioriProbabilities);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (Discriminant_and_TableOfReal_to_Configuration, U"Discriminant & TableOfReal: To Configuration", U"Discriminant & TableOfReal: To Configuration...")
-		INTEGER (U"Number of dimensions", U"0")
+FORM (NEW1_Discriminant_and_TableOfReal_to_Configuration, U"Discriminant & TableOfReal: To Configuration", U"Discriminant & TableOfReal: To Configuration...") {
+		INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0")
 		OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions");
-	REQUIRE (dimension >= 0, U"Number of dimensions must be greater equal zero.")
-	Discriminant me = FIRST (Discriminant);
-	TableOfReal tr = FIRST_GENERIC (TableOfReal);
-	autoConfiguration thee = Discriminant_and_TableOfReal_to_Configuration (me, tr, dimension);
-	praat_new (thee.move(), my name, U"_", tr->name);
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_TWO (Discriminant, TableOfReal)
+		autoConfiguration result = Discriminant_and_TableOfReal_to_Configuration (me, you, numberOfDimensions);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-DIRECT (hint_Discriminant_and_TableOfReal_to_ClassificationTable)
+DIRECT (hint_Discriminant_and_TableOfReal_to_ClassificationTable) {
 	Melder_information (U"You can use the Discriminant as a classifier by \nselecting a Discriminant and a TableOfReal object together.");
-END
+END }
 
-FORM (Discriminant_and_TableOfReal_to_ClassificationTable, U"Discriminant & TableOfReal: To ClassificationTable", U"Discriminant & TableOfReal: To ClassificationTable...")
-	BOOLEAN (U"Pool covariance matrices", true)
-	BOOLEAN (U"Use apriori probabilities", true)
+FORM (NEW1_Discriminant_and_TableOfReal_to_ClassificationTable, U"Discriminant & TableOfReal: To ClassificationTable", U"Discriminant & TableOfReal: To ClassificationTable...") {
+	BOOLEANVAR (poolCovariances, U"Pool covariance matrices", true)
+	BOOLEANVAR (useAPrioriProbabilities, U"Use apriori probabilities", true)
 	OK
 DO
-	Discriminant me = FIRST (Discriminant);
-	TableOfReal tr = FIRST_GENERIC (TableOfReal);
-	autoClassificationTable thee = Discriminant_and_TableOfReal_to_ClassificationTable (me, tr,
-		GET_INTEGER (U"Pool covariance matrices"), GET_INTEGER (U"Use apriori probabilities"));
-	praat_new (thee.move(), my name, U"_", tr->name);
-END
+	CONVERT_TWO (Discriminant, TableOfReal)
+		autoClassificationTable result = Discriminant_and_TableOfReal_to_ClassificationTable (me, you, poolCovariances, useAPrioriProbabilities);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (Discriminant_and_TableOfReal_mahalanobis, U"Discriminant & TableOfReal: To TableOfReal (mahalanobis)", U"Discriminant & TableOfReal: To TableOfReal (mahalanobis)...")
-	SENTENCE (U"Group label", U"")
-	BOOLEAN (U"Pool covariance matrices", false)
+FORM (NEW1_Discriminant_and_TableOfReal_mahalanobis, U"Discriminant & TableOfReal: To TableOfReal (mahalanobis)", U"Discriminant & TableOfReal: To TableOfReal (mahalanobis)...") {
+	SENTENCEVAR (groupLabel, U"Group label", U"")
+	BOOLEANVAR (poolCovariances, U"Pool covariance matrices", false)
 	OK
 DO
-	Discriminant me = FIRST (Discriminant);
-	TableOfReal tr = FIRST (TableOfReal);
-	long group = Discriminant_groupLabelToIndex (me, GET_STRING (U"Group label"));
-	REQUIRE (group > 0, U"Group label does not exist.")
-	autoTableOfReal thee = Discriminant_and_TableOfReal_mahalanobis (me, tr, group, GET_INTEGER (U"Pool covariance matrices"));
-	praat_new (thee.move(), U"mahalanobis");
-END
+	CONVERT_TWO (Discriminant, TableOfReal)
+		long group = Discriminant_groupLabelToIndex (me, groupLabel);
+		REQUIRE (group > 0, U"Group label does not exist.")
+		autoTableOfReal result = Discriminant_and_TableOfReal_mahalanobis (me, you, group, poolCovariances);
+	CONVERT_TWO_END (U"mahalanobis")
+}
 
-DIRECT (Discriminant_getNumberOfEigenvalues)
-	LOOP {
-		iam (Discriminant);
-		Melder_information (my eigen -> numberOfEigenvalues);
-	}
-END
+DIRECT (INTEGER_Discriminant_getNumberOfEigenvalues) {
+	INTEGER_ONE (Discriminant)
+		long result = my eigen -> numberOfEigenvalues;
+	INTEGER_ONE_END (U" (number of eigenvalues)")
+}
 
-DIRECT (Discriminant_getDimension)
-	LOOP {
-		iam (Discriminant);
-		Melder_information (my eigen -> dimension);
-	}
-END
+DIRECT (INTEGER_Discriminant_getDimension) {
+	INTEGER_ONE (Discriminant)
+		long result = my eigen -> dimension;
+	INTEGER_ONE_END (U" (dimension)")
+}
 
-FORM (Discriminant_getEigenvalue, U"Discriminant: Get eigenvalue", U"Eigen: Get eigenvalue...")
-	NATURAL (U"Eigenvalue number", U"1")
+FORM (REAL_Discriminant_getEigenvalue, U"Discriminant: Get eigenvalue", U"Eigen: Get eigenvalue...") {
+	NATURALVAR (eigenvalueNumber, U"Eigenvalue number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		long number = GET_INTEGER (U"Eigenvalue number");
-		if (number > my eigen -> numberOfEigenvalues) {
+	NUMBER_ONE (Discriminant)
+		if (eigenvalueNumber > my eigen -> numberOfEigenvalues) {
 			Melder_throw (U"Eigenvalue number must be smaller than ", my eigen -> numberOfEigenvalues + 1);
 		}
-		Melder_information (my eigen -> eigenvalues[number]);
-	}
-END
+		long result = my eigen -> eigenvalues[eigenvalueNumber];
+	NUMBER_ONE_END (U" (eigenvalue [)", eigenvalueNumber, U"])")
+}
 
-FORM (Discriminant_getSumOfEigenvalues, U"Discriminant:Get sum of eigenvalues", U"Eigen: Get sum of eigenvalues...")
-	INTEGER (U"left Eigenvalue range",  U"0")
-	INTEGER (U"right Eigenvalue range", U"0")
+FORM (REAL_Discriminant_getSumOfEigenvalues, U"Discriminant:Get sum of eigenvalues", U"Eigen: Get sum of eigenvalues...") {
+	INTEGERVAR (fromEigenvalue, U"left Eigenvalue range",  U"0")
+	INTEGERVAR (toEigenvalue, U"right Eigenvalue range", U"0")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Eigen_getSumOfEigenvalues (my eigen.get(), GET_INTEGER (U"left Eigenvalue range"), GET_INTEGER (U"right Eigenvalue range")));
-	}
-END
+	NUMBER_ONE (Discriminant)
+		double result = Eigen_getSumOfEigenvalues (my eigen.get(), fromEigenvalue, toEigenvalue);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (Discriminant_getEigenvectorElement, U"Discriminant: Get eigenvector element", U"Eigen: Get eigenvector element...")
-	NATURAL (U"Eigenvector number", U"1")
-	NATURAL (U"Element number", U"1")
+FORM (REAL_Discriminant_getEigenvectorElement, U"Discriminant: Get eigenvector element", U"Eigen: Get eigenvector element...") {
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
+	NATURALVAR (elementNumber, U"Element number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Eigen_getEigenvectorElement (my eigen.get(), GET_INTEGER (U"Eigenvector number"), GET_INTEGER (U"Element number")));
-	}
-END
+	NUMBER_ONE (Discriminant)
+		double result = Eigen_getEigenvectorElement (my eigen.get(), eigenvectorNumber, elementNumber);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (Discriminant_getWilksLambda, U"Discriminant: Get Wilks' lambda", U"Discriminant: Get Wilks' lambda...")
+FORM (REAL_Discriminant_getWilksLambda, U"Discriminant: Get Wilks' lambda", U"Discriminant: Get Wilks' lambda...") {
 	LABEL (U"", U"Product (i=from..numberOfEigenvalues, 1 / (1 + eigenvalue[i]))")
-	INTEGER (U"From", U"1")
+	INTEGERVAR (from, U"From", U"1") //TODO better name
 	OK
 DO
-	long from = GET_INTEGER (U"From");
 	REQUIRE (from >= 1, U"Number must be greater than or equal to one.")
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Discriminant_getWilksLambda (me, from));
-	}
-END
+	NUMBER_ONE (Discriminant)
+		double result = Discriminant_getWilksLambda (me, from);
+	NUMBER_ONE_END (U" (wilks lambda)")
+}
 
-FORM (Discriminant_getCumulativeContributionOfComponents, U"Discriminant: Get cumulative contribution of components", U"Eigen: Get cumulative contribution of components...")
-	NATURAL (U"From component", U"1")
-	NATURAL (U"To component", U"1")
+FORM (REAL_Discriminant_getCumulativeContributionOfComponents, U"Discriminant: Get cumulative contribution of components", U"Eigen: Get cumulative contribution of components...") {
+	NATURALVAR (fromComponent, U"From component", U"1")
+	NATURALVAR (toComponent, U"To component", U"1")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Eigen_getCumulativeContributionOfComponents (my eigen.get(),
-			GET_INTEGER (U"From component"), GET_INTEGER (U"To component")));
-	}
-END
+	NUMBER_ONE (Discriminant)
+		double result = Eigen_getCumulativeContributionOfComponents (my eigen.get(), fromComponent, toComponent);
+	NUMBER_ONE_END (U" (cumulative contribution)")
+}
 
 
-FORM (Discriminant_getPartialDiscriminationProbability, U"Discriminant: Get partial discrimination probability", U"Discriminant: Get partial discrimination probability...")
-	INTEGER (U"Number of dimensions", U"1")
+FORM (REAL_Discriminant_getPartialDiscriminationProbability, U"Discriminant: Get partial discrimination probability", U"Discriminant: Get partial discrimination probability...") {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"1")
 	OK
 DO
-	long n = GET_INTEGER (U"Number of dimensions");
-	REQUIRE (n >= 0, U"Number of dimensions must be greater than or equal to zero.")
-	LOOP {
-		iam (Discriminant);
-		double p, chisq, df;
-		Discriminant_getPartialDiscriminationProbability (me, n, & p, & chisq, & df);
-		Melder_information (p, U" (= probability, based on chisq = ", chisq, U"and ndf = ", df, U")");
-	}
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater than or equal to zero.")
+	NUMBER_ONE (Discriminant)
+		double result, chisq, df;
+		Discriminant_getPartialDiscriminationProbability (me, numberOfDimensions, & result, & chisq, & df);
+	NUMBER_ONE_END (U" (= probability, based on chisq = ", chisq, U" and ndf = ", df, U")");
+}
 
-DIRECT (Discriminant_getHomegeneityOfCovariances_box)
-	LOOP {
-		iam (Discriminant);
-		double chisq, p; double ndf;
-		SSCPList_getHomegeneityOfCovariances_box (my groups.get(), &p, &chisq, &ndf);
-		Melder_information (p, U" (= probability, based on chisq = ",
-			chisq, U"and ndf = ", ndf, U")");
-	}
-END
+DIRECT (REAL_Discriminant_getHomegeneityOfCovariances_box) {
+	NUMBER_ONE (Discriminant)
+		double chisq, result, ndf;
+		SSCPList_getHomegeneityOfCovariances_box (my groups.get(), & result, & chisq, & ndf);
+	NUMBER_ONE_END (U" (= probability, based on chisq = ", chisq, U" and ndf = ", ndf, U")")
+}
 
-DIRECT (Discriminant_reportEqualityOfCovariances_wald)
+DIRECT (INFO_Discriminant_reportEqualityOfCovariances_wald) {
 	MelderInfo_open ();
 	LOOP {
 		iam (Discriminant);
@@ -1479,796 +1270,567 @@ DIRECT (Discriminant_reportEqualityOfCovariances_wald)
 		MelderInfo_writeLine (U"Number of matrices: ", list.size);
 	}
 	MelderInfo_close ();
-END
+END }
 
-FORM (Discriminant_getConcentrationEllipseArea, U"Discriminant: Get concentration ellipse area", U"Discriminant: Get concentration ellipse area...")
-	SENTENCE (U"Group label", U"")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	BOOLEAN (U"Discriminant plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
+FORM (REAL_Discriminant_getConcentrationEllipseArea, U"Discriminant: Get concentration ellipse area", U"Discriminant: Get concentration ellipse area...") {
+	SENTENCEVAR (groupLabel, U"Group label", U"")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	BOOLEANVAR (discriminatPlane, U"Discriminant plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		long group = Discriminant_groupLabelToIndex (me, GET_STRING (U"Group label"));
+	NUMBER_ONE (Discriminant)
+		long group = Discriminant_groupLabelToIndex (me, groupLabel);
 		REQUIRE (group > 0, U"Group label does not exist.")
-		Melder_information (Discriminant_getConcentrationEllipseArea (me,
-			group,
-			GET_REAL (U"Number of sigmas"),
-			false,   // confidence
-			GET_INTEGER (U"Discriminant plane"),
-			GET_INTEGER (U"X-dimension"),
-			GET_INTEGER (U"Y-dimension")));
-	}
-END
+		double result = Discriminant_getConcentrationEllipseArea (me, group, numberOfSigmas, false, discriminatPlane, xDimension, yDimension);
+	NUMBER_ONE_END (U" (concentration ellipse area)")
+}
 
-FORM (Discriminant_getConfidenceEllipseArea, U"Discriminant: Get confidence ellipse area", U"Discriminant: Get confidence ellipse area...")
-	SENTENCE (U"Group label", U"")
-	POSITIVE (U"Confidence level (0-1)", U"0.95")
-	BOOLEAN (U"Discriminant plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
+FORM (REAL_Discriminant_getConfidenceEllipseArea, U"Discriminant: Get confidence ellipse area", U"Discriminant: Get confidence ellipse area...") {
+	SENTENCEVAR (groupLabel, U"Group label", U"")
+	POSITIVEVAR (confidenceLevel, U"Confidence level (0-1)", U"0.95")
+	BOOLEANVAR (discriminatPlane, U"Discriminant plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		long group = Discriminant_groupLabelToIndex (me, GET_STRING (U"Group label"));
+	NUMBER_ONE (Discriminant)
+		long group = Discriminant_groupLabelToIndex (me, groupLabel);
 		REQUIRE (group > 0, U"Group label does not exist.")
-		Melder_information (Discriminant_getConcentrationEllipseArea (me,
-			group,
-			GET_REAL (U"Confidence level"),
-			true,    //confidence
-			GET_INTEGER (U"Discriminant plane"),
-			GET_INTEGER (U"X-dimension"),
-			GET_INTEGER (U"Y-dimension")));
-	}
-END
+		double result = Discriminant_getConcentrationEllipseArea (me, group, confidenceLevel, true, discriminatPlane, xDimension, yDimension);
+	NUMBER_ONE_END (U" (confidence ellipse area)")
+}
 
-FORM (Discriminant_getLnDeterminant_group, U"Discriminant: Get determinant (group)", U"Discriminant: Get determinant (group)...")
-	SENTENCE (U"Group label", U"")
+FORM (REAL_Discriminant_getLnDeterminant_group, U"Discriminant: Get determinant (group)", U"Discriminant: Get determinant (group)...")
+	SENTENCEVAR (groupLabel, U"Group label", U"") {
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		long group = Discriminant_groupLabelToIndex (me, GET_STRING (U"Group label"));
+	NUMBER_ONE (Discriminant)
+		long group = Discriminant_groupLabelToIndex (me, groupLabel);
 		REQUIRE (group > 0, U"Group label does not exist.")
-		Melder_information (Discriminant_getLnDeterminant_group (me, group));
-	}
-END
+		double result = Discriminant_getLnDeterminant_group (me, group);
+	NUMBER_ONE_END (U" (ln(determinant) group")
+}
 
-DIRECT (Discriminant_getLnDeterminant_total)
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Discriminant_getLnDeterminant_total (me));
-	}
-END
+DIRECT (REAL_Discriminant_getLnDeterminant_total) {
+	NUMBER_ONE (Discriminant)
+		double result = Discriminant_getLnDeterminant_total (me);
+	NUMBER_ONE_END (U" (ln(determinant) total")
+}
 
-FORM (Discriminant_invertEigenvector, U"Discriminant: Invert eigenvector", nullptr)
-	NATURAL (U"Index of eigenvector", U"1")
+FORM (MODIFY_Discriminant_invertEigenvector, U"Discriminant: Invert eigenvector", nullptr) {
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
+	MODIFY_EACH (Discriminant)
 		Eigen_invertEigenvector (my eigen.get(), GET_INTEGER (U"Index of eigenvector"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Discriminant_drawEigenvalues, U"Discriminant: Draw eigenvalues", U"Eigen: Draw eigenvalues...")
-	INTEGER (U"left Eigenvalue range", U"0")
-	INTEGER (U"right Eigenvalue range", U"0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Fraction of eigenvalues summed", false)
-	BOOLEAN (U"Cumulative", false)
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Discriminant);
-		Eigen_drawEigenvalues (my eigen.get(), GRAPHICS,
-			GET_INTEGER (U"left Eigenvalue range"),
-			GET_INTEGER (U"right Eigenvalue range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Fraction of eigenvalues summed"),
-			GET_INTEGER (U"Cumulative"),
-			GET_REAL (U"Mark size"),
-			GET_STRING (U"Mark string"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Discriminant_drawEigenvector, U"Discriminant: Draw eigenvector", U"Eigen: Draw eigenvector...")
-	INTEGER (U"Eigenvector number", U"1")
-	BOOLEAN (U"Component loadings", false)
-	INTEGER (U"left Element range", U"0")
-	INTEGER (U"right Element range", U"0")
-	REAL (U"left Amplitude range", U"-1.0")
-	REAL (U"right Amplitude range", U"1.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Connect points", true)
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Discriminant);
-		Eigen_drawEigenvector (my eigen.get(), GRAPHICS,
-			GET_INTEGER (U"Eigenvector number"),
-			GET_INTEGER (U"left Element range"),
-			GET_INTEGER (U"right Element range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Component loadings"),
-			GET_REAL (U"Mark size"),
-			GET_STRING (U"Mark string"),
-			GET_INTEGER (U"Connect points"),
-			nullptr,   // rowLabels
-			GET_INTEGER (U"Garnish"));
-	}
-END
+FORM (GRAPHICS_Discriminant_drawEigenvalues, U"Discriminant: Draw eigenvalues", U"Eigen: Draw eigenvalues...") {
+	INTEGERVAR (fromEigenvalue, U"left Eigenvalue range", U"0")
+	INTEGERVAR (toEigenvalue, U"right Eigenvalue range", U"0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (showFractions, U"Fraction of eigenvalues summed", false)
+	BOOLEANVAR (showCumulativeValues, U"Cumulative", false)
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Discriminant)
+		Eigen_drawEigenvalues (my eigen.get(), GRAPHICS, fromEigenvalue, toEigenvalue, fromAmplitude, toAmplitude, showFractions, showCumulativeValues, markSize_mm, mark_string, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Discriminant_drawEigenvector, U"Discriminant: Draw eigenvector", U"Eigen: Draw eigenvector...") {
+	INTEGERVAR (eigenvectorNumber, U"Eigenvector number", U"1")
+	BOOLEANVAR (componentLoadings, U"Component loadings", false)
+	INTEGERVAR (fromElement, U"left Element range", U"0")
+	INTEGERVAR (toElement, U"right Element range", U"0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"-1.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"1.0")
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (connectPoints, U"Connect points", true)
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Discriminant)
+		Eigen_drawEigenvector (my eigen.get(), GRAPHICS, eigenvectorNumber, fromElement, toElement, fromAmplitude, toAmplitude, componentLoadings, markSize_mm, mark_string, connectPoints, nullptr,  garnish);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (Discriminant_drawSigmaEllipses, U"Discriminant: Draw sigma ellipses", U"Discriminant: Draw sigma ellipses...")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	BOOLEAN (U"Discriminant plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Discriminant_drawSigmaEllipses, U"Discriminant: Draw sigma ellipses", U"Discriminant: Draw sigma ellipses...") {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	BOOLEANVAR (discriminantPlane, U"Discriminant plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Discriminant);
-		Discriminant_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Number of sigmas"),
-			false,   // confidence
-			nullptr,   // label
-			GET_INTEGER (U"Discriminant plane"),
-			GET_INTEGER (U"X-dimension"),
-			GET_INTEGER (U"Y-dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Discriminant_drawOneSigmaEllipse, U"Discriminant: Draw one sigma ellipse", U"Discriminant: Draw one sigma ellipse...")
-	SENTENCE (U"Label", U"")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	BOOLEAN (U"Discriminant plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Discriminant);
-		Discriminant_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Number of sigmas"),
-			false,   // confidence
-			GET_STRING (U"Label"),
-			GET_INTEGER (U"Discriminant plane"),
-			GET_INTEGER (U"X-dimension"),
-			GET_INTEGER (U"Y-dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Discriminant_drawConfidenceEllipses, U"Discriminant: Draw confidence ellipses", nullptr)
-	POSITIVE (U"Confidence level (0-1)", U"0.95")
-	BOOLEAN (U"Discriminant plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Discriminant);
-		Discriminant_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Confidence level"),
-			true,   // confidence
-			nullptr,   // label
-			GET_INTEGER (U"Discriminant plane"),
-			GET_INTEGER (U"X-dimension"),
-			GET_INTEGER (U"Y-dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Discriminant)
+		Discriminant_drawConcentrationEllipses (me, GRAPHICS, numberOfSigmas, false, nullptr, discriminantPlane, xDimension, yDimension,xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
+FORM (GRAPHICS_Discriminant_drawOneSigmaEllipse, U"Discriminant: Draw one sigma ellipse", U"Discriminant: Draw one sigma ellipse...") {
+	SENTENCEVAR (label, U"Label", U"")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	BOOLEANVAR (discriminatPlane, U"Discriminant plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Discriminant)
+		Discriminant_drawConcentrationEllipses (me, GRAPHICS, numberOfSigmas, false,  label, discriminatPlane, xDimension, yDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Discriminant_drawOneConfidenceEllipse, U"Discriminant: Draw one confidence ellipse", nullptr)
-	SENTENCE (U"Label", U"")
-	POSITIVE (U"Confidence level (0-1)", U"0.95")
-	BOOLEAN (U"Discriminant plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Discriminant);
-		Discriminant_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Confidence level"),
-			true,   // confidence
-			GET_STRING (U"Label"),
-			GET_INTEGER (U"Discriminant plane"),
-			GET_INTEGER (U"X-dimension"),
-			GET_INTEGER (U"Y-dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+FORM (GRAPHICS_Discriminant_drawConfidenceEllipses, U"Discriminant: Draw confidence ellipses", nullptr) {
+	POSITIVEVAR (confidenceLevel, U"Confidence level (0-1)", U"0.95")
+	BOOLEANVAR (discriminatPlane, U"Discriminant plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Discriminant)
+		Discriminant_drawConcentrationEllipses (me, GRAPHICS, confidenceLevel, true, nullptr, discriminatPlane, xDimension, yDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Discriminant_extractBetweenGroupsSSCP)
-	LOOP {
-		iam (Discriminant);
-		autoSSCP thee = Discriminant_extractBetweenGroupsSSCP (me);
-		praat_new (thee.move());
-	}
-END
+FORM (GRAPHICS_Discriminant_drawOneConfidenceEllipse, U"Discriminant: Draw one confidence ellipse", nullptr) {
+	SENTENCEVAR (label, U"Label", U"")
+	POSITIVEVAR (confidenceLevel, U"Confidence level (0-1)", U"0.95")
+	BOOLEANVAR (discriminatPlane, U"Discriminant plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Discriminant)
+		Discriminant_drawConcentrationEllipses (me, GRAPHICS, confidenceLevel, true, label, discriminatPlane, xDimension, yDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Discriminant_extractGroupCentroids)
-	LOOP {
-		iam (Discriminant);
-		autoTableOfReal thee = Discriminant_extractGroupCentroids (me);
-		praat_new (thee.move(), U"centroids");
-	}
-END
+DIRECT (NEW_Discriminant_extractBetweenGroupsSSCP) {
+	CONVERT_EACH (Discriminant)
+		autoSSCP result = Discriminant_extractBetweenGroupsSSCP (me);
+	CONVERT_EACH_END (my name, U"_between")
+}
 
-DIRECT (Discriminant_extractGroupStandardDeviations)
-	LOOP {
-		iam (Discriminant);
-		autoTableOfReal thee = Discriminant_extractGroupStandardDeviations (me);
-		praat_new (thee.move(), U"group_stddevs");
-	}
-END
+DIRECT (NEW_Discriminant_extractGroupCentroids) {
+	CONVERT_EACH (Discriminant)
+		autoTableOfReal result = Discriminant_extractGroupCentroids (me);
+	CONVERT_EACH_END (my name, U"_centroids")
+}
 
-DIRECT (Discriminant_extractGroupLabels)
-	LOOP {
-		iam (Discriminant);
-		autoStrings thee = Discriminant_extractGroupLabels (me);
-		praat_new (thee.move(), U"group_labels");
-	}
-END
+DIRECT (NEW_Discriminant_extractGroupStandardDeviations) {
+	CONVERT_EACH (Discriminant)
+		autoTableOfReal result = Discriminant_extractGroupStandardDeviations (me);
+	CONVERT_EACH_END (U"group_stddevs")
+}
 
-DIRECT (Discriminant_extractPooledWithinGroupsSSCP)
-	LOOP {
-		iam (Discriminant);
-		autoSSCP thee = Discriminant_extractPooledWithinGroupsSSCP (me);
-		praat_new (thee.move(), U"pooled_within");
-	}
-END
+DIRECT (NEW_Discriminant_extractGroupLabels) {
+	CONVERT_EACH (Discriminant)
+		autoStrings result = Discriminant_extractGroupLabels (me);
+	CONVERT_EACH_END (U"group_labels")
+}
+
+DIRECT (NEW_Discriminant_extractEigen) {
+	CONVERT_EACH (Discriminant)
+		autoEigen result = Data_copy (my eigen.get());
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Discriminant_extractWithinGroupSSCP, U"Discriminant: Extract within-group SSCP", U"Discriminant: Extract within-group SSCP...")
-	NATURAL (U"Group index", U"1")
+DIRECT (NEW_Discriminant_extractPooledWithinGroupsSSCP) {
+	CONVERT_EACH (Discriminant)
+		autoSSCP result = Discriminant_extractPooledWithinGroupsSSCP (me);
+	CONVERT_EACH_END (U"pooled_within")
+}
+
+FORM (NEW_Discriminant_extractWithinGroupSSCP, U"Discriminant: Extract within-group SSCP", U"Discriminant: Extract within-group SSCP...") {
+	NATURALVAR (groupIndex, U"Group index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Group index");
-	LOOP {
-		iam (Discriminant);
-		autoSSCP thee = Discriminant_extractWithinGroupSSCP (me, index);
-		praat_new (thee.move(), my name, U"_g", index);
-	}
-END
+	CONVERT_EACH (Discriminant)
+		autoSSCP result = Discriminant_extractWithinGroupSSCP (me, groupIndex);
+	CONVERT_EACH_END (my name, U"_g", groupIndex)
+}
 
-DIRECT (Discriminant_getNumberOfFunctions)
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Discriminant_getNumberOfFunctions (me));
-	}
-END
+DIRECT (INTEGER_Discriminant_getNumberOfFunctions) {
+	INTEGER_ONE (Discriminant)
+		long result = Discriminant_getNumberOfFunctions (me);
+	INTEGER_ONE_END (U"")
+}
 
-DIRECT (Discriminant_getDimensionOfFunctions)
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Eigen_getDimensionOfComponents (my eigen.get()));
-	}
-END
+DIRECT (INTEGER_Discriminant_getDimensionOfFunctions) {
+	INTEGER_ONE (Discriminant)
+		long result = Eigen_getDimensionOfComponents (my eigen.get());
+	INTEGER_ONE_END (U"")
+}
 
-DIRECT (Discriminant_getNumberOfGroups)
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Discriminant_getNumberOfGroups (me));
-	}
-END
+DIRECT (INTEGER_Discriminant_getNumberOfGroups) {
+	INTEGER_ONE (Discriminant)
+		long result = Discriminant_getNumberOfGroups (me);
+	INTEGER_ONE_END (U"")
+}
 
-FORM (Discriminant_getNumberOfObservations, U"Discriminant: Get number of observations", U"Discriminant: Get number of observations...")
-	INTEGER (U"Group", U"0 (= total)")
+FORM (INTEGER_Discriminant_getNumberOfObservations, U"Discriminant: Get number of observations", U"Discriminant: Get number of observations...") {
+	INTEGERVAR (group, U"Group", U"0 (= total)")
 	OK
 DO
-	LOOP {
-		iam (Discriminant);
-		Melder_information (Discriminant_getNumberOfObservations (me, GET_INTEGER (U"Group")));
-	}
-END
+	INTEGER_ONE (Discriminant)
+		long result = Discriminant_getNumberOfObservations (me, group);
+	INTEGER_ONE_END (U"")
+}
 
 
 /********************** DTW *******************************************/
 
-FORM (DTW_and_Polygon_findPathInside, U"DTW & Polygon: Find path inside", nullptr)
-    RADIO (U"Slope constraint", 1)
+FORM (MODIFY_DTW_and_Polygon_findPathInside, U"DTW & Polygon: Find path inside", nullptr) {
+    RADIOVAR (slopeConstraint, U"Slope constraint", 1)
 		RADIOBUTTON (U"no restriction")
 		RADIOBUTTON (U"1/3 < slope < 3")
 		RADIOBUTTON (U"1/2 < slope < 2")
 		RADIOBUTTON (U"2/3 < slope < 3/2")
     OK
 DO
-    int localSlope = GET_INTEGER (U"Slope constraint");
-    DTW me = FIRST (DTW);
-    Polygon thee = FIRST (Polygon);
-    DTW_and_Polygon_findPathInside (me, thee, localSlope, 0);
-
-END
+	MODIFY_FIRST_OF_TWO (DTW, Polygon)
+		DTW_and_Polygon_findPathInside (me, you, slopeConstraint, 0);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (DTW_and_Polygon_to_Matrix_cummulativeDistances, U"DTW & Polygon: To Matrix (cumm. distances)", nullptr)
-    RADIO (U"Slope constraint", 1)
+FORM (NEW1_DTW_and_Polygon_to_Matrix_cummulativeDistances, U"DTW & Polygon: To Matrix (cumm. distances)", nullptr) {
+    RADIOVAR (slopeConstraint, U"Slope constraint", 1)
 		RADIOBUTTON (U"no restriction")
 		RADIOBUTTON (U"1/3 < slope < 3")
 		RADIOBUTTON (U"1/2 < slope < 2")
 		RADIOBUTTON (U"2/3 < slope < 3/2")
     OK
 DO
-    int localSlope = GET_INTEGER (U"Slope constraint");
-    DTW me = FIRST (DTW);
-    Polygon thee = FIRST (Polygon);
-    autoMatrix him = DTW_and_Polygon_to_Matrix_cummulativeDistances (me, thee, localSlope);
-    praat_new (him.move(), my name, U"_", localSlope);
-END
+    CONVERT_TWO (DTW, Polygon)
+		autoMatrix result = DTW_and_Polygon_to_Matrix_cummulativeDistances (me, you, slopeConstraint);
+     CONVERT_TWO_END (my name, U"_", slopeConstraint);
+}
 
-FORM (DTW_and_Sounds_draw, U"DTW & Sounds: Draw", U"DTW & Sounds: Draw...")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_DTW_and_Sounds_draw, U"DTW & Sounds: Draw", U"DTW & Sounds: Draw...") {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	Sound s1 = nullptr, s2 = nullptr;
-	DTW dtw = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classSound) {
-			(s1 ? s2 : s1) = (Sound) me;
-		} else if (CLASS == classDTW) {
-			dtw = (DTW) me;
-		}
-	}
-	Melder_assert (s1 && s2 && dtw);
-	autoPraatPicture picture;
-	DTW_and_Sounds_draw (dtw, s2, s1, GRAPHICS, GET_REAL (U"left Horizontal range"),
-		GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (DTW_and_Sounds_drawWarpX, U"DTW & Sounds: Draw warp (x)", U"DTW & Sounds: Draw warp (x)...")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Time (s)", U"0.1")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	DTW dtw = FIRST (DTW);
-	autoPraatPicture picture;
-	DTW_and_Sounds_drawWarpX (dtw, s2, s1, GRAPHICS,
-		GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_REAL (U"Time"), GET_INTEGER (U"Garnish"));
-END
-
-void DTW_constraints_addCommonFields (UiForm dia) {
-	UiField radio;
-	LABEL (U"", U"Boundary conditions")
-	BOOLEAN (U"Match begin positions", false)
-	BOOLEAN (U"Match end positions", false)
-	RADIO (U"Slope constraint", 1)
-		RADIOBUTTON (U"no restriction")
-		RADIOBUTTON (U"1/3 < slope < 3")
-		RADIOBUTTON (U"1/2 < slope < 2")
-		RADIOBUTTON (U"2/3 < slope < 3/2")
+	GRAPHICS_COUPLE_AND_ONE (Sound, DTW)
+		DTW_and_Sounds_draw (him, you, me, GRAPHICS, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_COUPLE_AND_ONE_END
 }
 
-void DTW_constraints_getCommonFields (UiForm dia, int *begin, int *end, int *slope) {
-	*begin = GET_INTEGER (U"Match begin positions");
-	*end = GET_INTEGER (U"Match end positions");
-	*slope = GET_INTEGER (U"Slope constraint");
+FORM (GRAPHICS_DTW_and_Sounds_drawWarpX, U"DTW & Sounds: Draw warp (x)", U"DTW & Sounds: Draw warp (x)...") {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (time, U"Time (s)", U"0.1")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_COUPLE_AND_ONE (Sound, DTW)
+		DTW_and_Sounds_drawWarpX (him, you, me, GRAPHICS, xmin, xmax, ymin, ymax, time, garnish);
+	GRAPHICS_COUPLE_AND_ONE_END
 }
 
-DIRECT (DTW_help) Melder_help (U"DTW"); END
+DIRECT (HELP_DTW_help) {
+	HELP (U"DTW")
+}
 
-FORM (DTW_drawPath, U"DTW: Draw path", nullptr)
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", false);
+FORM (GRAPHICS_DTW_drawPath, U"DTW: Draw path", nullptr) {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", false);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (DTW);
-		DTW_drawPath (me, GRAPHICS,
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DTW)
+		DTW_drawPath (me, GRAPHICS, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (DTW_drawDistancesAlongPath, U"DTW: Draw distances along path", nullptr)
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", false);
+FORM (GRAPHICS_DTW_drawDistancesAlongPath, U"DTW: Draw distances along path", nullptr) {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", false);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (DTW);
-		DTW_drawDistancesAlongPath (me,
-			GRAPHICS, GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DTW)
+		DTW_drawDistancesAlongPath (me, GRAPHICS, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (DTW_paintDistances, U"DTW: Paint distances", nullptr)
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	BOOLEAN (U"Garnish", false);
+FORM (GRAPHICS_DTW_paintDistances, U"DTW: Paint distances", nullptr) {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (minimum, U"Minimum", U"0.0")
+	REALVAR (maximum, U"Maximum", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", false);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (DTW);
-		DTW_paintDistances (me, GRAPHICS,
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Minimum"),
-			GET_REAL (U"Maximum"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DTW)
+		DTW_paintDistances (me, GRAPHICS, xmin, xmax, ymin, ymax, minimum, maximum, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (DTW_drawWarpX, U"DTW: Draw warp (x)", U"DTW: Draw warp (x)...")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Time (s)", U"0.1")
-	BOOLEAN (U"Garnish", false);
+FORM (GRAPHICS_DTW_drawWarpX, U"DTW: Draw warp (x)", U"DTW: Draw warp (x)...") {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (time, U"Time (s)", U"0.1")
+	BOOLEANVAR (garnish, U"Garnish", false);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (DTW);
-		DTW_drawWarpX (me, GRAPHICS,
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Time"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DTW)
+		DTW_drawWarpX (me, GRAPHICS, xmin, xmax, ymin, ymax, time, garnish);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (DTW_drawWarpY, U"DTW: Draw warp (y)", U"DTW: Draw warp (y)...")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Time (s)", U"0.1")
-	BOOLEAN (U"Garnish", false);
+FORM (GRAPHICS_DTW_drawWarpY, U"DTW: Draw warp (y)", U"DTW: Draw warp (y)...") {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (time, U"Time (s)", U"0.1")
+	BOOLEANVAR (garnish, U"Garnish", false);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (DTW);
-		DTW_drawWarpY (me, GRAPHICS,
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Time"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (DTW)
+		DTW_drawWarpY (me, GRAPHICS, xmin, xmax, ymin, ymax, time, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (DTW_getStartTimeX)
-	LOOP {
-		iam (DTW);
-		Melder_information (my xmin, U" s (= start time along x)");
-	}
-END
+DIRECT (REAL_DTW_getStartTimeX) {
+	NUMBER_ONE (DTW)
+		double result = my xmin;
+	NUMBER_ONE_END (U" s (= start time along x)")
+}
 
-DIRECT (DTW_getEndTimeX)
-	LOOP {
-		iam (DTW);
-		Melder_information (my xmax, U" s (= end time along x)");
-	}
-END
+DIRECT (REAL_DTW_getEndTimeX) {
+	NUMBER_ONE (DTW)
+		double result = my xmax;
+	NUMBER_ONE_END (U" s (= end time along x)");
+}
 
-DIRECT (DTW_getTotalDurationX)
-	LOOP {
-		iam (DTW);
-		Melder_information (my xmax - my xmin, U" s (= total duration along x)");
-	}
-END
+DIRECT (REAL_DTW_getTotalDurationX) {
+	NUMBER_ONE (DTW)
+		double result = my xmax - my xmin;
+	NUMBER_ONE_END (U" s (= total duration along x)");
+}
 
-DIRECT (DTW_getStartTimeY)
-	LOOP {
-		iam (DTW);
-		Melder_information (my ymin, U" s (= start time along y)");
-	}
-END
+DIRECT (REAL_DTW_getStartTimeY) {
+	NUMBER_ONE (DTW)
+		double result = my ymin;
+	NUMBER_ONE_END (U" s (= start time along y)");
+}
 
-DIRECT (DTW_getEndTimeY)
-	LOOP {
-		iam (DTW);
-		Melder_information (my ymax, U" s (= end time along y)");
-	}
-END
+DIRECT (REAL_DTW_getEndTimeY) {
+	NUMBER_ONE (DTW)
+		double result = my ymax;
+	NUMBER_ONE_END (U" s (= end time along y)");
+}
 
-DIRECT (DTW_getTotalDurationY)
-	LOOP {
-		iam (DTW);
-		Melder_information (my ymax - my ymin, U" s (= total duration along y)");
-	}
-END
+DIRECT (REAL_DTW_getTotalDurationY) {
+	NUMBER_ONE (DTW)
+		double result = my ymax - my ymin;
+	NUMBER_ONE_END (U" s (= total duration along y)")
+}
 
-DIRECT (DTW_getNumberOfFramesX)
-	LOOP {
-		iam (DTW);
-		Melder_information (my nx, U" (= number of frames along x)");
-	}
-END
+DIRECT (INTEGER_DTW_getNumberOfFramesX) {
+	INTEGER_ONE (DTW)
+		long result = my nx; 
+	INTEGER_ONE_END (U" (= number of frames along x)")
+}
 
-DIRECT (DTW_getTimeStepX)
-	LOOP {
-		iam (DTW);
-		Melder_information (my dx, U" s (= time step along x)");
-	}
-END
 
-FORM (DTW_getTimeFromFrameNumberX, U"DTW: Get time from frame number (x)", 0)
-	NATURAL (U"Frame number (x)", U"1")
+DIRECT (REAL_DTW_getTimeStepX) {
+	NUMBER_ONE (DTW)
+		double result = my dx;
+	NUMBER_ONE_END (U" s (= time step along x)")
+}
+
+FORM (REAL_DTW_getTimeFromFrameNumberX, U"DTW: Get time from frame number (x)", nullptr) {
+	NATURALVAR (frameNumber, U"Frame number (x)", U"1")
 	OK
 DO
-	long column = GET_INTEGER (U"Frame number");
-	LOOP {
-		iam (DTW);
-		Melder_information (Matrix_columnToX (me, column), U" s (= y time at x frame ", column, U")");
-	}
-END
+	NUMBER_ONE (DTW)
+		double result = Matrix_columnToX (me, frameNumber);
+	NUMBER_ONE_END (U" s (= y time at x frame ", frameNumber, U")")
+}
 
-FORM (DTW_getFrameNumberFromTimeX, U"DTW: Get frame number from time (x)", 0)
-	REAL (U"Time along x (s)", U"0.1")
+FORM (INTEGER_DTW_getFrameNumberFromTimeX, U"DTW: Get frame number from time (x)", nullptr) {
+	REALVAR (xTime, U"Time along x (s)", U"0.1")
 	OK
 DO
-	double time = GET_REAL (U"Time along x");
-	LOOP {
-		iam (DTW);
-		if (time < my xmin || time > my xmax) {
+	INTEGER_ONE (DTW)
+		if (xTime < my xmin || xTime > my xmax) {
 			Melder_throw (me, U"Time outside x domain.");
 		}
-		long iframe = lround (Matrix_xToColumn (me, time));
-		Melder_information (iframe, U" (= x frame at y time ", time, U")");
-	}
-END
+		long result = lround (Matrix_xToColumn (me, xTime));
+	INTEGER_ONE_END (U" (= x frame at y time ", xTime, U")")
+}
 
-DIRECT (DTW_getNumberOfFramesY)
-	LOOP {
-		iam (DTW);
-		Melder_information (my ny, U" (= number of frames along y)");
-	}
-END
+DIRECT (INTEGER_DTW_getNumberOfFramesY) {
+	INTEGER_ONE (DTW)
+		long result = my ny;
+	INTEGER_ONE_END (U" (= number of frames along y)")
+}
+
+DIRECT (REAL_DTW_getTimeStepY) {
+	NUMBER_ONE (DTW)
+		double result = my dy;
+	NUMBER_ONE_END (U" s (= time step along y)")
+}
 
-DIRECT (DTW_getTimeStepY)
-	LOOP {
-		iam (DTW);
-		Melder_information (my dy, U" s (= time step along y)");
-	}
-END
 
-FORM (DTW_getTimeFromFrameNumberY, U"DTW: Get time from frame number (y)", 0)
-	NATURAL (U"Frame number (y)", U"1")
+FORM (REAL_DTW_getTimeFromFrameNumberY, U"DTW: Get time from frame number (y)", nullptr) {
+	NATURALVAR (frameNumber, U"Frame number (y)", U"1")
 	OK
 DO
-	long row = GET_INTEGER (U"Frame number");
-	LOOP {
-		iam (DTW);
-		Melder_information (Matrix_rowToY (me, row), U" s (= x time at y frame ", row, U")");
-	}
-END
+	NUMBER_ONE (DTW)
+		double result = Matrix_rowToY (me, frameNumber);
+	NUMBER_ONE_END (U" s (= x time at y frame ", frameNumber, U")")
+}
 
-FORM (DTW_getFrameNumberFromTimeY, U"DTW: Get frame number from time (y)", 0)
-	REAL (U"Time along y (s)", U"0.1")
+FORM (INTEGER_DTW_getFrameNumberFromTimeY, U"DTW: Get frame number from time (y)", nullptr) {
+	REALVAR (yTime, U"Time along y (s)", U"0.1")
 	OK
 DO
-	double time = GET_REAL (U"Time along y");
-	LOOP {
-		iam (DTW);
-		if (time < my ymin || time > my ymax) {
+	INTEGER_ONE (DTW)
+		if (yTime < my ymin || yTime > my ymax) {
 			Melder_throw (me, U"Time outside y domain.");
 		}
-		long iframe = lround (Matrix_yToRow (me, time));
-		Melder_information (iframe, U" (= y frame at x time ", time, U")");
-	}
-END
-
+		long result = lround (Matrix_yToRow (me, yTime));
+	INTEGER_ONE_END (U" (= y frame at x time ", yTime, U")")
+}
 
-FORM (DTW_getPathY, U"DTW: Get time along path", U"DTW: Get time along path...")
-	REAL (U"Time (s)", U"0.0")
+FORM (REAL_DTW_getPathY, U"DTW: Get time along path", U"DTW: Get time along path...") {
+	REALVAR (xTime, U"Time (s)", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (DTW);
-		Melder_information (DTW_getYTimeFromXTime (me, GET_REAL (U"Time")));
-	}
-END
+	NUMBER_ONE (DTW)
+		double result = DTW_getYTimeFromXTime (me, xTime);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (DTW_getYTimeFromXTime, U"DTW: Get y time from x time", U"DTW: Get y time from x time...")
-	REAL (U"Time at x (s)", U"0.0")
+FORM (REAL_DTW_getYTimeFromXTime, U"DTW: Get y time from x time", U"DTW: Get y time from x time...") {
+	REALVAR (xTime, U"Time at x (s)", U"0.0")
 	OK
 DO
-	double time = GET_REAL (U"Time at x");
-	LOOP {
-		iam (DTW);
-		Melder_information (DTW_getYTimeFromXTime (me, time), U" s (= y time at x time ", time, U")");
-	}
-END
+	NUMBER_ONE (DTW)
+		double result = DTW_getYTimeFromXTime (me, xTime);
+	NUMBER_ONE_END (U" s (= y time at x time ", xTime, U")")
+}
 
-FORM (DTW_getXTimeFromYTime, U"DTW: Get x time from y time", U"DTW: Get x time from y time...")
-	REAL (U"Time at y (s)", U"0.0")
+FORM (REAL_DTW_getXTimeFromYTime, U"DTW: Get x time from y time", U"DTW: Get x time from y time...") {
+	REALVAR (yTime, U"Time at y (s)", U"0.0")
 	OK
 DO
-	double time = GET_REAL (U"Time at y");
-	LOOP {
-		iam (DTW);
-		Melder_information (DTW_getXTimeFromYTime (me, time), U" s (= x time at y time ", time, U")");
-	}
-END
+	NUMBER_ONE (DTW)
+		double result = DTW_getXTimeFromYTime (me, yTime);
+	NUMBER_ONE_END (U" s (= x time at y time ", yTime, U")")
+}
 
-FORM (DTW_getMaximumConsecutiveSteps, U"DTW: Get maximum consecutive steps", U"DTW: Get maximum consecutive steps...")
-	OPTIONMENU (U"Direction", 1)
+FORM (INTEGER_DTW_getMaximumConsecutiveSteps, U"DTW: Get maximum consecutive steps", U"DTW: Get maximum consecutive steps...") {
+	OPTIONMENUVAR (direction, U"Direction", 1)
 		OPTION (U"X")
 		OPTION (U"Y")
 		OPTION (U"Diagonaal")
 	OK
 DO
-	int direction [] = { DTW_START, DTW_X, DTW_Y, DTW_XANDY };
-	const char32 *string [] = { U"", U"x", U"y", U"diagonal" };
-	int d = GET_INTEGER (U"Direction");
-	LOOP {
-		iam (DTW);
-		Melder_information (DTW_getMaximumConsecutiveSteps (me, direction [d]),
-			U" (= maximum number of consecutive steps in ", string [d], U" direction)");
-	}
-END
+	int direction_code [] = { DTW_START, DTW_X, DTW_Y, DTW_XANDY };
+	const char32 *direction_string [] = { U"", U"x", U"y", U"diagonal" };
+	INTEGER_ONE (DTW)
+		long result = DTW_getMaximumConsecutiveSteps (me, direction_code [direction]);
+	INTEGER_ONE_END (U" (= maximum number of consecutive steps in ", direction_string [direction], U" direction)")
+}
 
-DIRECT (DTW_getWeightedDistance)
-	LOOP {
-		iam (DTW);
-		Melder_information (my weightedDistance);
-	}
-END
+DIRECT (REAL_DTW_getWeightedDistance) {
+	NUMBER_ONE (DTW)
+		double result = my weightedDistance;
+	NUMBER_ONE_END (U" (weighted distance)")
+}
 
-FORM (DTW_getDistanceValue, U"DTW: Get distance value", nullptr)
-	REAL (U"Time at x (s)", U"0.1")
-	REAL (U"Time at y (s)", U"0.1")
+FORM (REAL_DTW_getDistanceValue, U"DTW: Get distance value", nullptr) {
+	REALVAR (xTime, U"Time at x (s)", U"0.1")
+	REALVAR (yTime, U"Time at y (s)", U"0.1")
 	OK
 DO
-	double xtime = GET_REAL (U"Time at x");
-	double ytime = GET_REAL (U"Time at y");
-	double dist;
-	LOOP {
-		iam (DTW);
-		if (xtime < my xmin || xtime > my xmax || ytime < my ymin || ytime > my ymax) {
-			dist = NUMundefined;
-		} else
-		{
-			long irow = Matrix_yToNearestRow (me, ytime);
-			long icol = Matrix_xToNearestColumn (me, xtime);
-			dist = my z[irow][icol];
+	NUMBER_ONE (DTW)
+		double result = NUMundefined;
+		if ((xTime >= my xmin && xTime <= my xmax) && (yTime >= my ymin && yTime <= my ymax)) {
+			long irow = Matrix_yToNearestRow (me, yTime);
+			long icol = Matrix_xToNearestColumn (me, xTime);
+			result = my z[irow][icol];
 		}
-		Melder_information (dist, U" (= distance at (", xtime, U", ", ytime, U"))");
-	}
-END
+		NUMBER_ONE_END (U" (= distance at (", xTime, U", ", yTime, U"))")
+}
 
-DIRECT (DTW_getMinimumDistance)
-	LOOP {
-		iam (DTW);
-		double minimum = NUMundefined, maximum = NUMundefined;
-		Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
-		Melder_informationReal (minimum, 0);
-	}
-END
+DIRECT (REAL_DTW_getMinimumDistance) {
+	NUMBER_ONE (DTW)
+		double result, maximum;
+		Matrix_getWindowExtrema (me, 0, 0, 0, 0, & result, & maximum);
+	NUMBER_ONE_END (U" (minimum)")
+}
 
-DIRECT (DTW_getMaximumDistance)
-	LOOP {
-		iam (DTW);
-		double minimum = NUMundefined, maximum = NUMundefined;
-		Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
-		Melder_informationReal (maximum, 0);
-	}
-END
+DIRECT (REAL_DTW_getMaximumDistance) {
+	NUMBER_ONE (DTW)
+		double minimum, result;
+		Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & result);
+	NUMBER_ONE_END (U" (maximum)")
+}
 
-FORM (DTW_formulaDistances, U"DTW: Formula (distances)", 0)
+FORM (MODIFY_DTW_formulaDistances, U"DTW: Formula (distances)", nullptr) {
 	LABEL (U"label", U"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 (U"formula", U"self")
+	TEXTVAR (formula, U"formula", U"self")
 	OK
 DO
 	LOOP {
 		iam (DTW);
 		autoMatrix cp = DTW_to_Matrix_distances (me);
 		try {
-			Matrix_formula (reinterpret_cast <Matrix> (me), GET_STRING (U"formula"), interpreter, 0);
+			Matrix_formula (reinterpret_cast <Matrix> (me), formula, interpreter, 0);
 			double minimum, maximum;
 			Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
 			if (minimum < 0) {
@@ -2281,842 +1843,689 @@ DO
 			throw;
 		}
 	}
-END
+END }
 
-FORM (DTW_setDistanceValue, U"DTW: Set distance value", nullptr)
-	REAL (U"Time at x (s)", U"0.1")
-	REAL (U"Time at y (s)", U"0.1")
-	REAL (U"New value", U"0.0")
+FORM (MODIFY_DTW_setDistanceValue, U"DTW: Set distance value", nullptr) {
+	REALVAR (xTime, U"Time at x (s)", U"0.1")
+	REALVAR (yTime, U"Time at y (s)", U"0.1")
+	REALVAR (newDistance, U"New value", U"0.0")
 	OK
 DO
-	double xtime = GET_REAL (U"Time at x");
-	double ytime = GET_REAL (U"Time at y");
-	double val = GET_REAL (U"New value");
-	if (val < 0) {
+	if (newDistance < 0) {
 		Melder_throw (U"Distances cannot be negative.");
 	}
-	LOOP {
-		iam (DTW);
-		if (xtime < my xmin || xtime > my xmax) {
+	MODIFY_EACH (DTW)
+		if (xTime < my xmin || xTime > my xmax) {
 			Melder_throw (U"Time at x outside domain.");
 		}
-		if (ytime < my ymin || ytime > my ymax) {
+		if (yTime < my ymin || yTime > my ymax) {
 			Melder_throw (U"Time at y outside domain.");
 		}
-		long irow = Matrix_yToNearestRow (me, ytime);
-		long icol = Matrix_xToNearestColumn (me, xtime);
-		my z[irow][icol] = GET_REAL (U"New value");
-		praat_dataChanged (me);
-	}
-END
+		long irow = Matrix_yToNearestRow (me, yTime);
+		long icol = Matrix_xToNearestColumn (me, xTime);
+		my z[irow][icol] = newDistance;
+	MODIFY_EACH_END
+}
 
-FORM (DTW_findPath, U"DTW: Find path", nullptr)
-	DTW_constraints_addCommonFields (dia);
+FORM (MODIFY_DTW_findPath, U"DTW: Find path", nullptr) {
+	DTW_constraints_addCommonFields(matchStart,matchEnd,slopeConstraint)
 	OK
 DO
-	int begin, end, slope;
-	DTW_constraints_getCommonFields (dia, & begin, & end, & slope);
-	LOOP {
-		iam (DTW);
-		DTW_findPath (me, begin, end, slope);
-	}
-END
+	MODIFY_EACH (DTW)
+		DTW_findPath (me, matchStart, matchEnd, slopeConstraint);
+	MODIFY_EACH_END
+}
 
-FORM (DTW_findPath_bandAndSlope, U"DTW: find path (band & slope)", nullptr)
-    REAL (U"Sakoe-Chiba band (s)", U"0.05")
-    RADIO (U"Slope constraint", 1)
+FORM (MODIFY_DTW_findPath_bandAndSlope, U"DTW: find path (band & slope)", nullptr) {
+    REALVAR (sakoeChibaBand, U"Sakoe-Chiba band (s)", U"0.05")
+    RADIOVAR (slopeConstraint, U"Slope constraint", 1)
 		RADIOBUTTON (U"no restriction")
 		RADIOBUTTON (U"1/3 < slope < 3")
 		RADIOBUTTON (U"1/2 < slope < 2")
 		RADIOBUTTON (U"2/3 < slope < 3/2")
     OK
 DO
-    double band = GET_REAL (U"Sakoe-Chiba band");
-    int slope = GET_INTEGER (U"Slope constraint");
-    LOOP {
-        iam (DTW);
-        DTW_findPath_bandAndSlope (me, band, slope, nullptr);
-    }
-END
+    MODIFY_EACH (DTW)
+        DTW_findPath_bandAndSlope (me, sakoeChibaBand, slopeConstraint, nullptr);
+	MODIFY_EACH_END
+}
 
-FORM (DTW_to_Matrix_cummulativeDistances, U"DTW: To Matrix", nullptr)
-    REAL (U"Sakoe-Chiba band (s)", U"0.05")
-    RADIO (U"Slope constraint", 1)
+FORM (NEW_DTW_to_Matrix_cummulativeDistances, U"DTW: To Matrix", nullptr) {
+    REALVAR (sakoeChibaBand, U"Sakoe-Chiba band (s)", U"0.05")
+    RADIOVAR (slopeConstraint, U"Slope constraint", 1)
 		RADIOBUTTON (U"no restriction")
 		RADIOBUTTON (U"1/3 < slope < 3")
 		RADIOBUTTON (U"1/2 < slope < 2")
 		RADIOBUTTON (U"2/3 < slope < 3/2")
     OK
 DO
-    double band = GET_REAL (U"Sakoe-Chiba band");
-    int slope = GET_INTEGER (U"Slope constraint");
-    LOOP {
-        iam (DTW);
-        autoMatrix thee = DTW_to_Matrix_cummulativeDistances (me, band, slope);
-        praat_new (thee.move(), my name, U"_cd");
-    }
-END
+    CONVERT_EACH (DTW)
+        autoMatrix result = DTW_to_Matrix_cummulativeDistances (me, sakoeChibaBand, slopeConstraint);
+	CONVERT_EACH_END (my name, U"_cd")
+}
 
-FORM (DTW_to_Polygon, U"DTW: To Polygon...", 0)
-    REAL (U"Sakoe-Chiba band (s)", U"0.1")
-    RADIO (U"Slope constraint", 1)
+FORM (NEW_DTW_to_Polygon, U"DTW: To Polygon...", nullptr) {
+    REALVAR (sakoeChibaBand, U"Sakoe-Chiba band (s)", U"0.1")
+    RADIOVAR (slopeConstraint, U"Slope constraint", 1)
 		RADIOBUTTON (U"no restriction")
 		RADIOBUTTON (U"1/3 < slope < 3")
 		RADIOBUTTON (U"1/2 < slope < 2")
 		RADIOBUTTON (U"2/3 < slope < 3/2")
     OK
 DO
-    double band = GET_REAL (U"Sakoe-Chiba band");
-    int slope = GET_INTEGER (U"Slope constraint");
-    LOOP {
-        iam (DTW);
-        autoPolygon thee = DTW_to_Polygon (me, band, slope);
-        praat_new (thee.move(), my name);
-    }
-END
+    CONVERT_EACH (DTW)
+        autoPolygon result = DTW_to_Polygon (me, sakoeChibaBand, slopeConstraint);
+    CONVERT_EACH_END (my name)
+}
 
-DIRECT (DTW_to_Matrix_distances)
-	LOOP {
-		iam (DTW);
-		autoMatrix thee = DTW_to_Matrix_distances (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_DTW_to_Matrix_distances) {
+	CONVERT_EACH (DTW)
+		autoMatrix result = DTW_to_Matrix_distances (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (DTW_swapAxes)
-	LOOP {
-		iam (DTW);
-		autoDTW thee = DTW_swapAxes (me);
-		praat_new (thee.move(), my name, U"_axesSwapped");
-	}
-END
-
-DIRECT (DTW_and_Matrix_replace)
-	DTW me = FIRST (DTW);
-	Matrix m = FIRST (Matrix);
-	DTW_and_Matrix_replace (me, m);
-	praat_dataChanged (me);
-END
-
-DIRECT (DTW_and_TextGrid_to_TextGrid)
-	DTW me = FIRST (DTW);
-	TextGrid tg = FIRST (TextGrid);
-	autoTextGrid thee = DTW_and_TextGrid_to_TextGrid (me, tg, 0);
-	praat_new (thee.move(), tg -> name, U"_", my name);
-END
-
-DIRECT (DTW_and_IntervalTier_to_Table)
-	DTW me = FIRST (DTW);
-	IntervalTier ti = FIRST (IntervalTier);
-	autoTable thee = DTW_and_IntervalTier_to_Table (me, ti, 1.0/44100);
-	praat_new (thee.move(), my name);
-END
+DIRECT (NEW_DTW_swapAxes) {
+	CONVERT_EACH (DTW)
+		autoDTW result = DTW_swapAxes (me);
+	CONVERT_EACH_END (my name, U"_axesSwapped")
+}
+
+DIRECT (MODIFY_DTW_and_Matrix_replace) {
+	MODIFY_FIRST_OF_TWO (DTW, Matrix)
+		DTW_and_Matrix_replace (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+DIRECT (NEW1_DTW_and_TextGrid_to_TextGrid) {
+	CONVERT_TWO (DTW, TextGrid)
+		autoTextGrid result = DTW_and_TextGrid_to_TextGrid (me, you, 0);
+	CONVERT_TWO_END (your name, U"_", my name)
+}
+
+DIRECT (NEW1_DTW_and_IntervalTier_to_Table) {
+	CONVERT_TWO (DTW, IntervalTier)
+		autoTable result = DTW_and_IntervalTier_to_Table (me, you, 1.0/44100);
+	CONVERT_TWO_END (my name)
+}
 
 /******************** EditDistanceTable & EditCostsTable ********************************************/
 
-DIRECT (EditDistanceTable_help)
-	Melder_help (U"EditDistanceTable");
-END
+DIRECT (HELP_EditDistanceTable_help) {
+	HELP (U"EditDistanceTable")
+}
 
-DIRECT (EditDistanceTable_to_TableOfReal_directions)
-	LOOP {
-		iam (EditDistanceTable);
-		autoTableOfReal thee = EditDistanceTable_to_TableOfReal_directions (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_EditDistanceTable_to_TableOfReal_directions) {
+	CONVERT_EACH (EditDistanceTable)
+		autoTableOfReal result = EditDistanceTable_to_TableOfReal_directions (me);
+	CONVERT_EACH_END (my name);
+}
 
-DIRECT (EditDistanceTable_setEditCosts)
-	EditDistanceTable me = FIRST (EditDistanceTable);
-	EditCostsTable thee = FIRST(EditCostsTable);
-	EditDistanceTable_setEditCosts (me, thee);
-END
+DIRECT (MODIFY_EditDistanceTable_setEditCosts) {
+	MODIFY_FIRST_OF_TWO (EditDistanceTable, EditCostsTable)
+		EditDistanceTable_setEditCosts (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (EditDistanceTable_setDefaultCosts, U"", nullptr)
-	REAL (U"Insertion costs", U"1.0")
-	REAL (U"Deletion costs", U"1.0")
-	REAL (U"Substitution costs", U"2.0")
+FORM (MODIFY_EditDistanceTable_setDefaultCosts, U"", nullptr) {
+	REALVAR (insertionCosts, U"Insertion costs", U"1.0")
+	REALVAR (deletionCosts, U"Deletion costs", U"1.0")
+	REALVAR (substitutionCosts, U"Substitution costs", U"2.0")
 	OK
 DO
-	double insertionCosts = GET_REAL (U"Insertion costs");
 	if (insertionCosts < 0) {
 		Melder_throw (U"Insertion costs cannot be negative.");
 	}
-	double deletionCosts = GET_REAL (U"Deletion costs");
 	if (deletionCosts < 0) {
 		Melder_throw (U"Deletion costs cannot be negative.");
 	}
-	double substitutionCosts = GET_REAL (U"Substitution costs");
 	if (substitutionCosts < 0) {
 		Melder_throw (U"Substitution costs cannot be negative.");
 	}
-	LOOP {
-		iam (EditDistanceTable);
+	MODIFY_EACH (EditDistanceTable)
 		EditDistanceTable_setDefaultCosts (me, insertionCosts, deletionCosts, substitutionCosts);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (EditDistanceTable_draw, U"EditDistanceTable_draw", nullptr)
-	RADIO (U"Format", 3)
+FORM (GRAPHICS_EditDistanceTable_draw, U"EditDistanceTable_draw", nullptr) {
+	RADIOVAR (format, U"Format", 3)
 		RADIOBUTTON (U"decimal")
 		RADIOBUTTON (U"exponential")
 		RADIOBUTTON (U"free")
 		RADIOBUTTON (U"rational")
-	NATURAL (U"Precision", U"1")
-	REAL (U"Rotate source labels by (degrees)", U"0.0")
+	NATURALVAR (precision, U"Precision", U"1")
+	REALVAR (angle, U"Rotate source labels by (degrees)", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (EditDistanceTable);
-		EditDistanceTable_draw (me, GRAPHICS,
-			GET_INTEGER (U"Format"),
-			GET_INTEGER (U"Precision"),
-			GET_REAL (U"Rotate source labels by"));
-	}
-END
+	GRAPHICS_EACH (EditDistanceTable)
+		EditDistanceTable_draw (me, GRAPHICS, format, precision, angle);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (EditDistanceTable_drawEditOperations)
-	autoPraatPicture picture;
-	LOOP {
-		iam(EditDistanceTable);
+DIRECT (GRAPHICS_EditDistanceTable_drawEditOperations) {
+	GRAPHICS_EACH (EditDistanceTable)
 		EditDistanceTable_drawEditOperations (me, GRAPHICS);
-	}
-END
+	GRAPHICS_EACH_END
+}
 
-DIRECT (EditCostsTable_help)
-	Melder_help (U"EditCostsTable");
-END
+DIRECT (HELP_EditCostsTable_help) {
+	HELP (U"EditCostsTable")
+}
 
-FORM (EditCostsTable_getTargetIndex, U"EditCostsTable: Get target index", nullptr)
-	SENTENCE (U"Target", U"")
+FORM (INTEGER_EditCostsTable_getTargetIndex, U"EditCostsTable: Get target index", nullptr) {
+	SENTENCEVAR (target, U"Target", U"")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		Melder_informationReal (EditCostsTable_getTargetIndex (me,
-			GET_STRING (U"Target")), nullptr);
-	}
-END
+	INTEGER_ONE (EditCostsTable)
+		long result = EditCostsTable_getTargetIndex (me, target);
+	INTEGER_ONE_END (U" (target index)")
+}
 
-FORM (EditCostsTable_getSourceIndex, U"EditCostsTable: Get source index", nullptr)
-	SENTENCE (U"Source", U"")
+FORM (INTEGER_EditCostsTable_getSourceIndex, U"EditCostsTable: Get source index", nullptr) {
+	SENTENCEVAR (source, U"Source", U"")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		Melder_informationReal (EditCostsTable_getSourceIndex (me,
-			GET_STRING (U"Source")), nullptr);
-	}
-END
+	INTEGER_ONE (EditCostsTable)
+		long result = EditCostsTable_getSourceIndex (me, source);
+	INTEGER_ONE_END (U" (source index)")
+}
 
-FORM (EditCostsTable_getInsertionCost, U"EditCostsTable: Get insertion cost", nullptr)
-	SENTENCE (U"Target", U"")
+FORM (REAL_EditCostsTable_getInsertionCost, U"EditCostsTable: Get insertion cost", nullptr) {
+	SENTENCEVAR (target, U"Target", U"")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		Melder_informationReal (EditCostsTable_getInsertionCost (me,
-			GET_STRING (U"Target")), nullptr);
-	}
-END
+	NUMBER_ONE (EditCostsTable)
+		double result = EditCostsTable_getInsertionCost (me, target);
+	NUMBER_ONE_END (U" (insertion cost)")
+}
 
-FORM (EditCostsTable_getDeletionCost, U"EditCostsTable: Get deletion cost", nullptr)
-	SENTENCE (U"Source", U"")
+FORM (REAL_EditCostsTable_getDeletionCost, U"EditCostsTable: Get deletion cost", nullptr) {
+	SENTENCEVAR (source, U"Source", U"")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		Melder_informationReal (EditCostsTable_getDeletionCost (me,
-			GET_STRING (U"Source")), nullptr);
-	}
-END
+	NUMBER_ONE (EditCostsTable)
+		double result = EditCostsTable_getDeletionCost (me, source);
+	NUMBER_ONE_END (U" (deletion cost)")
+}
 
-FORM (EditCostsTable_getSubstitutionCost, U"EditCostsTable: Get substitution cost", nullptr)
-	SENTENCE (U"Target", U"")
-	SENTENCE (U"Source", U"")
+FORM (REAL_EditCostsTable_getSubstitutionCost, U"EditCostsTable: Get substitution cost", nullptr) {
+	SENTENCEVAR (target, U"Target", U"")
+	SENTENCEVAR (source, U"Source", U"")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		Melder_informationReal (EditCostsTable_getSubstitutionCost (me,
-			GET_STRING (U"Target"),
-			GET_STRING (U"Source")), nullptr);
-	}
-END
+	NUMBER_ONE (EditCostsTable)
+		double result = EditCostsTable_getSubstitutionCost (me, target, source);
+	NUMBER_ONE_END (U" (substitution cost)")
+}
 
-FORM (EditCostsTable_getOthersCost, U"EditCostsTable: Get cost (others)", nullptr)
-	RADIO (U"Others cost type", 1)
+FORM (REAL_EditCostsTable_getOthersCost, U"EditCostsTable: Get cost (others)", nullptr) {
+	RADIOVAR (costTypes, U"Others cost type", 1)
 		RADIOBUTTON (U"Insertion")
 		RADIOBUTTON (U"Deletion")
 		RADIOBUTTON (U"Equality")
 		RADIOBUTTON (U"Inequality")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		Melder_informationReal (EditCostsTable_getOthersCost (me,
-			GET_INTEGER (U"Others cost type")), nullptr);
-	}
-END
+	NUMBER_ONE (EditCostsTable)
+		double result = EditCostsTable_getOthersCost (me,costTypes);
+	NUMBER_ONE_END (U" (cost)")
+}
 
-FORM (EditCostsTable_setTargetSymbol_index, U"EditCostsTable: Set target symbol (index)", nullptr)
-	NATURAL (U"Index", U"1")
-	SENTENCE (U"Target", U"a")
+FORM (MODIFY_EditCostsTable_setTargetSymbol_index, U"EditCostsTable: Set target symbol (index)", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	SENTENCEVAR (target, U"Target", U"a")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_setRowLabel (me,
-			GET_INTEGER (U"Index"),
-			GET_STRING (U"Target"));
-	}
-END
+	MODIFY_EACH (EditCostsTable)
+		TableOfReal_setRowLabel (me, index, target);
+	MODIFY_EACH_END
+}
 
-FORM (EditCostsTable_setSourceSymbol_index, U"EditCostsTable: Set source symbol (index)", nullptr)
-	NATURAL (U"Index", U"1")
-	SENTENCE (U"Source", U"a")
+FORM (MODIFY_EditCostsTable_setSourceSymbol_index, U"EditCostsTable: Set source symbol (index)", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	SENTENCEVAR (source, U"Source", U"a")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_setColumnLabel (me,
-			GET_INTEGER (U"Index"),
-			GET_STRING (U"Source"));
-	}
-END
+	MODIFY_EACH (EditCostsTable)
+		TableOfReal_setColumnLabel (me, index, source);
+	MODIFY_EACH_END
+}
 
-FORM (EditCostsTable_setInsertionCosts, U"EditCostsTable: Set insertion costs", nullptr)
-	SENTENCE (U"Targets", U"")
-	REAL (U"Cost", U"2.0")
+FORM (MODIFY_EditCostsTable_setInsertionCosts, U"EditCostsTable: Set insertion costs", nullptr) {
+	SENTENCEVAR (targets, U"Targets", U"")
+	REALVAR (cost, U"Cost", U"2.0")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		EditCostsTable_setInsertionCosts (me,
-			GET_STRING (U"Targets"),
-			GET_REAL (U"Cost"));
-	}
-END
+	MODIFY_EACH (EditCostsTable)
+		EditCostsTable_setInsertionCosts (me, targets, cost);
+	MODIFY_EACH_END
+}
 
-FORM (EditCostsTable_setDeletionCosts, U"EditCostsTable: Set deletion costs", nullptr)
-	SENTENCE (U"Sources", U"")
-	REAL (U"Cost", U"2.0")
+FORM (MODIFY_EditCostsTable_setDeletionCosts, U"EditCostsTable: Set deletion costs", nullptr) {
+	SENTENCEVAR (sources, U"Sources", U"")
+	REALVAR (cost, U"Cost", U"2.0")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		EditCostsTable_setDeletionCosts (me,
-			GET_STRING (U"Sources"),
-			GET_REAL (U"Cost"));
-	}
-END
+	MODIFY_EACH (EditCostsTable)
+		EditCostsTable_setDeletionCosts (me, sources, cost);
+	MODIFY_EACH_END
+}
 
-FORM (EditCostsTable_setSubstitutionCosts, U"EditCostsTable: Set substitution costs", nullptr)
-	SENTENCE (U"Targets", U"a i u")
-	SENTENCE (U"Sources", U"a i u")
-	REAL (U"Cost", U"2.0")
+FORM (MODIFY_EditCostsTable_setSubstitutionCosts, U"EditCostsTable: Set substitution costs", nullptr) {
+	SENTENCEVAR (targets, U"Targets", U"a i u")
+	SENTENCEVAR (sources, U"Sources", U"a i u")
+	REALVAR (cost, U"Cost", U"2.0")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		EditCostsTable_setSubstitutionCosts (me,
-			GET_STRING (U"Targets"),
-			GET_STRING (U"Sources"),
-			GET_REAL (U"Cost"));
-	}
-END
+	MODIFY_EACH (EditCostsTable)
+		EditCostsTable_setSubstitutionCosts (me, targets, sources, cost);
+	MODIFY_EACH_END
+}
 
-FORM (EditCostsTable_setOthersCosts, U"EditCostsTable: Set costs (others)", nullptr)
+FORM (MODIFY_EditCostsTable_setOthersCosts, U"EditCostsTable: Set costs (others)", nullptr) {
 	LABEL (U"", U"Others costs")
-	REAL (U"Insertion", U"1.0")
-	REAL (U"Deletion", U"1.0")
-	LABEL (U"", U"Substitution costs")
-	REAL (U"Equality", U"0.0")
-	REAL (U"Inequality", U"2.0")
+	REALVAR (insertionCosts, U"Insertion", U"1.0")
+	REALVAR (deletionCosts, U"Deletion", U"1.0")
+	LABEL ( U"", U"Substitution costs")
+	REALVAR (equalityCosts, U"Equality", U"0.0")
+	REALVAR (inequalityCosts, U"Inequality", U"2.0")
 	OK
 DO
-	LOOP {
-		iam (EditCostsTable);
-		EditCostsTable_setOthersCosts (me,
-			GET_REAL (U"Insertion"),
-			GET_REAL (U"Deletion"),
-			GET_REAL (U"Equality"),
-			GET_REAL (U"Inequality"));
-	}
-END
+	MODIFY_EACH (EditCostsTable)
+		EditCostsTable_setOthersCosts (me, insertionCosts, deletionCosts, equalityCosts, inequalityCosts);
+	MODIFY_EACH_END
+}
 
-DIRECT (EditCostsTable_to_TableOfReal)
-	LOOP {
-		iam (EditCostsTable);
+DIRECT (NEW_EditCostsTable_to_TableOfReal) {
+	CONVERT_EACH (EditCostsTable)
 		autoTableOfReal result = EditCostsTable_to_TableOfReal (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name);
+}
 
-FORM (EditCostsTable_createEmpty, U"Create empty EditCostsTable", U"Create empty EditCostsTable...")
-	SENTENCE (U"Name", U"editCosts")
-	INTEGER (U"Number of target symbols", U"0")
-	INTEGER (U"Number of source symbols", U"0")
+FORM (NEW_EditCostsTable_createEmpty, U"Create empty EditCostsTable", U"Create empty EditCostsTable...") {
+	SENTENCEVAR (name, U"Name", U"editCosts")
+	INTEGERVAR (numberOfTargetSymbols, U"Number of target symbols", U"0")
+	INTEGERVAR (numberOfSourceSymbols, U"Number of source symbols", U"0")
 	OK
 DO
-	long numberOfTargetSymbols = GET_INTEGER (U"Number of target symbols");
-	numberOfTargetSymbols = numberOfTargetSymbols < 0 ? 0 : numberOfTargetSymbols;
-	long numberOfSourceSymbols = GET_INTEGER (U"Number of source symbols");
-	numberOfSourceSymbols = numberOfSourceSymbols < 0 ? 0 : numberOfSourceSymbols;
-	autoEditCostsTable result = EditCostsTable_create (numberOfTargetSymbols, numberOfSourceSymbols);
-	praat_new (result.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		numberOfTargetSymbols = numberOfTargetSymbols < 0 ? 0 : numberOfTargetSymbols;
+		numberOfSourceSymbols = numberOfSourceSymbols < 0 ? 0 : numberOfSourceSymbols;
+		autoEditCostsTable result = EditCostsTable_create (numberOfTargetSymbols, numberOfSourceSymbols);
+	CREATE_ONE_END (name)
+}
 
 /******************** Eigen ********************************************/
 
-DIRECT (Eigen_drawEigenvalues_scree)
+DIRECT (HELP_Eigen_help) {
+	HELP (U"Eigen")
+}
+
+DIRECT (GRAPHICS_Eigen_drawEigenvalues_scree) {
 	Melder_warning (U"The command \"Draw eigenvalues (scree)...\" has been "
 		"removed.\n To get a scree plot use \"Draw eigenvalues...\" with the "
 		"arguments\n 'Fraction of eigenvalues summed' and 'Cumulative' unchecked.");
-END
+	END 	
+}
 
-FORM (Eigen_drawEigenvalues, U"Eigen: Draw eigenvalues", U"Eigen: Draw eigenvalues...")
-	INTEGER (U"left Eigenvalue range", U"0")
-	INTEGER (U"right Eigenvalue range", U"0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Fraction of eigenvalues summed", false)
-	BOOLEAN (U"Cumulative", false)
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Eigen);
-		Eigen_drawEigenvalues (me, GRAPHICS,
-			GET_INTEGER (U"left Eigenvalue range"),
-			GET_INTEGER (U"right Eigenvalue range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Fraction of eigenvalues summed"),
-			GET_INTEGER (U"Cumulative"),
-			GET_REAL (U"Mark size"),
-			GET_STRING (U"Mark string"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Eigen_drawEigenvector, U"Eigen: Draw eigenvector", U"Eigen: Draw eigenvector...")
-	INTEGER (U"Eigenvector number", U"1")
-	BOOLEAN (U"Component loadings", false)
-	INTEGER (U"left Element range", U"0")
-	INTEGER (U"right Element range", U"0")
-	REAL (U"left Amplitude range", U"-1.0")
-	REAL (U"right Amplitude range", U"1.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Connect points", true)
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Eigen);
-		Eigen_drawEigenvector (me, GRAPHICS,
-			GET_INTEGER (U"Eigenvector number"),
-			GET_INTEGER (U"left Element range"),
-			GET_INTEGER (U"right Element range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Component loadings"),
-			GET_REAL (U"Mark size"),
-			GET_STRING (U"Mark string"),
-			GET_INTEGER (U"Connect points"),
-			nullptr,   // rowLabels
-			GET_INTEGER (U"Garnish"));
-	}
-END
+FORM (GRAPHICS_Eigen_drawEigenvalues, U"Eigen: Draw eigenvalues", U"Eigen: Draw eigenvalues...") {
+	INTEGERVAR (fromEigenvalue, U"left Eigenvalue range", U"0")
+	INTEGERVAR (toEigenvalue, U"right Eigenvalue range", U"0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (fractionSummed, U"Fraction of eigenvalues summed", false)
+	BOOLEANVAR (cumulative, U"Cumulative", false)
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Eigen)
+		Eigen_drawEigenvalues (me, GRAPHICS, fromEigenvalue, toEigenvalue, fromAmplitude, toAmplitude, fractionSummed, cumulative, markSize_mm, mark_string, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Eigen_getNumberOfEigenvalues)
-	LOOP {
-		iam (Eigen);
-		Melder_information (my numberOfEigenvalues);
-	}
-END
+FORM (GRAPHICS_Eigen_drawEigenvector, U"Eigen: Draw eigenvector", U"Eigen: Draw eigenvector...") {
+	INTEGERVAR (eigenvectorNumber, U"Eigenvector number", U"1")
+	BOOLEANVAR (loadings, U"Component loadings", false)
+	INTEGERVAR (fromElement, U"left Element range", U"0")
+	INTEGERVAR (toElement, U"right Element range", U"0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"-1.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"1.0")
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (connectPoints, U"Connect points", true)
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Eigen)
+		Eigen_drawEigenvector (me, GRAPHICS, eigenvectorNumber, fromElement, toElement, fromAmplitude, toAmplitude, loadings, markSize_mm, mark_string, connectPoints, nullptr,  garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Eigen_getDimension)
-	LOOP {
-		iam (Eigen);
-		Melder_information (my dimension);
-	}
-END
+DIRECT (INTEGER_Eigen_getNumberOfEigenvalues) {
+	INTEGER_ONE (Eigen)
+		long result = my numberOfEigenvalues;
+	INTEGER_ONE_END (U" (number of eigenvalues/vectors)")
+}
 
-FORM (Eigen_getEigenvalue, U"Eigen: Get eigenvalue", U"Eigen: Get eigenvalue...")
-	NATURAL (U"Eigenvalue number", U"1")
+DIRECT (INTEGER_Eigen_getDimension) {
+	INTEGER_ONE (Eigen)
+		long result = my dimension;
+	INTEGER_ONE_END (U" (dimension)")
+}
+
+FORM (REAL_Eigen_getEigenvalue, U"Eigen: Get eigenvalue", U"Eigen: Get eigenvalue...") {
+	NATURALVAR (eigenvalueNumber, U"Eigenvalue number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Eigen);
-		long number = GET_INTEGER (U"Eigenvalue number");
-		if (number > my numberOfEigenvalues) {
-			Melder_throw (U"Eigenvalue number must be smaller than ", my numberOfEigenvalues + 1);
+	NUMBER_ONE (Eigen)
+		double result = NUMundefined;
+		if (eigenvalueNumber > 0 && eigenvalueNumber <= my numberOfEigenvalues) {
+			result = my eigenvalues [eigenvalueNumber];
 		}
-		Melder_information (my eigenvalues[number]);
-	}
-END
+	NUMBER_ONE_END (U" (eigenvalue [", eigenvalueNumber, U"])")
+}
 
-FORM (Eigen_getSumOfEigenvalues, U"Eigen:Get sum of eigenvalues", U"Eigen: Get sum of eigenvalues...")
-	INTEGER (U"left Eigenvalue range",  U"0")
-	INTEGER (U"right Eigenvalue range", U"0")
+FORM (REAL_Eigen_getSumOfEigenvalues, U"Eigen:Get sum of eigenvalues", U"Eigen: Get sum of eigenvalues...") {
+	INTEGERVAR (fromEigenvalue, U"left Eigenvalue range",  U"0")
+	INTEGERVAR (toEigenvalue, U"right Eigenvalue range", U"0")
 	OK
 DO
-	LOOP {
-		iam (Eigen);
-		Melder_information (Eigen_getSumOfEigenvalues (me, GET_INTEGER (U"left Eigenvalue range"), GET_INTEGER (U"right Eigenvalue range")));
-	}
-END
+	NUMBER_ONE (Eigen)
+		double result = Eigen_getSumOfEigenvalues (me, fromEigenvalue, toEigenvalue);
+	NUMBER_ONE_END (U" (sum of eigenvalues [", fromEigenvalue, U"..", toEigenvalue, U"])")
+}
 
-FORM (Eigen_getEigenvectorElement, U"Eigen: Get eigenvector element", U"Eigen: Get eigenvector element...")
-	NATURAL (U"Eigenvector number", U"1")
-	NATURAL (U"Element number", U"1")
+FORM (REAL_Eigen_getEigenvectorElement, U"Eigen: Get eigenvector element", U"Eigen: Get eigenvector element...") {
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
+	NATURALVAR (elementNumber, U"Element number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Eigen);
-		Melder_information (Eigen_getEigenvectorElement (me, GET_INTEGER (U"Eigenvector number"), GET_INTEGER (U"Element number")));
-	}
-END
+	NUMBER_ONE (Eigen)
+		double result = Eigen_getEigenvectorElement (me, eigenvectorNumber, elementNumber);
+	NUMBER_ONE_END (U" (eigenvector [", eigenvectorNumber, U"] element [", elementNumber, U"])")
+}
 
-DIRECT (Eigens_alignEigenvectors)
-	OrderedOf<structEigen> list;
-	LOOP {
-		iam (Eigen);
-		list. addItem_ref (me);
-	}
-	Eigens_alignEigenvectors (& list);
-END
+FORM (MODIFY_Eigen_invertEigenvector, U"Eigen: Invert eigenvector", nullptr) {
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
+	OK
+DO
+	MODIFY_EACH (Eigen)
+		Eigen_invertEigenvector (me, eigenvectorNumber);
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_Eigens_alignEigenvectors) {
+	FIND_LIST (Eigen)
+		Eigens_alignEigenvectors (& list);
+	END
+}
 
-FORM (Eigen_and_Matrix_projectColumns, U"Eigen & Matrix: Project columns", U"Eigen & Matrix: Project...")
-	INTEGER (U"Number of dimensions", U"0")
+FORM (NEW1_Eigen_and_Matrix_projectColumns, U"Eigen & Matrix: Project columns", U"Eigen & Matrix: Project...") {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0")
 	OK
 DO
-	Eigen me = FIRST_GENERIC (Eigen);
-	Matrix thee = FIRST_GENERIC (Matrix);
-	autoMatrix him = Eigen_and_Matrix_to_Matrix_projectColumns (me, thee, GET_INTEGER (U"Number of dimensions"));
-	praat_new (him.move(), my name, U"_", thy name);
-END
+	CONVERT_TWO (Eigen, Matrix)
+		autoMatrix result = Eigen_and_Matrix_to_Matrix_projectColumns (me, you, GET_INTEGER (U"Number of dimensions"));
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-DIRECT (Eigen_and_SSCP_project)
-	Eigen me = FIRST_GENERIC (Eigen);
-	SSCP cp = FIRST (SSCP);
-	autoSSCP thee = Eigen_and_SSCP_project (me, cp);
-	praat_new (thee.move(), my name, U"_", cp->name);
-END
+DIRECT (NEW1_Eigen_and_SSCP_project) {
+	CONVERT_TWO (Eigen, SSCP)
+		autoSSCP result = Eigen_and_SSCP_project (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-DIRECT (Eigen_and_Covariance_project)
-	Eigen me = FIRST_GENERIC (Eigen);
-	Covariance cv = FIRST (Covariance);
-	autoCovariance thee = Eigen_and_Covariance_project (me, cv);
-	praat_new (thee.move(), my name, U"_", cv->name);
-END
+DIRECT (NEW1_Eigen_and_Covariance_project) {
+	CONVERT_TWO (Eigen, Covariance)
+		autoCovariance result = Eigen_and_Covariance_project (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
 /******************** Index ********************************************/
 
-DIRECT (Index_help)
-	Melder_help (U"Index");
-END
+DIRECT (HELP_Index_help) {
+	HELP (U"Index")
+}
 
-DIRECT (Index_getNumberOfClasses)
-	LOOP {
-		iam (Index);
-		Melder_information (my classes->size);
-	}
-END
+DIRECT (INTEGER_Index_getNumberOfClasses) {
+	INTEGER_ONE (Index)
+		long result = my classes -> size;
+	INTEGER_ONE_END (U" (number of classes)")
+}
 
-FORM (StringsIndex_getClassLabel, U"StringsIndex: Get class label", U"StringsIndex: Get class label...")
-	NATURAL (U"Class index", U"1")
+FORM (INFO_StringsIndex_getClassLabelFromClassIndex, U"StringsIndex: Get class label", U"StringsIndex: Get class label...") {
+	NATURALVAR (index, U"Class index", U"1")
 	OK
 DO
-	long klas = GET_INTEGER (U"Class index");
-	LOOP {
-		iam (StringsIndex);
-		long numberOfClasses = my classes->size;
-		if (klas > numberOfClasses) {
-			Melder_throw (U"Index must be less than or equal ", numberOfClasses, U".");
-		}
-		SimpleString ss = (SimpleString) my classes->at [klas];   // FIXME cast
-		Melder_information (ss -> string);
-	}
-END
+	STRING_ONE (StringsIndex)
+		const char32* result = StringsIndex_getClassLabelFromClassIndex (me, index);
+	STRING_ONE_END
+}
 
-FORM (StringsIndex_getLabel, U"StringsIndex: Get label", U"StringsIndex: Get label...")
-	NATURAL (U"Element index", U"1")
+FORM (INFO_StringsIndex_getItemLabelFromItemIndex, U"StringsIndex: Get item label", nullptr) {
+	NATURALVAR (itemIndex, U"Item index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Element index");
-	LOOP {
-		iam (StringsIndex);
-		if (index > my numberOfElements) {
-			Melder_throw (U"Index must be less than or equal ", my numberOfElements, U".");
-		}
-		long klas = my classIndex [index];
-		SimpleString ss = (SimpleString) my classes->at [klas];   // FIXME cast
-		Melder_information (ss -> string);
-	}
-END
+	STRING_ONE (StringsIndex)
+		const char32 *result = StringsIndex_getItemLabelFromItemIndex (me, itemIndex);
+	STRING_ONE_END
+}
 
-FORM (Index_getIndex, U"Index: Get index", U"Index: Get index...")
-	NATURAL (U"Element index", U"1")
+FORM (INTEGER_Index_getClassIndexFromItemIndex, U"Index: Get item index", nullptr) {
+	NATURALVAR (itemIndex, U"Item index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Element index");
-	LOOP {
-		iam (Index);
-		if (index > my numberOfElements) {
-			Melder_throw (U"Index must be less than or equal ", my numberOfElements, U".");
-		}
-		Melder_information (my classIndex [index]);
-	}
-END
+	INTEGER_ONE (Index)
+		long result = Index_getClassIndexFromItemIndex (me, itemIndex);
+	INTEGER_ONE_END (U" (class index)")
+}
 
-FORM (StringsIndex_getClassIndex, U"StringsIndex: Get class index", U"StringsIndex: Get class index...")
-	WORD (U"Class label", U"label")
+FORM (INTEGER_StringsIndex_getClassIndexFromClassLabel, U"StringsIndex: Get class index from calss label", nullptr) {
+	WORDVAR (klasLabel, U"Class label", U"label")
 	OK
 DO
-	char32 *klasLabel = GET_STRING (U"Class label");
-	LOOP {
-		iam (StringsIndex);
-		long index = StringsIndex_getClass (me, klasLabel);
-		Melder_information (index);
-	}
-END
+	INTEGER_ONE (StringsIndex)
+		long result = StringsIndex_getClassIndexFromClassLabel (me, klasLabel);
+	INTEGER_ONE_END (U" (class index)")
+}
 
-FORM (Index_extractPart, U"Index: Extract part", U"Index: Extract part...")
-	INTEGER (U"left Range", U"0")
-	INTEGER (U"right Range", U"0")
+FORM (NEW_Index_extractPart, U"Index: Extract part", U"Index: Extract part...") {
+	INTEGERVAR (fromItem, U"left Item range", U"0")
+	INTEGERVAR (toItem, U"right Item range", U"0")
 	OK
 DO
-	LOOP {
-		iam (Index);
-		autoIndex thee = Index_extractPart (me,
-			GET_INTEGER (U"left Range"),
-			GET_INTEGER (U"right Range"));
-		praat_new (thee.move(), Thing_getName (me), U"_part");
-	}
-END
+	CONVERT_EACH (Index);
+		autoIndex result = Index_extractPart (me, fromItem, toItem);
+	CONVERT_EACH_END (my name, U"_part")
+}
 
-FORM (Index_to_Permutation, U"Index: To Permutation", U"Index: To Permutation...")
-	BOOLEAN (U"Permute within classes", true)
+FORM (NEW_Index_to_Permutation, U"Index: To Permutation", U"Index: To Permutation...") {
+	BOOLEANVAR (permuteWithinClasses, U"Permute within classes", true)
 	OK
 DO
-	LOOP {
-		iam (Index);
-		autoPermutation result = Index_to_Permutation_permuteRandomly (me,
-			GET_INTEGER (U"Permute within classes"));
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH (Index);
+		autoPermutation result = Index_to_Permutation_permuteRandomly (me, permuteWithinClasses);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (StringsIndex_to_Strings)
-	LOOP {
-		iam (StringsIndex);
+DIRECT (NEW_StringsIndex_to_Strings) {
+	CONVERT_EACH (StringsIndex)
 		autoStrings result = StringsIndex_to_Strings (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
 /******************** Excitation ********************************************/
 
-DIRECT (Excitations_to_ExcitationList)
-	autoExcitationList result = ExcitationList_create ();
-	LOOP {
-		iam (Excitation);
-		autoExcitation copy = Data_copy (me);
-		result -> addItem_move (copy.move());
-	}
-	praat_new (result.move(), U"appended");
-END
+DIRECT (NEW1_Excitations_to_ExcitationList) {
+	CONVERT_LIST (Excitation)
+		autoExcitationList result = Excitations_to_ExcitationList (& list);
+	CONVERT_LIST_END (U"appended")
+}
 
-/******************** Excitations ********************************************/
+/******************** ExcitationList ********************************************/
 
-FORM (ExcitationList_formula, U"ExcitationList: Formula", 0)
+FORM (MODIFY_ExcitationList_formula, U"ExcitationList: Formula", nullptr) {
 	LABEL (U"label", U"for all objects in ExcitationList do { for col := 1 to ncol do { self [col] := `formula' ; x := x + dx } }")
-	TEXTFIELD (U"formula", U"self")
+	TEXTVAR (formula, U"formula", U"self")
 	OK
 DO
-	LOOP {
-		iam (ExcitationList);
+	MODIFY_EACH (ExcitationList)
 		for (long j = 1; j <= my size; j ++) {
-			Matrix_formula (my at [j], GET_STRING (U"formula"), interpreter, nullptr);
+			Matrix_formula (my at [j], formula, interpreter, nullptr);
 		}
-		praat_dataChanged (me);
-	}
-END
-
-DIRECT (ExcitationList_addItem)
-	ExcitationList list = FIRST (ExcitationList);
-	WHERE_DOWN (SELECTED && CLASS == classExcitation) {
-		iam (Excitation);
-		autoExcitation copy = Data_copy (me);
-		list -> addItem_move (copy.move());
-	}
-END
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_ExcitationList_addItem) {
+	MODIFY_FIRST_OF_ONE_AND_LIST (ExcitationList, Excitation)
+		ExcitationList_addItems (me, & list);
+	MODIFY_FIRST_OF_ONE_AND_LIST_END
+}
 
-FORM (ExcitationList_getItem, U"ExcitationList: Get item", nullptr)
-	NATURAL (U"Item number", U"1")
+FORM (NEW_ExcitationList_extractItem, U"ExcitationList: Extract item", nullptr) {
+	NATURALVAR (itemIndex, U"Item index", U"1")
 	OK
 DO
-	LOOP {
-		iam (ExcitationList);
-		autoExcitation result = ExcitationList_getItem (me,
-			GET_INTEGER (U"Item number"));
-		praat_new (result.move(), my name, U"_item");
-	}
-END
+	CONVERT_EACH (ExcitationList)
+		autoExcitation result = ExcitationList_extractItem (me, itemIndex);
+	CONVERT_EACH_END (my name, U"_", itemIndex)
+}
 
-DIRECT (ExcitationList_append)
-	ExcitationList e1 = nullptr, e2 = nullptr;
-	LOOP {
-		iam (ExcitationList);
-		(e1 ? e2 : e1) = me;
-	}
-	Melder_assert (e1 && e2);
-	autoExcitationList result = Data_copy (e1);
-	result -> merge (e2);
-	praat_new (result.move(), U"appended");
-END
+DIRECT (NEW1_ExcitationList_append) {
+	CONVERT_COUPLE (ExcitationList)
+		autoExcitationList result = Data_copy (me);
+		result -> merge (you);
+	CONVERT_COUPLE_END (U"appended")
+}
 
-FORM (ExcitationList_to_PatternList, U"Excitations: To PatternList", nullptr)
+FORM (NEW_ExcitationList_to_PatternList, U"Excitations: To PatternList", nullptr) {
 	NATURAL (U"Join", U"1")
 	OK
 DO
-	LOOP {
-		iam (ExcitationList);
+	CONVERT_EACH (ExcitationList)
 		autoPatternList result = ExcitationList_to_PatternList (me, GET_INTEGER (U"Join"));
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (ExcitationList_to_TableOfReal)
-	LOOP {
-		iam (ExcitationList);
+DIRECT (NEW_ExcitationList_to_TableOfReal) {
+	CONVERT_EACH (ExcitationList)
 		autoTableOfReal result = ExcitationList_to_TableOfReal (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
 
 /************************* FileInMemory ***********************************/
 
 
-FORM_READ2 (FileInMemory_create, U"Create file in memory", nullptr, true) {
+FORM_READ (READ1_FileInMemory_create, U"Create file in memory", nullptr, true) {
 	autoFileInMemory me = FileInMemory_create (file);
 	praat_new (me.move(), MelderFile_name (file));
-END2 }
+END }
 
-FORM (FileInMemory_setId, U"FileInMemory: Set id", nullptr)
-	SENTENCE (U"New id", U"New id")
+FORM (MODIFY_FileInMemory_setId, U"FileInMemory: Set id", nullptr) {
+	SENTENCEVAR (newId, U"New id", U"New id")
 	OK
 DO
-	LOOP {
-		iam (FileInMemory);
-		FileInMemory_setId (me, GET_STRING (U"New id"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (FileInMemory)
+		FileInMemory_setId (me, newId);
+	MODIFY_EACH_END
+}
 
-FORM (FileInMemory_showAsCode, U"FileInMemory: Show as code", nullptr)
-	WORD (U"Name", U"example")
-	INTEGER (U"Number of bytes per line", U"20")
+FORM (INFO_FileInMemory_showAsCode, U"FileInMemory: Show as code", nullptr) {
+	WORDVAR (name, U"Name", U"example")
+	INTEGERVAR (numberOfByterPerLine, U"Number of bytes per line", U"20")
 	OK
 DO
-	const char32 *name = GET_STRING (U"Name");
-	LOOP {
-		iam (FileInMemory);
+	INFO_ONE (FileInMemory)
 		MelderInfo_open ();
-		FileInMemory_showAsCode (me, name, GET_INTEGER (U"Number of bytes per line"));
+		FileInMemory_showAsCode (me, name, numberOfByterPerLine);
 		MelderInfo_close ();
-	}
-END
+	INFO_ONE_END
+}
 
 /************************* FileInMemorySet ***********************************/
 
-FORM (FileInMemorySet_createFromDirectoryContents, U"Create files in memory from directory contents", nullptr)
-	SENTENCE (U"Name", U"list")
+FORM (NEW_FileInMemorySet_createFromDirectoryContents, U"Create files in memory from directory contents", nullptr) {
+	SENTENCEVAR (name, U"Name", U"list")
 	LABEL (U"", U"Directory:")
-	TEXTFIELD (U"Directory", U"/home/david/praat/src/espeak-work/espeak-1.46.13/espeak-data")
-	WORD (U"Only files that match pattern", U"*.txt")
+	TEXTVAR (directory, U"Directory", U"/home/david/praat/src/espeak-work/espeak-1.46.13/espeak-data")
+	WORDVAR (fileGlobber, U"Only files that match pattern", U"*.txt")
 	OK
 DO
-	autoFileInMemorySet me = FileInMemorySet_createFromDirectoryContents (
-		GET_STRING (U"Directory"),
-		GET_STRING (U"Only files that match pattern"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoFileInMemorySet result = FileInMemorySet_createFromDirectoryContents (directory, fileGlobber);
+	CREATE_ONE_END (name)
+}
 
-FORM (FileInMemorySet_createCopyFromFileInMemorySet, U"", nullptr)
-	OPTIONMENU (U"Espeakdata", 5)
+FORM (NEW_FileInMemorySet_createCopyFromFileInMemorySet, U"", nullptr) {
+	OPTIONMENUVAR (whichFile, U"Espeakdata", 5)
 		OPTION (U"phons")
 		OPTION (U"dicts")
 		OPTION (U"voices")
-		OPTION (U"variants")
-		OPTION (U"voices_names")
-		OPTION (U"variants_names")
-	OK
-DO
-	long choice = GET_INTEGER (U"Espeakdata");
-	if (choice == 1) {
-		autoFileInMemorySet f = Data_copy (espeakdata_phons.get());
-		praat_new (f.move(), U"espeakdata_phons");
-	}
-	else if (choice == 2) {
-		autoFileInMemorySet f = Data_copy (espeakdata_dicts.get());
-		praat_new (f.move(), U"espeakdata_dicts");
-	}
-	else if (choice == 3) {
-		autoFileInMemorySet f = Data_copy (espeakdata_voices.get());
-		praat_new (f.move(), U"espeakdata_voices");
-	}
-	else if (choice == 4) {
-		autoFileInMemorySet f = Data_copy (espeakdata_variants.get());
-		praat_new (f.move(), U"espeakdata_variants");
-	}
-	else if (choice == 5) {
-		autoStrings s = Data_copy (espeakdata_voices_names.get());
-		praat_new (s.move(), U"espeakdata_voices_names");
-	}
-	else if (choice == 6) {
-		autoStrings s = Data_copy (espeakdata_variants_names.get());
-		praat_new (s.move(), U"espeakdata_variants_names");
-	}
-END
+		OPTION (U"variants")
+		OPTION (U"voices_names")
+		OPTION (U"variants_names")
+	OK
+DO
+	CREATE_ONE
+		autoDaata result;
+		const char32 *name;
+		if (whichFile == 1) {
+			result = Data_copy (espeakdata_phons.get());
+			name = U"espeakdata_phons";
+		}
+		else if (whichFile == 2) {
+			result = Data_copy (espeakdata_dicts.get());
+			name = U"espeakdata_dicts";
+		}
+		else if (whichFile == 3) {
+			result = Data_copy (espeakdata_voices.get());
+			name = U"espeakdata_voices";
+		}
+		else if (whichFile == 4) {
+			result = Data_copy (espeakdata_variants.get());
+			name = U"espeakdata_variants";
+		}
+		else if (whichFile == 5) {
+			result = Data_copy (espeakdata_voices_names.get());
+			name = U"espeakdata_voices_names";
+		}
+		else if (whichFile == 6) {
+			result = Data_copy (espeakdata_variants_names.get());
+			name =  U"espeakdata_variants_names";
+		} else {
+			name = U"";
+		}
+	CREATE_ONE_END (name)
+}
 
-FORM (FileInMemorySet_showAsCode, U"FileInMemorySet: Show as code", nullptr)
-	WORD (U"Name", U"example")
+FORM (INFO_FileInMemorySet_showAsCode, U"FileInMemorySet: Show as code", nullptr) {
+	WORDVAR (name, U"Name", U"example")
 	INTEGER (U"Number of bytes per line", U"20")
 	OK
 DO
-	LOOP {
-		iam (FileInMemorySet);
+	INFO_ONE (FileInMemorySet)
 		MelderInfo_open ();
-		FileInMemorySet_showAsCode (me, GET_STRING (U"Name"), GET_INTEGER (U"Number of bytes per line"));
+		FileInMemorySet_showAsCode (me, name, GET_INTEGER (U"Number of bytes per line"));
 		MelderInfo_close ();
-	}
-END
+	INFO_ONE_END
+}
 
-FORM (FileInMemorySet_showOneFileAsCode, U"FileInMemorySet: Show one file as code", nullptr)
-	NATURAL (U"Index", U"1")
-	WORD (U"Name", U"example")
+FORM (INFO_FileInMemorySet_showOneFileAsCode, U"FileInMemorySet: Show one file as code", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	WORDVAR (name, U"Name", U"example")
 	INTEGER (U"Number of bytes per line", U"20")
 	OK
 DO
-	LOOP {
-		iam (FileInMemorySet);
+	INFO_ONE (FileInMemorySet)
 		MelderInfo_open ();
-		FileInMemorySet_showOneFileAsCode (me, GET_INTEGER (U"Index"), GET_STRING (U"Name"), GET_INTEGER (U"Number of bytes per line"));
+		FileInMemorySet_showOneFileAsCode (me, index, name, GET_INTEGER (U"Number of bytes per line"));
 		MelderInfo_close ();
-	}
-END
+	INFO_ONE_END
+}
 
-DIRECT (FileInMemory_to_FileInMemorySet)
+DIRECT (NEW1_FileInMemory_to_FileInMemorySet) {
 	autoFileInMemorySet thee = FileInMemorySet_create ();
 	LOOP {
 		iam (FileInMemory);
@@ -3124,845 +2533,646 @@ DIRECT (FileInMemory_to_FileInMemorySet)
 		thy addItem_move (him.move());
 	}
 	praat_new (thee.move(), U"files");
-END
+END }
 
-DIRECT (FileInMemorySet_addItems)
-	FileInMemorySet thee = FIRST (FileInMemorySet);
-	LOOP {
-		iam (Daata);
-		if (CLASS == classFileInMemory) {
-			autoFileInMemory him = Data_copy ((FileInMemory) me);
-			thy addItem_move (him.move());
-		}
-	}
-END
+DIRECT (MODIFY_FileInMemorySet_addItems) {
+	MODIFY_FIRST_OF_TWO (FileInMemorySet, FileInMemory)
+		autoFileInMemory him = Data_copy (you);
+		my addItem_move (him.move());
+	MODIFY_FIRST_OF_TWO_END
+}
 
-DIRECT (FileInMemorySets_merge)
-	FileInMemorySet f1 = nullptr, f2 = nullptr;
-	LOOP { 
-		iam (FileInMemorySet);
-		(f1 ? f2 : f1) = me;
-	}
-	Melder_assert (f1 && f2);
-	autoFileInMemorySet result = Data_copy (f1);
-	result -> merge (f2);
-	praat_new (result.move(), f1 -> name, U"_", f2 -> name);
-END
+DIRECT (NEW1_FileInMemorySets_merge) {
+	CONVERT_COUPLE (FileInMemorySet)
+		autoFileInMemorySet result = Data_copy (me);
+		result -> merge (you);
+	CONVERT_COUPLE_END (my name, U"_", your name);
+}
 
-DIRECT (FileInMemorySet_to_Strings_id)
-	LOOP {
-		iam (FileInMemorySet);
+DIRECT (NEW_FileInMemorySet_to_Strings_id) {
+	CONVERT_EACH (FileInMemorySet)
 		autoStrings result = FileInMemorySet_to_Strings_id (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name);
+}
 
 /************************* FilterBank ***********************************/
 
-FORM (FilterBank_drawFilters, U"FilterBank: Draw filters", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
+FORM (GRAPHICS_FilterBank_drawFilters, U"FilterBank: Draw filters", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_drawRows (me, GRAPHICS,
-			GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawRows (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_drawOneContour, U"FilterBank: Draw one contour", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"Height (dB)", U"40.0")
+FORM (GRAPHICS_FilterBank_drawOneContour, U"FilterBank: Draw one contour", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (height, U"Height (dB)", U"40.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_drawOneContour (me, GRAPHICS,
-			GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"Height"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawOneContour (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, height);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_drawContours, U"FilterBank: Draw contours", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
+FORM (GRAPHICS_FilterBank_drawContours, U"FilterBank: Draw contours", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_drawContours (me, GRAPHICS,
-			GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawContours (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_drawFrequencyScales, U"FilterBank: Draw frequency scales", U"FilterBank: Draw frequency scales...")
-	RADIO (U"Horizontal frequency scale", 1)
+FORM (GRAPHICS_FilterBank_drawFrequencyScales, U"FilterBank: Draw frequency scales", U"FilterBank: Draw frequency scales...") {
+	RADIOVAR (xFrequencyScale, U"Horizontal frequency scale", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
 		RADIOBUTTON (U"mel")
-	REAL (U"left Horizontal frequency range", U"0.0")
-	REAL (U"right Horizontal frequency range", U"0.0")
-	RADIO (U"Vertical frequency scale", 1)
+	REALVAR (xFromFrequency, U"left Horizontal frequency range", U"0.0")
+	REALVAR (xToFrequency, U"right Horizontal frequency range", U"0.0")
+	RADIOVAR (yFrequencyScale, U"Vertical frequency scale", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
 		RADIOBUTTON (U"mel")
-	REAL (U"left Vertical frequency range", U"0.0")
-	REAL (U"right Vertical frequency range", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+	REALVAR (yFromFrequency, U"left Vertical frequency range", U"0.0")
+	REALVAR (yToFrequency, U"right Vertical frequency range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FilterBank);
-		FilterBank_drawFrequencyScales (me, GRAPHICS, GET_INTEGER (U"Horizontal frequency scale"),
-			GET_REAL (U"left Horizontal frequency range"), GET_REAL (U"right Horizontal frequency range"),
-			GET_INTEGER (U"Vertical frequency scale"), GET_REAL (U"left Vertical frequency range"),
-			GET_REAL (U"right Vertical frequency range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FilterBank)
+		FilterBank_drawFrequencyScales (me, GRAPHICS, xFrequencyScale, xFromFrequency, xToFrequency, yFrequencyScale, yFromFrequency, yToFrequency, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (MelSpectrogram_paintImage, U"MelSpectrogram: Paint image", U"MelSpectrogram: Paint image...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range (mel)", U"0.0")
-	REAL (U"right Frequency range (mel)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_MelSpectrogram_paintImage, U"MelSpectrogram: Paint image", U"MelSpectrogram: Paint image...") {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (MelSpectrogram);
-		BandFilterSpectrogram_paintImage (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (BandFilterSpectrogram)
+		BandFilterSpectrogram_paintImage (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (BarkSpectrogram_paintImage, U"BarkSpectrogram: Paint image", U"BarkSpectrogram: Paint image...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range (bark)", U"0.0")
-	REAL (U"right Frequency range (bark)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_BarkSpectrogram_paintImage, U"BarkSpectrogram: Paint image", U"BarkSpectrogram: Paint image...") {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (bark)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (bark)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (BarkSpectrogram);
-		BandFilterSpectrogram_paintImage (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (BandFilterSpectrogram)
+		BandFilterSpectrogram_paintImage (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_paintImage, U"FilterBank: Paint image", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
+FORM (GRAPHICS_FilterBank_paintImage, U"FilterBank: Paint image", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_paintImage (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintImage (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_paintContours, U"FilterBank: Paint contours", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
+FORM (GRAPHICS_FilterBank_paintContours, U"FilterBank: Paint contours", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_paintContours (me, GRAPHICS,
-			GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintContours (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (FilterBank_paintCells, U"FilterBank: Paint cells", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
+FORM (GRAPHICS_FilterBank_paintCells, U"FilterBank: Paint cells", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_paintCells (me, GRAPHICS,
-			GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintCells (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_paintSurface, U"FilterBank: Paint surface", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
+FORM (GRAPHICS_FilterBank_paintSurface, U"FilterBank: Paint surface", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_paintSurface (me, GRAPHICS,
-			GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"),
-			30,   // elevation in degrees
-			45);   // azimuth in degrees
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintSurface (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude,30, 45);
+	GRAPHICS_EACH_END
+}
 
-FORM (FilterBank_getFrequencyInHertz, U"FilterBank: Get frequency in Hertz", U"FilterBank: Get frequency in Hertz...")
-	REAL (U"Frequency", U"10.0")
-	RADIO (U"Unit", 2)
+FORM (REAL_FilterBank_getFrequencyInHertz, U"FilterBank: Get frequency in Hertz", U"FilterBank: Get frequency in Hertz...") {
+	REALVAR (frequency, U"Frequency", U"10.0")
+	RADIOVAR (frequencyUnit, U"Unit", 2)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
 		RADIOBUTTON (U"mel")
 	OK
 DO
-	LOOP {
-		iam (FilterBank);
-		double f = FilterBank_getFrequencyInHertz (me,
-			GET_REAL (U"Frequency"),
-			GET_INTEGER (U"Unit"));
-		Melder_informationReal (f, U"Hertz");
-	}
-END
+	NUMBER_ONE (FilterBank)
+		double result = FilterBank_getFrequencyInHertz (me, frequency, frequencyUnit);
+	NUMBER_ONE_END (U" hertz")
+}
 
-FORM (FilterBank_getFrequencyInBark, U"FilterBank: Get frequency in Bark", U"FilterBank: Get frequency in Bark...")
-	REAL (U"Frequency", U"93.17")
-	RADIO (U"Unit", 1)
+FORM (REAL_FilterBank_getFrequencyInBark, U"FilterBank: Get frequency in Bark", U"FilterBank: Get frequency in Bark...") {
+	REALVAR (frequency, U"Frequency", U"93.17")
+	RADIOVAR (frequencyUnit, U"Unit", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
 		RADIOBUTTON (U"mel")
 	OK
 DO
-	LOOP {
-		iam (FilterBank);
-		double f = FilterBank_getFrequencyInBark (me,
-			GET_REAL (U"Frequency"),
-			GET_INTEGER (U"Unit"));
-		Melder_informationReal (f, U"Bark");
-	}
-END
+	NUMBER_ONE (FilterBank)
+		double result = FilterBank_getFrequencyInBark (me, frequency, frequencyUnit);
+	NUMBER_ONE_END (U" bark")
+}
 
-FORM (FilterBank_getFrequencyInMel, U"FilterBank: Get frequency in mel", U"FilterBank: Get frequency in mel...")
-	REAL (U"Frequency", U"1000.0")
-	RADIO (U"Unit", 1)
+FORM (REAL_FilterBank_getFrequencyInMel, U"FilterBank: Get frequency in mel", U"FilterBank: Get frequency in mel...") {
+	REALVAR (frequency, U"Frequency", U"1000.0")
+	RADIOVAR (frequencyUnit, U"Unit", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
 		RADIOBUTTON (U"mel")
 	OK
 DO
-	LOOP {
-		iam (FilterBank);
-		double f = FilterBank_getFrequencyInMel (me,
-			GET_REAL (U"Frequency"),
-			GET_INTEGER (U"Unit"));
-		Melder_informationReal (f, U"mel");
-	}
-END
+	NUMBER_ONE (FilterBank)
+		double result = FilterBank_getFrequencyInMel (me, frequency, frequencyUnit);
+	NUMBER_ONE_END (U" mel")
+}
 
-FORM (FilterBank_equalizeIntensities, U"FilterBank: Equalize intensities", nullptr)
-	REAL (U"Intensity (dB)", U"80.0")
+FORM (MODIFY_FilterBank_equalizeIntensities, U"FilterBank: Equalize intensities", nullptr) {
+	REALVAR (intensity_dB, U"Intensity (dB)", U"80.0")
 	OK
 DO
-	LOOP {
-		iam (FilterBank);
-		FilterBank_equalizeIntensities (me,
-			GET_REAL (U"Intensity"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (FilterBank)
+		FilterBank_equalizeIntensities (me, intensity_dB);
+	MODIFY_EACH_END
+}
 
-FORM (BandFilterSpectrogram_equalizeIntensities, U"BandFilterSpectrogram: Equalize intensities", nullptr)
-	REAL (U"Intensity (dB)", U"80.0")
+FORM (MODIFY_BandFilterSpectrogram_equalizeIntensities, U"BandFilterSpectrogram: Equalize intensities", nullptr) {
+	REALVAR (intensity_dB, U"Intensity (dB)", U"80.0")
 	OK
 DO
-	LOOP {
-		iam (BandFilterSpectrogram);
-		BandFilterSpectrogram_equalizeIntensities (me,
-			GET_REAL (U"Intensity"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (BandFilterSpectrogram)
+		BandFilterSpectrogram_equalizeIntensities (me, intensity_dB);
+	MODIFY_EACH_END
+}
 
-DIRECT (FilterBank_to_Matrix)
-	LOOP {
-		iam (FilterBank);
-		autoMatrix thee = FilterBank_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_FilterBank_to_Matrix) {
+	CONVERT_EACH (FilterBank)
+		autoMatrix result = FilterBank_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (BandFilterSpectrogram_to_Matrix, U"BandFilterSpectrogram: To Matrix", nullptr)
-	BOOLEAN (U"Convert to dB values", 1)
+FORM (NEW_BandFilterSpectrogram_to_Matrix, U"BandFilterSpectrogram: To Matrix", nullptr) {
+	BOOLEANVAR (convertToDB, U"Convert to dB values", 1)
 	OK
 DO
-	LOOP {
-		iam (BandFilterSpectrogram);
-		autoMatrix thee = BandFilterSpectrogram_to_Matrix (me,
-			GET_INTEGER (U"Convert to dB values"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (BandFilterSpectrogram)
+		autoMatrix result = BandFilterSpectrogram_to_Matrix (me, convertToDB);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (FilterBanks_crossCorrelate, U"FilterBanks: Cross-correlate", nullptr)
+FORM (NEW1_FilterBanks_crossCorrelate, U"FilterBanks: Cross-correlate", nullptr) {
 	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
 	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
 	OK
 DO
-	FilterBank f1 = nullptr, f2 = nullptr;
-	LOOP {
-		iam (FilterBank);
-		(f1 ? f2 : f1) = me;
-	}
-	Melder_assert (f1 && f2);
-	autoSound result = FilterBanks_crossCorrelate (f1, f2,
-		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-	praat_new (result.move(), f1 -> name, U"_", f2 -> name);
-END
+	CONVERT_COUPLE (FilterBank)
+		autoSound result = FilterBanks_crossCorrelate (me, you,
+			GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
+			GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (BandFilterSpectrograms_crossCorrelate, U"BandFilterSpectrograms: Cross-correlate", nullptr)
+FORM (NEW1_BandFilterSpectrograms_crossCorrelate, U"BandFilterSpectrograms: Cross-correlate", nullptr) {
 	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
 	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
 	OK
 DO
-	BandFilterSpectrogram f1 = nullptr, f2 = nullptr;
-	LOOP {
-		iam (BandFilterSpectrogram); 
-		(f1 ? f2 : f1) = me;
-	}
-	Melder_assert (f1 && f2);
-	autoSound result = BandFilterSpectrograms_crossCorrelate (f1, f2,
-		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-	praat_new (result.move(), f1 -> name, U"_", f2 -> name);
-END
+	CONVERT_COUPLE (BandFilterSpectrogram)
+		autoSound result = BandFilterSpectrograms_crossCorrelate (me, you,
+			GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
+			GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (FilterBanks_convolve, U"FilterBanks: Convolve", nullptr)
+FORM (NEW1_FilterBanks_convolve, U"FilterBanks: Convolve", nullptr) {
 	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
 	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
 	OK
 DO
-	FilterBank f1 = nullptr, f2 = nullptr;
-	LOOP { iam (FilterBank); (f1 ? f2 : f1) = me; }
-	Melder_assert (f1 && f2);
-	autoSound result = FilterBanks_convolve (f1, f2,
-		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-	praat_new (result.move(), f1 -> name, U"_", f2 -> name);
-END
+	CONVERT_COUPLE (FilterBank)
+		autoSound result = FilterBanks_convolve (me, you,
+			GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
+			GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (BandFilterSpectrograms_convolve, U"BandFilterSpectrograms: Convolve", nullptr)
+FORM (NEW1_BandFilterSpectrograms_convolve, U"BandFilterSpectrograms: Convolve", nullptr) {
 	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
 	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
 	OK
 DO
-	BandFilterSpectrogram f1 = nullptr, f2 = nullptr;
-	LOOP {
-		iam (BandFilterSpectrogram);
-		(f1 ? f2 : f1) = me;
-	}
-	Melder_assert (f1 && f2);
-	autoSound result = BandFilterSpectrograms_convolve (f1, f2,
-		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-	praat_new (result.move(), f1 -> name, U"_", f2 -> name);
-END
+	CONVERT_COUPLE (BandFilterSpectrogram)
+		autoSound result = BandFilterSpectrograms_convolve (me, you,
+			GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
+			GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-DIRECT (FilterBank_to_Intensity)
-	LOOP {
-		iam (FilterBank);
+DIRECT (NEW_FilterBank_to_Intensity) {
+	CONVERT_EACH (FilterBank)
 		autoIntensity result = FilterBank_to_Intensity (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (BandFilterSpectrogram_to_Intensity)
-	LOOP {
-		iam (BandFilterSpectrogram);
+DIRECT (NEW_BandFilterSpectrogram_to_Intensity) {
+	CONVERT_EACH (BandFilterSpectrogram)
 		autoIntensity result = BandFilterSpectrogram_to_Intensity (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
 /*********** FormantFilter *******************************************/
 
-DIRECT (FormantFilter_help)
-	Melder_help (U"FormantFilter");
-END
+DIRECT (HELP_FormantFilter_help) {
+	HELP (U"FormantFilter")
+}
 
-FORM (FormantFilter_drawFilterFunctions, U"FormantFilter: Draw filter functions", U"FilterBank: Draw filter functions...")
-	INTEGER (U"left Filter range", U"0")
-	INTEGER (U"right Filter range", U"0")
-	POSITIVE (U"Bandwidth (Hz)", U"100.0")
-	RADIO (U"Frequency scale", 1)
-	RADIOBUTTON (U"Hertz")
-	RADIOBUTTON (U"Bark")
-	RADIOBUTTON (U"mel")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	BOOLEAN (U"Amplitude scale in dB", 1)
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_FormantFilter_drawFilterFunctions, U"FormantFilter: Draw filter functions", U"FilterBank: Draw filter functions...") {
+	INTEGERVAR (fromFilter, U"left Filter range", U"0")
+	INTEGERVAR (toFilter, U"right Filter range", U"0")
+	POSITIVEVAR (bandwidth, U"Bandwidth (Hz)", U"100.0")
+	RADIOVAR (frequencyScale, U"Frequency scale", 1)
+		RADIOBUTTON (U"Hertz")
+		RADIOBUTTON (U"Bark")
+		RADIOBUTTON (U"mel")
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	BOOLEANVAR (dBScale, U"Amplitude scale in dB", 1)
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantFilter);
-		FormantFilter_drawFilterFunctions (me, GRAPHICS, GET_REAL (U"Bandwidth"), GET_INTEGER (U"Frequency scale"),
-			GET_INTEGER (U"left Filter range"), GET_INTEGER (U"right Filter range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Amplitude scale in dB"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FormantFilter)
+		FormantFilter_drawFilterFunctions (me, GRAPHICS, bandwidth, frequencyScale, fromFilter, toFilter, fromFrequency, toFrequency, dBScale, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FormantFilter_drawSpectrum, U"FormantFilter: Draw spectrum (slice)", U"FilterBank: Draw spectrum (slice)...")
-	POSITIVE (U"Time (s)", U"0.1")
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_FormantFilter_drawSpectrum, U"FormantFilter: Draw spectrum (slice)", U"FilterBank: Draw spectrum (slice)...") {
+	REALVAR (time, U"Time (s)", U"0.1")
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FilterBank);
-		FilterBank_drawTimeSlice (me, GRAPHICS, GET_REAL (U"Time"), GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), U"Hz", GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FilterBank)
+		FilterBank_drawTimeSlice (me, GRAPHICS, time, fromFrequency, toFrequency, fromAmplitude, toAmplitude, U"Hz", garnish);
+	GRAPHICS_EACH_END
+}
 
 /****************** FormantGrid  *********************************/
 
-FORM (old_FormantGrid_draw, U"FormantGrid: Draw", 0)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0 (= auto)")
-	BOOLEAN (U"Bandwidths", false)
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_old_FormantGrid_draw, U"FormantGrid: Draw", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0 (= auto)")
+	BOOLEANVAR (bandwidths, U"Bandwidths", false)
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantGrid);
-		FormantGrid_draw (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Bandwidths"), GET_INTEGER (U"Garnish"), U"lines and speckles");
-	}
-END
-
-FORM (FormantGrid_draw, U"FormantGrid: Draw", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0 (= auto)")
-	BOOLEAN (U"Bandwidths", false)
-	BOOLEAN (U"Garnish", true)
+	GRAPHICS_EACH (FormantGrid)
+		FormantGrid_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, bandwidths, garnish, U"lines and speckles");
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_FormantGrid_draw, U"FormantGrid: Draw", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0 (= auto)")
+	BOOLEANVAR (bandwidths, U"Bandwidths", false)
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 1)
-	OPTION (U"lines")
-	OPTION (U"speckles")
-	OPTION (U"lines and speckles")
-	OK
-DO_ALTERNATIVE (old_FormantGrid_draw)
-	autoPraatPicture picture;
-	LOOP {
-		iam (FormantGrid);
-		FormantGrid_draw (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Bandwidths"), GET_INTEGER (U"Garnish"), GET_STRING (U"Drawing method"));
-	}
-END
+	OPTIONMENUSTRVAR (drawingMethod, U"Drawing method", 1)
+		OPTION (U"lines")
+		OPTION (U"speckles")
+		OPTION (U"lines and speckles")
+	OK
+DO_ALTERNATIVE (GRAPHICS_old_FormantGrid_draw)
+	GRAPHICS_EACH (FormantGrid)
+		FormantGrid_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, bandwidths, garnish, drawingMethod);
+	GRAPHICS_EACH_END
+}
 
 /****************** FunctionTerms  *********************************/
 
-FORM (FunctionTerms_draw, U"FunctionTerms: Draw", nullptr)
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Extrapolate", false)
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_FunctionTerms_draw, U"FunctionTerms: Draw", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (extrapolate, U"Extrapolate", false)
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FunctionTerms);
-		FunctionTerms_draw (me, GRAPHICS, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Extrapolate"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FunctionTerms)
+		FunctionTerms_draw (me, GRAPHICS, xmin, xmax, ymin, ymax,extrapolate, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FunctionTerms_drawBasisFunction, U"FunctionTerms: Draw basis function", nullptr)
-	NATURAL (U"Index", U"1")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Extrapolate", false)
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_FunctionTerms_drawBasisFunction, U"FunctionTerms: Draw basis function", nullptr) {
+	NATURALVAR (index, U"Index", U"1")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (extrapolate, U"Extrapolate", false)
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FunctionTerms);
-		FunctionTerms_drawBasisFunction (me, GRAPHICS, GET_INTEGER (U"Index"), GET_REAL (U"Xmin"),
-			GET_REAL (U"Xmax"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Extrapolate"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FunctionTerms)
+		FunctionTerms_drawBasisFunction (me, GRAPHICS, index, xmin, xmax, ymin, ymax, extrapolate, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (FunctionTerms_evaluate, U"FunctionTerms: Evaluate", nullptr)
-	REAL (U"X", U"0.0")
+FORM (REAL_FunctionTerms_evaluate, U"FunctionTerms: Evaluate", nullptr) {
+	REALVAR (x, U"X", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FunctionTerms);
-		Melder_information (FunctionTerms_evaluate (me, GET_REAL (U"X")));
-	}
-END
+	NUMBER_ONE (FunctionTerms)
+		double result = FunctionTerms_evaluate (me, x);
+	NUMBER_ONE_END (U"")
+}
 
-DIRECT (FunctionTerms_getNumberOfCoefficients)
-	LOOP {
-		iam (FunctionTerms);
-		Melder_information (my numberOfCoefficients);
-	}
-END
+DIRECT (INTEGER_FunctionTerms_getNumberOfCoefficients) {
+	INTEGER_ONE (FunctionTerms)
+		long result = my numberOfCoefficients;
+	INTEGER_ONE_END (U"")
+}
 
-FORM (FunctionTerms_getCoefficient, U"FunctionTerms: Get coefficient", nullptr)
+FORM (REAL_FunctionTerms_getCoefficient, U"FunctionTerms: Get coefficient", nullptr) {
 	LABEL (U"", U"p(x) = c[1] + c[2] x + ... c[n+1] x^n")
-	NATURAL (U"Index", U"1")
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (FunctionTerms);
-		if (index > my numberOfCoefficients) {
-			Melder_throw (U"Index too large.");
-		}
-		Melder_information (my coefficients[index]);
-	}
-END
+	NUMBER_ONE (FunctionTerms)
+		double result = (index > 0 && index <= my numberOfCoefficients) ? my coefficients [index] : NUMundefined;
+	NUMBER_ONE_END (U"")
+}
 
-DIRECT (FunctionTerms_getDegree)
-	LOOP {
-		iam (FunctionTerms);
-		Melder_information (FunctionTerms_getDegree (me));
-	}
-END
+DIRECT (INTEGER_FunctionTerms_getDegree) {
+	INTEGER_ONE (FunctionTerms)
+		long result = FunctionTerms_getDegree (me);
+	INTEGER_ONE_END (U"")
+}
 
-FORM (FunctionTerms_getMaximum, U"FunctionTerms: Get maximum", U"Polynomial: Get maximum...")
+FORM (REAL_FunctionTerms_getMaximum, U"FunctionTerms: Get maximum", U"Polynomial: Get maximum...") {
 	LABEL (U"", U"Interval")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FunctionTerms);
-		double x = FunctionTerms_getMaximum (me, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"));
-		Melder_information (x);
-	}
-END
+	NUMBER_ONE (FunctionTerms)
+		double result = FunctionTerms_getMaximum (me, xmin, xmax);
+	NUMBER_ONE_END (U" (maximum)")
+}
 
-FORM (FunctionTerms_getMinimum, U"FunctionTerms: Get minimum", U"Polynomial: Get minimum...")
+FORM (REAL_FunctionTerms_getMinimum, U"FunctionTerms: Get minimum", U"Polynomial: Get minimum...") {
 	LABEL (U"", U"Interval")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FunctionTerms);
-		double x = FunctionTerms_getMinimum (me, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"));
-		Melder_information (x);
-	}
-END
+	NUMBER_ONE (FunctionTerms)
+		double result = FunctionTerms_getMinimum (me, xmin, xmax);
+	NUMBER_ONE_END (U" (minimum)")
+}
 
-FORM (FunctionTerms_getXOfMaximum, U"FunctionTerms: Get x of maximum", U"Polynomial: Get x of maximum...")
+FORM (REAL_FunctionTerms_getXOfMaximum, U"FunctionTerms: Get x of maximum", U"Polynomial: Get x of maximum...") {
 	LABEL (U"", U"Interval")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FunctionTerms);
-		double x = FunctionTerms_getXOfMaximum (me, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"));
-		Melder_information (x);
-	}
-END
+	NUMBER_ONE (FunctionTerms)
+		double result = FunctionTerms_getXOfMaximum (me, xmin, xmax);
+	NUMBER_ONE_END (U" (x of maximum)")
+}
 
-FORM (FunctionTerms_getXOfMinimum, U"FunctionTerms: Get x of minimum", U"Polynomial: Get x of minimum...")
+FORM (REAL_FunctionTerms_getXOfMinimum, U"FunctionTerms: Get x of minimum", U"Polynomial: Get x of minimum...") {
 	LABEL (U"", U"Interval")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FunctionTerms);
-		double x = FunctionTerms_getXOfMinimum (me, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"));
-		Melder_information (x);
-	}
-END
+	NUMBER_ONE (FunctionTerms)
+		double result = FunctionTerms_getXOfMinimum (me, xmin, xmax);
+	NUMBER_ONE_END (U" (x of minimum)")
+}
 
-FORM (FunctionTerms_setCoefficient, U"FunctionTerms: Set coefficient", nullptr)
+FORM (MODIFY_FunctionTerms_setCoefficient, U"FunctionTerms: Set coefficient", nullptr) {
 	LABEL (U"", U"p(x) = c[1]F[0] + c[2]F[1] + ... c[n+1]F[n]")
 	LABEL (U"", U"F[k] is of degree k")
-	NATURAL (U"Index", U"1")
-	REAL (U"Value", U"0.0")
+	NATURALVAR (index, U"Index", U"1")
+	REALVAR (value, U"Value", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (FunctionTerms);
-		FunctionTerms_setCoefficient (me, GET_INTEGER (U"Index"), GET_REAL (U"Value"));
-	}
-END
+	MODIFY_EACH (FunctionTerms)
+		FunctionTerms_setCoefficient (me, index, value);
+	MODIFY_EACH_END
+}
 
-FORM (FunctionTerms_setDomain, U"FunctionTerms: Set domain", nullptr)
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"2.0")
+FORM (MODIFY_FunctionTerms_setDomain, U"FunctionTerms: Set domain", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"2.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	LOOP {
-		iam (FunctionTerms);
+	MODIFY_EACH (FunctionTerms)
 		if (xmax <= xmin) {
 			Melder_throw (U"Xmax should be larger than Xmin.");
 		}
 		FunctionTerms_setDomain (me, xmin, xmax);
-	}
-END
+	MODIFY_EACH_END
+}
 
 /***************** Intensity ***************************************************/
 
-FORM (Intensity_to_TextGrid_detectSilences, U"Intensity: To TextGrid (silences)", U"Intensity: To TextGrid (silences)...")
-	REAL (U"Silence threshold (dB)", U"-25.0")
-	POSITIVE (U"Minimum silent interval duration (s)", U"0.1")
-	POSITIVE (U"Minimum sounding interval duration (s)", U"0.05")
-	WORD (U"Silent interval label", U"silent")
-	WORD (U"Sounding interval label", U"sounding")
+FORM (NEW_Intensity_to_TextGrid_detectSilences, U"Intensity: To TextGrid (silences)", U"Intensity: To TextGrid (silences)...") {
+	REALVAR (silenceThreshold, U"Silence threshold (dB)", U"-25.0")
+	POSITIVEVAR (minimumSilenceDuration, U"Minimum silent interval duration (s)", U"0.1")
+	POSITIVEVAR (minimumSoundingDuration, U"Minimum sounding interval duration (s)", U"0.05")
+	WORDVAR (silenceLabel, U"Silent interval label", U"silent")
+	WORDVAR (soundingLabel, U"Sounding interval label", U"sounding")
 	OK
 DO
-	LOOP {
-		iam (Intensity);
-		autoTextGrid thee = Intensity_to_TextGrid_detectSilences (me, GET_REAL (U"Silence threshold"),
-			GET_REAL (U"Minimum silent interval duration"), GET_REAL (U"Minimum sounding interval duration"),
-			GET_STRING (U"Silent interval label"), GET_STRING (U"Sounding interval label"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Intensity)
+		autoTextGrid result = Intensity_to_TextGrid_detectSilences (me, silenceThreshold, minimumSilenceDuration, minimumSoundingDuration, silenceLabel, soundingLabel);
+	CONVERT_EACH_END (my name)
+}
 
 /***************** IntensityTier ***************************************************/
 
-FORM (IntensityTier_to_TextGrid_detectSilences, U"IntensityTier: To TextGrid (silences)", U"Intensity: To TextGrid (silences)...")
-	REAL (U"Silence threshold (dB)", U"-25.0")
-	POSITIVE (U"Minimum silent interval duration (s)", U"0.1")
-	POSITIVE (U"Minimum sounding interval duration (s)", U"0.05")
-	WORD (U"Silent interval label", U"silent")
-	WORD (U"Sounding interval label", U"sounding")
-	POSITIVE (U"Time step (s)", U"0.001")
+FORM (NEW_IntensityTier_to_TextGrid_detectSilences, U"IntensityTier: To TextGrid (silences)", U"Intensity: To TextGrid (silences)...") {
+	REALVAR (silenceThreshold, U"Silence threshold (dB)", U"-25.0")
+	POSITIVEVAR (minimumSilenceDuration, U"Minimum silent interval duration (s)", U"0.1")
+	POSITIVEVAR (minimumSoundingDuration, U"Minimum sounding interval duration (s)", U"0.05")
+	WORDVAR (silenceLabel, U"Silent interval label", U"silent")
+	WORDVAR (soundingLabel, U"Sounding interval label", U"sounding")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.001")
 	OK
 DO
-	LOOP {
-		iam (IntensityTier);
-		autoTextGrid thee = IntensityTier_to_TextGrid_detectSilences (me, GET_REAL (U"Time step"), GET_REAL (U"Silence threshold"),
-			GET_REAL (U"Minimum silent interval duration"), GET_REAL (U"Minimum sounding interval duration"),
-			GET_STRING (U"Silent interval label"), GET_STRING (U"Sounding interval label"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (IntensityTier)
+		autoTextGrid result = IntensityTier_to_TextGrid_detectSilences (me, timeStep, silenceThreshold, minimumSilenceDuration, minimumSoundingDuration, silenceLabel, soundingLabel);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (IntensityTier_to_Intensity, U"", nullptr)
-	POSITIVE (U"Time step (s)", U"0.001")
+FORM (NEW_IntensityTier_to_Intensity, U"", nullptr) {
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.001")
 	OK
 DO
-	LOOP {
-		iam (IntensityTier);
-		autoIntensity thee = IntensityTier_to_Intensity (me, GET_REAL (U"Time step"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (IntensityTier)
+		autoIntensity result = IntensityTier_to_Intensity (me, timeStep);
+	CONVERT_EACH_END (my name)
+}
 
 /***************** ISpline ***************************************************/
 
-DIRECT (ISpline_help) Melder_help (U"ISpline"); END
+DIRECT (HELP_ISpline_help) {
+	HELP (U"ISpline")
+}
 
-FORM (ISpline_create, U"Create ISpline", U"Create ISpline...")
-	WORD (U"Name", U"ispline")
+FORM (NEW1_ISpline_create, U"Create ISpline", U"Create ISpline...") {
+	WORDVAR (name, U"Name", U"ispline")
 	LABEL (U"", U"Domain")
-	REAL (U"Xmin", U"0")
-	REAL (U"Xmax", U"1")
+	REALVAR (xmin, U"Xmin", U"0")
+	REALVAR (xmax, U"Xmax", U"1")
 	LABEL (U"", U"ISpline(x) = c[1] I[1](x) + c[2] I[1](x) + ... c[n] I[n](x)")
 	LABEL (U"", U"all I[k] are polynomials of degree \"Degree\"")
 	LABEL (U"", U"Relation: numberOfCoefficients == numberOfInteriorKnots + degree")
-	INTEGER (U"Degree", U"3")
-	SENTENCE (U"Coefficients (c[k])", U"1.2 2.0 1.2 1.2 3.0 0.0")
-	SENTENCE (U"Interior knots" , U"0.3 0.5 0.6")
+	INTEGERVAR (degree, U"Degree", U"3")
+	SENTENCEVAR (coefficients_string, U"Coefficients (c[k])", U"1.2 2.0 1.2 1.2 3.0 0.0")
+	SENTENCEVAR (knots_string, U"Interior knots" , U"0.3 0.5 0.6")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	long degree = GET_INTEGER (U"Degree");
-	if (xmax <= xmin) {
-		Melder_throw (U"Xmin should be smaller than Xmax.");
-	}
-	autoISpline me = ISpline_createFromStrings (xmin, xmax, degree,
-		GET_STRING (U"Coefficients"), GET_STRING (U"Interior knots"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		if (xmax <= xmin) {
+			Melder_throw (U"Xmin should be smaller than Xmax.");
+		}
+		autoISpline result = ISpline_createFromStrings (xmin, xmax, degree, coefficients_string, knots_string);
+	CREATE_ONE_END (name)
+}
 
 /******************* KlattTable  *********************************/
 
-DIRECT (KlattTable_help) Melder_help (U"KlattTable"); END
-
-DIRECT (KlattTable_createExample)
-	autoKlattTable thee = KlattTable_createExample ();
-	praat_new (thee.move(), U"example");
-END
-
-FORM (KlattTable_to_Sound, U"KlattTable: To Sound", U"KlattTable: To Sound...")
-	POSITIVE (U"Sampling frequency", U"16000")
-	RADIO (U"Synthesis model", 1)
-	RADIOBUTTON (U"Cascade")
-	RADIOBUTTON (U"Parallel")
-	NATURAL (U"Number of formants", U"5")
-	POSITIVE (U"Frame duration (s)", U"0.005")
-	REAL (U"Flutter percentage (%)", U"0.0")   // ppgb: foutgevoelig
-	OPTIONMENU (U"Voicing source", 1)
-	OPTION (U"Impulsive")
-	OPTION (U"Natural")
-	OPTIONMENU (U"Output type", 1)
-	OPTION (U"Sound")
-	OPTION (U"Voicing")
-	OPTION (U"Aspiration")
-	OPTION (U"Frication")
-	OPTION (U"Cascade-glottal-output")
-	OPTION (U"Parallel-glottal-output")
-	OPTION (U"Bypass-output")
-	OPTION (U"All-excitations")
-	OK
-DO
-	double flutter = GET_REAL (U"Flutter percentage");
-	int outputType = GET_INTEGER (U"Output type") - 1;
-	if (flutter < 0.0 || flutter > 100.0) {
+DIRECT (HELP_KlattTable_help) {
+	HELP (U"KlattTable")
+}
+
+DIRECT (NEW1_KlattTable_createExample) {
+	CREATE_ONE
+		autoKlattTable result = KlattTable_createExample ();
+	CREATE_ONE_END (U"example")
+}
+
+FORM (NEW_KlattTable_to_Sound, U"KlattTable: To Sound", U"KlattTable: To Sound...") {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"16000")
+	RADIOVAR (synthesisModel, U"Synthesis model", 1)
+		RADIOBUTTON (U"Cascade")
+		RADIOBUTTON (U"Parallel")
+	NATURALVAR (numberOfFormants, U"Number of formants", U"5")
+	POSITIVEVAR (frameDuration, U"Frame duration (s)", U"0.005")
+	REALVAR (flutter_percentage, U"Flutter percentage (%)", U"0.0")   // ppgb: foutgevoelig
+	OPTIONMENUVAR (voicingSource, U"Voicing source", 1)
+		OPTION (U"Impulsive")
+		OPTION (U"Natural")
+	OPTIONMENUVAR (soundOutputType, U"Output type", 1)
+		OPTION (U"Sound")
+		OPTION (U"Voicing")
+		OPTION (U"Aspiration")
+		OPTION (U"Frication")
+		OPTION (U"Cascade-glottal-output")
+		OPTION (U"Parallel-glottal-output")
+		OPTION (U"Bypass-output")
+		OPTION (U"All-excitations")
+	OK
+DO
+	if (flutter_percentage < 0.0 || flutter_percentage > 100.0) {
 		Melder_throw (U"Flutter should be between 0 and 100%.");
 	}
-	LOOP {
-		iam (KlattTable);
-		autoSound thee = KlattTable_to_Sound (me, GET_REAL (U"Sampling frequency"), GET_INTEGER (U"Synthesis model"),
-			GET_INTEGER (U"Number of formants"), GET_REAL (U"Frame duration"), GET_INTEGER (U"Voicing source"),
-			GET_REAL (U"Flutter percentage"), outputType);
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (KlattTable)
+		autoSound result = KlattTable_to_Sound (me, samplingFrequency, synthesisModel, numberOfFormants, frameDuration, voicingSource, flutter_percentage, soundOutputType);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (KlattTable_to_KlattGrid, U"KlattTable: To KlattGrid", nullptr)
-	POSITIVE (U"Frame duration (s)", U"0.002")
+FORM (NEW_KlattTable_to_KlattGrid, U"KlattTable: To KlattGrid", nullptr) {
+	POSITIVEVAR (frameDuration, U"Frame duration (s)", U"0.002")
 	OK
 DO
-	LOOP {
-		iam (KlattTable);
-		praat_new (KlattTable_to_KlattGrid (me, GET_REAL (U"Frame duration")), my name);
-	}
-END
+	CONVERT_EACH (KlattTable)
+		autoKlattGrid result = KlattTable_to_KlattGrid (me, frameDuration);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (KlattTable_to_Table)
-	LOOP {
-		iam (KlattTable);
-		autoTable thee = KlattTable_to_Table (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_KlattTable_to_Table) {
+	CONVERT_EACH (KlattTable)
+		autoTable result = KlattTable_to_Table (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Table_to_KlattTable)
-	LOOP {
-		iam (Table);
-		autoKlattTable thee = Table_to_KlattTable (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Table_to_KlattTable) {
+	CONVERT_EACH (Table)
+		autoKlattTable result = Table_to_KlattTable (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Table_getMedianAbsoluteDeviation, U"Table: Get median absolute deviation", U"Table: Get median absolute deviation...")
-	SENTENCE (U"Column label", U"")
+FORM (REAL_Table_getMedianAbsoluteDeviation, U"Table: Get median absolute deviation", U"Table: Get median absolute deviation...") {
+	SENTENCEVAR (columnLabel, U"Column label", U"")
 	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		double mad = Table_getMedianAbsoluteDeviation (me, icol);
-		Melder_information (mad);
-	}
-END
+	NUMBER_ONE (Table)
+		long icol = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		double result = Table_getMedianAbsoluteDeviation (me, icol);
+	NUMBER_ONE_END (U"")
+}
 
 static void print_means (Table me);
 static void print_means (Table me) {
@@ -3985,1996 +3195,1652 @@ static void print_means (Table me) {
 	}
 }
 
-FORM (Table_getNumberOfRowsWhere, U"", nullptr)
+FORM (INTEGER_Table_getNumberOfRowsWhere, U"", nullptr) {
 	LABEL (U"", U"Count only rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"M\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"M\"")
 	OK
 DO
-	LOOP {
-		iam (Table);
-		long numberOfRows = Table_getNumberOfRowsWhere (me, GET_STRING (U"Formula"), interpreter);
-		Melder_information (numberOfRows);
-	}
-END
+	INTEGER_ONE (Table)
+		long result = Table_getNumberOfRowsWhere (me, formula, interpreter);
+	INTEGER_ONE_END (U"")
+}
 
-FORM (Table_reportOneWayAnova, U"Table: Report one-way anova",  U"Table: Report one-way anova...")
-	SENTENCE (U"Column with data", U"F0")
-	SENTENCE (U"Factor", U"Vowel")
-	BOOLEAN (U"Table with means", false);
-	BOOLEAN (U"Table with differences between means", false)
-	BOOLEAN (U"Table with Tukey's post-hoc HSD test", false)
+FORM (INFO_Table_reportOneWayAnova, U"Table: Report one-way anova",  U"Table: Report one-way anova...") {
+	SENTENCEVAR (dataColumn_string, U"Column with data", U"F0")
+	SENTENCEVAR (factor_string, U"Factor", U"Vowel")
+	BOOLEANVAR (wantMeans, U"Table with means", false);
+	BOOLEANVAR (wantDifferencesBetweenMeans, U"Table with differences between means", false)
+	BOOLEANVAR (wantTukeyPostHoc, U"Table with Tukey's post-hoc HSD test", false)
 	OK
 DO
-	char32 *factor = GET_STRING (U"Factor");
-	char32 *dataLabel = GET_STRING (U"Column with data");
-	bool getMeans = GET_INTEGER (U"Table with means");
-	bool getMeansDiff = GET_INTEGER (U"Table with differences between means");
-	bool getMeansDiffProbabilities = GET_INTEGER (U"Table with Tukey's post-hoc HSD test");
-	LOOP {
-		iam (Table);
-		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factor);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataLabel);
+	INFO_ONE (Table)
+		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factor_string);
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
 		autoTable means, meansDiff, meansDiffProbabilities;
 		autoTable anova = Table_getOneWayAnalysisOfVarianceF (me, dataColumn, factorColumn, &means, &meansDiff, & meansDiffProbabilities);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"One-way analysis of \"", dataLabel, U"\" by \"", factor, U"\".\n");
+		MelderInfo_writeLine (U"One-way analysis of \"", dataColumn_string, U"\" by \"", factor_string, U"\".\n");
 		Table_printAsAnovaTable (anova.get());
 		MelderInfo_writeLine (U"\nMeans:\n");
 		print_means (means.get());
 		MelderInfo_close ();
-		if (getMeans) {
+		if (wantMeans) {
 			praat_new (means.move(), my name, U"_groupMeans");
 		}
-		if (getMeansDiff) {
+		if (wantDifferencesBetweenMeans) {
 			praat_new (meansDiff.move(), my name, U"_meansDiff");
 		}
-		if (getMeansDiffProbabilities) {
+		if (wantTukeyPostHoc) {
 			praat_new (meansDiffProbabilities.move(), my name, U"_meansDiffP");
 		}
-	}
-END
+	INFO_ONE_END
+}
 
-FORM (Table_reportTwoWayAnova, U"Table: Report two-way anova", U"Table: Report two-way anova...")
-	SENTENCE (U"Column with data", U"Data")
-	SENTENCE (U"First factor", U"A")
-	SENTENCE (U"Second factor", U"B")
-	BOOLEAN (U"Table with means", 0);
+FORM (INFO_Table_reportTwoWayAnova, U"Table: Report two-way anova", U"Table: Report two-way anova...") {
+	SENTENCEVAR (dataColumn_string, U"Column with data", U"Data")
+	SENTENCEVAR (firstFactor_string, U"First factor", U"A")
+	SENTENCEVAR (secondFactor_string, U"Second factor", U"B")
+	BOOLEANVAR (wantMeans, U"Table with means", 0);
 	OK
 DO
-	char32 *factorA = GET_STRING (U"First factor");
-	char32 *factorB = GET_STRING (U"Second factor");
-	char32 *dataLabel = GET_STRING (U"Column with data");
-	bool getMeans = GET_INTEGER (U"Table with means");
-	LOOP {
-		iam (Table);
-		long factorColumnA = Table_getColumnIndexFromColumnLabel (me, factorA);
-		long factorColumnB = Table_getColumnIndexFromColumnLabel (me, factorB);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataLabel);
+	INFO_ONE (Table)
+		long firstFactorColumn = Table_getColumnIndexFromColumnLabel (me, firstFactor_string);
+		long secondFactorColumn = Table_getColumnIndexFromColumnLabel (me, secondFactor_string);
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
 		autoTable means, sizes;
-		autoTable anova = Table_getTwoWayAnalysisOfVarianceF (me, dataColumn, factorColumnA, factorColumnB, &means, &sizes);
+		autoTable anova = Table_getTwoWayAnalysisOfVarianceF (me, dataColumn, firstFactorColumn, secondFactorColumn, &means, &sizes);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"Two-way analysis of \"", dataLabel, U"\" by \"", factorA, U"\" and \"", factorB, U".\n");
-		Table_printAsAnovaTable (anova.get());
-		MelderInfo_writeLine (U"\nMeans:\n");
-		Table_printAsMeansTable (means.get());
-		MelderInfo_writeLine (U"\nCell sizes:\n");
-		Table_printAsMeansTable (sizes.get());
+			MelderInfo_writeLine (U"Two-way analysis of \"", dataColumn_string, U"\" by \"", firstFactor_string, U"\" and \"", secondFactor_string, U".\n");
+			Table_printAsAnovaTable (anova.get());
+			MelderInfo_writeLine (U"\nMeans:\n");
+			Table_printAsMeansTable (means.get());
+			MelderInfo_writeLine (U"\nCell sizes:\n");
+			Table_printAsMeansTable (sizes.get());
 		MelderInfo_close ();
-		if (getMeans) {
+		if (wantMeans) {
 			praat_new (means.move(), my name, U"_groupMeans");
 		}
-	}
-END
+	INFO_ONE_END
+}
 
-FORM (Table_reportOneWayKruskalWallis, U"Table: Report one-way Kruskal-Wallis", U"Table: Report one-way Kruskal-Wallis...")
-	SENTENCE (U"Column with data", U"Data")
-	SENTENCE (U"Factor", U"Group")
+FORM (INFO_Table_reportOneWayKruskalWallis, U"Table: Report one-way Kruskal-Wallis", U"Table: Report one-way Kruskal-Wallis...") {
+	SENTENCEVAR (dataColumn_string, U"Column with data", U"Data")
+	SENTENCEVAR (factor_string, U"Factor", U"Group")
 	OK
 DO
-	char32 *factor = GET_STRING (U"Factor");
-	char32 *dataLabel = GET_STRING (U"Column with data");
-	LOOP {
-		iam (Table);
-		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factor);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataLabel);
+	INFO_ONE (Table)
+		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factor_string);
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
 		double df, kruskalWallis, prob;
-		autoTable thee = Table_getOneWayKruskalWallis (me, dataColumn, factorColumn, & prob, & kruskalWallis, & df);
+		autoTable result = Table_getOneWayKruskalWallis (me, dataColumn, factorColumn, & prob, & kruskalWallis, & df);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"One-way Kruskal-Wallis of \"", dataLabel, U"\" by \"", factor, U"\".\n");
-		MelderInfo_writeLine (U"Chi squared: ", kruskalWallis);
-		MelderInfo_writeLine (U"Degrees of freedom: ", df);
-		MelderInfo_writeLine (U"Probability: ", prob);
-		MelderInfo_writeLine (U"\nMeans:\n");
-		print_means (thee.get());
+			MelderInfo_writeLine (U"One-way Kruskal-Wallis of \"", dataColumn_string, U"\" by \"", factor_string, U"\".\n");
+			MelderInfo_writeLine (U"Chi squared: ", kruskalWallis);
+			MelderInfo_writeLine (U"Degrees of freedom: ", df);
+			MelderInfo_writeLine (U"Probability: ", prob);
+			MelderInfo_writeLine (U"\nMeans:\n");
+			print_means (result.get());
 		MelderInfo_close ();
-		//praat_new (move(), my name, U"_groupMeans");
-	}
-END
+	INFO_ONE_END
+}
 
-FORM (Table_to_StringsIndex_column, U"Table: To StringsIndex (column)", nullptr)
-	SENTENCE (U"Column label", U"")
+FORM (NEW_Table_to_StringsIndex_column, U"Table: To StringsIndex (column)", nullptr) {
+	SENTENCEVAR (columnLabel, U"Column label", U"")
 	OK
 DO
-	char32 *columnLabel = GET_STRING (U"Column label");
-	LOOP {
-		iam (Table);
+	CONVERT_EACH (Table)
 		long icol = Table_getColumnIndexFromColumnLabel (me, columnLabel);
-		autoStringsIndex thee = Table_to_StringsIndex_column (me, icol);
-		praat_new (thee.move(), my name, U"_", columnLabel);
-	}
-END
+		autoStringsIndex result = Table_to_StringsIndex_column (me, icol);
+	CONVERT_EACH_END (my name, U"_", columnLabel)
+}
 
 /******************* LegendreSeries *********************************/
 
-FORM (LegendreSeries_create, U"Create LegendreSeries", U"Create LegendreSeries...")
-	WORD (U"Name", U"ls")
+FORM (NEW1_LegendreSeries_create, U"Create LegendreSeries", U"Create LegendreSeries...") {
+	WORDVAR (name, U"Name", U"ls")
 	LABEL (U"", U"Domain")
-	REAL (U"Xmin", U"-1")
-	REAL (U"Xmax", U"1")
+	REALVAR (xmin, U"Xmin", U"-1")
+	REALVAR (xmax, U"Xmax", U"1")
 	LABEL (U"", U"LegendreSeries(x) = c[1] P[0](x) + c[2] P[1](x) + ... c[n+1] P[n](x)")
 	LABEL (U"", U"P[k] is a Legendre polynomial of degree k")
-	SENTENCE (U"Coefficients", U"0 0 1.0")
+	SENTENCEVAR (coefficients_string, U"Coefficients", U"0 0 1.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	praat_new (LegendreSeries_createFromString (xmin, xmax, GET_STRING (U"Coefficients")), GET_STRING (U"Name"));
-END
+	REQUIRE  (xmin < xmax, U"Xmin must be smaller than Xmax.") 
+	CREATE_ONE
+		autoLegendreSeries result = LegendreSeries_createFromString (xmin, xmax, coefficients_string);
+	CREATE_ONE_END (name)
+}
+
+DIRECT (HELP_LegendreSeries_help) {
+	HELP (U"LegendreSeries")
+}
+
+DIRECT (NEW_LegendreSeries_to_Polynomial) {
+	CONVERT_EACH (LegendreSeries)
+		autoPolynomial result = LegendreSeries_to_Polynomial (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (LegendreSeries_help) Melder_help (U"LegendreSeries"); END
 
-DIRECT (LegendreSeries_to_Polynomial)
-	LOOP {
-		iam (LegendreSeries);
-		praat_new (LegendreSeries_to_Polynomial (me), my name);
-	}
-END
 /********************* LongSound **************************************/
 
-FORM_READ2 (LongSounds_appendToExistingSoundFile, U"LongSound: Append to existing sound file", 0, false) {
+FORM_READ (READ1_LongSounds_appendToExistingSoundFile, U"LongSound: Append to existing sound file", 0, false) {
 	OrderedOf<structSampled> list;
 	LOOP {
 		iam (Sampled);
 		list. addItem_ref (me);
 	}
 	LongSounds_appendToExistingSoundFile (& list, file);
-END2 }
-
-FORM_WRITE (LongSounds_writeToStereoAiffFile, U"LongSound: Save as AIFF file", 0, U"aiff")
-	LongSound s1 = 0, s2 = 0;
-	LOOP { iam (LongSound); (s1 ? s2 : s1) = me; }
-	Melder_assert (s1 != 0 && s2 != 0);
-	LongSounds_writeToStereoAudioFile16 (s1, s2, Melder_AIFF, file);
-END
-
-FORM_WRITE (LongSounds_writeToStereoAifcFile, U"LongSound: Save as AIFC file", 0, U"aifc")
-	LongSound s1 = 0, s2 = 0;
-	LOOP { iam (LongSound); (s1 ? s2 : s1) = me; }
-	Melder_assert (s1 != 0 && s2 != 0);
-	LongSounds_writeToStereoAudioFile16 (s1, s2, Melder_AIFC, file);
-END
-
-FORM_WRITE (LongSounds_writeToStereoWavFile, U"LongSound: Save as WAV file", 0, U"wav")
-	LongSound s1 = 0, s2 = 0;
-	LOOP { iam (LongSound); (s1 ? s2 : s1) = me; }
-	Melder_assert (s1 != 0 && s2 != 0);
-	LongSounds_writeToStereoAudioFile16 (s1, s2, Melder_WAV, file);
-END
-
-FORM_WRITE (LongSounds_writeToStereoNextSunFile, U"LongSound: Save as NeXT/Sun file", 0, U"au")
-	LongSound s1 = 0, s2 = 0;
-	LOOP { iam (LongSound); (s1 ? s2 : s1) = me; }
-	Melder_assert (s1 != 0 && s2 != 0);
-	LongSounds_writeToStereoAudioFile16 (s1, s2, Melder_NEXT_SUN, file);
-END
-
-FORM_WRITE (LongSounds_writeToStereoNistFile, U"LongSound: Save as NIST file", 0, U"nist")
-	LongSound s1 = 0, s2 = 0;
-	LOOP { iam (LongSound); (s1 ? s2 : s1) = me; }
-	Melder_assert (s1 != 0 && s2 != 0);
-	LongSounds_writeToStereoAudioFile16 (s1, s2, Melder_NIST, file);
-END
+END }
+
+FORM_SAVE (SAVE_LongSounds_writeToStereoAiffFile, U"LongSound: Save as AIFF file", 0, U"aiff") {
+	FIND_COUPLE (LongSound)
+		LongSounds_writeToStereoAudioFile16 (me, you, Melder_AIFF, file);
+	END
+}
+
+FORM_SAVE (SAVE_LongSounds_writeToStereoAifcFile, U"LongSound: Save as AIFC file", 0, U"aifc") {
+	FIND_COUPLE (LongSound)
+		LongSounds_writeToStereoAudioFile16 (me, you, Melder_AIFC, file);
+	END
+}
+
+
+FORM_SAVE (SAVE_LongSounds_writeToStereoWavFile, U"LongSound: Save as WAV file", 0, U"wav") {
+	FIND_COUPLE (LongSound)
+		LongSounds_writeToStereoAudioFile16 (me, you, Melder_WAV, file);
+	END
+}
+
+FORM_SAVE (SAVE_LongSounds_writeToStereoNextSunFile, U"LongSound: Save as NeXT/Sun file", 0, U"au") {
+	FIND_COUPLE (LongSound)
+		LongSounds_writeToStereoAudioFile16 (me, you, Melder_NEXT_SUN, file);
+	END
+}
+
+FORM_SAVE (SAVE_LongSounds_writeToStereoNistFile, U"LongSound: Save as NIST file", 0, U"nist") {
+	FIND_COUPLE (LongSound)
+		LongSounds_writeToStereoAudioFile16 (me, you, Melder_NIST, file);
+	END
+}
 
 /******************* Matrix **************************************************/
 
-FORM (Matrix_drawAsSquares, U"Matrix: Draw as squares", U"Matrix: Draw as squares...")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Matrix_drawAsSquares, U"Matrix: Draw as squares", U"Matrix: Draw as squares...") {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_drawAsSquares (me, GRAPHICS, GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawAsSquares (me, GRAPHICS, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Matrix_drawDistribution, U"Matrix: Draw distribution", U"Matrix: Draw distribution...")
+FORM (GRAPHICS_Matrix_drawDistribution, U"Matrix: Draw distribution", U"Matrix: Draw distribution...") {
 	LABEL (U"", U"Selection of (part of) Matrix")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	LABEL (U"", U"Selection of Matrix values")
-	REAL (U"Minimum value", U"0.0")
-	REAL (U"Maximum value", U"0.0")
+	REALVAR (minimumValue, U"Minimum value", U"0.0")
+	REALVAR (maximumValue, U"Maximum value", U"0.0")
 	LABEL (U"", U"Display of the distribution")
-	NATURAL (U"Number of bins", U"10")
-	REAL (U"Minimum frequency", U"0.0")
-	REAL (U"Maximum frequency", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	NATURALVAR (numberOfBins, U"Number of bins", U"10")
+	REALVAR (minimumFrequency, U"Minimum frequency", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_drawDistribution (me, GRAPHICS, GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"), GET_REAL (U"Minimum value"), GET_REAL (U"Maximum value"),
-			GET_INTEGER (U"Number of bins"), GET_REAL (U"Minimum frequency"), GET_REAL (U"Maximum frequency"), false,
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawDistribution (me, GRAPHICS, xmin, xmax, ymin, ymax, minimumValue, maximumValue, numberOfBins, minimumFrequency, maximumFrequency, false, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Matrix_drawCumulativeDistribution, U"Matrix: Draw cumulative distribution", U"")
+FORM (GRAPHICS_Matrix_drawCumulativeDistribution, U"Matrix: Draw cumulative distribution", nullptr) {
 	LABEL (U"", U"Selection of (part of) Matrix")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	LABEL (U"", U"Selection of Matrix values")
-	REAL (U"Minimum value", U"0.0")
-	REAL (U"Maximum value", U"0.0")
+	REALVAR (minimumValue, U"Minimum value", U"0.0")
+	REALVAR (maximumValue, U"Maximum value", U"0.0")
 	LABEL (U"", U"Display of the distribution")
-	NATURAL (U"Number of bins", U"10")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	NATURALVAR (numberOfBins, U"Number of bins", U"10")
+	REALVAR (minimum, U"Minimum", U"0.0")
+	REALVAR (maximum, U"Maximum", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_drawDistribution (me, GRAPHICS, GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Minimum value"), GET_REAL (U"Maximum value"), GET_INTEGER (U"Number of bins"),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), true, GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawDistribution (me, GRAPHICS, xmin, xmax, ymin, ymax, minimumValue, maximumValue, numberOfBins, minimum, maximum, true, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Matrix_getMean, U"Matrix: Get mean", nullptr)
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+FORM (REAL_Matrix_getMean, U"Matrix: Get mean", nullptr) {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	OK
 DO
-	Matrix me = FIRST_ANY (Matrix);
-	double mean = Matrix_getMean (me, GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"));
-	Melder_informationReal (mean, nullptr);
-END
+	NUMBER_ONE (Matrix)
+		double result = Matrix_getMean (me, xmin, xmax, ymin, ymax);
+	NUMBER_ONE_END (U" (mean)")
+}
 
-FORM (Matrix_getStandardDeviation, U"Matrix: Get standard deviation", nullptr)
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+FORM (REAL_Matrix_getStandardDeviation, U"Matrix: Get standard deviation", nullptr) {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	OK
 DO
-	Matrix me = FIRST_ANY (Matrix);
-	double stdev = Matrix_getStandardDeviation (me, GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"));
-	Melder_informationReal (stdev, nullptr);
-END
+	NUMBER_ONE (Matrix)
+		double result = Matrix_getStandardDeviation (me, xmin, xmax, ymin, ymax);
+	NUMBER_ONE_END (U" (std dev)")
+}
 
-FORM (Matrix_scale, U"Matrix: Scale", nullptr)
+FORM (MODIFY_Matrix_scale, U"Matrix: Scale", nullptr) {
 	LABEL (U"", U"self[row, col] := self[row, col] / `Scale factor'")
-	RADIO (U"Scale factor", 1)
-	RADIOBUTTON (U"Extremum in matrix")
-	RADIOBUTTON (U"Extremum in each row")
-	RADIOBUTTON (U"Extremum in each column")
+	RADIOVAR (scaleMethod, U"Scale factor", 1)
+		RADIOBUTTON (U"Extremum in matrix")
+		RADIOBUTTON (U"Extremum in each row")
+		RADIOBUTTON (U"Extremum in each column")
 	OK
 DO
-	int scale = GET_INTEGER (U"Scale factor");
-	if (scale < 1 || scale > 3) {
-		Melder_throw (U"Scale must be in (1,3) interval.");
-	}
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		Matrix_scale (me, scale);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Matrix)
+		Matrix_scale (me, scaleMethod);
+	MODIFY_EACH_END
+}
+
+DIRECT (NEW_Matrix_transpose) {
+	CONVERT_EACH (Matrix)
+		autoMatrix result = Matrix_transpose (me);
+	CONVERT_EACH_END (my name, U"_transposed")
+}
+
+DIRECT (NEW_Matrix_to_PCA_byColumns) {
+	CONVERT_EACH (Matrix)
+		autoPCA result = Matrix_to_PCA_byColumns (me);
+	CONVERT_EACH_END (my name, U"_columns");
+}
+
+DIRECT (NEW_Matrix_to_PCA_byRows) {
+	CONVERT_EACH (Matrix)
+		autoPCA result = Matrix_to_PCA_byRows (me);
+	CONVERT_EACH_END (my name, U"_rows")
+}
 
-DIRECT (Matrix_transpose)
-	LOOP {
-		iam (Matrix);
-		autoMatrix thee = Matrix_transpose (me);
-		praat_new (thee.move(), my name, U"_transposed");
-	}
-END
+FORM (NEW_Matrix_solveEquation, U"Matrix: Solve equation", U"Matrix: Solve equation...") {
+	REALVAR (tolerance, U"Tolerance", U"1.19e-7")
+	OK
+DO
+	CONVERT_EACH (Matrix)
+		autoMatrix result = Matrix_solveEquation (me, tolerance);
+	CONVERT_EACH_END (my name, U"_solution")
+}
 
-DIRECT (Matrix_to_PCA_byColumns)
-	LOOP {
-		iam (Matrix);
-		autoPCA thee = Matrix_to_PCA_byColumns (me);
-		praat_new (thee.move(), my name, U"_columns");
-	}
-END
-DIRECT (Matrix_to_PCA_byRows)
-	LOOP {
-		iam (Matrix);
-		autoPCA thee = Matrix_to_PCA_byRows (me);
-		praat_new (thee.move(), my name, U"_rows");
-	}
-END
+DIRECT (NEW1_Matrix_Categories_to_TableOfReal) {
+	CONVERT_ONE_AND_GENERIC (Categories, Matrix)
+		autoTableOfReal result = Matrix_and_Categories_to_TableOfReal (you, me);
+	CONVERT_ONE_AND_GENERIC_END (my name, U"_", your name)
+}
+
+DIRECT (NEW1_ActivationList_Categories_to_TableOfReal) {
+	CONVERT_TWO (ActivationList, Categories)
+		autoTableOfReal result = Matrix_and_Categories_to_TableOfReal (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (Matrix_solveEquation, U"Matrix: Solve equation", U"Matrix: Solve equation...")
-	REAL (U"Tolerance", U"1.19e-7")
+FORM (GRAPHICS_Matrix_scatterPlot, U"Matrix: Scatter plot", nullptr) {
+	NATURALVAR (xColumn, U"Column for X-axis", U"1")
+	NATURALVAR (yColumn, U"Column for Y-axis", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	LOOP {
-		iam (Matrix);
-		autoMatrix thee = Matrix_solveEquation (me, GET_REAL (U"Tolerance"));
-		praat_new (thee.move(), Thing_getName (me), U"_solution");
-	}
-END
-
-DIRECT (Matrix_Categories_to_TableOfReal)
-	Matrix me = FIRST_GENERIC (Matrix);
-	Categories cat = FIRST (Categories);
-	autoTableOfReal thee = Matrix_and_Categories_to_TableOfReal (me, cat);
-	praat_new (thee.move(), my name, U"_", cat -> name);
-END
-
-FORM (Matrix_scatterPlot, U"Matrix: Scatter plot", nullptr)
-	NATURAL (U"Column for X-axis", U"1")
-	NATURAL (U"Column for Y-axis", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Garnish", 1)
-	OK
-DO
-	long x = GET_INTEGER (U"Column for X-axis");
-	long y = GET_INTEGER (U"Column for Y-axis");
-	if (x == 0 || y == 0) {
-		Melder_throw (U"X and Y component must differ from 0.");
-	}
-	LOOP {
-		iam (Matrix);
-		Matrix_scatterPlot (me, GRAPHICS, x, y, GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"), GET_REAL (U"Mark size"), GET_STRING (U"Mark string"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
 
-DIRECT (Matrix_to_ActivationList)
-	LOOP {
-		iam (Matrix);
-		autoActivationList thee = Matrix_to_ActivationList (me);
-		praat_new (thee.move(), my name);
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		Matrix_scatterPlot (me, GRAPHICS, xColumn, yColumn, xmin, xmax, ymin, ymax, markSize_mm, mark_string, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Matrices_to_DTW, U"Matrices: To DTW", U"Matrix: To DTW...")
+DIRECT (NEW_Matrix_to_ActivationList) {
+	CONVERT_EACH (Matrix)
+		autoActivationList result = Matrix_to_ActivationList (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW1_Matrices_to_DTW, U"Matrices: To DTW", U"Matrix: To DTW...") {
 	LABEL (U"", U"Distance  between cepstral coefficients")
-	REAL (U"Distance metric", U"2.0")
-	DTW_constraints_addCommonFields (dia);
+	REALVAR (distanceMetric, U"Distance metric", U"2.0")
+	DTW_constraints_addCommonFields (matchStart, matchEnd, slopeConstraint)
 	OK
 DO
-	int begin, end, slope;
-	DTW_constraints_getCommonFields (dia, &begin, &end, &slope);
-	Matrix m1 = 0, m2 = 0;
-	LOOP {
-		iam (Matrix);
-		(m1 ? m2 : m1) = me;
-	}
-	Melder_assert (m1 && m2);
-	autoDTW thee = Matrices_to_DTW (m1, m2, begin, end, slope, GET_REAL (U"Distance metric"));
-	praat_new (thee.move(), m1->name, U"_", m2->name);
-END
+	CONVERT_COUPLE (Matrix)
+		autoDTW result = Matrices_to_DTW (me, you, matchStart, matchEnd, slopeConstraint, distanceMetric);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (Matrix_to_PatternList, U"Matrix: To PatternList", nullptr)
-	NATURAL (U"Join", U"1")
+FORM (NEW_Matrix_to_PatternList, U"Matrix: To PatternList", nullptr) {
+	NATURALVAR (join, U"Join", U"1")
 	OK
 DO
-	LOOP {
-		iam (Matrix);
-		praat_new (Matrix_to_PatternList (me, GET_INTEGER (U"Join")), my name);
-	}
-END
+	CONVERT_EACH (Matrix)
+		autoPatternList result = Matrix_to_PatternList (me, join);
+	CONVERT_EACH_END (my name)
+}
 
 /**** Filterbank (deprecated) *******/
 
-DIRECT (FilterBank_getHighestFrequency)
-	LOOP {
-		iam (FilterBank);
-		Melder_information (my ymax, U" ", my v_getFrequencyUnit ());
-	}
-END
+DIRECT (REAL_FilterBank_getHighestFrequency) {
+	NUMBER_ONE (FilterBank)
+		double result = my ymax;
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-DIRECT (FilterBank_getLowestFrequency)
-	LOOP {
-		iam (FilterBank);
-		Melder_information (my ymin, U" ", my v_getFrequencyUnit ());
-	}
-END
+DIRECT (REAL_FilterBank_getLowestFrequency) {
+	NUMBER_ONE (FilterBank)
+		double result = my ymin;
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-DIRECT (FilterBank_getNumberOfFrequencies)
-	LOOP {
-		iam (FilterBank);
-		Melder_information (my ny);
-	}
-END
+DIRECT (INTEGER_FilterBank_getNumberOfFrequencies) {
+	INTEGER_ONE (FilterBank)
+		long result = my ny;
+	INTEGER_ONE_END (U"")
+}
 
-DIRECT (FilterBank_getFrequencyDistance)
-	LOOP {
-		iam (FilterBank);
-		Melder_information (my dy, U" ", my v_getFrequencyUnit ());
-	}
-END
+DIRECT (REAL_FilterBank_getFrequencyDistance) {
+	NUMBER_ONE (FilterBank)
+		double result = my dy;
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-FORM (FilterBank_getXofColumn, U"Get time of column", nullptr)
-	NATURAL (U"Column number", U"1")
+FORM (REAL_FilterBank_getXofColumn, U"Get time of column", nullptr) {
+	NATURALVAR (columnNumber, U"Column number", U"1")
 	OK
 DO
-	LOOP {
-		iam (FilterBank);
-		Melder_information (Matrix_columnToX (me, GET_INTEGER (U"Column number")));
-	}
-END
+	NUMBER_ONE (FilterBank)
+		double result = Matrix_columnToX (me, columnNumber);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (FilterBank_getFrequencyOfRow, U"Get frequency of row", nullptr)
-	NATURAL (U"Row number", U"1")
+FORM (REAL_FilterBank_getFrequencyOfRow, U"Get frequency of row", nullptr) {
+	NATURALVAR (rowNumber, U"Row number", U"1")
 	OK
 DO
-	LOOP {
-		iam (FilterBank);
-		Melder_information (Matrix_rowToY (me, GET_INTEGER (U"Row number")), U" ", my v_getFrequencyUnit ());
-	}
-END
+	NUMBER_ONE (FilterBank)
+		double result = Matrix_rowToY (me, rowNumber);
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-FORM (FilterBank_getValueInCell, U"Get value in cell", nullptr)
-	POSITIVE (U"Time (s)", U"0.5")
-	POSITIVE (U"Frequency", U"1")
+FORM (REAL_FilterBank_getValueInCell, U"Get value in cell", nullptr) {
+	REALVAR (time, U"Time (s)", U"0.5")
+	POSITIVEVAR (frequency, U"Frequency", U"1.0")
 	OK
 DO
-	double t = GET_REAL (U"Time");
-	double f = GET_REAL (U"Frequency");
-	LOOP {
-		iam (FilterBank);
-		if (f < my ymin || f > my ymax) {
-			Melder_throw (U"Frequency out of range.");
-		}
-		if (t < my xmin || t > my xmax) {
-			Melder_throw (U"Time out of range.");
-		}
-		long col = Matrix_xToNearestColumn (me, t);
-		if (col < 1) {
-			col = 1;
-		}
-		if (col > my nx) {
-			col = my nx;
-		}
-		long row = Matrix_yToNearestRow (me, f);
-		if (row < 1) {
-			row = 1;
-		}
-		if (row > my ny) {
-			row = my ny;
+	NUMBER_ONE (FilterBank)
+		double result = NUMundefined;
+		if ((frequency >= my ymin && frequency <= my ymax) && (time >+ my xmin && time <= my ymin)) {
+			long col = Matrix_xToNearestColumn (me, time);
+			if (col < 1) {
+				col = 1;
+			}
+			if (col > my nx) {
+				col = my nx;
+			}
+			long row = Matrix_yToNearestRow (me, frequency);
+			if (row < 1) {
+				row = 1;
+			}
+			if (row > my ny) {
+				row = my ny;
+			}
+			result = my z[row][col];
 		}
-		double ta = Matrix_columnToX (me, col);
-		double fa = Matrix_rowToY (me, row);
-		Melder_information (my z[row][col], U" (delta t: ", ta - t, U" f: ",
-		fa - f, U")");
-	}
-END
+	NUMBER_ONE_END (U"")
+}
 
 /***** MATRIXFT *************/
 
-DIRECT (BandFilterSpectrogram_getHighestFrequency)
-	LOOP {
-		iam (BandFilterSpectrogram);
-		Melder_information (my ymax, U" ", my v_getFrequencyUnit ());
-	}
-END
+DIRECT (REAL_BandFilterSpectrogram_getHighestFrequency) {
+	NUMBER_ONE (BandFilterSpectrogram)
+		double result = my ymax;
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-DIRECT (BandFilterSpectrogram_getLowestFrequency)
-	LOOP {
-		iam (BandFilterSpectrogram);
-		Melder_information (my ymin, U" ", my v_getFrequencyUnit ());
-	}
-END
+DIRECT (REAL_BandFilterSpectrogram_getLowestFrequency) {
+	NUMBER_ONE (BandFilterSpectrogram)
+		double result = my ymin;
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-DIRECT (BandFilterSpectrogram_getNumberOfFrequencies)
-	LOOP {
-		iam (BandFilterSpectrogram);
-		Melder_information (my ny);
-	}
-END
+DIRECT (INTEGER_BandFilterSpectrogram_getNumberOfFrequencies) {
+	INTEGER_ONE (BandFilterSpectrogram)
+		long result = my ny;
+	INTEGER_ONE_END (U"")
+}
 
-DIRECT (BandFilterSpectrogram_getFrequencyDistance)
-	LOOP {
-		iam (BandFilterSpectrogram);
-		Melder_information (my dy, U" ", my v_getFrequencyUnit ());
-	}
-END
+DIRECT (REAL_BandFilterSpectrogram_getFrequencyDistance) {
+	NUMBER_ONE (BandFilterSpectrogram)
+		double result = my dy;
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-FORM (BandFilterSpectrogram_getFrequencyOfRow, U"Get frequency of row", nullptr)
-	NATURAL (U"Row number", U"1")
+FORM (REAL_BandFilterSpectrogram_getFrequencyOfRow, U"Get frequency of row", nullptr) {
+	NATURALVAR (rowNumber, U"Row number", U"1")
 	OK
 DO
-	LOOP {
-		iam (BandFilterSpectrogram);
-		Melder_information (Matrix_rowToY (me, GET_INTEGER (U"Row number")), U" ", my v_getFrequencyUnit ());
-	}
-END
+	NUMBER_ONE (BandFilterSpectrogram)
+		double result = Matrix_rowToY (me, rowNumber);
+	NUMBER_ONE_END (U" ", my v_getFrequencyUnit ())
+}
 
-FORM (BandFilterSpectrogram_getXofColumn, U"Get time of column", nullptr)
-	NATURAL (U"Column number", U"1")
+FORM (REAL_BandFilterSpectrogram_getXofColumn, U"Get time of column", nullptr) {
+	NATURALVAR (columnNumber, U"Column number", U"1")
 	OK
 DO
-	LOOP {
-		iam (BandFilterSpectrogram);
-		Melder_information (Matrix_columnToX (me, GET_INTEGER (U"Column number")));
-	}
-END
+	NUMBER_ONE (BandFilterSpectrogram)
+		double result = Matrix_columnToX (me, columnNumber);
+	NUMBER_ONE_END (U" s")
+}
 
-FORM (BandFilterSpectrogram_getValueInCell, U"Get value in cell", nullptr)
-	POSITIVE (U"Time (s)", U"0.5")
-	POSITIVE (U"Frequency", U"1")
+FORM (REAL_BandFilterSpectrogram_getValueInCell, U"Get value in cell", nullptr) {
+	REALVAR (time, U"Time (s)", U"0.5")
+	POSITIVEVAR (frequency, U"Frequency", U"1")
 	OK
 DO
-	double t = GET_REAL (U"Time");
-	double f = GET_REAL (U"Frequency");
-	LOOP {
-		iam (BandFilterSpectrogram);
-		if (f < my ymin || f > my ymax) {
-			Melder_throw (U"Frequency out of range.");
-		}
-		if (t < my xmin || t > my xmax) {
-			Melder_throw (U"Time out of range.");
-		}
-		long col = Matrix_xToNearestColumn (me, t);
-		if (col < 1) {
-			col = 1;
-		}
-		if (col > my nx) {
-			col = my nx;
-		}
-		long row = Matrix_yToNearestRow (me, f);
-		if (row < 1) {
-			row = 1;
-		}
-		if (row > my ny) {
-			row = my ny;
+	NUMBER_ONE (BandFilterSpectrogram)
+		double result = NUMundefined;
+		if ((frequency >= my ymin && frequency <= my ymax) && (time >+ my xmin && time <= my ymin)) {
+			long col = Matrix_xToNearestColumn (me, time);
+			if (col < 1) {
+				col = 1;
+			}
+			if (col > my nx) {
+				col = my nx;
+			}
+			long row = Matrix_yToNearestRow (me, frequency);
+			if (row < 1) {
+				row = 1;
+			}
+			if (row > my ny) {
+				row = my ny;
+			}
+			result = my z[row][col];
 		}
-		double ta = Matrix_columnToX (me, col);
-		double fa = Matrix_rowToY (me, row);
-		Melder_information (Melder_single (my z[row][col]), U" (delta t: ", ta - t, U" f: ",
-		fa - f, U")");
-	}
-END
+	NUMBER_ONE_END (U"")
+}
 
 /**************** MelFilter *******************************************/
 
-DIRECT (MelFilter_help)
-	Melder_help (U"MelFilter");
-END
+DIRECT (HELP_MelFilter_help) {
+	HELP (U"MelFilter")
+}
 
-DIRECT (MelSpectrogram_help)
-	Melder_help (U"MelSpectrogram");
-END
+DIRECT (HELP_MelSpectrogram_help) {
+	HELP (U"MelSpectrogram")
+}
 
-FORM (MelFilter_drawFilterFunctions, U"MelFilter: Draw filter functions", U"FilterBank: Draw filter functions...")
-	INTEGER (U"left Filter range", U"0")
-	INTEGER (U"right Filter range", U"0")
-	RADIO (U"Frequency scale", 1)
+FORM (GRAPHICS_MelFilter_drawFilterFunctions, U"MelFilter: Draw filter functions", U"FilterBank: Draw filter functions...") {
+	INTEGERVAR (fromFilter, U"left Filter range", U"0")
+	INTEGERVAR (toFilter, U"right Filter range", U"0")
+	RADIOVAR (frequencyScale, U"Frequency scale", 1)
 	RADIOBUTTON (U"Hertz")
 	RADIOBUTTON (U"Bark")
 	RADIOBUTTON (U"Mel")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	BOOLEAN (U"Amplitude scale in dB", 0)
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	BOOLEANVAR (dBScale, U"Amplitude scale in dB", 0)
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (MelFilter);
-		MelFilter_drawFilterFunctions (me, GRAPHICS, GET_INTEGER (U"Frequency scale"),
-			GET_INTEGER (U"left Filter range"), GET_INTEGER (U"right Filter range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Amplitude scale in dB"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (MelFilter)
+		MelFilter_drawFilterFunctions (me, GRAPHICS, frequencyScale, fromFilter, toFilter, fromFrequency, toFrequency, dBScale, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (MelSpectrogram_drawTriangularFilterFunctions, U"MelSpectrogram: Draw triangulat filter functions", U"MelSpectrogram: Draw filter functions...")
-	INTEGER (U"left Filter range", U"0")
-	INTEGER (U"right Filter range", U"0")
-	RADIO (U"Frequency scale", 1)
+FORM (GRAPHICS_MelSpectrogram_drawTriangularFilterFunctions, U"MelSpectrogram: Draw triangulat filter functions", U"MelSpectrogram: Draw filter functions...") {
+	INTEGERVAR (fromFilter, U"left Filter range", U"0")
+	INTEGERVAR (toFilter, U"right Filter range", U"0")
+	RADIOVAR (frequencyScale, U"Frequency scale", 1)
 	RADIOBUTTON (U"Mel")
 	RADIOBUTTON (U"Hertz")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right Frequency range", U"0.0")
-	BOOLEAN (U"Amplitude scale in dB", 0)
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range", U"0.0")
+	BOOLEANVAR (dBScale, U"Amplitude scale in dB", 0)
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (MelSpectrogram);
-		MelSpectrogram_drawTriangularFilterFunctions (me, GRAPHICS, GET_INTEGER (U"Frequency scale") - 1,
-			GET_INTEGER (U"left Filter range"), GET_INTEGER (U"right Filter range"),
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_INTEGER (U"Amplitude scale in dB"),
-			GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
-
+	GRAPHICS_EACH (MelSpectrogram)
+		MelSpectrogram_drawTriangularFilterFunctions (me, GRAPHICS, frequencyScale - 1, fromFilter, toFilter, fromFrequency, toFrequency, dBScale, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (MelFilter_drawSpectrum, U"MelFilter: Draw spectrum (slice)", U"FilterBank: Draw spectrum (slice)...")
-	POSITIVE (U"Time (s)", U"0.1")
-	REAL (U"left Frequency range (mel)", U"0.0")
-	REAL (U"right Frequency range (mel)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_MelFilter_drawSpectrum, U"MelFilter: Draw spectrum (slice)", U"FilterBank: Draw spectrum (slice)...") {
+	REALVAR (time, U"Time (s)", U"0.1")
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (FilterBank);
-		FilterBank_drawTimeSlice (me, GRAPHICS, GET_REAL (U"Time"), GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), U"Mels", GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (FilterBank)
+		FilterBank_drawTimeSlice (me, GRAPHICS, time, fromFrequency, toFrequency, fromAmplitude, toAmplitude, U"Mels", garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (MelSpectrogram_drawSpectrumAtNearestTimeSlice, U"MelSpectrogram: Draw spectrum at nearest time slice", U"BandFilterSpectrogram: Draw spectrum at nearest time slice...")
-	REAL (U"Time (s)", U"0.1")
-	REAL (U"left Frequency range (mel)", U"0.0")
-	REAL (U"right Frequency range (mel)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_MelSpectrogram_drawSpectrumAtNearestTimeSlice, U"MelSpectrogram: Draw spectrum at nearest time slice", U"BandFilterSpectrogram: Draw spectrum at nearest time slice...") {
+	REALVAR (time, U"Time (s)", U"0.1")
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (MelSpectrogram);
-		BandFilterSpectrogram_drawSpectrumAtNearestTimeSlice (me, GRAPHICS, GET_REAL (U"Time"), GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (MelSpectrogram)
+		BandFilterSpectrogram_drawSpectrumAtNearestTimeSlice (me, GRAPHICS, time, fromFrequency, toFrequency, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (BarkSpectrogram_drawSpectrumAtNearestTimeSlice, U"BarkSpectrogram: Draw spectrum at nearest time slice", U"BandFilterSpectrogram: Draw spectrum at nearest time slice...")
-	REAL (U"Time (s)", U"0.1")
-	REAL (U"left Frequency range (bark)", U"0.0")
-	REAL (U"right Frequency range (bark)", U"0.0")
-	REAL (U"left Amplitude range (dB)", U"0.0")
-	REAL (U"right Amplitude range (dB)", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_BarkSpectrogram_drawSpectrumAtNearestTimeSlice, U"BarkSpectrogram: Draw spectrum at nearest time slice", U"BandFilterSpectrogram: Draw spectrum at nearest time slice...") {
+	REALVAR (time, U"Time (s)", U"0.1")
+	REALVAR (fromFrequency, U"left Frequency range (bark)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (bark)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range (dB)", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range (dB)", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (MelSpectrogram);
-		BandFilterSpectrogram_drawSpectrumAtNearestTimeSlice (me, GRAPHICS, GET_REAL (U"Time"), GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"left Amplitude range"),
-			GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (MelSpectrogram)
+		BandFilterSpectrogram_drawSpectrumAtNearestTimeSlice (me, GRAPHICS, time, fromFrequency, toFrequency, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (MelFilter_paint, U"FilterBank: Paint", nullptr)
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Frequency range (mel)", U"0.0")
-	REAL (U"right Frequency range (mel)", U"0.0")
-	REAL (U"left Amplitude range", U"0.0")
-	REAL (U"right Amplitude range", U"0.0")
-	BOOLEAN (U"Garnish", false)
+FORM (GRAPHICS_MelFilter_paint, U"FilterBank: Paint", nullptr) {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"0.0")
+	REALVAR (fromAmplitude, U"left Amplitude range", U"0.0")
+	REALVAR (toAmplitude, U"right Amplitude range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", false)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Matrix);
-		FilterBank_paint ((FilterBank) me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-		GET_REAL (U"left Amplitude range"), GET_REAL (U"right Amplitude range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Matrix)
+		FilterBank_paint ((FilterBank) me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, fromAmplitude, toAmplitude, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (MelFilter_to_MFCC, U"MelFilter: To MFCC", U"MelSpectrogram: To MFCC...")
-	NATURAL (U"Number of coefficients", U"12")
+FORM (NEW_MelFilter_to_MFCC, U"MelFilter: To MFCC", U"MelSpectrogram: To MFCC...") {
+	NATURALVAR (numberOfCoefficients, U"Number of coefficients", U"12")
 	OK
 DO
-	LOOP {
-		iam (MelFilter);
-		praat_new (MelFilter_to_MFCC (me, GET_INTEGER (U"Number of coefficients")), my name);
-	}
-END
+	CONVERT_EACH (MelFilter)
+		autoMFCC result = MelFilter_to_MFCC (me, numberOfCoefficients);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (MelSpectrogram_to_MFCC, U"MelSpectrogram: To MFCC", U"MelSpectrogram: To MFCC...")
-	NATURAL (U"Number of coefficients", U"12")
+FORM (NEW_MelSpectrogram_to_MFCC, U"MelSpectrogram: To MFCC", U"MelSpectrogram: To MFCC...") {
+	NATURALVAR (numberOfCoefficients, U"Number of coefficients", U"12")
 	OK
 DO
-	LOOP {
-		iam (MelSpectrogram);
-		autoMFCC thee = MelSpectrogram_to_MFCC (me, GET_INTEGER (U"Number of coefficients"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (MelSpectrogram)
+		autoMFCC result = MelSpectrogram_to_MFCC (me, numberOfCoefficients);
+	CONVERT_EACH_END (my name)
+}
 
 /**************** Ltas *******************************************/
 
 #include "UnicodeData.h"
-FORM (Ltas_reportSpectralTilt, U"Ltas: Report spectral tilt", nullptr)
-	POSITIVE (U"left Frequency range (Hz)", U"100.0")
-	POSITIVE (U"right Frequency range (Hz)", U"5000.0")
-	OPTIONMENU (U"Frequency scale", 1)
-	OPTION (U"Linear")
-	OPTION (U"Logarithmic")
-	OPTIONMENU (U"Fit method", 2)
-	OPTION (U"Least squares")
-	OPTION (U"Robust")
-	OK
-DO
-	bool logScale = GET_INTEGER (U"Frequency scale") == 2;
-	LOOP {
-		iam (Ltas);
+FORM (INFO_Ltas_reportSpectralTilt, U"Ltas: Report spectral tilt", nullptr) {
+	POSITIVEVAR (fromFrequency, U"left Frequency range (Hz)", U"100.0")
+	POSITIVEVAR (toFrequency, U"right Frequency range (Hz)", U"5000.0")
+	OPTIONMENUVAR (frequencyScale, U"Frequency scale", 1)
+		OPTION (U"Linear")
+		OPTION (U"Logarithmic")
+	OPTIONMENUVAR (fitMethod, U"Fit method", 2)
+		OPTION (U"Least squares")
+		OPTION (U"Robust")
+	OK
+DO
+	bool logScale = frequencyScale == 2;
+	INFO_ONE (Ltas)
 		double a, b;
-		Ltas_fitTiltLine (me, GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			logScale, GET_INTEGER (U"Fit method"), &a, &b);
+		Ltas_fitTiltLine (me, fromFrequency, toFrequency, logScale, fitMethod, &a, &b);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"Spectral model: amplitude_dB(frequency_Hz) " UNITEXT_ALMOST_EQUAL_TO " ", logScale ? U"offset + slope * log (frequency_Hz)" : U"offset + slope * frequency_Hz");
-		MelderInfo_writeLine (U"Slope: ", a, logScale ? U" dB/decade" : U" dB/Hz");
-		MelderInfo_writeLine (U"Offset: ", b, U" dB");
+			MelderInfo_writeLine (U"Spectral model: amplitude_dB(frequency_Hz) " UNITEXT_ALMOST_EQUAL_TO " ", logScale ? U"offset + slope * log (frequency_Hz)" : U"offset + slope * frequency_Hz");
+			MelderInfo_writeLine (U"Slope: ", a, logScale ? U" dB/decade" : U" dB/Hz");
+			MelderInfo_writeLine (U"Offset: ", b, U" dB");
 		MelderInfo_close ();
-	}
-END
+	INFO_ONE_END
+}
 
 
 /**************** MFCC *******************************************/
 
-DIRECT (MFCC_help)
-	Melder_help (U"MFCC");
-END
+DIRECT (HELP_MFCC_help) {
+	HELP (U"MFCC")
+}
 
-FORM (MFCC_to_MelFilter, U"MFCC: To MelFilter", nullptr)
-	INTEGER (U"From coefficient", U"0")
-	INTEGER (U"To coefficient", U"0")
+FORM (NEW_MFCC_to_MelFilter, U"MFCC: To MelFilter", nullptr) {
+	INTEGERVAR (fromCoefficient, U"From coefficient", U"0")
+	INTEGERVAR (toCoefficient, U"To coefficient", U"0")
 	OK
 DO
-	LOOP {
-		iam (MFCC);
-		praat_new (MFCC_to_MelFilter (me, GET_INTEGER (U"From coefficient"), GET_INTEGER (U"To coefficient")), my name);
-	}
-END
+	CONVERT_EACH (MFCC)
+		autoMelFilter result = MFCC_to_MelFilter (me, fromCoefficient, toCoefficient);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (MFCC_to_MelSpectrogram, U"MFCC: MelSpectrogram", U"MFCC: To MelSpectrogram...")
-	INTEGER (U"From coefficient", U"0")
-	INTEGER (U"To coefficient", U"0")
-	BOOLEAN (U"Include constant term", true)
+FORM (NEW_MFCC_to_MelSpectrogram, U"MFCC: MelSpectrogram", U"MFCC: To MelSpectrogram...") {
+	INTEGERVAR (fromCoefficient, U"From coefficient", U"0")
+	INTEGERVAR (toCoefficient, U"To coefficient", U"0")
+	BOOLEANVAR (includeConstant, U"Include constant term", true)
 	OK
 DO
-	LOOP {
-		iam (MFCC);
-		autoMelSpectrogram thee = MFCC_to_MelSpectrogram (me, GET_INTEGER (U"From coefficient"), GET_INTEGER (U"To coefficient"),
-			GET_INTEGER (U"Include constant term"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (MFCC)
+		autoMelSpectrogram result = MFCC_to_MelSpectrogram (me, fromCoefficient, toCoefficient, includeConstant);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (MFCC_to_TableOfReal, U"MFCC: To TableOfReal", U"MFCC: To TableOfReal...")
-	BOOLEAN (U"Include energy", false)
+FORM (NEW_MFCC_to_TableOfReal, U"MFCC: To TableOfReal", U"MFCC: To TableOfReal...") {
+	BOOLEANVAR (includeEnergy, U"Include energy", false)
 	OK
 DO
-	LOOP {
-		iam (MFCC);
-		praat_new (MFCC_to_TableOfReal (me, GET_INTEGER (U"Include energy")), my name);
-	}
-END
+	CONVERT_EACH (MFCC)
+		autoTableOfReal result = MFCC_to_TableOfReal (me, includeEnergy);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (MFCC_to_Matrix_features, U"MFCC: To Matrix (features)", nullptr)
-	POSITIVE (U"Window length (s)", U"0.025")
-	BOOLEAN (U"Include energy", false)
+FORM (NEW_MFCC_to_Matrix_features, U"MFCC: To Matrix (features)", nullptr) {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	BOOLEANVAR (includeEnergy, U"Include energy", false)
 	OK
 DO
-	LOOP {
-		iam (MFCC);
-		praat_new (MFCC_to_Matrix_features (me, GET_REAL (U"Window length"), GET_INTEGER (U"Include energy")), my name);
-	}
-END
+	CONVERT_EACH (MFCC)
+		autoMatrix result = MFCC_to_Matrix_features (me, windowLength, includeEnergy);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (MFCCs_crossCorrelate, U"MFCC & MFCC: Cross-correlate", nullptr)
+FORM (NEW1_MFCCs_crossCorrelate, U"MFCC & MFCC: Cross-correlate", nullptr) {
 	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
 	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
 	OK
 DO
-	MFCC m1 = nullptr, m2 = nullptr;
-	LOOP {
-		iam (MFCC);
-		(m1 ? m2 : m1) = me;
-	}
-	Melder_assert (m1 && m2);
-	praat_new (MFCCs_crossCorrelate (m1, m2,
+	CONVERT_COUPLE (MFCC)
+		autoSound result = MFCCs_crossCorrelate (me, you,
 		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is...")),
-		m1 -> name, U"_", m2 -> name);
-END
+		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+	CONVERT_COUPLE_END (my name, U"_",your name)
+}
 
-FORM (MFCCs_convolve, U"MFCC & MFCC: Convolve", nullptr)
+FORM (NEW1_MFCCs_convolve, U"MFCC & MFCC: Convolve", nullptr) {
 	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
 	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
 	OK
 DO
-	MFCC m1 = nullptr, m2 = nullptr;
-	LOOP {
-		iam (MFCC);
-		(m1 ? m2 : m1) = me;
-	}
-	Melder_assert (m1 && m2);
-	praat_new (MFCCs_convolve (m1, m2,
+	CONVERT_COUPLE (MFCC)
+		autoSound result = MFCCs_convolve (me, you,
 		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is...")),
-		m1 -> name, U"_", m2 -> name);
-END
+		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+	CONVERT_COUPLE_END (my name, U"_",your name)
+}
 
-DIRECT (MFCC_to_Sound)
-	LOOP {
-		iam (MFCC);
-		praat_new (MFCC_to_Sound (me), my name);
-	}
-END
+DIRECT (NEW_MFCC_to_Sound) {
+	CONVERT_EACH (MFCC)
+		autoSound result = MFCC_to_Sound (me);
+	CONVERT_EACH_END (my name)
+}
 
 /**************** MSpline *******************************************/
 
-FORM (MSpline_create, U"Create MSpline", U"Create MSpline...")
-	WORD (U"Name", U"mspline")
+FORM (NEW_MSpline_create, U"Create MSpline", U"Create MSpline...") {
+	WORDVAR (name, U"Name", U"mspline")
 	LABEL (U"", U"Domain")
-	REAL (U"Xmin", U"0")
-	REAL (U"Xmax", U"1")
+	REALVAR (xmin, U"Xmin", U"0")
+	REALVAR (xmax, U"Xmax", U"1")
 	LABEL (U"", U"MSpline(x) = c[1] M[1](x) + c[2] M[1](x) + ... c[n] M[n](x)")
 	LABEL (U"", U"all M[k] are polynomials of degree \"Degree\"")
 	LABEL (U"", U"Relation: numberOfCoefficients == numberOfInteriorKnots + degree + 1")
-	INTEGER (U"Degree", U"2")
-	SENTENCE (U"Coefficients (c[k])", U"1.2 2.0 1.2 1.2 3.0 0.0")
-	SENTENCE (U"Interior knots" , U"0.3 0.5 0.6")
+	INTEGERVAR (degree, U"Degree", U"2")
+	SENTENCEVAR (coefficients_string, U"Coefficients (c[k])", U"1.2 2.0 1.2 1.2 3.0 0.0")
+	SENTENCEVAR (knots_string, U"Interior knots" , U"0.3 0.5 0.6")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	long degree = GET_INTEGER (U"Degree");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	praat_new (MSpline_createFromStrings (xmin, xmax, degree,
-		GET_STRING (U"Coefficients"), GET_STRING (U"Interior knots")), GET_STRING (U"Name"));
-END
+	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
+	CREATE_ONE
+		autoMSpline result = MSpline_createFromStrings (xmin, xmax, degree, coefficients_string, knots_string);
+	CREATE_ONE_END (name)
+}
 
-DIRECT (MSpline_help) Melder_help (U"MSpline"); END
+DIRECT (HELP_MSpline_help) {
+	HELP (U"MSpline")
+}
 
 /********************** PatternList *******************************************/
 
-DIRECT (PatternList_and_Categories_to_Discriminant)
-	PatternList me = FIRST (PatternList);
-	Categories cat = FIRST (Categories);
-	autoDiscriminant thee = PatternList_and_Categories_to_Discriminant (me, cat);
-	praat_new (thee.move(), my name, U"_", cat -> name);
-END
+DIRECT (NEW1_PatternList_and_Categories_to_Discriminant) {
+	CONVERT_TWO (PatternList, Categories)
+		autoDiscriminant result = PatternList_and_Categories_to_Discriminant (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (PatternList_draw, U"PatternList: Draw", 0)
-	NATURAL (U"PatternList number", U"1")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_PatternList_draw, U"PatternList: Draw", nullptr) {
+	NATURALVAR (patternNumber, U"Pattern number", U"1")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (PatternList);
-		PatternList_draw (me, GRAPHICS, GET_INTEGER (U"PatternList number"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (PatternList)
+		PatternList_draw (me, GRAPHICS, patternNumber, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (PatternList_getNumberOfPatterns)
-	LOOP {
-		iam (PatternList);
-		Melder_information (my ny);
-	}
-END
+DIRECT (INTEGER_PatternList_getNumberOfPatterns) {
+	INTEGER_ONE (PatternList)
+		long result = my ny;
+	INTEGER_ONE_END (U" (number of patterns)")
+}
 
-DIRECT (PatternList_getPatternSize)
-	LOOP {
-		iam (PatternList);
-		Melder_information (my nx);
-	}
-END
+DIRECT (INTEGER_PatternList_getPatternSize) {
+	INTEGER_ONE (PatternList)
+		long result = my nx;
+	INTEGER_ONE_END (U" (pattern size)")
+}
 
-FORM (PatternList_getValue, U"", nullptr)
-	NATURAL (U"Pattern number", U"1")
-	NATURAL (U"Node number", U"2")
+FORM (REAL_PatternList_getValue, U"", nullptr) {
+	NATURALVAR (patternNumber, U"Pattern number", U"1")
+	NATURALVAR (nodeNumber, U"Node number", U"2")
 	OK
 DO
-	long row = GET_INTEGER (U"Pattern number"), col = GET_INTEGER (U"Node number");
-	LOOP {
-		iam (PatternList);
-		Melder_information (row <= my ny && col <= my nx ? my z[row][col] : NUMundefined);
-	}
-END
+	NUMBER_ONE (PatternList)
+		double result = patternNumber <= my ny && nodeNumber <= my nx ? my z [patternNumber] [nodeNumber] : NUMundefined;
+	NUMBER_ONE_END (U"")
+}
 
-FORM (PatternList_formula, U"PatternList: Formula", nullptr)
+FORM (MODIFY_PatternList_formula, U"PatternList: Formula", nullptr) {
 	LABEL (U"label", U"        y := 1; for row := 1 to nrow do { x := 1; "
 		"for col := 1 to ncol do { self [row, col] := `formula' ; x := x + 1 } "
 		"y := y + 1 }}")
-	TEXTFIELD (U"formula", U"self")
+	TEXTVAR (formula, U"formula", U"self")
 	OK
 DO
-	praat_Fon_formula (dia, interpreter);
-END
+	MODIFY_EACH (PatternList)
+		Matrix_formula (reinterpret_cast <Matrix> (me), formula, interpreter, nullptr);
+	MODIFY_EACH_END
+}
 
-FORM (PatternList_setValue, U"PatternList: Set value", U"PatternList: Set value...")
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
-	REAL (U"New value", U"0.0")
+FORM (MODIFY_PatternList_setValue, U"PatternList: Set value", U"PatternList: Set value...") {
+	NATURALVAR (rowNumber, U"Row number", U"1")
+	NATURALVAR (columnNumber, U"Column number", U"1")
+	REALVAR (newValue, U"New value", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (PatternList);
-		long row = GET_INTEGER (U"Row number"), column = GET_INTEGER (U"Column number");
-		if (row > my ny) {
-			Melder_throw (U"Row number must not be greater than number of rows.");
-		}
-		if (column > my nx) {
-			Melder_throw (U"Column number must not be greater than number of columns.");
-		}
-		my z [row] [column] = GET_REAL (U"New value");
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (PatternList)
+		REQUIRE (rowNumber <= my ny, U"Row number must not be greater than number of rows.")
+		REQUIRE (columnNumber <= my nx, U"Column number must not be greater than number of columns.")
+		my z [rowNumber] [columnNumber] = newValue;
+	MODIFY_EACH_END
+}
 
-DIRECT (PatternList_to_Matrix)
-	LOOP {
-		iam (PatternList);
-		praat_new (PatternList_to_Matrix (me), my name);
-	}
-END
+DIRECT (NEW_PatternList_to_Matrix) {
+	CONVERT_EACH (PatternList)
+		autoMatrix result = PatternList_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
 
 /******************* PCA ******************************/
 
-DIRECT (PCA_help)
-	Melder_help (U"PCA");
-END
+DIRECT (HELP_PCA_help) {
+	HELP (U"PCA")
+}
 
-DIRECT (hint_PCA_and_TableOfReal_to_Configuration)
+DIRECT (HINT_hint_PCA_and_TableOfReal_to_Configuration) {
 	Melder_information (U"You can get principal components by selecting a PCA and a TableOfReal\n"
 		"together and choosing \"To Configuration...\".");
-END
+	END 
+
+}
 
-DIRECT (hint_PCA_and_Covariance_Project)
+DIRECT (HINT_hint_PCA_and_Covariance_Project) {
 	Melder_information (U"You can get a new Covariance object rotated to the directions of the direction vectors\n"
 		" in the PCA object by selecting a PCA and a Covariance object together.");
-END
+END }
 
-DIRECT (hint_PCA_and_Configuration_to_TableOfReal_reconstruct)
+DIRECT (HINT_hint_PCA_and_Configuration_to_TableOfReal_reconstruct) {
 	Melder_information (U"You can reconstruct the original TableOfReal as well as possible from\n"
 		" the principal components in the Configuration and the direction vectors in the PCA object.");
-END
+END }
 
-FORM (PCA_and_TableOfReal_getFractionVariance, U"PCA & TableOfReal: Get fraction variance", U"PCA & TableOfReal: Get fraction variance...")
-	NATURAL (U"left Principal component range", U"1")
-	NATURAL (U"right Principal component range", U"1")
+FORM (REAL_PCA_and_TableOfReal_getFractionVariance, U"PCA & TableOfReal: Get fraction variance", U"PCA & TableOfReal: Get fraction variance...") {
+	NATURALVAR (fromPrincipalComponent, U"left Principal component range", U"1")
+	NATURALVAR (toPrincipalComponent, U"right Principal component range", U"1")
 	OK
 DO
-	PCA me = FIRST (PCA);
-	TableOfReal tab = FIRST (TableOfReal);
-	Melder_information (PCA_and_TableOfReal_getFractionVariance (me, tab,
-		GET_INTEGER (U"left Principal component range"), GET_INTEGER (U"right Principal component range")));
-END
+	NUMBER_TWO (PCA, TableOfReal)
+		double result = PCA_and_TableOfReal_getFractionVariance (me, you, fromPrincipalComponent, toPrincipalComponent);
+	NUMBER_TWO_END (U"")
+}
 
-DIRECT (PCA_and_Configuration_to_TableOfReal_reconstruct)
-	PCA me = FIRST (PCA);
-	Configuration conf = FIRST (Configuration);
-	autoTableOfReal thee = PCA_and_Configuration_to_TableOfReal_reconstruct (me, conf);
-	praat_new (thee.move(), my name, U"_", conf->name);
-END
+DIRECT (NEW_PCA_and_Configuration_to_TableOfReal_reconstruct) {
+	CONVERT_TWO (PCA, Configuration)
+		autoTableOfReal result = PCA_and_Configuration_to_TableOfReal_reconstruct (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (PCA_and_TableOfReal_to_TableOfReal_projectRows, U"PCA & TableOfReal: To TableOfReal (project rows)", U"PCA & TableOfReal: To Configuration...")
-	INTEGER (U"Number of dimensions to keep", U"0 (= all)")
+FORM (NEW1_PCA_and_TableOfReal_to_TableOfReal_projectRows, U"PCA & TableOfReal: To TableOfReal (project rows)", U"PCA & TableOfReal: To Configuration...") {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions to keep", U"0 (= all)")
 	OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions to keep");
-	if (dimension < 0) {
-		Melder_throw (U"Number of dimensions must be greater equal zero.");
-	}
-	PCA me = FIRST (PCA);
-	TableOfReal tor = FIRST_GENERIC (TableOfReal);
-	autoTableOfReal thee = PCA_and_TableOfReal_to_TableOfReal_projectRows (me, tor, dimension);
-	praat_new (thee.move(), my name, U"_", tor -> name);
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_ONE_AND_GENERIC (PCA, TableOfReal)
+		autoTableOfReal result = PCA_and_TableOfReal_to_TableOfReal_projectRows (me, you, numberOfDimensions);
+	CONVERT_ONE_AND_GENERIC_END (my name, U"_", your name)
+}
 
-FORM (PCA_and_TableOfReal_to_Configuration, U"PCA & TableOfReal: To Configuration", U"PCA & TableOfReal: To Configuration...")
-	INTEGER (U"Number of dimensions", U"0 (= all)")
+FORM (NEW1_PCA_and_TableOfReal_to_Configuration, U"PCA & TableOfReal: To Configuration", U"PCA & TableOfReal: To Configuration...") {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0 (= all)")
 	OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions");
-	if (dimension < 0) {
-		Melder_throw (U"Number of dimensions must be greater equal zero.");
-	}
-	PCA me = FIRST (PCA);
-	TableOfReal tab = FIRST_GENERIC (TableOfReal);
-	autoConfiguration thee = PCA_and_TableOfReal_to_Configuration (me, tab, dimension);
-	praat_new (thee.move(), my name, U"_", tab->name);
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_ONE_AND_GENERIC (PCA, TableOfReal)
+		autoConfiguration result = PCA_and_TableOfReal_to_Configuration (me, you, numberOfDimensions);
+	CONVERT_ONE_AND_GENERIC_END (my name, U"_", your name)
+}
 
-FORM (PCA_and_TableOfReal_to_TableOfReal_zscores, U"PCA & TableOfReal: To TableOfReal (z-scores)", U"PCA & TableOfReal: To TableOfReal (z-scores)...")
-	INTEGER (U"Number of dimensions", U"0 (= all)")
+FORM (NEW1_PCA_and_TableOfReal_to_TableOfReal_zscores, U"PCA & TableOfReal: To TableOfReal (z-scores)", U"PCA & TableOfReal: To TableOfReal (z-scores)...") {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0 (= all)")
 	OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions");
-	if (dimension < 0) {
-		Melder_throw (U"Number of dimensions must be greater than or equal to zero.");
-	}
-	PCA me = FIRST (PCA);
-	TableOfReal thee = FIRST_GENERIC (TableOfReal);
-	autoTableOfReal him = PCA_and_TableOfReal_to_TableOfReal_zscores (me, thee, dimension);
-	praat_new (him.move(), my name, U"_", thy name, U"_zscores");
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_ONE_AND_GENERIC (PCA, TableOfReal)
+		autoTableOfReal result = PCA_and_TableOfReal_to_TableOfReal_zscores (me, you, numberOfDimensions);
+	CONVERT_ONE_AND_GENERIC_END (my name, U"_", your name, U"_zscores")
+}
 
-FORM (PCA_and_Matrix_to_Matrix_projectRows, U"PCA & Matrix: To Matrix (project rows)", U"")
-	INTEGER (U"Number of dimensions", U"0 (= all)")
+FORM (NEW1_PCA_and_Matrix_to_Matrix_projectRows, U"PCA & Matrix: To Matrix (project rows)", nullptr) {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0 (= all)")
 	OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions");
-	if (dimension < 0) {
-		Melder_throw (U"Number of dimensions must be greater than or equal to zero.");
-	}
-	PCA me = FIRST (PCA);
-	Matrix m = FIRST_GENERIC (Matrix);
-	autoMatrix thee = Eigen_and_Matrix_to_Matrix_projectRows (me, m, dimension);
-	praat_new (thee.move(), my name, U"_", m -> name);
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_TWO (PCA, Matrix)
+		autoMatrix result = Eigen_and_Matrix_to_Matrix_projectRows (me, you, numberOfDimensions);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (PCA_and_Matrix_to_Matrix_projectColumns, U"PCA & Matrix: To Matrix (project columns)", U"")
-	INTEGER (U"Number of dimensions", U"0 (= all)")
+FORM (NEW1_PCA_and_Matrix_to_Matrix_projectColumns, U"PCA & Matrix: To Matrix (project columns)", nullptr) {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0 (= all)")
 	OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions");
-	if (dimension < 0) {
-		Melder_throw (U"Number of dimensions must be greater than or equal to zero.");
-	}
-	PCA me = FIRST (PCA);
-	Matrix m = FIRST_GENERIC (Matrix);
-	autoMatrix thee = Eigen_and_Matrix_to_Matrix_projectColumns (me, m, dimension);
-	praat_new (thee.move(), my name, U"_", m -> name);
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_ONE_AND_GENERIC (PCA, Matrix)
+		autoMatrix result = Eigen_and_Matrix_to_Matrix_projectColumns (me, you, numberOfDimensions);
+	CONVERT_ONE_AND_GENERIC_END (my name, U"_", your name)
+}
 
-FORM (PCA_getCentroidElement, U"PCA: Get centroid element...", nullptr)
-	NATURAL (U"Number", U"1")
+FORM (REAL_PCA_getCentroidElement, U"PCA: Get centroid element...", nullptr) {
+	NATURALVAR (number, U"Number", U"1")
 	OK
 DO
-	long number = GET_INTEGER (U"Number");
-	LOOP {
-		iam (PCA);
-		if (number > my dimension) {
-			Melder_throw (U"Number may not be larger than ", my dimension, U".");
-		}
-		Melder_information (my centroid[number], U" (element ", number, U")");
-	}
-END
+	NUMBER_ONE (PCA)
+		REQUIRE (number <= my dimension, Melder_cat (U"Number may not be larger than ", my dimension, U"."))
+		double result = my centroid [number];
+	NUMBER_ONE_END (U" (element ", number, U")")
+}
 
-FORM (PCA_getEqualityOfEigenvalues, U"PCA: Get equality of eigenvalues", U"PCA: Get equality of eigenvalues...")
-	INTEGER (U"left Eigenvalue range", U"0")
-	INTEGER (U"right Eigenvalue range", U"0")
-	BOOLEAN (U"Conservative test", false)
+FORM (REAL_PCA_getEqualityOfEigenvalues, U"PCA: Get equality of eigenvalues", U"PCA: Get equality of eigenvalues...") {
+	INTEGERVAR (fromEigenvalue, U"left Eigenvalue range", U"0")
+	INTEGERVAR (toEigenvalue, U"right Eigenvalue range", U"0")
+	BOOLEANVAR (conservativeTest, U"Conservative test", false)
 	OK
 DO
-	LOOP {
-		iam (PCA);
-		double p, chisq, df;
-		PCA_getEqualityOfEigenvalues (me, GET_INTEGER (U"left Eigenvalue range"),
-		GET_INTEGER (U"right Eigenvalue range"), GET_INTEGER (U"Conservative test"), & p, & chisq, & df);
-		Melder_information (p, U" (= probability, based on chisq = ",
-		chisq, U" and df = ", df);
-	}
-END
+	NUMBER_ONE (PCA)
+		double result, chisq, df;
+		PCA_getEqualityOfEigenvalues (me, fromEigenvalue,
+		toEigenvalue, conservativeTest, & result, & chisq, & df);
+	NUMBER_ONE_END (U" (= probability, based on chisq = ", chisq, U" and df = ", df)
+}
 
-FORM (PCA_getNumberOfComponentsVAF, U"PCA: Get number of components (VAF)", U"PCA: Get number of components (VAF)...")
-	POSITIVE (U"Variance fraction (0-1)", U"0.95")
+FORM (INTEGER_PCA_getNumberOfComponentsVAF, U"PCA: Get number of components (VAF)", U"PCA: Get number of components (VAF)...") {
+	POSITIVEVAR (varianceFraction, U"Variance fraction (0-1)", U"0.95")
 	OK
 DO
-	double f = GET_REAL (U"Variance fraction");
-	LOOP {
-		iam (Eigen);
-		if (f <= 0 || f > 1) {
-			Melder_throw (U"The variance fraction must be in interval (0-1).");
-		}
-		Melder_information (Eigen_getDimensionOfFraction (me, f));
-	}
-END
+	REQUIRE (varianceFraction >= 0.0 && varianceFraction <= 1.0, U"The variance fraction must be in interval (0-1).")
+	NUMBER_ONE (PCA)
+		double result = Eigen_getDimensionOfFraction (me, varianceFraction);
+	NUMBER_ONE_END (U" (variance fraction)")
+}
 
-FORM (PCA_getFractionVAF, U"PCA: Get fraction variance accounted for", U"PCA: Get fraction variance accounted for...")
-	NATURAL (U"left Principal component range", U"1")
-	NATURAL (U"right Principal component range", U"1")
+FORM (REAL_PCA_getFractionVAF, U"PCA: Get fraction variance accounted for", U"PCA: Get fraction variance accounted for...") {
+	NATURALVAR (fromPrincipalComponent, U"left Principal component range", U"1")
+	NATURALVAR (toPrincipalComponent, U"right Principal component range", U"1")
 	OK
 DO
-	long from = GET_INTEGER (U"left Principal component range");
-	long to = GET_INTEGER (U"right Principal component range");
-	if (from > to) {
-		Melder_throw (U"The second component must be greater than or equal to the first component.");
-	}
-	LOOP {
-		iam (Eigen);
-		if (from > to) {
-			Melder_throw (U"The second component must be greater than or equal to the first component.");
-		}
-		Melder_information (Eigen_getCumulativeContributionOfComponents (me, from, to));
-	}
-END
+	REQUIRE (fromPrincipalComponent <= toPrincipalComponent, U"The second component must be greater than or equal to the first component.")
+	NUMBER_ONE (PCA)
+		double result = Eigen_getCumulativeContributionOfComponents (me, fromPrincipalComponent, toPrincipalComponent);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (PCA_invertEigenvector, U"PCA: Invert eigenvector", nullptr)
-	NATURAL (U"Eigenvector number", U"1")
+FORM (MODIFY_PCA_invertEigenvector, U"PCA: Invert eigenvector", nullptr) {
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Eigen);
-		Eigen_invertEigenvector (me, GET_INTEGER (U"Eigenvector number"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Eigen)
+		Eigen_invertEigenvector (me, eigenvectorNumber);
+	MODIFY_EACH_END
+}
 
-FORM (PCA_extractEigenvector, U"PCA: Extract eigenvector", nullptr)
-	NATURAL (U"Eigenvector number", U"1")
+FORM (NEW_PCA_extractEigenvector, U"PCA: Extract eigenvector", U"Eigen: Extract eigenvector...") {
+	NATURALVAR (eigenvectorNumber, U"Eigenvector number", U"1")
 	LABEL (U"", U"Reshape as")
-	INTEGER (U"Number of rows", U"0")
-	INTEGER (U"Number of columns", U"0")
+	INTEGERVAR (numberOfRows, U"Number of rows", U"0")
+	INTEGERVAR (numberOfColumns, U"Number of columns", U"0")
 	OK
 DO
-	long numberOfRows = GET_INTEGER (U"Number of rows");
-	long numberOfColumns = GET_INTEGER (U"Number of columns");
-	long index = GET_INTEGER (U"Eigenvector number");
 	REQUIRE (numberOfRows >= 0, U"Number of rows must be >= 0.")
 	REQUIRE (numberOfColumns >= 0, U"Number of columns must be >= 0.")
-	LOOP {
-		iam (PCA);
-		autoMatrix thee = Eigen_extractEigenvector (me, index, numberOfRows, numberOfColumns);
-		praat_new (thee.move(), my name, U"_ev", index);
-	}
-END
+	CONVERT_EACH (PCA);
+		autoMatrix result = Eigen_extractEigenvector (me, eigenvectorNumber, numberOfRows, numberOfColumns);
+	CONVERT_EACH_END (my name, U"_ev", eigenvectorNumber)
+}
 
-FORM (PCA_to_TableOfReal_reconstruct1, U"PCA: To TableOfReal (reconstruct)", U"PCA: To TableOfReal (reconstruct 1)...")
-	SENTENCE (U"Coefficients", U"1.0 1.0")
+DIRECT (NEW_PCA_extractEigen) {
+	CONVERT_EACH (PCA)
+		autoEigen result = PCA_to_Eigen (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PCA_to_TableOfReal_reconstruct1, U"PCA: To TableOfReal (reconstruct)", U"PCA: To TableOfReal (reconstruct 1)...") {
+	SENTENCEVAR (coefficients_string, U"Coefficients", U"1.0 1.0")
 	OK
 DO
-	LOOP {
-		iam (PCA);
-		autoTableOfReal thee = PCA_to_TableOfReal_reconstruct1 (me, GET_STRING (U"Coefficients"));
-		praat_new (thee.move(), my name, U"_reconstructed");
-	}
-END
+	CONVERT_EACH (PCA)
+		autoTableOfReal result = PCA_to_TableOfReal_reconstruct1 (me, coefficients_string);
+	CONVERT_EACH_END (my name, U"_reconstructed")
+}
 
-FORM (PCAs_to_Procrustes, U"PCA & PCA: To Procrustes", U"PCA & PCA: To Procrustes...")
-	NATURAL (U"left Eigenvector range", U"1")
-	NATURAL (U"right Eigenvector range", U"2")
+FORM (NEW1_PCAs_to_Procrustes, U"PCA & PCA: To Procrustes", U"PCA & PCA: To Procrustes...") {
+	NATURALVAR (fromEigenvector, U"left Eigenvector range", U"1")
+	NATURALVAR (toEigenvector, U"right Eigenvector range", U"2")
 	OK
 DO
-	long from = GET_INTEGER (U"left Eigenvector range");
-	long to = GET_INTEGER (U"right Eigenvector range");
-	PCA p1 = 0, p2 = 0;
-	LOOP {
-		iam (PCA);
-		(p1 ? p2 : p1) = me;
-	}
-	Melder_assert (p1 && p2);
-	autoProcrustes thee = Eigens_to_Procrustes (p1, p2, from, to);
-	praat_new (thee.move(), Thing_getName (p1), U"_", Thing_getName (p2));
-END
+	CONVERT_COUPLE (PCA)
+		autoProcrustes result = Eigens_to_Procrustes (me, you, fromEigenvector, toEigenvector);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
 
-DIRECT (PCAs_getAngleBetweenPc1Pc2Plane_degrees)
-	PCA p1 = nullptr, p2 = nullptr;
-	LOOP {
-		iam (PCA);
-		(p1 ? p2 : p1) = me;
-	}
-	Melder_assert (p1 && p2);
-	Melder_information (Eigens_getAngleBetweenEigenplanes_degrees (p1, p2),
-		U" degrees (= angle of intersection between the two pc1-pc2 eigenplanes)");
-END
+DIRECT (REAL_PCAs_getAngleBetweenPc1Pc2Plane_degrees) {
+	NUMBER_COUPLE (PCA)
+		double result = Eigens_getAngleBetweenEigenplanes_degrees (me, you);
+	NUMBER_COUPLE_END (U" degrees (= angle of intersection between the two pc1-pc2 eigenplanes)")
+}
 
 /******************* Permutation **************************************/
 
-DIRECT (Permutation_help)
-	Melder_help (U"Permutation");
-END
+DIRECT (HELP_Permutation_help) {
+	HELP (U"Permutation")
+}
 
-FORM (Permutation_create, U"Create Permutation", U"Create Permutation...")
-	WORD (U"Name", U"p")
-	NATURAL (U"Number of elements", U"10")
-	BOOLEAN (U"Identity Permutation", true)
+FORM (NEW_Permutation_create, U"Create Permutation", U"Create Permutation...") {
+	WORDVAR (name, U"Name", U"p")
+	NATURALVAR (numberOfElements, U"Number of elements", U"10")
+	BOOLEANVAR (identity, U"Identity Permutation", true)
 	OK
 DO
-	autoPermutation p = Permutation_create (GET_INTEGER (U"Number of elements"));
-	int identity = GET_INTEGER (U"Identity Permutation");
-	if (! identity) {
-		Permutation_permuteRandomly_inline (p.get(), 0, 0);
-	}
-	praat_new (p.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoPermutation result = Permutation_create (numberOfElements);
+		if (! identity) {
+			Permutation_permuteRandomly_inline (result.get(), 0, 0);
+		}
+	CREATE_ONE_END (name)
+}
 
-DIRECT (Permutation_getNumberOfElements)
-	LOOP {
-		iam (Permutation);
-		Melder_information (my numberOfElements);
-	}
-END
+DIRECT (INTEGER_Permutation_getNumberOfElements) {
+	INTEGER_ONE (Permutation)
+		long result = my numberOfElements;
+	INTEGER_ONE_END (U" (number of elements)")
+}
 
-FORM (Permutation_getValueAtIndex, U"Permutation: Get value", U"Permutation: Get value...")
-	NATURAL (U"Index", U"1")
+FORM (INTEGER_Permutation_getValueAtIndex, U"Permutation: Get value", U"Permutation: Get value...") {
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long index = GET_INTEGER (U"Index");
-	LOOP {
-		iam (Permutation);
-		Melder_information (Permutation_getValueAtIndex (me, index), U" (value, at index = ",
-			index, U")");
-	}
-END
+	INTEGER_ONE (Permutation)
+		long result = Permutation_getValueAtIndex (me, index);
+	INTEGER_ONE_END (U" (value, at index = ", index, U")")
+}
 
-FORM (Permutation_getIndexAtValue, U"Permutation: Get index", U"Permutation: Get index...")
-	NATURAL (U"Value", U"1")
+FORM (INTEGER_Permutation_getIndexAtValue, U"Permutation: Get index", U"Permutation: Get index...") {
+	NATURALVAR (value, U"Value", U"1")
 	OK
 DO
-	long value = GET_INTEGER (U"Value");
-	LOOP {
-		iam (Permutation);
-		Melder_information (Permutation_getIndexAtValue (me, value), U" (index, at value = ",
-			value, U")");
-	}
-END
+	INTEGER_ONE (Permutation)
+		long result = Permutation_getIndexAtValue (me, value);
+	INTEGER_ONE_END (U" (index, at value = ", value, U")")
+}
 
-DIRECT (Permutation_sort)
-	LOOP {
-		iam (Permutation);
+DIRECT (MODIFY_Permutation_sort) {
+	MODIFY_EACH (Permutation)
 		Permutation_sort (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Permutation_swapBlocks, U"Permutation: Swap blocks", U"Permutation: Swap blocks...")
-	NATURAL (U"From index", U"1")
-	NATURAL (U"To index", U"2")
-	NATURAL (U"Block size", U"1")
+FORM (MODIFY_Permutation_swapBlocks, U"Permutation: Swap blocks", U"Permutation: Swap blocks...") {
+	NATURALVAR (fromIndex, U"From index", U"1")
+	NATURALVAR (toIndex, U"To index", U"2")
+	NATURALVAR (blockSize, U"Block size", U"1")
 	OK
 DO
-	LOOP {
-		iam (Permutation);
-		Permutation_swapBlocks (me, GET_INTEGER (U"From index"), GET_INTEGER (U"To index"), GET_INTEGER (U"Block size"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Permutation)
+		Permutation_swapBlocks (me, fromIndex, toIndex, blockSize);
+	MODIFY_EACH_END
+}
 
-FORM (Permutation_swapPositions, U"Permutation: Swap positions", U"Permutation: Swap positions...")
-	NATURAL (U"First index", U"1")
-	NATURAL (U"Second index", U"2")
+FORM (MODIFY_Permutation_swapPositions, U"Permutation: Swap positions", U"Permutation: Swap positions...") {
+	NATURALVAR (firstIndex, U"First index", U"1")
+	NATURALVAR (secondIndex, U"Second index", U"2")
 	OK
 DO
 	LOOP {
 		iam (Permutation);
-		Permutation_swapPositions (me, GET_INTEGER (U"First index"), GET_INTEGER (U"Second index"));
+		Permutation_swapPositions (me, firstIndex, secondIndex);
 		praat_dataChanged (me);
 	}
-END
+END }
 
-FORM (Permutation_swapNumbers, U"Permutation: Swap numbers", U"Permutation: Swap numbers...")
-	NATURAL (U"First number", U"1")
-	NATURAL (U"Second number", U"2")
+FORM (MODIFY_Permutation_swapNumbers, U"Permutation: Swap numbers", U"Permutation: Swap numbers...") {
+	NATURALVAR (firstNumber, U"First number", U"1")
+	NATURALVAR (secondNumber, U"Second number", U"2")
 	OK
 DO
-	LOOP {
-		iam (Permutation);
-		Permutation_swapNumbers (me, GET_INTEGER (U"First number"), GET_INTEGER (U"Second number"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Permutation)
+		Permutation_swapNumbers (me, firstNumber, secondNumber);
+	MODIFY_EACH_END
+}
 
-FORM (Permutation_swapOneFromRange, U"Permutation: Swap one from range", U"Permutation: Swap one from range...")
+FORM (MODIFY_Permutation_swapOneFromRange, U"Permutation: Swap one from range", U"Permutation: Swap one from range...") {
 	LABEL (U"", U"A randomly chosen element from ")
-	INTEGER (U"left Index range", U"0")
-	INTEGER (U"right Index range", U"0")
+	INTEGERVAR (fromIndex, U"left Index range", U"0")
+	INTEGERVAR (toIndex, U"right Index range", U"0")
 	LABEL (U"", U"is swapped with the element at")
-	NATURAL (U"Index", U"1")
-	BOOLEAN (U"Forbid same", 1)
-	OK
-DO
-	LOOP {
-		iam (Permutation);
-		Permutation_swapOneFromRange (me, GET_INTEGER (U"left Index range"), GET_INTEGER (U"right Index range"),
-			GET_INTEGER (U"Index"), GET_INTEGER (U"Forbid same"));
-		praat_dataChanged (me);
-	}
-END
+	NATURALVAR (index, U"Index", U"1")
+	BOOLEANVAR (forbidSame, U"Forbid same", 1)
+	OK
+DO
+	MODIFY_EACH (Permutation)
+		Permutation_swapOneFromRange (me, fromIndex, toIndex, index, forbidSame);
+	MODIFY_EACH_END
+}
 
-FORM (Permutation_permuteRandomly, U"Permutation: Permute randomly", U"Permutation: Permute randomly...")
-	INTEGER (U"left Index range", U"0")
-	INTEGER (U"right Index range", U"0")
+FORM (NEW_Permutation_permuteRandomly, U"Permutation: Permute randomly", U"Permutation: Permute randomly...") {
+	INTEGERVAR (fromIndex, U"left Index range", U"0")
+	INTEGERVAR (toIndex, U"right Index range", U"0")
 	OK
 DO
-	LOOP {
-		iam (Permutation);
-		praat_new (Permutation_permuteRandomly (me, GET_INTEGER (U"left Index range"),
-		GET_INTEGER (U"right Index range")), Thing_getName (me), U"_rdm");
-	}
-END
+	CONVERT_EACH (Permutation)
+		autoPermutation result = Permutation_permuteRandomly (me, fromIndex, toIndex);
+	CONVERT_EACH_END (my name, U"_rdm")
+}
 
-FORM (Permutation_rotate, U"Permutation: Rotate", U"Permutation: Rotate...")
-	INTEGER (U"left Index range", U"0")
-	INTEGER (U"right Index range", U"0")
-	INTEGER (U"Step size", U"1")
+FORM (NEW_Permutation_rotate, U"Permutation: Rotate", U"Permutation: Rotate...") {
+	INTEGERVAR (fromIndex, U"left Index range", U"0")
+	INTEGERVAR (toIndex, U"right Index range", U"0")
+	INTEGERVAR (step, U"Step size", U"1")
 	OK
 DO
-	long step = GET_INTEGER (U"Step size");
-	LOOP {
-		iam (Permutation);
-		praat_new (Permutation_rotate (me, GET_INTEGER (U"left Index range"), GET_INTEGER (U"right Index range"), step),
-			Thing_getName (me), U"_rot", step);
-	}
-END
+	CONVERT_EACH (Permutation)
+		autoPermutation result = Permutation_rotate (me, fromIndex, toIndex, step);
+	CONVERT_EACH_END (my name, U"_rot", step)
+}
 
-FORM (Permutation_reverse, U"Permutation: Reverse", U"Permutation: Reverse...")
-	INTEGER (U"left Index range", U"0")
-	INTEGER (U"right Index range", U"0")
+FORM (NEW_Permutation_reverse, U"Permutation: Reverse", U"Permutation: Reverse...") {
+	INTEGERVAR (fromIndex, U"left Index range", U"0")
+	INTEGERVAR (toIndex, U"right Index range", U"0")
 	OK
 DO
-	LOOP {
-		iam (Permutation);
-		praat_new (Permutation_reverse (me, GET_INTEGER (U"left Index range"), GET_INTEGER (U"right Index range")),
-			Thing_getName (me), U"_rev");
-	}
-END
+	CONVERT_EACH (Permutation)
+		autoPermutation result = Permutation_reverse (me, fromIndex, toIndex);
+	CONVERT_EACH_END (my name, U"_rev")
+}
 
-FORM (Permutation_permuteBlocksRandomly, U"Permutation: Permute blocks randomly", U"Permutation: Permute randomly (blocks)...")
-	INTEGER (U"left Index range", U"0")
-	INTEGER (U"right Index range", U"0")
-	NATURAL (U"Block size", U"12")
-	BOOLEAN (U"Permute within blocks", 1)
-	BOOLEAN (U"No doublets", 0)
+FORM (NEW_Permutation_permuteBlocksRandomly, U"Permutation: Permute blocks randomly", U"Permutation: Permute randomly (blocks)...") {
+	INTEGERVAR (fromIndex, U"left Index range", U"0")
+	INTEGERVAR (toIndex, U"right Index range", U"0")
+	NATURALVAR (blockSize, U"Block size", U"12")
+	BOOLEANVAR (permuteWithinBlocks, U"Permute within blocks", 1)
+	BOOLEANVAR (noDoublets, U"No doublets", 0)
 	OK
 DO
-	long blocksize = GET_INTEGER (U"Block size");
-	LOOP {
-		iam (Permutation);
-		praat_new (Permutation_permuteBlocksRandomly (me, GET_INTEGER (U"left Index range"),
-			GET_INTEGER (U"right Index range"), blocksize, GET_INTEGER (U"Permute within blocks"),
-			GET_INTEGER (U"No doublets")), Thing_getName (me), U"_pbr", blocksize);
-	}
-END
+	CONVERT_EACH (Permutation)
+		autoPermutation result = Permutation_permuteBlocksRandomly (me, fromIndex, toIndex, blockSize, permuteWithinBlocks, noDoublets);
+	CONVERT_EACH_END (my name, U"_pbr", blockSize)
+}
 
-FORM (Permutation_interleave, U"Permutation: Interleave", U"Permutation: Interleave...")
-	INTEGER (U"left Index range", U"0")
-	INTEGER (U"right Index range", U"0")
-	NATURAL (U"Block size", U"12")
-	INTEGER (U"Offset", U"0")
+FORM (NEW_Permutation_interleave, U"Permutation: Interleave", U"Permutation: Interleave...") {
+	INTEGERVAR (fromIndex, U"left Index range", U"0")
+	INTEGERVAR (toIndex, U"right Index range", U"0")
+	NATURALVAR (blockSize, U"Block size", U"12")
+	INTEGERVAR (offset, U"Offset", U"0")
 	OK
 DO
-	LOOP {
-		iam (Permutation);
-		praat_new (Permutation_interleave (me, GET_INTEGER (U"left Index range"), GET_INTEGER (U"right Index range"),
-			GET_INTEGER (U"Block size"), GET_INTEGER (U"Offset")), Thing_getName (me), U"_itl");
-	}
-END
+	CONVERT_EACH (Permutation)
+		autoPermutation result = Permutation_interleave (me, fromIndex, toIndex, blockSize, offset);
+	CONVERT_EACH_END (my name, U"_itl")
+}
 
-DIRECT (Permutation_invert)
-	LOOP {
-		iam (Permutation);
-		praat_new (Permutation_invert (me), Thing_getName (me), U"_inv");
-	}
-END
+DIRECT (NEW_Permutation_invert) {
+	CONVERT_EACH (Permutation)
+		autoPermutation result = Permutation_invert (me);
+	CONVERT_EACH_END (my name, U"_inv")
+}
 
-DIRECT (Permutations_multiply)
-	OrderedOf<structPermutation> list;
-	LOOP {
-		iam (Permutation);
-		list. addItem_ref (me);
-	}
-	autoPermutation result = Permutations_multiply (& list);
-	praat_new (result.move(), U"mul_", list.size);
-END
+DIRECT (NEW1_Permutations_multiply) {
+	CONVERT_LIST (Permutation)
+		autoPermutation result = Permutations_multiply (& list);
+	CONVERT_LIST_END (U"mul_", list.size);
+}
 
-DIRECT (Permutations_next)
-	LOOP {
-		iam (Permutation);
+DIRECT (MODIFY_Permutations_next) {
+	MODIFY_EACH (Permutation)
 		Permutation_next_inline (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (Permutations_previous)
-	LOOP {
-		iam (Permutation);
+DIRECT (MODIFY_Permutations_previous) {
+	MODIFY_EACH (Permutation)
 		Permutation_previous_inline (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Pitches_to_DTW, U"Pitches: To DTW", U"Pitches: To DTW...")
-	REAL (U"Voiced-unvoiced costs", U"24.0")
-	REAL (U"Time costs weight", U"10.0")
-	DTW_constraints_addCommonFields (dia);
+FORM (NEW1_Pitches_to_DTW, U"Pitches: To DTW", U"Pitches: To DTW...") {
+	REALVAR (vuvCosts, U"Voiced-unvoiced costs", U"24.0")
+	REALVAR (weight, U"Time costs weight", U"10.0")
+	DTW_constraints_addCommonFields (matchStart, matchEnd, slopeConstraint)
 	OK
 DO
-	int begin, end, slope;
-	DTW_constraints_getCommonFields (dia, &begin, &end, &slope);
-	Pitch p1 = 0, p2 = 0;
-	LOOP {
-		iam (Pitch);
-		(p1 ? p2 : p1) = me;
-	}
-	Melder_assert (p1 && p2);
-	autoDTW thee = Pitches_to_DTW (p1, p2, GET_REAL (U"Voiced-unvoiced costs"), GET_REAL (U"Time costs weight"), begin, end, slope);
-	praat_new (thee.move(), U"dtw_", Thing_getName (p1), U"_", Thing_getName (p2));
-END
+	CONVERT_COUPLE (Pitch)
+		autoDTW result = Pitches_to_DTW (me, you, vuvCosts, weight, matchStart, matchEnd, slopeConstraint);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (PitchTier_to_Pitch, U"PitchTier: To Pitch", U"PitchTier: To Pitch...")
-	POSITIVE (U"Step size", U"0.02")
-	POSITIVE (U"Pitch floor", U"60.0")
-	POSITIVE (U"Pitch ceiling", U"400.0")
+FORM (NEW_PitchTier_to_Pitch, U"PitchTier: To Pitch", U"PitchTier: To Pitch...") {
+	POSITIVEVAR (stepSize, U"Step size", U"0.02")
+	POSITIVEVAR (pitchFloor, U"Pitch floor (Hz)", U"60.0")
+	POSITIVEVAR (pitchCeiling, U"Pitch ceiling (Hz)", U"400.0")
 	OK
 DO
-	LOOP {
-		iam (PitchTier);
-		autoPitch thee = PitchTier_to_Pitch (me, GET_REAL (U"Step size"),
-		GET_REAL (U"Pitch floor"), GET_REAL (U"Pitch ceiling"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (PitchTier)
+		autoPitch result = PitchTier_to_Pitch (me, stepSize, pitchFloor, pitchCeiling);
+	CONVERT_EACH_END (my name)
+}
 
 /******************* Polygon & Categories *************************************/
 
-FORM (Polygon_createSimple, U"Create simple Polygon", U"Create simple Polygon...")
-	WORD (U"Name", U"p")
-	SENTENCE (U"Vertices as X-Y pairs", U"0.0 0.0  0.0 1.0  1.0 0.0")
+FORM (NEW1_Polygon_createSimple, U"Create simple Polygon", U"Create simple Polygon...") {
+	WORDVAR (name, U"Name", U"p")
+	SENTENCEVAR (vertices_string, U"Vertices as X-Y pairs", U"0.0 0.0  0.0 1.0  1.0 0.0")
 	OK
 DO
-	autoPolygon thee = Polygon_createSimple (GET_STRING (U"Vertices as X-Y pairs"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoPolygon result = Polygon_createSimple (vertices_string);
+	CREATE_ONE_END (name)
+}
 
-FORM (Polygon_createFromRandomVertices, U"", nullptr)
-	WORD (U"Name", U"p")
-	NATURAL (U"Number of vertices", U"10")
-	REAL (U"left X range", U"0.0")
-	REAL (U"right X range", U"1.0")
-	REAL (U"left Y range", U"0.0")
-	REAL (U"right Y range", U"1.0")
+FORM (NEW1_Polygon_createFromRandomPoints, U"Polygon: Create from random points", nullptr) {
+	WORDVAR (name, U"Name", U"p")
+	NATURALVAR (numberOfPoints, U"Number of points", U"10")
+	REALVAR (xmin, U"left X range", U"0.0")
+	REALVAR (xmax, U"right X range", U"1.0")
+	REALVAR (ymin, U"left Y range", U"0.0")
+	REALVAR (ymax, U"right Y range", U"1.0")
 	OK
 DO
-	autoPolygon thee = Polygon_createFromRandomVertices (GET_INTEGER (U"Number of vertices"),
-		GET_REAL (U"left X range"), GET_REAL (U"right X range"),
-		GET_REAL (U"left Y range"), GET_REAL (U"right Y range"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoPolygon result = Polygon_createFromRandomPoints (numberOfPoints, xmin, xmax, ymin, ymax);
+	CREATE_ONE_END (name)
+}
 
-DIRECT (Polygon_getNumberOfPoints)
-	LOOP {
-		iam (Polygon);
-		Melder_information (my numberOfPoints);
-	}
-END
+DIRECT (INTEGER_Polygon_getNumberOfPoints) {
+	INTEGER_ONE (Polygon)
+		long result = my numberOfPoints;
+	INTEGER_ONE_END (U" (number of points)")
+}
 
-FORM (Polygon_getPointX, U"Polygon: Get point (x)", nullptr)
-	NATURAL (U"Point number", U"1")
+FORM (REAL_Polygon_getPointX, U"Polygon: Get point (x)", nullptr) {
+	NATURALVAR (pointNumber, U"Point number", U"1")
 	OK
 DO
-	long point = GET_INTEGER (U"Point number");
-	LOOP {
-		iam (Polygon);
-		if (point > my numberOfPoints) {
-			Melder_throw (U"Point cannot be larger than ", my numberOfPoints, U".");
-		}
-		Melder_information (my x[point]);
-	}
-END
+	NUMBER_ONE (Polygon)
+		double result = pointNumber <= my numberOfPoints ? my x[pointNumber] : NUMundefined;
+	NUMBER_ONE_END (U" (x [", pointNumber, U"])")
+}
 
-FORM (Polygon_getPointY, U"Polygon: Get point (y)", nullptr)
-	NATURAL (U"Point number", U"1")
+FORM (REAL_Polygon_getPointY, U"Polygon: Get point (y)", nullptr) {
+	NATURALVAR (pointNumber, U"Point number", U"1")
 	OK
 DO
-	long point = GET_INTEGER (U"Point number");
-	LOOP {
-		iam (Polygon);
-		if (point > my numberOfPoints) {
-			Melder_throw (U"Vertex cannot be larger than ", my numberOfPoints, U".");
-		}
-		Melder_information (my y[point]);
-	}
-END
+	NUMBER_ONE (Polygon)
+		double result = pointNumber <= my numberOfPoints ? my y[pointNumber] : NUMundefined;
+	NUMBER_ONE_END (U" (y [", pointNumber, U"])")
+}
 
-FORM (Polygon_getLocationOfPoint, U"Get location of point", U"Polygon: Get location of point...")
+FORM (INFO_Polygon_getLocationOfPoint, U"Get location of point", U"Polygon: Get location of point...") {
 	LABEL (U"", U"Point is (I)n, (O)ut, (E)dge or (V)ertex?")
-	REAL (U"X", U"0.0")
-	REAL (U"Y", U"0.0")
-	REAL (U"Precision", U"1.64e-15")
+	REALVAR (x, U"X", U"0.0")
+	REALVAR (y, U"Y", U"0.0")
+	REALVAR (eps, U"Precision", U"1.64e-15")
 	OK
 DO
-	double eps = GET_REAL (U"Precision");
 	REQUIRE (eps >= 0, U"The precision cannot be negative.")
-	LOOP {
-		iam (Polygon);
-		int loc = Polygon_getLocationOfPoint (me, GET_REAL (U"X"), GET_REAL (U"Y"), eps);
-		Melder_information (loc == Polygon_INSIDE ? U"I" : loc == Polygon_OUTSIDE ? U"O" :
-		loc == Polygon_EDGE ? U"E" : U"V");
-	}
-END
+	STRING_ONE (Polygon)
+		int loc = Polygon_getLocationOfPoint (me, x, y, eps);
+		const char32 * result = loc == Polygon_INSIDE ? U"I" : loc == Polygon_OUTSIDE ? U"O" :
+		loc == Polygon_EDGE ? U"E" : U"V";
+	STRING_ONE_END
+}
 
-DIRECT (Polygon_getAreaOfConvexHull)
-	LOOP {
-		iam (Polygon);
-		Melder_informationReal (Polygon_getAreaOfConvexHull (me), nullptr);
-	}
-END
+DIRECT (REAL_Polygon_getAreaOfConvexHull) {
+	NUMBER_ONE (Polygon)
+		double result = Polygon_getAreaOfConvexHull (me);
+	NUMBER_ONE_END (U" (area convex hull)")
+}
 
-FORM (Polygon_circularPermutation, U"Polygon: Circular permutation", nullptr)
-	INTEGER (U"Shift", U"1")
+FORM (NEW_Polygon_circularPermutation, U"Polygon: Circular permutation", nullptr) {
+	INTEGERVAR (shift, U"Shift", U"1")
 	OK
 DO
-	long shift = GET_INTEGER (U"Shift");
-	LOOP {
-		iam (Polygon);
-		autoPolygon thee = Polygon_circularPermutation (me, shift);
-		praat_new (thee.move(), my name, U"_", shift);
-	}
-END
+	CONVERT_EACH (Polygon)
+		autoPolygon result = Polygon_circularPermutation (me, shift);
+	CONVERT_EACH_END (my name, U"_", shift)
+}
 
-DIRECT (Polygon_simplify)
-	LOOP {
-		iam (Polygon);
-		autoPolygon thee = Polygon_simplify (me);
-		praat_new (thee.move(), my name, U"_s");
-	}
-END
 
-DIRECT (Polygon_convexHull)
-	LOOP {
-		iam (Polygon);
-		autoPolygon thee = Polygon_convexHull (me);
-		praat_new (thee.move(), my name, U"_hull");
-	}
-END
+DIRECT (NEW_Polygon_simplify) {
+	CONVERT_EACH (Polygon)
+		autoPolygon result = Polygon_simplify (me);
+	CONVERT_EACH_END (my name, U"_s")
+}
+
+DIRECT (NEW_Polygon_convexHull) {
+	CONVERT_EACH (Polygon)
+		autoPolygon result = Polygon_convexHull (me);
+	CONVERT_EACH_END (my name, U"_hull")
+}
 
-FORM (Polygon_translate, U"Polygon: Translate", U"Polygon: Translate...")
-	REAL (U"X", U"0.0")
-	REAL (U"Y", U"0.0")
+FORM (MODIFY_Polygon_translate, U"Polygon: Translate", U"Polygon: Translate...") {
+	REALVAR (xDistance, U"X distance", U"0.0")
+	REALVAR (yDistance, U"Y distance", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Polygon); 
-		Polygon_translate (me, GET_REAL (U"X"), GET_REAL (U"Y"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Polygon)
+		Polygon_translate (me, xDistance, yDistance);
+	MODIFY_EACH_END
+}
 
-FORM (Polygon_rotate, U"Polygon: Rotate", U"Polygon: Rotate...")
+FORM (MODIFY_Polygon_rotate, U"Polygon: Rotate", U"Polygon: Rotate...") {
 	LABEL (U"", U"Rotate counterclockwise over the")
-	REAL (U"Angle (degrees)", U"0.0")
+	REALVAR (angle_degrees, U"Angle (degrees)", U"0.0")
 	LABEL (U"", U"With respect to the point")
-	REAL (U"X", U"0.0")
-	REAL (U"Y", U"0.0")
+	REALVAR (x, U"X", U"0.0")
+	REALVAR (y, U"Y", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Polygon);
-		Polygon_rotate (me, GET_REAL (U"Angle"), GET_REAL (U"X"), GET_REAL (U"Y"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Polygon)
+		Polygon_rotate (me, angle_degrees, x, y);
+	MODIFY_EACH_END
+}
 
-FORM (Polygon_scale, U"Polygon: Scale polygon", nullptr)
-	REAL (U"X", U"0.0")
-	REAL (U"Y", U"0.0")
+FORM (MODIFY_Polygon_scale, U"Polygon: Scale polygon", nullptr) {
+	REALVAR (x, U"X", U"0.0")
+	REALVAR (y, U"Y", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Polygon);
-		Polygon_scale (me, GET_REAL (U"X"), GET_REAL (U"Y"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Polygon)
+		Polygon_scale (me, x, y);
+	MODIFY_EACH_END
+}
 
-FORM (Polygon_Categories_draw, U"Polygon & Categories: Draw", nullptr)
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Polygon_Categories_draw, U"Polygon & Categories: Draw", nullptr) {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	Polygon me = FIRST (Polygon);
-	Categories cat = FIRST (Categories);
-	Polygon_Categories_draw (me, cat, GRAPHICS, GET_REAL (U"left Horizontal range"),
-		GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_INTEGER (U"Garnish"));
-END
+	GRAPHICS_TWO (Polygon, Categories)
+		Polygon_Categories_draw (me, you, GRAPHICS, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_TWO_END
+}
 
-DIRECT (Polygon_reverseX)
-	LOOP {
-		iam (Polygon);
+DIRECT (MODIFY_Polygon_reverseX) {
+	MODIFY_EACH (Polygon)
 		Polygon_reverseX (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (Polygon_reverseY)
-	LOOP {
-		iam (Polygon);
+DIRECT (MODIFY_Polygon_reverseY) {
+	MODIFY_EACH (Polygon)
 		Polygon_reverseY (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
 /***************** Polynomial *******************/
 
-DIRECT (Polynomial_help) Melder_help (U"Polynomial"); END
+DIRECT (HELP_Polynomial_help) {
+	HELP (U"Polynomial")
+}
 
-FORM (Polynomial_create, U"Create Polynomial from coefficients", U"Create Polynomial...")
-	WORD (U"Name", U"p")
+FORM (NEW1_Polynomial_create, U"Create Polynomial from coefficients", U"Create Polynomial...") {
+	WORDVAR (name, U"Name", U"p")
 	LABEL (U"", U"Domain of polynomial")
-	REAL (U"Xmin", U"-3.0")
-	REAL (U"Xmax", U"4.0")
+	REALVAR (xmin, U"Xmin", U"-3.0")
+	REALVAR (xmax, U"Xmax", U"4.0")
 	LABEL (U"", U"p(x) = c[1] + c[2] x + ... c[n+1] x^n")
-	SENTENCE (U"Coefficients", U"2.0 -1.0 -2.0 1.0")
+	SENTENCEVAR (coefficients_string, U"Coefficients", U"2.0 -1.0 -2.0 1.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	praat_new (Polynomial_createFromString (xmin, xmax, GET_STRING (U"Coefficients")), GET_STRING (U"Name"));
-END
+	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
+	CREATE_ONE
+		autoPolynomial result = Polynomial_createFromString (xmin, xmax, coefficients_string);
+	CREATE_ONE_END (name)
+}
 
-FORM (Polynomial_createFromProducts, U"Create Polynomial from second order products", nullptr)
-	WORD (U"Name", U"p")
+FORM (NEW1_Polynomial_createFromProducts, U"Create Polynomial from second order products", nullptr) {
+	WORDVAR (name, U"Name", U"p")
 	LABEL (U"", U"Domain of polynomial")
-	REAL (U"Xmin", U"-2.0")
-	REAL (U"Xmax", U"2.0")
+	REALVAR (xmin, U"Xmin", U"-2.0")
+	REALVAR (xmax, U"Xmax", U"2.0")
 	LABEL (U"", U"(1+a[1]*x+x^2)*(1+a[2]*x+x^2)*...*(1+a[n]*x+x^2)")
-	SENTENCE (U"The a's", U"1.0 2.0")
+	SENTENCEVAR (coefficients_string, U"The a's", U"1.0 2.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	autoPolynomial thee = Polynomial_createFromProductOfSecondOrderTermsString (xmin, xmax, GET_STRING (U"The a's"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
+	CREATE_ONE
+		autoPolynomial result = Polynomial_createFromProductOfSecondOrderTermsString (xmin, xmax, coefficients_string);
+	CREATE_ONE_END (name)
+}
 
-FORM (Polynomial_createFromZeros, U"Create Polynomial from first order products", nullptr)
-	WORD (U"Name", U"p")
+FORM (NEW1_Polynomial_createFromZeros, U"Create Polynomial from first order products", nullptr) {
+	WORDVAR (name, U"Name", U"p")
 	LABEL (U"", U"Domain of polynomial")
-	REAL (U"Xmin", U"-3.0")
-	REAL (U"Xmax", U"3.0")
+	REALVAR (xmin, U"Xmin", U"-3.0")
+	REALVAR (xmax, U"Xmax", U"3.0")
 	LABEL (U"", U"(P(x) = (x-zero[1])*(1-zero[2])*...*(x-zero[n])")
-	SENTENCE (U"The zero's", U"1.0 2.0")
+	SENTENCEVAR (zeros_string, U"The zero's", U"1.0 2.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	autoPolynomial thee = Polynomial_createFromRealRootsString (xmin, xmax, GET_STRING (U"The zero's"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
+	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
+	CREATE_ONE
+		autoPolynomial result = Polynomial_createFromRealRootsString (xmin, xmax, zeros_string);
+	CREATE_ONE_END (name)
+}
 
-FORM (Polynomial_divide_secondOrderFactor, U"Polynomial: Divide second order factor", nullptr)
+FORM (MODIFY_Polynomial_divide_secondOrderFactor, U"Polynomial: Divide second order factor", nullptr) {
 	LABEL (U"", U"P(x) / (x^2 - factor)")
-	REAL (U"Factor", U"1.0")
+	REALVAR (factor, U"Factor", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (Polynomial);
-		Polynomial_divide_secondOrderFactor (me, GET_REAL (U"Factor"));
-	}
-END
+	MODIFY_EACH (Polynomial)
+		Polynomial_divide_secondOrderFactor (me, factor);
+	MODIFY_EACH_END
+}
 
-FORM (Polynomial_getArea, U"Polynomial: Get area", U"Polynomial: Get area...")
+FORM (REAL_Polynomial_getArea, U"Polynomial: Get area", U"Polynomial: Get area...") {
 	LABEL (U"", U"Interval")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Polynomial);
-		double area = Polynomial_getArea (me, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"));
-		Melder_information (area);
-	}
-END
+	NUMBER_ONE (Polynomial)
+		double result = Polynomial_getArea (me, xmin, xmax);
+	NUMBER_ONE_END (U" (area)")
+}
 
-FORM (Polynomial_getRemainder, U"", 0)
-	REAL (U"Monomial factor", U"1.0")
+FORM (REAL_Polynomial_getRemainderAfterDivision, U"Polynomial: Get remainder after division", nullptr) {
+	LABEL (U"", U"P(x) / (x - factor)")
+	REALVAR (factor, U"Monomial factor", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (Polynomial);
-		double remainder;
+	NUMBER_ONE (Polynomial)
+		double result;
 		autoPolynomial p = Data_copy (me);
-		Polynomial_divide_firstOrderFactor (p.get(), GET_REAL (U"Monomial factor"), & remainder);
-		Melder_information (remainder);
-	}
-END
+		Polynomial_divide_firstOrderFactor (p.get(), factor, & result);
+	NUMBER_ONE_END (U" (remainder)")
+}
 
-FORM (Polynomial_getDerivativesAtX, U"Polynomial: Get derivatives at X", nullptr)
-	REAL (U"X", U"0.5")
-	INTEGER (U"Number of derivatives", U"2")
+FORM (INFO_Polynomial_getDerivativesAtX, U"Polynomial: Get derivatives at X", nullptr) {
+	REALVAR (x, U"X", U"0.5")
+	INTEGERVAR (numberOfDerivatives, U"Number of derivatives", U"2")
 	OK
 DO
-	long numberOfDerivatives = GET_INTEGER (U"Number of derivatives");
 	autoNUMvector<double> derivatives (0L, numberOfDerivatives);
-	LOOP {
-		iam (Polynomial);
-		Polynomial_evaluateDerivatives (me, GET_REAL (U"X"), derivatives.peek(), numberOfDerivatives);
+	INFO_ONE (Polynomial)
+		Polynomial_evaluateDerivatives (me, x, derivatives.peek(), numberOfDerivatives);
 		MelderInfo_open ();
-		for (long i = 0; i <= numberOfDerivatives; i++) {
-			MelderInfo_writeLine (i, U": ", i < my numberOfCoefficients ? derivatives [i] : NUMundefined);
-		}
+			for (long i = 0; i <= numberOfDerivatives; i++) {
+				MelderInfo_writeLine (i, U": ", i < my numberOfCoefficients ? derivatives [i] : NUMundefined);
+			}
 		MelderInfo_close ();
-	}
-END
+	INFO_ONE_END
+}
 
-FORM (Polynomial_getOneRealRoot, U"Polynomial: Get one real root", nullptr)
+FORM (REAL_Polynomial_getOneRealRoot, U"Polynomial: Get one real root", nullptr) {
 	LABEL (U"", U"Interval: ")
-	REAL (U"left X Range", U"-1.0")
-	REAL (U"right X Range", U"1.0")
+	REALVAR (xmin, U"left X Range", U"-1.0")
+	REALVAR (xmax, U"right X Range", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (Polynomial);
-		double root = Polynomial_findOneSimpleRealRoot_nr (me, GET_REAL (U"left X Range"), GET_REAL (U"right X Range"));
-		Melder_information (root);
-	}
-END
+	NUMBER_ONE (Polynomial)
+		double result = Polynomial_findOneSimpleRealRoot_nr (me, xmin, xmax);
+	NUMBER_ONE_END (U" (root)")
+}
 
-DIRECT (Polynomial_getDerivative)
-	LOOP {
-		iam (Polynomial);
-		praat_new (Polynomial_getDerivative (me), my name, U"_derivative");
-	}
-END
+DIRECT (NEW_Polynomial_getDerivative) {
+	CONVERT_EACH (Polynomial)
+		autoPolynomial result = Polynomial_getDerivative (me);
+	CONVERT_EACH_END (my name, U"_derivative")
+}
 
-FORM (Polynomial_getPrimitive, U"Polynomial: Get primitive", nullptr)
-	REAL (U"Constant", U"0.0")
+FORM (NEW_Polynomial_getPrimitive, U"Polynomial: Get primitive", nullptr) {
+	REALVAR (constant, U"Constant", U"0.0")
 	OK
 DO
-	LOOP {
-		iam (Polynomial);
-		praat_new (Polynomial_getPrimitive (me, GET_REAL (U"Constant")), my name, U"_primitive");
-	}
-END
+	CONVERT_EACH (Polynomial)
+		autoPolynomial result = Polynomial_getPrimitive (me,constant);
+	CONVERT_EACH_END (my name, U"_primitive")
+}
 
-FORM (Polynomial_scaleX, U"Polynomial: Scale x", U"Polynomial: Scale x...")
+FORM (NEW_Polynomial_scaleX, U"Polynomial: Scale x", U"Polynomial: Scale x...") {
 	LABEL (U"", U"New domain")
-	REAL (U"Xmin", U"-1.0")
-	REAL (U"Xmax", U"1.0")
+	REALVAR (xmin, U"Xmin", U"-1.0")
+	REALVAR (xmax, U"Xmax", U"1.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	LOOP {
-		iam (Polynomial);
-		praat_new (Polynomial_scaleX (me, xmin, xmax), my name, U"_scaleX");
-	}
-END
+	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
+	CONVERT_EACH (Polynomial)
+		autoPolynomial result = Polynomial_scaleX (me, xmin, xmax);
+	CONVERT_EACH_END (my name, U"_scaleX")
+}
 
-DIRECT (Polynomial_scaleCoefficients_monic)
-	LOOP {
-		iam (Polynomial);
+DIRECT (MODIFY_Polynomial_scaleCoefficients_monic) {
+	MODIFY_EACH (Polynomial)
 		Polynomial_scaleCoefficients_monic (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (Polynomial_to_Roots)
-	LOOP {
-		iam (Polynomial);
-		praat_new (Polynomial_to_Roots (me), my name);
-	}
-END
+DIRECT (NEW_Polynomial_to_Roots) {
+	CONVERT_EACH (Polynomial)
+		autoRoots result = Polynomial_to_Roots (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Polynomial_evaluate_z, U"Polynomial: Get value (complex)", U"Polynomial: Get value (complex)...")
-	REAL (U"Real part", U"0.0")
-	REAL (U"Imaginary part", U"0.0")
+FORM (INFO_Polynomial_evaluate_z, U"Polynomial: Get value (complex)", U"Polynomial: Get value (complex)...") {
+	REALVAR (x, U"Real part", U"0.0")
+	REALVAR (y, U"Imaginary part", U"0.0")
 	OK
 DO
-	dcomplex p, z = dcomplex_create (GET_REAL (U"Real part"), GET_REAL (U"Imaginary part"));
-	LOOP {
-		iam (Polynomial);
+	dcomplex p, z = dcomplex_create (x, y);
+	INFO_ONE (Polynomial)
 		Polynomial_evaluate_z (me, & z, & p);
-		Melder_information (p.re, U" + ", p.im, U" i");
-	}
-END
-
+		MelderInfo_open ();
+			MelderInfo_writeLine (p.re, U" + ", p.im, U" i");
+		MelderInfo_close ();	
+	INFO_ONE_END
+}
 
-FORM (Polynomial_to_Spectrum, U"Polynomial: To Spectrum", U"Polynomial: To Spectrum...")
-	POSITIVE (U"Nyquist frequency (Hz)", U"5000.0")
-	NATURAL (U"Number of frequencies (>1)", U"1025")
+FORM (NEW_Polynomial_to_Spectrum, U"Polynomial: To Spectrum", U"Polynomial: To Spectrum...") {
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	NATURALVAR (numberOfFrequencies, U"Number of frequencies (>1)", U"1025")
 	OK
 DO
-	long n = GET_INTEGER (U"Number of frequencies");
-	LOOP {
-		iam (Polynomial);
-		praat_new (Polynomial_to_Spectrum (me, GET_REAL (U"Nyquist frequency"), n, 1.0), my name);
-	}
-END
+	CONVERT_EACH (Polynomial)
+		autoSpectrum result = Polynomial_to_Spectrum (me, maximumFrequency, numberOfFrequencies, 1.0);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Polynomials_multiply)
-	Polynomial p1 = nullptr, p2 = nullptr;
-	LOOP {
-		iam (Polynomial);
-		(p1 ? p2 : p1) = me;
-	}
-	Melder_assert (p1 && p2);
-	praat_new (Polynomials_multiply (p1, p2), Thing_getName (p1), U"_x_", Thing_getName (p2));
-END
+DIRECT (NEW_Polynomials_multiply) {
+	CONVERT_COUPLE (Polynomial)
+		autoPolynomial result = Polynomials_multiply (me, you);
+	CONVERT_COUPLE_END (my name, U"_x_", your name)
+}
 
-FORM (Polynomials_divide, U"Polynomials: Divide", U"Polynomials: Divide...")
-	BOOLEAN (U"Want quotient", true)
-	BOOLEAN (U"Want remainder", true)
+FORM (NEWMANY_Polynomials_divide, U"Polynomials: Divide", U"Polynomials: Divide...") {
+	BOOLEANVAR (wantQuotient, U"Want quotient", true)
+	BOOLEANVAR (wantRemainder, U"Want remainder", true)
 	OK
 DO
-/* With gcc (GCC) 3.2.2 20030217 (Red Hat Linux 8.0 3.2.2-2)
-	The following line initiates pq = nullptr and I don't know why
-Polynomial p1 = nullptr, p2 = nullptr, pq, pr;
-*/
+	/* With gcc (GCC) 3.2.2 20030217 (Red Hat Linux 8.0 3.2.2-2)
+		The following line initiates pq = nullptr and I don't know why
+		Polynomial p1 = nullptr, p2 = nullptr, pq, pr;
+	*/
 
-	bool wantq = GET_INTEGER (U"Want quotient");
-	bool wantr = GET_INTEGER (U"Want remainder");
-	if (! wantq && ! wantr) {
-		Melder_throw (U"Either \'Want quotient\' or \'Want remainder\' should be chosen");
-	}
-	Polynomial p1 = nullptr, p2 = nullptr;
-	LOOP {
-		iam (Polynomial);
-		(p1 ? p2 : p1) = me;
-	}
-	Melder_assert (p1 && p2);
-	autoPolynomial aq, ar;
-	Polynomials_divide (p1, p2, wantq ? & aq : nullptr, wantr ? & ar : nullptr);
-//	autoPolynomial aq = q, ar = r;
-	if (wantq) {
-		praat_new (aq.move(), Thing_getName (p1), U"_q");
-	}
-	if (wantr) {
-		praat_new (ar.move(), Thing_getName (p1), U"_r");
-	}
-END
+	REQUIRE (wantQuotient || wantRemainder, U"Either \'Want quotient\' or \'Want remainder\' should be chosen")
+	FIND_COUPLE (Polynomial)
+		autoPolynomial aq, ar;
+		Polynomials_divide (me, you, wantQuotient ? & aq : nullptr, wantRemainder ? & ar : nullptr);
+		if (wantQuotient) {
+			praat_new (aq.move(), my name, U"_q");
+		}
+		if (wantRemainder) {
+			praat_new (ar.move(), my name, U"_r");
+		}
+	END
+}
 
 /********************* Roots ******************************/
 
-DIRECT (Roots_help) Melder_help (U"Roots"); END
+DIRECT (HELP_Roots_help) {
+	HELP (U"Roots")
+}
 
-FORM (Roots_draw, U"Roots: Draw", nullptr)
-	REAL (U"Minimum of real axis", U"0.0")
-	REAL (U"Maximum of real axis", U"0.0")
-	REAL (U"Minimum of imaginary axis", U"0.0")
-	REAL (U"Maximum of imaginary axis", U"0.0")
-	SENTENCE (U"Mark string (+x0...)", U"o")
-	NATURAL (U"Mark size", U"12")
-	BOOLEAN (U"Garnish", false)
+FORM (GRAPHICS_Roots_draw, U"Roots: Draw", nullptr) {
+	REALVAR (xmin, U"Minimum of real axis", U"0.0")
+	REALVAR (xmax, U"Maximum of real axis", U"0.0")
+	REALVAR (ymin, U"Minimum of imaginary axis", U"0.0")
+	REALVAR (ymax, U"Maximum of imaginary axis", U"0.0")
+	SENTENCEVAR (mark_string, U"Mark string (+x0...)", U"o")
+	NATURALVAR (markSize, U"Mark size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", false)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Roots);
-		Roots_draw (me, GRAPHICS, GET_REAL (U"Minimum of real axis"), GET_REAL (U"Maximum of real axis"),
-		GET_REAL (U"Minimum of imaginary axis"), GET_REAL (U"Maximum of imaginary axis"),
-		GET_STRING (U"Mark string"), GET_INTEGER (U"Mark size"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Roots)
+		Roots_draw (me, GRAPHICS, xmin, xmax, ymin, ymax, mark_string, markSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Roots_getNumberOfRoots)
-	LOOP {
-		iam (Roots);
-		Melder_information (Roots_getNumberOfRoots (me));
-	}
-END
+DIRECT (INTEGER_Roots_getNumberOfRoots) {
+	INTEGER_ONE (Roots)
+		long result = Roots_getNumberOfRoots (me);
+	INTEGER_ONE_END (U"")
+}
 
-FORM (Roots_getRoot, U"Roots: Get root", nullptr)
-	NATURAL (U"Root number", U"1")
+FORM (COMPLEX_Roots_getRoot, U"Roots: Get root", nullptr) {
+	NATURALVAR (rootNumber, U"Root number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Roots);
-		dcomplex z = Roots_getRoot (me, GET_INTEGER (U"Root number"));
-		Melder_information (z.re, (z.im < 0 ? U" - " : U" + "), fabs (z.im), U" i");   // ppgb: waarom hier de absolute waarde maar beneden niet?
-	}
-END
+	INFO_ONE (Roots)
+		dcomplex z = Roots_getRoot (me, rootNumber);
+		MelderInfo_open ();
+			MelderInfo_writeLine (z.re, z.im,  U" i");
+		MelderInfo_close ();
+	INFO_ONE_END
+}
 
-FORM (Roots_getRealPartOfRoot, U"Roots: Get real part", nullptr)
-	NATURAL (U"Root number", U"1")
+FORM (REAL_Roots_getRealPartOfRoot, U"Roots: Get real part", nullptr) {
+	NATURALVAR (rootNumber, U"Root number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Roots);
-		dcomplex z = Roots_getRoot (me, GET_INTEGER (U"Root number"));
-		Melder_information (z.re);
-	}
-END
+	NUMBER_ONE (Roots)
+		dcomplex z = Roots_getRoot (me, rootNumber);
+		double result = z.re;
+	NUMBER_ONE_END (U"")
+}
 
-FORM (Roots_getImaginaryPartOfRoot, U"Roots: Get imaginary part", nullptr)
-	NATURAL (U"Root number", U"1")
+FORM (REAL_Roots_getImaginaryPartOfRoot, U"Roots: Get imaginary part", nullptr) {
+	NATURALVAR (rootNumber, U"Root number", U"1")
 	OK
 DO
-	LOOP {
-		iam (Roots);
+	NUMBER_ONE (Roots)
 		dcomplex z = Roots_getRoot (me, GET_INTEGER (U"Root number"));
-		Melder_information (z.im);   // ppgb: waarom hier de imaginaire waarde zelf, maar boven de absolute waarde daarvan?
-	}
-END
+		double result = z.im;
+	NUMBER_ONE_END (U" i")
+}
 
-FORM (Roots_setRoot, U"Roots: Set root", nullptr)
-	NATURAL (U"Root number", U"1")
-	REAL (U"Real part", U"1.0/sqrt(2)")
-	REAL (U"Imaginary part", U"1.0/sqrt(2)")
+FORM (MODIFY_Roots_setRoot, U"Roots: Set root", nullptr) {
+	NATURALVAR (rootNumber, U"Root number", U"1")
+	REALVAR (x, U"Real part", U"1.0/sqrt(2)")
+	REALVAR (y, U"Imaginary part", U"1.0/sqrt(2)")
 	OK
 DO
-	LOOP {
-		iam (Roots);
-		Roots_setRoot (me, GET_INTEGER (U"Root number"), GET_REAL (U"Real part"), GET_REAL (U"Imaginary part"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Roots)
+		Roots_setRoot (me, rootNumber, x, y);
+	MODIFY_EACH_END
+}
 
-FORM (Roots_to_Spectrum, U"Roots: To Spectrum", U"Roots: To Spectrum...")
-	POSITIVE (U"Nyquist frequency (Hz)", U"5000.0")
-	NATURAL (U"Number of frequencies (>1)", U"1025")
+FORM (NEW_Roots_to_Spectrum, U"Roots: To Spectrum", U"Roots: To Spectrum...") {
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	NATURALVAR (numberOfFrequencies, U"Number of frequencies (>1)", U"1025")
 	OK
 DO
-	long n = GET_INTEGER (U"Number of frequencies");
-	LOOP {
-		iam (Roots);
-		praat_new (Roots_to_Spectrum (me, GET_REAL (U"Nyquist frequency"), n, 1.0), my name);
-	}
-END
+	CONVERT_EACH (Roots)
+		autoSpectrum result = Roots_to_Spectrum (me, maximumFrequency, numberOfFrequencies, 1.0);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Roots_and_Polynomial_polish)
-	Roots me = FIRST (Roots);
-	Polynomial pol = FIRST (Polynomial);
-	Roots_and_Polynomial_polish (me, pol);
-	praat_dataChanged (me);
-END
+DIRECT (MODIFY_Roots_and_Polynomial_polish) {
+	MODIFY_FIRST_OF_TWO (Roots, Polynomial)
+		Roots_and_Polynomial_polish (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
 /*****************************************************************************/
 
-DIRECT (Praat_ReportFloatingPointProperties)
+DIRECT (INFO_Praat_ReportFloatingPointProperties) {
 	if (! NUMfpp) {
 		NUMmachar ();
 	}
@@ -5992,75 +4858,61 @@ DIRECT (Praat_ReportFloatingPointProperties)
 	MelderInfo_writeLine (U"Safe minimum (such that its inverse does not overflow): ", NUMfpp -> sfmin);
 	MelderInfo_writeLine (U"Overflow threshold (= (1 - eps) * radix ^ expmax): ", NUMfpp -> rmax);
 	MelderInfo_close ();
-END
-/*
-#ifdef HAVE_PULSEAUDIO
-void pulseAudioServer_report ();
-DIRECT (Praat_ReportSoundServerProperties)
-	pulseAudioServer_report ();
-END
-#endif
-*/
-FORM (Praat_getTukeyQ, U"Get TukeyQ", 0)
-	REAL (U"Critical value", U"2.0")
-	NATURAL (U"Number of means", U"3")
-	POSITIVE (U"Degrees of freedom", U"10.0")
-	NATURAL (U"Number of rows", U"1")
+END }
+
+FORM (REAL_Praat_getTukeyQ, U"Get TukeyQ", nullptr) {
+	POSITIVEVAR (criticalValue, U"Critical value", U"2.0")
+	NATURALVAR (numberOfMeans, U"Number of means", U"3")
+	POSITIVEVAR (degreesOfFreedon, U"Degrees of freedom", U"10.0")
+	NATURALVAR (numberOfRows, U"Number of rows", U"1")
 	OK
 DO
-	double q = GET_REAL (U"Critical value");
-	REQUIRE (q > 0 , U"Critical value must be > 0.")
-	double val = NUMtukeyQ (q, GET_INTEGER (U"Number of means"), GET_REAL (U"Degrees of freedom"), GET_INTEGER (U"Number of rows") );
-	Melder_informationReal (val, nullptr);
-END
+	double result = NUMtukeyQ (criticalValue, numberOfMeans, degreesOfFreedon, numberOfRows);
+	Melder_information (result, U" (tukeyQ)");
+END }
 
-FORM (Praat_getInvTukeyQ, U"Get invTukeyQ", 0)
-	REAL (U"Probability", U"0.05")
-	NATURAL (U"Number of means", U"3")
-	POSITIVE (U"Degrees of freedom", U"10.0")
-	NATURAL (U"Number of rows", U"1")
+FORM (REAL_Praat_getInvTukeyQ, U"Get invTukeyQ", nullptr) {
+	REALVAR (probability, U"Probability", U"0.05")
+	NATURALVAR (numberOfMeans, U"Number of means", U"3")
+	POSITIVEVAR (degreesOfFreedon, U"Degrees of freedom", U"10.0")
+	NATURALVAR (numberOfRows, U"Number of rows", U"1")
 	OK
 DO
-	double p = GET_REAL (U"Probability");
-	REQUIRE (p >= 0 && p <= 1, U"Probability must be in (0,1).")
-	double val = NUMinvTukeyQ (p, GET_INTEGER (U"Number of means"), GET_REAL (U"Degrees of freedom"), GET_INTEGER (U"Number of rows"));
-	Melder_informationReal (val, nullptr);
-END
+	REQUIRE (probability >= 0 && probability <= 1, U"Probability must be in (0,1).")
+	double result = NUMinvTukeyQ (probability, numberOfMeans, degreesOfFreedon, numberOfRows);
+	Melder_information (result, U" (inv tukeyQ)");
+END }
 
 /******************** Sound ****************************************/
 
-static void Sound_create_addCommonFields (UiForm dia, const char32 *endTime) {
-	REAL (U"Starting time (s)", U"0.0")
-	REAL (U"Finishing time (s)", endTime)
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-}
+#define Sound_create_addCommonFields(startTime,endTime,samplingFrequency) \
+	REALVAR (startTime, U"Start time (s)", U"0.0") \
+	REALVAR (endTime, U"End time (s)", U"1.0") \
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+
 
-static void Sound_create_checkCommonFields (UiForm dia, double *startingTime, double *finishingTime,
-        double *samplingFrequency) {
+static void Sound_create_checkCommonFields (double startTime, double endTime, double samplingFrequency) {
 	double numberOfSamples_real;
-	*startingTime = GET_REAL (U"Starting time");
-	*finishingTime = GET_REAL (U"Finishing time");
-	*samplingFrequency = GET_REAL (U"Sampling frequency");
-	numberOfSamples_real = round ( (*finishingTime - *startingTime) * *samplingFrequency);
-	if (*finishingTime <= *startingTime) {
-		if (*finishingTime == *startingTime) {
+	numberOfSamples_real = round ( (endTime - startTime) * samplingFrequency);
+	if (endTime <= startTime) {
+		if (endTime == startTime) {
 			Melder_throw (U"A Sound cannot have a duration of zero.");
 		} else {
 			Melder_throw (U"A Sound cannot have a duration less than zero.");
 		}
-		if (*startingTime == 0.0) {
+		if (startTime == 0.0) {
 			Melder_throw (U"Please set the finishing time to something greater than 0 seconds.");
 		} else {
 			Melder_throw (U"Please lower the starting time or raise the finishing time.");
 		}
 	}
-	if (*samplingFrequency <= 0.0)
+	if (samplingFrequency <= 0.0)
 		Melder_throw (U"A Sound cannot have a negative sampling frequency.\n"
-		              U"Please set the sampling frequency to something greater than zero, e.g. 44100 Hz.");
+		U"Please set the sampling frequency to something greater than zero, e.g. 44100 Hz.");
 
 	if (numberOfSamples_real < 1.0) {
 		Melder_appendError (U"A Sound cannot have zero samples.\n");
-		if (*startingTime == 0.0) {
+		if (startTime == 0.0) {
 			Melder_throw (U"Please raise the finishing time.");
 		} else {
 			Melder_throw (U"Please lower the starting time or raise the finishing time.");
@@ -6068,2016 +4920,1588 @@ static void Sound_create_checkCommonFields (UiForm dia, double *startingTime, do
 	}
 	if (numberOfSamples_real > LONG_MAX) {   // ppgb: kan niet in een 64-bit-omgeving
 		Melder_throw (U"A Sound cannot have ", Melder_bigInteger ((long) numberOfSamples_real), U" samples; the maximum is ", Melder_bigInteger (LONG_MAX), U" samples.\n");
-#if 0
-		if (*startingTime == 0.0) {
-			Melder_throw (U"Please lower the finishing time or the sampling frequency.");
-		} else {
-			Melder_throw (U"Please raise the starting time, lower the finishing time, or lower the sampling frequency.");
-		}
-#endif
 	}
 }
 
-FORM (Sound_and_Pitch_to_FormantFilter, U"Sound & Pitch: To FormantFilter", U"Sound & Pitch: To Spectrogram...")
-	POSITIVE (U"Analysis window duration (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW1_Sound_and_Pitch_to_FormantFilter, U"Sound & Pitch: To FormantFilter", U"Sound & Pitch: To Spectrogram...") {
+	POSITIVEVAR (windowLength, U"Analysis window duration (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (Hz)", U"100.0")
-	POSITIVE (U"Distance between filters (Hz)", U"50.0")
-	REAL (U"Maximum frequency", U"0");
-	POSITIVE (U"Relative bandwidth", U"1.1")
-	OK
-DO
-	Sound me = FIRST (Sound);
-	Pitch p = FIRST (Pitch);
-	praat_new (Sound_and_Pitch_to_FormantFilter (me, p, GET_REAL (U"Analysis window duration"),
-		GET_REAL (U"Time step"), GET_REAL (U"Position of first filter"),
-		GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"),
-		GET_REAL (U"Relative bandwidth")), my name, U"_", p->name);
-END
-
-FORM (Sound_and_Pitch_to_Spectrogram, U"Sound & Pitch: To Spectrogram", U"Sound & Pitch: To Spectrogram...")
-	POSITIVE (U"Analysis window duration (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+	POSITIVEVAR (firstFrequency, U"Position of first filter (Hz)", U"100.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (Hz)", U"50.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0");
+	POSITIVEVAR (relativeBandwidth, U"Relative bandwidth", U"1.1")
+	OK
+DO
+	CONVERT_TWO (Sound, Pitch)
+		autoFormantFilter result = Sound_and_Pitch_to_FormantFilter (me, you, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency, relativeBandwidth);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+FORM (NEW1_Sound_and_Pitch_to_Spectrogram, U"Sound & Pitch: To Spectrogram", U"Sound & Pitch: To Spectrogram...") {
+	POSITIVEVAR (windowLength, U"Analysis window duration (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (Hz)", U"100.0")
-	POSITIVE (U"Distance between filters (Hz)", U"50.0")
-	REAL (U"Maximum frequency", U"0");
-	POSITIVE (U"Relative bandwidth", U"1.1")
-	OK
-DO
-	Sound me = FIRST (Sound);
-	Pitch thee = FIRST (Pitch);
-	autoSpectrogram him = Sound_and_Pitch_to_Spectrogram (me, thee, GET_REAL (U"Analysis window duration"),
-		GET_REAL (U"Time step"), GET_REAL (U"Position of first filter"),
-		GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"),
-		GET_REAL (U"Relative bandwidth"));
-	praat_new (him.move(), my name, U"_", thy name);
-END
-
-FORM (Sound_and_Pitch_changeGender, U"Sound & Pitch: Change gender", U"Sound & Pitch: Change gender...")
-	POSITIVE (U"Formant shift ratio", U"1.2")
-	REAL (U"New pitch median (Hz)", U"0.0 (= no change)")
-	POSITIVE (U"Pitch range factor", U"1.0 (= no change)")
-	POSITIVE (U"Duration factor", U"1.0")
-	OK
-DO
-	Sound me = FIRST (Sound);
-	Pitch p = FIRST (Pitch);
-	autoSound thee = Sound_and_Pitch_changeGender_old (me, p, GET_REAL (U"Formant shift ratio"),
-		GET_REAL (U"New pitch median"), GET_REAL (U"Pitch range factor"), GET_REAL (U"Duration factor"));
-	praat_new (thee.move(), my name, U"_", p->name);
-END
-
-FORM (Sound_and_Pitch_changeSpeaker, U"Sound & Pitch: Change speaker", U"Sound & Pitch: Change speaker...")
-	POSITIVE (U"Multiply formants by", U"1.1 (male->female)")
-	POSITIVE (U"Multiply pitch by", U"1.8 (male->female")
-	REAL (U"Multiply pitch range by", U"1.0 (= no change)")
-	POSITIVE (U"Multiply duration", U"1.0")
-	OK
-DO
-	Sound me = FIRST (Sound);
-	Pitch p = FIRST (Pitch);
-	autoSound thee = Sound_and_Pitch_changeSpeaker (me, p, GET_REAL (U"Multiply formants by"),
-		GET_REAL (U"Multiply pitch by"), GET_REAL (U"Multiply pitch range by"), GET_REAL (U"Multiply duration"));
-	praat_new (thee.move(), my name, U"_", p -> name);
-END
-
-FORM (Sound_and_IntervalTier_cutPartsMatchingLabel, U"Sound & IntervalTier: Cut parts matching label", nullptr)
-	SENTENCE (U"Label", U"cut")
-	OK
-DO
-	const char32 *label = GET_STRING (U"Label");
-	Sound me = FIRST (Sound);
-	IntervalTier thee = FIRST (IntervalTier);
-	autoSound him = Sound_and_IntervalTier_cutPartsMatchingLabel (me, thee, label);
-	praat_new (him.move(), my name, U"_cut");
-END
-
-FORM (Sound_createFromGammaTone, U"Create a gammatone", U"Create Sound from gammatone...")
-	WORD (U"Name", U"gammatone")
-	Sound_create_addCommonFields (dia, U"0.1");
-	INTEGER (U"Gamma", U"4")
-	POSITIVE (U"Frequency (Hz)", U"1000.0")
-	REAL (U"Bandwidth (Hz)", U"150.0")
-	REAL (U"Initial phase (radians)", U"0.0")
-	REAL (U"Addition factor", U"0.0")
-	BOOLEAN (U"Scale amplitudes", 1)
-	OK
-DO
-	double startingTime, finishingTime, samplingFrequency;
-	long gamma = GET_INTEGER (U"Gamma");
-	double bandwidth = GET_REAL (U"Bandwidth");
-	double f = GET_REAL (U"Frequency");
-
-	Sound_create_checkCommonFields (dia, &startingTime, &finishingTime, &samplingFrequency);
-	if (f >= samplingFrequency / 2) Melder_throw (U"Frequency cannot be larger than half the sampling frequency.\n"
-				U"Please use a frequency smaller than ", samplingFrequency / 2);
-	if (gamma < 0) {
-		Melder_throw (U"Gamma cannot be negative.\nPlease use a positive or zero gamma.");
-	}
-	if (bandwidth < 0) {
-		Melder_throw (U"Bandwidth cannot be negative.\nPlease use a positive or zero bandwidth.");
-	}
-	autoSound sound = Sound_createGammaTone (startingTime, finishingTime, samplingFrequency, gamma, f, bandwidth,
-		GET_REAL (U"Initial phase"), GET_REAL (U"Addition factor"), GET_INTEGER (U"Scale amplitudes"));
-	//Sound_create_check (sound.get(), startingTime, finishingTime, samplingFrequency);//TODO
-	praat_new (sound.move(), GET_STRING (U"Name"));
-END
-
-FORM (Sound_createFromShepardTone, U"Create a Shepard tone", U"Create Sound from Shepard tone...")
-	WORD (U"Name", U"shepardTone")
-	Sound_create_addCommonFields (dia, U"1.0");
-	POSITIVE (U"Lowest frequency (Hz)", U"4.863")
-	NATURAL (U"Number of components", U"10")
-	REAL (U"Frequency change (semitones/s)", U"4.0")
-	REAL (U"Amplitude range (dB)", U"30.0")
-	REAL (U"Octave shift fraction ([0,1))", U"0.0")
-	OK
-DO
-	double startingTime, finishingTime, samplingFrequency;
-	double amplitudeRange = GET_REAL (U"Amplitude range");
-	double octaveShiftFraction = GET_REAL (U"Octave shift fraction");
-	Sound_create_checkCommonFields (dia, & startingTime, & finishingTime, & samplingFrequency);
-	if (amplitudeRange < 0) {
-		Melder_throw (U"Amplitude range cannot be negative.\nPlease use a positive or zero amplitude range.");
-	}
-	autoSound sound = Sound_createShepardToneComplex (startingTime, finishingTime, samplingFrequency,
-		GET_REAL (U"Lowest frequency"), GET_INTEGER (U"Number of components"),
-		GET_REAL (U"Frequency change"), GET_REAL (U"Amplitude range"), octaveShiftFraction);
-	// Sound_create_check (sound, startingTime, finishingTime, samplingFrequency); //TODO
-	praat_new (sound.move(), GET_STRING (U"Name"));
-END
-
-FORM (Sound_drawWhere, U"Sound: Draw where", U"Sound: Draw where...")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range", U"0.0 (= all)")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	BOOLEAN (U"Garnish", true)
+	POSITIVEVAR (firstFrequency, U"Position of first filter (Hz)", U"100.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (Hz)", U"50.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0");
+	POSITIVEVAR (relativeBandwidth, U"Relative bandwidth", U"1.1")
+	OK
+DO
+	CONVERT_TWO (Sound, Pitch)
+		autoSpectrogram result = Sound_and_Pitch_to_Spectrogram (me, you, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency, relativeBandwidth);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+FORM (NEW1_Sound_and_Pitch_changeGender, U"Sound & Pitch: Change gender", U"Sound & Pitch: Change gender...") {
+	POSITIVEVAR (formantShiftRatio, U"Formant shift ratio", U"1.2")
+	REALVAR (newPitchMedian, U"New pitch median (Hz)", U"0.0 (= no change)")
+	POSITIVEVAR (pitchRangeFactor, U"Pitch range factor", U"1.0 (= no change)")
+	POSITIVEVAR (durationFactor, U"Duration factor", U"1.0")
+	OK
+DO
+	CONVERT_TWO (Sound, Pitch)
+		autoSound result = Sound_and_Pitch_changeGender_old (me, you, formantShiftRatio, newPitchMedian, pitchRangeFactor, durationFactor);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+FORM (NEW1_Sound_and_Pitch_changeSpeaker, U"Sound & Pitch: Change speaker", U"Sound & Pitch: Change speaker...") {
+	POSITIVEVAR (formantFrequencyMultiplicationFactor, U"Multiply formants by", U"1.1 (male->female)")
+	POSITIVEVAR (pitchMultiplicationFactor, U"Multiply pitch by", U"1.8 (male->female")
+	REALVAR (pitchRangeMultiplicationFactor, U"Multiply pitch range by", U"1.0 (= no change)")
+	POSITIVEVAR (durationMultiplicationFactor, U"Multiply duration", U"1.0")
+	OK
+DO
+	CONVERT_TWO (Sound, Pitch)
+		autoSound result = Sound_and_Pitch_changeSpeaker (me, you, formantFrequencyMultiplicationFactor, pitchMultiplicationFactor, pitchRangeMultiplicationFactor, durationMultiplicationFactor);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+FORM (NEW1_Sound_and_IntervalTier_cutPartsMatchingLabel, U"Sound & IntervalTier: Cut parts matching label", nullptr) {
+	SENTENCEVAR (label, U"Label", U"cut")
+	OK
+DO
+	CONVERT_TWO (Sound, IntervalTier)
+		autoSound result = Sound_and_IntervalTier_cutPartsMatchingLabel (me, you, label);
+	CONVERT_TWO_END (my name, U"_cut")
+}
+
+FORM (NEW1_Sound_createAsGammaTone, U"Create a gammatone", U"Create Sound as gammatone...") {
+	WORDVAR (name, U"Name", U"gammatone")
+	Sound_create_addCommonFields (startTime, endTime, samplingFrequency)
+	INTEGERVAR (gamma, U"Gamma", U"4")
+	POSITIVEVAR (frequency, U"Frequency (Hz)", U"1000.0")
+	POSITIVEVAR (bandwidth, U"Bandwidth (Hz)", U"150.0")
+	REALVAR (initialPhase, U"Initial phase (radians)", U"0.0")
+	REALVAR (additionFactor, U"Addition factor", U"0.0")
+	BOOLEANVAR (scaleAmplitudes, U"Scale amplitudes", 1)
+	OK
+DO
+	CREATE_ONE
+		Sound_create_checkCommonFields (startTime, endTime, samplingFrequency);
+		REQUIRE (frequency < samplingFrequency / 2, Melder_cat (U"Frequency cannot be larger than half the sampling frequency.\nPlease use a frequency smaller than ", 	samplingFrequency / 2, U"."))
+		REQUIRE (gamma >= 0, U"Gamma cannot be negative.\nPlease use a positive or zero gamma.")
+		autoSound result = Sound_createGammaTone (startTime, endTime, samplingFrequency, gamma, frequency, bandwidth, initialPhase, additionFactor, scaleAmplitudes);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW_Sound_createAsShepardTone, U"Create a Shepard tone", U"Create Sound as Shepard tone...") {
+	WORDVAR (name, U"Name", U"shepardTone")
+	Sound_create_addCommonFields (startTime, endTime, samplingFrequency)
+	POSITIVEVAR (minimumFrequency, U"Lowest frequency (Hz)", U"4.863")
+	NATURALVAR (numberOfComponents, U"Number of components", U"10")
+	REALVAR (frequencyChange, U"Frequency change (semitones/s)", U"4.0")
+	POSITIVEVAR (amplitudeRange_dB, U"Amplitude range (dB)", U"30.0")
+	REALVAR (octaveShiftFraction, U"Octave shift fraction ([0,1))", U"0.0")
+	OK
+DO
+	CREATE_ONE
+		Sound_create_checkCommonFields (startTime, endTime, samplingFrequency);
+		autoSound result = Sound_createShepardToneComplex (startTime, endTime, samplingFrequency, minimumFrequency, numberOfComponents, frequencyChange, amplitudeRange_dB, octaveShiftFraction);
+	CREATE_ONE_END (name)
+}
+
+FORM (GRAPHICS_Sound_drawWhere, U"Sound: Draw where", U"Sound: Draw where...") {
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 1)
-	OPTION (U"Curve")
-	OPTION (U"Bars")
-	OPTION (U"Poles")
-	OPTION (U"Speckles")
+	OPTIONMENUSTRVAR (drawingMethod, U"Drawing method", 1)
+		OPTION (U"Curve")
+		OPTION (U"Bars")
+		OPTION (U"Poles")
+		OPTION (U"Speckles")
 	LABEL (U"", U"Draw only those parts where the following condition holds:")
-	TEXTFIELD (U"Formula", U"x < xmin + (xmax - xmin) / 2; first half")
+	TEXTVAR (formula, U"Formula", U"x < xmin + (xmax - xmin) / 2; first half")
 	OK
 DO
 	long numberOfBisections = 10;
-	autoPraatPicture picture;
-	LOOP {
-		iam (Sound);
-		Sound_drawWhere (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"),
-		GET_STRING (U"Drawing method"), numberOfBisections, GET_STRING (U"Formula"), interpreter);
-	}
-END
+	GRAPHICS_EACH (Sound)
+		Sound_drawWhere (me, GRAPHICS, fromTime, toTime, ymin, ymax, garnish, drawingMethod, numberOfBisections, formula, interpreter);
+	GRAPHICS_EACH_END
+}
 
-FORM (Sound_playOneChannel, U"Sound: Play one channel", nullptr)
-    NATURAL (U"Channel", U"1")
+FORM (PLAY_Sound_playOneChannel, U"Sound: Play one channel", nullptr) {
+    NATURALVAR (channel, U"Channel", U"1")
     OK
 DO
-    long ichannel = GET_INTEGER (U"Channel");
     LOOP {
         iam (Sound);
-        if (ichannel > my ny) {
-            Melder_throw (me, U": there is no channel ", ichannel, U". Sound has only ", my ny, U" channel",
+		if (channel > my ny) {
+			Melder_throw (me, U": there is no channel ", channel, U". Sound has only ", my ny, U" channel",
 				  (my ny > 1 ? U"s." : U"."));
         }
-        autoSound thee = Sound_extractChannel (me, ichannel);
+        autoSound thee = Sound_extractChannel (me, channel);
         Sound_play (thee.get(), 0, 0);
     }
-END
+END }
 
-FORM (Sound_playAsFrequencyShifted, U"Sound: Play as frequency shifted", U"Sound: Play as frequency shifted...")
-	REAL (U"Shift by (Hz)", U"1000.0")
-	POSITIVE (U"New sampling frequency (Hz)", U"44100.0")
-	NATURAL (U"Precision (samples)", U"50")
+FORM (PLAY_Sound_playAsFrequencyShifted, U"Sound: Play as frequency shifted", U"Sound: Play as frequency shifted...") {
+	REALVAR (frequencyShift, U"Shift by (Hz)", U"1000.0")
+	POSITIVEVAR (samplingFrequency, U"New sampling frequency (Hz)", U"44100.0")
+	NATURALVAR (samplePrecision, U"Precision (samples)", U"50")
 	OK
 DO
-	double shiftBy = GET_REAL (U"Shift by");
-	double newSamplingFrequency = GET_REAL (U"New sampling frequency");
-	long precision = GET_INTEGER (U"Precision");
 	LOOP {
 		iam (Sound);
-		Sound_playAsFrequencyShifted (me, shiftBy, newSamplingFrequency, precision);
+		Sound_playAsFrequencyShifted (me, frequencyShift, samplingFrequency, samplePrecision);
 	}
-END
+END }
 
-FORM (Sounds_to_DTW, U"Sounds: To DTW", nullptr)
-    POSITIVE (U"Window length (s)", U"0.015")
-    POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW1_Sounds_to_DTW, U"Sounds: To DTW", nullptr) {
+    POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+    POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
     LABEL (U"", U"")
-    REAL (U"Sakoe-Chiba band (s)", U"0.1")
-    RADIO (U"Slope constraint", 1)
-    RADIOBUTTON (U"no restriction")
-    RADIOBUTTON (U"1/3 < slope < 3")
-    RADIOBUTTON (U"1/2 < slope < 2")
-    RADIOBUTTON (U"2/3 < slope < 3/2")
+    REALVAR (sakoeChibaBand, U"Sakoe-Chiba band (s)", U"0.1")
+    RADIOVAR (slopeConstraint, U"Slope constraint", 1)
+		RADIOBUTTON (U"no restriction")
+		RADIOBUTTON (U"1/3 < slope < 3")
+		RADIOBUTTON (U"1/2 < slope < 2")
+		RADIOBUTTON (U"2/3 < slope < 3/2")
     OK
 DO
-    double analysisWidth = GET_REAL (U"Window length");
-    double dt = GET_REAL (U"Time step");
-    double band = GET_REAL (U"Sakoe-Chiba band");
-    int slope = GET_INTEGER (U"Slope constraint");
-    Sound s1 = 0, s2 = 0;
-    LOOP {
-        iam (Sound);
-        (s1 ? s2 : s1) = me;
-    }
-    Melder_assert (s1 && s2);
-	autoDTW thee = Sounds_to_DTW (s1, s2, analysisWidth, dt, band, slope);
-    praat_new (thee.move(), s1 -> name, U"_", s2 -> name);
-END
+    CONVERT_COUPLE (Sound)
+		autoDTW result = Sounds_to_DTW (me, you, windowLength, timeStep, sakoeChibaBand, slopeConstraint);
+   CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (Sound_to_TextGrid_detectSilences, U"Sound: To TextGrid (silences)", U"Sound: To TextGrid (silences)...")
+FORM (NEW_Sound_to_TextGrid_detectSilences, U"Sound: To TextGrid (silences)", U"Sound: To TextGrid (silences)...") {
 	LABEL (U"", U"Parameters for the intensity analysis")
-	POSITIVE (U"Minimum pitch (Hz)", U"100")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
+	POSITIVEVAR (minimumPitch, U"Minimum pitch (Hz)", U"100")
+	REALVAR (timeStep, U"Time step (s)", U"0.0 (= auto)")
 	LABEL (U"", U"Silent intervals detection")
-	REAL (U"Silence threshold (dB)", U"-25.0")
-	POSITIVE (U"Minimum silent interval duration (s)", U"0.1")
-	POSITIVE (U"Minimum sounding interval duration (s)", U"0.1")
-	WORD (U"Silent interval label", U"silent")
-	WORD (U"Sounding interval label", U"sounding")
+	REALVAR (silenceThreshold, U"Silence threshold (dB)", U"-25.0")
+	POSITIVEVAR (minimumSilenceDuration, U"Minimum silent interval duration (s)", U"0.1")
+	POSITIVEVAR (minimumSoundingDuration, U"Minimum sounding interval duration (s)", U"0.1")
+	WORDVAR (silenceLabel, U"Silent interval label", U"silent")
+	WORDVAR (soundingLabel, U"Sounding interval label", U"sounding")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoTextGrid thee = Sound_to_TextGrid_detectSilences (me, GET_REAL (U"Minimum pitch"), GET_REAL (U"Time step"),
-			GET_REAL (U"Silence threshold"), GET_REAL (U"Minimum silent interval duration"),
-			GET_REAL (U"Minimum sounding interval duration"), GET_STRING (U"Silent interval label"),
-			GET_STRING (U"Sounding interval label"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoTextGrid result = Sound_to_TextGrid_detectSilences (me, minimumPitch, timeStep, silenceThreshold, minimumSilenceDuration, minimumSoundingDuration, silenceLabel, soundingLabel);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_copyChannelRanges, U"Sound: Copy channel ranges", nullptr)
+FORM (NEW_Sound_copyChannelRanges, U"Sound: Copy channel ranges", nullptr) {
 	LABEL (U"", U"Create a new Sound from the following channels:")
-	TEXTFIELD (U"Ranges", U"1:64")
+	TEXTVAR (channels_string, U"Ranges", U"1:64")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_copyChannelRanges (me, GET_STRING (U"Ranges"));
-		praat_new (thee.move(), my name, U"_channels");
-	}
-END
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_copyChannelRanges (me, channels_string);
+	CONVERT_EACH_END (my name, U"_channels")
+}
 
-FORM (Sound_trimSilences, U"Sound: Trim silences", U"Sound: Trim silences...")
-    REAL (U"Trim duration (s)", U"0.08")
-	BOOLEAN (U"Only at start and end", true);
+FORM (NEW_Sound_trimSilences, U"Sound: Trim silences", U"Sound: Trim silences...") {
+    REALVAR (trimDuration, U"Trim duration (s)", U"0.08")
+	BOOLEANVAR (onlyAtStartAndEnd, U"Only at start and end", true);
 	LABEL (U"", U"Parameters for the intensity analysis")
-	POSITIVE (U"Minimum pitch (Hz)", U"100")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
+	POSITIVEVAR (minimumPitch, U"Minimum pitch (Hz)", U"100")
+	REALVAR (timeStep, U"Time step (s)", U"0.0 (= auto)")
 	LABEL (U"", U"Silent intervals detection")
-	REAL (U"Silence threshold (dB)", U"-35.0")
-	POSITIVE (U"Minimum silent interval duration (s)", U"0.1")
-	POSITIVE (U"Minimum sounding interval duration (s)", U"0.05")
-    BOOLEAN (U"Save trimming info as TextGrid", false)
-    WORD (U"Trim label", U"trimmed")
+	REALVAR (silenceThreshold, U"Silence threshold (dB)", U"-35.0")
+	POSITIVEVAR (minimumSilenceDuration, U"Minimum silent interval duration (s)", U"0.1")
+	POSITIVEVAR (minimumSoundingDuration, U"Minimum sounding interval duration (s)", U"0.05")
+    BOOLEANVAR (saveTextGrid, U"Save trimming info as TextGrid", false)
+    WORDVAR (trim_string, U"Trim label", U"trimmed")
 	OK
 DO
-    double trimDuration = GET_REAL (U"Trim duration");
-    if (trimDuration < 0.0) {
-        trimDuration = 0.0;
-    }
-	bool onlyAtStartAndEnd = GET_INTEGER (U"Only at start and end");
-	double minPitch = GET_REAL (U"Minimum pitch");
-	double timeStep = GET_REAL (U"Time step");
-	double silenceThreshold = GET_REAL (U"Silence threshold");
-	double minSilenceDuration = GET_REAL (U"Minimum silent interval duration");
-	double minSoundingDuration = GET_REAL (U"Minimum sounding interval duration");
-    bool saveTextGrid = GET_INTEGER (U"Save trimming info as TextGrid");
-    const char32 *trimlabel = GET_STRING (U"Trim label");
-	LOOP {
-		iam (Sound);
+    trimDuration = trimDuration < 0.0 ? 0.0 : trimDuration;
+	CONVERT_EACH (Sound)
         autoTextGrid tg;
-		autoSound thee = Sound_trimSilences (me, trimDuration, onlyAtStartAndEnd, minPitch, timeStep, silenceThreshold,
-			minSilenceDuration, minSoundingDuration, ( saveTextGrid ? &tg : nullptr ), trimlabel);
-        if (saveTextGrid) {
+		autoSound result = Sound_trimSilences (me, trimDuration, onlyAtStartAndEnd, minimumPitch, timeStep, silenceThreshold, minimumSilenceDuration, minimumSoundingDuration, (saveTextGrid ? &tg : nullptr ), trim_string);
+		if (saveTextGrid) {
             praat_new (tg.move(), my name, U"_trimmed");
         }
-		praat_new (thee.move(), my name, U"_trimmed");
-	}
-END
+	CONVERT_EACH_END (my name, U"_trimmed")
+}
 
 // deprecated
-FORM (Sound_to_BarkFilter, U"Sound: To BarkFilter", U"Sound: To BarkSpectrogram...")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_BarkFilter, U"Sound: To BarkFilter", U"Sound: To BarkSpectrogram...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (bark)", U"1.0")
-	POSITIVE (U"Distance between filters (bark)", U"1.0")
-	REAL (U"Maximum frequency (bark)", U"0.0");
+	POSITIVEVAR (firstFrequency, U"Position of first filter (bark)", U"1.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (bark)", U"1.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (bark)", U"0.0");
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		praat_new (Sound_to_BarkFilter (me, GET_REAL (U"Window length"),
-		GET_REAL (U"Time step"), GET_REAL (U"Position of first filter"),
-		GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters")), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoBarkFilter result = Sound_to_BarkFilter (me, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_BarkSpectrogram, U"Sound: To BarkSpectrogram", U"Sound: To BarkSpectrogram...")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_BarkSpectrogram, U"Sound: To BarkSpectrogram", U"Sound: To BarkSpectrogram...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (bark)", U"1.0")
-	POSITIVE (U"Distance between filters (bark)", U"1.0")
-	REAL (U"Maximum frequency (bark)", U"0.0");
+	POSITIVEVAR (firstFrequency, U"Position of first filter (bark)", U"1.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (bark)", U"1.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (bark)", U"0.0");
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoBarkSpectrogram thee = Sound_to_BarkSpectrogram (me, GET_REAL (U"Window length"),
-			GET_REAL (U"Time step"), GET_REAL (U"Position of first filter"),
-			GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoBarkSpectrogram result = Sound_to_BarkSpectrogram (me, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency);
+	CONVERT_EACH_END (my name)
+}
 
 // deprecated
-FORM (Sound_to_FormantFilter, U"Sound: To FormantFilter", U"Sound: To FormantFilter...")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_FormantFilter, U"Sound: To FormantFilter", U"Sound: To FormantFilter...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (Hz)", U"100.0")
-	POSITIVE (U"Distance between filters (Hz)", U"50.0")
-	REAL (U"Maximum frequency", U"0.0");
-	POSITIVE (U"Relative bandwidth", U"1.1")
+	POSITIVEVAR (firstFrequency, U"Position of first filter (Hz)", U"100.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (Hz)", U"50.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0.0");
+	POSITIVEVAR (relativeBandwidth, U"Relative bandwidth", U"1.1")
 	LABEL (U"", U"Pitch analysis")
-	REAL (U"Minimum pitch (Hz)", U"75.0")
-	REAL (U"Maximum pitch (Hz)", U"600.0")
+	REALVAR (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	REALVAR (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		praat_new (Sound_to_FormantFilter (me, GET_REAL (U"Window length"),
-		GET_REAL (U"Time step"), GET_REAL (U"Position of first filter"),
-		GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"),
-		GET_REAL (U"Relative bandwidth"), GET_REAL (U"Minimum pitch"),
-		GET_REAL (U"Maximum pitch")), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoFormantFilter result = Sound_to_FormantFilter (me, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency, relativeBandwidth, minimumPitch, maximumPitch);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_Spectrogram_pitchDependent, U"Sound: To Spectrogram (pitch-dependent)", U"Sound: To Spectrogram (pitch-dependent)...")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_Spectrogram_pitchDependent, U"Sound: To Spectrogram (pitch-dependent)", U"Sound: To Spectrogram (pitch-dependent)...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (Hz)", U"100.0")
-	POSITIVE (U"Distance between filters (Hz)", U"50.0")
-	REAL (U"Maximum frequency", U"0.0");
-	POSITIVE (U"Relative bandwidth", U"1.1")
+	POSITIVEVAR (firstFrequency, U"Position of first filter (Hz)", U"100.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (Hz)", U"50.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0.0");
+	POSITIVEVAR (relativeBandwidth, U"Relative bandwidth", U"1.1")
 	LABEL (U"", U"Pitch analysis")
-	REAL (U"Minimum pitch (Hz)", U"75.0")
-	REAL (U"Maximum pitch (Hz)", U"600.0")
+	REALVAR (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	REALVAR (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoSpectrogram thee = Sound_to_Spectrogram_pitchDependent (me, GET_REAL (U"Window length"), GET_REAL (U"Time step"), 
-			GET_REAL (U"Position of first filter"), GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"),
-			GET_REAL (U"Relative bandwidth"), GET_REAL (U"Minimum pitch"), GET_REAL (U"Maximum pitch"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoSpectrogram result = Sound_to_Spectrogram_pitchDependent (me, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency, relativeBandwidth, minimumPitch, maximumPitch);
+	CONVERT_EACH_END (my name)
+}
 
 // deprecated
-FORM (Sound_to_MelFilter, U"Sound: To MelFilter", U"Sound: To MelFilter...")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_MelFilter, U"Sound: To MelFilter", U"Sound: To MelFilter...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (mel)", U"100.0")
-	POSITIVE (U"Distance between filters (mel)", U"100.0")
-	REAL (U"Maximum frequency (mel)", U"0.0");
+	POSITIVEVAR (firstFrequency, U"Position of first filter (mel)", U"100.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (mel)", U"100.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (mel)", U"0.0");
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoMelFilter thee = Sound_to_MelFilter (me, GET_REAL (U"Window length"), GET_REAL (U"Time step"), 
-			GET_REAL (U"Position of first filter"), GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoMelFilter result = Sound_to_MelFilter (me, windowLength, timeStep, firstFrequency, maximumFrequency, deltaFrequency);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_MelSpectrogram, U"Sound: To MelSpectrogram", U"Sound: To MelSpectrogram...")
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_MelSpectrogram, U"Sound: To MelSpectrogram", U"Sound: To MelSpectrogram...") {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Filter bank parameters")
-	POSITIVE (U"Position of first filter (mel)", U"100.0")
-	POSITIVE (U"Distance between filters (mel)", U"100.0")
-	REAL (U"Maximum frequency (mel)", U"0.0");
+	POSITIVEVAR (firstFrequency, U"Position of first filter (mel)", U"100.0")
+	POSITIVEVAR (deltaFrequency, U"Distance between filters (mel)", U"100.0")
+	REALVAR (maximumFrequency, U"Maximum frequency (mel)", U"0.0");
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoMelSpectrogram thee = Sound_to_MelSpectrogram (me, GET_REAL (U"Window length"), GET_REAL (U"Time step"), 
-			GET_REAL (U"Position of first filter"), GET_REAL (U"Maximum frequency"), GET_REAL (U"Distance between filters"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoMelSpectrogram result = Sound_to_MelSpectrogram (me, windowLength, timeStep,  firstFrequency, maximumFrequency, deltaFrequency);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_ComplexSpectrogram, U"Sound: To ComplexSpectrogram", nullptr)
-	POSITIVE (U"Window length (s)", U"0.015")
-	POSITIVE (U"Time step", U"0.005")
+FORM (NEW_Sound_to_ComplexSpectrogram, U"Sound: To ComplexSpectrogram", nullptr) {
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.015")
+	POSITIVEVAR (timeStep, U"Time step", U"0.005")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoComplexSpectrogram thee = Sound_to_ComplexSpectrogram (me, GET_REAL (U"Window length"), GET_REAL (U"Time step"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoComplexSpectrogram result = Sound_to_ComplexSpectrogram (me, windowLength, timeStep);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_Pitch_shs, U"Sound: To Pitch (shs)", U"Sound: To Pitch (shs)...")
-	POSITIVE (U"Time step (s)", U"0.01")
-	POSITIVE (U"Minimum pitch (Hz)", U"50.0")
-	NATURAL (U"Max. number of candidates (Hz)", U"15")
+FORM (NEW_Sound_to_Pitch_shs, U"Sound: To Pitch (shs)", U"Sound: To Pitch (shs)...") {
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.01")
+	POSITIVEVAR (pitchFloor, U"Minimum pitch (Hz)", U"50.0")
+	NATURALVAR (maximumNumberOfCandidates, U"Max. number of candidates (Hz)", U"15")
 	LABEL (U"", U"Algorithm parameters")
-	POSITIVE (U"Maximum frequency component (Hz)", U"1250.0")
-	NATURAL (U"Max. number of subharmonics", U"15")
-	POSITIVE (U"Compression factor (<=1)", U"0.84")
-	POSITIVE (U"Ceiling (Hz)", U"600.0")
-	NATURAL (U"Number of points per octave", U"48");
-	OK
-DO
-	double minimumPitch = GET_REAL (U"Minimum pitch");
-	double fmax = GET_REAL (U"Maximum frequency component");
-	double ceiling = GET_REAL (U"Ceiling");
-	if (minimumPitch >= ceiling) {
-		Melder_throw (U"Minimum pitch should be smaller than ceiling.");
-	}
-	if (ceiling >= fmax) {
-		Melder_throw (U"Maximum frequency must be greater than or equal to ceiling.");
-	}
-	LOOP {
-		iam (Sound);
-		autoPitch thee = Sound_to_Pitch_shs (me, GET_REAL (U"Time step"), minimumPitch, fmax, ceiling,
-		GET_INTEGER (U"Max. number of subharmonics"), GET_INTEGER (U"Max. number of candidates"),
-		GET_REAL (U"Compression factor"), GET_INTEGER (U"Number of points per octave"));
-		praat_new (thee.move(), my name);
-	}
-END
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency component (Hz)", U"1250.0")
+	NATURALVAR (maximumNumberOfSubharmonics, U"Max. number of subharmonics", U"15")
+	POSITIVEVAR (compressionFactor, U"Compression factor (<=1)", U"0.84")
+	POSITIVEVAR (pitchCeiling, U"Ceiling (Hz)", U"600.0")
+	NATURALVAR (numberOfPointsPerOctave, U"Number of points per octave", U"48");
+	OK
+DO
+	REQUIRE (pitchFloor < pitchCeiling, U"Minimum pitch should be smaller than ceiling.")
+	REQUIRE (pitchCeiling < maximumFrequency, U"Maximum frequency must be greater than or equal to ceiling.")
+	CONVERT_EACH (Sound)
+		autoPitch result = Sound_to_Pitch_shs (me, timeStep, pitchFloor, maximumFrequency, pitchCeiling, maximumNumberOfSubharmonics, maximumNumberOfCandidates, compressionFactor, numberOfPointsPerOctave);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_fadeIn, U"Sound: Fade in", U"Sound: Fade in...")
-	CHANNEL (U"Channel (number, 0 = (all))", U"1")
-	REAL (U"Time (s)", U"-10000.0")
-	REAL (U"Fade time (s)", U"0.005")
-	BOOLEAN (U"Silent from start", false)
+FORM (MODIFY_Sound_fadeIn, U"Sound: Fade in", U"Sound: Fade in...") {
+	CHANNELVAR (channel, U"Channel (number, 0 = (all))", U"1")
+	REALVAR (time, U"Time (s)", U"-10000.0")
+	REALVAR (fadeTime, U"Fade time (s)", U"0.005")
+	BOOLEANVAR (silentFromStart, U"Silent from start", false)
 	OK
 DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (Sound);
-		Sound_fade (me, channel, GET_REAL (U"Time"), GET_REAL (U"Fade time"), -1, GET_INTEGER (U"Silent from start"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Sound)
+		Sound_fade (me, channel, time, fadeTime, -1, silentFromStart);
+	MODIFY_EACH_END
+}
 
-FORM (Sound_fadeOut, U"Sound: Fade out", U"Sound: Fade out...")
-	CHANNEL (U"Channel (number, 0 = (all))", U"1")
-	REAL (U"Time (s)", U"10000.0")
-	REAL (U"Fade time (s)", U"-0.005")
-	BOOLEAN (U"Silent to end", false)
+FORM (MODIFY_Sound_fadeOut, U"Sound: Fade out", U"Sound: Fade out...") {
+	CHANNELVAR (channel, U"Channel (number, 0 = (all))", U"1")
+	REALVAR (time, U"Time (s)", U"10000.0")
+	REALVAR (fadeTime, U"Fade time (s)", U"-0.005")
+	BOOLEANVAR (silentToEnd, U"Silent to end", false)
 	OK
 DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (Sound);
-		Sound_fade (me, channel, GET_REAL (U"Time"), GET_REAL (U"Fade time"), 1, GET_INTEGER (U"Silent to end"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (Sound)
+		Sound_fade (me, channel, time, fadeTime, 1, silentToEnd);
+	MODIFY_EACH_END
+}
 
-FORM (Sound_to_KlattGrid_simple, U"Sound: To KlattGrid (simple)", U"Sound: To KlattGrid (simple)...")
-	POSITIVE (U"Time step (s)", U"0.005")
+FORM (NEW_Sound_to_KlattGrid_simple, U"Sound: To KlattGrid (simple)", U"Sound: To KlattGrid (simple)...") {
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
 	LABEL (U"", U"Formant determination")
-	NATURAL (U"Max. number of formants", U"5")
-	POSITIVE (U"Maximum formant (Hz)", U"5500 (= adult female)")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
+	NATURALVAR (numberOfFormants, U"Max. number of formants", U"5")
+	POSITIVEVAR (maximumFormant, U"Maximum formant (Hz)", U"5500 (= adult female)")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
+	POSITIVEVAR (preEmphasisFrequency, U"Pre-emphasis from (Hz)", U"50.0")
 	LABEL (U"", U"Pitch determination")
-	POSITIVE (U"Pitch floor (Hz)", U"60.0")
-	POSITIVE (U"Pitch ceiling (Hz)", U"600.0")
+	POSITIVEVAR (pitchFloor, U"Pitch floor (Hz)", U"60.0")
+	POSITIVEVAR (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
 	LABEL (U"", U"Intensity determination")
-	POSITIVE (U"Minimum pitch (Hz)", U"100.0")
-	BOOLEAN (U"Subtract mean", true)
+	POSITIVEVAR (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
+	BOOLEANVAR (subtractMean, U"Subtract mean", true)
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		praat_new (Sound_to_KlattGrid_simple (me, GET_REAL (U"Time step"),
-			GET_INTEGER (U"Max. number of formants"), GET_REAL (U"Maximum formant"),
-			GET_REAL (U"Window length"), GET_REAL (U"Pre-emphasis from"),
-			GET_REAL (U"Pitch floor"), GET_REAL (U"Pitch ceiling"),
-			GET_REAL (U"Minimum pitch"), GET_INTEGER (U"Subtract mean")), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		autoKlattGrid result = Sound_to_KlattGrid_simple (me, timeStep, numberOfFormants, maximumFormant, windowLength, preEmphasisFrequency, pitchFloor, pitchCeiling, minimumPitch, subtractMean);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_Pitch_SPINET, U"Sound: To SPINET", U"Sound: To SPINET...")
-	POSITIVE (U"Time step (s)", U"0.005")
-	POSITIVE (U"Window length (s)", U"0.040")
+FORM (NEW_Sound_to_Pitch_SPINET, U"Sound: To SPINET", U"Sound: To SPINET...") {
+	POSITIVEVAR (timeStep, U"Time step (s)", U"0.005")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.040")
 	LABEL (U"", U"Gammatone filter bank")
-	POSITIVE (U"Minimum filter frequency (Hz)", U"70.0")
-	POSITIVE (U"Maximum filter frequency (Hz)", U"5000.0")
-	NATURAL (U"Number of filters", U"250");
-	POSITIVE (U"Ceiling (Hz)", U"500.0")
-	NATURAL (U"Max. number of candidates", U"15")
+	POSITIVEVAR (minimumFrequency, U"Minimum filter frequency (Hz)", U"70.0")
+	POSITIVEVAR (maximumFrequency, U"Maximum filter frequency (Hz)", U"5000.0")
+	NATURALVAR (numberOfFilters, U"Number of filters", U"250");
+	POSITIVEVAR (pitchCeiling, U"Ceiling (Hz)", U"500.0")
+	NATURALVAR (maximumNumberOfCandidates, U"Max. number of candidates", U"15")
 	OK
 DO
-	double fmin = GET_REAL (U"Minimum filter frequency");
-	double fmax = GET_REAL (U"Maximum filter frequency");
-	if (fmax <= fmin) {
-		Melder_throw (U"Maximum frequency must be larger than minimum frequency.");
-	}
-	LOOP {
-		iam (Sound);
-		autoPitch thee = Sound_to_Pitch_SPINET (me, GET_REAL (U"Time step"), GET_REAL (U"Window length"), fmin, fmax, 
-			GET_INTEGER (U"Number of filters"), GET_REAL (U"Ceiling"), GET_INTEGER (U"Max. number of candidates"));
-		praat_new (thee.move(), my name);
-	}
-END
+	REQUIRE (minimumFrequency < maximumFrequency, U"Maximum frequency must be larger than minimum frequency.")
+	CONVERT_EACH (Sound)
+		autoPitch result = Sound_to_Pitch_SPINET (me, timeStep, windowLength, minimumFrequency, maximumFrequency, numberOfFilters, pitchCeiling, maximumNumberOfCandidates);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sound_to_Polygon, U"Sound: To Polygon", U"Sound: To Polygon...")
-	CHANNEL (U"Channel (number, Left, or Right)", U"1")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Connection y-value", U"0.0")
+FORM (NEW_Sound_to_Polygon, U"Sound: To Polygon", U"Sound: To Polygon...") {
+	CHANNELVAR (channel, U"Channel (number, Left, or Right)", U"1")
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (connectionY, U"Connection y-value", U"0.0")
 	OK
 DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (Sound);
-		if (channel > my ny) {
-			channel = 1;
-		}
-		autoPolygon thee = Sound_to_Polygon (me, channel, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_REAL (U"Connection y-value"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Sound)
+		channel = channel > my ny ? 1 : channel;
+		autoPolygon result = Sound_to_Polygon (me, channel, fromTime, toTime, ymin, ymax, connectionY);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Sounds_to_Polygon_enclosed, U"Sounds: To Polygon (enclosed)", U"Sounds: To Polygon (enclosed)...")
-	CHANNEL (U"Channel (number, Left, or Right)", U"1")
-	OPTION (U"Left")
-	OPTION (U"Right")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+FORM (NEW1_Sounds_to_Polygon_enclosed, U"Sounds: To Polygon (enclosed)", U"Sounds: To Polygon (enclosed)...") {
+	CHANNELVAR (channel, U"Channel (number, Left, or Right)", U"1")
+		OPTION (U"Left")
+		OPTION (U"Right")
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	OK
 DO
-	long channel = GET_INTEGER (U"Channel");
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoPolygon thee = Sounds_to_Polygon_enclosed (s1, s2, channel, GET_REAL (U"left Time range"),
-		GET_REAL (U"right Time range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"));
-	praat_new (thee.move(), s1->name, U"_", s2->name);
-END
+	CONVERT_COUPLE (Sound)
+		autoPolygon result = Sounds_to_Polygon_enclosed (me, you, channel, fromTime, toTime, ymin, ymax);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (Sound_filterByGammaToneFilter4, U"Sound: Filter (gammatone)", U"Sound: Filter (gammatone)...")
-	POSITIVE (U"Centre frequency (Hz)", U"1000.0")
-	POSITIVE (U"Bandwidth (Hz)", U"150.0")
+FORM (NEW_Sound_filterByGammaToneFilter4, U"Sound: Filter (gammatone)", U"Sound: Filter (gammatone)...") {
+	POSITIVEVAR (centreFrequency, U"Centre frequency (Hz)", U"1000.0")
+	POSITIVEVAR (bandwidth, U"Bandwidth (Hz)", U"150.0")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filterByGammaToneFilter4 (me, GET_REAL (U"Centre frequency"), GET_REAL (U"Bandwidth"));
-		praat_new (thee.move(), my name, U"_filtered");
-	}
-END
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filterByGammaToneFilter4 (me, centreFrequency, bandwidth);
+	CONVERT_EACH_END (my name, U"_filtered")
+}
 
-FORM (Sound_removeNoise, U"Sound: Remove noise", U"Sound: Remove noise...")
-	REAL (U"left Noise time range (s)", U"0.0")
-	REAL (U"right Noise time range (s)", U"0.0")
-	POSITIVE (U"Window length (s)", U"0.025")
+FORM (NEW_Sound_removeNoise, U"Sound: Remove noise", U"Sound: Remove noise...") {
+	REALVAR (fromTime, U"left Noise time range (s)", U"0.0")
+	REALVAR (toTime, U"right Noise time range (s)", U"0.0")
+	POSITIVEVAR (windowLength, U"Window length (s)", U"0.025")
 	LABEL (U"", U"Filter")
-	REAL (U"left Filter frequency range (Hz)", U"80.0")
-	REAL (U"right Filter frequency range (Hz)", U"10000.0")
-	POSITIVE (U"Smoothing (Hz)", U"40.0")
-	OPTIONMENU (U"Noise reduction method", 1)
-	OPTION (U"Spectral subtraction")
+	REALVAR (fromFrequency, U"left Filter frequency range (Hz)", U"80.0")
+	REALVAR (toFrequency, U"right Filter frequency range (Hz)", U"10000.0")
+	POSITIVEVAR (smoothingBandwidth, U"Smoothing bandwidth, (Hz)", U"40.0")
+	OPTIONMENUVAR (noiseReductionMethod, U"Noise reduction method", 1)
+		OPTION (U"Spectral subtraction")
 	OK
 DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_removeNoise (me, GET_REAL (U"left Noise time range"), GET_REAL (U"right Noise time range"),
-			GET_REAL (U"Window length"), GET_REAL (U"left Filter frequency range"),
-			GET_REAL (U"right Filter frequency range"), GET_REAL (U"Smoothing"), GET_INTEGER (U"Noise reduction method"));
-		praat_new (thee.move(), my name, U"_denoised");
-	}
-END
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_removeNoise (me, fromTime, toTime, windowLength, fromFrequency, toFrequency, smoothingBandwidth, noiseReductionMethod);
+	CONVERT_EACH_END (my name, U"_denoised")
+}
 
-FORM (Sound_changeSpeaker, U"Sound: Change speaker", U"Sound: Change speaker...")
+FORM (NEW_Sound_changeSpeaker, U"Sound: Change speaker", U"Sound: Change speaker...") {
 	LABEL (U"", U"Pitch measurement parameters")
-	POSITIVE (U"Pitch floor (Hz)", U"75.0")
-	POSITIVE (U"Pitch ceiling (Hz)", U"600.0")
+	POSITIVEVAR (pitchFloor, U"Pitch floor (Hz)", U"75.0")
+	POSITIVEVAR (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
 	LABEL (U"", U"Modification parameters")
-	POSITIVE (U"Multiply formants by", U"1.2")
-	POSITIVE (U"Multiply pitch by", U"1.0")
-	REAL (U"Multiply pitch range by", U"1.0 (= no change)")
-	POSITIVE (U"Multiply duration by", U"1.0")
+	POSITIVEVAR (formantMultiplicationFactor, U"Multiply formants by", U"1.2")
+	POSITIVEVAR (pitchMultiplicationFactor, U"Multiply pitch by", U"1.0")
+	REALVAR (pitchRangeMultiplicationFactor, U"Multiply pitch range by", U"1.0 (= no change)")
+	POSITIVEVAR (durationMultiplicationFactor, U"Multiply duration by", U"1.0")
 	OK
 DO
-	double minimumPitch = GET_REAL (U"Pitch floor");
-	double maximumPitch = GET_REAL (U"Pitch ceiling");
-	if (minimumPitch >= maximumPitch) {
-		Melder_throw (U"Maximum pitch should be greater than minimum pitch.");
-	}
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_changeSpeaker (me, minimumPitch, maximumPitch, GET_REAL (U"Multiply formants by"), 
-			GET_REAL (U"Multiply pitch by"), GET_REAL (U"Multiply pitch range by"), GET_REAL (U"Multiply duration by"));
-		praat_new (thee.move(), my name, U"_changeSpeaker");
-	}
-END
+	REQUIRE (pitchFloor < pitchCeiling, U"Maximum pitch should be greater than minimum pitch.")
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_changeSpeaker (me, pitchFloor, pitchCeiling, formantMultiplicationFactor, pitchMultiplicationFactor, pitchRangeMultiplicationFactor, durationMultiplicationFactor);
+	CONVERT_EACH_END (my name, U"_changeSpeaker")
+}
 
-FORM (Sound_changeGender, U"Sound: Change gender", U"Sound: Change gender...")
+FORM (NEW_Sound_changeGender, U"Sound: Change gender", U"Sound: Change gender...") {
 	LABEL (U"", U"Pitch measurement parameters")
-	POSITIVE (U"Pitch floor (Hz)", U"75.0")
-	POSITIVE (U"Pitch ceiling (Hz)", U"600.0")
+	POSITIVEVAR (pitchFloor, U"Pitch floor (Hz)", U"75.0")
+	POSITIVEVAR (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
 	LABEL (U"", U"Modification parameters")
-	POSITIVE (U"Formant shift ratio", U"1.2")
-	REAL (U"New pitch median (Hz)", U"0.0 (= no change)")
-	REAL (U"Pitch range factor", U"1.0 (= no change)")
-	POSITIVE (U"Duration factor", U"1.0")
+	POSITIVEVAR (formantShiftRatio, U"Formant shift ratio", U"1.2")
+	REALVAR (pitchMedian, U"New pitch median (Hz)", U"0.0 (= no change)")
+	REALVAR (pitchRangeMultiplicationFactor, U"Pitch range factor", U"1.0 (= no change)")
+	POSITIVEVAR (durationMultiplicationFactor, U"Duration factor", U"1.0")
 	OK
 DO
-	double minimumPitch = GET_REAL (U"Pitch floor");
-	double maximumPitch = GET_REAL (U"Pitch ceiling");
-	double pitchrf = GET_REAL (U"Pitch range factor");
-	if (minimumPitch >= maximumPitch) {
-		Melder_throw (U"Maximum pitch should be greater than minimum pitch.");
-	}
-	if (pitchrf < 0) {
-		Melder_throw (U"Pitch range factor may not be negative");
-	}
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_changeGender_old (me, minimumPitch, maximumPitch, GET_REAL (U"Formant shift ratio"), 
-			GET_REAL (U"New pitch median"), pitchrf, GET_REAL (U"Duration factor"));
-		praat_new (thee.move(), my name, U"_changeGender");
-	}
-END
+	REQUIRE (pitchFloor < pitchCeiling, U"Maximum pitch should be greater than minimum pitch.")
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_changeGender_old (me, pitchFloor, pitchCeiling, formantShiftRatio, pitchMedian, pitchRangeMultiplicationFactor, durationMultiplicationFactor);
+	CONVERT_EACH_END (my name, U"_changeGender");
+}
 
-FORM (Sound_paintWhere, U"Sound paint where", U"Sound: Paint where...")
+FORM (GRAPHICS_Sound_paintWhere, U"Sound paint where", U"Sound: Paint where...") {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Fill from level", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	praat_TimeFunction_RANGE(fromTime,toTime)
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (level, U"Fill from level", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Paint only those parts where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; always")
+	TEXTVAR (formula, U"Formula", U"1; always")
 	OK
 DO
+	Graphics_Colour colour = GET_COLOUR (U"Colour");
 	long numberOfBisections = 10;
-	autoPraatPicture picture;
-	LOOP {
-		iam (Sound);
-		Sound_paintWhere (me, GRAPHICS, GET_COLOUR (U"Colour"), GET_REAL (U"left Time range"),
-		GET_REAL (U"right Time range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_REAL (U"Fill from level"), GET_INTEGER (U"Garnish"), numberOfBisections, GET_STRING (U"Formula"),
+	GRAPHICS_EACH (Sound)
+		Sound_paintWhere (me, GRAPHICS, colour, fromTime, toTime, ymin, ymax, level, garnish, numberOfBisections, formula,
 		interpreter);
-	}
-END
+	GRAPHICS_EACH_END
+}
 
-FORM (Sounds_paintEnclosed, U"Sounds paint enclosed", U"Sounds: Paint enclosed...")
+FORM (GRAPHICS_Sounds_paintEnclosed, U"Sounds paint enclosed", U"Sounds: Paint enclosed...") {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	REALVAR (xFromTime, U"left Horizontal time range (s)", U"0.0")
+	REALVAR (xToTime, U"right Horizontal time range (s)", U"0.0")
+	REALVAR (yFromTime, U"left Vertical time range", U"0.0")
+	REALVAR (yToTime, U"right Vertical time range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoPraatPicture picture;
-	Sounds_paintEnclosed (s1, s2, GRAPHICS, GET_COLOUR (U"Colour"),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-END
-
-FORM_READ2 (Sound_readFromRawFileLE, U"Read Sound from raw Little Endian file", nullptr, true) {
+	Graphics_Colour colour = GET_COLOUR (U"Colour");
+	GRAPHICS_COUPLE (Sound)
+		Sounds_paintEnclosed (me, you, GRAPHICS, colour, xFromTime, xToTime, yFromTime, yToTime, garnish);
+	GRAPHICS_COUPLE_END
+}
+
+FORM_READ (READ1_Sound_readFromRawFileLE, U"Read Sound from raw Little Endian file", nullptr, true) {
 	autoSound thee = Sound_readFromRawFile (file, nullptr, 16, 1, 0, 0, 16000.0);
 	praat_new (thee.move(), MelderFile_name (file));
-END2 }
+END }
 
-FORM_READ2 (Sound_readFromRawFileBE, U"Read Sound from raw 16-bit Little Endian file", nullptr, true) {
+FORM_READ (READ1_Sound_readFromRawFileBE, U"Read Sound from raw 16-bit Little Endian file", nullptr, true) {
 	autoSound thee = Sound_readFromRawFile (file, nullptr, 16, 0, 0, 0, 16000.0);
 	praat_new (thee.move(), MelderFile_name (file));
-END2 }
+END }
 
-FORM_READ2 (KlattTable_readFromRawTextFile, U"KlattTable_readFromRawTextFile", nullptr, true) {
+FORM_READ (READ1_KlattTable_readFromRawTextFile, U"KlattTable_readFromRawTextFile", nullptr, true) {
 	autoKlattTable thee = KlattTable_readFromRawTextFile (file);
 	praat_new (thee.move(), MelderFile_name (file));
-END2 }
+END }
 
 /************ Spectrograms *********************************************/
 
-FORM (Spectrograms_to_DTW, U"Spectrograms: To DTW", nullptr)
-	DTW_constraints_addCommonFields (dia);
+FORM (NEW1_Spectrograms_to_DTW, U"Spectrograms: To DTW", nullptr) {
+	DTW_constraints_addCommonFields (matchStart, matchEnd, slopeConstraint)
 	OK
 DO
-	int begin, end, slope;
-	DTW_constraints_getCommonFields (dia, &begin, &end, &slope);
-	Spectrogram s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Spectrogram);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoDTW thee = Spectrograms_to_DTW (s1, s2, begin, end, slope, 1.0);
-	praat_new (thee.move(), s1->name, U"_", s2->name);
-END
+	CONVERT_COUPLE (Spectrogram)
+		autoDTW result = Spectrograms_to_DTW (me, you, matchStart, matchEnd, slopeConstraint, 1.0);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
 /**************** Spectrum *******************************************/
 
-FORM (Spectrum_drawPhases, U"Spectrum: Draw phases", U"Spectrum: Draw phases...")
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0")
-	REAL (U"Minimum phase (dB/Hz)", U"0.0 (= auto)")
-	REAL (U"Maximum phase (dB/Hz)", U"0.0 (= auto)")
-	BOOLEAN (U"Unwrap", 1)
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_Spectrum_drawPhases, U"Spectrum: Draw phases", U"Spectrum: Draw phases...") {
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0")
+	REALVAR (fromPhase, U"Minimum phase (dB/Hz)", U"0.0 (= auto)")
+	REALVAR (toPhase, U"Maximum phase (dB/Hz)", U"0.0 (= auto)")
+	BOOLEANVAR (unwrap, U"Unwrap", 1)
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Spectrum);
-		Spectrum_drawPhases (me, GRAPHICS, GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-		GET_REAL (U"Minimum phase"), GET_REAL (U"Maximum phase"),
-		GET_INTEGER (U"Unwrap"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Spectrum)
+		Spectrum_drawPhases (me, GRAPHICS, fromFrequency, toFrequency, fromPhase, toPhase, unwrap, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Spectrum_setRealValueInBin, U"Spectrum: Set real value in bin", nullptr)
-	NATURAL (U"Bin number", U"100")
-	REAL (U"Value", U"0.0")
+FORM (MODIFY_Spectrum_setRealValueInBin, U"Spectrum: Set real value in bin", nullptr) {
+	NATURALVAR (binNumber, U"Bin number", U"100")
+	REALVAR (value, U"Value", U"0.0")
 	OK
 DO
-	long binNumber = GET_INTEGER (U"Bin number");
-	LOOP {
-		iam (Spectrum);
-		if (binNumber > my nx) Melder_throw (U"Bin number must not exceed number of bins.");
-		my z[1][binNumber]= GET_REAL (U"Value");
-	}
-END
+	MODIFY_EACH (Spectrum)
+		REQUIRE (binNumber <= my nx, U"Bin number must not exceed number of bins.")
+		my z[1][binNumber]= value;
+	MODIFY_EACH_END
+}
 
-FORM (Spectrum_setImaginaryValueInBin, U"Spectrum: Set imaginary value in bin", nullptr)
-	NATURAL (U"Bin number", U"100")
-	REAL (U"Value", U"0.0")
+FORM (MODIFY_Spectrum_setImaginaryValueInBin, U"Spectrum: Set imaginary value in bin", nullptr) {
+	NATURALVAR (binNumber, U"Bin number", U"100")
+	REALVAR (value, U"Value", U"0.0")
 	OK
 DO
-	long binNumber = GET_INTEGER (U"Bin number");
-	LOOP {
-		iam (Spectrum);
-		if (binNumber > my nx) Melder_throw (U"Bin number must not exceed number of bins.");
-		my z[2][binNumber]= GET_REAL (U"Value");
-	}
-END
+	MODIFY_EACH (Spectrum)
+		REQUIRE (binNumber <= my nx, U"Bin number must not exceed number of bins.")
+		my z[2][binNumber]= value;
+	MODIFY_EACH_END
+}
 
-DIRECT (Spectrum_conjugate)
-	LOOP {
-		iam (Spectrum);
+DIRECT (MODIFY_Spectrum_conjugate) {
+	MODIFY_EACH (Spectrum)
 		Spectrum_conjugate (me);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Spectrum_shiftFrequencies, U"Spectrum: Shift frequencies", U"Spectrum: Shift frequencies...")
-	REAL (U"Shift by (Hz)", U"1000.0")
-	POSITIVE (U"New maximum frequency (Hz)", U"22050")
-	NATURAL (U"Precision", U"50")
+FORM (NEW_Spectrum_shiftFrequencies, U"Spectrum: Shift frequencies", U"Spectrum: Shift frequencies...") {
+	REALVAR (frequencyShift, U"Shift by (Hz)", U"1000.0")
+	POSITIVEVAR (maximumFrequency, U"New maximum frequency (Hz)", U"22050")
+	NATURALVAR (interpolationDepth, U"Interpolation depth", U"50")
 	OK
 DO
-	double shiftBy = GET_REAL (U"Shift by");
-	double newMaximumFrequency = GET_REAL (U"New maximum frequency");
-	long precision = GET_INTEGER (U"Precision");
-	LOOP {
-		iam (Spectrum);
-		autoSpectrum thee = Spectrum_shiftFrequencies (me, shiftBy, newMaximumFrequency, precision);
-		praat_new (thee.move(), my name, (shiftBy < 0 ? U"_m" : U"_"), (long) floor (shiftBy));
-	}
-END
+	CONVERT_EACH (Spectrum)
+		autoSpectrum result = Spectrum_shiftFrequencies (me, frequencyShift, maximumFrequency, interpolationDepth);
+	CONVERT_EACH_END (my name, (frequencyShift < 0 ? U"_m" : U"_"), (long) floor (frequencyShift))
+}
 
-DIRECT (Spectra_multiply)
-	Spectrum s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Spectrum);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	praat_new (Spectra_multiply (s1, s2), Thing_getName (s1), U"_x_", Thing_getName (s2));
-END
+DIRECT (NEW_Spectra_multiply) {
+	CONVERT_COUPLE (Spectrum)
+		autoSpectrum result = Spectra_multiply (me, you);
+	CONVERT_COUPLE_END (my name, U"_x_", your name)
+}
 
-FORM (Spectrum_resample, U"Spectrum: Resample", nullptr)
-	NATURAL (U"New number of frequencies", U"256")
+FORM (NEW_Spectrum_resample, U"Spectrum: Resample", nullptr) {
+	NATURALVAR (numberOfFrequencies, U"New number of frequencies", U"256")
 	OK
 DO
-	long numberOfFrequencies = GET_INTEGER (U"New number of frequencies");
-	LOOP {
-		iam (Spectrum);
-		autoSpectrum thee = Spectrum_resample (me, numberOfFrequencies);
-		praat_new (thee.move(), my name, U"_", numberOfFrequencies);
-	}
-END
+	CONVERT_EACH (Spectrum)
+		autoSpectrum result = Spectrum_resample (me, numberOfFrequencies);
+	CONVERT_EACH_END (my name, U"_", numberOfFrequencies)
+}
 
-FORM (Spectrum_compressFrequencyDomain, U"Spectrum: Compress frequency domain", nullptr)
-	POSITIVE (U"Maximum frequency (Hz)", U"5000.0")
-	INTEGER (U"Interpolation depth", U"50")
-	RADIO (U"Interpolation scale", 1)
+FORM (NEW_Spectrum_compressFrequencyDomain, U"Spectrum: Compress frequency domain", nullptr) {
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	INTEGERVAR (interpolationDepth, U"Interpolation depth", U"50")
+	RADIOVAR (scale, U"Interpolation scale", 1)
 		RADIOBUTTON (U"Linear")
 		RADIOBUTTON (U"Logarithmic")
 	OK
 DO
-	double maximumFrequency = GET_REAL (U"Maximum frequency");
-	long interpolationDepth = GET_INTEGER (U"Interpolation depth");
-	int freqScale = GET_INTEGER (U"Interpolation scale");
-	LOOP {
-		iam (Spectrum);
-		autoSpectrum thee = Spectrum_compressFrequencyDomain (me, maximumFrequency, interpolationDepth, freqScale, 1);
-		praat_new (thee.move(), my name, U"_", (long) floor (maximumFrequency));
-	}
-END
+	CONVERT_EACH (Spectrum)
+		autoSpectrum result = Spectrum_compressFrequencyDomain (me, maximumFrequency, interpolationDepth, scale, 1);
+	CONVERT_EACH_END (my name, U"_", (long) floor (maximumFrequency))
+}
 
-DIRECT (Spectrum_unwrap)
-	LOOP {
-		iam (Spectrum);
-		praat_new (Spectrum_unwrap (me), my name);
-	}
-END
+DIRECT (NEW_Spectrum_unwrap) {
+	CONVERT_EACH (Spectrum)
+		autoMatrix result = Spectrum_unwrap (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Spectrum_to_PowerCepstrum)
-	LOOP {
-		iam (Spectrum);
-		autoPowerCepstrum thee = Spectrum_to_PowerCepstrum (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Spectrum_to_PowerCepstrum) {
+	CONVERT_EACH (Spectrum)
+		autoPowerCepstrum result = Spectrum_to_PowerCepstrum (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Spectrum_to_Cepstrum)
-	LOOP {
-		iam (Spectrum);
-		autoCepstrum thee = Spectrum_to_Cepstrum (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_Spectrum_to_Cepstrum) {
+	CONVERT_EACH (Spectrum)
+		autoCepstrum result = Spectrum_to_Cepstrum (me);
+	CONVERT_EACH_END (my name)
+}
 
 /************* SpeechSynthesizer *************************************************/
 
-DIRECT (SpeechSynthesizer_help)
-	Melder_help (U"SpeechSynthesizer");
-END
+DIRECT (HELP_SpeechSynthesizer_help) {
+	HELP (U"SpeechSynthesizer")
+}
 
-FORM (SpeechSynthesizer_create, U"Create SpeechSynthesizer", U"Create SpeechSynthesizer...")
-	long prefVoice = Strings_findString (espeakdata_voices_names.get(), U"English");
-	if (prefVoice == 0) {
-		prefVoice = 1;
-	}
-	LIST (U"Language", espeakdata_voices_names -> numberOfStrings, (const char32 **) espeakdata_voices_names -> strings, prefVoice)
-	long prefVariant = Strings_findString (espeakdata_variants_names.get(), U"default");
-	LIST (U"Voice variant", espeakdata_variants_names -> numberOfStrings,
-		(const char32 **) espeakdata_variants_names -> strings, prefVariant)
-	OK
-DO
-	long voiceIndex = GET_INTEGER (U"Language");
-	long variantIndex = GET_INTEGER (U"Voice variant"); // default is not in the list!
-	autoSpeechSynthesizer me = SpeechSynthesizer_create (espeakdata_voices_names -> strings[voiceIndex],
-		espeakdata_variants_names -> strings[variantIndex]);
-    praat_new (me.move(),  espeakdata_voices_names -> strings[voiceIndex], U"_",
-        espeakdata_variants_names -> strings[variantIndex]);
-END
+FORM (NEW1_SpeechSynthesizer_create, U"Create SpeechSynthesizer", U"Create SpeechSynthesizer...") {
+	/* 
+	 * In the speech synthesis world a language variant is called a "voice", we use the same terminology 
+	 * in our coding. However for the user interface we use "language" instead of "voice".
+	 */
+	static long prefLanguage = Strings_findString (espeakdata_voices_names.get(), U"English");
+	if (prefLanguage == 0) {
+		prefLanguage = 1;
+	}
+	// LIST does not scroll to the line with "prefLanguage"
+	LISTVAR (languageIndex, U"Language", espeakdata_voices_names -> numberOfStrings, (const char32 **) espeakdata_voices_names -> strings, prefLanguage)
+	static long prefVoiceVariant = Strings_findString (espeakdata_variants_names.get(), U"default");
+	LISTVAR (voiceVariantIndex, U"Voice variant", espeakdata_variants_names -> numberOfStrings,
+		(const char32 **) espeakdata_variants_names -> strings, prefVoiceVariant)
+	OK
+DO
+	CREATE_ONE
+		autoSpeechSynthesizer result = SpeechSynthesizer_create (espeakdata_voices_names -> strings[languageIndex], espeakdata_variants_names -> strings[voiceVariantIndex]);
+    CREATE_ONE_END (espeakdata_voices_names -> strings[languageIndex], U"_", espeakdata_variants_names -> strings[voiceVariantIndex])
+}
 
-FORM (SpeechSynthesizer_playText, U"SpeechSynthesizer: Play text", U"SpeechSynthesizer: Play text...")
-	TEXTFIELD (U"Text", U"This is some text.")
+FORM (PLAY_SpeechSynthesizer_playText, U"SpeechSynthesizer: Play text", U"SpeechSynthesizer: Play text...") {
+	TEXTVAR (text, U"Text", U"This is some text.")
 	OK
 DO
-	const char32 *text = GET_STRING (U"Text");
 	LOOP {
 		iam (SpeechSynthesizer);
 		SpeechSynthesizer_playText (me, text);
 	}
-END
+END }
 
-FORM (SpeechSynthesizer_to_Sound, U"SpeechSynthesizer: To Sound", U"SpeechSynthesizer: To Sound...")
-	TEXTFIELD (U"Text", U"This is some text.")
-	BOOLEAN (U"Create TextGrid with annotations", false);
+FORM (NEWMANY_SpeechSynthesizer_to_Sound, U"SpeechSynthesizer: To Sound", U"SpeechSynthesizer: To Sound...") {
+	TEXTVAR (text, U"Text", U"This is some text.")
+	BOOLEANVAR (wantTextGrid, U"Create TextGrid with annotations", false);
 	OK
 DO
-	const char32 *text = GET_STRING (U"Text");
-	bool createTextGrid = GET_INTEGER (U"Create TextGrid with annotations");
-	LOOP {
-		iam (SpeechSynthesizer);
+	CONVERT_EACH (SpeechSynthesizer)
 		autoTextGrid tg;
 		autoTable t;
-		autoSound thee = SpeechSynthesizer_to_Sound (me, text, (createTextGrid ? & tg : nullptr), (Melder_debug == -2 ? & t : nullptr ));
-		praat_new (thee.move(), my name);
-		if (createTextGrid) {
+		autoSound result = SpeechSynthesizer_to_Sound (me, text, (wantTextGrid ? & tg : nullptr), (Melder_debug == -2 ? & t : nullptr ));
+		if (wantTextGrid) {
 			praat_new (tg.move(), my name);
 		}
 		if (Melder_debug == -2) {
 			praat_new (t.move(), my name);
 		}
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (SpeechSynthesizer_getVoiceName)
-	LOOP {
-		iam (SpeechSynthesizer);
-		Melder_information (my d_voiceLanguageName);
-	}
-END
+DIRECT (INFO_SpeechSynthesizer_getVoiceName) {
+	STRING_ONE (SpeechSynthesizer)
+		const char32 *result = my d_voiceLanguageName;
+	STRING_ONE_END
+}
 
-DIRECT (SpeechSynthesizer_getVoiceVariant)
-	LOOP {
-		iam (SpeechSynthesizer);
-		Melder_information (my d_voiceVariantName);
-	}
-END
+DIRECT (INFO_SpeechSynthesizer_getVoiceVariant) {
+	STRING_ONE (SpeechSynthesizer)
+		const char32 *result = my d_voiceVariantName;
+	STRING_ONE_END
+}
 
-FORM (SpeechSynthesizer_setTextInputSettings, U"SpeechSynthesizer: Set text input settings", U"SpeechSynthesizer: Set text input settings...")
-	OPTIONMENU (U"Input text format is", 1)
+FORM (MODIFY_SpeechSynthesizer_setTextInputSettings, U"SpeechSynthesizer: Set text input settings", U"SpeechSynthesizer: Set text input settings...") {
+	OPTIONMENUVAR (inputTextFormat, U"Input text format is", 1)
 		OPTION (U"Text only")
 		OPTION (U"Phoneme codes only")
 		OPTION (U"Mixed with tags")
-	OPTIONMENU (U"Input phoneme codes are", 1)
+	OPTIONMENUVAR (inputPhonemeCoding, U"Input phoneme codes are", 1)
 		OPTION (U"Kirshenbaum_espeak")
 	OK
 DO
-	int inputTextFormat = GET_INTEGER (U"Input text format is");
-	int inputPhonemeCoding = SpeechSynthesizer_PHONEMECODINGS_KIRSHENBAUM; //
-	LOOP {
-		iam (SpeechSynthesizer);
-		SpeechSynthesizer_setTextInputSettings (me, inputTextFormat, inputPhonemeCoding);
-	}
-END
-
-FORM (SpeechSynthesizer_setSpeechOutputSettings, U"SpeechSynthesizer: Set speech output settings", U"SpeechSynthesizer: Set speech output settings...")
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	REAL (U"Gap between words (s)", U"0.01")
-	INTEGER (U"Pitch adjustment (0-99)", U"50")
-	INTEGER (U"Pitch range (0-99)", U"50");
-	NATURAL (U"Words per minute (80-450)", U"175");
-	BOOLEAN (U"Estimate rate from data", true);
-	OPTIONMENU (U"Output phoneme codes are", 2)
+	int inputPhonemeCoding_always = SpeechSynthesizer_PHONEMECODINGS_KIRSHENBAUM;
+	MODIFY_EACH (SpeechSynthesizer)
+		SpeechSynthesizer_setTextInputSettings (me, inputTextFormat, inputPhonemeCoding_always);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_SpeechSynthesizer_setSpeechOutputSettings, U"SpeechSynthesizer: Set speech output settings", U"SpeechSynthesizer: Set speech output settings...") {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	REALVAR (wordGap, U"Gap between words (s)", U"0.01")
+	INTEGERVAR (pitchAdjustment, U"Pitch adjustment (0-99)", U"50")
+	INTEGERVAR (pitchRange_0_99, U"Pitch range (0-99)", U"50");
+	NATURALVAR (wordsPerMinute, U"Words per minute (80-450)", U"175");
+	BOOLEANVAR (estimateWordsPerMinute, U"Estimate rate from data", true);
+	OPTIONMENUVAR (outputPhonemeCodes, U"Output phoneme codes are", 2)
 		OPTION (U"Kirshenbaum_espeak")
 		OPTION (U"IPA")
 	OK
 DO
-	double samplingFrequency = GET_REAL (U"Sampling frequency");
-	double wordgap = GET_REAL (U"Gap between words");
-	if (wordgap < 0) wordgap = 0;
-	long pitchAdjustment = GET_INTEGER (U"Pitch adjustment");   // ppgb: waarom was dit een double?
+	if (wordGap < 0) wordGap = 0;
 	if (pitchAdjustment < 0) pitchAdjustment = 0;
 	if (pitchAdjustment > 99) pitchAdjustment = 99;
-	long pitchRange = GET_INTEGER (U"Pitch range");   // ppgb: waarom was dit een double?
-	if (pitchRange < 0) pitchRange = 0;
-	if (pitchRange > 99) pitchRange = 99;
-	long wordsPerMinute = GET_INTEGER (U"Words per minute");   // ppgb: waarom was dit een double?
-	bool estimateWordsPerMinute = GET_INTEGER (U"Estimate rate from data");
-	int outputPhonemeCodes = GET_INTEGER (U"Output phoneme codes are");
-
-	LOOP {
-		iam (SpeechSynthesizer);
-		SpeechSynthesizer_setSpeechOutputSettings (me, samplingFrequency, wordgap, pitchAdjustment, pitchRange, wordsPerMinute, estimateWordsPerMinute, outputPhonemeCodes);
-	}
-END
+	if (pitchRange_0_99 < 0) pitchRange_0_99 = 0;
+	if (pitchRange_0_99 > 99) pitchRange_0_99 = 99;
+	MODIFY_EACH (SpeechSynthesizer)
+		SpeechSynthesizer_setSpeechOutputSettings (me, samplingFrequency, wordGap, pitchAdjustment, pitchRange_0_99, wordsPerMinute, estimateWordsPerMinute, outputPhonemeCodes);
+	MODIFY_EACH_END
+}
 
 /************* SpeechSynthesizer and TextGrid ************************/
 
-FORM (SpeechSynthesizer_and_TextGrid_to_Sound, U"SpeechSynthesizer & TextGrid: To Sound", nullptr)
-	NATURAL (U"Tier number", U"1")
-	NATURAL (U"Interval number", U"1")
-	BOOLEAN (U"Create TextGrid with annotations", false);
-	OK
-DO
-	bool createAnnotations = GET_INTEGER (U"Create TextGrid with annotations");
-	SpeechSynthesizer me = FIRST (SpeechSynthesizer);
-	TextGrid thee = FIRST (TextGrid);
-	autoTextGrid annotations;
-	autoSound him = SpeechSynthesizer_and_TextGrid_to_Sound (me, thee, GET_INTEGER (U"Tier number"),
-		GET_INTEGER (U"Interval number"), ( createAnnotations ? & annotations : nullptr ));
-	praat_new (him.move(), my name);
-	if (createAnnotations) {
-		praat_new (annotations.move(), my name);
-	}
-END
-
-FORM (SpeechSynthesizer_and_Sound_and_TextGrid_align, U"SpeechSynthesizer & Sound & TextGrid: To TextGrid (align)", nullptr)
-	NATURAL (U"Tier number", U"1")
-	NATURAL (U"From interval number", U"1")
-	NATURAL (U"To interval number", U"1")
-	REAL (U"Silence threshold (dB)", U"-35.0")
-	POSITIVE (U"Minimum silent interval duration (s)", U"0.1")
-	POSITIVE (U"Minimum sounding interval duration (s)", U"0.1")
-	OK
-DO
-	double silenceThreshold = GET_REAL (U"Silence threshold");
-	double minSilenceDuration = GET_REAL (U"Minimum silent interval duration");
-	double minSoundingDuration = GET_REAL (U"Minimum sounding interval duration");
-	SpeechSynthesizer synth = FIRST (SpeechSynthesizer);
-	Sound s = FIRST (Sound);
-	TextGrid tg = FIRST (TextGrid);
-	autoTextGrid thee = SpeechSynthesizer_and_Sound_and_TextGrid_align (synth, s, tg,
-		GET_INTEGER (U"Tier number"), GET_INTEGER (U"From interval number"),
-		GET_INTEGER (U"To interval number"), silenceThreshold, minSilenceDuration, minSoundingDuration);
-	praat_new (thee.move(), s -> name, U"_aligned");
-END
-
-FORM (SpeechSynthesizer_and_Sound_and_TextGrid_align2, U"SpeechSynthesizer & Sound & TextGrid: To TextGrid (align, trim)", nullptr)
-    NATURAL (U"Tier number", U"1")
-    NATURAL (U"From interval number", U"1")
-    NATURAL (U"To interval number", U"1")
-    REAL (U"Silence threshold (dB)", U"-35.0")
-    POSITIVE (U"Minimum silent interval duration (s)", U"0.1")
-    POSITIVE (U"Minimum sounding interval duration (s)", U"0.1")
-    REAL (U"Silence trim duration (s)", U"0.08")
+FORM (NEW1_SpeechSynthesizer_and_TextGrid_to_Sound, U"SpeechSynthesizer & TextGrid: To Sound", nullptr) {
+	NATURALVAR (tierNumber, U"Tier number", U"1")
+	NATURALVAR (intervalNumber, U"Interval number", U"1")
+	BOOLEANVAR (createAnnotations, U"Create TextGrid with annotations", false);
+	OK
+DO
+	CONVERT_TWO (SpeechSynthesizer, TextGrid)
+		autoTextGrid annotations;
+		autoSound result = SpeechSynthesizer_and_TextGrid_to_Sound (me, you, tierNumber, intervalNumber, (createAnnotations ? & annotations : nullptr ));
+		if (createAnnotations) {
+			praat_new (annotations.move(), my name);
+		}
+	CONVERT_TWO_END (my name)
+}
+
+FORM (NEW1_SpeechSynthesizer_and_Sound_and_TextGrid_align, U"SpeechSynthesizer & Sound & TextGrid: To TextGrid (align)", nullptr) {
+	NATURALVAR (tierNumber, U"Tier number", U"1")
+	NATURALVAR (fromInterval, U"From interval number", U"1")
+	NATURALVAR (toInterval, U"To interval number", U"1")
+	REALVAR (silenceThreshold_dB, U"Silence threshold (dB)", U"-35.0")
+	POSITIVEVAR (minimumSilenceDuration, U"Minimum silent interval duration (s)", U"0.1")
+	POSITIVEVAR (minimumSoundingDuration, U"Minimum sounding interval duration (s)", U"0.1")
+	OK
+DO
+	CONVERT_THREE (SpeechSynthesizer, Sound, TextGrid)
+		autoTextGrid result = SpeechSynthesizer_and_Sound_and_TextGrid_align (me, you, him, tierNumber, fromInterval, toInterval, silenceThreshold_dB, minimumSilenceDuration, minimumSoundingDuration);
+	CONVERT_THREE_END (your name, U"_aligned")
+}
+
+FORM (NEW1_SpeechSynthesizer_and_Sound_and_TextGrid_align2, U"SpeechSynthesizer & Sound & TextGrid: To TextGrid (align, trim)", nullptr) {
+    NATURALVAR (tierNumber, U"Tier number", U"1")
+    NATURALVAR (fromInterval, U"From interval number", U"1")
+    NATURALVAR (toInterval, U"To interval number", U"1")
+    REALVAR (silenceThreshold_dB, U"Silence threshold (dB)", U"-35.0")
+    POSITIVEVAR (minimumSilenceDuration, U"Minimum silent interval duration (s)", U"0.1")
+    POSITIVEVAR (minimumSoundingDuration, U"Minimum sounding interval duration (s)", U"0.1")
+    REALVAR (trimDuration, U"Silence trim duration (s)", U"0.08")
     OK
 DO
-    double silenceThreshold = GET_REAL (U"Silence threshold");
-    double minSilenceDuration = GET_REAL (U"Minimum silent interval duration");
-    double minSoundingDuration = GET_REAL (U"Minimum sounding interval duration");
-    double trimDuration = GET_REAL (U"Silence trim duration");
-    if (trimDuration < 0.0) {
-        trimDuration = 0.0;
-    }
-    SpeechSynthesizer synth = FIRST (SpeechSynthesizer);
-    Sound s = FIRST (Sound);
-    TextGrid tg = FIRST (TextGrid);
-    autoTextGrid thee = SpeechSynthesizer_and_Sound_and_TextGrid_align2 (synth, s, tg,
-        GET_INTEGER (U"Tier number"), GET_INTEGER (U"From interval number"),
-        GET_INTEGER (U"To interval number"), silenceThreshold, minSilenceDuration, minSoundingDuration, trimDuration);
-    praat_new (thee.move(), s -> name, U"_aligned");
-END
+   trimDuration = trimDuration < 0.0 ? 0.0 : trimDuration;
+    CONVERT_THREE (SpeechSynthesizer, Sound, TextGrid)
+		autoTextGrid result = SpeechSynthesizer_and_Sound_and_TextGrid_align2 (me, you, him, tierNumber, fromInterval, toInterval, silenceThreshold_dB, minimumSilenceDuration, minimumSoundingDuration, trimDuration);
+    CONVERT_THREE_END (his name, U"_aligned")
+}
 
 /************* Spline *************************************************/
 
-FORM (Spline_drawKnots, U"Spline: Draw knots", nullptr)
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Spline_drawKnots, U"Spline: Draw knots", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	LOOP {
-		iam (Spline);
-		Spline_drawKnots (me, GRAPHICS, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Spline)
+		Spline_drawKnots (me, GRAPHICS, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Spline_getOrder)
-	LOOP {
-		iam (Spline);
-		Melder_information (Spline_getOrder (me));
-	}
-END
+DIRECT (INTEGER_Spline_getOrder) {
+	INTEGER_ONE (Spline)
+		long result = Spline_getOrder (me);
+	INTEGER_ONE_END (U" (order)")
+}
 
-FORM (Spline_scaleX, U"Spline: Scale x", U"Spline: Scale x...")
+FORM (NEW_Spline_scaleX, U"Spline: Scale x", U"Spline: Scale x...") {
 	LABEL (U"", U"New domain")
-	REAL (U"Xmin", U"-1.0")
-	REAL (U"Xmax", U"1.0")
+	REALVAR (xmin, U"Xmin", U"-1.0")
+	REALVAR (xmax, U"Xmax", U"1.0")
 	OK
 DO
-	double xmin = GET_REAL (U"Xmin"), xmax = GET_REAL (U"Xmax");
-	if (xmin >= xmax) {
-		Melder_throw (U"Xmin must be smaller than Xmax.");
-	}
-	LOOP {
-		iam (Spline);
-		praat_new (Spline_scaleX (me, xmin, xmax), my name, U"_scaleX");
-	}
-END
+	REQUIRE (xmin < xmax, U"Xmin must be smaller than Xmax.")
+	CONVERT_EACH (Spline)
+		autoSpline result = Spline_scaleX (me, xmin, xmax);
+	CONVERT_EACH_END (my name, U"_scaleX")
+}
 
 /************ SSCP ***************************************************/
 
-DIRECT (SSCP_help) Melder_help (U"SSCP"); END
+DIRECT (HELP_SSCP_help) {
+	HELP (U"SSCP")
+}
 
-FORM (SSCP_drawConfidenceEllipse, U"SSCP: Draw confidence ellipse", nullptr)
-	POSITIVE (U"Confidence level", U"0.95")
-	NATURAL (U"Index for X-axis", U"1")
-	NATURAL (U"Index for Y-axis", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_SSCP_drawConfidenceEllipse, U"SSCP: Draw confidence ellipse", nullptr) {
+	POSITIVEVAR (confidenceLevel, U"Confidence level", U"0.95")
+	NATURALVAR (xIndex, U"Index for X-axis", U"1")
+	NATURALVAR (yIndex, U"Index for Y-axis", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (SSCP);
-		SSCP_drawConcentrationEllipse (me, GRAPHICS, GET_REAL (U"Confidence level"), 1,
-			GET_INTEGER (U"Index for X-axis"), GET_INTEGER (U"Index for Y-axis"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (SSCP)
+		SSCP_drawConcentrationEllipse (me, GRAPHICS, confidenceLevel, 1, xIndex, yIndex, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (SSCP_drawSigmaEllipse, U"SSCP: Draw sigma ellipse", U"SSCP: Draw sigma ellipse...")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	NATURAL (U"Index for X-axis", U"1")
-	NATURAL (U"Index for Y-axis", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_SSCP_drawSigmaEllipse, U"SSCP: Draw sigma ellipse", U"SSCP: Draw sigma ellipse...") {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	NATURALVAR (xIndex, U"Index for X-axis", U"1")
+	NATURALVAR (yIndex, U"Index for Y-axis", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (SSCP);
-		SSCP_drawConcentrationEllipse (me, GRAPHICS, GET_REAL (U"Number of sigmas"), 0,
-			GET_INTEGER (U"Index for X-axis"), GET_INTEGER (U"Index for Y-axis"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (SSCP)
+		SSCP_drawConcentrationEllipse (me, GRAPHICS, numberOfSigmas, 0, xIndex, yIndex, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (SSCP_extractCentroid)
-	LOOP {
-		iam (SSCP);
-		praat_new (SSCP_extractCentroid (me), my name, U"_centroid");
-	}
-END
+DIRECT (NEW_SSCP_extractCentroid) {
+	CONVERT_EACH (SSCP)
+		autoTableOfReal result = SSCP_extractCentroid (me);
+	CONVERT_EACH_END (my name, U"_centroid")
+}
 
-FORM (SSCP_getConfidenceEllipseArea, U"SSCP: Get confidence ellipse area", U"SSCP: Get confidence ellipse area...")
-	POSITIVE (U"Confidence level", U"0.95")
-	NATURAL (U"Index for X-axis", U"1")
-	NATURAL (U"Index for Y-axis", U"2")
+FORM (REAL_SSCP_getConfidenceEllipseArea, U"SSCP: Get confidence ellipse area", U"SSCP: Get confidence ellipse area...") {
+	POSITIVEVAR (confidenceLevel, U"Confidence level", U"0.95")
+	NATURALVAR (xIndex, U"Index for X-axis", U"1")
+	NATURALVAR (yIndex, U"Index for Y-axis", U"2")
 	OK
 DO
-	double conf = GET_REAL (U"Confidence level");
-	long d1 = GET_INTEGER (U"Index for X-axis");
-	long d2 = GET_INTEGER (U"Index for Y-axis");
-	LOOP {
-		iam (SSCP);
-		Melder_information (SSCP_getConcentrationEllipseArea (me, conf, 1, d1, d2));
-	}
-END
+	NUMBER_ONE (SSCP)
+		double result = SSCP_getConcentrationEllipseArea (me, confidenceLevel, 1, xIndex, yIndex);
+	NUMBER_ONE_END (U" (confidence ellipse area)")
+}
 
-FORM (SSCP_getFractionVariation, U"SSCP: Get fraction variation", U"SSCP: Get fraction variation...")
-	NATURAL (U"From dimension", U"1")
-	NATURAL (U"To dimension", U"1")
+FORM (REAL_SSCP_getFractionVariation, U"SSCP: Get fraction variation", U"SSCP: Get fraction variation...") {
+	NATURALVAR (fromDimension, U"From dimension", U"1")
+	NATURALVAR (toDimension, U"To dimension", U"1")
 	OK
 DO
-	LOOP {
-		iam (SSCP);
-		Melder_information (SSCP_getFractionVariation (me,
-			GET_INTEGER (U"From dimension"), GET_INTEGER (U"To dimension")));
-	}
-END
+	NUMBER_ONE (SSCP)
+		double result = SSCP_getFractionVariation (me, fromDimension, toDimension);
+	NUMBER_ONE_END (U" (fraction)")
+}
 
 
-FORM (SSCP_getConcentrationEllipseArea, U"SSCP: Get sigma ellipse area", U"SSCP: Get sigma ellipse area...")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	NATURAL (U"Index for X-axis", U"1")
-	NATURAL (U"Index for Y-axis", U"2")
+FORM (REAL_SSCP_getConcentrationEllipseArea, U"SSCP: Get sigma ellipse area", U"SSCP: Get sigma ellipse area...") {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	NATURALVAR (xIndex, U"Index for X-axis", U"1")
+	NATURALVAR (yIndex, U"Index for Y-axis", U"2")
 	OK
 DO
-	double nsigmas = GET_REAL (U"Number of sigmas");
-	long d1 = GET_INTEGER (U"Index for X-axis");
-	long d2 = GET_INTEGER (U"Index for Y-axis");
-	LOOP {
-		iam (SSCP);
-		Melder_information (SSCP_getConcentrationEllipseArea (me, nsigmas, 0, d1, d2));
+	NUMBER_ONE (SSCP)
+		double result = SSCP_getConcentrationEllipseArea (me, numberOfSigmas, 0, xIndex, yIndex);
+	NUMBER_ONE_END (U" (concentation ellipse area)")
 }
-END
 
-DIRECT (SSCP_getDegreesOfFreedom)
-	LOOP {
-		iam (SSCP);
-		Melder_information (SSCP_getDegreesOfFreedom (me));
-	}
-END
+DIRECT (INTEGER_SSCP_getDegreesOfFreedom) {
+	INTEGER_ONE (SSCP)
+		long result = SSCP_getDegreesOfFreedom (me);
+	INTEGER_ONE_END (U" (degrees of freedom)")
+}
 
-DIRECT (SSCP_getNumberOfObservations)
-	LOOP {
-		iam (SSCP);
-		Melder_information ((long) floor (my numberOfObservations));   // ppgb: blijf ik raar vinden
-	}
-END
+DIRECT (INTEGER_SSCP_getNumberOfObservations) {
+	INTEGER_ONE (SSCP)
+		long result = (long) floor (my numberOfObservations);   // ppgb: blijf ik raar vinden
+	INTEGER_ONE_END (U" (number of observations)")
+}
 
-DIRECT (SSCP_getTotalVariance)
-	LOOP {
-		iam (SSCP);
-		Melder_information (SSCP_getTotalVariance (me));
-	}
-END
+DIRECT (REAL_SSCP_getTotalVariance) {
+	NUMBER_ONE (SSCP)
+		double result = SSCP_getTotalVariance (me);
+	NUMBER_ONE_END (U" (total variance)")
+}
 
-FORM (SSCP_getCentroidElement, U"SSCP: Get centroid element", U"SSCP: Get centroid element")
-	NATURAL (U"Number", U"1")
+FORM (REAL_SSCP_getCentroidElement, U"SSCP: Get centroid element", U"SSCP: Get centroid element") {
+	NATURALVAR (number, U"Number", U"1")
 	OK
 DO
-	long number = GET_INTEGER (U"Number");
-	LOOP {
-		iam (SSCP);
-		if (number < 1 || number > my numberOfColumns) {
-			Melder_throw (U"\"Number\" must be smaller than ", my numberOfColumns + 1, U".");
+	NUMBER_ONE (SSCP)
+		double result = NUMundefined;
+		if (number > 0 && number <= my numberOfColumns) {
+			result = my centroid [number];
 		}
-		Melder_information (my centroid[number]);
-	}
-END
+	NUMBER_ONE_END (U" (centroid [", number, U"])")
+}
 
-DIRECT (SSCP_getLnDeterminant)
-	LOOP {
-		iam (SSCP);
-		Melder_information (SSCP_getLnDeterminant (me));
-	}
-END
+DIRECT (REAL_SSCP_getLnDeterminant) {
+	NUMBER_ONE (SSCP)
+		double result = SSCP_getLnDeterminant (me);
+	NUMBER_ONE_END (U" (ln (determinant))")
+}
 
-FORM (SSCP_testDiagonality_bartlett, U"SSCP: Get diagonality (bartlett)", U"SSCP: Get diagonality (bartlett)...")
-	NATURAL (U"Number of contraints", U"1")
+FORM (REAL_SSCP_testDiagonality_bartlett, U"SSCP: Get diagonality (bartlett)", U"SSCP: Get diagonality (bartlett)...") {
+	NATURALVAR (numberOfConstraints, U"Number of constraints", U"1")
 	OK
 DO
-	double chisq, p, df;
-	long nc = GET_INTEGER (U"Number of contraints");
-	LOOP {
-		iam (SSCP);
-		SSCP_testDiagonality_bartlett (me, nc, & chisq, & p, & df);
-		Melder_information (p, U" (= probability for chisq = ", chisq, U" and ndf = ", df, U")");
-	}
-END
+	NUMBER_ONE (SSCP)
+		double chisq, result, df;
+		SSCP_testDiagonality_bartlett (me, numberOfConstraints, & chisq, & result, & df);
+	NUMBER_ONE_END (U" (= probability for chisq = ", chisq, U" and ndf = ", df, U")")
+}
 
-DIRECT (SSCP_to_Correlation)
-	LOOP {
-		iam (SSCP);
-		praat_new (SSCP_to_Correlation (me), U"");
-	}
-END
+DIRECT (NEW_SSCP_to_Correlation) {
+	CONVERT_EACH (SSCP)
+		autoCorrelation result = SSCP_to_Correlation (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (SSCP_to_Covariance, U"SSCP: To Covariance", U"SSCP: To Covariance...")
-	NATURAL (U"Number of constraints", U"1")
+FORM (NEW_SSCP_to_Covariance, U"SSCP: To Covariance", U"SSCP: To Covariance...") {
+	NATURALVAR (numberOfConstraints, U"Number of constraints", U"1")
 	OK
 DO
-	long noc = GET_INTEGER (U"Number of constraints");
-	LOOP {
-		iam (SSCP);
-		praat_new (SSCP_to_Covariance (me, noc), U"");
-	}
-END
+	CONVERT_EACH (SSCP)
+		autoCovariance result = SSCP_to_Covariance (me, numberOfConstraints);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (SSCP_to_PCA)
-	LOOP {
-		iam (SSCP);
-		praat_new (SSCP_to_PCA (me), U"");
-	}
-END
+DIRECT (NEW_SSCP_to_PCA) {
+	CONVERT_EACH (SSCP)
+		autoPCA result = SSCP_to_PCA (me);
+	CONVERT_EACH_END (my name)
+}
 
 /******************* Strings ****************************/
-DIRECT (Strings_createFromEspeakVoices)
+
+DIRECT (NEW1_Strings_createFromEspeakVoices) {
 	//praat_new (nullptr, U"voices"); // TODO ??
-END
+END }
 
-FORM (Strings_createAsCharacters, U"Strings: Create as characters", nullptr)
-	SENTENCE (U"Text", U"intention")
+FORM (NEW1_Strings_createAsCharacters, U"Strings: Create as characters", nullptr) {
+	SENTENCEVAR (text, U"Text", U"intention")
 	OK
 DO
-	autoStrings thee = Strings_createAsCharacters (GET_STRING (U"Text"));
-	praat_new (thee.move(), U"");
-END
+	CREATE_ONE
+		autoStrings result = Strings_createAsCharacters (text);
+	CREATE_ONE_END (U"chars")
+}
 
-FORM (Strings_createAsTokens, U"Strings: Create as tokens", nullptr)
-	SENTENCE (U"Text", U"There are seven tokens in this text")
+FORM (NEW1_Strings_createAsTokens, U"Strings: Create as tokens", nullptr) {
+	SENTENCEVAR (text, U"Text", U"There are seven tokens in this text")
 	OK
 DO
-	autoStrings thee = Strings_createAsTokens (GET_STRING (U"Text"));
-	praat_new (thee.move(), U"");
-END
+	CREATE_ONE
+		autoStrings result = Strings_createAsTokens (text);
+	CREATE_ONE_END (U"tokens")
+}
 
-DIRECT (Strings_append)
-	OrderedOf<structStrings> list;
-	LOOP {
-		iam (Strings);
-		list. addItem_ref (me);
-	}
-	autoStrings thee = Strings_append (& list);
-	praat_new (thee.move(), U"appended");
-END
+DIRECT (NEW1_Strings_append) {
+	CONVERT_LIST (Strings)
+		autoStrings result = Strings_append (& list);
+	CONVERT_LIST_END (U"appended")
+}
 
-DIRECT (Strings_to_Categories)
-	LOOP {
-		iam (Strings);
-		autoCategories thee = Strings_to_Categories (me);
-		praat_new (thee.move(), U"");
-	}
-END
+DIRECT (NEW_Strings_to_Categories) {
+	CONVERT_EACH (Strings)
+		autoCategories result = Strings_to_Categories (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Strings_change, U"Strings: Change", U"Strings: Change")
-	SENTENCE (U"Search", U"a")
-	SENTENCE (U"Replace", U"a")
-	INTEGER (U"Replace limit", U"0 (= unlimited)")
-	RADIO (U"Search and replace are:", 1)
+FORM (NEW_Strings_change, U"Strings: Change", U"Strings: Change") {
+	SENTENCEVAR (search_string, U"Search", U"a")
+	SENTENCEVAR (replace_string, U"Replace", U"a")
+	INTEGERVAR (replaceLimit, U"Replace limit", U"0 (= unlimited)")
+	RADIOVAR (stringType, U"Search and replace are:", 1)
 	RADIOBUTTON (U"Literals")
 	RADIOBUTTON (U"Regular Expressions")
 	OK
 DO
-	long nmatches, nstringmatches;
-	LOOP {
-		iam (Strings);
-		autoStrings thee = Strings_change (me, GET_STRING (U"Search"), GET_STRING (U"Replace"),
-		GET_INTEGER (U"Replace limit"), &nmatches, &nstringmatches, GET_INTEGER (U"Search and replace are") - 1);
-		praat_new (thee.move());
-	}
-END
+	CONVERT_EACH (Strings)
+		long nmatches, nstringmatches;
+		autoStrings result = Strings_change (me, search_string, replace_string, replaceLimit, &nmatches, &nstringmatches, stringType - 1);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Strings_extractPart, U"Strings: Extract part", nullptr)
-	NATURAL (U"From index", U"1")
-	NATURAL (U"To index", U"1")
+FORM (NEW_Strings_extractPart, U"Strings: Extract part", nullptr) {
+	NATURALVAR (fromIndex, U"From index", U"1")
+	NATURALVAR (toIndex, U"To index", U"1")
 	OK
 DO
-	LOOP {
-		iam (Strings);
-		autoStrings thee = Strings_extractPart (me, GET_INTEGER (U"From index"), GET_INTEGER (U"To index"));
-		praat_new (thee.move(), my name, U"_part");
-	}
-END
+	CONVERT_EACH (Strings)
+		autoStrings result = Strings_extractPart (me, fromIndex, toIndex);
+	CONVERT_EACH_END (my name, U"_part");
+}
 
-DIRECT (Strings_to_EditDistanceTable)
-	Strings s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam(Strings);
-		(s1 ? s2 : s1) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoEditDistanceTable table = EditDistanceTable_create (s1, s2);
-	praat_new (table.move(), s1 -> name, U"_", s2 -> name);
-END
+DIRECT (NEW_Strings_to_EditDistanceTable) {
+	CONVERT_COUPLE (Strings)
+		autoEditDistanceTable result = EditDistanceTable_create (me, you);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (Strings_to_Permutation, U"Strings: To Permutation", U"Strings: To Permutation...")
-	BOOLEAN (U"Sort", true)
+FORM (NEW_Strings_to_Permutation, U"Strings: To Permutation", U"Strings: To Permutation...") {
+	BOOLEANVAR (sort, U"Sort", true)
 	OK
 DO
-	LOOP {
-		iam (Strings);
-		autoPermutation thee = Strings_to_Permutation (me, GET_INTEGER (U"Sort"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (Strings)
+		autoPermutation result = Strings_to_Permutation (me, sort);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Strings_and_Permutation_permuteStrings)
-	Strings me = FIRST (Strings);
-	Permutation p = FIRST (Permutation);
-	autoStrings thee = Strings_and_Permutation_permuteStrings (me, p);
-	praat_new (thee.move(), my name, U"_", p->name);
-END
+DIRECT (NEW1_Strings_and_Permutation_permuteStrings) {
+	CONVERT_TWO (Strings, Permutation)
+		autoStrings result = Strings_and_Permutation_permuteStrings (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (SVD_to_TableOfReal, U"SVD: To TableOfReal", U"SVD: To TableOfReal...")
-	NATURAL (U"First component", U"1")
-	INTEGER (U"Last component", U"0 (= all)")
+FORM (NEW_SVD_to_TableOfReal, U"SVD: To TableOfReal", U"SVD: To TableOfReal...") {
+	NATURALVAR (fromComponent, U"First component", U"1")
+	INTEGERVAR (toComponent, U"Last component", U"0 (= all)")
 	OK
 DO
-	LOOP {
-		iam (SVD);
-		autoTableOfReal thee = SVD_to_TableOfReal (me, GET_INTEGER (U"First component"), GET_INTEGER (U"Last component"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (SVD_extractLeftSingularVectors)
-	LOOP {
-		iam (SVD);
-		autoTableOfReal thee = SVD_extractLeftSingularVectors (me);
-		praat_new (thee.move(), my name, U"_lsv");
-	}
-END
+	CONVERT_EACH (SVD)
+		autoTableOfReal result = SVD_to_TableOfReal (me, fromComponent, toComponent);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (SVD_extractRightSingularVectors)
+DIRECT (NEW_SVD_extractLeftSingularVectors) {
 	LOOP {
 		iam (SVD);
-		autoTableOfReal thee = SVD_extractRightSingularVectors (me);
-		praat_new (thee.move(), my name, U"_rsv");
-	}
-END
+		autoTableOfReal result = SVD_extractLeftSingularVectors (me);
+	CONVERT_EACH_END (my name, U"_lsv")
+}
 
-DIRECT (SVD_extractSingularValues)
-	LOOP {
-		iam (SVD);
-		autoTableOfReal thee = SVD_extractSingularValues (me);
-		praat_new (thee.move(), my name, U"_sv");
-	}
-END
+DIRECT (NEW_SVD_extractRightSingularVectors) {
+	CONVERT_EACH (SVD)
+		autoTableOfReal result = SVD_extractRightSingularVectors (me);
+	CONVERT_EACH_END (my name, U"_rsv")
+}
+
+DIRECT (NEW_SVD_extractSingularValues) {
+	CONVERT_EACH (SVD)
+		autoTableOfReal result = SVD_extractSingularValues (me);
+	CONVERT_EACH_END (my name, U"_sv");
+}
 
 /******************* Table ****************************/
 
-DIRECT (Table_createFromPetersonBarneyData)
-	praat_new (Table_createFromPetersonBarneyData (), U"pb");
-END
-
-DIRECT (Table_createFromPolsVanNieropData)
-	praat_new (Table_createFromPolsVanNieropData (), U"pvn");
-END
-
-DIRECT (Table_createFromWeeninkData)
-	praat_new (Table_createFromWeeninkData (), U"m10w10c10");
-END
-
-FORM (Table_scatterPlotWhere, U"Table: Scatter plot where", nullptr)
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	WORD (U"Column with marks", U"")
-	NATURAL (U"Font size", U"12")
-	BOOLEAN (U"Garnish", true)
+DIRECT (NEW1_Table_create_petersonBarney1952) {
+	CREATE_ONE
+		autoTable result = Table_create_petersonBarney1952 ();
+	CREATE_ONE_END (U"pb")
+}
+
+DIRECT (NEW1_Table_create_polsVanNierop1973) {
+	CREATE_ONE
+		autoTable result = Table_create_polsVanNierop1973 ();
+	CREATE_ONE_END (U"pvn")
+}
+
+DIRECT (NEW1_Table_create_weenink1983) {
+	CREATE_ONE
+		autoTable result = Table_create_weenink1983 ();
+	CREATE_ONE_END (U"m10w10c10")
+}
+
+FORM (GRAPHICS_Table_scatterPlotWhere, U"Table: Scatter plot where", nullptr) {
+	WORDVAR (xColumn_string, U"Horizontal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0 (= auto)")
+	WORDVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	WORDVAR (markColumn_string, U"Column with marks", U"")
+	NATURALVAR (fontSize, U"Font size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Use only data from rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long markColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column with marks"));
-		autoTable thee = Table_extractRowsWhere (me,  GET_STRING (U"Formula"), interpreter);
-		Table_scatterPlot (thee.get(), GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			markColumn, GET_INTEGER (U"Font size"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Table_scatterPlotMarkWhere, U"Scatter plot where (marks)", nullptr)
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", true)
-	SENTENCE (U"Mark string (+xo.)", U"+")
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long markColumn = Table_getColumnIndexFromColumnLabel (me, markColumn_string);
+		autoTable part = Table_extractRowsWhere (me, formula, interpreter);
+		Table_scatterPlot (part.get(), GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, markColumn, fontSize, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_scatterPlotMarkWhere, U"Scatter plot where (marks)", nullptr) {
+	WORDVAR (xColumn_string, U"Horizontal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0 (= auto)")
+	WORDVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	POSITIVEVAR (markSize_mm, U"Mark size (mm)", U"1.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	SENTENCEVAR (mark_string, U"Mark string (+xo.)", U"+")
 	LABEL (U"", U"Use only data from rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		autoTable thee = Table_extractRowsWhere (me,  GET_STRING (U"Formula"), interpreter);
-		Table_scatterPlot_mark (thee.get(), GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Mark size"), GET_STRING (U"Mark string"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		autoTable part = Table_extractRowsWhere (me, formula, interpreter);
+		Table_scatterPlot_mark (part.get(), GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, markSize_mm, mark_string, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_barPlotWhere, U"Table: Bar plot where", U"Table: Bar plot where...")
-	SENTENCE (U"Vertical column(s)", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	SENTENCE (U"Column with labels", U"")
+FORM (GRAPHICS_Table_barPlotWhere, U"Table: Bar plot where", U"Table: Bar plot where...") {
+	SENTENCEVAR (yColumns_string, U"Vertical column(s)", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	SENTENCEVAR (markColumn_string, U"Column with labels", U"")
 	LABEL (U"", U"Distances are in units of 'bar width'")
-	REAL (U"Distance of first bar from border", U"1.0")
-	REAL (U"Distance between bar groups", U"1.0")
-	REAL (U"Distance between bars within group", U"0.0")
-	SENTENCE (U"Colours", U"Grey")
-	REAL (U"Label text angle (degrees)", U"0.0");
-	BOOLEAN (U"Garnish", true)
+	REALVAR (distanceFromBorder, U"Distance of first bar from border", U"1.0")
+	REALVAR (distanceBetweenGroups, U"Distance between bar groups", U"1.0")
+	REALVAR (distanceWithinGroup, U"Distance between bars within group", U"0.0")
+	SENTENCEVAR (colours, U"Colours", U"Grey")
+	REALVAR (angle_degrees, U"Label text angle (degrees)", U"0.0");
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Use only data from rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"row >= 1 and row <= 8")
+	TEXTVAR (formula, U"Formula", U"row >= 1 and row <= 8")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		Table_barPlotWhere (me, GRAPHICS, GET_STRING (U"Vertical column"), GET_REAL (U"left Vertical range"), 
-			GET_REAL (U"right Vertical range"), GET_STRING (U"Column with labels"),
-			GET_REAL (U"Distance of first bar from border"), GET_REAL (U"Distance between bars within group"), GET_REAL (U"Distance between bar groups"),
-			GET_STRING (U"Colours"),GET_REAL (U"Label text angle"), GET_INTEGER (U"Garnish"), GET_STRING (U"Formula"), interpreter);
-	}
-END
-
-FORM (Table_LineGraphWhere, U"Table: Line graph where", U"Table: Line graph where...")
-	SENTENCE (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	SENTENCE (U"Horizonal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Text", U"+")
-	REAL (U"Label text angle (degrees)", U"0.0");
-	BOOLEAN (U"Garnish", true)
+	GRAPHICS_EACH (Table)
+		Table_barPlotWhere (me, GRAPHICS, yColumns_string, ymin, ymax, markColumn_string, distanceFromBorder, distanceWithinGroup, distanceBetweenGroups, colours, angle_degrees, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_LineGraphWhere, U"Table: Line graph where", U"Table: Line graph where...") {
+	SENTENCEVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	SENTENCEVAR (xColumn_string, U"Horizonal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0 (= auto)")
+	WORDVAR (text, U"Text", U"+")
+	REALVAR (angle_degrees, U"Label text angle (degrees)", U"0.0");
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Use only data from rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; (= everything)")
+	TEXTVAR (formula, U"Formula", U"1; (= everything)")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long xcolumn = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Horizonal column"));
-		Table_lineGraphWhere (me, GRAPHICS, xcolumn, GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			ycolumn, GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), 
-			GET_STRING (U"Text"), GET_REAL (U"Label text angle"),
-		  	GET_INTEGER (U"Garnish"), GET_STRING (U"Formula"), interpreter);
-	}
-END
+	GRAPHICS_EACH (Table)
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long xcolumn = Table_findColumnIndexFromColumnLabel (me, xColumn_string);
+		Table_lineGraphWhere (me, GRAPHICS, xcolumn, xmin, xmax,ycolumn, ymin, ymax, text, angle_degrees, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_boxPlots, U"Table: Box plots", nullptr)
-	WORD (U"Data columns", U"")
-	WORD (U"Factor column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true);
+FORM (GRAPHICS_Table_boxPlots, U"Table: Box plots", nullptr) {
+	WORDVAR (dataColumns_string, U"Data columns", U"F1 F2")
+	WORDVAR (factorColumn_string, U"Factor column", U"Sex")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
 DO
-	autoPraatPicture picture;
-	double ymin = GET_REAL (U"left Vertical range");
-	double ymax = GET_REAL (U"right Vertical range");
-	int garnish = GET_INTEGER (U"Garnish");
-	LOOP {
-		iam (Table);
-		long factorColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Factor column"));
-		Table_boxPlotsWhere (me, GRAPHICS, GET_STRING (U"Data columns"), factorColumn, ymin, ymax, garnish, U"1", interpreter);
-	}
-END
-
-FORM (Table_boxPlotsWhere, U"Table: Box plots where", U"Table: Box plots where...")
-	SENTENCE (U"Data columns", U"")
-	WORD (U"Factor column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", true);
+	GRAPHICS_EACH (Table)
+		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factorColumn_string);
+		Table_boxPlotsWhere (me, GRAPHICS, dataColumns_string, factorColumn, ymin, ymax, garnish, U"1", interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_boxPlotsWhere, U"Table: Box plots where", U"Table: Box plots where...") {
+	SENTENCEVAR (dataColumns_string, U"Data columns", U"F1 F2")
+	WORDVAR (factorColumn_string, U"Factor column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	double ymin = GET_REAL (U"left Vertical range");
-	double ymax = GET_REAL (U"right Vertical range");
-	int garnish = GET_INTEGER (U"Garnish");
-	char32 *dataColumns = GET_STRING (U"Data columns");
-	LOOP {
-		iam (Table);
-		long factorColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Factor column"));
-		Table_boxPlotsWhere (me, GRAPHICS, dataColumns, factorColumn, ymin, ymax, garnish, GET_STRING (U"Formula"), interpreter);
-	}
-END
-
-FORM (Table_drawEllipseWhere, U"Draw ellipse (standard deviation)", nullptr)
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	POSITIVE (U"Number of sigmas", U"2.0")
-	BOOLEAN (U"Garnish", true)
+	GRAPHICS_EACH (Table)
+		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factorColumn_string);
+		Table_boxPlotsWhere (me, GRAPHICS, dataColumns_string, factorColumn, ymin, ymax, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_drawEllipseWhere, U"Draw ellipse (standard deviation)", nullptr) {
+	WORDVAR (xColumn_string, U"Horizontal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0 (= auto)")
+	WORDVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"2.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		autoTable thee = Table_extractRowsWhere (me, GET_STRING (U"Formula"), interpreter);
-		Table_drawEllipse_e (thee.get(), GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Table_drawEllipses, U"Table: Draw ellipses", nullptr)
-	WORD (U"Horizontal column", U"F2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"F1")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	WORD (U"Factor column", U"Vowel")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	INTEGER (U"Font size", U"12 (0 = no label)")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long factorcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Factor column"));
-		Table_drawEllipsesWhere (me, GRAPHICS, xcolumn, ycolumn, factorcolumn, GET_REAL (U"left Horizontal range"), 
-			 GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			 GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Font size"), GET_INTEGER (U"Garnish"), U"1", interpreter);
-	}
-END
-
-FORM (Table_drawEllipsesWhere, U"Table: Draw ellipses where", nullptr)
-	WORD (U"Horizontal column", U"F2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"F1")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	WORD (U"Factor column", U"Vowel")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	INTEGER (U"Font size", U"12 (0 = no label)")
-	BOOLEAN (U"Garnish", true)
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		autoTable thee = Table_extractRowsWhere (me, formula, interpreter);
+		Table_drawEllipse_e (thee.get(), GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, numberOfSigmas, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_drawEllipses, U"Table: Draw ellipses", nullptr) {
+	WORDVAR (xColumn_string, U"Horizontal column", U"F2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0 (= auto)")
+	WORDVAR (yColumn_string, U"Vertical column", U"F1")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	WORDVAR (factorColumn_string, U"Factor column", U"Vowel")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	INTEGERVAR (fontSize, U"Font size", U"12 (0 = no label)")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long factorcolumn = Table_getColumnIndexFromColumnLabel (me, factorColumn_string);
+		Table_drawEllipsesWhere (me, GRAPHICS, xcolumn, ycolumn, factorcolumn, xmin, xmax, ymin, ymax, numberOfSigmas, fontSize, garnish, U"1", interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_drawEllipsesWhere, U"Table: Draw ellipses where", nullptr) {
+	WORDVAR (xColumn_string, U"Horizontal column", U"F2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0 (= auto)")
+	WORDVAR (yColumn_string, U"Vertical column", U"F1")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0 (= auto)")
+	WORDVAR (factorColumn_string, U"Factor column", U"Vowel")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	INTEGERVAR (fontSize, U"Font size", U"12 (0 = no label)")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long factorcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Factor column"));
-		Table_drawEllipsesWhere (me, GRAPHICS, xcolumn, ycolumn, factorcolumn, GET_REAL (U"left Horizontal range"), 
-			 GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			 GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Font size"), GET_INTEGER (U"Garnish"), GET_STRING (U"Formula"), interpreter);
-	}
-END
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long factorcolumn = Table_getColumnIndexFromColumnLabel (me, factorColumn_string);
+		Table_drawEllipsesWhere (me, GRAPHICS, xcolumn, ycolumn, factorcolumn, xmin,  xmax, ymin, ymax,  numberOfSigmas, fontSize, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (Table_normalProbabilityPlot, U"Table: Normal probability plot", U"Table: Normal probability plot...")
-	WORD (U"Column", U"")
-	NATURAL (U"Number of quantiles", U"100")
-	REAL (U"Number of sigmas", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", true);
+FORM (GRAPHICS_Table_normalProbabilityPlot, U"Table: Normal probability plot", U"Table: Normal probability plot...") {
+	WORDVAR (column_string, U"Column", U"F1")
+	NATURALVAR (numberOfQuantiles, U"Number of quantiles", U"100")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column"));
-		Table_normalProbabilityPlot (me, GRAPHICS, column,
-			GET_INTEGER (U"Number of quantiles"), GET_REAL (U"Number of sigmas"),
-			GET_INTEGER (U"Label size"), GET_STRING (U"Label"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Table_normalProbabilityPlotWhere, U"Table: Normal probability plot where", U"Table: Normal probability plot...")
-	WORD (U"Column", U"")
-	NATURAL (U"Number of quantiles", U"100")
-	REAL (U"Number of sigmas", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", true);
+	GRAPHICS_EACH (Table)
+		long column = Table_getColumnIndexFromColumnLabel (me, column_string);
+		Table_normalProbabilityPlot (me, GRAPHICS, column, numberOfQuantiles, numberOfSigmas, labelSize, label, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_normalProbabilityPlotWhere, U"Table: Normal probability plot where", U"Table: Normal probability plot...") {
+	WORDVAR (column_string, U"Column", U"F0")
+	NATURALVAR (numberOfQuantiles, U"Number of quantiles", U"100")
+	REALVAR (numberOfSigmas, U"Number of sigmas", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column"));
-		autoTable thee = Table_extractRowsWhere (me, GET_STRING (U"Formula"), interpreter);
-		Table_normalProbabilityPlot (thee.get(), GRAPHICS, column,
-			GET_INTEGER (U"Number of quantiles"), GET_REAL (U"Number of sigmas"),
-			GET_INTEGER (U"Label size"), GET_STRING (U"Label"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Table_quantileQuantilePlot, U"Table: Quantile-quantile plot", U"Table: Quantile-quantile plot...")
-	WORD (U"Horizontal axis column", U"")
-	WORD (U"Vertical axis column", U"")
-	NATURAL (U"Number of quantiles", U"100")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", true);
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal axis column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical axis column"));
-		Table_quantileQuantilePlot (me, GRAPHICS, xcolumn, ycolumn, GET_INTEGER (U"Number of quantiles"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"), GET_STRING (U"Label"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (Table_quantileQuantilePlot_betweenLevels, U"Table: Quantile-quantile plot (between levels)", U"Table: Quantile-quantile plot...")
-	WORD (U"Data column", U"")
-	WORD (U"Factor column", U"")
-	WORD (U"Horizontal factor level", U"")
-	WORD (U"Vertical factor level", U"")
-	NATURAL (U"Number of quantiles", U"100")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", 1);
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Data column"));
-		long factorColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Factor column"));
-		char32 *xLevel = GET_STRING (U"Horizontal factor level");
-		char32 *yLevel = GET_STRING (U"Vertical factor level");
-		Table_quantileQuantilePlot_betweenLevels (me, GRAPHICS, dataColumn, factorColumn, xLevel, yLevel,
-			GET_INTEGER (U"Number of quantiles"), GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"), GET_INTEGER (U"Label size"), GET_STRING (U"Label"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Table)
+		long column = Table_getColumnIndexFromColumnLabel (me, column_string);
+		autoTable thee = Table_extractRowsWhere (me, formula, interpreter);
+		Table_normalProbabilityPlot (thee.get(), GRAPHICS, column, numberOfQuantiles, numberOfSigmas, labelSize, label, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_quantileQuantilePlot, U"Table: Quantile-quantile plot", U"Table: Quantile-quantile plot...") {
+	WORDVAR (xColumn_string, U"Horizontal axis column", U"")
+	WORDVAR (yColumn_string, U"Vertical axis column", U"")
+	NATURALVAR (numberOfQuantiles, U"Number of quantiles", U"100")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		Table_quantileQuantilePlot (me, GRAPHICS, xcolumn, ycolumn, numberOfQuantiles, xmin, xmax, ymin, ymax, labelSize, label, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_quantileQuantilePlot_betweenLevels, U"Table: Quantile-quantile plot (between levels)", U"Table: Quantile-quantile plot...") {
+	WORDVAR (dataColumn_string, U"Data column", U"F0")
+	WORDVAR (factorColumn_string, U"Factor column", U"Sex")
+	WORDVAR (xLevel_string, U"Horizontal factor level", U"")
+	WORDVAR (yLevelString, U"Vertical factor level", U"")
+	NATURALVAR (numberOfQuantiles, U"Number of quantiles", U"100")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
+		long factorColumn = Table_getColumnIndexFromColumnLabel (me, factorColumn_string);
+		Table_quantileQuantilePlot_betweenLevels (me, GRAPHICS, dataColumn, factorColumn, xLevel_string, yLevelString, numberOfQuantiles, xmin, xmax, ymin, ymax, labelSize, label, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_lagPlot, U"Table: lag plot",0)
-	WORD (U"Data column", U"errors")
-	NATURAL (U"Lag", U"1")
-	REAL (U"left Horizontal and vertical range", U"0.0")
-	REAL (U"right Horizontal and vertical range", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", 1);
+FORM (GRAPHICS_Table_lagPlot, U"Table: lag plot", nullptr) {
+	WORDVAR (dataColumn_string, U"Data column", U"errors")
+	NATURALVAR (lag, U"Lag", U"1")
+	REALVAR (fromXY, U"left Horizontal and vertical range", U"0.0")
+	REALVAR (toXY, U"right Horizontal and vertical range", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Data column"));
-		Table_lagPlotWhere (me, GRAPHICS, dataColumn, GET_INTEGER (U"Lag"), GET_REAL (U"left Horizontal and vertical range"),
-			GET_REAL (U"right Horizontal and vertical range"), GET_STRING (U"Label"), GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"), U"1", interpreter);
-	}
-END
+	GRAPHICS_EACH (Table)
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
+		Table_lagPlotWhere (me, GRAPHICS, dataColumn, lag, fromXY, toXY, label, labelSize, garnish, U"1", interpreter);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (Table_lagPlotWhere, U"Table: lag plot where",0)
-	WORD (U"Data column", U"errors")
-	NATURAL (U"Lag", U"1")
-	REAL (U"left Horizontal and vertical range", U"0.0")
-	REAL (U"right Horizontal and vertical range", U"0.0")
-	NATURAL (U"Label size", U"12")
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", 1);
+FORM (GRAPHICS_Table_lagPlotWhere, U"Table: lag plot where", nullptr) {
+	WORDVAR (dataColumn_string, U"Data column", U"errors")
+	NATURALVAR (lag, U"Lag", U"1")
+	REALVAR (fromXY, U"left Horizontal and vertical range", U"0.0")
+	REALVAR (toXY, U"right Horizontal and vertical range", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Data column"));
-		Table_lagPlotWhere (me, GRAPHICS, dataColumn, GET_INTEGER (U"Lag"), GET_REAL (U"left Horizontal and vertical range"),
-			GET_REAL (U"right Horizontal and vertical range"), GET_STRING (U"Label"), GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"), GET_STRING (U"Formula"), interpreter);
-	}
-END
+	GRAPHICS_EACH (Table)
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
+		Table_lagPlotWhere (me, GRAPHICS, dataColumn, lag, fromXY, toXY, label, labelSize, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_distributionPlot, U"Table: Distribution plot", 0)
-	WORD (U"Data column", U"data")
-	REAL (U"Minimum value", U"0.0")
-	REAL (U"Maximum value", U"0.0")
+FORM (GRAPHICS_Table_distributionPlot, U"Table: Distribution plot", nullptr) {
+	WORDVAR (dataColumn_string, U"Data column", U"data")
+	REALVAR (minimumValue, U"Minimum value", U"0.0")
+	REALVAR (maximumValue, U"Maximum value", U"0.0")
 	LABEL (U"", U"Display of the distribution")
-	NATURAL (U"Number of bins", U"10")
-	REAL (U"Minimum frequency", U"0.0")
-	REAL (U"Maximum frequency", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+	NATURALVAR (numberOfBins, U"Number of bins", U"10")
+	REALVAR (minimumFrequency, U"Minimum frequency", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Data column"));
-		Table_distributionPlotWhere (me, GRAPHICS, dataColumn, GET_REAL (U"Minimum value"), GET_REAL (U"Maximum value"),
-			GET_INTEGER (U"Number of bins"), GET_REAL (U"Minimum frequency"), GET_REAL (U"Maximum frequency"), 
-			GET_INTEGER (U"Garnish"), U"1", interpreter);
-	}
-END
+	GRAPHICS_EACH (Table)
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
+		Table_distributionPlotWhere (me, GRAPHICS, dataColumn, minimumValue, maximumValue, numberOfBins, minimumFrequency, maximumFrequency, garnish, U"1", interpreter);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_distributionPlotWhere, U"Table: Distribution plot where", 0)
-	WORD (U"Data column", U"data")
-	REAL (U"Minimum value", U"0.0")
-	REAL (U"Maximum value", U"0.0")
+FORM (GRAPHICS_Table_distributionPlotWhere, U"Table: Distribution plot where", nullptr) {
+	WORDVAR (dataColumn_string, U"Data column", U"data")
+	REALVAR (minimumValue, U"Minimum value", U"0.0")
+	REALVAR (maximumValue, U"Maximum value", U"0.0")
 	LABEL (U"", U"Display of the distribution")
-	NATURAL (U"Number of bins", U"10")
-	REAL (U"Minimum frequency", U"0.0")
-	REAL (U"Maximum frequency", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+	NATURALVAR (numberOfBins, U"Number of bins", U"10")
+	REALVAR (minimumFrequency, U"Minimum frequency", U"0.0")
+	REALVAR (maximumFrequency, U"Maximum frequency", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long dataColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Data column"));
-		Table_distributionPlotWhere (me, GRAPHICS, dataColumn, GET_REAL (U"Minimum value"), GET_REAL (U"Maximum value"),
-			GET_INTEGER (U"Number of bins"), GET_REAL (U"Minimum frequency"), GET_REAL (U"Maximum frequency"), GET_INTEGER (U"Garnish"),
-			GET_STRING (U"Formula"), interpreter);
-	}
-END
-
-FORM (Table_horizontalErrorBarsPlot, U"Table: Horizontal error bars plot", U"Table: Horizontal error bars plot...")
-	WORD (U"Horizontal column", U"x")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	WORD (U"Vertical column", U"y")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	WORD (U"Lower error value column", U"")
-	WORD (U"Upper error value column", U"")
-	REAL (U"Bar size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", 1);
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long xl = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Lower error value column"));
-		long xu = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Upper error value column"));
-		
-		Table_horizontalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			xl, xu, GET_REAL (U"Bar size"), GET_INTEGER (U"Garnish"), U"1", interpreter);
-	}
-END
-
-FORM (Table_horizontalErrorBarsPlotWhere, U"Table: Horizontal error bars plot where", U"Table: Horizontal error bars plot where...")
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	WORD (U"Lower error value column", U"")
-	WORD (U"Upper error value column", U"")
-	REAL (U"Bar size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", 1);
+	GRAPHICS_EACH (Table)
+		long dataColumn = Table_getColumnIndexFromColumnLabel (me, dataColumn_string);
+		Table_distributionPlotWhere (me, GRAPHICS, dataColumn, minimumValue, maximumValue, numberOfBins, minimumFrequency, maximumFrequency, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_horizontalErrorBarsPlot, U"Table: Horizontal error bars plot", U"Table: Horizontal error bars plot...") {
+	WORDVAR (xColumn_string, U"Horizontal column", U"x")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	WORDVAR (yColumn_string, U"Vertical column", U"y")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	WORDVAR (lowerErrorColumn_string, U"Lower error value column", U"error1")
+	WORDVAR (upperErrorColumn_string, U"Upper error value column", U"error2")
+	REALVAR (barSize_mm, U"Bar size (mm)", U"1.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long xl = Table_findColumnIndexFromColumnLabel (me, lowerErrorColumn_string);
+		long xu = Table_findColumnIndexFromColumnLabel (me, upperErrorColumn_string);
+		Table_horizontalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, xl, xu, barSize_mm, garnish, U"1", interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_horizontalErrorBarsPlotWhere, U"Table: Horizontal error bars plot where", U"Table: Horizontal error bars plot where...") {
+	WORDVAR (xColumn_string, U"Horizontal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	WORDVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	WORDVAR (lowerErrorColumn_string, U"Lower error value column", U"error1")
+	WORDVAR (upperErrorColumn_string, U"Upper error value column", U"error2")
+	REALVAR (barSize_mm, U"Bar size (mm)", U"1.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long xl = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Lower error value column"));
-		long xu = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Upper error value column"));
-		
-		Table_horizontalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			xl, xu, GET_REAL (U"Bar size"), GET_INTEGER (U"Garnish"), GET_STRING (U"Formula"), interpreter);
-	}
-END
-
-FORM (Table_verticalErrorBarsPlot, U"Table: Vertical error bars plot", U"Table: Vertical error bars plot...")
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	WORD (U"Lower error value column", U"")
-	WORD (U"Upper error value column", U"")
-	REAL (U"Bar size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", 1);
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long yl = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Lower error value column"));
-		long yu = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Upper error value column"));
-		
-		Table_verticalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			yl, yu, GET_REAL (U"Bar size"), GET_INTEGER (U"Garnish"), U"1", interpreter);
-	}
-END
-
-FORM (Table_verticalErrorBarsPlotWhere, U"Table: Vertical error bars plot where", U"Table: Vertical error bars plot where...")
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	WORD (U"Lower error value column", U"")
-	WORD (U"Upper error value column", U"")
-	REAL (U"Bar size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", 1);
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long xl = Table_findColumnIndexFromColumnLabel (me, lowerErrorColumn_string);
+		long xu = Table_findColumnIndexFromColumnLabel (me, upperErrorColumn_string);
+		Table_horizontalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, xl, xu, barSize_mm, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_verticalErrorBarsPlot, U"Table: Vertical error bars plot", U"Table: Vertical error bars plot...") {
+	WORDVAR (xColumn_string, U"Horizontal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	WORDVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	WORDVAR (lowerErrorColumn_string, U"Lower error value column", U"error1")
+	WORDVAR (upperErrorColumn_string, U"Upper error value column", U"error2")
+	REALVAR (barSize_mm, U"Bar size (mm)", U"1.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long yl = Table_findColumnIndexFromColumnLabel (me, lowerErrorColumn_string);
+		long yu = Table_findColumnIndexFromColumnLabel (me, upperErrorColumn_string);
+		Table_verticalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, yl, yu, barSize_mm, garnish, U"1", interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Table_verticalErrorBarsPlotWhere, U"Table: Vertical error bars plot where", U"Table: Vertical error bars plot where...") {
+	WORDVAR (xColumn_string, U"Horizontal column", U"")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	WORDVAR (yColumn_string, U"Vertical column", U"")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	WORDVAR (lowerErrorColumn_string, U"Lower error value column", U"error1")
+	WORDVAR (upperErrorColumn_string, U"Upper error value column", U"error2")
+	REALVAR (barSize_mm, U"Bar size (mm)", U"1.0")
+	BOOLEANVAR (garnish, U"Garnish", true);
 	LABEL (U"", U"Use only data in rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long yl = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Lower error value column"));
-		long yu = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Upper error value column"));
-		
-		Table_verticalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			yl, yu, GET_REAL (U"Bar size"), GET_INTEGER (U"Garnish"), GET_STRING (U"Formula"), interpreter);
-	}
-END
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, xColumn_string);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, yColumn_string);
+		long yl = Table_findColumnIndexFromColumnLabel (me, lowerErrorColumn_string);
+		long yu = Table_findColumnIndexFromColumnLabel (me, upperErrorColumn_string);
+		Table_verticalErrorBarsPlotWhere (me, GRAPHICS, xcolumn, ycolumn, xmin, xmax, ymin, ymax, yl, yu, barSize_mm, garnish, formula, interpreter);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_extractRowsWhere, U"Table: Extract rows where", 0)
+FORM (NEW_Table_extractRowsWhere, U"Table: Extract rows where", nullptr) {
 	LABEL (U"", U"Extract rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	LOOP {
-		iam (Table);
-		autoTable thee = Table_extractRowsWhere (me, GET_STRING (U"Formula"), interpreter);
-		praat_new (thee.move(), my name, U"_formula");
-	}
-END
+	CONVERT_EACH (Table)
+		autoTable result = Table_extractRowsWhere (me, formula, interpreter);
+	CONVERT_EACH_END (my name, U"_formula")
+}
 
-FORM (Table_extractRowsMahalanobisWhere, U"Table: Extract rows where (mahalanobis)", 0)
-	SENTENCE (U"Extract all rows where columns...", U"")
+FORM (NEW_Table_extractRowsMahalanobisWhere, U"Table: Extract rows where (mahalanobis)", nullptr) {
+	SENTENCEVAR (dataColumns_string, U"Extract all rows where columns...", U"F1 F2 F3")
 	RADIO_ENUM (U"...have a mahalanobis distance...", kMelder_number, GREATER_THAN)
-	REAL (U"...the number", U"2.0")
-	WORD (U"Factor column", U"")
+	REALVAR (numberOfSigmas, U"...the number", U"2.0")
+	WORDVAR (factorColumn_string, U"Factor column", U"")
 	LABEL (U"", U"Process only rows where the following condition holds:")
-	TEXTFIELD (U"Formula", U"1; self$[\"gender\"]=\"male\"")
+	TEXTVAR (formula, U"Formula", U"1; self$[\"gender\"]=\"male\"")
 	OK
 DO
-	double numberOfSigmas = GET_REAL (U"...the number");
-	LOOP {
-		iam (Table);
-		autoTable thee = Table_extractMahalanobisWhere(me, GET_STRING (U"Extract all rows where columns..."), 
-		   GET_STRING (U"Factor column"), numberOfSigmas, GET_ENUM (kMelder_number, U"...have a mahalanobis distance..."),
-		   GET_STRING (U"Formula"), interpreter);
-		praat_new (thee.move(), my name, U"_mahalanobis");
-	}
-END
+	CONVERT_EACH (Table)
+		autoTable result = Table_extractMahalanobisWhere(me, dataColumns_string, factorColumn_string, numberOfSigmas, GET_ENUM (kMelder_number, U"...have a mahalanobis distance..."), formula, interpreter);
+	CONVERT_EACH_END (my name, U"_mahalanobis")
+}
 
-FORM (Table_extractColumnRanges, U"Table: Extract column ranges", 0)
+FORM (NEW_Table_extractColumnRanges, U"Table: Extract column ranges", nullptr) {
 	LABEL (U"", U"Create a new Table from the following columns:")
-	TEXTFIELD (U"Ranges", U"1 2")
+	TEXTVAR (columnRanges_string, U"Ranges", U"1 2")
 	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
 	OK
 DO
-	LOOP {
-		iam (Table);
-		autoTable thee = Table_extractColumnRanges (me, GET_STRING (U"Ranges"));
-		praat_new (thee.move(), my name, U"_columns");
-	}
-END
+	CONVERT_EACH (Table)
+		autoTable result = Table_extractColumnRanges (me, columnRanges_string);
+	CONVERT_EACH_END (my name, U"_columns")
+}
 
 /******************* TableOfReal ****************************/
 
-DIRECT (New_CreateIrisDataset)
-	praat_new (TableOfReal_createIrisDataset (), U"");
-END
+DIRECT (NEW1_CreateIrisDataset) {
+	CREATE_ONE
+		autoTableOfReal result = TableOfReal_createIrisDataset ();
+	CREATE_ONE_END (U"iris")
+}
 
-FORM (TableOfReal_reportMultivariateNormality, U"TableOfReal: Report multivariate normality (BHEP)", U"TableOfReal: Report multivariate normality (BHEP)...")
-	REAL (U"Smoothing parameter", U"0.0")
+FORM (INFO_TableOfReal_reportMultivariateNormality, U"TableOfReal: Report multivariate normality (BHEP)", U"TableOfReal: Report multivariate normality (BHEP)...") {
+	REALVAR (h, U"Smoothing parameter", U"0.0")
 	OK
 DO
-	double h = GET_REAL (U"Smoothing parameter");
-	MelderInfo_open ();
-	LOOP {
-		iam (TableOfReal);
+	INFO_ONE (TableOfReal)
 		double tnb, lnmu, lnvar;
 		double prob = TableOfReal_normalityTest_BHEP (me, &h, &tnb, &lnmu, &lnvar);
 		MelderInfo_open ();
@@ -8089,617 +6513,484 @@ DO
 		MelderInfo_writeLine (U"Smoothing: ", h);
 		MelderInfo_writeLine (U"Sample size: ", my numberOfRows);
 		MelderInfo_writeLine (U"Number of variables: ", my numberOfColumns);
-	}
-	MelderInfo_close ();
-END
+		MelderInfo_close ();
+	INFO_ONE_END
+}
 
-DIRECT (TableOfReal_and_Permutation_permuteRows)
-	TableOfReal me = FIRST (TableOfReal);
-	Permutation p = FIRST (Permutation);
-	praat_new (TableOfReal_and_Permutation_permuteRows (me, p),
-		my name, U"_", p->name);
-END
+DIRECT (NEW1_TableOfReal_and_Permutation_permuteRows) {
+	CONVERT_TWO (TableOfReal, Permutation)
+		autoTableOfReal result = TableOfReal_and_Permutation_permuteRows (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-DIRECT (TableOfReal_to_Permutation_sortRowlabels)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Permutation_sortRowLabels (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Permutation_sortRowlabels) {
+	CONVERT_EACH (TableOfReal)
+		autoPermutation result = TableOfReal_to_Permutation_sortRowLabels (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_appendColumns)
-	autoTableOfRealList list = TableOfRealList_create ();
-	LOOP {
-		iam (TableOfReal);
-		list -> addItem_ref (me);
-	}
-	autoTableOfReal result = TableOfRealList_appendColumnsMany (list.get());
-	praat_new (result.move(), U"columns_appended");
-END
+DIRECT (NEW1_TableOfReal_appendColumns) {
+	CONVERT_TYPED_LIST (TableOfReal, TableOfRealList)
+		autoTableOfReal result = TableOfRealList_appendColumnsMany (list.get());
+	CONVERT_TYPED_LIST_END (U"columns_appended");
+}
 
-FORM (TableOfReal_createFromPolsData_50males, U"Create TableOfReal (Pols 1973)", U"Create TableOfReal (Pols 1973)...")
-	BOOLEAN (U"Include formant levels", false)
+FORM (NEW1_TableOfReal_create_pols1973, U"Create TableOfReal (Pols 1973)", U"Create TableOfReal (Pols 1973)...") {
+	BOOLEANVAR (includeFormantAmplitudeLevels, U"Include formant levels", false)
 	OK
 DO
-	autoTableOfReal result = TableOfReal_createFromPolsData_50males (
-		GET_INTEGER (U"Include formant levels"));
-	praat_new (result.move(), U"pols_50males");
-END
+	CREATE_ONE
+		autoTableOfReal result = TableOfReal_create_pols1973 (includeFormantAmplitudeLevels);
+	CREATE_ONE_END (U"pols1973")
+}
 
-DIRECT (Table_createFromEspositoData)
-	praat_new (Table_createFromEspositoData (), U"h1_h2");
-END
+DIRECT (NEW_Table_create_esposito2006) {
+	CREATE_ONE
+		autoTable result = Table_create_esposito2006 ();
+	CREATE_ONE_END (U"esposito2006")
+}
 
-DIRECT (Table_createFromGanongData)
-	praat_new (Table_createFromGanongData (), U"ganong");
-END
+DIRECT (NEW_Table_create_ganong1980) {
+	CREATE_ONE
+		autoTable result = Table_create_ganong1980 ();
+	CREATE_ONE_END (U"ganong")
+}
 
-FORM (TableOfReal_createFromVanNieropData_25females, U"Create TableOfReal (Van Nierop 1973)...", U"Create TableOfReal (Van Nierop 1973)...")
-	BOOLEAN (U"Include formant levels", false)
+FORM (NEW_TableOfReal_create_vanNierop1973, U"Create TableOfReal (Van Nierop 1973)...", U"Create TableOfReal (Van Nierop 1973)...") {
+	BOOLEANVAR (includeFormantAmplitudeLevels, U"Include formant levels", false)
 	OK
 DO
-	praat_new (TableOfReal_createFromVanNieropData_25females (GET_INTEGER (U"Include formant levels")), U"vannierop_25females");
-END
+	CREATE_ONE
+		autoTableOfReal result = TableOfReal_create_vanNierop1973 (includeFormantAmplitudeLevels);
+	CREATE_ONE_END (U"vanNierop1973")
+}
 
-FORM (TableOfReal_createFromWeeninkData, U"Create TableOfReal (Weenink 1985)...", U"Create TableOfReal (Weenink 1985)...")
-	RADIO (U"Speakers group", 1)
+FORM (NEW_TableOfReal_create_weenink1983, U"Create TableOfReal (Weenink 1985)...", U"Create TableOfReal (Weenink 1985)...") {
+	RADIOVAR (speakerGroup, U"Speakers group", 1)
 		RADIOBUTTON (U"Men")
 		RADIOBUTTON (U"Women")
 		RADIOBUTTON (U"Children")
 	OK
 DO
-	int type = GET_INTEGER (U"Speakers group");
-	praat_new (TableOfReal_createFromWeeninkData (type),
-		(type == 1 ? U"m10" : type == 2 ? U"w10" : U"c10"));
-END
+	CREATE_ONE
+		autoTableOfReal result = TableOfReal_create_weenink1983 (speakerGroup);
+	CREATE_ONE_END ((speakerGroup == 1 ? U"m10" : speakerGroup == 2 ? U"w10" : U"c10"));
+}
 
-FORM (TableOfReal_drawScatterPlot, U"TableOfReal: Draw scatter plot", U"TableOfReal: Draw scatter plot...")
+FORM (GRAPHICS_TableOfReal_drawScatterPlot, U"TableOfReal: Draw scatter plot", U"TableOfReal: Draw scatter plot...") {
 	LABEL (U"", U"Select the part of the table")
-	NATURAL (U"Horizontal axis column number", U"1")
-	NATURAL (U"Vertical axis column number", U"2")
-	INTEGER (U"left Row number range", U"0")
-	INTEGER (U"right Row number range", U"0")
+	NATURALVAR (xColumn, U"Horizontal axis column number", U"1")
+	NATURALVAR (yColumn, U"Vertical axis column number", U"2")
+	INTEGERVAR (fromRow, U"left Row number range", U"0")
+	INTEGERVAR (toRow, U"right Row number range", U"0")
 	LABEL (U"", U"Select the drawing area limits")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	NATURAL (U"Label size", U"12")
-	BOOLEAN (U"Use row labels", false)
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawScatterPlot (me, GRAPHICS,
-			GET_INTEGER (U"Horizontal axis column number"),
-			GET_INTEGER (U"Vertical axis column number"),
-			GET_INTEGER (U"left Row number range"),
-			GET_INTEGER (U"right Row number range"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Use row labels"),
-			GET_STRING (U"Label"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	NATURALVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (useRowLabels, U"Use row labels", false)
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawScatterPlot (me, GRAPHICS, xColumn, yColumn, fromRow, toRow, xmin, xmax, ymin, ymax, labelSize, useRowLabels, label, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawScatterPlotMatrix, U"TableOfReal: Draw scatter plots matrix", 0)
-	INTEGER (U"From column", U"0")
-	INTEGER (U"To column", U"0")
-	POSITIVE (U"Fraction white", U"0.1")
+FORM (GRAPHICS_TableOfReal_drawScatterPlotMatrix, U"TableOfReal: Draw scatter plots matrix", nullptr) {
+	INTEGERVAR (fromColumn, U"From column", U"0")
+	INTEGERVAR (toColumn, U"To column", U"0")
+	POSITIVEVAR (fractionWhite, U"Fraction white", U"0.1")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawScatterPlotMatrix (me, GRAPHICS,
-			GET_INTEGER (U"From column"),
-			GET_INTEGER (U"To column"),
-			GET_REAL (U"Fraction white"));
-	}
-END
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawScatterPlotMatrix (me, GRAPHICS, fromColumn, toColumn, fractionWhite);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawBiplot, U"TableOfReal: Draw biplot", U"TableOfReal: Draw biplot...")
+FORM (GRAPHICS_TableOfReal_drawBiplot, U"TableOfReal: Draw biplot", U"TableOfReal: Draw biplot...") {
 	LABEL (U"", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	REAL (U"Split factor", U"0.5")
-	INTEGER (U"Label size", U"10")
-	BOOLEAN (U"Garnish", 1)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawBiplot (me, GRAPHICS,
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Split factor"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	REALVAR (splitFactor, U"Split factor", U"0.5")
+	INTEGERVAR (labelSize, U"Label size", U"10")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawBiplot (me, GRAPHICS, xmin, xmax, ymin, ymax, splitFactor, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawVectors, U"Draw vectors", U"TableOfReal: Draw vectors...")
+FORM (GRAPHICS_TableOfReal_drawVectors, U"Draw vectors", U"TableOfReal: Draw vectors...") {
 	LABEL (U"", U"From (x1, y1) to (x2, y2)")
-	NATURAL (U"left From columns (x1, y1)", U"1")
-	NATURAL (U"right From columns (x1, y1)", U"2")
-	NATURAL (U"left To columns (x2, y2)", U"3")
-	NATURAL (U"right To columns (x2, y2)", U"4")
+	NATURALVAR (x1Column, U"X1 column", U"1")
+	NATURALVAR (y1Column, U"Y1 column", U"2")
+	NATURALVAR (x2Column, U"X2 column", U"3")
+	NATURALVAR (y2Column, U"Y2 column", U"4")
 	LABEL (U"", U"Select the drawing area")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	RADIO (U"Vector type", 1)
-	RADIOBUTTON (U"Arrow")
-	RADIOBUTTON (U"Double arrow")
-	RADIOBUTTON (U"Line")
-	INTEGER (U"Label size", U"10")
-	BOOLEAN (U"Garnish", 1)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawVectors (me, GRAPHICS,
-			GET_INTEGER (U"left From columns"),
-			GET_INTEGER (U"right From columns"),
-			GET_INTEGER (U"left To columns"),
-			GET_INTEGER (U"right To columns"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Vector type"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	RADIOVAR (vectorType, U"Vector type", 1)
+		RADIOBUTTON (U"Arrow")
+		RADIOBUTTON (U"Double arrow")
+		RADIOBUTTON (U"Line")
+	INTEGERVAR (labelSize, U"Label size", U"10")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawVectors (me, GRAPHICS, x1Column, y1Column, x2Column, y2Column, xmin, xmax, ymin, ymax, vectorType, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawRowAsHistogram, U"Draw row as histogram", U"TableOfReal: Draw rows as histogram...")
+FORM (GRAPHICS_TableOfReal_drawRowAsHistogram, U"Draw row as histogram", U"TableOfReal: Draw rows as histogram...") {
 	LABEL (U"", U"Select from the table")
-	WORD (U"Row number", U"1")
-	INTEGER (U"left Column range", U"0")
-	INTEGER (U"right Column range", U"0")
+	WORDVAR (rowNumber, U"Row number", U"1")
+	INTEGERVAR (fromColumn, U"left Column range", U"0")
+	INTEGERVAR (toColumn, U"right Column range", U"0")
 	LABEL (U"", U"Vertical drawing range")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	LABEL (U"", U"Offset and distance in units of 'bar width'")
-	REAL (U"Horizontal offset", U"0.5")
-	REAL (U"Distance between bars", U"1.0")
-	WORD (U"Grey value (1=white)", U"0.7")
-	BOOLEAN (U"Garnish", 1)
+	REALVAR (xOffset, U"Horizontal offset", U"0.5")
+	REALVAR (distanceBetweenBars, U"Distance between bars", U"1.0")
+	WORDVAR (greys, U"Grey value (1=white)", U"0.7")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawRowsAsHistogram (me, GRAPHICS, GET_STRING (U"Row number"),
-			GET_INTEGER (U"left Column range"),
-			GET_INTEGER (U"right Column range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Horizontal offset"),
-			0,
-			GET_REAL (U"Distance between bars"),
-			GET_STRING (U"Grey value"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawRowsAsHistogram (me, GRAPHICS, rowNumber, fromColumn, toColumn, ymin, ymax, xOffset, 0, distanceBetweenBars, greys, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawRowsAsHistogram, U"Draw rows as histogram", U"TableOfReal: Draw rows as histogram...")
+FORM (GRAPHICS_TableOfReal_drawRowsAsHistogram, U"Draw rows as histogram", U"TableOfReal: Draw rows as histogram...") {
 	LABEL (U"", U"Select from the table")
-	SENTENCE (U"Row numbers", U"1 2")
-	INTEGER (U"left Column range", U"0")
-	INTEGER (U"right Column range", U"0")
+	SENTENCEVAR (rowNumbers_string, U"Row numbers", U"1 2")
+	INTEGERVAR (fromColumn, U"left Column range", U"0")
+	INTEGERVAR (toColumn, U"right Column range", U"0")
 	LABEL (U"", U"Vertical drawing range")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
 	LABEL (U"", U"Offset and distance in units of 'bar width'")
-	REAL (U"Horizontal offset", U"1.0")
-	REAL (U"Distance between bar groups", U"1.0")
-	REAL (U"Distance between bars", U"0.0")
-	SENTENCE (U"Grey values (1=white)", U"1 1")
-	BOOLEAN (U"Garnish", 1)
+	REALVAR (xOffset, U"Horizontal offset", U"1.0")
+	REALVAR (distanceBetweenBarGroups, U"Distance between bar groups", U"1.0")
+	REALVAR (distanceBetweenBars, U"Distance between bars", U"0.0")
+	SENTENCEVAR (greys_string, U"Grey values (1=white)", U"1 1")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawRowsAsHistogram (me, GRAPHICS,
-		GET_STRING (U"Row numbers"),
-		GET_INTEGER (U"left Column range"), GET_INTEGER (U"right Column range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_REAL (U"Horizontal offset"), GET_REAL (U"Distance between bars"),
-		GET_REAL (U"Distance between bar groups"), GET_STRING (U"Grey values"),
-		GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawRowsAsHistogram (me, GRAPHICS, rowNumbers_string, fromColumn, toColumn, ymin, ymax,xOffset, distanceBetweenBars,distanceBetweenBarGroups, greys_string, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawBoxPlots, U"TableOfReal: Draw box plots", U"TableOfReal: Draw box plots...")
-	INTEGER (U"From row", U"0")
-	INTEGER (U"To row", U"0")
-	INTEGER (U"From column", U"0")
-	INTEGER (U"To column", U"0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	BOOLEAN (U"Garnish", 1)
+FORM (GRAPHICS_TableOfReal_drawBoxPlots, U"TableOfReal: Draw box plots", U"TableOfReal: Draw box plots...") {
+	INTEGERVAR (fromRow, U"From row", U"0")
+	INTEGERVAR (toRow, U"To row", U"0")
+	INTEGERVAR (fromColumn, U"From column", U"0")
+	INTEGERVAR (toColumn, U"To column", U"0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawBoxPlots (me, GRAPHICS, GET_INTEGER (U"From row"), GET_INTEGER (U"To row"),
-		GET_INTEGER (U"From column"), GET_INTEGER (U"To column"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawBoxPlots (me, GRAPHICS, fromRow, toRow, fromColumn, toColumn, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_drawColumnAsDistribution, U"TableOfReal: Draw column as distribution", U"TableOfReal: Draw column as distribution...")
-	NATURAL (U"Column number", U"1")
-	REAL (U"left Value range", U"0.0")
-	REAL (U"right Value range", U"0.0")
-	REAL (U"left Frequency range", U"0.0")
-	REAL (U"right frequency range", U"0.0")
-	NATURAL (U"Number of bins", U"10")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_TableOfReal_drawColumnAsDistribution, U"TableOfReal: Draw column as distribution", U"TableOfReal: Draw column as distribution...") {
+	NATURALVAR (columnNumber, U"Column number", U"1")
+	REALVAR (fromValue, U"left Value range", U"0.0")
+	REALVAR (toValue, U"right Value range", U"0.0")
+	REALVAR (fromFrequency, U"left Frequency range", U"0.0")
+	REALVAR (toFrequency, U"right frequency range", U"0.0")
+	NATURALVAR (numberOfBins, U"Number of bins", U"10")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawColumnAsDistribution (me, GRAPHICS, GET_INTEGER (U"Column number"),
-		GET_REAL (U"left Value range"), GET_REAL (U"right Value range"), GET_INTEGER (U"Number of bins"),
-		GET_REAL (U"left Frequency range"), GET_REAL (U"right frequency range"), false, GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawColumnAsDistribution (me, GRAPHICS, columnNumber, fromValue, toValue, numberOfBins, fromFrequency, toFrequency, false, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (TableOfReal_to_Configuration_lda, U"TableOfReal: To Configuration (lda)", U"TableOfReal: To Configuration (lda)...")
-	INTEGER (U"Number of dimensions", U"0 (= all)")
+FORM (NEW_TableOfReal_to_Configuration_lda, U"TableOfReal: To Configuration (lda)", U"TableOfReal: To Configuration (lda)...") {
+	INTEGERVAR (numberOfDimensions, U"Number of dimensions", U"0 (= all)")
 	OK
 DO
-	long dimension = GET_INTEGER (U"Number of dimensions");
-	if (dimension < 0) {
-		Melder_throw (U"Number of dimensions must be greater equal zero.");
-	}
-	LOOP {
-		iam (TableOfReal);
-		autoConfiguration thee = TableOfReal_to_Configuration_lda (me, dimension);
-		praat_new (thee.move(), my name, U"_lda");
-	}
-END
+	REQUIRE (numberOfDimensions >= 0, U"Number of dimensions must be greater equal zero.")
+	CONVERT_EACH (TableOfReal)
+		autoConfiguration result = TableOfReal_to_Configuration_lda (me, numberOfDimensions);
+	CONVERT_EACH_END (my name, U"_lda")
+}
 
-FORM (TableOfReal_to_CCA, U"TableOfReal: To CCA", U"TableOfReal: To CCA...")
+FORM (NEW_TableOfReal_to_CCA, U"TableOfReal: To CCA", U"TableOfReal: To CCA...") {
 	NATURAL (U"Dimension of dependent variate", U"2")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		autoCCA thee = TableOfReal_to_CCA (me, GET_INTEGER (U"Dimension of dependent variate"));
-		praat_new (thee.move(), my name);
-	}
-END
+	CONVERT_EACH (TableOfReal)
+		autoCCA result = TableOfReal_to_CCA (me, GET_INTEGER (U"Dimension of dependent variate"));
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_to_Configuration_pca, U"TableOfReal: To Configuration (pca)", U"TableOfReal: To Configuration (pca)...")
+FORM (NEW_TableOfReal_to_Configuration_pca, U"TableOfReal: To Configuration (pca)", U"TableOfReal: To Configuration (pca)...") {
 	NATURAL (U"Number of dimensions", U"2")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		autoConfiguration thee = TableOfReal_to_Configuration_pca (me, GET_INTEGER (U"Number of dimensions"));
-		praat_new (thee.move(), my name, U"_pca");
-	}
-END
+	CONVERT_EACH (TableOfReal)
+		autoConfiguration result = TableOfReal_to_Configuration_pca (me, GET_INTEGER (U"Number of dimensions"));
+	CONVERT_EACH_END (my name, U"_pca")
+}
 
-DIRECT (TableOfReal_to_Discriminant)
-	LOOP {
-		iam (TableOfReal);
-		autoDiscriminant thee = TableOfReal_to_Discriminant (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Discriminant) {
+	CONVERT_EACH (TableOfReal)
+		autoDiscriminant result = TableOfReal_to_Discriminant (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_PCA_byRows)
-	LOOP {
-		iam (TableOfReal);
-		autoPCA thee = TableOfReal_to_PCA_byRows (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_PCA_byRows) {
+	CONVERT_EACH (TableOfReal)
+		autoPCA result = TableOfReal_to_PCA_byRows (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_to_SSCP, U"TableOfReal: To SSCP", U"TableOfReal: To SSCP...")
-	INTEGER (U"Begin row", U"0")
-	INTEGER (U"End row", U"0")
-	INTEGER (U"Begin column", U"0")
-	INTEGER (U"End column", U"0")
+FORM (NEW_TableOfReal_to_SSCP, U"TableOfReal: To SSCP", U"TableOfReal: To SSCP...") {
+	INTEGERVAR (fromRow, U"Begin row", U"0")
+	INTEGERVAR (toRow, U"End row", U"0")
+	INTEGERVAR (fromColumn, U"Begin column", U"0")
+	INTEGERVAR (toColumn, U"End column", U"0")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_SSCP (me, GET_INTEGER (U"Begin row"), GET_INTEGER (U"End row"),
-		GET_INTEGER (U"Begin column"), GET_INTEGER (U"End column")), my name);
-	}
-END
+	CONVERT_EACH (TableOfReal)
+		autoSSCP result = TableOfReal_to_SSCP (me, fromRow, toRow, fromColumn, toColumn);
+	CONVERT_EACH_END (my name)
+}
 
 /* For the inheritors */
-DIRECT (TableOfReal_to_TableOfReal)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_TableOfReal (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_TableOfReal) {
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_to_TableOfReal (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Correlation)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Correlation (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Correlation) {
+	CONVERT_EACH (TableOfReal)
+		autoCorrelation result = TableOfReal_to_Correlation (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Correlation_rank)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Correlation_rank (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Correlation_rank) {
+	CONVERT_EACH (TableOfReal)
+		autoCorrelation result = TableOfReal_to_Correlation_rank (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Covariance)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Covariance (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Covariance) {
+	CONVERT_EACH (TableOfReal)
+		autoCovariance result = TableOfReal_to_Covariance (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_SVD)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_SVD (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_SVD) {
+	CONVERT_EACH (TableOfReal)
+		autoSVD result = TableOfReal_to_SVD (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TablesOfReal_to_Eigen_gsvd)
-	TableOfReal t1 = nullptr, t2 = nullptr;
-	LOOP {
-		iam (TableOfReal);
-		(t1 ? t2 : t1) = me;
-	}
-	Melder_assert (t1 && t2);
-	autoEigen thee = TablesOfReal_to_Eigen_gsvd (t1, t2);
-	praat_new (thee.move(), U"");
-END
+DIRECT (NEW1_TablesOfReal_to_Eigen_gsvd) {
+	CONVERT_COUPLE (TableOfReal)
+		autoEigen result = TablesOfReal_to_Eigen_gsvd (me, you);
+	CONVERT_COUPLE_END (U"gsvd");
+}
 
-FORM (TableOfReal_and_TableOfReal_crossCorrelations, U"TableOfReal & TableOfReal: Cross-correlations", 0)
-	OPTIONMENU (U"Correlations between", 1)
-	OPTION (U"Rows")
-	OPTION (U"Columns")
-	BOOLEAN (U"Center", 0)
-	BOOLEAN (U"Normalize", 0)
+FORM (NEW1_TableOfReal_and_TableOfReal_crossCorrelations, U"TableOfReal & TableOfReal: Cross-correlations", nullptr) {
+	OPTIONMENUVAR (between, U"Correlations between", 1)
+		OPTION (U"Rows")
+		OPTION (U"Columns")
+	BOOLEANVAR (center, U"Center", false)
+	BOOLEANVAR (normalize, U"Normalize", false)
 	OK
 DO
-	int by_columns = GET_INTEGER (U"Correlations between") - 1;
-	TableOfReal t1 = 0, t2 = 0;
-	LOOP {
-		iam (TableOfReal);
-		(t1 ? t2 : t1) = me;
-	}
-	Melder_assert (t1 && t2);
-	praat_new (TableOfReal_and_TableOfReal_crossCorrelations (t1, t2, by_columns,
-			GET_INTEGER (U"Center"), GET_INTEGER (U"Normalize")), (by_columns ? U"by_columns" : U"by_rows"), U"cc");
-END
+	int by_columns = between - 1;
+	CONVERT_COUPLE (TableOfReal)
+		autoTableOfReal result = TableOfReal_and_TableOfReal_crossCorrelations (me, you, by_columns, center, normalize);
+	CONVERT_COUPLE_END (U"cc_", by_columns ? U"by_cols" : U"by_rows")
+}
 
-DIRECT (TablesOfReal_to_GSVD)
-	TableOfReal t1 = 0, t2 = 0;
-	LOOP {
-		iam (TableOfReal);
-		(t1 ? t2 : t1) = me;
-	}
-	Melder_assert (t1 && t2);
-	praat_new (TablesOfReal_to_GSVD (t1, t2), U"");
-END
+void praat_TableOfReal_init3 (ClassInfo klas);
+void praat_TableOfReal_init3 (ClassInfo klas) {
+	praat_TableOfReal_init (klas);
+	praat_addAction1 (klas, 2, U"To TableOfReal (cross-correlations)...", 0, 0, NEW1_TableOfReal_and_TableOfReal_crossCorrelations);
+}
+
+DIRECT (NEW1_TablesOfReal_to_GSVD) {
+	CONVERT_COUPLE (TableOfReal)
+		autoGSVD result = TablesOfReal_to_GSVD (me, you);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
 
-FORM (TableOfReal_choleskyDecomposition, U"TableOfReal: Cholesky decomposition", 0)
-	BOOLEAN (U"Upper (else L)", 0)
-	BOOLEAN (U"Inverse", 0)
+FORM (NEW_TableOfReal_choleskyDecomposition, U"TableOfReal: Cholesky decomposition", nullptr) {
+	BOOLEANVAR (wantUpper, U"Upper (else L)", 0)
+	BOOLEANVAR (wantInverse, U"Inverse", 0)
 	OK
-	DO
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_choleskyDecomposition (me, GET_INTEGER (U"Upper"), GET_INTEGER (U"Inverse")), my name);
-	}
-END
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_choleskyDecomposition (me, wantUpper, wantInverse);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_to_PatternList_and_Categories, U"TableOfReal: To PatternList and Categories", U"TableOfReal: To PatternList and Categories...")
-	INTEGER (U"left Row range", U"0")
-	INTEGER (U"right Row range", U"0 (= all)")
-	INTEGER (U"left Column range", U"0")
-	INTEGER (U"right Column range", U"0 (= all)")
+FORM (NEWMANY_TableOfReal_to_PatternList_and_Categories, U"TableOfReal: To PatternList and Categories", U"TableOfReal: To PatternList and Categories...") {
+	INTEGERVAR (fromRow, U"left Row range", U"0")
+	INTEGERVAR (toRow, U"right Row range", U"0 (= all)")
+	INTEGERVAR (fromColumn, U"left Column range", U"0")
+	INTEGERVAR (toColumn, U"right Column range", U"0 (= all)")
 	OK
-	DO
-	LOOP {
-		iam (TableOfReal);
+DO
+	CONVERT_EACH (TableOfReal)
 		autoPatternList ap; 
-		autoCategories ac;
-		TableOfReal_to_PatternList_and_Categories (me, GET_INTEGER (U"left Row range"),
-		GET_INTEGER (U"right Row range"), GET_INTEGER (U"left Column range"),
-		GET_INTEGER (U"right Column range"), & ap, & ac);
-		praat_new (ap.move(), Thing_getName (me));
-		praat_new (ac.move(), Thing_getName (me));
-	}
-END
+		autoCategories result;
+		TableOfReal_to_PatternList_and_Categories (me, fromRow, toRow, fromColumn, toColumn, & ap, & result);
+		praat_new (ap.move(), my name);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_getColumnSum, U"TableOfReal: Get column sum", U"")
-	INTEGER (U"Column", U"1")
+FORM (REAL_TableOfReal_getColumnSum, U"TableOfReal: Get column sum", U"") {
+	INTEGERVAR (columnNumber, U"Column", U"1")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (TableOfReal_getColumnSum (me, GET_INTEGER (U"Column")));
-	}
-END
+	NUMBER_ONE (TableOfReal)
+		double result = TableOfReal_getColumnSum (me, columnNumber);
+	NUMBER_ONE_END (U"(column sum)")
+}
 
-FORM (TableOfReal_getRowSum, U"TableOfReal: Get row sum", U"")
-	INTEGER (U"Row", U"1")
+FORM (REAL_TableOfReal_getRowSum, U"TableOfReal: Get row sum", U"") {
+	INTEGERVAR (rowNumber, U"Row", U"1")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (TableOfReal_getRowSum (me, GET_INTEGER (U"Row")));
-	}
-END
+	NUMBER_ONE (TableOfReal)
+		double result = TableOfReal_getRowSum (me, rowNumber);
+	NUMBER_ONE_END (U"(row sum)")
+}
 
-DIRECT (TableOfReal_getGrandSum)
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (TableOfReal_getGrandSum (me));
-	}
-END
+DIRECT (REAL_TableOfReal_getGrandSum) {
+	NUMBER_ONE (TableOfReal)
+		double result = TableOfReal_getGrandSum (me);
+	NUMBER_ONE_END (U"(grand sum)")
+}
 
-FORM (TableOfReal_meansByRowLabels, U"TableOfReal: Means by row labels", U"TableOfReal: To TableOfReal (means by row labels)...")
-	BOOLEAN (U"Expand", 0)
+FORM (NEW_TableOfReal_meansByRowLabels, U"TableOfReal: Means by row labels", U"TableOfReal: To TableOfReal (means by row labels)...") {
+	BOOLEANVAR (wantExpand, U"Expand", 0)
 	OK
-	DO
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_meansByRowLabels (me, GET_INTEGER (U"Expand"), 0), NAME, U"_byrowlabels");
-	}
-END
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_meansByRowLabels (me, wantExpand, 0);
+	CONVERT_EACH_END (my name, U"_byrowlabels")
+}
 
-FORM (TableOfReal_mediansByRowLabels, U"TableOfReal: Medians by row labels", U"TableOfReal: To TableOfReal (medians by row labels)...")
-	BOOLEAN (U"Expand", 0)
+FORM (NEW_TableOfReal_mediansByRowLabels, U"TableOfReal: Medians by row labels", U"TableOfReal: To TableOfReal (medians by row labels)...") {
+	BOOLEANVAR (wantExpand, U"Expand", 0)
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_meansByRowLabels (me, GET_INTEGER (U"Expand"), 1), Thing_getName (me), U"_byrowlabels");
-	}
-END
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_meansByRowLabels (me, wantExpand, 1);
+	CONVERT_EACH_END (my name, U"_byrowlabels")
+}
 
 /***** TableOfReal and FilterBank  *****/
 
-FORM (TextGrid_extendTime, U"TextGrid: Extend time", U"TextGrid: Extend time...")
+FORM (MODIFY_TextGrid_extendTime, U"TextGrid: Extend time", U"TextGrid: Extend time...") {
 	LABEL (U"", U"")
-	POSITIVE (U"Extend domain by (s)", U"1.0")
-	RADIO (U"At", 1)
+	POSITIVEVAR (extension_s, U"Extend domain by (s)", U"1.0")
+	RADIOVAR (position, U"At", 1)
 	RADIOBUTTON (U"End")
 	RADIOBUTTON (U"Start")
 	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_extendTime (me, GET_REAL (U"Extend domain by"), GET_INTEGER (U"At") - 1);
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (TextGrid)
+		TextGrid_extendTime (me,extension_s, position - 1);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_replaceIntervalTexts, U"TextGrid: Replace interval text", U"TextGrid: Replace interval text...")
+FORM (MODIFY_TextGrid_replaceIntervalTexts, U"TextGrid: Replace interval text", U"TextGrid: Replace interval text...") {
 	LABEL (U"", U"")
-	NATURAL (U"Tier number", U"1")
-	INTEGER (U"left Interval range", U"0")
-	INTEGER (U"right Interval range", U"0")
-	SENTENCE (U"Search", U"a")
-	SENTENCE (U"Replace", U"a")
-	RADIO (U"Search and replace strings are:", 1)
-	RADIOBUTTON (U"Literals")
-	RADIOBUTTON (U"Regular Expressions")
+	NATURALVAR (tierNumber, U"Tier number", U"1")
+	INTEGERVAR (fromInterval, U"left Interval range", U"0")
+	INTEGERVAR (toInterval, U"right Interval range", U"0")
+	SENTENCEVAR (search_string, U"Search", U"a")
+	SENTENCEVAR (replace_string, U"Replace", U"a")
+	RADIOVAR (searchType, U"Search and replace strings are:", 1)
+		RADIOBUTTON (U"Literals")
+		RADIOBUTTON (U"Regular Expressions")
 	OK
 DO
-	long from = GET_INTEGER (U"left Interval range");
-	long to = GET_INTEGER (U"right Interval range");
-	int isregexp = GET_INTEGER (U"Search and replace strings are") - 1;
-	char32 *search = GET_STRING (U"Search");
-	LOOP {
-		iam (TextGrid);
+	MODIFY_EACH (TextGrid)
 		long nmatches, nstringmatches;
-		TextGrid_changeLabels (me, GET_INTEGER (U"Tier number"), from, to, search, GET_STRING (U"Replace"),
-		isregexp, &nmatches, &nstringmatches);
-		praat_dataChanged (me);
-	}
-END
+		TextGrid_changeLabels (me, tierNumber, fromInterval, toInterval, search_string, replace_string, searchType - 1, &nmatches, &nstringmatches);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_replacePointTexts, U"TextGrid: Replace point text", U"TextGrid: Replace point text...")
+FORM (MODIFY_TextGrid_replacePointTexts, U"TextGrid: Replace point text", U"TextGrid: Replace point text...") {
 	LABEL (U"", U"")
-	NATURAL (U"Tier number", U"1")
-	INTEGER (U"left Interval range", U"0")
-	INTEGER (U"right Interval range", U"0")
-	SENTENCE (U"Search", U"a")
-	SENTENCE (U"Replace", U"a")
-	RADIO (U"Search and replace strings are:", 1)
-	RADIOBUTTON (U"Literals")
-	RADIOBUTTON (U"Regular Expressions")
+	NATURALVAR (tierNumber, U"Tier number", U"1")
+	INTEGERVAR (fromInterval, U"left Interval range", U"0")
+	INTEGERVAR (toInterval, U"right Interval range", U"0")
+	SENTENCEVAR (search_string, U"Search", U"a")
+	SENTENCEVAR (replace_string, U"Replace", U"a")
+	RADIOVAR (searchType, U"Search and replace strings are:", 1)
+		RADIOBUTTON (U"Literals")
+		RADIOBUTTON (U"Regular Expressions")
 	OK
 DO
-	long from = GET_INTEGER (U"left Interval range");
-	long to = GET_INTEGER (U"right Interval range");
-	LOOP {
-		iam (TextGrid);
+	MODIFY_EACH (TextGrid)
 		long nmatches, nstringmatches;
-		TextGrid_changeLabels (me, GET_INTEGER (U"Tier number"), from, to, GET_STRING (U"Search"), GET_STRING (U"Replace"),
-		GET_INTEGER (U"Search and replace strings are") - 1, &nmatches, &nstringmatches);
-		praat_dataChanged (me);
-	}
-END
+		TextGrid_changeLabels (me, tierNumber, fromInterval, toInterval, search_string, replace_string, searchType - 1, &nmatches, &nstringmatches);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrids_to_Table_textAlignmentment, U"TextGrids: To Table (text alignment)", 0)
-	NATURAL (U"Target tier", U"1")
-	NATURAL (U"Source tier", U"1")
+FORM (NEW1_TextGrids_to_Table_textAlignmentment, U"TextGrids: To Table (text alignment)", nullptr) {
+	NATURALVAR (targetTierNumber, U"Target tier", U"1")
+	NATURALVAR (sourceTierNumber, U"Source tier", U"1")
 	OK
 DO
-	TextGrid tg1 = 0, tg2 = 0;
-    LOOP {
-        iam (TextGrid);
-        (tg1 ? tg2 : tg1) = me;
-    }
-    Melder_assert (tg1 && tg2);
-	praat_new (TextGrids_to_Table_textAlignmentment (tg1, GET_INTEGER (U"Target tier"), tg2, GET_INTEGER (U"Source tier"), 0), tg1 -> name, U"_", tg2 -> name);
-END
+	CONVERT_COUPLE (TextGrid)
+ 		autoTable result = TextGrids_to_Table_textAlignmentment (me, targetTierNumber, you, sourceTierNumber, nullptr);
+	CONVERT_COUPLE_END (my name, U"_", your name);
+}
 
-FORM (TextGrids_and_EditCostsTable_to_Table_textAlignmentment, U"TextGrids & EditCostsTable: To Table(text alignmentment)", 0)
-	NATURAL (U"Target tier", U"1")
-	NATURAL (U"Source tier", U"1")
+FORM (NEW1_TextGrids_and_EditCostsTable_to_Table_textAlignmentment, U"TextGrids & EditCostsTable: To Table(text alignmentment)", nullptr) {
+	NATURALVAR (targetTierNumber, U"Target tier", U"1")
+	NATURALVAR (sourceTierNumber, U"Source tier", U"1")
 	OK
 DO
-	TextGrid tg1 = 0, tg2 = 0; EditCostsTable ect = 0;
-    LOOP {
-        if (CLASS == classTextGrid) {
-        	(tg1 ? tg2 : tg1) = (TextGrid) OBJECT;
-		} else {
-			ect = (EditCostsTable) OBJECT;
-		}
-    }
- 	Melder_assert (tg1 && tg2 && ect);
-	praat_new (TextGrids_to_Table_textAlignmentment (tg1, GET_INTEGER (U"Target tier"), tg2, GET_INTEGER (U"Source tier"), ect), tg1 -> name, U"_", tg2 -> name);
-END
+	CONVERT_COUPLE_AND_ONE (TextGrid, EditCostsTable)
+		autoTable result = TextGrids_to_Table_textAlignmentment (me, targetTierNumber, you, sourceTierNumber, him);
+	CONVERT_COUPLE_AND_ONE_END (my name, U"_", your name)
+}
 
-FORM (TextGrid_setTierName, U"TextGrid: Set tier name", U"TextGrid: Set tier name...")
-	NATURAL (U"Tier number:", U"1")
-	SENTENCE (U"Name", U"");
+FORM (MODIFY_TextGrid_setTierName, U"TextGrid: Set tier name", U"TextGrid: Set tier name...") {
+	NATURALVAR (tierNUmber, U"Tier number:", U"1")
+	SENTENCEVAR (name, U"Name", U"");
 	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_setTierName (me, GET_INTEGER (U"Tier number"), GET_STRING (U"Name"));
-		praat_dataChanged (me);
-	}
-END
+	MODIFY_EACH (TextGrid)
+		TextGrid_setTierName (me, tierNUmber, name);
+	MODIFY_EACH_END
+}
 
-DIRECT (VowelEditor_create)
+DIRECT (WINDOW_VowelEditor_create) {
 	if (theCurrentPraatApplication -> batch) {
 		Melder_throw (U"Cannot edit from batch.");
 	}
 	autoVowelEditor vowelEditor = VowelEditor_create (U"VowelEditor", nullptr);
 	vowelEditor.releaseToUser();
-END
+END }
 
 static autoDaata cmuAudioFileRecognizer (int nread, const char *header, MelderFile file) {
 	return nread < 12 || header [0] != 6 || header [1] != 0 ?
@@ -8707,48 +6998,48 @@ static autoDaata cmuAudioFileRecognizer (int nread, const char *header, MelderFi
 }
 
 void praat_CC_init (ClassInfo klas) {
-	praat_addAction1 (klas, 1, U"Paint...", nullptr, 1, DO_CC_paint);
-	praat_addAction1 (klas, 1, U"Draw...", nullptr, 1, DO_CC_drawC0);
+	praat_addAction1 (klas, 1, U"Paint...", nullptr, 1, GRAPHICS_CC_paint);
+	praat_addAction1 (klas, 1, U"Draw...", nullptr, 1, GRAPHICS_CC_drawC0);
 	praat_addAction1 (klas, 1, QUERY_BUTTON, nullptr, 0, 0);
 	praat_TimeFrameSampled_query_init (klas);
-	praat_addAction1 (klas, 1, U"Get number of coefficients...", nullptr, 1, DO_CC_getNumberOfCoefficients);
-	praat_addAction1 (klas, 1, U"Get value in frame...", nullptr, 1, DO_CC_getValueInFrame);
-	praat_addAction1 (klas, 1, U"Get c0 value in frame...", nullptr, 1, DO_CC_getC0ValueInFrame);
-	praat_addAction1 (klas, 1, U"Get value...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_CC_getValue);
-	praat_addAction1 (klas, 0, U"To Matrix", nullptr, 0, DO_CC_to_Matrix);
-	praat_addAction1 (klas, 2, U"To DTW...", nullptr, 0, DO_CCs_to_DTW);
+	praat_addAction1 (klas, 1, U"Get number of coefficients...", nullptr, 1, INTEGER_CC_getNumberOfCoefficients);
+	praat_addAction1 (klas, 1, U"Get value in frame...", nullptr, 1, REAL_CC_getValueInFrame);
+	praat_addAction1 (klas, 1, U"Get c0 value in frame...", nullptr, 1, REAL_CC_getC0ValueInFrame);
+	praat_addAction1 (klas, 1, U"Get value...", nullptr, praat_HIDDEN + praat_DEPTH_1, REAL_CC_getValue);
+	praat_addAction1 (klas, 0, U"To Matrix", nullptr, 0, NEW_CC_to_Matrix);
+	praat_addAction1 (klas, 2, U"To DTW...", nullptr, 0, NEW1_CCs_to_DTW);
 }
 
 static void praat_Eigen_Matrix_project (ClassInfo klase, ClassInfo klasm); // deprecated 2014
 static void praat_Eigen_Matrix_project (ClassInfo klase, ClassInfo klasm) {
-	praat_addAction2 (klase, 1, klasm, 1, U"Project...", nullptr, praat_HIDDEN, DO_Eigen_and_Matrix_projectColumns);
-	praat_addAction2 (klase, 1, klasm, 1, U"To Matrix (project columns)...", nullptr, praat_HIDDEN, DO_Eigen_and_Matrix_projectColumns);
+	praat_addAction2 (klase, 1, klasm, 1, U"Project...", nullptr, praat_HIDDEN, NEW1_Eigen_and_Matrix_projectColumns);
+	praat_addAction2 (klase, 1, klasm, 1, U"To Matrix (project columns)...", nullptr, praat_HIDDEN, NEW1_Eigen_and_Matrix_projectColumns);
 }
 
 static void praat_Eigen_Spectrogram_project (ClassInfo klase, ClassInfo klasm);
 static void praat_Eigen_Spectrogram_project (ClassInfo klase, ClassInfo klasm) {
-	praat_addAction2 (klase, 1, klasm, 1, U"Project...", nullptr, praat_HIDDEN, DO_Eigen_and_Matrix_projectColumns);
-	praat_addAction2 (klase, 1, klasm, 1, U"To Matrix (project columns)...", nullptr, 0, DO_Eigen_and_Matrix_projectColumns);
+	praat_addAction2 (klase, 1, klasm, 1, U"Project...", nullptr, praat_HIDDEN, NEW1_Eigen_and_Matrix_projectColumns);
+	praat_addAction2 (klase, 1, klasm, 1, U"To Matrix (project columns)...", nullptr, 0, NEW1_Eigen_and_Matrix_projectColumns);
 }
 
 static void praat_Eigen_query_init (ClassInfo klas) {
-	praat_addAction1 (klas, 1, U"Get eigenvalue...", nullptr, 1, DO_Eigen_getEigenvalue);
-	praat_addAction1 (klas, 1, U"Get sum of eigenvalues...", nullptr, 1, DO_Eigen_getSumOfEigenvalues);
-	praat_addAction1 (klas, 1, U"Get number of eigenvectors", nullptr, 1, DO_Eigen_getNumberOfEigenvalues);
-	praat_addAction1 (klas, 1, U"Get eigenvector dimension", nullptr, 1, DO_Eigen_getDimension);
-	praat_addAction1 (klas, 1, U"Get eigenvector element...", nullptr, 1, DO_Eigen_getEigenvectorElement);
+	praat_addAction1 (klas, 1, U"Get eigenvalue...", nullptr, 1, REAL_Eigen_getEigenvalue);
+	praat_addAction1 (klas, 1, U"Get sum of eigenvalues...", nullptr, 1, REAL_Eigen_getSumOfEigenvalues);
+	praat_addAction1 (klas, 1, U"Get number of eigenvectors", nullptr, 1, INTEGER_Eigen_getNumberOfEigenvalues);
+	praat_addAction1 (klas, 1, U"Get eigenvector dimension", nullptr, 1, INTEGER_Eigen_getDimension);
+	praat_addAction1 (klas, 1, U"Get eigenvector element...", nullptr, 1, REAL_Eigen_getEigenvectorElement);
 }
 
 static void praat_Eigen_draw_init (ClassInfo klas) {
-	praat_addAction1 (klas, 0, U"Draw eigenvalues...", nullptr, 1, DO_Eigen_drawEigenvalues);
-	praat_addAction1 (klas, 0, U"Draw eigenvalues (scree)...", nullptr, praat_DEPTH_1 | praat_HIDDEN, DO_Eigen_drawEigenvalues_scree);
-	praat_addAction1 (klas, 0, U"Draw eigenvector...", nullptr, 1, DO_Eigen_drawEigenvector);
+	praat_addAction1 (klas, 0, U"Draw eigenvalues...", nullptr, 1,GRAPHICS_Eigen_drawEigenvalues);
+	praat_addAction1 (klas, 0, U"Draw eigenvalues (scree)...", U"*Draw eigenvalues...", praat_DEPRECATED_2010 | praat_DEPTH_1, GRAPHICS_Eigen_drawEigenvalues_scree);
+	praat_addAction1 (klas, 0, U"Draw eigenvector...", nullptr, 1, GRAPHICS_Eigen_drawEigenvector);
 }
 
 static void praat_Index_init (ClassInfo klas) {
-	praat_addAction1 (klas, 1, U"Get number of classes", nullptr, 0, DO_Index_getNumberOfClasses);
-	praat_addAction1 (klas, 1, U"To Permutation...", nullptr, 0, DO_Index_to_Permutation);
-	praat_addAction1 (klas, 1, U"Extract part...", nullptr, 0, DO_Index_extractPart);
+	praat_addAction1 (klas, 1, U"Get number of classes", nullptr, 0, INTEGER_Index_getNumberOfClasses);
+	praat_addAction1 (klas, 1, U"To Permutation...", nullptr, 0, NEW_Index_to_Permutation);
+	praat_addAction1 (klas, 1, U"Extract part...", nullptr, 0, NEW_Index_extractPart);
 }
 
 static void praat_BandFilterSpectrogram_draw_init (ClassInfo klas);
@@ -8762,65 +7053,46 @@ static void praat_BandFilterSpectrogram_draw_init (ClassInfo klas) {
 //	praat_addAction1 (klas, 0, U"Paint cells...", nullptr, 1, DO_FilterBank_paintCells);
 //	praat_addAction1 (klas, 0, U"Paint surface...", nullptr, 1, DO_FilterBank_paintSurface);
 	praat_addAction1 (klas, 0, U"-- frequency scales --", nullptr, 1, nullptr);
-	praat_addAction1 (klas, 0, U"Draw frequency scale...", nullptr, 1, DO_BandFilterSpectrogram_drawFrequencyScale);
-}
-
-void praat_Matrixft_query_init (ClassInfo klas);
-void praat_Matrixft_query_init (ClassInfo klas) {
-	praat_TimeFrameSampled_query_init (klas);
-	praat_addAction1 (klas, 1, U"Get time from column...", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getXofColumn);
-	praat_addAction1 (klas, 1, U"-- frequencies --", nullptr, praat_DEPTH_1, 0);
-	praat_addAction1 (klas, 1, U"Get lowest frequency", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getLowestFrequency);
-	praat_addAction1 (klas, 1, U"Get highest frequency", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getHighestFrequency);
-	praat_addAction1 (klas, 1, U"Get number of frequencies", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getNumberOfFrequencies);
-	praat_addAction1 (klas, 1, U"Get frequency distance", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getFrequencyDistance);
-	praat_addAction1 (klas, 1, U"Get frequency from row...", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getFrequencyOfRow);
-	praat_addAction1 (klas, 1, U"-- get value --", nullptr, praat_DEPTH_1, 0);
-	praat_addAction1 (klas, 1, U"Get value in cell...", nullptr, praat_DEPTH_1, DO_BandFilterSpectrogram_getValueInCell);
-}
-
-void praat_Matrixtype_query_init (ClassInfo klas);
-void praat_Matrixtype_query_init (ClassInfo klas) {
-	praat_TimeFrameSampled_query_init (klas);
-	praat_addAction1 (klas, 1, U"Get time from column...", nullptr, praat_DEPTH_1, DO_FilterBank_getXofColumn);
-	praat_addAction1 (klas, 1, U"-- frequencies --", nullptr, praat_DEPTH_1, 0);
-	praat_addAction1 (klas, 1, U"Get lowest frequency", nullptr, praat_DEPTH_1, DO_FilterBank_getLowestFrequency);
-	praat_addAction1 (klas, 1, U"Get highest frequency", nullptr, praat_DEPTH_1, DO_FilterBank_getHighestFrequency);
-	praat_addAction1 (klas, 1, U"Get number of frequencies", nullptr, praat_DEPTH_1, DO_FilterBank_getNumberOfFrequencies);
-	praat_addAction1 (klas, 1, U"Get frequency distance", nullptr, praat_DEPTH_1, DO_FilterBank_getFrequencyDistance);
-	praat_addAction1 (klas, 1, U"Get frequency from row...", nullptr, praat_DEPTH_1, DO_FilterBank_getFrequencyOfRow);
-	praat_addAction1 (klas, 1, U"-- get value --", nullptr, praat_DEPTH_1, 0);
-	praat_addAction1 (klas, 1, U"Get value in cell...", nullptr, praat_DEPTH_1, DO_FilterBank_getValueInCell);
+	praat_addAction1 (klas, 0, U"Draw frequency scale...", nullptr, 1, GRAPHICS_BandFilterSpectrogram_drawFrequencyScale);
 }
 
 static void praat_FilterBank_query_init (ClassInfo klas);
 static void praat_FilterBank_query_init (ClassInfo klas) {
 	praat_addAction1 (klas, 0, QUERY_BUTTON, nullptr, 0, 0);
-	praat_Matrixtype_query_init (klas);
+	praat_TimeFrameSampled_query_init (klas);
+	praat_addAction1 (klas, 1, U"Get time from column...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getXofColumn);
+	praat_addAction1 (klas, 1, U"-- frequencies --", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, 0);
+	praat_addAction1 (klas, 1, U"Get lowest frequency", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getLowestFrequency);
+	praat_addAction1 (klas, 1, U"Get highest frequency", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getHighestFrequency);
+	praat_addAction1 (klas, 1, U"Get number of frequencies", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, INTEGER_FilterBank_getNumberOfFrequencies);
+	praat_addAction1 (klas, 1, U"Get frequency distance", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getFrequencyDistance);
+	praat_addAction1 (klas, 1, U"Get frequency from row...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getFrequencyOfRow);
+	praat_addAction1 (klas, 1, U"-- get value --", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, 0);
+	praat_addAction1 (klas, 1, U"Get value in cell...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getValueInCell);
 	praat_addAction1 (klas, 0, U"-- frequency scales --", nullptr, praat_DEPTH_1, 0);
-	praat_addAction1 (klas, 1, U"Get frequency in Hertz...", nullptr, praat_DEPTH_1, DO_FilterBank_getFrequencyInHertz);
-	praat_addAction1 (klas, 1, U"Get frequency in Bark...", nullptr, praat_DEPTH_1, DO_FilterBank_getFrequencyInBark);
-	praat_addAction1 (klas, 1, U"Get frequency in mel...", nullptr, praat_DEPTH_1, DO_FilterBank_getFrequencyInMel);
+	praat_addAction1 (klas, 1, U"Get frequency in Hertz...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getFrequencyInHertz);
+	praat_addAction1 (klas, 1, U"Get frequency in Bark...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getFrequencyInBark);
+	praat_addAction1 (klas, 1, U"Get frequency in mel...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, REAL_FilterBank_getFrequencyInMel);
 }
 
 static void praat_FilterBank_modify_init (ClassInfo klas);
 static void praat_FilterBank_modify_init (ClassInfo klas) {
 	// praat_addAction1 (klas, 0, MODIFY_BUTTON, nullptr, 0, 0); 
-	praat_addAction1 (klas, 0, U"Equalize intensities...", nullptr, praat_DEPTH_1, DO_FilterBank_equalizeIntensities);
+	praat_addAction1 (klas, 0, U"Equalize intensities...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, MODIFY_FilterBank_equalizeIntensities);
 }
 
 static void praat_FilterBank_draw_init (ClassInfo klas);
 static void praat_FilterBank_draw_init (ClassInfo klas) {
 	// praat_addAction1 (klas, 0, DRAW_BUTTON, 0, 0, 0);
-	praat_addAction1 (klas, 0, U"Draw filters...", nullptr, praat_DEPTH_1, DO_FilterBank_drawFilters);
-	praat_addAction1 (klas, 0, U"Draw one contour...", nullptr, praat_DEPTH_1, DO_FilterBank_drawOneContour);
-	praat_addAction1 (klas, 0, U"Draw contours...", nullptr, praat_DEPTH_1, DO_FilterBank_drawContours);
-	praat_addAction1 (klas, 0, U"Paint image...", nullptr, praat_DEPTH_1, DO_FilterBank_paintImage);
-	praat_addAction1 (klas, 0, U"Paint contours...", nullptr, praat_DEPTH_1, DO_FilterBank_paintContours);
-	praat_addAction1 (klas, 0, U"Paint cells...", nullptr, praat_DEPTH_1, DO_FilterBank_paintCells);
-	praat_addAction1 (klas, 0, U"Paint surface...", nullptr, praat_DEPTH_1, DO_FilterBank_paintSurface);
-	praat_addAction1 (klas, 0, U"-- frequency scales --", nullptr, praat_DEPTH_1, 0);
-	praat_addAction1 (klas, 0, U"Draw frequency scales...", nullptr, praat_DEPTH_1, DO_FilterBank_drawFrequencyScales);
+	praat_addAction1 (klas, 0, U"Draw filters...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_drawFilters);
+	praat_addAction1 (klas, 0, U"Draw one contour...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_drawOneContour);
+	praat_addAction1 (klas, 0, U"Draw contours...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_drawContours);
+	praat_addAction1 (klas, 0, U"Paint image...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_paintImage);
+	praat_addAction1 (klas, 0, U"Paint contours...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_paintContours);
+	praat_addAction1 (klas, 0, U"Paint cells...", nullptr,praat_DEPRECATED_2014 |  praat_DEPTH_1, GRAPHICS_FilterBank_paintCells);
+	praat_addAction1 (klas, 0, U"Paint surface...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_paintSurface);
+	praat_addAction1 (klas, 0, U"-- frequency scales --", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, 0);
+	praat_addAction1 (klas, 0, U"Draw frequency scales...", nullptr, praat_DEPRECATED_2014 | praat_DEPTH_1, GRAPHICS_FilterBank_drawFrequencyScales);
 }
 
 static void praat_FilterBank_all_init (ClassInfo klas);
@@ -8828,29 +7100,29 @@ static void praat_FilterBank_all_init (ClassInfo klas) {
 	praat_FilterBank_draw_init (klas);
 	praat_FilterBank_query_init (klas);
 	praat_FilterBank_modify_init (klas);
-	praat_addAction1 (klas, 0, U"To Intensity", nullptr, praat_HIDDEN, DO_FilterBank_to_Intensity);
-	praat_addAction1 (klas, 0, U"To Matrix", nullptr, praat_HIDDEN, DO_FilterBank_to_Matrix);
-	praat_addAction1 (klas, 2, U"Cross-correlate...", nullptr, praat_HIDDEN, DO_FilterBanks_crossCorrelate);
-	praat_addAction1 (klas, 2, U"Convolve...", nullptr, praat_HIDDEN, DO_FilterBanks_convolve);
+	praat_addAction1 (klas, 0, U"To Intensity", nullptr, praat_DEPRECATED_2014, NEW_FilterBank_to_Intensity);
+	praat_addAction1 (klas, 0, U"To Matrix", nullptr, praat_DEPRECATED_2014, NEW_FilterBank_to_Matrix);
+	praat_addAction1 (klas, 2, U"Cross-correlate...", nullptr, praat_DEPRECATED_2014, NEW1_FilterBanks_crossCorrelate);
+	praat_addAction1 (klas, 2, U"Convolve...", nullptr, praat_DEPRECATED_2014, NEW1_FilterBanks_convolve);
 }
 
 static void praat_FunctionTerms_init (ClassInfo klas) {
 	praat_addAction1 (klas, 0, DRAW_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (klas, 0, U"Draw...", nullptr, 1, DO_FunctionTerms_draw);
-	praat_addAction1 (klas, 0, U"Draw basis function...", nullptr, 1, DO_FunctionTerms_drawBasisFunction);
+	praat_addAction1 (klas, 0, U"Draw...", nullptr, 1, GRAPHICS_FunctionTerms_draw);
+	praat_addAction1 (klas, 0, U"Draw basis function...", nullptr, 1, GRAPHICS_FunctionTerms_drawBasisFunction);
 	praat_addAction1 (klas, 0, QUERY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (klas, 1, U"Get number of coefficients", nullptr, 1, DO_FunctionTerms_getNumberOfCoefficients);
-	praat_addAction1 (klas, 1, U"Get coefficient...", nullptr, 1, DO_FunctionTerms_getCoefficient);
-	praat_addAction1 (klas, 1, U"Get degree", nullptr, 1, DO_FunctionTerms_getDegree);
+	praat_addAction1 (klas, 1, U"Get number of coefficients", nullptr, 1, INTEGER_FunctionTerms_getNumberOfCoefficients);
+	praat_addAction1 (klas, 1, U"Get coefficient...", nullptr, 1, REAL_FunctionTerms_getCoefficient);
+	praat_addAction1 (klas, 1, U"Get degree", nullptr, 1, INTEGER_FunctionTerms_getDegree);
 	praat_addAction1 (klas, 0, U"-- function specifics --", nullptr, 1, 0);
-	praat_addAction1 (klas, 1, U"Get value...", nullptr, 1, DO_FunctionTerms_evaluate);
-	praat_addAction1 (klas, 1, U"Get minimum...", nullptr, 1, DO_FunctionTerms_getMinimum);
-	praat_addAction1 (klas, 1, U"Get x of minimum...", nullptr, 1, DO_FunctionTerms_getXOfMinimum);
-	praat_addAction1 (klas, 1, U"Get maximum...", nullptr, 1, DO_FunctionTerms_getMaximum);
-	praat_addAction1 (klas, 1, U"Get x of maximum...", nullptr, 1, DO_FunctionTerms_getXOfMaximum);
+	praat_addAction1 (klas, 1, U"Get value...", nullptr, 1, REAL_FunctionTerms_evaluate);
+	praat_addAction1 (klas, 1, U"Get minimum...", nullptr, 1, REAL_FunctionTerms_getMinimum);
+	praat_addAction1 (klas, 1, U"Get x of minimum...", nullptr, 1, REAL_FunctionTerms_getXOfMinimum);
+	praat_addAction1 (klas, 1, U"Get maximum...", nullptr, 1, REAL_FunctionTerms_getMaximum);
+	praat_addAction1 (klas, 1, U"Get x of maximum...", nullptr, 1, REAL_FunctionTerms_getXOfMaximum);
 	praat_addAction1 (klas, 0, U"Modify -", nullptr, 0, 0);
-	praat_addAction1 (klas, 1, U"Set domain...", nullptr, 1, DO_FunctionTerms_setDomain);
-	praat_addAction1 (klas, 1, U"Set coefficient...", nullptr, 1, DO_FunctionTerms_setCoefficient);
+	praat_addAction1 (klas, 1, U"Set domain...", nullptr, 1, MODIFY_FunctionTerms_setDomain);
+	praat_addAction1 (klas, 1, U"Set coefficient...", nullptr, 1, MODIFY_FunctionTerms_setCoefficient);
 	praat_addAction1 (klas, 0, U"Analyse", nullptr, 0, 0);
 }
 
@@ -8858,87 +7130,85 @@ static void praat_FunctionTerms_init (ClassInfo klas) {
 
 void praat_BandFilterSpectrogram_query_init (ClassInfo klas) {
 	praat_TimeFrameSampled_query_init (klas);
-	praat_addAction1 (klas, 1, U"Get time from column...", nullptr, 1, DO_BandFilterSpectrogram_getXofColumn);
+	praat_addAction1 (klas, 1, U"Get time from column...", nullptr, 1, REAL_BandFilterSpectrogram_getXofColumn);
 	praat_addAction1 (klas, 1, U"-- frequencies --", nullptr, 1, 0);
-	praat_addAction1 (klas, 1, U"Get lowest frequency", nullptr, 1, DO_BandFilterSpectrogram_getLowestFrequency);
-	praat_addAction1 (klas, 1, U"Get highest frequency", nullptr, 1, DO_BandFilterSpectrogram_getHighestFrequency);
-	praat_addAction1 (klas, 1, U"Get number of frequencies", nullptr, 1, DO_BandFilterSpectrogram_getNumberOfFrequencies);
-	praat_addAction1 (klas, 1, U"Get frequency distance", nullptr, 1, DO_BandFilterSpectrogram_getFrequencyDistance);
-	praat_addAction1 (klas, 1, U"Get frequency from row...", nullptr, 1, DO_BandFilterSpectrogram_getFrequencyOfRow);
+	praat_addAction1 (klas, 1, U"Get lowest frequency", nullptr, 1, REAL_BandFilterSpectrogram_getLowestFrequency);
+	praat_addAction1 (klas, 1, U"Get highest frequency", nullptr, 1, REAL_BandFilterSpectrogram_getHighestFrequency);
+	praat_addAction1 (klas, 1, U"Get number of frequencies", nullptr, 1, INTEGER_BandFilterSpectrogram_getNumberOfFrequencies);
+	praat_addAction1 (klas, 1, U"Get frequency distance", nullptr, 1, REAL_BandFilterSpectrogram_getFrequencyDistance);
+	praat_addAction1 (klas, 1, U"Get frequency from row...", nullptr, 1, REAL_BandFilterSpectrogram_getFrequencyOfRow);
 	praat_addAction1 (klas, 1, U"-- get value --", nullptr, 1, 0);
-	praat_addAction1 (klas, 1, U"Get value in cell...", nullptr, 1, DO_BandFilterSpectrogram_getValueInCell);
+	praat_addAction1 (klas, 1, U"Get value in cell...", nullptr, 1, REAL_BandFilterSpectrogram_getValueInCell);
 }
 
-void praat_PatternList_query_init (ClassInfo klas) {
+static void praat_PatternList_query_init (ClassInfo klas) {
 	praat_addAction1 (klas, 0, QUERY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (klas, 1, U"Get number of patterns", nullptr, 1, DO_PatternList_getNumberOfPatterns);
-	praat_addAction1 (klas, 1, U"Get pattern size", nullptr, 1, DO_PatternList_getPatternSize);
-	praat_addAction1 (klas, 1, U"Get value...", nullptr, 1, DO_PatternList_getValue);
+	praat_addAction1 (klas, 1, U"Get number of patterns", nullptr, 1, INTEGER_PatternList_getNumberOfPatterns);
+	praat_addAction1 (klas, 1, U"Get pattern size", nullptr, 1, INTEGER_PatternList_getPatternSize);
+	praat_addAction1 (klas, 1, U"Get value...", nullptr, 1, REAL_PatternList_getValue);
 
 }
 
 static void praat_Spline_init (ClassInfo klas) {
 	praat_FunctionTerms_init (klas);
-	praat_addAction1 (klas, 0, U"Draw knots...", U"Draw basis function...", 1, DO_Spline_drawKnots);
-	praat_addAction1 (klas, 1, U"Get order", U"Get degree", 1, DO_Spline_getOrder);
-	praat_addAction1 (klas, 1, U"Scale x...", U"Analyse",	0, DO_Spline_scaleX);
+	praat_addAction1 (klas, 0, U"Draw knots...", U"Draw basis function...", 1, GRAPHICS_Spline_drawKnots);
+	praat_addAction1 (klas, 1, U"Get order", U"Get degree", 1, INTEGER_Spline_getOrder);
+	praat_addAction1 (klas, 1, U"Scale x...", U"Analyse",	0, NEW_Spline_scaleX);
 }
 
 static void praat_SSCP_query_init (ClassInfo klas) {
 	praat_addAction1 (klas, 1, U"-- statistics --", U"Get value...", 1, 0);
-	praat_addAction1 (klas, 1, U"Get number of observations", U"-- statistics --", 1, DO_SSCP_getNumberOfObservations);
-	praat_addAction1 (klas, 1, U"Get degrees of freedom", U"Get number of observations", 1, DO_SSCP_getDegreesOfFreedom);
-	praat_addAction1 (klas, 1, U"Get centroid element...", U"Get degrees of freedom", 1, DO_SSCP_getCentroidElement);
-	praat_addAction1 (klas, 1, U"Get ln(determinant)", U"Get centroid element...", 1, DO_SSCP_getLnDeterminant);
+	praat_addAction1 (klas, 1, U"Get number of observations", U"-- statistics --", 1, INTEGER_SSCP_getNumberOfObservations);
+	praat_addAction1 (klas, 1, U"Get degrees of freedom", U"Get number of observations", 1, INTEGER_SSCP_getDegreesOfFreedom);
+	praat_addAction1 (klas, 1, U"Get centroid element...", U"Get degrees of freedom", 1, REAL_SSCP_getCentroidElement);
+	praat_addAction1 (klas, 1, U"Get ln(determinant)", U"Get centroid element...", 1, REAL_SSCP_getLnDeterminant);
 }
 
 static void praat_SSCP_extract_init (ClassInfo klas) {
-	praat_addAction1 (klas, 1, U"Extract centroid", EXTRACT_BUTTON, 1, DO_SSCP_extractCentroid);
+	praat_addAction1 (klas, 1, U"Extract centroid", EXTRACT_BUTTON, 1, NEW_SSCP_extractCentroid);
 }
 
-FORM (SSCP_setValue, U"Covariance: Set value", U"Covariance: Set value...")
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
-	REAL (U"New value", U"1.0")
+FORM (MODIFY_SSCP_setValue, U"Covariance: Set value", U"Covariance: Set value...") {
+	NATURALVAR (rowNumber, U"Row number", U"1")
+	NATURALVAR (columnNumber, U"Column number", U"1")
+	REALVAR (value, U"New value", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (SSCP);
-		SSCP_setValue (me, GET_INTEGER (U"Row number"), GET_INTEGER (U"Column number"), GET_REAL (U"New value"));
-	}
-END
+	MODIFY_EACH (SSCP)
+		SSCP_setValue (me, rowNumber, columnNumber, value);
+	MODIFY_EACH_END
+}
 
-FORM (SSCP_setCentroid, U"", 0)
-	NATURAL (U"Element number", U"1")
-	REAL (U"New value", U"1.0")
+FORM (MODIFY_SSCP_setCentroid, U"", nullptr) {
+	NATURALVAR (elementNumber, U"Element number", U"1")
+	REALVAR (value, U"New value", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (SSCP);
-		SSCP_setCentroid (me, GET_INTEGER (U"Element number"), GET_REAL (U"New value"));
-	}
-END
+	MODIFY_EACH (SSCP)
+		SSCP_setCentroid (me, elementNumber, value);
+	MODIFY_EACH_END
+}
 
 void praat_SSCP_as_TableOfReal_init (ClassInfo klas) {
 	praat_TableOfReal_init (klas);
 	praat_removeAction (klas, nullptr, nullptr, U"Set value...");
-	praat_addAction1 (klas, 1, U"Set centroid...", U"Formula...", 1, DO_SSCP_setCentroid);
-	praat_addAction1 (klas, 1, U"Set value...", U"Formula...", 1, DO_SSCP_setValue);
-	praat_addAction1 (klas, 0, U"To TableOfReal", U"To Matrix", 1, DO_TableOfReal_to_TableOfReal);
+	praat_addAction1 (klas, 1, U"Set centroid...", U"Formula...", 1, MODIFY_SSCP_setCentroid);
+	praat_addAction1 (klas, 1, U"Set value...", U"Formula...", 1, MODIFY_SSCP_setValue);
+	praat_addAction1 (klas, 0, U"To TableOfReal", U"To Matrix", 1, NEW_TableOfReal_to_TableOfReal);
 
 }
 
 void praat_TableOfReal_init2 (ClassInfo klas) {
 	praat_TableOfReal_init (klas);
-	praat_addAction1 (klas, 0, U"To TableOfReal", U"To Matrix", 1, DO_TableOfReal_to_TableOfReal);
+	praat_addAction1 (klas, 0, U"To TableOfReal", U"To Matrix", 1, NEW_TableOfReal_to_TableOfReal);
 }
 
 void praat_EditDistanceTable_as_TableOfReal_init (ClassInfo klas) {
 	praat_TableOfReal_init (klas);
-	praat_addAction1 (klas, 0, U"Set default costs...", U"Formula...", 1, DO_EditDistanceTable_setDefaultCosts);
+	praat_addAction1 (klas, 0, U"Set default costs...", U"Formula...", 1, MODIFY_EditDistanceTable_setDefaultCosts);
 	praat_removeAction (klas, nullptr, nullptr, U"Draw as numbers...");
-	praat_addAction1 (klas, 0, U"Draw...", U"Draw -", 1, DO_EditDistanceTable_draw);
-	praat_addAction1 (klas, 0, U"Draw edit operations", U"Draw...", 1, DO_EditDistanceTable_drawEditOperations);
+	praat_addAction1 (klas, 0, U"Draw...", U"Draw -", 1, GRAPHICS_EditDistanceTable_draw);
+	praat_addAction1 (klas, 0, U"Draw edit operations", U"Draw...", 1, GRAPHICS_EditDistanceTable_drawEditOperations);
 	praat_removeAction (klas, nullptr, nullptr, U"Draw as numbers if...");
 	praat_removeAction (klas, nullptr, nullptr, U"Draw as squares...");
 	praat_removeAction (klas, nullptr, nullptr, U"Draw vertical lines...");
@@ -8973,248 +7243,249 @@ void praat_uvafon_David_init () {
 
 	espeakdata_praat_init ();
 
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report floating point properties", U"Report integer properties", 0, DO_Praat_ReportFloatingPointProperties);
-	praat_addMenuCommand (U"Objects", U"Goodies", U"Get TukeyQ...", 0, praat_HIDDEN, DO_Praat_getTukeyQ);
-	praat_addMenuCommand (U"Objects", U"Goodies", U"Get invTukeyQ...", 0, praat_HIDDEN, DO_Praat_getInvTukeyQ);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Strings from espeak voices", U"Create Strings as directory list...", praat_DEPTH_1 + praat_HIDDEN, DO_Strings_createFromEspeakVoices);
-	praat_addMenuCommand (U"Objects", U"New", U"Create iris data set", U"Create TableOfReal...", 1, DO_New_CreateIrisDataset);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Permutation...", nullptr, 0, DO_Permutation_create);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report floating point properties", U"Report integer properties", 0, INFO_Praat_ReportFloatingPointProperties);
+	praat_addMenuCommand (U"Objects", U"Goodies", U"Get TukeyQ...", 0, praat_HIDDEN, REAL_Praat_getTukeyQ);
+	praat_addMenuCommand (U"Objects", U"Goodies", U"Get invTukeyQ...", 0, praat_HIDDEN, REAL_Praat_getInvTukeyQ);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Strings from espeak voices", U"Create Strings as directory list...", praat_DEPTH_1 + praat_HIDDEN, NEW1_Strings_createFromEspeakVoices);
+	praat_addMenuCommand (U"Objects", U"New", U"Create iris data set", U"Create TableOfReal...", 1, NEW1_CreateIrisDataset);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Permutation...", nullptr, 0, NEW_Permutation_create);
 	praat_addMenuCommand (U"Objects", U"New", U"Polynomial", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Polynomial...", nullptr, 1, DO_Polynomial_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Polynomial from product terms...", nullptr, 1, DO_Polynomial_createFromProducts);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Polynomial from real zeros...", nullptr, 1, DO_Polynomial_createFromZeros);
-	praat_addMenuCommand (U"Objects", U"New", U"Create LegendreSeries...", nullptr, 1, DO_LegendreSeries_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create ChebyshevSeries...", nullptr, 1, DO_ChebyshevSeries_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create MSpline...", nullptr, 1, DO_MSpline_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create ISpline...", nullptr, 1, DO_ISpline_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from gammatone...", U"Create Sound from tone complex...", 1, DO_Sound_createFromGammaTone);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from gamma-tone...", U"Create Sound from tone complex...", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_createFromGammaTone);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from Shepard tone...", U"Create Sound from gammatone...", 1, DO_Sound_createFromShepardTone);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from VowelEditor...", U"Create Sound from Shepard tone...", praat_DEPTH_1, DO_VowelEditor_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create SpeechSynthesizer...", U"Create Sound from VowelEditor...", praat_DEPTH_1, DO_SpeechSynthesizer_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create formant table (Pols & Van Nierop 1973)", U"Create Table...", 1, DO_Table_createFromPolsVanNieropData);
-	praat_addMenuCommand (U"Objects", U"New", U"Create formant table (Peterson & Barney 1952)", U"Create Table...", 1, DO_Table_createFromPetersonBarneyData);
-	praat_addMenuCommand (U"Objects", U"New", U"Create formant table (Weenink 1985)", U"Create formant table (Peterson & Barney 1952)", 1, DO_Table_createFromWeeninkData);
-	praat_addMenuCommand (U"Objects", U"New", U"Create H1H2 table (Esposito 2006)", U"Create formant table (Weenink 1985)", praat_DEPTH_1+ praat_HIDDEN, DO_Table_createFromEspositoData);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Table (Ganong 1980)", U"Create H1H2 table (Esposito 2006)", praat_DEPTH_1+ praat_HIDDEN, DO_Table_createFromGanongData);
-	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal (Pols 1973)...", U"Create TableOfReal...", 1, DO_TableOfReal_createFromPolsData_50males);
-	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal (Van Nierop 1973)...", U"Create TableOfReal (Pols 1973)...", 1, DO_TableOfReal_createFromVanNieropData_25females);
-	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal (Weenink 1985)...", U"Create TableOfReal (Van Nierop 1973)...", 1, DO_TableOfReal_createFromWeeninkData);
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple Confusion...", U"Create TableOfReal (Weenink 1985)...", 1, DO_Confusion_createSimple);
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple Covariance...", U"Create simple Confusion...", 1, DO_Covariance_createSimple);
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple Correlation...", U"Create simple Covariance...", 1, DO_Correlation_createSimple);
-	praat_addMenuCommand (U"Objects", U"New", U"Create empty EditCostsTable...", U"Create simple Covariance...", 1, DO_EditCostsTable_createEmpty);
-
-	praat_addMenuCommand (U"Objects", U"New", U"Create KlattTable example", U"Create TableOfReal (Weenink 1985)...", praat_DEPTH_1 + praat_HIDDEN, DO_KlattTable_createExample);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as characters...", U"Create TextGrid...", praat_HIDDEN, DO_Strings_createAsCharacters);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as tokens...", U"Create TextGrid...", praat_HIDDEN, DO_Strings_createAsTokens);
-
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple Polygon...", nullptr, praat_HIDDEN, DO_Polygon_createSimple);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Polygon (random vertices)...", nullptr, praat_HIDDEN, DO_Polygon_createFromRandomVertices);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Polynomial...", nullptr, 1, NEW1_Polynomial_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Polynomial from product terms...", nullptr, 1, NEW1_Polynomial_createFromProducts);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Polynomial from real zeros...", nullptr, 1, NEW1_Polynomial_createFromZeros);
+	praat_addMenuCommand (U"Objects", U"New", U"Create LegendreSeries...", nullptr, 1, NEW1_LegendreSeries_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create ChebyshevSeries...", nullptr, 1, NEW1_ChebyshevSeries_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create MSpline...", nullptr, 1, NEW_MSpline_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create ISpline...", nullptr, 1, NEW1_ISpline_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Sound as gammatone...", U"Create Sound as tone complex...", 1, NEW1_Sound_createAsGammaTone);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from gammatone...", U"*Create Sound as gammatone...", praat_DEPTH_1 | praat_DEPRECATED_2016, NEW1_Sound_createAsGammaTone);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Sound as Shepard tone...", U"Create Sound as gammatone...", praat_DEPTH_1, NEW_Sound_createAsShepardTone);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from Shepard tone...", U"*Create Sound as Shepard tone...", praat_DEPTH_1 | praat_DEPRECATED_2016, NEW_Sound_createAsShepardTone);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Sound from VowelEditor...", U"Create Sound as Shepard tone...", praat_DEPTH_1 | praat_NO_API, WINDOW_VowelEditor_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create SpeechSynthesizer...", U"Create Sound from VowelEditor...", praat_DEPTH_1, NEW1_SpeechSynthesizer_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create formant table (Pols & Van Nierop 1973)", U"Create Table...", 1, NEW1_Table_create_polsVanNierop1973);
+	praat_addMenuCommand (U"Objects", U"New", U"Create formant table (Peterson & Barney 1952)", U"Create Table...", 1, NEW1_Table_create_petersonBarney1952);
+	praat_addMenuCommand (U"Objects", U"New", U"Create formant table (Weenink 1985)", U"Create formant table (Peterson & Barney 1952)", 1, NEW1_Table_create_weenink1983);
+	praat_addMenuCommand (U"Objects", U"New", U"Create H1H2 table (Esposito 2006)", U"Create formant table (Weenink 1985)", praat_DEPTH_1+ praat_HIDDEN, NEW_Table_create_esposito2006);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Table (Ganong 1980)", U"Create H1H2 table (Esposito 2006)", praat_DEPTH_1+ praat_HIDDEN, NEW_Table_create_ganong1980);
+	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal (Pols 1973)...", U"Create TableOfReal...", 1, NEW1_TableOfReal_create_pols1973);
+	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal (Van Nierop 1973)...", U"Create TableOfReal (Pols 1973)...", 1, NEW_TableOfReal_create_vanNierop1973);
+	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal (Weenink 1985)...", U"Create TableOfReal (Van Nierop 1973)...", 1, NEW_TableOfReal_create_weenink1983);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple Confusion...", U"Create TableOfReal (Weenink 1985)...", 1, NEW1_Confusion_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple Covariance...", U"Create simple Confusion...", 1, NEW1_Covariance_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple Correlation...", U"Create simple Covariance...", 1, NEW1_Correlation_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create empty EditCostsTable...", U"Create simple Covariance...", 1, NEW_EditCostsTable_createEmpty);
+
+	praat_addMenuCommand (U"Objects", U"New", U"Create KlattTable example", U"Create TableOfReal (Weenink 1985)...", praat_DEPTH_1 + praat_HIDDEN, NEW1_KlattTable_createExample);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as characters...", U"Create TextGrid...", praat_HIDDEN, NEW1_Strings_createAsCharacters);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as tokens...", U"Create TextGrid...", praat_HIDDEN, NEW1_Strings_createAsTokens);
+
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple Polygon...", nullptr, praat_HIDDEN, NEW1_Polygon_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Polygon (random vertices)...", nullptr, praat_DEPRECATED_2016, NEW1_Polygon_createFromRandomPoints);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Polygon (random points)...", nullptr, praat_HIDDEN, NEW1_Polygon_createFromRandomPoints);
 	praat_addMenuCommand (U"Objects", U"New", U"FileInMemory", nullptr, praat_HIDDEN, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create FileInMemory...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_FileInMemory_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create FileInMemory...", nullptr, praat_DEPTH_1 + praat_HIDDEN, READ1_FileInMemory_create);
 		//praat_addMenuCommand (U"Objects", U"New", U"Create copy from FilesInMemory...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_FileInMemorySet_createCopyFromFileInMemorySet);
-		praat_addMenuCommand (U"Objects", U"New", U"Create copy from FileInMemorySet...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_FileInMemorySet_createCopyFromFileInMemorySet);
-		praat_addMenuCommand (U"Objects", U"New", U"Create FileInMemorySet from directory contents...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_FileInMemorySet_createFromDirectoryContents);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw 16-bit Little Endian file...", U"Read from special sound file", 1, DO_Sound_readFromRawFileLE);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw 16-bit Big Endian file...", U"Read Sound from raw 16-bit Little Endian file...", 1, DO_Sound_readFromRawFileBE);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read KlattTable from raw text file...", U"Read Matrix from raw text file...", praat_HIDDEN, DO_KlattTable_readFromRawTextFile);
+		praat_addMenuCommand (U"Objects", U"New", U"Create copy from FileInMemorySet...", nullptr, praat_DEPTH_1 + praat_HIDDEN, NEW_FileInMemorySet_createCopyFromFileInMemorySet);
+		praat_addMenuCommand (U"Objects", U"New", U"Create FileInMemorySet from directory contents...", nullptr, praat_DEPTH_1 + praat_HIDDEN, NEW_FileInMemorySet_createFromDirectoryContents);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw 16-bit Little Endian file...", U"Read from special sound file", 1, READ1_Sound_readFromRawFileLE);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw 16-bit Big Endian file...", U"Read Sound from raw 16-bit Little Endian file...", 1, READ1_Sound_readFromRawFileBE);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read KlattTable from raw text file...", U"Read Matrix from raw text file...", praat_HIDDEN, READ1_KlattTable_readFromRawTextFile);
 
 	praat_addAction1 (classActivationList, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classActivationList, 0, U"Formula...", nullptr, 0, DO_ActivationList_formula);
+	praat_addAction1 (classActivationList, 0, U"Formula...", nullptr, 0, MODIFY_ActivationList_formula);
 	praat_addAction1 (classActivationList, 0, U"Hack", nullptr, 0, nullptr);
-	praat_addAction1 (classActivationList, 0, U"To Matrix", nullptr, 0, DO_ActivationList_to_Matrix);
-	praat_addAction1 (classActivationList, 0, U"To PatternList", nullptr, 0, DO_ActivationList_to_PatternList);
+	praat_addAction1 (classActivationList, 0, U"To Matrix", nullptr, 0, NEW_ActivationList_to_Matrix);
+	praat_addAction1 (classActivationList, 0, U"To PatternList", nullptr, 0, NEW_ActivationList_to_PatternList);
 
-	praat_addAction2 (classActivationList, 1, classCategories, 1, U"To TableOfReal", nullptr, 0, DO_Matrix_Categories_to_TableOfReal);
+	praat_addAction2 (classActivationList, 1, classCategories, 1, U"To TableOfReal", nullptr, 0, NEW1_ActivationList_Categories_to_TableOfReal);
 
-	praat_addAction1 (classBarkFilter, 0, U"BarkFilter help", nullptr, 0, DO_BarkFilter_help);
+	praat_addAction1 (classBarkFilter, 0, U"BarkFilter help", nullptr, 0, HELP_BarkFilter_help);
 	praat_FilterBank_all_init (classBarkFilter);	// deprecated 2014
-	praat_addAction1 (classBarkFilter, 0, U"Draw spectrum (slice)...", U"Draw filters...", praat_DEPTH_1, DO_BarkFilter_drawSpectrum);	// deprecated 2014
-	praat_addAction1 (classBarkFilter, 1, U"Draw filter functions...", U"Draw filters...", praat_DEPTH_1, DO_BarkFilter_drawSekeyHansonFilterFunctions);	// deprecated 2014
-	praat_addAction1 (classBarkFilter, 0, U"Paint...", U"Draw filters...", praat_DEPTH_1, DO_BarkFilter_paint);	// deprecated 2014
-	praat_addAction1 (classBarkFilter, 0, U"To BarkSpectrogram", nullptr, 0, DO_BarkFilter_to_BarkSpectrogram);
+	praat_addAction1 (classBarkFilter, 0, U"Draw spectrum (slice)...", U"Draw filters...", praat_DEPRECATED_2014, GRAPHICS_BarkFilter_drawSpectrum);	// deprecated 2014
+	praat_addAction1 (classBarkFilter, 1, U"Draw filter functions...", U"Draw filters...", praat_DEPRECATED_2014, GRAPHICS_BarkFilter_drawSekeyHansonFilterFunctions);	// deprecated 2014
+	praat_addAction1 (classBarkFilter, 0, U"Paint...", U"Draw filters...", praat_DEPTH_1, GRAPHICS_BarkFilter_paint);	// deprecated 2014
+	praat_addAction1 (classBarkFilter, 0, U"To BarkSpectrogram", nullptr, 0, NEW_BarkFilter_to_BarkSpectrogram);
 
-	praat_addAction1 (classBarkSpectrogram, 0, U"BarkSpectrogram help", nullptr, 0, DO_BarkSpectrogram_help);
+	praat_addAction1 (classBarkSpectrogram, 0, U"BarkSpectrogram help", nullptr, 0, HELP_BarkSpectrogram_help);
 	praat_BandFilterSpectrogram_draw_init (classBarkSpectrogram);
-	praat_addAction1 (classBarkSpectrogram, 0, U"Paint image...", nullptr, 1, DO_BarkSpectrogram_paintImage);
-	praat_addAction1 (classBarkSpectrogram, 0, U"Draw Sekey-Hanson auditory filters...", nullptr, 1, DO_BarkSpectrogram_drawSekeyHansonAuditoryFilters);
-	praat_addAction1 (classBarkSpectrogram, 0, U"Draw spectrum at nearest time slice...", nullptr, 1, DO_BarkSpectrogram_drawSpectrumAtNearestTimeSlice);
+	praat_addAction1 (classBarkSpectrogram, 0, U"Paint image...", nullptr, 1, GRAPHICS_BarkSpectrogram_paintImage);
+	praat_addAction1 (classBarkSpectrogram, 0, U"Draw Sekey-Hanson auditory filters...", nullptr, 1, GRAPHICS_BarkSpectrogram_drawSekeyHansonAuditoryFilters);
+	praat_addAction1 (classBarkSpectrogram, 0, U"Draw spectrum at nearest time slice...", nullptr, 1, GRAPHICS_BarkSpectrogram_drawSpectrumAtNearestTimeSlice);
 	praat_addAction1 (classBarkSpectrogram, 0, QUERY_BUTTON, nullptr, 0, nullptr);
 	praat_BandFilterSpectrogram_query_init (classBarkSpectrogram);
-	praat_addAction1 (classBarkSpectrogram, 0, U"Equalize intensities...", nullptr, 0, DO_BandFilterSpectrogram_equalizeIntensities);
-	praat_addAction1 (classBarkSpectrogram, 0, U"To Intensity", nullptr, 0, DO_BandFilterSpectrogram_to_Intensity);
-	praat_addAction1 (classBarkSpectrogram, 0, U"To Matrix...", nullptr, 0, DO_BandFilterSpectrogram_to_Matrix);
-	praat_addAction1 (classBarkSpectrogram, 2, U"Cross-correlate...", nullptr, 0, DO_BandFilterSpectrograms_crossCorrelate);
-	praat_addAction1 (classBarkSpectrogram, 2, U"Convolve...", nullptr, 0, DO_BandFilterSpectrograms_convolve);
+	praat_addAction1 (classBarkSpectrogram, 0, U"Equalize intensities...", nullptr, 0, MODIFY_BandFilterSpectrogram_equalizeIntensities);
+	praat_addAction1 (classBarkSpectrogram, 0, U"To Intensity", nullptr, 0, NEW_BandFilterSpectrogram_to_Intensity);
+	praat_addAction1 (classBarkSpectrogram, 0, U"To Matrix...", nullptr, 0, NEW_BandFilterSpectrogram_to_Matrix);
+	praat_addAction1 (classBarkSpectrogram, 2, U"Cross-correlate...", nullptr, 0, NEW1_BandFilterSpectrograms_crossCorrelate);
+	praat_addAction1 (classBarkSpectrogram, 2, U"Convolve...", nullptr, 0, NEW1_BandFilterSpectrograms_convolve);
 	
 	
-	praat_addAction1 (classCategories, 0, U"View & Edit", nullptr, 0, DO_Categories_edit);
-	praat_addAction1 (classCategories, 0, U"Edit", nullptr, praat_HIDDEN, DO_Categories_edit); // deprecated 2015
+	praat_addAction1 (classCategories, 0, U"View & Edit", nullptr, praat_NO_API, WINDOW_Categories_edit);
+	praat_addAction1 (classCategories, 0,   U"Edit", U"*View & Edit", praat_DEPRECATED_2015 | praat_NO_API, WINDOW_Categories_edit);
 	praat_addAction1 (classCategories, 0, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction1 (classCategories, 1, U"Get number of categories", QUERY_BUTTON, 1, DO_Categories_getNumberOfCategories);
-	praat_addAction1 (classCategories, 2, U"Get difference", QUERY_BUTTON, praat_HIDDEN | praat_DEPTH_1, DO_Categories_difference);
-	praat_addAction1 (classCategories, 2, U"Get number of differences", QUERY_BUTTON, 1, DO_Categories_getNumberOfDifferences);
-	praat_addAction1 (classCategories, 2, U"Get fraction different", QUERY_BUTTON, 1, DO_Categories_getFractionDifferent);
+	praat_addAction1 (classCategories, 1, U"Get number of categories", QUERY_BUTTON, 1, INTEGER_Categories_getNumberOfCategories);
+	praat_addAction1 (classCategories, 2, U"Get difference", QUERY_BUTTON, praat_HIDDEN | praat_DEPTH_1, INTEGER_Categories_difference);
+	praat_addAction1 (classCategories, 2, U"Get number of differences", QUERY_BUTTON, 1, INTEGER_Categories_getNumberOfDifferences);
+	praat_addAction1 (classCategories, 2, U"Get fraction different", QUERY_BUTTON, 1, REAL_Categories_getFractionDifferent);
 	praat_addAction1 (classCategories, 0, MODIFY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction1 (classCategories, 1, U"Append category...", MODIFY_BUTTON, 1, DO_Categories_append);
-	praat_addAction1 (classCategories, 1, U"Append 1 category...", U"Append category...", praat_HIDDEN | praat_DEPTH_1, DO_Categories_append);
+	praat_addAction1 (classCategories, 1, U"Append category...", MODIFY_BUTTON, 1, MODIFY_Categories_append);
+	praat_addAction1 (classCategories, 1, U"Append 1 category...", U"Append category...", praat_HIDDEN | praat_DEPTH_1, MODIFY_Categories_append);
 	praat_addAction1 (classCategories, 0, U"Extract", nullptr, 0, nullptr);
-	praat_addAction1 (classCategories, 0, U"To unique Categories", nullptr, 0, DO_Categories_selectUniqueItems);
+	praat_addAction1 (classCategories, 0, U"To unique Categories", nullptr, 0, NEW_Categories_selectUniqueItems);
 	praat_addAction1 (classCategories, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classCategories, 2, U"To Confusion", nullptr, 0, DO_Categories_to_Confusion);
+	praat_addAction1 (classCategories, 2, U"To Confusion", nullptr, 0, NEW_Categories_to_Confusion);
 	praat_addAction1 (classCategories, 0, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction1 (classCategories, 2, U"Join", nullptr, 0, DO_Categories_join);
-	praat_addAction1 (classCategories, 0, U"Permute items", nullptr, 0, DO_Categories_permuteItems);
-	praat_addAction1 (classCategories, 0, U"To Strings", nullptr, 0, DO_Categories_to_Strings);
+	praat_addAction1 (classCategories, 2, U"Join", nullptr, 0, NEW1_Categories_join);
+	praat_addAction1 (classCategories, 0, U"Permute items", nullptr, 0, NEW_Categories_permuteItems);
+	praat_addAction1 (classCategories, 0, U"To Strings", nullptr, 0, NEW_Categories_to_Strings);
 
-	praat_addAction1 (classChebyshevSeries, 0, U"ChebyshevSeries help", nullptr, 0, DO_ChebyshevSeries_help);
+	praat_addAction1 (classChebyshevSeries, 0, U"ChebyshevSeries help", nullptr, 0, HELP_ChebyshevSeries_help);
 	praat_FunctionTerms_init (classChebyshevSeries);
-	praat_addAction1 (classChebyshevSeries, 0, U"To Polynomial", U"Analyse", 0, DO_ChebyshevSeries_to_Polynomial);
-
-	praat_addAction1 (classCCA, 1, U"Draw eigenvector...", nullptr, 0, DO_CCA_drawEigenvector);
-	praat_addAction1 (classCCA, 1, U"Get number of correlations", nullptr, 0, DO_CCA_getNumberOfCorrelations);
-	praat_addAction1 (classCCA, 1, U"Get correlation...", nullptr, 0, DO_CCA_getCorrelationCoefficient);
-	praat_addAction1 (classCCA, 1, U"Get eigenvector element...", nullptr, 0, DO_CCA_getEigenvectorElement);
-	praat_addAction1 (classCCA, 1, U"Get zero correlation probability...", nullptr, 0, DO_CCA_getZeroCorrelationProbability);
-
-	praat_addAction2 (classCCA, 1, classTableOfReal, 1, U"To TableOfReal (scores)...", nullptr, 0, DO_CCA_and_TableOfReal_scores);
-	praat_addAction2 (classCCA, 1, classTableOfReal, 1, U"To TableOfReal (loadings)", nullptr, 0, DO_CCA_and_TableOfReal_factorLoadings);
-	praat_addAction2 (classCCA, 1, classTableOfReal, 1, U"Predict...", nullptr, 0, DO_CCA_and_TableOfReal_predict);
-	praat_addAction2 (classCCA, 1, classCorrelation, 1, U"To TableOfReal (loadings)", nullptr, 0, DO_CCA_and_Correlation_factorLoadings);
-	praat_addAction2 (classCCA, 1, classCorrelation, 1, U"Get variance fraction...", nullptr, 0, DO_CCA_and_Correlation_getVarianceFraction);
-	praat_addAction2 (classCCA, 1, classCorrelation, 1, U"Get redundancy (sl)...", nullptr, 0, DO_CCA_and_Correlation_getRedundancy_sl);
+	praat_addAction1 (classChebyshevSeries, 0, U"To Polynomial", U"Analyse", 0, NEW_ChebyshevSeries_to_Polynomial);
+
+	praat_addAction1 (classCCA, 1, U"CCA help", nullptr, 0, HELP_CCA_help);
+	praat_addAction1 (classCCA, 1, U"Draw eigenvector...", nullptr, 0, GRAPHICS_CCA_drawEigenvector);
+	praat_addAction1 (classCCA, 1, U"Get number of correlations", nullptr, 0, INTEGER_CCA_getNumberOfCorrelations);
+	praat_addAction1 (classCCA, 1, U"Get correlation...", nullptr, 0, REAL_CCA_getCorrelationCoefficient);
+	praat_addAction1 (classCCA, 1, U"Get eigenvector element...", nullptr, 0, REAL_CCA_getEigenvectorElement);
+	praat_addAction1 (classCCA, 1, U"Get zero correlation probability...", nullptr, 0, REAL_CCA_getZeroCorrelationProbability);
+	praat_addAction1 (classCCA, 1, U"Extract Eigen...", nullptr, 0, NEW_CCA_extractEigen);
+
+	praat_addAction2 (classCCA, 1, classTableOfReal, 1, U"To TableOfReal (scores)...", nullptr, 0, NEW_CCA_and_TableOfReal_scores);
+	praat_addAction2 (classCCA, 1, classTableOfReal, 1, U"To TableOfReal (loadings)", nullptr, 0, NEW_CCA_and_TableOfReal_factorLoadings);
+	praat_addAction2 (classCCA, 1, classTableOfReal, 1, U"Predict...", nullptr, 0, NEW1_CCA_and_TableOfReal_predict);
+	praat_addAction2 (classCCA, 1, classCorrelation, 1, U"To TableOfReal (loadings)", nullptr, 0, NEW1_CCA_and_Correlation_factorLoadings);
+	praat_addAction2 (classCCA, 1, classCorrelation, 1, U"Get variance fraction...", nullptr, 0, REAL_CCA_and_Correlation_getVarianceFraction);
+	praat_addAction2 (classCCA, 1, classCorrelation, 1, U"Get redundancy (sl)...", nullptr, 0, REAL_CCA_and_Correlation_getRedundancy_sl);
 	
 	
-	praat_addAction1 (classComplexSpectrogram, 0, U"ComplexSpectrogram help", nullptr, 0, DO_ComplexSpectrogram_help);
+	praat_addAction1 (classComplexSpectrogram, 0, U"ComplexSpectrogram help", nullptr, 0, HELP_ComplexSpectrogram_help);
 	praat_addAction1 (classComplexSpectrogram, 0, DRAW_BUTTON, nullptr, 0, nullptr);
-	praat_addAction1 (classComplexSpectrogram, 0, U"To Sound...", nullptr, 0, DO_ComplexSpectrogram_to_Sound);
-	praat_addAction1 (classComplexSpectrogram, 0, U"Down to Spectrogram", nullptr, 0, DO_ComplexSpectrogram_to_Spectrogram);
-	praat_addAction1 (classComplexSpectrogram, 0, U"To Spectrum (slice)...", nullptr, 0, DO_ComplexSpectrogram_to_Spectrum);
+	praat_addAction1 (classComplexSpectrogram, 0, U"To Sound...", nullptr, 0, NEW_ComplexSpectrogram_to_Sound);
+	praat_addAction1 (classComplexSpectrogram, 0, U"Down to Spectrogram", nullptr, 0, NEW_ComplexSpectrogram_to_Spectrogram);
+	praat_addAction1 (classComplexSpectrogram, 0, U"To Spectrum (slice)...", nullptr, 0, NEW_ComplexSpectrogram_to_Spectrum);
 	//praat_addAction1 (classComplexSpectrogram, 0, U"Paint...", 0, 1, DO_Spectrogram_paint);
 
-	praat_addAction1 (classConfusion, 0, U"Confusion help", nullptr, 0, DO_Confusion_help);
+	praat_addAction1 (classConfusion, 0, U"Confusion help", nullptr, 0, HELP_Confusion_help);
 	praat_TableOfReal_init2 (classConfusion);
 	praat_removeAction (classConfusion, nullptr, nullptr, U"Draw as numbers...");
 	praat_removeAction (classConfusion, nullptr, nullptr, U"Sort by label...");
 	praat_removeAction (classConfusion, nullptr, nullptr, U"Sort by column...");
-	praat_addAction1 (classConfusion, 0, U"Draw as numbers...", U"Draw -", 1, DO_Confusion_drawAsNumbers);
-	praat_addAction1 (classConfusion, 1, U"Get value (labels)...", U"Get value...", 1, DO_Confusion_getValue);
+	praat_addAction1 (classConfusion, 0, U"Draw as numbers...", U"Draw -", 1, GRAPHICS_Confusion_drawAsNumbers);
+	praat_addAction1 (classConfusion, 1, U"Get value (labels)...", U"Get value...", 1, REAL_Confusion_getValue);
 	praat_addAction1 (classConfusion, 0, U"-- confusion statistics --", U"Get value (labels)...", 1, nullptr);
-	praat_addAction1 (classConfusion, 1, U"Get fraction correct", U"-- confusion statistics --", 1, DO_Confusion_getFractionCorrect);
-	praat_addAction1 (classConfusion, 1, U"Get stimulus sum...", U"Get fraction correct", 1, DO_Confusion_getStimulusSum);
-	praat_addAction1 (classConfusion, 1, U"Get row sum...", U"Get fraction correct", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_getRowSum);
-	praat_addAction1 (classConfusion, 1, U"Get response sum...", U"Get stimulus sum...", 1, DO_Confusion_getResponseSum);
-	praat_addAction1 (classConfusion, 1, U"Get column sum...", U"Get row sum...", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_getColumnSum);
-	praat_addAction1 (classConfusion, 1, U"Get grand sum", U"Get response sum...", 1, DO_TableOfReal_getGrandSum);
-	praat_addAction1 (classConfusion, 0, U"Increase...", U"Formula...", 1, DO_Confusion_increase);
-	praat_addAction1 (classConfusion, 0, U"To TableOfReal (marginals)", U"To TableOfReal", 0, DO_Confusion_to_TableOfReal_marginals);
+	praat_addAction1 (classConfusion, 1, U"Get fraction correct", U"-- confusion statistics --", 1, REAL_Confusion_getFractionCorrect);
+	praat_addAction1 (classConfusion, 1, U"Get stimulus sum...", U"Get fraction correct", 1, REAL_Confusion_getStimulusSum);
+	praat_addAction1 (classConfusion, 1, U"Get row sum...", U"Get fraction correct", praat_DEPTH_1 | praat_HIDDEN, REAL_TableOfReal_getRowSum);
+	praat_addAction1 (classConfusion, 1, U"Get response sum...", U"Get stimulus sum...", 1, REAL_Confusion_getResponseSum);
+	praat_addAction1 (classConfusion, 1, U"Get column sum...", U"Get row sum...", praat_DEPTH_1 | praat_HIDDEN, REAL_TableOfReal_getColumnSum);
+	praat_addAction1 (classConfusion, 1, U"Get grand sum", U"Get response sum...", 1, REAL_TableOfReal_getGrandSum);
+	praat_addAction1 (classConfusion, 0, U"Increase...", U"Formula...", 1, MODIFY_Confusion_increase);
+	praat_addAction1 (classConfusion, 0, U"To TableOfReal (marginals)", U"To TableOfReal", 0, NEW_Confusion_to_TableOfReal_marginals);
 	praat_addAction1 (classConfusion, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classConfusion, 0, U"Condense...", nullptr, praat_HIDDEN, DO_Confusion_condense);
-	praat_addAction1 (classConfusion, 0, U"Group...", nullptr, 0, DO_Confusion_group);
-	praat_addAction1 (classConfusion, 0, U"Group stimuli...", nullptr, 0, DO_Confusion_groupStimuli);
-	praat_addAction1 (classConfusion, 0, U"Group responses...", nullptr, 0, DO_Confusion_groupResponses);
-	praat_addAction1 (classConfusion, 2, U"To difference matrix", nullptr, 0, DO_Confusion_difference);
+	praat_addAction1 (classConfusion, 0, U"Condense...", nullptr, praat_HIDDEN, NEW_Confusion_condense);
+	praat_addAction1 (classConfusion, 0, U"Group...", nullptr, 0, NEW_Confusion_group);
+	praat_addAction1 (classConfusion, 0, U"Group stimuli...", nullptr, 0, NEW_Confusion_groupStimuli);
+	praat_addAction1 (classConfusion, 0, U"Group responses...", nullptr, 0, NEW_Confusion_groupResponses);
+	praat_addAction1 (classConfusion, 2, U"To difference matrix", nullptr, 0, NEW1_Confusion_difference);
 	
-	praat_addAction2 (classConfusion, 1, classClassificationTable, 1, U"Increase confusion count", nullptr, 0, DO_Confusion_and_ClassificationTable_increase);
+	praat_addAction2 (classConfusion, 1, classClassificationTable, 1, U"Increase confusion count", nullptr, 0, MODIFY_Confusion_and_ClassificationTable_increase);
 
 	praat_addAction2 (classConfusion, 1, classMatrix, 1, U"Draw", nullptr, 0, nullptr);
-	praat_addAction2 (classConfusion, 1, classMatrix, 1, U"Draw confusion...", nullptr, 0, DO_Confusion_Matrix_draw);
+	praat_addAction2 (classConfusion, 1, classMatrix, 1, U"Draw confusion...", nullptr, 0, GRAPHICS_Confusion_Matrix_draw);
 
-	praat_addAction1 (classCovariance, 0, U"Covariance help", nullptr, 0, DO_Covariance_help);
+	praat_addAction1 (classCovariance, 0, U"Covariance help", nullptr, 0, HELP_Covariance_help);
 	praat_SSCP_as_TableOfReal_init (classCovariance);
 	praat_SSCP_query_init (classCovariance);
 	praat_SSCP_extract_init (classCovariance);
-	praat_addAction1 (classCovariance, 1, U"Get probability at position...", U"Get value...", 1, DO_Covariance_getProbabilityAtPosition);
-	praat_addAction1 (classCovariance, 1, U"Get diagonality (bartlett)...", U"Get ln(determinant)", 1, DO_SSCP_testDiagonality_bartlett);
-	praat_addAction1 (classCovariance, 1, U"Get significance of one mean...", U"Get diagonality (bartlett)...", 1, DO_Covariance_getSignificanceOfOneMean);
-	praat_addAction1 (classCovariance, 1, U"Get significance of means difference...", U"Get significance of one mean...", 1, DO_Covariance_getSignificanceOfMeansDifference);
-	praat_addAction1 (classCovariance, 1, U"Get significance of one variance...", U"Get significance of means difference...", 1, DO_Covariance_getSignificanceOfOneVariance);
-	praat_addAction1 (classCovariance, 1, U"Get significance of variances ratio...", U"Get significance of one variance...", 1, DO_Covariance_getSignificanceOfVariancesRatio);
-	praat_addAction1 (classCovariance, 1, U"Get fraction variance...", U"Get significance of variances ratio...", 1, DO_Covariance_getFractionVariance);
-	praat_addAction1 (classCovariance, 2, U"Report multivariate mean difference...", U"Get fraction variance...", 1, DO_Covariances_reportMultivariateMeanDifference);
-	praat_addAction1 (classCovariance, 2, U"Difference", U"Report multivariate mean difference...", praat_DEPTH_1 | praat_HIDDEN, DO_Covariances_reportEquality);
-	praat_addAction1 (classCovariance, 0, U"Report equality of covariances", U"Report multivariate mean difference...", praat_DEPTH_1 | praat_HIDDEN, DO_Covariances_reportEquality);
-
-	praat_addAction1 (classCovariance, 0, U"To TableOfReal (random sampling)...", nullptr, 0, DO_Covariance_to_TableOfReal_randomSampling);
-
-	praat_addAction1 (classCovariance, 0, U"To Correlation", nullptr, 0, DO_Covariance_to_Correlation);
-	praat_addAction1 (classCovariance, 0, U"To PCA", nullptr, 0, DO_Covariance_to_PCA);
+	praat_addAction1 (classCovariance, 1, U"Get probability at position...", U"Get value...", 1, REAL_Covariance_getProbabilityAtPosition);
+	praat_addAction1 (classCovariance, 1, U"Get diagonality (bartlett)...", U"Get ln(determinant)", 1, REAL_SSCP_testDiagonality_bartlett);
+	praat_addAction1 (classCovariance, 1, U"Get significance of one mean...", U"Get diagonality (bartlett)...", 1, REAL_Covariance_getSignificanceOfOneMean);
+	praat_addAction1 (classCovariance, 1, U"Get significance of means difference...", U"Get significance of one mean...", 1, REAL_Covariance_getSignificanceOfMeansDifference);
+	praat_addAction1 (classCovariance, 1, U"Get significance of one variance...", U"Get significance of means difference...", 1, REAL_Covariance_getSignificanceOfOneVariance);
+	praat_addAction1 (classCovariance, 1, U"Get significance of variances ratio...", U"Get significance of one variance...", 1, REAL_Covariance_getSignificanceOfVariancesRatio);
+	praat_addAction1 (classCovariance, 1, U"Get fraction variance...", U"Get significance of variances ratio...", 1, REAL_Covariance_getFractionVariance);
+	praat_addAction1 (classCovariance, 2, U"Report multivariate mean difference...", U"Get fraction variance...", 1, INFO_Covariances_reportMultivariateMeanDifference);
+	praat_addAction1 (classCovariance, 2, U"Difference", U"Report multivariate mean difference...", praat_DEPTH_1 | praat_HIDDEN, INFO_Covariances_reportEquality);
+	praat_addAction1 (classCovariance, 0, U"Report equality of covariances", U"Report multivariate mean difference...", praat_DEPTH_1 | praat_HIDDEN, INFO_Covariances_reportEquality);
+
+	praat_addAction1 (classCovariance, 0, U"To TableOfReal (random sampling)...", nullptr, 0, NEW_Covariance_to_TableOfReal_randomSampling);
+
+	praat_addAction1 (classCovariance, 0, U"To Correlation", nullptr, 0, NEW_Covariance_to_Correlation);
+	praat_addAction1 (classCovariance, 0, U"To PCA", nullptr, 0, NEW_Covariance_to_PCA);
 	
-	praat_addAction1 (classCovariance, 0, U"Pool", nullptr, 0, DO_Covariances_pool);
+	praat_addAction1 (classCovariance, 0, U"Pool", nullptr, 0, NEW1_Covariances_pool);
 
-	praat_addAction2 (classCovariance, 1, classTableOfReal, 1, U"To TableOfReal (mahalanobis)...", nullptr, 0, DO_Covariance_and_TableOfReal_mahalanobis);
+	praat_addAction2 (classCovariance, 1, classTableOfReal, 1, U"To TableOfReal (mahalanobis)...", nullptr, 0, NEW1_Covariance_and_TableOfReal_mahalanobis);
 
-	praat_addAction1 (classClassificationTable, 0, U"ClassificationTable help", nullptr, 0, DO_ClassificationTable_help);
+	praat_addAction1 (classClassificationTable, 0, U"ClassificationTable help", nullptr, 0, HELP_ClassificationTable_help);
 	praat_TableOfReal_init (classClassificationTable);
-	praat_addAction1 (classClassificationTable, 0, U"Get class index at maximum in row...", U"Get column index...", 1, DO_ClassificationTable_getClassIndexAtMaximumInRow);
-	praat_addAction1 (classClassificationTable, 0, U"Get class label at maximum in row...", U"Get class index at maximum in row...", 1, DO_ClassificationTable_getClassLabelAtMaximumInRow);
-	praat_addAction1 (classClassificationTable, 0, U"To Confusion", nullptr, praat_HIDDEN, DO_ClassificationTable_to_Confusion_old); // deprecated 2014
-	praat_addAction1 (classClassificationTable, 0, U"To Confusion...", nullptr, 0, DO_ClassificationTable_to_Confusion);
-	praat_addAction1 (classClassificationTable, 0, U"To Correlation (columns)", nullptr, 0, DO_ClassificationTable_to_Correlation_columns);
-	praat_addAction1 (classClassificationTable, 0, U"To Strings (max. prob.)", nullptr, 0, DO_ClassificationTable_to_Strings_maximumProbability);
-
-	praat_addAction1 (classCorrelation, 0, U"Correlation help", nullptr, 0, DO_Correlation_help);
+	praat_addAction1 (classClassificationTable, 0, U"Get class index at maximum in row...", U"Get column index...", 1, INTEGER_ClassificationTable_getClassIndexAtMaximumInRow);
+	praat_addAction1 (classClassificationTable, 0, U"Get class label at maximum in row...", U"Get class index at maximum in row...", 1, INTEGER_ClassificationTable_getClassLabelAtMaximumInRow);
+	praat_addAction1 (classClassificationTable, 0, U"To Confusion", U"*To Confusion...", praat_DEPRECATED_2014, NEW_ClassificationTable_to_Confusion_old); // deprecated 2014
+	praat_addAction1 (classClassificationTable, 0, U"To Confusion...", nullptr, 0, NEW_ClassificationTable_to_Confusion);
+	praat_addAction1 (classClassificationTable, 0, U"To Correlation (columns)", nullptr, 0, NEW_ClassificationTable_to_Correlation_columns);
+	praat_addAction1 (classClassificationTable, 0, U"To Strings (max. prob.)", nullptr, 0, NEW_ClassificationTable_to_Strings_maximumProbability);
+
+	praat_addAction1 (classCorrelation, 0, U"Correlation help", nullptr, 0, HELP_Correlation_help);
 	praat_TableOfReal_init2 (classCorrelation);
 	praat_SSCP_query_init (classCorrelation);
 	praat_SSCP_extract_init (classCorrelation);
-	praat_addAction1 (classCorrelation, 1, U"Get diagonality (bartlett)...", U"Get ln(determinant)", 1, DO_Correlation_testDiagonality_bartlett);
-	praat_addAction1 (classCorrelation, 0, U"Confidence intervals...", nullptr, 0, DO_Correlation_confidenceIntervals);
-	praat_addAction1 (classCorrelation, 0, U"To PCA", nullptr, 0, DO_Correlation_to_PCA);
+	praat_addAction1 (classCorrelation, 1, U"Get diagonality (bartlett)...", U"Get ln(determinant)", 1, REAL_Correlation_testDiagonality_bartlett);
+	praat_addAction1 (classCorrelation, 0, U"Confidence intervals...", nullptr, 0, NEW_Correlation_confidenceIntervals);
+	praat_addAction1 (classCorrelation, 0, U"To PCA", nullptr, 0, NEW_Correlation_to_PCA);
 
-	praat_addAction1 (classDiscriminant, 0, U"Discriminant help", 0, 0, DO_Discriminant_help);
+	praat_addAction1 (classDiscriminant, 0, U"Discriminant help", 0, 0, HELP_Discriminant_help);
 	praat_addAction1 (classDiscriminant, 0, DRAW_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classDiscriminant, 0, U"Draw eigenvalues...", nullptr, 1, DO_Discriminant_drawEigenvalues);
-	praat_addAction1 (classDiscriminant, 0, U"Draw eigenvalues (scree)...", nullptr, praat_DEPTH_1 | praat_HIDDEN, DO_Eigen_drawEigenvalues_scree);
-	praat_addAction1 (classDiscriminant, 0, U"Draw eigenvector...", nullptr, 1, DO_Discriminant_drawEigenvector);
+	praat_addAction1 (classDiscriminant, 0, U"Draw eigenvalues...", nullptr, 1, GRAPHICS_Discriminant_drawEigenvalues);
+	praat_addAction1 (classDiscriminant, 0, U"Draw eigenvalues (scree)...", nullptr, praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Eigen_drawEigenvalues_scree);
+	praat_addAction1 (classDiscriminant, 0, U"Draw eigenvector...", nullptr, 1, GRAPHICS_Discriminant_drawEigenvector);
 
 	praat_addAction1 (classDiscriminant, 0, U"-- sscps --", 0, 1, 0);
-	praat_addAction1 (classDiscriminant, 0, U"Draw sigma ellipses...", 0, 1, DO_Discriminant_drawSigmaEllipses);
-	praat_addAction1 (classDiscriminant, 0, U"Draw one sigma ellipse...", 0, 1, DO_Discriminant_drawOneSigmaEllipse);
-	praat_addAction1 (classDiscriminant, 0, U"Draw confidence ellipses...", 0, 1, DO_Discriminant_drawConfidenceEllipses);
+	praat_addAction1 (classDiscriminant, 0, U"Draw sigma ellipses...", 0, 1, GRAPHICS_Discriminant_drawSigmaEllipses);
+	praat_addAction1 (classDiscriminant, 0, U"Draw one sigma ellipse...", 0, 1, GRAPHICS_Discriminant_drawOneSigmaEllipse);
+	praat_addAction1 (classDiscriminant, 0, U"Draw confidence ellipses...", 0, 1, GRAPHICS_Discriminant_drawConfidenceEllipses);
 
 	praat_addAction1 (classDiscriminant, 1, QUERY_BUTTON, nullptr, 0, 0);
 	praat_addAction1 (classDiscriminant, 1, U"-- eigen structure --", nullptr, 1, 0);
-	praat_addAction1 (classDiscriminant, 1, U"Get eigenvalue...", nullptr, 1, DO_Discriminant_getEigenvalue);
-	praat_addAction1 (classDiscriminant, 1, U"Get sum of eigenvalues...", nullptr, 1, DO_Discriminant_getSumOfEigenvalues);
-	praat_addAction1 (classDiscriminant, 1, U"Get number of eigenvectors", nullptr, 1, DO_Discriminant_getNumberOfEigenvalues);
-	praat_addAction1 (classDiscriminant, 1, U"Get eigenvector dimension", nullptr, 1, DO_Discriminant_getDimension);
-	praat_addAction1 (classDiscriminant, 1, U"Get eigenvector element...", nullptr, 1, DO_Discriminant_getEigenvectorElement);
+	praat_addAction1 (classDiscriminant, 1, U"Get eigenvalue...", nullptr, 1, REAL_Discriminant_getEigenvalue);
+	praat_addAction1 (classDiscriminant, 1, U"Get sum of eigenvalues...", nullptr, 1, REAL_Discriminant_getSumOfEigenvalues);
+	praat_addAction1 (classDiscriminant, 1, U"Get number of eigenvectors", nullptr, 1, INTEGER_Discriminant_getNumberOfEigenvalues);
+	praat_addAction1 (classDiscriminant, 1, U"Get eigenvector dimension", nullptr, 1, INTEGER_Discriminant_getDimension);
+	praat_addAction1 (classDiscriminant, 1, U"Get eigenvector element...", nullptr, 1, REAL_Discriminant_getEigenvectorElement);
 
 	praat_addAction1 (classDiscriminant, 1, U"-- discriminant --", 0, 1, 0);
-	praat_addAction1 (classDiscriminant, 1, U"Get number of functions", 0, 1, DO_Discriminant_getNumberOfFunctions);
-	praat_addAction1 (classDiscriminant, 1, U"Get dimension of functions", 0, 1, DO_Discriminant_getDimensionOfFunctions);
-	praat_addAction1 (classDiscriminant, 1, U"Get number of groups", 0, 1, DO_Discriminant_getNumberOfGroups);
-	praat_addAction1 (classDiscriminant, 1, U"Get number of observations...", 0, 1, DO_Discriminant_getNumberOfObservations);
+	praat_addAction1 (classDiscriminant, 1, U"Get number of functions", 0, 1, INTEGER_Discriminant_getNumberOfFunctions);
+	praat_addAction1 (classDiscriminant, 1, U"Get dimension of functions", 0, 1, INTEGER_Discriminant_getDimensionOfFunctions);
+	praat_addAction1 (classDiscriminant, 1, U"Get number of groups", 0, 1, INTEGER_Discriminant_getNumberOfGroups);
+	praat_addAction1 (classDiscriminant, 1, U"Get number of observations...", 0, 1, INTEGER_Discriminant_getNumberOfObservations);
 	praat_addAction1 (classDiscriminant, 1, U"-- tests --", 0, 1, 0);
-	praat_addAction1 (classDiscriminant, 1, U"Get Wilks lambda...", 0, 1, DO_Discriminant_getWilksLambda);
-	praat_addAction1 (classDiscriminant, 1, U"Get cumulative contribution of components...", 0, 1, DO_Discriminant_getCumulativeContributionOfComponents);
-	praat_addAction1 (classDiscriminant, 1, U"Get partial discrimination probability...", 0, 1,
-	                  DO_Discriminant_getPartialDiscriminationProbability);
-	praat_addAction1 (classDiscriminant, 1, U"Get homogeneity of covariances (box)", 0, praat_DEPTH_1 | praat_HIDDEN,
-	                  DO_Discriminant_getHomegeneityOfCovariances_box);
-	praat_addAction1 (classDiscriminant, 1, U"Report equality of covariance matrices", 0, 1,
-	                  DO_Discriminant_reportEqualityOfCovariances_wald);
+	praat_addAction1 (classDiscriminant, 1, U"Get Wilks lambda...", 0, 1, REAL_Discriminant_getWilksLambda);
+	praat_addAction1 (classDiscriminant, 1, U"Get cumulative contribution of components...", 0, 1, REAL_Discriminant_getCumulativeContributionOfComponents);
+	praat_addAction1 (classDiscriminant, 1, U"Get partial discrimination probability...", 0, 1, REAL_Discriminant_getPartialDiscriminationProbability);
+	praat_addAction1 (classDiscriminant, 1, U"Get homogeneity of covariances (box)", 0, praat_DEPTH_1 | praat_HIDDEN, REAL_Discriminant_getHomegeneityOfCovariances_box);
+	praat_addAction1 (classDiscriminant, 1, U"Report equality of covariance matrices", 0, 1, INFO_Discriminant_reportEqualityOfCovariances_wald);
 	praat_addAction1 (classDiscriminant, 1, U"-- ellipses --", 0, 1, 0);
-	praat_addAction1 (classDiscriminant, 1, U"Get sigma ellipse area...", 0, 1, DO_Discriminant_getConcentrationEllipseArea);
-	praat_addAction1 (classDiscriminant, 1, U"Get confidence ellipse area...", 0, 1, DO_Discriminant_getConfidenceEllipseArea);
-	praat_addAction1 (classDiscriminant, 1, U"Get ln(determinant_group)...", 0, 1, DO_Discriminant_getLnDeterminant_group);
-	praat_addAction1 (classDiscriminant, 1, U"Get ln(determinant_total)", 0, 1, DO_Discriminant_getLnDeterminant_total);
+	praat_addAction1 (classDiscriminant, 1, U"Get sigma ellipse area...", 0, 1, REAL_Discriminant_getConcentrationEllipseArea);
+	praat_addAction1 (classDiscriminant, 1, U"Get confidence ellipse area...", 0, 1, REAL_Discriminant_getConfidenceEllipseArea);
+	praat_addAction1 (classDiscriminant, 1, U"Get ln(determinant_group)...", 0, 1, REAL_Discriminant_getLnDeterminant_group);
+	praat_addAction1 (classDiscriminant, 1, U"Get ln(determinant_total)", 0, 1, REAL_Discriminant_getLnDeterminant_total);
 
 	praat_addAction1 (classDiscriminant, 0, MODIFY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classDiscriminant, 1, U"Invert eigenvector...", nullptr, 1, DO_Discriminant_invertEigenvector);
-	praat_addAction1 (classDiscriminant, 0, U"Align eigenvectors", nullptr, 1, DO_Eigens_alignEigenvectors);
+	praat_addAction1 (classDiscriminant, 1, U"Invert eigenvector...", nullptr, 1, MODIFY_Discriminant_invertEigenvector);
+	praat_addAction1 (classDiscriminant, 0, U"Align eigenvectors", nullptr, 1, MODIFY_Eigens_alignEigenvectors);
 
-	praat_addAction1 (classDiscriminant, 0, EXTRACT_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classDiscriminant, 1, U"Extract pooled within-groups SSCP", nullptr, 1,
-	                  DO_Discriminant_extractPooledWithinGroupsSSCP);
-	praat_addAction1 (classDiscriminant, 1, U"Extract within-group SSCP...", nullptr, 1, DO_Discriminant_extractWithinGroupSSCP);
-	praat_addAction1 (classDiscriminant, 1, U"Extract between-groups SSCP", nullptr, 1, DO_Discriminant_extractBetweenGroupsSSCP);
-	praat_addAction1 (classDiscriminant, 1, U"Extract group centroids", nullptr, 1, DO_Discriminant_extractGroupCentroids);
-	praat_addAction1 (classDiscriminant, 1, U"Extract group standard deviations", nullptr, 1, DO_Discriminant_extractGroupStandardDeviations);
-	praat_addAction1 (classDiscriminant, 1, U"Extract group labels", nullptr, 1, DO_Discriminant_extractGroupLabels);
+	praat_addAction1 (classDiscriminant, 0, U"Extract -", nullptr, 0, 0);
+		praat_addAction1 (classDiscriminant, 0, U"Extract pooled within-groups SSCP", nullptr, 1, NEW_Discriminant_extractPooledWithinGroupsSSCP);
+		praat_addAction1 (classDiscriminant, 0, U"Extract within-group SSCP...", nullptr, 1, NEW_Discriminant_extractWithinGroupSSCP);
+		praat_addAction1 (classDiscriminant, 0, U"Extract between-groups SSCP", nullptr, 1, NEW_Discriminant_extractBetweenGroupsSSCP);
+		praat_addAction1 (classDiscriminant, 0, U"Extract group centroids", nullptr, 1, NEW_Discriminant_extractGroupCentroids);
+		praat_addAction1 (classDiscriminant, 0, U"Extract group standard deviations", nullptr, 1, NEW_Discriminant_extractGroupStandardDeviations);
+		praat_addAction1 (classDiscriminant, 0, U"Extract group labels", nullptr, 1, NEW_Discriminant_extractGroupLabels);
+		praat_addAction1 (classDiscriminant, 0, U"Extract Eigen", nullptr, 1, NEW_Discriminant_extractEigen);
 
-	praat_addAction1 (classDiscriminant , 0, U"& TableOfReal: To ClassificationTable?", nullptr, 0, DO_hint_Discriminant_and_TableOfReal_to_ClassificationTable);
+	praat_addAction1 (classDiscriminant , 0, U"& TableOfReal: To ClassificationTable?", nullptr, 0, hint_Discriminant_and_TableOfReal_to_ClassificationTable);
 
 	/*		praat_addAction1 (classDiscriminant, 1, U"Extract coefficients...", nullptr, 1, DO_Discriminant_extractCoefficients);*/
 
@@ -9228,273 +7499,291 @@ void praat_uvafon_David_init () {
 	praat_Eigen_Matrix_project (classDiscriminant, classBarkFilter); // deprecated 2014
 	praat_Eigen_Matrix_project (classDiscriminant, classMelFilter); // deprecated 2014
 
-	praat_addAction2 (classDiscriminant, 1, classPatternList, 1, U"To Categories...", nullptr, 0, DO_Discriminant_and_PatternList_to_Categories);
-	praat_addAction2 (classDiscriminant, 1, classSSCP, 1, U"Project", nullptr, 0, DO_Eigen_and_SSCP_project);
+	praat_addAction2 (classDiscriminant, 1, classPatternList, 1, U"To Categories...", nullptr, 0, NEW1_Discriminant_and_PatternList_to_Categories);
+	praat_addAction2 (classDiscriminant, 1, classSSCP, 1, U"Project", nullptr, 0, NEW1_Eigen_and_SSCP_project);
 	praat_addAction2 (classDiscriminant, 1, classStrings, 1, U"Modify Discriminant", nullptr, 0, 0);
-	praat_addAction2 (classDiscriminant, 1, classStrings, 1, U"Set group labels", nullptr, 0, DO_Discriminant_setGroupLabels);
+	praat_addAction2 (classDiscriminant, 1, classStrings, 1, U"Set group labels", nullptr, 0, MODIFY_Discriminant_setGroupLabels);
 
-	praat_addAction2 (classDiscriminant, 1, classTableOfReal, 1, U"To Configuration...", nullptr, 0, DO_Discriminant_and_TableOfReal_to_Configuration);
-	praat_addAction2 (classDiscriminant, 1, classTableOfReal, 1, U"To ClassificationTable...", nullptr, 0,
-	                  DO_Discriminant_and_TableOfReal_to_ClassificationTable);
-	praat_addAction2 (classDiscriminant, 1, classTableOfReal, 1, U"To TableOfReal (mahalanobis)...", nullptr, 0, DO_Discriminant_and_TableOfReal_mahalanobis);
+	praat_addAction2 (classDiscriminant, 1, classTableOfReal, 1, U"To Configuration...", nullptr, 0, NEW1_Discriminant_and_TableOfReal_to_Configuration);
+	praat_addAction2 (classDiscriminant, 1, classTableOfReal, 1, U"To ClassificationTable...", nullptr, 0, NEW1_Discriminant_and_TableOfReal_to_ClassificationTable);
+	praat_addAction2 (classDiscriminant, 1, classTableOfReal, 1, U"To TableOfReal (mahalanobis)...", nullptr, 0, NEW1_Discriminant_and_TableOfReal_mahalanobis);
 
 
-	praat_addAction1 (classDTW, 0, U"DTW help", nullptr, 0, DO_DTW_help);
+	praat_addAction1 (classDTW, 0, U"DTW help", nullptr, 0, HELP_DTW_help);
 	praat_addAction1 (classDTW, 0, DRAW_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classDTW, 0, U"Draw path...", nullptr, 1, DO_DTW_drawPath);
-	praat_addAction1 (classDTW, 0, U"Paint distances...", nullptr, 1, DO_DTW_paintDistances);
-	praat_addAction1 (classDTW, 0, U"Draw warp (x)...", nullptr, 1, DO_DTW_drawWarpX);
-	praat_addAction1 (classDTW, 0, U"Draw warp (y)...", nullptr, 1, DO_DTW_drawWarpY);
+	praat_addAction1 (classDTW, 0, U"Draw path...", nullptr, 1, GRAPHICS_DTW_drawPath);
+	praat_addAction1 (classDTW, 0, U"Paint distances...", nullptr, 1, GRAPHICS_DTW_paintDistances);
+	praat_addAction1 (classDTW, 0, U"Draw warp (x)...", nullptr, 1, GRAPHICS_DTW_drawWarpX);
+	praat_addAction1 (classDTW, 0, U"Draw warp (y)...", nullptr, 1, GRAPHICS_DTW_drawWarpY);
 	praat_addAction1 (classDTW, 0, QUERY_BUTTON, nullptr, 0, 0);
 	praat_addAction1 (classDTW, 1, U"Query time domains", nullptr, 1, 0);
-	praat_addAction1 (classDTW, 1, U"Get start time (x)", nullptr, 2, DO_DTW_getStartTimeX);
-	praat_addAction1 (classDTW, 1, U"Get end time (x)", nullptr, 2, DO_DTW_getEndTimeX);
-	praat_addAction1 (classDTW, 1, U"Get total duration (x)", nullptr, 2, DO_DTW_getTotalDurationX);
+	praat_addAction1 (classDTW, 1, U"Get start time (x)", nullptr, 2, REAL_DTW_getStartTimeX);
+	praat_addAction1 (classDTW, 1, U"Get end time (x)", nullptr, 2, REAL_DTW_getEndTimeX);
+	praat_addAction1 (classDTW, 1, U"Get total duration (x)", nullptr, 2, REAL_DTW_getTotalDurationX);
 	praat_addAction1 (classDTW, 1, U"-- time domain x from y separator --", nullptr, 2, 0);
-	praat_addAction1 (classDTW, 1, U"Get start time (y)", nullptr, 2, DO_DTW_getStartTimeY);
-	praat_addAction1 (classDTW, 1, U"Get end time (y)", nullptr, 2, DO_DTW_getEndTimeY);
-	praat_addAction1 (classDTW, 1, U"Get total duration (y)", nullptr, 2, DO_DTW_getTotalDurationY);
+	praat_addAction1 (classDTW, 1, U"Get start time (y)", nullptr, 2, REAL_DTW_getStartTimeY);
+	praat_addAction1 (classDTW, 1, U"Get end time (y)", nullptr, 2, REAL_DTW_getEndTimeY);
+	praat_addAction1 (classDTW, 1, U"Get total duration (y)", nullptr, 2, REAL_DTW_getTotalDurationY);
 	praat_addAction1 (classDTW, 1, U"Query time samplings", nullptr, 1, 0);
-	praat_addAction1 (classDTW, 1, U"Get number of frames (x)", nullptr, 2, DO_DTW_getNumberOfFramesX);
-	praat_addAction1 (classDTW, 1, U"Get time step (x)", nullptr, 2, DO_DTW_getTimeStepX);
-	praat_addAction1 (classDTW, 1, U"Get time from frame number (x)...", nullptr, 2, DO_DTW_getTimeFromFrameNumberX);
-	praat_addAction1 (classDTW, 1, U"Get frame number from time (x)...", nullptr, 2, DO_DTW_getFrameNumberFromTimeX);
+	praat_addAction1 (classDTW, 1, U"Get number of frames (x)", nullptr, 2, INTEGER_DTW_getNumberOfFramesX);
+	praat_addAction1 (classDTW, 1, U"Get time step (x)", nullptr, 2, REAL_DTW_getTimeStepX);
+	praat_addAction1 (classDTW, 1, U"Get time from frame number (x)...", nullptr, 2, REAL_DTW_getTimeFromFrameNumberX);
+	praat_addAction1 (classDTW, 1, U"Get frame number from time (x)...", nullptr, 2, INTEGER_DTW_getFrameNumberFromTimeX);
 	praat_addAction1 (classDTW, 1, U"-- time sampling x from y separator --", nullptr, 2, 0);
-	praat_addAction1 (classDTW, 1, U"Get number of frames (y)", nullptr, 2, DO_DTW_getNumberOfFramesY);
-	praat_addAction1 (classDTW, 1, U"Get time step (y)", nullptr, 2, DO_DTW_getTimeStepY);
-	praat_addAction1 (classDTW, 1, U"Get time from frame number (y)...", nullptr, 2, DO_DTW_getTimeFromFrameNumberY);
-	praat_addAction1 (classDTW, 1, U"Get frame number from time (y)...", nullptr, 2, DO_DTW_getFrameNumberFromTimeY);
-
-	praat_addAction1 (classDTW, 1, U"Get y time from x time...", nullptr, 1, DO_DTW_getYTimeFromXTime);
-	praat_addAction1 (classDTW, 1, U"Get x time from y time...", nullptr, 1, DO_DTW_getXTimeFromYTime);
-	praat_addAction1 (classDTW, 1, U"Get y time...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_DTW_getYTimeFromXTime);
-	praat_addAction1 (classDTW, 1, U"Get x time...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_DTW_getXTimeFromYTime);
-	praat_addAction1 (classDTW, 1, U"Get maximum consecutive steps...", nullptr, 1, DO_DTW_getMaximumConsecutiveSteps);
-	praat_addAction1 (classDTW, 1, U"Get time along path...", nullptr, praat_DEPTH_1 | praat_HIDDEN, DO_DTW_getPathY);
+	praat_addAction1 (classDTW, 1, U"Get number of frames (y)", nullptr, 2, INTEGER_DTW_getNumberOfFramesY);
+	praat_addAction1 (classDTW, 1, U"Get time step (y)", nullptr, 2, REAL_DTW_getTimeStepY);
+	praat_addAction1 (classDTW, 1, U"Get time from frame number (y)...", nullptr, 2, REAL_DTW_getTimeFromFrameNumberY);
+	praat_addAction1 (classDTW, 1, U"Get frame number from time (y)...", nullptr, 2, INTEGER_DTW_getFrameNumberFromTimeY);
+
+	praat_addAction1 (classDTW, 1, U"Get y time from x time...", nullptr, 1, REAL_DTW_getYTimeFromXTime);
+	praat_addAction1 (classDTW, 1, U"Get x time from y time...", nullptr, 1, REAL_DTW_getXTimeFromYTime);
+	praat_addAction1 (classDTW, 1, U"Get y time...", nullptr, praat_HIDDEN + praat_DEPTH_1, REAL_DTW_getYTimeFromXTime);
+	praat_addAction1 (classDTW, 1, U"Get x time...", nullptr, praat_HIDDEN + praat_DEPTH_1, REAL_DTW_getXTimeFromYTime);
+	praat_addAction1 (classDTW, 1, U"Get maximum consecutive steps...", nullptr, 1, INTEGER_DTW_getMaximumConsecutiveSteps);
+	praat_addAction1 (classDTW, 1, U"Get time along path...", nullptr, praat_DEPTH_1 | praat_HIDDEN, REAL_DTW_getPathY);
 	praat_addAction1 (classDTW, 1, U"-- distance queries --", nullptr, 1, 0);
-	praat_addAction1 (classDTW, 1, U"Get distance value...", nullptr, 1, DO_DTW_getDistanceValue);
-	praat_addAction1 (classDTW, 1, U"Get minimum distance", nullptr, 1, DO_DTW_getMinimumDistance);
-	praat_addAction1 (classDTW, 1, U"Get maximum distance", nullptr, 1, DO_DTW_getMaximumDistance);
-	praat_addAction1 (classDTW, 1, U"Get distance (weighted)", nullptr, 1, DO_DTW_getWeightedDistance);
+	praat_addAction1 (classDTW, 1, U"Get distance value...", nullptr, 1, REAL_DTW_getDistanceValue);
+	praat_addAction1 (classDTW, 1, U"Get minimum distance", nullptr, 1, REAL_DTW_getMinimumDistance);
+	praat_addAction1 (classDTW, 1, U"Get maximum distance", nullptr, 1, REAL_DTW_getMaximumDistance);
+	praat_addAction1 (classDTW, 1, U"Get distance (weighted)", nullptr, 1, REAL_DTW_getWeightedDistance);
 	praat_addAction1 (classDTW, 0, MODIFY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classDTW, 0, U"Formula (distances)...", nullptr, 1, DO_DTW_formulaDistances);
-	praat_addAction1 (classDTW, 0, U"Set distance value...", nullptr, 1, DO_DTW_setDistanceValue);
+	praat_addAction1 (classDTW, 0, U"Formula (distances)...", nullptr, 1, MODIFY_DTW_formulaDistances);
+	praat_addAction1 (classDTW, 0, U"Set distance value...", nullptr, 1, MODIFY_DTW_setDistanceValue);
 
 	praat_addAction1 (classDTW, 0, U"Analyse", nullptr, 0, 0);
-    praat_addAction1 (classDTW, 0, U"Find path...", nullptr, praat_HIDDEN, DO_DTW_findPath);
-    praat_addAction1 (classDTW, 0, U"Find path (band & slope)...", nullptr, 0, DO_DTW_findPath_bandAndSlope);
-    praat_addAction1 (classDTW, 0, U"To Polygon...", nullptr, 1, DO_DTW_to_Polygon);
-	praat_addAction1 (classDTW, 0, U"To Matrix (distances)", nullptr, 0, DO_DTW_to_Matrix_distances);
-    praat_addAction1 (classDTW, 0, U"To Matrix (cumm. distances)...", nullptr, 0, DO_DTW_to_Matrix_cummulativeDistances);
-	praat_addAction1 (classDTW, 0, U"Swap axes", nullptr, 0, DO_DTW_swapAxes);
-
-	praat_addAction2 (classDTW, 1, classMatrix, 1, U"Replace matrix", nullptr, 0, DO_DTW_and_Matrix_replace);
-	praat_addAction2 (classDTW, 1, classTextGrid, 1, U"To TextGrid (warp times)", nullptr, 0, DO_DTW_and_TextGrid_to_TextGrid);
-	praat_addAction2 (classDTW, 1, classIntervalTier, 1, U"To Table (distances)", nullptr, 0, DO_DTW_and_IntervalTier_to_Table);
-
-    praat_addAction2 (classDTW, 1, classPolygon, 1, U"Find path inside...", nullptr, 0, DO_DTW_and_Polygon_findPathInside);
-    praat_addAction2 (classDTW, 1, classPolygon, 1, U"To Matrix (cumm. distances)...", nullptr, 0, DO_DTW_and_Polygon_to_Matrix_cummulativeDistances);
-	praat_addAction2 (classDTW, 1, classSound, 2, U"Draw...", nullptr, 0, DO_DTW_and_Sounds_draw);
-	praat_addAction2 (classDTW, 1, classSound, 2, U"Draw warp (x)...", nullptr, 0, DO_DTW_and_Sounds_drawWarpX);
-
-	praat_addAction1 (classEditDistanceTable, 1, U"EditDistanceTable help", nullptr, 0, DO_EditDistanceTable_help);
+    praat_addAction1 (classDTW, 0, U"Find path...", nullptr, praat_HIDDEN, MODIFY_DTW_findPath);
+    praat_addAction1 (classDTW, 0, U"Find path (band & slope)...", nullptr, 0, MODIFY_DTW_findPath_bandAndSlope);
+    praat_addAction1 (classDTW, 0, U"To Polygon...", nullptr, 1, NEW_DTW_to_Polygon);
+	praat_addAction1 (classDTW, 0, U"To Matrix (distances)", nullptr, 0, NEW_DTW_to_Matrix_distances);
+    praat_addAction1 (classDTW, 0, U"To Matrix (cumm. distances)...", nullptr, 0, NEW_DTW_to_Matrix_cummulativeDistances);
+	praat_addAction1 (classDTW, 0, U"Swap axes", nullptr, 0, NEW_DTW_swapAxes);
+
+	praat_addAction2 (classDTW, 1, classMatrix, 1, U"Replace matrix", nullptr, 0, MODIFY_DTW_and_Matrix_replace);
+	praat_addAction2 (classDTW, 1, classTextGrid, 1, U"To TextGrid (warp times)", nullptr, 0, NEW1_DTW_and_TextGrid_to_TextGrid);
+	praat_addAction2 (classDTW, 1, classIntervalTier, 1, U"To Table (distances)", nullptr, 0, NEW1_DTW_and_IntervalTier_to_Table);
+
+    praat_addAction2 (classDTW, 1, classPolygon, 1, U"Find path inside...", nullptr, 0, MODIFY_DTW_and_Polygon_findPathInside);
+    praat_addAction2 (classDTW, 1, classPolygon, 1, U"To Matrix (cumm. distances)...", nullptr, 0, NEW1_DTW_and_Polygon_to_Matrix_cummulativeDistances);
+	praat_addAction2 (classDTW, 1, classSound, 2, U"Draw...", nullptr, 0, GRAPHICS_DTW_and_Sounds_draw);
+	praat_addAction2 (classDTW, 1, classSound, 2, U"Draw warp (x)...", nullptr, 0, GRAPHICS_DTW_and_Sounds_drawWarpX);
+
+	praat_addAction1 (classEditDistanceTable, 1, U"EditDistanceTable help", nullptr, 0, HELP_EditDistanceTable_help);
 	praat_EditDistanceTable_as_TableOfReal_init (classEditDistanceTable);
-	praat_addAction1 (classEditDistanceTable, 1, U"To TableOfReal (directions)...", nullptr, praat_HIDDEN, DO_EditDistanceTable_to_TableOfReal_directions);
-	praat_addAction2 (classEditDistanceTable, 1, classEditCostsTable, 1, U"Set new edit costs", nullptr, 0, DO_EditDistanceTable_setEditCosts);
+	praat_addAction1 (classEditDistanceTable, 1, U"To TableOfReal (directions)...", nullptr, praat_HIDDEN, NEW_EditDistanceTable_to_TableOfReal_directions);
+	praat_addAction2 (classEditDistanceTable, 1, classEditCostsTable, 1, U"Set new edit costs", nullptr, 0, MODIFY_EditDistanceTable_setEditCosts);
 
-	praat_addAction1 (classEditCostsTable, 1, U"EditCostsTable help", nullptr, 0, DO_EditCostsTable_help);
+	praat_addAction1 (classEditCostsTable, 1, U"EditCostsTable help", nullptr, 0, HELP_EditCostsTable_help);
 	praat_addAction1 (classEditCostsTable, 0, QUERY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classEditCostsTable, 1, U"Get target index...", nullptr, 1, DO_EditCostsTable_getTargetIndex);
-	praat_addAction1 (classEditCostsTable, 1, U"Get source index...", nullptr, 1, DO_EditCostsTable_getSourceIndex);
-	praat_addAction1 (classEditCostsTable, 1, U"Get insertion cost...", nullptr, 1, DO_EditCostsTable_getInsertionCost);
-	praat_addAction1 (classEditCostsTable, 1, U"Get deletion cost...", nullptr, 1, DO_EditCostsTable_getDeletionCost);
-	praat_addAction1 (classEditCostsTable, 1, U"Get substitution cost...", nullptr, 1, DO_EditCostsTable_getSubstitutionCost);
-	praat_addAction1 (classEditCostsTable, 1, U"Get cost (others)...", nullptr, 1, DO_EditCostsTable_getOthersCost);
+	praat_addAction1 (classEditCostsTable, 1, U"Get target index...", nullptr, 1, INTEGER_EditCostsTable_getTargetIndex);
+	praat_addAction1 (classEditCostsTable, 1, U"Get source index...", nullptr, 1, INTEGER_EditCostsTable_getSourceIndex);
+	praat_addAction1 (classEditCostsTable, 1, U"Get insertion cost...", nullptr, 1, REAL_EditCostsTable_getInsertionCost);
+	praat_addAction1 (classEditCostsTable, 1, U"Get deletion cost...", nullptr, 1, REAL_EditCostsTable_getDeletionCost);
+	praat_addAction1 (classEditCostsTable, 1, U"Get substitution cost...", nullptr, 1, REAL_EditCostsTable_getSubstitutionCost);
+	praat_addAction1 (classEditCostsTable, 1, U"Get cost (others)...", nullptr, 1, REAL_EditCostsTable_getOthersCost);
 	praat_addAction1 (classEditCostsTable, 0, MODIFY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classEditCostsTable, 1, U"Set target symbol (index)...", nullptr, 1, DO_EditCostsTable_setTargetSymbol_index);
-	praat_addAction1 (classEditCostsTable, 1, U"Set source symbol (index)...", nullptr, 1, DO_EditCostsTable_setSourceSymbol_index);
-	praat_addAction1 (classEditCostsTable, 1, U"Set insertion costs...", nullptr, 1, DO_EditCostsTable_setInsertionCosts);
-	praat_addAction1 (classEditCostsTable, 1, U"Set deletion costs...", nullptr, 1, DO_EditCostsTable_setDeletionCosts);
-	praat_addAction1 (classEditCostsTable, 1, U"Set substitution costs...", nullptr, 1, DO_EditCostsTable_setSubstitutionCosts);
-	praat_addAction1 (classEditCostsTable, 1, U"Set costs (others)...", nullptr, 1, DO_EditCostsTable_setOthersCosts);
-	praat_addAction1 (classEditCostsTable, 1, U"To TableOfReal", nullptr, 0, DO_EditCostsTable_to_TableOfReal);
+	praat_addAction1 (classEditCostsTable, 1, U"Set target symbol (index)...", nullptr, 1, MODIFY_EditCostsTable_setTargetSymbol_index);
+	praat_addAction1 (classEditCostsTable, 1, U"Set source symbol (index)...", nullptr, 1, MODIFY_EditCostsTable_setSourceSymbol_index);
+	praat_addAction1 (classEditCostsTable, 1, U"Set insertion costs...", nullptr, 1, MODIFY_EditCostsTable_setInsertionCosts);
+	praat_addAction1 (classEditCostsTable, 1, U"Set deletion costs...", nullptr, 1, MODIFY_EditCostsTable_setDeletionCosts);
+	praat_addAction1 (classEditCostsTable, 1, U"Set substitution costs...", nullptr, 1, MODIFY_EditCostsTable_setSubstitutionCosts);
+	praat_addAction1 (classEditCostsTable, 1, U"Set costs (others)...", nullptr, 1, MODIFY_EditCostsTable_setOthersCosts);
+	praat_addAction1 (classEditCostsTable, 1, U"To TableOfReal", nullptr, 0, NEW_EditCostsTable_to_TableOfReal);
 
 	praat_Index_init (classStringsIndex);
-	praat_addAction1 (classIndex, 0, U"Index help", nullptr, 0, DO_Index_help);
-	praat_addAction1 (classStringsIndex, 1, U"Get class label...", nullptr, 0, DO_StringsIndex_getClassLabel);
-	praat_addAction1 (classStringsIndex, 1, U"Get class index...", nullptr, 0, DO_StringsIndex_getClassIndex);
-	praat_addAction1 (classStringsIndex, 1, U"Get label...", nullptr, 0, DO_StringsIndex_getLabel);
-	praat_addAction1 (classIndex, 1, U"Get index...", nullptr, 0, DO_Index_getIndex);
-	praat_addAction1 (classStringsIndex, 1, U"To Strings", nullptr, 0, DO_StringsIndex_to_Strings);
-
+	praat_addAction1 (classIndex, 0, U"Index help", nullptr, 0, HELP_Index_help);
+	praat_addAction1 (classStringsIndex, 1, U"Get class label...", nullptr, 0, INFO_StringsIndex_getClassLabelFromClassIndex);
+	praat_addAction1 (classStringsIndex, 1, U"Get class index...", nullptr, 0, INTEGER_StringsIndex_getClassIndexFromClassLabel);
+	praat_addAction1 (classStringsIndex, 1, U"Get label...", nullptr, 0, INFO_StringsIndex_getItemLabelFromItemIndex);
+	praat_addAction1 (classStringsIndex, 1, U"Get class index from item index...", nullptr, 0, INTEGER_Index_getClassIndexFromItemIndex);
+	praat_addAction1 (classIndex, 1, U"Get index...", nullptr, 0, INTEGER_Index_getClassIndexFromItemIndex);
+	praat_addAction1 (classStringsIndex, 1, U"To Strings", nullptr, 0, NEW_StringsIndex_to_Strings);
+
+	praat_addAction1 (classEigen, 0, U"Eigen help", nullptr, 0, HELP_Eigen_help);
+	praat_addAction1 (classEigen, 0, U"Draw -", nullptr, 0, nullptr);
+		praat_addAction1 (classEigen, 0, U"Draw eigenvalues (scree)...", nullptr, praat_DEPTH_1 | praat_DEPRECATED_2010, GRAPHICS_Eigen_drawEigenvalues_scree);
+		praat_addAction1 (classEigen, 0, U"Draw eigenvalues...", nullptr, 1, GRAPHICS_Eigen_drawEigenvalues);
+		praat_addAction1 (classEigen, 0, U"Draw eigenvector...", nullptr, 1, GRAPHICS_Eigen_drawEigenvector);
+	praat_addAction1 (classEigen, 0, U"Query -", nullptr, 0, nullptr);
+		praat_addAction1 (classEigen, 1, U"Get number of eigenvalues", nullptr, 1, INTEGER_Eigen_getNumberOfEigenvalues);
+		praat_addAction1 (classEigen, 1, U"Get eigenvalue...", nullptr, 1, REAL_Eigen_getEigenvalue);
+		praat_addAction1 (classEigen, 1, U"Get sum of eigenvalues...", nullptr, 1, REAL_Eigen_getSumOfEigenvalues);
+	praat_addAction1 (classEigen, 1, U"-- eigenvectors --", nullptr, 1, 0);
+		praat_addAction1 (classEigen, 1, U"Get number of eigenvectors", nullptr, 1, INTEGER_Eigen_getNumberOfEigenvalues);
+		praat_addAction1 (classEigen, 1, U"Get eigenvector dimension", nullptr, 1, INTEGER_Eigen_getDimension);
+		praat_addAction1 (classEigen, 1, U"Get eigenvector element...", nullptr, 1, REAL_Eigen_getEigenvectorElement);
+	praat_addAction1 (classEigen, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_addAction1 (classEigen, 1, U"Invert eigenvector...", nullptr, 1, MODIFY_Eigen_invertEigenvector);
 	praat_addAction1 (classExcitation, 0, U"Synthesize", U"To Formant...", 0, 0);
-	praat_addAction1 (classExcitation, 0, U"To ExcitationList", U"Synthesize", 0, DO_Excitations_to_ExcitationList);
-	praat_addAction1 (classExcitation, 0, U"To Excitations", U"Synthesize", praat_HIDDEN, DO_Excitations_to_ExcitationList);
+	praat_addAction1 (classExcitation, 0, U"To ExcitationList", U"Synthesize", 0, NEW1_Excitations_to_ExcitationList);
+	praat_addAction1 (classExcitation, 0, U"To Excitations", U"Synthesize", praat_DEPRECATED_2015, NEW1_Excitations_to_ExcitationList);
 
 	praat_addAction1 (classExcitationList, 0, U"Modify", nullptr, 0, 0);
-	praat_addAction1 (classExcitationList, 0, U"Formula...", nullptr, 0, DO_ExcitationList_formula);
+	praat_addAction1 (classExcitationList, 0, U"Formula...", nullptr, 0, MODIFY_ExcitationList_formula);
 	praat_addAction1 (classExcitationList, 0, U"Extract", nullptr, 0, 0);
-	praat_addAction1 (classExcitationList, 0, U"Extract Excitation...", nullptr, 0, DO_ExcitationList_getItem);
+		praat_addAction1 (classExcitationList, 0, U"Extract Excitation...", nullptr, 0, NEW_ExcitationList_extractItem);
 	praat_addAction1 (classExcitationList, 0, U"Synthesize", nullptr, 0, 0);
-	praat_addAction1 (classExcitationList, 2, U"Append", nullptr, 0, DO_ExcitationList_append);
+	praat_addAction1 (classExcitationList, 2, U"Append", nullptr, 0, NEW1_ExcitationList_append);
 	praat_addAction1 (classExcitationList, 0, U"Convert", nullptr, 0, 0);
-	praat_addAction1 (classExcitationList, 0, U"To PatternList...", nullptr, 0, DO_ExcitationList_to_PatternList);
-	praat_addAction1 (classExcitationList, 0, U"To Pattern...", nullptr, praat_HIDDEN, DO_ExcitationList_to_PatternList);
-	praat_addAction1 (classExcitationList, 0, U"To TableOfReal", nullptr, 0, DO_ExcitationList_to_TableOfReal);
+	praat_addAction1 (classExcitationList, 0, U"To PatternList...", nullptr, 0, NEW_ExcitationList_to_PatternList);
+	praat_addAction1 (classExcitationList, 0, U"To Pattern...", nullptr, praat_HIDDEN, NEW_ExcitationList_to_PatternList);
+	praat_addAction1 (classExcitationList, 0, U"To TableOfReal", nullptr, 0, NEW_ExcitationList_to_TableOfReal);
 
-	praat_addAction2 (classExcitationList, 1, classExcitation, 0, U"Add to ExcitationList", nullptr, 0, DO_ExcitationList_addItem);
-	praat_addAction2 (classExcitationList, 1, classExcitation, 0, U"Add to Excitations", nullptr, praat_HIDDEN, DO_ExcitationList_addItem);
+	praat_addAction2 (classExcitationList, 1, classExcitation, 0, U"Add to ExcitationList", nullptr, 0, MODIFY_ExcitationList_addItem);
+	praat_addAction2 (classExcitationList, 1, classExcitation, 0, U"Add to Excitations", nullptr, praat_HIDDEN, MODIFY_ExcitationList_addItem);
 
-	praat_addAction1 (classFileInMemory, 1, U"Show as code...", nullptr, 0, DO_FileInMemory_showAsCode);
-	praat_addAction1 (classFileInMemory, 1, U"Set id...", nullptr, 0, DO_FileInMemory_setId);
-	praat_addAction1 (classFileInMemory, 0, U"To FileInMemorySet", nullptr, 0, DO_FileInMemory_to_FileInMemorySet);
-	praat_addAction1 (classFileInMemory, 0, U"To FilesInMemory", nullptr, praat_HIDDEN, DO_FileInMemory_to_FileInMemorySet); // Deprecated since 2015
+	praat_addAction1 (classFileInMemory, 1, U"Show as code...", nullptr, 0, INFO_FileInMemory_showAsCode);
+	praat_addAction1 (classFileInMemory, 1, U"Set id...", nullptr, 0, MODIFY_FileInMemory_setId);
+	praat_addAction1 (classFileInMemory, 0, U"To FileInMemorySet", nullptr, 0, NEW1_FileInMemory_to_FileInMemorySet);
+	praat_addAction1 (classFileInMemory, 0, U"To FilesInMemory", nullptr, praat_DEPRECATED_2015, NEW1_FileInMemory_to_FileInMemorySet);
 
-	praat_addAction1 (classFileInMemorySet, 1, U"Show as code...", nullptr, 0, DO_FileInMemorySet_showAsCode);
-	praat_addAction1 (classFileInMemorySet, 1, U"Show one file as code...", nullptr, 0, DO_FileInMemorySet_showOneFileAsCode);
-	praat_addAction1 (classFileInMemorySet, 2, U"Merge", nullptr, 0, DO_FileInMemorySets_merge);
-	praat_addAction1 (classFileInMemorySet, 0, U"To Strings (id)", nullptr, 0, DO_FileInMemorySet_to_Strings_id);
+	praat_addAction1 (classFileInMemorySet, 1, U"Show as code...", nullptr, 0, INFO_FileInMemorySet_showAsCode);
+	praat_addAction1 (classFileInMemorySet, 1, U"Show one file as code...", nullptr, 0, INFO_FileInMemorySet_showOneFileAsCode);
+	praat_addAction1 (classFileInMemorySet, 2, U"Merge", nullptr, 0, NEW1_FileInMemorySets_merge);
+	praat_addAction1 (classFileInMemorySet, 0, U"To Strings (id)", nullptr, 0, NEW_FileInMemorySet_to_Strings_id);
 
-	praat_addAction2 (classFileInMemorySet, 1, classFileInMemory, 0, U"Add items to Collection", nullptr, 0, DO_FileInMemorySet_addItems);
+	praat_addAction2 (classFileInMemorySet, 1, classFileInMemory, 0, U"Add items to Collection", nullptr, 0, MODIFY_FileInMemorySet_addItems);
 
-	praat_addAction1 (classFormantFilter, 0, U"FormantFilter help", nullptr, 0, DO_FormantFilter_help);
+	praat_addAction1 (classFormantFilter, 0, U"FormantFilter help", nullptr, praat_DEPRECATED_2015, HELP_FormantFilter_help);
 	praat_FilterBank_all_init (classFormantFilter);
-	praat_addAction1 (classFormantFilter, 0, U"Draw spectrum (slice)...", U"Draw filters...", praat_DEPTH_1 + praat_HIDDEN, DO_FormantFilter_drawSpectrum);
-	praat_addAction1 (classFormantFilter, 0, U"Draw filter functions...", U"Draw filters...",  praat_DEPTH_1 + praat_HIDDEN, DO_FormantFilter_drawFilterFunctions);
-	praat_addAction1 (classFormantFilter, 0, U"To Spectrogram", nullptr, 0, DO_FormantFilter_to_Spectrogram);
+	praat_addAction1 (classFormantFilter, 0, U"Draw spectrum (slice)...", U"Draw filters...", praat_DEPTH_1 | praat_DEPRECATED_2014, GRAPHICS_FormantFilter_drawSpectrum);
+	praat_addAction1 (classFormantFilter, 0, U"Draw filter functions...", U"Draw filters...",  praat_DEPTH_1  | praat_DEPRECATED_2014, GRAPHICS_FormantFilter_drawFilterFunctions);
+	praat_addAction1 (classFormantFilter, 0, U"To Spectrogram", nullptr, 0, NEW_FormantFilter_to_Spectrogram);
 
-	praat_addAction1 (classFormantGrid, 0, U"Draw...", U"Edit", praat_DEPTH_1 + praat_HIDDEN, DO_FormantGrid_draw);
+	praat_addAction1 (classFormantGrid, 0, U"Draw...", U"Edit", praat_DEPTH_1 + praat_HIDDEN, GRAPHICS_FormantGrid_draw);
 
-	praat_addAction1 (classIntensity, 0, U"To TextGrid (silences)...", U"To IntensityTier (valleys)", 0, DO_Intensity_to_TextGrid_detectSilences);
-	praat_addAction1 (classIntensityTier, 0, U"To TextGrid (silences)...", nullptr, 0, DO_IntensityTier_to_TextGrid_detectSilences);
-	praat_addAction1 (classIntensityTier, 0, U"To Intensity...", nullptr, praat_HIDDEN, DO_IntensityTier_to_Intensity);
+	praat_addAction1 (classIntensity, 0, U"To TextGrid (silences)...", U"To IntensityTier (valleys)", 0, NEW_Intensity_to_TextGrid_detectSilences);
+	praat_addAction1 (classIntensityTier, 0, U"To TextGrid (silences)...", nullptr, 0, NEW_IntensityTier_to_TextGrid_detectSilences);
+	praat_addAction1 (classIntensityTier, 0, U"To Intensity...", nullptr, praat_HIDDEN, NEW_IntensityTier_to_Intensity);
 
-	praat_addAction1 (classISpline, 0, U"ISpline help", nullptr, 0, DO_ISpline_help);
+	praat_addAction1 (classISpline, 0, U"ISpline help", nullptr, 0, HELP_ISpline_help);
 	praat_Spline_init (classISpline);
 
-	praat_addAction1 (classKlattTable, 0, U"KlattTable help", nullptr, 0, DO_KlattTable_help);
-	praat_addAction1 (classKlattTable, 0, U"To Sound...", nullptr, 0, DO_KlattTable_to_Sound);
-	praat_addAction1 (classKlattTable, 0, U"To KlattGrid...", nullptr, 0, DO_KlattTable_to_KlattGrid);
-	praat_addAction1 (classKlattTable, 0, U"To Table", nullptr, 0, DO_KlattTable_to_Table);
+	praat_addAction1 (classKlattTable, 0, U"KlattTable help", nullptr, 0, HELP_KlattTable_help);
+	praat_addAction1 (classKlattTable, 0, U"To Sound...", nullptr, 0, NEW_KlattTable_to_Sound);
+	praat_addAction1 (classKlattTable, 0, U"To KlattGrid...", nullptr, 0, NEW_KlattTable_to_KlattGrid);
+	praat_addAction1 (classKlattTable, 0, U"To Table", nullptr, 0, NEW_KlattTable_to_Table);
 
-	praat_addAction1 (classLegendreSeries, 0, U"LegendreSeries help", nullptr, 0, DO_LegendreSeries_help);
+	praat_addAction1 (classLegendreSeries, 0, U"LegendreSeries help", nullptr, 0, HELP_LegendreSeries_help);
 	praat_FunctionTerms_init (classLegendreSeries);
-	praat_addAction1 (classLegendreSeries, 0, U"To Polynomial", U"Analyse", 0, DO_LegendreSeries_to_Polynomial);
-
-	praat_addAction1 (classLongSound, 0, U"Append to existing sound file...", nullptr, 0, DO_LongSounds_appendToExistingSoundFile);
-	praat_addAction1 (classSound, 0, U"Append to existing sound file...", nullptr, 0, DO_LongSounds_appendToExistingSoundFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Append to existing sound file...", nullptr, 0, DO_LongSounds_appendToExistingSoundFile);
-
-	praat_addAction1 (classLongSound, 2, U"Save as stereo AIFF file...", U"Save as NIST file...", 1, DO_LongSounds_writeToStereoAiffFile);
-	praat_addAction1 (classLongSound, 2, U"Write to stereo AIFF file...", U"Write to NIST file...", praat_HIDDEN + praat_DEPTH_1, DO_LongSounds_writeToStereoAiffFile);
-	praat_addAction1 (classLongSound, 2, U"Save as stereo AIFC file...", U"Save as stereo AIFF file...", 1, DO_LongSounds_writeToStereoAifcFile);
-	praat_addAction1 (classLongSound, 2, U"Write to stereo AIFC file...", U"Write to stereo AIFF file...", praat_HIDDEN + praat_DEPTH_1, DO_LongSounds_writeToStereoAifcFile);
-	praat_addAction1 (classLongSound, 2, U"Save as stereo WAV file...", U"Save as stereo AIFC file...", 1, DO_LongSounds_writeToStereoWavFile);
-	praat_addAction1 (classLongSound, 2, U"Write to stereo WAV file...", U"Write to stereo AIFC file...", praat_HIDDEN + praat_DEPTH_1, DO_LongSounds_writeToStereoWavFile);
-	praat_addAction1 (classLongSound, 2, U"Save as stereo NeXt/Sun file...", U"Save as stereo WAV file...", 1, DO_LongSounds_writeToStereoNextSunFile);
-	praat_addAction1 (classLongSound, 2, U"Write to stereo NeXt/Sun file...", U"Write to stereo WAV file...", praat_HIDDEN + praat_DEPTH_1, DO_LongSounds_writeToStereoNextSunFile);
-	praat_addAction1 (classLongSound, 2, U"Save as stereo NIST file...", U"Save as stereo NeXt/Sun file...", 1, DO_LongSounds_writeToStereoNistFile);
-	praat_addAction1 (classLongSound, 2, U"Write to stereo NIST file...", U"Write to stereo NeXt/Sun file...", praat_HIDDEN + praat_DEPTH_1, DO_LongSounds_writeToStereoNistFile);
-
-	praat_addAction1 (classLtas, 0, U"Report spectral tilt...", U"Get slope...", 1, DO_Ltas_reportSpectralTilt);
-
-	praat_addAction1 (classMatrix, 0, U"Scatter plot...", U"Paint cells...", 1, DO_Matrix_scatterPlot);
-	praat_addAction1 (classMatrix, 0, U"Draw as squares...", U"Scatter plot...", 1, DO_Matrix_drawAsSquares);
-	praat_addAction1 (classMatrix, 0, U"Draw distribution...", U"Draw as squares...", 1, DO_Matrix_drawDistribution);
-	praat_addAction1 (classMatrix, 0, U"Draw cumulative distribution...", U"Draw distribution...", 1, DO_Matrix_drawCumulativeDistribution);
-	praat_addAction1 (classMatrix, 0, U"Get mean...", U"Get sum", 1, DO_Matrix_getMean);
-	praat_addAction1 (classMatrix, 0, U"Get standard deviation...", U"Get mean...", 1, DO_Matrix_getStandardDeviation);
-	praat_addAction1 (classMatrix, 0, U"Transpose", U"Synthesize", 0, DO_Matrix_transpose);
-	praat_addAction1 (classMatrix, 0, U"Solve equation...", U"Analyse", 0, DO_Matrix_solveEquation);
-	praat_addAction1 (classMatrix, 0, U"To PCA (by rows)", U"Solve equation...", 0, DO_Matrix_to_PCA_byRows);
-	praat_addAction1 (classMatrix, 0, U"To PCA (by columns)", U"To PCA (by rows)", 0, DO_Matrix_to_PCA_byColumns);
-	praat_addAction1 (classMatrix, 0, U"To PatternList...", U"To VocalTract", 1, DO_Matrix_to_PatternList);
-	praat_addAction1 (classMatrix, 0, U"To Pattern...", U"To VocalTract", praat_HIDDEN, DO_Matrix_to_PatternList);
-	praat_addAction1 (classMatrix, 0, U"To ActivationList", U"To PatternList...", 1, DO_Matrix_to_ActivationList);
-	praat_addAction1 (classMatrix, 0, U"To Activation", U"To PatternList...", praat_HIDDEN, DO_Matrix_to_ActivationList);
-	praat_addAction1 (classMatrix, 2, U"To DTW...", U"To ParamCurve", 1, DO_Matrices_to_DTW);
-
-	praat_addAction2 (classMatrix, 1, classCategories, 1, U"To TableOfReal", nullptr, 0, DO_Matrix_Categories_to_TableOfReal);
-
-	praat_addAction1 (classMelSpectrogram, 0, U"MelSpectrogram help", nullptr, 0, DO_MelSpectrogram_help);
+	praat_addAction1 (classLegendreSeries, 0, U"To Polynomial", U"Analyse", 0, NEW_LegendreSeries_to_Polynomial);
+
+	praat_addAction1 (classLongSound, 0, U"Append to existing sound file...", nullptr, 0, READ1_LongSounds_appendToExistingSoundFile);
+	praat_addAction1 (classSound, 0, U"Append to existing sound file...", nullptr, 0, READ1_LongSounds_appendToExistingSoundFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Append to existing sound file...", nullptr, 0, READ1_LongSounds_appendToExistingSoundFile);
+
+	praat_addAction1 (classLongSound, 2, U"Save as stereo AIFF file...", U"Save as NIST file...", 1, SAVE_LongSounds_writeToStereoAiffFile);
+	praat_addAction1 (classLongSound, 2, U"Write to stereo AIFF file...", U"Write to NIST file...", praat_HIDDEN + praat_DEPTH_1, SAVE_LongSounds_writeToStereoAiffFile);
+	praat_addAction1 (classLongSound, 2, U"Save as stereo AIFC file...", U"Save as stereo AIFF file...", 1, SAVE_LongSounds_writeToStereoAifcFile);
+	praat_addAction1 (classLongSound, 2, U"Write to stereo AIFC file...", U"Write to stereo AIFF file...", praat_HIDDEN + praat_DEPTH_1, SAVE_LongSounds_writeToStereoAifcFile);
+	praat_addAction1 (classLongSound, 2, U"Save as stereo WAV file...", U"Save as stereo AIFC file...", 1, SAVE_LongSounds_writeToStereoWavFile);
+	praat_addAction1 (classLongSound, 2, U"Write to stereo WAV file...", U"Write to stereo AIFC file...", praat_HIDDEN + praat_DEPTH_1, SAVE_LongSounds_writeToStereoWavFile);
+	praat_addAction1 (classLongSound, 2, U"Save as stereo NeXt/Sun file...", U"Save as stereo WAV file...", 1, SAVE_LongSounds_writeToStereoNextSunFile);
+	praat_addAction1 (classLongSound, 2, U"Write to stereo NeXt/Sun file...", U"Write to stereo WAV file...", praat_HIDDEN + praat_DEPTH_1, SAVE_LongSounds_writeToStereoNextSunFile);
+	praat_addAction1 (classLongSound, 2, U"Save as stereo NIST file...", U"Save as stereo NeXt/Sun file...", 1, SAVE_LongSounds_writeToStereoNistFile);
+	praat_addAction1 (classLongSound, 2, U"Write to stereo NIST file...", U"Write to stereo NeXt/Sun file...", praat_HIDDEN + praat_DEPTH_1, SAVE_LongSounds_writeToStereoNistFile);
+
+	praat_addAction1 (classLtas, 0, U"Report spectral tilt...", U"Get slope...", 1, INFO_Ltas_reportSpectralTilt);
+
+	praat_addAction1 (classMatrix, 0, U"Scatter plot...", U"Paint cells...", 1, GRAPHICS_Matrix_scatterPlot);
+	praat_addAction1 (classMatrix, 0, U"Draw as squares...", U"Scatter plot...", 1, GRAPHICS_Matrix_drawAsSquares);
+	praat_addAction1 (classMatrix, 0, U"Draw distribution...", U"Draw as squares...", 1, GRAPHICS_Matrix_drawDistribution);
+	praat_addAction1 (classMatrix, 0, U"Draw cumulative distribution...", U"Draw distribution...", 1, GRAPHICS_Matrix_drawCumulativeDistribution);
+	praat_addAction1 (classMatrix, 0, U"Get mean...", U"Get sum", 1, REAL_Matrix_getMean);
+	praat_addAction1 (classMatrix, 0, U"Get standard deviation...", U"Get mean...", 1, REAL_Matrix_getStandardDeviation);
+	praat_addAction1 (classMatrix, 0, U"Transpose", U"Synthesize", 0, NEW_Matrix_transpose);
+	praat_addAction1 (classMatrix, 0, U"Solve equation...", U"Analyse", 0, NEW_Matrix_solveEquation);
+	praat_addAction1 (classMatrix, 0, U"To PCA (by rows)", U"Solve equation...", 0, NEW_Matrix_to_PCA_byRows);
+	praat_addAction1 (classMatrix, 0, U"To PCA (by columns)", U"To PCA (by rows)", 0, NEW_Matrix_to_PCA_byColumns);
+	praat_addAction1 (classMatrix, 0, U"To PatternList...", U"To VocalTract", 1, NEW_Matrix_to_PatternList);
+	praat_addAction1 (classMatrix, 0, U"To Pattern...", U"*To PatternList...", praat_DEPRECATED_2016, NEW_Matrix_to_PatternList);
+	praat_addAction1 (classMatrix, 0, U"To ActivationList", U"To PatternList...", 1, NEW_Matrix_to_ActivationList);
+	praat_addAction1 (classMatrix, 0, U"To Activation", U"*To ActivationList", praat_DEPRECATED_2016, NEW_Matrix_to_ActivationList);
+	praat_addAction1 (classMatrix, 2, U"To DTW...", U"To ParamCurve", 1, NEW1_Matrices_to_DTW);
+
+	praat_addAction2 (classMatrix, 1, classCategories, 1, U"To TableOfReal", nullptr, 0, NEW1_Matrix_Categories_to_TableOfReal);
+
+	praat_addAction1 (classMelSpectrogram, 0, U"MelSpectrogram help", nullptr, 0, HELP_MelSpectrogram_help);
 	praat_BandFilterSpectrogram_draw_init (classMelSpectrogram);
-	praat_addAction1 (classMelSpectrogram, 0, U"Paint image...", nullptr, 1, DO_MelSpectrogram_paintImage);
-	praat_addAction1 (classMelSpectrogram, 0, U"Draw triangular filter functions...", nullptr, 1, DO_MelSpectrogram_drawTriangularFilterFunctions);
-	praat_addAction1 (classMelSpectrogram, 0, U"Draw spectrum at nearest time slice...", nullptr, 1, DO_MelSpectrogram_drawSpectrumAtNearestTimeSlice);
+	praat_addAction1 (classMelSpectrogram, 0, U"Paint image...", nullptr, 1, GRAPHICS_MelSpectrogram_paintImage);
+	praat_addAction1 (classMelSpectrogram, 0, U"Draw triangular filter functions...", nullptr, 1, GRAPHICS_MelSpectrogram_drawTriangularFilterFunctions);
+	praat_addAction1 (classMelSpectrogram, 0, U"Draw spectrum at nearest time slice...", nullptr, 1, GRAPHICS_MelSpectrogram_drawSpectrumAtNearestTimeSlice);
 	praat_addAction1 (classMelSpectrogram, 0, QUERY_BUTTON, nullptr, 0, 0);
 	praat_BandFilterSpectrogram_query_init (classMelSpectrogram);
 
-	praat_addAction1 (classMelSpectrogram, 0, U"Equalize intensities...", nullptr, 0, DO_BandFilterSpectrogram_equalizeIntensities);
-	praat_addAction1 (classMelSpectrogram, 0, U"To MFCC...", nullptr, 0, DO_MelSpectrogram_to_MFCC);
-	praat_addAction1 (classMelSpectrogram, 0, U"To Intensity", nullptr, 0, DO_BandFilterSpectrogram_to_Intensity);
-	praat_addAction1 (classMelSpectrogram, 0, U"To Matrix...", nullptr, 0, DO_BandFilterSpectrogram_to_Matrix);
-	praat_addAction1 (classMelSpectrogram, 2, U"Cross-correlate...", nullptr, 0, DO_BandFilterSpectrograms_crossCorrelate);
-	praat_addAction1 (classMelSpectrogram, 2, U"Convolve...", nullptr, 0, DO_BandFilterSpectrograms_convolve);
+	praat_addAction1 (classMelSpectrogram, 0, U"Equalize intensities...", nullptr, 0, MODIFY_BandFilterSpectrogram_equalizeIntensities);
+	praat_addAction1 (classMelSpectrogram, 0, U"To MFCC...", nullptr, 0, NEW_MelSpectrogram_to_MFCC);
+	praat_addAction1 (classMelSpectrogram, 0, U"To Intensity", nullptr, 0, NEW_BandFilterSpectrogram_to_Intensity);
+	praat_addAction1 (classMelSpectrogram, 0, U"To Matrix...", nullptr, 0, NEW_BandFilterSpectrogram_to_Matrix);
+	praat_addAction1 (classMelSpectrogram, 2, U"Cross-correlate...", nullptr, 0, NEW1_BandFilterSpectrograms_crossCorrelate);
+	praat_addAction1 (classMelSpectrogram, 2, U"Convolve...", nullptr, 0, NEW1_BandFilterSpectrograms_convolve);
 	
-	praat_addAction1 (classMelFilter, 0, U"MelFilter help", nullptr, 0, DO_MelFilter_help); // deprecated 2014
+	praat_addAction1 (classMelFilter, 0, U"MelFilter help", U"*MelSpectrogram help", 0, HELP_MelFilter_help);
 	praat_FilterBank_all_init (classMelFilter); // deprecated 2014
-	praat_addAction1 (classMelFilter, 0, U"Draw spectrum (slice)...", U"Draw filters...", praat_DEPTH_1 + praat_HIDDEN, DO_MelFilter_drawSpectrum); // deprecated 2014
-	praat_addAction1 (classMelFilter, 0, U"Draw filter functions...", U"Draw filters...", praat_DEPTH_1 + praat_HIDDEN, DO_MelFilter_drawFilterFunctions); // deprecated 2014
-	praat_addAction1 (classMelFilter, 0, U"Paint...", U"Draw filter functions...", praat_DEPTH_1 + praat_HIDDEN, DO_MelFilter_paint); // deprecated 2014
-	praat_addAction1 (classMelFilter, 0, U"To MFCC...", nullptr, praat_HIDDEN, DO_MelFilter_to_MFCC); // deprecated 2014
-	praat_addAction1 (classMelFilter, 0, U"To MelSpectrogram", nullptr, 0, DO_MelFilter_to_MelSpectrogram);
+	praat_addAction1 (classMelFilter, 0, U"Draw spectrum (slice)...", U"Draw filters...", praat_DEPTH_1 | praat_DEPRECATED_2014, GRAPHICS_MelFilter_drawSpectrum); 
+	praat_addAction1 (classMelFilter, 0, U"Draw filter functions...", U"Draw filters...", praat_DEPTH_1 | praat_DEPRECATED_2014, GRAPHICS_MelFilter_drawFilterFunctions);
+	praat_addAction1 (classMelFilter, 0, U"Paint...", U"Draw filter functions...", praat_DEPTH_1 | praat_DEPRECATED_2014, GRAPHICS_MelFilter_paint);
+	praat_addAction1 (classMelFilter, 0, U"To MFCC...", nullptr, praat_DEPRECATED_2014, NEW_MelFilter_to_MFCC); // deprecated 2014
+	praat_addAction1 (classMelFilter, 0, U"To MelSpectrogram", nullptr, 0, NEW_MelFilter_to_MelSpectrogram);
 	
-	praat_addAction1 (classMFCC, 0, U"MFCC help", nullptr, 0, DO_MFCC_help);
+	praat_addAction1 (classMFCC, 0, U"MFCC help", nullptr, 0, HELP_MFCC_help);
 	praat_CC_init (classMFCC);
-	praat_addAction1 (classMFCC, 0, U"To MelFilter...", nullptr, praat_HIDDEN, DO_MFCC_to_MelFilter);
-	praat_addAction1 (classMFCC, 0, U"To MelSpectrogram...", nullptr, 0, DO_MFCC_to_MelSpectrogram);
-	praat_addAction1 (classMFCC, 0, U"To TableOfReal...", nullptr, 0, DO_MFCC_to_TableOfReal);
-	praat_addAction1 (classMFCC, 0, U"To Matrix (features)...", nullptr, praat_HIDDEN, DO_MFCC_to_Matrix_features);
-	praat_addAction1 (classMFCC, 0, U"To Sound", nullptr, praat_HIDDEN, DO_MFCC_to_Sound);
-	praat_addAction1 (classMFCC, 2, U"Cross-correlate...", nullptr, 0, DO_MFCCs_crossCorrelate);
-	praat_addAction1 (classMFCC, 2, U"Convolve...", nullptr, 0, DO_MFCCs_convolve);
-
-	praat_addAction1 (classMSpline, 0, U"MSpline help", nullptr, 0, DO_MSpline_help);
+	praat_addAction1 (classMFCC, 0, U"To MelFilter...", nullptr, praat_DEPRECATED_2014, NEW_MFCC_to_MelFilter);
+	praat_addAction1 (classMFCC, 0, U"To MelSpectrogram...", nullptr, 0, NEW_MFCC_to_MelSpectrogram);
+	praat_addAction1 (classMFCC, 0, U"To TableOfReal...", nullptr, 0, NEW_MFCC_to_TableOfReal);
+	praat_addAction1 (classMFCC, 0, U"To Matrix (features)...", nullptr, praat_HIDDEN, NEW_MFCC_to_Matrix_features);
+	praat_addAction1 (classMFCC, 0, U"To Sound", nullptr, praat_HIDDEN, NEW_MFCC_to_Sound);
+	praat_addAction1 (classMFCC, 2, U"Cross-correlate...", nullptr, 0, NEW1_MFCCs_crossCorrelate);
+	praat_addAction1 (classMFCC, 2, U"Convolve...", nullptr, 0, NEW1_MFCCs_convolve);
+
+	praat_addAction1 (classMSpline, 0, U"MSpline help", nullptr, 0, HELP_MSpline_help);
 	praat_Spline_init (classMSpline);
 
 	praat_addAction1 (classPatternList, 0, U"Draw", nullptr, 0, 0);
-	praat_addAction1 (classPatternList, 0, U"Draw...", nullptr, 0, DO_PatternList_draw);
+	praat_addAction1 (classPatternList, 0, U"Draw...", nullptr, 0, GRAPHICS_PatternList_draw);
 	praat_PatternList_query_init (classPatternList);
 	praat_addAction1 (classPatternList, 0, MODIFY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classPatternList, 0, U"Formula...", nullptr, 1, DO_PatternList_formula);
-	praat_addAction1 (classPatternList, 0, U"Set value...", nullptr, 1, DO_PatternList_setValue);
-	praat_addAction1 (classPatternList, 0, U"To Matrix", nullptr, 0, DO_PatternList_to_Matrix);
+	praat_addAction1 (classPatternList, 0, U"Formula...", nullptr, 1, MODIFY_PatternList_formula);
+	praat_addAction1 (classPatternList, 0, U"Set value...", nullptr, 1, MODIFY_PatternList_setValue);
+	praat_addAction1 (classPatternList, 0, U"To Matrix", nullptr, 0, NEW_PatternList_to_Matrix);
 
-	praat_addAction2 (classPatternList, 1, classCategories, 1, U"To TableOfReal", nullptr, 0, DO_Matrix_Categories_to_TableOfReal);
-	praat_addAction2 (classPatternList, 1, classCategories, 1, U"To Discriminant", nullptr, 0, DO_PatternList_and_Categories_to_Discriminant);
+	praat_addAction2 (classPatternList, 1, classCategories, 1, U"To TableOfReal", nullptr, 0, NEW1_Matrix_Categories_to_TableOfReal);
+	praat_addAction2 (classPatternList, 1, classCategories, 1, U"To Discriminant", nullptr, 0, NEW1_PatternList_and_Categories_to_Discriminant);
 
-	praat_addAction1 (classPCA, 0, U"PCA help", nullptr, 0, DO_PCA_help);
+	praat_addAction1 (classPCA, 0, U"PCA help", nullptr, 0, HELP_PCA_help);
 	praat_addAction1 (classPCA, 0, DRAW_BUTTON, nullptr, 0, 0);
 	praat_Eigen_draw_init (classPCA);
 	praat_addAction1 (classPCA, 0, QUERY_BUTTON, nullptr, 0, 0);
 	praat_Eigen_query_init (classPCA);
 	praat_addAction1 (classPCA, 1, U"-- pca --", nullptr, 1, 0);
-	praat_addAction1 (classPCA, 1, U"Get centroid element...", nullptr, 1, DO_PCA_getCentroidElement);
-	praat_addAction1 (classPCA, 1, U"Get equality of eigenvalues...", nullptr, 1, DO_PCA_getEqualityOfEigenvalues);
-	praat_addAction1 (classPCA, 1, U"Get fraction variance accounted for...", nullptr, 1, DO_PCA_getFractionVAF);
-	praat_addAction1 (classPCA, 1, U"Get number of components (VAF)...", nullptr, 1, DO_PCA_getNumberOfComponentsVAF);
-	praat_addAction1 (classPCA, 2, U"Get angle between pc1-pc2 planes", nullptr, 1, DO_PCAs_getAngleBetweenPc1Pc2Plane_degrees);
+	praat_addAction1 (classPCA, 1, U"Get centroid element...", nullptr, 1, REAL_PCA_getCentroidElement);
+	praat_addAction1 (classPCA, 1, U"Get equality of eigenvalues...", nullptr, 1, REAL_PCA_getEqualityOfEigenvalues);
+	praat_addAction1 (classPCA, 1, U"Get fraction variance accounted for...", nullptr, 1, REAL_PCA_getFractionVAF);
+	praat_addAction1 (classPCA, 1, U"Get number of components (VAF)...", nullptr, 1, INTEGER_PCA_getNumberOfComponentsVAF);
+	praat_addAction1 (classPCA, 2, U"Get angle between pc1-pc2 planes", nullptr, 1, REAL_PCAs_getAngleBetweenPc1Pc2Plane_degrees);
 	praat_addAction1 (classPCA, 0, MODIFY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classPCA, 1, U"Invert eigenvector...", nullptr, 1, DO_PCA_invertEigenvector);
-	praat_addAction1 (classPCA, 0, U"Align eigenvectors", nullptr, 1, DO_Eigens_alignEigenvectors);
-	praat_addAction1 (classPCA, 2, U"To Procrustes...", nullptr, 0, DO_PCAs_to_Procrustes);
-	praat_addAction1 (classPCA, 0, U"To TableOfReal (reconstruct 1)...", nullptr, 0, DO_PCA_to_TableOfReal_reconstruct1);
-	praat_addAction1 (classPCA, 0, U"Extract eigenvector...", nullptr, 0, DO_PCA_extractEigenvector);
-	praat_addAction1 (classPCA, 0, U"& TableOfReal: To Configuration?", nullptr, 0, DO_hint_PCA_and_TableOfReal_to_Configuration);
-	praat_addAction1 (classPCA, 0, U"& Configuration (reconstruct)?", nullptr, 0, DO_hint_PCA_and_Configuration_to_TableOfReal_reconstruct);
-	praat_addAction1 (classPCA, 0, U"& Covariance: Project?", nullptr, 0, DO_hint_PCA_and_Covariance_Project);
-	praat_addAction2 (classPCA, 1, classConfiguration, 1, U"To TableOfReal (reconstruct)", nullptr, 0, DO_PCA_and_Configuration_to_TableOfReal_reconstruct);
-	praat_addAction2 (classPCA, 1, classMatrix, 1, U"To Matrix (pc)...", nullptr, praat_HIDDEN, DO_PCA_and_Matrix_to_Matrix_projectColumns);
-	praat_addAction2 (classPCA, 1, classMatrix, 1, U"To Matrix (project rows)...", nullptr, 0, DO_PCA_and_Matrix_to_Matrix_projectRows);
-	praat_addAction2 (classPCA, 1, classMatrix, 1, U"To Matrix (project columns)...", nullptr, 0, DO_PCA_and_Matrix_to_Matrix_projectColumns);
-	praat_addAction2 (classPCA, 1, classPatternList, 1, U"To Matrix (project rows)...", nullptr, 0, DO_PCA_and_Matrix_to_Matrix_projectRows);
-	praat_addAction2 (classPCA, 1, classSSCP, 1, U"Project", nullptr, 0, DO_Eigen_and_SSCP_project);
-	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To TableOfReal...", nullptr, 0, DO_PCA_and_TableOfReal_to_TableOfReal_projectRows);
-	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To TableOfReal (project rows)...", nullptr, 0, DO_PCA_and_TableOfReal_to_TableOfReal_projectRows);
-	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To Configuration...", nullptr, 0, DO_PCA_and_TableOfReal_to_Configuration);
-	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To TableOfReal (z-scores)...", nullptr, 0, DO_PCA_and_TableOfReal_to_TableOfReal_zscores);
-	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"Get fraction variance...", nullptr, 0, DO_PCA_and_TableOfReal_getFractionVariance);
-	praat_addAction2 (classPCA, 1, classCovariance, 1, U"Project", nullptr, 0, DO_Eigen_and_Covariance_project);
+	praat_addAction1 (classPCA, 1, U"Invert eigenvector...", nullptr, 1, MODIFY_PCA_invertEigenvector);
+	praat_addAction1 (classPCA, 0, U"Align eigenvectors", nullptr, 1, MODIFY_Eigens_alignEigenvectors);
+	praat_addAction1 (classPCA, 0, U"Extract -", nullptr, 0, 0);
+		praat_addAction1 (classPCA, 0, U"Extract eigenvector...", nullptr, 1, NEW_PCA_extractEigenvector);
+		praat_addAction1 (classPCA, 0, U"Extract Eigen", nullptr, 1, NEW_PCA_extractEigen);
+	praat_addAction1 (classPCA, 2, U"To Procrustes...", nullptr, 0, NEW1_PCAs_to_Procrustes);
+	praat_addAction1 (classPCA, 0, U"To TableOfReal (reconstruct 1)...", nullptr, 0, NEW_PCA_to_TableOfReal_reconstruct1);
+	
+	praat_addAction1 (classPCA, 0, U"& TableOfReal: To Configuration?", nullptr, praat_NO_API, HINT_hint_PCA_and_TableOfReal_to_Configuration);
+	praat_addAction1 (classPCA, 0, U"& Configuration (reconstruct)?", nullptr, praat_NO_API, HINT_hint_PCA_and_Configuration_to_TableOfReal_reconstruct);
+	praat_addAction1 (classPCA, 0, U"& Covariance: Project?", nullptr, praat_NO_API, HINT_hint_PCA_and_Covariance_Project);
+	praat_addAction2 (classPCA, 1, classConfiguration, 1, U"To TableOfReal (reconstruct)", nullptr, 0, NEW_PCA_and_Configuration_to_TableOfReal_reconstruct);
+	praat_addAction2 (classPCA, 1, classMatrix, 1, U"To Matrix (pc)...", nullptr, praat_HIDDEN, NEW1_PCA_and_Matrix_to_Matrix_projectColumns);
+	praat_addAction2 (classPCA, 1, classMatrix, 1, U"To Matrix (project rows)...", nullptr, 0, NEW1_PCA_and_Matrix_to_Matrix_projectRows);
+	praat_addAction2 (classPCA, 1, classMatrix, 1, U"To Matrix (project columns)...", nullptr, 0, NEW1_PCA_and_Matrix_to_Matrix_projectColumns);
+	praat_addAction2 (classPCA, 1, classPatternList, 1, U"To Matrix (project rows)...", nullptr, 0, NEW1_PCA_and_Matrix_to_Matrix_projectRows);
+	praat_addAction2 (classPCA, 1, classSSCP, 1, U"Project", nullptr, 0, NEW1_Eigen_and_SSCP_project);
+	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To TableOfReal (project rows)...", nullptr, 0, NEW1_PCA_and_TableOfReal_to_TableOfReal_projectRows);
+	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To TableOfReal...", U"*To TableOfReal (project rows)...", praat_DEPRECATED_2016, NEW1_PCA_and_TableOfReal_to_TableOfReal_projectRows);
+	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To Configuration...", nullptr, 0, NEW1_PCA_and_TableOfReal_to_Configuration);
+	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"To TableOfReal (z-scores)...", nullptr, 0, NEW1_PCA_and_TableOfReal_to_TableOfReal_zscores);
+	praat_addAction2 (classPCA, 1, classTableOfReal, 1, U"Get fraction variance...", nullptr, 0, REAL_PCA_and_TableOfReal_getFractionVariance);
+	praat_addAction2 (classPCA, 1, classCovariance, 1, U"Project", nullptr, 0, NEW1_Eigen_and_Covariance_project);
 
 	praat_Eigen_Spectrogram_project (classPCA, classSpectrogram);
 	praat_Eigen_Spectrogram_project (classPCA, classBarkSpectrogram);
@@ -9504,270 +7793,271 @@ void praat_uvafon_David_init () {
 	praat_Eigen_Matrix_project (classPCA, classBarkFilter); // deprecated 2014
 	praat_Eigen_Matrix_project (classPCA, classMelFilter); // deprecated 2014
 
-	praat_addAction1 (classPermutation, 0, U"Permutation help", nullptr, 0, DO_Permutation_help);
+	praat_addAction1 (classPermutation, 0, U"Permutation help", nullptr, 0, HELP_Permutation_help);
 	praat_addAction1 (classPermutation, 0, QUERY_BUTTON, 0, 0, 0);
-	praat_addAction1 (classPermutation, 1, U"Get number of elements", nullptr, 1, DO_Permutation_getNumberOfElements);
-	praat_addAction1 (classPermutation, 1, U"Get value...", nullptr, 1, DO_Permutation_getValueAtIndex);
-	praat_addAction1 (classPermutation, 1, U"Get index...", nullptr, 1, DO_Permutation_getIndexAtValue);
+	praat_addAction1 (classPermutation, 1, U"Get number of elements", nullptr, 1, INTEGER_Permutation_getNumberOfElements);
+	praat_addAction1 (classPermutation, 1, U"Get value...", nullptr, 1, INTEGER_Permutation_getValueAtIndex);
+	praat_addAction1 (classPermutation, 1, U"Get index...", nullptr, 1, INTEGER_Permutation_getIndexAtValue);
 	praat_addAction1 (classPermutation, 0, MODIFY_BUTTON, 0, 0, 0);
-	praat_addAction1 (classPermutation, 1, U"Sort", nullptr, 1, DO_Permutation_sort);
-	praat_addAction1 (classPermutation, 1, U"Swap blocks...", nullptr, 1, DO_Permutation_swapBlocks);
-	praat_addAction1 (classPermutation, 1, U"Swap numbers...", nullptr, 1, DO_Permutation_swapNumbers);
-	praat_addAction1 (classPermutation, 1, U"Swap positions...", nullptr, 1, DO_Permutation_swapPositions);
-	praat_addAction1 (classPermutation, 1, U"Swap one from range...", nullptr, 1, DO_Permutation_swapOneFromRange);
+	praat_addAction1 (classPermutation, 1, U"Sort", nullptr, 1, MODIFY_Permutation_sort);
+	praat_addAction1 (classPermutation, 1, U"Swap blocks...", nullptr, 1, MODIFY_Permutation_swapBlocks);
+	praat_addAction1 (classPermutation, 1, U"Swap numbers...", nullptr, 1, MODIFY_Permutation_swapNumbers);
+	praat_addAction1 (classPermutation, 1, U"Swap positions...", nullptr, 1, MODIFY_Permutation_swapPositions);
+	praat_addAction1 (classPermutation, 1, U"Swap one from range...", nullptr, 1, MODIFY_Permutation_swapOneFromRange);
 	praat_addAction1 (classPermutation, 0, U"-- sequential permutations --", nullptr, 1, 0);
-	praat_addAction1 (classPermutation, 0, U"Next", nullptr, 1, DO_Permutations_next);
-	praat_addAction1 (classPermutation, 0, U"Previous", nullptr, 1, DO_Permutations_previous);
-	praat_addAction1 (classPermutation, 1, U"Permute randomly...", nullptr, 0, DO_Permutation_permuteRandomly);
-	praat_addAction1 (classPermutation, 1, U"Permute randomly (blocks)...", nullptr, 0, DO_Permutation_permuteBlocksRandomly);
-	praat_addAction1 (classPermutation, 1, U"Interleave...", nullptr, 0, DO_Permutation_interleave);
-	praat_addAction1 (classPermutation, 1, U"Rotate...", nullptr, 0, DO_Permutation_rotate);
-	praat_addAction1 (classPermutation, 1, U"Reverse...", nullptr, 0, DO_Permutation_reverse);
-	praat_addAction1 (classPermutation, 1, U"Invert", nullptr, 0, DO_Permutation_invert);
-	praat_addAction1 (classPermutation, 0, U"Multiply", nullptr, 0, DO_Permutations_multiply);
-
-	praat_addAction1 (classPitch, 2, U"To DTW...", U"To PointProcess", praat_HIDDEN, DO_Pitches_to_DTW);
-
-	praat_addAction1 (classPitchTier, 0, U"To Pitch...", U"To Sound (sine)...", 1, DO_PitchTier_to_Pitch);
+	praat_addAction1 (classPermutation, 0, U"Next", nullptr, 1, MODIFY_Permutations_next);
+	praat_addAction1 (classPermutation, 0, U"Previous", nullptr, 1, MODIFY_Permutations_previous);
+	
+	praat_addAction1 (classPermutation, 1, U"Permute randomly...", nullptr, 0, NEW_Permutation_permuteRandomly);
+	praat_addAction1 (classPermutation, 1, U"Permute randomly (blocks)...", nullptr, 0, NEW_Permutation_permuteBlocksRandomly);
+	praat_addAction1 (classPermutation, 1, U"Interleave...", nullptr, 0, NEW_Permutation_interleave);
+	praat_addAction1 (classPermutation, 1, U"Rotate...", nullptr, 0, NEW_Permutation_rotate);
+	praat_addAction1 (classPermutation, 1, U"Reverse...", nullptr, 0, NEW_Permutation_reverse);
+	praat_addAction1 (classPermutation, 1, U"Invert", nullptr, 0, NEW_Permutation_invert);
+	praat_addAction1 (classPermutation, 0, U"Multiply", nullptr, 0, NEW1_Permutations_multiply);
+
+	praat_addAction1 (classPitch, 2, U"To DTW...", U"To PointProcess", praat_HIDDEN, NEW1_Pitches_to_DTW);
+
+	praat_addAction1 (classPitchTier, 0, U"To Pitch...", U"To Sound (sine)...", 1, NEW_PitchTier_to_Pitch);
 	praat_addAction1 (classPolygon, 0, QUERY_BUTTON, U"Paint circles...", 0, 0);
-	praat_addAction1 (classPolygon, 0, U"Get number of points", QUERY_BUTTON, 1, DO_Polygon_getNumberOfPoints);
-	praat_addAction1 (classPolygon, 0, U"Get point (x)...", U"Get number of points", 1, DO_Polygon_getPointX);
-	praat_addAction1 (classPolygon, 0, U"Get point (y)...",  U"Get point (x)...", 1, DO_Polygon_getPointY);
+	praat_addAction1 (classPolygon, 0, U"Get number of points", QUERY_BUTTON, 1, INTEGER_Polygon_getNumberOfPoints);
+	praat_addAction1 (classPolygon, 0, U"Get point (x)...", U"Get number of points", 1, REAL_Polygon_getPointX);
+	praat_addAction1 (classPolygon, 0, U"Get point (y)...",  U"Get point (x)...", 1, REAL_Polygon_getPointY);
 	praat_addAction1 (classPolygon, 0, U"-- other queries --",  U"Get point (y)...", 1, 0);
-	praat_addAction1 (classPolygon, 0, U"Get location of point...", U"-- other queries --", 1, DO_Polygon_getLocationOfPoint);
-	praat_addAction1 (classPolygon, 0, U"Get area of convex hull...", U"Get location of point...", praat_DEPTH_1 + praat_HIDDEN, DO_Polygon_getAreaOfConvexHull);
+	praat_addAction1 (classPolygon, 0, U"Get location of point...", U"-- other queries --", 1, INFO_Polygon_getLocationOfPoint);
+	praat_addAction1 (classPolygon, 0, U"Get area of convex hull...", U"Get location of point...", praat_DEPTH_1 + praat_HIDDEN, REAL_Polygon_getAreaOfConvexHull);
 	
-	praat_addAction1 (classPolygon, 0, U"Translate...", MODIFY_BUTTON, 1, DO_Polygon_translate);
-	praat_addAction1 (classPolygon, 0, U"Rotate...", U"Translate...", 1, DO_Polygon_rotate);
-	praat_addAction1 (classPolygon, 0, U"Scale...", U"Rotate...", 1, DO_Polygon_scale);
-	praat_addAction1 (classPolygon, 0, U"Reverse X", U"Scale...", 1, DO_Polygon_reverseX);
-	praat_addAction1 (classPolygon, 0, U"Reverse Y", U"Reverse X", 1, DO_Polygon_reverseY);
-	praat_addAction1 (classPolygon, 0, U"Simplify", nullptr, praat_HIDDEN, DO_Polygon_simplify);
-	praat_addAction1 (classPolygon, 0, U"Convex hull", nullptr, 0, DO_Polygon_convexHull);
-	praat_addAction1 (classPolygon, 0, U"Circular permutation...", nullptr, praat_HIDDEN, DO_Polygon_circularPermutation);
-
-	praat_addAction2 (classPolygon, 1, classCategories, 1, U"Draw...", nullptr, 0, DO_Polygon_Categories_draw);
-
-	praat_addAction1 (classPolynomial, 0, U"Polynomial help", nullptr, 0, DO_Polynomial_help);
+	praat_addAction1 (classPolygon, 0, U"Translate...", MODIFY_BUTTON, 1, MODIFY_Polygon_translate);
+	praat_addAction1 (classPolygon, 0, U"Rotate...", U"Translate...", 1, MODIFY_Polygon_rotate);
+	praat_addAction1 (classPolygon, 0, U"Scale...", U"Rotate...", 1, MODIFY_Polygon_scale);
+	praat_addAction1 (classPolygon, 0, U"Reverse X", U"Scale...", 1, MODIFY_Polygon_reverseX);
+	praat_addAction1 (classPolygon, 0, U"Reverse Y", U"Reverse X", 1, MODIFY_Polygon_reverseY);
+	praat_addAction1 (classPolygon, 0, U"Simplify", nullptr, praat_HIDDEN, NEW_Polygon_simplify);
+	praat_addAction1 (classPolygon, 0, U"Convex hull", nullptr, 0, NEW_Polygon_convexHull);
+	praat_addAction1 (classPolygon, 0, U"Circular permutation...", nullptr, praat_HIDDEN, NEW_Polygon_circularPermutation);
+
+	praat_addAction2 (classPolygon, 1, classCategories, 1, U"Draw...", nullptr, 0, GRAPHICS_Polygon_Categories_draw);
+
+	praat_addAction1 (classPolynomial, 0, U"Polynomial help", nullptr, 0, HELP_Polynomial_help);
 	praat_FunctionTerms_init (classPolynomial);
 	praat_addAction1 (classPolynomial, 0, U"-- area --", U"Get x of maximum...", 1, 0);
-	praat_addAction1 (classPolynomial, 1, U"Get area...", U"-- area --", 1, DO_Polynomial_getArea);
-	praat_addAction1 (classPolynomial, 1, U"Get remainder...", U"Get area...", 1, DO_Polynomial_getRemainder);
+	praat_addAction1 (classPolynomial, 1, U"Get area...", U"-- area --", 1, REAL_Polynomial_getArea);
+	praat_addAction1 (classPolynomial, 1, U"Get remainder after division...", U"Get area...", 1, REAL_Polynomial_getRemainderAfterDivision);
+	praat_addAction1 (classPolynomial, 1, U"Get remainder...", U"*Get remainder after division...", praat_DEPRECATED_2016, REAL_Polynomial_getRemainderAfterDivision);
 	praat_addAction1 (classPolynomial, 0, U"-- monic --", U"Set coefficient...", 1, 0);
-	praat_addAction1 (classPolynomial, 0, U"Scale coefficients (monic)", U"-- monic --", 1, DO_Polynomial_scaleCoefficients_monic);
-	praat_addAction1 (classPolynomial, 1, U"Divide (second order factor)...", U"Scale coefficients (monic)", 1, DO_Polynomial_divide_secondOrderFactor);
+	praat_addAction1 (classPolynomial, 0, U"Scale coefficients (monic)", U"-- monic --", 1, MODIFY_Polynomial_scaleCoefficients_monic);
+	praat_addAction1 (classPolynomial, 1, U"Divide (second order factor)...", U"Scale coefficients (monic)", 1, MODIFY_Polynomial_divide_secondOrderFactor);
 	
-	praat_addAction1 (classPolynomial, 1, U"Get value (complex)...", U"Get value...", 1, DO_Polynomial_evaluate_z);
-	praat_addAction1 (classPolynomial, 1, U"Get derivatives at X...", U"Get value (complex)...", 1, DO_Polynomial_getDerivativesAtX);
-	praat_addAction1 (classPolynomial, 1, U"Get one real root...", U"Get derivatives at X...", 1, DO_Polynomial_getOneRealRoot);
-	praat_addAction1 (classPolynomial, 0, U"To Spectrum...", U"Analyse", 0, DO_Polynomial_to_Spectrum);
-	praat_addAction1 (classPolynomial, 0, U"To Roots", nullptr, 0, DO_Polynomial_to_Roots);
-	praat_addAction1 (classPolynomial, 0, U"To Polynomial (derivative)", nullptr, 0, DO_Polynomial_getDerivative);
-	praat_addAction1 (classPolynomial, 0, U"To Polynomial (primitive)...", nullptr, 0, DO_Polynomial_getPrimitive);
-	praat_addAction1 (classPolynomial, 0, U"Scale x...", nullptr, 0, DO_Polynomial_scaleX);
-	praat_addAction1 (classPolynomial, 2, U"Multiply", nullptr, 0, DO_Polynomials_multiply);
-	praat_addAction1 (classPolynomial, 2, U"Divide...", nullptr, 0, DO_Polynomials_divide);
-
-	praat_addAction1 (classRoots, 1, U"Roots help", nullptr, 0, DO_Roots_help);
-	praat_addAction1 (classRoots, 1, U"Draw...", nullptr, 0, DO_Roots_draw);
+	praat_addAction1 (classPolynomial, 1, U"Get value (complex)...", U"Get value...", 1, INFO_Polynomial_evaluate_z);
+	praat_addAction1 (classPolynomial, 1, U"Get derivatives at X...", U"Get value (complex)...", 1, INFO_Polynomial_getDerivativesAtX);
+	praat_addAction1 (classPolynomial, 1, U"Get one real root...", U"Get derivatives at X...", 1, REAL_Polynomial_getOneRealRoot);
+	praat_addAction1 (classPolynomial, 0, U"To Spectrum...", U"Analyse", 0, NEW_Polynomial_to_Spectrum);
+	praat_addAction1 (classPolynomial, 0, U"To Roots", nullptr, 0, NEW_Polynomial_to_Roots);
+	praat_addAction1 (classPolynomial, 0, U"To Polynomial (derivative)", nullptr, 0, NEW_Polynomial_getDerivative);
+	praat_addAction1 (classPolynomial, 0, U"To Polynomial (primitive)...", nullptr, 0, NEW_Polynomial_getPrimitive);
+	praat_addAction1 (classPolynomial, 0, U"Scale x...", nullptr, 0, NEW_Polynomial_scaleX);
+	praat_addAction1 (classPolynomial, 2, U"Multiply", nullptr, 0, NEW_Polynomials_multiply);
+	praat_addAction1 (classPolynomial, 2, U"Divide...", nullptr, 0, NEWMANY_Polynomials_divide);
+
+	praat_addAction1 (classRoots, 1, U"Roots help", nullptr, 0, HELP_Roots_help);
+	praat_addAction1 (classRoots, 1, U"Draw...", nullptr, 0, GRAPHICS_Roots_draw);
 	praat_addAction1 (classRoots, 1, QUERY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classRoots, 1, U"Get number of roots", nullptr, 1, DO_Roots_getNumberOfRoots);
+	praat_addAction1 (classRoots, 1, U"Get number of roots", nullptr, 1, INTEGER_Roots_getNumberOfRoots);
 	praat_addAction1 (classRoots, 1, U"-- roots --", nullptr, 1, 0);
-	praat_addAction1 (classRoots, 1, U"Get root...", nullptr, 1, DO_Roots_getRoot);
-	praat_addAction1 (classRoots, 1, U"Get real part of root...", nullptr, 1, DO_Roots_getRealPartOfRoot);
-	praat_addAction1 (classRoots, 1, U"Get imaginary part of root...", nullptr, 1, DO_Roots_getImaginaryPartOfRoot);
+	praat_addAction1 (classRoots, 1, U"Get root...", nullptr, 1, COMPLEX_Roots_getRoot);
+	praat_addAction1 (classRoots, 1, U"Get real part of root...", nullptr, 1, REAL_Roots_getRealPartOfRoot);
+	praat_addAction1 (classRoots, 1, U"Get imaginary part of root...", nullptr, 1, REAL_Roots_getImaginaryPartOfRoot);
 	praat_addAction1 (classRoots, 1, MODIFY_BUTTON, nullptr, 0, 0);
-	praat_addAction1 (classRoots, 1, U"Set root...", nullptr, 1, DO_Roots_setRoot);
+	praat_addAction1 (classRoots, 1, U"Set root...", nullptr, 1, MODIFY_Roots_setRoot);
 	praat_addAction1 (classRoots, 0, U"Analyse", nullptr, 0, 0);
-	praat_addAction1 (classRoots, 0, U"To Spectrum...", nullptr, 0, DO_Roots_to_Spectrum);
+	praat_addAction1 (classRoots, 0, U"To Spectrum...", nullptr, 0, NEW_Roots_to_Spectrum);
 
-	praat_addAction2 (classRoots, 1, classPolynomial, 1, U"Polish roots", nullptr, 0, DO_Roots_and_Polynomial_polish);
+	praat_addAction2 (classRoots, 1, classPolynomial, 1, U"Polish roots", nullptr, 0, MODIFY_Roots_and_Polynomial_polish);
 
-	praat_addAction1 (classSound, 0, U"To TextGrid (silences)...", U"To IntervalTier", 1, DO_Sound_to_TextGrid_detectSilences);
-    praat_addAction1 (classSound, 0, U"Play one channel...", U"Play", praat_HIDDEN, DO_Sound_playOneChannel);
-    praat_addAction1 (classSound, 0, U"Play as frequency shifted...", U"Play", praat_HIDDEN, DO_Sound_playAsFrequencyShifted);
-	praat_addAction1 (classSound, 0, U"Draw where...", U"Draw...", 1, DO_Sound_drawWhere);
+	praat_addAction1 (classSound, 0, U"To TextGrid (silences)...", U"To IntervalTier", 1, NEW_Sound_to_TextGrid_detectSilences);
+    praat_addAction1 (classSound, 0, U"Play one channel...", U"Play", praat_HIDDEN, PLAY_Sound_playOneChannel);
+    praat_addAction1 (classSound, 0, U"Play as frequency shifted...", U"Play", praat_HIDDEN, PLAY_Sound_playAsFrequencyShifted);
+	praat_addAction1 (classSound, 0, U"Draw where...", U"Draw...", 1, GRAPHICS_Sound_drawWhere);
 	//	praat_addAction1 (classSound, 0, U"Paint where...", U"Draw where...", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_paintWhere);
-	praat_addAction1 (classSound, 0, U"Paint where...", U"Draw where...", 1, DO_Sound_paintWhere);
+	praat_addAction1 (classSound, 0, U"Paint where...", U"Draw where...", 1, GRAPHICS_Sound_paintWhere);
 	//	praat_addAction1 (classSound, 2, U"Paint enclosed...", U"Paint where...", praat_DEPTH_1 | praat_HIDDEN, DO_Sounds_paintEnclosed);
-	praat_addAction1 (classSound, 2, U"Paint enclosed...", U"Paint where...", 1, DO_Sounds_paintEnclosed);
-
-	praat_addAction1 (classSound, 0, U"To Pitch (shs)...", U"To Pitch (cc)...", 1, DO_Sound_to_Pitch_shs);
-	praat_addAction1 (classSound, 0, U"Fade in...", U"Multiply by window...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_fadeIn);
-	praat_addAction1 (classSound, 0, U"Fade out...", U"Fade in...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_fadeOut);
-	praat_addAction1 (classSound, 0, U"To Pitch (SPINET)...", U"To Pitch (cc)...", 1, DO_Sound_to_Pitch_SPINET);
-
-	praat_addAction1 (classSound, 0, U"To FormantFilter...", U"To Cochleagram (edb)...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_FormantFilter);
-	praat_addAction1 (classSound, 0, U"To Spectrogram (pitch-dependent)...", U"To Cochleagram (edb)...", 1, DO_Sound_to_Spectrogram_pitchDependent);
-
-	praat_addAction1 (classSound, 0, U"To BarkFilter...", U"To FormantFilter...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_BarkFilter); // deprecated 2014
-	praat_addAction1 (classSound, 0, U"To BarkSpectrogram...", U"To FormantFilter...", praat_DEPTH_1, DO_Sound_to_BarkSpectrogram);
-
-	praat_addAction1 (classSound, 0, U"To MelFilter...", U"To BarkFilter...", praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_MelFilter); // deprecated 2014
-	praat_addAction1 (classSound, 0, U"To MelSpectrogram...", U"To BarkSpectrogram...", praat_DEPTH_1, DO_Sound_to_MelSpectrogram);
-	praat_addAction1 (classSound, 0, U"To ComplexSpectrogram...", U"To MelSpectrogram...", praat_DEPTH_1 + praat_HIDDEN, DO_Sound_to_ComplexSpectrogram);
-
-	praat_addAction1 (classSound, 0, U"To Polygon...", U"Down to Matrix", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_to_Polygon);
-    praat_addAction1 (classSound, 2, U"To Polygon (enclosed)...", U"Cross-correlate...", praat_DEPTH_1 | praat_HIDDEN, DO_Sounds_to_Polygon_enclosed);
-    praat_addAction1 (classSound, 2, U"To DTW...", U"Cross-correlate...", praat_DEPTH_1, DO_Sounds_to_DTW);
-
-	praat_addAction1 (classSound, 1, U"Filter (gammatone)...", U"Filter (de-emphasis)...", 1, DO_Sound_filterByGammaToneFilter4);
-	praat_addAction1 (classSound, 0, U"Remove noise...", U"Filter (formula)...", 1, DO_Sound_removeNoise);
-
-	praat_addAction1 (classSound, 0, U"Change gender...", U"Deepen band modulation...", 1, DO_Sound_changeGender);
-
-	praat_addAction1 (classSound, 0, U"Change speaker...", U"Deepen band modulation...", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_changeSpeaker);
-	praat_addAction1 (classSound, 0, U"Copy channel ranges...", U"Extract all channels", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_copyChannelRanges);
-	praat_addAction1 (classSound, 0, U"Trim silences...", U"Resample...", praat_DEPTH_1 | praat_HIDDEN, DO_Sound_trimSilences);
-	praat_addAction1 (classSound, 0, U"To KlattGrid (simple)...", U"To Manipulation...", 1, DO_Sound_to_KlattGrid_simple);
-	praat_addAction2 (classSound, 1, classPitch, 1, U"To FormantFilter...", nullptr, praat_HIDDEN, DO_Sound_and_Pitch_to_FormantFilter);
-	praat_addAction2 (classSound, 1, classPitch, 1, U"To Spectrogram (pitch-dependent)...", nullptr, 0, DO_Sound_and_Pitch_to_Spectrogram);
-
-	praat_addAction2 (classSound, 1, classPitch, 1, U"Change gender...", nullptr, 0, DO_Sound_and_Pitch_changeGender);
-	praat_addAction2 (classSound, 1, classPitch, 1, U"Change speaker...", nullptr, praat_HIDDEN, DO_Sound_and_Pitch_changeSpeaker);
-	praat_addAction2 (classSound, 1, classIntervalTier, 1, U"Cut parts matching label...", nullptr, 0, DO_Sound_and_IntervalTier_cutPartsMatchingLabel);
-	praat_addAction1 (classSpectrogram, 2, U"To DTW...", U"To Spectrum (slice)...", 1, DO_Spectrograms_to_DTW);
-	praat_addAction1 (classSpectrum, 0, U"Draw phases...", U"Draw (log freq)...", praat_DEPTH_1 | praat_HIDDEN, DO_Spectrum_drawPhases);
-	praat_addAction1 (classSpectrum, 0, U"Set real value in bin...", U"Formula...", praat_HIDDEN | praat_DEPTH_1, DO_Spectrum_setRealValueInBin);
-	praat_addAction1 (classSpectrum, 0, U"Set imaginary value in bin...", U"Formula...", praat_HIDDEN | praat_DEPTH_1, DO_Spectrum_setImaginaryValueInBin);
-	praat_addAction1 (classSpectrum, 0, U"Conjugate", U"Formula...", praat_HIDDEN | praat_DEPTH_1, DO_Spectrum_conjugate);
-	praat_addAction1 (classSpectrum, 2, U"Multiply", U"To Sound (fft)", praat_HIDDEN, DO_Spectra_multiply);
-	praat_addAction1 (classSpectrum, 0, U"To Matrix (unwrap)", U"To Matrix", praat_HIDDEN, DO_Spectrum_unwrap);
-	praat_addAction1 (classSpectrum, 0, U"Shift frequencies...", U"To Matrix", praat_HIDDEN, DO_Spectrum_shiftFrequencies);
-	praat_addAction1 (classSpectrum, 0, U"Compress frequency domain...", U"Shift frequencies...", praat_HIDDEN, DO_Spectrum_compressFrequencyDomain);
-	praat_addAction1 (classSpectrum, 0, U"Resample...", U"Compress frequency domain...", praat_HIDDEN, DO_Spectrum_resample);
-	praat_addAction1 (classSpectrum, 0, U"To Cepstrum", U"To Spectrogram", 1, DO_Spectrum_to_Cepstrum);
-	praat_addAction1 (classSpectrum, 0, U"To PowerCepstrum", U"To Cepstrum", 1, DO_Spectrum_to_PowerCepstrum);
-
-	praat_addAction1 (classSpeechSynthesizer, 0, U"SpeechSynthesizer help", nullptr, 0, DO_SpeechSynthesizer_help);
-	praat_addAction1 (classSpeechSynthesizer, 0, U"Play text...", nullptr, 0, DO_SpeechSynthesizer_playText);
-	praat_addAction1 (classSpeechSynthesizer, 0, U"To Sound...", nullptr, 0, DO_SpeechSynthesizer_to_Sound);
+	praat_addAction1 (classSound, 2, U"Paint enclosed...", U"Paint where...", 1, GRAPHICS_Sounds_paintEnclosed);
+
+	praat_addAction1 (classSound, 0, U"To Pitch (shs)...", U"To Pitch (cc)...", 1, NEW_Sound_to_Pitch_shs);
+	praat_addAction1 (classSound, 0, U"Fade in...", U"Multiply by window...", praat_HIDDEN + praat_DEPTH_1, MODIFY_Sound_fadeIn);
+	praat_addAction1 (classSound, 0, U"Fade out...", U"Fade in...", praat_HIDDEN + praat_DEPTH_1, MODIFY_Sound_fadeOut);
+	praat_addAction1 (classSound, 0, U"To Pitch (SPINET)...", U"To Pitch (cc)...", 1, NEW_Sound_to_Pitch_SPINET);
+
+	praat_addAction1 (classSound, 0, U"To FormantFilter...", U"To Cochleagram (edb)...", praat_DEPRECATED_2014 | praat_DEPTH_1, NEW_Sound_to_FormantFilter);
+	praat_addAction1 (classSound, 0, U"To Spectrogram (pitch-dependent)...", U"To Cochleagram (edb)...", 1, NEW_Sound_to_Spectrogram_pitchDependent);
+
+	praat_addAction1 (classSound, 0, U"To BarkFilter...", U"To FormantFilter...", praat_DEPRECATED_2014 | praat_DEPTH_1, NEW_Sound_to_BarkFilter);
+	praat_addAction1 (classSound, 0, U"To BarkSpectrogram...", U"To FormantFilter...", praat_DEPTH_1, NEW_Sound_to_BarkSpectrogram);
+
+	praat_addAction1 (classSound, 0, U"To MelFilter...", U"To BarkFilter...", praat_DEPRECATED_2014 | praat_DEPTH_1, NEW_Sound_to_MelFilter);
+	praat_addAction1 (classSound, 0, U"To MelSpectrogram...", U"To BarkSpectrogram...", praat_DEPTH_1, NEW_Sound_to_MelSpectrogram);
+	praat_addAction1 (classSound, 0, U"To ComplexSpectrogram...", U"To MelSpectrogram...", praat_DEPTH_1 + praat_HIDDEN, NEW_Sound_to_ComplexSpectrogram);
+
+	praat_addAction1 (classSound, 0, U"To Polygon...", U"Down to Matrix", praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_to_Polygon);
+    praat_addAction1 (classSound, 2, U"To Polygon (enclosed)...", U"Cross-correlate...", praat_DEPTH_1 | praat_HIDDEN, NEW1_Sounds_to_Polygon_enclosed);
+    praat_addAction1 (classSound, 2, U"To DTW...", U"Cross-correlate...", praat_DEPTH_1, NEW1_Sounds_to_DTW);
+
+	praat_addAction1 (classSound, 1, U"Filter (gammatone)...", U"Filter (de-emphasis)...", 1, NEW_Sound_filterByGammaToneFilter4);
+	praat_addAction1 (classSound, 0, U"Remove noise...", U"Filter (formula)...", 1, NEW_Sound_removeNoise);
+
+	praat_addAction1 (classSound, 0, U"Change gender...", U"Deepen band modulation...", 1, NEW_Sound_changeGender);
+
+	praat_addAction1 (classSound, 0, U"Change speaker...", U"Deepen band modulation...", praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_changeSpeaker);
+	praat_addAction1 (classSound, 0, U"Copy channel ranges...", U"Extract all channels", praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_copyChannelRanges);
+	praat_addAction1 (classSound, 0, U"Trim silences...", U"Resample...", praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_trimSilences);
+	praat_addAction1 (classSound, 0, U"To KlattGrid (simple)...", U"To Manipulation...", 1, NEW_Sound_to_KlattGrid_simple);
+	praat_addAction2 (classSound, 1, classPitch, 1, U"To FormantFilter...", nullptr, praat_DEPRECATED_2014, NEW1_Sound_and_Pitch_to_FormantFilter);
+	praat_addAction2 (classSound, 1, classPitch, 1, U"To Spectrogram (pitch-dependent)...", nullptr, 0,NEW1_Sound_and_Pitch_to_Spectrogram);
+
+	praat_addAction2 (classSound, 1, classPitch, 1, U"Change gender...", nullptr, 0, NEW1_Sound_and_Pitch_changeGender);
+	praat_addAction2 (classSound, 1, classPitch, 1, U"Change speaker...", nullptr, praat_HIDDEN, NEW1_Sound_and_Pitch_changeSpeaker);
+	praat_addAction2 (classSound, 1, classIntervalTier, 1, U"Cut parts matching label...", nullptr, 0, NEW1_Sound_and_IntervalTier_cutPartsMatchingLabel);
+	praat_addAction1 (classSpectrogram, 2, U"To DTW...", U"To Spectrum (slice)...", 1, NEW1_Spectrograms_to_DTW);
+	praat_addAction1 (classSpectrum, 0, U"Draw phases...", U"Draw (log freq)...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Spectrum_drawPhases);
+	praat_addAction1 (classSpectrum, 0, U"Set real value in bin...", U"Formula...", praat_HIDDEN | praat_DEPTH_1, MODIFY_Spectrum_setRealValueInBin);
+	praat_addAction1 (classSpectrum, 0, U"Set imaginary value in bin...", U"Formula...", praat_HIDDEN | praat_DEPTH_1, MODIFY_Spectrum_setImaginaryValueInBin);
+	praat_addAction1 (classSpectrum, 0, U"Conjugate", U"Formula...", praat_HIDDEN | praat_DEPTH_1, MODIFY_Spectrum_conjugate);
+	praat_addAction1 (classSpectrum, 2, U"Multiply", U"To Sound (fft)", praat_HIDDEN, NEW_Spectra_multiply);
+	praat_addAction1 (classSpectrum, 0, U"To Matrix (unwrap)", U"To Matrix", praat_HIDDEN, NEW_Spectrum_unwrap);
+	praat_addAction1 (classSpectrum, 0, U"Shift frequencies...", U"To Matrix", praat_HIDDEN, NEW_Spectrum_shiftFrequencies);
+	praat_addAction1 (classSpectrum, 0, U"Compress frequency domain...", U"Shift frequencies...", praat_HIDDEN, NEW_Spectrum_compressFrequencyDomain);
+	praat_addAction1 (classSpectrum, 0, U"Resample...", U"Compress frequency domain...", praat_HIDDEN, NEW_Spectrum_resample);
+	praat_addAction1 (classSpectrum, 0, U"To Cepstrum", U"To Spectrogram", 1, NEW_Spectrum_to_Cepstrum);
+	praat_addAction1 (classSpectrum, 0, U"To PowerCepstrum", U"To Cepstrum", 1, NEW_Spectrum_to_PowerCepstrum);
+
+	praat_addAction1 (classSpeechSynthesizer, 0, U"SpeechSynthesizer help", nullptr, 0, HELP_SpeechSynthesizer_help);
+	praat_addAction1 (classSpeechSynthesizer, 0, U"Play text...", nullptr, 0, PLAY_SpeechSynthesizer_playText);
+	praat_addAction1 (classSpeechSynthesizer, 0, U"To Sound...", nullptr, 0, NEWMANY_SpeechSynthesizer_to_Sound);
 	praat_addAction1 (classSpeechSynthesizer, 0, QUERY_BUTTON, nullptr, 0, 0);
-		praat_addAction1 (classSpeechSynthesizer, 1, U"Get voice name", nullptr, 1, DO_SpeechSynthesizer_getVoiceName);
-		praat_addAction1 (classSpeechSynthesizer, 1, U"Get voice variant", nullptr, 1, DO_SpeechSynthesizer_getVoiceVariant);
+		praat_addAction1 (classSpeechSynthesizer, 1, U"Get voice name", nullptr, 1, INFO_SpeechSynthesizer_getVoiceName);
+		praat_addAction1 (classSpeechSynthesizer, 1, U"Get voice variant", nullptr, 1, INFO_SpeechSynthesizer_getVoiceVariant);
 	praat_addAction1 (classSpeechSynthesizer, 0, MODIFY_BUTTON, nullptr, 0, 0);
-		praat_addAction1 (classSpeechSynthesizer, 0, U"Set text input settings...", nullptr, 1, DO_SpeechSynthesizer_setTextInputSettings);
-		praat_addAction1 (classSpeechSynthesizer, 0, U"Set speech output settings...", nullptr, 1, DO_SpeechSynthesizer_setSpeechOutputSettings);
-	praat_addAction2 (classSpeechSynthesizer, 1, classTextGrid, 1, U"To Sound...", nullptr, 0, DO_SpeechSynthesizer_and_TextGrid_to_Sound);
+		praat_addAction1 (classSpeechSynthesizer, 0, U"Set text input settings...", nullptr, 1, MODIFY_SpeechSynthesizer_setTextInputSettings);
+		praat_addAction1 (classSpeechSynthesizer, 0, U"Set speech output settings...", nullptr, 1, MODIFY_SpeechSynthesizer_setSpeechOutputSettings);
+	praat_addAction2 (classSpeechSynthesizer, 1, classTextGrid, 1, U"To Sound...", nullptr, 0, NEW1_SpeechSynthesizer_and_TextGrid_to_Sound);
 
-	praat_addAction3 (classSpeechSynthesizer, 1, classSound, 1, classTextGrid, 1, U"To TextGrid (align)...", nullptr, 0, DO_SpeechSynthesizer_and_Sound_and_TextGrid_align);
-    praat_addAction3 (classSpeechSynthesizer, 1, classSound, 1, classTextGrid, 1, U"To TextGrid (align,trim)...", nullptr, 0, DO_SpeechSynthesizer_and_Sound_and_TextGrid_align2);
+	praat_addAction3 (classSpeechSynthesizer, 1, classSound, 1, classTextGrid, 1, U"To TextGrid (align)...", nullptr, 0, NEW1_SpeechSynthesizer_and_Sound_and_TextGrid_align);
+    praat_addAction3 (classSpeechSynthesizer, 1, classSound, 1, classTextGrid, 1, U"To TextGrid (align,trim)...", nullptr, 0, NEW1_SpeechSynthesizer_and_Sound_and_TextGrid_align2);
 
-	praat_addAction1 (classSSCP, 0, U"SSCP help", nullptr, 0, DO_SSCP_help);
+	praat_addAction1 (classSSCP, 0, U"SSCP help", nullptr, 0, HELP_SSCP_help);
 	praat_TableOfReal_init2 (classSSCP);
 	praat_removeAction (classSSCP, nullptr, nullptr, U"Append");
-	praat_addAction1 (classSSCP, 0, U"Draw sigma ellipse...", DRAW_BUTTON, 1, DO_SSCP_drawSigmaEllipse);
-	praat_addAction1 (classSSCP, 0, U"Draw confidence ellipse...", DRAW_BUTTON, 1, DO_SSCP_drawConfidenceEllipse);
+	praat_addAction1 (classSSCP, 0, U"Draw sigma ellipse...", DRAW_BUTTON, 1, GRAPHICS_SSCP_drawSigmaEllipse);
+	praat_addAction1 (classSSCP, 0, U"Draw confidence ellipse...", DRAW_BUTTON, 1, GRAPHICS_SSCP_drawConfidenceEllipse);
 	praat_SSCP_query_init (classSSCP);
-	praat_addAction1 (classSSCP, 1, U"Get diagonality (bartlett)...", U"Get ln(determinant)", 1, DO_SSCP_testDiagonality_bartlett);
-	praat_addAction1 (classSSCP, 1, U"Get total variance", U"Get diagonality (bartlett)...", 1, DO_SSCP_getTotalVariance);
-	praat_addAction1 (classSSCP, 1, U"Get sigma ellipse area...", U"Get total variance", 1, DO_SSCP_getConcentrationEllipseArea);
-	praat_addAction1 (classSSCP, 1, U"Get confidence ellipse area...", U"Get sigma ellipse area...", 1, DO_SSCP_getConfidenceEllipseArea);
-	praat_addAction1 (classSSCP, 1, U"Get fraction variation...", U"Get confidence ellipse area...", 1, DO_SSCP_getFractionVariation);
+	praat_addAction1 (classSSCP, 1, U"Get diagonality (bartlett)...", U"Get ln(determinant)", 1, REAL_SSCP_testDiagonality_bartlett);
+	praat_addAction1 (classSSCP, 1, U"Get total variance", U"Get diagonality (bartlett)...", 1, REAL_SSCP_getTotalVariance);
+	praat_addAction1 (classSSCP, 1, U"Get sigma ellipse area...", U"Get total variance", 1, REAL_SSCP_getConcentrationEllipseArea);
+	praat_addAction1 (classSSCP, 1, U"Get confidence ellipse area...", U"Get sigma ellipse area...", 1, REAL_SSCP_getConfidenceEllipseArea);
+	praat_addAction1 (classSSCP, 1, U"Get fraction variation...", U"Get confidence ellipse area...", 1, REAL_SSCP_getFractionVariation);
 	praat_SSCP_extract_init (classSSCP);
-	praat_addAction1 (classSSCP, 0, U"To PCA", nullptr, 0, DO_SSCP_to_PCA);
-	praat_addAction1 (classSSCP, 0, U"To Correlation", nullptr, 0, DO_SSCP_to_Correlation);
-	praat_addAction1 (classSSCP, 0, U"To Covariance...", nullptr, 0, DO_SSCP_to_Covariance);
-
-	praat_addAction1 (classStrings, 0, U"To Categories", nullptr, 0, DO_Strings_to_Categories);
-	praat_addAction1 (classStrings, 0, U"Append", nullptr, 0, DO_Strings_append);
-	praat_addAction1 (classStrings, 0, U"Change...", U"Replace all...", praat_HIDDEN, DO_Strings_change);
-	praat_addAction1 (classStrings, 0, U"Extract part...", U"Replace all...", 0, DO_Strings_extractPart);
-	praat_addAction1 (classStrings, 0, U"To Permutation...", U"To Distributions", 0, DO_Strings_to_Permutation);
-	praat_addAction1 (classStrings, 2, U"To EditDistanceTable", U"To Distributions", 0, DO_Strings_to_EditDistanceTable);
-
-	praat_addAction1 (classSVD, 0, U"To TableOfReal...", nullptr, 0, DO_SVD_to_TableOfReal);
-	praat_addAction1 (classSVD, 0, U"Extract left singular vectors", nullptr, 0, DO_SVD_extractLeftSingularVectors);
-	praat_addAction1 (classSVD, 0, U"Extract right singular vectors", nullptr, 0, DO_SVD_extractRightSingularVectors);
-	praat_addAction1 (classSVD, 0, U"Extract singular values", nullptr, 0, DO_SVD_extractSingularValues);
-		praat_addAction1 (classTable, 0, U"Draw ellipses...", U"Draw ellipse (standard deviation)...", praat_DEPTH_1, DO_Table_drawEllipses);
-		praat_addAction1 (classTable, 0, U"Box plots...", U"Draw ellipses...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_boxPlots);
-		praat_addAction1 (classTable, 0, U"Normal probability plot...", U"Box plots...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_normalProbabilityPlot);
-		praat_addAction1 (classTable, 0, U"Quantile-quantile plot...", U"Normal probability plot...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_quantileQuantilePlot);
-		praat_addAction1 (classTable, 0, U"Quantile-quantile plot (between levels)...", U"Quantile-quantile plot...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_quantileQuantilePlot_betweenLevels);
-		praat_addAction1 (classTable, 0, U"Lag plot...", U"Quantile-quantile plot (between levels)...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_lagPlot);
-		praat_addAction1 (classTable, 0, U"Horizontal error bars plot...", U"Scatter plot (mark)...", praat_DEPTH_1, DO_Table_horizontalErrorBarsPlot);
-		praat_addAction1 (classTable, 0, U"Vertical error bars plot...", U"Scatter plot (mark)...", praat_DEPTH_1, DO_Table_verticalErrorBarsPlot);
-		praat_addAction1 (classTable, 0, U"Distribution plot...", U"Quantile-quantile plot...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_distributionPlot);
+	praat_addAction1 (classSSCP, 0, U"To PCA", nullptr, 0, NEW_SSCP_to_PCA);
+	praat_addAction1 (classSSCP, 0, U"To Correlation", nullptr, 0, NEW_SSCP_to_Correlation);
+	praat_addAction1 (classSSCP, 0, U"To Covariance...", nullptr, 0, NEW_SSCP_to_Covariance);
+
+	praat_addAction1 (classStrings, 0, U"To Categories", nullptr, 0, NEW_Strings_to_Categories);
+	praat_addAction1 (classStrings, 0, U"Append", nullptr, 0, NEW1_Strings_append);
+	praat_addAction1 (classStrings, 0, U"Change...", U"Replace all...", praat_HIDDEN, NEW_Strings_change);
+	praat_addAction1 (classStrings, 0, U"Extract part...", U"Replace all...", 0, NEW_Strings_extractPart);
+	praat_addAction1 (classStrings, 0, U"To Permutation...", U"To Distributions", 0, NEW_Strings_to_Permutation);
+	praat_addAction1 (classStrings, 2, U"To EditDistanceTable", U"To Distributions", 0, NEW_Strings_to_EditDistanceTable);
+
+	praat_addAction1 (classSVD, 0, U"To TableOfReal...", nullptr, 0, NEW_SVD_to_TableOfReal);
+	praat_addAction1 (classSVD, 0, U"Extract left singular vectors", nullptr, 0, NEW_SVD_extractLeftSingularVectors);
+	praat_addAction1 (classSVD, 0, U"Extract right singular vectors", nullptr, 0, NEW_SVD_extractRightSingularVectors);
+	praat_addAction1 (classSVD, 0, U"Extract singular values", nullptr, 0, NEW_SVD_extractSingularValues);
+		praat_addAction1 (classTable, 0, U"Draw ellipses...", U"Draw ellipse (standard deviation)...", praat_DEPTH_1, GRAPHICS_Table_drawEllipses);
+		praat_addAction1 (classTable, 0, U"Box plots...", U"Draw ellipses...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Table_boxPlots);
+		praat_addAction1 (classTable, 0, U"Normal probability plot...", U"Box plots...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Table_normalProbabilityPlot);
+		praat_addAction1 (classTable, 0, U"Quantile-quantile plot...", U"Normal probability plot...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Table_quantileQuantilePlot);
+		praat_addAction1 (classTable, 0, U"Quantile-quantile plot (between levels)...", U"Quantile-quantile plot...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Table_quantileQuantilePlot_betweenLevels);
+		praat_addAction1 (classTable, 0, U"Lag plot...", U"Quantile-quantile plot (between levels)...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Table_lagPlot);
+		praat_addAction1 (classTable, 0, U"Horizontal error bars plot...", U"Scatter plot (mark)...", praat_DEPTH_1, GRAPHICS_Table_horizontalErrorBarsPlot);
+		praat_addAction1 (classTable, 0, U"Vertical error bars plot...", U"Scatter plot (mark)...", praat_DEPTH_1, GRAPHICS_Table_verticalErrorBarsPlot);
+		praat_addAction1 (classTable, 0, U"Distribution plot...", U"Quantile-quantile plot...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_Table_distributionPlot);
 		praat_addAction1 (classTable, 1, U"Draw where",  U"Lag plot...", 1 , 0);
-			praat_addAction1 (classTable, 0, U"Scatter plot where...", U"Draw where", 2, DO_Table_scatterPlotWhere);
-			praat_addAction1 (classTable, 0, U"Scatter plot where (mark)...", U"Scatter plot where...", 2, DO_Table_scatterPlotMarkWhere);
-			praat_addAction1 (classTable, 0, U"Horizontal error bars plot where...", U"Scatter plot where (mark)...", praat_DEPTH_2, DO_Table_horizontalErrorBarsPlotWhere);
-			praat_addAction1 (classTable, 0, U"Vertical error bars plot where...", U"Scatter plot where (mark)...", praat_DEPTH_2, DO_Table_verticalErrorBarsPlotWhere);
+			praat_addAction1 (classTable, 0, U"Scatter plot where...", U"Draw where", 2, GRAPHICS_Table_scatterPlotWhere);
+			praat_addAction1 (classTable, 0, U"Scatter plot where (mark)...", U"Scatter plot where...", 2, GRAPHICS_Table_scatterPlotMarkWhere);
+			praat_addAction1 (classTable, 0, U"Horizontal error bars plot where...", U"Scatter plot where (mark)...", praat_DEPTH_2, GRAPHICS_Table_horizontalErrorBarsPlotWhere);
+			praat_addAction1 (classTable, 0, U"Vertical error bars plot where...", U"Scatter plot where (mark)...", praat_DEPTH_2, GRAPHICS_Table_verticalErrorBarsPlotWhere);
 			
-			praat_addAction1 (classTable, 0, U"Distribution plot where...", U"Scatter plot where (mark)...", 2, DO_Table_distributionPlotWhere);
-			praat_addAction1 (classTable, 0, U"Draw ellipse where (standard deviation)...", U"Distribution plot where...", 2, DO_Table_drawEllipseWhere);
-			praat_addAction1 (classTable, 0, U"Box plots where...", U"Draw ellipse where (standard deviation)...", 2, DO_Table_boxPlotsWhere);
-			praat_addAction1 (classTable, 0, U"Normal probability plot where...", U"Box plots where...", 2, DO_Table_normalProbabilityPlotWhere);
-			praat_addAction1 (classTable, 0, U"Bar plot where...", U"Normal probability plot where...", 2, DO_Table_barPlotWhere);
-			praat_addAction1 (classTable, 0, U"Line graph where...", U"Bar plot where...", 2, DO_Table_LineGraphWhere);
-			praat_addAction1 (classTable, 0, U"Lag plot where...", U"Line graph where...", 2, DO_Table_lagPlotWhere);
-			praat_addAction1 (classTable, 0, U"Draw ellipses where...", U"Lag plot where...", 2, DO_Table_drawEllipsesWhere);
-
-	praat_addAction1 (classTable, 1, U"Get number of rows where...", U"Get number of rows", praat_DEPTH_1 | praat_HIDDEN,	DO_Table_getNumberOfRowsWhere);
-	praat_addAction1 (classTable, 1, U"Report one-way anova...", U"Report group difference (Wilcoxon rank sum)...", praat_DEPTH_1 | praat_HIDDEN,	DO_Table_reportOneWayAnova);
-	praat_addAction1 (classTable, 1, U"Report one-way Kruskal-Wallis...", U"Report one-way anova...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_reportOneWayKruskalWallis);
-	praat_addAction1 (classTable, 1, U"Report two-way anova...", U"Report one-way Kruskal-Wallis...", praat_DEPTH_1 | praat_HIDDEN, DO_Table_reportTwoWayAnova);
-	praat_addAction1 (classTable, 0, U"Extract rows where...", U"Extract rows where column (text)...", praat_DEPTH_1, DO_Table_extractRowsWhere);
-	praat_addAction1 (classTable, 0, U"Extract rows where (mahalanobis)...", U"Extract rows where...", praat_DEPTH_1| praat_HIDDEN, DO_Table_extractRowsMahalanobisWhere);
+			praat_addAction1 (classTable, 0, U"Distribution plot where...", U"Scatter plot where (mark)...", 2, GRAPHICS_Table_distributionPlotWhere);
+			praat_addAction1 (classTable, 0, U"Draw ellipse where (standard deviation)...", U"Distribution plot where...", 2, GRAPHICS_Table_drawEllipseWhere);
+			praat_addAction1 (classTable, 0, U"Box plots where...", U"Draw ellipse where (standard deviation)...", 2, GRAPHICS_Table_boxPlotsWhere);
+			praat_addAction1 (classTable, 0, U"Normal probability plot where...", U"Box plots where...", 2, GRAPHICS_Table_normalProbabilityPlotWhere);
+			praat_addAction1 (classTable, 0, U"Bar plot where...", U"Normal probability plot where...", 2, GRAPHICS_Table_barPlotWhere);
+			praat_addAction1 (classTable, 0, U"Line graph where...", U"Bar plot where...", 2, GRAPHICS_Table_LineGraphWhere);
+			praat_addAction1 (classTable, 0, U"Lag plot where...", U"Line graph where...", 2, GRAPHICS_Table_lagPlotWhere);
+			praat_addAction1 (classTable, 0, U"Draw ellipses where...", U"Lag plot where...", 2, GRAPHICS_Table_drawEllipsesWhere);
+
+	praat_addAction1 (classTable, 1, U"Get number of rows where...", U"Get number of rows", praat_DEPTH_1 | praat_HIDDEN,	INTEGER_Table_getNumberOfRowsWhere);
+	praat_addAction1 (classTable, 1, U"Report one-way anova...", U"Report group difference (Wilcoxon rank sum)...", praat_DEPTH_1 | praat_HIDDEN,	INFO_Table_reportOneWayAnova);
+	praat_addAction1 (classTable, 1, U"Report one-way Kruskal-Wallis...", U"Report one-way anova...", praat_DEPTH_1 | praat_HIDDEN, INFO_Table_reportOneWayKruskalWallis);
+	praat_addAction1 (classTable, 1, U"Report two-way anova...", U"Report one-way Kruskal-Wallis...", praat_DEPTH_1 | praat_HIDDEN, INFO_Table_reportTwoWayAnova);
+	praat_addAction1 (classTable, 0, U"Extract rows where...", U"Extract rows where column (text)...", praat_DEPTH_1, NEW_Table_extractRowsWhere);
+	praat_addAction1 (classTable, 0, U"Extract rows where (mahalanobis)...", U"Extract rows where...", praat_DEPTH_1| praat_HIDDEN, NEW_Table_extractRowsMahalanobisWhere);
 	praat_addAction1 (classTable, 0, U"-- Extract columns ----", U"Extract rows where (mahalanobis)...", praat_DEPTH_1| praat_HIDDEN, 0);
-	praat_addAction1 (classTable, 0, U"Extract column ranges...", U"-- Extract columns ----", praat_DEPTH_1| praat_HIDDEN, DO_Table_extractColumnRanges);
+	praat_addAction1 (classTable, 0, U"Extract column ranges...", U"-- Extract columns ----", praat_DEPTH_1| praat_HIDDEN, NEW_Table_extractColumnRanges);
 
-	praat_addAction1 (classTable, 0, U"To KlattTable", nullptr, praat_HIDDEN, DO_Table_to_KlattTable);
-	praat_addAction1 (classTable, 1, U"Get median absolute deviation...", U"Get standard deviation...", 1, DO_Table_getMedianAbsoluteDeviation);
-	praat_addAction1 (classTable, 0, U"To StringsIndex (column)...", nullptr, praat_HIDDEN, DO_Table_to_StringsIndex_column);
+	praat_addAction1 (classTable, 0, U"To KlattTable", nullptr, praat_HIDDEN, NEW_Table_to_KlattTable);
+	praat_addAction1 (classTable, 1, U"Get median absolute deviation...", U"Get standard deviation...", 1, REAL_Table_getMedianAbsoluteDeviation);
+	praat_addAction1 (classTable, 0, U"To StringsIndex (column)...", nullptr, praat_HIDDEN, NEW_Table_to_StringsIndex_column);
 
-	praat_addAction1 (classTableOfReal, 1, U"Report multivariate normality...", U"Get column stdev (label)...",
-		praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_reportMultivariateNormality);
-	praat_addAction1 (classTableOfReal, 0, U"Append columns", U"Append", 1, DO_TableOfReal_appendColumns);
+	praat_addAction1 (classTableOfReal, 1, U"Report multivariate normality...", U"Get column stdev (label)...", praat_DEPTH_1 | praat_HIDDEN, INFO_TableOfReal_reportMultivariateNormality);
+	praat_addAction1 (classTableOfReal, 0, U"Append columns", U"Append", 1, NEW1_TableOfReal_appendColumns);
 	praat_addAction1 (classTableOfReal, 0, U"Multivariate statistics -", nullptr, 0, 0);
-	praat_addAction1 (classTableOfReal, 0, U"To Discriminant", nullptr, 1, DO_TableOfReal_to_Discriminant);
-	praat_addAction1 (classTableOfReal, 0, U"To PCA", nullptr, 1, DO_TableOfReal_to_PCA_byRows);
-	praat_addAction1 (classTableOfReal, 0, U"To SSCP...", nullptr, 1, DO_TableOfReal_to_SSCP);
-	praat_addAction1 (classTableOfReal, 0, U"To Covariance", nullptr, 1, DO_TableOfReal_to_Covariance);
-	praat_addAction1 (classTableOfReal, 0, U"To Correlation", nullptr, 1, DO_TableOfReal_to_Correlation);
-	praat_addAction1 (classTableOfReal, 0, U"To Correlation (rank)", nullptr, 1, DO_TableOfReal_to_Correlation_rank);
-	praat_addAction1 (classTableOfReal, 0, U"To CCA...", nullptr, 1, DO_TableOfReal_to_CCA);
-	praat_addAction1 (classTableOfReal, 0, U"To TableOfReal (means by row labels)...", nullptr, 1, DO_TableOfReal_meansByRowLabels);
-	praat_addAction1 (classTableOfReal, 0, U"To TableOfReal (medians by row labels)...", nullptr, 1, DO_TableOfReal_mediansByRowLabels);
+	praat_addAction1 (classTableOfReal, 0, U"To Discriminant", nullptr, 1, NEW_TableOfReal_to_Discriminant);
+	praat_addAction1 (classTableOfReal, 0, U"To PCA", nullptr, 1, NEW_TableOfReal_to_PCA_byRows);
+	praat_addAction1 (classTableOfReal, 0, U"To SSCP...", nullptr, 1, NEW_TableOfReal_to_SSCP);
+	praat_addAction1 (classTableOfReal, 0, U"To Covariance", nullptr, 1, NEW_TableOfReal_to_Covariance);
+	praat_addAction1 (classTableOfReal, 0, U"To Correlation", nullptr, 1, NEW_TableOfReal_to_Correlation);
+	praat_addAction1 (classTableOfReal, 0, U"To Correlation (rank)", nullptr, 1, NEW_TableOfReal_to_Correlation_rank);
+	praat_addAction1 (classTableOfReal, 0, U"To CCA...", nullptr, 1, NEW_TableOfReal_to_CCA);
+	praat_addAction1 (classTableOfReal, 0, U"To TableOfReal (means by row labels)...", nullptr, 1, NEW_TableOfReal_meansByRowLabels);
+	praat_addAction1 (classTableOfReal, 0, U"To TableOfReal (medians by row labels)...", nullptr, 1, NEW_TableOfReal_mediansByRowLabels);
 
 	praat_addAction1 (classTableOfReal, 0, U"-- configurations --", nullptr, 1, 0);
-	praat_addAction1 (classTableOfReal, 0, U"To Configuration (pca)...", nullptr, 1, DO_TableOfReal_to_Configuration_pca);
-	praat_addAction1 (classTableOfReal, 0, U"To Configuration (lda)...", nullptr, 1, DO_TableOfReal_to_Configuration_lda);
+	praat_addAction1 (classTableOfReal, 0, U"To Configuration (pca)...", nullptr, 1, NEW_TableOfReal_to_Configuration_pca);
+	praat_addAction1 (classTableOfReal, 0, U"To Configuration (lda)...", nullptr, 1, NEW_TableOfReal_to_Configuration_lda);
 	praat_addAction1 (classTableOfReal, 2, U"-- between tables --", U"To Configuration (lda)...", 1, 0);
-	praat_addAction1 (classTableOfReal, 2, U"To TableOfReal (cross-correlations)...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_TableOfReal_and_TableOfReal_crossCorrelations);
+	praat_addAction1 (classTableOfReal, 2, U"To TableOfReal (cross-correlations)...", nullptr, praat_HIDDEN + praat_DEPTH_1, NEW1_TableOfReal_and_TableOfReal_crossCorrelations);
 
-	praat_addAction1 (classTableOfReal, 1, U"To PatternList and Categories...", U"To Matrix", 1, DO_TableOfReal_to_PatternList_and_Categories);
-	praat_addAction1 (classTableOfReal, 1, U"To Pattern and Categories...", U"To Matrix", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_to_PatternList_and_Categories);
-	praat_addAction1 (classTableOfReal, 1, U"Split into Pattern and Categories...", U"To Pattern and Categories...", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_to_PatternList_and_Categories);
-	praat_addAction1 (classTableOfReal, 0, U"To Permutation (sort row labels)", U"To Matrix", 1, DO_TableOfReal_to_Permutation_sortRowlabels);
+	praat_addAction1 (classTableOfReal, 1, U"To PatternList and Categories...", U"To Matrix", 1, NEWMANY_TableOfReal_to_PatternList_and_Categories);
+	praat_addAction1 (classTableOfReal, 1, U"To Pattern and Categories...", U"*To PatternList and Categories...", praat_DEPTH_1 | praat_DEPRECATED_2015, NEWMANY_TableOfReal_to_PatternList_and_Categories);
+	praat_addAction1 (classTableOfReal, 1, U"Split into Pattern and Categories...", U"*To PatternList and Categories...", praat_DEPTH_1 | praat_DEPRECATED_2015, NEWMANY_TableOfReal_to_PatternList_and_Categories);
+	praat_addAction1 (classTableOfReal, 0, U"To Permutation (sort row labels)", U"To Matrix", 1, NEW_TableOfReal_to_Permutation_sortRowlabels);
 
-	praat_addAction1 (classTableOfReal, 1, U"To SVD", nullptr, praat_HIDDEN, DO_TableOfReal_to_SVD);
-	praat_addAction1 (classTableOfReal, 2, U"To GSVD", nullptr, praat_HIDDEN, DO_TablesOfReal_to_GSVD);
-	praat_addAction1 (classTableOfReal, 2, U"To Eigen (gsvd)", nullptr, praat_HIDDEN, DO_TablesOfReal_to_Eigen_gsvd);
+	praat_addAction1 (classTableOfReal, 1, U"To SVD", nullptr, praat_HIDDEN, NEW_TableOfReal_to_SVD);
+	praat_addAction1 (classTableOfReal, 2, U"To GSVD", nullptr, praat_HIDDEN, NEW1_TablesOfReal_to_GSVD);
+	praat_addAction1 (classTableOfReal, 2, U"To Eigen (gsvd)", nullptr, praat_HIDDEN, NEW1_TablesOfReal_to_Eigen_gsvd);
 
-	praat_addAction1 (classTableOfReal, 0, U"To TableOfReal (cholesky)...", nullptr, praat_HIDDEN, DO_TableOfReal_choleskyDecomposition);
+	praat_addAction1 (classTableOfReal, 0, U"To TableOfReal (cholesky)...", nullptr, praat_HIDDEN, NEW_TableOfReal_choleskyDecomposition);
 
 	praat_addAction1 (classTableOfReal, 0, U"-- scatter plots --", U"Draw top and bottom lines...", 1, 0);
-	praat_addAction1 (classTableOfReal, 0, U"Draw scatter plot...", U"-- scatter plots --", 1, DO_TableOfReal_drawScatterPlot);
-	praat_addAction1 (classTableOfReal, 0, U"Draw scatter plot matrix...", U"Draw scatter plot...", 1, DO_TableOfReal_drawScatterPlotMatrix);
-	praat_addAction1 (classTableOfReal, 0, U"Draw box plots...", U"Draw scatter plot matrix...", 1, DO_TableOfReal_drawBoxPlots);
-	praat_addAction1 (classTableOfReal, 0, U"Draw biplot...", U"Draw box plots...", 1, DO_TableOfReal_drawBiplot);
-	praat_addAction1 (classTableOfReal, 0, U"Draw vectors...", U"Draw box plots...", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_drawVectors);
-	praat_addAction1 (classTableOfReal, 1, U"Draw row as histogram...", U"Draw biplot...", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_drawRowAsHistogram);
-	praat_addAction1 (classTableOfReal, 1, U"Draw rows as histogram...", U"Draw row as histogram...", praat_DEPTH_1 | praat_HIDDEN, DO_TableOfReal_drawRowsAsHistogram);
-	praat_addAction1 (classTableOfReal, 1, U"Draw column as distribution...", U"Draw rows as histogram...", praat_DEPTH_1, DO_TableOfReal_drawColumnAsDistribution);
-
-	praat_addAction2 (classStrings, 1, classPermutation, 1, U"Permute strings", nullptr, 0, DO_Strings_and_Permutation_permuteStrings);
-
-	praat_addAction2 (classTableOfReal, 1, classPermutation, 1, U"Permute rows", nullptr, 0, DO_TableOfReal_and_Permutation_permuteRows);
-
-	praat_addAction1 (classTextGrid, 0, U"Extend time...", U"Scale times...", 2, DO_TextGrid_extendTime);
-	praat_addAction1 (classTextGrid, 1, U"Set tier name...", U"Remove tier...", 1, DO_TextGrid_setTierName);
-	praat_addAction1 (classTextGrid, 0, U"Replace interval text...", U"Set interval text...", 2, DO_TextGrid_replaceIntervalTexts);
-	praat_addAction1 (classTextGrid, 0, U"Replace point text...", U"Set point text...", 2, DO_TextGrid_replacePointTexts);
-	praat_addAction1 (classTextGrid, 2, U"To Table (text alignment)...", U"Extract part...", 0, DO_TextGrids_to_Table_textAlignmentment);
-	praat_addAction2 (classTextGrid, 2, classEditCostsTable, 1, U"To Table (text alignment)...", nullptr, 0, DO_TextGrids_and_EditCostsTable_to_Table_textAlignmentment);
+	praat_addAction1 (classTableOfReal, 0, U"Draw scatter plot...", U"-- scatter plots --", 1, GRAPHICS_TableOfReal_drawScatterPlot);
+	praat_addAction1 (classTableOfReal, 0, U"Draw scatter plot matrix...", U"Draw scatter plot...", 1, GRAPHICS_TableOfReal_drawScatterPlotMatrix);
+	praat_addAction1 (classTableOfReal, 0, U"Draw box plots...", U"Draw scatter plot matrix...", 1, GRAPHICS_TableOfReal_drawBoxPlots);
+	praat_addAction1 (classTableOfReal, 0, U"Draw biplot...", U"Draw box plots...", 1, GRAPHICS_TableOfReal_drawBiplot);
+	praat_addAction1 (classTableOfReal, 0, U"Draw vectors...", U"Draw box plots...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_TableOfReal_drawVectors);
+	praat_addAction1 (classTableOfReal, 1, U"Draw row as histogram...", U"Draw biplot...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_TableOfReal_drawRowAsHistogram);
+	praat_addAction1 (classTableOfReal, 1, U"Draw rows as histogram...", U"Draw row as histogram...", praat_DEPTH_1 | praat_HIDDEN, GRAPHICS_TableOfReal_drawRowsAsHistogram);
+	praat_addAction1 (classTableOfReal, 1, U"Draw column as distribution...", U"Draw rows as histogram...", praat_DEPTH_1, GRAPHICS_TableOfReal_drawColumnAsDistribution);
+
+	praat_addAction2 (classStrings, 1, classPermutation, 1, U"Permute strings", nullptr, 0, NEW1_Strings_and_Permutation_permuteStrings);
+
+	praat_addAction2 (classTableOfReal, 1, classPermutation, 1, U"Permute rows", nullptr, 0, NEW1_TableOfReal_and_Permutation_permuteRows);
+
+	praat_addAction1 (classTextGrid, 0, U"Extend time...", U"Scale times...", 2, MODIFY_TextGrid_extendTime);
+	praat_addAction1 (classTextGrid, 1, U"Set tier name...", U"Remove tier...", 1, MODIFY_TextGrid_setTierName);
+	praat_addAction1 (classTextGrid, 0, U"Replace interval text...", U"Set interval text...", 2, MODIFY_TextGrid_replaceIntervalTexts);
+	praat_addAction1 (classTextGrid, 0, U"Replace point text...", U"Set point text...", 2, MODIFY_TextGrid_replacePointTexts);
+	praat_addAction1 (classTextGrid, 2, U"To Table (text alignment)...", U"Extract part...", 0, NEW1_TextGrids_to_Table_textAlignmentment);
+	praat_addAction2 (classTextGrid, 2, classEditCostsTable, 1, U"To Table (text alignment)...", nullptr, 0, NEW1_TextGrids_and_EditCostsTable_to_Table_textAlignmentment);
 
 	INCLUDE_MANPAGES (manual_dwtools_init)
 	INCLUDE_MANPAGES (manual_Permutation_init)
@@ -9778,4 +8068,4 @@ void praat_uvafon_David_init () {
 	INCLUDE_LIBRARY (praat_BSS_init)
 }
 
-/* End of file praat_David.cpp */
+/* End of file praat_David.cpp 9790*/
diff --git a/dwtools/praat_HMM_init.cpp b/dwtools/praat_HMM_init.cpp
index 43e335b..db5c65a 100644
--- a/dwtools/praat_HMM_init.cpp
+++ b/dwtools/praat_HMM_init.cpp
@@ -1,6 +1,6 @@
 /* praat_HMM_init.cpp
  *
- * Copyright (C) 2010-2011,2015 David Weenink
+ * Copyright (C) 2010-2011,2015-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,14 +22,8 @@
 #include "Strings_extensions.h"
 #include "TableOfReal.h"
 
-#undef iam
-#define iam iam_LOOP
-
-//#undef praat_HIDDEN
-//#define praat_HIDDEN 0
-
 #define GaussianMixture_OPTION_MENU_CRITERIA \
-	OPTIONMENU (U"Criterion based on", 1) \
+	OPTIONMENUVAR (criterion, U"Criterion based on", 1) \
 		OPTION (U"Likelihood") \
 		OPTION (U"Message length") \
 		OPTION (U"Bayes information") \
@@ -37,910 +31,715 @@
 		OPTION (U"Akaike corrected") \
 		OPTION (U"Complete-data ML")
 
-DIRECT (GaussianMixture_help)
-	Melder_help (U"GaussianMixture");
-END
+DIRECT (HELP_GaussianMixture_help) {
+	HELP (U"GaussianMixture")
+}
+
+FORM (GRAPHICS_GaussianMixture_drawConcentrationEllipses, U"GaussianMixture: Draw concentration ellipses", U"GaussianMixture: Draw concentration ellipses...") {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	BOOLEANVAR (principalComponentPlane, U"Principal component plane", true)
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (GaussianMixture)
+		GaussianMixture_drawConcentrationEllipses (me, GRAPHICS, numberOfSigmas, 0, 0, principalComponentPlane, xDimension, yDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (GaussianMixture_drawConcentrationEllipses, U"GaussianMixture: Draw concentration ellipses", U"GaussianMixture: Draw concentration ellipses...")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	BOOLEAN (U"Principal component plane", true)
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_GaussianMixture_and_PCA_drawConcentrationEllipses, U"GaussianMixture & PCA: Draw concentration ellipses", U"GaussianMixture & PCA: Draw concentration ellipses...") {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (GaussianMixture, PCA)
+		GaussianMixture_and_PCA_drawConcentrationEllipses (me, you, GRAPHICS, numberOfSigmas, 0, nullptr, xDimension, yDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_TWO_END	
+}
+
+FORM (GRAPHICS_GaussianMixture_drawMarginalPdf, U"GaussianMixture: Draw marginal pdf", U"GaussianMixture: Draw marginal pdf...") {
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	NATURALVAR (numberOfPoints, U"Number of points", U"500")
+	INTEGERVAR (numberOfBins, U"Number of bins", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (GaussianMixture);
-		GaussianMixture_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Number of sigmas"), 0, 0, GET_INTEGER (U"Principal component plane"),
-			GET_INTEGER (U"X-dimension"), GET_INTEGER (U"Y-dimension"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-FORM (GaussianMixture_and_PCA_drawConcentrationEllipses, U"GaussianMixture & PCA: Draw concentration ellipses", U"GaussianMixture & PCA: Draw concentration ellipses...")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	GaussianMixture me = FIRST (GaussianMixture);
-	PCA pca = FIRST (PCA);
-	GaussianMixture_and_PCA_drawConcentrationEllipses (me, pca, GRAPHICS,
-		GET_REAL (U"Number of sigmas"), 0, nullptr, GET_INTEGER (U"X-dimension"), GET_INTEGER (U"Y-dimension"),
-		GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-		GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-		GET_INTEGER (U"Label size"), GET_INTEGER (U"Garnish"));
-END
-
-FORM (GaussianMixture_drawMarginalPdf, U"GaussianMixture: Draw marginal pdf", U"GaussianMixture: Draw marginal pdf...")
-	INTEGER (U"X-dimension", U"1")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	NATURAL (U"Number of points", U"500")
-	INTEGER (U"Number of bins", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	GRAPHICS_EACH (GaussianMixture)
+		GaussianMixture_drawMarginalPdf (me, GRAPHICS, xDimension, xmin, xmax, ymin, ymax, numberOfPoints, numberOfBins, garnish);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (INTEGER_GaussianMixture_getNumberOfComponents) {
+	INTEGER_ONE (GaussianMixture)
+		long result = my numberOfComponents;
+	INTEGER_ONE_END (U"(= number of components)")
+}
+
+DIRECT (INTEGER_GaussianMixture_getDimensionOfComponent) {
+	INTEGER_ONE (GaussianMixture)
+		long result = my dimension;
+	INTEGER_ONE_END (U"(= dimension of component)")
+}
+
+FORM (REAL_GaussianMixture_getProbabilityAtPosition, U"GaussianMixture: Get probability at position", nullptr) {
+	SENTENCEVAR (position_string, U"Position", U"100.0 300.0")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (GaussianMixture);
-		GaussianMixture_drawMarginalPdf (me, GRAPHICS, GET_INTEGER (U"X-dimension"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Number of points"), GET_INTEGER (U"Number of bins"), GET_INTEGER (U"Garnish"));
-	}
-END
-
-DIRECT (GaussianMixture_getNumberOfComponents)
-	LOOP {
-		iam (GaussianMixture);
-		Melder_information (my numberOfComponents, U" (= number of components)");
-	}
-END
-
-DIRECT (GaussianMixture_getDimensionOfComponent)
-	LOOP {
-		iam (GaussianMixture);
-		Melder_information (my dimension, U" (= dimension of component)");
-	}
-END
-
-FORM (GaussianMixture_getProbabilityAtPosition, U"GaussianMixture: Get probability at position", nullptr)
-	SENTENCE (U"Position", U"100.0 300.0")
-	OK
-DO
-	const char32 *position = GET_STRING (U"Position");
-	LOOP {
-		iam (GaussianMixture);
-		double p = GaussianMixture_getProbabilityAtPosition_string (me, position);
-		Melder_information (p, U" (= probability at position ", position);
-	}
-END
-
-FORM (GaussianMixture_splitComponent, U"GaussianMixture: Split component", U"GaussianMixture: Split component...")
-	NATURAL (U"Component", U"1")
-	OK
-DO
-	LOOP {
-		iam (GaussianMixture);
-		GaussianMixture_splitComponent (me, GET_INTEGER (U"Component"));
-	}
-END
-
-FORM (GaussianMixture_and_PCA_drawMarginalPdf, U"GaussianMixture & PCA: Draw pdf function", U"GaussianMixture: Draw marginal pdf...")
-	INTEGER (U"X-dimension", U"1")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	NATURAL (U"Number of points", U"500")
-	INTEGER (U"Number of bins", U"0.0")
-	BOOLEAN (U"Garnish", true)
+	NUMBER_ONE (GaussianMixture)
+		double result = GaussianMixture_getProbabilityAtPosition_string (me, position_string);
+	NUMBER_ONE_END (U" (= probability at position ", position_string, U")")
+}
+
+FORM (MODIFY_GaussianMixture_splitComponent, U"GaussianMixture: Split component", U"GaussianMixture: Split component...") {
+	NATURALVAR (component, U"Component", U"1")
 	OK
 DO
-	autoPraatPicture picture;
-	GaussianMixture me = FIRST (GaussianMixture);
-	PCA thee = FIRST (PCA);
-	GaussianMixture_and_PCA_drawMarginalPdf (me, thee, GRAPHICS,
-		GET_INTEGER (U"X-dimension"),
-		GET_REAL (U"left Horizontal range"),
-		GET_REAL (U"right Horizontal range"),
-		GET_REAL (U"left Vertical range"),
-		GET_REAL (U"right Vertical range"),
-		GET_INTEGER (U"Number of points"),
-		GET_INTEGER (U"Number of bins"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (GaussianMixture_and_PCA_to_Matrix_density, U"GaussianMixture & PCA: To Matrix density", U"GaussianMixture & PCA: To Matrix (density)...")
-	INTEGER (U"X-dimension", U"1")
-	INTEGER (U"Y-dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	NATURAL (U"Number of columns", U"100")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
-	NATURAL (U"Number of rows", U"100")
-	OK
-DO
-	GaussianMixture me = FIRST (GaussianMixture);
-	PCA thee = FIRST (PCA);
-	autoMatrix result = GaussianMixture_and_PCA_to_Matrix_density (me, thee,
-		GET_INTEGER (U"X-dimension"),
-		GET_INTEGER (U"Y-dimension"),
-		GET_REAL (U"left Horizontal range"),
-		GET_REAL (U"right Horizontal range"),
-		GET_INTEGER (U"Number of columns"),
-		GET_REAL (U"left Vertical range"),
-		GET_REAL (U"right Vertical range"),
-		GET_INTEGER (U"Number of rows"));
-	praat_new (result.move(), my name, U"_", thy name);
-END
-
-FORM (GaussianMixture_extractComponent, U"GaussianMixture: Extract component", nullptr)
-	NATURAL (U"Component", U"1")
-	OK
-DO
-	LOOP {
-		iam (GaussianMixture);
-		autoCovariance result = GaussianMixture_extractComponent (me,
-			GET_INTEGER (U"Component"));
-		praat_new (result.move(), my name, U"_", result -> name);
-	}
-END
-
-DIRECT (GaussianMixture_extractCentroids)
-	LOOP {
-		iam (GaussianMixture);
+	MODIFY_EACH (GaussianMixture)
+		GaussianMixture_splitComponent (me, component);
+	MODIFY_EACH_END
+}
+
+FORM (GRAPHICS_GaussianMixture_and_PCA_drawMarginalPdf, U"GaussianMixture & PCA: Draw pdf function", U"GaussianMixture: Draw marginal pdf...") {
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	NATURALVAR (numberOfPoints, U"Number of points", U"500")
+	INTEGERVAR (numberOfBins, U"Number of bins", U"0.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (GaussianMixture, PCA)
+		GaussianMixture_and_PCA_drawMarginalPdf (me, you, GRAPHICS, xDimension, xmin, xmax, ymin, ymax, numberOfPoints, numberOfBins, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (NEW1_GaussianMixture_and_PCA_to_Matrix_density, U"GaussianMixture & PCA: To Matrix density", U"GaussianMixture & PCA: To Matrix (density)...") {
+	INTEGERVAR (xDimension, U"X-dimension", U"1")
+	INTEGERVAR (yDimension, U"Y-dimension", U"2")
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"0.0")
+	NATURALVAR (numberOfColumns, U"Number of columns", U"100")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+	NATURALVAR (numberOfRows, U"Number of rows", U"100")
+	OK
+DO
+	CONVERT_TWO (GaussianMixture, PCA)
+		autoMatrix result = GaussianMixture_and_PCA_to_Matrix_density (me, you, xDimension, yDimension, xmin, xmax, numberOfColumns, ymin, ymax, numberOfRows);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+FORM (NEW_GaussianMixture_extractComponent, U"GaussianMixture: Extract component", nullptr) {
+	NATURALVAR (component, U"Component", U"1")
+	OK
+DO
+	CONVERT_EACH (GaussianMixture)
+		autoCovariance result = GaussianMixture_extractComponent (me, component);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_GaussianMixture_extractCentroids) {
+	CONVERT_EACH (GaussianMixture)
 		autoTableOfReal result = GaussianMixture_extractCentroids (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (GaussianMixture_extractMixingProbabilities)
-	LOOP {
-		iam (GaussianMixture);
+DIRECT (NEW_GaussianMixture_extractMixingProbabilities) {
+	CONVERT_EACH (GaussianMixture)
 		autoTableOfReal result = GaussianMixture_extractMixingProbabilities (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (GaussianMixture_to_PCA)
-	LOOP {
-		iam (GaussianMixture);
+DIRECT (NEW_GaussianMixture_to_PCA) {
+	CONVERT_EACH (GaussianMixture)
 		autoPCA result = GaussianMixture_to_PCA (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-FORM (GaussianMixture_to_TableOfReal_randomSampling, U"GaussianMixture: To TableOfReal (random sampling)", U"GaussianMixture: To TableOfReal (random sampling)...")
-	NATURAL (U"Number of data points", U"100")
+FORM (NEW_GaussianMixture_to_TableOfReal_randomSampling, U"GaussianMixture: To TableOfReal (random sampling)", U"GaussianMixture: To TableOfReal (random sampling)...") {
+	NATURALVAR (numberOfPoints, U"Number of data points", U"100")
 	OK
 DO
-	long numberOfpoints = GET_INTEGER (U"Number of data points");
-	LOOP {
-		iam (GaussianMixture);
-		autoTableOfReal result = GaussianMixture_to_TableOfReal_randomSampling (me, numberOfpoints);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH (GaussianMixture)
+		autoTableOfReal result = GaussianMixture_to_TableOfReal_randomSampling (me, numberOfPoints);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (GaussianMixture_to_Covariance_between)
-	LOOP {
-		iam (GaussianMixture);
+DIRECT (NEW_GaussianMixture_to_Covariance_between) {
+	CONVERT_EACH (GaussianMixture)
 		autoCovariance result = GaussianMixture_to_Covariance_between (me);
-		praat_new (result.move(), my name, U"_b");
-	}
-END
+	CONVERT_EACH_END (my name, U"_b")
+}
 
-DIRECT (GaussianMixture_to_Covariance_within)
-	LOOP {
-		iam (GaussianMixture);
+DIRECT (NEW_GaussianMixture_to_Covariance_within) {
+	CONVERT_EACH (GaussianMixture)
 		autoCovariance result = GaussianMixture_to_Covariance_within (me);
-		praat_new (result.move(), my name, U"_w");
-	}
-END
+	CONVERT_EACH_END (my name, U"_w");
+}
 
-DIRECT (GaussianMixture_to_Covariance_total)
-	LOOP {
-		iam (GaussianMixture);
+DIRECT (NEW_GaussianMixture_to_Covariance_total) {
+	CONVERT_EACH (GaussianMixture)
 		autoCovariance result = GaussianMixture_to_Covariance_total (me);
-		praat_new (result.move(), my name, U"_t");
-	}
-END
+	CONVERT_EACH_END (my name, U"_t");
+}
 
-FORM (GaussianMixture_and_TableOfReal_getLikelihoodValue, U"GaussianMixture & TableOfReal: Get likelihood value",
-      U"GaussianMixture & TableOfReal: Get likelihood value...")
+FORM (REAL_GaussianMixture_and_TableOfReal_getLikelihoodValue, U"GaussianMixture & TableOfReal: Get likelihood value",
+      U"GaussianMixture & TableOfReal: Get likelihood value...") {
 	GaussianMixture_OPTION_MENU_CRITERIA
 	OK
 DO
-	GaussianMixture me = FIRST (GaussianMixture);
-	TableOfReal thee = FIRST (TableOfReal);
-	int criterion = GET_INTEGER (U"Criterion based on") - 1;
-	const char32 *criterionText = GaussianMixture_criterionText (criterion);
-	double lnpdn = GaussianMixture_and_TableOfReal_getLikelihoodValue (me, thee, criterion);
-	Melder_information (lnpdn / thy numberOfRows, U" (= ", criterionText, U", n = ",
-		thy numberOfRows, U")");
-END
-
-DIRECT (HMM_help)
-	Melder_help (U"HMM");
-END
-
-FORM (HMM_create, U"Create HMM", nullptr)
-	WORD (U"Name", U"hmm")
-	BOOLEAN (U"Left to right model", false)
-	NATURAL (U"Number of states", U"3")
-	NATURAL (U"Number of observations", U"3")
-	OK
-DO
-	autoHMM thee = HMM_create (
-		GET_INTEGER (U"Left to right model"),
-		GET_INTEGER (U"Number of states"),
-		GET_INTEGER (U"Number of observations"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
-
-FORM (HMM_createSimple, U"HMM: Create simple", U"HMM: Create simple HMM...")
-	WORD (U"Name", U"weather")
-	BOOLEAN (U"Left to right model", false)
-	SENTENCE (U"States", U"Rainy Sunny")
-	SENTENCE (U"Observations", U"Walk Shop Clean")
-	OK
-DO
-	autoHMM thee = HMM_createSimple (GET_INTEGER (U"Left to right model"), GET_STRING (U"States"), GET_STRING (U"Observations"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
-
-FORM (HMM_createContinuousModel, U"HMM: Create continuous model", nullptr)
-	WORD (U"Name", U"cm")
-	BOOLEAN (U"Left to right model", false)
-	NATURAL (U"Number of states", U"3")
-	NATURAL (U"Number of symbols", U"10")
+	NUMBER_TWO (GaussianMixture, TableOfReal)
+		const char32 *criterionText = GaussianMixture_criterionText (criterion);
+		double lnpdn = GaussianMixture_and_TableOfReal_getLikelihoodValue (me, you, criterion - 1);
+		double result = lnpdn / you -> numberOfRows;
+	NUMBER_TWO_END (U" (= ", criterionText, U", n = ", you -> numberOfRows, U")")
+}
+
+DIRECT (HELP_HMM_help) {
+	HELP (U"HMM")
+}
+
+FORM (NEW1_HMM_create, U"Create HMM", nullptr) {
+	WORDVAR (name, U"Name", U"hmm")
+	BOOLEANVAR (leftToRightModel, U"Left to right model", false)
+	NATURALVAR (numberOfStates, U"Number of states", U"3")
+	NATURALVAR (numberOfObservations, U"Number of observations", U"3")
+	OK
+DO
+	CREATE_ONE
+		autoHMM result = HMM_create (leftToRightModel, numberOfStates, numberOfObservations);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_HMM_createSimple, U"HMM: Create simple", U"HMM: Create simple HMM...") {
+	WORDVAR (name, U"Name", U"weather")
+	BOOLEANVAR (leftToRightModel, U"Left to right model", false)
+	SENTENCEVAR (states_string, U"States", U"Rainy Sunny")
+	SENTENCEVAR (observations_string, U"Observations", U"Walk Shop Clean")
+	OK
+DO
+	CREATE_ONE
+		autoHMM result = HMM_createSimple (leftToRightModel, states_string, observations_string);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_HMM_createContinuousModel, U"HMM: Create continuous model", nullptr) {
+	WORDVAR (name, U"Name", U"cm")
+	BOOLEANVAR (leftToRightModel, U"Left to right model", false)
+	NATURALVAR (numberOfStates, U"Number of states", U"3")
+	NATURALVAR (numberOfSymbols, U"Number of symbols", U"10")
 	LABEL (U"", U"For the Gaussian mixtures:")
-	NATURAL (U"Number of components", U"3")
-	NATURAL (U"Dimension of component", U"39")
-	OPTIONMENU (U"Covariance matrices are", 1)
+	NATURALVAR (numberOfComponents, U"Number of components", U"3")
+	NATURALVAR (componentDimension, U"Dimension of component", U"39")
+	OPTIONMENUVAR (matricesType, U"Covariance matrices are", 1)
 		OPTION (U"Complete")
 		OPTION (U"Diagonal")
 	OK
 DO
-	long componentStorage = GET_INTEGER (U"Covariance matrices are") - 1;
-	long dimension = GET_INTEGER (U"Dimension of component");
-	REQUIRE (componentStorage >= 0 && componentStorage <= dimension, U"Not a valid covariance matrix type")
-	autoHMM thee = HMM_createContinuousModel (
-		GET_INTEGER (U"Left to right model"),
-		GET_INTEGER (U"Number of states"),
-		GET_INTEGER (U"Number of symbols"),
-		GET_INTEGER (U"Number of components"),
-		dimension,
-		componentStorage);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END
-
-FORM (HMMObservationSequence_to_HMM, U"HMMObservationSequence: To HMM", nullptr)
+	REQUIRE (matricesType >= 0 && matricesType <= componentDimension, U"Not a valid covariance matrix type")
+	CREATE_ONE
+		autoHMM result = HMM_createContinuousModel (leftToRightModel, numberOfStates, numberOfSymbols, numberOfComponents, componentDimension, matricesType - 1);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW_HMMObservationSequence_to_HMM, U"HMMObservationSequence: To HMM", nullptr) {
 	LABEL (U"", U"(0 states gives a non-hidden model) ")
-	INTEGER (U"Number of hidden states", U"2")
-	BOOLEAN (U"Left to right model", false)
+	INTEGERVAR (numberOfHiddenStates, U"Number of hidden states", U"2")
+	BOOLEANVAR (leftToRightModel, U"Left to right model", false)
 	OK
 DO
-	long numberOfStates = GET_INTEGER (U"Number of hidden states");
-	LOOP {
-		iam (HMMObservationSequence);
-		autoHMM result = HMM_createFromHMMObservationSequence (me,
-			numberOfStates,
-			GET_INTEGER (U"Left to right model"));
-		praat_new (result.move(), my name, U"_", numberOfStates);
-	}
-END
+	CONVERT_EACH (HMMObservationSequence)
+		autoHMM result = HMM_createFromHMMObservationSequence (me, numberOfHiddenStates, leftToRightModel);
+	CONVERT_EACH_END (my name, U"_", numberOfHiddenStates)
+}
 
-FORM (HMM_draw, U"HMM: Draw", nullptr)
-	BOOLEAN (U"Garnish", false)
+FORM (GRAPHICS_HMM_draw, U"HMM: Draw", nullptr) {
+	BOOLEANVAR (garnish, U"Garnish", false)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (HMM);
-		HMM_draw (me, GRAPHICS,
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (HMM)
+		HMM_draw (me, GRAPHICS, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (HMM_and_HMMStateSequence_drawTrellis, U"HMM & Strings: Draw trellis", nullptr)
-	BOOLEAN (U"Connect", true);
-	BOOLEAN (U"Garnish", true);
+FORM (GRAPHICS_HMM_and_HMMStateSequence_drawTrellis, U"HMM & Strings: Draw trellis", nullptr) {
+	BOOLEANVAR (connect, U"Connect", true);
+	BOOLEANVAR (garnish, U"Garnish", true);
 	OK
 DO
-	autoPraatPicture picture;
-	HMM me = FIRST (HMM);
-	HMMStateSequence hmmStateSequence = FIRST (HMMStateSequence);
-	HMM_and_HMMStateSequence_drawTrellis (me, hmmStateSequence, GRAPHICS,
-		GET_INTEGER (U"Connect"),
-		GET_INTEGER (U"Garnish"));
-END
-
-DIRECT (HMM_drawForwardProbabilitiesIllustration)
+	GRAPHICS_TWO (HMM, HMMStateSequence)
+		HMM_and_HMMStateSequence_drawTrellis (me, you, GRAPHICS, connect, garnish);
+	GRAPHICS_TWO_END
+}
+
+DIRECT (GRAPHICS_HMM_drawForwardProbabilitiesIllustration) {
 	autoPraatPicture picture;
 	HMM_drawForwardProbabilitiesIllustration (GRAPHICS, true);
-END
+END }
 
-DIRECT (HMM_drawBackwardProbabilitiesIllustration)
+DIRECT (GRAPHICS_HMM_drawBackwardProbabilitiesIllustration) {
 	autoPraatPicture picture;
 	HMM_drawBackwardProbabilitiesIllustration (GRAPHICS, true);
-END
+END }
 
-DIRECT (HMM_drawForwardAndBackwardProbabilitiesIllustration)
+DIRECT (GRAPHICS_HMM_drawForwardAndBackwardProbabilitiesIllustration) {
 	autoPraatPicture picture;
 	HMM_drawForwardAndBackwardProbabilitiesIllustration (GRAPHICS, true);
-END
-
-FORM (HMM_getTransitionProbability, U"HMM: Get transition probability", U"HMM: Get transition probability...")
-	NATURAL (U"From state number", U"1")
-	NATURAL (U"To state number", U"1")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		long s1 = GET_INTEGER (U"From state number"), s2 = GET_INTEGER (U"To state number");
-		REQUIRE (s1 <= my numberOfStates && s2 <= my numberOfStates, U"State number(s) too high.")
-		Melder_information (my transitionProbs[s1][s2], U" : [ ", s1, U", ", s2, U" ]");
-	}
-END
-
-FORM (HMM_getEmissionProbability, U"HMM: Get emission probability", U"HMM: Get emission probability...")
-	NATURAL (U"From state number", U"1")
-	NATURAL (U"To symbol number", U"1")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		long s1 = GET_INTEGER (U"From state number"), s2 = GET_INTEGER (U"To symbol number");
-		REQUIRE (s1 <= my numberOfStates, U"State number too high.")
-		REQUIRE (s2 <= my numberOfObservationSymbols, U"Symbol number too high.")
-		Melder_information (my emissionProbs[s1][s2], U" : [ ", s1, U", ", s2, U" ]");
-	}
-END
-
-FORM (HMM_getStartProbability, U"HMM: Get start probability", U"HMM: Get start probability...")
-	NATURAL (U"State number", U"1")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		long s1 = GET_INTEGER (U"State number");
-		REQUIRE (s1 <= my numberOfStates, U"State number too high.")
-		Melder_information (my transitionProbs[0][s1], U" : [ ", s1, U" ]");
-	}
-END
-
-FORM (HMM_getProbabilityAtTimeBeingInState, U"HMM: Get probability of being in state at time",
-      U"HMM: Get p (time, state)...")
-	NATURAL (U"Time index", U"10")
-	NATURAL (U"State number", U"1")
-	OK
-DO
-	long istate = GET_INTEGER (U"State number");
-	long itime = GET_INTEGER (U"Time index");
-	LOOP {
-		iam (HMM);
-		double lnp = HMM_getProbabilityAtTimeBeingInState (me, itime, istate);
-		Melder_information (lnp, U" (= ln(p), p = ", Melder_naturalLogarithm (lnp), U") Being in state ",
-			istate, U" at time ", itime);
-	}
-END
-
-FORM (HMM_getProbabilityAtTimeBeingInStateEmittingSymbol, U"HMM: get probability being at time in state emitting symbol", U"HMM: Get p (time, state, symbol)...")
-	NATURAL (U"Time index", U"10")
-	NATURAL (U"State number", U"1")
-	NATURAL (U"Symbol number", U"1")
-	OK
-DO
-	long istate = GET_INTEGER (U"State number");
-	long itime = GET_INTEGER (U"Time index");
-	long isymbol = GET_INTEGER (U"Symbol number");
-	LOOP {
-		iam (HMM);
-		double lnp = HMM_getProbabilityAtTimeBeingInStateEmittingSymbol (me,
-			itime,
-			istate,
-			isymbol);
-		Melder_information (lnp, U" (= ln(p), p = ", Melder_naturalLogarithm (lnp), U") Being in state ",
-			istate, U" emitting symbol ", isymbol, U" at time ", itime);
-	}
-END
-
-FORM (HMM_getProbabilityOfStayingInState, U"HMM: Get probability of staying in state", U"HMM: Get probability staying in state...")
-	NATURAL (U"State number", U"1")
-	NATURAL (U"Number of times", U"2")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		Melder_informationReal (HMM_getProbabilityOfStayingInState (me,
-			GET_INTEGER (U"State number"),
-			GET_INTEGER (U"Number of times")), nullptr);
-	}
-END
-
-FORM (HMM_getExpectedValueOfDurationInState, U"HMM: Get expected value of duration in state",
-      U"HMM: Get expected duration in state...")
-	NATURAL (U"State number", U"1")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		Melder_informationReal (HMM_getExpectedValueOfDurationInState (me,
-			GET_INTEGER (U"State number")), U" time units");
-	}
-END
-
-FORM (HMM_getSymbolLabel, U"HMM: Get symbol label", nullptr)
-	NATURAL (U"Symbol number", U"1")
-	OK
-DO
-	long is = GET_INTEGER (U"Symbol number");
-	LOOP {
-		iam (HMM);
-		REQUIRE (is <= my numberOfObservationSymbols, U"Symbol number too high.")
-		HMMObservation s = my observationSymbols->at [is];
-		Melder_information (s -> label);
-	}
-END
-
-FORM (HMM_getStateLabel, U"HMM: Get state label", nullptr)
-	NATURAL (U"State number", U"1")
-	OK
-DO
-	long stateNumber = GET_INTEGER (U"State number");
-	LOOP {
-		iam (HMM);
+END }
+
+FORM (REAL_HMM_getTransitionProbability, U"HMM: Get transition probability", U"HMM: Get transition probability...") {
+	NATURALVAR (fromState, U"From state number", U"1")
+	NATURALVAR (toState, U"To state number", U"1")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		REQUIRE (fromState <= my numberOfStates && toState <= my numberOfStates, U"State number(s) too high.")
+		double result = my transitionProbs [fromState] [toState];
+	NUMBER_ONE_END (U" : [ ", fromState, U", ", toState, U" ]")
+}
+
+FORM (REAL_HMM_getEmissionProbability, U"HMM: Get emission probability", U"HMM: Get emission probability...") {
+	NATURALVAR (fromState, U"From state number", U"1")
+	NATURALVAR (toState, U"To state number", U"1")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		REQUIRE (fromState <= my numberOfStates, U"State number too high.")
+		REQUIRE (toState <= my numberOfObservationSymbols, U"Symbol number too high.")
+		double result = my emissionProbs[fromState][toState];
+	NUMBER_ONE_END (U" : [ ", fromState, U", ", toState, U" ]")
+}
+
+FORM (REAL_HMM_getStartProbability, U"HMM: Get start probability", U"HMM: Get start probability...") {
+	NATURALVAR (stateNumber, U"State number", U"1")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		REQUIRE (stateNumber <= my numberOfStates, U"State number too high.")
+		double result = my transitionProbs[0][stateNumber];
+	NUMBER_ONE_END (U" : [ ", stateNumber, U" ]")
+}
+
+FORM (REAL_HMM_getProbabilityAtTimeBeingInState, U"HMM: Get probability of being in state at time",
+      U"HMM: Get p (time, state)...") {
+	NATURALVAR (timeIndex, U"Time index", U"10")
+	NATURALVAR (stateNumber, U"State number", U"1")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		double result = HMM_getProbabilityAtTimeBeingInState (me, timeIndex, stateNumber);
+	NUMBER_ONE_END (U" (= ln(p), p = ", Melder_naturalLogarithm (result), U") Being in state ", stateNumber, U" at time ", timeIndex)
+}
+
+FORM (REAL_HMM_getProbabilityAtTimeBeingInStateEmittingSymbol, U"HMM: get probability being at time in state emitting symbol", U"HMM: Get p (time, state, symbol)...") {
+	NATURALVAR (timeIndex, U"Time index", U"10")
+	NATURALVAR (stateNumber, U"State number", U"1")
+	NATURALVAR (symbolNumber, U"Symbol number", U"1")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		double result = HMM_getProbabilityAtTimeBeingInStateEmittingSymbol (me, timeIndex, stateNumber, symbolNumber);
+	NUMBER_ONE_END (U" (= ln(p), p = ", Melder_naturalLogarithm (result), U") Being in state ", stateNumber, U" emitting symbol ", symbolNumber, U" at time ", timeIndex)
+}
+
+FORM (REAL_HMM_getProbabilityOfStayingInState, U"HMM: Get probability of staying in state", U"HMM: Get probability staying in state...") {
+	NATURALVAR (stateNumber, U"State number", U"1")
+	NATURALVAR (numberOfTimeUnits, U"Number of time units", U"2")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		double result = HMM_getProbabilityOfStayingInState (me, stateNumber, numberOfTimeUnits);
+	NUMBER_ONE_END (U"(probability of staying in state)")
+}
+
+FORM (REAL_HMM_getExpectedValueOfDurationInState, U"HMM: Get expected value of duration in state",
+      U"HMM: Get expected duration in state...") {
+	NATURALVAR (stateNumber, U"State number", U"1")
+	OK
+DO
+	NUMBER_ONE (HMM)
+		double result = HMM_getExpectedValueOfDurationInState (me, stateNumber);
+	NUMBER_ONE_END (U" time units")
+}
+
+FORM (INFO_HMM_getSymbolLabel, U"HMM: Get symbol label", nullptr) {
+	NATURALVAR (symbolNumber, U"Symbol number", U"1")
+	OK
+DO
+	STRING_ONE (HMM)
+		REQUIRE (symbolNumber <= my numberOfObservationSymbols, U"Symbol number too high.")
+		HMMObservation s = my observationSymbols->at [symbolNumber];
+		const char32 *result = s -> label;
+	STRING_ONE_END
+}
+
+FORM (INFO_HMM_getStateLabel, U"HMM: Get state label", nullptr) {
+	NATURALVAR (stateNumber, U"State number", U"1")
+	OK
+DO
+	STRING_ONE (HMM)
 		REQUIRE (stateNumber <= my numberOfStates, U"State number too high.")
 		HMMState state = my states->at [stateNumber];
-		Melder_information (state -> label);
-	}
-END
-
-FORM (HMM_and_HMM_getCrossEntropy, U"HMM & HMM: Get cross-entropy...", U"HMM & HMM: Get cross-entropy...")
-	NATURAL (U"Observation length", U"2000")
-	BOOLEAN (U"Symmetric", true)
-	OK
-DO
-	long n = GET_INTEGER (U"Observation length");
-	int sym = GET_INTEGER (U"Symmetric");
-	HMM m1 = nullptr, m2 = nullptr;
-	LOOP {
-		iam (HMM);
-		(m1 ? m2 : m1) = me;
-	}
-	Melder_assert (m1 && m2);
-	double ce = HMM_and_HMM_getCrossEntropy (m1, m2, n, sym);
-	Melder_information (ce, U" (= ", (sym ? U"symmetric " : U""),
-		U" cross-entropy between models for observation length = ", n, U")");
-END
-
-DIRECT (HMM_and_HMM_and_HMMObservationSequence_getCrossEntropy)
-	HMM m1 = nullptr, m2 = nullptr;
-	HMMObservationSequence hmm_os = nullptr;
-	LOOP {
-		if (CLASS == classHMMObservationSequence) {
-			hmm_os = (HMMObservationSequence) OBJECT;
-		} else { (m1 ? m2 : m1) = (HMM) OBJECT; }
-	}
-	Melder_assert (m1 && m2 && hmm_os);
-	double ce = HMM_and_HMM_and_HMMObservationSequence_getCrossEntropy (m1, m2, hmm_os);
-	Melder_information (ce, U" (= symmetric cross-entropy between models)");
-END
-
-FORM (HMM_to_HMMObservationSequence, U"HMM: To HMMObservationSequence (generate observations)", U"HMM: To HMMObservationSequence...")
-	INTEGER (U"Start state", U"0")
-	NATURAL (U"Number of observations", U"20")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		autoHMMObservationSequence thee = HMM_to_HMMObservationSequence (me, GET_INTEGER (U"Start state"), GET_INTEGER (U"Number of observations"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (HMM_and_HMMStateSequence_getProbability)
-	HMM me = FIRST (HMM);
-	HMMStateSequence hmm_ss = FIRST (HMMStateSequence);
-	double lnp = HMM_and_HMMStateSequence_getProbability (me, hmm_ss);
-	Melder_information (lnp, U" (= ln(p), p = ", Melder_naturalLogarithm (lnp), U")");
-END
-
-DIRECT (HMM_and_HMMObservationSequence_getProbability)
-	HMM me = FIRST (HMM);
-	HMMObservationSequence hmm_os = FIRST (HMMObservationSequence);
-	double lnp = HMM_and_HMMObservationSequence_getProbability (me, hmm_os);
-	Melder_information (lnp, U" (= ln(p), p = ", Melder_naturalLogarithm (lnp), U")");
-END
-
-DIRECT (HMM_and_HMMObservationSequence_getCrossEntropy)
-	HMM me = FIRST (HMM);
-	HMMObservationSequence hmm_os = FIRST (HMMObservationSequence);
-	double ce = HMM_and_HMMObservationSequence_getCrossEntropy (me, hmm_os);
-	Melder_information (ce, U" (= cross-entropy)");
-END
-
-DIRECT (HMM_and_HMMObservationSequence_getPerplexity)
-	HMM me = FIRST (HMM);
-	HMMObservationSequence hmm_os = FIRST (HMMObservationSequence);
-	double py = HMM_and_HMMObservationSequence_getPerplexity (me, hmm_os);
-	Melder_information (py, U" (= perplexity)");
-END
-
-DIRECT (HMM_and_HMMObservationSequence_to_HMMStateSequence)
-	HMM me = FIRST (HMM);
-	HMMObservationSequence thee = FIRST (HMMObservationSequence);
-	autoHMMStateSequence result = HMM_and_HMMObservationSequence_to_HMMStateSequence (me, thee);
-	praat_new (result.move(), my name, U"_", thy name, U"_states");
-END
-
-FORM (HMM_and_HMMObservationSequence_learn, U"HMM & HMMObservationSequence: Learn", U"HMM & HMMObservationSequences: Learn...")
-	POSITIVE (U"Relative precision in log(p)", U"0.001")
-	REAL (U"Minimum probability", U"0.00000000001")
-	BOOLEAN (U"Learning history in Info window", false)
-	OK
-DO
-	double minProb = GET_REAL (U"Minimum probability");
-	REQUIRE (minProb >= 0 && minProb < 1, U"A probabilty must be >= 0 and < 1!")
-	autoHMMObservationSequenceBag hmmObservationSequences = HMMObservationSequenceBag_create ();
-	HMM hmm = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classHMMObservationSequence) {
-			hmmObservationSequences -> addItem_ref ((HMMObservationSequence) me);
-		} else {
-			hmm = (HMM) me;
-		}
-	}
-	HMM_and_HMMObservationSequenceBag_learn (hmm, hmmObservationSequences.get(),
-		GET_REAL (U"Relative precision in log"),
-		minProb,
-		GET_INTEGER (U"Learning history in Info window"));
-END
-
-FORM (HMM_setTransitionProbabilities, U"HMM: Set transition probabilities", U"HMM: Set transition probabilities...")
-	NATURAL (U"State number", U"1")
-	SENTENCE (U"Probabilities", U"0.1 0.9")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		HMM_setTransitionProbabilities (me,
-			GET_INTEGER (U"State number"),
-			GET_STRING (U"Probabilities"));
-	}
-END
-
-FORM (HMM_setEmissionProbabilities, U"HMM: Set emission probabilities", U"HMM: Set emission probabilities...")
-	NATURAL (U"State number", U"1")
-	SENTENCE (U"Probabilities", U"0.1 0.7 0.2")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		HMM_setEmissionProbabilities (me,
-			GET_INTEGER (U"State number"),
-			GET_STRING (U"Probabilities"));
-	}
-END
-
-FORM (HMM_setStartProbabilities, U"HMM: Set start probabilities", U"HMM: Set start probabilities...")
-	SENTENCE (U"Probabilities", U"0.1 0.9")
-	OK
-DO
-	LOOP {
-		iam (HMM);
-		HMM_setStartProbabilities (me,
-			GET_STRING (U"Probabilities"));
-	}
-END
-
-DIRECT (HMM_extractTransitionProbabilities)
-	LOOP {
-		iam (HMM);
+		const char32 *result = state -> label;
+	STRING_ONE_END
+}
+
+FORM (REAL_HMM_and_HMM_getCrossEntropy, U"HMM & HMM: Get cross-entropy...", U"HMM & HMM: Get cross-entropy...") {
+	NATURALVAR (observationLength, U"Observation length", U"2000")
+	BOOLEANVAR (symmetric, U"Symmetric", true)
+	OK
+DO
+	NUMBER_COUPLE (HMM)
+		double result = HMM_and_HMM_getCrossEntropy (me, you, observationLength, symmetric);
+	NUMBER_COUPLE_END (U" (= ", (symmetric ? U"symmetric " : U""), U" cross-entropy between models for observation length = ", observationLength, U")")
+}
+
+DIRECT (REAL_HMM_and_HMM_and_HMMObservationSequence_getCrossEntropy) {
+	NUMBER_COUPLE_AND_ONE (HMM, HMMObservationSequence)
+		double result = HMM_and_HMM_and_HMMObservationSequence_getCrossEntropy (me, you, him);
+	NUMBER_COUPLE_AND_ONE_END (U"(= symmetric cross-entropy between models)")
+}
+
+FORM (NEW_HMM_to_HMMObservationSequence, U"HMM: To HMMObservationSequence (generate observations)", U"HMM: To HMMObservationSequence...") {
+	INTEGERVAR (startState, U"Start state", U"0")
+	NATURALVAR (numberOfObservations, U"Number of observations", U"20")
+	OK
+DO
+	CONVERT_EACH (HMM)
+		autoHMMObservationSequence result = HMM_to_HMMObservationSequence (me, startState, numberOfObservations);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (REAL_HMM_and_HMMStateSequence_getProbability) {
+	NUMBER_TWO (HMM, HMMStateSequence)
+		double result = HMM_and_HMMStateSequence_getProbability (me, you);
+	NUMBER_TWO_END (U" (= ln(p), p = ", Melder_naturalLogarithm (result), U")")
+}
+
+DIRECT (REAL_HMM_and_HMMObservationSequence_getProbability) {
+	NUMBER_TWO (HMM, HMMObservationSequence)
+		double result = HMM_and_HMMObservationSequence_getProbability (me, you);
+	NUMBER_TWO_END (U" (= ln(p), p = ", Melder_naturalLogarithm (result), U")")
+}
+
+DIRECT (REAL_HMM_and_HMMObservationSequence_getCrossEntropy) {
+	NUMBER_TWO (HMM, HMMObservationSequence)
+	double result = HMM_and_HMMObservationSequence_getCrossEntropy (me, you);
+	NUMBER_TWO_END (U" (= cross-entropy)")
+}
+
+DIRECT (REAL_HMM_and_HMMObservationSequence_getPerplexity) {
+	NUMBER_TWO (HMM, HMMObservationSequence)
+		double result = HMM_and_HMMObservationSequence_getPerplexity (me, you);
+	NUMBER_TWO_END (U" (= perplexity)")
+}
+
+DIRECT (NEW1_HMM_and_HMMObservationSequence_to_HMMStateSequence) {
+	CONVERT_TWO (HMM, HMMObservationSequence)
+		autoHMMStateSequence result = HMM_and_HMMObservationSequence_to_HMMStateSequence (me, you);
+	CONVERT_TWO_END (my name, U"_", your name, U"_states")
+}
+
+FORM (MODIFY_HMM_and_HMMObservationSequence_learn, U"HMM & HMMObservationSequence: Learn", U"HMM & HMMObservationSequences: Learn...") {
+	POSITIVEVAR (relativePrecision_log, U"Relative precision in log(p)", U"0.001")
+	REALVAR (minimumProbability, U"Minimum probability", U"0.00000000001")
+	BOOLEANVAR (showProgress, U"Learning history in Info window", false)
+	OK
+DO
+	REQUIRE (minimumProbability >= 0 && minimumProbability < 1, U"A probabilty must be >= 0 and < 1!")
+	MODIFY_FIRST_OF_ONE_AND_LIST(HMM, HMMObservationSequence)
+		HMM_and_HMMObservationSequenceBag_learn (me, (HMMObservationSequenceBag) &list, relativePrecision_log, minimumProbability, showProgress);
+	MODIFY_FIRST_OF_ONE_AND_LIST_END
+}
+
+FORM (MODIFY_HMM_setTransitionProbabilities, U"HMM: Set transition probabilities", U"HMM: Set transition probabilities...") {
+	NATURALVAR (stateNumber, U"State number", U"1")
+	SENTENCEVAR (probabilities_string, U"Probabilities", U"0.1 0.9")
+	OK
+DO
+	MODIFY_EACH (HMM)
+		HMM_setTransitionProbabilities (me, stateNumber, probabilities_string);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_HMM_setEmissionProbabilities, U"HMM: Set emission probabilities", U"HMM: Set emission probabilities...") {
+	NATURALVAR (stateNumber, U"State number", U"1")
+	SENTENCEVAR (probabilities_string, U"Probabilities", U"0.1 0.7 0.2")
+	OK
+DO
+	MODIFY_EACH (HMM)
+		HMM_setEmissionProbabilities (me, stateNumber, probabilities_string);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_HMM_setStartProbabilities, U"HMM: Set start probabilities", U"HMM: Set start probabilities...") {
+	SENTENCEVAR (probabilities_string, U"Probabilities", U"0.1 0.9")
+	OK
+DO
+	MODIFY_EACH (HMM)
+		HMM_setStartProbabilities (me, probabilities_string);
+	MODIFY_EACH_END
+}
+
+DIRECT (NEW_HMM_extractTransitionProbabilities) {
+	CONVERT_EACH (HMM)
 		autoTableOfReal result = HMM_extractTransitionProbabilities (me);
-		praat_new (result.move(), my name, U"_t");
-	}
-END
+	CONVERT_EACH_END (my name, U"_t")
+}
 
-DIRECT (HMM_extractEmissionProbabilities)
-	LOOP {
-		iam (HMM);
+DIRECT (NEW_HMM_extractEmissionProbabilities) {
+	CONVERT_EACH (HMM)
 		autoTableOfReal result = HMM_extractEmissionProbabilities (me);
-		praat_new (result.move(), my name, U"_e");
-	}
-END
-
-FORM (HMMObservationSequence_to_TableOfReal, U"HMMObservationSequence: To TableOfReal ", U"HMMObservationSequence: To TableOfReal (bigrams)...")
-	BOOLEAN (U"As probabilities", true)
-	OK
-DO
-	LOOP {
-		iam (HMMObservationSequence);
-		autoTableOfReal result = HMMObservationSequence_to_TableOfReal_transitions (me,
-			GET_INTEGER (U"As probabilities"));
-		praat_new (result.move(), my name);
-	}
-END
-
-FORM (HMM_and_HMMObservationSequence_to_TableOfReal, U"HMM & HMMObservationSequence: To TableOfReal", U"HMM & HMMObservationSequence: To TableOfReal (bigrams)...")
-	BOOLEAN (U"As probabilities", true)
-	OK
-DO
-	HMM me = FIRST (HMM);
-	HMMObservationSequence hmm_os = FIRST (HMMObservationSequence);
-	autoTableOfReal thee = HMM_and_HMMObservationSequence_to_TableOfReal_transitions (me, hmm_os,GET_INTEGER (U"As probabilities"));
-	praat_new (thee.move(), hmm_os -> name, U"_m");
-END
-
-FORM (HMM_and_HMMStateSequence_to_TableOfReal, U"HMM & HMMStateSequence: To TableOfReal", nullptr)
-	BOOLEAN (U"As probabilities", true)
-	OK
-DO
-	HMM me = FIRST (HMM);
-	HMMStateSequence hmm_ss = FIRST (HMMStateSequence);
-	autoTableOfReal thee = HMM_and_HMMStateSequence_to_TableOfReal_transitions (me, hmm_ss, GET_INTEGER (U"As probabilities"));
-	praat_new (thee.move(), Thing_getName (hmm_ss), U"_m");
-END
-
-FORM (HMMStateSequence_to_TableOfReal, U"HMMStateSequence: To TableOfReal", nullptr)
-	BOOLEAN (U"As probabilities", true)
-	OK
-DO
-	LOOP {
-		iam (HMMStateSequence);
-		autoTableOfReal thee = Strings_to_TableOfReal_transitions (me, GET_INTEGER (U"As probabilities"));
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (HMMObservationSequence_to_Strings)
-	LOOP {
-		iam (HMMObservationSequence);
-		autoStrings thee = HMMObservationSequence_to_Strings (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (Strings_to_HMMObservationSequence)
-	LOOP {
-		iam (Strings);
-		autoHMMObservationSequence thee = Strings_to_HMMObservationSequence (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-DIRECT (HMMStateSequence_to_Strings)
-	LOOP {
-		iam (HMMStateSequence);
-		autoStrings thee = HMMStateSequence_to_Strings (me);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (TableOfReal_to_GaussianMixture_fromRowlabels, U"TableOfReal: To GaussianMixture from row labels", U"TableOfReal: To GaussianMixture (row labels)...")
-	OPTIONMENU (U"Covariance matrices are", 1)
+	CONVERT_EACH_END (my name, U"_e")
+}
+
+FORM (NEW_HMMObservationSequence_to_TableOfReal, U"HMMObservationSequence: To TableOfReal ", U"HMMObservationSequence: To TableOfReal (bigrams)...") {
+	BOOLEANVAR (asProbabilities, U"As probabilities", true)
+	OK
+DO
+	CONVERT_EACH (HMMObservationSequence)
+		autoTableOfReal result = HMMObservationSequence_to_TableOfReal_transitions (me, asProbabilities);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW1_HMM_and_HMMObservationSequence_to_TableOfReal, U"HMM & HMMObservationSequence: To TableOfReal", U"HMM & HMMObservationSequence: To TableOfReal (bigrams)...") {
+	BOOLEANVAR (asProbabilities, U"As probabilities", true)
+	OK
+DO
+	CONVERT_TWO (HMM, HMMObservationSequence)
+		autoTableOfReal result = HMM_and_HMMObservationSequence_to_TableOfReal_transitions (me, you, asProbabilities);
+	CONVERT_TWO_END (your name, U"_m")
+}
+
+FORM (NEW1_HMM_and_HMMStateSequence_to_TableOfReal, U"HMM & HMMStateSequence: To TableOfReal", nullptr) {
+	BOOLEANVAR (asProbabilities, U"As probabilities", true)
+	OK
+DO
+	CONVERT_TWO (HMM, HMMStateSequence)
+		autoTableOfReal result = HMM_and_HMMStateSequence_to_TableOfReal_transitions (me, you, asProbabilities);
+	CONVERT_TWO_END (your name, U"_m")
+}
+
+FORM (NEW_HMMStateSequence_to_TableOfReal, U"HMMStateSequence: To TableOfReal", nullptr) {
+	BOOLEANVAR (asProbabilities, U"As probabilities", true)
+	OK
+DO
+	CONVERT_EACH (HMMStateSequence)
+		autoTableOfReal result = Strings_to_TableOfReal_transitions (me, asProbabilities);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_HMMObservationSequence_to_Strings) {
+	CONVERT_EACH (HMMObservationSequence)
+		autoStrings result = HMMObservationSequence_to_Strings (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Strings_to_HMMObservationSequence) {
+	CONVERT_EACH (Strings)
+		autoHMMObservationSequence result = Strings_to_HMMObservationSequence (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_HMMStateSequence_to_Strings) {
+	CONVERT_EACH (HMMStateSequence)
+		autoStrings result = HMMStateSequence_to_Strings (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_TableOfReal_to_GaussianMixture_fromRowlabels, U"TableOfReal: To GaussianMixture from row labels", U"TableOfReal: To GaussianMixture (row labels)...") {
+	OPTIONMENUVAR (matricesType, U"Covariance matrices are", 1)
 		OPTION (U"Complete")
 		OPTION (U"Diagonal")
 	OK
 DO
-	long storage = GET_INTEGER (U"Covariance matrices are") - 1;
-	LOOP {
-		iam (TableOfReal);
-		autoGaussianMixture thee = TableOfReal_to_GaussianMixture_fromRowLabels (me, storage);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (TableOfReal_to_GaussianMixture, U"TableOfReal: To GaussianMixture (no labels)", U"TableOfReal: To GaussianMixture...")
-	NATURAL (U"Number of components", U"2")
-	POSITIVE (U"Tolerance of minimizer", U"0.001")
-	INTEGER (U"Maximum number of iterations", U"200")
-	REAL (U"Stability coefficient lambda", U"0.001")
-	OPTIONMENU (U"Covariance matrices are", 1)
+	CONVERT_EACH (TableOfReal)
+		autoGaussianMixture result = TableOfReal_to_GaussianMixture_fromRowLabels (me, matricesType - 1);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_TableOfReal_to_GaussianMixture, U"TableOfReal: To GaussianMixture (no labels)", U"TableOfReal: To GaussianMixture...") {
+	NATURALVAR (numberOfComponents, U"Number of components", U"2")
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"0.001")
+	INTEGERVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"200")
+	REALVAR (lambda, U"Stability coefficient lambda", U"0.001")
+	OPTIONMENUVAR (matricesType, U"Covariance matrices are", 1)
 		OPTION (U"Complete")
 		OPTION (U"Diagonal")
 	GaussianMixture_OPTION_MENU_CRITERIA
 	OK
 DO
-	double lambda = GET_REAL (U"Stability coefficient lambda");
 	REQUIRE (lambda >= 0.0 && lambda < 1.0, U"Lambda must be in interval [0,1).")
-	LOOP {
-		iam (TableOfReal);
-		autoGaussianMixture thee = TableOfReal_to_GaussianMixture (me,
-			GET_INTEGER (U"Number of components"),
-			GET_REAL (U"Tolerance of minimizer"),
-			GET_INTEGER (U"Maximum number of iterations"),
-			lambda,
-			GET_INTEGER (U"Covariance matrices are") - 1,
-			GET_INTEGER (U"Criterion based on") - 1);
-		praat_new (thee.move(), my name);
-	}
-END
-
-FORM (GaussianMixture_and_TableOfReal_improveLikelihood, U"GaussianMixture & TableOfReal: Improve likelihood", U"GaussianMixture & TableOfReal: Improve likelihood...")
-	POSITIVE (U"Tolerance of minimizer", U"0.001")
-	NATURAL (U"Maximum number of iterations", U"200")
-	REAL (U"Stability coefficient lambda", U"0.001")
+	CONVERT_EACH (TableOfReal)
+		autoGaussianMixture result = TableOfReal_to_GaussianMixture (me, numberOfComponents, tolerance, maximumNumberOfIterations, lambda, matricesType - 1, criterion - 1);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (MODIFY_GaussianMixture_and_TableOfReal_improveLikelihood, U"GaussianMixture & TableOfReal: Improve likelihood", U"GaussianMixture & TableOfReal: Improve likelihood...") {
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"0.001")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"200")
+	REALVAR (lambda, U"Stability coefficient lambda", U"0.001")
 	GaussianMixture_OPTION_MENU_CRITERIA
 	OK
 DO
-	double lambda = GET_REAL (U"Stability coefficient lambda");
 	REQUIRE (lambda >= 0.0 && lambda < 1.0, U"Lambda must be in interval [0,1).")
-	GaussianMixture me = FIRST (GaussianMixture);
-	TableOfReal thee = FIRST (TableOfReal);
-	REQUIRE (thy numberOfColumns == my dimension, U"The number of columns and the dimension of the model do not agree.");
-	REQUIRE (my numberOfComponents < thy numberOfRows / 2, U"Not enough data points.")
-	GaussianMixture_and_TableOfReal_improveLikelihood (me, thee,
-		GET_REAL (U"Tolerance of minimizer"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		lambda,
-		GET_INTEGER (U"Criterion based on") - 1);
-END
-
-FORM (GaussianMixture_and_TableOfReal_to_GaussianMixture_CEMM, U"GaussianMixture & TableOfReal: To GaussianMixture (CEMM)", U"GaussianMixture & TableOfReal: To GaussianMixture (CEMM)...")
-	INTEGER (U"Minimum number of components", U"1")
-	POSITIVE (U"Tolerance of minimizer", U"0.001")
-	NATURAL (U"Maximum number of iterations", U"200")
-	REAL (U"Stability coefficient lambda", U"0.001")
+	MODIFY_FIRST_OF_TWO (GaussianMixture, TableOfReal)
+		REQUIRE (your numberOfColumns == my dimension, U"The number of columns and the dimension of the model do not agree.");
+		REQUIRE (my numberOfComponents < you -> numberOfRows / 2, U"Not enough data points.")
+		GaussianMixture_and_TableOfReal_improveLikelihood (me, you, tolerance, maximumNumberOfIterations, lambda, criterion - 1);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+FORM (NEW1_GaussianMixture_and_TableOfReal_to_GaussianMixture_CEMM, U"GaussianMixture & TableOfReal: To GaussianMixture (CEMM)", U"GaussianMixture & TableOfReal: To GaussianMixture (CEMM)...") {
+	INTEGERVAR (minimumNumberOfComponents, U"Minimum number of components", U"1")
+	POSITIVEVAR (tolerance, U"Tolerance of minimizer", U"0.001")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"200")
+	REALVAR (lambda, U"Stability coefficient lambda (0-1)", U"0.001")
 	GaussianMixture_OPTION_MENU_CRITERIA
 	OK
 DO
-	double lambda = GET_REAL (U"Stability coefficient lambda");
 	REQUIRE (lambda >= 0.0 && lambda < 1.0, U"Lambda must be in interval [0,1).")
-	GaussianMixture me = FIRST (GaussianMixture);
-	TableOfReal thee = FIRST (TableOfReal);
-	REQUIRE (thy numberOfColumns == my dimension, U"The number of columns and the dimension of the model do not agree.");
-	REQUIRE (my numberOfComponents < thy numberOfRows / 2, U"Not enough data points.")
-	autoGaussianMixture him = GaussianMixture_and_TableOfReal_to_GaussianMixture_CEMM (me, thee,
-		GET_INTEGER (U"Minimum number of components"),
-		GET_REAL (U"Tolerance of minimizer"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		lambda,
-		GET_INTEGER (U"Criterion based on") - 1);
-	praat_new (him.move(), my name);
-END
-
-DIRECT (GaussianMixture_and_TableOfReal_to_ClassificationTable)
-	GaussianMixture me = FIRST (GaussianMixture);
-	TableOfReal thee = FIRST (TableOfReal);
-	autoClassificationTable him = GaussianMixture_and_TableOfReal_to_ClassificationTable (me, thee);
-	praat_new (him.move(), my name, U"_", thy name);
-END
-
-DIRECT (GaussianMixture_and_TableOfReal_to_Correlation)
-	GaussianMixture me = FIRST (GaussianMixture);
-	TableOfReal thee = FIRST (TableOfReal);
-	autoCorrelation him = GaussianMixture_and_TableOfReal_to_Correlation (me, thee);
-	praat_new (him.move(), my name, U"_", thy name);
-END
-
-FORM (GaussianMixture_and_TableOfReal_to_TableOfReal_BHEPNormalityTests, U"GaussianMixture & TableOfReal: To TableOfReal BHEP normality tests", U"GaussianMixture & TableOfReal: To TableOfReal (BHEP normality tests)...")
-	REAL (U"Smoothing parameter", U"1.41")
-	OK
-DO
-	GaussianMixture me = FIRST (GaussianMixture);
-	TableOfReal thee = FIRST (TableOfReal);
-	double h = GET_REAL (U"Smoothing parameter");
-	autoTableOfReal him = GaussianMixture_and_TableOfReal_to_TableOfReal_BHEPNormalityTests (me, thee, h);
-	praat_new (him.move(), my name, U"_", thy name);
-END
+	CONVERT_TWO (GaussianMixture, TableOfReal)
+		REQUIRE (your numberOfColumns == my dimension, U"The number of columns and the dimension of the model do not agree.");
+		REQUIRE (my numberOfComponents < you -> numberOfRows / 2, U"Not enough data points.")
+		autoGaussianMixture result = GaussianMixture_and_TableOfReal_to_GaussianMixture_CEMM (me, you, minimumNumberOfComponents, tolerance, maximumNumberOfIterations, lambda, criterion - 1);
+	CONVERT_TWO_END (my name)
+}
+
+DIRECT (NEW1_GaussianMixture_and_TableOfReal_to_ClassificationTable) {
+	CONVERT_TWO (GaussianMixture, TableOfReal)
+		autoClassificationTable result = GaussianMixture_and_TableOfReal_to_ClassificationTable (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+DIRECT (NEW1_GaussianMixture_and_TableOfReal_to_Correlation) {
+	CONVERT_TWO (GaussianMixture, TableOfReal)
+		autoCorrelation result = GaussianMixture_and_TableOfReal_to_Correlation (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+FORM (NEW1_GaussianMixture_and_TableOfReal_to_TableOfReal_BHEPNormalityTests, U"GaussianMixture & TableOfReal: To TableOfReal BHEP normality tests", U"GaussianMixture & TableOfReal: To TableOfReal (BHEP normality tests)...") {
+	REALVAR (smoothingParameter, U"Smoothing parameter", U"1.41")
+	OK
+DO
+	CONVERT_TWO (GaussianMixture, TableOfReal)
+		autoTableOfReal result = GaussianMixture_and_TableOfReal_to_TableOfReal_BHEPNormalityTests (me, you, smoothingParameter);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
 void praat_HMM_init ();
 void praat_HMM_init () {
 	Thing_recognizeClassesByName (classHMM, classHMMState, classHMMObservation, classHMMObservationSequence, classHMMStateSequence, classGaussianMixture, nullptr);
 
 	praat_addMenuCommand (U"Objects", U"New", U"Markov models", nullptr, praat_HIDDEN, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create HMM...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_HMM_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create simple HMM...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_HMM_createSimple);
-	praat_addMenuCommand (U"Objects", U"New", U"Create continuous HMM...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_HMM_createContinuousModel);
+	praat_addMenuCommand (U"Objects", U"New", U"Create HMM...", nullptr, praat_HIDDEN + praat_DEPTH_1, NEW1_HMM_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create simple HMM...", nullptr, praat_HIDDEN + praat_DEPTH_1, NEW1_HMM_createSimple);
+	praat_addMenuCommand (U"Objects", U"New", U"Create continuous HMM...", nullptr, praat_HIDDEN + praat_DEPTH_1, NEW1_HMM_createContinuousModel);
 	praat_addMenuCommand (U"Objects", U"New", U"--drawings--", nullptr, praat_HIDDEN + praat_DEPTH_1, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Draw forward probabilities illustration", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_HMM_drawForwardProbabilitiesIllustration);
-	praat_addMenuCommand (U"Objects", U"New", U"Draw backward probabilities illustration", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_HMM_drawBackwardProbabilitiesIllustration);
-	praat_addMenuCommand (U"Objects", U"New", U"Draw forward and backward probabilities illustration", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_HMM_drawForwardAndBackwardProbabilitiesIllustration);
+	praat_addMenuCommand (U"Objects", U"New", U"Draw forward probabilities illustration", nullptr, praat_HIDDEN + praat_DEPTH_1, GRAPHICS_HMM_drawForwardProbabilitiesIllustration);
+	praat_addMenuCommand (U"Objects", U"New", U"Draw backward probabilities illustration", nullptr, praat_HIDDEN + praat_DEPTH_1, GRAPHICS_HMM_drawBackwardProbabilitiesIllustration);
+	praat_addMenuCommand (U"Objects", U"New", U"Draw forward and backward probabilities illustration", nullptr, praat_HIDDEN + praat_DEPTH_1, GRAPHICS_HMM_drawForwardAndBackwardProbabilitiesIllustration);
 
-	praat_addAction1 (classGaussianMixture, 0, U"GaussianMixture help", nullptr, 0, DO_GaussianMixture_help);
-	praat_addAction1 (classGaussianMixture, 0, U"Draw concentration ellipses...", nullptr, 0, DO_GaussianMixture_drawConcentrationEllipses);
-	praat_addAction1 (classGaussianMixture, 0, U"Draw marginal pdf...", nullptr, 0, DO_GaussianMixture_drawMarginalPdf);
+	praat_addAction1 (classGaussianMixture, 0, U"GaussianMixture help", nullptr, 0, HELP_GaussianMixture_help);
+	praat_addAction1 (classGaussianMixture, 0, U"Draw concentration ellipses...", nullptr, 0, GRAPHICS_GaussianMixture_drawConcentrationEllipses);
+	praat_addAction1 (classGaussianMixture, 0, U"Draw marginal pdf...", nullptr, 0, GRAPHICS_GaussianMixture_and_PCA_drawConcentrationEllipses);
 	praat_addAction1 (classGaussianMixture, 0, U"Query -", nullptr, 0, nullptr);
-	praat_addAction1 (classGaussianMixture, 1, U"Get number of components", nullptr, 1, DO_GaussianMixture_getNumberOfComponents);
-	praat_addAction1 (classGaussianMixture, 1, U"Get dimension of component", nullptr, 1, DO_GaussianMixture_getDimensionOfComponent);
-	praat_addAction1 (classGaussianMixture, 1, U"Get probability at position...", nullptr, 1, DO_GaussianMixture_getProbabilityAtPosition);
+	praat_addAction1 (classGaussianMixture, 1, U"Get number of components", nullptr, 1, INTEGER_GaussianMixture_getNumberOfComponents);
+	praat_addAction1 (classGaussianMixture, 1, U"Get dimension of component", nullptr, 1, INTEGER_GaussianMixture_getDimensionOfComponent);
+	praat_addAction1 (classGaussianMixture, 1, U"Get probability at position...", nullptr, 1, REAL_GaussianMixture_getProbabilityAtPosition);
 	praat_addAction1 (classGaussianMixture, 0, U"Modify -", nullptr, 0, nullptr);
-	praat_addAction1 (classGaussianMixture, 1, U"Split component...", nullptr, 1, DO_GaussianMixture_splitComponent);
+	praat_addAction1 (classGaussianMixture, 1, U"Split component...", nullptr, 1, MODIFY_GaussianMixture_splitComponent);
 	praat_addAction1 (classGaussianMixture, 0, U"Extract -", nullptr, 0, nullptr);
-	praat_addAction1 (classGaussianMixture, 0, U"Extract mixing probabilities", nullptr, 1, DO_GaussianMixture_extractMixingProbabilities);
-	praat_addAction1 (classGaussianMixture, 0, U"Extract component...", nullptr, 1, DO_GaussianMixture_extractComponent);
-	praat_addAction1 (classGaussianMixture, 0, U"Extract centroids", nullptr, 1, DO_GaussianMixture_extractCentroids);
-	praat_addAction1 (classGaussianMixture, 0, U"To Covariance (between)", nullptr, 0, DO_GaussianMixture_to_Covariance_between);
-	praat_addAction1 (classGaussianMixture, 0, U"To Covariance (within)", nullptr, 0, DO_GaussianMixture_to_Covariance_within);
-	praat_addAction1 (classGaussianMixture, 0, U"To Covariance (total)", nullptr, 0, DO_GaussianMixture_to_Covariance_total);
-	praat_addAction1 (classGaussianMixture, 0, U"To PCA", nullptr, 0, DO_GaussianMixture_to_PCA);
-	praat_addAction1 (classGaussianMixture, 0, U"To TableOfReal (random sampling)...", nullptr, 0, DO_GaussianMixture_to_TableOfReal_randomSampling);
-
-	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"Get likelihood value...", nullptr, 0, DO_GaussianMixture_and_TableOfReal_getLikelihoodValue);
-	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"Improve likelihood...", nullptr, 0, DO_GaussianMixture_and_TableOfReal_improveLikelihood);
-	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To GaussianMixture (CEMM)...", nullptr, 0, DO_GaussianMixture_and_TableOfReal_to_GaussianMixture_CEMM);
-	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To ClassificationTable", nullptr, 0, DO_GaussianMixture_and_TableOfReal_to_ClassificationTable);
-	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To Correlation", nullptr, 0, DO_GaussianMixture_and_TableOfReal_to_Correlation);
-	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To TableOfReal (BHEP normality tests)...", nullptr, 0, DO_GaussianMixture_and_TableOfReal_to_TableOfReal_BHEPNormalityTests);
-
-	praat_addAction2 (classGaussianMixture, 1, classPCA, 1, U"Draw concentration ellipses...", nullptr, 0, DO_GaussianMixture_and_PCA_drawConcentrationEllipses);
-	praat_addAction2 (classGaussianMixture, 1, classPCA, 1, U"Draw marginal pdf...", nullptr, 0, DO_GaussianMixture_and_PCA_drawMarginalPdf);
-	praat_addAction2 (classGaussianMixture, 1, classPCA, 1, U"To Matrix (density)...", nullptr, 0, DO_GaussianMixture_and_PCA_to_Matrix_density);
-
-	praat_addAction1 (classHMM, 0, U"HMM help ", nullptr, 0, DO_HMM_help);
-	praat_addAction1 (classHMM, 0, U"Draw...", nullptr, 0, DO_HMM_draw);
+	praat_addAction1 (classGaussianMixture, 0, U"Extract mixing probabilities", nullptr, 1, NEW_GaussianMixture_extractMixingProbabilities);
+	praat_addAction1 (classGaussianMixture, 0, U"Extract component...", nullptr, 1, NEW_GaussianMixture_extractComponent);
+	praat_addAction1 (classGaussianMixture, 0, U"Extract centroids", nullptr, 1, NEW_GaussianMixture_extractCentroids);
+	praat_addAction1 (classGaussianMixture, 0, U"To Covariance (between)", nullptr, 0, NEW_GaussianMixture_to_Covariance_between);
+	praat_addAction1 (classGaussianMixture, 0, U"To Covariance (within)", nullptr, 0, NEW_GaussianMixture_to_Covariance_within);
+	praat_addAction1 (classGaussianMixture, 0, U"To Covariance (total)", nullptr, 0, NEW_GaussianMixture_to_Covariance_total);
+	praat_addAction1 (classGaussianMixture, 0, U"To PCA", nullptr, 0, NEW_GaussianMixture_to_PCA);
+	praat_addAction1 (classGaussianMixture, 0, U"To TableOfReal (random sampling)...", nullptr, 0, NEW_GaussianMixture_to_TableOfReal_randomSampling);
+
+	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"Get likelihood value...", nullptr, 0, REAL_GaussianMixture_and_TableOfReal_getLikelihoodValue);
+	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"Improve likelihood...", nullptr, 0, MODIFY_GaussianMixture_and_TableOfReal_improveLikelihood);
+	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To GaussianMixture (CEMM)...", nullptr, 0, NEW1_GaussianMixture_and_TableOfReal_to_GaussianMixture_CEMM);
+	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To ClassificationTable", nullptr, 0, NEW1_GaussianMixture_and_TableOfReal_to_ClassificationTable);
+	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To Correlation", nullptr, 0, NEW1_GaussianMixture_and_TableOfReal_to_Correlation);
+	praat_addAction2 (classGaussianMixture, 1, classTableOfReal, 1, U"To TableOfReal (BHEP normality tests)...", nullptr, 0, NEW1_GaussianMixture_and_TableOfReal_to_TableOfReal_BHEPNormalityTests);
+
+	praat_addAction2 (classGaussianMixture, 1, classPCA, 1, U"Draw concentration ellipses...", nullptr, 0, GRAPHICS_GaussianMixture_and_PCA_drawConcentrationEllipses);
+	praat_addAction2 (classGaussianMixture, 1, classPCA, 1, U"Draw marginal pdf...", nullptr, 0, GRAPHICS_GaussianMixture_and_PCA_drawMarginalPdf);
+	praat_addAction2 (classGaussianMixture, 1, classPCA, 1, U"To Matrix (density)...", nullptr, 0, NEW1_GaussianMixture_and_PCA_to_Matrix_density);
+
+	praat_addAction1 (classHMM, 0, U"HMM help ", nullptr, 0, HELP_HMM_help);
+	praat_addAction1 (classHMM, 0, U"Draw...", nullptr, 0, GRAPHICS_HMM_draw);
 	praat_addAction1 (classHMM, 0, U"Query -", nullptr, 0, nullptr);
-	praat_addAction1 (classHMM, 1, U"Get transition probability...", nullptr, 1, DO_HMM_getTransitionProbability);
-	praat_addAction1 (classHMM, 1, U"Get emission probability...", nullptr, 1, DO_HMM_getEmissionProbability);
-	praat_addAction1 (classHMM, 1, U"Get start probability...", nullptr, 1, DO_HMM_getStartProbability);
-	praat_addAction1 (classHMM, 1, U"Get p (time, state)...", nullptr, 1, DO_HMM_getProbabilityAtTimeBeingInState);
-	praat_addAction1 (classHMM, 1, U"Get p (time, state, symbol)...", nullptr, 1, DO_HMM_getProbabilityAtTimeBeingInStateEmittingSymbol);
-	praat_addAction1 (classHMM, 1, U"Get probability staying in state...", nullptr, 1, DO_HMM_getProbabilityOfStayingInState);
-	praat_addAction1 (classHMM, 1, U"Get expected duration in state...", nullptr, 1, DO_HMM_getExpectedValueOfDurationInState);
+	praat_addAction1 (classHMM, 1, U"Get transition probability...", nullptr, 1, REAL_HMM_getTransitionProbability);
+	praat_addAction1 (classHMM, 1, U"Get emission probability...", nullptr, 1, REAL_HMM_getEmissionProbability);
+	praat_addAction1 (classHMM, 1, U"Get start probability...", nullptr, 1, REAL_HMM_getStartProbability);
+	praat_addAction1 (classHMM, 1, U"Get p (time, state)...", nullptr, 1, REAL_HMM_getProbabilityAtTimeBeingInState);
+	praat_addAction1 (classHMM, 1, U"Get p (time, state, symbol)...", nullptr, 1, REAL_HMM_getProbabilityAtTimeBeingInStateEmittingSymbol);
+	praat_addAction1 (classHMM, 1, U"Get probability staying in state...", nullptr, 1, REAL_HMM_getProbabilityOfStayingInState);
+	praat_addAction1 (classHMM, 1, U"Get expected duration in state...", nullptr, 1, REAL_HMM_getExpectedValueOfDurationInState);
 	praat_addAction1 (classHMM, 1, U"---- states / symbols -----", nullptr, 1, nullptr);
-	praat_addAction1 (classHMM, 1, U"Get state label...", nullptr, 1, DO_HMM_getStateLabel);
-	praat_addAction1 (classHMM, 1, U"Get symbol label...", nullptr, 1, DO_HMM_getSymbolLabel);
+	praat_addAction1 (classHMM, 1, U"Get state label...", nullptr, 1, INFO_HMM_getStateLabel);
+	praat_addAction1 (classHMM, 1, U"Get symbol label...", nullptr, 1, INFO_HMM_getSymbolLabel);
 	praat_addAction1 (classHMM, 0, U"--- multiple HMMs ----", nullptr, 1, nullptr);
-	praat_addAction1 (classHMM, 2, U"Get cross-entropy...", nullptr, 1, DO_HMM_and_HMM_getCrossEntropy);
+	praat_addAction1 (classHMM, 2, U"Get cross-entropy...", nullptr, 1, REAL_HMM_and_HMM_getCrossEntropy);
 
 	praat_addAction1 (classHMM, 0, U"Modify -", nullptr, 0, nullptr);
-	praat_addAction1 (classHMM, 1, U"Set transition probabilities...", nullptr, 1, DO_HMM_setTransitionProbabilities);
-	praat_addAction1 (classHMM, 1, U"Set emission probabilities...", nullptr, 1, DO_HMM_setEmissionProbabilities);
-	praat_addAction1 (classHMM, 1, U"Set start probabilities...", nullptr, 1, DO_HMM_setStartProbabilities);
+	praat_addAction1 (classHMM, 1, U"Set transition probabilities...", nullptr, 1, MODIFY_HMM_setTransitionProbabilities);
+	praat_addAction1 (classHMM, 1, U"Set emission probabilities...", nullptr, 1, MODIFY_HMM_setEmissionProbabilities);
+	praat_addAction1 (classHMM, 1, U"Set start probabilities...", nullptr, 1, MODIFY_HMM_setStartProbabilities);
 
 	praat_addAction1 (classHMM, 0, U"Extract -", nullptr, 0, nullptr);
-	praat_addAction1 (classHMM, 0, U"Extract transition probabilities", nullptr, 1, DO_HMM_extractTransitionProbabilities);
-	praat_addAction1 (classHMM, 0, U"Extract emission probabilities", nullptr, 1, DO_HMM_extractEmissionProbabilities);
+	praat_addAction1 (classHMM, 0, U"Extract transition probabilities", nullptr, 1, NEW_HMM_extractTransitionProbabilities);
+	praat_addAction1 (classHMM, 0, U"Extract emission probabilities", nullptr, 1, NEW_HMM_extractEmissionProbabilities);
 
-	praat_addAction1 (classHMM, 0, U"To HMMObservationSequence...", nullptr, 0, DO_HMM_to_HMMObservationSequence);
-	praat_addAction2 (classHMM, 1, classHMMStateSequence, 1, U"Draw trellis...", nullptr, 0, DO_HMM_and_HMMStateSequence_drawTrellis);
-	praat_addAction2 (classHMM, 1, classHMMStateSequence, 1, U"Get probability", nullptr, 0, DO_HMM_and_HMMStateSequence_getProbability);
-	praat_addAction2 (classHMM, 1, classHMMStateSequence, 1, U"To TableOfReal (bigrams)...", nullptr, 0, DO_HMM_and_HMMStateSequence_to_TableOfReal);
-	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"Get probability", nullptr, 0, DO_HMM_and_HMMObservationSequence_getProbability);
-	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"Get cross-entropy", nullptr, 0, DO_HMM_and_HMMObservationSequence_getCrossEntropy);
-	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"Get perplexity", nullptr, 0, DO_HMM_and_HMMObservationSequence_getPerplexity);
+	praat_addAction1 (classHMM, 0, U"To HMMObservationSequence...", nullptr, 0, NEW_HMM_to_HMMObservationSequence);
+	praat_addAction2 (classHMM, 1, classHMMStateSequence, 1, U"Draw trellis...", nullptr, 0, GRAPHICS_HMM_and_HMMStateSequence_drawTrellis);
+	praat_addAction2 (classHMM, 1, classHMMStateSequence, 1, U"Get probability", nullptr, 0, REAL_HMM_and_HMMStateSequence_getProbability);
+	praat_addAction2 (classHMM, 1, classHMMStateSequence, 1, U"To TableOfReal (bigrams)...", nullptr, 0, NEW1_HMM_and_HMMStateSequence_to_TableOfReal);
+	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"Get probability", nullptr, 0, REAL_HMM_and_HMMObservationSequence_getProbability);
+	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"Get cross-entropy", nullptr, 0, REAL_HMM_and_HMMObservationSequence_getCrossEntropy);
+	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"Get perplexity", nullptr, 0, REAL_HMM_and_HMMObservationSequence_getPerplexity);
 
 
-	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"To HMMStateSequence", nullptr, 0, DO_HMM_and_HMMObservationSequence_to_HMMStateSequence);
-	praat_addAction2 (classHMM, 2, classHMMObservationSequence, 1, U"Get cross-entropy", nullptr, 0, DO_HMM_and_HMM_and_HMMObservationSequence_getCrossEntropy);
-	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"To TableOfReal (bigrams)...", nullptr, 0, DO_HMM_and_HMMObservationSequence_to_TableOfReal);
-	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 0, U"Learn...", nullptr, 0, DO_HMM_and_HMMObservationSequence_learn);
+	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"To HMMStateSequence", nullptr, 0, NEW1_HMM_and_HMMObservationSequence_to_HMMStateSequence);
+	praat_addAction2 (classHMM, 2, classHMMObservationSequence, 1, U"Get cross-entropy", nullptr, 0, REAL_HMM_and_HMM_and_HMMObservationSequence_getCrossEntropy);
+	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 1, U"To TableOfReal (bigrams)...", nullptr, 0, NEW1_HMM_and_HMMObservationSequence_to_TableOfReal);
+	praat_addAction2 (classHMM, 1, classHMMObservationSequence, 0, U"Learn...", nullptr, 0, MODIFY_HMM_and_HMMObservationSequence_learn);
 
-	praat_addAction1 (classHMMObservationSequence, 0, U"To TableOfReal (bigrams)...", nullptr, 0, DO_HMMObservationSequence_to_TableOfReal);
-	praat_addAction1 (classHMMObservationSequence, 0, U"To Strings", nullptr, 0, DO_HMMObservationSequence_to_Strings);
-	praat_addAction1 (classHMMStateSequence, 0, U"To TableOfReal (bigrams)...", nullptr, 0, DO_HMMStateSequence_to_TableOfReal);
-	praat_addAction1 (classHMMStateSequence, 0, U"To Strings", nullptr, 0, DO_HMMStateSequence_to_Strings);
+	praat_addAction1 (classHMMObservationSequence, 0, U"To TableOfReal (bigrams)...", nullptr, 0, NEW_HMMObservationSequence_to_TableOfReal);
+	praat_addAction1 (classHMMObservationSequence, 0, U"To Strings", nullptr, 0, NEW_HMMObservationSequence_to_Strings);
+	praat_addAction1 (classHMMStateSequence, 0, U"To TableOfReal (bigrams)...", nullptr, 0, NEW_HMMStateSequence_to_TableOfReal);
+	praat_addAction1 (classHMMStateSequence, 0, U"To Strings", nullptr, 0, NEW_HMMStateSequence_to_Strings);
 
-	praat_addAction1 (classHMMObservationSequence, 0, U"To HMM...", nullptr, 1, DO_HMMObservationSequence_to_HMM);
+	praat_addAction1 (classHMMObservationSequence, 0, U"To HMM...", nullptr, 1, NEW_HMMObservationSequence_to_HMM);
 
-	praat_addAction1 (classStrings, 0, U"To HMMObservationSequence", nullptr, praat_HIDDEN, DO_Strings_to_HMMObservationSequence);
-	praat_addAction1 (classTableOfReal, 0, U"To GaussianMixture (row labels)...", U"To Covariance", praat_HIDDEN + praat_DEPTH_1, DO_TableOfReal_to_GaussianMixture_fromRowlabels);
-	praat_addAction1 (classTableOfReal, 0, U"To GaussianMixture...", U"To Covariance", praat_HIDDEN + praat_DEPTH_1, DO_TableOfReal_to_GaussianMixture);
+	praat_addAction1 (classStrings, 0, U"To HMMObservationSequence", nullptr, praat_HIDDEN, NEW_Strings_to_HMMObservationSequence);
+	praat_addAction1 (classTableOfReal, 0, U"To GaussianMixture (row labels)...", U"To Covariance", praat_HIDDEN + praat_DEPTH_1, NEW_TableOfReal_to_GaussianMixture_fromRowlabels);
+	praat_addAction1 (classTableOfReal, 0, U"To GaussianMixture...", U"To Covariance", praat_HIDDEN + praat_DEPTH_1, NEW_TableOfReal_to_GaussianMixture);
 
 	INCLUDE_MANPAGES (manual_HMM)
 }
 
-/* End of file praat_HMM_init.cpp */
+/* End of file praat_HMM_init.cpp 941*/
diff --git a/dwtools/praat_KlattGrid_init.cpp b/dwtools/praat_KlattGrid_init.cpp
index 44f3a8c..009dd0b 100644
--- a/dwtools/praat_KlattGrid_init.cpp
+++ b/dwtools/praat_KlattGrid_init.cpp
@@ -1,6 +1,6 @@
 /* praat_KlattGrid_init.cpp
  *
- * Copyright (C) 2009-2015 David Weenink
+ * Copyright (C) 2009-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,188 +25,158 @@
 #include "IntensityTierEditor.h"
 #include "KlattGridEditors.h"
 #include "KlattTable.h"
+#include "praat_TimeFunction.h"
 
 #undef iam
 #define iam iam_LOOP
 
-
 /******************* KlattGrid  *********************************/
 
 static const char32 *formant_names[] = { U"", U"oral ", U"nasal ", U"frication ", U"tracheal ", U"nasal anti", U"tracheal anti", U"delta "};
 
-static void KlattGrid_4formants_addCommonField (UiForm dia) {
-	UiField radio;
-	OPTIONMENU (U"Formant type", 1)
-		OPTION (U"Normal formant")
-		OPTION (U"Nasal formant")
-		OPTION (U"Frication formant")
+#define KlattGrid_4formants_addCommonField(formantType) \
+	OPTIONMENUVAR (formantType, U"Formant type", 1) \
+		OPTION (U"Normal formant") \
+		OPTION (U"Nasal formant") \
+		OPTION (U"Frication formant") \
 		OPTION (U"Tracheal formant")
-}
 
-static void KlattGrid_6formants_addCommonField (UiForm dia) {
-	UiField radio;
-	OPTIONMENU (U"Formant type", 1)
-		OPTION (U"Normal formant")
-		OPTION (U"Nasal formant")
-		OPTION (U"Frication formant")
-		OPTION (U"Tracheal formant")
-		OPTION (U"Nasal antiformant")
-		OPTION (U"Tracheal antiformant")
-		//	OPTION (U"Delta formant")
-}
-
-static void KlattGrid_7formants_addCommonField (UiForm dia) {
-	UiField radio;
-	OPTIONMENU (U"Formant type", 1)
-		OPTION (U"Normal formant")
-		OPTION (U"Nasal formant")
-		OPTION (U"Frication formant")
-		OPTION (U"Tracheal formant")
-		OPTION (U"Nasal antiformant")
-		OPTION (U"Tracheal antiformant")
+#define KlattGrid_6formants_addCommonField(formantType) \
+	OPTIONMENUVAR (formantType, U"Formant type", 1) \
+		OPTION (U"Normal formant") \
+		OPTION (U"Nasal formant") \
+		OPTION (U"Frication formant") \
+		OPTION (U"Tracheal formant") \
+		OPTION (U"Nasal antiformant") \
+		OPTION (U"Tracheal antiformant") \
+	//	OPTION (U"Delta formant")
+
+#define KlattGrid_7formants_addCommonField(formantType) \
+	OPTIONMENUVAR (formantType, U"Formant type", 1) \
+		OPTION (U"Normal formant") \
+		OPTION (U"Nasal formant") \
+		OPTION (U"Frication formant") \
+		OPTION (U"Tracheal formant") \
+		OPTION (U"Nasal antiformant") \
+		OPTION (U"Tracheal antiformant") \
 		OPTION (U"Delta formant")
+
+#define KlattGrid_PhonationGridPlayOptions_addCommonFields(useVoicing,useFlutter,useDoublePulsing,useCollisionPhase,useSpectralTilt,flowFunctionType,useFlowDerivative,useAspiration,useBreathiness) \
+	BOOLEANVAR (useVoicing, U"Voicing", true) \
+	BOOLEANVAR (useFlutter, U"Flutter", true) \
+	BOOLEANVAR (useDoublePulsing, U"Double pulsing", true) \
+	BOOLEANVAR (useCollisionPhase, U"Collision phase", true) \
+	BOOLEANVAR (useSpectralTilt, U"Spectral tilt", true) \
+	OPTIONMENUVAR (flowFunctionType, U"Flow function", 1) \
+		OPTION (U"Powers in tiers") \
+		OPTION (U"t^2-t^3") \
+		OPTION (U"t^3-t^4") \
+	BOOLEANVAR (useFlowDerivative, U"Flow derivative", true) \
+	BOOLEANVAR (useAspiration, U"Aspiration", true) \
+	BOOLEANVAR (useBreathiness, U"Breathiness", true)
+
+static void KlattGrid_PhonationGridPlayOptions (KlattGrid me, int useVoicing, int useFlutter, int useDoublePulsing, int useCollisionPhase, int useSpectralTilt, int flowFunctionType, int useFlowDerivative, int useAspiration, int useBreathiness) {
+	PhonationGridPlayOptions pp = my phonation -> options.get();
+	pp -> voicing = useVoicing;
+	pp -> flutter = useFlutter;
+	pp -> doublePulsing = useDoublePulsing;
+	pp -> collisionPhase = useCollisionPhase;
+	pp -> spectralTilt = useSpectralTilt;
+	pp -> flowFunction = flowFunctionType;
+	pp -> flowDerivative = useFlowDerivative;
+	pp -> aspiration = useAspiration;
+	pp -> breathiness = useBreathiness;
 }
 
-static void KlattGrid_PhonationGridPlayOptions_addCommonFields (UiForm dia) {
-	UiField radio;
-	//LABEL (U"", U"Phonation options")
-	BOOLEAN (U"Voicing", true)
-	BOOLEAN (U"Flutter", true)
-	BOOLEAN (U"Double pulsing", true)
-	BOOLEAN (U"Collision phase", true)
-	BOOLEAN (U"Spectral tilt", true)
-	OPTIONMENU (U"Flow function", 1)
-		OPTION (U"Powers in tiers")
-		OPTION (U"t^2-t^3")
-		OPTION (U"t^3-t^4")
-	BOOLEAN (U"Flow derivative", true)
-	BOOLEAN (U"Aspiration", true)
-	BOOLEAN (U"Breathiness", true)
+#define KlattGrid_formantSelection_vocalTract_commonFields(filtersStructure,fromOralFormant,toOralFormant,fromNasalFormant,toNasalFormant,fromNasalAntiFormant,toNasalAntiFormant) \
+	OPTIONMENUVAR (filtersStructure, U"Filter options", 1) \
+		OPTION (U"Cascade") \
+		OPTION (U"Parallel") \
+	INTEGERVAR (fromOralFormant, U"left Oral formant range", U"1") \
+	INTEGERVAR (toOralFormant, U"right Oral formant range", U"5") \
+	INTEGERVAR (fromNasalFormant, U"left Nasal formant range", U"1") \
+	INTEGERVAR (toNasalFormant, U"right Nasal formant range", U"1") \
+	INTEGERVAR (fromNasalAntiFormant, U"left Nasal antiformant range", U"1") \
+	INTEGERVAR (toNasalAntiFormant, U"right Nasal antiformant range", U"1")
+	
+static void KlattGrid_formantSelection_vocalTract (KlattGrid me, int filtersStructure, long fromOralFormant, long toOralFormant, long fromNasalFormant, long toNasalFormant, long fromNasalAntiFormant, long toNasalAntiFormant) {
+	VocalTractGridPlayOptions pv = my vocalTract -> options.get();
+	pv -> filterModel = (filtersStructure == 1 ? KlattGrid_FILTER_CASCADE : KlattGrid_FILTER_PARALLEL);
+	pv -> startOralFormant = fromOralFormant;
+	pv -> endOralFormant  = toOralFormant;
+	pv -> startNasalFormant = fromNasalFormant;
+	pv -> endNasalFormant = toNasalFormant;
+	pv -> startNasalAntiFormant = fromNasalAntiFormant;
+	pv -> endNasalAntiFormant = toNasalAntiFormant;
 }
 
-static void KlattGrid_PhonationGridPlayOptions_getCommonFields (UiForm dia, KlattGrid thee) {
-	PhonationGridPlayOptions pp = thy phonation -> options.get();
-	pp -> voicing = GET_INTEGER (U"Voicing");
-	pp -> flutter = GET_INTEGER (U"Flutter");
-	pp -> doublePulsing = GET_INTEGER (U"Double pulsing");
-	pp -> collisionPhase = GET_INTEGER (U"Collision phase");
-	pp -> spectralTilt = GET_INTEGER (U"Spectral tilt");
-	pp -> flowFunction = GET_INTEGER (U"Flow function");
-	pp -> flowDerivative = GET_INTEGER (U"Flow derivative");
-	pp -> aspiration = GET_INTEGER (U"Aspiration");
-	pp -> breathiness = GET_INTEGER (U"Breathiness");
+#define KlattGrid_formantSelection_coupling_commonFields(fromTrachealFormant,toTrachealFormant,fromTrachealAntiFormant,toTrachealAntiFormant,fromDeltaFormant,toDeltaFormant,fromDeltaBandwidth,toDeltaBandwidth) \
+	INTEGERVAR (fromTrachealFormant, U"left Tracheal formant range", U"1") \
+	INTEGERVAR (toTrachealFormant, U"right Tracheal formant range", U"1") \
+	INTEGERVAR (fromTrachealAntiFormant, U"left Tracheal antiformant range", U"1") \
+	INTEGERVAR (toTrachealAntiFormant, U"right Tracheal antiformant range", U"1") \
+	INTEGERVAR (fromDeltaFormant, U"left Delta formant range", U"1") \
+	INTEGERVAR (toDeltaFormant, U"right Delta formant range", U"1") \
+	INTEGERVAR (fromDeltaBandwidth, U"left Delta bandwidth range", U"1") \
+	INTEGERVAR (toDeltaBandwidth, U"right Delta bandwidth range", U"1")
+
+static void KlattGrid_formantSelection_coupling (KlattGrid me, long fromTrachealFormant, long toTrachealFormant, long fromTrachealAntiFormant, long toTrachealAntiFormant, long fromDeltaFormant, long toDeltaFormant, long fromDeltaBandwidth, long toDeltaBandwidth) {
+	CouplingGridPlayOptions pc = my coupling -> options.get();
+	pc -> startTrachealFormant = fromTrachealFormant;
+	pc -> endTrachealFormant = toTrachealFormant;
+	pc -> startTrachealAntiFormant = fromTrachealAntiFormant;
+	pc -> endTrachealAntiFormant = toTrachealAntiFormant;
+	pc -> startDeltaFormant = fromDeltaFormant;
+	pc -> endDeltaFormant = toDeltaFormant;
+	pc -> startDeltaBandwidth = fromDeltaBandwidth;
+	pc -> endDeltaFormant = toDeltaBandwidth;
 }
 
-static void KlattGrid_PlayOptions_addCommonFields (UiForm dia, bool hasSound) {
-	UiField radio;
-	//LABEL (U"", U"Time domain")
-	REAL (U"left Time range (s)", U"0")
-	REAL (U"right Time range (s)", U"0")
-	if (hasSound) {
-		POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	}
-	BOOLEAN (U"Scale peak", true)
-	KlattGrid_PhonationGridPlayOptions_addCommonFields (dia);
-	OPTIONMENU (U"Filter options", 1)
-		OPTION (U"Cascade")
-		OPTION (U"Parallel")
-	INTEGER (U"left Oral formant range", U"1")
-	INTEGER (U"right Oral formant range", U"5")
-	INTEGER (U"left Nasal formant range", U"1")
-	INTEGER (U"right Nasal formant range", U"1")
-	INTEGER (U"left Nasal antiformant range", U"1")
-	INTEGER (U"right Nasal antiformant range", U"1")
-	//LABEL (U"", U"Coupling options")
-	INTEGER (U"left Tracheal formant range", U"1")
-	INTEGER (U"right Tracheal formant range", U"1")
-	INTEGER (U"left Tracheal antiformant range", U"1")
-	INTEGER (U"right Tracheal antiformant range", U"1")
-	INTEGER (U"left Delta formant range", U"1")
-	INTEGER (U"right Delta formant range", U"1")
-	INTEGER (U"left Delta bandwidth range", U"1")
-	INTEGER (U"right Delta bandwidth range", U"1")
-	//LABEL (U"", U"Frication options")
-	INTEGER (U"left Frication formant range", U"1")
-	INTEGER (U"right Frication formant range", U"6")
-	BOOLEAN (U"Frication bypass", true)
+#define KlattGrid_formantSelection_frication_commonFields(fromFricationFormant,toFricationFormant,useFricationBypass) \
+	INTEGERVAR (fromFricationFormant, U"left Frication formant range", U"1") \
+	INTEGERVAR (toFricationFormant, U"right Frication formant range", U"6") \
+	BOOLEANVAR (useFricationBypass, U"Frication bypass", true)
+
+static void KlattGrid_formantSelection_frication (KlattGrid me, long fromFricationFormant, long toFricationFormant, int useFricationBypass) {
+	FricationGridPlayOptions pf = my frication -> options.get();
+	pf -> startFricationFormant = fromFricationFormant;
+	pf -> endFricationFormant = toFricationFormant;
+	pf -> bypass = useFricationBypass;
 }
 
-static void KlattGrid_PlayOptions_getCommonFields (UiForm dia, bool hasSound, KlattGrid thee) {
-	KlattGrid_setDefaultPlayOptions (thee);
-	KlattGridPlayOptions pk = thy options.get();
-	pk -> scalePeak = GET_INTEGER (U"Scale peak");
-	pk -> xmin = GET_REAL (U"left Time range");
-	pk -> xmax = GET_REAL (U"right Time range");
-	if (hasSound) {
-		pk -> samplingFrequency = GET_REAL (U"Sampling frequency");
-	}
-	pk -> scalePeak = GET_INTEGER (U"Scale peak");
-	KlattGrid_PhonationGridPlayOptions_getCommonFields (dia, thee);
-	VocalTractGridPlayOptions pv = thy vocalTract -> options.get();
-	pv -> filterModel = ( GET_INTEGER (U"Filter options") == 1 ? KlattGrid_FILTER_CASCADE : KlattGrid_FILTER_PARALLEL );
-	pv -> startOralFormant = GET_INTEGER (U"left Oral formant range");
-	pv -> endOralFormant  = GET_INTEGER (U"right Oral formant range");
-	pv -> startNasalFormant = GET_INTEGER (U"left Nasal formant range");
-	pv -> endNasalFormant = GET_INTEGER (U"right Nasal formant range");
-	pv -> startNasalAntiFormant = GET_INTEGER (U"left Nasal antiformant range");
-	pv -> endNasalAntiFormant = GET_INTEGER (U"right Nasal antiformant range");
-	CouplingGridPlayOptions pc = thy coupling -> options.get();
-	pc -> startTrachealFormant = GET_INTEGER (U"left Tracheal formant range");
-	pc -> endTrachealFormant = GET_INTEGER (U"right Tracheal formant range");
-	pc -> startTrachealAntiFormant = GET_INTEGER (U"left Tracheal antiformant range");
-	pc -> endTrachealAntiFormant = GET_INTEGER (U"right Tracheal antiformant range");
-	pc -> startDeltaFormant = GET_INTEGER (U"left Delta formant range");
-	pc -> endDeltaFormant = GET_INTEGER (U"right Delta formant range");
-	pc -> startDeltaBandwidth = GET_INTEGER (U"left Delta bandwidth range");
-	pc -> endDeltaFormant = GET_INTEGER (U"right Delta bandwidth range");
-	FricationGridPlayOptions pf = thy frication -> options.get();
-	pf -> startFricationFormant = GET_INTEGER (U"left Frication formant range");
-	pf -> endFricationFormant = GET_INTEGER (U"right Frication formant range");
-	pf -> bypass = GET_INTEGER (U"Frication bypass");
+DIRECT (NEW1_KlattGrid_createExample) {
+	CREATE_ONE
+		autoKlattGrid result = KlattGrid_createExample();
+	CREATE_ONE_END (U"example")
 }
 
-DIRECT (KlattGrid_createExample)
-	praat_new (KlattGrid_createExample(), U"example");
-END
-
-FORM (KlattGrid_create, U"Create KlattGrid", U"Create KlattGrid...")
-	WORD (U"Name", U"kg")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	INTEGER (U"Number of oral formants", U"6")
-	INTEGER (U"Number of nasal formants", U"1")
-	INTEGER (U"Number of nasal antiformants", U"1")
-	INTEGER (U"Number of frication formants", U"6")
+FORM (NEW1_KlattGrid_create, U"Create KlattGrid", U"Create KlattGrid...") {
+	WORDVAR (name, U"Name", U"kg")
+	REALVAR (fromTime, U"Start time (s)", U"0.0")
+	REALVAR (toTime, U"End time (s)", U"1.0")
+	INTEGERVAR (numberOfOralFormants, U"Number of oral formants", U"6")
+	INTEGERVAR (numberOfNasalFormants, U"Number of nasal formants", U"1")
+	INTEGERVAR (numberOfNasalAntiFormants, U"Number of nasal antiformants", U"1")
+	INTEGERVAR (numberOfFricationFormants, U"Number of frication formants", U"6")
 	LABEL (U"", U"Coupling between source and filter")
-	INTEGER (U"Number of tracheal formants", U"1")
-	INTEGER (U"Number of tracheal antiformants", U"1")
-	INTEGER (U"Number of delta formants", U"1")
+	INTEGERVAR (numberOfTrachealFormants, U"Number of tracheal formants", U"1")
+	INTEGERVAR (numberOfTrachealAntiFormants, U"Number of tracheal antiformants", U"1")
+	INTEGERVAR (numberOfDeltaFormants, U"Number of delta formants", U"1")
 	OK
 DO
-	double tmin = GET_REAL (U"Start time");
-	double tmax = GET_REAL (U"End time");
-	REQUIRE (tmin < tmax, U"The start time must lie before the end time.")
-	long numberOfOralFormants = GET_INTEGER (U"Number of oral formants");
-	long numberOfNasalFormants = GET_INTEGER (U"Number of nasal formants");
-	long numberOfNasalAntiFormants = GET_INTEGER (U"Number of nasal antiformants");
-	long numberOfTrachealFormants = GET_INTEGER (U"Number of tracheal formants");
-	long numberOfTrachealAntiFormants = GET_INTEGER (U"Number of tracheal antiformants");
-	long numberOfFricationFormants = GET_INTEGER (U"Number of frication formants");
-	long numberOfDeltaFormants = GET_INTEGER (U"Number of delta formants");
+	REQUIRE (fromTime < toTime, U"The start time must lie before the end time.")
 	REQUIRE (numberOfOralFormants >= 0 && numberOfNasalFormants >= 0 && numberOfNasalAntiFormants >= 0
 		&& numberOfTrachealFormants >= 0 && numberOfTrachealAntiFormants >= 0
 		&& numberOfFricationFormants >= 0 && numberOfDeltaFormants >= 0,
 		U"The number of (..) formants cannot be negative!")
-	praat_new (KlattGrid_create (tmin, tmax, numberOfOralFormants,
-		numberOfNasalFormants, numberOfNasalAntiFormants,
-		numberOfTrachealFormants, numberOfTrachealAntiFormants,
-		numberOfFricationFormants, numberOfDeltaFormants),
-		GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoKlattGrid result = KlattGrid_create (fromTime, toTime, numberOfOralFormants, numberOfNasalFormants, numberOfNasalAntiFormants, numberOfTrachealFormants, numberOfTrachealAntiFormants, numberOfFricationFormants, numberOfDeltaFormants);
+	CREATE_ONE_END (name)
+}
 
 
 #define KlattGrid_INSTALL_TIER_EDITOR(Name) \
-DIRECT (KlattGrid_edit##Name##Tier) \
+DIRECT (WINDOW_KlattGrid_edit##Name##Tier)  {\
 	if (theCurrentPraatApplication -> batch) { Melder_throw (U"Cannot edit a KlattGrid from batch."); } \
 	LOOP {\
 		iam (KlattGrid); \
@@ -214,7 +184,7 @@ DIRECT (KlattGrid_edit##Name##Tier) \
 		praat_installEditor (editor.get(), IOBJECT); \
 		editor.releaseToUser(); \
 	}\
-END
+END }
 
 KlattGrid_INSTALL_TIER_EDITOR (Pitch)
 KlattGrid_INSTALL_TIER_EDITOR (VoicingAmplitude)
@@ -233,17 +203,17 @@ KlattGrid_INSTALL_TIER_EDITOR (FricationAmplitude)
 
 #undef KlattGrid_INSTALL_TIER_EDITOR
 
-#define KlattGRID_EDIT_FORMANTGRID(Name,formantType) \
-DIRECT (KlattGrid_edit##Name##FormantGrid) \
+#define KlattGRID_EDIT_FORMANTGRID(Name,formantType)  \
+DIRECT (WINDOW_KlattGrid_edit##Name##FormantGrid) { \
 	if (theCurrentPraatApplication -> batch) { Melder_throw (U"Cannot edit a KlattGrid from batch."); } \
-	LOOP {\
+	LOOP { \
 		iam (KlattGrid); \
-		const char32 *id_and_name = Melder_cat (ID, U". ", formant_names[formantType], U"formant grid"); \
+		const char32 *id_and_name = Melder_cat (ID, U". ", formant_names [formantType], U" formant grid"); \
 		autoKlattGrid_FormantGridEditor editor = KlattGrid_FormantGridEditor_create (id_and_name, me, formantType); \
 		praat_installEditor (editor.get(), IOBJECT); \
 		editor.releaseToUser(); \
 	} \
-END
+END }
 
 KlattGRID_EDIT_FORMANTGRID (Oral, KlattGrid_ORAL_FORMANTS)
 KlattGRID_EDIT_FORMANTGRID (Nasal, KlattGrid_NASAL_FORMANTS)
@@ -255,24 +225,23 @@ KlattGRID_EDIT_FORMANTGRID (Frication, KlattGrid_FRICATION_FORMANTS)
 
 #undef KlattGRID_EDIT_FORMANTGRID
 
-#define KlattGrid_EDIT_FORMANT_AMPLITUDE_TIER(Name,name,formantType) \
-FORM (KlattGrid_edit##Name##FormantAmplitudeTier, U"KlattGrid: View & Edit " #name "formant amplitude tier", nullptr) \
-	NATURAL (U"Formant number", U"1") \
+#define KlattGrid_EDIT_FORMANT_AMPLITUDE_TIER(Name,name,formantType)  \
+FORM (WINDOW_KlattGrid_edit##Name##FormantAmplitudeTier, U"KlattGrid: View & Edit " #name " formant amplitude tier", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
 	OK \
 DO \
-	long formantNumber = GET_INTEGER (U"Formant number"); \
 	if (theCurrentPraatApplication -> batch) { Melder_throw (U"Cannot edit a KlattGrid from batch."); } \
 	LOOP { \
 		iam (KlattGrid); \
 		OrderedOf<structIntensityTier>* amp = KlattGrid_getAddressOfAmplitudes (me, formantType); \
 		if (! amp) Melder_throw (U"Unknown formant type"); \
 		if (formantNumber > amp->size) Melder_throw (U"Formant number does not exist."); \
-		const char32 *id_and_name = Melder_cat (ID, U". ", formant_names[formantType], U"formant amplitude tier"); \
+		const char32 *id_and_name = Melder_cat (ID, U". ", formant_names [formantType], U" formant amplitude tier"); \
 		autoKlattGrid_DecibelTierEditor editor = KlattGrid_DecibelTierEditor_create (id_and_name, me, amp->at [formantNumber]); \
 		praat_installEditor (editor.get(), IOBJECT); \
 		editor.releaseToUser(); \
 	} \
-END
+END }
 
 KlattGrid_EDIT_FORMANT_AMPLITUDE_TIER (Oral, oral, KlattGrid_ORAL_FORMANTS)
 KlattGrid_EDIT_FORMANT_AMPLITUDE_TIER (Nasal, nasal, KlattGrid_NASAL_FORMANTS)
@@ -281,48 +250,44 @@ KlattGrid_EDIT_FORMANT_AMPLITUDE_TIER (Frication, frication, KlattGrid_FRICATION
 
 #undef KlattGrid_EDIT_FORMANT_AMPLITUDE_TIER
 
-#define KlattGrid_PHONATION_GET_ADD_REMOVE_EXTRACT_REPLACE(Name,name,unit,default,require,requiremessage,newname,tiertype) \
-FORM (KlattGrid_get##Name##AtTime, U"KlattGrid: Get " #name " at time", nullptr) \
-	REAL (U"Time", U"0.5") \
+#define KlattGrid_PHONATION_GET_ADD_REMOVE_EXTRACT_REPLACE(Name,name,unit,default,require,requiremessage,newname,tiertype)  \
+FORM (REAL_KlattGrid_get##Name##AtTime, U"KlattGrid: Get " #name " at time", nullptr) { \
+	REALVAR (time, U"Time", U"0.5") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-	Melder_informationReal (KlattGrid_get##Name##AtTime (me, GET_REAL (U"Time")), unit); \
-	}\
-END \
-FORM (KlattGrid_add##Name##Point, U"KlattGrid: Add " #name " point", nullptr) \
-	REAL (U"Time (s)", U"0.5") \
-	REAL (U"Value" unit, default) \
+	NUMBER_ONE (KlattGrid) \
+		double result = KlattGrid_get##Name##AtTime (me, time); \
+	NUMBER_ONE_END (unit) \
+} \
+FORM (MODIFY_KlattGrid_add##Name##Point, U"KlattGrid: Add " #name " point", nullptr) { \
+	REALVAR (time, U"Time (s)", U"0.5") \
+	REALVAR (value, U"Value" unit, default) \
 	OK \
 DO \
-	double value = GET_REAL (U"Value"); \
 	REQUIRE (require, requiremessage) \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_add##Name##Point (me, GET_REAL (U"Time"), value); \
-		praat_dataChanged (me); \
-	} \
-END \
-FORM (KlattGrid_remove##Name##Points, U"Remove " #name " points", nullptr) \
-	REAL (U"From time (s)", U"0.3")\
-	REAL (U"To time (s)", U"0.7") \
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_add##Name##Point (me, time, value); \
+	MODIFY_EACH_END \
+} \
+FORM (MODIFY_KlattGrid_remove##Name##Points, U"Remove " #name " points", nullptr) { \
+	REALVAR (fromTime, U"From time (s)", U"0.3") \
+	REALVAR (toTime, U"To time (s)", U"0.7") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_remove##Name##Points (me, GET_REAL (U"From time"), GET_REAL (U"To time")); \
-		praat_dataChanged (me);\
-	} \
-END \
-DIRECT (KlattGrid_extract##Name##Tier) \
-	LOOP { iam (KlattGrid); \
-		praat_new (KlattGrid_extract##Name##Tier (me), newname); \
-	} \
-END \
-DIRECT (KlattGrid_replace##Name##Tier) \
-	KlattGrid me = FIRST(KlattGrid); \
-	tiertype thee = FIRST(tiertype); \
-	KlattGrid_replace##Name##Tier (me, thee); \
-	praat_dataChanged (me);\
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_remove##Name##Points (me, fromTime, toTime); \
+	MODIFY_EACH_END \
+} \
+DIRECT (NEW_KlattGrid_extract##Name##Tier) { \
+	CONVERT_EACH (KlattGrid) \
+		autoDaata result = KlattGrid_extract##Name##Tier (me); \
+	CONVERT_EACH_END (newname) \
+} \
+DIRECT (MODIFY_KlattGrid_replace##Name##Tier) { \
+	MODIFY_FIRST_OF_TWO (KlattGrid, tiertype); \
+		KlattGrid_replace##Name##Tier (me, you); \
+	MODIFY_FIRST_OF_TWO_END \
+}
 
 // 55 DO_KlattGrid... functions
 KlattGrid_PHONATION_GET_ADD_REMOVE_EXTRACT_REPLACE (Pitch, pitch, U" (Hz)", (U"100.0"),
@@ -355,115 +320,105 @@ KlattGrid_PHONATION_GET_ADD_REMOVE_EXTRACT_REPLACE (FricationBypass, frication b
 
 #undef KlattGrid_PHONATION_GET_ADD_REMOVE_EXTRACT_REPLACE
 
-#define KlattGrid_FORMULA_FORMANT_FBA_VALUE(Name,namef,ForBs,forbs,textfield,formantType,label) \
-FORM (KlattGrid_formula##Name##Formant##ForBs, U"KlattGrid: Formula (" #namef "ormant " #forbs ")", U"Formant: Formula (" #forbs ")...") \
+#define KlattGrid_FORMULA_FORMANT_FBA_VALUE(Name,namef,ForBs,forbs,textfield,formantType,label)  \
+FORM (MODIFY_KlattGrid_formula##Name##Formant##ForBs, U"KlattGrid: Formula (" #namef "ormant " #forbs ")", U"Formant: Formula (" #forbs ")...") { \
 	LABEL (U"", U"row is formant number, col is point number:\nfor row from 1 to nrow do for col from 1 to ncol do " #ForBs " (row, col) :=") \
 	LABEL (U"", label) \
-	TEXTFIELD (U"formula", textfield) \
+	TEXTVAR (formula, U"formula", textfield) \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_formula_##forbs (me, formantType, GET_STRING (U"formula"), interpreter); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_formula_##forbs (me, formantType, formula, interpreter); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_ADD_FBA_VALUE(Name,namef,Form,FBA,fba,formantType,default,unit,require,requiremessage) \
-FORM (KlattGrid_add##Name##Formant##FBA##Point, U"KlattGrid: Add " #namef "ormant " #fba " point", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
-	REAL (U"Value " #unit, default) \
+#define KlattGrid_ADD_FBA_VALUE(Name,namef,Form,FBA,fba,formantType,default,unit,require,requiremessage)  \
+FORM (MODIFY_KlattGrid_add##Name##Formant##FBA##Point, U"KlattGrid: Add " #namef "ormant " #fba " point", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
+	REALVAR (value, U"Value " #unit, default) \
 	OK \
 DO \
-	double value = GET_REAL (U"Value"); \
 	REQUIRE (require, requiremessage) \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_add##Form##Point (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), value); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_add##Form##Point (me, formantType, formantNumber, time, value); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_REMOVE_FBA_VALUE(Name,namef,Form,FBA,fba,formantType) \
-FORM (KlattGrid_remove##Name##Formant##FBA##Points, U"KlattGrid: Remove " #namef "ormant " #fba " points", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"From time (s)", U"0.3")\
-	REAL (U"To time (s)", U"0.7") \
+#define KlattGrid_REMOVE_FBA_VALUE(Name,namef,Form,FBA,fba,formantType)  \
+FORM (MODIFY_KlattGrid_remove##Name##Formant##FBA##Points, U"KlattGrid: Remove " #namef "ormant " #fba " points", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (fromTime, U"From time (s)", U"0.3")\
+	REALVAR (toTime, U"To time (s)", U"0.7") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_remove##Form##Points (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"From time"), GET_REAL (U"To time")); \
-		praat_dataChanged (me);\
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_remove##Form##Points (me, formantType, formantNumber, fromTime, toTime); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_ADD_FORMANT(Name,namef,formantType) \
-FORM (KlattGrid_add##Name##Formant, U"KlattGrid: Add " #namef "ormant", nullptr) \
-	INTEGER (U"Position", U"0 (= at end)") \
+#define KlattGrid_ADD_FORMANT(Name,namef,formantType)  \
+FORM (MODIFY_KlattGrid_add##Name##Formant, U"KlattGrid: Add " #namef "ormant", nullptr) { \
+	INTEGERVAR (position, U"Position", U"0 (= at end)") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_addFormant (me, formantType, GET_INTEGER (U"Position")); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_addFormant (me, formantType, position); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_REMOVE_FORMANT(Name,namef,formantType) \
-FORM (KlattGrid_remove##Name##Formant, U"KlattGrid: Remove " #namef "ormant", nullptr) \
-	INTEGER (U"Position", U"0 (= do nothing)") \
+#define KlattGrid_REMOVE_FORMANT(Name,namef,formantType)  \
+FORM (MODIFY_KlattGrid_remove##Name##Formant, U"KlattGrid: Remove " #namef "ormant", nullptr) { \
+	INTEGERVAR (position, U"Position", U"0 (= do nothing)") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_removeFormant (me, formantType, GET_INTEGER (U"Position")); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_removeFormant (me, formantType, position); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-FORM (KlattGrid_add##Name##FormantFrequencyAndBandwidthTiers, U"KlattGrid: Add " #namef "ormant", nullptr) \
-	INTEGER (U"Position", U"0 (= at end)") \
+#define KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType)  \
+FORM (MODIFY_KlattGrid_add##Name##FormantFrequencyAndBandwidthTiers, U"KlattGrid: Add " #namef "ormant", nullptr) { \
+	INTEGERVAR (position, U"Position", U"0 (= at end)") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_addFormantFrequencyAndBandwidthTiers (me, formantType, GET_INTEGER (U"Position")); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_addFormantFrequencyAndBandwidthTiers (me, formantType, position); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-FORM (KlattGrid_remove##Name##FormantFrequencyAndBandwidthTiers, U"KlattGrid: Remove " #namef "ormant", nullptr) \
-	INTEGER (U"Position", U"0 (= do nothing)") \
+#define KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType)  \
+FORM (MODIFY_KlattGrid_remove##Name##FormantFrequencyAndBandwidthTiers, U"KlattGrid: Remove " #namef "ormant", nullptr) { \
+	INTEGERVAR (position, U"Position", U"0 (= at end)") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_removeFormantFrequencyAndBandwidthTiers (me, formantType, GET_INTEGER (U"Position")); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_removeFormantFrequencyAndBandwidthTiers (me, formantType, position); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_ADD_FORMANT_AMPLITUDETIER(Name,namef,formantType) \
-FORM (KlattGrid_add##Name##FormantAmplitudeTier, U"KlattGrid: Add " #namef "ormant amplitude tier", nullptr) \
-	INTEGER (U"Position", U"0 (= at end)") \
+#define KlattGrid_ADD_FORMANT_AMPLITUDETIER(Name,namef,formantType)  \
+FORM (MODIFY_KlattGrid_add##Name##FormantAmplitudeTier, U"KlattGrid: Add " #namef "ormant amplitude tier", nullptr) { \
+	INTEGERVAR (position, U"Position", U"0 (= at end)") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_addFormantAmplitudeTier (me, formantType, GET_INTEGER (U"Position")); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_addFormantAmplitudeTier (me, formantType, position); \
+	MODIFY_EACH_END \
+}
 
-#define KlattGrid_REMOVE_FORMANT_AMPLITUDETIER(Name,namef,formantType) \
-FORM (KlattGrid_remove##Name##FormantAmplitudeTier, U"KlattGrid: Remove " #namef "ormant amplitude tier", nullptr) \
-	INTEGER (U"Position", U"0 (= do nothing)") \
+#define KlattGrid_REMOVE_FORMANT_AMPLITUDETIER(Name,namef,formantType)  \
+FORM (MODIFY_KlattGrid_remove##Name##FormantAmplitudeTier, U"KlattGrid: Remove " #namef "ormant amplitude tier", nullptr) { \
+	INTEGERVAR (position, U"Position", U"0 (= at end)") \
 	OK \
 DO \
-	LOOP { iam (KlattGrid); \
-		KlattGrid_removeFormant (me, formantType, GET_INTEGER (U"Position")); \
-		praat_dataChanged (me); \
-	} \
-END
+	MODIFY_EACH (KlattGrid); \
+		KlattGrid_removeFormant (me, formantType, position); \
+	MODIFY_EACH_END \
+}
 
 
-#define KlattGrid_FORMULA_ADD_REMOVE_FBA(Name,namef,formantType) \
+#define KlattGrid_FORMULA_ADD_REMOVE_FBA(Name,namef,formantType)  \
 KlattGrid_FORMULA_FORMANT_FBA_VALUE (Name, namef, Frequencies, frequencies, U"if row = 2 then self + 200 else self fi", formantType, U" ") \
 KlattGrid_FORMULA_FORMANT_FBA_VALUE (Name, namef, Bandwidths, bandwidths, U"self / 10 ; 10% of frequency", formantType, U"Warning: self is formant frequency.") \
 KlattGrid_ADD_FBA_VALUE (Name, namef, Formant, Frequency, frequency, formantType, U"500.0", (Hz), (value>0), U"Frequency must be greater than zero.") \
@@ -472,15 +427,15 @@ KlattGrid_ADD_FBA_VALUE (Name, namef, Amplitude, Amplitude, amplitude, formantTy
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Formant, Frequency, frequency, formantType) \
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Bandwidth, Bandwidth, bandwidth, formantType) \
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Amplitude, Amplitude, amplitude, formantType) \
-KlattGrid_ADD_FORMANT(Name,namef,formantType) \
-KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT_AMPLITUDETIER(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT(Name,namef,formantType) \
-KlattGrid_ADD_FORMANT_AMPLITUDETIER(Name,namef,formantType)
+KlattGrid_ADD_FORMANT (Name, namef, formantType) \
+KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT_AMPLITUDETIER (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT (Name, namef, formantType) \
+KlattGrid_ADD_FORMANT_AMPLITUDETIER (Name, namef, formantType)
 
 
-#define KlattGrid_FORMULA_ADD_REMOVE_FB(Name,namef,formantType) \
+#define KlattGrid_FORMULA_ADD_REMOVE_FB(Name,namef,formantType)  \
 KlattGrid_FORMULA_FORMANT_FBA_VALUE (Name, namef, Frequencies, frequencies, U"if row = 2 then self + 200 else self fi",formantType, U" ") \
 KlattGrid_FORMULA_FORMANT_FBA_VALUE (Name, namef, Bandwidths, bandwidths, U"self / 10 ; 10% of frequency",formantType, U"Warning: self is formant frequency.") \
 KlattGrid_ADD_FBA_VALUE (Name, namef, Formant,Frequency, frequency, formantType, U"500.0", (Hz), (value>0), U"Frequency must be greater than zero.") \
@@ -488,21 +443,21 @@ KlattGrid_ADD_FBA_VALUE (Name, namef, Bandwidth, Bandwidth, bandwidth, formantTy
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Formant, Frequency, frequency, formantType) \
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Bandwidth, Bandwidth, bandwidth, formantType) \
 KlattGrid_ADD_FORMANT(Name,namef,formantType) \
-KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT(Name,namef,formantType)
+KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT (Name, namef, formantType)
 
-#define KlattGrid_FORMULA_ADD_REMOVE_FB_DELTA(Name,namef,formantType) \
+#define KlattGrid_FORMULA_ADD_REMOVE_FB_DELTA(Name,namef,formantType)  \
 KlattGrid_FORMULA_FORMANT_FBA_VALUE (Name, namef, Frequencies, frequencies, U"if row = 2 then self + 200 else self fi",formantType, U" ") \
 KlattGrid_FORMULA_FORMANT_FBA_VALUE (Name, namef, Bandwidths, bandwidths, U"self / 10 ; 10% of frequency",formantType, U"Warning: self is formant frequency.") \
 KlattGrid_ADD_FBA_VALUE (Name, namef, Formant,Frequency, frequency, formantType, U"-100.0", (Hz), (value!=NUMundefined), U"Frequency must be defined.") \
 KlattGrid_ADD_FBA_VALUE (Name, namef, Bandwidth, Bandwidth, bandwidth, formantType,  U"-50.0", (Hz), (value!=NUMundefined), U"Bandwidth must be defined.") \
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Formant, Frequency, frequency, formantType) \
 KlattGrid_REMOVE_FBA_VALUE (Name, namef, Bandwidth, Bandwidth, bandwidth, formantType) \
-KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS(Name,namef,formantType) \
-KlattGrid_ADD_FORMANT(Name,namef,formantType) \
-KlattGrid_REMOVE_FORMANT(Name,namef,formantType)
+KlattGrid_ADD_FORMANT_FREQUENCYANDBANDWIDTHTIERS (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT_FREQUENCYANDBANDWIDTHTIERS (Name, namef, formantType) \
+KlattGrid_ADD_FORMANT (Name, namef, formantType) \
+KlattGrid_REMOVE_FORMANT (Name, namef, formantType)
 
 KlattGrid_FORMULA_ADD_REMOVE_FBA (Oral, oral f, KlattGrid_ORAL_FORMANTS)
 KlattGrid_FORMULA_ADD_REMOVE_FBA (Nasal, nasal f, KlattGrid_NASAL_FORMANTS)
@@ -519,66 +474,59 @@ KlattGrid_FORMULA_ADD_REMOVE_FBA (Frication, frication f, KlattGrid_FRICATION_FO
 #undef KlattGrid_ADD_FBA_VALUE
 #undef KlattGrid_FORMULA_FORMANT_FB_VALUE
 
-DIRECT (KlattGrid_extractPointProcess_glottalClosures)
-LOOP {
-	iam (KlattGrid);
-	praat_new (KlattGrid_extractPointProcess_glottalClosures (me), my name);
+DIRECT (NEW_KlattGrid_extractPointProcess_glottalClosures) {
+	CONVERT_EACH (KlattGrid)
+		autoPointProcess result = KlattGrid_extractPointProcess_glottalClosures (me);
+	CONVERT_EACH_END (my name)
 }
-END
 
-FORM (KlattGrid_formula_frequencies, U"KlattGrid: Formula (frequencies)", U"Formant: Formula (frequencies)...")
-	KlattGrid_6formants_addCommonField (dia);
+FORM (MODIFY_KlattGrid_formula_frequencies, U"KlattGrid: Formula (frequencies)", U"Formant: Formula (frequencies)...") {
+	KlattGrid_6formants_addCommonField (formantType)
 	LABEL (U"", U"row is formant number, col is point number: for row from 1 to nrow do for col from 1 to ncol do F (row, col) :=")
-	TEXTFIELD (U"formula", U"if row = 2 then self + 200 else self fi")
+	TEXTVAR (formula, U"formula", U"if row = 2 then self + 200 else self fi")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_formula_frequencies (me, formantType, GET_STRING (U"formula"), interpreter);
-		praat_dataChanged (me);
-	}
-END
-
-FORM (KlattGrid_formula_bandwidths, U"KlattGrid: Formula (bandwidths)", U"Formant: Formula (bandwidths)...")
-	KlattGrid_6formants_addCommonField (dia);
+	MODIFY_EACH (KlattGrid)
+		KlattGrid_formula_frequencies (me, formantType, formula, interpreter);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_KlattGrid_formula_bandwidths, U"KlattGrid: Formula (bandwidths)", U"Formant: Formula (bandwidths)...") {
+	KlattGrid_6formants_addCommonField (formantType)
 	LABEL (U"", U"row is formant number, col is point number: for row from 1 to nrow do for col from 1 to ncol do F (row, col) :=")
-	TEXTFIELD (U"formula", U"if row = 2 then self + 200 else self fi")
+	TEXTVAR (formula, U"formula", U"if row = 2 then self + 200 else self fi")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_formula_bandwidths (me, formantType, GET_STRING (U"formula"), interpreter);
-		praat_dataChanged (me);
-	}
-END
-
-#define KlattGrid_FORMANT_GET_FB_VALUE(Name,name,ForB,forb,FormB,formantType) \
-FORM (KlattGrid_get##Name##Formant##ForB##AtTime, U"KlattGrid: Get " #name " " #forb " at time", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
+	MODIFY_EACH (KlattGrid)
+		KlattGrid_formula_bandwidths (me, formantType, formula, interpreter);
+	MODIFY_EACH_END
+}
+
+#define KlattGrid_FORMANT_GET_FB_VALUE(Name,name,ForB,forb,FormB,formantType)  \
+FORM (REAL_KlattGrid_get##Name##Formant##ForB##AtTime, U"KlattGrid: Get " #name " " #forb " at time", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
 	OK \
 DO \
 	LOOP { iam (KlattGrid); \
-		Melder_informationReal (KlattGrid_get##FormB##AtTime (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time")), U" (Hz)"); \
+		Melder_informationReal (KlattGrid_get##FormB##AtTime (me, formantType, formantNumber, time), U" (Hz)"); \
 	} \
-END
+END }
 
-#define KlattGrid_FORMANT_GET_A_VALUE(Name,name,formantType) \
-FORM (KlattGrid_get##Name##FormantAmplitudeAtTime, U"KlattGrid: Get " #name " formant amplitude at time", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
+#define KlattGrid_FORMANT_GET_A_VALUE(Name,name,formantType)  \
+FORM (REAL_KlattGrid_get##Name##FormantAmplitudeAtTime, U"KlattGrid: Get " #name " formant amplitude at time", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
 	OK \
 DO \
 	LOOP { iam (KlattGrid); \
-	Melder_informationReal (KlattGrid_getAmplitudeAtTime (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time")), U" (dB)"); \
+	Melder_informationReal (KlattGrid_getAmplitudeAtTime (me, formantType, formantNumber, time), U" (dB)"); \
 	} \
-END
+END }
 
 #define KlattGrid_FORMANT_GET_FB_VALUES(Name,name,formantType) \
-KlattGrid_FORMANT_GET_FB_VALUE(Name,name,Frequency,frequency,Formant,formantType) \
-KlattGrid_FORMANT_GET_FB_VALUE(Name,name,Bandwidth,bandwidth,Bandwidth,formantType)
+KlattGrid_FORMANT_GET_FB_VALUE (Name, name, Frequency, frequency, Formant, formantType) \
+KlattGrid_FORMANT_GET_FB_VALUE (Name, name, Bandwidth, bandwidth, Bandwidth, formantType)
 
 KlattGrid_FORMANT_GET_FB_VALUES (Oral, oral, KlattGrid_ORAL_FORMANTS)
 KlattGrid_FORMANT_GET_A_VALUE (Oral, oral, KlattGrid_ORAL_FORMANTS)
@@ -595,22 +543,22 @@ KlattGrid_FORMANT_GET_A_VALUE (Frication, frication, KlattGrid_FRICATION_FORMANT
 #undef KlattGrid_FORMANT_GET_FB_VALUES
 #undef KlattGrid_FORMANT_GET_A_VALUE
 
-#define KlattGrid_EXTRACT_FORMANT_GRID(Name,gridType) \
-DIRECT (KlattGrid_extract##Name##FormantGrid) \
+#define KlattGrid_EXTRACT_FORMANT_GRID(Name,gridType)  \
+DIRECT (NEW_KlattGrid_extract##Name##FormantGrid) { \
 	LOOP { iam (KlattGrid); \
 		praat_new (KlattGrid_extractFormantGrid (me, gridType), formant_names[gridType]); \
 	} \
-END
+END }
 
-#define KlattGrid_EXTRACT_FORMANT_AMPLITUDE(Name,name,formantType) \
-FORM (KlattGrid_extract##Name##FormantAmplitudeTier, U"KlattGrid: Extract " #name " formant amplitude tier", nullptr) \
-	NATURAL (U"Formant number", U"1") \
+#define KlattGrid_EXTRACT_FORMANT_AMPLITUDE(Name,name,formantType)  \
+FORM (NEW_KlattGrid_extract##Name##FormantAmplitudeTier, U"KlattGrid: Extract " #name " formant amplitude tier", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
 	OK \
 DO \
 	LOOP { iam (KlattGrid); \
-		praat_new (KlattGrid_extractAmplitudeTier (me, formantType, GET_INTEGER (U"Formant number")), formant_names[formantType]); \
+		praat_new (KlattGrid_extractAmplitudeTier (me, formantType, formantNumber), formant_names[formantType]); \
 	} \
-END
+END }
 
 KlattGrid_EXTRACT_FORMANT_GRID (Oral, KlattGrid_ORAL_FORMANTS)
 KlattGrid_EXTRACT_FORMANT_AMPLITUDE (Oral, oral, KlattGrid_ORAL_FORMANTS)
@@ -626,24 +574,22 @@ KlattGrid_EXTRACT_FORMANT_GRID (Delta, KlattGrid_DELTA_FORMANTS)
 
 #undef KlattGrid_EXTRACT_FORMANTGRID
 
-#define KlattGrid_REPLACE_FORMANT_GRID(Name,formantType) \
-DIRECT (KlattGrid_replace##Name##FormantGrid) \
-	KlattGrid me = FIRST (KlattGrid); \
-	FormantGrid thee = FIRST (FormantGrid); \
-	KlattGrid_replaceFormantGrid (me, formantType, thee); \
-	praat_dataChanged (me); \
-END
-
-#define KlattGrid_REPLACE_FORMANT_AMPLITUDE(Name,name,formantType) \
-FORM (KlattGrid_replace##Name##FormantAmplitudeTier, U"KlattGrid: Replace " #name " formant amplitude tier", nullptr) \
-	NATURAL (U"Formant number", U"1") \
+#define KlattGrid_REPLACE_FORMANT_GRID(Name,formantType)  \
+DIRECT (MODIFY_KlattGrid_replace##Name##FormantGrid) { \
+	MODIFY_FIRST_OF_TWO (KlattGrid, FormantGrid); \
+		KlattGrid_replaceFormantGrid (me, formantType, you); \
+	MODIFY_FIRST_OF_TWO_END \
+}
+
+#define KlattGrid_REPLACE_FORMANT_AMPLITUDE(Name,name,formantType)  \
+FORM (MODIFY_KlattGrid_replace##Name##FormantAmplitudeTier, U"KlattGrid: Replace " #name " formant amplitude tier", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
 	OK \
 DO \
-	KlattGrid me = FIRST (KlattGrid); \
-	IntensityTier thee = FIRST (IntensityTier); \
-	KlattGrid_replaceAmplitudeTier (me, formantType, GET_INTEGER (U"Formant number"), thee); \
-	praat_dataChanged (me); \
-END
+	MODIFY_FIRST_OF_TWO (KlattGrid, IntensityTier); \
+		KlattGrid_replaceAmplitudeTier (me, formantType, formantNumber, you); \
+	MODIFY_FIRST_OF_TWO_END \
+}
 
 KlattGrid_REPLACE_FORMANT_GRID (Oral, KlattGrid_ORAL_FORMANTS)
 KlattGrid_REPLACE_FORMANT_AMPLITUDE (Oral, oral, KlattGrid_ORAL_FORMANTS)
@@ -660,307 +606,299 @@ KlattGrid_REPLACE_FORMANT_AMPLITUDE (Frication, frication, KlattGrid_FRICATION_F
 #undef KlattGrid_REPLACE_FORMANT_AMPLITUDE
 #undef KlattGrid_REPLACE_FORMANTGRID
 
-#define KlattGrid_FORMANT_GET_ADD_REMOVE(Name,name,unit,default,require,requiremessage) \
-FORM (KlattGrid_get##Name##AtTime, U"KlattGrid: Get " #name " at time", nullptr) \
-	KlattGrid_6formants_addCommonField (dia); \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
+#define KlattGrid_FORMANT_GET_ADD_REMOVE(Name,name,unit,default,require,requiremessage)  \
+FORM (REAL_KlattGrid_get##Name##AtTime, U"KlattGrid: Get " #name " at time", nullptr) { \
+	KlattGrid_6formants_addCommonField (formantType) \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
 	OK \
 DO \
-	int formantType = GET_INTEGER (U"Formant type"); \
 	LOOP { iam (KlattGrid); \
-		Melder_informationReal (KlattGrid_get##Name##AtTime (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time")), U" (Hz)"); \
+		Melder_informationReal (KlattGrid_get##Name##AtTime (me, formantType, formantNumber, time), U" (Hz)"); \
 	} \
-END \
-FORM (KlattGrid_getDelta##Name##AtTime, U"KlattGrid: Get delta " #name " at time", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
+END } \
+FORM (REAL_KlattGrid_getDelta##Name##AtTime, U"KlattGrid: Get delta " #name " at time", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
 	OK \
 DO \
 	LOOP { iam (KlattGrid); \
-		Melder_informationReal (KlattGrid_getDelta##Name##AtTime (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time")), U" (Hz)"); \
+		Melder_informationReal (KlattGrid_getDelta##Name##AtTime (me, formantNumber, time), U" (Hz)"); \
 	} \
-END \
-FORM (KlattGrid_add##Name##Point, U"KlattGrid: Add " #name " point", nullptr) \
-	KlattGrid_6formants_addCommonField (dia); \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
-	REAL (U"Value" unit, default) \
+END } \
+FORM (MODIFY_KlattGrid_add##Name##Point, U"KlattGrid: Add " #name " point", nullptr) { \
+	KlattGrid_6formants_addCommonField (formantType) \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
+	REALVAR (value, U"Value" unit, default) \
 	OK \
 DO \
-	int formantType = GET_INTEGER (U"Formant type"); \
-	double value = GET_REAL (U"Value"); \
 	REQUIRE (require, requiremessage) \
 	LOOP { iam (KlattGrid); \
-		KlattGrid_add##Name##Point (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), value); \
+		KlattGrid_add##Name##Point (me, formantType, formantNumber, time, value); \
 		praat_dataChanged (me); \
 	} \
-END \
-FORM (KlattGrid_addDelta##Name##Point, U"KlattGrid: Add delta " #name " point", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"Time (s)", U"0.5") \
-	REAL (U"Value" unit, default) \
+END } \
+FORM (MODIFY_KlattGrid_addDelta##Name##Point, U"KlattGrid: Add delta " #name " point", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (time, U"Time (s)", U"0.5") \
+	REALVAR (value, U"Value" unit, default) \
 	OK \
 DO \
-	double value = GET_REAL (U"Value"); \
 	REQUIRE (require, requiremessage) \
 	LOOP { iam (KlattGrid); \
-		KlattGrid_addDelta##Name##Point (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), value); \
+		KlattGrid_addDelta##Name##Point (me, formantNumber, time, value); \
 		praat_dataChanged (me); \
 	} \
-END \
-FORM (KlattGrid_remove##Name##Points, U"Remove " #name " points", nullptr) \
-	KlattGrid_6formants_addCommonField (dia); \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"From time (s)", U"0.3")\
-	REAL (U"To time (s)", U"0.7") \
+END } \
+FORM (MODIFY_KlattGrid_remove##Name##Points, U"Remove " #name " points", nullptr) { \
+	KlattGrid_6formants_addCommonField (formantType) \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (fromTime, U"From time (s)", U"0.3")\
+	REALVAR (toTime, U"To time (s)", U"0.7") \
 	OK \
 DO \
-	int formantType = GET_INTEGER (U"Formant type"); \
 	LOOP { iam (KlattGrid); \
-		KlattGrid_remove##Name##Points (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"From time"), GET_REAL (U"To time")); \
+		KlattGrid_remove##Name##Points (me, formantType, formantNumber, fromTime, toTime); \
 		praat_dataChanged (me);\
 	} \
-END \
-FORM (KlattGrid_removeDelta##Name##Points, U"Remove delta " #name " points", nullptr) \
-	NATURAL (U"Formant number", U"1") \
-	REAL (U"From time (s)", U"0.3")\
-	REAL (U"To time (s)", U"0.7") \
+END } \
+FORM (MODIFY_KlattGrid_removeDelta##Name##Points, U"Remove delta " #name " points", nullptr) { \
+	NATURALVAR (formantNumber, U"Formant number", U"1") \
+	REALVAR (fromTime, U"From time (s)", U"0.3")\
+	REALVAR (toTime, U"To time (s)", U"0.7") \
 	OK \
 DO \
 	LOOP { iam (KlattGrid); \
-		KlattGrid_removeDelta##Name##Points (me, GET_INTEGER (U"Formant number"), GET_REAL (U"From time"), GET_REAL (U"To time")); \
+		KlattGrid_removeDelta##Name##Points (me, formantNumber, fromTime, toTime); \
 		praat_dataChanged (me);\
 	} \
-END
+END }
 
 KlattGrid_FORMANT_GET_ADD_REMOVE (Formant, formant, U" (Hz)", U"500.0", (value > 0), U"Frequency must be greater than zero.")
 KlattGrid_FORMANT_GET_ADD_REMOVE (Bandwidth, bandwidth, U" (Hz)", U"50.0", (value > 0), U"Bandwidth must be greater than zero.")
 
 #undef KlattGrid_FORMANT_GET_ADD_REMOVE
 
-FORM (KlattGrid_addFormantAndBandwidthTier, U"", nullptr)
-	KlattGrid_7formants_addCommonField (dia);
+FORM (MODIFY_KlattGrid_addFormantAndBandwidthTier, U"", nullptr) {
+	KlattGrid_7formants_addCommonField (formantType)
 	INTEGER (U"Position", U"0 (= at end)")
 	OK
 DO
-	long gridType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_addFormantFrequencyAndBandwidthTiers (me, gridType, GET_INTEGER (U"Position"));
-		praat_dataChanged (me);
-	}
-END
-
-FORM (KlattGrid_extractFormantGrid, U"KlattGrid: Extract formant grid", nullptr)
-	KlattGrid_6formants_addCommonField (dia);
+	MODIFY_EACH (KlattGrid)
+		KlattGrid_addFormantFrequencyAndBandwidthTiers (me, formantType, GET_INTEGER (U"Position"));
+	MODIFY_EACH_END
+}
+
+FORM (NEW_KlattGrid_extractFormantGrid, U"KlattGrid: Extract formant grid", nullptr) {
+	KlattGrid_6formants_addCommonField (formantType)
 	OK
 DO
-	long gridType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		praat_new (KlattGrid_extractFormantGrid (me, gridType), formant_names[gridType]);
-	}
-END
-
-FORM (KlattGrid_replaceFormantGrid, U"KlattGrid: Replace formant grid", nullptr)
-	KlattGrid_6formants_addCommonField (dia);
+	CONVERT_EACH (KlattGrid)
+		autoFormantGrid result = KlattGrid_extractFormantGrid (me, formantType);
+	CONVERT_EACH_END (formant_names[formantType])
+}
+
+FORM (MODIFY_KlattGrid_replaceFormantGrid, U"KlattGrid: Replace formant grid", nullptr) {
+	KlattGrid_6formants_addCommonField (formantType)
 	OK
 DO
-	KlattGrid me = FIRST (KlattGrid);
-	FormantGrid thee = FIRST (FormantGrid);
-	KlattGrid_replaceFormantGrid (me, GET_INTEGER (U"Formant type"), thee);
-	praat_dataChanged (OBJECT);
-END
-
-FORM (KlattGrid_getAmplitudeAtTime, U"KlattGrid: Get amplitude at time", nullptr)
-	KlattGrid_4formants_addCommonField (dia);
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
+	MODIFY_FIRST_OF_TWO (KlattGrid, FormantGrid)
+		KlattGrid_replaceFormantGrid (me, formantType, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+FORM (REAL_KlattGrid_getAmplitudeAtTime, U"KlattGrid: Get amplitude at time", nullptr) {
+	KlattGrid_4formants_addCommonField (formantType)
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	REALVAR (time, U"Time (s)", U"0.5")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		Melder_informationReal (KlattGrid_getAmplitudeAtTime (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time")), U" (dB)");
-	}
-END
-
-FORM (KlattGrid_addAmplitudePoint, U"KlattGrid: Add amplitude point", nullptr)
-	KlattGrid_4formants_addCommonField (dia);
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	REAL (U"Value (Hz)", U"80.0")
+	NUMBER_ONE (KlattGrid)
+		double result = KlattGrid_getAmplitudeAtTime (me, formantType, formantNumber, time);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (MODIFY_KlattGrid_addAmplitudePoint, U"KlattGrid: Add amplitude point", nullptr) {
+	KlattGrid_4formants_addCommonField (formantType)
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	REALVAR (time, U"Time (s)", U"0.5")
+	REALVAR (value_hz, U"Value (Hz)", U"80.0")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	double value = GET_REAL (U"Value");
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_addAmplitudePoint (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), value);
-		praat_dataChanged (me);
-	}
-END
-
-FORM (KlattGrid_removeAmplitudePoints, U"Remove amplitude points", nullptr)
-	KlattGrid_4formants_addCommonField (dia);
-	NATURAL (U"Formant number", U"1")
-	REAL (U"From time (s)", U"0.3")
-	REAL (U"To time (s)", U"0.7")
+	MODIFY_EACH (KlattGrid)
+		KlattGrid_addAmplitudePoint (me, formantType, formantNumber, time, value_hz);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_KlattGrid_removeAmplitudePoints, U"Remove amplitude points", nullptr) {
+	KlattGrid_4formants_addCommonField (formantType)
+	NATURALVAR (formantNumber, U"Formant number", U"1")
+	REALVAR (fromTime, U"From time (s)", U"0.3")
+	REALVAR (toTime, U"To time (s)", U"0.7")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_removeAmplitudePoints (me, formantType, GET_INTEGER (U"Formant number"), GET_REAL (U"From time"), GET_REAL (U"To time"));
-		praat_dataChanged (me);
-	}
-END
-
-FORM (KlattGrid_extractAmplitudeTier, U"", nullptr)
-	KlattGrid_4formants_addCommonField (dia);
-	NATURAL (U"Formant number", U"1")
+	MODIFY_EACH (KlattGrid);
+		KlattGrid_removeAmplitudePoints (me, formantType, formantNumber, fromTime, toTime);
+	MODIFY_EACH_END
+}
+
+FORM (NEW_KlattGrid_extractAmplitudeTier, U"", nullptr) {
+	KlattGrid_4formants_addCommonField (formantType)
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	LOOP {
-		iam (KlattGrid);
-		praat_new (KlattGrid_extractAmplitudeTier (me, formantType, GET_INTEGER (U"Formant number")), formant_names[formantType]);
-	}
-END
-
-FORM (KlattGrid_replaceAmplitudeTier, U"KlattGrid: Replace amplitude tier", nullptr)
-	KlattGrid_4formants_addCommonField (dia);
-	NATURAL (U"Formant number", U"1")
+	CONVERT_EACH (KlattGrid)
+		autoIntensityTier result = KlattGrid_extractAmplitudeTier (me, formantType, formantNumber);
+	CONVERT_EACH_END (formant_names[formantType])
+}
+
+FORM (MODIFY_KlattGrid_replaceAmplitudeTier, U"KlattGrid: Replace amplitude tier", nullptr) {
+	KlattGrid_4formants_addCommonField (formantType)
+	NATURALVAR (formantNumber, U"Formant number", U"1")
 	OK
 DO
-	int formantType = GET_INTEGER (U"Formant type");
-	KlattGrid me = FIRST (KlattGrid);
-	IntensityTier thee = FIRST (IntensityTier);
-	KlattGrid_replaceAmplitudeTier (me, formantType, GET_INTEGER (U"Formant number"), thee);
-	praat_dataChanged (me);
-END
-
-FORM (KlattGrid_to_Sound_special, U"KlattGrid: To Sound (special)", U"KlattGrid: To Sound (special)...")
-	KlattGrid_PlayOptions_addCommonFields (dia, true);
+	MODIFY_FIRST_OF_TWO (KlattGrid, IntensityTier)
+		KlattGrid_replaceAmplitudeTier (me, formantType, formantNumber, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+FORM (NEW_KlattGrid_to_Sound_special, U"KlattGrid: To Sound (special)", U"KlattGrid: To Sound (special)...") {
+	REALVAR (fromTime, U"left Time range (s)", U"0")
+	REALVAR (toTime, U"right Time range (s)", U"0")
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	BOOLEANVAR (scalePeak, U"Scale peak", true)
+	KlattGrid_PhonationGridPlayOptions_addCommonFields (useVoicing, useFlutter, useDoublePulsing, useCollisionPhase, useSpectralTilt, flowFunctionType, useFlowDerivative, useAspiration, useBreathiness)
+	KlattGrid_formantSelection_vocalTract_commonFields (filtersStructure, fromOralFormant, toOralFormant, fromNasalFormant, toNasalFormant, fromNasalAntiFormant, toNasalAntiFormant)
+	KlattGrid_formantSelection_coupling_commonFields (fromTrachealFormant, toTrachealFormant, fromTrachealAntiFormant, toTrachealAntiFormant, fromDeltaFormant, toDeltaFormant, fromDeltaBandwidth, toDeltaBandwidth)
+	KlattGrid_formantSelection_frication_commonFields(fromFricationFormant,toFricationFormant,useFricationBypass)
 	OK
 DO
-	LOOP {
-		iam (KlattGrid);
+	CONVERT_EACH (KlattGrid)
 		KlattGrid_setDefaultPlayOptions (me);
-		KlattGrid_PlayOptions_getCommonFields (dia, true, me);
-		praat_new (KlattGrid_to_Sound (me), my name);
-	}
-END
-
-DIRECT (KlattGrid_to_Sound)
-	LOOP {
-		iam (KlattGrid);
+		KlattGridPlayOptions pk = my options.get();
+		pk -> scalePeak = scalePeak;
+		pk -> xmin = fromTime;
+		pk -> xmax = toTime;
+		pk -> samplingFrequency = samplingFrequency;
+		pk -> scalePeak = scalePeak;
+		KlattGrid_PhonationGridPlayOptions (me, useVoicing, useFlutter, useDoublePulsing, useCollisionPhase, useSpectralTilt, flowFunctionType, useFlowDerivative, useAspiration, useBreathiness);
+		KlattGrid_formantSelection_vocalTract (me, filtersStructure, fromOralFormant, toOralFormant, fromNasalFormant, toNasalFormant, fromNasalAntiFormant, toNasalAntiFormant);
+		KlattGrid_formantSelection_coupling (me, fromTrachealFormant, toTrachealFormant, fromTrachealAntiFormant, toTrachealAntiFormant, fromDeltaFormant, toDeltaFormant, fromDeltaBandwidth, toDeltaBandwidth);
+		KlattGrid_formantSelection_frication (me, fromFricationFormant, toFricationFormant, useFricationBypass);
+		autoSound result = KlattGrid_to_Sound (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_KlattGrid_to_Sound) {
+	CONVERT_EACH (KlattGrid)
 		KlattGrid_setDefaultPlayOptions (me);
-		praat_new (KlattGrid_to_Sound (me), my name);
-	}
-END
+		autoSound result = KlattGrid_to_Sound (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (KlattGrid_playSpecial, U"KlattGrid: Play special", U"KlattGrid: Play special...")
-	KlattGrid_PlayOptions_addCommonFields (dia, false);
+FORM (PLAY_KlattGrid_playSpecial, U"KlattGrid: Play special", U"KlattGrid: Play special...") {
+	REALVAR (fromTime, U"left Time range (s)", U"0")
+	REALVAR (toTime, U"right Time range (s)", U"0")
+	BOOLEANVAR (scalePeak, U"Scale peak", true)
+	KlattGrid_PhonationGridPlayOptions_addCommonFields (useVoicing, useFlutter, useDoublePulsing, useCollisionPhase, useSpectralTilt, flowFunctionType, useFlowDerivative, useAspiration, useBreathiness)
+	KlattGrid_formantSelection_vocalTract_commonFields (filtersStructure, fromOralFormant, toOralFormant, fromNasalFormant, toNasalFormant, fromNasalAntiFormant, toNasalAntiFormant);
+	KlattGrid_formantSelection_coupling_commonFields (fromTrachealFormant, toTrachealFormant, fromTrachealAntiFormant, toTrachealAntiFormant, fromDeltaFormant, toDeltaFormant, fromDeltaBandwidth, toDeltaBandwidth)
+	KlattGrid_formantSelection_frication_commonFields(fromFricationFormant,toFricationFormant,useFricationBypass)
 	OK
 DO
-	LOOP {
-		iam (KlattGrid);
+	PLAY_EACH (KlattGrid)
 		KlattGrid_setDefaultPlayOptions (me);
-		KlattGrid_PlayOptions_getCommonFields (dia, false, me);
+		KlattGridPlayOptions pk = my options.get();
+		pk -> scalePeak = scalePeak;
+		pk -> xmin = fromTime;
+		pk -> xmax = toTime;
+		pk -> scalePeak = scalePeak;
+		KlattGrid_PhonationGridPlayOptions (me, useVoicing, useFlutter, useDoublePulsing, useCollisionPhase, useSpectralTilt, flowFunctionType, useFlowDerivative, useAspiration, useBreathiness);
+		KlattGrid_formantSelection_vocalTract (me, filtersStructure, fromOralFormant, toOralFormant, fromNasalFormant, toNasalFormant, fromNasalAntiFormant, toNasalAntiFormant);
+		KlattGrid_formantSelection_coupling (me, fromTrachealFormant, toTrachealFormant, fromTrachealAntiFormant, toTrachealAntiFormant, fromDeltaFormant, toDeltaFormant, fromDeltaBandwidth, toDeltaBandwidth);
+		KlattGrid_formantSelection_frication (me, fromFricationFormant, toFricationFormant, useFricationBypass);
 		KlattGrid_playSpecial (me);
-	}
-END
+	PLAY_EACH_END
+}
 
-FORM (KlattGrid_to_Sound_phonation, U"KlattGrid: To Sound (phonation)", U"KlattGrid: To Sound (phonation)...")
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	KlattGrid_PhonationGridPlayOptions_addCommonFields (dia);
+FORM (NEW_KlattGrid_to_Sound_phonation, U"KlattGrid: To Sound (phonation)", U"KlattGrid: To Sound (phonation)...") {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	KlattGrid_PhonationGridPlayOptions_addCommonFields (useVoicing, useFlutter, useDoublePulsing, useCollisionPhase, useSpectralTilt, flowFunctionType, useFlowDerivative, useAspiration, useBreathiness)
 	OK
 DO
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_PhonationGridPlayOptions_getCommonFields (dia, me);
-		my options -> samplingFrequency = GET_REAL (U"Sampling frequency");
-		praat_new (KlattGrid_to_Sound_phonation (me), my name, U"_phonation");
-	}
-END
-
-DIRECT (KlattGrid_help) Melder_help (U"KlattGrid"); END
-
-DIRECT (KlattGrid_play)
-	LOOP {
-		iam (KlattGrid);
+	CONVERT_EACH (KlattGrid)
+		KlattGrid_PhonationGridPlayOptions (me, useVoicing, useFlutter, useDoublePulsing, useCollisionPhase, useSpectralTilt, flowFunctionType, useFlowDerivative, useAspiration, useBreathiness);
+		my options -> samplingFrequency = samplingFrequency;
+		autoSound result = KlattGrid_to_Sound_phonation (me);
+	CONVERT_EACH_END (my name, U"_phonation") 
+}
+
+DIRECT (HELP_KlattGrid_help)  {
+	HELP (U"KlattGrid")
+}
+
+DIRECT (PLAY_KlattGrid_play) {
+	PLAY_EACH (KlattGrid)
 		KlattGrid_play (me);
-	}
-END
+	PLAY_EACH_END
+}
 
-FORM (KlattGrid_draw, U"KlattGrid: Draw", nullptr)
-	RADIO (U"Synthesis model", 1)
+FORM (GRAPHICS_KlattGrid_draw, U"KlattGrid: Draw", nullptr) {
+	RADIOVAR (filtersStructure, U"Synthesis filters structure", 1)
 		RADIOBUTTON (U"Cascade")
 		RADIOBUTTON (U"Parallel")
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_draw (me, GRAPHICS, GET_INTEGER (U"Synthesis model") - 1);
-	}
-END
-
-FORM (KlattGrid_drawVocalTract, U"KlattGrid: Draw vocal tract", nullptr)
-	RADIO (U"Synthesis model", 1)
+	GRAPHICS_EACH (KlattGrid)
+		KlattGrid_draw (me, GRAPHICS, filtersStructure - 1);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_KlattGrid_drawVocalTract, U"KlattGrid: Draw vocal tract", nullptr) {
+	RADIOVAR (filtersStructure, U"Synthesis filters structure", 1)
 		RADIOBUTTON (U"Cascade")
 		RADIOBUTTON (U"Parallel")
-	BOOLEAN (U"Include tracheal formants", true);
+	BOOLEANVAR (includeTrachealFormants, U"Include tracheal formants", true);
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (KlattGrid);
-		KlattGrid_drawVocalTract (me, GRAPHICS, GET_INTEGER (U"Synthesis model") - 1, GET_INTEGER (U"Include tracheal formants"));
-	}
-END
-
-DIRECT (KlattGrid_drawPhonation)
-	autoPraatPicture picture;
-	LOOP {
-		iam (KlattGrid);
+	GRAPHICS_EACH (KlattGrid)
+		KlattGrid_drawVocalTract (me, GRAPHICS, filtersStructure - 1, includeTrachealFormants);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (GRAPHICS_KlattGrid_drawPhonation) {
+	GRAPHICS_EACH (KlattGrid)
 		PhonationGrid_draw (my phonation.get(), GRAPHICS);
-	}
-END
+	GRAPHICS_EACH_END
+}
 
-DIRECT (KlattGrid_drawFrication)
-	autoPraatPicture picture;
-	LOOP {
-		iam (KlattGrid);
+DIRECT (GRAPHICS_KlattGrid_drawFrication) {
+	GRAPHICS_EACH (KlattGrid)
 		FricationGrid_draw (my frication.get(), GRAPHICS);
-	}
-END
+	GRAPHICS_EACH_END
+}
 
-FORM (KlattGrid_to_oralFormantGrid_openPhases, U"KlattGrid: Extract oral formant grid (open phases)", U"KlattGrid: Extract oral formant grid (open phases)...")
-	REAL (U"Fade fraction (0..0.5)", U"0.1")
+FORM (NEW_KlattGrid_to_oralFormantGrid_openPhases, U"KlattGrid: Extract oral formant grid (open phases)", U"KlattGrid: Extract oral formant grid (open phases)...") {
+	REALVAR (fadeFraction, U"Fade fraction (0..0.5)", U"0.1")
 	OK
 DO
-	double fadeFraction = GET_REAL (U"Fade fraction");
 	REQUIRE (fadeFraction < 0.5, U"Fade fraction has to be smaller than 0.5.")
-	LOOP {
-		iam (KlattGrid);
-		praat_new (KlattGrid_to_oralFormantGrid_openPhases (me, fadeFraction), U"corrected");
-	}
-END
-
-FORM (Sound_KlattGrid_filterByVocalTract, U"Sound & KlattGrid: Filter by vocal tract", U"Sound & KlattGrid: Filter by vocal tract...")
-	RADIO (U"Vocal tract filter model", 1)
+	CONVERT_EACH (KlattGrid)
+		autoFormantGrid result = KlattGrid_to_oralFormantGrid_openPhases (me, fadeFraction);
+	CONVERT_EACH_END (U"corrected")
+}
+
+FORM (NEW_Sound_KlattGrid_filterByVocalTract, U"Sound & KlattGrid: Filter by vocal tract", U"Sound & KlattGrid: Filter by vocal tract...") {
+	RADIOVAR (filtersStructure, U"Vocal tract filter model", 1)
 		RADIOBUTTON (U"Cascade")
 		RADIOBUTTON (U"Parallel")
 	OK
 DO
-	Sound me = FIRST (Sound);
-	KlattGrid thee = FIRST (KlattGrid);
-	int filterModel = GET_INTEGER (U"Vocal tract filter model") - 1;
-	praat_new (Sound_KlattGrid_filterByVocalTract (me, thee, filterModel), my name, U"_", thy name);
-END
+	CONVERT_TWO (Sound, KlattGrid)
+		autoSound result = Sound_KlattGrid_filterByVocalTract (me, you, filtersStructure);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
 void praat_KlattGrid_init ();
 void praat_KlattGrid_init () {
@@ -968,10 +906,10 @@ void praat_KlattGrid_init () {
 	Thing_recognizeClassesByName (classKlattGrid, nullptr);
 
 	praat_addMenuCommand (U"Objects", U"New", U"Acoustic synthesis (Klatt)", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"KlattGrid help", nullptr, 1, DO_KlattGrid_help);
+	praat_addMenuCommand (U"Objects", U"New", U"KlattGrid help", nullptr, praat_DEPTH_1 | praat_NO_API, HELP_KlattGrid_help);
 	praat_addMenuCommand (U"Objects", U"New", U"-- the synthesizer grid --", nullptr, 1, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create KlattGrid...", nullptr, 1, DO_KlattGrid_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create KlattGrid example", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_createExample);
+	praat_addMenuCommand (U"Objects", U"New", U"Create KlattGrid...", nullptr, 1, NEW1_KlattGrid_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create KlattGrid example", nullptr, praat_DEPTH_1 + praat_HIDDEN, NEW1_KlattGrid_createExample);
 
 	/*
 	Edit oral/nasal/tracheal/frication/delta formant grid
@@ -1009,76 +947,76 @@ void praat_KlattGrid_init () {
 	#define KlattGrid_TRACHEAL_ANTIFORMANTS 6
 	#define KlattGrid_DELTA_FORMANTS 7
 	*/
-	praat_addAction1 (classKlattGrid, 0, U"KlattGrid help", nullptr, 0, DO_KlattGrid_help);
+	praat_addAction1 (classKlattGrid, 0, U"KlattGrid help", nullptr, 0, HELP_KlattGrid_help);
 	praat_addAction1 (classKlattGrid, 0, U"Edit phonation -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Edit pitch tier", nullptr, 1, DO_KlattGrid_editPitchTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit voicing amplitude tier", nullptr, 1, DO_KlattGrid_editVoicingAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit flutter tier", nullptr, 1, DO_KlattGrid_editFlutterTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit power1 tier", nullptr, 1, DO_KlattGrid_editPower1Tier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit power2 tier", nullptr, 1, DO_KlattGrid_editPower2Tier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit open phase tier", nullptr, 1, DO_KlattGrid_editOpenPhaseTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit collision phase tier", nullptr, 1, DO_KlattGrid_editCollisionPhaseTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit double pulsing tier", nullptr, 1, DO_KlattGrid_editDoublePulsingTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit spectral tilt tier", nullptr, 1, DO_KlattGrid_editSpectralTiltTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit aspiration amplitude tier", nullptr, 1, DO_KlattGrid_editAspirationAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit breathiness amplitude tier", nullptr, 1, DO_KlattGrid_editBreathinessAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit pitch tier", nullptr, 1, WINDOW_KlattGrid_editPitchTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit voicing amplitude tier", nullptr, 1, WINDOW_KlattGrid_editVoicingAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit flutter tier", nullptr, 1, WINDOW_KlattGrid_editFlutterTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit power1 tier", nullptr, 1, WINDOW_KlattGrid_editPower1Tier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit power2 tier", nullptr, 1, WINDOW_KlattGrid_editPower2Tier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit open phase tier", nullptr, 1, WINDOW_KlattGrid_editOpenPhaseTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit collision phase tier", nullptr, 1, WINDOW_KlattGrid_editCollisionPhaseTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit double pulsing tier", nullptr, 1, WINDOW_KlattGrid_editDoublePulsingTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit spectral tilt tier", nullptr, 1, WINDOW_KlattGrid_editSpectralTiltTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit aspiration amplitude tier", nullptr, 1, WINDOW_KlattGrid_editAspirationAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit breathiness amplitude tier", nullptr, 1, WINDOW_KlattGrid_editBreathinessAmplitudeTier);
 
 	praat_addAction1 (classKlattGrid, 0, U"Edit filters -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Edit oral formant grid", nullptr, 1, DO_KlattGrid_editOralFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit nasal formant grid", nullptr, 1, DO_KlattGrid_editNasalFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit nasal antiformant grid", nullptr, 1, DO_KlattGrid_editNasalAntiFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit oral formant amplitude tier...", nullptr, 1, DO_KlattGrid_editOralFormantAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit nasal formant amplitude tier...", nullptr, 1, DO_KlattGrid_editNasalFormantAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit oral formant grid", nullptr, 1, WINDOW_KlattGrid_editOralFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit nasal formant grid", nullptr, 1, WINDOW_KlattGrid_editNasalFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit nasal antiformant grid", nullptr, 1, WINDOW_KlattGrid_editNasalAntiFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit oral formant amplitude tier...", nullptr, 1, WINDOW_KlattGrid_editOralFormantAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit nasal formant amplitude tier...", nullptr, 1, WINDOW_KlattGrid_editNasalFormantAmplitudeTier);
 	praat_addAction1 (classKlattGrid, 0, U"-- edit delta formant grid --", nullptr, 1, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Edit delta formant grid", nullptr, 1, DO_KlattGrid_editDeltaFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit tracheal formant grid", nullptr, 1, DO_KlattGrid_editTrachealFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit tracheal antiformant grid", nullptr, 1, DO_KlattGrid_editTrachealAntiFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit tracheal formant amplitude tier...", nullptr, 1, DO_KlattGrid_editTrachealFormantAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit delta formant grid", nullptr, 1, WINDOW_KlattGrid_editDeltaFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit tracheal formant grid", nullptr, 1, WINDOW_KlattGrid_editTrachealFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit tracheal antiformant grid", nullptr, 1, WINDOW_KlattGrid_editTrachealAntiFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit tracheal formant amplitude tier...", nullptr, 1, WINDOW_KlattGrid_editTrachealFormantAmplitudeTier);
 	praat_addAction1 (classKlattGrid, 0, U"-- edit frication tiers --", nullptr, 1, nullptr);
-	praat_addAction1 (classKlattGrid, 1, U"Edit frication amplitude tier", nullptr, 1, DO_KlattGrid_editFricationAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit frication formant grid", nullptr, 1, DO_KlattGrid_editFricationFormantGrid);
-	praat_addAction1 (classKlattGrid, 0, U"Edit frication formant amplitude tier...", nullptr, 1, DO_KlattGrid_editFricationFormantAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Edit frication bypass tier", nullptr, 1, DO_KlattGrid_editFricationBypassTier);
-	praat_addAction1 (classKlattGrid, 1, U"Edit frication amplitude tier", nullptr, 1, DO_KlattGrid_editFricationAmplitudeTier);
-
-	praat_addAction1 (classKlattGrid, 0, U"Play", nullptr, 0, DO_KlattGrid_play);
-	praat_addAction1 (classKlattGrid, 0, U"Play special...", nullptr, 0, DO_KlattGrid_playSpecial);
-	praat_addAction1 (classKlattGrid, 0, U"To Sound", nullptr, 0, DO_KlattGrid_to_Sound);
-	praat_addAction1 (classKlattGrid, 0, U"To Sound (special)...", nullptr, 0, DO_KlattGrid_to_Sound_special);
-	praat_addAction1 (classKlattGrid, 0, U"To Sound (phonation)...", nullptr, 0, DO_KlattGrid_to_Sound_phonation);
+	praat_addAction1 (classKlattGrid, 1, U"Edit frication amplitude tier", nullptr, 1, WINDOW_KlattGrid_editFricationAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit frication formant grid", nullptr, 1, WINDOW_KlattGrid_editFricationFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Edit frication formant amplitude tier...", nullptr, 1, WINDOW_KlattGrid_editFricationFormantAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Edit frication bypass tier", nullptr, 1, WINDOW_KlattGrid_editFricationBypassTier);
+	praat_addAction1 (classKlattGrid, 1, U"Edit frication amplitude tier", nullptr, 1, WINDOW_KlattGrid_editFricationAmplitudeTier);
+
+	praat_addAction1 (classKlattGrid, 0, U"Play", nullptr, 0, PLAY_KlattGrid_play);
+	praat_addAction1 (classKlattGrid, 0, U"Play special...", nullptr, 0, PLAY_KlattGrid_playSpecial);
+	praat_addAction1 (classKlattGrid, 0, U"To Sound", nullptr, 0, NEW_KlattGrid_to_Sound);
+	praat_addAction1 (classKlattGrid, 0, U"To Sound (special)...", nullptr, 0, NEW_KlattGrid_to_Sound_special);
+	praat_addAction1 (classKlattGrid, 0, U"To Sound (phonation)...", nullptr, 0, NEW_KlattGrid_to_Sound_phonation);
 
 	praat_addAction1 (classKlattGrid, 0, U"Draw -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Draw synthesizer...", nullptr, 1, DO_KlattGrid_draw);
-	praat_addAction1 (classKlattGrid, 0, U"Draw vocal tract...", nullptr, 1, DO_KlattGrid_drawVocalTract);
-	praat_addAction1 (classKlattGrid, 0, U"Draw phonation", nullptr, 1, DO_KlattGrid_drawPhonation);
-	praat_addAction1 (classKlattGrid, 0, U"Draw frication", nullptr, 1, DO_KlattGrid_drawFrication);
+	praat_addAction1 (classKlattGrid, 0, U"Draw synthesizer...", nullptr, 1, GRAPHICS_KlattGrid_draw);
+	praat_addAction1 (classKlattGrid, 0, U"Draw vocal tract...", nullptr, 1, GRAPHICS_KlattGrid_drawVocalTract);
+	praat_addAction1 (classKlattGrid, 0, U"Draw phonation", nullptr, 1, GRAPHICS_KlattGrid_drawPhonation);
+	praat_addAction1 (classKlattGrid, 0, U"Draw frication", nullptr, 1, GRAPHICS_KlattGrid_drawFrication);
 
 	praat_addAction1 (classKlattGrid, 0, U"Query phonation -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 1, U"Get pitch at time...", nullptr, 1, DO_KlattGrid_getPitchAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get voicing amplitude at time...", nullptr, 1, DO_KlattGrid_getVoicingAmplitudeAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get flutter at time...", nullptr, 1, DO_KlattGrid_getFlutterAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get power1 at time...", nullptr, 1, DO_KlattGrid_getPower1AtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get power2 at time...", nullptr, 1, DO_KlattGrid_getPower2AtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get open phase at time...", nullptr, 1, DO_KlattGrid_getOpenPhaseAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get collision phase at time...", nullptr, 1, DO_KlattGrid_getCollisionPhaseAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get double pulsing at time...", nullptr, 1, DO_KlattGrid_getDoublePulsingAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get spectral tilt at time...", nullptr, 1, DO_KlattGrid_getSpectralTiltAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get aspiration amplitude at time...", nullptr, 1, DO_KlattGrid_getAspirationAmplitudeAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get breathiness amplitude at time...", nullptr, 1, DO_KlattGrid_getBreathinessAmplitudeAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get pitch at time...", nullptr, 1, REAL_KlattGrid_getPitchAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get voicing amplitude at time...", nullptr, 1, REAL_KlattGrid_getVoicingAmplitudeAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get flutter at time...", nullptr, 1, REAL_KlattGrid_getFlutterAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get power1 at time...", nullptr, 1, REAL_KlattGrid_getPower1AtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get power2 at time...", nullptr, 1, REAL_KlattGrid_getPower2AtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get open phase at time...", nullptr, 1, REAL_KlattGrid_getOpenPhaseAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get collision phase at time...", nullptr, 1, REAL_KlattGrid_getCollisionPhaseAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get double pulsing at time...", nullptr, 1, REAL_KlattGrid_getDoublePulsingAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get spectral tilt at time...", nullptr, 1, REAL_KlattGrid_getSpectralTiltAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get aspiration amplitude at time...", nullptr, 1, REAL_KlattGrid_getAspirationAmplitudeAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get breathiness amplitude at time...", nullptr, 1, REAL_KlattGrid_getBreathinessAmplitudeAtTime);
 
 	praat_addAction1 (classKlattGrid, 0, U"Query filters -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 1, U"Get formant at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_getFormantAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get bandwidth at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_getBandwidthAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get amplitude at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_getAmplitudeAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get delta formant at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_getDeltaFormantAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get delta bandwidth at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_getDeltaBandwidthAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get formant at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, REAL_KlattGrid_getFormantAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get bandwidth at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, REAL_KlattGrid_getBandwidthAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get amplitude at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, REAL_KlattGrid_getAmplitudeAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get delta formant at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, REAL_KlattGrid_getDeltaFormantAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get delta bandwidth at time...", nullptr, praat_DEPTH_1 + praat_HIDDEN, REAL_KlattGrid_getDeltaBandwidthAtTime);
 
 #define KlattGRID_GET_FORMANT_FB_VALUES_ACTION(Name, formantname) \
-	praat_addAction1 (classKlattGrid, 1, U"Get " #formantname " frequency at time...", nullptr, 1, DO_KlattGrid_get##Name##FormantFrequencyAtTime); \
-	praat_addAction1 (classKlattGrid, 1, U"Get " #formantname " bandwidth at time...", nullptr, 1, DO_KlattGrid_get##Name##FormantBandwidthAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get " #formantname " frequency at time...", nullptr, 1, REAL_KlattGrid_get##Name##FormantFrequencyAtTime); \
+	praat_addAction1 (classKlattGrid, 1, U"Get " #formantname " bandwidth at time...", nullptr, 1, REAL_KlattGrid_get##Name##FormantBandwidthAtTime);
 
 #define KlattGRID_GET_FORMANT_A_VALUES_ACTION(Name,formantname) \
-	praat_addAction1 (classKlattGrid, 1, U"Get " #formantname " amplitude at time...", nullptr, 1, DO_KlattGrid_get##Name##FormantAmplitudeAtTime); \
+	praat_addAction1 (classKlattGrid, 1, U"Get " #formantname " amplitude at time...", nullptr, 1, REAL_KlattGrid_get##Name##FormantAmplitudeAtTime); \
 
 	KlattGRID_GET_FORMANT_FB_VALUES_ACTION (Oral, oral formant)
 	KlattGRID_GET_FORMANT_A_VALUES_ACTION (Oral, oral formant)
@@ -1098,25 +1036,25 @@ void praat_KlattGrid_init () {
 #undef KlattGRID_GET_FORMANT_A_VALUES_ACTION
 #undef KlattGRID_GET_FORMANT_A_VALUES_ACTION
 
-	praat_addAction1 (classKlattGrid, 1, U"Get frication bypass at time...", nullptr, 1, DO_KlattGrid_getFricationBypassAtTime);
-	praat_addAction1 (classKlattGrid, 1, U"Get frication amplitude at time...", nullptr, 1, DO_KlattGrid_getFricationAmplitudeAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get frication bypass at time...", nullptr, 1, REAL_KlattGrid_getFricationBypassAtTime);
+	praat_addAction1 (classKlattGrid, 1, U"Get frication amplitude at time...", nullptr, 1, REAL_KlattGrid_getFricationAmplitudeAtTime);
 
 	praat_addAction1 (classKlattGrid, 0, U"Modify phonation -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Add pitch point...", nullptr, 1, DO_KlattGrid_addPitchPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add voicing amplitude point...", nullptr, 1, DO_KlattGrid_addVoicingAmplitudePoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add flutter point...", nullptr, 1, DO_KlattGrid_addFlutterPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add power1 point...", nullptr, 1, DO_KlattGrid_addPower1Point);
-	praat_addAction1 (classKlattGrid, 0, U"Add power2 point...", nullptr, 1, DO_KlattGrid_addPower2Point);
-	praat_addAction1 (classKlattGrid, 0, U"Add open phase point...", nullptr, 1, DO_KlattGrid_addOpenPhasePoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add collision phase point...", nullptr, 1, DO_KlattGrid_addCollisionPhasePoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add double pulsing point...", nullptr, 1, DO_KlattGrid_addDoublePulsingPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add spectral tilt point...", nullptr, 1, DO_KlattGrid_addSpectralTiltPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add aspiration amplitude point...", nullptr, 1, DO_KlattGrid_addAspirationAmplitudePoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add breathiness amplitude point...", nullptr, 1, DO_KlattGrid_addBreathinessAmplitudePoint);
-
-#define KlattGrid_REMOVE_POINTS_ACTION(Name,name) \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #name " points between...", nullptr, praat_DEPTH_1+praat_HIDDEN, DO_KlattGrid_remove##Name##Points); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #name " points...", nullptr, 1, DO_KlattGrid_remove##Name##Points);
+	praat_addAction1 (classKlattGrid, 0, U"Add pitch point...", nullptr, 1, MODIFY_KlattGrid_addPitchPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add voicing amplitude point...", nullptr, 1, MODIFY_KlattGrid_addVoicingAmplitudePoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add flutter point...", nullptr, 1, MODIFY_KlattGrid_addFlutterPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add power1 point...", nullptr, 1, MODIFY_KlattGrid_addPower1Point);
+	praat_addAction1 (classKlattGrid, 0, U"Add power2 point...", nullptr, 1, MODIFY_KlattGrid_addPower2Point);
+	praat_addAction1 (classKlattGrid, 0, U"Add open phase point...", nullptr, 1, MODIFY_KlattGrid_addOpenPhasePoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add collision phase point...", nullptr, 1, MODIFY_KlattGrid_addCollisionPhasePoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add double pulsing point...", nullptr, 1, MODIFY_KlattGrid_addDoublePulsingPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add spectral tilt point...", nullptr, 1, MODIFY_KlattGrid_addSpectralTiltPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add aspiration amplitude point...", nullptr, 1, MODIFY_KlattGrid_addAspirationAmplitudePoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add breathiness amplitude point...", nullptr, 1, MODIFY_KlattGrid_addBreathinessAmplitudePoint);
+
+#define KlattGrid_REMOVE_POINTS_ACTION(Name,name)  \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #name " points between...", nullptr, praat_DEPTH_1+praat_HIDDEN, MODIFY_KlattGrid_remove##Name##Points); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #name " points...", nullptr, 1, MODIFY_KlattGrid_remove##Name##Points);
 
 	KlattGrid_REMOVE_POINTS_ACTION (Pitch, pitch)
 	KlattGrid_REMOVE_POINTS_ACTION (VoicingAmplitude, voicing amplitude)
@@ -1132,33 +1070,33 @@ void praat_KlattGrid_init () {
 
 	praat_addAction1 (classKlattGrid, 0, U"Modify vocal tract -", nullptr, 0, nullptr);
 
-#define KlattGrid_MODIFY_ACTIONS_FBA(Name,formantname) \
-	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " frequencies)...", nullptr, 1, DO_KlattGrid_formula##Name##FormantFrequencies); \
-	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " bandwidths)...", nullptr, 1, DO_KlattGrid_formula##Name##FormantBandwidths); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency point...", nullptr, 1, DO_KlattGrid_add##Name##FormantFrequencyPoint); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " bandwidth point...", nullptr, 1, DO_KlattGrid_add##Name##FormantBandwidthPoint); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " amplitude point...", nullptr, 1, DO_KlattGrid_add##Name##FormantAmplitudePoint); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency points...", nullptr, 1, DO_KlattGrid_remove##Name##FormantFrequencyPoints); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " bandwidth points...", nullptr, 1, DO_KlattGrid_remove##Name##FormantBandwidthPoints); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " amplitude points...", nullptr, 1, DO_KlattGrid_remove##Name##FormantAmplitudePoints); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency and bandwidth tiers...", nullptr, 1, DO_KlattGrid_add##Name##FormantFrequencyAndBandwidthTiers); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency and bandwidth tiers...", nullptr, 1, DO_KlattGrid_remove##Name##FormantFrequencyAndBandwidthTiers); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " amplitude tier...", nullptr, 1, DO_KlattGrid_add##Name##FormantAmplitudeTier); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " amplitude tier...", nullptr, 1, DO_KlattGrid_remove##Name##FormantAmplitudeTier); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_add##Name##Formant); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_remove##Name##Formant);
-
-#define KlattGrid_MODIFY_ACTIONS_FB(Name,formantname) \
-	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " frequencies)...", nullptr, 1, DO_KlattGrid_formula##Name##FormantFrequencies); \
-	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " bandwidths)...", nullptr, 1, DO_KlattGrid_formula##Name##FormantBandwidths); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency point...", nullptr, 1, DO_KlattGrid_add##Name##FormantFrequencyPoint); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " bandwidth point...", nullptr, 1, DO_KlattGrid_add##Name##FormantBandwidthPoint); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency points...", nullptr, 1, DO_KlattGrid_remove##Name##FormantFrequencyPoints); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " bandwidth points...", nullptr, 1, DO_KlattGrid_remove##Name##FormantBandwidthPoints); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency and bandwidth tiers...", nullptr, 1, DO_KlattGrid_add##Name##FormantFrequencyAndBandwidthTiers); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency and bandwidth tiers...", nullptr, 1, DO_KlattGrid_remove##Name##FormantFrequencyAndBandwidthTiers); \
-	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_add##Name##Formant); \
-	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_remove##Name##Formant);
+#define KlattGrid_MODIFY_ACTIONS_FBA(Name,formantname)  \
+	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " frequencies)...", nullptr, 1, MODIFY_KlattGrid_formula##Name##FormantFrequencies); \
+	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " bandwidths)...", nullptr, 1, MODIFY_KlattGrid_formula##Name##FormantBandwidths); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency point...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantFrequencyPoint); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " bandwidth point...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantBandwidthPoint); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " amplitude point...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantAmplitudePoint); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency points...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantFrequencyPoints); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " bandwidth points...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantBandwidthPoints); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " amplitude points...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantAmplitudePoints); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency and bandwidth tiers...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantFrequencyAndBandwidthTiers); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency and bandwidth tiers...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantFrequencyAndBandwidthTiers); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " amplitude tier...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantAmplitudeTier); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " amplitude tier...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantAmplitudeTier); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_add##Name##Formant); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_remove##Name##Formant);
+
+#define KlattGrid_MODIFY_ACTIONS_FB(Name,formantname)  \
+	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " frequencies)...", nullptr, 1, MODIFY_KlattGrid_formula##Name##FormantFrequencies); \
+	praat_addAction1 (classKlattGrid, 0, U"Formula (" #formantname " bandwidths)...", nullptr, 1, MODIFY_KlattGrid_formula##Name##FormantBandwidths); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency point...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantFrequencyPoint); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " bandwidth point...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantBandwidthPoint); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency points...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantFrequencyPoints); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " bandwidth points...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantBandwidthPoints); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname " frequency and bandwidth tiers...", nullptr, 1, MODIFY_KlattGrid_add##Name##FormantFrequencyAndBandwidthTiers); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname " frequency and bandwidth tiers...", nullptr, 1, MODIFY_KlattGrid_remove##Name##FormantFrequencyAndBandwidthTiers); \
+	praat_addAction1 (classKlattGrid, 0, U"Add " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_add##Name##Formant); \
+	praat_addAction1 (classKlattGrid, 0, U"Remove " #formantname "...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_remove##Name##Formant);
 
 	KlattGrid_MODIFY_ACTIONS_FBA (Oral, oral formant)
 	praat_addAction1 (classKlattGrid, 0, U"-- oral modify separator --", nullptr, 1, nullptr);
@@ -1166,14 +1104,14 @@ void praat_KlattGrid_init () {
 	praat_addAction1 (classKlattGrid, 0, U"-- nasal modify separator --", nullptr, 1, nullptr);
 	KlattGrid_MODIFY_ACTIONS_FB (NasalAnti, nasal antiformant)
 
-	praat_addAction1 (classKlattGrid, 0, U"Formula (frequencies)...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_formula_frequencies);
-	praat_addAction1 (classKlattGrid, 0, U"Formula (bandwidths)...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_formula_bandwidths);
-	praat_addAction1 (classKlattGrid, 0, U"Add formant point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_addFormantPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add bandwidth point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_addBandwidthPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add amplitude point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_addAmplitudePoint);
-	praat_addAction1 (classKlattGrid, 0, U"Remove formant points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_removeFormantPoints);
-	praat_addAction1 (classKlattGrid, 0, U"Remove bandwidth points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_removeBandwidthPoints);
-	praat_addAction1 (classKlattGrid, 0, U"Remove amplitude points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_removeAmplitudePoints);
+	praat_addAction1 (classKlattGrid, 0, U"Formula (frequencies)...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_formula_frequencies);
+	praat_addAction1 (classKlattGrid, 0, U"Formula (bandwidths)...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_formula_bandwidths);
+	praat_addAction1 (classKlattGrid, 0, U"Add formant point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_addFormantPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add bandwidth point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_addBandwidthPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add amplitude point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_addAmplitudePoint);
+	praat_addAction1 (classKlattGrid, 0, U"Remove formant points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_removeFormantPoints);
+	praat_addAction1 (classKlattGrid, 0, U"Remove bandwidth points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_removeBandwidthPoints);
+	praat_addAction1 (classKlattGrid, 0, U"Remove amplitude points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_removeAmplitudePoints);
 	praat_addAction1 (classKlattGrid, 0, U"Modify coupling - ", nullptr, 0, nullptr);
 	KlattGrid_MODIFY_ACTIONS_FB (Delta, delta formant)
 	praat_addAction1 (classKlattGrid, 0, U"-- delta modify separator --", nullptr, 1, nullptr);
@@ -1181,84 +1119,84 @@ void praat_KlattGrid_init () {
 	praat_addAction1 (classKlattGrid, 0, U"-- nasal modify separator --", nullptr, 1, nullptr);
 	KlattGrid_MODIFY_ACTIONS_FB (TrachealAnti, tracheal antiformant)
 
-	praat_addAction1 (classKlattGrid, 0, U"Add delta formant point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_addDeltaFormantPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add delta bandwidth point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_addDeltaBandwidthPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Remove delta formant points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_removeDeltaFormantPoints);
-	praat_addAction1 (classKlattGrid, 0, U"Remove delta bandwidth points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_removeDeltaBandwidthPoints);
+	praat_addAction1 (classKlattGrid, 0, U"Add delta formant point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_addDeltaFormantPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add delta bandwidth point...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_addDeltaBandwidthPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Remove delta formant points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_removeDeltaFormantPoints);
+	praat_addAction1 (classKlattGrid, 0, U"Remove delta bandwidth points between...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_removeDeltaBandwidthPoints);
 
 	praat_addAction1 (classKlattGrid, 0, U"Modify frication -", nullptr, 0, nullptr);
 	KlattGrid_MODIFY_ACTIONS_FBA (Frication, frication formant)
 	praat_addAction1 (classKlattGrid, 0, U"-- frication modify separator --", nullptr, 1, nullptr);
 
-	praat_addAction1 (classKlattGrid, 0, U"Add frication bypass point...", nullptr, 1, DO_KlattGrid_addFricationBypassPoint);
-	praat_addAction1 (classKlattGrid, 0, U"Add frication amplitude point...", nullptr, 1, DO_KlattGrid_addFricationAmplitudePoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add frication bypass point...", nullptr, 1, MODIFY_KlattGrid_addFricationBypassPoint);
+	praat_addAction1 (classKlattGrid, 0, U"Add frication amplitude point...", nullptr, 1, MODIFY_KlattGrid_addFricationAmplitudePoint);
 	KlattGrid_REMOVE_POINTS_ACTION (FricationBypass, frication bypass)
 	KlattGrid_REMOVE_POINTS_ACTION (FricationAmplitude, frication amplitude)
-	praat_addAction1 (classKlattGrid, 0, U"Add formant and bandwidth tier...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_addFormantAndBandwidthTier);
+	praat_addAction1 (classKlattGrid, 0, U"Add formant and bandwidth tier...", nullptr, praat_DEPTH_1 + praat_HIDDEN, MODIFY_KlattGrid_addFormantAndBandwidthTier);
 
 #undef KlattGrid_REMOVE_POINTS_ACTION
 #undef KlattGrid_MODIFY_ACTION_FB
 #undef KlattGrid_MODIFY_ACTION_FBA
 
 	praat_addAction1 (classKlattGrid, 0, U"Extract phonation -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Extract pitch tier", nullptr, 1, DO_KlattGrid_extractPitchTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract voicing amplitude tier", nullptr, 1, DO_KlattGrid_extractVoicingAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract flutter tier", nullptr, 1, DO_KlattGrid_extractFlutterTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract power1 tier", nullptr, 1, DO_KlattGrid_extractPower1Tier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract power2 tier", nullptr, 1, DO_KlattGrid_extractPower2Tier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract open phase tier", nullptr, 1, DO_KlattGrid_extractOpenPhaseTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract collision phase tier", nullptr, 1, DO_KlattGrid_extractCollisionPhaseTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract double pulsing tier", nullptr, 1, DO_KlattGrid_extractDoublePulsingTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract spectral tilt tier", nullptr, 1, DO_KlattGrid_extractSpectralTiltTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract aspiration amplitude tier", nullptr, 1, DO_KlattGrid_extractAspirationAmplitudeTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract breathiness amplitude tier", nullptr, 1, DO_KlattGrid_extractBreathinessAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract pitch tier", nullptr, 1, NEW_KlattGrid_extractPitchTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract voicing amplitude tier", nullptr, 1, NEW_KlattGrid_extractVoicingAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract flutter tier", nullptr, 1, NEW_KlattGrid_extractFlutterTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract power1 tier", nullptr, 1, NEW_KlattGrid_extractPower1Tier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract power2 tier", nullptr, 1, NEW_KlattGrid_extractPower2Tier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract open phase tier", nullptr, 1, NEW_KlattGrid_extractOpenPhaseTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract collision phase tier", nullptr, 1, NEW_KlattGrid_extractCollisionPhaseTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract double pulsing tier", nullptr, 1, NEW_KlattGrid_extractDoublePulsingTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract spectral tilt tier", nullptr, 1, NEW_KlattGrid_extractSpectralTiltTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract aspiration amplitude tier", nullptr, 1, NEW_KlattGrid_extractAspirationAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract breathiness amplitude tier", nullptr, 1, NEW_KlattGrid_extractBreathinessAmplitudeTier);
 	praat_addAction1 (classKlattGrid, 0, U"-- extract glottal events--", nullptr, 1, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Extract PointProcess (glottal closures)", nullptr, 1, DO_KlattGrid_extractPointProcess_glottalClosures);
+	praat_addAction1 (classKlattGrid, 0, U"Extract PointProcess (glottal closures)", nullptr, 1, NEW_KlattGrid_extractPointProcess_glottalClosures);
 
-#define KlattGRID_EXTRACT_FORMANT_GRID_ACTION(Name,namef) \
-	praat_addAction1 (classKlattGrid, 0, U"Extract " #namef "ormant grid", nullptr, 1, DO_KlattGrid_extract##Name##FormantGrid);
-#define KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION(Name,name) \
-	praat_addAction1 (classKlattGrid, 0, U"Extract " #name " formant amplitude tier...", nullptr, 1, DO_KlattGrid_extract##Name##FormantAmplitudeTier);
+#define KlattGRID_EXTRACT_FORMANT_GRID_ACTION(Name,namef)  \
+	praat_addAction1 (classKlattGrid, 0, U"Extract " #namef "ormant grid", nullptr, 1, NEW_KlattGrid_extract##Name##FormantGrid);
+#define KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION(Name,name)  \
+	praat_addAction1 (classKlattGrid, 0, U"Extract " #name " formant amplitude tier...", nullptr, 1, NEW_KlattGrid_extract##Name##FormantAmplitudeTier);
 
 	praat_addAction1 (classKlattGrid, 0, U"Extract filters -", nullptr, 0, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Extract formant grid...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_extractFormantGrid); // deprecated
+	praat_addAction1 (classKlattGrid, 0, U"Extract formant grid...", nullptr, praat_DEPTH_1 + praat_HIDDEN + praat_NO_API, NEW_KlattGrid_extractFormantGrid); // deprecated
 	KlattGRID_EXTRACT_FORMANT_GRID_ACTION (Oral, oral f)
-	praat_addAction1 (classKlattGrid, 0, U"Extract amplitude tier...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_KlattGrid_extractAmplitudeTier); // deprecated
-	praat_addAction1 (classKlattGrid, 0, U"Extract formant grid (open phases)...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_KlattGrid_to_oralFormantGrid_openPhases);
-	praat_addAction1 (classKlattGrid, 0, U"Extract oral formant grid (open phases)...", nullptr, 1, DO_KlattGrid_to_oralFormantGrid_openPhases);
+	praat_addAction1 (classKlattGrid, 0, U"Extract amplitude tier...", nullptr, praat_DEPTH_1 + praat_HIDDEN + praat_NO_API, NEW_KlattGrid_extractAmplitudeTier); // deprecated
+	praat_addAction1 (classKlattGrid, 0, U"Extract formant grid (open phases)...", nullptr, praat_HIDDEN + praat_DEPTH_1, NEW_KlattGrid_to_oralFormantGrid_openPhases);
+	praat_addAction1 (classKlattGrid, 0, U"Extract oral formant grid (open phases)...", nullptr, 1, NEW_KlattGrid_to_oralFormantGrid_openPhases);
 	KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION (Oral, oral)
 	KlattGRID_EXTRACT_FORMANT_GRID_ACTION (Nasal, nasal f)
 	KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION (Nasal, nasal)
 	KlattGRID_EXTRACT_FORMANT_GRID_ACTION (NasalAnti, nasal antif)
 
 	praat_addAction1 (classKlattGrid, 0, U"-- extract delta characteristics", nullptr, 1, nullptr);
-	praat_addAction1 (classKlattGrid, 0, U"Extract delta formant grid", nullptr, 1, DO_KlattGrid_extractDeltaFormantGrid);
+	praat_addAction1 (classKlattGrid, 0, U"Extract delta formant grid", nullptr, 1, NEW_KlattGrid_extractDeltaFormantGrid);
 	KlattGRID_EXTRACT_FORMANT_GRID_ACTION (Tracheal, tracheal f)
 	KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION (Tracheal, tracheal)
 	KlattGRID_EXTRACT_FORMANT_GRID_ACTION (TrachealAnti, tracheal antif)
 	praat_addAction1 (classKlattGrid, 0, U"-- extract frication characteristics", nullptr, 1, nullptr);
 	KlattGRID_EXTRACT_FORMANT_GRID_ACTION (Frication, frication f)
 	KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION (Frication, frication)
-	praat_addAction1 (classKlattGrid, 0, U"Extract frication bypass tier", nullptr, 1, DO_KlattGrid_extractFricationBypassTier);
-	praat_addAction1 (classKlattGrid, 0, U"Extract frication amplitude tier", nullptr, 1, DO_KlattGrid_extractFricationAmplitudeTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract frication bypass tier", nullptr, 1, NEW_KlattGrid_extractFricationBypassTier);
+	praat_addAction1 (classKlattGrid, 0, U"Extract frication amplitude tier", nullptr, 1, NEW_KlattGrid_extractFricationAmplitudeTier);
 
 #undef KlattGRID_EXTRACT_FORMANT_AMPLITUDE_ACTION
 #undef KlattGRID_EXTRACT_FORMANT_GRID_ACTION
 
-	praat_addAction2 (classKlattGrid, 1, classPitchTier, 1, U"Replace pitch tier", nullptr, 1, DO_KlattGrid_replacePitchTier);
-	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace flutter tier", nullptr, 1, DO_KlattGrid_replaceFlutterTier);
-	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace power1 tier", nullptr, 1, DO_KlattGrid_replacePower1Tier);
-	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace power2 tier", nullptr, 1, DO_KlattGrid_replacePower2Tier);
-	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace open phase tier", nullptr, 1, DO_KlattGrid_replaceOpenPhaseTier);
-	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace collision phase tier", nullptr, 1, DO_KlattGrid_replaceCollisionPhaseTier);
-	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace double pulsing tier", nullptr, 1, DO_KlattGrid_replaceDoublePulsingTier);
+	praat_addAction2 (classKlattGrid, 1, classPitchTier, 1, U"Replace pitch tier", nullptr, 1, MODIFY_KlattGrid_replacePitchTier);
+	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace flutter tier", nullptr, 1, MODIFY_KlattGrid_replaceFlutterTier);
+	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace power1 tier", nullptr, 1, MODIFY_KlattGrid_replacePower1Tier);
+	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace power2 tier", nullptr, 1, MODIFY_KlattGrid_replacePower2Tier);
+	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace open phase tier", nullptr, 1, MODIFY_KlattGrid_replaceOpenPhaseTier);
+	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace collision phase tier", nullptr, 1, MODIFY_KlattGrid_replaceCollisionPhaseTier);
+	praat_addAction2 (classKlattGrid, 1, classRealTier, 1, U"Replace double pulsing tier", nullptr, 1, MODIFY_KlattGrid_replaceDoublePulsingTier);
 
 	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"-- replace formant amplitudes --", nullptr, 1, nullptr);
 
-#define KlattGrid_REPLACE_FORMANTGRID_ACTION(Name,namef) \
-	praat_addAction2 (classKlattGrid, 1, classFormantGrid, 1, U"Replace " #namef "ormant grid", nullptr, 1, DO_KlattGrid_replace##Name##FormantGrid);
-#define KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION(Name,namef) \
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace " #namef "ormant amplitude tier...", nullptr, 1, DO_KlattGrid_replace##Name##FormantAmplitudeTier);
+#define KlattGrid_REPLACE_FORMANTGRID_ACTION(Name,namef)  \
+	praat_addAction2 (classKlattGrid, 1, classFormantGrid, 1, U"Replace " #namef "ormant grid", nullptr, 1, MODIFY_KlattGrid_replace##Name##FormantGrid);
+#define KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION(Name,namef)  \
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace " #namef "ormant amplitude tier...", nullptr, 1, MODIFY_KlattGrid_replace##Name##FormantAmplitudeTier);
 
 	KlattGrid_REPLACE_FORMANTGRID_ACTION (Oral, oral f)
 	KlattGrid_REPLACE_FORMANTGRID_ACTION (Nasal, nasal f)
@@ -1269,27 +1207,25 @@ void praat_KlattGrid_init () {
 	KlattGrid_REPLACE_FORMANTGRID_ACTION (Delta, delta f)
 	praat_addAction2 (classKlattGrid, 1, classFormantGrid, 1, U"-- replace frication --", nullptr, 1, nullptr);
 	KlattGrid_REPLACE_FORMANTGRID_ACTION (Frication, frication f)
-	praat_addAction2 (classKlattGrid, 1, classFormantGrid, 1, U"Replace formant grid...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_KlattGrid_replaceFormantGrid);
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace voicing amplitude tier", nullptr, 1, DO_KlattGrid_replaceVoicingAmplitudeTier);
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace spectral tilt tier", nullptr, 1, DO_KlattGrid_replaceSpectralTiltTier);
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace aspiration amplitude tier", nullptr, 1,
-	                  DO_KlattGrid_replaceAspirationAmplitudeTier);
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace breathiness amplitude tier", nullptr, 1,
-	                  DO_KlattGrid_replaceBreathinessAmplitudeTier);
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace amplitude tier...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_KlattGrid_replaceAmplitudeTier);
+	praat_addAction2 (classKlattGrid, 1, classFormantGrid, 1, U"Replace formant grid...", nullptr, praat_HIDDEN + praat_DEPTH_1, MODIFY_KlattGrid_replaceFormantGrid);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace voicing amplitude tier", nullptr, 1, MODIFY_KlattGrid_replaceVoicingAmplitudeTier);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace spectral tilt tier", nullptr, 1, MODIFY_KlattGrid_replaceSpectralTiltTier);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace aspiration amplitude tier", nullptr, 1, MODIFY_KlattGrid_replaceAspirationAmplitudeTier);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace breathiness amplitude tier", nullptr, 1, MODIFY_KlattGrid_replaceBreathinessAmplitudeTier);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace amplitude tier...", nullptr, praat_HIDDEN + praat_DEPTH_1, MODIFY_KlattGrid_replaceAmplitudeTier);
 	KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION (Oral, oral f)
 	KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION (Nasal, nasal f)
 	KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION (Tracheal, tracheal f)
 	KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION (Frication, frication f)
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace frication amplitude tier", nullptr, 1, DO_KlattGrid_replaceFricationAmplitudeTier);
-	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace frication bypass tier", nullptr, 1, DO_KlattGrid_replaceFricationBypassTier);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace frication amplitude tier", nullptr, 1, MODIFY_KlattGrid_replaceFricationAmplitudeTier);
+	praat_addAction2 (classKlattGrid, 1, classIntensityTier, 1, U"Replace frication bypass tier", nullptr, 1, MODIFY_KlattGrid_replaceFricationBypassTier);
 
 #undef KlattGrid_REPLACE_FORMANT_AMPLITUDE_ACTION
 #undef KlattGrid_REPLACE_FORMANTGRID_ACTION
 
-	praat_addAction2 (classKlattGrid, 1, classSound, 1, U"Filter by vocal tract...", nullptr, 1, DO_Sound_KlattGrid_filterByVocalTract);
+	praat_addAction2 (classKlattGrid, 1, classSound, 1, U"Filter by vocal tract...", nullptr, 1, NEW_Sound_KlattGrid_filterByVocalTract);
 
 	INCLUDE_MANPAGES (manual_KlattGrid)
 }
 
-/* End of file praat_KlattGrid_init.cpp */
+/* End of file praat_KlattGrid_init.cpp 1290*/
diff --git a/dwtools/praat_MDS_init.cpp b/dwtools/praat_MDS_init.cpp
index 03e1c77..fec200c 100644
--- a/dwtools/praat_MDS_init.cpp
+++ b/dwtools/praat_MDS_init.cpp
@@ -1,6 +1,6 @@
 /* praat_MDS_init.cpp
  *
- * Copyright (C) 1992-2012, 2015 David Weenink
+ * Copyright (C) 1992-2012, 2015-2016 David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -43,7 +43,6 @@
 #include "Confusion.h"
 #include "Formula.h"
 
-void praat_TableOfReal_init (ClassInfo klas);
 void praat_TableOfReal_init2 (ClassInfo klas);
 
 static const char32 *QUERY_BUTTON   = U"Query -";
@@ -91,1767 +90,1277 @@ static void TabelOfReal_testSorting (TableOfReal me, long rowtoindex) {
 #undef iam
 #define iam iam_LOOP
 
-FORM (TabelOfReal_testSorting, U"TabelOfReal: Sort and index", U"")
-	NATURAL (U"Row to index", U"1")
+FORM (MODIFY_TabelOfReal_testSorting, U"TabelOfReal: Sort and index", U"") {
+	NATURALVAR (rowIndex, U"Row to index", U"1")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TabelOfReal_testSorting (me, GET_INTEGER (U"Row to index"));
-	}
-END
+	MODIFY_EACH (TableOfReal)
+		TabelOfReal_testSorting (me, rowIndex);
+	MODIFY_EACH_END
+}
 
 /************************* examples ***************************************/
 
-FORM (Dissimilarity_createLetterRExample, U"Create letter R example", U"Create letter R example...")
+FORM (NEW1_Dissimilarity_createLetterRExample, U"Create letter R example", U"Create letter R example...") {
 	LABEL (U"", U"For the monotone transformation on the distances")
-	REAL (U"Noise range", U"32.5")
+	REALVAR (noiseRange, U"Noise range", U"32.5")
 	OK
 DO
-	praat_new (Dissimilarity_createLetterRExample (GET_REAL (U"Noise range")), U"");
-END
+	CREATE_ONE
+		autoDissimilarity result = Dissimilarity_createLetterRExample (noiseRange);
+	CREATE_ONE_END (U"R")
+}
 
-FORM (INDSCAL_createCarrollWishExample,
-      U"Create INDSCAL Carroll & Wish example...",
-      U"Create INDSCAL Carroll & Wish example...")
-	REAL (U"Noise standard deviation", U"0.0")
-OK
-	DO
-	praat_new (INDSCAL_createCarrollWishExample (GET_REAL (U"Noise standard deviation")), U""); 
-END
+FORM (NEWMANY_INDSCAL_createCarrollWishExample, U"Create INDSCAL Carroll & Wish example...", U"Create INDSCAL Carroll & Wish example...") {
+	REALVAR (noiseStandardDeviation, U"Noise standard deviation", U"0.0")
+	OK
+DO
+	praat_new (INDSCAL_createCarrollWishExample (noiseStandardDeviation), U""); 
+END }
 
-FORM (Configuration_create, U"Create Configuration", U"Create Configuration...")
-	WORD (U"Name", U"uniform")
-	NATURAL (U"Number of points", U"10")
-	NATURAL (U"Number of dimensions", U"2")
+FORM (NEW1_Configuration_create, U"Create Configuration", U"Create Configuration...") {
+	WORDVAR (name, U"Name", U"uniform")
+	NATURALVAR (numberOfPoints, U"Number of points", U"10")
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
 	LABEL (U"", U"Formula:")
-	TEXTFIELD (U"formula", U"randomUniform(-1.5, 1.5)")
+	TEXTVAR (formula, U"formula", U"randomUniform(-1.5, 1.5)")
 	OK
 DO
-	autoConfiguration me = Configuration_create (GET_INTEGER (U"Number of points"), GET_INTEGER (U"Number of dimensions"));
-	TableOfReal_formula (me.get(), GET_STRING (U"formula"), interpreter, nullptr);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END
+	CREATE_ONE
+		autoConfiguration result = Configuration_create (numberOfPoints, numberOfDimensions);
+		TableOfReal_formula (result.get(), formula, interpreter, nullptr);
+	CREATE_ONE_END (name)
+}
 
-FORM (drawSplines, U"Draw splines", U"spline")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"1.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"20.0")
-	RADIO (U"Spline type", 1)
+FORM (GRAPHICS_drawSplines, U"Draw splines", U"spline") {
+	REALVAR (xmin, U"left Horizontal range", U"0.0")
+	REALVAR (xmax, U"right Horizontal range", U"1.0")
+	REALVAR (ymin, U"left Vertical range", U"0.0")
+	REALVAR (ymax, U"right Vertical range", U"20.0")
+	RADIOVAR (splineType, U"Spline type", 1)
 		RADIOBUTTON (U"M-spline")
 		RADIOBUTTON (U"I-spline")
-	INTEGER (U"Order", U"3")
-	SENTENCE (U"Interior knots", U"0.3 0.5 0.6")
-	BOOLEAN (U"Garnish", true)
+	INTEGERVAR (order, U"Order", U"3")
+	SENTENCEVAR (interiorKnots_string, U"Interior knots", U"0.3 0.5 0.6")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	double xmin = GET_REAL (U"left Horizontal range"), xmax = GET_REAL (U"right Horizontal range");
-	double ymin = GET_REAL (U"left Vertical range"), ymax = GET_REAL (U"right Vertical range");
 	if (xmax <= xmin or ymax <= ymin) {
 		Melder_throw (U"Required: xmin < xmax and ymin < ymax.");
 	}
-	autoPraatPicture picture;
-	drawSplines (GRAPHICS, xmin, xmax, ymin, ymax,
-		GET_INTEGER (U"Spline type"),
-		GET_INTEGER (U"Order"),
-		GET_STRING (U"Interior knots"),
-		GET_INTEGER (U"Garnish"));
-END
+	GRAPHICS_NONE
+		drawSplines (GRAPHICS, xmin, xmax, ymin, ymax, splineType,order, interiorKnots_string, garnish);
+	GRAPHICS_NONE_END
+}
 
-DIRECT (drawMDSClassRelations)
-	autoPraatPicture picture;
-	drawMDSClassRelations (GRAPHICS);
-END
+DIRECT (GRAPHICS_drawMDSClassRelations) {
+	GRAPHICS_NONE
+		drawMDSClassRelations (GRAPHICS);
+	GRAPHICS_NONE_END	
+}
 
 
 /***************** AffineTransform ***************************************/
 
 
-DIRECT (AffineTransform_help)
-	Melder_help (U"AffineTransform");
-END
+DIRECT (HELP_AffineTransform_help) {
+	HELP (U"AffineTransform");
+}
 
-DIRECT (AffineTransform_invert)
-	LOOP {
-		iam (AffineTransform);
-		praat_new (AffineTransform_invert (me), NAME, U"_inv");
-	}
-END
+DIRECT (NEW_AffineTransform_invert) {
+	CONVERT_EACH (AffineTransform)
+		autoAffineTransform result = AffineTransform_invert (me);
+	CONVERT_EACH_END (my name, U"_inv")
+}
 
-FORM (AffineTransform_getTransformationElement, U"AffineTransform: Get transformation element", U"Procrustes")
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
+FORM (REAL_AffineTransform_getTransformationElement, U"AffineTransform: Get transformation element", U"Procrustes") {
+	NATURALVAR (row, U"Row number", U"1")
+	NATURALVAR (column, U"Column number", U"1")
 	OK
 DO
-	long row = GET_INTEGER (U"Row number");
-	long column = GET_INTEGER (U"Column number");
-	LOOP {
-		iam (AffineTransform);
+	NUMBER_ONE (AffineTransform)
 		if (row > my n) {
 			Melder_throw (U"Row number must not exceed number of rows.");
 		}
 		if (column > my n) {
 			Melder_throw (U"Column number must not exceed number of columns.");
 		}
-		Melder_information (my r [row] [column]);
-	}
-END
+		double result = my r [row] [column];
+	NUMBER_ONE_END (U"")
+}
 
-FORM (AffineTransform_getTranslationElement, U"AffineTransform: Get translation element", U"Procrustes")
-	NATURAL (U"Index", U"1")
+FORM (REAL_AffineTransform_getTranslationElement, U"AffineTransform: Get translation element", U"Procrustes") {
+	NATURALVAR (index, U"Index", U"1")
 	OK
 DO
-	long number = GET_INTEGER (U"Index");
-	LOOP {
-		iam (AffineTransform);
-		if (number > my n) {
+	NUMBER_ONE (AffineTransform)
+		if (index > my n) {
 			Melder_throw (U"Index must not exceed number of elements.");
 		}
-		Melder_information (my t [number]);
-	}
-END
+		double result = my t [index];
+	NUMBER_ONE_END (U"")
+}
 
-DIRECT (AffineTransform_extractMatrix)
-	LOOP {
-		iam (AffineTransform);
-		autoTableOfReal thee = AffineTransform_extractMatrix (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_AffineTransform_extractMatrix) {
+	CONVERT_EACH (AffineTransform)
+		autoTableOfReal result = AffineTransform_extractMatrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (AffineTransform_extractTranslationVector)
-	LOOP {
-		iam (AffineTransform);
-		autoTableOfReal thee = AffineTransform_extractTranslationVector (me);
-		praat_new (thee.move(), my name);
-	}
-END
+DIRECT (NEW_AffineTransform_extractTranslationVector) {
+	CONVERT_EACH (AffineTransform)
+		autoTableOfReal result = AffineTransform_extractTranslationVector (me);
+	CONVERT_EACH_END (my name)
+}
 
 /***************** Configuration ***************************************/
 
-DIRECT (Configuration_help)
-	Melder_help (U"Configuration");
-END
-
-static void Configuration_draw_addCommonFields (UiForm dia) {
-	NATURAL (U"Horizontal dimension", U"1")
-	NATURAL (U"Vertical dimension", U"2")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0")
+DIRECT (HELP_Configuration_help) {
+	HELP (U"Configuration")
 }
 
-FORM (Configuration_draw, U"Configuration: Draw", U"Configuration: Draw...")
-	Configuration_draw_addCommonFields (dia);
-	NATURAL (U"Label size", U"12")
-	BOOLEAN (U"Use row labels", false)
-	WORD (U"Label", U"+")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Configuration);
-		Configuration_draw (me, GRAPHICS, GET_INTEGER (U"Horizontal dimension"), GET_INTEGER (U"Vertical dimension"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"), GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"), GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Use row labels"), GET_STRING (U"Label"), GET_INTEGER (U"Garnish"));
-	}
-END
+#define praat_Configuration_draw_commonFields(horizontalDimension,verticalDimension,xmin,xmax,ymin,ymax) \
+	NATURALVAR (horizontalDimension, U"Horizontal dimension", U"1") \
+	NATURALVAR (verticalDimension, U"Vertical dimension", U"2") \
+	REALVAR (xmin, U"left Horizontal range", U"0.0") \
+	REALVAR (xmax, U"right Horizontal range", U"0.0") \
+	REALVAR (ymin, U"left Vertical range", U"0.0") \
+	REALVAR (ymax, U"right Vertical range", U"0.0")
+
+FORM (GRAPHICS_Configuration_draw, U"Configuration: Draw", U"Configuration: Draw...") {
+	praat_Configuration_draw_commonFields(horizontalDimension,verticalDimension,xmin,xmax,ymin,ymax)
+	NATURALVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (useRowLables, U"Use row labels", false)
+	WORDVAR (label, U"Label", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Configuration)
+		Configuration_draw (me, GRAPHICS, horizontalDimension, verticalDimension, xmin, xmax, ymin, ymax, labelSize, useRowLables, label, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Configuration_drawSigmaEllipses, U"Configuration: Draw sigma ellipses", U"Configuration: Draw sigma ellipses...")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	Configuration_draw_addCommonFields (dia);
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Configuration_drawSigmaEllipses, U"Configuration: Draw sigma ellipses", U"Configuration: Draw sigma ellipses...") {
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	praat_Configuration_draw_commonFields(horizontalDimension,verticalDimension,xmin,xmax,ymin,ymax)
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Configuration);
-		Configuration_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Number of sigmas"),
-			false,   // confidence (i.e. the previous argument is a number of sigmas, not a confidence level)
-			nullptr,
-			GET_INTEGER (U"Horizontal dimension"), GET_INTEGER (U"Vertical dimension"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"), GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Configuration)
+		Configuration_drawConcentrationEllipses (me, GRAPHICS, numberOfSigmas, false, nullptr, horizontalDimension, verticalDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Configuration_drawOneSigmaEllipse, U"Configuration: Draw one sigma ellipse", U"Configuration: Draw sigma ellipses...")
-	SENTENCE (U"Label", U"")
-	POSITIVE (U"Number of sigmas", U"1.0")
-	Configuration_draw_addCommonFields (dia);
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Configuration_drawOneSigmaEllipse, U"Configuration: Draw one sigma ellipse", U"Configuration: Draw sigma ellipses...") {
+	SENTENCEVAR (label, U"Label", U"")
+	POSITIVEVAR (numberOfSigmas, U"Number of sigmas", U"1.0")
+	praat_Configuration_draw_commonFields(horizontalDimension,verticalDimension,xmin,xmax,ymin,ymax)
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Configuration);
-		Configuration_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Number of sigmas"),
-			false,   // confidence
-			GET_STRING (U"Label"),
-			GET_INTEGER (U"Horizontal dimension"),
-			GET_INTEGER (U"Vertical dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Configuration)
+		Configuration_drawConcentrationEllipses (me, GRAPHICS, numberOfSigmas,false, label, horizontalDimension, verticalDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
 
-FORM (Configuration_drawConfidenceEllipses, U"Configuration: Draw confidence ellipses", nullptr)
-	POSITIVE (U"Confidence level (0-1)", U"0.95")
-	Configuration_draw_addCommonFields (dia);
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Configuration_drawConfidenceEllipses, U"Configuration: Draw confidence ellipses", nullptr) {
+	POSITIVEVAR (confidenceLevel, U"Confidence level (0-1)", U"0.95")
+	praat_Configuration_draw_commonFields(horizontalDimension,verticalDimension,xmin,xmax,ymin,ymax)
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Configuration);
-		Configuration_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Confidence level"),
-			true,   // confidence (i.e. the previous argument is a confidence level, not a number of sigmas)
-			nullptr,   // label
-			GET_INTEGER (U"Horizontal dimension"),
-			GET_INTEGER (U"Vertical dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Configuration)
+		Configuration_drawConcentrationEllipses (me, GRAPHICS, confidenceLevel, true /* confidence */, nullptr, horizontalDimension, verticalDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Configuration_drawOneConfidenceEllipse, U"Configuration: Draw one confidence ellipse", nullptr)
-	SENTENCE (U"Label", U"")
-	POSITIVE (U"Confidence level (0-1)", U"0.95")
-	Configuration_draw_addCommonFields (dia);
-	INTEGER (U"Label size", U"12")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Configuration_drawOneConfidenceEllipse, U"Configuration: Draw one confidence ellipse", nullptr) {
+	SENTENCEVAR (label, U"Label", U"")
+	POSITIVEVAR (confidenceLevel, U"Confidence level (0-1)", U"0.95")
+	praat_Configuration_draw_commonFields(horizontalDimension,verticalDimension,xmin,xmax,ymin,ymax)
+	INTEGERVAR (labelSize, U"Label size", U"12")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Configuration);
-		Configuration_drawConcentrationEllipses (me, GRAPHICS,
-			GET_REAL (U"Confidence level"),
-			true,   // confidence
-			GET_STRING (U"Label"),
-			GET_INTEGER (U"Horizontal dimension"),
-			GET_INTEGER (U"Vertical dimension"),
-			GET_REAL (U"left Horizontal range"),
-			GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"),
-			GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Label size"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Configuration)
+		Configuration_drawConcentrationEllipses (me, GRAPHICS, confidenceLevel, true, label, horizontalDimension, verticalDimension, xmin, xmax, ymin, ymax, labelSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT (Configuration_randomize)
-	LOOP {
-		iam (Configuration);
+DIRECT (MODIFY_Configuration_randomize) {
+	MODIFY_EACH (Configuration)
 		Configuration_randomize (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Configuration_normalize, U"Configuration: Normalize", U"Configuration: Normalize...")
-	REAL (U"Sum of squares", U"0.0")
+FORM (MODIFY_Configuration_normalize, U"Configuration: Normalize", U"Configuration: Normalize...") {
+	REALVAR (sumOfSquares, U"Sum of squares", U"0.0")
 	LABEL (U"", U"On (INDSCAL), Off (Kruskal)")
-	BOOLEAN (U"Each dimension separately", true)
+	BOOLEANVAR (separateDimensions, U"Each dimension separately", true)
 	OK
 DO
-	LOOP {
-		iam (Configuration);
-		Configuration_normalize (me,
-			GET_REAL (U"Sum of squares"),
-			GET_INTEGER (U"Each dimension separately"));
-	}
-END
+	MODIFY_EACH (Configuration)
+		Configuration_normalize (me, sumOfSquares, separateDimensions);
+	MODIFY_EACH_END
+}
 
-DIRECT (Configuration_centralize)
-	LOOP {
-		iam (Configuration);
+DIRECT (MODIFY_Configuration_centralize) {
+	MODIFY_EACH (Configuration)
 		TableOfReal_centreColumns (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Configuration_rotate, U"Configuration: Rotate", U"Configuration: Rotate...")
-	NATURAL (U"Dimension 1", U"1")
-	NATURAL (U"Dimension 2", U"2")
-	REAL (U"Angle (degrees)", U"60.0")
+FORM (MODIFY_Configuration_rotate, U"Configuration: Rotate", U"Configuration: Rotate...") {
+	NATURALVAR (dimension1, U"Dimension 1", U"1")
+	NATURALVAR (dimension2, U"Dimension 2", U"2")
+	REALVAR (angle_degrees, U"Angle (degrees)", U"60.0")
 	OK
 DO
-	LOOP {
-		iam (Configuration);
-		Configuration_rotate (me,
-			GET_INTEGER (U"Dimension 1"),
-			GET_INTEGER (U"Dimension 2"),
-			GET_REAL (U"Angle"));
-	}
-END
+	MODIFY_EACH (Configuration)
+		Configuration_rotate (me, dimension1, dimension2, angle_degrees);
+	MODIFY_EACH_END
+}
 
-DIRECT (Configuration_rotateToPrincipalDirections)
-	LOOP {
-		iam (Configuration);
+DIRECT (MODIFY_Configuration_rotateToPrincipalDirections) {
+	MODIFY_EACH (Configuration)
 		Configuration_rotateToPrincipalDirections (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-FORM (Configuration_invertDimension, U"Configuration: Invert dimension", U"Configuration: Invert dimension...")
-	NATURAL (U"Dimension", U"1")
+FORM (MODIFY_Configuration_invertDimension, U"Configuration: Invert dimension", U"Configuration: Invert dimension...") {
+	NATURALVAR (dimension, U"Dimension", U"1")
 	OK
 DO
-	LOOP {
-		iam (Configuration);
-		Configuration_invertDimension (me,
-			GET_INTEGER (U"Dimension"));
-	}
-END
+	MODIFY_EACH (Configuration)
+		Configuration_invertDimension (me, dimension);
+	MODIFY_EACH_END
+}
 
-DIRECT (Configuration_to_Distance)
-	LOOP {
-		iam (Configuration);
-		praat_new (Configuration_to_Distance (me), my name);
-	}
-END
+DIRECT (NEW_Configuration_to_Distance) {
+	CONVERT_EACH (Configuration)
+		autoDistance result = Configuration_to_Distance (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Configuration_varimax, U"Configuration: To Configuration (varimax)", U"Configuration: To Configuration (varimax)...")
-	BOOLEAN (U"Normalize rows", true)
-	BOOLEAN (U"Quartimax", false)
-	NATURAL (U"Maximum number of iterations", U"50")
-	POSITIVE (U"Tolerance", U"1e-6")
+FORM (NEW_Configuration_varimax, U"Configuration: To Configuration (varimax)", U"Configuration: To Configuration (varimax)...") {
+	BOOLEANVAR (normalizeRows, U"Normalize rows", true)
+	BOOLEANVAR (useQuartimax, U"Quartimax", false)
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"50")
+	POSITIVEVAR (tolerance, U"Tolerance", U"1e-6")
 	OK
 DO
-	LOOP {
-		iam (Configuration);
-		autoConfiguration result = Configuration_varimax (me,
-			GET_INTEGER (U"Normalize rows"),
-			GET_INTEGER (U"Quartimax"),
-			GET_INTEGER (U"Maximum number of iterations"),
-			GET_REAL (U"Tolerance"));
-		praat_new (result.move(), my name, U"_varimax");
-	}
-END
+	CONVERT_EACH (Configuration)
+		autoConfiguration result = Configuration_varimax (me, normalizeRows, useQuartimax, maximumNumberOfIterations, tolerance);
+	CONVERT_EACH_END (my name, U"_varimax")
+}
 
-DIRECT (Configurations_to_Similarity_cc)
-	autoConfigurationList list = ConfigurationList_create ();
-	LOOP {
-		iam (Configuration);
-		list -> addItem_ref (me);
-	}
-	Weight nullWeight = nullptr;
-	autoSimilarity result = ConfigurationList_to_Similarity_cc (list.get(), nullWeight);
-	praat_new (result.move(), U"congruence");
-END
+DIRECT (NEW1_Configurations_to_Similarity_cc) {
+	CONVERT_TYPED_LIST (Configuration, ConfigurationList)
+		autoSimilarity result = ConfigurationList_to_Similarity_cc (list.get(), nullptr);
+	CONVERT_TYPED_LIST_END (U"congruence")
+}
 
-FORM (Configurations_to_Procrustes, U"Configuration & Configuration: To Procrustes", U"Configuration & Configuration: To Procrustes...")
-	BOOLEAN (U"Orthogonal transform", false)
+FORM (NEW1_Configurations_to_Procrustes, U"Configuration & Configuration: To Procrustes", U"Configuration & Configuration: To Procrustes...") {
+	BOOLEANVAR (useOrthogonalTransform, U"Use orthogonal transform", false)
 	OK
 DO
-	Configuration configuration1 = nullptr;
-	Configuration configuration2 = nullptr;
-	LOOP {
-		iam (Configuration);
-		( configuration1 ? configuration2 : configuration1 ) = me;
-	}
-	Melder_assert (configuration1 && configuration2);
-	autoProcrustes result = Configurations_to_Procrustes (configuration1, configuration2,
-		GET_INTEGER (U"Orthogonal transform"));
-	praat_new (result.move(), Thing_getName (configuration2), U"_to_", Thing_getName (configuration1));
-END
+	CONVERT_COUPLE (Configuration)
+		autoProcrustes result = Configurations_to_Procrustes (me, you, useOrthogonalTransform);
+	CONVERT_COUPLE_END (your name, U"_to_", my name)
+}
 
-FORM (Configurations_to_AffineTransform_congruence, U"Configurations: To AffineTransform (congruence)", U"Configurations: To AffineTransform (congruence)...")
-	NATURAL (U"Maximum number of iterations", U"50")
-	POSITIVE (U"Tolerance", U"1e-6")
+FORM (NEW1_Configurations_to_AffineTransform_congruence, U"Configurations: To AffineTransform (congruence)", U"Configurations: To AffineTransform (congruence)...") {
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"50")
+	POSITIVEVAR (tolerance, U"Tolerance", U"1e-6")
 	OK
 DO
-	Configuration configuration1 = nullptr;
-	Configuration configuration2 = nullptr;
-	LOOP {
-		iam (Configuration);
-		( configuration1 ? configuration2 : configuration1 ) = me;
-	}
-	Melder_assert (configuration1 && configuration2);
-	autoAffineTransform result = Configurations_to_AffineTransform_congruence (configuration1, configuration2,
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_REAL (U"Tolerance"));
-	praat_new (result.move(), configuration1 -> name, U"_", configuration2 -> name);
-END
-
-DIRECT (Configuration_Weight_to_Similarity_cc)
-	autoConfigurationList configurations = ConfigurationList_create ();
-	Weight weight = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classConfiguration) {
-			configurations -> addItem_ref ((Configuration) me);
-		} else if (CLASS == classWeight) {
-			weight = (Weight) me;
-		}
-	}
-	Melder_assert (configurations->size > 0 && weight);
-	autoSimilarity result = ConfigurationList_to_Similarity_cc (configurations.get(), weight);
-	praat_new (result.move(), U"congruence");
-END
-
-DIRECT (Configuration_and_AffineTransform_to_Configuration)
-	Configuration me = FIRST (Configuration);
-	AffineTransform thee = FIRST_GENERIC (AffineTransform);
-	autoConfiguration result = Configuration_and_AffineTransform_to_Configuration (me, thee);
-	praat_new (result.move(), my name, U"_", thy name);
-END
+	CONVERT_COUPLE (Configuration)
+		autoAffineTransform result = Configurations_to_AffineTransform_congruence (me, you, maximumNumberOfIterations, tolerance);
+	CONVERT_COUPLE_END (your name, U"_to_", my name)
+}
+
+DIRECT (NEW1_Configuration_Weight_to_Similarity_cc) {
+	CONVERT_ONE_AND_TYPED_LIST (Weight, Configuration, ConfigurationList)
+		autoSimilarity result = ConfigurationList_to_Similarity_cc (list.get(), me);
+	CONVERT_ONE_AND_TYPED_LIST_END (U"congruence")
+}
+
+DIRECT (NEW1_Configuration_and_AffineTransform_to_Configuration) {
+	CONVERT_TWO (Configuration, AffineTransform)
+		autoConfiguration result = Configuration_and_AffineTransform_to_Configuration (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
+
+DIRECT (NEW1_Configuration_and_Procrustes_to_Configuration) {
+	CONVERT_TWO (Configuration, Procrustes)
+		autoConfiguration result = Configuration_and_AffineTransform_to_Configuration (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
 /*************** Confusion *********************************/
 
-FORM (Confusion_to_Dissimilarity_pdf, U"Confusion: To Dissimilarity (pdf)", U"Confusion: To Dissimilarity (pdf)...")
-	POSITIVE (U"Minimum confusion level", U"0.5")
+FORM (NEW_Confusion_to_Dissimilarity_pdf, U"Confusion: To Dissimilarity (pdf)", U"Confusion: To Dissimilarity (pdf)...") {
+	POSITIVEVAR (minimumConfusionLevel, U"Minimum confusion level", U"0.5")
 	OK
 DO
-	LOOP {
-		iam (Confusion);
-		autoDissimilarity result = Confusion_to_Dissimilarity_pdf (me,
-			GET_REAL (U"Minimum confusion level"));
-		praat_new (result.move(), my name, U"_pdf");
-	}
-END
+	CONVERT_EACH (Confusion)
+		autoDissimilarity result = Confusion_to_Dissimilarity_pdf (me, minimumConfusionLevel);
+	CONVERT_EACH_END (my name, U"_pdf")
+}
 
-FORM (Confusion_to_Similarity, U"Confusion: To Similarity", U"Confusion: To Similarity...")
-	BOOLEAN (U"Normalize", true)
-	RADIO (U"Symmetrization", 1)
+FORM (NEW_Confusion_to_Similarity, U"Confusion: To Similarity", U"Confusion: To Similarity...") {
+	BOOLEANVAR (normalize, U"Normalize", true)
+	RADIOVAR (symmetrizeMethod, U"Symmetrization", 1)
 		RADIOBUTTON (U"No symmetrization")
 		RADIOBUTTON (U"Average (s[i][j] = (c[i][j]+c[j][i])/2)")
 		RADIOBUTTON (U"Houtgast (s[i][j]= sum (min(c[i][k],c[j][k])))")
 	OK
 DO
-	LOOP {
-		iam (Confusion);
-		autoSimilarity result = Confusion_to_Similarity (me,
-			GET_INTEGER (U"Normalize"),
-			GET_INTEGER (U"Symmetrization"));
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH (Confusion)
+		autoSimilarity result = Confusion_to_Similarity (me, normalize, symmetrizeMethod);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Confusions_sum)
-	autoConfusionList confusions = ConfusionList_create ();
-	LOOP {
-		iam (Confusion);
-		confusions -> addItem_ref (me);
-	}
-	autoConfusion result = ConfusionList_sum (confusions.get());
-	praat_new (result.move(), U"sum");
-END
+DIRECT (NEW1_Confusions_sum) {
+	CONVERT_TYPED_LIST (Confusion, ConfusionList)
+		autoConfusion result = ConfusionList_sum (list.get());
+	CONVERT_TYPED_LIST_END (U"sum")
+}
 
-DIRECT (Confusion_to_ContingencyTable)
-	LOOP {
-		iam (Confusion);
+DIRECT (NEW_Confusion_to_ContingencyTable) {
+	CONVERT_EACH (Confusion)
 		autoContingencyTable result = Confusion_to_ContingencyTable (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
 /*************** ContingencyTable *********************************/
 
 
-FORM (ContingencyTable_to_Configuration_ca, U"ContingencyTable: To Configuration (ca)", U"ContingencyTable: To Configuration (ca)...")
-	NATURAL (U"Number of dimensions", U"2")
-	RADIO (U"Scaling of final configuration", 3)
+FORM (NEW_ContingencyTable_to_Configuration_ca, U"ContingencyTable: To Configuration (ca)", U"ContingencyTable: To Configuration (ca)...") {
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	RADIOVAR (scalingType, U"Scaling of final configuration", 3)
 		RADIOBUTTON (U"Row points in centre of gravity of column points")
 		RADIOBUTTON (U"Column points in centre of gravity of row points")
 		RADIOBUTTON (U"Row points and column points symmetric")
 	OK
 DO
-	LOOP {
-		iam (ContingencyTable);
-		praat_new (ContingencyTable_to_Configuration_ca (me, GET_INTEGER (U"Number of dimensions"),
-			GET_INTEGER (U"Scaling of final configuration")), my name);
-	}
-END
+	CONVERT_EACH (ContingencyTable)
+		autoConfiguration result = ContingencyTable_to_Configuration_ca (me, numberOfDimensions, scalingType);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (ContingencyTable_chisqProbability)
-	LOOP {
-		iam (ContingencyTable);
-		Melder_information (ContingencyTable_chisqProbability (me));
-	}
-END
+DIRECT (REAL_ContingencyTable_chisqProbability) {
+	NUMBER_ONE (ContingencyTable)
+		double result = ContingencyTable_chisqProbability (me);
+	NUMBER_ONE_END (U"(probability)")
+}
 
-DIRECT (ContingencyTable_cramersStatistic)
-	LOOP {
-		iam (ContingencyTable);
-		Melder_information (ContingencyTable_cramersStatistic (me));
-	}
-END
+DIRECT (REAL_ContingencyTable_cramersStatistic) {
+	NUMBER_ONE (ContingencyTable)
+		double result = ContingencyTable_cramersStatistic (me);
+	NUMBER_ONE_END (U"(cramer)")
+}
 
-DIRECT (ContingencyTable_contingencyCoefficient)
-	LOOP {
-		iam (ContingencyTable);
-		Melder_information (ContingencyTable_contingencyCoefficient (me));
-	}
-END
+DIRECT (REAL_ContingencyTable_contingencyCoefficient) {
+	NUMBER_ONE (ContingencyTable)
+		double result = ContingencyTable_contingencyCoefficient (me);
+	NUMBER_ONE_END (U"(contingency coefficient)")
+}
 
 /************************* Correlation ***********************************/
 
-FORM (Correlation_to_Configuration, U"Correlation: To Configuration", 0)
-	NATURAL (U"Number of dimensions", U"2")
+FORM (NEW_Correlation_to_Configuration, U"Correlation: To Configuration", nullptr) {
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
 	OK
 DO
-	LOOP {
-		iam (Correlation);
-		autoConfiguration result = Correlation_to_Configuration (me,
-			GET_INTEGER (U"Number of dimensions"));
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH (Correlation)
+		autoConfiguration result = Correlation_to_Configuration (me, numberOfDimensions);
+	CONVERT_EACH_END (my name)
+}
 
 
 /************************* Similarity ***************************************/
 
-DIRECT (Similarity_help)
-	Melder_help (U"Similarity");
-END
+DIRECT (HELP_Similarity_help) {
+	HELP (U"Similarity")
+}
 
-FORM (Similarity_to_Dissimilarity, U"Similarity: To Dissimilarity", U"Similarity: To Dissimilarity...")
-	REAL (U"Maximum dissimilarity", U"0.0 (= from data)")
+FORM (NEW_Similarity_to_Dissimilarity, U"Similarity: To Dissimilarity", U"Similarity: To Dissimilarity...") {
+	REALVAR (maximumDissimilarity, U"Maximum dissimilarity", U"0.0 (= from data)")
 	OK
 DO
-	LOOP {
-		iam (Similarity);
-		autoDissimilarity result = Similarity_to_Dissimilarity (me,
-			GET_REAL (U"Maximum dissimilarity"));
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH (Similarity)
+		autoDissimilarity result = Similarity_to_Dissimilarity (me, maximumDissimilarity);
+	CONVERT_EACH_END (my name)
+}
 
 /**************** Dissimilarity ***************************************/
 
-static void Dissimilarity_to_Configuration_addCommonFields (UiForm dia) {
-	LABEL (U"", U"Minimization parameters")
-	REAL (U"Tolerance", U"1e-5")
-	NATURAL (U"Maximum number of iterations", U"50 (= each repetition)")
-	NATURAL (U"Number of repetitions", U"1")
-}
+#define praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions) \
+	LABEL (U"", U"Minimization parameters") \
+	REALVAR (tolerance, U"Tolerance", U"1e-5") \
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"50 (= each repetition)") \
+	NATURALVAR (numberOfRepetitions, U"Number of repetitions", U"1")
+
 
-static void Dissimilarity_and_Configuration_getStress_addCommonFields (UiForm dia, UiField radio) {
-	RADIO (U"Stress measure", 1)
-		RADIOBUTTON (U"Normalized")
-		RADIOBUTTON (U"Kruskal's stress-1")
-		RADIOBUTTON (U"Kruskal's stress-2")
+#define Dissimilarity_and_Configuration_getStress_addCommonFields(stressMeasure) \
+	RADIOVAR (stressMeasure, U"Stress measure", 1) \
+		RADIOBUTTON (U"Normalized") \
+		RADIOBUTTON (U"Kruskal's stress-1") \
+		RADIOBUTTON (U"Kruskal's stress-2") \
 		RADIOBUTTON (U"Raw")
-}
 
-static void Dissimilarity_Configuration_drawDiagram_addCommonFields (UiForm dia) {
-	REAL (U"left Proximity range", U"0.0")
-	REAL (U"right Proximity range", U"0.0")
-	REAL (U"left Distance range", U"0.0")
-	REAL (U"right Distance range", U"0.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Garnish", true)
+#define praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish) \
+	REALVAR (fromProximity, U"left Proximity range", U"0.0") \
+	REALVAR (toProximity, U"right Proximity range", U"0.0") \
+	REALVAR (fromDistance, U"left Distance range", U"0.0") \
+	REALVAR (toDistance, U"right Distance range", U"0.0") \
+	POSITIVEVAR (markSize, U"Mark size (mm)", U"1.0") \
+	SENTENCEVAR (markString, U"Mark string (+xo.)", U"+") \
+	BOOLEANVAR (garnish, U"Garnish", true)
+
+DIRECT (HELP_Dissimilarity_help) {
+	HELP (U"Dissimilarity")
 }
 
-DIRECT (Dissimilarity_help)
-	Melder_help (U"Dissimilarity");
-END
-
-DIRECT (Dissimilarity_getAdditiveConstant)
+DIRECT (REAL_Dissimilarity_getAdditiveConstant) {
 	LOOP {
 		iam (Dissimilarity);
 		double c = Dissimilarity_getAdditiveConstant (me);
 		Melder_information (c);
 	}
-END
+END }
 
-FORM (Dissimilarity_Configuration_kruskal, U"Dissimilarity & Configuration: To Configuration (kruskal)", U"Dissimilarity & Configuration: To Configuration (kruskal)...")
-	RADIO (U"Handling of ties", 1)
+FORM (NEW1_Dissimilarity_Configuration_kruskal, U"Dissimilarity & Configuration: To Configuration (kruskal)", U"Dissimilarity & Configuration: To Configuration (kruskal)...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
 		RADIOBUTTON (U"Primary approach")
 		RADIOBUTTON (U"Secondary approach")
-	RADIO (U"Stress calculation", 1)
+	RADIOVAR (stressFormula, U"Stress calculation", 1)
 		RADIOBUTTON (U"Formula1")
 		RADIOBUTTON (U"Formula2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	autoConfiguration result = Dissimilarity_Configuration_kruskal (me, thee,
-		GET_INTEGER (U"Handling of ties"),
-		GET_INTEGER (U"Stress calculation"),
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"));
-	praat_new (result.move(), my name, U"_kruskal");
-END
-
-FORM (Dissimilarity_Configuration_absolute_mds, U"Dissimilarity & Configuration: To Configuration (absolute mds)", U"Dissimilarity & Configuration: To Configuration (absolute mds)...")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_absolute_mds (me, thee, nullptr,
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), my name, U"_absolute");
-END
-
-FORM (Dissimilarity_Configuration_ratio_mds, U"Dissimilarity & Configuration: To Configuration (ratio mds)", U"Dissimilarity & Configuration: To Configuration (ratio mds)...")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_ratio_mds (me, thee, nullptr,
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), my name, U"_ratio");
-END
-
-FORM (Dissimilarity_Configuration_interval_mds, U"Dissimilarity & Configuration: To Configuration (interval mds)", U"Dissimilarity & Configuration: To Configuration (interval mds)...")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_interval_mds (me, thee, nullptr,
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), my name, U"_interval");
-END
-
-FORM (Dissimilarity_Configuration_monotone_mds, U"Dissimilarity & Configuration: To Configuration (monotone mds)", U"Dissimilarity & Configuration: To Configuration (monotone mds)...")
-	RADIO (U"Handling of ties", 1)
-	RADIOBUTTON (U"Primary approach")
-	RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_monotone_mds (me, thee, nullptr,
-		GET_INTEGER (U"Handling of ties"),
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), my name, U"_monotone");
-END
-
-FORM (Dissimilarity_Configuration_ispline_mds, U"Dissimilarity & Configuration: To Configuration (i-spline mds)", U"Dissimilarity & Configuration: To Configuration (i-spline mds)...")
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_TWO (Dissimilarity, Configuration)
+		autoConfiguration result = Dissimilarity_Configuration_kruskal (me, you, tiesHandling, stressFormula, tolerance, maximumNumberOfIterations, numberOfRepetitions);
+	CONVERT_TWO_END (my name, U"_kruskal")
+}
+
+FORM (NEW1_Dissimilarity_Configuration_absolute_mds, U"Dissimilarity & Configuration: To Configuration (absolute mds)", U"Dissimilarity & Configuration: To Configuration (absolute mds)...") {
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_TWO (Dissimilarity, Configuration)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_absolute_mds (me, you, nullptr, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_absolute");
+}
+
+FORM (NEW1_Dissimilarity_Configuration_ratio_mds, U"Dissimilarity & Configuration: To Configuration (ratio mds)", U"Dissimilarity & Configuration: To Configuration (ratio mds)...") {
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_TWO (Dissimilarity, Configuration)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_ratio_mds (me, you, nullptr, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_ratio");
+}
+
+FORM (NEW1_Dissimilarity_Configuration_interval_mds, U"Dissimilarity & Configuration: To Configuration (interval mds)", U"Dissimilarity & Configuration: To Configuration (interval mds)...") {
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_TWO (Dissimilarity, Configuration)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_interval_mds (me, you, nullptr, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_interval");
+}
+
+FORM (NEW1_Dissimilarity_Configuration_monotone_mds, U"Dissimilarity & Configuration: To Configuration (monotone mds)", U"Dissimilarity & Configuration: To Configuration (monotone mds)...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
+		RADIOBUTTON (U"Primary approach")
+		RADIOBUTTON (U"Secondary approach")
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_TWO (Dissimilarity, Configuration)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_monotone_mds (me, you, nullptr, tiesHandling, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_monotone");
+}
+
+FORM (NEW1_Dissimilarity_Configuration_ispline_mds, U"Dissimilarity & Configuration: To Configuration (i-spline mds)", U"Dissimilarity & Configuration: To Configuration (i-spline mds)...") {
 	LABEL (U"", U"Spline smoothing")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"1")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_ispline_mds (me, thee, nullptr,
-		GET_INTEGER (U"Number of interior knots"),
-		GET_INTEGER (U"Order of I-spline"),
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), my name, U"_ispline");
-END
-
-FORM (Dissimilarity_Configuration_Weight_absolute_mds, U"Dissimilarity & Configuration & Weight: To Configuration (absolute mds)", U"Dissimilarity & Configuration & Weight: To Configuration...")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_absolute_mds (dissimilarity, configuration, weight,
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), dissimilarity -> name, U"_w_absolute");
-END
-
-FORM (Dissimilarity_Configuration_Weight_ratio_mds, U"Dissimilarity & Configuration & Weight: To Configuration (ratio mds)", U"Dissimilarity & Configuration & Weight: To Configuration...")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_ratio_mds (dissimilarity, configuration, weight,
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), dissimilarity -> name, U"_w_ratio");
-END
-
-FORM (Dissimilarity_Configuration_Weight_interval_mds, U"Dissimilarity & Configuration & Weight: To Configuration (interval mds)", U"Dissimilarity & Configuration & Weight: To Configuration...")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	bool showProgress = true;
-	autoConfiguration result = Dissimilarity_Configuration_Weight_interval_mds (dissimilarity, configuration, weight,
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		showProgress);
-	praat_new (result.move(), dissimilarity -> name, U"_w_interval");
-END
-
-FORM (Dissimilarity_Configuration_Weight_monotone_mds,
-      U"Dissimilarity & Configuration & Weight: To Configuration (monotone mds)",
-      U"Dissimilarity & Configuration & Weight: To Configuration...")
-	RADIO (U"Handling of ties", 1)
-	RADIOBUTTON (U"Primary approach")
-	RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	bool showProgress = true;
-	praat_new (Dissimilarity_Configuration_Weight_monotone_mds (dissimilarity, configuration, weight,
-			GET_INTEGER (U"Handling of ties"),
-			GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"),
-			showProgress),
-		dissimilarity -> name, U"_sw_monotone");
-END
-
-FORM (Dissimilarity_Configuration_Weight_ispline_mds,
-      U"Dissimilarity & Configuration & Weight: To Configuration (i-spline mds)",
-      U"Dissimilarity & Configuration & Weight: To Configuration...")
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"1")
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_TWO (Dissimilarity, Configuration)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_ispline_mds (me, you, nullptr, numberOfInteriorKnots, order, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_ispline");
+}
+
+FORM (NEW1_Dissimilarity_Configuration_Weight_absolute_mds, U"Dissimilarity & Configuration & Weight: To Configuration (absolute mds)", U"Dissimilarity & Configuration & Weight: To Configuration...") {
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_THREE (Dissimilarity, Configuration, Weight)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_absolute_mds (me, you, him, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_THREE_END (my name, U"_w_absolute")
+}
+
+FORM (NEW1_Dissimilarity_Configuration_Weight_ratio_mds, U"Dissimilarity & Configuration & Weight: To Configuration (ratio mds)", U"Dissimilarity & Configuration & Weight: To Configuration...") {
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_THREE (Dissimilarity, Configuration, Weight)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_ratio_mds (me, you, him, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_THREE_END (my name, U"_w_ratio");
+}
+
+FORM (NEW1_Dissimilarity_Configuration_Weight_interval_mds, U"Dissimilarity & Configuration & Weight: To Configuration (interval mds)", U"Dissimilarity & Configuration & Weight: To Configuration...") {
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_THREE (Dissimilarity, Configuration, Weight)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_interval_mds (me, you, him, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_THREE_END (my name, U"_w_interval")
+}
+
+FORM (NEW1_Dissimilarity_Configuration_Weight_monotone_mds, U"Dissimilarity & Configuration & Weight: To Configuration (monotone mds)", U"Dissimilarity & Configuration & Weight: To Configuration...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
+		RADIOBUTTON (U"Primary approach")
+		RADIOBUTTON (U"Secondary approach")
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_THREE (Dissimilarity, Configuration, Weight)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_monotone_mds (me, you, him, tiesHandling, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_THREE_END (my name, U"_sw_monotone")
+}
+
+FORM (NEW1_Dissimilarity_Configuration_Weight_ispline_mds,  U"Dissimilarity & Configuration & Weight: To Configuration (i-spline mds)", U"Dissimilarity & Configuration & Weight: To Configuration...") {
 	LABEL (U"", U"Spline smoothing")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"1")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	bool showProgress = true;
-	praat_new (Dissimilarity_Configuration_Weight_ispline_mds (dissimilarity, configuration, weight,
-			GET_INTEGER (U"Number of interior knots"),
-			GET_INTEGER (U"Order of I-spline"),
-			GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"),
-			showProgress),
-		dissimilarity -> name, U"_sw_ispline");
-END
-
-FORM (Dissimilarity_Configuration_getStress, U"Dissimilarity & Configuration: Get stress",
-      U"Dissimilarity & Configuration: get stress")
-	RADIO (U"Handling of ties", 1)
-	RADIOBUTTON (U"Primary approach")
-	RADIOBUTTON (U"Secondary approach")
-	RADIO (U"Stress calculation", 1)
-	RADIOBUTTON (U"Formula1")
-	RADIOBUTTON (U"Formula2")
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Melder_information (Dissimilarity_Configuration_getStress (me, thee,
-		GET_INTEGER (U"Handling of ties"), GET_INTEGER (U"Stress calculation")));
-END
-
-FORM (Dissimilarity_Configuration_absolute_stress,
-      U"Dissimilarity & Configuration: Get stress (absolute mds)",
-      U"Dissimilarity & Configuration: Get stress (absolute mds)...")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Melder_information (Dissimilarity_Configuration_Weight_absolute_stress (me, thee, nullptr,
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_ratio_stress, U"Dissimilarity & Configuration: Get stress (ratio mds)",
-      U"Dissimilarity & Configuration: Get stress (ratio mds)...")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Melder_information (Dissimilarity_Configuration_Weight_ratio_stress (me, thee, nullptr,
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_interval_stress,
-      U"Dissimilarity & Configuration: Get stress (interval mds)",
-      U"Dissimilarity & Configuration: Get stress (interval mds)...")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Melder_information (Dissimilarity_Configuration_Weight_interval_stress (me, thee, nullptr,
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_monotone_stress,
-      U"Dissimilarity & Configuration: Get stress (monotone mds)",
-      U"Dissimilarity & Configuration: Get stress (monotone mds)...")
-	RADIO (U"Handling of ties", 1)
-	RADIOBUTTON (U"Primary approach")
-	RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Melder_information (Dissimilarity_Configuration_Weight_monotone_stress (me, thee, nullptr,
-		GET_INTEGER (U"Handling of ties"),
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_ispline_stress,
-      U"Dissimilarity & Configuration: Get stress (i-spline mds)",
-      U"Dissimilarity & Configuration: Get stress (i-spline mds)...")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"3")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Melder_information (Dissimilarity_Configuration_Weight_ispline_stress (me, thee, nullptr,
-		GET_INTEGER (U"Number of interior knots"),
-		GET_INTEGER (U"Order of I-spline"),
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_Weight_absolute_stress,
-      U"Dissimilarity & Configuration & Weight: Get stress (absolute mds)",
-      U"Dissimilarity & Configuration & Weight: Get stress (absolute mds)...")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	Melder_information (Dissimilarity_Configuration_Weight_absolute_stress (dissimilarity, configuration, weight,
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_Weight_ratio_stress,
-      U"Dissimilarity & Configuration & Weight: Get stress (ratio mds)",
-      U"Dissimilarity & Configuration & Weight: Get stress (ratio mds)...")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	Melder_information (Dissimilarity_Configuration_Weight_ratio_stress (dissimilarity, configuration, weight,
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_Weight_interval_stress,
-      U"Dissimilarity & Configuration & Weight: Get stress (interval mds)",
-      U"Dissimilarity & Configuration & Weight: Get stress (interval mds)...")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	Melder_information (Dissimilarity_Configuration_Weight_interval_stress (dissimilarity, configuration, weight,
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_Weight_monotone_stress,
-      U"Dissimilarity & Configuration & Weight: Get stress (monotone mds)",
-      U"Dissimilarity & Configuration & Weight: Get stress (monotone mds)...")
-	RADIO (U"Handling of ties", 1)
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"1")
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance,maximumNumberOfIterations,numberOfRepetitions)
+	OK
+DO
+	CONVERT_THREE (Dissimilarity, Configuration, Weight)
+		bool showProgress = true;
+		autoConfiguration result = Dissimilarity_Configuration_Weight_ispline_mds (me, you, him, numberOfInteriorKnots, order, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_THREE_END (my name, U"_sw_ispline");
+}
+
+FORM (REAL_Dissimilarity_Configuration_getStress, U"Dissimilarity & Configuration: Get stress",  U"Dissimilarity & Configuration: get stress") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
+		RADIOBUTTON (U"Primary approach")
+		RADIOBUTTON (U"Secondary approach")
+	RADIOVAR (stressFormula, U"Stress calculation", 1)
+		RADIOBUTTON (U"Formula1")
+		RADIOBUTTON (U"Formula2")
+	OK
+DO
+	NUMBER_TWO (Dissimilarity, Configuration)
+		double result = Dissimilarity_Configuration_getStress (me, you, tiesHandling, stressFormula);
+	NUMBER_TWO_END (U"(stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_absolute_stress, U"Dissimilarity & Configuration: Get stress (absolute mds)", U"Dissimilarity & Configuration: Get stress (absolute mds)...") {
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_TWO (Dissimilarity, Configuration)
+		double result = Dissimilarity_Configuration_Weight_absolute_stress (me, you, nullptr,stressMeasure);
+	NUMBER_TWO_END (U"(absolute mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_ratio_stress, U"Dissimilarity & Configuration: Get stress (ratio mds)", U"Dissimilarity & Configuration: Get stress (ratio mds)...") {
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_TWO (Dissimilarity, Configuration)
+		double result = Dissimilarity_Configuration_Weight_ratio_stress (me, you, nullptr, stressMeasure);
+	NUMBER_TWO_END (U"(ratio mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_interval_stress, U"Dissimilarity & Configuration: Get stress (interval mds)", U"Dissimilarity & Configuration: Get stress (interval mds)...") {
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_TWO (Dissimilarity, Configuration)
+		double result = Dissimilarity_Configuration_Weight_interval_stress (me, you, nullptr, stressMeasure);
+	NUMBER_TWO_END (U"(interval mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_monotone_stress, U"Dissimilarity & Configuration: Get stress (monotone mds)", U"Dissimilarity & Configuration: Get stress (monotone mds)...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
+		RADIOBUTTON (U"Primary approach")
+		RADIOBUTTON (U"Secondary approach")
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_TWO (Dissimilarity, Configuration)
+		double result = Dissimilarity_Configuration_Weight_monotone_stress (me, you, nullptr, tiesHandling,stressMeasure);
+	NUMBER_TWO_END (U"(monotone mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_ispline_stress, U"Dissimilarity & Configuration: Get stress (i-spline mds)", U"Dissimilarity & Configuration: Get stress (i-spline mds)...") {
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"3")
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_TWO (Dissimilarity, Configuration)
+		double result = Dissimilarity_Configuration_Weight_ispline_stress (me, you, nullptr, numberOfInteriorKnots, order, stressMeasure);
+	NUMBER_TWO_END (U"(i-spline mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_Weight_absolute_stress, U"Dissimilarity & Configuration & Weight: Get stress (absolute mds)", U"Dissimilarity & Configuration & Weight: Get stress (absolute mds)...") {
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_THREE (Dissimilarity, Configuration, Weight)
+		double result = Dissimilarity_Configuration_Weight_absolute_stress (me, you, him, stressMeasure);
+	NUMBER_THREE_END (U"(absolute mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_Weight_ratio_stress, U"Dissimilarity & Configuration & Weight: Get stress (ratio mds)", U"Dissimilarity & Configuration & Weight: Get stress (ratio mds)...") {
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_THREE (Dissimilarity, Configuration, Weight)
+		double result = Dissimilarity_Configuration_Weight_ratio_stress (me, you, him, stressMeasure);
+	NUMBER_THREE_END (U"(ratio mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_Weight_interval_stress, U"Dissimilarity & Configuration & Weight: Get stress (interval mds)", U"Dissimilarity & Configuration & Weight: Get stress (interval mds)...") {
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_THREE (Dissimilarity, Configuration, Weight)
+		double result = Dissimilarity_Configuration_Weight_interval_stress (me, you, him, stressMeasure);
+	NUMBER_THREE_END (U"(interval mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_Weight_monotone_stress, U"Dissimilarity & Configuration & Weight: Get stress (monotone mds)", U"Dissimilarity & Configuration & Weight: Get stress (monotone mds)...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
 		RADIOBUTTON (U"Primary approach)")
 		RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	Melder_information (Dissimilarity_Configuration_Weight_monotone_stress (dissimilarity, configuration, weight,
-		GET_INTEGER (U"Handling of ties"),
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_Weight_ispline_stress,
-      U"Dissimilarity & Configuration & Weight: Get stress (i-spline mds)",
-      U"Dissimilarity & Configuration & Weight: Get stress (i-spline mds)...")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"3")
-	Dissimilarity_and_Configuration_getStress_addCommonFields (dia, radio);
-	OK
-DO
-	Dissimilarity dissimilarity = FIRST (Dissimilarity);
-	Configuration configuration = FIRST (Configuration);
-	Weight weight = FIRST (Weight);
-	Melder_information (Dissimilarity_Configuration_Weight_ispline_stress (dissimilarity, configuration, weight,
-		GET_INTEGER (U"Number of interior knots"),
-		GET_INTEGER (U"Order of I-spline"),
-		GET_INTEGER (U"Stress measure")));
-END
-
-FORM (Dissimilarity_Configuration_drawShepardDiagram, U"Dissimilarity & Configuration: Draw Shepard diagram",
-      U"Dissimilarity & Configuration: Draw Shepard diagram...")
-	Dissimilarity_Configuration_drawDiagram_addCommonFields (dia);
-	OK
-DO
-	autoPraatPicture picture;
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Dissimilarity_Configuration_drawShepardDiagram (me, thee, GRAPHICS,
-		GET_REAL (U"left Proximity range"),
-		GET_REAL (U"right Proximity range"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Dissimilarity_Configuration_drawAbsoluteRegression,
-      U"Dissimilarity & Configuration: Draw regression (absolute mds)",
-      U"Dissimilarity & Configuration: Draw regression (absolute mds)...")
-	Dissimilarity_Configuration_drawDiagram_addCommonFields (dia);
-	OK
-DO
-	autoPraatPicture picture;
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Dissimilarity_Configuration_Weight_drawAbsoluteRegression (me, thee, nullptr, GRAPHICS,
-		GET_REAL (U"left Proximity range"),
-		GET_REAL (U"right Proximity range"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Dissimilarity_Configuration_drawRatioRegression,
-      U"Dissimilarity & Configuration: Draw regression (ratio mds)",
-      U"Dissimilarity & Configuration: Draw regression (ratio mds)...")
-	Dissimilarity_Configuration_drawDiagram_addCommonFields (dia);
-	OK
-DO
-	autoPraatPicture picture;
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Dissimilarity_Configuration_Weight_drawRatioRegression (me, thee, nullptr, GRAPHICS,
-		GET_REAL (U"left Proximity range"),
-		GET_REAL (U"right Proximity range"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Dissimilarity_Configuration_drawIntervalRegression,
-      U"Dissimilarity & Configuration: Draw regression (interval mds)",
-      U"Dissimilarity & Configuration: Draw regression (interval mds)...")
-	Dissimilarity_Configuration_drawDiagram_addCommonFields (dia);
-	OK
-DO
-	autoPraatPicture picture;
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Dissimilarity_Configuration_Weight_drawIntervalRegression (me, thee, nullptr, GRAPHICS,
-		GET_REAL (U"left Proximity range"),
-		GET_REAL (U"right Proximity range"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Dissimilarity_Configuration_drawMonotoneRegression,
-      U"Dissimilarity & Configuration: Draw regression (monotone mds)",
-      U"Dissimilarity & Configuration: Draw regression (monotone mds)...")
-	RADIO (U"Handling of ties", 1)
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_THREE (Dissimilarity, Configuration, Weight)
+		double result = Dissimilarity_Configuration_Weight_monotone_stress (me, you, him, tiesHandling, stressMeasure);
+	NUMBER_THREE_END (U"(monotone mds stress)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_Weight_ispline_stress, U"Dissimilarity & Configuration & Weight: Get stress (i-spline mds)", U"Dissimilarity & Configuration & Weight: Get stress (i-spline mds)...") {
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"3")
+	Dissimilarity_and_Configuration_getStress_addCommonFields (stressMeasure);
+	OK
+DO
+	NUMBER_THREE (Dissimilarity, Configuration, Weight)
+		double result = Dissimilarity_Configuration_Weight_ispline_stress (me, you, him, numberOfInteriorKnots, order, stressMeasure);
+	NUMBER_THREE_END (U"(i-spline mds stress)")
+}
+
+FORM (GRAPHICS_Dissimilarity_Configuration_drawShepardDiagram, U"Dissimilarity & Configuration: Draw Shepard diagram", U"Dissimilarity & Configuration: Draw Shepard diagram...") {
+	praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish)	OK
+DO
+	GRAPHICS_TWO (Dissimilarity, Configuration)
+		Dissimilarity_Configuration_drawShepardDiagram (me, you, GRAPHICS, fromProximity, toProximity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_Dissimilarity_Configuration_drawAbsoluteRegression, U"Dissimilarity & Configuration: Draw regression (absolute mds)", U"Dissimilarity & Configuration: Draw regression (absolute mds)...") {
+	praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish)	OK
+DO
+	GRAPHICS_TWO (Dissimilarity, Configuration)
+		Dissimilarity_Configuration_Weight_drawAbsoluteRegression (me, you, nullptr, GRAPHICS, fromProximity, toProximity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_Dissimilarity_Configuration_drawRatioRegression, U"Dissimilarity & Configuration: Draw regression (ratio mds)", U"Dissimilarity & Configuration: Draw regression (ratio mds)...") {
+	praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish)	OK
+DO
+	GRAPHICS_TWO (Dissimilarity, Configuration)
+		Dissimilarity_Configuration_Weight_drawRatioRegression (me, you, nullptr, GRAPHICS, fromProximity, toProximity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_Dissimilarity_Configuration_drawIntervalRegression, U"Dissimilarity & Configuration: Draw regression (interval mds)", U"Dissimilarity & Configuration: Draw regression (interval mds)...") {
+	praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish)	OK
+DO
+	GRAPHICS_TWO (Dissimilarity, Configuration)
+		Dissimilarity_Configuration_Weight_drawIntervalRegression (me, you, nullptr, GRAPHICS, fromProximity, toProximity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_Dissimilarity_Configuration_drawMonotoneRegression, U"Dissimilarity & Configuration: Draw regression (monotone mds)", U"Dissimilarity & Configuration: Draw regression (monotone mds)...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
 		RADIOBUTTON (U"Primary approach)")
 		RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_Configuration_drawDiagram_addCommonFields (dia);
-	OK
-DO
-	autoPraatPicture picture;
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Dissimilarity_Configuration_Weight_drawMonotoneRegression (me, thee, nullptr, GRAPHICS,
-		GET_INTEGER (U"Handling of ties"),
-		GET_REAL (U"left Proximity range"),
-		GET_REAL (U"right Proximity range"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Dissimilarity_Configuration_drawISplineRegression,
-      U"Dissimilarity & Configuration: Draw regression (i-spline mds)",
-      U"Dissimilarity & Configuration: Draw regression (i-spline mds)...")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"3")
-	Dissimilarity_Configuration_drawDiagram_addCommonFields (dia);
-	OK
-DO
-	autoPraatPicture picture;
-	Dissimilarity me = FIRST (Dissimilarity);
-	Configuration thee = FIRST (Configuration);
-	Dissimilarity_Configuration_Weight_drawISplineRegression (me, thee, nullptr, GRAPHICS,
-		GET_INTEGER (U"Number of interior knots"),
-		GET_INTEGER (U"Order of I-spline"),
-		GET_REAL (U"left Proximity range"),
-		GET_REAL (U"right Proximity range"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Dissimilarity_kruskal, U"Dissimilarity: To Configuration (kruskal)", U"Dissimilarity: To Configuration (kruskal)...")
+	praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish)	OK
+DO
+	GRAPHICS_TWO (Dissimilarity, Configuration)
+		Dissimilarity_Configuration_Weight_drawMonotoneRegression (me, you, nullptr, GRAPHICS, tiesHandling, fromProximity, toProximity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_Dissimilarity_Configuration_drawISplineRegression, U"Dissimilarity & Configuration: Draw regression (i-spline mds)", U"Dissimilarity & Configuration: Draw regression (i-spline mds)...") {
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"3")
+	praat_Dissimilarity_Configuration_drawing_commonFields(fromProximity,toProximity,fromDistance,toDistance,markSize,markString,garnish)	OK
+DO
+	GRAPHICS_TWO (Dissimilarity, Configuration)
+		Dissimilarity_Configuration_Weight_drawISplineRegression (me, you, nullptr, GRAPHICS, numberOfInteriorKnots, order,fromProximity, toProximity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (NEW_Dissimilarity_to_Configuration_kruskal, U"Dissimilarity: To Configuration (kruskal)", U"Dissimilarity: To Configuration (kruskal)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	NATURAL (U"Distance metric", U"2 (= Euclidean)")
-	RADIO (U"Handling of ties", 1)
-	RADIOBUTTON (U"Primary approach")
-	RADIOBUTTON (U"Secondary approach")
-	RADIO (U"Stress calculation", 1)
-	RADIOBUTTON (U"Formula1")
-	RADIOBUTTON (U"Formula2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	NATURALVAR (distanceMetric, U"Distance metric", U"2 (= Euclidean)")
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
+		RADIOBUTTON (U"Primary approach")
+		RADIOBUTTON (U"Secondary approach")
+	RADIOVAR (stressFormula, U"Stress calculation", 1)
+		RADIOBUTTON (U"Formula1")
+		RADIOBUTTON (U"Formula2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	LOOP {
-		iam (Dissimilarity);
-		praat_new (Dissimilarity_kruskal (me,
-			GET_INTEGER (U"Number of dimensions"),
-			GET_INTEGER (U"Distance metric"),
-			GET_INTEGER (U"Handling of ties"),
-			GET_INTEGER (U"Stress calculation"),
-			GET_REAL (U"Tolerance"),
-			GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions")), my name);
-	}
-END
+	CONVERT_EACH (Dissimilarity)
+		autoConfiguration result = Dissimilarity_to_Configuration_kruskal (me, numberOfDimensions, distanceMetric, tiesHandling, stressFormula, tolerance, maximumNumberOfIterations, numberOfRepetitions);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Dissimilarity_absolute_mds, U"Dissimilarity: To Configuration (absolute mds)",
-      U"Dissimilarity: To Configuration (absolute mds)...")
+FORM (NEW_Dissimilarity_to_Configuration_absolute_mds, U"Dissimilarity: To Configuration (absolute mds)", U"Dissimilarity: To Configuration (absolute mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	LOOP {
-		iam (Dissimilarity);
+	CONVERT_EACH (Dissimilarity)
 		int showProgress = 1;
-		praat_new (Dissimilarity_Weight_absolute_mds (me, nullptr, GET_INTEGER (U"Number of dimensions"),
-			GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_absolute");
-	}
-END
+		autoConfiguration result = Dissimilarity_Weight_absolute_mds (me, nullptr, numberOfDimensions, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress); 
+	CONVERT_EACH_END (my name, U"_absolute")
+}
 
-FORM (Dissimilarity_ratio_mds, U"Dissimilarity: To Configuration (ratio mds)",
-      U"Dissimilarity: To Configuration (ratio mds)...")
+FORM (NEW_Dissimilarity_to_Configuration_ratio_mds, U"Dissimilarity: To Configuration (ratio mds)", U"Dissimilarity: To Configuration (ratio mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	LOOP {
-		iam (Dissimilarity);
+	CONVERT_EACH (Dissimilarity)
 		int showProgress = 1;
-		praat_new (Dissimilarity_Weight_ratio_mds (me, 0, GET_INTEGER (U"Number of dimensions"),
-			GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_ratio");
-	}
-END
+		autoConfiguration result = Dissimilarity_Weight_ratio_mds (me, nullptr, numberOfDimensions, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_EACH_END (my name, U"_ratio")
+}
 
-FORM (Dissimilarity_interval_mds, U"Dissimilarity: To Configuration (interval mds)",
-      U"Dissimilarity: To Configuration (interval mds)...")
+FORM (NEW_Dissimilarity_to_Configuration_interval_mds, U"Dissimilarity: To Configuration (interval mds)", U"Dissimilarity: To Configuration (interval mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	LOOP {
-		iam (Dissimilarity);
+	CONVERT_EACH (Dissimilarity)
 		int showProgress = 1;
-		praat_new (Dissimilarity_Weight_interval_mds (me, 0, GET_INTEGER (U"Number of dimensions"),
-			GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_interval");
-	}
-END
+		autoConfiguration result = Dissimilarity_Weight_interval_mds (me, nullptr, numberOfDimensions, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_EACH_END (my name, U"_interval")
+}
 
-FORM (Dissimilarity_monotone_mds, U"Dissimilarity: To Configuration (monotone mds)",
-      U"Dissimilarity: To Configuration (monotone mds)...")
+FORM (NEW_Dissimilarity_to_Configuration_monotone_mds, U"Dissimilarity: To Configuration (monotone mds)", U"Dissimilarity: To Configuration (monotone mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	RADIO (U"Handling of ties", 1)
-	RADIOBUTTON (U"Primary approach")
-	RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
+		RADIOBUTTON (U"Primary approach")
+		RADIOBUTTON (U"Secondary approach")
+	praat_Dissimilarity_to_Configuration_commonFields (tolerance, maximumNumberOfIterations, numberOfRepetitions)	
 	OK
 DO
-	LOOP {
-		iam (Dissimilarity);
+	CONVERT_EACH (Dissimilarity)
 		int showProgress = 1;
-		praat_new (Dissimilarity_Weight_monotone_mds (me, 0, GET_INTEGER (U"Number of dimensions"),
-			GET_INTEGER (U"Handling of ties"),
-			GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_monotone");
-	}
-END
+		autoConfiguration result = Dissimilarity_Weight_monotone_mds (me, nullptr, numberOfDimensions, tiesHandling, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_EACH_END (my name, U"_monotone");
+}
 
-FORM (Dissimilarity_ispline_mds, U"Dissimilarity: To Configuration (i-spline mds)",
-      U"Dissimilarity: To Configuration (i-spline mds)...")
+FORM (NEW_Dissimilarity_to_Configuration_ispline_mds, U"Dissimilarity: To Configuration (i-spline mds)", U"Dissimilarity: To Configuration (i-spline mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
 	LABEL (U"", U"Spline smoothing")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"1")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"1")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	long niknots = GET_INTEGER (U"Number of interior knots");
-	long order = GET_INTEGER (U"Order of I-spline");
-	if (not (order > 0 || niknots > 0)) {
+	if (not (order > 0 || numberOfInteriorKnots > 0)) {
 		Melder_throw (U"Order-zero spline must at least have 1 interior knot.");
 	}
-	LOOP {
-		iam (Dissimilarity);
+	CONVERT_EACH (Dissimilarity)
 		int showProgress = 1;
-		praat_new (Dissimilarity_Weight_ispline_mds (me, 0, GET_INTEGER (U"Number of dimensions"), niknots, order,
-			GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-			GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_ispline");
-	}
-END
+		autoConfiguration result = Dissimilarity_Weight_ispline_mds (me, nullptr, numberOfDimensions, numberOfInteriorKnots, order, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_EACH_END (my name, U"_ispline");
+}
 
-FORM (Dissimilarity_Weight_ispline_mds, U"Dissimilarity & Weight: To Configuration (i-spline mds)",
-      U"Dissimilarity & Weight: To Configuration (i-spline mds)...")
+FORM (NEW1_Dissimilarity_Weight_ispline_mds, U"Dissimilarity & Weight: To Configuration (i-spline mds)", U"Dissimilarity & Weight: To Configuration (i-spline mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
 	LABEL (U"", U"Spline smoothing")
-	INTEGER (U"Number of interior knots", U"1")
-	INTEGER (U"Order of I-spline", U"1")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	INTEGERVAR (numberOfInteriorKnots, U"Number of interior knots", U"1")
+	INTEGERVAR (order, U"Order of I-spline", U"1")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Weight w = FIRST (Weight);
-	int showProgress = 1;
-	long niknots = GET_INTEGER (U"Number of interior knots");
-	long order = GET_INTEGER (U"Order of I-spline");
-	if (not (order > 0 || niknots > 0)) {
-		Melder_throw (U"Order-zero spline must at least have 1 interior knot.");
-	}
-	praat_new (Dissimilarity_Weight_ispline_mds (me, w, GET_INTEGER (U"Number of dimensions"), niknots, order,
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_ispline");
-END
+	CONVERT_TWO (Dissimilarity, Weight)
+		int showProgress = 1;
+		if (not (order > 0 || numberOfInteriorKnots > 0)) {
+			Melder_throw (U"Order-zero spline must at least have 1 interior knot.");
+		}
+		autoConfiguration result = Dissimilarity_Weight_ispline_mds (me, you, numberOfDimensions, numberOfInteriorKnots, order, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_ispline")
+}
 
-FORM (Dissimilarity_Weight_absolute_mds, U"Dissimilarity & Weight: To Configuration (absolute mds)",
-      U"Dissimilarity & Weight: To Configuration (absolute mds)...")
+FORM (NEW1_Dissimilarity_Weight_absolute_mds, U"Dissimilarity & Weight: To Configuration (absolute mds)", U"Dissimilarity & Weight: To Configuration (absolute mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Weight w = FIRST (Weight);
-	int showProgress = 1;
-	praat_new (Dissimilarity_Weight_absolute_mds (me, w, GET_INTEGER (U"Number of dimensions"),
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_absolute");
-END
+	CONVERT_TWO (Dissimilarity, Weight)
+		int showProgress = 1;
+		autoConfiguration result = Dissimilarity_Weight_absolute_mds (me, you, numberOfDimensions, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_absolute")
+}
 
-FORM (Dissimilarity_Weight_ratio_mds, U"Dissimilarity & Weight: To Configuration (ratio mds)",
-      U"Dissimilarity & Weight: To Configuration (ratio mds)...")
+FORM (NEW1_Dissimilarity_Weight_ratio_mds, U"Dissimilarity & Weight: To Configuration (ratio mds)", U"Dissimilarity & Weight: To Configuration (ratio mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Weight w = FIRST (Weight);
-	int showProgress = 1;
-	praat_new (Dissimilarity_Weight_ratio_mds (me, w, GET_INTEGER (U"Number of dimensions"),
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_absolute");
-END
+	CONVERT_TWO (Dissimilarity, Weight)
+		int showProgress = 1;
+		autoConfiguration result = Dissimilarity_Weight_ratio_mds (me, you, numberOfDimensions, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_absolute")
+}
 
-FORM (Dissimilarity_Weight_interval_mds, U"Dissimilarity & Weight: To Configuration (interval mds)",
-      U"Dissimilarity & Weight: To Configuration (interval mds)...")
+FORM (NEW1_Dissimilarity_Weight_interval_mds, U"Dissimilarity & Weight: To Configuration (interval mds)", U"Dissimilarity & Weight: To Configuration (interval mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Weight w = FIRST (Weight);
-	int showProgress = 1;
-	praat_new (Dissimilarity_Weight_interval_mds (me, w, GET_INTEGER (U"Number of dimensions"),
-		GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_absolute");
-END
+	CONVERT_TWO (Dissimilarity, Weight)
+		int showProgress = 1;
+		autoConfiguration result = Dissimilarity_Weight_interval_mds (me, you, numberOfDimensions, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_absolute")
+}
 
-FORM (Dissimilarity_Weight_monotone_mds, U"Dissimilarity & Weight: To Configuration (monotone mds)",
-      U"Dissimilarity & Weight: To Configuration (monotone mds)...")
+FORM (NEW1_Dissimilarity_Weight_monotone_mds, U"Dissimilarity & Weight: To Configuration (monotone mds)", U"Dissimilarity & Weight: To Configuration (monotone mds)...") {
 	LABEL (U"", U"Configuration")
-	NATURAL (U"Number of dimensions", U"2")
-	RADIO (U"Handling of ties", 1)
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
 		RADIOBUTTON (U"Primary approach")
 		RADIOBUTTON (U"Secondary approach")
-	Dissimilarity_to_Configuration_addCommonFields (dia);
+	praat_Dissimilarity_to_Configuration_commonFields(tolerance,maximumNumberOfIterations,numberOfRepetitions)	
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Weight w = FIRST (Weight);
-	int showProgress = 1;
-	praat_new (Dissimilarity_Weight_monotone_mds (me, w, GET_INTEGER (U"Number of dimensions"),
-		GET_INTEGER (U"Handling of ties"), GET_REAL (U"Tolerance"), GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"), showProgress), my name, U"_monotone");
-END
+	CONVERT_TWO (Dissimilarity, Weight)
+		int showProgress = 1;
+		autoConfiguration result = Dissimilarity_Weight_monotone_mds (me, you, numberOfDimensions, tiesHandling, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgress);
+	CONVERT_TWO_END (my name, U"_monotone")
+}
 
-FORM (Dissimilarity_to_Distance, U"Dissimilarity: To Distance", U"Dissimilarity: To Distance...")
-	BOOLEAN (U"Scale (additive constant)", true)
+FORM (NEW_Dissimilarity_to_Distance, U"Dissimilarity: To Distance", U"Dissimilarity: To Distance...") {
+	BOOLEANVAR (scale, U"Scale (additive constant)", true)
 	OK
 DO
-	LOOP {
-		iam (Dissimilarity);
-		praat_new (Dissimilarity_to_Distance (me, GET_INTEGER (U"Scale")), my name);
-	}
-END
+	CONVERT_EACH (Dissimilarity)
+		autoDistance result = Dissimilarity_to_Distance (me, scale);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Dissimilarity_to_Weight)
-	LOOP {
-		iam (Dissimilarity);
-		praat_new (Dissimilarity_to_Weight (me), my name);
-	}
-END
+DIRECT (NEW_Dissimilarity_to_Weight) {
+	CONVERT_EACH (Dissimilarity)
+		autoWeight result = Dissimilarity_to_Weight (me);
+	CONVERT_EACH_END (my name)
+}
 
 /************************* Distance(s) ***************************************/
 
-FORM (Distance_to_ScalarProduct, U"Distance: To ScalarProduct", U"Distance: To ScalarProduct...")
-	BOOLEAN (U"Make sum of squares equal 1.0", true)
+FORM (NEW_Distance_to_ScalarProduct, U"Distance: To ScalarProduct", U"Distance: To ScalarProduct...") {
+	BOOLEANVAR (scaleSumOfSquares, U"Make sum of squares equal 1.0", true)
 	OK
 DO
-	LOOP {
-		iam (Distance);
-		praat_new (Distance_to_ScalarProduct (me, GET_INTEGER (U"Make sum of squares equal 1.0")), my name);
-	}
-END
+	CONVERT_EACH (Distance)
+		autoScalarProduct result = Distance_to_ScalarProduct (me, scaleSumOfSquares);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (Distance_to_Dissimilarity)
-	LOOP {
-		iam (Distance);
-		praat_new (Distance_to_Dissimilarity (me), my name);
-	}
-END
+DIRECT (NEW_Distance_to_Dissimilarity) {
+	CONVERT_EACH (Distance)
+		autoDissimilarity result = Distance_to_Dissimilarity (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEWMANY_old_Distances_to_Configuration_indscal, U"Distance: To Configuration (indscal)", U"Distance: To Configuration (indscal)...") {
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
+	LABEL (U"", U"Minimization parameters")
+	REALVAR (tolerance, U"Tolerance", U"1e-5")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100 (= each repetition)")
+	NATURALVAR (numberOfRepetitions, U"Number of repetitions", U"1")
+	OK
+DO
+	FIND_LIST (Distance)
+		autoConfiguration configurationResult;
+		autoSalience salienceResult;
+		DistanceList_to_Configuration_indscal ((DistanceList) & list, numberOfDimensions, normalizeScalarProducts, tolerance, maximumNumberOfIterations, numberOfRepetitions,true /* showProgress */, & configurationResult, & salienceResult);
+		praat_new (configurationResult.move(), U"indscal");
+		praat_new (salienceResult.move(), U"indscal");
+	END 
+}
 
-FORM (Distances_indscal, U"Distance: To Configuration (indscal)", U"Distance: To Configuration (indscal)...")
-	NATURAL (U"Number of dimensions", U"2")
-	BOOLEAN (U"Normalize scalar products", true)
+FORM (NEWMANY_Distances_to_Configuration_indscal, U"Distance: To Configuration (indscal)", U"Distance: To Configuration (indscal)...") {
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
 	LABEL (U"", U"Minimization parameters")
-	REAL (U"Tolerance", U"1e-5")
-	NATURAL (U"Maximum number of iterations", U"100 (= each repetition)")
-	NATURAL (U"Number of repetitions", U"1")
+	REALVAR (tolerance, U"Tolerance", U"1e-5")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100 (= each repetition)")
+	NATURALVAR (numberOfRepetitions, U"Number of repetitions", U"1")
+	BOOLEANVAR (wantSalience, U"Want Salience", true)
+	BOOLEANVAR (showProgressInfo, U"Show progress info", false)
+	OK
+DO_ALTERNATIVE (NEWMANY_old_Distances_to_Configuration_indscal)
+	FIND_LIST (Distance)
+		autoConfiguration configurationResult;
+		autoSalience salienceResult;
+		DistanceList_to_Configuration_indscal ((DistanceList) & list, numberOfDimensions, normalizeScalarProducts, tolerance, maximumNumberOfIterations, numberOfRepetitions, showProgressInfo, & configurationResult, (wantSalience ? & salienceResult: nullptr));
+		praat_new (configurationResult.move(), U"indscal");
+		if (wantSalience) {
+			praat_new (salienceResult.move(), U"indscal");
+		}
+	END
+}
+
+FORM (GRAPHICS_Distance_and_Configuration_drawScatterDiagram, U"Distance & Configuration: Draw scatter diagram", U"Distance & Configuration: Draw scatter diagram...") {
+	REALVAR (xmin, U"Minimum x-distance", U"0.0")
+	REALVAR (xmax, U"Maximum x-distance", U"0.0")
+	REALVAR (ymin, U"Minimum y-distance", U"0.0")
+	REALVAR (ymax, U"Maximum y-distance", U"0.0")
+	POSITIVEVAR (markSize, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (markString, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	autoDistanceList distances = DistanceList_create ();
-	LOOP {
-		iam (Distance);
-		distances -> addItem_ref (me);
-	}
-	autoConfiguration configurationResult;
-	autoSalience salienceResult;
-	DistanceList_indscal (distances.get(),
-		GET_INTEGER (U"Number of dimensions"),
-		GET_INTEGER (U"Normalize scalar products"),
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		GET_INTEGER (U"Number of repetitions"),
-		true,   // showProgress
-		& configurationResult, & salienceResult);
-	praat_new (configurationResult.move(), U"indscal");
-	praat_new (salienceResult.move(), U"indscal");
-END
-
-FORM (Distance_and_Configuration_drawScatterDiagram, U"Distance & Configuration: Draw scatter diagram", U"Distance & Configuration: Draw scatter diagram...")
-	REAL (U"Minimum x-distance", U"0.0")
-	REAL (U"Maximum x-distance", U"0.0")
-	REAL (U"Minimum y-distance", U"0.0")
-	REAL (U"Maximum y-distance", U"0.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Garnish", true)
-	OK
-DO
-	autoPraatPicture picture;
-	Distance me = FIRST (Distance);
-	Configuration thee = FIRST (Configuration);
-	Distance_and_Configuration_drawScatterDiagram (me, thee, GRAPHICS,
-		GET_REAL (U"Minimum x-distance"),
-		GET_REAL (U"Maximum x-distance"),
-		GET_REAL (U"Minimum y-distance"),
-		GET_REAL (U"Maximum y-distance"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
-
-FORM (Distance_Configuration_indscal, U"Distance & Configuration: To Configuration (indscal)", U"Distance & Configuration: To Configuration (indscal)...")
-	BOOLEAN (U"Normalize scalar products", true)
+	GRAPHICS_TWO (Distance, Configuration)
+		Distance_and_Configuration_drawScatterDiagram (me, you, GRAPHICS, xmin, xmax, ymin, ymax, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
+
+FORM (NEWMANY_Distance_Configuration_indscal, U"Distance & Configuration: To Configuration (indscal)", U"Distance & Configuration: To Configuration (indscal)...") {
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
 	LABEL (U"", U"Minimization parameters")
-	REAL (U"Tolerance", U"1e-5")
-	NATURAL (U"Maximum number of iterations", U"100 (= each repetition)")
+	REALVAR (tolerance, U"Tolerance", U"1e-5")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100 (= each repetition)")
 	OK
 DO
-	autoDistanceList distances = DistanceList_create ();
-	Configuration configuration = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classDistance) {
-			distances -> addItem_ref ((Distance) me);
-		} else if (CLASS == classConfiguration) {
-			configuration = (Configuration) me;
-		}
-	}
-	Melder_assert (distances->size > 0 && configuration);
-	autoConfiguration configurationResult;
-	autoSalience salienceResult;
-	DistanceList_Configuration_indscal (distances.get(), configuration,
-		GET_INTEGER (U"Normalize scalar products"),
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		true,   // showProgress
-		& configurationResult, & salienceResult);
-	praat_new (configurationResult.move(), U"indscal");
-	praat_new (salienceResult.move(), U"indscal");
-END
-
-FORM (Distance_Configuration_vaf, U"Distance & Configuration: Get VAF", U"Distance & Configuration: Get VAF...")
-	BOOLEAN (U"Normalize scalar products", true)
-	OK
-DO
-	autoDistanceList distances = DistanceList_create ();
-	Configuration configuration = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classDistance) {
-			distances -> addItem_ref ((Distance) me);
-		} else if (CLASS == classConfiguration) {
-			configuration = (Configuration) me;
-		}
-	}
-	Melder_assert (distances->size > 0 && configuration);
-	double varianceAccountedFor;
-	DistanceList_Configuration_vaf (distances.get(), configuration,
-		GET_INTEGER (U"Normalize scalar products"),
-		& varianceAccountedFor);
-	Melder_information (varianceAccountedFor);
-END
+	FIND_ONE_AND_LIST (Configuration, Distance)
+		autoConfiguration configurationResult;
+		autoSalience salienceResult;
+		DistanceList_Configuration_indscal ((DistanceList) & list, me, normalizeScalarProducts, tolerance, maximumNumberOfIterations, true, & configurationResult, & salienceResult);
+		praat_new (configurationResult.move(), U"indscal");
+		praat_new (salienceResult.move(), U"indscal");
+	END
+}
 
-FORM (Distance_Configuration_Salience_vaf, U"Distance & Configuration & Salience: Get VAF", U"Distance & Configuration & Salience: Get VAF...")
-	BOOLEAN (U"Normalize scalar products", true)
+FORM (REAL_Distance_Configuration_vaf, U"Distance & Configuration: Get VAF", U"Distance & Configuration: Get VAF...") {
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
 	OK
 DO
-	autoDistanceList distances = DistanceList_create ();
-	Configuration configuration = nullptr;
-	Salience salience = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classDistance) {
-			distances -> addItem_ref ((Distance) me);
-		} else if (CLASS == classConfiguration) {
-			configuration = (Configuration) me;
-		} else if (CLASS == classSalience) {
-			salience = (Salience) me;
-		}
-	}
-	Melder_assert (distances->size > 0 && configuration && salience);
-	double varianceAccountedFor;
-	DistanceList_Configuration_Salience_vaf (distances.get(), configuration, salience,
-		GET_INTEGER (U"Normalize scalar products"),
-		& varianceAccountedFor);
-	Melder_information (varianceAccountedFor);
-END
-
-FORM (Dissimilarity_Configuration_Salience_vaf, U"Dissimilarity & Configuration & Salience: Get VAF",
-      U"Dissimilarity & Configuration & Salience: Get VAF...")
-	RADIO (U"Handling of ties", 1)
+	NUMBER_ONE_AND_LIST (Configuration, Distance)
+		double result;
+		DistanceList_Configuration_vaf ((DistanceList) & list, me, normalizeScalarProducts, & result);
+	NUMBER_ONE_AND_LIST_END (U" (variance accounted for)")
+}
+
+FORM (REAL_Distance_Configuration_Salience_vaf, U"Distance & Configuration & Salience: Get VAF", U"Distance & Configuration & Salience: Get VAF...") {
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
+	OK
+DO
+	NUMBER_TWO_AND_LIST (Configuration, Salience, Distance)
+		double result;
+		DistanceList_Configuration_Salience_vaf ((DistanceList) & list, me, you, normalizeScalarProducts, & result);
+	NUMBER_TWO_AND_LIST_END (U" (variance accounted for)")
+}
+
+FORM (REAL_Dissimilarity_Configuration_Salience_vaf, U"Dissimilarity & Configuration & Salience: Get VAF", U"Dissimilarity & Configuration & Salience: Get VAF...") {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
 		RADIOBUTTON (U"Primary approach")
 		RADIOBUTTON (U"Secondary approach")
-	BOOLEAN (U"Normalize scalar products", true)
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
 	OK
 DO
-	autoDissimilarityList dissimilarities = DissimilarityList_create ();
-	Configuration configuration = nullptr;
-	Salience salience = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classDissimilarity) {
-			dissimilarities -> addItem_ref ((Dissimilarity) me);
-		} else if (CLASS == classConfiguration) {
-			configuration = (Configuration) me;
-		} else if (CLASS == classSalience) {
-			salience = (Salience) me;
-		}
-	}
-	Melder_assert (dissimilarities->size > 0 && configuration && salience);
-	double varianceAccountedFor;
-	DissimilarityList_Configuration_Salience_vaf (dissimilarities.get(), configuration, salience,
-		GET_INTEGER (U"Handling of ties"),
-		GET_INTEGER (U"Normalize scalar products"),
-		& varianceAccountedFor);
-	Melder_information (varianceAccountedFor);
-END
-
-FORM (Distance_Configuration_Salience_indscal,
-      U"Distance & Configuration & Salience: To Configuration (indscal)",
-      U"Distance & Configuration & Salience: To Configuration (indscal)...")
-	BOOLEAN (U"Normalize scalar products", true)
+	NUMBER_TWO_AND_LIST (Configuration, Salience, Dissimilarity)
+		double result;
+		DissimilarityList_Configuration_Salience_vaf ((DissimilarityList) & list, me, you ,tiesHandling, normalizeScalarProducts, & result);
+	NUMBER_TWO_AND_LIST_END (U" (variance accounted for)");
+}
+
+FORM (NEWMANY_Distance_Configuration_Salience_indscal, U"Distance & Configuration & Salience: To Configuration (indscal)", U"Distance & Configuration & Salience: To Configuration (indscal)...") {
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
 	LABEL (U"", U"Minimization parameters")
-	REAL (U"Tolerance", U"1e-5")
-	NATURAL (U"Maximum number of iterations", U"100")
+	REALVAR (tolerance, U"Tolerance", U"1e-5")
+	NATURALVAR (maximumNumberOfIterations, U"Maximum number of iterations", U"100")
 	OK
 DO
-	autoDistanceList thee = DistanceList_create ();
-	Configuration configuration = nullptr;
-	Salience salience = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classDistance) {
-			thy addItem_ref ((Distance) me);
-		} else if (CLASS == classConfiguration) {
-			configuration = (Configuration) me;
-		} else if (CLASS == classSalience) {
-			salience = (Salience) me;
+	FIND_TWO_AND_LIST (Configuration, Salience, Distance)
+		autoConfiguration configurationResult;
+		autoSalience salienceResult;
+		DistanceList_Configuration_Salience_indscal ((DistanceList) & list, me, you, normalizeScalarProducts, tolerance, maximumNumberOfIterations, true, & configurationResult, & salienceResult, nullptr);
+		praat_new (configurationResult.move(), U"indscal");
+		praat_new (salienceResult.move(), U"indscal");
+	END 
+}
+
+FORM (NEWMANY_Distances_to_Configuration_ytl, U"Distance: To Configuration (ytl)", U"Distance: To Configuration (ytl)...") {
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
+	BOOLEANVAR (normalizeScalarProducts, U"Normalize scalar products", true)
+	BOOLEANVAR (wantSalienceObject, U"Salience object", false)
+	OK
+DO
+	FIND_LIST (Distance)
+		autoConfiguration configurationResult;
+		autoSalience salienceResult;
+		DistanceList_to_Configuration_ytl ((DistanceList) & list, numberOfDimensions, normalizeScalarProducts, & configurationResult, & salienceResult);
+		praat_new (configurationResult.move(), U"ytl");
+		if (wantSalienceObject) {
+			praat_new (salienceResult.move(), U"ytl");
 		}
-	}
-	Melder_assert (thy size > 0 && configuration && salience);
-	double varianceAccountedFor;
-	autoConfiguration configurationResult;
-	autoSalience salienceResult;
-	DistanceList_Configuration_Salience_indscal (thee.get(), configuration, salience,
-		GET_INTEGER (U"Normalize scalar products"),
-		GET_REAL (U"Tolerance"),
-		GET_INTEGER (U"Maximum number of iterations"),
-		true,   // showProgress
-		& configurationResult, & salienceResult, & varianceAccountedFor);
-	praat_new (configurationResult.move(), U"indscal");
-	praat_new (salienceResult.move(), U"indscal");
-END
-
-FORM (Distances_to_Configuration_ytl, U"Distance: To Configuration (ytl)", U"Distance: To Configuration (ytl)...")
-	NATURAL (U"Number of dimensions", U"2")
-	BOOLEAN (U"Normalize scalar products", true)
-	BOOLEAN (U"Salience object", false)
-	OK
-DO
-	autoDistanceList distances = DistanceList_create ();
-	LOOP {
-		iam (Distance);
-		distances -> addItem_ref (me);
-	}
-	autoConfiguration configurationResult;
-	autoSalience salienceResult;
-	DistanceList_to_Configuration_ytl (distances.get(), GET_INTEGER (U"Number of dimensions"),
-		GET_INTEGER (U"Normalize scalar products"), & configurationResult, & salienceResult);
-	praat_new (configurationResult.move(), U"ytl");
-	if (GET_INTEGER (U"Salience object")) {
-		praat_new (salienceResult.move(), U"ytl");
-	}
-END
+	END
+}
 
-FORM (Dissimilarity_Distance_monotoneRegression, U"Dissimilarity & Distance: Monotone regression", nullptr)
-	RADIO (U"Handling of ties", 1)
+FORM (NEW1_Dissimilarity_Distance_monotoneRegression, U"Dissimilarity & Distance: Monotone regression", nullptr) {
+	RADIOVAR (tiesHandling, U"Handling of ties", 1)
 		RADIOBUTTON (U"Primary approach")
 		RADIOBUTTON (U"Secondary approach")
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Distance thee = FIRST (Distance);
-	praat_new (Dissimilarity_Distance_monotoneRegression (me, thee,
-		GET_INTEGER (U"Handling of ties")), my name);
-END
+	CONVERT_TWO (Dissimilarity, Distance)
+		autoDistance result = Dissimilarity_Distance_monotoneRegression (me, you, tiesHandling);
+	CONVERT_TWO_END (my name)
+}
 
-FORM (Distance_Dissimilarity_drawShepardDiagram, U"Distance & Dissimilarity: Draw Shepard diagram", nullptr)
-	REAL (U"Minimum dissimilarity", U"0.0")
-	REAL (U"Maximum dissimilarity", U"0.0")
-	REAL (U"left Distance range", U"0.0")
-	REAL (U"right Distance range", U"0.0")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Distance_Dissimilarity_drawShepardDiagram, U"Distance & Dissimilarity: Draw Shepard diagram", nullptr) {
+	REALVAR (fromDissimilarity, U"left dissimilarity range", U"0.0")
+	REALVAR (toDissimilarity, U"right dissimilarity range", U"0.0")
+	REALVAR (fromDistance, U"left Distance range", U"0.0")
+	REALVAR (toDistance, U"right Distance range", U"0.0")
+	POSITIVEVAR (markSize, U"Mark size (mm)", U"1.0")
+	SENTENCEVAR (markString, U"Mark string (+xo.)", U"+")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	Dissimilarity me = FIRST (Dissimilarity);
-	Distance thee = FIRST (Distance);
-	Proximity_Distance_drawScatterDiagram (me, thee, GRAPHICS,
-		GET_REAL (U"Minimum dissimilarity"),
-		GET_REAL (U"Maximum dissimilarity"),
-		GET_REAL (U"left Distance range"),
-		GET_REAL (U"right Distance range"),
-		GET_REAL (U"Mark size"),
-		GET_STRING (U"Mark string"),
-		GET_INTEGER (U"Garnish"));
-END
+	GRAPHICS_TWO (Dissimilarity, Distance)
+		Proximity_Distance_drawScatterDiagram (me, you, GRAPHICS, fromDissimilarity, toDissimilarity, fromDistance, toDistance, markSize, markString, garnish);
+	GRAPHICS_TWO_END
+}
 
-DIRECT (MDS_help)
-	Melder_help (U"Multidimensional scaling");
-END
+DIRECT (HELP_MDS_help) {
+	HELP (U"Multidimensional scaling")
+}
 
 
 /************************* Salience ***************************************/
 
 
-FORM (Salience_draw, U"Salience: Draw", nullptr)
-	NATURAL (U"Horizontal dimension", U"1")
-	NATURAL (U"Vertical dimension", U"2")
-	BOOLEAN (U"Garnish", true)
+FORM (GRAPHICS_Salience_draw, U"Salience: Draw", nullptr) {
+	NATURALVAR (horizontalDimension, U"Horizontal dimension", U"1")
+	NATURALVAR (verticalDimension, U"Vertical dimension", U"2")
+	BOOLEANVAR (garnish, U"Garnish", true)
 	OK
 DO
-	LOOP {
-		iam (Salience);
-		Salience_draw (me, GRAPHICS,
-			GET_INTEGER (U"Horizontal dimension"),
-			GET_INTEGER (U"Vertical dimension"),
-			GET_INTEGER (U"Garnish"));
-	}
-END
+	GRAPHICS_EACH (Salience)
+		Salience_draw (me, GRAPHICS, horizontalDimension, verticalDimension, garnish);
+	GRAPHICS_EACH_END
+}
 
 /************************* COVARIANCE & CONFIGURATION  ********************/
 
-FORM (Covariance_to_Configuration, U"Covariance: To Configuration", nullptr)
-	NATURAL (U"Number of dimensions", U"2")
+FORM (NEW_Covariance_to_Configuration, U"Covariance: To Configuration", nullptr) {
+	NATURALVAR (numberOfDimensions, U"Number of dimensions", U"2")
 	OK
 DO
-	LOOP {
-		iam (Covariance);
-		autoConfiguration result = Covariance_to_Configuration (me,
-			GET_INTEGER (U"Number of dimensions"));
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH (Covariance)
+		autoConfiguration result = Covariance_to_Configuration (me, numberOfDimensions);
+	CONVERT_EACH_END (my name)
+}
 
 /********* Procrustes ***************************/
 
-DIRECT (Procrustes_help)
-	Melder_help (U"Procrustes");
-END
+DIRECT (HELP_Procrustes_help) {
+	HELP (U"Procrustes")
+}
 
-DIRECT (Procrustes_getScale)
-	LOOP {
-		iam (Procrustes);
-		Melder_information (my s);
-	}
-END
+DIRECT (REAL_Procrustes_getScale) {
+	NUMBER_ONE (Procrustes)
+		double result = my s;
+	NUMBER_ONE_END (U"(scale)")
+}
 
 /********* Casts from & to TableOfReal ***************************/
 
-DIRECT (TableOfReal_to_Dissimilarity)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Dissimilarity (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Dissimilarity) {
+	CONVERT_EACH (TableOfReal)
+		autoDissimilarity result = TableOfReal_to_Dissimilarity (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Similarity)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Similarity (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Similarity) {
+	CONVERT_EACH (TableOfReal)
+		autoSimilarity result = TableOfReal_to_Similarity (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Distance)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Distance (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Distance) {
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_to_Distance (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Salience)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Salience (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Salience) {
+	CONVERT_EACH (TableOfReal)
+		autoSalience result = TableOfReal_to_Salience (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Weight)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_Weight (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_Weight) {
+	CONVERT_EACH (TableOfReal)
+		autoWeight result = TableOfReal_to_Weight (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_ScalarProduct)
-	LOOP {
-		iam (TableOfReal);
-		praat_new (TableOfReal_to_ScalarProduct (me), my name);
-	}
-END
+DIRECT (NEW_TableOfReal_to_ScalarProduct) {
+	CONVERT_EACH (TableOfReal)
+		autoScalarProduct result = TableOfReal_to_ScalarProduct (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_Configuration)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (NEW_TableOfReal_to_Configuration) {
+	CONVERT_EACH (TableOfReal)
 		autoConfiguration result = TableOfReal_to_Configuration (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT (TableOfReal_to_ContingencyTable)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (NEW_TableOfReal_to_ContingencyTable) {
+	CONVERT_EACH (TableOfReal)
 		autoContingencyTable result = TableOfReal_to_ContingencyTable (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
 /********************** TableOfReal ***************************************/
 
-DIRECT (TableOfReal_getTableNorm)
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (TableOfReal_getTableNorm (me));
-	}
-END
+DIRECT (REAL_TableOfReal_getTableNorm) {
+	NUMBER_ONE (TableOfReal)
+		double result = TableOfReal_getTableNorm (me);
+	NUMBER_ONE_END (U"(norm)")
+}
 
-FORM (TableOfReal_normalizeTable, U"TableOfReal: Normalize table", U"TableOfReal: Normalize table...")
-	POSITIVE (U"Norm", U"1.0")
+FORM (MODIFY_TableOfReal_normalizeTable, U"TableOfReal: Normalize table", U"TableOfReal: Normalize table...") {
+	POSITIVEVAR (norm, U"Norm", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_normalizeTable (me, GET_REAL (U"Norm"));
-	}
-END
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_normalizeTable (me, norm);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_normalizeRows, U"TableOfReal: Normalize rows", U"TableOfReal: Normalize rows...")
-	POSITIVE (U"Norm", U"1.0")
+FORM (MODIFY_TableOfReal_normalizeRows, U"TableOfReal: Normalize rows", U"TableOfReal: Normalize rows...") {
+	POSITIVEVAR (norm, U"Norm", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_normalizeRows (me, GET_REAL (U"Norm"));
-	}
-END
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_normalizeRows (me, norm);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_normalizeColumns, U"TableOfReal: Normalize columns", U"TableOfReal: Normalize columns...")
-	POSITIVE (U"Norm", U"1.0")
+FORM (MODIFY_TableOfReal_normalizeColumns, U"TableOfReal: Normalize columns", U"TableOfReal: Normalize columns...") {
+	POSITIVEVAR (norm, U"Norm", U"1.0")
 	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_normalizeColumns (me, GET_REAL (U"Norm"));
-	}
-END
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_normalizeColumns (me, norm);
+	MODIFY_EACH_END
+}
 
-DIRECT (TableOfReal_centreRows)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (MODIFY_TableOfReal_centreRows) {
+	MODIFY_EACH (TableOfReal)
 		TableOfReal_centreRows (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (TableOfReal_centreColumns)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (MODIFY_TableOfReal_centreColumns) {
+	MODIFY_EACH (TableOfReal)
 		TableOfReal_centreColumns (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (TableOfReal_doubleCentre)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (MODIFY_TableOfReal_doubleCentre) {
+	MODIFY_EACH (TableOfReal)
 		TableOfReal_doubleCentre (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (TableOfReal_standardizeRows)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (MODIFY_TableOfReal_standardizeRows) {
+	MODIFY_EACH (TableOfReal)
 		TableOfReal_standardizeRows (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (TableOfReal_standardizeColumns)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (MODIFY_TableOfReal_standardizeColumns) {
+	MODIFY_EACH (TableOfReal)
 		TableOfReal_standardizeColumns (me);
-	}
-END
+	MODIFY_EACH_END
+}
 
-DIRECT (TableOfReal_to_Confusion)
-	LOOP {
-		iam (TableOfReal);
+DIRECT (NEW_TableOfReal_to_Confusion) {
+	CONVERT_EACH (TableOfReal)
 		autoConfusion result = TableOfReal_to_Confusion (me);
-		praat_new (result.move(), my name);
-	}
-END
+	CONVERT_EACH_END (my name)
+}
 
 static void praat_AffineTransform_init (ClassInfo klas) {
 	praat_addAction1 (klas, 0, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction1 (klas, 1, U"Get transformation element...", QUERY_BUTTON, 1, DO_AffineTransform_getTransformationElement);
-	praat_addAction1 (klas, 1, U"Get translation element...", QUERY_BUTTON, 1, DO_AffineTransform_getTranslationElement);
-	praat_addAction1 (klas, 0, U"Invert", nullptr, 0, DO_AffineTransform_invert);
-}
-
-static void praat_Configuration_and_AffineTransform_init (ClassInfo transform) {
-	praat_addAction2 (classConfiguration, 1, transform, 1, U"To Configuration", nullptr, 0, DO_Configuration_and_AffineTransform_to_Configuration);
+	praat_addAction1 (klas, 1, U"Get transformation element...", QUERY_BUTTON, 1, REAL_AffineTransform_getTransformationElement);
+	praat_addAction1 (klas, 1, U"Get translation element...", QUERY_BUTTON, 1, REAL_AffineTransform_getTranslationElement);
+	praat_addAction1 (klas, 0, U"Invert", nullptr, 0, NEW_AffineTransform_invert);
 }
 
 void praat_TableOfReal_extras (ClassInfo klas);
 void praat_TableOfReal_extras (ClassInfo klas) {
 	praat_addAction1 (klas, 1, U"-- get additional --", U"Get value...", 1, nullptr);
-	praat_addAction1 (klas, 1, U"Get table norm", U"-- get additional --", 1, DO_TableOfReal_getTableNorm);
-	praat_addAction1 (klas, 1, U"-- set additional --", U"Set column label (label)...", 1, nullptr);
-	praat_addAction1 (klas, 1, U"Normalize rows...", U"-- set additional --", 1, DO_TableOfReal_normalizeRows);
-	praat_addAction1 (klas, 1, U"Normalize columns...", U"Normalize rows...", 1, DO_TableOfReal_normalizeColumns);
-	praat_addAction1 (klas, 1, U"Normalize table...", U"Normalize columns...", 1, DO_TableOfReal_normalizeTable);
-	praat_addAction1 (klas, 1, U"Standardize rows", U"Normalize table...", 1, DO_TableOfReal_standardizeRows);
-	praat_addAction1 (klas, 1, U"Standardize columns", U"Standardize rows", 1, DO_TableOfReal_standardizeColumns);
-	praat_addAction1 (klas, 1, U"Test sorting...", U"Standardize columns", praat_DEPTH_1 + praat_HIDDEN, DO_TabelOfReal_testSorting);
+	praat_addAction1 (klas, 1, U"Get table norm", U"-- get additional --", 1, REAL_TableOfReal_getTableNorm);
+	praat_addAction1 (klas, 0, U"-- set additional --", U"Set column label (label)...", 1, nullptr);
+	praat_addAction1 (klas, 0, U"Normalize rows...", U"-- set additional --", 1, MODIFY_TableOfReal_normalizeRows);
+	praat_addAction1 (klas, 0, U"Normalize columns...", U"Normalize rows...", 1, MODIFY_TableOfReal_normalizeColumns);
+	praat_addAction1 (klas, 0, U"Normalize table...", U"Normalize columns...", 1, MODIFY_TableOfReal_normalizeTable);
+	praat_addAction1 (klas, 0, U"Standardize rows", U"Normalize table...", 1, MODIFY_TableOfReal_standardizeRows);
+	praat_addAction1 (klas, 0, U"Standardize columns", U"Standardize rows", 1, MODIFY_TableOfReal_standardizeColumns);
+	praat_addAction1 (klas, 0, U"Test sorting...", U"Standardize columns", praat_DEPTH_1 + praat_HIDDEN + praat_NO_API, MODIFY_TabelOfReal_testSorting);
 }
 
 void praat_uvafon_MDS_init ();
@@ -1861,210 +1370,210 @@ void praat_uvafon_MDS_init () {
 	Thing_recognizeClassByOtherName (classProcrustes, U"Procrustus");
 
 	praat_addMenuCommand (U"Objects", U"New", U"Multidimensional scaling", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"MDS tutorial", nullptr, 1, DO_MDS_help);
+	praat_addMenuCommand (U"Objects", U"New", U"MDS tutorial", nullptr, praat_DEPTH_1 | praat_NO_API, HELP_MDS_help);
 	praat_addMenuCommand (U"Objects", U"New", U"-- MDS --", nullptr, 1, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create letter R example...", nullptr, 1, DO_Dissimilarity_createLetterRExample);
-	praat_addMenuCommand (U"Objects", U"New", U"Create INDSCAL Carroll Wish example...", nullptr, 1, DO_INDSCAL_createCarrollWishExample);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Configuration...", nullptr, 1, DO_Configuration_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Draw splines...", nullptr, 1, DO_drawSplines);
-	praat_addMenuCommand (U"Objects", U"New", U"Draw MDS class relations", nullptr, 1, DO_drawMDSClassRelations);
+	praat_addMenuCommand (U"Objects", U"New", U"Create letter R example...", nullptr, 1, NEW1_Dissimilarity_createLetterRExample);
+	praat_addMenuCommand (U"Objects", U"New", U"Create INDSCAL Carroll Wish example...", nullptr, 1, NEWMANY_INDSCAL_createCarrollWishExample);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Configuration...", nullptr, 1, NEW1_Configuration_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Draw splines...", nullptr, 1, GRAPHICS_drawSplines);
+	praat_addMenuCommand (U"Objects", U"New", U"Draw MDS class relations", nullptr, 1, GRAPHICS_drawMDSClassRelations);
 
 	/****** 1 class ********************************************************/
 
-	praat_addAction1 (classAffineTransform, 0, U"AffineTransform help", nullptr, 0, DO_AffineTransform_help);
+	praat_addAction1 (classAffineTransform, 0, U"AffineTransform help", nullptr, 0, HELP_AffineTransform_help);
 	praat_AffineTransform_init (classAffineTransform);
 
 
-	praat_addAction1 (classConfiguration, 0, U"Configuration help", nullptr, 0, DO_Configuration_help);
+	praat_addAction1 (classConfiguration, 0, U"Configuration help", nullptr, 0, HELP_Configuration_help);
 	praat_TableOfReal_init2 (classConfiguration);
 	praat_TableOfReal_extras (classConfiguration);
 	(void) praat_removeAction (classConfiguration, nullptr, nullptr, U"Insert column (index)...");
 	(void) praat_removeAction (classConfiguration, nullptr, nullptr, U"Remove column (index)...");
 	(void) praat_removeAction (classConfiguration, nullptr, nullptr, U"Append");
-	praat_addAction1 (classConfiguration, 0, U"Draw...", DRAW_BUTTON, 1, DO_Configuration_draw);
-	praat_addAction1 (classConfiguration, 0, U"Draw sigma ellipses...", U"Draw...", 1, DO_Configuration_drawSigmaEllipses);
-	praat_addAction1 (classConfiguration, 0, U"Draw one sigma ellipse...", U"Draw...", 1, DO_Configuration_drawOneSigmaEllipse);
-	praat_addAction1 (classConfiguration, 0, U"Draw confidence ellipses...", U"Draw sigma ellipses...", 1, DO_Configuration_drawConfidenceEllipses);
-	praat_addAction1 (classConfiguration, 0, U"Draw one confidence ellipse...", U"Draw sigma ellipses...", 1, DO_Configuration_drawOneConfidenceEllipse);
-
-	praat_addAction1 (classConfiguration, 0, U"Randomize", U"Normalize table...", 1, DO_Configuration_randomize);
-	praat_addAction1 (classConfiguration, 0, U"Normalize...", U"Randomize", 1, DO_Configuration_normalize);
-	praat_addAction1 (classConfiguration, 0, U"Centralize", U"Randomize", 1, DO_Configuration_centralize);
+	praat_addAction1 (classConfiguration, 0, U"Draw...", DRAW_BUTTON, 1, GRAPHICS_Configuration_draw);
+	praat_addAction1 (classConfiguration, 0, U"Draw sigma ellipses...", U"Draw...", 1, GRAPHICS_Configuration_drawSigmaEllipses);
+	praat_addAction1 (classConfiguration, 0, U"Draw one sigma ellipse...", U"Draw...", 1, GRAPHICS_Configuration_drawOneSigmaEllipse);
+	praat_addAction1 (classConfiguration, 0, U"Draw confidence ellipses...", U"Draw sigma ellipses...", 1, GRAPHICS_Configuration_drawConfidenceEllipses);
+	praat_addAction1 (classConfiguration, 0, U"Draw one confidence ellipse...", U"Draw sigma ellipses...", 1, GRAPHICS_Configuration_drawOneConfidenceEllipse);
+
+	praat_addAction1 (classConfiguration, 0, U"Randomize", U"Normalize table...", 1, MODIFY_Configuration_randomize);
+	praat_addAction1 (classConfiguration, 0, U"Normalize...", U"Randomize", 1, MODIFY_Configuration_normalize);
+	praat_addAction1 (classConfiguration, 0, U"Centralize", U"Randomize", 1, MODIFY_Configuration_centralize);
 	praat_addAction1 (classConfiguration, 1, U"-- set rotations & reflections --", U"Centralize", 1, nullptr);
 
-	praat_addAction1 (classConfiguration, 0, U"Rotate...", U"-- set rotations & reflections --", 1, DO_Configuration_rotate);
-	praat_addAction1 (classConfiguration, 0, U"Rotate (pc)", U"Rotate...", 1, DO_Configuration_rotateToPrincipalDirections);
-	praat_addAction1 (classConfiguration, 0, U"Invert dimension...", U"Rotate (pc)", 1, DO_Configuration_invertDimension);
+	praat_addAction1 (classConfiguration, 0, U"Rotate...", U"-- set rotations & reflections --", 1, MODIFY_Configuration_rotate);
+	praat_addAction1 (classConfiguration, 0, U"Rotate (pc)", U"Rotate...", 1, MODIFY_Configuration_rotateToPrincipalDirections);
+	praat_addAction1 (classConfiguration, 0, U"Invert dimension...", U"Rotate (pc)", 1, MODIFY_Configuration_invertDimension);
 	praat_addAction1 (classConfiguration, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classConfiguration, 0, U"To Distance", nullptr, 0, DO_Configuration_to_Distance);
-	praat_addAction1 (classConfiguration, 0, U"To Configuration (varimax)...", nullptr, 0, DO_Configuration_varimax);
-	praat_addAction1 (classConfiguration, 0, U"To Similarity (cc)", nullptr, 0, DO_Configurations_to_Similarity_cc);
+	praat_addAction1 (classConfiguration, 0, U"To Distance", nullptr, 0, NEW_Configuration_to_Distance);
+	praat_addAction1 (classConfiguration, 0, U"To Configuration (varimax)...", nullptr, 0, NEW_Configuration_varimax);
+	praat_addAction1 (classConfiguration, 0, U"To Similarity (cc)", nullptr, 0, NEW1_Configurations_to_Similarity_cc);
 
 	praat_addAction1 (classConfiguration, 0, U"Match configurations -", nullptr, 0, nullptr);
-	praat_addAction1 (classConfiguration, 2, U"To Procrustes...", nullptr, 1, DO_Configurations_to_Procrustes);
-	praat_addAction1 (classConfiguration, 2, U"To AffineTransform (congruence)...", nullptr, 1, DO_Configurations_to_AffineTransform_congruence);
+	praat_addAction1 (classConfiguration, 2, U"To Procrustes...", nullptr, 1, NEW1_Configurations_to_Procrustes);
+	praat_addAction1 (classConfiguration, 2, U"To AffineTransform (congruence)...", nullptr, 1, NEW1_Configurations_to_AffineTransform_congruence);
 
-	praat_addAction1 (classConfusion, 0, U"To ContingencyTable", U"To Matrix", 0, DO_Confusion_to_ContingencyTable);
+	praat_addAction1 (classConfusion, 0, U"To ContingencyTable", U"To Matrix", 0, NEW_Confusion_to_ContingencyTable);
 	praat_addAction1 (classConfusion, 0, U"To Proximity -", U"Analyse", 0, nullptr);
-	praat_addAction1 (classConfusion, 0, U"To Dissimilarity (pdf)...", U"To Proximity -", 1, DO_Confusion_to_Dissimilarity_pdf);
-	praat_addAction1 (classConfusion, 0, U"To Similarity...", U"To Proximity -", 1, DO_Confusion_to_Similarity);
-	praat_addAction1 (classConfusion, 0, U"Sum", U"Synthesize -", 1, DO_Confusions_sum);
+	praat_addAction1 (classConfusion, 0, U"To Dissimilarity (pdf)...", U"To Proximity -", 1, NEW_Confusion_to_Dissimilarity_pdf);
+	praat_addAction1 (classConfusion, 0, U"To Similarity...", U"To Proximity -", 1, NEW_Confusion_to_Similarity);
+	praat_addAction1 (classConfusion, 0, U"Sum", U"Synthesize -", 1, NEW1_Confusions_sum);
 
 
 	praat_TableOfReal_init2 (classContingencyTable);
 	praat_addAction1 (classContingencyTable, 1, U"-- statistics --", U"Get value...", 1, nullptr);
-	praat_addAction1 (classContingencyTable, 1, U"Get chi squared probability", U"-- statistics --", 1, DO_ContingencyTable_chisqProbability);
-	praat_addAction1 (classContingencyTable, 1, U"Get Cramer's statistic", U"Get chi squared probability", 1, DO_ContingencyTable_cramersStatistic);
-	praat_addAction1 (classContingencyTable, 1, U"Get contingency coefficient", U"Get Cramer's statistic", 1,
-	                  DO_ContingencyTable_contingencyCoefficient);
+	praat_addAction1 (classContingencyTable, 1, U"Get chi squared probability", U"-- statistics --", 1, REAL_ContingencyTable_chisqProbability);
+	praat_addAction1 (classContingencyTable, 1, U"Get Cramer's statistic", U"Get chi squared probability", 1, REAL_ContingencyTable_cramersStatistic);
+	praat_addAction1 (classContingencyTable, 1, U"Get contingency coefficient", U"Get Cramer's statistic", 1, REAL_ContingencyTable_contingencyCoefficient);
 	praat_addAction1 (classContingencyTable, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classContingencyTable, 1, U"To Configuration (ca)...", nullptr, 0, DO_ContingencyTable_to_Configuration_ca);
+	praat_addAction1 (classContingencyTable, 1, U"To Configuration (ca)...", nullptr, 0, NEW_ContingencyTable_to_Configuration_ca);
 
 
-	praat_addAction1 (classCorrelation, 0, U"To Configuration...", nullptr, 0, DO_Correlation_to_Configuration);
+	praat_addAction1 (classCorrelation, 0, U"To Configuration...", nullptr, 0, NEW_Correlation_to_Configuration);
 
-	praat_addAction1 (classDissimilarity, 0, U"Dissimilarity help", nullptr, 0, DO_Dissimilarity_help);
+	praat_addAction1 (classDissimilarity, 0, U"Dissimilarity help", nullptr, 0, HELP_Dissimilarity_help);
 	praat_TableOfReal_init2 (classDissimilarity);
 	praat_TableOfReal_extras (classDissimilarity);
-	praat_addAction1 (classDissimilarity, 0, U"Get additive constant", U"Get table norm", 1, DO_Dissimilarity_getAdditiveConstant);
+	praat_addAction1 (classDissimilarity, 0, U"Get additive constant", U"Get table norm", 1, REAL_Dissimilarity_getAdditiveConstant);
 	praat_addAction1 (classDissimilarity, 0, CONFIGURATION_BUTTON, nullptr, 0, nullptr);
-	praat_addAction1 (classDissimilarity, 1, U"To Configuration (monotone mds)...", nullptr, 1, DO_Dissimilarity_monotone_mds);
-	praat_addAction1 (classDissimilarity, 1, U"To Configuration (i-spline mds)...", nullptr, 1, DO_Dissimilarity_ispline_mds);
-	praat_addAction1 (classDissimilarity, 1, U"To Configuration (interval mds)...", nullptr, 1, DO_Dissimilarity_interval_mds);
-	praat_addAction1 (classDissimilarity, 1, U"To Configuration (ratio mds)...", nullptr, 1, DO_Dissimilarity_ratio_mds);
-	praat_addAction1 (classDissimilarity, 1, U"To Configuration (absolute mds)...", nullptr, 1, DO_Dissimilarity_absolute_mds);
-	praat_addAction1 (classDissimilarity, 1, U"To Configuration (kruskal)...", nullptr, 1, DO_Dissimilarity_kruskal);
-	praat_addAction1 (classDissimilarity, 0, U"To Distance...", nullptr, 0, DO_Dissimilarity_to_Distance);
-	praat_addAction1 (classDissimilarity, 0, U"To Weight", nullptr, 0, DO_Dissimilarity_to_Weight);
+	praat_addAction1 (classDissimilarity, 1, U"To Configuration (monotone mds)...", nullptr, 1, NEW_Dissimilarity_to_Configuration_monotone_mds);
+	praat_addAction1 (classDissimilarity, 1, U"To Configuration (i-spline mds)...", nullptr, 1, NEW_Dissimilarity_to_Configuration_ispline_mds);
+	praat_addAction1 (classDissimilarity, 1, U"To Configuration (interval mds)...", nullptr, 1, NEW_Dissimilarity_to_Configuration_interval_mds);
+	praat_addAction1 (classDissimilarity, 1, U"To Configuration (ratio mds)...", nullptr, 1, NEW_Dissimilarity_to_Configuration_ratio_mds);
+	praat_addAction1 (classDissimilarity, 1, U"To Configuration (absolute mds)...", nullptr, 1, NEW_Dissimilarity_to_Configuration_absolute_mds);
+	praat_addAction1 (classDissimilarity, 1, U"To Configuration (kruskal)...", nullptr, 1, NEW_Dissimilarity_to_Configuration_kruskal);
+	praat_addAction1 (classDissimilarity, 0, U"To Distance...", nullptr, 0, NEW_Dissimilarity_to_Distance);
+	praat_addAction1 (classDissimilarity, 0, U"To Weight", nullptr, 0, NEW_Dissimilarity_to_Weight);
 
 
-	praat_addAction1 (classCovariance, 0, U"To Configuration...", nullptr, 0, DO_Covariance_to_Configuration);
+	praat_addAction1 (classCovariance, 0, U"To Configuration...", nullptr, 0, NEW_Covariance_to_Configuration);
 
 
 	praat_TableOfReal_init2 (classDistance);
 	praat_TableOfReal_extras (classDistance);
 	praat_addAction1 (classDistance, 0, U"Analyse -", nullptr, 0, nullptr);
 	praat_addAction1 (classDistance, 0, CONFIGURATION_BUTTON, nullptr, 0, nullptr);
-	praat_addAction1 (classDistance, 0, U"To Configuration (indscal)...", nullptr, 1, DO_Distances_indscal);
-	praat_addAction1 (classDistance, 0, U"-- linear scaling --", nullptr, 1, 0);
-	praat_addAction1 (classDistance, 0, U"To Configuration (ytl)...", nullptr, 1, DO_Distances_to_Configuration_ytl);
-	praat_addAction1 (classDistance, 0, U"To Dissimilarity", nullptr, 0, DO_Distance_to_Dissimilarity);
-	praat_addAction1 (classDistance, 0, U"To ScalarProduct...", nullptr, 0, DO_Distance_to_ScalarProduct);
+	praat_addAction1 (classDistance, 0, U"To Configuration (indscal)...", nullptr, 1, NEWMANY_Distances_to_Configuration_indscal);
+	praat_addAction1 (classDistance, 0, U"-- linear scaling --", nullptr, 1, nullptr);
+	praat_addAction1 (classDistance, 0, U"To Configuration (ytl)...", nullptr, 1, NEWMANY_Distances_to_Configuration_ytl);
+	praat_addAction1 (classDistance, 0, U"To Dissimilarity", nullptr, 0, NEW_Distance_to_Dissimilarity);
+	praat_addAction1 (classDistance, 0, U"To ScalarProduct...", nullptr, 0, NEW_Distance_to_ScalarProduct);
 
 
-	praat_addAction1 (classProcrustes, 0, U"Procrustes help", nullptr, 0, DO_Procrustes_help);
+	praat_addAction1 (classProcrustes, 0, U"Procrustes help", nullptr, 0, HELP_Procrustes_help);
 	praat_AffineTransform_init (classProcrustes);
-	praat_addAction1 (classProcrustes, 1, U"Get scale", QUERY_BUTTON, 1, DO_Procrustes_getScale);
-	praat_addAction1 (classProcrustes, 0, U"Extract transformation matrix", nullptr, 0, DO_AffineTransform_extractMatrix);
-	praat_addAction1 (classProcrustes, 0, U"Extract translation vector", nullptr, 0, DO_AffineTransform_extractTranslationVector);
+	praat_addAction1 (classProcrustes, 1, U"Get scale", QUERY_BUTTON, 1, REAL_Procrustes_getScale);
+	praat_addAction1 (classProcrustes, 0, U"Extract transformation matrix", nullptr, 0, NEW_AffineTransform_extractMatrix);
+	praat_addAction1 (classProcrustes, 0, U"Extract translation vector", nullptr, 0, NEW_AffineTransform_extractTranslationVector);
 
 	praat_TableOfReal_init2 (classSalience);
 	praat_TableOfReal_extras (classSalience);
-	praat_addAction1 (classSalience, 0, U"Draw...", DRAW_BUTTON, 1, DO_Salience_draw);
+	praat_addAction1 (classSalience, 0, U"Draw...", DRAW_BUTTON, 1, GRAPHICS_Salience_draw);
 
 
-	praat_addAction1 (classSimilarity, 0, U"Similarity help", nullptr, 0, DO_Similarity_help);
+	praat_addAction1 (classSimilarity, 0, U"Similarity help", nullptr, 0, HELP_Similarity_help);
 	praat_TableOfReal_init2 (classSimilarity);
 	praat_TableOfReal_extras (classSimilarity);
 	praat_addAction1 (classSimilarity, 0, U"Analyse -", nullptr, 0, nullptr);
-	praat_addAction1 (classSimilarity, 0, U"To Dissimilarity...", nullptr, 0, DO_Similarity_to_Dissimilarity);
+	praat_addAction1 (classSimilarity, 0, U"To Dissimilarity...", nullptr, 0, NEW_Similarity_to_Dissimilarity);
 
 
 	praat_TableOfReal_init2 (classScalarProduct);
 	praat_TableOfReal_extras (classScalarProduct);
 
 	praat_TableOfReal_extras (classTableOfReal);
-	praat_addAction1 (classTableOfReal, 1, U"Centre rows", U"Normalize table...", 1, DO_TableOfReal_centreRows);
-	praat_addAction1 (classTableOfReal, 1, U"Centre columns", U"Centre rows", 1, DO_TableOfReal_centreColumns);
-	praat_addAction1 (classTableOfReal, 1, U"Double centre", U"Centre columns", 1, DO_TableOfReal_doubleCentre);
+	praat_addAction1 (classTableOfReal, 1, U"Centre rows", U"Normalize table...", 1, MODIFY_TableOfReal_centreRows);
+	praat_addAction1 (classTableOfReal, 1, U"Centre columns", U"Centre rows", 1, MODIFY_TableOfReal_centreColumns);
+	praat_addAction1 (classTableOfReal, 1, U"Double centre", U"Centre columns", 1, MODIFY_TableOfReal_doubleCentre);
 	praat_addAction1 (classTableOfReal, 0, U"Cast -", nullptr, 0, nullptr);
-	praat_addAction1 (classTableOfReal, 0, U"To Confusion", nullptr, 1, DO_TableOfReal_to_Confusion);
-	praat_addAction1 (classTableOfReal, 0, U"To Dissimilarity", nullptr, 1, DO_TableOfReal_to_Dissimilarity);
-	praat_addAction1 (classTableOfReal, 0, U"To Similarity", nullptr, 1, DO_TableOfReal_to_Similarity);
-	praat_addAction1 (classTableOfReal, 0, U"To Distance", nullptr, 1, DO_TableOfReal_to_Distance);
-	praat_addAction1 (classTableOfReal, 0, U"To Salience", nullptr, 1, DO_TableOfReal_to_Salience);
-	praat_addAction1 (classTableOfReal, 0, U"To Weight", nullptr, 1, DO_TableOfReal_to_Weight);
-	praat_addAction1 (classTableOfReal, 0, U"To ScalarProduct", nullptr, 1, DO_TableOfReal_to_ScalarProduct);
-	praat_addAction1 (classTableOfReal, 0, U"To Configuration", nullptr, 1, DO_TableOfReal_to_Configuration);
-	praat_addAction1 (classTableOfReal, 0, U"To ContingencyTable", nullptr, 1, DO_TableOfReal_to_ContingencyTable);
+	praat_addAction1 (classTableOfReal, 0, U"To Confusion", nullptr, 1, NEW_TableOfReal_to_Confusion);
+	praat_addAction1 (classTableOfReal, 0, U"To Dissimilarity", nullptr, 1, NEW_TableOfReal_to_Dissimilarity);
+	praat_addAction1 (classTableOfReal, 0, U"To Similarity", nullptr, 1, NEW_TableOfReal_to_Similarity);
+	praat_addAction1 (classTableOfReal, 0, U"To Distance", nullptr, 1, NEW_TableOfReal_to_Distance);
+	praat_addAction1 (classTableOfReal, 0, U"To Salience", nullptr, 1, NEW_TableOfReal_to_Salience);
+	praat_addAction1 (classTableOfReal, 0, U"To Weight", nullptr, 1, NEW_TableOfReal_to_Weight);
+	praat_addAction1 (classTableOfReal, 0, U"To ScalarProduct", nullptr, 1, NEW_TableOfReal_to_ScalarProduct);
+	praat_addAction1 (classTableOfReal, 0, U"To Configuration", nullptr, 1, NEW_TableOfReal_to_Configuration);
+	praat_addAction1 (classTableOfReal, 0, U"To ContingencyTable", nullptr, 1, NEW_TableOfReal_to_ContingencyTable);
 
 	praat_TableOfReal_init2 (classWeight);
 
 	/****** 2 classes ********************************************************/
 
-	praat_Configuration_and_AffineTransform_init (classAffineTransform);
-	praat_Configuration_and_AffineTransform_init (classProcrustes);
+	praat_addAction2 (classConfiguration, 1, classAffineTransform, 1, U"To Configuration", nullptr, 0, NEW1_Configuration_and_AffineTransform_to_Configuration);
+	praat_addAction2 (classConfiguration, 1, classProcrustes, 1, U"To Configuration", nullptr, 0, NEW1_Configuration_and_Procrustes_to_Configuration);
+	//praat_Configuration_and_AffineTransform_init (classAffineTransform);
+	//praat_Configuration_and_AffineTransform_init (classProcrustes);
 
 	praat_addAction2 (classConfiguration, 0, classWeight, 1, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction2 (classConfiguration, 0, classWeight, 1, U"To Similarity (cc)", nullptr, 0, DO_Configuration_Weight_to_Similarity_cc);
+	praat_addAction2 (classConfiguration, 0, classWeight, 1, U"To Similarity (cc)", nullptr, 0, NEW1_Configuration_Weight_to_Similarity_cc);
 
 	praat_addAction2 (classDissimilarity, 1, classWeight, 1, ANALYSE_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (monotone mds)...", nullptr, 1, DO_Dissimilarity_Weight_monotone_mds);
-	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (i-spline mds)...", nullptr, 1, DO_Dissimilarity_Weight_ispline_mds);
-	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (interval mds)...", nullptr, 1, DO_Dissimilarity_Weight_interval_mds);
-	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (ratio mds)...", nullptr, 1, DO_Dissimilarity_Weight_ratio_mds);
-	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (absolute mds)...", nullptr, 1, DO_Dissimilarity_Weight_absolute_mds);
+	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (monotone mds)...", nullptr, 1, NEW1_Dissimilarity_Weight_monotone_mds);
+	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (i-spline mds)...", nullptr, 1, NEW1_Dissimilarity_Weight_ispline_mds);
+	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (interval mds)...", nullptr, 1, NEW1_Dissimilarity_Weight_interval_mds);
+	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (ratio mds)...", nullptr, 1, NEW1_Dissimilarity_Weight_ratio_mds);
+	praat_addAction2 (classDissimilarity, 1, classWeight, 1, U"To Configuration (absolute mds)...", nullptr, 1, NEW1_Dissimilarity_Weight_absolute_mds);
 
 
 	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, DRAW_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw Shepard diagram...", nullptr, 1, DO_Dissimilarity_Configuration_drawShepardDiagram);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw Shepard diagram...", nullptr, 1, GRAPHICS_Dissimilarity_Configuration_drawShepardDiagram);
 	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"-- draw regressions --", nullptr, 1, nullptr);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw monotone regression...", nullptr, 1, DO_Dissimilarity_Configuration_drawMonotoneRegression);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw i-spline regression...", nullptr, 1, DO_Dissimilarity_Configuration_drawISplineRegression);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw interval regression...", nullptr, 1, DO_Dissimilarity_Configuration_drawIntervalRegression);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw ratio regression...", nullptr, 1, DO_Dissimilarity_Configuration_drawRatioRegression);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw absolute regression...", nullptr, 1, DO_Dissimilarity_Configuration_drawAbsoluteRegression);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw monotone regression...", nullptr, 1, GRAPHICS_Dissimilarity_Configuration_drawMonotoneRegression);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw i-spline regression...", nullptr, 1, GRAPHICS_Dissimilarity_Configuration_drawISplineRegression);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw interval regression...", nullptr, 1, GRAPHICS_Dissimilarity_Configuration_drawIntervalRegression);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw ratio regression...", nullptr, 1, GRAPHICS_Dissimilarity_Configuration_drawRatioRegression);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Draw absolute regression...", nullptr, 1, GRAPHICS_Dissimilarity_Configuration_drawAbsoluteRegression);
 	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress...", nullptr, 1, DO_Dissimilarity_Configuration_getStress);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (monotone mds)...", nullptr, 1, DO_Dissimilarity_Configuration_monotone_stress);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (i-spline mds)...", nullptr, 1, DO_Dissimilarity_Configuration_ispline_stress);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (interval mds)...", nullptr, 1, DO_Dissimilarity_Configuration_interval_stress);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (ratio mds)...", nullptr, 1, DO_Dissimilarity_Configuration_ratio_stress);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (absolute mds)...", nullptr, 1, DO_Dissimilarity_Configuration_absolute_stress);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (monotone mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_monotone_stress);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (i-spline mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_ispline_stress);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (interval mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_interval_stress);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (ratio mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_ratio_stress);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress (absolute mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_absolute_stress);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"Get stress...", nullptr, 1, REAL_Dissimilarity_Configuration_getStress);
 	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, ANALYSE_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (monotone mds)...", nullptr, 1, DO_Dissimilarity_Configuration_monotone_mds);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (i-spline mds)...", nullptr, 1, DO_Dissimilarity_Configuration_ispline_mds);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (interval mds)...", nullptr, 1, DO_Dissimilarity_Configuration_interval_mds);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (ratio mds)...", nullptr, 1, DO_Dissimilarity_Configuration_ratio_mds);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (absolute mds)...", nullptr, 1, DO_Dissimilarity_Configuration_absolute_mds);
-	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (kruskal)...", nullptr, 1, DO_Dissimilarity_Configuration_kruskal);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (monotone mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_monotone_mds);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (i-spline mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_ispline_mds);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (interval mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_interval_mds);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (ratio mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_ratio_mds);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (absolute mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_absolute_mds);
+	praat_addAction2 (classDissimilarity, 1, classConfiguration, 1, U"To Configuration (kruskal)...", nullptr, 1, NEW1_Dissimilarity_Configuration_kruskal);
 
 	praat_addAction2 (classDistance, 1, classConfiguration, 1, DRAW_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDistance, 1, classConfiguration, 1, U"Draw scatter diagram...", nullptr, 0, DO_Distance_and_Configuration_drawScatterDiagram);
+	praat_addAction2 (classDistance, 1, classConfiguration, 1, U"Draw scatter diagram...", nullptr, 0, GRAPHICS_Distance_and_Configuration_drawScatterDiagram);
 	praat_addAction2 (classDistance, 1, classConfiguration, 1, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDistance, 0, classConfiguration, 1, U"Get VAF...", nullptr, 0, DO_Distance_Configuration_vaf);
+	praat_addAction2 (classDistance, 0, classConfiguration, 1, U"Get VAF...", nullptr, 0, REAL_Distance_Configuration_vaf);
 	praat_addAction2 (classDistance, 1, classConfiguration, 1, ANALYSE_BUTTON, nullptr, 0, nullptr);
-	praat_addAction2 (classDistance, 0, classConfiguration, 1, U"To Configuration (indscal)...", nullptr, 1, DO_Distance_Configuration_indscal);
+	praat_addAction2 (classDistance, 0, classConfiguration, 1, U"To Configuration (indscal)...", nullptr, 1, NEWMANY_Distance_Configuration_indscal);
 
-	praat_addAction2 (classDistance, 1, classDissimilarity, 1, U"Draw Shepard diagram...", nullptr, 0, DO_Distance_Dissimilarity_drawShepardDiagram);
-	praat_addAction2 (classDissimilarity, 1, classDistance, 1, U"Monotone regression...", nullptr, 0, DO_Dissimilarity_Distance_monotoneRegression);
+	praat_addAction2 (classDistance, 1, classDissimilarity, 1, U"Draw Shepard diagram...", nullptr, 0, GRAPHICS_Distance_Dissimilarity_drawShepardDiagram);
+	praat_addAction2 (classDissimilarity, 1, classDistance, 1, U"Monotone regression...", nullptr, 0, NEW1_Dissimilarity_Distance_monotoneRegression);
 
 	/****** 3 classes ********************************************************/
 
 	praat_addAction3 (classDissimilarity, 0, classConfiguration, 1, classSalience, 1, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction3 (classDissimilarity, 0, classConfiguration, 1, classSalience, 1, U"Get VAF...", nullptr, 1, DO_Dissimilarity_Configuration_Salience_vaf);
+	praat_addAction3 (classDissimilarity, 0, classConfiguration, 1, classSalience, 1, U"Get VAF...", nullptr, 1, REAL_Dissimilarity_Configuration_Salience_vaf);
 
 	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (monotone mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_monotone_stress);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (i-spline mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_ispline_stress);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (interval mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_interval_stress);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (ratio mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_ratio_stress);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (absolute mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_absolute_stress);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (monotone mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_Weight_monotone_stress);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (i-spline mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_Weight_ispline_stress);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (interval mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_Weight_interval_stress);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (ratio mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_Weight_ratio_stress);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"Get stress (absolute mds)...", nullptr, 1, REAL_Dissimilarity_Configuration_Weight_absolute_stress);
 	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, ANALYSE_BUTTON, nullptr, 0, nullptr);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (monotone mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_monotone_mds);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (i-spline mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_ispline_mds);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (interval mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_interval_mds);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (ratio mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_ratio_mds);
-	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (absolute mds)...", nullptr, 1, DO_Dissimilarity_Configuration_Weight_absolute_mds);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (monotone mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_Weight_monotone_mds);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (i-spline mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_Weight_ispline_mds);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (interval mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_Weight_interval_mds);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (ratio mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_Weight_ratio_mds);
+	praat_addAction3 (classDissimilarity, 1, classConfiguration, 1, classWeight, 1, U"To Configuration (absolute mds)...", nullptr, 1, NEW1_Dissimilarity_Configuration_Weight_absolute_mds);
 
 
 	praat_addAction3 (classDistance, 0, classConfiguration, 1, classSalience, 1, QUERY_BUTTON, nullptr, 0, nullptr);
-	praat_addAction3 (classDistance, 0, classConfiguration, 1, classSalience, 1, U"Get VAF...", nullptr, 1, DO_Distance_Configuration_Salience_vaf);
+	praat_addAction3 (classDistance, 0, classConfiguration, 1, classSalience, 1, U"Get VAF...", nullptr, 1, REAL_Distance_Configuration_Salience_vaf);
 	praat_addAction3 (classDistance, 0, classConfiguration, 1, classSalience, 1, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction3 (classDistance, 0, classConfiguration, 1, classSalience, 1, U"To Configuration (indscal)...", nullptr, 0, DO_Distance_Configuration_Salience_indscal);
-
+	praat_addAction3 (classDistance, 0, classConfiguration, 1, classSalience, 1, U"To Configuration (indscal)...", nullptr, 0, NEWMANY_Distance_Configuration_Salience_indscal);
 
 	INCLUDE_MANPAGES (manual_MDS_init)
 }
 
-/* End of file praat_MDS_init.c 1775*/
+/* End of file praat_MDS_init.c 2010*/
diff --git a/external/espeak/READ_ME.TXT b/external/espeak/READ_ME.TXT
index 9b46bf2..720c5d8 100644
--- a/external/espeak/READ_ME.TXT
+++ b/external/espeak/READ_ME.TXT
@@ -218,3 +218,6 @@ const char string_ordinal[] = {0xc2,0xba,0};  // masculine ordinal character, UT
 by
 const char string_ordinal[] = {static_cast<char>(0xc2),static_cast<char>(0xba),0};  // masculine ordinal character, UTF-8
 to compile on 32 bit systems
+
+20161101
+voices.cpp: increase size of array voice_identifier[40] to prevent buffer overflow static char voice_identifier[80];
diff --git a/external/espeak/synthdata.cpp b/external/espeak/synthdata.cpp
index ea5d887..f8788e4 100755
--- a/external/espeak/synthdata.cpp
+++ b/external/espeak/synthdata.cpp
@@ -501,7 +501,7 @@ void LoadConfig(void)
 
 		if(memcmp(buf,"log",3)==0)
 		{
-			if(sscanf(&buf[4],"%d %s",&logging_type,string)==2)
+			if(sscanf(&buf[4],"%d %199s",&logging_type,string)==2)
 				f_logespeak = fopen(string,"w");
 		}
 		else
@@ -517,7 +517,7 @@ void LoadConfig(void)
 		else
 		if(memcmp(buf,"soundicon",9)==0)
 		{
-			ix = sscanf(&buf[10],"_%c %s",&c1,string);
+			ix = sscanf(&buf[10],"_%c %199s",&c1,string);
 			if(ix==2)
 			{
 				soundicon_tab[n_soundicon_tab].name = c1;
diff --git a/external/espeak/voices.cpp b/external/espeak/voices.cpp
index 4f77d34..502adb9 100755
--- a/external/espeak/voices.cpp
+++ b/external/espeak/voices.cpp
@@ -343,7 +343,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
 			priority = DEFAULT_LANGUAGE_PRIORITY;
 			vlanguage[0] = 0;
 
-			sscanf(&linebuf[8],"%s %d",vlanguage,&priority);
+			sscanf(&linebuf[8],"%79s %d",vlanguage,&priority);
 			len = strlen(vlanguage) + 2;
 			// check for space in languages[]
 			if(len < (sizeof(languages)-langix-1))
@@ -357,7 +357,7 @@ static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*lea
 		}
 		else if(memcmp(linebuf,"gender",6)==0)
 		{
-			sscanf(&linebuf[6],"%s %d",vgender,&age);
+			sscanf(&linebuf[6],"%79s %d",vgender,&age);
 		}
 		else if(memcmp(linebuf,"variants",8)==0)
 		{
@@ -518,7 +518,7 @@ static void PhonemeReplacement(int type, char *p)
 	char phon_string2[12];
 
 	strcpy(phon_string2,"NULL");
-	n = sscanf(p,"%d %s %s",&flags,phon_string1,phon_string2);
+	n = sscanf(p,"%d %11s %11s",&flags,phon_string1,phon_string2);
 	if((n < 2) || (n_replace_phonemes >= N_REPLACE_PHONEMES))
 		return;
 
@@ -604,7 +604,7 @@ voice_t *LoadVoice(const char *vname, int control)
 	int pitch1;
 	int pitch2;
 
-	static char voice_identifier[40];  // file name for  current_voice_selected
+	static char voice_identifier[80];  // djmw20161031 increased 40->80 to prevent bufferoverflow file name for  current_voice_selected
 	static char voice_name[40];        // voice name for current_voice_selected
 	static char voice_languages[100];  // list of languages and priorities for current_voice_selected
 
@@ -713,8 +713,10 @@ voice_t *LoadVoice(const char *vname, int control)
 		// append the variant file name to the voice identifier
 		if((p = strchr(voice_identifier,'+')) != NULL)
 			*p = 0;    // remove previous variant name
-		sprintf(buf,"+%s",&vname[3]);    // TODO was vname[0], omit  !v/  from the variant filename
-		strcat(voice_identifier,buf);
+		if (vname[3] != '\0') {
+			sprintf(buf,"+%s",&vname[3]);    // TODO was vname[0], omit  !v/  from the variant filename
+			strcat(voice_identifier,buf);
+		}
 		langopts = &translator->langopts;
 	}
 	VoiceReset(tone_only);
@@ -750,7 +752,7 @@ voice_t *LoadVoice(const char *vname, int control)
 			priority = DEFAULT_LANGUAGE_PRIORITY;
 			language_name[0] = 0;
 
-			sscanf(p,"%s %d",language_name,&priority);
+			sscanf(p,"%39s %d",language_name,&priority);
 			if(strcmp(language_name,"variant") == 0)
 				break;
 
@@ -796,7 +798,7 @@ voice_t *LoadVoice(const char *vname, int control)
 		{
 			int age = 0;
 			char vgender[80];
-			sscanf(p,"%s %d",vgender,&age);
+			sscanf(p,"%79s %d",vgender,&age);
 			current_voice_selected.gender = LookupMnem(genders,vgender);
 			current_voice_selected.age = age;
 		}
@@ -805,7 +807,7 @@ voice_t *LoadVoice(const char *vname, int control)
 		case V_TRANSLATOR:
 			if(tone_only) break;
 
-			sscanf(p,"%s",translator_name);
+			sscanf(p,"%39s",translator_name);
 
 			if(new_translator != NULL)
 				DeleteTranslator(new_translator);
@@ -815,11 +817,11 @@ voice_t *LoadVoice(const char *vname, int control)
 			break;
 
 		case V_DICTIONARY:        // dictionary
-			sscanf(p,"%s",new_dictionary);
+			sscanf(p,"%39s",new_dictionary);
 			break;
 
 		case V_PHONEMES:        // phoneme table
-			sscanf(p,"%s",phonemes_name);
+			sscanf(p,"%39s",phonemes_name);
 			break;
 
 		case V_FORMANT:
@@ -857,7 +859,7 @@ voice_t *LoadVoice(const char *vname, int control)
 			break;
 
 		case V_TUNES:
-			n = sscanf(p,"%s %s %s %s %s %s",names[0],names[1],names[2],names[3],names[4],names[5]);
+			n = sscanf(p,"%39s %39s %39s %39s %39s %39s",names[0],names[1],names[2],names[3],names[4],names[5]);
 			langopts->intonation_group = 0;
 			for(ix=0; ix<n; ix++)
 			{
@@ -932,7 +934,7 @@ voice_t *LoadVoice(const char *vname, int control)
 
 		case V_OPTION:
 			value2 = 0;
-			if(((sscanf(p,"%s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) ||
+			if(((sscanf(p,"%39s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) ||
 				((sscanf(p,"%d %d %d",&ix,&value,&value2) >= 2) && (ix < N_LOPTS)))
 			{
 				langopts->param[ix] = value;
@@ -1012,7 +1014,7 @@ voice_t *LoadVoice(const char *vname, int control)
 			int srate = 16000;
 
 			name2[0] = 0;
-			sscanf(p,"%s %s %d",name1,name2,&srate);
+			sscanf(p,"%39s %79s %d",name1,name2,&srate);
 			if(LoadMbrolaTable(name1,name2,srate) != EE_OK)
 			{
 				fprintf(stderr,"mbrola voice not found\n");
@@ -1040,7 +1042,7 @@ voice_t *LoadVoice(const char *vname, int control)
 			{
 				ALPHABET *alphabet;
 				name1[0] = name2[0] = 0;
-				sscanf(p, "%s %s", name1, name2);
+				sscanf(p, "%39s %79s", name1, name2);
 
 				if(strcmp(name1, "latin") == 0)
 				{
@@ -1060,7 +1062,7 @@ voice_t *LoadVoice(const char *vname, int control)
 
 		case V_DICTDIALECT:
 			// specify a dialect to use for foreign words, eg, en-us for _^_EN
-			if(sscanf(p, "%s", name1) == 1)
+			if(sscanf(p, "%39s", name1) == 1)
 			{
 				if((ix = LookupMnem(dict_dialects, name1)) > 0)
 				{
diff --git a/external/gsl/gsl__config.h b/external/gsl/gsl__config.h
index 7b5ce65..d314034 100644
--- a/external/gsl/gsl__config.h
+++ b/external/gsl/gsl__config.h
@@ -24,7 +24,7 @@
 /* Define to 1 if you have the declaration of `feenableexcept', and to 0 if
    you don't. */
 #if defined(linux)
-	#define HAVE_DECL_FEENABLEEXCEPT 1
+	#define HAVE_DECL_FEENABLEEXCEPT 0
 #else
 	#define HAVE_DECL_FEENABLEEXCEPT 0
 #endif
@@ -52,7 +52,7 @@
 /* Define to 1 if you have the declaration of `isfinite', and to 0 if you
    don't. */
 #if defined(linux)
-   #define HAVE_DECL_ISFINITE 0
+   #define HAVE_DECL_ISFINITE 1
 #else
    #define HAVE_DECL_ISFINITE 0
 #endif
diff --git a/external/gsl/gsl_eigen__gen.c b/external/gsl/gsl_eigen__gen.c
index 1483033..9b87d5d 100644
--- a/external/gsl/gsl_eigen__gen.c
+++ b/external/gsl/gsl_eigen__gen.c
@@ -118,7 +118,7 @@ gsl_eigen_gen_alloc(const size_t n)
                       GSL_EINVAL);
     }
 
-  w = calloc (1, sizeof (gsl_eigen_gen_workspace));
+  w = (gsl_eigen_gen_workspace *) calloc (1, sizeof (gsl_eigen_gen_workspace));
 
   if (w == 0)
     {
diff --git a/external/gsl/gsl_eigen__genherm.c b/external/gsl/gsl_eigen__genherm.c
index 994723c..522dde9 100644
--- a/external/gsl/gsl_eigen__genherm.c
+++ b/external/gsl/gsl_eigen__genherm.c
@@ -57,7 +57,7 @@ gsl_eigen_genherm_alloc(const size_t n)
                       GSL_EINVAL);
     }
 
-  w = calloc (1, sizeof (gsl_eigen_genherm_workspace));
+  w = (gsl_eigen_genherm_workspace *) calloc (1, sizeof (gsl_eigen_genherm_workspace));
 
   if (w == 0)
     {
diff --git a/external/gsl/gsl_eigen__genhermv.c b/external/gsl/gsl_eigen__genhermv.c
index 6fbd6b9..dac9d5e 100644
--- a/external/gsl/gsl_eigen__genhermv.c
+++ b/external/gsl/gsl_eigen__genhermv.c
@@ -59,7 +59,7 @@ gsl_eigen_genhermv_alloc(const size_t n)
                       GSL_EINVAL);
     }
 
-  w = calloc (1, sizeof (gsl_eigen_genhermv_workspace));
+  w = (gsl_eigen_genhermv_workspace *) calloc (1, sizeof (gsl_eigen_genhermv_workspace));
 
   if (w == 0)
     {
diff --git a/external/gsl/gsl_eigen__gensymm.c b/external/gsl/gsl_eigen__gensymm.c
index 3501fe2..d425109 100644
--- a/external/gsl/gsl_eigen__gensymm.c
+++ b/external/gsl/gsl_eigen__gensymm.c
@@ -55,7 +55,7 @@ gsl_eigen_gensymm_alloc(const size_t n)
                       GSL_EINVAL);
     }
 
-  w = calloc (1, sizeof (gsl_eigen_gensymm_workspace));
+  w = (gsl_eigen_gensymm_workspace *) calloc (1, sizeof (gsl_eigen_gensymm_workspace));
 
   if (w == 0)
     {
diff --git a/external/gsl/gsl_eigen__gensymmv.c b/external/gsl/gsl_eigen__gensymmv.c
index f22c506..56b975f 100644
--- a/external/gsl/gsl_eigen__gensymmv.c
+++ b/external/gsl/gsl_eigen__gensymmv.c
@@ -57,7 +57,7 @@ gsl_eigen_gensymmv_alloc(const size_t n)
                       GSL_EINVAL);
     }
 
-  w = calloc (1, sizeof (gsl_eigen_gensymmv_workspace));
+  w = (gsl_eigen_gensymmv_workspace *)calloc (1, sizeof (gsl_eigen_gensymmv_workspace));
 
   if (w == 0)
     {
diff --git a/external/gsl/gsl_eigen__genv.c b/external/gsl/gsl_eigen__genv.c
index e5ded25..73ac7fe 100644
--- a/external/gsl/gsl_eigen__genv.c
+++ b/external/gsl/gsl_eigen__genv.c
@@ -68,7 +68,7 @@ gsl_eigen_genv_alloc(const size_t n)
                       GSL_EINVAL);
     }
 
-  w = calloc (1, sizeof (gsl_eigen_genv_workspace));
+  w = (gsl_eigen_genv_workspace *) calloc (1, sizeof (gsl_eigen_genv_workspace));
 
   if (w == 0)
     {
diff --git a/fon/AmplitudeTier.cpp b/fon/AmplitudeTier.cpp
index a42f3ca..9ddc8e2 100644
--- a/fon/AmplitudeTier.cpp
+++ b/fon/AmplitudeTier.cpp
@@ -101,18 +101,18 @@ autoSound Sound_AmplitudeTier_multiply (Sound me, AmplitudeTier amplitude) {
 	}
 }
 
-autoAmplitudeTier PointProcess_Sound_to_AmplitudeTier_point (PointProcess me, Sound thee) {
+autoAmplitudeTier PointProcess_Sound_to_AmplitudeTier_point (PointProcess me, Sound you) {
 	try {
 		long imin, imax, numberOfPeaks = PointProcess_getWindowPoints (me, my xmin, my xmax, & imin, & imax);
 		if (numberOfPeaks < 3) return autoAmplitudeTier();
 		autoAmplitudeTier him = AmplitudeTier_create (my xmin, my xmax);
 		for (long i = imin; i <= imax; i ++) {
-			double value = Vector_getValueAtX (thee, my t [i], Vector_CHANNEL_AVERAGE, Vector_VALUE_INTERPOLATION_SINC700);
+			double value = Vector_getValueAtX (you, my t [i], Vector_CHANNEL_AVERAGE, Vector_VALUE_INTERPOLATION_SINC700);
 			if (NUMdefined (value)) RealTier_addPoint (him.get(), my t [i], value);
 		}
 		return him;
 	} catch (MelderError) {
-		Melder_throw (me, U" & ", thee, U": not converted to AmplitudeTier.");
+		Melder_throw (me, U" & ", you, U": not converted to AmplitudeTier.");
 	}
 }
 /*
@@ -364,10 +364,10 @@ autoSound AmplitudeTier_to_Sound (AmplitudeTier me, double samplingFrequency, lo
 					sound [j] += amplitude;
 				else if (angle < 0.0)
 					sound [j] += halfampsinangle *
-						(1 + cos (angle / (mid - begin + 1))) / angle;
+						(1.0 + cos (angle / (mid - begin + 1))) / angle;
 				else
 					sound [j] += halfampsinangle *
-						(1 + cos (angle / (end - mid + 1))) / angle;
+						(1.0 + cos (angle / (end - mid + 1))) / angle;
 				angle += NUMpi;
 				halfampsinangle = - halfampsinangle;
 			}
diff --git a/fon/ExperimentMFC.cpp b/fon/ExperimentMFC.cpp
index d516cb9..f6ec5eb 100644
--- a/fon/ExperimentMFC.cpp
+++ b/fon/ExperimentMFC.cpp
@@ -182,7 +182,7 @@ void ExperimentMFC_start (ExperimentMFC me) {
 		NUMvector_free <long> (my responses, 1);
 		NUMvector_free <double> (my goodnesses, 1);
 		NUMvector_free <double> (my reactionTimes, 1);
-		my playBuffer.reset();
+		my playBuffer.reset();   // is this needed?
 		my pausing = false;
 		my numberOfTrials = my numberOfDifferentStimuli * my numberOfReplicationsPerStimulus;
 		my stimuli = NUMvector <long> (1, my numberOfTrials);
diff --git a/fon/Formant.cpp b/fon/Formant.cpp
index 865f584..6468e4b 100644
--- a/fon/Formant.cpp
+++ b/fon/Formant.cpp
@@ -75,7 +75,7 @@ double structFormant :: v_getValueAtSample (long iframe, long which, int units)
 		double bandwidth = frame -> formant [iformant]. bandwidth;
 		if (units) {
 			double fleft = frequency - 0.5 * bandwidth, fright = frequency + 0.5 * bandwidth;
-			fleft = fleft <= 0 ? 0 : NUMhertzToBark (fleft);   // prevent NUMundefined
+			fleft = fleft <= 0.0 ? 0.0 : NUMhertzToBark (fleft);   // prevent NUMundefined
 			fright = NUMhertzToBark (fright);
 			return fright - fleft;
 		}
@@ -231,17 +231,16 @@ void Formant_formula_frequencies (Formant me, const char32 *formula, Interpreter
 }
 
 void Formant_getExtrema (Formant me, int iformant, double tmin, double tmax, double *fmin, double *fmax) {
-	long itmin, itmax, iframe;
 	if (fmin) *fmin = 0.0;
 	if (fmax) *fmax = 0.0;
 	if (iformant < 1) return;
 	if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
+	long itmin, itmax;
 	if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return;
-	for (iframe = itmin; iframe <= itmax; iframe ++) {
+	for (long iframe = itmin; iframe <= itmax; iframe ++) {
 		Formant_Frame frame = & my d_frames [iframe];
-		double f;
 		if (iformant > frame -> nFormants) continue;
-		f = frame -> formant [iformant]. frequency;
+		double f = frame -> formant [iformant]. frequency;
 		if (f == 0.0) continue;
 		if (fmin) if (f < *fmin || *fmin == 0.0) *fmin = f;
 		if (fmax) if (f > *fmax) *fmax = f;
diff --git a/fon/FormantGridEditor.cpp b/fon/FormantGridEditor.cpp
index 8d03fad..2616395 100644
--- a/fon/FormantGridEditor.cpp
+++ b/fon/FormantGridEditor.cpp
@@ -1,6 +1,6 @@
 /* FormantGridEditor.cpp
  *
- * Copyright (C) 2008-2011,2012,2013,2014,2015 Paul Boersma & David Weenink
+ * Copyright (C) 2008-2011,2012,2013,2014,2015,2016 Paul Boersma & David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -183,7 +183,7 @@ void structFormantGridEditor :: v_createMenus () {
 	EditorMenu_addCommand (menu, U"Add point at cursor", 'T', menu_cb_addPointAtCursor);
 	EditorMenu_addCommand (menu, U"Add point at...", 0, menu_cb_addPointAt);
 	EditorMenu_addCommand (menu, U"-- remove point --", 0, nullptr);
-	EditorMenu_addCommand (menu, U"Remove point(s)", GuiMenu_OPTION + 'T', menu_cb_removePoints);
+	EditorMenu_addCommand (menu, U"Remove point(s)", GuiMenu_OPTION | 'T', menu_cb_removePoints);
 	if (our v_hasSourceMenu ()) {
 		menu = Editor_addMenu (this, U"Source", 0);
 		EditorMenu_addCommand (menu, U"Pitch settings...", 0, menu_cb_pitchSettings);
diff --git a/fon/FunctionEditor.cpp b/fon/FunctionEditor.cpp
index 7ae96a7..90df72e 100644
--- a/fon/FunctionEditor.cpp
+++ b/fon/FunctionEditor.cpp
@@ -962,7 +962,7 @@ void structFunctionEditor :: v_createMenuItems_view_audio (EditorMenu menu) {
 	EditorMenu_addCommand (menu, U"Audio:", GuiMenu_INSENSITIVE, menu_cb_play /* dummy */);
 	EditorMenu_addCommand (menu, U"Play...", 0, menu_cb_play);
 	EditorMenu_addCommand (menu, U"Play or stop", GuiMenu_TAB, menu_cb_playOrStop);
-	EditorMenu_addCommand (menu, U"Play window", GuiMenu_SHIFT + GuiMenu_TAB, menu_cb_playWindow);
+	EditorMenu_addCommand (menu, U"Play window", GuiMenu_SHIFT | GuiMenu_TAB, menu_cb_playWindow);
 	EditorMenu_addCommand (menu, U"Interrupt playing", GuiMenu_ESCAPE, menu_cb_interruptPlaying);
 }
 
@@ -1001,12 +1001,12 @@ void structFunctionEditor :: v_createMenus () {
 	/*Editor_addCommand (this, U"Select", U"Move cursor back by half a second", motif_, menu_cb_moveCursorBy);*/
 	Editor_addCommand (this, U"Select", U"Select earlier", GuiMenu_UP_ARROW, menu_cb_selectEarlier);
 	Editor_addCommand (this, U"Select", U"Select later", GuiMenu_DOWN_ARROW, menu_cb_selectLater);
-	Editor_addCommand (this, U"Select", U"Move start of selection left", GuiMenu_SHIFT + GuiMenu_UP_ARROW, menu_cb_moveBleft);
+	Editor_addCommand (this, U"Select", U"Move start of selection left", GuiMenu_SHIFT | GuiMenu_UP_ARROW, menu_cb_moveBleft);
 	Editor_addCommand (this, U"Select", U"Move begin of selection left", Editor_HIDDEN, menu_cb_moveBleft);
-	Editor_addCommand (this, U"Select", U"Move start of selection right", GuiMenu_SHIFT + GuiMenu_DOWN_ARROW, menu_cb_moveBright);
+	Editor_addCommand (this, U"Select", U"Move start of selection right", GuiMenu_SHIFT | GuiMenu_DOWN_ARROW, menu_cb_moveBright);
 	Editor_addCommand (this, U"Select", U"Move begin of selection right", Editor_HIDDEN, menu_cb_moveBright);
-	Editor_addCommand (this, U"Select", U"Move end of selection left", GuiMenu_COMMAND + GuiMenu_UP_ARROW, menu_cb_moveEleft);
-	Editor_addCommand (this, U"Select", U"Move end of selection right", GuiMenu_COMMAND + GuiMenu_DOWN_ARROW, menu_cb_moveEright);
+	Editor_addCommand (this, U"Select", U"Move end of selection left", GuiMenu_COMMAND | GuiMenu_UP_ARROW, menu_cb_moveEleft);
+	Editor_addCommand (this, U"Select", U"Move end of selection right", GuiMenu_COMMAND | GuiMenu_DOWN_ARROW, menu_cb_moveEright);
 }
 
 void structFunctionEditor :: v_createHelpMenuItems (EditorMenu menu) {
diff --git a/fon/Harmonicity.cpp b/fon/Harmonicity.cpp
index 28d88da..a306577 100644
--- a/fon/Harmonicity.cpp
+++ b/fon/Harmonicity.cpp
@@ -29,7 +29,7 @@ double Harmonicity_getMean (Harmonicity me, double tmin, double tmax) {
 	double sum = 0.0;
 	long nSounding = 0;
 	for (long i = imin; i <= imax; i ++) {
-		if (my z [1] [i] != -200) {
+		if (my z [1] [i] != -200.0) {
 			nSounding ++;
 			sum += my z [1] [i];
 		}
@@ -46,7 +46,7 @@ double Harmonicity_getStandardDeviation (Harmonicity me, double tmin, double tma
 	double sum = 0.0;
 	long nSounding = 0;
 	for (long i = imin; i <= imax; i ++) {
-		if (my z [1] [i] != -200) {
+		if (my z [1] [i] != -200.0) {
 			nSounding ++;
 			sum += my z [1] [i];
 		}
@@ -55,7 +55,7 @@ double Harmonicity_getStandardDeviation (Harmonicity me, double tmin, double tma
 	double mean = sum / nSounding;
 	double sumOfSquares = 0.0;
 	for (long i = imin; i <= imax; i ++) {
-		if (my z [1] [i] != -200) {
+		if (my z [1] [i] != -200.0) {
 			double d = my z [1] [i] - mean;
 			sumOfSquares += d * d;
 		}
@@ -67,7 +67,7 @@ double Harmonicity_getQuantile (Harmonicity me, double quantile) {
 	autoNUMvector <double> strengths (1, my nx);
 	long nSounding = 0;
 	for (long ix = 1; ix <= my nx; ix ++)
-		if (my z [1] [ix] != -200)
+		if (my z [1] [ix] != -200.0)
 			strengths [++ nSounding] = my z [1] [ix];
 	double result = -200.0;
 	if (nSounding >= 1) {
@@ -86,14 +86,13 @@ void structHarmonicity :: v_info () {
 	autoNUMvector <double> strengths (1, nx);
 	long nSounding = 0;
 	for (long ix = 1; ix <= nx; ix ++)
-		if (z [1] [ix] != -200)
+		if (z [1] [ix] != -200.0)
 			strengths [++ nSounding] = z [1] [ix];
 	MelderInfo_writeLine (U"Time sampling:");
 	MelderInfo_writeLine (U"   Number of frames: ", nx, U" (", nSounding, U" sounding)");
 	MelderInfo_writeLine (U"   Time step: ", dx, U" seconds");
 	MelderInfo_writeLine (U"   First frame centred at: ", x1, U" seconds");
 	if (nSounding) {
-		double sum = 0, sumOfSquares = 0;
 		MelderInfo_writeLine (U"Periodicity-to-noise ratios of sounding frames:");
 		NUMsort_d (nSounding, strengths.peek());
 		MelderInfo_writeLine (U"   Median ", Melder_single (NUMquantile (nSounding, strengths.peek(), 0.50)), U" dB");
@@ -105,6 +104,7 @@ void structHarmonicity :: v_info () {
 			Melder_single (NUMquantile (nSounding, strengths.peek(), 0.75)), U" dB");
 		MelderInfo_writeLine (U"Minimum: ", Melder_single (strengths [1]), U" dB");
 		MelderInfo_writeLine (U"Maximum: ", Melder_single (strengths [nSounding]), U" dB");
+		double sum = 0.0, sumOfSquares = 0.0;
 		for (long i = 1; i <= nSounding; i ++) {
 			double f = strengths [i];
 			sum += f;
@@ -121,7 +121,7 @@ void structHarmonicity :: v_info () {
 autoHarmonicity Harmonicity_create (double tmin, double tmax, long nt, double dt, double t1) {
 	try {
 		autoHarmonicity me = Thing_new (Harmonicity);
-		Matrix_init (me.get(), tmin, tmax, nt, dt, t1, 1, 1, 1, 1, 1);
+		Matrix_init (me.get(), tmin, tmax, nt, dt, t1, 1.0, 1.0, 1, 1.0, 1.0);
 		return me;
 	} catch (MelderError) {
 		Melder_throw (U"Harmonicity not created.");
diff --git a/fon/LongSound.cpp b/fon/LongSound.cpp
index d9c1c6a..6848ee4 100644
--- a/fon/LongSound.cpp
+++ b/fon/LongSound.cpp
@@ -364,7 +364,7 @@ static void writePartToOpenFile (LongSound me, int audioFileType, long imin, lon
 	my imax = 0;
 }
 
-void LongSound_writePartToAudioFile (LongSound me, int audioFileType, double tmin, double tmax, MelderFile file, int numberOfBitsPerSamplePoint) {
+void LongSound_savePartAsAudioFile (LongSound me, int audioFileType, double tmin, double tmax, MelderFile file, int numberOfBitsPerSamplePoint) {
 	try {
 		if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
 		if (tmin < my xmin) tmin = my xmin;
@@ -382,7 +382,7 @@ void LongSound_writePartToAudioFile (LongSound me, int audioFileType, double tmi
 	}
 }
 
-void LongSound_writeChannelToAudioFile (LongSound me, int audioFileType, int channel, MelderFile file) {
+void LongSound_saveChannelAsAudioFile (LongSound me, int audioFileType, int channel, MelderFile file) {
 	try {
 		if (my numberOfChannels != 2)
 			Melder_throw (U"This audio file is not a stereo file. It does not have a ", channel == 0 ? U"left" : U"right", U" channel.");
diff --git a/fon/LongSound.h b/fon/LongSound.h
index d4e5606..849757a 100644
--- a/fon/LongSound.h
+++ b/fon/LongSound.h
@@ -2,7 +2,7 @@
 #define _LongSound_h_
 /* LongSound.h
  *
- * Copyright (C) 1992-2012,2015 Paul Boersma, 2007 Erez Volk (for FLAC, MP3)
+ * Copyright (C) 1992-2012,2015,2016 Paul Boersma, 2007 Erez Volk (for FLAC, MP3)
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -70,8 +70,8 @@ void LongSound_getWindowExtrema (LongSound me, double tmin, double tmax, int cha
 void LongSound_playPart (LongSound me, double tmin, double tmax,
 	Sound_PlayCallback callback, Thing boss);
 
-void LongSound_writePartToAudioFile (LongSound me, int audioFileType, double tmin, double tmax, MelderFile file, int numberOfBitsPerSamplePoint);
-void LongSound_writeChannelToAudioFile (LongSound me, int audioFileType, int channel, MelderFile file);
+void LongSound_savePartAsAudioFile (LongSound me, int audioFileType, double tmin, double tmax, MelderFile file, int numberOfBitsPerSamplePoint);
+void LongSound_saveChannelAsAudioFile (LongSound me, int audioFileType, int channel, MelderFile file);
 
 void LongSound_readAudioToFloat (LongSound me, double **buffer, long firstSample, long numberOfSamples);
 void LongSound_readAudioToShort (LongSound me, int16 *buffer, long firstSample, long numberOfSamples);
diff --git a/fon/Makefile b/fon/Makefile
index 3643c00..5650181 100644
--- a/fon/Makefile
+++ b/fon/Makefile
@@ -1,5 +1,5 @@
 # Makefile of the library "fon"
-# Paul Boersma, 27 October 2013
+# Paul Boersma, 27 October 2016
 
 include ../makefile.defs
 
@@ -29,7 +29,7 @@ OBJECTS = Transition.o Distributions_and_Transition.o \
    ManipulationEditor.o TextGridEditor.o FormantGridEditor.o \
    WordList.o SpellingChecker.o \
    FujisakiPitch.o \
-   ExperimentMFC.o RunnerMFC.o manual_Exp.o praat_Exp.o \
+   ExperimentMFC.o RunnerMFC.o manual_ExperimentMFC.o praat_ExperimentMFC.o \
    Photo.o Movie.o MovieWindow.o \
    Corpus.o \
    manual_Picture.o manual_Manual.o manual_Script.o \
@@ -37,7 +37,8 @@ OBJECTS = Transition.o Distributions_and_Transition.o \
    manual_programming.o manual_Fon.o manual_voice.o Praat_tests.o \
    manual_glossary.o manual_Sampling.o manual_exampleSound.o \
    manual_sound.o manual_pitch.o manual_spectrum.o manual_formant.o manual_annotation.o \
-   praat_Sound_init.o praat_TextGrid_init.o praat_Fon.o
+   praat_TimeFunction.o praat_TimeTier.o praat_TimeFrameSampled.o \
+   praat_Sound.o praat_Matrix.o praat_Tiers.o praat_TextGrid_init.o praat_Fon.o
 
 .PHONY: all clean
 
diff --git a/fon/ManipulationEditor.cpp b/fon/ManipulationEditor.cpp
index 5c092e0..b0e9cd2 100644
--- a/fon/ManipulationEditor.cpp
+++ b/fon/ManipulationEditor.cpp
@@ -539,14 +539,14 @@ void structManipulationEditor :: v_createMenus () {
 	Editor_addCommand (this, U"Pulse", U"Add pulse at cursor", 'P', menu_cb_addPulseAtCursor);
 	Editor_addCommand (this, U"Pulse", U"Add pulse at...", 0, menu_cb_addPulseAt);
 	Editor_addCommand (this, U"Pulse", U"-- remove pulses --", 0, nullptr);
-	Editor_addCommand (this, U"Pulse", U"Remove pulse(s)", GuiMenu_OPTION + 'P', menu_cb_removePulses);
+	Editor_addCommand (this, U"Pulse", U"Remove pulse(s)", GuiMenu_OPTION | 'P', menu_cb_removePulses);
 
 	Editor_addMenu (this, U"Pitch", 0);
 	Editor_addCommand (this, U"Pitch", U"Add pitch point at cursor", 'T', menu_cb_addPitchPointAtCursor);
 	Editor_addCommand (this, U"Pitch", U"Add pitch point at time slice", 0, menu_cb_addPitchPointAtSlice);
 	Editor_addCommand (this, U"Pitch", U"Add pitch point at...", 0, menu_cb_addPitchPointAt);
 	Editor_addCommand (this, U"Pitch", U"-- remove pitch --", 0, nullptr);
-	Editor_addCommand (this, U"Pitch", U"Remove pitch point(s)", GuiMenu_OPTION + 'T', menu_cb_removePitchPoints);
+	Editor_addCommand (this, U"Pitch", U"Remove pitch point(s)", GuiMenu_OPTION | 'T', menu_cb_removePitchPoints);
 	Editor_addCommand (this, U"Pitch", U"-- pitch prefs --", 0, nullptr);
 	Editor_addCommand (this, U"Pitch", U"Set pitch range...", 0, menu_cb_setPitchRange);
 	Editor_addCommand (this, U"Pitch", U"Set pitch units...", 0, menu_cb_setPitchUnits);
@@ -564,7 +564,7 @@ void structManipulationEditor :: v_createMenus () {
 	Editor_addCommand (this, U"Dur", U"Add duration point at cursor", 'D', menu_cb_addDurationPointAtCursor);
 	Editor_addCommand (this, U"Dur", U"Add duration point at...", 0, menu_cb_addDurationPointAt);
 	Editor_addCommand (this, U"Dur", U"-- remove duration --", 0, nullptr);
-	Editor_addCommand (this, U"Dur", U"Remove duration point(s)", GuiMenu_OPTION + 'D', menu_cb_removeDurationPoints);
+	Editor_addCommand (this, U"Dur", U"Remove duration point(s)", GuiMenu_OPTION | 'D', menu_cb_removeDurationPoints);
 	Editor_addCommand (this, U"Dur", U"-- duration prefs --", 0, nullptr);
 	Editor_addCommand (this, U"Dur", U"Set duration range...", 0, menu_cb_setDurationRange);
 	Editor_addCommand (this, U"Dur", U"-- refresh duration --", 0, nullptr);
diff --git a/fon/ParamCurve.cpp b/fon/ParamCurve.cpp
index d9ace97..56f1aff 100644
--- a/fon/ParamCurve.cpp
+++ b/fon/ParamCurve.cpp
@@ -1,6 +1,6 @@
 /* ParamCurve.cpp
  *
- * Copyright (C) 1992-2012,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,35 +32,35 @@
 Thing_implement (ParamCurve, Function, 2);
 
 void structParamCurve :: v_info () {
-	double xmin = 1e308, xmax = -1e308, ymin = 1e308, ymax = -1e308;
+	double xvalmin = 1e308, xvalmax = -1e308, yvalmin = 1e308, yvalmax = -1e308;
 	for (long i = 1; i <= our x -> nx; i ++) {
 		double value = our x -> z [1] [i];
-		if (value < xmin) xmin = value;
-		if (value > xmax) xmax = value;
+		if (value < xvalmin) xvalmin = value;
+		if (value > xvalmax) xvalmax = value;
 	}
 	for (long i = 1; i <= y -> nx; i ++) {
 		double value = our y -> z [1] [i];
-		if (value < ymin) ymin = value;
-		if (value > ymax) ymax = value;
+		if (value < yvalmin) yvalmin = value;
+		if (value > yvalmax) yvalmax = value;
 	}
 	structDaata :: v_info ();
 	MelderInfo_writeLine (U"Domain:");
-	MelderInfo_writeLine (U"   tmin: ", xmin);
-	MelderInfo_writeLine (U"   tmax: ", xmax);
+	MelderInfo_writeLine (U"   tmin: ", our xmin);
+	MelderInfo_writeLine (U"   tmax: ", our xmax);
 	MelderInfo_writeLine (U"x sampling:");
 	MelderInfo_writeLine (U"   Number of values of t in x: ", our x -> nx);
 	MelderInfo_writeLine (U"   t step in x: ", our x -> dx, U" (sampling rate ", 1.0 / our x -> dx, U")");
 	MelderInfo_writeLine (U"   First t in x: ", our x -> x1);
 	MelderInfo_writeLine (U"x values:");
-	MelderInfo_writeLine (U"   Minimum x: ", xmin);
-	MelderInfo_writeLine (U"   Maximum x: ", xmax);
+	MelderInfo_writeLine (U"   Minimum x: ", xvalmin);
+	MelderInfo_writeLine (U"   Maximum x: ", xvalmax);
 	MelderInfo_writeLine (U"y sampling:");
 	MelderInfo_writeLine (U"   Number of values of t in y: ", our y -> nx);
 	MelderInfo_writeLine (U"   t step in y: ", our y -> dx, U" (sampling rate ", 1.0 / our y -> dx, U")");
 	MelderInfo_writeLine (U"   First t in y: ", our y -> x1);
 	MelderInfo_writeLine (U"y values:");
-	MelderInfo_writeLine (U"   Minimum y: ", ymin);
-	MelderInfo_writeLine (U"   Maximum y: ", ymax);
+	MelderInfo_writeLine (U"   Minimum y: ", yvalmin);
+	MelderInfo_writeLine (U"   Maximum y: ", yvalmax);
 }
 
 void structParamCurve :: v_writeText (MelderFile file) {
diff --git a/fon/PointEditor.cpp b/fon/PointEditor.cpp
index 5c3afba..7f61c22 100644
--- a/fon/PointEditor.cpp
+++ b/fon/PointEditor.cpp
@@ -141,7 +141,7 @@ void structPointEditor :: v_createMenus () {
 	Editor_addCommand (this, U"Point", U"Add point at cursor", 'P', menu_cb_addPointAtCursor);
 	Editor_addCommand (this, U"Point", U"Add point at...", 0, menu_cb_addPointAt);
 	Editor_addCommand (this, U"Point", U"-- remove point --", 0, nullptr);
-	Editor_addCommand (this, U"Point", U"Remove point(s)", GuiMenu_OPTION + 'P', menu_cb_removePoints);
+	Editor_addCommand (this, U"Point", U"Remove point(s)", GuiMenu_OPTION | 'P', menu_cb_removePoints);
 }
 
 void structPointEditor :: v_createHelpMenuItems (EditorMenu menu) {
diff --git a/fon/PointProcess.cpp b/fon/PointProcess.cpp
index ef79eea..ad18d75 100644
--- a/fon/PointProcess.cpp
+++ b/fon/PointProcess.cpp
@@ -205,15 +205,15 @@ void PointProcess_addPoint (PointProcess me, double t) {
 	}
 }
 
-void PointProcess_removePoint (PointProcess me, long index) {
-	if (index < 1 || index > my nt) return;
-	for (long i = index; i < my nt; i ++)
+void PointProcess_removePoint (PointProcess me, long pointNumber) {
+	if (pointNumber < 1 || pointNumber > my nt) return;
+	for (long i = pointNumber; i < my nt; i ++)
 		my t [i] = my t [i + 1];
 	my nt --;
 }
 
-void PointProcess_removePointNear (PointProcess me, double t) {
-	PointProcess_removePoint (me, PointProcess_getNearestIndex (me, t));
+void PointProcess_removePointNear (PointProcess me, double time) {
+	PointProcess_removePoint (me, PointProcess_getNearestIndex (me, time));
 }
 
 void PointProcess_removePoints (PointProcess me, long first, long last) {
diff --git a/fon/Praat_tests.cpp b/fon/Praat_tests.cpp
index fe9db69..c955528 100644
--- a/fon/Praat_tests.cpp
+++ b/fon/Praat_tests.cpp
@@ -333,4 +333,70 @@ int Praat_tests (int itest, char32 *arg1, char32 *arg2, char32 *arg3, char32 *ar
 	return 1;
 }
 
+/* More compiler stuff */
+#if 1
+/*
+	Trying out inheritance without encapsulation...
+	Advantage: everything is a method; therefore, the Law of Demeter is satisfied idiomatically
+	Disadvantage: problematic encapsulation
+*/
+Thing_declare (Matrix_);
+Thing_declare (Sound_);
+Thing_declare (Pitch_);
+
+/*
+	The following two sets of files have to be included
+	in Pitch_to_Sound.cpp as well as in Sound_to_Pitch.cpp,
+	but can come in either order:
+*/
+
+/*
+	Set 1: Pitch.h
+*/
+struct structPitch_ : structThing {
+	double f0;
+	autoSound_ toSound ();   // anti-encapsulation
+};
+
+/*
+	Set 2: Matrix.h followed by Sound.h
+*/
+struct structMatrix_ : structThing {
+	private: double x, y;
+	public: double getX () { return x; }
+	void setX (double newX) { x = newX; }
+};
+struct structSound_ : public structMatrix_ {   // the definition of structSound_ requires the prior definition of structMatrix_
+	autoPitch_ toPitch ();   // anti-encapsulation
+};
+
+/*
+	The following two files are independent of each other:
+*/
+
+/*
+	Pitch_to_Sound.cpp:
+	#include "Pitch.h"
+	#include "Sound.h"
+*/
+autoSound_ structPitch_::toSound () {   // this requires the prior definition of structPitch_ and the prior declaration of structSound_
+	autoSound_ result = autoSound_ ();
+	result -> setX (f0);   // this requires the prior definition of structSound_ and structMatrix_
+	return result;
+}
+
+/*
+	Sound_to_Pitch.cpp:
+	#include "Sound.h"
+	#include "Pitch.h"
+*/
+autoPitch_ structSound_::toPitch () {   // this requires the prior definition of structSound_ and the prior declaration of structPitch_
+	double x = getX ();   // this requires the prior definition of structSound_ and structMatrix_
+	autoPitch_ result = autoPitch_ ();
+	result -> f0 = x;   // this requires the prior definition of structPitch_
+	return result;
+}
+
+#endif
+
 /* End of file Praat_tests.cpp */
diff --git a/fon/RealTier.cpp b/fon/RealTier.cpp
index 1e7b50c..63a5d49 100644
--- a/fon/RealTier.cpp
+++ b/fon/RealTier.cpp
@@ -68,7 +68,7 @@ double structRealTier :: v_getFunction1 (long irow, double x) {
 	return RealTier_getValueAtTime (this, x);
 }
 
-Thing_implement (RealTier, AnyTier, 0);
+Thing_implement (RealTier, AnyTier, 0);   // the semantic superclass (see RealTier_def.h for explanation)
 
 void RealTier_init (RealTier me, double tmin, double tmax) {
 	my xmin = tmin;
diff --git a/fon/RealTier.h b/fon/RealTier.h
index 207bd01..1617a55 100644
--- a/fon/RealTier.h
+++ b/fon/RealTier.h
@@ -2,7 +2,7 @@
 #define _RealTier_h_
 /* RealTier.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -37,8 +37,6 @@ autoRealPoint RealPoint_create (double time, double value);
 
 /********** class RealTier **********/
 
-//oo_CLASS_CREATE (RealTier);
-
 void RealTier_init (RealTier me, double tmin, double tmax);
 autoRealTier RealTier_create (double tmin, double tmax);
 autoRealTier RealTier_createWithClass (double tmin, double tmax, ClassInfo klas);
diff --git a/fon/RealTierEditor.cpp b/fon/RealTierEditor.cpp
index 2145525..0ce1b90 100644
--- a/fon/RealTierEditor.cpp
+++ b/fon/RealTierEditor.cpp
@@ -1,6 +1,6 @@
 /* RealTierEditor.cpp
  *
- * Copyright (C) 1992-2011,2012,2013,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -97,7 +97,7 @@ void structRealTierEditor :: v_createMenus () {
 	EditorMenu_addCommand (menu, U"Add point at cursor", 'T', menu_cb_addPointAtCursor);
 	EditorMenu_addCommand (menu, U"Add point at...", 0, menu_cb_addPointAt);
 	EditorMenu_addCommand (menu, U"-- remove point --", 0, nullptr);
-	EditorMenu_addCommand (menu, U"Remove point(s)", GuiMenu_OPTION + 'T', menu_cb_removePoints);
+	EditorMenu_addCommand (menu, U"Remove point(s)", GuiMenu_OPTION | 'T', menu_cb_removePoints);
 }
 
 void RealTierEditor_updateScaling (RealTierEditor me) {
@@ -149,7 +149,7 @@ void structRealTierEditor :: v_dataChanged () {
 void structRealTierEditor :: v_draw () {
 	RealTier data = (RealTier) our data;
 	long n = data -> points.size;
-	Melder_casual (U"structRealTierEditor :: v_draw ", n);
+	trace (U"structRealTierEditor :: v_draw ", n);
 	Graphics_Viewport viewport;
 	if (our d_sound.data) {
 		viewport = Graphics_insetViewport (our d_graphics.get(), 0.0, 1.0, 1.0 - SOUND_HEIGHT, 1.0);
@@ -175,7 +175,7 @@ void structRealTierEditor :: v_draw () {
 	Graphics_text (our d_graphics.get(), our d_endWindow, our ymin,   Melder_float (Melder_half (our ymin)), our v_rightTickUnits ());
 	long ifirstSelected = AnyTier_timeToHighIndex (data->asAnyTier(), our d_startSelection);
 	long ilastSelected = AnyTier_timeToLowIndex (data->asAnyTier(), our d_endSelection);
-	Melder_casual (U"structRealTierEditor :: v_draw: selected from ", our d_startSelection, U" ",
+	trace (U"structRealTierEditor :: v_draw: selected from ", our d_startSelection, U" ",
 		ifirstSelected, U" to ", our d_endSelection, U" ", ilastSelected);
 	long imin = AnyTier_timeToHighIndex (data->asAnyTier(), our d_startWindow);
 	long imax = AnyTier_timeToLowIndex (data->asAnyTier(), our d_endWindow);
diff --git a/fon/RealTier_def.h b/fon/RealTier_def.h
index f5a27ab..195a9dc 100644
--- a/fon/RealTier_def.h
+++ b/fon/RealTier_def.h
@@ -1,6 +1,6 @@
 /* RealTier_def.h
  *
- * Copyright (C) 1992-2012,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,13 +26,18 @@ oo_END_CLASS (RealPoint)
 #undef ooSTRUCT
 
 
+/*
+	RealTier inherits from Function,
+	but most of the time a RealTier should also be able to pose as an AnyTier,
+	because the SortedSetDoubleOf contains RealPoints, which inherit from AnyPoints.
+*/
 #define ooSTRUCT RealTier
-oo_DEFINE_CLASS (RealTier, Function)
+oo_DEFINE_CLASS (RealTier, Function)   // syntactic inheritance
 
-	oo_COLLECTION_OF (SortedSetOfDoubleOf, points, RealPoint, 0)   // a kind of AnyTier though
+	oo_COLLECTION_OF (SortedSetOfDoubleOf, points, RealPoint, 0)   // semantically a kind of AnyTier though
 
 	#if oo_DECLARING
-		AnyTier_METHODS
+		AnyTier_METHODS   // the semantic superclass has to be copied in by hand (for shift() and scale())
 
 		void v_info ()
 			override;
diff --git a/fon/Sampled.cpp b/fon/Sampled.cpp
index 8a32e24..28cb1a2 100644
--- a/fon/Sampled.cpp
+++ b/fon/Sampled.cpp
@@ -189,7 +189,7 @@ static void Sampled_getSumAndDefinitionRange
 						definitionRange -= 0.5;   // delete constant extrapolation over 0.5 sample
 						sum -= 0.5 * rightValue;
 						if (NUMdefined (leftValue)) {
-							definitionRange += phase;   /* Add current fraction. */
+							definitionRange += phase;   // add current fraction
 							sum += phase * (rightValue + 0.5 * phase * (leftValue - rightValue));   // interpolate to outside sample
 						} else {
 							if (phase > 0.5) phase = 0.5;
diff --git a/fon/Sound.cpp b/fon/Sound.cpp
index 67596c3..25d05e9 100644
--- a/fon/Sound.cpp
+++ b/fon/Sound.cpp
@@ -919,12 +919,12 @@ autoSound Sound_createAsPureTone (long numberOfChannels, double startingTime, do
 	}
 }
 
-autoSound Sound_createFromToneComplex (double startingTime, double endTime, double sampleRate,
+autoSound Sound_createAsToneComplex (double startTime, double endTime, double samplingFrequency,
 	int phase, double frequencyStep, double firstFrequency, double ceiling, long numberOfComponents)
 {
 	try {
 		if (frequencyStep == 0.0)
-			Melder_throw (U"Frequency step must not be zero.");
+			Melder_throw (U"The frequency step should not be zero.");
 		/*
 		 * Translate default firstFrequency.
 		 */
@@ -933,7 +933,7 @@ autoSound Sound_createFromToneComplex (double startingTime, double endTime, doub
 		/*
 		 * Translate default ceiling.
 		 */
-		double omegaStep = 2 * NUMpi * frequencyStep, nyquistFrequency = 0.5 * sampleRate;
+		double omegaStep = 2 * NUMpi * frequencyStep, nyquistFrequency = 0.5 * samplingFrequency;
 		if (ceiling <= 0.0 || ceiling > nyquistFrequency) ceiling = nyquistFrequency;
 		/*
 		 * Translate number of components.
@@ -942,28 +942,29 @@ autoSound Sound_createFromToneComplex (double startingTime, double endTime, doub
 		if (numberOfComponents <= 0 || numberOfComponents > maximumNumberOfComponents)
 			numberOfComponents = maximumNumberOfComponents;
 		if (numberOfComponents < 1)
-			Melder_throw (U"Zero sine waves.");
+			Melder_throw (U"There would be zero sine waves.");
 		/*
 		 * Generate the Sound.
 		 */
 		double factor = 0.99 / numberOfComponents;
-		autoSound me = Sound_create (1, startingTime, endTime, lround ((endTime - startingTime) * sampleRate),
-			1.0 / sampleRate, startingTime + 0.5 / sampleRate);
+		autoSound me = Sound_create (1, startTime, endTime, lround ((endTime - startTime) * samplingFrequency),
+			1.0 / samplingFrequency, startTime + 0.5 / samplingFrequency);
 		double *amplitude = my z [1];
 		for (long isamp = 1; isamp <= my nx; isamp ++) {
 			double value = 0.0, t = Sampled_indexToX (me.get(), isamp);
 			double omegaStepT = omegaStep * t, firstOmegaT = firstOmega * t;
-			if (phase == Sound_TONE_COMPLEX_SINE)
+			if (phase == Sound_TONE_COMPLEX_SINE) {
 				for (long icomp = 1; icomp <= numberOfComponents; icomp ++)
 					value += sin (firstOmegaT + (icomp - 1) * omegaStepT);
-			else
+			} else {
 				for (long icomp = 1; icomp <= numberOfComponents; icomp ++)
 					value += cos (firstOmegaT + (icomp - 1) * omegaStepT);
+			}
 			amplitude [isamp] = value * factor;
 		}
 		return me;
 	} catch (MelderError) {
-		Melder_throw (U"Sound not created from tone complex.");
+		Melder_throw (U"Sound not created as tone complex.");
 	}
 }
 
diff --git a/fon/Sound.h b/fon/Sound.h
index ae315e0..36a002e 100644
--- a/fon/Sound.h
+++ b/fon/Sound.h
@@ -166,7 +166,7 @@ void Sound_setZero (Sound me, double tmin, double tmax, bool roundTimesToNearest
 
 autoSound Sound_createAsPureTone (long numberOfChannels, double startingTime, double endTime,
 	double sampleRate, double frequency, double amplitude, double fadeInDuration, double fadeOutDuration);
-autoSound Sound_createFromToneComplex (double startingTime, double endTime,
+autoSound Sound_createAsToneComplex (double startingTime, double endTime,
 	double sampleRate, int phase, double frequencyStep,
 	double firstFrequency, double ceiling, long numberOfComponents);
 /* Values for `phase' parameter: */
@@ -221,7 +221,7 @@ extern autoSound Sound_clipboard;
 
 /********** Sound_audio.cpp **********/
 
-autoSound Sound_recordFixedTime (int inputSource,
+autoSound Sound_record_fixedTime (int inputSource,
 	double gain, double balance, double samplingFrequency, double duration);
 	/*
 		Function:
@@ -244,7 +244,7 @@ autoSound Sound_recordFixedTime (int inputSource,
 				1.0 = right channel only.
 			samplingFrequency:
 				<=0.0 = do not change.
-				must be one of the sample rates supported by the hardware.
+				must be one of the sampling frequencies supported by the hardware.
 			duration:
 				positive time in seconds.
 		Return value:
@@ -300,9 +300,9 @@ void Sound_play (Sound me, Sound_PlayCallback playCallback, Thing playBoss);
 
 /* To avoid clipping, keep the absolute amplitude below 1.000. */
 /* All are mono or stereo PCM. */
-void Sound_writeToAudioFile (Sound me, MelderFile file, int audioFileType, int numberOfBitsPerSamplePoint);
-void Sound_writeToKayFile (Sound me, MelderFile file);   // 16-bit
-void Sound_writeToSesamFile (Sound me, MelderFile file);   // 12-bit SESAM/LVS
+void Sound_saveAsAudioFile (Sound me, MelderFile file, int audioFileType, int numberOfBitsPerSamplePoint);
+void Sound_saveAsKayFile (Sound me, MelderFile file);   // 16-bit
+void Sound_saveAsSesamFile (Sound me, MelderFile file);   // 12-bit SESAM/LVS
 
 autoSound Sound_readFromSoundFile (MelderFile file);   // AIFF, WAV, NeXT/Sun, or NIST
 autoSound Sound_readFromKayFile (MelderFile file);   // 16-bit
@@ -323,7 +323,7 @@ autoSound Sound_readFromRawSoundFile (MelderFile file, int encoding, int numberO
 	'numberOfChannels' is 1 (mono) or 2 (stereo)
 	'sampleRate' is in hertz
 */
-void Sound_writeToRawSoundFile (Sound me, MelderFile file, int encoding);
+void Sound_saveAsRawSoundFile (Sound me, MelderFile file, int encoding);
 /*
 	'encoding' is any of the following:
 		Melder_LINEAR_8_SIGNED
diff --git a/fon/SoundRecorder.cpp b/fon/SoundRecorder.cpp
index ff78a8d..fca57cb 100644
--- a/fon/SoundRecorder.cpp
+++ b/fon/SoundRecorder.cpp
@@ -661,7 +661,7 @@ static void initialize (SoundRecorder me) {
 			#if defined (macintosh)
 			#elif defined (_WIN32)
 				(void) me;
-			#elif defined (linux)
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				int sampleRate = (int) theControlPanel. sampleRate, sampleSize = 16;
 				int channels = my numberOfChannels, stereo = ( my numberOfChannels == 2 ), val;
 				#if __BYTE_ORDER == __BIG_ENDIAN
@@ -725,7 +725,7 @@ static void gui_radiobutton_cb_input (SoundRecorder me, GuiRadioButtonEvent even
 			} catch (MelderError) {
 				Melder_flushError ();
 			}
-		#elif defined (linux)
+		#elif defined (linux) && ! defined (NO_AUDIO)
 			int fd_mixer = open ("/dev/mixer", O_WRONLY);		
 			if (fd_mixer == -1) {
 				Melder_flushError (U"(Sound_record:) Cannot open /dev/mixer.");
@@ -774,7 +774,7 @@ static void gui_radiobutton_cb_fsamp (SoundRecorder me, GuiRadioButtonEvent even
 			#elif defined (macintosh)
 				//SPBCloseDevice (my refNum);
 				initialize (me);
-			#elif defined (linux)		
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				close (my fd);
 				initialize (me);
 			#endif
@@ -913,41 +913,41 @@ static void writeAudioFile (SoundRecorder me, MelderFile file, int audioFileType
 }
 
 static void menu_cb_writeWav (SoundRecorder me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save as WAV file", nullptr)
+	EDITOR_FORM_SAVE (U"Save as WAV file", nullptr)
 		char32 *name = GuiText_getString (my soundName);
 		Melder_sprint (defaultName,300, name, U".wav");
 		Melder_free (name);
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		writeAudioFile (me, file, Melder_WAV);
 	EDITOR_END
 }
 
 static void menu_cb_writeAifc (SoundRecorder me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save as AIFC file", nullptr)
+	EDITOR_FORM_SAVE (U"Save as AIFC file", nullptr)
 		char32 *name = GuiText_getString (my soundName);
 		Melder_sprint (defaultName,300, name, U".aifc");
 		Melder_free (name);
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		writeAudioFile (me, file, Melder_AIFC);
 	EDITOR_END
 }
 
 static void menu_cb_writeNextSun (SoundRecorder me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save as NeXT/Sun file", nullptr)
+	EDITOR_FORM_SAVE (U"Save as NeXT/Sun file", nullptr)
 		char32 *name = GuiText_getString (my soundName);
 		Melder_sprint (defaultName,300, name, U".au");
 		Melder_free (name);
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		writeAudioFile (me, file, Melder_NEXT_SUN);
 	EDITOR_END
 }
 
 static void menu_cb_writeNist (SoundRecorder me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save as NIST file", nullptr)
+	EDITOR_FORM_SAVE (U"Save as NIST file", nullptr)
 		char32 *name = GuiText_getString (my soundName);
 		Melder_sprint (defaultName,300, name, U".nist");
 		Melder_free (name);
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		writeAudioFile (me, file, Melder_NIST);
 	EDITOR_END
 }
diff --git a/fon/SoundRecorder.h b/fon/SoundRecorder.h
index 431282e..bc4ef00 100644
--- a/fon/SoundRecorder.h
+++ b/fon/SoundRecorder.h
@@ -34,10 +34,12 @@
 	#include <sys/ioctl.h>
 	#include <fcntl.h>
 	#include <unistd.h>
-	#if defined (__OpenBSD__) || defined (__NetBSD__)
-		#include <soundcard.h>
-	#else
-		#include <sys/soundcard.h>
+	#if ! defined (NO_AUDIO)
+		#if defined (__OpenBSD__) || defined (__NetBSD__)
+			#include <soundcard.h>
+		#else
+			#include <sys/soundcard.h>
+		#endif
 	#endif
 #endif
 
@@ -89,9 +91,11 @@ Thing_define (SoundRecorder, Editor) {
 	GuiMenuItem d_meterIntensityButton, d_meterCentreOfGravityVersusIntensityButton;
 	autoGraphics graphics;
 	bool inputUsesPortAudio;
+
 	const PaDeviceInfo *deviceInfos [1+SoundRecorder_IDEVICE_MAX];
 	PaDeviceIndex deviceIndices [1+SoundRecorder_IDEVICE_MAX];
 	PaStream *portaudioStream;
+
 	#if cocoa
 		CFRunLoopTimerRef d_cocoaTimer;
 	#elif motif
diff --git a/fon/Sound_audio.cpp b/fon/Sound_audio.cpp
index 157af61..769e01c 100644
--- a/fon/Sound_audio.cpp
+++ b/fon/Sound_audio.cpp
@@ -26,6 +26,8 @@
 
 #include "Sound.h"
 #include "Preferences.h"
+
+
 #include "../external/portaudio/portaudio.h"
 
 #if defined (macintosh)
@@ -39,10 +41,12 @@
 	#include "winport_off.h"
 #elif defined (linux)
 	#include <fcntl.h>
-	#if defined (__OpenBSD__) || defined (__NetBSD__)
-		#include <soundcard.h>
-	#else
-		#include <sys/soundcard.h>
+	#if ! defined (NO_AUDIO)
+		#if defined (__OpenBSD__) || defined (__NetBSD__)
+			#include <soundcard.h>
+		#else
+			#include <sys/soundcard.h>
+		#endif
 	#endif
 	#include <sys/ioctl.h>   /* ioctl */
 	#include <unistd.h>   /* open write close read */
@@ -93,6 +97,7 @@ static long getNumberOfSamplesRead (volatile struct Sound_recordFixedTime_Info *
 	volatile long numberOfSamplesRead = info -> numberOfSamplesRead;
 	return numberOfSamplesRead;
 }
+
 static int portaudioStreamCallback (
     const void *input, void *output,
     unsigned long frameCount,
@@ -119,7 +124,7 @@ static int portaudioStreamCallback (
 	return paContinue;
 }
 
-autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, double sampleRate, double duration) {
+autoSound Sound_record_fixedTime (int inputSource, double gain, double balance, double sampleRate, double duration) {
 	bool inputUsesPortAudio =
 		#if defined (_WIN32)
 			MelderAudio_getInputSoundSystem () == kMelder_inputSoundSystem_MME_VIA_PORTAUDIO;
@@ -209,7 +214,7 @@ autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, d
 		} else {
 			#if defined (macintosh)
 			#elif defined (_WIN32)
-			#else
+			#elif ! defined (NO_AUDIO)
 				/* We must open the port now, because we use an ioctl to set the info to an open port. */
 				fd = open (DEV_AUDIO, O_RDONLY);
 				if (fd == -1) {
@@ -238,7 +243,7 @@ autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, d
 			streamParameters. device = inputSource - 1;
 		} else {
 			#if defined (macintosh)
-			#elif defined (linux)
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				fd_mixer = open ("/dev/mixer", O_WRONLY);		
 				if (fd_mixer == -1)
 					Melder_throw (U"Cannot open /dev/mixer.");
@@ -255,7 +260,7 @@ autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, d
 		} else {
 			#if defined (macintosh) || defined (_WIN32)
 				/* Taken from Audio Control Panel. */
-			#elif defined (linux)
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				val = (gain <= 0.0 ? 0 : gain >= 1.0 ? 100 : floor (gain * 100 + 0.5));  
 				balance = balance <= 0 ? 0 : balance >= 1 ? 1 : balance;
 				if (balance >= 0.5) {
@@ -284,7 +289,7 @@ autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, d
 			// Set while opening.
 		} else {
 			#if defined (macintosh)
-			#elif defined (linux)
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				int sampleRate_int = (int) sampleRate;
 				if (ioctl (fd, SNDCTL_DSP_SPEED, & sampleRate_int) == -1)
 					Melder_throw (U"Cannot set sampling frequency to ", sampleRate, U" Hz.");
@@ -299,7 +304,7 @@ autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, d
 			streamParameters. channelCount = 1;
 		} else {
 			#if defined (macintosh)
-			#elif defined (linux)
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				val = 1;
 				if (ioctl (fd, SNDCTL_DSP_CHANNELS, & val) == -1)
 					Melder_throw (U"Cannot set to mono.");
@@ -314,7 +319,7 @@ autoSound Sound_recordFixedTime (int inputSource, double gain, double balance, d
 			streamParameters. sampleFormat = paInt16;
 		} else {
 			#if defined (macintosh)
-			#elif defined (linux)
+			#elif defined (linux) && ! defined (NO_AUDIO)
 				#if __BYTE_ORDER == __BIG_ENDIAN
 					val = AFMT_S16_BE;
 				#else
diff --git a/fon/Sound_files.cpp b/fon/Sound_files.cpp
index 622b8a8..0f3ff46 100644
--- a/fon/Sound_files.cpp
+++ b/fon/Sound_files.cpp
@@ -1,6 +1,6 @@
 /* Sound_files.cpp
  *
- * Copyright (C) 1992-2011,2012,2014,2015 Paul Boersma & David Weenink
+ * Copyright (C) 1992-2011,2012,2014,2015,2016 Paul Boersma & David Weenink
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
  * pb 2007/03/17 resistant against conflicting declarations of Collection
  * pb 2007/05/08 removed warning about stereo sounds
  * pb 2007/10/05 removed FSSpec
- * pb 2007/10/05 made Sound_readFromMacSoundFile compatible with sample rates between 32768 and 65535 Hz
+ * pb 2007/10/05 made Sound_readFromMacSoundFile compatible with sampling frequencies between 32768 and 65535 Hz
  * pb 2008/01/19 double
  * pb 2009/09/21 made stereo movies readable
  * pb 2010/12/27 support for multiple channels (i.e. more than two)
@@ -265,7 +265,7 @@ autoSound Sound_readFromRawAlawFile (MelderFile file) {
 	}
 }
 
-void Sound_writeToAudioFile (Sound me, MelderFile file, int audioFileType, int numberOfBitsPerSamplePoint) {
+void Sound_saveAsAudioFile (Sound me, MelderFile file, int audioFileType, int numberOfBitsPerSamplePoint) {
 	try {
 		autoMelderFile mfile = MelderFile_create (file);
 		MelderFile_writeAudioFileHeader (file, audioFileType, lround (1.0 / my dx), my nx, my ny, numberOfBitsPerSamplePoint);
@@ -277,7 +277,7 @@ void Sound_writeToAudioFile (Sound me, MelderFile file, int audioFileType, int n
 	}
 }
 
-void Sound_writeToSesamFile (Sound me, MelderFile file) {
+void Sound_saveAsSesamFile (Sound me, MelderFile file) {
 	try {
 		autofile f = Melder_fopen (file, "wb");
 		long header [1 + 128], tail;
@@ -306,7 +306,7 @@ void Sound_writeToSesamFile (Sound me, MelderFile file) {
 	}
 }
 
-void Sound_writeToKayFile (Sound me, MelderFile file) {
+void Sound_saveAsKayFile (Sound me, MelderFile file) {
 	try {
 		autoMelderFile mfile = MelderFile_create (file);
 
@@ -353,7 +353,7 @@ void Sound_writeToKayFile (Sound me, MelderFile file) {
 	}
 }
 
-void Sound_writeToRawSoundFile (Sound me, MelderFile file, int encoding) {
+void Sound_saveAsRawSoundFile (Sound me, MelderFile file, int encoding) {
 	try {
 		autoMelderFile mfile = MelderFile_create (file);
 		MelderFile_writeFloatToAudio (file, my ny, encoding, my z, my nx, true);
diff --git a/fon/TextGrid.cpp b/fon/TextGrid.cpp
index 6f96fb2..5e810a1 100644
--- a/fon/TextGrid.cpp
+++ b/fon/TextGrid.cpp
@@ -397,7 +397,7 @@ autoTextTier TextTier_readFromXwaves (MelderFile file) {
 			double time;
 			long colour;
 			char mark [300];
-			if (sscanf (line, "%lf%ld%s", & time, & colour, mark) < 3)   // BUG: buffer overflow
+			if (sscanf (line, "%lf%ld%299s", & time, & colour, mark) < 3)   // BUG: buffer overflow
 				Melder_throw (U"Line too short: \"", Melder_peek8to32 (line), U"\".");
 			TextTier_addPoint (me.get(), time, Melder_peek8to32 (mark));
 		}
@@ -924,7 +924,7 @@ autoIntervalTier IntervalTier_readFromXwaves (MelderFile file) {
 
 			line = MelderFile_readLine (file);
 			if (! line) break;   // normal end-of-file
-			numberOfElements = sscanf (line, "%lf%ld%s", & time, & colour, mark);
+			numberOfElements = sscanf (line, "%lf%ld%199s", & time, & colour, mark);
 			if (numberOfElements == 0) {
 				break;   // an empty line, hopefully at the end
 			}
@@ -1068,7 +1068,7 @@ static void genericize (char32 **pstring, char32 *buffer) {
 	}
 }
 
-void TextGrid_genericize (TextGrid me) {
+void TextGrid_convertToBackslashTrigraphs (TextGrid me) {
 	try {
 		autostring32 buffer = Melder_calloc (char32, TextGrid_maximumLabelLength (me) * 3 + 1);
 		for (long itier = 1; itier <= my tiers->size; itier ++) {
@@ -1092,7 +1092,7 @@ void TextGrid_genericize (TextGrid me) {
 	}
 }
 
-void TextGrid_nativize (TextGrid me) {
+void TextGrid_convertToUnicode (TextGrid me) {
 	try {
 		autostring32 buffer = Melder_calloc (char32, TextGrid_maximumLabelLength (me) + 1);
 		for (long itier = 1; itier <= my tiers->size; itier ++) {
diff --git a/fon/TextGrid.h b/fon/TextGrid.h
index 91e4fba..65e6d29 100644
--- a/fon/TextGrid.h
+++ b/fon/TextGrid.h
@@ -102,8 +102,8 @@ long TextPoint_labelLength (TextPoint me);
 long IntervalTier_maximumLabelLength (IntervalTier me);
 long TextTier_maximumLabelLength (TextTier me);
 long TextGrid_maximumLabelLength (TextGrid me);
-void TextGrid_genericize (TextGrid me);
-void TextGrid_nativize (TextGrid me);
+void TextGrid_convertToBackslashTrigraphs (TextGrid me);
+void TextGrid_convertToUnicode (TextGrid me);
 
 void TextInterval_removeText (TextInterval me);
 void TextPoint_removeText (TextPoint me);
diff --git a/fon/TextGridEditor.cpp b/fon/TextGridEditor.cpp
index 0417e57..5d2a3bf 100644
--- a/fon/TextGridEditor.cpp
+++ b/fon/TextGridEditor.cpp
@@ -183,9 +183,9 @@ void structTextGridEditor :: v_createMenuItems_file_extract (EditorMenu menu) {
 }
 
 static void menu_cb_WriteToTextFile (TextGridEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save as TextGrid text file", nullptr)
+	EDITOR_FORM_SAVE (U"Save as TextGrid text file", nullptr)
 		Melder_sprint (defaultName,300, my data -> name, U".TextGrid");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		Data_writeToTextFile (my data, file);
 	EDITOR_END
 }
@@ -273,17 +273,17 @@ static void menu_cb_Erase (TextGridEditor me, EDITOR_ARGS_DIRECT) {
 }
 #endif
 
-static void menu_cb_Genericize (TextGridEditor me, EDITOR_ARGS_DIRECT) {
+static void menu_cb_ConvertToBackslashTrigraphs (TextGridEditor me, EDITOR_ARGS_DIRECT) {
 	Editor_save (me, U"Convert to Backslash Trigraphs");
-	TextGrid_genericize ((TextGrid) my data);
+	TextGrid_convertToBackslashTrigraphs ((TextGrid) my data);
 	FunctionEditor_updateText (me);
 	FunctionEditor_redraw (me);
 	Editor_broadcastDataChanged (me);
 }
 
-static void menu_cb_Nativize (TextGridEditor me, EDITOR_ARGS_DIRECT) {
+static void menu_cb_ConvertToUnicode (TextGridEditor me, EDITOR_ARGS_DIRECT) {
 	Editor_save (me, U"Convert to Unicode");
-	TextGrid_nativize ((TextGrid) my data);
+	TextGrid_convertToUnicode ((TextGrid) my data);
 	FunctionEditor_updateText (me);
 	FunctionEditor_redraw (me);
 	Editor_broadcastDataChanged (me);
@@ -1162,12 +1162,8 @@ void structTextGridEditor :: v_createMenus () {
 		Editor_addCommand (this, U"Edit", U"Erase", Editor_HIDDEN, menu_cb_Erase);
 	#endif
 	Editor_addCommand (this, U"Edit", U"-- encoding --", 0, nullptr);
-	Editor_addCommand (this, U"Edit", U"Convert entire TextGrid to backslash trigraphs", 0, menu_cb_Genericize);
-	Editor_addCommand (this, U"Edit", U"Genericize entire TextGrid", Editor_HIDDEN, menu_cb_Genericize);
-	Editor_addCommand (this, U"Edit", U"Genericize", Editor_HIDDEN, menu_cb_Genericize);
-	Editor_addCommand (this, U"Edit", U"Convert entire TextGrid to Unicode", 0, menu_cb_Nativize);
-	Editor_addCommand (this, U"Edit", U"Nativize entire TextGrid", Editor_HIDDEN, menu_cb_Nativize);
-	Editor_addCommand (this, U"Edit", U"Nativize", Editor_HIDDEN, menu_cb_Nativize);
+	Editor_addCommand (this, U"Edit", U"Convert entire TextGrid to backslash trigraphs", 0, menu_cb_ConvertToBackslashTrigraphs);
+	Editor_addCommand (this, U"Edit", U"Convert entire TextGrid to Unicode", 0, menu_cb_ConvertToUnicode);
 	Editor_addCommand (this, U"Edit", U"-- search --", 0, nullptr);
 	Editor_addCommand (this, U"Edit", U"Find...", 'F', menu_cb_Find);
 	Editor_addCommand (this, U"Edit", U"Find again", 'G', menu_cb_FindAgain);
diff --git a/fon/TimeSoundAnalysisEditor.cpp b/fon/TimeSoundAnalysisEditor.cpp
index b8d5ffb..1c24128 100644
--- a/fon/TimeSoundAnalysisEditor.cpp
+++ b/fon/TimeSoundAnalysisEditor.cpp
@@ -932,7 +932,7 @@ static void menu_cb_drawVisibleIntensityContour (TimeSoundAnalysisEditor me, EDI
 		my v_form_pictureWindow (cmd);
 		my v_form_pictureMargins (cmd);
 		my v_form_pictureSelection (cmd);
-		BOOLEAN (U"Garnish", 1);
+		BOOLEAN (U"Garnish", true);
 	EDITOR_OK
 		my v_ok_pictureWindow (cmd);
 		my v_ok_pictureMargins (cmd);
@@ -1351,11 +1351,11 @@ static void cb_getJitter_xx (TimeSoundAnalysisEditor me, double (*PointProcess_g
 	Melder_informationReal (PointProcess_getJitter_xx (my d_pulses, my startSelection, my endSelection,
 		minimumPeriod, maximumPeriod, my p_pulses_maximumPeriodFactor), nullptr);
 }
-DIRECT (TimeSoundAnalysisEditor, cb_getJitter_local) cb_getJitter_xx (me, PointProcess_getJitter_local); END
-DIRECT (TimeSoundAnalysisEditor, cb_getJitter_local_absolute) cb_getJitter_xx (me, PointProcess_getJitter_local_absolute); END
-DIRECT (TimeSoundAnalysisEditor, cb_getJitter_rap) cb_getJitter_xx (me, PointProcess_getJitter_rap); END
-DIRECT (TimeSoundAnalysisEditor, cb_getJitter_ppq5) cb_getJitter_xx (me, PointProcess_getJitter_ppq5); END
-DIRECT (TimeSoundAnalysisEditor, cb_getJitter_ddp) cb_getJitter_xx (me, PointProcess_getJitter_ddp); END
+DIRECT (TimeSoundAnalysisEditor, cb_getJitter_local) { cb_getJitter_xx (me, PointProcess_getJitter_local); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getJitter_local_absolute) { cb_getJitter_xx (me, PointProcess_getJitter_local_absolute); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getJitter_rap) { cb_getJitter_xx (me, PointProcess_getJitter_rap); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getJitter_ppq5) { cb_getJitter_xx (me, PointProcess_getJitter_ppq5); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getJitter_ddp) { cb_getJitter_xx (me, PointProcess_getJitter_ddp); END }
 
 static void cb_getShimmer_xx (TimeSoundAnalysisEditor me, double (*PointProcess_Sound_getShimmer_xx) (PointProcess, Sound, double, double, double, double, double)) {
 	double minimumPeriod = 0.8 / my p_pitch_ceiling, maximumPeriod = 1.25 / my p_pitch_floor;
@@ -1372,12 +1372,12 @@ static void cb_getShimmer_xx (TimeSoundAnalysisEditor me, double (*PointProcess_
 	Melder_informationReal (PointProcess_Sound_getShimmer_xx (my d_pulses, sound, my startSelection, my endSelection,
 		minimumPeriod, maximumPeriod, my p_pulses_maximumAmplitudeFactor), nullptr);
 }
-DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_local) cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_local); END
-DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_local_dB) cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_local_dB); END
-DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_apq3) cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_apq3); END
-DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_apq5) cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_apq5); END
-DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_apq11) cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_apq11); END
-DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_dda) cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_dda); END
+DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_local) { cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_local); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_local_dB) { cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_local_dB); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_apq3) { cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_apq3); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_apq5) { cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_apq5); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_apq11) { cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_apq11); END }
+DIRECT (TimeSoundAnalysisEditor, cb_getShimmer_dda) { cb_getShimmer_xx (me, PointProcess_Sound_getShimmer_dda); END }
 */
 
 void structTimeSoundAnalysisEditor :: v_createMenuItems_view_sound (EditorMenu menu) {
@@ -1405,9 +1405,9 @@ void structTimeSoundAnalysisEditor :: v_createMenuItems_query_log (EditorMenu me
 	EditorMenu_addCommand (menu, U"Delete log file 1", 0, menu_cb_deleteLogFile1);
 	EditorMenu_addCommand (menu, U"Delete log file 2", 0, menu_cb_deleteLogFile2);
 	EditorMenu_addCommand (menu, U"Log 1", GuiMenu_F12, menu_cb_log1);
-	EditorMenu_addCommand (menu, U"Log 2", GuiMenu_F12 + GuiMenu_SHIFT, menu_cb_log2);
-	EditorMenu_addCommand (menu, U"Log script 3 (...)", GuiMenu_F12 + GuiMenu_OPTION, menu_cb_logScript3);
-	EditorMenu_addCommand (menu, U"Log script 4 (...)", GuiMenu_F12 + GuiMenu_COMMAND, menu_cb_logScript4);
+	EditorMenu_addCommand (menu, U"Log 2", GuiMenu_F12 | GuiMenu_SHIFT, menu_cb_log2);
+	EditorMenu_addCommand (menu, U"Log script 3 (...)", GuiMenu_F12 | GuiMenu_OPTION, menu_cb_logScript3);
+	EditorMenu_addCommand (menu, U"Log script 4 (...)", GuiMenu_F12 | GuiMenu_COMMAND, menu_cb_logScript4);
 }
 
 void structTimeSoundAnalysisEditor :: v_createMenus_analysis () {
@@ -1443,12 +1443,12 @@ void structTimeSoundAnalysisEditor :: v_createMenus_analysis () {
 		EditorMenu_addCommand (menu, U"Query:", GuiMenu_INSENSITIVE, menu_cb_getFrequency /* dummy */);
 		EditorMenu_addCommand (menu, U"Pitch listing", 0, menu_cb_pitchListing);
 		EditorMenu_addCommand (menu, U"Get pitch", GuiMenu_F5, menu_cb_getPitch);
-		EditorMenu_addCommand (menu, U"Get minimum pitch", GuiMenu_F5 + GuiMenu_COMMAND, menu_cb_getMinimumPitch);
-		EditorMenu_addCommand (menu, U"Get maximum pitch", GuiMenu_F5 + GuiMenu_SHIFT, menu_cb_getMaximumPitch);
+		EditorMenu_addCommand (menu, U"Get minimum pitch", GuiMenu_F5 | GuiMenu_COMMAND, menu_cb_getMinimumPitch);
+		EditorMenu_addCommand (menu, U"Get maximum pitch", GuiMenu_F5 | GuiMenu_SHIFT, menu_cb_getMaximumPitch);
 		EditorMenu_addCommand (menu, U"-- pitch select --", 0, nullptr);
 		EditorMenu_addCommand (menu, U"Select:", GuiMenu_INSENSITIVE, menu_cb_moveCursorToMinimumPitch /* dummy */);
-		EditorMenu_addCommand (menu, U"Move cursor to minimum pitch", GuiMenu_COMMAND + GuiMenu_SHIFT + 'L', menu_cb_moveCursorToMinimumPitch);
-		EditorMenu_addCommand (menu, U"Move cursor to maximum pitch", GuiMenu_COMMAND + GuiMenu_SHIFT + 'H', menu_cb_moveCursorToMaximumPitch);
+		EditorMenu_addCommand (menu, U"Move cursor to minimum pitch", GuiMenu_SHIFT | 'L', menu_cb_moveCursorToMinimumPitch);
+		EditorMenu_addCommand (menu, U"Move cursor to maximum pitch", GuiMenu_SHIFT | 'H', menu_cb_moveCursorToMaximumPitch);
 		v_createMenuItems_pitch_picture (menu);
 		EditorMenu_addCommand (menu, U"-- pitch extract --", 0, nullptr);
 		EditorMenu_addCommand (menu, U"Extract to objects window:", GuiMenu_INSENSITIVE, menu_cb_extractVisiblePitchContour /* dummy */);
@@ -1464,8 +1464,8 @@ void structTimeSoundAnalysisEditor :: v_createMenus_analysis () {
 		EditorMenu_addCommand (menu, U"Query:", GuiMenu_INSENSITIVE, menu_cb_getFrequency /* dummy */);
 		EditorMenu_addCommand (menu, U"Intensity listing", 0, menu_cb_intensityListing);
 		EditorMenu_addCommand (menu, U"Get intensity", GuiMenu_F8, menu_cb_getIntensity);
-		EditorMenu_addCommand (menu, U"Get minimum intensity", GuiMenu_F8 + GuiMenu_COMMAND, menu_cb_getMinimumIntensity);
-		EditorMenu_addCommand (menu, U"Get maximum intensity", GuiMenu_F8 + GuiMenu_SHIFT, menu_cb_getMaximumIntensity);
+		EditorMenu_addCommand (menu, U"Get minimum intensity", GuiMenu_F8 | GuiMenu_COMMAND, menu_cb_getMinimumIntensity);
+		EditorMenu_addCommand (menu, U"Get maximum intensity", GuiMenu_F8 | GuiMenu_SHIFT, menu_cb_getMaximumIntensity);
 		v_createMenuItems_intensity_picture (menu);
 		EditorMenu_addCommand (menu, U"-- intensity extract --", 0, nullptr);
 		EditorMenu_addCommand (menu, U"Extract to objects window:", GuiMenu_INSENSITIVE, menu_cb_extractVisibleIntensityContour /* dummy */);
diff --git a/fon/TimeSoundEditor.cpp b/fon/TimeSoundEditor.cpp
index fcfebee..39f6134 100644
--- a/fon/TimeSoundEditor.cpp
+++ b/fon/TimeSoundEditor.cpp
@@ -188,7 +188,7 @@ static void do_write (TimeSoundEditor me, MelderFile file, int format, int numbe
 	if (my d_startSelection >= my d_endSelection)
 		Melder_throw (U"No samples selected.");
 	if (my d_longSound.data) {
-		LongSound_writePartToAudioFile (my d_longSound.data, format, my d_startSelection, my d_endSelection, file, numberOfBitsPerSamplePoint);
+		LongSound_savePartAsAudioFile (my d_longSound.data, format, my d_startSelection, my d_endSelection, file, numberOfBitsPerSamplePoint);
 	} else if (my d_sound.data) {
 		Sound sound = my d_sound.data;
 		double margin = 0.0;
@@ -207,73 +207,73 @@ static void do_write (TimeSoundEditor me, MelderFile file, int format, int numbe
 					save -> z [channel] [i - offset] = sound -> z [channel] [i];
 				}
 			}
-			Sound_writeToAudioFile (save.get(), file, format, numberOfBitsPerSamplePoint);
+			Sound_saveAsAudioFile (save.get(), file, format, numberOfBitsPerSamplePoint);
 		}
 	}
 }
 
 static void menu_cb_WriteWav (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as WAV file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as WAV file", nullptr)
 		Melder_sprint (defaultName,300, my d_longSound.data ? my d_longSound.data -> name : my d_sound.data -> name, U".wav");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_WAV, 16);
 	EDITOR_END
 }
 
 static void menu_cb_SaveAs24BitWav (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as 24-bit WAV file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as 24-bit WAV file", nullptr)
 		Melder_assert (! my d_longSound.data && my d_sound.data);
 		Melder_sprint (defaultName,300, my d_sound.data -> name, U".wav");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_WAV, 24);
 	EDITOR_END
 }
 
 static void menu_cb_SaveAs32BitWav (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as 32-bit WAV file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as 32-bit WAV file", nullptr)
 		Melder_assert (! my d_longSound.data && my d_sound.data);
 		Melder_sprint (defaultName,300, my d_sound.data -> name, U".wav");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_WAV, 32);
 	EDITOR_END
 }
 
 static void menu_cb_WriteAiff (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as AIFF file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as AIFF file", nullptr)
 		Melder_sprint (defaultName,300, my d_longSound.data ? my d_longSound.data -> name : my d_sound.data -> name, U".aiff");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_AIFF, 16);
 	EDITOR_END
 }
 
 static void menu_cb_WriteAifc (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as AIFC file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as AIFC file", nullptr)
 		Melder_sprint (defaultName,300, my d_longSound.data ? my d_longSound.data -> name : my d_sound.data -> name, U".aifc");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_AIFC, 16);
 	EDITOR_END
 }
 
 static void menu_cb_WriteNextSun (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as NeXT/Sun file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as NeXT/Sun file", nullptr)
 		Melder_sprint (defaultName,300, my d_longSound.data ? my d_longSound.data -> name : my d_sound.data -> name, U".au");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_NEXT_SUN, 16);
 	EDITOR_END
 }
 
 static void menu_cb_WriteNist (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as NIST file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as NIST file", nullptr)
 		Melder_sprint (defaultName,300, my d_longSound.data ? my d_longSound.data -> name : my d_sound.data -> name, U".nist");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_NIST, 16);
 	EDITOR_END
 }
 
 static void menu_cb_WriteFlac (TimeSoundEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save selected sound as FLAC file", nullptr)
+	EDITOR_FORM_SAVE (U"Save selected sound as FLAC file", nullptr)
 		Melder_sprint (defaultName,300, my d_longSound.data ? my d_longSound.data -> name : my d_sound.data -> name, U".flac");
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		do_write (me, file, Melder_FLAC, 16);
 	EDITOR_END
 }
diff --git a/fon/manual_Exp.cpp b/fon/manual_ExperimentMFC.cpp
similarity index 99%
rename from fon/manual_Exp.cpp
rename to fon/manual_ExperimentMFC.cpp
index 9c6b276..136869f 100644
--- a/fon/manual_Exp.cpp
+++ b/fon/manual_ExperimentMFC.cpp
@@ -1,6 +1,6 @@
-/* manual_Exp.c
+/* manual_ExperimentMFC.cpp
  *
- * Copyright (C) 2001-2011,2013,2015 Paul Boersma
+ * Copyright (C) 2001-2011,2013,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +18,8 @@
 
 #include "ManPagesM.h"
 
-void manual_Exp_init (ManPages me);
-void manual_Exp_init (ManPages me) {
+void manual_ExperimentMFC_init (ManPages me);
+void manual_ExperimentMFC_init (ManPages me) {
 
 MAN_BEGIN (U"ExperimentMFC", U"ppgb", 20130101)
 INTRO (U"One of the @@types of objects@ in Praat, "
@@ -805,4 +805,4 @@ NORMAL (U"If you read this file with ##Read from file...#, you will see two Expe
 MAN_END
 }
 
-/* End of file manual_Exp.cpp */
+/* End of file manual_ExperimentMFC.cpp */
diff --git a/fon/manual_Script.cpp b/fon/manual_Script.cpp
index a11fd2d..8fccbe1 100644
--- a/fon/manual_Script.cpp
+++ b/fon/manual_Script.cpp
@@ -1499,7 +1499,7 @@ SCRIPT (5.4, Manual_SETTINGS_WINDOW_HEIGHT (4), U""
 	Manual_DRAW_SETTINGS_WINDOW ("Sound: Draw", 4)
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Time range (s)", "0.0", "0.0 (= all)")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Vertical range", "0.0", "0.0 (= auto)")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN ("Garnish", 1)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN ("Garnish", true)
 	Manual_DRAW_SETTINGS_WINDOW_OPTIONMENU ("Drawing method", "Curve")
 )
 NORMAL (U"In this example, all the settings have their standard values: you want to draw the whole time domain of the Sound, "
@@ -1516,7 +1516,7 @@ SCRIPT (5.4, Manual_SETTINGS_WINDOW_HEIGHT (4), U""
 	Manual_DRAW_SETTINGS_WINDOW ("Sound: Draw", 4)
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Time range (s)", "1.0", "3.2")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Vertical range", "-1", "1")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN ("Garnish", 0)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN ("Garnish", false)
 	Manual_DRAW_SETTINGS_WINDOW_OPTIONMENU ("Drawing method", "Poles")
 )
 NORMAL (U"In a script this would look like")
@@ -1536,7 +1536,7 @@ SCRIPT (5.4, Manual_SETTINGS_WINDOW_HEIGHT (6.1), U""   // 7 - 3 * 0.3 (three is
 	Manual_DRAW_SETTINGS_WINDOW ("Sound: Draw", 6.1)
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Time range (s)", "1.0", "3.2")
 	Manual_DRAW_SETTINGS_WINDOW_RANGE ("Vertical range", "-1", "1")
-	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN ("Garnish", 0)
+	Manual_DRAW_SETTINGS_WINDOW_BOOLEAN ("Garnish", false)
 	Manual_DRAW_SETTINGS_WINDOW_RADIO ("Drawing method", "Curve", 0)
 	"y -= 12\n"
 	Manual_DRAW_SETTINGS_WINDOW_RADIO ("", "Bars", 0)
@@ -3915,7 +3915,7 @@ CODE (U"endfor")
 CODE (U"selectObject: sound, textgrid")
 MAN_END
 
-MAN_BEGIN (U"Demo window", U"ppgb", 20150826)
+MAN_BEGIN (U"Demo window", U"ppgb", 20161130)
 INTRO (U"The Demo window is a window in which you can draw and ask for user input. "
 	"You can use it for demonstrations, presentations, simulations, adaptive listening experiments, "
 	"and stand-alone programs (see @@Scripting 9.1. Turning a script into a stand-alone program@).")
@@ -4034,12 +4034,12 @@ NORMAL (U"This uses two tricks, namely the possibility of following the #goto st
 	"and using #demoInput to quickly test for multiple possible inputs (the bullet represents a mouse click).")
 ENTRY (U"Getting click locations")
 NORMAL (U"You can use the functions #demoX and #demoY to see where the user has clicked. "
-	"These function respond in world coordinates. To see whether the user has clicked in the sound that occupies the "
-	"upper half of the screne in the above example, you do")
+	"These functions respond in world coordinates. To see whether the user has clicked in the sound that occupies the "
+	"upper half of the screen in the above example, you do for instance")
 CODE (U"while demoWaitForInput ( )")
 	CODE1 (U"if demoClicked ( )")
-		CODE2 (U"Select outer viewport: 0, 100, 50, 100")
-		CODE2 (U"Axes: 0, 3, -1, 1")
+		CODE2 (U"demo Select outer viewport: 0, 100, 50, 100")
+		CODE2 (U"demo Axes: 0, 3, -1, 1")
 		CODE2 (U"if #demoX ( ) >= 0 and demoX ( ) < 3 and #demoY ( ) >= -1 and demoY ( ) < 1")
 NORMAL (U"The last line can be shortened to:")
 		CODE2 (U"if #demoClickedIn (0, 3, -1, 1)")
@@ -4050,8 +4050,7 @@ CODE (U"demo Text: 50, \"centre\", 20, \"half\", \"Analyse\"")
 CODE (U"while demoWaitForInput ( )")
 	CODE1 (U"goto ANALYSE demoClickedIn (30, 70, 16, 24)")
 ENTRY (U"Full-screen viewing")
-NORMAL (U"When you click in the top right corner of the Demo window (64-bit Mac) "
-	"or in the \"zoom box\" (the green button in the title bar of the Demo window on 32-bit Mac), "
+NORMAL (U"When you click in the \"zoom box\" (the green button in the title bar of the Demo window on the Mac), "
 	"the Demo window will zoom out very strongly: it will fill up the whole screen. The menu bar becomes invisible, "
 	"although you can still make it temporarily visible and accessible by moving the mouse to the upper edge of the screen. "
 	"The Dock also becomes invisible, although you can make it temporarily visible and accessible by moving the mouse to the edge "
@@ -4089,6 +4088,10 @@ NORMAL (U"To see whether any function keys are pressed (during a mouse click or
 NORMAL (U"To put some text in the title bar of the Demo window, try")
 CODE (U"#demoWindowTitle: \"This is the title of my presentation\"")
 ENTRY (U"Tips and Tricks")
+NORMAL (U"The initial size of the Demo window when you start it up is 1344\\xx756 pixels, "
+	"which is 70 percent of a standard wide screen (1920\\xx1080 pixels). "
+	"This means that if a font looks good at a size of 35 in the initial Demo window, "
+	"the font will look equally good at a size of 50 when you use a 1920\\xx1080 video projector full-screen.")
 NORMAL (U"If you resize the Demo window with the handle in the bottom left, or if you zoom the window out to the full screen, "
 	"you may see that the relative positions of the contents of the window will change. Also, clicking on buttons and in parts "
 	"of the window may yield unexpected %x and %y values. It is therefore advisable to resize the window only if you are on a page "
diff --git a/fon/manual_sound.cpp b/fon/manual_sound.cpp
index 82beac5..154aee7 100644
--- a/fon/manual_sound.cpp
+++ b/fon/manual_sound.cpp
@@ -108,7 +108,7 @@ Create Sound from formula... 'Naam' Mono begintijd eindtijd samplefrequentie
 */
 MAN_END
 
-MAN_BEGIN (U"Create Sound from tone complex...", U"ppgb", 20140421)
+MAN_BEGIN (U"Create Sound as tone complex...", U"ppgb", 20161013)
 INTRO (U"A command in the @@New menu@ to create a @Sound as the sum of a number of sine waves "
 	"with equidistant frequencies.")
 ENTRY (U"Settings")
@@ -142,7 +142,7 @@ NORMAL (U"A series of pulses at regular intervals, "
 	"sampled after low-pass filtering at the Nyquist frequency, "
 	"can be regarded as a sum of cosine waves. For instance, a 100-Hz pulse train, "
 	"sampled at 44100 Hz, can be created with:")
-CODE (U"Create Sound from tone complex: \"train\", 0, 1, 44100, \"Cosine\", 100, 0, 0, 0")
+CODE (U"Create Sound as tone complex: \"train\", 0, 1, 44100, \"Cosine\", 100, 0, 0, 0")
 NORMAL (U"Supplying the value 0 for %firstFrequency yields an unshifted harmonic complex.")
 ENTRY (U"Example 2: a shifted harmonic complex")
 NORMAL (U"Some experiments on human pitch perception (%%residue pitch%) use "
@@ -150,9 +150,9 @@ NORMAL (U"Some experiments on human pitch perception (%%residue pitch%) use "
 	"related frequencies that are all shifted by a constant amount.")
 NORMAL (U"For instance, to get a sum of sine waves with frequencies 105 Hz, 205 Hz, and 305 Hz, "
 	"you would use:")
-CODE (U"Create Sound from tone complex: \"train\", 0.3, 1, 44100, \"Sine\", 100, 105, 0, 3")
+CODE (U"Create Sound as tone complex: \"train\", 0.3, 1, 44100, \"Sine\", 100, 105, 0, 3")
 NORMAL (U"or")
-CODE (U"Create Sound from tone complex: \"train\", 0.3, 1, 44100, \"Sine\", 100, 105, 350, 0")
+CODE (U"Create Sound as tone complex: \"train\", 0.3, 1, 44100, \"Sine\", 100, 105, 350, 0")
 NORMAL (U"whichever you prefer.")
 NORMAL (U"Some of these experiments are described in @@Plomp (1967)@ and @@Patterson & Wightman (1976)@.")
 ENTRY (U"Algorithm")
@@ -213,16 +213,16 @@ MAN_BEGIN (U"Record stereo Sound...", U"ppgb", 20021212)
 INTRO (U"A command in the @@New menu@ to record a @Sound. Creates a @SoundRecorder window.")
 MAN_END
 
-MAN_BEGIN (U"Sound", U"ppgb", 20110131)
+MAN_BEGIN (U"Sound", U"ppgb", 20161013)
 INTRO (U"One of the @@types of objects@ in Praat. For tutorial information, see all of the @Intro.")
 ENTRY (U"Commands")
 NORMAL (U"Creation:")
 LIST_ITEM (U"\\bu @@Record mono Sound...@ (from microphone or line input, with the @SoundRecorder)")
 LIST_ITEM (U"\\bu @@Record stereo Sound...@")
 LIST_ITEM (U"\\bu @@Create Sound from formula...@")
-LIST_ITEM (U"\\bu @@Create Sound from tone complex...")
-LIST_ITEM (U"\\bu @@Create Sound from gammatone...")
-LIST_ITEM (U"\\bu @@Create Sound from Shepard tone...")
+LIST_ITEM (U"\\bu @@Create Sound as tone complex...")
+LIST_ITEM (U"\\bu @@Create Sound as gammatone...")
+LIST_ITEM (U"\\bu @@Create Sound as Shepard tone...")
 NORMAL (U"Opening and saving:")
 LIST_ITEM (U"\\bu @@Sound files")
 NORMAL (U"You can also use the text and binary (real-valued) formats for Sounds, like for any other class:")
diff --git a/fon/manual_tutorials.cpp b/fon/manual_tutorials.cpp
index 65c7361..178462e 100644
--- a/fon/manual_tutorials.cpp
+++ b/fon/manual_tutorials.cpp
@@ -22,10 +22,14 @@
 void manual_tutorials_init (ManPages me);
 void manual_tutorials_init (ManPages me) {
 
-MAN_BEGIN (U"What's new?", U"ppgb", 20160925)
+MAN_BEGIN (U"What's new?", U"ppgb", 20161115)
 INTRO (U"Latest changes in Praat.")
 //LIST_ITEM (U"• Manual page about @@drawing a vowel triangle at .")
 
+NORMAL (U"##6.0.22# (15 November 2016)")
+LIST_ITEM (U"• Scripting: correct error messages for expressions like: 5 + \"hello\"")
+LIST_ITEM (U"• Command line: the --open option works correctly in the GUI if you open multiple files.")
+//LIST_ITEM (U"• Sound window: option for showing time in minutes instead of just seconds.")   // too confusing in UI
 NORMAL (U"##6.0.21# (25 September 2016)")
 LIST_ITEM (U"• ExperimentMFC: you can now specify font sizes and response keys for goodness judgments.")
 LIST_ITEM (U"• Table: when drawing ellipses, a font size of 0 can now be used to prevent drawing the labels.")
@@ -1256,7 +1260,7 @@ LIST_ITEM (U"• TextGrid & Pitch: draw with text alignment.")
 NORMAL (U"##4.3.26# (29 September 2005)")
 LIST_ITEM (U"• Macintosh: corrected error introduced in 4.3.25.")
 NORMAL (U"##4.3.25# (28 September 2005)")
-LIST_ITEM (U"• Macintosh: allowed recording with sample rates of 12 and 64 kHz.")
+LIST_ITEM (U"• Macintosh: allowed recording with sampling frequencies of 12 and 64 kHz.")
 NORMAL (U"##4.3.24# (26 September 2005)")
 LIST_ITEM (U"• Table: Down to TableOfReal...: one column of the Table can be used as the row labels for the TableOfReal, "
 	"and the strings in the remaining columns of the Table are replaced with whole numbers assigned in alphabetical order.")
@@ -3065,15 +3069,15 @@ NORMAL (U"To change the selection of one object (without changing the others), "
 	"use Control-click (Unix, Windows) or Command-click (Macintosh).")
 MAN_END
 
-MAN_BEGIN (U"New menu", U"ppgb", 20080427)
+MAN_BEGIN (U"New menu", U"ppgb", 20161013)
 INTRO (U"The ##New menu# is one of the menus in the @@Object window at . "
 	"You use this menu to create new objects from scratch. It contains the following commands:")
 LIST_ITEM (U"• @@Record mono Sound...@")
 LIST_ITEM (U"• @@Record stereo Sound...@")
 LIST_ITEM (U"• @@Create Sound from formula...@")
-LIST_ITEM (U"• @@Create Sound from tone complex...")
-LIST_ITEM (U"• @@Create Sound from gammatone...")
-LIST_ITEM (U"• @@Create Sound from Shepard tone...")
+LIST_ITEM (U"• @@Create Sound as tone complex...")
+LIST_ITEM (U"• @@Create Sound as gammatone...")
+LIST_ITEM (U"• @@Create Sound as Shepard tone...")
 LIST_ITEM (U"• @@Create Matrix...@ (from a formula)")
 LIST_ITEM (U"• @@Create simple Matrix...@ (from a formula)")
 LIST_ITEM (U"• @@Create empty PointProcess...@")
diff --git a/fon/praat_Exp.cpp b/fon/praat_Exp.cpp
deleted file mode 100644
index e644152..0000000
--- a/fon/praat_Exp.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/* praat_Exp.cpp
- *
- * Copyright (C) 2001-2012,2015 Paul Boersma
- *
- * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "praat.h"
-
-#include "ExperimentMFC.h"
-#include "RunnerMFC.h"
-
-/***** CATEGORIES *****/
-
-DIRECT2 (Categories_getEntropy) {
-	iam_ONLY (Categories);
-	double entropy = Categories_getEntropy (me);
-	Melder_informationReal (entropy, U"bits");
-END2 }
-
-DIRECT2 (Categories_sort) {
-	WHERE (SELECTED) {
-		iam_LOOP (Categories);
-		Categories_sort (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-/***** EXPERIMENT_MFC *****/
-
-DIRECT2 (ExperimentMFC_run) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot run experiments from the command line.");
-	autoRunnerMFC runner;
-	{// scope
-		/*
-			This `scope` comment refers to the idea that an autoThing (here, `experiments`)
-			is created in the beginning of the scope and invalidated at the end of the scope (by `move`).
-		*/
-		autoExperimentMFCList experiments = ExperimentMFCList_create ();
-		WHERE (SELECTED) {
-			iam_LOOP (ExperimentMFC);
-			Melder_assert (my classInfo == classExperimentMFC);
-			experiments -> addItem_ref (me);
-		}
-		Melder_assert (experiments->size >= 1);
-		Melder_assert (experiments->at [1] -> classInfo == classExperimentMFC);
-		Melder_assert (experiments->at [experiments->size] -> classInfo == classExperimentMFC);
-		runner = RunnerMFC_create (U"listening experiments", experiments.move());
-		/*
-			Now that `experiments` has been moved, it has become invalid.
-			We help the compiler notice this by ending the scope here:
-		*/
-	}
-	/*
-		As a result of the scope braces above, the compiler will now protest
-		if we refer to `experiments` in the next line. So instead we refer to the `runner`-internal experiments,
-		which are still in scope and haven't been invalidated:
-	*/
-	praat_installEditorN (runner.get(), runner -> experiments->asDaataList());   // refer to the moved version!
-	runner.releaseToUser();
-END2 }
-
-DIRECT2 (ExperimentMFC_extractResults) {
-	WHERE (SELECTED) {
-		iam_LOOP (ExperimentMFC);
-		autoResultsMFC thee = ExperimentMFC_extractResults (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-/***** RESULTS_MFC *****/
-
-DIRECT2 (ResultsMFC_getNumberOfTrials) {
-	iam_ONLY (ResultsMFC);
-	Melder_information (my numberOfTrials);
-END2 }
-
-FORM (ResultsMFC_getResponse, U"ResultsMFC: Get response", nullptr) {
-	NATURAL (U"Trial", U"1")
-	OK2
-DO
-	iam_ONLY (ResultsMFC);
-	long trial = GET_INTEGER (U"Trial");
-	if (trial > my numberOfTrials)
-		Melder_throw (U"Trial ", trial, U" does not exist (maximum ", my numberOfTrials, U").");
-	Melder_information (my result [trial]. response);
-END2 }
-
-FORM (ResultsMFC_getStimulus, U"ResultsMFC: Get stimulus", nullptr) {
-	NATURAL (U"Trial", U"1")
-	OK2
-DO
-	iam_ONLY (ResultsMFC);
-	long trial = GET_INTEGER (U"Trial");
-	if (trial > my numberOfTrials)
-		Melder_throw (U"Trial ", trial, U" does not exist (maximum ", my numberOfTrials, U").");
-	Melder_information (my result [trial]. stimulus);
-END2 }
-
-DIRECT2 (ResultsMFC_removeUnsharedStimuli) {
-	ResultsMFC res1 = nullptr, res2 = nullptr;
-	WHERE (SELECTED) { if (res1) res2 = (ResultsMFC) OBJECT; else res1 = (ResultsMFC) OBJECT; }
-	Melder_assert (res1 && res2);
-	autoResultsMFC result = ResultsMFC_removeUnsharedStimuli (res1, res2);
-	praat_new (result.move(), res2 -> name, U"_shared");
-END2 }
-
-DIRECT2 (ResultsMFC_to_Categories_stimuli) {
-	WHERE (SELECTED) {
-		iam_LOOP (ResultsMFC);
-		autoCategories thee = ResultsMFC_to_Categories_stimuli (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (ResultsMFC_to_Categories_responses) {
-	WHERE (SELECTED) {
-		iam_LOOP (ResultsMFC);
-		autoCategories thee = ResultsMFC_to_Categories_responses (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (ResultsMFCs_to_Table) {
-	OrderedOf<structResultsMFC> collection;
-	WHERE (SELECTED) {
-		iam_LOOP (ResultsMFC);
-		collection. addItem_ref (me);
-	}
-	autoTable thee = ResultsMFCs_to_Table (& collection);
-	praat_new (thee.move(), U"allResults");
-END2 }
-
-/***** buttons *****/
-
-void praat_uvafon_Exp_init ();
-void praat_uvafon_Exp_init () {
-	Thing_recognizeClassesByName (classExperimentMFC, classResultsMFC, nullptr);
-
-	praat_addAction1 (classCategories, 0, U"Sort", nullptr, 0, DO_Categories_sort);
-	praat_addAction1 (classCategories, 1, U"Get entropy", nullptr, 0, DO_Categories_getEntropy);
-
-	praat_addAction1 (classExperimentMFC, 0, U"Run", nullptr, 0, DO_ExperimentMFC_run);
-	praat_addAction1 (classExperimentMFC, 0, U"Extract results", nullptr, 0, DO_ExperimentMFC_extractResults);
-
-	praat_addAction1 (classResultsMFC, 0, U"Query -", nullptr, 0, nullptr);
-	praat_addAction1 (classResultsMFC, 1, U"Get number of trials", nullptr, 1, DO_ResultsMFC_getNumberOfTrials);
-	praat_addAction1 (classResultsMFC, 1, U"Get stimulus...", nullptr, 1, DO_ResultsMFC_getStimulus);
-	praat_addAction1 (classResultsMFC, 1, U"Get response...", nullptr, 1, DO_ResultsMFC_getResponse);
-	praat_addAction1 (classResultsMFC, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classResultsMFC, 2, U"Remove unshared stimuli", 0, 0, DO_ResultsMFC_removeUnsharedStimuli);
-	praat_addAction1 (classResultsMFC, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classResultsMFC, 0, U"To Categories (stimuli)", nullptr, 0, DO_ResultsMFC_to_Categories_stimuli);
-	praat_addAction1 (classResultsMFC, 0, U"To Categories (responses)", nullptr, 0, DO_ResultsMFC_to_Categories_responses);
-	praat_addAction1 (classResultsMFC, 0, U"Collect", nullptr, 0, nullptr);
-	praat_addAction1 (classResultsMFC, 0, U"Collect to Table", nullptr, 0, DO_ResultsMFCs_to_Table);
-}
-
-/* End of file praat_Exp.cpp */
diff --git a/fon/praat_ExperimentMFC.cpp b/fon/praat_ExperimentMFC.cpp
new file mode 100644
index 0000000..21f0e94
--- /dev/null
+++ b/fon/praat_ExperimentMFC.cpp
@@ -0,0 +1,158 @@
+/* praat_ExperimentMFC.cpp
+ *
+ * Copyright (C) 2001-2012,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "praat_ExperimentMFC.h"
+
+// MARK: - CATEGORIES
+
+// MARK: Query
+
+DIRECT (REAL_Categories_getEntropy) {
+	NUMBER_ONE (Categories)
+		double result = Categories_getEntropy (me);
+	NUMBER_ONE_END (U" bits")
+}
+
+// MARK: Modify
+
+DIRECT (MODIFY_Categories_sort) {
+	MODIFY_EACH (Categories)
+		Categories_sort (me);
+	MODIFY_EACH_END
+}
+
+// MARK: - EXPERIMENT_MFC
+
+DIRECT (WINDOW_ExperimentMFC_run) {
+		if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot run experiments from the command line.");
+		autoRunnerMFC runner;
+		{// scope
+			/*
+				This `scope` comment refers to the idea that an autoThing (here, `experiments`)
+				is created in the beginning of the scope and invalidated at the end of the scope (by `move`).
+			*/
+			autoExperimentMFCList experiments = ExperimentMFCList_create ();
+			WHERE (SELECTED) {
+				iam_LOOP (ExperimentMFC);
+				Melder_assert (my classInfo == classExperimentMFC);
+				experiments -> addItem_ref (me);
+			}
+			Melder_assert (experiments->size >= 1);
+			Melder_assert (experiments->at [1] -> classInfo == classExperimentMFC);
+			Melder_assert (experiments->at [experiments->size] -> classInfo == classExperimentMFC);
+			runner = RunnerMFC_create (U"listening experiments", experiments.move());
+			/*
+				Now that `experiments` has been moved, it has become invalid.
+				We help the compiler notice this by ending the scope here:
+			*/
+		}
+		/*
+			As a result of the scope braces above, the compiler will now protest
+			if we refer to `experiments` in the next line. So instead we refer to the `runner`-internal experiments,
+			which are still in scope and haven't been invalidated:
+		*/
+		praat_installEditorN (runner.get(), runner -> experiments->asDaataList());   // refer to the moved version!
+		runner.releaseToUser();
+	END
+}
+
+DIRECT (NEW_ExperimentMFC_extractResults) {
+	CONVERT_EACH (ExperimentMFC)
+		autoResultsMFC result = ExperimentMFC_extractResults (me);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - RESULTS_MFC
+
+DIRECT (INTEGER_ResultsMFC_getNumberOfTrials) {
+	NUMBER_ONE (ResultsMFC)
+		long result = my numberOfTrials;
+	NUMBER_ONE_END (U" trials")
+}
+
+FORM (STRING_ResultsMFC_getResponse, U"ResultsMFC: Get response", nullptr) {
+	NATURAL4 (trial, U"Trial", U"1")
+	OK
+DO
+	STRING_ONE (ResultsMFC)
+		if (trial > my numberOfTrials)
+			Melder_throw (U"Trial ", trial, U" does not exist (maximum ", my numberOfTrials, U").");
+		const char32 *result = my result [trial]. response;
+	STRING_ONE_END
+}
+
+FORM (STRING_ResultsMFC_getStimulus, U"ResultsMFC: Get stimulus", nullptr) {
+	NATURAL4 (trial, U"Trial", U"1")
+	OK
+DO
+	STRING_ONE (ResultsMFC)
+		if (trial > my numberOfTrials)
+			Melder_throw (U"Trial ", trial, U" does not exist (maximum ", my numberOfTrials, U").");
+		const char32 *result = my result [trial]. stimulus;
+	STRING_ONE_END
+}
+
+DIRECT (NEW1_ResultsMFC_removeUnsharedStimuli) {
+	CONVERT_COUPLE (ResultsMFC)
+		autoResultsMFC result = ResultsMFC_removeUnsharedStimuli (me, you);
+	CONVERT_COUPLE_END (your name, U"_shared")
+}
+
+DIRECT (NEW_ResultsMFC_to_Categories_stimuli) {
+	CONVERT_EACH (ResultsMFC)
+		autoCategories result = ResultsMFC_to_Categories_stimuli (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_ResultsMFC_to_Categories_responses) {
+	CONVERT_EACH (ResultsMFC)
+		autoCategories result = ResultsMFC_to_Categories_responses (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW1_ResultsMFCs_to_Table) {
+	CONVERT_LIST (ResultsMFC)
+		autoTable result = ResultsMFCs_to_Table (& list);
+	CONVERT_LIST_END (U"allResults")
+}
+
+// MARK: - buttons
+
+void praat_ExperimentMFC_init () {
+	Thing_recognizeClassesByName (classExperimentMFC, classResultsMFC, nullptr);
+
+	praat_addAction1 (classCategories, 0, U"Sort", nullptr, 0, MODIFY_Categories_sort);
+	praat_addAction1 (classCategories, 1, U"Get entropy", nullptr, 0, REAL_Categories_getEntropy);
+
+	praat_addAction1 (classExperimentMFC, 0, U"Run", nullptr, 0, WINDOW_ExperimentMFC_run);
+	praat_addAction1 (classExperimentMFC, 0, U"Extract results", nullptr, 0, NEW_ExperimentMFC_extractResults);
+
+	praat_addAction1 (classResultsMFC, 0, U"Query -", nullptr, 0, nullptr);
+	praat_addAction1 (classResultsMFC, 1, U"Get number of trials", nullptr, 1, INTEGER_ResultsMFC_getNumberOfTrials);
+	praat_addAction1 (classResultsMFC, 1, U"Get stimulus...", nullptr, 1, STRING_ResultsMFC_getStimulus);
+	praat_addAction1 (classResultsMFC, 1, U"Get response...", nullptr, 1, STRING_ResultsMFC_getResponse);
+	praat_addAction1 (classResultsMFC, 0, U"Modify", nullptr, 0, nullptr);
+	praat_addAction1 (classResultsMFC, 2, U"Remove unshared stimuli", 0, 0, NEW1_ResultsMFC_removeUnsharedStimuli);
+	praat_addAction1 (classResultsMFC, 0, U"Convert", nullptr, 0, nullptr);
+	praat_addAction1 (classResultsMFC, 0, U"To Categories (stimuli)", nullptr, 0, NEW_ResultsMFC_to_Categories_stimuli);
+	praat_addAction1 (classResultsMFC, 0, U"To Categories (responses)", nullptr, 0, NEW_ResultsMFC_to_Categories_responses);
+	praat_addAction1 (classResultsMFC, 0, U"Collect", nullptr, 0, nullptr);
+	praat_addAction1 (classResultsMFC, 0, U"Collect to Table", nullptr, 0, NEW1_ResultsMFCs_to_Table);
+}
+
+/* End of file praat_ExperimentMFC.cpp */
diff --git a/sys/InfoEditor.h b/fon/praat_ExperimentMFC.h
similarity index 63%
copy from sys/InfoEditor.h
copy to fon/praat_ExperimentMFC.h
index 032e683..4cb4b88 100644
--- a/sys/InfoEditor.h
+++ b/fon/praat_ExperimentMFC.h
@@ -1,8 +1,8 @@
-#ifndef _InfoEditor_h_
-#define _InfoEditor_h_
-/* InfoEditor.h
+#ifndef _praat_ExperimentMFC_h_
+#define _praat_ExperimentMFC_h_
+/* praat_ExperimentMFC.h
  *
- * Copyright (C) 2004-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,18 +18,15 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "TextEditor.h"
+/*
+	Interface functions for ExperimentMFC and RunnerMFC.
+*/
 
-Thing_define (InfoEditor, TextEditor) {
-	void v_destroy () noexcept
-		override;
-	bool v_scriptable ()
-		override { return false; }
-	bool v_fileBased ()
-		override { return false; }
-	void v_clear ()
-		override;
-};
+#include "ExperimentMFC.h"
+#include "RunnerMFC.h"
+#include "praat.h"
 
-/* End of file InfoEditor.h */
+void praat_ExperimentMFC_init ();
+
+/* End of file praat_ExperimentMFC.h */
 #endif
diff --git a/fon/praat_Fon.cpp b/fon/praat_Fon.cpp
index ee707ba..16da6ec 100644
--- a/fon/praat_Fon.cpp
+++ b/fon/praat_Fon.cpp
@@ -16,8 +16,6 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "praat.h"
-
 #include "AmplitudeTier.h"
 #include "AmplitudeTierEditor.h"
 #include "Cochleagram_and_Excitation.h"
@@ -39,10 +37,8 @@
 #include "Matrix_and_PointProcess.h"
 #include "Matrix_and_Polygon.h"
 #include "Matrix_extensions.h"
-
-#include "MovieWindow.h"
+#include "Movie.h"
 #include "ParamCurve.h"
-#include "Photo.h"
 #include "Pitch_Intensity.h"
 #include "Pitch_to_PitchTier.h"
 #include "Pitch_to_PointProcess.h"
@@ -71,413 +67,110 @@
 #include "VoiceAnalysis.h"
 #include "WordList.h"
 
+#include "praat_TimeTier.h"
+#include "praat_TimeFrameSampled.h"
+#include "praat_TimeVector.h"
+#include "praat_Sound.h"
+#include "praat_Matrix.h"
+#include "praat_Tiers.h"
+#include "praat_ExperimentMFC.h"
+#include "praat_uvafon.h"
+
 #undef iam
 #define iam iam_LOOP
 
-static const char32 *STRING_FROM_TIME_SECONDS = U"left Time range (s)";
-static const char32 *STRING_TO_TIME_SECONDS = U"right Time range (s)";
-static const char32 *STRING_FROM_TIME = U"left Time range";
-static const char32 *STRING_TO_TIME = U"right Time range";
 static const char32 *STRING_FROM_FREQUENCY_HZ = U"left Frequency range (Hz)";
 static const char32 *STRING_TO_FREQUENCY_HZ = U"right Frequency range (Hz)";
-static const char32 *STRING_FROM_FREQUENCY = U"left Frequency range";
-static const char32 *STRING_TO_FREQUENCY = U"right Frequency range";
-
-/***** Common dialog contents. *****/
-
-void praat_dia_timeRange (UiForm dia);
-void praat_dia_timeRange (UiForm dia) {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-}
-void praat_get_timeRange (UiForm dia, double *tmin, double *tmax);
-void praat_get_timeRange (UiForm dia, double *tmin, double *tmax) {
-	*tmin = GET_REAL (STRING_FROM_TIME);
-	*tmax = GET_REAL (STRING_TO_TIME);
-}
-int praat_get_frequencyRange (UiForm dia, double *fmin, double *fmax);
-int praat_get_frequencyRange (UiForm dia, double *fmin, double *fmax) {
-	*fmin = GET_REAL (STRING_FROM_FREQUENCY);
-	*fmax = GET_REAL (STRING_TO_FREQUENCY);
-	REQUIRE (*fmax > *fmin, U"Maximum frequency must be greater than minimum frequency.")
-	return 1;
-}
-static void dia_Vector_getExtremum (UiForm dia) {
-	UiField radio;
-	praat_dia_timeRange (dia);
-	RADIO (U"Interpolation", 2)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-}
-static void dia_Vector_getValue (UiForm dia) {
-	UiField radio;
-	REAL (U"Time (s)", U"0.5")
-	RADIO (U"Interpolation", 3)
-		RADIOBUTTON (U"Nearest")
-		RADIOBUTTON (U"Linear")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-}
 
-static void getTminTmaxFminFmax (UiForm 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, U"Maximum frequency must be greater than minimum frequency.")
-}
-#define GET_TMIN_TMAX_FMIN_FMAX \
-	double tmin, tmax, fmin, fmax; \
-	getTminTmaxFminFmax (dia, & tmin, & tmax, & fmin, & fmax);
+// MARK: - COCHLEAGRAM
 
-/***** Two auxiliary routines, exported. *****/
+// MARK: Help
 
-int praat_Fon_formula (UiForm dia, Interpreter interpreter);
-int praat_Fon_formula (UiForm dia, Interpreter interpreter) {
-	int IOBJECT;
-	LOOP {
-		iam (Matrix);
-		try {
-			Matrix_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-	return 1;
+DIRECT (HELP_Cochleagram_help) {
+	HELP (U"Cochleagram")
 }
 
-static autoGraphics graphics;
-
-static void gui_drawingarea_cb_expose (Thing /* boss */, GuiDrawingArea_ExposeEvent /* event */) {
-	if (! graphics) return;
-	Graphics_play (graphics.get(), graphics.get());
-}
+// MARK: Movie
 
-extern "C" Graphics Movie_create (const char32 *title, int width, int height);
-extern "C" Graphics Movie_create (const char32 *title, int width, int height) {
-	static GuiDialog dialog;
-	static GuiDrawingArea drawingArea;
-	if (! graphics) {
-		dialog = GuiDialog_create (theCurrentPraatApplication -> topShell, 100, 100, width + 2, height + 2, title, nullptr, nullptr, 0);
-		drawingArea = GuiDrawingArea_createShown (dialog, 0, width, 0, height, gui_drawingarea_cb_expose, nullptr, nullptr, nullptr, nullptr, 0);
-		GuiThing_show (dialog);
-		graphics = Graphics_create_xmdrawingarea (drawingArea);
-	}
-	GuiShell_setTitle (dialog, title);
-	GuiControl_setSize (dialog, width + 2, height + 2);
-	GuiControl_setSize (drawingArea, width, height);
-	GuiThing_show (dialog);
-	return graphics.get();
+DIRECT (MOVIE_Cochleagram_movie) {
+	MOVIE_ONE (Cochleagram, U"Cochleagram movie", 300, 300)
+		Matrix_movie (me, graphics);
+	MOVIE_ONE_END
 }
 
-/***** AMPLITUDETIER *****/
-
-FORM (AmplitudeTier_addPoint, U"Add one point", U"AmplitudeTier: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	REAL (U"Sound pressure (Pa)", U"0.8")
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		RealTier_addPoint (me, GET_REAL (U"Time"), GET_REAL (U"Sound pressure"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (AmplitudeTier_create, U"Create empty AmplitudeTier", nullptr) {
-	WORD (U"Name", U"empty")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	OK2
-DO
-	double startTime = GET_REAL (U"Start time"), endTime = GET_REAL (U"End time");
-	if (endTime <= startTime) Melder_throw (U"End time must be greater than start time.");
-	autoAmplitudeTier thee = AmplitudeTier_create (startTime, endTime);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END2 }
-
-DIRECT2 (AmplitudeTier_downto_PointProcess) {
-	LOOP {
-		iam (AmplitudeTier);
-		autoPointProcess thee = AnyTier_downto_PointProcess (me->asAnyTier());
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (AmplitudeTier_downto_TableOfReal) {
-	LOOP {
-		iam (AmplitudeTier);
-		autoTableOfReal thee = AmplitudeTier_downto_TableOfReal (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: Info
 
-DIRECT2 (AmplitudeTier_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an AmplitudeTier from batch.");
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;   // may stay null
-	}
-	LOOP if (CLASS == classAmplitudeTier) {
-		iam (AmplitudeTier);
-		autoAmplitudeTierEditor editor = AmplitudeTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-FORM (AmplitudeTier_formula, U"AmplitudeTier: Formula", U"AmplitudeTier: Formula...") {
-	LABEL (U"", U"# ncol = the number of points")
-	LABEL (U"", U"for col from 1 to ncol")
-	LABEL (U"", U"   # x = the time of the colth point, in seconds")
-	LABEL (U"", U"   # self = the value of the colth point, in Pascal")
-	LABEL (U"", U"   self = `formula'")
-	LABEL (U"", U"endfor")
-	TEXTFIELD (U"formula", U"- self ; upside down")
-	OK2
+FORM (REAL_Cochleagram_difference, U"Cochleagram difference", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
 DO
-	LOOP {
-		iam (AmplitudeTier);
-		try {
-			RealTier_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-END2 }
-
-static void dia_AmplitudeTier_getRangeProperty (UiForm dia) {
-	REAL (U"Shortest period (s)", U"0.0001")
-	REAL (U"Longest period (s)", U"0.02")
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
+	NUMBER_COUPLE (Cochleagram)
+		double result = Cochleagram_difference (me, you, fromTime, toTime);
+	NUMBER_COUPLE_END (U" hertz (root-mean-square)")
 }
 
-FORM (AmplitudeTier_getShimmer_local, U"AmplitudeTier: Get shimmer (local)", U"AmplitudeTier: Get shimmer (local)...") {
-	dia_AmplitudeTier_getRangeProperty (dia);
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		double shimmer = AmplitudeTier_getShimmer_local (me,
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum amplitude factor"));
-		Melder_informationReal (shimmer, nullptr);
-	}
-END2 }
-
-FORM (AmplitudeTier_getShimmer_local_dB, U"AmplitudeTier: Get shimmer (local, dB)", U"AmplitudeTier: Get shimmer (local, dB)...") {
-	dia_AmplitudeTier_getRangeProperty (dia);
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		double shimmer = AmplitudeTier_getShimmer_local_dB (me,
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum amplitude factor"));
-		Melder_informationReal (shimmer, nullptr);
-	}
-END2 }
-
-FORM (AmplitudeTier_getShimmer_apq3, U"AmplitudeTier: Get shimmer (apq3)", U"AmplitudeTier: Get shimmer (apq3)...") {
-	dia_AmplitudeTier_getRangeProperty (dia);
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		double shimmer = AmplitudeTier_getShimmer_apq3 (me,
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum amplitude factor"));
-		Melder_informationReal (shimmer, nullptr);
-	}
-END2 }
-
-FORM (AmplitudeTier_getShimmer_apq5, U"AmplitudeTier: Get shimmer (apq5)", U"AmplitudeTier: Get shimmer (apq5)...") {
-	dia_AmplitudeTier_getRangeProperty (dia);
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		double shimmer = AmplitudeTier_getShimmer_apq5 (me,
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum amplitude factor"));
-		Melder_informationReal (shimmer, nullptr);
-	}
-END2 }
-
-FORM (AmplitudeTier_getShimmer_apq11, U"AmplitudeTier: Get shimmer (apq11)", U"AmplitudeTier: Get shimmer (apq11)...") {
-	dia_AmplitudeTier_getRangeProperty (dia);
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		double shimmer = AmplitudeTier_getShimmer_apq11 (me,
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum amplitude factor"));
-		Melder_informationReal (shimmer, nullptr);
-	}
-END2 }
-
-FORM (AmplitudeTier_getShimmer_dda, U"AmplitudeTier: Get shimmer (dda)", U"AmplitudeTier: Get shimmer (dda)...") {
-	dia_AmplitudeTier_getRangeProperty (dia);
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		double shimmer = AmplitudeTier_getShimmer_dda (me,
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum amplitude factor"));
-		Melder_informationReal (shimmer, nullptr);
-	}
-END2 }
-
-/*FORM (AmplitudeTier_getValueAtTime, U"Get AmplitudeTier value", U"AmplitudeTier: Get value at time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	Melder_informationReal (RealTier_getValueAtTime (ONLY_OBJECT, GET_REAL (U"Time")), U"Pa");
-END2 }
-	
-FORM (AmplitudeTier_getValueAtIndex, U"Get AmplitudeTier value", U"AmplitudeTier: Get value at index...") {
-	INTEGER (U"Point number", U"10")
-	OK2
-DO
-	Melder_informationReal (RealTier_getValueAtIndex (ONLY_OBJECT, GET_INTEGER (U"Point number")), U"Pa");
-END2 }*/
-
-DIRECT2 (AmplitudeTier_help) {
-	Melder_help (U"AmplitudeTier");
-END2 }
-
-FORM (AmplitudeTier_to_IntensityTier, U"AmplitudeTier: To IntensityTier", U"AmplitudeTier: To IntensityTier...") {
-	REAL (U"Threshold (dB)", U"-10000.0")
-	OK2
-DO
-	LOOP {
-		iam (AmplitudeTier);
-		autoIntensityTier thee = AmplitudeTier_to_IntensityTier (me, GET_REAL (U"Threshold"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: Draw
 
-FORM (AmplitudeTier_to_Sound, U"AmplitudeTier: To Sound (pulse train)", U"AmplitudeTier: To Sound (pulse train)...") {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100")
-	NATURAL (U"Interpolation depth (samples)", U"2000")
-	OK2
+FORM (GRAPHICS_Cochleagram_paint, U"Paint Cochleagram", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	LOOP {
-		iam (AmplitudeTier);
-		autoSound thee = AmplitudeTier_to_Sound (me, GET_REAL (U"Sampling frequency"), GET_INTEGER (U"Interpolation depth"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (info_AmplitudeTier_Sound_edit) {
-	Melder_information (U"To include a copy of a Sound in your AmplitudeTier editor:\n"
-		"   select an AmplitudeTier and a Sound, and click \"View & Edit\".");
-END2 }
-
-/***** AMPLITUDETIER & SOUND *****/
-
-DIRECT2 (Sound_AmplitudeTier_multiply) {
-	Sound sound = nullptr;
-	AmplitudeTier tier = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-		if (CLASS == classAmplitudeTier) tier = (AmplitudeTier) OBJECT;
-	}
-	autoSound thee = Sound_AmplitudeTier_multiply (sound, tier);
-	praat_new (thee.move(), sound -> name, U"_amp");
-END2 }
-
-/***** COCHLEAGRAM *****/
+	GRAPHICS_EACH (Cochleagram)
+		Cochleagram_paint (me, GRAPHICS, fromTime, toTime, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Cochleagram_difference, U"Cochleagram difference", nullptr) {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	Cochleagram coch1 = nullptr, coch2 = nullptr;
-	LOOP (coch1 ? coch2 : coch1) = (Cochleagram) OBJECT;
-	Melder_informationReal (Cochleagram_difference (coch1, coch2,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range")), U"Hertz (root-mean-square)");
-END2 }
+// MARK: Modify
 
-FORM (Cochleagram_formula, U"Cochleagram Formula", U"Cochleagram: Formula...") {
+FORM (MODIFY_Cochleagram_formula, U"Cochleagram Formula", U"Cochleagram: Formula...") {
 	LABEL (U"label", U"`x' is time in seconds, `y' is place in Bark")
 	LABEL (U"label", U"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 (U"formula", U"self")
-	OK2
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
 DO
-	LOOP {
-		iam (Cochleagram);
-		try {
-			Matrix_formula (reinterpret_cast <Matrix> (me), GET_STRING (U"formula"), interpreter, NULL);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Cochleagram may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-DIRECT2 (Cochleagram_help) {
-	Melder_help (U"Cochleagram");
-END2 }
+	MODIFY_EACH_WEAK (Cochleagram)
+		Matrix_formula (me, formula, interpreter, NULL);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (Cochleagram_movie) {
-	Graphics g = Movie_create (U"Cochleagram movie", 300, 300);
-	LOOP {
-		iam (Cochleagram);
-		Matrix_movie (me, g);
-	}
-END2 }
+// MARK: Analyse
 
-FORM (Cochleagram_paint, U"Paint Cochleagram", nullptr) {
-	praat_dia_timeRange (dia);
-	BOOLEAN (U"Garnish", true)
-	OK2
+FORM (NEW_Cochleagram_to_Excitation, U"From Cochleagram to Excitation", nullptr) {
+	REAL4 (time, U"Time (s)", U"0.0")
+	OK
 DO
-	LOOP {
-		iam (Cochleagram);
-		autoPraatPicture picture;
-		Cochleagram_paint (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+	CONVERT_EACH (Cochleagram)
+		autoExcitation result = Cochleagram_to_Excitation (me, time);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Cochleagram_to_Excitation, U"From Cochleagram to Excitation", nullptr) {
-	REAL (U"Time (s)", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Cochleagram);
-		autoExcitation thee = Cochleagram_to_Excitation (me, GET_REAL (U"Time"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: Hack
 
-DIRECT2 (Cochleagram_to_Matrix) {
-	LOOP {
-		iam (Cochleagram);
-		autoMatrix thee = Cochleagram_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Cochleagram_to_Matrix) {
+	CONVERT_EACH (Cochleagram)
+		autoMatrix result = Cochleagram_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** CORPUS *****/
+// MARK: - CORPUS
 
-FORM (Corpus_create, U"Create Corpus", U"Create Corpus...") {
-	WORD (U"Name", U"myCorpus")
+// MARK: New
+
+FORM (NEW1_Corpus_create, U"Create Corpus", U"Create Corpus...") {
+	WORD4 (name, U"Name", U"myCorpus")
 	LABEL (U"", U"Folder with sound files:")
-	TEXTFIELD (U"folderWithSoundFiles", U"")
+	TEXTFIELD4 (folderWithSoundFiles, U"folderWithSoundFiles", U"")
 	LABEL (U"", U"Folder with annotation files:")
-	TEXTFIELD (U"folderWithAnnotationFiles", U"")
-	OK2
+	TEXTFIELD4 (folderWithAnnotationFiles, U"folderWithAnnotationFiles", U"")
+	OK
 DO
-END2 }
+END }
+
+// MARK: View & Edit
 
-DIRECT2 (Corpus_edit) {
+DIRECT (WINDOW_Corpus_edit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot edit a Corpus from batch.");
 	LOOP {
 		iam (Corpus);
@@ -485,1954 +178,1098 @@ DIRECT2 (Corpus_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-/***** DISTRIBUTIONS *****/
+// MARK: - DISTRIBUTIONS
 
-FORM (Distributions_to_Transition, U"To Transition", nullptr) {
-	NATURAL (U"Environment", U"1")
-	BOOLEAN (U"Greedy", true)
-	OK2
+FORM (NEW_Distributions_to_Transition, U"To Transition", nullptr) {
+	NATURAL4 (environment, U"Environment", U"1")
+	BOOLEAN4 (greedy, U"Greedy", true)
+	OK
 DO
-	LOOP {
-		iam (Distributions);
-		autoTransition thee = Distributions_to_Transition (me, nullptr, GET_INTEGER (U"Environment"), nullptr, GET_INTEGER (U"Greedy"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Distributions)
+		autoTransition result = Distributions_to_Transition (me, nullptr, environment, nullptr, greedy);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Distributions_to_Transition_adj, U"To Transition", nullptr) {
-	NATURAL (U"Environment", U"1")
-	BOOLEAN (U"Greedy", true)
-	OK2
+FORM (NEW1_Distributions_to_Transition_adj, U"To Transition", nullptr) {
+	NATURAL4 (environment, U"Environment", U"1")
+	BOOLEAN4 (greedy, U"Greedy", true)
+	OK
 DO
-	Distributions dist = nullptr;
-	Transition trans = nullptr;
-	LOOP {
-		if (CLASS == classDistributions) dist = (Distributions) OBJECT;
-		if (CLASS == classTransition) trans = (Transition) OBJECT;
-	}
-	autoTransition thee = Distributions_to_Transition (dist, nullptr, GET_INTEGER (U"Environment"), trans, GET_INTEGER (U"Greedy"));
-	praat_new (thee.move());
-END2 }
-
-FORM (Distributions_to_Transition_noise, U"To Transition (noise)", nullptr) {
-	NATURAL (U"Environment", U"1")
-	BOOLEAN (U"Greedy", true)
-	OK2
-DO
-	Distributions underlying = nullptr, surface = nullptr;
-	LOOP (underlying ? surface : underlying) = (Distributions) OBJECT;
-	autoTransition thee = Distributions_to_Transition (underlying, surface, GET_INTEGER (U"Environment"), nullptr, GET_INTEGER (U"Greedy"));
-	praat_new (thee.move());
-END2 }
-
-FORM (Distributions_to_Transition_noise_adj, U"To Transition (noise)", nullptr) {
-	NATURAL (U"Environment", U"1")
-	BOOLEAN (U"Greedy", true)
-	OK2
-DO
-	Distributions underlying = nullptr, surface = nullptr;
-	Transition trans = nullptr;
-	LOOP {
-		if (CLASS == classDistributions) (underlying ? surface : underlying) = (Distributions) OBJECT;
-		if (CLASS == classTransition) trans = (Transition) OBJECT;
-	}
-	autoTransition thee = Distributions_to_Transition (underlying, surface, GET_INTEGER (U"Environment"), trans, GET_INTEGER (U"Greedy"));
-	praat_new (thee.move());
-END2 }
+	CONVERT_TWO (Distributions, Transition)
+		autoTransition result = Distributions_to_Transition (me, nullptr, environment, you, greedy);
+	CONVERT_TWO_END (my name)
+}
 
-/***** DISTRIBUTIONS & TRANSITION *****/
+FORM (NEW1_Distributions_to_Transition_noise, U"To Transition (noise)", nullptr) {
+	NATURAL4 (environment, U"Environment", U"1")
+	BOOLEAN4 (greedy, U"Greedy", true)
+	OK
+DO
+	CONVERT_COUPLE (Distributions)
+		autoTransition result = Distributions_to_Transition (me, you, environment, nullptr, greedy);
+	CONVERT_COUPLE_END (my name)
+}
 
-DIRECT2 (Distributions_Transition_map) {
-	Distributions dist = nullptr;
-	Transition trans = nullptr;
-	LOOP {
-		if (CLASS == classDistributions) dist = (Distributions) OBJECT;
-		if (CLASS == classTransition) trans = (Transition) OBJECT;
-	}
-	autoDistributions thee = Distributions_Transition_map (dist, trans);
-	praat_new (thee.move(), U"surface");
-END2 }
+FORM (NEW1_Distributions_to_Transition_noise_adj, U"To Transition (noise)", nullptr) {
+	NATURAL4 (environment, U"Environment", U"1")
+	BOOLEAN4 (greedy, U"Greedy", true)
+	OK
+DO
+	CONVERT_COUPLE_AND_ONE (Distributions, Transition)
+		autoTransition result = Distributions_to_Transition (me, you, environment, him, greedy);
+	CONVERT_COUPLE_AND_ONE_END (my name)
+}
 
-/***** DURATIONTIER *****/
+// MARK: - DISTRIBUTIONS & TRANSITION
 
-FORM (DurationTier_addPoint, U"Add one point to DurationTier", U"DurationTier: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	REAL (U"Relative duration", U"1.5")
-	OK2
-DO
-	LOOP {
-		iam (DurationTier);
-		RealTier_addPoint (me, GET_REAL (U"Time"), GET_REAL (U"Relative duration"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (NEW1_Distributions_Transition_map) {
+	CONVERT_TWO (Distributions, Transition)
+		autoDistributions result = Distributions_Transition_map (me, you);
+	CONVERT_TWO_END (U"surface")
+}
 
-FORM (DurationTier_create, U"Create empty DurationTier", U"Create DurationTier...") {
-	WORD (U"Name", U"empty")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	OK2
-DO
-	double startTime = GET_REAL (U"Start time"), endTime = GET_REAL (U"End time");
-	if (endTime <= startTime) Melder_throw (U"End time must be greater than start time.");
-	autoDurationTier thee = DurationTier_create (startTime, endTime);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END2 }
+// MARK: - EXCITATION
 
-DIRECT2 (DurationTier_downto_PointProcess) {
-	LOOP {
-		iam (DurationTier);
-		autoPointProcess thee = AnyTier_downto_PointProcess (me->asAnyTier());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: Help
 
-DIRECT2 (DurationTier_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a DurationTier from batch.");
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;   // may stay null
-	}
-	LOOP if (CLASS == classDurationTier) {
-		iam (DurationTier);
-		autoDurationTierEditor editor = DurationTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-FORM (DurationTier_formula, U"DurationTier: Formula", U"DurationTier: Formula...") {
-	LABEL (U"", U"# ncol = the number of points")
-	LABEL (U"", U"for col from 1 to ncol")
-	LABEL (U"", U"   # x = the time of the colth point, in seconds")
-	LABEL (U"", U"   # self = the value of the colth point, in relative units")
-	LABEL (U"", U"   self = `formula'")
-	LABEL (U"", U"endfor")
-	TEXTFIELD (U"formula", U"self * 1.5 ; slow down")
-	OK2
-DO
-	LOOP {
-		iam (DurationTier);
-		try {
-			RealTier_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-END2 }
+DIRECT (HELP_Excitation_help) {
+	HELP (U"Excitation")
+}
 
-FORM (DurationTier_getTargetDuration, U"Get target duration", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1.0")
-	OK2
-DO
-	LOOP {
-		iam (DurationTier);
-		double area = RealTier_getArea (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (area, U"seconds");
-	}
-END2 }
+// MARK: Draw
 
-FORM (DurationTier_getValueAtTime, U"Get DurationTier value", U"DurationTier: Get value at time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (DurationTier);
-		double value = RealTier_getValueAtTime (me, GET_REAL (U"Time"));
-		Melder_informationReal (value, nullptr);
-	}
-END2 }
-	
-FORM (DurationTier_getValueAtIndex, U"Get DurationTier value", U"Duration: Get value at index...") {
-	INTEGER (U"Point number", U"10")
-	OK2
+FORM (GRAPHICS_Excitation_draw, U"Draw Excitation", nullptr) {
+	REAL4 (fromFrequency, U"From frequency (Bark)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Bark)", U"25.6")
+	REAL4 (minimum, U"Minimum (phon)", U"0.0")
+	REAL4 (maximum, U"Maximum (phon)", U"100.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	LOOP {
-		iam (DurationTier);
-		double value = RealTier_getValueAtIndex (me, GET_INTEGER (U"Point number"));
-		Melder_informationReal (value, nullptr);
-	}
-END2 }
-
-DIRECT2 (DurationTier_help) {
-	Melder_help (U"DurationTier");
-END2 }
+	GRAPHICS_EACH (Excitation)
+		Excitation_draw (me, GRAPHICS, fromFrequency, toFrequency, minimum, maximum, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (info_DurationTier_Sound_edit) {
-	Melder_information (U"To include a copy of a Sound in your DurationTier editor:\n"
-		"   select a DurationTier and a Sound, and click \"View & Edit\".");
-END2 }
+// MARK: Query
 
-/***** EXCITATION *****/
+DIRECT (REAL_Excitation_getLoudness) {
+	NUMBER_ONE (Excitation)
+		double result = Excitation_getLoudness (me);
+	NUMBER_ONE_END (U" sones")
+}
 
-FORM (Excitation_draw, U"Draw Excitation", 0) {
-	REAL (U"From frequency (Bark)", U"0")
-	REAL (U"To frequency (Bark)", U"25.6")
-	REAL (U"Minimum (phon)", U"0")
-	REAL (U"Maximum (phon)", U"100")
-	BOOLEAN (U"Garnish", 1)
-	OK2
-DO
-	LOOP {
-		iam (Excitation);
-		autoPraatPicture picture;
-		Excitation_draw (me, GRAPHICS,
-			GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+// MARK: Modify
 
-FORM (Excitation_formula, U"Excitation Formula", U"Excitation: Formula...") {
+FORM (MODIFY_Excitation_formula, U"Excitation Formula", U"Excitation: Formula...") {
 	LABEL (U"label", U"`x' is the place in Bark, `col' is the bin number")
 	LABEL (U"label", U"x := 0;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
-	TEXTFIELD (U"formula", U"self")
-	OK2
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
 DO
-	LOOP {
-		iam (Excitation);
-		try {
-			Matrix_formula (reinterpret_cast <Matrix> (me), GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-END2 }
-
-DIRECT2 (Excitation_getLoudness) {
-	LOOP {
-		iam (Excitation);
-		double loudness = Excitation_getLoudness (me);
-		Melder_informationReal (loudness, U"sones");
-	}
-END2 }
+	MODIFY_EACH_WEAK (Excitation)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (Excitation_help) {
-	Melder_help (U"Excitation");
-END2 }
+// MARK: Convert
 
-FORM (Excitation_to_Formant, U"From Excitation to Formant", 0) {
-	NATURAL (U"Maximum number of formants", U"20")
-	OK2
+FORM (NEW_Excitation_to_Formant, U"From Excitation to Formant", 0) {
+	NATURAL4 (maximumNumberOfFormants, U"Maximum number of formants", U"20")
+	OK
 DO
-	LOOP {
-		iam (Excitation);
-		autoFormant thee = Excitation_to_Formant (me, GET_INTEGER (U"Maximum number of formants"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Excitation)
+		autoFormant result = Excitation_to_Formant (me, maximumNumberOfFormants);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Excitation_to_Matrix) {
-	LOOP {
-		iam (Excitation);
-		autoMatrix thee = Excitation_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Excitation_to_Matrix) {
+	CONVERT_EACH (Excitation)
+		autoMatrix result = Excitation_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** FORMANT *****/
+// MARK: - FORMANT
 
-DIRECT2 (Formant_downto_FormantGrid) {
-	LOOP {
-		iam (Formant);
-		autoFormantGrid thee = Formant_downto_FormantGrid (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: Help
 
-DIRECT2 (Formant_downto_FormantTier) {
-	LOOP {
-		iam (Formant);
-		autoFormantTier thee = Formant_downto_FormantTier (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (HELP_Formant_help) {
+	HELP (U"Formant")
+}
 
-FORM (Formant_drawSpeckles, U"Draw Formant", U"Formant: Draw speckles...") {
-	praat_dia_timeRange (dia);
-	POSITIVE (U"Maximum frequency (Hz)", U"5500.0")
-	REAL (U"Dynamic range (dB)", U"30.0")
-	BOOLEAN (U"Garnish", 1)
-	OK2
-DO
-	LOOP {
-		iam (Formant);
-		autoPraatPicture picture;
-		Formant_drawSpeckles (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Maximum frequency"),
-			GET_REAL (U"Dynamic range"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+// MARK: Draw
 
-FORM (Formant_drawTracks, U"Draw formant tracks", U"Formant: Draw tracks...") {
-	praat_dia_timeRange (dia);
-	POSITIVE (U"Maximum frequency (Hz)", U"5500.0")
-	BOOLEAN (U"Garnish", 1)
-	OK2
+FORM (GRAPHICS_Formant_drawSpeckles, U"Draw Formant", U"Formant: Draw speckles...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	REALVAR (dynamicRange, U"Dynamic range (dB)", U"30.0")
+	BOOLEANVAR (garnish, U"Garnish", 1)
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		autoPraatPicture picture;
-		Formant_drawTracks (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Maximum frequency"),
-			GET_INTEGER (U"Garnish"));
-	}
-END2 }
+	GRAPHICS_EACH (Formant)
+		Formant_drawSpeckles (me, GRAPHICS, fromTime, toTime, maximumFrequency, dynamicRange, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Formant_formula_bandwidths, U"Formant: Formula (bandwidths)", U"Formant: Formula (bandwidths)...") {
-	LABEL (U"", U"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 (U"formula", U"self / 2 ; sharpen all peaks")
-	OK2
+FORM (GRAPHICS_Formant_drawTracks, U"Draw formant tracks", U"Formant: Draw tracks...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	BOOLEANVAR (garnish, U"Garnish", 1)
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		try {
-			Formant_formula_bandwidths (me, GET_STRING (U"formula"), interpreter);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Formant may have partially changed
-			throw;
-		}
-	}
-END2 }
+	GRAPHICS_EACH (Formant)
+		Formant_drawTracks (me, GRAPHICS, fromTime, toTime, maximumFrequency, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Formant_formula_frequencies, U"Formant: Formula (frequencies)", U"Formant: Formula (frequencies)...") {
-	LABEL (U"", U"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 (U"formula", U"if row = 2 then self + 200 else self fi")
-	OK2
+FORM (GRAPHICS_Formant_scatterPlot, U"Formant: Scatter plot", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	NATURAL4 (horizontalFormantNumber, U"Horizontal formant number", U"2")
+	REAL4 (left, U"left Horizontal range (Hz)", U"3000.0")
+	REAL4 (right, U"right Horizontal range (Hz)", U"400.0")
+	NATURAL4 (verticalFormantNumber, U"Vertical formant number", U"1")
+	REAL4 (bottom, U"left Vertical range (Hz)", U"1500.0")
+	REAL4 (top, U"right Vertical range (Hz)", U"100.0")
+	POSITIVE4 (markSize, U"Mark size (mm)", U"1.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	SENTENCE4 (markString, U"Mark string (+xo.)", U"+")
+	OK
+DO
+	GRAPHICS_EACH (Formant)
+		Formant_scatterPlot (me, GRAPHICS, fromTime, toTime,
+			horizontalFormantNumber, left, right, verticalFormantNumber, bottom, top,
+			markSize, markString, garnish);
+	GRAPHICS_EACH_END
+}
+
+// MARK: Tabulate
+
+FORM (LIST_Formant_list, U"Formant: List", nullptr) {
+	BOOLEAN4 (includeFrameNumber, U"Include frame number", false)
+	BOOLEAN4 (includeTime, U"Include time", true)
+	NATURAL4 (numberOfTimeDecimals, U"Number of time decimals", U"6")
+	BOOLEAN4 (includeIntensity, U"Include intensity", false)
+	NATURAL4 (numberOfIntensityDecimals, U"Number of intensity decimals", U"3")
+	BOOLEAN4 (includeNumberOfFormants, U"Include number of formants", true)
+	NATURAL4 (numberOfFrequencyDecimals, U"Number of frequency decimals", U"3")
+	BOOLEAN4 (includeBandwidths, U"Include bandwidths", true)
+	OK
+DO
+	INFO_ONE (Formant)
+		Formant_list (me, includeFrameNumber, includeTime, numberOfTimeDecimals,
+			includeIntensity, numberOfIntensityDecimals, includeNumberOfFormants, numberOfFrequencyDecimals,
+			includeBandwidths);
+	INFO_ONE_END
+}
+
+FORM (NEW_Formant_downto_Table, U"Formant: Down to Table", nullptr) {
+	BOOLEAN4 (includeFrameNumber, U"Include frame number", false)
+	BOOLEAN4 (includeTime, U"Include time", true)
+	NATURAL4 (numberOfTimeDecimals, U"Number of time decimals", U"6")
+	BOOLEAN4 (includeIntensity, U"Include intensity", false)
+	NATURAL4 (numberOfIntensityDecimals, U"Number of intensity decimals", U"3")
+	BOOLEAN4 (includeNumberOfFormants, U"Include number of formants", true)
+	NATURAL4 (numberOfFrequencyDecimals, U"Number of frequency decimals", U"3")
+	BOOLEAN4 (includeBandwidths, U"Include bandwidths", true)
+	OK
+DO
+	CONVERT_EACH (Formant)
+		autoTable result = Formant_downto_Table (me, includeFrameNumber, includeTime, numberOfTimeDecimals,
+			includeIntensity, numberOfIntensityDecimals, includeNumberOfFormants, numberOfFrequencyDecimals,
+			includeBandwidths);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: Query
+
+FORM (REAL_Formant_getValueAtTime, U"Formant: Get value", U"Formant: Get value at time...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	RADIO4x (unit, U"Unit", 1, 0)
+		RADIOBUTTON (U"Hertz")
+		RADIOBUTTON (U"Bark")
+	RADIO4 (interpolation, U"Interpolation", 1)   // ignored
+		RADIOBUTTON (U"Linear")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		try {
-			Formant_formula_frequencies (me, GET_STRING (U"formula"), interpreter);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Formant may have partially changed
-			throw;
-		}
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getValueAtTime (me, formantNumber, time, unit);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-FORM (Formant_getBandwidthAtTime, U"Formant: Get bandwidth", U"Formant: Get bandwidth at time...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getBandwidthAtTime, U"Formant: Get bandwidth", U"Formant: Get bandwidth at time...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	RADIO4x (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	RADIO (U"Interpolation", 1)
+	RADIO4 (interpolation, U"Interpolation", 1)   // ignored
 		RADIOBUTTON (U"Linear")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double bandwidth = Formant_getBandwidthAtTime (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), GET_INTEGER (U"Unit") - 1);
-		Melder_informationReal (bandwidth, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
-	
-FORM (Formant_getMaximum, U"Formant: Get maximum", U"Formant: Get maximum...") {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+	NUMBER_ONE (Formant)
+		double result = Formant_getBandwidthAtTime (me, formantNumber, time, unit);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
+
+FORM (REAL_Formant_getMinimum, U"Formant: Get minimum", U"Formant: Get minimum...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4x (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	RADIO (U"Interpolation", 2)
+	RADIO4x (interpolation, U"Interpolation", 2, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double maximum = Formant_getMaximum (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Unit") - 1, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (maximum, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
-
-DIRECT2 (Formant_getMaximumNumberOfFormants) {
-	LOOP {
-		iam (Formant);
-		long maximumNumberOfFormants = Formant_getMaxNumFormants (me);
-		Melder_information (maximumNumberOfFormants, U" (there are at most this many formants in every frame)");
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getMinimum (me, formantNumber, fromTime, toTime, unit, interpolation);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-FORM (Formant_getMean, U"Formant: Get mean", U"Formant: Get mean...") {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getMaximum, U"Formant: Get maximum", U"Formant: Get maximum...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4x (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	OK2
+	RADIO4x (interpolation, U"Interpolation", 2, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double mean = Formant_getMean (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Unit") - 1);
-		Melder_informationReal (mean, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getMaximum (me, formantNumber, fromTime, toTime, unit, interpolation);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-FORM (Formant_getMinimum, U"Formant: Get minimum", U"Formant: Get minimum...") {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getTimeOfMinimum, U"Formant: Get time of minimum", U"Formant: Get time of minimum...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4x (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	RADIO (U"Interpolation", 2)
+	RADIO4x (interpolation, U"Interpolation", 2, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
-	OK2
-DO
-	LOOP {
-		iam (Formant);
-		double minimum = Formant_getMinimum (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Unit") - 1,
-			GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (minimum, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
-
-DIRECT2 (Formant_getMinimumNumberOfFormants) {
-	LOOP {
-		iam (Formant);
-		long minimumNumberOfFormants = Formant_getMinNumFormants (me);
-		Melder_information (minimumNumberOfFormants, U" (there are at least this many formants in every frame)");
-		break;
-	}
-END2 }
-
-FORM (Formant_getNumberOfFormants, U"Formant: Get number of formants", U"Formant: Get number of formants...") {
-	NATURAL (U"Frame number", U"1")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		long frame = GET_INTEGER (U"Frame number");
-		if (frame > my nx) Melder_throw (U"There is no frame ", frame, U" in a Formant with only ", my nx, U" frames.");
-		Melder_information (my d_frames [frame]. nFormants, U" formants");
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getTimeOfMinimum (me, formantNumber, fromTime, toTime, unit, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
 
-FORM (Formant_getQuantile, U"Formant: Get quantile", nullptr) {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getTimeOfMaximum, U"Formant: Get time of maximum", U"Formant: Get time of maximum...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4x (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	REAL (U"Quantile", U"0.50 (= median)")
-	OK2
+	RADIO4x (interpolation, U"Interpolation", 2, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double quantile = Formant_getQuantile (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"Quantile"), GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Unit") - 1);
-		Melder_informationReal (quantile, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getTimeOfMaximum (me, formantNumber, fromTime, toTime, unit, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
 
-FORM (Formant_getQuantileOfBandwidth, U"Formant: Get quantile of bandwidth", nullptr) {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+DIRECT (INTEGER_Formant_getMaximumNumberOfFormants) {
+	NUMBER_ONE (Formant)
+		long result = Formant_getMaxNumFormants (me);
+	NUMBER_ONE_END (U" (there are at most this many formants in every frame)")
+}
+
+FORM (REAL_Formant_getMean, U"Formant: Get mean", U"Formant: Get mean...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4x (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	REAL (U"Quantile", U"0.50 (= median)")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double quantile = Formant_getQuantileOfBandwidth (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"Quantile"), GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Unit") - 1);
-		Melder_informationReal (quantile, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getMean (me, formantNumber, fromTime, toTime, unit);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-FORM (Formant_getStandardDeviation, U"Formant: Get standard deviation", nullptr) {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
-		RADIOBUTTON (U"Hertz")
-		RADIOBUTTON (U"Bark")
-	OK2
+DIRECT (INTEGER_Formant_getMinimumNumberOfFormants) {
+	NUMBER_ONE (Formant)
+		long result = Formant_getMinNumFormants (me);
+	NUMBER_ONE_END (U" (there are at least this many formants in every frame)");
+}
+
+FORM (INTEGER_Formant_getNumberOfFormants, U"Formant: Get number of formants", U"Formant: Get number of formants...") {
+	NATURAL4 (frameNumber, U"Frame number", U"1")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double stdev = Formant_getStandardDeviation (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Unit") - 1);
-		Melder_informationReal (stdev, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		if (frameNumber > my nx)
+			Melder_throw (U"There is no frame ", frameNumber, U" in a Formant with only ", my nx, U" frames.");
+		long result = my d_frames [frameNumber]. nFormants;
+	NUMBER_ONE_END (U" formants")
+}
 
-FORM (Formant_getTimeOfMaximum, U"Formant: Get time of maximum", U"Formant: Get time of maximum...") {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getQuantile, U"Formant: Get quantile", nullptr) {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4 (unit, U"Unit", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	RADIO (U"Interpolation", 2)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-	OK2
+	REAL4 (quantile, U"Quantile", U"0.50 (= median)")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double time = Formant_getTimeOfMaximum (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"Unit") - 1, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (time, U"seconds");
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getQuantile (me, formantNumber, quantile, fromTime, toTime, unit - 1);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-FORM (Formant_getTimeOfMinimum, U"Formant: Get time of minimum", U"Formant: Get time of minimum...") {
-	NATURAL (U"Formant number", U"1")
-	praat_dia_timeRange (dia);
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getQuantileOfBandwidth, U"Formant: Get quantile of bandwidth", nullptr) {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4 (unit, U"Unit", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	RADIO (U"Interpolation", 2)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-	OK2
+	REAL4 (quantile, U"Quantile", U"0.50 (= median)")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		double time = Formant_getTimeOfMinimum (me, GET_INTEGER (U"Formant number"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"Unit") - 1, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (time, U"seconds");
-		break;
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getQuantileOfBandwidth (me, formantNumber, quantile, fromTime, toTime, unit - 1);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-FORM (Formant_getValueAtTime, U"Formant: Get value", U"Formant: Get value at time...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	RADIO (U"Unit", 1)
+FORM (REAL_Formant_getStandardDeviation, U"Formant: Get standard deviation", nullptr) {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4 (unit, U"Unit", 1)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Bark")
-	RADIO (U"Interpolation", 1)
-		RADIOBUTTON (U"Linear")
-	OK2
-DO
-	LOOP {
-		iam (Formant);
-		double value = Formant_getValueAtTime (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), GET_INTEGER (U"Unit") - 1);
-		Melder_informationReal (value, GET_STRING (U"Unit"));
-		break;
-	}
-END2 }
-	
-DIRECT2 (Formant_help) {
-	Melder_help (U"Formant");
-END2 }
-
-FORM (Formant_downto_Table, U"Formant: Down to Table", nullptr) {
-	BOOLEAN (U"Include frame number", false)
-	BOOLEAN (U"Include time", true)
-	NATURAL (U"Time decimals", U"6")
-	BOOLEAN (U"Include intensity", false)
-	NATURAL (U"Intensity decimals", U"3")
-	BOOLEAN (U"Include number of formants", true)
-	NATURAL (U"Frequency decimals", U"3")
-	BOOLEAN (U"Include bandwidths", true)
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		autoTable thee = Formant_downto_Table (me, GET_INTEGER (U"Include frame number"),
-			GET_INTEGER (U"Include time"), GET_INTEGER (U"Time decimals"),
-			GET_INTEGER (U"Include intensity"), GET_INTEGER (U"Intensity decimals"),
-			GET_INTEGER (U"Include number of formants"), GET_INTEGER (U"Frequency decimals"),
-			GET_INTEGER (U"Include bandwidths"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Formant_list, U"Formant: List", 0) {
-	BOOLEAN (U"Include frame number", false)
-	BOOLEAN (U"Include time", true)
-	NATURAL (U"Time decimals", U"6")
-	BOOLEAN (U"Include intensity", false)
-	NATURAL (U"Intensity decimals", U"3")
-	BOOLEAN (U"Include number of formants", true)
-	NATURAL (U"Frequency decimals", U"3")
-	BOOLEAN (U"Include bandwidths", true)
-	OK2
-DO
-	LOOP {
-		iam (Formant);
-		Formant_list (me, GET_INTEGER (U"Include frame number"),
-			GET_INTEGER (U"Include time"), GET_INTEGER (U"Time decimals"),
-			GET_INTEGER (U"Include intensity"), GET_INTEGER (U"Intensity decimals"),
-			GET_INTEGER (U"Include number of formants"), GET_INTEGER (U"Frequency decimals"),
-			GET_INTEGER (U"Include bandwidths"));
-		break;
-	}
-END2 }
-
-FORM (Formant_scatterPlot, U"Formant: Scatter plot", nullptr) {
-	praat_dia_timeRange (dia);
-	NATURAL (U"Horizontal formant number", U"2")
-	REAL (U"left Horizontal range (Hz)", U"3000")
-	REAL (U"right Horizontal range (Hz)", U"400")
-	NATURAL (U"Vertical formant number", U"1")
-	REAL (U"left Vertical range (Hz)", U"1500")
-	REAL (U"right Vertical range (Hz)", U"100")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", true)
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	OK2
-DO
-	LOOP {
-		iam (Formant);
-		autoPraatPicture picture;
-		Formant_scatterPlot (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_INTEGER (U"Horizontal formant number"),
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_INTEGER (U"Vertical formant number"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Mark size"), GET_STRING (U"Mark string"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+	NUMBER_ONE (Formant)
+		double result = Formant_getStandardDeviation (me, formantNumber, fromTime, toTime, unit - 1);
+	NUMBER_ONE_END (U" ", GET_STRING (U"Unit"))
+}
 
-DIRECT2 (Formant_sort) {
-	LOOP {
-		iam (Formant);
+// MARK: Modify
+
+DIRECT (MODIFY_Formant_sort) {
+	MODIFY_EACH (Formant)
 		Formant_sort (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (Formant_to_Matrix, U"From Formant to Matrix", nullptr) {
-	INTEGER (U"Formant", U"1")
-	OK2
+FORM (MODIFY_Formant_formula_frequencies, U"Formant: Formula (frequencies)", U"Formant: Formula (frequencies)...") {
+	LABEL (U"", U"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) :=")
+	TEXTFIELD4 (formula, U"formula", U"if row = 2 then self + 200 else self fi")
+	OK
 DO
-	LOOP {
-		iam (Formant);
-		autoMatrix thee = Formant_to_Matrix (me, GET_INTEGER (U"Formant"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Formant_tracker, U"Formant tracker", U"Formant: Track...") {
-	NATURAL (U"Number of tracks (1-5)", U"3")
-	REAL (U"Reference F1 (Hz)", U"550")
-	REAL (U"Reference F2 (Hz)", U"1650")
-	REAL (U"Reference F3 (Hz)", U"2750")
-	REAL (U"Reference F4 (Hz)", U"3850")
-	REAL (U"Reference F5 (Hz)", U"4950")
-	REAL (U"Frequency cost (/kHz)", U"1.0")
-	REAL (U"Bandwidth cost", U"1.0")
-	REAL (U"Transition cost (/octave)", U"1.0")
-	OK2
-DO
-	long numberOfTracks = GET_INTEGER (U"Number of tracks");
-	if (numberOfTracks > 5) Melder_throw (U"Number of tracks cannot be more than 5.");
-	LOOP {
-		iam (Formant);
-		autoFormant thee = Formant_tracker (me, GET_INTEGER (U"Number of tracks"),
-			GET_REAL (U"Reference F1"), GET_REAL (U"Reference F2"),
-			GET_REAL (U"Reference F3"), GET_REAL (U"Reference F4"),
-			GET_REAL (U"Reference F5"), GET_REAL (U"Frequency cost"),
-			GET_REAL (U"Bandwidth cost"), GET_REAL (U"Transition cost"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-/***** FORMANT & POINTPROCESS *****/
-
-DIRECT2 (Formant_PointProcess_to_FormantTier) {
-	Formant formant = nullptr;
-	PointProcess point = nullptr;
-	LOOP {
-		if (CLASS == classFormant) formant = (Formant) OBJECT;
-		if (CLASS == classPointProcess) point = (PointProcess) OBJECT;
-		if (formant && point) break;
-	}
-	autoFormantTier thee = Formant_PointProcess_to_FormantTier (formant, point);
-	praat_new (thee.move(), formant -> name, U"_", point -> name);
-END2 }
+	MODIFY_EACH_WEAK (Formant)
+		Formant_formula_frequencies (me, formula, interpreter);
+	MODIFY_EACH_WEAK_END
+}
 
-/***** FORMANT & SOUND *****/
+FORM (MODIFY_Formant_formula_bandwidths, U"Formant: Formula (bandwidths)", U"Formant: Formula (bandwidths)...") {
+	LABEL (U"", U"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) :=")
+	TEXTFIELD4 (formula, U"formula", U"self / 2 ; sharpen all peaks")
+	OK
+DO
+	MODIFY_EACH_WEAK (Formant)
+		Formant_formula_bandwidths (me, formula, interpreter);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (Sound_Formant_filter) {
-	Sound sound = nullptr;
-	Formant formant = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-		if (CLASS == classFormant) formant = (Formant) OBJECT;
-		if (sound && formant) break;
-	}
-	autoSound thee = Sound_Formant_filter (sound, formant);
-	praat_new (thee.move(), sound -> name, U"_filt");
-END2 }
+// MARK: Convert
+
+FORM (NEW_Formant_tracker, U"Formant tracker", U"Formant: Track...") {
+	NATURAL4 (numberOfTracks, U"Number of tracks (1-5)", U"3")
+	REAL4 (referenceF1, U"Reference F1 (Hz)", U"550")
+	REAL4 (referenceF2, U"Reference F2 (Hz)", U"1650")
+	REAL4 (referenceF3, U"Reference F3 (Hz)", U"2750")
+	REAL4 (referenceF4, U"Reference F4 (Hz)", U"3850")
+	REAL4 (referenceF5, U"Reference F5 (Hz)", U"4950")
+	REAL4 (frequencyCost, U"Frequency cost (/kHz)", U"1.0")
+	REAL4 (bandwidthCost, U"Bandwidth cost", U"1.0")
+	REAL4 (transitionCost, U"Transition cost (/octave)", U"1.0")
+	OK
+DO
+	if (numberOfTracks > 5) Melder_throw (U"Your number of tracks should not be more than 5.");
+	CONVERT_EACH (Formant)
+		autoFormant result = Formant_tracker (me, numberOfTracks,
+			referenceF1, referenceF2, referenceF3, referenceF4, referenceF5,
+			frequencyCost, bandwidthCost, transitionCost);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Sound_Formant_filter_noscale) {
-	Sound sound = nullptr;
-	Formant formant = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-		if (CLASS == classFormant) formant = (Formant) OBJECT;
-		if (sound && formant) break;
-	}
-	autoSound thee = Sound_Formant_filter_noscale (sound, formant);
-	praat_new (thee.move(), sound -> name, U"_filt");
-END2 }
+DIRECT (NEW_Formant_downto_FormantGrid) {
+	CONVERT_EACH (Formant)
+		autoFormantGrid result = Formant_downto_FormantGrid (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** FORMANTGRID *****/
+DIRECT (NEW_Formant_downto_FormantTier) {
+	CONVERT_EACH (Formant)
+		autoFormantTier result = Formant_downto_FormantTier (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (FormantGrid_addBandwidthPoint, U"FormantGrid: Add bandwidth point", U"FormantGrid: Add bandwidth point...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	POSITIVE (U"Bandwidth (Hz)", U"100.0")
-	OK2
+FORM (NEW_Formant_to_Matrix, U"From Formant to Matrix", nullptr) {
+	INTEGER4 (formantNumber, U"Formant number", U"1")
+	OK
 DO
-	LOOP {
-		iam (FormantGrid);
-		FormantGrid_addBandwidthPoint (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), GET_REAL (U"Bandwidth"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (Formant)
+		autoMatrix result = Formant_to_Matrix (me, formantNumber);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (FormantGrid_addFormantPoint, U"FormantGrid: Add formant point", U"FormantGrid: Add formant point...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	POSITIVE (U"Frequency (Hz)", U"550.0")
-	OK2
-DO
-	LOOP {
-		iam (FormantGrid);
-		FormantGrid_addFormantPoint (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"), GET_REAL (U"Frequency"));
-		praat_dataChanged (OBJECT);
-	}
-END2 }
-
-FORM (FormantGrid_create, U"Create FormantGrid", nullptr) {
-	WORD (U"Name", U"schwa")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	NATURAL (U"Number of formants", U"10")
-	POSITIVE (U"Initial first formant (Hz)", U"550.0")
-	POSITIVE (U"Initial formant spacing (Hz)", U"1100.0")
-	REAL (U"Initial first bandwidth (Hz)", U"60.0")
-	REAL (U"Initial bandwidth spacing (Hz)", U"50.0")
-	OK2
-DO
-	double startTime = GET_REAL (U"Start time"), endTime = GET_REAL (U"End time");
-	if (endTime <= startTime) Melder_throw (U"End time must be greater than start time.");
-	autoFormantGrid thee = FormantGrid_create (startTime, endTime, GET_INTEGER (U"Number of formants"),
-		GET_REAL (U"Initial first formant"), GET_REAL (U"Initial formant spacing"),
-		GET_REAL (U"Initial first bandwidth"), GET_REAL (U"Initial bandwidth spacing"));
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END2 }
-
-static void cb_FormantGridEditor_publish (Editor /* me */, autoDaata publish) {
-	/*
-	 * Keep the gate for error handling.
-	 */
-	try {
-		praat_new (publish.move(), U"fromFormantGridEditor");
-		praat_updateSelection ();
-	} catch (MelderError) {
-		Melder_flushError ();
-	}
+// MARK: - FORMANT & POINTPROCESS
+
+DIRECT (NEW1_Formant_PointProcess_to_FormantTier) {
+	CONVERT_TWO (Formant, PointProcess)
+		autoFormantTier result = Formant_PointProcess_to_FormantTier (me, you);
+	CONVERT_TWO_END (my name, U"_", your name)
 }
-DIRECT2 (FormantGrid_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a FormantGrid from batch.");
-	LOOP {
-		iam (FormantGrid);
-		autoFormantGridEditor editor = FormantGridEditor_create (ID_AND_FULL_NAME, me);
-		Editor_setPublicationCallback (editor.get(), cb_FormantGridEditor_publish);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
 
-FORM (FormantGrid_formula_bandwidths, U"FormantGrid: Formula (bandwidths)", U"Formant: Formula (bandwidths)...") {
-	LABEL (U"", U"row is formant number, col is point number: for row from 1 to nrow do for col from 1 to ncol do B (row, col) :=")
-	LABEL (U"", U"self [] is the FormantGrid itself, so it returns frequencies, not bandwidths!")
-	TEXTFIELD (U"formula", U"self / 10 ; one tenth of the formant frequency")
-	OK2
-DO
-	LOOP {
-		iam (FormantGrid);
-		try {
-			FormantGrid_formula_bandwidths (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the FormantGrid may have partially changed
-			throw;
-		}
-	}
-END2 }
+// MARK: - FORMANT & SOUND
 
-FORM (FormantGrid_formula_frequencies, U"FormantGrid: Formula (frequencies)", U"Formant: Formula (frequencies)...") {
-	LABEL (U"", U"row is formant number, col is point number: for row from 1 to nrow do for col from 1 to ncol do F (row, col) :=")
-	TEXTFIELD (U"formula", U"if row = 2 then self + 200 else self fi")
-	OK2
-DO
-	LOOP {
-		iam (FormantGrid);
-		try {
-			FormantGrid_formula_frequencies (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the FormantGrid may have partially changed
-			throw;
-		}
-	}
-END2 }
+DIRECT (NEW1_Sound_Formant_filter) {
+	CONVERT_TWO (Sound, Formant)
+		autoSound result = Sound_Formant_filter (me, you);
+	CONVERT_TWO_END (my name, U"_filt")
+}
 
-DIRECT2 (FormantGrid_help) {
-	Melder_help (U"FormantGrid");
-END2 }
+DIRECT (NEW1_Sound_Formant_filter_noscale) {
+	CONVERT_TWO (Sound, Formant)
+		autoSound result = Sound_Formant_filter_noscale (me, you);
+	CONVERT_TWO_END (my name, U"_filt")
+}
 
-FORM (FormantGrid_removeBandwidthPointsBetween, U"Remove bandwidth points between", U"FormantGrid: Remove bandwidth points between...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"From time (s)", U"0.3")
-	REAL (U"To time (s)", U"0.7")
-	OK2
-DO
-	LOOP {
-		iam (FormantGrid);
-		FormantGrid_removeBandwidthPointsBetween (me, GET_INTEGER (U"Formant number"), GET_REAL (U"From time"), GET_REAL (U"To time"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - HARMONICITY
 
-FORM (FormantGrid_removeFormantPointsBetween, U"Remove formant points between", U"FormantGrid: Remove formant points between...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"From time (s)", U"0.3")
-	REAL (U"To time (s)", U"0.7")
-	OK2
-DO
-	LOOP {
-		iam (FormantGrid);
-		FormantGrid_removeFormantPointsBetween (me, GET_INTEGER (U"Formant number"), GET_REAL (U"From time"), GET_REAL (U"To time"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: Help
 
-FORM (FormantGrid_to_Formant, U"FormantGrid: To Formant", nullptr) {
-	POSITIVE (U"Time step (s)", U"0.01")
-	REAL (U"Intensity (Pa\u00B2)", U"0.1")
-	OK2
-DO
-	double intensity = GET_REAL (U"Intensity");
-	if (intensity < 0.0) Melder_throw (U"Intensity cannot be negative.");
-	LOOP {
-		iam (FormantGrid);
-		autoFormant thee = FormantGrid_to_Formant (me, GET_REAL (U"Time step"), intensity);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (HELP_Harmonicity_help) {
+	HELP (U"Harmonicity")
+}
 
-/***** FORMANTGRID & SOUND *****/
+// MARK: Draw
 
-DIRECT2 (Sound_FormantGrid_filter) {
-	Sound me = nullptr;
-	FormantGrid grid = nullptr;
+FORM (GRAPHICS_Harmonicity_draw, U"Draw harmonicity", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (minimum, U"Minimum", U"0.0")
+	REALVAR (maximum, U"Maximum", U"0.0 (= auto)")
+	OK
+DO
 	LOOP {
-		if (CLASS == classSound) me = (Sound) OBJECT;
-		if (CLASS == classFormantGrid) grid = (FormantGrid) OBJECT;
-		if (me && grid) break;   // OPTIMIZE
+		iam (Harmonicity);
+		autoPraatPicture picture;
+		Matrix_drawRows (me, GRAPHICS, fromTime, toTime, 0.0, 0.0, minimum, maximum);
 	}
-	autoSound thee = Sound_FormantGrid_filter (me, grid);
-	praat_new (thee.move(), my name, U"_filt");
-END2 }
+END }
 
-DIRECT2 (Sound_FormantGrid_filter_noscale) {
-	Sound me = nullptr;
-	FormantGrid grid = nullptr;
-	LOOP {
-		if (CLASS == classSound) me = (Sound) OBJECT;
-		if (CLASS == classFormantGrid) grid = (FormantGrid) OBJECT;
-		if (me && grid) break;   // OPTIMIZE
-	}
-	autoSound thee = Sound_FormantGrid_filter_noscale (me, grid);
-	praat_new (thee.move(), my name, U"_filt");
-END2 }
-
-/***** FORMANTTIER *****/
-
-FORM (FormantTier_addPoint, U"Add one point", U"FormantTier: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	LABEL (U"", U"Frequencies and bandwidths (Hz):")
-	TEXTFIELD (U"fb pairs", U"500 50 1500 100 2500 150 3500 200 4500 300")
-	OK2
-DO
-	autoFormantPoint point = FormantPoint_create (GET_REAL (U"Time"));
-	double *f = point -> formant, *b = point -> bandwidth;
-	char *fbpairs = Melder_peek32to8 (GET_STRING (U"fb pairs"));
-	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)
-		Melder_throw (U"Number of formant-bandwidth pairs must be at least 1.");
-	point -> numberOfFormants = numberOfFormants;
-	LOOP {
-		iam (FormantTier);
-		autoFormantPoint point2 = Data_copy (point.get());
-		AnyTier_addPoint_move (me->asAnyTier(), point2.move());
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: Query
 
-FORM (FormantTier_create, U"Create empty FormantTier", nullptr) {
-	WORD (U"Name", U"empty")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	OK2
+FORM (REAL_Harmonicity_getMaximum, U"Harmonicity: Get maximum", U"Harmonicity: Get maximum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
 DO
-	double startTime = GET_REAL (U"Start time"), endTime = GET_REAL (U"End time");
-	if (endTime <= startTime) Melder_throw (U"End time must be greater than start time.");
-	autoFormantTier thee = FormantTier_create (startTime, endTime);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END2 }
+	NUMBER_ONE (Harmonicity)
+		double result = Vector_getMaximum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (FormantTier_downto_TableOfReal, U"Down to TableOfReal", nullptr) {
-	BOOLEAN (U"Include formants", true)
-	BOOLEAN (U"Include bandwidths", false)
-	OK2
+FORM (REAL_Harmonicity_getMean, U"Harmonicity: Get mean", U"Harmonicity: Get mean...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
 DO
-	LOOP {
-		iam (FormantTier);
-		autoTableOfReal thee = FormantTier_downto_TableOfReal (me, GET_INTEGER (U"Include formants"), GET_INTEGER (U"Include bandwidths"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	NUMBER_ONE (Harmonicity)
+		double result = Harmonicity_getMean (me, fromTime, toTime);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (FormantTier_getBandwidthAtTime, U"FormantTier: Get bandwidth", U"FormantTier: Get bandwidth at time...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (FormantTier);
-		double bandwidth = FormantTier_getBandwidthAtTime (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"));
-		Melder_informationReal (bandwidth, U"hertz");
-	}
-END2 }
-	
-FORM (FormantTier_getValueAtTime, U"FormantTier: Get value", U"FormantTier: Get value at time...") {
-	NATURAL (U"Formant number", U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
+FORM (REAL_Harmonicity_getMinimum, U"Harmonicity: Get minimum", U"Harmonicity: Get minimum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
 DO
-	LOOP {
-		iam (FormantTier);
-		double value = FormantTier_getValueAtTime (me, GET_INTEGER (U"Formant number"), GET_REAL (U"Time"));
-		Melder_informationReal (value, U"hertz");
-	}
-END2 }
-	
-DIRECT2 (FormantTier_help) {
-	Melder_help (U"FormantTier");
-END2 }
+	NUMBER_ONE (Harmonicity)
+		double result = Vector_getMinimum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (FormantTier_speckle, U"Draw FormantTier", nullptr) {
-	praat_dia_timeRange (dia);
-	POSITIVE (U"Maximum frequency (Hz)", U"5500.0")
-	BOOLEAN (U"Garnish", 1)
-	OK2
+FORM (REAL_Harmonicity_getStandardDeviation, U"Harmonicity: Get standard deviation", U"Harmonicity: Get standard deviation...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
 DO
-	LOOP {
-		iam (FormantTier);
-		autoPraatPicture picture;
-		FormantTier_speckle (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Maximum frequency"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-/***** FORMANTTIER & SOUND *****/
+	NUMBER_ONE (Harmonicity)
+		double result = Harmonicity_getStandardDeviation (me, fromTime, toTime);
+	NUMBER_ONE_END (U" dB")
+}
 
-DIRECT2 (Sound_FormantTier_filter) {
-	Sound me = nullptr;
-	FormantTier tier = nullptr;
-	LOOP {
-		if (CLASS == classSound) me = (Sound) OBJECT;
-		if (CLASS == classFormantTier) tier = (FormantTier) OBJECT;
-		if (me && tier) break;   // OPTIMIZE
-	}
-	autoSound thee = Sound_FormantTier_filter (me, tier);
-	praat_new (thee.move(), my name, U"_filt");
-END2 }
+FORM (REAL_Harmonicity_getTimeOfMaximum, U"Harmonicity: Get time of maximum", U"Harmonicity: Get time of maximum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
+DO
+	NUMBER_ONE (Harmonicity)
+		double result = Vector_getXOfMaximum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
 
-DIRECT2 (Sound_FormantTier_filter_noscale) {
-	Sound me = nullptr;
-	FormantTier tier = nullptr;
-	LOOP {
-		if (CLASS == classSound) me = (Sound) OBJECT;
-		if (CLASS == classFormantTier) tier = (FormantTier) OBJECT;
-		if (me && tier) break;   // OPTIMIZE
-	}
-	autoSound thee = Sound_FormantTier_filter_noscale (me, tier);
-	praat_new (thee.move(), my name, U"_filt");
-END2 }
+FORM (REAL_Harmonicity_getTimeOfMinimum, U"Harmonicity: Get time of minimum", U"Harmonicity: Get time of minimum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
+DO
+	NUMBER_ONE (Harmonicity)
+		double result = Vector_getXOfMinimum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
 
-/***** HARMONICITY *****/
+FORM (REAL_Harmonicity_getValueAtTime, U"Harmonicity: Get value", U"Harmonicity: Get value at time...") {
+	praat_TimeVector_INTERPOLATED_VALUE (time, interpolation)
+	OK
+DO
+	NUMBER_ONE (Harmonicity)
+		double result = Vector_getValueAtX (me, time, 1, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Harmonicity_draw, U"Draw harmonicity", 0) {
-	praat_dia_timeRange (dia);
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0 (= auto)")
-	OK2
+FORM (REAL_Harmonicity_getValueInFrame, U"Get value in frame", U"Harmonicity: Get value in frame...") {
+	INTEGER4 (frameNumber, U"Frame number", U"10")
+	OK
 DO
-	LOOP {
-		iam (Harmonicity);
-		autoPraatPicture picture;
-		Matrix_drawRows (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 0.0, 0.0,
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"));
-	}
-END2 }
+	NUMBER_ONE (Harmonicity)
+		double result = frameNumber < 1 || frameNumber > my nx ? NUMundefined : my z [1] [frameNumber];
+	NUMBER_ONE_END (U" dB")
+}
+
+// MARK: Modify
 
-FORM (Harmonicity_formula, U"Harmonicity Formula", U"Harmonicity: Formula...") {
+FORM (MODIFY_Harmonicity_formula, U"Harmonicity Formula", U"Harmonicity: Formula...") {
 	LABEL (U"label", U"x is time")
 	LABEL (U"label", U"for col := 1 to ncol do { self [col] := `formula' ; x := x + dx }")
-	TEXTFIELD (U"formula", U"self")
-	OK2
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
 DO
-	LOOP {
-		iam (Harmonicity);
-		try {
-			Matrix_formula ((Matrix) me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Harmonicity may have partically changed
-			throw;
-		}
-	}
-END2 }
+	MODIFY_EACH_WEAK (Harmonicity)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM (Harmonicity_getMaximum, U"Harmonicity: Get maximum", U"Harmonicity: Get maximum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double maximum = Vector_getMaximum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (maximum, U"dB");
-	}
-END2 }
+// MARK: Convert
 
-FORM (Harmonicity_getMean, U"Harmonicity: Get mean", U"Harmonicity: Get mean...") {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double mean = Harmonicity_getMean (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (mean, U"dB");
-	}
-END2 }
+DIRECT (NEW_Harmonicity_to_Matrix) {
+	CONVERT_EACH (Harmonicity)
+		autoMatrix result = Harmonicity_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Harmonicity_getMinimum, U"Harmonicity: Get minimum", U"Harmonicity: Get minimum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double minimum = Vector_getMinimum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (minimum, U"dB");
-	}
-END2 }
+// MARK: - INTENSITY
 
-FORM (Harmonicity_getStandardDeviation, U"Harmonicity: Get standard deviation", U"Harmonicity: Get standard deviation...") {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double stdev = Harmonicity_getStandardDeviation (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (stdev, U"dB");
-	}
-END2 }
+// MARK: Help
 
-FORM (Harmonicity_getTimeOfMaximum, U"Harmonicity: Get time of maximum", U"Harmonicity: Get time of maximum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double maximum = Vector_getXOfMaximum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (maximum, U"seconds");
-	}
-END2 }
+DIRECT (HELP_Intensity_help) {
+	HELP (U"Intensity")
+}
 
-FORM (Harmonicity_getTimeOfMinimum, U"Harmonicity: Get time of minimum", U"Harmonicity: Get time of minimum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double minimum = Vector_getXOfMinimum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (minimum, U"seconds");
-	}
-END2 }
+// MARK: Draw
 
-FORM (Harmonicity_getValueAtTime, U"Harmonicity: Get value", U"Harmonicity: Get value at time...") {
-	dia_Vector_getValue (dia);
-	OK2
-DO
-	LOOP {
-		iam (Harmonicity);
-		double value = Vector_getValueAtX (me, GET_REAL (U"Time"), 1, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (value, U"dB");
-	}
-END2 }
-	
-FORM (Harmonicity_getValueInFrame, U"Get value in frame", U"Harmonicity: Get value in frame...") {
-	INTEGER (U"Frame number", U"10")
-	OK2
+FORM (GRAPHICS_Intensity_draw, U"Draw Intensity", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REAL4 (minimum, U"Minimum (dB)", U"0.0")
+	REAL4 (maximum, U"Maximum (dB)", U"0.0 (= auto)")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	LOOP {
-		iam (Harmonicity);
-		long frameNumber = GET_INTEGER (U"Frame number");
-		Melder_informationReal (frameNumber < 1 || frameNumber > my nx ? NUMundefined : my z [1] [frameNumber], U"dB");
-	}
-END2 }
+	GRAPHICS_EACH (Intensity)
+		Intensity_draw (me, GRAPHICS, fromTime, toTime, minimum, maximum, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Harmonicity_help) {
-	Melder_help (U"Harmonicity");
-END2 }
+// MARK: Query
 
-DIRECT2 (Harmonicity_to_Matrix) {
-	LOOP {
-		iam (Harmonicity);
-		autoMatrix thee = Harmonicity_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (REAL_Intensity_getValueAtTime, U"Intensity: Get value", U"Intensity: Get value at time...") {
+	praat_TimeVector_INTERPOLATED_VALUE (time, interpolation)
+	OK
+DO
+	NUMBER_ONE (Intensity)
+		double result = Vector_getValueAtX (me, time, 1, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-/***** INTENSITY *****/
+FORM (REAL_Intensity_getValueInFrame, U"Get value in frame", U"Intensity: Get value in frame...") {
+	INTEGERVAR (frameNumber, U"Frame number", U"10")
+	OK
+DO
+	NUMBER_ONE (Intensity)
+		double result = frameNumber < 1 || frameNumber > my nx ? NUMundefined : my z [1] [frameNumber];
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Intensity_draw, U"Draw Intensity", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"Minimum (dB)", U"0.0")
-	REAL (U"Maximum (dB)", U"0.0 (= auto)")
-	BOOLEAN (U"Garnish", true)
-	OK2
+FORM (REAL_Intensity_getMinimum, U"Intensity: Get minimum", U"Intensity: Get minimum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
 DO
-	LOOP {
-		iam (Intensity);
-		autoPraatPicture picture;
-		Intensity_draw (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+	NUMBER_ONE (Intensity)
+		double result = Vector_getMinimum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-DIRECT2 (Intensity_downto_IntensityTier) {
-	LOOP {
-		iam (Intensity);
-		autoIntensityTier thee = Intensity_downto_IntensityTier (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (REAL_Intensity_getTimeOfMinimum, U"Intensity: Get time of minimum", U"Intensity: Get time of minimum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
+DO
+	NUMBER_ONE (Intensity)
+		double result = Vector_getXOfMinimum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
 
-DIRECT2 (Intensity_downto_Matrix) {
-	LOOP {
-		iam (Intensity);
-		autoMatrix thee = Intensity_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (REAL_Intensity_getMaximum, U"Intensity: Get maximum", U"Intensity: Get maximum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
+DO
+	NUMBER_ONE (Intensity)
+		double result = Vector_getMaximum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Intensity_formula, U"Intensity Formula", 0) {
-	LABEL (U"label", U"`x' is the time in seconds, `col' is the frame number, `self' is in dB")
-	LABEL (U"label", U"x := x1;   for col := 1 to ncol do { self [col] := `formula' ; x := x + dx }")
-	TEXTFIELD (U"formula", U"0")
-	OK2
+FORM (REAL_Intensity_getTimeOfMaximum, U"Intensity: Get time of maximum", U"Intensity: Get time of maximum...") {
+	praat_TimeVector_INTERPOLATED_EXTREMUM (fromTime, toTime, interpolation)
+	OK
 DO
-	LOOP {
-		iam (Intensity);
-		try {
-			Matrix_formula ((Matrix) me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Intensity may have partially changed
-			throw;
-		}
-	}
-END2 }
+	NUMBER_ONE (Intensity)
+		double result = Vector_getXOfMaximum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
 
-FORM (Intensity_getMaximum, U"Intensity: Get maximum", U"Intensity: Get maximum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
+FORM (REAL_Intensity_getQuantile, U"Intensity: Get quantile", 0) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REAL4 (quantile, U"Quantile (0-1)", U"0.50")
+	OK
 DO
-	LOOP {
-		iam (Intensity);
-		double maximum = Vector_getMaximum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (maximum, U"dB");
-		break;   // OPTIMIZE
-	}
-END2 }
+	NUMBER_ONE (Intensity)
+		double result = Intensity_getQuantile (me, fromTime, toTime, quantile);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (old_Intensity_getMean, U"Intensity: Get mean", U"Intensity: Get mean...") {
-	praat_dia_timeRange (dia);
-	OK2
+FORM (REAL_old_Intensity_getMean, U"Intensity: Get mean", U"Intensity: Get mean...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
 DO
-	LOOP {
-		iam (Intensity);
-		double mean = Sampled_getMean_standardUnit (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 0, 0, true);
-		Melder_informationReal (mean, U"dB");
-		break;   // OPTIMIZE
-	}
-END2 }
+	NUMBER_ONE (Intensity)
+		double result = Sampled_getMean_standardUnit (me, fromTime, toTime, 0, 0, true);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Intensity_getMean, U"Intensity: Get mean", U"Intensity: Get mean...") {
-	praat_dia_timeRange (dia);
-	RADIO (U"Averaging method", 1)
+FORM (REAL_Intensity_getMean, U"Intensity: Get mean", U"Intensity: Get mean...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	RADIO4 (averagingMethod, U"Averaging method", 1)
 		RADIOBUTTON (U"energy")
 		RADIOBUTTON (U"sones")
 		RADIOBUTTON (U"dB")
-	OK2
-DO_ALTERNATIVE (old_Intensity_getMean)
-	LOOP {
-		iam (Intensity);
-		double mean = Sampled_getMean_standardUnit (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			0, GET_INTEGER (U"Averaging method"), true);
-		Melder_informationReal (mean, U"dB");
-		break;   // OPTIMIZE
-	}
-END2 }
+	OK
+DO_ALTERNATIVE (REAL_old_Intensity_getMean)
+	NUMBER_ONE (Intensity)
+		double result = Sampled_getMean_standardUnit (me, fromTime, toTime, 0, averagingMethod, true);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Intensity_getMinimum, U"Intensity: Get minimum", U"Intensity: Get minimum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
+FORM (REAL_Intensity_getStandardDeviation, U"Intensity: Get standard deviation", U"Intensity: Get standard deviation...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
 DO
-	LOOP {
-		iam (Intensity);
-		double minimum = Vector_getMinimum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (minimum, U"dB");
-		break;   // OPTIMIZE
-	}
-END2 }
+	NUMBER_ONE (Intensity)
+		double result = Vector_getStandardDeviation (me, fromTime, toTime, 1);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Intensity_getQuantile, U"Intensity: Get quantile", 0) {
-	praat_dia_timeRange (dia);
-	REAL (U"Quantile (0-1)", U"0.50")
-	OK2
-DO
-	LOOP {
-		iam (Intensity);
-		double quantile = Intensity_getQuantile (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Quantile"));
-		Melder_informationReal (quantile, U"dB");
-	}
-END2 }
+// MARK: Modify
 
-FORM (Intensity_getStandardDeviation, U"Intensity: Get standard deviation", U"Intensity: Get standard deviation...") {
-	praat_dia_timeRange (dia);
-	OK2
+FORM (MODIFY_Intensity_formula, U"Intensity Formula", nullptr) {
+	LABEL (U"label", U"`x' is the time in seconds, `col' is the frame number, `self' is in dB")
+	LABEL (U"label", U"x := x1;   for col := 1 to ncol do { self [col] := `formula' ; x := x + dx }")
+	TEXTFIELD4 (formula, U"formula", U"0")
+	OK
 DO
-	LOOP {
-		iam (Intensity);
-		double stdev = Vector_getStandardDeviation (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), 1);
-		Melder_informationReal (stdev, U"dB");
-	}
-END2 }
+	MODIFY_EACH_WEAK (Intensity)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM (Intensity_getTimeOfMaximum, U"Intensity: Get time of maximum", U"Intensity: Get time of maximum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
-DO
-	LOOP {
-		iam (Intensity);
-		double time = Vector_getXOfMaximum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (time, U"seconds");
-	}
-END2 }
+// MARK: Analyse
 
-FORM (Intensity_getTimeOfMinimum, U"Intensity: Get time of minimum", U"Intensity: Get time of minimum...") {
-	dia_Vector_getExtremum (dia);
-	OK2
-DO
-	LOOP {
-		iam (Intensity);
-		double time = Vector_getXOfMinimum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (time, U"seconds");
-	}
-END2 }
+DIRECT (NEW_Intensity_to_IntensityTier_peaks) {
+	CONVERT_EACH (Intensity)
+		autoIntensityTier result = Intensity_to_IntensityTier_peaks (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Intensity_getValueAtTime, U"Intensity: Get value", U"Intensity: Get value at time...") {
-	dia_Vector_getValue (dia);
-	OK2
-DO
-	LOOP {
-		iam (Intensity);
-		double value = Vector_getValueAtX (me, GET_REAL (U"Time"), 1, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (value, U"dB");
-	}
-END2 }
-	
-FORM (Intensity_getValueInFrame, U"Get value in frame", U"Intensity: Get value in frame...") {
-	INTEGER (U"Frame number", U"10")
-	OK2
-DO
-	LOOP {
-		iam (Intensity);
-		long frameNumber = GET_INTEGER (U"Frame number");
-		Melder_informationReal (frameNumber < 1 || frameNumber > my nx ? NUMundefined : my z [1] [frameNumber], U"dB");
-	}
-END2 }
+DIRECT (NEW_Intensity_to_IntensityTier_valleys) {
+	CONVERT_EACH (Intensity)
+		autoIntensityTier result = Intensity_to_IntensityTier_valleys (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Intensity_help) {
-	Melder_help (U"Intensity");
-END2 }
+// MARK: Convert
 
-DIRECT2 (Intensity_to_IntensityTier_peaks) {
-	LOOP {
-		iam (Intensity);
-		autoIntensityTier thee = Intensity_to_IntensityTier_peaks (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Intensity_downto_IntensityTier) {
+	CONVERT_EACH (Intensity)
+		autoIntensityTier result = Intensity_downto_IntensityTier (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Intensity_to_IntensityTier_valleys) {
-	LOOP {
-		iam (Intensity);
-		autoIntensityTier thee = Intensity_to_IntensityTier_valleys (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Intensity_downto_Matrix) {
+	CONVERT_EACH (Intensity)
+		autoMatrix result = Intensity_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** INTENSITY & PITCH *****/
+// MARK: - INTENSITY & PITCH
 
-FORM (Pitch_Intensity_draw, U"Plot intensity by pitch", nullptr) {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= auto)")
-	REAL (U"From intensity (dB)", U"0.0")
-	REAL (U"To intensity (dB)", U"100.0")
-	BOOLEAN (U"Garnish", true)
-	RADIO (U"Drawing method", 1)
+FORM (GRAPHICS_Pitch_Intensity_draw, U"Plot intensity by pitch", nullptr) {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= auto)")
+	REAL4 (fromIntensity, U"From intensity (dB)", U"0.0")
+	REAL4 (toIntensity, U"To intensity (dB)", U"100.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	RADIO4 (drawingMethod, U"Drawing method", 1)
 		RADIOBUTTON (U"Speckles")
 		RADIOBUTTON (U"Curve")
 		RADIOBUTTON (U"Speckles and curve")
-	OK2
+	OK
 DO
-	Pitch pitch = nullptr;
-	Intensity intensity = nullptr;
-	LOOP {
-		if (CLASS == classPitch) pitch = (Pitch) OBJECT;
-		if (CLASS == classIntensity) intensity = (Intensity) OBJECT;
-		if (pitch && intensity) break;   // OPTIMIZE
-	}
-	autoPraatPicture picture;
-	Pitch_Intensity_draw (pitch, intensity, GRAPHICS,
-		GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-		GET_REAL (U"From intensity"), GET_REAL (U"To intensity"), GET_INTEGER (U"Garnish"), GET_INTEGER (U"Drawing method"));
-END2 }
-
-FORM (Pitch_Intensity_speckle, U"Plot intensity by pitch", nullptr) {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= auto)")
-	REAL (U"From intensity (dB)", U"0.0")
-	REAL (U"To intensity (dB)", U"100.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	Pitch pitch = nullptr;
-	Intensity intensity = nullptr;
-	LOOP {
-		if (CLASS == classPitch) pitch = (Pitch) OBJECT;
-		if (CLASS == classIntensity) intensity = (Intensity) OBJECT;
-		if (pitch && intensity) break;   // OPTIMIZE
-	}
-	autoPraatPicture picture;
-	Pitch_Intensity_draw (pitch, intensity, GRAPHICS,
-		GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-		GET_REAL (U"From intensity"), GET_REAL (U"To intensity"), GET_INTEGER (U"Garnish"), 1);
-END2 }
-
-DIRECT2 (Pitch_Intensity_getMean) {
-	Pitch pitch = nullptr;
-	Intensity intensity = nullptr;
-	LOOP {
-		if (CLASS == classPitch) pitch = (Pitch) OBJECT;
-		if (CLASS == classIntensity) intensity = (Intensity) OBJECT;
-		if (pitch && intensity) break;   // OPTIMIZE
-	}
-	double value = Pitch_Intensity_getMean (pitch, intensity);
-	Melder_informationReal (value, U"dB");
-END2 }
+	GRAPHICS_TWO (Pitch, Intensity)
+		Pitch_Intensity_draw (me, you, GRAPHICS,
+			fromFrequency, toFrequency, fromIntensity, toIntensity, garnish, drawingMethod);
+	GRAPHICS_TWO_END
+}
 
-DIRECT2 (Pitch_Intensity_getMeanAbsoluteSlope) {
-	Pitch pitch = nullptr;
-	Intensity intensity = nullptr;
-	LOOP {
-		if (CLASS == classPitch) pitch = (Pitch) OBJECT;
-		if (CLASS == classIntensity) intensity = (Intensity) OBJECT;
-		if (pitch && intensity) break;   // OPTIMIZE
-	}
-	double slope = Pitch_Intensity_getMeanAbsoluteSlope (pitch, intensity);
-	Melder_informationReal (slope, U"dB/second");
-END2 }
+DIRECT (REAL_Pitch_Intensity_getMean) {
+	NUMBER_TWO (Pitch, Intensity)
+		double result = Pitch_Intensity_getMean (me, you);
+	NUMBER_TWO_END (U" dB")
+}
 
-/***** INTENSITY & POINTPROCESS *****/
+DIRECT (REAL_Pitch_Intensity_getMeanAbsoluteSlope) {
+	NUMBER_TWO (Pitch, Intensity)
+		double result = Pitch_Intensity_getMeanAbsoluteSlope (me, you);
+	NUMBER_TWO_END (U" dB/second")
+}
 
-DIRECT2 (Intensity_PointProcess_to_IntensityTier) {
-	Intensity intensity = nullptr;
-	PointProcess point = nullptr;
-	LOOP {
-		if (CLASS == classIntensity) intensity = (Intensity) OBJECT;
-		if (CLASS == classPointProcess) point = (PointProcess) OBJECT;
-		if (intensity && point) break;   // OPTIMIZE
-	}
-	autoIntensityTier thee = Intensity_PointProcess_to_IntensityTier (intensity, point);
-	praat_new (thee.move(), intensity -> name);
-END2 }
+// MARK: - INTENSITY & POINTPROCESS
 
-/***** INTENSITYTIER *****/
+DIRECT (NEW1_Intensity_PointProcess_to_IntensityTier) {
+	CONVERT_TWO (Intensity, PointProcess)
+		autoIntensityTier result = Intensity_PointProcess_to_IntensityTier (me, you);
+	CONVERT_TWO_END (my name)
+}
 
-FORM (IntensityTier_addPoint, U"Add one point", U"IntensityTier: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	REAL (U"Intensity (dB)", U"75")
-	OK2
-DO
-	LOOP {
-		iam (IntensityTier);
-		RealTier_addPoint (me, GET_REAL (U"Time"), GET_REAL (U"Intensity"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - INTERVALTIER, the remainder is in praat_TextGrid_init.cpp
 
-FORM (IntensityTier_create, U"Create empty IntensityTier", nullptr) {
-	WORD (U"Name", U"empty")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	OK2
-DO
-	double startTime = GET_REAL (U"Start time"), endTime = GET_REAL (U"End time");
-	if (endTime <= startTime) Melder_throw (U"End time must be greater than start time.");
-	autoIntensityTier thee = IntensityTier_create (startTime, endTime);
-	praat_new (thee.move(), GET_STRING (U"Name"));
-END2 }
+FORM_READ (READ1_IntervalTier_readFromXwaves, U"Read IntervalTier from Xwaves", 0, true) {
+	READ_ONE
+		autoIntervalTier result = IntervalTier_readFromXwaves (file);
+	READ_ONE_END
+}
 
-DIRECT2 (IntensityTier_downto_PointProcess) {
-	LOOP {
-		iam (IntensityTier);
-		autoPointProcess thee = AnyTier_downto_PointProcess (me->asAnyTier());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: - LTAS
 
-DIRECT2 (IntensityTier_downto_TableOfReal) {
-	LOOP {
-		iam (IntensityTier);
-		autoTableOfReal thee = IntensityTier_downto_TableOfReal (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW1_Ltases_average) {
+	CONVERT_TYPED_LIST (Ltas, LtasBag)
+		autoLtas result = Ltases_average (list.get());
+	CONVERT_TYPED_LIST_END (U"averaged")
+}
 
-DIRECT2 (IntensityTier_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an IntensityTier from batch.");
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;   // may stay null
-		if (sound) break;   // OPTIMIZE
-	}
-	LOOP if (CLASS == classIntensityTier) {
-		iam (IntensityTier);
-		autoIntensityTierEditor editor = IntensityTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-FORM (IntensityTier_formula, U"IntensityTier: Formula", U"IntensityTier: Formula...") {
-	LABEL (U"", U"# ncol = the number of points")
-	LABEL (U"", U"for col from 1 to ncol")
-	LABEL (U"", U"   # x = the time of the colth point, in seconds")
-	LABEL (U"", U"   # self = the value of the colth point, in dB")
-	LABEL (U"", U"   self = `formula'")
-	LABEL (U"", U"endfor")
-	TEXTFIELD (U"formula", U"self + 3.0")
-	OK2
+FORM (NEW_Ltas_computeTrendLine, U"Ltas: Compute trend line", U"Ltas: Compute trend line...") {
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"600.0")
+	POSITIVEVAR (toFrequency, U"right Frequency range (Hz)", U"4000.0")
+	OK
 DO
-	LOOP {
-		iam (IntensityTier);
-		try {
-			RealTier_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the IntensityTier may have partially changed
-			throw;
-		}
-	}
-END2 }
+	CONVERT_EACH (Ltas)
+		autoLtas result = Ltas_computeTrendLine (me, fromFrequency, toFrequency);
+	CONVERT_EACH_END (my name, U"_trend")
+}
 
-FORM (IntensityTier_getValueAtTime, U"Get IntensityTier value", U"IntensityTier: Get value at time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (IntensityTier);
-		double value = RealTier_getValueAtTime (me, GET_REAL (U"Time"));
-		Melder_informationReal (value, U"dB");
-	}
-END2 }
-	
-FORM (IntensityTier_getValueAtIndex, U"Get IntensityTier value", U"IntensityTier: Get value at index...") {
-	INTEGER (U"Point number", U"10")
-	OK2
-DO
-	LOOP {
-		iam (IntensityTier);
-		double value = RealTier_getValueAtIndex (me, GET_INTEGER (U"Point number"));
-		Melder_informationReal (value, U"dB");
-	}
-END2 }
-
-DIRECT2 (IntensityTier_help) {
-	Melder_help (U"IntensityTier");
-END2 }
-
-DIRECT2 (IntensityTier_to_AmplitudeTier) {
-	LOOP {
-		iam (IntensityTier);
-		autoAmplitudeTier thee = IntensityTier_to_AmplitudeTier (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (info_IntensityTier_Sound_edit) {
-	Melder_information (U"To include a copy of a Sound in your IntensityTier editor:\n"
-		"   select an IntensityTier and a Sound, and click \"View & Edit\".");
-END2 }
-
-/***** INTENSITYTIER & POINTPROCESS *****/
-
-DIRECT2 (IntensityTier_PointProcess_to_IntensityTier) {
-	IntensityTier intensity = nullptr;
-	PointProcess point = nullptr;
-	LOOP {
-		if (CLASS == classIntensityTier) intensity = (IntensityTier) OBJECT;
-		if (CLASS == classPointProcess) point = (PointProcess) OBJECT;
-		if (intensity && point) break;   // OPTIMIZE
-	}
-	autoIntensityTier thee = IntensityTier_PointProcess_to_IntensityTier (intensity, point);
-	praat_new (thee.move(), intensity -> name);
-END2 }
-
-/***** INTENSITYTIER & SOUND *****/
+FORM (GRAPHICS_old_Ltas_draw, U"Ltas: Draw", nullptr) {
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0 (= all)")
+	REALVAR (fromPower, U"left Power range (dB/Hz)", U"-20.0")
+	REALVAR (toPower, U"right Power range (dB/Hz)", U"80.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Ltas)
+		Ltas_draw (me, GRAPHICS, fromFrequency, toFrequency, fromPower, toPower, garnish, U"Bars");
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Sound_IntensityTier_multiply_old) {
-	Sound sound = nullptr;
-	IntensityTier intensity = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-		if (CLASS == classIntensityTier) intensity = (IntensityTier) OBJECT;
-		if (sound && intensity) break;   // OPTIMIZE
-	}
-	autoSound thee = Sound_IntensityTier_multiply (sound, intensity, true);
-	praat_new (thee.move(), sound -> name, U"_int");
-END2 }
+FORM (GRAPHICS_Ltas_draw, U"Ltas: Draw", nullptr) {
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0 (= all)")
+	REALVAR (fromPower, U"left Power range (dB/Hz)", U"-20.0")
+	REALVAR (toPower, U"right Power range (dB/Hz)", U"80.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	LABEL (U"", U"")
+	OPTIONMENUSTRVAR (drawingMethod, U"Drawing method", 2)
+		OPTION (U"Curve")
+		OPTION (U"Bars")
+		OPTION (U"Poles")
+		OPTION (U"Speckles")
+	OK
+DO_ALTERNATIVE (GRAPHICS_old_Ltas_draw)
+	GRAPHICS_EACH (Ltas)
+		Ltas_draw (me, GRAPHICS, fromFrequency, toFrequency, fromPower, toPower, garnish, drawingMethod);
+	GRAPHICS_EACH_END
+}
 
-FORM (Sound_IntensityTier_multiply, U"Sound & IntervalTier: Multiply", nullptr) {
-	BOOLEAN (U"Scale to 0.9", true)
-	OK2
+FORM (MODIFY_Ltas_formula, U"Ltas Formula", nullptr) {
+	LABEL (U"label", U"`x' is the frequency in hertz, `col' is the bin number")
+	LABEL (U"label", U"x := x1;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
+	TEXTFIELD4 (formula, U"formula", U"0")
+	OK
 DO
-	Sound sound = nullptr;
-	IntensityTier intensity = nullptr;
-	LOOP {
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-		if (CLASS == classIntensityTier) intensity = (IntensityTier) OBJECT;
-		if (sound && intensity) break;   // OPTIMIZE
-	}
-	autoSound thee = Sound_IntensityTier_multiply (sound, intensity, GET_INTEGER (U"Scale to 0.9"));
-	praat_new (thee.move(), sound -> name, U"_int");
-END2 }
-
-/***** INTERVALTIER, rest in praat_TextGrid_init.cpp *****/
+	MODIFY_EACH_WEAK (Ltas)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM_READ2 (IntervalTier_readFromXwaves, U"Read IntervalTier from Xwaves", 0, true) {
-	autoIntervalTier me = IntervalTier_readFromXwaves (file);
-	praat_newWithFile (me.move(), file, MelderFile_name (file));
-END2 }
+DIRECT (REAL_Ltas_getLowestFrequency) {
+	NUMBER_ONE (Ltas)
+		double result = my xmin;
+	NUMBER_ONE_END (U" hertz")
+}
 
-/***** LTAS *****/
+DIRECT (REAL_Ltas_getHighestFrequency) {
+	NUMBER_ONE (Ltas)
+		double result = my xmax;
+	NUMBER_ONE_END (U" hertz")
+}
 
-DIRECT2 (Ltases_average) {
-	autoLtasBag ltases = LtasBag_create ();
-	LOOP {
-		iam (Ltas);
-		ltases -> addItem_ref (me);
-	}
-	autoLtas result = Ltases_average (ltases.get());
-	praat_new (result.move(), U"averaged");
-END2 }
+DIRECT (REAL_Ltas_getBinWidth) {
+	NUMBER_ONE (Ltas)
+		double result = my dx;
+	NUMBER_ONE_END (U" hertz")
+}
 
-FORM (Ltas_computeTrendLine, U"Ltas: Compute trend line", U"Ltas: Compute trend line...") {
-	REAL (U"left Frequency range (Hz)", U"600.0")
-	POSITIVE (U"right Frequency range (Hz)", U"4000.0")
-	OK2
+FORM (REAL_Ltas_getFrequencyFromBinNumber, U"Ltas: Get frequency from bin number", U"Ltas: Get frequency from bin number...") {
+	NATURAL4 (binNumber, U"Bin number", U"1")
+	OK
 DO
-	LOOP {
-		iam (Ltas);
-		autoLtas thee = Ltas_computeTrendLine (me, GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"));
-		praat_new (thee.move(), my name, U"_trend");
-	}
-END2 }
+	NUMBER_ONE (Ltas)
+		double result = Sampled_indexToX (me, binNumber);
+	NUMBER_ONE_END (U" hertz")
+}
 
-FORM (old_Ltas_draw, U"Ltas: Draw", nullptr) {
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0 (= all)")
-	REAL (U"left Power range (dB/Hz)", U"-20.0")
-	REAL (U"right Power range (dB/Hz)", U"80.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
+FORM (REAL_Ltas_getBinNumberFromFrequency, U"Ltas: Get band from frequency", U"Ltas: Get band from frequency...") {
+	REAL4 (frequency, U"Frequency (Hz)", U"2000.0")
+	OK
 DO
-	LOOP {
-		iam (Ltas);
-		autoPraatPicture picture;
-		Ltas_draw (me, GRAPHICS,
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Power range"),
-			GET_REAL (U"right Power range"),
-			GET_INTEGER (U"Garnish"), U"Bars");
-	}
-END2 }
-
-FORM (Ltas_draw, U"Ltas: Draw", nullptr) {
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0 (= all)")
-	REAL (U"left Power range (dB/Hz)", U"-20.0")
-	REAL (U"right Power range (dB/Hz)", U"80.0")
-	BOOLEAN (U"Garnish", true)
-	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 2)
-		OPTION (U"Curve")
-		OPTION (U"Bars")
-		OPTION (U"Poles")
-		OPTION (U"Speckles")
-	OK2
-DO_ALTERNATIVE (old_Ltas_draw)
-	LOOP {
-		iam (Ltas);
-		autoPraatPicture picture;
-		Ltas_draw (me, GRAPHICS,
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Power range"),
-			GET_REAL (U"right Power range"),
-			GET_INTEGER (U"Garnish"),
-			GET_STRING (U"Drawing method"));
-	}
-END2 }
+	NUMBER_ONE (Ltas)
+		double result = Sampled_xToIndex (me, frequency);
+	NUMBER_ONE_END (U"")
+}
 
-FORM (Ltas_formula, U"Ltas Formula", nullptr) {
-	LABEL (U"label", U"`x' is the frequency in hertz, `col' is the bin number")
-	LABEL (U"label", U"x := x1;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
-	TEXTFIELD (U"formula", U"0")
-	OK2
-DO
-	LOOP {
-		iam (Ltas);
-		try {
-			Matrix_formula (reinterpret_cast <Matrix> (me), GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Ltas may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (Ltas_getBinNumberFromFrequency, U"Ltas: Get band from frequency", U"Ltas: Get band from frequency...") {
-	REAL (U"Frequency (Hz)", U"2000.0")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double binNumber = Sampled_xToIndex (me, GET_REAL (U"Frequency"));
-	Melder_informationReal (binNumber, nullptr);
-END2 }
-
-DIRECT2 (Ltas_getBinWidth) {
-	Ltas me = FIRST (Ltas);
-	Melder_informationReal (my dx, U"hertz");
-END2 }
-
-FORM (Ltas_getFrequencyFromBinNumber, U"Ltas: Get frequency from bin number", U"Ltas: Get frequency from bin number...") {
-	NATURAL (U"Bin number", U"1")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double frequency = Sampled_indexToX (me, GET_INTEGER (U"Bin number"));
-	Melder_informationReal (frequency, U"hertz");
-END2 }
-
-FORM (Ltas_getFrequencyOfMaximum, U"Ltas: Get frequency of maximum", U"Ltas: Get frequency of maximum...") {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 1)
+FORM (REAL_Ltas_getFrequencyOfMinimum, U"Ltas: Get frequency of minimum", U"Ltas: Get frequency of minimum...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 1, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double frequency = Vector_getXOfMaximum (me,
-		GET_REAL (U"From frequency"),
-		GET_REAL (U"To frequency"),
-		GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (frequency, U"hertz");
-END2 }
-
-FORM (Ltas_getFrequencyOfMinimum, U"Ltas: Get frequency of minimum", U"Ltas: Get frequency of minimum...") {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Vector_getXOfMinimum (me, fromFrequency, toFrequency, interpolation);
+	NUMBER_ONE_END (U" hertz");
+}
+
+FORM (REAL_Ltas_getFrequencyOfMaximum, U"Ltas: Get frequency of maximum", U"Ltas: Get frequency of maximum...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 1, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double frequency = Vector_getXOfMinimum (me,
-		GET_REAL (U"From frequency"),
-		GET_REAL (U"To frequency"),
-		GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (frequency, U"hertz");
-END2 }
-
-DIRECT2 (Ltas_getHighestFrequency) {
-	Ltas me = FIRST (Ltas);
-	Melder_informationReal (my xmax, U"Hz");
-END2 }
-
-FORM (Ltas_getLocalPeakHeight, U"Ltas: Get local peak height", nullptr) {
-	REAL (U"left Environment (Hz)", U"1700.0")
-	REAL (U"right Environment (Hz)", U"4200.0")
-	REAL (U"left Peak (Hz)", U"2400.0")
-	REAL (U"right Peak (Hz)", U"3200.0")
-	RADIO (U"Averaging method", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Vector_getXOfMaximum (me, fromFrequency, toFrequency, interpolation);
+	NUMBER_ONE_END (U" hertz");
+}
+
+FORM (REAL_Ltas_getLocalPeakHeight, U"Ltas: Get local peak height", nullptr) {
+	REALVAR (environmentMin, U"left Environment (Hz)", U"1700.0")
+	REALVAR (environmentMax, U"right Environment (Hz)", U"4200.0")
+	REALVAR (peakMin, U"left Peak (Hz)", U"2400.0")
+	REALVAR (peakMax, U"right Peak (Hz)", U"3200.0")
+	RADIOVAR (averagingMethod, U"Averaging method", 1)
 		RADIOBUTTON (U"energy")
 		RADIOBUTTON (U"sones")
 		RADIOBUTTON (U"dB")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double environmentMin = GET_REAL (U"left Environment"), environmentMax = GET_REAL (U"right Environment");
-	double peakMin = GET_REAL (U"left Peak"), peakMax = GET_REAL (U"right Peak");
-	if (environmentMin >= peakMin) Melder_throw (U"The beginning of the environment must lie before the peak.");
-	if (peakMin >= peakMax) Melder_throw (U"The end of the peak must lie after its beginning.");
-	if (environmentMax <= peakMax) Melder_throw (U"The end of the environment must lie after the peak.");
-	double localPeakHeight = Ltas_getLocalPeakHeight (me, environmentMin, environmentMax,
-		peakMin, peakMax, GET_INTEGER (U"Averaging method"));
-	Melder_informationReal (localPeakHeight, U"dB");
-END2 }
-
-DIRECT2 (Ltas_getLowestFrequency) {
-	Ltas me = FIRST (Ltas);
-	Melder_informationReal (my xmin, U"hertz");
-END2 }
-
-FORM (Ltas_getMaximum, U"Ltas: Get maximum", U"Ltas: Get maximum...") {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		if (environmentMin >= peakMin)
+			Melder_throw (U"The beginning of the environment must lie before the peak.");
+		if (peakMin >= peakMax)
+			Melder_throw (U"The end of the peak must lie after its beginning.");
+		if (environmentMax <= peakMax)
+			Melder_throw (U"The end of the environment must lie after the peak.");
+		double result = Ltas_getLocalPeakHeight (me, environmentMin, environmentMax, peakMin, peakMax, averagingMethod);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_Ltas_getMaximum, U"Ltas: Get maximum", U"Ltas: Get maximum...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 1, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double maximum = Vector_getMaximum (me,
-		GET_REAL (U"From frequency"),
-		GET_REAL (U"To frequency"),
-		GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (maximum, U"dB");
-END2 }
-
-FORM (Ltas_getMean, U"Ltas: Get mean", U"Ltas: Get mean...") {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= all)")
-	RADIO (U"Averaging method", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Vector_getMaximum (me, fromFrequency, toFrequency, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_Ltas_getMean, U"Ltas: Get mean", U"Ltas: Get mean...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= all)")
+	RADIO4 (averagingMethod, U"Averaging method", 1)
 		RADIOBUTTON (U"energy")
 		RADIOBUTTON (U"sones")
 		RADIOBUTTON (U"dB")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double mean = Sampled_getMean_standardUnit (me,
-		GET_REAL (U"From frequency"),
-		GET_REAL (U"To frequency"),
-		0,
-		GET_INTEGER (U"Averaging method"),
-		false);
-	Melder_informationReal (mean, U"dB");
-END2 }
-
-FORM (Ltas_getMinimum, U"Ltas: Get minimum", U"Ltas: Get minimum...") {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Sampled_getMean_standardUnit (me, fromFrequency, toFrequency,
+			0, averagingMethod, false);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_Ltas_getMinimum, U"Ltas: Get minimum", U"Ltas: Get minimum...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 1, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double minimum = Vector_getMinimum (me,
-		GET_REAL (U"From frequency"),
-		GET_REAL (U"To frequency"),
-		GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (minimum, U"dB");
-END2 }
-
-DIRECT2 (Ltas_getNumberOfBins) {
-	Ltas me = FIRST (Ltas);
-	long numberOfBins = my nx;
-	Melder_information (numberOfBins, U" bins");
-END2 }
-
-FORM (Ltas_getSlope, U"Ltas: Get slope", 0) {
-	REAL (U"left Low band (Hz)", U"0.0")
-	REAL (U"right Low band (Hz)", U"1000.0")
-	REAL (U"left High band (Hz)", U"1000.0")
-	REAL (U"right High band (Hz)", U"4000.0")
-	RADIO (U"Averaging method", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Vector_getMinimum (me, fromFrequency, toFrequency, interpolation);
+	NUMBER_ONE_END (U" dB")
+}
+
+DIRECT (INTEGER_Ltas_getNumberOfBins) {
+	NUMBER_ONE (Ltas)
+		long result = my nx;
+	NUMBER_ONE_END (U" bins")
+}
+
+FORM (REAL_Ltas_getSlope, U"Ltas: Get slope", 0) {
+	REAL4 (lowBandFrom, U"left Low band (Hz)", U"0.0")
+	REAL4 (lowBandTo, U"right Low band (Hz)", U"1000.0")
+	REAL4 (highBandFrom, U"left High band (Hz)", U"1000.0")
+	REAL4 (highBandTo, U"right High band (Hz)", U"4000.0")
+	RADIO4 (averagingMethod, U"Averaging method", 1)
 		RADIOBUTTON (U"energy")
 		RADIOBUTTON (U"sones")
 		RADIOBUTTON (U"dB")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double slope = Ltas_getSlope (me,
-		GET_REAL (U"left Low band"),
-		GET_REAL (U"right Low band"),
-		GET_REAL (U"left High band"),
-		GET_REAL (U"right High band"),
-		GET_INTEGER (U"Averaging method"));
-	Melder_informationReal (slope, U"dB");
-END2 }
-
-FORM (Ltas_getStandardDeviation, U"Ltas: Get standard deviation", U"Ltas: Get standard deviation...") {
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"0.0 (= all)")
-	RADIO (U"Averaging method", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Ltas_getSlope (me, lowBandFrom, lowBandTo, highBandFrom, highBandTo, averagingMethod);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_Ltas_getStandardDeviation, U"Ltas: Get standard deviation", U"Ltas: Get standard deviation...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"0.0 (= all)")
+	RADIO4 (averagingMethod, U"Averaging method", 1)
 		RADIOBUTTON (U"energy")
 		RADIOBUTTON (U"sones")
 		RADIOBUTTON (U"dB")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double stdev = Sampled_getStandardDeviation_standardUnit (me,
-		GET_REAL (U"From frequency"),
-		GET_REAL (U"To frequency"),
-		0,   // level (irrelevant)
-		GET_INTEGER (U"Averaging method"),
-		false);   // interpolate (don't)
-	Melder_informationReal (stdev, U"dB");
-END2 }
-
-FORM (Ltas_getValueAtFrequency, U"Ltas: Get value", U"Ltas: Get value at frequency...") {
-	REAL (U"Frequency (Hz)", U"1500")
-	RADIO (U"Interpolation", 1)
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Sampled_getStandardDeviation_standardUnit (me, fromFrequency, toFrequency,
+			0,   // level (irrelevant)
+			averagingMethod,
+			false);   // interpolate (don't)
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_Ltas_getValueAtFrequency, U"Ltas: Get value", U"Ltas: Get value at frequency...") {
+	REAL4 (frequency, U"Frequency (Hz)", U"1500.0")
+	RADIO4x (interpolation, U"Interpolation", 1, 0)
 		RADIOBUTTON (U"Nearest")
 		RADIOBUTTON (U"Linear")
 		RADIOBUTTON (U"Cubic")
 		RADIOBUTTON (U"Sinc70")
 		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	double value = Vector_getValueAtX (me,
-		GET_REAL (U"Frequency"),
-		1,   // level
-		GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (value, U"dB");
-END2 }
-	
-FORM (Ltas_getValueInBin, U"Get value in bin", U"Ltas: Get value in bin...") {
-	INTEGER (U"Bin number", U"100")
-	OK2
-DO
-	Ltas me = FIRST (Ltas);
-	long binNumber = GET_INTEGER (U"Bin number");
-	double value = binNumber < 1 || binNumber > my nx ? NUMundefined : my z [1] [binNumber];
-	Melder_informationReal (value, U"dB");
-END2 }
-
-DIRECT2 (Ltas_help) {
-	Melder_help (U"Ltas");
-END2 }
-
-DIRECT2 (Ltases_merge) {
-	autoLtasBag ltases = LtasBag_create ();
-	LOOP {
-		iam (Ltas);
-		ltases -> addItem_ref (me);
-	}
-	autoLtas thee = Ltases_merge (ltases.get());
-	praat_new (thee.move(), U"merged");
-END2 }
+	OK
+DO
+	NUMBER_ONE (Ltas)
+		double result = Vector_getValueAtX (me, frequency,
+			1,   // level
+			interpolation);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Ltas_subtractTrendLine, U"Ltas: Subtract trend line", U"Ltas: Subtract trend line...") {
-	REAL (U"left Frequency range (Hz)", U"600.0")
-	POSITIVE (U"right Frequency range (Hz)", U"4000.0")
-	OK2
+FORM (REAL_Ltas_getValueInBin, U"Get value in bin", U"Ltas: Get value in bin...") {
+	INTEGER4 (binNumber, U"Bin number", U"100")
+	OK
 DO
-	LOOP {
-		iam (Ltas);
-		autoLtas result = Ltas_subtractTrendLine (me,
-			GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"));
-		praat_new (result.move(), my name, U"_fit");
-	}
-END2 }
+	NUMBER_ONE (Ltas)
+		double result = binNumber < 1 || binNumber > my nx ? NUMundefined : my z [1] [binNumber];
+	NUMBER_ONE_END (U" dB")
+}
 
-DIRECT2 (Ltas_to_Matrix) {
-	LOOP {
-		iam (Ltas);
+DIRECT (HELP_Ltas_help) {
+	HELP (U"Ltas")
+}
+
+DIRECT (NEW1_Ltases_merge) {
+	CONVERT_TYPED_LIST (Ltas, LtasBag)
+		autoLtas result = Ltases_merge (list.get());
+	CONVERT_TYPED_LIST_END (U"merged")
+}
+
+FORM (NEW_Ltas_subtractTrendLine, U"Ltas: Subtract trend line", U"Ltas: Subtract trend line...") {
+	REAL4 (fromFrequency, U"left Frequency range (Hz)", U"600.0")
+	POSITIVE4 (toFrequency, U"right Frequency range (Hz)", U"4000.0")
+	OK
+DO
+	CONVERT_EACH (Ltas)
+		autoLtas result = Ltas_subtractTrendLine (me, fromFrequency, toFrequency);
+	CONVERT_EACH_END (my name, U"_fit")
+}
+
+DIRECT (NEW_Ltas_to_Matrix) {
+	CONVERT_EACH (Ltas)
 		autoMatrix result = Ltas_to_Matrix (me);
-		praat_new (result.move(), my name);
-	}
-END2 }
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Ltas_to_SpectrumTier_peaks) {
-	LOOP {
-		iam (Ltas);
-		autoSpectrumTier thee = Ltas_to_SpectrumTier_peaks (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Ltas_to_SpectrumTier_peaks) {
+	CONVERT_EACH (Ltas)
+		autoSpectrumTier result = Ltas_to_SpectrumTier_peaks (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** MANIPULATION *****/
+// MARK: - MANIPULATION
 
 static void cb_ManipulationEditor_publication (Editor /* editor */, autoDaata publication) {
 	try {
@@ -2442,7 +1279,7 @@ static void cb_ManipulationEditor_publication (Editor /* editor */, autoDaata pu
 		Melder_flushError ();
 	}
 }
-DIRECT2 (Manipulation_edit) {
+DIRECT (WINDOW_Manipulation_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Manipulation from batch.");
 	LOOP {
 		iam (Manipulation);
@@ -2451,2873 +1288,941 @@ DIRECT2 (Manipulation_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-DIRECT2 (Manipulation_extractDurationTier) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (NEW_Manipulation_extractDurationTier) {
+	CONVERT_EACH (Manipulation)
 		if (! my duration) Melder_throw (me, U": I don't contain a DurationTier.");
-		autoDurationTier thee = Data_copy (my duration.get());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+		autoDurationTier result = Data_copy (my duration.get());
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Manipulation_extractOriginalSound) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (NEW_Manipulation_extractOriginalSound) {
+	CONVERT_EACH (Manipulation)
 		if (! my sound) Melder_throw (me, U": I don't contain a Sound.");
-		autoSound thee = Data_copy (my sound.get());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+		autoSound result = Data_copy (my sound.get());
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Manipulation_extractPitchTier) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (NEW_Manipulation_extractPitchTier) {
+	CONVERT_EACH (Manipulation)
 		if (! my pitch) Melder_throw (me, U": I don't contain a PitchTier.");
-		autoPitchTier thee = Data_copy (my pitch.get());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+		autoPitchTier result = Data_copy (my pitch.get());
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Manipulation_extractPulses) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (NEW_Manipulation_extractPulses) {
+	CONVERT_EACH (Manipulation)
 		if (! my pulses) Melder_throw (me, U": I don't contain a PointProcess.");
-		autoPointProcess thee = Data_copy (my pulses.get());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+		autoPointProcess result = Data_copy (my pulses.get());
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Manipulation_getResynthesis_lpc) {
-	LOOP {
-		iam (Manipulation);
-		autoSound thee = Manipulation_to_Sound (me, Manipulation_PITCH_LPC);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Manipulation_getResynthesis_lpc) {
+	CONVERT_EACH (Manipulation)
+		autoSound result = Manipulation_to_Sound (me, Manipulation_PITCH_LPC);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Manipulation_getResynthesis_overlapAdd) {
-	LOOP {
-		iam (Manipulation);
-		autoSound thee = Manipulation_to_Sound (me, Manipulation_OVERLAPADD);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Manipulation_getResynthesis_overlapAdd) {
+	CONVERT_EACH (Manipulation)
+		autoSound result = Manipulation_to_Sound (me, Manipulation_OVERLAPADD);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Manipulation_help) {
-	Melder_help (U"Manipulation");
-END2 }
+DIRECT (HELP_Manipulation_help) {
+	HELP (U"Manipulation")
+}
 
-DIRECT2 (Manipulation_play_lpc) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (PLAY_Manipulation_play_lpc) {
+	PLAY_EACH (Manipulation)
 		Manipulation_play (me, Manipulation_PITCH_LPC);
-	}
-END2 }
+	PLAY_EACH_END
+}
 
-DIRECT2 (Manipulation_play_overlapAdd) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (PLAY_Manipulation_play_overlapAdd) {
+	PLAY_EACH (Manipulation)
 		Manipulation_play (me, Manipulation_OVERLAPADD);
-	}
-END2 }
+	PLAY_EACH_END
+}
 
-DIRECT2 (Manipulation_removeDuration) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (MODIFY_Manipulation_removeDuration) {
+	MODIFY_EACH (Manipulation)
 		my duration = autoDurationTier();
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (Manipulation_removeOriginalSound) {
-	LOOP {
-		iam (Manipulation);
+DIRECT (MODIFY_Manipulation_removeOriginalSound) {
+	MODIFY_EACH (Manipulation)
 		my sound = autoSound();
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM_WRITE (Manipulation_writeToBinaryFileWithoutSound, U"Binary file without Sound", nullptr, nullptr)
-	Manipulation_writeToBinaryFileWithoutSound (FIRST_ANY (Manipulation), file);
-END
-
-FORM_WRITE (Manipulation_writeToTextFileWithoutSound, U"Text file without Sound", nullptr, nullptr)
-	Manipulation_writeToTextFileWithoutSound (FIRST_ANY (Manipulation), file);
-END
-
-DIRECT2 (info_DurationTier_Manipulation_replace) {
-	Melder_information (U"To replace the DurationTier in a Manipulation object,\n"
-		"select a DurationTier object and a Manipulation object\nand choose \"Replace duration\".");
-END2 }
-
-DIRECT2 (info_PitchTier_Manipulation_replace) {
-	Melder_information (U"To replace the PitchTier in a Manipulation object,\n"
-		"select a PitchTier object and a Manipulation object\nand choose \"Replace pitch\".");
-END2 }
-
-/***** MANIPULATION & DURATIONTIER *****/
-
-DIRECT2 (Manipulation_replaceDurationTier) {
-	Manipulation me = FIRST (Manipulation);
-	Manipulation_replaceDurationTier (me, FIRST (DurationTier));
-	praat_dataChanged (me);
-END2 }
-
-DIRECT2 (Manipulation_replaceDurationTier_help) {
-	Melder_help (U"Manipulation: Replace duration tier");
-END2 }
-
-/***** MANIPULATION & PITCHTIER *****/
-
-DIRECT2 (Manipulation_replacePitchTier) {
-	Manipulation me = FIRST (Manipulation);
-	Manipulation_replacePitchTier (me, FIRST (PitchTier));
-	praat_dataChanged (me);
-END2 }
-
-DIRECT2 (Manipulation_replacePitchTier_help) {
-	Melder_help (U"Manipulation: Replace pitch tier");
-END2 }
-
-/***** MANIPULATION & POINTPROCESS *****/
-
-DIRECT2 (Manipulation_replacePulses) {
-	Manipulation me = FIRST (Manipulation);
-	Manipulation_replacePulses (me, FIRST (PointProcess));
-	praat_dataChanged (me);
-END2 }
-
-/***** MANIPULATION & SOUND *****/
-
-DIRECT2 (Manipulation_replaceOriginalSound) {
-	Manipulation me = FIRST (Manipulation);
-	Manipulation_replaceOriginalSound (me, FIRST (Sound));
-	praat_dataChanged (me);
-END2 }
-
-/***** MANIPULATION & TEXTTIER *****/
-
-DIRECT2 (Manipulation_TextTier_to_Manipulation) {
-	Manipulation me = FIRST (Manipulation);
-	TextTier thee = FIRST (TextTier);
-	autoManipulation him = Manipulation_AnyTier_to_Manipulation (me, reinterpret_cast <AnyTier> (thee));
-	praat_new (him.move(), my name);
-END2 }
-
-/***** MATRIX *****/
-
-DIRECT2 (Matrix_appendRows) {
-	Matrix m1 = nullptr, m2 = nullptr;
-	LOOP (m1 ? m2 : m1) = (Matrix) OBJECT;
-	autoMatrix thee = Matrix_appendRows (m1, m2, classMatrix);
-	praat_new (thee.move(), m1 -> name, U"_", m2 -> name);
-END2 }
-
-FORM (Matrix_create, U"Create Matrix", U"Create Matrix...") {
-	WORD (U"Name", U"xy")
-	REAL (U"xmin", U"1.0")
-	REAL (U"xmax", U"1.0")
-	NATURAL (U"Number of columns", U"1")
-	POSITIVE (U"dx", U"1.0")
-	REAL (U"x1", U"1.0")
-	REAL (U"ymin", U"1.0")
-	REAL (U"ymax", U"1.0")
-	NATURAL (U"Number of rows", U"1")
-	POSITIVE (U"dy", U"1.0")
-	REAL (U"y1", U"1.0")
-	LABEL (U"", U"Formula:")
-	TEXTFIELD (U"formula", U"x*y")
-	OK2
-DO
-	double xmin = GET_REAL (U"xmin"), xmax = GET_REAL (U"xmax");
-	double ymin = GET_REAL (U"ymin"), ymax = GET_REAL (U"ymax");
-	if (xmax < xmin) Melder_throw (U"xmax (", Melder_single (xmax), U") should not be less than xmin (", Melder_single (xmin), U").");
-	if (ymax < ymin) Melder_throw (U"ymax (", Melder_single (ymax), U") should not be less than ymin (", Melder_single (ymin), U").");
-	autoMatrix me = Matrix_create (
-		xmin, xmax, GET_INTEGER (U"Number of columns"), GET_REAL (U"dx"), GET_REAL (U"x1"),
-		ymin, ymax, GET_INTEGER (U"Number of rows"), GET_REAL (U"dy"), GET_REAL (U"y1"));
-	Matrix_formula (me.get(), GET_STRING (U"formula"), interpreter, nullptr);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Matrix_createSimple, U"Create simple Matrix", U"Create simple Matrix...") {
-	WORD (U"Name", U"xy")
-	NATURAL (U"Number of rows", U"10")
-	NATURAL (U"Number of columns", U"10")
-	LABEL (U"", U"Formula:")
-	TEXTFIELD (U"formula", U"x*y")
-	OK2
-DO
-	autoMatrix me = Matrix_createSimple (GET_INTEGER (U"Number of rows"), GET_INTEGER (U"Number of columns"));
-	Matrix_formula (me.get(), GET_STRING (U"formula"), interpreter, nullptr);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Matrix_drawOneContour, U"Draw one altitude contour", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Height", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_drawOneContour (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Height"));
-	}
-END2 }
-
-FORM (Matrix_drawContours, U"Draw altitude contours", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_drawContours (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"));
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (Matrix_drawRows, U"Draw rows", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_drawRows (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="),
-			GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"));
-	}
-END2 }
+FORM_SAVE (SAVE_Manipulation_writeToBinaryFileWithoutSound, U"Binary file without Sound", nullptr, nullptr) {
+	SAVE_ONE (Manipulation)
+		Manipulation_writeToBinaryFileWithoutSound (me, file);
+	SAVE_ONE_END
+}
 
-DIRECT2 (Matrix_eigen) {
-	LOOP {
-		iam (Matrix);
-		autoMatrix vectors, values;
-		Matrix_eigen (me, & vectors, & values);
-		praat_new (vectors.move(), U"eigenvectors");
-		praat_new (values.move(), U"eigenvalues");
-	}
-END2 }
+FORM_SAVE (SAVE_Manipulation_writeToTextFileWithoutSound, U"Text file without Sound", nullptr, nullptr) {
+	SAVE_ONE (Manipulation)
+		Manipulation_writeToTextFileWithoutSound (me, file);
+	SAVE_ONE_END
+}
 
-FORM (Matrix_formula, U"Matrix Formula", U"Formula...") {
-	LABEL (U"label", U"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 (U"formula", U"self")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		try {
-			Matrix_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Matrix may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-DIRECT2 (Matrix_getHighestX) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_informationReal (my xmax, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getHighestY) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_informationReal (my ymax, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getLowestX) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_informationReal (my xmin, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getLowestY) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_informationReal (my ymin, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getNumberOfColumns) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_information (my nx);
-END2 }
-
-DIRECT2 (Matrix_getNumberOfRows) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_information (my ny);
-END2 }
-
-DIRECT2 (Matrix_getColumnDistance) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_informationReal (my dx, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getRowDistance) {
-	Matrix me = FIRST_ANY (Matrix);
-	Melder_informationReal (my dy, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getSum) {
-	Matrix me = FIRST_ANY (Matrix);
-	double sum = Matrix_getSum (me);
-	Melder_informationReal (sum, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getMaximum) {
-	Matrix me = FIRST_ANY (Matrix);
-	double minimum = NUMundefined, maximum = NUMundefined;
-	Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
-	Melder_informationReal (maximum, nullptr);
-END2 }
-
-DIRECT2 (Matrix_getMinimum) {
-	Matrix me = FIRST_ANY (Matrix);
-	double minimum = NUMundefined, maximum = NUMundefined;
-	Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
-	Melder_informationReal (minimum, nullptr);
-END2 }
-
-FORM (Matrix_getValueAtXY, U"Matrix: Get value at xy", nullptr) {
-	REAL (U"X", U"0")
-	REAL (U"Y", U"0")
-	OK2
-DO
-	Matrix me = FIRST_ANY (Matrix);
-	double x = GET_REAL (U"X"), y = GET_REAL (U"Y");
-	double value = Matrix_getValueAtXY (me, x, y);
-	Melder_information (value, U" (at x = ", x, U" and y = ", y, U")");
-END2 }
-
-FORM (Matrix_getValueInCell, U"Matrix: Get value in cell", nullptr) {
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	Matrix me = FIRST_ANY (Matrix);
-	long row = GET_INTEGER (U"Row number"), column = GET_INTEGER (U"Column number");
-	if (row > my ny) Melder_throw (U"Row number must not exceed number of rows.");
-	if (column > my nx) Melder_throw (U"Column number must not exceed number of columns.");
-	Melder_informationReal (my z [row] [column], nullptr);
-END2 }
-
-FORM (Matrix_getXofColumn, U"Matrix: Get x of column", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	Matrix me = FIRST_ANY (Matrix);
-	double x = Matrix_columnToX (me, GET_INTEGER (U"Column number"));
-	Melder_informationReal (x, nullptr);
-END2 }
-
-FORM (Matrix_getYofRow, U"Matrix: Get y of row", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
-DO
-	Matrix me = FIRST_ANY (Matrix);
-	double y = Matrix_rowToY (me, GET_INTEGER (U"Row number"));
-	Melder_informationReal (y, nullptr);
-END2 }
-
-DIRECT2 (Matrix_help) {
-	Melder_help (U"Matrix");
-END2 }
-
-DIRECT2 (Matrix_movie) {
-	Graphics g = Movie_create (U"Matrix movie", 300, 300);
-	LOOP {
-		iam (Matrix);
-		Matrix_movie (me, g);
-	}
-END2 }
+// MARK: - MANIPULATION & DURATIONTIER
 
-FORM (Matrix_paintCells, U"Matrix: Paint cells with greys", U"Matrix: Paint cells...") {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_paintCells (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"));
-	}
-END2 }
+DIRECT (MODIFY_Manipulation_replaceDurationTier) {
+	MODIFY_FIRST_OF_TWO (Manipulation, DurationTier)
+		Manipulation_replaceDurationTier (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (Matrix_paintContours, U"Matrix: Paint altitude contours with greys", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_paintContours (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"));
-	}
-END2 }
+DIRECT (HELP_Manipulation_replaceDurationTier_help) {
+	HELP (U"Manipulation: Replace duration tier")
+}
 
-FORM (Matrix_paintImage, U"Matrix: Paint grey image", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_paintImage (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"));
-	}
-END2 }
+// MARK: - MANIPULATION & PITCHTIER
 
-FORM (Matrix_paintSurface, U"Matrix: Paint 3-D surface plot", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	REAL (U"Minimum", U"0.0")
-	REAL (U"Maximum", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoPraatPicture picture;
-		Matrix_paintSurface (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="),
-			GET_REAL (U"Minimum"), GET_REAL (U"Maximum"), 30, 45);
-	}
-END2 }
+DIRECT (MODIFY_Manipulation_replacePitchTier) {
+	MODIFY_FIRST_OF_TWO (Manipulation, PitchTier)
+		Manipulation_replacePitchTier (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (Matrix_power, U"Matrix: Power...", nullptr) {
-	NATURAL (U"Power", U"2")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoMatrix thee = Matrix_power (me, GET_INTEGER (U"Power"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (HELP_Manipulation_replacePitchTier_help) {
+	HELP (U"Manipulation: Replace pitch tier")
+}
 
-FORM_READ2 (Matrix_readFromRawTextFile, U"Read Matrix from raw text file", nullptr, true) {
-	autoMatrix me = Matrix_readFromRawTextFile (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
+// MARK: - MANIPULATION & POINTPROCESS
 
-FORM_READ2 (Matrix_readAP, U"Read Matrix from LVS AP file", nullptr, true) {
-	autoMatrix me = Matrix_readAP (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
+DIRECT (MODIFY_Manipulation_replacePulses) {
+	MODIFY_FIRST_OF_TWO (Manipulation, PointProcess)
+		Manipulation_replacePulses (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (Matrix_setValue, U"Matrix: Set value", U"Matrix: Set value...") {
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
-	REAL (U"New value", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		long row = GET_INTEGER (U"Row number"), column = GET_INTEGER (U"Column number");
-		if (row > my ny) Melder_throw (U"Row number must not be greater than number of rows.");
-		if (column > my nx) Melder_throw (U"Column number must not be greater than number of columns.");
-		my z [row] [column] = GET_REAL (U"New value");
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - MANIPULATION & SOUND
 
-DIRECT2 (Matrix_to_Cochleagram) {
-	LOOP {
-		iam (Matrix);
-		autoCochleagram thee = Matrix_to_Cochleagram (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (MODIFY_Manipulation_replaceOriginalSound) {
+	MODIFY_FIRST_OF_TWO (Manipulation, Sound)
+		Manipulation_replaceOriginalSound (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-DIRECT2 (Matrix_to_Excitation) {
-	LOOP {
-		iam (Matrix);
-		autoExcitation thee = Matrix_to_Excitation (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: - MANIPULATION & TEXTTIER
 
-DIRECT2 (Matrix_to_Harmonicity) {
-	LOOP {
-		iam (Matrix);
-		autoHarmonicity thee = Matrix_to_Harmonicity (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW1_Manipulation_TextTier_to_Manipulation) {
+	CONVERT_TWO (Manipulation, TextTier)
+		autoManipulation result = Manipulation_AnyTier_to_Manipulation (me, reinterpret_cast <AnyTier> (you));
+	CONVERT_TWO_END (my name)
+}
 
-DIRECT2 (Matrix_to_Intensity) {
-	LOOP {
-		iam (Matrix);
-		autoIntensity thee = Matrix_to_Intensity (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: - PARAMCURVE
+
+FORM (GRAPHICS_ParamCurve_draw, U"Draw parametrized curve", nullptr) {
+	REAL4 (tmin, U"Tmin", U"0.0")
+	REAL4 (tmax, U"Tmax", U"0.0")
+	REAL4 (step, U"Step", U"0.0")
+	REAL4 (xmin, U"Xmin", U"0.0")
+	REAL4 (xmax, U"Xmax", U"0.0")
+	REAL4 (ymin, U"Ymin", U"0.0")
+	REAL4 (ymax, U"Ymax", U"0.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (ParamCurve)
+		ParamCurve_draw (me, GRAPHICS, tmin, tmax, step, xmin, xmax, ymin, ymax, garnish);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_Pitch) {
-	LOOP {
-		iam (Matrix);
-		autoPitch thee = Matrix_to_Pitch (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (HELP_ParamCurve_help) {
+	HELP (U"ParamCurve")
+}
 
-DIRECT2 (Matrix_to_Spectrogram) {
-	LOOP {
-		iam (Matrix);
-		autoSpectrogram thee = Matrix_to_Spectrogram (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: - PITCH
 
-DIRECT2 (Matrix_to_Spectrum) {
-	LOOP {
-		iam (Matrix);
-		autoSpectrum thee = Matrix_to_Spectrum (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (INTEGER_Pitch_getNumberOfVoicedFrames) {
+	NUMBER_ONE (Pitch)
+		long result = Pitch_countVoicedFrames (me);
+	NUMBER_ONE_END (U" voiced frames")
+}
 
-DIRECT2 (Matrix_to_Ltas) {
-	LOOP {
-		iam (Matrix);
-		autoLtas thee = Matrix_to_Ltas (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (INFO_Pitch_difference) {
+	INFO_COUPLE (Pitch)
+		Pitch_difference (me, you);
+	INFO_COUPLE_END
+}
 
-DIRECT2 (Matrix_to_ParamCurve) {
-	Matrix m1 = nullptr, m2 = nullptr;
-	LOOP (m1 ? m2 : m1) = (Matrix) OBJECT;
-	autoSound sound1 = Matrix_to_Sound (m1), sound2 = Matrix_to_Sound (m2);
-	autoParamCurve thee = ParamCurve_create (sound1.get(), sound2.get());
-	praat_new (thee.move(), m1 -> name, U"_", m2 -> name);
-END2 }
+FORM (GRAPHICS_Pitch_draw, U"Pitch: Draw", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"0.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	if (toFrequency <= fromFrequency) Melder_throw (U"Maximum frequency must be greater than minimum frequency.");
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_HERTZ);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_PointProcess) {
-	LOOP {
-		iam (Matrix);
-		autoPointProcess thee = Matrix_to_PointProcess (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_drawErb, U"Pitch: Draw erb", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (ERB)", U"0")
+	REALVAR (toFrequency, U"right Frequency range (ERB)", U"10.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_ERB);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_Polygon) {
-	LOOP {
-		iam (Matrix);
-		autoPolygon thee = Matrix_to_Polygon (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_drawLogarithmic, U"Pitch: Draw logarithmic", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"50.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	if (toFrequency <= fromFrequency) Melder_throw (U"Maximum frequency must be greater than minimum frequency.");
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_HERTZ_LOGARITHMIC);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_Sound) {
-	LOOP {
-		iam (Matrix);
-		autoSound thee = Matrix_to_Sound (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_drawMel, U"Pitch: Draw mel", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"500.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_MEL);
+	GRAPHICS_EACH_END
+}
 
-FORM (Matrix_to_Sound_mono, U"Matrix: To Sound (mono)", 0) {
-	INTEGER (U"Row", U"1")
-	LABEL (U"", U"(negative values count from last row)")
-	OK2
-DO
-	LOOP {
-		iam (Matrix);
-		autoSound thee = Matrix_to_Sound_mono (me, GET_INTEGER (U"Row"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_drawSemitones100, U"Pitch: Draw semitones (re 100 Hz)", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	LABEL (U"", U"Range in semitones re 100 Hz:")
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-12.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"30.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_SEMITONES_100);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_TableOfReal) {
-	LOOP {
-		iam (Matrix);
-		autoTableOfReal thee = Matrix_to_TableOfReal (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_drawSemitones200, U"Pitch: Draw semitones (re 200 Hz)", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	LABEL (U"", U"Range in semitones re 200 Hz:")
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-24.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"18.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_SEMITONES_200);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_Transition) {
-	LOOP {
-		iam (Matrix);
-		autoTransition thee = Matrix_to_Transition (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_drawSemitones440, U"Pitch: Draw semitones (re 440 Hz)", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	LABEL (U"", U"Range in semitones re 440 Hz:")
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-36.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"6.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, Pitch_speckle_NO, kPitch_unit_SEMITONES_440);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Matrix_to_VocalTract) {
+DIRECT (WINDOW_Pitch_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Pitch from batch.");
 	LOOP {
-		iam (Matrix);
-		autoVocalTract thee = Matrix_to_VocalTract (me);
-		praat_new (thee.move(), my name);
+		iam (Pitch);
+		autoPitchEditor editor = PitchEditor_create (ID_AND_FULL_NAME, me);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM_WRITE (Matrix_writeToMatrixTextFile, U"Save Matrix as matrix text file", nullptr, U"mat")
-	Matrix me = FIRST (Matrix);
-	Matrix_writeToMatrixTextFile (me, file);
-END
-
-FORM_WRITE (Matrix_writeToHeaderlessSpreadsheetFile, U"Save Matrix as spreadsheet", nullptr, U"txt")
-	Matrix me = FIRST (Matrix);
-	Matrix_writeToHeaderlessSpreadsheetFile (me, file);
-END
+FORM (MODIFY_Pitch_formula, U"Pitch: Formula", U"Formula...") {
+	LABEL (U"", U"x = time; col = frame; row = candidate (1 = current path); frequency (time, candidate) :=")
+	TEXTFIELD4 (formula, U"formula", U"self*2; Example: octave jump up")
+	OK
+DO
+	MODIFY_EACH_WEAK (Pitch)
+		Pitch_formula (me, formula, interpreter);
+	MODIFY_EACH_WEAK_END
+}
 
-/***** MOVIE *****/
+FORM (REAL_Pitch_getMinimum, U"Pitch: Get minimum", 0) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	RADIOVARx (interpolation, U"Interpolation", 2, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+	OK
+DO
+	NUMBER_ONE (Pitch)
+		double result = Pitch_getMinimum (me, fromTime, toTime, unit, interpolation);
+		result = Function_convertToNonlogarithmic (me, result, Pitch_LEVEL_FREQUENCY, unit);
+	NUMBER_ONE_END (U" ", Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0))
+}
 
-FORM_READ2 (Movie_openFromSoundFile, U"Open movie file", nullptr, true) {
-	autoMovie me = Movie_openFromSoundFile (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
+FORM (REAL_Pitch_getMaximum, U"Pitch: Get maximum", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	RADIOVARx (interpolation, U"Interpolation", 2, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+	OK
+DO
+	NUMBER_ONE (Pitch)
+		double result = Pitch_getMaximum (me, fromTime, toTime, unit, interpolation);
+		result = Function_convertToNonlogarithmic (me, result, Pitch_LEVEL_FREQUENCY, unit);
+	NUMBER_ONE_END (U" ", Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0))
+}
 
-FORM (Movie_paintOneImage, U"Movie: Paint one image", nullptr) {
-	NATURAL (U"Frame number", U"1")
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"1.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"1.0")
-	OK2
+FORM (REAL_Pitch_getMean, U"Pitch: Get mean", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	OK
 DO
-	LOOP {
-		iam (Movie);
-		autoPraatPicture picture;
-		Movie_paintOneImage (me, GRAPHICS, GET_INTEGER (U"Frame number"),
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="));
-	}
-END2 }
-
-DIRECT2 (Movie_viewAndEdit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Movie from batch.");
-	LOOP {
-		iam (Movie);
-		autoMovieWindow editor = MovieWindow_create (ID_AND_FULL_NAME, me);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-/***** PARAMCURVE *****/
-
-FORM (ParamCurve_draw, U"Draw parametrized curve", nullptr) {
-	REAL (U"Tmin", U"0.0")
-	REAL (U"Tmax", U"0.0")
-	REAL (U"Step", U"0.0")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	LOOP {
-		iam (ParamCurve);
-		autoPraatPicture picture;
-		ParamCurve_draw (me, GRAPHICS,
-			GET_REAL (U"Tmin"), GET_REAL (U"Tmax"), GET_REAL (U"Step"),
-			GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"),
-			GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-DIRECT (ParamCurve_help) Melder_help (U"ParamCurve"); END
-
-/***** PHOTO *****/
-
-FORM (Photo_create, U"Create Photo", U"Create Photo...") {
-	WORD (U"Name", U"xy")
-	REAL (U"xmin", U"1.0")
-	REAL (U"xmax", U"1.0")
-	NATURAL (U"Number of columns", U"1")
-	POSITIVE (U"dx", U"1.0")
-	REAL (U"x1", U"1.0")
-	REAL (U"ymin", U"1.0")
-	REAL (U"ymax", U"1.0")
-	NATURAL (U"Number of rows", U"1")
-	POSITIVE (U"dy", U"1.0")
-	REAL (U"y1", U"1.0")
-	LABEL (U"", U"Red formula:")
-	TEXTFIELD (U"redFormula", U"x*y/100")
-	LABEL (U"", U"Green formula:")
-	TEXTFIELD (U"greenFormula", U"x*y/1000")
-	LABEL (U"", U"Blue formula:")
-	TEXTFIELD (U"blueFormula", U"x*y/100")
-	OK2
-DO
-	double xmin = GET_REAL (U"xmin"), xmax = GET_REAL (U"xmax");
-	double ymin = GET_REAL (U"ymin"), ymax = GET_REAL (U"ymax");
-	if (xmax < xmin) Melder_throw (U"xmax (", Melder_single (xmax), U") should not be less than xmin (", Melder_single (xmin), U").");
-	if (ymax < ymin) Melder_throw (U"ymax (", Melder_single (ymax), U") should not be less than ymin (", Melder_single (ymin), U").");
-	autoPhoto me = Photo_create (
-		xmin, xmax, GET_INTEGER (U"Number of columns"), GET_REAL (U"dx"), GET_REAL (U"x1"),
-		ymin, ymax, GET_INTEGER (U"Number of rows"), GET_REAL (U"dy"), GET_REAL (U"y1"));
-	Matrix_formula (my d_red  .get(), GET_STRING (U"redFormula"),   interpreter, nullptr);
-	Matrix_formula (my d_green.get(), GET_STRING (U"greenFormula"), interpreter, nullptr);
-	Matrix_formula (my d_blue .get(), GET_STRING (U"blueFormula"),  interpreter, nullptr);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Photo_createSimple, U"Create simple Photo", U"Create simple Photo...") {
-	WORD (U"Name", U"xy")
-	NATURAL (U"Number of rows", U"10")
-	NATURAL (U"Number of columns", U"10")
-	LABEL (U"", U"Red formula:")
-	TEXTFIELD (U"redFormula", U"x*y/100")
-	LABEL (U"", U"Green formula:")
-	TEXTFIELD (U"greenFormula", U"x*y/1000")
-	LABEL (U"", U"Blue formula:")
-	TEXTFIELD (U"blueFormula", U"x*y/100")
-	OK2
-DO
-	autoPhoto me = Photo_createSimple (GET_INTEGER (U"Number of rows"), GET_INTEGER (U"Number of columns"));
-	Matrix_formula (my d_red.get(),   GET_STRING (U"redFormula"),   interpreter, nullptr);
-	Matrix_formula (my d_green.get(), GET_STRING (U"greenFormula"), interpreter, nullptr);
-	Matrix_formula (my d_blue.get(),  GET_STRING (U"blueFormula"),  interpreter, nullptr);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-DIRECT2 (Photo_extractBlue) {
-	LOOP {
-		iam (Photo);
-		autoMatrix thee = Data_copy (my d_blue.get());
-		praat_new (thee.move(), my name, U"_blue");
-	}
-END2 }
-
-DIRECT2 (Photo_extractGreen) {
-	LOOP {
-		iam (Photo);
-		autoMatrix thee = Data_copy (my d_green.get());
-		praat_new (thee.move(), my name, U"_green");
-	}
-END2 }
-
-DIRECT2 (Photo_extractRed) {
-	LOOP {
-		iam (Photo);
-		autoMatrix thee = Data_copy (my d_red.get());
-		praat_new (thee.move(), my name, U"_red");
-	}
-END2 }
-
-DIRECT2 (Photo_extractTransparency) {
-	LOOP {
-		iam (Photo);
-		autoMatrix thee = Data_copy (my d_transparency.get());
-		praat_new (thee.move(), my name, U"_transparency");
-	}
-END2 }
-
-FORM (Photo_formula_red, U"Photo Formula (red)", U"Formula (red)...") {
-	LABEL (U"label", U"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 (U"formula", U"self")
-	OK2
-DO
-	LOOP {
-		iam (Photo);
-		try {
-			Matrix_formula (my d_red.get(), GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Photo may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (Photo_formula_green, U"Photo Formula (green)", U"Formula (green)...") {
-	LABEL (U"label", U"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 (U"formula", U"self")
-	OK2
-DO
-	LOOP {
-		iam (Photo);
-		try {
-			Matrix_formula (my d_green.get(), GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Photo may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (Photo_formula_blue, U"Photo Formula (blue)", U"Formula (blue)...") {
-	LABEL (U"label", U"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 (U"formula", U"self")
-	OK2
-DO
-	LOOP {
-		iam (Photo);
-		try {
-			Matrix_formula (my d_blue.get(), GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Photo may have partially changed
-			throw;
-		}
-	}
-END2 }
+	NUMBER_ONE (Pitch)
+		double result = Pitch_getMean (me, fromTime, toTime, unit);
+		result = Function_convertToNonlogarithmic (me, result, Pitch_LEVEL_FREQUENCY, unit);
+	NUMBER_ONE_END (U" ", Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
+}
 
-FORM (Photo_formula_transparency, U"Photo Formula (transparency)", U"Formula (transparency)...") {
-	LABEL (U"label", U"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 (U"formula", U"self")
-	OK2
-DO
-	LOOP {
-		iam (Photo);
-		try {
-			Matrix_formula (my d_transparency.get(), GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Photo may have partially changed
-			throw;
+FORM (REAL_Pitch_getMeanAbsoluteSlope, U"Pitch: Get mean absolute slope", 0) {
+	RADIOVAR (unit, U"Unit", 1)
+		RADIOBUTTON (U"Hertz")
+		RADIOBUTTON (U"Mel")
+		RADIOBUTTON (U"Semitones")
+		RADIOBUTTON (U"ERB")
+	OK
+DO
+	FIND_ONE (Pitch)
+		double slope;
+		long nVoiced = (unit == 1 ? Pitch_getMeanAbsSlope_hertz : unit == 2 ? Pitch_getMeanAbsSlope_mel : unit == 3 ? Pitch_getMeanAbsSlope_semitones : Pitch_getMeanAbsSlope_erb)
+			(me, & slope);
+		if (nVoiced < 2) {
+			Melder_information (U"--undefined--");
+		} else {
+			Melder_information (slope, U" ", GET_STRING (U"Unit"), U"/s");
 		}
-	}
-END2 }
-
-FORM (Photo_paintCells, U"Photo: Paint cells with colour", U"Photo: Paint cells...") {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Photo);
-		autoPraatPicture picture;
-		Photo_paintCells (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="));
-	}
-END2 }
-
-FORM (Photo_paintImage, U"Photo: Paint colour image", nullptr) {
-	REAL (U"From x =", U"0.0")
-	REAL (U"To x =", U"0.0")
-	REAL (U"From y =", U"0.0")
-	REAL (U"To y =", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Photo);
-		autoPraatPicture picture;
-		Photo_paintImage (me, GRAPHICS,
-			GET_REAL (U"From x ="), GET_REAL (U"To x ="), GET_REAL (U"From y ="), GET_REAL (U"To y ="));
-	}
-END2 }
-
-FORM_WRITE (Photo_saveAsAppleIconFile, U"Save as Apple icon file", nullptr, U"icns")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsAppleIconFile (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsGIF, U"Save as GIF file", nullptr, U"gif")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsGIF (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsJPEG, U"Save as JPEG file", nullptr, U"jpg")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsJPEG (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsJPEG2000, U"Save as JPEG-2000 file", nullptr, U"jpg")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsJPEG2000 (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsPNG, U"Save as PNG file", nullptr, U"png")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsPNG (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsTIFF, U"Save as TIFF file", nullptr, U"tiff")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsTIFF (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsWindowsBitmapFile, U"Save as Windows bitmap file", nullptr, U"bmp")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsWindowsBitmapFile (me, file);
-	}
-END
-
-FORM_WRITE (Photo_saveAsWindowsIconFile, U"Save as Windows icon file", nullptr, U"ico")
-	LOOP {
-		iam (Photo);
-		Photo_saveAsWindowsIconFile (me, file);
-	}
-END
-
-/***** PHOTO & MATRIX *****/
-
-DIRECT2 (Photo_Matrix_replaceBlue) {
-	Photo me = FIRST (Photo);
-	Matrix thee = FIRST (Matrix);
-	Photo_replaceBlue (me, thee);
-	praat_dataChanged (me);
-END2 }
-
-DIRECT2 (Photo_Matrix_replaceGreen) {
-	Photo me = FIRST (Photo);
-	Matrix thee = FIRST (Matrix);
-	Photo_replaceGreen (me, thee);
-	praat_dataChanged (me);
-END2 }
-
-DIRECT2 (Photo_Matrix_replaceRed) {
-	Photo me = FIRST (Photo);
-	Matrix thee = FIRST (Matrix);
-	Photo_replaceRed (me, thee);
-	praat_dataChanged (me);
-END2 }
-
-DIRECT2 (Photo_Matrix_replaceTransparency) {
-	Photo me = FIRST (Photo);
-	Matrix thee = FIRST (Matrix);
-	Photo_replaceTransparency (me, thee);
-	praat_dataChanged (me);
-END2 }
-
-/***** PITCH *****/
-
-DIRECT2 (Pitch_getNumberOfVoicedFrames) {
-	Pitch me = FIRST (Pitch);
-	Melder_information (Pitch_countVoicedFrames (me), U" voiced frames");
-END2 }
-
-DIRECT2 (Pitch_difference) {
-	Pitch pit1 = nullptr, pit2 = nullptr;
-	LOOP (pit1 ? pit2 : pit1) = (Pitch) OBJECT;
-	Pitch_difference (pit1, pit2);
-END2 }
-
-FORM (Pitch_draw, U"Pitch: Draw", U"Pitch: Draw...") {
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_HERTZ);
-	}
-END2 }
-
-FORM (Pitch_drawErb, U"Pitch: Draw erb", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	REAL (U"left Frequency range (ERB)", U"0")
-	REAL (U"right Frequency range (ERB)", U"10.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_ERB);
-	}
-END2 }
-
-FORM (Pitch_drawLogarithmic, U"Pitch: Draw logarithmic", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	POSITIVE (STRING_FROM_FREQUENCY_HZ, U"50.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_HERTZ_LOGARITHMIC);
-	}
-END2 }
-
-FORM (Pitch_drawMel, U"Pitch: Draw mel", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	REAL (U"left Frequency range (mel)", U"0.0")
-	REAL (U"right Frequency range (mel)", U"500.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_MEL);
-	}
-END2 }
-
-FORM (Pitch_drawSemitones100, U"Pitch: Draw semitones (re 100 Hz)", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	LABEL (U"", U"Range in semitones re 100 Hz:")
-	REAL (U"left Frequency range (st)", U"-12.0")
-	REAL (U"right Frequency range (st)", U"30.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_SEMITONES_100);
-	}
-END2 }
-
-FORM (Pitch_drawSemitones200, U"Pitch: Draw semitones (re 200 Hz)", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	LABEL (U"", U"Range in semitones re 200 Hz:")
-	REAL (U"left Frequency range (st)", U"-24.0")
-	REAL (U"right Frequency range (st)", U"18.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_SEMITONES_200);
-	}
-END2 }
-
-FORM (Pitch_drawSemitones440, U"Pitch: Draw semitones (re 440 Hz)", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	LABEL (U"", U"Range in semitones re 440 Hz:")
-	REAL (U"left Frequency range (st)", U"-36.0")
-	REAL (U"right Frequency range (st)", U"6.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax,
-			GET_INTEGER (U"Garnish"), Pitch_speckle_NO, kPitch_unit_SEMITONES_440);
-	}
-END2 }
+	END
+}
 
-DIRECT2 (Pitch_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Pitch from batch.");
-	LOOP {
-		iam (Pitch);
-		autoPitchEditor editor = PitchEditor_create (ID_AND_FULL_NAME, me);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
+DIRECT (REAL_Pitch_getMeanAbsSlope_noOctave) {
+	NUMBER_ONE (Pitch)
+		double result;
+		(void) Pitch_getMeanAbsSlope_noOctave (me, & result);
+	NUMBER_ONE_END (U" semitones/s")
+}
 
-FORM (Pitch_formula, U"Pitch: Formula", U"Formula...") {
-	LABEL (U"", U"x = time; col = frame; row = candidate (1 = current path); frequency (time, candidate) :=")
-	TEXTFIELD (U"formula", U"self*2; Example: octave jump up")
-	OK2
+FORM (REAL_Pitch_getQuantile, U"Pitch: Get quantile", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (quantile, U"Quantile", U"0.50 (= median)")
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	OK
 DO
-	LOOP {
-		iam (Pitch);
-		try {
-			Pitch_formula (me, GET_STRING (U"formula"), interpreter);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Pitch may have partially changed
-			throw;
-		}
-	}
-END2 }
+	NUMBER_ONE (Pitch)
+		double result = Sampled_getQuantile (me, fromTime, toTime, quantile, Pitch_LEVEL_FREQUENCY, unit);
+		result = Function_convertToNonlogarithmic (me, result, Pitch_LEVEL_FREQUENCY, unit);
+	NUMBER_ONE_END (U" ", Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0))
+}
 
-FORM (Pitch_getMaximum, U"Pitch: Get maximum", nullptr) {
-	praat_dia_timeRange (dia);
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	RADIO (U"Interpolation", 2)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-	OK2
-DO
-	enum kPitch_unit unit = GET_ENUM (kPitch_unit, U"Unit");
-	Pitch me = FIRST (Pitch);
-	double value = Pitch_getMaximum (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), unit, GET_INTEGER (U"Interpolation") - 1);
-	value = Function_convertToNonlogarithmic (me, value, Pitch_LEVEL_FREQUENCY, unit);
-	Melder_informationReal (value, Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
-END2 }
-
-FORM (Pitch_getMean, U"Pitch: Get mean", nullptr) {
-	praat_dia_timeRange (dia);
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	OK2
-DO
-	enum kPitch_unit unit = GET_ENUM (kPitch_unit, U"Unit");
-	Pitch me = FIRST (Pitch);
-	double value = Pitch_getMean (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), unit);
-	value = Function_convertToNonlogarithmic (me, value, Pitch_LEVEL_FREQUENCY, unit);
-	Melder_informationReal (value, Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
-END2 }
-
-FORM (Pitch_getMeanAbsoluteSlope, U"Pitch: Get mean absolute slope", 0) {
-	RADIO (U"Unit", 1)
-		RADIOBUTTON (U"Hertz")
-		RADIOBUTTON (U"Mel")
-		RADIOBUTTON (U"Semitones")
-		RADIOBUTTON (U"ERB")
-	OK2
-DO
-	int unit = GET_INTEGER (U"Unit");
-	Pitch me = FIRST (Pitch);
-	double slope;
-	long nVoiced = (unit == 1 ? Pitch_getMeanAbsSlope_hertz : unit == 2 ? Pitch_getMeanAbsSlope_mel : unit == 3 ? Pitch_getMeanAbsSlope_semitones : Pitch_getMeanAbsSlope_erb)
-		(me, & slope);
-	if (nVoiced < 2) {
-		Melder_information (U"--undefined--");
-	} else {
-		Melder_information (slope, U" ", GET_STRING (U"Unit"), U"/s");
-	}
-END2 }
-
-DIRECT2 (Pitch_getMeanAbsSlope_noOctave) {
-	Pitch me = FIRST (Pitch);
-	double slope;
-	(void) Pitch_getMeanAbsSlope_noOctave (me, & slope);
-	Melder_informationReal (slope, U"Semitones/s");
-END2 }
-
-FORM (Pitch_getMinimum, U"Pitch: Get minimum", 0) {
-	praat_dia_timeRange (dia);
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	RADIO (U"Interpolation", 2)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-	OK2
-DO
-	enum kPitch_unit unit = GET_ENUM (kPitch_unit, U"Unit");
-	Pitch me = FIRST (Pitch);
-	double value = Sampled_getMinimum (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		Pitch_LEVEL_FREQUENCY, unit, GET_INTEGER (U"Interpolation") - 1);
-	value = Function_convertToNonlogarithmic (me, value, Pitch_LEVEL_FREQUENCY, unit);
-	Melder_informationReal (value, Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
-END2 }
-
-FORM (Pitch_getQuantile, U"Pitch: Get quantile", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"Quantile", U"0.50 (= median)")
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	OK2
-DO
-	enum kPitch_unit unit = GET_ENUM (kPitch_unit, U"Unit");
-	Pitch me = FIRST (Pitch);
-	double value = Sampled_getQuantile (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Quantile"), Pitch_LEVEL_FREQUENCY, unit);
-	value = Function_convertToNonlogarithmic (me, value, Pitch_LEVEL_FREQUENCY, unit);
-	Melder_informationReal (value, Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
-END2 }
-
-FORM (Pitch_getStandardDeviation, U"Pitch: Get standard deviation", nullptr) {
-	praat_dia_timeRange (dia);
-	OPTIONMENU (U"Unit", 1)
+FORM (REAL_Pitch_getStandardDeviation, U"Pitch: Get standard deviation", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OPTIONMENUVAR (unit, U"Unit", 1)
 		OPTION (U"Hertz")
 		OPTION (U"mel")
 		OPTION (U"logHertz")
 		OPTION (U"semitones")
 		OPTION (U"ERB")
-	OK2
+	OK
 DO
-	int unit = GET_INTEGER (U"Unit");
 	unit =
 		unit == 1 ? kPitch_unit_HERTZ :
 		unit == 2 ? kPitch_unit_MEL :
 		unit == 3 ? kPitch_unit_LOG_HERTZ :
 		unit == 4 ? kPitch_unit_SEMITONES_1 :
 		kPitch_unit_ERB;
-	Pitch me = FIRST (Pitch);
-	double value = Pitch_getStandardDeviation (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), unit);
-	const char32 *unitText =
-		unit == kPitch_unit_HERTZ ? U"Hz" :
-		unit == kPitch_unit_MEL ? U"mel" :
-		unit == kPitch_unit_LOG_HERTZ ? U"logHz" :
-		unit == kPitch_unit_SEMITONES_1 ? U"semitones" :
-		U"ERB";
-	Melder_informationReal (value, unitText);
-END2 }
-
-FORM (Pitch_getTimeOfMaximum, U"Pitch: Get time of maximum", nullptr) {
-	praat_dia_timeRange (dia);
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	RADIO (U"Interpolation", 2)
+	NUMBER_ONE (Pitch)
+		double result = Pitch_getStandardDeviation (me, fromTime, toTime, unit);
+		const char32 *unitText =
+			unit == kPitch_unit_HERTZ ? U"Hz" :
+			unit == kPitch_unit_MEL ? U"mel" :
+			unit == kPitch_unit_LOG_HERTZ ? U"logHz" :
+			unit == kPitch_unit_SEMITONES_1 ? U"semitones" :
+			U"ERB";
+	NUMBER_ONE_END (U" ", unitText)
+}
+
+FORM (REAL_Pitch_getTimeOfMaximum, U"Pitch: Get time of maximum", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	RADIOVARx (interpolation, U"Interpolation", 2, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
-	OK2
-DO
-	Pitch me = FIRST (Pitch);
-	double time = Pitch_getTimeOfMaximum (me,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_ENUM (kPitch_unit, U"Unit"), GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (time, U"seconds");
-END2 }
-
-FORM (Pitch_getTimeOfMinimum, U"Pitch: Get time of minimum", nullptr) {
-	praat_dia_timeRange (dia);
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	RADIO (U"Interpolation", 2)
+	OK
+DO
+	NUMBER_ONE (Pitch)
+		double result = Pitch_getTimeOfMaximum (me, fromTime, toTime, unit, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_Pitch_getTimeOfMinimum, U"Pitch: Get time of minimum", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	RADIOVARx (interpolation, U"Interpolation", 2, 0)
 		RADIOBUTTON (U"None")
 		RADIOBUTTON (U"Parabolic")
-	OK2
-DO
-	Pitch me = FIRST (Pitch);
-	double time = Pitch_getTimeOfMinimum (me,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_ENUM (kPitch_unit, U"Unit"), GET_INTEGER (U"Interpolation") - 1);
-	Melder_informationReal (time, U"seconds");
-END2 }
-
-FORM (Pitch_getValueAtTime, U"Pitch: Get value at time", U"Pitch: Get value at time...") {
-	REAL (U"Time (s)", U"0.5")
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	RADIO (U"Interpolation", 2)
+	OK
+DO
+	NUMBER_ONE (Pitch)
+		double result = Pitch_getTimeOfMinimum (me, fromTime, toTime, unit, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_Pitch_getValueAtTime, U"Pitch: Get value at time", U"Pitch: Get value at time...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	RADIOVARx (interpolation, U"Interpolation", 2, 0)
 		RADIOBUTTON (U"Nearest")
 		RADIOBUTTON (U"Linear")
-	OK2
-DO
-	enum kPitch_unit unit = GET_ENUM (kPitch_unit, U"Unit");
-	Pitch me = FIRST (Pitch);
-	double value = Sampled_getValueAtX (me, GET_REAL (U"Time"), Pitch_LEVEL_FREQUENCY, unit, GET_INTEGER (U"Interpolation") - 1);
-	value = Function_convertToNonlogarithmic (me, value, Pitch_LEVEL_FREQUENCY, unit);
-	Melder_informationReal (value, Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
-END2 }
+	OK
+DO
+	NUMBER_ONE (Pitch)
+		double result = Sampled_getValueAtX (me, time, Pitch_LEVEL_FREQUENCY, unit, interpolation);
+		result = Function_convertToNonlogarithmic (me, result, Pitch_LEVEL_FREQUENCY, unit);
+	NUMBER_ONE_END (U" ", Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0))
+}
 	
-FORM (Pitch_getValueInFrame, U"Pitch: Get value in frame", U"Pitch: Get value in frame...") {
-	INTEGER (U"Frame number", U"10")
-	OPTIONMENU_ENUM (U"Unit", kPitch_unit, DEFAULT)
-	OK2
-DO
-	enum kPitch_unit unit = GET_ENUM (kPitch_unit, U"Unit");
-	Pitch me = FIRST (Pitch);
-	double value = Sampled_getValueAtSample (me, GET_INTEGER (U"Frame number"), Pitch_LEVEL_FREQUENCY, unit);
-	value = Function_convertToNonlogarithmic (me, value, Pitch_LEVEL_FREQUENCY, unit);
-	Melder_informationReal (value, Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
-END2 }
-
-DIRECT2 (Pitch_help) {
-	Melder_help (U"Pitch");
-END2 }
-
-DIRECT2 (Pitch_hum) {
-	LOOP {
-		iam (Pitch);
+FORM (REAL_Pitch_getValueInFrame, U"Pitch: Get value in frame", U"Pitch: Get value in frame...") {
+	INTEGERVAR (frameNumber, U"Frame number", U"10")
+	OPTIONMENU_ENUMVAR (unit, U"Unit", kPitch_unit, DEFAULT)
+	OK
+DO
+	NUMBER_ONE (Pitch)
+		double result = Sampled_getValueAtSample (me, frameNumber, Pitch_LEVEL_FREQUENCY, unit);
+		result = Function_convertToNonlogarithmic (me, result, Pitch_LEVEL_FREQUENCY, unit);
+	NUMBER_ONE_END (U" ", Function_getUnitText (me, Pitch_LEVEL_FREQUENCY, unit, 0));
+}
+
+DIRECT (HELP_Pitch_help) {
+	HELP (U"Pitch")
+}
+
+DIRECT (PLAY_Pitch_hum) {
+	PLAY_EACH (Pitch)
 		Pitch_hum (me, 0.0, 0.0);
-	}
-END2 }
+	PLAY_EACH_END
+}
 
-DIRECT2 (Pitch_interpolate) {
-	LOOP {
-		iam (Pitch);
-		autoPitch thee = Pitch_interpolate (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_interpolate) {
+	CONVERT_EACH (Pitch)
+		autoPitch result = Pitch_interpolate (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_killOctaveJumps) {
-	LOOP {
-		iam (Pitch);
-		autoPitch thee = Pitch_killOctaveJumps (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_killOctaveJumps) {
+	CONVERT_EACH (Pitch)
+		autoPitch result = Pitch_killOctaveJumps (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_play) {
-	LOOP {
-		iam (Pitch);
+DIRECT (PLAY_Pitch_play) {
+	PLAY_EACH (Pitch)
 		Pitch_play (me, 0.0, 0.0);
-	}
-END2 }
+	PLAY_EACH_END
+}
 
-FORM (Pitch_smooth, U"Pitch: Smooth", U"Pitch: Smooth...") {
-	REAL (U"Bandwidth (Hz)", U"10.0")
-	OK2
+FORM (NEW_Pitch_smooth, U"Pitch: Smooth", U"Pitch: Smooth...") {
+	REALVAR (bandwidth, U"Bandwidth (Hz)", U"10.0")
+	OK
 DO
-	LOOP {
-		iam (Pitch);
-		autoPitch thee = Pitch_smooth (me, GET_REAL (U"Bandwidth"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Pitch)
+		autoPitch result = Pitch_smooth (me, bandwidth);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Pitch_speckle, U"Pitch: Speckle", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_HERTZ);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_speckle, U"Pitch: Speckle", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"0.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	if (toFrequency <= fromFrequency) Melder_throw (U"Maximum frequency should be greater than minimum frequency.");
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_HERTZ);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_speckleErb, U"Pitch: Speckle erb", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	REAL (U"left Frequency range (ERB)", U"0")
-	REAL (U"right Frequency range (ERB)", U"10.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
+FORM (GRAPHICS_Pitch_speckleErb, U"Pitch: Speckle erb", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (ERB)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (ERB)", U"10.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
 DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_ERB);
-	}
-END2 }
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_ERB);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_speckleLogarithmic, U"Pitch: Speckle logarithmic", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	POSITIVE (STRING_FROM_FREQUENCY_HZ, U"50.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_HERTZ_LOGARITHMIC);
-	}
-END2 }
+FORM (GRAPHICS_Pitch_speckleLogarithmic, U"Pitch: Speckle logarithmic", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"50.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	if (toFrequency <= fromFrequency) Melder_throw (U"Maximum frequency must be greater than minimum frequency.");
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_HERTZ_LOGARITHMIC);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_speckleMel, U"Pitch: Speckle mel", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
-	REAL (U"left Frequency range (mel)", U"0")
-	REAL (U"right Frequency range (mel)", U"500")
-	BOOLEAN (U"Garnish", true)
-	OK2
+FORM (GRAPHICS_Pitch_speckleMel, U"Pitch: Speckle mel", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"500.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
 DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_MEL);
-	}
-END2 }
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_MEL);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_speckleSemitones100, U"Pitch: Speckle semitones (re 100 Hz)", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
+FORM (GRAPHICS_Pitch_speckleSemitones100, U"Pitch: Speckle semitones (re 100 Hz)", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 100 hertz:")
-	REAL (U"left Frequency range (st)", U"-12.0")
-	REAL (U"right Frequency range (st)", U"30.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_SEMITONES_100);
-	}
-END2 }
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-12.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"30.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_SEMITONES_100);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_speckleSemitones200, U"Pitch: Speckle semitones (re 200 Hz)", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
+FORM (GRAPHICS_Pitch_speckleSemitones200, U"Pitch: Speckle semitones (re 200 Hz)", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 200 hertz:")
-	REAL (U"left Frequency range (st)", U"-24.0")
-	REAL (U"right Frequency range (st)", U"18.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_SEMITONES_200);
-	}
-END2 }
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-24.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"18.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_SEMITONES_200);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_speckleSemitones440, U"Pitch: Speckle semitones (re 440 Hz)", U"Pitch: Draw...") {
-	REAL (STRING_FROM_TIME_SECONDS, U"0.0")
-	REAL (STRING_TO_TIME_SECONDS, U"0.0 (= all)")
+FORM (GRAPHICS_Pitch_speckleSemitones440, U"Pitch: Speckle semitones (re 440 Hz)", U"Pitch: Draw...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 440 hertz:")
-	REAL (U"left Frequency range (st)", U"-36.0")
-	REAL (U"right Frequency range (st)", U"6.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	GET_TMIN_TMAX_FMIN_FMAX
-	LOOP {
-		iam (Pitch);
-		autoPraatPicture picture;
-		Pitch_draw (me, GRAPHICS, tmin, tmax, fmin, fmax, GET_INTEGER (U"Garnish"), Pitch_speckle_YES, kPitch_unit_SEMITONES_440);
-	}
-END2 }
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-36.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"6.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Pitch)
+		Pitch_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, Pitch_speckle_YES, kPitch_unit_SEMITONES_440);
+	GRAPHICS_EACH_END
+}
 
-FORM (Pitch_subtractLinearFit, U"Pitch: subtract linear fit", nullptr) {
-	RADIO (U"Unit", 1)
+FORM (NEW_Pitch_subtractLinearFit, U"Pitch: subtract linear fit", nullptr) {
+	RADIOVARx (unit, U"Unit", 1, 0)
 		RADIOBUTTON (U"Hertz")
 		RADIOBUTTON (U"Hertz (logarithmic)")
 		RADIOBUTTON (U"Mel")
 		RADIOBUTTON (U"Semitones")
 		RADIOBUTTON (U"ERB")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Pitch);
-		autoPitch thee = Pitch_subtractLinearFit (me, GET_INTEGER (U"Unit") - 1);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Pitch)
+		autoPitch result = Pitch_subtractLinearFit (me, unit);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_IntervalTier) {
-	LOOP {
-		iam (Pitch);
-		autoIntervalTier thee = IntervalTier_create (my xmin, my xmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_IntervalTier) {
+	CONVERT_EACH (Pitch)
+		autoIntervalTier result = IntervalTier_create (my xmin, my xmax);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_Matrix) {
-	LOOP {
-		iam (Pitch);
-		autoMatrix thee = Pitch_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_Matrix) {
+	CONVERT_EACH (Pitch)
+		autoMatrix result = Pitch_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_PitchTier) {
-	LOOP {
-		iam (Pitch);
-		autoPitchTier thee = Pitch_to_PitchTier (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_PitchTier) {
+	CONVERT_EACH (Pitch)
+		autoPitchTier result = Pitch_to_PitchTier (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_PointProcess) {
-	LOOP {
-		iam (Pitch);
-		autoPointProcess thee = Pitch_to_PointProcess (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_PointProcess) {
+	CONVERT_EACH (Pitch)
+		autoPointProcess result = Pitch_to_PointProcess (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_Sound_pulses) {
-	LOOP {
-		iam (Pitch);
-		autoSound thee = Pitch_to_Sound (me, 0.0, 0.0, false);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_Sound_pulses) {
+	CONVERT_EACH (Pitch)
+		autoSound result = Pitch_to_Sound (me, 0.0, 0.0, false);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_Sound_hum) {
-	LOOP {
-		iam (Pitch);
-		autoSound thee = Pitch_to_Sound (me, 0.0, 0.0, true);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_Sound_hum) {
+	CONVERT_EACH (Pitch)
+		autoSound result = Pitch_to_Sound (me, 0.0, 0.0, true);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Pitch_to_Sound_sine, U"Pitch: To Sound (sine)", nullptr) {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	RADIO (U"Cut voiceless stretches", 2)
+FORM (NEW_Pitch_to_Sound_sine, U"Pitch: To Sound (sine)", nullptr) {
+	POSITIVE4 (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	RADIO4x (cutVoicelessStretches, U"Cut voiceless stretches", 2, 0)
 		OPTION (U"exactly")
 		OPTION (U"at nearest zero crossings")
-	OK2
+	OK
 DO
-	LOOP {
-		iam (Pitch);
-		autoSound thee = Pitch_to_Sound_sine (me, 0.0, 0.0, GET_REAL (U"Sampling frequency"), GET_INTEGER (U"Cut voiceless stretches") - 1);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Pitch)
+		autoSound result = Pitch_to_Sound_sine (me, 0.0, 0.0, samplingFrequency, cutVoicelessStretches);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Pitch_to_TextGrid, U"To TextGrid...", U"Pitch: To TextGrid...") {
-	SENTENCE (U"Tier names", U"Mary John bell")
-	SENTENCE (U"Point tiers", U"bell")
-	OK2
+FORM (NEW_Pitch_to_TextGrid, U"To TextGrid...", U"Pitch: To TextGrid...") {
+	SENTENCEVAR (tierNames, U"Tier names", U"Mary John bell")
+	SENTENCEVAR (pointTiers, U"Point tiers", U"bell")
+	OK
 DO
-	LOOP {
-		iam (Pitch);
-		autoTextGrid thee = TextGrid_create (my xmin, my xmax, GET_STRING (U"Tier names"), GET_STRING (U"Point tiers"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Pitch)
+		autoTextGrid result = TextGrid_create (my xmin, my xmax, tierNames, pointTiers);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Pitch_to_TextTier) {
-	LOOP {
-		iam (Pitch);
-		autoTextTier thee = TextTier_create (my xmin, my xmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Pitch_to_TextTier) {
+	CONVERT_EACH (Pitch)
+		autoTextTier result = TextTier_create (my xmin, my xmax);
+	CONVERT_EACH_END (my name)
+}
 
-/***** PITCH & PITCHTIER *****/
+// MARK: - PITCH & PITCHTIER
 
-FORM (old_PitchTier_Pitch_draw, U"PitchTier & Pitch: Draw", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"500.0")
-	RADIO (U"Line type for non-periodic intervals", 2)
+FORM (GRAPHICS_old_PitchTier_Pitch_draw, U"PitchTier & Pitch: Draw", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REALVAR (toFrequency, U"To frequency (Hz)", U"500.0")
+	RADIOVARx (lineTypeForNonperiodicIntervals, U"Line type for non-periodic intervals", 2, 0)
 		RADIOBUTTON (U"Normal")
 		RADIOBUTTON (U"Dotted")
 		RADIOBUTTON (U"Blank")
-	BOOLEAN (U"Garnish", 1)
-	OK2
-DO
-	PitchTier me = FIRST (PitchTier);
-	Pitch thee = FIRST (Pitch);
-	autoPraatPicture picture;
-	PitchTier_Pitch_draw (me, thee, GRAPHICS,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-		GET_INTEGER (U"Line type for non-periodic intervals") - 1,
-		GET_INTEGER (U"Garnish"), U"lines and speckles");
-END2 }
-
-FORM (PitchTier_Pitch_draw, U"PitchTier & Pitch: Draw", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"From frequency (Hz)", U"0.0")
-	REAL (U"To frequency (Hz)", U"500.0")
-	RADIO (U"Line type for non-periodic intervals", 2)
+	BOOLEANVAR (garnish, U"Garnish", 1)
+	OK
+DO
+	GRAPHICS_TWO (PitchTier, Pitch)
+		PitchTier_Pitch_draw (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			lineTypeForNonperiodicIntervals, garnish, U"lines and speckles");
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_PitchTier_Pitch_draw, U"PitchTier & Pitch: Draw", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"From frequency (Hz)", U"0.0")
+	REALVAR (toFrequency, U"To frequency (Hz)", U"500.0")
+	RADIOVARx (lineTypeForNonperiodicIntervals, U"Line type for non-periodic intervals", 2, 0)
 		RADIOBUTTON (U"Normal")
 		RADIOBUTTON (U"Dotted")
 		RADIOBUTTON (U"Blank")
-	BOOLEAN (U"Garnish", true)
+	BOOLEANVAR (garnish, U"Garnish", 1)
 	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 1)
+	OPTIONMENUSTRVAR (drawingMethod, U"Drawing method", 1)
 		OPTION (U"lines")
 		OPTION (U"speckles")
 		OPTION (U"lines and speckles")
-	OK2
-DO_ALTERNATIVE (old_PitchTier_Pitch_draw)
-	PitchTier me = FIRST (PitchTier);
-	Pitch thee = FIRST (Pitch);
-	autoPraatPicture picture;
-	PitchTier_Pitch_draw (me, thee, GRAPHICS,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-		GET_INTEGER (U"Line type for non-periodic intervals") - 1,
-		GET_INTEGER (U"Garnish"), GET_STRING (U"Drawing method"));
-END2 }
-
-DIRECT2 (Pitch_PitchTier_to_Pitch) {
-	Pitch pitch = FIRST (Pitch);
-	PitchTier tier = FIRST (PitchTier);
-	autoPitch thee = Pitch_PitchTier_to_Pitch (pitch, tier);
-	praat_new (thee.move(), pitch -> name, U"_stylized");
-END2 }
-
-/***** PITCH & POINTPROCESS *****/
-
-DIRECT2 (Pitch_PointProcess_to_PitchTier) {
-	Pitch pitch = FIRST (Pitch);
-	PointProcess point = FIRST (PointProcess);
-	autoPitchTier thee = Pitch_PointProcess_to_PitchTier (pitch, point);
-	praat_new (thee.move(), pitch -> name);
-END2 }
-
-/***** PITCH & SOUND *****/
-
-DIRECT2 (Sound_Pitch_to_Manipulation) {
-	Pitch pitch = FIRST (Pitch);
-	Sound sound = FIRST (Sound);
-	autoManipulation thee = Sound_Pitch_to_Manipulation (sound, pitch);
-	praat_new (thee.move(), pitch -> name);
-END2 }
-
-DIRECT2 (Sound_Pitch_to_PointProcess_cc) {
-	Sound sound = FIRST (Sound);
-	Pitch pitch = FIRST (Pitch);
-	autoPointProcess thee = Sound_Pitch_to_PointProcess_cc (sound, pitch);
-	praat_new (thee.move(), sound -> name, U"_", pitch -> name);
-END2 }
-
-FORM (Sound_Pitch_to_PointProcess_peaks, U"Sound & Pitch: To PointProcess (peaks)", 0) {
-	BOOLEAN (U"Include maxima", 1)
-	BOOLEAN (U"Include minima", 0)
-	OK2
-DO
-	Sound sound = FIRST (Sound);
-	Pitch pitch = FIRST (Pitch);
-	autoPointProcess thee = Sound_Pitch_to_PointProcess_peaks (sound, pitch, GET_INTEGER (U"Include maxima"), GET_INTEGER (U"Include minima"));
-	praat_new (thee.move(), sound -> name, U"_", pitch -> name);
-END2 }
-
-/***** PITCHTIER *****/
-
-FORM (PitchTier_addPoint, U"PitchTier: Add point", U"PitchTier: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	REAL (U"Pitch (Hz)", U"200.0")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		RealTier_addPoint (me, GET_REAL (U"Time"), GET_REAL (U"Pitch"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (PitchTier_create, U"Create empty PitchTier", nullptr) {
-	WORD (U"Name", U"empty")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	OK2
-DO
-	double startTime = GET_REAL (U"Start time"), endTime = GET_REAL (U"End time");
-	if (endTime <= startTime) Melder_throw (U"End time must be greater than start time.");
-	autoPitchTier me = PitchTier_create (startTime, endTime);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-DIRECT2 (PitchTier_downto_PointProcess) {
-	LOOP {
-		iam (PitchTier);
-		autoPointProcess thee = AnyTier_downto_PointProcess (me->asAnyTier());
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (PitchTier_downto_TableOfReal, U"PitchTier: Down to TableOfReal", nullptr) {
-	RADIO (U"Unit", 1)
-		RADIOBUTTON (U"Hertz")
-		RADIOBUTTON (U"Semitones")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		autoTableOfReal thee = PitchTier_downto_TableOfReal (me, GET_INTEGER (U"Unit") - 1);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (old_PitchTier_draw, U"PitchTier: Draw", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	double minimumFrequency = GET_REAL (STRING_FROM_FREQUENCY);
-	double maximumFrequency = GET_REAL (STRING_TO_FREQUENCY);
-	if (maximumFrequency <= minimumFrequency) Melder_throw (U"Maximum frequency must be greater than minimum frequency.");
-	LOOP {
-		iam (PitchTier);
-		autoPraatPicture picture;
-		PitchTier_draw (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), minimumFrequency, maximumFrequency,
-			GET_INTEGER (U"Garnish"), U"lines and speckles");
-	}
-END2 }
-
-FORM (PitchTier_draw, U"PitchTier: Draw", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Garnish", true)
-	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 1)
-		OPTION (U"lines")
-		OPTION (U"speckles")
-		OPTION (U"lines and speckles")
-	OK2
-DO_ALTERNATIVE (old_PitchTier_draw)
-	double minimumFrequency = GET_REAL (STRING_FROM_FREQUENCY);
-	double maximumFrequency = GET_REAL (STRING_TO_FREQUENCY);
-	if (maximumFrequency <= minimumFrequency) Melder_throw (U"Maximum frequency must be greater than minimum frequency.");
-	LOOP {
-		iam (PitchTier);
-		autoPraatPicture picture;
-		PitchTier_draw (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), minimumFrequency, maximumFrequency,
-			GET_INTEGER (U"Garnish"), GET_STRING (U"Drawing method"));
-	}
-END2 }
-
-DIRECT2 (PitchTier_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a PitchTier from batch.");
-	Sound sound = FIRST (Sound);
-	LOOP if (CLASS == classPitchTier) {
-		iam (PitchTier);
-		autoPitchTierEditor editor = PitchTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-FORM (PitchTier_formula, U"PitchTier: Formula", U"PitchTier: Formula...") {
-	LABEL (U"", U"# ncol = the number of points")
-	LABEL (U"", U"for col from 1 to ncol")
-	LABEL (U"", U"   # x = the time of the colth point, in seconds")
-	LABEL (U"", U"   # self = the value of the colth point, in hertz")
-	LABEL (U"", U"   self = `formula'")
-	LABEL (U"", U"endfor")
-	TEXTFIELD (U"formula", U"self * 2 ; one octave up")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		try {
-			RealTier_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the PitchTier may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (PitchTier_getMean_curve, U"PitchTier: Get mean (curve)", U"PitchTier: Get mean (curve)...") {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	Melder_informationReal (RealTier_getMean_curve (FIRST_ANY (PitchTier), GET_REAL (U"left Time range"), GET_REAL (U"right Time range")), U"Hz");
-END2 }
-	
-FORM (PitchTier_getMean_points, U"PitchTier: Get mean (points)", U"PitchTier: Get mean (points)...") {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	Melder_informationReal (RealTier_getMean_points (FIRST_ANY (PitchTier), GET_REAL (U"left Time range"), GET_REAL (U"right Time range")), U"Hz");
-END2 }
-	
-FORM (PitchTier_getStandardDeviation_curve, U"PitchTier: Get standard deviation (curve)", U"PitchTier: Get standard deviation (curve)...") {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	Melder_informationReal (RealTier_getStandardDeviation_curve (FIRST_ANY (PitchTier), GET_REAL (U"left Time range"), GET_REAL (U"right Time range")), U"Hz");
-END2 }
-	
-FORM (PitchTier_getStandardDeviation_points, U"PitchTier: Get standard deviation (points)", U"PitchTier: Get standard deviation (points)...") {
-	praat_dia_timeRange (dia);
-	OK2
-DO
-	Melder_informationReal (RealTier_getStandardDeviation_points (FIRST_ANY (PitchTier), GET_REAL (U"left Time range"), GET_REAL (U"right Time range")), U"Hz");
-END2 }
-	
-FORM (PitchTier_getValueAtTime, U"PitchTier: Get value at time", U"PitchTier: Get value at time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	Melder_informationReal (RealTier_getValueAtTime (FIRST_ANY (PitchTier), GET_REAL (U"Time")), U"Hz");
-END2 }
-	
-FORM (PitchTier_getValueAtIndex, U"PitchTier: Get value at index", U"PitchTier: Get value at index...") {
-	INTEGER (U"Point number", U"10")
-	OK2
-DO
-	Melder_informationReal (RealTier_getValueAtIndex (FIRST_ANY (PitchTier), GET_INTEGER (U"Point number")), U"Hz");
-END2 }
-
-DIRECT2 (PitchTier_help) {
-	Melder_help (U"PitchTier");
-END2 }
-
-DIRECT2 (PitchTier_hum) {
-	LOOP {
-		iam (PitchTier);
-		PitchTier_hum (me);
-	}
-END2 }
-
-FORM (PitchTier_interpolateQuadratically, U"PitchTier: Interpolate quadratically", nullptr) {
-	NATURAL (U"Number of points per parabola", U"4")
-	RADIO (U"Unit", 2)
-		RADIOBUTTON (U"Hz")
-		RADIOBUTTON (U"Semitones")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		RealTier_interpolateQuadratically (me, GET_INTEGER (U"Number of points per parabola"), GET_INTEGER (U"Unit") - 1);
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (PitchTier_play) {
-	LOOP {
-		iam (PitchTier);
-		PitchTier_play (me);
-	}
-END2 }
-
-DIRECT2 (PitchTier_playSine) {
-	LOOP {
-		iam (PitchTier);
-		PitchTier_playPart_sine (me, 0.0, 0.0);
-	}
-END2 }
-
-FORM (PitchTier_shiftFrequencies, U"PitchTier: Shift frequencies", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1000.0")
-	REAL (U"Frequency shift", U"-20.0")
-	OPTIONMENU (U"Unit", 1)
-		OPTION (U"Hertz")
-		OPTION (U"mel")
-		OPTION (U"logHertz")
-		OPTION (U"semitones")
-		OPTION (U"ERB")
-	OK2
-DO
-	int unit = GET_INTEGER (U"Unit");
-	unit =
-		unit == 1 ? kPitch_unit_HERTZ :
-		unit == 2 ? kPitch_unit_MEL :
-		unit == 3 ? kPitch_unit_LOG_HERTZ :
-		unit == 4 ? kPitch_unit_SEMITONES_1 :
-		kPitch_unit_ERB;
-	LOOP {
-		iam (PitchTier);
-		try {
-			PitchTier_shiftFrequencies (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Frequency shift"), unit);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the PitchTier may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (PitchTier_multiplyFrequencies, U"PitchTier: Multiply frequencies", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1000.0")
-	POSITIVE (U"Factor", U"1.2")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		PitchTier_multiplyFrequencies (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Factor"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (PitchTier_stylize, U"PitchTier: Stylize", U"PitchTier: Stylize...") {
-	REAL (U"Frequency resolution", U"4.0")
-	RADIO (U"Unit", 2)
-		RADIOBUTTON (U"Hz")
-		RADIOBUTTON (U"Semitones")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		PitchTier_stylize (me, GET_REAL (U"Frequency resolution"), GET_INTEGER (U"Unit") - 1);
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (PitchTier_to_PointProcess) {
-	LOOP {
-		iam (PitchTier);
-		autoPointProcess thee = PitchTier_to_PointProcess (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (PitchTier_to_Sound_phonation, U"PitchTier: To Sound (phonation)", nullptr) {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100")
-	POSITIVE (U"Adaptation factor", U"1.0")
-	POSITIVE (U"Maximum period (s)", U"0.05")
-	POSITIVE (U"Open phase", U"0.7")
-	REAL (U"Collision phase", U"0.03")
-	POSITIVE (U"Power 1", U"3.0")
-	POSITIVE (U"Power 2", U"4.0")
-	BOOLEAN (U"Hum", false)
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		autoSound thee = PitchTier_to_Sound_phonation (me, GET_REAL (U"Sampling frequency"),
-			GET_REAL (U"Adaptation factor"), GET_REAL (U"Maximum period"),
-			GET_REAL (U"Open phase"), GET_REAL (U"Collision phase"), GET_REAL (U"Power 1"), GET_REAL (U"Power 2"), GET_INTEGER (U"Hum"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (PitchTier_to_Sound_pulseTrain, U"PitchTier: To Sound (pulse train)", nullptr) {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100")
-	POSITIVE (U"Adaptation factor", U"1.0")
-	POSITIVE (U"Adaptation time", U"0.05")
-	NATURAL (U"Interpolation depth (samples)", U"2000")
-	BOOLEAN (U"Hum", false)
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		autoSound thee = PitchTier_to_Sound_pulseTrain (me, GET_REAL (U"Sampling frequency"),
-			GET_REAL (U"Adaptation factor"), GET_REAL (U"Adaptation time"),
-			GET_INTEGER (U"Interpolation depth"), GET_INTEGER (U"Hum"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (PitchTier_to_Sound_sine, U"PitchTier: To Sound (sine)", nullptr) {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	OK2
-DO
-	LOOP {
-		iam (PitchTier);
-		autoSound thee = PitchTier_to_Sound_sine (me, 0.0, 0.0, GET_REAL (U"Sampling frequency"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (info_PitchTier_Sound_edit) {
-	Melder_information (U"To include a copy of a Sound in your PitchTier editor:\n"
-		"   select a PitchTier and a Sound, and click \"View & Edit\".");
-END2 }
-
-FORM_WRITE (PitchTier_writeToPitchTierSpreadsheetFile, U"Save PitchTier as spreadsheet", nullptr, U"PitchTier")
-	LOOP {
-		iam (PitchTier);
-		PitchTier_writeToPitchTierSpreadsheetFile (me, file);
-	}
-END
-
-FORM_WRITE (PitchTier_writeToHeaderlessSpreadsheetFile, U"Save PitchTier as spreadsheet", nullptr, U"txt")
-	LOOP {
-		iam (PitchTier);
-		PitchTier_writeToHeaderlessSpreadsheetFile (me, file);
-	}
-END
-
-/***** PITCHTIER & POINTPROCESS *****/
-
-DIRECT2 (PitchTier_PointProcess_to_PitchTier) {
-	PitchTier pitch = FIRST (PitchTier);
-	PointProcess point = FIRST (PointProcess);
-	autoPitchTier thee = PitchTier_PointProcess_to_PitchTier (pitch, point);
-	praat_new (thee.move(), pitch -> name);
-END2 }
-
-/***** POINTPROCESS *****/
-
-FORM (PointProcess_addPoint, U"PointProcess: Add point", U"PointProcess: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		PointProcess_addPoint (me, GET_REAL (U"Time"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (PointProcess_createEmpty, U"Create an empty PointProcess", U"Create empty PointProcess...") {
-	WORD (U"Name", U"empty")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	OK2
-DO
-	double tmin = GET_REAL (U"Start time"), tmax = GET_REAL (U"End time");
-	if (tmax < tmin) Melder_throw (U"End time (", tmax, U") should not be less than start time (", tmin, U").");
-	autoPointProcess me = PointProcess_create (tmin, tmax, 0);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (PointProcess_createPoissonProcess, U"Create Poisson process", U"Create Poisson process...") {
-	WORD (U"Name", U"poisson")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	POSITIVE (U"Density (/s)", U"100.0")
-	OK2
-DO
-	double tmin = GET_REAL (U"Start time"), tmax = GET_REAL (U"End time");
-	if (tmax < tmin)
-		Melder_throw (U"End time (", tmax, U") should not be less than start time (", tmin, U").");
-	autoPointProcess me = PointProcess_createPoissonProcess (tmin, tmax, GET_REAL (U"Density"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-DIRECT2 (PointProcess_difference) {
-	PointProcess point1 = nullptr, point2 = nullptr;
-	LOOP (point1 ? point2 : point1) = (PointProcess) OBJECT;
-	autoPointProcess thee = PointProcesses_difference (point1, point2);
-	praat_new (thee.move(), U"difference");
-END2 }
-
-FORM (PointProcess_draw, U"PointProcess: Draw", nullptr) {
-	praat_dia_timeRange (dia);
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		autoPraatPicture picture;
-		PointProcess_draw (me, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-DIRECT2 (PointProcess_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a PointProcess from batch.");
-	Sound sound = FIRST (Sound);
-	LOOP if (CLASS == classPointProcess) {
-		iam (PointProcess);
-		autoPointEditor editor = PointEditor_create (ID_AND_FULL_NAME, me, sound);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-FORM (PointProcess_fill, U"PointProcess: Fill", nullptr) {
-	praat_dia_timeRange (dia);
-	POSITIVE (U"Period (s)", U"0.01")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		try {
-			PointProcess_fill (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_REAL (U"Period"));
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the PointProcess may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (PointProcess_getInterval, U"PointProcess: Get interval", U"PointProcess: Get interval...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	Melder_informationReal (PointProcess_getInterval (FIRST_ANY (PointProcess), GET_REAL (U"Time")), U"seconds");
-END2 }
-
-static void dia_PointProcess_getRangeProperty (UiForm dia) {
-	praat_dia_timeRange (dia);
-	REAL (U"Shortest period (s)", U"0.0001")
-	REAL (U"Longest period (s)", U"0.02")
-	POSITIVE (U"Maximum period factor", U"1.3")
+	OK
+DO_ALTERNATIVE (GRAPHICS_old_PitchTier_Pitch_draw)
+	GRAPHICS_TWO (PitchTier, Pitch)
+		PitchTier_Pitch_draw (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			lineTypeForNonperiodicIntervals, garnish, drawingMethod);
+	GRAPHICS_TWO_END
 }
 
-FORM (PointProcess_getJitter_local, U"PointProcess: Get jitter (local)", U"PointProcess: Get jitter (local)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getJitter_local (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), nullptr);
-END2 }
-
-FORM (PointProcess_getJitter_local_absolute, U"PointProcess: Get jitter (local, absolute)", U"PointProcess: Get jitter (local, absolute)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getJitter_local_absolute (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), U"seconds");
-END2 }
-
-FORM (PointProcess_getJitter_rap, U"PointProcess: Get jitter (rap)", U"PointProcess: Get jitter (rap)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getJitter_rap (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), nullptr);
-END2 }
-
-FORM (PointProcess_getJitter_ppq5, U"PointProcess: Get jitter (ppq5)", U"PointProcess: Get jitter (ppq5)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getJitter_ppq5 (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), nullptr);
-END2 }
-
-FORM (PointProcess_getJitter_ddp, U"PointProcess: Get jitter (ddp)", U"PointProcess: Get jitter (ddp)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getJitter_ddp (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), nullptr);
-END2 }
-
-FORM (PointProcess_getMeanPeriod, U"PointProcess: Get mean period", U"PointProcess: Get mean period...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getMeanPeriod (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), U"seconds");
-END2 }
-
-FORM (PointProcess_getStdevPeriod, U"PointProcess: Get stdev period", U"PointProcess: Get stdev period...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_informationReal (PointProcess_getStdevPeriod (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")), U"seconds");
-END2 }
-
-FORM (PointProcess_getLowIndex, U"PointProcess: Get low index", U"PointProcess: Get low index...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	Melder_information (PointProcess_getLowIndex (FIRST_ANY (PointProcess), GET_REAL (U"Time")));
-END2 }
-
-FORM (PointProcess_getHighIndex, U"PointProcess: Get high index", U"PointProcess: Get high index...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	Melder_information (PointProcess_getHighIndex (FIRST_ANY (PointProcess), GET_REAL (U"Time")));
-END2 }
-
-FORM (PointProcess_getNearestIndex, U"PointProcess: Get nearest index", U"PointProcess: Get nearest index...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	Melder_information (PointProcess_getNearestIndex (FIRST_ANY (PointProcess), GET_REAL (U"Time")));
-END2 }
-
-DIRECT2 (PointProcess_getNumberOfPoints) {
-	PointProcess me = FIRST_ANY (PointProcess);
-	Melder_information (my nt);
-END2 }
-
-FORM (PointProcess_getNumberOfPeriods, U"PointProcess: Get number of periods", U"PointProcess: Get number of periods...") {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	Melder_information (PointProcess_getNumberOfPeriods (FIRST_ANY (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor")));
-END2 }
-
-FORM (PointProcess_getTimeFromIndex, U"Get time", 0 /*"PointProcess: Get time from index..."*/) {
-	NATURAL (U"Point number", U"10")
-	OK2
-DO
-	PointProcess me = FIRST_ANY (PointProcess);
-	long i = GET_INTEGER (U"Point number");
-	if (i > my nt) Melder_information (U"--undefined--");
-	else Melder_informationReal (my t [i], U"seconds");
-END2 }
-
-DIRECT2 (PointProcess_help) {
-	Melder_help (U"PointProcess");
-END2 }
-
-DIRECT2 (PointProcess_hum) {
-	LOOP {
-		iam (PointProcess);
-		PointProcess_hum (me, my xmin, my xmax);
-	}
-END2 }
-
-DIRECT2 (PointProcess_intersection) {
-	PointProcess point1 = nullptr, point2 = nullptr;
-	LOOP (point1 ? point2 : point1) = (PointProcess) OBJECT;
-	autoPointProcess thee = PointProcesses_intersection (point1, point2);
-	praat_new (thee.move(), U"intersection");
-END2 }
-
-DIRECT2 (PointProcess_play) {
-	LOOP {
-		iam (PointProcess);
-		PointProcess_play (me);
-	}
-END2 }
-
-FORM (PointProcess_removePoint, U"PointProcess: Remove point", U"PointProcess: Remove point...") {
-	NATURAL (U"Index", U"1")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		PointProcess_removePoint (me, GET_INTEGER (U"Index"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (NEW1_Pitch_PitchTier_to_Pitch) {
+	CONVERT_TWO (Pitch, PitchTier)
+		autoPitch result = Pitch_PitchTier_to_Pitch (me, you);
+	CONVERT_TWO_END (my name, U"_stylized");
+}
 
-FORM (PointProcess_removePointNear, U"PointProcess: Remove point near", U"PointProcess: Remove point near...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		PointProcess_removePointNear (me, GET_REAL (U"Time"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - PITCH & POINTPROCESS
 
-FORM (PointProcess_removePoints, U"PointProcess: Remove points", U"PointProcess: Remove points...") {
-	NATURAL (U"From index", U"1")
-	NATURAL (U"To index", U"10")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		PointProcess_removePoints (me, GET_INTEGER (U"From index"), GET_INTEGER (U"To index"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (NEW1_Pitch_PointProcess_to_PitchTier) {
+	CONVERT_TWO (Pitch, PointProcess)
+		autoPitchTier result = Pitch_PointProcess_to_PitchTier (me, you);
+	CONVERT_TWO_END (my name);
+}
 
-FORM (PointProcess_removePointsBetween, U"PointProcess: Remove points between", U"PointProcess: Remove points between...") {
-	REAL (U"left Time range (s)", U"0.3")
-	REAL (U"right Time range (s)", U"0.7")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		PointProcess_removePointsBetween (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - PITCH & SOUND
 
-DIRECT2 (PointProcess_to_IntervalTier) {
-	LOOP {
-		iam (PointProcess);
-		autoIntervalTier thee = IntervalTier_create (my xmin, my xmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW1_Sound_Pitch_to_Manipulation) {
+	CONVERT_TWO (Sound, Pitch)
+		autoManipulation result = Sound_Pitch_to_Manipulation (me, you);
+	CONVERT_TWO_END (your name);
+}
 
-DIRECT2 (PointProcess_to_Matrix) {
-	LOOP {
-		iam (PointProcess);
-		autoMatrix thee = PointProcess_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW1_Sound_Pitch_to_PointProcess_cc) {
+	CONVERT_TWO (Sound, Pitch)
+		autoPointProcess result = Sound_Pitch_to_PointProcess_cc (me, you);
+	CONVERT_TWO_END (my name, U"_", your name);
+}
 
-FORM (PointProcess_to_PitchTier, U"PointProcess: To PitchTier", U"PointProcess: To PitchTier...") {
-	POSITIVE (U"Maximum interval (s)", U"0.02")
-	OK2
+FORM (NEW1_Sound_Pitch_to_PointProcess_peaks, U"Sound & Pitch: To PointProcess (peaks)", 0) {
+	BOOLEANVAR (includeMaxima, U"Include maxima", 1)
+	BOOLEANVAR (includeMinima, U"Include minima", 0)
+	OK
 DO
-	LOOP {
-		iam (PointProcess);
-		autoPitchTier thee = PointProcess_to_PitchTier (me, GET_REAL (U"Maximum interval"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_TWO (Sound, Pitch)
+		autoPointProcess result = Sound_Pitch_to_PointProcess_peaks (me, you, includeMaxima, includeMinima);
+	CONVERT_TWO_END (my name, U"_", your name)
+}
 
-FORM (PointProcess_to_TextGrid, U"PointProcess: To TextGrid...", U"PointProcess: To TextGrid...") {
-	SENTENCE (U"Tier names", U"Mary John bell")
-	SENTENCE (U"Point tiers", U"bell")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		autoTextGrid thee = TextGrid_create (my xmin, my xmax, GET_STRING (U"Tier names"), GET_STRING (U"Point tiers"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: - POLYGON
 
-FORM (PointProcess_to_TextGrid_vuv, U"PointProcess: To TextGrid (vuv)...", U"PointProcess: To TextGrid (vuv)...") {
-	POSITIVE (U"Maximum period (s)", U"0.02")
-	REAL (U"Mean period (s)", U"0.01")
-	OK2
+FORM (GRAPHICS_Polygon_draw, U"Polygon: Draw", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0 (= all)")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0 (= all)")
+	OK
 DO
-	LOOP {
-		iam (PointProcess);
-		autoTextGrid thee = PointProcess_to_TextGrid_vuv (me, GET_REAL (U"Maximum period"), GET_REAL (U"Mean period"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	GRAPHICS_EACH (Polygon)
+		Polygon_draw (me, GRAPHICS, xmin, xmax, ymin, ymax);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (PointProcess_to_TextTier) {
-	LOOP {
-		iam (PointProcess);
-		autoTextTier thee = TextTier_create (my xmin, my xmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (PointProcess_to_Sound_phonation, U"PointProcess: To Sound (phonation)", U"PointProcess: To Sound (phonation)...") {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100")
-	POSITIVE (U"Adaptation factor", U"1.0")
-	POSITIVE (U"Maximum period (s)", U"0.05")
-	POSITIVE (U"Open phase", U"0.7")
-	REAL (U"Collision phase", U"0.03")
-	POSITIVE (U"Power 1", U"3.0")
-	POSITIVE (U"Power 2", U"4.0")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		autoSound thee = PointProcess_to_Sound_phonation (me, GET_REAL (U"Sampling frequency"),
-			GET_REAL (U"Adaptation factor"), GET_REAL (U"Maximum period"),
-			GET_REAL (U"Open phase"), GET_REAL (U"Collision phase"), GET_REAL (U"Power 1"), GET_REAL (U"Power 2"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Polygon_drawCircles, U"Polygon: Draw circles", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0 (= all)")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0 (= all)")
+	POSITIVEVAR (diameter, U"Diameter (mm)", U"3.0")
+	OK
+DO
+	GRAPHICS_EACH (Polygon)
+		Polygon_drawCircles (me, GRAPHICS, xmin, xmax, ymin, ymax, diameter);
+	GRAPHICS_EACH_END
+}
 
-FORM (PointProcess_to_Sound_pulseTrain, U"PointProcess: To Sound (pulse train)", U"PointProcess: To Sound (pulse train)...") {
-	POSITIVE (U"Sampling frequency (Hz)", U"44100")
-	POSITIVE (U"Adaptation factor", U"1.0")
-	POSITIVE (U"Adaptation time (s)", U"0.05")
-	NATURAL (U"Interpolation depth (samples)", U"2000")
-	OK2
+FORM (GRAPHICS_Polygon_drawClosed, U"Polygon: Draw", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0 (= all)")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0 (= all)")
+	OK
 DO
-	LOOP {
-		iam (PointProcess);
-		autoSound thee = PointProcess_to_Sound_pulseTrain (me, GET_REAL (U"Sampling frequency"),
-			GET_REAL (U"Adaptation factor"), GET_REAL (U"Adaptation time"),
-			GET_INTEGER (U"Interpolation depth"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (PointProcess_to_Sound_hum) {
-	LOOP {
-		iam (PointProcess);
-		autoSound thee = PointProcess_to_Sound_hum (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	GRAPHICS_EACH (Polygon)
+		Polygon_drawClosed (me, GRAPHICS, xmin, xmax, ymin, ymax);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (PointProcess_union) {
-	PointProcess point1 = nullptr, point2 = nullptr;
-	LOOP (point1 ? point2 : point1) = (PointProcess) OBJECT;
-	autoPointProcess thee = PointProcesses_union (point1, point2);
-	praat_new (thee.move(), U"union");
-END2 }
+FORM (GRAPHICS_Polygons_drawConnection, U"Polygons: Draw connection", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0 (= all)")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0 (= all)")
+	BOOLEANVAR (arrow, U"Arrow", false)
+	POSITIVEVAR (relativeLength, U"Relative length", U"0.9")
+	OK
+DO
+	GRAPHICS_COUPLE (Polygon)
+		Polygons_drawConnection (me, you, GRAPHICS, xmin, xmax, ymin, ymax, arrow, relativeLength);
+	GRAPHICS_COUPLE_END
+}
 
-FORM (PointProcess_upto_IntensityTier, U"PointProcess: Up to IntensityTier", U"PointProcess: Up to IntensityTier...") {
-	POSITIVE (U"Intensity (dB)", U"70.0")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		autoIntensityTier thee = PointProcess_upto_IntensityTier (me, GET_REAL (U"Intensity"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (HELP_Polygon_help) {
+	HELP (U"Polygon")
+}
 
-FORM (PointProcess_upto_PitchTier, U"PointProcess: Up to PitchTier", U"PointProcess: Up to PitchTier...") {
-	POSITIVE (U"Frequency (Hz)", U"190.0")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		autoPitchTier thee = PointProcess_upto_PitchTier (me, GET_REAL (U"Frequency"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Polygon_paint, U"Polygon: Paint", nullptr) {
+	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0 (= all)")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0 (= all)")
+	OK
+DO
+	GRAPHICS_EACH (Polygon)
+		Polygon_paint (me, GRAPHICS, GET_COLOUR (U"Colour"), xmin, xmax, ymin, ymax);
+	GRAPHICS_EACH_END
+}
 
-FORM (PointProcess_upto_TextTier, U"PointProcess: Up to TextTier", U"PointProcess: Up to TextTier...") {
-	SENTENCE (U"Text", U"")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		autoTextTier thee = PointProcess_upto_TextTier (me, GET_STRING (U"Text"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (GRAPHICS_Polygon_paintCircles, U"Polygon: Paint circles", nullptr) {
+	REALVAR (xmin, U"Xmin", U"0.0")
+	REALVAR (xmax, U"Xmax", U"0.0 (= all)")
+	REALVAR (ymin, U"Ymin", U"0.0")
+	REALVAR (ymax, U"Ymax", U"0.0 (= all)")
+	POSITIVEVAR (diameter, U"Diameter (mm)", U"3.0")
+	OK
+DO
+	GRAPHICS_EACH (Polygon)
+		Polygon_paintCircles (me, GRAPHICS, xmin, xmax, ymin, ymax, diameter);
+	GRAPHICS_EACH_END
+}
 
-FORM (PointProcess_voice, U"PointProcess: Fill unvoiced parts", nullptr) {
-	POSITIVE (U"Period (s)", U"0.01")
-	POSITIVE (U"Maximum voiced period (s)", U"0.02000000001")
-	OK2
-DO
-	LOOP {
-		iam (PointProcess);
-		try {
-			PointProcess_voice (me, GET_REAL (U"Period"), GET_REAL (U"Maximum voiced period"));
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the PointProcess may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-DIRECT2 (info_PointProcess_Sound_edit) {
-	Melder_information (U"To include a copy of a Sound in your PointProcess editor:\n"
-		"   select a PointProcess and a Sound, and click \"View & Edit\".");
-END2 }
-
-/***** POINTPROCESS & SOUND *****/
-
-DIRECT2 (Point_Sound_transplantDomain) {
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	point -> xmin = sound -> xmin;
-	point -> xmax = sound -> xmax;
-	praat_dataChanged (point);
-END2 }
-
-FORM (Point_Sound_getShimmer_local, U"PointProcess & Sound: Get shimmer (local)", U"PointProcess & Sound: Get shimmer (local)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	double shimmer = PointProcess_Sound_getShimmer_local (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"));
-	Melder_informationReal (shimmer, nullptr);
-END2 }
-
-FORM (Point_Sound_getShimmer_local_dB, U"PointProcess & Sound: Get shimmer (local, dB)", U"PointProcess & Sound: Get shimmer (local, dB)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	double shimmer = PointProcess_Sound_getShimmer_local_dB (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"));
-	Melder_informationReal (shimmer, nullptr);
-END2 }
-
-FORM (Point_Sound_getShimmer_apq3, U"PointProcess & Sound: Get shimmer (apq3)", U"PointProcess & Sound: Get shimmer (apq3)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	double shimmer = PointProcess_Sound_getShimmer_apq3 (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"));
-	Melder_informationReal (shimmer, nullptr);
-END2 }
-
-FORM (Point_Sound_getShimmer_apq5, U"PointProcess & Sound: Get shimmer (apq)", U"PointProcess & Sound: Get shimmer (apq5)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	double shimmer = PointProcess_Sound_getShimmer_apq5 (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"));
-	Melder_informationReal (shimmer, nullptr);
-END2 }
-
-FORM (Point_Sound_getShimmer_apq11, U"PointProcess & Sound: Get shimmer (apq11)", U"PointProcess & Sound: Get shimmer (apq11)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	double shimmer = PointProcess_Sound_getShimmer_apq11 (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"));
-	Melder_informationReal (shimmer, nullptr);
-END2 }
-
-FORM (Point_Sound_getShimmer_dda, U"PointProcess & Sound: Get shimmer (dda)", U"PointProcess & Sound: Get shimmer (dda)...") {
-	dia_PointProcess_getRangeProperty (dia);
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	double shimmer = PointProcess_Sound_getShimmer_dda (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"));
-	Melder_informationReal (shimmer, nullptr);
-END2 }
-
-FORM (PointProcess_Sound_to_AmplitudeTier_period, U"PointProcess & Sound: To AmplitudeTier (period)", nullptr) {
-	dia_PointProcess_getRangeProperty (dia);
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	autoAmplitudeTier thee = PointProcess_Sound_to_AmplitudeTier_period (point, sound,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor"));
-	praat_new (thee.move(), sound -> name, U"_", point -> name);
-END2 }
-
-DIRECT2 (PointProcess_Sound_to_AmplitudeTier_point) {
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	autoAmplitudeTier thee = PointProcess_Sound_to_AmplitudeTier_point (point, sound);
-	praat_new (thee.move(), sound -> name, U"_", point -> name);
-END2 }
-
-FORM (PointProcess_Sound_to_Ltas, U"PointProcess & Sound: To Ltas", nullptr) {
-	POSITIVE (U"Maximum frequency (Hz)", U"5000")
-	POSITIVE (U"Band width (Hz)", U"100")
-	REAL (U"Shortest period (s)", U"0.0001")
-	REAL (U"Longest period (s)", U"0.02")
-	POSITIVE (U"Maximum period factor", U"1.3")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	autoLtas thee = PointProcess_Sound_to_Ltas (point, sound,
-		GET_REAL (U"Maximum frequency"), GET_REAL (U"Band width"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor"));
-	praat_new (thee.move(), sound -> name);
-END2 }
-
-FORM (PointProcess_Sound_to_Ltas_harmonics, U"PointProcess & Sound: To Ltas (harmonics", nullptr) {
-	NATURAL (U"Maximum harmonic", U"20")
-	REAL (U"Shortest period (s)", U"0.0001")
-	REAL (U"Longest period (s)", U"0.02")
-	POSITIVE (U"Maximum period factor", U"1.3")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	autoLtas thee = PointProcess_Sound_to_Ltas_harmonics (point, sound,
-		GET_INTEGER (U"Maximum harmonic"),
-		GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor"));
-	praat_new (thee.move(), sound -> name);
-END2 }
-
-FORM (Sound_PointProcess_to_SoundEnsemble_correlate, U"Sound & PointProcess: To SoundEnsemble (correlate)", nullptr) {
-	REAL (U"From time (s)", U"-0.1")
-	REAL (U"To time (s)", U"1.0")
-	OK2
-DO
-	PointProcess point = FIRST (PointProcess);
-	Sound sound = FIRST (Sound);
-	autoSound thee = Sound_PointProcess_to_SoundEnsemble_correlate (sound, point, GET_REAL (U"From time"), GET_REAL (U"To time"));
-	praat_new (thee.move(), point -> name);
-END2 }
-
-/***** POLYGON *****/
-
-FORM (Polygon_draw, U"Polygon: Draw", nullptr) {
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Polygon);
-		autoPraatPicture picture;
-		Polygon_draw (me, GRAPHICS, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"));
-	}
-END2 }
+DIRECT (MODIFY_Polygon_randomize) {
+	MODIFY_EACH (Polygon)
+		Polygon_randomize (me);
+	MODIFY_EACH_END
+}
 
-FORM (Polygon_drawCircles, U"Polygon: Draw circles", nullptr) {
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0 (= all)")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0 (= all)")
-	POSITIVE (U"Diameter (mm)", U"3.0")
-	OK2
+FORM (MODIFY_Polygon_salesperson, U"Polygon: Find shortest path", nullptr) {
+	NATURALVAR (numberOfIterations, U"Number of iterations", U"1")
+	OK
 DO
-	LOOP {
-		iam (Polygon);
-		autoPraatPicture picture;
-		Polygon_drawCircles (me, GRAPHICS,
-			GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"),
-			GET_REAL (U"Diameter"));
-	}
-END2 }
+	MODIFY_EACH (Polygon)
+		Polygon_salesperson (me, numberOfIterations);
+	MODIFY_EACH_END
+}
 
-FORM (Polygon_drawClosed, U"Polygon: Draw", nullptr) {
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0")
-	OK2
-DO
-	LOOP {
-		iam (Polygon);
-		autoPraatPicture picture;
-		Polygon_drawClosed (me, GRAPHICS, GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"));
-	}
-END2 }
-
-FORM (Polygons_drawConnection, U"Polygons: Draw connection", nullptr) {
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0 (= all)")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0 (= all)")
-	BOOLEAN (U"Arrow", 0)
-	POSITIVE (U"Relative length", U"0.9")
-	OK2
-DO
-	Polygon polygon1 = nullptr, polygon2 = nullptr;
-	LOOP (polygon1 ? polygon2 : polygon1) = (Polygon) OBJECT;
-	autoPraatPicture picture;
-	Polygons_drawConnection (polygon1, polygon2, GRAPHICS,
-		GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"),
-		GET_INTEGER (U"Arrow"), GET_REAL (U"Relative length"));
-END2 }
-
-DIRECT2 (Polygon_help) {
-	Melder_help (U"Polygon");
-END2 }
-
-FORM (Polygon_paint, U"Polygon: Paint", nullptr) {
-	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0 (= all)")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0 (= all)")
-	OK2
-DO
-	LOOP {
-		iam (Polygon);
-		autoPraatPicture picture;
-		Polygon_paint (me, GRAPHICS, GET_COLOUR (U"Colour"), GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"));
-	}
-END2 }
+DIRECT (NEW_Polygon_to_Matrix) {
+	CONVERT_EACH (Polygon)
+		autoMatrix result = Polygon_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Polygon_paintCircles, U"Polygon: Paint circles", nullptr) {
-	REAL (U"Xmin", U"0.0")
-	REAL (U"Xmax", U"0.0 (= all)")
-	REAL (U"Ymin", U"0.0")
-	REAL (U"Ymax", U"0.0 (= all)")
-	POSITIVE (U"Diameter (mm)", U"3.0")
-	OK2
-DO
-	LOOP {
-		iam (Polygon);
-		autoPraatPicture picture;
-		Polygon_paintCircles (me, GRAPHICS,
-			GET_REAL (U"Xmin"), GET_REAL (U"Xmax"), GET_REAL (U"Ymin"), GET_REAL (U"Ymax"), GET_REAL (U"Diameter"));
-	}
-END2 }
+// MARK: - SOUND & PITCH & POINTPROCESS
+
+FORM (INFO_Sound_Pitch_PointProcess_voiceReport, U"Voice report", U"Voice") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVE4 (fromPitch, U"left Pitch range (Hz)", U"75.0")
+	POSITIVE4 (toPitch, U"right Pitch range (Hz)", U"600.0")
+	POSITIVE4 (maximumPeriodFactor, U"Maximum period factor", U"1.3")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	REAL4 (silenceThreshold, U"Silence threshold", U"0.03")
+	REAL4 (voicingThreshold, U"Voicing threshold", U"0.45")
+	OK
+DO
+	INFO_THREE (Sound, Pitch, PointProcess)
+		MelderInfo_open ();
+		Sound_Pitch_PointProcess_voiceReport (me, you, him, fromTime, toTime, fromPitch, toPitch,
+			maximumPeriodFactor, maximumAmplitudeFactor, silenceThreshold, voicingThreshold);
+		MelderInfo_close ();
+	INFO_THREE_END
+}
 
-DIRECT2 (Polygon_randomize) {
-	LOOP {
-		iam (Polygon);
-		Polygon_randomize (me);
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - SOUND & POINTPROCESS & PITCHTIER & DURATIONTIER
 
-FORM (Polygon_salesperson, U"Polygon: Find shortest path", nullptr) {
-	NATURAL (U"Number of iterations", U"1")
-	OK2
+FORM (NEW1_Sound_Point_Pitch_Duration_to_Sound, U"To Sound", nullptr) {
+	POSITIVE4 (longestPeriod, U"Longest period (s)", U"0.02")
+	OK
 DO
-	LOOP {
-		iam (Polygon);
-		Polygon_salesperson (me, GET_INTEGER (U"Number of iterations"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_FOUR (Sound, PointProcess, PitchTier, DurationTier)
+		autoSound result = Sound_Point_Pitch_Duration_to_Sound (me, you, him, she, longestPeriod);
+	CONVERT_FOUR_END (U"manip");
+}
 
-DIRECT2 (Polygon_to_Matrix) {
-	LOOP {
-		iam (Polygon);
-		autoMatrix thee = Polygon_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-/***** SOUND & PITCH & POINTPROCESS *****/
-
-FORM (Sound_Pitch_PointProcess_voiceReport, U"Voice report", U"Voice") {
-	praat_dia_timeRange (dia);
-	POSITIVE (U"left Pitch range (Hz)", U"75.0")
-	POSITIVE (U"right Pitch range (Hz)", U"600.0")
-	POSITIVE (U"Maximum period factor", U"1.3")
-	POSITIVE (U"Maximum amplitude factor", U"1.6")
-	REAL (U"Silence threshold", U"0.03")
-	REAL (U"Voicing threshold", U"0.45")
-	OK2
-DO
-	MelderInfo_open ();
-	Sound_Pitch_PointProcess_voiceReport (FIRST (Sound), FIRST (Pitch), FIRST (PointProcess),
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-		GET_REAL (U"left Pitch range"), GET_REAL (U"right Pitch range"),
-		GET_REAL (U"Maximum period factor"), GET_REAL (U"Maximum amplitude factor"),
-		GET_REAL (U"Silence threshold"), GET_REAL (U"Voicing threshold"));
-	MelderInfo_close ();
-END2 }
-
-/***** SOUND & POINTPROCESS & PITCHTIER & DURATIONTIER *****/
-
-FORM (Sound_Point_Pitch_Duration_to_Sound, U"To Sound", nullptr) {
-	POSITIVE (U"Longest period (s)", U"0.02")
-	OK2
-DO
-	autoSound thee = Sound_Point_Pitch_Duration_to_Sound (FIRST (Sound), FIRST (PointProcess),
-		FIRST (PitchTier), FIRST (DurationTier), GET_REAL (U"Longest period"));
-	praat_new (thee.move(), U"manip");
-END2 }
-
-/***** SPECTROGRAM *****/
-
-FORM (Spectrogram_paint, U"Spectrogram: Paint", U"Spectrogram: Paint...") {
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0 (= all)")
-	REAL (U"Maximum (dB/Hz)", U"100.0")
-	BOOLEAN (U"Autoscaling", 1)
-	POSITIVE (U"Dynamic range (dB)", U"50.0")
-	REAL (U"Pre-emphasis (dB/oct)", U"6.0")
-	REAL (U"Dynamic compression (0-1)", U"0.0")
-	BOOLEAN (U"Garnish", 1)
-	OK2
-DO
-	LOOP {
-		iam (Spectrogram);
-		autoPraatPicture picture;
-		Spectrogram_paint (me, GRAPHICS, GET_REAL (U"left Time range"),
-			GET_REAL (U"right Time range"), GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_REAL (U"Maximum"), GET_INTEGER (U"Autoscaling"),
-			GET_REAL (U"Dynamic range"), GET_REAL (U"Pre-emphasis"),
-			GET_REAL (U"Dynamic compression"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+// MARK: - SPECTROGRAM
+
+FORM (GRAPHICS_Spectrogram_paint, U"Spectrogram: Paint", U"Spectrogram: Paint...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (Hz)", U"0.0 (= all)")
+	REAL4 (maximum, U"Maximum (dB/Hz)", U"100.0")
+	BOOLEAN4 (autoscaling, U"Autoscaling", 1)
+	POSITIVE4 (dynamicRange, U"Dynamic range (dB)", U"50.0")
+	REAL4 (preEmphasis, U"Pre-emphasis (dB/oct)", U"6.0")
+	REAL4 (dynamicCompression, U"Dynamic compression (0-1)", U"0.0")
+	BOOLEAN4 (garnish, U"Garnish", 1)
+	OK
+DO
+	GRAPHICS_EACH (Spectrogram)
+		Spectrogram_paint (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			maximum, autoscaling, dynamicRange, preEmphasis, dynamicCompression, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Spectrogram_formula, U"Spectrogram: Formula", U"Spectrogram: Formula...") {
+FORM (MODIFY_Spectrogram_formula, U"Spectrogram: Formula", U"Spectrogram: Formula...") {
 	LABEL (U"label", U"Do for all times and frequencies:")
 	LABEL (U"label", U"   `x' is the time in seconds")
 	LABEL (U"label", U"   `y' is the frequency in hertz")
 	LABEL (U"label", U"   `self' is the current value in Pa\u00B2/Hz")
 	LABEL (U"label", U"   Replace all values with:")
-	TEXTFIELD (U"formula", U"self * exp (- x / 0.1)")
-	OK2
+	TEXTFIELD4 (formula, U"formula", U"self * exp (- x / 0.1)")
+	OK
 DO
-	LOOP {
-		iam (Spectrogram);
-		try {
-			Matrix_formula ((Matrix) me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Spectrogram may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (Spectrogram_getPowerAt, U"Spectrogram: Get power at (time, frequency)", nullptr) {
-	REAL (U"Time (s)", U"0.5")
-	REAL (U"Frequency (Hz)", U"1000")
-	OK2
-DO
-	Spectrogram me = FIRST_ANY (Spectrogram);
-	double time = GET_REAL (U"Time"), frequency = GET_REAL (U"Frequency");
-	MelderInfo_open ();
-	MelderInfo_write (Matrix_getValueAtXY (me, time, frequency));
-	MelderInfo_write (U" Pa2/Hz (at time = ", time, U" seconds and frequency = ", frequency, U" Hz)");
-	MelderInfo_close ();
-END2 }
-
-DIRECT2 (Spectrogram_help) {
-	Melder_help (U"Spectrogram");
-END2 }
-
-DIRECT2 (Spectrogram_movie) {
-	Graphics g = Movie_create (U"Spectrogram movie", 300, 300);
-	LOOP {
-		iam (Spectrogram);
-		Matrix_movie (me, g);
-	}
-END2 }
+	MODIFY_EACH_WEAK (Spectrogram)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (Spectrogram_to_Matrix) {
-	LOOP {
-		iam (Spectrogram);
-		autoMatrix thee = Spectrogram_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (REAL_Spectrogram_getPowerAt, U"Spectrogram: Get power at (time, frequency)", nullptr) {
+	REAL4 (time, U"Time (s)", U"0.5")
+	REAL4 (frequency, U"Frequency (Hz)", U"1000")
+	OK
+DO
+	NUMBER_ONE (Spectrogram)
+		double result = Matrix_getValueAtXY (me, time, frequency);
+	NUMBER_ONE_END (U" Pa2/Hz (at time = ", time, U" seconds and frequency = ", frequency, U" Hz)")
+}
+
+DIRECT (HELP_Spectrogram_help) {
+	HELP (U"Spectrogram")
+}
+
+DIRECT (MOVIE_Spectrogram_movie) {
+	MOVIE_ONE (Spectrogram, U"Spectrogram movie", 300, 300)
+		Matrix_movie (me, graphics);
+	MOVIE_ONE_END
+}
 
-FORM (Spectrogram_to_Sound, U"Spectrogram: To Sound", nullptr) {
-	REAL (U"Sampling frequency (Hz)", U"44100")
-	OK2
+DIRECT (NEW_Spectrogram_to_Matrix) {
+	CONVERT_EACH (Spectrogram)
+		autoMatrix result = Spectrogram_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Spectrogram_to_Sound, U"Spectrogram: To Sound", nullptr) {
+	REAL4 (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrogram);
-		autoSound thee = Spectrogram_to_Sound (me, GET_REAL (U"Sampling frequency"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Spectrogram)
+		autoSound result = Spectrogram_to_Sound (me, samplingFrequency);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Spectrogram_to_Spectrum, U"Spectrogram: To Spectrum (slice)", nullptr) {
-	REAL (U"Time (seconds)", U"0.0")
-	OK2
+FORM (NEW_Spectrogram_to_Spectrum, U"Spectrogram: To Spectrum (slice)", nullptr) {
+	REALVAR (time, U"Time (seconds)", U"0.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrogram);
-		autoSpectrum thee = Spectrogram_to_Spectrum (me, GET_REAL (U"Time"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Spectrogram)
+		autoSpectrum result = Spectrogram_to_Spectrum (me, time);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Spectrogram_view) {
+DIRECT (WINDOW_Spectrogram_view) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Spectrogram from batch.");
 	LOOP {
 		iam (Spectrogram);
@@ -5325,56 +2230,19 @@ DIRECT2 (Spectrogram_view) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-/***** SPECTRUM *****/
+// MARK: - SPECTRUM
 
-FORM (Spectrum_cepstralSmoothing, U"Spectrum: Cepstral smoothing", nullptr) {
-	POSITIVE (U"Bandwidth (Hz)", U"500.0")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		autoSpectrum thee = Spectrum_cepstralSmoothing (me, GET_REAL (U"Bandwidth"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: - Help
 
-FORM (Spectrum_draw, U"Spectrum: Draw", nullptr) {
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"0.0 (= all)")
-	REAL (U"Minimum power (dB/Hz)", U"0 (= auto)")
-	REAL (U"Maximum power (dB/Hz)", U"0 (= auto)")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		autoPraatPicture picture;
-		Spectrum_draw (me, GRAPHICS, GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"Minimum power"), GET_REAL (U"Maximum power"),
-			GET_INTEGER (U"Garnish"));
-	}
-END2 }
+DIRECT (HELP_Spectrum_help) {
+	HELP (U"Spectrum")
+}
 
-FORM (Spectrum_drawLogFreq, U"Spectrum: Draw (log freq)", nullptr) {
-	POSITIVE (U"left Frequency range (Hz)", U"10.0")
-	POSITIVE (U"right Frequency range (Hz)", U"10000.0")
-	REAL (U"Minimum power (dB/Hz)", U"0 (= auto)")
-	REAL (U"Maximum power (dB/Hz)", U"0 (= auto)")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		autoPraatPicture picture;
-		Spectrum_drawLogFreq (me, GRAPHICS, GET_REAL (U"left Frequency range"),
-			GET_REAL (U"right Frequency range"), GET_REAL (U"Minimum power"), GET_REAL (U"Maximum power"),
-			GET_INTEGER (U"Garnish"));
-	}
-END2 }
+// MARK: View & Edit
 
-DIRECT2 (Spectrum_edit) {
+DIRECT (WINDOW_Spectrum_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Spectrum from batch.");
 	LOOP {
 		iam (Spectrum);
@@ -5382,917 +2250,581 @@ DIRECT2 (Spectrum_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM (Spectrum_formula, U"Spectrum: Formula", U"Spectrum: Formula...") {
-	LABEL (U"label", U"`x' is the frequency in hertz, `col' is the bin number;   "
-		"`y' = `row' is 1 (real part) or 2 (imaginary part)")
-	LABEL (U"label", U"y := 1;   row := 1;   "
-		"x := 0;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
-	LABEL (U"label", U"y := 2;   row := 2;   "
-		"x := 0;   for col := 1 to ncol do { self [2, col] := `formula' ; x := x + dx }")
-	TEXTFIELD (U"formula", U"0")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		try {
-			Matrix_formula ((Matrix) me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Spectrum may have partially changed
-			throw;
-		}
-	}
-END2 }
+// MARK: Draw
 
-FORM (Spectrum_getBandDensity, U"Spectrum: Get band density", nullptr) {
-	REAL (U"Band floor (Hz)", U"200.0")
-	REAL (U"Band ceiling (Hz)", U"1000")
-	OK2
+FORM (GRAPHICS_Spectrum_draw, U"Spectrum: Draw", nullptr) {
+	REAL4 (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REAL4 (toFrequency, U"right Frequency range (Hz)", U"0.0 (= all)")
+	REAL4 (minimumPower, U"Minimum power (dB/Hz)", U"0 (= auto)")
+	REAL4 (maximumPower, U"Maximum power (dB/Hz)", U"0 (= auto)")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double density = Spectrum_getBandDensity (me, GET_REAL (U"Band floor"), GET_REAL (U"Band ceiling"));
-		Melder_informationReal (density, U"Pa2 / Hz2");
-	}
-END2 }
+	GRAPHICS_EACH (Spectrum)
+		Spectrum_draw (me, GRAPHICS, fromFrequency, toFrequency, minimumPower, maximumPower, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Spectrum_getBandDensityDifference, U"Spectrum: Get band density difference", nullptr) {
-	REAL (U"Low band floor (Hz)", U"0.0")
-	REAL (U"Low band ceiling (Hz)", U"500.0")
-	REAL (U"High band floor (Hz)", U"500.0")
-	REAL (U"High band ceiling (Hz)", U"4000.0")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		double difference = Spectrum_getBandDensityDifference (me,
-			GET_REAL (U"Low band floor"), GET_REAL (U"Low band ceiling"), GET_REAL (U"High band floor"), GET_REAL (U"High band ceiling"));
-		Melder_informationReal (difference, U"dB");
-	}
-END2 }
+FORM (GRAPHICS_Spectrum_drawLogFreq, U"Spectrum: Draw (log freq)", nullptr) {
+	POSITIVE4 (fromFrequency, U"left Frequency range (Hz)", U"10.0")
+	POSITIVE4 (toFrequency, U"right Frequency range (Hz)", U"10000.0")
+	REAL4 (minimumPower, U"Minimum power (dB/Hz)", U"0 (= auto)")
+	REAL4 (maximumPower, U"Maximum power (dB/Hz)", U"0 (= auto)")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Spectrum)
+		Spectrum_drawLogFreq (me, GRAPHICS, fromFrequency, toFrequency, minimumPower, maximumPower, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Spectrum_getBandEnergy, U"Spectrum: Get band energy", nullptr) {
-	REAL (U"Band floor (Hz)", U"200.0")
-	REAL (U"Band ceiling (Hz)", U"1000.0")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		double energy = Spectrum_getBandEnergy (me, GET_REAL (U"Band floor"), GET_REAL (U"Band ceiling"));
-		Melder_informationReal (energy, U"Pa2 sec");
-	}
-END2 }
+// MARK: Tabulate
+
+FORM (LIST_Spectrum_list, U"Spectrum: List", 0) {
+	BOOLEAN4 (includeBinNumber, U"Include bin number", false)
+	BOOLEAN4 (includeFrequency, U"Include frequency", true)
+	BOOLEAN4 (includeRealPart, U"Include real part", false)
+	BOOLEAN4 (includeImaginaryPart, U"Include imaginary part", false)
+	BOOLEAN4 (includeEnergyDensity, U"Include energy density", false)
+	BOOLEAN4 (includePowerDensity, U"Include power density", true)
+	OK
+DO
+	INFO_ONE (Spectrum)
+		Spectrum_list (me, includeBinNumber, includeFrequency, includeRealPart, includeImaginaryPart,
+			includeEnergyDensity, includePowerDensity);
+	INFO_ONE_END
+}
 
-FORM (Spectrum_getBandEnergyDifference, U"Spectrum: Get band energy difference", nullptr) {
-	REAL (U"Low band floor (Hz)", U"0.0")
-	REAL (U"Low band ceiling (Hz)", U"500.0")
-	REAL (U"High band floor (Hz)", U"500.0")
-	REAL (U"High band ceiling (Hz)", U"4000.0")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		double difference = Spectrum_getBandEnergyDifference (me,
-			GET_REAL (U"Low band floor"), GET_REAL (U"Low band ceiling"), GET_REAL (U"High band floor"), GET_REAL (U"High band ceiling"));
-		Melder_informationReal (difference, U"dB");
-	}
-END2 }
+// MARK: Query
 
-FORM (Spectrum_getBinFromFrequency, U"Spectrum: Get bin from frequency", nullptr) {
-	REAL (U"Frequency (Hz)", U"2000")
-	OK2
+FORM (REAL_Spectrum_getBandDensity, U"Spectrum: Get band density", nullptr) {
+	REAL4 (bandFloor, U"Band floor (Hz)", U"200.0")
+	REAL4 (bandCeiling, U"Band ceiling (Hz)", U"1000.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double bin = Sampled_xToIndex (me, GET_REAL (U"Frequency"));
-		Melder_informationReal (bin, nullptr);
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getBandDensity (me, bandFloor, bandCeiling);
+	NUMBER_ONE_END (U" Pa2 / Hz2")
+}
 
-DIRECT2 (Spectrum_getBinWidth) {
-	LOOP {
-		iam (Spectrum);
-		Melder_informationReal (my dx, U"hertz");
-	}
-END2 }
+FORM (REAL_Spectrum_getBandDensityDifference, U"Spectrum: Get band density difference", nullptr) {
+	REAL4 (lowBandFloor, U"Low band floor (Hz)", U"0.0")
+	REAL4 (lowBandCeiling, U"Low band ceiling (Hz)", U"500.0")
+	REAL4 (highBandFloor, U"High band floor (Hz)", U"500.0")
+	REAL4 (highBandCeiling, U"High band ceiling (Hz)", U"4000.0")
+	OK
+DO
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getBandDensityDifference (me,
+			lowBandFloor, lowBandCeiling, highBandFloor, highBandCeiling);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Spectrum_getCentralMoment, U"Spectrum: Get central moment", U"Spectrum: Get central moment...") {
-	POSITIVE (U"Moment", U"3.0")
-	POSITIVE (U"Power", U"2.0")
-	OK2
+FORM (REAL_Spectrum_getBandEnergy, U"Spectrum: Get band energy", nullptr) {
+	REAL4 (bandFloor, U"Band floor (Hz)", U"200.0")
+	REAL4 (bandCeiling, U"Band ceiling (Hz)", U"1000.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double moment = Spectrum_getCentralMoment (me, GET_REAL (U"Moment"), GET_REAL (U"Power"));
-		Melder_informationReal (moment, U"hertz to the power 'moment'");
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getBandEnergy (me, bandFloor, bandCeiling);
+	NUMBER_ONE_END (U" Pa2 sec")
+}
 
-FORM (Spectrum_getCentreOfGravity, U"Spectrum: Get centre of gravity", U"Spectrum: Get centre of gravity...") {
-	POSITIVE (U"Power", U"2.0")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		double centreOfGravity = Spectrum_getCentreOfGravity (me, GET_REAL (U"Power"));
-		Melder_informationReal (centreOfGravity, U"hertz");
-	}
-END2 }
+FORM (REAL_Spectrum_getBandEnergyDifference, U"Spectrum: Get band energy difference", nullptr) {
+	REAL4 (lowBandFloor, U"Low band floor (Hz)", U"0.0")
+	REAL4 (lowBandCeiling, U"Low band ceiling (Hz)", U"500.0")
+	REAL4 (highBandFloor, U"High band floor (Hz)", U"500.0")
+	REAL4 (highBandCeiling, U"High band ceiling (Hz)", U"4000.0")
+	OK
+DO
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getBandEnergyDifference (me,
+			lowBandFloor, lowBandCeiling, highBandFloor, highBandCeiling);
+	NUMBER_ONE_END (U" dB")
+}
 
-FORM (Spectrum_getFrequencyFromBin, U"Spectrum: Get frequency from bin", nullptr) {
-	NATURAL (U"Band number", U"1")
-	OK2
+FORM (REAL_Spectrum_getBinNumberFromFrequency, U"Spectrum: Get bin number from frequency", nullptr) {
+	REAL4 (frequency, U"Frequency (Hz)", U"2000.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double frequency = Sampled_indexToX (me, GET_INTEGER (U"Band number"));
-		Melder_informationReal (frequency, U"hertz");
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Sampled_xToIndex (me, frequency);
+	NUMBER_ONE_END (U" (bin number as a real value)")
+}
 
-DIRECT2 (Spectrum_getHighestFrequency) {
-	LOOP {
-		iam (Spectrum);
-		Melder_informationReal (my xmax, U"hertz");
-	}
-END2 }
+DIRECT (REAL_Spectrum_getBinWidth) {
+	NUMBER_ONE (Spectrum)
+		double result = my dx;
+	NUMBER_ONE_END (U" hertz")
+}
 
-FORM (Spectrum_getImaginaryValueInBin, U"Spectrum: Get imaginary value in bin", nullptr) {
-	NATURAL (U"Bin number", U"100")
-	OK2
+FORM (REAL_Spectrum_getCentralMoment, U"Spectrum: Get central moment", U"Spectrum: Get central moment...") {
+	POSITIVE4 (moment, U"Moment", U"3.0")
+	POSITIVE4 (power, U"Power", U"2.0")
+	OK
 DO
-	long binNumber = GET_INTEGER (U"Bin number");
-	LOOP {
-		iam (Spectrum);
-		if (binNumber > my nx) Melder_throw (U"Bin number must not exceed number of bins.");
-		Melder_informationReal (my z [2] [binNumber], nullptr);
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getCentralMoment (me, moment, power);
+	NUMBER_ONE_END (U" hertz to the power ", moment)
+}
 
-FORM (Spectrum_getKurtosis, U"Spectrum: Get kurtosis", U"Spectrum: Get kurtosis...") {
-	POSITIVE (U"Power", U"2.0")
-	OK2
+FORM (REAL_Spectrum_getCentreOfGravity, U"Spectrum: Get centre of gravity", U"Spectrum: Get centre of gravity...") {
+	POSITIVE4 (power, U"Power", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double kurtosis = Spectrum_getKurtosis (me, GET_REAL (U"Power"));
-		Melder_informationReal (kurtosis, nullptr);
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getCentreOfGravity (me, power);
+	NUMBER_ONE_END (U" hertz")
+}
 
-DIRECT2 (Spectrum_getLowestFrequency) {
-	LOOP {
-		iam (Spectrum);
-		Melder_informationReal (my xmin, U"hertz");
-	}
-END2 }
+FORM (REAL_Spectrum_getFrequencyFromBin, U"Spectrum: Get frequency from bin", nullptr) {
+	NATURAL4 (bandNumber, U"Band number", U"1")
+	OK
+DO
+	NUMBER_ONE (Spectrum)
+		double result = Sampled_indexToX (me, bandNumber);
+	NUMBER_ONE_END (U" hertz")
+}
 
-DIRECT2 (Spectrum_getNumberOfBins) {
-	LOOP {
-		iam (Spectrum);
-		Melder_information (my nx, U" bins");
-	}
-END2 }
+DIRECT (REAL_Spectrum_getLowestFrequency) {
+	NUMBER_ONE (Spectrum)
+		double result = my xmin;
+	NUMBER_ONE_END (U" hertz")
+}
+
+DIRECT (REAL_Spectrum_getHighestFrequency) {
+	NUMBER_ONE (Spectrum)
+		double result = my xmax;
+	NUMBER_ONE_END (U" hertz");
+}
 
-FORM (Spectrum_getRealValueInBin, U"Spectrum: Get real value in bin", nullptr) {
-	NATURAL (U"Bin number", U"100")
-	OK2
+FORM (REAL_Spectrum_getRealValueInBin, U"Spectrum: Get real value in bin", nullptr) {
+	NATURAL4 (binNumber, U"Bin number", U"100")
+	OK
 DO
-	long binNumber = GET_INTEGER (U"Bin number");
-	LOOP {
-		iam (Spectrum);
+	NUMBER_ONE (Spectrum)
 		if (binNumber > my nx) Melder_throw (U"Bin number must not exceed number of bins.");
-		Melder_informationReal (my z [1] [binNumber], nullptr);
-	}
-END2 }
+		double result = my z [1] [binNumber];
+	NUMBER_ONE_END (U" (real value in bin ", binNumber, U")")
+}
 
-FORM (Spectrum_getSkewness, U"Spectrum: Get skewness", U"Spectrum: Get skewness...") {
-	POSITIVE (U"Power", U"2.0")
-	OK2
+FORM (REAL_Spectrum_getImaginaryValueInBin, U"Spectrum: Get imaginary value in bin", nullptr) {
+	NATURAL4 (binNumber, U"Bin number", U"100")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double skewness = Spectrum_getSkewness (me, GET_REAL (U"Power"));
-		Melder_informationReal (skewness, nullptr);
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		if (binNumber > my nx) Melder_throw (U"The bin number should not exceed the number of bins.");
+		double result = my z [2] [binNumber];
+	NUMBER_ONE_END (U" (imaginary value in bin ", binNumber, U")")
+}
 
-FORM (Spectrum_getStandardDeviation, U"Spectrum: Get standard deviation", U"Spectrum: Get standard deviation...") {
-	POSITIVE (U"Power", U"2.0")
-	OK2
+FORM (REAL_Spectrum_getKurtosis, U"Spectrum: Get kurtosis", U"Spectrum: Get kurtosis...") {
+	POSITIVE4 (power, U"Power", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		double stdev = Spectrum_getStandardDeviation (me, GET_REAL (U"Power"));
-		Melder_informationReal (stdev, U"hertz");
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getKurtosis (me, power);
+	NUMBER_ONE_END (U" (kurtosis)")
+}
 
-DIRECT2 (Spectrum_help) {
-	Melder_help (U"Spectrum");
-END2 }
+DIRECT (INTEGER_Spectrum_getNumberOfBins) {
+	NUMBER_ONE (Spectrum)
+		long result = my nx;
+	NUMBER_ONE_END (U" bins")
+}
 
-FORM (Spectrum_list, U"Spectrum: List", 0) {
-	BOOLEAN (U"Include bin number", false)
-	BOOLEAN (U"Include frequency", true)
-	BOOLEAN (U"Include real part", false)
-	BOOLEAN (U"Include imaginary part", false)
-	BOOLEAN (U"Include energy density", false)
-	BOOLEAN (U"Include power density", true)
-	OK2
+FORM (REAL_Spectrum_getSkewness, U"Spectrum: Get skewness", U"Spectrum: Get skewness...") {
+	POSITIVEVAR (power, U"Power", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		Spectrum_list (me, GET_INTEGER (U"Include bin number"), GET_INTEGER (U"Include frequency"),
-			GET_INTEGER (U"Include real part"), GET_INTEGER (U"Include imaginary part"),
-			GET_INTEGER (U"Include energy density"), GET_INTEGER (U"Include power density"));
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getSkewness (me, power);
+	NUMBER_ONE_END (U" (skewness)")
+}
 
-FORM (Spectrum_lpcSmoothing, U"Spectrum: LPC smoothing", 0) {
-	NATURAL (U"Number of peaks", U"5")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	OK2
+FORM (REAL_Spectrum_getStandardDeviation, U"Spectrum: Get standard deviation", U"Spectrum: Get standard deviation...") {
+	POSITIVEVAR (power, U"Power", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		autoSpectrum thee = Spectrum_lpcSmoothing (me, GET_INTEGER (U"Number of peaks"), GET_REAL (U"Pre-emphasis from"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	NUMBER_ONE (Spectrum)
+		double result = Spectrum_getStandardDeviation (me, power);
+	NUMBER_ONE_END (U" hertz")
+}
 
-FORM (Spectrum_passHannBand, U"Spectrum: Filter (pass Hann band)", U"Spectrum: Filter (pass Hann band)...") {
-	REAL (U"From frequency (Hz)", U"500")
-	REAL (U"To frequency (Hz)", U"1000")
-	POSITIVE (U"Smoothing (Hz)", U"100")
-	OK2
-DO
-	LOOP {
-		iam (Spectrum);
-		Spectrum_passHannBand (me, GET_REAL (U"From frequency"), GET_REAL (U"To frequency"), GET_REAL (U"Smoothing"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: Modify
 
-FORM (Spectrum_stopHannBand, U"Spectrum: Filter (stop Hann band)", U"Spectrum: Filter (stop Hann band)...") {
-	REAL (U"From frequency (Hz)", U"500")
-	REAL (U"To frequency (Hz)", U"1000")
-	POSITIVE (U"Smoothing (Hz)", U"100")
-	OK2
+FORM (MODIFY_Spectrum_formula, U"Spectrum: Formula", U"Spectrum: Formula...") {
+	LABEL (U"label", U"`x' is the frequency in hertz, `col' is the bin number;   "
+		"`y' = `row' is 1 (real part) or 2 (imaginary part)")
+	LABEL (U"label", U"y := 1;   row := 1;   "
+		"x := 0;   for col := 1 to ncol do { self [1, col] := `formula' ; x := x + dx }")
+	LABEL (U"label", U"y := 2;   row := 2;   "
+		"x := 0;   for col := 1 to ncol do { self [2, col] := `formula' ; x := x + dx }")
+	TEXTFIELD4 (formula, U"formula", U"0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		Spectrum_stopHannBand (me, GET_REAL (U"From frequency"), GET_REAL (U"To frequency"), GET_REAL (U"Smoothing"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_WEAK (Spectrum)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM (Spectrum_to_Excitation, U"Spectrum: To Excitation", 0) {
-	POSITIVE (U"Frequency resolution (Bark)", U"0.1")
-	OK2
+FORM (MODIFY_Spectrum_passHannBand, U"Spectrum: Filter (pass Hann band)", U"Spectrum: Filter (pass Hann band)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"500.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"1000.0")
+	POSITIVE4 (smoothing, U"Smoothing (Hz)", U"100.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		autoExcitation thee = Spectrum_to_Excitation (me, GET_REAL (U"Frequency resolution"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	MODIFY_EACH (Spectrum)
+		Spectrum_passHannBand (me, fromFrequency, toFrequency, smoothing);
+	MODIFY_EACH_END
+}
 
-FORM (Spectrum_to_Formant_peaks, U"Spectrum: To Formant (peaks)", 0) {
-	LABEL (U"", U"Warning: this simply picks peaks from 0 Hz up!")
-	NATURAL (U"Maximum number of formants", U"1000")
-	OK2
+FORM (MODIFY_Spectrum_stopHannBand, U"Spectrum: Filter (stop Hann band)", U"Spectrum: Filter (stop Hann band)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"500.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"1000.0")
+	POSITIVE4 (smoothing, U"Smoothing (Hz)", U"100.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		autoFormant thee = Spectrum_to_Formant (me, GET_INTEGER (U"Maximum number of formants"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	MODIFY_EACH (Spectrum)
+		Spectrum_stopHannBand (me, fromFrequency, toFrequency, smoothing);
+	MODIFY_EACH_END
+}
+
+// MARK: Convert
 
-FORM (Spectrum_to_Ltas, U"Spectrum: To Long-term average spectrum", nullptr) {
-	POSITIVE (U"Bandwidth (Hz)", U"1000.0")
-	OK2
+FORM (NEW_Spectrum_cepstralSmoothing, U"Spectrum: Cepstral smoothing", nullptr) {
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"500.0")
+	OK
 DO
-	LOOP {
-		iam (Spectrum);
-		autoLtas thee = Spectrum_to_Ltas (me, GET_REAL (U"Bandwidth"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Spectrum)
+		autoSpectrum result = Spectrum_cepstralSmoothing (me, bandwidth);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Spectrum_to_Ltas_1to1) {
-	LOOP {
-		iam (Spectrum);
-		autoLtas thee = Spectrum_to_Ltas_1to1 (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (NEW_Spectrum_lpcSmoothing, U"Spectrum: LPC smoothing", 0) {
+	NATURAL4 (numberOfPeaks, U"Number of peaks", U"5")
+	POSITIVE4 (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
+	OK
+DO
+	CONVERT_EACH (Spectrum)
+		autoSpectrum result = Spectrum_lpcSmoothing (me, numberOfPeaks, preEmphasisFrom);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Spectrum_to_Matrix) {
-	LOOP {
-		iam (Spectrum);
-		autoMatrix thee = Spectrum_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (NEW_Spectrum_to_Excitation, U"Spectrum: To Excitation", nullptr) {
+	POSITIVE4 (frequencyResolution, U"Frequency resolution (Bark)", U"0.1")
+	OK
+DO
+	CONVERT_EACH (Spectrum)
+		autoExcitation result = Spectrum_to_Excitation (me, frequencyResolution);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Spectrum_to_Sound) {
-	LOOP {
-		iam (Spectrum);
-		autoSound thee = Spectrum_to_Sound (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (NEW_Spectrum_to_Formant_peaks, U"Spectrum: To Formant (peaks)", nullptr) {
+	LABEL (U"", U"Warning: this simply picks peaks from 0 Hz up!")
+	NATURAL4 (maximumNumberOfFormants, U"Maximum number of formants", U"1000")
+	OK
+DO
+	CONVERT_EACH (Spectrum)
+		autoFormant result = Spectrum_to_Formant (me, maximumNumberOfFormants);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Spectrum_to_Spectrogram) {
-	LOOP {
-		iam (Spectrum);
-		autoSpectrogram thee = Spectrum_to_Spectrogram (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (NEW_Spectrum_to_Ltas, U"Spectrum: To Long-term average spectrum", nullptr) {
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"1000.0")
+	OK
+DO
+	CONVERT_EACH (Spectrum)
+		autoLtas result = Spectrum_to_Ltas (me, bandwidth);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Spectrum_to_SpectrumTier_peaks) {
-	LOOP {
-		iam (Spectrum);
-		autoSpectrumTier thee = Spectrum_to_SpectrumTier_peaks (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Spectrum_to_Ltas_1to1) {
+	CONVERT_EACH (Spectrum)
+		autoLtas result = Spectrum_to_Ltas_1to1 (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** SPECTRUMTIER *****/
+DIRECT (NEW_Spectrum_to_Matrix) {
+	CONVERT_EACH (Spectrum)
+		autoMatrix result = Spectrum_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (SpectrumTier_downto_Table) {
-	LOOP {
-		iam (SpectrumTier);
-		autoTable thee = SpectrumTier_downto_Table (me, true, true, true);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Spectrum_to_Sound) {
+	CONVERT_EACH (Spectrum)
+		autoSound result = Spectrum_to_Sound (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (old_SpectrumTier_draw, U"SpectrumTier: Draw", nullptr) {   // 2010-10-19
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"10000.0")
-	REAL (U"left Power range (dB)", U"20.0")
-	REAL (U"right Power range (dB)", U"80.0")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	LOOP {
-		iam (SpectrumTier);
-		autoPraatPicture picture;
-		SpectrumTier_draw (me, GRAPHICS,
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Power range"), GET_REAL (U"right Power range"),
-			GET_INTEGER (U"Garnish"), U"lines and speckles");
-	}
-END2 }
-
-FORM (SpectrumTier_draw, U"SpectrumTier: Draw", nullptr) {
-	REAL (U"left Frequency range (Hz)", U"0.0")
-	REAL (U"right Frequency range (Hz)", U"10000.0")
-	REAL (U"left Power range (dB)", U"20.0")
-	REAL (U"right Power range (dB)", U"80.0")
-	BOOLEAN (U"Garnish", true)
-	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 1)
-		OPTION (U"lines")
-		OPTION (U"speckles")
-		OPTION (U"lines and speckles")
-	OK2
-DO_ALTERNATIVE (old_SpectrumTier_draw)
-	LOOP {
-		iam (SpectrumTier);
-		autoPraatPicture picture;
-		SpectrumTier_draw (me, GRAPHICS,
-			GET_REAL (U"left Frequency range"), GET_REAL (U"right Frequency range"),
-			GET_REAL (U"left Power range"), GET_REAL (U"right Power range"),
-			GET_INTEGER (U"Garnish"), GET_STRING (U"Drawing method"));
-	}
-END2 }
+DIRECT (NEW_Spectrum_to_Spectrogram) {
+	CONVERT_EACH (Spectrum)
+		autoSpectrogram result = Spectrum_to_Spectrogram (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (SpectrumTier_list, U"SpectrumTier: List", nullptr) {
-	BOOLEAN (U"Include indexes", true)
-	BOOLEAN (U"Include frequency", true)
-	BOOLEAN (U"Include power density", true)
-	OK2
-DO
-	LOOP {
-		iam (SpectrumTier);
-		SpectrumTier_list (me, GET_INTEGER (U"Include indexes"), GET_INTEGER (U"Include frequency"), GET_INTEGER (U"Include power density"));
-	}
-END2 }
+DIRECT (NEW_Spectrum_to_SpectrumTier_peaks) {
+	CONVERT_EACH (Spectrum)
+		autoSpectrumTier result = Spectrum_to_SpectrumTier_peaks (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (SpectrumTier_removePointsBelow, U"SpectrumTier: Remove points below", nullptr) {
-	REAL (U"Remove all points below (dB)", U"40.0")
-	OK2
-DO
-	LOOP {
-		iam (SpectrumTier);
-		RealTier_removePointsBelow ((RealTier) me, GET_REAL (U"Remove all points below"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - STRINGS
 
-/***** STRINGS *****/
+// MARK: New
 
-FORM (Strings_createAsFileList, U"Create Strings as file list", U"Create Strings as file list...") {
-	SENTENCE (U"Name", U"fileList")
+FORM (NEW1_Strings_createAsFileList, U"Create Strings as file list", U"Create Strings as file list...") {
+	SENTENCEVAR (name, U"Name", U"fileList")
 	LABEL (U"", U"File path:")
-	TEXTFIELD (U"path", U"/people/Miep/*.wav")
-	OK2
-static bool inited;
-if (! inited) {
-	structMelderDir defaultDir { { 0 } };
-	Melder_getDefaultDir (& defaultDir);
-	const char32 *workingDirectory = Melder_dirToPath (& defaultDir);
-	char32 path [kMelder_MAXPATH+1];
+	static structMelderDir defaultDir { { 0 } };
+	Melder_getHomeDir (& defaultDir);
+	static const char32 *homeDirectory = Melder_dirToPath (& defaultDir);
+	static char32 defaultPath [kMelder_MAXPATH+1];
 	#if defined (UNIX)
-		Melder_sprint (path, kMelder_MAXPATH+1, workingDirectory, U"/*.wav");
+		Melder_sprint (defaultPath,kMelder_MAXPATH+1, homeDirectory, U"/*.wav");
 	#elif defined (_WIN32)
 	{
-		int len = str32len (workingDirectory);
-		Melder_sprint (path, kMelder_MAXPATH+1, workingDirectory, len == 0 || workingDirectory [len - 1] != U'\\' ? U"\\" : U"", U"*.wav");
+		static int len = str32len (homeDirectory);
+		Melder_sprint (defaultPath,kMelder_MAXPATH+1, homeDirectory, len == 0 || homeDirectory [len - 1] != U'\\' ? U"\\" : U"", U"*.wav");
 	}
 	#else
-		Melder_sprint (path, kMelder_MAXPATH+1, workingDirectory, U"*.wav");
+		Melder_sprint (defaultPath,kMelder_MAXPATH+1, homeDirectory, U"/*.wav");
 	#endif
-	SET_STRING (U"path", path);
-	inited = true;
-}
+	TEXTVAR (path, U"path", defaultPath)
+	OK
 DO
-	autoStrings me = Strings_createAsFileList (GET_STRING (U"path"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
+	CREATE_ONE
+		autoStrings result = Strings_createAsFileList (path);
+	CREATE_ONE_END (name)
+}
 
-FORM (Strings_createAsDirectoryList, U"Create Strings as directory list", U"Create Strings as directory list...") {
-	SENTENCE (U"Name", U"directoryList")
+FORM (NEW1_Strings_createAsDirectoryList, U"Create Strings as directory list", U"Create Strings as directory list...") {
+	SENTENCEVAR (name, U"Name", U"directoryList")
 	LABEL (U"", U"Path:")
-	TEXTFIELD (U"path", U"/people/Miep/*")
-	OK2
-static bool inited;
-if (! inited) {
-	structMelderDir defaultDir = { { 0 } };
-	Melder_getDefaultDir (& defaultDir);
-	const char32 *workingDirectory = Melder_dirToPath (& defaultDir);
-	char32 path [kMelder_MAXPATH+1];
+	static structMelderDir defaultDir = { { 0 } };
+	Melder_getHomeDir (& defaultDir);
+	static const char32 *homeDirectory = Melder_dirToPath (& defaultDir);
+	static char32 defaultPath [kMelder_MAXPATH+1];
 	#if defined (UNIX)
-		Melder_sprint (path, kMelder_MAXPATH+1, workingDirectory, U"/*");
+		Melder_sprint (defaultPath,kMelder_MAXPATH+1, homeDirectory, U"/*");
 	#elif defined (_WIN32)
 	{
-		int len = str32len (workingDirectory);
-		Melder_sprint (path, kMelder_MAXPATH+1, workingDirectory, len == 0 || workingDirectory [len - 1] != U'\\' ? U"\\" : U"");
+		int len = str32len (homeDirectory);
+		Melder_sprint (defaultPath,kMelder_MAXPATH+1, homeDirectory, len == 0 || homeDirectory [len - 1] != U'\\' ? U"\\" : U"");
 	}
 	#else
-		Melder_sprint (path, kMelder_MAXPATH+1, workingDirectory, U"*");
+		Melder_sprint (defaultPath,kMelder_MAXPATH+1, homeDirectory, U"/*");
 	#endif
-	SET_STRING (U"path", path);
-	inited = true;
-}
+	TEXTVAR (path, U"path", defaultPath)
+	OK
 DO
-	autoStrings me = Strings_createAsDirectoryList (GET_STRING (U"path"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-DIRECT2 (Strings_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Strings from batch.");
-	LOOP {
-		iam (Strings);
-		autoStringsEditor editor = StringsEditor_create (ID_AND_FULL_NAME, me);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
+	CREATE_ONE
+		autoStrings result = Strings_createAsDirectoryList (path);
+	CREATE_ONE_END (name)
+}
 
-DIRECT2 (Strings_equal) {
-	Strings s1 = nullptr, s2 = nullptr;
-	LOOP (s1 ? s2 : s1) = (Strings) OBJECT;
-	bool equal = Data_equal (s1, s2);
-	Melder_information ((int) equal);   // we need a 0 or 1
-END2 }
+// MARK: Open
 
-DIRECT2 (Strings_genericize) {
-	LOOP {
-		iam (Strings);
-		try {
-			Strings_genericize (me);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // BUG: in case of error, the Strings may have partially changed
-			throw;
-		}
-	}
-END2 }
+FORM_READ (READ1_Strings_readFromRawTextFile, U"Read Strings from raw text file", nullptr, true) {
+	READ_ONE
+		autoStrings result = Strings_readFromRawTextFile (file);
+	READ_ONE_END
+}
 
-DIRECT2 (Strings_getNumberOfStrings) {
-	LOOP {
-		iam (Strings);
-		Melder_information (my numberOfStrings);
-	}
-END2 }
+// MARK: Save
 
-FORM (Strings_getString, U"Get string", nullptr) {
-	NATURAL (U"Position", U"1")
-	OK2
-DO
-	LOOP {
-		iam (Strings);
-		long index = GET_INTEGER (U"Position");
-		Melder_information (index > my numberOfStrings ? U"" : my strings [index]);   // TODO
-	}
-END2 }
+FORM_SAVE (SAVE_Strings_writeToRawTextFile, U"Save Strings as text file", nullptr, U"txt") {
+	SAVE_ONE (Strings)
+		Strings_writeToRawTextFile (me, file);
+	SAVE_ONE_END
+}
 
-DIRECT2 (Strings_help) {
-	Melder_help (U"Strings");
-END2 }
+// MARK: Help
 
-FORM (Strings_insertString, U"Strings: Insert string", 0) {
-	NATURAL (U"At position", U"1")
-	LABEL (U"", U"String:")
-	TEXTFIELD (U"string", U"")
-	OK2
-DO
-	LOOP {
-		iam (Strings);
-		Strings_insert (me, GET_INTEGER (U"At position"), GET_STRING (U"string"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (HELP_Strings_help) {
+	HELP (U"Strings")
+}
 
-DIRECT2 (Strings_nativize) {
-	LOOP {
-		iam (Strings);
-		try {
-			Strings_nativize (me);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // BUG: in case of error, the Strings may have partially changed
-			throw;
-		}
-	}
-END2 }
+// MARK: View & Edit
 
-DIRECT2 (Strings_randomize) {
+DIRECT (WINDOW_Strings_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Strings from batch.");
 	LOOP {
 		iam (Strings);
-		Strings_randomize (me);
-		praat_dataChanged (me);
+		autoStringsEditor editor = StringsEditor_create (ID_AND_FULL_NAME, me);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM_READ2 (Strings_readFromRawTextFile, U"Read Strings from raw text file", 0, true) {
-	autoStrings me = Strings_readFromRawTextFile (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
+// MARK: Query
 
-FORM (Strings_removeString, U"Strings: Remove string", nullptr) {
-	NATURAL (U"Position", U"1")
-	OK2
-DO
-	LOOP {
-		iam (Strings);
-		Strings_remove (me, GET_INTEGER (U"Position"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (BOOLEAN_Strings_equal) {
+	NUMBER_COUPLE (Strings)
+		long result = (long) Data_equal (me, you);   // cast bool to 0 or 1
+	NUMBER_COUPLE_END (result ? U" (equal)" : U" (unequal)")
+}
 
-FORM (Strings_replaceAll, U"Strings: Replace all", nullptr) {
-	SENTENCE (U"Find", U"a")
-	SENTENCE (U"Replace with", U"b")
-	INTEGER (U"Replace limit per string", U"0 (= unlimited)")
-	RADIO (U"Find and replace strings are", 1)
-		RADIOBUTTON (U"literals")
-		RADIOBUTTON (U"regular expressions")
-	OK2
-DO
-	long numberOfMatches, numberOfStringMatches;
-	LOOP {
-		iam (Strings);
-		autoStrings thee = Strings_change (me, GET_STRING (U"Find"), GET_STRING (U"Replace with"),
-			GET_INTEGER (U"Replace limit per string"), & numberOfMatches, & numberOfStringMatches, GET_INTEGER (U"Find and replace strings are") - 1);
-		praat_new (thee.move());
-	}
-END2 }
+DIRECT (INTEGER_Strings_getNumberOfStrings) {
+	NUMBER_ONE (Strings)
+		long result = my numberOfStrings;
+	NUMBER_ONE_END (U" strings")
+}
 
-FORM (Strings_setString, U"Strings: Set string", nullptr) {
-	NATURAL (U"Position", U"1")
-	LABEL (U"", U"New string:")
-	TEXTFIELD (U"newString", U"")
-	OK2
+FORM (STRING_Strings_getString, U"Get string", nullptr) {
+	NATURAL4 (position, U"Position", U"1")
+	OK
 DO
-	LOOP {
-		iam (Strings);
-		Strings_replace (me, GET_INTEGER (U"Position"), GET_STRING (U"newString"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Strings_sort) {
-	LOOP {
-		iam (Strings);
-		Strings_sort (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Strings_to_Distributions) {
-	LOOP {
-		iam (Strings);
-		autoDistributions thee = Strings_to_Distributions (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Strings_to_WordList) {
-	LOOP {
-		iam (Strings);
-		autoWordList thee = Strings_to_WordList (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM_WRITE (Strings_writeToRawTextFile, U"Save Strings as text file", nullptr, U"txt")
-	LOOP {
-		iam (Strings);
-		Strings_writeToRawTextFile (me, file);
-	}
-END
-
-/***** TABLE, rest in praat_Stat.cpp *****/
-
-DIRECT2 (Table_to_Matrix) {
-	LOOP {
-		iam (Table);
-		autoMatrix thee = Table_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	STRING_ONE (Strings)
+		const char32 *result = position > my numberOfStrings ? U"" : my strings [position];   // TODO
+	STRING_ONE_END
+}
 
-/***** TEXTGRID, rest in praat_TextGrid_init.cpp *****/
+// MARK: Modify
 
-FORM (TextGrid_create, U"Create TextGrid", U"Create TextGrid...") {
-	LABEL (U"", U"Hint: to label or segment an existing Sound,")
-	LABEL (U"", U"select that Sound and choose \"To TextGrid...\".")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	SENTENCE (U"All tier names", U"Mary John bell")
-	SENTENCE (U"Which of these are point tiers?", U"bell")
-	OK2
+FORM (MODIFY_Strings_insertString, U"Strings: Insert string", nullptr) {
+	INTEGERVAR (atPosition, U"At position", U"0 (= at end)")
+	LABEL (U"", U"String:")
+	TEXTVAR (string, U"string", U"")
+	OK
 DO
-	double tmin = GET_REAL (U"Start time"), tmax = GET_REAL (U"End time");
-	if (tmax <= tmin) Melder_throw (U"End time should be greater than start time");
-	autoTextGrid thee = TextGrid_create (tmin, tmax, GET_STRING (U"All tier names"), GET_STRING (U"Which of these are point tiers?"));
-	praat_new (thee.move(), GET_STRING (U"All tier names"));
-END2 }
-
-/***** TEXTTIER, rest in praat_TextGrid_init.cpp *****/
-
-FORM_READ2 (TextTier_readFromXwaves, U"Read TextTier from Xwaves", nullptr, true) {
-	autoTextTier me = TextTier_readFromXwaves (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
-
-/***** TIMEFRAMESAMPLED *****/
+	MODIFY_EACH (Strings)
+		Strings_insert (me, atPosition, string);
+	MODIFY_EACH_END
+}
 
-DIRECT2 (TimeFrameSampled_getNumberOfFrames) {
-	LOOP {
-		iam (Sampled);
-		long numberOfFrames = my nx;
-		Melder_information (numberOfFrames, U" frames");
-	}
-END2 }
+DIRECT (MODIFY_Strings_nativize) {
+	MODIFY_EACH_WEAK (Strings)
+		Strings_nativize (me);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM (TimeFrameSampled_getFrameFromTime, U"Get frame number from time", U"Get frame number from time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (Sampled);
-		double frame = Sampled_xToIndex (me, GET_REAL (U"Time"));
-		Melder_informationReal (frame, nullptr);
-	}
-END2 }
+DIRECT (MODIFY_Strings_genericize) {
+	MODIFY_EACH_WEAK (Strings)
+		Strings_genericize (me);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (TimeFrameSampled_getFrameLength) {
-	LOOP {
-		iam (Sampled);
-		double frameLength = my dx;
-		Melder_informationReal (frameLength, U"seconds");
-	}
-END2 }
+DIRECT (MODIFY_Strings_randomize) {
+	MODIFY_EACH (Strings)
+		Strings_randomize (me);
+	MODIFY_EACH_END
+}
 
-FORM (TimeFrameSampled_getTimeFromFrame, U"Get time from frame number", U"Get time from frame number...") {
-	NATURAL (U"Frame number", U"1")
-	OK2
+FORM (MODIFY_Strings_removeString, U"Strings: Remove string", nullptr) {
+	NATURAL4 (position, U"Position", U"1")
+	OK
 DO
-	LOOP {
-		iam (Sampled);
-		double time = Sampled_indexToX (me, GET_INTEGER (U"Frame number"));
-		Melder_informationReal (time, U"seconds");
-	}
-END2 }
-
-/***** TIMEFUNCTION *****/
-
-DIRECT2 (TimeFunction_getDuration) {
-	LOOP {
-		iam (Function);
-		double duration = my xmax - my xmin;
-		Melder_informationReal (duration, U"seconds");
-	}
-END2 }
-
-DIRECT2 (TimeFunction_getEndTime) {
-	LOOP {
-		iam (Function);
-		double endTime = my xmax;
-		Melder_informationReal (endTime, U"seconds");
-	}
-END2 }
-
-DIRECT2 (TimeFunction_getStartTime) {
-	LOOP {
-		iam (Function);
-		double startTime = my xmin;
-		Melder_informationReal (startTime, U"seconds");
-	}
-END2 }
+	MODIFY_EACH (Strings)
+		Strings_remove (me, position);
+	MODIFY_EACH_END
+}
 
-FORM (TimeFunction_scaleTimesBy, U"Scale times by", nullptr) {
-	POSITIVE (U"Factor", U"2.0")
-	OK2
+FORM (MODIFY_Strings_setString, U"Strings: Set string", nullptr) {
+	NATURAL4 (position, U"Position", U"1")
+	LABEL (U"", U"New string:")
+	TEXTFIELD4 (newString, U"newString", U"")
+	OK
 DO
-	LOOP {
-		iam (Function);
-		Function_scaleXBy (me, GET_REAL (U"Factor"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Strings)
+		Strings_replace (me, position, newString);
+	MODIFY_EACH_END
+}
 
-FORM (TimeFunction_scaleTimesTo, U"Scale times to", nullptr) {
-	REAL (U"New start time (s)", U"0.0")
-	REAL (U"New end time (s)", U"1.0")
-	OK2
-DO
-	double tminto = GET_REAL (U"New start time"), tmaxto = GET_REAL (U"New end time");
-	if (tminto >= tmaxto) Melder_throw (U"New end time should be greater than new start time.");
-	LOOP {
-		iam (Function);
-		Function_scaleXTo (me, tminto, tmaxto);
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (MODIFY_Strings_sort) {
+	MODIFY_EACH (Strings)
+		Strings_sort (me);
+	MODIFY_EACH_END
+}
 
-FORM (TimeFunction_shiftTimesBy, U"Shift times by", nullptr) {
-	REAL (U"Shift (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (Function);
-		Function_shiftXBy (me, GET_REAL (U"Shift"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: Convert
 
-FORM (TimeFunction_shiftTimesTo, U"Shift times to", nullptr) {
-	RADIO (U"Shift", 1)
-		OPTION (U"start time")
-		OPTION (U"centre time")
-		OPTION (U"end time")
-	REAL (U"To time (s)", U"0.0")
-	OK2
+FORM (NEW_Strings_replaceAll, U"Strings: Replace all", nullptr) {
+	SENTENCE4 (find, U"Find", U"a")
+	SENTENCE4 (replaceWith, U"Replace with", U"b")
+	INTEGER4 (replaceLimitPerString, U"Replace limit per string", U"0 (= unlimited)")
+	RADIO4x (findAndReplaceStringsAre, U"Find and replace strings are", 1, 0)
+		RADIOBUTTON (U"literals")
+		RADIOBUTTON (U"regular expressions")
+	OK
 DO
-	int shift = GET_INTEGER (U"Shift");
-	LOOP {
-		iam (Function);
-		Function_shiftXTo (me, shift == 1 ? my xmin : shift == 2 ? 0.5 * (my xmin + my xmax) : my xmax, GET_REAL (U"To time"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (TimeFunction_shiftToZero) {
-	LOOP {
-		iam (Function);
-		Function_shiftXTo (me, my xmin, 0.0);
-		praat_dataChanged (me);
-	}
-END2 }
-
-/***** TIMETIER *****/
+	CONVERT_EACH (Strings)
+		long numberOfMatches, numberOfStringMatches;
+		autoStrings result = Strings_change (me, find, replaceWith,
+			replaceLimitPerString, & numberOfMatches, & numberOfStringMatches, findAndReplaceStringsAre);   // FIXME: boolean inappropriate
+	CONVERT_EACH_END (my name, U"_replaced")
+}
 
-FORM (TimeTier_getHighIndexFromTime, U"Get high index", U"AnyTier: Get high index from time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		Melder_information (my points.size == 0 ? U"--undefined--" : Melder_integer (AnyTier_timeToHighIndex (me, GET_REAL (U"Time"))));
-	}
-END2 }
+DIRECT (NEW_Strings_to_Distributions) {
+	CONVERT_EACH (Strings)
+		autoDistributions result = Strings_to_Distributions (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TimeTier_getLowIndexFromTime, U"Get low index", U"AnyTier: Get low index from time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		Melder_information (my points.size == 0 ? U"--undefined--" : Melder_integer (AnyTier_timeToLowIndex (me, GET_REAL (U"Time"))));
-	}
-END2 }
+DIRECT (NEW_Strings_to_WordList) {
+	CONVERT_EACH (Strings)
+		autoWordList result = Strings_to_WordList (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TimeTier_getNearestIndexFromTime, U"Get nearest index", U"AnyTier: Get nearest index from time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		Melder_information (my points.size == 0 ? U"--undefined--" : Melder_integer (AnyTier_timeToNearestIndex (me, GET_REAL (U"Time"))));
-	}
-END2 }
+// MARK: - TABLE; the remainder is in praat_Stat.cpp *****/
 
-DIRECT2 (TimeTier_getNumberOfPoints) {
-	LOOP {
-		iam (AnyTier);
-		Melder_information (my points.size, U" points");
-	}
-END2 }
+DIRECT (NEW_Table_to_Matrix) {
+	CONVERT_EACH (Table)
+		autoMatrix result = Table_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TimeTier_getTimeFromIndex, U"Get time", nullptr /*"AnyTier: Get time from index..."*/) {
-	NATURAL (U"Point number", U"10")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		long i = GET_INTEGER (U"Point number");
-		if (i > my points.size) Melder_information (U"--undefined--");
-		else Melder_informationReal (my points.at [i] -> number, U"seconds");
-	}
-END2 }
+// MARK: - TEXTGRID; the remainder is in praat_TextGrid_init.cpp
 
-FORM (TimeTier_removePoint, U"Remove one point", U"AnyTier: Remove point...") {
-	NATURAL (U"Point number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		AnyTier_removePoint (me, GET_INTEGER (U"Point number"));
-		praat_dataChanged (me);
-	}
-END2 }
+FORM (NEW1_TextGrid_create, U"Create TextGrid", U"Create TextGrid...") {
+	LABEL (U"", U"Hint: to label or segment an existing Sound,")
+	LABEL (U"", U"select that Sound and choose \"To TextGrid...\".")
+	REAL4 (startTime, U"Start time (s)", U"0.0")
+	REAL4 (endTime, U"End time (s)", U"1.0")
+	SENTENCE4 (allTierNames, U"All tier names", U"Mary John bell")
+	SENTENCE4 (whichOfTheseArePointTiers, U"Which of these are point tiers?", U"bell")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"The end time should be greater than the start time");
+	CREATE_ONE
+		autoTextGrid result = TextGrid_create (startTime, endTime, allTierNames, whichOfTheseArePointTiers);
+	CREATE_ONE_END (allTierNames)
+}
 
-FORM (TimeTier_removePointNear, U"Remove one point", U"AnyTier: Remove point near...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		AnyTier_removePointNear (me, GET_REAL (U"Time"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: - TEXTTIER; the remainder is in praat_TextGrid_init.cpp *****/
 
-FORM (TimeTier_removePointsBetween, U"Remove points", U"AnyTier: Remove points between...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1.0")
-	OK2
-DO
-	LOOP {
-		iam (AnyTier);
-		AnyTier_removePointsBetween (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		praat_dataChanged (me);
-	}
-END2 }
+FORM_READ (READ1_TextTier_readFromXwaves, U"Read TextTier from Xwaves", nullptr, true) {
+	READ_ONE
+		autoTextTier result = TextTier_readFromXwaves (file);
+	READ_ONE_END
+}
 
-/***** TRANSITION *****/
+// MARK: - TRANSITION
 
-DIRECT2 (Transition_conflate) {
-	LOOP {
-		iam (Transition);
-		autoDistributions thee = Transition_to_Distributions_conflate (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_Transition_conflate) {
+	CONVERT_EACH (Transition)
+		autoDistributions result = Transition_to_Distributions_conflate (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Transition_drawAsNumbers, U"Draw as numbers", nullptr) {
-	RADIO (U"Format", 1)
+FORM (GRAPHICS_Transition_drawAsNumbers, U"Draw as numbers", nullptr) {
+	RADIO4 (format, U"Format", 1)
 		RADIOBUTTON (U"decimal")
 		RADIOBUTTON (U"exponential")
 		RADIOBUTTON (U"free")
 		RADIOBUTTON (U"rational")
-	NATURAL (U"Precision", U"2")
-	OK2
+	NATURAL4 (precision, U"Precision", U"2")
+	OK
 DO
-	LOOP {
-		iam (Transition);
-		autoPraatPicture picture;
-		Transition_drawAsNumbers (me, GRAPHICS, GET_INTEGER (U"Format"), GET_INTEGER (U"Precision"));
-	}
-END2 }
+	GRAPHICS_EACH (Transition)
+		Transition_drawAsNumbers (me, GRAPHICS, format, precision);
+	GRAPHICS_EACH_END
+}
 
-DIRECT2 (Transition_eigen) {
+DIRECT (NEWTIMES2_Transition_eigen) {
 	LOOP {
 		iam (Transition);
 		autoMatrix vectors, values;
@@ -6300,62 +2832,59 @@ DIRECT2 (Transition_eigen) {
 		praat_new (vectors.move(), U"eigenvectors");
 		praat_new (values.move(), U"eigenvalues");
 	}
-END2 }
+END }
+
+DIRECT (HELP_Transition_help) {
+	HELP (U"Transition")
+}
+
+FORM (NEW_Transition_power, U"Transition: Power...", nullptr) {
+	NATURAL4 (power, U"Power", U"2")
+	OK
+DO
+	CONVERT_EACH (Transition)
+		autoTransition result = Transition_power (me, power);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (Transition_help) {
-	Melder_help (U"Transition");
-END2 }
+DIRECT (NEW_Transition_to_Matrix) {
+	CONVERT_EACH (Transition)
+		autoMatrix result = Transition_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - Praat menu
 
-FORM (Transition_power, U"Transition: Power...", nullptr) {
-	NATURAL (U"Power", U"2")
-	OK2
+FORM (INFO_Praat_test, U"Praat test", 0) {
+	OPTIONMENU_ENUM4 (test, U"Test", kPraatTests, DEFAULT)
+	SENTENCE4 (arg1, U"arg1", U"1000000")
+	SENTENCE4 (arg2, U"arg2", U"")
+	SENTENCE4 (arg3, U"arg3", U"")
+	SENTENCE4 (arg4, U"arg4", U"")
+	OK
 DO
-	LOOP {
-		iam (Transition);
-		autoTransition thee = Transition_power (me, GET_INTEGER (U"Power"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	INFO_NONE
+		Praat_tests (test, arg1, arg2, arg3, arg4);
+	INFO_NONE_END
+}
 
-DIRECT2 (Transition_to_Matrix) {
-	LOOP {
-		iam (Transition);
-		autoMatrix thee = Transition_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-/***** Praat menu *****/
-
-FORM (Praat_test, U"Praat test", 0) {
-	OPTIONMENU_ENUM (U"Test", kPraatTests, DEFAULT)
-	SENTENCE (U"arg1", U"1000000")
-	SENTENCE (U"arg2", U"")
-	SENTENCE (U"arg3", U"")
-	SENTENCE (U"arg4", U"")
-	OK2
-DO
-	Praat_tests (GET_ENUM (kPraatTests, U"Test"), GET_STRING (U"arg1"),
-		GET_STRING (U"arg2"), GET_STRING (U"arg3"), GET_STRING (U"arg4"));
-END2 }
-
-/***** Help menu *****/
-
-DIRECT (ObjectWindow) Melder_help (U"Object window"); END
-DIRECT (Intro) Melder_help (U"Intro"); END
-DIRECT (WhatsNew) Melder_help (U"What's new?"); END
-DIRECT (TypesOfObjects) Melder_help (U"Types of objects"); END
-DIRECT (Editors) Melder_help (U"Editors"); END
-DIRECT (FrequentlyAskedQuestions) Melder_help (U"FAQ (Frequently Asked Questions)"); END
-DIRECT (Acknowledgments) Melder_help (U"Acknowledgments"); END
-DIRECT (FormulasTutorial) Melder_help (U"Formulas"); END
-DIRECT (ScriptingTutorial) Melder_help (U"Scripting"); END
-DIRECT (DemoWindow) Melder_help (U"Demo window"); END
-DIRECT (Interoperability) Melder_help (U"Interoperability"); END
-DIRECT (Programming) Melder_help (U"Programming with Praat"); END
-DIRECT (SearchManual) Melder_search (); END
-
-/***** file recognizers *****/
+// MARK: - Help menu
+
+DIRECT (HELP_ObjectWindow) { HELP (U"Object window") }
+DIRECT (HELP_Intro) { HELP (U"Intro") }
+DIRECT (HELP_WhatsNew) { HELP (U"What's new?") }
+DIRECT (HELP_TypesOfObjects) { HELP (U"Types of objects") }
+DIRECT (HELP_Editors) { HELP (U"Editors") }
+DIRECT (HELP_FrequentlyAskedQuestions) { HELP (U"FAQ (Frequently Asked Questions)") }
+DIRECT (HELP_Acknowledgments) { HELP (U"Acknowledgments") }
+DIRECT (HELP_FormulasTutorial) { HELP (U"Formulas") }
+DIRECT (HELP_ScriptingTutorial) { HELP (U"Scripting") }
+DIRECT (HELP_DemoWindow) { HELP (U"Demo window") }
+DIRECT (HELP_Interoperability) { HELP (U"Interoperability") }
+DIRECT (HELP_Programming) { HELP (U"Programming with Praat") }
+DIRECT (HELP_SearchManual_Fon) { Melder_search (); END }
+
+// MARK: - file recognizers
 
 static autoDaata cgnSyntaxFileRecognizer (int nread, const char *header, MelderFile file) {
 	if (nread < 57) return autoDaata ();
@@ -6384,94 +2913,18 @@ static autoDaata chronologicalTextGridTextFileRecognizer (int nread, const char
 	return autoDaata ();
 }
 
-static autoDaata imageFileRecognizer (int /* nread */, const char * /* header */, MelderFile file) {
-	const char32 *fileName = MelderFile_name (file);
-	if (Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".jpg") ||
-	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".JPG") ||
-	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".jpeg") ||
-		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".JPEG") ||
-	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".png") ||
-		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".PNG") ||
-	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".tiff") ||
-		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".TIFF") ||
-		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".tif") ||
-		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".TIF"))
-	{
-		return Photo_readFromImageFile (file);
-	}
-	return autoDaata ();
-}
+// MARK: - buttons
 
-/***** buttons *****/
-
-void praat_TableOfReal_init (ClassInfo klas);   // Buttons for TableOfReal and for its subclasses.
-
-void praat_TimeFunction_query_init (ClassInfo klas);   // Query buttons for time-based subclasses of Function.
-void praat_TimeFunction_query_init (ClassInfo klas) {
-	praat_addAction1 (klas, 1, U"Query time domain", nullptr, 1, nullptr);
-	praat_addAction1 (klas, 1, U"Get start time", nullptr, 2, DO_TimeFunction_getStartTime);
-						praat_addAction1 (klas, 1, U"Get starting time", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_getStartTime);
-	praat_addAction1 (klas, 1, U"Get end time", nullptr, 2, DO_TimeFunction_getEndTime);
-						praat_addAction1 (klas, 1, U"Get finishing time", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_getEndTime);
-	praat_addAction1 (klas, 1, U"Get total duration", nullptr, 2, DO_TimeFunction_getDuration);
-						praat_addAction1 (klas, 1, U"Get duration", 0, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_getDuration);
-}
-
-void praat_TimeFunction_modify_init (ClassInfo klas);   // Modify buttons for time-based subclasses of Function.
-void praat_TimeFunction_modify_init (ClassInfo klas) {
-	praat_addAction1 (klas, 0, U"Modify times", nullptr, 1, nullptr);
-	praat_addAction1 (klas, 0, U"Shift times by...", nullptr, 2, DO_TimeFunction_shiftTimesBy);
-	praat_addAction1 (klas, 0, U"Shift times to...", nullptr, 2, DO_TimeFunction_shiftTimesTo);
-						praat_addAction1 (klas, 0, U"Shift to zero", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_shiftToZero);   // hidden 2008
-	praat_addAction1 (klas, 0, U"Scale times by...", nullptr, 2, DO_TimeFunction_scaleTimesBy);
-	praat_addAction1 (klas, 0, U"Scale times to...", nullptr, 2, DO_TimeFunction_scaleTimesTo);
-						praat_addAction1 (klas, 0, U"Scale times...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TimeFunction_scaleTimesTo);   // hidden 2008
-}
-
-void praat_TimeFrameSampled_query_init (ClassInfo klas);   // Query buttons for frame-based time-based subclasses of Sampled.
-void praat_TimeFrameSampled_query_init (ClassInfo klas) {
-	praat_TimeFunction_query_init (klas);
-	praat_addAction1 (klas, 1, U"Query time sampling", nullptr, 1, nullptr);
-	praat_addAction1 (klas, 1, U"Get number of frames", nullptr, 2, DO_TimeFrameSampled_getNumberOfFrames);
-	praat_addAction1 (klas, 1, U"Get time step", nullptr, 2, DO_TimeFrameSampled_getFrameLength);
-						praat_addAction1 (klas, 1, U"Get frame length", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getFrameLength);
-						praat_addAction1 (klas, 1, U"Get frame duration", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getFrameLength);
-	praat_addAction1 (klas, 1, U"Get time from frame number...", nullptr, 2, DO_TimeFrameSampled_getTimeFromFrame);
-						praat_addAction1 (klas, 1, U"Get time from frame...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getTimeFromFrame);
-	praat_addAction1 (klas, 1, U"Get frame number from time...", nullptr, 2, DO_TimeFrameSampled_getFrameFromTime);
-						praat_addAction1 (klas, 1, U"Get frame from time...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TimeFrameSampled_getFrameFromTime);
-}
-
-void praat_TimeTier_query_init (ClassInfo klas);   // Query buttons for time-based subclasses of AnyTier.
-void praat_TimeTier_query_init (ClassInfo klas) {
-	praat_TimeFunction_query_init (klas);
-	praat_addAction1 (klas, 1, U"Get number of points", nullptr, 1, DO_TimeTier_getNumberOfPoints);
-	praat_addAction1 (klas, 1, U"Get low index from time...", nullptr, 1, DO_TimeTier_getLowIndexFromTime);
-	praat_addAction1 (klas, 1, U"Get high index from time...", nullptr, 1, DO_TimeTier_getHighIndexFromTime);
-	praat_addAction1 (klas, 1, U"Get nearest index from time...", nullptr, 1, DO_TimeTier_getNearestIndexFromTime);
-	praat_addAction1 (klas, 1, U"Get time from index...", nullptr, 1, DO_TimeTier_getTimeFromIndex);
-}
-
-void praat_TimeTier_modify_init (ClassInfo klas);   // Modification buttons for time-based subclasses of AnyTier.
-void praat_TimeTier_modify_init (ClassInfo klas) {
-	praat_TimeFunction_modify_init (klas);
-	praat_addAction1 (klas, 0, U"Remove point...", nullptr, 1, DO_TimeTier_removePoint);
-	praat_addAction1 (klas, 0, U"Remove point near...", nullptr, 1, DO_TimeTier_removePointNear);
-	praat_addAction1 (klas, 0, U"Remove points between...", nullptr, 1, DO_TimeTier_removePointsBetween);
-}
-
-void praat_uvafon_init ();
 void praat_uvafon_init () {
-	Thing_recognizeClassesByName (classSound, classMatrix, classPolygon, classPointProcess, classParamCurve,
+	Thing_recognizeClassesByName (classPolygon, classParamCurve,
 		classSpectrum, classLtas, classSpectrogram, classFormant,
-		classExcitation, classCochleagram, classVocalTract, classFormantPoint, classFormantTier, classFormantGrid,
+		classExcitation, classCochleagram, classVocalTract,
 		classLabel, classTier, classAutosegment,   // three obsolete classes
 		classIntensity, classPitch, classHarmonicity,
 		classTransition,
-		classRealPoint, classRealTier, classPitchTier, classIntensityTier, classDurationTier, classAmplitudeTier, classSpectrumTier,
 		classManipulation, classTextPoint, classTextInterval, classTextTier,
-		classIntervalTier, classTextGrid, classLongSound, classWordList, classSpellingChecker,
-		classMovie, classCorpus, classPhoto,
+		classIntervalTier, classTextGrid, classWordList, classSpellingChecker,
+		classCorpus,
 		nullptr);
 	Thing_recognizeClassByOtherName (classManipulation, U"Psola");
 	Thing_recognizeClassByOtherName (classManipulation, U"Analysis");
@@ -6479,803 +2932,466 @@ void praat_uvafon_init () {
 
 	Data_recognizeFileType (cgnSyntaxFileRecognizer);
 	Data_recognizeFileType (chronologicalTextGridTextFileRecognizer);
-	Data_recognizeFileType (imageFileRecognizer);
 	Data_recognizeFileType (IDXFormattedMatrixFileRecognizer);
 	
 	structManipulationEditor :: f_preferences ();
 	structSpectrumEditor     :: f_preferences ();
 	structFormantGridEditor  :: f_preferences ();
 
-	INCLUDE_LIBRARY (praat_uvafon_Sound_init)
-	INCLUDE_LIBRARY (praat_uvafon_TextGrid_init)
-
-	praat_addMenuCommand (U"Objects", U"Technical", U"Praat test...", nullptr, 0, DO_Praat_test);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Praat test...", nullptr, 0, INFO_Praat_test);
 
+	/*
+		The user interfaces for the classes are included in the order
+		in which they have to appear in the New menu:
+	*/
+	praat_Sound_init ();
 	praat_addMenuCommand (U"Objects", U"New", U"-- new numerics --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Matrix", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Matrix...", nullptr, 1, DO_Matrix_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create simple Matrix...", nullptr, 1, DO_Matrix_createSimple);
-		praat_addMenuCommand (U"Objects", U"New", U"-- colour matrix --", nullptr, 1, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Photo...", nullptr, 1, DO_Photo_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create simple Photo...", nullptr, 1, DO_Photo_createSimple);
-	praat_addMenuCommand (U"Objects", U"Open", U"-- read movie --", nullptr, praat_HIDDEN, nullptr);
-	praat_addMenuCommand (U"Objects", U"Open", U"Open movie file...", nullptr, praat_HIDDEN, DO_Movie_openFromSoundFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"-- read raw --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Matrix from raw text file...", nullptr, 0, DO_Matrix_readFromRawTextFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Matrix from LVS AP file...", nullptr, praat_HIDDEN, DO_Matrix_readAP);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Strings from raw text file...", nullptr, 0, DO_Strings_readFromRawTextFile);
-
+	praat_Matrix_init ();
 	INCLUDE_LIBRARY (praat_uvafon_stat_init)
+	praat_Tiers_init ();
+	praat_uvafon_TextGrid_init ();
+
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Strings from raw text file...", nullptr, 0, READ1_Strings_readFromRawTextFile);
 
-	praat_addMenuCommand (U"Objects", U"New", U"Tiers", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create empty PointProcess...", nullptr, 1, DO_PointProcess_createEmpty);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Poisson process...", nullptr, 1, DO_PointProcess_createPoissonProcess);
-		praat_addMenuCommand (U"Objects", U"New", U"-- new tiers ---", nullptr, 1, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create PitchTier...", nullptr, 1, DO_PitchTier_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create FormantGrid...", nullptr, 1, DO_FormantGrid_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create FormantTier...", nullptr, praat_HIDDEN | praat_DEPTH_1, DO_FormantTier_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create IntensityTier...", nullptr, 1, DO_IntensityTier_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create DurationTier...", nullptr, 1, DO_DurationTier_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create AmplitudeTier...", nullptr, 1, DO_AmplitudeTier_create);
 	praat_addMenuCommand (U"Objects", U"New", U"-- new textgrid --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"New", U"Create TextGrid...", nullptr, 0, DO_TextGrid_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Corpus...", nullptr, praat_HIDDEN, DO_Corpus_create);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as file list...", nullptr, 0, DO_Strings_createAsFileList);
-	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as directory list...", nullptr, 0, DO_Strings_createAsDirectoryList);
+	praat_addMenuCommand (U"Objects", U"New", U"Create TextGrid...", nullptr, 0, NEW1_TextGrid_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Corpus...", nullptr, praat_HIDDEN, NEW1_Corpus_create);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as file list...", nullptr, 0, NEW1_Strings_createAsFileList);
+	praat_addMenuCommand (U"Objects", U"New", U"Create Strings as directory list...", nullptr, 0, NEW1_Strings_createAsDirectoryList);
 
 	praat_addMenuCommand (U"Objects", U"Open", U"-- read tier --", nullptr, 0, nullptr);
 	praat_addMenuCommand (U"Objects", U"Open", U"Read from special tier file...", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"Open", U"Read TextTier from Xwaves...", nullptr, 1, DO_TextTier_readFromXwaves);
-		praat_addMenuCommand (U"Objects", U"Open", U"Read IntervalTier from Xwaves...", nullptr, 1, DO_IntervalTier_readFromXwaves);
+		praat_addMenuCommand (U"Objects", U"Open", U"Read TextTier from Xwaves...", nullptr, 1, READ1_TextTier_readFromXwaves);
+		praat_addMenuCommand (U"Objects", U"Open", U"Read IntervalTier from Xwaves...", nullptr, 1, READ1_IntervalTier_readFromXwaves);
 
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Praat Intro", nullptr, '?', DO_Intro);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Praat Intro", nullptr, '?', HELP_Intro);
 	#ifndef macintosh
-		praat_addMenuCommand (U"Objects", U"Help", U"Object window", nullptr, 0, DO_ObjectWindow);
+		praat_addMenuCommand (U"Objects", U"Help", U"Object window", nullptr, 0, HELP_ObjectWindow);
 	#endif
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Frequently asked questions", nullptr, 0, DO_FrequentlyAskedQuestions);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"What's new?", nullptr, 0, DO_WhatsNew);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Types of objects", nullptr, 0, DO_TypesOfObjects);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Editors", nullptr, 0, DO_Editors);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Acknowledgments", nullptr, 0, DO_Acknowledgments);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Frequently asked questions", nullptr, 0, HELP_FrequentlyAskedQuestions);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"What's new?", nullptr, 0, HELP_WhatsNew);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Types of objects", nullptr, 0, HELP_TypesOfObjects);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Editors", nullptr, 0, HELP_Editors);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Acknowledgments", nullptr, 0, HELP_Acknowledgments);
 	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"-- shell help --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Formulas tutorial", nullptr, 0, DO_FormulasTutorial);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Scripting tutorial", nullptr, 0, DO_ScriptingTutorial);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Demo window", nullptr, 0, DO_DemoWindow);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Interoperability", nullptr, 0, DO_Interoperability);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Programming", nullptr, 0, DO_Programming);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Formulas tutorial", nullptr, 0, HELP_FormulasTutorial);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Scripting tutorial", nullptr, 0, HELP_ScriptingTutorial);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Demo window", nullptr, 0, HELP_DemoWindow);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Interoperability", nullptr, 0, HELP_Interoperability);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Programming", nullptr, 0, HELP_Programming);
 	#ifdef macintosh
-		praat_addMenuCommand (U"Objects", U"Help", U"Praat Intro", nullptr, '?', DO_Intro);
-		praat_addMenuCommand (U"Objects", U"Help", U"Object window help", nullptr, 0, DO_ObjectWindow);
+		praat_addMenuCommand (U"Objects", U"Help", U"Praat Intro", nullptr, '?', HELP_Intro);
+		praat_addMenuCommand (U"Objects", U"Help", U"Object window help", nullptr, 0, HELP_ObjectWindow);
 		praat_addMenuCommand (U"Objects", U"Help", U"-- manual --", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"Help", U"Search Praat manual...", nullptr, 'M', DO_SearchManual);
+		praat_addMenuCommand (U"Objects", U"Help", U"Search Praat manual...", nullptr, 'M', HELP_SearchManual_Fon);
 	#endif
 
-	praat_addAction1 (classAmplitudeTier, 0, U"AmplitudeTier help", nullptr, 0, DO_AmplitudeTier_help);
-	praat_addAction1 (classAmplitudeTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_AmplitudeTier_edit);
-	praat_addAction1 (classAmplitudeTier, 1, U"Edit", nullptr, praat_HIDDEN, DO_AmplitudeTier_edit);
-	praat_addAction1 (classAmplitudeTier, 0, U"View & Edit with Sound?", 0, 0, DO_info_AmplitudeTier_Sound_edit);
-	praat_addAction1 (classAmplitudeTier, 0, U"Query -", nullptr, 0, nullptr);
-		praat_TimeTier_query_init (classAmplitudeTier);
-		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (local)...", nullptr, 1, DO_AmplitudeTier_getShimmer_local);
-		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (local_dB)...", nullptr, 1, DO_AmplitudeTier_getShimmer_local_dB);
-		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (apq3)...", nullptr, 1, DO_AmplitudeTier_getShimmer_apq3);
-		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (apq5)...", nullptr, 1, DO_AmplitudeTier_getShimmer_apq5);
-		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (apq11)...", nullptr, 1, DO_AmplitudeTier_getShimmer_apq11);
-		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (dda)...", nullptr, 1, DO_AmplitudeTier_getShimmer_dda);
-	praat_addAction1 (classAmplitudeTier, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeTier_modify_init (classAmplitudeTier);
-		praat_addAction1 (classAmplitudeTier, 0, U"Add point...", nullptr, 1, DO_AmplitudeTier_addPoint);
-		praat_addAction1 (classAmplitudeTier, 0, U"Formula...", nullptr, 1, DO_AmplitudeTier_formula);
-praat_addAction1 (classAmplitudeTier, 0, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction1 (classAmplitudeTier, 0, U"To Sound (pulse train)...", nullptr, 0, DO_AmplitudeTier_to_Sound);
-praat_addAction1 (classAmplitudeTier, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classAmplitudeTier, 0, U"To IntensityTier...", nullptr, 0, DO_AmplitudeTier_to_IntensityTier);
-	praat_addAction1 (classAmplitudeTier, 0, U"Down to PointProcess", nullptr, 0, DO_AmplitudeTier_downto_PointProcess);
-	praat_addAction1 (classAmplitudeTier, 0, U"Down to TableOfReal", nullptr, 0, DO_AmplitudeTier_downto_TableOfReal);
-
-	praat_addAction1 (classCochleagram, 0, U"Cochleagram help", nullptr, 0, DO_Cochleagram_help);
-	praat_addAction1 (classCochleagram, 1, U"Movie", nullptr, 0, DO_Cochleagram_movie);
+	praat_addAction1 (classCochleagram, 0, U"Cochleagram help", nullptr, 0, HELP_Cochleagram_help);
+	praat_addAction1 (classCochleagram, 1, U"Movie", nullptr, 0, MOVIE_Cochleagram_movie);
 praat_addAction1 (classCochleagram, 0, U"Info", nullptr, 0, nullptr);
-	praat_addAction1 (classCochleagram, 2, U"Difference...", nullptr, 0, DO_Cochleagram_difference);
+	praat_addAction1 (classCochleagram, 2, U"Difference...", nullptr, 0, REAL_Cochleagram_difference);
 praat_addAction1 (classCochleagram, 0, U"Draw", nullptr, 0, nullptr);
-	praat_addAction1 (classCochleagram, 0, U"Paint...", nullptr, 0, DO_Cochleagram_paint);
+	praat_addAction1 (classCochleagram, 0, U"Paint...", nullptr, 0, GRAPHICS_Cochleagram_paint);
 praat_addAction1 (classCochleagram, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classCochleagram, 0, U"Formula...", nullptr, 0, DO_Cochleagram_formula);
+	praat_addAction1 (classCochleagram, 0, U"Formula...", nullptr, 0, MODIFY_Cochleagram_formula);
 praat_addAction1 (classCochleagram, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classCochleagram, 0, U"To Excitation (slice)...", nullptr, 0, DO_Cochleagram_to_Excitation);
+	praat_addAction1 (classCochleagram, 0, U"To Excitation (slice)...", nullptr, 0, NEW_Cochleagram_to_Excitation);
 praat_addAction1 (classCochleagram, 0, U"Hack", nullptr, 0, nullptr);
-	praat_addAction1 (classCochleagram, 0, U"To Matrix", nullptr, 0, DO_Cochleagram_to_Matrix);
+	praat_addAction1 (classCochleagram, 0, U"To Matrix", nullptr, 0, NEW_Cochleagram_to_Matrix);
 
-	praat_addAction1 (classCorpus, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Corpus_edit);
+	praat_addAction1 (classCorpus, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Corpus_edit);
 
 praat_addAction1 (classDistributions, 0, U"Learn", nullptr, 0, nullptr);
-	praat_addAction1 (classDistributions, 1, U"To Transition...", nullptr, 0, DO_Distributions_to_Transition);
-	praat_addAction1 (classDistributions, 2, U"To Transition (noise)...", nullptr, 0, DO_Distributions_to_Transition_noise);
-
-	praat_addAction1 (classDurationTier, 0, U"DurationTier help", nullptr, 0, DO_DurationTier_help);
-	praat_addAction1 (classDurationTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_DurationTier_edit);
-	praat_addAction1 (classDurationTier, 1, U"Edit", nullptr, praat_HIDDEN, DO_DurationTier_edit);
-	praat_addAction1 (classDurationTier, 0, U"View & Edit with Sound?", nullptr, 0, DO_info_DurationTier_Sound_edit);
-	praat_addAction1 (classDurationTier, 0, U"& Manipulation: Replace?", nullptr, 0, DO_info_DurationTier_Manipulation_replace);
-	praat_addAction1 (classDurationTier, 0, U"Query -", nullptr, 0, nullptr);
-		praat_TimeTier_query_init (classDurationTier);
-		praat_addAction1 (classDurationTier, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classDurationTier, 1, U"Get value at time...", nullptr, 1, DO_DurationTier_getValueAtTime);
-		praat_addAction1 (classDurationTier, 1, U"Get value at index...", nullptr, 1, DO_DurationTier_getValueAtIndex);
-		praat_addAction1 (classDurationTier, 1, U"Get target duration...", nullptr, 1, DO_DurationTier_getTargetDuration);
-	praat_addAction1 (classDurationTier, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeTier_modify_init (classDurationTier);
-		praat_addAction1 (classDurationTier, 0, U"Add point...", nullptr, 1, DO_DurationTier_addPoint);
-		praat_addAction1 (classDurationTier, 0, U"Formula...", nullptr, 1, DO_DurationTier_formula);
-praat_addAction1 (classDurationTier, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classDurationTier, 0, U"Down to PointProcess", nullptr, 0, DO_DurationTier_downto_PointProcess);
-
-	praat_addAction1 (classExcitation, 0, U"Excitation help", nullptr, 0, DO_Excitation_help);
+	praat_addAction1 (classDistributions, 1, U"To Transition...", nullptr, 0, NEW_Distributions_to_Transition);
+	praat_addAction1 (classDistributions, 2, U"To Transition (noise)...", nullptr, 0, NEW1_Distributions_to_Transition_noise);
+
+	praat_addAction1 (classExcitation, 0, U"Excitation help", nullptr, 0, HELP_Excitation_help);
 praat_addAction1 (classExcitation, 0, U"Draw", nullptr, 0, nullptr);
-	praat_addAction1 (classExcitation, 0, U"Draw...", nullptr, 0, DO_Excitation_draw);
+	praat_addAction1 (classExcitation, 0, U"Draw...", nullptr, 0, GRAPHICS_Excitation_draw);
 praat_addAction1 (classExcitation, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classExcitation, 0, U"To Formant...", nullptr, 0, DO_Excitation_to_Formant);
+	praat_addAction1 (classExcitation, 0, U"To Formant...", nullptr, 0, NEW_Excitation_to_Formant);
 praat_addAction1 (classExcitation, 1, U"Query -", nullptr, 0, nullptr);
-	praat_addAction1 (classExcitation, 1, U"Get loudness", nullptr, 0, DO_Excitation_getLoudness);
+	praat_addAction1 (classExcitation, 1, U"Get loudness", nullptr, 0, REAL_Excitation_getLoudness);
 praat_addAction1 (classExcitation, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classExcitation, 0, U"Formula...", nullptr, 0, DO_Excitation_formula);
+	praat_addAction1 (classExcitation, 0, U"Formula...", nullptr, 0, MODIFY_Excitation_formula);
 praat_addAction1 (classExcitation, 0, U"Hack", nullptr, 0, nullptr);
-	praat_addAction1 (classExcitation, 0, U"To Matrix", nullptr, 0, DO_Excitation_to_Matrix);
+	praat_addAction1 (classExcitation, 0, U"To Matrix", nullptr, 0, NEW_Excitation_to_Matrix);
 
-	praat_addAction1 (classFormant, 0, U"Formant help", nullptr, 0, DO_Formant_help);
+	praat_addAction1 (classFormant, 0, U"Formant help", nullptr, 0, HELP_Formant_help);
 	praat_addAction1 (classFormant, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classFormant, 0, U"Speckle...", nullptr, 1, DO_Formant_drawSpeckles);
-		praat_addAction1 (classFormant, 0, U"Draw tracks...", nullptr, 1, DO_Formant_drawTracks);
-		praat_addAction1 (classFormant, 0, U"Scatter plot...", nullptr, 1, DO_Formant_scatterPlot);
+		praat_addAction1 (classFormant, 0, U"Speckle...", nullptr, 1, GRAPHICS_Formant_drawSpeckles);
+		praat_addAction1 (classFormant, 0, U"Draw tracks...", nullptr, 1, GRAPHICS_Formant_drawTracks);
+		praat_addAction1 (classFormant, 0, U"Scatter plot...", nullptr, 1, GRAPHICS_Formant_scatterPlot);
 	praat_addAction1 (classFormant, 0, U"Tabulate -", nullptr, 0, nullptr);
-		praat_addAction1 (classFormant, 1, U"List...", nullptr, 1, DO_Formant_list);
-		praat_addAction1 (classFormant, 0, U"Down to Table...", nullptr, 1, DO_Formant_downto_Table);
+		praat_addAction1 (classFormant, 1, U"List...", nullptr, 1, LIST_Formant_list);
+		praat_addAction1 (classFormant, 0, U"Down to Table...", nullptr, 1, NEW_Formant_downto_Table);
 	praat_addAction1 (classFormant, 0, U"Query -", nullptr, 0, nullptr);
 		praat_TimeFrameSampled_query_init (classFormant);
-		praat_addAction1 (classFormant, 1, U"Get number of formants...", nullptr, 1, DO_Formant_getNumberOfFormants);
-		praat_addAction1 (classFormant, 1, U"Get minimum number of formants", nullptr, 1, DO_Formant_getMinimumNumberOfFormants);
-		praat_addAction1 (classFormant, 1, U"Get maximum number of formants", nullptr, 1, DO_Formant_getMaximumNumberOfFormants);
+		praat_addAction1 (classFormant, 1, U"Get number of formants...", nullptr, 1, INTEGER_Formant_getNumberOfFormants);
+		praat_addAction1 (classFormant, 1, U"Get minimum number of formants", nullptr, 1, INTEGER_Formant_getMinimumNumberOfFormants);
+		praat_addAction1 (classFormant, 1, U"Get maximum number of formants", nullptr, 1, INTEGER_Formant_getMaximumNumberOfFormants);
 		praat_addAction1 (classFormant, 1, U"-- get value --", nullptr, 1, nullptr);
-		praat_addAction1 (classFormant, 1, U"Get value at time...", nullptr, 1, DO_Formant_getValueAtTime);
-		praat_addAction1 (classFormant, 1, U"Get bandwidth at time...", nullptr, 1, DO_Formant_getBandwidthAtTime);
+		praat_addAction1 (classFormant, 1, U"Get value at time...", nullptr, 1, REAL_Formant_getValueAtTime);
+		praat_addAction1 (classFormant, 1, U"Get bandwidth at time...", nullptr, 1, REAL_Formant_getBandwidthAtTime);
 		praat_addAction1 (classFormant, 1, U"-- get extreme --", nullptr, 1, nullptr);
-		praat_addAction1 (classFormant, 1, U"Get minimum...", nullptr, 1, DO_Formant_getMinimum);
-		praat_addAction1 (classFormant, 1, U"Get time of minimum...", nullptr, 1, DO_Formant_getTimeOfMinimum);
-		praat_addAction1 (classFormant, 1, U"Get maximum...", nullptr, 1, DO_Formant_getMaximum);
-		praat_addAction1 (classFormant, 1, U"Get time of maximum...", nullptr, 1, DO_Formant_getTimeOfMaximum);
+		praat_addAction1 (classFormant, 1, U"Get minimum...", nullptr, 1, REAL_Formant_getMinimum);
+		praat_addAction1 (classFormant, 1, U"Get time of minimum...", nullptr, 1, REAL_Formant_getTimeOfMinimum);
+		praat_addAction1 (classFormant, 1, U"Get maximum...", nullptr, 1, REAL_Formant_getMaximum);
+		praat_addAction1 (classFormant, 1, U"Get time of maximum...", nullptr, 1, REAL_Formant_getTimeOfMaximum);
 		praat_addAction1 (classFormant, 1, U"-- get distribution --", nullptr, 1, nullptr);
-		praat_addAction1 (classFormant, 1, U"Get quantile...", nullptr, 1, DO_Formant_getQuantile);
-		praat_addAction1 (classFormant, 1, U"Get quantile of bandwidth...", nullptr, 1, DO_Formant_getQuantileOfBandwidth);
-		praat_addAction1 (classFormant, 1, U"Get mean...", nullptr, 1, DO_Formant_getMean);
-		praat_addAction1 (classFormant, 1, U"Get standard deviation...", nullptr, 1, DO_Formant_getStandardDeviation);
+		praat_addAction1 (classFormant, 1, U"Get quantile...", nullptr, 1, REAL_Formant_getQuantile);
+		praat_addAction1 (classFormant, 1, U"Get quantile of bandwidth...", nullptr, 1, REAL_Formant_getQuantileOfBandwidth);
+		praat_addAction1 (classFormant, 1, U"Get mean...", nullptr, 1, REAL_Formant_getMean);
+		praat_addAction1 (classFormant, 1, U"Get standard deviation...", nullptr, 1, REAL_Formant_getStandardDeviation);
 	praat_addAction1 (classFormant, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classFormant);
-		praat_addAction1 (classFormant, 0, U"Sort", nullptr, 1, DO_Formant_sort);
-		praat_addAction1 (classFormant, 0, U"Formula (frequencies)...", nullptr, 1, DO_Formant_formula_frequencies);
-		praat_addAction1 (classFormant, 0, U"Formula (bandwidths)...", nullptr, 1, DO_Formant_formula_bandwidths);
+		praat_addAction1 (classFormant, 0, U"Sort", nullptr, 1, MODIFY_Formant_sort);
+		praat_addAction1 (classFormant, 0, U"Formula (frequencies)...", nullptr, 1, MODIFY_Formant_formula_frequencies);
+		praat_addAction1 (classFormant, 0, U"Formula (bandwidths)...", nullptr, 1, MODIFY_Formant_formula_bandwidths);
 praat_addAction1 (classFormant, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classFormant, 0, U"Track...", nullptr, 0, DO_Formant_tracker);
-	praat_addAction1 (classFormant, 0, U"Down to FormantTier", nullptr, praat_HIDDEN, DO_Formant_downto_FormantTier);
-	praat_addAction1 (classFormant, 0, U"Down to FormantGrid", nullptr, 0, DO_Formant_downto_FormantGrid);
+	praat_addAction1 (classFormant, 0, U"Track...", nullptr, 0, NEW_Formant_tracker);
+	praat_addAction1 (classFormant, 0, U"Down to FormantTier", nullptr, praat_HIDDEN, NEW_Formant_downto_FormantTier);
+	praat_addAction1 (classFormant, 0, U"Down to FormantGrid", nullptr, 0, NEW_Formant_downto_FormantGrid);
 praat_addAction1 (classFormant, 0, U"Hack", nullptr, 0, nullptr);
-	praat_addAction1 (classFormant, 0, U"To Matrix...", nullptr, 0, DO_Formant_to_Matrix);
-
-	praat_addAction1 (classFormantGrid, 0, U"FormantGrid help", nullptr, 0, DO_FormantGrid_help);
-	praat_addAction1 (classFormantGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_FormantGrid_edit);
-	praat_addAction1 (classFormantGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_FormantGrid_edit);
-	praat_addAction1 (classFormantGrid, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeFunction_modify_init (classFormantGrid);
-		praat_addAction1 (classFormantGrid, 0, U"Formula (frequencies)...", nullptr, 1, DO_FormantGrid_formula_frequencies);
-		//praat_addAction1 (classFormantGrid, 0, U"Formula (bandwidths)...", nullptr, 1, DO_FormantGrid_formula_bandwidths);
-		praat_addAction1 (classFormantGrid, 0, U"Add formant point...", nullptr, 1, DO_FormantGrid_addFormantPoint);
-		praat_addAction1 (classFormantGrid, 0, U"Add bandwidth point...", nullptr, 1, DO_FormantGrid_addBandwidthPoint);
-		praat_addAction1 (classFormantGrid, 0, U"Remove formant points between...", nullptr, 1, DO_FormantGrid_removeFormantPointsBetween);
-		praat_addAction1 (classFormantGrid, 0, U"Remove bandwidth points between...", nullptr, 1, DO_FormantGrid_removeBandwidthPointsBetween);
-	praat_addAction1 (classFormantGrid, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (classFormantGrid, 0, U"To Formant...", nullptr, 1, DO_FormantGrid_to_Formant);
-
-	praat_addAction1 (classFormantTier, 0, U"FormantTier help", nullptr, 0, DO_FormantTier_help);
-	praat_addAction1 (classFormantTier, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classFormantTier, 0, U"Speckle...", nullptr, 1, DO_FormantTier_speckle);
-	praat_addAction1 (classFormantTier, 0, U"Query -", nullptr, 0, nullptr);
-		praat_TimeTier_query_init (classFormantTier);
-		praat_addAction1 (classFormantTier, 1, U"-- get value --", nullptr, 1, nullptr);
-		praat_addAction1 (classFormantTier, 1, U"Get value at time...", nullptr, 1, DO_FormantTier_getValueAtTime);
-		praat_addAction1 (classFormantTier, 1, U"Get bandwidth at time...", nullptr, 1, DO_FormantTier_getBandwidthAtTime);
-	praat_addAction1 (classFormantTier, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeTier_modify_init (classFormantTier);
-		praat_addAction1 (classFormantTier, 0, U"Add point...", nullptr, 1, DO_FormantTier_addPoint);
-praat_addAction1 (classFormantTier, 0, U"Down", nullptr, 0, nullptr);
-	praat_addAction1 (classFormantTier, 0, U"Down to TableOfReal...", nullptr, 0, DO_FormantTier_downto_TableOfReal);
-
-	praat_addAction1 (classHarmonicity, 0, U"Harmonicity help", nullptr, 0, DO_Harmonicity_help);
+	praat_addAction1 (classFormant, 0, U"To Matrix...", nullptr, 0, NEW_Formant_to_Matrix);
+
+	praat_addAction1 (classHarmonicity, 0, U"Harmonicity help", nullptr, 0, HELP_Harmonicity_help);
 	praat_addAction1 (classHarmonicity, 0, U"Draw", nullptr, 0, nullptr);
-		praat_addAction1 (classHarmonicity, 0, U"Draw...", nullptr, 0, DO_Harmonicity_draw);
+		praat_addAction1 (classHarmonicity, 0, U"Draw...", nullptr, 0, GRAPHICS_Harmonicity_draw);
 	praat_addAction1 (classHarmonicity, 1, U"Query -", nullptr, 0, nullptr);
 		praat_TimeFrameSampled_query_init (classHarmonicity);
 		praat_addAction1 (classHarmonicity, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classHarmonicity, 1, U"Get value at time...", nullptr, 1, DO_Harmonicity_getValueAtTime);
-		praat_addAction1 (classHarmonicity, 1, U"Get value in frame...", nullptr, 1, DO_Harmonicity_getValueInFrame);
+		praat_addAction1 (classHarmonicity, 1, U"Get value at time...", nullptr, 1, REAL_Harmonicity_getValueAtTime);
+		praat_addAction1 (classHarmonicity, 1, U"Get value in frame...", nullptr, 1, REAL_Harmonicity_getValueInFrame);
 		praat_addAction1 (classHarmonicity, 1, U"-- get extreme --", nullptr, 1, nullptr);
-		praat_addAction1 (classHarmonicity, 1, U"Get minimum...", nullptr, 1, DO_Harmonicity_getMinimum);
-		praat_addAction1 (classHarmonicity, 1, U"Get time of minimum...", nullptr, 1, DO_Harmonicity_getTimeOfMinimum);
-		praat_addAction1 (classHarmonicity, 1, U"Get maximum...", nullptr, 1, DO_Harmonicity_getMaximum);
-		praat_addAction1 (classHarmonicity, 1, U"Get time of maximum...", nullptr, 1, DO_Harmonicity_getTimeOfMaximum);
+		praat_addAction1 (classHarmonicity, 1, U"Get minimum...", nullptr, 1, REAL_Harmonicity_getMinimum);
+		praat_addAction1 (classHarmonicity, 1, U"Get time of minimum...", nullptr, 1, REAL_Harmonicity_getTimeOfMinimum);
+		praat_addAction1 (classHarmonicity, 1, U"Get maximum...", nullptr, 1, REAL_Harmonicity_getMaximum);
+		praat_addAction1 (classHarmonicity, 1, U"Get time of maximum...", nullptr, 1, REAL_Harmonicity_getTimeOfMaximum);
 		praat_addAction1 (classHarmonicity, 1, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classHarmonicity, 1, U"Get mean...", nullptr, 1, DO_Harmonicity_getMean);
-		praat_addAction1 (classHarmonicity, 1, U"Get standard deviation...", nullptr, 1, DO_Harmonicity_getStandardDeviation);
+		praat_addAction1 (classHarmonicity, 1, U"Get mean...", nullptr, 1, REAL_Harmonicity_getMean);
+		praat_addAction1 (classHarmonicity, 1, U"Get standard deviation...", nullptr, 1, REAL_Harmonicity_getStandardDeviation);
 	praat_addAction1 (classHarmonicity, 0, U"Modify", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classHarmonicity);
-		praat_addAction1 (classHarmonicity, 0, U"Formula...", nullptr, 0, DO_Harmonicity_formula);
+		praat_addAction1 (classHarmonicity, 0, U"Formula...", nullptr, 0, MODIFY_Harmonicity_formula);
 	praat_addAction1 (classHarmonicity, 0, U"Hack", nullptr, 0, nullptr);
-		praat_addAction1 (classHarmonicity, 0, U"To Matrix", nullptr, 0, DO_Harmonicity_to_Matrix);
+		praat_addAction1 (classHarmonicity, 0, U"To Matrix", nullptr, 0, NEW_Harmonicity_to_Matrix);
 
-	praat_addAction1 (classIntensity, 0, U"Intensity help", nullptr, 0, DO_Intensity_help);
-	praat_addAction1 (classIntensity, 0, U"Draw...", nullptr, 0, DO_Intensity_draw);
+	praat_addAction1 (classIntensity, 0, U"Intensity help", nullptr, 0, HELP_Intensity_help);
+	praat_addAction1 (classIntensity, 0, U"Draw...", nullptr, 0, GRAPHICS_Intensity_draw);
 	praat_addAction1 (classIntensity, 1, U"Query -", nullptr, 0, nullptr);
 		praat_TimeFrameSampled_query_init (classIntensity);
 		praat_addAction1 (classIntensity, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classIntensity, 1, U"Get value at time...", nullptr, 1, DO_Intensity_getValueAtTime);
-		praat_addAction1 (classIntensity, 1, U"Get value in frame...", nullptr, 1, DO_Intensity_getValueInFrame);
+		praat_addAction1 (classIntensity, 1, U"Get value at time...", nullptr, 1, REAL_Intensity_getValueAtTime);
+		praat_addAction1 (classIntensity, 1, U"Get value in frame...", nullptr, 1, REAL_Intensity_getValueInFrame);
 		praat_addAction1 (classIntensity, 1, U"-- get extreme --", nullptr, 1, nullptr);
-		praat_addAction1 (classIntensity, 1, U"Get minimum...", nullptr, 1, DO_Intensity_getMinimum);
-		praat_addAction1 (classIntensity, 1, U"Get time of minimum...", nullptr, 1, DO_Intensity_getTimeOfMinimum);
-		praat_addAction1 (classIntensity, 1, U"Get maximum...", nullptr, 1, DO_Intensity_getMaximum);
-		praat_addAction1 (classIntensity, 1, U"Get time of maximum...", nullptr, 1, DO_Intensity_getTimeOfMaximum);
+		praat_addAction1 (classIntensity, 1, U"Get minimum...", nullptr, 1, REAL_Intensity_getMinimum);
+		praat_addAction1 (classIntensity, 1, U"Get time of minimum...", nullptr, 1, REAL_Intensity_getTimeOfMinimum);
+		praat_addAction1 (classIntensity, 1, U"Get maximum...", nullptr, 1, REAL_Intensity_getMaximum);
+		praat_addAction1 (classIntensity, 1, U"Get time of maximum...", nullptr, 1, REAL_Intensity_getTimeOfMaximum);
 		praat_addAction1 (classIntensity, 1, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classIntensity, 1, U"Get quantile...", nullptr, 1, DO_Intensity_getQuantile);
-		praat_addAction1 (classIntensity, 1, U"Get mean...", nullptr, 1, DO_Intensity_getMean);
-		praat_addAction1 (classIntensity, 1, U"Get standard deviation...", nullptr, 1, DO_Intensity_getStandardDeviation);
+		praat_addAction1 (classIntensity, 1, U"Get quantile...", nullptr, 1, REAL_Intensity_getQuantile);
+		praat_addAction1 (classIntensity, 1, U"Get mean...", nullptr, 1, REAL_Intensity_getMean);
+		praat_addAction1 (classIntensity, 1, U"Get standard deviation...", nullptr, 1, REAL_Intensity_getStandardDeviation);
 	praat_addAction1 (classIntensity, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classIntensity);
-		praat_addAction1 (classIntensity, 0, U"Formula...", nullptr, 1, DO_Intensity_formula);
+		praat_addAction1 (classIntensity, 0, U"Formula...", nullptr, 1, MODIFY_Intensity_formula);
 	praat_addAction1 (classIntensity, 0, U"Analyse", nullptr, 0, nullptr);
-		praat_addAction1 (classIntensity, 0, U"To IntensityTier (peaks)", nullptr, 0, DO_Intensity_to_IntensityTier_peaks);
-		praat_addAction1 (classIntensity, 0, U"To IntensityTier (valleys)", nullptr, 0, DO_Intensity_to_IntensityTier_valleys);
+		praat_addAction1 (classIntensity, 0, U"To IntensityTier (peaks)", nullptr, 0, NEW_Intensity_to_IntensityTier_peaks);
+		praat_addAction1 (classIntensity, 0, U"To IntensityTier (valleys)", nullptr, 0, NEW_Intensity_to_IntensityTier_valleys);
 	praat_addAction1 (classIntensity, 0, U"Convert", nullptr, 0, nullptr);
-		praat_addAction1 (classIntensity, 0, U"Down to IntensityTier", nullptr, 0, DO_Intensity_downto_IntensityTier);
-		praat_addAction1 (classIntensity, 0, U"Down to Matrix", nullptr, 0, DO_Intensity_downto_Matrix);
-
-	praat_addAction1 (classIntensityTier, 0, U"IntensityTier help", nullptr, 0, DO_IntensityTier_help);
-	praat_addAction1 (classIntensityTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_IntensityTier_edit);
-	praat_addAction1 (classIntensityTier, 1, U"Edit", nullptr, praat_HIDDEN, DO_IntensityTier_edit);
-	praat_addAction1 (classIntensityTier, 0, U"View & Edit with Sound?", nullptr, 0, DO_info_IntensityTier_Sound_edit);
-	praat_addAction1 (classIntensityTier, 0, U"Query -", nullptr, 0, nullptr);
-		praat_TimeTier_query_init (classIntensityTier);
-		praat_addAction1 (classIntensityTier, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classIntensityTier, 1, U"Get value at time...", nullptr, 1, DO_IntensityTier_getValueAtTime);
-		praat_addAction1 (classIntensityTier, 1, U"Get value at index...", nullptr, 1, DO_IntensityTier_getValueAtIndex);
-	praat_addAction1 (classIntensityTier, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeTier_modify_init (classIntensityTier);
-		praat_addAction1 (classIntensityTier, 0, U"Add point...", nullptr, 1, DO_IntensityTier_addPoint);
-		praat_addAction1 (classIntensityTier, 0, U"Formula...", nullptr, 1, DO_IntensityTier_formula);
-praat_addAction1 (classIntensityTier, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classIntensityTier, 0, U"To AmplitudeTier", nullptr, 0, DO_IntensityTier_to_AmplitudeTier);
-	praat_addAction1 (classIntensityTier, 0, U"Down to PointProcess", nullptr, 0, DO_IntensityTier_downto_PointProcess);
-	praat_addAction1 (classIntensityTier, 0, U"Down to TableOfReal", nullptr, 0, DO_IntensityTier_downto_TableOfReal);
-
-	praat_addAction1 (classLtas, 0, U"Ltas help", nullptr, 0, DO_Ltas_help);
-	praat_addAction1 (classLtas, 0, U"Draw...", nullptr, 0, DO_Ltas_draw);
+		praat_addAction1 (classIntensity, 0, U"Down to IntensityTier", nullptr, 0, NEW_Intensity_downto_IntensityTier);
+		praat_addAction1 (classIntensity, 0, U"Down to Matrix", nullptr, 0, NEW_Intensity_downto_Matrix);
+
+	praat_addAction1 (classLtas, 0, U"Ltas help", nullptr, 0, HELP_Ltas_help);
+	praat_addAction1 (classLtas, 0, U"Draw...", nullptr, 0, GRAPHICS_Ltas_draw);
 	praat_addAction1 (classLtas, 1, U"Query -", nullptr, 0, nullptr);
 		praat_addAction1 (classLtas, 1, U"Frequency domain", nullptr, 1, nullptr);
-		praat_addAction1 (classLtas, 1, U"Get lowest frequency", nullptr, 2, DO_Ltas_getLowestFrequency);
-		praat_addAction1 (classLtas, 1, U"Get highest frequency", nullptr, 2, DO_Ltas_getHighestFrequency);
+		praat_addAction1 (classLtas, 1, U"Get lowest frequency", nullptr, 2, REAL_Ltas_getLowestFrequency);
+		praat_addAction1 (classLtas, 1, U"Get highest frequency", nullptr, 2, REAL_Ltas_getHighestFrequency);
 		praat_addAction1 (classLtas, 1, U"Frequency sampling", nullptr, 1, nullptr);
-		praat_addAction1 (classLtas, 1, U"Get number of bins", nullptr, 2, DO_Ltas_getNumberOfBins);
-			praat_addAction1 (classLtas, 1, U"Get number of bands", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getNumberOfBins);
-		praat_addAction1 (classLtas, 1, U"Get bin width", nullptr, 2, DO_Ltas_getBinWidth);
-			praat_addAction1 (classLtas, 1, U"Get band width", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getBinWidth);
-		praat_addAction1 (classLtas, 1, U"Get frequency from bin number...", nullptr, 2, DO_Ltas_getFrequencyFromBinNumber);
-			praat_addAction1 (classLtas, 1, U"Get frequency from band...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getFrequencyFromBinNumber);
-		praat_addAction1 (classLtas, 1, U"Get bin number from frequency...", nullptr, 2, DO_Ltas_getBinNumberFromFrequency);
-			praat_addAction1 (classLtas, 1, U"Get band from frequency...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Ltas_getBinNumberFromFrequency);
+		praat_addAction1 (classLtas, 1, U"Get number of bins", nullptr, 2, INTEGER_Ltas_getNumberOfBins);
+			praat_addAction1 (classLtas, 1, U"Get number of bands", U"*Get number of bins", praat_DEPTH_2 | praat_DEPRECATED_2004, INTEGER_Ltas_getNumberOfBins);
+		praat_addAction1 (classLtas, 1, U"Get bin width", nullptr, 2, REAL_Ltas_getBinWidth);
+			praat_addAction1 (classLtas, 1, U"Get band width", U"*Get bin width", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Ltas_getBinWidth);
+		praat_addAction1 (classLtas, 1, U"Get frequency from bin number...", nullptr, 2, REAL_Ltas_getFrequencyFromBinNumber);
+			praat_addAction1 (classLtas, 1, U"Get frequency from band...", U"*Get frequency from bin number...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Ltas_getFrequencyFromBinNumber);
+		praat_addAction1 (classLtas, 1, U"Get bin number from frequency...", nullptr, 2, REAL_Ltas_getBinNumberFromFrequency);
+			praat_addAction1 (classLtas, 1, U"Get band from frequency...", U"*Get bin number from frequency...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Ltas_getBinNumberFromFrequency);
 		praat_addAction1 (classLtas, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classLtas, 1, U"Get value at frequency...", nullptr, 1, DO_Ltas_getValueAtFrequency);
-		praat_addAction1 (classLtas, 1, U"Get value in bin...", nullptr, 1, DO_Ltas_getValueInBin);
-			praat_addAction1 (classLtas, 1, U"Get value in band...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Ltas_getValueInBin);
+		praat_addAction1 (classLtas, 1, U"Get value at frequency...", nullptr, 1, REAL_Ltas_getValueAtFrequency);
+		praat_addAction1 (classLtas, 1, U"Get value in bin...", nullptr, 1, REAL_Ltas_getValueInBin);
+			praat_addAction1 (classLtas, 1, U"Get value in band...", U"*Get value in bin...", praat_DEPTH_1 | praat_DEPRECATED_2004, REAL_Ltas_getValueInBin);
 		praat_addAction1 (classLtas, 1, U"-- get extreme --", nullptr, 1, nullptr);
-		praat_addAction1 (classLtas, 1, U"Get minimum...", nullptr, 1, DO_Ltas_getMinimum);
-		praat_addAction1 (classLtas, 1, U"Get frequency of minimum...", nullptr, 1, DO_Ltas_getFrequencyOfMinimum);
-		praat_addAction1 (classLtas, 1, U"Get maximum...", nullptr, 1, DO_Ltas_getMaximum);
-		praat_addAction1 (classLtas, 1, U"Get frequency of maximum...", nullptr, 1, DO_Ltas_getFrequencyOfMaximum);
+		praat_addAction1 (classLtas, 1, U"Get minimum...", nullptr, 1, REAL_Ltas_getMinimum);
+		praat_addAction1 (classLtas, 1, U"Get frequency of minimum...", nullptr, 1, REAL_Ltas_getFrequencyOfMinimum);
+		praat_addAction1 (classLtas, 1, U"Get maximum...", nullptr, 1, REAL_Ltas_getMaximum);
+		praat_addAction1 (classLtas, 1, U"Get frequency of maximum...", nullptr, 1, REAL_Ltas_getFrequencyOfMaximum);
 		praat_addAction1 (classLtas, 1, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classLtas, 1, U"Get mean...", nullptr, 1, DO_Ltas_getMean);
-		praat_addAction1 (classLtas, 1, U"Get slope...", nullptr, 1, DO_Ltas_getSlope);
-		praat_addAction1 (classLtas, 1, U"Get local peak height...", nullptr, 1, DO_Ltas_getLocalPeakHeight);
-		praat_addAction1 (classLtas, 1, U"Get standard deviation...", nullptr, 1, DO_Ltas_getStandardDeviation);
+		praat_addAction1 (classLtas, 1, U"Get mean...", nullptr, 1, REAL_Ltas_getMean);
+		praat_addAction1 (classLtas, 1, U"Get slope...", nullptr, 1, REAL_Ltas_getSlope);
+		praat_addAction1 (classLtas, 1, U"Get local peak height...", nullptr, 1, REAL_Ltas_getLocalPeakHeight);
+		praat_addAction1 (classLtas, 1, U"Get standard deviation...", nullptr, 1, REAL_Ltas_getStandardDeviation);
 	praat_addAction1 (classLtas, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classLtas, 0, U"Formula...", nullptr, 0, DO_Ltas_formula);
+	praat_addAction1 (classLtas, 0, U"Formula...", nullptr, 0, MODIFY_Ltas_formula);
 	praat_addAction1 (classLtas, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classLtas, 0, U"To SpectrumTier (peaks)", nullptr, 0, DO_Ltas_to_SpectrumTier_peaks);
+	praat_addAction1 (classLtas, 0, U"To SpectrumTier (peaks)", nullptr, 0, NEW_Ltas_to_SpectrumTier_peaks);
 	praat_addAction1 (classLtas, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classLtas, 0, U"Compute trend line...", nullptr, 0, DO_Ltas_computeTrendLine);
-	praat_addAction1 (classLtas, 0, U"Subtract trend line...", nullptr, 0, DO_Ltas_subtractTrendLine);
+	praat_addAction1 (classLtas, 0, U"Compute trend line...", nullptr, 0, NEW_Ltas_computeTrendLine);
+	praat_addAction1 (classLtas, 0, U"Subtract trend line...", nullptr, 0, NEW_Ltas_subtractTrendLine);
 	praat_addAction1 (classLtas, 0, U"Combine", nullptr, 0, nullptr);
-	praat_addAction1 (classLtas, 0, U"Merge", nullptr, praat_HIDDEN, DO_Ltases_merge);
-	praat_addAction1 (classLtas, 0, U"Average", nullptr, 0, DO_Ltases_average);
+	praat_addAction1 (classLtas, 0, U"Merge", nullptr, praat_DEPRECATED_2005, NEW1_Ltases_merge);
+	praat_addAction1 (classLtas, 0, U"Average", nullptr, 0, NEW1_Ltases_average);
 	praat_addAction1 (classLtas, 0, U"Hack", nullptr, 0, nullptr);
-	praat_addAction1 (classLtas, 0, U"To Matrix", nullptr, 0, DO_Ltas_to_Matrix);
-
-	praat_addAction1 (classManipulation, 0, U"Manipulation help", nullptr, 0, DO_Manipulation_help);
-	praat_addAction1 (classManipulation, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Manipulation_edit);
-	praat_addAction1 (classManipulation, 1, U"Edit", nullptr, praat_HIDDEN, DO_Manipulation_edit);
-	praat_addAction1 (classManipulation, 0, U"Play (overlap-add)", nullptr, 0, DO_Manipulation_play_overlapAdd);
-	praat_addAction1 (classManipulation, 0, U"Play (PSOLA)", nullptr, praat_HIDDEN, DO_Manipulation_play_overlapAdd);
-	praat_addAction1 (classManipulation, 0, U"Play (LPC)", nullptr, 0, DO_Manipulation_play_lpc);
-	praat_addAction1 (classManipulation, 0, U"Get resynthesis (overlap-add)", nullptr, 0, DO_Manipulation_getResynthesis_overlapAdd);
-	praat_addAction1 (classManipulation, 0, U"Get resynthesis (PSOLA)", nullptr, praat_HIDDEN, DO_Manipulation_getResynthesis_overlapAdd);
-	praat_addAction1 (classManipulation, 0, U"Get resynthesis (LPC)", nullptr, 0, DO_Manipulation_getResynthesis_lpc);
-	praat_addAction1 (classManipulation, 0, U"Extract original sound", nullptr, 0, DO_Manipulation_extractOriginalSound);
-	praat_addAction1 (classManipulation, 0, U"Extract pulses", nullptr, 0, DO_Manipulation_extractPulses);
-	praat_addAction1 (classManipulation, 0, U"Extract pitch tier", nullptr, 0, DO_Manipulation_extractPitchTier);
-	praat_addAction1 (classManipulation, 0, U"Extract duration tier", nullptr, 0, DO_Manipulation_extractDurationTier);
+	praat_addAction1 (classLtas, 0, U"To Matrix", nullptr, 0, NEW_Ltas_to_Matrix);
+
+	praat_addAction1 (classManipulation, 0, U"Manipulation help", nullptr, 0, HELP_Manipulation_help);
+	praat_addAction1 (classManipulation, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Manipulation_viewAndEdit);
+	praat_addAction1 (classManipulation, 1,   U"Edit", nullptr, praat_DEPRECATED_2011, WINDOW_Manipulation_viewAndEdit);
+	praat_addAction1 (classManipulation, 0, U"Play (overlap-add)", nullptr, 0, PLAY_Manipulation_play_overlapAdd);
+	praat_addAction1 (classManipulation, 0,   U"Play (PSOLA)", nullptr, praat_DEPRECATED_2007, PLAY_Manipulation_play_overlapAdd);
+	praat_addAction1 (classManipulation, 0, U"Play (LPC)", nullptr, 0, PLAY_Manipulation_play_lpc);
+	praat_addAction1 (classManipulation, 0, U"Get resynthesis (overlap-add)", nullptr, 0, NEW_Manipulation_getResynthesis_overlapAdd);
+	praat_addAction1 (classManipulation, 0,   U"Get resynthesis (PSOLA)", U"*Get resynthesis (overlap-add)", praat_DEPRECATED_2007, NEW_Manipulation_getResynthesis_overlapAdd);
+	praat_addAction1 (classManipulation, 0, U"Get resynthesis (LPC)", nullptr, 0, NEW_Manipulation_getResynthesis_lpc);
+	praat_addAction1 (classManipulation, 0, U"Extract original sound", nullptr, 0, NEW_Manipulation_extractOriginalSound);
+	praat_addAction1 (classManipulation, 0, U"Extract pulses", nullptr, 0, NEW_Manipulation_extractPulses);
+	praat_addAction1 (classManipulation, 0, U"Extract pitch tier", nullptr, 0, NEW_Manipulation_extractPitchTier);
+	praat_addAction1 (classManipulation, 0, U"Extract duration tier", nullptr, 0, NEW_Manipulation_extractDurationTier);
 	praat_addAction1 (classManipulation, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classManipulation);
-		praat_addAction1 (classManipulation, 0, U"Replace pitch tier?", nullptr, 1, DO_Manipulation_replacePitchTier_help);
-		praat_addAction1 (classManipulation, 0, U"Replace duration tier?", nullptr, 1, DO_Manipulation_replaceDurationTier_help);
-	praat_addAction1 (classManipulation, 1, U"Save as text file without Sound...", nullptr, 0, DO_Manipulation_writeToTextFileWithoutSound);
-	praat_addAction1 (classManipulation, 1, U"Write to text file without Sound...", nullptr, praat_HIDDEN, DO_Manipulation_writeToTextFileWithoutSound);
-	praat_addAction1 (classManipulation, 1, U"Save as binary file without Sound...", nullptr, 0, DO_Manipulation_writeToBinaryFileWithoutSound);
-	praat_addAction1 (classManipulation, 1, U"Write to binary file without Sound...", nullptr, praat_HIDDEN, DO_Manipulation_writeToBinaryFileWithoutSound);
-
-	praat_addAction1 (classMatrix, 0, U"Matrix help", nullptr, 0, DO_Matrix_help);
-	praat_addAction1 (classMatrix, 1, U"Save as matrix text file...", nullptr, 0, DO_Matrix_writeToMatrixTextFile);
-	praat_addAction1 (classMatrix, 1, U"Write to matrix text file...", nullptr, praat_HIDDEN, DO_Matrix_writeToMatrixTextFile);
-	praat_addAction1 (classMatrix, 1, U"Save as headerless spreadsheet file...", nullptr, 0, DO_Matrix_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (classMatrix, 1, U"Write to headerless spreadsheet file...", nullptr, praat_HIDDEN, DO_Matrix_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (classMatrix, 1, U"Play movie", nullptr, 0, DO_Matrix_movie);
-	praat_addAction1 (classMatrix, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classMatrix, 0, U"Draw rows...", nullptr, 1, DO_Matrix_drawRows);
-		praat_addAction1 (classMatrix, 0, U"Draw one contour...", nullptr, 1, DO_Matrix_drawOneContour);
-		praat_addAction1 (classMatrix, 0, U"Draw contours...", nullptr, 1, DO_Matrix_drawContours);
-		praat_addAction1 (classMatrix, 0, U"Paint image...", nullptr, 1, DO_Matrix_paintImage);
-		praat_addAction1 (classMatrix, 0, U"Paint contours...", nullptr, 1, DO_Matrix_paintContours);
-		praat_addAction1 (classMatrix, 0, U"Paint cells...", nullptr, 1, DO_Matrix_paintCells);
-		praat_addAction1 (classMatrix, 0, U"Paint surface...", nullptr, 1, DO_Matrix_paintSurface);
-	praat_addAction1 (classMatrix, 1, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classMatrix, 1, U"Get lowest x", nullptr, 1, DO_Matrix_getLowestX);
-		praat_addAction1 (classMatrix, 1, U"Get highest x", nullptr, 1, DO_Matrix_getHighestX);
-		praat_addAction1 (classMatrix, 1, U"Get lowest y", nullptr, 1, DO_Matrix_getLowestY);
-		praat_addAction1 (classMatrix, 1, U"Get highest y", nullptr, 1, DO_Matrix_getHighestY);
-		praat_addAction1 (classMatrix, 1, U"-- get structure --", nullptr, 1, nullptr);
-		praat_addAction1 (classMatrix, 1, U"Get number of rows", nullptr, 1, DO_Matrix_getNumberOfRows);
-		praat_addAction1 (classMatrix, 1, U"Get number of columns", nullptr, 1, DO_Matrix_getNumberOfColumns);
-		praat_addAction1 (classMatrix, 1, U"Get row distance", nullptr, 1, DO_Matrix_getRowDistance);
-		praat_addAction1 (classMatrix, 1, U"Get column distance", nullptr, 1, DO_Matrix_getColumnDistance);
-		praat_addAction1 (classMatrix, 1, U"Get y of row...", nullptr, 1, DO_Matrix_getYofRow);
-		praat_addAction1 (classMatrix, 1, U"Get x of column...", nullptr, 1, DO_Matrix_getXofColumn);
-		praat_addAction1 (classMatrix, 1, U"-- get value --", nullptr, 1, nullptr);
-		praat_addAction1 (classMatrix, 1, U"Get value in cell...", nullptr, 1, DO_Matrix_getValueInCell);
-		praat_addAction1 (classMatrix, 1, U"Get value at xy...", nullptr, 1, DO_Matrix_getValueAtXY);
-		praat_addAction1 (classMatrix, 1, U"Get minimum", nullptr, 1, DO_Matrix_getMinimum);
-		praat_addAction1 (classMatrix, 1, U"Get maximum", nullptr, 1, DO_Matrix_getMaximum);
-		praat_addAction1 (classMatrix, 1, U"Get sum", nullptr, 1, DO_Matrix_getSum);
-	praat_addAction1 (classMatrix, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classMatrix, 0, U"Formula...", nullptr, 1, DO_Matrix_formula);
-		praat_addAction1 (classMatrix, 0, U"Set value...", nullptr, 1, DO_Matrix_setValue);
-praat_addAction1 (classMatrix, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classMatrix, 0, U"Eigen", nullptr, 0, DO_Matrix_eigen);
-	praat_addAction1 (classMatrix, 0, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction1 (classMatrix, 0, U"Power...", nullptr, 0, DO_Matrix_power);
-	praat_addAction1 (classMatrix, 0, U"Combine two Matrices -", nullptr, 0, nullptr);
-		praat_addAction1 (classMatrix, 2, U"Merge (append rows)", nullptr, 1, DO_Matrix_appendRows);
-		praat_addAction1 (classMatrix, 2, U"To ParamCurve", nullptr, 1, DO_Matrix_to_ParamCurve);
-	praat_addAction1 (classMatrix, 0, U"Cast -", nullptr, 0, nullptr);
-		praat_addAction1 (classMatrix, 0, U"To Cochleagram", nullptr, 1, DO_Matrix_to_Cochleagram);
-		praat_addAction1 (classMatrix, 0, U"To Excitation", nullptr, 1, DO_Matrix_to_Excitation);
-		praat_addAction1 (classMatrix, 0, U"To Harmonicity", nullptr, 1, DO_Matrix_to_Harmonicity);
-		praat_addAction1 (classMatrix, 0, U"To Intensity", nullptr, 1, DO_Matrix_to_Intensity);
-		praat_addAction1 (classMatrix, 0, U"To Ltas", nullptr, 1, DO_Matrix_to_Ltas);
-		praat_addAction1 (classMatrix, 0, U"To Pitch", nullptr, 1, DO_Matrix_to_Pitch);
-		praat_addAction1 (classMatrix, 0, U"To PointProcess", nullptr, 1, DO_Matrix_to_PointProcess);
-		praat_addAction1 (classMatrix, 0, U"To Polygon", nullptr, 1, DO_Matrix_to_Polygon);
-		praat_addAction1 (classMatrix, 0, U"To Sound", nullptr, 1, DO_Matrix_to_Sound);
-		praat_addAction1 (classMatrix, 0, U"To Sound (slice)...", nullptr, 1, DO_Matrix_to_Sound_mono);
-		praat_addAction1 (classMatrix, 0, U"To Spectrogram", nullptr, 1, DO_Matrix_to_Spectrogram);
-		praat_addAction1 (classMatrix, 0, U"To TableOfReal", nullptr, 1, DO_Matrix_to_TableOfReal);
-		praat_addAction1 (classMatrix, 0, U"To Spectrum", nullptr, 1, DO_Matrix_to_Spectrum);
-		praat_addAction1 (classMatrix, 0, U"To Transition", nullptr, 1, DO_Matrix_to_Transition);
-		praat_addAction1 (classMatrix, 0, U"To VocalTract", nullptr, 1, DO_Matrix_to_VocalTract);
-
-	praat_addAction1 (classMovie, 1, U"Paint one image...", nullptr, 1, DO_Movie_paintOneImage);
-	praat_addAction1 (classMovie, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Movie_viewAndEdit);
-
-	praat_addAction1 (classParamCurve, 0, U"ParamCurve help", nullptr, 0, DO_ParamCurve_help);
+		praat_addAction1 (classManipulation, 0, U"Replace pitch tier?", nullptr, 1, HELP_Manipulation_replacePitchTier_help);
+		praat_addAction1 (classManipulation, 0, U"Replace duration tier?", nullptr, 1, HELP_Manipulation_replaceDurationTier_help);
+	praat_addAction1 (classManipulation, 1, U"Save as text file without Sound...", nullptr, 0, SAVE_Manipulation_writeToTextFileWithoutSound);
+	praat_addAction1 (classManipulation, 1,   U"Write to text file without Sound...", U"*Save as text file without Sound...", praat_DEPRECATED_2011, SAVE_Manipulation_writeToTextFileWithoutSound);
+	praat_addAction1 (classManipulation, 1, U"Save as binary file without Sound...", nullptr, 0, SAVE_Manipulation_writeToBinaryFileWithoutSound);
+	praat_addAction1 (classManipulation, 1,   U"Write to binary file without Sound...", U"*Save as binary file without Sound...", praat_DEPRECATED_2011, SAVE_Manipulation_writeToBinaryFileWithoutSound);
+
+	praat_addAction1 (classParamCurve, 0, U"ParamCurve help", nullptr, 0, HELP_ParamCurve_help);
 	praat_addAction1 (classParamCurve, 0, U"Draw", nullptr, 0, nullptr);
-	praat_addAction1 (classParamCurve, 0, U"Draw...", nullptr, 0, DO_ParamCurve_draw);
-
-	praat_addAction1 (classPhoto, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classPhoto, 0, U"Paint image...", nullptr, 1, DO_Photo_paintImage);
-		praat_addAction1 (classPhoto, 0, U"Paint cells...", nullptr, 1, DO_Photo_paintCells);
-	praat_addAction1 (classPhoto, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classPhoto, 0, U"Formula (red)...", nullptr, 1, DO_Photo_formula_red);
-		praat_addAction1 (classPhoto, 0, U"Formula (green)...", nullptr, 1, DO_Photo_formula_green);
-		praat_addAction1 (classPhoto, 0, U"Formula (blue)...", nullptr, 1, DO_Photo_formula_blue);
-		praat_addAction1 (classPhoto, 0, U"Formula (transparency)...", nullptr, 1, DO_Photo_formula_transparency);
-	praat_addAction1 (classPhoto, 0, U"Extract -", nullptr, 0, nullptr);
-		praat_addAction1 (classPhoto, 0, U"Extract red", nullptr, 1, DO_Photo_extractRed);
-		praat_addAction1 (classPhoto, 0, U"Extract green", nullptr, 1, DO_Photo_extractGreen);
-		praat_addAction1 (classPhoto, 0, U"Extract blue", nullptr, 1, DO_Photo_extractBlue);
-		praat_addAction1 (classPhoto, 0, U"Extract transparency", nullptr, 1, DO_Photo_extractTransparency);
-	praat_addAction1 (classPhoto, 1, U"Save as PNG file...", nullptr, 0, DO_Photo_saveAsPNG);
-	#if defined (macintosh) || defined (_WIN32)
-		praat_addAction1 (classPhoto, 1, U"Save as TIFF file...", nullptr, 0, DO_Photo_saveAsTIFF);
-		praat_addAction1 (classPhoto, 1, U"Save as GIF file...", nullptr, 0, DO_Photo_saveAsGIF);
-		praat_addAction1 (classPhoto, 1, U"Save as Windows bitmap file...", nullptr, 0, DO_Photo_saveAsWindowsBitmapFile);
-		praat_addAction1 (classPhoto, 1, U"Save as lossy JPEG file...", nullptr, 0, DO_Photo_saveAsJPEG);
-	#endif
-	#if defined (macintosh)
-		praat_addAction1 (classPhoto, 1, U"Save as JPEG-2000 file...", nullptr, 0, DO_Photo_saveAsJPEG2000);
-		praat_addAction1 (classPhoto, 1, U"Save as Apple icon file...", nullptr, 0, DO_Photo_saveAsAppleIconFile);
-		praat_addAction1 (classPhoto, 1, U"Save as Windows icon file...", nullptr, 0, DO_Photo_saveAsWindowsIconFile);
-	#endif
+	praat_addAction1 (classParamCurve, 0, U"Draw...", nullptr, 0, GRAPHICS_ParamCurve_draw);
 
-	praat_addAction1 (classPitch, 0, U"Pitch help", nullptr, 0, DO_Pitch_help);
-	praat_addAction1 (classPitch, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Pitch_edit);
-	praat_addAction1 (classPitch, 1, U"Edit", nullptr, praat_HIDDEN, DO_Pitch_edit);
+	praat_addAction1 (classPitch, 0, U"Pitch help", nullptr, 0, HELP_Pitch_help);
+	praat_addAction1 (classPitch, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Pitch_viewAndEdit);
+	praat_addAction1 (classPitch, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_Pitch_viewAndEdit);
 	praat_addAction1 (classPitch, 0, U"Sound -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitch, 0, U"Play pulses", nullptr, 1, DO_Pitch_play);
-		praat_addAction1 (classPitch, 0, U"Hum", nullptr, 1, DO_Pitch_hum);
+		praat_addAction1 (classPitch, 0, U"Play pulses", nullptr, 1, PLAY_Pitch_play);
+		praat_addAction1 (classPitch, 0, U"Hum", nullptr, 1, PLAY_Pitch_hum);
 		praat_addAction1 (classPitch, 0, U"-- to sound --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 0, U"To Sound (pulses)", nullptr, 1, DO_Pitch_to_Sound_pulses);
-		praat_addAction1 (classPitch, 0, U"To Sound (hum)", nullptr, 1, DO_Pitch_to_Sound_hum);
-		praat_addAction1 (classPitch, 0, U"To Sound (sine)...", nullptr, 1, DO_Pitch_to_Sound_sine);
+		praat_addAction1 (classPitch, 0, U"To Sound (pulses)", nullptr, 1, NEW_Pitch_to_Sound_pulses);
+		praat_addAction1 (classPitch, 0, U"To Sound (hum)", nullptr, 1, NEW_Pitch_to_Sound_hum);
+		praat_addAction1 (classPitch, 0, U"To Sound (sine)...", nullptr, 1, NEW_Pitch_to_Sound_sine);
 	praat_addAction1 (classPitch, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitch, 0, U"Draw...", nullptr, 1, DO_Pitch_draw);
-		praat_addAction1 (classPitch, 0, U"Draw logarithmic...", nullptr, 1, DO_Pitch_drawLogarithmic);
-		praat_addAction1 (classPitch, 0, U"Draw semitones (re 100 Hz)...", nullptr, 1, DO_Pitch_drawSemitones100);
-		praat_addAction1 (classPitch, 0, U"Draw semitones...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Pitch_drawSemitones100);
-		praat_addAction1 (classPitch, 0, U"Draw semitones (re 200 Hz)...", nullptr, 1, DO_Pitch_drawSemitones200);
-		praat_addAction1 (classPitch, 0, U"Draw semitones (re 440 Hz)...", nullptr, 1, DO_Pitch_drawSemitones440);
-		praat_addAction1 (classPitch, 0, U"Draw mel...", nullptr, 1, DO_Pitch_drawMel);
-		praat_addAction1 (classPitch, 0, U"Draw erb...", nullptr, 1, DO_Pitch_drawErb);
-		praat_addAction1 (classPitch, 0, U"Speckle...", nullptr, 1, DO_Pitch_speckle);
-		praat_addAction1 (classPitch, 0, U"Speckle logarithmic...", nullptr, 1, DO_Pitch_speckleLogarithmic);
-		praat_addAction1 (classPitch, 0, U"Speckle semitones (re 100 Hz)...", nullptr, 1, DO_Pitch_speckleSemitones100);
-		praat_addAction1 (classPitch, 0, U"Speckle semitones...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Pitch_speckleSemitones100);
-		praat_addAction1 (classPitch, 0, U"Speckle semitones (re 200 Hz)...", nullptr, 1, DO_Pitch_speckleSemitones200);
-		praat_addAction1 (classPitch, 0, U"Speckle semitones (re 440 Hz)...", nullptr, 1, DO_Pitch_speckleSemitones440);
-		praat_addAction1 (classPitch, 0, U"Speckle mel...", nullptr, 1, DO_Pitch_speckleMel);
-		praat_addAction1 (classPitch, 0, U"Speckle erb...", nullptr, 1, DO_Pitch_speckleErb);
+		praat_addAction1 (classPitch, 0, U"Draw...", nullptr, 1, GRAPHICS_Pitch_draw);
+		praat_addAction1 (classPitch, 0, U"Draw logarithmic...", nullptr, 1, GRAPHICS_Pitch_drawLogarithmic);
+		praat_addAction1 (classPitch, 0, U"Draw semitones (re 100 Hz)...", nullptr, 1, GRAPHICS_Pitch_drawSemitones100);
+		praat_addAction1 (classPitch, 0,   U"Draw semitones...", U"*Draw semitones (re 100 Hz)...", praat_DEPTH_1 | praat_DEPRECATED_2012, GRAPHICS_Pitch_drawSemitones100);
+		praat_addAction1 (classPitch, 0, U"Draw semitones (re 200 Hz)...", nullptr, 1, GRAPHICS_Pitch_drawSemitones200);
+		praat_addAction1 (classPitch, 0, U"Draw semitones (re 440 Hz)...", nullptr, 1, GRAPHICS_Pitch_drawSemitones440);
+		praat_addAction1 (classPitch, 0, U"Draw mel...", nullptr, 1, GRAPHICS_Pitch_drawMel);
+		praat_addAction1 (classPitch, 0, U"Draw erb...", nullptr, 1, GRAPHICS_Pitch_drawErb);
+		praat_addAction1 (classPitch, 0, U"Speckle...", nullptr, 1, GRAPHICS_Pitch_speckle);
+		praat_addAction1 (classPitch, 0, U"Speckle logarithmic...", nullptr, 1, GRAPHICS_Pitch_speckleLogarithmic);
+		praat_addAction1 (classPitch, 0, U"Speckle semitones (re 100 Hz)...", nullptr, 1, GRAPHICS_Pitch_speckleSemitones100);
+		praat_addAction1 (classPitch, 0,   U"Speckle semitones...", U"*Speckle semitones (re 100 Hz)...", praat_DEPTH_1 | praat_DEPRECATED_2012, GRAPHICS_Pitch_speckleSemitones100);
+		praat_addAction1 (classPitch, 0, U"Speckle semitones (re 200 Hz)...", nullptr, 1, GRAPHICS_Pitch_speckleSemitones200);
+		praat_addAction1 (classPitch, 0, U"Speckle semitones (re 440 Hz)...", nullptr, 1, GRAPHICS_Pitch_speckleSemitones440);
+		praat_addAction1 (classPitch, 0, U"Speckle mel...", nullptr, 1, GRAPHICS_Pitch_speckleMel);
+		praat_addAction1 (classPitch, 0, U"Speckle erb...", nullptr, 1, GRAPHICS_Pitch_speckleErb);
 	praat_addAction1 (classPitch, 0, U"Query -", nullptr, 0, nullptr);
 		praat_TimeFrameSampled_query_init (classPitch);
 		praat_addAction1 (classPitch, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 1, U"Count voiced frames", nullptr, 1, DO_Pitch_getNumberOfVoicedFrames);
-		praat_addAction1 (classPitch, 1, U"Get value at time...", nullptr, 1, DO_Pitch_getValueAtTime);
-		praat_addAction1 (classPitch, 1, U"Get value in frame...", nullptr, 1, DO_Pitch_getValueInFrame);
+		praat_addAction1 (classPitch, 1, U"Count voiced frames", nullptr, 1, INTEGER_Pitch_getNumberOfVoicedFrames);
+		praat_addAction1 (classPitch, 1, U"Get value at time...", nullptr, 1, REAL_Pitch_getValueAtTime);
+		praat_addAction1 (classPitch, 1, U"Get value in frame...", nullptr, 1, REAL_Pitch_getValueInFrame);
 		praat_addAction1 (classPitch, 1, U"-- get extreme --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 1, U"Get minimum...", nullptr, 1, DO_Pitch_getMinimum);
-		praat_addAction1 (classPitch, 1, U"Get time of minimum...", nullptr, 1, DO_Pitch_getTimeOfMinimum);
-		praat_addAction1 (classPitch, 1, U"Get maximum...", nullptr, 1, DO_Pitch_getMaximum);
-		praat_addAction1 (classPitch, 1, U"Get time of maximum...", nullptr, 1, DO_Pitch_getTimeOfMaximum);
+		praat_addAction1 (classPitch, 1, U"Get minimum...", nullptr, 1, REAL_Pitch_getMinimum);
+		praat_addAction1 (classPitch, 1, U"Get time of minimum...", nullptr, 1, REAL_Pitch_getTimeOfMinimum);
+		praat_addAction1 (classPitch, 1, U"Get maximum...", nullptr, 1, REAL_Pitch_getMaximum);
+		praat_addAction1 (classPitch, 1, U"Get time of maximum...", nullptr, 1, REAL_Pitch_getTimeOfMaximum);
 		praat_addAction1 (classPitch, 1, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 1, U"Get quantile...", nullptr, 1, DO_Pitch_getQuantile);
-		/*praat_addAction1 (classPitch, 1, U"Get spreading...", nullptr, 1, DO_Pitch_getSpreading);*/
-		praat_addAction1 (classPitch, 1, U"Get mean...", nullptr, 1, DO_Pitch_getMean);
-		praat_addAction1 (classPitch, 1, U"Get standard deviation...", nullptr, 1, DO_Pitch_getStandardDeviation);
+		praat_addAction1 (classPitch, 1, U"Get quantile...", nullptr, 1, REAL_Pitch_getQuantile);
+		/*praat_addAction1 (classPitch, 1, U"Get spreading...", nullptr, 1, REAL_Pitch_getSpreading);*/
+		praat_addAction1 (classPitch, 1, U"Get mean...", nullptr, 1, REAL_Pitch_getMean);
+		praat_addAction1 (classPitch, 1, U"Get standard deviation...", nullptr, 1, REAL_Pitch_getStandardDeviation);
 		praat_addAction1 (classPitch, 1, U"-- get slope --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 1, U"Get mean absolute slope...", nullptr, 1, DO_Pitch_getMeanAbsoluteSlope);
-		praat_addAction1 (classPitch, 1, U"Get slope without octave jumps", nullptr, 1, DO_Pitch_getMeanAbsSlope_noOctave);
+		praat_addAction1 (classPitch, 1, U"Get mean absolute slope...", nullptr, 1, REAL_Pitch_getMeanAbsoluteSlope);
+		praat_addAction1 (classPitch, 1, U"Get slope without octave jumps", nullptr, 1, REAL_Pitch_getMeanAbsSlope_noOctave);
 		praat_addAction1 (classPitch, 2, U"-- query two --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 2, U"Count differences", nullptr, 1, DO_Pitch_difference);
+		praat_addAction1 (classPitch, 2, U"Count differences", nullptr, 1, INFO_Pitch_difference);
 	praat_addAction1 (classPitch, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classPitch);
-		praat_addAction1 (classPitch, 0, U"Formula...", nullptr, 1, DO_Pitch_formula);
+		praat_addAction1 (classPitch, 0, U"Formula...", nullptr, 1, MODIFY_Pitch_formula);
 	praat_addAction1 (classPitch, 0, U"Annotate -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitch, 0, U"To TextGrid...", nullptr, 1, DO_Pitch_to_TextGrid);
+		praat_addAction1 (classPitch, 0, U"To TextGrid...", nullptr, 1, NEW_Pitch_to_TextGrid);
 		praat_addAction1 (classPitch, 0, U"-- to single tier --", nullptr, praat_HIDDEN + praat_DEPTH_1, nullptr);
-		praat_addAction1 (classPitch, 0, U"To TextTier", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Pitch_to_TextTier);
-		praat_addAction1 (classPitch, 0, U"To IntervalTier", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Pitch_to_IntervalTier);
+		praat_addAction1 (classPitch, 0, U"To TextTier", nullptr, praat_HIDDEN | praat_DEPTH_1, NEW_Pitch_to_TextTier);
+		praat_addAction1 (classPitch, 0, U"To IntervalTier", nullptr, praat_HIDDEN | praat_DEPTH_1, NEW_Pitch_to_IntervalTier);
 	praat_addAction1 (classPitch, 0, U"Analyse -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitch, 0, U"To PointProcess", nullptr, 1, DO_Pitch_to_PointProcess);
+		praat_addAction1 (classPitch, 0, U"To PointProcess", nullptr, 1, NEW_Pitch_to_PointProcess);
 	praat_addAction1 (classPitch, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitch, 0, U"Interpolate", nullptr, 1, DO_Pitch_interpolate);
-		praat_addAction1 (classPitch, 0, U"Smooth...", nullptr, 1, DO_Pitch_smooth);
-		praat_addAction1 (classPitch, 0, U"Subtract linear fit...", nullptr, 1, DO_Pitch_subtractLinearFit);
+		praat_addAction1 (classPitch, 0, U"Interpolate", nullptr, 1, NEW_Pitch_interpolate);
+		praat_addAction1 (classPitch, 0, U"Smooth...", nullptr, 1, NEW_Pitch_smooth);
+		praat_addAction1 (classPitch, 0, U"Subtract linear fit...", nullptr, 1, NEW_Pitch_subtractLinearFit);
 		praat_addAction1 (classPitch, 0, U"Hack", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 0, U"Kill octave jumps", nullptr, 2, DO_Pitch_killOctaveJumps);
+		praat_addAction1 (classPitch, 0, U"Kill octave jumps", nullptr, 2, NEW_Pitch_killOctaveJumps);
 		praat_addAction1 (classPitch, 0, U"-- to other types --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitch, 0, U"Down to PitchTier", nullptr, 1, DO_Pitch_to_PitchTier);
-		praat_addAction1 (classPitch, 0, U"To Matrix", nullptr, 1, DO_Pitch_to_Matrix);
-
-	praat_addAction1 (classPitchTier, 1, U"Save as PitchTier spreadsheet file...", nullptr, 0, DO_PitchTier_writeToPitchTierSpreadsheetFile);
-	praat_addAction1 (classPitchTier, 1, U"Write to PitchTier spreadsheet file...", nullptr, praat_HIDDEN, DO_PitchTier_writeToPitchTierSpreadsheetFile);
-	praat_addAction1 (classPitchTier, 1, U"Save as headerless spreadsheet file...", nullptr, 0, DO_PitchTier_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (classPitchTier, 1, U"Write to headerless spreadsheet file...", nullptr, praat_HIDDEN, DO_PitchTier_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (classPitchTier, 0, U"PitchTier help", nullptr, 0, DO_PitchTier_help);
-	praat_addAction1 (classPitchTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_PitchTier_edit);
-	praat_addAction1 (classPitchTier, 1, U"Edit", nullptr, praat_HIDDEN, DO_PitchTier_edit);
-	praat_addAction1 (classPitchTier, 0, U"View & Edit with Sound?", nullptr, 0, DO_info_PitchTier_Sound_edit);
-	praat_addAction1 (classPitchTier, 0, U"Play pulses", nullptr, 0, DO_PitchTier_play);
-	praat_addAction1 (classPitchTier, 0, U"Hum", nullptr, 0, DO_PitchTier_hum);
-	praat_addAction1 (classPitchTier, 0, U"Play sine", nullptr, 0, DO_PitchTier_playSine);
-	praat_addAction1 (classPitchTier, 0, U"Draw...", nullptr, 0, DO_PitchTier_draw);
-	praat_addAction1 (classPitchTier, 0, U"& Manipulation: Replace?", nullptr, 0, DO_info_PitchTier_Manipulation_replace);
-	praat_addAction1 (classPitchTier, 0, U"Query -", nullptr, 0, nullptr);
-		praat_TimeTier_query_init (classPitchTier);
-		praat_addAction1 (classPitchTier, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitchTier, 1, U"Get value at time...", nullptr, 1, DO_PitchTier_getValueAtTime);
-		praat_addAction1 (classPitchTier, 1, U"Get value at index...", nullptr, 1, DO_PitchTier_getValueAtIndex);
-		praat_addAction1 (classPitchTier, 1, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitchTier, 1, U"Get mean (curve)...", nullptr, 1, DO_PitchTier_getMean_curve);
-		praat_addAction1 (classPitchTier, 1, U"Get mean (points)...", nullptr, 1, DO_PitchTier_getMean_points);
-		praat_addAction1 (classPitchTier, 1, U"Get standard deviation (curve)...", nullptr, 1, DO_PitchTier_getStandardDeviation_curve);
-		praat_addAction1 (classPitchTier, 1, U"Get standard deviation (points)...", nullptr, 1, DO_PitchTier_getStandardDeviation_points);
-	praat_addAction1 (classPitchTier, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeTier_modify_init (classPitchTier);
-		praat_addAction1 (classPitchTier, 0, U"Add point...", nullptr, 1, DO_PitchTier_addPoint);
-		praat_addAction1 (classPitchTier, 0, U"Formula...", nullptr, 1, DO_PitchTier_formula);
-		praat_addAction1 (classPitchTier, 0, U"-- stylize --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitchTier, 0, U"Stylize...", nullptr, 1, DO_PitchTier_stylize);
-		praat_addAction1 (classPitchTier, 0, U"Interpolate quadratically...", nullptr, 1, DO_PitchTier_interpolateQuadratically);
-		praat_addAction1 (classPitchTier, 0, U"-- modify frequencies --", nullptr, 1, nullptr);
-		praat_addAction1 (classPitchTier, 0, U"Shift frequencies...", nullptr, 1, DO_PitchTier_shiftFrequencies);
-		praat_addAction1 (classPitchTier, 0, U"Multiply frequencies...", nullptr, 1, DO_PitchTier_multiplyFrequencies);
-	praat_addAction1 (classPitchTier, 0, U"Synthesize -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitchTier, 0, U"To PointProcess", nullptr, 1, DO_PitchTier_to_PointProcess);
-		praat_addAction1 (classPitchTier, 0, U"To Sound (pulse train)...", nullptr, 1, DO_PitchTier_to_Sound_pulseTrain);
-		praat_addAction1 (classPitchTier, 0, U"To Sound (phonation)...", nullptr, 1, DO_PitchTier_to_Sound_phonation);
-		praat_addAction1 (classPitchTier, 0, U"To Sound (sine)...", nullptr, 1, DO_PitchTier_to_Sound_sine);
-	praat_addAction1 (classPitchTier, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (classPitchTier, 0, U"Down to PointProcess", nullptr, 1, DO_PitchTier_downto_PointProcess);
-		praat_addAction1 (classPitchTier, 0, U"Down to TableOfReal...", nullptr, 1, DO_PitchTier_downto_TableOfReal);
-
-	praat_addAction1 (classPointProcess, 0, U"PointProcess help", nullptr, 0, DO_PointProcess_help);
-	praat_addAction1 (classPointProcess, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_PointProcess_edit);
-	praat_addAction1 (classPointProcess, 1, U"View & Edit alone", nullptr, praat_HIDDEN, DO_PointProcess_edit);
-	praat_addAction1 (classPointProcess, 1, U"Edit alone", nullptr, praat_HIDDEN, DO_PointProcess_edit);
-	praat_addAction1 (classPointProcess, 0, U"View & Edit with Sound?", nullptr, 0, DO_info_PointProcess_Sound_edit);
-	praat_addAction1 (classPointProcess, 0, U"Play -", nullptr, 0, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"Play as pulse train", nullptr, 1, DO_PointProcess_play);
-		praat_addAction1 (classPointProcess, 0, U"Hum", nullptr, 1, DO_PointProcess_hum);
-		praat_addAction1 (classPointProcess, 0, U"-- to sound --", nullptr, 1, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"To Sound (pulse train)...", nullptr, 1, DO_PointProcess_to_Sound_pulseTrain);
-		praat_addAction1 (classPointProcess, 0, U"To Sound (phonation)...", nullptr, 1, DO_PointProcess_to_Sound_phonation);
-		praat_addAction1 (classPointProcess, 0, U"To Sound (hum)", nullptr, 1, DO_PointProcess_to_Sound_hum);
-	praat_addAction1 (classPointProcess, 0, U"Draw...", nullptr, 0, DO_PointProcess_draw);
-	praat_addAction1 (classPointProcess, 0, U"Query -", nullptr, 0, nullptr);
-		praat_TimeFunction_query_init (classPointProcess);
-		praat_addAction1 (classPointProcess, 1, U"-- script get --", nullptr, 1, nullptr);
-		praat_addAction1 (classPointProcess, 1, U"Get number of points", nullptr, 1, DO_PointProcess_getNumberOfPoints);
-		praat_addAction1 (classPointProcess, 1, U"Get low index...", nullptr, 1, DO_PointProcess_getLowIndex);
-		praat_addAction1 (classPointProcess, 1, U"Get high index...", nullptr, 1, DO_PointProcess_getHighIndex);
-		praat_addAction1 (classPointProcess, 1, U"Get nearest index...", nullptr, 1, DO_PointProcess_getNearestIndex);
-		praat_addAction1 (classPointProcess, 1, U"Get time from index...", nullptr, 1, DO_PointProcess_getTimeFromIndex);
-		praat_addAction1 (classPointProcess, 1, U"Get interval...", nullptr, 1, DO_PointProcess_getInterval);
-		praat_addAction1 (classPointProcess, 1, U"-- periods --", nullptr, 1, nullptr);
-		praat_addAction1 (classPointProcess, 1, U"Get number of periods...", nullptr, 1, DO_PointProcess_getNumberOfPeriods);
-		praat_addAction1 (classPointProcess, 1, U"Get mean period...", nullptr, 1, DO_PointProcess_getMeanPeriod);
-		praat_addAction1 (classPointProcess, 1, U"Get stdev period...", nullptr, 1, DO_PointProcess_getStdevPeriod);
-		praat_addAction1 (classPointProcess, 1, U"Get jitter (local)...", nullptr, 1, DO_PointProcess_getJitter_local);
-		praat_addAction1 (classPointProcess, 1, U"Get jitter (local, absolute)...", nullptr, 1, DO_PointProcess_getJitter_local_absolute);
-		praat_addAction1 (classPointProcess, 1, U"Get jitter (rap)...", nullptr, 1, DO_PointProcess_getJitter_rap);
-		praat_addAction1 (classPointProcess, 1, U"Get jitter (ppq5)...", nullptr, 1, DO_PointProcess_getJitter_ppq5);
-		praat_addAction1 (classPointProcess, 1, U"Get jitter (ddp)...", nullptr, 1, DO_PointProcess_getJitter_ddp);
-	praat_addAction1 (classPointProcess, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeFunction_modify_init (classPointProcess);
-		praat_addAction1 (classPointProcess, 0, U"Add point...", nullptr, 1, DO_PointProcess_addPoint);
-		praat_addAction1 (classPointProcess, 0, U"Remove point...", nullptr, 1, DO_PointProcess_removePoint);
-		praat_addAction1 (classPointProcess, 0, U"Remove point near...", nullptr, 1, DO_PointProcess_removePointNear);
-		praat_addAction1 (classPointProcess, 0, U"Remove points...", nullptr, 1, DO_PointProcess_removePoints);
-		praat_addAction1 (classPointProcess, 0, U"Remove points between...", nullptr, 1, DO_PointProcess_removePointsBetween);
-		praat_addAction1 (classPointProcess, 0, U"-- voice --", nullptr, 1, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"Fill...", nullptr, 1, DO_PointProcess_fill);
-		praat_addAction1 (classPointProcess, 0, U"Voice...", nullptr, 1, DO_PointProcess_voice);
-	praat_addAction1 (classPointProcess, 0, U"Annotate -", nullptr, 0, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"To TextGrid...", nullptr, 1, DO_PointProcess_to_TextGrid);
-		praat_addAction1 (classPointProcess, 0, U"-- to single tier --", nullptr, 1, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"To TextTier", nullptr, 1, DO_PointProcess_to_TextTier);
-		praat_addAction1 (classPointProcess, 0, U"To IntervalTier", nullptr, 1, DO_PointProcess_to_IntervalTier);
-	praat_addAction1 (classPointProcess, 0, U"Analyse -", nullptr, 0, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"To PitchTier...", nullptr, 1, DO_PointProcess_to_PitchTier);
-		praat_addAction1 (classPointProcess, 0, U"To TextGrid (vuv)...", nullptr, 1, DO_PointProcess_to_TextGrid_vuv);
-	praat_addAction1 (classPointProcess, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (classPointProcess, 0, U"Hack", nullptr, 1, nullptr);
-			praat_addAction1 (classPointProcess, 0, U"To Matrix", nullptr, 2, DO_PointProcess_to_Matrix);
-			praat_addAction1 (classPointProcess, 0, U"Up to TextTier...", nullptr, 2, DO_PointProcess_upto_TextTier);
-			praat_addAction1 (classPointProcess, 0, U"Up to PitchTier...", nullptr, 2, DO_PointProcess_upto_PitchTier);
-			praat_addAction1 (classPointProcess, 0, U"Up to IntensityTier...", nullptr, 2, DO_PointProcess_upto_IntensityTier);
-	praat_addAction1 (classPointProcess, 0, U"Combine -", nullptr, 0, nullptr);
-		praat_addAction1 (classPointProcess, 2, U"Union", nullptr, 1, DO_PointProcess_union);
-		praat_addAction1 (classPointProcess, 2, U"Intersection", nullptr, 1, DO_PointProcess_intersection);
-		praat_addAction1 (classPointProcess, 2, U"Difference", nullptr, 1, DO_PointProcess_difference);
-
-	praat_addAction1 (classPolygon, 0, U"Polygon help", nullptr, 0, DO_Polygon_help);
+		praat_addAction1 (classPitch, 0, U"Down to PitchTier", nullptr, 1, NEW_Pitch_to_PitchTier);
+		praat_addAction1 (classPitch, 0, U"To Matrix", nullptr, 1, NEW_Pitch_to_Matrix);
+
+	praat_addAction1 (classPolygon, 0, U"Polygon help", nullptr, 0, HELP_Polygon_help);
 praat_addAction1 (classPolygon, 0, U"Draw -", nullptr, 0, nullptr);
-	praat_addAction1 (classPolygon, 0, U"Draw...", nullptr, 1, DO_Polygon_draw);
-	praat_addAction1 (classPolygon, 0, U"Draw closed...", nullptr, 1, DO_Polygon_drawClosed);
-	praat_addAction1 (classPolygon, 0, U"Paint...", nullptr, 1, DO_Polygon_paint);
-	praat_addAction1 (classPolygon, 0, U"Draw circles...", nullptr, 1, DO_Polygon_drawCircles);
-	praat_addAction1 (classPolygon, 0, U"Paint circles...", nullptr, 1, DO_Polygon_paintCircles);
-	praat_addAction1 (classPolygon, 2, U"Draw connection...", nullptr, 1, DO_Polygons_drawConnection);
+	praat_addAction1 (classPolygon, 0, U"Draw...", nullptr, 1, GRAPHICS_Polygon_draw);
+	praat_addAction1 (classPolygon, 0, U"Draw closed...", nullptr, 1, GRAPHICS_Polygon_drawClosed);
+	praat_addAction1 (classPolygon, 0, U"Paint...", nullptr, 1, GRAPHICS_Polygon_paint);
+	praat_addAction1 (classPolygon, 0, U"Draw circles...", nullptr, 1, GRAPHICS_Polygon_drawCircles);
+	praat_addAction1 (classPolygon, 0, U"Paint circles...", nullptr, 1, GRAPHICS_Polygon_paintCircles);
+	praat_addAction1 (classPolygon, 2, U"Draw connection...", nullptr, 1, GRAPHICS_Polygons_drawConnection);
 praat_addAction1 (classPolygon, 0, U"Modify -", nullptr, 0, nullptr);
-	praat_addAction1 (classPolygon, 0, U"Randomize", nullptr, 1, DO_Polygon_randomize);
-	praat_addAction1 (classPolygon, 0, U"Salesperson...", nullptr, 1, DO_Polygon_salesperson);
+	praat_addAction1 (classPolygon, 0, U"Randomize", nullptr, 1, MODIFY_Polygon_randomize);
+	praat_addAction1 (classPolygon, 0, U"Salesperson...", nullptr, 1, MODIFY_Polygon_salesperson);
 praat_addAction1 (classPolygon, 0, U"Hack -", nullptr, 0, nullptr);
-	praat_addAction1 (classPolygon, 0, U"To Matrix", nullptr, 1, DO_Polygon_to_Matrix);
+	praat_addAction1 (classPolygon, 0, U"To Matrix", nullptr, 1, NEW_Polygon_to_Matrix);
 
-	praat_addAction1 (classSpectrogram, 0, U"Spectrogram help", nullptr, 0, DO_Spectrogram_help);
-	praat_addAction1 (classSpectrogram, 1, U"View", nullptr, 0, DO_Spectrogram_view);
-	praat_addAction1 (classSpectrogram, 1, U"Movie", nullptr, 0, DO_Spectrogram_movie);
+	praat_addAction1 (classSpectrogram, 0, U"Spectrogram help", nullptr, 0, HELP_Spectrogram_help);
+	praat_addAction1 (classSpectrogram, 1, U"View", nullptr, 0, WINDOW_Spectrogram_view);
+	praat_addAction1 (classSpectrogram, 1, U"Movie", nullptr, 0, MOVIE_Spectrogram_movie);
 	praat_addAction1 (classSpectrogram, 0, U"Query -", nullptr, 0, nullptr);
 		praat_TimeFrameSampled_query_init (classSpectrogram);
-		praat_addAction1 (classSpectrogram, 1, U"Get power at...", nullptr, 1, DO_Spectrogram_getPowerAt);
+		praat_addAction1 (classSpectrogram, 1, U"Get power at...", nullptr, 1, REAL_Spectrogram_getPowerAt);
 	praat_addAction1 (classSpectrogram, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrogram, 0, U"Paint...", nullptr, 1, DO_Spectrogram_paint);
+		praat_addAction1 (classSpectrogram, 0, U"Paint...", nullptr, 1, GRAPHICS_Spectrogram_paint);
 	praat_addAction1 (classSpectrogram, 0, U"Analyse -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrogram, 0, U"To Spectrum (slice)...", nullptr, 1, DO_Spectrogram_to_Spectrum);
+		praat_addAction1 (classSpectrogram, 0, U"To Spectrum (slice)...", nullptr, 1, NEW_Spectrogram_to_Spectrum);
 	praat_addAction1 (classSpectrogram, 0, U"Synthesize -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrogram, 0, U"To Sound...", nullptr, 1, DO_Spectrogram_to_Sound);
+		praat_addAction1 (classSpectrogram, 0, U"To Sound...", nullptr, 1, NEW_Spectrogram_to_Sound);
 	praat_addAction1 (classSpectrogram, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeFunction_modify_init (classSpectrogram);
-		praat_addAction1 (classSpectrogram, 0, U"Formula...", nullptr, 1, DO_Spectrogram_formula);
+		praat_addAction1 (classSpectrogram, 0, U"Formula...", nullptr, 1, MODIFY_Spectrogram_formula);
 	praat_addAction1 (classSpectrogram, 0, U"Hack -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrogram, 0, U"To Matrix", nullptr, 1, DO_Spectrogram_to_Matrix);
+		praat_addAction1 (classSpectrogram, 0, U"To Matrix", nullptr, 1, NEW_Spectrogram_to_Matrix);
 
-	praat_addAction1 (classSpectrum, 0, U"Spectrum help", nullptr, 0, DO_Spectrum_help);
-	praat_addAction1 (classSpectrum, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Spectrum_edit);
-	praat_addAction1 (classSpectrum, 1, U"Edit", nullptr, praat_HIDDEN, DO_Spectrum_edit);
+	praat_addAction1 (classSpectrum, 0, U"Spectrum help", nullptr, 0, HELP_Spectrum_help);
+	praat_addAction1 (classSpectrum, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Spectrum_viewAndEdit);
+	praat_addAction1 (classSpectrum, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_Spectrum_viewAndEdit);
 	praat_addAction1 (classSpectrum, 0, U"Sound -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrum, 0, U"To Sound", nullptr, 1, DO_Spectrum_to_Sound);
-						praat_addAction1 (classSpectrum, 0, U"To Sound (fft)", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Spectrum_to_Sound);
+		praat_addAction1 (classSpectrum, 0, U"To Sound", nullptr, 1, NEW_Spectrum_to_Sound);
+		praat_addAction1 (classSpectrum, 0,   U"To Sound (fft)", U"*To Sound", praat_DEPTH_1 | praat_DEPRECATED_2004, NEW_Spectrum_to_Sound);
 	praat_addAction1 (classSpectrum, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrum, 0, U"Draw...", nullptr, 1, DO_Spectrum_draw);
-		praat_addAction1 (classSpectrum, 0, U"Draw (log freq)...", nullptr, 1, DO_Spectrum_drawLogFreq);
+		praat_addAction1 (classSpectrum, 0, U"Draw...", nullptr, 1, GRAPHICS_Spectrum_draw);
+		praat_addAction1 (classSpectrum, 0, U"Draw (log freq)...", nullptr, 1, GRAPHICS_Spectrum_drawLogFreq);
 	praat_addAction1 (classSpectrum, 1, U"Tabulate -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrum, 1, U"List...", nullptr, 1, DO_Spectrum_list);
+		praat_addAction1 (classSpectrum, 1, U"List...", nullptr, 1, LIST_Spectrum_list);
 	praat_addAction1 (classSpectrum, 1, U"Query -", nullptr, 0, nullptr);
 		praat_addAction1 (classSpectrum, 1, U"Frequency domain", nullptr, 1, nullptr);
-			praat_addAction1 (classSpectrum, 1, U"Get lowest frequency", nullptr, 2, DO_Spectrum_getLowestFrequency);
-			praat_addAction1 (classSpectrum, 1, U"Get highest frequency", nullptr, 2, DO_Spectrum_getHighestFrequency);
+			praat_addAction1 (classSpectrum, 1, U"Get lowest frequency", nullptr, 2, REAL_Spectrum_getLowestFrequency);
+			praat_addAction1 (classSpectrum, 1, U"Get highest frequency", nullptr, 2, REAL_Spectrum_getHighestFrequency);
 		praat_addAction1 (classSpectrum, 1, U"Frequency sampling", nullptr, 1, nullptr);
-			praat_addAction1 (classSpectrum, 1, U"Get number of bins", nullptr, 2, DO_Spectrum_getNumberOfBins);
-			praat_addAction1 (classSpectrum, 1, U"Get bin width", nullptr, 2, DO_Spectrum_getBinWidth);
-			praat_addAction1 (classSpectrum, 1, U"Get frequency from bin number...", nullptr, 2, DO_Spectrum_getFrequencyFromBin);
-						praat_addAction1 (classSpectrum, 1, U"Get frequency from bin...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Spectrum_getFrequencyFromBin);
-			praat_addAction1 (classSpectrum, 1, U"Get bin number from frequency...", nullptr, 2, DO_Spectrum_getBinFromFrequency);
-						praat_addAction1 (classSpectrum, 1, U"Get bin from frequency...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Spectrum_getBinFromFrequency);
+			praat_addAction1 (classSpectrum, 1, U"Get number of bins", nullptr, 2, INTEGER_Spectrum_getNumberOfBins);
+			praat_addAction1 (classSpectrum, 1, U"Get bin width", nullptr, 2, REAL_Spectrum_getBinWidth);
+			praat_addAction1 (classSpectrum, 1, U"Get frequency from bin number...", nullptr, 2, REAL_Spectrum_getFrequencyFromBin);
+			praat_addAction1 (classSpectrum, 1,   U"Get frequency from bin...", U"*Get frequency from bin number...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Spectrum_getFrequencyFromBin);
+			praat_addAction1 (classSpectrum, 1, U"Get bin number from frequency...", nullptr, 2, REAL_Spectrum_getBinNumberFromFrequency);
+			praat_addAction1 (classSpectrum, 1,   U"Get bin from frequency...", nullptr, praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Spectrum_getBinNumberFromFrequency);
 		praat_addAction1 (classSpectrum, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classSpectrum, 1, U"Get real value in bin...", nullptr, 1, DO_Spectrum_getRealValueInBin);
-		praat_addAction1 (classSpectrum, 1, U"Get imaginary value in bin...", nullptr, 1, DO_Spectrum_getImaginaryValueInBin);
+		praat_addAction1 (classSpectrum, 1, U"Get real value in bin...", nullptr, 1, REAL_Spectrum_getRealValueInBin);
+		praat_addAction1 (classSpectrum, 1, U"Get imaginary value in bin...", nullptr, 1, REAL_Spectrum_getImaginaryValueInBin);
 		praat_addAction1 (classSpectrum, 1, U"-- get energy --", nullptr, 1, nullptr);
-		praat_addAction1 (classSpectrum, 1, U"Get band energy...", nullptr, 1, DO_Spectrum_getBandEnergy);
-		praat_addAction1 (classSpectrum, 1, U"Get band density...", nullptr, 1, DO_Spectrum_getBandDensity);
-		praat_addAction1 (classSpectrum, 1, U"Get band energy difference...", nullptr, 1, DO_Spectrum_getBandEnergyDifference);
-		praat_addAction1 (classSpectrum, 1, U"Get band density difference...", nullptr, 1, DO_Spectrum_getBandDensityDifference);
+		praat_addAction1 (classSpectrum, 1, U"Get band energy...", nullptr, 1, REAL_Spectrum_getBandEnergy);
+		praat_addAction1 (classSpectrum, 1, U"Get band density...", nullptr, 1, REAL_Spectrum_getBandDensity);
+		praat_addAction1 (classSpectrum, 1, U"Get band energy difference...", nullptr, 1, REAL_Spectrum_getBandEnergyDifference);
+		praat_addAction1 (classSpectrum, 1, U"Get band density difference...", nullptr, 1, REAL_Spectrum_getBandDensityDifference);
 		praat_addAction1 (classSpectrum, 1, U"-- get moments --", nullptr, 1, nullptr);
-		praat_addAction1 (classSpectrum, 1, U"Get centre of gravity...", nullptr, 1, DO_Spectrum_getCentreOfGravity);
-		praat_addAction1 (classSpectrum, 1, U"Get standard deviation...", nullptr, 1, DO_Spectrum_getStandardDeviation);
-		praat_addAction1 (classSpectrum, 1, U"Get skewness...", nullptr, 1, DO_Spectrum_getSkewness);
-		praat_addAction1 (classSpectrum, 1, U"Get kurtosis...", nullptr, 1, DO_Spectrum_getKurtosis);
-		praat_addAction1 (classSpectrum, 1, U"Get central moment...", nullptr, 1, DO_Spectrum_getCentralMoment);
+		praat_addAction1 (classSpectrum, 1, U"Get centre of gravity...", nullptr, 1, REAL_Spectrum_getCentreOfGravity);
+		praat_addAction1 (classSpectrum, 1, U"Get standard deviation...", nullptr, 1, REAL_Spectrum_getStandardDeviation);
+		praat_addAction1 (classSpectrum, 1, U"Get skewness...", nullptr, 1, REAL_Spectrum_getSkewness);
+		praat_addAction1 (classSpectrum, 1, U"Get kurtosis...", nullptr, 1, REAL_Spectrum_getKurtosis);
+		praat_addAction1 (classSpectrum, 1, U"Get central moment...", nullptr, 1, REAL_Spectrum_getCentralMoment);
 	praat_addAction1 (classSpectrum, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrum, 0, U"Formula...", nullptr, 1, DO_Spectrum_formula);
-		praat_addAction1 (classSpectrum, 0, U"Filter (pass Hann band)...", nullptr, 1, DO_Spectrum_passHannBand);
-		praat_addAction1 (classSpectrum, 0, U"Filter (stop Hann band)...", nullptr, 1, DO_Spectrum_stopHannBand);
+		praat_addAction1 (classSpectrum, 0, U"Formula...", nullptr, 1, MODIFY_Spectrum_formula);
+		praat_addAction1 (classSpectrum, 0, U"Filter (pass Hann band)...", nullptr, 1, MODIFY_Spectrum_passHannBand);
+		praat_addAction1 (classSpectrum, 0, U"Filter (stop Hann band)...", nullptr, 1, MODIFY_Spectrum_stopHannBand);
 	praat_addAction1 (classSpectrum, 0, U"Analyse -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrum, 0, U"To Excitation...", nullptr, 1, DO_Spectrum_to_Excitation);
-		praat_addAction1 (classSpectrum, 0, U"To SpectrumTier (peaks)", nullptr, 1, DO_Spectrum_to_SpectrumTier_peaks);
-		praat_addAction1 (classSpectrum, 0, U"To Formant (peaks)...", nullptr, 1, DO_Spectrum_to_Formant_peaks);
-		praat_addAction1 (classSpectrum, 0, U"To Ltas...", nullptr, 1, DO_Spectrum_to_Ltas);
-		praat_addAction1 (classSpectrum, 0, U"To Ltas (1-to-1)", nullptr, 1, DO_Spectrum_to_Ltas_1to1);
-		praat_addAction1 (classSpectrum, 0, U"To Spectrogram", nullptr, 1, DO_Spectrum_to_Spectrogram);
+		praat_addAction1 (classSpectrum, 0, U"To Excitation...", nullptr, 1, NEW_Spectrum_to_Excitation);
+		praat_addAction1 (classSpectrum, 0, U"To SpectrumTier (peaks)", nullptr, 1, NEW_Spectrum_to_SpectrumTier_peaks);
+		praat_addAction1 (classSpectrum, 0, U"To Formant (peaks)...", nullptr, 1, NEW_Spectrum_to_Formant_peaks);
+		praat_addAction1 (classSpectrum, 0, U"To Ltas...", nullptr, 1, NEW_Spectrum_to_Ltas);
+		praat_addAction1 (classSpectrum, 0, U"To Ltas (1-to-1)", nullptr, 1, NEW_Spectrum_to_Ltas_1to1);
+		praat_addAction1 (classSpectrum, 0, U"To Spectrogram", nullptr, 1, NEW_Spectrum_to_Spectrogram);
 	praat_addAction1 (classSpectrum, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrum, 0, U"Cepstral smoothing...", nullptr, 1, DO_Spectrum_cepstralSmoothing);
-		praat_addAction1 (classSpectrum, 0, U"LPC smoothing...", nullptr, 1, DO_Spectrum_lpcSmoothing);
+		praat_addAction1 (classSpectrum, 0, U"Cepstral smoothing...", nullptr, 1, NEW_Spectrum_cepstralSmoothing);
+		praat_addAction1 (classSpectrum, 0, U"LPC smoothing...", nullptr, 1, NEW_Spectrum_lpcSmoothing);
 		praat_addAction1 (classSpectrum, 0, U"Hack", nullptr, 1, nullptr);
-			praat_addAction1 (classSpectrum, 0, U"To Matrix", nullptr, 2, DO_Spectrum_to_Matrix);
-
-	praat_addAction1 (classSpectrumTier, 0, U"Draw...", nullptr, 0, DO_SpectrumTier_draw);
-	praat_addAction1 (classSpectrumTier, 0, U"Tabulate -", nullptr, 0, nullptr);
-		praat_addAction1 (classSpectrumTier, 1, U"List...", nullptr, 1, DO_SpectrumTier_list);
-		praat_addAction1 (classSpectrumTier, 0, U"Down to Table", nullptr, 1, DO_SpectrumTier_downto_Table);
-	praat_addAction1 (classSpectrumTier, 0, U"Remove points below...", nullptr, 0, DO_SpectrumTier_removePointsBelow);
-
-	praat_addAction1 (classStrings, 0, U"Strings help", nullptr, 0, DO_Strings_help);
-	praat_addAction1 (classStrings, 1, U"Save as raw text file...", nullptr, 0, DO_Strings_writeToRawTextFile);
-	praat_addAction1 (classStrings, 1, U"Write to raw text file...", nullptr, praat_HIDDEN, DO_Strings_writeToRawTextFile);
-	praat_addAction1 (classStrings, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Strings_edit);
-	praat_addAction1 (classStrings, 1, U"Edit", nullptr, praat_HIDDEN, DO_Strings_edit);
+			praat_addAction1 (classSpectrum, 0, U"To Matrix", nullptr, 2, NEW_Spectrum_to_Matrix);
+
+	praat_addAction1 (classStrings, 0, U"Strings help", nullptr, 0, HELP_Strings_help);
+	praat_addAction1 (classStrings, 1, U"Save as raw text file...", nullptr, 0, SAVE_Strings_writeToRawTextFile);
+	praat_addAction1 (classStrings, 1,   U"Write to raw text file...", U"*Save as raw text file...", praat_DEPRECATED_2011, SAVE_Strings_writeToRawTextFile);
+	praat_addAction1 (classStrings, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Strings_viewAndEdit);
+	praat_addAction1 (classStrings, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_Strings_viewAndEdit);
 	praat_addAction1 (classStrings, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classStrings, 2, U"Equal?", nullptr, 1, DO_Strings_equal);
-		praat_addAction1 (classStrings, 1, U"Get number of strings", nullptr, 1, DO_Strings_getNumberOfStrings);
-		praat_addAction1 (classStrings, 1, U"Get string...", nullptr, 1, DO_Strings_getString);
+		praat_addAction1 (classStrings, 2, U"Equal?", nullptr, 1, BOOLEAN_Strings_equal);
+		praat_addAction1 (classStrings, 1, U"Get number of strings", nullptr, 1, INTEGER_Strings_getNumberOfStrings);
+		praat_addAction1 (classStrings, 1, U"Get string...", nullptr, 1, STRING_Strings_getString);
 	praat_addAction1 (classStrings, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classStrings, 0, U"Set string...", nullptr, 1, DO_Strings_setString);
-		praat_addAction1 (classStrings, 0, U"Insert string...", nullptr, 1, DO_Strings_insertString);
-		praat_addAction1 (classStrings, 0, U"Remove string...", nullptr, 1, DO_Strings_removeString);
+		praat_addAction1 (classStrings, 0, U"Set string...", nullptr, 1, MODIFY_Strings_setString);
+		praat_addAction1 (classStrings, 0, U"Insert string...", nullptr, 1, MODIFY_Strings_insertString);
+		praat_addAction1 (classStrings, 0, U"Remove string...", nullptr, 1, MODIFY_Strings_removeString);
 		praat_addAction1 (classStrings, 0, U"-- modify order --", nullptr, 1, nullptr);
-		praat_addAction1 (classStrings, 0, U"Randomize", nullptr, 1, DO_Strings_randomize);
-		praat_addAction1 (classStrings, 0, U"Sort", nullptr, 1, DO_Strings_sort);
+		praat_addAction1 (classStrings, 0, U"Randomize", nullptr, 1, MODIFY_Strings_randomize);
+		praat_addAction1 (classStrings, 0, U"Sort", nullptr, 1, MODIFY_Strings_sort);
 		praat_addAction1 (classStrings, 0, U"-- convert --", nullptr, 1, nullptr);
-		praat_addAction1 (classStrings, 0, U"Replace all...", nullptr, 1, DO_Strings_replaceAll);
-		praat_addAction1 (classStrings, 0, U"Genericize", nullptr, 1, DO_Strings_genericize);
-		praat_addAction1 (classStrings, 0, U"Nativize", nullptr, 1, DO_Strings_nativize);
+		praat_addAction1 (classStrings, 0, U"Convert to backslash trigraphs", nullptr, 1, MODIFY_Strings_genericize);
+		praat_addAction1 (classStrings, 0, U"Genericize", U"*Convert to backslash trigraphs", praat_DEPTH_1 | praat_DEPRECATED_2016, MODIFY_Strings_genericize);
+		praat_addAction1 (classStrings, 0, U"Convert to Unicode", nullptr, 1, MODIFY_Strings_nativize);
+		praat_addAction1 (classStrings, 0, U"Nativize", U"*Convert to Unicode", praat_DEPTH_1 | praat_DEPRECATED_2016, MODIFY_Strings_nativize);
+	praat_addAction1 (classStrings, 0, U"Convert -", nullptr, 0, nullptr);
+		praat_addAction1 (classStrings, 0, U"Replace all...", nullptr, 1, NEW_Strings_replaceAll);
 	praat_addAction1 (classStrings, 0, U"Analyze", nullptr, 0, nullptr);
-		praat_addAction1 (classStrings, 0, U"To Distributions", nullptr, 0, DO_Strings_to_Distributions);
+		praat_addAction1 (classStrings, 0, U"To Distributions", nullptr, 0, NEW_Strings_to_Distributions);
 	praat_addAction1 (classStrings, 0, U"Synthesize", nullptr, 0, nullptr);
-		praat_addAction1 (classStrings, 0, U"To WordList", nullptr, 0, DO_Strings_to_WordList);
+		praat_addAction1 (classStrings, 0, U"To WordList", nullptr, 0, NEW_Strings_to_WordList);
 
-	praat_addAction1 (classTable, 0, U"Down to Matrix", nullptr, 0, DO_Table_to_Matrix);
+	praat_addAction1 (classTable, 0, U"Down to Matrix", nullptr, 0, NEW_Table_to_Matrix);
 
-	praat_addAction1 (classTransition, 0, U"Transition help", nullptr, 0, DO_Transition_help);
+	praat_addAction1 (classTransition, 0, U"Transition help", nullptr, 0, HELP_Transition_help);
 praat_addAction1 (classTransition, 0, U"Draw", nullptr, 0, nullptr);
-	praat_addAction1 (classTransition, 0, U"Draw as numbers...", nullptr, 0, DO_Transition_drawAsNumbers);
+	praat_addAction1 (classTransition, 0, U"Draw as numbers...", nullptr, 0, GRAPHICS_Transition_drawAsNumbers);
 praat_addAction1 (classTransition, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classTransition, 0, U"Eigen", nullptr, 0, DO_Transition_eigen);
-	praat_addAction1 (classTransition, 0, U"Conflate", nullptr, 0, DO_Transition_conflate);
+	praat_addAction1 (classTransition, 0, U"Eigen", nullptr, 0, NEWTIMES2_Transition_eigen);
+	praat_addAction1 (classTransition, 0, U"Conflate", nullptr, 0, NEW_Transition_conflate);
 praat_addAction1 (classTransition, 0, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction1 (classTransition, 0, U"Power...", nullptr, 0, DO_Transition_power);
+	praat_addAction1 (classTransition, 0, U"Power...", nullptr, 0, NEW_Transition_power);
 praat_addAction1 (classTransition, 0, U"Cast", nullptr, 0, nullptr);
-	praat_addAction1 (classTransition, 0, U"To Matrix", nullptr, 0, DO_Transition_to_Matrix);
-
-	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_AmplitudeTier_edit);
-	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, U"Edit", nullptr, praat_HIDDEN, DO_AmplitudeTier_edit);   // hidden 2011
-	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, U"Multiply", nullptr, 0, DO_Sound_AmplitudeTier_multiply);
-	praat_addAction2 (classDistributions, 1, classTransition, 1, U"Map", nullptr, 0, DO_Distributions_Transition_map);
-	praat_addAction2 (classDistributions, 1, classTransition, 1, U"To Transition...", nullptr, 0, DO_Distributions_to_Transition_adj);
-	praat_addAction2 (classDistributions, 2, classTransition, 1, U"To Transition (noise)...", nullptr, 0, DO_Distributions_to_Transition_noise_adj);
-	praat_addAction2 (classDurationTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_DurationTier_edit);
-	praat_addAction2 (classDurationTier, 1, classSound, 1, U"Edit", nullptr, praat_HIDDEN, DO_DurationTier_edit);
-	praat_addAction2 (classFormant, 1, classPointProcess, 1, U"To FormantTier", nullptr, 0, DO_Formant_PointProcess_to_FormantTier);
-	praat_addAction2 (classFormant, 1, classSound, 1, U"Filter", nullptr, 0, DO_Sound_Formant_filter);
-	praat_addAction2 (classFormant, 1, classSound, 1, U"Filter (no scale)", nullptr, 0, DO_Sound_Formant_filter_noscale);
-	praat_addAction2 (classFormantGrid, 1, classSound, 1, U"Filter", nullptr, 0, DO_Sound_FormantGrid_filter);
-	praat_addAction2 (classFormantGrid, 1, classSound, 1, U"Filter (no scale)", nullptr, 0, DO_Sound_FormantGrid_filter_noscale);
-	praat_addAction2 (classFormantTier, 1, classSound, 1, U"Filter", nullptr, 0, DO_Sound_FormantTier_filter);
-	praat_addAction2 (classFormantTier, 1, classSound, 1, U"Filter (no scale)", nullptr, 0, DO_Sound_FormantTier_filter_noscale);
+	praat_addAction1 (classTransition, 0, U"To Matrix", nullptr, 0, NEW_Transition_to_Matrix);
+
+	praat_addAction2 (classDistributions, 1, classTransition, 1, U"Map", nullptr, 0, NEW1_Distributions_Transition_map);
+	praat_addAction2 (classDistributions, 1, classTransition, 1, U"To Transition...", nullptr, 0, NEW1_Distributions_to_Transition_adj);
+	praat_addAction2 (classDistributions, 2, classTransition, 1, U"To Transition (noise)...", nullptr, 0, NEW1_Distributions_to_Transition_noise_adj);
+
+	praat_addAction2 (classFormant, 1, classPointProcess, 1, U"To FormantTier", nullptr, 0, NEW1_Formant_PointProcess_to_FormantTier);
+	praat_addAction2 (classFormant, 1, classSound, 1, U"Filter", nullptr, 0, NEW1_Sound_Formant_filter);
+	praat_addAction2 (classFormant, 1, classSound, 1, U"Filter (no scale)", nullptr, 0, NEW1_Sound_Formant_filter_noscale);
 	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Draw", nullptr, 0, nullptr);
-	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Draw (phonetogram)...", nullptr, 0, DO_Pitch_Intensity_draw);
-	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Speckle (phonetogram)...", nullptr, praat_HIDDEN, DO_Pitch_Intensity_speckle);   /* grandfathered 2005 */
-	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Get mean", nullptr, 1, DO_Pitch_Intensity_getMean);
-	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Get mean absolute slope", nullptr, 1, DO_Pitch_Intensity_getMeanAbsoluteSlope);
-	praat_addAction2 (classIntensity, 1, classPointProcess, 1, U"To IntensityTier", nullptr, 0, DO_Intensity_PointProcess_to_IntensityTier);
-	praat_addAction2 (classIntensityTier, 1, classPointProcess, 1, U"To IntensityTier", nullptr, 0, DO_IntensityTier_PointProcess_to_IntensityTier);
-	praat_addAction2 (classIntensityTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_IntensityTier_edit);
-	praat_addAction2 (classIntensityTier, 1, classSound, 1, U"Edit", nullptr, praat_HIDDEN, DO_IntensityTier_edit);
-	praat_addAction2 (classIntensityTier, 1, classSound, 1, U"Multiply", nullptr, praat_HIDDEN, DO_Sound_IntensityTier_multiply_old);
-	praat_addAction2 (classIntensityTier, 1, classSound, 1, U"Multiply...", nullptr, 0, DO_Sound_IntensityTier_multiply);
-	praat_addAction2 (classManipulation, 1, classSound, 1, U"Replace original sound", nullptr, 0, DO_Manipulation_replaceOriginalSound);
-	praat_addAction2 (classManipulation, 1, classPointProcess, 1, U"Replace pulses", nullptr, 0, DO_Manipulation_replacePulses);
-	praat_addAction2 (classManipulation, 1, classPitchTier, 1, U"Replace pitch tier", nullptr, 0, DO_Manipulation_replacePitchTier);
-	praat_addAction2 (classManipulation, 1, classDurationTier, 1, U"Replace duration tier", nullptr, 0, DO_Manipulation_replaceDurationTier);
-	praat_addAction2 (classManipulation, 1, classTextTier, 1, U"To Manipulation", nullptr, 0, DO_Manipulation_TextTier_to_Manipulation);
-	praat_addAction2 (classMatrix, 1, classSound, 1, U"To ParamCurve", nullptr, 0, DO_Matrix_to_ParamCurve);
-	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace red", nullptr, 0, DO_Photo_Matrix_replaceRed);
-	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace green", nullptr, 0, DO_Photo_Matrix_replaceGreen);
-	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace blue", nullptr, 0, DO_Photo_Matrix_replaceBlue);
-	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace transparency", nullptr, 0, DO_Photo_Matrix_replaceTransparency);
-	praat_addAction2 (classPitch, 1, classPitchTier, 1, U"Draw...", nullptr, 0, DO_PitchTier_Pitch_draw);
-	praat_addAction2 (classPitch, 1, classPitchTier, 1, U"To Pitch", nullptr, 0, DO_Pitch_PitchTier_to_Pitch);
-	praat_addAction2 (classPitch, 1, classPointProcess, 1, U"To PitchTier", nullptr, 0, DO_Pitch_PointProcess_to_PitchTier);
-	praat_addAction3 (classPitch, 1, classPointProcess, 1, classSound, 1, U"Voice report...", nullptr, 0, DO_Sound_Pitch_PointProcess_voiceReport);
-	praat_addAction2 (classPitch, 1, classSound, 1, U"To PointProcess (cc)", nullptr, 0, DO_Sound_Pitch_to_PointProcess_cc);
-	praat_addAction2 (classPitch, 1, classSound, 1, U"To PointProcess (peaks)...", nullptr, 0, DO_Sound_Pitch_to_PointProcess_peaks);
-	praat_addAction2 (classPitch, 1, classSound, 1, U"To Manipulation", nullptr, 0, DO_Sound_Pitch_to_Manipulation);
-	praat_addAction2 (classPitchTier, 1, classPointProcess, 1, U"To PitchTier", nullptr, 0, DO_PitchTier_PointProcess_to_PitchTier);
-	praat_addAction2 (classPitchTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_PitchTier_edit);
-	praat_addAction2 (classPitchTier, 1, classSound, 1, U"Edit", nullptr, praat_HIDDEN, DO_PitchTier_edit);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_PointProcess_edit);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Edit", nullptr, praat_HIDDEN, DO_PointProcess_edit);
-praat_addAction2 (classPointProcess, 1, classSound, 1, U"Query", nullptr, 0, nullptr);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (local)...", nullptr, 0, DO_Point_Sound_getShimmer_local);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (local_dB)...", nullptr, 0, DO_Point_Sound_getShimmer_local_dB);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (apq3)...", nullptr, 0, DO_Point_Sound_getShimmer_apq3);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (apq5)...", nullptr, 0, DO_Point_Sound_getShimmer_apq5);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (apq11)...", nullptr, 0, DO_Point_Sound_getShimmer_apq11);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (dda)...", nullptr, 0, DO_Point_Sound_getShimmer_dda);
-praat_addAction2 (classPointProcess, 1, classSound, 1, U"Modify", nullptr, 0, nullptr);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Transplant time domain", nullptr, 0, DO_Point_Sound_transplantDomain);
-praat_addAction2 (classPointProcess, 1, classSound, 1, U"Analyse", nullptr, 0, nullptr);
-	/*praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Manipulation", nullptr, 0, DO_Sound_PointProcess_to_Manipulation);*/
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To AmplitudeTier (point)", nullptr, 0, DO_PointProcess_Sound_to_AmplitudeTier_point);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To AmplitudeTier (period)...", nullptr, 0, DO_PointProcess_Sound_to_AmplitudeTier_period);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Ltas...", nullptr, 0, DO_PointProcess_Sound_to_Ltas);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Ltas (only harmonics)...", nullptr, 0, DO_PointProcess_Sound_to_Ltas_harmonics);
-praat_addAction2 (classPointProcess, 1, classSound, 1, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Sound ensemble...", nullptr, 0, DO_Sound_PointProcess_to_SoundEnsemble_correlate);
-
-	praat_addAction4 (classDurationTier, 1, classPitchTier, 1, classPointProcess, 1, classSound, 1, U"To Sound...", nullptr, 0, DO_Sound_Point_Pitch_Duration_to_Sound);
+	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Draw (phonetogram)...", nullptr, 0, GRAPHICS_Pitch_Intensity_draw);
+	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Get mean", nullptr, 1, REAL_Pitch_Intensity_getMean);
+	praat_addAction2 (classIntensity, 1, classPitch, 1, U"Get mean absolute slope", nullptr, 1, REAL_Pitch_Intensity_getMeanAbsoluteSlope);
+	praat_addAction2 (classIntensity, 1, classPointProcess, 1, U"To IntensityTier", nullptr, 0, NEW1_Intensity_PointProcess_to_IntensityTier);
+
+	praat_addAction2 (classManipulation, 1, classSound, 1, U"Replace original sound", nullptr, 0, MODIFY_Manipulation_replaceOriginalSound);
+	praat_addAction2 (classManipulation, 1, classPointProcess, 1, U"Replace pulses", nullptr, 0, MODIFY_Manipulation_replacePulses);
+	praat_addAction2 (classManipulation, 1, classPitchTier, 1, U"Replace pitch tier", nullptr, 0, MODIFY_Manipulation_replacePitchTier);
+	praat_addAction2 (classManipulation, 1, classDurationTier, 1, U"Replace duration tier", nullptr, 0, MODIFY_Manipulation_replaceDurationTier);
+	praat_addAction2 (classManipulation, 1, classTextTier, 1, U"To Manipulation", nullptr, 0, NEW1_Manipulation_TextTier_to_Manipulation);
+	praat_addAction2 (classPitch, 1, classPitchTier, 1, U"Draw...", nullptr, 0, GRAPHICS_PitchTier_Pitch_draw);
+	praat_addAction2 (classPitch, 1, classPitchTier, 1, U"To Pitch", nullptr, 0, NEW1_Pitch_PitchTier_to_Pitch);
+	praat_addAction2 (classPitch, 1, classPointProcess, 1, U"To PitchTier", nullptr, 0, NEW1_Pitch_PointProcess_to_PitchTier);
+	praat_addAction3 (classPitch, 1, classPointProcess, 1, classSound, 1, U"Voice report...", nullptr, 0, INFO_Sound_Pitch_PointProcess_voiceReport);
+	praat_addAction2 (classPitch, 1, classSound, 1, U"To PointProcess (cc)", nullptr, 0, NEW1_Sound_Pitch_to_PointProcess_cc);
+	praat_addAction2 (classPitch, 1, classSound, 1, U"To PointProcess (peaks)...", nullptr, 0, NEW1_Sound_Pitch_to_PointProcess_peaks);
+	praat_addAction2 (classPitch, 1, classSound, 1, U"To Manipulation", nullptr, 0, NEW1_Sound_Pitch_to_Manipulation);
+
+	praat_addAction4 (classDurationTier, 1, classPitchTier, 1, classPointProcess, 1, classSound, 1, U"To Sound...", nullptr, 0, NEW1_Sound_Point_Pitch_Duration_to_Sound);
 
 	INCLUDE_MANPAGES (manual_Manual_init)
 	INCLUDE_MANPAGES (manual_Script_init)
@@ -7290,7 +3406,7 @@ praat_addAction2 (classPointProcess, 1, classSound, 1, U"Synthesize", nullptr, 0
 	INCLUDE_MANPAGES (manual_voice_init)
 	INCLUDE_MANPAGES (manual_programming_init)
 	INCLUDE_MANPAGES (manual_gram_init)
-	INCLUDE_MANPAGES (manual_Exp_init)
+	INCLUDE_MANPAGES (manual_ExperimentMFC_init)
 	INCLUDE_MANPAGES (manual_EEG_init)
 
 	INCLUDE_LIBRARY (praat_EEG_init)
@@ -7301,7 +3417,7 @@ praat_addAction2 (classPointProcess, 1, classSound, 1, U"Synthesize", nullptr, 0
 	INCLUDE_LIBRARY (praat_uvafon_gram_init)
 	INCLUDE_LIBRARY (praat_uvafon_FFNet_init)
 	INCLUDE_LIBRARY (praat_uvafon_LPC_init)
-	INCLUDE_LIBRARY (praat_uvafon_Exp_init)
+	praat_ExperimentMFC_init ();
 }
 
 /* End of file praat_Fon.cpp */
diff --git a/fon/praat_Matrix.cpp b/fon/praat_Matrix.cpp
new file mode 100644
index 0000000..d3e0d97
--- /dev/null
+++ b/fon/praat_Matrix.cpp
@@ -0,0 +1,927 @@
+/* praat_Matrix.cpp
+ *
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Cochleagram.h"
+#include "Excitation.h"
+#include "Harmonicity.h"
+#include "Intensity.h"
+#include "Ltas.h"
+#include "Matrix_and_PointProcess.h"
+#include "Matrix_and_Polygon.h"
+#include "Matrix_and_Pitch.h"
+#include "MovieWindow.h"
+#include "ParamCurve.h"
+#include "Photo.h"
+#include "Spectrogram.h"
+#include "Spectrum.h"
+#include "Transition.h"
+#include "VocalTract.h"
+
+#include "praat_Matrix.h"
+
+#undef iam
+#define iam iam_LOOP
+
+int praat_Matrix_formula (UiForm dia, Interpreter interpreter) {
+	int IOBJECT;
+	LOOP {
+		iam (Matrix);
+		try {
+			Matrix_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			throw;
+		}
+	}
+	return 1;
+}
+
+// MARK: - MATRIX
+
+// MARK: New
+
+FORM (NEW1_Matrix_create, U"Create Matrix", U"Create Matrix...") {
+	WORD4 (name, U"Name", U"xy")
+	REAL4 (xmin, U"xmin", U"1.0")
+	REAL4 (xmax, U"xmax", U"1.0")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"1")
+	POSITIVE4 (dx, U"dx", U"1.0")
+	REAL4 (x1, U"x1", U"1.0")
+	REAL4 (ymin, U"ymin", U"1.0")
+	REAL4 (ymax, U"ymax", U"1.0")
+	NATURAL4 (numberOfRows, U"Number of rows", U"1")
+	POSITIVE4 (dy, U"dy", U"1.0")
+	REAL4 (y1, U"y1", U"1.0")
+	LABEL (U"", U"Formula:")
+	TEXTFIELD4 (formula, U"formula", U"x*y")
+	OK
+DO
+	if (xmax < xmin) Melder_throw (U"Your xmax (", Melder_single (xmax), U") should not be less than your xmin (", Melder_single (xmin), U").");
+	if (ymax < ymin) Melder_throw (U"Your ymax (", Melder_single (ymax), U") should not be less than your ymin (", Melder_single (ymin), U").");
+	CREATE_ONE
+		autoMatrix result = Matrix_create (
+			xmin, xmax, numberOfColumns, dx, x1,
+			ymin, ymax, numberOfRows, dy, y1);
+		Matrix_formula (result.get(), formula, interpreter, nullptr);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_Matrix_createSimple, U"Create simple Matrix", U"Create simple Matrix...") {
+	WORD4 (name, U"Name", U"xy")
+	NATURAL4 (numberOfRows, U"Number of rows", U"10")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"10")
+	LABEL (U"", U"Formula:")
+	TEXTFIELD4 (formula, U"formula", U"x*y")
+	OK
+DO
+	CREATE_ONE
+		autoMatrix result = Matrix_createSimple (numberOfRows, numberOfColumns);
+		Matrix_formula (result.get(), formula, interpreter, nullptr);
+	CREATE_ONE_END (name);
+}
+
+// MARK: Open
+
+FORM_READ (READ1_Matrix_readFromRawTextFile, U"Read Matrix from raw text file", nullptr, true) {
+	READ_ONE
+		autoMatrix result = Matrix_readFromRawTextFile (file);
+	READ_ONE_END
+}
+
+FORM_READ (READ1_Matrix_readAP, U"Read Matrix from LVS AP file", nullptr, true) {
+	READ_ONE
+		autoMatrix result = Matrix_readAP (file);
+	READ_ONE_END
+}
+
+// MARK: Save
+
+FORM_SAVE (SAVE_Matrix_writeToMatrixTextFile, U"Save Matrix as matrix text file", nullptr, U"mat") {
+	FIND_ONE (Matrix)
+		Matrix_writeToMatrixTextFile (me, file);
+	END
+}
+
+FORM_SAVE (SAVE_Matrix_writeToHeaderlessSpreadsheetFile, U"Save Matrix as spreadsheet", nullptr, U"txt") {
+	FIND_ONE (Matrix)
+		Matrix_writeToHeaderlessSpreadsheetFile (me, file);
+	END
+}
+
+// MARK: Help
+
+DIRECT (HELP_Matrix_help) {
+	HELP (U"Matrix")
+}
+
+// MARK: Movie
+
+static autoGraphics theMovieGraphics;
+
+static void gui_drawingarea_cb_expose (Thing /* boss */, GuiDrawingArea_ExposeEvent /* event */) {
+	if (! theMovieGraphics) return;
+	Graphics_play (theMovieGraphics.get(), theMovieGraphics.get());
+}
+
+extern "C" Graphics Movie_create (const char32 *title, int width, int height) {
+	static GuiDialog dialog;
+	static GuiDrawingArea drawingArea;
+	if (! theMovieGraphics) {
+		dialog = GuiDialog_create (theCurrentPraatApplication -> topShell, 100, 100, width + 2, height + 2, title, nullptr, nullptr, 0);
+		drawingArea = GuiDrawingArea_createShown (dialog, 0, width, 0, height, gui_drawingarea_cb_expose, nullptr, nullptr, nullptr, nullptr, 0);
+		GuiThing_show (dialog);
+		theMovieGraphics = Graphics_create_xmdrawingarea (drawingArea);
+	}
+	GuiShell_setTitle (dialog, title);
+	GuiControl_setSize (dialog, width + 2, height + 2);
+	GuiControl_setSize (drawingArea, width, height);
+	GuiThing_show (dialog);
+	return theMovieGraphics.get();
+}
+
+DIRECT (MOVIE_Matrix_movie) {
+	MOVIE_ONE (Matrix, U"Matrix movie", 300, 300)
+		Matrix_movie (me, graphics);
+	MOVIE_ONE_END
+}
+
+// MARK: Draw
+
+FORM (GRAPHICS_Matrix_drawRows, U"Draw rows", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (minimum, U"Minimum", U"0.0")
+	REAL4 (maximum, U"Maximum", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawRows (me, GRAPHICS, fromX, toX, fromY, toY, minimum, maximum);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Matrix_drawOneContour, U"Draw one altitude contour", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (height, U"Height", U"0.5")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawOneContour (me, GRAPHICS,fromX, toX, fromY, toY, height);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Matrix_drawContours, U"Draw altitude contours", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (minimum, U"Minimum", U"0.0")
+	REAL4 (maximum, U"Maximum", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_drawContours (me, GRAPHICS, fromX, toX, fromY, toY, minimum, maximum);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Matrix_paintImage, U"Matrix: Paint grey image", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (minimum, U"Minimum", U"0.0")
+	REAL4 (maximum, U"Maximum", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintImage (me, GRAPHICS, fromX, toX, fromY, toY, minimum, maximum);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Matrix_paintContours, U"Matrix: Paint altitude contours with greys", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (minimum, U"Minimum", U"0.0")
+	REAL4 (maximum, U"Maximum", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintContours (me, GRAPHICS, fromX, toX, fromY, toY, minimum, maximum);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Matrix_paintCells, U"Matrix: Paint cells with greys", U"Matrix: Paint cells...") {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (minimum, U"Minimum", U"0.0")
+	REAL4 (maximum, U"Maximum", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintCells (me, GRAPHICS, fromX, toX, fromY, toY, minimum, maximum);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Matrix_paintSurface, U"Matrix: Paint 3-D surface plot", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	REAL4 (minimum, U"Minimum", U"0.0")
+	REAL4 (maximum, U"Maximum", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Matrix)
+		Matrix_paintSurface (me, GRAPHICS, fromX, toX, fromY, toY, minimum, maximum, 30, 45);
+	GRAPHICS_EACH_END
+}
+
+// MARK: Query
+
+DIRECT (REAL_Matrix_getLowestX) {
+	NUMBER_ONE (Matrix)
+		double result = my xmin;
+	NUMBER_ONE_END (U" (xmin)")
+}
+
+DIRECT (REAL_Matrix_getHighestX) {
+	NUMBER_ONE (Matrix)
+		double result = my xmax;
+	NUMBER_ONE_END (U" (xmax)")
+}
+
+DIRECT (REAL_Matrix_getLowestY) {
+	NUMBER_ONE (Matrix)
+		double result = my ymin;
+	NUMBER_ONE_END (U" (ymin)")
+}
+
+DIRECT (REAL_Matrix_getHighestY) {
+	NUMBER_ONE (Matrix)
+		double result = my ymax;
+	NUMBER_ONE_END (U" (xmax)")
+}
+
+DIRECT (INTEGER_Matrix_getNumberOfRows) {
+	NUMBER_ONE (Matrix)
+		long result = my ny;
+	NUMBER_ONE_END (U" rows")
+}
+
+DIRECT (INTEGER_Matrix_getNumberOfColumns) {
+	NUMBER_ONE (Matrix)
+		long result = my nx;
+	NUMBER_ONE_END (U" columns")
+}
+
+DIRECT (REAL_Matrix_getRowDistance) {
+	NUMBER_ONE (Matrix)
+		double result = my dy;
+	NUMBER_ONE_END (U" (row distance)")
+}
+
+DIRECT (REAL_Matrix_getColumnDistance) {
+	NUMBER_ONE (Matrix)
+		double result = my dx;
+	NUMBER_ONE_END (U" (column distance)")
+}
+
+FORM (REAL_Matrix_getYofRow, U"Matrix: Get y of row", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
+DO
+	NUMBER_ONE (Matrix)
+		double result = Matrix_rowToY (me, rowNumber);
+	NUMBER_ONE_END (U" (y of row ", rowNumber, U")")
+}
+
+FORM (REAL_Matrix_getXofColumn, U"Matrix: Get x of column", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	NUMBER_ONE (Matrix)
+		double result = Matrix_columnToX (me, columnNumber);
+	NUMBER_ONE_END (U" (x of column ", columnNumber, U")")
+}
+
+FORM (REAL_Matrix_getValueInCell, U"Matrix: Get value in cell", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	NUMBER_ONE (Matrix)
+		if (rowNumber > my ny) Melder_throw (U"Row number must not exceed number of rows.");
+		if (columnNumber > my nx) Melder_throw (U"Column number must not exceed number of columns.");
+		double result = my z [rowNumber] [columnNumber];
+	NUMBER_ONE_END (U" (value in column ", columnNumber, U" of row ", rowNumber, U")")
+}
+
+FORM (REAL_Matrix_getValueAtXY, U"Matrix: Get value at xy", nullptr) {
+	REALVAR (x, U"X", U"0.0")
+	REALVAR (y, U"Y", U"0.0")
+	OK
+DO
+	NUMBER_ONE (Matrix)
+		double result = Matrix_getValueAtXY (me, x, y);
+	NUMBER_ONE_END (U" (at x = ", x, U" and y = ", y, U")");
+}
+
+DIRECT (REAL_Matrix_getMinimum) {
+	NUMBER_ONE (Matrix)
+		double minimum = NUMundefined, maximum = NUMundefined;
+		Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
+		double result = minimum;
+	NUMBER_ONE_END (U" (minimum)");
+}
+
+DIRECT (REAL_Matrix_getMaximum) {
+	NUMBER_ONE (Matrix)
+		double minimum = NUMundefined, maximum = NUMundefined;
+		Matrix_getWindowExtrema (me, 0, 0, 0, 0, & minimum, & maximum);
+		double result = maximum;
+	NUMBER_ONE_END (U" (maximum)");
+}
+
+DIRECT (REAL_Matrix_getSum) {
+	NUMBER_ONE (Matrix)
+		double result = Matrix_getSum (me);
+	NUMBER_ONE_END (U" (sum)");
+}
+
+// MARK: Modify
+
+FORM (MODIFY_Matrix_formula, U"Matrix Formula", U"Formula...") {
+	LABEL (U"label", U"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 }")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
+DO
+	MODIFY_EACH_WEAK (Matrix)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_Matrix_setValue, U"Matrix: Set value", U"Matrix: Set value...") {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL4 (newValue, U"New value", U"0.0")
+	OK
+DO
+	MODIFY_EACH (Matrix)
+		if (rowNumber > my ny)
+			Melder_throw (U"Your row number should not be greater than your number of rows.");
+		if (columnNumber > my nx)
+			Melder_throw (U"Your column number should not be greater than your number of columns.");
+		my z [rowNumber] [columnNumber] = newValue;
+	MODIFY_EACH_END
+}
+
+// MARK: Analyse
+
+DIRECT (NEWTIMES2_Matrix_eigen) {
+	LOOP {
+		iam_LOOP (Matrix);
+		autoMatrix vectors, values;
+		Matrix_eigen (me, & vectors, & values);
+		praat_new (vectors.move(), U"eigenvectors");
+		praat_new (values.move(), U"eigenvalues");
+	}
+END }
+
+// MARK: Synthesize
+
+FORM (NEW_Matrix_power, U"Matrix: Power...", nullptr) {
+	NATURAL4 (power, U"Power", U"2")
+	OK
+DO
+	CONVERT_EACH (Matrix)
+		autoMatrix result = Matrix_power (me, power);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: Combine
+
+DIRECT (NEW1_Matrix_appendRows) {
+	CONVERT_COUPLE (Matrix)
+		autoMatrix result = Matrix_appendRows (me, you, classMatrix);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
+
+// MARK: Cast
+
+DIRECT (NEW_Matrix_to_Cochleagram) {
+	CONVERT_EACH (Matrix)
+		autoCochleagram result = Matrix_to_Cochleagram (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Excitation) {
+	CONVERT_EACH (Matrix)
+		autoExcitation result = Matrix_to_Excitation (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Harmonicity) {
+	CONVERT_EACH (Matrix)
+		autoHarmonicity result = Matrix_to_Harmonicity (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Intensity) {
+	CONVERT_EACH (Matrix)
+		autoIntensity result = Matrix_to_Intensity (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Ltas) {
+	CONVERT_EACH (Matrix)
+		autoLtas result = Matrix_to_Ltas (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Pitch) {
+	CONVERT_EACH (Matrix)
+		autoPitch result = Matrix_to_Pitch (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_PointProcess) {
+	CONVERT_EACH (Matrix)
+		autoPointProcess result = Matrix_to_PointProcess (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Polygon) {
+	CONVERT_EACH (Matrix)
+		autoPolygon result = Matrix_to_Polygon (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Sound) {
+	CONVERT_EACH (Matrix)
+		autoSound result = Matrix_to_Sound (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Matrix_to_Sound_mono, U"Matrix: To Sound (mono)", 0) {
+	INTEGER4 (rowNumber, U"Row number", U"1")
+	LABEL (U"", U"(negative values count from last row)")
+	OK
+DO
+	CONVERT_EACH (Matrix)
+		autoSound result = Matrix_to_Sound_mono (me, rowNumber);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Spectrogram) {
+	CONVERT_EACH (Matrix)
+		autoSpectrogram result = Matrix_to_Spectrogram (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Spectrum) {
+	CONVERT_EACH (Matrix)
+		autoSpectrum result = Matrix_to_Spectrum (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_TableOfReal) {
+	CONVERT_EACH (Matrix)
+		autoTableOfReal result = Matrix_to_TableOfReal (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_Transition) {
+	CONVERT_EACH (Matrix)
+		autoTransition result = Matrix_to_Transition (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Matrix_to_VocalTract) {
+	CONVERT_EACH (Matrix)
+		autoVocalTract result = Matrix_to_VocalTract (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW1_Matrix_to_ParamCurve) {
+	CONVERT_COUPLE (Matrix)
+		autoSound sound1 = Matrix_to_Sound (me), sound2 = Matrix_to_Sound (you);
+		autoParamCurve result = ParamCurve_create (sound1.get(), sound2.get());
+	CONVERT_COUPLE_END (my name, U"_", your name);
+}
+
+// MARK: - PHOTO
+
+// MARK: New
+
+FORM (NEW1_Photo_create, U"Create Photo", U"Create Photo...") {
+	WORD4 (name, U"Name", U"xy")
+	REAL4 (xmin, U"xmin", U"1.0")
+	REAL4 (xmax, U"xmax", U"1.0")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"1")
+	POSITIVE4 (dx, U"dx", U"1.0")
+	REAL4 (x1, U"x1", U"1.0")
+	REAL4 (ymin, U"ymin", U"1.0")
+	REAL4 (ymax, U"ymax", U"1.0")
+	NATURAL4 (numberOfRows, U"Number of rows", U"1")
+	POSITIVE4 (dy, U"dy", U"1.0")
+	REAL4 (y1, U"y1", U"1.0")
+	LABEL (U"", U"Red formula:")
+	TEXTFIELD4 (redFormula, U"redFormula", U"x*y/100")
+	LABEL (U"", U"Green formula:")
+	TEXTFIELD4 (greenFormula, U"greenFormula", U"x*y/1000")
+	LABEL (U"", U"Blue formula:")
+	TEXTFIELD4 (blueFormula, U"blueFormula", U"x*y/100")
+	OK
+DO
+	if (xmax < xmin)
+		Melder_throw (U"Your xmax (", Melder_single (xmax), U") should not be less than your xmin (", Melder_single (xmin), U").");
+	if (ymax < ymin)
+		Melder_throw (U"Your ymax (", Melder_single (ymax), U") should not be less than your ymin (", Melder_single (ymin), U").");
+	CREATE_ONE
+		autoPhoto result = Photo_create (
+			xmin, xmax, numberOfColumns, dx, x1,
+			ymin, ymax, numberOfRows, dy, y1);
+		Matrix_formula (result -> d_red  .get(), redFormula,   interpreter, nullptr);
+		Matrix_formula (result -> d_green.get(), greenFormula, interpreter, nullptr);
+		Matrix_formula (result -> d_blue .get(), blueFormula,  interpreter, nullptr);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_Photo_createSimple, U"Create simple Photo", U"Create simple Photo...") {
+	WORD4 (name, U"Name", U"xy")
+	NATURAL4 (numberOfRows, U"Number of rows", U"10")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"10")
+	LABEL (U"", U"Red formula:")
+	TEXTFIELD4 (redFormula, U"redFormula", U"x*y/100")
+	LABEL (U"", U"Green formula:")
+	TEXTFIELD4 (greenFormula, U"greenFormula", U"x*y/1000")
+	LABEL (U"", U"Blue formula:")
+	TEXTFIELD4 (blueFormula, U"blueFormula", U"x*y/100")
+	OK
+DO
+	CREATE_ONE
+		autoPhoto result = Photo_createSimple (numberOfRows, numberOfColumns);
+		Matrix_formula (result -> d_red.get(),   redFormula,   interpreter, nullptr);
+		Matrix_formula (result -> d_green.get(), greenFormula, interpreter, nullptr);
+		Matrix_formula (result -> d_blue.get(),  blueFormula,  interpreter, nullptr);
+	CREATE_ONE_END (name)
+}
+
+DIRECT (NEW_Photo_extractBlue) {
+	CONVERT_EACH (Photo)
+		autoMatrix result = Data_copy (my d_blue.get());
+	CONVERT_EACH_END (my name, U"_blue");
+}
+
+DIRECT (NEW_Photo_extractGreen) {
+	CONVERT_EACH (Photo)
+		autoMatrix result = Data_copy (my d_green.get());
+	CONVERT_EACH_END (my name, U"_green");
+}
+
+DIRECT (NEW_Photo_extractRed) {
+	CONVERT_EACH (Photo)
+		autoMatrix result = Data_copy (my d_red.get());
+	CONVERT_EACH_END (my name, U"_red");
+}
+
+DIRECT (NEW_Photo_extractTransparency) {
+	CONVERT_EACH (Photo)
+		autoMatrix result = Data_copy (my d_transparency.get());
+	CONVERT_EACH_END (my name, U"_transparency");
+}
+
+FORM (MODIFY_Photo_formula_red, U"Photo Formula (red)", U"Formula (red)...") {
+	LABEL (U"label", U"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 }")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
+DO
+	MODIFY_EACH_WEAK (Photo)
+		Matrix_formula (my d_red.get(), formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_Photo_formula_green, U"Photo Formula (green)", U"Formula (green)...") {
+	LABEL (U"label", U"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 }")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
+DO
+	MODIFY_EACH_WEAK (Photo)
+		Matrix_formula (my d_green.get(), formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_Photo_formula_blue, U"Photo Formula (blue)", U"Formula (blue)...") {
+	LABEL (U"label", U"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 }")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
+DO
+	MODIFY_EACH_WEAK (Photo)
+		Matrix_formula (my d_blue.get(), formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_Photo_formula_transparency, U"Photo Formula (transparency)", U"Formula (transparency)...") {
+	LABEL (U"label", U"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 }")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	OK
+DO
+	MODIFY_EACH_WEAK (Photo)
+		Matrix_formula (my d_transparency.get(), formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (GRAPHICS_Photo_paintCells, U"Photo: Paint cells with colour", U"Photo: Paint cells...") {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Photo)
+		Photo_paintCells (me, GRAPHICS, fromX, toX, fromY, toY);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Photo_paintImage, U"Photo: Paint colour image", nullptr) {
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"0.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"0.0")
+	OK
+DO
+	GRAPHICS_EACH (Photo)
+		Photo_paintImage (me, GRAPHICS, fromX, toX, fromY, toY);
+	GRAPHICS_EACH_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsAppleIconFile, U"Save as Apple icon file", nullptr, U"icns") {
+	SAVE_ONE (Photo)
+		Photo_saveAsAppleIconFile (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsGIF, U"Save as GIF file", nullptr, U"gif") {
+	SAVE_ONE (Photo)
+		Photo_saveAsGIF (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsJPEG, U"Save as JPEG file", nullptr, U"jpg") {
+	SAVE_ONE (Photo)
+		Photo_saveAsJPEG (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsJPEG2000, U"Save as JPEG-2000 file", nullptr, U"jpg") {
+	SAVE_ONE (Photo)
+		Photo_saveAsJPEG2000 (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsPNG, U"Save as PNG file", nullptr, U"png") {
+	SAVE_ONE (Photo)
+		Photo_saveAsPNG (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsTIFF, U"Save as TIFF file", nullptr, U"tiff") {
+	SAVE_ONE (Photo)
+		Photo_saveAsTIFF (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsWindowsBitmapFile, U"Save as Windows bitmap file", nullptr, U"bmp") {
+	SAVE_ONE (Photo)
+		Photo_saveAsWindowsBitmapFile (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Photo_saveAsWindowsIconFile, U"Save as Windows icon file", nullptr, U"ico") {
+	SAVE_ONE (Photo)
+		Photo_saveAsWindowsIconFile (me, file);
+	SAVE_ONE_END
+}
+
+// MARK: - PHOTO & MATRIX
+
+DIRECT (MODIFY_Photo_Matrix_replaceBlue) {
+	MODIFY_FIRST_OF_TWO (Photo, Matrix)
+		Photo_replaceBlue (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+DIRECT (MODIFY_Photo_Matrix_replaceGreen) {
+	MODIFY_FIRST_OF_TWO (Photo, Matrix)
+		Photo_replaceGreen (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+DIRECT (MODIFY_Photo_Matrix_replaceRed) {
+	MODIFY_FIRST_OF_TWO (Photo, Matrix)
+		Photo_replaceRed (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+DIRECT (MODIFY_Photo_Matrix_replaceTransparency) {
+	MODIFY_FIRST_OF_TWO (Photo, Matrix)
+		Photo_replaceTransparency (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+// MARK: - MOVIE
+
+FORM_READ (READ1_Movie_openFromSoundFile, U"Open movie file", nullptr, true) {
+	READ_ONE
+		autoMovie result = Movie_openFromSoundFile (file);
+	READ_ONE_END   // but loses data when saving, if object is associated only with the sound file
+}
+
+FORM (GRAPHICS_Movie_paintOneImage, U"Movie: Paint one image", nullptr) {
+	NATURAL4 (frameNumber, U"Frame number", U"1")
+	REAL4 (fromX, U"From x =", U"0.0")
+	REAL4 (toX, U"To x =", U"1.0")
+	REAL4 (fromY, U"From y =", U"0.0")
+	REAL4 (toY, U"To y =", U"1.0")
+	OK
+DO
+	GRAPHICS_EACH (Movie)
+		Movie_paintOneImage (me, GRAPHICS, frameNumber, fromX, toX, fromY, toY);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (WINDOW_Movie_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Movie from batch.");
+	LOOP {
+		iam (Movie);
+		autoMovieWindow editor = MovieWindow_create (ID_AND_FULL_NAME, me);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+// MARK: file recognizers
+
+static autoDaata imageFileRecognizer (int /* nread */, const char * /* header */, MelderFile file) {
+	const char32 *fileName = MelderFile_name (file);
+	if (Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".jpg") ||
+	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".JPG") ||
+	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".jpeg") ||
+		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".JPEG") ||
+	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".png") ||
+		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".PNG") ||
+	    Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".tiff") ||
+		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".TIFF") ||
+		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".tif") ||
+		Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".TIF"))
+	{
+		return Photo_readFromImageFile (file);
+	}
+	return autoDaata ();
+}
+
+// MARK: - buttons
+
+void praat_Matrix_init () {
+	Thing_recognizeClassesByName (classMatrix, classPhoto, classMovie, nullptr);
+
+	Data_recognizeFileType (imageFileRecognizer);
+
+	praat_addMenuCommand (U"Objects", U"New", U"Matrix", nullptr, 0, nullptr);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Matrix...", nullptr, 1, NEW1_Matrix_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create simple Matrix...", nullptr, 1, NEW1_Matrix_createSimple);
+		praat_addMenuCommand (U"Objects", U"New", U"-- colour matrix --", nullptr, 1, nullptr);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Photo...", nullptr, 1, NEW1_Photo_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create simple Photo...", nullptr, 1, NEW1_Photo_createSimple);
+
+	praat_addMenuCommand (U"Objects", U"Open", U"-- read movie --", nullptr, praat_HIDDEN, nullptr);
+	praat_addMenuCommand (U"Objects", U"Open", U"Open movie file...", nullptr, praat_HIDDEN, READ1_Movie_openFromSoundFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"-- read raw --", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Matrix from raw text file...", nullptr, 0, READ1_Matrix_readFromRawTextFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Matrix from LVS AP file...", nullptr, praat_HIDDEN, READ1_Matrix_readAP);
+
+	praat_addAction1 (classMatrix, 0, U"Matrix help", nullptr, 0, HELP_Matrix_help);
+	praat_addAction1 (classMatrix, 1, U"Save as matrix text file...", nullptr, 0, SAVE_Matrix_writeToMatrixTextFile);
+	praat_addAction1 (classMatrix, 1,   U"Write to matrix text file...", U"*Save as matrix text file...", praat_DEPRECATED_2011, SAVE_Matrix_writeToMatrixTextFile);
+	praat_addAction1 (classMatrix, 1, U"Save as headerless spreadsheet file...", nullptr, 0, SAVE_Matrix_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (classMatrix, 1,   U"Write to headerless spreadsheet file...", nullptr, praat_DEPRECATED_2011, SAVE_Matrix_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (classMatrix, 1, U"Play movie", nullptr, 0, MOVIE_Matrix_movie);
+	praat_addAction1 (classMatrix, 0, U"Draw -", nullptr, 0, nullptr);
+		praat_addAction1 (classMatrix, 0, U"Draw rows...", nullptr, 1, GRAPHICS_Matrix_drawRows);
+		praat_addAction1 (classMatrix, 0, U"Draw one contour...", nullptr, 1, GRAPHICS_Matrix_drawOneContour);
+		praat_addAction1 (classMatrix, 0, U"Draw contours...", nullptr, 1, GRAPHICS_Matrix_drawContours);
+		praat_addAction1 (classMatrix, 0, U"Paint image...", nullptr, 1, GRAPHICS_Matrix_paintImage);
+		praat_addAction1 (classMatrix, 0, U"Paint contours...", nullptr, 1, GRAPHICS_Matrix_paintContours);
+		praat_addAction1 (classMatrix, 0, U"Paint cells...", nullptr, 1, GRAPHICS_Matrix_paintCells);
+		praat_addAction1 (classMatrix, 0, U"Paint surface...", nullptr, 1, GRAPHICS_Matrix_paintSurface);
+	praat_addAction1 (classMatrix, 1, U"Query -", nullptr, 0, nullptr);
+		praat_addAction1 (classMatrix, 1, U"Get lowest x", nullptr, 1, REAL_Matrix_getLowestX);
+		praat_addAction1 (classMatrix, 1, U"Get highest x", nullptr, 1, REAL_Matrix_getHighestX);
+		praat_addAction1 (classMatrix, 1, U"Get lowest y", nullptr, 1, REAL_Matrix_getLowestY);
+		praat_addAction1 (classMatrix, 1, U"Get highest y", nullptr, 1, REAL_Matrix_getHighestY);
+		praat_addAction1 (classMatrix, 1, U"-- get structure --", nullptr, 1, nullptr);
+		praat_addAction1 (classMatrix, 1, U"Get number of rows", nullptr, 1, INTEGER_Matrix_getNumberOfRows);
+		praat_addAction1 (classMatrix, 1, U"Get number of columns", nullptr, 1, INTEGER_Matrix_getNumberOfColumns);
+		praat_addAction1 (classMatrix, 1, U"Get row distance", nullptr, 1, REAL_Matrix_getRowDistance);
+		praat_addAction1 (classMatrix, 1, U"Get column distance", nullptr, 1, REAL_Matrix_getColumnDistance);
+		praat_addAction1 (classMatrix, 1, U"Get y of row...", nullptr, 1, REAL_Matrix_getYofRow);
+		praat_addAction1 (classMatrix, 1, U"Get x of column...", nullptr, 1, REAL_Matrix_getXofColumn);
+		praat_addAction1 (classMatrix, 1, U"-- get value --", nullptr, 1, nullptr);
+		praat_addAction1 (classMatrix, 1, U"Get value in cell...", nullptr, 1, REAL_Matrix_getValueInCell);
+		praat_addAction1 (classMatrix, 1, U"Get value at xy...", nullptr, 1, REAL_Matrix_getValueAtXY);
+		praat_addAction1 (classMatrix, 1, U"Get minimum", nullptr, 1, REAL_Matrix_getMinimum);
+		praat_addAction1 (classMatrix, 1, U"Get maximum", nullptr, 1, REAL_Matrix_getMaximum);
+		praat_addAction1 (classMatrix, 1, U"Get sum", nullptr, 1, REAL_Matrix_getSum);
+	praat_addAction1 (classMatrix, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_addAction1 (classMatrix, 0, U"Formula...", nullptr, 1, MODIFY_Matrix_formula);
+		praat_addAction1 (classMatrix, 0, U"Set value...", nullptr, 1, MODIFY_Matrix_setValue);
+praat_addAction1 (classMatrix, 0, U"Analyse", nullptr, 0, nullptr);
+	praat_addAction1 (classMatrix, 0, U"Eigen", nullptr, 0, NEWTIMES2_Matrix_eigen);
+	praat_addAction1 (classMatrix, 0, U"Synthesize", nullptr, 0, nullptr);
+	praat_addAction1 (classMatrix, 0, U"Power...", nullptr, 0, NEW_Matrix_power);
+	praat_addAction1 (classMatrix, 0, U"Combine two Matrices -", nullptr, 0, nullptr);
+		praat_addAction1 (classMatrix, 2, U"Merge (append rows)", nullptr, 1, NEW1_Matrix_appendRows);
+		praat_addAction1 (classMatrix, 2, U"To ParamCurve", nullptr, 1, NEW1_Matrix_to_ParamCurve);
+	praat_addAction1 (classMatrix, 0, U"Cast -", nullptr, 0, nullptr);
+		praat_addAction1 (classMatrix, 0, U"To Cochleagram", nullptr, 1, NEW_Matrix_to_Cochleagram);
+		praat_addAction1 (classMatrix, 0, U"To Excitation", nullptr, 1, NEW_Matrix_to_Excitation);
+		praat_addAction1 (classMatrix, 0, U"To Harmonicity", nullptr, 1, NEW_Matrix_to_Harmonicity);
+		praat_addAction1 (classMatrix, 0, U"To Intensity", nullptr, 1, NEW_Matrix_to_Intensity);
+		praat_addAction1 (classMatrix, 0, U"To Ltas", nullptr, 1, NEW_Matrix_to_Ltas);
+		praat_addAction1 (classMatrix, 0, U"To Pitch", nullptr, 1, NEW_Matrix_to_Pitch);
+		praat_addAction1 (classMatrix, 0, U"To PointProcess", nullptr, 1, NEW_Matrix_to_PointProcess);
+		praat_addAction1 (classMatrix, 0, U"To Polygon", nullptr, 1, NEW_Matrix_to_Polygon);
+		praat_addAction1 (classMatrix, 0, U"To Sound", nullptr, 1, NEW_Matrix_to_Sound);
+		praat_addAction1 (classMatrix, 0, U"To Sound (slice)...", nullptr, 1, NEW_Matrix_to_Sound_mono);
+		praat_addAction1 (classMatrix, 0, U"To Spectrogram", nullptr, 1, NEW_Matrix_to_Spectrogram);
+		praat_addAction1 (classMatrix, 0, U"To TableOfReal", nullptr, 1, NEW_Matrix_to_TableOfReal);
+		praat_addAction1 (classMatrix, 0, U"To Spectrum", nullptr, 1, NEW_Matrix_to_Spectrum);
+		praat_addAction1 (classMatrix, 0, U"To Transition", nullptr, 1, NEW_Matrix_to_Transition);
+		praat_addAction1 (classMatrix, 0, U"To VocalTract", nullptr, 1, NEW_Matrix_to_VocalTract);
+
+	praat_addAction1 (classPhoto, 0, U"Draw -", nullptr, 0, nullptr);
+		praat_addAction1 (classPhoto, 0, U"Paint image...", nullptr, 1, GRAPHICS_Photo_paintImage);
+		praat_addAction1 (classPhoto, 0, U"Paint cells...", nullptr, 1, GRAPHICS_Photo_paintCells);
+	praat_addAction1 (classPhoto, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_addAction1 (classPhoto, 0, U"Formula (red)...", nullptr, 1, MODIFY_Photo_formula_red);
+		praat_addAction1 (classPhoto, 0, U"Formula (green)...", nullptr, 1, MODIFY_Photo_formula_green);
+		praat_addAction1 (classPhoto, 0, U"Formula (blue)...", nullptr, 1, MODIFY_Photo_formula_blue);
+		praat_addAction1 (classPhoto, 0, U"Formula (transparency)...", nullptr, 1, MODIFY_Photo_formula_transparency);
+	praat_addAction1 (classPhoto, 0, U"Extract -", nullptr, 0, nullptr);
+		praat_addAction1 (classPhoto, 0, U"Extract red", nullptr, 1, NEW_Photo_extractRed);
+		praat_addAction1 (classPhoto, 0, U"Extract green", nullptr, 1, NEW_Photo_extractGreen);
+		praat_addAction1 (classPhoto, 0, U"Extract blue", nullptr, 1, NEW_Photo_extractBlue);
+		praat_addAction1 (classPhoto, 0, U"Extract transparency", nullptr, 1, NEW_Photo_extractTransparency);
+	praat_addAction1 (classPhoto, 1, U"Save as PNG file...", nullptr, 0, SAVE_Photo_saveAsPNG);
+	#if defined (macintosh) || defined (_WIN32)
+		praat_addAction1 (classPhoto, 1, U"Save as TIFF file...", nullptr, 0, SAVE_Photo_saveAsTIFF);
+		praat_addAction1 (classPhoto, 1, U"Save as GIF file...", nullptr, 0, SAVE_Photo_saveAsGIF);
+		praat_addAction1 (classPhoto, 1, U"Save as Windows bitmap file...", nullptr, 0, SAVE_Photo_saveAsWindowsBitmapFile);
+		praat_addAction1 (classPhoto, 1, U"Save as lossy JPEG file...", nullptr, 0, SAVE_Photo_saveAsJPEG);
+	#endif
+	#if defined (macintosh)
+		praat_addAction1 (classPhoto, 1, U"Save as JPEG-2000 file...", nullptr, 0, SAVE_Photo_saveAsJPEG2000);
+		praat_addAction1 (classPhoto, 1, U"Save as Apple icon file...", nullptr, 0, SAVE_Photo_saveAsAppleIconFile);
+		praat_addAction1 (classPhoto, 1, U"Save as Windows icon file...", nullptr, 0, SAVE_Photo_saveAsWindowsIconFile);
+	#endif
+
+	praat_addAction1 (classMovie, 1, U"Paint one image...", nullptr, 1, GRAPHICS_Movie_paintOneImage);
+	praat_addAction1 (classMovie, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_Movie_viewAndEdit);
+
+	praat_addAction2 (classMatrix, 1, classSound, 1, U"To ParamCurve", nullptr, 0, NEW1_Matrix_to_ParamCurve);
+	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace red", nullptr, 0, MODIFY_Photo_Matrix_replaceRed);
+	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace green", nullptr, 0, MODIFY_Photo_Matrix_replaceGreen);
+	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace blue", nullptr, 0, MODIFY_Photo_Matrix_replaceBlue);
+	praat_addAction2 (classPhoto, 1, classMatrix, 1, U"Replace transparency", nullptr, 0, MODIFY_Photo_Matrix_replaceTransparency);
+}
+
+/* End of file praat_Matrix.cpp */
diff --git a/artsynth/Speaker.h b/fon/praat_Matrix.h
similarity index 60%
copy from artsynth/Speaker.h
copy to fon/praat_Matrix.h
index e3c6992..dcc0481 100644
--- a/artsynth/Speaker.h
+++ b/fon/praat_Matrix.h
@@ -1,8 +1,8 @@
-#ifndef _Speaker_h_
-#define _Speaker_h_
-/* Speaker.h
+#ifndef _praat_Matrix_h_
+#define _praat_Matrix_h_
+/* praat_Matrix.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,15 +18,21 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "Data.h"
+/*
+	Interface functions for subclasses of Matrix.
+*/
 
-#include "Speaker_def.h"
+#include "Matrix.h"
+#include "praat.h"
 
-autoSpeaker Speaker_create (char32 *kindOfSpeaker, int numberOfVocalCordMasses);
-	/* Preconditions:								*/
-	/*    1 <= numberOfVocalCordMasses <= 2;					*/
-	/* Failures:									*/
-	/*    Kind of speaker is not one of "Female", "Male", or "Child".		*/
+int praat_Matrix_formula (UiForm dia, Interpreter interpreter);
 
-/* End of file Speaker.h */
+extern "C" Graphics Movie_create (const char32 *title, int width, int height);
+
+/*
+	Action buttons.
+*/
+void praat_Matrix_init ();
+
+/* End of file praat_Matrix.h */
 #endif
diff --git a/fon/praat_Sound.cpp b/fon/praat_Sound.cpp
new file mode 100644
index 0000000..4ea8c28
--- /dev/null
+++ b/fon/praat_Sound.cpp
@@ -0,0 +1,2407 @@
+/* praat_Sound_init.cpp
+ *
+ * Copyright (C) 1992-2012,2014,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Ltas.h"
+#include "LongSound.h"
+#include "Manipulation.h"
+#include "ParamCurve.h"
+#include "Sound_and_Spectrogram.h"
+#include "Sound_and_Spectrum.h"
+#include "Sound_extensions.h"
+#include "Sound_to_Cochleagram.h"
+#include "Sound_to_Formant.h"
+#include "Sound_to_Harmonicity.h"
+#include "Sound_to_Intensity.h"
+#include "Sound_to_Pitch.h"
+#include "Sound_to_PointProcess.h"
+#include "SoundEditor.h"
+#include "SoundRecorder.h"
+#include "SpectrumEditor.h"
+#include "TextGrid_Sound.h"
+#include "mp3.h"
+
+#include "praat_Sound.h"
+
+#undef iam
+#define iam iam_LOOP
+
+/***** LONGSOUND *****/
+
+DIRECT (INFO_LongSound_concatenate) {
+	INFO_NONE
+		Melder_information (U"To concatenate LongSound objects, select them in the list\nand choose \"Save as WAV file...\" or a similar command.\n"
+			"The result will be a sound file that contains\nthe concatenation of the selected sounds.");
+	INFO_NONE_END
+}
+
+FORM (NEW_LongSound_extractPart, U"LongSound: Extract part", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"1.0")
+	BOOLEAN4 (preserveTimes, U"Preserve times", true)
+	OK
+DO
+	CONVERT_EACH (LongSound)
+		autoSound result = LongSound_extractPart (me, fromTime, toTime, preserveTimes);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (REAL_LongSound_getIndexFromTime, U"LongSound: Get sample index from time", U"Sound: Get index from time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (LongSound)
+		double result = Sampled_xToIndex (me, time);
+	NUMBER_ONE_END (U" (index at ", time, U" seconds)")
+}
+
+DIRECT (REAL_LongSound_getSamplePeriod) {
+	NUMBER_ONE (LongSound)
+		double result = my dx;
+	NUMBER_ONE_END (U" seconds");
+}
+
+DIRECT (REAL_LongSound_getSampleRate) {
+	NUMBER_ONE (LongSound)
+		double result = 1.0 / my dx;
+	NUMBER_ONE_END (U" Hz")
+}
+
+FORM (REAL_LongSound_getTimeFromIndex, U"LongSound: Get time from sample index", U"Sound: Get time from index...") {
+	INTEGER4 (sampleIndex, U"Sample index", U"100")
+	OK
+DO
+	NUMBER_ONE (LongSound)
+		double result = Sampled_indexToX (me, sampleIndex);
+	NUMBER_ONE_END (U" seconds")
+}
+
+DIRECT (INTEGER_LongSound_getNumberOfSamples) {
+	NUMBER_ONE (LongSound)
+		long result = my nx;
+	NUMBER_ONE_END (U" samples")
+}
+
+DIRECT (HELP_LongSound_help) {
+	HELP (U"LongSound")
+}
+
+FORM_READ (READ1_LongSound_open, U"Open long sound file", nullptr, true) {
+	READ_ONE
+		autoLongSound result = LongSound_open (file);
+	READ_ONE_END
+}
+
+FORM (PLAY_LongSound_playPart, U"LongSound: Play part", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"10.0")
+	OK
+DO
+	int n = 0;
+	LOOP n ++;
+	if (n == 1 || MelderAudio_getOutputMaximumAsynchronicity () < kMelder_asynchronicityLevel_ASYNCHRONOUS) {
+		LOOP {
+			iam (LongSound);
+			LongSound_playPart (me, fromTime, toTime, nullptr, nullptr);
+		}
+	} else {
+		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_INTERRUPTABLE);
+		LOOP {
+			iam (LongSound);
+			LongSound_playPart (me, fromTime, toTime, nullptr, nullptr);
+		}
+		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_ASYNCHRONOUS);
+	}
+END }
+
+FORM (SAVE_LongSound_savePartAsAudioFile, U"LongSound: Save part as audio file", nullptr) {
+	LABEL (U"", U"Audio file:")
+	TEXTFIELD4 (audioFile, U"Audio file", U"")
+	RADIOVAR (type, U"Type", 3)
+	{ int i; for (i = 1; i <= Melder_NUMBER_OF_AUDIO_FILE_TYPES; i ++) {
+		RADIOBUTTON (Melder_audioFileTypeString (i))
+	}}
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"10.0")
+	OK
+DO
+	SAVE_ONE (LongSound)
+		structMelderFile file = { 0 };
+		Melder_relativePathToFile (audioFile, & file);
+		LongSound_savePartAsAudioFile (me, type, fromTime, toTime, & file, 16);
+	SAVE_ONE_END
+}
+
+FORM (NEW_LongSound_to_TextGrid, U"LongSound: To TextGrid...", U"LongSound: To TextGrid...") {
+	SENTENCE4 (tierNames, U"Tier names", U"Mary John bell")
+	SENTENCE4 (pointTiers, U"Point tiers", U"bell")
+	OK
+DO
+	CONVERT_EACH (LongSound)
+		autoTextGrid result = TextGrid_create (my xmin, my xmax, tierNames, pointTiers);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (WINDOW_LongSound_view) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a LongSound from batch.");
+	LOOP {
+		iam (LongSound);
+		autoSoundEditor editor = SoundEditor_create (ID_AND_FULL_NAME, me);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+FORM_SAVE (SAVE_LongSound_saveAsAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveAsAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveAsNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveAsNistFile, U"Save as NIST file", nullptr, U"nist") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NIST, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveAsFlacFile, U"Save as FLAC file", nullptr, U"flac") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveAsWavFile, U"Save as WAV file", nullptr, U"wav") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_WAV, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveLeftChannelAsAifcFile, U"Save left channel as AIFC file", nullptr, U"aifc") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_AIFC, 0, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveLeftChannelAsAiffFile, U"Save left channel as AIFF file", nullptr, U"aiff") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_AIFF, 0, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveLeftChannelAsNextSunFile, U"Save left channel as NeXT/Sun file", nullptr, U"au") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_NEXT_SUN, 0, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveLeftChannelAsNistFile, U"Save left channel as NIST file", nullptr, U"nist") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_NIST, 0, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveLeftChannelAsFlacFile, U"Save left channel as FLAC file", nullptr, U"flac") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_FLAC, 0, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveLeftChannelAsWavFile, U"Save left channel as WAV file", nullptr, U"wav") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_WAV, 0, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveRightChannelAsAifcFile, U"Save right channel as AIFC file", nullptr, U"aifc") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_AIFC, 1, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveRightChannelAsAiffFile, U"Save right channel as AIFF file", nullptr, U"aiff") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_AIFF, 1, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveRightChannelAsNextSunFile, U"Save right channel as NeXT/Sun file", nullptr, U"au") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_NEXT_SUN, 1, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveRightChannelAsNistFile, U"Save right channel as NIST file", nullptr, U"nist") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_NIST, 1, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveRightChannelAsFlacFile, U"Save right channel as FLAC file", 0, U"flac") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_FLAC, 1, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_LongSound_saveRightChannelAsWavFile, U"Save right channel as WAV file", 0, U"wav") {
+	SAVE_ONE (LongSound)
+		LongSound_saveChannelAsAudioFile (me, Melder_WAV, 1, file);
+	SAVE_ONE_END
+}
+
+FORM (PREFS_LongSoundPrefs, U"LongSound preferences", U"LongSound") {
+	LABEL (U"", U"This setting determines the maximum number of seconds")
+	LABEL (U"", U"for viewing the waveform and playing a sound in the LongSound window.")
+	LABEL (U"", U"The LongSound window can become very slow if you set it too high.")
+	NATURAL (U"Maximum viewable part (seconds)", U"60")
+	LABEL (U"", U"Note: this setting works for the next long sound file that you open,")
+	LABEL (U"", U"not for currently existing LongSound objects.")
+OK
+	SET_INTEGER (U"Maximum viewable part", LongSound_getBufferSizePref_seconds ())
+DO
+	LongSound_setBufferSizePref_seconds (GET_INTEGER (U"Maximum viewable part"));
+END }
+
+/********** LONGSOUND & SOUND **********/
+
+FORM_SAVE (SAVE_LongSound_Sound_saveAsAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_Sound_saveAsAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_Sound_saveAsNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_Sound_saveAsNistFile, U"Save as NIST file", nullptr, U"nist") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NIST, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_Sound_saveAsFlacFile, U"Save as FLAC file", nullptr, U"flac") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_LongSound_Sound_saveAsWavFile, U"Save as WAV file", nullptr, U"wav") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_WAV, 16);
+	SAVE_TYPED_LIST_END
+}
+
+/********** SOUND **********/
+
+FORM (MODIFY_Sound_add, U"Sound: Add", nullptr) {
+	LABEL (U"", U"The following number will be added to the amplitudes of ")
+	LABEL (U"", U"all samples of the sound.")
+	REALVAR (number, U"Number", U"0.1")
+	OK
+DO
+	LOOP {
+		iam (Sound);
+		Vector_addScalar (me, number);
+		praat_dataChanged (me);
+	}
+END }
+
+FORM (NEW_Sound_autoCorrelate, U"Sound: autocorrelate", U"Sound: Autocorrelate...") {
+	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
+	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
+ 	OK
+DO
+	LOOP {
+		iam (Sound);
+		autoSound thee = Sound_autoCorrelate (me,
+			GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
+			GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
+		praat_new (thee.move(), U"ac_", my name);
+	}
+END }
+
+DIRECT (NEW1_Sounds_combineToStereo) {
+	CONVERT_LIST (Sound)
+		autoSound result = Sounds_combineToStereo (& list);
+		long numberOfChannels = result -> ny;   // dereference before transferring
+	CONVERT_LIST_END (U"combined_", numberOfChannels)
+}
+
+DIRECT (NEW1_Sounds_concatenate) {
+	CONVERT_LIST (Sound)
+		autoSound result = Sounds_concatenate (list, 0.0);
+	CONVERT_LIST_END (U"chain")
+}
+
+FORM (NEW1_Sounds_concatenateWithOverlap, U"Sounds: Concatenate with overlap", U"Sounds: Concatenate with overlap...") {
+	POSITIVE4 (overlap, U"Overlap (s)", U"0.01")
+	OK
+DO
+	CONVERT_LIST (Sound)
+		autoSound result = Sounds_concatenate (list, overlap);
+	CONVERT_LIST_END (U"chain")
+}
+
+DIRECT (NEW2_Sounds_concatenateRecoverably) {
+	long numberOfChannels = 0, nx = 0, iinterval = 0;
+	double dx = 0.0, tmin = 0.0;
+	LOOP {
+		iam (Sound);
+		if (numberOfChannels == 0) {
+			numberOfChannels = my ny;
+		} else if (my ny != numberOfChannels) {
+			Melder_throw (U"To concatenate sounds, their numbers of channels (mono, stereo) must be equal.");
+		}
+		if (dx == 0.0) {
+			dx = my dx;
+		} else if (my dx != dx) {
+			Melder_throw (U"To concatenate sounds, their sampling frequencies must be equal.\n"
+				"You could resample one or more of the sounds before concatenating.");
+		}
+		nx += my nx;
+	}
+	autoSound thee = Sound_create (numberOfChannels, 0.0, nx * dx, nx, dx, 0.5 * dx);
+	autoTextGrid him = TextGrid_create (0.0, nx * dx, U"labels", U"");
+	nx = 0;
+	LOOP {
+		iam (Sound);
+		double tmax = tmin + my nx * dx;
+		for (long channel = 1; channel <= numberOfChannels; channel ++) {
+			NUMvector_copyElements (my z [channel], thy z [channel] + nx, 1, my nx);
+		}
+		iinterval ++;
+		if (iinterval > 1) {
+			TextGrid_insertBoundary (him.get(), 1, tmin);
+		}
+		TextGrid_setIntervalText (him.get(), 1, iinterval, my name);
+		nx += my nx;
+		tmin = tmax;
+	}
+	praat_new (thee.move(), U"chain");
+	praat_new (him.move(), U"chain");
+	END
+}
+
+DIRECT (NEW_Sound_convertToMono) {
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_convertToMono (me);
+	CONVERT_EACH_END (my name, U"_mono")
+}
+
+DIRECT (NEW_Sound_convertToStereo) {
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_convertToStereo (me);
+	CONVERT_EACH_END (my name, U"_stereo")
+}
+
+DIRECT (NEW1_Sounds_convolve_old) {
+	CONVERT_COUPLE (Sound)
+		autoSound result = Sounds_convolve (me, you,
+			kSounds_convolve_scaling_SUM, kSounds_convolve_signalOutsideTimeDomain_ZERO);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
+
+FORM (NEW1_Sounds_convolve, U"Sounds: Convolve", U"Sounds: Convolve...") {
+	RADIO_ENUM4 (amplitudeScaling, U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
+	RADIO_ENUM4 (signalOutsideTimeDomainIs, U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
+	OK
+DO
+	CONVERT_COUPLE (Sound)
+		autoSound result = Sounds_convolve (me, you,
+			(kSounds_convolve_scaling) amplitudeScaling,
+			(kSounds_convolve_signalOutsideTimeDomain) signalOutsideTimeDomainIs);
+	CONVERT_COUPLE_END (my name, U"_", your name)
+}
+
+static void common_Sound_create (const char32 *name, long numberOfChannels, double startTime, double endTime,
+	double samplingFrequency, const char32 *formula, Interpreter interpreter)
+{
+	double numberOfSamples_real = round ((endTime - startTime) * samplingFrequency);
+	if (endTime <= startTime) {
+		if (endTime == startTime)
+			Melder_appendError (U"A Sound cannot have a duration of zero.");
+		else
+			Melder_appendError (U"A Sound cannot have a duration less than zero.");
+		if (startTime == 0.0)
+			Melder_throw (U"Please set the end time to something greater than 0 seconds.");
+		else
+			Melder_throw (U"Please lower the start time or raise the end time.");
+	}
+	if (samplingFrequency <= 0.0) {
+		Melder_appendError (U"A Sound cannot have a negative sampling frequency.");
+		Melder_throw (U"Please set the sampling frequency to something greater than zero, e.g. 44100 Hz.");
+	}
+	if (numberOfChannels < 1)
+		Melder_throw (U"A Sound cannot have zero channels.");
+	if (numberOfSamples_real < 1.0) {
+		Melder_appendError (U"A Sound cannot have zero samples.");
+		if (startTime == 0.0)
+			Melder_throw (U"Please raise the end time.");
+		else
+			Melder_throw (U"Please lower the start time or raise the end time.");
+	}
+	if (numberOfSamples_real > INT54_MAX) {
+		Melder_appendError (U"A Sound cannot have ", numberOfSamples_real, U" samples; the maximum is ",
+			Melder_bigInteger (INT54_MAX), U" samples (or less, depending on your computer's memory).");
+		if (startTime == 0.0)
+			Melder_throw (U"Please lower the end time or the sampling frequency.");
+		else
+			Melder_throw (U"Please raise the start time, lower the end time, or lower the sampling frequency.");
+	}
+	int64 numberOfSamples = (int64) numberOfSamples_real;
+	autoSound sound;
+	try {
+		sound = Sound_create (numberOfChannels, startTime, endTime, numberOfSamples, 1.0 / samplingFrequency,
+			startTime + 0.5 * (endTime - startTime - (numberOfSamples - 1) / samplingFrequency));
+	} catch (MelderError) {
+		if (str32str (Melder_getError (), U"memory")) {
+			Melder_clearError ();
+			Melder_appendError (U"There is not enough memory to create a Sound that contains ", Melder_bigInteger (numberOfSamples), U" samples.");
+			if (startTime == 0.0)
+				Melder_throw (U"You could lower the end time or the sampling frequency and try again.");
+			else
+				Melder_throw (U"You could raise the start time or lower the end time or the sampling frequency, and try again.");
+		} else {
+			throw;   // unexpected error; wait for generic message
+		}
+	}
+	Matrix_formula (sound.get(), formula, interpreter, nullptr);
+	praat_new (sound.move(), name);
+	//praat_updateSelection ();
+}
+
+FORM (NEW1_Sound_create, U"Create mono Sound", U"Create Sound from formula...") {
+	WORDVAR (name, U"Name", U"sineWithNoise")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"1.0")
+	REALVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100")
+	LABEL (U"", U"Formula:")
+	TEXTVAR (formula, U"formula", U"1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)")
+	OK
+DO
+	common_Sound_create (name, 1, startTime, endTime, samplingFrequency, formula, interpreter);
+END }
+
+FORM (NEW1_Sound_createFromFormula, U"Create Sound from formula", U"Create Sound from formula...") {
+	WORDVAR (name, U"Name", U"sineWithNoise")
+	CHANNELVAR (numberOfChannels, U"Number of channels", U"1 (= mono)")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"1.0")
+	REALVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100")
+	LABEL (U"", U"Formula:")
+	TEXTVAR (formula, U"formula", U"1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)")
+	OK
+DO
+	common_Sound_create (name, numberOfChannels, startTime, endTime, samplingFrequency, formula, interpreter);
+END }
+
+FORM (NEW1_Sound_createAsPureTone, U"Create Sound as pure tone", U"Create Sound as pure tone...") {
+	WORDVAR (name, U"Name", U"tone")
+	CHANNELVAR (numberOfChannels, U"Number of channels", U"1 (= mono)")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"0.4")
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	POSITIVEVAR (toneFrequency, U"Tone frequency (Hz)", U"440.0")
+	POSITIVEVAR (amplitude, U"Amplitude (Pa)", U"0.2")
+	POSITIVEVAR (fadeInDuration, U"Fade-in duration (s)", U"0.01")
+	POSITIVEVAR (fadeOutDuration, U"Fade-out duration (s)", U"0.01")
+	OK
+DO
+	CREATE_ONE
+		autoSound result = Sound_createAsPureTone (numberOfChannels, startTime, endTime,
+			samplingFrequency, toneFrequency, amplitude, fadeInDuration, fadeOutDuration);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_Sound_createAsToneComplex, U"Create Sound as tone complex", U"Create Sound as tone complex...") {
+	WORDVAR (name, U"Name", U"toneComplex")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"1.0")
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	RADIOVARx (phase, U"Phase", 2, Sound_TONE_COMPLEX_SINE)
+		RADIOBUTTON (U"sine")
+		RADIOBUTTON (U"cosine")
+	POSITIVEVAR (frequencyStep, U"Frequency step (Hz)", U"100.0")
+	REALVAR (firstFrequency, U"First frequency (Hz)", U"0.0 (= frequency step)")
+	REALVAR (ceiling, U"Ceiling (Hz)", U"0.0 (= Nyquist)")
+	INTEGERVAR (numberOfComponents, U"Number of components", U"0 (= maximum)")
+	OK
+DO
+	CREATE_ONE
+		autoSound result = Sound_createAsToneComplex (startTime, endTime,
+			samplingFrequency, phase, frequencyStep, firstFrequency, ceiling, numberOfComponents);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_old_Sounds_crossCorrelate, U"Cross-correlate (short)", nullptr) {
+	REAL4 (fromLag, U"From lag (s)", U"-0.1")
+	REAL4 (toLag, U"To lag (s)", U"0.1")
+	BOOLEAN4 (normalize, U"Normalize", true)
+	OK
+DO
+	CONVERT_COUPLE (Sound)
+		autoSound result = Sounds_crossCorrelate_short (me, you, fromLag, toLag, normalize);
+	CONVERT_COUPLE_END (U"cc_", my name, U"_", your name)
+}
+
+FORM (NEW1_Sounds_crossCorrelate, U"Sounds: Cross-correlate", U"Sounds: Cross-correlate...") {
+	RADIO_ENUM4 (amplitudeScaling, U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
+	RADIO_ENUM4 (signalOutsideTimeDomainIs, U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
+	OK
+DO_ALTERNATIVE (NEW1_old_Sounds_crossCorrelate)
+	CONVERT_COUPLE (Sound)
+		autoSound result = Sounds_crossCorrelate (me, you,
+			(kSounds_convolve_scaling) amplitudeScaling,
+			(kSounds_convolve_signalOutsideTimeDomain) signalOutsideTimeDomainIs);
+	CONVERT_COUPLE_END (U"cc_", my name, U"_", your name)
+}
+
+FORM (MODIFY_Sound_deemphasizeInline, U"Sound: De-emphasize (in-line)", U"Sound: De-emphasize (in-line)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"50.0")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_deEmphasis (me, fromFrequency);
+		Vector_scale (me, 0.99);
+	MODIFY_EACH_END
+}
+
+FORM (NEW_Sound_deepenBandModulation, U"Deepen band modulation", U"Sound: Deepen band modulation...") {
+	POSITIVE4 (enhancement, U"Enhancement (dB)", U"20.0")
+	POSITIVE4 (fromFrequency, U"From frequency (Hz)", U"300.0")
+	POSITIVE4 (toFrequency, U"To frequency (Hz)", U"8000.0")
+	POSITIVE4 (slowModulation, U"Slow modulation (Hz)", U"3.0")
+	POSITIVE4 (fastModulation, U"Fast modulation (Hz)", U"30.0")
+	POSITIVE4 (bandSmoothing, U"Band smoothing (Hz)", U"100.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_deepenBandModulation (me, enhancement, fromFrequency, toFrequency,
+			slowModulation, fastModulation, bandSmoothing);
+	CONVERT_EACH_END (my name, U"_", (long) enhancement)   // truncate number toward zero for visual effect
+}
+
+FORM (GRAPHICS_old_Sound_draw, U"Sound: Draw", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range", U"0.0 (= all)")
+	REAL4 (fromAmplitude, U"left Amplitude range", U"0.0")
+	REAL4 (toAmplitude, U"right Amplitude range", U"0.0 (= auto)")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Sound)
+		Sound_draw (me, GRAPHICS, fromTime, toTime,
+			fromAmplitude, toAmplitude, garnish, U"curve");
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_Sound_draw, U"Sound: Draw", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range", U"0.0 (= all)")
+	REAL4 (fromAmplitude, U"left Amplitude range", U"0.0")
+	REAL4 (toAmplitude, U"right Amplitude range", U"0.0 (= auto)")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	LABEL (U"", U"")
+	OPTIONMENUSTR4 (drawingMethod, U"Drawing method", 1)
+		OPTION (U"Curve")
+		OPTION (U"Bars")
+		OPTION (U"Poles")
+		OPTION (U"Speckles")
+	OK
+DO_ALTERNATIVE (GRAPHICS_old_Sound_draw)
+	GRAPHICS_EACH (Sound)
+		Sound_draw (me, GRAPHICS, fromTime, toTime,
+			fromAmplitude, toAmplitude, garnish, drawingMethod);
+	GRAPHICS_EACH_END
+}
+
+static void cb_SoundEditor_publication (Editor /* me */, autoDaata publication) {
+	/*
+	 * Keep the gate for error handling.
+	 */
+	try {
+		bool isaSpectrum = Thing_isa (publication.get(), classSpectrum);
+		praat_new (publication.move(), U"");
+		praat_updateSelection ();
+		if (isaSpectrum) {
+			int IOBJECT;
+			LOOP {
+				iam (Spectrum);
+				autoSpectrumEditor editor2 = SpectrumEditor_create (ID_AND_FULL_NAME, me);
+				praat_installEditor (editor2.get(), IOBJECT);
+				editor2.releaseToUser();
+			}
+		}
+	} catch (MelderError) {
+		Melder_flushError ();
+	}
+}
+DIRECT (WINDOW_Sound_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Sound from batch.");
+	LOOP {
+		iam (Sound);
+		autoSoundEditor editor = SoundEditor_create (ID_AND_FULL_NAME, me);
+		Editor_setPublicationCallback (editor.get(), cb_SoundEditor_publication);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+DIRECT (NEWMANY_Sound_extractAllChannels) {
+	LOOP {
+		iam (Sound);
+		for (long channel = 1; channel <= my ny; channel ++) {
+			autoSound thee = Sound_extractChannel (me, channel);
+			praat_new (thee.move(), my name, U"_ch", channel);
+		}
+	}
+	END
+}
+
+FORM (NEW_Sound_extractChannel, U"Sound: Extract channel", nullptr) {
+	CHANNEL4 (channel, U"Channel (number, Left, or Right)", U"1")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_extractChannel (me, channel);
+	CONVERT_EACH_END (my name, U"_ch", channel)
+}
+
+DIRECT (NEW_Sound_extractLeftChannel) {
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_extractChannel (me, 1);
+	CONVERT_EACH_END (my name, U"_left")
+}
+
+FORM (NEW_Sound_extractPart, U"Sound: Extract part", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.1")
+	OPTIONMENU_ENUM4 (windowShape, U"Window shape", kSound_windowShape, DEFAULT)
+	POSITIVE4 (relativeWidth, U"Relative width", U"1.0")
+	BOOLEAN4 (preserveTimes, U"Preserve times", false)
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_extractPart (me, fromTime, toTime,
+			(kSound_windowShape) windowShape, relativeWidth, preserveTimes);
+	CONVERT_EACH_END (my name, U"_part")
+}
+
+FORM (NEW_Sound_extractPartForOverlap, U"Sound: Extract part for overlap", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.1")
+	POSITIVE4 (overlap, U"Overlap (s)", U"0.01")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_extractPartForOverlap (me, fromTime, toTime, overlap);
+	CONVERT_EACH_END (my name, U"_part")
+}
+
+DIRECT (NEW_Sound_extractRightChannel) {
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_extractChannel (me, 2);
+	CONVERT_EACH_END (my name, U"_right")
+}
+
+FORM (NEW_Sound_filter_deemphasis, U"Sound: Filter (de-emphasis)", U"Sound: Filter (de-emphasis)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"50.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filter_deemphasis (me, fromFrequency);
+	CONVERT_EACH_END (my name, U"_deemp")
+}
+
+FORM (NEW_Sound_filter_formula, U"Sound: Filter (formula)...", U"Formula...") {
+	LABEL (U"", U"Frequency-domain filtering with a formula (uses Sound-to-Spectrum and Spectrum-to-Sound): x is frequency in hertz")
+	TEXTFIELD4 (formula, U"formula", U"if x<500 or x>1000 then 0 else self fi; rectangular band filter")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filter_formula (me, formula, interpreter);
+	CONVERT_EACH_END (my name, U"_filt")
+}
+
+FORM (NEW_Sound_filter_oneFormant, U"Sound: Filter (one formant)", U"Sound: Filter (one formant)...") {
+	REAL4 (frequency, U"Frequency (Hz)", U"1000.0")
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"100.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filter_oneFormant (me, frequency, bandwidth);
+	CONVERT_EACH_END (my name, U"_filt")
+}
+
+FORM (MODIFY_Sound_filterWithOneFormantInline, U"Sound: Filter with one formant (in-line)", U"Sound: Filter with one formant (in-line)...") {
+	REAL4 (frequency, U"Frequency (Hz)", U"1000.0")
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"100.0")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_filterWithOneFormantInline (me, frequency, bandwidth);
+	MODIFY_EACH_END
+}
+
+FORM (NEW_Sound_filter_passHannBand, U"Sound: Filter (pass Hann band)", U"Sound: Filter (pass Hann band)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"500.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"1000.0")
+	POSITIVE4 (smoothing, U"Smoothing (Hz)", U"100.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filter_passHannBand (me, fromFrequency, toFrequency, smoothing);
+	CONVERT_EACH_END (my name, U"_band")
+}
+
+FORM (NEW_Sound_filter_preemphasis, U"Sound: Filter (pre-emphasis)", U"Sound: Filter (pre-emphasis)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"50.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filter_preemphasis (me, fromFrequency);
+	CONVERT_EACH_END (my name, U"_preemp")
+}
+
+FORM (NEW_Sound_filter_stopHannBand, U"Sound: Filter (stop Hann band)", U"Sound: Filter (stop Hann band)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"500.0")
+	REAL4 (toFrequency, U"To frequency (Hz)", U"1000.0")
+	POSITIVE4 (smoothing, U"Smoothing (Hz)", U"100.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_filter_stopHannBand (me, fromFrequency, toFrequency, smoothing);
+	CONVERT_EACH_END (my name, U"_band")
+}
+
+FORM (MODIFY_Sound_formula, U"Sound: Formula", U"Sound: Formula...") {
+	LABEL (U"label1", U"! `x' is the time in seconds, `col' is the sample number.")
+	LABEL (U"label2", U"x = x1   ! time associated with first sample")
+	LABEL (U"label3", U"for col from 1 to ncol")
+	LABEL (U"label4", U"   self [col] = ...")
+	TEXTFIELD4 (formula, U"formula", U"self")
+	LABEL (U"label5", U"   x = x + dx")
+	LABEL (U"label6", U"endfor")
+	OK
+DO
+	MODIFY_EACH_WEAK (Sound)
+		Matrix_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_Sound_formula_part, U"Sound: Formula (part)", U"Sound: Formula...") {
+	REAL4 (fromTime, U"From time", U"0.0")
+	REAL4 (toTime, U"To time", U"0.0 (= all)")
+	NATURAL4 (fromChannel, U"From channel", U"1")
+	NATURAL4 (toChannel, U"To channel", U"2")
+	TEXTFIELD4 (formula, U"formula", U"2 * self")
+	OK
+DO
+	MODIFY_EACH_WEAK (Sound)
+		Matrix_formula_part (me, fromTime, toTime,
+			fromChannel - 0.5, toChannel + 0.5,
+			formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (REAL_Sound_getAbsoluteExtremum, U"Sound: Get absolute extremum", U"Sound: Get absolute extremum...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getAbsoluteExtremum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getEnergy, U"Sound: Get energy", U"Sound: Get energy...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Sound_getEnergy (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Pa2 sec")
+}
+
+DIRECT (REAL_Sound_getEnergyInAir) {
+	NUMBER_ONE (Sound)
+		double result = Sound_getEnergyInAir (me);
+	NUMBER_ONE_END (U" Joule/m2")
+}
+
+FORM (REAL_Sound_getIndexFromTime, U"Get sample number from time", U"Get sample number from time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Sampled_xToIndex (me, time);
+	NUMBER_ONE_END (U" (index at time ", time, U" seconds)")
+}
+
+DIRECT (REAL_Sound_getIntensity_dB) {
+	NUMBER_ONE (Sound)
+		double result = Sound_getIntensity_dB (me);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_Sound_getMaximum, U"Sound: Get maximum", U"Sound: Get maximum...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getMaximum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_old_Sound_getMean, U"Sound: Get mean", U"Sound: Get mean...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getMean (me, fromTime, toTime, Vector_CHANNEL_AVERAGE);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getMean, U"Sound: Get mean", U"Sound: Get mean...") {
+	CHANNEL4 (channel, U"Channel", U"0 (= all)")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO_ALTERNATIVE (REAL_old_Sound_getMean)
+	NUMBER_ONE (Sound)
+		if (channel > my ny) channel = 1;
+		double result = Vector_getMean (me, fromTime, toTime, channel);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getMinimum, U"Sound: Get minimum", U"Sound: Get minimum...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getMinimum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_old_Sound_getNearestZeroCrossing, U"Sound: Get nearest zero crossing", U"Sound: Get nearest zero crossing...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		if (my ny > 1) Melder_throw (U"Cannot determine a zero crossing for a stereo sound.");
+		double result = Sound_getNearestZeroCrossing (me, time, 1);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_Sound_getNearestZeroCrossing, U"Sound: Get nearest zero crossing", U"Sound: Get nearest zero crossing...") {
+	CHANNEL4 (channel, U"Channel (number, Left, or Right)", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO_ALTERNATIVE (REAL_old_Sound_getNearestZeroCrossing)
+	NUMBER_ONE (Sound)
+		if (channel > my ny) channel = 1;
+		double result = Sound_getNearestZeroCrossing (me, time, channel);
+	NUMBER_ONE_END (U" seconds")
+}
+
+DIRECT (INTEGER_Sound_getNumberOfChannels) {
+	NUMBER_ONE (Sound)
+		long result = my ny;
+	NUMBER_ONE_END (result == 1 ? U" channel (mono)" : result == 2 ? U" channels (stereo)" : U" channels")
+}
+
+DIRECT (INTEGER_Sound_getNumberOfSamples) {
+	NUMBER_ONE (Sound)
+		long result = my nx;
+	NUMBER_ONE_END (U" samples")
+}
+
+FORM (REAL_Sound_getPower, U"Sound: Get power", U"Sound: Get power...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Sound_getPower (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Pa2")
+}
+
+DIRECT (REAL_Sound_getPowerInAir) {
+	NUMBER_ONE (Sound)
+		double result = Sound_getPowerInAir (me);
+	NUMBER_ONE_END (U" Watt/m2")
+}
+
+FORM (REAL_Sound_getRootMeanSquare, U"Sound: Get root-mean-square", U"Sound: Get root-mean-square...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Sound_getRootMeanSquare (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+DIRECT (REAL_Sound_getSamplePeriod) {
+	NUMBER_ONE (Sound)
+		double result = my dx;
+	NUMBER_ONE_END (U" seconds")
+}
+
+DIRECT (REAL_Sound_getSampleRate) {
+	NUMBER_ONE (Sound)
+		double result = 1.0 / my dx;
+	NUMBER_ONE_END (U" Hz")
+}
+
+FORM (REAL_old_Sound_getStandardDeviation, U"Sound: Get standard deviation", U"Sound: Get standard deviation...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getStandardDeviation (me, fromTime, toTime, Vector_CHANNEL_AVERAGE);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getStandardDeviation, U"Sound: Get standard deviation", U"Sound: Get standard deviation...") {
+	CHANNEL4 (channel, U"Channel", U"0 (= average)")
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	OK
+DO_ALTERNATIVE (REAL_old_Sound_getStandardDeviation)
+	NUMBER_ONE (Sound)
+		if (channel > my ny) channel = 1;
+		double result = Vector_getStandardDeviation (me, fromTime, toTime, channel);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getTimeFromIndex, U"Get time from sample number", U"Get time from sample number...") {
+	INTEGER4 (sampleNumber, U"Sample number", U"100")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Sampled_indexToX (me, sampleNumber);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_Sound_getTimeOfMaximum, U"Sound: Get time of maximum", U"Sound: Get time of maximum...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getXOfMaximum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_Sound_getTimeOfMinimum, U"Sound: Get time of minimum", U"Sound: Get time of minimum...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getXOfMinimum (me, fromTime, toTime, interpolation);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_old_Sound_getValueAtIndex, U"Sound: Get value at sample number", U"Sound: Get value at sample number...") {
+	INTEGER4 (sampleNumber, U"Sample number", U"100")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = sampleNumber < 1 || sampleNumber > my nx ? NUMundefined :
+			my ny == 1 ? my z [1] [sampleNumber] : 0.5 * (my z [1] [sampleNumber] + my z [2] [sampleNumber]);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getValueAtIndex, U"Sound: Get value at sample number", U"Sound: Get value at sample number...") {
+	CHANNEL4 (channel, U"Channel", U"0 (= average)")
+	INTEGER4 (sampleNumber, U"Sample number", U"100")
+	OK
+DO_ALTERNATIVE (REAL_old_Sound_getValueAtIndex)
+	NUMBER_ONE (Sound)
+		if (channel > my ny) channel = 1;
+		double result = sampleNumber < 1 || sampleNumber > my nx ? NUMundefined :
+			Sampled_getValueAtSample (me, sampleNumber, channel, 0);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_old_Sound_getValueAtTime, U"Sound: Get value at time", U"Sound: Get value at time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"Nearest")
+		RADIOBUTTON (U"Linear")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	NUMBER_ONE (Sound)
+		double result = Vector_getValueAtX (me, time, Vector_CHANNEL_AVERAGE, interpolation);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+FORM (REAL_Sound_getValueAtTime, U"Sound: Get value at time", U"Sound: Get value at time...") {
+	CHANNEL4 (channel, U"Channel", U"0 (= average)")
+	REAL4 (time, U"Time (s)", U"0.5")
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"Nearest")
+		RADIOBUTTON (U"Linear")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO_ALTERNATIVE (REAL_old_Sound_getValueAtTime)
+	NUMBER_ONE (Sound)
+		if (channel > my ny) channel = 1;
+		double result = Vector_getValueAtX (me, time, channel, interpolation);
+	NUMBER_ONE_END (U" Pascal")
+}
+
+DIRECT (HELP_Sound_help) {
+	HELP (U"Sound")
+}
+
+FORM (NEW_Sound_lengthen_overlapAdd, U"Sound: Lengthen (overlap-add)", U"Sound: Lengthen (overlap-add)...") {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	POSITIVE4 (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
+	POSITIVE4 (factor, U"Factor", U"1.5")
+	OK
+DO
+	if (minimumPitch >= maximumPitch) Melder_throw (U"Maximum pitch should be greater than minimum pitch.");
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_lengthen_overlapAdd (me, minimumPitch, maximumPitch, factor);
+	CONVERT_EACH_END (my name, U"_", Melder_fixed (factor, 2));
+}
+
+FORM (MODIFY_Sound_multiply, U"Sound: Multiply", nullptr) {
+	REAL4 (multiplicationFactor, U"Multiplication factor", U"1.5")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Vector_multiplyByScalar (me, multiplicationFactor);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Sound_multiplyByWindow, U"Sound: Multiply by window", nullptr) {
+	OPTIONMENU_ENUM4 (windowShape, U"Window shape", kSound_windowShape, HANNING)
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_multiplyByWindow (me, (kSound_windowShape) windowShape);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Sound_overrideSamplingFrequency, U"Sound: Override sampling frequency", nullptr) {
+	POSITIVE4 (newSamplingFrequency, U"New sampling frequency (Hz)", U"16000.0")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_overrideSamplingFrequency (me, newSamplingFrequency);
+	MODIFY_EACH_END
+}
+
+DIRECT (PLAY_Sound_play) {
+	int n = 0;
+	LOOP {
+		n ++;
+	}
+	if (n == 1 || MelderAudio_getOutputMaximumAsynchronicity () < kMelder_asynchronicityLevel_ASYNCHRONOUS) {
+		LOOP {
+			iam (Sound);
+			Sound_play (me, nullptr, nullptr);
+		}
+	} else {
+		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_INTERRUPTABLE);
+		LOOP {
+			iam (Sound);
+			Sound_play (me, nullptr, nullptr);   // BUG: exception-safe?
+		}
+		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_ASYNCHRONOUS);
+	}
+END }
+
+FORM (MODIFY_Sound_preemphasizeInline, U"Sound: Pre-emphasize (in-line)", U"Sound: Pre-emphasize (in-line)...") {
+	REAL4 (fromFrequency, U"From frequency (Hz)", U"50.0")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_preEmphasis (me, fromFrequency);
+		Vector_scale (me, 0.99);
+	MODIFY_EACH_END
+}
+
+FORM_READ (READMANY_Sound_readSeparateChannelsFromSoundFile, U"Read separate channels from sound file", nullptr, true) {
+	autoSound sound = Sound_readFromSoundFile (file);
+	char32 name [300];
+	Melder_sprint (name,300, MelderFile_name (file));
+	char32 *lastPeriod = str32rchr (name, U'.');
+	if (lastPeriod) {
+		*lastPeriod = U'\0';
+	}
+	for (long ichan = 1; ichan <= sound -> ny; ichan ++) {
+		autoSound thee = Sound_extractChannel (sound.get(), ichan);
+		praat_new (thee.move(), name, U"_ch", ichan);
+	}
+	END
+}
+
+FORM_READ (READ1_Sound_readFromRawAlawFile, U"Read Sound from raw Alaw file", nullptr, true) {
+	READ_ONE
+		autoSound result = Sound_readFromRawAlawFile (file);
+	READ_ONE_END
+}
+
+static SoundRecorder theReferenceToTheOnlySoundRecorder;
+static int thePreviousNumberOfChannels;
+
+static void cb_SoundRecorder_destruction (SoundRecorder /* me */) {
+	theReferenceToTheOnlySoundRecorder = nullptr;
+}
+static void cb_SoundRecorder_publication (Editor /* me */, autoDaata publication) {
+	try {
+		praat_new (publication.move());
+	} catch (MelderError) {
+		Melder_flushError ();
+	}
+	praat_updateSelection ();
+}
+static void do_Sound_record (int numberOfChannels) {
+	if (theCurrentPraatApplication -> batch)
+		Melder_throw (U"Cannot record a Sound from batch.");
+	if (theReferenceToTheOnlySoundRecorder && numberOfChannels == thePreviousNumberOfChannels) {
+		Editor_raise (theReferenceToTheOnlySoundRecorder);
+	} else {
+		forget (theReferenceToTheOnlySoundRecorder);
+		autoSoundRecorder recorder = SoundRecorder_create (numberOfChannels);
+		Editor_setDestructionCallback (recorder.get(), cb_SoundRecorder_destruction);
+		Editor_setPublicationCallback (recorder.get(), cb_SoundRecorder_publication);
+		theReferenceToTheOnlySoundRecorder = recorder.get();
+		recorder.releaseToUser();
+		thePreviousNumberOfChannels = numberOfChannels;
+	}
+}
+DIRECT (WINDOW_Sound_recordMono) {
+	do_Sound_record (1);
+END }
+DIRECT (WINDOW_Sound_recordStereo) {
+	do_Sound_record (2);
+END }
+
+FORM (RECORD1_Sound_record_fixedTime, U"Record Sound", nullptr) {
+	RADIO4 (inputSource, U"Input source", 1)
+		RADIOBUTTON (U"Microphone")
+		RADIOBUTTON (U"Line")
+	REAL4 (gain, U"Gain (0-1)", U"0.1")
+	REAL4 (balance, U"Balance (0-1)", U"0.5")
+	RADIOSTR4 (samplingFrequency, U"Sampling frequency", 1)
+		#ifdef UNIX
+		RADIOBUTTON (U"8000")
+		#endif
+		#ifndef macintosh
+		RADIOBUTTON (U"11025")
+		#endif
+		#ifdef UNIX
+		RADIOBUTTON (U"16000")
+		#endif
+		#ifndef macintosh
+		RADIOBUTTON (U"22050")
+		#endif
+		#ifdef UNIX
+		RADIOBUTTON (U"32000")
+		#endif
+		RADIOBUTTON (U"44100")
+		RADIOBUTTON (U"48000")
+		RADIOBUTTON (U"96000")
+	POSITIVE4 (duration, U"Duration (seconds)", U"1.0")
+	OK
+DO
+	CREATE_ONE
+		autoSound result = Sound_record_fixedTime (inputSource,
+			gain, balance, Melder_atof (samplingFrequency), duration);
+	CREATE_ONE_END (U"untitled")
+}
+
+extern "C" void* Praat_Sound_resample (void* sound, double newSamplingFrequency, int precision);
+#if 0
+void* Praat_Sound_resample (void* sound, double newSamplingFrequency, int precision) {
+	try {
+		if (newSamplingFrequency <= 0.0) Melder_throw (U"`newSamplingFrequency` has to be positive.");
+		if (precision <= 0) Melder_throw (U"`precision` has to be greater than 0.");
+		autoSound thee = Sound_resample ((Sound) sound, newSamplingFrequency, precision);
+		return (void*) thee.releaseToAmbiguousOwner();
+	} catch (MelderError) {
+		Melder_flushError (U"Praat: Sound_resample: not performed.");
+		return NULL;
+	}
+}
+#elif 0
+typedef struct {
+	int type;
+	union { void* _object; double _double; int _int; };
+} PraatLibArg;
+#define PraatLibArg_OBJECT  0
+#define PraatLibArg_DOUBLE  1
+#define PraatLibArg_INT  2
+extern "C" void* praatlib_do (const char *commandTitle, PraatLibArg args [], int narg);
+void* Praat_Sound_resample (void* sound, double newSamplingFrequency, int precision) {
+	PraatLibArg args [3];
+	args [0]. type = PraatLibArg_OBJECT;
+	args [0]. _object = sound;
+	args [1]. type = PraatLibArg_DOUBLE;
+	args [1]. _double = newSamplingFrequency;
+	args [2]. type = PraatLibArg_INT;
+	args [2]. _int = precision;
+	return praatlib_do ("Sound: Resample...", args, 3);
+}
+#endif
+
+FORM (NEW_Sound_resample, U"Sound: Resample", U"Sound: Resample...") {
+	POSITIVE4 (newSamplingFrequency, U"New sampling frequency (Hz)", U"10000.0")
+	NATURAL4 (precision, U"Precision (samples)", U"50")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSound result = Sound_resample (me, newSamplingFrequency, precision);
+	CONVERT_EACH_END (my name, U"_", lround (newSamplingFrequency));
+}
+
+DIRECT (MODIFY_Sound_reverse) {
+	MODIFY_EACH (Sound)
+		Sound_reverse (me, 0.0, 0.0);
+	MODIFY_EACH_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAs24BitWavFile, U"Save as 24-bit WAV file", nullptr, U"wav") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_WAV, 24);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAs32BitWavFile, U"Save as 32-bit WAV file", nullptr, U"wav") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_WAV, 32);
+	SAVE_TYPED_LIST_END
+}
+
+FORM (MODIFY_Sound_scalePeak, U"Sound: Scale peak", U"Sound: Scale peak...") {
+	POSITIVE4 (newAbsolutePeak, U"New absolute peak", U"0.99")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Vector_scale (me, newAbsolutePeak);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Sound_scaleIntensity, U"Sound: Scale intensity", U"Sound: Scale intensity...") {
+	POSITIVE4 (newAverageIntensity, U"New average intensity (dB SPL)", U"70.0")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_scaleIntensity (me, newAverageIntensity);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_old_Sound_setValueAtIndex, U"Sound: Set value at sample number", U"Sound: Set value at sample number...") {
+	NATURAL4 (sampleNumber, U"Sample number", U"100")
+	REAL4 (newValue, U"New value", U"0.0")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		if (sampleNumber > my nx)
+			Melder_throw (U"The sample number should not exceed the number of samples, which is ", my nx, U".");
+		for (long channel = 1; channel <= my ny; channel ++)
+			my z [channel] [sampleNumber] = newValue;
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Sound_setValueAtIndex, U"Sound: Set value at sample number", U"Sound: Set value at sample number...") {
+	CHANNEL4 (channel, U"Channel", U"0 (= all)")
+	NATURAL4 (sampleNumber, U"Sample number", U"100")
+	REAL4 (newValue, U"New value", U"0.0")
+	OK
+DO_ALTERNATIVE (MODIFY_old_Sound_setValueAtIndex)
+	MODIFY_EACH (Sound)
+		if (sampleNumber > my nx)
+			Melder_throw (U"The sample number should not exceed the number of samples, which is ", my nx, U".");
+		if (channel > my ny) channel = 1;
+		if (channel > 0) {
+			my z [channel] [sampleNumber] = newValue;
+		} else {
+			for (channel = 1; channel <= my ny; channel ++) {
+				my z [channel] [sampleNumber] = newValue;
+			}
+		}
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Sound_setPartToZero, U"Sound: Set part to zero", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"0.0 (= all)")
+	RADIO4x (cut, U"Cut", 2, 0)
+		OPTION (U"at exactly these times")
+		OPTION (U"at nearest zero crossing")
+	OK
+DO
+	MODIFY_EACH (Sound)
+		Sound_setZero (me, fromTime, toTime, cut);
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_Sound_subtractMean) {
+	MODIFY_EACH (Sound)
+		Vector_subtractMean (me);
+	MODIFY_EACH_END
+}
+
+FORM (NEW_Sound_to_Manipulation, U"Sound: To Manipulation", U"Manipulation") {
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.01")
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	POSITIVE4 (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
+	OK
+DO
+	if (maximumPitch <= minimumPitch) Melder_throw (U"The maximum pitch should be greater than the minimum pitch.");
+	CONVERT_EACH (Sound)
+		autoManipulation result = Sound_to_Manipulation (me, timeStep, minimumPitch, maximumPitch);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Cochleagram, U"Sound: To Cochleagram", nullptr) {
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.01")
+	POSITIVE4 (frequencyResolution, U"Frequency resolution (Bark)", U"0.1")
+	POSITIVE4 (windowLength, U"Window length (s)", U"0.03")
+	REAL4 (forwardMaskingTime, U"Forward-masking time (s)", U"0.03")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoCochleagram result = Sound_to_Cochleagram (me, timeStep,
+			frequencyResolution, windowLength, forwardMaskingTime);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Cochleagram_edb, U"Sound: To Cochleagram (De Boer, Meddis & Hewitt)", nullptr) {
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.01")
+	POSITIVE4 (frequencyResolution, U"Frequency resolution (Bark)", U"0.1")
+	BOOLEAN4 (hasSynapse, U"Has synapse", true)
+	LABEL (U"", U"Meddis synapse properties")
+	POSITIVE4 (replenishmentRate, U"   replenishment rate (/sec)", U"5.05")
+	POSITIVE4 (lossRate, U"   loss rate (/sec)", U"2500.0")
+	POSITIVE4 (returnRate, U"   return rate (/sec)", U"6580.0")
+	POSITIVE4 (reprocessingRate, U"   reprocessing rate (/sec)", U"66.31")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoCochleagram result = Sound_to_Cochleagram_edb (me, timeStep, frequencyResolution, hasSynapse,
+			replenishmentRate, lossRate, returnRate, reprocessingRate);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Formant_burg, U"Sound: To Formant (Burg method)", U"Sound: To Formant (burg)...") {
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVE4 (maximumNumberOfFormants, U"Max. number of formants", U"5.0")
+	REAL4 (maximumFormant, U"Maximum formant (Hz)", U"5500.0 (= adult female)")
+	POSITIVE4 (windowLength, U"Window length (s)", U"0.025")
+	POSITIVE4 (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoFormant result = Sound_to_Formant_burg (me, timeStep,
+			maximumNumberOfFormants, maximumFormant, windowLength, preEmphasisFrom);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Formant_keepAll, U"Sound: To Formant (keep all)", U"Sound: To Formant (keep all)...") {
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVE4 (maximumNumberOfFormants, U"Max. number of formants", U"5.0")
+	REAL4 (maximumFormant, U"Maximum formant (Hz)", U"5500.0 (= adult female)")
+	POSITIVE4 (windowLength, U"Window length (s)", U"0.025")
+	POSITIVE4 (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoFormant result = Sound_to_Formant_keepAll (me, timeStep,
+			maximumNumberOfFormants, maximumFormant, windowLength, preEmphasisFrom);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Formant_willems, U"Sound: To Formant (split Levinson (Willems))", U"Sound: To Formant (sl)...") {
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVE4 (numberOfFormants, U"Number of formants", U"5.0")
+	REAL4 (maximumFormant, U"Maximum formant (Hz)", U"5500.0 (= adult female)")
+	POSITIVE4 (windowLength, U"Window length (s)", U"0.025")
+	POSITIVE4 (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoFormant result = Sound_to_Formant_willems (me, timeStep,
+			numberOfFormants, maximumFormant, windowLength, preEmphasisFrom);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Harmonicity_ac, U"Sound: To Harmonicity (ac)", U"Sound: To Harmonicity (ac)...") {
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.01")
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	REAL4 (silenceThreshold, U"Silence threshold", U"0.1")
+	POSITIVE4 (periodsPerWindow, U"Periods per window", U"4.5")
+	OK
+DO
+	if (periodsPerWindow < 3.0) Melder_throw (U"Number of periods per window must be at least 3.0.");
+	CONVERT_EACH (Sound)
+		autoHarmonicity result = Sound_to_Harmonicity_ac (me, timeStep,
+			minimumPitch, silenceThreshold, periodsPerWindow);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Harmonicity_cc, U"Sound: To Harmonicity (cc)", U"Sound: To Harmonicity (cc)...") {
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.01")
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	REAL4 (silenceThreshold, U"Silence threshold", U"0.1")
+	POSITIVE4 (periodsPerWindow, U"Periods per window", U"4.5")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoHarmonicity result = Sound_to_Harmonicity_cc (me, timeStep,
+			minimumPitch, silenceThreshold, periodsPerWindow);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Harmonicity_gne, U"Sound: To Harmonicity (gne)", nullptr) {
+	POSITIVE4 (minimumFrequency, U"Minimum frequency (Hz)", U"500.0")
+	POSITIVE4 (maximumFrequency, U"Maximum frequency (Hz)", U"4500.0")
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"1000.0")
+	POSITIVE4 (step, U"Step (Hz)", U"80.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoMatrix result = Sound_to_Harmonicity_GNE (me, minimumFrequency,
+			maximumFrequency, bandwidth, step);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_old_Sound_to_Intensity, U"Sound: To Intensity", U"Sound: To Intensity...") {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoIntensity result = Sound_to_Intensity (me,
+			minimumPitch, timeStep, false);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Intensity, U"Sound: To Intensity", U"Sound: To Intensity...") {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	BOOLEAN4 (subtractMean, U"Subtract mean", true)
+	OK
+DO_ALTERNATIVE (NEW_old_Sound_to_Intensity)
+	CONVERT_EACH (Sound)
+		autoIntensity result = Sound_to_Intensity (me,
+			minimumPitch, timeStep, subtractMean);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_IntensityTier, U"Sound: To IntensityTier", nullptr) {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	BOOLEAN4 (subtractMean, U"Subtract mean", true)
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoIntensityTier result = Sound_to_IntensityTier (me,
+			minimumPitch, timeStep, subtractMean);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Sound_to_IntervalTier) {
+	CONVERT_EACH (Sound)
+		autoIntervalTier result = IntervalTier_create (my xmin, my xmax);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Ltas, U"Sound: To long-term average spectrum", nullptr) {
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"100")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoLtas result = Sound_to_Ltas (me, bandwidth);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Ltas_pitchCorrected, U"Sound: To Ltas (pitch-corrected)", U"Sound: To Ltas (pitch-corrected)...") {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	POSITIVE4 (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
+	POSITIVE4 (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"100.0")
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumPeriodFactor, U"Maximum period factor", U"1.3")
+	OK
+DO
+	if (maximumPitch <= minimumPitch) Melder_throw (U"Your maximum pitch should be greater than your minimum pitch.");
+	CONVERT_EACH (Sound)
+		autoLtas result = Sound_to_Ltas_pitchCorrected (me, minimumPitch, maximumPitch,
+			maximumFrequency, bandwidth, shortestPeriod, longestPeriod, maximumPeriodFactor);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Sound_to_Matrix) {
+	CONVERT_EACH (Sound)
+		autoMatrix result = Sound_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW1_Sounds_to_ParamCurve) {
+	Sound s1 = nullptr, s2 = nullptr;
+	LOOP {
+		iam (Sound);
+		( s1 ? s2 : s1 ) = me;
+	}
+	autoParamCurve thee = ParamCurve_create (s1, s2);
+	praat_new (thee.move(), s1 -> name, U"_", s2 -> name);
+END }
+
+FORM (NEW_Sound_to_Pitch, U"Sound: To Pitch", U"Sound: To Pitch...") {
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVE4 (pitchFloor, U"Pitch floor (Hz)", U"75.0")
+	POSITIVE4 (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoPitch result = Sound_to_Pitch (me, timeStep, pitchFloor, pitchCeiling);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Pitch_ac, U"Sound: To Pitch (ac)", U"Sound: To Pitch (ac)...") {
+	LABEL (U"", U"Finding the candidates")
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVE4 (pitchFloor, U"Pitch floor (Hz)", U"75.0")
+	NATURAL4 (maximumNumberOfCandidates, U"Max. number of candidates", U"15")
+	BOOLEAN4 (veryAccurate, U"Very accurate", false)
+	LABEL (U"", U"Finding a path")
+	REAL4 (silenceThreshold, U"Silence threshold", U"0.03")
+	REAL4 (voicingThreshold, U"Voicing threshold", U"0.45")
+	REAL4 (octaveCost, U"Octave cost", U"0.01")
+	REAL4 (octaveJumpCost, U"Octave-jump cost", U"0.35")
+	REAL4 (voicedUnvoicedCost, U"Voiced / unvoiced cost", U"0.14")
+	POSITIVE4 (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
+	OK
+DO
+	if (maximumNumberOfCandidates <= 1)
+		Melder_throw (U"Your maximum number of candidates should be greater than 1.");
+	CONVERT_EACH (Sound)
+		autoPitch result = Sound_to_Pitch_ac (me, timeStep,
+			pitchFloor, 3.0, maximumNumberOfCandidates, veryAccurate,
+			silenceThreshold, voicingThreshold, octaveCost, octaveJumpCost, voicedUnvoicedCost, pitchCeiling);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Pitch_cc, U"Sound: To Pitch (cc)", U"Sound: To Pitch (cc)...") {
+	LABEL (U"", U"Finding the candidates")
+	REAL4 (timeStep, U"Time step (s)", U"0.0 (= auto)")
+	POSITIVE4 (pitchFloor, U"Pitch floor (Hz)", U"75.0")
+	NATURAL4 (maximumNumberOfCandidates, U"Max. number of candidates", U"15")
+	BOOLEAN4 (veryAccurate, U"Very accurate", false)
+	LABEL (U"", U"Finding a path")
+	REAL4 (silenceThreshold, U"Silence threshold", U"0.03")
+	REAL4 (voicingThreshold, U"Voicing threshold", U"0.45")
+	REAL4 (octaveCost, U"Octave cost", U"0.01")
+	REAL4 (octaveJumpCost, U"Octave-jump cost", U"0.35")
+	REAL4 (voicedUnvoicedCost, U"Voiced / unvoiced cost", U"0.14")
+	POSITIVE4 (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
+	OK
+DO
+	long maxnCandidates = GET_INTEGER (U"Max. number of candidates");
+	if (maxnCandidates <= 1) Melder_throw (U"Maximum number of candidates must be greater than 1.");
+	CONVERT_EACH (Sound)
+		autoPitch result = Sound_to_Pitch_cc (me, timeStep,
+			pitchFloor, 1.0, maximumNumberOfCandidates, veryAccurate,
+			silenceThreshold, voicingThreshold, octaveCost, octaveJumpCost, voicedUnvoicedCost, pitchCeiling);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_PointProcess_extrema, U"Sound: To PointProcess (extrema)", nullptr) {
+	CHANNEL4 (channel, U"Channel (number, Left, or Right)", U"1")
+	BOOLEAN4 (includeMaxima, U"Include maxima", true)
+	BOOLEAN4 (includeMinima, U"Include minima", false)
+	RADIO4x (interpolation, U"Interpolation", 4, 0)
+		RADIOBUTTON (U"None")
+		RADIOBUTTON (U"Parabolic")
+		RADIOBUTTON (U"Cubic")
+		RADIOBUTTON (U"Sinc70")
+		RADIOBUTTON (U"Sinc700")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoPointProcess result = Sound_to_PointProcess_extrema (me, channel > my ny ? 1 : channel,
+			interpolation, includeMaxima, includeMinima);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_PointProcess_periodic_cc, U"Sound: To PointProcess (periodic, cc)", U"Sound: To PointProcess (periodic, cc)...") {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	POSITIVE4 (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
+	OK
+DO
+	if (maximumPitch <= minimumPitch)
+		Melder_throw (U"Your maximum pitch should be greater than your minimum pitch.");
+	CONVERT_EACH (Sound)
+		autoPointProcess result = Sound_to_PointProcess_periodic_cc (me, minimumPitch, maximumPitch);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_PointProcess_periodic_peaks, U"Sound: To PointProcess (periodic, peaks)", U"Sound: To PointProcess (periodic, peaks)...") {
+	POSITIVE4 (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
+	POSITIVE4 (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
+	BOOLEAN4 (includeMaxima, U"Include maxima", true)
+	BOOLEAN4 (includeMinima, U"Include minima", false)
+	OK
+DO
+	if (maximumPitch <= minimumPitch)
+		Melder_throw (U"Your maximum pitch should be greater than your minimum pitch.");
+	CONVERT_EACH (Sound)
+		autoPointProcess result = Sound_to_PointProcess_periodic_peaks (me,
+			minimumPitch, maximumPitch, includeMaxima, includeMinima);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_PointProcess_zeroes, U"Get zeroes", nullptr) {
+	CHANNEL4 (channel, U"Channel (number, Left, or Right)", U"1")
+	BOOLEAN4 (includeRaisers, U"Include raisers", true)
+	BOOLEAN4 (includeFallers, U"Include fallers", false)
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoPointProcess result = Sound_to_PointProcess_zeroes (me, channel > my ny ? 1 : channel,
+			includeRaisers, includeFallers);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Spectrogram, U"Sound: To Spectrogram", U"Sound: To Spectrogram...") {
+	POSITIVE4 (windowLength, U"Window length (s)", U"0.005")
+	POSITIVE4 (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.002")
+	POSITIVE4 (frequencyStep, U"Frequency step (Hz)", U"20.0")
+	RADIO_ENUM4 (windowShape, U"Window shape", kSound_to_Spectrogram_windowShape, DEFAULT)
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSpectrogram result = Sound_to_Spectrogram (me, windowLength,
+			maximumFrequency, timeStep,
+			frequencyStep, (kSound_to_Spectrogram_windowShape) windowShape, 8.0, 8.0);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_Spectrum, U"Sound: To Spectrum", U"Sound: To Spectrum...") {
+	BOOLEAN4 (fast, U"Fast", true)
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoSpectrum result = Sound_to_Spectrum (me, fast);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Sound_to_Spectrum_dft) {
+	CONVERT_EACH (Sound)
+		autoSpectrum result = Sound_to_Spectrum (me, false);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Sound_to_Spectrum_fft) {
+	CONVERT_EACH (Sound)
+		autoSpectrum result = Sound_to_Spectrum (me, true);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_Sound_to_TextGrid, U"Sound: To TextGrid", U"Sound: To TextGrid...") {
+	SENTENCE4 (allTierNames, U"All tier names", U"Mary John bell")
+	SENTENCE4 (whichOfTheseArePointTiers, U"Which of these are point tiers?", U"bell")
+	OK
+DO
+	CONVERT_EACH (Sound)
+		autoTextGrid result = TextGrid_create (my xmin, my xmax, allTierNames, whichOfTheseArePointTiers);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_Sound_to_TextTier) {
+	CONVERT_EACH (Sound)
+		autoTextTier result = TextTier_create (my xmin, my xmax);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (PREFS_SoundInputPrefs, U"Sound recording preferences", U"SoundRecorder") {
+	NATURAL4 (bufferSize, U"Buffer size (MB)", U"60")
+	OPTIONMENU_ENUM4 (inputSoundSystem, U"Input sound system", kMelder_inputSoundSystem, DEFAULT)
+OK
+	SET_INTEGER (U"Buffer size", SoundRecorder_getBufferSizePref_MB ())
+	SET_ENUM (U"Input sound system", kMelder_inputSoundSystem, MelderAudio_getInputSoundSystem())
+DO
+	if (bufferSize > 1000) Melder_throw (U"Buffer size cannot exceed 1000 megabytes.");
+	SoundRecorder_setBufferSizePref_MB (bufferSize);
+	MelderAudio_setInputSoundSystem ((kMelder_inputSoundSystem) inputSoundSystem);
+END }
+
+FORM (PREFS_SoundOutputPrefs, U"Sound playing preferences", nullptr) {
+	LABEL (U"", U"The following determines how sounds are played.")
+	LABEL (U"", U"Between parentheses, you find what you can do simultaneously.")
+	LABEL (U"", U"Decrease asynchronicity if sound plays with discontinuities.")
+	OPTIONMENU_ENUM4 (maximumAsynchronicity, U"Maximum asynchronicity", kMelder_asynchronicityLevel, DEFAULT)
+	#define xstr(s) str(s)
+	#define str(s) #s
+	REAL4 (silenceBefore, U"Silence before (s)", U"" xstr (kMelderAudio_outputSilenceBefore_DEFAULT))
+	REAL4 (silenceAfter, U"Silence after (s)", U"" xstr (kMelderAudio_outputSilenceAfter_DEFAULT))
+	OPTIONMENU_ENUM4 (outputSoundSystem, U"Output sound system", kMelder_outputSoundSystem, DEFAULT)
+OK
+	SET_ENUM (U"Maximum asynchronicity", kMelder_asynchronicityLevel, MelderAudio_getOutputMaximumAsynchronicity ())
+	SET_REAL (U"Silence before", MelderAudio_getOutputSilenceBefore ())
+	SET_REAL (U"Silence after", MelderAudio_getOutputSilenceAfter ())
+	SET_ENUM (U"Output sound system", kMelder_outputSoundSystem, MelderAudio_getOutputSoundSystem())
+DO
+	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
+	MelderAudio_setOutputMaximumAsynchronicity ((kMelder_asynchronicityLevel) maximumAsynchronicity);
+	MelderAudio_setOutputSilenceBefore (silenceBefore);
+	MelderAudio_setOutputSilenceAfter (silenceAfter);
+	MelderAudio_setOutputSoundSystem ((kMelder_outputSoundSystem) outputSoundSystem);
+	END
+}
+
+#ifdef HAVE_PULSEAUDIO
+void pulseAudio_serverReport ();
+DIRECT (INFO_Praat_reportSoundServerProperties) {
+	pulseAudio_serverReport ();
+END }
+#endif
+
+FORM_SAVE (SAVE_Sound_saveAsAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
+END }
+
+FORM_SAVE (SAVE_Sound_saveAsFlacFile, U"Save as FLAC file", nullptr, U"flac") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsKayFile, U"Save as Kay sound file", nullptr, U"kay") {
+	SAVE_ONE (Sound)
+		Sound_saveAsKayFile (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsNistFile, U"Save as NIST file", nullptr, U"nist") {
+	SAVE_TYPED_LIST (Sampled, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NIST, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw8bitSignedFile, U"Save as raw 8-bit signed sound file", nullptr, U"8sig") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_8_SIGNED);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw8bitUnsignedFile, U"Save as raw 8-bit unsigned sound file", nullptr, U"8uns") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_8_UNSIGNED);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw16bitBigEndianFile, U"Save as raw 16-bit big-endian sound file", nullptr, U"16be") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_16_BIG_ENDIAN);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw16bitLittleEndianFile, U"Save as raw 16-bit little-endian sound file", nullptr, U"16le") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_16_LITTLE_ENDIAN);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw24bitBigEndianFile, U"Save as raw 24-bit big-endian sound file", nullptr, U"24be") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_24_BIG_ENDIAN);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw24bitLittleEndianFile, U"Save as raw 24-bit little-endian sound file", nullptr, U"24le") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_24_LITTLE_ENDIAN);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw32bitBigEndianFile, U"Save as raw 32-bit big-endian sound file", nullptr, U"32be") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_32_BIG_ENDIAN);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsRaw32bitLittleEndianFile, U"Save as raw 32-bit little-endian sound file", nullptr, U"32le") {
+	SAVE_ONE (Sound)
+		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_32_LITTLE_ENDIAN);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsSesamFile, U"Save as Sesam file", nullptr, U"sdf") {
+	SAVE_ONE (Sound)
+		Sound_saveAsSesamFile (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsStereoAifcFile, U"Save as stereo AIFC file", nullptr, U"aifc") {
+	SAVE_LIST (Sound)
+		autoSound stereo = Sounds_combineToStereo (& list);
+		Sound_saveAsAudioFile (stereo.get(), file, Melder_AIFC, 16);
+	SAVE_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsStereoAiffFile, U"Save as stereo AIFF file", nullptr, U"aiff") {
+	SAVE_LIST (Sound)
+		autoSound stereo = Sounds_combineToStereo (& list);
+		Sound_saveAsAudioFile (stereo.get(), file, Melder_AIFF, 16);
+	SAVE_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsStereoNextSunFile, U"Save as stereo NeXT/Sun file", nullptr, U"au") {
+	SAVE_LIST (Sound)
+		autoSound stereo = Sounds_combineToStereo (& list);
+		Sound_saveAsAudioFile (stereo.get(), file, Melder_NEXT_SUN, 16);
+	SAVE_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsStereoNistFile, U"Save as stereo NIST file", nullptr, U"nist") {
+	SAVE_LIST (Sound)
+		autoSound stereo = Sounds_combineToStereo (& list);
+		Sound_saveAsAudioFile (stereo.get(), file, Melder_NIST, 16);
+	SAVE_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsStereoFlacFile, U"Save as stereo FLAC file", nullptr, U"flac") {
+	SAVE_LIST (Sound)
+		autoSound stereo = Sounds_combineToStereo (& list);
+		Sound_saveAsAudioFile (stereo.get(), file, Melder_FLAC, 16);
+	SAVE_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsStereoWavFile, U"Save as stereo WAV file", nullptr, U"wav") {
+	SAVE_LIST (Sound)
+		autoSound stereo = Sounds_combineToStereo (& list);
+		Sound_saveAsAudioFile (stereo.get(), file, Melder_WAV, 16);
+	SAVE_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsSunAudioFile, U"Save as NeXT/Sun file", nullptr, U"au") {
+	SAVE_TYPED_LIST (Sound, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
+	SAVE_TYPED_LIST_END
+}
+
+FORM_SAVE (SAVE_Sound_saveAsWavFile, U"Save as WAV file", nullptr, U"wav") {
+	SAVE_TYPED_LIST (Sound, SoundAndLongSoundList)
+		LongSound_concatenate (list.get(), file, Melder_WAV, 16);
+	SAVE_TYPED_LIST_END
+}
+
+/***** STOP *****/
+
+DIRECT (PLAY_stopPlayingSound) {
+	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
+END }
+
+/***** Help menus *****/
+
+DIRECT (HELP_AnnotationTutorial) {
+	HELP (U"Intro 7. Annotation")
+}
+
+DIRECT (HELP_FilteringTutorial) {
+	HELP (U"Filtering")
+}
+
+/***** file recognizers *****/
+
+static autoDaata macSoundOrEmptyFileRecognizer (int nread, const char * /* header */, MelderFile file) {
+	/***** No data in file? This may be a Macintosh sound file with only a resource fork. *****/
+	if (nread > 0) return autoDaata ();
+	Melder_throw (U"File ", file, U" contains no audio data.");   // !!!
+}
+
+static autoDaata soundFileRecognizer (int nread, const char *header, MelderFile file) {
+	if (nread < 16) return autoDaata ();
+	if (strnequ (header, "FORM", 4) && strnequ (header + 8, "AIF", 3)) return Sound_readFromSoundFile (file);
+	if (strnequ (header, "RIFF", 4) && (strnequ (header + 8, "WAVE", 4) || strnequ (header + 8, "CDDA", 4))) return Sound_readFromSoundFile (file);
+	if (strnequ (header, ".snd", 4)) return Sound_readFromSoundFile (file);
+	if (strnequ (header, "NIST_1A", 7)) return Sound_readFromSoundFile (file);
+	if (strnequ (header, "fLaC", 4)) return Sound_readFromSoundFile (file);   // Erez Volk, March 2007
+	if ((Melder_stringMatchesCriterion (MelderFile_name (file), kMelder_string_ENDS_WITH, U".mp3") ||
+	     Melder_stringMatchesCriterion (MelderFile_name (file), kMelder_string_ENDS_WITH, U".MP3"))
+		&& mp3_recognize (nread, header)) return Sound_readFromSoundFile (file);   // Erez Volk, May 2007
+	return autoDaata ();
+}
+
+static autoDaata movieFileRecognizer (int nread, const char * /* header */, MelderFile file) {
+	const char32 *fileName = MelderFile_name (file);
+	/*Melder_casual ("%d %d %d %d %d %d %d %d %d %d", header [0],
+		header [1], header [2], header [3],
+		header [4], header [5], header [6],
+		header [7], header [8], header [9]);*/
+	if (nread < 512 || (! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".mov") &&
+	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".MOV") &&
+	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".avi") &&
+	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".AVI"))) return autoDaata ();
+	Melder_throw (U"This Praat version cannot open movie files.");
+	return autoDaata ();
+}
+
+static autoDaata sesamFileRecognizer (int nread, const char * /* header */, MelderFile file) {
+	const char32 *fileName = MelderFile_name (file);
+	if (nread < 512 || (! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".sdf") &&
+	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".SDF"))) return autoDaata ();
+	return Sound_readFromSesamFile (file);
+}
+
+static autoDaata bellLabsFileRecognizer (int nread, const char *header, MelderFile file) {
+	if (nread < 16 || ! strnequ (& header [0], "SIG\n", 4)) return autoDaata ();
+	return Sound_readFromBellLabsFile (file);
+}
+
+static autoDaata kayFileRecognizer (int nread, const char *header, MelderFile file) {
+	if (nread <= 12 || ! strnequ (& header [0], "FORMDS16", 8)) return autoDaata ();
+	return Sound_readFromKayFile (file);
+}
+
+/***** override play and record buttons in manuals *****/
+
+static autoSound melderSound, melderSoundFromFile;
+static Sound last;
+static int recordProc (double duration) {
+	if (last == melderSound.get()) last = nullptr;
+	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
+	melderSound = Sound_record_fixedTime (1, 1.0, 0.5, 44100, duration);
+	if (! melderSound) return 0;
+	last = melderSound.get();
+	return 1;
+}
+static int recordFromFileProc (MelderFile file) {
+	if (last == melderSoundFromFile.get()) last = nullptr;
+	Melder_warningOff ();   // like "misssing samples"
+	melderSoundFromFile = Data_readFromFile (file). static_cast_move<structSound>();
+	Melder_warningOn ();
+	if (! melderSoundFromFile) return 0;
+	if (! Thing_isa (melderSoundFromFile.get(), classSound)) { melderSoundFromFile.reset(); return 0; }
+	last = melderSoundFromFile.get();
+	Sound_play (melderSoundFromFile.get(), nullptr, nullptr);
+	return 1;
+}
+static void playProc () {
+	if (melderSound) {
+		Sound_play (melderSound.get(), nullptr, nullptr);
+		last = melderSound.get();
+	}
+}
+static void playReverseProc () {
+	/*if (melderSound) Sound_playReverse (melderSound);*/
+}
+static int publishPlayedProc () {
+	if (! last) return 0;
+	autoSound sound = Data_copy (last);
+	return Data_publish (sound.move());
+}
+
+/***** buttons *****/
+
+void praat_Sound_init () {
+	Thing_recognizeClassesByName (classSound, classLongSound, nullptr);
+
+	Data_recognizeFileType (macSoundOrEmptyFileRecognizer);
+	Data_recognizeFileType (soundFileRecognizer);
+	Data_recognizeFileType (movieFileRecognizer);
+	Data_recognizeFileType (sesamFileRecognizer);
+	Data_recognizeFileType (bellLabsFileRecognizer);
+	Data_recognizeFileType (kayFileRecognizer);
+
+	SoundRecorder_preferences ();
+	structSoundRecorder           :: f_preferences ();
+	structFunctionEditor          :: f_preferences ();
+	LongSound_preferences ();
+	structTimeSoundEditor         :: f_preferences ();
+	structTimeSoundAnalysisEditor :: f_preferences ();
+
+	Melder_setRecordProc (recordProc);
+	Melder_setRecordFromFileProc (recordFromFileProc);
+	Melder_setPlayProc (playProc);
+	Melder_setPlayReverseProc (playReverseProc);
+	Melder_setPublishPlayedProc (publishPlayedProc);
+
+	praat_addMenuCommand (U"Objects", U"New", U"Record mono Sound...", nullptr, praat_ATTRACTIVE | 'R' | praat_NO_API, WINDOW_Sound_recordMono);
+	praat_addMenuCommand (U"Objects", U"New", U"Record stereo Sound...", nullptr, praat_NO_API, WINDOW_Sound_recordStereo);
+	praat_addMenuCommand (U"Objects", U"New", U"Record Sound (fixed time)...", nullptr, praat_HIDDEN | praat_FORCE_API, RECORD1_Sound_record_fixedTime);
+	praat_addMenuCommand (U"Objects", U"New", U"Sound", nullptr, 0, nullptr);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Sound as pure tone...", nullptr, 1, NEW1_Sound_createAsPureTone);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Sound from formula...", nullptr, 1, NEW1_Sound_createFromFormula);
+		praat_addMenuCommand (U"Objects", U"New",   U"Create Sound...", U"*Create Sound from formula...", praat_DEPTH_1 | praat_DEPRECATED_2007, NEW1_Sound_create);
+		praat_addMenuCommand (U"Objects", U"New", U"-- create sound advanced --", nullptr, 1, nullptr);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Sound as tone complex...", nullptr, 1, NEW1_Sound_createAsToneComplex);
+		praat_addMenuCommand (U"Objects", U"New",   U"Create Sound from tone complex...", U"*Create Sound as tone complex...", praat_DEPTH_1 | praat_DEPRECATED_2013, NEW1_Sound_createAsToneComplex);
+
+	praat_addMenuCommand (U"Objects", U"Open", U"-- read sound --", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Objects", U"Open", U"Open long sound file...", nullptr, 'L', READ1_LongSound_open);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read two Sounds from stereo file...", nullptr, praat_DEPRECATED_2010, READMANY_Sound_readSeparateChannelsFromSoundFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read separate channels from sound file...", nullptr, 0, READMANY_Sound_readSeparateChannelsFromSoundFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read from special sound file", nullptr, 0, nullptr);
+		praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw Alaw file...", nullptr, praat_DEPTH_1, READ1_Sound_readFromRawAlawFile);
+
+	praat_addMenuCommand (U"Objects", U"Goodies", U"Stop playing sound", nullptr, GuiMenu_ESCAPE, PLAY_stopPlayingSound);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"-- sound prefs --", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"Sound recording preferences...", nullptr, 0, PREFS_SoundInputPrefs);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"Sound playing preferences...", nullptr, 0, PREFS_SoundOutputPrefs);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"LongSound preferences...", nullptr, 0, PREFS_LongSoundPrefs);
+#ifdef HAVE_PULSEAUDIO
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report sound server properties", U"Report system properties", 0, INFO_Praat_reportSoundServerProperties);
+#endif
+
+	praat_addAction1 (classLongSound, 0, U"LongSound help", nullptr, 0, HELP_LongSound_help);
+	praat_addAction1 (classLongSound, 1, U"View", nullptr, praat_ATTRACTIVE, WINDOW_LongSound_view);
+	praat_addAction1 (classLongSound, 1,   U"Open", U"*View", praat_DEPRECATED_2011, WINDOW_LongSound_view);
+	praat_addAction1 (classLongSound, 0, U"Play part...", nullptr, 0, PLAY_LongSound_playPart);
+	praat_addAction1 (classLongSound, 1, U"Query -", nullptr, 0, nullptr);
+		praat_TimeFunction_query_init (classLongSound);
+		praat_addAction1 (classLongSound, 1, U"Sampling", nullptr, 1, nullptr);
+		praat_addAction1 (classLongSound, 1, U"Get number of samples", nullptr, 2, INTEGER_LongSound_getNumberOfSamples);
+		praat_addAction1 (classLongSound, 1, U"Get sampling period", nullptr, 2, REAL_LongSound_getSamplePeriod);
+		praat_addAction1 (classLongSound, 1,   U"Get sample duration", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getSamplePeriod);
+		praat_addAction1 (classLongSound, 1,   U"Get sample period", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getSamplePeriod);
+		praat_addAction1 (classLongSound, 1, U"Get sampling frequency", nullptr, 2, REAL_LongSound_getSampleRate);
+		praat_addAction1 (classLongSound, 1,   U"Get sample rate", U"*Get sampling frequency", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getSampleRate);
+		praat_addAction1 (classLongSound, 1, U"-- get time discretization --", nullptr, 2, nullptr);
+		praat_addAction1 (classLongSound, 1, U"Get time from sample number...", nullptr, 2, REAL_LongSound_getTimeFromIndex);
+		praat_addAction1 (classLongSound, 1,   U"Get time from index...", U"*Get time from sample number...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getTimeFromIndex);
+		praat_addAction1 (classLongSound, 1, U"Get sample number from time...", nullptr, 2, REAL_LongSound_getIndexFromTime);
+		praat_addAction1 (classLongSound, 1,   U"Get index from time...", U"*Get sample number from time...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getIndexFromTime);
+	praat_addAction1 (classLongSound, 0, U"Annotate -", nullptr, 0, nullptr);
+		praat_addAction1 (classLongSound, 0, U"Annotation tutorial", nullptr, 1, HELP_AnnotationTutorial);
+		praat_addAction1 (classLongSound, 0, U"-- to text grid --", nullptr, 1, nullptr);
+		praat_addAction1 (classLongSound, 0, U"To TextGrid...", nullptr, 1, NEW_LongSound_to_TextGrid);
+	praat_addAction1 (classLongSound, 0, U"Convert to Sound", nullptr, 0, nullptr);
+	praat_addAction1 (classLongSound, 0, U"Extract part...", nullptr, 0, NEW_LongSound_extractPart);
+	praat_addAction1 (classLongSound, 0, U"Concatenate?", nullptr, 0, INFO_LongSound_concatenate);
+	praat_addAction1 (classLongSound, 0, U"Save as WAV file...", nullptr, 0, SAVE_LongSound_saveAsWavFile);
+	praat_addAction1 (classLongSound, 0,   U"Write to WAV file...", U"*Save as WAV file...", praat_DEPRECATED_2011, SAVE_LongSound_saveAsWavFile);
+	praat_addAction1 (classLongSound, 0, U"Save as AIFF file...", nullptr, 0, SAVE_LongSound_saveAsAiffFile);
+	praat_addAction1 (classLongSound, 0,   U"Write to AIFF file...", U"*Save as AIFF file...", praat_DEPRECATED_2011, SAVE_LongSound_saveAsAiffFile);
+	praat_addAction1 (classLongSound, 0, U"Save as AIFC file...", nullptr, 0, SAVE_LongSound_saveAsAifcFile);
+	praat_addAction1 (classLongSound, 0,   U"Write to AIFC file...", U"*Save as AIFC file...", praat_DEPRECATED_2011, SAVE_LongSound_saveAsAifcFile);
+	praat_addAction1 (classLongSound, 0, U"Save as Next/Sun file...", nullptr, 0, SAVE_LongSound_saveAsNextSunFile);
+	praat_addAction1 (classLongSound, 0,   U"Write to Next/Sun file...", U"*Save as Next/Sun file...", praat_DEPRECATED_2011, SAVE_LongSound_saveAsNextSunFile);
+	praat_addAction1 (classLongSound, 0, U"Save as NIST file...", nullptr, 0, SAVE_LongSound_saveAsNistFile);
+	praat_addAction1 (classLongSound, 0,   U"Write to NIST file...", U"*Save as NIST file...", praat_DEPRECATED_2011, SAVE_LongSound_saveAsNistFile);
+	praat_addAction1 (classLongSound, 0, U"Save as FLAC file...", nullptr, 0, SAVE_LongSound_saveAsFlacFile);
+	praat_addAction1 (classLongSound, 0,   U"Write to FLAC file...", U"*Save as FLAC file...", praat_DEPRECATED_2011, SAVE_LongSound_saveAsFlacFile);
+	praat_addAction1 (classLongSound, 0, U"Save left channel as WAV file...", nullptr, 0, SAVE_LongSound_saveLeftChannelAsWavFile);
+	praat_addAction1 (classLongSound, 0,   U"Write left channel to WAV file...", U"*Save left channel as WAV file...", praat_DEPRECATED_2011, SAVE_LongSound_saveLeftChannelAsWavFile);
+	praat_addAction1 (classLongSound, 0, U"Save left channel as AIFF file...", nullptr, 0, SAVE_LongSound_saveLeftChannelAsAiffFile);
+	praat_addAction1 (classLongSound, 0,   U"Write left channel to AIFF file...", U"*Save left channel as AIFF file...", praat_DEPRECATED_2011, SAVE_LongSound_saveLeftChannelAsAiffFile);
+	praat_addAction1 (classLongSound, 0, U"Save left channel as AIFC file...", nullptr, 0, SAVE_LongSound_saveLeftChannelAsAifcFile);
+	praat_addAction1 (classLongSound, 0,   U"Write left channel to AIFC file...", U"*Save left channel as AIFC file...", praat_DEPRECATED_2011, SAVE_LongSound_saveLeftChannelAsAifcFile);
+	praat_addAction1 (classLongSound, 0, U"Save left channel as Next/Sun file...", nullptr, 0, SAVE_LongSound_saveLeftChannelAsNextSunFile);
+	praat_addAction1 (classLongSound, 0,   U"Write left channel to Next/Sun file...", U"*Save left channel as Next/Sun file...", praat_DEPRECATED_2011, SAVE_LongSound_saveLeftChannelAsNextSunFile);
+	praat_addAction1 (classLongSound, 0, U"Save left channel as NIST file...", nullptr, 0, SAVE_LongSound_saveLeftChannelAsNistFile);
+	praat_addAction1 (classLongSound, 0,   U"Write left channel to NIST file...", U"*Save left channel as NIST file...", praat_DEPRECATED_2011, SAVE_LongSound_saveLeftChannelAsNistFile);
+	praat_addAction1 (classLongSound, 0, U"Save left channel as FLAC file...", nullptr, 0, SAVE_LongSound_saveLeftChannelAsFlacFile);
+	praat_addAction1 (classLongSound, 0,   U"Write left channel to FLAC file...", U"*Save left channel as FLAC file...", praat_DEPRECATED_2011, SAVE_LongSound_saveLeftChannelAsFlacFile);
+	praat_addAction1 (classLongSound, 0, U"Save right channel as WAV file...", nullptr, 0, SAVE_LongSound_saveRightChannelAsWavFile);
+	praat_addAction1 (classLongSound, 0,   U"Write right channel to WAV file...", U"*Save right channel as WAV file...", praat_DEPRECATED_2011, SAVE_LongSound_saveRightChannelAsWavFile);
+	praat_addAction1 (classLongSound, 0, U"Save right channel as AIFF file...", nullptr, 0, SAVE_LongSound_saveRightChannelAsAiffFile);
+	praat_addAction1 (classLongSound, 0,   U"Write right channel to AIFF file...", U"*Save right channel as AIFF file...", praat_DEPRECATED_2011, SAVE_LongSound_saveRightChannelAsAiffFile);
+	praat_addAction1 (classLongSound, 0, U"Save right channel as AIFC file...", nullptr, 0, SAVE_LongSound_saveRightChannelAsAifcFile);
+	praat_addAction1 (classLongSound, 0,   U"Write right channel to AIFC file...", U"*Save right channel as AIFC file...", praat_DEPRECATED_2011, SAVE_LongSound_saveRightChannelAsAifcFile);
+	praat_addAction1 (classLongSound, 0, U"Save right channel as Next/Sun file...", nullptr, 0, SAVE_LongSound_saveRightChannelAsNextSunFile);
+	praat_addAction1 (classLongSound, 0,   U"Write right channel to Next/Sun file...", U"*Save right channel as Next/Sun file...", praat_DEPRECATED_2011, SAVE_LongSound_saveRightChannelAsNextSunFile);
+	praat_addAction1 (classLongSound, 0, U"Save right channel as NIST file...", nullptr, 0, SAVE_LongSound_saveRightChannelAsNistFile);
+	praat_addAction1 (classLongSound, 0,   U"Write right channel to NIST file...", U"*Save right channel as NIST file...", praat_DEPRECATED_2011, SAVE_LongSound_saveRightChannelAsNistFile);
+	praat_addAction1 (classLongSound, 0, U"Save right channel as FLAC file...", nullptr, 0, SAVE_LongSound_saveRightChannelAsFlacFile);
+	praat_addAction1 (classLongSound, 0,   U"Write right channel to FLAC file...", U"*Save right channel as FLAC file...", praat_DEPRECATED_2011, SAVE_LongSound_saveRightChannelAsFlacFile);
+	praat_addAction1 (classLongSound, 0, U"Save part as audio file...", nullptr, 0, SAVE_LongSound_savePartAsAudioFile);
+	praat_addAction1 (classLongSound, 0,   U"Write part to audio file...", U"*Save part as audio file...", praat_DEPRECATED_2011, SAVE_LongSound_savePartAsAudioFile);
+
+	praat_addAction1 (classSound, 0, U"Save as WAV file...", nullptr, 0, SAVE_Sound_saveAsWavFile);
+	praat_addAction1 (classSound, 0,   U"Write to WAV file...", U"*Save as WAV file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsWavFile);
+	praat_addAction1 (classSound, 0, U"Save as AIFF file...", nullptr, 0, SAVE_Sound_saveAsAiffFile);
+	praat_addAction1 (classSound, 0,   U"Write to AIFF file...", U"*Save as AIFF file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsAiffFile);
+	praat_addAction1 (classSound, 0, U"Save as AIFC file...", nullptr, 0, SAVE_Sound_saveAsAifcFile);
+	praat_addAction1 (classSound, 0,   U"Write to AIFC file...", U"*Save as AIFC file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsAifcFile);
+	praat_addAction1 (classSound, 0, U"Save as Next/Sun file...", nullptr, 0, SAVE_Sound_saveAsNextSunFile);
+	praat_addAction1 (classSound, 0,   U"Write to Next/Sun file...", U"*Save as Next/Sun file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsNextSunFile);
+	praat_addAction1 (classSound, 0, U"Save as Sun audio file...", nullptr, praat_HIDDEN, SAVE_Sound_saveAsSunAudioFile);
+	praat_addAction1 (classSound, 0,   U"Write to Sun audio file...", U"*Save as Sun audio file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsSunAudioFile);
+	praat_addAction1 (classSound, 0, U"Save as NIST file...", nullptr, 0, SAVE_Sound_saveAsNistFile);
+	praat_addAction1 (classSound, 0,   U"Write to NIST file...", U"*Save as NIST file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsNistFile);
+	praat_addAction1 (classSound, 0, U"Save as FLAC file...", nullptr, 0, SAVE_Sound_saveAsFlacFile);
+	praat_addAction1 (classSound, 0,   U"Write to FLAC file...", U"*Save as FLAC file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsFlacFile);
+	praat_addAction1 (classSound, 1, U"Save as Kay sound file...", nullptr, 0, SAVE_Sound_saveAsKayFile);
+	praat_addAction1 (classSound, 1,   U"Write to Kay sound file...", U"*Save as Kay sound file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsKayFile);
+	praat_addAction1 (classSound, 1, U"Save as Sesam file...", nullptr, praat_HIDDEN, SAVE_Sound_saveAsSesamFile);
+	praat_addAction1 (classSound, 1,   U"Write to Sesam file...", U"*Save as Sesam file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsSesamFile);
+	praat_addAction1 (classSound, 0, U"Save as 24-bit WAV file...", nullptr, 0, SAVE_Sound_saveAs24BitWavFile);
+	praat_addAction1 (classSound, 0, U"Save as 32-bit WAV file...", nullptr, 0, SAVE_Sound_saveAs32BitWavFile);
+	praat_addAction1 (classSound, 2,   U"Write to stereo WAV file...", U"* \"Combine to stereo\" and \"Save to WAV file...\"", praat_DEPRECATED_2007, SAVE_Sound_saveAsStereoWavFile);
+	praat_addAction1 (classSound, 2,   U"Write to stereo AIFF file...", U"* \"Combine to stereo\" and \"Save to AIFF file...\"", praat_DEPRECATED_2007, SAVE_Sound_saveAsStereoAiffFile);
+	praat_addAction1 (classSound, 2,   U"Write to stereo AIFC file...", U"* \"Combine to stereo\" and \"Save to AIFC file...\"", praat_DEPRECATED_2007, SAVE_Sound_saveAsStereoAifcFile);
+	praat_addAction1 (classSound, 2,   U"Write to stereo Next/Sun file...", U"* \"Combine to stereo\" and \"Save to Next/Sun file...\"", praat_DEPRECATED_2007, SAVE_Sound_saveAsStereoNextSunFile);
+	praat_addAction1 (classSound, 2,   U"Write to stereo NIST file...", U"* \"Combine to stereo\" and \"Save to NIST file...\"", praat_DEPRECATED_2007, SAVE_Sound_saveAsStereoNistFile);
+	praat_addAction1 (classSound, 2,   U"Write to stereo FLAC file...", U"* \"Combine to stereo\" and \"Save to FLAC file...\"", praat_DEPRECATED_2007, SAVE_Sound_saveAsStereoFlacFile);
+	//praat_addAction1 (classSound, 1, U"Save as raw sound file", nullptr, 0, nullptr);
+	praat_addAction1 (classSound, 1, U"Save as raw 8-bit signed file...", nullptr, 0, SAVE_Sound_saveAsRaw8bitSignedFile);
+	praat_addAction1 (classSound, 1,   U"Write to raw 8-bit signed file...", U"*Save as raw 8-bit signed file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsRaw8bitSignedFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 8-bit unsigned file...", nullptr, 0, SAVE_Sound_saveAsRaw8bitUnsignedFile);
+	praat_addAction1 (classSound, 1,   U"Write to raw 8-bit unsigned file...", U"*Save as raw 8-bit unsigned file...", praat_DEPRECATED_2011, SAVE_Sound_saveAsRaw8bitUnsignedFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 16-bit big-endian file...", nullptr, 0, SAVE_Sound_saveAsRaw16bitBigEndianFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 16-bit little-endian file...", nullptr, 0, SAVE_Sound_saveAsRaw16bitLittleEndianFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 24-bit big-endian file...", nullptr, 0, SAVE_Sound_saveAsRaw24bitBigEndianFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 24-bit little-endian file...", nullptr, 0, SAVE_Sound_saveAsRaw24bitLittleEndianFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 32-bit big-endian file...", nullptr, 0, SAVE_Sound_saveAsRaw32bitBigEndianFile);
+	praat_addAction1 (classSound, 1, U"Save as raw 32-bit little-endian file...", nullptr, 0, SAVE_Sound_saveAsRaw32bitLittleEndianFile);
+	praat_addAction1 (classSound, 0, U"Sound help", nullptr, 0, HELP_Sound_help);
+	praat_addAction1 (classSound, 1, U"View & Edit", 0, praat_ATTRACTIVE | praat_NO_API, WINDOW_Sound_viewAndEdit);
+	praat_addAction1 (classSound, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011 | praat_NO_API, WINDOW_Sound_viewAndEdit);
+	praat_addAction1 (classSound, 1,   U"Open", U"*View & Edit", praat_DEPRECATED_2011 | praat_NO_API, WINDOW_Sound_viewAndEdit);
+	praat_addAction1 (classSound, 0, U"Play", nullptr, 0, PLAY_Sound_play);
+	praat_addAction1 (classSound, 1, U"Draw -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"Draw...", nullptr, 1, GRAPHICS_Sound_draw);
+	praat_addAction1 (classSound, 1, U"Query -", nullptr, 0, nullptr);
+		praat_TimeFunction_query_init (classSound);
+		praat_addAction1 (classSound, 1, U"Get number of channels", nullptr, 1, INTEGER_Sound_getNumberOfChannels);
+		praat_addAction1 (classSound, 1, U"Query time sampling", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 1, U"Get number of samples", nullptr, 2, INTEGER_Sound_getNumberOfSamples);
+		praat_addAction1 (classSound, 1, U"Get sampling period", nullptr, 2, REAL_Sound_getSamplePeriod);
+		praat_addAction1 (classSound, 1,   U"Get sample duration", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Sound_getSamplePeriod);
+		praat_addAction1 (classSound, 1,   U"Get sample period", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Sound_getSamplePeriod);
+		praat_addAction1 (classSound, 1, U"Get sampling frequency", nullptr, 2, REAL_Sound_getSampleRate);
+		praat_addAction1 (classSound, 1,   U"Get sample rate", U"*Get sampling frequency", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Sound_getSampleRate);
+		praat_addAction1 (classSound, 1, U"-- get time discretization --", nullptr, 2, nullptr);
+		praat_addAction1 (classSound, 1, U"Get time from sample number...", nullptr, 2, REAL_Sound_getTimeFromIndex);
+		praat_addAction1 (classSound, 1,   U"Get time from index...", U"*Get time from sample number...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Sound_getTimeFromIndex);
+		praat_addAction1 (classSound, 1, U"Get sample number from time...", nullptr, 2, REAL_Sound_getIndexFromTime);
+		praat_addAction1 (classSound, 1,   U"Get index from time...", U"*Get sample number from time...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_Sound_getIndexFromTime);
+		praat_addAction1 (classSound, 1, U"-- get content --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 1, U"Get value at time...", nullptr, 1, REAL_Sound_getValueAtTime);
+		praat_addAction1 (classSound, 1, U"Get value at sample number...", nullptr, 1, REAL_Sound_getValueAtIndex);
+		praat_addAction1 (classSound, 1,   U"Get value at index...", U"*Get value at sample number...", praat_DEPTH_1 | praat_DEPRECATED_2004, REAL_Sound_getValueAtIndex);
+		praat_addAction1 (classSound, 1, U"-- get shape --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 1, U"Get minimum...", nullptr, 1, REAL_Sound_getMinimum);
+		praat_addAction1 (classSound, 1, U"Get time of minimum...", nullptr, 1, REAL_Sound_getTimeOfMinimum);
+		praat_addAction1 (classSound, 1, U"Get maximum...", nullptr, 1, REAL_Sound_getMaximum);
+		praat_addAction1 (classSound, 1, U"Get time of maximum...", nullptr, 1, REAL_Sound_getTimeOfMaximum);
+		praat_addAction1 (classSound, 1, U"Get absolute extremum...", nullptr, 1, REAL_Sound_getAbsoluteExtremum);
+		praat_addAction1 (classSound, 1, U"Get nearest zero crossing...", nullptr, 1, REAL_Sound_getNearestZeroCrossing);
+		praat_addAction1 (classSound, 1, U"-- get statistics --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 1, U"Get mean...", nullptr, 1, REAL_Sound_getMean);
+		praat_addAction1 (classSound, 1, U"Get root-mean-square...", nullptr, 1, REAL_Sound_getRootMeanSquare);
+		praat_addAction1 (classSound, 1, U"Get standard deviation...", nullptr, 1, REAL_Sound_getStandardDeviation);
+		praat_addAction1 (classSound, 1, U"-- get energy --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 1, U"Get energy...", nullptr, 1, REAL_Sound_getEnergy);
+		praat_addAction1 (classSound, 1, U"Get power...", nullptr, 1, REAL_Sound_getPower);
+		praat_addAction1 (classSound, 1, U"-- get energy in air --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 1, U"Get energy in air", nullptr, 1, REAL_Sound_getEnergyInAir);
+		praat_addAction1 (classSound, 1, U"Get power in air", nullptr, 1, REAL_Sound_getPowerInAir);
+		praat_addAction1 (classSound, 1, U"Get intensity (dB)", nullptr, 1, REAL_Sound_getIntensity_dB);
+	praat_addAction1 (classSound, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeFunction_modify_init (classSound);
+		praat_addAction1 (classSound, 0, U"-- modify generic --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Reverse", nullptr, 1, MODIFY_Sound_reverse);
+		praat_addAction1 (classSound, 0, U"Formula...", nullptr, 1, MODIFY_Sound_formula);
+		praat_addAction1 (classSound, 0, U"Formula (part)...", nullptr, 1, MODIFY_Sound_formula_part);
+		praat_addAction1 (classSound, 0, U"-- add & mul --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Add...", nullptr, 1, MODIFY_Sound_add);
+		praat_addAction1 (classSound, 0, U"Subtract mean", nullptr, 1, MODIFY_Sound_subtractMean);
+		praat_addAction1 (classSound, 0, U"Multiply...", nullptr, 1, MODIFY_Sound_multiply);
+		praat_addAction1 (classSound, 0, U"Multiply by window...", nullptr, 1, MODIFY_Sound_multiplyByWindow);
+		praat_addAction1 (classSound, 0, U"Scale peak...", nullptr, 1, MODIFY_Sound_scalePeak);
+		praat_addAction1 (classSound, 0,   U"Scale...", nullptr, praat_DEPTH_1 | praat_DEPRECATED_2004, MODIFY_Sound_scalePeak);
+		praat_addAction1 (classSound, 0, U"Scale intensity...", nullptr, 1, MODIFY_Sound_scaleIntensity);
+		praat_addAction1 (classSound, 0, U"-- set --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Set value at sample number...", nullptr, 1, MODIFY_Sound_setValueAtIndex);
+		praat_addAction1 (classSound, 0,   U"Set value at index...", U"*Set value at sample number...", praat_DEPTH_1 | praat_DEPRECATED_2004, MODIFY_Sound_setValueAtIndex);
+		praat_addAction1 (classSound, 0, U"Set part to zero...", nullptr, 1, MODIFY_Sound_setPartToZero);
+		praat_addAction1 (classSound, 0, U"-- modify hack --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Override sampling frequency...", nullptr, 1, MODIFY_Sound_overrideSamplingFrequency);
+		praat_addAction1 (classSound, 0,   U"Override sample rate...", U"*Override sampling frequency...", praat_DEPTH_1 | praat_DEPRECATED_2004, MODIFY_Sound_overrideSamplingFrequency);
+		praat_addAction1 (classSound, 0, U"-- in-line filters --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"In-line filters", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Filter with one formant (in-line)...", nullptr, 2, MODIFY_Sound_filterWithOneFormantInline);
+		praat_addAction1 (classSound, 0, U"Pre-emphasize (in-line)...", nullptr, 2, MODIFY_Sound_preemphasizeInline);
+		praat_addAction1 (classSound, 0, U"De-emphasize (in-line)...", nullptr, 2, MODIFY_Sound_deemphasizeInline);
+	praat_addAction1 (classSound, 0, U"Annotate -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"Annotation tutorial", nullptr, 1, HELP_AnnotationTutorial);
+		praat_addAction1 (classSound, 0, U"-- to text grid --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"To TextGrid...", nullptr, 1, NEW_Sound_to_TextGrid);
+		praat_addAction1 (classSound, 0, U"To TextTier", nullptr, praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_to_TextTier);
+		praat_addAction1 (classSound, 0, U"To IntervalTier", nullptr, praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_to_IntervalTier);
+	praat_addAction1 (classSound, 0, U"Analyse periodicity -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"To Pitch...", nullptr, 1, NEW_Sound_to_Pitch);
+		praat_addAction1 (classSound, 0, U"To Pitch (ac)...", nullptr, 1, NEW_Sound_to_Pitch_ac);
+		praat_addAction1 (classSound, 0, U"To Pitch (cc)...", nullptr, 1, NEW_Sound_to_Pitch_cc);
+		praat_addAction1 (classSound, 0, U"To PointProcess (periodic, cc)...", nullptr, 1, NEW_Sound_to_PointProcess_periodic_cc);
+		praat_addAction1 (classSound, 0, U"To PointProcess (periodic, peaks)...", nullptr, 1, NEW_Sound_to_PointProcess_periodic_peaks);
+		praat_addAction1 (classSound, 0, U"-- points --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"To PointProcess (extrema)...", nullptr, 1, NEW_Sound_to_PointProcess_extrema);
+		praat_addAction1 (classSound, 0, U"To PointProcess (zeroes)...", nullptr, 1, NEW_Sound_to_PointProcess_zeroes);
+		praat_addAction1 (classSound, 0, U"-- hnr --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"To Harmonicity (cc)...", nullptr, 1, NEW_Sound_to_Harmonicity_cc);
+		praat_addAction1 (classSound, 0, U"To Harmonicity (ac)...", nullptr, 1, NEW_Sound_to_Harmonicity_ac);
+		praat_addAction1 (classSound, 0, U"To Harmonicity (gne)...", nullptr, 1, NEW_Sound_to_Harmonicity_gne);
+		praat_addAction1 (classSound, 0, U"-- autocorrelation --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Autocorrelate...", nullptr, 1, NEW_Sound_autoCorrelate);
+	praat_addAction1 (classSound, 0, U"Analyse spectrum -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"To Spectrum...", nullptr, 1, NEW_Sound_to_Spectrum);
+		praat_addAction1 (classSound, 0,   U"To Spectrum (fft)", U"*To Spectrum...", praat_DEPTH_1 | praat_DEPRECATED_2004, NEW_Sound_to_Spectrum_fft);
+		praat_addAction1 (classSound, 0,   U"To Spectrum", U"*To Spectrum...", praat_DEPTH_1 | praat_DEPRECATED_2004, NEW_Sound_to_Spectrum_fft);
+		praat_addAction1 (classSound, 0,   U"To Spectrum (dft)", U"*To Spectrum...", praat_DEPTH_1 | praat_DEPRECATED_2004, NEW_Sound_to_Spectrum_dft);
+		praat_addAction1 (classSound, 0, U"To Ltas...", nullptr, 1, NEW_Sound_to_Ltas);
+		praat_addAction1 (classSound, 0, U"To Ltas (pitch-corrected)...", nullptr, 1, NEW_Sound_to_Ltas_pitchCorrected);
+		praat_addAction1 (classSound, 0, U"-- spectrotemporal --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"To Spectrogram...", nullptr, 1, NEW_Sound_to_Spectrogram);
+		praat_addAction1 (classSound, 0, U"To Cochleagram...", nullptr, 1, NEW_Sound_to_Cochleagram);
+		praat_addAction1 (classSound, 0, U"To Cochleagram (edb)...", nullptr, praat_DEPTH_1 | praat_HIDDEN, NEW_Sound_to_Cochleagram_edb);
+		praat_addAction1 (classSound, 0, U"-- formants --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"To Formant (burg)...", nullptr, 1, NEW_Sound_to_Formant_burg);
+		praat_addAction1 (classSound, 0, U"To Formant (hack)", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"To Formant (keep all)...", nullptr, 2, NEW_Sound_to_Formant_keepAll);
+		praat_addAction1 (classSound, 0, U"To Formant (sl)...", nullptr, 2, NEW_Sound_to_Formant_willems);
+	praat_addAction1 (classSound, 0, U"To Intensity...", nullptr, 0, NEW_Sound_to_Intensity);
+	praat_addAction1 (classSound, 0, U"To IntensityTier...", nullptr, praat_HIDDEN, NEW_Sound_to_IntensityTier);
+	praat_addAction1 (classSound, 0, U"Manipulate -", nullptr, 0, nullptr);
+	praat_addAction1 (classSound, 0, U"To Manipulation...", nullptr, 1, NEW_Sound_to_Manipulation);
+	praat_addAction1 (classSound, 0, U"Convert -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"Convert to mono", nullptr, 1, NEW_Sound_convertToMono);
+		praat_addAction1 (classSound, 0, U"Convert to stereo", nullptr, 1, NEW_Sound_convertToStereo);
+		praat_addAction1 (classSound, 0, U"Extract all channels", nullptr, 1, NEWMANY_Sound_extractAllChannels);
+		praat_addAction1 (classSound, 0, U"Extract one channel...", nullptr, 1, NEW_Sound_extractChannel);
+		praat_addAction1 (classSound, 0,   U"Extract left channel", U"*Extract one channel...", praat_DEPTH_1 | praat_DEPRECATED_2010, NEW_Sound_extractLeftChannel);
+		praat_addAction1 (classSound, 0,   U"Extract right channel", U"*Extract one channel...", praat_DEPTH_1 | praat_DEPRECATED_2010, NEW_Sound_extractRightChannel);
+		praat_addAction1 (classSound, 0, U"Extract part...", nullptr, 1, NEW_Sound_extractPart);
+		praat_addAction1 (classSound, 0, U"Extract part for overlap...", nullptr, 1, NEW_Sound_extractPartForOverlap);
+		praat_addAction1 (classSound, 0, U"Resample...", nullptr, 1, NEW_Sound_resample);
+		praat_addAction1 (classSound, 0, U"-- enhance --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Lengthen (overlap-add)...", nullptr, 1, NEW_Sound_lengthen_overlapAdd);
+		praat_addAction1 (classSound, 0,   U"Lengthen (PSOLA)...", U"*Lengthen (overlap-add)...", praat_DEPTH_1 | praat_DEPRECATED_2007, NEW_Sound_lengthen_overlapAdd);
+		praat_addAction1 (classSound, 0, U"Deepen band modulation...", nullptr, 1, NEW_Sound_deepenBandModulation);
+		praat_addAction1 (classSound, 0, U"-- cast --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Down to Matrix", nullptr, 1, NEW_Sound_to_Matrix);
+	praat_addAction1 (classSound, 0, U"Filter -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"Filtering tutorial", nullptr, 1, HELP_FilteringTutorial);
+		praat_addAction1 (classSound, 0, U"-- frequency-domain filter --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Filter (pass Hann band)...", nullptr, 1, NEW_Sound_filter_passHannBand);
+		praat_addAction1 (classSound, 0, U"Filter (stop Hann band)...", nullptr, 1, NEW_Sound_filter_stopHannBand);
+		praat_addAction1 (classSound, 0, U"Filter (formula)...", nullptr, 1, NEW_Sound_filter_formula);
+		praat_addAction1 (classSound, 0, U"-- time-domain filter --", nullptr, 1, nullptr);
+		praat_addAction1 (classSound, 0, U"Filter (one formant)...", nullptr, 1, NEW_Sound_filter_oneFormant);
+		praat_addAction1 (classSound, 0, U"Filter (pre-emphasis)...", nullptr, 1, NEW_Sound_filter_preemphasis);
+		praat_addAction1 (classSound, 0, U"Filter (de-emphasis)...", nullptr, 1, NEW_Sound_filter_deemphasis);
+	praat_addAction1 (classSound, 0, U"Combine -", nullptr, 0, nullptr);
+		praat_addAction1 (classSound, 0, U"Combine to stereo", nullptr, 1, NEW1_Sounds_combineToStereo);
+		praat_addAction1 (classSound, 0, U"Concatenate", nullptr, 1, NEW1_Sounds_concatenate);
+		praat_addAction1 (classSound, 0, U"Concatenate recoverably", nullptr, 1, NEW2_Sounds_concatenateRecoverably);
+		praat_addAction1 (classSound, 0, U"Concatenate with overlap...", nullptr, 1, NEW1_Sounds_concatenateWithOverlap);
+		praat_addAction1 (classSound, 2, U"Convolve...", nullptr, 1, NEW1_Sounds_convolve);
+		praat_addAction1 (classSound, 2,   U"Convolve", U"*Convolve...", praat_DEPTH_1 | praat_DEPRECATED_2010, NEW1_Sounds_convolve_old);
+		praat_addAction1 (classSound, 2, U"Cross-correlate...", nullptr, 1, NEW1_Sounds_crossCorrelate);
+		praat_addAction1 (classSound, 2, U"To ParamCurve", nullptr, 1, NEW1_Sounds_to_ParamCurve);
+
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as WAV file...", nullptr, 0, SAVE_LongSound_Sound_saveAsWavFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to WAV file...", U"*Save as WAV file...", praat_DEPRECATED_2011, SAVE_LongSound_Sound_saveAsWavFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as AIFF file...", nullptr, 0, SAVE_LongSound_Sound_saveAsAiffFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to AIFF file...", U"*Save as AIFF file...", praat_DEPRECATED_2011, SAVE_LongSound_Sound_saveAsAiffFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as AIFC file...", nullptr, 0, SAVE_LongSound_Sound_saveAsAifcFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to AIFC file...", U"*Save as AIFC file...", praat_DEPRECATED_2011, SAVE_LongSound_Sound_saveAsAifcFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as NeXT/Sun file...", nullptr, 0, SAVE_LongSound_Sound_saveAsNextSunFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to NeXT/Sun file...", U"*Save as NeXT/Sun file...", praat_DEPRECATED_2011, SAVE_LongSound_Sound_saveAsNextSunFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as NIST file...", nullptr, 0, SAVE_LongSound_Sound_saveAsNistFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to NIST file...", U"*Save as NIST file...", praat_DEPRECATED_2011, SAVE_LongSound_Sound_saveAsNistFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as FLAC file...", nullptr, 0, SAVE_LongSound_Sound_saveAsFlacFile);
+	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to FLAC file...", U"*Save as FLAC file...", praat_DEPRECATED_2011, SAVE_LongSound_Sound_saveAsFlacFile);
+}
+
+/* End of file praat_Sound.cpp */
diff --git a/sys/InfoEditor.h b/fon/praat_Sound.h
similarity index 63%
copy from sys/InfoEditor.h
copy to fon/praat_Sound.h
index 032e683..ececb35 100644
--- a/sys/InfoEditor.h
+++ b/fon/praat_Sound.h
@@ -1,8 +1,8 @@
-#ifndef _InfoEditor_h_
-#define _InfoEditor_h_
-/* InfoEditor.h
+#ifndef _praat_Sound_h_
+#define _praat_Sound_h_
+/* praat_Sound.h
  *
- * Copyright (C) 2004-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,18 +18,15 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "TextEditor.h"
+/*
+	User interface functions for Sound and LongSound.
+*/
 
-Thing_define (InfoEditor, TextEditor) {
-	void v_destroy () noexcept
-		override;
-	bool v_scriptable ()
-		override { return false; }
-	bool v_fileBased ()
-		override { return false; }
-	void v_clear ()
-		override;
-};
+#include "Sound.h"
+#include "LongSound.h"
+#include "praat_TimeFunction.h"
 
-/* End of file InfoEditor.h */
+void praat_Sound_init ();
+
+/* End of file praat_Sound.h */
 #endif
diff --git a/fon/praat_Sound_init.cpp b/fon/praat_Sound_init.cpp
deleted file mode 100644
index e9ecc23..0000000
--- a/fon/praat_Sound_init.cpp
+++ /dev/null
@@ -1,2738 +0,0 @@
-/* praat_Sound_init.cpp
- *
- * Copyright (C) 1992-2012,2014,2015,2016 Paul Boersma
- *
- * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "praat.h"
-
-#include "Ltas.h"
-#include "LongSound.h"
-#include "Manipulation.h"
-#include "ParamCurve.h"
-#include "Sound_and_Spectrogram.h"
-#include "Sound_and_Spectrum.h"
-#include "Sound_extensions.h"
-#include "Sound_to_Cochleagram.h"
-#include "Sound_to_Formant.h"
-#include "Sound_to_Harmonicity.h"
-#include "Sound_to_Intensity.h"
-#include "Sound_to_Pitch.h"
-#include "Sound_to_PointProcess.h"
-#include "SoundEditor.h"
-#include "SoundRecorder.h"
-#include "SpectrumEditor.h"
-#include "TextGrid_Sound.h"
-#include "mp3.h"
-
-#undef iam
-#define iam iam_LOOP
-
-void praat_TimeFunction_query_init (ClassInfo klas);
-void praat_TimeFunction_modify_init (ClassInfo klas);
-
-/***** LONGSOUND *****/
-
-DIRECT2 (LongSound_concatenate) {
-	Melder_information (U"To concatenate LongSound objects, select them in the list\nand choose \"Save as WAV file...\" or a similar command.\n"
-		"The result will be a sound file that contains\nthe concatenation of the selected sounds.");
-END2 }
-
-FORM (LongSound_extractPart, U"LongSound: Extract part", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1.0")
-	BOOLEAN (U"Preserve times", true)
-	OK2
-DO
-	LOOP {
-		iam (LongSound);
-		autoSound thee = LongSound_extractPart (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Preserve times"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (LongSound_getIndexFromTime, U"LongSound: Get sample index from time", U"Sound: Get index from time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (LongSound);
-		double index = Sampled_xToIndex (me, GET_REAL (U"Time"));
-		Melder_informationReal (index, nullptr);
-	}
-END2 }
-
-DIRECT2 (LongSound_getSamplePeriod) {
-	LOOP {
-		iam (LongSound);
-		Melder_informationReal (my dx, U"seconds");
-	}
-END2 }
-
-DIRECT2 (LongSound_getSampleRate) {
-	LOOP {
-		iam (LongSound);
-		Melder_informationReal (1.0 / my dx, U"Hz");
-	}
-END2 }
-
-FORM (LongSound_getTimeFromIndex, U"LongSound: Get time from sample index", U"Sound: Get time from index...") {
-	INTEGER (U"Sample index", U"100")
-	OK2
-DO
-	LOOP {
-		iam (LongSound);
-		Melder_informationReal (Sampled_indexToX (me, GET_INTEGER (U"Sample index")), U"seconds");
-	}
-END2 }
-
-DIRECT2 (LongSound_getNumberOfSamples) {
-	LOOP {
-		iam (LongSound);
-		Melder_information (my nx, U" samples");
-	}
-END2 }
-
-DIRECT2 (LongSound_help) { Melder_help (U"LongSound"); END2 }
-
-FORM_READ2 (LongSound_open, U"Open long sound file", nullptr, true) {
-	autoLongSound me = LongSound_open (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
-
-FORM (LongSound_playPart, U"LongSound: Play part", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	OK2
-DO
-	int n = 0;
-	LOOP n ++;
-	if (n == 1 || MelderAudio_getOutputMaximumAsynchronicity () < kMelder_asynchronicityLevel_ASYNCHRONOUS) {
-		LOOP {
-			iam (LongSound);
-			LongSound_playPart (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), nullptr, nullptr);
-		}
-	} else {
-		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_INTERRUPTABLE);
-		LOOP {
-			iam (LongSound);
-			LongSound_playPart (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), nullptr, nullptr);
-		}
-		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_ASYNCHRONOUS);
-	}
-END2 }
-
-FORM (LongSound_writePartToAudioFile, U"LongSound: Save part as audio file", nullptr) {
-	LABEL (U"", U"Audio file:")
-	TEXTFIELD (U"Audio file", U"")
-	RADIO (U"Type", 3)
-	{ int i; for (i = 1; i <= Melder_NUMBER_OF_AUDIO_FILE_TYPES; i ++) {
-		RADIOBUTTON (Melder_audioFileTypeString (i))
-	}}
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"10.0")
-	OK2
-DO
-	LOOP {
-		iam (LongSound);
-		structMelderFile file = { 0 };
-		Melder_relativePathToFile (GET_STRING (U"Audio file"), & file);
-		LongSound_writePartToAudioFile (me, GET_INTEGER (U"Type"),
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), & file, 16);
-	}
-END2 }
-	
-FORM (LongSound_to_TextGrid, U"LongSound: To TextGrid...", U"LongSound: To TextGrid...") {
-	SENTENCE (U"Tier names", U"Mary John bell")
-	SENTENCE (U"Point tiers", U"bell")
-	OK2
-DO
-	LOOP {
-		iam (LongSound);
-		autoTextGrid thee = TextGrid_create (my xmin, my xmax, GET_STRING (U"Tier names"), GET_STRING (U"Point tiers"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (LongSound_view) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a LongSound from batch.");
-	LOOP {
-		iam (LongSound);
-		autoSoundEditor editor = SoundEditor_create (ID_AND_FULL_NAME, me);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeToAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_writeToAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_writeToNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_writeToNistFile, U"Save as NIST file", nullptr, U"nist") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NIST, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_writeToFlacFile, U"Save as FLAC file", nullptr, U"flac") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_writeToWavFile, U"Save as WAV file", nullptr, U"wav") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_WAV, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_writeLeftChannelToAifcFile, U"Save left channel as AIFC file", nullptr, U"aifc") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_AIFC, 0, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeLeftChannelToAiffFile, U"Save left channel as AIFF file", nullptr, U"aiff") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_AIFF, 0, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeLeftChannelToNextSunFile, U"Save left channel as NeXT/Sun file", nullptr, U"au") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_NEXT_SUN, 0, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeLeftChannelToNistFile, U"Save left channel as NIST file", nullptr, U"nist") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_NIST, 0, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeLeftChannelToFlacFile, U"Save left channel as FLAC file", nullptr, U"flac") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_FLAC, 0, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeLeftChannelToWavFile, U"Save left channel as WAV file", nullptr, U"wav") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_WAV, 0, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeRightChannelToAifcFile, U"Save right channel as AIFC file", nullptr, U"aifc") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_AIFC, 1, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeRightChannelToAiffFile, U"Save right channel as AIFF file", nullptr, U"aiff") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_AIFF, 1, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeRightChannelToNextSunFile, U"Save right channel as NeXT/Sun file", nullptr, U"au") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_NEXT_SUN, 1, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeRightChannelToNistFile, U"Save right channel as NIST file", nullptr, U"nist") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_NIST, 1, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeRightChannelToFlacFile, U"Save right channel as FLAC file", 0, U"flac") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_FLAC, 1, file);
-	}
-END2 }
-
-FORM_WRITE2 (LongSound_writeRightChannelToWavFile, U"Save right channel as WAV file", 0, U"wav") {
-	LOOP {
-		iam (LongSound);
-		LongSound_writeChannelToAudioFile (me, Melder_WAV, 1, file);
-	}
-END2 }
-
-FORM (LongSoundPrefs, U"LongSound preferences", U"LongSound") {
-	LABEL (U"", U"This setting determines the maximum number of seconds")
-	LABEL (U"", U"for viewing the waveform and playing a sound in the LongSound window.")
-	LABEL (U"", U"The LongSound window can become very slow if you set it too high.")
-	NATURAL (U"Maximum viewable part (seconds)", U"60")
-	LABEL (U"", U"Note: this setting works for the next long sound file that you open,")
-	LABEL (U"", U"not for currently existing LongSound objects.")
-	OK2
-SET_INTEGER (U"Maximum viewable part", LongSound_getBufferSizePref_seconds ())
-DO
-	LongSound_setBufferSizePref_seconds (GET_INTEGER (U"Maximum viewable part"));
-END2 }
-
-/********** LONGSOUND & SOUND **********/
-
-FORM_WRITE2 (LongSound_Sound_writeToAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_Sound_writeToAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_Sound_writeToNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_Sound_writeToNistFile, U"Save as NIST file", nullptr, U"nist") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NIST, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_Sound_writeToFlacFile, U"Save as FLAC file", nullptr, U"flac") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
-END2 }
-
-FORM_WRITE2 (LongSound_Sound_writeToWavFile, U"Save as WAV file", nullptr, U"wav") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_WAV, 16);
-END2 }
-
-/********** SOUND **********/
-
-FORM (Sound_add, U"Sound: Add", nullptr) {
-	LABEL (U"", U"The following number will be added to the amplitudes of ")
-	LABEL (U"", U"all samples of the sound.")
-	REAL (U"Number", U"0.1")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Vector_addScalar (me, GET_REAL (U"Number"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_autoCorrelate, U"Sound: autocorrelate", U"Sound: Autocorrelate...") {
-	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
-	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
- 	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_autoCorrelate (me,
-			GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-			GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-		praat_new (thee.move(), U"ac_", my name);
-	}
-END2 }
-
-DIRECT2 (Sounds_combineToStereo) {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound result = Sounds_combineToStereo (& list);
-	long numberOfChannels = result -> ny;   // dereference before transferring
-	praat_new (result.move(), U"combined_", numberOfChannels);
-END2 }
-
-DIRECT2 (Sounds_concatenate) {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam_LOOP (Sound);
-		list.addItem_ref (me);
-	}
-	autoSound result = Sounds_concatenate (list, 0.0);
-	praat_new (result.move(), U"chain");
-END2 }
-
-FORM (Sounds_concatenateWithOverlap, U"Sounds: Concatenate with overlap", U"Sounds: Concatenate with overlap...") {
-	POSITIVE (U"Overlap (s)", U"0.01")
-	OK2
-DO
-	OrderedOf<structSound> list;
-	LOOP {
-		iam_LOOP (Sound);
-		list.addItem_ref (me);
-	}
-	autoSound result = Sounds_concatenate (list, GET_REAL (U"Overlap"));
-	praat_new (result.move(), U"chain");
-END2 }
-
-DIRECT2 (Sounds_concatenateRecoverably) {
-	long numberOfChannels = 0, nx = 0, iinterval = 0;
-	double dx = 0.0, tmin = 0.0;
-	LOOP {
-		iam (Sound);
-		if (numberOfChannels == 0) {
-			numberOfChannels = my ny;
-		} else if (my ny != numberOfChannels) {
-			Melder_throw (U"To concatenate sounds, their numbers of channels (mono, stereo) must be equal.");
-		}
-		if (dx == 0.0) {
-			dx = my dx;
-		} else if (my dx != dx) {
-			Melder_throw (U"To concatenate sounds, their sampling frequencies must be equal.\n"
-				"You could resample one or more of the sounds before concatenating.");
-		}
-		nx += my nx;
-	}
-	autoSound thee = Sound_create (numberOfChannels, 0.0, nx * dx, nx, dx, 0.5 * dx);
-	autoTextGrid him = TextGrid_create (0.0, nx * dx, U"labels", U"");
-	nx = 0;
-	LOOP {
-		iam (Sound);
-		double tmax = tmin + my nx * dx;
-		for (long channel = 1; channel <= numberOfChannels; channel ++) {
-			NUMvector_copyElements (my z [channel], thy z [channel] + nx, 1, my nx);
-		}
-		iinterval ++;
-		if (iinterval > 1) {
-			TextGrid_insertBoundary (him.get(), 1, tmin);
-		}
-		TextGrid_setIntervalText (him.get(), 1, iinterval, my name);
-		nx += my nx;
-		tmin = tmax;
-	}
-	praat_new (thee.move(), U"chain");
-	praat_new (him.move(), U"chain");
-END2 }
-
-DIRECT2 (Sound_convertToMono) {
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_convertToMono (me);
-		praat_new (thee.move(), my name, U"_mono");
-	}
-END2 }
-
-DIRECT2 (Sound_convertToStereo) {
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_convertToStereo (me);
-		praat_new (thee.move(), my name, U"_stereo");
-	}
-END2 }
-
-DIRECT2 (Sounds_convolve_old) {
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		( s1 ? s2 : s1 ) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoSound thee = Sounds_convolve (s1, s2, kSounds_convolve_scaling_SUM, kSounds_convolve_signalOutsideTimeDomain_ZERO);
-	praat_new (thee.move(), s1 -> name, U"_", s2 -> name);
-END2 }
-
-FORM (Sounds_convolve, U"Sounds: Convolve", U"Sounds: Convolve...") {
-	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
-	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
-	OK2
-DO
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		( s1 ? s2 : s1 ) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoSound thee = Sounds_convolve (s1, s2,
-		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-	praat_new (thee.move(), s1 -> name, U"_", s2 -> name);
-END2 }
-
-static void common_Sound_create (UiForm dia, Interpreter interpreter, bool allowMultipleChannels) {
-	long numberOfChannels = allowMultipleChannels ? GET_INTEGER (U"Number of channels") : 1;
-	double startTime = GET_REAL (U"Start time");
-	double endTime = GET_REAL (U"End time");
-	double samplingFrequency = GET_REAL (U"Sampling frequency");
-	double numberOfSamples_real = round ((endTime - startTime) * samplingFrequency);
-	if (endTime <= startTime) {
-		if (endTime == startTime)
-			Melder_appendError (U"A Sound cannot have a duration of zero.");
-		else
-			Melder_appendError (U"A Sound cannot have a duration less than zero.");
-		if (startTime == 0.0)
-			Melder_throw (U"Please set the end time to something greater than 0 seconds.");
-		else
-			Melder_throw (U"Please lower the start time or raise the end time.");
-	}
-	if (samplingFrequency <= 0.0) {
-		Melder_appendError (U"A Sound cannot have a negative sampling frequency.");
-		Melder_throw (U"Please set the sampling frequency to something greater than zero, e.g. 44100 Hz.");
-	}
-	if (numberOfChannels < 1)
-		Melder_throw (U"A Sound cannot have zero channels.");
-	if (numberOfSamples_real < 1.0) {
-		Melder_appendError (U"A Sound cannot have zero samples.");
-		if (startTime == 0.0)
-			Melder_throw (U"Please raise the end time.");
-		else
-			Melder_throw (U"Please lower the start time or raise the end time.");
-	}
-	if (numberOfSamples_real > INT54_MAX) {
-		Melder_appendError (U"A Sound cannot have ", numberOfSamples_real, U" samples; the maximum is ",
-			Melder_bigInteger (INT54_MAX), U" samples (or less, depending on your computer's memory).");
-		if (startTime == 0.0)
-			Melder_throw (U"Please lower the end time or the sampling frequency.");
-		else
-			Melder_throw (U"Please raise the start time, lower the end time, or lower the sampling frequency.");
-	}
-	int64 numberOfSamples = (int64) numberOfSamples_real;
-	autoSound sound;
-	try {
-		sound = Sound_create (numberOfChannels, startTime, endTime, numberOfSamples, 1.0 / samplingFrequency,
-			startTime + 0.5 * (endTime - startTime - (numberOfSamples - 1) / samplingFrequency));
-	} catch (MelderError) {
-		if (str32str (Melder_getError (), U"memory")) {
-			Melder_clearError ();
-			Melder_appendError (U"There is not enough memory to create a Sound that contains ", Melder_bigInteger (numberOfSamples), U" samples.");
-			if (startTime == 0.0)
-				Melder_throw (U"You could lower the end time or the sampling frequency and try again.");
-			else
-				Melder_throw (U"You could raise the start time or lower the end time or the sampling frequency, and try again.");
-		} else {
-			throw;   // unexpected error; wait for generic message
-		}
-	}
-	Matrix_formula (sound.get(), GET_STRING (U"formula"), interpreter, nullptr);
-	praat_new (sound.move(), GET_STRING (U"Name"));
-	//praat_updateSelection ();
-}
-
-FORM (Sound_create, U"Create mono Sound", U"Create Sound from formula...") {
-	WORD (U"Name", U"sineWithNoise")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	REAL (U"Sampling frequency (Hz)", U"44100")
-	LABEL (U"", U"Formula:")
-	TEXTFIELD (U"formula", U"1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)")
-	OK2
-DO
-	common_Sound_create (dia, interpreter, false);
-END2 }
-
-FORM (Sound_createFromFormula, U"Create Sound from formula", U"Create Sound from formula...") {
-	WORD (U"Name", U"sineWithNoise")
-	CHANNEL (U"Number of channels", U"1 (= mono)")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	REAL (U"Sampling frequency (Hz)", U"44100")
-	LABEL (U"", U"Formula:")
-	TEXTFIELD (U"formula", U"1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)")
-	OK2
-DO
-	common_Sound_create (dia, interpreter, true);
-END2 }
-
-FORM (Sound_createAsPureTone, U"Create Sound as pure tone", U"Create Sound as pure tone...") {
-	WORD (U"Name", U"tone")
-	CHANNEL (U"Number of channels", U"1 (= mono)")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"0.4")
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	POSITIVE (U"Tone frequency (Hz)", U"440.0")
-	POSITIVE (U"Amplitude (Pa)", U"0.2")
-	POSITIVE (U"Fade-in duration (s)", U"0.01")
-	POSITIVE (U"Fade-out duration (s)", U"0.01")
-	OK2
-DO
-	autoSound me = Sound_createAsPureTone (GET_INTEGER (U"Number of channels"), GET_REAL (U"Start time"), GET_REAL (U"End time"),
-		GET_REAL (U"Sampling frequency"), GET_REAL (U"Tone frequency"), GET_REAL (U"Amplitude"),
-		GET_REAL (U"Fade-in duration"), GET_REAL (U"Fade-out duration"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Sound_createFromToneComplex, U"Create Sound from tone complex", U"Create Sound from tone complex...") {
-	WORD (U"Name", U"toneComplex")
-	REAL (U"Start time (s)", U"0.0")
-	REAL (U"End time (s)", U"1.0")
-	POSITIVE (U"Sampling frequency (Hz)", U"44100.0")
-	RADIO (U"Phase", 2)
-		RADIOBUTTON (U"Sine")
-		RADIOBUTTON (U"Cosine")
-	POSITIVE (U"Frequency step (Hz)", U"100.0")
-	REAL (U"First frequency (Hz)", U"0.0 (= frequency step)")
-	REAL (U"Ceiling (Hz)", U"0.0 (= Nyquist)")
-	INTEGER (U"Number of components", U"0 (= maximum)")
-	OK2
-DO
-	autoSound me = Sound_createFromToneComplex (GET_REAL (U"Start time"), GET_REAL (U"End time"),
-		GET_REAL (U"Sampling frequency"), GET_INTEGER (U"Phase") - 1, GET_REAL (U"Frequency step"),
-		GET_REAL (U"First frequency"), GET_REAL (U"Ceiling"), GET_INTEGER (U"Number of components"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (old_Sounds_crossCorrelate, U"Cross-correlate (short)", nullptr) {
-	REAL (U"From lag (s)", U"-0.1")
-	REAL (U"To lag (s)", U"0.1")
-	BOOLEAN (U"Normalize", true)
-	OK2
-DO
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		( s1 ? s2 : s1 ) = me;
-	}
-	autoSound thee = Sounds_crossCorrelate_short (s1, s2, GET_REAL (U"From lag"), GET_REAL (U"To lag"), GET_INTEGER (U"Normalize"));
-	praat_new (thee.move(), U"cc_", s1 -> name, U"_", s2 -> name);
-END2 }
-
-FORM (Sounds_crossCorrelate, U"Sounds: Cross-correlate", U"Sounds: Cross-correlate...") {
-	RADIO_ENUM (U"Amplitude scaling", kSounds_convolve_scaling, DEFAULT)
-	RADIO_ENUM (U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain, DEFAULT)
-	OK2
-DO_ALTERNATIVE (old_Sounds_crossCorrelate)
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		( s1 ? s2 : s1 ) = me;
-	}
-	Melder_assert (s1 && s2);
-	autoSound thee = Sounds_crossCorrelate (s1, s2,
-		GET_ENUM (kSounds_convolve_scaling, U"Amplitude scaling"),
-		GET_ENUM (kSounds_convolve_signalOutsideTimeDomain, U"Signal outside time domain is..."));
-	praat_new (thee.move(), s1 -> name, U"_", s2 -> name);
-END2 }
-
-FORM (Sound_deemphasizeInline, U"Sound: De-emphasize (in-line)", U"Sound: De-emphasize (in-line)...") {
-	REAL (U"From frequency (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_deEmphasis (me, GET_REAL (U"From frequency"));
-		Vector_scale (me, 0.99);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_deepenBandModulation, U"Deepen band modulation", U"Sound: Deepen band modulation...") {
-	POSITIVE (U"Enhancement (dB)", U"20")
-	POSITIVE (U"From frequency (Hz)", U"300")
-	POSITIVE (U"To frequency (Hz)", U"8000")
-	POSITIVE (U"Slow modulation (Hz)", U"3")
-	POSITIVE (U"Fast modulation (Hz)", U"30")
-	POSITIVE (U"Band smoothing (Hz)", U"100")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_deepenBandModulation (me, GET_REAL (U"Enhancement"),
-			GET_REAL (U"From frequency"), GET_REAL (U"To frequency"),
-			GET_REAL (U"Slow modulation"), GET_REAL (U"Fast modulation"), GET_REAL (U"Band smoothing"));
-		praat_new (thee.move(), my name, U"_", (long) (GET_REAL (U"Enhancement")));   // truncate number toward zero for visual effect
-	}
-END2 }
-
-FORM (old_Sound_draw, U"Sound: Draw", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range", U"0.0 (= all)")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Sound);
-		Sound_draw (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"), U"curve");
-	}
-END2 }
-
-FORM (Sound_draw, U"Sound: Draw", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range", U"0.0 (= all)")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	BOOLEAN (U"Garnish", true)
-	LABEL (U"", U"")
-	OPTIONMENU (U"Drawing method", 1)
-		OPTION (U"Curve")
-		OPTION (U"Bars")
-		OPTION (U"Poles")
-		OPTION (U"Speckles")
-	OK2
-DO_ALTERNATIVE (old_Sound_draw)
-	autoPraatPicture picture;
-	LOOP {
-		iam (Sound);
-		Sound_draw (me, GRAPHICS, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"), GET_INTEGER (U"Garnish"), GET_STRING (U"Drawing method"));
-	}
-END2 }
-
-static void cb_SoundEditor_publication (Editor /* me */, autoDaata publication) {
-	/*
-	 * Keep the gate for error handling.
-	 */
-	try {
-		bool isaSpectrum = Thing_isa (publication.get(), classSpectrum);
-		praat_new (publication.move(), U"");
-		praat_updateSelection ();
-		if (isaSpectrum) {
-			int IOBJECT;
-			LOOP {
-				iam (Spectrum);
-				autoSpectrumEditor editor2 = SpectrumEditor_create (ID_AND_FULL_NAME, me);
-				praat_installEditor (editor2.get(), IOBJECT);
-				editor2.releaseToUser();
-			}
-		}
-	} catch (MelderError) {
-		Melder_flushError ();
-	}
-}
-DIRECT2 (Sound_edit) {
-	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a Sound from batch.");
-	LOOP {
-		iam (Sound);
-		autoSoundEditor editor = SoundEditor_create (ID_AND_FULL_NAME, me);
-		Editor_setPublicationCallback (editor.get(), cb_SoundEditor_publication);
-		praat_installEditor (editor.get(), IOBJECT);
-		editor.releaseToUser();
-	}
-END2 }
-
-DIRECT2 (Sound_extractAllChannels) {
-	LOOP {
-		iam (Sound);
-		for (long channel = 1; channel <= my ny; channel ++) {
-			autoSound thee = Sound_extractChannel (me, channel);
-			praat_new (thee.move(), my name, U"_ch", channel);
-		}
-	}
-END2 }
-
-FORM (Sound_extractChannel, U"Sound: Extract channel", nullptr) {
-	CHANNEL (U"Channel (number, Left, or Right)", U"1")
-	OK2
-DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_extractChannel (me, channel);
-		praat_new (thee.move(), my name, U"_ch", channel);
-	}
-END2 }
-
-DIRECT2 (Sound_extractLeftChannel) {
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_extractChannel (me, 1);
-		praat_new (thee.move(), my name, U"_left");
-	}
-END2 }
-
-FORM (Sound_extractPart, U"Sound: Extract part", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.1")
-	OPTIONMENU_ENUM (U"Window shape", kSound_windowShape, DEFAULT)
-	POSITIVE (U"Relative width", U"1.0")
-	BOOLEAN (U"Preserve times", false)
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_extractPart (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_ENUM (kSound_windowShape, U"Window shape"), GET_REAL (U"Relative width"),
-			GET_INTEGER (U"Preserve times"));
-		praat_new (thee.move(), my name, U"_part");
-	}
-END2 }
-
-FORM (Sound_extractPartForOverlap, U"Sound: Extract part for overlap", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.1")
-	POSITIVE (U"Overlap (s)", U"0.01")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_extractPartForOverlap (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"),
-			GET_REAL (U"Overlap"));
-		praat_new (thee.move(), my name, U"_part");
-	}
-END2 }
-
-DIRECT2 (Sound_extractRightChannel) {
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_extractChannel (me, 2);
-		praat_new (thee.move(), my name, U"_right");
-	}
-END2 }
-
-FORM (Sound_filter_deemphasis, U"Sound: Filter (de-emphasis)", U"Sound: Filter (de-emphasis)...") {
-	REAL (U"From frequency (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filter_deemphasis (me, GET_REAL (U"From frequency"));
-		praat_new (thee.move(), my name, U"_deemp");
-	}
-END2 }
-
-FORM (Sound_filter_formula, U"Sound: Filter (formula)...", U"Formula...") {
-	LABEL (U"", U"Frequency-domain filtering with a formula (uses Sound-to-Spectrum and Spectrum-to-Sound): x is frequency in hertz")
-	TEXTFIELD (U"formula", U"if x<500 or x>1000 then 0 else self fi; rectangular band filter")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filter_formula (me, GET_STRING (U"formula"), interpreter);
-		praat_new (thee.move(), my name, U"_filt");
-	}
-END2 }
-
-FORM (Sound_filter_oneFormant, U"Sound: Filter (one formant)", U"Sound: Filter (one formant)...") {
-	REAL (U"Frequency (Hz)", U"1000.0")
-	POSITIVE (U"Bandwidth (Hz)", U"100.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filter_oneFormant (me, GET_REAL (U"Frequency"), GET_REAL (U"Bandwidth"));
-		praat_new (thee.move(), my name, U"_filt");
-	}
-END2 }
-
-FORM (Sound_filterWithOneFormantInline, U"Sound: Filter with one formant (in-line)", U"Sound: Filter with one formant (in-line)...") {
-	REAL (U"Frequency (Hz)", U"1000.0")
-	POSITIVE (U"Bandwidth (Hz)", U"100.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_filterWithOneFormantInline (me, GET_REAL (U"Frequency"), GET_REAL (U"Bandwidth"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_filter_passHannBand, U"Sound: Filter (pass Hann band)", U"Sound: Filter (pass Hann band)...") {
-	REAL (U"From frequency (Hz)", U"500.0")
-	REAL (U"To frequency (Hz)", U"1000.0")
-	POSITIVE (U"Smoothing (Hz)", U"100.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filter_passHannBand (me,
-			GET_REAL (U"From frequency"), GET_REAL (U"To frequency"), GET_REAL (U"Smoothing"));
-		praat_new (thee.move(), my name, U"_band");
-	}
-END2 }
-
-FORM (Sound_filter_preemphasis, U"Sound: Filter (pre-emphasis)", U"Sound: Filter (pre-emphasis)...") {
-	REAL (U"From frequency (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filter_preemphasis (me, GET_REAL (U"From frequency"));
-		praat_new (thee.move(), my name, U"_preemp");
-	}
-END2 }
-
-FORM (Sound_filter_stopHannBand, U"Sound: Filter (stop Hann band)", U"Sound: Filter (stop Hann band)...") {
-	REAL (U"From frequency (Hz)", U"500.0")
-	REAL (U"To frequency (Hz)", U"1000.0")
-	POSITIVE (U"Smoothing (Hz)", U"100.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_filter_stopHannBand (me, GET_REAL (U"From frequency"), GET_REAL (U"To frequency"), GET_REAL (U"Smoothing"));
-		praat_new (thee.move(), my name, U"_band");
-	}
-END2 }
-
-FORM (Sound_formula, U"Sound: Formula", U"Sound: Formula...") {
-	LABEL (U"label1", U"! `x' is the time in seconds, `col' is the sample number.")
-	LABEL (U"label2", U"x = x1   ! time associated with first sample")
-	LABEL (U"label3", U"for col from 1 to ncol")
-	LABEL (U"label4", U"   self [col] = ...")
-	TEXTFIELD (U"formula", U"self")
-	LABEL (U"label5", U"   x = x + dx")
-	LABEL (U"label6", U"endfor")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		try {
-			Matrix_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Sound may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (Sound_formula_part, U"Sound: Formula (part)", U"Sound: Formula...") {
-	REAL (U"From time", U"0.0")
-	REAL (U"To time", U"0.0 (= all)")
-	NATURAL (U"From channel", U"1")
-	NATURAL (U"To channel", U"2")
-	TEXTFIELD (U"formula", U"2 * self")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		try {
-			Matrix_formula_part (me,
-				GET_REAL (U"From time"), GET_REAL (U"To time"),
-				GET_INTEGER (U"From channel") - 0.5, GET_INTEGER (U"To channel") + 0.5,
-				GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Sound may have partially changed
-			throw;
-		}
-	}
-END2 }
-
-FORM (Sound_getAbsoluteExtremum, U"Sound: Get absolute extremum", U"Sound: Get absolute extremum...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double absoluteExtremum = Vector_getAbsoluteExtremum (me,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (absoluteExtremum, U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getEnergy, U"Sound: Get energy", U"Sound: Get energy...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double energy = Sound_getEnergy (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (energy, U"Pa2 sec");
-	}
-END2 }
-
-DIRECT2 (Sound_getEnergyInAir) {
-	LOOP {
-		iam (Sound);
-		double energyInAir = Sound_getEnergyInAir (me);
-		Melder_informationReal (energyInAir, U"Joule/m2");
-	}
-END2 }
-
-FORM (Sound_getIndexFromTime, U"Get sample number from time", U"Get sample number from time...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double realIndex = Sampled_xToIndex (me, GET_REAL (U"Time"));
-		Melder_informationReal (realIndex, nullptr);
-	}
-END2 }
-
-DIRECT2 (Sound_getIntensity_dB) {
-	LOOP {
-		iam (Sound);
-		double intensity = Sound_getIntensity_dB (me);
-		Melder_informationReal (intensity, U"dB");
-	}
-END2 }
-
-FORM (Sound_getMaximum, U"Sound: Get maximum", U"Sound: Get maximum...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double maximum = Vector_getMaximum (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (maximum, U"Pascal");
-	}
-END2 }
-
-FORM (old_Sound_getMean, U"Sound: Get mean", U"Sound: Get mean...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double mean = Vector_getMean (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), Vector_CHANNEL_AVERAGE);
-		Melder_informationReal (mean, U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getMean, U"Sound: Get mean", U"Sound: Get mean...") {
-	CHANNEL (U"Channel", U"0 (= all)")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO_ALTERNATIVE (old_Sound_getMean)
-	LOOP {
-		iam (Sound);
-		long channel = GET_INTEGER (U"Channel");
-		if (channel > my ny) channel = 1;
-		double mean = Vector_getMean (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channel);
-		Melder_informationReal (mean, U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getMinimum, U"Sound: Get minimum", U"Sound: Get minimum...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double minimum = Vector_getMinimum (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (minimum, U"Pascal");
-	}
-END2 }
-
-FORM (old_Sound_getNearestZeroCrossing, U"Sound: Get nearest zero crossing", U"Sound: Get nearest zero crossing...") {
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		if (my ny > 1) Melder_throw (U"Cannot determine a zero crossing for a stereo sound.");
-		double zeroCrossing = Sound_getNearestZeroCrossing (me, GET_REAL (U"Time"), 1);
-		Melder_informationReal (zeroCrossing, U"seconds");
-	}
-END2 }
-
-FORM (Sound_getNearestZeroCrossing, U"Sound: Get nearest zero crossing", U"Sound: Get nearest zero crossing...") {
-	CHANNEL (U"Channel (number, Left, or Right)", U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO_ALTERNATIVE (old_Sound_getNearestZeroCrossing)
-	LOOP {
-		iam (Sound);
-		long channel = GET_INTEGER (U"Channel");
-		if (channel > my ny) channel = 1;
-		double zeroCrossing = Sound_getNearestZeroCrossing (me, GET_REAL (U"Time"), channel);
-		Melder_informationReal (zeroCrossing, U"seconds");
-	}
-END2 }
-
-DIRECT2 (Sound_getNumberOfChannels) {
-	LOOP {
-		iam (Sound);
-		long numberOfChannels = my ny;
-		Melder_information (numberOfChannels, numberOfChannels == 1 ? U" channel (mono)" : numberOfChannels == 2 ? U" channels (stereo)" : U"channels");
-	}
-END2 }
-
-DIRECT2 (Sound_getNumberOfSamples) {
-	LOOP {
-		iam (Sound);
-		long numberOfSamples = my nx;
-		Melder_information (numberOfSamples, U" samples");
-	}
-END2 }
-
-FORM (Sound_getPower, U"Sound: Get power", U"Sound: Get power...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double power = Sound_getPower (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (power, U"Pa2");
-	}
-END2 }
-
-DIRECT2 (Sound_getPowerInAir) {
-	LOOP {
-		iam (Sound);
-		double powerInAir = Sound_getPowerInAir (me);
-		Melder_informationReal (powerInAir, U"Watt/m2");
-	}
-END2 }
-
-FORM (Sound_getRootMeanSquare, U"Sound: Get root-mean-square", U"Sound: Get root-mean-square...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double rootMeanSquare = Sound_getRootMeanSquare (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"));
-		Melder_informationReal (rootMeanSquare, U"Pascal");
-	}
-END2 }
-
-DIRECT2 (Sound_getSamplePeriod) {
-	LOOP {
-		iam (Sound);
-		double samplePeriod = my dx;
-		Melder_informationReal (samplePeriod, U"seconds");
-	}
-END2 }
-
-DIRECT2 (Sound_getSampleRate) {
-	LOOP {
-		iam (Sound);
-		double samplingFrequency = 1.0 / my dx;
-		Melder_informationReal (samplingFrequency, U"Hz");
-	}
-END2 }
-
-FORM (old_Sound_getStandardDeviation, U"Sound: Get standard deviation", U"Sound: Get standard deviation...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double stdev = Vector_getStandardDeviation (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), Vector_CHANNEL_AVERAGE);
-		Melder_informationReal (stdev, U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getStandardDeviation, U"Sound: Get standard deviation", U"Sound: Get standard deviation...") {
-	CHANNEL (U"Channel", U"0 (= average)")
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	OK2
-DO_ALTERNATIVE (old_Sound_getStandardDeviation)
-	LOOP {
-		iam (Sound);
-		long channel = GET_INTEGER (U"Channel");
-		if (channel > my ny) channel = 1;
-		double stdev = Vector_getStandardDeviation (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), channel);
-		Melder_informationReal (stdev, U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getTimeFromIndex, U"Get time from sample number", U"Get time from sample number...") {
-	INTEGER (U"Sample number", U"100")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double time = Sampled_indexToX (me, GET_INTEGER (U"Sample number"));
-		Melder_informationReal (time, U"seconds");
-	}
-END2 }
-
-FORM (Sound_getTimeOfMaximum, U"Sound: Get time of maximum", U"Sound: Get time of maximum...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double time = Vector_getXOfMaximum (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (time, U"seconds");
-	}
-END2 }
-
-FORM (Sound_getTimeOfMinimum, U"Sound: Get time of minimum", U"Sound: Get time of minimum...") {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double time = Vector_getXOfMinimum (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (time, U"seconds");
-	}
-END2 }
-
-FORM (old_Sound_getValueAtIndex, U"Sound: Get value at sample number", U"Sound: Get value at sample number...") {
-	INTEGER (U"Sample number", U"100")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		long sampleIndex = GET_INTEGER (U"Sample number");
-		Melder_informationReal (sampleIndex < 1 || sampleIndex > my nx ? NUMundefined :
-			my ny == 1 ? my z [1] [sampleIndex] : 0.5 * (my z [1] [sampleIndex] + my z [2] [sampleIndex]), U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getValueAtIndex, U"Sound: Get value at sample number", U"Sound: Get value at sample number...") {
-	CHANNEL (U"Channel", U"0 (= average)")
-	INTEGER (U"Sample number", U"100")
-	OK2
-DO_ALTERNATIVE (old_Sound_getValueAtIndex)
-	LOOP {
-		iam (Sound);
-		long sampleIndex = GET_INTEGER (U"Sample number");
-		long channel = GET_INTEGER (U"Channel");
-		if (channel > my ny) channel = 1;
-		Melder_informationReal (sampleIndex < 1 || sampleIndex > my nx ? NUMundefined :
-			Sampled_getValueAtSample (me, sampleIndex, channel, 0), U"Pascal");
-	}
-END2 }
-
-FORM (old_Sound_getValueAtTime, U"Sound: Get value at time", U"Sound: Get value at time...") {
-	REAL (U"Time (s)", U"0.5")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"Nearest")
-		RADIOBUTTON (U"Linear")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		double value = Vector_getValueAtX (me, GET_REAL (U"Time"), Vector_CHANNEL_AVERAGE, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (value, U"Pascal");
-	}
-END2 }
-
-FORM (Sound_getValueAtTime, U"Sound: Get value at time", U"Sound: Get value at time...") {
-	CHANNEL (U"Channel", U"0 (= average)")
-	REAL (U"Time (s)", U"0.5")
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"Nearest")
-		RADIOBUTTON (U"Linear")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO_ALTERNATIVE (old_Sound_getValueAtTime)
-	LOOP {
-		iam (Sound);
-		long channel = GET_INTEGER (U"Channel");
-		if (channel > my ny) channel = 1;
-		double value = Vector_getValueAtX (me, GET_REAL (U"Time"), channel, GET_INTEGER (U"Interpolation") - 1);
-		Melder_informationReal (value, U"Pascal");
-	}
-END2 }
-
-DIRECT2 (Sound_help) {
-	Melder_help (U"Sound");
-END2 }
-
-FORM (Sound_lengthen_overlapAdd, U"Sound: Lengthen (overlap-add)", U"Sound: Lengthen (overlap-add)...") {
-	POSITIVE (U"Minimum pitch (Hz)", U"75")
-	POSITIVE (U"Maximum pitch (Hz)", U"600")
-	POSITIVE (U"Factor", U"1.5")
-	OK2
-DO
-	double minimumPitch = GET_REAL (U"Minimum pitch"), maximumPitch = GET_REAL (U"Maximum pitch");
-	double factor = GET_REAL (U"Factor");
-	if (minimumPitch >= maximumPitch) Melder_throw (U"Maximum pitch should be greater than minimum pitch.");
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_lengthen_overlapAdd (me, minimumPitch, maximumPitch, factor);
-		praat_new (thee.move(), my name, U"_", Melder_fixed (factor, 2));
-	}
-END2 }
-
-FORM (Sound_multiply, U"Sound: Multiply", nullptr) {
-	REAL (U"Multiplication factor", U"1.5")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Vector_multiplyByScalar (me, GET_REAL (U"Multiplication factor"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_multiplyByWindow, U"Sound: Multiply by window", nullptr) {
-	OPTIONMENU_ENUM (U"Window shape", kSound_windowShape, HANNING)
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_multiplyByWindow (me, GET_ENUM (kSound_windowShape, U"Window shape"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_overrideSamplingFrequency, U"Sound: Override sampling frequency", nullptr) {
-	POSITIVE (U"New sampling frequency (Hz)", U"16000.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_overrideSamplingFrequency (me, GET_REAL (U"New sampling frequency"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Sound_play) {
-	int n = 0;
-	LOOP {
-		n ++;
-	}
-	if (n == 1 || MelderAudio_getOutputMaximumAsynchronicity () < kMelder_asynchronicityLevel_ASYNCHRONOUS) {
-		LOOP {
-			iam (Sound);
-			Sound_play (me, nullptr, nullptr);
-		}
-	} else {
-		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_INTERRUPTABLE);
-		LOOP {
-			iam (Sound);
-			Sound_play (me, nullptr, nullptr);   // BUG: exception-safe?
-		}
-		MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_ASYNCHRONOUS);
-	}
-END2 }
-
-FORM (Sound_preemphasizeInline, U"Sound: Pre-emphasize (in-line)", U"Sound: Pre-emphasize (in-line)...") {
-	REAL (U"From frequency (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_preEmphasis (me, GET_REAL (U"From frequency"));
-		Vector_scale (me, 0.99);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM_READ2 (Sound_readSeparateChannelsFromSoundFile, U"Read separate channels from sound file", nullptr, true) {
-	autoSound sound = Sound_readFromSoundFile (file);
-	char32 name [300];
-	Melder_sprint (name,300, MelderFile_name (file));
-	char32 *lastPeriod = str32rchr (name, U'.');
-	if (lastPeriod) {
-		*lastPeriod = U'\0';
-	}
-	for (long ichan = 1; ichan <= sound -> ny; ichan ++) {
-		autoSound thee = Sound_extractChannel (sound.get(), ichan);
-		praat_new (thee.move(), name, U"_ch", ichan);
-	}
-END2 }
-
-FORM_READ2 (Sound_readFromRawAlawFile, U"Read Sound from raw Alaw file", nullptr, true) {
-	autoSound me = Sound_readFromRawAlawFile (file);
-	praat_new (me.move(), MelderFile_name (file));
-END2 }
-
-static SoundRecorder theReferenceToTheOnlySoundRecorder;
-static int thePreviousNumberOfChannels;
-
-static void cb_SoundRecorder_destruction (SoundRecorder /* me */) {
-	theReferenceToTheOnlySoundRecorder = nullptr;
-}
-static void cb_SoundRecorder_publication (Editor /* me */, autoDaata publication) {
-	try {
-		praat_new (publication.move());
-	} catch (MelderError) {
-		Melder_flushError ();
-	}
-	praat_updateSelection ();
-}
-static void do_Sound_record (int numberOfChannels) {
-	if (theCurrentPraatApplication -> batch)
-		Melder_throw (U"Cannot record a Sound from batch.");
-	if (theReferenceToTheOnlySoundRecorder && numberOfChannels == thePreviousNumberOfChannels) {
-		Editor_raise (theReferenceToTheOnlySoundRecorder);
-	} else {
-		forget (theReferenceToTheOnlySoundRecorder);
-		autoSoundRecorder recorder = SoundRecorder_create (numberOfChannels);
-		Editor_setDestructionCallback (recorder.get(), cb_SoundRecorder_destruction);
-		Editor_setPublicationCallback (recorder.get(), cb_SoundRecorder_publication);
-		theReferenceToTheOnlySoundRecorder = recorder.get();
-		recorder.releaseToUser();
-		thePreviousNumberOfChannels = numberOfChannels;
-	}
-}
-DIRECT2 (Sound_record_mono) {
-	do_Sound_record (1);
-END2 }
-DIRECT2 (Sound_record_stereo) {
-	do_Sound_record (2);
-END2 }
-
-FORM (Sound_recordFixedTime, U"Record Sound", nullptr) {
-	RADIO (U"Input source", 1)
-		RADIOBUTTON (U"Microphone")
-		RADIOBUTTON (U"Line")
-	REAL (U"Gain (0-1)", U"0.1")
-	REAL (U"Balance (0-1)", U"0.5")
-	RADIO (U"Sampling frequency", 1)
-		#ifdef UNIX
-		RADIOBUTTON (U"8000")
-		#endif
-		#ifndef macintosh
-		RADIOBUTTON (U"11025")
-		#endif
-		#ifdef UNIX
-		RADIOBUTTON (U"16000")
-		#endif
-		#ifndef macintosh
-		RADIOBUTTON (U"22050")
-		#endif
-		#ifdef UNIX
-		RADIOBUTTON (U"32000")
-		#endif
-		RADIOBUTTON (U"44100")
-		RADIOBUTTON (U"48000")
-		RADIOBUTTON (U"96000")
-	POSITIVE (U"Duration (seconds)", U"1.0")
-	OK2
-DO
-	autoSound me = Sound_recordFixedTime (GET_INTEGER (U"Input source"),
-		GET_REAL (U"Gain"), GET_REAL (U"Balance"),
-		Melder_atof (GET_STRING (U"Sampling frequency")), GET_REAL (U"Duration"));
-	praat_new (me.move(), U"untitled");
-END2 }
-
-FORM (Sound_resample, U"Sound: Resample", U"Sound: Resample...") {
-	POSITIVE (U"New sampling frequency (Hz)", U"10000.0")
-	NATURAL (U"Precision (samples)", U"50")
-	OK2
-DO
-	double samplingFrequency = GET_REAL (U"New sampling frequency");
-	LOOP {
-		iam (Sound);
-		autoSound thee = Sound_resample (me, samplingFrequency, GET_INTEGER (U"Precision"));
-		praat_new (thee.move(), my name, U"_", (long) round (samplingFrequency));
-	}
-END2 }
-
-DIRECT2 (Sound_reverse) {
-	LOOP {
-		iam (Sound);
-		Sound_reverse (me, 0.0, 0.0);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAs24BitWavFile, U"Save as 24-bit WAV file", nullptr, U"wav") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_WAV, 24);
-END2 }
-
-FORM_WRITE2 (Sound_saveAs32BitWavFile, U"Save as 32-bit WAV file", nullptr, U"wav") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_WAV, 32);
-END2 }
-
-FORM (Sound_scalePeak, U"Sound: Scale peak", U"Sound: Scale peak...") {
-	POSITIVE (U"New absolute peak", U"0.99")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Vector_scale (me, GET_REAL (U"New absolute peak"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_scaleIntensity, U"Sound: Scale intensity", U"Sound: Scale intensity...") {
-	POSITIVE (U"New average intensity (dB SPL)", U"70.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_scaleIntensity (me, GET_REAL (U"New average intensity"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (old_Sound_setValueAtIndex, U"Sound: Set value at sample number", U"Sound: Set value at sample number...") {
-	NATURAL (U"Sample number", U"100")
-	REAL (U"New value", U"0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		long index = GET_INTEGER (U"Sample number");
-		if (index > my nx)
-			Melder_throw (U"The sample number should not exceed the number of samples, which is ", my nx, U".");
-		for (long channel = 1; channel <= my ny; channel ++)
-			my z [channel] [index] = GET_REAL (U"New value");
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_setValueAtIndex, U"Sound: Set value at sample number", U"Sound: Set value at sample number...") {
-	CHANNEL (U"Channel", U"0 (= all)")
-	NATURAL (U"Sample number", U"100")
-	REAL (U"New value", U"0")
-	OK2
-DO_ALTERNATIVE (old_Sound_setValueAtIndex)
-	LOOP {
-		iam (Sound);
-		long index = GET_INTEGER (U"Sample number");
-		if (index > my nx)
-			Melder_throw (U"The sample number should not exceed the number of samples, which is ", my nx, U".");
-		long channel = GET_INTEGER (U"Channel");
-		if (channel > my ny) channel = 1;
-		if (channel > 0) {
-			my z [channel] [index] = GET_REAL (U"New value");
-		} else {
-			for (channel = 1; channel <= my ny; channel ++) {
-				my z [channel] [index] = GET_REAL (U"New value");
-			}
-		}
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_setPartToZero, U"Sound: Set part to zero", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"0.0 (= all)")
-	RADIO (U"Cut", 2)
-		OPTION (U"at exactly these times")
-		OPTION (U"at nearest zero crossing")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		Sound_setZero (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Cut") - 1);
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Sound_subtractMean) {
-	LOOP {
-		iam (Sound);
-		Vector_subtractMean (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Sound_to_Manipulation, U"Sound: To Manipulation", U"Manipulation") {
-	POSITIVE (U"Time step (s)", U"0.01")
-	POSITIVE (U"Minimum pitch (Hz)", U"75")
-	POSITIVE (U"Maximum pitch (Hz)", U"600")
-	OK2
-DO
-	double fmin = GET_REAL (U"Minimum pitch"), fmax = GET_REAL (U"Maximum pitch");
-	if (fmax <= fmin) Melder_throw (U"Maximum pitch must be greater than minimum pitch.");
-	LOOP {
-		iam (Sound);
-		autoManipulation thee = Sound_to_Manipulation (me, GET_REAL (U"Time step"), fmin, fmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Cochleagram, U"Sound: To Cochleagram", nullptr) {
-	POSITIVE (U"Time step (s)", U"0.01")
-	POSITIVE (U"Frequency resolution (Bark)", U"0.1")
-	POSITIVE (U"Window length (s)", U"0.03")
-	REAL (U"Forward-masking time (s)", U"0.03")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoCochleagram thee = Sound_to_Cochleagram (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Frequency resolution"), GET_REAL (U"Window length"), GET_REAL (U"Forward-masking time"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Cochleagram_edb, U"Sound: To Cochleagram (De Boer, Meddis & Hewitt)", nullptr) {
-	POSITIVE (U"Time step (s)", U"0.01")
-	POSITIVE (U"Frequency resolution (Bark)", U"0.1")
-	BOOLEAN (U"Has synapse", true)
-	LABEL (U"", U"Meddis synapse properties")
-	POSITIVE (U"   replenishment rate (/sec)", U"5.05")
-	POSITIVE (U"   loss rate (/sec)", U"2500.0")
-	POSITIVE (U"   return rate (/sec)", U"6580.0")
-	POSITIVE (U"   reprocessing rate (/sec)", U"66.31")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoCochleagram thee = Sound_to_Cochleagram_edb (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Frequency resolution"), GET_INTEGER (U"Has synapse"),
-			GET_REAL (U"   replenishment rate"), GET_REAL (U"   loss rate"),
-			GET_REAL (U"   return rate"), GET_REAL (U"   reprocessing rate"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Formant_burg, U"Sound: To Formant (Burg method)", U"Sound: To Formant (burg)...") {
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Max. number of formants", U"5.0")
-	REAL (U"Maximum formant (Hz)", U"5500.0 (= adult female)")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoFormant thee = Sound_to_Formant_burg (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Max. number of formants"), GET_REAL (U"Maximum formant"),
-			GET_REAL (U"Window length"), GET_REAL (U"Pre-emphasis from"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Formant_keepAll, U"Sound: To Formant (keep all)", U"Sound: To Formant (keep all)...") {
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Max. number of formants", U"5.0")
-	REAL (U"Maximum formant (Hz)", U"5500.0 (= adult female)")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoFormant thee = Sound_to_Formant_keepAll (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Max. number of formants"), GET_REAL (U"Maximum formant"),
-			GET_REAL (U"Window length"), GET_REAL (U"Pre-emphasis from"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Formant_willems, U"Sound: To Formant (split Levinson (Willems))", U"Sound: To Formant (sl)...") {
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Number of formants", U"5.0")
-	REAL (U"Maximum formant (Hz)", U"5500.0 (= adult female)")
-	POSITIVE (U"Window length (s)", U"0.025")
-	POSITIVE (U"Pre-emphasis from (Hz)", U"50.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoFormant thee = Sound_to_Formant_willems (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Number of formants"), GET_REAL (U"Maximum formant"),
-			GET_REAL (U"Window length"), GET_REAL (U"Pre-emphasis from"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Harmonicity_ac, U"Sound: To Harmonicity (ac)", U"Sound: To Harmonicity (ac)...") {
-	POSITIVE (U"Time step (s)", U"0.01")
-	POSITIVE (U"Minimum pitch (Hz)", U"75.0")
-	REAL (U"Silence threshold", U"0.1")
-	POSITIVE (U"Periods per window", U"4.5")
-	OK2
-DO
-	double periodsPerWindow = GET_REAL (U"Periods per window");
-	if (periodsPerWindow < 3.0) Melder_throw (U"Number of periods per window must be at least 3.0.");
-	LOOP {
-		iam (Sound);
-		autoHarmonicity thee = Sound_to_Harmonicity_ac (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Minimum pitch"), GET_REAL (U"Silence threshold"), periodsPerWindow);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Harmonicity_cc, U"Sound: To Harmonicity (cc)", U"Sound: To Harmonicity (cc)...") {
-	POSITIVE (U"Time step (s)", U"0.01")
-	POSITIVE (U"Minimum pitch (Hz)", U"75.0")
-	REAL (U"Silence threshold", U"0.1")
-	POSITIVE (U"Periods per window", U"1.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoHarmonicity thee = Sound_to_Harmonicity_cc (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Minimum pitch"), GET_REAL (U"Silence threshold"),
-			GET_REAL (U"Periods per window"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Harmonicity_gne, U"Sound: To Harmonicity (gne)", nullptr) {
-	POSITIVE (U"Minimum frequency (Hz)", U"500.0")
-	POSITIVE (U"Maximum frequency (Hz)", U"4500.0")
-	POSITIVE (U"Bandwidth (Hz)", U"1000.0")
-	POSITIVE (U"Step (Hz)", U"80.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoMatrix thee = Sound_to_Harmonicity_GNE (me, GET_REAL (U"Minimum frequency"),
-			GET_REAL (U"Maximum frequency"), GET_REAL (U"Bandwidth"),
-			GET_REAL (U"Step"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (old_Sound_to_Intensity, U"Sound: To Intensity", U"Sound: To Intensity...") {
-	POSITIVE (U"Minimum pitch (Hz)", U"100.0")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoIntensity thee = Sound_to_Intensity (me,
-			GET_REAL (U"Minimum pitch"), GET_REAL (U"Time step"), false);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Intensity, U"Sound: To Intensity", U"Sound: To Intensity...") {
-	POSITIVE (U"Minimum pitch (Hz)", U"100.0")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	BOOLEAN (U"Subtract mean", true)
-	OK2
-DO_ALTERNATIVE (old_Sound_to_Intensity)
-	LOOP {
-		iam (Sound);
-		autoIntensity thee = Sound_to_Intensity (me,
-			GET_REAL (U"Minimum pitch"), GET_REAL (U"Time step"), GET_INTEGER (U"Subtract mean"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_IntensityTier, U"Sound: To IntensityTier", nullptr) {
-	POSITIVE (U"Minimum pitch (Hz)", U"100.0")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	BOOLEAN (U"Subtract mean", true)
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoIntensityTier thee = Sound_to_IntensityTier (me,
-			GET_REAL (U"Minimum pitch"), GET_REAL (U"Time step"), GET_INTEGER (U"Subtract mean"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Sound_to_IntervalTier) {
-	LOOP {
-		iam (Sound);
-		autoIntervalTier thee = IntervalTier_create (my xmin, my xmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Ltas, U"Sound: To long-term average spectrum", nullptr) {
-	POSITIVE (U"Bandwidth (Hz)", U"100")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoLtas thee = Sound_to_Ltas (me, GET_REAL (U"Bandwidth"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Ltas_pitchCorrected, U"Sound: To Ltas (pitch-corrected)", U"Sound: To Ltas (pitch-corrected)...") {
-	POSITIVE (U"Minimum pitch (Hz)", U"75.0")
-	POSITIVE (U"Maximum pitch (Hz)", U"600.0")
-	POSITIVE (U"Maximum frequency (Hz)", U"5000.0")
-	POSITIVE (U"Bandwidth (Hz)", U"100.0")
-	REAL (U"Shortest period (s)", U"0.0001")
-	REAL (U"Longest period (s)", U"0.02")
-	POSITIVE (U"Maximum period factor", U"1.3")
-	OK2
-DO
-	double fmin = GET_REAL (U"Minimum pitch"), fmax = GET_REAL (U"Maximum pitch");
-	if (fmax <= fmin) Melder_throw (U"Maximum pitch must be greater than minimum pitch.");
-	LOOP {
-		iam (Sound);
-		autoLtas thee = Sound_to_Ltas_pitchCorrected (me, fmin, fmax,
-			GET_REAL (U"Maximum frequency"), GET_REAL (U"Bandwidth"),
-			GET_REAL (U"Shortest period"), GET_REAL (U"Longest period"), GET_REAL (U"Maximum period factor"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Sound_to_Matrix) {
-	LOOP {
-		iam (Sound);
-		autoMatrix thee = Sound_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Sounds_to_ParamCurve) {
-	Sound s1 = nullptr, s2 = nullptr;
-	LOOP {
-		iam (Sound);
-		( s1 ? s2 : s1 ) = me;
-	}
-	autoParamCurve thee = ParamCurve_create (s1, s2);
-	praat_new (thee.move(), s1 -> name, U"_", s2 -> name);
-END2 }
-
-FORM (Sound_to_Pitch, U"Sound: To Pitch", U"Sound: To Pitch...") {
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Pitch floor (Hz)", U"75.0")
-	POSITIVE (U"Pitch ceiling (Hz)", U"600.0")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoPitch thee = Sound_to_Pitch (me, GET_REAL (U"Time step"), GET_REAL (U"Pitch floor"), GET_REAL (U"Pitch ceiling"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Pitch_ac, U"Sound: To Pitch (ac)", U"Sound: To Pitch (ac)...") {
-	LABEL (U"", U"Finding the candidates")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Pitch floor (Hz)", U"75.0")
-	NATURAL (U"Max. number of candidates", U"15")
-	BOOLEAN (U"Very accurate", false)
-	LABEL (U"", U"Finding a path")
-	REAL (U"Silence threshold", U"0.03")
-	REAL (U"Voicing threshold", U"0.45")
-	REAL (U"Octave cost", U"0.01")
-	REAL (U"Octave-jump cost", U"0.35")
-	REAL (U"Voiced / unvoiced cost", U"0.14")
-	POSITIVE (U"Pitch ceiling (Hz)", U"600.0")
-	OK2
-DO
-	long maxnCandidates = GET_INTEGER (U"Max. number of candidates");
-	if (maxnCandidates <= 1) Melder_throw (U"Maximum number of candidates must be greater than 1.");
-	LOOP {
-		iam (Sound);
-		autoPitch thee = Sound_to_Pitch_ac (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Pitch floor"), 3.0, maxnCandidates, GET_INTEGER (U"Very accurate"),
-			GET_REAL (U"Silence threshold"), GET_REAL (U"Voicing threshold"),
-			GET_REAL (U"Octave cost"), GET_REAL (U"Octave-jump cost"),
-			GET_REAL (U"Voiced / unvoiced cost"), GET_REAL (U"Pitch ceiling"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Pitch_cc, U"Sound: To Pitch (cc)", U"Sound: To Pitch (cc)...") {
-	LABEL (U"", U"Finding the candidates")
-	REAL (U"Time step (s)", U"0.0 (= auto)")
-	POSITIVE (U"Pitch floor (Hz)", U"75.0")
-	NATURAL (U"Max. number of candidates", U"15")
-	BOOLEAN (U"Very accurate", false)
-	LABEL (U"", U"Finding a path")
-	REAL (U"Silence threshold", U"0.03")
-	REAL (U"Voicing threshold", U"0.45")
-	REAL (U"Octave cost", U"0.01")
-	REAL (U"Octave-jump cost", U"0.35")
-	REAL (U"Voiced / unvoiced cost", U"0.14")
-	POSITIVE (U"Pitch ceiling (Hz)", U"600")
-	OK2
-DO
-	long maxnCandidates = GET_INTEGER (U"Max. number of candidates");
-	if (maxnCandidates <= 1) Melder_throw (U"Maximum number of candidates must be greater than 1.");
-	LOOP {
-		iam (Sound);
-		autoPitch thee = Sound_to_Pitch_cc (me, GET_REAL (U"Time step"),
-			GET_REAL (U"Pitch floor"), 1.0, maxnCandidates, GET_INTEGER (U"Very accurate"),
-			GET_REAL (U"Silence threshold"), GET_REAL (U"Voicing threshold"),
-			GET_REAL (U"Octave cost"), GET_REAL (U"Octave-jump cost"),
-			GET_REAL (U"Voiced / unvoiced cost"), GET_REAL (U"Pitch ceiling"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_PointProcess_extrema, U"Sound: To PointProcess (extrema)", nullptr) {
-	CHANNEL (U"Channel (number, Left, or Right)", U"1")
-	BOOLEAN (U"Include maxima", true)
-	BOOLEAN (U"Include minima", false)
-	RADIO (U"Interpolation", 4)
-		RADIOBUTTON (U"None")
-		RADIOBUTTON (U"Parabolic")
-		RADIOBUTTON (U"Cubic")
-		RADIOBUTTON (U"Sinc70")
-		RADIOBUTTON (U"Sinc700")
-	OK2
-DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (Sound);
-		autoPointProcess thee = Sound_to_PointProcess_extrema (me, channel > my ny ? 1 : channel, GET_INTEGER (U"Interpolation") - 1,
-			GET_INTEGER (U"Include maxima"), GET_INTEGER (U"Include minima"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_PointProcess_periodic_cc, U"Sound: To PointProcess (periodic, cc)", U"Sound: To PointProcess (periodic, cc)...") {
-	POSITIVE (U"Minimum pitch (Hz)", U"75")
-	POSITIVE (U"Maximum pitch (Hz)", U"600")
-	OK2
-DO
-	double fmin = GET_REAL (U"Minimum pitch"), fmax = GET_REAL (U"Maximum pitch");
-	if (fmax <= fmin) Melder_throw (U"Maximum pitch must be greater than minimum pitch.");
-	LOOP {
-		iam (Sound);
-		autoPointProcess thee = Sound_to_PointProcess_periodic_cc (me, fmin, fmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_PointProcess_periodic_peaks, U"Sound: To PointProcess (periodic, peaks)", U"Sound: To PointProcess (periodic, peaks)...") {
-	POSITIVE (U"Minimum pitch (Hz)", U"75")
-	POSITIVE (U"Maximum pitch (Hz)", U"600")
-	BOOLEAN (U"Include maxima", true)
-	BOOLEAN (U"Include minima", false)
-	OK2
-DO
-	double fmin = GET_REAL (U"Minimum pitch"), fmax = GET_REAL (U"Maximum pitch");
-	if (fmax <= fmin) Melder_throw (U"Maximum pitch must be greater than minimum pitch.");
-	LOOP {
-		iam (Sound);
-		autoPointProcess thee = Sound_to_PointProcess_periodic_peaks (me, fmin, fmax, GET_INTEGER (U"Include maxima"), GET_INTEGER (U"Include minima"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_PointProcess_zeroes, U"Get zeroes", nullptr) {
-	CHANNEL (U"Channel (number, Left, or Right)", U"1")
-	BOOLEAN (U"Include raisers", true)
-	BOOLEAN (U"Include fallers", false)
-	OK2
-DO
-	long channel = GET_INTEGER (U"Channel");
-	LOOP {
-		iam (Sound);
-		autoPointProcess thee = Sound_to_PointProcess_zeroes (me, channel > my ny ? 1 : channel, GET_INTEGER (U"Include raisers"), GET_INTEGER (U"Include fallers"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Spectrogram, U"Sound: To Spectrogram", U"Sound: To Spectrogram...") {
-	POSITIVE (U"Window length (s)", U"0.005")
-	POSITIVE (U"Maximum frequency (Hz)", U"5000.0")
-	POSITIVE (U"Time step (s)", U"0.002")
-	POSITIVE (U"Frequency step (Hz)", U"20.0")
-	RADIO_ENUM (U"Window shape", kSound_to_Spectrogram_windowShape, DEFAULT)
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSpectrogram thee = Sound_to_Spectrogram (me, GET_REAL (U"Window length"),
-			GET_REAL (U"Maximum frequency"), GET_REAL (U"Time step"),
-			GET_REAL (U"Frequency step"), GET_ENUM (kSound_to_Spectrogram_windowShape, U"Window shape"), 8.0, 8.0);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_Spectrum, U"Sound: To Spectrum", U"Sound: To Spectrum...") {
-	BOOLEAN (U"Fast", true)
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoSpectrum thee = Sound_to_Spectrum (me, GET_INTEGER (U"Fast"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Sound_to_Spectrum_dft) {
-	LOOP {
-		iam (Sound);
-		autoSpectrum thee = Sound_to_Spectrum (me, false);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Sound_to_Spectrum_fft) {
-	LOOP {
-		iam (Sound);
-		autoSpectrum thee = Sound_to_Spectrum (me, true);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (Sound_to_TextGrid, U"Sound: To TextGrid", U"Sound: To TextGrid...") {
-	SENTENCE (U"All tier names", U"Mary John bell")
-	SENTENCE (U"Which of these are point tiers?", U"bell")
-	OK2
-DO
-	LOOP {
-		iam (Sound);
-		autoTextGrid thee = TextGrid_create (my xmin, my xmax, GET_STRING (U"All tier names"), GET_STRING (U"Which of these are point tiers?"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-DIRECT2 (Sound_to_TextTier) {
-	LOOP {
-		iam (Sound);
-		autoTextTier thee = TextTier_create (my xmin, my xmax);
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM (SoundInputPrefs, U"Sound recording preferences", U"SoundRecorder") {
-	NATURAL (U"Buffer size (MB)", U"60")
-	OPTIONMENU_ENUM (U"Input sound system", kMelder_inputSoundSystem, DEFAULT)
-	OK2
-SET_INTEGER (U"Buffer size", SoundRecorder_getBufferSizePref_MB ())
-SET_ENUM (U"Input sound system", kMelder_inputSoundSystem, MelderAudio_getInputSoundSystem())
-DO
-	long size = GET_INTEGER (U"Buffer size");
-	if (size > 1000) Melder_throw (U"Buffer size cannot exceed 1000 megabytes.");
-	SoundRecorder_setBufferSizePref_MB (size);
-	MelderAudio_setInputSoundSystem (GET_ENUM (kMelder_inputSoundSystem, U"Input sound system"));
-END2 }
-
-FORM (SoundOutputPrefs, U"Sound playing preferences", nullptr) {
-	LABEL (U"", U"The following determines how sounds are played.")
-	LABEL (U"", U"Between parentheses, you find what you can do simultaneously.")
-	LABEL (U"", U"Decrease asynchronicity if sound plays with discontinuities.")
-	OPTIONMENU_ENUM (U"Maximum asynchronicity", kMelder_asynchronicityLevel, DEFAULT)
-	#define xstr(s) str(s)
-	#define str(s) #s
-	REAL (U"Silence before (s)", U"" xstr (kMelderAudio_outputSilenceBefore_DEFAULT))
-	REAL (U"Silence after (s)", U"" xstr (kMelderAudio_outputSilenceAfter_DEFAULT))
-	OPTIONMENU_ENUM (U"Output sound system", kMelder_outputSoundSystem, DEFAULT)
-	OK2
-SET_ENUM (U"Maximum asynchronicity", kMelder_asynchronicityLevel, MelderAudio_getOutputMaximumAsynchronicity ())
-SET_REAL (U"Silence before", MelderAudio_getOutputSilenceBefore ())
-SET_REAL (U"Silence after", MelderAudio_getOutputSilenceAfter ())
-SET_ENUM (U"Output sound system", kMelder_outputSoundSystem, MelderAudio_getOutputSoundSystem())
-DO
-	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
-	MelderAudio_setOutputMaximumAsynchronicity (GET_ENUM (kMelder_asynchronicityLevel, U"Maximum asynchronicity"));
-	MelderAudio_setOutputSilenceBefore (GET_REAL (U"Silence before"));
-	MelderAudio_setOutputSilenceAfter (GET_REAL (U"Silence after"));
-	MelderAudio_setOutputSoundSystem (GET_ENUM (kMelder_outputSoundSystem, U"Output sound system"));
-END2 }
-
-#ifdef HAVE_PULSEAUDIO
-void pulseAudio_serverReport ();
-DIRECT (Praat_reportSoundServerProperties)
-	pulseAudio_serverReport ();
-END
-#endif
-
-FORM_WRITE2 (Sound_writeToAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToFlacFile, U"Save as FLAC file", nullptr, U"flac") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToKayFile, U"Save as Kay sound file", nullptr, U"kay") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToKayFile (me, file);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_writeToNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToNistFile, U"Save as NIST file", nullptr, U"nist") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NIST, 16);
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw8bitSignedFile, U"Save as raw 8-bit signed sound file", nullptr, U"8sig") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_8_SIGNED);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw8bitUnsignedFile, U"Save as raw 8-bit unsigned sound file", nullptr, U"8uns") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_8_UNSIGNED);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw16bitBigEndianFile, U"Save as raw 16-bit big-endian sound file", nullptr, U"16be") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_16_BIG_ENDIAN);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw16bitLittleEndianFile, U"Save as raw 16-bit little-endian sound file", nullptr, U"16le") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_16_LITTLE_ENDIAN);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw24bitBigEndianFile, U"Save as raw 24-bit big-endian sound file", nullptr, U"24be") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_24_BIG_ENDIAN);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw24bitLittleEndianFile, U"Save as raw 24-bit little-endian sound file", nullptr, U"24le") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_24_LITTLE_ENDIAN);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw32bitBigEndianFile, U"Save as raw 32-bit big-endian sound file", nullptr, U"32be") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_32_BIG_ENDIAN);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_saveAsRaw32bitLittleEndianFile, U"Save as raw 32-bit little-endian sound file", nullptr, U"32le") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToRawSoundFile (me, file, Melder_LINEAR_32_LITTLE_ENDIAN);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_writeToSesamFile, U"Save as Sesam file", nullptr, U"sdf") {
-	LOOP {
-		iam (Sound);
-		Sound_writeToSesamFile (me, file);
-	}
-END2 }
-
-FORM_WRITE2 (Sound_writeToStereoAifcFile, U"Save as stereo AIFC file", nullptr, U"aifc") {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound stereo = Sounds_combineToStereo (& list);
-	Sound_writeToAudioFile (stereo.get(), file, Melder_AIFC, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToStereoAiffFile, U"Save as stereo AIFF file", nullptr, U"aiff") {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound stereo = Sounds_combineToStereo (& list);
-	Sound_writeToAudioFile (stereo.get(), file, Melder_AIFF, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToStereoNextSunFile, U"Save as stereo NeXT/Sun file", nullptr, U"au") {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound stereo = Sounds_combineToStereo (& list);
-	Sound_writeToAudioFile (stereo.get(), file, Melder_NEXT_SUN, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToStereoNistFile, U"Save as stereo NIST file", nullptr, U"nist") {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound stereo = Sounds_combineToStereo (& list);
-	Sound_writeToAudioFile (stereo.get(), file, Melder_NIST, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToStereoFlacFile, U"Save as stereo FLAC file", nullptr, U"flac") {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound stereo = Sounds_combineToStereo (& list);
-	Sound_writeToAudioFile (stereo.get(), file, Melder_FLAC, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToStereoWavFile, U"Save as stereo WAV file", nullptr, U"wav") {
-	OrderedOf<structSound> list;
-	LOOP {
-		iam (Sound);
-		list. addItem_ref (me);
-	}
-	autoSound stereo = Sounds_combineToStereo (& list);
-	Sound_writeToAudioFile (stereo.get(), file, Melder_WAV, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToSunAudioFile, U"Save as NeXT/Sun file", nullptr, U"au") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
-END2 }
-
-FORM_WRITE2 (Sound_writeToWavFile, U"Save as WAV file", nullptr, U"wav") {
-	autoSoundAndLongSoundList list = SoundAndLongSoundList_create ();
-	LOOP {
-		iam (Sampled);
-		list -> addItem_ref (me);
-	}
-	LongSound_concatenate (list.get(), file, Melder_WAV, 16);
-END2 }
-
-/***** STOP *****/
-
-DIRECT2 (stopPlayingSound) {
-	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
-END2 }
-
-/***** Help menus *****/
-
-DIRECT2 (AnnotationTutorial) {
-	Melder_help (U"Intro 7. Annotation");
-END2 }
-
-DIRECT2 (FilteringTutorial) {
-	Melder_help (U"Filtering");
-END2 }
-
-/***** file recognizers *****/
-
-static autoDaata macSoundOrEmptyFileRecognizer (int nread, const char * /* header */, MelderFile file) {
-	/***** No data in file? This may be a Macintosh sound file with only a resource fork. *****/
-	if (nread > 0) return autoDaata ();
-	Melder_throw (U"File ", file, U" contains no audio data.");   // !!!
-}
-
-static autoDaata soundFileRecognizer (int nread, const char *header, MelderFile file) {
-	if (nread < 16) return autoDaata ();
-	if (strnequ (header, "FORM", 4) && strnequ (header + 8, "AIF", 3)) return Sound_readFromSoundFile (file);
-	if (strnequ (header, "RIFF", 4) && (strnequ (header + 8, "WAVE", 4) || strnequ (header + 8, "CDDA", 4))) return Sound_readFromSoundFile (file);
-	if (strnequ (header, ".snd", 4)) return Sound_readFromSoundFile (file);
-	if (strnequ (header, "NIST_1A", 7)) return Sound_readFromSoundFile (file);
-	if (strnequ (header, "fLaC", 4)) return Sound_readFromSoundFile (file);   // Erez Volk, March 2007
-	if ((Melder_stringMatchesCriterion (MelderFile_name (file), kMelder_string_ENDS_WITH, U".mp3") ||
-	     Melder_stringMatchesCriterion (MelderFile_name (file), kMelder_string_ENDS_WITH, U".MP3"))
-		&& mp3_recognize (nread, header)) return Sound_readFromSoundFile (file);   // Erez Volk, May 2007
-	return autoDaata ();
-}
-
-static autoDaata movieFileRecognizer (int nread, const char * /* header */, MelderFile file) {
-	const char32 *fileName = MelderFile_name (file);
-	/*Melder_casual ("%d %d %d %d %d %d %d %d %d %d", header [0],
-		header [1], header [2], header [3],
-		header [4], header [5], header [6],
-		header [7], header [8], header [9]);*/
-	if (nread < 512 || (! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".mov") &&
-	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".MOV") &&
-	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".avi") &&
-	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".AVI"))) return autoDaata ();
-	Melder_throw (U"This Praat version cannot open movie files.");
-	return autoDaata ();
-}
-
-static autoDaata sesamFileRecognizer (int nread, const char * /* header */, MelderFile file) {
-	const char32 *fileName = MelderFile_name (file);
-	if (nread < 512 || (! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".sdf") &&
-	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string_ENDS_WITH, U".SDF"))) return autoDaata ();
-	return Sound_readFromSesamFile (file);
-}
-
-static autoDaata bellLabsFileRecognizer (int nread, const char *header, MelderFile file) {
-	if (nread < 16 || ! strnequ (& header [0], "SIG\n", 4)) return autoDaata ();
-	return Sound_readFromBellLabsFile (file);
-}
-
-static autoDaata kayFileRecognizer (int nread, const char *header, MelderFile file) {
-	if (nread <= 12 || ! strnequ (& header [0], "FORMDS16", 8)) return autoDaata ();
-	return Sound_readFromKayFile (file);
-}
-
-/***** override play and record buttons in manuals *****/
-
-static autoSound melderSound, melderSoundFromFile;
-static Sound last;
-static int recordProc (double duration) {
-	if (last == melderSound.get()) last = nullptr;
-	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
-	melderSound = Sound_recordFixedTime (1, 1.0, 0.5, 44100, duration);
-	if (! melderSound) return 0;
-	last = melderSound.get();
-	return 1;
-}
-static int recordFromFileProc (MelderFile file) {
-	if (last == melderSoundFromFile.get()) last = nullptr;
-	Melder_warningOff ();   // like "misssing samples"
-	melderSoundFromFile = Data_readFromFile (file). static_cast_move<structSound>();
-	Melder_warningOn ();
-	if (! melderSoundFromFile) return 0;
-	if (! Thing_isa (melderSoundFromFile.get(), classSound)) { melderSoundFromFile.reset(); return 0; }
-	last = melderSoundFromFile.get();
-	Sound_play (melderSoundFromFile.get(), nullptr, nullptr);
-	return 1;
-}
-static void playProc () {
-	if (melderSound) {
-		Sound_play (melderSound.get(), nullptr, nullptr);
-		last = melderSound.get();
-	}
-}
-static void playReverseProc () {
-	/*if (melderSound) Sound_playReverse (melderSound);*/
-}
-static int publishPlayedProc () {
-	if (! last) return 0;
-	autoSound sound = Data_copy (last);
-	return Data_publish (sound.move());
-}
-
-/***** buttons *****/
-
-void praat_uvafon_Sound_init ();
-void praat_uvafon_Sound_init () {
-
-	Data_recognizeFileType (macSoundOrEmptyFileRecognizer);
-	Data_recognizeFileType (soundFileRecognizer);
-	Data_recognizeFileType (movieFileRecognizer);
-	Data_recognizeFileType (sesamFileRecognizer);
-	Data_recognizeFileType (bellLabsFileRecognizer);
-	Data_recognizeFileType (kayFileRecognizer);
-
-	SoundRecorder_preferences ();
-	structSoundRecorder           :: f_preferences ();
-	structFunctionEditor          :: f_preferences ();
-	LongSound_preferences ();
-	structTimeSoundEditor         :: f_preferences ();
-	structTimeSoundAnalysisEditor :: f_preferences ();
-
-	Melder_setRecordProc (recordProc);
-	Melder_setRecordFromFileProc (recordFromFileProc);
-	Melder_setPlayProc (playProc);
-	Melder_setPlayReverseProc (playReverseProc);
-	Melder_setPublishPlayedProc (publishPlayedProc);
-
-	praat_addMenuCommand (U"Objects", U"New", U"Record mono Sound...", nullptr, praat_ATTRACTIVE + 'R', DO_Sound_record_mono);
-	praat_addMenuCommand (U"Objects", U"New", U"Record stereo Sound...", nullptr, 0, DO_Sound_record_stereo);
-	praat_addMenuCommand (U"Objects", U"New", U"Record Sound (fixed time)...", nullptr, praat_HIDDEN, DO_Sound_recordFixedTime);
-	praat_addMenuCommand (U"Objects", U"New", U"Sound", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Sound...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_create);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Sound as pure tone...", nullptr, 1, DO_Sound_createAsPureTone);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Sound from formula...", nullptr, 1, DO_Sound_createFromFormula);
-		praat_addMenuCommand (U"Objects", U"New", U"-- create sound advanced --", nullptr, 1, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Sound as tone complex...", nullptr, 1, DO_Sound_createFromToneComplex);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Sound from tone complex...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_createFromToneComplex);
-
-	praat_addMenuCommand (U"Objects", U"Open", U"-- read sound --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Open", U"Open long sound file...", nullptr, 'L', DO_LongSound_open);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read two Sounds from stereo file...", nullptr, praat_HIDDEN, DO_Sound_readSeparateChannelsFromSoundFile);   // deprecated 2010
-	praat_addMenuCommand (U"Objects", U"Open", U"Read separate channels from sound file...", nullptr, 0, DO_Sound_readSeparateChannelsFromSoundFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read from special sound file", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw Alaw file...", nullptr, 1, DO_Sound_readFromRawAlawFile);
-
-	praat_addMenuCommand (U"Objects", U"Goodies", U"Stop playing sound", nullptr, GuiMenu_ESCAPE, DO_stopPlayingSound);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"-- sound prefs --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"Sound recording preferences...", nullptr, 0, DO_SoundInputPrefs);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"Sound playing preferences...", nullptr, 0, DO_SoundOutputPrefs);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"LongSound preferences...", nullptr, 0, DO_LongSoundPrefs);
-#ifdef HAVE_PULSEAUDIO
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report sound server properties", U"Report system properties", 0, DO_Praat_reportSoundServerProperties);
-#endif
-
-	praat_addAction1 (classLongSound, 0, U"LongSound help", nullptr, 0, DO_LongSound_help);
-	praat_addAction1 (classLongSound, 1, U"View", nullptr, praat_ATTRACTIVE, DO_LongSound_view);
-	praat_addAction1 (classLongSound, 1, U"Open", nullptr, praat_HIDDEN, DO_LongSound_view);   // deprecated 2011
-	praat_addAction1 (classLongSound, 0, U"Play part...", nullptr, 0, DO_LongSound_playPart);
-	praat_addAction1 (classLongSound, 1, U"Query -", nullptr, 0, nullptr);
-		praat_TimeFunction_query_init (classLongSound);
-		praat_addAction1 (classLongSound, 1, U"Sampling", nullptr, 1, nullptr);
-		praat_addAction1 (classLongSound, 1, U"Get number of samples", nullptr, 2, DO_LongSound_getNumberOfSamples);
-		praat_addAction1 (classLongSound, 1, U"Get sampling period", nullptr, 2, DO_LongSound_getSamplePeriod);
-							praat_addAction1 (classLongSound, 1, U"Get sample duration", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_LongSound_getSamplePeriod);
-							praat_addAction1 (classLongSound, 1, U"Get sample period", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_LongSound_getSamplePeriod);
-		praat_addAction1 (classLongSound, 1, U"Get sampling frequency", nullptr, 2, DO_LongSound_getSampleRate);
-							praat_addAction1 (classLongSound, 1, U"Get sample rate", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_LongSound_getSampleRate);   // deprecated 2004
-		praat_addAction1 (classLongSound, 1, U"-- get time discretization --", nullptr, 2, nullptr);
-		praat_addAction1 (classLongSound, 1, U"Get time from sample number...", nullptr, 2, DO_LongSound_getTimeFromIndex);
-							praat_addAction1 (classLongSound, 1, U"Get time from index...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_LongSound_getTimeFromIndex);
-		praat_addAction1 (classLongSound, 1, U"Get sample number from time...", nullptr, 2, DO_LongSound_getIndexFromTime);
-							praat_addAction1 (classLongSound, 1, U"Get index from time...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_LongSound_getIndexFromTime);
-	praat_addAction1 (classLongSound, 0, U"Annotate -", nullptr, 0, nullptr);
-		praat_addAction1 (classLongSound, 0, U"Annotation tutorial", nullptr, 1, DO_AnnotationTutorial);
-		praat_addAction1 (classLongSound, 0, U"-- to text grid --", nullptr, 1, nullptr);
-		praat_addAction1 (classLongSound, 0, U"To TextGrid...", nullptr, 1, DO_LongSound_to_TextGrid);
-	praat_addAction1 (classLongSound, 0, U"Convert to Sound", nullptr, 0, nullptr);
-	praat_addAction1 (classLongSound, 0, U"Extract part...", nullptr, 0, DO_LongSound_extractPart);
-	praat_addAction1 (classLongSound, 0, U"Concatenate?", nullptr, 0, DO_LongSound_concatenate);
-	praat_addAction1 (classLongSound, 0, U"Save as WAV file...", nullptr, 0, DO_LongSound_writeToWavFile);
-	praat_addAction1 (classLongSound, 0, U"Write to WAV file...", nullptr, praat_HIDDEN, DO_LongSound_writeToWavFile);
-	praat_addAction1 (classLongSound, 0, U"Save as AIFF file...", nullptr, 0, DO_LongSound_writeToAiffFile);
-	praat_addAction1 (classLongSound, 0, U"Write to AIFF file...", nullptr, praat_HIDDEN, DO_LongSound_writeToAiffFile);
-	praat_addAction1 (classLongSound, 0, U"Save as AIFC file...", nullptr, 0, DO_LongSound_writeToAifcFile);
-	praat_addAction1 (classLongSound, 0, U"Write to AIFC file...", nullptr, praat_HIDDEN, DO_LongSound_writeToAifcFile);
-	praat_addAction1 (classLongSound, 0, U"Save as Next/Sun file...", nullptr, 0, DO_LongSound_writeToNextSunFile);
-	praat_addAction1 (classLongSound, 0, U"Write to Next/Sun file...", nullptr, praat_HIDDEN, DO_LongSound_writeToNextSunFile);
-	praat_addAction1 (classLongSound, 0, U"Save as NIST file...", nullptr, 0, DO_LongSound_writeToNistFile);
-	praat_addAction1 (classLongSound, 0, U"Write to NIST file...", nullptr, praat_HIDDEN, DO_LongSound_writeToNistFile);
-	praat_addAction1 (classLongSound, 0, U"Save as FLAC file...", nullptr, 0, DO_LongSound_writeToFlacFile);
-	praat_addAction1 (classLongSound, 0, U"Write to FLAC file...", nullptr, praat_HIDDEN, DO_LongSound_writeToFlacFile);
-	praat_addAction1 (classLongSound, 0, U"Save left channel as WAV file...", nullptr, 0, DO_LongSound_writeLeftChannelToWavFile);
-	praat_addAction1 (classLongSound, 0, U"Write left channel to WAV file...", nullptr, praat_HIDDEN, DO_LongSound_writeLeftChannelToWavFile);
-	praat_addAction1 (classLongSound, 0, U"Save left channel as AIFF file...", nullptr, 0, DO_LongSound_writeLeftChannelToAiffFile);
-	praat_addAction1 (classLongSound, 0, U"Write left channel to AIFF file...", nullptr, praat_HIDDEN, DO_LongSound_writeLeftChannelToAiffFile);
-	praat_addAction1 (classLongSound, 0, U"Save left channel as AIFC file...", nullptr, 0, DO_LongSound_writeLeftChannelToAifcFile);
-	praat_addAction1 (classLongSound, 0, U"Write left channel to AIFC file...", nullptr, praat_HIDDEN, DO_LongSound_writeLeftChannelToAifcFile);
-	praat_addAction1 (classLongSound, 0, U"Save left channel as Next/Sun file...", nullptr, 0, DO_LongSound_writeLeftChannelToNextSunFile);
-	praat_addAction1 (classLongSound, 0, U"Write left channel to Next/Sun file...", nullptr, praat_HIDDEN, DO_LongSound_writeLeftChannelToNextSunFile);
-	praat_addAction1 (classLongSound, 0, U"Save left channel as NIST file...", nullptr, 0, DO_LongSound_writeLeftChannelToNistFile);
-	praat_addAction1 (classLongSound, 0, U"Write left channel to NIST file...", nullptr, praat_HIDDEN, DO_LongSound_writeLeftChannelToNistFile);
-	praat_addAction1 (classLongSound, 0, U"Save left channel as FLAC file...", nullptr, 0, DO_LongSound_writeLeftChannelToFlacFile);
-	praat_addAction1 (classLongSound, 0, U"Write left channel to FLAC file...", nullptr, praat_HIDDEN, DO_LongSound_writeLeftChannelToFlacFile);
-	praat_addAction1 (classLongSound, 0, U"Save right channel as WAV file...", nullptr, 0, DO_LongSound_writeRightChannelToWavFile);
-	praat_addAction1 (classLongSound, 0, U"Write right channel to WAV file...", nullptr, praat_HIDDEN, DO_LongSound_writeRightChannelToWavFile);
-	praat_addAction1 (classLongSound, 0, U"Save right channel as AIFF file...", nullptr, 0, DO_LongSound_writeRightChannelToAiffFile);
-	praat_addAction1 (classLongSound, 0, U"Write right channel to AIFF file...", nullptr, praat_HIDDEN, DO_LongSound_writeRightChannelToAiffFile);
-	praat_addAction1 (classLongSound, 0, U"Save right channel as AIFC file...", nullptr, 0, DO_LongSound_writeRightChannelToAifcFile);
-	praat_addAction1 (classLongSound, 0, U"Write right channel to AIFC file...", nullptr, praat_HIDDEN, DO_LongSound_writeRightChannelToAifcFile);
-	praat_addAction1 (classLongSound, 0, U"Save right channel as Next/Sun file...", nullptr, 0, DO_LongSound_writeRightChannelToNextSunFile);
-	praat_addAction1 (classLongSound, 0, U"Write right channel to Next/Sun file...", nullptr, praat_HIDDEN, DO_LongSound_writeRightChannelToNextSunFile);
-	praat_addAction1 (classLongSound, 0, U"Save right channel as NIST file...", nullptr, 0, DO_LongSound_writeRightChannelToNistFile);
-	praat_addAction1 (classLongSound, 0, U"Write right channel to NIST file...", nullptr, praat_HIDDEN, DO_LongSound_writeRightChannelToNistFile);
-	praat_addAction1 (classLongSound, 0, U"Save right channel as FLAC file...", nullptr, 0, DO_LongSound_writeRightChannelToFlacFile);
-	praat_addAction1 (classLongSound, 0, U"Write right channel to FLAC file...", nullptr, praat_HIDDEN, DO_LongSound_writeRightChannelToFlacFile);
-	praat_addAction1 (classLongSound, 0, U"Save part as audio file...", nullptr, 0, DO_LongSound_writePartToAudioFile);
-	praat_addAction1 (classLongSound, 0, U"Write part to audio file...", nullptr, praat_HIDDEN, DO_LongSound_writePartToAudioFile);
-
-	praat_addAction1 (classSound, 0, U"Save as WAV file...", nullptr, 0, DO_Sound_writeToWavFile);
-	praat_addAction1 (classSound, 0, U"Write to WAV file...", nullptr, praat_HIDDEN, DO_Sound_writeToWavFile);   // hidden 2011
-	praat_addAction1 (classSound, 0, U"Save as AIFF file...", nullptr, 0, DO_Sound_writeToAiffFile);
-	praat_addAction1 (classSound, 0, U"Write to AIFF file...", nullptr, praat_HIDDEN, DO_Sound_writeToAiffFile);
-	praat_addAction1 (classSound, 0, U"Save as AIFC file...", nullptr, 0, DO_Sound_writeToAifcFile);
-	praat_addAction1 (classSound, 0, U"Write to AIFC file...", nullptr, praat_HIDDEN, DO_Sound_writeToAifcFile);
-	praat_addAction1 (classSound, 0, U"Save as Next/Sun file...", nullptr, 0, DO_Sound_writeToNextSunFile);
-	praat_addAction1 (classSound, 0, U"Write to Next/Sun file...", nullptr, praat_HIDDEN, DO_Sound_writeToNextSunFile);
-	praat_addAction1 (classSound, 0, U"Save as Sun audio file...", nullptr, praat_HIDDEN, DO_Sound_writeToSunAudioFile);
-	praat_addAction1 (classSound, 0, U"Write to Sun audio file...", nullptr, praat_HIDDEN, DO_Sound_writeToSunAudioFile);
-	praat_addAction1 (classSound, 0, U"Save as NIST file...", nullptr, 0, DO_Sound_writeToNistFile);
-	praat_addAction1 (classSound, 0, U"Write to NIST file...", nullptr, praat_HIDDEN, DO_Sound_writeToNistFile);
-	praat_addAction1 (classSound, 0, U"Save as FLAC file...", nullptr, 0, DO_Sound_writeToFlacFile);
-	praat_addAction1 (classSound, 0, U"Write to FLAC file...", nullptr, praat_HIDDEN, DO_Sound_writeToFlacFile);
-	praat_addAction1 (classSound, 1, U"Save as Kay sound file...", nullptr, 0, DO_Sound_writeToKayFile);
-	praat_addAction1 (classSound, 1, U"Write to Kay sound file...", nullptr, praat_HIDDEN, DO_Sound_writeToKayFile);
-	praat_addAction1 (classSound, 1, U"Save as Sesam file...", nullptr, praat_HIDDEN, DO_Sound_writeToSesamFile);
-	praat_addAction1 (classSound, 1, U"Write to Sesam file...", nullptr, praat_HIDDEN, DO_Sound_writeToSesamFile);
-	praat_addAction1 (classSound, 0, U"Save as 24-bit WAV file...", nullptr, 0, DO_Sound_saveAs24BitWavFile);
-	praat_addAction1 (classSound, 0, U"Save as 32-bit WAV file...", nullptr, 0, DO_Sound_saveAs32BitWavFile);
-	praat_addAction1 (classSound, 2, U"Write to stereo WAV file...", nullptr, praat_HIDDEN, DO_Sound_writeToStereoWavFile);   // deprecated 2007
-	praat_addAction1 (classSound, 2, U"Write to stereo AIFF file...", nullptr, praat_HIDDEN, DO_Sound_writeToStereoAiffFile);   // deprecated 2007
-	praat_addAction1 (classSound, 2, U"Write to stereo AIFC file...", nullptr, praat_HIDDEN, DO_Sound_writeToStereoAifcFile);   // deprecated 2007
-	praat_addAction1 (classSound, 2, U"Write to stereo Next/Sun file...", nullptr, praat_HIDDEN, DO_Sound_writeToStereoNextSunFile);   // deprecated 2007
-	praat_addAction1 (classSound, 2, U"Write to stereo NIST file...", nullptr, praat_HIDDEN, DO_Sound_writeToStereoNistFile);   // deprecated 2007
-	praat_addAction1 (classSound, 2, U"Write to stereo FLAC file...", nullptr, praat_HIDDEN, DO_Sound_writeToStereoFlacFile);
-	//praat_addAction1 (classSound, 1, U"Save as raw sound file", nullptr, 0, nullptr);
-	praat_addAction1 (classSound, 1, U"Save as raw 8-bit signed file...", nullptr, 0, DO_Sound_saveAsRaw8bitSignedFile);
-	praat_addAction1 (classSound, 1, U"Write to raw 8-bit signed file...", nullptr, praat_HIDDEN, DO_Sound_saveAsRaw8bitSignedFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 8-bit unsigned file...", nullptr, 0, DO_Sound_saveAsRaw8bitUnsignedFile);
-	praat_addAction1 (classSound, 1, U"Write to raw 8-bit unsigned file...", nullptr, praat_HIDDEN, DO_Sound_saveAsRaw8bitUnsignedFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 16-bit big-endian file...", nullptr, 0, DO_Sound_saveAsRaw16bitBigEndianFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 16-bit little-endian file...", nullptr, 0, DO_Sound_saveAsRaw16bitLittleEndianFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 24-bit big-endian file...", nullptr, 0, DO_Sound_saveAsRaw24bitBigEndianFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 24-bit little-endian file...", nullptr, 0, DO_Sound_saveAsRaw24bitLittleEndianFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 32-bit big-endian file...", nullptr, 0, DO_Sound_saveAsRaw32bitBigEndianFile);
-	praat_addAction1 (classSound, 1, U"Save as raw 32-bit little-endian file...", nullptr, 0, DO_Sound_saveAsRaw32bitLittleEndianFile);
-	praat_addAction1 (classSound, 0, U"Sound help", nullptr, 0, DO_Sound_help);
-	praat_addAction1 (classSound, 1, U"Edit", nullptr, praat_HIDDEN, DO_Sound_edit);   // deprecated 2011
-	praat_addAction1 (classSound, 1, U"Open", nullptr, praat_HIDDEN, DO_Sound_edit);   // deprecated 2011
-	praat_addAction1 (classSound, 1, U"View & Edit", 0, praat_ATTRACTIVE, DO_Sound_edit);
-	praat_addAction1 (classSound, 0, U"Play", nullptr, 0, DO_Sound_play);
-	praat_addAction1 (classSound, 1, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"Draw...", nullptr, 1, DO_Sound_draw);
-	praat_addAction1 (classSound, 1, U"Query -", nullptr, 0, nullptr);
-		praat_TimeFunction_query_init (classSound);
-		praat_addAction1 (classSound, 1, U"Get number of channels", nullptr, 1, DO_Sound_getNumberOfChannels);
-		praat_addAction1 (classSound, 1, U"Query time sampling", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 1, U"Get number of samples", nullptr, 2, DO_Sound_getNumberOfSamples);
-		praat_addAction1 (classSound, 1, U"Get sampling period", nullptr, 2, DO_Sound_getSamplePeriod);
-							praat_addAction1 (classSound, 1, U"Get sample duration", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Sound_getSamplePeriod);
-							praat_addAction1 (classSound, 1, U"Get sample period", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Sound_getSamplePeriod);
-		praat_addAction1 (classSound, 1, U"Get sampling frequency", nullptr, 2, DO_Sound_getSampleRate);
-							praat_addAction1 (classSound, 1, U"Get sample rate", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Sound_getSampleRate);   // deprecated 2004
-		praat_addAction1 (classSound, 1, U"-- get time discretization --", nullptr, 2, nullptr);
-		praat_addAction1 (classSound, 1, U"Get time from sample number...", nullptr, 2, DO_Sound_getTimeFromIndex);
-							praat_addAction1 (classSound, 1, U"Get time from index...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Sound_getTimeFromIndex);
-		praat_addAction1 (classSound, 1, U"Get sample number from time...", nullptr, 2, DO_Sound_getIndexFromTime);
-							praat_addAction1 (classSound, 1, U"Get index from time...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_Sound_getIndexFromTime);
-		praat_addAction1 (classSound, 1, U"-- get content --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 1, U"Get value at time...", nullptr, 1, DO_Sound_getValueAtTime);
-		praat_addAction1 (classSound, 1, U"Get value at sample number...", nullptr, 1, DO_Sound_getValueAtIndex);
-							praat_addAction1 (classSound, 1, U"Get value at index...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_getValueAtIndex);
-		praat_addAction1 (classSound, 1, U"-- get shape --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 1, U"Get minimum...", nullptr, 1, DO_Sound_getMinimum);
-		praat_addAction1 (classSound, 1, U"Get time of minimum...", nullptr, 1, DO_Sound_getTimeOfMinimum);
-		praat_addAction1 (classSound, 1, U"Get maximum...", nullptr, 1, DO_Sound_getMaximum);
-		praat_addAction1 (classSound, 1, U"Get time of maximum...", nullptr, 1, DO_Sound_getTimeOfMaximum);
-		praat_addAction1 (classSound, 1, U"Get absolute extremum...", nullptr, 1, DO_Sound_getAbsoluteExtremum);
-		praat_addAction1 (classSound, 1, U"Get nearest zero crossing...", nullptr, 1, DO_Sound_getNearestZeroCrossing);
-		praat_addAction1 (classSound, 1, U"-- get statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 1, U"Get mean...", nullptr, 1, DO_Sound_getMean);
-		praat_addAction1 (classSound, 1, U"Get root-mean-square...", nullptr, 1, DO_Sound_getRootMeanSquare);
-		praat_addAction1 (classSound, 1, U"Get standard deviation...", nullptr, 1, DO_Sound_getStandardDeviation);
-		praat_addAction1 (classSound, 1, U"-- get energy --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 1, U"Get energy...", nullptr, 1, DO_Sound_getEnergy);
-		praat_addAction1 (classSound, 1, U"Get power...", nullptr, 1, DO_Sound_getPower);
-		praat_addAction1 (classSound, 1, U"-- get energy in air --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 1, U"Get energy in air", nullptr, 1, DO_Sound_getEnergyInAir);
-		praat_addAction1 (classSound, 1, U"Get power in air", nullptr, 1, DO_Sound_getPowerInAir);
-		praat_addAction1 (classSound, 1, U"Get intensity (dB)", nullptr, 1, DO_Sound_getIntensity_dB);
-	praat_addAction1 (classSound, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_TimeFunction_modify_init (classSound);
-		praat_addAction1 (classSound, 0, U"-- modify generic --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Reverse", nullptr, 1, DO_Sound_reverse);
-		praat_addAction1 (classSound, 0, U"Formula...", nullptr, 1, DO_Sound_formula);
-		praat_addAction1 (classSound, 0, U"Formula (part)...", nullptr, 1, DO_Sound_formula_part);
-		praat_addAction1 (classSound, 0, U"-- add & mul --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Add...", nullptr, 1, DO_Sound_add);
-		praat_addAction1 (classSound, 0, U"Subtract mean", nullptr, 1, DO_Sound_subtractMean);
-		praat_addAction1 (classSound, 0, U"Multiply...", nullptr, 1, DO_Sound_multiply);
-		praat_addAction1 (classSound, 0, U"Multiply by window...", nullptr, 1, DO_Sound_multiplyByWindow);
-		praat_addAction1 (classSound, 0, U"Scale peak...", nullptr, 1, DO_Sound_scalePeak);
-		praat_addAction1 (classSound, 0, U"Scale...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_scalePeak);
-		praat_addAction1 (classSound, 0, U"Scale intensity...", nullptr, 1, DO_Sound_scaleIntensity);
-		praat_addAction1 (classSound, 0, U"-- set --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Set value at sample number...", nullptr, 1, DO_Sound_setValueAtIndex);
-							praat_addAction1 (classSound, 0, U"Set value at index...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_setValueAtIndex);
-		praat_addAction1 (classSound, 0, U"Set part to zero...", nullptr, 1, DO_Sound_setPartToZero);
-		praat_addAction1 (classSound, 0, U"-- modify hack --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Override sampling frequency...", nullptr, 1, DO_Sound_overrideSamplingFrequency);
-							praat_addAction1 (classSound, 0, U"Override sample rate...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_overrideSamplingFrequency);
-		praat_addAction1 (classSound, 0, U"-- in-line filters --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"In-line filters", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Filter with one formant (in-line)...", nullptr, 2, DO_Sound_filterWithOneFormantInline);
-		praat_addAction1 (classSound, 0, U"Pre-emphasize (in-line)...", nullptr, 2, DO_Sound_preemphasizeInline);
-		praat_addAction1 (classSound, 0, U"De-emphasize (in-line)...", nullptr, 2, DO_Sound_deemphasizeInline);
-	praat_addAction1 (classSound, 0, U"Annotate -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"Annotation tutorial", nullptr, 1, DO_AnnotationTutorial);
-		praat_addAction1 (classSound, 0, U"-- to text grid --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"To TextGrid...", nullptr, 1, DO_Sound_to_TextGrid);
-		praat_addAction1 (classSound, 0, U"To TextTier", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_TextTier);
-		praat_addAction1 (classSound, 0, U"To IntervalTier", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_to_IntervalTier);
-	praat_addAction1 (classSound, 0, U"Analyse periodicity -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"To Pitch...", nullptr, 1, DO_Sound_to_Pitch);
-		praat_addAction1 (classSound, 0, U"To Pitch (ac)...", nullptr, 1, DO_Sound_to_Pitch_ac);
-		praat_addAction1 (classSound, 0, U"To Pitch (cc)...", nullptr, 1, DO_Sound_to_Pitch_cc);
-		praat_addAction1 (classSound, 0, U"To PointProcess (periodic, cc)...", nullptr, 1, DO_Sound_to_PointProcess_periodic_cc);
-		praat_addAction1 (classSound, 0, U"To PointProcess (periodic, peaks)...", nullptr, 1, DO_Sound_to_PointProcess_periodic_peaks);
-		praat_addAction1 (classSound, 0, U"-- points --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"To PointProcess (extrema)...", nullptr, 1, DO_Sound_to_PointProcess_extrema);
-		praat_addAction1 (classSound, 0, U"To PointProcess (zeroes)...", nullptr, 1, DO_Sound_to_PointProcess_zeroes);
-		praat_addAction1 (classSound, 0, U"-- hnr --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"To Harmonicity (cc)...", nullptr, 1, DO_Sound_to_Harmonicity_cc);
-		praat_addAction1 (classSound, 0, U"To Harmonicity (ac)...", nullptr, 1, DO_Sound_to_Harmonicity_ac);
-		praat_addAction1 (classSound, 0, U"To Harmonicity (gne)...", nullptr, 1, DO_Sound_to_Harmonicity_gne);
-		praat_addAction1 (classSound, 0, U"-- autocorrelation --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Autocorrelate...", nullptr, 1, DO_Sound_autoCorrelate);
-	praat_addAction1 (classSound, 0, U"Analyse spectrum -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"To Spectrum...", nullptr, 1, DO_Sound_to_Spectrum);
-							praat_addAction1 (classSound, 0, U"To Spectrum (fft)", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_to_Spectrum_fft);
-							praat_addAction1 (classSound, 0, U"To Spectrum", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_to_Spectrum_fft);
-							praat_addAction1 (classSound, 0, U"To Spectrum (dft)", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_to_Spectrum_dft);
-		praat_addAction1 (classSound, 0, U"To Ltas...", nullptr, 1, DO_Sound_to_Ltas);
-		praat_addAction1 (classSound, 0, U"To Ltas (pitch-corrected)...", nullptr, 1, DO_Sound_to_Ltas_pitchCorrected);
-		praat_addAction1 (classSound, 0, U"-- spectrotemporal --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"To Spectrogram...", nullptr, 1, DO_Sound_to_Spectrogram);
-		praat_addAction1 (classSound, 0, U"To Cochleagram...", nullptr, 1, DO_Sound_to_Cochleagram);
-		praat_addAction1 (classSound, 0, U"To Cochleagram (edb)...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_to_Cochleagram_edb);
-		praat_addAction1 (classSound, 0, U"-- formants --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"To Formant (burg)...", nullptr, 1, DO_Sound_to_Formant_burg);
-		praat_addAction1 (classSound, 0, U"To Formant (hack)", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"To Formant (keep all)...", nullptr, 2, DO_Sound_to_Formant_keepAll);
-		praat_addAction1 (classSound, 0, U"To Formant (sl)...", nullptr, 2, DO_Sound_to_Formant_willems);
-	praat_addAction1 (classSound, 0, U"To Intensity...", nullptr, 0, DO_Sound_to_Intensity);
-	praat_addAction1 (classSound, 0, U"To IntensityTier...", nullptr, praat_HIDDEN, DO_Sound_to_IntensityTier);
-	praat_addAction1 (classSound, 0, U"Manipulate -", nullptr, 0, nullptr);
-	praat_addAction1 (classSound, 0, U"To Manipulation...", nullptr, 1, DO_Sound_to_Manipulation);
-	praat_addAction1 (classSound, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"Convert to mono", nullptr, 1, DO_Sound_convertToMono);
-		praat_addAction1 (classSound, 0, U"Convert to stereo", nullptr, 1, DO_Sound_convertToStereo);
-		praat_addAction1 (classSound, 0, U"Extract all channels", nullptr, 1, DO_Sound_extractAllChannels);
-		praat_addAction1 (classSound, 0, U"Extract left channel", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_extractLeftChannel);   // deprecated 2010
-		praat_addAction1 (classSound, 0, U"Extract right channel", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sound_extractRightChannel);   // deprecated 2010
-		praat_addAction1 (classSound, 0, U"Extract one channel...", nullptr, 1, DO_Sound_extractChannel);
-		praat_addAction1 (classSound, 0, U"Extract part...", nullptr, 1, DO_Sound_extractPart);
-		praat_addAction1 (classSound, 0, U"Extract part for overlap...", nullptr, 1, DO_Sound_extractPartForOverlap);
-		praat_addAction1 (classSound, 0, U"Resample...", nullptr, 1, DO_Sound_resample);
-		praat_addAction1 (classSound, 0, U"-- enhance --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Lengthen (overlap-add)...", nullptr, 1, DO_Sound_lengthen_overlapAdd);
-		praat_addAction1 (classSound, 0, U"Lengthen (PSOLA)...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Sound_lengthen_overlapAdd);
-		praat_addAction1 (classSound, 0, U"Deepen band modulation...", nullptr, 1, DO_Sound_deepenBandModulation);
-		praat_addAction1 (classSound, 0, U"-- cast --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Down to Matrix", nullptr, 1, DO_Sound_to_Matrix);
-	praat_addAction1 (classSound, 0, U"Filter -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"Filtering tutorial", nullptr, 1, DO_FilteringTutorial);
-		praat_addAction1 (classSound, 0, U"-- frequency-domain filter --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Filter (pass Hann band)...", nullptr, 1, DO_Sound_filter_passHannBand);
-		praat_addAction1 (classSound, 0, U"Filter (stop Hann band)...", nullptr, 1, DO_Sound_filter_stopHannBand);
-		praat_addAction1 (classSound, 0, U"Filter (formula)...", nullptr, 1, DO_Sound_filter_formula);
-		praat_addAction1 (classSound, 0, U"-- time-domain filter --", nullptr, 1, nullptr);
-		praat_addAction1 (classSound, 0, U"Filter (one formant)...", nullptr, 1, DO_Sound_filter_oneFormant);
-		praat_addAction1 (classSound, 0, U"Filter (pre-emphasis)...", nullptr, 1, DO_Sound_filter_preemphasis);
-		praat_addAction1 (classSound, 0, U"Filter (de-emphasis)...", nullptr, 1, DO_Sound_filter_deemphasis);
-	praat_addAction1 (classSound, 0, U"Combine -", nullptr, 0, nullptr);
-		praat_addAction1 (classSound, 0, U"Combine to stereo", nullptr, 1, DO_Sounds_combineToStereo);
-		praat_addAction1 (classSound, 0, U"Concatenate", nullptr, 1, DO_Sounds_concatenate);
-		praat_addAction1 (classSound, 0, U"Concatenate recoverably", nullptr, 1, DO_Sounds_concatenateRecoverably);
-		praat_addAction1 (classSound, 0, U"Concatenate with overlap...", nullptr, 1, DO_Sounds_concatenateWithOverlap);
-		praat_addAction1 (classSound, 2, U"Convolve", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Sounds_convolve_old);
-		praat_addAction1 (classSound, 2, U"Convolve...", nullptr, 1, DO_Sounds_convolve);
-		praat_addAction1 (classSound, 2, U"Cross-correlate...", nullptr, 1, DO_Sounds_crossCorrelate);
-		praat_addAction1 (classSound, 2, U"To ParamCurve", nullptr, 1, DO_Sounds_to_ParamCurve);
-
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as WAV file...", nullptr, 0, DO_LongSound_Sound_writeToWavFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Write to WAV file...", nullptr, praat_HIDDEN, DO_LongSound_Sound_writeToWavFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as AIFF file...", nullptr, 0, DO_LongSound_Sound_writeToAiffFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Write to AIFF file...", nullptr, praat_HIDDEN, DO_LongSound_Sound_writeToAiffFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as AIFC file...", nullptr, 0, DO_LongSound_Sound_writeToAifcFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Write to AIFC file...", nullptr, praat_HIDDEN, DO_LongSound_Sound_writeToAifcFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as NeXT/Sun file...", nullptr, 0, DO_LongSound_Sound_writeToNextSunFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Write to NeXT/Sun file...", nullptr, praat_HIDDEN, DO_LongSound_Sound_writeToNextSunFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as NIST file...", nullptr, 0, DO_LongSound_Sound_writeToNistFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Write to NIST file...", nullptr, praat_HIDDEN, DO_LongSound_Sound_writeToNistFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as FLAC file...", nullptr, 0, DO_LongSound_Sound_writeToFlacFile);
-	praat_addAction2 (classLongSound, 0, classSound, 0, U"Write to FLAC file...", nullptr, praat_HIDDEN, DO_LongSound_Sound_writeToFlacFile);
-}
-
-/* End of file praat_Sound.cpp */
diff --git a/fon/praat_TextGrid_init.cpp b/fon/praat_TextGrid_init.cpp
index 8b7a707..66d56a1 100644
--- a/fon/praat_TextGrid_init.cpp
+++ b/fon/praat_TextGrid_init.cpp
@@ -16,8 +16,6 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "praat.h"
-
 #include "Pitch_AnyTier_to_PitchTier.h"
 #include "SpectrumEditor.h"
 #include "SpellingChecker.h"
@@ -26,819 +24,662 @@
 #include "TextGrid_Sound.h"
 #include "WordList.h"
 
+#include "praat_TimeTier.h"
+#include "praat_uvafon.h"
+
 #undef iam
 #define iam iam_LOOP
 
-void praat_dia_timeRange (UiForm dia);
-void praat_get_timeRange (UiForm dia, double *tmin, double *tmax);
-int praat_get_frequencyRange (UiForm dia, double *fmin, double *fmax);
-
 static const char32 *STRING_FROM_FREQUENCY_HZ = U"left Frequency range (Hz)";
 static const char32 *STRING_TO_FREQUENCY_HZ = U"right Frequency range (Hz)";
 static const char32 *STRING_TIER_NUMBER = U"Tier number";
 static const char32 *STRING_INTERVAL_NUMBER = U"Interval number";
 static const char32 *STRING_POINT_NUMBER = U"Point number";
 
-void praat_TimeFunction_modify_init (ClassInfo klas);   // Modify buttons for time-based subclasses of Function.
-
-/***** ANYTIER (generic) *****/
+// MARK: - ANYTIER (generic)
 
-DIRECT2 (AnyTier_into_TextGrid) {
-	autoTextGrid grid = TextGrid_createWithoutTiers (1e30, -1e30);
-	LOOP {
-		iam (AnyTier);
-		TextGrid_addTier_copy (grid.get(), me);
-	}
-	praat_new (grid.move(), U"grid");
-END2 }
+DIRECT (NEW1_AnyTier_into_TextGrid) {
+	CONVERT_LIST (Function)
+		autoTextGrid result = TextGrid_createWithoutTiers (1e30, -1e30);
+		for (long i = 1; i <= list.size; i ++) {
+			TextGrid_addTier_copy (result.get(), list.at [i]);
+		}
+	CONVERT_LIST_END (U"grid")
+}
 
-/***** INTERVALTIER *****/
+// MARK: - INTERVALTIER
 
-FORM (IntervalTier_downto_TableOfReal, U"IntervalTier: Down to TableOfReal", 0) {
-	SENTENCE (U"Label", U"")
-	OK2
+FORM (NEW_IntervalTier_downto_TableOfReal, U"IntervalTier: Down to TableOfReal", nullptr) {
+	SENTENCE4 (label, U"Label", U"")
+	OK
 DO
-	LOOP {
-		iam (IntervalTier);
-		autoTableOfReal thee = IntervalTier_downto_TableOfReal (me, GET_STRING (U"Label"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (IntervalTier)
+		autoTableOfReal result = IntervalTier_downto_TableOfReal (me, label);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (IntervalTier_downto_TableOfReal_any) {
-	LOOP {
-		iam (IntervalTier);
-		autoTableOfReal thee = IntervalTier_downto_TableOfReal_any (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_IntervalTier_downto_TableOfReal_any) {
+	CONVERT_EACH (IntervalTier)
+		autoTableOfReal result = IntervalTier_downto_TableOfReal_any (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (IntervalTier_getCentrePoints, U"IntervalTier: Get centre points", 0) {
-	SENTENCE (U"Text", U"")
-	OK2
+FORM (NEW_IntervalTier_getCentrePoints, U"IntervalTier: Get centre points", nullptr) {
+	SENTENCE4 (text, U"Text", U"")
+	OK
 DO
-	LOOP {
-		iam (IntervalTier);
-		autoPointProcess thee = IntervalTier_getCentrePoints (me, GET_STRING (U"Text"));
-		praat_new (thee.move(), GET_STRING (U"Text"));
-	}
-END2 }
+	CONVERT_EACH (IntervalTier)
+		autoPointProcess result = IntervalTier_getCentrePoints (me, text);
+	CONVERT_EACH_END (text)
+}
 
-FORM (IntervalTier_getEndPoints, U"IntervalTier: Get end points", 0) {
-	SENTENCE (U"Text", U"")
-	OK2
+FORM (NEW_IntervalTier_getEndPoints, U"IntervalTier: Get end points", nullptr) {
+	SENTENCE4 (text, U"Text", U"")
+	OK
 DO
-	LOOP {
-		iam (IntervalTier);
-		autoPointProcess thee = IntervalTier_getEndPoints (me, GET_STRING (U"Text"));
-		praat_new (thee.move(), GET_STRING (U"Text"));
-	}
-END2 }
+	CONVERT_EACH (IntervalTier)
+		autoPointProcess result = IntervalTier_getEndPoints (me, text);
+	CONVERT_EACH_END (text)
+}
 
-FORM (IntervalTier_getStartingPoints, U"IntervalTier: Get starting points", 0) {
-	SENTENCE (U"Text", U"")
-	OK2
+FORM (NEW_IntervalTier_getStartingPoints, U"IntervalTier: Get starting points", nullptr) {
+	SENTENCE4 (text, U"Text", U"")
+	OK
 DO
-	LOOP {
-		iam (IntervalTier);
-		autoPointProcess thee = IntervalTier_getStartingPoints (me, GET_STRING (U"Text"));
-		praat_new (thee.move(), GET_STRING (U"Text"));
-	}
-END2 }
+	CONVERT_EACH (IntervalTier)
+		autoPointProcess result = IntervalTier_getStartingPoints (me, text);
+	CONVERT_EACH_END (text)
+}
 
-DIRECT2 (IntervalTier_help) {
-	Melder_help (U"IntervalTier");
-END2 }
+DIRECT (HELP_IntervalTier_help) {
+	HELP (U"IntervalTier")
+}
 
-FORM_WRITE2 (IntervalTier_writeToXwaves, U"Xwaves label file", 0, 0) {
-	LOOP {
-		iam (IntervalTier);
+FORM_SAVE (SAVE_IntervalTier_writeToXwaves, U"Xwaves label file", nullptr, nullptr) {
+	SAVE_ONE (IntervalTier)
 		IntervalTier_writeToXwaves (me, file);
-	}
-END2 }
+	SAVE_ONE_END
+}
 
-/***** INTERVALTIER & POINTPROCESS *****/
+// MARK: - INTERVALTIER & POINTPROCESS
 
-FORM (IntervalTier_PointProcess_endToCentre, U"From end to centre", U"IntervalTier & PointProcess: End to centre...") {
-	REAL (U"Phase (0-1)", U"0.5")
-	OK2
+FORM (NEW1_IntervalTier_PointProcess_startToCentre, U"From start to centre", U"IntervalTier & PointProcess: Start to centre...") {
+	REALVAR (phase, U"Phase (0-1)", U"0.5")
+	OK
 DO
-	IntervalTier tier = nullptr;
-	PointProcess point = nullptr;
-	LOOP {
-		if (CLASS == classIntervalTier) tier = (IntervalTier) OBJECT;
-		if (CLASS == classPointProcess) point = (PointProcess) OBJECT;
-	}
-	double phase = GET_REAL (U"Phase");
-	autoPointProcess thee = IntervalTier_PointProcess_endToCentre (tier, point, phase);
-	praat_new (thee.move(), tier -> name, U"_", point -> name, U"_", lround (100.0 * phase));
-END2 }
+	CONVERT_TWO (IntervalTier, PointProcess)
+		autoPointProcess result = IntervalTier_PointProcess_startToCentre (me, you, phase);
+	CONVERT_TWO_END (my name, U"_", your name, U"_", lround (100.0 * phase));
+}
 
-FORM (IntervalTier_PointProcess_startToCentre, U"From start to centre", U"IntervalTier & PointProcess: Start to centre...") {
-	REAL (U"Phase (0-1)", U"0.5")
-	OK2
+FORM (NEW1_IntervalTier_PointProcess_endToCentre, U"From end to centre", U"IntervalTier & PointProcess: End to centre...") {
+	REALVAR (phase, U"Phase (0-1)", U"0.5")
+	OK
 DO
-	IntervalTier tier = nullptr;
-	PointProcess point = nullptr;
-	LOOP {
-		if (CLASS == classIntervalTier) tier = (IntervalTier) OBJECT;
-		if (CLASS == classPointProcess) point = (PointProcess) OBJECT;
-	}
-	double phase = GET_REAL (U"Phase");
-	autoPointProcess thee = IntervalTier_PointProcess_startToCentre (tier, point, phase);
-	praat_new (thee.move(), tier -> name, U"_", point -> name, U"_", lround (100.0 * phase));
-END2 }
+	CONVERT_TWO (IntervalTier, PointProcess)
+		autoPointProcess result = IntervalTier_PointProcess_endToCentre (me, you, phase);
+	CONVERT_TWO_END (my name, U"_", your name, U"_", lround (100.0 * phase));
+}
 
-/***** LABEL (obsolete) *****/
+// MARK: - LABEL (obsolete)
 
-DIRECT2 (Label_Sound_to_TextGrid) {
-	Label label = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classLabel) label = (Label) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	autoTextGrid thee = Label_Function_to_TextGrid (label, sound);
-	praat_new (thee.move(), sound -> name);
-END2 }
+DIRECT (NEW1_Label_Sound_to_TextGrid) {
+	CONVERT_TWO (Label, Sound)
+		autoTextGrid result = Label_Function_to_TextGrid (me, you);
+	CONVERT_TWO_END (your name)
+}
 
-DIRECT2 (info_Label_Sound_to_TextGrid) {
-	Melder_information (U"This is an old-style Label object. To turn it into a TextGrid, U"
-		"select it together with a Sound of the appropriate duration, and click \"To TextGrid\".");
-END2 }
+DIRECT (HINT_Label_Sound_to_TextGrid) {
+	INFO_NONE
+		Melder_information (U"This is an old-style Label object. To turn it into a TextGrid, U"
+			"select it together with a Sound of the appropriate duration, and click \"To TextGrid\".");
+	INFO_NONE_END
+}
 
-/***** PITCH & TEXTGRID *****/
+// MARK: - PITCH & TEXTGRID
+
+FORM (GRAPHICS_TextGrid_Pitch_draw, U"TextGrid & Pitch: Draw", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"0.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	INTEGER4 (fontSize, U"Font size (points)", U"18")
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	OPTIONMENU4x (textAlignment, U"Text alignment", 2, 0) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_draw (me, you, GRAPHICS, tierNumber, fromTime, toTime, fromFrequency, toFrequency,
+			fontSize, useTextStyles, textAlignment, garnish, Pitch_speckle_NO, kPitch_unit_HERTZ);
+	GRAPHICS_TWO_END
+}
 
-static void pr_TextGrid_Pitch_draw (UiForm dia, int speckle, int unit) {
-	TextGrid grid = nullptr;
-	Pitch pitch = nullptr;
-	int IOBJECT;
-	LOOP {
-		if (CLASS == classTextGrid) grid = (TextGrid) OBJECT;
-		if (CLASS == classPitch) pitch = (Pitch) OBJECT;
-	}
-	double tmin, tmax, fmin, fmax;
-	praat_get_timeRange (dia, & tmin, & tmax);
-	praat_get_frequencyRange (dia, & fmin, & fmax);
-	autoPraatPicture picture;
-	TextGrid_Pitch_draw (grid, pitch, GRAPHICS,
-		GET_INTEGER (STRING_TIER_NUMBER), tmin, tmax, fmin, fmax, GET_INTEGER (U"Font size"),
-		GET_INTEGER (U"Use text styles"), GET_INTEGER (U"Text alignment") - 1, GET_INTEGER (U"Garnish"), speckle, unit);
-}
-
-FORM (TextGrid_Pitch_draw, U"TextGrid & Pitch: Draw", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_NO, kPitch_unit_HERTZ);
-END2 }
-
-FORM (TextGrid_Pitch_drawErb, U"TextGrid & Pitch: Draw erb", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (ERB)", U"0")
-	REAL (U"right Frequency range (ERB)", U"10.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_NO, kPitch_unit_ERB);
-END2 }
-
-FORM (TextGrid_Pitch_drawLogarithmic, U"TextGrid & Pitch: Draw logarithmic", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	POSITIVE (STRING_FROM_FREQUENCY_HZ, U"50.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_NO, kPitch_unit_HERTZ_LOGARITHMIC);
-END2 }
-
-FORM (TextGrid_Pitch_drawMel, U"TextGrid & Pitch: Draw mel", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (mel)", U"0")
-	REAL (U"right Frequency range (mel)", U"500")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_NO, kPitch_unit_MEL);
-END2 }
-
-FORM (TextGrid_Pitch_drawSemitones, U"TextGrid & Pitch: Draw semitones", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
+FORM (GRAPHICS_TextGrid_Pitch_drawErb, U"TextGrid & Pitch: Draw erb", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (ERB)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (ERB)", U"10.0")
+	INTEGER4 (fontSize, U"Font size (points)", U"18")
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	OPTIONMENU4x (textAlignment, U"Text alignment", 2, 0) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_draw (me, you, GRAPHICS, tierNumber, fromTime, toTime, fromFrequency, toFrequency,
+			fontSize, useTextStyles, textAlignment, garnish, Pitch_speckle_NO, kPitch_unit_ERB);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawLogarithmic, U"TextGrid & Pitch: Draw logarithmic", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"50.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	INTEGER4 (fontSize, U"Font size (points)", U"18")
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	OPTIONMENU4x (textAlignment, U"Text alignment", 2, 0) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_draw (me, you, GRAPHICS, tierNumber, fromTime, toTime, fromFrequency, toFrequency,
+			fontSize, useTextStyles, textAlignment, garnish, Pitch_speckle_NO, kPitch_unit_HERTZ_LOGARITHMIC);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawMel, U"TextGrid & Pitch: Draw mel", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"500.0")
+	INTEGER4 (fontSize, U"Font size (points)", U"18")
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	OPTIONMENU4x (textAlignment, U"Text alignment", 2, 0) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_draw (me, you, GRAPHICS, tierNumber, fromTime, toTime, fromFrequency, toFrequency,
+			fontSize, useTextStyles, textAlignment, garnish, Pitch_speckle_NO, kPitch_unit_MEL);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawSemitones, U"TextGrid & Pitch: Draw semitones", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 100 hertz:")
-	REAL (U"left Frequency range (st)", U"-12.0")
-	REAL (U"right Frequency range (st)", U"30.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_NO, kPitch_unit_SEMITONES_100);
-END2 }
-
-static void pr_TextGrid_Pitch_drawSeparately (UiForm dia, int speckle, int unit) {
-	TextGrid grid = nullptr;
-	Pitch pitch = nullptr;
-	int IOBJECT;
-	LOOP {
-		if (CLASS == classTextGrid) grid = (TextGrid) OBJECT;
-		if (CLASS == classPitch) pitch = (Pitch) OBJECT;
-	}
-	double tmin, tmax, fmin, fmax;
-	praat_get_timeRange (dia, & tmin, & tmax);
-	praat_get_frequencyRange (dia, & fmin, & fmax);
-	autoPraatPicture picture;
-	TextGrid_Pitch_drawSeparately (grid, pitch, GRAPHICS,
-		tmin, tmax, fmin, fmax, GET_INTEGER (U"Show boundaries"),
-		GET_INTEGER (U"Use text styles"), GET_INTEGER (U"Garnish"), speckle, unit);
-}
-
-FORM (TextGrid_Pitch_drawSeparately, U"TextGrid & Pitch: Draw separately", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	REAL (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_NO, kPitch_unit_HERTZ);
-END2 }
-
-FORM (TextGrid_Pitch_drawSeparatelyErb, U"TextGrid & Pitch: Draw separately erb", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (ERB)", U"0")
-	REAL (U"right Frequency range (ERB)", U"10.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_NO, kPitch_unit_ERB);
-END2 }
-
-FORM (TextGrid_Pitch_drawSeparatelyLogarithmic, U"TextGrid & Pitch: Draw separately logarithmic", nullptr) {
-	praat_dia_timeRange (dia);
-	POSITIVE (STRING_FROM_FREQUENCY_HZ, U"50.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_NO, kPitch_unit_HERTZ_LOGARITHMIC);
-END2 }
-
-FORM (TextGrid_Pitch_drawSeparatelyMel, U"TextGrid & Pitch: Draw separately mel", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (mel)", U"0")
-	REAL (U"right Frequency range (mel)", U"500")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_NO, kPitch_unit_MEL);
-END2 }
-
-FORM (TextGrid_Pitch_drawSeparatelySemitones, U"TextGrid & Pitch: Draw separately semitones", nullptr) {
-	praat_dia_timeRange (dia);
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-12.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"30.0")
+	INTEGER4 (fontSize, U"Font size (points)", U"18")
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	OPTIONMENU4x (textAlignment, U"Text alignment", 2, 0) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_draw (me, you, GRAPHICS, tierNumber, fromTime, toTime, fromFrequency, toFrequency,
+			fontSize, useTextStyles, textAlignment, garnish, Pitch_speckle_NO, kPitch_unit_SEMITONES_100);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawSeparately, U"TextGrid & Pitch: Draw separately", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"0.0")
+	REALVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_NO, kPitch_unit_HERTZ);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawSeparatelyErb, U"TextGrid & Pitch: Draw separately erb", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (ERB)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (ERB)", U"10.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_NO, kPitch_unit_ERB);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawSeparatelyLogarithmic, U"TextGrid & Pitch: Draw separately logarithmic", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"50.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_NO, kPitch_unit_HERTZ_LOGARITHMIC);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawSeparatelyMel, U"TextGrid & Pitch: Draw separately mel", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_NO, kPitch_unit_MEL);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_drawSeparatelySemitones, U"TextGrid & Pitch: Draw separately semitones", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 100 hertz:")
-	REAL (U"left Frequency range (st)", U"-12.0")
-	REAL (U"right Frequency range (st)", U"30.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_NO, kPitch_unit_SEMITONES_100);
-END2 }
-
-FORM (TextGrid_Pitch_speckle, U"TextGrid & Pitch: Speckle", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_YES, kPitch_unit_HERTZ);
-END2 }
-
-FORM (TextGrid_Pitch_speckleErb, U"TextGrid & Pitch: Speckle erb", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (ERB)", U"0")
-	REAL (U"right Frequency range (ERB)", U"10.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_YES, kPitch_unit_ERB);
-END2 }
-
-FORM (TextGrid_Pitch_speckleLogarithmic, U"TextGrid & Pitch: Speckle logarithmic", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	POSITIVE (STRING_FROM_FREQUENCY_HZ, U"50.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_YES, kPitch_unit_HERTZ_LOGARITHMIC);
-END2 }
-
-FORM (TextGrid_Pitch_speckleMel, U"TextGrid & Pitch: Speckle mel", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (mel)", U"0")
-	REAL (U"right Frequency range (mel)", U"500")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_YES, kPitch_unit_MEL);
-END2 }
-
-FORM (TextGrid_Pitch_speckleSemitones, U"TextGrid & Pitch: Speckle semitones", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	praat_dia_timeRange (dia);
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-12.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"30.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_NO, kPitch_unit_SEMITONES_100);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckle, U"TextGrid & Pitch: Speckle", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"0.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_HERTZ);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleErb, U"TextGrid & Pitch: Speckle erb", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (ERB)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (ERB)", U"10.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_ERB);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleLogarithmic, U"TextGrid & Pitch: Speckle logarithmic", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"50.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_HERTZ_LOGARITHMIC);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleMel, U"TextGrid & Pitch: Speckle mel", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_MEL);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleSemitones, U"TextGrid & Pitch: Speckle semitones", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 100 hertz:")
-	REAL (U"left Frequency range (st)", U"-12.0")
-	REAL (U"right Frequency range (st)", U"30.0")
-	INTEGER (U"Font size (points)", U"18")
-	BOOLEAN (U"Use text styles", true)
-	OPTIONMENU (U"Text alignment", 2) OPTION (U"Left") OPTION (U"Centre") OPTION (U"Right")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_draw (dia, Pitch_speckle_YES, kPitch_unit_SEMITONES_100);
-END2 }
-
-FORM (TextGrid_Pitch_speckleSeparately, U"TextGrid & Pitch: Speckle separately", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (STRING_FROM_FREQUENCY_HZ, U"0.0")
-	REAL (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_YES, kPitch_unit_HERTZ);
-END2 }
-
-FORM (TextGrid_Pitch_speckleSeparatelyErb, U"TextGrid & Pitch: Speckle separately erb", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (ERB)", U"0")
-	REAL (U"right Frequency range (ERB)", U"10.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_YES, kPitch_unit_ERB);
-END2 }
-
-FORM (TextGrid_Pitch_speckleSeparatelyLogarithmic, U"TextGrid & Pitch: Speckle separately logarithmic", nullptr) {
-	praat_dia_timeRange (dia);
-	POSITIVE (STRING_FROM_FREQUENCY_HZ, U"50.0")
-	POSITIVE (STRING_TO_FREQUENCY_HZ, U"500.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_YES, kPitch_unit_HERTZ_LOGARITHMIC);
-END2 }
-
-FORM (TextGrid_Pitch_speckleSeparatelyMel, U"TextGrid & Pitch: Speckle separately mel", nullptr) {
-	praat_dia_timeRange (dia);
-	REAL (U"left Frequency range (mel)", U"0")
-	REAL (U"right Frequency range (mel)", U"500")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_YES, kPitch_unit_MEL);
-END2 }
-
-FORM (TextGrid_Pitch_speckleSeparatelySemitones, U"TextGrid & Pitch: Speckle separately semitones", nullptr) {
-	praat_dia_timeRange (dia);
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-12.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"30.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_SEMITONES_100);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleSeparately, U"TextGrid & Pitch: Speckle separately", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"0.0")
+	REALVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_HERTZ);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleSeparatelyErb, U"TextGrid & Pitch: Speckle separately erb", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (ERB)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (ERB)", U"10.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_ERB);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleSeparatelyLogarithmic, U"TextGrid & Pitch: Speckle separately logarithmic", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVEVAR (fromFrequency, STRING_FROM_FREQUENCY_HZ, U"50.0")
+	POSITIVEVAR (toFrequency, STRING_TO_FREQUENCY_HZ, U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_HERTZ_LOGARITHMIC);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleSeparatelyMel, U"TextGrid & Pitch: Speckle separately mel", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (mel)", U"0.0")
+	REALVAR (toFrequency, U"right Frequency range (mel)", U"500.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_MEL);
+	GRAPHICS_TWO_END
+}
+
+FORM (GRAPHICS_TextGrid_Pitch_speckleSeparatelySemitones, U"TextGrid & Pitch: Speckle separately semitones", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
 	LABEL (U"", U"Range in semitones re 100 hertz:")
-	REAL (U"left Frequency range (st)", U"-12.0")
-	REAL (U"right Frequency range (st)", U"30.0")
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	pr_TextGrid_Pitch_drawSeparately (dia, Pitch_speckle_YES, kPitch_unit_SEMITONES_100);
-END2 }
+	REALVAR (fromFrequency, U"left Frequency range (st)", U"-12.0")
+	REALVAR (toFrequency, U"right Frequency range (st)", U"30.0")
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_TWO (TextGrid, Pitch)
+		TextGrid_Pitch_drawSeparately (me, you, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			showBoundaries, useTextStyles, garnish, Pitch_speckle_YES, kPitch_unit_MEL);
+	GRAPHICS_TWO_END
+}
 
-/***** PITCH & TEXTTIER *****/
+// MARK: - PITCH & TEXTTIER
 
-FORM (Pitch_TextTier_to_PitchTier, U"Pitch & TextTier to PitchTier", U"Pitch & TextTier: To PitchTier...") {
-	RADIO (U"Unvoiced strategy", 3)
+FORM (NEW1_Pitch_TextTier_to_PitchTier, U"Pitch & TextTier to PitchTier", U"Pitch & TextTier: To PitchTier...") {
+	RADIO4x (unvoicedStrategy, U"Unvoiced strategy", 3, 0)
 		RADIOBUTTON (U"Zero")
 		RADIOBUTTON (U"Error")
 		RADIOBUTTON (U"Interpolate")
-	OK2
+	OK
 DO
-	Pitch pitch = nullptr;
-	TextTier tier = nullptr;
-	LOOP {
-		iam (Daata);
-		if (CLASS == classPitch) pitch = (Pitch) me;
-		if (CLASS == classTextTier) tier = (TextTier) me;
-	}
-	autoPitchTier thee = Pitch_AnyTier_to_PitchTier (pitch, (AnyTier) tier, GET_INTEGER (U"Unvoiced strategy") - 1);
-	praat_new (thee.move(), pitch -> name);
-END2 }
+	CONVERT_TWO (Pitch, TextTier)
+		autoPitchTier result = Pitch_AnyTier_to_PitchTier (me, you->asAnyTier(), unvoicedStrategy);
+	CONVERT_TWO_END (my name)
+}
 
-/***** SOUND & TEXTGRID *****/
+// MARK: - SOUND & TEXTGRID
 
-FORM (TextGrid_Sound_draw, U"TextGrid & Sound: Draw...", nullptr) {
-	praat_dia_timeRange (dia);
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
+FORM (GRAPHICS_TextGrid_Sound_draw, U"TextGrid & Sound: Draw...", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	autoPraatPicture picture;
-	TextGrid_Sound_draw (textgrid, sound, GRAPHICS,
-		GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Show boundaries"),
-		GET_INTEGER (U"Use text styles"), GET_INTEGER (U"Garnish"));
-END2 }
-
-FORM (TextGrid_Sound_extractAllIntervals, U"TextGrid & Sound: Extract all intervals", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	BOOLEAN (U"Preserve times", false)
-	OK2
-DO
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	autoSoundList thee = TextGrid_Sound_extractAllIntervals (textgrid, sound,
-		GET_INTEGER (STRING_TIER_NUMBER), GET_INTEGER (U"Preserve times"));
-	thy classInfo = classCollection;   // YUCK
-	praat_new (thee.move(), U"dummy");
-END2 }
-
-FORM (TextGrid_Sound_extractNonemptyIntervals, U"TextGrid & Sound: Extract non-empty intervals", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	BOOLEAN (U"Preserve times", false)
-	OK2
-DO
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	autoSoundList thee = TextGrid_Sound_extractNonemptyIntervals (textgrid, sound,
-		GET_INTEGER (STRING_TIER_NUMBER), GET_INTEGER (U"Preserve times"));
-	thy classInfo = classCollection;   // YUCK
-	praat_new (thee.move(), U"dummy");
-END2 }
-
-FORM (TextGrid_Sound_extractIntervals, U"TextGrid & Sound: Extract intervals", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	BOOLEAN (U"Preserve times", false)
-	SENTENCE (U"Label text", U"")
-	OK2
-DO
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	autoSoundList thee = TextGrid_Sound_extractIntervalsWhere (textgrid, sound,
-		GET_INTEGER (STRING_TIER_NUMBER), kMelder_string_EQUAL_TO, GET_STRING (U"Label text"),
-		GET_INTEGER (U"Preserve times"));
-	thy classInfo = classCollection;   // YUCK
-	praat_new (thee.move(), GET_STRING (U"Label text"));
-END2 }
-
-FORM (TextGrid_Sound_extractIntervalsWhere, U"TextGrid & Sound: Extract intervals", nullptr) {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	BOOLEAN (U"Preserve times", false)
-	OPTIONMENU_ENUM (U"Extract every interval whose label...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"")
-	OK2
-DO
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	autoSoundList thee = TextGrid_Sound_extractIntervalsWhere (textgrid, sound,
-		GET_INTEGER (STRING_TIER_NUMBER),
-		GET_ENUM (kMelder_string, U"Extract every interval whose label..."),
-		GET_STRING (U"...the text"),
-		GET_INTEGER (U"Preserve times"));
-	thy classInfo = classCollection;   // YUCK
-	praat_new (thee.move(), GET_STRING (U"...the text"));
-END2 }
-
-DIRECT2 (TextGrid_Sound_scaleTimes) {
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	Function_scaleXTo (textgrid, sound -> xmin, sound -> xmax);
-	praat_dataChanged (textgrid);
-END2 }
+	GRAPHICS_TWO (TextGrid, Sound)
+		TextGrid_Sound_draw (me, you, GRAPHICS, fromTime, toTime, showBoundaries, useTextStyles, garnish);
+	GRAPHICS_TWO_END
+}
 
-DIRECT2 (TextGrid_Sound_cloneTimeDomain) {
-	TextGrid textgrid = nullptr;
-	Sound sound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) textgrid = (TextGrid) OBJECT;
-		if (CLASS == classSound) sound = (Sound) OBJECT;
-	}
-	sound -> x1 += textgrid -> xmin - sound -> xmin;
-	sound -> xmin = textgrid -> xmin;
-	sound -> xmax = textgrid -> xmax;
-	praat_dataChanged (sound);
-END2 }
+FORM (NEW1_TextGrid_Sound_extractAllIntervals, U"TextGrid & Sound: Extract all intervals", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	BOOLEAN4 (preserveTimes, U"Preserve times", false)
+	OK
+DO
+	CONVERT_TWO (TextGrid, Sound)
+		autoSoundList result = TextGrid_Sound_extractAllIntervals (me, you, tierNumber, preserveTimes);
+		result -> classInfo = classCollection;   // YUCK, in order to force automatic unpacking
+	CONVERT_TWO_END (U"dummy")
+}
+
+FORM (NEW1_TextGrid_Sound_extractNonemptyIntervals, U"TextGrid & Sound: Extract non-empty intervals", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	BOOLEAN4 (preserveTimes, U"Preserve times", false)
+	OK
+DO
+	CONVERT_TWO (TextGrid, Sound)
+		autoSoundList result = TextGrid_Sound_extractNonemptyIntervals (me, you, tierNumber, preserveTimes);
+		result -> classInfo = classCollection;   // YUCK, in order to force automatic unpacking
+	CONVERT_TWO_END (U"dummy")
+}
+
+FORM (NEW1_TextGrid_Sound_extractIntervals, U"TextGrid & Sound: Extract intervals", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	BOOLEAN4 (preserveTimes, U"Preserve times", false)
+	SENTENCE4 (labelText, U"Label text", U"")
+	OK
+DO
+	CONVERT_TWO (TextGrid, Sound)
+		autoSoundList result = TextGrid_Sound_extractIntervalsWhere (me, you,
+			tierNumber, kMelder_string_EQUAL_TO, labelText, preserveTimes);
+		result -> classInfo = classCollection;   // YUCK, in order to force automatic unpacking
+	CONVERT_TWO_END (U"dummy")
+}
+
+FORM (NEW1_TextGrid_Sound_extractIntervalsWhere, U"TextGrid & Sound: Extract intervals", nullptr) {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	BOOLEAN4 (preserveTimes, U"Preserve times", false)
+	OPTIONMENU_ENUM4 (extractEveryIntervalWhoseLabel___, U"Extract every interval whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (__theText, U"...the text", U"")
+	OK
+DO
+	CONVERT_TWO (TextGrid, Sound)
+		autoSoundList result = TextGrid_Sound_extractIntervalsWhere (me, you, tierNumber,
+			extractEveryIntervalWhoseLabel___, __theText, preserveTimes);
+		result -> classInfo = classCollection;   // YUCK, in order to force automatic unpacking
+	CONVERT_TWO_END (U"dummy")
+}
+
+DIRECT (MODIFY_TextGrid_Sound_scaleTimes) {
+	MODIFY_FIRST_OF_TWO (TextGrid, Sound)
+		Function_scaleXTo (me, your xmin, your xmax);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+DIRECT (MODIFY_TextGrid_Sound_cloneTimeDomain) {
+	MODIFY_FIRST_OF_TWO (Sound, TextGrid)
+		my x1 += your xmin - your xmin;
+		my xmin = your xmin;
+		my xmax = your xmax;
+	MODIFY_FIRST_OF_TWO_END
+}
 
-/***** SPELLINGCHECKER *****/
+// MARK: - SPELLINGCHECKER
 
-FORM (SpellingChecker_addNewWord, U"Add word to user dictionary", U"SpellingChecker") {
-	SENTENCE (U"New word", U"")
-	OK2
+FORM (MODIFY_SpellingChecker_addNewWord, U"Add word to user dictionary", U"SpellingChecker") {
+	SENTENCE4 (newWord, U"New word", U"")
+	OK
 DO
-	LOOP {
-		iam (SpellingChecker);
-		SpellingChecker_addNewWord (me, GET_STRING (U"New word"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (SpellingChecker)
+		SpellingChecker_addNewWord (me, newWord);
+	MODIFY_EACH_END
+}
 
-FORM (SpellingChecker_edit, U"Edit spelling checker", U"SpellingChecker") {
+FORM (WINDOW_SpellingChecker_viewAndEdit, U"Edit spelling checker", U"SpellingChecker") {
 	LABEL (U"", U"-- Syntax --")
-	SENTENCE (U"Forbidden strings", U"")
-	BOOLEAN (U"Check matching parentheses", false)
-	SENTENCE (U"Separating characters", U"")
-	BOOLEAN (U"Allow all parenthesized", false)
+	SENTENCE4 (forbiddenStrings, U"Forbidden strings", U"")
+	BOOLEAN4 (checkMatchingParentheses, U"Check matching parentheses", false)
+	SENTENCE4 (separatingCharacters, U"Separating characters", U"")
+	BOOLEAN4 (allowAllParenthesized, U"Allow all parenthesized", false)
 	LABEL (U"", U"-- Capitals --")
-	BOOLEAN (U"Allow all names", false)
-	SENTENCE (U"Name prefixes", U"")
-	BOOLEAN (U"Allow all abbreviations", false)
+	BOOLEAN4 (allowAllNames, U"Allow all names", false)
+	SENTENCE4 (namePrefixes, U"Name prefixes", U"")
+	BOOLEAN4 (allowAllAbbreviations, U"Allow all abbreviations", false)
 	LABEL (U"", U"-- Capitalization --")
-	BOOLEAN (U"Allow caps sentence-initially", false)
-	BOOLEAN (U"Allow caps after colon", false)
+	BOOLEAN4 (allowCapsSentenceInitially, U"Allow caps sentence-initially", false)
+	BOOLEAN4 (allowCapsAfterColon, U"Allow caps after colon", false)
 	LABEL (U"", U"-- Word parts --")
-	SENTENCE (U"Allow all words containing", U"")
-	SENTENCE (U"Allow all words starting with", U"")
-	SENTENCE (U"Allow all words ending in", U"")
-	OK2
-int IOBJECT;
-LOOP {
-	iam (SpellingChecker);
-	SET_STRING (U"Forbidden strings", my forbiddenStrings)
-	SET_INTEGER (U"Check matching parentheses", my checkMatchingParentheses)
-	SET_STRING (U"Separating characters", my separatingCharacters)
-	SET_INTEGER (U"Allow all parenthesized", my allowAllParenthesized)
-	SET_INTEGER (U"Allow all names", my allowAllNames)
-	SET_STRING (U"Name prefixes", my namePrefixes)
-	SET_INTEGER (U"Allow all abbreviations", my allowAllAbbreviations)
-	SET_INTEGER (U"Allow caps sentence-initially", my allowCapsSentenceInitially)
-	SET_INTEGER (U"Allow caps after colon", my allowCapsAfterColon)
-	SET_STRING (U"Allow all words containing", my allowAllWordsContaining)
-	SET_STRING (U"Allow all words starting with", my allowAllWordsStartingWith)
-	SET_STRING (U"Allow all words ending in", my allowAllWordsEndingIn)
+	SENTENCE4 (allowAllWordsContaining, U"Allow all words containing", U"")
+	SENTENCE4 (allowAllWordsStartingWith, U"Allow all words starting with", U"")
+	SENTENCE4 (allowAllWordsEndingIn, U"Allow all words ending in", U"")
+OK
+	FIND_ONE (SpellingChecker)
+		SET_STRING (U"Forbidden strings", my forbiddenStrings)
+		SET_INTEGER (U"Check matching parentheses", my checkMatchingParentheses)
+		SET_STRING (U"Separating characters", my separatingCharacters)
+		SET_INTEGER (U"Allow all parenthesized", my allowAllParenthesized)
+		SET_INTEGER (U"Allow all names", my allowAllNames)
+		SET_STRING (U"Name prefixes", my namePrefixes)
+		SET_INTEGER (U"Allow all abbreviations", my allowAllAbbreviations)
+		SET_INTEGER (U"Allow caps sentence-initially", my allowCapsSentenceInitially)
+		SET_INTEGER (U"Allow caps after colon", my allowCapsAfterColon)
+		SET_STRING (U"Allow all words containing", my allowAllWordsContaining)
+		SET_STRING (U"Allow all words starting with", my allowAllWordsStartingWith)
+		SET_STRING (U"Allow all words ending in", my allowAllWordsEndingIn)
+DO
+	MODIFY_EACH (SpellingChecker)
+		Melder_free (my forbiddenStrings); my forbiddenStrings = Melder_dup_f (forbiddenStrings);
+		my checkMatchingParentheses = checkMatchingParentheses;
+		Melder_free (my separatingCharacters); my separatingCharacters = Melder_dup_f (separatingCharacters);
+		my allowAllParenthesized = allowAllParenthesized;
+		my allowAllNames = allowAllNames;
+		Melder_free (my namePrefixes); my namePrefixes = Melder_dup_f (namePrefixes);
+		my allowAllAbbreviations = allowAllAbbreviations;
+		my allowCapsSentenceInitially = allowCapsSentenceInitially;
+		my allowCapsAfterColon = allowCapsAfterColon;
+		Melder_free (my allowAllWordsContaining); my allowAllWordsContaining = Melder_dup_f (allowAllWordsContaining);
+		Melder_free (my allowAllWordsStartingWith); my allowAllWordsStartingWith = Melder_dup_f (allowAllWordsStartingWith);
+		Melder_free (my allowAllWordsEndingIn); my allowAllWordsEndingIn = Melder_dup_f (allowAllWordsEndingIn);
+	MODIFY_EACH_END
 }
-DO
-	LOOP {
-		iam (SpellingChecker);
-		Melder_free (my forbiddenStrings); my forbiddenStrings = Melder_dup_f (GET_STRING (U"Forbidden strings"));
-		my checkMatchingParentheses = GET_INTEGER (U"Check matching parentheses");
-		Melder_free (my separatingCharacters); my separatingCharacters = Melder_dup_f (GET_STRING (U"Separating characters"));
-		my allowAllParenthesized = GET_INTEGER (U"Allow all parenthesized");
-		my allowAllNames = GET_INTEGER (U"Allow all names");
-		Melder_free (my namePrefixes); my namePrefixes = Melder_dup_f (GET_STRING (U"Name prefixes"));
-		my allowAllAbbreviations = GET_INTEGER (U"Allow all abbreviations");
-		my allowCapsSentenceInitially = GET_INTEGER (U"Allow caps sentence-initially");
-		my allowCapsAfterColon = GET_INTEGER (U"Allow caps after colon");
-		Melder_free (my allowAllWordsContaining); my allowAllWordsContaining = Melder_dup_f (GET_STRING (U"Allow all words containing"));
-		Melder_free (my allowAllWordsStartingWith); my allowAllWordsStartingWith = Melder_dup_f (GET_STRING (U"Allow all words starting with"));
-		Melder_free (my allowAllWordsEndingIn); my allowAllWordsEndingIn = Melder_dup_f (GET_STRING (U"Allow all words ending in"));
-		praat_dataChanged (me);
-	}
-END2 }
 
-DIRECT2 (SpellingChecker_extractWordList) {
-	LOOP {
-		iam (SpellingChecker);
-		autoWordList thee = SpellingChecker_extractWordList (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_SpellingChecker_extractWordList) {
+	CONVERT_EACH (SpellingChecker)
+		autoWordList result = SpellingChecker_extractWordList (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (SpellingChecker_extractUserDictionary) {
-	LOOP {
-		iam (SpellingChecker);
-		autoStringSet thee = SpellingChecker_extractUserDictionary (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_SpellingChecker_extractUserDictionary) {
+	CONVERT_EACH (SpellingChecker)
+		autoStringSet result = SpellingChecker_extractUserDictionary (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (SpellingChecker_isWordAllowed, U"Is word allowed?", U"SpellingChecker") {
-	SENTENCE (U"Word", U"")
-	OK2
+FORM (BOOLEAN_SpellingChecker_isWordAllowed, U"Is word allowed?", U"SpellingChecker") {
+	SENTENCE4 (word, U"Word", U"")
+	OK
 DO
-	LOOP {
-		iam (SpellingChecker);
-		bool isWordAllowed = SpellingChecker_isWordAllowed (me, GET_STRING (U"Word"));
-		Melder_information (isWordAllowed ? U"1 (allowed)" : U"0 (not allowed)");
-	}
-END2 }
+	NUMBER_ONE (SpellingChecker)
+		long result = SpellingChecker_isWordAllowed (me, word);
+	NUMBER_ONE_END (result ? U" (allowed)" : U" (not allowed)")
+}
 
-FORM (SpellingChecker_nextNotAllowedWord, U"Next not allowed word?", U"SpellingChecker") {
+FORM (STRING_SpellingChecker_nextNotAllowedWord, U"Next not allowed word?", U"SpellingChecker") {
 	LABEL (U"", U"Sentence:")
-	TEXTFIELD (U"sentence", U"")
-	INTEGER (U"Starting character", U"0")
-	OK2
-DO
-	LOOP {
-		iam (SpellingChecker);
-		char32 *sentence = GET_STRING (U"sentence");
-		long startingCharacter = GET_INTEGER (U"Starting character");
-		if (startingCharacter < 0) Melder_throw (U"Starting character should be 0 or positive.");
-		if (startingCharacter > (int) str32len (sentence)) Melder_throw (U"Starting character should not exceed end of sentence.");
-		char32 *nextNotAllowedWord = SpellingChecker_nextNotAllowedWord (me, sentence, & startingCharacter);
-		Melder_information (nextNotAllowedWord);
-	}
-END2 }
-
-DIRECT2 (SpellingChecker_replaceWordList) {
-	SpellingChecker spellingChecker = nullptr;
-	WordList wordList = nullptr;
-	LOOP {
-		if (CLASS == classSpellingChecker) spellingChecker = (SpellingChecker) OBJECT;
-		if (CLASS == classWordList) wordList = (WordList) OBJECT;
-		SpellingChecker_replaceWordList (spellingChecker, wordList);
-		praat_dataChanged (spellingChecker);
-	}
-END2 }
+	TEXTFIELD4 (sentence, U"sentence", U"")
+	INTEGER4 (startingCharacter, U"Starting character", U"0")
+	OK
+DO
+	STRING_ONE (SpellingChecker)
+		if (startingCharacter < 0)
+			Melder_throw (U"Your starting character should be 0 or positive.");
+		if (startingCharacter > (int) str32len (sentence))
+			Melder_throw (U"Your starting character should not exceed the end of the sentence.");
+		const char32 *result = SpellingChecker_nextNotAllowedWord (me, sentence, & startingCharacter);
+	STRING_ONE_END
+}
 
-DIRECT2 (SpellingChecker_replaceWordList_help) {
-	Melder_information (U"To replace the checker's word list\nby the contents of a Strings object:\n"
-		U"1. select the Strings;\n2. convert to a WordList object;\n3. select the SpellingChecker and the WordList;\n"
-		U"4. choose Replace.");
-END2 }
+DIRECT (MODIFY_SpellingChecker_replaceWordList) {
+	MODIFY_FIRST_OF_TWO (SpellingChecker, WordList)
+		SpellingChecker_replaceWordList (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-DIRECT2 (SpellingChecker_replaceUserDictionary) {
-	SpellingChecker spellingChecker = nullptr;
-	StringSet dictionary = nullptr;
-	LOOP {
-		if (CLASS == classSpellingChecker) spellingChecker = (SpellingChecker) OBJECT;
-		if (CLASS == classStringSet) dictionary = (StringSet) OBJECT;
-		SpellingChecker_replaceUserDictionary (spellingChecker, dictionary);
-	}
-END2 }
+DIRECT (HINT_SpellingChecker_replaceWordList_help) {
+	INFO_NONE
+		Melder_information (U"To replace the checker's word list\nby the contents of a Strings object:\n"
+			U"1. select the Strings;\n2. convert to a WordList object;\n3. select the SpellingChecker and the WordList;\n"
+			U"4. choose Replace.");
+	INFO_NONE_END
+}
 
-/***** TEXTGRID *****/
+DIRECT (MODIFY_SpellingChecker_replaceUserDictionary) {
+	MODIFY_FIRST_OF_TWO (SpellingChecker, StringSet)
+		SpellingChecker_replaceUserDictionary (me, you);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (TextGrid_countIntervalsWhere, U"Count intervals", U"TextGrid: Count intervals where...") {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Count intervals whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
-DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TextGrid);
-		long numberOfLabels = TextGrid_countIntervalsWhere (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Count intervals whose label"), text);
-		Melder_information (numberOfLabels, U" intervals");
-	}
-END2 }
+// MARK: - TEXTGRID
 
-FORM (TextGrid_countLabels, U"Count labels", U"TextGrid: Count labels...") {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	SENTENCE (U"Label text", U"a")
-	OK2
-DO
-	LOOP {
-		iam (TextGrid);
-		long numberOfLabels = TextGrid_countLabels (me, GET_INTEGER (STRING_TIER_NUMBER), GET_STRING (U"Label text"));
-		Melder_information (numberOfLabels, U" labels");
-	}
-END2 }
+// MARK: Save
 
-FORM (TextGrid_countPointsWhere, U"Count points", U"TextGrid: Count points where...") {
-	INTEGER (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Count points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
-DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TextGrid);
-		long numberOfLabels = TextGrid_countPointsWhere (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Count points whose label"), text);
-		Melder_information (numberOfLabels, U" points");
-	}
-END2 }
+FORM_SAVE (SAVE_TextGrid_writeToChronologicalTextFile, U"Text file", nullptr, nullptr) {
+	SAVE_ONE (TextGrid)
+		TextGrid_writeToChronologicalTextFile (me, file);
+	SAVE_ONE_END
+}
 
-FORM (TextGrid_downto_Table, U"TextGrid: Down to Table", nullptr) {
-	BOOLEAN (U"Include line number", false)
-	NATURAL (U"Time decimals", U"6")
-	BOOLEAN (U"Include tier names", true)
-	BOOLEAN (U"Include empty intervals", false)
-	OK2
-DO
-	LOOP {
-		iam (TextGrid);
-		autoTable thee = TextGrid_downto_Table (me, GET_INTEGER (U"Include line number"), GET_INTEGER (U"Time decimals"),
-			GET_INTEGER (U"Include tier names"), GET_INTEGER (U"Include empty intervals"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+// MARK: Help
 
-FORM (TextGrid_draw, U"TextGrid: Draw", nullptr) {
-	praat_dia_timeRange (dia);
-	BOOLEAN (U"Show boundaries", true)
-	BOOLEAN (U"Use text styles", true)
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TextGrid);
-		TextGrid_Sound_draw (me, nullptr, GRAPHICS,
-			GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Show boundaries"),
-			GET_INTEGER (U"Use text styles"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+DIRECT (HELP_TextGrid_help) {
+	HELP (U"TextGrid")
+}
 
-FORM (TextGrid_duplicateTier, U"TextGrid: Duplicate tier", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (U"Position", U"1 (= at top)")
-	WORD (U"Name", U"")
-	OK2
-DO
-	LOOP {
-		iam (TextGrid);
-		int itier = GET_INTEGER (STRING_TIER_NUMBER);
-		int position = GET_INTEGER (U"Position");
-		const char32 *name = GET_STRING (U"Name");
-		if (itier > my tiers->size) itier = my tiers->size;
-		{// scope
-			autoFunction newTier = Data_copy (my tiers->at [itier]);
-			Thing_setName (newTier.get(), name);
-			my tiers -> addItemAtPosition_move (newTier.move(), position);
-		}
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: View & Edit
 
 static void cb_TextGridEditor_publication (Editor /* editor */, autoDaata publication) {
 	/*
@@ -861,7 +702,7 @@ static void cb_TextGridEditor_publication (Editor /* editor */, autoDaata public
 		Melder_flushError ();
 	}
 }
-DIRECT2 (TextGrid_edit) {
+DIRECT (WINDOW_TextGrid_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a TextGrid from batch.");
 	Sound sound = nullptr;
 	LOOP {
@@ -874,11 +715,11 @@ DIRECT2 (TextGrid_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM (TextGrid_editWithCallback, U"TextGrid: View & Edit with callback", nullptr) {
-	SENTENCE (U"Callback text", U"r1")
-	OK2
+FORM (WINDOW_TextGrid_viewAndEditWithCallback, U"TextGrid: View & Edit with callback", nullptr) {
+	SENTENCE4 (callbackText, U"Callback text", U"r1")
+	OK
 DO
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a TextGrid from batch.");
 	Sound sound = nullptr;
@@ -887,14 +728,14 @@ DO
 	}
 	LOOP if (CLASS == classTextGrid) {
 		iam (TextGrid);
-		autoTextGridEditor editor = TextGridEditor_create (ID_AND_FULL_NAME, me, sound, true, nullptr, Melder_peek32to8 (GET_STRING (U"Callback text")));
+		autoTextGridEditor editor = TextGridEditor_create (ID_AND_FULL_NAME, me, sound, true, nullptr, Melder_peek32to8 (callbackText));
 		Editor_setPublicationCallback (editor.get(), cb_TextGridEditor_publication);
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-DIRECT2 (TextGrid_LongSound_edit) {
+DIRECT (WINDOW_TextGrid_LongSound_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a TextGrid from batch.");
 	LongSound longSound = nullptr;
 	int ilongSound = 0;
@@ -909,9 +750,9 @@ DIRECT2 (TextGrid_LongSound_edit) {
 		praat_installEditor2 (editor.get(), IOBJECT, ilongSound);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-DIRECT2 (TextGrid_SpellingChecker_edit) {
+DIRECT (WINDOW_TextGrid_SpellingChecker_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a TextGrid from batch.");
 	SpellingChecker spellingChecker = nullptr;
 	int ispellingChecker = 0;
@@ -927,9 +768,9 @@ DIRECT2 (TextGrid_SpellingChecker_edit) {
 		praat_installEditor2 (editor.get(), IOBJECT, ispellingChecker);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-DIRECT2 (TextGrid_LongSound_SpellingChecker_edit) {
+DIRECT (WINDOW_TextGrid_LongSound_SpellingChecker_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a TextGrid from batch.");
 	LongSound longSound = nullptr;
 	SpellingChecker spellingChecker = nullptr;
@@ -945,967 +786,958 @@ DIRECT2 (TextGrid_LongSound_SpellingChecker_edit) {
 		praat_installEditor3 (editor.get(), IOBJECT, ilongSound, ispellingChecker);
 		editor.releaseToUser();
 	}
-END2 }
+END }
+
+DIRECT (HINT_TextGrid_Sound_viewAndEdit) {
+	INFO_NONE
+		Melder_information (U"To include a copy of a Sound in your TextGrid window:\n"
+			U"   select a TextGrid and a Sound, and click \"View & Edit\".");
+	INFO_NONE_END
+}
+
+// MARK: Draw
 
-FORM (TextGrid_extractPart, U"TextGrid: Extract part", nullptr) {
-	REAL (U"left Time range (s)", U"0.0")
-	REAL (U"right Time range (s)", U"1.0")
-	BOOLEAN (U"Preserve times", false)
-	OK2
+FORM (GRAPHICS_TextGrid_draw, U"TextGrid: Draw", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	BOOLEAN4 (showBoundaries, U"Show boundaries", true)
+	BOOLEAN4 (useTextStyles, U"Use text styles", true)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		autoTextGrid thee = TextGrid_extractPart (me, GET_REAL (U"left Time range"), GET_REAL (U"right Time range"), GET_INTEGER (U"Preserve times"));
-		praat_new (thee.move(), my name, U"_part");
-	}
-END2 }
+	GRAPHICS_EACH (TextGrid)
+		TextGrid_Sound_draw (me, nullptr, GRAPHICS, fromTime, toTime, showBoundaries, useTextStyles, garnish);
+	GRAPHICS_EACH_END
+}
 
-static Function pr_TextGrid_peekTier (UiForm dia) {
-	int IOBJECT;
-	LOOP {
-		iam (TextGrid);
-		long tierNumber = GET_INTEGER (STRING_TIER_NUMBER);
-		if (tierNumber > my tiers->size)
-			Melder_throw (U"Tier number (", tierNumber, U") should not be larger than number of tiers (", my tiers->size, U").");
-		return my tiers->at [tierNumber];
-	}
-	return nullptr;   // should not occur
+DIRECT (HINT_TextGrid_Sound_draw) {
+	INFO_NONE
+		Melder_information (U"You can draw a TextGrid together with a Sound after selecting them both.");
+	INFO_NONE_END
+}
+
+DIRECT (HINT_TextGrid_Pitch_draw) {
+	INFO_NONE
+		Melder_information (U"You can draw a TextGrid together with a Pitch after selecting them both.");
+	INFO_NONE_END
+}
+
+// MARK: Tabulate
+
+FORM (LIST_TextGrid_list, U"TextGrid: List", nullptr) {
+	BOOLEAN4 (includeLineNumber, U"Include line number", false)
+	NATURAL4 (timeDecimals, U"Time decimals", U"6")
+	BOOLEAN4 (includeTierNames, U"Include tier names", true)
+	BOOLEAN4 (includeEmptyIntervals, U"Include empty intervals", false)
+	OK
+DO
+	INFO_ONE (TextGrid)
+		TextGrid_list (me, includeLineNumber, timeDecimals, includeTierNames, includeEmptyIntervals);
+	INFO_ONE_END
+}
+
+FORM (NEW_TextGrid_downto_Table, U"TextGrid: Down to Table", nullptr) {
+	BOOLEAN4 (includeLineNumber, U"Include line number", false)
+	NATURAL4 (timeDecimals, U"Time decimals", U"6")
+	BOOLEAN4 (includeTierNames, U"Include tier names", true)
+	BOOLEAN4 (includeEmptyIntervals, U"Include empty intervals", false)
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		autoTable result = TextGrid_downto_Table (me, includeLineNumber, timeDecimals,
+			includeTierNames, includeEmptyIntervals);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: Query
+
+DIRECT (INTEGER_TextGrid_getNumberOfTiers) {
+	NUMBER_ONE (TextGrid)
+		long result = my tiers->size;
+	NUMBER_ONE_END (U" tiers")
+}
+
+inline static void pr_TextGrid_checkTierNumber (TextGrid me, long tierNumber) {
+	if (tierNumber > my tiers->size)
+		Melder_throw (U"Your tier number (", tierNumber,
+			U") should not be greater than the number of tiers (", my tiers->size, U").");
 }
 
-static IntervalTier pr_TextGrid_peekIntervalTier (UiForm dia) {
-	Function tier = pr_TextGrid_peekTier (dia);
-	if (tier -> classInfo != classIntervalTier) Melder_throw (U"Tier should be interval tier.");
+inline static Function pr_TextGrid_peekTier (TextGrid me, long tierNumber) {
+	pr_TextGrid_checkTierNumber (me, tierNumber);
+	return my tiers->at [tierNumber];
+}
+
+FORM (STRING_TextGrid_getTierName, U"TextGrid: Get tier name", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
+DO
+	STRING_ONE (TextGrid)
+		Function tier = pr_TextGrid_peekTier (me, tierNumber);
+		const char32 *result = tier -> name;
+	STRING_ONE_END
+}
+
+FORM (BOOLEAN_TextGrid_isIntervalTier, U"TextGrid: Is interval tier?", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		Function tier = pr_TextGrid_peekTier (me, tierNumber);
+		long result = ( tier -> classInfo == classIntervalTier );
+	NUMBER_ONE_END (result ? U" (yes, tier " : U" (no, tier ", tierNumber,
+		result ? U" is an interval tier)" : U" is a point tier)")
+}
+
+static IntervalTier pr_TextGrid_peekIntervalTier (TextGrid me, long tierNumber) {
+	Function tier = pr_TextGrid_peekTier (me, tierNumber);
+	if (tier -> classInfo != classIntervalTier)
+		Melder_throw (U"Your tier should be an interval tier.");
 	return (IntervalTier) tier;
 }
 
-static TextTier pr_TextGrid_peekTextTier (UiForm dia) {
-	Function tier = pr_TextGrid_peekTier (dia);
-	if (! tier) return nullptr;
-	if (tier -> classInfo != classTextTier) Melder_throw (U"Tier should be point tier (TextTier).");
-	return (TextTier) tier;
+FORM (INTEGER_TextGrid_getNumberOfIntervals, U"TextGrid: Get number of intervals", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
+		long result = intervalTier -> intervals.size;
+	NUMBER_ONE_END (U" intervals")
 }
 
-static TextInterval pr_TextGrid_peekInterval (UiForm dia) {
-	int intervalNumber = GET_INTEGER (STRING_INTERVAL_NUMBER);
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
+static TextInterval pr_TextGrid_peekInterval (TextGrid me, long tierNumber, long intervalNumber) {
+	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
 	if (intervalNumber > intervalTier -> intervals.size) Melder_throw (U"Interval number too large.");
 	return intervalTier -> intervals.at [intervalNumber];
 }
 
-static TextPoint pr_TextGrid_peekPoint (UiForm dia) {	
-	long pointNumber = GET_INTEGER (STRING_POINT_NUMBER);
-	TextTier textTier = pr_TextGrid_peekTextTier (dia);
+FORM (REAL_TextGrid_getStartTimeOfInterval, U"TextGrid: Get start time of interval", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (intervalNumber, STRING_INTERVAL_NUMBER, U"1")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		TextInterval interval = pr_TextGrid_peekInterval (me, tierNumber, intervalNumber);
+		double result = interval -> xmin;
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_TextGrid_getEndTimeOfInterval, U"TextGrid: Get end time of interval", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (intervalNumber, STRING_INTERVAL_NUMBER, U"1")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		TextInterval interval = pr_TextGrid_peekInterval (me, tierNumber, intervalNumber);
+		double result = interval -> xmax;
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (STRING_TextGrid_getLabelOfInterval, U"TextGrid: Get label of interval", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (intervalNumber, STRING_INTERVAL_NUMBER, U"1")
+	OK
+DO
+	STRING_ONE (TextGrid)
+		TextInterval interval = pr_TextGrid_peekInterval (me, tierNumber, intervalNumber);
+		const char32 *result = interval -> text;
+	STRING_ONE_END
+}
+
+FORM (INTEGER_TextGrid_getIntervalAtTime, U"TextGrid: Get interval at time", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
+		long result = IntervalTier_timeToIndex (intervalTier, time);
+	NUMBER_ONE_END (U" (interval number)")
+}
+
+FORM (INTEGER_TextGrid_getLowIntervalAtTime, U"TextGrid: Get low interval at time", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
+		long result = IntervalTier_timeToHighIndex (intervalTier, time);
+	NUMBER_ONE_END (U" (low interval)")
+}
+
+FORM (INTEGER_TextGrid_getHighIntervalAtTime, U"TextGrid: Get high interval at time", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
+		long result = IntervalTier_timeToLowIndex (intervalTier, time);
+	NUMBER_ONE_END (U" (high interval)")
+}
+
+FORM (INTEGER_TextGrid_getIntervalEdgeFromTime, U"TextGrid: Get interval edge from time", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
+		long result = IntervalTier_hasTime (intervalTier, time);
+	NUMBER_ONE_END (U" (interval edge)")
+}
+
+FORM (INTEGER_TextGrid_getIntervalBoundaryFromTime, U"TextGrid: Get interval boundary from time", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (me, tierNumber);
+		long result = IntervalTier_hasBoundary (intervalTier, time);
+	NUMBER_ONE_END (U" (interval boundary)")
+}
+
+FORM (INTEGER_TextGrid_countIntervalsWhere, U"Count intervals", U"TextGrid: Count intervals where...") {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (countIntervalsWhoseLabel___, U"Count intervals whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		long result = TextGrid_countIntervalsWhere (me, tierNumber, countIntervalsWhoseLabel___, ___theText);
+	NUMBER_ONE_END (U" intervals containing ", ___theText);
+}
+
+static TextTier pr_TextGrid_peekTextTier (TextGrid me, long tierNumber) {
+	Function tier = pr_TextGrid_peekTier (me, tierNumber);
+	if (! tier) return nullptr;
+	if (tier -> classInfo != classTextTier) Melder_throw (U"Your tier should be a point tier (TextTier).");
+	return (TextTier) tier;
+}
+
+FORM (INTEGER_TextGrid_getNumberOfPoints, U"TextGrid: Get number of points", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		TextTier textTier = pr_TextGrid_peekTextTier (me, tierNumber);
+		long result = textTier -> points.size;
+	NUMBER_ONE_END (U" (points")
+}
+
+static TextPoint pr_TextGrid_peekPoint (TextGrid me, long tierNumber, long pointNumber) {
+	TextTier textTier = pr_TextGrid_peekTextTier (me, tierNumber);
 	if (pointNumber > textTier -> points.size) Melder_throw (U"Point number too large.");
 	return textTier -> points.at [pointNumber];
 }
 
-FORM (TextGrid_extractOneTier, U"TextGrid: Extract one tier", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
+FORM (REAL_TextGrid_getTimeOfPoint, U"TextGrid: Get time of point", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (pointNumber, STRING_POINT_NUMBER, U"1")
+	OK
 DO
-	Function tier = pr_TextGrid_peekTier (dia);   // a reference
-	autoTextGrid grid = TextGrid_createWithoutTiers (1e30, -1e30);
-	TextGrid_addTier_copy (grid.get(), tier);   // no transfer of tier ownership, because a copy is made
-	praat_new (grid.move(), tier -> name);
-END2 }
+	NUMBER_ONE (TextGrid)
+		TextPoint point = pr_TextGrid_peekPoint (me, tierNumber, pointNumber);
+		double result = point -> number;
+	NUMBER_ONE_END (U" seconds")
+}
 
-FORM (TextGrid_extractTier, U"TextGrid: Extract tier", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
+FORM (STRING_TextGrid_getLabelOfPoint, U"TextGrid: Get label of point", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (pointNumber, STRING_POINT_NUMBER, U"1")
+	OK
 DO
-	Function tier = pr_TextGrid_peekTier (dia);
-	autoFunction thee = Data_copy (tier);
-	praat_new (thee.move(), tier -> name);
-END2 }
+	STRING_ONE (TextGrid)
+		TextPoint point = pr_TextGrid_peekPoint (me, tierNumber, pointNumber);
+		const char32 *result = point -> mark;
+	STRING_ONE_END
+}
 
-DIRECT2 (TextGrid_genericize) {
-	LOOP {
-		iam (TextGrid);
-		TextGrid_genericize (me);
-		praat_dataChanged (me);
-	}
-END2 }
+FORM (INTEGER_TextGrid_getLowIndexFromTime, U"Get low index", U"AnyTier: Get low index from time...") {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		TextTier textTier = pr_TextGrid_peekTextTier (me, tierNumber);
+		long result = AnyTier_timeToLowIndex (textTier->asAnyTier(), time);
+	NUMBER_ONE_END (U" (low index)")
+}
 
-DIRECT2 (TextGrid_nativize) {
-	LOOP {
-		iam (TextGrid);
-		TextGrid_nativize (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (TextGrid_getHighIndexFromTime, U"Get high index", U"AnyTier: Get high index from time...") {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	TextTier textTier = pr_TextGrid_peekTextTier (dia);
-	long highIndex = AnyTier_timeToHighIndex (textTier->asAnyTier(), GET_REAL (U"Time"));
-	Melder_information (highIndex);
-END2 }
-
-FORM (TextGrid_getHighIntervalAtTime, U"TextGrid: Get high interval at time", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
-	long index = IntervalTier_timeToLowIndex (intervalTier, GET_REAL (U"Time"));
-	Melder_information (index);
-END2 }
-
-FORM (TextGrid_getIntervalBoundaryFromTime, U"TextGrid: Get interval boundary from time", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
-	long index = IntervalTier_hasBoundary (intervalTier, GET_REAL (U"Time"));
-	Melder_information (index);
-END2 }
-
-FORM (TextGrid_getIntervalEdgeFromTime, U"TextGrid: Get interval edge from time", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
-	long index = IntervalTier_hasTime (intervalTier, GET_REAL (U"Time"));
-	Melder_information (index);
-END2 }
-
-FORM (TextGrid_getLowIndexFromTime, U"Get low index", U"AnyTier: Get low index from time...") {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	TextTier textTier = pr_TextGrid_peekTextTier (dia);
-	long lowIndex = AnyTier_timeToLowIndex (textTier->asAnyTier(), GET_REAL (U"Time"));
-	Melder_information (lowIndex);
-END2 }
-
-FORM (TextGrid_getLowIntervalAtTime, U"TextGrid: Get low interval at time", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
-	long index = IntervalTier_timeToHighIndex (intervalTier, GET_REAL (U"Time"));
-	Melder_information (index);
-END2 }
-
-FORM (TextGrid_getNearestIndexFromTime, U"Get nearest index", U"AnyTier: Get nearest index from time...") {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	TextTier textTier = pr_TextGrid_peekTextTier (dia);
-	long nearestIndex = AnyTier_timeToNearestIndex (textTier->asAnyTier(), GET_REAL (U"Time"));
-	Melder_information (nearestIndex);
-END2 }
-
-FORM (TextGrid_getIntervalAtTime, U"TextGrid: Get interval at time", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
-DO
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
-	long index = IntervalTier_timeToIndex (intervalTier, GET_REAL (U"Time"));
-	Melder_information (index);
-END2 }
-
-FORM (TextGrid_getNumberOfIntervals, U"TextGrid: Get number of intervals", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
-DO
-	IntervalTier intervalTier = pr_TextGrid_peekIntervalTier (dia);
-	long numberOfIntervals = intervalTier -> intervals.size;
-	Melder_information (numberOfIntervals);
-END2 }
-
-DIRECT2 (TextGrid_getNumberOfTiers) {
-	LOOP {
-		iam (TextGrid);
-		long numberOfTiers = my tiers->size;
-		Melder_information (numberOfTiers);
-	}
-END2 }
-
-FORM (TextGrid_getStartingPoint, U"TextGrid: Get starting point", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_INTERVAL_NUMBER, U"1")
-	OK2
-DO
-	TextInterval interval = pr_TextGrid_peekInterval (dia);
-	double startingPoint = interval -> xmin;
-	Melder_informationReal (startingPoint, U"seconds");
-END2 }
-
-FORM (TextGrid_getEndPoint, U"TextGrid: Get end point", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_INTERVAL_NUMBER, U"1")
-	OK2
-DO
-	TextInterval interval = pr_TextGrid_peekInterval (dia);
-	double endPoint = interval -> xmax;
-	Melder_informationReal (endPoint, U"seconds");
-END2 }
-
-FORM (TextGrid_getLabelOfInterval, U"TextGrid: Get label of interval", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_INTERVAL_NUMBER, U"1")
-	OK2
-DO
-	TextInterval interval = pr_TextGrid_peekInterval (dia);
-	MelderInfo_open ();
-	MelderInfo_write (interval -> text);
-	MelderInfo_close ();
-END2 }
-
-FORM (TextGrid_getNumberOfPoints, U"TextGrid: Get number of points", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
-DO
-	TextTier textTier = pr_TextGrid_peekTextTier (dia);
-	long numberOfPoints = textTier -> points.size;
-	Melder_information (numberOfPoints);
-END2 }
-
-FORM (TextGrid_getTierName, U"TextGrid: Get tier name", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
-DO
-	Daata tier = pr_TextGrid_peekTier (dia);
-	Melder_information (tier -> name);
-END2 }
-
-FORM (TextGrid_getTimeOfPoint, U"TextGrid: Get time of point", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_POINT_NUMBER, U"1")
-	OK2
-DO
-	TextPoint point = pr_TextGrid_peekPoint (dia);
-	Melder_informationReal (point -> number, U"seconds");
-END2 }
-
-FORM (TextGrid_getLabelOfPoint, U"TextGrid: Get label of point", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_POINT_NUMBER, U"1")
-	OK2
-DO
-	TextPoint point = pr_TextGrid_peekPoint (dia);
-	Melder_information (point -> mark);
-END2 }
-
-DIRECT2 (TextGrid_help) {
-	Melder_help (U"TextGrid");
-END2 }
-
-FORM (TextGrid_insertBoundary, U"TextGrid: Insert boundary", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
+FORM (INTEGER_TextGrid_getHighIndexFromTime, U"Get high index", U"AnyTier: Get high index from time...") {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_insertBoundary (me, GET_INTEGER (STRING_TIER_NUMBER), GET_REAL (U"Time"));
-		praat_dataChanged (me);
-	}
-END2 }
+	NUMBER_ONE (TextGrid)
+		TextTier textTier = pr_TextGrid_peekTextTier (me, tierNumber);
+		long result = AnyTier_timeToHighIndex (textTier->asAnyTier(), time);
+	NUMBER_ONE_END (U" (high index)")
+}
 
-FORM (TextGrid_insertIntervalTier, U"TextGrid: Insert interval tier", nullptr) {
-	NATURAL (U"Position", U"1 (= at top)")
-	WORD (U"Name", U"")
-	OK2
+FORM (INTEGER_TextGrid_getNearestIndexFromTime, U"Get nearest index", U"AnyTier: Get nearest index from time...") {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		int position = GET_INTEGER (U"Position");
-		const char32 *name = GET_STRING (U"Name");
+	NUMBER_ONE (TextGrid)
+		TextTier textTier = pr_TextGrid_peekTextTier (me, tierNumber);
+		long result = AnyTier_timeToNearestIndex (textTier->asAnyTier(), time);
+	NUMBER_ONE_END (U" (nearest index)")
+}
+
+FORM (INTEGER_TextGrid_countPointsWhere, U"Count points", U"TextGrid: Count points where...") {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (countPointsWhoseLabel___, U"Count points whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		long result = TextGrid_countPointsWhere (me, tierNumber, countPointsWhoseLabel___, ___theText);
+	NUMBER_ONE_END (U" points containing ", ___theText);
+}
+
+FORM (INTEGER_TextGrid_countLabels, U"Count labels", U"TextGrid: Count labels...") {
+	INTEGER4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	SENTENCE4 (labelText, U"Label text", U"a")
+	OK
+DO
+	NUMBER_ONE (TextGrid)
+		long result = TextGrid_countLabels (me, tierNumber, labelText);
+	NUMBER_ONE_END (U" labels ", labelText)
+}
+
+// MARK: Modify
+
+DIRECT (MODIFY_TextGrid_convertToBackslashTrigraphs) {
+	MODIFY_EACH (TextGrid)
+		TextGrid_convertToBackslashTrigraphs (me);
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_TextGrid_convertToUnicode) {
+	MODIFY_EACH (TextGrid)
+		TextGrid_convertToUnicode (me);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TextGrid_insertIntervalTier, U"TextGrid: Insert interval tier", nullptr) {
+	NATURAL4 (position, U"Position", U"1 (= at top)")
+	WORD4 (name, U"Name", U"")
+	OK
+DO
+	MODIFY_EACH (TextGrid)
 		{// scope
 			autoIntervalTier tier = IntervalTier_create (my xmin, my xmax);
 			if (position > my tiers->size) position = my tiers->size + 1;
 			Thing_setName (tier.get(), name);
 			my tiers -> addItemAtPosition_move (tier.move(), position);
 		}
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (TextGrid_insertPoint, U"TextGrid: Insert point", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	LABEL (U"", U"Text:")
-	TEXTFIELD (U"text", U"")
-	OK2
-DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_insertPoint (me, GET_INTEGER (STRING_TIER_NUMBER), GET_REAL (U"Time"), GET_STRING (U"text"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_insertPointTier, U"TextGrid: Insert point tier", nullptr) {
-	NATURAL (U"Position", U"1 (= at top)")
-	WORD (U"Name", U"")
-	OK2
+FORM (MODIFY_TextGrid_insertPointTier, U"TextGrid: Insert point tier", nullptr) {
+	NATURAL4 (position, U"Position", U"1 (= at top)")
+	WORD4 (name, U"Name", U"")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		int position = GET_INTEGER (U"Position");
-		const char32 *name = GET_STRING (U"Name");
+	MODIFY_EACH (TextGrid)
 		{// scope
 			autoTextTier tier = TextTier_create (my xmin, my xmax);
 			if (position > my tiers->size) position = my tiers->size + 1;
 			Thing_setName (tier.get(), name);
 			my tiers -> addItemAtPosition_move (tier.move(), position);
 		}
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_isIntervalTier, U"TextGrid: Is interval tier?", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
+FORM (MODIFY_TextGrid_duplicateTier, U"TextGrid: Duplicate tier", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (position, U"Position", U"1 (= at top)")
+	WORD4 (name, U"Name", U"")
+	OK
 DO
-	Daata tier = pr_TextGrid_peekTier (dia);
-	if (tier -> classInfo == classIntervalTier) {
-		Melder_information (U"1 (yes, tier ", GET_INTEGER (STRING_TIER_NUMBER), U" is an interval tier)");
-	} else {
-		Melder_information (U"0 (no, tier ", GET_INTEGER (STRING_TIER_NUMBER), U" is a point tier)");
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		if (tierNumber > my tiers->size) tierNumber = my tiers->size;
+		{// scope
+			autoFunction newTier = Data_copy (my tiers->at [tierNumber]);
+			Thing_setName (newTier.get(), name);
+			my tiers -> addItemAtPosition_move (newTier.move(), position);
+		}
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_list, U"TextGrid: List", nullptr) {
-	BOOLEAN (U"Include line number", false)
-	NATURAL (U"Time decimals", U"6")
-	BOOLEAN (U"Include tier names", true)
-	BOOLEAN (U"Include empty intervals", false)
-	OK2
+FORM (MODIFY_TextGrid_removeTier, U"TextGrid: Remove tier", nullptr) {
+	NATURALVAR (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_list (me, GET_INTEGER (U"Include line number"), GET_INTEGER (U"Time decimals"),
-			GET_INTEGER (U"Include tier names"), GET_INTEGER (U"Include empty intervals"));
-	}
-END2 }
-
-DIRECT2 (TextGrids_concatenate) {
-	OrderedOf <structTextGrid> textGrids;
-	LOOP {
-		iam (TextGrid);
-		textGrids. addItem_ref (me);
-	}
-	autoTextGrid thee = TextGrids_concatenate (& textGrids);
-	praat_new (thee.move(), U"chain");
-END2 }
-
-DIRECT2 (TextGrids_merge) {
-	OrderedOf <structTextGrid> textGrids;
-	LOOP {
-		iam (TextGrid);
-		textGrids. addItem_ref (me);
-	}
-	autoTextGrid thee = TextGrids_merge (& textGrids);
-	praat_new (thee.move(), U"merged");
-END2 }
-
-DIRECT2 (info_TextGrid_Pitch_draw) {
-	Melder_information (U"You can draw a TextGrid together with a Pitch after selecting them both.");
-END2 }
+	MODIFY_EACH (TextGrid)
+		if (my tiers->size <= 1)
+			Melder_throw (U"Sorry, I refuse to remove the last tier.");
+		if (tierNumber > my tiers->size) tierNumber = my tiers->size;
+		my tiers -> removeItem (tierNumber);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_removeBoundaryAtTime, U"TextGrid: Remove boundary at time", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	REAL (U"Time (s)", U"0.5")
-	OK2
+FORM (MODIFY_TextGrid_insertBoundary, U"TextGrid: Insert boundary", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_removeBoundaryAtTime (me, GET_INTEGER (STRING_TIER_NUMBER), GET_REAL (U"Time"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		TextGrid_insertBoundary (me, tierNumber, time);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_getCentrePoints, U"TextGrid: Get centre points", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Get centre points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+FORM (MODIFY_TextGrid_removeLeftBoundary, U"TextGrid: Remove left boundary", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (intervalNumber, STRING_INTERVAL_NUMBER, U"2")
+	OK
 DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TextGrid);
-		autoPointProcess thee = TextGrid_getCentrePoints (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Get centre points whose label"), text);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		IntervalTier intervalTier;
+		if (tierNumber > my tiers->size)
+			Melder_throw (U"You cannot remove a boundary from tier ", tierNumber, U" of ", me,
+				U", because that TextGrid has only ", my tiers->size, U" tiers.");
+		intervalTier = (IntervalTier) my tiers->at [tierNumber];
+		if (intervalTier -> classInfo != classIntervalTier)
+			Melder_throw (U"You cannot remove a boundary from tier ", tierNumber, U" of ", me,
+				U", because that tier is a point tier instead of an interval tier.");
+		if (intervalNumber > intervalTier -> intervals.size)
+			Melder_throw (U"You cannot remove a boundary from interval ", intervalNumber, U" of tier ", tierNumber, U" of ", me,
+				U", because that tier has only ", intervalTier -> intervals.size, U" intervals.");
+		if (intervalNumber == 1)
+			Melder_throw (U"You cannot remove the left boundary from interval 1 of tier ", tierNumber, U" of ", me,
+				U", because this is at the left edge of the tier.");
+		IntervalTier_removeLeftBoundary (intervalTier, intervalNumber);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_getEndPoints, U"TextGrid: Get end points", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Get end points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+FORM (MODIFY_TextGrid_removeRightBoundary, U"TextGrid: Remove right boundary", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (intervalNumber, STRING_INTERVAL_NUMBER, U"2")
+	OK
 DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TextGrid);
-		autoPointProcess thee = TextGrid_getEndPoints (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Get end points whose label"), text);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		IntervalTier intervalTier;
+		if (tierNumber > my tiers->size)
+			Melder_throw (U"You cannot remove a boundary from tier ", tierNumber, U" of ", me,
+				U", because that TextGrid has only ", my tiers->size, U" tiers.");
+		intervalTier = (IntervalTier) my tiers->at [tierNumber];
+		if (intervalTier -> classInfo != classIntervalTier)
+			Melder_throw (U"You cannot remove a boundary from tier ", tierNumber, U" of ", me,
+				U", because that tier is a point tier instead of an interval tier.");
+		if (tierNumber > intervalTier -> intervals.size)
+			Melder_throw (U"You cannot remove a boundary from interval ", tierNumber, U" of tier ", tierNumber, U" of ", me,
+				U", because that tier has only ", intervalTier -> intervals.size, U" intervals.");
+		if (tierNumber == intervalTier -> intervals.size)
+			Melder_throw (U"You cannot remove the right boundary from interval ", tierNumber, U" of tier ", tierNumber, U" of ", me,
+				U", because this is at the right edge of the tier.");
+		IntervalTier_removeLeftBoundary (intervalTier, tierNumber + 1);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_getStartingPoints, U"TextGrid: Get starting points", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Get starting points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+FORM (MODIFY_TextGrid_removeBoundaryAtTime, U"TextGrid: Remove boundary at time", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
 DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TextGrid);
-		autoPointProcess thee = TextGrid_getStartingPoints (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Get starting points whose label"), text);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		TextGrid_removeBoundaryAtTime (me, tierNumber, time);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_getPoints, U"Get points", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Get points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+FORM (MODIFY_TextGrid_setIntervalText, U"TextGrid: Set interval text", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (intervalNumber, STRING_INTERVAL_NUMBER, U"1")
+	LABEL (U"", U"Text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TextGrid);
-		autoPointProcess thee = TextGrid_getPoints (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Get points whose label"), text);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
-
-FORM (TextGrid_getPoints_followed, U"Get points (followed)", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Get points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OPTIONMENU_ENUM (U"followed by a label that", kMelder_string, DEFAULT)
-	SENTENCE (U" ...the text", U"there")
-	OK2
-DO
-	const char32 *text = GET_STRING (U"...the text");
-	const char32 *following = GET_STRING (U" ...the text");
-	LOOP {
-		iam (TextGrid);
-		autoPointProcess thee = TextGrid_getPoints_followed (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Get points whose label"), text,
-			GET_ENUM (kMelder_string, U"followed by a label that"), following);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
-
-FORM (TextGrid_getPoints_preceded, U"Get points (preceded)", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Get points whose label", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"there")
-	OPTIONMENU_ENUM (U"preceded by a label that", kMelder_string, DEFAULT)
-	SENTENCE (U" ...the text", U"hi")
-	OK2
-DO
-	const char32 *text = GET_STRING (U"...the text");
-	const char32 *preceding = GET_STRING (U" ...the text");
-	LOOP {
-		iam (TextGrid);
-		autoPointProcess thee = TextGrid_getPoints_preceded (me, GET_INTEGER (STRING_TIER_NUMBER),
-			GET_ENUM (kMelder_string, U"Get points whose label"), text,
-			GET_ENUM (kMelder_string, U"preceded by a label that"), preceding);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		TextGrid_setIntervalText (me, tierNumber, intervalNumber, text);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_removeLeftBoundary, U"TextGrid: Remove left boundary", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_INTERVAL_NUMBER, U"2")
-	OK2
+FORM (MODIFY_TextGrid_insertPoint, U"TextGrid: Insert point", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	LABEL (U"", U"Text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	long itier = GET_INTEGER (STRING_TIER_NUMBER);
-	long iinterval = GET_INTEGER (STRING_INTERVAL_NUMBER);
-	LOOP {
-		iam (TextGrid);
-		IntervalTier intervalTier;
-		if (itier > my tiers->size)
-			Melder_throw (U"You cannot remove a boundary from tier ", itier, U" of ", me,
-				U", because that TextGrid has only ", my tiers->size, U" tiers.");
-		intervalTier = (IntervalTier) my tiers->at [itier];
-		if (intervalTier -> classInfo != classIntervalTier)
-			Melder_throw (U"You cannot remove a boundary from tier ", itier, U" of ", me,
-				U", because that tier is a point tier instead of an interval tier.");
-		if (iinterval > intervalTier -> intervals.size)
-			Melder_throw (U"You cannot remove a boundary from interval ", iinterval, U" of tier ", itier, U" of ", me,
-				U", because that tier has only ", intervalTier -> intervals.size, U" intervals.");
-		if (iinterval == 1)
-			Melder_throw (U"You cannot remove the left boundary from interval 1 of tier ", itier, U" of ", me,
-				U", because this is at the left edge of the tier.");
-		IntervalTier_removeLeftBoundary (intervalTier, iinterval);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		TextGrid_insertPoint (me, tierNumber, time, text);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_removePoint, U"TextGrid: Remove point", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_POINT_NUMBER, U"2")
-	OK2
+FORM (MODIFY_TextGrid_removePoint, U"TextGrid: Remove point", nullptr) {
+	NATURALVAR (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURALVAR (pointNumber, STRING_POINT_NUMBER, U"2")
+	OK
 DO
-	long itier = GET_INTEGER (STRING_TIER_NUMBER);
-	long ipoint = GET_INTEGER (STRING_POINT_NUMBER);
-	LOOP {
-		iam (TextGrid);
+	MODIFY_EACH (TextGrid)
 		TextTier pointTier;
-		if (itier > my tiers->size)
-			Melder_throw (U"You cannot remove a point from tier ", itier, U" of ", me,
+		if (tierNumber > my tiers->size)
+			Melder_throw (U"You cannot remove a point from tier ", tierNumber, U" of ", me,
 				U", because that TextGrid has only ", my tiers->size, U" tiers.");
-		pointTier = (TextTier) my tiers->at [itier];
+		pointTier = (TextTier) my tiers->at [tierNumber];
 		if (pointTier -> classInfo != classTextTier)
-			Melder_throw (U"You cannot remove a point from tier ", itier, U" of ", me,
+			Melder_throw (U"You cannot remove a point from tier ", tierNumber, U" of ", me,
 				U", because that tier is an interval tier instead of a point tier.");
-		if (ipoint > pointTier -> points.size)
-			Melder_throw (U"You cannot remove point ", ipoint, U" from tier ", itier, U" of ", me,
+		if (pointNumber > pointTier -> points.size)
+			Melder_throw (U"You cannot remove point ", pointNumber, U" from tier ", tierNumber, U" of ", me,
 				U", because that tier has only ", pointTier -> points.size, U" points.");
-		TextTier_removePoint (pointTier, ipoint);
-		praat_dataChanged (me);
-	}
-END2 }
+		TextTier_removePoint (pointTier, pointNumber);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_removePoints, U"Remove points", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OPTIONMENU_ENUM (U"Remove every point whose label...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+FORM (MODIFY_TextGrid_removePoints, U"Remove points", nullptr) {
+	NATURALVAR (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (removeEveryPointWhoseLabel___, U"Remove every point whose label...", kMelder_string, DEFAULT)
+	SENTENCEVAR (___theText, U"...the text", U"hi")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_removePoints (me, GET_INTEGER (STRING_TIER_NUMBER), GET_ENUM (kMelder_string, U"Remove every point whose label..."), GET_STRING (U"...the text"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		TextGrid_removePoints (me, tierNumber, removeEveryPointWhoseLabel___, ___theText);
+	MODIFY_EACH_END
+}
 
-FORM (TextGrid_removeRightBoundary, U"TextGrid: Remove right boundary", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_INTERVAL_NUMBER, U"1")
-	OK2
+FORM (MODIFY_TextGrid_setPointText, U"TextGrid: Set point text", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	NATURAL4 (pointNumber, STRING_POINT_NUMBER, U"1")
+	LABEL (U"", U"Text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	long itier = GET_INTEGER (STRING_TIER_NUMBER);
-	long iinterval = GET_INTEGER (STRING_INTERVAL_NUMBER);
-	LOOP {
-		iam (TextGrid);
-		IntervalTier intervalTier;
-		if (itier > my tiers->size)
-			Melder_throw (U"You cannot remove a boundary from tier ", itier, U" of ", me,
-				U", because that TextGrid has only ", my tiers->size, U" tiers.");
-		intervalTier = (IntervalTier) my tiers->at [itier];
-		if (intervalTier -> classInfo != classIntervalTier)
-			Melder_throw (U"You cannot remove a boundary from tier ", itier, U" of ", me,
-				U", because that tier is a point tier instead of an interval tier.");
-		if (iinterval > intervalTier -> intervals.size)
-			Melder_throw (U"You cannot remove a boundary from interval ", iinterval, U" of tier ", itier, U" of ", me,
-				U", because that tier has only ", intervalTier -> intervals.size, U" intervals.");
-		if (iinterval == intervalTier -> intervals.size)
-			Melder_throw (U"You cannot remove the right boundary from interval ", iinterval, U" of tier ", itier, U" of ", me,
-				U", because this is at the right edge of the tier.");
-		IntervalTier_removeLeftBoundary (intervalTier, iinterval + 1);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (TextGrid)
+		TextGrid_setPointText (me, tierNumber, pointNumber, text);
+	MODIFY_EACH_END
+}
+
+// MARK: Analyse
 
-FORM (TextGrid_removeTier, U"TextGrid: Remove tier", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	OK2
+FORM (NEW1_TextGrid_extractOneTier, U"TextGrid: Extract one tier", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		int itier = GET_INTEGER (STRING_TIER_NUMBER);
-		if (my tiers->size <= 1)
-			Melder_throw (U"Sorry, I refuse to remove the last tier.");
-		if (itier > my tiers->size) itier = my tiers->size;
-		my tiers -> removeItem (itier);
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (TextGrid)
+		Function tier = pr_TextGrid_peekTier (me, tierNumber);
+		autoTextGrid result = TextGrid_createWithoutTiers (1e30, -1e30);
+		TextGrid_addTier_copy (result.get(), tier);   // no transfer of tier ownership, because a copy is made
+	CONVERT_EACH_END (tier -> name)
+}
 
-DIRECT2 (info_TextGrid_Sound_edit) {
-	Melder_information (U"To include a copy of a Sound in your TextGrid editor:\n"
-		U"   select a TextGrid and a Sound, and click \"View & Edit\".");
-END2 }
+FORM (NEW1_TextGrid_extractTier, U"TextGrid: Extract tier", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		Function tier = pr_TextGrid_peekTier (me, tierNumber);
+		autoFunction result = Data_copy (tier);
+	CONVERT_EACH_END (tier -> name)
+}
 
-DIRECT2 (info_TextGrid_Sound_draw) {
-	Melder_information (U"You can draw a TextGrid together with a Sound after selecting them both.");
-END2 }
+FORM (NEW_TextGrid_extractPart, U"TextGrid: Extract part", nullptr) {
+	REAL4 (fromTime, U"left Time range (s)", U"0.0")
+	REAL4 (toTime, U"right Time range (s)", U"1.0")
+	BOOLEAN4 (preserveTimes, U"Preserve times", false)
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		autoTextGrid result = TextGrid_extractPart (me, fromTime, toTime, preserveTimes);
+	CONVERT_EACH_END (my name, U"_part")
+}
 
-FORM (TextGrid_setIntervalText, U"TextGrid: Set interval text", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_INTERVAL_NUMBER, U"1")
-	LABEL (U"", U"Text:")
-	TEXTFIELD (U"text", U"")
-	OK2
+FORM (NEW_TextGrid_getStartingPoints, U"TextGrid: Get starting points", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (getStartingPointsWhoseLabel___, U"Get starting points whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_setIntervalText (me, GET_INTEGER (STRING_TIER_NUMBER), GET_INTEGER (STRING_INTERVAL_NUMBER), GET_STRING (U"text"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (TextGrid)
+		autoPointProcess result = TextGrid_getStartingPoints (me, tierNumber, getStartingPointsWhoseLabel___, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-FORM (TextGrid_setPointText, U"TextGrid: Set point text", nullptr) {
-	NATURAL (STRING_TIER_NUMBER, U"1")
-	NATURAL (STRING_POINT_NUMBER, U"1")
-	LABEL (U"", U"Text:")
-	TEXTFIELD (U"text", U"")
-	OK2
+FORM (NEW_TextGrid_getEndPoints, U"TextGrid: Get end points", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (getEndPointsWhoseLabel___, U"Get end points whose label", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
 DO
-	LOOP {
-		iam (TextGrid);
-		TextGrid_setPointText (me, GET_INTEGER (STRING_TIER_NUMBER), GET_INTEGER (STRING_POINT_NUMBER), GET_STRING (U"text"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (TextGrid)
+		autoPointProcess result = TextGrid_getEndPoints (me, tierNumber, getEndPointsWhoseLabel___, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-FORM_WRITE2 (TextGrid_writeToChronologicalTextFile, U"Text file", nullptr, nullptr) {
-	LOOP {
-		iam (TextGrid);
-		TextGrid_writeToChronologicalTextFile (me, file);
-	}
-END2 }
+FORM (NEW_TextGrid_getCentrePoints, U"TextGrid: Get centre points", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (getCentrePointsWhoseLabel___, U"Get centre points whose label", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		autoPointProcess result = TextGrid_getCentrePoints (me, tierNumber, getCentrePointsWhoseLabel___, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-/***** TEXTGRID & ANYTIER *****/
+FORM (NEW_TextGrid_getPoints, U"Get points", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (getPointsWhoseLabel___, U"Get points whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		autoPointProcess result = TextGrid_getPoints (me, tierNumber, getPointsWhoseLabel___, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-DIRECT2 (TextGrid_AnyTier_append) {
-	TextGrid oldGrid = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) oldGrid = (TextGrid) OBJECT;
-	}
-	autoTextGrid newGrid = Data_copy (oldGrid);
-	LOOP if (OBJECT != oldGrid) {
-		iam (AnyTier);
-		TextGrid_addTier_copy (newGrid.get(), me);
-	}
-	praat_new (newGrid.move(), oldGrid -> name);
-END2 }
+FORM (NEW_TextGrid_getPoints_preceded, U"Get points (preceded)", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (getPointsWhoseLabel___, U"Get points whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"there")
+	OPTIONMENU_ENUM4 (___precededByALabelThat___, U"...preceded by a label that...", kMelder_string, DEFAULT)
+	SENTENCE4 (____theText, U" ...the text", U"hi")
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		autoPointProcess result = TextGrid_getPoints_preceded (me, tierNumber,
+			getPointsWhoseLabel___, ___theText, ___precededByALabelThat___, ____theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-/***** TEXTGRID & LONGSOUND *****/
+FORM (NEW_TextGrid_getPoints_followed, U"Get points (followed)", nullptr) {
+	NATURAL4 (tierNumber, STRING_TIER_NUMBER, U"1")
+	OPTIONMENU_ENUM4 (getPointsWhoseLabel___, U"Get points whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OPTIONMENU_ENUM4 (___followedByALabelThat___, U"...followed by a label that...", kMelder_string, DEFAULT)
+	SENTENCE4 (____theText, U" ...the text", U"there")
+	OK
+DO
+	CONVERT_EACH (TextGrid)
+		autoPointProcess result = TextGrid_getPoints_followed (me, tierNumber,
+			getPointsWhoseLabel___, ___theText, ___followedByALabelThat___, ____theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-DIRECT2 (TextGrid_LongSound_scaleTimes) {
-	TextGrid grid = nullptr;
-	LongSound longSound = nullptr;
-	LOOP {
-		if (CLASS == classTextGrid) grid = (TextGrid) OBJECT;
-		if (CLASS == classLongSound) longSound = (LongSound) OBJECT;
-	}
-	Function_scaleXTo (grid, longSound -> xmin, longSound -> xmax);
-	praat_dataChanged (grid);
-END2 }
+// MARK: Synthesize
+
+DIRECT (NEW1_TextGrids_merge) {
+	CONVERT_LIST (TextGrid)
+		autoTextGrid result = TextGrids_merge (& list);
+	CONVERT_LIST_END (U"merged")
+}
+
+DIRECT (NEW1_TextGrids_concatenate) {
+	CONVERT_LIST (TextGrid)
+		autoTextGrid result = TextGrids_concatenate (& list);
+	CONVERT_LIST_END (U"chain")
+}
+
+// MARK: - TEXTGRID & ANYTIER
+
+DIRECT (NEW1_TextGrid_IntervalTier_append) {
+	CONVERT_TWO (TextGrid, IntervalTier)
+		autoTextGrid result = Data_copy (me);
+		TextGrid_addTier_copy (result.get(), you);
+	CONVERT_TWO_END (my name)
+}
+
+DIRECT (NEW1_TextGrid_TextTier_append) {
+	CONVERT_TWO (TextGrid, TextTier)
+		autoTextGrid result = Data_copy (me);
+		TextGrid_addTier_copy (result.get(), you);
+	CONVERT_TWO_END (my name)
+}
+
+// MARK: - TEXTGRID & LONGSOUND
+
+DIRECT (MODIFY_TextGrid_LongSound_scaleTimes) {
+	MODIFY_FIRST_OF_TWO (TextGrid, LongSound)
+		Function_scaleXTo (me, your xmin, your xmax);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-/***** TEXTTIER *****/
+// MARK: - TEXTTIER
 
-FORM (TextTier_addPoint, U"TextTier: Add point", U"TextTier: Add point...") {
-	REAL (U"Time (s)", U"0.5")
-	SENTENCE (U"Text", U"")
-	OK2
+FORM (MODIFY_TextTier_addPoint, U"TextTier: Add point", U"TextTier: Add point...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	SENTENCE4 (text, U"Text", U"")
+	OK
 DO
-	LOOP {
-		iam (TextTier);
-		TextTier_addPoint (me, GET_REAL (U"Time"), GET_STRING (U"Text"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (TextTier)
+		TextTier_addPoint (me, time, text);
+	MODIFY_EACH_END
+}
 
-DIRECT2 (TextTier_downto_PointProcess) {
-	LOOP {
-		iam (TextTier);
-		autoPointProcess thee = AnyTier_downto_PointProcess (me->asAnyTier());
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_TextTier_downto_PointProcess) {
+	CONVERT_EACH (TextTier)
+		autoPointProcess result = AnyTier_downto_PointProcess (me->asAnyTier());
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TextTier_downto_TableOfReal, U"TextTier: Down to TableOfReal", nullptr) {
-	SENTENCE (U"Label", U"")
-	OK2
+FORM (NEW_TextTier_downto_TableOfReal, U"TextTier: Down to TableOfReal", nullptr) {
+	SENTENCE4 (label, U"Label", U"")
+	OK
 DO
-	LOOP {
-		iam (TextTier);
-		autoTableOfReal thee = TextTier_downto_TableOfReal (me, GET_STRING (U"Label"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (TextTier)
+		autoTableOfReal result = TextTier_downto_TableOfReal (me, label);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (TextTier_downto_TableOfReal_any) {
-	LOOP {
-		iam (TextTier);
-		autoTableOfReal thee = TextTier_downto_TableOfReal_any (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_TextTier_downto_TableOfReal_any) {
+	CONVERT_EACH (TextTier)
+		autoTableOfReal result = TextTier_downto_TableOfReal_any (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TextTier_getLabelOfPoint, U"Get label of point", nullptr) {
-	NATURAL (U"Point number", U"1")
-	OK2
+FORM (STRING_TextTier_getLabelOfPoint, U"Get label of point", nullptr) {
+	NATURAL4 (pointNumber, U"Point number", U"1")
+	OK
 DO
-	LOOP {
-		iam (TextTier);
-		long ipoint = GET_INTEGER (U"Point number");
-		if (ipoint > my points.size) Melder_throw (U"No such point.");
-		TextPoint point = my points.at [ipoint];
-		Melder_information (point -> mark);
-	}
-END2 }
+	STRING_ONE (TextTier)
+		if (pointNumber > my points.size) Melder_throw (U"No such point.");
+		TextPoint point = my points.at [pointNumber];
+		const char32 *result = point -> mark;
+	STRING_ONE_END
+}
 
-FORM (TextTier_getPoints, U"Get points", nullptr) {
-	SENTENCE (U"Text", U"")
-	OK2
+FORM (NEW_TextTier_getPoints, U"Get points", nullptr) {
+	SENTENCE4 (text, U"Text", U"")
+	OK
 DO
-	LOOP {
-		iam (TextTier);
-		autoPointProcess thee = TextTier_getPoints (me, GET_STRING (U"Text"));
-		praat_new (thee.move(), GET_STRING (U"Text"));
-	}
-END2 }
+	CONVERT_EACH (TextTier)
+		autoPointProcess result = TextTier_getPoints (me, text);
+	CONVERT_EACH_END (text)
+}
 
-DIRECT2 (TextTier_help) {
-	Melder_help (U"TextTier");
-END2 }
+DIRECT (HELP_TextTier_help) {
+	HELP (U"TextTier")
+}
 
-/***** WORDLIST *****/
+// MARK: - WORDLIST
 
-FORM (WordList_hasWord, U"Does word occur in list?", U"WordList") {
-	SENTENCE (U"Word", U"")
-	OK2
+FORM (BOOLEAN_WordList_hasWord, U"Does word occur in list?", U"WordList") {
+	SENTENCE4 (word, U"Word", U"")
+	OK
 DO
-	LOOP {
-		iam (WordList);
-		bool hasWord = WordList_hasWord (me, GET_STRING (U"Word"));
-		Melder_information (hasWord ? U"1" : U"0");
-	}
-END2 }
+	NUMBER_ONE (WordList)
+		long result = WordList_hasWord (me, word);
+	NUMBER_ONE_END (result ? U" (present)" : U" (absent)")
+}
 
-DIRECT2 (WordList_to_Strings) {
-	LOOP {
-		iam (WordList);
-		autoStrings thee = WordList_to_Strings (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_WordList_to_Strings) {
+	CONVERT_EACH (WordList)
+		autoStrings result = WordList_to_Strings (me);
+	CONVERT_EACH_END (my name)
+}
 
-DIRECT2 (WordList_upto_SpellingChecker) {
-	LOOP {
-		iam (WordList);
-		autoSpellingChecker thee = WordList_upto_SpellingChecker (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_WordList_upto_SpellingChecker) {
+	CONVERT_EACH (WordList)
+		autoSpellingChecker result = WordList_upto_SpellingChecker (me);
+	CONVERT_EACH_END (my name)
+}
 
 /***** buttons *****/
 
-void praat_TimeFunction_query_init (ClassInfo klas);
-void praat_TimeTier_query_init (ClassInfo klas);
-void praat_TimeTier_modify_init (ClassInfo klas);
-
-void praat_uvafon_TextGrid_init ();
 void praat_uvafon_TextGrid_init () {
 	Thing_recognizeClassByOtherName (classTextTier, U"MarkTier");
 
 	structTextGridEditor :: f_preferences ();
 
-	praat_addAction1 (classIntervalTier, 0, U"IntervalTier help", nullptr, 0, DO_IntervalTier_help);
-	praat_addAction1 (classIntervalTier, 1, U"Save as Xwaves label file...", nullptr, 0, DO_IntervalTier_writeToXwaves);
-	praat_addAction1 (classIntervalTier, 1, U"Write to Xwaves label file...", nullptr, praat_HIDDEN, DO_IntervalTier_writeToXwaves);
+	praat_addAction1 (classIntervalTier, 1, U"Save as Xwaves label file...", nullptr, 0, SAVE_IntervalTier_writeToXwaves);
+	praat_addAction1 (classIntervalTier, 1,   U"Write to Xwaves label file...", nullptr, praat_DEPRECATED_2011, SAVE_IntervalTier_writeToXwaves);
+	praat_addAction1 (classIntervalTier, 0, U"IntervalTier help", nullptr, 0, HELP_IntervalTier_help);
 	praat_addAction1 (classIntervalTier, 0, U"Collect", nullptr, 0, nullptr);
-	praat_addAction1 (classIntervalTier, 0, U"Into TextGrid", nullptr, 0, DO_AnyTier_into_TextGrid);
+	praat_addAction1 (classIntervalTier, 0, U"Into TextGrid", nullptr, 0, NEW1_AnyTier_into_TextGrid);
 	praat_addAction1 (classIntervalTier, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classIntervalTier, 0, U"Get starting points...", nullptr, 0, DO_IntervalTier_getStartingPoints);
-	praat_addAction1 (classIntervalTier, 0, U"Get centre points...", nullptr, 0, DO_IntervalTier_getCentrePoints);
-	praat_addAction1 (classIntervalTier, 0, U"Get end points...", nullptr, 0, DO_IntervalTier_getEndPoints);
+	praat_addAction1 (classIntervalTier, 0, U"Get starting points...", nullptr, 0, NEW_IntervalTier_getStartingPoints);
+	praat_addAction1 (classIntervalTier, 0, U"Get centre points...", nullptr, 0, NEW_IntervalTier_getCentrePoints);
+	praat_addAction1 (classIntervalTier, 0, U"Get end points...", nullptr, 0, NEW_IntervalTier_getEndPoints);
 	praat_addAction1 (classIntervalTier, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classIntervalTier, 0, U"Down to TableOfReal (any)", nullptr, 0, DO_IntervalTier_downto_TableOfReal_any);
-	praat_addAction1 (classIntervalTier, 0, U"Down to TableOfReal...", nullptr, 0, DO_IntervalTier_downto_TableOfReal);
+	praat_addAction1 (classIntervalTier, 0, U"Down to TableOfReal (any)", nullptr, 0, NEW_IntervalTier_downto_TableOfReal_any);
+	praat_addAction1 (classIntervalTier, 0, U"Down to TableOfReal...", nullptr, 0, NEW_IntervalTier_downto_TableOfReal);
 
-	praat_addAction1 (classLabel, 0, U"& Sound: To TextGrid?", nullptr, 0, DO_info_Label_Sound_to_TextGrid);
+	praat_addAction1 (classLabel, 0, U"& Sound: To TextGrid?", nullptr, 0, HINT_Label_Sound_to_TextGrid);
 
-	praat_addAction1 (classSpellingChecker, 1, U"View & Edit...", nullptr, praat_ATTRACTIVE, DO_SpellingChecker_edit);
-	praat_addAction1 (classSpellingChecker, 1, U"Edit...", nullptr, praat_HIDDEN, DO_SpellingChecker_edit);
+	praat_addAction1 (classSpellingChecker, 1, U"View & Edit...", nullptr, praat_ATTRACTIVE, WINDOW_SpellingChecker_viewAndEdit);
+	praat_addAction1 (classSpellingChecker, 1,   U"Edit...", U"*View & Edit...", praat_DEPRECATED_2011, WINDOW_SpellingChecker_viewAndEdit);
 	praat_addAction1 (classSpellingChecker, 0, U"Query", nullptr, 0, nullptr);
-	praat_addAction1 (classSpellingChecker, 1, U"Is word allowed...", nullptr, 0, DO_SpellingChecker_isWordAllowed);
-	praat_addAction1 (classSpellingChecker, 1, U"Next not allowed word...", nullptr, 0, DO_SpellingChecker_nextNotAllowedWord);
+	praat_addAction1 (classSpellingChecker, 1, U"Is word allowed...", nullptr, 0, BOOLEAN_SpellingChecker_isWordAllowed);
+	praat_addAction1 (classSpellingChecker, 1, U"Next not allowed word...", nullptr, 0, STRING_SpellingChecker_nextNotAllowedWord);
 	praat_addAction1 (classSpellingChecker, 0, U"Modify", nullptr, 0, nullptr);
-	praat_addAction1 (classSpellingChecker, 0, U"Add new word...", nullptr, 0, DO_SpellingChecker_addNewWord);
+	praat_addAction1 (classSpellingChecker, 0, U"Add new word...", nullptr, 0, MODIFY_SpellingChecker_addNewWord);
 	praat_addAction1 (classSpellingChecker, 0, U"Analyze", nullptr, 0, nullptr);
-	praat_addAction1 (classSpellingChecker, 0, U"Extract WordList", nullptr, 0, DO_SpellingChecker_extractWordList);
-	praat_addAction1 (classSpellingChecker, 0, U"Extract user dictionary", nullptr, 0, DO_SpellingChecker_extractUserDictionary);
-
-	praat_addAction1 (classTextGrid, 0, U"TextGrid help", nullptr, 0, DO_TextGrid_help);
-	praat_addAction1 (classTextGrid, 1, U"Save as chronological text file...", nullptr, 0, DO_TextGrid_writeToChronologicalTextFile);
-	praat_addAction1 (classTextGrid, 1, U"Write to chronological text file...", nullptr, praat_HIDDEN, DO_TextGrid_writeToChronologicalTextFile);
-	praat_addAction1 (classTextGrid, 1, U"View & Edit alone", nullptr, 0, DO_TextGrid_edit);
-	praat_addAction1 (classTextGrid, 1, U"View & Edit", nullptr, praat_HIDDEN, DO_TextGrid_edit);
-	praat_addAction1 (classTextGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_TextGrid_edit);
-	praat_addAction1 (classTextGrid, 1, U"View & Edit with Sound?", nullptr, praat_ATTRACTIVE, DO_info_TextGrid_Sound_edit);
+	praat_addAction1 (classSpellingChecker, 0, U"Extract WordList", nullptr, 0, NEW_SpellingChecker_extractWordList);
+	praat_addAction1 (classSpellingChecker, 0, U"Extract user dictionary", nullptr, 0, NEW_SpellingChecker_extractUserDictionary);
+
+	praat_addAction1 (classTextGrid, 1, U"Save as chronological text file...", nullptr, 0, SAVE_TextGrid_writeToChronologicalTextFile);
+	praat_addAction1 (classTextGrid, 1,   U"Write to chronological text file...", nullptr, praat_HIDDEN, SAVE_TextGrid_writeToChronologicalTextFile);
+	praat_addAction1 (classTextGrid, 0, U"TextGrid help", nullptr, 0, HELP_TextGrid_help);
+	praat_addAction1 (classTextGrid, 1, U"View & Edit alone", nullptr, 0, WINDOW_TextGrid_viewAndEdit);
+	praat_addAction1 (classTextGrid, 1,   U"View & Edit", U"*View & Edit alone", praat_DEPRECATED_2011, WINDOW_TextGrid_viewAndEdit);
+	praat_addAction1 (classTextGrid, 1,   U"Edit", U"*View & Edit alone", praat_DEPRECATED_2011, WINDOW_TextGrid_viewAndEdit);
+	praat_addAction1 (classTextGrid, 1, U"View & Edit with Sound?", nullptr, praat_ATTRACTIVE | praat_NO_API, HINT_TextGrid_Sound_viewAndEdit);
 	praat_addAction1 (classTextGrid, 0, U"Draw -", nullptr, 0, nullptr);
-	praat_addAction1 (classTextGrid, 0, U"Draw...", nullptr, 1, DO_TextGrid_draw);
-	praat_addAction1 (classTextGrid, 1, U"Draw with Sound?", nullptr, 1, DO_info_TextGrid_Sound_draw);
-	praat_addAction1 (classTextGrid, 1, U"Draw with Pitch?", nullptr, 1, DO_info_TextGrid_Pitch_draw);
-	praat_addAction1 (classTextGrid, 1, U"List...", nullptr, 0, DO_TextGrid_list);
-	praat_addAction1 (classTextGrid, 0, U"Down to Table...", nullptr, 0, DO_TextGrid_downto_Table);
+	praat_addAction1 (classTextGrid, 0, U"Draw...", nullptr, 1, GRAPHICS_TextGrid_draw);
+	praat_addAction1 (classTextGrid, 1, U"Draw with Sound?", nullptr, 1, HINT_TextGrid_Sound_draw);
+	praat_addAction1 (classTextGrid, 1, U"Draw with Pitch?", nullptr, 1, HINT_TextGrid_Pitch_draw);
+	praat_addAction1 (classTextGrid, 1, U"List...", nullptr, 0, LIST_TextGrid_list);
+	praat_addAction1 (classTextGrid, 0, U"Down to Table...", nullptr, 0, NEW_TextGrid_downto_Table);
 	praat_addAction1 (classTextGrid, 0, U"Query -", nullptr, 0, nullptr);
 		praat_TimeFunction_query_init (classTextGrid);
 		praat_addAction1 (classTextGrid, 1, U"-- query textgrid --", nullptr, 1, nullptr);
-		praat_addAction1 (classTextGrid, 1, U"Get number of tiers", nullptr, 1, DO_TextGrid_getNumberOfTiers);
-		praat_addAction1 (classTextGrid, 1, U"Get tier name...", nullptr, 1, DO_TextGrid_getTierName);
-		praat_addAction1 (classTextGrid, 1, U"Is interval tier...", nullptr, 1, DO_TextGrid_isIntervalTier);
+		praat_addAction1 (classTextGrid, 1, U"Get number of tiers", nullptr, 1, INTEGER_TextGrid_getNumberOfTiers);
+		praat_addAction1 (classTextGrid, 1, U"Get tier name...", nullptr, 1, STRING_TextGrid_getTierName);
+		praat_addAction1 (classTextGrid, 1, U"Is interval tier...", nullptr, 1, BOOLEAN_TextGrid_isIntervalTier);
 		praat_addAction1 (classTextGrid, 1, U"-- query tier --", nullptr, 1, nullptr);
 		praat_addAction1 (classTextGrid, 1, U"Query interval tier", nullptr, 1, nullptr);
-			praat_addAction1 (classTextGrid, 1, U"Get number of intervals...", nullptr, 2, DO_TextGrid_getNumberOfIntervals);
-			praat_addAction1 (classTextGrid, 1, U"Get starting point...", nullptr, 2, DO_TextGrid_getStartingPoint);
-			praat_addAction1 (classTextGrid, 1, U"Get start point...", nullptr, praat_HIDDEN + praat_DEPTH_2, DO_TextGrid_getStartingPoint);
-			praat_addAction1 (classTextGrid, 1, U"Get end point...", nullptr, 2, DO_TextGrid_getEndPoint);
-			praat_addAction1 (classTextGrid, 1, U"Get label of interval...", nullptr, 2, DO_TextGrid_getLabelOfInterval);
-			praat_addAction1 (classTextGrid, 1, U"-- query interval from time --", nullptr, 2, nullptr);
-			praat_addAction1 (classTextGrid, 1, U"Get interval at time...", nullptr, 2, DO_TextGrid_getIntervalAtTime);
-			praat_addAction1 (classTextGrid, 1, U"Get low interval at time...", nullptr, 2, DO_TextGrid_getLowIntervalAtTime);
-			praat_addAction1 (classTextGrid, 1, U"Get high interval at time...", nullptr, 2, DO_TextGrid_getHighIntervalAtTime);
-			praat_addAction1 (classTextGrid, 1, U"Get interval edge from time...", nullptr, 2, DO_TextGrid_getIntervalEdgeFromTime);
-			praat_addAction1 (classTextGrid, 1, U"Get interval boundary from time...", nullptr, 2, DO_TextGrid_getIntervalBoundaryFromTime);
+			praat_addAction1 (classTextGrid, 1, U"Get number of intervals...", nullptr, praat_DEPTH_2, INTEGER_TextGrid_getNumberOfIntervals);
+			praat_addAction1 (classTextGrid, 1, U"Get start time of interval...", nullptr, praat_DEPTH_2, REAL_TextGrid_getStartTimeOfInterval);
+			praat_addAction1 (classTextGrid, 1,   U"Get starting point...", U"*Get start time of interval...", praat_DEPTH_2 | praat_DEPRECATED_2016, REAL_TextGrid_getStartTimeOfInterval);
+			praat_addAction1 (classTextGrid, 1,   U"Get start point...", U"*Get start time of interval...", praat_DEPTH_2 | praat_DEPRECATED_2016, REAL_TextGrid_getStartTimeOfInterval);
+			praat_addAction1 (classTextGrid, 1, U"Get end time of interval...", nullptr, praat_DEPTH_2, REAL_TextGrid_getEndTimeOfInterval);
+			praat_addAction1 (classTextGrid, 1,   U"Get end point...", U"*Get end time of interval...", praat_DEPTH_2 | praat_DEPRECATED_2016, REAL_TextGrid_getEndTimeOfInterval);
+			praat_addAction1 (classTextGrid, 1, U"Get label of interval...", nullptr, praat_DEPTH_2, STRING_TextGrid_getLabelOfInterval);
+			praat_addAction1 (classTextGrid, 1, U"-- query interval from time --", nullptr, praat_DEPTH_2, nullptr);
+			praat_addAction1 (classTextGrid, 1, U"Get interval at time...", nullptr, 2, INTEGER_TextGrid_getIntervalAtTime);
+			praat_addAction1 (classTextGrid, 1, U"Get low interval at time...", nullptr, 2, INTEGER_TextGrid_getLowIntervalAtTime);
+			praat_addAction1 (classTextGrid, 1, U"Get high interval at time...", nullptr, 2, INTEGER_TextGrid_getHighIntervalAtTime);
+			praat_addAction1 (classTextGrid, 1, U"Get interval edge from time...", nullptr, 2, INTEGER_TextGrid_getIntervalEdgeFromTime);
+			praat_addAction1 (classTextGrid, 1, U"Get interval boundary from time...", nullptr, 2, INTEGER_TextGrid_getIntervalBoundaryFromTime);
 			praat_addAction1 (classTextGrid, 1, U"-- query interval labels --", nullptr, 2, nullptr);
-			praat_addAction1 (classTextGrid, 1, U"Count intervals where...", nullptr, 2, DO_TextGrid_countIntervalsWhere);
+			praat_addAction1 (classTextGrid, 1, U"Count intervals where...", nullptr, 2, INTEGER_TextGrid_countIntervalsWhere);
 		praat_addAction1 (classTextGrid, 1, U"Query point tier", nullptr, 1, nullptr);
-			praat_addAction1 (classTextGrid, 1, U"Get number of points...", nullptr, 2, DO_TextGrid_getNumberOfPoints);
-			praat_addAction1 (classTextGrid, 1, U"Get time of point...", nullptr, 2, DO_TextGrid_getTimeOfPoint);
-			praat_addAction1 (classTextGrid, 1, U"Get label of point...", nullptr, 2, DO_TextGrid_getLabelOfPoint);
+			praat_addAction1 (classTextGrid, 1, U"Get number of points...", nullptr, 2, INTEGER_TextGrid_getNumberOfPoints);
+			praat_addAction1 (classTextGrid, 1, U"Get time of point...", nullptr, 2, REAL_TextGrid_getTimeOfPoint);
+			praat_addAction1 (classTextGrid, 1, U"Get label of point...", nullptr, 2, STRING_TextGrid_getLabelOfPoint);
 			praat_addAction1 (classTextGrid, 1, U"-- query point from time --", nullptr, 2, nullptr);
-			praat_addAction1 (classTextGrid, 1, U"Get low index from time...", nullptr, 2, DO_TextGrid_getLowIndexFromTime);
-			praat_addAction1 (classTextGrid, 1, U"Get high index from time...", nullptr, 2, DO_TextGrid_getHighIndexFromTime);
-			praat_addAction1 (classTextGrid, 1, U"Get nearest index from time...", nullptr, 2, DO_TextGrid_getNearestIndexFromTime);
+			praat_addAction1 (classTextGrid, 1, U"Get low index from time...", nullptr, 2, INTEGER_TextGrid_getLowIndexFromTime);
+			praat_addAction1 (classTextGrid, 1, U"Get high index from time...", nullptr, 2, INTEGER_TextGrid_getHighIndexFromTime);
+			praat_addAction1 (classTextGrid, 1, U"Get nearest index from time...", nullptr, 2, INTEGER_TextGrid_getNearestIndexFromTime);
 			praat_addAction1 (classTextGrid, 1, U"-- query point labels --", nullptr, 2, nullptr);
-			praat_addAction1 (classTextGrid, 1, U"Count points where...", nullptr, 2, DO_TextGrid_countPointsWhere);
-		praat_addAction1 (classTextGrid, 1, U"-- query labels --", nullptr, praat_HIDDEN + praat_DEPTH_1, nullptr);
-		praat_addAction1 (classTextGrid, 1, U"Count labels...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_TextGrid_countLabels);   // hidden 2015
+			praat_addAction1 (classTextGrid, 1, U"Count points where...", nullptr, 2, INTEGER_TextGrid_countPointsWhere);
+		praat_addAction1 (classTextGrid, 1, U"-- query labels --", nullptr, praat_DEPTH_1 | praat_DEPRECATED_2015, nullptr);
+		praat_addAction1 (classTextGrid, 1, U"Count labels...", nullptr, praat_DEPTH_1 | praat_DEPRECATED_2015, INTEGER_TextGrid_countLabels);
 	praat_addAction1 (classTextGrid, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classTextGrid, 0, U"Convert to backslash trigraphs", nullptr, 1, DO_TextGrid_genericize);
-		praat_addAction1 (classTextGrid, 0, U"Genericize", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_TextGrid_genericize);   // hidden 2007
-		praat_addAction1 (classTextGrid, 0, U"Convert to Unicode", nullptr, 1, DO_TextGrid_nativize);
-		praat_addAction1 (classTextGrid, 0, U"Nativize", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_TextGrid_nativize);   // hidden 2007
+		praat_addAction1 (classTextGrid, 0, U"Convert to backslash trigraphs", nullptr, 1, MODIFY_TextGrid_convertToBackslashTrigraphs);
+		praat_addAction1 (classTextGrid, 0, U"Convert to Unicode", nullptr, 1, MODIFY_TextGrid_convertToUnicode);
 		praat_TimeFunction_modify_init (classTextGrid);
 		praat_addAction1 (classTextGrid, 0, U"-- modify tiers --", nullptr, 1, nullptr);
-		praat_addAction1 (classTextGrid, 0, U"Insert interval tier...", nullptr, 1, DO_TextGrid_insertIntervalTier);
-		praat_addAction1 (classTextGrid, 0, U"Insert point tier...", nullptr, 1, DO_TextGrid_insertPointTier);
-		praat_addAction1 (classTextGrid, 0, U"Duplicate tier...", nullptr, 1, DO_TextGrid_duplicateTier);
-		praat_addAction1 (classTextGrid, 0, U"Remove tier...", nullptr, 1, DO_TextGrid_removeTier);
+		praat_addAction1 (classTextGrid, 0, U"Insert interval tier...", nullptr, 1, MODIFY_TextGrid_insertIntervalTier);
+		praat_addAction1 (classTextGrid, 0, U"Insert point tier...", nullptr, 1, MODIFY_TextGrid_insertPointTier);
+		praat_addAction1 (classTextGrid, 0, U"Duplicate tier...", nullptr, 1, MODIFY_TextGrid_duplicateTier);
+		praat_addAction1 (classTextGrid, 0, U"Remove tier...", nullptr, 1, MODIFY_TextGrid_removeTier);
 		praat_addAction1 (classTextGrid, 1, U"-- modify tier --", nullptr, 1, nullptr);
 		praat_addAction1 (classTextGrid, 0, U"Modify interval tier", nullptr, 1, nullptr);
-			praat_addAction1 (classTextGrid, 0, U"Insert boundary...", nullptr, 2, DO_TextGrid_insertBoundary);
-			praat_addAction1 (classTextGrid, 0, U"Remove left boundary...", nullptr, 2, DO_TextGrid_removeLeftBoundary);
-			praat_addAction1 (classTextGrid, 0, U"Remove right boundary...", nullptr, 2, DO_TextGrid_removeRightBoundary);
-			praat_addAction1 (classTextGrid, 0, U"Remove boundary at time...", nullptr, 2, DO_TextGrid_removeBoundaryAtTime);
-			praat_addAction1 (classTextGrid, 0, U"Set interval text...", nullptr, 2, DO_TextGrid_setIntervalText);
+			praat_addAction1 (classTextGrid, 0, U"Insert boundary...", nullptr, 2, MODIFY_TextGrid_insertBoundary);
+			praat_addAction1 (classTextGrid, 0, U"Remove left boundary...", nullptr, 2, MODIFY_TextGrid_removeLeftBoundary);
+			praat_addAction1 (classTextGrid, 0, U"Remove right boundary...", nullptr, 2, MODIFY_TextGrid_removeRightBoundary);
+			praat_addAction1 (classTextGrid, 0, U"Remove boundary at time...", nullptr, 2, MODIFY_TextGrid_removeBoundaryAtTime);
+			praat_addAction1 (classTextGrid, 0, U"Set interval text...", nullptr, 2, MODIFY_TextGrid_setIntervalText);
 		praat_addAction1 (classTextGrid, 0, U"Modify point tier", nullptr, 1, nullptr);
-			praat_addAction1 (classTextGrid, 0, U"Insert point...", nullptr, 2, DO_TextGrid_insertPoint);
-			praat_addAction1 (classTextGrid, 0, U"Remove point...", nullptr, 2, DO_TextGrid_removePoint);
-			praat_addAction1 (classTextGrid, 0, U"Remove points...", nullptr, 2, DO_TextGrid_removePoints);
-			praat_addAction1 (classTextGrid, 0, U"Set point text...", nullptr, 2, DO_TextGrid_setPointText);
+			praat_addAction1 (classTextGrid, 0, U"Insert point...", nullptr, 2, MODIFY_TextGrid_insertPoint);
+			praat_addAction1 (classTextGrid, 0, U"Remove point...", nullptr, 2, MODIFY_TextGrid_removePoint);
+			praat_addAction1 (classTextGrid, 0, U"Remove points...", nullptr, 2, MODIFY_TextGrid_removePoints);
+			praat_addAction1 (classTextGrid, 0, U"Set point text...", nullptr, 2, MODIFY_TextGrid_setPointText);
 praat_addAction1 (classTextGrid, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classTextGrid, 1, U"Extract one tier...", nullptr, 0, DO_TextGrid_extractOneTier);
-	praat_addAction1 (classTextGrid, 1, U"Extract tier...", nullptr, praat_HIDDEN, DO_TextGrid_extractTier);   // hidden 2010
-	praat_addAction1 (classTextGrid, 1, U"Extract part...", nullptr, 0, DO_TextGrid_extractPart);
-	praat_addAction1 (classTextGrid, 1, U"Analyse interval tier -", nullptr, 0, nullptr);
-		praat_addAction1 (classTextGrid, 1, U"Get starting points...", nullptr, 1, DO_TextGrid_getStartingPoints);
-		praat_addAction1 (classTextGrid, 1, U"Get end points...", nullptr, 1, DO_TextGrid_getEndPoints);
-		praat_addAction1 (classTextGrid, 1, U"Get centre points...", nullptr, 1, DO_TextGrid_getCentrePoints);
-	praat_addAction1 (classTextGrid, 1, U"Analyse point tier -", nullptr, 0, nullptr);
-		praat_addAction1 (classTextGrid, 1, U"Get points...", nullptr, 1, DO_TextGrid_getPoints);
-		praat_addAction1 (classTextGrid, 1, U"Get points (preceded)...", nullptr, 1, DO_TextGrid_getPoints_preceded);
-		praat_addAction1 (classTextGrid, 1, U"Get points (followed)...", nullptr, 1, DO_TextGrid_getPoints_followed);
+	praat_addAction1 (classTextGrid, 0, U"Extract one tier...", nullptr, 0, NEW1_TextGrid_extractOneTier);
+	praat_addAction1 (classTextGrid, 0,   U"Extract tier...", U"*Extract one tier...", praat_DEPRECATED_2010, NEW1_TextGrid_extractTier);
+	praat_addAction1 (classTextGrid, 0, U"Extract part...", nullptr, 0, NEW_TextGrid_extractPart);
+	praat_addAction1 (classTextGrid, 0, U"Analyse interval tier -", nullptr, 0, nullptr);
+		praat_addAction1 (classTextGrid, 0, U"Get starting points...", nullptr, 1, NEW_TextGrid_getStartingPoints);
+		praat_addAction1 (classTextGrid, 0, U"Get end points...", nullptr, 1, NEW_TextGrid_getEndPoints);
+		praat_addAction1 (classTextGrid, 0, U"Get centre points...", nullptr, 1, NEW_TextGrid_getCentrePoints);
+	praat_addAction1 (classTextGrid, 0, U"Analyse point tier -", nullptr, 0, nullptr);
+		praat_addAction1 (classTextGrid, 0, U"Get points...", nullptr, 1, NEW_TextGrid_getPoints);
+		praat_addAction1 (classTextGrid, 0, U"Get points (preceded)...", nullptr, 1, NEW_TextGrid_getPoints_preceded);
+		praat_addAction1 (classTextGrid, 0, U"Get points (followed)...", nullptr, 1, NEW_TextGrid_getPoints_followed);
 praat_addAction1 (classTextGrid, 0, U"Synthesize", nullptr, 0, nullptr);
-	praat_addAction1 (classTextGrid, 0, U"Merge", nullptr, 0, DO_TextGrids_merge);
-	praat_addAction1 (classTextGrid, 0, U"Concatenate", nullptr, 0, DO_TextGrids_concatenate);
+	praat_addAction1 (classTextGrid, 0, U"Merge", nullptr, 0, NEW1_TextGrids_merge);
+	praat_addAction1 (classTextGrid, 0, U"Concatenate", nullptr, 0, NEW1_TextGrids_concatenate);
 
-	praat_addAction1 (classTextTier, 0, U"TextTier help", nullptr, 0, DO_TextTier_help);
+	praat_addAction1 (classTextTier, 0, U"TextTier help", nullptr, 0, HELP_TextTier_help);
 	praat_addAction1 (classTextTier, 0, U"Query -", nullptr, 0, nullptr);
 		praat_TimeTier_query_init (classTextTier);
-		praat_addAction1 (classTextTier, 0, U"Get label of point...", nullptr, 1, DO_TextTier_getLabelOfPoint);
+		praat_addAction1 (classTextTier, 0, U"Get label of point...", nullptr, 1, STRING_TextTier_getLabelOfPoint);
 	praat_addAction1 (classTextTier, 0, U"Modify -", nullptr, 0, nullptr);
 		praat_TimeTier_modify_init (classTextTier);
-		praat_addAction1 (classTextTier, 0, U"Add point...", nullptr, 1, DO_TextTier_addPoint);
+		praat_addAction1 (classTextTier, 0, U"Add point...", nullptr, 1, MODIFY_TextTier_addPoint);
 	praat_addAction1 (classTextTier, 0, U"Analyse", nullptr, 0, nullptr);
-	praat_addAction1 (classTextTier, 0, U"Get points...", nullptr, 0, DO_TextTier_getPoints);
+	praat_addAction1 (classTextTier, 0, U"Get points...", nullptr, 0, NEW_TextTier_getPoints);
 	praat_addAction1 (classTextTier, 0, U"Collect", nullptr, 0, nullptr);
-	praat_addAction1 (classTextTier, 0, U"Into TextGrid", nullptr, 0, DO_AnyTier_into_TextGrid);
+	praat_addAction1 (classTextTier, 0, U"Into TextGrid", nullptr, 0, NEW1_AnyTier_into_TextGrid);
 	praat_addAction1 (classTextTier, 0, U"Convert", nullptr, 0, nullptr);
-	praat_addAction1 (classTextTier, 0, U"Down to PointProcess", nullptr, 0, DO_TextTier_downto_PointProcess);
-	praat_addAction1 (classTextTier, 0, U"Down to TableOfReal (any)", nullptr, 0, DO_TextTier_downto_TableOfReal_any);
-	praat_addAction1 (classTextTier, 0, U"Down to TableOfReal...", nullptr, 0, DO_TextTier_downto_TableOfReal);
+	praat_addAction1 (classTextTier, 0, U"Down to PointProcess", nullptr, 0, NEW_TextTier_downto_PointProcess);
+	praat_addAction1 (classTextTier, 0, U"Down to TableOfReal (any)", nullptr, 0, NEW_TextTier_downto_TableOfReal_any);
+	praat_addAction1 (classTextTier, 0, U"Down to TableOfReal...", nullptr, 0, NEW_TextTier_downto_TableOfReal);
 
 	praat_addAction1 (classWordList, 0, U"Query", nullptr, 0, nullptr);
-		praat_addAction1 (classWordList, 1, U"Has word...", nullptr, 0, DO_WordList_hasWord);
+		praat_addAction1 (classWordList, 1, U"Has word...", nullptr, 0, BOOLEAN_WordList_hasWord);
 	praat_addAction1 (classWordList, 0, U"Analyze", nullptr, 0, nullptr);
-		praat_addAction1 (classWordList, 0, U"To Strings", nullptr, 0, DO_WordList_to_Strings);
+		praat_addAction1 (classWordList, 0, U"To Strings", nullptr, 0, NEW_WordList_to_Strings);
 	praat_addAction1 (classWordList, 0, U"Synthesize", nullptr, 0, nullptr);
-		praat_addAction1 (classWordList, 0, U"Up to SpellingChecker", nullptr, 0, DO_WordList_upto_SpellingChecker);
+		praat_addAction1 (classWordList, 0, U"Up to SpellingChecker", nullptr, 0, NEW_WordList_upto_SpellingChecker);
 
-	praat_addAction2 (classIntervalTier, 1, classPointProcess, 1, U"Start to centre...", nullptr, 0, DO_IntervalTier_PointProcess_startToCentre);
-	praat_addAction2 (classIntervalTier, 1, classPointProcess, 1, U"End to centre...", nullptr, 0, DO_IntervalTier_PointProcess_endToCentre);
+	praat_addAction2 (classIntervalTier, 1, classPointProcess, 1, U"Start to centre...", nullptr, 0, NEW1_IntervalTier_PointProcess_startToCentre);
+	praat_addAction2 (classIntervalTier, 1, classPointProcess, 1, U"End to centre...", nullptr, 0, NEW1_IntervalTier_PointProcess_endToCentre);
 	praat_addAction2 (classIntervalTier, 0, classTextTier, 0, U"Collect", nullptr, 0, nullptr);
-	praat_addAction2 (classIntervalTier, 0, classTextTier, 0, U"Into TextGrid", nullptr, 0, DO_AnyTier_into_TextGrid);
-	praat_addAction2 (classLabel, 1, classSound, 1, U"To TextGrid", nullptr, 0, DO_Label_Sound_to_TextGrid);
-	praat_addAction2 (classLongSound, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_TextGrid_LongSound_edit);
-	praat_addAction2 (classLongSound, 1, classTextGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_TextGrid_LongSound_edit);   // hidden 2011
-	praat_addAction2 (classLongSound, 1, classTextGrid, 1, U"Scale times", nullptr, 0, DO_TextGrid_LongSound_scaleTimes);
+	praat_addAction2 (classIntervalTier, 0, classTextTier, 0, U"Into TextGrid", nullptr, 0, NEW1_AnyTier_into_TextGrid);
+	praat_addAction2 (classLabel, 1, classSound, 1, U"To TextGrid", nullptr, 0, NEW1_Label_Sound_to_TextGrid);
+	praat_addAction2 (classLongSound, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_TextGrid_LongSound_viewAndEdit);
+	praat_addAction2 (classLongSound, 1, classTextGrid, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_TextGrid_LongSound_viewAndEdit);
+	praat_addAction2 (classLongSound, 1, classTextGrid, 1, U"Scale times", nullptr, 0, MODIFY_TextGrid_LongSound_scaleTimes);
 	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw -", nullptr, 0, nullptr);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw...", nullptr, 1, DO_TextGrid_Pitch_draw);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw logarithmic...", nullptr, 1, DO_TextGrid_Pitch_drawLogarithmic);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw semitones...", nullptr, 1, DO_TextGrid_Pitch_drawSemitones);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw mel...", nullptr, 1, DO_TextGrid_Pitch_drawMel);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw erb...", nullptr, 1, DO_TextGrid_Pitch_drawErb);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle...", nullptr, 1, DO_TextGrid_Pitch_speckle);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle logarithmic...", nullptr, 1, DO_TextGrid_Pitch_speckleLogarithmic);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle semitones...", nullptr, 1, DO_TextGrid_Pitch_speckleSemitones);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle mel...", nullptr, 1, DO_TextGrid_Pitch_speckleMel);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle erb...", nullptr, 1, DO_TextGrid_Pitch_speckleErb);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw...", nullptr, 1, GRAPHICS_TextGrid_Pitch_draw);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw logarithmic...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawLogarithmic);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw semitones...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawSemitones);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw mel...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawMel);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw erb...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawErb);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckle);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle logarithmic...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleLogarithmic);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle semitones...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleSemitones);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle mel...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleMel);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle erb...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleErb);
 	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"-- draw separately --", nullptr, 1, nullptr);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately...", nullptr, 1, DO_TextGrid_Pitch_drawSeparately);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (logarithmic)...", nullptr, 1, DO_TextGrid_Pitch_drawSeparatelyLogarithmic);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (semitones)...", nullptr, 1, DO_TextGrid_Pitch_drawSeparatelySemitones);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (mel)...", nullptr, 1, DO_TextGrid_Pitch_drawSeparatelyMel);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (erb)...", nullptr, 1, DO_TextGrid_Pitch_drawSeparatelyErb);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately...", nullptr, 1, DO_TextGrid_Pitch_speckleSeparately);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (logarithmic)...", nullptr, 1, DO_TextGrid_Pitch_speckleSeparatelyLogarithmic);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (semitones)...", nullptr, 1, DO_TextGrid_Pitch_speckleSeparatelySemitones);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (mel)...", nullptr, 1, DO_TextGrid_Pitch_speckleSeparatelyMel);
-	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (erb)...", nullptr, 1, DO_TextGrid_Pitch_speckleSeparatelyErb);
-	praat_addAction2 (classPitch, 1, classTextTier, 1, U"To PitchTier...", nullptr, 0, DO_Pitch_TextTier_to_PitchTier);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_TextGrid_edit);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"View & Edit with callback...", nullptr, praat_HIDDEN, DO_TextGrid_editWithCallback);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_TextGrid_edit);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Draw...", nullptr, 0, DO_TextGrid_Sound_draw);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawSeparately);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (logarithmic)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawSeparatelyLogarithmic);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (semitones)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawSeparatelySemitones);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (mel)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawSeparatelyMel);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Draw separately (erb)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_drawSeparatelyErb);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleSeparately);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (logarithmic)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleSeparatelyLogarithmic);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (semitones)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleSeparatelySemitones);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (mel)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleSeparatelyMel);
+	praat_addAction2 (classPitch, 1, classTextGrid, 1, U"Speckle separately (erb)...", nullptr, 1, GRAPHICS_TextGrid_Pitch_speckleSeparatelyErb);
+	praat_addAction2 (classPitch, 1, classTextTier, 1, U"To PitchTier...", nullptr, 0, NEW1_Pitch_TextTier_to_PitchTier);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_TextGrid_viewAndEdit);
+	praat_addAction2 (classSound, 1, classTextGrid, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_TextGrid_viewAndEdit);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"View & Edit with callback...", nullptr, praat_HIDDEN, WINDOW_TextGrid_viewAndEditWithCallback);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Draw...", nullptr, 0, GRAPHICS_TextGrid_Sound_draw);
 	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract -", nullptr, 0, nullptr);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract all intervals...", nullptr, praat_DEPTH_1, DO_TextGrid_Sound_extractAllIntervals);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract non-empty intervals...", nullptr, praat_DEPTH_1, DO_TextGrid_Sound_extractNonemptyIntervals);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract intervals...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_TextGrid_Sound_extractIntervals);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract intervals where...", nullptr, praat_DEPTH_1, DO_TextGrid_Sound_extractIntervalsWhere);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract all intervals...", nullptr, praat_DEPTH_1, NEW1_TextGrid_Sound_extractAllIntervals);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract non-empty intervals...", nullptr, praat_DEPTH_1, NEW1_TextGrid_Sound_extractNonemptyIntervals);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Extract intervals where...", nullptr, praat_DEPTH_1, NEW1_TextGrid_Sound_extractIntervalsWhere);
+	praat_addAction2 (classSound, 1, classTextGrid, 1,   U"Extract intervals...", U"*Extract intervals where...", praat_DEPTH_1 | praat_DEPRECATED_2005, NEW1_TextGrid_Sound_extractIntervals);
 	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Modify TextGrid", nullptr, 0, nullptr);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Scale times", nullptr, 0, DO_TextGrid_Sound_scaleTimes);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Scale times", nullptr, 0, MODIFY_TextGrid_Sound_scaleTimes);
 	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Modify Sound", nullptr, 0, nullptr);
-	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Clone time domain", nullptr, 0, DO_TextGrid_Sound_cloneTimeDomain);
-	praat_addAction2 (classSpellingChecker, 1, classWordList, 1, U"Replace WordList", nullptr, 0, DO_SpellingChecker_replaceWordList);
-	praat_addAction2 (classSpellingChecker, 1, classStringSet, 1, U"Replace user dictionary", nullptr, 0, DO_SpellingChecker_replaceUserDictionary);
-	praat_addAction2 (classSpellingChecker, 1, classStrings, 1, U"Replace word list?", nullptr, 0, DO_SpellingChecker_replaceWordList_help);
-	praat_addAction2 (classSpellingChecker, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_TextGrid_SpellingChecker_edit);
-	praat_addAction2 (classSpellingChecker, 1, classTextGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_TextGrid_SpellingChecker_edit);   // hidden 2011
-	praat_addAction2 (classTextGrid, 1, classTextTier, 1, U"Append", nullptr, 0, DO_TextGrid_AnyTier_append);
-	praat_addAction2 (classTextGrid, 1, classIntervalTier, 1, U"Append", nullptr, 0, DO_TextGrid_AnyTier_append);
-
-	praat_addAction3 (classLongSound, 1, classSpellingChecker, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_TextGrid_LongSound_SpellingChecker_edit);
-	praat_addAction3 (classLongSound, 1, classSpellingChecker, 1, classTextGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_TextGrid_LongSound_SpellingChecker_edit);
-	praat_addAction3 (classSound, 1, classSpellingChecker, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_TextGrid_SpellingChecker_edit);
-	praat_addAction3 (classSound, 1, classSpellingChecker, 1, classTextGrid, 1, U"Edit", nullptr, praat_HIDDEN, DO_TextGrid_SpellingChecker_edit);
+	praat_addAction2 (classSound, 1, classTextGrid, 1, U"Clone time domain", nullptr, 0, MODIFY_TextGrid_Sound_cloneTimeDomain);
+	praat_addAction2 (classSpellingChecker, 1, classWordList, 1, U"Replace WordList", nullptr, 0, MODIFY_SpellingChecker_replaceWordList);
+	praat_addAction2 (classSpellingChecker, 1, classStringSet, 1, U"Replace user dictionary", nullptr, 0, MODIFY_SpellingChecker_replaceUserDictionary);
+	praat_addAction2 (classSpellingChecker, 1, classStrings, 1, U"Replace word list?", nullptr, 0, HINT_SpellingChecker_replaceWordList_help);
+	praat_addAction2 (classSpellingChecker, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_TextGrid_SpellingChecker_viewAndEdit);
+	praat_addAction2 (classSpellingChecker, 1, classTextGrid, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_TextGrid_SpellingChecker_viewAndEdit);
+	praat_addAction2 (classTextGrid, 1, classIntervalTier, 1, U"Append", nullptr, 0, NEW1_TextGrid_IntervalTier_append);
+	praat_addAction2 (classTextGrid, 1, classTextTier, 1, U"Append", nullptr, 0, NEW1_TextGrid_TextTier_append);
+
+	praat_addAction3 (classLongSound, 1, classSpellingChecker, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_TextGrid_LongSound_SpellingChecker_viewAndEdit);
+	praat_addAction3 (classLongSound, 1, classSpellingChecker, 1, classTextGrid, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_TextGrid_LongSound_SpellingChecker_viewAndEdit);
+	praat_addAction3 (classSound, 1, classSpellingChecker, 1, classTextGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_TextGrid_SpellingChecker_viewAndEdit);
+	praat_addAction3 (classSound, 1, classSpellingChecker, 1, classTextGrid, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_TextGrid_SpellingChecker_viewAndEdit);
 }
 
 /* End of file praat_TextGrid_init.cpp */
diff --git a/fon/praat_Tiers.cpp b/fon/praat_Tiers.cpp
new file mode 100644
index 0000000..bb6cd00
--- /dev/null
+++ b/fon/praat_Tiers.cpp
@@ -0,0 +1,1890 @@
+/* praat_Tiers.cpp
+ *
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Ltas.h"
+#include "PitchTier_to_PointProcess.h"
+#include "PitchTier_to_Sound.h"
+#include "Matrix_and_PointProcess.h"
+#include "PointProcess_and_Sound.h"
+#include "Sound_PointProcess.h"
+#include "SpectrumTier.h"
+#include "TextGrid.h"
+#include "VoiceAnalysis.h"
+
+#include "praat_Tiers.h"
+
+// MARK: - AMPLITUDETIER
+
+// MARK: New
+
+FORM (NEW1_AmplitudeTier_create, U"Create empty AmplitudeTier", nullptr) {
+	WORD4 (name, U"Name", U"empty")
+	REAL4 (startTime, U"Start time (s)", U"0.0")
+	REAL4 (endTime, U"End time (s)", U"1.0")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"The end time should be greater than the start time.");
+	CREATE_ONE
+		autoAmplitudeTier result = AmplitudeTier_create (startTime, endTime);
+	CREATE_ONE_END (name)
+}
+
+// MARK: Help
+
+DIRECT (HELP_AmplitudeTier_help) {
+	HELP (U"AmplitudeTier")
+}
+
+// MARK: View & Edit
+
+DIRECT (WINDOW_AmplitudeTier_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an AmplitudeTier from batch.");
+	Sound sound = nullptr;
+	LOOP {
+		if (CLASS == classSound) sound = (Sound) OBJECT;   // may stay null
+	}
+	LOOP if (CLASS == classAmplitudeTier) {
+		iam_LOOP (AmplitudeTier);
+		autoAmplitudeTierEditor editor = AmplitudeTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+DIRECT (HINT_AmplitudeTier_Sound_viewAndEdit) {
+	INFO_NONE
+		Melder_information (U"To include a copy of a Sound in your AmplitudeTier window:\n"
+			"   select an AmplitudeTier and a Sound, and click \"View & Edit\".");
+	INFO_NONE_END
+}
+
+// MARK: Query
+
+FORM (REAL_AmplitudeTier_getShimmer_local, U"AmplitudeTier: Get shimmer (local)", U"AmplitudeTier: Get shimmer (local)...") {
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = AmplitudeTier_getShimmer_local (me, shortestPeriod, longestPeriod, maximumAmplitudeFactor);
+	NUMBER_ONE_END (U" (local shimmer)")
+}
+
+FORM (REAL_AmplitudeTier_getShimmer_local_dB, U"AmplitudeTier: Get shimmer (local, dB)", U"AmplitudeTier: Get shimmer (local, dB)...") {
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = AmplitudeTier_getShimmer_local_dB (me, shortestPeriod, longestPeriod, maximumAmplitudeFactor);
+	NUMBER_ONE_END (U" dB (local shimmer)")
+}
+
+FORM (REAL_AmplitudeTier_getShimmer_apq3, U"AmplitudeTier: Get shimmer (apq3)", U"AmplitudeTier: Get shimmer (apq3)...") {
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = AmplitudeTier_getShimmer_apq3 (me, shortestPeriod, longestPeriod, maximumAmplitudeFactor);
+	NUMBER_ONE_END (U" (apq3 shimmer)")
+}
+
+FORM (REAL_AmplitudeTier_getShimmer_apq5, U"AmplitudeTier: Get shimmer (apq5)", U"AmplitudeTier: Get shimmer (apq5)...") {
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = AmplitudeTier_getShimmer_apq5 (me, shortestPeriod, longestPeriod, maximumAmplitudeFactor);
+	NUMBER_ONE_END (U" (apq5 shimmer)")
+}
+
+FORM (REAL_AmplitudeTier_getShimmer_apq11, U"AmplitudeTier: Get shimmer (apq11)", U"AmplitudeTier: Get shimmer (apq11)...") {
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = AmplitudeTier_getShimmer_apq11 (me, shortestPeriod, longestPeriod, maximumAmplitudeFactor);
+	NUMBER_ONE_END (U" (apq11 shimmer)")
+}
+
+FORM (REAL_AmplitudeTier_getShimmer_dda, U"AmplitudeTier: Get shimmer (dda)", U"AmplitudeTier: Get shimmer (dda)...") {
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = AmplitudeTier_getShimmer_dda (me, shortestPeriod, longestPeriod, maximumAmplitudeFactor);
+	NUMBER_ONE_END (U" (dda shimmer)")
+}
+
+/*
+FORM (REAL_AmplitudeTier_getValueAtTime, U"Get AmplitudeTier value", U"AmplitudeTier: Get value at time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = RealTier_getValueAtTime (me, time);
+	NUMBER_ONE_END (U" Pa")
+}
+	
+FORM (REAL_AmplitudeTier_getValueAtIndex, U"Get AmplitudeTier value", U"AmplitudeTier: Get value at index...") {
+	INTEGER4 (pointNumber, U"Point number", U"10")
+	OK
+DO
+	NUMBER_ONE (AmplitudeTier)
+		double result = RealTier_getValueAtIndex (me, pointNumber);
+	NUMBER_ONE_END (U" Pa")
+}
+*/
+
+// MARK: Modify
+
+FORM (MODIFY_AmplitudeTier_addPoint, U"Add one point", U"AmplitudeTier: Add point...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	REAL4 (soundPressure, U"Sound pressure (Pa)", U"0.8")
+	OK
+DO
+	MODIFY_EACH (AmplitudeTier)
+		RealTier_addPoint (me, time, soundPressure);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_AmplitudeTier_formula, U"AmplitudeTier: Formula", U"AmplitudeTier: Formula...") {
+	LABEL (U"", U"# ncol = the number of points")
+	LABEL (U"", U"for col from 1 to ncol")
+	LABEL (U"", U"   # x = the time of the colth point, in seconds")
+	LABEL (U"", U"   # self = the value of the colth point, in Pascal")
+	LABEL (U"", U"   self = `formula'")
+	LABEL (U"", U"endfor")
+	TEXTFIELD4 (formula, U"formula", U"- self ; upside down")
+	OK
+DO
+	MODIFY_EACH_WEAK (AmplitudeTier)
+		RealTier_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+// MARK: Synthesize
+
+FORM (NEW_AmplitudeTier_to_Sound, U"AmplitudeTier: To Sound (pulse train)", U"AmplitudeTier: To Sound (pulse train)...") {
+	POSITIVE4 (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	NATURAL4 (interpolationDepth, U"Interpolation depth (samples)", U"2000")
+	OK
+DO
+	CONVERT_EACH (AmplitudeTier)
+		autoSound result = AmplitudeTier_to_Sound (me, samplingFrequency, interpolationDepth);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: Convert
+
+DIRECT (NEW_AmplitudeTier_downto_PointProcess) {
+	CONVERT_EACH (AmplitudeTier)
+		autoPointProcess result = AnyTier_downto_PointProcess (me->asAnyTier());
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_AmplitudeTier_downto_TableOfReal) {
+	CONVERT_EACH (AmplitudeTier)
+		autoTableOfReal result = AmplitudeTier_downto_TableOfReal (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_AmplitudeTier_to_IntensityTier, U"AmplitudeTier: To IntensityTier", U"AmplitudeTier: To IntensityTier...") {
+	REAL4 (threshold, U"Threshold (dB)", U"-10000.0")
+	OK
+DO
+	CONVERT_EACH (AmplitudeTier)
+		autoIntensityTier result = AmplitudeTier_to_IntensityTier (me, threshold);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - AMPLITUDETIER & SOUND
+
+DIRECT (NEW1_Sound_AmplitudeTier_multiply) {
+	CONVERT_TWO (Sound, AmplitudeTier)
+		autoSound result = Sound_AmplitudeTier_multiply (me, you);
+	CONVERT_TWO_END (my name, U"_amp")
+}
+
+// MARK: - DURATIONTIER
+
+// MARK: New
+
+FORM (NEW1_DurationTier_create, U"Create empty DurationTier", U"Create DurationTier...") {
+	WORD4 (name, U"Name", U"empty")
+	REAL4 (startTime, U"Start time (s)", U"0.0")
+	REAL4 (endTime, U"End time (s)", U"1.0")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"Your end time should be greater than your start time.");
+	CREATE_ONE
+		autoDurationTier result = DurationTier_create (startTime, endTime);
+	CREATE_ONE_END (name)
+}
+
+// MARK: Help
+
+DIRECT (HELP_DurationTier_help) {
+	HELP (U"DurationTier")
+}
+
+// MARK: View & Edit
+
+DIRECT (WINDOW_DurationTier_edit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a DurationTier from batch.");
+	Sound sound = nullptr;
+	LOOP {
+		if (CLASS == classSound) sound = (Sound) OBJECT;   // may stay null
+	}
+	LOOP if (CLASS == classDurationTier) {
+		iam_LOOP (DurationTier);
+		autoDurationTierEditor editor = DurationTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+DIRECT (HINT_DurationTier_Sound_edit) {
+	INFO_NONE
+		Melder_information (U"To include a copy of a Sound in your DurationTier window:\n"
+			"   select a DurationTier and a Sound, and click \"View & Edit\".");
+	INFO_NONE_END
+}
+
+DIRECT (HINT_DurationTier_Manipulation_replace) {
+	INFO_NONE
+		Melder_information (U"To replace the DurationTier in a Manipulation object,\n"
+			"select a DurationTier object and a Manipulation object\nand choose \"Replace duration\".");
+	INFO_NONE_END
+}
+
+// MARK: Query
+
+FORM (REAL_DurationTier_getTargetDuration, U"Get target duration", nullptr) {
+	REAL4 (fromSourceTime, U"left Source time range (s)", U"0.0")
+	REAL4 (toSourceTime, U"right Source time range (s)", U"1.0")
+	OK
+DO
+	NUMBER_ONE (DurationTier)
+		double result = RealTier_getArea (me, fromSourceTime, toSourceTime);
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_DurationTier_getValueAtTime, U"Get DurationTier value", U"DurationTier: Get value at time...") {
+	REAL4 (sourceTime, U"Source time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (DurationTier)
+		double result = RealTier_getValueAtTime (me, sourceTime);
+	NUMBER_ONE_END (U" (relative duration)")
+}
+
+FORM (REAL_DurationTier_getValueAtIndex, U"Get DurationTier value", U"Duration: Get value at index...") {
+	INTEGER4 (pointNumber, U"Point number", U"10")
+	OK
+DO
+	NUMBER_ONE (DurationTier)
+		double result = RealTier_getValueAtIndex (me, pointNumber);
+	NUMBER_ONE_END (U" (relative duration)")
+}
+
+// MARK: Modify
+
+FORM (MODIFY_DurationTier_addPoint, U"Add one point to DurationTier", U"DurationTier: Add point...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	REAL4 (relativeDuration, U"Relative duration", U"1.5")
+	OK
+DO
+	MODIFY_EACH (DurationTier)
+		RealTier_addPoint (me, time, relativeDuration);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_DurationTier_formula, U"DurationTier: Formula", U"DurationTier: Formula...") {
+	LABEL (U"", U"# ncol = the number of points")
+	LABEL (U"", U"for col from 1 to ncol")
+	LABEL (U"", U"   # x = the time of the colth point, in seconds")
+	LABEL (U"", U"   # self = the value of the colth point, in relative units")
+	LABEL (U"", U"   self = `formula'")
+	LABEL (U"", U"endfor")
+	TEXTFIELD4 (formula, U"formula", U"self * 1.5 ; slow down")
+	OK
+DO
+	MODIFY_EACH_WEAK (DurationTier)
+		RealTier_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+// MARK: Convert
+
+DIRECT (NEW_DurationTier_downto_PointProcess) {
+	CONVERT_EACH (DurationTier)
+		autoPointProcess result = AnyTier_downto_PointProcess (me->asAnyTier());
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - FORMANTGRID
+
+// MARK: New
+
+FORM (NEW1_FormantGrid_create, U"Create FormantGrid", nullptr) {
+	WORD4 (name, U"Name", U"schwa")
+	REAL4 (startTime, U"Start time (s)", U"0.0")
+	REAL4 (endTime, U"End time (s)", U"1.0")
+	NATURAL4 (numberOfFormants, U"Number of formants", U"10")
+	POSITIVE4 (initialFirstFormant, U"Initial first formant (Hz)", U"550.0")
+	POSITIVE4 (initialFormatSpacing, U"Initial formant spacing (Hz)", U"1100.0")
+	REAL4 (initialFirstBandwidth, U"Initial first bandwidth (Hz)", U"60.0")
+	REAL4 (initialBandwidthSpacing, U"Initial bandwidth spacing (Hz)", U"50.0")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"Your end time should be greater than your start time.");
+	CREATE_ONE
+		autoFormantGrid result = FormantGrid_create (startTime, endTime, numberOfFormants,
+			initialFirstFormant, initialFormatSpacing, initialFirstBandwidth, initialBandwidthSpacing);
+	CREATE_ONE_END (name)
+}
+
+// MARK: Help
+
+DIRECT (HELP_FormantGrid_help) {
+	HELP (U"FormantGrid")
+}
+
+// MARK: View & Edit
+
+static void cb_FormantGridEditor_publish (Editor /* me */, autoDaata publish) {
+	/*
+	 * Keep the gate for error handling.
+	 */
+	try {
+		praat_new (publish.move(), U"fromFormantGridEditor");
+		praat_updateSelection ();
+	} catch (MelderError) {
+		Melder_flushError ();
+	}
+}
+DIRECT (WINDOW_FormantGrid_edit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a FormantGrid from batch.");
+	LOOP {
+		iam_LOOP (FormantGrid);
+		autoFormantGridEditor editor = FormantGridEditor_create (ID_AND_FULL_NAME, me);
+		Editor_setPublicationCallback (editor.get(), cb_FormantGridEditor_publish);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+// MARK: Modify
+
+FORM (MODIFY_FormantGrid_formula_frequencies, U"FormantGrid: Formula (frequencies)", U"Formant: Formula (frequencies)...") {
+	LABEL (U"", U"row is formant number, col is point number: for row from 1 to nrow do for col from 1 to ncol do F (row, col) :=")
+	TEXTFIELD4 (formula, U"formula", U"if row = 2 then self + 200 else self fi")
+	OK
+DO
+	MODIFY_EACH_WEAK (FormantGrid)
+		FormantGrid_formula_frequencies (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_FormantGrid_formula_bandwidths, U"FormantGrid: Formula (bandwidths)", U"Formant: Formula (bandwidths)...") {
+	LABEL (U"", U"row is formant number, col is point number: for row from 1 to nrow do for col from 1 to ncol do B (row, col) :=")
+	LABEL (U"", U"self [] is the FormantGrid itself, so it returns frequencies, not bandwidths!")
+	TEXTFIELD4 (formula, U"formula", U"self / 10 ; one tenth of the formant frequency")
+	OK
+DO
+	MODIFY_EACH_WEAK (FormantGrid)
+		FormantGrid_formula_bandwidths (me, formula, interpreter, nullptr);
+			praat_dataChanged (me);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_FormantGrid_addFormantPoint, U"FormantGrid: Add formant point", U"FormantGrid: Add formant point...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	POSITIVE4 (frequency, U"Frequency (Hz)", U"550.0")
+	OK
+DO
+	MODIFY_EACH (FormantGrid)
+		FormantGrid_addFormantPoint (me, formantNumber, time, frequency);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_FormantGrid_addBandwidthPoint, U"FormantGrid: Add bandwidth point", U"FormantGrid: Add bandwidth point...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	POSITIVE4 (bandwidth, U"Bandwidth (Hz)", U"100.0")
+	OK
+DO
+	MODIFY_EACH (FormantGrid)
+		FormantGrid_addBandwidthPoint (me, formantNumber, time, bandwidth);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_FormantGrid_removeBandwidthPointsBetween, U"Remove bandwidth points between", U"FormantGrid: Remove bandwidth points between...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (fromTime, U"From time (s)", U"0.3")
+	REAL4 (toTime, U"To time (s)", U"0.7")
+	OK
+DO
+	MODIFY_EACH (FormantGrid)
+		FormantGrid_removeBandwidthPointsBetween (me, formantNumber, fromTime, toTime);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_FormantGrid_removeFormantPointsBetween, U"Remove formant points between", U"FormantGrid: Remove formant points between...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (fromTime, U"From time (s)", U"0.3")
+	REAL4 (toTime, U"To time (s)", U"0.7")
+	OK
+DO
+	MODIFY_EACH (FormantGrid)
+		FormantGrid_removeFormantPointsBetween (me, formantNumber, fromTime, toTime);
+	MODIFY_EACH_END
+}
+
+// MARK: Convert
+
+FORM (NEW_FormantGrid_to_Formant, U"FormantGrid: To Formant", nullptr) {
+	POSITIVE4 (timeStep, U"Time step (s)", U"0.01")
+	REAL4 (intensity, U"Intensity (Pa\u00B2)", U"0.1")
+	OK
+DO
+	if (intensity < 0.0) Melder_throw (U"Intensity cannot be negative.");
+	CONVERT_EACH (FormantGrid)
+		autoFormant result = FormantGrid_to_Formant (me, timeStep, intensity);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - FORMANTGRID & SOUND
+
+DIRECT (NEW1_Sound_FormantGrid_filter) {
+	CONVERT_TWO (Sound, FormantGrid)
+		autoSound result = Sound_FormantGrid_filter (me, you);
+	CONVERT_TWO_END (my name, U"_filt")
+}
+
+DIRECT (NEW1_Sound_FormantGrid_filter_noscale) {
+	CONVERT_TWO (Sound, FormantGrid)
+		autoSound result = Sound_FormantGrid_filter_noscale (me, you);
+	CONVERT_TWO_END (my name, U"_filt")
+}
+
+// MARK: - FORMANTTIER
+
+// MARK: New
+
+FORM (NEW1_FormantTier_create, U"Create empty FormantTier", nullptr) {
+	WORD4 (name, U"Name", U"empty")
+	REAL4 (startTime, U"Start time (s)", U"0.0")
+	REAL4 (endTime, U"End time (s)", U"1.0")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"Your end time should be greater than your start time.");
+	CREATE_ONE
+		autoFormantTier result = FormantTier_create (startTime, endTime);
+	CREATE_ONE_END (name)
+}
+
+// MARK: Draw
+
+FORM (GRAPHICS_FormantTier_speckle, U"Draw FormantTier", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVE4 (maximumFrequency, U"Maximum frequency (Hz)", U"5500.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (FormantTier)
+		FormantTier_speckle (me, GRAPHICS, fromTime, toTime, maximumFrequency, garnish);
+	GRAPHICS_EACH_END
+}
+
+// MARK: Query
+
+FORM (REAL_FormantTier_getValueAtTime, U"FormantTier: Get value", U"FormantTier: Get value at time...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (FormantTier)
+		double result = FormantTier_getValueAtTime (me, formantNumber, time);
+	NUMBER_ONE_END (U" Hz")
+}
+
+FORM (REAL_FormantTier_getBandwidthAtTime, U"FormantTier: Get bandwidth", U"FormantTier: Get bandwidth at time...") {
+	NATURAL4 (formantNumber, U"Formant number", U"1")
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (FormantTier)
+		double result = FormantTier_getBandwidthAtTime (me, formantNumber, time);
+	NUMBER_ONE_END (U" Hz")
+}
+
+// MARK: Modify
+
+FORM (MODIFY_FormantTier_addPoint, U"Add one point", U"FormantTier: Add point...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	LABEL (U"", U"Frequencies and bandwidths (Hz):")
+	TEXTFIELD4 (formantBandwidthPairs, U"fb pairs", U"500 50 1500 100 2500 150 3500 200 4500 300")
+	OK
+DO
+	autoFormantPoint point = FormantPoint_create (time);
+	double *f = point -> formant, *b = point -> bandwidth;
+	char *fbpairs = Melder_peek32to8 (formantBandwidthPairs);
+	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)
+		Melder_throw (U"Number of formant-bandwidth pairs must be at least 1.");
+	point -> numberOfFormants = numberOfFormants;
+	MODIFY_EACH (FormantTier)
+		autoFormantPoint point2 = Data_copy (point.get());
+		AnyTier_addPoint_move (me->asAnyTier(), point2.move());
+	MODIFY_EACH_END
+}
+
+// MARK: Convert
+
+FORM (NEW_FormantTier_downto_TableOfReal, U"Down to TableOfReal", nullptr) {
+	BOOLEAN4 (includeFormants, U"Include formants", true)
+	BOOLEAN4 (includeBandwidths, U"Include bandwidths", false)
+	OK
+DO
+	CONVERT_EACH (FormantTier)
+		autoTableOfReal result = FormantTier_downto_TableOfReal (me, includeFormants, includeBandwidths);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - FORMANTTIER & SOUND
+
+DIRECT (NEW1_Sound_FormantTier_filter) {
+	CONVERT_TWO (Sound, FormantTier)
+		autoSound result = Sound_FormantTier_filter (me, you);
+	CONVERT_TWO_END (my name, U"_filt")
+}
+
+DIRECT (NEW1_Sound_FormantTier_filter_noscale) {
+	CONVERT_TWO (Sound, FormantTier)
+		autoSound result = Sound_FormantTier_filter_noscale (me, you);
+	CONVERT_TWO_END (my name, U"_filt")
+}
+
+// MARK: - INTENSITYTIER
+
+// MARK: New
+
+FORM (NEW1_IntensityTier_create, U"Create empty IntensityTier", nullptr) {
+	WORD4 (name, U"Name", U"empty")
+	REAL4 (startTime, U"Start time (s)", U"0.0")
+	REAL4 (endTime, U"End time (s)", U"1.0")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"Your end time should be greater than your start time.");
+	CREATE_ONE
+		autoIntensityTier result = IntensityTier_create (startTime, endTime);
+	CREATE_ONE_END (name)
+}
+
+// MARK: Help
+
+DIRECT (HELP_IntensityTier_help) {
+	HELP (U"IntensityTier")
+}
+
+// MARK: View & Edit
+
+DIRECT (WINDOW_IntensityTier_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit an IntensityTier from batch.");
+	Sound sound = nullptr;
+	LOOP {
+		if (CLASS == classSound) sound = (Sound) OBJECT;   // may stay null
+		if (sound) break;   // OPTIMIZE
+	}
+	LOOP if (CLASS == classIntensityTier) {
+		iam_LOOP (IntensityTier);
+		autoIntensityTierEditor editor = IntensityTierEditor_create (ID_AND_FULL_NAME, me, sound, true);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	}
+END }
+
+DIRECT (HINT_IntensityTier_Sound_viewAndEdit) {
+	INFO_NONE
+		Melder_information (U"To include a copy of a Sound in your IntensityTier window:\n"
+			"   select an IntensityTier and a Sound, and click \"View & Edit\".");
+	INFO_NONE_END
+}
+
+// MARK: Query
+
+FORM (REAL_IntensityTier_getValueAtTime, U"Get IntensityTier value", U"IntensityTier: Get value at time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (IntensityTier)
+		double result = RealTier_getValueAtTime (me, time);
+	NUMBER_ONE_END (U" dB")
+}
+
+FORM (REAL_IntensityTier_getValueAtIndex, U"Get IntensityTier value", U"IntensityTier: Get value at index...") {
+	INTEGER4 (pointNumber, U"Point number", U"10")
+	OK
+DO
+	NUMBER_ONE (IntensityTier)
+		double result = RealTier_getValueAtIndex (me, pointNumber);
+	NUMBER_ONE_END (U" dB")
+}
+
+// MARK: Modify
+
+FORM (MODIFY_IntensityTier_addPoint, U"Add one point", U"IntensityTier: Add point...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	REAL4 (intensity, U"Intensity (dB)", U"75")
+	OK
+DO
+	MODIFY_EACH (IntensityTier)
+		RealTier_addPoint (me, time, intensity);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_IntensityTier_formula, U"IntensityTier: Formula", U"IntensityTier: Formula...") {
+	LABEL (U"", U"# ncol = the number of points")
+	LABEL (U"", U"for col from 1 to ncol")
+	LABEL (U"", U"   # x = the time of the colth point, in seconds")
+	LABEL (U"", U"   # self = the value of the colth point, in dB")
+	LABEL (U"", U"   self = `formula'")
+	LABEL (U"", U"endfor")
+	TEXTFIELD4 (formula, U"formula", U"self + 3.0")
+	OK
+DO
+	MODIFY_EACH_WEAK (IntensityTier)
+		RealTier_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+// MARK: Convert
+
+DIRECT (NEW_IntensityTier_downto_PointProcess) {
+	CONVERT_EACH (IntensityTier)
+		autoPointProcess result = AnyTier_downto_PointProcess (me->asAnyTier());
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_IntensityTier_downto_TableOfReal) {
+	CONVERT_EACH (IntensityTier)
+		autoTableOfReal result = IntensityTier_downto_TableOfReal (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_IntensityTier_to_AmplitudeTier) {
+	CONVERT_EACH (IntensityTier)
+		autoAmplitudeTier result = IntensityTier_to_AmplitudeTier (me);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - INTENSITYTIER & POINTPROCESS
+
+DIRECT (NEW1_IntensityTier_PointProcess_to_IntensityTier) {
+	CONVERT_TWO (IntensityTier, PointProcess)
+		autoIntensityTier result = IntensityTier_PointProcess_to_IntensityTier (me, you);
+	CONVERT_TWO_END (my name)
+}
+
+// MARK: - INTENSITYTIER & SOUND
+
+DIRECT (NEW1_Sound_IntensityTier_multiply_old) {
+	CONVERT_TWO (Sound, IntensityTier)
+		autoSound result = Sound_IntensityTier_multiply (me, you, true);
+	CONVERT_TWO_END (my name, U"_int")
+}
+
+FORM (NEW1_Sound_IntensityTier_multiply, U"Sound & IntervalTier: Multiply", nullptr) {
+	BOOLEANVAR (scaleTo09, U"Scale to 0.9", true)
+	OK
+DO
+	CONVERT_TWO (Sound, IntensityTier)
+		autoSound result = Sound_IntensityTier_multiply (me, you, scaleTo09);
+	CONVERT_TWO_END (my name, U"_int")
+}
+
+// MARK: - PITCHTIER
+
+FORM (MODIFY_PitchTier_addPoint, U"PitchTier: Add point", U"PitchTier: Add point...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	REALVAR (pitch, U"Pitch (Hz)", U"200.0")
+	OK
+DO
+	MODIFY_EACH (PitchTier)
+		RealTier_addPoint (me, time, pitch);
+	MODIFY_EACH_END
+}
+
+FORM (NEW1_PitchTier_create, U"Create empty PitchTier", nullptr) {
+	WORDVAR (name, U"Name", U"empty")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"1.0")
+	OK
+DO
+	if (endTime <= startTime) Melder_throw (U"Your end time should be greater than your start time.");
+	CREATE_ONE
+		autoPitchTier result = PitchTier_create (startTime, endTime);
+	CREATE_ONE_END (name)
+}
+
+DIRECT (NEW_PitchTier_downto_PointProcess) {
+	CONVERT_EACH (PitchTier)
+		autoPointProcess result = AnyTier_downto_PointProcess (me->asAnyTier());
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PitchTier_downto_TableOfReal, U"PitchTier: Down to TableOfReal", nullptr) {
+	RADIO4x (unit, U"Unit", 1, 0)
+		RADIOBUTTON (U"Hertz")
+		RADIOBUTTON (U"Semitones")
+	OK
+DO
+	CONVERT_EACH (PitchTier)
+		autoTableOfReal result = PitchTier_downto_TableOfReal (me, unit);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (GRAPHICS_old_PitchTier_draw, U"PitchTier: Draw", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	POSITIVEVAR (toFrequency, U"right Frequency range (Hz)", U"500.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	OK
+DO
+	if (toFrequency <= fromFrequency)
+		Melder_throw (U"Your maximum frequency should be greater than your minimum frequency.");
+	GRAPHICS_EACH (PitchTier)
+		PitchTier_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency,
+			garnish, U"lines and speckles");
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_PitchTier_draw, U"PitchTier: Draw", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	REALVAR (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	POSITIVEVAR (toFrequency, U"right Frequency range (Hz)", U"500.0")
+	BOOLEANVAR (garnish, U"Garnish", true)
+	LABEL (U"", U"")
+	OPTIONMENUSTRVAR (drawingMethod, U"Drawing method", 1)
+		OPTION (U"lines")
+		OPTION (U"speckles")
+		OPTION (U"lines and speckles")
+	OK
+DO_ALTERNATIVE (GRAPHICS_old_PitchTier_draw)
+	if (toFrequency <= fromFrequency)
+		Melder_throw (U"Your maximum frequency should be greater than your minimum frequency.");
+	GRAPHICS_EACH (PitchTier)
+		PitchTier_draw (me, GRAPHICS, fromTime, toTime, fromFrequency, toFrequency, garnish, drawingMethod);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (WINDOW_PitchTier_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a PitchTier from batch.");
+	FIND_TWO (PitchTier, Sound)   // Sound may be null
+		autoPitchTierEditor editor = PitchTierEditor_create (ID_AND_FULL_NAME, me, you, true);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	END
+}
+
+FORM (MODIFY_PitchTier_formula, U"PitchTier: Formula", U"PitchTier: Formula...") {
+	LABEL (U"", U"# ncol = the number of points")
+	LABEL (U"", U"for col from 1 to ncol")
+	LABEL (U"", U"   # x = the time of the colth point, in seconds")
+	LABEL (U"", U"   # self = the value of the colth point, in hertz")
+	LABEL (U"", U"   self = `formula'")
+	LABEL (U"", U"endfor")
+	TEXTFIELD4 (formula, U"formula", U"self * 2 ; one octave up")
+	OK
+DO
+	MODIFY_EACH_WEAK (PitchTier)
+		RealTier_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (REAL_PitchTier_getMean_curve, U"PitchTier: Get mean (curve)", U"PitchTier: Get mean (curve)...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
+DO
+	NUMBER_ONE (PitchTier)
+		double result = RealTier_getMean_curve (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Hz")
+}
+	
+FORM (REAL_PitchTier_getMean_points, U"PitchTier: Get mean (points)", U"PitchTier: Get mean (points)...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
+DO
+	NUMBER_ONE (PitchTier)
+		double result = RealTier_getMean_points (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Hz")
+}
+	
+FORM (REAL_PitchTier_getStandardDeviation_curve, U"PitchTier: Get standard deviation (curve)", U"PitchTier: Get standard deviation (curve)...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
+DO
+	NUMBER_ONE (PitchTier)
+		double result = RealTier_getStandardDeviation_curve (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Hz")
+}
+	
+FORM (REAL_PitchTier_getStandardDeviation_points, U"PitchTier: Get standard deviation (points)", U"PitchTier: Get standard deviation (points)...") {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	OK
+DO
+	NUMBER_ONE (PitchTier)
+		double result = RealTier_getStandardDeviation_points (me, fromTime, toTime);
+	NUMBER_ONE_END (U" Hz")
+}
+	
+FORM (REAL_PitchTier_getValueAtTime, U"PitchTier: Get value at time", U"PitchTier: Get value at time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (PitchTier)
+		double result = RealTier_getValueAtTime (me, time);
+	NUMBER_ONE_END (U" Hz")
+}
+	
+FORM (REAL_PitchTier_getValueAtIndex, U"PitchTier: Get value at index", U"PitchTier: Get value at index...") {
+	INTEGER4 (pointNumber, U"Point number", U"10")
+	OK
+DO
+	NUMBER_ONE (PitchTier)
+		double result = RealTier_getValueAtIndex (me, pointNumber);
+	NUMBER_ONE_END (U" Hz")
+}
+
+DIRECT (HELP_PitchTier_help) {
+	HELP (U"PitchTier")
+}
+
+DIRECT (PLAY_PitchTier_hum) {
+	PLAY_EACH (PitchTier)
+		PitchTier_hum (me);
+	PLAY_EACH_END
+}
+
+FORM (MODIFY_PitchTier_interpolateQuadratically, U"PitchTier: Interpolate quadratically", nullptr) {
+	NATURAL4 (numberOfPointsPerParabola, U"Number of points per parabola", U"4")
+	RADIO4x (unit, U"Unit", 2, 0)
+		RADIOBUTTON (U"Hz")
+		RADIOBUTTON (U"Semitones")
+	OK
+DO
+	MODIFY_EACH (PitchTier)
+		RealTier_interpolateQuadratically (me, numberOfPointsPerParabola, unit);
+	MODIFY_EACH_END
+}
+
+DIRECT (PLAY_PitchTier_play) {
+	PLAY_EACH (PitchTier)
+		PitchTier_play (me);
+	PLAY_EACH_END
+}
+
+DIRECT (PLAY_PitchTier_playSine) {
+	PLAY_EACH (PitchTier)
+		PitchTier_playPart_sine (me, 0.0, 0.0);
+	PLAY_EACH_END
+}
+
+FORM (MODIFY_PitchTier_shiftFrequencies, U"PitchTier: Shift frequencies", nullptr) {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"1000.0")
+	REALVAR (frequencyShift, U"Frequency shift", U"-20.0")
+	OPTIONMENUVAR (unit, U"Unit", 1)
+		OPTION (U"Hertz")
+		OPTION (U"mel")
+		OPTION (U"logHertz")
+		OPTION (U"semitones")
+		OPTION (U"ERB")
+	OK
+DO
+	unit =
+		unit == 1 ? kPitch_unit_HERTZ :
+		unit == 2 ? kPitch_unit_MEL :
+		unit == 3 ? kPitch_unit_LOG_HERTZ :
+		unit == 4 ? kPitch_unit_SEMITONES_1 :
+		kPitch_unit_ERB;
+	MODIFY_EACH_WEAK (PitchTier)
+		PitchTier_shiftFrequencies (me, fromTime, toTime, frequencyShift, unit);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_PitchTier_multiplyFrequencies, U"PitchTier: Multiply frequencies", nullptr){
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"1000.0")
+	POSITIVEVAR (factor, U"Factor", U"1.2")
+	OK
+DO
+	MODIFY_EACH (PitchTier)
+		PitchTier_multiplyFrequencies (me, fromTime, toTime, factor);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_PitchTier_stylize, U"PitchTier: Stylize", U"PitchTier: Stylize...") {
+	REALVAR (frequencyResolution, U"Frequency resolution", U"4.0")
+	RADIOVARx (unit, U"Unit", 2, 0)
+		RADIOBUTTON (U"Hz")
+		RADIOBUTTON (U"Semitones")
+	OK
+DO
+	MODIFY_EACH (PitchTier)
+		PitchTier_stylize (me, frequencyResolution, unit);
+	MODIFY_EACH_END
+}
+
+DIRECT (NEW_PitchTier_to_PointProcess) {
+	CONVERT_EACH (PitchTier)
+		autoPointProcess result = PitchTier_to_PointProcess (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PitchTier_to_Sound_phonation, U"PitchTier: To Sound (phonation)", nullptr) {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100")
+	POSITIVEVAR (adaptationFactor, U"Adaptation factor", U"1.0")
+	POSITIVEVAR (maximumPeriod, U"Maximum period (s)", U"0.05")
+	POSITIVEVAR (openPhase, U"Open phase", U"0.7")
+	REALVAR (collisionPhase, U"Collision phase", U"0.03")
+	POSITIVEVAR (power1, U"Power 1", U"3.0")
+	POSITIVEVAR (power2, U"Power 2", U"4.0")
+	BOOLEANVAR (hum, U"Hum", false)
+	OK
+DO
+	CONVERT_EACH (PitchTier)
+		autoSound result = PitchTier_to_Sound_phonation (me, samplingFrequency,
+			adaptationFactor, maximumPeriod, openPhase, collisionPhase, power1, power2, hum);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PitchTier_to_Sound_pulseTrain, U"PitchTier: To Sound (pulse train)", nullptr) {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100")
+	POSITIVEVAR (adaptationFactor, U"Adaptation factor", U"1.0")
+	POSITIVEVAR (adaptationTime, U"Adaptation time", U"0.05")
+	NATURALVAR (interpolationDepth, U"Interpolation depth (samples)", U"2000")
+	BOOLEANVAR (hum, U"Hum", false)
+	OK
+DO
+	CONVERT_EACH (PitchTier)
+		autoSound result = PitchTier_to_Sound_pulseTrain (me, samplingFrequency,
+			adaptationFactor, adaptationTime, interpolationDepth, hum);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PitchTier_to_Sound_sine, U"PitchTier: To Sound (sine)", nullptr) {
+	POSITIVEVAR (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	OK
+DO
+	CONVERT_EACH (PitchTier)
+		autoSound result = PitchTier_to_Sound_sine (me, 0.0, 0.0, samplingFrequency);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (HINT_PitchTier_Sound_viewAndEdit) {
+	Melder_information (U"To include a copy of a Sound in your PitchTier window:\n"
+		"   select a PitchTier and a Sound, and click \"View & Edit\".");
+END }
+
+FORM_SAVE (SAVE_PitchTier_writeToPitchTierSpreadsheetFile, U"Save PitchTier as spreadsheet", nullptr, U"PitchTier") {
+	SAVE_ONE (PitchTier)
+		PitchTier_writeToPitchTierSpreadsheetFile (me, file);
+	SAVE_ONE_END
+}
+
+FORM_SAVE (SAVE_PitchTier_writeToHeaderlessSpreadsheetFile, U"Save PitchTier as spreadsheet", nullptr, U"txt") {
+	SAVE_ONE (PitchTier)
+		PitchTier_writeToHeaderlessSpreadsheetFile (me, file);
+	SAVE_ONE_END
+}
+
+DIRECT (INFO_PitchTier_Manipulation_replace) {
+	INFO_NONE
+		Melder_information (U"To replace the PitchTier in a Manipulation object,\n"
+			"select a PitchTier object and a Manipulation object\nand choose \"Replace pitch\".");
+	INFO_NONE_END
+}
+
+// MARK: - PITCHTIER & POINTPROCESS
+
+DIRECT (NEW1_PitchTier_PointProcess_to_PitchTier) {
+	CONVERT_TWO (PitchTier, PointProcess)
+		autoPitchTier result = PitchTier_PointProcess_to_PitchTier (me, you);
+	CONVERT_TWO_END (my name)
+}
+
+// MARK: - POINTPROCESS
+
+FORM (MODIFY_PointProcess_addPoint, U"PointProcess: Add point", U"PointProcess: Add point...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	MODIFY_EACH (PointProcess)
+		PointProcess_addPoint (me, time);
+	MODIFY_EACH_END
+}
+
+FORM (NEW1_PointProcess_createEmpty, U"Create an empty PointProcess", U"Create empty PointProcess...") {
+	WORDVAR (name, U"Name", U"empty")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"1.0")
+	OK
+DO
+	if (endTime < startTime)
+		Melder_throw (U"Your end time (", endTime, U") should not be less than your start time (", startTime, U").");
+	CREATE_ONE
+		autoPointProcess result = PointProcess_create (startTime, endTime, 0L);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_PointProcess_createPoissonProcess, U"Create Poisson process", U"Create Poisson process...") {
+	WORDVAR (name, U"Name", U"poisson")
+	REALVAR (startTime, U"Start time (s)", U"0.0")
+	REALVAR (endTime, U"End time (s)", U"1.0")
+	POSITIVEVAR (density, U"Density (/s)", U"100.0")
+	OK
+DO
+	if (endTime < startTime)
+		Melder_throw (U"Your end time (", endTime, U") should not be less than your start time (", startTime, U").");
+	CREATE_ONE
+		autoPointProcess result = PointProcess_createPoissonProcess (startTime, endTime, density);
+	CREATE_ONE_END (name)
+}
+
+DIRECT (NEW1_PointProcesses_difference) {
+	CONVERT_COUPLE (PointProcess)
+		autoPointProcess result = PointProcesses_difference (me, you);
+	CONVERT_COUPLE_END (U"difference")
+}
+
+FORM (GRAPHICS_PointProcess_draw, U"PointProcess: Draw", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (PointProcess)
+		PointProcess_draw (me, GRAPHICS, fromTime, toTime, garnish);
+	GRAPHICS_EACH_END
+}
+
+DIRECT (WINDOW_PointProcess_viewAndEdit) {
+	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot view or edit a PointProcess from batch.");
+	FIND_TWO (PointProcess, Sound)   // Sound may be null
+		autoPointEditor editor = PointEditor_create (ID_AND_FULL_NAME, me, you);
+		praat_installEditor (editor.get(), IOBJECT);
+		editor.releaseToUser();
+	END
+}
+
+FORM (MODIFY_PointProcess_fill, U"PointProcess: Fill", nullptr) {
+	praat_TimeFunction_RANGE (fromTime, toTime)
+	POSITIVE4 (period, U"Period (s)", U"0.01")
+	OK
+DO
+	MODIFY_EACH_WEAK (PointProcess)
+		PointProcess_fill (me, fromTime, toTime, period);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (REAL_PointProcess_getInterval, U"PointProcess: Get interval", U"PointProcess: Get interval...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getInterval (me, time);
+	NUMBER_ONE_END (U" seconds")
+}
+
+#define dia_PointProcess_getRangeProperty(fromTime,toTime,shortestPeriod,longestPeriod,maximumPeriodfactor) \
+	praat_TimeFunction_RANGE (fromTime, toTime) \
+	REALVAR (shortestPeriod, U"Shortest period (s)", U"0.0001") \
+	REALVAR (longestPeriod, U"Longest period (s)", U"0.02") \
+	POSITIVEVAR (maximumPeriodFactor, U"Maximum period factor", U"1.3")
+
+FORM (REAL_PointProcess_getJitter_local, U"PointProcess: Get jitter (local)", U"PointProcess: Get jitter (local)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getJitter_local (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" (local jitter)")
+}
+
+FORM (REAL_PointProcess_getJitter_local_absolute, U"PointProcess: Get jitter (local, absolute)", U"PointProcess: Get jitter (local, absolute)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getJitter_local_absolute (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" seconds (local absolute jitter)")
+}
+
+FORM (REAL_PointProcess_getJitter_rap, U"PointProcess: Get jitter (rap)", U"PointProcess: Get jitter (rap)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getJitter_rap (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" (rap jitter)")
+}
+
+FORM (REAL_PointProcess_getJitter_ppq5, U"PointProcess: Get jitter (ppq5)", U"PointProcess: Get jitter (ppq5)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getJitter_ppq5 (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" (ppq5 jitter)")
+}
+
+FORM (REAL_PointProcess_getJitter_ddp, U"PointProcess: Get jitter (ddp)", U"PointProcess: Get jitter (ddp)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getJitter_ddp (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" (ddp jitter)")
+}
+
+FORM (REAL_PointProcess_getMeanPeriod, U"PointProcess: Get mean period", U"PointProcess: Get mean period...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getMeanPeriod (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" seconds (mean period)")
+}
+
+FORM (REAL_PointProcess_getStdevPeriod, U"PointProcess: Get stdev period", U"PointProcess: Get stdev period...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = PointProcess_getStdevPeriod (me, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" (stdev period)")
+}
+
+FORM (INTEGER_PointProcess_getLowIndex, U"PointProcess: Get low index", U"PointProcess: Get low index...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		long result = PointProcess_getLowIndex (me, time);
+	NUMBER_ONE_END (U" (low index)")
+}
+
+FORM (INTEGER_PointProcess_getHighIndex, U"PointProcess: Get high index", U"PointProcess: Get high index...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		long result = PointProcess_getHighIndex (me, time);
+	NUMBER_ONE_END (U" (high index)")
+}
+
+FORM (INTEGER_PointProcess_getNearestIndex, U"PointProcess: Get nearest index", U"PointProcess: Get nearest index...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		long result = PointProcess_getNearestIndex (me, time);
+	NUMBER_ONE_END (U" (nearest index)")
+}
+
+DIRECT (INTEGER_PointProcess_getNumberOfPoints) {
+	NUMBER_ONE (PointProcess)
+		long result = my nt;
+	NUMBER_ONE_END (U" points")
+}
+
+FORM (INTEGER_PointProcess_getNumberOfPeriods, U"PointProcess: Get number of periods", U"PointProcess: Get number of periods...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		long result = PointProcess_getNumberOfPeriods (me, fromTime, toTime,
+		shortestPeriod, longestPeriod, maximumPeriodFactor);
+	NUMBER_ONE_END (U" periods")
+}
+
+FORM (REAL_PointProcess_getTimeFromIndex, U"Get time", 0 /*"PointProcess: Get time from index..."*/) {
+	NATURAL4 (pointNumber, U"Point number", U"10")
+	OK
+DO
+	NUMBER_ONE (PointProcess)
+		double result = ( pointNumber > my nt ? NUMundefined : my t [pointNumber] );
+	NUMBER_ONE_END (U" seconds")
+}
+
+DIRECT (HELP_PointProcess_help) {
+	HELP (U"PointProcess")
+}
+
+DIRECT (PLAY_PointProcess_hum) {
+	PLAY_EACH (PointProcess)
+		PointProcess_hum (me, my xmin, my xmax);
+	PLAY_EACH_END
+}
+
+DIRECT (NEW1_PointProcesses_intersection) {
+	CONVERT_COUPLE (PointProcess)
+		autoPointProcess result = PointProcesses_intersection (me, you);
+	CONVERT_COUPLE_END (U"intersection")
+}
+
+DIRECT (PLAY_PointProcess_play) {
+	PLAY_EACH (PointProcess)
+		PointProcess_play (me);
+	PLAY_EACH_END
+}
+
+FORM (MODIFY_PointProcess_removePoint, U"PointProcess: Remove point", U"PointProcess: Remove point...") {
+	NATURAL4 (pointNumber, U"Point number", U"1")
+	OK
+DO
+	MODIFY_EACH (PointProcess)
+		PointProcess_removePoint (me, pointNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_PointProcess_removePointNear, U"PointProcess: Remove point near", U"PointProcess: Remove point near...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	MODIFY_EACH (PointProcess)
+		PointProcess_removePointNear (me, time);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_PointProcess_removePoints, U"PointProcess: Remove points", U"PointProcess: Remove points...") {
+	NATURAL4 (fromPointNumber, U"From point number", U"1")
+	NATURAL4 (toPointNumber, U"To point number", U"10")
+	OK
+DO
+	MODIFY_EACH (PointProcess)
+		PointProcess_removePoints (me, fromPointNumber, toPointNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_PointProcess_removePointsBetween, U"PointProcess: Remove points between", U"PointProcess: Remove points between...") {
+	REAL4 (fromTime, U"left Time range (s)", U"0.3")
+	REAL4 (toTime, U"right Time range (s)", U"0.7")
+	OK
+DO
+	MODIFY_EACH (PointProcess)
+		PointProcess_removePointsBetween (me, fromTime, toTime);
+	MODIFY_EACH_END
+}
+
+DIRECT (NEW_PointProcess_to_IntervalTier) {
+	CONVERT_EACH (PointProcess)
+		autoIntervalTier result = IntervalTier_create (my xmin, my xmax);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_PointProcess_to_Matrix) {
+	CONVERT_EACH (PointProcess)
+		autoMatrix result = PointProcess_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_to_PitchTier, U"PointProcess: To PitchTier", U"PointProcess: To PitchTier...") {
+	POSITIVEVAR (maximumInterval, U"Maximum interval (s)", U"0.02")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoPitchTier result = PointProcess_to_PitchTier (me, maximumInterval);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_to_TextGrid, U"PointProcess: To TextGrid...", U"PointProcess: To TextGrid...") {
+	SENTENCE4 (tierNames, U"Tier names", U"Mary John bell")
+	SENTENCE4 (pointTiers, U"Point tiers", U"bell")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoTextGrid result = TextGrid_create (my xmin, my xmax, tierNames, pointTiers);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_to_TextGrid_vuv, U"PointProcess: To TextGrid (vuv)...", U"PointProcess: To TextGrid (vuv)...") {
+	POSITIVE4 (maximumPeriod, U"Maximum period (s)", U"0.02")
+	REAL4 (meanPeriod, U"Mean period (s)", U"0.01")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoTextGrid result = PointProcess_to_TextGrid_vuv (me, maximumPeriod, meanPeriod);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_PointProcess_to_TextTier) {
+	CONVERT_EACH (PointProcess)
+		autoTextTier result = TextTier_create (my xmin, my xmax);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_to_Sound_phonation, U"PointProcess: To Sound (phonation)", U"PointProcess: To Sound (phonation)...") {
+	POSITIVE4 (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	POSITIVE4 (adaptationFactor, U"Adaptation factor", U"1.0")
+	POSITIVE4 (maximumPeriod, U"Maximum period (s)", U"0.05")
+	POSITIVE4 (openPhase, U"Open phase", U"0.7")
+	REAL4 (collisionPhase, U"Collision phase", U"0.03")
+	POSITIVE4 (power1, U"Power 1", U"3.0")
+	POSITIVE4 (power2, U"Power 2", U"4.0")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoSound result = PointProcess_to_Sound_phonation (me, samplingFrequency,
+			adaptationFactor, maximumPeriod, openPhase, collisionPhase, power1, power2);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_to_Sound_pulseTrain, U"PointProcess: To Sound (pulse train)", U"PointProcess: To Sound (pulse train)...") {
+	POSITIVE4 (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
+	POSITIVE4 (adaptationFactor, U"Adaptation factor", U"1.0")
+	POSITIVE4 (adaptationTime, U"Adaptation time (s)", U"0.05")
+	NATURAL4 (interpolationDepth, U"Interpolation depth (samples)", U"2000")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoSound result = PointProcess_to_Sound_pulseTrain (me, samplingFrequency,
+			adaptationFactor, adaptationTime, interpolationDepth);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW_PointProcess_to_Sound_hum) {
+	CONVERT_EACH (PointProcess)
+		autoSound result = PointProcess_to_Sound_hum (me);
+	CONVERT_EACH_END (my name)
+}
+
+DIRECT (NEW1_PointProcesses_union) {
+	CONVERT_COUPLE (PointProcess)
+		autoPointProcess result = PointProcesses_union (me, you);
+	CONVERT_COUPLE_END (U"union")
+}
+
+FORM (NEW_PointProcess_upto_IntensityTier, U"PointProcess: Up to IntensityTier", U"PointProcess: Up to IntensityTier...") {
+	POSITIVE4 (intensity, U"Intensity (dB)", U"70.0")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoIntensityTier result = PointProcess_upto_IntensityTier (me, intensity);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_upto_PitchTier, U"PointProcess: Up to PitchTier", U"PointProcess: Up to PitchTier...") {
+	POSITIVE4 (frequency, U"Frequency (Hz)", U"190.0")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoPitchTier result = PointProcess_upto_PitchTier (me, frequency);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_PointProcess_upto_TextTier, U"PointProcess: Up to TextTier", U"PointProcess: Up to TextTier...") {
+	SENTENCE4 (text, U"Text", U"")
+	OK
+DO
+	CONVERT_EACH (PointProcess)
+		autoTextTier result = PointProcess_upto_TextTier (me, text);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (MODIFY_PointProcess_voice, U"PointProcess: Fill unvoiced parts", nullptr) {
+	POSITIVEVAR (period, U"Period (s)", U"0.01")
+	POSITIVEVAR (maximumVoicedPeriod, U"Maximum voiced period (s)", U"0.02000000001")
+	OK
+DO
+	MODIFY_EACH_WEAK (PointProcess)
+		PointProcess_voice (me, period, maximumVoicedPeriod);
+	MODIFY_EACH_WEAK_END
+}
+
+DIRECT (HINT_PointProcess_Sound_viewAndEdit) {
+	INFO_NONE
+		Melder_information (U"To include a copy of a Sound in your PointProcess window:\n"
+			"   select a PointProcess and a Sound, and click \"View & Edit\".");
+	INFO_NONE_END
+}
+
+// MARK: - POINTPROCESS & SOUND
+
+DIRECT (MODIFY_Point_Sound_transplantDomain) {
+	MODIFY_FIRST_OF_TWO (PointProcess, Sound)
+		my xmin = your xmin;
+		my xmax = your xmax;
+	MODIFY_FIRST_OF_TWO_END
+}
+
+FORM (REAL_Point_Sound_getShimmer_local, U"PointProcess & Sound: Get shimmer (local)", U"PointProcess & Sound: Get shimmer (local)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	POSITIVEVAR (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_TWO (PointProcess, Sound)
+		double result = PointProcess_Sound_getShimmer_local (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor, maximumAmplitudeFactor);
+	NUMBER_TWO_END (U" (local shimmer)");
+}
+
+FORM (REAL_Point_Sound_getShimmer_local_dB, U"PointProcess & Sound: Get shimmer (local, dB)", U"PointProcess & Sound: Get shimmer (local, dB)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	POSITIVEVAR (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_TWO (PointProcess, Sound)
+		double result = PointProcess_Sound_getShimmer_local_dB (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor, maximumAmplitudeFactor);
+	NUMBER_TWO_END (U" dB (local shimmer)");
+}
+
+FORM (REAL_Point_Sound_getShimmer_apq3, U"PointProcess & Sound: Get shimmer (apq3)", U"PointProcess & Sound: Get shimmer (apq3)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	POSITIVEVAR (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_TWO (PointProcess, Sound)
+		double result = PointProcess_Sound_getShimmer_apq3 (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor, maximumAmplitudeFactor);
+	NUMBER_TWO_END (U" (apq3 shimmer)");
+}
+
+FORM (REAL_Point_Sound_getShimmer_apq5, U"PointProcess & Sound: Get shimmer (apq)", U"PointProcess & Sound: Get shimmer (apq5)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	POSITIVEVAR (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_TWO (PointProcess, Sound)
+		double result = PointProcess_Sound_getShimmer_apq5 (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor, maximumAmplitudeFactor);
+	NUMBER_TWO_END (U" (apq5 shimmer)");
+}
+
+FORM (REAL_Point_Sound_getShimmer_apq11, U"PointProcess & Sound: Get shimmer (apq11)", U"PointProcess & Sound: Get shimmer (apq11)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	POSITIVEVAR (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_TWO (PointProcess, Sound)
+		double result = PointProcess_Sound_getShimmer_apq11 (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor, maximumAmplitudeFactor);
+	NUMBER_TWO_END (U" (apq11 shimmer)");
+}
+
+FORM (REAL_Point_Sound_getShimmer_dda, U"PointProcess & Sound: Get shimmer (dda)", U"PointProcess & Sound: Get shimmer (dda)...") {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	POSITIVEVAR (maximumAmplitudeFactor, U"Maximum amplitude factor", U"1.6")
+	OK
+DO
+	NUMBER_TWO (PointProcess, Sound)
+		double result = PointProcess_Sound_getShimmer_dda (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor, maximumAmplitudeFactor);
+	NUMBER_TWO_END (U" (dda shimmer)");
+}
+
+FORM (NEW1_PointProcess_Sound_to_AmplitudeTier_period, U"PointProcess & Sound: To AmplitudeTier (period)", nullptr) {
+	dia_PointProcess_getRangeProperty (fromTime, toTime, shortestPeriod, longestPeriod, maximumPeriodfactor)
+	OK
+DO
+	CONVERT_TWO (PointProcess, Sound)
+		autoAmplitudeTier result = PointProcess_Sound_to_AmplitudeTier_period (me, you, fromTime, toTime,
+			shortestPeriod, longestPeriod, maximumPeriodFactor);
+	CONVERT_TWO_END (your name, U"_", my name)
+}
+
+DIRECT (NEW1_PointProcess_Sound_to_AmplitudeTier_point) {
+	CONVERT_TWO (PointProcess, Sound)
+		autoAmplitudeTier result = PointProcess_Sound_to_AmplitudeTier_point (me, you);
+	CONVERT_TWO_END (your name, U"_", my name);
+}
+
+FORM (NEW1_PointProcess_Sound_to_Ltas, U"PointProcess & Sound: To Ltas", nullptr) {
+	POSITIVE4 (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
+	POSITIVE4 (bandwidth, U"Band width (Hz)", U"100.0")
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumPeriodFactor, U"Maximum period factor", U"1.3")
+	OK
+DO
+	CONVERT_TWO (PointProcess, Sound)
+		autoLtas result = PointProcess_Sound_to_Ltas (me, you,
+			maximumFrequency, bandwidth, shortestPeriod, longestPeriod, maximumPeriodFactor);
+	CONVERT_TWO_END (your name)
+}
+
+FORM (NEW1_PointProcess_Sound_to_Ltas_harmonics, U"PointProcess & Sound: To Ltas (harmonics", nullptr) {
+	NATURAL4 (maximumHarmonic, U"Maximum harmonic", U"20")
+	REAL4 (shortestPeriod, U"Shortest period (s)", U"0.0001")
+	REAL4 (longestPeriod, U"Longest period (s)", U"0.02")
+	POSITIVE4 (maximumPeriodFactor, U"Maximum period factor", U"1.3")
+	OK
+DO
+	CONVERT_TWO (PointProcess, Sound)
+		autoLtas result = PointProcess_Sound_to_Ltas_harmonics (me, you,
+			maximumHarmonic, shortestPeriod, longestPeriod, maximumPeriodFactor);
+	CONVERT_TWO_END (your name)
+}
+
+FORM (NEW1_Sound_PointProcess_to_SoundEnsemble_correlate, U"Sound & PointProcess: To SoundEnsemble (correlate)", nullptr) {
+	REAL4 (fromTime, U"From time (s)", U"-0.1")
+	REAL4 (toTime, U"To time (s)", U"1.0")
+	OK
+DO
+	CONVERT_TWO (Sound, PointProcess)
+		autoSound result = Sound_PointProcess_to_SoundEnsemble_correlate (me, you, fromTime, toTime);
+	CONVERT_TWO_END (your name)
+}
+
+// MARK: - SPECTRUMTIER
+
+DIRECT (NEW_SpectrumTier_downto_Table) {
+	CONVERT_EACH (SpectrumTier)
+		autoTable result = SpectrumTier_downto_Table (me, true, true, true);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (GRAPHICS_old_SpectrumTier_draw, U"SpectrumTier: Draw", nullptr) {   // 2010-10-19
+	REAL4 (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REAL4 (toFrequency, U"right Frequency range (Hz)", U"10000.0")
+	REAL4 (fromPower, U"left Power range (dB)", U"20.0")
+	REAL4 (toPower, U"right Power range (dB)", U"80.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (SpectrumTier)
+		SpectrumTier_draw (me, GRAPHICS, fromFrequency, toFrequency,
+			fromPower, toPower, garnish, U"lines and speckles");
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_SpectrumTier_draw, U"SpectrumTier: Draw", nullptr) {
+	REAL4 (fromFrequency, U"left Frequency range (Hz)", U"0.0")
+	REAL4 (toFrequency, U"right Frequency range (Hz)", U"10000.0")
+	REAL4 (fromPower, U"left Power range (dB)", U"20.0")
+	REAL4 (toPower, U"right Power range (dB)", U"80.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	LABEL (U"", U"")
+	OPTIONMENUSTR4 (drawingMethod, U"Drawing method", 1)
+		OPTION (U"lines")
+		OPTION (U"speckles")
+		OPTION (U"lines and speckles")
+	OK
+DO_ALTERNATIVE (GRAPHICS_old_SpectrumTier_draw)
+	GRAPHICS_EACH (SpectrumTier)
+		SpectrumTier_draw (me, GRAPHICS, fromFrequency, toFrequency,
+			fromPower, toPower, garnish, drawingMethod);
+	GRAPHICS_EACH_END
+}
+
+FORM (LIST_SpectrumTier_list, U"SpectrumTier: List", nullptr) {
+	BOOLEAN4 (includeIndexes, U"Include indexes", true)
+	BOOLEAN4 (includeFrequency, U"Include frequency", true)
+	BOOLEAN4 (includePowerDensity, U"Include power density", true)
+	OK
+DO
+	INFO_ONE (SpectrumTier)
+		SpectrumTier_list (me, includeIndexes, includeFrequency, includePowerDensity);
+	INFO_ONE_END
+}
+
+FORM (MODIFY_SpectrumTier_removePointsBelow, U"SpectrumTier: Remove points below", nullptr) {
+	REAL4 (removeAllPointsBelow, U"Remove all points below (dB)", U"40.0")
+	OK
+DO
+	MODIFY_EACH (SpectrumTier)
+		RealTier_removePointsBelow (me, removeAllPointsBelow);
+	MODIFY_EACH_END
+}
+
+// MARK: - buttons
+
+void praat_Tiers_init () {
+	Thing_recognizeClassesByName (classPointProcess,
+		classRealPoint, classRealTier,
+		classPitchTier, classIntensityTier, classDurationTier, classAmplitudeTier,
+		classSpectrumTier,
+		classFormantPoint, classFormantTier, classFormantGrid,
+		nullptr);
+
+	praat_addMenuCommand (U"Objects", U"New", U"Tiers", nullptr, 0, nullptr);
+		praat_addMenuCommand (U"Objects", U"New", U"Create empty PointProcess...", nullptr, 1, NEW1_PointProcess_createEmpty);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Poisson process...", nullptr, 1, NEW1_PointProcess_createPoissonProcess);
+		praat_addMenuCommand (U"Objects", U"New", U"-- new tiers ---", nullptr, 1, nullptr);
+		praat_addMenuCommand (U"Objects", U"New", U"Create PitchTier...", nullptr, 1, NEW1_PitchTier_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create FormantGrid...", nullptr, 1, NEW1_FormantGrid_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create FormantTier...", nullptr, praat_HIDDEN | praat_DEPTH_1, NEW1_FormantTier_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create IntensityTier...", nullptr, 1, NEW1_IntensityTier_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create DurationTier...", nullptr, 1, NEW1_DurationTier_create);
+		praat_addMenuCommand (U"Objects", U"New", U"Create AmplitudeTier...", nullptr, 1, NEW1_AmplitudeTier_create);
+
+	praat_addAction1 (classAmplitudeTier, 0, U"AmplitudeTier help", nullptr, 0, HELP_AmplitudeTier_help);
+	praat_addAction1 (classAmplitudeTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_AmplitudeTier_viewAndEdit);
+	praat_addAction1 (classAmplitudeTier, 1,   U"Edit", nullptr, praat_DEPRECATED_2011, WINDOW_AmplitudeTier_viewAndEdit);
+	praat_addAction1 (classAmplitudeTier, 0, U"View & Edit with Sound?", nullptr, 0, HINT_AmplitudeTier_Sound_viewAndEdit);
+	praat_addAction1 (classAmplitudeTier, 0, U"Query -", nullptr, 0, nullptr);
+		praat_TimeTier_query_init (classAmplitudeTier);
+		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (local)...", nullptr, 1, REAL_AmplitudeTier_getShimmer_local);
+		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (local_dB)...", nullptr, 1, REAL_AmplitudeTier_getShimmer_local_dB);
+		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (apq3)...", nullptr, 1, REAL_AmplitudeTier_getShimmer_apq3);
+		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (apq5)...", nullptr, 1, REAL_AmplitudeTier_getShimmer_apq5);
+		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (apq11)...", nullptr, 1, REAL_AmplitudeTier_getShimmer_apq11);
+		praat_addAction1 (classAmplitudeTier, 1, U"Get shimmer (dda)...", nullptr, 1, REAL_AmplitudeTier_getShimmer_dda);
+	praat_addAction1 (classAmplitudeTier, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeTier_modify_init (classAmplitudeTier);
+		praat_addAction1 (classAmplitudeTier, 0, U"Add point...", nullptr, 1, MODIFY_AmplitudeTier_addPoint);
+		praat_addAction1 (classAmplitudeTier, 0, U"Formula...", nullptr, 1, MODIFY_AmplitudeTier_formula);
+	praat_addAction1 (classAmplitudeTier, 0, U"Synthesize", nullptr, 0, nullptr);
+		praat_addAction1 (classAmplitudeTier, 0, U"To Sound (pulse train)...", nullptr, 0, NEW_AmplitudeTier_to_Sound);
+	praat_addAction1 (classAmplitudeTier, 0, U"Convert", nullptr, 0, nullptr);
+		praat_addAction1 (classAmplitudeTier, 0, U"To IntensityTier...", nullptr, 0, NEW_AmplitudeTier_to_IntensityTier);
+		praat_addAction1 (classAmplitudeTier, 0, U"Down to PointProcess", nullptr, 0, NEW_AmplitudeTier_downto_PointProcess);
+		praat_addAction1 (classAmplitudeTier, 0, U"Down to TableOfReal", nullptr, 0, NEW_AmplitudeTier_downto_TableOfReal);
+
+	praat_addAction1 (classDurationTier, 0, U"DurationTier help", nullptr, 0, HELP_DurationTier_help);
+	praat_addAction1 (classDurationTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_DurationTier_edit);
+	praat_addAction1 (classDurationTier, 1,   U"Edit", nullptr, praat_DEPRECATED_2011, WINDOW_DurationTier_edit);
+	praat_addAction1 (classDurationTier, 0, U"View & Edit with Sound?", nullptr, 0, HINT_DurationTier_Sound_edit);
+	praat_addAction1 (classDurationTier, 0, U"& Manipulation: Replace?", nullptr, 0, HINT_DurationTier_Manipulation_replace);
+	praat_addAction1 (classDurationTier, 0, U"Query -", nullptr, 0, nullptr);
+		praat_TimeTier_query_init (classDurationTier);
+		praat_addAction1 (classDurationTier, 1, U"-- get content --", nullptr, 1, nullptr);
+		praat_addAction1 (classDurationTier, 1, U"Get value at time...", nullptr, 1, REAL_DurationTier_getValueAtTime);
+		praat_addAction1 (classDurationTier, 1, U"Get value at index...", nullptr, 1, REAL_DurationTier_getValueAtIndex);
+		praat_addAction1 (classDurationTier, 1, U"Get target duration...", nullptr, 1, REAL_DurationTier_getTargetDuration);
+	praat_addAction1 (classDurationTier, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeTier_modify_init (classDurationTier);
+		praat_addAction1 (classDurationTier, 0, U"Add point...", nullptr, 1, MODIFY_DurationTier_addPoint);
+		praat_addAction1 (classDurationTier, 0, U"Formula...", nullptr, 1, MODIFY_DurationTier_formula);
+	praat_addAction1 (classDurationTier, 0, U"Convert", nullptr, 0, nullptr);
+		praat_addAction1 (classDurationTier, 0, U"Down to PointProcess", nullptr, 0, NEW_DurationTier_downto_PointProcess);
+
+	praat_addAction1 (classFormantGrid, 0, U"FormantGrid help", nullptr, 0, HELP_FormantGrid_help);
+	praat_addAction1 (classFormantGrid, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_FormantGrid_edit);
+	praat_addAction1 (classFormantGrid, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_FormantGrid_edit);
+	praat_addAction1 (classFormantGrid, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeFunction_modify_init (classFormantGrid);
+		praat_addAction1 (classFormantGrid, 0, U"Formula (frequencies)...", nullptr, 1, MODIFY_FormantGrid_formula_frequencies);
+		//praat_addAction1 (classFormantGrid, 0, U"Formula (bandwidths)...", nullptr, 1, MODIFY_FormantGrid_formula_bandwidths);
+		praat_addAction1 (classFormantGrid, 0, U"Add formant point...", nullptr, 1, MODIFY_FormantGrid_addFormantPoint);
+		praat_addAction1 (classFormantGrid, 0, U"Add bandwidth point...", nullptr, 1, MODIFY_FormantGrid_addBandwidthPoint);
+		praat_addAction1 (classFormantGrid, 0, U"Remove formant points between...", nullptr, 1, MODIFY_FormantGrid_removeFormantPointsBetween);
+		praat_addAction1 (classFormantGrid, 0, U"Remove bandwidth points between...", nullptr, 1, MODIFY_FormantGrid_removeBandwidthPointsBetween);
+	praat_addAction1 (classFormantGrid, 0, U"Convert -", nullptr, 0, nullptr);
+		praat_addAction1 (classFormantGrid, 0, U"To Formant...", nullptr, 1, NEW_FormantGrid_to_Formant);
+
+	praat_addAction1 (classFormantTier, 0, U"Draw -", nullptr, 0, nullptr);
+		praat_addAction1 (classFormantTier, 0, U"Speckle...", nullptr, 1, GRAPHICS_FormantTier_speckle);
+	praat_addAction1 (classFormantTier, 0, U"Query -", nullptr, 0, nullptr);
+		praat_TimeTier_query_init (classFormantTier);
+		praat_addAction1 (classFormantTier, 1, U"-- get value --", nullptr, 1, nullptr);
+		praat_addAction1 (classFormantTier, 1, U"Get value at time...", nullptr, 1, REAL_FormantTier_getValueAtTime);
+		praat_addAction1 (classFormantTier, 1, U"Get bandwidth at time...", nullptr, 1, REAL_FormantTier_getBandwidthAtTime);
+	praat_addAction1 (classFormantTier, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeTier_modify_init (classFormantTier);
+		praat_addAction1 (classFormantTier, 0, U"Add point...", nullptr, 1, MODIFY_FormantTier_addPoint);
+	praat_addAction1 (classFormantTier, 0, U"Down", nullptr, 0, nullptr);
+		praat_addAction1 (classFormantTier, 0, U"Down to TableOfReal...", nullptr, 0, NEW_FormantTier_downto_TableOfReal);
+
+	praat_addAction1 (classIntensityTier, 0, U"IntensityTier help", nullptr, 0, HELP_IntensityTier_help);
+	praat_addAction1 (classIntensityTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_IntensityTier_viewAndEdit);
+	praat_addAction1 (classIntensityTier, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_IntensityTier_viewAndEdit);
+	praat_addAction1 (classIntensityTier, 0, U"View & Edit with Sound?", nullptr, 0, HINT_IntensityTier_Sound_viewAndEdit);
+	praat_addAction1 (classIntensityTier, 0, U"Query -", nullptr, 0, nullptr);
+		praat_TimeTier_query_init (classIntensityTier);
+		praat_addAction1 (classIntensityTier, 1, U"-- get content --", nullptr, 1, nullptr);
+		praat_addAction1 (classIntensityTier, 1, U"Get value at time...", nullptr, 1, REAL_IntensityTier_getValueAtTime);
+		praat_addAction1 (classIntensityTier, 1, U"Get value at index...", nullptr, 1, REAL_IntensityTier_getValueAtIndex);
+	praat_addAction1 (classIntensityTier, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeTier_modify_init (classIntensityTier);
+		praat_addAction1 (classIntensityTier, 0, U"Add point...", nullptr, 1, MODIFY_IntensityTier_addPoint);
+		praat_addAction1 (classIntensityTier, 0, U"Formula...", nullptr, 1, MODIFY_IntensityTier_formula);
+	praat_addAction1 (classIntensityTier, 0, U"Convert", nullptr, 0, nullptr);
+		praat_addAction1 (classIntensityTier, 0, U"To AmplitudeTier", nullptr, 0, NEW_IntensityTier_to_AmplitudeTier);
+		praat_addAction1 (classIntensityTier, 0, U"Down to PointProcess", nullptr, 0, NEW_IntensityTier_downto_PointProcess);
+		praat_addAction1 (classIntensityTier, 0, U"Down to TableOfReal", nullptr, 0, NEW_IntensityTier_downto_TableOfReal);
+
+	praat_addAction1 (classPitchTier, 1, U"Save as PitchTier spreadsheet file...", nullptr, 0, SAVE_PitchTier_writeToPitchTierSpreadsheetFile);
+	praat_addAction1 (classPitchTier, 1,   U"Write to PitchTier spreadsheet file...", U"*Save as PitchTier spreadsheet file...", praat_DEPRECATED_2011, SAVE_PitchTier_writeToPitchTierSpreadsheetFile);
+	praat_addAction1 (classPitchTier, 1, U"Save as headerless spreadsheet file...", nullptr, 0, SAVE_PitchTier_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (classPitchTier, 1,   U"Write to headerless spreadsheet file...", U"*Save as headerless spreadsheet file...", praat_DEPRECATED_2011, SAVE_PitchTier_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (classPitchTier, 0, U"PitchTier help", nullptr, 0, HELP_PitchTier_help);
+	praat_addAction1 (classPitchTier, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_PitchTier_viewAndEdit);
+	praat_addAction1 (classPitchTier, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_PitchTier_viewAndEdit);
+	praat_addAction1 (classPitchTier, 0, U"View & Edit with Sound?", nullptr, 0, HINT_PitchTier_Sound_viewAndEdit);
+	praat_addAction1 (classPitchTier, 0, U"Play pulses", nullptr, 0, PLAY_PitchTier_play);
+	praat_addAction1 (classPitchTier, 0, U"Hum", nullptr, 0, PLAY_PitchTier_hum);
+	praat_addAction1 (classPitchTier, 0, U"Play sine", nullptr, 0, PLAY_PitchTier_playSine);
+	praat_addAction1 (classPitchTier, 0, U"Draw...", nullptr, 0, GRAPHICS_PitchTier_draw);
+	praat_addAction1 (classPitchTier, 0, U"& Manipulation: Replace?", nullptr, 0, INFO_PitchTier_Manipulation_replace);
+	praat_addAction1 (classPitchTier, 0, U"Query -", nullptr, 0, nullptr);
+		praat_TimeTier_query_init (classPitchTier);
+		praat_addAction1 (classPitchTier, 1, U"-- get content --", nullptr, 1, nullptr);
+		praat_addAction1 (classPitchTier, 1, U"Get value at time...", nullptr, 1, REAL_PitchTier_getValueAtTime);
+		praat_addAction1 (classPitchTier, 1, U"Get value at index...", nullptr, 1, REAL_PitchTier_getValueAtIndex);
+		praat_addAction1 (classPitchTier, 1, U"-- get statistics --", nullptr, 1, nullptr);
+		praat_addAction1 (classPitchTier, 1, U"Get mean (curve)...", nullptr, 1, REAL_PitchTier_getMean_curve);
+		praat_addAction1 (classPitchTier, 1, U"Get mean (points)...", nullptr, 1, REAL_PitchTier_getMean_points);
+		praat_addAction1 (classPitchTier, 1, U"Get standard deviation (curve)...", nullptr, 1, REAL_PitchTier_getStandardDeviation_curve);
+		praat_addAction1 (classPitchTier, 1, U"Get standard deviation (points)...", nullptr, 1, REAL_PitchTier_getStandardDeviation_points);
+	praat_addAction1 (classPitchTier, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeTier_modify_init (classPitchTier);
+		praat_addAction1 (classPitchTier, 0, U"Add point...", nullptr, 1, MODIFY_PitchTier_addPoint);
+		praat_addAction1 (classPitchTier, 0, U"Formula...", nullptr, 1, MODIFY_PitchTier_formula);
+		praat_addAction1 (classPitchTier, 0, U"-- stylize --", nullptr, 1, nullptr);
+		praat_addAction1 (classPitchTier, 0, U"Stylize...", nullptr, 1, MODIFY_PitchTier_stylize);
+		praat_addAction1 (classPitchTier, 0, U"Interpolate quadratically...", nullptr, 1, MODIFY_PitchTier_interpolateQuadratically);
+		praat_addAction1 (classPitchTier, 0, U"-- modify frequencies --", nullptr, 1, nullptr);
+		praat_addAction1 (classPitchTier, 0, U"Shift frequencies...", nullptr, 1, MODIFY_PitchTier_shiftFrequencies);
+		praat_addAction1 (classPitchTier, 0, U"Multiply frequencies...", nullptr, 1, MODIFY_PitchTier_multiplyFrequencies);
+	praat_addAction1 (classPitchTier, 0, U"Synthesize -", nullptr, 0, nullptr);
+		praat_addAction1 (classPitchTier, 0, U"To PointProcess", nullptr, 1, NEW_PitchTier_to_PointProcess);
+		praat_addAction1 (classPitchTier, 0, U"To Sound (pulse train)...", nullptr, 1, NEW_PitchTier_to_Sound_pulseTrain);
+		praat_addAction1 (classPitchTier, 0, U"To Sound (phonation)...", nullptr, 1, NEW_PitchTier_to_Sound_phonation);
+		praat_addAction1 (classPitchTier, 0, U"To Sound (sine)...", nullptr, 1, NEW_PitchTier_to_Sound_sine);
+	praat_addAction1 (classPitchTier, 0, U"Convert -", nullptr, 0, nullptr);
+		praat_addAction1 (classPitchTier, 0, U"Down to PointProcess", nullptr, 1, NEW_PitchTier_downto_PointProcess);
+		praat_addAction1 (classPitchTier, 0, U"Down to TableOfReal...", nullptr, 1, NEW_PitchTier_downto_TableOfReal);
+
+	praat_addAction1 (classPointProcess, 0, U"PointProcess help", nullptr, 0, HELP_PointProcess_help);
+	praat_addAction1 (classPointProcess, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_PointProcess_viewAndEdit);
+	praat_addAction1 (classPointProcess, 1,   U"View & Edit alone", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_PointProcess_viewAndEdit);
+	praat_addAction1 (classPointProcess, 1,   U"Edit alone", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_PointProcess_viewAndEdit);
+	praat_addAction1 (classPointProcess, 0, U"View & Edit with Sound?", nullptr, praat_NO_API, HINT_PointProcess_Sound_viewAndEdit);
+	praat_addAction1 (classPointProcess, 0, U"Play -", nullptr, 0, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"Play as pulse train", nullptr, 1, PLAY_PointProcess_play);
+		praat_addAction1 (classPointProcess, 0, U"Hum", nullptr, 1, PLAY_PointProcess_hum);
+		praat_addAction1 (classPointProcess, 0, U"-- to sound --", nullptr, 1, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"To Sound (pulse train)...", nullptr, 1, NEW_PointProcess_to_Sound_pulseTrain);
+		praat_addAction1 (classPointProcess, 0, U"To Sound (phonation)...", nullptr, 1, NEW_PointProcess_to_Sound_phonation);
+		praat_addAction1 (classPointProcess, 0, U"To Sound (hum)", nullptr, 1, NEW_PointProcess_to_Sound_hum);
+	praat_addAction1 (classPointProcess, 0, U"Draw...", nullptr, 0, GRAPHICS_PointProcess_draw);
+	praat_addAction1 (classPointProcess, 0, U"Query -", nullptr, 0, nullptr);
+		praat_TimeFunction_query_init (classPointProcess);
+		praat_addAction1 (classPointProcess, 1, U"-- script get --", nullptr, 1, nullptr);
+		praat_addAction1 (classPointProcess, 1, U"Get number of points", nullptr, 1, INTEGER_PointProcess_getNumberOfPoints);
+		praat_addAction1 (classPointProcess, 1, U"Get low index...", nullptr, 1, INTEGER_PointProcess_getLowIndex);
+		praat_addAction1 (classPointProcess, 1, U"Get high index...", nullptr, 1, INTEGER_PointProcess_getHighIndex);
+		praat_addAction1 (classPointProcess, 1, U"Get nearest index...", nullptr, 1, INTEGER_PointProcess_getNearestIndex);
+		praat_addAction1 (classPointProcess, 1, U"Get time from index...", nullptr, 1, REAL_PointProcess_getTimeFromIndex);
+		praat_addAction1 (classPointProcess, 1, U"Get interval...", nullptr, 1, REAL_PointProcess_getInterval);
+		praat_addAction1 (classPointProcess, 1, U"-- periods --", nullptr, 1, nullptr);
+		praat_addAction1 (classPointProcess, 1, U"Get number of periods...", nullptr, 1, INTEGER_PointProcess_getNumberOfPeriods);
+		praat_addAction1 (classPointProcess, 1, U"Get mean period...", nullptr, 1, REAL_PointProcess_getMeanPeriod);
+		praat_addAction1 (classPointProcess, 1, U"Get stdev period...", nullptr, 1, REAL_PointProcess_getStdevPeriod);
+		praat_addAction1 (classPointProcess, 1, U"Get jitter (local)...", nullptr, 1, REAL_PointProcess_getJitter_local);
+		praat_addAction1 (classPointProcess, 1, U"Get jitter (local, absolute)...", nullptr, 1, REAL_PointProcess_getJitter_local_absolute);
+		praat_addAction1 (classPointProcess, 1, U"Get jitter (rap)...", nullptr, 1, REAL_PointProcess_getJitter_rap);
+		praat_addAction1 (classPointProcess, 1, U"Get jitter (ppq5)...", nullptr, 1, REAL_PointProcess_getJitter_ppq5);
+		praat_addAction1 (classPointProcess, 1, U"Get jitter (ddp)...", nullptr, 1, REAL_PointProcess_getJitter_ddp);
+	praat_addAction1 (classPointProcess, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_TimeFunction_modify_init (classPointProcess);
+		praat_addAction1 (classPointProcess, 0, U"Add point...", nullptr, 1, MODIFY_PointProcess_addPoint);
+		praat_addAction1 (classPointProcess, 0, U"Remove point...", nullptr, 1, MODIFY_PointProcess_removePoint);
+		praat_addAction1 (classPointProcess, 0, U"Remove point near...", nullptr, 1, MODIFY_PointProcess_removePointNear);
+		praat_addAction1 (classPointProcess, 0, U"Remove points...", nullptr, 1, MODIFY_PointProcess_removePoints);
+		praat_addAction1 (classPointProcess, 0, U"Remove points between...", nullptr, 1, MODIFY_PointProcess_removePointsBetween);
+		praat_addAction1 (classPointProcess, 0, U"-- voice --", nullptr, 1, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"Fill...", nullptr, 1, MODIFY_PointProcess_fill);
+		praat_addAction1 (classPointProcess, 0, U"Voice...", nullptr, 1, MODIFY_PointProcess_voice);
+	praat_addAction1 (classPointProcess, 0, U"Annotate -", nullptr, 0, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"To TextGrid...", nullptr, 1, NEW_PointProcess_to_TextGrid);
+		praat_addAction1 (classPointProcess, 0, U"-- to single tier --", nullptr, 1, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"To TextTier", nullptr, 1, NEW_PointProcess_to_TextTier);
+		praat_addAction1 (classPointProcess, 0, U"To IntervalTier", nullptr, 1, NEW_PointProcess_to_IntervalTier);
+	praat_addAction1 (classPointProcess, 0, U"Analyse -", nullptr, 0, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"To PitchTier...", nullptr, 1, NEW_PointProcess_to_PitchTier);
+		praat_addAction1 (classPointProcess, 0, U"To TextGrid (vuv)...", nullptr, 1, NEW_PointProcess_to_TextGrid_vuv);
+	praat_addAction1 (classPointProcess, 0, U"Convert -", nullptr, 0, nullptr);
+		praat_addAction1 (classPointProcess, 0, U"Hack", nullptr, 1, nullptr);
+			praat_addAction1 (classPointProcess, 0, U"To Matrix", nullptr, 2, NEW_PointProcess_to_Matrix);
+			praat_addAction1 (classPointProcess, 0, U"Up to TextTier...", nullptr, 2, NEW_PointProcess_upto_TextTier);
+			praat_addAction1 (classPointProcess, 0, U"Up to PitchTier...", nullptr, 2, NEW_PointProcess_upto_PitchTier);
+			praat_addAction1 (classPointProcess, 0, U"Up to IntensityTier...", nullptr, 2, NEW_PointProcess_upto_IntensityTier);
+	praat_addAction1 (classPointProcess, 0, U"Combine -", nullptr, 0, nullptr);
+		praat_addAction1 (classPointProcess, 2, U"Union", nullptr, 1, NEW1_PointProcesses_union);
+		praat_addAction1 (classPointProcess, 2, U"Intersection", nullptr, 1, NEW1_PointProcesses_intersection);
+		praat_addAction1 (classPointProcess, 2, U"Difference", nullptr, 1, NEW1_PointProcesses_difference);
+
+	praat_addAction1 (classSpectrumTier, 0, U"Draw...", nullptr, 0, GRAPHICS_SpectrumTier_draw);
+	praat_addAction1 (classSpectrumTier, 0, U"Tabulate -", nullptr, 0, nullptr);
+		praat_addAction1 (classSpectrumTier, 1, U"List...", nullptr, 1, LIST_SpectrumTier_list);
+		praat_addAction1 (classSpectrumTier, 0, U"Down to Table", nullptr, 1, NEW_SpectrumTier_downto_Table);
+	praat_addAction1 (classSpectrumTier, 0, U"Remove points below...", nullptr, 0, MODIFY_SpectrumTier_removePointsBelow);
+
+	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_AmplitudeTier_viewAndEdit);
+	praat_addAction2 (classAmplitudeTier, 1, classSound, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_AmplitudeTier_viewAndEdit);
+	praat_addAction2 (classAmplitudeTier, 1, classSound, 1, U"Multiply", nullptr, 0, NEW1_Sound_AmplitudeTier_multiply);
+	praat_addAction2 (classDurationTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_DurationTier_edit);
+	praat_addAction2 (classDurationTier, 1, classSound, 1,   U"Edit", nullptr, praat_DEPRECATED_2011, WINDOW_DurationTier_edit);
+	praat_addAction2 (classFormantGrid, 1, classSound, 1, U"Filter", nullptr, 0, NEW1_Sound_FormantGrid_filter);
+	praat_addAction2 (classFormantGrid, 1, classSound, 1, U"Filter (no scale)", nullptr, 0, NEW1_Sound_FormantGrid_filter_noscale);
+	praat_addAction2 (classFormantTier, 1, classSound, 1, U"Filter", nullptr, 0, NEW1_Sound_FormantTier_filter);
+	praat_addAction2 (classFormantTier, 1, classSound, 1, U"Filter (no scale)", nullptr, 0, NEW1_Sound_FormantTier_filter_noscale);
+	praat_addAction2 (classIntensityTier, 1, classPointProcess, 1, U"To IntensityTier", nullptr, 0, NEW1_IntensityTier_PointProcess_to_IntensityTier);
+	praat_addAction2 (classIntensityTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_IntensityTier_viewAndEdit);
+	praat_addAction2 (classIntensityTier, 1, classSound, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_IntensityTier_viewAndEdit);
+	praat_addAction2 (classIntensityTier, 1, classSound, 1, U"Multiply...", nullptr, 0, NEW1_Sound_IntensityTier_multiply);
+	praat_addAction2 (classIntensityTier, 1, classSound, 1,   U"Multiply", U"*Multiply...", praat_DEPRECATED_2005, NEW1_Sound_IntensityTier_multiply_old);
+	praat_addAction2 (classPitchTier, 1, classPointProcess, 1, U"To PitchTier", nullptr, 0, NEW1_PitchTier_PointProcess_to_PitchTier);
+	praat_addAction2 (classPitchTier, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_PitchTier_viewAndEdit);
+	praat_addAction2 (classPitchTier, 1, classSound, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_PitchTier_viewAndEdit);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_PointProcess_viewAndEdit);
+	praat_addAction2 (classPointProcess, 1, classSound, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_PointProcess_viewAndEdit);
+praat_addAction2 (classPointProcess, 1, classSound, 1, U"Query", nullptr, 0, nullptr);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (local)...", nullptr, 0, REAL_Point_Sound_getShimmer_local);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (local_dB)...", nullptr, 0, REAL_Point_Sound_getShimmer_local_dB);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (apq3)...", nullptr, 0, REAL_Point_Sound_getShimmer_apq3);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (apq5)...", nullptr, 0, REAL_Point_Sound_getShimmer_apq5);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (apq11)...", nullptr, 0, REAL_Point_Sound_getShimmer_apq11);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Get shimmer (dda)...", nullptr, 0, REAL_Point_Sound_getShimmer_dda);
+praat_addAction2 (classPointProcess, 1, classSound, 1, U"Modify", nullptr, 0, nullptr);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"Transplant time domain", nullptr, 0, MODIFY_Point_Sound_transplantDomain);
+praat_addAction2 (classPointProcess, 1, classSound, 1, U"Analyse", nullptr, 0, nullptr);
+	/*praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Manipulation", nullptr, 0, NEW1_Sound_PointProcess_to_Manipulation);*/
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To AmplitudeTier (point)", nullptr, 0, NEW1_PointProcess_Sound_to_AmplitudeTier_point);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To AmplitudeTier (period)...", nullptr, 0, NEW1_PointProcess_Sound_to_AmplitudeTier_period);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Ltas...", nullptr, 0, NEW1_PointProcess_Sound_to_Ltas);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Ltas (only harmonics)...", nullptr, 0, NEW1_PointProcess_Sound_to_Ltas_harmonics);
+praat_addAction2 (classPointProcess, 1, classSound, 1, U"Synthesize", nullptr, 0, nullptr);
+	praat_addAction2 (classPointProcess, 1, classSound, 1, U"To Sound ensemble...", nullptr, 0, NEW1_Sound_PointProcess_to_SoundEnsemble_correlate);
+}
+
+/* End of file praat_Tiers.cpp */
diff --git a/artsynth/Speaker.h b/fon/praat_Tiers.h
similarity index 58%
copy from artsynth/Speaker.h
copy to fon/praat_Tiers.h
index e3c6992..2f269f4 100644
--- a/artsynth/Speaker.h
+++ b/fon/praat_Tiers.h
@@ -1,8 +1,8 @@
-#ifndef _Speaker_h_
-#define _Speaker_h_
-/* Speaker.h
+#ifndef _praat_Tiers_h_
+#define _praat_Tiers_h_
+/* praat_Sound.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,15 +18,20 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "Data.h"
+/*
+	User interface functions for PointProcess and subclasses of RealTier.
+*/
 
-#include "Speaker_def.h"
+#include "AmplitudeTierEditor.h"
+#include "DurationTierEditor.h"
+#include "FormantGridEditor.h"
+#include "FormantTier.h"
+#include "IntensityTierEditor.h"
+#include "PitchTierEditor.h"
+#include "PointEditor.h"
+#include "praat_TimeTier.h"
 
-autoSpeaker Speaker_create (char32 *kindOfSpeaker, int numberOfVocalCordMasses);
-	/* Preconditions:								*/
-	/*    1 <= numberOfVocalCordMasses <= 2;					*/
-	/* Failures:									*/
-	/*    Kind of speaker is not one of "Female", "Male", or "Child".		*/
+void praat_Tiers_init ();
 
-/* End of file Speaker.h */
+/* End of file praat_Tiers.h */
 #endif
diff --git a/fon/praat_TimeFrameSampled.cpp b/fon/praat_TimeFrameSampled.cpp
new file mode 100644
index 0000000..3452976
--- /dev/null
+++ b/fon/praat_TimeFrameSampled.cpp
@@ -0,0 +1,68 @@
+/* praat_TimeFrameSampled.cpp
+ *
+ * Copyright (C) 2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "praat_TimeFrameSampled.h"
+
+// MARK: - TIMEFRAMESAMPLED
+
+DIRECT (INTEGER_TimeFrameSampled_getNumberOfFrames) {
+	NUMBER_ONE (Sampled)
+		long result = my nx;
+	NUMBER_ONE_END (U" frames");
+}
+
+FORM (REAL_TimeFrameSampled_getFrameFromTime, U"Get frame number from time", U"Get frame number from time...") {
+	REAL4 (time, U"Time (s)", U"0.5")
+	OK
+DO
+	NUMBER_ONE (Sampled)
+		double result = Sampled_xToIndex (me, time);
+	NUMBER_ONE_END (U" (frame as a real number)")
+}
+
+DIRECT (REAL_TimeFrameSampled_getFrameLength) {
+	NUMBER_ONE (Sampled)
+		double result = my dx;
+	NUMBER_ONE_END (U" seconds")
+}
+
+FORM (REAL_TimeFrameSampled_getTimeFromFrame, U"Get time from frame number", U"Get time from frame number...") {
+	NATURAL4 (frameNumber, U"Frame number", U"1")
+	OK
+DO
+	NUMBER_ONE (Sampled)
+		double result = Sampled_indexToX (me, frameNumber);
+	NUMBER_ONE_END (U" seconds")
+}
+
+// MARK: - buttons
+
+void praat_TimeFrameSampled_query_init (ClassInfo klas) {
+	praat_TimeFunction_query_init (klas);
+	praat_addAction1 (klas, 1, U"Query time sampling", nullptr, 1, nullptr);
+	praat_addAction1 (klas, 1, U"Get number of frames", nullptr, 2, INTEGER_TimeFrameSampled_getNumberOfFrames);
+	praat_addAction1 (klas, 1, U"Get time step", nullptr, 2, REAL_TimeFrameSampled_getFrameLength);
+	praat_addAction1 (klas, 1,   U"Get frame length", U"*Get time step", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_TimeFrameSampled_getFrameLength);
+	praat_addAction1 (klas, 1,   U"Get frame duration", U"*Get time step", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_TimeFrameSampled_getFrameLength);
+	praat_addAction1 (klas, 1, U"Get time from frame number...", nullptr, 2, REAL_TimeFrameSampled_getTimeFromFrame);
+	praat_addAction1 (klas, 1,   U"Get time from frame...", U"*Get time from frame number...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_TimeFrameSampled_getTimeFromFrame);
+	praat_addAction1 (klas, 1, U"Get frame number from time...", nullptr, 2, REAL_TimeFrameSampled_getFrameFromTime);
+	praat_addAction1 (klas, 1,   U"Get frame from time...", U"*Get frame number from time...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_TimeFrameSampled_getFrameFromTime);
+}
+
+/* End of file praat_TimeFrameSampled.cpp */
diff --git a/sys/InfoEditor.h b/fon/praat_TimeFrameSampled.h
similarity index 63%
copy from sys/InfoEditor.h
copy to fon/praat_TimeFrameSampled.h
index 032e683..c02ca67 100644
--- a/sys/InfoEditor.h
+++ b/fon/praat_TimeFrameSampled.h
@@ -1,8 +1,8 @@
-#ifndef _InfoEditor_h_
-#define _InfoEditor_h_
-/* InfoEditor.h
+#ifndef _praat_TimeFrameSampled_h_
+#define _praat_TimeFrameSampled_h_
+/* praat_TimeFrameSampled.h
  *
- * Copyright (C) 2004-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,18 +18,10 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "TextEditor.h"
+#include "Sampled.h"
+#include "praat_TimeFunction.h"
 
-Thing_define (InfoEditor, TextEditor) {
-	void v_destroy () noexcept
-		override;
-	bool v_scriptable ()
-		override { return false; }
-	bool v_fileBased ()
-		override { return false; }
-	void v_clear ()
-		override;
-};
+void praat_TimeFrameSampled_query_init (ClassInfo klas);   // Query buttons for frame-based time-based subclasses of Sampled.
 
-/* End of file InfoEditor.h */
 #endif
+/* End of file praat_TimeFrameSampled.h */
diff --git a/fon/praat_TimeFunction.cpp b/fon/praat_TimeFunction.cpp
new file mode 100644
index 0000000..65d3d16
--- /dev/null
+++ b/fon/praat_TimeFunction.cpp
@@ -0,0 +1,115 @@
+/* praat_TimeFunction.cpp
+ *
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "praat_TimeFunction.h"
+
+// MARK: - TIMEFUNCTION
+
+// MARK: Query
+
+DIRECT (REAL_TimeFunction_getStartTime) {
+	NUMBER_ONE (Function)
+		double result = my xmin;
+	NUMBER_ONE_END (U" seconds")
+}
+
+DIRECT (REAL_TimeFunction_getEndTime) {
+	NUMBER_ONE (Function)
+		double result = my xmax;
+	NUMBER_ONE_END (U" seconds")
+}
+
+DIRECT (REAL_TimeFunction_getTotalDuration) {
+	NUMBER_ONE (Function)
+		double result = my xmax - my xmin;
+	NUMBER_ONE_END (U" seconds")
+}
+
+// MARK: Modify
+
+FORM (MODIFY_TimeFunction_shiftTimesBy, U"Shift times by", nullptr) {
+	REALVAR (shift, U"Shift (s)", U"0.5")
+	OK
+DO
+	MODIFY_EACH (Function)
+		Function_shiftXBy (me, shift);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TimeFunction_shiftTimesTo, U"Shift times to", nullptr) {
+	RADIOVAR (shift, U"Shift", 1)
+		OPTION (U"start time")
+		OPTION (U"centre time")
+		OPTION (U"end time")
+	REALVAR (toTime, U"To time (s)", U"0.0")
+	OK
+DO
+	MODIFY_EACH (Function)
+		Function_shiftXTo (me, shift == 1 ? my xmin : shift == 2 ? 0.5 * (my xmin + my xmax) : my xmax, toTime);
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_TimeFunction_shiftToZero) {
+	MODIFY_EACH (Function)
+		Function_shiftXTo (me, my xmin, 0.0);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TimeFunction_scaleTimesBy, U"Scale times by", nullptr) {
+	POSITIVEVAR (factor, U"Factor", U"2.0")
+	OK
+DO
+	MODIFY_EACH (Function)
+		Function_scaleXBy (me, factor);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TimeFunction_scaleTimesTo, U"Scale times to", nullptr) {
+	REALVAR (newStartTime, U"New start time (s)", U"0.0")
+	REALVAR (newEndTime, U"New end time (s)", U"1.0")
+	OK
+DO
+	if (newStartTime >= newEndTime) Melder_throw (U"New end time should be greater than new start time.");
+	MODIFY_EACH (Function)
+		Function_scaleXTo (me, newStartTime, newEndTime);
+	MODIFY_EACH_END
+}
+
+// MARK: - buttons
+
+void praat_TimeFunction_query_init (ClassInfo klas) {
+	praat_addAction1 (klas, 1, U"Query time domain", nullptr, 1, nullptr);
+	praat_addAction1 (klas, 1, U"Get start time", nullptr, 2, REAL_TimeFunction_getStartTime);
+	praat_addAction1 (klas, 1,   U"Get starting time", U"*Get start time", praat_DEPTH_2 | praat_DEPRECATED_2006, REAL_TimeFunction_getStartTime);
+	praat_addAction1 (klas, 1, U"Get end time", nullptr, 2, REAL_TimeFunction_getEndTime);
+	praat_addAction1 (klas, 1,   U"Get finishing time", U"*Get end time", praat_DEPTH_2 | praat_DEPRECATED_2006, REAL_TimeFunction_getEndTime);
+	praat_addAction1 (klas, 1, U"Get total duration", nullptr, 2, REAL_TimeFunction_getTotalDuration);
+	praat_addAction1 (klas, 1,   U"Get duration", U"*Get total duration", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_TimeFunction_getTotalDuration);
+}
+
+void praat_TimeFunction_modify_init (ClassInfo klas) {
+	praat_addAction1 (klas, 0, U"Modify times", nullptr, 1, nullptr);
+	praat_addAction1 (klas, 0, U"Shift times by...", nullptr, 2, MODIFY_TimeFunction_shiftTimesBy);
+	praat_addAction1 (klas, 0, U"Shift times to...", nullptr, 2, MODIFY_TimeFunction_shiftTimesTo);
+	praat_addAction1 (klas, 0,   U"Shift to zero", U"*Shift times to...", praat_DEPTH_2 | praat_DEPRECATED_2008, MODIFY_TimeFunction_shiftToZero);
+	praat_addAction1 (klas, 0, U"Scale times by...", nullptr, 2, MODIFY_TimeFunction_scaleTimesBy);
+	praat_addAction1 (klas, 0, U"Scale times to...", nullptr, 2, MODIFY_TimeFunction_scaleTimesTo);
+	praat_addAction1 (klas, 0,   U"Scale times...", U"*Scale times to...", praat_DEPTH_2 | praat_DEPRECATED_2008, MODIFY_TimeFunction_scaleTimesTo);
+}
+
+/* End of file praat_TimeFunction.cpp */
diff --git a/fon/praat_TimeFunction.h b/fon/praat_TimeFunction.h
new file mode 100644
index 0000000..55d608f
--- /dev/null
+++ b/fon/praat_TimeFunction.h
@@ -0,0 +1,42 @@
+#ifndef _praat_TimeFunction_h_
+#define _praat_TimeFunction_h_
+/* praat_TimeFunction.h
+ *
+ * Copyright (C) 2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+	Interface functions for time-based subclasses of Function.
+*/
+
+#include "Function.h"
+#include "praat.h"
+
+/*
+	Prompting for fromTime and toTime on one row with two fields.
+*/
+#define praat_TimeFunction_RANGE(fromTime,toTime) \
+	REALVAR (fromTime, U"left Time range (s)", U"0.0") \
+	REALVAR (toTime, U"right Time range (s)", U"0.0 (= all)")
+
+/*
+	Action buttons.
+*/
+void praat_TimeFunction_query_init (ClassInfo klas);   // Query buttons for end points and duration
+void praat_TimeFunction_modify_init (ClassInfo klas);   // Modify buttons for time shifting and time scaling
+
+/* End of file praat_TimeFunction.h */
+#endif
diff --git a/fon/praat_TimeTier.cpp b/fon/praat_TimeTier.cpp
new file mode 100644
index 0000000..324ab43
--- /dev/null
+++ b/fon/praat_TimeTier.cpp
@@ -0,0 +1,116 @@
+/* praat_TimeTier.cpp
+ *
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "praat_TimeTier.h"
+
+// MARK: TIMETIER
+
+// MARK: Query
+
+DIRECT (INTEGER_TimeTier_getNumberOfPoints) {
+	NUMBER_ONE (AnyTier)
+		long result = my points.size;
+	NUMBER_ONE_END (U" points")
+}
+
+FORM (INTEGER_TimeTier_getLowIndexFromTime, U"Get low index", U"AnyTier: Get low index from time...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	FIND_ONE (AnyTier)
+		Melder_information (my points.size == 0 ? U"--undefined--" : Melder_integer (AnyTier_timeToLowIndex (me, time)));
+	END
+}
+
+FORM (INTEGER_TimeTier_getHighIndexFromTime, U"Get high index", U"AnyTier: Get high index from time...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	FIND_ONE (AnyTier)
+		Melder_information (my points.size == 0 ? U"--undefined--" : Melder_integer (AnyTier_timeToHighIndex (me, GET_REAL (U"Time"))));
+	END
+}
+
+FORM (INTEGER_TimeTier_getNearestIndexFromTime, U"Get nearest index", U"AnyTier: Get nearest index from time...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	FIND_ONE (AnyTier)
+		Melder_information (my points.size == 0 ? U"--undefined--" : Melder_integer (AnyTier_timeToNearestIndex (me, GET_REAL (U"Time"))));
+	END
+}
+
+FORM (REAL_TimeTier_getTimeFromIndex, U"Get time", nullptr /*"AnyTier: Get time from index..."*/) {
+	NATURALVAR (pointNumber, U"Point number", U"10")
+	OK
+DO
+	FIND_ONE (AnyTier)
+		if (pointNumber > my points.size) Melder_information (U"--undefined--");
+		else Melder_informationReal (my points.at [pointNumber] -> number, U"seconds");
+	END
+}
+
+// MARK: Modify
+
+FORM (MODIFY_TimeTier_removePoint, U"Remove one point", U"AnyTier: Remove point...") {
+	NATURALVAR (pointNumber, U"Point number", U"1")
+	OK
+DO
+	MODIFY_EACH (AnyTier)
+		AnyTier_removePoint (me, pointNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TimeTier_removePointNear, U"Remove one point", U"AnyTier: Remove point near...") {
+	REALVAR (time, U"Time (s)", U"0.5")
+	OK
+DO
+	MODIFY_EACH (AnyTier)
+		AnyTier_removePointNear (me, time);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TimeTier_removePointsBetween, U"Remove points", U"AnyTier: Remove points between...") {
+	REALVAR (fromTime, U"left Time range (s)", U"0.0")
+	REALVAR (toTime, U"right Time range (s)", U"1.0")
+	OK
+DO
+	MODIFY_EACH (AnyTier)
+		AnyTier_removePointsBetween (me, fromTime, toTime);
+	MODIFY_EACH_END
+}
+
+// MARK: - buttons
+
+void praat_TimeTier_query_init (ClassInfo klas) {
+	praat_TimeFunction_query_init (klas);
+	praat_addAction1 (klas, 1, U"Get number of points", nullptr, 1, INTEGER_TimeTier_getNumberOfPoints);
+	praat_addAction1 (klas, 1, U"Get low index from time...", nullptr, 1, INTEGER_TimeTier_getLowIndexFromTime);
+	praat_addAction1 (klas, 1, U"Get high index from time...", nullptr, 1, INTEGER_TimeTier_getHighIndexFromTime);
+	praat_addAction1 (klas, 1, U"Get nearest index from time...", nullptr, 1, INTEGER_TimeTier_getNearestIndexFromTime);
+	praat_addAction1 (klas, 1, U"Get time from index...", nullptr, 1, REAL_TimeTier_getTimeFromIndex);
+}
+
+void praat_TimeTier_modify_init (ClassInfo klas) {
+	praat_TimeFunction_modify_init (klas);
+	praat_addAction1 (klas, 0, U"Remove point...", nullptr, 1, MODIFY_TimeTier_removePoint);
+	praat_addAction1 (klas, 0, U"Remove point near...", nullptr, 1, MODIFY_TimeTier_removePointNear);
+	praat_addAction1 (klas, 0, U"Remove points between...", nullptr, 1, MODIFY_TimeTier_removePointsBetween);
+}
+
+/* End of file praat_TimeTier.cpp */
diff --git a/artsynth/Speaker.h b/fon/praat_TimeTier.h
similarity index 56%
copy from artsynth/Speaker.h
copy to fon/praat_TimeTier.h
index e3c6992..996a145 100644
--- a/artsynth/Speaker.h
+++ b/fon/praat_TimeTier.h
@@ -1,8 +1,8 @@
-#ifndef _Speaker_h_
-#define _Speaker_h_
-/* Speaker.h
+#ifndef _praat_TimeTier_h_
+#define _praat_TimeTier_h_
+/* praat_TimeTier.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,15 +18,18 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "Data.h"
+/*
+	Interface functions for time-based subclasses of AnyTier.
+*/
 
-#include "Speaker_def.h"
+#include "AnyTier.h"
+#include "praat_TimeFunction.h"
 
-autoSpeaker Speaker_create (char32 *kindOfSpeaker, int numberOfVocalCordMasses);
-	/* Preconditions:								*/
-	/*    1 <= numberOfVocalCordMasses <= 2;					*/
-	/* Failures:									*/
-	/*    Kind of speaker is not one of "Female", "Male", or "Child".		*/
+/*
+	Action buttons.
+*/
+void praat_TimeTier_query_init (ClassInfo klas);   // Query buttons for time-based subclasses of AnyTier.
+void praat_TimeTier_modify_init (ClassInfo klas);   // Modification buttons for time-based subclasses of AnyTier.
 
-/* End of file Speaker.h */
+/* End of file praat_TimeTier.h */
 #endif
diff --git a/fon/praat_TimeVector.h b/fon/praat_TimeVector.h
new file mode 100644
index 0000000..8f99fd7
--- /dev/null
+++ b/fon/praat_TimeVector.h
@@ -0,0 +1,51 @@
+#ifndef _praat_TimeVector_h_
+#define _praat_TimeVector_h_
+/* praat_TimeVector.h
+ *
+ * Copyright (C) 2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+	Interface functions for time-based subclasses of Vector.
+*/
+
+#include "Vector.h"
+#include "praat_TimeFunction.h"
+
+/*
+	Prompting for interpolated values at a time or within a time range.
+*/
+
+#define praat_TimeVector_INTERPOLATED_VALUE(time,interpolation) \
+	REALVAR (time, U"Time (s)", U"0.5") \
+	RADIOVARx (interpolation, U"Interpolation", 3, 0) \
+		RADIOBUTTON (U"Nearest") \
+		RADIOBUTTON (U"Linear") \
+		RADIOBUTTON (U"Cubic") \
+		RADIOBUTTON (U"Sinc70") \
+		RADIOBUTTON (U"Sinc700")
+
+#define praat_TimeVector_INTERPOLATED_EXTREMUM(fromTime,toTime,interpolation) \
+	praat_TimeFunction_RANGE (fromTime, toTime) \
+	RADIOVARx (interpolation, U"Interpolation", 2, 0) \
+		RADIOBUTTON (U"None") \
+		RADIOBUTTON (U"Parabolic") \
+		RADIOBUTTON (U"Cubic") \
+		RADIOBUTTON (U"Sinc70") \
+		RADIOBUTTON (U"Sinc700")
+
+/* End of file praat_TimeVector.h */
+#endif
diff --git a/sys/InfoEditor.h b/fon/praat_uvafon.h
similarity index 63%
copy from sys/InfoEditor.h
copy to fon/praat_uvafon.h
index 032e683..d3388d8 100644
--- a/sys/InfoEditor.h
+++ b/fon/praat_uvafon.h
@@ -1,8 +1,8 @@
-#ifndef _InfoEditor_h_
-#define _InfoEditor_h_
-/* InfoEditor.h
+#ifndef _praat_uvafon_h_
+#define _praat_uvafon_h_
+/* praat_uvafon.h
  *
- * Copyright (C) 2004-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,18 +18,10 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "TextEditor.h"
+#include "praat.h"
 
-Thing_define (InfoEditor, TextEditor) {
-	void v_destroy () noexcept
-		override;
-	bool v_scriptable ()
-		override { return false; }
-	bool v_fileBased ()
-		override { return false; }
-	void v_clear ()
-		override;
-};
+void praat_uvafon_init ();
+void praat_uvafon_TextGrid_init ();
 
-/* End of file InfoEditor.h */
 #endif
+/* End of file praat_uvafon.h */
diff --git a/gram/Network.cpp b/gram/Network.cpp
index 6baca7f..a7a0ba0 100644
--- a/gram/Network.cpp
+++ b/gram/Network.cpp
@@ -369,11 +369,11 @@ autoNetwork Network_create_rectangle_vertical (double spreadingRate, enum kNetwo
 	}
 }
 
-void Network_draw (Network me, Graphics graphics, bool colour) {
+void Network_draw (Network me, Graphics graphics, bool useColour) {
 	double saveLineWidth = Graphics_inqLineWidth (graphics);
 	Graphics_setInner (graphics);
 	Graphics_setWindow (graphics, my xmin, my xmax, my ymin, my ymax);
-	if (colour) {
+	if (useColour) {
 		Graphics_setColour (graphics, Graphics_SILVER);
 		Graphics_fillRectangle (graphics, my xmin, my xmax, my ymin, my ymax);
 	}
@@ -386,7 +386,7 @@ void Network_draw (Network me, Graphics graphics, bool colour) {
 			NetworkNode nodeFrom = & my nodes [conn -> nodeFrom];
 			NetworkNode nodeTo = & my nodes [conn -> nodeTo];
 			Graphics_setLineWidth (graphics, fabs (conn -> weight) * 6.0);
-			Graphics_setColour (graphics, conn -> weight < 0.0 ? (colour ? Graphics_WHITE : Graphics_SILVER) : Graphics_BLACK);
+			Graphics_setColour (graphics, conn -> weight < 0.0 ? ( useColour ? Graphics_WHITE : Graphics_SILVER ) : Graphics_BLACK);
 			Graphics_line (graphics, nodeFrom -> x, nodeFrom -> y, nodeTo -> x, nodeTo -> y);
 		}
 	}
@@ -396,7 +396,7 @@ void Network_draw (Network me, Graphics graphics, bool colour) {
 	 */
 	for (long inode = 1; inode <= my numberOfNodes; inode ++) {
 		NetworkNode node = & my nodes [inode];
-		Graphics_setColour (graphics, colour ? Graphics_SILVER : Graphics_WHITE);
+		Graphics_setColour (graphics, useColour ? Graphics_SILVER : Graphics_WHITE);
 		Graphics_fillCircle_mm (graphics, node -> x, node -> y, 5.0);
 	}
 	/*
@@ -419,7 +419,7 @@ void Network_draw (Network me, Graphics graphics, bool colour) {
 		double diameter = activity * 5.0;
 		if (diameter != 0.0) {
 			Graphics_setColour (graphics,
-				colour ? ( node -> activity < 0.0 ? Graphics_BLUE : Graphics_RED )
+				useColour ? ( node -> activity < 0.0 ? Graphics_BLUE : Graphics_RED )
 				: ( node -> activity < 0.0 ? Graphics_SILVER : Graphics_BLACK));
 			Graphics_fillCircle_mm (graphics, node -> x, node -> y, diameter);
 		}
diff --git a/gram/OTGrammar.cpp b/gram/OTGrammar.cpp
index 8f92aaf..4f868c5 100644
--- a/gram/OTGrammar.cpp
+++ b/gram/OTGrammar.cpp
@@ -345,7 +345,7 @@ long OTGrammar_getTableau (OTGrammar me, const char32 *input) {
 	Melder_throw (U"Input \"", input, U"\" not in list of tableaus.");
 }
 
-static void _OTGrammar_fillInHarmonies (OTGrammar me, long itab) {
+static void _OTGrammar_fillInHarmonies (OTGrammar me, long itab) noexcept {
 	if (my decisionStrategy == kOTGrammar_decisionStrategy_OPTIMALITY_THEORY) return;
 	OTGrammarTableau tableau = & my tableaus [itab];
 	for (long icand = 1; icand <= tableau -> numberOfCandidates; icand ++) {
@@ -382,7 +382,7 @@ static void _OTGrammar_fillInHarmonies (OTGrammar me, long itab) {
 	}
 }
 
-int OTGrammar_compareCandidates (OTGrammar me, long itab1, long icand1, long itab2, long icand2) {
+int OTGrammar_compareCandidates (OTGrammar me, long itab1, long icand1, long itab2, long icand2) noexcept {
 	int *marks1 = my tableaus [itab1]. candidates [icand1]. marks;
 	int *marks2 = my tableaus [itab2]. candidates [icand2]. marks;
 	if (my decisionStrategy == kOTGrammar_decisionStrategy_OPTIMALITY_THEORY) {
@@ -445,7 +445,7 @@ int OTGrammar_compareCandidates (OTGrammar me, long itab1, long icand1, long ita
 	return 0;   // the two total disharmonies are equal
 }
 
-static void _OTGrammar_fillInProbabilities (OTGrammar me, long itab) {
+static void _OTGrammar_fillInProbabilities (OTGrammar me, long itab) noexcept {
 	OTGrammarTableau tableau = & my tableaus [itab];
 	double maximumHarmony = tableau -> candidates [1]. harmony;
 	for (long icand = 2; icand <= tableau -> numberOfCandidates; icand ++) {
@@ -471,7 +471,7 @@ static void _OTGrammar_fillInProbabilities (OTGrammar me, long itab) {
 	}
 }
 
-long OTGrammar_getWinner (OTGrammar me, long itab) {
+long OTGrammar_getWinner (OTGrammar me, long itab) noexcept {
 	long icand_best = 1;
 	if (my decisionStrategy == kOTGrammar_decisionStrategy_MAXIMUM_ENTROPY ||
 		my decisionStrategy == kOTGrammar_decisionStrategy_EXPONENTIAL_MAXIMUM_ENTROPY)
@@ -1156,7 +1156,7 @@ static bool honoursFixedRankings (OTGrammar me) {
 	return true;
 }
 
-autoDistributions OTGrammar_measureTypology (OTGrammar me) {
+autoDistributions OTGrammar_measureTypology_WEAK (OTGrammar me) {
 	try {
 		long totalNumberOfOutputs = 0, nout = 0, ncons = my numberOfConstraints, nperm, factorial [1+12];
 		if (ncons > 12)
diff --git a/gram/OTGrammar.h b/gram/OTGrammar.h
index a9fbf94..6c202dc 100644
--- a/gram/OTGrammar.h
+++ b/gram/OTGrammar.h
@@ -2,7 +2,7 @@
 #define _OTGrammar_h_
 /* OTGrammar.h
  *
- * Copyright (C) 1997-2011,2014,2015 Paul Boersma
+ * Copyright (C) 1997-2011,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@ void OTGrammar_sort (OTGrammar me);
 void OTGrammar_newDisharmonies (OTGrammar me, double spreading);
 
 long OTGrammar_getTableau (OTGrammar me, const char32 *input);
-int OTGrammar_compareCandidates (OTGrammar me, long itab1, long icand1, long itab2, long icand2);
+int OTGrammar_compareCandidates (OTGrammar me, long itab1, long icand1, long itab2, long icand2) noexcept;
 	/*
 	 * Function:
 	 *    to compare the optimality of candidates icand1 in tableau itab1
@@ -61,7 +61,7 @@ int OTGrammar_compareCandidates (OTGrammar me, long itab1, long icand1, long ita
 	 */
 
 /* Productive parsing. */
-long OTGrammar_getWinner (OTGrammar me, long itab);
+long OTGrammar_getWinner (OTGrammar me, long itab) noexcept;
 	/* Gives randomized results in case of tied candidates. */
 long OTGrammar_getNumberOfOptimalCandidates (OTGrammar me, long itab);
 bool OTGrammar_isCandidateGrammatical (OTGrammar me, long itab, long icand);
@@ -87,7 +87,7 @@ autoStrings OTGrammar_inputsToOutputs (OTGrammar me, Strings inputs, double eval
 autoStrings OTGrammar_inputToOutputs (OTGrammar me, const char32 *input, long n, double evaluationNoise);
 autoDistributions OTGrammar_to_Distribution (OTGrammar me, long trialsPerInput, double evaluationNoise);
 autoPairDistribution OTGrammar_to_PairDistribution (OTGrammar me, long trialsPerInput, double evaluationNoise);
-autoDistributions OTGrammar_measureTypology (OTGrammar me);
+autoDistributions OTGrammar_measureTypology_WEAK (OTGrammar me);   // WEAK because it has a progress bar
 
 void OTGrammar_learnOne (OTGrammar me, const char32 *input, const char32 *adultOutput,
 	double rankingSpreading, enum kOTGrammar_rerankingStrategy updateRule, bool honourLocalRankings,
diff --git a/gram/OTGrammar_def.h b/gram/OTGrammar_def.h
index cc13114..504d23c 100644
--- a/gram/OTGrammar_def.h
+++ b/gram/OTGrammar_def.h
@@ -92,7 +92,7 @@ oo_DEFINE_CLASS (OTGrammar, Daata)
 	oo_ENDFROM
 	oo_LONG (numberOfConstraints)
 	oo_STRUCT_VECTOR (OTGrammarConstraint, constraints, numberOfConstraints)
-	oo_LONG_VECTOR (index, numberOfConstraints)
+	oo_LONG_VECTOR (index, numberOfConstraints)   // not read or written in text files
 	oo_LONG (numberOfFixedRankings)
 	oo_STRUCT_VECTOR (OTGrammarFixedRanking, fixedRankings, numberOfFixedRankings)
 	oo_LONG (numberOfTableaus)
diff --git a/gram/manual_gram.cpp b/gram/manual_gram.cpp
index 0aa6046..d159d12 100644
--- a/gram/manual_gram.cpp
+++ b/gram/manual_gram.cpp
@@ -409,14 +409,15 @@ NORMAL (U"However, in the remaining part of this tutorial, we will stick with a
 	"the differences between their ranking values are in the vicinity of 10.")
 MAN_END
 
-MAN_BEGIN (U"OT learning 2.5. Editing a grammar", U"ppgb", 20110808)
+MAN_BEGIN (U"OT learning 2.5. Editing a grammar", U"ppgb", 20161028)
 NORMAL (U"In the N\\s{O}C\\s{ODA} example, the winning candidate for the input /pat/ was always [pa].")
 NORMAL (U"To make [pat] the winner instead, N\\s{O}C\\s{ODA} should be ranked lower than P\\s{ARSE}. "
-	"To achieve this even with zero noise, go to the editor and select the N\\s{O}C\\s{ODA} constraint by clicking on it "
+	"To achieve this even with zero noise, "
+	"go to the OTGrammar window and select the N\\s{O}C\\s{ODA} constraint by clicking on it "
 	"(a spade symbol ♠︎ will mark the selected constraint), "
 	"and choose ##Edit ranking...# from the #Edit menu, or use the keyboard shortcut Command-E.")
 NORMAL (U"In the resulting command window, we lower the ranking of the constraint from 100 to 80, and click OK. "
-	"This is what you will see in the editor:")
+	"This is what you will then see in the OTGrammar window:")
 LIST_ITEM1 (U"\t\t      %%ranking value\t      %disharmony\t      %plasticity")
 LIST_ITEM1 (U"\t♠︎ ##N\\s{O}C\\s{ODA}#\t      80.000\t      103.429\t       1.000")
 LIST_ITEM1 (U"\t##P\\s{ARSE}#\t      90.000\t      88.083\t       1.000")
diff --git a/gram/praat_gram.cpp b/gram/praat_gram.cpp
index b7a5aaa..0cdfee6 100644
--- a/gram/praat_gram.cpp
+++ b/gram/praat_gram.cpp
@@ -16,8 +16,6 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "praat.h"
-
 #include "Network.h"
 #include "OTGrammar.h"
 #include "OTMulti.h"
@@ -25,445 +23,401 @@
 #include "OTMultiEditor.h"
 #include "RBM.h"
 
+#include "praat_TableOfReal.h"
+
 #undef iam
 #define iam iam_LOOP
 
-#pragma mark -
-#pragma mark NETWORK
-
-#pragma mark New
-
-static void UiForm_addNetworkFields (UiForm dia) {
-	UiField radio;
-	LABEL (U"", U"Activity spreading settings:")
-	REAL (U"Spreading rate", U"0.01")
-	OPTIONMENU_ENUM (U"Activity clipping rule", kNetwork_activityClippingRule, DEFAULT)
-	REAL (U"left Activity range", U"0.0")
-	REAL (U"right Activity range", U"1.0")
-	REAL (U"Activity leak", U"1.0")
-	LABEL (U"", U"Weight update settings:")
-	REAL (U"Learning rate", U"0.1")
-	REAL (U"left Weight range", U"-1.0")
-	REAL (U"right Weight range", U"1.0")
-	REAL (U"Weight leak", U"0.0")
-}
-
-FORM (Create_empty_Network, U"Create empty Network", 0) {
-	WORD (U"Name", U"network")
-	UiForm_addNetworkFields (dia);
+// MARK: - NETWORK
+
+// MARK: New
+
+#define UiForm_addNetworkFields  \
+	LABEL (U"", U"Activity spreading settings:") \
+	REAL4 (spreadingRate, U"Spreading rate", U"0.01") \
+	OPTIONMENU_ENUM4 (activityClippingRule, U"Activity clipping rule", kNetwork_activityClippingRule, DEFAULT) \
+	REAL4 (minimumActivity, U"left Activity range", U"0.0") \
+	REAL4 (maximumActivity, U"right Activity range", U"1.0") \
+	REAL4 (activityLeak, U"Activity leak", U"1.0") \
+	LABEL (U"", U"Weight update settings:") \
+	REAL4 (learningRate, U"Learning rate", U"0.1") \
+	REAL4 (minimumWeight, U"left Weight range", U"-1.0") \
+	REAL4 (maximumWeight, U"right Weight range", U"1.0") \
+	REAL4 (weightLeak, U"Weight leak", U"0.0")
+
+FORM (NEW1_Create_empty_Network, U"Create empty Network", nullptr) {
+	WORD4 (name, U"Name", U"network")
+	UiForm_addNetworkFields
 	LABEL (U"", U"World coordinates:")
-	REAL (U"left x range", U"0.0")
-	REAL (U"right x range", U"10.0")
-	REAL (U"left y range", U"0.0")
-	REAL (U"right y range", U"10.0")
-	OK2
-DO
-	autoNetwork me = Network_create (GET_REAL (U"Spreading rate"), GET_ENUM (kNetwork_activityClippingRule, U"Activity clipping rule"),
-		GET_REAL (U"left Activity range"), GET_REAL (U"right Activity range"), GET_REAL (U"Activity leak"),
-		GET_REAL (U"Learning rate"), GET_REAL (U"left Weight range"), GET_REAL (U"right Weight range"), GET_REAL (U"Weight leak"),
-		GET_REAL (U"left x range"), GET_REAL (U"right x range"), GET_REAL (U"left y range"), GET_REAL (U"right y range"),
-		0, 0);
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Create_rectangular_Network, U"Create rectangular Network", 0) {
-	UiForm_addNetworkFields (dia);
+	REAL4 (fromX, U"left x range", U"0.0")
+	REAL4 (toX, U"right x range", U"10.0")
+	REAL4 (fromY, U"left y range", U"0.0")
+	REAL4 (toY, U"right y range", U"10.0")
+	OK
+DO
+	CREATE_ONE
+		autoNetwork result = Network_create (spreadingRate,
+			(kNetwork_activityClippingRule) activityClippingRule,
+			minimumActivity, maximumActivity, activityLeak, learningRate, minimumWeight, maximumWeight, weightLeak,
+			fromX, toX, fromY, toY, 0, 0);
+	CREATE_ONE_END (name)
+}
+
+FORM (NEW1_Create_rectangular_Network, U"Create rectangular Network", nullptr) {
+	UiForm_addNetworkFields
 	LABEL (U"", U"Structure settings:")
-	NATURAL (U"Number of rows", U"10")
-	NATURAL (U"Number of columns", U"10")
-	BOOLEAN (U"Bottom row clamped", 1)
+	NATURAL4 (numberOfRows, U"Number of rows", U"10")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"10")
+	BOOLEAN4 (bottomRowClamped, U"Bottom row clamped", 1)
 	LABEL (U"", U"Initial state settings:")
-	REAL (U"left Initial weight range", U"-0.1")
-	REAL (U"right Initial weight range", U"0.1")
-	OK2
-DO
-	autoNetwork me = Network_create_rectangle (GET_REAL (U"Spreading rate"), GET_ENUM (kNetwork_activityClippingRule, U"Activity clipping rule"),
-		GET_REAL (U"left Activity range"), GET_REAL (U"right Activity range"), GET_REAL (U"Activity leak"),
-		GET_REAL (U"Learning rate"), GET_REAL (U"left Weight range"), GET_REAL (U"right Weight range"), GET_REAL (U"Weight leak"),
-		GET_INTEGER (U"Number of rows"), GET_INTEGER (U"Number of columns"),
-		GET_INTEGER (U"Bottom row clamped"),
-		GET_REAL (U"left Initial weight range"), GET_REAL (U"right Initial weight range"));
-	praat_new (me.move(),
-			U"rectangle_", GET_INTEGER (U"Number of rows"),
-			U"_", GET_INTEGER (U"Number of columns"));
-END2 }
-
-FORM (Create_rectangular_Network_vertical, U"Create rectangular Network (vertical)", 0) {
-	UiForm_addNetworkFields (dia);
+	REAL4 (minimumInitialWeight, U"left Initial weight range", U"-0.1")
+	REAL4 (maximumInitialWeight, U"right Initial weight range", U"0.1")
+	OK
+DO
+	CREATE_ONE
+		autoNetwork result = Network_create_rectangle (spreadingRate,
+			(kNetwork_activityClippingRule) activityClippingRule,
+			minimumActivity, maximumActivity, activityLeak, learningRate, minimumWeight, maximumWeight, weightLeak,
+			numberOfRows, numberOfColumns, bottomRowClamped, minimumInitialWeight, maximumInitialWeight);
+	CREATE_ONE_END (U"rectangle_", numberOfRows, U"_", numberOfColumns)
+}
+
+FORM (NEW1_Create_rectangular_Network_vertical, U"Create rectangular Network (vertical)", nullptr) {
+	UiForm_addNetworkFields
 	LABEL (U"", U"Structure settings:")
-	NATURAL (U"Number of rows", U"10")
-	NATURAL (U"Number of columns", U"10")
-	BOOLEAN (U"Bottom row clamped", 1)
+	NATURAL4 (numberOfRows, U"Number of rows", U"10")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"10")
+	BOOLEAN4 (bottomRowClamped, U"Bottom row clamped", 1)
 	LABEL (U"", U"Initial state settings:")
-	REAL (U"left Initial weight range", U"-0.1")
-	REAL (U"right Initial weight range", U"0.1")
-	OK2
-DO
-	autoNetwork me = Network_create_rectangle_vertical (GET_REAL (U"Spreading rate"), GET_ENUM (kNetwork_activityClippingRule, U"Activity clipping rule"),
-		GET_REAL (U"left Activity range"), GET_REAL (U"right Activity range"), GET_REAL (U"Activity leak"),
-		GET_REAL (U"Learning rate"), GET_REAL (U"left Weight range"), GET_REAL (U"right Weight range"), GET_REAL (U"Weight leak"),
-		GET_INTEGER (U"Number of rows"), GET_INTEGER (U"Number of columns"),
-		GET_INTEGER (U"Bottom row clamped"),
-		GET_REAL (U"left Initial weight range"), GET_REAL (U"right Initial weight range"));
-	praat_new (me.move(),
-			U"rectangle_", GET_INTEGER (U"Number of rows"),
-			U"_", GET_INTEGER (U"Number of columns"));
-END2 }
-
-#pragma mark Draw
-
-FORM (Network_draw, U"Draw Network", 0) {
-	BOOLEAN (U"Colour", 1)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam_LOOP (Network);
-		Network_draw (me, GRAPHICS, GET_INTEGER (U"Colour"));
-	}
-END2 }
-
-#pragma mark Tabulate
-
-FORM (Network_listNodes, U"Network: List nodes", 0) {
-	INTEGER (U"From node number", U"1")
-	INTEGER (U"To node number", U"1000")
-	BOOLEAN (U"Include node numbers", true)
-	BOOLEAN (U"Include x", false)
-	BOOLEAN (U"Include y", false)
-	INTEGER (U"Position decimals", U"6")
-	BOOLEAN (U"Include clamped", false)
-	BOOLEAN (U"Include activity", true)
-	BOOLEAN (U"Include excitation", false)
-	INTEGER (U"Activity decimals", U"6")
-	OK2
+	REAL4 (minimumInitialWeight, U"left Initial weight range", U"-0.1")
+	REAL4 (maximumInitialWeight, U"right Initial weight range", U"0.1")
+	OK
+DO
+	CREATE_ONE
+		autoNetwork result = Network_create_rectangle_vertical (spreadingRate,
+			(kNetwork_activityClippingRule) activityClippingRule,
+			minimumActivity, maximumActivity, activityLeak, learningRate, minimumWeight, maximumWeight, weightLeak,
+			numberOfRows, numberOfColumns, bottomRowClamped, minimumInitialWeight, maximumInitialWeight);
+	CREATE_ONE_END (U"rectangle_", numberOfRows, U"_", numberOfColumns)
+}
+
+// MARK: Draw
+
+FORM (GRAPHICS_Network_draw, U"Draw Network", nullptr) {
+	BOOLEAN4 (useColour, U"Use colour", true)
+	OK
 DO
-	LOOP {
-		iam (Network);
-		Network_listNodes (me, GET_INTEGER (U"From node number"), GET_INTEGER (U"To node number"),
-			GET_INTEGER (U"Include node numbers"),
-			GET_INTEGER (U"Include x"), GET_INTEGER (U"Include y"), GET_INTEGER (U"Position decimals"),
-			GET_INTEGER (U"Include clamped"),
-			GET_INTEGER (U"Include activity"), GET_INTEGER (U"Include excitation"), GET_INTEGER (U"Activity decimals"));
-	}
-END2 }
-
-FORM (Network_nodes_downto_Table, U"Network: Nodes down to Table", 0) {
-	INTEGER (U"From node number", U"1")
-	INTEGER (U"To node number", U"1000")
-	BOOLEAN (U"Include node numbers", true)
-	BOOLEAN (U"Include x", false)
-	BOOLEAN (U"Include y", false)
-	INTEGER (U"Position decimals", U"6")
-	BOOLEAN (U"Include clamped", false)
-	BOOLEAN (U"Include activity", true)
-	BOOLEAN (U"Include excitation", false)
-	INTEGER (U"Activity decimals", U"6")
-	OK2
+	GRAPHICS_EACH (Network)
+		Network_draw (me, GRAPHICS, useColour);
+	GRAPHICS_EACH_END
+}
+
+// MARK: Tabulate
+
+FORM (LIST_Network_listNodes, U"Network: List nodes", nullptr) {
+	INTEGER4 (fromNodeNumber, U"From node number", U"1")
+	INTEGER4 (toNodeNumber, U"To node number", U"1000")
+	BOOLEAN4 (includeNodeNumbers, U"Include node numbers", true)
+	BOOLEAN4 (includeX, U"Include x", false)
+	BOOLEAN4 (includeY, U"Include y", false)
+	INTEGER4 (positionDecimals, U"Position decimals", U"6")
+	BOOLEAN4 (includeClamped, U"Include clamped", false)
+	BOOLEAN4 (includeActivity, U"Include activity", true)
+	BOOLEAN4 (includeExcitation, U"Include excitation", false)
+	INTEGER4 (activityDecimals, U"Activity decimals", U"6")
+	OK
+DO
+	INFO_ONE (Network)
+		Network_listNodes (me, fromNodeNumber, toNodeNumber,
+			includeNodeNumbers, includeX, includeY, positionDecimals,
+			includeClamped, includeActivity, includeExcitation, activityDecimals);
+	INFO_ONE_END
+}
+
+FORM (NEW_Network_nodes_downto_Table, U"Network: Nodes down to Table", nullptr) {
+	INTEGER4 (fromNodeNumber, U"From node number", U"1")
+	INTEGER4 (toNodeNumber, U"To node number", U"1000")
+	BOOLEAN4 (includeNodeNumbers, U"Include node numbers", true)
+	BOOLEAN4 (includeX, U"Include x", false)
+	BOOLEAN4 (includeY, U"Include y", false)
+	INTEGER4 (positionDecimals, U"Position decimals", U"6")
+	BOOLEAN4 (includeClamped, U"Include clamped", false)
+	BOOLEAN4 (includeActivity, U"Include activity", true)
+	BOOLEAN4 (includeExcitation, U"Include excitation", false)
+	INTEGER4 (activityDecimals, U"Activity decimals", U"6")
+	OK
+DO
+	CONVERT_EACH (Network)
+		autoTable result = Network_nodes_downto_Table (me, fromNodeNumber, toNodeNumber,
+			includeNodeNumbers, includeX, includeY, positionDecimals,
+			includeClamped, includeActivity, includeExcitation, activityDecimals);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: Query
+
+FORM (REAL_Network_getActivity, U"Network: Get activity", nullptr) {
+	NATURAL4 (node, U"Node", U"1")
+	OK
 DO
-	LOOP {
-		iam (Network);
-		autoTable thee = Network_nodes_downto_Table (me, GET_INTEGER (U"From node number"), GET_INTEGER (U"To node number"),
-			GET_INTEGER (U"Include node numbers"),
-			GET_INTEGER (U"Include x"), GET_INTEGER (U"Include y"), GET_INTEGER (U"Position decimals"),
-			GET_INTEGER (U"Include clamped"),
-			GET_INTEGER (U"Include activity"), GET_INTEGER (U"Include excitation"), GET_INTEGER (U"Activity decimals"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	NUMBER_ONE (Network)
+		double result = Network_getActivity (me, node);
+	NUMBER_ONE_END (U" (activity of node ", node, U")")
+}
 
-#pragma mark Query
+FORM (REAL_Network_getWeight, U"Network: Get weight", nullptr) {
+	NATURAL4 (connection, U"Connection", U"1")
+	OK
+DO
+	NUMBER_ONE (Network)
+		double result = Network_getWeight (me, connection);
+	NUMBER_ONE_END (U" (weight of connection ", connection, U")")
+}
+
+// MARK: Modify
 
-FORM (Network_getActivity, U"Network: Get activity", 0) {
-	NATURAL (U"Node", U"1")
-	OK2
+FORM (MODIFY_Network_addConnection, U"Network: Add connection", nullptr) {
+	NATURAL4 (fromNode, U"From node", U"1")
+	NATURAL4 (toNode, U"To node", U"2")
+	REAL4 (weight, U"Weight", U"0.0")
+	REAL4 (plasticity, U"Plasticity", U"1.0")
+	OK
 DO
-	iam_ONLY (Network);
-	double activity = Network_getActivity (me, GET_INTEGER (U"Node"));
-	Melder_information (activity);
-END2 }
+	MODIFY_EACH (Network)
+		Network_addConnection (me, fromNode, toNode, weight, plasticity);
+	MODIFY_EACH_END
+}
 
-FORM (Network_getWeight, U"Network: Get weight", 0) {
-	NATURAL (U"Connection", U"1")
-	OK2
+FORM (MODIFY_Network_addNode, U"Network: Add node", nullptr) {
+	REAL4 (x, U"x", U"5.0")
+	REAL4 (y, U"y", U"5.0")
+	REAL4 (activity, U"Activity", U"0.0")
+	BOOLEAN4 (clamping, U"Clamping", false)
+	OK
 DO
-	iam_ONLY (Network);
-	double weight = Network_getWeight (me, GET_INTEGER (U"Connection"));
-	Melder_information (weight);
-END2 }
+	MODIFY_EACH (Network)
+		Network_addNode (me, x, y, activity, clamping);
+	MODIFY_EACH_END
+}
 
-#pragma mark Modify
+FORM (MODIFY_Network_normalizeActivities, U"Network: Normalize activities", nullptr) {
+	INTEGER4 (fromNode, U"From node", U"1")
+	INTEGER4 (toNode, U"To node", U"0 (= all)")
+	OK
+DO
+	MODIFY_EACH (Network)
+		Network_normalizeActivities (me, fromNode, toNode);
+	MODIFY_EACH_END
+}
 
-FORM (Network_addConnection, U"Network: Add connection", 0) {
-	NATURAL (U"From node", U"1")
-	NATURAL (U"To node", U"2")
-	REAL (U"Weight", U"0.0")
-	REAL (U"Plasticity", U"1.0")
-	OK2
+FORM (MODIFY_Network_normalizeWeights, U"Network: Normalize weights", nullptr) {
+	INTEGER4 (fromNode, U"From node", U"1")
+	INTEGER4 (toNode, U"To node", U"0 (= all)")
+	INTEGER4 (fromIncomingNode, U"From incoming node", U"1")
+	INTEGER4 (toIncomingNode, U"To incoming node", U"10")
+	REAL4 (newSum, U"New sum", U"1.0")
+	OK
+DO
+	MODIFY_EACH (Network)
+		Network_normalizeWeights (me, fromNode, toNode, fromIncomingNode, toIncomingNode, newSum);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Network_setActivity, U"Network: Set activity", nullptr) {
+	NATURAL4 (node, U"Node", U"1")
+	REAL4 (activity, U"Activity", U"1.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_addConnection (me, GET_INTEGER (U"From node"), GET_INTEGER (U"To node"), GET_REAL (U"Weight"), GET_REAL (U"Plasticity"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setActivity (me, node, activity);
+	MODIFY_EACH_END
+}
 
-FORM (Network_addNode, U"Network: Add node", 0) {
-	REAL (U"x", U"5.0")
-	REAL (U"y", U"5.0")
-	REAL (U"Activity", U"0.0")
-	BOOLEAN (U"Clamping", 0)
-	OK2
+FORM (MODIFY_Network_setActivityClippingRule, U"Network: Set activity clipping rule", nullptr) {
+	RADIO_ENUM (U"Activity clipping rule", kNetwork_activityClippingRule, DEFAULT)
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_addNode (me, GET_REAL (U"x"), GET_REAL (U"y"), GET_REAL (U"Activity"), GET_INTEGER (U"Clamping"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setActivityClippingRule (me, GET_ENUM (kNetwork_activityClippingRule, U"Activity clipping rule"));
+	MODIFY_EACH_END
+}
 
-FORM (Network_normalizeActivities, U"Network: Normalize activities", 0) {
-	INTEGER (U"From node", U"1")
-	INTEGER (U"To node", U"0 (= all)")
-	OK2
+FORM (MODIFY_Network_setActivityLeak, U"Network: Set activity leak", nullptr) {
+	REAL4 (activityLeak, U"Activity leak", U"1.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_normalizeActivities (me, GET_INTEGER (U"From node"), GET_INTEGER (U"To node"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setActivityLeak (me, activityLeak);
+	MODIFY_EACH_END
+}
 
-FORM (Network_normalizeWeights, U"Network: Normalize weights", 0) {
-	INTEGER (U"From node", U"1")
-	INTEGER (U"To node", U"0 (= all)")
-	INTEGER (U"From incoming node", U"1")
-	INTEGER (U"To incoming node", U"10")
-	REAL (U"New sum", U"1.0")
-	OK2
+FORM (MODIFY_Network_setClamping, U"Network: Set clamping", nullptr) {
+	NATURAL4 (node, U"Node", U"1")
+	BOOLEAN4 (clamping, U"Clamping", true)
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_normalizeWeights (me, GET_INTEGER (U"From node"), GET_INTEGER (U"To node"),
-			GET_INTEGER (U"From incoming node"), GET_INTEGER (U"To incoming node"), GET_REAL (U"New sum"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setClamping (me, node, clamping);
+	MODIFY_EACH_END
+}
 
-FORM (Network_setActivity, U"Network: Set activity", 0) {
-	NATURAL (U"Node", U"1")
-	REAL (U"Activity", U"1.0")
-	OK2
+FORM (MODIFY_Network_setInstar, U"Network: Set instar", nullptr) {
+	REAL4 (instar, U"Instar", U"0.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_setActivity (me, GET_INTEGER (U"Node"), GET_REAL (U"Activity"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setInstar (me, instar);
+	MODIFY_EACH_END
+}
 
-FORM (Network_setActivityClippingRule, U"Network: Set activity clipping rule", 0) {
-	RADIO_ENUM (U"Activity clipping rule", kNetwork_activityClippingRule, DEFAULT)
-	OK2
-iam_ONLY (Network);
-SET_ENUM (U"Activity clipping rule", kNetwork_activityClippingRule, my activityClippingRule);
-DO
-	iam_ONLY (Network);
-	Network_setActivityClippingRule (me, GET_ENUM (kNetwork_activityClippingRule, U"Activity clipping rule"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (Network_setActivityLeak, U"Network: Set activity leak", 0) {
-	REAL (U"Activity leak", U"1.0")
-	OK2
-iam_ONLY (Network);
-SET_REAL (U"Activity leak", my activityLeak);
-DO
-	iam_ONLY (Network);
-	Network_setActivityLeak (me, GET_REAL (U"Activity leak"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (Network_setClamping, U"Network: Set clamping", 0) {
-	NATURAL (U"Node", U"1")
-	BOOLEAN (U"Clamping", 1)
-	OK2
+FORM (MODIFY_Network_setWeightLeak, U"Network: Set weight leak", nullptr) {
+	REAL4 (weightLeak, U"Weight leak", U"0.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_setClamping (me, GET_INTEGER (U"Node"), GET_INTEGER (U"Clamping"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Network_setInstar, U"Network: Set instar", 0) {
-	REAL (U"Instar", U"0.0")
-	OK2
-iam_ONLY (Network);
-SET_REAL (U"Instar", my instar);
-DO
-	iam_ONLY (Network);
-	Network_setInstar (me, GET_REAL (U"Instar"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (Network_setWeightLeak, U"Network: Set weight leak", 0) {
-	REAL (U"Weight leak", U"0.0")
-	OK2
-iam_ONLY (Network);
-SET_REAL (U"Weight leak", my weightLeak);
-DO
-	iam_ONLY (Network);
-	Network_setWeightLeak (me, GET_REAL (U"Weight leak"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (Network_setOutstar, U"Network: Set outstar", 0) {
-	REAL (U"Outstar", U"0.0")
-	OK2
-iam_ONLY (Network);
-SET_REAL (U"Outstar", my outstar);
-DO
-	iam_ONLY (Network);
-	Network_setOutstar (me, GET_REAL (U"Outstar"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (Network_setShunting, U"Network: Set shunting", 0) {
-	REAL (U"Shunting", U"1.0")
-	OK2
+	MODIFY_EACH (Network)
+		Network_setWeightLeak (me, weightLeak);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_Network_setOutstar, U"Network: Set outstar", nullptr) {
+	REAL4 (outstar, U"Outstar", U"0.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_setShunting (me, GET_REAL (U"Shunting"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setOutstar (me, outstar);
+	MODIFY_EACH_END
+}
 
-FORM (Network_setWeight, U"Network: Set weight", 0) {
-	NATURAL (U"Connection", U"1")
-	REAL (U"Weight", U"1.0")
-	OK2
+FORM (MODIFY_Network_setShunting, U"Network: Set shunting", nullptr) {
+	REAL4 (shunting, U"Shunting", U"1.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_setWeight (me, GET_INTEGER (U"Connection"), GET_REAL (U"Weight"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setShunting (me, shunting);
+	MODIFY_EACH_END
+}
 
-FORM (Network_spreadActivities, U"Network: Spread activities", 0) {
-	NATURAL (U"Number of steps", U"20")
-	OK2
+FORM (MODIFY_Network_setWeight, U"Network: Set weight", nullptr) {
+	NATURAL4 (connection, U"Connection", U"1")
+	REAL4 (weight, U"Weight", U"1.0")
+	OK
 DO
-	LOOP {
-		iam_LOOP (Network);
-		Network_spreadActivities (me, GET_INTEGER (U"Number of steps"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_setWeight (me, connection, weight);
+	MODIFY_EACH_END
+}
 
-DIRECT2 (Network_updateWeights) {
-	LOOP {
-		iam_LOOP (Network);
+FORM (MODIFY_Network_spreadActivities, U"Network: Spread activities", nullptr) {
+	NATURAL4 (numberOfSteps, U"Number of steps", U"20")
+	OK
+DO
+	MODIFY_EACH (Network)
+		Network_spreadActivities (me, numberOfSteps);
+	MODIFY_EACH_END
+}
+
+DIRECT (MODIFY_Network_updateWeights) {
+	MODIFY_EACH (Network)
 		Network_updateWeights (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (Network_zeroActivities, U"Network: Zero activities", 0) {
-	INTEGER (U"From node", U"1")
-	INTEGER (U"To node", U"0 (= all)")
-	OK2
+FORM (MODIFY_Network_zeroActivities, U"Network: Zero activities", nullptr) {
+	INTEGER4 (fromNode, U"From node", U"1")
+	INTEGER4 (toNode, U"To node", U"0 (= all)")
+	OK
 DO
-	LOOP {
-		iam (Network);
-		Network_zeroActivities (me, GET_INTEGER (U"From node"), GET_INTEGER (U"To node"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Network)
+		Network_zeroActivities (me, fromNode, toNode);
+	MODIFY_EACH_END
+}
 
-#pragma mark -
-#pragma mark OTGRAMMAR
+// MARK: - OTGRAMMAR
 
-#pragma mark New
+// MARK: New
 
-DIRECT2 (OT_learning_tutorial) {
-	Melder_help (U"OT learning");
-END2 }
+DIRECT (HELP_OT_learning_tutorial) {
+	HELP (U"OT learning")
+}
 
-DIRECT2 (Create_NoCoda_grammar) {
-	autoOTGrammar me = OTGrammar_create_NoCoda_grammar ();
-	praat_new (me.move(), U"NoCoda");
-END2 }
+DIRECT (NEW1_Create_NoCoda_grammar) {
+	CREATE_ONE
+		autoOTGrammar result = OTGrammar_create_NoCoda_grammar ();
+	CREATE_ONE_END (U"NoCoda")
+}
 
-DIRECT2 (Create_NPA_grammar) {
-	autoOTGrammar me = OTGrammar_create_NPA_grammar ();
-	praat_new (me.move(), U"assimilation");
-END2 }
+DIRECT (NEW1_Create_NPA_grammar) {
+	CREATE_ONE
+		autoOTGrammar result = OTGrammar_create_NPA_grammar ();
+	CREATE_ONE_END (U"assimilation")
+}
 
-DIRECT2 (Create_NPA_distribution) {
-	autoPairDistribution me = OTGrammar_create_NPA_distribution ();
-	praat_new (me.move(), U"assimilation");
-END2 }
+DIRECT (NEW1_Create_NPA_distribution) {
+	CREATE_ONE
+		autoPairDistribution result = OTGrammar_create_NPA_distribution ();
+	CREATE_ONE_END (U"assimilation")
+}
 
-FORM (Create_tongue_root_grammar, U"Create tongue-root grammar", U"Create tongue-root grammar...") {
-	RADIO (U"Constraint set", 1)
+FORM (NEW1_Create_tongue_root_grammar, U"Create tongue-root grammar", U"Create tongue-root grammar...") {
+	RADIO4 (constraintSet, U"Constraint set", 1)
 		RADIOBUTTON (U"Five")
 		RADIOBUTTON (U"Nine")
-	RADIO (U"Ranking", 3)
+	RADIO4 (ranking, U"Ranking", 3)
 		RADIOBUTTON (U"Equal")
 		RADIOBUTTON (U"Random")
 		RADIOBUTTON (U"Infant")
 		RADIOBUTTON (U"Wolof")
-	OK2
+	OK
 DO
-	autoOTGrammar me = OTGrammar_create_tongueRoot_grammar (GET_INTEGER (U"Constraint set"), GET_INTEGER (U"Ranking"));
-	praat_new (me.move(), GET_STRING (U"Ranking"));
-END2 }
+	CREATE_ONE
+		autoOTGrammar result = OTGrammar_create_tongueRoot_grammar (constraintSet, ranking);
+	CREATE_ONE_END (GET_STRING (U"Ranking"))
+}
 
-FORM (Create_metrics_grammar, U"Create metrics grammar", 0) {
-	OPTIONMENU (U"Initial ranking", 1)
+FORM (NEW1_Create_metrics_grammar, U"Create metrics grammar", nullptr) {
+	OPTIONMENU4 (initialRanking, U"Initial ranking", 1)
 		OPTION (U"Equal")
 		OPTION (U"Foot form high")
 		OPTION (U"WSP high")
-	OPTIONMENU (U"Trochaicity constraint", 1)
+	OPTIONMENU4 (trochaicityConstraint, U"Trochaicity constraint", 1)
 		OPTION (U"FtNonfinal")
 		OPTION (U"Trochaic")
-	BOOLEAN (U"Include FootBimoraic", 0)
-	BOOLEAN (U"Include FootBisyllabic", 0)
-	BOOLEAN (U"Include Peripheral", 0)
-	OPTIONMENU (U"Nonfinality constraint", 1)
+	BOOLEAN4 (includeFootBimoraic, U"Include FootBimoraic", false)
+	BOOLEAN4 (includeFootBisyllabic, U"Include FootBisyllabic", false)
+	BOOLEAN4 (includePeripheral, U"Include Peripheral", false)
+	OPTIONMENU4 (nonfinalityConstraint, U"Nonfinality constraint", 1)
 		OPTION (U"Nonfinal")
 		OPTION (U"MainNonfinal")
 		OPTION (U"HeadNonfinal")
-	BOOLEAN (U"Overt forms have secondary stress", 1)
-	BOOLEAN (U"Include *Clash and *Lapse", 0)
-	BOOLEAN (U"Include codas", 0)
-	OK2
-DO
-	autoOTGrammar me = OTGrammar_create_metrics (GET_INTEGER (U"Initial ranking"), GET_INTEGER (U"Trochaicity constraint"),
-		GET_INTEGER (U"Include FootBimoraic"), GET_INTEGER (U"Include FootBisyllabic"),
-		GET_INTEGER (U"Include Peripheral"), GET_INTEGER (U"Nonfinality constraint"),
-		GET_INTEGER (U"Overt forms have secondary stress"), GET_INTEGER (U"Include *Clash and *Lapse"), GET_INTEGER (U"Include codas"));
-	praat_new (me.move(), GET_STRING (U"Initial ranking"));
-END2 }
+	BOOLEAN4 (overtFormsHaveSecondaryStress, U"Overt forms have secondary stress", true)
+	BOOLEAN4 (includeClashAndLapse, U"Include *Clash and *Lapse", false)
+	BOOLEAN4 (includeCodas, U"Include codas", false)
+	OK
+DO
+	CREATE_ONE
+		autoOTGrammar result = OTGrammar_create_metrics (initialRanking, trochaicityConstraint,
+			includeFootBimoraic, includeFootBisyllabic, includePeripheral, nonfinalityConstraint,
+			overtFormsHaveSecondaryStress, includeClashAndLapse, includeCodas);
+	CREATE_ONE_END (GET_STRING (U"Initial ranking"))
+}
+
+// MARK: Save
 
-#pragma mark Save
-FORM_WRITE2 (OTGrammar_writeToHeaderlessSpreadsheetFile, U"Write OTGrammar to spreadsheet", 0, U"txt") {
-	iam_ONLY (OTGrammar);
-	OTGrammar_writeToHeaderlessSpreadsheetFile (me, file);
-END2 }
+FORM_SAVE (SAVE_OTGrammar_writeToHeaderlessSpreadsheetFile, U"Write OTGrammar to spreadsheet", 0, U"txt") {
+	SAVE_ONE (OTGrammar)
+		OTGrammar_writeToHeaderlessSpreadsheetFile (me, file);
+	SAVE_ONE_END
+}
 
-#pragma mark Help
+// MARK: Help
 
-DIRECT2 (OTGrammar_help) {
-	Melder_help (U"OTGrammar");
-END2 }
+DIRECT (HELP_OTGrammar_help) {
+	HELP (U"OTGrammar")
+}
 
-#pragma mark Edit
+// MARK: View & Edit
 
-DIRECT2 (OTGrammar_edit) {
+DIRECT (WINDOW_OTGrammar_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot edit from batch.");
 	LOOP {
 		iam (OTGrammar);
@@ -471,313 +425,307 @@ DIRECT2 (OTGrammar_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-#pragma mark Draw
+// MARK: Draw
 
-FORM (OTGrammar_drawTableau, U"Draw tableau", U"OT learning") {
-	SENTENCE (U"Input string", U"")
-	OK2
+FORM (GRAPHICS_OTGrammar_drawTableau, U"Draw tableau", U"OT learning") {
+	SENTENCE4 (inputString, U"Input string", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_drawTableau (me, GRAPHICS, false, GET_STRING (U"Input string"));
-	}
-END2 }
+	GRAPHICS_EACH (OTGrammar)
+		OTGrammar_drawTableau (me, GRAPHICS, false, inputString);
+	GRAPHICS_EACH_END
+}
 
-FORM (OTGrammar_drawTableau_narrowly, U"Draw tableau (narrowly)", U"OT learning") {
-	SENTENCE (U"Input string", U"")
-	OK2
+FORM (GRAPHICS_OTGrammar_drawTableau_narrowly, U"Draw tableau (narrowly)", U"OT learning") {
+	SENTENCE4 (inputString, U"Input string", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_drawTableau (me, GRAPHICS, true, GET_STRING (U"Input string"));
-	}
-END2 }
-
-#pragma mark Query
-
-DIRECT2 (OTGrammar_getNumberOfConstraints) {
-	iam_ONLY (OTGrammar);
-	Melder_information (my numberOfConstraints);
-END2 }
-
-FORM (OTGrammar_getConstraint, U"Get constraint name", 0) {
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my constraints [icons]. name);
-END2 }
-
-FORM (OTGrammar_getRankingValue, U"Get ranking value", 0) {
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my constraints [icons]. ranking);
-END2 }
-
-FORM (OTGrammar_getDisharmony, U"Get disharmony", 0) {
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my constraints [icons]. disharmony);
-END2 }
-
-DIRECT2 (OTGrammar_getNumberOfTableaus) {
-	iam_ONLY (OTGrammar);
-	Melder_information (my numberOfTableaus);
-END2 }
-
-FORM (OTGrammar_getInput, U"Get input", 0) {
-	NATURAL (U"Tableau number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau number");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	Melder_information (my tableaus [itab]. input);
-END2 }
-
-FORM (OTGrammar_getNumberOfCandidates, U"Get number of candidates", 0) {
-	NATURAL (U"Tableau number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau number");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	Melder_information (my tableaus [itab]. numberOfCandidates);
-END2 }
-
-FORM (OTGrammar_getCandidate, U"Get candidate", 0) {
-	NATURAL (U"Tableau number", U"1")
-	NATURAL (U"Candidate number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	OTGrammarTableau tableau;
-	long itab = GET_INTEGER (U"Tableau number"), icand = GET_INTEGER (U"Candidate number");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	tableau = & my tableaus [itab];
-	if (icand > tableau -> numberOfCandidates)
-		Melder_throw (U"The specified candidate should not exceed the number of candidates.");
-	Melder_information (tableau -> candidates [icand]. output);
-END2 }
-
-FORM (OTGrammar_getNumberOfViolations, U"Get number of violations", 0) {
-	NATURAL (U"Tableau number", U"1")
-	NATURAL (U"Candidate number", U"1")
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau number"), icand = GET_INTEGER (U"Candidate number"), icons = GET_INTEGER (U"Constraint number");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	if (icand > my tableaus [itab]. numberOfCandidates)
-		Melder_throw (U"The specified candidate should not exceed the number of candidates.");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my tableaus [itab]. candidates [icand]. marks [icons]);
-END2 }
-
-#pragma mark Query (parse)
-
-FORM (OTGrammar_getWinner, U"Get winner", 0) {
-	NATURAL (U"Tableau", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	Melder_information (OTGrammar_getWinner (me, itab));
-END2 }
-
-FORM (OTGrammar_compareCandidates, U"Compare candidates", 0) {
-	NATURAL (U"Tableau number 1", U"1")
-	NATURAL (U"Candidate number 1", U"1")
-	NATURAL (U"Tableau number 2", U"1")
-	NATURAL (U"Candidate number 2", U"2")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab1 = GET_INTEGER (U"Tableau number 1"), icand1 = GET_INTEGER (U"Candidate number 1");
-	long itab2 = GET_INTEGER (U"Tableau number 2"), icand2 = GET_INTEGER (U"Candidate number 2");
-	if (itab1 > my numberOfTableaus)
-		Melder_throw (U"The specified tableau (number 1) should not exceed the number of tableaus.");
-	if (itab2 > my numberOfTableaus)
-		Melder_throw (U"The specified tableau (number 2) should not exceed the number of tableaus.");
-	if (icand1 > my tableaus [itab1]. numberOfCandidates)
-		Melder_throw (U"The specified candidate (number 1) should not exceed the number of candidates for this tableau.");
-	if (icand2 > my tableaus [itab1]. numberOfCandidates)
-		Melder_throw (U"The specified candidate (number 2) should not exceed the number of candidates for this tableau.");
-	Melder_information (OTGrammar_compareCandidates (me, itab1, icand1, itab2, icand2));
-END2 }
-
-FORM (OTGrammar_getNumberOfOptimalCandidates, U"Get number of optimal candidates", 0) {
-	NATURAL (U"Tableau number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau number");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	Melder_information (OTGrammar_getNumberOfOptimalCandidates (me, itab));
-END2 }
-
-FORM (OTGrammar_isCandidateGrammatical, U"Is candidate grammatical?", 0) {
-	NATURAL (U"Tableau", U"1")
-	NATURAL (U"Candidate", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	long icand = GET_INTEGER (U"Candidate");
-	if (icand > my tableaus [itab]. numberOfCandidates)
-		Melder_throw (U"The specified candidate should not exceed the number of candidates.");
-	Melder_information ((int) OTGrammar_isCandidateGrammatical (me, itab, icand));   // 0 or 1
-END2 }
-
-FORM (OTGrammar_isCandidateSinglyGrammatical, U"Is candidate singly grammatical?", 0) {
-	NATURAL (U"Tableau", U"1")
-	NATURAL (U"Candidate", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long itab = GET_INTEGER (U"Tableau");
-	if (itab > my numberOfTableaus)
-		Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
-	long icand = GET_INTEGER (U"Candidate");
-	if (icand > my tableaus [itab]. numberOfCandidates)
-		Melder_throw (U"The specified candidate should not exceed the number of candidates.");
-	Melder_information ((int) OTGrammar_isCandidateSinglyGrammatical (me, itab, icand));   // 0 or 1
-END2 }
-
-FORM (OTGrammar_getInterpretiveParse, U"OTGrammar: Interpretive parse", 0) {
-	SENTENCE (U"Partial output", U"")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	long bestInput, bestOutput;
-	OTGrammar_getInterpretiveParse (me, GET_STRING (U"Partial output"), & bestInput, & bestOutput);
-	Melder_information (U"Best input = ", bestInput, U": ", my tableaus [bestInput]. input,
-		U"\nBest output = ", bestOutput, U": ", my tableaus [bestInput]. candidates [bestOutput]. output);
-END2 }
-
-FORM (OTGrammar_isPartialOutputGrammatical, U"Is partial output grammatical?", 0) {
-	SENTENCE (U"Partial output", U"")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	Melder_information ((int) OTGrammar_isPartialOutputGrammatical (me, GET_STRING (U"Partial output")));   // "0" or "1"
-END2 }
-
-FORM (OTGrammar_isPartialOutputSinglyGrammatical, U"Is partial output singly grammatical?", 0) {
-	SENTENCE (U"Partial output", U"")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	Melder_information ((int) OTGrammar_isPartialOutputSinglyGrammatical (me, GET_STRING (U"Partial output")));   // "0" or "1"
-END2 }
-
-#pragma mark -
-
-FORM (OTGrammar_generateInputs, U"Generate inputs", U"OTGrammar: Generate inputs...") {
-	NATURAL (U"Number of trials", U"1000")
-	OK2
+	GRAPHICS_EACH (OTGrammar)
+		OTGrammar_drawTableau (me, GRAPHICS, true, inputString);
+	GRAPHICS_EACH_END
+}
+
+// MARK: Query
+
+DIRECT (INTEGER_OTGrammar_getNumberOfConstraints) {
+	INTEGER_ONE (OTGrammar)
+		long result = my numberOfConstraints;
+	INTEGER_ONE_END (U" constraints")
+}
+
+FORM (STRING_OTGrammar_getConstraint, U"Get constraint name", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		autoStrings thee = OTGrammar_generateInputs (me, GET_INTEGER (U"Number of trials"));
-		praat_new (thee.move(), my name, U"_in");
-	}
-END2 }
+	STRING_ONE (OTGrammar)
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
+		const char32 *result = my constraints [constraintNumber]. name;
+	STRING_ONE_END
+}
 
-DIRECT2 (OTGrammar_getInputs) {
-	LOOP {
-		iam (OTGrammar);
-		autoStrings thee = OTGrammar_getInputs (me);
-		praat_new (thee.move(), my name, U"_in");
-	}
-END2 }
+FORM (REAL_OTGrammar_getRankingValue, U"Get ranking value", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
+		double result = my constraints [constraintNumber]. ranking;
+	NUMBER_ONE_END (U" (ranking of constraint ", constraintNumber, U")")
+}
+
+FORM (REAL_OTGrammar_getDisharmony, U"Get disharmony", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
+		double result = my constraints [constraintNumber]. disharmony;
+	NUMBER_ONE_END (U" (disharmony of constraint ", constraintNumber, U")")
+}
+
+DIRECT (INTEGER_OTGrammar_getNumberOfTableaus) {
+	INTEGER_ONE (OTGrammar)
+		long result = my numberOfTableaus;
+	INTEGER_ONE_END (U" tableaus")
+}
+
+FORM (STRING_OTGrammar_getInput, U"Get input", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	OK
+DO
+	STRING_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		const char32 *result = my tableaus [tableauNumber]. input;
+	STRING_ONE_END
+}
 
-DIRECT2 (OTGrammar_measureTypology) {
+FORM (INTEGER_OTGrammar_getNumberOfCandidates, U"Get number of candidates", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		long result = my tableaus [tableauNumber]. numberOfCandidates;
+	NUMBER_ONE_END (U" candidates in tableau ", tableauNumber)
+}
+
+FORM (STRING_OTGrammar_getCandidate, U"Get candidate", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	NATURAL4 (candidateNumber, U"Candidate number", U"1")
+	OK
+DO
+	STRING_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		OTGrammarTableau tableau = & my tableaus [tableauNumber];
+		if (candidateNumber > tableau -> numberOfCandidates)
+			Melder_throw (U"The specified candidate should not exceed the number of candidates.");
+		const char32 *result = tableau -> candidates [candidateNumber]. output;
+	STRING_ONE_END
+}
+
+FORM (INTEGER_OTGrammar_getNumberOfViolations, U"Get number of violations", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	NATURAL4 (candidateNumber, U"Candidate number", U"1")
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		if (candidateNumber > my tableaus [tableauNumber]. numberOfCandidates)
+			Melder_throw (U"The specified candidate should not exceed the number of candidates.");
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
+		long result = my tableaus [tableauNumber]. candidates [candidateNumber]. marks [constraintNumber];
+	NUMBER_ONE_END (U" violations")
+}
+
+// MARK: Query (parse)
+
+FORM (INTEGER_OTGrammar_getWinner, U"Get winner", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		long result = OTGrammar_getWinner (me, tableauNumber);
+	NUMBER_ONE_END (U" (winner in tableau ", tableauNumber, U")")
+}
+
+FORM (INTEGER_OTGrammar_compareCandidates, U"Compare candidates", nullptr) {
+	NATURAL4 (tableauNumber1, U"Tableau number 1", U"1")
+	NATURAL4 (candidateNumber1, U"Candidate number 1", U"1")
+	NATURAL4 (tableauNumber2, U"Tableau number 2", U"1")
+	NATURAL4 (candidateNumber2, U"Candidate number 2", U"2")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber1 > my numberOfTableaus)
+			Melder_throw (U"The specified tableau (number 1) should not exceed the number of tableaus.");
+		if (candidateNumber1 > my tableaus [tableauNumber1]. numberOfCandidates)
+			Melder_throw (U"The specified candidate (number 1) should not exceed the number of candidates for this tableau.");
+		if (tableauNumber2 > my numberOfTableaus)
+			Melder_throw (U"The specified tableau (number 2) should not exceed the number of tableaus.");
+		if (candidateNumber2 > my tableaus [tableauNumber2]. numberOfCandidates)
+			Melder_throw (U"The specified candidate (number 2) should not exceed the number of candidates for this tableau.");
+		long result = OTGrammar_compareCandidates (me, tableauNumber1, candidateNumber1, tableauNumber2, candidateNumber2);
+	NUMBER_ONE_END (result == -1 ? U" (candidate 1 is better)" :
+					result == +1 ? U" (candidate 2 is better)" : U" (candidates are equally good)")
+}
+
+FORM (INTEGER_OTGrammar_getNumberOfOptimalCandidates, U"Get number of optimal candidates", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		long result = OTGrammar_getNumberOfOptimalCandidates (me, tableauNumber);
+	NUMBER_ONE_END (U" optimal candidates in tableau ", tableauNumber)
+}
+
+FORM (BOOLEAN_OTGrammar_isCandidateGrammatical, U"Is candidate grammatical?", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	NATURAL4 (candidateNumber, U"Candidate number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		if (candidateNumber > my tableaus [tableauNumber]. numberOfCandidates)
+			Melder_throw (U"The specified candidate should not exceed the number of candidates.");
+		long result = OTGrammar_isCandidateGrammatical (me, tableauNumber, candidateNumber);
+	NUMBER_ONE_END (result ? U" (grammatical)" : U" (ungrammatical)")
+}
+
+FORM (BOOLEAN_OTGrammar_isCandidateSinglyGrammatical, U"Is candidate singly grammatical?", nullptr) {
+	NATURAL4 (tableauNumber, U"Tableau number", U"1")
+	NATURAL4 (candidateNumber, U"Candidate number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		if (tableauNumber > my numberOfTableaus)
+			Melder_throw (U"The specified tableau number should not exceed the number of tableaus.");
+		if (candidateNumber > my tableaus [tableauNumber]. numberOfCandidates)
+			Melder_throw (U"The specified candidate should not exceed the number of candidates.");
+		long result = OTGrammar_isCandidateSinglyGrammatical (me, tableauNumber, candidateNumber);
+	NUMBER_ONE_END (result ? U" (singly grammatical)" : U" (not singly grammatical)")
+}
+
+FORM (STRING_OTGrammar_getInterpretiveParse, U"OTGrammar: Interpretive parse", nullptr) {
+	SENTENCE4 (partialOutput, U"Partial output", U"")
+	OK
+DO
+	FIND_ONE (OTGrammar)
+		long bestInput, bestOutput;
+		OTGrammar_getInterpretiveParse (me, partialOutput, & bestInput, & bestOutput);
+		Melder_information (U"Best input = ", bestInput, U": ", my tableaus [bestInput]. input,
+			U"\nBest output = ", bestOutput, U": ", my tableaus [bestInput]. candidates [bestOutput]. output);
+	END
+}
+
+FORM (BOOLEAN_OTGrammar_isPartialOutputGrammatical, U"Is partial output grammatical?", nullptr) {
+	SENTENCE4 (partialOutput, U"Partial output", U"")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		long result = OTGrammar_isPartialOutputGrammatical (me, partialOutput);
+	NUMBER_ONE_END (result ? U" (grammatical)" : U" (ungrammatical)")
+}
+
+FORM (BOOLEAN_OTGrammar_isPartialOutputSinglyGrammatical, U"Is partial output singly grammatical?", nullptr) {
+	SENTENCE4 (partialOutput, U"Partial output", U"")
+	OK
+DO
+	NUMBER_ONE (OTGrammar)
+		long result = OTGrammar_isPartialOutputSinglyGrammatical (me, partialOutput);
+	NUMBER_ONE_END (result ? U" (singly grammatical)" : U" (not singly grammatical)")
+}
+
+// MARK: -
+
+FORM (NEW_OTGrammar_generateInputs, U"Generate inputs", U"OTGrammar: Generate inputs...") {
+	NATURAL4 (numberOfTrials, U"Number of trials", U"1000")
+	OK
+DO
+	CONVERT_EACH (OTGrammar)
+		autoStrings result = OTGrammar_generateInputs (me, numberOfTrials);
+	CONVERT_EACH_END (my name, U"_in")
+}
+
+DIRECT (NEW_OTGrammar_getInputs) {
+	CONVERT_EACH (OTGrammar)
+		autoStrings result = OTGrammar_getInputs (me);
+	CONVERT_EACH_END (my name, U"_in")
+}
+
+DIRECT (NEW_MODIFY_OTGrammar_measureTypology) {
 	LOOP try {
 		iam (OTGrammar);
-		autoDistributions thee = OTGrammar_measureTypology (me);
+		autoDistributions thee = OTGrammar_measureTypology_WEAK (me);
 		praat_new (thee.move(), my name, U"_out");
 		praat_dataChanged (me);
 	} catch (MelderError) {
 		praat_dataChanged (OBJECT);
 		throw;
 	}
-END2 }
+END }
 
-#pragma mark Evaluate
+// MARK: Evaluate
 
-FORM (OTGrammar_evaluate, U"OTGrammar: Evaluate", 0) {
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
+FORM (MODIFY_OTGrammar_evaluate, U"OTGrammar: Evaluate", nullptr) {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_newDisharmonies (me, GET_REAL (U"Evaluation noise"));
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_newDisharmonies (me, evaluationNoise);
+	MODIFY_EACH_END
+}
+
+FORM (STRING_MODIFY_OTGrammar_inputToOutput, U"OTGrammar: Input to output", U"OTGrammar: Input to output...") {
+	SENTENCE4 (inputForm, U"Input form", U"")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
+DO
+	FIND_ONE (OTGrammar)
+		char32 output [100];
+		OTGrammar_inputToOutput (me, inputForm, output, evaluationNoise);
+		Melder_information (output);
 		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (OTGrammar_inputToOutput, U"OTGrammar: Input to output", U"OTGrammar: Input to output...") {
-	SENTENCE (U"Input form", U"")
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	char32 output [100];
-	OTGrammar_inputToOutput (me, GET_STRING (U"Input form"), output, GET_REAL (U"Evaluation noise"));
-	Melder_information (output);
-	praat_dataChanged (me);
-END2 }
-
-FORM (OTGrammar_inputToOutputs, U"OTGrammar: Input to outputs", U"OTGrammar: Input to outputs...") {
-	NATURAL (U"Trials", U"1000")
-	REAL (U"Evaluation noise", U"2.0")
-	SENTENCE (U"Input form", U"")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	autoStrings thee = OTGrammar_inputToOutputs (me, GET_STRING (U"Input form"), GET_INTEGER (U"Trials"), GET_REAL (U"Evaluation noise"));
-	praat_new (thee.move(), my name, U"_out");
-	praat_dataChanged (me);
-END2 }
-
-FORM (OTGrammar_to_Distributions, U"OTGrammar: Compute output distributions", U"OTGrammar: To output Distributions...") {
-	NATURAL (U"Trials per input", U"100000")
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
+	END
+}
+
+FORM (NEW1_MODIFY_OTGrammar_inputToOutputs, U"OTGrammar: Input to outputs", U"OTGrammar: Input to outputs...") {
+	NATURAL4 (trials, U"Trials", U"1000")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	SENTENCE4 (inputForm, U"Input form", U"")
+	OK
+DO
+	FIND_ONE (OTGrammar)
+		autoStrings thee = OTGrammar_inputToOutputs (me, inputForm, trials, evaluationNoise);
+		praat_new (thee.move(), my name, U"_out");
+		praat_dataChanged (me);
+	END
+}
+
+FORM (NEW_MODIFY_OTGrammar_to_Distributions, U"OTGrammar: Compute output distributions", U"OTGrammar: To output Distributions...") {
+	NATURAL4 (trialsPerInput, U"Trials per input", U"100000")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
 DO
 	LOOP {
 		iam (OTGrammar);
 		try {
-			autoDistributions thee = OTGrammar_to_Distribution (me, GET_INTEGER (U"Trials per input"), GET_REAL (U"Evaluation noise"));
+			autoDistributions thee = OTGrammar_to_Distribution (me, trialsPerInput, evaluationNoise);
 			praat_new (thee.move(), my name, U"_out");
 			praat_dataChanged (me);
 		} catch (MelderError) {
@@ -785,573 +733,499 @@ DO
 			throw;
 		}
 	}
-END2 }
+END }
 
-FORM (OTGrammar_to_PairDistribution, U"OTGrammar: Compute output distributions", 0) {
-	NATURAL (U"Trials per input", U"100000")
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
+FORM (NEW_MODIFY_OTGrammar_to_PairDistribution, U"OTGrammar: Compute output distributions", nullptr) {
+	NATURAL4 (trialsPerInput, U"Trials per input", U"100000")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
 DO
 	LOOP try {
 		iam (OTGrammar);
-		autoPairDistribution thee = OTGrammar_to_PairDistribution (me, GET_INTEGER (U"Trials per input"), GET_REAL (U"Evaluation noise"));
+		autoPairDistribution thee = OTGrammar_to_PairDistribution (me, trialsPerInput, evaluationNoise);
 		praat_new (thee.move(), my name, U"_out");
 		praat_dataChanged (me);
 	} catch (MelderError) {
 		praat_dataChanged (OBJECT);
 		throw;
 	}
-END2 }
+END }
 
-#pragma mark Modify ranking
+// MARK: Modify ranking
 
-FORM (OTGrammar_setRanking, U"OTGrammar: Set ranking", 0) {
-	NATURAL (U"Constraint", U"1")
-	REAL (U"Ranking", U"100.0")
-	REAL (U"Disharmony", U"100.0")
-	OK2
+FORM (MODIFY_OTGrammar_setRanking, U"OTGrammar: Set ranking", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	REAL4 (ranking, U"Ranking", U"100.0")
+	REAL4 (disharmony, U"Disharmony", U"100.0")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_setRanking (me, GET_INTEGER (U"Constraint"), GET_REAL (U"Ranking"), GET_REAL (U"Disharmony"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_setRanking (me, constraintNumber, ranking, disharmony);
+	MODIFY_EACH_END
+}
 
-FORM (OTGrammar_resetAllRankings, U"OTGrammar: Reset all rankings", 0) {
-	REAL (U"Ranking", U"100.0")
-	OK2
+FORM (MODIFY_OTGrammar_resetAllRankings, U"OTGrammar: Reset all rankings", nullptr) {
+	REAL4 (ranking, U"Ranking", U"100.0")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_reset (me, GET_REAL (U"Ranking"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_reset (me, ranking);
+	MODIFY_EACH_END
+}
 
-FORM (OTGrammar_resetToRandomRanking, U"OTGrammar: Reset to random ranking", 0) {
-	REAL (U"Mean", U"10.0")
-	POSITIVE (U"Standard deviation", U"0.0001")
-	OK2
+FORM (MODIFY_OTGrammar_resetToRandomRanking, U"OTGrammar: Reset to random ranking", nullptr) {
+	REAL4 (mean, U"Mean", U"10.0")
+	POSITIVE4 (standardDeviation, U"Standard deviation", U"1e-4")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_resetToRandomRanking (me, GET_REAL (U"Mean"), GET_REAL (U"Standard deviation"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_resetToRandomRanking (me, mean, standardDeviation);
+	MODIFY_EACH_END
+}
 
-FORM (OTGrammar_resetToRandomTotalRanking, U"OTGrammar: Reset to random total ranking", 0) {
-	REAL (U"Maximum ranking", U"100.0")
-	POSITIVE (U"Ranking distance", U"1.0")
-	OK2
-DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_resetToRandomTotalRanking (me, GET_REAL (U"Maximum ranking"), GET_REAL (U"Ranking distance"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (OTGrammar_learnOne, U"OTGrammar: Learn one", U"OTGrammar: Learn one...") {
-	SENTENCE (U"Input string", U"")
-	SENTENCE (U"Output string", U"")
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Plasticity", U"0.1")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	OK2
+FORM (MODIFY_OTGrammar_resetToRandomTotalRanking, U"OTGrammar: Reset to random total ranking", nullptr) {
+	REAL4 (maximumRanking, U"Maximum ranking", U"100.0")
+	POSITIVE4 (rankingDistance, U"Ranking distance", U"1.0")
+	OK
 DO
-	LOOP try {
-		iam (OTGrammar);
-		OTGrammar_learnOne (me, GET_STRING (U"Input string"), GET_STRING (U"Output string"),
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Plasticity"), GET_REAL (U"Rel. plasticity spreading"), true, true, nullptr);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (OBJECT);
-		throw;
-	}
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_resetToRandomTotalRanking (me, maximumRanking, rankingDistance);
+	MODIFY_EACH_END
+}
 
-FORM (OTGrammar_learnOneFromPartialOutput, U"OTGrammar: Learn one from partial adult output", 0) {
+FORM (MODIFY_OTGrammar_learnOne, U"OTGrammar: Learn one", U"OTGrammar: Learn one...") {
+	SENTENCE4 (inputString, U"Input string", U"")
+	SENTENCE4 (outputString, U"Output string", U"")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (plasticity, U"Plasticity", U"0.1")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	OK
+DO
+	MODIFY_EACH_WEAK (OTGrammar)
+		OTGrammar_learnOne (me, inputString, outputString, evaluationNoise,
+			(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+			plasticity, relativePlasticitySpreading, true, true, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_OTGrammar_learnOneFromPartialOutput, U"OTGrammar: Learn one from partial adult output", nullptr) {
 	LABEL (U"", U"Partial adult surface form (e.g. overt form):")
-	SENTENCE (U"Partial output", U"")
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Plasticity", U"0.1")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	OK2
+	SENTENCE4 (partialOutput, U"Partial output", U"")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (plasticity, U"Plasticity", U"0.1")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	OK
+DO
+	MODIFY_EACH_WEAK (OTGrammar)
+		OTGrammar_learnOneFromPartialOutput (me, partialOutput, evaluationNoise,
+			(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+			plasticity, relativePlasticitySpreading, numberOfChews, true);
+	MODIFY_EACH_WEAK_END
+}
+
+// MARK: Modify behaviour
+
+FORM (MODIFY_OTGrammar_setDecisionStrategy, U"OTGrammar: Set decision strategy", nullptr) {
+	RADIO_ENUM4 (decisionStrategy, U"Decision strategy", kOTGrammar_decisionStrategy, DEFAULT)
+OK
+	FIND_ONE (OTGrammar)
+		SET_ENUM (U"Decision strategy", kOTGrammar_decisionStrategy, my decisionStrategy);
 DO
-	LOOP try {
-		iam (OTGrammar);
-		OTGrammar_learnOneFromPartialOutput (me, GET_STRING (U"Partial output"),
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Plasticity"), GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"), true);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (OBJECT);
-		throw;
-	}
-END2 }
+	MODIFY_EACH (OTGrammar)
+		my decisionStrategy = decisionStrategy;
+	MODIFY_EACH_END
+}
 
-#pragma mark Modify behaviour
+FORM (MODIFY_OTGrammar_setLeak, U"OTGrammar: Set leak", nullptr) {
+	REAL4 (leak, U"Leak", U"0.0")
+OK
+	FIND_ONE (OTGrammar)
+		SET_REAL (U"Leak", my leak);
+DO
+	MODIFY_EACH (OTGrammar)
+		my leak = leak;
+	MODIFY_EACH_END
+}
 
-FORM (OTGrammar_setDecisionStrategy, U"OTGrammar: Set decision strategy", 0) {
-	RADIO_ENUM (U"Decision strategy", kOTGrammar_decisionStrategy, DEFAULT)
-	OK2
-iam_ONLY (OTGrammar);
-SET_ENUM (U"Decision strategy", kOTGrammar_decisionStrategy, my decisionStrategy);
+FORM (MODIFY_OTGrammar_setConstraintPlasticity, U"OTGrammar: Set constraint plasticity", nullptr) {
+	NATURAL4 (constraint, U"Constraint", U"1")
+	REAL4 (plasticity, U"Plasticity", U"1.0")
+	OK
 DO
-	iam_ONLY (OTGrammar);
-	my decisionStrategy = GET_ENUM (kOTGrammar_decisionStrategy, U"Decision strategy");
-	praat_dataChanged (me);
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_setConstraintPlasticity (me, constraint, plasticity);
+	MODIFY_EACH_END
+}
+
+// MARK: Modify structure
 
-FORM (OTGrammar_setLeak, U"OTGrammar: Set leak", 0) {
-	REAL (U"Leak", U"0.0")
-	OK2
-iam_ONLY (OTGrammar);
-SET_REAL (U"Leak", my leak);
+FORM (MODIFY_OTGrammar_removeConstraint, U"OTGrammar: Remove constraint", nullptr) {
+	SENTENCE4 (constraintName, U"Constraint name", U"")
+	OK
 DO
-	iam_ONLY (OTGrammar);
-	my leak = GET_REAL (U"Leak");
-	praat_dataChanged (me);
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_removeConstraint (me, constraintName);
+	MODIFY_EACH_END
+}
 
-FORM (OTGrammar_setConstraintPlasticity, U"OTGrammar: Set constraint plasticity", 0) {
-	NATURAL (U"Constraint", U"1")
-	REAL (U"Plasticity", U"1.0")
-	OK2
+FORM (MODIFY_OTGrammar_removeHarmonicallyBoundedCandidates, U"OTGrammar: Remove harmonically bounded candidates", nullptr) {
+	BOOLEAN4 (singly, U"Singly", false)
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_setConstraintPlasticity (me, GET_INTEGER (U"Constraint"), GET_REAL (U"Plasticity"));
-		praat_dataChanged (OBJECT);
-	}
-END2 }
+	MODIFY_EACH (OTGrammar)
+		OTGrammar_removeHarmonicallyBoundedCandidates (me, singly);
+	MODIFY_EACH_END
+}
 
-#pragma mark Modify structure
+// MARK: OTGRAMMAR & STRINGS
 
-FORM (OTGrammar_removeConstraint, U"OTGrammar: Remove constraint", 0) {
-	SENTENCE (U"Constraint name", U"")
-	OK2
+FORM (NEW1_MODIFY_OTGrammar_Strings_inputsToOutputs, U"OTGrammar: Inputs to outputs", U"OTGrammar: Inputs to outputs...") {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_removeConstraint (me, GET_STRING (U"Constraint name"));
+	FIND_TWO (OTGrammar, Strings)
+		autoStrings result = OTGrammar_inputsToOutputs (me, you, evaluationNoise);
+		praat_new (result.move(), my name, U"_out");
 		praat_dataChanged (me);
-	}
-END2 }
+	END
+}
+
+DIRECT (BOOLEAN_OTGrammar_Strings_areAllPartialOutputsGrammatical) {
+	NUMBER_TWO (OTGrammar, Strings)
+		long result = OTGrammar_areAllPartialOutputsGrammatical (me, you);
+	NUMBER_TWO_END (result ? U" (all grammatical)" : U" (not all grammatical)")
+}
+
+DIRECT (BOOLEAN_OTGrammar_Strings_areAllPartialOutputsSinglyGrammatical) {
+	NUMBER_TWO (OTGrammar, Strings)
+		long result = OTGrammar_areAllPartialOutputsSinglyGrammatical (me, you);
+	NUMBER_TWO_END (result ? U" (all singly grammatical)" : U" (not all singly grammatical)")
+}
+
+FORM (MODIFY_OTGrammar_Stringses_learn, U"OTGrammar: Learn", U"OTGrammar & 2 Strings: Learn...") {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (plasticity, U"Plasticity", U"0.1")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	OK
+DO
+	MODIFY_FIRST_OF_ONE_AND_COUPLE_WEAK (OTGrammar, Strings)
+		OTGrammar_learn (me, you, him, evaluationNoise, (enum kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+			plasticity, relativePlasticitySpreading, numberOfChews);
+	MODIFY_FIRST_OF_ONE_AND_COUPLE_WEAK_END
+}
 
-FORM (OTGrammar_removeHarmonicallyBoundedCandidates, U"OTGrammar: Remove harmonically bounded candidates", 0) {
-	BOOLEAN (U"Singly", 0)
-	OK2
+FORM (MODIFY_OTGrammar_Strings_learnFromPartialOutputs, U"OTGrammar: Learn from partial adult outputs", nullptr) {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (plasticity, U"Plasticity", U"0.1")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	INTEGER4 (storeHistoryEvery, U"Store history every", U"0")
+	OK
+DO
+	FIND_TWO (OTGrammar, Strings)
+		autoOTHistory history;
+		try {
+			OTGrammar_learnFromPartialOutputs (me, you, evaluationNoise,
+				(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+				plasticity, relativePlasticitySpreading, numberOfChews, storeHistoryEvery, & history);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);   // e.g. in case of partial learning
+			Melder_flushError ();
+			// trickle down to save history
+		}
+		if (history) praat_new (history.move(), my name);
+	END
+}
+
+// MARK: OTGRAMMAR & DISTRIBUTIONS
+
+FORM (REAL_MODIFY_OTGrammar_Distributions_getFractionCorrect, U"OTGrammar & Distributions: Get fraction correct...", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	INTEGER4 (replications, U"Replications", U"100000")
+	OK
 DO
-	LOOP {
-		iam (OTGrammar);
-		OTGrammar_removeHarmonicallyBoundedCandidates (me, GET_INTEGER (U"Singly"));
+	FIND_TWO (OTGrammar, Distributions)
+		double result = OTGrammar_Distributions_getFractionCorrect (me, you, columnNumber,
+			evaluationNoise, replications);
 		praat_dataChanged (me);
-	}
-END2 }
-
-#pragma mark OTGRAMMAR & STRINGS
-
-FORM (OTGrammar_Strings_inputsToOutputs, U"OTGrammar: Inputs to outputs", U"OTGrammar: Inputs to outputs...") {
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Strings);
-	autoStrings him = OTGrammar_inputsToOutputs (me, thee, GET_REAL (U"Evaluation noise"));
-	praat_new (him.move(), my name, U"_out");
-	praat_dataChanged (me);
-END2 }
-
-DIRECT2 (OTGrammar_Strings_areAllPartialOutputsGrammatical) {
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Strings);
-	Melder_information ((int) OTGrammar_areAllPartialOutputsGrammatical (me, thee));   // "0" or "1"
-END2 }
-
-DIRECT2 (OTGrammar_Strings_areAllPartialOutputsSinglyGrammatical) {
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Strings);
-	Melder_information ((int) OTGrammar_areAllPartialOutputsSinglyGrammatical (me, thee));   // "0" or "1"
-END2 }
-
-FORM (OTGrammar_Stringses_learn, U"OTGrammar: Learn", U"OTGrammar & 2 Strings: Learn...") {
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Plasticity", U"0.1")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	Strings inputs = nullptr, outputs = nullptr;
-	WHERE (SELECTED && CLASS == classStrings) { if (! inputs) inputs = (Strings) OBJECT; else outputs = (Strings) OBJECT; }
-	try {
-		OTGrammar_learn (me, inputs, outputs,
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Plasticity"), GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"));
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);   // partial change
-		throw;
-	}
-END2 }
-
-FORM (OTGrammar_Strings_learnFromPartialOutputs, U"OTGrammar: Learn from partial adult outputs", 0) {
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Plasticity", U"0.1")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	INTEGER (U"Store history every", U"0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Strings);
-	autoOTHistory history;
-	try {
-		OTGrammar_learnFromPartialOutputs (me, thee,
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Plasticity"), GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"),
-			GET_INTEGER (U"Store history every"), & history);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);   // e.g. in case of partial learning
-		Melder_flushError ();
-		// trickle down to save history
-	}
-	if (history) praat_new (history.move(), my name);
-END2 }
-
-#pragma mark OTGRAMMAR & DISTRIBUTIONS
-
-FORM (OTGrammar_Distributions_getFractionCorrect, U"OTGrammar & Distributions: Get fraction correct...", 0) {
-	NATURAL (U"Column number", U"1")
-	REAL (U"Evaluation noise", U"2.0")
-	INTEGER (U"Replications", U"100000")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Distributions);
-	double result = OTGrammar_Distributions_getFractionCorrect (me, thee, GET_INTEGER (U"Column number"),
-		GET_REAL (U"Evaluation noise"), GET_INTEGER (U"Replications"));
-	praat_dataChanged (me);
-	Melder_informationReal (result, nullptr);
-END2 }
-
-FORM (OTGrammar_Distributions_learnFromPartialOutputs, U"OTGrammar & Distributions: Learn from partial outputs", U"OT learning 6. Shortcut to grammar learning") {
-	NATURAL (U"Column number", U"1")
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Initial plasticity", U"1.0")
-	NATURAL (U"Replications per plasticity", U"100000")
-	REAL (U"Plasticity decrement", U"0.1")
-	NATURAL (U"Number of plasticities", U"4")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	INTEGER (U"Store history every", U"0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Distributions);
-	autoOTHistory history;
-	try {
-		OTGrammar_Distributions_learnFromPartialOutputs (me, thee, GET_INTEGER (U"Column number"),
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Initial plasticity"), GET_INTEGER (U"Replications per plasticity"),
-			GET_REAL (U"Plasticity decrement"), GET_INTEGER (U"Number of plasticities"),
-			GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"),
-			GET_INTEGER (U"Store history every"), & history, false, false, 0);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		Melder_flushError ();
-	}
-	if (history) praat_new (history.move(), my name);
-END2 }
-
-FORM (OTGrammar_Distributions_learnFromPartialOutputs_rrip, U"OTGrammar & Distributions: Learn from partial outputs (rrip)", U"OT learning 6. Shortcut to grammar learning") {
-	NATURAL (U"Column number", U"1")
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Initial plasticity", U"1.0")
-	NATURAL (U"Replications per plasticity", U"100000")
-	REAL (U"Plasticity decrement", U"0.1")
-	NATURAL (U"Number of plasticities", U"4")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	INTEGER (U"Store history every", U"0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Distributions);
-	autoOTHistory history;
-	try {
-		OTGrammar_Distributions_learnFromPartialOutputs (me, thee, GET_INTEGER (U"Column number"),
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Initial plasticity"), GET_INTEGER (U"Replications per plasticity"),
-			GET_REAL (U"Plasticity decrement"), GET_INTEGER (U"Number of plasticities"),
-			GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"),
-			GET_INTEGER (U"Store history every"), & history, true, true, 0);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		Melder_flushError ();
-	}
-	if (history) praat_new (history.move(), my name);
-END2 }
-
-FORM (OTGrammar_Distributions_learnFromPartialOutputs_eip, U"OTGrammar & Distributions: Learn from partial outputs (eip)", U"OT learning 6. Shortcut to grammar learning") {
-	NATURAL (U"Column number", U"1")
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Initial plasticity", U"1.0")
-	NATURAL (U"Replications per plasticity", U"100000")
-	REAL (U"Plasticity decrement", U"0.1")
-	NATURAL (U"Number of plasticities", U"4")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	INTEGER (U"Store history every", U"0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Distributions);
-	autoOTHistory history;
-	try {
-		OTGrammar_Distributions_learnFromPartialOutputs (me, thee, GET_INTEGER (U"Column number"),
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Initial plasticity"), GET_INTEGER (U"Replications per plasticity"),
-			GET_REAL (U"Plasticity decrement"), GET_INTEGER (U"Number of plasticities"),
-			GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"),
-			GET_INTEGER (U"Store history every"), & history, true, true, 1000);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		Melder_flushError ();
-	}
-	if (history) praat_new (history.move(), my name);
-END2 }
-
-FORM (OTGrammar_Distributions_learnFromPartialOutputs_wrip, U"OTGrammar & Distributions: Learn from partial outputs (wrip)", U"OT learning 6. Shortcut to grammar learning") {
-	NATURAL (U"Column number", U"1")
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	REAL (U"Initial plasticity", U"1.0")
-	NATURAL (U"Replications per plasticity", U"100000")
-	REAL (U"Plasticity decrement", U"0.1")
-	NATURAL (U"Number of plasticities", U"4")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", 1)
-	NATURAL (U"Number of chews", U"1")
-	INTEGER (U"Store history every", U"0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Distributions);
-	autoOTHistory history;
-	try {
-		OTGrammar_Distributions_learnFromPartialOutputs (me, thee, GET_INTEGER (U"Column number"),
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Initial plasticity"), GET_INTEGER (U"Replications per plasticity"),
-			GET_REAL (U"Plasticity decrement"), GET_INTEGER (U"Number of plasticities"),
-			GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"),
-			GET_INTEGER (U"Store history every"), & history, true, true, 1);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		Melder_flushError ();
-	}
-	if (history) praat_new (history.move(), my name);
-END2 }
-
-FORM (OTGrammar_Distributions_listObligatoryRankings, U"OTGrammar & Distributions: Get fraction correct...", 0) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (Distributions);
-	OTGrammar_Distributions_listObligatoryRankings (me, thee, GET_INTEGER (U"Column number"));
-END2 }
-
-#pragma mark OTGRAMMAR & PAIRDISTRIBUTION
-
-FORM (OTGrammar_PairDistribution_findPositiveWeights, U"OTGrammar & PairDistribution: Find positive weights", U"OTGrammar & PairDistribution: Find positive weights...") {
-	POSITIVE (U"Weight floor", U"1.0")
-	POSITIVE (U"Margin of separation", U"1.0")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (PairDistribution);
-	OTGrammar_PairDistribution_findPositiveWeights_e (me, thee,
-		GET_REAL (U"Weight floor"), GET_REAL (U"Margin of separation"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (OTGrammar_PairDistribution_getFractionCorrect, U"OTGrammar & PairDistribution: Get fraction correct...", 0) {
-	REAL (U"Evaluation noise", U"2.0")
-	INTEGER (U"Replications", U"100000")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (PairDistribution);
-	double result;
-	try {
-		result = OTGrammar_PairDistribution_getFractionCorrect (me, thee,
-			GET_REAL (U"Evaluation noise"), GET_INTEGER (U"Replications"));
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		throw;
-	}
-	Melder_informationReal (result, nullptr);
-END2 }
-
-FORM (OTGrammar_PairDistribution_getMinimumNumberCorrect, U"OTGrammar & PairDistribution: Get minimum number correct...", 0) {
-	REAL (U"Evaluation noise", U"2.0")
-	INTEGER (U"Replications per input", U"1000")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (PairDistribution);
-	long result;
-	try {
-		result = OTGrammar_PairDistribution_getMinimumNumberCorrect (me, thee,
-			GET_REAL (U"Evaluation noise"), GET_INTEGER (U"Replications per input"));
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		throw;
-	}
-	Melder_information (result);
-END2 }
-
-FORM (OTGrammar_PairDistribution_learn, U"OTGrammar & PairDistribution: Learn", U"OT learning 6. Shortcut to grammar learning") {
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	POSITIVE (U"Initial plasticity", U"1.0")
-	NATURAL (U"Replications per plasticity", U"100000")
-	REAL (U"Plasticity decrement", U"0.1")
-	NATURAL (U"Number of plasticities", U"4")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	BOOLEAN (U"Honour local rankings", true)
-	NATURAL (U"Number of chews", U"1")
-	OK2
-DO
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (PairDistribution);
-	try {
-		OTGrammar_PairDistribution_learn (me, thee,
-			GET_REAL (U"Evaluation noise"), GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"), GET_INTEGER (U"Honour local rankings"),
-			GET_REAL (U"Initial plasticity"), GET_INTEGER (U"Replications per plasticity"),
-			GET_REAL (U"Plasticity decrement"), GET_INTEGER (U"Number of plasticities"),
-			GET_REAL (U"Rel. plasticity spreading"), GET_INTEGER (U"Number of chews"));
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);
-		throw;
-	}
-END2 }
+		Melder_informationReal (result, nullptr);
+	END
+}
 
-DIRECT2 (OTGrammar_PairDistribution_listObligatoryRankings) {
-	iam_ONLY (OTGrammar);
-	thouart_ONLY (PairDistribution);
-	OTGrammar_PairDistribution_listObligatoryRankings (me, thee);
-END2 }
+FORM (MODIFY_OTGrammar_Distributions_learnFromPartialOutputs, U"OTGrammar & Distributions: Learn from partial outputs", U"OT learning 6. Shortcut to grammar learning") {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (initialPlasticity, U"Initial plasticity", U"1.0")
+	NATURAL4 (replicationsPerPlasticity, U"Replications per plasticity", U"100000")
+	REAL4 (plasticityDecrement, U"Plasticity decrement", U"0.1")
+	NATURAL4 (numberOfPlasticities, U"Number of plasticities", U"4")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	INTEGER4 (storeHistoryEvery, U"Store history every", U"0")
+	OK
+DO
+	FIND_TWO (OTGrammar, Distributions)
+		autoOTHistory history;
+		try {
+			OTGrammar_Distributions_learnFromPartialOutputs (me, you, columnNumber, evaluationNoise,
+				(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+				initialPlasticity, replicationsPerPlasticity, plasticityDecrement, numberOfPlasticities,
+				relativePlasticitySpreading, numberOfChews, storeHistoryEvery, & history, false, false, 0);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			Melder_flushError ();
+		}
+		if (history) praat_new (history.move(), my name);
+	END
+}
 
-#pragma mark -
-#pragma mark OTMULTI
+FORM (MODIFY_OTGrammar_Distributions_learnFromPartialOutputs_rrip, U"OTGrammar & Distributions: Learn from partial outputs (rrip)", U"OT learning 6. Shortcut to grammar learning") {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (initialPlasticity, U"Initial plasticity", U"1.0")
+	NATURAL4 (replicationsPerPlasticity, U"Replications per plasticity", U"100000")
+	REAL4 (plasticityDecrement, U"Plasticity decrement", U"0.1")
+	NATURAL4 (numberOfPlasticities, U"Number of plasticities", U"4")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	INTEGER4 (storeHistoryEvery, U"Store history every", U"0")
+	OK
+DO
+	FIND_TWO (OTGrammar, Distributions)
+		autoOTHistory history;
+		try {
+			OTGrammar_Distributions_learnFromPartialOutputs (me, you, columnNumber, evaluationNoise,
+				(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+				initialPlasticity, replicationsPerPlasticity, plasticityDecrement, numberOfPlasticities,
+				relativePlasticitySpreading, numberOfChews, storeHistoryEvery, & history, true, true, 0);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			Melder_flushError ();
+		}
+		if (history) praat_new (history.move(), my name);
+	END
+}
 
-#pragma mark New
+FORM (MODIFY_OTGrammar_Distributions_learnFromPartialOutputs_eip, U"OTGrammar & Distributions: Learn from partial outputs (eip)", U"OT learning 6. Shortcut to grammar learning") {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (initialPlasticity, U"Initial plasticity", U"1.0")
+	NATURAL4 (replicationsPerPlasticity, U"Replications per plasticity", U"100000")
+	REAL4 (plasticityDecrement, U"Plasticity decrement", U"0.1")
+	NATURAL4 (numberOfPlasticities, U"Number of plasticities", U"4")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	INTEGER4 (storeHistoryEvery, U"Store history every", U"0")
+	OK
+DO
+	FIND_TWO (OTGrammar, Distributions)
+		autoOTHistory history;
+		try {
+			OTGrammar_Distributions_learnFromPartialOutputs (me, you, columnNumber, evaluationNoise,
+				(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+				initialPlasticity, replicationsPerPlasticity, plasticityDecrement, numberOfPlasticities,
+				relativePlasticitySpreading, numberOfChews, storeHistoryEvery, & history, true, true, 1000);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			Melder_flushError ();
+		}
+		if (history) praat_new (history.move(), my name);
+	END
+}
 
-FORM (Create_multi_level_metrics_grammar, U"Create multi-level metrics grammar", nullptr) {
-	OPTIONMENU (U"Initial ranking", 1)
+FORM (MODIFY_OTGrammar_Distributions_learnFromPartialOutputs_wrip, U"OTGrammar & Distributions: Learn from partial outputs (wrip)", U"OT learning 6. Shortcut to grammar learning") {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	REAL4 (initialPlasticity, U"Initial plasticity", U"1.0")
+	NATURAL4 (replicationsPerPlasticity, U"Replications per plasticity", U"100000")
+	REAL4 (plasticityDecrement, U"Plasticity decrement", U"0.1")
+	NATURAL4 (numberOfPlasticities, U"Number of plasticities", U"4")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", 1)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	INTEGER4 (storeHistoryEvery, U"Store history every", U"0")
+	OK
+DO
+	FIND_TWO (OTGrammar, Distributions)
+		autoOTHistory history;
+		try {
+			OTGrammar_Distributions_learnFromPartialOutputs (me, you, columnNumber, evaluationNoise,
+				(kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+				initialPlasticity, replicationsPerPlasticity, plasticityDecrement, numberOfPlasticities,
+				relativePlasticitySpreading, numberOfChews, storeHistoryEvery, & history, true, true, 1);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			Melder_flushError ();
+		}
+		if (history) praat_new (history.move(), my name);
+	END
+}
+
+FORM (LIST_OTGrammar_Distributions_listObligatoryRankings, U"OTGrammar & Distributions: Get fraction correct...", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	INFO_TWO (OTGrammar, Distributions)
+		OTGrammar_Distributions_listObligatoryRankings (me, you, columnNumber);
+	INFO_TWO_END
+}
+
+// MARK: OTGRAMMAR & PAIRDISTRIBUTION
+
+FORM (MODIFY_OTGrammar_PairDistribution_findPositiveWeights, U"OTGrammar & PairDistribution: Find positive weights", U"OTGrammar & PairDistribution: Find positive weights...") {
+	POSITIVE4 (weightFloor, U"Weight floor", U"1.0")
+	POSITIVE4 (marginOfSeparation, U"Margin of separation", U"1.0")
+	OK
+DO
+	MODIFY_FIRST_OF_TWO (OTGrammar, PairDistribution)
+		OTGrammar_PairDistribution_findPositiveWeights_e (me, you, weightFloor, marginOfSeparation);
+	MODIFY_FIRST_OF_TWO_END
+}
+
+FORM (REAL_MODIFY_OTGrammar_PairDistribution_getFractionCorrect, U"OTGrammar & PairDistribution: Get fraction correct...", nullptr) {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	INTEGER4 (replications, U"Replications", U"100000")
+	OK
+DO
+	FIND_TWO (OTGrammar, PairDistribution)
+		double result;
+		try {
+			result = OTGrammar_PairDistribution_getFractionCorrect (me, you, evaluationNoise, replications);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			throw;
+		}
+		Melder_information (result, U" correct");
+	END
+}
+
+FORM (INTEGER_MODIFY_OTGrammar_PairDistribution_getMinimumNumberCorrect, U"OTGrammar & PairDistribution: Get minimum number correct...", nullptr) {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	INTEGER4 (replicationsPerInput, U"Replications per input", U"1000")
+	OK
+DO
+	FIND_TWO (OTGrammar, PairDistribution)
+		long result;
+		try {
+			result = OTGrammar_PairDistribution_getMinimumNumberCorrect (me, you,
+				evaluationNoise, replicationsPerInput);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);
+			throw;
+		}
+		Melder_information (result, U" (minimally correct)");
+	END
+}
+
+FORM (MODIFY_OTGrammar_PairDistribution_learn, U"OTGrammar & PairDistribution: Learn", U"OT learning 6. Shortcut to grammar learning") {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	POSITIVE4 (initialPlasticity, U"Initial plasticity", U"1.0")
+	NATURAL4 (replicationsPerPlasticity, U"Replications per plasticity", U"100000")
+	REAL4 (plasticityDecrement, U"Plasticity decrement", U"0.1")
+	NATURAL4 (numberOfPlasticities, U"Number of plasticities", U"4")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	BOOLEAN4 (honourLocalRankings, U"Honour local rankings", true)
+	NATURAL4 (numberOfChews, U"Number of chews", U"1")
+	OK
+DO
+	MODIFY_FIRST_OF_TWO_WEAK (OTGrammar, PairDistribution)
+		OTGrammar_PairDistribution_learn (me, you,
+			evaluationNoise, (enum kOTGrammar_rerankingStrategy) updateRule, honourLocalRankings,
+			initialPlasticity, replicationsPerPlasticity,
+			plasticityDecrement, numberOfPlasticities, relativePlasticitySpreading, numberOfChews);
+	MODIFY_FIRST_OF_TWO_WEAK_END
+}
+
+DIRECT (LIST_OTGrammar_PairDistribution_listObligatoryRankings) {
+	FIND_TWO (OTGrammar, PairDistribution)
+		OTGrammar_PairDistribution_listObligatoryRankings (me, you);
+	END
+}
+
+// MARK: - OTMULTI
+
+// MARK: New
+
+FORM (NEW1_Create_multi_level_metrics_grammar, U"Create multi-level metrics grammar", nullptr) {
+	OPTIONMENU4 (initialRanking, U"Initial ranking", 1)
 		OPTION (U"Equal")
 		OPTION (U"Foot form high")
 		OPTION (U"WSP high")
-	OPTIONMENU (U"Trochaicity constraint", 1)
+	OPTIONMENU4 (trochaicityConstraint, U"Trochaicity constraint", 1)
 		OPTION (U"FtNonfinal")
 		OPTION (U"Trochaic")
-	BOOLEAN (U"Include FootBimoraic", false)
-	BOOLEAN (U"Include FootBisyllabic", false)
-	BOOLEAN (U"Include Peripheral", false)
-	OPTIONMENU (U"Nonfinality constraint", 1)
+	BOOLEAN4 (includeFootBimoraic, U"Include FootBimoraic", false)
+	BOOLEAN4 (includeFootBisyllabic, U"Include FootBisyllabic", false)
+	BOOLEAN4 (includePeripheral, U"Include Peripheral", false)
+	OPTIONMENU4 (nonfinalityConstraint, U"Nonfinality constraint", 1)
 		OPTION (U"Nonfinal")
 		OPTION (U"MainNonfinal")
 		OPTION (U"HeadNonfinal")
-	BOOLEAN (U"Overt forms have secondary stress", true)
-	BOOLEAN (U"Include *Clash and *Lapse", false)
-	BOOLEAN (U"Include codas", false)
-	OK2
-DO
-	autoOTMulti me = OTMulti_create_metrics (GET_INTEGER (U"Initial ranking"), GET_INTEGER (U"Trochaicity constraint"),
-		GET_INTEGER (U"Include FootBimoraic"), GET_INTEGER (U"Include FootBisyllabic"),
-		GET_INTEGER (U"Include Peripheral"), GET_INTEGER (U"Nonfinality constraint"),
-		GET_INTEGER (U"Overt forms have secondary stress"), GET_INTEGER (U"Include *Clash and *Lapse"), GET_INTEGER (U"Include codas"));
-	praat_new (me.move(), GET_STRING (U"Initial ranking"));
-END2 }
-
-#pragma mark Draw
-
-FORM (OTMulti_drawTableau, U"Draw tableau", U"OT learning") {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	BOOLEAN (U"Show disharmonies", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (OTMulti);
-		OTMulti_drawTableau (me, GRAPHICS, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2"),
-			false, GET_INTEGER (U"Show disharmonies"));
-	}
-END2 }
+	BOOLEAN4 (overtFormsHaveSecondaryStress, U"Overt forms have secondary stress", true)
+	BOOLEAN4 (includeClashAndLapse, U"Include *Clash and *Lapse", false)
+	BOOLEAN4 (includeCodas, U"Include codas", false)
+	OK
+DO
+	CREATE_ONE
+		autoOTMulti result = OTMulti_create_metrics (initialRanking, trochaicityConstraint,
+			includeFootBimoraic, includeFootBisyllabic, includePeripheral, nonfinalityConstraint,
+			overtFormsHaveSecondaryStress, includeClashAndLapse, includeCodas);
+	CREATE_ONE_END (GET_STRING (U"Initial ranking"))
+}
 
-FORM (OTMulti_drawTableau_narrowly, U"Draw tableau (narrowly)", U"OT learning") {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	BOOLEAN (U"Show disharmonies", true)
-	OK2
+// MARK: Draw
+
+FORM (GRAPHICS_OTMulti_drawTableau, U"Draw tableau", U"OT learning") {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	BOOLEAN4 (showDisharmonies, U"Show disharmonies", true)
+	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (OTMulti);
-		OTMulti_drawTableau (me, GRAPHICS, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2"),
-			true, GET_INTEGER (U"Show disharmonies"));
-	}
-END2 }
+	GRAPHICS_EACH (OTMulti)
+		OTMulti_drawTableau (me, GRAPHICS, partialForm1, partialForm2, false, showDisharmonies);
+	GRAPHICS_EACH_END
+}
 
-#pragma mark Edit
+FORM (GRAPHICS_OTMulti_drawTableau_narrowly, U"Draw tableau (narrowly)", U"OT learning") {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	BOOLEAN4 (showDisharmonies, U"Show disharmonies", true)
+	OK
+DO
+	GRAPHICS_EACH (OTMulti)
+		OTMulti_drawTableau (me, GRAPHICS, partialForm1, partialForm2, true, showDisharmonies);
+	GRAPHICS_EACH_END
+}
+
+// MARK: View & Edit
 
-DIRECT2 (OTMulti_edit) {
+DIRECT (WINDOW_OTMulti_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot edit an OTMulti from batch.");
 	LOOP {
 		iam (OTMulti);
@@ -1359,480 +1233,429 @@ DIRECT2 (OTMulti_edit) {
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
-
-#pragma mark Query
-
-DIRECT2 (OTMulti_getNumberOfConstraints) {
-	iam_ONLY (OTMulti);
-	Melder_information (my numberOfConstraints);
-END2 }
-
-FORM (OTMulti_getConstraint, U"Get constraint name", nullptr) {
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my constraints [icons]. name);
-END2 }
-
-FORM (OTMulti_getConstraintIndexFromName, U"OTMulti: Get constraint number", nullptr) {
-	SENTENCE (U"Constraint name", U"")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	Melder_information (OTMulti_getConstraintIndexFromName (me, GET_STRING (U"Constraint name")));
-END2 }
-
-FORM (OTMulti_getRankingValue, U"Get ranking value", nullptr) {
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my constraints [icons]. ranking);
-END2 }
-
-FORM (OTMulti_getDisharmony, U"Get disharmony", nullptr) {
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my constraints [icons]. disharmony);
-END2 }
-
-DIRECT2 (OTMulti_getNumberOfCandidates) {
-	iam_ONLY (OTMulti);
-	Melder_information (my numberOfCandidates);
-END2 }
-
-FORM (OTMulti_getCandidate, U"Get candidate", nullptr) {
-	NATURAL (U"Candidate", U"1")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	long icand = GET_INTEGER (U"Candidate");
-	if (icand > my numberOfCandidates)
-		Melder_throw (U"The specified candidate number should not exceed the number of candidates.");
-	Melder_information (my candidates [icand]. string);
-END2 }
-
-FORM (OTMulti_getNumberOfViolations, U"Get number of violations", nullptr) {
-	NATURAL (U"Candidate number", U"1")
-	NATURAL (U"Constraint number", U"1")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	long icand = GET_INTEGER (U"Candidate number");
-	if (icand > my numberOfCandidates)
-		Melder_throw (U"The specified candidate number should not exceed the number of candidates.");
-	long icons = GET_INTEGER (U"Constraint number");
-	if (icons > my numberOfConstraints)
-		Melder_throw (U"The specified constraint number should not exceed the number of constraints.");
-	Melder_information (my candidates [icand]. marks [icons]);
-END2 }
-
-FORM (OTMulti_getWinner, U"OTMulti: Get winner", nullptr) {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	Melder_information (OTMulti_getWinner (me, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2")));
-END2 }
-
-#pragma mark Evaluate
-
-FORM (OTMulti_evaluate, U"OTMulti: Evaluate", nullptr) {
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	OTMulti_newDisharmonies (me, GET_REAL (U"Evaluation noise"));
-	praat_dataChanged (me);
-END2 }
-
-FORM (OTMulti_generateOptimalForm, U"OTMulti: Generate optimal form", nullptr) {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	char32 output [100];
-	OTMulti_generateOptimalForm (me, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2"),
-		output, GET_REAL (U"Evaluation noise"));
-	Melder_information (output);
-	praat_dataChanged (me);
-END2 }
-
-FORM (OTMulti_generateOptimalForms, U"OTMulti: Generate optimal forms", nullptr) {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	NATURAL (U"Number of trials", U"1000")
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	autoStrings thee = OTMulti_generateOptimalForms (me, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2"),
-		GET_INTEGER (U"Number of trials"), GET_REAL (U"Evaluation noise"));
-	praat_new (thee.move(), my name, U"_out");
-	praat_dataChanged (me);
-END2 }
-
-FORM (OTMulti_to_Distribution, U"OTMulti: Compute output distribution", nullptr) {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	NATURAL (U"Number of trials", U"100000")
-	POSITIVE (U"Evaluation noise", U"2.0")
-	OK2
+END }
+
+// MARK: Query
+
+DIRECT (INTEGER_OTMulti_getNumberOfConstraints) {
+	NUMBER_ONE (OTMulti)
+		long result = my numberOfConstraints;
+	NUMBER_ONE_END (U" constraints")
+}
+
+FORM (STRING_OTMulti_getConstraint, U"Get constraint name", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
 DO
-	LOOP {
-		iam (OTMulti);
-		try {
-			autoDistributions thee = OTMulti_to_Distribution (me, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2"),
-				GET_INTEGER (U"Number of trials"), GET_REAL (U"Evaluation noise"));
-			praat_new (thee.move(), my name, U"_out");
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-END2 }
+	STRING_ONE (OTMulti)
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"Your constraint number should not exceed the number of constraints.");
+		const char32 *result = my constraints [constraintNumber]. name;
+	STRING_ONE_END
+}
 
-#pragma mark Modify ranking
+FORM (INTEGER_OTMulti_getConstraintIndexFromName, U"OTMulti: Get constraint number", nullptr) {
+	SENTENCE4 (constraintName, U"Constraint name", U"")
+	OK
+DO
+	NUMBER_ONE (OTMulti)
+		long result = OTMulti_getConstraintIndexFromName (me, constraintName);
+	NUMBER_ONE_END (U" (index of constraint ", constraintName, U")")
+}
 
-FORM (OTMulti_setRanking, U"OTMulti: Set ranking", nullptr) {
-	NATURAL (U"Constraint", U"1")
-	REAL (U"Ranking", U"100.0")
-	REAL (U"Disharmony", U"100.0")
-	OK2
+FORM (REAL_OTMulti_getRankingValue, U"Get ranking value", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
 DO
-	LOOP {
-		iam (OTMulti);
-		OTMulti_setRanking (me, GET_INTEGER (U"Constraint"), GET_REAL (U"Ranking"), GET_REAL (U"Disharmony"));
+	NUMBER_ONE (OTMulti)
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"Your constraint number should not exceed the number of constraints.");
+		double result = my constraints [constraintNumber]. ranking;
+	NUMBER_ONE_END (U" (ranking of constraint ", constraintNumber, U")")
+}
+
+FORM (REAL_OTMulti_getDisharmony, U"Get disharmony", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTMulti)
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"Your constraint number should not exceed the number of constraints.");
+		double result = my constraints [constraintNumber]. disharmony;
+	NUMBER_ONE_END (U" (disharmony of constraint ", constraintNumber, U")")
+}
+
+DIRECT (INTEGER_OTMulti_getNumberOfCandidates) {
+	NUMBER_ONE (OTMulti)
+		long result = my numberOfCandidates;
+	NUMBER_ONE_END (U" candidates")
+}
+
+FORM (STRING_OTMulti_getCandidate, U"Get candidate", nullptr) {
+	NATURAL4 (candidateNumber, U"Candidate number", U"1")
+	OK
+DO
+	STRING_ONE (OTMulti)
+		if (candidateNumber > my numberOfCandidates)
+			Melder_throw (U"Your candidate number should not exceed the number of candidates.");
+		const char32 *result = my candidates [candidateNumber]. string;
+	STRING_ONE_END
+}
+
+FORM (INTEGER_OTMulti_getNumberOfViolations, U"Get number of violations", nullptr) {
+	NATURAL4 (candidateNumber, U"Candidate number", U"1")
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	OK
+DO
+	NUMBER_ONE (OTMulti)
+		if (candidateNumber > my numberOfCandidates)
+			Melder_throw (U"Your candidate number should not exceed the number of candidates.");
+		if (constraintNumber > my numberOfConstraints)
+			Melder_throw (U"Your constraint number should not exceed the number of constraints.");
+		long result = my candidates [candidateNumber]. marks [constraintNumber];
+	NUMBER_ONE_END (U" violations")
+}
+
+FORM (INTEGER_OTMulti_getWinner, U"OTMulti: Get winner", nullptr) {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	OK
+DO
+	NUMBER_ONE (OTMulti)
+		long result = OTMulti_getWinner (me, partialForm1, partialForm2);
+	NUMBER_ONE_END (U" (winner)")
+}
+
+// MARK: Evaluate
+
+FORM (MODIFY_OTMulti_evaluate, U"OTMulti: Evaluate", nullptr) {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
+DO
+	MODIFY_EACH (OTMulti)
+		OTMulti_newDisharmonies (me, evaluationNoise);
+	MODIFY_EACH_END
+}
+
+FORM (STRING_MODIFY_OTMulti_generateOptimalForm, U"OTMulti: Generate optimal form", nullptr) {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
+DO
+	FIND_ONE (OTMulti)
+		char32 output [100];
+		OTMulti_generateOptimalForm (me, partialForm1, partialForm2, output, evaluationNoise);
+		Melder_information (output);
 		praat_dataChanged (me);
-	}
-END2 }
+	END
+}
 
-FORM (OTMulti_resetAllRankings, U"OTMulti: Reset all rankings", nullptr) {
-	REAL (U"Ranking", U"100.0")
-	OK2
+FORM (NEW1_MODIFY_OTMulti_generateOptimalForms, U"OTMulti: Generate optimal forms", nullptr) {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	NATURAL4 (numberOfTrials, U"Number of trials", U"1000")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
 DO
-	LOOP {
-		iam (OTMulti);
-		OTMulti_reset (me, GET_REAL (U"Ranking"));
+	FIND_ONE (OTMulti)
+		autoStrings thee = OTMulti_generateOptimalForms (me, partialForm1, partialForm2,
+			numberOfTrials, evaluationNoise);
+		praat_new (thee.move(), my name, U"_out");
 		praat_dataChanged (me);
-	}
-END2 }
+	END
+}
 
-FORM (OTMulti_learnOne, U"OTMulti: Learn one", nullptr) {
-	SENTENCE (U"Partial form 1", U"")
-	SENTENCE (U"Partial form 2", U"")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	OPTIONMENU (U"Direction", 3)
-		OPTION (U"forward")
-		OPTION (U"backward")
-		OPTION (U"bidirectionally")
-	POSITIVE (U"Plasticity", U"0.1")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	OK2
+FORM (NEW_MODIFY_OTMulti_to_Distribution, U"OTMulti: Compute output distribution", nullptr) {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	NATURAL4 (numberOfTrials, U"Number of trials", U"100000")
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OK
 DO
 	LOOP {
 		iam (OTMulti);
 		try {
-			OTMulti_learnOne (me, GET_STRING (U"Partial form 1"), GET_STRING (U"Partial form 2"),
-				GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-				GET_INTEGER (U"Direction"), GET_REAL (U"Plasticity"), GET_REAL (U"Rel. plasticity spreading"));
+			autoDistributions result = OTMulti_to_Distribution (me, partialForm1, partialForm2,
+				numberOfTrials, evaluationNoise);
+			praat_new (result.move(), my name, U"_out");
 			praat_dataChanged (me);
 		} catch (MelderError) {
 			praat_dataChanged (me);
 			throw;
 		}
 	}
-END2 }
+END }
 
-#pragma mark Modify behaviour
+// MARK: Modify ranking
 
-FORM (OTMulti_setDecisionStrategy, U"OTMulti: Set decision strategy", nullptr) {
-	RADIO_ENUM (U"Decision strategy", kOTGrammar_decisionStrategy, DEFAULT)
-	OK2
-iam_ONLY (OTMulti);
-SET_ENUM (U"Decision strategy", kOTGrammar_decisionStrategy, my decisionStrategy);
+FORM (MODIFY_OTMulti_setRanking, U"OTMulti: Set ranking", nullptr) {
+	NATURAL4 (constraint, U"Constraint", U"1")
+	REAL4 (ranking, U"Ranking", U"100.0")
+	REAL4 (disharmony, U"Disharmony", U"100.0")
+	OK
 DO
-	iam_ONLY (OTMulti);
-	my decisionStrategy = GET_ENUM (kOTGrammar_decisionStrategy, U"Decision strategy");
-	praat_dataChanged (me);
-END2 }
+	MODIFY_EACH (OTMulti)
+		OTMulti_setRanking (me, constraint, ranking, disharmony);
+	MODIFY_EACH_END
+}
 
-FORM (OTMulti_setLeak, U"OTGrammar: Set leak", nullptr) {
-	REAL (U"Leak", U"0.0")
-	OK2
-iam_ONLY (OTMulti);
-SET_REAL (U"Leak", my leak);
+FORM (MODIFY_OTMulti_resetAllRankings, U"OTMulti: Reset all rankings", nullptr) {
+	REAL4 (ranking, U"Ranking", U"100.0")
+	OK
 DO
-	iam_ONLY (OTMulti);
-	my leak = GET_REAL (U"Leak");
-	praat_dataChanged (me);
-END2 }
+	MODIFY_EACH (OTMulti)
+		OTMulti_reset (me, ranking);
+	MODIFY_EACH_END
+}
 
-FORM (OTMulti_setConstraintPlasticity, U"OTMulti: Set constraint plasticity", nullptr) {
-	NATURAL (U"Constraint", U"1")
-	REAL (U"Plasticity", U"1.0")
-	OK2
+FORM (MODIFY_OTMulti_learnOne, U"OTMulti: Learn one", nullptr) {
+	SENTENCE4 (partialForm1, U"Partial form 1", U"")
+	SENTENCE4 (partialForm2, U"Partial form 2", U"")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	OPTIONMENU4 (direction, U"Direction", 3)
+		OPTION (U"forward")
+		OPTION (U"backward")
+		OPTION (U"bidirectionally")
+	POSITIVE4 (plasticity, U"Plasticity", U"0.1")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	OK
+DO
+	MODIFY_EACH_WEAK (OTMulti)
+		OTMulti_learnOne (me, partialForm1, partialForm2, (kOTGrammar_rerankingStrategy) updateRule,
+			direction, plasticity, relativePlasticitySpreading);
+	MODIFY_EACH_WEAK_END
+}
+
+// MARK: Modify behaviour
+
+FORM (MODIFY_OTMulti_setDecisionStrategy, U"OTMulti: Set decision strategy", nullptr) {
+	RADIO_ENUM4 (decisionStrategy, U"Decision strategy", kOTGrammar_decisionStrategy, DEFAULT)
+OK
+	FIND_ONE (OTMulti)
+		SET_ENUM (U"Decision strategy", kOTGrammar_decisionStrategy, my decisionStrategy);
 DO
-	LOOP {
-		iam (OTMulti);
-		OTMulti_setConstraintPlasticity (me, GET_INTEGER (U"Constraint"), GET_REAL (U"Plasticity"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (OTMulti)
+		my decisionStrategy = decisionStrategy;
+	MODIFY_EACH_END
+}
 
-#pragma mark Modify structure
+FORM (MODIFY_OTMulti_setLeak, U"OTGrammar: Set leak", nullptr) {
+	REAL4 (leak, U"Leak", U"0.0")
+OK
+	FIND_ONE (OTMulti)
+		SET_REAL (U"Leak", my leak);
+DO
+	MODIFY_EACH (OTMulti)
+		my leak = leak;
+	MODIFY_EACH_END
+}
 
-FORM (OTMulti_removeConstraint, U"OTMulti: Remove constraint", nullptr) {
-	SENTENCE (U"Constraint name", U"")
-	OK2
+FORM (MODIFY_OTMulti_setConstraintPlasticity, U"OTMulti: Set constraint plasticity", nullptr) {
+	NATURAL4 (constraintNumber, U"Constraint number", U"1")
+	REAL4 (plasticity, U"Plasticity", U"1.0")
+	OK
 DO
-	LOOP {
-		iam (OTMulti);
-		OTMulti_removeConstraint (me, GET_STRING (U"Constraint name"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (OTMulti)
+		OTMulti_setConstraintPlasticity (me, constraintNumber, plasticity);
+	MODIFY_EACH_END
+}
 
-#pragma mark OTMULTI & PAIRDISTRIBUTION
+// MARK: Modify structure
 
-FORM (OTMulti_PairDistribution_learn, U"OTMulti & PairDistribution: Learn", nullptr) {
-	REAL (U"Evaluation noise", U"2.0")
-	OPTIONMENU_ENUM (U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
-	OPTIONMENU (U"Direction", 3)
+FORM (MODIFY_OTMulti_removeConstraint, U"OTMulti: Remove constraint", nullptr) {
+	SENTENCE4 (constraintName, U"Constraint name", U"")
+	OK
+DO
+	MODIFY_EACH (OTMulti)
+		OTMulti_removeConstraint (me, constraintName);
+	MODIFY_EACH_END
+}
+
+// MARK: OTMULTI & PAIRDISTRIBUTION
+
+FORM (DANGEROUS_MODIFY_OTMulti_PairDistribution_learn, U"OTMulti & PairDistribution: Learn", nullptr) {
+	REAL4 (evaluationNoise, U"Evaluation noise", U"2.0")
+	OPTIONMENU_ENUM4 (updateRule, U"Update rule", kOTGrammar_rerankingStrategy, SYMMETRIC_ALL)
+	OPTIONMENU4 (direction, U"Direction", 3)
 		OPTION (U"forward")
 		OPTION (U"backward")
 		OPTION (U"bidirectionally")
-	POSITIVE (U"Initial plasticity", U"1.0")
-	NATURAL (U"Replications per plasticity", U"100000")
-	REAL (U"Plasticity decrement", U"0.1")
-	NATURAL (U"Number of plasticities", U"4")
-	REAL (U"Rel. plasticity spreading", U"0.1")
-	INTEGER (U"Store history every", U"0")
-	OK2
-DO
-	iam_ONLY (OTMulti);
-	thouart_ONLY (PairDistribution);
-	autoTable history;
-	try {
-		OTMulti_PairDistribution_learn (me, thee,
-			GET_REAL (U"Evaluation noise"),
-			GET_ENUM (kOTGrammar_rerankingStrategy, U"Update rule"),
-			GET_INTEGER (U"Direction"),
-			GET_REAL (U"Initial plasticity"), GET_INTEGER (U"Replications per plasticity"),
-			GET_REAL (U"Plasticity decrement"), GET_INTEGER (U"Number of plasticities"),
-			GET_REAL (U"Rel. plasticity spreading"),
-			GET_INTEGER (U"Store history every"), & history);
-		praat_dataChanged (me);
-	} catch (MelderError) {
-		praat_dataChanged (me);   // e.g. in case of partial learning
-		Melder_flushError ();
-		// trickle down to save history
-	}
-	if (history) praat_new (history.move(), my name);
-END2 }
+	POSITIVE4 (initialPlasticity, U"Initial plasticity", U"1.0")
+	NATURAL4 (replicationsPerPlasticity, U"Replications per plasticity", U"100000")
+	REAL4 (plasticityDecrement, U"Plasticity decrement", U"0.1")
+	NATURAL4 (numberOfPlasticities, U"Number of plasticities", U"4")
+	REAL4 (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
+	INTEGER4 (storeHistoryEvery, U"Store history every", U"0")
+	OK
+DO
+	FIND_TWO (OTMulti, PairDistribution)
+		autoTable history;
+		try {
+			OTMulti_PairDistribution_learn (me, you, evaluationNoise,
+				(kOTGrammar_rerankingStrategy) updateRule, direction,
+				initialPlasticity, replicationsPerPlasticity, plasticityDecrement, numberOfPlasticities,
+				relativePlasticitySpreading, storeHistoryEvery, & history);
+			praat_dataChanged (me);
+		} catch (MelderError) {
+			praat_dataChanged (me);   // e.g. in case of partial learning
+			Melder_flushError ();
+			// trickle down to save history
+		}
+		if (history) praat_new (history.move(), my name);
+	END
+}
 
-#pragma mark OTMULTI & STRINGS
+// MARK: OTMULTI & STRINGS
 
-FORM (OTMulti_Strings_generateOptimalForms, U"OTGrammar: Inputs to outputs", U"OTGrammar: Inputs to outputs...") {
-	REAL (U"Evaluation noise", U"2.0")
-	OK2
+FORM (NEW1_MODIFY_OTMulti_Strings_generateOptimalForms, U"OTGrammar: Inputs to outputs", U"OTGrammar: Inputs to outputs...") {
+	REAL4 (evaluationNoide, U"Evaluation noise", U"2.0")
+	OK
 DO
-	iam_ONLY (OTMulti);
-	thouart_ONLY (Strings);
-	autoStrings him = OTMulti_Strings_generateOptimalForms (me, thee, GET_REAL (U"Evaluation noise"));
-	praat_new (him.move(), my name, U"_out");
-	praat_dataChanged (me);
-END2 }
+	FIND_TWO (OTMulti, Strings)
+		autoStrings result = OTMulti_Strings_generateOptimalForms (me, you, evaluationNoide);
+		praat_new (result.move(), my name, U"_out");
+		praat_dataChanged (me);
+	END
+}
 
-#pragma mark -
-#pragma mark RBM
+// MARK: - RBM
 
-#pragma mark New
+// MARK: New
 
-FORM (Create_RBM, U"Create RBM (Restricted Boltzmann Machine)", nullptr) {
-	WORD (U"Name", U"network")
-	NATURAL (U"Number of input nodes", U"50")
-	NATURAL (U"Number of output nodes", U"20")
-	BOOLEAN (U"Inputs are binary", true)
-	OK2
+FORM (NEW1_Create_RBM, U"Create RBM (Restricted Boltzmann Machine)", nullptr) {
+	WORD4 (name, U"Name", U"network")
+	NATURAL4 (numberOfInputNodes, U"Number of input nodes", U"50")
+	NATURAL4 (numberOfOutputNodes, U"Number of output nodes", U"20")
+	BOOLEAN4 (inputsAreBinary, U"Inputs are binary", true)
+	OK
 DO
-	autoRBM me = RBM_create (
-		GET_INTEGER (U"Number of input nodes"),
-		GET_INTEGER (U"Number of output nodes"),
-		GET_INTEGER (U"Inputs are binary"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
+	CREATE_ONE
+		autoRBM result = RBM_create (numberOfInputNodes, numberOfOutputNodes, inputsAreBinary);
+	CREATE_ONE_END (name)
+}
 
-#pragma mark Modify
+// MARK: Modify
 
-DIRECT2 (RBM_spreadUp) {
-	LOOP {
-		iam_LOOP (RBM);
+DIRECT (MODIFY_RBM_spreadUp) {
+	MODIFY_EACH (RBM)
 		RBM_spreadUp (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (RBM_spreadDown) {
-	LOOP {
-		iam_LOOP (RBM);
+DIRECT (MODIFY_RBM_spreadDown) {
+	MODIFY_EACH (RBM)
 		RBM_spreadDown (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (RBM_spreadUp_reconstruction) {
-	LOOP {
-		iam_LOOP (RBM);
+DIRECT (MODIFY_RBM_spreadUp_reconstruction) {
+	MODIFY_EACH (RBM)
 		RBM_spreadUp_reconstruction (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (RBM_spreadDown_reconstruction) {
-	LOOP {
-		iam_LOOP (RBM);
+DIRECT (MODIFY_RBM_spreadDown_reconstruction) {
+	MODIFY_EACH (RBM)
 		RBM_spreadDown_reconstruction (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (RBM_sampleInput) {
-	LOOP {
-		iam_LOOP (RBM);
+DIRECT (MODIFY_RBM_sampleInput) {
+	MODIFY_EACH (RBM)
 		RBM_sampleInput (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (RBM_sampleOutput) {
-	LOOP {
-		iam_LOOP (RBM);
+DIRECT (MODIFY_RBM_sampleOutput) {
+	MODIFY_EACH (RBM)
 		RBM_sampleOutput (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-FORM (RBM_update, U"RBM: Update", nullptr) {
-	POSITIVE (U"Learning rate", U"0.001")
-	OK2
+FORM (MODIFY_RBM_update, U"RBM: Update", nullptr) {
+	POSITIVE4 (learningRate, U"Learning rate", U"0.001")
+	OK
 DO
-	LOOP {
-		iam_LOOP (RBM);
-		RBM_update (me, GET_REAL (U"Learning rate"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (RBM)
+		RBM_update (me, learningRate);
+	MODIFY_EACH_END
+}
 
-#pragma mark Extract
+// MARK: Extract
 
-DIRECT2 (RBM_extractInputActivities) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractInputActivities (me);
-		praat_new (thee.move(), my name, U"_inputActivities");
-	}
-END2 }
+DIRECT (NEW_RBM_extractInputActivities) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractInputActivities (me);
+	CONVERT_EACH_END (my name, U"_inputActivities")
+}
 
-DIRECT2 (RBM_extractOutputActivities) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractOutputActivities (me);
-		praat_new (thee.move(), my name, U"_outputActivities");
-	}
-END2 }
+DIRECT (NEW_RBM_extractOutputActivities) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractOutputActivities (me);
+	CONVERT_EACH_END (my name, U"_outputActivities")
+}
 
-DIRECT2 (RBM_extractInputReconstruction) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractInputReconstruction (me);
-		praat_new (thee.move(), my name, U"_inputReconstruction");
-	}
-END2 }
+DIRECT (NEW_RBM_extractInputReconstruction) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractInputReconstruction (me);
+	CONVERT_EACH_END (my name, U"_inputReconstruction")
+}
 
-DIRECT2 (RBM_extractOutputReconstruction) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractOutputReconstruction (me);
-		praat_new (thee.move(), my name, U"_outputReconstruction");
-	}
-END2 }
+DIRECT (NEW_RBM_extractOutputReconstruction) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractOutputReconstruction (me);
+	CONVERT_EACH_END (my name, U"_outputReconstruction")
+}
 
-DIRECT2 (RBM_extractInputBiases) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractInputBiases (me);
-		praat_new (thee.move(), my name, U"_inputBiases");
-	}
-END2 }
+DIRECT (NEW_RBM_extractInputBiases) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractInputBiases (me);
+	CONVERT_EACH_END (my name, U"_inputBiases")
+}
 
-DIRECT2 (RBM_extractOutputBiases) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractOutputBiases (me);
-		praat_new (thee.move(), my name, U"_outputBiases");
-	}
-END2 }
+DIRECT (NEW_RBM_extractOutputBiases) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractOutputBiases (me);
+	CONVERT_EACH_END (my name, U"_outputBiases")
+}
 
-DIRECT2 (RBM_extractWeights) {
-	LOOP {
-		iam_LOOP (RBM);
-		autoMatrix thee = RBM_extractWeights (me);
-		praat_new (thee.move(), my name, U"_weights");
-	}
-END2 }
+DIRECT (NEW_RBM_extractWeights) {
+	CONVERT_EACH (RBM)
+		autoMatrix result = RBM_extractWeights (me);
+	CONVERT_EACH_END (my name, U"_weights")
+}
 
-#pragma mark RBM & PATTERN
+// MARK: - RBM & PATTERN
 
-FORM (RBM_PatternList_applyToInput, U"RBM & PatternList: Apply to input", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
+FORM (MODIFY_RBM_PatternList_applyToInput, U"RBM & PatternList: Apply to input", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
 DO
-	iam_ONLY (RBM);
-	thouart_ONLY (PatternList);
-	RBM_PatternList_applyToInput (me, thee, GET_INTEGER (U"Row number"));
-	praat_dataChanged (me);
-END2 }
+	MODIFY_FIRST_OF_TWO (RBM, PatternList)
+		RBM_PatternList_applyToInput (me, you, rowNumber);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (RBM_PatternList_applyToOutput, U"RBM & PatternList: Apply to output", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
+FORM (MODIFY_RBM_PatternList_applyToOutput, U"RBM & PatternList: Apply to output", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
 DO
-	iam_ONLY (RBM);
-	thouart_ONLY (PatternList);
-	RBM_PatternList_applyToOutput (me, thee, GET_INTEGER (U"Row number"));
-	praat_dataChanged (me);
-END2 }
+	MODIFY_FIRST_OF_TWO (RBM, PatternList)
+		RBM_PatternList_applyToOutput (me, you, rowNumber);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-FORM (RBM_PatternList_learn, U"RBM & PatternList: Learn", nullptr) {
-	POSITIVE (U"Learning rate", U"0.001")
-	OK2
+FORM (MODIFY_RBM_PatternList_learn, U"RBM & PatternList: Learn", nullptr) {
+	POSITIVE4 (learningRate, U"Learning rate", U"0.001")
+	OK
 DO
-	iam_ONLY (RBM);
-	thouart_ONLY (PatternList);
-	RBM_PatternList_learn (me, thee, GET_REAL (U"Learning rate"));
-	praat_dataChanged (me);
-END2 }
+	MODIFY_FIRST_OF_TWO (RBM, PatternList)
+		RBM_PatternList_learn (me, you, learningRate);
+	MODIFY_FIRST_OF_TWO_END
+}
 
-#pragma mark -
-#pragma mark buttons
+// MARK: - buttons
 
 void praat_uvafon_gram_init ();
 void praat_uvafon_gram_init () {
@@ -1843,174 +1666,174 @@ void praat_uvafon_gram_init () {
 	Thing_recognizeClassByOtherName (classOTGrammar, U"OTCase");
 
 	praat_addMenuCommand (U"Objects", U"New", U"Constraint grammars", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"OT learning tutorial", nullptr, 1, DO_OT_learning_tutorial);
+		praat_addMenuCommand (U"Objects", U"New", U"OT learning tutorial", nullptr, praat_DEPTH_1 | praat_NO_API, HELP_OT_learning_tutorial);
 		praat_addMenuCommand (U"Objects", U"New", U"-- tableau grammars --", nullptr, 1, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create NoCoda grammar", nullptr, 1, DO_Create_NoCoda_grammar);
-		praat_addMenuCommand (U"Objects", U"New", U"Create place assimilation grammar", nullptr, 1, DO_Create_NPA_grammar);
-		praat_addMenuCommand (U"Objects", U"New", U"Create place assimilation distribution", nullptr, 1, DO_Create_NPA_distribution);
-		praat_addMenuCommand (U"Objects", U"New", U"Create tongue-root grammar...", nullptr, 1, DO_Create_tongue_root_grammar);
-		praat_addMenuCommand (U"Objects", U"New", U"Create metrics grammar...", nullptr, 1, DO_Create_metrics_grammar);
-		praat_addMenuCommand (U"Objects", U"New", U"Create multi-level metrics grammar...", nullptr, 1, DO_Create_multi_level_metrics_grammar);
-	praat_addAction1 (classOTGrammar, 1, U"Save as headerless spreadsheet file...", nullptr, 0, DO_OTGrammar_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (classOTGrammar, 1, U"Write to headerless spreadsheet file...", nullptr, praat_HIDDEN, DO_OTGrammar_writeToHeaderlessSpreadsheetFile);
-
-	praat_addAction1 (classOTGrammar, 0, U"OTGrammar help", nullptr, 0, DO_OTGrammar_help);
-	praat_addAction1 (classOTGrammar, 0, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_OTGrammar_edit);
-	praat_addAction1 (classOTGrammar, 0, U"Edit", nullptr, praat_HIDDEN, DO_OTGrammar_edit);
+		praat_addMenuCommand (U"Objects", U"New", U"Create NoCoda grammar", nullptr, 1, NEW1_Create_NoCoda_grammar);
+		praat_addMenuCommand (U"Objects", U"New", U"Create place assimilation grammar", nullptr, 1, NEW1_Create_NPA_grammar);
+		praat_addMenuCommand (U"Objects", U"New", U"Create place assimilation distribution", nullptr, 1, NEW1_Create_NPA_distribution);
+		praat_addMenuCommand (U"Objects", U"New", U"Create tongue-root grammar...", nullptr, 1, NEW1_Create_tongue_root_grammar);
+		praat_addMenuCommand (U"Objects", U"New", U"Create metrics grammar...", nullptr, 1, NEW1_Create_metrics_grammar);
+		praat_addMenuCommand (U"Objects", U"New", U"Create multi-level metrics grammar...", nullptr, 1, NEW1_Create_multi_level_metrics_grammar);
+	praat_addAction1 (classOTGrammar, 1, U"Save as headerless spreadsheet file...", nullptr, 0, SAVE_OTGrammar_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (classOTGrammar, 1,   U"Write to headerless spreadsheet file...", U"*Save as headerless spreadsheet file...", praat_DEPRECATED_2011, SAVE_OTGrammar_writeToHeaderlessSpreadsheetFile);
+
+	praat_addAction1 (classOTGrammar, 0, U"OTGrammar help", nullptr, 0, HELP_OTGrammar_help);
+	praat_addAction1 (classOTGrammar, 0, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_OTGrammar_viewAndEdit);
+	praat_addAction1 (classOTGrammar, 0,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_OTGrammar_viewAndEdit);
 	praat_addAction1 (classOTGrammar, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTGrammar, 0, U"Draw tableau...", nullptr, 0, DO_OTGrammar_drawTableau);
-		praat_addAction1 (classOTGrammar, 0, U"Draw tableau (narrowly)...", nullptr, 0, DO_OTGrammar_drawTableau_narrowly);
+		praat_addAction1 (classOTGrammar, 0, U"Draw tableau...", nullptr, 0, GRAPHICS_OTGrammar_drawTableau);
+		praat_addAction1 (classOTGrammar, 0, U"Draw tableau (narrowly)...", nullptr, 0, GRAPHICS_OTGrammar_drawTableau_narrowly);
 	praat_addAction1 (classOTGrammar, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTGrammar, 1, U"Get number of constraints", nullptr, 1, DO_OTGrammar_getNumberOfConstraints);
-		praat_addAction1 (classOTGrammar, 1, U"Get constraint...", nullptr, 1, DO_OTGrammar_getConstraint);
-		praat_addAction1 (classOTGrammar, 1, U"Get ranking value...", nullptr, 1, DO_OTGrammar_getRankingValue);
-		praat_addAction1 (classOTGrammar, 1, U"Get disharmony...", nullptr, 1, DO_OTGrammar_getDisharmony);
-		praat_addAction1 (classOTGrammar, 1, U"Get number of tableaus", nullptr, 1, DO_OTGrammar_getNumberOfTableaus);
-		praat_addAction1 (classOTGrammar, 1, U"Get input...", nullptr, 1, DO_OTGrammar_getInput);
-		praat_addAction1 (classOTGrammar, 1, U"Get number of candidates...", nullptr, 1, DO_OTGrammar_getNumberOfCandidates);
-		praat_addAction1 (classOTGrammar, 1, U"Get candidate...", nullptr, 1, DO_OTGrammar_getCandidate);
-		praat_addAction1 (classOTGrammar, 1, U"Get number of violations...", nullptr, 1, DO_OTGrammar_getNumberOfViolations);
+		praat_addAction1 (classOTGrammar, 1, U"Get number of constraints", nullptr, 1, INTEGER_OTGrammar_getNumberOfConstraints);
+		praat_addAction1 (classOTGrammar, 1, U"Get constraint...", nullptr, 1, STRING_OTGrammar_getConstraint);
+		praat_addAction1 (classOTGrammar, 1, U"Get ranking value...", nullptr, 1, REAL_OTGrammar_getRankingValue);
+		praat_addAction1 (classOTGrammar, 1, U"Get disharmony...", nullptr, 1, REAL_OTGrammar_getDisharmony);
+		praat_addAction1 (classOTGrammar, 1, U"Get number of tableaus", nullptr, 1, INTEGER_OTGrammar_getNumberOfTableaus);
+		praat_addAction1 (classOTGrammar, 1, U"Get input...", nullptr, 1, STRING_OTGrammar_getInput);
+		praat_addAction1 (classOTGrammar, 1, U"Get number of candidates...", nullptr, 1, INTEGER_OTGrammar_getNumberOfCandidates);
+		praat_addAction1 (classOTGrammar, 1, U"Get candidate...", nullptr, 1, STRING_OTGrammar_getCandidate);
+		praat_addAction1 (classOTGrammar, 1, U"Get number of violations...", nullptr, 1, INTEGER_OTGrammar_getNumberOfViolations);
 		praat_addAction1 (classOTGrammar, 1, U"-- parse --", nullptr, 1, nullptr);
-		praat_addAction1 (classOTGrammar, 1, U"Get winner...", nullptr, 1, DO_OTGrammar_getWinner);
-		praat_addAction1 (classOTGrammar, 1, U"Compare candidates...", nullptr, 1, DO_OTGrammar_compareCandidates);
-		praat_addAction1 (classOTGrammar, 1, U"Get number of optimal candidates...", nullptr, 1, DO_OTGrammar_getNumberOfOptimalCandidates);
-		praat_addAction1 (classOTGrammar, 1, U"Is candidate grammatical...", nullptr, 1, DO_OTGrammar_isCandidateGrammatical);
-		praat_addAction1 (classOTGrammar, 1, U"Is candidate singly grammatical...", nullptr, 1, DO_OTGrammar_isCandidateSinglyGrammatical);
-		praat_addAction1 (classOTGrammar, 1, U"Get interpretive parse...", nullptr, 1, DO_OTGrammar_getInterpretiveParse);
-		praat_addAction1 (classOTGrammar, 1, U"Is partial output grammatical...", nullptr, 1, DO_OTGrammar_isPartialOutputGrammatical);
-		praat_addAction1 (classOTGrammar, 1, U"Is partial output singly grammatical...", nullptr, 1, DO_OTGrammar_isPartialOutputSinglyGrammatical);
-	praat_addAction1 (classOTGrammar, 0, U"Generate inputs...", nullptr, 0, DO_OTGrammar_generateInputs);
-	praat_addAction1 (classOTGrammar, 0, U"Get inputs", nullptr, 0, DO_OTGrammar_getInputs);
-	praat_addAction1 (classOTGrammar, 0, U"Measure typology", nullptr, 0, DO_OTGrammar_measureTypology);
+		praat_addAction1 (classOTGrammar, 1, U"Get winner...", nullptr, 1, INTEGER_OTGrammar_getWinner);
+		praat_addAction1 (classOTGrammar, 1, U"Compare candidates...", nullptr, 1, INTEGER_OTGrammar_compareCandidates);
+		praat_addAction1 (classOTGrammar, 1, U"Get number of optimal candidates...", nullptr, 1, INTEGER_OTGrammar_getNumberOfOptimalCandidates);
+		praat_addAction1 (classOTGrammar, 1, U"Is candidate grammatical...", nullptr, 1, BOOLEAN_OTGrammar_isCandidateGrammatical);
+		praat_addAction1 (classOTGrammar, 1, U"Is candidate singly grammatical...", nullptr, 1, BOOLEAN_OTGrammar_isCandidateSinglyGrammatical);
+		praat_addAction1 (classOTGrammar, 1, U"Get interpretive parse...", nullptr, 1, STRING_OTGrammar_getInterpretiveParse);
+		praat_addAction1 (classOTGrammar, 1, U"Is partial output grammatical...", nullptr, 1, BOOLEAN_OTGrammar_isPartialOutputGrammatical);
+		praat_addAction1 (classOTGrammar, 1, U"Is partial output singly grammatical...", nullptr, 1, BOOLEAN_OTGrammar_isPartialOutputSinglyGrammatical);
+	praat_addAction1 (classOTGrammar, 0, U"Generate inputs...", nullptr, 0, NEW_OTGrammar_generateInputs);
+	praat_addAction1 (classOTGrammar, 0, U"Get inputs", nullptr, 0, NEW_OTGrammar_getInputs);
+	praat_addAction1 (classOTGrammar, 0, U"Measure typology", nullptr, 0, NEW_MODIFY_OTGrammar_measureTypology);
 	praat_addAction1 (classOTGrammar, 0, U"Evaluate", nullptr, 0, nullptr);
-		praat_addAction1 (classOTGrammar, 0, U"Evaluate...", nullptr, 0, DO_OTGrammar_evaluate);
-		praat_addAction1 (classOTGrammar, 0, U"Input to output...", nullptr, 0, DO_OTGrammar_inputToOutput);
-		praat_addAction1 (classOTGrammar, 0, U"Input to outputs...", nullptr, 0, DO_OTGrammar_inputToOutputs);
-		praat_addAction1 (classOTGrammar, 0, U"To output Distributions...", nullptr, 0, DO_OTGrammar_to_Distributions);
-		praat_addAction1 (classOTGrammar, 0, U"To PairDistribution...", nullptr, 0, DO_OTGrammar_to_PairDistribution);
+		praat_addAction1 (classOTGrammar, 0, U"Evaluate...", nullptr, 0, MODIFY_OTGrammar_evaluate);
+		praat_addAction1 (classOTGrammar, 0, U"Input to output...", nullptr, 0, STRING_MODIFY_OTGrammar_inputToOutput);
+		praat_addAction1 (classOTGrammar, 0, U"Input to outputs...", nullptr, 0, NEW1_MODIFY_OTGrammar_inputToOutputs);
+		praat_addAction1 (classOTGrammar, 0, U"To output Distributions...", nullptr, 0, NEW_MODIFY_OTGrammar_to_Distributions);
+		praat_addAction1 (classOTGrammar, 0, U"To PairDistribution...", nullptr, 0, NEW_MODIFY_OTGrammar_to_PairDistribution);
 	praat_addAction1 (classOTGrammar, 0, U"Modify ranking -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTGrammar, 0, U"Set ranking...", nullptr, 1, DO_OTGrammar_setRanking);
-		praat_addAction1 (classOTGrammar, 0, U"Reset all rankings...", nullptr, 1, DO_OTGrammar_resetAllRankings);
-		praat_addAction1 (classOTGrammar, 0, U"Reset to random ranking...", nullptr, 1, DO_OTGrammar_resetToRandomRanking);
-		praat_addAction1 (classOTGrammar, 0, U"Reset to random total ranking...", nullptr, 1, DO_OTGrammar_resetToRandomTotalRanking);
-		praat_addAction1 (classOTGrammar, 0, U"Learn one...", nullptr, 1, DO_OTGrammar_learnOne);
-		praat_addAction1 (classOTGrammar, 0, U"Learn one from partial output...", nullptr, 1, DO_OTGrammar_learnOneFromPartialOutput);
+		praat_addAction1 (classOTGrammar, 0, U"Set ranking...", nullptr, 1, MODIFY_OTGrammar_setRanking);
+		praat_addAction1 (classOTGrammar, 0, U"Reset all rankings...", nullptr, 1, MODIFY_OTGrammar_resetAllRankings);
+		praat_addAction1 (classOTGrammar, 0, U"Reset to random ranking...", nullptr, 1, MODIFY_OTGrammar_resetToRandomRanking);
+		praat_addAction1 (classOTGrammar, 0, U"Reset to random total ranking...", nullptr, 1, MODIFY_OTGrammar_resetToRandomTotalRanking);
+		praat_addAction1 (classOTGrammar, 0, U"Learn one...", nullptr, 1, MODIFY_OTGrammar_learnOne);
+		praat_addAction1 (classOTGrammar, 0, U"Learn one from partial output...", nullptr, 1, MODIFY_OTGrammar_learnOneFromPartialOutput);
 	praat_addAction1 (classOTGrammar, 0, U"Modify behaviour -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTGrammar, 1, U"Set harmony computation method...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_OTGrammar_setDecisionStrategy);
-		praat_addAction1 (classOTGrammar, 1, U"Set decision strategy...", nullptr, 1, DO_OTGrammar_setDecisionStrategy);
-		praat_addAction1 (classOTGrammar, 1, U"Set leak...", nullptr, 1, DO_OTGrammar_setLeak);
-		praat_addAction1 (classOTGrammar, 1, U"Set constraint plasticity...", nullptr, 1, DO_OTGrammar_setConstraintPlasticity);
+		praat_addAction1 (classOTGrammar, 1, U"Set decision strategy...", nullptr, 1, MODIFY_OTGrammar_setDecisionStrategy);
+		praat_addAction1 (classOTGrammar, 1,   U"Set harmony computation method...", U"*Set decision strategy...", praat_DEPTH_1 | praat_DEPRECATED_2006, MODIFY_OTGrammar_setDecisionStrategy);
+		praat_addAction1 (classOTGrammar, 1, U"Set leak...", nullptr, 1, MODIFY_OTGrammar_setLeak);
+		praat_addAction1 (classOTGrammar, 1, U"Set constraint plasticity...", nullptr, 1, MODIFY_OTGrammar_setConstraintPlasticity);
 	praat_addAction1 (classOTGrammar, 0, U"Modify structure -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTGrammar, 0, U"Remove constraint...", nullptr, 1, DO_OTGrammar_removeConstraint);
-		praat_addAction1 (classOTGrammar, 0, U"Remove harmonically bounded candidates...", nullptr, 1, DO_OTGrammar_removeHarmonicallyBoundedCandidates);
+		praat_addAction1 (classOTGrammar, 0, U"Remove constraint...", nullptr, 1, MODIFY_OTGrammar_removeConstraint);
+		praat_addAction1 (classOTGrammar, 0, U"Remove harmonically bounded candidates...", nullptr, 1, MODIFY_OTGrammar_removeHarmonicallyBoundedCandidates);
 
-	{ void praat_TableOfReal_init (ClassInfo klas); praat_TableOfReal_init (classOTHistory); }
+	praat_TableOfReal_init (classOTHistory);
 
-	praat_addAction1 (classOTMulti, 0, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_OTMulti_edit);
-	praat_addAction1 (classOTMulti, 0, U"Edit", nullptr, praat_HIDDEN, DO_OTMulti_edit);
+	praat_addAction1 (classOTMulti, 0, U"View & Edit", nullptr, praat_ATTRACTIVE, WINDOW_OTMulti_viewAndEdit);
+	praat_addAction1 (classOTMulti, 0,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011, WINDOW_OTMulti_viewAndEdit);
 	praat_addAction1 (classOTMulti, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTMulti, 0, U"Draw tableau...", nullptr, 1, DO_OTMulti_drawTableau);
-		praat_addAction1 (classOTMulti, 0, U"Draw tableau (narrowly)...", nullptr, 1, DO_OTMulti_drawTableau_narrowly);
+		praat_addAction1 (classOTMulti, 0, U"Draw tableau...", nullptr, 1, GRAPHICS_OTMulti_drawTableau);
+		praat_addAction1 (classOTMulti, 0, U"Draw tableau (narrowly)...", nullptr, 1, GRAPHICS_OTMulti_drawTableau_narrowly);
 	praat_addAction1 (classOTMulti, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTMulti, 1, U"Get number of constraints", nullptr, 1, DO_OTMulti_getNumberOfConstraints);
-		praat_addAction1 (classOTMulti, 1, U"Get constraint...", nullptr, 1, DO_OTMulti_getConstraint);
-		praat_addAction1 (classOTMulti, 1, U"Get constraint number...", nullptr, 1, DO_OTMulti_getConstraintIndexFromName);
-		praat_addAction1 (classOTMulti, 1, U"Get ranking value...", nullptr, 1, DO_OTMulti_getRankingValue);
-		praat_addAction1 (classOTMulti, 1, U"Get disharmony...", nullptr, 1, DO_OTMulti_getDisharmony);
-		praat_addAction1 (classOTMulti, 1, U"Get number of candidates", nullptr, 1, DO_OTMulti_getNumberOfCandidates);
-		praat_addAction1 (classOTMulti, 1, U"Get candidate...", nullptr, 1, DO_OTMulti_getCandidate);
-		praat_addAction1 (classOTMulti, 1, U"Get number of violations...", nullptr, 1, DO_OTMulti_getNumberOfViolations);
+		praat_addAction1 (classOTMulti, 1, U"Get number of constraints", nullptr, 1, INTEGER_OTMulti_getNumberOfConstraints);
+		praat_addAction1 (classOTMulti, 1, U"Get constraint...", nullptr, 1, STRING_OTMulti_getConstraint);
+		praat_addAction1 (classOTMulti, 1, U"Get constraint number...", nullptr, 1, INTEGER_OTMulti_getConstraintIndexFromName);
+		praat_addAction1 (classOTMulti, 1, U"Get ranking value...", nullptr, 1, REAL_OTMulti_getRankingValue);
+		praat_addAction1 (classOTMulti, 1, U"Get disharmony...", nullptr, 1, REAL_OTMulti_getDisharmony);
+		praat_addAction1 (classOTMulti, 1, U"Get number of candidates", nullptr, 1, INTEGER_OTMulti_getNumberOfCandidates);
+		praat_addAction1 (classOTMulti, 1, U"Get candidate...", nullptr, 1, STRING_OTMulti_getCandidate);
+		praat_addAction1 (classOTMulti, 1, U"Get number of violations...", nullptr, 1, INTEGER_OTMulti_getNumberOfViolations);
 		praat_addAction1 (classOTMulti, 1, U"-- parse --", nullptr, 1, nullptr);
-		praat_addAction1 (classOTMulti, 1, U"Get winner...", nullptr, 1, DO_OTMulti_getWinner);
+		praat_addAction1 (classOTMulti, 1, U"Get winner...", nullptr, 1, INTEGER_OTMulti_getWinner);
 	praat_addAction1 (classOTMulti, 0, U"Evaluate", nullptr, 0, nullptr);
-		praat_addAction1 (classOTMulti, 0, U"Evaluate...", nullptr, 1, DO_OTMulti_evaluate);
-		praat_addAction1 (classOTMulti, 0, U"Get output...", nullptr, 1, DO_OTMulti_generateOptimalForm);
-		praat_addAction1 (classOTMulti, 0, U"Get outputs...", nullptr, 1, DO_OTMulti_generateOptimalForms);
-		praat_addAction1 (classOTMulti, 0, U"To output Distribution...", nullptr, 1, DO_OTMulti_to_Distribution);
+		praat_addAction1 (classOTMulti, 0, U"Evaluate...", nullptr, 1, MODIFY_OTMulti_evaluate);
+		praat_addAction1 (classOTMulti, 0, U"Get output...", nullptr, 1, STRING_MODIFY_OTMulti_generateOptimalForm);
+		praat_addAction1 (classOTMulti, 0, U"Get outputs...", nullptr, 1, NEW1_MODIFY_OTMulti_generateOptimalForms);
+		praat_addAction1 (classOTMulti, 0, U"To output Distribution...", nullptr, 1, NEW_MODIFY_OTMulti_to_Distribution);
 	praat_addAction1 (classOTMulti, 0, U"Modify ranking", nullptr, 0, nullptr);
-		praat_addAction1 (classOTMulti, 0, U"Set ranking...", nullptr, 0, DO_OTMulti_setRanking);
-		praat_addAction1 (classOTMulti, 0, U"Reset all rankings...", nullptr, 0, DO_OTMulti_resetAllRankings);
-		praat_addAction1 (classOTMulti, 0, U"Learn one...", nullptr, 0, DO_OTMulti_learnOne);
+		praat_addAction1 (classOTMulti, 0, U"Set ranking...", nullptr, 0, MODIFY_OTMulti_setRanking);
+		praat_addAction1 (classOTMulti, 0, U"Reset all rankings...", nullptr, 0, MODIFY_OTMulti_resetAllRankings);
+		praat_addAction1 (classOTMulti, 0, U"Learn one...", nullptr, 0, MODIFY_OTMulti_learnOne);
 	praat_addAction1 (classOTMulti, 0, U"Modify behaviour -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTMulti, 1, U"Set decision strategy...", nullptr, 1, DO_OTMulti_setDecisionStrategy);
-		praat_addAction1 (classOTMulti, 1, U"Set leak...", nullptr, 1, DO_OTMulti_setLeak);
-		praat_addAction1 (classOTMulti, 1, U"Set constraint plasticity...", nullptr, 1, DO_OTMulti_setConstraintPlasticity);
+		praat_addAction1 (classOTMulti, 1, U"Set decision strategy...", nullptr, 1, MODIFY_OTMulti_setDecisionStrategy);
+		praat_addAction1 (classOTMulti, 1, U"Set leak...", nullptr, 1, MODIFY_OTMulti_setLeak);
+		praat_addAction1 (classOTMulti, 1, U"Set constraint plasticity...", nullptr, 1, MODIFY_OTMulti_setConstraintPlasticity);
 	praat_addAction1 (classOTMulti, 0, U"Modify structure -", nullptr, 0, nullptr);
-		praat_addAction1 (classOTMulti, 0, U"Remove constraint...", nullptr, 1, DO_OTMulti_removeConstraint);
+		praat_addAction1 (classOTMulti, 0, U"Remove constraint...", nullptr, 1, MODIFY_OTMulti_removeConstraint);
 
 	praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Query -", nullptr, 0, nullptr);
-		praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Are all partial outputs grammatical?", nullptr, 1, DO_OTGrammar_Strings_areAllPartialOutputsGrammatical);
-		praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Are all partial outputs singly grammatical?", nullptr, 1, DO_OTGrammar_Strings_areAllPartialOutputsSinglyGrammatical);
-	praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Inputs to outputs...", nullptr, 0, DO_OTGrammar_Strings_inputsToOutputs);
-	praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Learn from partial outputs...", nullptr, 0, DO_OTGrammar_Strings_learnFromPartialOutputs);
-	praat_addAction2 (classOTGrammar, 1, classStrings, 2, U"Learn...", nullptr, 0, DO_OTGrammar_Stringses_learn);
-	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs...", nullptr, 0, DO_OTGrammar_Distributions_learnFromPartialOutputs);
-	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs (rrip)...", nullptr, 0, DO_OTGrammar_Distributions_learnFromPartialOutputs_rrip);
-	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs (eip)...", nullptr, 0, DO_OTGrammar_Distributions_learnFromPartialOutputs_eip);
-	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs (wrip)...", nullptr, 0, DO_OTGrammar_Distributions_learnFromPartialOutputs_wrip);
-	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Get fraction correct...", nullptr, 0, DO_OTGrammar_Distributions_getFractionCorrect);
-	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"List obligatory rankings...", nullptr, praat_HIDDEN, DO_OTGrammar_Distributions_listObligatoryRankings);
-	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Learn...", nullptr, 0, DO_OTGrammar_PairDistribution_learn);
-	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Find positive weights...", nullptr, 0, DO_OTGrammar_PairDistribution_findPositiveWeights);
-	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Get fraction correct...", nullptr, 0, DO_OTGrammar_PairDistribution_getFractionCorrect);
-	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Get minimum number correct...", nullptr, 0, DO_OTGrammar_PairDistribution_getMinimumNumberCorrect);
-	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"List obligatory rankings", nullptr, 0, DO_OTGrammar_PairDistribution_listObligatoryRankings);
-	praat_addAction2 (classOTMulti, 1, classPairDistribution, 1, U"Learn...", nullptr, 0, DO_OTMulti_PairDistribution_learn);
-	praat_addAction2 (classOTMulti, 1, classStrings, 1, U"Get outputs...", nullptr, 0, DO_OTMulti_Strings_generateOptimalForms);
+		praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Are all partial outputs grammatical?", nullptr, 1, BOOLEAN_OTGrammar_Strings_areAllPartialOutputsGrammatical);
+		praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Are all partial outputs singly grammatical?", nullptr, 1, BOOLEAN_OTGrammar_Strings_areAllPartialOutputsSinglyGrammatical);
+	praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Inputs to outputs...", nullptr, 0, NEW1_MODIFY_OTGrammar_Strings_inputsToOutputs);
+	praat_addAction2 (classOTGrammar, 1, classStrings, 1, U"Learn from partial outputs...", nullptr, 0, MODIFY_OTGrammar_Strings_learnFromPartialOutputs);
+	praat_addAction2 (classOTGrammar, 1, classStrings, 2, U"Learn...", nullptr, 0, MODIFY_OTGrammar_Stringses_learn);
+	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs...", nullptr, 0, MODIFY_OTGrammar_Distributions_learnFromPartialOutputs);
+	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs (rrip)...", nullptr, 0, MODIFY_OTGrammar_Distributions_learnFromPartialOutputs_rrip);
+	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs (eip)...", nullptr, 0, MODIFY_OTGrammar_Distributions_learnFromPartialOutputs_eip);
+	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Learn from partial outputs (wrip)...", nullptr, 0, MODIFY_OTGrammar_Distributions_learnFromPartialOutputs_wrip);
+	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"Get fraction correct...", nullptr, 0, REAL_MODIFY_OTGrammar_Distributions_getFractionCorrect);
+	praat_addAction2 (classOTGrammar, 1, classDistributions, 1, U"List obligatory rankings...", nullptr, praat_HIDDEN, LIST_OTGrammar_Distributions_listObligatoryRankings);
+	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Learn...", nullptr, 0, MODIFY_OTGrammar_PairDistribution_learn);
+	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Find positive weights...", nullptr, 0, MODIFY_OTGrammar_PairDistribution_findPositiveWeights);
+	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Get fraction correct...", nullptr, 0, REAL_MODIFY_OTGrammar_PairDistribution_getFractionCorrect);
+	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"Get minimum number correct...", nullptr, 0, INTEGER_MODIFY_OTGrammar_PairDistribution_getMinimumNumberCorrect);
+	praat_addAction2 (classOTGrammar, 1, classPairDistribution, 1, U"List obligatory rankings", nullptr, 0, LIST_OTGrammar_PairDistribution_listObligatoryRankings);
+	praat_addAction2 (classOTMulti, 1, classPairDistribution, 1, U"Learn...", nullptr, 0, DANGEROUS_MODIFY_OTMulti_PairDistribution_learn);
+	praat_addAction2 (classOTMulti, 1, classStrings, 1, U"Get outputs...", nullptr, 0, NEW1_MODIFY_OTMulti_Strings_generateOptimalForms);
 
 	praat_addMenuCommand (U"Objects", U"New", U"Symmetric neural networks", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create empty Network...", nullptr, 1, DO_Create_empty_Network);
-		praat_addMenuCommand (U"Objects", U"New", U"Create rectangular Network...", nullptr, 1, DO_Create_rectangular_Network);
-		praat_addMenuCommand (U"Objects", U"New", U"Create rectangular Network (vertical)...", nullptr, 1, DO_Create_rectangular_Network_vertical);
-		praat_addMenuCommand (U"Objects", U"New", U"Create RBM...", nullptr, 1, DO_Create_RBM);
+		praat_addMenuCommand (U"Objects", U"New", U"Create empty Network...", nullptr, 1, NEW1_Create_empty_Network);
+		praat_addMenuCommand (U"Objects", U"New", U"Create rectangular Network...", nullptr, 1, NEW1_Create_rectangular_Network);
+		praat_addMenuCommand (U"Objects", U"New", U"Create rectangular Network (vertical)...", nullptr, 1, NEW1_Create_rectangular_Network_vertical);
+		praat_addMenuCommand (U"Objects", U"New", U"Create RBM...", nullptr, 1, NEW1_Create_RBM);
 
-	praat_addAction1 (classNetwork, 0, U"Draw...", nullptr, 0, DO_Network_draw);
+	praat_addAction1 (classNetwork, 0, U"Draw...", nullptr, 0, GRAPHICS_Network_draw);
 	praat_addAction1 (classNetwork, 1, U"Tabulate -", nullptr, 0, nullptr);
-		praat_addAction1 (classNetwork, 1, U"List nodes...", nullptr, 1, DO_Network_listNodes);
-		praat_addAction1 (classNetwork, 1, U"Nodes down to table...", nullptr, 1, DO_Network_nodes_downto_Table);
+		praat_addAction1 (classNetwork, 1, U"List nodes...", nullptr, 1, LIST_Network_listNodes);
+		praat_addAction1 (classNetwork, 1, U"Nodes down to table...", nullptr, 1, NEW_Network_nodes_downto_Table);
 	praat_addAction1 (classNetwork, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classNetwork, 1, U"Get activity...", nullptr, 1, DO_Network_getActivity);
-		praat_addAction1 (classNetwork, 1, U"Get weight...", nullptr, 1, DO_Network_getWeight);
+		praat_addAction1 (classNetwork, 1, U"Get activity...", nullptr, 1, REAL_Network_getActivity);
+		praat_addAction1 (classNetwork, 1, U"Get weight...", nullptr, 1, REAL_Network_getWeight);
 	praat_addAction1 (classNetwork, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classNetwork, 0, U"Add node...", nullptr, 1, DO_Network_addNode);
-		praat_addAction1 (classNetwork, 0, U"Add connection...", nullptr, 1, DO_Network_addConnection);
-		praat_addAction1 (classNetwork, 1, U"-- activity --", nullptr, 1, nullptr);
-		praat_addAction1 (classNetwork, 0, U"Set activity...", nullptr, 1, DO_Network_setActivity);
-		praat_addAction1 (classNetwork, 0, U"Set clamping...", nullptr, 1, DO_Network_setClamping);
-		praat_addAction1 (classNetwork, 0, U"Zero activities...", nullptr, 1, DO_Network_zeroActivities);
-		praat_addAction1 (classNetwork, 0, U"Normalize activities...", nullptr, 1, DO_Network_normalizeActivities);
-		praat_addAction1 (classNetwork, 0, U"Spread activities...", nullptr, 1, DO_Network_spreadActivities);
-		praat_addAction1 (classNetwork, 1, U"Set activity clipping rule...", nullptr, 1, DO_Network_setActivityClippingRule);
-		praat_addAction1 (classNetwork, 1, U"Set activity leak...", nullptr, 1, DO_Network_setActivityLeak);
-		praat_addAction1 (classNetwork, 1, U"Set shunting...", nullptr, 1, DO_Network_setShunting);
-		praat_addAction1 (classNetwork, 1, U"-- weight --", nullptr, 1, nullptr);
-		praat_addAction1 (classNetwork, 0, U"Set weight...", nullptr, 1, DO_Network_setWeight);
-		praat_addAction1 (classNetwork, 0, U"Update weights", nullptr, 1, DO_Network_updateWeights);
-		praat_addAction1 (classNetwork, 0, U"Normalize weights...", nullptr, 1, DO_Network_normalizeWeights);
-		praat_addAction1 (classNetwork, 1, U"Set instar...", nullptr, 1, DO_Network_setInstar);
-		praat_addAction1 (classNetwork, 1, U"Set outstar...", nullptr, 1, DO_Network_setOutstar);
-		praat_addAction1 (classNetwork, 1, U"Set weight leak...", nullptr, 1, DO_Network_setWeightLeak);
+		praat_addAction1 (classNetwork, 0, U"Add node...", nullptr, 1, MODIFY_Network_addNode);
+		praat_addAction1 (classNetwork, 0, U"Add connection...", nullptr, 1, MODIFY_Network_addConnection);
+		praat_addAction1 (classNetwork, 0, U"-- activity --", nullptr, 1, nullptr);
+		praat_addAction1 (classNetwork, 0, U"Set activity...", nullptr, 1, MODIFY_Network_setActivity);
+		praat_addAction1 (classNetwork, 0, U"Set clamping...", nullptr, 1, MODIFY_Network_setClamping);
+		praat_addAction1 (classNetwork, 0, U"Zero activities...", nullptr, 1, MODIFY_Network_zeroActivities);
+		praat_addAction1 (classNetwork, 0, U"Normalize activities...", nullptr, 1, MODIFY_Network_normalizeActivities);
+		praat_addAction1 (classNetwork, 0, U"Spread activities...", nullptr, 1, MODIFY_Network_spreadActivities);
+		praat_addAction1 (classNetwork, 0, U"Set activity clipping rule...", nullptr, 1, MODIFY_Network_setActivityClippingRule);
+		praat_addAction1 (classNetwork, 0, U"Set activity leak...", nullptr, 1, MODIFY_Network_setActivityLeak);
+		praat_addAction1 (classNetwork, 0, U"Set shunting...", nullptr, 1, MODIFY_Network_setShunting);
+		praat_addAction1 (classNetwork, 0, U"-- weight --", nullptr, 1, nullptr);
+		praat_addAction1 (classNetwork, 0, U"Set weight...", nullptr, 1, MODIFY_Network_setWeight);
+		praat_addAction1 (classNetwork, 0, U"Update weights", nullptr, 1, MODIFY_Network_updateWeights);
+		praat_addAction1 (classNetwork, 0, U"Normalize weights...", nullptr, 1, MODIFY_Network_normalizeWeights);
+		praat_addAction1 (classNetwork, 0, U"Set instar...", nullptr, 1, MODIFY_Network_setInstar);
+		praat_addAction1 (classNetwork, 0, U"Set outstar...", nullptr, 1, MODIFY_Network_setOutstar);
+		praat_addAction1 (classNetwork, 0, U"Set weight leak...", nullptr, 1, MODIFY_Network_setWeightLeak);
 
 	praat_addAction1 (classRBM, 0, U"Modify", nullptr, 0, nullptr);
-		praat_addAction1 (classRBM, 0, U"Spread up", nullptr, 0, DO_RBM_spreadUp);
-		praat_addAction1 (classRBM, 0, U"Spread down", nullptr, 0, DO_RBM_spreadDown);
-		praat_addAction1 (classRBM, 0, U"Spread up (reconstruction)", nullptr, 0, DO_RBM_spreadUp_reconstruction);
-		praat_addAction1 (classRBM, 0, U"Spread down (reconstruction)", nullptr, 0, DO_RBM_spreadDown_reconstruction);
-		praat_addAction1 (classRBM, 0, U"Sample input", nullptr, 0, DO_RBM_sampleInput);
-		praat_addAction1 (classRBM, 0, U"Sample output", nullptr, 0, DO_RBM_sampleOutput);
-		praat_addAction1 (classRBM, 0, U"Update...", nullptr, 0, DO_RBM_update);
+		praat_addAction1 (classRBM, 0, U"Spread up", nullptr, 0, MODIFY_RBM_spreadUp);
+		praat_addAction1 (classRBM, 0, U"Spread down", nullptr, 0, MODIFY_RBM_spreadDown);
+		praat_addAction1 (classRBM, 0, U"Spread up (reconstruction)", nullptr, 0, MODIFY_RBM_spreadUp_reconstruction);
+		praat_addAction1 (classRBM, 0, U"Spread down (reconstruction)", nullptr, 0, MODIFY_RBM_spreadDown_reconstruction);
+		praat_addAction1 (classRBM, 0, U"Sample input", nullptr, 0, MODIFY_RBM_sampleInput);
+		praat_addAction1 (classRBM, 0, U"Sample output", nullptr, 0, MODIFY_RBM_sampleOutput);
+		praat_addAction1 (classRBM, 0, U"Update...", nullptr, 0, MODIFY_RBM_update);
 	praat_addAction1 (classRBM, 0, U"Extract", nullptr, 0, nullptr);
-		praat_addAction1 (classRBM, 0, U"Extract input activities", nullptr, 0, DO_RBM_extractInputActivities);
-		praat_addAction1 (classRBM, 0, U"Extract output activities", nullptr, 0, DO_RBM_extractOutputActivities);
-		praat_addAction1 (classRBM, 0, U"Extract input reconstruction", nullptr, 0, DO_RBM_extractInputReconstruction);
-		praat_addAction1 (classRBM, 0, U"Extract output reconstruction", nullptr, 0, DO_RBM_extractOutputReconstruction);
-		praat_addAction1 (classRBM, 0, U"Extract input biases", nullptr, 0, DO_RBM_extractInputBiases);
-		praat_addAction1 (classRBM, 0, U"Extract output biases", nullptr, 0, DO_RBM_extractOutputBiases);
-		praat_addAction1 (classRBM, 0, U"Extract weights", nullptr, 0, DO_RBM_extractWeights);
-
-	praat_addAction2 (classRBM, 1, classPatternList, 1, U"Apply to input...", nullptr, 0, DO_RBM_PatternList_applyToInput);
-	praat_addAction2 (classRBM, 1, classPatternList, 1, U"Apply to output...", nullptr, 0, DO_RBM_PatternList_applyToOutput);
-	praat_addAction2 (classRBM, 1, classPatternList, 1, U"Learn...", nullptr, 0, DO_RBM_PatternList_learn);
+		praat_addAction1 (classRBM, 0, U"Extract input activities", nullptr, 0, NEW_RBM_extractInputActivities);
+		praat_addAction1 (classRBM, 0, U"Extract output activities", nullptr, 0, NEW_RBM_extractOutputActivities);
+		praat_addAction1 (classRBM, 0, U"Extract input reconstruction", nullptr, 0, NEW_RBM_extractInputReconstruction);
+		praat_addAction1 (classRBM, 0, U"Extract output reconstruction", nullptr, 0, NEW_RBM_extractOutputReconstruction);
+		praat_addAction1 (classRBM, 0, U"Extract input biases", nullptr, 0, NEW_RBM_extractInputBiases);
+		praat_addAction1 (classRBM, 0, U"Extract output biases", nullptr, 0, NEW_RBM_extractOutputBiases);
+		praat_addAction1 (classRBM, 0, U"Extract weights", nullptr, 0, NEW_RBM_extractWeights);
+
+	praat_addAction2 (classRBM, 1, classPatternList, 1, U"Apply to input...", nullptr, 0, MODIFY_RBM_PatternList_applyToInput);
+	praat_addAction2 (classRBM, 1, classPatternList, 1, U"Apply to output...", nullptr, 0, MODIFY_RBM_PatternList_applyToOutput);
+	praat_addAction2 (classRBM, 1, classPatternList, 1, U"Learn...", nullptr, 0, MODIFY_RBM_PatternList_learn);
 }
 
 /* End of file praat_gram.cpp */
diff --git a/kar/longchar.cpp b/kar/longchar.cpp
index 108cd49..f3bedcc 100644
--- a/kar/longchar.cpp
+++ b/kar/longchar.cpp
@@ -1,6 +1,6 @@
 /* longchar.cpp
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -671,22 +671,6 @@ char32_t * Longchar_nativize32 (const char32_t *generic, char32_t *native, int e
 	return native;
 }
 
-char *Longchar_genericize (const char *native, char *g) {
-	unsigned char kar;
-	if (! inited) init ();
-	while ((kar = *native++) != '\0') {
-		if (kar >= 32 && kar <= 126) {
-			*g++ = kar;
-		} else {
-			*g++ = '\\';
-			*g++ = genericDigraph [kar]. first;
-			*g++ = genericDigraph [kar]. second;
-		}
-	}
-	*g++ = '\0';
-	return g;
-}
-
 char32_t *Longchar_genericize32 (const char32_t *native, char32_t *g) {
 	char32_t kar;
 	if (! inited) init ();
diff --git a/kar/longchar.h b/kar/longchar.h
index bebacd5..8f9d8f7 100644
--- a/kar/longchar.h
+++ b/kar/longchar.h
@@ -2,7 +2,7 @@
 #define _longchar_h_
 /* longchar.h
  *
- * Copyright (C) 1992-2011,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -50,7 +50,6 @@
 
 char32_t * Longchar_nativize32 (const char32_t *generic, char32_t *native, int educateQuotes);
 
-char * Longchar_genericize (const char *native, char *generic);
 char32_t *Longchar_genericize32 (const char32_t *native, char32_t *generic);
 /*
 	Function:
diff --git a/main/praat_cocoa.plist b/main/praat.plist
similarity index 100%
rename from main/praat_cocoa.plist
rename to main/praat.plist
diff --git a/makefile b/makefile
index 965db26..95cf961 100644
--- a/makefile
+++ b/makefile
@@ -1,7 +1,7 @@
 # File: makefile
 
 # Makefile for Praat.
-# Paul Boersma, 14 January 2012
+# Paul Boersma, 22 October 2016
 
 # System-dependent definitions of CC, LIBS, ICON and MAIN_ICON should be in
 # makefile.defs, which has to be copied and renamed
@@ -9,6 +9,8 @@
 # Perhaps that file requires some editing.
 include makefile.defs
 
+.PHONY: all clean install
+
 # Makes the Praat executable in the source directory.
 all:
 	$(MAKE) -C external/gsl
@@ -64,3 +66,6 @@ clean:
 	$(MAKE) -C contrib/ola clean
 	$(MAKE) -C main clean
 	$(RM) praat
+
+install:
+	$(INSTALL)
diff --git a/makefiles/makefile.defs.linux.barren b/makefiles/makefile.defs.linux.barren
index 8f3a2b1..aebdc36 100644
--- a/makefiles/makefile.defs.linux.barren
+++ b/makefiles/makefile.defs.linux.barren
@@ -1,7 +1,7 @@
 # File: makefile.defs.linux.barren
 
 # System: Linux without GUI, network, graphics, and sound
-# Paul Boersma, 12 September 2016
+# Paul Boersma, 26 September 2016
 
 CC = gcc -std=gnu99
 
@@ -21,3 +21,5 @@ AR = ar
 RANLIB = ls
 ICON =
 MAIN_ICON =
+
+INSTALL = cp ./praat /usr/bin
\ No newline at end of file
diff --git a/makefiles/makefile.defs.linux.pulse b/makefiles/makefile.defs.linux.pulse
index 8fda41a..c8064d6 100644
--- a/makefiles/makefile.defs.linux.pulse
+++ b/makefiles/makefile.defs.linux.pulse
@@ -1,7 +1,7 @@
 # File: makefile.defs.linux.pulse
 
 # System: Linux
-# David Weenink and Paul Boersma, 17 January 2016
+# David Weenink and Paul Boersma, 22 October 2016
 
 CC = gcc -std=gnu99
 
@@ -21,3 +21,5 @@ AR = ar
 RANLIB = ls
 ICON =
 MAIN_ICON =
+
+INSTALL = install -p praat /usr/local/bin
diff --git a/stat/Makefile b/stat/Makefile
index 715485f..39a36ad 100644
--- a/stat/Makefile
+++ b/stat/Makefile
@@ -1,11 +1,12 @@
 # Makefile of the library "stat"
-# Paul Boersma, 24 August 2013
+# Paul Boersma, 22 October 2016
 
 include ../makefile.defs
 
 CPPFLAGS = -I ../num -I ../kar -I ../sys -I ../dwsys -I ../dwtools -I ../fon -I ../stat
 
-OBJECTS = Table.o TableEditor.o Regression.o manual_statistics.o praat_Stat.o \
+OBJECTS = Table.o TableEditor.o Regression.o manual_statistics.o \
+   praat_TableOfReal.o praat_Stat.o \
    TableOfReal.o Distributions.o Distributions_and_Strings.o PairDistribution.o \
    LogisticRegression.o
 
diff --git a/stat/Regression_def.h b/stat/Regression_def.h
index 4c2dffe..8de51d2 100644
--- a/stat/Regression_def.h
+++ b/stat/Regression_def.h
@@ -1,6 +1,6 @@
 /* Regression_def.h
  *
- * Copyright (C) 2005-2007,2015 Paul Boersma
+ * Copyright (C) 2005-2007,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ oo_DEFINE_CLASS (RegressionParameter, Daata)
 	oo_DOUBLE (minimum)
 	oo_DOUBLE (maximum)
 	oo_DOUBLE (value)
+
 	#if oo_DECLARING || oo_COPYING
 		oo_LONG (tableColumnIndex)
 	#endif
diff --git a/stat/Table_def.h b/stat/Table_def.h
index f16c0a2..97800e6 100644
--- a/stat/Table_def.h
+++ b/stat/Table_def.h
@@ -1,6 +1,6 @@
 /* Table_def.h
  *
- * Copyright (C) 2002-2012,2015 Paul Boersma
+ * Copyright (C) 2002-2012,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
 oo_DEFINE_STRUCT (TableCell)
 
 	oo_STRING (string)
+
 	#if oo_DECLARING || oo_COPYING
 		oo_DOUBLE (number)
 	#endif
@@ -32,13 +33,13 @@ oo_END_STRUCT (TableCell)
 #define ooSTRUCT TableRow
 oo_DEFINE_CLASS (TableRow, Daata)
 
+	oo_LONG (numberOfColumns)
+	oo_STRUCT_VECTOR (TableCell, cells, numberOfColumns)
+
 	#if oo_DECLARING || oo_COPYING
 		oo_LONG (sortingIndex)
 	#endif
 
-	oo_LONG (numberOfColumns)
-	oo_STRUCT_VECTOR (TableCell, cells, numberOfColumns)
-
 oo_END_CLASS (TableRow)
 #undef ooSTRUCT
 
diff --git a/stat/praat_Stat.cpp b/stat/praat_Stat.cpp
index a472a17..8173140 100644
--- a/stat/praat_Stat.cpp
+++ b/stat/praat_Stat.cpp
@@ -1,6 +1,6 @@
 /* praat_Stat.cpp
  *
- * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,8 +16,6 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "praat.h"
-
 #include "Distributions_and_Strings.h"
 #include "LogisticRegression.h"
 #include "Matrix.h"
@@ -26,8 +24,7 @@
 #include "TableEditor.h"
 #include "UnicodeData.h"
 
-#undef iam
-#define iam iam_LOOP
+#include "praat_TableOfReal.h"
 
 static const char32 * Table_messageColumn (Table me, long column) {
 	if (my columnHeaders [column]. label && my columnHeaders [column]. label [0] != U'\0')
@@ -36,1664 +33,987 @@ static const char32 * Table_messageColumn (Table me, long column) {
 		return Melder_integer (column);
 }
 
-/***** DISTRIBUTIONS *****/
-#pragma mark -
-#pragma mark DISTRIBUTIONS
+// MARK: - DISTRIBUTIONS
 
-DIRECT2 (Distributionses_add) {
-	OrderedOf<structDistributions> list;
-	LOOP {
-		iam (Distributions);
-		list. addItem_ref (me);
-	}
-	autoDistributions thee = Distributions_addMany (& list);
-	praat_new (thee.move(), U"added");
-END2 }
+// MARK: Help
+
+DIRECT (HELP_Distributions_help) {
+	HELP (U"Distributions")
+}
+
+DIRECT (HELP_Table_help) {
+	HELP (U"Table")
+}
+
+// MARK: Query
 
-FORM (Distributionses_getMeanAbsoluteDifference, U"Get mean difference", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
+FORM (REAL_Distributionses_getMeanAbsoluteDifference, U"Get mean difference", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
 DO
-	Distributions me = nullptr, thee = nullptr;
-	LOOP {
-		(me ? thee : me) = (Distributions) OBJECT;
-	}
-	Melder_informationReal (Distributionses_getMeanAbsoluteDifference (me, thee, GET_INTEGER (U"Column number")), nullptr);
-END2 }
+	NUMBER_COUPLE (Distributions)
+		double result = Distributionses_getMeanAbsoluteDifference (me, you, columnNumber);
+	NUMBER_COUPLE_END (U" (mean absolute difference between columns ", columnNumber, U")")
+}
 
-FORM (Distributions_getProbability, U"Get probability", nullptr) {
-	NATURAL (U"Column number", U"1")
-	SENTENCE (U"String", U"")
-	OK2
+FORM (REAL_Distributions_getProbability, U"Get probability", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	SENTENCE4 (string, U"String", U"")
+	OK
 DO
-	LOOP {
-		iam (Distributions);
-		double probability = Distributions_getProbability (me, GET_STRING (U"String"), GET_INTEGER (U"Column number"));
-		Melder_informationReal (probability, nullptr);
-	}
-END2 }
+	NUMBER_ONE (Distributions)
+		double result = Distributions_getProbability (me, string, columnNumber);
+	NUMBER_ONE_END (U" (probability)")
+}
+
+// MARK: Modify
 
-DIRECT2 (Distributions_help) {
-	Melder_help (U"Distributions");
-END2 }
+DIRECT (NEW1_Distributionses_add) {
+	CONVERT_LIST (Distributions)
+		autoDistributions result = Distributions_addMany (& list);
+	CONVERT_LIST_END (U"added")
+}
+
+// MARK: Generate
 
-FORM (Distributions_to_Strings, U"To Strings", nullptr) {
-	NATURAL (U"Column number", U"1")
-	NATURAL (U"Number of strings", U"1000")
-	OK2
+FORM (NEW_Distributions_to_Strings, U"To Strings", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	NATURAL4 (numberOfStrings, U"Number of strings", U"1000")
+	OK
 DO
-	LOOP {
-		iam (Distributions);
-		autoStrings thee = Distributions_to_Strings (me, GET_INTEGER (U"Column number"), GET_INTEGER (U"Number of strings"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Distributions)
+		autoStrings result = Distributions_to_Strings (me, columnNumber, numberOfStrings);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (Distributions_to_Strings_exact, U"To Strings (exact)", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
+FORM (NEW_Distributions_to_Strings_exact, U"To Strings (exact)", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
 DO
-	LOOP {
-		iam (Distributions);
-		autoStrings thee = Distributions_to_Strings_exact (me, GET_INTEGER (U"Column number"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-/***** LOGISTICREGRESSION *****/
-#pragma mark -
-#pragma mark LOGISTICREGRESSION
-
-FORM (LogisticRegression_drawBoundary, U"LogisticRegression: Draw boundary", nullptr) {
-	WORD (U"Horizontal factor", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical factor", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	BOOLEAN (U"Garnish", true)
-	OK2
+	CONVERT_EACH (Distributions)
+		autoStrings result = Distributions_to_Strings_exact (me, columnNumber);
+	CONVERT_EACH_END (my name)
+}
+
+// MARK: - LOGISTICREGRESSION
+
+// MARK: Draw
+
+FORM (GRAPHICS_LogisticRegression_drawBoundary, U"LogisticRegression: Draw boundary", nullptr) {
+	WORD4 (horizontalFactor, U"Horizontal factor", U"")
+	REAL4 (fromHorizontal, U"left Horizontal range", U"0.0")
+	REAL4 (toHorizontal, U"right Horizontal range", U"0.0 (= auto)")
+	WORD4 (verticalFactor, U"Vertical factor", U"")
+	REAL4 (fromVertical, U"left Vertical range", U"0.0")
+	REAL4 (toVertical, U"right Vertical range", U"0.0 (= auto)")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (LogisticRegression);
-		long xfactor = Regression_getFactorIndexFromFactorName_e (me, GET_STRING (U"Horizontal factor"));
-		long yfactor = Regression_getFactorIndexFromFactorName_e (me, GET_STRING (U"Vertical factor"));
+	GRAPHICS_EACH (LogisticRegression)
+		long xfactor = Regression_getFactorIndexFromFactorName_e (me, horizontalFactor);
+		long yfactor = Regression_getFactorIndexFromFactorName_e (me, verticalFactor);
 		LogisticRegression_drawBoundary (me, GRAPHICS,
-			xfactor, GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			yfactor, GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_INTEGER (U"Garnish"));
-	}
-END2 }
+			xfactor, fromHorizontal, toHorizontal,
+			yfactor, fromVertical, toVertical,
+			garnish);
+	GRAPHICS_EACH_END
+}
 
-/***** PAIRDISTRIBUTION *****/
-#pragma mark -
-#pragma mark PAIRDISTRIBUTION
+// MARK: - PAIRDISTRIBUTION
 
-DIRECT2 (PairDistribution_getFractionCorrect_maximumLikelihood) {
-	LOOP {
-		iam (PairDistribution);
-		double fractionCorrect = PairDistribution_getFractionCorrect_maximumLikelihood (me);
-		Melder_informationReal (fractionCorrect, nullptr);
-	}
-END2 }
+// MARK: Help
 
-DIRECT2 (PairDistribution_getFractionCorrect_probabilityMatching) {
-	LOOP {
-		iam (PairDistribution);
-		double fractionCorrect = PairDistribution_getFractionCorrect_probabilityMatching (me);
-		Melder_informationReal (fractionCorrect, nullptr);
-	}
-END2 }
+DIRECT (HELP_PairDistribution_help) {
+	HELP (U"PairDistribution")
+}
 
-DIRECT2 (PairDistribution_getNumberOfPairs) {
-	LOOP {
-		iam (PairDistribution);
-		Melder_information (my pairs.size);
-	}
-END2 }
+// MARK: Query
+
+DIRECT (REAL_PairDistribution_getFractionCorrect_maximumLikelihood) {
+	NUMBER_ONE (PairDistribution)
+		double result = PairDistribution_getFractionCorrect_maximumLikelihood (me);
+	NUMBER_ONE_END (U" (fraction correct)")
+}
 
-FORM (PairDistribution_getString1, U"Get string1", nullptr) {
-	NATURAL (U"Pair number", U"1")
-	OK2
+DIRECT (REAL_PairDistribution_getFractionCorrect_probabilityMatching) {
+	NUMBER_ONE (PairDistribution)
+		double result = PairDistribution_getFractionCorrect_probabilityMatching (me);
+	NUMBER_ONE_END (U" (fraction correct)")
+}
+
+DIRECT (INTEGER_PairDistribution_getNumberOfPairs) {
+	NUMBER_ONE (PairDistribution)
+		long result = my pairs.size;
+	NUMBER_ONE_END (U" pairs")
+}
+
+FORM (STRING_PairDistribution_getString1, U"Get string1", nullptr) {
+	NATURAL4 (pairNumber, U"Pair number", U"1")
+	OK
 DO
-	LOOP {
-		iam (PairDistribution);
-		const char32 *string1 = PairDistribution_getString1 (me, GET_INTEGER (U"Pair number"));
-		Melder_information (string1);
-	}
-END2 }
+	STRING_ONE (PairDistribution)
+		const char32 *result = PairDistribution_getString1 (me, pairNumber);
+	STRING_ONE_END
+}
 
-FORM (PairDistribution_getString2, U"Get string2", nullptr) {
-	NATURAL (U"Pair number", U"1")
-	OK2
+FORM (STRING_PairDistribution_getString2, U"Get string2", nullptr) {
+	NATURAL4 (pairNumber, U"Pair number", U"1")
+	OK
 DO
-	LOOP {
-		iam (PairDistribution);
-		const char32 *string2 = PairDistribution_getString2 (me, GET_INTEGER (U"Pair number"));
-		Melder_information (string2);
-	}
-END2 }
+	STRING_ONE (PairDistribution)
+		const char32 *result = PairDistribution_getString2 (me, pairNumber);
+	STRING_ONE_END
+}
 
-FORM (PairDistribution_getWeight, U"Get weight", nullptr) {
-	NATURAL (U"Pair number", U"1")
-	OK2
+FORM (REAL_PairDistribution_getWeight, U"Get weight", nullptr) {
+	NATURAL4 (pairNumber, U"Pair number", U"1")
+	OK
 DO
-	LOOP {
-		iam (PairDistribution);
-		double weight = PairDistribution_getWeight (me, GET_INTEGER (U"Pair number"));
-		Melder_information (weight);
-	}
-END2 }
+	NUMBER_ONE (PairDistribution)
+		double result = PairDistribution_getWeight (me, pairNumber);
+	NUMBER_ONE_END (U" (weight of pair ", pairNumber, U")")
+}
 
-DIRECT2 (PairDistribution_help) {
-	Melder_help (U"PairDistribution");
-END2 }
+// MARK: Modify
 
-DIRECT2 (PairDistribution_removeZeroWeights) {
-	LOOP {
-		iam (PairDistribution);
+DIRECT (MODIFY_PairDistribution_removeZeroWeights) {
+	MODIFY_EACH (PairDistribution)
 		PairDistribution_removeZeroWeights (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
 
-DIRECT2 (PairDistribution_swapInputsAndOutputs) {
-	LOOP {
-		iam (PairDistribution);
+DIRECT (MODIFY_PairDistribution_swapInputsAndOutputs) {
+	MODIFY_EACH (PairDistribution)
 		PairDistribution_swapInputsAndOutputs (me);
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH_END
+}
+
+// MARK: Generate
 
-FORM (PairDistribution_to_Stringses, U"Generate two Strings objects", nullptr) {
-	NATURAL (U"Number", U"1000")
-	SENTENCE (U"Name of first Strings", U"input")
-	SENTENCE (U"Name of second Strings", U"output")
-	OK2
+FORM (NEW2_PairDistribution_to_Stringses, U"Generate two Strings objects", nullptr) {
+	NATURAL4 (number, U"Number", U"1000")
+	SENTENCE4 (nameOfFirstStrings, U"Name of first Strings", U"input")
+	SENTENCE4 (nameOfSecondStrings, U"Name of second Strings", U"output")
+	OK
 DO
-	LOOP {
-		iam (PairDistribution);
+	FIND_ONE (PairDistribution)
 		autoStrings strings1, strings2;
-		PairDistribution_to_Stringses (me, GET_INTEGER (U"Number"), & strings1, & strings2);
-		praat_new (strings1.move(), GET_STRING (U"Name of first Strings"));
-		praat_new (strings2.move(), GET_STRING (U"Name of second Strings"));
-	}
-END2 }
+		PairDistribution_to_Stringses (me, number, & strings1, & strings2);
+		praat_new (strings1.move(), nameOfFirstStrings);
+		praat_new (strings2.move(), nameOfSecondStrings);
+	END
+}
 
-DIRECT2 (PairDistribution_to_Table) {
-	LOOP {
-		iam (PairDistribution);
-		autoTable thee = PairDistribution_to_Table (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+DIRECT (NEW_PairDistribution_to_Table) {
+	CONVERT_EACH (PairDistribution)
+		autoTable result = PairDistribution_to_Table (me);
+	CONVERT_EACH_END (my name)
+}
 
-/***** PAIRDISTRIBUTION & DISTRIBUTIONS *****/
-#pragma mark -
-#pragma mark PAIRDISTRIBUTION & DISTRIBUTIONS
+// MARK: - PAIRDISTRIBUTION & DISTRIBUTIONS
 
-FORM (PairDistribution_Distributions_getFractionCorrect, U"PairDistribution & Distributions: Get fraction correct", nullptr) {
-	NATURAL (U"Column", U"1")
-	OK2
+FORM (REAL_PairDistribution_Distributions_getFractionCorrect, U"PairDistribution & Distributions: Get fraction correct", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
 DO
-	PairDistribution me = nullptr;
-	Distributions thee = nullptr;
-	LOOP {
-		if (CLASS == classPairDistribution) me = (PairDistribution) OBJECT;
-		if (CLASS == classDistributions) thee = (Distributions) OBJECT;
-	}
-	double fractionCorrect = PairDistribution_Distributions_getFractionCorrect (me, thee, GET_INTEGER (U"Column"));
-	Melder_informationReal (fractionCorrect, nullptr);
-END2 }
+	NUMBER_TWO (PairDistribution, Distributions)
+		double result = PairDistribution_Distributions_getFractionCorrect (me, you, columnNumber);
+	NUMBER_TWO_END (U" (fraction correct)")
+}
 
-/***** TABLE *****/
-#pragma mark -
-#pragma mark TABLE
+// MARK: - TABLE
 
-DIRECT2 (Tables_append) {
-	OrderedOf<structTable> list;
-	LOOP {
-		iam (Table);
-		list. addItem_ref (me);
-	}
-	autoTable thee = Tables_append (& list);
-	praat_new (thee.move(), U"appended");
-END2 }
+// MARK: New
 
-FORM (Table_appendColumn, U"Table: Append column", nullptr) {
-	WORD (U"Label", U"newcolumn")
-	OK2
+FORM (NEW1_Table_createWithColumnNames, U"Create Table with column names", nullptr) {
+	WORD4 (name, U"Name", U"table")
+	INTEGER4 (numberOfRows, U"Number of rows", U"10")
+	LABEL (U"", U"Column names:")
+	TEXTFIELD4 (columnNames, U"columnNames", U"speaker dialect age vowel F0 F1 F2")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		Table_appendColumn (me, GET_STRING (U"Label"));
-		praat_dataChanged (OBJECT);
-	}
-END2 }
+	CREATE_ONE
+		autoTable result = Table_createWithColumnNames (numberOfRows, columnNames);
+	CREATE_ONE_END (name)
+}
 
-FORM (Table_appendDifferenceColumn, U"Table: Append difference column", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	WORD (U"Label", U"diff")
-	OK2
+FORM (NEW1_Table_createWithoutColumnNames, U"Create Table without column names", nullptr) {
+	WORD4 (name, U"Name", U"table")
+	INTEGER4 (numberOfRows, U"Number of rows", U"10")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"3")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long jcol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		Table_appendDifferenceColumn (me, icol, jcol, GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CREATE_ONE
+		autoTable result = Table_createWithoutColumnNames (numberOfRows, numberOfColumns);
+	CREATE_ONE_END (name)
+}
 
-FORM (Table_appendProductColumn, U"Table: Append product column", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	WORD (U"Label", U"diff")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long jcol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		Table_appendProductColumn (me, icol, jcol, GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+// MARK: Open
 
-FORM (Table_appendQuotientColumn, U"Table: Append quotient column", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	WORD (U"Label", U"diff")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long jcol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		Table_appendQuotientColumn (me, icol, jcol, GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+FORM_READ (READ1_Table_readFromTableFile, U"Read Table from table file", nullptr, true) {
+	READ_ONE
+		autoTable result = Table_readFromTableFile (file);
+	READ_ONE_END
+}
 
-FORM (Table_appendSumColumn, U"Table: Append sum column", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	WORD (U"Label", U"diff")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long jcol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		Table_appendSumColumn (me, icol, jcol, GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+FORM_READ (READ1_Table_readFromCommaSeparatedFile, U"Read Table from comma-separated file", nullptr, true) {
+	READ_ONE
+		autoTable result = Table_readFromCharacterSeparatedTextFile (file, U',');
+	READ_ONE_END
+}
 
-DIRECT2 (Table_appendRow) {
-	LOOP {
-		iam (Table);
-		Table_appendRow (me);
-		praat_dataChanged (me);
-	}
-END2 }
+FORM_READ (READ1_Table_readFromTabSeparatedFile, U"Read Table from tab-separated file", nullptr, true) {
+	READ_ONE
+		autoTable result = Table_readFromCharacterSeparatedTextFile (file, U'\t');
+	READ_ONE_END
+}
 
-FORM (Table_collapseRows, U"Table: Collapse rows", nullptr) {
-	LABEL (U"", U"Columns with factors (independent variables):")
-	TEXTFIELD (U"factors", U"speaker dialect age vowel")
-	LABEL (U"", U"Columns to sum:")
-	TEXTFIELD (U"columnsToSum", U"number cost")
-	LABEL (U"", U"Columns to average:")
-	TEXTFIELD (U"columnsToAverage", U"price")
-	LABEL (U"", U"Columns to medianize:")
-	TEXTFIELD (U"columnsToMedianize", U"vot")
-	LABEL (U"", U"Columns to average logarithmically:")
-	TEXTFIELD (U"columnsToAverageLogarithmically", U"duration")
-	LABEL (U"", U"Columns to medianize logarithmically:")
-	TEXTFIELD (U"columnsToMedianizeLogarithmically", U"F0 F1 F2 F3")
-	LABEL (U"", U"Columns not mentioned above will be ignored.")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		autoTable thee = Table_collapseRows (me,
-			GET_STRING (U"factors"), GET_STRING (U"columnsToSum"),
-			GET_STRING (U"columnsToAverage"), GET_STRING (U"columnsToMedianize"),
-			GET_STRING (U"columnsToAverageLogarithmically"), GET_STRING (U"columnsToMedianizeLogarithmically"));
-		praat_new (thee.move(), my name, U"_pooled");
-	}
-END2 }
+// MARK: Save
 
-FORM (Table_createWithColumnNames, U"Create Table with column names", nullptr) {
-	WORD (U"Name", U"table")
-	INTEGER (U"Number of rows", U"10")
-	LABEL (U"", U"Column names:")
-	TEXTFIELD (U"columnNames", U"speaker dialect age vowel F0 F1 F2")
-	OK2
-DO
-	autoTable me = Table_createWithColumnNames (GET_INTEGER (U"Number of rows"), GET_STRING (U"columnNames"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Table_createWithoutColumnNames, U"Create Table without column names", nullptr) {
-	WORD (U"Name", U"table")
-	INTEGER (U"Number of rows", U"10")
-	NATURAL (U"Number of columns", U"3")
-	OK2
-DO
-	autoTable me = Table_createWithoutColumnNames (GET_INTEGER (U"Number of rows"), GET_INTEGER (U"Number of columns"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (Table_drawEllipse, U"Draw ellipse (standard deviation)", nullptr) {
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	POSITIVE (U"Number of sigmas", U"2.0")
-	BOOLEAN (U"Garnish", 1)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		Table_drawEllipse_e (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Number of sigmas"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
+FORM_SAVE (SAVE_Table_writeToCommaSeparatedFile, U"Save Table as comma-separated file", 0, U"Table") {
+	SAVE_ONE (Table)
+		Table_writeToCommaSeparatedFile (me, file);
+	SAVE_ONE_END
+}
 
-FORM (Table_drawRowFromDistribution, U"Table: Draw row from distribution", nullptr) {
-	WORD (U"Column with distribution", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column with distribution"));
-		long row = Table_drawRowFromDistribution (me, icol);
-		Melder_information (row);
-	}
-END2 }
+FORM_SAVE (SAVE_Table_writeToTabSeparatedFile, U"Save Table as tab-separated file", 0, U"Table") {
+	SAVE_ONE (Table)
+		Table_writeToTabSeparatedFile (me, file);
+	SAVE_ONE_END
+}
+
+// MARK: Help
 
-DIRECT2 (Table_edit) {
+DIRECT (HELP_StatisticsTutorial) {
+	HELP (U"Statistics")
+}
+
+// MARK: View & Edit
+
+DIRECT (WINDOW_Table_viewAndEdit) {
 	if (theCurrentPraatApplication -> batch) Melder_throw (U"Cannot edit a Table from batch.");
 	LOOP {
-		iam (Table);
+		iam_LOOP (Table);
 		autoTableEditor editor = TableEditor_create (ID_AND_FULL_NAME, me);
 		praat_installEditor (editor.get(), IOBJECT);
 		editor.releaseToUser();
 	}
-END2 }
+END }
 
-FORM (Table_extractRowsWhereColumn_number, U"Table: Extract rows where column (number)", nullptr) {
-	WORD (U"Extract all rows where column...", U"")
-	RADIO_ENUM (U"...is...", kMelder_number, DEFAULT)
-	REAL (U"...the number", U"0.0")
-	OK2
-DO
-	double value = GET_REAL (U"...the number");
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Extract all rows where column..."));
-		autoTable thee = Table_extractRowsWhereColumn_number (me, icol, GET_ENUM (kMelder_number, U"...is..."), value);
-		praat_new (thee.move(), my name, U"_", Table_messageColumn (static_cast <Table> OBJECT, icol), U"_", NUMdefined (value) ? Melder_integer (lround (value)) : U"undefined");
-		praat_dataChanged (me);   // WHY?
-	}
-END2 }
+// MARK: Tabulate
 
-FORM (Table_extractRowsWhereColumn_text, U"Table: Extract rows where column (text)", nullptr) {
-	WORD (U"Extract all rows where column...", U"")
-	OPTIONMENU_ENUM (U"...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"hi")
-	OK2
+FORM (LIST_Table_list, U"Table: List", nullptr) {
+	BOOLEAN4 (includeRowNumbers, U"Include row numbers", true)
+	OK
 DO
-	const char32 *value = GET_STRING (U"...the text");
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Extract all rows where column..."));
-		autoTable thee = Table_extractRowsWhereColumn_string (me, icol, GET_ENUM (kMelder_string, U"..."), value);
-		praat_new (thee.move(), my name, U"_", value);
-		praat_dataChanged (me);   // WHY?
-	}
-END2 }
+	INFO_ONE (Table)
+		Table_list (me, includeRowNumbers);
+	INFO_ONE_END
+}
 
-FORM (Table_formula, U"Table: Formula", U"Table: Formula...") {
-	WORD (U"Column label", U"")
-	TEXTFIELD (U"formula", U"abs (self)")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		try {
-			long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-			Table_formula (me, icol, GET_STRING (U"formula"), interpreter);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Table may have partially changed
-			throw;
-		}
-	}
-END2 }
+// MARK: Draw
+
+FORM (GRAPHICS_Table_scatterPlot, U"Scatter plot", nullptr) {
+	WORD4 (horizontalColumn, U"Horizontal column", U"")
+	REAL4 (fromHorizontal, U"left Horizontal range", U"0.0")
+	REAL4 (toHorizontal, U"right Horizontal range", U"0.0 (= auto)")
+	WORD4 (verticalColumn, U"Vertical column", U"")
+	REAL4 (fromVertical, U"left Vertical range", U"0.0")
+	REAL4 (toVertical, U"right Vertical range", U"0.0 (= auto)")
+	WORD4 (columnWithMarks, U"Column with marks", U"")
+	NATURAL4 (fontSize, U"Font size", U"12")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, horizontalColumn);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, verticalColumn);
+		long markColumn = Table_getColumnIndexFromColumnLabel (me, columnWithMarks);
+		Table_scatterPlot (me, GRAPHICS, xcolumn, ycolumn,
+			fromHorizontal, toHorizontal, fromVertical, toVertical, markColumn, fontSize, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_formula_columnRange, U"Table: Formula (column range)", U"Table: Formula...") {
-	WORD (U"From column label", U"")
-	WORD (U"To column label", U"")
-	TEXTFIELD (U"formula", U"log10 (self)")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		try {
-			long icol1 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"From column label"));
-			long icol2 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"To column label"));
-			Table_formula_columnRange (me, icol1, icol2, GET_STRING (U"formula"), interpreter);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);   // in case of error, the Table may have partially changed
-			throw;
-		}
-	}
-END2 }
+FORM (GRAPHICS_Table_scatterPlot_mark, U"Scatter plot (marks)", nullptr) {
+	WORD4 (horizontalColumn, U"Horizontal column", U"")
+	REAL4 (fromHorizontal, U"left Horizontal range", U"0.0")
+	REAL4 (toHorizontal, U"right Horizontal range", U"0.0 (= auto)")
+	WORD4 (verticalColumn, U"Vertical column", U"")
+	REAL4 (fromVertical, U"left Vertical range", U"0.0")
+	REAL4 (toVertical, U"right Vertical range", U"0.0 (= auto)")
+	POSITIVE4 (markSize, U"Mark size (mm)", U"1.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	SENTENCE4 (markString, U"Mark string (+xo.)", U"+")
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, horizontalColumn);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, verticalColumn);
+		Table_scatterPlot_mark (me, GRAPHICS, xcolumn, ycolumn,
+			fromHorizontal, toHorizontal, fromVertical, toVertical,
+			markSize, markString, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_getColumnIndex, U"Table: Get column index", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		Melder_information (Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Column label")));
-	}
-END2 }
+FORM (GRAPHICS_Table_drawEllipse, U"Draw ellipse (standard deviation)", nullptr) {
+	WORD4 (horizontalColumn, U"Horizontal column", U"")
+	REAL4 (fromHorizontal, U"left Horizontal range", U"0.0")
+	REAL4 (toHorizontal, U"right Horizontal range", U"0.0 (= auto)")
+	WORD4 (verticalColumn, U"Vertical column", U"")
+	REAL4 (fromVertical, U"left Vertical range", U"0.0")
+	REAL4 (toVertical, U"right Vertical range", U"0.0 (= auto)")
+	POSITIVE4 (numberOfSigmas, U"Number of sigmas", U"2.0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (Table)
+		long xcolumn = Table_getColumnIndexFromColumnLabel (me, horizontalColumn);
+		long ycolumn = Table_getColumnIndexFromColumnLabel (me, verticalColumn);
+		Table_drawEllipse_e (me, GRAPHICS, xcolumn, ycolumn,
+			fromHorizontal, toHorizontal, fromVertical, toVertical, numberOfSigmas, garnish);
+	GRAPHICS_EACH_END
+}
 
-FORM (Table_getColumnLabel, U"Table: Get column label", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = GET_INTEGER (U"Column number");
-		if (icol > my numberOfColumns) Melder_throw (U"Column number must not be greater than number of columns.");
-		Melder_information (my columnHeaders [icol]. label);
-	}
-END2 }
+// MARK: Query
 
-FORM (Table_getGroupMean, U"Table: Get group mean", nullptr) {
-	WORD (U"Column label", U"salary")
-	WORD (U"Group column", U"gender")
-	SENTENCE (U"Group", U"F")
-	OK2
+FORM (INTEGER_Table_drawRowFromDistribution, U"Table: Draw row from distribution", nullptr) {
+	WORD4 (columnWithDistribution, U"Column with distribution", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		long groupColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Group column"));
-		Melder_information (Table_getGroupMean (static_cast <Table> ONLY_OBJECT, column, groupColumn, GET_STRING (U"Group")));
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnWithDistribution);
+		long result = Table_drawRowFromDistribution (me, columnNumber);
+	NUMBER_ONE_END (U" (random row number)")
+}
 
-FORM (Table_getMaximum, U"Table: Get maximum", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
+FORM (INTEGER_Table_getColumnIndex, U"Table: Get column index", nullptr) {
+	SENTENCE4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		double maximum = Table_getMaximum (me, icol);
-		Melder_information (maximum);
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long result = Table_findColumnIndexFromColumnLabel (me, columnLabel);
+	NUMBER_ONE_END (U" (index of column ", columnLabel, U")")
+}
 
-FORM (Table_getMean, U"Table: Get mean", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
+FORM (STRING_Table_getColumnLabel, U"Table: Get column label", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		double mean = Table_getMean (me, icol);
-		Melder_information (mean);
-	}
-END2 }
+	STRING_ONE (Table)
+		if (columnNumber > my numberOfColumns)
+			Melder_throw (U"Your column number should not be greater than the number of columns.");
+		const char32 *result = my columnHeaders [columnNumber]. label;
+	STRING_ONE_END
+}
 
-FORM (Table_getMinimum, U"Table: Get minimum", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		double minimum = Table_getMinimum (me, icol);
-		Melder_information (minimum);
-	}
-END2 }
+FORM (REAL_Table_getGroupMean, U"Table: Get group mean", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"salary")
+	WORD4 (groupColumnLabel, U"Group column label", U"gender")
+	SENTENCE4 (group, U"Group", U"F")
+	OK
+DO
+	NUMBER_ONE (Table)
+		long column = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		long groupColumn = Table_getColumnIndexFromColumnLabel (me, groupColumnLabel);
+		double result = Table_getGroupMean (me, column, groupColumn, group);
+	NUMBER_ONE_END (U" (mean of ", columnLabel, U" in group ", group, U")")
+}
 
-FORM (Table_getQuantile, U"Table: Get quantile", nullptr) {
-	SENTENCE (U"Column label", U"")
-	POSITIVE (U"Quantile", U"0.50 (= median)")
-	OK2
+FORM (REAL_Table_getMaximum, U"Table: Get maximum", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		double quantile = Table_getQuantile (me, icol, GET_REAL (U"Quantile"));
-		Melder_information (quantile);
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		double result = Table_getMaximum (me, columnNumber);
+	NUMBER_ONE_END (U" (maximum of ", columnLabel, U")")
+}
 
-FORM (Table_getStandardDeviation, U"Table: Get standard deviation", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
+FORM (REAL_Table_getMean, U"Table: Get mean", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		double stdev = Table_getStdev (me, icol);
-		Melder_information (stdev);
-	}
-END2 }
-
-DIRECT2 (Table_getNumberOfColumns) {
-	LOOP {
-		iam (Table);
-		Melder_information (my numberOfColumns);
-	}
-END2 }
-
-DIRECT2 (Table_getNumberOfRows) {
-	LOOP {
-		iam (Table);
-		Melder_information (my rows.size);
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		double result = Table_getMean (me, columnNumber);
+	NUMBER_ONE_END (U" (mean of ", columnLabel, U")")
+}
 
-FORM (Table_getValue, U"Table: Get value", nullptr) {
-	NATURAL (U"Row number", U"1")
-	WORD (U"Column label", U"")
-	OK2
+FORM (REAL_Table_getMinimum, U"Table: Get minimum", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long rowNumber = GET_INTEGER (U"Row number");
-		Table_checkSpecifiedRowNumberWithinRange (me, rowNumber);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		Melder_information (my rows.at [rowNumber] -> cells [icol]. string);
-	}
-END2 }
-
-DIRECT2 (Table_help) {
-	Melder_help (U"Table");
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		double result = Table_getMinimum (me, columnNumber);
+	NUMBER_ONE_END (U" (minimum of ", columnLabel, U")")
+}
 
-FORM (Table_insertColumn, U"Table: Insert column", nullptr) {
-	NATURAL (U"Position", U"1")
-	WORD (U"Label", U"newcolumn")
-	OK2
+FORM (REAL_Table_getQuantile, U"Table: Get quantile", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"")
+	POSITIVE4 (quantile, U"Quantile", U"0.50 (= median)")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		Table_insertColumn (me, GET_INTEGER (U"Position"), GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		double result = Table_getQuantile (me, columnNumber, quantile);
+	NUMBER_ONE_END (U" (", quantile, U" quantile of ", columnLabel, U")")
+}
 
-FORM (Table_insertRow, U"Table: Insert row", nullptr) {
-	NATURAL (U"Position", U"1")
-	OK2
+FORM (REAL_Table_getStandardDeviation, U"Table: Get standard deviation", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		Table_insertRow (me, GET_INTEGER (U"Position"));
-		praat_dataChanged (me);
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		double result = Table_getStdev (me, columnNumber);
+	NUMBER_ONE_END (U" (standard deviation of ", columnLabel, U")")
+}
 
-FORM (Table_list, U"Table: List", nullptr) {
-	BOOLEAN (U"Include row numbers", true)
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		Table_list (me, GET_INTEGER (U"Include row numbers"));
-	}
-END2 }
-
-FORM_READ2 (Table_readFromTableFile, U"Read Table from table file", nullptr, true) {
-	autoTable me = Table_readFromTableFile (file);
-	praat_newWithFile (me.move(), file, MelderFile_name (file));
-END2 }
-
-FORM_READ2 (Table_readFromCommaSeparatedFile, U"Read Table from comma-separated file", nullptr, true) {
-	autoTable me = Table_readFromCharacterSeparatedTextFile (file, U',');
-	praat_newWithFile (me.move(), file, MelderFile_name (file));
-END2 }
-
-FORM_READ2 (Table_readFromTabSeparatedFile, U"Read Table from tab-separated file", nullptr, true) {
-	autoTable me = Table_readFromCharacterSeparatedTextFile (file, U'\t');
-	praat_newWithFile (me.move(), file, MelderFile_name (file));
-END2 }
-
-FORM (Table_removeColumn, U"Table: Remove column", nullptr) {
-	WORD (U"Column label", U"")
-	OK2
+DIRECT (INTEGER_Table_getNumberOfColumns) {
+	NUMBER_ONE (Table)
+		long result = my numberOfColumns;
+	NUMBER_ONE_END (U" columns")
+}
+
+DIRECT (INTEGER_Table_getNumberOfRows) {
+	NUMBER_ONE (Table)
+		long result = my rows.size;
+	NUMBER_ONE_END (U" rows")
+}
+
+FORM (STRING_Table_getValue, U"Table: Get value", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	SENTENCE4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		Table_removeColumn (me, icol);
-		praat_dataChanged (me);
-	}
-END2 }
+	STRING_ONE (Table)
+		Table_checkSpecifiedRowNumberWithinRange (me, rowNumber);
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		const char32 *result = my rows.at [rowNumber] -> cells [columnNumber]. string;
+	STRING_ONE_END
+}
 
-FORM (Table_removeRow, U"Table: Remove row", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
+FORM (INTEGER_Table_searchColumn, U"Table: Search column", nullptr) {
+	SENTENCE4 (columnLabel, U"Column label", U"")
+	SENTENCE4 (value, U"Value", U"")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		Table_removeRow (me, GET_INTEGER (U"Row number"));
-		praat_dataChanged (me);
-	}
-END2 }
+	NUMBER_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		long result = Table_searchColumn (me, columnNumber, value);
+	NUMBER_ONE_END (U" (first row in which ", columnLabel, U" is ", value)
+}
+	
+// MARK: Statistics
 
-FORM (Table_reportCorrelation_kendallTau, U"Report correlation (Kendall tau)", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	POSITIVE (U"One-tailed unconfidence", U"0.025")
-	OK2
+FORM (INFO_Table_reportCorrelation_kendallTau, U"Report correlation (Kendall tau)", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	POSITIVE4 (oneTailedUnconfidence, U"One-tailed unconfidence", U"0.025")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column1 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long column2 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		double unconfidence = GET_REAL (U"One-tailed unconfidence");
+	INFO_ONE (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
 		double correlation, significance, lowerLimit, upperLimit;
-		correlation = Table_getCorrelation_kendallTau (me, column1, column2, unconfidence,
+		correlation = Table_getCorrelation_kendallTau (me, columnNumber1, columnNumber2, oneTailedUnconfidence,
 			& significance, & lowerLimit, & upperLimit);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"Correlation between column ", Table_messageColumn (me, column1),
-			U" and column ", Table_messageColumn (me, column2), U":");
+		MelderInfo_writeLine (U"Correlation between column ", Table_messageColumn (me, columnNumber1),
+			U" and column ", Table_messageColumn (me, columnNumber2), U":");
 		MelderInfo_writeLine (U"Correlation = ", correlation, U" (Kendall's tau-b)");
 		MelderInfo_writeLine (U"Significance from zero = ", significance, U" (one-tailed)");
-		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * unconfidence), U"%):");
+		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * oneTailedUnconfidence), U"%):");
 		MelderInfo_writeLine (U"   Lower limit = ", lowerLimit,
-			U" (lowest tau that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (lowest tau that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_writeLine (U"   Upper limit = ", upperLimit,
-			U" (highest tau that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (highest tau that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_close ();
-	}
-END2 }
+	INFO_ONE_END
+}
 
-FORM (Table_reportCorrelation_pearsonR, U"Report correlation (Pearson r)", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	POSITIVE (U"One-tailed unconfidence", U"0.025")
-	OK2
+FORM (INFO_Table_reportCorrelation_pearsonR, U"Report correlation (Pearson r)", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	POSITIVE4 (oneTailedUnconfidence, U"One-tailed unconfidence", U"0.025")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column1 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long column2 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		double unconfidence = GET_REAL (U"One-tailed unconfidence");
+	INFO_ONE (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
 		double correlation, significance, lowerLimit, upperLimit;
-		correlation = Table_getCorrelation_pearsonR (me, column1, column2, unconfidence,
+		correlation = Table_getCorrelation_pearsonR (me, columnNumber1, columnNumber2, oneTailedUnconfidence,
 			& significance, & lowerLimit, & upperLimit);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"Correlation between column ", Table_messageColumn (me, column1),
-			U" and column ", Table_messageColumn (me, column2), U":");
+		MelderInfo_writeLine (U"Correlation between column ", Table_messageColumn (me, columnNumber1),
+			U" and column ", Table_messageColumn (me, columnNumber2), U":");
 		MelderInfo_writeLine (U"Correlation = ", correlation, U" (Pearson's r)");
 		MelderInfo_writeLine (U"Number of degrees of freedom = ", my rows.size - 2);
 		MelderInfo_writeLine (U"Significance from zero = ", significance, U" (one-tailed)");
-		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * unconfidence), U"%):");
+		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * oneTailedUnconfidence), U"%):");
 		MelderInfo_writeLine (U"   Lower limit = ", lowerLimit,
-			U" (lowest r that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (lowest r that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_writeLine (U"   Upper limit = ", upperLimit,
-			U" (highest r that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (highest r that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_close ();
-	}
-END2 }
-	
-FORM (Table_reportDifference_studentT, U"Report difference (Student t)", nullptr) {
-	WORD (U"left Columns", U"")
-	WORD (U"right Columns", U"")
-	POSITIVE (U"One-tailed unconfidence", U"0.025")
-	OK2
+	INFO_ONE_END
+}
+
+FORM (INFO_Table_reportDifference_studentT, U"Report difference (Student t)", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	POSITIVE4 (oneTailedUnconfidence, U"One-tailed unconfidence", U"0.025")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column1 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"left Columns"));
-		long column2 = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"right Columns"));
-		double unconfidence = GET_REAL (U"One-tailed unconfidence");
+	INFO_ONE (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
 		double difference, t, numberOfDegreesOfFreedom, significance, lowerLimit, upperLimit;
-		difference = Table_getDifference_studentT (me, column1, column2, unconfidence,
+		difference = Table_getDifference_studentT (me, columnNumber1, columnNumber2, oneTailedUnconfidence,
 			& t, & numberOfDegreesOfFreedom, & significance, & lowerLimit, & upperLimit);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"Difference between column ", Table_messageColumn (me, column1),
-			U" and column ", Table_messageColumn (me, column2), U":");
+		MelderInfo_writeLine (U"Difference between column ", Table_messageColumn (me, columnNumber1),
+			U" and column ", Table_messageColumn (me, columnNumber2), U":");
 		MelderInfo_writeLine (U"Difference = ", difference);
 		MelderInfo_writeLine (U"Student's t = ", t);
 		MelderInfo_writeLine (U"Number of degrees of freedom = ", numberOfDegreesOfFreedom);
 		MelderInfo_writeLine (U"Significance from zero = ", significance, U" (one-tailed)");
-		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * unconfidence), U"%):");
+		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * oneTailedUnconfidence), U"%):");
 		MelderInfo_writeLine (U"   Lower limit = ", lowerLimit,
-			U" (lowest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (lowest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_writeLine (U"   Upper limit = ", upperLimit,
-			U" (highest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (highest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_close ();
-	}
-END2 }
-	
-FORM (Table_reportGroupDifference_studentT, U"Report group difference (Student t)", nullptr) {
-	WORD (U"Column", U"salary")
-	WORD (U"Group column", U"gender")
-	SENTENCE (U"Group 1", U"F")
-	SENTENCE (U"Group 2", U"M")
-	POSITIVE (U"One-tailed unconfidence", U"0.025")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column"));
-		long groupColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Group column"));
-		double unconfidence = GET_REAL (U"One-tailed unconfidence");
-		const char32 *group1 = GET_STRING (U"Group 1"), *group2 = GET_STRING (U"Group 2");
+	INFO_ONE_END
+}
+
+FORM (INFO_Table_reportGroupDifference_studentT, U"Report group difference (Student t)", nullptr) {
+	WORD4 (column, U"Column", U"salary")
+	WORD4 (groupColumn, U"Group column", U"gender")
+	SENTENCE4 (group1, U"Group 1", U"F")
+	SENTENCE4 (group2, U"Group 2", U"M")
+	POSITIVE4 (oneTailedUnconfidence, U"One-tailed unconfidence", U"0.025")
+	OK
+DO
+	INFO_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, column);
+		long groupColumnNumber = Table_getColumnIndexFromColumnLabel (me, groupColumn);
 		double mean, tFromZero, numberOfDegreesOfFreedom, significanceFromZero, lowerLimit, upperLimit;
-		mean = Table_getGroupDifference_studentT (me, column, groupColumn, group1, group2, unconfidence,
+		mean = Table_getGroupDifference_studentT (me, columnNumber, groupColumnNumber, group1, group2, oneTailedUnconfidence,
 			& tFromZero, & numberOfDegreesOfFreedom, & significanceFromZero, & lowerLimit, & upperLimit);
 		MelderInfo_open ();
-		MelderInfo_write (U"Difference in column ", Table_messageColumn (me, column), U" between groups ", group1);
-		MelderInfo_writeLine (U" and ", group2, U" of column ", Table_messageColumn (me, groupColumn), U":");
+		MelderInfo_write (U"Difference in column ", Table_messageColumn (me, columnNumber), U" between groups ", group1);
+		MelderInfo_writeLine (U" and ", group2, U" of column ", Table_messageColumn (me, groupColumnNumber), U":");
 		MelderInfo_writeLine (U"Difference = ", mean);
 		MelderInfo_writeLine (U"Student's t = ", tFromZero);
 		MelderInfo_writeLine (U"Number of degrees of freedom = ", numberOfDegreesOfFreedom);
 		MelderInfo_writeLine (U"Significance from zero = ", significanceFromZero, U" (one-tailed)");
-		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * unconfidence), U"%):");
+		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * oneTailedUnconfidence), U"%):");
 		MelderInfo_writeLine (U"   Lower limit = ", lowerLimit,
-			U" (lowest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (lowest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_writeLine (U"   Upper limit = ", upperLimit,
-			U" (highest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (highest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_close ();
-	}
-END2 }
-
-FORM (Table_reportGroupDifference_wilcoxonRankSum, U"Report group difference (Wilcoxon rank sum)", nullptr) {
-	WORD (U"Column", U"salary")
-	WORD (U"Group column", U"gender")
-	SENTENCE (U"Group 1", U"F")
-	SENTENCE (U"Group 2", U"M")
-	OK2
+	INFO_ONE_END
+}
+
+FORM (INFO_Table_reportGroupDifference_wilcoxonRankSum, U"Report group difference (Wilcoxon rank sum)", nullptr) {
+	WORD4 (column, U"Column", U"salary")
+	WORD4 (groupColumn, U"Group column", U"gender")
+	SENTENCE4 (group1, U"Group 1", U"F")
+	SENTENCE4 (group2, U"Group 2", U"M")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column"));
-		long groupColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Group column"));
-		const char32 *group1 = GET_STRING (U"Group 1"), *group2 = GET_STRING (U"Group 2");
+	INFO_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, column);
+		long groupColumnNumber = Table_getColumnIndexFromColumnLabel (me, groupColumn);
 		double areaUnderCurve, rankSum, significanceFromZero;
-		areaUnderCurve = Table_getGroupDifference_wilcoxonRankSum (me, column, groupColumn, group1, group2,
+		areaUnderCurve = Table_getGroupDifference_wilcoxonRankSum (me, columnNumber, groupColumnNumber, group1, group2,
 			& rankSum, & significanceFromZero);
 		MelderInfo_open ();
-		MelderInfo_write (U"Difference in column ", Table_messageColumn (me, column), U" between groups ", group1);
-		MelderInfo_writeLine (U" and ", group2, U" of column ", Table_messageColumn (me, groupColumn), U":");
+		MelderInfo_write (U"Difference in column ", Table_messageColumn (me, columnNumber), U" between groups ", group1);
+		MelderInfo_writeLine (U" and ", group2, U" of column ", Table_messageColumn (me, groupColumnNumber), U":");
 		MelderInfo_writeLine (U"Larger: ", areaUnderCurve < 0.5 ? group1 : areaUnderCurve > 0.5 ? group2 : U"(both equal)");
 		MelderInfo_writeLine (U"Area under curve: ", areaUnderCurve);
 		MelderInfo_writeLine (U"Rank sum: ", rankSum);
 		MelderInfo_writeLine (U"Significance from zero: ", significanceFromZero, U" (one-tailed)");
 		MelderInfo_close ();
-	}
-END2 }
-
-FORM (Table_reportGroupMean_studentT, U"Report group mean (Student t)", nullptr) {
-	WORD (U"Column", U"salary")
-	WORD (U"Group column", U"gender")
-	SENTENCE (U"Group", U"F")
-	POSITIVE (U"One-tailed unconfidence", U"0.025")
-	OK2
+	INFO_ONE_END
+}
+
+FORM (INFO_Table_reportGroupMean_studentT, U"Report group mean (Student t)", nullptr) {
+	WORD4 (column, U"Column", U"salary")
+	WORD4 (groupColumn, U"Group column", U"gender")
+	SENTENCE4 (group, U"Group", U"F")
+	POSITIVE4 (oneTailedUnconfidence, U"One-tailed unconfidence", U"0.025")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column"));
-		long groupColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Group column"));
-		double unconfidence = GET_REAL (U"One-tailed unconfidence");
-		const char32 *group = GET_STRING (U"Group");
+	INFO_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, column);
+		long groupColumnNumber = Table_getColumnIndexFromColumnLabel (me, groupColumn);
 		double mean, tFromZero, numberOfDegreesOfFreedom, significanceFromZero, lowerLimit, upperLimit;
-		mean = Table_getGroupMean_studentT (me, column, groupColumn, group, unconfidence,
+		mean = Table_getGroupMean_studentT (me, columnNumber, groupColumnNumber, group, oneTailedUnconfidence,
 			& tFromZero, & numberOfDegreesOfFreedom, & significanceFromZero, & lowerLimit, & upperLimit);
 		MelderInfo_open ();
-		MelderInfo_write (U"Mean in column ", Table_messageColumn (me, column), U" of group ", group);
-		MelderInfo_writeLine (U" of column ", Table_messageColumn (me, groupColumn), U":");
+		MelderInfo_write (U"Mean in column ", Table_messageColumn (me, columnNumber), U" of group ", group);
+		MelderInfo_writeLine (U" of column ", Table_messageColumn (me, groupColumnNumber), U":");
 		MelderInfo_writeLine (U"Mean = ", mean);
 		MelderInfo_writeLine (U"Student's t from zero = ", tFromZero);
 		MelderInfo_writeLine (U"Number of degrees of freedom = ", numberOfDegreesOfFreedom);
 		MelderInfo_writeLine (U"Significance from zero = ", significanceFromZero, U" (one-tailed)");
-		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * unconfidence), U"%):");
+		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * oneTailedUnconfidence), U"%):");
 		MelderInfo_writeLine (U"   Lower limit = ", lowerLimit,
-			U" (lowest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (lowest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_writeLine (U"   Upper limit = ", upperLimit,
-			U" (highest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (highest difference that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_close ();
-	}
-END2 }
+	INFO_ONE_END
+}
 
-FORM (Table_reportMean_studentT, U"Report mean (Student t)", nullptr) {
-	WORD (U"Column", U"")
-	POSITIVE (U"One-tailed unconfidence", U"0.025")
-	OK2
+FORM (INFO_Table_reportMean_studentT, U"Report mean (Student t)", nullptr) {
+	WORD4 (column, U"Column", U"")
+	POSITIVE4 (oneTailedUnconfidence, U"One-tailed unconfidence", U"0.025")
+	OK
 DO
-	LOOP {
-		iam (Table);
-		long column = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column"));
-		double unconfidence = GET_REAL (U"One-tailed unconfidence");
+	INFO_ONE (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, column);
 		double mean, tFromZero, numberOfDegreesOfFreedom, significanceFromZero, lowerLimit, upperLimit;
-		mean = Table_getMean_studentT (me, column, unconfidence,
+		mean = Table_getMean_studentT (me, columnNumber, oneTailedUnconfidence,
 			& tFromZero, & numberOfDegreesOfFreedom, & significanceFromZero, & lowerLimit, & upperLimit);
 		MelderInfo_open ();
-		MelderInfo_writeLine (U"Mean of column ", Table_messageColumn (me, column), U":");
+		MelderInfo_writeLine (U"Mean of column ", Table_messageColumn (me, columnNumber), U":");
 		MelderInfo_writeLine (U"Mean = ", mean);
 		MelderInfo_writeLine (U"Student's t from zero = ", tFromZero);
 		MelderInfo_writeLine (U"Number of degrees of freedom = ", numberOfDegreesOfFreedom);
 		MelderInfo_writeLine (U"Significance from zero = ", significanceFromZero, U" (one-tailed)");
-		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * unconfidence), U"%):");
+		MelderInfo_writeLine (U"Confidence interval (", 100.0 * (1.0 - 2.0 * oneTailedUnconfidence), U"%):");
 		MelderInfo_writeLine (U"   Lower limit = ", lowerLimit,
-			U" (lowest value that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (lowest value that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_writeLine (U"   Upper limit = ", upperLimit,
-			U" (highest value that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", unconfidence, U")");
+			U" (highest value that cannot be rejected with " UNITEXT_GREEK_SMALL_LETTER_ALPHA " = ", oneTailedUnconfidence, U")");
 		MelderInfo_close ();
-	}
-END2 }
-
-FORM (Table_rowsToColumns, U"Table: Rows to columns", nullptr) {
-	LABEL (U"", U"Columns with factors (independent variables):")
-	TEXTFIELD (U"factors", U"dialect gender speaker")
-	WORD (U"Column to transpose", U"vowel")
-	LABEL (U"", U"Columns to expand:")
-	TEXTFIELD (U"columnsToExpand", U"duration F0 F1 F2 F3")
-	LABEL (U"", U"Columns not mentioned above will be ignored.")
-	OK2
-DO
-	const char32 *columnLabel = GET_STRING (U"Column to transpose");
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, columnLabel);
-		autoTable thee = Table_rowsToColumns (me, GET_STRING (U"factors"), icol, GET_STRING (U"columnsToExpand"));
-		praat_new (thee.move(), NAME, U"_nested");
-	}
-END2 }
-
-FORM (Table_scatterPlot, U"Scatter plot", nullptr) {
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	WORD (U"Column with marks", U"")
-	NATURAL (U"Font size", U"12")
-	BOOLEAN (U"Garnish", true)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		long markColumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column with marks"));
-		Table_scatterPlot (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			markColumn, GET_INTEGER (U"Font size"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-FORM (Table_scatterPlot_mark, U"Scatter plot (marks)", nullptr) {
-	WORD (U"Horizontal column", U"")
-	REAL (U"left Horizontal range", U"0.0")
-	REAL (U"right Horizontal range", U"0.0 (= auto)")
-	WORD (U"Vertical column", U"")
-	REAL (U"left Vertical range", U"0.0")
-	REAL (U"right Vertical range", U"0.0 (= auto)")
-	POSITIVE (U"Mark size (mm)", U"1.0")
-	BOOLEAN (U"Garnish", true)
-	SENTENCE (U"Mark string (+xo.)", U"+")
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (Table);
-		long xcolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Horizontal column"));
-		long ycolumn = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Vertical column"));
-		Table_scatterPlot_mark (me, GRAPHICS, xcolumn, ycolumn,
-			GET_REAL (U"left Horizontal range"), GET_REAL (U"right Horizontal range"),
-			GET_REAL (U"left Vertical range"), GET_REAL (U"right Vertical range"),
-			GET_REAL (U"Mark size"), GET_STRING (U"Mark string"), GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-FORM (Table_searchColumn, U"Table: Search column", nullptr) {
-	WORD (U"Column label", U"")
-	WORD (U"Value", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		Melder_information (Table_searchColumn (me, icol, GET_STRING (U"Value")));
-	}
-END2 }
-	
-FORM (Table_setColumnLabel_index, U"Set column label", nullptr) {
-	NATURAL (U"Column number", U"1")
-	SENTENCE (U"Label", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		Table_setColumnLabel (me, GET_INTEGER (U"Column number"), GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Table_setColumnLabel_label, U"Set column label", nullptr) {
-	SENTENCE (U"Old label", U"")
-	SENTENCE (U"New label", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		Table_setColumnLabel (me, Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Old label")), GET_STRING (U"New label"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Table_setNumericValue, U"Table: Set numeric value", nullptr) {
-	NATURAL (U"Row number", U"1")
-	WORD (U"Column label", U"")
-	REAL_OR_UNDEFINED (U"Numeric value", U"1.5")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		Table_setNumericValue (me, GET_INTEGER (U"Row number"), icol, GET_REAL (U"Numeric value"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Table_setStringValue, U"Table: Set string value", nullptr) {
-	NATURAL (U"Row number", U"1")
-	WORD (U"Column label", U"")
-	SENTENCE (U"String value", U"xx")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_getColumnIndexFromColumnLabel (me, GET_STRING (U"Column label"));
-		Table_setStringValue (me, GET_INTEGER (U"Row number"), icol, GET_STRING (U"String value"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Table_randomizeRows) {
-	LOOP {
-		iam (Table);
-		Table_randomizeRows (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Table_reflectRows) {
-	LOOP {
-		iam (Table);
-		Table_reflectRows (me);
-		praat_dataChanged (me);
-	}
-END2 }
-
-FORM (Table_sortRows, U"Table: Sort rows", nullptr) {
-	LABEL (U"", U"One or more column labels for sorting:")
-	TEXTFIELD (U"columnLabels", U"dialect gender name")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		Table_sortRows_string (me, GET_STRING (U"columnLabels"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (Table_to_LinearRegression) {
-	LOOP {
-		iam (Table);
-		autoLinearRegression thee = Table_to_LinearRegression (me);
-		praat_new (thee.move(), NAME);
-	}
-END2 }
-
-FORM (Table_to_LogisticRegression, U"Table: To LogisticRegression", nullptr) {
-	LABEL (U"", U"Factors (column names):")
-	TEXTFIELD (U"factors", U"F0 F1 duration")
-	WORD (U"Dependent 1 (column name)", U"e")
-	WORD (U"Dependent 2 (column name)", U"i")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		autoLogisticRegression thee = Table_to_LogisticRegression (me, GET_STRING (U"factors"), GET_STRING (U"Dependent 1"), GET_STRING (U"Dependent 2"));
-		praat_new (thee.move(), NAME);
-	}
-END2 }
-
-FORM (Table_to_TableOfReal, U"Table: Down to TableOfReal", nullptr) {
-	WORD (U"Column for row labels", U"")
-	OK2
-DO
-	LOOP {
-		iam (Table);
-		long icol = Table_findColumnIndexFromColumnLabel (me, GET_STRING (U"Column for row labels"));
-		autoTableOfReal thee = Table_to_TableOfReal (me, icol);
-		praat_new (thee.move(), NAME);
-	}
-END2 }
-
-DIRECT2 (Table_transpose) {
-	LOOP {
-		iam (Table);
-		autoTable thee = Table_transpose (me);
-		praat_new (thee.move(), NAME, U"_transposed");
-	}
-END2 }
-
-FORM_WRITE2 (Table_writeToCommaSeparatedFile, U"Save Table as comma-separated file", 0, U"Table") {
-	LOOP {
-		iam (Table);
-		Table_writeToCommaSeparatedFile (me, file);
-	}
-END2 }
-
-FORM_WRITE2 (Table_writeToTabSeparatedFile, U"Save Table as tab-separated file", 0, U"Table") {
-	LOOP {
-		iam (Table);
-		Table_writeToTabSeparatedFile (me, file);
-	}
-END2 }
-
-/***** TABLEOFREAL *****/
-#pragma mark -
-#pragma mark TABLEOFREAL
-
-DIRECT2 (TablesOfReal_append) {
-	OrderedOf<structTableOfReal> list;
-	LOOP {
-		iam (TableOfReal);
-		list. addItem_ref (me);
-	}
-	autoTableOfReal thee = TablesOfReal_appendMany (& list);
-	praat_new (thee.move(), U"appended");
-END2 }
-
-FORM (TableOfReal_create, U"Create TableOfReal", nullptr) {
-	WORD (U"Name", U"table")
-	NATURAL (U"Number of rows", U"10")
-	NATURAL (U"Number of columns", U"3")
-	OK2
-DO
-	autoTableOfReal me = TableOfReal_create (GET_INTEGER (U"Number of rows"), GET_INTEGER (U"Number of columns"));
-	praat_new (me.move(), GET_STRING (U"Name"));
-END2 }
-
-FORM (TableOfReal_drawAsNumbers, U"Draw as numbers", nullptr) {
-	NATURAL (U"From row", U"1")
-	INTEGER (U"To row", U"0 (= all)")
-	RADIO (U"Format", 3)
-		RADIOBUTTON (U"decimal")
-		RADIOBUTTON (U"exponential")
-		RADIOBUTTON (U"free")
-		RADIOBUTTON (U"rational")
-	NATURAL (U"Precision", U"5")
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawAsNumbers (me, GRAPHICS,
-			GET_INTEGER (U"From row"), GET_INTEGER (U"To row"),
-			GET_INTEGER (U"Format"), GET_INTEGER (U"Precision"));
-	}
-END2 }
-
-FORM (TableOfReal_drawAsNumbers_if, U"Draw as numbers if...", nullptr) {
-	NATURAL (U"From row", U"1")
-	INTEGER (U"To row", U"0 (= all)")
-	RADIO (U"Format", 3)
-		RADIOBUTTON (U"decimal")
-		RADIOBUTTON (U"exponential")
-		RADIOBUTTON (U"free")
-		RADIOBUTTON (U"rational")
-	NATURAL (U"Precision", U"5")
-	LABEL (U"", U"Condition:")
-	TEXTFIELD (U"condition", U"self <> 0")
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawAsNumbers_if (me, GRAPHICS,
-			GET_INTEGER (U"From row"), GET_INTEGER (U"To row"),
-			GET_INTEGER (U"Format"), GET_INTEGER (U"Precision"), GET_STRING (U"condition"), interpreter);
-	}
-END2 }
-
-FORM (TableOfReal_drawAsSquares, U"Draw table as squares", nullptr) {
-	INTEGER (U"From row", U"1")
-	INTEGER (U"To row", U"0")
-	INTEGER (U"From column", U"1")
-	INTEGER (U"To column", U"0")
-	BOOLEAN (U"Garnish", 1)
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawAsSquares (me, GRAPHICS, 
-			GET_INTEGER (U"From row"), GET_INTEGER (U"To row"),
-			GET_INTEGER (U"From column"), GET_INTEGER (U"To column"),
-			GET_INTEGER (U"Garnish"));
-	}
-END2 }
-
-FORM (TableOfReal_drawHorizontalLines, U"Draw horizontal lines", nullptr) {
-	NATURAL (U"From row", U"1")
-	INTEGER (U"To row", U"0 (= all)")
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawHorizontalLines (me, GRAPHICS, GET_INTEGER (U"From row"), GET_INTEGER (U"To row"));
-	}
-END2 }
+	INFO_ONE_END
+}
 
-FORM (TableOfReal_drawLeftAndRightLines, U"Draw left and right lines", nullptr) {
-	NATURAL (U"From row", U"1")
-	INTEGER (U"To row", U"0 (= all)")
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawLeftAndRightLines (me, GRAPHICS, GET_INTEGER (U"From row"), GET_INTEGER (U"To row"));
-	}
-END2 }
+// MARK: Modify
 
-FORM (TableOfReal_drawTopAndBottomLines, U"Draw top and bottom lines", nullptr) {
-	NATURAL (U"From row", U"1")
-	INTEGER (U"To row", U"0 (= all)")
-	OK2
+FORM (MODIFY_Table_appendColumn, U"Table: Append column", nullptr) {
+	WORD4 (label, U"Label", U"newcolumn")
+	OK
 DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawTopAndBottomLines (me, GRAPHICS, GET_INTEGER (U"From row"), GET_INTEGER (U"To row"));
-	}
-END2 }
+	MODIFY_EACH (Table)
+		Table_appendColumn (me, label);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_drawVerticalLines, U"Draw vertical lines", nullptr) {
-	NATURAL (U"From row", U"1")
-	INTEGER (U"To row", U"0 (= all)")
-	OK2
-DO
-	autoPraatPicture picture;
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_drawVerticalLines (me, GRAPHICS, GET_INTEGER (U"From row"), GET_INTEGER (U"To row"));
-	}
-END2 }
+FORM (MODIFY_Table_appendDifferenceColumn, U"Table: Append difference column", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	WORD4 (label, U"Label", U"diff")
+	OK
+DO
+	MODIFY_EACH (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
+		Table_appendDifferenceColumn (me, columnNumber1, columnNumber2, label);
+	MODIFY_EACH_END
+}
 
-DIRECT2 (TableOfReal_extractColumnLabelsAsStrings) {
-	LOOP {
-		iam (TableOfReal);
-		autoStrings thee = TableOfReal_extractColumnLabelsAsStrings (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (MODIFY_Table_appendProductColumn, U"Table: Append product column", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	WORD4 (label, U"Label", U"prod")
+	OK
+DO
+	MODIFY_EACH (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
+		Table_appendProductColumn (me, columnNumber1, columnNumber2, label);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractColumnRanges, U"Extract column ranges", nullptr) {
-	LABEL (U"", U"Create a new TableOfReal from the following columns:")
-	TEXTFIELD (U"ranges", U"1 2")
-	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractColumnRanges (me, GET_STRING (U"ranges"));
-		praat_new (thee.move(), my name, U"_cols");
-	}
-END2 }
+FORM (MODIFY_Table_appendQuotientColumn, U"Table: Append quotient column", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	WORD4 (label, U"Label", U"quot")
+	OK
+DO
+	MODIFY_EACH (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
+		Table_appendQuotientColumn (me, columnNumber1, columnNumber2, label);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractColumnsWhere, U"Extract columns where", nullptr) {
-	LABEL (U"", U"Extract all columns with at least one cell where:")
-	TEXTFIELD (U"condition", U"col mod 3 = 0 ; this example extracts every third column")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractColumnsWhere (me, GET_STRING (U"condition"), interpreter);
-		praat_new (thee.move(), my name, U"_cols");
-	}
-END2 }
+FORM (MODIFY_Table_appendSumColumn, U"Table: Append sum column", nullptr) {
+	WORD4 (column1, U"left Columns", U"")
+	WORD4 (column2, U"right Columns", U"")
+	WORD4 (label, U"Label", U"sum")
+	OK
+DO
+	MODIFY_EACH (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, column1);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, column2);
+		Table_appendSumColumn (me, columnNumber1, columnNumber2, label);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractColumnsWhereLabel, U"Extract column where label", nullptr) {
-	OPTIONMENU_ENUM (U"Extract all columns whose label...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"a")
-	OK2
-DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractColumnsWhereLabel (me, GET_ENUM (kMelder_string, U"Extract all columns whose label..."), text);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
+DIRECT (MODIFY_Table_appendRow) {
+	MODIFY_EACH (Table)
+		Table_appendRow (me);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractColumnsWhereRow, U"Extract columns where row", nullptr) {
-	NATURAL (U"Extract all columns where row...", U"1")
-	OPTIONMENU_ENUM (U"...is...", kMelder_number, DEFAULT)
-	REAL (U"...the value", U"0.0")
-	OK2
+FORM (MODIFY_Table_formula, U"Table: Formula", U"Table: Formula...") {
+	WORD4 (columnLabel, U"Column (label)", U"")
+	TEXTFIELD4 (formula, U"formula", U"abs (self)")
+	OK
 DO
-	long row = GET_INTEGER (U"Extract all columns where row...");
-	double value = GET_REAL (U"...the value");
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractColumnsWhereRow (me, row, GET_ENUM (kMelder_number, U"...is..."), value);
-		praat_new (thee.move(), my name, U"_", row, U"_", lround (value));
-	}
-END2 }
+	MODIFY_EACH_WEAK (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		Table_formula (me, columnNumber, formula, interpreter);
+	MODIFY_EACH_WEAK_END
+}
 
-DIRECT2 (TableOfReal_extractRowLabelsAsStrings) {
-	LOOP {
-		iam (TableOfReal);
-		autoStrings thee = TableOfReal_extractRowLabelsAsStrings (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+FORM (MODIFY_Table_formula_columnRange, U"Table: Formula (column range)", U"Table: Formula...") {
+	WORD4 (fromColumn, U"From column (label)", U"")
+	WORD4 (toColumn, U"To column (label)", U"")
+	TEXTFIELD4 (formula, U"formula", U"log10 (self)")
+	OK
+DO
+	MODIFY_EACH_WEAK (Table)
+		long columnNumber1 = Table_getColumnIndexFromColumnLabel (me, fromColumn);
+		long columnNumber2 = Table_getColumnIndexFromColumnLabel (me, toColumn);
+		Table_formula_columnRange (me, columnNumber1, columnNumber2, formula, interpreter);
+	MODIFY_EACH_WEAK_END
+}
 
-FORM (TableOfReal_extractRowRanges, U"Extract row ranges", nullptr) {
-	LABEL (U"", U"Create a new TableOfReal from the following rows:")
-	TEXTFIELD (U"ranges", U"1 2")
-	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
-	OK2
+FORM (MODIFY_Table_insertColumn, U"Table: Insert column", nullptr) {
+	NATURAL4 (position, U"Position", U"1")
+	WORD4 (label, U"Label", U"newcolumn")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractRowRanges (me, GET_STRING (U"ranges"));
-		praat_new (thee.move(), my name, U"_rows");
-	}
-END2 }
+	MODIFY_EACH (Table)
+		Table_insertColumn (me, position, label);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractRowsWhere, U"Extract rows where", nullptr) {
-	LABEL (U"", U"Extract all rows with at least one cell where:")
-	TEXTFIELD (U"condition", U"row mod 3 = 0 ; this example extracts every third row")
-	OK2
+FORM (MODIFY_Table_insertRow, U"Table: Insert row", nullptr) {
+	NATURAL4 (position, U"Position", U"1")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractRowsWhere (me, GET_STRING (U"condition"), interpreter);
-		praat_new (thee.move(), my name, U"_rows");
-	}
-END2 }
+	MODIFY_EACH (Table)
+		Table_insertRow (me, position);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractRowsWhereColumn, U"Extract rows where column", nullptr) {
-	NATURAL (U"Extract all rows where column...", U"1")
-	OPTIONMENU_ENUM (U"...is...", kMelder_number, DEFAULT)
-	REAL (U"...the value", U"0.0")
-	OK2
+FORM (MODIFY_Table_removeColumn, U"Table: Remove column", nullptr) {
+	WORD4 (columnLabel, U"Column label", U"")
+	OK
 DO
-	long column = GET_INTEGER (U"Extract all rows where column...");
-	double value = GET_REAL (U"...the value");
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractRowsWhereColumn (me,
-			column, GET_ENUM (kMelder_number, U"...is..."), value);
-		praat_new (thee.move(), my name, U"_", column, U"_", lround (value));
-	}
-END2 }
+	MODIFY_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		Table_removeColumn (me, columnNumber);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_extractRowsWhereLabel, U"Extract rows where label", nullptr) {
-	OPTIONMENU_ENUM (U"Extract all rows whose label...", kMelder_string, DEFAULT)
-	SENTENCE (U"...the text", U"a")
-	OK2
+FORM (MODIFY_Table_removeRow, U"Table: Remove row", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
 DO
-	const char32 *text = GET_STRING (U"...the text");
-	LOOP {
-		iam (TableOfReal);
-		autoTableOfReal thee = TableOfReal_extractRowsWhereLabel (me, GET_ENUM (kMelder_string, U"Extract all rows whose label..."), text);
-		praat_new (thee.move(), my name, U"_", text);
-	}
-END2 }
+	MODIFY_EACH (Table)
+		Table_removeRow (me, rowNumber);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_formula, U"TableOfReal: Formula", U"Formula...") {
-	LABEL (U"", U"for row from 1 to nrow do for col from 1 to ncol do self [row, col] = ...")
-	TEXTFIELD (U"formula", U"if col = 5 then self + self [6] else self fi")
-	OK2
+FORM (MODIFY_Table_setColumnLabel_index, U"Set column label", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	SENTENCE4 (newLabel, U"New label", U"")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		try {
-			TableOfReal_formula (me, GET_STRING (U"formula"), interpreter, nullptr);
-			praat_dataChanged (me);
-		} catch (MelderError) {
-			praat_dataChanged (me);
-			throw;
-		}
-	}
-END2 }
+	MODIFY_EACH (Table)
+		Table_setColumnLabel (me, columnNumber, newLabel);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_getColumnIndex, U"Get column index", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = TableOfReal_columnLabelToIndex (me, GET_STRING (U"Column label"));
-		Melder_information (columnNumber);
-	}
-END2 }
-	
-FORM (TableOfReal_getColumnLabel, U"Get column label", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = GET_INTEGER (U"Column number");
-		if (columnNumber > my numberOfColumns) Melder_throw (me, U": column number must not be greater than number of columns.");
-		Melder_information (my columnLabels ? my columnLabels [columnNumber] : U"");
-	}
-END2 }
-	
-FORM (TableOfReal_getColumnMean_index, U"Get column mean", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = GET_INTEGER (U"Column number");
-		if (columnNumber > my numberOfColumns) Melder_throw (me, U": column number must not be greater than number of columns.");
-		double columnMean = TableOfReal_getColumnMean (me, columnNumber);
-		Melder_informationReal (columnMean, nullptr);
-	}
-END2 }
-	
-FORM (TableOfReal_getColumnMean_label, U"Get column mean", nullptr) {
-	SENTENCE (U"Column label", U"")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = TableOfReal_columnLabelToIndex (me, GET_STRING (U"Column label"));
-		if (columnNumber == 0) Melder_throw (me, U": column label does not exist.");
-		double columnMean = TableOfReal_getColumnMean (me, columnNumber);
-		Melder_informationReal (columnMean, nullptr);
-	}
-END2 }
-	
-FORM (TableOfReal_getColumnStdev_index, U"Get column standard deviation", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = GET_INTEGER (U"Column number");
-		if (columnNumber > my numberOfColumns) Melder_throw (me, U": column number must not be greater than number of columns.");
-		double stdev = TableOfReal_getColumnStdev (me, columnNumber);
-		Melder_informationReal (stdev, nullptr);
-	}
-END2 }
-	
-FORM (TableOfReal_getColumnStdev_label, U"Get column standard deviation", nullptr) {
-	SENTENCE (U"Column label", U"1")
-	OK2
+FORM (MODIFY_Table_setColumnLabel_label, U"Set column label", nullptr) {
+	SENTENCE4 (oldLabel, U"Old label", U"")
+	WORD4 (newLabel, U"New label", U"")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = TableOfReal_columnLabelToIndex (me, GET_STRING (U"Column label"));
-		if (columnNumber == 0) Melder_throw (me, U": column label does not exist.");
-		double stdev = TableOfReal_getColumnStdev (me, columnNumber);
-		Melder_informationReal (stdev, nullptr);
-	}
-END2 }
-
-DIRECT2 (TableOfReal_getNumberOfColumns) {
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (my numberOfColumns);
-	}
-END2 }
-
-DIRECT2 (TableOfReal_getNumberOfRows) {
-	LOOP {
-		iam (TableOfReal);
-		Melder_information (my numberOfRows);
-	}
-END2 }
+	MODIFY_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, oldLabel);
+		Table_setColumnLabel (me, columnNumber, newLabel);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_getRowIndex, U"Get row index", nullptr) {
-	SENTENCE (U"Row label", U"")
-	OK2
+FORM (MODIFY_Table_setNumericValue, U"Table: Set numeric value", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	WORD4 (columnLabel, U"Column label", U"")
+	REAL_OR_UNDEFINED4 (numericValue, U"Numeric value", U"1.5")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		long rowNumber = TableOfReal_rowLabelToIndex (me, GET_STRING (U"Row label"));
-		Melder_information (rowNumber);
-	}
-END2 }
-	
-FORM (TableOfReal_getRowLabel, U"Get row label", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long rowNumber = GET_INTEGER (U"Row number");
-		if (rowNumber > my numberOfRows) Melder_throw (me, U": row number must not be greater than number of rows.");
-		Melder_information (my rowLabels ? my rowLabels [rowNumber] : U"");
-	}
-END2 }
+	MODIFY_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		Table_setNumericValue (me, rowNumber, columnNumber, numericValue);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_getValue, U"Get value", nullptr) {
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
-	OK2
+FORM (MODIFY_Table_setStringValue, U"Table: Set string value", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	WORD4 (columnLabel, U"Column label", U"")
+	SENTENCE4 (stringValue, U"String value", U"xx")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		long rowNumber = GET_INTEGER (U"Row number"), columnNumber = GET_INTEGER (U"Column number");
-		if (rowNumber > my numberOfRows) Melder_throw (me, U": row number must not exceed number of rows.");
-		if (columnNumber > my numberOfColumns) Melder_throw (me, U": column number must not exceed number of columns.");
-		Melder_informationReal (my data [rowNumber] [columnNumber], nullptr);
-	}
-END2 }
+	MODIFY_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnLabel);
+		Table_setStringValue (me, rowNumber, columnNumber, stringValue);
+	MODIFY_EACH_END
+}
 
-DIRECT2 (TableOfReal_help) {
-	Melder_help (U"TableOfReal");
-END2 }
+DIRECT (MODIFY_Table_randomizeRows) {
+	MODIFY_EACH (Table)
+		Table_randomizeRows (me);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_insertColumn, U"Insert column", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_insertColumn (me, GET_INTEGER (U"Column number"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (MODIFY_Table_reflectRows) {
+	MODIFY_EACH (Table)
+		Table_reflectRows (me);
+	MODIFY_EACH_END
+}
 
-FORM (TableOfReal_insertRow, U"Insert row", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
+FORM (MODIFY_Table_sortRows, U"Table: Sort rows", nullptr) {
+	LABEL (U"", U"One or more column labels for sorting:")
+	TEXTFIELD4 (columnLabels, U"columnLabels", U"dialect gender name")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_insertRow (me, GET_INTEGER (U"Row number"));
-		praat_dataChanged (me);
-	}
-END2 }
+	MODIFY_EACH (Table)
+		Table_sortRows_string (me, columnLabels);
+	MODIFY_EACH_END
+}
 
-FORM_READ2 (TableOfReal_readFromHeaderlessSpreadsheetFile, U"Read TableOfReal from headerless spreadsheet file", nullptr, true) {
-	autoTableOfReal me = TableOfReal_readFromHeaderlessSpreadsheetFile (file);
-	praat_newWithFile (me.move(), file, MelderFile_name (file));
-END2 }
+// MARK: Convert
 
-FORM (TableOfReal_removeColumn, U"Remove column", nullptr) {
-	NATURAL (U"Column number", U"1")
-	OK2
+FORM (NEW_Table_collapseRows, U"Table: Collapse rows", nullptr) {
+	LABEL (U"", U"Columns with factors (independent variables):")
+	TEXTFIELD4 (factors, U"factors", U"speaker dialect age vowel")
+	LABEL (U"", U"Columns to sum:")
+	TEXTFIELD4 (columnsToSum, U"columnsToSum", U"number cost")
+	LABEL (U"", U"Columns to average:")
+	TEXTFIELD4 (columnsToAverage, U"columnsToAverage", U"price")
+	LABEL (U"", U"Columns to medianize:")
+	TEXTFIELD4 (columnsToMedianize, U"columnsToMedianize", U"vot")
+	LABEL (U"", U"Columns to average logarithmically:")
+	TEXTFIELD4 (columnsToAverageLogarithmically, U"columnsToAverageLogarithmically", U"duration")
+	LABEL (U"", U"Columns to medianize logarithmically:")
+	TEXTFIELD4 (columnsToMedianizeLogarithmically, U"columnsToMedianizeLogarithmically", U"F0 F1 F2 F3")
+	LABEL (U"", U"Columns not mentioned above will be ignored.")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_removeColumn (me, GET_INTEGER (U"Column number"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (Table)
+		autoTable result = Table_collapseRows (me, factors, columnsToSum, columnsToAverage,
+			columnsToMedianize, columnsToAverageLogarithmically, columnsToMedianizeLogarithmically);
+	CONVERT_EACH_END (my name, U"_pooled")
+}
 
-FORM (TableOfReal_removeRow, U"Remove row", nullptr) {
-	NATURAL (U"Row number", U"1")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_removeRow (me, GET_INTEGER (U"Row number"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (NEW1_Tables_append) {
+	CONVERT_LIST (Table)
+		autoTable result = Tables_append (& list);
+	CONVERT_LIST_END (U"appended")
+}
 
-FORM (TableOfReal_setColumnLabel_index, U"Set column label", nullptr) {
-	NATURAL (U"Column number", U"1")
-	SENTENCE (U"Label", U"")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_setColumnLabel (me, GET_INTEGER (U"Column number"), GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+FORM (NEW_Table_extractRowsWhereColumn_number, U"Table: Extract rows where column (number)", nullptr) {
+	WORD4 (extractAllRowsWhereColumn___, U"Extract all rows where column...", U"")
+	RADIO_ENUM4 (___is___, U"...is...", kMelder_number, DEFAULT)
+	REAL4 (___theNumber, U"...the number", U"0.0")
+	OK
+DO
+	CONVERT_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, extractAllRowsWhereColumn___);
+		autoTable result = Table_extractRowsWhereColumn_number (me, columnNumber, ___is___, ___theNumber);
+	CONVERT_EACH_END (my name, U"_", Table_messageColumn (me, columnNumber), U"_",
+		NUMdefined (___theNumber) ? Melder_integer (lround (___theNumber)) : U"undefined")
+}
 
-FORM (TableOfReal_setColumnLabel_label, U"Set column label", nullptr) {
-	SENTENCE (U"Old label", U"")
-	SENTENCE (U"New label", U"")
-	OK2
+FORM (NEW_Table_extractRowsWhereColumn_text, U"Table: Extract rows where column (text)", nullptr) {
+	WORD4 (extractAllRowsWhereColumn___, U"Extract all rows where column...", U"")
+	OPTIONMENU_ENUM4 (___, U"...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"hi")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		long columnNumber = TableOfReal_columnLabelToIndex (me, GET_STRING (U"Old label"));
-		TableOfReal_setColumnLabel (me, columnNumber, GET_STRING (U"New label"));
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, extractAllRowsWhereColumn___);
+		autoTable result = Table_extractRowsWhereColumn_string (me, columnNumber, ___, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
 
-FORM (TableOfReal_setRowLabel_index, U"Set row label", nullptr) {
-	NATURAL (U"Row number", U"1")
-	SENTENCE (U"Label", U"")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_setRowLabel (me, GET_INTEGER (U"Row number"), GET_STRING (U"Label"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (NEW_Table_transpose) {
+	CONVERT_EACH (Table)
+		autoTable result = Table_transpose (me);
+	CONVERT_EACH_END (my name, U"_transposed");
+}
 
-FORM (TableOfReal_setValue, U"Set value", U"TableOfReal: Set value...") {
-	NATURAL (U"Row number", U"1")
-	NATURAL (U"Column number", U"1")
-	REAL_OR_UNDEFINED (U"New value", U"0.0")
-	OK2
+FORM (NEW_Table_rowsToColumns, U"Table: Rows to columns", nullptr) {
+	LABEL (U"", U"Columns with factors (independent variables):")
+	TEXTFIELD4 (factors, U"factors", U"dialect gender speaker")
+	WORD4 (columnToTranspose, U"Column to transpose", U"vowel")
+	LABEL (U"", U"Columns to expand:")
+	TEXTFIELD4 (columnsToExpand, U"columnsToExpand", U"duration F0 F1 F2 F3")
+	LABEL (U"", U"Columns not mentioned above will be ignored.")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		long rowNumber = GET_INTEGER (U"Row number"), columnNumber = GET_INTEGER (U"Column number");
-		if (rowNumber > my numberOfRows) Melder_throw (me, U": row number too large.");
-		if (columnNumber > my numberOfColumns) Melder_throw (me, U": column number too large.");
-		my data [rowNumber] [columnNumber] = GET_REAL (U"New value");
-		praat_dataChanged (me);
-	}
-END2 }
+	CONVERT_EACH (Table)
+		long columnNumber = Table_getColumnIndexFromColumnLabel (me, columnToTranspose);
+		autoTable result = Table_rowsToColumns (me, factors, columnNumber, columnsToExpand);
+	CONVERT_EACH_END (my name, U"_nested")
+}
 
-FORM (TableOfReal_setRowLabel_label, U"Set row label", nullptr) {
-	SENTENCE (U"Old label", U"")
-	SENTENCE (U"New label", U"")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		long rowNumber = TableOfReal_rowLabelToIndex (me, GET_STRING (U"Old label"));
-		TableOfReal_setRowLabel (me, rowNumber, GET_STRING (U"New label"));
-		praat_dataChanged (me);
-	}
-END2 }
+DIRECT (NEW_Table_to_LinearRegression) {
+	CONVERT_EACH (Table)
+		autoLinearRegression result = Table_to_LinearRegression (me);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_sortByColumn, U"Sort rows by column", nullptr) {
-	INTEGER (U"Column", U"1")
-	INTEGER (U"Secondary column", U"0")
-	OK2
-DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_sortByColumn (me, GET_INTEGER (U"Column"), GET_INTEGER (U"Secondary column"));
-		praat_dataChanged (me);
-	}
-END2 }
+FORM (NEW_Table_to_LogisticRegression, U"Table: To LogisticRegression", nullptr) {
+	LABEL (U"", U"Factors (column names):")
+	TEXTFIELD4 (factors, U"factors", U"F0 F1 duration")
+	WORD4 (dependent1, U"Dependent 1 (column name)", U"e")
+	WORD4 (dependent2, U"Dependent 2 (column name)", U"i")
+	OK
+DO
+	CONVERT_EACH (Table)
+		autoLogisticRegression result = Table_to_LogisticRegression (me, factors, dependent1, dependent2);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_sortByLabel, U"Sort rows by label", nullptr) {
-	LABEL (U"", U"Secondary sorting keys:")
-	INTEGER (U"Column1", U"1")
-	INTEGER (U"Column2", U"0")
-	OK2
+FORM (NEW_Table_to_TableOfReal, U"Table: Down to TableOfReal", nullptr) {
+	WORD4 (columnForRowLabels, U"Column for row labels", U"")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_sortByLabel (me, GET_INTEGER (U"Column1"), GET_INTEGER (U"Column2"));
-		praat_dataChanged (me);
-	}
-END2 }
-
-DIRECT2 (TableOfReal_to_Matrix) {
-	LOOP {
-		iam (TableOfReal);
-		autoMatrix thee = TableOfReal_to_Matrix (me);
-		praat_new (thee.move(), my name);
-	}
-END2 }
+	CONVERT_EACH (Table)
+		long columnNumber = Table_findColumnIndexFromColumnLabel (me, columnForRowLabels);
+		autoTableOfReal result = Table_to_TableOfReal (me, columnNumber);
+	CONVERT_EACH_END (my name)
+}
 
-FORM (TableOfReal_to_Table, U"TableOfReal: To Table", nullptr) {
-	SENTENCE (U"Label of first column", U"rowLabel")
-	OK2
+FORM (NEW1_TableOfReal_create, U"Create TableOfReal", nullptr) {
+	WORD4 (name, U"Name", U"table")
+	NATURAL4 (numberOfRows, U"Number of rows", U"10")
+	NATURAL4 (numberOfColumns, U"Number of columns", U"3")
+	OK
 DO
-	LOOP {
-		iam (TableOfReal);
-		autoTable thee = TableOfReal_to_Table (me, GET_STRING (U"Label of first column"));
-		praat_new (thee.move(), my name);
-	}
-END2 }
-
-FORM_WRITE2 (TableOfReal_writeToHeaderlessSpreadsheetFile, U"Save TableOfReal as spreadsheet", 0, U"txt") {
-	LOOP {
-		iam (TableOfReal);
-		TableOfReal_writeToHeaderlessSpreadsheetFile (me, file);
-	}
-END2 }
-
+	CREATE_ONE
+		autoTableOfReal result = TableOfReal_create (numberOfRows, numberOfColumns);
+	CREATE_ONE_END (name)
+}
 
-DIRECT2 (StatisticsTutorial) {
-	Melder_help (U"Statistics");
-END2 }
+FORM_READ (READ1_TableOfReal_readFromHeaderlessSpreadsheetFile, U"Read TableOfReal from headerless spreadsheet file", nullptr, true) {
+	READ_ONE
+		autoTableOfReal result = TableOfReal_readFromHeaderlessSpreadsheetFile (file);
+	READ_ONE_END
+}
 
 static bool isTabSeparated_8bit (int nread, const char *header) {
 	for (long i = 0; i < nread; i ++) {
@@ -1733,69 +1053,6 @@ static autoDaata tabSeparatedFileRecognizer (int nread, const char *header, Meld
 	return Table_readFromCharacterSeparatedTextFile (file, '\t');
 }
 
-void praat_TableOfReal_init (ClassInfo klas);   // buttons for TableOfReal and for its subclasses
-void praat_TableOfReal_init (ClassInfo klas) {
-	praat_addAction1 (klas, 1, U"Save as headerless spreadsheet file...", nullptr, 0, DO_TableOfReal_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (klas, 1, U"Write to headerless spreadsheet file...", nullptr, praat_HIDDEN, DO_TableOfReal_writeToHeaderlessSpreadsheetFile);
-	praat_addAction1 (klas, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 0, U"Draw as numbers...", nullptr, 1, DO_TableOfReal_drawAsNumbers);
-		praat_addAction1 (klas, 0, U"Draw as numbers if...", nullptr, 1, DO_TableOfReal_drawAsNumbers_if);
-		praat_addAction1 (klas, 0, U"Draw as squares...", nullptr, 1, DO_TableOfReal_drawAsSquares);
-		praat_addAction1 (klas, 0, U"-- draw lines --", nullptr, 1, 0);
-		praat_addAction1 (klas, 0, U"Draw vertical lines...", nullptr, 1, DO_TableOfReal_drawVerticalLines);
-		praat_addAction1 (klas, 0, U"Draw horizontal lines...", nullptr, 1, DO_TableOfReal_drawHorizontalLines);
-		praat_addAction1 (klas, 0, U"Draw left and right lines...", nullptr, 1, DO_TableOfReal_drawLeftAndRightLines);
-		praat_addAction1 (klas, 0, U"Draw top and bottom lines...", nullptr, 1, DO_TableOfReal_drawTopAndBottomLines);
-	praat_addAction1 (klas, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 1, U"Get number of rows", nullptr, 1, DO_TableOfReal_getNumberOfRows);
-		praat_addAction1 (klas, 1, U"Get number of columns", nullptr, 1, DO_TableOfReal_getNumberOfColumns);
-		praat_addAction1 (klas, 1, U"Get row label...", nullptr, 1, DO_TableOfReal_getRowLabel);
-		praat_addAction1 (klas, 1, U"Get column label...", nullptr, 1, DO_TableOfReal_getColumnLabel);
-		praat_addAction1 (klas, 1, U"Get row index...", nullptr, 1, DO_TableOfReal_getRowIndex);
-		praat_addAction1 (klas, 1, U"Get column index...", nullptr, 1, DO_TableOfReal_getColumnIndex);
-		praat_addAction1 (klas, 1, U"-- get value --", nullptr, 1, nullptr);
-		praat_addAction1 (klas, 1, U"Get value...", nullptr, 1, DO_TableOfReal_getValue);
-		if (klas == classTableOfReal) {
-			praat_addAction1 (klas, 1, U"-- get statistics --", nullptr, 1, nullptr);
-			praat_addAction1 (klas, 1, U"Get column mean (index)...", nullptr, 1, DO_TableOfReal_getColumnMean_index);
-			praat_addAction1 (klas, 1, U"Get column mean (label)...", nullptr, 1, DO_TableOfReal_getColumnMean_label);
-			praat_addAction1 (klas, 1, U"Get column stdev (index)...", nullptr, 1, DO_TableOfReal_getColumnStdev_index);
-			praat_addAction1 (klas, 1, U"Get column stdev (label)...", nullptr, 1, DO_TableOfReal_getColumnStdev_label);
-		}
-	praat_addAction1 (klas, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 0, U"Formula...", nullptr, 1, DO_TableOfReal_formula);
-		praat_addAction1 (klas, 0, U"Set value...", nullptr, 1, DO_TableOfReal_setValue);
-		praat_addAction1 (klas, 0, U"Sort by label...", nullptr, 1, DO_TableOfReal_sortByLabel);
-		praat_addAction1 (klas, 0, U"Sort by column...", nullptr, 1, DO_TableOfReal_sortByColumn);
-		praat_addAction1 (klas, 0, U"-- structure --", nullptr, 1, nullptr);
-		praat_addAction1 (klas, 0, U"Remove row (index)...", nullptr, 1, DO_TableOfReal_removeRow);
-		praat_addAction1 (klas, 0, U"Remove column (index)...", nullptr, 1, DO_TableOfReal_removeColumn);
-		praat_addAction1 (klas, 0, U"Insert row (index)...", nullptr, 1, DO_TableOfReal_insertRow);
-		praat_addAction1 (klas, 0, U"Insert column (index)...", nullptr, 1, DO_TableOfReal_insertColumn);
-		praat_addAction1 (klas, 0, U"-- set --", nullptr, 1, nullptr);
-		praat_addAction1 (klas, 0, U"Set row label (index)...", nullptr, 1, DO_TableOfReal_setRowLabel_index);
-		praat_addAction1 (klas, 0, U"Set row label (label)...", nullptr, 1, DO_TableOfReal_setRowLabel_label);
-		praat_addAction1 (klas, 0, U"Set column label (index)...", nullptr, 1, DO_TableOfReal_setColumnLabel_index);
-		praat_addAction1 (klas, 0, U"Set column label (label)...", nullptr, 1, DO_TableOfReal_setColumnLabel_label);
-	praat_addAction1 (klas, 0, U"Synthesize -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 0, U"Append", nullptr, 1, DO_TablesOfReal_append);
-	praat_addAction1 (klas, 0, U"Extract part -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 0, U"Extract row ranges...", nullptr, 1, DO_TableOfReal_extractRowRanges);
-		praat_addAction1 (klas, 0, U"Extract rows where column...", nullptr, 1, DO_TableOfReal_extractRowsWhereColumn);
-		praat_addAction1 (klas, 0, U"Extract rows where label...", nullptr, 1, DO_TableOfReal_extractRowsWhereLabel);
-		praat_addAction1 (klas, 0, U"Extract rows where...", nullptr, 1, DO_TableOfReal_extractRowsWhere);
-		praat_addAction1 (klas, 0, U"Extract column ranges...", nullptr, 1, DO_TableOfReal_extractColumnRanges);
-		praat_addAction1 (klas, 0, U"Extract columns where row...", nullptr, 1, DO_TableOfReal_extractColumnsWhereRow);
-		praat_addAction1 (klas, 0, U"Extract columns where label...", nullptr, 1, DO_TableOfReal_extractColumnsWhereLabel);
-		praat_addAction1 (klas, 0, U"Extract columns where...", nullptr, 1, DO_TableOfReal_extractColumnsWhere);
-	praat_addAction1 (klas, 0, U"Extract -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 0, U"Extract row labels as Strings", nullptr, 1, DO_TableOfReal_extractRowLabelsAsStrings);
-		praat_addAction1 (klas, 0, U"Extract column labels as Strings", nullptr, 1, DO_TableOfReal_extractColumnLabelsAsStrings);
-	praat_addAction1 (klas, 0, U"Convert -", nullptr, 0, nullptr);
-		praat_addAction1 (klas, 0, U"To Table...", nullptr, 1, DO_TableOfReal_to_Table);
-		praat_addAction1 (klas, 0, U"To Matrix", nullptr, 1, DO_TableOfReal_to_Matrix);
-}
-
 void praat_uvafon_stat_init ();
 void praat_uvafon_stat_init () {
 
@@ -1807,127 +1064,126 @@ void praat_uvafon_stat_init () {
 	structTableEditor :: f_preferences ();
 
 	praat_addMenuCommand (U"Objects", U"New", U"Tables", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Table with column names...", nullptr, 1, DO_Table_createWithColumnNames);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Table without column names...", nullptr, 1, DO_Table_createWithoutColumnNames);
-		praat_addMenuCommand (U"Objects", U"New", U"Create Table...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Table_createWithoutColumnNames);
-		praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal...", nullptr, 1, DO_TableOfReal_create);
-
-	praat_addMenuCommand (U"Objects", U"Open", U"Read TableOfReal from headerless spreadsheet file...", nullptr, 0, DO_TableOfReal_readFromHeaderlessSpreadsheetFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from tab-separated file...", nullptr, 0, DO_Table_readFromTabSeparatedFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from comma-separated file...", nullptr, 0, DO_Table_readFromCommaSeparatedFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from whitespace-separated file...", nullptr, 0, DO_Table_readFromTableFile);
-	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from table file...", nullptr, praat_HIDDEN, DO_Table_readFromTableFile);
-
-	praat_addAction1 (classDistributions, 0, U"Distributions help", nullptr, 0, DO_Distributions_help);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Table with column names...", nullptr, 1, NEW1_Table_createWithColumnNames);
+		praat_addMenuCommand (U"Objects", U"New", U"Create Table without column names...", nullptr, 1, NEW1_Table_createWithoutColumnNames);
+		praat_addMenuCommand (U"Objects", U"New",   U"Create Table...", U"*Create Table without column names...", praat_DEPTH_1 | praat_DEPRECATED_2006, NEW1_Table_createWithoutColumnNames);
+	praat_addMenuCommand (U"Objects", U"New", U"Create TableOfReal...", nullptr, 1, NEW1_TableOfReal_create);
+
+	praat_addMenuCommand (U"Objects", U"Open", U"Read TableOfReal from headerless spreadsheet file...", nullptr, 0, READ1_TableOfReal_readFromHeaderlessSpreadsheetFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from tab-separated file...", nullptr, 0, READ1_Table_readFromTabSeparatedFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from comma-separated file...", nullptr, 0, READ1_Table_readFromCommaSeparatedFile);
+	praat_addMenuCommand (U"Objects", U"Open", U"Read Table from whitespace-separated file...", nullptr, 0, READ1_Table_readFromTableFile);
+	praat_addMenuCommand (U"Objects", U"Open",   U"Read Table from table file...", U"*Read Table from whitespace-separated file...", praat_DEPRECATED_2011, READ1_Table_readFromTableFile);
+
+	praat_addAction1 (classDistributions, 0, U"Distributions help", nullptr, 0, HELP_Distributions_help);
 	praat_TableOfReal_init (classDistributions);
-	praat_addAction1 (classDistributions, 1, U"Get probability (label)...", U"Get value...", 1, DO_Distributions_getProbability);
+	praat_addAction1 (classDistributions, 1, U"Get probability (label)...", U"Get value...", 1, REAL_Distributions_getProbability);
 	praat_addAction1 (classDistributions, 0, U"-- get from two --", U"Get probability (label)...", 1, nullptr);
-	praat_addAction1 (classDistributions, 2, U"Get mean absolute difference...", U"-- get from two --", 1, DO_Distributionses_getMeanAbsoluteDifference);
+	praat_addAction1 (classDistributions, 2, U"Get mean absolute difference...", U"-- get from two --", 1, REAL_Distributionses_getMeanAbsoluteDifference);
 	praat_addAction1 (classDistributions, 0, U"-- add --", U"Append", 1, nullptr);
-	praat_addAction1 (classDistributions, 0, U"Add", U"-- add --", 1, DO_Distributionses_add);
+	praat_addAction1 (classDistributions, 0, U"Add", U"-- add --", 1, NEW1_Distributionses_add);
 	praat_addAction1 (classDistributions, 0, U"Generate", nullptr, 0, nullptr);   // FIXME no hyphen?
-		praat_addAction1 (classDistributions, 0, U"To Strings...", nullptr, 0, DO_Distributions_to_Strings);
-		praat_addAction1 (classDistributions, 0, U"To Strings (exact)...", nullptr, 0, DO_Distributions_to_Strings_exact);
+		praat_addAction1 (classDistributions, 0, U"To Strings...", nullptr, 0, NEW_Distributions_to_Strings);
+		praat_addAction1 (classDistributions, 0, U"To Strings (exact)...", nullptr, 0, NEW_Distributions_to_Strings_exact);
 
-	praat_addAction1 (classLogisticRegression, 0, U"Draw boundary...", nullptr, 0, DO_LogisticRegression_drawBoundary);
+	praat_addAction1 (classLogisticRegression, 0, U"Draw boundary...", nullptr, 0, GRAPHICS_LogisticRegression_drawBoundary);
 
-	praat_addAction1 (classPairDistribution, 0, U"PairDistribution help", nullptr, 0, DO_PairDistribution_help);
-	praat_addAction1 (classPairDistribution, 0, U"To Table", nullptr, 0, DO_PairDistribution_to_Table);
-	praat_addAction1 (classPairDistribution, 1, U"To Stringses...", nullptr, 0, DO_PairDistribution_to_Stringses);
+	praat_addAction1 (classPairDistribution, 0, U"PairDistribution help", nullptr, 0, HELP_PairDistribution_help);
+	praat_addAction1 (classPairDistribution, 0, U"To Table", nullptr, 0, NEW_PairDistribution_to_Table);
+	praat_addAction1 (classPairDistribution, 1, U"To Stringses...", nullptr, 0, NEW2_PairDistribution_to_Stringses);
 	praat_addAction1 (classPairDistribution, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classPairDistribution, 1, U"Get number of pairs", nullptr, 1, DO_PairDistribution_getNumberOfPairs);
-		praat_addAction1 (classPairDistribution, 1, U"Get string1...", nullptr, 1, DO_PairDistribution_getString1);
-		praat_addAction1 (classPairDistribution, 1, U"Get string2...", nullptr, 1, DO_PairDistribution_getString2);
-		praat_addAction1 (classPairDistribution, 1, U"Get weight...", nullptr, 1, DO_PairDistribution_getWeight);
+		praat_addAction1 (classPairDistribution, 1, U"Get number of pairs", nullptr, 1, INTEGER_PairDistribution_getNumberOfPairs);
+		praat_addAction1 (classPairDistribution, 1, U"Get string1...", nullptr, 1, STRING_PairDistribution_getString1);
+		praat_addAction1 (classPairDistribution, 1, U"Get string2...", nullptr, 1, STRING_PairDistribution_getString2);
+		praat_addAction1 (classPairDistribution, 1, U"Get weight...", nullptr, 1, REAL_PairDistribution_getWeight);
 		praat_addAction1 (classPairDistribution, 1, U"-- get fraction correct --", nullptr, 1, nullptr);
-		praat_addAction1 (classPairDistribution, 1, U"Get fraction correct (maximum likelihood)", nullptr, 1, DO_PairDistribution_getFractionCorrect_maximumLikelihood);
-		praat_addAction1 (classPairDistribution, 1, U"Get fraction correct (probability matching)", nullptr, 1, DO_PairDistribution_getFractionCorrect_probabilityMatching);
+		praat_addAction1 (classPairDistribution, 1, U"Get fraction correct (maximum likelihood)", nullptr, 1, REAL_PairDistribution_getFractionCorrect_maximumLikelihood);
+		praat_addAction1 (classPairDistribution, 1, U"Get fraction correct (probability matching)", nullptr, 1, REAL_PairDistribution_getFractionCorrect_probabilityMatching);
 	praat_addAction1 (classPairDistribution, 0, U"Modify -", nullptr, 0, nullptr);
-	praat_addAction1 (classPairDistribution, 0, U"Remove zero weights", nullptr, 1, DO_PairDistribution_removeZeroWeights);
-	praat_addAction1 (classPairDistribution, 0, U"Swap inputs and outputs", nullptr, 1, DO_PairDistribution_swapInputsAndOutputs);
-
-	praat_addAction1 (classTable, 0, U"Table help", nullptr, 0, DO_Table_help);
-	praat_addAction1 (classTable, 1, U"Save as tab-separated file...", nullptr, 0, DO_Table_writeToTabSeparatedFile);
-	praat_addAction1 (classTable, 1, U"Save as comma-separated file...", nullptr, 0, DO_Table_writeToCommaSeparatedFile);
-	praat_addAction1 (classTable, 1, U"Save as table file...", nullptr, praat_HIDDEN, DO_Table_writeToTabSeparatedFile);
-	praat_addAction1 (classTable, 1, U"Write to table file...", nullptr, praat_HIDDEN, DO_Table_writeToTabSeparatedFile);
-	praat_addAction1 (classTable, 1, U"View & Edit", nullptr, praat_ATTRACTIVE, DO_Table_edit);
-	praat_addAction1 (classTable, 1, U"Edit", nullptr, praat_HIDDEN, DO_Table_edit);
+	praat_addAction1 (classPairDistribution, 0, U"Remove zero weights", nullptr, 1, MODIFY_PairDistribution_removeZeroWeights);
+	praat_addAction1 (classPairDistribution, 0, U"Swap inputs and outputs", nullptr, 1, MODIFY_PairDistribution_swapInputsAndOutputs);
+
+	praat_addAction1 (classTable, 0, U"Table help", nullptr, 0, HELP_Table_help);
+	praat_addAction1 (classTable, 1, U"Save as tab-separated file...", nullptr, 0, SAVE_Table_writeToTabSeparatedFile);
+	praat_addAction1 (classTable, 1, U"Save as table file...", nullptr, praat_DEPRECATED_2011, SAVE_Table_writeToTabSeparatedFile);
+	praat_addAction1 (classTable, 1,   U"Write to table file...", nullptr, praat_DEPRECATED_2011, SAVE_Table_writeToTabSeparatedFile);
+	praat_addAction1 (classTable, 1, U"Save as comma-separated file...", nullptr, 0, SAVE_Table_writeToCommaSeparatedFile);
+	praat_addAction1 (classTable, 1, U"View & Edit", nullptr, praat_ATTRACTIVE | praat_NO_API, WINDOW_Table_viewAndEdit);
+	praat_addAction1 (classTable, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011 | praat_NO_API, WINDOW_Table_viewAndEdit);
 	praat_addAction1 (classTable, 0, U"Draw -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 0, U"Scatter plot...", nullptr, 1, DO_Table_scatterPlot);
-		praat_addAction1 (classTable, 0, U"Scatter plot (mark)...", nullptr, 1, DO_Table_scatterPlot_mark);
-		praat_addAction1 (classTable, 0, U"Draw ellipse (standard deviation)...", nullptr, 1, DO_Table_drawEllipse);
+		praat_addAction1 (classTable, 0, U"Scatter plot...", nullptr, 1, GRAPHICS_Table_scatterPlot);
+		praat_addAction1 (classTable, 0, U"Scatter plot (mark)...", nullptr, 1, GRAPHICS_Table_scatterPlot_mark);
+		praat_addAction1 (classTable, 0, U"Draw ellipse (standard deviation)...", nullptr, 1, GRAPHICS_Table_drawEllipse);
 	praat_addAction1 (classTable, 0, U"Query -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 1, U"List...", nullptr, 1, DO_Table_list);
+		praat_addAction1 (classTable, 1, U"List...", nullptr, 1, LIST_Table_list);
 		praat_addAction1 (classTable, 1, U"-- get structure --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 1, U"Get number of rows", nullptr, 1, DO_Table_getNumberOfRows);
-		praat_addAction1 (classTable, 1, U"Get number of columns", nullptr, 1, DO_Table_getNumberOfColumns);
-		praat_addAction1 (classTable, 1, U"Get column label...", nullptr, 1, DO_Table_getColumnLabel);
-		praat_addAction1 (classTable, 1, U"Get column index...", nullptr, 1, DO_Table_getColumnIndex);
+		praat_addAction1 (classTable, 1, U"Get number of rows", nullptr, 1, INTEGER_Table_getNumberOfRows);
+		praat_addAction1 (classTable, 1, U"Get number of columns", nullptr, 1, INTEGER_Table_getNumberOfColumns);
+		praat_addAction1 (classTable, 1, U"Get column label...", nullptr, 1, STRING_Table_getColumnLabel);
+		praat_addAction1 (classTable, 1, U"Get column index...", nullptr, 1, INTEGER_Table_getColumnIndex);
 		praat_addAction1 (classTable, 1, U"-- get value --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 1, U"Get value...", nullptr, 1, DO_Table_getValue);
-		praat_addAction1 (classTable, 1, U"Search column...", nullptr, 1, DO_Table_searchColumn);
+		praat_addAction1 (classTable, 1, U"Get value...", nullptr, 1, STRING_Table_getValue);
+		praat_addAction1 (classTable, 1, U"Search column...", nullptr, 1, INTEGER_Table_searchColumn);
 		praat_addAction1 (classTable, 1, U"-- statistics --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 1, U"Statistics tutorial", nullptr, 1, DO_StatisticsTutorial);
+		praat_addAction1 (classTable, 1, U"Statistics tutorial", nullptr, 1, HELP_StatisticsTutorial);
 		praat_addAction1 (classTable, 1, U"-- get stats --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 1, U"Get quantile...", nullptr, 1, DO_Table_getQuantile);
-		praat_addAction1 (classTable, 1, U"Get minimum...", nullptr, 1, DO_Table_getMinimum);
-		praat_addAction1 (classTable, 1, U"Get maximum...", nullptr, 1, DO_Table_getMaximum);
-		praat_addAction1 (classTable, 1, U"Get mean...", nullptr, 1, DO_Table_getMean);
-		praat_addAction1 (classTable, 1, U"Get group mean...", nullptr, 1, DO_Table_getGroupMean);
-		praat_addAction1 (classTable, 1, U"Get standard deviation...", nullptr, 1, DO_Table_getStandardDeviation);
+		praat_addAction1 (classTable, 1, U"Get quantile...", nullptr, 1, REAL_Table_getQuantile);
+		praat_addAction1 (classTable, 1, U"Get minimum...", nullptr, 1, REAL_Table_getMinimum);
+		praat_addAction1 (classTable, 1, U"Get maximum...", nullptr, 1, REAL_Table_getMaximum);
+		praat_addAction1 (classTable, 1, U"Get mean...", nullptr, 1, REAL_Table_getMean);
+		praat_addAction1 (classTable, 1, U"Get group mean...", nullptr, 1, REAL_Table_getGroupMean);
+		praat_addAction1 (classTable, 1, U"Get standard deviation...", nullptr, 1, REAL_Table_getStandardDeviation);
 		praat_addAction1 (classTable, 1, U"-- report stats --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 1, U"Report mean (Student t)...", nullptr, 1, DO_Table_reportMean_studentT);
+		praat_addAction1 (classTable, 1, U"Report mean (Student t)...", nullptr, 1, INFO_Table_reportMean_studentT);
 		/*praat_addAction1 (classTable, 1, U"Report standard deviation...", nullptr, 1, DO_Table_reportStandardDeviation);*/
-		praat_addAction1 (classTable, 1, U"Report difference (Student t)...", nullptr, 1, DO_Table_reportDifference_studentT);
-		praat_addAction1 (classTable, 1, U"Report group mean (Student t)...", nullptr, 1, DO_Table_reportGroupMean_studentT);
-		praat_addAction1 (classTable, 1, U"Report group difference (Student t)...", nullptr, 1, DO_Table_reportGroupDifference_studentT);
-		praat_addAction1 (classTable, 1, U"Report group difference (Wilcoxon rank sum)...", nullptr, 1, DO_Table_reportGroupDifference_wilcoxonRankSum);
-		praat_addAction1 (classTable, 1, U"Report correlation (Pearson r)...", nullptr, 1, DO_Table_reportCorrelation_pearsonR);
-		praat_addAction1 (classTable, 1, U"Report correlation (Kendall tau)...", nullptr, 1, DO_Table_reportCorrelation_kendallTau);
+		praat_addAction1 (classTable, 1, U"Report difference (Student t)...", nullptr, 1, INFO_Table_reportDifference_studentT);
+		praat_addAction1 (classTable, 1, U"Report group mean (Student t)...", nullptr, 1, INFO_Table_reportGroupMean_studentT);
+		praat_addAction1 (classTable, 1, U"Report group difference (Student t)...", nullptr, 1, INFO_Table_reportGroupDifference_studentT);
+		praat_addAction1 (classTable, 1, U"Report group difference (Wilcoxon rank sum)...", nullptr, 1, INFO_Table_reportGroupDifference_wilcoxonRankSum);
+		praat_addAction1 (classTable, 1, U"Report correlation (Pearson r)...", nullptr, 1, INFO_Table_reportCorrelation_pearsonR);
+		praat_addAction1 (classTable, 1, U"Report correlation (Kendall tau)...", nullptr, 1, INFO_Table_reportCorrelation_kendallTau);
 	praat_addAction1 (classTable, 0, U"Modify -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 0, U"Set string value...", nullptr, 1, DO_Table_setStringValue);
-		praat_addAction1 (classTable, 0, U"Set numeric value...", nullptr, 1, DO_Table_setNumericValue);
-		praat_addAction1 (classTable, 0, U"Formula...", nullptr, 1, DO_Table_formula);
-		praat_addAction1 (classTable, 0, U"Formula (column range)...", nullptr, 1, DO_Table_formula_columnRange);
-		praat_addAction1 (classTable, 0, U"Sort rows...", nullptr, 1, DO_Table_sortRows);
-		praat_addAction1 (classTable, 0, U"Randomize rows", nullptr, 1, DO_Table_randomizeRows);
-		praat_addAction1 (classTable, 0, U"Reflect rows", nullptr, 1, DO_Table_reflectRows);
+		praat_addAction1 (classTable, 0, U"Set string value...", nullptr, 1, MODIFY_Table_setStringValue);
+		praat_addAction1 (classTable, 0, U"Set numeric value...", nullptr, 1, MODIFY_Table_setNumericValue);
+		praat_addAction1 (classTable, 0, U"Formula...", nullptr, 1, MODIFY_Table_formula);
+		praat_addAction1 (classTable, 0, U"Formula (column range)...", nullptr, 1, MODIFY_Table_formula_columnRange);
+		praat_addAction1 (classTable, 0, U"Sort rows...", nullptr, 1, MODIFY_Table_sortRows);
+		praat_addAction1 (classTable, 0, U"Randomize rows", nullptr, 1, MODIFY_Table_randomizeRows);
+		praat_addAction1 (classTable, 0, U"Reflect rows", nullptr, 1, MODIFY_Table_reflectRows);
 		praat_addAction1 (classTable, 0, U"-- structure --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 0, U"Append row", nullptr, 1, DO_Table_appendRow);
-		praat_addAction1 (classTable, 0, U"Append column...", nullptr, 1, DO_Table_appendColumn);
-		praat_addAction1 (classTable, 0, U"Append sum column...", nullptr, 1, DO_Table_appendSumColumn);
-		praat_addAction1 (classTable, 0, U"Append difference column...", nullptr, 1, DO_Table_appendDifferenceColumn);
-		praat_addAction1 (classTable, 0, U"Append product column...", nullptr, 1, DO_Table_appendProductColumn);
-		praat_addAction1 (classTable, 0, U"Append quotient column...", nullptr, 1, DO_Table_appendQuotientColumn);
-		praat_addAction1 (classTable, 0, U"Remove row...", nullptr, 1, DO_Table_removeRow);
-		praat_addAction1 (classTable, 0, U"Remove column...", nullptr, 1, DO_Table_removeColumn);
-		praat_addAction1 (classTable, 0, U"Insert row...", nullptr, 1, DO_Table_insertRow);
-		praat_addAction1 (classTable, 0, U"Insert column...", nullptr, 1, DO_Table_insertColumn);
+		praat_addAction1 (classTable, 0, U"Append row", nullptr, 1, MODIFY_Table_appendRow);
+		praat_addAction1 (classTable, 0, U"Append column...", nullptr, 1, MODIFY_Table_appendColumn);
+		praat_addAction1 (classTable, 0, U"Append sum column...", nullptr, 1, MODIFY_Table_appendSumColumn);
+		praat_addAction1 (classTable, 0, U"Append difference column...", nullptr, 1, MODIFY_Table_appendDifferenceColumn);
+		praat_addAction1 (classTable, 0, U"Append product column...", nullptr, 1, MODIFY_Table_appendProductColumn);
+		praat_addAction1 (classTable, 0, U"Append quotient column...", nullptr, 1, MODIFY_Table_appendQuotientColumn);
+		praat_addAction1 (classTable, 0, U"Remove row...", nullptr, 1, MODIFY_Table_removeRow);
+		praat_addAction1 (classTable, 0, U"Remove column...", nullptr, 1, MODIFY_Table_removeColumn);
+		praat_addAction1 (classTable, 0, U"Insert row...", nullptr, 1, MODIFY_Table_insertRow);
+		praat_addAction1 (classTable, 0, U"Insert column...", nullptr, 1, MODIFY_Table_insertColumn);
 		praat_addAction1 (classTable, 0, U"-- set --", nullptr, 1, nullptr);
-		praat_addAction1 (classTable, 0, U"Set column label (index)...", nullptr, 1, DO_Table_setColumnLabel_index);
-		praat_addAction1 (classTable, 0, U"Set column label (label)...", nullptr, 1, DO_Table_setColumnLabel_label);
+		praat_addAction1 (classTable, 0, U"Set column label (index)...", nullptr, 1, MODIFY_Table_setColumnLabel_index);
+		praat_addAction1 (classTable, 0, U"Set column label (label)...", nullptr, 1, MODIFY_Table_setColumnLabel_label);
 	praat_addAction1 (classTable, 0, U"Analyse -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 0, U"To linear regression", nullptr, 1, DO_Table_to_LinearRegression);
-		praat_addAction1 (classTable, 0, U"To logistic regression...", nullptr, 1, DO_Table_to_LogisticRegression);
+		praat_addAction1 (classTable, 0, U"To linear regression", nullptr, 1, NEW_Table_to_LinearRegression);
+		praat_addAction1 (classTable, 0, U"To logistic regression...", nullptr, 1, NEW_Table_to_LogisticRegression);
 	praat_addAction1 (classTable, 0, U"Synthesize -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 0, U"Append", nullptr, 1, DO_Tables_append);
+		praat_addAction1 (classTable, 0, U"Append", nullptr, 1, NEW1_Tables_append);
 	praat_addAction1 (classTable, 0, U"Generate -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 1, U"Draw row from distribution...", nullptr, 1, DO_Table_drawRowFromDistribution);
+		praat_addAction1 (classTable, 1, U"Draw row from distribution...", nullptr, 1, INTEGER_Table_drawRowFromDistribution);
 	praat_addAction1 (classTable, 0, U"Extract -", nullptr, 0, nullptr);
-		praat_addAction1 (classTable, 0, U"Extract rows where column (number)...", nullptr, 1, DO_Table_extractRowsWhereColumn_number);
-		praat_addAction1 (classTable, 0, U"Extract rows where column...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Table_extractRowsWhereColumn_number);
-		praat_addAction1 (classTable, 0, U"Select rows where column...", nullptr, praat_DEPTH_1 + praat_HIDDEN, DO_Table_extractRowsWhereColumn_number);
-		praat_addAction1 (classTable, 0, U"Extract rows where column (text)...", nullptr, 1, DO_Table_extractRowsWhereColumn_text);
-		praat_addAction1 (classTable, 0, U"Transpose", nullptr, 1, DO_Table_transpose);
-		praat_addAction1 (classTable, 0, U"Collapse rows...", nullptr, 1, DO_Table_collapseRows);
-		praat_addAction1 (classTable, 0, U"Rows to columns...", nullptr, 1, DO_Table_rowsToColumns);
-	praat_addAction1 (classTable, 0, U"Down to TableOfReal...", nullptr, 0, DO_Table_to_TableOfReal);
-
-	praat_addAction1 (classTableOfReal, 0, U"TableOfReal help", nullptr, 0, DO_TableOfReal_help);
+		praat_addAction1 (classTable, 0, U"Extract rows where column (number)...", nullptr, 1, NEW_Table_extractRowsWhereColumn_number);
+		praat_addAction1 (classTable, 0,   U"Extract rows where column...", U"*Extract rows where column (number)...", praat_DEPTH_1 | praat_DEPRECATED_2006, NEW_Table_extractRowsWhereColumn_number);
+		praat_addAction1 (classTable, 0,   U"Select rows where column...", U"*Extract rows where column (number)...", praat_DEPTH_1 | praat_DEPRECATED_2004, NEW_Table_extractRowsWhereColumn_number);
+		praat_addAction1 (classTable, 0, U"Extract rows where column (text)...", nullptr, 1, NEW_Table_extractRowsWhereColumn_text);
+		praat_addAction1 (classTable, 0, U"Transpose", nullptr, 1, NEW_Table_transpose);
+		praat_addAction1 (classTable, 0, U"Collapse rows...", nullptr, 1, NEW_Table_collapseRows);
+		praat_addAction1 (classTable, 0, U"Rows to columns...", nullptr, 1, NEW_Table_rowsToColumns);
+	praat_addAction1 (classTable, 0, U"Down to TableOfReal...", nullptr, 0, NEW_Table_to_TableOfReal);
+
 	praat_TableOfReal_init (classTableOfReal);
 
-	praat_addAction2 (classPairDistribution, 1, classDistributions, 1, U"Get fraction correct...", nullptr, 0, DO_PairDistribution_Distributions_getFractionCorrect);
+	praat_addAction2 (classPairDistribution, 1, classDistributions, 1, U"Get fraction correct...", nullptr, 0, REAL_PairDistribution_Distributions_getFractionCorrect);
 }
 
 /* End of file praat_Stat.cpp */
diff --git a/stat/praat_TableOfReal.cpp b/stat/praat_TableOfReal.cpp
new file mode 100644
index 0000000..da8c553
--- /dev/null
+++ b/stat/praat_TableOfReal.cpp
@@ -0,0 +1,553 @@
+/* praat_TableOfReal.cpp
+ *
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Matrix.h"
+#include "praat_TableOfReal.h"
+
+#undef iam
+#define iam iam_LOOP
+
+// MARK: - TABLEOFREAL
+
+// MARK: Help
+
+DIRECT (HELP_TableOfReal_help) {
+	HELP (U"TableOfReal")
+}
+
+// MARK: Draw
+
+FORM (GRAPHICS_TableOfReal_drawAsNumbers, U"Draw as numbers", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	RADIO4 (format, U"Format", 3)
+		RADIOBUTTON (U"decimal")
+		RADIOBUTTON (U"exponential")
+		RADIOBUTTON (U"free")
+		RADIOBUTTON (U"rational")
+	NATURAL4 (precision, U"Precision", U"5")
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawAsNumbers (me, GRAPHICS, fromRow, toRow, format, precision);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_TableOfReal_drawAsNumbers_if, U"Draw as numbers if...", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	RADIO4 (format, U"Format", 3)
+		RADIOBUTTON (U"decimal")
+		RADIOBUTTON (U"exponential")
+		RADIOBUTTON (U"free")
+		RADIOBUTTON (U"rational")
+	NATURAL4 (precision, U"Precision", U"5")
+	LABEL (U"", U"Condition:")
+	TEXTFIELD4 (condition, U"condition", U"self <> 0")
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawAsNumbers_if (me, GRAPHICS, fromRow, toRow, format, precision, condition, interpreter);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_TableOfReal_drawAsSquares, U"Draw table as squares", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	NATURAL4 (fromColumn, U"From column", U"1")
+	INTEGER4 (toColumn, U"To column", U"0")
+	BOOLEAN4 (garnish, U"Garnish", true)
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawAsSquares (me, GRAPHICS, fromRow, toRow, fromColumn, toColumn, garnish);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_TableOfReal_drawHorizontalLines, U"Draw horizontal lines", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawHorizontalLines (me, GRAPHICS, fromRow, toRow);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_TableOfReal_drawLeftAndRightLines, U"Draw left and right lines", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawLeftAndRightLines (me, GRAPHICS, fromRow, toRow);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_TableOfReal_drawTopAndBottomLines, U"Draw top and bottom lines", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawTopAndBottomLines (me, GRAPHICS, fromRow, toRow);
+	GRAPHICS_EACH_END
+}
+
+FORM (GRAPHICS_TableOfReal_drawVerticalLines, U"Draw vertical lines", nullptr) {
+	NATURAL4 (fromRow, U"From row", U"1")
+	INTEGER4 (toRow, U"To row", U"0 (= all)")
+	OK
+DO
+	GRAPHICS_EACH (TableOfReal)
+		TableOfReal_drawVerticalLines (me, GRAPHICS, fromRow, toRow);
+	GRAPHICS_EACH_END
+}
+
+// MARK: Query
+
+FORM (INTEGER_TableOfReal_getColumnIndex, U"Get column index", nullptr) {
+	SENTENCE4 (columnLabel, U"Column label", U"")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		long result = TableOfReal_columnLabelToIndex (me, columnLabel);
+	NUMBER_ONE_END (U" (index of column ", columnLabel, U")")
+}
+	
+FORM (STRING_TableOfReal_getColumnLabel, U"Get column label", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	STRING_ONE (TableOfReal)
+		if (columnNumber > my numberOfColumns)
+			Melder_throw (me, U": your column number should not be greater than the number of columns.");
+		const char32 *result = my columnLabels ? my columnLabels [columnNumber] : U"";
+	STRING_ONE_END
+}
+	
+FORM (REAL_TableOfReal_getColumnMean_index, U"Get column mean", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		if (columnNumber > my numberOfColumns)
+			Melder_throw (me, U": your column number should not be greater than the number of columns.");
+		double result = TableOfReal_getColumnMean (me, columnNumber);
+	NUMBER_ONE_END (U" (mean of column ", columnNumber, U")")
+}
+
+FORM (REAL_TableOfReal_getColumnMean_label, U"Get column mean", nullptr) {
+	SENTENCE4 (columnLabel, U"Column label", U"")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		long columnNumber = TableOfReal_columnLabelToIndex (me, columnLabel);
+		if (columnNumber == 0) Melder_throw (me, U": your column label does not exist.");
+		double result = TableOfReal_getColumnMean (me, columnNumber);
+	NUMBER_ONE_END (U" (mean of column ", columnLabel, U")")
+}
+
+FORM (REAL_TableOfReal_getColumnStdev_index, U"Get column standard deviation", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		if (columnNumber > my numberOfColumns)
+			Melder_throw (me, U": your column number should not be greater than the number of columns.");
+		double result = TableOfReal_getColumnStdev (me, columnNumber);
+	NUMBER_ONE_END (U" (standard deviation of column ", columnNumber, U")")
+}
+
+FORM (REAL_TableOfReal_getColumnStdev_label, U"Get column standard deviation", nullptr) {
+	SENTENCE4 (columnLabel, U"Column label", U"1")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		long columnNumber = TableOfReal_columnLabelToIndex (me, columnLabel);
+		if (columnNumber == 0) Melder_throw (me, U": column label does not exist.");
+		double result = TableOfReal_getColumnStdev (me, columnNumber);
+	NUMBER_ONE_END (U" (standard deviation of column ", columnLabel, U")")
+}
+
+DIRECT (INTEGER_TableOfReal_getNumberOfColumns) {
+	NUMBER_ONE (TableOfReal)
+		long result = my numberOfColumns;
+	NUMBER_ONE_END (U" columns")
+}
+
+DIRECT (INTEGER_TableOfReal_getNumberOfRows) {
+	NUMBER_ONE (TableOfReal)
+		long result = my numberOfRows;
+	NUMBER_ONE_END (U" rows")
+}
+
+FORM (INTEGER_TableOfReal_getRowIndex, U"Get row index", nullptr) {
+	SENTENCE4 (rowLabel, U"Row label", U"")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		long result = TableOfReal_rowLabelToIndex (me, rowLabel);
+	NUMBER_ONE_END (U" (index of row ", rowLabel, U")")
+}
+
+FORM (STRING_TableOfReal_getRowLabel, U"Get row label", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
+DO
+	STRING_ONE (TableOfReal)
+		if (rowNumber > my numberOfRows)
+			Melder_throw (me, U": your row number should not be greater than the number of rows.");
+		const char32 *result = my rowLabels ? my rowLabels [rowNumber] : U"";
+	STRING_ONE_END
+}
+
+FORM (REAL_TableOfReal_getValue, U"Get value", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	NUMBER_ONE (TableOfReal)
+		if (rowNumber > my numberOfRows)
+			Melder_throw (me, U": your row number should not exceed the number of rows.");
+		if (columnNumber > my numberOfColumns)
+			Melder_throw (me, U": your column number should not exceed the number of columns.");
+		double result = my data [rowNumber] [columnNumber];
+	NUMBER_ONE_END (U" (value in column ", columnNumber, U" of row ", rowNumber, U")")
+}
+
+// MARK: Modify
+
+FORM (MODIFY_TableOfReal_formula, U"TableOfReal: Formula", U"Formula...") {
+	LABEL (U"", U"for row from 1 to nrow do for col from 1 to ncol do self [row, col] = ...")
+	TEXTFIELD4 (formula, U"formula", U"if col = 5 then self + self [6] else self fi")
+	OK
+DO
+	MODIFY_EACH_WEAK (TableOfReal)
+		TableOfReal_formula (me, formula, interpreter, nullptr);
+	MODIFY_EACH_WEAK_END
+}
+
+FORM (MODIFY_TableOfReal_insertColumn, U"Insert column", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_insertColumn (me, columnNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_insertRow, U"Insert row", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_insertRow (me, rowNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_removeColumn, U"Remove column", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_removeColumn (me, columnNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_removeRow, U"Remove row", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_removeRow (me, rowNumber);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_setColumnLabel_index, U"Set column label", nullptr) {
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	SENTENCE4 (label, U"Label", U"")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_setColumnLabel (me, columnNumber, label);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_setColumnLabel_label, U"Set column label", nullptr) {
+	SENTENCE4 (oldLabel, U"Old label", U"")
+	SENTENCE4 (newLabel, U"New label", U"")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		long columnNumber = TableOfReal_columnLabelToIndex (me, oldLabel);
+		TableOfReal_setColumnLabel (me, columnNumber, newLabel);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_setRowLabel_index, U"Set row label", nullptr) {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	SENTENCE4 (label, U"Label", U"")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_setRowLabel (me, rowNumber, label);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_setValue, U"Set value", U"TableOfReal: Set value...") {
+	NATURAL4 (rowNumber, U"Row number", U"1")
+	NATURAL4 (columnNumber, U"Column number", U"1")
+	REAL_OR_UNDEFINED4 (newValue, U"New value", U"0.0")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		if (rowNumber > my numberOfRows)
+			Melder_throw (me, U": your row number should not be greater than the number of rows.");
+		if (columnNumber > my numberOfColumns)
+			Melder_throw (me, U": your column number should not be greater than the number of columns.");
+		my data [rowNumber] [columnNumber] = newValue;
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_setRowLabel_label, U"Set row label", nullptr) {
+	SENTENCE4 (oldLabel, U"Old label", U"")
+	WORD4 (newLabel, U"New label", U"")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		long rowNumber = TableOfReal_rowLabelToIndex (me, oldLabel);
+		TableOfReal_setRowLabel (me, rowNumber, newLabel);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_sortByColumn, U"Sort rows by column", nullptr) {
+	INTEGER4 (column, U"Column", U"1")
+	INTEGER4 (secondaryColumn, U"Secondary column", U"0")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_sortByColumn (me, column, secondaryColumn);
+	MODIFY_EACH_END
+}
+
+FORM (MODIFY_TableOfReal_sortByLabel, U"Sort rows by label", nullptr) {
+	LABEL (U"", U"Secondary sorting keys:")
+	INTEGER4 (column1, U"Column1", U"1")
+	INTEGER4 (column2, U"Column2", U"0")
+	OK
+DO
+	MODIFY_EACH (TableOfReal)
+		TableOfReal_sortByLabel (me, column1, column2);
+	MODIFY_EACH_END
+}
+
+// MARK: Extract
+
+DIRECT (NEW_TableOfReal_extractColumnLabelsAsStrings) {
+	CONVERT_EACH (TableOfReal)
+		autoStrings result = TableOfReal_extractColumnLabelsAsStrings (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_TableOfReal_extractColumnRanges, U"Extract column ranges", nullptr) {
+	LABEL (U"", U"Create a new TableOfReal from the following columns:")
+	TEXTFIELD4 (ranges, U"ranges", U"1 2")
+	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractColumnRanges (me, ranges);
+	CONVERT_EACH_END (my name, U"_cols")
+}
+
+FORM (NEW_TableOfReal_extractColumnsWhere, U"Extract columns where", nullptr) {
+	LABEL (U"", U"Extract all columns with at least one cell where:")
+	TEXTFIELD4 (condition, U"condition", U"col mod 3 = 0 ; this example extracts every third column")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractColumnsWhere (me, condition, interpreter);
+	CONVERT_EACH_END (my name, U"_cols")
+}
+
+FORM (NEW_TableOfReal_extractColumnsWhereLabel, U"Extract column where label", nullptr) {
+	OPTIONMENU_ENUM4 (extractAllColumnsWhoseLabel, U"Extract all columns whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"a")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractColumnsWhereLabel (me, extractAllColumnsWhoseLabel, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
+
+FORM (NEW_TableOfReal_extractColumnsWhereRow, U"Extract columns where row", nullptr) {
+	NATURAL4 (extractAllColumnsWhereRow, U"Extract all columns where row...", U"1")
+	OPTIONMENU_ENUM4 (___is___, U"...is...", kMelder_number, DEFAULT)
+	REAL4 (___theValue, U"...the value", U"0.0")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractColumnsWhereRow (me, extractAllColumnsWhereRow, ___is___, ___theValue);
+	CONVERT_EACH_END (my name, U"_", extractAllColumnsWhereRow, U"_", lround (___theValue))
+}
+
+DIRECT (NEW_TableOfReal_extractRowLabelsAsStrings) {
+	CONVERT_EACH (TableOfReal)
+		autoStrings result = TableOfReal_extractRowLabelsAsStrings (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_TableOfReal_extractRowRanges, U"Extract row ranges", nullptr) {
+	LABEL (U"", U"Create a new TableOfReal from the following rows:")
+	TEXTFIELD4 (ranges, U"ranges", U"1 2")
+	LABEL (U"", U"To supply rising or falling ranges, use e.g. 2:6 or 5:3.")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractRowRanges (me, ranges);
+	CONVERT_EACH_END (my name, U"_rows")
+}
+
+FORM (NEW_TableOfReal_extractRowsWhere, U"Extract rows where", nullptr) {
+	LABEL (U"", U"Extract all rows with at least one cell where:")
+	TEXTFIELD4 (condition, U"condition", U"row mod 3 = 0 ; this example extracts every third row")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractRowsWhere (me, condition, interpreter);
+	CONVERT_EACH_END (my name, U"_rows")
+}
+
+FORM (NEW_TableOfReal_extractRowsWhereColumn, U"Extract rows where column", nullptr) {
+	NATURAL4 (extractAllRowsWhereColumn, U"Extract all rows where column...", U"1")
+	OPTIONMENU_ENUM4 (___is___, U"...is...", kMelder_number, DEFAULT)
+	REAL4 (___theValue, U"...the value", U"0.0")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractRowsWhereColumn (me, extractAllRowsWhereColumn, ___is___, ___theValue);
+	CONVERT_EACH_END (my name, U"_", extractAllRowsWhereColumn, U"_", lround (___theValue))
+}
+
+FORM (NEW_TableOfReal_extractRowsWhereLabel, U"Extract rows where label", nullptr) {
+	OPTIONMENU_ENUM4 (extractAllRowsWhoseLabel, U"Extract all rows whose label...", kMelder_string, DEFAULT)
+	SENTENCE4 (___theText, U"...the text", U"a")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTableOfReal result = TableOfReal_extractRowsWhereLabel (me, extractAllRowsWhoseLabel, ___theText);
+	CONVERT_EACH_END (my name, U"_", ___theText)
+}
+
+// MARK: Convert
+
+DIRECT (NEW1_TablesOfReal_append) {
+	CONVERT_LIST (TableOfReal)
+		autoTableOfReal result = TablesOfReal_appendMany (& list);
+	CONVERT_LIST_END (U"appended")
+}
+
+
+DIRECT (NEW_TableOfReal_to_Matrix) {
+	CONVERT_EACH (TableOfReal)
+		autoMatrix result = TableOfReal_to_Matrix (me);
+	CONVERT_EACH_END (my name)
+}
+
+FORM (NEW_TableOfReal_to_Table, U"TableOfReal: To Table", nullptr) {
+	SENTENCE4 (labelOfFirstColumn, U"Label of first column", U"rowLabel")
+	OK
+DO
+	CONVERT_EACH (TableOfReal)
+		autoTable result = TableOfReal_to_Table (me, labelOfFirstColumn);
+	CONVERT_EACH_END (my name)
+}
+
+FORM_SAVE (SAVE_TableOfReal_writeToHeaderlessSpreadsheetFile, U"Save TableOfReal as spreadsheet", 0, U"txt") {
+	SAVE_ONE (TableOfReal)
+		TableOfReal_writeToHeaderlessSpreadsheetFile (me, file);
+	SAVE_ONE_END
+}
+
+void praat_TableOfReal_init (ClassInfo klas) {
+	if (klas == classTableOfReal) {
+		praat_addAction1 (classTableOfReal, 0, U"TableOfReal help", nullptr, 0, HELP_TableOfReal_help);
+	}
+	praat_addAction1 (klas, 1, U"Save as headerless spreadsheet file...", nullptr, 0, SAVE_TableOfReal_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (klas, 1,   U"Write to headerless spreadsheet file...", U"*Save as headerless spreadsheet file...", praat_DEPRECATED_2011, SAVE_TableOfReal_writeToHeaderlessSpreadsheetFile);
+	praat_addAction1 (klas, 0, U"Draw -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 0, U"Draw as numbers...", nullptr, 1, GRAPHICS_TableOfReal_drawAsNumbers);
+		praat_addAction1 (klas, 0, U"Draw as numbers if...", nullptr, 1, GRAPHICS_TableOfReal_drawAsNumbers_if);
+		praat_addAction1 (klas, 0, U"Draw as squares...", nullptr, 1, GRAPHICS_TableOfReal_drawAsSquares);
+		praat_addAction1 (klas, 0, U"-- draw lines --", nullptr, 1, 0);
+		praat_addAction1 (klas, 0, U"Draw vertical lines...", nullptr, 1, GRAPHICS_TableOfReal_drawVerticalLines);
+		praat_addAction1 (klas, 0, U"Draw horizontal lines...", nullptr, 1, GRAPHICS_TableOfReal_drawHorizontalLines);
+		praat_addAction1 (klas, 0, U"Draw left and right lines...", nullptr, 1, GRAPHICS_TableOfReal_drawLeftAndRightLines);
+		praat_addAction1 (klas, 0, U"Draw top and bottom lines...", nullptr, 1, GRAPHICS_TableOfReal_drawTopAndBottomLines);
+	praat_addAction1 (klas, 0, U"Query -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 1, U"Get number of rows", nullptr, 1, INTEGER_TableOfReal_getNumberOfRows);
+		praat_addAction1 (klas, 1, U"Get number of columns", nullptr, 1, INTEGER_TableOfReal_getNumberOfColumns);
+		praat_addAction1 (klas, 1, U"Get row label...", nullptr, 1, STRING_TableOfReal_getRowLabel);
+		praat_addAction1 (klas, 1, U"Get column label...", nullptr, 1, STRING_TableOfReal_getColumnLabel);
+		praat_addAction1 (klas, 1, U"Get row index...", nullptr, 1, INTEGER_TableOfReal_getRowIndex);
+		praat_addAction1 (klas, 1, U"Get column index...", nullptr, 1, INTEGER_TableOfReal_getColumnIndex);
+		praat_addAction1 (klas, 1, U"-- get value --", nullptr, 1, nullptr);
+		praat_addAction1 (klas, 1, U"Get value...", nullptr, 1, REAL_TableOfReal_getValue);
+		if (klas == classTableOfReal) {
+			praat_addAction1 (klas, 1, U"-- get statistics --", nullptr, 1, nullptr);
+			praat_addAction1 (klas, 1, U"Get column mean (index)...", nullptr, 1, REAL_TableOfReal_getColumnMean_index);
+			praat_addAction1 (klas, 1, U"Get column mean (label)...", nullptr, 1, REAL_TableOfReal_getColumnMean_label);
+			praat_addAction1 (klas, 1, U"Get column stdev (index)...", nullptr, 1, REAL_TableOfReal_getColumnStdev_index);
+			praat_addAction1 (klas, 1, U"Get column stdev (label)...", nullptr, 1, REAL_TableOfReal_getColumnStdev_label);
+		}
+	praat_addAction1 (klas, 0, U"Modify -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 0, U"Formula...", nullptr, 1, MODIFY_TableOfReal_formula);
+		praat_addAction1 (klas, 0, U"Set value...", nullptr, 1, MODIFY_TableOfReal_setValue);
+		praat_addAction1 (klas, 0, U"Sort by label...", nullptr, 1, MODIFY_TableOfReal_sortByLabel);
+		praat_addAction1 (klas, 0, U"Sort by column...", nullptr, 1, MODIFY_TableOfReal_sortByColumn);
+		praat_addAction1 (klas, 0, U"-- structure --", nullptr, 1, nullptr);
+		praat_addAction1 (klas, 0, U"Remove row (index)...", nullptr, 1, MODIFY_TableOfReal_removeRow);
+		praat_addAction1 (klas, 0, U"Remove column (index)...", nullptr, 1, MODIFY_TableOfReal_removeColumn);
+		praat_addAction1 (klas, 0, U"Insert row (index)...", nullptr, 1, MODIFY_TableOfReal_insertRow);
+		praat_addAction1 (klas, 0, U"Insert column (index)...", nullptr, 1, MODIFY_TableOfReal_insertColumn);
+		praat_addAction1 (klas, 0, U"-- set --", nullptr, 1, nullptr);
+		praat_addAction1 (klas, 0, U"Set row label (index)...", nullptr, 1, MODIFY_TableOfReal_setRowLabel_index);
+		praat_addAction1 (klas, 0, U"Set row label (label)...", nullptr, 1, MODIFY_TableOfReal_setRowLabel_label);
+		praat_addAction1 (klas, 0, U"Set column label (index)...", nullptr, 1, MODIFY_TableOfReal_setColumnLabel_index);
+		praat_addAction1 (klas, 0, U"Set column label (label)...", nullptr, 1, MODIFY_TableOfReal_setColumnLabel_label);
+	praat_addAction1 (klas, 0, U"Synthesize -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 0, U"Append", nullptr, 1, NEW1_TablesOfReal_append);
+	praat_addAction1 (klas, 0, U"Extract part -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 0, U"Extract row ranges...", nullptr, 1, NEW_TableOfReal_extractRowRanges);
+		praat_addAction1 (klas, 0, U"Extract rows where column...", nullptr, 1, NEW_TableOfReal_extractRowsWhereColumn);
+		praat_addAction1 (klas, 0, U"Extract rows where label...", nullptr, 1, NEW_TableOfReal_extractRowsWhereLabel);
+		praat_addAction1 (klas, 0, U"Extract rows where...", nullptr, 1, NEW_TableOfReal_extractRowsWhere);
+		praat_addAction1 (klas, 0, U"Extract column ranges...", nullptr, 1, NEW_TableOfReal_extractColumnRanges);
+		praat_addAction1 (klas, 0, U"Extract columns where row...", nullptr, 1, NEW_TableOfReal_extractColumnsWhereRow);
+		praat_addAction1 (klas, 0, U"Extract columns where label...", nullptr, 1, NEW_TableOfReal_extractColumnsWhereLabel);
+		praat_addAction1 (klas, 0, U"Extract columns where...", nullptr, 1, NEW_TableOfReal_extractColumnsWhere);
+	praat_addAction1 (klas, 0, U"Extract -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 0, U"Extract row labels as Strings", nullptr, 1, NEW_TableOfReal_extractRowLabelsAsStrings);
+		praat_addAction1 (klas, 0, U"Extract column labels as Strings", nullptr, 1, NEW_TableOfReal_extractColumnLabelsAsStrings);
+	praat_addAction1 (klas, 0, U"Convert -", nullptr, 0, nullptr);
+		praat_addAction1 (klas, 0, U"To Table...", nullptr, 1, NEW_TableOfReal_to_Table);
+		praat_addAction1 (klas, 0, U"To Matrix", nullptr, 1, NEW_TableOfReal_to_Matrix);
+}
+
+/* End of file praat_TableOfReal.cpp */
diff --git a/sys/InfoEditor.h b/stat/praat_TableOfReal.h
similarity index 63%
copy from sys/InfoEditor.h
copy to stat/praat_TableOfReal.h
index 032e683..91d4341 100644
--- a/sys/InfoEditor.h
+++ b/stat/praat_TableOfReal.h
@@ -1,8 +1,8 @@
-#ifndef _InfoEditor_h_
-#define _InfoEditor_h_
-/* InfoEditor.h
+#ifndef _praat_TableOfReal_h_
+#define _praat_TableOfReal_h_
+/* praat_TableOfReal.h
  *
- * Copyright (C) 2004-2011,2015 Paul Boersma
+ * Copyright (C) 2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,18 +18,17 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "TextEditor.h"
+/*
+	Interface functions for subclasses of TableOfReal.
+*/
 
-Thing_define (InfoEditor, TextEditor) {
-	void v_destroy () noexcept
-		override;
-	bool v_scriptable ()
-		override { return false; }
-	bool v_fileBased ()
-		override { return false; }
-	void v_clear ()
-		override;
-};
+#include "TableOfReal.h"
+#include "praat.h"
 
-/* End of file InfoEditor.h */
+/*
+	Action buttons.
+*/
+void praat_TableOfReal_init (ClassInfo klas);
+
+/* End of file praat_TableOfReal.h */
 #endif
diff --git a/sys/Collection.cpp b/sys/Collection.cpp
index 627a373..bc9bf6b 100644
--- a/sys/Collection.cpp
+++ b/sys/Collection.cpp
@@ -33,13 +33,13 @@ void _CollectionOfDaata_v_copy (_CollectionOfDaata* me, _CollectionOfDaata* thee
 		thy at._elements --;   // immediately turn from base-0 into base-1  // BUG use NUMvector
 	}
 	for (long i = 1; i <= my size; i ++) {
-		Daata itempie = my at [i];
+		Daata item = my at [i];
 		if (my _ownItems) {
-			if (! Thing_isa (itempie, classDaata))
-				Melder_throw (U"Cannot copy item of class ", Thing_className (itempie), U".");
-			thy at [i] = Data_copy (itempie).releaseToAmbiguousOwner();
+			if (! Thing_isa (item, classDaata))
+				Melder_throw (U"Cannot copy item of class ", Thing_className (item), U".");
+			thy at [i] = Data_copy (item).releaseToAmbiguousOwner();
 		} else {
-			thy at [i] = itempie;   // reference copy: if me doesn't own the items, then thee shouldn't either   // NOTE: the items don't have to be Daata
+			thy at [i] = item;   // reference copy: if me doesn't own the items, then thee shouldn't either   // NOTE: the items don't have to be Daata
 		}
 	}
 }
@@ -109,7 +109,7 @@ void _CollectionOfDaata_v_readText (_CollectionOfDaata* me, MelderReadText text,
 				if (! line.peek())
 					Melder_throw (U"Missing object line.");
 			} while (strncmp (line.peek(), "Object ", 7));
-			stringsRead = sscanf (line.peek(), "Object %ld: class %s %s%n", & itemNumberRead, klas, nameTag, & n);
+			stringsRead = sscanf (line.peek(), "Object %ld: class %199s %1999s%n", & itemNumberRead, klas, nameTag, & n);
 			if (stringsRead < 2)
 				Melder_throw (U"Collection::readText: cannot read header of object ", i, U".");
 			if (itemNumberRead != i)
@@ -169,7 +169,7 @@ void _CollectionOfDaata_v_readBinary (_CollectionOfDaata* me, FILE *f, int forma
 		my _grow (l_size);
 		for (int32_t i = 1; i <= l_size; i ++) {
 			char klas [200], name [2000];
-			if (fscanf (f, "%s%s", klas, name) < 2)   // BUG
+			if (fscanf (f, "%199s%1999s", klas, name) < 2)
 				Melder_throw (U"Cannot read class and name.");
 			my at [i] = (Daata) Thing_newFromClassName (Melder_peek8to32 (klas), nullptr).releaseToAmbiguousOwner();
 			my size ++;
diff --git a/sys/Collection.h b/sys/Collection.h
index 9e6a31b..b297cb7 100644
--- a/sys/Collection.h
+++ b/sys/Collection.h
@@ -431,10 +431,10 @@ struct CollectionOf : structDaata {
 
 	void v_destroy () noexcept override {
 		/*
-			The items are destroyed automatically be the destructor,
+			The items are destroyed automatically by the destructor,
 			which is called by delete, which is called by forget().
 			So we only have to destroy the members of Daata,
-			which are not automatic.
+			many of which are not destroyed automatically.
 		*/
 		structDaata::v_destroy ();
 	}
diff --git a/sys/DataEditor.cpp b/sys/DataEditor.cpp
index 9209ca0..8101c7d 100644
--- a/sys/DataEditor.cpp
+++ b/sys/DataEditor.cpp
@@ -691,11 +691,11 @@ static void MatrixEditor_create (DataEditor root, const char32 *title, void *add
 Thing_implement (ClassEditor, StructEditor, 0);
 
 static void ClassEditor_showMembers_recursive (ClassEditor me, ClassInfo klas) {
-	ClassInfo parentClass = klas -> parent;
+	ClassInfo parentClass = klas -> semanticParent;
 	Data_Description description = Class_getDescription (klas);
 	int classFieldsTraversed = 0;
 	while (Class_getDescription (parentClass) == description)
-		parentClass = parentClass -> parent;
+		parentClass = parentClass -> semanticParent;
 	if (parentClass != classDaata) {
 		ClassEditor_showMembers_recursive (me, parentClass);
 		classFieldsTraversed = Data_Description_countMembers (Class_getDescription (parentClass));
diff --git a/sys/DemoEditor.cpp b/sys/DemoEditor.cpp
index a0b99c4..b9b88a6 100644
--- a/sys/DemoEditor.cpp
+++ b/sys/DemoEditor.cpp
@@ -108,7 +108,7 @@ void structDemoEditor :: v_createChildren () {
 }
 
 void DemoEditor_init (DemoEditor me) {
-	Editor_init (me, 0, 0, 1024, 768, U"", nullptr);
+	Editor_init (me, 0, 0, 1344, 756, U"", nullptr);   // 70 percent of the standard 1920x1080 screen
 	my graphics = Graphics_create_xmdrawingarea (my drawingArea);
 	Graphics_setColour (my graphics.get(), Graphics_WHITE);
 	Graphics_setWindow (my graphics.get(), 0.0, 1.0, 0.0, 1.0);
diff --git a/sys/EditorM.h b/sys/EditorM.h
index 6f997a5..909c9f9 100644
--- a/sys/EditorM.h
+++ b/sys/EditorM.h
@@ -2,7 +2,7 @@
 #define _EditorM_h_
 /* EditorM.h
  *
- * Copyright (C) 1992-2011,2013,2015 Paul Boersma
+ * Copyright (C) 1992-2011,2013,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,7 +18,6 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#undef FORM
 #undef REAL
 #undef REAL_OR_UNDEFINED
 #undef POSITIVE
@@ -35,20 +34,12 @@
 #undef RADIOBUTTON
 #undef OPTIONMENU
 #undef OPTION
-#undef RADIOBUTTONS_ENUM
-#undef OPTIONS_ENUM
 #undef RADIO_ENUM
 #undef OPTIONMENU_ENUM
 #undef LIST
-#undef OK
 #undef SET_REAL
 #undef SET_INTEGER
 #undef SET_STRING
-#undef DO
-#undef END
-#undef DIRECT
-#undef FORM_WRITE
-#undef DO_WRITE
 #undef GET_REAL
 #undef GET_INTEGER
 #undef GET_STRING
@@ -70,8 +61,6 @@
 #define RADIOBUTTON(label)	UiRadio_addButton (radio, label);
 #define OPTIONMENU(label,def)	radio = UiForm_addOptionMenu (cmd -> d_uiform.get(), label, def);
 #define OPTION(label)	UiOptionMenu_addButton (radio, label);
-#define RADIOBUTTONS_ENUM(labelProc,min,max) { for (int itext = min; itext <= max; itext ++) RADIOBUTTON (labelProc) }
-#define OPTIONS_ENUM(labelProc,min,max) { for (int itext = min; itext <= max; itext ++) OPTION (labelProc) }
 #define RADIO_ENUM(label,enum,def) \
 	RADIO (label, def - enum##_MIN + 1) \
 	for (int ienum = enum##_MIN; ienum <= enum##_MAX; ienum ++) \
@@ -98,11 +87,11 @@
 	UiForm_parseStringE (cmd, narg, args, sendingString, interpreter); } else {
 #define EDITOR_END  }
 
-#define EDITOR_FORM_WRITE(title,helpTitle) \
+#define EDITOR_FORM_SAVE(title,helpTitle) \
 	if (! cmd -> d_uiform) { \
 		cmd -> d_uiform = autoUiForm (UiOutfile_createE (cmd, title, cmd -> itemTitle, helpTitle)); \
 		} if (! sendingForm && ! args && ! sendingString) { char32 defaultName [300]; defaultName [0] = U'\0';
-#define EDITOR_DO_WRITE \
+#define EDITOR_DO_SAVE \
 	UiOutfile_do (cmd -> d_uiform.get(), defaultName); } else { MelderFile file; structMelderFile file2 { 0 }; \
 		if (! args && ! sendingString) file = UiFile_getFile (sendingForm); \
 		else { Melder_relativePathToFile (args ? args [1]. string : sendingString, & file2); file = & file2; }
diff --git a/sys/Formula.cpp b/sys/Formula.cpp
index e84b8ee..53b32e0 100644
--- a/sys/Formula.cpp
+++ b/sys/Formula.cpp
@@ -2128,7 +2128,9 @@ static void do_add () {
 			*/
 			double yvalue = y->number;
 			pushNumber (xvalue == NUMundefined || yvalue == NUMundefined ? NUMundefined : xvalue + yvalue);
-		} else if (y->which == Stackel_NUMERIC_VECTOR) {
+			return;
+		}
+		if (y->which == Stackel_NUMERIC_VECTOR) {
 			/*
 				result# = x + y#
 			*/
@@ -2145,7 +2147,9 @@ static void do_add () {
 				}
 			}
 			pushNumericVector (ny, result);
-		} else if (y->which == Stackel_NUMERIC_MATRIX) {
+			return;
+		}
+		if (y->which == Stackel_NUMERIC_MATRIX) {
 			/*
 				result## = x + y##
 			*/
@@ -2166,8 +2170,10 @@ static void do_add () {
 				}
 			}
 			pushNumericMatrix (nrow, ncol, result);
+			return;
 		}
-	} else if (x->which == Stackel_NUMERIC_VECTOR && y->which == Stackel_NUMERIC_VECTOR) {
+	}
+	if (x->which == Stackel_NUMERIC_VECTOR && y->which == Stackel_NUMERIC_VECTOR) {
 		long nx = x->numericVector.numberOfElements, ny = y->numericVector.numberOfElements;
 		if (nx != ny)
 			Melder_throw (U"When adding vectors, their numbers of elements should be equal, instead of ", nx, U" and ", ny, U".");
@@ -2178,7 +2184,9 @@ static void do_add () {
 			result [i] = xvalue == NUMundefined || yvalue == NUMundefined ? NUMundefined : xvalue + yvalue;
 		}
 		pushNumericVector (nx, result);
-	} else if (x->which == Stackel_NUMERIC_MATRIX && y->which == Stackel_NUMERIC_MATRIX) {
+		return;
+	}
+	if (x->which == Stackel_NUMERIC_MATRIX && y->which == Stackel_NUMERIC_MATRIX) {
 		long xnrow = x->numericMatrix.numberOfRows, xncol = x->numericMatrix.numberOfColumns;
 		long ynrow = y->numericMatrix.numberOfRows, yncol = y->numericMatrix.numberOfColumns;
 		if (xnrow != ynrow)
@@ -2194,15 +2202,17 @@ static void do_add () {
 			}
 		}
 		pushNumericMatrix (xnrow, xncol, result);
-	} else if (x->which == Stackel_STRING && y->which == Stackel_STRING) {
+		return;
+	}
+	if (x->which == Stackel_STRING && y->which == Stackel_STRING) {
 		long length1 = str32len (x->string), length2 = str32len (y->string);
 		char32 *result = Melder_malloc (char32, length1 + length2 + 1);
 		str32cpy (result, x->string);
 		str32cpy (result + length1, y->string);
 		pushString (result);
-	} else {
-		Melder_throw (U"Cannot add ", Stackel_whichText (y), U" to ", Stackel_whichText (x), U".");
+		return;
 	}
+	Melder_throw (U"Cannot add ", Stackel_whichText (y), U" to ", Stackel_whichText (x), U".");
 }
 static void do_sub () {
 	/*
@@ -2217,7 +2227,9 @@ static void do_sub () {
 			*/
 			double yvalue = y->number;
 			pushNumber (xvalue == NUMundefined || yvalue == NUMundefined ? NUMundefined : xvalue - yvalue);
-		} else if (y->which == Stackel_NUMERIC_VECTOR) {
+			return;
+		}
+		if (y->which == Stackel_NUMERIC_VECTOR) {
 			/*
 				result# = x - y#
 			*/
@@ -2234,7 +2246,9 @@ static void do_sub () {
 				}
 			}
 			pushNumericVector (ny, result);
-		} else if (y->which == Stackel_NUMERIC_MATRIX) {
+			return;
+		}
+		if (y->which == Stackel_NUMERIC_MATRIX) {
 			/*
 				result## = x - y##
 			*/
@@ -2255,8 +2269,10 @@ static void do_sub () {
 				}
 			}
 			pushNumericMatrix (nrow, ncol, result);
+			return;
 		}
-	} else if (x->which == Stackel_NUMERIC_VECTOR && y->which == Stackel_NUMERIC_VECTOR) {
+	}
+	if (x->which == Stackel_NUMERIC_VECTOR && y->which == Stackel_NUMERIC_VECTOR) {
 		long nx = x->numericVector.numberOfElements, ny = y->numericVector.numberOfElements;
 		if (nx != ny)
 			Melder_throw (U"When subtracting vectors, their numbers of elements should be equal, instead of ", nx, U" and ", ny, U".");
@@ -2267,7 +2283,9 @@ static void do_sub () {
 			result [i] = xvalue == NUMundefined || yvalue == NUMundefined ? NUMundefined : xvalue - yvalue;
 		}
 		pushNumericVector (nx, result);
-	} else if (x->which == Stackel_NUMERIC_MATRIX && y->which == Stackel_NUMERIC_MATRIX) {
+		return;
+	}
+	if (x->which == Stackel_NUMERIC_MATRIX && y->which == Stackel_NUMERIC_MATRIX) {
 		long xnrow = x->numericMatrix.numberOfRows, xncol = x->numericMatrix.numberOfColumns;
 		long ynrow = y->numericMatrix.numberOfRows, yncol = y->numericMatrix.numberOfColumns;
 		if (xnrow != ynrow)
@@ -2283,7 +2301,9 @@ static void do_sub () {
 			}
 		}
 		pushNumericMatrix (xnrow, xncol, result);
-	} else if (x->which == Stackel_STRING && y->which == Stackel_STRING) {
+		return;
+	}
+	if (x->which == Stackel_STRING && y->which == Stackel_STRING) {
 		int64 length1 = str32len (x->string), length2 = str32len (y->string), newlength = length1 - length2;
 		char32 *result;
 		if (newlength >= 0 && str32nequ (x->string + newlength, y->string, length2)) {
@@ -2294,9 +2314,9 @@ static void do_sub () {
 			result = Melder_dup (x->string);
 		}
 		pushString (result);
-	} else {
-		Melder_throw (U"Cannot subtract (-) ", Stackel_whichText (y), U" from ", Stackel_whichText (x), U".");
+		return;
 	}
+	Melder_throw (U"Cannot subtract (-) ", Stackel_whichText (y), U" from ", Stackel_whichText (x), U".");
 }
 static void do_mul () {
 	/*
@@ -2311,7 +2331,9 @@ static void do_mul () {
 			*/
 			double yvalue = y->number;
 			pushNumber (xvalue == NUMundefined || yvalue == NUMundefined ? NUMundefined : xvalue * yvalue);
-		} else if (y->which == Stackel_NUMERIC_VECTOR) {
+			return;
+		}
+		if (y->which == Stackel_NUMERIC_VECTOR) {
 			/*
 				result# = x * y#
 			*/
@@ -2328,7 +2350,9 @@ static void do_mul () {
 				}
 			}
 			pushNumericVector (ny, result);
-		} else if (y->which == Stackel_NUMERIC_MATRIX) {
+			return;
+		}
+		if (y->which == Stackel_NUMERIC_MATRIX) {
 			/*
 				result## = x * y##
 			*/
@@ -2349,8 +2373,10 @@ static void do_mul () {
 				}
 			}
 			pushNumericMatrix (nrow, ncol, result);
+			return;
 		}
-	} else if (x->which == Stackel_NUMERIC_VECTOR && y->which == Stackel_NUMERIC_VECTOR) {
+	}
+	if (x->which == Stackel_NUMERIC_VECTOR && y->which == Stackel_NUMERIC_VECTOR) {
 		/*
 			result# = x# * y#
 		*/
@@ -2364,9 +2390,9 @@ static void do_mul () {
 			result [i] = xvalue == NUMundefined || yvalue == NUMundefined ? NUMundefined : xvalue * yvalue;
 		}
 		pushNumericVector (nx, result);
-	} else {
-		Melder_throw (U"Cannot multiply (*) ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
+		return;
 	}
+	Melder_throw (U"Cannot multiply (*) ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
 }
 static void do_rdiv () {
 	Stackel y = pop, x = pop;
@@ -2374,7 +2400,9 @@ static void do_rdiv () {
 		pushNumber (x->number == NUMundefined || y->number == NUMundefined ? NUMundefined :
 			y->number == 0.0 ? NUMundefined :
 			x->number / y->number);
-	} else if (x->which == Stackel_NUMERIC_VECTOR) {
+		return;
+	}
+	if (x->which == Stackel_NUMERIC_VECTOR) {
 		if (y->which == Stackel_NUMERIC_VECTOR) {
 			long nelem1 = x->numericVector.numberOfElements, nelem2 = y->numericVector.numberOfElements;
 			if (nelem1 != nelem2)
@@ -2383,7 +2411,9 @@ static void do_rdiv () {
 			for (long ielem = 1; ielem <= nelem1; ielem ++)
 				result [ielem] = y->numericVector.data [ielem] == 0.0 ? NUMundefined : x->numericVector.data [ielem] / y->numericVector.data [ielem];
 			pushNumericVector (nelem1, result);
-		} else if (y->which == Stackel_NUMBER) {
+			return;
+		}
+		if (y->which == Stackel_NUMBER) {
 			/*
 				result# = x# / y
 			*/
@@ -2399,12 +2429,10 @@ static void do_rdiv () {
 				}
 			}
 			pushNumericVector (xn, result);
-		} else {
-			Melder_throw (U"Cannot divide (/) ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
+			return;
 		}
-	} else {
-		Melder_throw (U"Cannot divide (/) ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
 	}
+	Melder_throw (U"Cannot divide (/) ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
 }
 static void do_idiv () {
 	Stackel y = pop, x = pop;
@@ -2412,9 +2440,9 @@ static void do_idiv () {
 		pushNumber (x->number == NUMundefined || y->number == NUMundefined ? NUMundefined :
 			y->number == 0.0 ? NUMundefined :
 			floor (x->number / y->number));
-	} else {
-		Melder_throw (U"Cannot divide (\"div\") ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
+		return;
 	}
+	Melder_throw (U"Cannot divide (\"div\") ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
 }
 static void do_mod () {
 	Stackel y = pop, x = pop;
@@ -2422,9 +2450,9 @@ static void do_mod () {
 		pushNumber (x->number == NUMundefined || y->number == NUMundefined ? NUMundefined :
 			y->number == 0.0 ? NUMundefined :
 			x->number - floor (x->number / y->number) * y->number);
-	} else {
-		Melder_throw (U"Cannot divide (\"mod\") ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
+		return;
 	}
+	Melder_throw (U"Cannot divide (\"mod\") ", Stackel_whichText (x), U" by ", Stackel_whichText (y), U".");
 }
 static void do_minus () {
 	Stackel x = pop;
diff --git a/sys/Gui.h b/sys/Gui.h
index 115d5cd..ca89647 100644
--- a/sys/Gui.h
+++ b/sys/Gui.h
@@ -657,9 +657,9 @@ Thing_define (GuiMenuItem, GuiThing) {
 #define GuiMenu_BUTTON_STATE_MASK  (GuiMenu_INSENSITIVE|GuiMenu_CHECKBUTTON|GuiMenu_TOGGLE_ON|GuiMenu_ATTRACTIVE|GuiMenu_RADIO_FIRST|GuiMenu_RADIO_NEXT)
 
 /* Accelerators: */
-#define GuiMenu_OPTION  (1 << 21)
-#define GuiMenu_SHIFT  (1 << 22)
-#define GuiMenu_COMMAND  (1 << 23)
+#define GuiMenu_OPTION  (1 << 24)
+#define GuiMenu_SHIFT  (1 << 25)
+#define GuiMenu_COMMAND  (1 << 26)
 #define GuiMenu_LEFT_ARROW  1
 #define GuiMenu_RIGHT_ARROW  2
 #define GuiMenu_UP_ARROW  3
diff --git a/sys/GuiButton.cpp b/sys/GuiButton.cpp
index b4508e3..b57d569 100644
--- a/sys/GuiButton.cpp
+++ b/sys/GuiButton.cpp
@@ -70,7 +70,7 @@ Thing_implement (GuiButton, GuiControl, 0);
 			try {
 				my d_activateCallback (my d_activateBoss, & event);
 			} catch (MelderError) {
-				Melder_flushError (U"Your click on button \"", U"xx", U"\" was not completely handled.");
+				Melder_flushError (U"Your click on button \"", my name, U"\" was not completely handled.");
 			}
 		}
 	}
@@ -139,6 +139,7 @@ GuiButton GuiButton_create (GuiForm parent, int left, int right, int top, int bo
 //		}
 	#elif cocoa
 		GuiCocoaButton *button = [[GuiCocoaButton alloc] init];
+		my name = Melder_dup (buttonText);
 		my d_widget = (GuiObject) button;
 		my v_positionInForm (my d_widget, left, right, top, bottom, parent);
 		[button setUserData: me.get()];
diff --git a/sys/GuiMenu.cpp b/sys/GuiMenu.cpp
index 76cd2d5..06e094b 100644
--- a/sys/GuiMenu.cpp
+++ b/sys/GuiMenu.cpp
@@ -17,6 +17,7 @@
  */
 
 #include "GuiP.h"
+#include "praatP.h"   // BUG
 
 Thing_implement (GuiMenu, GuiThing, 0);
 
@@ -172,6 +173,7 @@ void structGuiMenu :: v_destroy () noexcept {
 	- (void) application: (NSApplication *) sender openFiles: (NSArray *) fileNames
 	{
 		(void) sender;
+		if (praatP.userWantsToOpen) return;
 		for (NSUInteger i = 1; i <= [fileNames count]; i ++) {
 			NSString *cocoaFileName = [fileNames objectAtIndex: i - 1];
 			structMelderFile file = { 0 };
diff --git a/sys/InfoEditor.cpp b/sys/InfoEditor.cpp
index 236e6ee..bf095df 100644
--- a/sys/InfoEditor.cpp
+++ b/sys/InfoEditor.cpp
@@ -31,8 +31,7 @@ void structInfoEditor :: v_clear () {
 	Melder_clearInfo ();
 }
 
-void gui_information (const char32 *message);   // BUG
-void gui_information (const char32 *message) {
+InfoEditor InfoEditor_getTheReferenceToTheOnlyInstance () {
 	if (! theReferenceToTheOnlyInfoEditor) {
 		autoInfoEditor editor = Thing_new (InfoEditor);
 		TextEditor_init (editor.get(), U"");
@@ -40,8 +39,14 @@ void gui_information (const char32 *message) {
 		theReferenceToTheOnlyInfoEditor = editor.get();
 		editor.releaseToUser();
 	}
-	GuiText_setString (theReferenceToTheOnlyInfoEditor -> textWidget, message);
-	GuiThing_show (theReferenceToTheOnlyInfoEditor -> d_windowForm);
+	return theReferenceToTheOnlyInfoEditor;
+}
+
+void gui_information (const char32 *message);   // BUG
+void gui_information (const char32 *message) {
+	InfoEditor editor = InfoEditor_getTheReferenceToTheOnlyInstance ();
+	GuiText_setString (editor -> textWidget, message);
+	GuiThing_show (editor -> d_windowForm);
 	/*
 	 * Try to make sure that the invalidated text widget and the elements of the fronted window are redrawn before the next event.
 	 */
@@ -60,21 +65,21 @@ void gui_information (const char32 *message) {
 			}
 		#else
 			/*
-				The following is an attempt to explicitly perform the actions that event polling is supposed to perform.
-				It would be nice not to actually have to poll events (with nextEventMatchingMask),
+				The following is an attempt to explicitly perform the actions that event waiting is supposed to perform.
+				It would be nice not to actually have to wait for events (with nextEventMatchingMask),
 				because we are not interested in the events; we're interested only in the graphics update.
 			*/
-			//[theReferenceToTheOnlyInfoEditor -> d_windowForm -> d_cocoaWindow   displayIfNeeded];   // apparently, this does not suffice
-			//[theReferenceToTheOnlyInfoEditor -> textWidget -> d_cocoaTextView   lockFocus];   // this displays the menu as well as the text
-			[theReferenceToTheOnlyInfoEditor -> d_windowForm -> d_cocoaWindow   display];   // this displays the menu as well as the text
-			//[theReferenceToTheOnlyInfoEditor -> textWidget -> d_cocoaTextView   displayIfNeeded];   // this displays only the text
-			//[theReferenceToTheOnlyInfoEditor -> textWidget -> d_cocoaTextView   display];
-			//[theReferenceToTheOnlyInfoEditor -> textWidget -> d_cocoaTextView   unlockFocus];   // this displays the menu as well as the text
-			[theReferenceToTheOnlyInfoEditor -> d_windowForm -> d_cocoaWindow   flushWindow];
+			//[editor -> d_windowForm -> d_cocoaWindow   displayIfNeeded];   // apparently, this does not suffice
+			//[editor -> textWidget -> d_cocoaTextView   lockFocus];   // this displays the menu as well as the text
+			[editor -> d_windowForm -> d_cocoaWindow   display];   // this displays the menu as well as the text
+			//[editor -> textWidget -> d_cocoaTextView   displayIfNeeded];   // this displays only the text
+			//[editor -> textWidget -> d_cocoaTextView   display];
+			//[editor -> textWidget -> d_cocoaTextView   unlockFocus];   // this displays the menu as well as the text
+			[editor -> d_windowForm -> d_cocoaWindow   flushWindow];
 			[NSApp  updateWindows];   // called automatically?
 		#endif
 	#elif defined (macintosh)
-		GuiShell_drain (theReferenceToTheOnlyInfoEditor -> d_windowForm);
+		GuiShell_drain (editor -> d_windowForm);
 	#endif
 }
 
diff --git a/sys/InfoEditor.h b/sys/InfoEditor.h
index 032e683..6105209 100644
--- a/sys/InfoEditor.h
+++ b/sys/InfoEditor.h
@@ -2,7 +2,7 @@
 #define _InfoEditor_h_
 /* InfoEditor.h
  *
- * Copyright (C) 2004-2011,2015 Paul Boersma
+ * Copyright (C) 2004-2011,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,5 +31,7 @@ Thing_define (InfoEditor, TextEditor) {
 		override;
 };
 
+InfoEditor InfoEditor_getTheReferenceToTheOnlyInstance ();
+
 /* End of file InfoEditor.h */
 #endif
diff --git a/sys/Makefile b/sys/Makefile
index b1ad348..e633149 100644
--- a/sys/Makefile
+++ b/sys/Makefile
@@ -1,9 +1,9 @@
 # Makefile of the library "sys"
-# Paul Boersma, 21 June 2015
+# Paul Boersma, 22 October 2016
 
 include ../makefile.defs
 
-CPPFLAGS = -I ../num -I ../sys -I ../dwsys -I ../kar -I ../external/portaudio -I ../external/flac -I ../external/mp3
+CPPFLAGS = -I ../sys -I ../num -I ../dwsys -I ../kar -I ../external/portaudio -I ../external/flac -I ../external/mp3
 
 OBJECTS = abcio.o complex.o \
    melder_ftoa.o melder_atof.o melder_error.o melder_alloc.o melder.o melder_strings.o \
@@ -20,9 +20,10 @@ OBJECTS = abcio.o complex.o \
    Preferences.o site.o \
    Picture.o Ui.o UiFile.o UiPause.o Editor.o DataEditor.o HyperPage.o Manual.o TextEditor.o \
    praat.o praat_actions.o praat_menuCommands.o praat_picture.o sendpraat.o sendsocket.o \
-   praat_script.o praat_statistics.o praat_logo.o \
+   praat_script.o praat_statistics.o praat_logo.o praat_library.o \
    praat_objectMenus.o InfoEditor.o ScriptEditor.o ButtonEditor.o Interpreter.o Formula.o \
    StringsEditor.o DemoEditor.o \
+   MelderGui.o \
    motifEmulator.o GuiText.o GuiWindow.o Gui.o GuiObject.o GuiDrawingArea.o \
    GuiMenu.o GuiMenuItem.o GuiButton.o GuiLabel.o GuiCheckButton.o GuiRadioButton.o \
    GuiDialog.o GuiList.o GuiFileSelect.o GuiScale.o GuiScrollBar.o GuiScrolledWindow.o \
diff --git a/sys/Manual.cpp b/sys/Manual.cpp
index 2e0620b..72fe92e 100644
--- a/sys/Manual.cpp
+++ b/sys/Manual.cpp
@@ -37,7 +37,7 @@ static const char32 *month [] =
 	  U"July", U"August", U"September", U"October", U"November", U"December" };
 
 static void menu_cb_writeOneToHtmlFile (Manual me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM_WRITE (U"Save as HTML file", nullptr)
+	EDITOR_FORM_SAVE (U"Save as HTML file", nullptr)
 		ManPages manPages = (ManPages) my data;
 		autoMelderString buffer;
 		MelderString_copy (& buffer, manPages -> pages.at [my path] -> title);
@@ -45,7 +45,7 @@ static void menu_cb_writeOneToHtmlFile (Manual me, EDITOR_ARGS_FORM) {
 		while (*p) { if (! isalnum ((int) *p) && *p != U'_') *p = U'_'; p ++; }
 		MelderString_append (& buffer, U".html");
 		Melder_sprint (defaultName,300, buffer.string);
-	EDITOR_DO_WRITE
+	EDITOR_DO_SAVE
 		ManPages_writeOneToHtmlFile ((ManPages) my data, my path, file);
 	EDITOR_END
 }
diff --git a/sys/MelderGui.cpp b/sys/MelderGui.cpp
new file mode 100644
index 0000000..d540dd8
--- /dev/null
+++ b/sys/MelderGui.cpp
@@ -0,0 +1,379 @@
+/* MelderGui.cpp
+ *
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma, 2008 Stefan de Konink, 2010 Franz Brausse, 2013 Tom Naughton
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <time.h>
+//#include <ctype.h>
+
+#include <assert.h>
+#include "melder.h"
+#ifdef _WIN32
+	#include <windows.h>
+#endif
+
+#include "Graphics.h"
+#include "Gui.h"
+
+/********** Exported variable. **********/
+
+static GuiWindow Melder_topShell;
+
+/********** PROGRESS **********/
+
+static bool theProgressCancelled = false;
+
+static bool waitWhileProgress (double progress, const char32 *message, GuiDialog dia, GuiProgressBar scale, GuiLabel label1, GuiLabel label2, GuiButton cancelButton) {
+	#if gtk
+		// Wait for all pending events to be processed. If anybody knows how to inspect GTK's
+		// event queue for specific events, dump the code here, please.
+		// Until then, the button click attaches a g_object data key named "pressed" to the cancelButton
+		// which this function reads out in order to tell whether interruption has occurred
+		while (gtk_events_pending ()) {
+			trace (U"event pending");
+			gtk_main_iteration ();
+		}
+	#elif defined (macintosh)
+		NSEvent *nsEvent = [NSApp
+			nextEventMatchingMask: NSAnyEventMask
+			untilDate: [NSDate distantPast]
+			inMode: NSDefaultRunLoopMode
+			dequeue: YES
+			];
+		if (nsEvent) {
+			NSUInteger nsEventType = [nsEvent type];
+			if (nsEventType == NSKeyDown) NSBeep ();
+			[[nsEvent window]  sendEvent: nsEvent];
+		}
+	#elif defined (_WIN32)
+		XEvent event;
+		while (PeekMessage (& event, 0, 0, 0, PM_REMOVE)) {
+			if (event. message == WM_KEYDOWN) {
+				/*
+				 * Ignore all key-down messages, except Escape.
+				 */
+				if (LOWORD (event. wParam) == VK_ESCAPE) {
+					XtUnmanageChild (dia -> d_widget);
+					return false;   // don't continue
+				}
+			} else if (event. message == WM_LBUTTONDOWN) {
+				/*
+				 * Ignore all mouse-down messages, except click in Interrupt button.
+				 */
+				GuiObject me = (GuiObject) GetWindowLongPtr (event. hwnd, GWLP_USERDATA);
+				if (me == cancelButton -> d_widget) {
+					XtUnmanageChild (dia -> d_widget);
+					return false;   // don't continue
+				}
+			} else if (event. message != WM_SYSKEYDOWN) {
+				/*
+				 * Process paint messages etc.
+				 */
+				DispatchMessage (& event);
+			}
+		}
+	#endif
+	if (progress >= 1.0) {
+		GuiThing_hide (dia);
+	} else {
+		if (progress <= 0.0) progress = 0.0;
+		GuiThing_show (dia);   // TODO: prevent raising to the front
+		const char32 *newline = str32chr (message, U'\n');
+		if (newline) {
+			static MelderString buffer { 0 };
+			MelderString_copy (& buffer, message);
+			buffer.string [newline - message] = U'\0';
+			GuiLabel_setText (label1, buffer.string);
+			buffer.string [newline - message] = U'\n';
+			GuiLabel_setText (label2, buffer.string + (newline - message) + 1);
+		} else {
+			GuiLabel_setText (label1, message);
+			GuiLabel_setText (label2, U"");
+		}
+		#if gtk
+			trace (U"update the progress bar");
+			GuiProgressBar_setValue (scale, progress);
+			while (gtk_events_pending ()) {
+				trace (U"event pending");
+				gtk_main_iteration ();
+			}
+			trace (U"check whether the cancel button has the \"pressed\" key set");
+			if (g_object_steal_data (G_OBJECT (cancelButton -> d_widget), "pressed")) {
+				trace (U"the cancel button has been pressed");
+				return false;   // don't continue
+			}
+		#elif cocoa
+			GuiProgressBar_setValue (scale, progress);
+			//[scale -> d_cocoaProgressBar   displayIfNeeded];
+			if (theProgressCancelled) {
+				theProgressCancelled = false;
+				return false;
+			}
+		#elif motif
+			GuiProgressBar_setValue (scale, progress);
+			GdiFlush ();
+		#endif
+	}
+	trace (U"continue");
+	return true;
+}
+
+static GuiButton theProgressCancelButton = nullptr;
+
+#if gtk || macintosh
+static void progress_dia_close (Thing /* boss */) {
+	theProgressCancelled = true;
+	#if gtk
+		g_object_set_data (G_OBJECT (theProgressCancelButton -> d_widget), "pressed", (gpointer) 1);
+	#endif
+}
+static void progress_cancel_btn_press (Thing /* boss */, GuiButtonEvent /* event */) {
+	theProgressCancelled = true;
+	#if gtk
+		g_object_set_data (G_OBJECT (theProgressCancelButton -> d_widget), "pressed", (gpointer) 1);
+	#endif
+}
+#endif
+
+static void _Melder_dia_init (GuiDialog *dia, GuiProgressBar *scale, GuiLabel *label1, GuiLabel *label2, GuiButton *cancelButton, bool hasMonitor) {
+	trace (U"creating the dialog");
+	*dia = GuiDialog_create (Melder_topShell, 200, 100, 400, hasMonitor ? 430 : 200, U"Work in progress",
+		#if gtk || macintosh
+			progress_dia_close, nullptr,
+		#else
+			nullptr, nullptr,
+		#endif
+		0);
+
+	trace (U"creating the labels");
+	*label1 = GuiLabel_createShown (*dia, 3, 403, 0, Gui_LABEL_HEIGHT, U"label1", 0);
+	*label2 = GuiLabel_createShown (*dia, 3, 403, 30, 30 + Gui_LABEL_HEIGHT, U"label2", 0);
+
+	trace (U"creating the scale");
+	*scale = GuiProgressBar_createShown (*dia, 3, -3, 70, 110, 0);
+
+	trace (U"creating the cancel button");
+	*cancelButton = GuiButton_createShown (*dia, 0, 400, 170, 170 + Gui_PUSHBUTTON_HEIGHT,
+		U"Interrupt",
+		#if gtk
+			progress_cancel_btn_press, nullptr,
+		#elif macintosh
+			progress_cancel_btn_press, nullptr,
+		#else
+			nullptr, nullptr,
+		#endif
+		0);
+	trace (U"end");
+}
+
+static void gui_progress (double progress, const char32 *message) {
+	static clock_t lastTime;
+	static GuiDialog dia = nullptr;
+	static GuiProgressBar scale = nullptr;
+	static GuiLabel label1 = nullptr, label2 = nullptr;
+	clock_t now = clock ();
+	if (progress <= 0.0 || progress >= 1.0 ||
+		now - lastTime > CLOCKS_PER_SEC / 4)   // this time step must be much longer than the null-event waiting time
+	{
+		if (! dia)
+			_Melder_dia_init (& dia, & scale, & label1, & label2, & theProgressCancelButton, false);
+		if (! waitWhileProgress (progress, message, dia, scale, label1, label2, theProgressCancelButton))
+			Melder_throw (U"Interrupted!");
+		lastTime = now;
+	}
+}
+
+static autoGraphics graphics;
+
+static void gui_drawingarea_cb_expose (Thing /* boss */, GuiDrawingArea_ExposeEvent /* event */) {
+	if (! graphics) return;
+	Graphics_play (graphics.get(), graphics.get());
+}
+
+static void * gui_monitor (double progress, const char32 *message) {
+	static clock_t lastTime;
+	static GuiDialog dia = nullptr;
+	static GuiProgressBar scale = nullptr;
+	static GuiDrawingArea drawingArea = nullptr;
+	static GuiButton cancelButton = nullptr;
+	static GuiLabel label1 = nullptr, label2 = nullptr;
+	clock_t now = clock ();
+	if (progress <= 0.0 || progress >= 1.0 ||
+		now - lastTime > CLOCKS_PER_SEC / 4)   // this time step must be much longer than the null-event waiting time
+	{
+		if (! dia) {
+			_Melder_dia_init (& dia, & scale, & label1, & label2, & cancelButton, true);
+			drawingArea = GuiDrawingArea_createShown (dia, 0, 400, 230, 430, gui_drawingarea_cb_expose, nullptr, nullptr, nullptr, nullptr, 0);
+			GuiThing_show (dia);
+			graphics = Graphics_create_xmdrawingarea (drawingArea);
+		}
+		if (graphics)
+			Graphics_flushWs (graphics.get());
+		if (! waitWhileProgress (progress, message, dia, scale, label1, label2, cancelButton))
+			Melder_throw (U"Interrupted!");
+		lastTime = now;
+		if (progress == 0.0)
+			return graphics.get();
+	}
+	return nullptr;
+}
+
+#if defined (macintosh)
+static void mac_message (NSAlertStyle macAlertType, const char32 *message32) {
+	static unichar messageU [4000];
+	int messageLength = str32len (message32);
+	int j = 0;
+	for (int i = 0; i < messageLength && j <= 4000 - 3; i ++) {
+		char32 kar = message32 [i];
+		if (kar <= 0x00FFFF) {
+			messageU [j ++] = kar;
+		} else if (kar <= 0x10FFFF) {
+			kar -= 0x010000;
+			messageU [j ++] = 0x00D800 | (kar >> 10);
+			messageU [j ++] = 0x00DC00 | (kar & 0x0003FF);
+		}
+	}
+	messageU [j] = '\0';   // append null byte because we are going to search this string
+
+	/*
+	 * Split up the message between header (will appear in bold) and rest.
+	 * The split is done at the first line break, except if the first line ends in a colon,
+	 * in which case the split is done at the second line break.
+	 */
+	UniChar *lineBreak = & messageU [0];
+	for (; *lineBreak != '\0'; lineBreak ++) {
+		if (*lineBreak == '\n') {
+			break;
+		}
+	}
+	if (*lineBreak == '\n' && lineBreak - messageU > 0 && lineBreak [-1] == ':') {
+		for (lineBreak ++; *lineBreak != '\0'; lineBreak ++) {
+			if (*lineBreak == '\n') {
+				break;
+			}
+		}
+	}
+	/*
+	 * Create an alert dialog with an icon that is appropriate for the level.
+	 */
+	NSAlert *alert = [[NSAlert alloc] init];
+	[alert setAlertStyle: macAlertType];
+	/*
+	 * Add the header in bold.
+	 */
+	NSString *header = [[NSString alloc] initWithCharacters: messageU   length: lineBreak - messageU];   // note: init can change the object pointer!
+	if (header) {   // make this very safe, because we can be at error time or at fatal time
+		[alert setMessageText: header];
+		[header release];
+	}
+	/*
+	 * Add the rest of the message in small type.
+	 */
+	if (lineBreak - messageU < j) {
+		NSString *rest = [[NSString alloc] initWithCharacters: lineBreak + 1   length: j - 1 - (lineBreak - messageU)];
+		if (rest) {   // make this very safe, because we can be at error time or at fatal time
+			[alert setInformativeText: rest];
+			[rest release];
+		}
+	}
+	/*
+	 * Display the alert dialog and synchronously wait for the user to click OK.
+	 */
+	[alert runModal];
+	[alert release];
+}
+#endif
+
+#define theMessageFund_SIZE  100000
+static char * theMessageFund = nullptr;
+
+static void gui_fatal (const char32 *message) {
+	free (theMessageFund);
+	#if gtk
+		GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", Melder_peek32to8 (message));
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+	#elif defined (macintosh)
+		mac_message (NSCriticalAlertStyle, message);
+		SysError (11);
+	#elif defined (_WIN32)
+		MessageBox (nullptr, Melder_peek32toW (message), L"Fatal error", MB_OK | MB_TOPMOST | MB_ICONSTOP);
+	#endif
+}
+
+static void gui_error (const char32 *message) {
+	bool memoryIsLow = str32str (message, U"Out of memory");
+	if (memoryIsLow) {
+		free (theMessageFund);
+	}
+	#if gtk
+		trace (U"create dialog");
+		GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", Melder_peek32to8 (message));
+		trace (U"run dialog");
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		trace (U"destroy dialog");
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+	#elif defined (macintosh)
+		mac_message (NSWarningAlertStyle, message);
+	#elif defined (_WIN32)
+		MessageBox (nullptr, Melder_peek32toW (message), L"Message", MB_OK | MB_TOPMOST | MB_ICONWARNING);   // or (HWND) XtWindow ((GuiObject) Melder_topShell)
+	#endif
+	if (memoryIsLow) {
+		theMessageFund = (char *) malloc (theMessageFund_SIZE);
+		if (! theMessageFund) {
+			#if gtk
+				GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
+					GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
+				gtk_dialog_run (GTK_DIALOG (dialog));
+				gtk_widget_destroy (GTK_WIDGET (dialog));
+			#elif defined (macintosh)
+				mac_message (NSCriticalAlertStyle, U"Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
+			#elif defined (_WIN32)
+				MessageBox (nullptr, L"Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.", L"Message", MB_OK);
+			#endif
+		}
+	}
+}
+
+static void gui_warning (const char32 *message) {
+	#if gtk
+		GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", Melder_peek32to8 (message));
+		gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+	#elif defined (macintosh)
+		mac_message (NSInformationalAlertStyle, message);
+	#elif defined (_WIN32)
+		MessageBox (nullptr, Melder_peek32toW (message), L"Warning", MB_OK | MB_TOPMOST | MB_ICONINFORMATION);
+	#endif
+}
+
+void gui_information (const char32 *);   // BUG: no prototype
+void MelderGui_create (void *parent) {
+	theMessageFund = (char *) malloc (theMessageFund_SIZE);
+	assert (theMessageFund);
+	Melder_topShell = (GuiWindow) parent;
+	Melder_setInformationProc (gui_information);
+	Melder_setFatalProc (gui_fatal);
+	Melder_setErrorProc (gui_error);
+	Melder_setWarningProc (gui_warning);
+	Melder_setProgressProc (gui_progress);
+	Melder_setMonitorProc (gui_monitor);
+}
+
+/* End of file MelderGui.cpp */
diff --git a/sys/Strings.cpp b/sys/Strings.cpp
index 7439696..581cbef 100644
--- a/sys/Strings.cpp
+++ b/sys/Strings.cpp
@@ -132,7 +132,6 @@ static autoStrings Strings_createAsFileOrDirectoryList (const char32 *path /* ca
 				Melder_throw (U"Cannot open directory ", searchDirectory. string, U".");
 			//Melder_casual (U"opened");
 			autoStrings me = Thing_new (Strings);
-			my strings = NUMvector <char32 *> (1, 1000000);
 			struct dirent *entry;
 			while (!! (entry = readdir (d))) {
 				MelderString_copy (& filePath, searchDirectory. string [0] ? searchDirectory. string : U".");
@@ -158,7 +157,7 @@ static autoStrings Strings_createAsFileOrDirectoryList (const char32 *path /* ca
 						(left. length == 0 || str32nequ (buffer32, left. string, left. length)) &&
 						(right. length == 0 || (length >= right. length && str32equ (buffer32 + (length - right. length), right. string))))
 					{
-						my strings [++ my numberOfStrings] = Melder_dup (buffer32);
+						Strings_insert (me.get(), 0, buffer32);
 					}
 				}
 			}
@@ -176,7 +175,6 @@ static autoStrings Strings_createAsFileOrDirectoryList (const char32 *path /* ca
 			bool hasAsterisk = !! str32chr (path, U'*');
 			bool endsInSeparator = ( len != 0 && path [len - 1] == U'\\' );
 			autoStrings me = Thing_new (Strings);
-			my strings = NUMvector <char32 *> (1, 1000000);
 			Melder_sprint (searchPath, kMelder_MAXPATH+1, path, hasAsterisk || endsInSeparator ? U"" : U"\\", hasAsterisk ? U"" : U"*");
 			WIN32_FIND_DATAW findData;
 			HANDLE searchHandle = FindFirstFileW (Melder_peek32toW (searchPath), & findData);
@@ -188,7 +186,7 @@ static autoStrings Strings_createAsFileOrDirectoryList (const char32 *path /* ca
 							(findData. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
 					{
 						if (findData. cFileName [0] != L'.') {
-							my strings [++ my numberOfStrings] = Melder_dup (Melder_peekWto32 (findData. cFileName));
+							Strings_insert (me.get(), 0, Melder_peekWto32 (findData. cFileName));
 						}
 					}
 				} while (FindNextFileW (searchHandle, & findData));
@@ -339,14 +337,20 @@ void Strings_insert (Strings me, long position, const char32 *text) {
 	 * Create without change.
 	 */
 	autostring32 newString = Melder_dup (text);
+	autoNUMvector <char32 *> newStrings (1, my numberOfStrings + 1);
 	/*
 	 * Change without error.
 	 */
-	for (long i = my numberOfStrings + 1; i > position; i --) {
-		my strings [i] = my strings [i - 1];
+	for (long i = 1; i < position; i ++) {
+		newStrings [i] = my strings [i];
 	}
-	my strings [position] = newString.transfer();
+	newStrings [position] = newString.transfer();
 	my numberOfStrings ++;
+	for (long i = position + 1; i <= my numberOfStrings; i ++) {
+		newStrings [i] = my strings [i - 1];
+	}
+	NUMvector_free (my strings, 1);
+	my strings = newStrings.transfer();
 }
 
 /* End of file Strings.cpp */
diff --git a/sys/TextEditor.cpp b/sys/TextEditor.cpp
index 90e3820..fbd5571 100644
--- a/sys/TextEditor.cpp
+++ b/sys/TextEditor.cpp
@@ -251,33 +251,67 @@ static void menu_cb_new (TextEditor me, EDITOR_ARGS_CMD) {
 	}
 }
 
-static void menu_cb_clear (TextEditor me, EDITOR_ARGS_DIRECT) {
-	my v_clear ();
+static void gui_button_cb_cancelReopen (EditorCommand cmd, GuiButtonEvent /* event */) {
+	TextEditor me = (TextEditor) cmd -> d_editor;
+	GuiThing_hide (my dirtyReopenDialog);
 }
 
-static void menu_cb_save (TextEditor me, EDITOR_ARGS_CMD) {
-	if (my name [0]) {
+static void gui_button_cb_discardAndReopen (EditorCommand cmd, GuiButtonEvent /* event */) {
+	TextEditor me = (TextEditor) cmd -> d_editor;
+	GuiThing_hide (my dirtyReopenDialog);
+	openDocument (me, & my file);
+}
+
+static void menu_cb_reopen (TextEditor me, EDITOR_ARGS_CMD) {
+	Melder_assert (my v_fileBased());
+	if (my name [0] == U'\0') {
+		Melder_throw (U"Cannot reopen from disk, because the text has never been saved yet.");
+	}
+	if (my dirty) {
+		if (! my dirtyReopenDialog) {
+			int buttonWidth = 250, buttonSpacing = 20;
+			my dirtyReopenDialog = GuiDialog_create (my d_windowForm,
+				150, 70, Gui_LEFT_DIALOG_SPACING + 2 * buttonWidth + 1 * buttonSpacing + Gui_RIGHT_DIALOG_SPACING,
+					Gui_TOP_DIALOG_SPACING + Gui_TEXTFIELD_HEIGHT + Gui_VERTICAL_DIALOG_SPACING_SAME + 2 * Gui_BOTTOM_DIALOG_SPACING + Gui_PUSHBUTTON_HEIGHT,
+				U"Text changed", nullptr, nullptr, GuiDialog_MODAL);
+			GuiLabel_createShown (my dirtyReopenDialog,
+				Gui_LEFT_DIALOG_SPACING, - Gui_RIGHT_DIALOG_SPACING,
+				Gui_TOP_DIALOG_SPACING, Gui_TOP_DIALOG_SPACING + Gui_LABEL_HEIGHT,
+				U"The text in the editor contains changes! Reopen nevertheless?", 0);
+			int x = Gui_LEFT_DIALOG_SPACING, y = - Gui_BOTTOM_DIALOG_SPACING;
+			GuiButton_createShown (my dirtyReopenDialog,
+				x, x + buttonWidth, y - Gui_PUSHBUTTON_HEIGHT, y,
+				U"Keep visible version", gui_button_cb_cancelReopen, cmd, GuiButton_CANCEL);
+			x += buttonWidth + buttonSpacing;
+			GuiButton_createShown (my dirtyReopenDialog,
+				x, x + buttonWidth, y - Gui_PUSHBUTTON_HEIGHT, y,
+				U"Replace with version from disk", gui_button_cb_discardAndReopen, cmd, GuiButton_DEFAULT);
+		}
+		GuiThing_show (my dirtyReopenDialog);
+	} else {
 		try {
-			saveDocument (me, & my file);
+			openDocument (me, & my file);
 		} catch (MelderError) {
 			Melder_flushError ();
 			return;
 		}
-	} else {
-		menu_cb_saveAs (me, cmd, nullptr, 0, nullptr, nullptr, nullptr);
 	}
 }
 
-static void menu_cb_reopen (TextEditor me, EDITOR_ARGS_DIRECT) {
+static void menu_cb_clear (TextEditor me, EDITOR_ARGS_DIRECT) {
+	my v_clear ();
+}
+
+static void menu_cb_save (TextEditor me, EDITOR_ARGS_CMD) {
 	if (my name [0]) {
 		try {
-			openDocument (me, & my file);
+			saveDocument (me, & my file);
 		} catch (MelderError) {
 			Melder_flushError ();
 			return;
 		}
 	} else {
-		Melder_throw (U"Cannot reopen from disk, because the text has never been saved yet.");
+		menu_cb_saveAs (me, cmd, nullptr, 0, nullptr, nullptr, nullptr);
 	}
 }
 
@@ -330,6 +364,9 @@ void structTextEditor :: v_goAway () {
 				x, x + buttonWidth, y - Gui_PUSHBUTTON_HEIGHT, y,
 				U"Save & Close", gui_button_cb_saveAndClose, this, 0);
 		}
+		if (our dirtyNewDialog) GuiThing_hide (our dirtyNewDialog);
+		if (our dirtyOpenDialog) GuiThing_hide (our dirtyOpenDialog);
+		if (our dirtyReopenDialog) GuiThing_hide (our dirtyReopenDialog);
 		GuiThing_show (dirtyCloseDialog);
 	} else {
 		closeDocument (this);
@@ -435,7 +472,7 @@ static void do_replace (TextEditor me) {
 }
 
 static void menu_cb_find (TextEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM (U"Find", 0)
+	EDITOR_FORM (U"Find", nullptr)
 		LABEL (U"", U"Find:")
 		TEXTFIELD (U"findString", U"")
 	EDITOR_OK
@@ -452,7 +489,7 @@ static void menu_cb_findAgain (TextEditor me, EDITOR_ARGS_DIRECT) {
 }
 
 static void menu_cb_replace (TextEditor me, EDITOR_ARGS_FORM) {
-	EDITOR_FORM (U"Find", 0)
+	EDITOR_FORM (U"Find", nullptr)
 		LABEL (U"", U"This is a \"slow\" find-and-replace method;")
 		LABEL (U"", U"if the selected text is identical to the Find string,")
 		LABEL (U"", U"the selected text will be replaced by the Replace string;")
@@ -604,7 +641,7 @@ void structTextEditor :: v_createMenus () {
 	if (v_fileBased ()) {
 		Editor_addCommand (this, U"File", U"New", 'N', menu_cb_new);
 		Editor_addCommand (this, U"File", U"Open...", 'O', menu_cb_open);
-		Editor_addCommand (this, U"File", U"Reopen from disk", 0, menu_cb_reopen);
+		Editor_addCommand (this, U"File", U"Reopen from disk", GuiMenu_SHIFT | 'O', menu_cb_reopen);
 	} else {
 		Editor_addCommand (this, U"File", U"Clear", 'N', menu_cb_clear);
 	}
@@ -627,8 +664,8 @@ void structTextEditor :: v_createMenus () {
 	Editor_addMenu (this, U"Search", 0);
 	Editor_addCommand (this, U"Search", U"Find...", 'F', menu_cb_find);
 	Editor_addCommand (this, U"Search", U"Find again", 'G', menu_cb_findAgain);
-	Editor_addCommand (this, U"Search", U"Replace...", GuiMenu_SHIFT + 'F', menu_cb_replace);
-	Editor_addCommand (this, U"Search", U"Replace again", GuiMenu_SHIFT + 'G', menu_cb_replaceAgain);
+	Editor_addCommand (this, U"Search", U"Replace...", GuiMenu_SHIFT | 'F', menu_cb_replace);
+	Editor_addCommand (this, U"Search", U"Replace again", GuiMenu_SHIFT | 'G', menu_cb_replaceAgain);
 	Editor_addCommand (this, U"Search", U"-- line --", 0, nullptr);
 	Editor_addCommand (this, U"Search", U"Where am I?", 0, menu_cb_whereAmI);
 	Editor_addCommand (this, U"Search", U"Go to line...", 'L', menu_cb_goToLine);
diff --git a/sys/TextEditor.h b/sys/TextEditor.h
index ea7b458..25b10e6 100644
--- a/sys/TextEditor.h
+++ b/sys/TextEditor.h
@@ -2,7 +2,7 @@
 #define _TextEditor_h_
 /* TextEditor.h
  *
- * Copyright (C) 1997-2011,2012,2013,2015 Paul Boersma
+ * Copyright (C) 1997-2011,2012,2013,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ Thing_define (TextEditor, Editor) {
 	GuiText textWidget;
 	autoUiForm openDialog, saveDialog;
 	bool dirty;
-	GuiDialog dirtyNewDialog, dirtyOpenDialog, dirtyCloseDialog;
+	GuiDialog dirtyNewDialog, dirtyOpenDialog, dirtyReopenDialog, dirtyCloseDialog;
 	GuiMenuItem fontSizeButton_10, fontSizeButton_12, fontSizeButton_14, fontSizeButton_18, fontSizeButton_24;
 
 	void v_destroy () noexcept
diff --git a/sys/Thing.cpp b/sys/Thing.cpp
index 7af86de..bd25e57 100644
--- a/sys/Thing.cpp
+++ b/sys/Thing.cpp
@@ -169,7 +169,7 @@ void _Thing_forget (Thing me) {
 }
 
 bool Thing_isSubclass (ClassInfo klas, ClassInfo ancestor) {
-	while (klas != ancestor && klas) klas = klas -> parent;
+	while (klas != ancestor && klas) klas = klas -> semanticParent;
 	return !! klas;
 }
 
@@ -187,7 +187,7 @@ void * _Thing_check (Thing me, ClassInfo klas, const char *fileName, int line) {
 			U"."
 		);
 	ClassInfo classInfo = my classInfo;
-	while (classInfo != klas && classInfo) classInfo = classInfo -> parent;
+	while (classInfo != klas && classInfo) classInfo = classInfo -> semanticParent;
 	if (! classInfo)
 		Melder_fatal (U"(_Thing_check:)"
 			U" Object of wrong class (", my classInfo -> className,
@@ -199,7 +199,7 @@ void * _Thing_check (Thing me, ClassInfo klas, const char *fileName, int line) {
 	return me;
 }
 
-void Thing_infoWithIdAndFile (Thing me, unsigned long id, MelderFile file) {
+void Thing_infoWithIdAndFile (Thing me, long id, MelderFile file) {
 	//Melder_assert (me);
 	Melder_clearInfo ();
 	MelderInfo_open ();
diff --git a/sys/Thing.h b/sys/Thing.h
index 279f87f..2596dbc 100644
--- a/sys/Thing.h
+++ b/sys/Thing.h
@@ -35,18 +35,18 @@
 #define _Thing_auto_DEBUG  0
 
 /*
-	Use the macro 'I' for an object in the formal parameter lists
-	(if the explicit type cannot be used).
 	Use the macro 'iam'
 	as the first declaration in a function definition.
 	After this, the object 'me' has the right class (for the compiler),
 	so that you can use the macro 'my' to refer to members.
-	Example: int Person_getAge (I) { iam (Person); return my age; }
+	Example: int Person_getAge (void *void_me) { iam (Person); return my age; }
 */
 #define iam(klas)  klas me = (klas) void_me
 #define my  me ->
 #define thy  thee ->
+#define your  you ->
 #define his  him ->
+#define her  she ->
 #define our  this ->
 
 typedef struct structClassInfo *ClassInfo;
@@ -55,7 +55,7 @@ struct structClassInfo {
 	 * The following five fields are statically initialized by the Thing_implement() macro.
 	 */
 	const char32 *className;
-	ClassInfo parent;
+	ClassInfo semanticParent;
 	long size;
 	Thing (* _new) ();   // objects have to be constructed via this function, because it calls C++ "new", which initializes the C++ class pointer
 	long version;
@@ -75,14 +75,14 @@ struct structClassInfo {
 	extern struct structClassInfo theClassInfo_##klas; \
 	extern ClassInfo class##klas
 
-#define Thing_define(klas,parentKlas) \
+#define Thing_define(klas,syntacticParentKlas) \
 	Thing_declare (klas); \
-	typedef struct##parentKlas klas##_Parent; \
-	struct struct##klas : public struct##parentKlas
+	typedef struct##syntacticParentKlas klas##_Parent; \
+	struct struct##klas : public struct##syntacticParentKlas
 
-#define Thing_implement(klas,parentKlas,version) \
+#define Thing_implement(klas,semanticParentKlas,version) \
 	static Thing _##klas##_new () { return new struct##klas; } \
-	struct structClassInfo theClassInfo_##klas = { U"" #klas, & theClassInfo_##parentKlas, sizeof (class struct##klas), _##klas##_new, version, 0, nullptr}; \
+	struct structClassInfo theClassInfo_##klas = { U"" #klas, & theClassInfo_##semanticParentKlas, sizeof (class struct##klas), _##klas##_new, version, 0, nullptr}; \
 	ClassInfo class##klas = & theClassInfo_##klas
 
 /*
@@ -166,7 +166,7 @@ bool Thing_isSubclass (ClassInfo klas, ClassInfo ancestor);
 */
 
 void Thing_info (Thing me);
-void Thing_infoWithIdAndFile (Thing me, unsigned long id, MelderFile file);
+void Thing_infoWithIdAndFile (Thing me, long id, MelderFile file);
 
 void Thing_recognizeClassesByName (ClassInfo readableClass, ...);
 /*
@@ -331,7 +331,7 @@ public:
 	/*
 		Sometimes the ownership is determined by a flag such as _ownItems or _ownData or _ownSound.
 		In that case, the autoThing has be released as a raw Thing pointer,
-		and the ambiguous owner may become responsible for destruction the object.
+		and the ambiguous owner may become responsible for destroying the object.
 		In Praat, this happens with Collection items and with some editors.
 	*/
 	T* releaseToAmbiguousOwner () noexcept {
diff --git a/sys/Ui.cpp b/sys/Ui.cpp
index c16b9cb..1e44327 100644
--- a/sys/Ui.cpp
+++ b/sys/Ui.cpp
@@ -191,6 +191,7 @@ static void UiField_widgetToValue (UiField me) {
 				Melder_throw (U_LEFT_DOUBLE_QUOTE, my name, U_RIGHT_DOUBLE_QUOTE U" has the value \"undefined\".");
 			if (my type == UI_POSITIVE && my realValue <= 0.0)
 				Melder_throw (U_LEFT_DOUBLE_QUOTE, my name, U_RIGHT_DOUBLE_QUOTE U" must be greater than 0.0.");
+			if (my realVariable) *my realVariable = my realValue;
 		} break; case UI_INTEGER: case UI_NATURAL: case UI_CHANNEL: {
 			autostring32 dirty = GuiText_getString (my text);
 			if (my type == UI_CHANNEL && (str32equ (dirty.peek(), U"Left") || str32equ (dirty.peek(), U"Mono"))) {
@@ -210,17 +211,21 @@ static void UiField_widgetToValue (UiField me) {
 			if ((my type == UI_NATURAL || my type == UI_CHANNEL) && my integerValue < 1) {
 				Melder_throw (U_LEFT_DOUBLE_QUOTE, my name, U_RIGHT_DOUBLE_QUOTE U" must be a positive whole number.");
 			}
+			if (my longVariable) *my longVariable = my integerValue;
 		} break; case UI_WORD: {
 			Melder_free (my stringValue);
 			my stringValue = GuiText_getString (my text);
 			char32 *p = my stringValue;
 			while (*p != '\0') { if (*p == U' ' || *p == U'\t') *p = U'\0'; p ++; }
 			GuiText_setString (my text, my stringValue);
+			if (my stringVariable) *my stringVariable = my stringValue;
 		} break; case UI_SENTENCE: case UI_TEXT: {
 			Melder_free (my stringValue);
 			my stringValue = GuiText_getString (my text);
+			if (my stringVariable) *my stringVariable = my stringValue;
 		} break; case UI_BOOLEAN: {
 			my integerValue = GuiCheckButton_getValue (my checkButton);
+			if (my boolVariable) *my boolVariable = my integerValue;
 		} break; case UI_RADIO: {
 			my integerValue = 0;
 			for (int i = 1; i <= my options.size; i ++) {
@@ -230,10 +235,14 @@ static void UiField_widgetToValue (UiField me) {
 			}
 			if (my integerValue == 0)
 				Melder_throw (U"No option chosen for " U_LEFT_DOUBLE_QUOTE, my name, U_RIGHT_DOUBLE_QUOTE U".");
+			if (my intVariable) *my intVariable = my integerValue - my subtract;
+			if (my stringVariable) *my stringVariable = my options.at [my integerValue] -> name;
 		} break; case UI_OPTIONMENU: {
 			my integerValue = GuiOptionMenu_getValue (my optionMenu);
 			if (my integerValue == 0)
 				Melder_throw (U"No option chosen for " U_LEFT_DOUBLE_QUOTE, my name, U_RIGHT_DOUBLE_QUOTE U".");
+			if (my intVariable) *my intVariable = my integerValue - my subtract;
+			if (my stringVariable) *my stringVariable = my options.at [my integerValue] -> name;
 		} break; case UI_LIST: {
 			long numberOfSelected, *selected = GuiList_getSelectedPositions (my list, & numberOfSelected);   // BUG memory
 			if (! selected) {
@@ -244,6 +253,8 @@ static void UiField_widgetToValue (UiField me) {
 				my integerValue = selected [1];
 				NUMvector_free <long> (selected, 1);
 			}
+			if (my longVariable) *my longVariable = my integerValue;
+			if (my stringVariable) *my stringVariable = (char32 *) my strings [my integerValue];
 		} break; case UI_COLOUR: {
 			autostring32 string = GuiText_getString (my text);
 			if (colourToValue (me, string.peek())) {
@@ -266,6 +277,7 @@ static void UiField_stringToValue (UiField me, const char32 *string, Interpreter
 				Melder_throw (U"\"", my name, U"\" has the value \"undefined\".");
 			if (my type == UI_POSITIVE && my realValue <= 0.0)
 				Melder_throw (U"\"", my name, U"\" must be greater than 0.");
+			if (my realVariable) *my realVariable = my realValue;
 		} break; case UI_INTEGER: case UI_NATURAL: case UI_CHANNEL: {
 			if (str32spn (string, U" \t") == str32len (string))
 				Melder_throw (U"Argument “", my name, U"” empty.");
@@ -282,14 +294,17 @@ static void UiField_stringToValue (UiField me, const char32 *string, Interpreter
 			}
 			if (my type == UI_NATURAL && my integerValue < 1)
 				Melder_throw (U"\"", my name, U"\" must be a positive whole number.");
+			if (my longVariable) *my longVariable = my integerValue;
 		} break; case UI_WORD: case UI_SENTENCE: case UI_TEXT: {
 			Melder_free (my stringValue);
 			my stringValue = Melder_dup_f (string);
+			if (my stringVariable) *my stringVariable = my stringValue;
 		} break; case UI_BOOLEAN: {
 			if (! string [0])
 				Melder_throw (U"Empty argument for toggle button.");
 			my integerValue = string [0] == U'1' || string [0] == U'y' || string [0] == U'Y' ||
 				string [0] == U't' || string [0] == U'T';
+			if (my boolVariable) *my boolVariable = my integerValue;
 		} break; case UI_RADIO: case UI_OPTIONMENU: {
 			my integerValue = 0;
 			for (int i = 1; i <= my options.size; i ++) {
@@ -314,6 +329,8 @@ static void UiField_stringToValue (UiField me, const char32 *string, Interpreter
 			if (my integerValue == 0) {
 				Melder_throw (U"Field \"", my name, U"\" must not have the value \"", string, U"\".");
 			}
+			if (my intVariable) *my intVariable = my integerValue - my subtract;
+			if (my stringVariable) *my stringVariable = my options.at [my integerValue] -> name;
 		} break; case UI_LIST: {
 			long i = 1;
 			for (; i <= my numberOfStrings; i ++)
@@ -321,6 +338,8 @@ static void UiField_stringToValue (UiField me, const char32 *string, Interpreter
 			if (i > my numberOfStrings)
 				Melder_throw (U"Field \"", my name, U"\" must not have the value \"", string, U"\".");
 			my integerValue = i;
+			if (my longVariable) *my longVariable = my integerValue;
+			if (my stringVariable) *my stringVariable = (char32 *) my strings [my integerValue];
 		} break; case UI_COLOUR: {
 			autostring32 string2 = Melder_dup_f (string);
 			if (colourToValue (me, string2.peek())) {
@@ -603,42 +622,98 @@ UiField UiForm_addReal (UiForm me, const char32 *label, const char32 *defaultVal
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addReal4 (UiForm me, double *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_REAL, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy realVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addRealOrUndefined (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_REAL_OR_UNDEFINED, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addRealOrUndefined4 (UiForm me, double *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_REAL_OR_UNDEFINED, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy realVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addPositive (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_POSITIVE, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addPositive4 (UiForm me, double *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_POSITIVE, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy realVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addInteger (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_INTEGER, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addInteger4 (UiForm me, long *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_INTEGER, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy longVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addNatural (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_NATURAL, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addNatural4 (UiForm me, long *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_NATURAL, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy longVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addWord (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_WORD, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addWord4 (UiForm me, char32 **variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_WORD, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy stringVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addSentence (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_SENTENCE, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addSentence4 (UiForm me, char32 **variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_SENTENCE, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy stringVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addLabel (UiForm me, const char32 *name, const char32 *label) {
 	autoUiField thee (UiForm_addField (me, UI_LABEL, name));
 	thy stringValue = Melder_dup (label);
@@ -651,24 +726,60 @@ UiField UiForm_addBoolean (UiForm me, const char32 *label, int defaultValue) {
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addBoolean4 (UiForm me, bool *variable, const char32 *variableName, const char32 *label, int defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_BOOLEAN, label));
+	thy integerDefaultValue = defaultValue;
+	thy boolVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addText (UiForm me, const char32 *name, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_TEXT, name));
 	thy stringDefaultValue = Melder_dup (defaultValue);
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addText4 (UiForm me, char32 **variable, const char32 *variableName, const char32 *name, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_TEXT, name));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy stringVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addRadio (UiForm me, const char32 *label, int defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_RADIO, label));
 	thy integerDefaultValue = defaultValue;
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addRadio4 (UiForm me, int *intVariable, char32 **stringVariable, const char32 *variableName, const char32 *label, int defaultValue, int base) {
+	autoUiField thee (UiForm_addField (me, UI_RADIO, label));
+	thy integerDefaultValue = defaultValue;
+	thy intVariable = intVariable;
+	thy stringVariable = stringVariable;
+	thy variableName = variableName;
+	thy subtract = ( base == 1 ? 0 : 1 );
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addOptionMenu (UiForm me, const char32 *label, int defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_OPTIONMENU, label));
 	thy integerDefaultValue = defaultValue;
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addOptionMenu4 (UiForm me, int *intVariable, char32 **stringVariable, const char32 *variableName, const char32 *label, int defaultValue, int base) {
+	autoUiField thee (UiForm_addField (me, UI_OPTIONMENU, label));
+	thy integerDefaultValue = defaultValue;
+	thy intVariable = intVariable;
+	thy stringVariable = stringVariable;
+	thy variableName = variableName;
+	thy subtract = ( base == 1 ? 0 : 1 );
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addList (UiForm me, const char32 *label, long numberOfStrings, const char32 **strings, long defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_LIST, label));
 	thy numberOfStrings = numberOfStrings;
@@ -677,6 +788,17 @@ UiField UiForm_addList (UiForm me, const char32 *label, long numberOfStrings, co
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addList4 (UiForm me, long *longVariable, char32 **stringVariable, const char32 *variableName, const char32 *label, long numberOfStrings, const char32 **strings, long defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_LIST, label));
+	thy numberOfStrings = numberOfStrings;
+	thy strings = strings;
+	thy integerDefaultValue = defaultValue;
+	thy longVariable = longVariable;
+	thy stringVariable = stringVariable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 UiField UiForm_addColour (UiForm me, const char32 *label, const char32 *defaultValue) {
 	autoUiField thee (UiForm_addField (me, UI_COLOUR, label));
 	thy stringDefaultValue = Melder_dup (defaultValue);
@@ -689,6 +811,14 @@ UiField UiForm_addChannel (UiForm me, const char32 *label, const char32 *default
 	return thee.releaseToAmbiguousOwner();
 }
 
+UiField UiForm_addChannel4 (UiForm me, long *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue) {
+	autoUiField thee (UiForm_addField (me, UI_CHANNEL, label));
+	thy stringDefaultValue = Melder_dup (defaultValue);
+	thy longVariable = variable;
+	thy variableName = variableName;
+	return thee.releaseToAmbiguousOwner();
+}
+
 #define DIALOG_X  150
 #define DIALOG_Y  70
 #define HELP_BUTTON_WIDTH  60
@@ -938,6 +1068,163 @@ void UiForm_do (UiForm me, bool modified) {
 		UiForm_okOrApply (me, nullptr, true);
 }
 
+static void UiField_api_header_C (UiField me, UiField next, bool isLastNonLabelField) {
+	if (my type == UI_LABEL) {
+		if (! next || next -> type != UI_TEXT) {
+			MelderInfo_writeLine (U"\t/* ", my stringValue, U" */");
+		}
+		return;
+	}
+
+	/*
+		Write the type of the field.
+	*/
+	bool isText = false, isBoolean = false, isEnum = false, isPositive = false;
+	switch (my type) {
+		case UI_REAL: case UI_REAL_OR_UNDEFINED: case UI_POSITIVE: {
+			MelderInfo_write (U"\tdouble ");
+			isPositive = ( my type == UI_POSITIVE);
+		} break; case UI_INTEGER: case UI_NATURAL: case UI_CHANNEL: {
+			MelderInfo_write (U"\tint64_t ");
+			isPositive = ( my type == UI_NATURAL);
+		} break; case UI_WORD: case UI_SENTENCE: case UI_TEXT: case UI_COLOUR: case UI_LIST: {
+			MelderInfo_write (U"\tconst char *");
+			isText = true;
+		} break; case UI_RADIO: case UI_OPTIONMENU: {
+			MelderInfo_write (U"\tconst char *");
+			isText = true;
+			isEnum = true;
+		} break; case UI_BOOLEAN: {
+			MelderInfo_write (U"\tint32_t ");
+			isBoolean = true;
+		} break; default: {
+		}
+	}
+
+	/*
+		Write the title of the field.
+	*/
+	char32 cName [100], *q = & cName [0];
+	Melder_assert (my formLabel);
+	const char32 *p = & my formLabel [0];
+	*q ++ = tolower (*p ++);
+	bool up = false;
+	for (; *p != U'\0'; p ++) {
+		if (*p == U'(') {
+			break;
+		} else if (*p == U'\'') {
+			continue;
+		} else if (*p == U' ' || *p == U'-') {
+			if (p [1] == U'(') { p ++; break; }
+			up = true;
+		} else if (*p == U'*') {
+			*q ++ = U'S';
+			*q ++ = U't';
+			*q ++ = U'a';
+			*q ++ = U'r';
+		} else if (up) {
+			*q ++ = toupper (*p);
+			up = false;
+		} else {
+			*q ++ = *p;
+		}
+	}
+	*q = U'\0';
+	MelderInfo_write (my variableName ? my variableName : cName);
+	if (! isLastNonLabelField) MelderInfo_write (U",");
+
+	/*
+		Get the units.
+	*/
+	char32 units [100];
+	q = & units [0];
+	if (*p == U'(') {
+		for (p ++; *p != U'\0'; p ++) {
+			if (*p == U')') {
+				break;
+			} else {
+				*q ++ = *p;
+			}
+		}
+	}
+	*q = U'\0';
+	bool unitsAreAvailable = ( units [0] != U'\0' );
+	bool unitsContainRange = str32str (units, U"-");
+
+	/*
+		Get the example.
+	*/
+	const char32 *example = my stringDefaultValue;
+	bool exampleIsAvailable = ( example && example [0] != U'\0' );
+
+	if (exampleIsAvailable) {
+		/*
+			Split up the default string.
+		*/
+		char32 defaultValue [100], defaultComment [100];
+		str32cpy (defaultValue, my stringDefaultValue);
+		str32cpy (defaultComment, U"");
+		if (unitsAreAvailable) {
+			char32 *parenthesis = str32chr (defaultValue, U'(');
+			if (parenthesis && parenthesis - defaultValue > 1) {
+				parenthesis [-1] = U'\0';
+				str32cpy (defaultComment, parenthesis);
+			}
+		}
+
+		MelderInfo_write (U"   // ");
+		if (isPositive) {
+			MelderInfo_write (U"positive, ");
+		}
+		if (unitsContainRange) {
+			MelderInfo_write (units, U", ");
+		}
+		MelderInfo_write (U"e.g. ");
+		if (isText) MelderInfo_write (U"\"");
+		MelderInfo_write (defaultValue);
+		if (isText) MelderInfo_write (U"\"");
+		if (unitsAreAvailable && ! unitsContainRange) {
+			MelderInfo_write (U" ", units);
+		}
+		if (defaultComment [0]) {
+			MelderInfo_write (U" ", defaultComment);
+		}
+	} else if (isBoolean) {
+		MelderInfo_write (U"   // boolean, e.g. ");
+		MelderInfo_write (my integerDefaultValue, my integerDefaultValue ? U" (true)" : U" (false)");
+	} else if (isEnum) {
+		MelderInfo_write (U"   // e.g. \"");
+		MelderInfo_write (my options.at [my integerDefaultValue] -> name);
+		MelderInfo_write (U"\"; other choice", ( my options.size > 2 ? U"s" : U"" ), U":");
+		bool firstWritten = false;
+		for (int i = 1; i <= my options.size; i ++) {
+			if (i == my integerDefaultValue) continue;
+			if (firstWritten) MelderInfo_write (U",");
+			MelderInfo_write (U" \"", my options.at [i] -> name, U"\"");
+			firstWritten = true;
+		}
+	}
+	MelderInfo_writeLine (U"");
+}
+
+void UiForm_info (UiForm me, int narg) {
+	if (narg == -1) {
+		/*
+			The C interface.
+		*/
+		int lastNonLabelFieldNumber = 0;
+		for (int ifield = my numberOfFields; ifield > 0; ifield --) {
+			if (my field [ifield] -> type != UI_LABEL) {
+				lastNonLabelFieldNumber = ifield;
+				break;
+			}
+		}
+		for (int ifield = 1; ifield <= my numberOfFields; ifield ++) {
+			UiField_api_header_C (my field [ifield], ifield == my numberOfFields ? nullptr : my field [ifield + 1], ifield == lastNonLabelFieldNumber);
+		}
+	}
+}
+
 static void UiField_argToValue (UiField me, Stackel arg, Interpreter /* interpreter */) {
 	switch (my type) {
 		case UI_REAL: case UI_REAL_OR_UNDEFINED: case UI_POSITIVE: {
@@ -948,6 +1235,7 @@ static void UiField_argToValue (UiField me, Stackel arg, Interpreter /* interpre
 				Melder_throw (U"Argument \"", my name, U"\" has the value \"undefined\".");
 			if (my type == UI_POSITIVE && my realValue <= 0.0)
 				Melder_throw (U"Argument \"", my name, U"\" must be greater than 0.");
+			if (my realVariable) *my realVariable = my realValue;
 		} break; case UI_INTEGER: case UI_NATURAL: case UI_CHANNEL: {
 			if (arg -> which == Stackel_STRING) {
 				if (my type == UI_CHANNEL) {
@@ -971,11 +1259,13 @@ static void UiField_argToValue (UiField me, Stackel arg, Interpreter /* interpre
 			} else {
 				Melder_throw (U"Argument \"", my name, U"\" should be a number, not ", Stackel_whichText (arg), U".");
 			}
+			if (my longVariable) *my longVariable = my integerValue;
 		} break; case UI_WORD: case UI_SENTENCE: case UI_TEXT: {
 			if (arg -> which != Stackel_STRING)
 				Melder_throw (U"Argument \"", my name, U"\" should be a string, not ", Stackel_whichText(arg), U".");
 			Melder_free (my stringValue);
 			my stringValue = Melder_dup (arg -> string);
+			if (my stringVariable) *my stringVariable = my stringValue;
 		} break; case UI_BOOLEAN: {
 			if (arg -> which == Stackel_STRING) {
 				if (str32equ (arg -> string, U"no") || str32equ (arg -> string, U"off")) {
@@ -991,6 +1281,7 @@ static void UiField_argToValue (UiField me, Stackel arg, Interpreter /* interpre
 			} else {
 				Melder_throw (U"Boolean argument \"", my name, U"\" should be a number (0 or 1), not ", Stackel_whichText (arg), U".");
 			}
+			if (my boolVariable) *my boolVariable = my integerValue;
 		} break; case UI_RADIO: case UI_OPTIONMENU: {
 			if (arg -> which != Stackel_STRING)
 				Melder_throw (U"Option argument \"", my name, U"\" should be a string, not ", Stackel_whichText (arg), U".");
@@ -1017,6 +1308,8 @@ static void UiField_argToValue (UiField me, Stackel arg, Interpreter /* interpre
 			if (my integerValue == 0) {
 				Melder_throw (U"Option argument \"", my name, U"\" cannot have the value \"", arg -> string, U"\".");
 			}
+			if (my intVariable) *my intVariable = my integerValue - my subtract;
+			if (my stringVariable) *my stringVariable = my options.at [my integerValue] -> name;
 		} break; case UI_LIST: {
 			if (arg -> which != Stackel_STRING)
 				Melder_throw (U"List argument \"", my name, U"\" should be a string, not ", Stackel_whichText(arg), U".");
@@ -1026,6 +1319,8 @@ static void UiField_argToValue (UiField me, Stackel arg, Interpreter /* interpre
 			if (i > my numberOfStrings)
 				Melder_throw (U"List argument \"", my name, U"\" cannot have the value \"", arg -> string, U"\".");
 			my integerValue = i;
+			if (my longVariable) *my longVariable = my integerValue;
+			if (my stringVariable) *my stringVariable = (char32 *) my strings [my integerValue];
 		} break; case UI_COLOUR: {
 			if (arg -> which == Stackel_NUMBER) {
 				if (arg -> number < 0.0 || arg -> number > 1.0)
@@ -1068,7 +1363,7 @@ void UiForm_parseString (UiForm me, const char32 *arguments, Interpreter interpr
 		static char32 stringValue [3000];
 		int ichar = 0;
 		if (my field [i] -> type == UI_LABEL)
-			continue;   /* Ignore non-trailing fields without a value. */
+			continue;   // ignore non-trailing fields without a value
 		/*
 		 * Skip spaces until next argument.
 		 */
diff --git a/sys/Ui.h b/sys/Ui.h
index db36612..78f6b99 100644
--- a/sys/Ui.h
+++ b/sys/Ui.h
@@ -94,11 +94,21 @@ Thing_define (UiField, Thing) {
 	GuiOptionMenu optionMenu;
 	int y;
 
+	const char32 *variableName;
+	double *realVariable;
+	long *longVariable;
+	int *intVariable;
+	bool *boolVariable;
+	char32 **stringVariable;
+	int subtract;
+
 	void v_destroy () noexcept
 		override;
 };
 
-typedef void (*UiCallback) (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter interpreter, const char32 *invokingButtonTitle, bool modified, void *closure);
+#define UiCallback_ARGS \
+	UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter interpreter, const char32 *invokingButtonTitle, bool modified, void *closure
+typedef void (*UiCallback) (UiCallback_ARGS);
 
 #define MAXIMUM_NUMBER_OF_FIELDS  50
 #define MAXIMUM_NUMBER_OF_CONTINUE_BUTTONS  10
@@ -145,22 +155,35 @@ UiForm UiForm_create (GuiWindow parent, const char32 *title,
 	UiCallback okCallback, void *buttonClosure,
 	const char32 *invokingButtonTitle, const char32 *helpTitle);
 UiField UiForm_addReal (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addReal4 (UiForm me, double *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addRealOrUndefined (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addRealOrUndefined4 (UiForm me, double *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addPositive (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addPositive4 (UiForm me, double *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addInteger (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addInteger4 (UiForm me, long *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addNatural (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addNatural4 (UiForm me, long *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addWord (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addWord4 (UiForm me, char32 **variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addSentence (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addSentence4 (UiForm me, char32 **variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addLabel (UiForm me, const char32 *name, const char32 *label);
 UiField UiForm_addBoolean (UiForm me, const char32 *label, int defaultValue);
+UiField UiForm_addBoolean4 (UiForm me, bool *variable, const char32 *variableName, const char32 *label, int defaultValue);
 UiField UiForm_addText (UiForm me, const char32 *name, const char32 *defaultValue);
+UiField UiForm_addText4 (UiForm me, char32 **variable, const char32 *variableName, const char32 *name, const char32 *defaultValue);
 UiField UiForm_addRadio (UiForm me, const char32 *label, int defaultValue);
+UiField UiForm_addRadio4 (UiForm me, int *intVariable, char32 **stringVariable, const char32 *variableName, const char32 *label, int defaultValue, int base);
 UiOption UiRadio_addButton (UiField me, const char32 *label);
 UiField UiForm_addOptionMenu (UiForm me, const char32 *label, int defaultValue);
+UiField UiForm_addOptionMenu4 (UiForm me, int *intVariable, char32 **stringVariable, const char32 *variableName, const char32 *label, int defaultValue, int base);
 UiOption UiOptionMenu_addButton (UiField me, const char32 *label);
 UiField UiForm_addList (UiForm me, const char32 *label, long numberOfStrings, const char32 **strings, long defaultValue);
+UiField UiForm_addList4 (UiForm me, long *longVariable, char32 **stringVariable, const char32 *variableName, const char32 *label, long numberOfStrings, const char32 **strings, long defaultValue);
 UiField UiForm_addColour (UiForm me, const char32 *label, const char32 *defaultValue);
 UiField UiForm_addChannel (UiForm me, const char32 *label, const char32 *defaultValue);
+UiField UiForm_addChannel4 (UiForm me, long *variable, const char32 *variableName, const char32 *label, const char32 *defaultValue);
 void UiForm_finish (UiForm me);
 
 void UiForm_destroyWhenUnmanaged (UiForm me);
@@ -211,16 +234,17 @@ void UiForm_do (UiForm me, bool modified);
 		The form will still appear on the screen,
 		but the okCallback will be called immediately.
 */
+void UiForm_info (UiForm me, int narg);
 
 /* The 'okCallback' can use the following four routines to ask arguments. */
 /* The field names are the 'label' or 'name' arguments to UiForm_addXXXXXX (), */
 /* without anything from parentheses or from a colon. */
 /* These routines work from the screen and from batch. */
-double UiForm_getReal (UiForm me, const char32 *fieldName);	// Real, Positive
-long UiForm_getInteger (UiForm me, const char32 *fieldName);	// Integer, Natural, Boolean, Radio, List
-char32 * UiForm_getString (UiForm me, const char32 *fieldName);	// Word, Sentence, Text, Radio, List
+double UiForm_getReal (UiForm me, const char32 *fieldName);	  // Real, Positive
+long UiForm_getInteger (UiForm me, const char32 *fieldName);   // Integer, Natural, Boolean, Radio, List
+char32 * UiForm_getString (UiForm me, const char32 *fieldName);   // Word, Sentence, Text, Radio, List
 Graphics_Colour UiForm_getColour (UiForm me, const char32 *fieldName);   // Colour
-MelderFile UiForm_getFile (UiForm me, const char32 *fieldName); // FileIn, FileOut
+MelderFile UiForm_getFile (UiForm me, const char32 *fieldName);   // FileIn, FileOut
 
 double UiForm_getReal_check (UiForm me, const char32 *fieldName);
 long UiForm_getInteger_check (UiForm me, const char32 *fieldName);
diff --git a/sys/melder.cpp b/sys/melder.cpp
index c44c13e..55da8f2 100644
--- a/sys/melder.cpp
+++ b/sys/melder.cpp
@@ -1,6 +1,6 @@
 /* melder.cpp
  *
- * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma, 2008 Stefan de Konink, 2010 Franz Brausse, 2013 Tom Naughton
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,29 +16,21 @@
  * along with this work. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <time.h>
-#include <ctype.h>
-#include <assert.h>
+//#include <ctype.h>
+//#include <assert.h>
 #include "melder.h"
-#include "longchar.h"
 #include "regularExp.h"
 #ifdef _WIN32
 	#include <windows.h>
 #endif
-#if defined (macintosh)
-	#include "macport_on.h"
-	//#include <Sound.h>
-	#include "macport_off.h"
-#endif
 
-#include "Graphics.h"
-#include "machine.h"
+//#include "Graphics.h"
+//#include "machine.h"
 #ifdef macintosh
 	#include "macport_on.h"
 	#include <AudioToolbox/AudioToolbox.h>
 	#include "macport_off.h"
 #endif
-#include "Gui.h"
 
 #include "MelderThread.h"
 
@@ -54,8 +46,6 @@ bool Melder_backgrounding;   // are we running a script?- Set and unset dynamica
 bool Melder_asynchronous;
 int32 Melder_systemVersion;
 
-GuiWindow Melder_topShell;
-
 static void defaultHelp (const char32 *query) {
 	Melder_flushError (U"Don't know how to find help on \"", query, U"\".");
 }
@@ -64,6 +54,13 @@ static void defaultSearch () {
 	Melder_flushError (U"Do not know how to search.");
 }
 
+static void defaultProgress (double progress, const char32 *message) {
+}
+
+static void * defaultMonitor (double progress, const char32 *message) {
+	return NULL;
+}
+
 static void defaultWarning (const char32 *message) {
 	Melder_writeToConsole (U"Warning: ", true);
 	Melder_writeToConsole (message, true);
@@ -99,6 +96,8 @@ static int defaultPublishPlayed () {
 static struct {
 	void (*help) (const char32 *query);
 	void (*search) ();
+	void (*progress) (double progress, const char32 *message);
+	void * (*monitor) (double progress, const char32 *message);
 	void (*warning) (const char32 *message);
 	void (*fatal) (const char32 *message);
 	int (*record) (double duration);
@@ -109,6 +108,7 @@ static struct {
 }
 	theMelder = {
 		defaultHelp, defaultSearch,
+		defaultProgress, defaultMonitor,
 		defaultWarning, defaultFatal,
 		defaultRecord, defaultRecordFromFile, defaultPlay, defaultPlayReverse, defaultPublishPlayed
 	};
@@ -116,169 +116,12 @@ static struct {
 /********** PROGRESS **********/
 
 static int theProgressDepth = 0;
-static bool theProgressCancelled = false;
 void Melder_progressOff () { theProgressDepth --; }
 void Melder_progressOn () { theProgressDepth ++; }
 
-static bool waitWhileProgress (double progress, const char32 *message, GuiDialog dia, GuiProgressBar scale, GuiLabel label1, GuiLabel label2, GuiButton cancelButton) {
-	#if gtk
-		// Wait for all pending events to be processed. If anybody knows how to inspect GTK's
-		// event queue for specific events, dump the code here, please.
-		// Until then, the button click attaches a g_object data key named "pressed" to the cancelButton
-		// which this function reads out in order to tell whether interruption has occurred
-		while (gtk_events_pending ()) {
-			trace (U"event pending");
-			gtk_main_iteration ();
-		}
-	#elif defined (macintosh)
-		NSEvent *nsEvent = [NSApp
-			nextEventMatchingMask: NSAnyEventMask
-			untilDate: [NSDate distantPast]
-			inMode: NSDefaultRunLoopMode
-			dequeue: YES
-			];
-		if (nsEvent) {
-			NSUInteger nsEventType = [nsEvent type];
-			if (nsEventType == NSKeyDown) NSBeep ();
-			[[nsEvent window]  sendEvent: nsEvent];
-		}
-	#elif defined (_WIN32)
-		XEvent event;
-		while (PeekMessage (& event, 0, 0, 0, PM_REMOVE)) {
-			if (event. message == WM_KEYDOWN) {
-				/*
-				 * Ignore all key-down messages, except Escape.
-				 */
-				if (LOWORD (event. wParam) == VK_ESCAPE) {
-					XtUnmanageChild (dia -> d_widget);
-					return false;   // don't continue
-				}
-			} else if (event. message == WM_LBUTTONDOWN) {
-				/*
-				 * Ignore all mouse-down messages, except click in Interrupt button.
-				 */
-				GuiObject me = (GuiObject) GetWindowLongPtr (event. hwnd, GWLP_USERDATA);
-				if (me == cancelButton -> d_widget) {
-					XtUnmanageChild (dia -> d_widget);
-					return false;   // don't continue
-				}
-			} else if (event. message != WM_SYSKEYDOWN) {
-				/*
-				 * Process paint messages etc.
-				 */
-				DispatchMessage (& event);
-			}
-		}
-	#endif
-	if (progress >= 1.0) {
-		GuiThing_hide (dia);
-	} else {
-		if (progress <= 0.0) progress = 0.0;
-		GuiThing_show (dia);   // TODO: prevent raising to the front
-		const char32 *newline = str32chr (message, U'\n');
-		if (newline) {
-			static MelderString buffer { 0 };
-			MelderString_copy (& buffer, message);
-			buffer.string [newline - message] = U'\0';
-			GuiLabel_setText (label1, buffer.string);
-			buffer.string [newline - message] = U'\n';
-			GuiLabel_setText (label2, buffer.string + (newline - message) + 1);
-		} else {
-			GuiLabel_setText (label1, message);
-			GuiLabel_setText (label2, U"");
-		}
-		#if gtk
-			trace (U"update the progress bar");
-			GuiProgressBar_setValue (scale, progress);
-			while (gtk_events_pending ()) {
-				trace (U"event pending");
-				gtk_main_iteration ();
-			}
-			trace (U"check whether the cancel button has the \"pressed\" key set");
-			if (g_object_steal_data (G_OBJECT (cancelButton -> d_widget), "pressed")) {
-				trace (U"the cancel button has been pressed");
-				return false;   // don't continue
-			}
-		#elif cocoa
-			GuiProgressBar_setValue (scale, progress);
-			//[scale -> d_cocoaProgressBar   displayIfNeeded];
-			if (theProgressCancelled) {
-				theProgressCancelled = false;
-				return false;
-			}
-		#elif motif
-			GuiProgressBar_setValue (scale, progress);
-			GdiFlush ();
-		#endif
-	}
-	trace (U"continue");
-	return true;
-}
-
-static GuiButton theProgressCancelButton = nullptr;
-
-#if gtk || macintosh
-static void progress_dia_close (Thing /* boss */) {
-	theProgressCancelled = true;
-	#if gtk
-		g_object_set_data (G_OBJECT (theProgressCancelButton -> d_widget), "pressed", (gpointer) 1);
-	#endif
-}
-static void progress_cancel_btn_press (Thing /* boss */, GuiButtonEvent /* event */) {
-	theProgressCancelled = true;
-	#if gtk
-		g_object_set_data (G_OBJECT (theProgressCancelButton -> d_widget), "pressed", (gpointer) 1);
-	#endif
-}
-#endif
-
-static void _Melder_dia_init (GuiDialog *dia, GuiProgressBar *scale, GuiLabel *label1, GuiLabel *label2, GuiButton *cancelButton, bool hasMonitor) {
-	trace (U"creating the dialog");
-	*dia = GuiDialog_create (Melder_topShell, 200, 100, 400, hasMonitor ? 430 : 200, U"Work in progress",
-		#if gtk || macintosh
-			progress_dia_close, nullptr,
-		#else
-			nullptr, nullptr,
-		#endif
-		0);
-
-	trace (U"creating the labels");
-	*label1 = GuiLabel_createShown (*dia, 3, 403, 0, Gui_LABEL_HEIGHT, U"label1", 0);
-	*label2 = GuiLabel_createShown (*dia, 3, 403, 30, 30 + Gui_LABEL_HEIGHT, U"label2", 0);
-
-	trace (U"creating the scale");
-	*scale = GuiProgressBar_createShown (*dia, 3, -3, 70, 110, 0);
-
-	trace (U"creating the cancel button");
-	*cancelButton = GuiButton_createShown (*dia, 0, 400, 170, 170 + Gui_PUSHBUTTON_HEIGHT,
-		U"Interrupt",
-		#if gtk
-			progress_cancel_btn_press, nullptr,
-		#elif macintosh
-			progress_cancel_btn_press, nullptr,
-		#else
-			nullptr, nullptr,
-		#endif
-		0);
-	trace (U"end");
-}
-
 static void _Melder_progress (double progress, const char32 *message) {
 	if (! Melder_batch && theProgressDepth >= 0 && Melder_debug != 14) {
-		static clock_t lastTime;
-		static GuiDialog dia = nullptr;
-		static GuiProgressBar scale = nullptr;
-		static GuiLabel label1 = nullptr, label2 = nullptr;
-		clock_t now = clock ();
-		if (progress <= 0.0 || progress >= 1.0 ||
-			now - lastTime > CLOCKS_PER_SEC / 4)   // this time step must be much longer than the null-event waiting time
-		{
-			if (! dia)
-				_Melder_dia_init (& dia, & scale, & label1, & label2, & theProgressCancelButton, false);
-			if (! waitWhileProgress (progress, message, dia, scale, label1, label2, theProgressCancelButton))
-				Melder_throw (U"Interrupted!");
-			lastTime = now;
-		}
+		theMelder. progress (progress, message);
 	}
 }
 
@@ -344,41 +187,12 @@ void Melder_progress (double progress, Melder_19_ARGS) {
 	_Melder_progress (progress, theProgressBuffer.string);
 }
 
-static autoGraphics graphics;
-
-static void gui_drawingarea_cb_expose (Thing /* boss */, GuiDrawingArea_ExposeEvent /* event */) {
-	if (! graphics) return;
-	Graphics_play (graphics.get(), graphics.get());
-}
-
-static Graphics _Melder_monitor (double progress, const char32 *message) {
+static void * _Melder_monitor (double progress, const char32 *message) {
 	if (! Melder_batch && theProgressDepth >= 0) {
-		static clock_t lastTime;
-		static GuiDialog dia = nullptr;
-		static GuiProgressBar scale = nullptr;
-		static GuiDrawingArea drawingArea = nullptr;
-		static GuiButton cancelButton = nullptr;
-		static GuiLabel label1 = nullptr, label2 = nullptr;
-		clock_t now = clock ();
-		if (progress <= 0.0 || progress >= 1.0 ||
-			now - lastTime > CLOCKS_PER_SEC / 4)   // this time step must be much longer than the null-event waiting time
-		{
-			if (! dia) {
-				_Melder_dia_init (& dia, & scale, & label1, & label2, & cancelButton, true);
-				drawingArea = GuiDrawingArea_createShown (dia, 0, 400, 230, 430, gui_drawingarea_cb_expose, nullptr, nullptr, nullptr, nullptr, 0);
-				GuiThing_show (dia);
-				graphics = Graphics_create_xmdrawingarea (drawingArea);
-			}
-			if (graphics)
-				Graphics_flushWs (graphics.get());
-			if (! waitWhileProgress (progress, message, dia, scale, label1, label2, cancelButton))
-				Melder_throw (U"Interrupted!");
-			lastTime = now;
-			if (progress == 0.0)
-				return graphics.get();
-		}
+		void *result = theMelder. monitor (progress, message);
+		if (result) return result;
 	}
-	return progress <= 0.0 ? nullptr /* no Graphics */ : (Graphics) -1 /* any non-null pointer */;
+	return progress <= 0.0 ? nullptr /* no Graphics */ : (void *) -1 /* any non-null pointer */;
 }
 
 void * Melder_monitor (double progress) {
@@ -975,149 +789,6 @@ void Melder_assert_ (const char *fileName, int lineNumber, const char *condition
 	abort ();
 }
 
-#if defined (macintosh)
-static void mac_message (NSAlertStyle macAlertType, const char32 *message32) {
-	static unichar messageU [4000];
-	int messageLength = str32len (message32);
-	int j = 0;
-	for (int i = 0; i < messageLength && j <= 4000 - 3; i ++) {
-		char32 kar = message32 [i];
-		if (kar <= 0x00FFFF) {
-			messageU [j ++] = kar;
-		} else if (kar <= 0x10FFFF) {
-			kar -= 0x010000;
-			messageU [j ++] = 0x00D800 | (kar >> 10);
-			messageU [j ++] = 0x00DC00 | (kar & 0x0003FF);
-		}
-	}
-	messageU [j] = '\0';   // append null byte because we are going to search this string
-
-	/*
-	 * Split up the message between header (will appear in bold) and rest.
-	 * The split is done at the first line break, except if the first line ends in a colon,
-	 * in which case the split is done at the second line break.
-	 */
-	UniChar *lineBreak = & messageU [0];
-	for (; *lineBreak != '\0'; lineBreak ++) {
-		if (*lineBreak == '\n') {
-			break;
-		}
-	}
-	if (*lineBreak == '\n' && lineBreak - messageU > 0 && lineBreak [-1] == ':') {
-		for (lineBreak ++; *lineBreak != '\0'; lineBreak ++) {
-			if (*lineBreak == '\n') {
-				break;
-			}
-		}
-	}
-	/*
-	 * Create an alert dialog with an icon that is appropriate for the level.
-	 */
-	NSAlert *alert = [[NSAlert alloc] init];
-	[alert setAlertStyle: macAlertType];
-	/*
-	 * Add the header in bold.
-	 */
-	NSString *header = [[NSString alloc] initWithCharacters: messageU   length: lineBreak - messageU];   // note: init can change the object pointer!
-	if (header) {   // make this very safe, because we can be at error time or at fatal time
-		[alert setMessageText: header];
-		[header release];
-	}
-	/*
-	 * Add the rest of the message in small type.
-	 */
-	if (lineBreak - messageU < j) {
-		NSString *rest = [[NSString alloc] initWithCharacters: lineBreak + 1   length: j - 1 - (lineBreak - messageU)];
-		if (rest) {   // make this very safe, because we can be at error time or at fatal time
-			[alert setInformativeText: rest];
-			[rest release];
-		}
-	}
-	/*
-	 * Display the alert dialog and synchronously wait for the user to click OK.
-	 */
-	[alert runModal];
-	[alert release];
-}
-#endif
-
-#define theMessageFund_SIZE  100000
-static char * theMessageFund = nullptr;
-
-static void gui_fatal (const char32 *message) {
-	free (theMessageFund);
-	#if gtk
-		GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
-			GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", Melder_peek32to8 (message));
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-	#elif defined (macintosh)
-		mac_message (NSCriticalAlertStyle, message);
-		SysError (11);
-	#elif defined (_WIN32)
-		MessageBox (nullptr, Melder_peek32toW (message), L"Fatal error", MB_OK | MB_TOPMOST | MB_ICONSTOP);
-	#endif
-}
-
-static void gui_error (const char32 *message) {
-	bool memoryIsLow = str32str (message, U"Out of memory");
-	if (memoryIsLow) {
-		free (theMessageFund);
-	}
-	#if gtk
-		trace (U"create dialog");
-		GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
-			GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", Melder_peek32to8 (message));
-		trace (U"run dialog");
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		trace (U"destroy dialog");
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-	#elif defined (macintosh)
-		mac_message (NSWarningAlertStyle, message);
-	#elif defined (_WIN32)
-		MessageBox (nullptr, Melder_peek32toW (message), L"Message", MB_OK | MB_TOPMOST | MB_ICONWARNING);   // or (HWND) XtWindow ((GuiObject) Melder_topShell)
-	#endif
-	if (memoryIsLow) {
-		theMessageFund = (char *) malloc (theMessageFund_SIZE);
-		if (! theMessageFund) {
-			#if gtk
-				GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
-					GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
-				gtk_dialog_run (GTK_DIALOG (dialog));
-				gtk_widget_destroy (GTK_WIDGET (dialog));
-			#elif defined (macintosh)
-				mac_message (NSCriticalAlertStyle, U"Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
-			#elif defined (_WIN32)
-				MessageBox (nullptr, L"Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.", L"Message", MB_OK);
-			#endif
-		}
-	}
-}
-
-static void gui_warning (const char32 *message) {
-	#if gtk
-		GuiObject dialog = gtk_message_dialog_new (GTK_WINDOW (Melder_topShell -> d_gtkWindow), GTK_DIALOG_DESTROY_WITH_PARENT,
-			GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", Melder_peek32to8 (message));
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-	#elif defined (macintosh)
-		mac_message (NSInformationalAlertStyle, message);
-	#elif defined (_WIN32)
-		MessageBox (nullptr, Melder_peek32toW (message), L"Warning", MB_OK | MB_TOPMOST | MB_ICONINFORMATION);
-	#endif
-}
-
-void gui_information (const char32 *);   // BUG: no prototype
-void MelderGui_create (void *parent) {
-	theMessageFund = (char *) malloc (theMessageFund_SIZE);
-	assert (theMessageFund);
-	Melder_topShell = (GuiWindow) parent;
-	Melder_setInformationProc (gui_information);
-	Melder_setFatalProc (gui_fatal);
-	Melder_setErrorProc (gui_error);
-	Melder_setWarningProc (gui_warning);
-}
-
 int Melder_record (double duration) {
 	return theMelder. record (duration);
 }
@@ -1149,6 +820,12 @@ void Melder_setSearchProc (void (*search) (void))
 void Melder_setWarningProc (void (*warning) (const char32 *))
 	{ theMelder. warning = warning ? warning : defaultWarning; }
 
+void Melder_setProgressProc (void (*progress) (double, const char32 *))
+	{ theMelder. progress = progress ? progress : defaultProgress; }
+
+void Melder_setMonitorProc (void * (*monitor) (double, const char32 *))
+	{ theMelder. monitor = monitor ? monitor : defaultMonitor; }
+
 void Melder_setFatalProc (void (*fatal) (const char32 *))
 	{ theMelder. fatal = fatal ? fatal : defaultFatal; }
 
diff --git a/sys/melder.h b/sys/melder.h
index 723023a..5a5b126 100644
--- a/sys/melder.h
+++ b/sys/melder.h
@@ -1174,10 +1174,6 @@ extern bool Melder_batch;   // true if run from the batch or from an interactive
 extern bool Melder_backgrounding;   // true if running a script
 extern bool Melder_consoleIsAnsi;
 extern bool Melder_asynchronous;   // true if specified by the "asynchronous" directive in a script
-#ifndef CONTROL_APPLICATION
-	typedef struct structGuiWindow *GuiWindow;
-	extern GuiWindow Melder_topShell;
-#endif
 
 /********** OVERRIDE DEFAULT BEHAVIOUR **********/
 
@@ -1192,6 +1188,8 @@ void Melder_setInformationProc (void (*informationProc) (const char32 *message))
 void Melder_setHelpProc (void (*help) (const char32 *query));
 void Melder_setSearchProc (void (*search) ());
 void Melder_setWarningProc (void (*warningProc) (const char32 *message));
+void Melder_setProgressProc (void (*progress) (double, const char32 *));
+void Melder_setMonitorProc (void * (*monitor) (double, const char32 *));
 void Melder_setErrorProc (void (*errorProc) (const char32 *message));
 void Melder_setFatalProc (void (*fatalProc) (const char32 *message));
 void Melder_setRecordProc (int (*record) (double));
diff --git a/sys/melder_audio.cpp b/sys/melder_audio.cpp
index 1f799b1..a1fe10a 100644
--- a/sys/melder_audio.cpp
+++ b/sys/melder_audio.cpp
@@ -33,10 +33,12 @@
 	#if defined HAVE_PULSEAUDIO
 		#include <pulse/pulseaudio.h>
 	#endif
-	#if defined (__OpenBSD__) || defined (__NetBSD__)
-		#include <soundcard.h>
-	#else
-		#include <sys/soundcard.h>
+	#if ! defined (NO_AUDIO)
+		#if defined (__OpenBSD__) || defined (__NetBSD__)
+			#include <soundcard.h>
+		#else
+			#include <sys/soundcard.h>
+		#endif
 	#endif
 	#include <errno.h>
 #endif
@@ -57,6 +59,7 @@
 	void stream_drain_complete_cb (pa_stream *stream, int success, void *userdata);
 	void context_state_cb (pa_context *context, void *userdata);
 	void context_drain_complete_cb (pa_context *context, void *userdata);
+	void prepare_and_play (struct MelderPlay *me);
 	void stream_write_cb (pa_stream *stream, size_t length, void *userdata);
 	void stream_write_cb2 (pa_stream *stream, size_t length, void *userdata);
 	void pulseAudio_server_info_cb (pa_context *context, const pa_server_info *info, void *userdata);
@@ -143,6 +146,9 @@ static double theStartingTime = 0.0;
 #define PA_WRITING_DONE 8
 #define PA_RECORDING 16
 #define PA_RECORDING_DONE 32
+#define PA_QUERY_NUMBEROFCHANNELS 64
+#define PA_QUERY_NUMBEROFCHANNELS_DONE 128
+
 
 #ifdef HAVE_PULSEAUDIO
 typedef struct pulseAudio {
@@ -333,7 +339,7 @@ static bool flush () {
 	#endif
 	} else {
 	#if defined (macintosh)
-	#elif defined (linux)
+	#elif defined (linux) && ! defined (NO_AUDIO)
 		
 		/*
 		 * As on Sun.
@@ -474,7 +480,7 @@ static bool workProc (void *closure) {
 	#endif
 	} else {
 	#if defined (macintosh)
-	#elif defined (linux)
+	#elif defined (linux) && ! defined (NO_AUDIO)
 		if (my samplesLeft > 0) {
 			int dsamples = my samplesLeft > 500 ? 500 : my samplesLeft;
 			write (my audio_fd, (char *) & my buffer [my samplesSent * my numberOfChannels], 2 * dsamples * my numberOfChannels);
@@ -630,28 +636,30 @@ void pulseAudio_server_info_cb (pa_context *context, const pa_server_info *info,
 		return;
 	}
 	const pa_sample_spec *sp = & (info -> sample_spec);
-	long numberOfChannels = sp -> channels;
+	my numberOfChannels = sp -> channels;
 	Melder_assert (context == my pulseAudio.context);
-	MelderInfo_open ();
-	MelderInfo_writeLine (U"PulseAudio Server characteristics:");
-	MelderInfo_writeLine (U"User name: ", Melder_peek8to32 (info -> user_name));
-	MelderInfo_writeLine (U"Host name: ", Melder_peek8to32 (info -> host_name));
-	MelderInfo_writeLine (U"Server version: ", Melder_peek8to32 (info -> server_version));
-	MelderInfo_writeLine (U"Server name: ", Melder_peek8to32 (info -> server_name));
-	MelderInfo_writeLine (U"Sample specification: ");
-		MelderInfo_writeLine (U"\tNumber of channels: ", numberOfChannels);
-		MelderInfo_writeLine (U"\tSampling frequency: ", sp->rate);
-		const char *sample_format_string = pa_sample_format_to_string (sp -> format);
-		MelderInfo_writeLine (U"\tSample format: ", Melder_peek8to32 (sample_format_string));
-	MelderInfo_writeLine (U"Default sink name: ", Melder_peek8to32 (info -> default_sink_name));
-	MelderInfo_writeLine (U"Default source name: ", Melder_peek8to32 (info -> default_source_name));
-	const pa_channel_map *cm = &(info -> channel_map);
-	MelderInfo_writeLine (U"Channel specification: ");
-	for (long channel = 1; channel <= cm -> channels; channel++) {
-		const char *channel_text = pa_channel_position_to_pretty_string (cm -> map[channel - 1]); // 0-..
-		MelderInfo_writeLine (U"\t Channel ", channel, U": ", Melder_peek8to32 (channel_text));
+	if ((my pulseAudio.occupation & PA_QUERY_NUMBEROFCHANNELS) != PA_QUERY_NUMBEROFCHANNELS) {
+		MelderInfo_open ();
+		MelderInfo_writeLine (U"PulseAudio Server characteristics:");
+		MelderInfo_writeLine (U"User name: ", Melder_peek8to32 (info -> user_name));
+		MelderInfo_writeLine (U"Host name: ", Melder_peek8to32 (info -> host_name));
+		MelderInfo_writeLine (U"Server version: ", Melder_peek8to32 (info -> server_version));
+		MelderInfo_writeLine (U"Server name: ", Melder_peek8to32 (info -> server_name));
+		MelderInfo_writeLine (U"Sample specification: ");
+			MelderInfo_writeLine (U"\tNumber of channels: ", my numberOfChannels);
+			MelderInfo_writeLine (U"\tSampling frequency: ", sp -> rate);
+			const char *sample_format_string = pa_sample_format_to_string (sp -> format);
+			MelderInfo_writeLine (U"\tSample format: ", Melder_peek8to32 (sample_format_string));
+		MelderInfo_writeLine (U"Default sink name: ", Melder_peek8to32 (info -> default_sink_name));
+		MelderInfo_writeLine (U"Default source name: ", Melder_peek8to32 (info -> default_source_name));
+		const pa_channel_map *cm = &(info -> channel_map);
+		MelderInfo_writeLine (U"Channel specification: ");
+		for (long channel = 1; channel <= cm -> channels; channel++) {
+			const char *channel_text = pa_channel_position_to_pretty_string (cm -> map[channel - 1]); // 0-..
+			MelderInfo_writeLine (U"\t Channel ", channel, U": ", Melder_peek8to32 (channel_text));
+		}
+		MelderInfo_close ();
 	}
-	MelderInfo_close ();
 	trace (U"before signal");
 	my pulseAudio.occupation |= PA_GETTINGINFO_DONE;
 	 // We are done, signal it to pulseAudio_serverReport
@@ -675,9 +683,9 @@ void pulseAudio_serverReport () {
 			}
 			// Now it is save to unref because the server info operation has completed
 			pa_operation_unref (operation);
-			my pulseAudio.occupation ^= ~PA_GETTINGINFO_DONE;
+			my pulseAudio.occupation &= ~PA_GETTINGINFO_DONE;
 		}
-		my pulseAudio.occupation ^= ~PA_GETTINGINFO;
+		my pulseAudio.occupation &= ~PA_GETTINGINFO;
 		pa_threaded_mainloop_unlock (my pulseAudio.mainloop);
 	} else {
 		my pulseAudio.occupation |= PA_GETTINGINFO;
@@ -694,8 +702,8 @@ void pulseAudio_serverReport () {
 		// Now we know that the operation to get server info has succeeded!
 		pa_operation_unref (my pulseAudio.operation_info);
 		my pulseAudio.operation_info = nullptr;
-		my pulseAudio.occupation ^= ~PA_GETTINGINFO;
-		my pulseAudio.occupation ^= ~PA_GETTINGINFO_DONE;
+		my pulseAudio.occupation &= ~PA_GETTINGINFO;
+		my pulseAudio.occupation &= ~PA_GETTINGINFO_DONE;
 		pa_threaded_mainloop_unlock (my pulseAudio.mainloop);
 		if (! MelderAudio_isPlaying) {
 			my pulseAudio.occupation = 0;
@@ -729,7 +737,7 @@ void stream_drain_complete_cb (pa_stream *stream, int success, void *userdata) {
 		pa_stream_disconnect (my pulseAudio.stream);
 		pa_stream_unref (my pulseAudio.stream);
 		my pulseAudio.stream = nullptr;
-		my pulseAudio.occupation ^= ~PA_WRITING;
+		my pulseAudio.occupation &= ~PA_WRITING;
 		my pulseAudio.occupation |= PA_WRITING_DONE;
 		MelderAudio_isPlaying = false;
 		if (my pulseAudio.timer_event) {
@@ -781,7 +789,7 @@ void stream_write_cb2 (pa_stream *stream, size_t length, void *userdata) {
 						pa_stream_unref (my pulseAudio.stream);
 						my pulseAudio.stream = nullptr;
 						trace (U"stream exists");
-						my pulseAudio.occupation ^= ~PA_WRITING;
+						my pulseAudio.occupation &= ~PA_WRITING;
 						my pulseAudio.occupation |= PA_WRITING_DONE;
 						pa_threaded_mainloop_signal (my pulseAudio.mainloop, 0);
 						if (my pulseAudio.timer_event) {
@@ -845,7 +853,7 @@ void stream_write_cb (pa_stream *stream, size_t length, void *userdata) {
 						pa_stream_unref (my pulseAudio.stream);
 						my pulseAudio.stream = nullptr;
 						trace (U"stream exists");
-						my pulseAudio.occupation ^= ~PA_WRITING;
+						my pulseAudio.occupation &= ~PA_WRITING;
 						my pulseAudio.occupation |= PA_WRITING_DONE;
 						pa_threaded_mainloop_signal (my pulseAudio.mainloop, 0);
 						if (my pulseAudio.timer_event) {
@@ -904,6 +912,49 @@ static void stream_overflow_callback(pa_stream *s, void *userdata) {
 	trace (U"yes");
 }
 
+void prepare_and_play (struct MelderPlay *me) {
+	
+	#if __BYTE_ORDER == __BIG_ENDIAN
+		my pulseAudio.sample_spec.format = PA_SAMPLE_S16BE;
+	#else
+		my pulseAudio.sample_spec.format = PA_SAMPLE_S16LE;
+	#endif
+	my samplesPlayed = my samplesSent = 0;
+	my pulseAudio.sample_spec.rate = my sampleRate;
+	my pulseAudio.sample_spec.channels = my numberOfChannels;
+	my pulseAudio.stream = pa_stream_new (my pulseAudio.context, "Praat", &(my pulseAudio.sample_spec), nullptr);
+	if (! my pulseAudio.stream) {
+		Melder_throw (U"Cannot connect to sound server: ", Melder_peek8to32 (pa_strerror (pa_context_errno (my pulseAudio.context))));
+	}
+
+	//my pulseAudio.stream_flags = PA_STREAM_NOFLAGS;
+	my pulseAudio.stream_flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE);
+	my pulseAudio.latency = pa_usec_to_bytes (1000 * my pulseAudio.latency_msec, &(my pulseAudio.sample_spec));
+	
+	my pulseAudio.buffer_attr.maxlength = (uint32_t) -1;
+	my pulseAudio.buffer_attr.prebuf = (uint32_t) -1;
+	my pulseAudio.buffer_attr.minreq = (uint32_t) -1;
+	my pulseAudio.buffer_attr.prebuf = (uint32_t) -1;
+	my pulseAudio.buffer_attr.tlength = my pulseAudio.latency;
+	my pulseAudio.buffer_attr.fragsize = (uint32_t) -1;
+
+	pa_stream_set_state_callback (my pulseAudio.stream, stream_state_cb, me);
+	pa_stream_set_write_callback (my pulseAudio.stream, stream_write_cb, me);
+	pa_stream_set_underflow_callback (my pulseAudio.stream, stream_underflow_callback, me);
+	pa_stream_set_overflow_callback (my pulseAudio.stream, stream_overflow_callback, me);
+	
+	// BUG in pa 5.9  & 6.0: the server doesn't honour our wish for a reasonable tlength. Instead it uses some
+	//   ridiculously low value for tlength that will constantly give underflows.
+	//   audio playback was completely shit if in the stream_write_cb we used pa_stream_write instead of
+	// first pa_stream_begin_write followed by pa_stream_write.
+	//
+	my pulseAudio.stream_flags = PA_STREAM_NOFLAGS;
+	if (pa_stream_connect_playback (my pulseAudio.stream, nullptr, &(my pulseAudio.buffer_attr), my pulseAudio.stream_flags, nullptr, nullptr) < 0) {
+		Melder_throw (U"pa_stream_connect_playback() failed: ", Melder_peek8to32 (pa_strerror (pa_context_errno (my pulseAudio.context))));
+	}
+	trace (U"tlength = ", my pulseAudio.buffer_attr.tlength, U", channels = ", my numberOfChannels);
+}
+
 void context_state_cb (pa_context *context, void *userdata) {
 	struct MelderPlay *me = (struct MelderPlay *) userdata;
 
@@ -936,45 +987,7 @@ void context_state_cb (pa_context *context, void *userdata) {
 					Melder_throw (U"pulseAudioServer report: ", Melder_peek8to32 (pa_strerror (pa_context_errno (my pulseAudio.context))));
 				}
 			} else if ((my pulseAudio.occupation & PA_WRITING) == PA_WRITING) {
-				#if __BYTE_ORDER == __BIG_ENDIAN
-					my pulseAudio.sample_spec.format = PA_SAMPLE_S16BE;
-				#else
-					my pulseAudio.sample_spec.format = PA_SAMPLE_S16LE;
-				#endif
-				my samplesPlayed = my samplesSent = 0;
-				my pulseAudio.sample_spec.rate = my sampleRate;
-				my pulseAudio.sample_spec.channels = my numberOfChannels;
-				my pulseAudio.stream = pa_stream_new (my pulseAudio.context, "Praat", &(my pulseAudio.sample_spec), nullptr);
-				if (! my pulseAudio.stream) {
-					Melder_throw (U"Cannot connect to sound server: ", Melder_peek8to32 (pa_strerror (pa_context_errno (my pulseAudio.context))));
-				}
-
-				//my pulseAudio.stream_flags = PA_STREAM_NOFLAGS;
-				my pulseAudio.stream_flags = (pa_stream_flags_t) (PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE);
-				my pulseAudio.latency = pa_usec_to_bytes (1000 * my pulseAudio.latency_msec, &(my pulseAudio.sample_spec));
-				
-				my pulseAudio.buffer_attr.maxlength = (uint32_t) -1;
-				my pulseAudio.buffer_attr.prebuf = (uint32_t) -1;
-				my pulseAudio.buffer_attr.minreq = (uint32_t) -1;
-				my pulseAudio.buffer_attr.prebuf = (uint32_t) -1;
-				my pulseAudio.buffer_attr.tlength = my pulseAudio.latency;
-				my pulseAudio.buffer_attr.fragsize = (uint32_t) -1;
-
-				pa_stream_set_state_callback (my pulseAudio.stream, stream_state_cb, me);
-				pa_stream_set_write_callback (my pulseAudio.stream, stream_write_cb, me);
-			    pa_stream_set_underflow_callback (my pulseAudio.stream, stream_underflow_callback, me);
-			    pa_stream_set_overflow_callback (my pulseAudio.stream, stream_overflow_callback, me);
-				
-				// BUG in pa 5.9  & 6.0: the server doesn't honour our wish for a reasonable tlength. Instead it uses some
-				//   ridiculously low value for tlength that will constantly give underflows.
-				//   audio playback was completely shit if in the stream_write_cb we used pa_stream_write instead of
-				// first pa_stream_begin_write followed by pa_stream_write.
-				//
-				my pulseAudio.stream_flags = PA_STREAM_NOFLAGS;
-				if (pa_stream_connect_playback (my pulseAudio.stream, nullptr, &(my pulseAudio.buffer_attr), my pulseAudio.stream_flags, nullptr, nullptr) < 0) {
-					Melder_throw (U"pa_stream_connect_playback() failed: ", Melder_peek8to32 (pa_strerror (pa_context_errno (my pulseAudio.context))));
-				}
-				trace (U"tlength = ", my pulseAudio.buffer_attr.tlength, U", channels = ", my numberOfChannels);
+				prepare_and_play (me);
 			} else if ((my pulseAudio.occupation & PA_RECORDING) == PA_RECORDING) {
 				
 			}
@@ -1000,7 +1013,7 @@ void MelderAudio_play16 (int16_t *buffer, long sampleRate, long numberOfSamples,
 			pulseAudio_cleanup ();
 		}
 	#endif
-	my buffer = buffer;
+	my buffer = buffer;   // 0-based, as all buffers are
 	my sampleRate = sampleRate;
 	my numberOfSamples = numberOfSamples;
 	my numberOfChannels = numberOfChannels;
@@ -1176,9 +1189,48 @@ void MelderAudio_play16 (int16_t *buffer, long sampleRate, long numberOfSamples,
 		flush ();
 		return;
 	#ifdef HAVE_PULSEAUDIO
-	} if (my usePulseAudio) {
+	} else if (my usePulseAudio) {
+		my pulseAudio.occupation |= PA_QUERY_NUMBEROFCHANNELS; // set query bit on
+		pulseAudio_serverReport ();
+		my pulseAudio.occupation &= ~PA_QUERY_NUMBEROFCHANNELS; // set query bit off
+		
+		if (numberOfChannels > my numberOfChannels) {
+			/*
+			 * Redistribute the in channels over the out channels. TODO make channelmap
+			 */
+			if (numberOfChannels == 4 && my numberOfChannels == 2) {   // a common case
+				int16_t *in = & my buffer [0], *out = & my buffer [0];
+				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+					long in1 = *in ++, in2 = *in ++, in3 = *in ++, in4 = *in ++;
+					*out ++ = (in1 + in2) / 2;
+					*out ++ = (in3 + in4) / 2;
+				}
+			} else {
+				int16_t *in = & my buffer [0], *out = & my buffer [0];
+				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+					for (long iout = 1; iout <= my numberOfChannels; iout ++) {
+						long outValue = 0;
+						long numberOfIn = numberOfChannels / my numberOfChannels;
+						if (iout == my numberOfChannels)
+							numberOfIn += numberOfChannels % my numberOfChannels;
+						for (long iin = 1; iin <= numberOfIn; iin ++)
+							outValue += *in ++;
+						outValue /= numberOfIn;
+						*out ++ = outValue;
+					}
+				}
+			}
+		} else if (numberOfChannels < my numberOfChannels) {
+			// pulseaudio will divide the input over the output channels
+			my numberOfChannels = numberOfChannels;
+		}
+		
 		my pulseAudio.occupation |= PA_WRITING;
 		pulseAudio_initialize ();
+		if (pa_context_get_state (my pulseAudio.context) == PA_CONTEXT_READY) {
+			prepare_and_play (me);
+		}
+
 		if (my asynchronicity < kMelder_asynchronicityLevel_ASYNCHRONOUS) {
 			pa_threaded_mainloop_lock (my pulseAudio.mainloop);
 			trace (U"occupation ", my pulseAudio.occupation);
@@ -1191,7 +1243,7 @@ void MelderAudio_play16 (int16_t *buffer, long sampleRate, long numberOfSamples,
 				pa_operation_unref (my pulseAudio.operation_drain);
 			}
 			my pulseAudio.operation_drain = nullptr;
-			my pulseAudio.occupation ^= ~PA_WRITING_DONE;
+			my pulseAudio.occupation &= ~PA_WRITING_DONE;
 
 			pa_threaded_mainloop_unlock (my pulseAudio.mainloop);
 			//pa_threaded_mainloop_accept (my pulseAudio.mainloop);
@@ -1200,16 +1252,18 @@ void MelderAudio_play16 (int16_t *buffer, long sampleRate, long numberOfSamples,
 		} else {
 			// my workProcId_gtk = g_timeout_add (ms, workProc_gtk, nullptr);
 			// without a timer, on my computer the workproc would be called almost once in every sampling period.
-			// Such frequent updates are not necessary, some 50 updates a second is fast enough for displayong a runnning cursor
+			// Such frequent updates are not necessary, some 50 updates a second is fast enough for displaying a runnning cursor
 			// the timeout will be automatically stopped if workProc_gtk returns false.
-			#ifndef NO_GRAPHICS
-				my workProcId_gtk = g_timeout_add (20, workProc_gtk, nullptr);
+			#if gtk
+				#ifndef NO_GRAPHICS
+					my workProcId_gtk = g_timeout_add (20, workProc_gtk, nullptr);
+				#endif
 			#endif
 		}
 	#endif
 	} else {
 		#if defined (macintosh)
-		#elif defined (linux)
+		#elif defined (linux) && ! defined (NO_AUDIO)
 			try {
 				/* Big-endian version added by Stefan de Konink, Nov 29, 2007 */
 				#if __BYTE_ORDER == __BIG_ENDIAN
diff --git a/sys/melder_audiofiles.cpp b/sys/melder_audiofiles.cpp
index 126069a..10d8b67 100644
--- a/sys/melder_audiofiles.cpp
+++ b/sys/melder_audiofiles.cpp
@@ -610,7 +610,7 @@ static int nistGetValue (const char *header, const char *object, double *rval, c
 	char obj [30], type [10];
 	const char *match = strstr (header, object);
 	if (! match) return 0;
-	if (sscanf (match, "%s%s%s", obj, type, sval) != 3) return 0;
+	if (sscanf (match, "%29s%9s%99s", obj, type, sval) != 3) return 0;
 	if (strequ (type, "-i") || strequ (type, "-r")) *rval = atof (sval);
 	else if (strncmp (type, "-s", 2)) return 0;
 	return 1;
diff --git a/sys/melder_debug.cpp b/sys/melder_debug.cpp
index f0daf6b..9482ce3 100644
--- a/sys/melder_debug.cpp
+++ b/sys/melder_debug.cpp
@@ -78,7 +78,7 @@ the behaviour of that program changes in the following way:
 46: trace GTK parent sizes in _GuiObject_position ()
 47: force resampling in OTGrammar RIP
 900: use DG Meta Serif Science instead of Palatino
-1264: Mac: Sound_recordFixedTime uses microphone "FW Solo (1264)"
+1264: Mac: Sound_record_fixedTime uses microphone "FW Solo (1264)"
 
 (negative values are for David)
 
diff --git a/sys/melder_info.cpp b/sys/melder_info.cpp
index 4f74c68..8f39beb 100644
--- a/sys/melder_info.cpp
+++ b/sys/melder_info.cpp
@@ -1,6 +1,6 @@
 /* melder_info.cpp
  *
- * Copyright (C) 1992-2012,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -439,7 +439,7 @@ void MelderInfo_close () {
 			When writing to a diverted string, we must *not* add a newline symbol,
 			because scripts expect returned strings without appended newlines!
 		*/
-		if (theInfos -> length == 0 || theInfos -> string [theInfos -> length - 1] != U'\n') {   // Only if no newline there yet.
+		if (theInfos -> length == 0 || theInfos -> string [theInfos -> length - 1] != U'\n') {   // only if no newline there yet
 			MelderString_appendCharacter (theInfos, U'\n');
 			if (theInformation == defaultInformation) {
 				Melder_writeToConsole (U"\n", false);
@@ -461,12 +461,11 @@ void MelderInfo_drain () {
 
 void Melder_informationReal (double value, const char32 *units) {
 	MelderInfo_open ();
-	if (value == NUMundefined)
-		MelderInfo_write (U"--undefined--");
-	else if (! units)
+	if (! units) {
 		MelderInfo_write (value);
-	else
+	} else {
 		MelderInfo_write (value, U" ", units);
+	}
 	MelderInfo_close ();
 }
 
diff --git a/sys/praat.cpp b/sys/praat.cpp
index 13365e9..00a61fc 100644
--- a/sys/praat.cpp
+++ b/sys/praat.cpp
@@ -202,51 +202,6 @@ void praat_list_foreground () {
 	}
 }
 
-Daata praat_onlyObject (ClassInfo klas) {
-	int IOBJECT, result = 0, found = 0;
-	WHERE (SELECTED && CLASS == klas) { result = IOBJECT; found += 1; }
-	if (found != 1) return nullptr;
-	return theCurrentPraatObjects -> list [result]. object;
-}
-
-Daata praat_firstObject (ClassInfo klas) {
-	int IOBJECT;
-	LOOP {
-		if (CLASS == klas) return theCurrentPraatObjects -> list [IOBJECT]. object;
-	}
-	return nullptr;   // this is often OK
-}
-
-Daata praat_onlyObject_generic (ClassInfo klas) {
-	int IOBJECT, result = 0, found = 0;
-	WHERE (SELECTED && Thing_isSubclass (CLASS, klas)) { result = IOBJECT; found += 1; }
-	if (found != 1) return nullptr;
-	return theCurrentPraatObjects -> list [result]. object;
-}
-
-Daata praat_firstObject_generic (ClassInfo klas) {
-	int IOBJECT;
-	LOOP {
-		if (Thing_isSubclass (CLASS, klas)) return theCurrentPraatObjects -> list [IOBJECT]. object;
-	}
-	return nullptr;   // this is often OK
-}
-
-praat_Object praat_onlyScreenObject () {
-	int IOBJECT, result = 0, found = 0;
-	WHERE (SELECTED) { result = IOBJECT; found += 1; }
-	if (found != 1) Melder_fatal (U"praat_onlyScreenObject: found ", found, U" objects instead of 1.");
-	return & theCurrentPraatObjects -> list [result];
-}
-
-Daata praat_firstObject_any () {
-	int IOBJECT;
-	LOOP {
-		return theCurrentPraatObjects -> list [IOBJECT]. object;
-	}
-	return nullptr;   // this is often OK
-}
-
 autoCollection praat_getSelectedObjects () {
 	autoCollection thee = Collection_create ();
 	int IOBJECT;
@@ -510,14 +465,13 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2) {
 }
 
 void praat_removeObject (int i) {
-	int j, ieditor;
 	praat_remove (i, true);   // dangle
-	for (j = i; j < theCurrentPraatObjects -> n; j ++)
+	for (int j = i; j < theCurrentPraatObjects -> n; j ++)
 		theCurrentPraatObjects -> list [j] = theCurrentPraatObjects -> list [j + 1];   // undangle but create second references
 	theCurrentPraatObjects -> list [theCurrentPraatObjects -> n]. name = nullptr;   // undangle or remove second reference
 	theCurrentPraatObjects -> list [theCurrentPraatObjects -> n]. object = nullptr;   // undangle or remove second reference
 	theCurrentPraatObjects -> list [theCurrentPraatObjects -> n]. isSelected = 0;
-	for (ieditor = 0; ieditor < praat_MAXNUM_EDITORS; ieditor ++)
+	for (int ieditor = 0; ieditor < praat_MAXNUM_EDITORS; ieditor ++)
 		theCurrentPraatObjects -> list [theCurrentPraatObjects -> n]. editors [ieditor] = nullptr;   // undangle or remove second reference
 	MelderFile_setToNull (& theCurrentPraatObjects -> list [theCurrentPraatObjects -> n]. file);   // undangle or remove second reference
 	-- theCurrentPraatObjects -> n;
@@ -814,7 +768,7 @@ static int publishProc (autoDaata me) {
 
 /***** QUIT *****/
 
-FORM (Quit, U"Confirm Quit", U"Quit")
+FORM (DO_Quit, U"Confirm Quit", U"Quit") {
 	LABEL (U"label", U"You have objects in your list!")
 	OK
 {
@@ -834,7 +788,7 @@ FORM (Quit, U"Confirm Quit", U"Quit")
 }
 DO
 	praat_exit (0);
-END
+END }
 
 static void gui_cb_quit (Thing /* me */) {
 	DO_Quit (nullptr, 0, nullptr, nullptr, nullptr, nullptr, false, nullptr);
@@ -915,7 +869,7 @@ void praat_dontUsePictureWindow () { praatP.dontUsePictureWindow = true; }
 			sendpraatW (nullptr, Melder_peek32toW (praatP.title), 0, Melder_peek32toW (text));
 		#endif
 	}
-#elif cocoa
+#elif macintosh
 	static int (*theUserMessageCallback) (char32 *message);
 	static void mac_setUserMessageCallback (int (*userMessageCallback) (char32 *message)) {
 		theUserMessageCallback = userMessageCallback;
@@ -977,20 +931,6 @@ void praat_dontUsePictureWindow () { praatP.dontUsePictureWindow = true; }
 		DO_Quit (nullptr, 0, nullptr, nullptr, nullptr, nullptr, false, nullptr);
 		return 0;
 	}
-#elif defined (macintosh)
-	static int cb_userMessage (char32 *message) {
-		autoPraatBackground background;
-		try {
-			praat_executeScriptFromText (message);
-		} catch (MelderError) {
-			Melder_flushError (praatP.title, U": message not completely handled.");
-		}
-		return 0;
-	}
-	static int cb_quitApplication () {
-		DO_Quit (nullptr, 0, nullptr, nullptr, nullptr, nullptr, false, nullptr);
-		return 0;
-	}
 #endif
 
 static const char32 * thePraatStandAloneScriptText = nullptr;
@@ -1155,7 +1095,7 @@ void praat_init (const char32 *title, int argc, char **argv)
 			MelderInfo_writeLine (U"  --version        print the Praat version");
 			MelderInfo_writeLine (U"  --help           print this list of command line options");
 			MelderInfo_writeLine (U"  -a, --ansi       Windows only: use ISO Latin-1 encoding instead of UTF-16LE");
-			MelderInfo_writeLine (U"                   (this option is needed when you redirect to a pipe or file");
+			MelderInfo_writeLine (U"                   (this option is needed when you redirect to a pipe or file)");
 			MelderInfo_close ();
 			exit (0);
 		} else if (strequ (argv [praatP.argumentNumber], "-a") || strequ (argv [praatP.argumentNumber], "--ansi")) {
@@ -1350,8 +1290,6 @@ void praat_init (const char32 *title, int argc, char **argv)
 			argv [0] = Melder_32to8 (praatP. title);   // argc == 4
 			Gui_setOpenDocumentCallback (cb_openDocument);
 			GuiAppInitialize ("Praatwulg", argc, argv);
-		#elif defined (macintosh)
-			GuiAppInitialize ("Praatwulg", argc, argv);
 		#endif
 
 		trace (U"creating and installing the Objects window");
@@ -1507,7 +1445,7 @@ void praat_run () {
 
 	trace (U"adding the Quit command");
 	praat_addMenuCommand (U"Objects", U"Praat", U"-- quit --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Quit", nullptr, praat_UNHIDABLE + 'Q', DO_Quit);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Quit", nullptr, praat_UNHIDABLE | 'Q' | praat_NO_API, DO_Quit);
 
 	trace (U"read the preferences file, and notify those who want to be notified of this");
 	/* ...namely, those who already have a window (namely, the Picture window),
@@ -1671,6 +1609,8 @@ void praat_run () {
 		praat_sortMenuCommands ();
 		praat_sortActions ();
 
+		praatP.phase = praat_HANDLING_EVENTS;
+
 		if (praatP.userWantsToOpen) {
 			for (; praatP.argumentNumber < praatP.argc; praatP.argumentNumber ++) {
 				//Melder_casual (U"File to open <<", Melder_peek8to32 (theArgv [iarg]), U">>");
@@ -1684,8 +1624,6 @@ void praat_run () {
 			}
 		}
 
-		praatP.phase = praat_HANDLING_EVENTS;
-
 		#if gtk
 			//gtk_widget_add_events (G_OBJECT (theCurrentPraatApplication -> topShell), GDK_ALL_EVENTS_MASK);
 			trace (U"install GTK key snooper");
diff --git a/sys/praat.h b/sys/praat.h
index 458da6c..5f935ee 100644
--- a/sys/praat.h
+++ b/sys/praat.h
@@ -1,6 +1,8 @@
+#ifndef _praat_h_
+#define _praat_h_
 /* praat.h
  *
- * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -49,7 +51,7 @@ The dots consist of, in any order:
 	Thing_recognizeClassesByName (...);
 	Data_recognizeFileType (...);
 	praat_addMenuCommand (...);
-	praat_addAction (...);
+	praat_addAction1 (...);
 All of these statements are optional and may occur more than once.
 To make any class string-readable, use Thing_recognizeClassesByName ().
 String-readable classes are known by Thing_newFromClassName () and can therefore
@@ -60,20 +62,23 @@ void praat_run ();
 void praat_setStandAloneScriptText (const char32 *text);   // call before praat_init if you want to create a stand-alone application without Objects and Picture window
 extern "C" void praatlib_init ();   // for use in an application that uses Praatlib
 
-void praat_addAction (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback);
-/* 'class2', 'class3', 'title', 'after', and 'callback' may be null; 'title' is reference-copied. */
-void praat_addAction1 (ClassInfo class1, int n1,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback);
-void praat_addAction2 (ClassInfo class1, int n1, ClassInfo class2, int n2,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback);
-void praat_addAction3 (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback);
-void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3, ClassInfo class4, int n4,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback);
+#define praat_addAction1(c1,n1,t,a,f,c)  praat_addAction1_ (c1, n1, t, a, f, c, U"" #c)
+#define praat_addAction2(c1,n1,c2,n2,t,a,f,c)  praat_addAction2_ (c1, n1, c2, n2, t, a, f, c, U"" #c)
+#define praat_addAction3(c1,n1,c2,n2,c3,n3,t,a,f,c)  praat_addAction3_ (c1, n1, c2, n2, c3, n3, t, a, f, c, U"" #c)
+#define praat_addAction4(c1,n1,c2,n2,c3,n3,c4,n4,t,a,f,c)  praat_addAction4_ (c1, n1, c2, n2, c3, n3, c4, n4, t, a, f, c, U"" #c)
+
+void praat_addAction1_ (ClassInfo class1, int n1,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback);
+void praat_addAction2_ (ClassInfo class1, int n1, ClassInfo class2, int n2,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback);
+void praat_addAction3_ (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback);
+void praat_addAction4_ (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3, ClassInfo class4, int n4,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback);
 /*
 	'title' is the name that will appear in the dynamic menu,
-		and also the command that is used in command files.
+		and also the command that is used in command files;
+		this title is reference-copied.
 	'callback' refers to a function prototyped like this:
 		static int DO_Class_action (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter interpreter, void *closure);
 		this function should throw an exception if the command failed,
@@ -88,13 +93,13 @@ void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, Class
 	The availability of the dynamic commands depends on
 	the current selection: e.g., if the user has selected three objects
 	of type Matrix and nothing else, the commands registered with
-	praat_addAction (classMatrix, n, 0, 0, 0, 0, "xxx", "xxxx", x, DO_xxx) are visible,
+	praat_addAction1 (classMatrix, n, "xxx", "xxxx", x, DO_xxx) are visible,
 	and those with n=0 or n=3 are executable (the buttons are sensitive)
 	and, if chosen, performed on each of these three objects;
 	if the user has selected one object of type Artword and one of type
-	Speaker, the commands from praat_addAction (classArtword, 1, classSpeaker, 1, ...) are executable.
+	Speaker, the commands from praat_addAction2 (classArtword, 1, classSpeaker, 1, ...) are executable.
 	You may want to restrict the availability to one object for commands that write objects to file,
-	commands that present information in a dialog, or the Edit command.
+	commands that present information in a dialog, or the View & Edit command.
 */
 #define praat_INSENSITIVE  GuiMenu_INSENSITIVE
 #define praat_CHECKBUTTON  GuiMenu_CHECKBUTTON
@@ -111,13 +116,35 @@ void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, Class
 #define praat_DEPTH_5  0x00050000
 #define praat_DEPTH_6  0x00060000
 #define praat_DEPTH_7  0x00070000
-#define praat_CTRL  0x00200000
+#define praat_NO_API  0x00080000
+#define praat_FORCE_API  0x00100000
+#define praat_DEPRECATED  (0x00200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2004  (0x04200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2005  (0x05200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2006  (0x06200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2007  (0x07200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2008  (0x08200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2009  (0x09200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2010  (0x0A200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2011  (0x0B200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2012  (0x0C200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2013  (0x0D200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2014  (0x0E200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2015  (0x0F200000 | praat_HIDDEN)
+#define praat_DEPRECATED_2016  (0x10200000 | praat_HIDDEN)
+/*
+	The following three can also be used, but not for deprecated commands.
+*/
+//#define GuiMenu_OPTION  (1 << 24)
+//#define GuiMenu_SHIFT  (1 << 25)
+//#define GuiMenu_COMMAND  (1 << 26)
 void praat_removeAction (ClassInfo class1, ClassInfo class2, ClassInfo class3, const char32 *title);
 	/* 'class2' and 'class3' may be null. */
 	/* 'title' may be null; reference-copied. */
 
-GuiMenuItem praat_addMenuCommand (const char32 *window, const char32 *menu, const char32 *title /* cattable */,
-	const char32 *after, unsigned long flags, UiCallback callback);
+#define praat_addMenuCommand(w,m,t,a,f,c)  praat_addMenuCommand_ (w, m, t, a, f, c, U"" #c)
+GuiMenuItem praat_addMenuCommand_ (const char32 *window, const char32 *menu, const char32 *title /* cattable */,
+	const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback);
 /* All strings are reference-copied; 'title', 'after', and 'callback' may be null. */
 
 #define praat_MAXNUM_EDITORS 5
@@ -162,11 +189,6 @@ extern structPraatPicture theForegroundPraatPicture;
 extern PraatPicture theCurrentPraatPicture;
 	/* The global objects containing the state of the application; only reachable from interface files. */
 
-Daata praat_onlyObject (ClassInfo klas);
-	/* Returns a selected Daata of class 'klas'. */
-Daata praat_onlyObject_generic (ClassInfo klas);
-	/* Returns a selected Daata of class 'klas' or a subclass. */
-praat_Object praat_onlyScreenObject ();
 char32 *praat_name (int iobject);
 void praat_write_do (UiForm dia, const char32 *extension);
 void praat_new (autoDaata me);
@@ -183,7 +205,7 @@ void praat_newWithFile (autoDaata me, MelderFile file, const char32 *name);
 void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 
 /* Macros for description of forms (dialog boxes).
-	FORM prompts the user for arguments to DO_proc.
+	FORM prompts the user for arguments to proc.
 	Macros for FORM:
 	FORM (proc, title, helpString)
 		'proc' is the 'cb' argument of the corresponding VERB macro.
@@ -232,58 +254,108 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 		...
 		END
 	See Ui.h for more information.
-	Between DO and END, you should return 0 if something is wrong;
-	if everything is alright, you should trickle down to END; never return 1!
-	E.g. NOT return praat_new1 (...); BUT if (! praat_new1 (...)) return 0;
-	This is because END updates the selection if an object was created.
+	Between DO and END, you can throw an exception if anything is wrong;
+	if everything is all right, you just trickle down to END.
+	Never do "return", because END will update the selection if an object is created.
  */
 
 #ifndef _EditorM_h_
 
-#define FORM(proc,name,helpTitle) \
-	static void DO_##proc (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter interpreter, const char32 *invokingButtonTitle, bool modified, void *buttonClosure) { \
+#define FORM(proc,name,helpTitle)  \
+	extern "C" void proc (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter interpreter, const char32 *invokingButtonTitle, bool modified, void *buttonClosure); \
+	void proc (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter interpreter, const char32 *invokingButtonTitle, bool modified, void *buttonClosure) { \
+		int IOBJECT = 0; \
+		(void) IOBJECT; \
+		UiField radio = nullptr; \
+		(void) radio; \
 		static UiForm dia; \
-		if (! dia) { \
-			UiField radio = nullptr; \
-			(void) radio; \
-			dia = UiForm_create (theCurrentPraatApplication -> topShell, name, DO_##proc, buttonClosure, invokingButtonTitle, helpTitle);
-#define REAL(label,def)		UiForm_addReal (dia, label, def);
+		if (dia) goto dia_inited; \
+		dia = UiForm_create (theCurrentPraatApplication -> topShell, name, proc, buttonClosure, invokingButtonTitle, helpTitle);
+
+#define REAL(label,def)  UiForm_addReal (dia, label, def);
+#define REAL4(variable,label,def)  static double variable; UiForm_addReal4 (dia, & variable, U"" #variable, label, def);
+#define REALVAR REAL4
 #define REAL_OR_UNDEFINED(label,def)  UiForm_addRealOrUndefined (dia, label, def);
-#define POSITIVE(label,def)	UiForm_addPositive (dia, label, def);
-#define INTEGER(label,def)	UiForm_addInteger (dia, label, def);
-#define NATURAL(label,def)	UiForm_addNatural (dia, label, def);
-#define WORD(label,def)		UiForm_addWord (dia, label, def);
-#define SENTENCE(label,def)	UiForm_addSentence (dia, label, def);
-#define BOOLEAN(label,def)	UiForm_addBoolean (dia, label, def);
-#define LABEL(name,label)	UiForm_addLabel (dia, name, label);
-#define TEXTFIELD(name,def)	UiForm_addText (dia, name, def);
-#define RADIO(label,def)	radio = UiForm_addRadio (dia, label, def);
-#define RADIOBUTTON(label)	UiRadio_addButton (radio, label);
-#define OPTIONMENU(label,def)	radio = UiForm_addOptionMenu (dia, label, def);
+#define REAL_OR_UNDEFINED4(variable,label,def)  static double variable; UiForm_addRealOrUndefined4 (dia, & variable, U"" #variable, label, def);
+#define REAL_OR_UNDEFINEDVAR REAL_OR_UNDEFINEDVAR4
+#define POSITIVE(label,def)  UiForm_addPositive (dia, label, def);
+#define POSITIVE4(variable,label,def)  static double variable; UiForm_addPositive4 (dia, & variable, U"" #variable, label, def);
+#define POSITIVEVAR POSITIVE4
+#define INTEGER(label,def)  UiForm_addInteger (dia, label, def);
+#define INTEGER4(variable,label,def)  static long variable; UiForm_addInteger4 (dia, & variable, U"" #variable, label, def);
+#define INTEGERVAR INTEGER4
+#define NATURAL(label,def)  UiForm_addNatural (dia, label, def);
+#define NATURAL4(variable,label,def)  static long variable; UiForm_addNatural4 (dia, & variable, U"" #variable, label, def);
+#define NATURALVAR NATURAL4
+#define WORD(label,def)  UiForm_addWord (dia, label, def);
+#define WORD4(variable,label,def)  static char32 *variable; UiForm_addWord4 (dia, & variable, U"" #variable, label, def);
+#define WORDVAR WORD4
+#define SENTENCE(label,def)  UiForm_addSentence (dia, label, def);
+#define SENTENCE4(variable,label,def)  static char32 *variable; UiForm_addSentence4 (dia, & variable, U"" #variable, label, def);
+#define SENTENCEVAR SENTENCE4
+#define BOOLEAN(label,def)  UiForm_addBoolean (dia, label, def);
+#define BOOLEAN4(variable,label,def)  static bool variable; UiForm_addBoolean4 (dia, & variable, U"" #variable, label, def);
+#define BOOLEANVAR BOOLEAN4
+#define LABEL(name,label)  UiForm_addLabel (dia, name, label);
+#define TEXTFIELD(name,def)  UiForm_addText (dia, name, def);
+#define TEXTFIELD4(variable,name,def)  static char32 *variable; UiForm_addText4 (dia, & variable, U"" #variable, name, def);
+#define TEXTVAR TEXTFIELD4
+#define RADIO(label,def)  radio = UiForm_addRadio (dia, label, def);
+#define RADIO4(variable,label,def)  static int variable; radio = UiForm_addRadio4 (dia, & variable, nullptr, U"" #variable, label, def, 1);
+#define RADIOVAR RADIO4
+#define RADIO4x(variable,label,def,base)  static int variable; radio = UiForm_addRadio4 (dia, & variable, nullptr, U"" #variable, label, def, base);
+#define RADIOVARx RADIO4x
+#define RADIOSTR4(variable,label,def)  static char32 *variable; radio = UiForm_addRadio4 (dia, nullptr, & variable, U"" #variable, label, def, 1);
+#define RADIOSTRVAR RADIOSTR4
+#define RADIOBUTTON(label)  UiRadio_addButton (radio, label);
+#define OPTIONMENU(label,def)  radio = UiForm_addOptionMenu (dia, label, def);
+#define OPTIONMENU4(variable,label,def)  static int variable; radio = UiForm_addOptionMenu4 (dia, & variable, nullptr, U"" #variable, label, def, 1);
+#define OPTIONMENUVAR OPTIONMENU4
+#define OPTIONMENU4x(variable,label,def,base)  static int variable; radio = UiForm_addOptionMenu4 (dia, & variable, nullptr, U"" #variable, label, def, base);
+#define OPTIONMENUVARx OPTIONMENU4x
+#define OPTIONMENUSTR4(variable,label,def)  static char32 *variable; radio = UiForm_addOptionMenu4 (dia, nullptr, & variable, U"" #variable, label, def, 1);
+#define OPTIONMENUSTRVAR OPTIONMENUSTR4
 #define OPTION(label)	UiOptionMenu_addButton (radio, label);
-#define RADIOBUTTONS_ENUM(labelProc,min,max) { for (int itext = min; itext <= max; itext ++) RADIOBUTTON (labelProc) }
-#define OPTIONS_ENUM(labelProc,min,max) { for (int itext = min; itext <= max; itext ++) OPTION (labelProc) }
-#define RADIO_ENUM(label,enum,def) \
+#define RADIO_ENUM(label,enum,def)  \
 	RADIO (label, enum##_##def - enum##_MIN + 1) \
 	for (int ienum = enum##_MIN; ienum <= enum##_MAX; ienum ++) \
 		OPTION (enum##_getText (ienum))
-#define OPTIONMENU_ENUM(label,enum,def) \
+#define RADIO_ENUM4(variable,label,enum,def)  \
+	RADIO4x (variable, label, enum##_##def - enum##_MIN + 1, enum##_MIN) \
+	for (int ienum = enum##_MIN; ienum <= enum##_MAX; ienum ++) \
+		OPTION (enum##_getText (ienum))
+#define OPTIONMENU_ENUM(label,enum,def)  \
 	OPTIONMENU (label, enum##_##def - enum##_MIN + 1) \
 	for (int ienum = enum##_MIN; ienum <= enum##_MAX; ienum ++) \
 		OPTION (enum##_getText (ienum))
-#define LIST(label,n,str,def)	UiForm_addList (dia, label, n, str, def);
+#define OPTIONMENU_ENUM4(variable,label,enum,def)  \
+	OPTIONMENU4x (variable, label, enum##_##def - enum##_MIN + 1, enum##_MIN) \
+	for (int ienum = enum##_MIN; ienum <= enum##_MAX; ienum ++) \
+		OPTION (enum##_getText (ienum))
+#define OPTIONMENU_ENUMVAR OPTIONMENU_ENUM4
+#define OPTIONMENU_ENUMSTR4(variable,label,enum,def)  \
+	OPTIONMENUSTRVAR (variable, label, enum##_##def - enum##_MIN + 1) \
+	for (int ienum = enum##_MIN; ienum <= enum##_MAX; ienum ++) \
+		OPTION (enum##_getText (ienum))
+#define OPTIONMENU_ENUMSTRVAR OPTIONMENU_ENUMSTR4
+#define LIST(label,n,str,def)  UiForm_addList (dia, label, n, str, def);
+#define LIST4(variable,label,n,str,def)  static long variable; UiForm_addList4 (dia, & variable, nullptr, U"" #variable, label, n, str, def);
+#define LISTVAR LIST4
+#define LISTSTR4(variable,label,n,str,def)  static char32 *variable; UiForm_addList4 (dia, nullptr, & variable, U"" #variable, label, n, str, def);
+#define LISTSTRVAR LISTSTR4
 #define FILE_IN(label)		UiForm_addFileIn (dia, label);
 #define FILE_OUT(label,def)	UiForm_addFileOut (dia, label, def);
 #define COLOUR(label,def)	UiForm_addColour (dia, label, def);
 #define CHANNEL(label,def)	UiForm_addChannel (dia, label, def);
-#define OK UiForm_finish (dia); } if (! sendingForm && ! args && ! sendingString) {
-#define OK2 } UiForm_finish (dia); } if (! sendingForm && ! args && ! sendingString) {
+#define CHANNEL4(variable,label,def)   static long variable; UiForm_addChannel4 (dia, & variable, U"" #variable, label, def);
+#define CHANNELVAR CHANNEL4
+#define OK UiForm_finish (dia); dia_inited: if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 #define SET_REAL(name,value)	UiForm_setReal (dia, name, value);
 #define SET_INTEGER(name,value)	UiForm_setInteger (dia, name, value);
 #define SET_STRING(name,value)	UiForm_setString (dia, name, value);
 #define SET_ENUM(name,enum,value)  SET_STRING (name, enum##_getText (value))
 
-#define DO \
+#define DO  \
 			UiForm_do (dia, modified); \
 		} else if (! sendingForm) { \
 			trace (U"args ", Melder_pointer (args)); \
@@ -294,11 +366,9 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 			} \
 		} else { \
 			try { \
-				int IOBJECT = 0; \
-				(void) IOBJECT; \
 				{
 
-#define DO_ALTERNATIVE(alternative) \
+#define DO_ALTERNATIVE(alternative)  \
 			UiForm_do (dia, modified); \
 		} else if (! sendingForm) { \
 			trace (U"alternative args ", Melder_pointer (args)); \
@@ -312,7 +382,7 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 				char32 *parkedError = Melder_dup_f (Melder_getError ()); \
 				Melder_clearError (); \
 				try { \
-					DO_##alternative (nullptr, narg, args, sendingString, interpreter, invokingButtonTitle, modified, buttonClosure); \
+					alternative (nullptr, narg, args, sendingString, interpreter, invokingButtonTitle, modified, buttonClosure); \
 				} catch (MelderError) { \
 					Melder_clearError (); \
 					Melder_appendError (parkedError); \
@@ -323,11 +393,9 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 			} \
 		} else { \
 			try { \
-				int IOBJECT = 0; \
-				(void) IOBJECT; \
 				{
 
-#define END \
+#define END  \
 				} \
 			} catch (MelderError) { \
 				praat_updateSelection (); \
@@ -336,38 +404,31 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 			praat_updateSelection (); \
 		} \
 	}
-#define END2 \
+
+#define END_NO_NEW_DATA  \
 				} \
 			} catch (MelderError) { \
-				praat_updateSelection (); \
 				throw; \
 			} \
-			praat_updateSelection (); \
-		}
-
-#define DIRECT(proc) \
-	static void DO_##proc (UiForm dummy1, int narg, Stackel args, const char32 *dummy2, Interpreter dummy3, const char32 *dummy4, bool dummy5, void *dummy6) { \
-		(void) dummy1; (void) narg; (void) args; (void) dummy2; (void) dummy3; (void) dummy4; (void) dummy5; (void) dummy6; \
-		{ \
-			try { \
-				int IOBJECT = 0; \
-				(void) IOBJECT; \
-				{
+		} \
+	}
 
-#define DIRECT2(proc) \
-	static void DO_##proc (UiForm dummy1, int narg, Stackel args, const char32 *dummy2, Interpreter dummy3, const char32 *dummy4, bool dummy5, void *dummy6) { \
+#define DIRECT(proc)  \
+	extern "C" void proc (UiForm dummy1, int narg, Stackel args, const char32 *dummy2, Interpreter dummy3, const char32 *dummy4, bool dummy5, void *dummy6); \
+	void proc (UiForm dummy1, int narg, Stackel args, const char32 *dummy2, Interpreter dummy3, const char32 *dummy4, bool dummy5, void *dummy6) { \
 		(void) dummy1; (void) narg; (void) args; (void) dummy2; (void) dummy3; (void) dummy4; (void) dummy5; (void) dummy6; \
-		{ \
-			try { \
-				int IOBJECT = 0; \
-				(void) IOBJECT;
-
-#define FORM_READ2(proc,title,help,allowMult) \
-	static void DO_##proc (UiForm sendingForm, int, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure) { \
-		static UiForm dia; \
+		int IOBJECT = 0; \
+		(void) IOBJECT; \
+		{ { \
+			try {
+
+#define FORM_READ(proc,title,help,allowMult)  \
+	extern "C" void proc (UiForm sendingForm, int, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure); \
+	void proc (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure) { \
+		{ static UiForm dia; \
 		if (! dia) \
-			dia = UiInfile_create (theCurrentPraatApplication -> topShell, title, DO_##proc, okClosure, invokingButtonTitle, help, allowMult); \
-		if (! sendingForm && ! args && ! sendingString) { \
+			dia = UiInfile_create (theCurrentPraatApplication -> topShell, title, proc, okClosure, invokingButtonTitle, help, allowMult); \
+		if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) { \
 			UiInfile_do (dia); \
 		} else { \
 			try { \
@@ -382,33 +443,13 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 					file = & file2; \
 				}
 
-#define FORM_WRITE(proc,title,help,ext) \
-	static void DO_##proc (UiForm sendingForm, int, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure) { \
-		static UiForm dia; \
-		if (! dia) \
-			dia = UiOutfile_create (theCurrentPraatApplication -> topShell, title, DO_##proc, okClosure, invokingButtonTitle, help); \
-		if (! sendingForm && ! args && ! sendingString) { \
-			praat_write_do (dia, ext); \
-		} else { \
-			try { \
-				MelderFile file; \
-				int IOBJECT = 0; \
-				structMelderFile file2 { 0 }; \
-				(void) IOBJECT; \
-				if (! args && ! sendingString) { \
-					file = UiFile_getFile (dia); \
-				} else { \
-					Melder_relativePathToFile (args ? args [1]. string : sendingString, & file2); \
-					file = & file2; \
-				} \
-				{
-
-#define FORM_WRITE2(proc,title,help,ext) \
-	static void DO_##proc (UiForm sendingForm, int, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure) { \
-		static UiForm dia; \
+#define FORM_SAVE(proc,title,help,ext)  \
+	extern "C" void proc (UiForm sendingForm, int, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure); \
+	void proc (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString, Interpreter, const char32 *invokingButtonTitle, bool, void *okClosure) { \
+		{ static UiForm dia; \
 		if (! dia) \
-			dia = UiOutfile_create (theCurrentPraatApplication -> topShell, title, DO_##proc, okClosure, invokingButtonTitle, help); \
-		if (! sendingForm && ! args && ! sendingString) { \
+			dia = UiOutfile_create (theCurrentPraatApplication -> topShell, title, proc, okClosure, invokingButtonTitle, help); \
+		if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) { \
 			praat_write_do (dia, ext); \
 		} else { \
 			try { \
@@ -423,16 +464,6 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 					file = & file2; \
 				}
 
-/*
-	Macros for DO_proc:
-	GET_REAL (name)
-	GET_INTEGER (name)
-	GET_STRING (name)
-	GET_COLOUR (name)
-	GET_FILE (name)
-	REQUIRE (condition, errorMessage)
-		throws an error if condition false.
-*/
 #define GET_REAL(name)  UiForm_getReal (dia, name)
 #define GET_INTEGER(name)  UiForm_getInteger (dia, name)
 #define GET_STRING(name)  UiForm_getString (dia, name)
@@ -453,21 +484,207 @@ void praat_name2 (char32 *name, ClassInfo klas1, ClassInfo klas2);
 #define ID  (theCurrentPraatObjects -> list [IOBJECT]. id)
 #define ID_AND_FULL_NAME  Melder_cat (ID, U". ", FULL_NAME)
 #define NAME  praat_name (IOBJECT)
-#define EVERY(proc)  WHERE (SELECTED) proc;
-#define EVERY_CHECK(proc)  EVERY (if (! proc) return 0)
-#define EVERY_TO(proc)  EVERY_CHECK (praat_new1 (proc, NAME))
-#define ONLY(klas)  praat_onlyObject (klas)
-#define ONLY_GENERIC(klas)  praat_onlyObject_generic (klas)
-#define ONLY_OBJECT  (praat_onlyScreenObject () -> object)
-Daata praat_firstObject (ClassInfo klas);
-Daata praat_firstObject_generic (ClassInfo klas);
-Daata praat_firstObject_any ();
-#define FIRST(Klas)  (Klas) praat_firstObject (class##Klas)
-#define FIRST_GENERIC(Klas)  (Klas) praat_firstObject_generic (class##Klas)
-#define FIRST_ANY(Klas)  (Klas) praat_firstObject_any ()
-
-#define EVERY_DRAW(proc) \
-	praat_picture_open (); WHERE (SELECTED) proc; praat_picture_close (); return 1;
+
+#define CREATE_ONE
+#define CREATE_ONE_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define FIND_ONE(klas)  \
+	klas me = nullptr; \
+	LOOP { if (CLASS == class##klas || Thing_isSubclass (CLASS, class##klas)) me = (klas) OBJECT; break; }
+
+#define FIND_TWO(klas1,klas2)  \
+	klas1 me = nullptr; klas2 you = nullptr; \
+	LOOP { if (CLASS == class##klas1) me = (klas1) OBJECT; else if (CLASS == class##klas2) you = (klas2) OBJECT; \
+	if (me && you) break; }
+
+#define FIND_COUPLE(klas)  \
+	klas me = nullptr, you = nullptr; \
+	LOOP if (CLASS == class##klas || Thing_isSubclass (CLASS, class##klas)) (me ? you : me) = (klas) OBJECT;
+
+#define FIND_COUPLE_AND_ONE(klas1,klas2)  \
+	klas1 me = nullptr, you = nullptr; klas2 him = nullptr; \
+	LOOP { if (CLASS == class##klas1) (me ? you : me) = (klas1) OBJECT; else if (CLASS == class##klas2) him = (klas2) OBJECT; \
+	if (me && you && him) break; }
+
+#define FIND_ONE_AND_COUPLE(klas1,klas2)  \
+	klas1 me; klas2 you = nullptr, him = nullptr; \
+	LOOP { if (CLASS == class##klas1) me = (klas1) OBJECT; else if (CLASS == class##klas2) (you ? him : you) = (klas2) OBJECT; \
+	if (me && you && him) break; }
+
+#define FIND_THREE(klas1,klas2,klas3)  \
+	klas1 me = nullptr; klas2 you = nullptr; klas3 him = nullptr; \
+	LOOP { if (CLASS == class##klas1) me = (klas1) OBJECT; else if (CLASS == class##klas2) you = (klas2) OBJECT; \
+	else if (CLASS == class##klas3) him = (klas3) OBJECT; if (me && you && him) break; }
+
+#define FIND_FOUR(klas1,klas2,klas3,klas4)  \
+	klas1 me = nullptr; klas2 you = nullptr; klas3 him = nullptr; klas4 she = nullptr; \
+	LOOP { if (CLASS == class##klas1) me = (klas1) OBJECT; else if (CLASS == class##klas2) you = (klas2) OBJECT; \
+	else if (CLASS == class##klas3) him = (klas3) OBJECT; else if (CLASS == class##klas4) she = (klas4) OBJECT; \
+	if (me && you && him && she) break; }
+
+#define FIND_LIST(klas)  \
+	OrderedOf<struct##klas> list; \
+	LOOP { iam_LOOP (klas); list. addItem_ref (me); }
+	
+#define FIND_TYPED_LIST(klas,listClass)  \
+	auto##listClass list = listClass##_create (); \
+	LOOP { iam_LOOP (klas); list -> addItem_ref (me); }
+	
+#define FIND_ONE_AND_LIST(klas1,klas2)  \
+	OrderedOf<struct##klas2> list; klas1 me = nullptr; \
+	LOOP { if (CLASS == class##klas2) list. addItem_ref ((klas2) OBJECT); else if (CLASS == class##klas1) me = (klas1) OBJECT; }
+
+#define FIND_ONE_AND_TYPED_LIST(klas1,klas2,listClass)  \
+	auto##listClass list = listClass##_create (); klas1 me = nullptr; \
+	LOOP { if (CLASS == class##klas2) list -> addItem_ref ((klas2) OBJECT); else if (CLASS == class##klas1) me = (klas1) OBJECT; }
+
+#define FIND_TWO_AND_LIST(klas1,klas2,klas3)  \
+	OrderedOf<struct##klas3> list; klas1 me = nullptr; klas2 you = nullptr; \
+	LOOP { if (CLASS == class##klas3) list. addItem_ref ((klas3) OBJECT); else if (CLASS == class##klas1) me = (klas1) OBJECT; \
+	else if (CLASS == class##klas2) you = (klas2) OBJECT; }
+
+#define INFO_NONE
+#define INFO_NONE_END  END_NO_NEW_DATA
+
+#define INFO_ONE(klas)  FIND_ONE (klas)
+#define INFO_ONE_END  END_NO_NEW_DATA
+
+#define INFO_TWO(klas1,klas2)  FIND_TWO (klas1, klas2)
+#define INFO_TWO_END  END_NO_NEW_DATA
+
+#define INFO_COUPLE(klas)  FIND_COUPLE (klas)
+#define INFO_COUPLE_END  END_NO_NEW_DATA
+
+#define INFO_THREE(klas1,klas2,klas3)  FIND_THREE (klas1, klas2, klas3)
+#define INFO_THREE_END  END_NO_NEW_DATA
+
+#define HELP(page)  Melder_help (page); END_NO_NEW_DATA
+
+#define PLAY_EACH(klas)  LOOP { iam_LOOP (klas);
+#define PLAY_EACH_END  } END_NO_NEW_DATA
+
+#define GRAPHICS_NONE  autoPraatPicture picture;
+#define GRAPHICS_NONE_END  END_NO_NEW_DATA
+
+#define GRAPHICS_EACH(klas)  autoPraatPicture picture; LOOP { iam_LOOP (klas);
+#define GRAPHICS_EACH_END  } END_NO_NEW_DATA
+
+#define GRAPHICS_TWO(klas1,klas2)  autoPraatPicture picture; FIND_TWO (klas1, klas2)
+#define GRAPHICS_TWO_END  END_NO_NEW_DATA
+
+#define GRAPHICS_COUPLE(klas)  autoPraatPicture picture; FIND_COUPLE (klas)
+#define GRAPHICS_COUPLE_END  END_NO_NEW_DATA
+
+#define GRAPHICS_COUPLE_AND_ONE(klas1,klas2)  autoPraatPicture picture; FIND_COUPLE_AND_ONE (klas1, klas2)
+#define GRAPHICS_COUPLE_AND_ONE_END  END_NO_NEW_DATA
+
+#define MOVIE_ONE(klas,title,width,height)  \
+	Graphics graphics = Movie_create (title, width, height); \
+	FIND_ONE (klas)
+#define MOVIE_ONE_END  END_NO_NEW_DATA
+
+#define MOVIE_TWO(klas1,klas2,title,width,height)  \
+	Graphics graphics = Movie_create (title, width, height); \
+	FIND_TWO (klas1, klas2)
+#define MOVIE_TWO_END  END_NO_NEW_DATA
+
+#define MOVIE_THREE(klas1,klas2,klas3,title,width,height)  \
+	Graphics graphics = Movie_create (title, width, height); \
+	FIND_THREE (klas1, klas2, klas3)
+#define MOVIE_THREE_END  END_NO_NEW_DATA
+
+#define NUMBER_ONE(klas)  FIND_ONE (klas)
+#define NUMBER_ONE_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define NUMBER_TWO(klas1,klas2)  FIND_TWO (klas1, klas2)
+#define NUMBER_TWO_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define NUMBER_THREE(klas1,klas2,klas3)  FIND_THREE (klas1, klas2, klas3)
+#define NUMBER_THREE_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define NUMBER_COUPLE(klas)  FIND_COUPLE (klas)
+#define NUMBER_COUPLE_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define NUMBER_COUPLE_AND_ONE(klas1,klas2)  FIND_COUPLE_AND_ONE (klas1, klas2)
+#define NUMBER_COUPLE_AND_ONE_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define NUMBER_ONE_AND_LIST(klas1,klas2)  FIND_ONE_AND_LIST (klas1, klas2)
+#define NUMBER_ONE_AND_LIST_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define NUMBER_TWO_AND_LIST(klas1,klas2,klas3)  FIND_TWO_AND_LIST (klas1, klas2, klas3)
+#define NUMBER_TWO_AND_LIST_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define INTEGER_ONE(klas)  FIND_ONE (klas)
+#define INTEGER_ONE_END(...)  Melder_information (result, __VA_ARGS__); END_NO_NEW_DATA
+
+#define STRING_ONE(klas)  FIND_ONE (klas)
+#define STRING_ONE_END  Melder_information (result); END_NO_NEW_DATA
+
+#define MODIFY_EACH(klas)  LOOP { iam_LOOP (klas);
+#define MODIFY_EACH_END  praat_dataChanged (me); } END_NO_NEW_DATA
+
+#define MODIFY_EACH_WEAK(klas)  LOOP { iam_LOOP (klas); try {
+#define MODIFY_EACH_WEAK_END  praat_dataChanged (me); } catch (MelderError) { praat_dataChanged (me); throw; } } END_NO_NEW_DATA
+
+#define MODIFY_FIRST_OF_TWO(klas1,klas2)  FIND_TWO (klas1, klas2)
+#define MODIFY_FIRST_OF_TWO_END  praat_dataChanged (me); END_NO_NEW_DATA
+
+#define MODIFY_FIRST_OF_TWO_WEAK(klas1,klas2)  FIND_TWO (klas1, klas2) try {
+#define MODIFY_FIRST_OF_TWO_WEAK_END  praat_dataChanged (me); } catch (MelderError) { praat_dataChanged (me); throw; } END_NO_NEW_DATA
+
+#define MODIFY_FIRST_OF_THREE(klas1,klas2,klas3)  FIND_THREE (klas1, klas2, klas3)
+#define MODIFY_FIRST_OF_THREE_END  praat_dataChanged (me); END_NO_NEW_DATA
+
+#define MODIFY_FIRST_OF_ONE_AND_COUPLE(klas1,klas2)  FIND_ONE_AND_COUPLE (klas1, klas2)
+#define MODIFY_FIRST_OF_ONE_AND_COUPLE_END  praat_dataChanged (me); END_NO_NEW_DATA
+
+#define MODIFY_FIRST_OF_ONE_AND_COUPLE_WEAK(klas1,klas2)  FIND_ONE_AND_COUPLE (klas1, klas2) try {
+#define MODIFY_FIRST_OF_ONE_AND_COUPLE_WEAK_END  praat_dataChanged (me); } catch (MelderError) { praat_dataChanged (me); throw; } END_NO_NEW_DATA
+
+#define MODIFY_FIRST_OF_ONE_AND_LIST(klas1,klas2)  FIND_ONE_AND_LIST (klas1, klas2)
+#define MODIFY_FIRST_OF_ONE_AND_LIST_END  praat_dataChanged (me); END_NO_NEW_DATA
+
+#define CONVERT_EACH(klas)  LOOP { iam_LOOP (klas);
+#define CONVERT_EACH_END(...)  praat_new (result.move(), __VA_ARGS__); } END
+
+#define CONVERT_TWO(klas1,klas2)  FIND_TWO (klas1, klas2)
+#define CONVERT_TWO_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_COUPLE(klas)  FIND_COUPLE (klas)
+#define CONVERT_COUPLE_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_COUPLE_AND_ONE(klas1,klas2)  FIND_COUPLE_AND_ONE (klas1,klas2)
+#define CONVERT_COUPLE_AND_ONE_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_THREE(klas1,klas2,klas3)  FIND_THREE (klas1, klas2, klas3)
+#define CONVERT_THREE_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_FOUR(klas1,klas2,klas3,klas4)  FIND_FOUR (klas1, klas2, klas3, klas4)
+#define CONVERT_FOUR_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_LIST(klas)  FIND_LIST (klas)
+#define CONVERT_LIST_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_TYPED_LIST(klas,listClass)  FIND_TYPED_LIST (klas,listClass)
+#define CONVERT_TYPED_LIST_END(...)  praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_ONE_AND_LIST(klas1,klas2) FIND_ONE_AND_LIST (klas1, klas2)
+#define CONVERT_ONE_AND_LIST_END(...) praat_new (result.move(), __VA_ARGS__); END
+
+#define CONVERT_ONE_AND_TYPED_LIST(klas1,klas2,listClass) FIND_ONE_AND_TYPED_LIST (klas1, klas2, listClass)
+#define CONVERT_ONE_AND_TYPED_LIST_END(...) praat_new (result.move(), __VA_ARGS__); END
+
+#define READ_ONE
+#define READ_ONE_END  praat_newWithFile (result.move(), file, MelderFile_name (file)); END
+
+#define SAVE_ONE(klas)  FIND_ONE (klas)
+#define SAVE_ONE_END  END_NO_NEW_DATA
+
+#define SAVE_LIST(klas)  FIND_LIST (klas)
+#define SAVE_LIST_END  END_NO_NEW_DATA
+
+#define SAVE_TYPED_LIST(klas,listClass)  FIND_TYPED_LIST (klas, listClass)
+#define SAVE_TYPED_LIST_END  END_NO_NEW_DATA
 
 /* Used by praat_Sybil.cpp, if you put an Editor on the screen: */
 int praat_installEditor (Editor editor, int iobject);
@@ -475,17 +692,17 @@ int praat_installEditor (Editor editor, int iobject);
    which is in the list at position 'iobject'.
    It sets the destroyCallback and dataChangedCallback as appropriate for Praat:
    the destroyCallback will set the now dangling reference to nullptr,
-   so that a subsequent click on the "Edit" button will create a new editor;
+   so that a subsequent click on the "View & Edit" button will create a new editor;
    the dataChangedCallback will notify an open DataEditor with the same data,
    after that data will have changed.
       Return value: normally 1, but 0 if 'editor' is null.
    A typical calling sequence is:
-	DIRECT (Spectrogram_edit)
-		if (praat.batch) Melder_throw (U"Cannot edit a Spectrogram from batch.");
+	DIRECT (WINDOW_Spectrogram_viewAndEdit) {
+		if (praat.batch) Melder_throw (U"Cannot view or edit a Spectrogram from batch.");
 		else WHERE (SELECTED)
 			praat_installEditor
 				(SpectrogramEditor_create (praat.topShell, ID_AND_FULL_NAME, OBJECT), IOBJECT);
-	END
+	END }
 */
 int praat_installEditor2 (Editor editor, int iobject1, int iobject2);
 int praat_installEditor3 (Editor editor, int iobject1, int iobject2, int iobject3);
@@ -500,13 +717,13 @@ void praat_dataChanged (Daata object);
 void praat_picture_open ();
 void praat_picture_close ();
 /* These two routines should bracket drawing commands. */
-/* See also the EVERY_DRAW macro. */
+/* However, they usually do so RAII-wise by being packed into autoPraatPicture (see GRAPHICS_EACH). */
 
 /* For main.cpp */
 
-#define INCLUDE_LIBRARY(praat_xxx_init) \
+#define INCLUDE_LIBRARY(praat_xxx_init)  \
    { extern void praat_xxx_init (); praat_xxx_init (); }
-#define INCLUDE_MANPAGES(manual_xxx_init) \
+#define INCLUDE_MANPAGES(manual_xxx_init)  \
    { extern void manual_xxx_init (ManPages me); manual_xxx_init (theCurrentPraatApplication -> manPages); }
 
 /* For text-only applications that do not want to see that irritating Picture window. */
@@ -533,9 +750,6 @@ void praat_updateSelection ();
 void praat_addCommandsToEditor (Editor me);
 
 #define iam_LOOP(klas)  klas me = static_cast<klas> (OBJECT)
-#define iam_ONLY(klas)  klas me = static_cast<klas> (ONLY (class##klas))
-#define thouart_ONLY(klas)  klas thee = static_cast<klas> (ONLY (class##klas))
-#define heis_ONLY(klas)  klas him = static_cast<klas> (ONLY (class##klas))
 #define LOOP  for (IOBJECT = 1; IOBJECT <= theCurrentPraatObjects -> n; IOBJECT ++) if (SELECTED)
 
 autoCollection praat_getSelectedObjects ();
@@ -550,3 +764,4 @@ struct autoPraatPicture {
 #endif
 
 /* End of file praat.h */
+#endif
diff --git a/sys/praatP.h b/sys/praatP.h
index d3c8ce7..bee060b 100644
--- a/sys/praatP.h
+++ b/sys/praatP.h
@@ -1,6 +1,6 @@
 /* praatP.h
  *
- * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -45,7 +45,8 @@ void praat_addMenuCommandScript (const char32 *window, const char32 *menu, const
 void praat_hideMenuCommand (const char32 *window, const char32 *menu, const char32 *title);
 void praat_showMenuCommand (const char32 *window, const char32 *menu, const char32 *title);
 void praat_saveMenuCommands (MelderString *buffer);
-void praat_addFixedButtonCommand (GuiForm parent, const char32 *title, UiCallback callback, int x, int y);
+#define praat_addFixedButtonCommand(p,t,c,x,y)  praat_addFixedButtonCommand_ (p, t, c, U"" #c, x, y)
+void praat_addFixedButtonCommand_ (GuiForm parent, const char32 *title, UiCallback callback, const char32 *nameOfCallback, int x, int y);
 void praat_sensitivizeFixedButtonCommand (const char32 *title, int sensitive);
 void praat_sortMenuCommands ();
 
@@ -65,19 +66,23 @@ Thing_define (Praat_Command, Thing) {
 		/* If sendingString exists (apparently from a command file),
 			UiForm_parseString should be called, which will call this routine again with sendingForm. */
 		/* All of these things are normally taken care of by the macros defined in praat.h. */
+	const char32 *nameOfCallback;
 	signed char
 		visible,   // do the selected classes match class1, class2, class3 and class4?
 		executable,   // is the command actually executable? I.e. isn't the button greyed out?
 		depth,   // 0 = command in main menu, 1 = command in submenu, 2 = command in submenu of submenu
-		hidden,
-		toggled,
+		hidden,   // this can change when Praat is running, even from the start-up file
+		toggled,   // did the hiddenness change when Praat was running? The factory value for "hidden" is (hidden != toggled)
 		phase,
 		unhidable,
-		attractive;
+		attractive,
+		noApi,   // do not include in a library API ("View & Edit", help commands...)
+		forceApi;   // include in a library API even if this button is hidden by default ("Record Sound (fixed time)...")
+	int32 deprecationYear;
 	GuiThing button;
 	const char32 *window, *menu;
 	const char32 *script;   // if 'callback' equals DO_RunTheScriptFromAnyAddedMenuCommand
-	const char32 *after;   // title of previous command, often null
+	const char32 *after;   // title of previous command, often null; if starting with an asterisk (deprecation), then a reference to the replacement
 	int32 uniqueID;   // for sorting the added commands
 	int32 sortingTail;
 };
@@ -157,6 +162,18 @@ void praat_addFixedButtons (GuiWindow window);
 void praat_addMenus (GuiWindow window);
 void praat_addMenus2 ();
 
+/* API creation: */
+void praat_library_createC (bool isInHeaderFile, bool includeCreateAPI, bool includeReadAPI, bool includeSaveAPI,
+	bool includeQueryAPI, bool includeModifyAPI, bool includeToAPI,
+	bool includeRecordAPI, bool includePlayAPI,
+	bool includeDrawAPI, bool includeHelpAPI, bool includeWindowAPI,
+	bool includeDemoAPI);
+void praat_menuCommands_writeC (bool isInHeaderFile, bool includeCreateAPI, bool includeReadAPI,
+	bool includeRecordAPI, bool includePlayAPI, bool includeDrawAPI, bool includeHelpAPI, bool includeWindowAPI);
+void praat_actions_writeAsCHeader (bool includeSaveAPI,
+	bool includeQueryAPI, bool includeModifyAPI, bool includeToAPI,
+	bool includePlayAPI, bool includeDrawAPI, bool includeHelpAPI, bool includeWindowAPI);
+
 void praat_cleanUpName (char32 *name);
 void praat_list_renameAndSelect (int position, const char32 *name);
 
diff --git a/sys/praat_actions.cpp b/sys/praat_actions.cpp
index e963580..36c924a 100644
--- a/sys/praat_actions.cpp
+++ b/sys/praat_actions.cpp
@@ -1,6 +1,6 @@
 /* praat_actions.cpp
  *
- * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -81,36 +81,32 @@ static long lookUpMatchingAction (ClassInfo class1, ClassInfo class2, ClassInfo
 	return 0;   // not found
 }
 
-void praat_addAction (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback)
-{ praat_addAction4 (class1, n1, class2, n2, class3, n3, nullptr, 0, title, after, flags, callback); }
+void praat_addAction1_ (ClassInfo class1, int n1,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback)
+{ praat_addAction4_ (class1, n1, nullptr, 0, nullptr, 0, nullptr, 0, title, after, flags, callback, nameOfCallback); }
 
-void praat_addAction1 (ClassInfo class1, int n1,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback)
-{ praat_addAction4 (class1, n1, nullptr, 0, nullptr, 0, nullptr, 0, title, after, flags, callback); }
+void praat_addAction2_ (ClassInfo class1, int n1, ClassInfo class2, int n2,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback)
+{ praat_addAction4_ (class1, n1, class2, n2, nullptr, 0, nullptr, 0, title, after, flags, callback, nameOfCallback); }
 
-void praat_addAction2 (ClassInfo class1, int n1, ClassInfo class2, int n2,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback)
-{ praat_addAction4 (class1, n1, class2, n2, nullptr, 0, nullptr, 0, title, after, flags, callback); }
+void praat_addAction3_ (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback)
+{ praat_addAction4_ (class1, n1, class2, n2, class3, n3, nullptr, 0, title, after, flags, callback, nameOfCallback); }
 
-void praat_addAction3 (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback)
-{ praat_addAction4 (class1, n1, class2, n2, class3, n3, nullptr, 0, title, after, flags, callback); }
-
-void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3, ClassInfo class4, int n4,
-	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback)
+void praat_addAction4_ (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3, ClassInfo class4, int n4,
+	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback)
 {
 	try {
 		int depth = flags, key = 0;
 		bool unhidable = false, hidden = false, attractive = false;
-		unsigned long motifFlags = 0;
+		unsigned long guiFlags = 0;
 		if (flags > 7) {
 			depth = ((flags & praat_DEPTH_7) >> 16);
 			unhidable = (flags & praat_UNHIDABLE) != 0;
 			hidden = (flags & praat_HIDDEN) != 0 && ! unhidable;
 			key = flags & 0x000000FF;
-			motifFlags = key ? flags & (0x002000FF | GuiMenu_BUTTON_STATE_MASK) : flags & GuiMenu_BUTTON_STATE_MASK;
-			attractive = (motifFlags & praat_ATTRACTIVE) != 0;
+			guiFlags = key ? flags & (0x000000FF | GuiMenu_SHIFT | GuiMenu_BUTTON_STATE_MASK) : flags & GuiMenu_BUTTON_STATE_MASK;
+			attractive = (guiFlags & praat_ATTRACTIVE) != 0;
 		}
 		fixSelectionSpecification (& class1, & n1, & class2, & n2, & class3, & n3);
 
@@ -128,7 +124,7 @@ void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, Class
 		 * Determine the position of the new command.
 		 */
 		long position;
-		if (after) {   // search for existing command with same selection
+		if (after && after [0] != U'*') {   // search for existing command with same selection
 			long found = lookUpMatchingAction (class1, class2, class3, class4, after);
 			if (found == 0)
 				Melder_throw (U"The action command \"", title, U"\" cannot be put after \"", after, U"\",\n"
@@ -153,6 +149,7 @@ void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, Class
 		action -> title = Melder_dup_f (title);
 		action -> depth = depth;
 		action -> callback = callback;   // null for a separator
+		action -> nameOfCallback = nameOfCallback;
 		action -> button = nullptr;
 		action -> script = nullptr;
 		action -> hidden = hidden;
@@ -173,7 +170,7 @@ static void deleteDynamicMenu () {
 	if (actionsInvisible) return;
 	static long numberOfDeletions;
 	trace (U"deletion #", ++ numberOfDeletions);
-	for (int i = 1; i <= theActions.size; i ++) {
+	for (long i = 1; i <= theActions.size; i ++) {
 		Praat_Command action = theActions.at [i];
 		if (action -> button) {
 			trace (U"trying to destroy action ", i, U" of ", theActions.size, U": ", action -> title);
diff --git a/sys/praat_library.cpp b/sys/praat_library.cpp
new file mode 100644
index 0000000..03b60de
--- /dev/null
+++ b/sys/praat_library.cpp
@@ -0,0 +1,54 @@
+/* praat_library.cpp
+ *
+ * Copyright (C) 2016 Paul Boersma
+ *
+ * This code 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 code 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 work. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "praatP.h"
+
+void praat_library_createC (bool isInHeaderFile, bool includeCreateAPI, bool includeReadAPI, bool includeSaveAPI,
+	bool includeQueryAPI, bool includeModifyAPI, bool includeToAPI,
+	bool includeRecordAPI, bool includePlayAPI,
+	bool includeDrawAPI, bool includeHelpAPI, bool includeWindowAPI,
+	bool /* includeDemoAPI */)
+{
+	MelderInfo_open ();
+	MelderInfo_writeLine (U"/* praatlib.h");
+	MelderInfo_writeLine (U" *");
+	MelderInfo_writeLine (U" * Copyright (C) 2016 Paul Boersma");
+	MelderInfo_writeLine (U" *");
+	MelderInfo_writeLine (U" * This code is free software; you can redistribute it and/or modify");
+	MelderInfo_writeLine (U" * it under the terms of the GNU General Public License as published by");
+	MelderInfo_writeLine (U" * the Free Software Foundation; either version 3 of the License, or (at");
+	MelderInfo_writeLine (U" * your option) any later version.");
+	MelderInfo_writeLine (U" *");
+	MelderInfo_writeLine (U" * This code is distributed in the hope that it will be useful, but");
+	MelderInfo_writeLine (U" * WITHOUT ANY WARRANTY; without even the implied warranty of");
+	MelderInfo_writeLine (U" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
+	MelderInfo_writeLine (U" * See the GNU General Public License for more details.");
+	MelderInfo_writeLine (U" *");
+	MelderInfo_writeLine (U" * You should have received a copy of the GNU General Public License");
+	MelderInfo_writeLine (U" * along with this work. If not, see <http://www.gnu.org/licenses/>.");
+	MelderInfo_writeLine (U" */");
+
+	praat_menuCommands_writeC (true, includeCreateAPI, includeReadAPI,
+		includeRecordAPI, includePlayAPI, includeDrawAPI, includeHelpAPI, includeWindowAPI);
+	//praat_actions_writeAsCHeader (includeSaveAPI,
+	//	includeQueryAPI, includeModifyAPI, includeToAPI,
+	//	includePlayAPI, includeDrawAPI, includeHelpAPI, includeWindowAPI);
+	MelderInfo_close ();
+}
+
+/* End of file praat_statistics.cpp */
diff --git a/sys/praat_menuCommands.cpp b/sys/praat_menuCommands.cpp
index 78c51c0..82ecea3 100644
--- a/sys/praat_menuCommands.cpp
+++ b/sys/praat_menuCommands.cpp
@@ -1,6 +1,6 @@
 /* praat_menuCommands.cpp
  *
- * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
 
 #include "praatP.h"
 #include "praat_script.h"
+#include "praat_version.h"
 #include "GuiP.h"
 
 static OrderedOf <structPraat_Command> theCommands;
@@ -103,19 +104,23 @@ static GuiMenu windowMenuToWidget (const char32 *window, const char32 *menu) {
 		str32equ (window, U"Objects") ? praat_objects_resolveMenu (menu) : nullptr;
 }
 
-GuiMenuItem praat_addMenuCommand (const char32 *window, const char32 *menu, const char32 *title /* cattable */,
-	const char32 *after, unsigned long flags, UiCallback callback)
+GuiMenuItem praat_addMenuCommand_ (const char32 *window, const char32 *menu, const char32 *title /* cattable */,
+	const char32 *after, unsigned long flags, UiCallback callback, const char32 *nameOfCallback)
 {
 	long position;
 	int depth = flags, key = 0;
-	bool unhidable = false, hidden = false;
+	bool unhidable = false, hidden = false, noApi = false, forceApi = false;
+	int deprecationYear = 0;
 	unsigned long guiFlags = 0;
 	if (flags > 7) {
 		depth = ((flags & praat_DEPTH_7) >> 16);
 		unhidable = (flags & praat_UNHIDABLE) != 0;
 		hidden = (flags & praat_HIDDEN) != 0 && ! unhidable;
 		key = flags & 0x000000FF;
-		guiFlags = key ? flags & (0x006000FF | GuiMenu_BUTTON_STATE_MASK) : flags & GuiMenu_BUTTON_STATE_MASK;
+		noApi = (flags & praat_NO_API) != 0;
+		forceApi = (flags & praat_FORCE_API) != 0;
+		deprecationYear = (flags & praat_DEPRECATED) == praat_DEPRECATED ? 2000 + (flags >> 24) : 0;
+		guiFlags = key ? flags & (0x000000FF | GuiMenu_SHIFT | GuiMenu_OPTION | GuiMenu_BUTTON_STATE_MASK) : flags & GuiMenu_BUTTON_STATE_MASK;
 	}
 	if (callback && ! title) {
 		Melder_flushError (U"praat_addMenuCommand: command with callback has no title. Window \"", window, U"\", menu \"", menu, U"\".");
@@ -125,7 +130,7 @@ GuiMenuItem praat_addMenuCommand (const char32 *window, const char32 *menu, cons
 	/*
 	 * Determine the position of the new command.
 	 */
-	if (after) {   // search for existing command with same selection
+	if (after && after [0] != U'*') {   // search for existing command with same selection
 		long found = lookUpMatchingMenuCommand (window, menu, after);
 		if (found) {
 			position = found + 1;   // after 'after'
@@ -150,10 +155,14 @@ GuiMenuItem praat_addMenuCommand (const char32 *window, const char32 *menu, cons
 	trace (U"insert new command \"", title, U"\"");
 	command -> depth = depth;
 	command -> callback = callback;   // null for a separator or cascade button
+	command -> nameOfCallback = nameOfCallback;
 	command -> executable = !! callback;
 	command -> script = nullptr;
 	command -> hidden = hidden;
 	command -> unhidable = unhidable;
+	command -> deprecationYear = deprecationYear;
+	command -> noApi = noApi;
+	command -> forceApi = forceApi;
 
 	if (! theCurrentPraatApplication -> batch) {
 		GuiMenu parentMenu = nullptr;
@@ -231,7 +240,7 @@ void praat_addMenuCommandScript (const char32 *window, const char32 *menu, const
 		 * Determine the position of the new command.
 		 */
 		long position;
-		if (str32len (after)) {   // search for existing command with same selection
+		if (str32len (after) && after [0] != U'*') {   // search for existing command with same selection
 			long found = lookUpMatchingMenuCommand (window, menu, after);
 			if (found) {
 				position = found + 1;   // after 'after'
@@ -255,6 +264,7 @@ void praat_addMenuCommandScript (const char32 *window, const char32 *menu, const
 		command -> depth = depth;
 		command -> callback = str32len (script) ? DO_RunTheScriptFromAnyAddedMenuCommand : nullptr;   // null for a separator or cascade button
 		command -> executable = str32len (script) != 0;
+		command -> noApi = true;
 		if (str32len (script) == 0) {
 			command -> script = Melder_dup_f (U"");   // empty string, which will be needed to signal origin
 		} else {
@@ -363,12 +373,14 @@ void praat_saveMenuCommands (MelderString *buffer) {
 
 /***** FIXED BUTTONS *****/
 
-void praat_addFixedButtonCommand (GuiForm parent, const char32 *title, UiCallback callback, int x, int y) {
+void praat_addFixedButtonCommand_ (GuiForm parent, const char32 *title, UiCallback callback, const char32 *nameOfCallback, int x, int y) {
 	autoPraat_Command me = Thing_new (Praat_Command);
 	my window = Melder_dup_f (U"Objects");
 	my title = title;
 	my callback = callback;
+	my nameOfCallback = nameOfCallback;
 	my unhidable = true;
+	my noApi = ( str32equ (title, U"Inspect") );
 	if (theCurrentPraatApplication -> batch) {
 		my button = nullptr;
 	} else {
@@ -443,4 +455,81 @@ void praat_addCommandsToEditor (Editor me) {
 	}
 }
 
+static bool commandIsToBeIncluded (Praat_Command command, bool deprecated, bool includeCreateAPI, bool includeReadAPI,
+	bool includeRecordAPI, bool includePlayAPI, bool includeDrawAPI, bool includeHelpAPI, bool includeWindowAPI)
+{
+	bool obsolete = ( deprecated && (command -> deprecationYear < PRAAT_YEAR - 10 || command -> deprecationYear < 2017) );
+	bool hiddenByDefault = ( command -> hidden != command -> toggled );
+	bool explicitlyHidden = hiddenByDefault && ! deprecated;
+	bool hidden = explicitlyHidden || ! command -> callback || command -> noApi || obsolete ||
+		(! includeWindowAPI && Melder_nequ (command -> nameOfCallback, U"WINDOW_", 7)) ||
+		(! includeHelpAPI && Melder_nequ (command -> nameOfCallback, U"HELP_", 5)) ||
+		(! includeDrawAPI && Melder_nequ (command -> nameOfCallback, U"GRAPHICS_", 9)) ||
+		(! includePlayAPI && Melder_nequ (command -> nameOfCallback, U"PLAY_", 5)) ||
+		(! includeRecordAPI && Melder_nequ (command -> nameOfCallback, U"RECORD_", 7)) ||
+		(! includeReadAPI && Melder_nequ (command -> nameOfCallback, U"READ_", 5)) ||
+		(! includeReadAPI && Melder_nequ (command -> nameOfCallback, U"READ1_", 6)) ||
+		(! includeCreateAPI && Melder_nequ (command -> nameOfCallback, U"NEW1_", 5));
+	return command -> forceApi || ! hidden;
+}
+
+static bool commandHasFileNameArgument (Praat_Command command) {
+	bool hasFileNameArgument =
+		Melder_nequ (command -> nameOfCallback, U"READ1_", 6) ||
+		Melder_nequ (command -> nameOfCallback, U"SAVE_", 5)
+	;
+	return hasFileNameArgument;
+}
+
+static const char32 * getReturnType (Praat_Command command) {
+	const char32 *returnType =
+		Melder_nequ (command -> nameOfCallback, U"NEW1_", 5) ? U"PraatObject" :
+		Melder_nequ (command -> nameOfCallback, U"READ1_", 6) ? U"PraatObject" :
+		Melder_nequ (command -> nameOfCallback, U"REAL_", 5) ? U"double" :
+		Melder_nequ (command -> nameOfCallback, U"INTEGER_", 8) ? U"int64_t" :
+		Melder_nequ (command -> nameOfCallback, U"STRING_", 7) ? U"char *" :
+		Melder_nequ (command -> nameOfCallback, U"REPORT_", 7) ? U"char *" :
+		Melder_nequ (command -> nameOfCallback, U"LIST_", 5) ? U"char *" :
+		Melder_nequ (command -> nameOfCallback, U"INFO_", 5) ? U"char *" :
+		Melder_nequ (command -> nameOfCallback, U"HINT_", 5) ? U"char *" :
+		U"void";
+	return returnType;
+}
+
+void praat_menuCommands_writeC (bool isInHeaderFile, bool includeCreateAPI, bool includeReadAPI,
+	bool includeRecordAPI, bool includePlayAPI, bool includeDrawAPI, bool includeHelpAPI, bool includeWindowAPI)
+{
+	long numberOfApiMenuCommands = 0;
+	#define xstr(s) str(s)
+	#define str(s) #s
+	MelderInfo_writeLine (U"/* C API, version ", U"" xstr (PRAAT_MONTH), U" ", PRAAT_DAY, U", ", PRAAT_YEAR, U" */");
+	for (long i = 1; i <= theCommands.size; i ++) {
+		Praat_Command command = theCommands.at [i];
+		bool deprecated = ( command -> deprecationYear > 0 );
+		if (! commandIsToBeIncluded (command, deprecated, includeCreateAPI, includeReadAPI,
+			includeRecordAPI, includePlayAPI, includeDrawAPI, includeHelpAPI, includeWindowAPI)) continue;
+		MelderInfo_writeLine (U"\n/* Menu command \"", command -> title, U"\"",
+			deprecated ? U", deprecated " : U"", deprecated ? Melder_integer (command -> deprecationYear) : U"",
+			U" */");
+		const char32 *returnType = getReturnType (command);
+		MelderInfo_writeLine (returnType, U" Praat", str32chr (command -> nameOfCallback, U'_'), U" (");
+		bool isDirect = ! str32str (command -> title, U"...");
+		if (isDirect) {
+		} else {
+			command -> callback (0, -1, 0, 0, 0, 0, 0, 0);
+		}
+		if (commandHasFileNameArgument (command)) {
+			MelderInfo_writeLine (U"\tconst char *fileName");
+		}
+		MelderInfo_write (U")");
+		if (isInHeaderFile) {
+			MelderInfo_writeLine (U";");
+		} else {
+			MelderInfo_writeLine (U" {");
+			MelderInfo_writeLine (U"}");
+		}
+		numberOfApiMenuCommands += 1;
+	}
+}
+
 /* End of file praat_menuCommands.cpp */
diff --git a/sys/praat_objectMenus.cpp b/sys/praat_objectMenus.cpp
index 972b7ae..584b841 100644
--- a/sys/praat_objectMenus.cpp
+++ b/sys/praat_objectMenus.cpp
@@ -33,37 +33,28 @@
 
 /********** Callbacks of the fixed buttons. **********/
 
-DIRECT2 (Remove) {
+DIRECT (PRAAT_Remove) {
 	WHERE_DOWN (SELECTED)
 		praat_removeObject (IOBJECT);
 	praat_show ();
-END2 }
+END }
 
-FORM (Rename, U"Rename object", U"Rename...") {
+FORM (MODIFY_Rename, U"Rename object", U"Rename...") {
 	LABEL (U"rename object", U"New name:")
-	TEXTFIELD (U"newName", U"")
-	OK2
-int IOBJECT; WHERE (SELECTED) SET_STRING (U"newName", NAME)
+	TEXTFIELD4 (newName, U"newName", U"")
+OK
+	WHERE (SELECTED) SET_STRING (U"newName", NAME)
 DO
-	char32 *string = GET_STRING (U"newName");
 	if (theCurrentPraatObjects -> totalSelection == 0)
 		Melder_throw (U"Selection changed!\nNo object selected. Cannot rename.");
 	if (theCurrentPraatObjects -> totalSelection > 1)
 		Melder_throw (U"Selection changed!\nCannot rename more than one object at a time.");
 	WHERE (SELECTED) break;
-	praat_cleanUpName (string);   // this is allowed because "string" is local and dispensible
-	#if 0
-	std::u32string newFullName = std::u32string (Thing_className (OBJECT) + U" " + string;
-	if (newFullName != std::u32string (FULL_NAME)) {
-		Melder_free (FULL_NAME), FULL_NAME = Melder_dup_f (newFullName.c_str());
-		praat_list_renameAndSelect (IOBJECT, (std::u32string (Melder_integer (ID)) + U". " + newFullName). c_str());
-		for (int ieditor = 0; ieditor < praat_MAXNUM_EDITORS; ieditor ++)
-			if (EDITOR [ieditor]) Thing_setName (EDITOR [ieditor], newFullName.c_str());
-		Thing_setName (OBJECT, string);
-	}
-	#else
+	static MelderString string;
+	MelderString_copy (& string, newName);
+	praat_cleanUpName (string.string);
 	static MelderString fullName { 0 };
-	MelderString_copy (& fullName, Thing_className (OBJECT), U" ", string);
+	MelderString_copy (& fullName, Thing_className (OBJECT), U" ", string.string);
 	if (! str32equ (fullName.string, FULL_NAME)) {
 		Melder_free (FULL_NAME), FULL_NAME = Melder_dup_f (fullName.string);
 		autoMelderString listName;
@@ -71,36 +62,34 @@ DO
 		praat_list_renameAndSelect (IOBJECT, listName.string);
 		for (int ieditor = 0; ieditor < praat_MAXNUM_EDITORS; ieditor ++)
 			if (EDITOR [ieditor]) Thing_setName (EDITOR [ieditor], fullName.string);
-		Thing_setName (OBJECT, string);
+		Thing_setName (OBJECT, string.string);
 	}
-	#endif
-END2 }
+END }
 
-FORM (Copy, U"Copy object", U"Copy...") {
+FORM (NEW1_Copy, U"Copy object", U"Copy...") {
 	LABEL (U"copy object", U"Name of new object:")
-	TEXTFIELD (U"newName", U"")
-	OK2
-{ int IOBJECT; WHERE (SELECTED) SET_STRING (U"newName", NAME) }
+	TEXTFIELD4 (newName, U"newName", U"")
+OK
+	WHERE (SELECTED) SET_STRING (U"newName", NAME)
 DO
 	if (theCurrentPraatObjects -> totalSelection == 0)
 		Melder_throw (U"Selection changed!\nNo object selected. Cannot copy.");
 	if (theCurrentPraatObjects -> totalSelection > 1)
 		Melder_throw (U"Selection changed!\nCannot copy more than one object at a time.");
 	WHERE (SELECTED) {
-		char32 *name = GET_STRING (U"newName");
-		praat_new (Data_copy ((Daata) OBJECT), name);
+		praat_new (Data_copy ((Daata) OBJECT), newName);
 	}
-END2 }
+END }
 
-DIRECT2 (Info) {
+DIRECT (INFO_Info) {
 	if (theCurrentPraatObjects -> totalSelection == 0)
 		Melder_throw (U"Selection changed!\nNo object selected. Cannot query.");
 	if (theCurrentPraatObjects -> totalSelection > 1)
 		Melder_throw (U"Selection changed!\nCannot query more than one object at a time.");
 	WHERE (SELECTED) Thing_infoWithIdAndFile (OBJECT, ID, & theCurrentPraatObjects -> list [IOBJECT]. file);
-END2 }
+END }
 
-DIRECT2 (Inspect) {
+DIRECT (WINDOW_Inspect) {
 	if (theCurrentPraatObjects -> totalSelection == 0)
 		Melder_throw (U"Selection changed!\nNo object selected. Cannot inspect.");
 	if (theCurrentPraatApplication -> batch) {
@@ -112,7 +101,7 @@ DIRECT2 (Inspect) {
 			editor.releaseToUser();
 		}
 	}
-END2 }
+END }
 
 /********** The fixed menus. **********/
 
@@ -141,20 +130,20 @@ GuiMenu praat_objects_resolveMenu (const char32 *menu) {
 
 /********** Callbacks of the Praat menu. **********/
 
-DIRECT2 (About) {
+DIRECT (WINDOW_About) {
 	praat_showLogo (false);
-END2 }
+END }
 
-DIRECT2 (praat_newScript) {
+DIRECT (WINDOW_praat_newScript) {
 	autoScriptEditor editor = ScriptEditor_createFromText (nullptr, nullptr);
 	editor.releaseToUser();
-END2 }
+END }
 
-DIRECT2 (praat_openScript) {
+DIRECT (WINDOW_praat_openScript) {
 	autoScriptEditor editor = ScriptEditor_createFromText (nullptr, nullptr);
 	TextEditor_showOpen (editor.get());
 	editor.releaseToUser();
-END2 }
+END }
 
 static ButtonEditor theReferenceToTheOnlyButtonEditor;
 
@@ -162,7 +151,7 @@ static void cb_ButtonEditor_destruction (Editor /* editor */) {
 	theReferenceToTheOnlyButtonEditor = nullptr;
 }
 
-DIRECT2 (praat_editButtons) {
+DIRECT (WINDOW_praat_editButtons) {
 	if (theReferenceToTheOnlyButtonEditor) {
 		Editor_raise (theReferenceToTheOnlyButtonEditor);
 	} else {
@@ -171,123 +160,118 @@ DIRECT2 (praat_editButtons) {
 		theReferenceToTheOnlyButtonEditor = editor.get();
 		editor.releaseToUser();
 	}
-END2 }
-
-FORM (praat_addMenuCommand, U"Add menu command", U"Add menu command...") {
-	WORD (U"Window", U"Objects")
-	WORD (U"Menu", U"New")
-	SENTENCE (U"Command", U"Hallo...")
-	SENTENCE (U"After command", U"")
-	INTEGER (U"Depth", U"0")
+END }
+
+FORM (PRAAT_addMenuCommand, U"Add menu command", U"Add menu command...") {
+	WORD4 (window, U"Window", U"Objects")
+	WORD4 (menu, U"Menu", U"New")
+	SENTENCE4 (command, U"Command", U"Hallo...")
+	SENTENCE4 (afterCommand, U"After command", U"")
+	INTEGER4 (depth, U"Depth", U"0")
 	LABEL (U"", U"Script file:")
-	TEXTFIELD (U"Script", U"/u/miep/hallo.praat")
-	OK2
+	TEXTFIELD4 (script, U"script", U"/u/miep/hallo.praat")
+	OK
 DO
-	praat_addMenuCommandScript (GET_STRING (U"Window"), GET_STRING (U"Menu"),
-		GET_STRING (U"Command"), GET_STRING (U"After command"),
-		GET_INTEGER (U"Depth"), GET_STRING (U"Script"));
-END2 }
-
-FORM (praat_hideMenuCommand, U"Hide menu command", U"Hide menu command...") {
-	WORD (U"Window", U"Objects")
-	WORD (U"Menu", U"New")
-	SENTENCE (U"Command", U"Hallo...")
-	OK2
+	praat_addMenuCommandScript (window, menu, command, afterCommand, depth, script);
+END }
+
+FORM (PRAAT_hideMenuCommand, U"Hide menu command", U"Hide menu command...") {
+	WORD4 (window, U"Window", U"Objects")
+	WORD4 (menu, U"Menu", U"New")
+	SENTENCE4 (command, U"Command", U"Hallo...")
+	OK
 DO
-	praat_hideMenuCommand (GET_STRING (U"Window"), GET_STRING (U"Menu"), GET_STRING (U"Command"));
-END2 }
-
-FORM (praat_showMenuCommand, U"Show menu command", U"Show menu command...") {
-	WORD (U"Window", U"Objects")
-	WORD (U"Menu", U"New")
-	SENTENCE (U"Command", U"Hallo...")
-	OK2
+	praat_hideMenuCommand (window, menu, command);
+END }
+
+FORM (PRAAT_showMenuCommand, U"Show menu command", U"Show menu command...") {
+	WORD4 (window, U"Window", U"Objects")
+	WORD4 (menu, U"Menu", U"New")
+	SENTENCE4 (command, U"Command", U"Hallo...")
+	OK
 DO
-	praat_showMenuCommand (GET_STRING (U"Window"), GET_STRING (U"Menu"), GET_STRING (U"Command"));
-END2 }
-
-FORM (praat_addAction, U"Add action command", U"Add action command...") {
-	WORD (U"Class 1", U"Sound")
-	INTEGER (U"Number 1", U"0")
-	WORD (U"Class 2", U"")
-	INTEGER (U"Number 2", U"0")
-	WORD (U"Class 3", U"")
-	INTEGER (U"Number 3", U"0")
-	SENTENCE (U"Command", U"Play reverse")
-	SENTENCE (U"After command", U"Play")
-	INTEGER (U"Depth", U"0")
+	praat_showMenuCommand (window, menu, command);
+END }
+
+FORM (PRAAT_addAction, U"Add action command", U"Add action command...") {
+	WORD4 (class1, U"Class 1", U"Sound")
+	INTEGER4 (number1, U"Number 1", U"0")
+	WORD4 (class2, U"Class 2", U"")
+	INTEGER4 (number2, U"Number 2", U"0")
+	WORD4 (class3, U"Class 3", U"")
+	INTEGER4 (number3, U"Number 3", U"0")
+	SENTENCE4 (command, U"Command", U"Play reverse")
+	SENTENCE4 (afterCommand, U"After command", U"Play")
+	INTEGER4 (depth, U"Depth", U"0")
 	LABEL (U"", U"Script file:")
-	TEXTFIELD (U"Script", U"/u/miep/playReverse.praat")
-	OK2
+	TEXTFIELD4 (script, U"script", U"/u/miep/playReverse.praat")
+	OK
 DO
-	praat_addActionScript (GET_STRING (U"Class 1"), GET_INTEGER (U"Number 1"),
-		GET_STRING (U"Class 2"), GET_INTEGER (U"Number 2"), GET_STRING (U"Class 3"),
-		GET_INTEGER (U"Number 3"), GET_STRING (U"Command"), GET_STRING (U"After command"),
-		GET_INTEGER (U"Depth"), GET_STRING (U"Script"));
-END2 }
-
-FORM (praat_hideAction, U"Hide action command", U"Hide action command...") {
-	WORD (U"Class 1", U"Sound")
-	WORD (U"Class 2", U"")
-	WORD (U"Class 3", U"")
-	SENTENCE (U"Command", U"Play")
-	OK2
+	praat_addActionScript (class1, number1, class2, number2, class3, number3, command, afterCommand, depth, script);
+END }
+
+FORM (PRAAT_hideAction, U"Hide action command", U"Hide action command...") {
+	WORD4 (class1, U"Class 1", U"Sound")
+	WORD4 (class2, U"Class 2", U"")
+	WORD4 (class3, U"Class 3", U"")
+	SENTENCE4 (command, U"Command", U"Play")
+	OK
 DO
-	praat_hideAction_classNames (GET_STRING (U"Class 1"), GET_STRING (U"Class 2"), GET_STRING (U"Class 3"), GET_STRING (U"Command"));
-END2 }
-
-FORM (praat_showAction, U"Show action command", U"Show action command...") {
-	WORD (U"Class 1", U"Sound")
-	WORD (U"Class 2", U"")
-	WORD (U"Class 3", U"")
-	SENTENCE (U"Command", U"Play")
-	OK2
+	praat_hideAction_classNames (class1, class2, class3, command);
+END }
+
+FORM (PRAAT_showAction, U"Show action command", U"Show action command...") {
+	WORD4 (class1, U"Class 1", U"Sound")
+	WORD4 (class2, U"Class 2", U"")
+	WORD4 (class3, U"Class 3", U"")
+	SENTENCE4 (command, U"Command", U"Play")
+	OK
 DO
-	praat_showAction_classNames (GET_STRING (U"Class 1"), GET_STRING (U"Class 2"), GET_STRING (U"Class 3"), GET_STRING (U"Command"));
-END2 }
+	praat_showAction_classNames (class1, class2, class3, command);
+END }
 
 /********** Callbacks of the Preferences menu. **********/
 
-FORM (TextInputEncodingSettings, U"Text reading preferences", U"Unicode") {
-	RADIO_ENUM (U"Encoding of 8-bit text files", kMelder_textInputEncoding, DEFAULT)
-	OK2
-SET_ENUM (U"Encoding of 8-bit text files", kMelder_textInputEncoding, Melder_getInputEncoding ())
+FORM (PREFS_TextInputEncodingSettings, U"Text reading preferences", U"Unicode") {
+	RADIO_ENUM4 (encodingOf8BitTextFiles, U"Encoding of 8-bit text files", kMelder_textInputEncoding, DEFAULT)
+OK
+	SET_ENUM (U"Encoding of 8-bit text files", kMelder_textInputEncoding, Melder_getInputEncoding ())
 DO
-	Melder_setInputEncoding (GET_ENUM (kMelder_textInputEncoding, U"Encoding of 8-bit text files"));
-END2 }
+	Melder_setInputEncoding ((kMelder_textInputEncoding) encodingOf8BitTextFiles);
+END }
 
-FORM (TextOutputEncodingSettings, U"Text writing preferences", U"Unicode") {
-	RADIO_ENUM (U"Output encoding", kMelder_textOutputEncoding, DEFAULT)
-	OK2
-SET_ENUM (U"Output encoding", kMelder_textOutputEncoding, Melder_getOutputEncoding ())
+FORM (PREFS_TextOutputEncodingSettings, U"Text writing preferences", U"Unicode") {
+	RADIO_ENUM4 (outputEncoding, U"Output encoding", kMelder_textOutputEncoding, DEFAULT)
+OK
+	SET_ENUM (U"Output encoding", kMelder_textOutputEncoding, Melder_getOutputEncoding ())
 DO
-	Melder_setOutputEncoding (GET_ENUM (kMelder_textOutputEncoding, U"Output encoding"));
-END2 }
+	Melder_setOutputEncoding ((kMelder_textOutputEncoding) outputEncoding);
+END }
 
-FORM (GraphicsCjkFontStyleSettings, U"CJK font style preferences", nullptr) {
-	OPTIONMENU_ENUM (U"CJK font style", kGraphics_cjkFontStyle, DEFAULT)
-	OK2
-SET_ENUM (U"CJK font style", kGraphics_cjkFontStyle, theGraphicsCjkFontStyle)
+FORM (PREFS_GraphicsCjkFontStyleSettings, U"CJK font style preferences", nullptr) {
+	OPTIONMENU_ENUM4 (cjkFontStyle, U"CJK font style", kGraphics_cjkFontStyle, DEFAULT)
+OK
+	SET_ENUM (U"CJK font style", kGraphics_cjkFontStyle, theGraphicsCjkFontStyle)
 DO
-	theGraphicsCjkFontStyle = GET_ENUM (kGraphics_cjkFontStyle, U"CJK font style");
-END2 }
+	theGraphicsCjkFontStyle = (kGraphics_cjkFontStyle) cjkFontStyle;
+END }
 
 /********** Callbacks of the Goodies menu. **********/
 
-FORM (praat_calculator, U"Calculator", U"Calculator") {
+FORM (STRING_praat_calculator, U"Calculator", U"Calculator") {
 	LABEL (U"", U"Type any numeric formula or string formula:")
-	TEXTFIELD (U"expression", U"5*5")
+	TEXTFIELD4 (expression, U"expression", U"5*5")
 	LABEL (U"", U"Note that you can include many special functions in your formula,")
 	LABEL (U"", U"including statistical functions and acoustics-auditory conversions.")
 	LABEL (U"", U"For details, click Help.")
-	OK2
+	OK
 DO
 	struct Formula_Result result;
 	if (! interpreter) {
 		autoInterpreter tempInterpreter = Interpreter_create (nullptr, nullptr);
-		Interpreter_anyExpression (tempInterpreter.get(), GET_STRING (U"expression"), & result);
+		Interpreter_anyExpression (tempInterpreter.get(), expression, & result);
 	} else {
-		Interpreter_anyExpression (interpreter, GET_STRING (U"expression"), & result);
+		Interpreter_anyExpression (interpreter, expression, & result);
 	}
 	switch (result. expressionType) {
 		case kFormula_EXPRESSION_TYPE_NUMERIC: {
@@ -302,22 +286,20 @@ DO
 		case kFormula_EXPRESSION_TYPE_NUMERIC_MATRIX: {
 		}
 	}
-END2 }
-
-FORM (praat_reportDifferenceOfTwoProportions, U"Report difference of two proportions", U"Difference of two proportions") {
-	INTEGER (U"left Row 1", U"71")
-	INTEGER (U"right Row 1", U"39")
-	INTEGER (U"left Row 2", U"93")
-	INTEGER (U"right Row 2", U"27")
-	OK2
+END }
+
+FORM (INFO_reportDifferenceOfTwoProportions, U"Report difference of two proportions", U"Difference of two proportions") {
+	INTEGER4 (a, U"left Row 1", U"71")
+	INTEGER4 (b, U"right Row 1", U"39")
+	INTEGER4 (c, U"left Row 2", U"93")
+	INTEGER4 (d, U"right Row 2", U"27")
+	OK
 DO
-	double a = GET_INTEGER (U"left Row 1"), b = GET_INTEGER (U"right Row 1");
-	double c = GET_INTEGER (U"left Row 2"), d = GET_INTEGER (U"right Row 2");
 	double n = a + b + c + d;
 	double aexp, bexp, cexp, dexp, crossDifference, x2;
-	REQUIRE (a >= 0 && b >= 0 && c >= 0 && d >= 0, U"Numbers must not be negative.")
-	REQUIRE ((a > 0 || b > 0) && (c > 0 || d > 0), U"Row totals must be positive.")
-	REQUIRE ((a > 0 || c > 0) && (b > 0 || d > 0), U"Column totals must be positive.")
+	if (a < 0 || b < 0 || c < 0 || d < 0) Melder_throw (U"The numbers should not be negative.");
+	if (a + b <= 0 || c + d <= 0) Melder_throw (U"The row totals should be positive.");
+	if (a + c <= 0 || b + d <= 0) Melder_throw (U"The column totals should be positive.");
 	MelderInfo_open ();
 	MelderInfo_writeLine (U"Observed row 1 =    ", lround (a), U"    ", lround (b));
 	MelderInfo_writeLine (U"Observed row 2 =    ", lround (c), U"    ", lround (d));
@@ -351,11 +333,11 @@ DO
 	MelderInfo_writeLine (U"Chi-square =    ", x2);
 	MelderInfo_writeLine (U"Two-tailed p =    ", NUMchiSquareQ (x2, 1));
 	MelderInfo_close ();
-END2 }
+END }
 
 /********** Callbacks of the Technical menu. **********/
 
-FORM (praat_debug, U"Set debugging options", nullptr) {
+FORM (PRAAT_debug, U"Set debugging options", nullptr) {
 	LABEL (U"", U"If you switch Tracing on, Praat will write lots of detailed ")
 	LABEL (U"", U"information about what goes on in Praat")
 	structMelderDir dir;
@@ -367,42 +349,63 @@ FORM (praat_debug, U"Set debugging options", nullptr) {
 		MelderDir_getFile (& dir, U"Tracing.txt", & file);
 	#endif
 	LABEL (U"", Melder_cat (U"to ", Melder_fileToPath (& file), U"."))
-	BOOLEAN (U"Tracing", false)
+	BOOLEAN4 (tracing, U"Tracing", false)
 	LABEL (U"", U"Setting the following to anything other than zero")
 	LABEL (U"", U"will alter the behaviour of Praat")
 	LABEL (U"", U"in unpredictable ways.")
-	INTEGER (U"Debug option", U"0")
-	OK2
-SET_INTEGER (U"Tracing", Melder_isTracing)
-SET_INTEGER (U"Debug option", Melder_debug)
+	INTEGER4 (debugOption, U"Debug option", U"0")
+OK
+	SET_INTEGER (U"Tracing", Melder_isTracing)
+	SET_INTEGER (U"Debug option", Melder_debug)
 DO
-	Melder_setTracing (GET_INTEGER (U"Tracing"));
-	Melder_debug = GET_INTEGER (U"Debug option");
-END2 }
+	Melder_setTracing (tracing);
+	Melder_debug = debugOption;
+END }
 
-DIRECT2 (praat_listReadableTypesOfObjects) {
+DIRECT (INFO_listReadableTypesOfObjects) {
 	Thing_listReadableClasses ();
-END2 }
+END }
+
+FORM (INFO_praat_library_createC, U"PraatLib: Create C header or file", nullptr) {
+	BOOLEAN4 (isInHeader, U"Is in header", true)
+	BOOLEAN4 (includeCreateAPI, U"Include \"Create\" API", true)
+	BOOLEAN4 (includeReadAPI, U"Include \"Read\" API", true)
+	BOOLEAN4 (includeSaveAPI, U"Include \"Save\" API", true)
+	BOOLEAN4 (includeQueryAPI, U"Include \"Query\" API", true)
+	BOOLEAN4 (includeModifyAPI, U"Include \"Modify\" API", true)
+	BOOLEAN4 (includeToAPI, U"Include \"To\" API", true)
+	BOOLEAN4 (includeRecordAPI, U"Include \"Record\" API", true)
+	BOOLEAN4 (includePlayAPI, U"Include \"Play\" API", true)
+	BOOLEAN4 (includeDrawAPI, U"Include \"Draw\" API", true)
+	BOOLEAN4 (includeHelpAPI, U"Include \"Help\" API", false)
+	BOOLEAN4 (includeWindowAPI, U"Include \"Window\" API", false)
+	BOOLEAN4 (includeDemoAPI, U"Include \"Demo\" API", false)
+	OK
+DO
+	praat_library_createC (isInHeader, includeCreateAPI, includeReadAPI, includeSaveAPI,
+		includeQueryAPI, includeModifyAPI, includeToAPI, includeRecordAPI, includePlayAPI,
+		includeDrawAPI, includeHelpAPI, includeWindowAPI, includeDemoAPI);
+END }
 
-DIRECT2 (praat_reportSystemProperties) {
+DIRECT (INFO_reportSystemProperties) {
 	praat_reportSystemProperties ();
-END2 }
+END }
 
-DIRECT2 (praat_reportGraphicalProperties) {
+DIRECT (INFO_reportGraphicalProperties) {
 	praat_reportGraphicalProperties ();
-END2 }
+END }
 
-DIRECT2 (praat_reportIntegerProperties) {
+DIRECT (INFO_reportIntegerProperties) {
 	praat_reportIntegerProperties ();
-END2 }
+END }
 
-DIRECT2 (praat_reportMemoryUse) {
+DIRECT (INFO_reportMemoryUse) {
 	praat_reportMemoryUse ();
-END2 }
+END }
 
-DIRECT2 (praat_reportTextProperties) {
+DIRECT (INFO_reportTextProperties) {
 	praat_reportTextProperties ();
-END2 }
+END }
 
 /********** Callbacks of the Open menu. **********/
 
@@ -432,13 +435,13 @@ static void readFromFile (MelderFile file) {
 	praat_updateSelection ();
 }
 
-FORM_READ2 (Data_readFromFile, U"Read Object(s) from file", 0, true) {
+FORM_READ (READMANY_Data_readFromFile, U"Read Object(s) from file", 0, true) {
 	readFromFile (file);
-END2 }
+END }
 
 /********** Callbacks of the Save menu. **********/
 
-FORM_WRITE2 (Data_writeToTextFile, U"Save Object(s) as one text file", nullptr, nullptr) {
+FORM_SAVE (SAVE_Data_writeToTextFile, U"Save Object(s) as one text file", nullptr, nullptr) {
 	if (theCurrentPraatObjects -> totalSelection == 1) {
 		LOOP {
 			iam (Daata);
@@ -448,9 +451,9 @@ FORM_WRITE2 (Data_writeToTextFile, U"Save Object(s) as one text file", nullptr,
 		autoCollection set = praat_getSelectedObjects ();
 		Data_writeToTextFile (set.get(), file);
 	}
-END2 }
+END }
 
-FORM_WRITE2 (Data_writeToShortTextFile, U"Save Object(s) as one short text file", nullptr, nullptr) {
+FORM_SAVE (SAVE_Data_writeToShortTextFile, U"Save Object(s) as one short text file", nullptr, nullptr) {
 	if (theCurrentPraatObjects -> totalSelection == 1) {
 		LOOP {
 			iam (Daata);
@@ -460,9 +463,9 @@ FORM_WRITE2 (Data_writeToShortTextFile, U"Save Object(s) as one short text file"
 		autoCollection set = praat_getSelectedObjects ();
 		Data_writeToShortTextFile (set.get(), file);
 	}
-END2 }
+END }
 
-FORM_WRITE2 (Data_writeToBinaryFile, U"Save Object(s) as one binary file", nullptr, nullptr) {
+FORM_SAVE (SAVE_Data_writeToBinaryFile, U"Save Object(s) as one binary file", nullptr, nullptr) {
 	if (theCurrentPraatObjects -> totalSelection == 1) {
 		LOOP {
 			iam (Daata);
@@ -472,24 +475,23 @@ FORM_WRITE2 (Data_writeToBinaryFile, U"Save Object(s) as one binary file", nullp
 		autoCollection set = praat_getSelectedObjects ();
 		Data_writeToBinaryFile (set.get(), file);
 	}
-END2 }
+END }
 
-FORM (ManPages_saveToHtmlDirectory, U"Save all pages as HTML files", nullptr) {
+FORM (PRAAT_ManPages_saveToHtmlDirectory, U"Save all pages as HTML files", nullptr) {
 	LABEL (U"", U"Type a directory name:")
-	TEXTFIELD (U"directory", U"")
-	OK2
-structMelderDir currentDirectory { { 0 } };
-Melder_getDefaultDir (& currentDirectory);
-SET_STRING (U"directory", Melder_dirToPath (& currentDirectory))
+	TEXTFIELD4 (directory, U"directory", U"")
+OK
+	structMelderDir currentDirectory { { 0 } };
+	Melder_getDefaultDir (& currentDirectory);
+	SET_STRING (U"directory", Melder_dirToPath (& currentDirectory))
 DO
-	char32 *directory = GET_STRING (U"directory");
 	LOOP {
 		iam (ManPages);
 		ManPages_writeAllToHtmlDir (me, directory);
 	}
-END2 }
+END }
 
-DIRECT2 (ManPages_view) {
+DIRECT (WINDOW_ManPages_view) {
 	LOOP {
 		iam (ManPages);
 		ManPage firstPage = my pages.at [1];
@@ -500,46 +502,45 @@ DIRECT2 (ManPages_view) {
 		praat_installEditor (manual.get(), IOBJECT);
 		manual.releaseToUser();
 	}
-END2 }
+END }
 
 /********** Callbacks of the Help menu. **********/
 
-FORM (SearchManual, U"Search manual", U"Manual") {
+FORM (HELP_SearchManual, U"Search manual", U"Manual") {
 	LABEL (U"", U"Search for strings (separate with spaces):")
-	TEXTFIELD (U"query", U"")
-	OK2
+	TEXTFIELD4 (query, U"query", U"")
+	OK
 DO
 	if (theCurrentPraatApplication -> batch)
 		Melder_throw (U"Cannot view a manual from batch.");
 	autoManual manual = Manual_create (U"Intro", theCurrentPraatApplication -> manPages, false);
-	Manual_search (manual.get(), GET_STRING (U"query"));
+	Manual_search (manual.get(), query);
 	manual.releaseToUser();
-END2 }
+END }
 
-FORM (GoToManualPage, U"Go to manual page", nullptr) {
-	{long numberOfPages;
-	const char32 **pages = ManPages_getTitles (theCurrentPraatApplication -> manPages, & numberOfPages);
-	LIST (U"Page", numberOfPages, pages, 1)}
-	OK2
+FORM (HELP_GoToManualPage, U"Go to manual page", nullptr) {
+	static long numberOfPages;
+	static const char32 **pages = ManPages_getTitles (theCurrentPraatApplication -> manPages, & numberOfPages);
+	LIST (U"Page", numberOfPages, pages, 1)
+	OK
 DO
 	if (theCurrentPraatApplication -> batch)
 		Melder_throw (U"Cannot view a manual from batch.");
 	autoManual manual = Manual_create (U"Intro", theCurrentPraatApplication -> manPages, false);
 	HyperPage_goToPage_i (manual.get(), GET_INTEGER (U"Page"));
 	manual.releaseToUser();
-END2 }
+END }
 
-FORM (WriteManualToHtmlDirectory, U"Save all pages as HTML files", nullptr) {
+FORM (HELP_WriteManualToHtmlDirectory, U"Save all pages as HTML files", nullptr) {
 	LABEL (U"", U"Type a directory name:")
-	TEXTFIELD (U"directory", U"")
-	OK2
-structMelderDir currentDirectory { { 0 } };
-Melder_getDefaultDir (& currentDirectory);
-SET_STRING (U"directory", Melder_dirToPath (& currentDirectory))
+	TEXTFIELD4 (directory, U"directory", U"")
+OK
+	structMelderDir currentDirectory { { 0 } };
+	Melder_getDefaultDir (& currentDirectory);
+	SET_STRING (U"directory", Melder_dirToPath (& currentDirectory))
 DO
-	char32 *directory = GET_STRING (U"directory");
 	ManPages_writeAllToHtmlDir (theCurrentPraatApplication -> manPages, directory);
-END2 }
+END }
 
 /********** Menu descriptions. **********/
 
@@ -560,15 +561,15 @@ void praat_show () {
 /********** Menu descriptions. **********/
 
 void praat_addFixedButtons (GuiWindow window) {
-	praat_addFixedButtonCommand (window, U"Rename...", DO_Rename, 8, 70);
-	praat_addFixedButtonCommand (window, U"Copy...", DO_Copy, 98, 70);
-	praat_addFixedButtonCommand (window, U"Inspect", DO_Inspect, 8, 40);
-	praat_addFixedButtonCommand (window, U"Info", DO_Info, 98, 40);
-	praat_addFixedButtonCommand (window, U"Remove", DO_Remove, 8, 10);
+	praat_addFixedButtonCommand (window, U"Rename...", MODIFY_Rename, 8, 70);
+	praat_addFixedButtonCommand (window, U"Copy...", NEW1_Copy, 98, 70);
+	praat_addFixedButtonCommand (window, U"Inspect", WINDOW_Inspect, 8, 40);
+	praat_addFixedButtonCommand (window, U"Info", INFO_Info, 98, 40);
+	praat_addFixedButtonCommand (window, U"Remove", PRAAT_Remove, 8, 10);
 }
 
 static void searchProc () {
-	DO_SearchManual (nullptr, 0, nullptr, nullptr, nullptr, nullptr, false, nullptr);
+	HELP_SearchManual (nullptr, 0, nullptr, nullptr, nullptr, nullptr, false, nullptr);
 }
 
 static MelderString itemTitle_about { 0 };
@@ -593,24 +594,24 @@ static void cb_openDocument (MelderFile file) {
 }
 
 #if cocoa
-DIRECT2 (praat_cut) {
+DIRECT (PRAAT_cut) {
 	[[[NSApp keyWindow] fieldEditor: YES forObject: nil] cut: nil];
-END2 }
-DIRECT2 (praat_copy) {
+END }
+DIRECT (PRAAT_copy) {
 	[[[NSApp keyWindow] fieldEditor: YES forObject: nil] copy: nil];
-END2 }
-DIRECT2 (praat_paste) {
+END }
+DIRECT (PRAAT_paste) {
 	[[[NSApp keyWindow] fieldEditor: YES forObject: nil] pasteAsPlainText: nil];
-END2 }
-DIRECT2 (praat_minimize) {
+END }
+DIRECT (PRAAT_minimize) {
 	[[NSApp keyWindow] performMiniaturize: nil];
-END2 }
-DIRECT2 (praat_zoom) {
+END }
+DIRECT (PRAAT_zoom) {
 	[[NSApp keyWindow] performZoom: nil];
-END2 }
-DIRECT2 (praat_close) {
+END }
+DIRECT (PRAAT_close) {
 	[[NSApp keyWindow] performClose: nil];
-END2 }
+END }
 #endif
 
 void praat_addMenus (GuiWindow window) {
@@ -642,81 +643,83 @@ void praat_addMenus (GuiWindow window) {
 	
 	MelderString_append (& itemTitle_about, U"About ", praatP.title, U"...");
 	#ifdef macintosh
-		praat_addMenuCommand (U"Objects", U"Praat", itemTitle_about.string, nullptr, praat_UNHIDABLE, DO_About);
+		praat_addMenuCommand (U"Objects", U"Praat", itemTitle_about.string, nullptr, praat_UNHIDABLE, WINDOW_About);
 		#if cocoa
 			/*
 			 * HACK: give the following command weird names,
 			 * because otherwise they may be called from a script.
 			 * (we add three alt-spaces)
 			 */
-			praat_addMenuCommand (U"Objects", U"Edit", U"Cut   ", nullptr, praat_UNHIDABLE + 'X', DO_praat_cut);
-			praat_addMenuCommand (U"Objects", U"Edit", U"Copy   ", nullptr, praat_UNHIDABLE + 'C', DO_praat_copy);
-			praat_addMenuCommand (U"Objects", U"Edit", U"Paste   ", nullptr, praat_UNHIDABLE + 'V', DO_praat_paste);
-			praat_addMenuCommand (U"Objects", U"Window", U"Minimize   ", nullptr, praat_UNHIDABLE, DO_praat_minimize);
-			praat_addMenuCommand (U"Objects", U"Window", U"Zoom   ", nullptr, praat_UNHIDABLE, DO_praat_zoom);
-			praat_addMenuCommand (U"Objects", U"Window", U"Close   ", nullptr, 'W', DO_praat_close);
+			praat_addMenuCommand (U"Objects", U"Edit", U"Cut   ", nullptr, praat_UNHIDABLE | 'X' | praat_NO_API, PRAAT_cut);
+			praat_addMenuCommand (U"Objects", U"Edit", U"Copy   ", nullptr, praat_UNHIDABLE | 'C' | praat_NO_API, PRAAT_copy);
+			praat_addMenuCommand (U"Objects", U"Edit", U"Paste   ", nullptr, praat_UNHIDABLE | 'V' | praat_NO_API, PRAAT_paste);
+			praat_addMenuCommand (U"Objects", U"Window", U"Minimize   ", nullptr, praat_UNHIDABLE | praat_NO_API, PRAAT_minimize);
+			praat_addMenuCommand (U"Objects", U"Window", U"Zoom   ", nullptr, praat_UNHIDABLE | praat_NO_API, PRAAT_zoom);
+			praat_addMenuCommand (U"Objects", U"Window", U"Close   ", nullptr, 'W' | praat_NO_API, PRAAT_close);
 		#endif
 	#endif
 	#ifdef UNIX
-		praat_addMenuCommand (U"Objects", U"Praat", itemTitle_about.string, nullptr, praat_UNHIDABLE, DO_About);
+		praat_addMenuCommand (U"Objects", U"Praat", itemTitle_about.string, nullptr, praat_UNHIDABLE, WINDOW_About);
 	#endif
 	praat_addMenuCommand (U"Objects", U"Praat", U"-- script --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Praat", U"New Praat script", nullptr, 0, DO_praat_newScript);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Open Praat script...", nullptr, 0, DO_praat_openScript);
+	praat_addMenuCommand (U"Objects", U"Praat", U"New Praat script", nullptr, praat_NO_API, WINDOW_praat_newScript);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Open Praat script...", nullptr, praat_NO_API, WINDOW_praat_openScript);
 	praat_addMenuCommand (U"Objects", U"Praat", U"-- buttons --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Add menu command...", nullptr, praat_HIDDEN, DO_praat_addMenuCommand);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Hide menu command...", nullptr, praat_HIDDEN, DO_praat_hideMenuCommand);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Show menu command...", nullptr, praat_HIDDEN, DO_praat_showMenuCommand);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Add action command...", nullptr, praat_HIDDEN, DO_praat_addAction);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Hide action command...", nullptr, praat_HIDDEN, DO_praat_hideAction);
-	praat_addMenuCommand (U"Objects", U"Praat", U"Show action command...", nullptr, praat_HIDDEN, DO_praat_showAction);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Add menu command...", nullptr, praat_HIDDEN | praat_NO_API, PRAAT_addMenuCommand);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Hide menu command...", nullptr, praat_HIDDEN | praat_NO_API, PRAAT_hideMenuCommand);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Show menu command...", nullptr, praat_HIDDEN | praat_NO_API, PRAAT_showMenuCommand);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Add action command...", nullptr, praat_HIDDEN | praat_NO_API, PRAAT_addAction);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Hide action command...", nullptr, praat_HIDDEN | praat_NO_API, PRAAT_hideAction);
+	praat_addMenuCommand (U"Objects", U"Praat", U"Show action command...", nullptr, praat_HIDDEN | praat_NO_API, PRAAT_showAction);
 
 	GuiMenuItem menuItem = praat_addMenuCommand (U"Objects", U"Praat", U"Goodies", nullptr, praat_UNHIDABLE, nullptr);
 	goodiesMenu = menuItem ? menuItem -> d_menu : nullptr;
-	praat_addMenuCommand (U"Objects", U"Goodies", U"Calculator...", nullptr, 'U', DO_praat_calculator);
-	praat_addMenuCommand (U"Objects", U"Goodies", U"Report difference of two proportions...", nullptr, 0, DO_praat_reportDifferenceOfTwoProportions);
+	praat_addMenuCommand (U"Objects", U"Goodies", U"Calculator...", nullptr, 'U', STRING_praat_calculator);
+	praat_addMenuCommand (U"Objects", U"Goodies", U"Report difference of two proportions...", nullptr, 0, INFO_reportDifferenceOfTwoProportions);
 
 	menuItem = praat_addMenuCommand (U"Objects", U"Praat", U"Preferences", nullptr, praat_UNHIDABLE, nullptr);
 	preferencesMenu = menuItem ? menuItem -> d_menu : nullptr;
-	praat_addMenuCommand (U"Objects", U"Preferences", U"Buttons...", nullptr, praat_UNHIDABLE, DO_praat_editButtons);   /* Cannot be hidden. */
+	praat_addMenuCommand (U"Objects", U"Preferences", U"Buttons...", nullptr, praat_UNHIDABLE, WINDOW_praat_editButtons);
 	praat_addMenuCommand (U"Objects", U"Preferences", U"-- encoding prefs --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"Text reading preferences...", nullptr, 0, DO_TextInputEncodingSettings);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"Text writing preferences...", nullptr, 0, DO_TextOutputEncodingSettings);
-	praat_addMenuCommand (U"Objects", U"Preferences", U"CJK font style preferences...", nullptr, 0, DO_GraphicsCjkFontStyleSettings);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"Text reading preferences...", nullptr, 0, PREFS_TextInputEncodingSettings);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"Text writing preferences...", nullptr, 0, PREFS_TextOutputEncodingSettings);
+	praat_addMenuCommand (U"Objects", U"Preferences", U"CJK font style preferences...", nullptr, 0, PREFS_GraphicsCjkFontStyleSettings);
 
 	menuItem = praat_addMenuCommand (U"Objects", U"Praat", U"Technical", nullptr, praat_UNHIDABLE, nullptr);
 	technicalMenu = menuItem ? menuItem -> d_menu : nullptr;
-	praat_addMenuCommand (U"Objects", U"Technical", U"List readable types of objects", nullptr, 0, DO_praat_listReadableTypesOfObjects);
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report memory use", nullptr, 0, DO_praat_reportMemoryUse);
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report integer properties", nullptr, 0, DO_praat_reportIntegerProperties);
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report text properties", nullptr, 0, DO_praat_reportTextProperties);
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report system properties", nullptr, 0, DO_praat_reportSystemProperties);
-	praat_addMenuCommand (U"Objects", U"Technical", U"Report graphical properties", nullptr, 0, DO_praat_reportGraphicalProperties);
-	praat_addMenuCommand (U"Objects", U"Technical", U"Debug...", nullptr, 0, DO_praat_debug);
-
-	praat_addMenuCommand (U"Objects", U"Open", U"Read from file...", nullptr, praat_ATTRACTIVE + 'O', DO_Data_readFromFile);
-
-	praat_addAction1 (classDaata, 0, U"Save as text file...", nullptr, 0, DO_Data_writeToTextFile);
-	praat_addAction1 (classDaata, 0, U"Write to text file...", nullptr, praat_HIDDEN, DO_Data_writeToTextFile);
-	praat_addAction1 (classDaata, 0, U"Save as short text file...", nullptr, 0, DO_Data_writeToShortTextFile);
-	praat_addAction1 (classDaata, 0, U"Write to short text file...", nullptr, praat_HIDDEN, DO_Data_writeToShortTextFile);
-	praat_addAction1 (classDaata, 0, U"Save as binary file...", nullptr, 0, DO_Data_writeToBinaryFile);
-	praat_addAction1 (classDaata, 0, U"Write to binary file...", nullptr, praat_HIDDEN, DO_Data_writeToBinaryFile);
-
-	praat_addAction1 (classManPages, 1, U"Save to HTML directory...", nullptr, 0, DO_ManPages_saveToHtmlDirectory);
-	praat_addAction1 (classManPages, 1, U"View", nullptr, 0, DO_ManPages_view);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report memory use", nullptr, 0, INFO_reportMemoryUse);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report integer properties", nullptr, 0, INFO_reportIntegerProperties);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report text properties", nullptr, 0, INFO_reportTextProperties);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report system properties", nullptr, 0, INFO_reportSystemProperties);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Report graphical properties", nullptr, 0, INFO_reportGraphicalProperties);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Debug...", nullptr, 0, PRAAT_debug);
+	praat_addMenuCommand (U"Objects", U"Technical", U"-- api --", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Objects", U"Technical", U"List readable types of objects", nullptr, 0, INFO_listReadableTypesOfObjects);
+	praat_addMenuCommand (U"Objects", U"Technical", U"Create C interface...", nullptr, 0, INFO_praat_library_createC);
+
+	praat_addMenuCommand (U"Objects", U"Open", U"Read from file...", nullptr, praat_ATTRACTIVE | 'O', READMANY_Data_readFromFile);
+
+	praat_addAction1 (classDaata, 0, U"Save as text file...", nullptr, 0, SAVE_Data_writeToTextFile);
+	praat_addAction1 (classDaata, 0,   U"Write to text file...", nullptr, praat_DEPRECATED_2011, SAVE_Data_writeToTextFile);
+	praat_addAction1 (classDaata, 0, U"Save as short text file...", nullptr, 0, SAVE_Data_writeToShortTextFile);
+	praat_addAction1 (classDaata, 0,   U"Write to short text file...", nullptr, praat_DEPRECATED_2011, SAVE_Data_writeToShortTextFile);
+	praat_addAction1 (classDaata, 0, U"Save as binary file...", nullptr, 0, SAVE_Data_writeToBinaryFile);
+	praat_addAction1 (classDaata, 0,   U"Write to binary file...", nullptr, praat_DEPRECATED_2011, SAVE_Data_writeToBinaryFile);
+
+	praat_addAction1 (classManPages, 1, U"Save to HTML directory...", nullptr, 0, PRAAT_ManPages_saveToHtmlDirectory);
+	praat_addAction1 (classManPages, 1, U"View", nullptr, 0, WINDOW_ManPages_view);
 }
 
 void praat_addMenus2 () {
 	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"-- manual --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Go to manual page...", nullptr, 0, DO_GoToManualPage);
-	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Write manual to HTML directory...", nullptr, praat_HIDDEN, DO_WriteManualToHtmlDirectory);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Go to manual page...", nullptr, 0, HELP_GoToManualPage);
+	praat_addMenuCommand (U"Objects", U"ApplicationHelp", U"Write manual to HTML directory...", nullptr, praat_HIDDEN, HELP_WriteManualToHtmlDirectory);
 	praat_addMenuCommand (U"Objects", U"ApplicationHelp",
 		Melder_cat (U"Search ", praatP.title, U" manual..."),
-		nullptr, 'M', DO_SearchManual);
+		nullptr, 'M' | praat_NO_API, HELP_SearchManual);
 	#ifdef _WIN32
 		praat_addMenuCommand (U"Objects", U"Help", U"-- about --", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Objects", U"Help", itemTitle_about.string, nullptr, praat_UNHIDABLE, DO_About);
+		praat_addMenuCommand (U"Objects", U"Help", itemTitle_about.string, nullptr, praat_UNHIDABLE, WINDOW_About);
 	#endif
 
 	#if defined (macintosh) || defined (_WIN32)
diff --git a/sys/praat_picture.cpp b/sys/praat_picture.cpp
index e84fb3e..e6d4839 100644
--- a/sys/praat_picture.cpp
+++ b/sys/praat_picture.cpp
@@ -61,10 +61,10 @@ static void setFont (kGraphics_font font) {
 		updateFontMenu ();
 	}
 }
-DIRECT (Times)     { setFont (kGraphics_font_TIMES);     } END
-DIRECT (Helvetica) { setFont (kGraphics_font_HELVETICA); } END
-DIRECT (Palatino)  { setFont (kGraphics_font_PALATINO);  } END
-DIRECT (Courier)   { setFont (kGraphics_font_COURIER);   } END
+DIRECT (GRAPHICS_Times)     { setFont (kGraphics_font_TIMES);     END }
+DIRECT (GRAPHICS_Helvetica) { setFont (kGraphics_font_HELVETICA); END }
+DIRECT (GRAPHICS_Palatino)  { setFont (kGraphics_font_PALATINO);  END }
+DIRECT (GRAPHICS_Courier)   { setFont (kGraphics_font_COURIER);   END }
 
 /***** "Font" MENU: size part *****/
 
@@ -90,18 +90,18 @@ static void setFontSize (int fontSize) {
 	}
 }
 
-DIRECT (10) { setFontSize (10); } END
-DIRECT (12) { setFontSize (12); } END
-DIRECT (14) { setFontSize (14); } END
-DIRECT (18) { setFontSize (18); } END
-DIRECT (24) { setFontSize (24); } END
-FORM (Font_size, U"Praat picture: Font size", U"Font menu") {
-	NATURAL (U"Font size (points)", U"10")
-OK2
+DIRECT (GRAPHICS_10) { setFontSize (10); END }
+DIRECT (GRAPHICS_12) { setFontSize (12); END }
+DIRECT (GRAPHICS_14) { setFontSize (14); END }
+DIRECT (GRAPHICS_18) { setFontSize (18); END }
+DIRECT (GRAPHICS_24) { setFontSize (24); END }
+FORM (GRAPHICS_Font_size, U"Praat picture: Font size", U"Font menu") {
+	NATURAL4 (fontSize, U"Font size (points)", U"10")
+OK
 	SET_INTEGER (U"Font size", (long) theCurrentPraatPicture -> fontSize);
 DO
-	setFontSize (GET_INTEGER (U"Font size"));
-END2 }
+	setFontSize (fontSize);
+END }
 
 /*static void setFontSize_keepInnerViewport (int fontSize) {
 	double xmargin = praat_size * 4.2 / 72.0, ymargin = praat_size * 2.8 / 72.0;
@@ -136,7 +136,7 @@ static void updateViewportMenu () {
 	}
 }
 
-DIRECT (MouseSelectsInnerViewport) {
+DIRECT (GRAPHICS_MouseSelectsInnerViewport) {
 	if (theCurrentPraatPicture != & theForegroundPraatPicture)
 		Melder_throw (U"Mouse commands are not available inside pictures.");
 	{// scope
@@ -144,9 +144,9 @@ DIRECT (MouseSelectsInnerViewport) {
 		Picture_setMouseSelectsInnerViewport (praat_picture.get(), praat_mouseSelectsInnerViewport = true);
 	}
 	updateViewportMenu ();
-} END
+END }
 
-DIRECT (MouseSelectsOuterViewport) {
+DIRECT (GRAPHICS_MouseSelectsOuterViewport) {
 	if (theCurrentPraatPicture != & theForegroundPraatPicture)
 		Melder_throw (U"Mouse commands are not available inside pictures.");
 	{// scope
@@ -154,18 +154,18 @@ DIRECT (MouseSelectsOuterViewport) {
 		Picture_setMouseSelectsInnerViewport (praat_picture.get(), praat_mouseSelectsInnerViewport = false);
 	}
 	updateViewportMenu ();
-} END
+END }
 
-FORM (SelectInnerViewport, U"Praat picture: Select inner viewport", U"Select inner viewport...") {
+FORM (GRAPHICS_SelectInnerViewport, U"Praat picture: Select inner viewport", U"Select inner viewport...") {
 	LABEL (U"", U"The viewport is the selected rectangle in the Picture window.")
 	LABEL (U"", U"It is where your next drawing will appear.")
 	LABEL (U"", U"The rectangle you select here will not include the margins.")
 	LABEL (U"", U"")
-	REAL (U"left Horizontal range (inches)", U"0.0")
-	REAL (U"right Horizontal range (inches)", U"6.0")
-	REAL (U"left Vertical range (inches)", U"0.0")
-	REAL (U"right Vertical range (inches)", U"6.0")
-OK2
+	REAL4 (left, U"left Horizontal range (inches)", U"0.0")
+	REAL4 (right, U"right Horizontal range (inches)", U"6.0")
+	REAL4 (top, U"left Vertical range (inches)", U"0.0")
+	REAL4 (bottom, U"right Vertical range (inches)", U"6.0")
+OK
 	double xmargin = theCurrentPraatPicture -> fontSize * 4.2 / 72.0, ymargin = theCurrentPraatPicture -> fontSize * 2.8 / 72.0;
 	if (ymargin > 0.4 * (theCurrentPraatPicture -> y2NDC - theCurrentPraatPicture -> y1NDC))
 		ymargin = 0.4 * (theCurrentPraatPicture -> y2NDC - theCurrentPraatPicture -> y1NDC);
@@ -177,8 +177,6 @@ OK2
 	SET_REAL (U"right Vertical range", 12 - theCurrentPraatPicture -> y1NDC - ymargin)
 DO
 	//if (theCurrentPraatObjects != & theForegroundPraatObjects) Melder_throw (U"Viewport commands are not available inside manuals.");
-	double left = GET_REAL (U"left Horizontal range"), right = GET_REAL (U"right Horizontal range");
-	double top = GET_REAL (U"left Vertical range"), bottom = GET_REAL (U"right Vertical range");
 	double xmargin = theCurrentPraatPicture -> fontSize * 4.2 / 72.0, ymargin = theCurrentPraatPicture -> fontSize * 2.8 / 72.0;
 	trace (U"1: xmargin ", xmargin, U" ymargin ", ymargin);
 	if (theCurrentPraatPicture != & theForegroundPraatPicture) {
@@ -227,26 +225,24 @@ DO
 		U" y1NDC ", theCurrentPraatPicture -> y1NDC,
 		U" y2NDC ", theCurrentPraatPicture -> y2NDC
 	);
-END2 }
+END }
 
-FORM (SelectOuterViewport, U"Praat picture: Select outer viewport", U"Select outer viewport...") {
+FORM (GRAPHICS_SelectOuterViewport, U"Praat picture: Select outer viewport", U"Select outer viewport...") {
 	LABEL (U"", U"The viewport is the selected rectangle in the Picture window.")
 	LABEL (U"", U"It is where your next drawing will appear.")
 	LABEL (U"", U"The rectangle you select here will include the margins.")
 	LABEL (U"", U"")
-	REAL (U"left Horizontal range (inches)", U"0.0")
-	REAL (U"right Horizontal range (inches)", U"6.0")
-	REAL (U"left Vertical range (inches)", U"0.0")
-	REAL (U"right Vertical range (inches)", U"6.0")
-OK2
+	REAL4 (left, U"left Horizontal range (inches)", U"0.0")
+	REAL4 (right, U"right Horizontal range (inches)", U"6.0")
+	REAL4 (top, U"left Vertical range (inches)", U"0.0")
+	REAL4 (bottom, U"right Vertical range (inches)", U"6.0")
+OK
 	SET_REAL (U"left Horizontal range", theCurrentPraatPicture -> x1NDC);
 	SET_REAL (U"right Horizontal range", theCurrentPraatPicture -> x2NDC);
 	SET_REAL (U"left Vertical range", 12 - theCurrentPraatPicture -> y2NDC);
 	SET_REAL (U"right Vertical range", 12 - theCurrentPraatPicture -> y1NDC);
 DO
 	//if (theCurrentPraatObjects != & theForegroundPraatObjects) Melder_throw (U"Viewport commands are not available inside manuals.");
-	double left = GET_REAL (U"left Horizontal range"), right = GET_REAL (U"right Horizontal range");
-	double top = GET_REAL (U"left Vertical range"), bottom = GET_REAL (U"right Vertical range");
 	if (left == right) {
 		Melder_throw (U"The left and right edges of the viewport cannot be equal.\nPlease change the horizontal range.");
 	}
@@ -274,34 +270,32 @@ DO
 		theCurrentPraatPicture -> y1NDC = bottom;
 		theCurrentPraatPicture -> y2NDC = top;
 	}
-END2 }
+END }
 
-FORM (ViewportText, U"Praat picture: Viewport text", U"Viewport text...") {
-	RADIO (U"Horizontal alignment", 2)
+FORM (GRAPHICS_ViewportText, U"Praat picture: Viewport text", U"Viewport text...") {
+	RADIO4x (horizontalAlignment, U"Horizontal alignment", 2, 0)
 		RADIOBUTTON (U"Left")
 		RADIOBUTTON (U"Centre")
 		RADIOBUTTON (U"Right")
-	RADIO (U"Vertical alignment", 2)
+	RADIO4x (verticalAlignment, U"Vertical alignment", 2, 0)
 		RADIOBUTTON (U"Bottom")
 		RADIOBUTTON (U"Half")
 		RADIOBUTTON (U"Top")
-	REAL (U"Rotation (degrees)", U"0")
-	TEXTFIELD (U"text", U"")
-OK2
+	REAL4 (rotation, U"Rotation (degrees)", U"0")
+	TEXTFIELD4 (text, U"text", U"")
+OK
 DO
 	double x1WC, x2WC, y1WC, y2WC;
-	int hor = GET_INTEGER (U"Horizontal alignment") - 1;
-	int vert = GET_INTEGER (U"Vertical alignment") - 1;
 	autoPraatPicture picture;
 	Graphics_inqWindow (GRAPHICS, & x1WC, & x2WC, & y1WC, & y2WC);
 	Graphics_setWindow (GRAPHICS, 0, 1, 0, 1);
-	Graphics_setTextAlignment (GRAPHICS, hor, vert);
-	Graphics_setTextRotation (GRAPHICS, GET_REAL (U"Rotation"));
-	Graphics_text (GRAPHICS, hor == 0 ? 0 : hor == 1 ? 0.5 : 1,
-		vert == 0 ? 0 : vert == 1 ? 0.5 : 1, GET_STRING (U"text"));
+	Graphics_setTextAlignment (GRAPHICS, horizontalAlignment, verticalAlignment);
+	Graphics_setTextRotation (GRAPHICS, rotation);
+	Graphics_text (GRAPHICS, horizontalAlignment == 0 ? 0.0 : horizontalAlignment == 1 ? 0.5 : 1.0,
+		verticalAlignment == 0 ? 0.0 : verticalAlignment == 1 ? 0.5 : 1.0, text);
 	Graphics_setTextRotation (GRAPHICS, 0.0);
 	Graphics_setWindow (GRAPHICS, x1WC, x2WC, y1WC, y2WC);
-END2 }
+END }
 
 /***** "Pen" MENU *****/
 
@@ -345,51 +339,48 @@ static void setLineType (int lineType) {
 		updatePenMenu ();
 	}
 }
-DIRECT (Solid_line)         { setLineType (Graphics_DRAWN);         } END
-DIRECT (Dotted_line)        { setLineType (Graphics_DOTTED);        } END
-DIRECT (Dashed_line)        { setLineType (Graphics_DASHED);        } END
-DIRECT (Dashed_dotted_line) { setLineType (Graphics_DASHED_DOTTED); } END
-
-FORM (Line_width, U"Praat picture: Line width", 0) {
-	POSITIVE (U"Line width", U"1.0")
-OK2
+DIRECT (GRAPHICS_Solid_line)         { setLineType (Graphics_DRAWN);         END }
+DIRECT (GRAPHICS_Dotted_line)        { setLineType (Graphics_DOTTED);        END }
+DIRECT (GRAPHICS_Dashed_line)        { setLineType (Graphics_DASHED);        END }
+DIRECT (GRAPHICS_Dashed_dotted_line) { setLineType (Graphics_DASHED_DOTTED); END }
+
+FORM (GRAPHICS_Line_width, U"Praat picture: Line width", nullptr) {
+	POSITIVE4 (lineWidth, U"Line width", U"1.0")
+OK
 	SET_REAL (U"Line width", theCurrentPraatPicture -> lineWidth);
 DO
-	double lineWidth = GET_REAL (U"Line width");
 	{// scope
 		autoPraatPicture picture;
 		Graphics_setLineWidth (GRAPHICS, lineWidth);
 	}
 	theCurrentPraatPicture -> lineWidth = lineWidth;
-END2 }
+END }
 
-FORM (Arrow_size, U"Praat picture: Arrow size", 0) {
-	POSITIVE (U"Arrow size", U"1.0")
-OK2
+FORM (GRAPHICS_Arrow_size, U"Praat picture: Arrow size", nullptr) {
+	POSITIVE4 (arrowSize, U"Arrow size", U"1.0")
+OK
 	SET_REAL (U"Arrow size", theCurrentPraatPicture -> arrowSize);
 DO
-	double arrowSize = GET_REAL (U"Arrow size");
 	{// scope
 		autoPraatPicture picture;
 		Graphics_setArrowSize (GRAPHICS, arrowSize);
 	}
 	theCurrentPraatPicture -> arrowSize = arrowSize;
-END2 }
+END }
 
-FORM (Speckle_size, U"Praat picture: Speckle size", 0) {
+FORM (GRAPHICS_Speckle_size, U"Praat picture: Speckle size", nullptr) {
 	LABEL (U"", U"Here you determine the diameter (in millimetres)")
 	LABEL (U"", U"of the dots that are drawn by \"speckle\" commands.")
-	POSITIVE (U"Speckle size (mm)", U"1.0")
-OK2
+	POSITIVE4 (speckleSize, U"Speckle size (mm)", U"1.0")
+OK
 	SET_REAL (U"Speckle size", theCurrentPraatPicture -> speckleSize);
 DO
-	double speckleSize = GET_REAL (U"Speckle size");
 	{// scope
 		autoPraatPicture picture;
 		Graphics_setSpeckleSize (GRAPHICS, speckleSize);
 	}
 	theCurrentPraatPicture -> speckleSize = speckleSize;
-END2 }
+END }
 
 static void setColour (Graphics_Colour colour) {
 	{// scope
@@ -401,27 +392,27 @@ static void setColour (Graphics_Colour colour) {
 		updatePenMenu ();
 	}
 }
-DIRECT (Black)   { setColour (Graphics_BLACK);   } END
-DIRECT (White)   { setColour (Graphics_WHITE);   } END
-DIRECT (Red)     { setColour (Graphics_RED);     } END
-DIRECT (Green)   { setColour (Graphics_GREEN);   } END
-DIRECT (Blue)    { setColour (Graphics_BLUE);    } END
-DIRECT (Yellow)  { setColour (Graphics_YELLOW);  } END
-DIRECT (Cyan)    { setColour (Graphics_CYAN);    } END
-DIRECT (Magenta) { setColour (Graphics_MAGENTA); } END
-DIRECT (Maroon)  { setColour (Graphics_MAROON);  } END
-DIRECT (Lime)    { setColour (Graphics_LIME);    } END
-DIRECT (Navy)    { setColour (Graphics_NAVY);    } END
-DIRECT (Teal)    { setColour (Graphics_TEAL);    } END
-DIRECT (Purple)  { setColour (Graphics_PURPLE);  } END
-DIRECT (Olive)   { setColour (Graphics_OLIVE);   } END
-DIRECT (Pink)    { setColour (Graphics_PINK);    } END
-DIRECT (Silver)  { setColour (Graphics_SILVER);  } END
-DIRECT (Grey)    { setColour (Graphics_GREY);    } END
-
-FORM (Colour, U"Praat picture: Colour", 0) {
+DIRECT (GRAPHICS_Black)   { setColour (Graphics_BLACK);   END }
+DIRECT (GRAPHICS_White)   { setColour (Graphics_WHITE);   END }
+DIRECT (GRAPHICS_Red)     { setColour (Graphics_RED);     END }
+DIRECT (GRAPHICS_Green)   { setColour (Graphics_GREEN);   END }
+DIRECT (GRAPHICS_Blue)    { setColour (Graphics_BLUE);    END }
+DIRECT (GRAPHICS_Yellow)  { setColour (Graphics_YELLOW);  END }
+DIRECT (GRAPHICS_Cyan)    { setColour (Graphics_CYAN);    END }
+DIRECT (GRAPHICS_Magenta) { setColour (Graphics_MAGENTA); END }
+DIRECT (GRAPHICS_Maroon)  { setColour (Graphics_MAROON);  END }
+DIRECT (GRAPHICS_Lime)    { setColour (Graphics_LIME);    END }
+DIRECT (GRAPHICS_Navy)    { setColour (Graphics_NAVY);    END }
+DIRECT (GRAPHICS_Teal)    { setColour (Graphics_TEAL);    END }
+DIRECT (GRAPHICS_Purple)  { setColour (Graphics_PURPLE);  END }
+DIRECT (GRAPHICS_Olive)   { setColour (Graphics_OLIVE);   END }
+DIRECT (GRAPHICS_Pink)    { setColour (Graphics_PINK);    END }
+DIRECT (GRAPHICS_Silver)  { setColour (Graphics_SILVER);  END }
+DIRECT (GRAPHICS_Grey)    { setColour (Graphics_GREY);    END }
+
+FORM (GRAPHICS_Colour, U"Praat picture: Colour", nullptr) {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.0")
-OK2
+OK
 DO
 	Graphics_Colour colour = GET_COLOUR (U"Colour");
 	{// scope
@@ -432,21 +423,21 @@ DO
 	if (theCurrentPraatPicture == & theForegroundPraatPicture) {
 		updatePenMenu ();
 	}
-END2 }
+END }
 
 /***** "File" MENU *****/
 
-FORM_READ2 (Picture_readFromPraatPictureFile, U"Read picture from praat picture file", 0, false) {
+FORM_READ (GRAPHICS_Picture_readFromPraatPictureFile, U"Read picture from praat picture file", 0, false) {
 	Picture_readFromPraatPictureFile (praat_picture.get(), file);
-END2 }
+END }
 
-static void DO_Picture_writeToEpsFile (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToEpsFile (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as EPS file",
-		DO_Picture_writeToEpsFile, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToEpsFile, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.eps");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -454,17 +445,17 @@ static void DO_Picture_writeToEpsFile (UiForm sendingForm, int /* narg */, Stack
 		Picture_writeToEpsFile (praat_picture.get(), file, true, false);
 	}
 }
-/*FORM_WRITE (Picture_writeToEpsFile, U"Save picture as Encapsulated PostScript file", 0, U"praat.eps")
+/*FORM_SAVE (GRAPHICS_Picture_writeToEpsFile, U"Save picture as Encapsulated PostScript file", 0, U"praat.eps")
 	if (! Picture_writeToEpsFile (praat_picture, fileName, true, false)) return 0;
 END*/
 
-static void DO_Picture_writeToFontlessEpsFile_xipa (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToFontlessEpsFile_xipa (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as fontless EPS file",
-		DO_Picture_writeToFontlessEpsFile_xipa, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToFontlessEpsFile_xipa, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.eps");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -473,13 +464,13 @@ static void DO_Picture_writeToFontlessEpsFile_xipa (UiForm sendingForm, int /* n
 	}
 }
 
-static void DO_Picture_writeToFontlessEpsFile_silipa (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToFontlessEpsFile_silipa (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as fontless EPS file",
-		DO_Picture_writeToFontlessEpsFile_silipa, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToFontlessEpsFile_silipa, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.eps");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -488,13 +479,13 @@ static void DO_Picture_writeToFontlessEpsFile_silipa (UiForm sendingForm, int /*
 	}
 }
 
-static void DO_Picture_writeToPdfFile (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToPdfFile (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as PDF file",
-		DO_Picture_writeToPdfFile, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToPdfFile, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.pdf");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -513,13 +504,13 @@ static void DO_Picture_writeToPdfFile (UiForm sendingForm, int /* narg */, Stack
 	}
 }
 
-static void DO_Picture_writeToPngFile_300 (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToPngFile_300 (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as PNG file",
-		DO_Picture_writeToPngFile_300, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToPngFile_300, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.png");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -537,13 +528,13 @@ static void DO_Picture_writeToPngFile_300 (UiForm sendingForm, int /* narg */, S
 	}
 }
 
-static void DO_Picture_writeToPngFile_600 (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToPngFile_600 (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as PNG file",
-		DO_Picture_writeToPngFile_600, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToPngFile_600, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.png");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -561,13 +552,13 @@ static void DO_Picture_writeToPngFile_600 (UiForm sendingForm, int /* narg */, S
 	}
 }
 
-static void DO_Picture_writeToPraatPictureFile (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+static void GRAPHICS_Picture_writeToPraatPictureFile (UiForm sendingForm, int narg, Stackel args, const char32 *sendingString,
 	Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 {
 	static UiForm dia;
 	if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as Praat picture file",
-		DO_Picture_writeToPraatPictureFile, nullptr, invokingButtonTitle, nullptr);
-	if (! sendingForm && ! args && ! sendingString) {
+		GRAPHICS_Picture_writeToPraatPictureFile, nullptr, invokingButtonTitle, nullptr);
+	if (narg < 0) UiForm_info (dia, narg); else if (! sendingForm && ! args && ! sendingString) {
 		UiOutfile_do (dia, U"praat.prapic");
 	} else { MelderFile file; structMelderFile file2 { 0 };
 		if (! args && ! sendingString) file = UiFile_getFile (dia);
@@ -577,26 +568,26 @@ static void DO_Picture_writeToPraatPictureFile (UiForm sendingForm, int /* narg
 }
 
 #ifdef macintosh
-DIRECT (Page_setup) {
+DIRECT (GRAPHICS_Page_setup) {
 	Printer_pageSetup ();
-} END
+END }
 #endif
 
-DIRECT (PostScript_settings) {
+DIRECT (GRAPHICS_PostScript_settings) {
 	Printer_postScriptSettings ();
-} END
+END }
 
-DIRECT (Print) {
+DIRECT (GRAPHICS_Print) {
 	Picture_print (praat_picture.get());
-} END
+END }
 
 #ifdef _WIN32
-	static void DO_Picture_writeToWindowsMetafile (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
+	static void GRAPHICS_Picture_writeToWindowsMetafile (UiForm sendingForm, int /* narg */, Stackel args, const char32 *sendingString,
 		Interpreter /* interpreter */, const char32 *invokingButtonTitle, bool /* modified */, void *)
 	{
 		static UiForm dia;
 		if (! dia) dia = UiOutfile_create (theCurrentPraatApplication -> topShell, U"Save as Windows metafile",
-			DO_Picture_writeToWindowsMetafile, nullptr, invokingButtonTitle, nullptr);
+			GRAPHICS_Picture_writeToWindowsMetafile, nullptr, invokingButtonTitle, nullptr);
 		if (! sendingForm && ! args && ! sendingString) {
 			UiOutfile_do (dia, U"praat.emf");
 		} else { MelderFile file; structMelderFile file2 { 0 };
@@ -608,131 +599,134 @@ DIRECT (Print) {
 #endif
 
 #if defined (_WIN32) || defined (macintosh)
-	DIRECT (Copy_picture_to_clipboard) {
+	DIRECT (GRAPHICS_Copy_picture_to_clipboard) {
 		Picture_copyToClipboard (praat_picture.get());
-	} END
+	END }
 #endif
 
 /***** "Edit" MENU *****/
 
-DIRECT (Undo) {
+DIRECT (GRAPHICS_Undo) {
 	Graphics_undoGroup (GRAPHICS);
 	if (theCurrentPraatPicture != & theForegroundPraatPicture) {
 		Graphics_play (GRAPHICS, GRAPHICS);
 	}
 	Graphics_updateWs (GRAPHICS);
-} END
+END }
 
-DIRECT (Erase_all) {
+DIRECT (GRAPHICS_Erase_all) {
 	if (theCurrentPraatPicture == & theForegroundPraatPicture) {
 		Picture_erase (praat_picture.get());   // this kills the recording
 	} else {
 		Graphics_clearRecording (GRAPHICS);
 		Graphics_clearWs (GRAPHICS);
 	}
-} END
+END }
 
 /***** "World" MENU *****/
 
-FORM (Text, U"Praat picture: Text", U"Text...") {
-	REAL (U"Horizontal position", U"0.0")
-	OPTIONMENU (U"Horizontal alignment", 2)
+FORM (GRAPHICS_Text, U"Praat picture: Text", U"Text...") {
+	REAL4 (horizontalPosition, U"Horizontal position", U"0.0")
+	OPTIONMENU4x (horizontalAlignment, U"Horizontal alignment", 2, 0)
 		OPTION (U"Left")
 		OPTION (U"Centre")
 		OPTION (U"Right")
-	REAL (U"Vertical position", U"0.0")
-	OPTIONMENU (U"Vertical alignment", 2)
+	REAL4 (verticalPosition, U"Vertical position", U"0.0")
+	OPTIONMENU4x (verticalAlignment, U"Vertical alignment", 2, 0)
 		OPTION (U"Bottom")
 		OPTION (U"Half")
 		OPTION (U"Top")
 	LABEL (U"", U"Text:")
-	TEXTFIELD (U"text", U"")
-OK2
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setTextAlignment (GRAPHICS,
-		GET_INTEGER (U"Horizontal alignment") - 1, GET_INTEGER (U"Vertical alignment") - 1);
-	Graphics_setInner (GRAPHICS);
-	Graphics_text (GRAPHICS, GET_REAL (U"Horizontal position"),
-		GET_REAL (U"Vertical position"), GET_STRING (U"text"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
-
-FORM (Text_special, U"Praat picture: Text special", 0) {
-	REAL (U"Horizontal position", U"0.0")
-	OPTIONMENU (U"Horizontal alignment", 2)
-		OPTION (U"left")
-		OPTION (U"centre")
-		OPTION (U"right")
-	REAL (U"Vertical position", U"0.0")
-	OPTIONMENU (U"Vertical alignment", 2)
-		OPTION (U"bottom")
-		OPTION (U"half")
-		OPTION (U"top")
-	OPTIONMENU_ENUM (U"Font", kGraphics_font, DEFAULT)
-	NATURAL (U"Font size", U"10")
-	SENTENCE (U"Rotation (degrees or dx;dy)", U"0")
+	GRAPHICS_NONE
+		Graphics_setTextAlignment (GRAPHICS, horizontalAlignment, verticalAlignment);
+		Graphics_setInner (GRAPHICS);
+		Graphics_text (GRAPHICS, horizontalPosition, verticalPosition, text);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_TextSpecial, U"Praat picture: Text special", nullptr) {
+	REAL4 (horizontalPosition, U"Horizontal position", U"0.0")
+	OPTIONMENU4x (horizontalAlignment, U"Horizontal alignment", 2, 0)
+		OPTION (U"Left")
+		OPTION (U"Centre")
+		OPTION (U"Right")
+	REAL4 (verticalPosition, U"Vertical position", U"0.0")
+	OPTIONMENU4x (verticalAlignment, U"Vertical alignment", 2, 0)
+		OPTION (U"Bottom")
+		OPTION (U"Half")
+		OPTION (U"Top")
+	OPTIONMENU_ENUM4 (font, U"Font", kGraphics_font, DEFAULT)
+	NATURAL4 (fontSize, U"Font size", U"10")
+	SENTENCE4 (rotation, U"Rotation (degrees or dx;dy)", U"0")
 	LABEL (U"", U"Text:")
-	TEXTFIELD (U"text", U"")
-OK2
+	TEXTFIELD4 (text, U"text", U"")
+OK
 DO
 	kGraphics_font currentFont = Graphics_inqFont (GRAPHICS);
 	int currentSize = Graphics_inqFontSize (GRAPHICS);
-	autoPraatPicture picture;
-	Graphics_setTextAlignment (GRAPHICS, GET_INTEGER (U"Horizontal alignment") - 1, GET_INTEGER (U"Vertical alignment") - 1);
-	Graphics_setInner (GRAPHICS);
-	Graphics_setFont (GRAPHICS, GET_ENUM (kGraphics_font, U"Font"));
-	Graphics_setFontSize (GRAPHICS, GET_INTEGER (U"Font size"));
-	char32 *rotation = GET_STRING (U"Rotation"), *semicolon;
-	if (!! (semicolon = str32chr (rotation, ';')))
-		Graphics_setTextRotation_vector (GRAPHICS, Melder_atof (rotation), Melder_atof (semicolon + 1));
-	else
-		Graphics_setTextRotation (GRAPHICS, Melder_atof (rotation));
-	Graphics_text (GRAPHICS, GET_REAL (U"Horizontal position"), GET_REAL (U"Vertical position"), GET_STRING (U"text"));
-	Graphics_setFont (GRAPHICS, currentFont);
-	Graphics_setFontSize (GRAPHICS, currentSize);
-	Graphics_setTextRotation (GRAPHICS, 0.0);
-	Graphics_unsetInner (GRAPHICS);
-END2 }
-
-static void dia_line (UiForm dia) {
-	REAL (U"From x", U"0.0")
-	REAL (U"From y", U"0.0")
-	REAL (U"To x", U"1.0")
-	REAL (U"To y", U"1.0")
+	GRAPHICS_NONE
+		Graphics_setTextAlignment (GRAPHICS, horizontalAlignment, verticalAlignment);
+		Graphics_setInner (GRAPHICS);
+		Graphics_setFont (GRAPHICS, (kGraphics_font) font);
+		Graphics_setFontSize (GRAPHICS, fontSize);
+		const char32 *semicolon;
+		if (!! (semicolon = str32chr (rotation, ';')))
+			Graphics_setTextRotation_vector (GRAPHICS, Melder_atof (rotation), Melder_atof (semicolon + 1));
+		else
+			Graphics_setTextRotation (GRAPHICS, Melder_atof (rotation));
+		Graphics_text (GRAPHICS, horizontalPosition, verticalPosition, text);
+		Graphics_setFont (GRAPHICS, currentFont);
+		Graphics_setFontSize (GRAPHICS, currentSize);
+		Graphics_setTextRotation (GRAPHICS, 0.0);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
 }
-FORM (DrawLine, U"Praat picture: Draw line", 0) {
-	dia_line (dia);
-OK2
+
+FORM (GRAPHICS_DrawLine, U"Praat picture: Draw line", nullptr) {
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_line (GRAPHICS, GET_REAL (U"From x"), GET_REAL (U"From y"), GET_REAL (U"To x"),
-		GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_line (GRAPHICS, fromX, fromY, toX, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (DrawArrow, U"Praat picture: Draw arrow", 0) {
-	dia_line (dia);
-OK2
+FORM (GRAPHICS_DrawArrow, U"Praat picture: Draw arrow", nullptr) {
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_arrow (GRAPHICS, GET_REAL (U"From x"), GET_REAL (U"From y"), GET_REAL (U"To x"),
-		GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_arrow (GRAPHICS, fromX, fromY, toX, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (DrawDoubleArrow, U"Praat picture: Draw double arrow", 0) {
-	dia_line (dia);
-OK2
+FORM (GRAPHICS_DrawDoubleArrow, U"Praat picture: Draw double arrow", nullptr) {
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_doubleArrow (GRAPHICS, GET_REAL (U"From x"), GET_REAL (U"From y"), GET_REAL (U"To x"),
-		GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_doubleArrow (GRAPHICS, fromX, fromY, toX, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
 Thing_define (PraatPictureFunction, Daata) {
 	// new data:
@@ -748,205 +742,225 @@ Thing_define (PraatPictureFunction, Daata) {
 };
 Thing_implement (PraatPictureFunction, Daata, 0);
 
-FORM (DrawFunction, U"Praat picture: Draw function", 0) {
+FORM (GRAPHICS_DrawFunction, U"Praat picture: Draw function", nullptr) {
 	LABEL (U"", U"This command assumes that the x and y axes")
 	LABEL (U"", U"have been set by a Draw command or by \"Axes...\".")
-	REAL (U"From x", U"0.0")
-	REAL (U"To x", U"0.0 (= all)")
-	NATURAL (U"Number of horizontal steps", U"1000")
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"0.0 (= all)")
+	NATURAL4 (numberOfHorizontalSteps, U"Number of horizontal steps", U"1000")
 	LABEL (U"", U"Formula:")
-	TEXTFIELD (U"formula", U"x^2 - x^4")
-OK2
+	TEXTFIELD4 (formula, U"formula", U"x^2 - x^4")
+	OK
 DO
 	double x1WC, x2WC, y1WC, y2WC;
-	double fromX = GET_REAL (U"From x"), toX = GET_REAL (U"To x");
-	long n = GET_INTEGER (U"Number of horizontal steps");
-	char32 *formula = GET_STRING (U"formula");
-	if (n < 2) return;
+	if (numberOfHorizontalSteps < 2) return;
 	Graphics_inqWindow (GRAPHICS, & x1WC, & x2WC, & y1WC, & y2WC);
 	if (fromX == toX) fromX = x1WC, toX = x2WC;
-	autoNUMvector <double> y (1, n);
+	autoNUMvector <double> y (1, numberOfHorizontalSteps);
 	autoPraatPictureFunction function = Thing_new (PraatPictureFunction);
 	function -> xmin = x1WC;
 	function -> xmax = x2WC;
-	function -> nx = n;
+	function -> nx = numberOfHorizontalSteps;
 	function -> x1 = fromX;
-	function -> dx = (toX - fromX) / (n - 1);
+	function -> dx = (toX - fromX) / (numberOfHorizontalSteps - 1);
 	Formula_compile (interpreter, function.get(), formula, kFormula_EXPRESSION_TYPE_NUMERIC, true);
-	for (long i = 1; i <= n; i ++) {
+	for (long i = 1; i <= numberOfHorizontalSteps; i ++) {
 		struct Formula_Result result;
 		Formula_run (1, i, & result);
 		y [i] = result. result.numericResult;
 	}
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_function (GRAPHICS, y.peek(), 1, n, fromX, toX);
-	Graphics_unsetInner (GRAPHICS);
-END2 }
-
-static void dia_rectangle (UiForm dia) {
-	REAL (U"From x", U"0.0")
-	REAL (U"To x", U"1.0")
-	REAL (U"From y", U"0.0")
-	REAL (U"To y", U"1.0")
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_function (GRAPHICS, y.peek(), 1, numberOfHorizontalSteps, fromX, toX);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
 }
-FORM (DrawRectangle, U"Praat picture: Draw rectangle", 0) {
-	dia_rectangle (dia);
-OK2
+
+FORM (GRAPHICS_DrawRectangle, U"Praat picture: Draw rectangle", nullptr) {
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_rectangle (GRAPHICS,
-		GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_rectangle (GRAPHICS, fromX, toX, fromY, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (PaintRectangle, U"Praat picture: Paint rectangle", 0) {
+FORM (GRAPHICS_PaintRectangle, U"Praat picture: Paint rectangle", nullptr) {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	dia_rectangle (dia);
-OK2
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
-	Graphics_fillRectangle (GRAPHICS, GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
+		Graphics_fillRectangle (GRAPHICS, fromX, toX, fromY, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (DrawRoundedRectangle, U"Praat picture: Draw rounded rectangle", 0) {
-	dia_rectangle (dia);
-	POSITIVE (U"Radius (mm)", U"3.0")
-OK2
+FORM (GRAPHICS_DrawRoundedRectangle, U"Praat picture: Draw rounded rectangle", nullptr) {
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	POSITIVE4 (radius, U"Radius (mm)", U"3.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_roundedRectangle (GRAPHICS,
-		GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"), GET_REAL (U"Radius"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_roundedRectangle (GRAPHICS, fromX, toX, fromY, toY, radius);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (PaintRoundedRectangle, U"Praat picture: Paint rounded rectangle", 0) {
+FORM (GRAPHICS_PaintRoundedRectangle, U"Praat picture: Paint rounded rectangle", nullptr) {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	dia_rectangle (dia);
-	POSITIVE (U"Radius (mm)", U"3.0")
-OK2
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	POSITIVE4 (radius, U"Radius (mm)", U"3.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
-	Graphics_fillRoundedRectangle (GRAPHICS, GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"), GET_REAL (U"Radius"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
-
-FORM (DrawArc, U"Praat picture: Draw arc", 0) {
-	REAL (U"Centre x", U"0.0")
-	REAL (U"Centre y", U"0.0")
-	POSITIVE (U"Radius (along x)", U"1.0")
-	REAL (U"From angle (degrees)", U"0.0")
-	REAL (U"To angle (degrees)", U"90.0")
-OK2
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
+		Graphics_fillRoundedRectangle (GRAPHICS, fromX, toX, fromY, toY, radius);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_DrawArc, U"Praat picture: Draw arc", nullptr) {
+	REAL4 (centreX, U"Centre x", U"0.0")
+	REAL4 (centreY, U"Centre y", U"0.0")
+	POSITIVE4 (radius, U"Radius (along x)", U"1.0")
+	REAL4 (fromAngle, U"From angle (degrees)", U"0.0")
+	REAL4 (toAngle, U"To angle (degrees)", U"90.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_arc (GRAPHICS, GET_REAL (U"Centre x"), GET_REAL (U"Centre y"), GET_REAL (U"Radius"),
-		GET_REAL (U"From angle"), GET_REAL (U"To angle"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_arc (GRAPHICS, centreX, centreY, radius, fromAngle, toAngle);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (DrawEllipse, U"Praat picture: Draw ellipse", 0) {
-	dia_rectangle (dia);
-OK2
+FORM (GRAPHICS_DrawEllipse, U"Praat picture: Draw ellipse", nullptr) {
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_ellipse (GRAPHICS,
-		GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_ellipse (GRAPHICS, fromX, toX, fromY, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (PaintEllipse, U"Praat picture: Paint ellipse", 0) {
+FORM (GRAPHICS_PaintEllipse, U"Praat picture: Paint ellipse", nullptr) {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	dia_rectangle (dia);
-OK2
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
-	Graphics_fillEllipse (GRAPHICS, GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
+		Graphics_fillEllipse (GRAPHICS, fromX, toX, fromY, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (DrawCircle, U"Praat picture: Draw circle", 0) {
-	REAL (U"Centre x", U"0.0")
-	REAL (U"Centre y", U"0.0")
-	POSITIVE (U"Radius (along x)", U"1.0")
-OK2
+FORM (GRAPHICS_DrawCircle, U"Praat picture: Draw circle", nullptr) {
+	REAL4 (centreX, U"Centre x", U"0.0")
+	REAL4 (centreY, U"Centre y", U"0.0")
+	POSITIVE4 (radius, U"Radius (along x)", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_circle (GRAPHICS, GET_REAL (U"Centre x"), GET_REAL (U"Centre y"), GET_REAL (U"Radius"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_circle (GRAPHICS, centreX, centreY, radius);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (PaintCircle, U"Praat picture: Paint circle", 0) {
+FORM (GRAPHICS_PaintCircle, U"Praat picture: Paint circle", nullptr) {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	REAL (U"Centre x", U"0")
-	REAL (U"Centre y", U"0")
-	POSITIVE (U"Radius (along x)", U"1.0")
-OK2
+	REAL4 (centreX, U"Centre x", U"0.0")
+	REAL4 (centreY, U"Centre y", U"0.0")
+	POSITIVE4 (radius, U"Radius (along x)", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
-	Graphics_fillCircle (GRAPHICS, GET_REAL (U"Centre x"), GET_REAL (U"Centre y"), GET_REAL (U"Radius"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
+		Graphics_fillCircle (GRAPHICS, centreX, centreY, radius);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (DrawCircle_mm, U"Praat picture: Draw circle (mm)", 0) {
-	REAL (U"Centre x", U"0.0")
-	REAL (U"Centre y", U"0.0")
-	POSITIVE (U"Diameter (mm)", U"5.0")
-OK2
+FORM (GRAPHICS_DrawCircle_mm, U"Praat picture: Draw circle (mm)", nullptr) {
+	REAL4 (centreX, U"Centre x", U"0.0")
+	REAL4 (centreY, U"Centre y", U"0.0")
+	POSITIVE4 (diameter, U"Diameter (mm)", U"5.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_circle_mm (GRAPHICS, GET_REAL (U"Centre x"), GET_REAL (U"Centre y"), GET_REAL (U"Diameter"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_circle_mm (GRAPHICS, centreX, centreY, diameter);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (PaintCircle_mm, U"Praat picture: Paint circle (mm)", 0) {
+FORM (GRAPHICS_PaintCircle_mm, U"Praat picture: Paint circle (mm)", nullptr) {
 	COLOUR (U"Colour (0-1, name, or {r,g,b})", U"0.5")
-	REAL (U"Centre x", U"0.0")
-	REAL (U"Centre y", U"0.0")
-	POSITIVE (U"Diameter (mm)", U"5.0")
-OK2
+	REAL4 (centreX, U"Centre x", U"0.0")
+	REAL4 (centreY, U"Centre y", U"0.0")
+	POSITIVE4 (diameter, U"Diameter (mm)", U"5.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
-	Graphics_fillCircle_mm (GRAPHICS, GET_REAL (U"Centre x"), GET_REAL (U"Centre y"), GET_REAL (U"Diameter"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_setColour (GRAPHICS, GET_COLOUR (U"Colour"));
+		Graphics_fillCircle_mm (GRAPHICS, centreX, centreY, diameter);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (InsertPictureFromFile, U"Praat picture: Insert picture from file", U"Insert picture from file...") {
+FORM (GRAPHICS_InsertPictureFromFile, U"Praat picture: Insert picture from file", U"Insert picture from file...") {
 	LABEL (U"", U"File name:")
-	TEXTFIELD (U"fileName", U"~/Desktop/paul.jpg")
-	dia_rectangle (dia);
-OK2
+	TEXTFIELD4 (fileName, U"fileName", U"~/Desktop/paul.jpg")
+	REAL4 (fromX, U"From x", U"0.0")
+	REAL4 (toX, U"To x", U"1.0")
+	REAL4 (fromY, U"From y", U"0.0")
+	REAL4 (toY, U"To y", U"1.0")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_setInner (GRAPHICS);
-	Graphics_imageFromFile (GRAPHICS, GET_STRING (U"fileName"), GET_REAL (U"From x"), GET_REAL (U"To x"), GET_REAL (U"From y"), GET_REAL (U"To y"));
-	Graphics_unsetInner (GRAPHICS);
-END2 }
-
+	GRAPHICS_NONE
+		Graphics_setInner (GRAPHICS);
+		Graphics_imageFromFile (GRAPHICS, fileName, fromX, toX, fromY, toY);
+		Graphics_unsetInner (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (Axes, U"Praat picture: Axes", U"Axes...") {
-	REAL (U"left Left and right", U"0.0")
-	REAL (U"right Left and right", U"1.0")
-	REAL (U"left Bottom and top", U"0.0")
-	REAL (U"right Bottom and top", U"1.0")
-OK2
+FORM (GRAPHICS_Axes, U"Praat picture: Axes", U"Axes...") {
+	REAL4 (left, U"left Left and right", U"0.0")
+	REAL4 (right, U"right Left and right", U"1.0")
+	REAL4 (bottom, U"left Bottom and top", U"0.0")
+	REAL4 (top, U"right Bottom and top", U"1.0")
+OK
 	double x1WC, x2WC, y1WC, y2WC;
 	Graphics_inqWindow (GRAPHICS, & x1WC, & x2WC, & y1WC, & y2WC);
 	SET_REAL (U"left Left and right", x1WC);
@@ -954,121 +968,191 @@ OK2
 	SET_REAL (U"left Bottom and top", y1WC);
 	SET_REAL (U"right Bottom and top", y2WC);
 DO
-	double left = GET_REAL (U"left Left and right"), right = GET_REAL (U"right Left and right");
-	double top = GET_REAL (U"right Bottom and top"), bottom = GET_REAL (U"left Bottom and top");
-	REQUIRE (right != left, U"Left and right must not be equal.")
-	REQUIRE (top != bottom, U"Top and bottom must not be equal.")
-	autoPraatPicture picture;
-	Graphics_setWindow (GRAPHICS, left, right, bottom, top);
-END2 }
+	if (left == right) Melder_throw (U"Left and right should not be equal.");
+	if (top == bottom) Melder_throw (U"Top and bottom should not be equal.");
+	GRAPHICS_NONE
+		Graphics_setWindow (GRAPHICS, left, right, bottom, top);
+	GRAPHICS_NONE_END
+}
 
-/***** "Margins" MENU *****/
+// MARK: Margins
 
-DIRECT (DrawInnerBox) {
-	autoPraatPicture picture;
-	Graphics_drawInnerBox (GRAPHICS);
-} END
+DIRECT (GRAPHICS_DrawInnerBox) {
+	GRAPHICS_NONE
+		Graphics_drawInnerBox (GRAPHICS);
+	GRAPHICS_NONE_END
+}
 
-FORM (Text_left, U"Praat picture: Text left", U"Text left/right/top/bottom...") {
-	BOOLEAN (U"Far", true)
-	TEXTFIELD (U"text", U"")
-OK2
+FORM (GRAPHICS_TextLeft, U"Praat picture: Text left", U"Text left/right/top/bottom...") {
+	BOOLEAN4 (farr, U"Far", true)
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_textLeft (GRAPHICS, GET_INTEGER (U"Far"), GET_STRING (U"text"));
-END2 }
+	GRAPHICS_NONE
+		Graphics_textLeft (GRAPHICS, farr, text);
+	GRAPHICS_NONE_END
+}
 
-FORM (Text_right, U"Praat picture: Text right", U"Text left/right/top/bottom...") {
-	BOOLEAN (U"Far", true)
-	TEXTFIELD (U"text", U"")
-OK2
+FORM (GRAPHICS_TextRight, U"Praat picture: Text right", U"Text left/right/top/bottom...") {
+	BOOLEAN4 (farr, U"Far", true)
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_textRight (GRAPHICS, GET_INTEGER (U"Far"), GET_STRING (U"text"));
-END2 }
+	GRAPHICS_NONE
+		Graphics_textRight (GRAPHICS, farr, text);
+	GRAPHICS_NONE_END
+}
 
-FORM (Text_top, U"Praat picture: Text top", U"Text left/right/top/bottom...") {
-	BOOLEAN (U"Far", false)
-	TEXTFIELD (U"text", U"")
-OK2
+FORM (GRAPHICS_TextTop, U"Praat picture: Text top", U"Text left/right/top/bottom...") {
+	BOOLEAN4 (farr, U"Far", true)
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_textTop (GRAPHICS, GET_INTEGER (U"Far"), GET_STRING (U"text"));
-END2 }
+	GRAPHICS_NONE
+		Graphics_textTop (GRAPHICS, farr, text);
+	GRAPHICS_NONE_END
+}
 
-FORM (Text_bottom, U"Praat picture: Text bottom", U"Text left/right/top/bottom...") {
-	BOOLEAN (U"Far", true)
-	TEXTFIELD (U"text", U"")
-OK2
+FORM (GRAPHICS_TextBottom, U"Praat picture: Text bottom", U"Text left/right/top/bottom...") {
+	BOOLEAN4 (farr, U"Far", true)
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	autoPraatPicture picture;
-	Graphics_textBottom (GRAPHICS, GET_INTEGER (U"Far"), GET_STRING (U"text"));
-END2 }
+	GRAPHICS_NONE
+		Graphics_textBottom (GRAPHICS, farr, text);
+	GRAPHICS_NONE_END
+}
+
+#define FIELDS_MARKS_EVERY  \
+	POSITIVE4 (units, U"Units", U"1.0") \
+	POSITIVE4 (distance, U"Distance", U"0.1") \
+	BOOLEAN4 (writeNumbers, U"Write numbers", true) \
+	BOOLEAN4 (drawTicks, U"Draw ticks", true) \
+	BOOLEAN4 (drawDottedLines, U"Draw dotted lines", true)
 
-static void dia_marksEvery (UiForm dia) {
-	POSITIVE (U"Units", U"1.0")
-	POSITIVE (U"Distance", U"0.1")
-	BOOLEAN (U"Write numbers", true)
-	BOOLEAN (U"Draw ticks", true)
-	BOOLEAN (U"Draw dotted lines", true)
+FORM (GRAPHICS_MarksLeftEvery, U"Praat picture: Marks left every...", U"Marks left/right/top/bottom every...") {
+	FIELDS_MARKS_EVERY
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksLeftEvery (GRAPHICS, units, distance, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_MarksRightEvery, U"Praat picture: Marks right every...", U"Marks left/right/top/bottom every...") {
+	FIELDS_MARKS_EVERY
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksRightEvery (GRAPHICS, units, distance, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_MarksBottomEvery, U"Praat picture: Marks bottom every...", U"Marks left/right/top/bottom every...") {
+	FIELDS_MARKS_EVERY
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksBottomEvery (GRAPHICS, units, distance, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_MarksTopEvery, U"Praat picture: Marks top every...", U"Marks left/right/top/bottom every...") {
+	FIELDS_MARKS_EVERY
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksTopEvery (GRAPHICS, units, distance, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+#define FIELDS_MARKS  \
+	NATURAL4 (numberOfMarks, U"Number of marks", U"6") \
+	BOOLEAN4 (writeNumbers, U"Write numbers", true) \
+	BOOLEAN4 (drawTicks, U"Draw ticks", true) \
+	BOOLEAN4 (drawDottedLines, U"Draw dotted lines", true)
+
+FORM (GRAPHICS_MarksLeft, U"Praat picture: Marks left", U"Marks left/right/top/bottom...") {
+	FIELDS_MARKS
+	OK
+DO
+	GRAPHICS_NONE
+		if (numberOfMarks < 2) Melder_throw (U"The number of marks should be at least 2.");
+		Graphics_marksLeft (GRAPHICS, numberOfMarks, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_MarksRight, U"Praat picture: Marks right", U"Marks left/right/top/bottom...") {
+	FIELDS_MARKS
+	OK
+DO
+	GRAPHICS_NONE
+		if (numberOfMarks < 2) Melder_throw (U"The number of marks should be at least 2.");
+		Graphics_marksRight (GRAPHICS, numberOfMarks, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_MarksBottom, U"Praat picture: Marks bottom", U"Marks left/right/top/bottom...") {
+	FIELDS_MARKS
+	OK
+DO
+	GRAPHICS_NONE
+		if (numberOfMarks < 2) Melder_throw (U"The number of marks should be at least 2.");
+		Graphics_marksBottom (GRAPHICS, numberOfMarks, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_MarksTop, U"Praat picture: Marks top", U"Marks left/right/top/bottom...") {
+	FIELDS_MARKS
+	OK
+DO
+	GRAPHICS_NONE
+		if (numberOfMarks < 2) Melder_throw (U"The number of marks should be at least 2.");
+		Graphics_marksTop (GRAPHICS, numberOfMarks, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+#define FIELDS_MARKS_LOGARITHMIC  \
+	NATURAL4 (marksPerDecade, U"Marks per decade", U"3") \
+	BOOLEAN4 (writeNumbers, U"Write numbers", true) \
+	BOOLEAN4 (drawTicks, U"Draw ticks", true) \
+	BOOLEAN4 (drawDottedLines, U"Draw dotted lines", true)
+
+FORM (GRAPHICS_LogarithmicMarksLeft, U"Praat picture: Logarithmic marks left", U"Logarithmic marks left/right/top/bottom...") {
+	FIELDS_MARKS_LOGARITHMIC
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksLeftLogarithmic (GRAPHICS, marksPerDecade, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_LogarithmicMarksRight, U"Praat picture: Logarithmic marks right", U"Logarithmic marks left/right/top/bottom...") {
+	FIELDS_MARKS_LOGARITHMIC
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksRightLogarithmic (GRAPHICS, marksPerDecade, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_LogarithmicMarksBottom, U"Praat picture: Logarithmic marks bottom", U"Logarithmic marks left/right/top/bottom...") {
+	FIELDS_MARKS_LOGARITHMIC
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksBottomLogarithmic (GRAPHICS, marksPerDecade, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_LogarithmicMarksTop, U"Praat picture: Logarithmic marks top", U"Logarithmic marks left/right/top/bottom...") {
+	FIELDS_MARKS_LOGARITHMIC
+	OK
+DO
+	GRAPHICS_NONE
+		Graphics_marksTopLogarithmic (GRAPHICS, marksPerDecade, writeNumbers, drawTicks, drawDottedLines);
+	GRAPHICS_NONE_END
 }
-static void do_marksEvery (UiForm dia, void (*Graphics_marksEvery) (Graphics, double, double, bool, bool, bool)) {
-	autoPraatPicture picture;
-	Graphics_marksEvery (GRAPHICS, GET_REAL (U"Units"), GET_REAL (U"Distance"),
-		GET_INTEGER (U"Write numbers"),
-		GET_INTEGER (U"Draw ticks"), GET_INTEGER (U"Draw dotted lines"));
-}
-FORM (Marks_left_every, U"Praat picture: Marks left every...", U"Marks left/right/top/bottom every...") {
-	dia_marksEvery (dia); OK2 DO do_marksEvery (dia, Graphics_marksLeftEvery); END2 }
-FORM (Marks_right_every, U"Praat picture: Marks right every...", U"Marks left/right/top/bottom every...") {
-	dia_marksEvery (dia); OK2 DO do_marksEvery (dia, Graphics_marksRightEvery); END2 }
-FORM (Marks_bottom_every, U"Praat picture: Marks bottom every...", U"Marks left/right/top/bottom every...") {
-	dia_marksEvery (dia); OK2 DO do_marksEvery (dia, Graphics_marksBottomEvery); END2 }
-FORM (Marks_top_every, U"Praat picture: Marks top every...", U"Marks left/right/top/bottom every...") {
-	dia_marksEvery (dia); OK2 DO do_marksEvery (dia, Graphics_marksTopEvery); END2 }
-
-static void dia_marks (UiForm dia) {
-	NATURAL (U"Number of marks", U"6")
-	BOOLEAN (U"Write numbers", true)
-	BOOLEAN (U"Draw ticks", true)
-	BOOLEAN (U"Draw dotted lines", true)
-}
-static void do_marks (UiForm dia, void (*Graphics_marks) (Graphics, int, bool, bool, bool)) {
-	long numberOfMarks = GET_INTEGER (U"Number of marks");
-	REQUIRE (numberOfMarks >= 2, U"`Number of marks' must be at least 2.")
-	autoPraatPicture picture;
-	Graphics_marks (GRAPHICS, numberOfMarks, GET_INTEGER (U"Write numbers"),
-		GET_INTEGER (U"Draw ticks"), GET_INTEGER (U"Draw dotted lines"));
-}
-FORM (Marks_left, U"Praat picture: Marks left", U"Marks left/right/top/bottom...") {
-	dia_marks (dia); OK2 DO do_marks (dia, Graphics_marksLeft); END2 }
-FORM (Marks_right, U"Praat picture: Marks right", U"Marks left/right/top/bottom...") {
-	dia_marks (dia); OK2 DO do_marks (dia, Graphics_marksRight); END2 }
-FORM (Marks_bottom, U"Praat picture: Marks bottom", U"Marks left/right/top/bottom...") {
-	dia_marks (dia); OK2 DO do_marks (dia, Graphics_marksBottom); END2 }
-FORM (Marks_top, U"Praat picture: Marks top", U"Marks left/right/top/bottom...") {
-	dia_marks (dia); OK2 DO do_marks (dia, Graphics_marksTop); END2 }
-
-static void dia_marksLogarithmic (UiForm dia) {
-	NATURAL (U"Marks per decade", U"3")
-	BOOLEAN (U"Write numbers", true)
-	BOOLEAN (U"Draw ticks", true)
-	BOOLEAN (U"Draw dotted lines", true)
-}
-static void do_marksLogarithmic (UiForm dia, void (*Graphics_marksLogarithmic) (Graphics, int, bool, bool, bool)) {
-	long numberOfMarksPerDecade = GET_INTEGER (U"Marks per decade");
-	autoPraatPicture picture;
-	Graphics_marksLogarithmic (GRAPHICS, numberOfMarksPerDecade, GET_INTEGER (U"Write numbers"),
-		GET_INTEGER (U"Draw ticks"), GET_INTEGER (U"Draw dotted lines"));
-}
-FORM (marksLeftLogarithmic, U"Praat picture: Logarithmic marks left", U"Logarithmic marks left/right/top/bottom...") {
-	dia_marksLogarithmic (dia); OK2 DO do_marksLogarithmic (dia, Graphics_marksLeftLogarithmic); END2 }
-FORM (marksRightLogarithmic, U"Praat picture: Logarithmic marks right", U"Logarithmic marks left/right/top/bottom...") {
-	dia_marksLogarithmic (dia); OK2 DO do_marksLogarithmic (dia, Graphics_marksRightLogarithmic); END2 }
-FORM (marksBottomLogarithmic, U"Praat picture: Logarithmic marks bottom", U"Logarithmic marks left/right/top/bottom...") {
-	dia_marksLogarithmic (dia); OK2 DO do_marksLogarithmic (dia, Graphics_marksBottomLogarithmic); END2 }
-FORM (marksTopLogarithmic, U"Praat picture: Logarithmic marks top", U"Logarithmic marks left/right/top/bottom...") {
-	dia_marksLogarithmic (dia); OK2 DO do_marksLogarithmic (dia, Graphics_marksTopLogarithmic); END2 }
 
 static void sortBoundingBox (double *x1WC, double *x2WC, double *y1WC, double *y2WC) {
 	double temp;
@@ -1076,19 +1160,15 @@ static void sortBoundingBox (double *x1WC, double *x2WC, double *y1WC, double *y
 	if (*y1WC > *y2WC) temp = *y1WC, *y1WC = *y2WC, *y2WC = temp;
 }
 
-static void dia_oneMark (UiForm dia) {
-	REAL (U"Position", U"0.0")
-	BOOLEAN (U"Write number", true)
-	BOOLEAN (U"Draw tick", true)
-	BOOLEAN (U"Draw dotted line", true)
+FORM (GRAPHICS_OneMarkLeft, U"Praat picture: One mark left", U"One mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"0.0")
+	BOOLEAN4 (writeNumber, U"Write number", true)
+	BOOLEAN4 (drawTick, U"Draw tick", true)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", true)
 	LABEL (U"", U"Draw text:")
-	TEXTFIELD (U"text", U"")
-}
-FORM (Mark_left, U"Praat picture: One mark left", U"One mark left/right/top/bottom...") {
-	dia_oneMark (dia);
-OK2
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dy;
 	{// scope
 		autoPraatPicture picture;
@@ -1098,17 +1178,20 @@ DO
 	dy = 0.2 * (y2WC - y1WC);
 	if (position < y1WC - dy || position > y2WC + dy)
 		Melder_throw (U"\"Position\" must be between ", y1WC, U" and ", y2WC, U".");
-	autoPraatPicture picture;
-	Graphics_markLeft (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (Mark_right, U"Praat picture: One mark right", U"One mark left/right/top/bottom...") {
-	dia_oneMark (dia);
-OK2
+	GRAPHICS_NONE
+		Graphics_markLeft (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_OneMarkRight, U"Praat picture: One mark right", U"One mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"0.0")
+	BOOLEAN4 (writeNumber, U"Write number", true)
+	BOOLEAN4 (drawTick, U"Draw tick", true)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", true)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dy;
 	{// scope
 		autoPraatPicture picture;
@@ -1118,17 +1201,20 @@ DO
 	dy = 0.2 * (y2WC - y1WC);
 	if (position < y1WC - dy || position > y2WC + dy)
 		Melder_throw (U"\"Position\" must be between ", y1WC, U" and ", y2WC, U".");
-	autoPraatPicture picture;
-	Graphics_markRight (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (Mark_top, U"Praat picture: One mark top", U"One mark left/right/top/bottom...") {
-	dia_oneMark (dia);
-OK2
+	GRAPHICS_NONE
+		Graphics_markRight (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_OneMarkTop, U"Praat picture: One mark top", U"One mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"0.0")
+	BOOLEAN4 (writeNumber, U"Write number", true)
+	BOOLEAN4 (drawTick, U"Draw tick", true)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", true)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dx;
 	{// scope
 		autoPraatPicture picture;   // WHY?
@@ -1138,17 +1224,20 @@ DO
 	dx = 0.2 * (x2WC - x1WC);
 	if (position < x1WC - dx || position > x2WC + dx)
 		Melder_throw (U"\"Position\" must be between ", x1WC, U" and ", x2WC, U".");
-	autoPraatPicture picture;
-	Graphics_markTop (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (Mark_bottom, U"Praat picture: One mark bottom", U"One mark left/right/top/bottom...") {
-	dia_oneMark (dia);
-OK2
+	GRAPHICS_NONE
+		Graphics_markTop (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_OneMarkBottom, U"Praat picture: One mark bottom", U"One mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"0.0")
+	BOOLEAN4 (writeNumber, U"Write number", true)
+	BOOLEAN4 (drawTick, U"Draw tick", true)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", true)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dx;
 	{// scope
 		autoPraatPicture picture;
@@ -1158,25 +1247,20 @@ DO
 	dx = 0.2 * (x2WC - x1WC);
 	if (position < x1WC - dx || position > x2WC + dx)
 		Melder_throw (U"\"Position\" must be between ", x1WC, U" and ", x2WC, U".");
-	autoPraatPicture picture;
-	Graphics_markBottom (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-static void dia_oneLogarithmicMark (UiForm dia) {
-	REAL (U"Position", U"1.0")
-	BOOLEAN (U"Write number", 1)
-	BOOLEAN (U"Draw tick", 1)
-	BOOLEAN (U"Draw dotted line", 1)
-	LABEL (U"", U"Draw text:")
-	TEXTFIELD (U"text", U"")
+	GRAPHICS_NONE
+		Graphics_markBottom (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
 }
-FORM (LogarithmicMark_left, U"Praat picture: One logarithmic mark left", U"One logarithmic mark left/right/top/bottom...") {
-	dia_oneLogarithmicMark (dia);
-OK2
+
+FORM (GRAPHICS_OneLogarithmicMarkLeft, U"Praat picture: One logarithmic mark left", U"One logarithmic mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"1.0")
+	BOOLEAN4 (writeNumber, U"Write number", 1)
+	BOOLEAN4 (drawTick, U"Draw tick", 1)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", 1)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dy;
 	{// scope
 		autoPraatPicture picture;
@@ -1186,17 +1270,20 @@ DO
 	dy = 0.2 * (y2WC - y1WC);
 	if (position < pow (10, y1WC - dy) || position > pow (10, y2WC + dy))
 		Melder_throw (U"\"Position\" must be between ", pow (10, y1WC), U" and ", pow (10, y2WC), U".");
-	autoPraatPicture picture;
-	Graphics_markLeftLogarithmic (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (LogarithmicMark_right, U"Praat picture: One logarithmic mark right", U"One logarithmic mark left/right/top/bottom...") {
-	dia_oneLogarithmicMark (dia);
-OK2
+	GRAPHICS_NONE
+		Graphics_markLeftLogarithmic (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_OneLogarithmicMarkRight, U"Praat picture: One logarithmic mark right", U"One logarithmic mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"1.0")
+	BOOLEAN4 (writeNumber, U"Write number", 1)
+	BOOLEAN4 (drawTick, U"Draw tick", 1)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", 1)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dy;
 	{// scope
 		autoPraatPicture picture;
@@ -1206,17 +1293,20 @@ DO
 	dy = 0.2 * (y2WC - y1WC);
 	if (position < pow (10, y1WC - dy) || position > pow (10, y2WC + dy))
 		Melder_throw (U"\"Position\" must be between ", pow (10, y1WC), U" and ", pow (10, y2WC), U".");
-	autoPraatPicture picture;
-	Graphics_markRightLogarithmic (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (LogarithmicMark_top, U"Praat picture: One logarithmic mark top", U"One logarithmic mark left/right/top/bottom...") {
-	dia_oneLogarithmicMark (dia);
-OK2
+	GRAPHICS_NONE
+		Graphics_markRightLogarithmic (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_OneLogarithmicMarkTop, U"Praat picture: One logarithmic mark top", U"One logarithmic mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"1.0")
+	BOOLEAN4 (writeNumber, U"Write number", 1)
+	BOOLEAN4 (drawTick, U"Draw tick", 1)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", 1)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dx;
 	{// scope
 		autoPraatPicture picture;
@@ -1226,17 +1316,20 @@ DO
 	dx = 0.2 * (x2WC - x1WC);
 	if (position < pow (10, x1WC - dx) || position > pow (10, x2WC + dx))
 		Melder_throw (U"\"Position\" must be between ", pow (10, x1WC), U" and ", pow (10, x2WC), U".");
-	autoPraatPicture picture;
-	Graphics_markTopLogarithmic (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (LogarithmicMark_bottom, U"Praat picture: One logarithmic mark bottom", U"One logarithmic mark left/right/top/bottom...") {
-	dia_oneLogarithmicMark (dia);
-OK2
+	GRAPHICS_NONE
+		Graphics_markTopLogarithmic (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_OneLogarithmicMarkBottom, U"Praat picture: One logarithmic mark bottom", U"One logarithmic mark left/right/top/bottom...") {
+	REAL4 (position, U"Position", U"1.0")
+	BOOLEAN4 (writeNumber, U"Write number", 1)
+	BOOLEAN4 (drawTick, U"Draw tick", 1)
+	BOOLEAN4 (drawDottedLine, U"Draw dotted line", 1)
+	LABEL (U"", U"Draw text:")
+	TEXTFIELD4 (text, U"text", U"")
+	OK
 DO
-	double position = GET_REAL (U"Position");
 	double x1WC, x2WC, y1WC, y2WC, dx;
 	{// scope
 		autoPraatPicture picture;
@@ -1246,124 +1339,123 @@ DO
 	dx = 0.2 * (x2WC - x1WC);
 	if (position < pow (10, x1WC - dx) || position > pow (10, x2WC + dx))
 		Melder_throw (U"\"Position\" must be between ", pow (10, x1WC), U" and ", pow (10, x2WC), U".");
-	autoPraatPicture picture;
-	Graphics_markBottomLogarithmic (GRAPHICS, position, GET_INTEGER (U"Write number"),
-		GET_INTEGER (U"Draw tick"), GET_INTEGER (U"Draw dotted line"),
-		GET_STRING (U"text"));
-END2 }
-
-FORM (dxMMtoWC, U"Compute horizontal distance in world coordinates", 0) {
-	REAL (U"Distance (mm)", U"10.0")
-OK2
+	GRAPHICS_NONE
+		Graphics_markBottomLogarithmic (GRAPHICS, position, writeNumber, drawTick, drawDottedLine, text);
+	GRAPHICS_NONE_END
+}
+
+FORM (GRAPHICS_HorizontalMmToWorldCoordinates, U"Compute horizontal distance in world coordinates", nullptr) {
+	REAL4 (distance, U"Distance (mm)", U"10.0")
+	OK
 DO
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double wc = Graphics_dxMMtoWC (GRAPHICS, GET_REAL (U"Distance"));
+	double wc = Graphics_dxMMtoWC (GRAPHICS, distance);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (wc, U"(world coordinates)");
-END2 }
+END }
 
-FORM (dxWCtoMM, U"Compute horizontal distance in millimetres", 0) {
-	REAL (U"Distance (wc)", U"0.1")
-OK2
+FORM (GRAPHICS_HorizontalWorldCoordinatesToMm, U"Compute horizontal distance in millimetres", nullptr) {
+	REAL4 (distance, U"Distance (wc)", U"0.1")
+	OK
 DO
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double mm = Graphics_dxWCtoMM (GRAPHICS, GET_REAL (U"Distance"));
+	double mm = Graphics_dxWCtoMM (GRAPHICS, distance);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (mm, U"mm");
-END2 }
+END }
 
-FORM (dyMMtoWC, U"Compute vertical distance in world coordinates", 0) {
-	REAL (U"Distance (mm)", U"10.0")
-OK2
+FORM (GRAPHICS_VerticalMmToWorldCoordinates, U"Compute vertical distance in world coordinates", nullptr) {
+	REAL4 (distance, U"Distance (mm)", U"10.0")
+	OK
 DO
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double wc = Graphics_dyMMtoWC (GRAPHICS, GET_REAL (U"Distance"));
+	double wc = Graphics_dyMMtoWC (GRAPHICS, distance);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (wc, U"(world coordinates)");
-END2 }
+END }
 
-FORM (dyWCtoMM, U"Compute vertical distance in millimetres", 0) {
-	REAL (U"Distance (wc)", U"1.0")
-OK2
+FORM (GRAPHICS_VerticalWorldCoordinatesToMm, U"Compute vertical distance in millimetres", nullptr) {
+	REAL4 (distance, U"Distance (wc)", U"1.0")
+	OK
 DO
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double mm = Graphics_dyWCtoMM (GRAPHICS, GET_REAL (U"Distance"));
+	double mm = Graphics_dyWCtoMM (GRAPHICS, distance);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (mm, U"mm");
-END2 }
+END }
 
-FORM (textWidth_wc, U"Text width in world coordinates", 0) {
-	TEXTFIELD (U"text", U"Hello world")
-OK2
+FORM (GRAPHICS_TextWidth_worldCoordinates, U"Text width in world coordinates", nullptr) {
+	TEXTFIELD4 (text, U"text", U"Hello world")
+	OK
 DO
 	Graphics_setFont (GRAPHICS, static_cast<kGraphics_font> (theCurrentPraatPicture -> font));
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double wc = Graphics_textWidth (GRAPHICS, GET_STRING (U"text"));
+	double wc = Graphics_textWidth (GRAPHICS, text);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (wc, U"(world coordinates)");
-END2 }
+END }
 
-FORM (textWidth_mm, U"Text width in millimetres", 0) {
-	TEXTFIELD (U"text", U"Hello world")
-OK2
+FORM (GRAPHICS_TextWidth_mm, U"Text width in millimetres", nullptr) {
+	TEXTFIELD4 (text, U"text", U"Hello world")
+	OK
 DO
 	Graphics_setFont (GRAPHICS, static_cast<kGraphics_font> (theCurrentPraatPicture -> font));
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double mm = Graphics_dxWCtoMM (GRAPHICS, Graphics_textWidth (GRAPHICS, GET_STRING (U"text")));
+	double mm = Graphics_dxWCtoMM (GRAPHICS, Graphics_textWidth (GRAPHICS, text));
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (mm, U"mm");
-END2 }
+END }
 
-FORM (textWidth_ps_wc, U"PostScript text width in world coordinates", 0) {
-	RADIO (U"Phonetic font", 1)
+FORM (GRAPHICS_PostScriptTextWidth_worldCoordinates, U"PostScript text width in world coordinates", nullptr) {
+	RADIO4x (phoneticFont, U"Phonetic font", 1, 0)
 		RADIOBUTTON (U"XIPA")
 		RADIOBUTTON (U"SILIPA")
-	TEXTFIELD (U"text", U"Hello world")
-OK2
+	TEXTFIELD4 (text, U"text", U"Hello world")
+	OK
 DO
 	Graphics_setFont (GRAPHICS, static_cast<kGraphics_font> (theCurrentPraatPicture -> font));
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double wc = Graphics_textWidth_ps (GRAPHICS, GET_STRING (U"text"), GET_INTEGER (U"Phonetic font") - 1);
+	double wc = Graphics_textWidth_ps (GRAPHICS, text, phoneticFont);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (wc, U"(world coordinates)");
-END2 }
+END }
 
-FORM (textWidth_ps_mm, U"PostScript text width in millimetres", 0) {
-	RADIO (U"Phonetic font", 1)
+FORM (GRAPHICS_PostScriptTextWidth_mm, U"PostScript text width in millimetres", nullptr) {
+	RADIO4x (phoneticFont, U"Phonetic font", 1, 0)
 		RADIOBUTTON (U"XIPA")
 		RADIOBUTTON (U"SILIPA")
-	TEXTFIELD (U"text", U"Hello world")
-OK2
+	TEXTFIELD4 (text, U"text", U"Hello world")
+	OK
 DO
 	Graphics_setFont (GRAPHICS, static_cast<kGraphics_font> (theCurrentPraatPicture -> font));
 	Graphics_setFontSize (GRAPHICS, theCurrentPraatPicture -> fontSize);
 	Graphics_setViewport (GRAPHICS, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
 	Graphics_setInner (GRAPHICS);
-	double mm = Graphics_textWidth_ps_mm (GRAPHICS, GET_STRING (U"text"), GET_INTEGER (U"Phonetic font") - 1);
+	double mm = Graphics_textWidth_ps_mm (GRAPHICS, text, phoneticFont);
 	Graphics_unsetInner (GRAPHICS);
 	Melder_informationReal (mm, U"mm");
-END2 }
-
-DIRECT (SearchManual) { Melder_search (); } END
-DIRECT (PictureWindowHelp) { Melder_help (U"Picture window"); } END
-DIRECT (AboutSpecialSymbols) { Melder_help (U"Special symbols"); } END
-DIRECT (AboutTextStyles) { Melder_help (U"Text styles"); } END
-DIRECT (PhoneticSymbols) { Melder_help (U"Phonetic symbols"); } END
-DIRECT (Picture_settings_report) {
+END }
+
+DIRECT (HELP_SearchManual_Picture) { Melder_search (); END }
+DIRECT (HELP_PictureWindowHelp) { HELP (U"Picture window") }
+DIRECT (HELP_AboutSpecialSymbols) { HELP (U"Special symbols") }
+DIRECT (HELP_AboutTextStyles) { HELP (U"Text styles") }
+DIRECT (HELP_PhoneticSymbols) { HELP (U"Phonetic symbols") }
+DIRECT (GRAPHICS_Picture_settings_report) {
 	MelderInfo_open ();
 	const char32 *units = theCurrentPraatPicture == & theForegroundPraatPicture ? U" inches" : U"";
 	MelderInfo_writeLine (U"Outer viewport left: ", theCurrentPraatPicture -> x1NDC, units);
@@ -1423,7 +1515,7 @@ DIRECT (Picture_settings_report) {
 	MelderInfo_writeLine (U"Axis bottom: ", y1WC);
 	MelderInfo_writeLine (U"Axis top: ", y2WC);
 	MelderInfo_close ();
-} END
+END }
 
 
 /**********   **********/
@@ -1600,179 +1692,185 @@ void praat_picture_init () {
 		helpMenu =    GuiMenu_createInWindow (dialog, U"Help", 0);
 	}
 
-	praat_addMenuCommand (U"Picture", U"File", U"Picture info", nullptr, 0, DO_Picture_settings_report);
-	praat_addMenuCommand (U"Picture", U"File", U"Picture settings report", nullptr, praat_HIDDEN, DO_Picture_settings_report);
+	praat_addMenuCommand (U"Picture", U"File", U"Picture info", nullptr, 0, GRAPHICS_Picture_settings_report);
+	praat_addMenuCommand (U"Picture", U"File",   U"Picture settings report", U"*Picture info", praat_DEPRECATED_2007, GRAPHICS_Picture_settings_report);
 	praat_addMenuCommand (U"Picture", U"File", U"-- save --", nullptr, 0, nullptr);
 	#if defined (macintosh) || defined (UNIX)
-		praat_addMenuCommand (U"Picture", U"File", U"Save as PDF file...", nullptr, 'S', DO_Picture_writeToPdfFile);
-		praat_addMenuCommand (U"Picture", U"File", U"Write to PDF file...", nullptr, praat_HIDDEN, DO_Picture_writeToPdfFile);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as PDF file...", nullptr, 'S', GRAPHICS_Picture_writeToPdfFile);
+		praat_addMenuCommand (U"Picture", U"File",   U"Write to PDF file...", U"*Save as PDF file...", praat_DEPRECATED_2011, GRAPHICS_Picture_writeToPdfFile);
 	#endif
-	praat_addMenuCommand (U"Picture", U"File", U"Save as 300-dpi PNG file...", nullptr, 0, DO_Picture_writeToPngFile_300);
+	praat_addMenuCommand (U"Picture", U"File", U"Save as 300-dpi PNG file...", nullptr, 0, GRAPHICS_Picture_writeToPngFile_300);
 	#if defined (_WIN32)
-		praat_addMenuCommand (U"Picture", U"File", U"Save as 600-dpi PNG file...", nullptr, 'S', DO_Picture_writeToPngFile_600);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as 600-dpi PNG file...", nullptr, 'S', GRAPHICS_Picture_writeToPngFile_600);
 	#endif
 	#if defined (macintosh) || defined (UNIX)
-		praat_addMenuCommand (U"Picture", U"File", U"Save as 600-dpi PNG file...", nullptr, 0, DO_Picture_writeToPngFile_600);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as 600-dpi PNG file...", nullptr, 0, GRAPHICS_Picture_writeToPngFile_600);
 	#endif
 	praat_addMenuCommand (U"Picture", U"File", U"Save as EPS file", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Picture", U"File", U"PostScript settings...", nullptr, 1, DO_PostScript_settings);
-		praat_addMenuCommand (U"Picture", U"File", U"Save as EPS file...", nullptr, 1, DO_Picture_writeToEpsFile);
-		praat_addMenuCommand (U"Picture", U"File", U"Write to EPS file...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Picture_writeToEpsFile);
-		praat_addMenuCommand (U"Picture", U"File", U"Save as fontless EPS file (XIPA)...", nullptr, 1, DO_Picture_writeToFontlessEpsFile_xipa);
-		praat_addMenuCommand (U"Picture", U"File", U"Write to fontless EPS file (XIPA)...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Picture_writeToFontlessEpsFile_xipa);
-		praat_addMenuCommand (U"Picture", U"File", U"Save as fontless EPS file (SILIPA)...", nullptr, 1, DO_Picture_writeToFontlessEpsFile_silipa);
-		praat_addMenuCommand (U"Picture", U"File", U"Write to fontless EPS file (SILIPA)...", nullptr, praat_HIDDEN + praat_DEPTH_1, DO_Picture_writeToFontlessEpsFile_silipa);
+		praat_addMenuCommand (U"Picture", U"File", U"PostScript settings...", nullptr, praat_DEPTH_1 | praat_NO_API, GRAPHICS_PostScript_settings);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as EPS file...", nullptr, 1, GRAPHICS_Picture_writeToEpsFile);
+		praat_addMenuCommand (U"Picture", U"File",   U"Write to EPS file...", U"*Save as EPS file...", praat_DEPTH_1 | praat_DEPRECATED_2011, GRAPHICS_Picture_writeToEpsFile);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as fontless EPS file (XIPA)...", nullptr, 1, GRAPHICS_Picture_writeToFontlessEpsFile_xipa);
+		praat_addMenuCommand (U"Picture", U"File",   U"Write to fontless EPS file (XIPA)...", U"*Save as fontless EPS file (XIPA)...", praat_DEPTH_1 | praat_DEPRECATED_2011, GRAPHICS_Picture_writeToFontlessEpsFile_xipa);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as fontless EPS file (SILIPA)...", nullptr, 1, GRAPHICS_Picture_writeToFontlessEpsFile_silipa);
+		praat_addMenuCommand (U"Picture", U"File",   U"Write to fontless EPS file (SILIPA)...", U"*Save as fontless EPS file (SILIPA)...", praat_DEPTH_1 | praat_DEPRECATED_2011, GRAPHICS_Picture_writeToFontlessEpsFile_silipa);
 	#ifdef _WIN32
-		praat_addMenuCommand (U"Picture", U"File", U"Save as Windows metafile...", nullptr, 0, DO_Picture_writeToWindowsMetafile);
-		praat_addMenuCommand (U"Picture", U"File", U"Write to Windows metafile...", nullptr, praat_HIDDEN, DO_Picture_writeToWindowsMetafile);
+		praat_addMenuCommand (U"Picture", U"File", U"Save as Windows metafile...", nullptr, 0, GRAPHICS_Picture_writeToWindowsMetafile);
+		praat_addMenuCommand (U"Picture", U"File",   U"Write to Windows metafile...", U"*Save as Windows metafile...", praat_DEPRECATED_2011, GRAPHICS_Picture_writeToWindowsMetafile);
 	#endif
 	praat_addMenuCommand (U"Picture", U"File", U"-- praat picture file --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"File", U"Read from praat picture file...", nullptr, 0, DO_Picture_readFromPraatPictureFile);
-	praat_addMenuCommand (U"Picture", U"File", U"Save as praat picture file...", nullptr, 0, DO_Picture_writeToPraatPictureFile);
-	praat_addMenuCommand (U"Picture", U"File", U"Write to praat picture file...", nullptr, praat_HIDDEN, DO_Picture_writeToPraatPictureFile);
+	praat_addMenuCommand (U"Picture", U"File", U"Read from praat picture file...", nullptr, 0, GRAPHICS_Picture_readFromPraatPictureFile);
+	praat_addMenuCommand (U"Picture", U"File", U"Save as praat picture file...", nullptr, 0, GRAPHICS_Picture_writeToPraatPictureFile);
+	praat_addMenuCommand (U"Picture", U"File",   U"Write to praat picture file...", U"*Save as praat picture file...", praat_DEPRECATED_2011, GRAPHICS_Picture_writeToPraatPictureFile);
 	praat_addMenuCommand (U"Picture", U"File", U"-- print --", nullptr, 0, nullptr);
 	#if defined (macintosh)
-		praat_addMenuCommand (U"Picture", U"File", U"Page setup...", nullptr, 0, DO_Page_setup);
+		praat_addMenuCommand (U"Picture", U"File", U"Page setup...", nullptr, praat_NO_API, GRAPHICS_Page_setup);
 	#endif
-	praat_addMenuCommand (U"Picture", U"File", U"Print...", nullptr, 'P', DO_Print);
+	praat_addMenuCommand (U"Picture", U"File", U"Print...", nullptr, 'P' | praat_NO_API, GRAPHICS_Print);
 
-	praat_addMenuCommand (U"Picture", U"Edit", U"Undo", nullptr, 'Z', DO_Undo);
+	praat_addMenuCommand (U"Picture", U"Edit", U"Undo", nullptr, 'Z' | praat_NO_API, GRAPHICS_Undo);
 	#if defined (macintosh) || defined (_WIN32)
 		praat_addMenuCommand (U"Picture", U"Edit", U"-- clipboard --", nullptr, 0, nullptr);
-		praat_addMenuCommand (U"Picture", U"Edit", U"Copy to clipboard", nullptr, 'C', DO_Copy_picture_to_clipboard);
+		praat_addMenuCommand (U"Picture", U"Edit", U"Copy to clipboard", nullptr, 'C' | praat_NO_API, GRAPHICS_Copy_picture_to_clipboard);
 	#endif
 	praat_addMenuCommand (U"Picture", U"Edit", U"-- erase --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Edit", U"Erase all", nullptr, 'E', DO_Erase_all);
+	praat_addMenuCommand (U"Picture", U"Edit", U"Erase all", nullptr, 'E', GRAPHICS_Erase_all);
 
-	praat_addMenuCommand (U"Picture", U"Margins", U"Draw inner box", nullptr, 0, DO_DrawInnerBox);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Draw inner box", nullptr, 0, GRAPHICS_DrawInnerBox);
 	praat_addMenuCommand (U"Picture", U"Margins", U"-- text --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Text left...", nullptr, 0, DO_Text_left);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Text right...", nullptr, 0, DO_Text_right);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Text top...", nullptr, 0, DO_Text_top);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Text bottom...", nullptr, 0, DO_Text_bottom);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Text left...", nullptr, 0, GRAPHICS_TextLeft);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Text right...", nullptr, 0, GRAPHICS_TextRight);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Text top...", nullptr, 0, GRAPHICS_TextTop);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Text bottom...", nullptr, 0, GRAPHICS_TextBottom);
 	praat_addMenuCommand (U"Picture", U"Margins", U"-- marks every --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks left every...", nullptr, 0, DO_Marks_left_every);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks right every...", nullptr, 0, DO_Marks_right_every);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks bottom every...", nullptr, 0, DO_Marks_bottom_every);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks top every...", nullptr, 0, DO_Marks_top_every);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks left every...", nullptr, 0, GRAPHICS_MarksLeftEvery);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks right every...", nullptr, 0, GRAPHICS_MarksRightEvery);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks bottom every...", nullptr, 0, GRAPHICS_MarksBottomEvery);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks top every...", nullptr, 0, GRAPHICS_MarksTopEvery);
 	praat_addMenuCommand (U"Picture", U"Margins", U"-- one mark --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One mark left...", nullptr, 0, DO_Mark_left);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One mark right...", nullptr, 0, DO_Mark_right);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One mark bottom...", nullptr, 0, DO_Mark_bottom);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One mark top...", nullptr, 0, DO_Mark_top);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One mark left...", nullptr, 0, GRAPHICS_OneMarkLeft);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One mark right...", nullptr, 0, GRAPHICS_OneMarkRight);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One mark bottom...", nullptr, 0, GRAPHICS_OneMarkBottom);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One mark top...", nullptr, 0, GRAPHICS_OneMarkTop);
 	praat_addMenuCommand (U"Picture", U"Margins", U"-- marks --", nullptr, 0, nullptr);
 	praat_addMenuCommand (U"Picture", U"Margins", U"Marks", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks left...", nullptr, 1, DO_Marks_left);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks right...", nullptr, 1, DO_Marks_right);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks bottom...", nullptr, 1, DO_Marks_bottom);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Marks top...", nullptr, 1, DO_Marks_top);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks left...", nullptr, 1, GRAPHICS_MarksLeft);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks right...", nullptr, 1, GRAPHICS_MarksRight);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks bottom...", nullptr, 1, GRAPHICS_MarksBottom);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Marks top...", nullptr, 1, GRAPHICS_MarksTop);
 	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks left...", nullptr, 1, DO_marksLeftLogarithmic);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks right...", nullptr, 1, DO_marksRightLogarithmic);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks bottom...", nullptr, 1, DO_marksBottomLogarithmic);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks top...", nullptr, 1, DO_marksTopLogarithmic);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks left...", nullptr, 1, GRAPHICS_LogarithmicMarksLeft);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks right...", nullptr, 1, GRAPHICS_LogarithmicMarksRight);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks bottom...", nullptr, 1, GRAPHICS_LogarithmicMarksBottom);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Logarithmic marks top...", nullptr, 1, GRAPHICS_LogarithmicMarksTop);
 	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark left...", nullptr, 1, DO_LogarithmicMark_left);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark right...", nullptr, 1, DO_LogarithmicMark_right);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark bottom...", nullptr, 1, DO_LogarithmicMark_bottom);
-	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark top...", nullptr, 1, DO_LogarithmicMark_top);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark left...", nullptr, 1, GRAPHICS_OneLogarithmicMarkLeft);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark right...", nullptr, 1, GRAPHICS_OneLogarithmicMarkRight);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark bottom...", nullptr, 1, GRAPHICS_OneLogarithmicMarkBottom);
+	praat_addMenuCommand (U"Picture", U"Margins", U"One logarithmic mark top...", nullptr, 1, GRAPHICS_OneLogarithmicMarkTop);
 	praat_addMenuCommand (U"Picture", U"Margins", U"-- axes --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Margins", U"Axes...", nullptr, 0, DO_Axes);
-
-	praat_addMenuCommand (U"Picture", U"World", U"Text...", nullptr, 0, DO_Text);
-	praat_addMenuCommand (U"Picture", U"World", U"Text special...", nullptr, 0, DO_Text_special);
-	praat_addMenuCommand (U"Picture", U"World", U"-- line --", nullptr, 0, 0);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw line...", nullptr, 0, DO_DrawLine);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw arrow...", nullptr, 0, DO_DrawArrow);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw two-way arrow...", nullptr, 0, DO_DrawDoubleArrow);
+	praat_addMenuCommand (U"Picture", U"Margins", U"Axes...", nullptr, 0, GRAPHICS_Axes);
+
+	praat_addMenuCommand (U"Picture", U"World", U"Text...", nullptr, 0, GRAPHICS_Text);
+	praat_addMenuCommand (U"Picture", U"World", U"Text special...", nullptr, 0, GRAPHICS_TextSpecial);
+	praat_addMenuCommand (U"Picture", U"World", U"-- line --", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw line...", nullptr, 0, GRAPHICS_DrawLine);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw arrow...", nullptr, 0, GRAPHICS_DrawArrow);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw two-way arrow...", nullptr, 0, GRAPHICS_DrawDoubleArrow);
 	praat_addMenuCommand (U"Picture", U"World", U"-- function --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw function...", nullptr, 0, DO_DrawFunction);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw function...", nullptr, 0, GRAPHICS_DrawFunction);
 	praat_addMenuCommand (U"Picture", U"World", U"-- rectangle --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw rectangle...", nullptr, 0, DO_DrawRectangle);
-	praat_addMenuCommand (U"Picture", U"World", U"Paint rectangle...", nullptr, 0, DO_PaintRectangle);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw rounded rectangle...", nullptr, 0, DO_DrawRoundedRectangle);
-	praat_addMenuCommand (U"Picture", U"World", U"Paint rounded rectangle...", nullptr, 0, DO_PaintRoundedRectangle);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw rectangle...", nullptr, 0, GRAPHICS_DrawRectangle);
+	praat_addMenuCommand (U"Picture", U"World", U"Paint rectangle...", nullptr, 0, GRAPHICS_PaintRectangle);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw rounded rectangle...", nullptr, 0, GRAPHICS_DrawRoundedRectangle);
+	praat_addMenuCommand (U"Picture", U"World", U"Paint rounded rectangle...", nullptr, 0, GRAPHICS_PaintRoundedRectangle);
 	praat_addMenuCommand (U"Picture", U"World", U"-- arc --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw arc...", nullptr, 0, DO_DrawArc);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw ellipse...", nullptr, 0, DO_DrawEllipse);
-	praat_addMenuCommand (U"Picture", U"World", U"Paint ellipse...", nullptr, 0, DO_PaintEllipse);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw circle...", nullptr, 0, DO_DrawCircle);
-	praat_addMenuCommand (U"Picture", U"World", U"Paint circle...", nullptr, 0, DO_PaintCircle);
-	praat_addMenuCommand (U"Picture", U"World", U"Draw circle (mm)...", nullptr, 0, DO_DrawCircle_mm);
-	praat_addMenuCommand (U"Picture", U"World", U"Paint circle (mm)...", nullptr, 0, DO_PaintCircle_mm);
-	praat_addMenuCommand (U"Picture", U"World", U"-- picture --", nullptr, 0, 0);
-	praat_addMenuCommand (U"Picture", U"World", U"Insert picture from file...", nullptr, 0, DO_InsertPictureFromFile);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw arc...", nullptr, 0, GRAPHICS_DrawArc);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw ellipse...", nullptr, 0, GRAPHICS_DrawEllipse);
+	praat_addMenuCommand (U"Picture", U"World", U"Paint ellipse...", nullptr, 0, GRAPHICS_PaintEllipse);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw circle...", nullptr, 0, GRAPHICS_DrawCircle);
+	praat_addMenuCommand (U"Picture", U"World", U"Paint circle...", nullptr, 0, GRAPHICS_PaintCircle);
+	praat_addMenuCommand (U"Picture", U"World", U"Draw circle (mm)...", nullptr, 0, GRAPHICS_DrawCircle_mm);
+	praat_addMenuCommand (U"Picture", U"World", U"Paint circle (mm)...", nullptr, 0, GRAPHICS_PaintCircle_mm);
+	praat_addMenuCommand (U"Picture", U"World", U"-- picture --", nullptr, 0, nullptr);
+	praat_addMenuCommand (U"Picture", U"World", U"Insert picture from file...", nullptr, 0, GRAPHICS_InsertPictureFromFile);
 	praat_addMenuCommand (U"Picture", U"World", U"-- axes --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"World", U"Axes...", nullptr, 0, DO_Axes);
+	praat_addMenuCommand (U"Picture", U"World", U"Axes...", nullptr, 0, GRAPHICS_Axes);
 	praat_addMenuCommand (U"Picture", U"World", U"Measure", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"World", U"Horizontal mm to wc...", nullptr, 1, DO_dxMMtoWC);
-	praat_addMenuCommand (U"Picture", U"World", U"Horizontal wc to mm...", nullptr, 1, DO_dxWCtoMM);
-	praat_addMenuCommand (U"Picture", U"World", U"Vertical mm to wc...", nullptr, 1, DO_dyMMtoWC);
-	praat_addMenuCommand (U"Picture", U"World", U"Vertical wc to mm...", nullptr, 1, DO_dyWCtoMM);
+	praat_addMenuCommand (U"Picture", U"World", U"Horizontal mm to world coordinates...", nullptr, 1, GRAPHICS_HorizontalMmToWorldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World",   U"Horizontal mm to wc...", U"*Horizontal mm to world coordinates...", praat_DEPTH_1 | praat_DEPRECATED_2016, GRAPHICS_HorizontalMmToWorldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World", U"Horizontal world coordinates to mm...", nullptr, 1, GRAPHICS_HorizontalWorldCoordinatesToMm);
+	praat_addMenuCommand (U"Picture", U"World",   U"Horizontal wc to mm...", U"*Horizontal world coordinates to mm...", praat_DEPTH_1 | praat_DEPRECATED_2016, GRAPHICS_HorizontalWorldCoordinatesToMm);
+	praat_addMenuCommand (U"Picture", U"World", U"Vertical mm to world coordinates...", nullptr, 1, GRAPHICS_VerticalMmToWorldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World",   U"Vertical mm to wc...", U"*Vertical mm to world coordinates...", praat_DEPTH_1 | praat_DEPRECATED_2016, GRAPHICS_VerticalMmToWorldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World", U"Vertical world coordinates to mm...", nullptr, 1, GRAPHICS_VerticalWorldCoordinatesToMm);
+	praat_addMenuCommand (U"Picture", U"World",   U"Vertical wc to mm...", U"*Vertical world coordinates to mm...", praat_DEPTH_1 | praat_DEPRECATED_2016, GRAPHICS_VerticalWorldCoordinatesToMm);
 	praat_addMenuCommand (U"Picture", U"World", U"-- text measure --", nullptr, 1, nullptr);
-	praat_addMenuCommand (U"Picture", U"World", U"Text width (wc)...", nullptr, 1, DO_textWidth_wc);
-	praat_addMenuCommand (U"Picture", U"World", U"Text width (mm)...", nullptr, 1, DO_textWidth_mm);
-	praat_addMenuCommand (U"Picture", U"World", U"PostScript text width (wc)...", nullptr, 1, DO_textWidth_ps_wc);
-	praat_addMenuCommand (U"Picture", U"World", U"PostScript text width (mm)...", nullptr, 1, DO_textWidth_ps_mm);
-
-	praatButton_innerViewport = praat_addMenuCommand (U"Picture", U"Select", U"Mouse selects inner viewport", nullptr, praat_RADIO_FIRST, DO_MouseSelectsInnerViewport);
-	praatButton_outerViewport = praat_addMenuCommand (U"Picture", U"Select", U"Mouse selects outer viewport", nullptr, praat_RADIO_NEXT, DO_MouseSelectsOuterViewport);
+	praat_addMenuCommand (U"Picture", U"World", U"Text width (world coordinates)...", nullptr, 1, GRAPHICS_TextWidth_worldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World",   U"Text width (wc)...", U"*Text width (world coordinates)...", praat_DEPTH_1 | praat_DEPRECATED_2016, GRAPHICS_TextWidth_worldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World", U"Text width (mm)...", nullptr, 1, GRAPHICS_TextWidth_mm);
+	praat_addMenuCommand (U"Picture", U"World", U"PostScript text width (world coordinates)...", nullptr, 1, GRAPHICS_PostScriptTextWidth_worldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World",   U"PostScript text width (wc)...", U"*PostScript text width (world coordinates)...", praat_DEPTH_1 | praat_DEPRECATED_2016, GRAPHICS_PostScriptTextWidth_worldCoordinates);
+	praat_addMenuCommand (U"Picture", U"World", U"PostScript text width (mm)...", nullptr, 1, GRAPHICS_PostScriptTextWidth_mm);
+
+	praatButton_innerViewport = praat_addMenuCommand (U"Picture", U"Select", U"Mouse selects inner viewport", nullptr, praat_RADIO_FIRST | praat_NO_API, GRAPHICS_MouseSelectsInnerViewport);
+	praatButton_outerViewport = praat_addMenuCommand (U"Picture", U"Select", U"Mouse selects outer viewport", nullptr, praat_RADIO_NEXT | praat_NO_API, GRAPHICS_MouseSelectsOuterViewport);
 	praat_addMenuCommand (U"Picture", U"Select", U"-- select --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Select", U"Select inner viewport...", nullptr, 0, DO_SelectInnerViewport);
-	praat_addMenuCommand (U"Picture", U"Select", U"Select outer viewport...", nullptr, 0, DO_SelectOuterViewport);
-	praat_addMenuCommand (U"Picture", U"Select", U"Viewport...", nullptr, praat_HIDDEN, DO_SelectOuterViewport);
+	praat_addMenuCommand (U"Picture", U"Select", U"Select inner viewport...", nullptr, 0, GRAPHICS_SelectInnerViewport);
+	praat_addMenuCommand (U"Picture", U"Select", U"Select outer viewport...", nullptr, 0, GRAPHICS_SelectOuterViewport);
+	praat_addMenuCommand (U"Picture", U"Select", U"Viewport...", U"*Select outer viewport...", praat_DEPRECATED_2004, GRAPHICS_SelectOuterViewport);
 	praat_addMenuCommand (U"Picture", U"Select", U"-- viewport drawing --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Select", U"Viewport text...", nullptr, 0, DO_ViewportText);
+	praat_addMenuCommand (U"Picture", U"Select", U"Viewport text...", nullptr, 0, GRAPHICS_ViewportText);
 
-	praatButton_lines [Graphics_DRAWN] = praat_addMenuCommand (U"Picture", U"Pen", U"Solid line", nullptr, praat_RADIO_FIRST, DO_Solid_line);
-	praat_addMenuCommand (U"Picture", U"Pen", U"Plain line", nullptr, praat_RADIO_NEXT | praat_HIDDEN, DO_Solid_line);
-	praatButton_lines [Graphics_DOTTED] = praat_addMenuCommand (U"Picture", U"Pen", U"Dotted line", nullptr, praat_RADIO_NEXT, DO_Dotted_line);
-	praatButton_lines [Graphics_DASHED] = praat_addMenuCommand (U"Picture", U"Pen", U"Dashed line", nullptr, praat_RADIO_NEXT, DO_Dashed_line);
-	praatButton_lines [Graphics_DASHED_DOTTED] = praat_addMenuCommand (U"Picture", U"Pen", U"Dashed-dotted line", nullptr, praat_RADIO_NEXT, DO_Dashed_dotted_line);
+	praatButton_lines [Graphics_DRAWN] = praat_addMenuCommand (U"Picture", U"Pen", U"Solid line", nullptr, praat_RADIO_FIRST, GRAPHICS_Solid_line);
+	praat_addMenuCommand (U"Picture", U"Pen", U"Plain line", nullptr, praat_RADIO_NEXT | praat_DEPRECATED_2006, GRAPHICS_Solid_line);
+	praatButton_lines [Graphics_DOTTED] = praat_addMenuCommand (U"Picture", U"Pen", U"Dotted line", nullptr, praat_RADIO_NEXT, GRAPHICS_Dotted_line);
+	praatButton_lines [Graphics_DASHED] = praat_addMenuCommand (U"Picture", U"Pen", U"Dashed line", nullptr, praat_RADIO_NEXT, GRAPHICS_Dashed_line);
+	praatButton_lines [Graphics_DASHED_DOTTED] = praat_addMenuCommand (U"Picture", U"Pen", U"Dashed-dotted line", nullptr, praat_RADIO_NEXT, GRAPHICS_Dashed_dotted_line);
 	praat_addMenuCommand (U"Picture", U"Pen", U"-- line width --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Pen", U"Line width...", nullptr, 0, DO_Line_width);
-	praat_addMenuCommand (U"Picture", U"Pen", U"Arrow size...", nullptr, 0, DO_Arrow_size);
-	praat_addMenuCommand (U"Picture", U"Pen", U"Speckle size...", nullptr, 0, DO_Speckle_size);
+	praat_addMenuCommand (U"Picture", U"Pen", U"Line width...", nullptr, 0, GRAPHICS_Line_width);
+	praat_addMenuCommand (U"Picture", U"Pen", U"Arrow size...", nullptr, 0, GRAPHICS_Arrow_size);
+	praat_addMenuCommand (U"Picture", U"Pen", U"Speckle size...", nullptr, 0, GRAPHICS_Speckle_size);
 	praat_addMenuCommand (U"Picture", U"Pen", U"-- colour --", nullptr, 0, nullptr);
-	praat_addMenuCommand (U"Picture", U"Pen", U"Colour...", nullptr, 0, DO_Colour);
-	praatButton_black = praat_addMenuCommand (U"Picture", U"Pen", U"Black", nullptr, praat_CHECKBUTTON, DO_Black);
-	praatButton_white = praat_addMenuCommand (U"Picture", U"Pen", U"White", nullptr, praat_CHECKBUTTON, DO_White);
-	praatButton_red = praat_addMenuCommand (U"Picture", U"Pen", U"Red", nullptr, praat_CHECKBUTTON, DO_Red);
-	praatButton_green = praat_addMenuCommand (U"Picture", U"Pen", U"Green", nullptr, praat_CHECKBUTTON, DO_Green);
-	praatButton_blue = praat_addMenuCommand (U"Picture", U"Pen", U"Blue", nullptr, praat_CHECKBUTTON, DO_Blue);
-	praatButton_yellow = praat_addMenuCommand (U"Picture", U"Pen", U"Yellow", nullptr, praat_CHECKBUTTON, DO_Yellow);
-	praatButton_cyan = praat_addMenuCommand (U"Picture", U"Pen", U"Cyan", nullptr, praat_CHECKBUTTON, DO_Cyan);
-	praatButton_magenta = praat_addMenuCommand (U"Picture", U"Pen", U"Magenta", nullptr, praat_CHECKBUTTON, DO_Magenta);
-	praatButton_maroon = praat_addMenuCommand (U"Picture", U"Pen", U"Maroon", nullptr, praat_CHECKBUTTON, DO_Maroon);
-	praatButton_lime = praat_addMenuCommand (U"Picture", U"Pen", U"Lime", nullptr, praat_CHECKBUTTON, DO_Lime);
-	praatButton_navy = praat_addMenuCommand (U"Picture", U"Pen", U"Navy", nullptr, praat_CHECKBUTTON, DO_Navy);
-	praatButton_teal = praat_addMenuCommand (U"Picture", U"Pen", U"Teal", nullptr, praat_CHECKBUTTON, DO_Teal);
-	praatButton_purple = praat_addMenuCommand (U"Picture", U"Pen", U"Purple", nullptr, praat_CHECKBUTTON, DO_Purple);
-	praatButton_olive = praat_addMenuCommand (U"Picture", U"Pen", U"Olive", nullptr, praat_CHECKBUTTON, DO_Olive);
-	praatButton_pink = praat_addMenuCommand (U"Picture", U"Pen", U"Pink", nullptr, praat_CHECKBUTTON, DO_Pink);
-	praatButton_silver = praat_addMenuCommand (U"Picture", U"Pen", U"Silver", nullptr, praat_CHECKBUTTON, DO_Silver);
-	praatButton_grey = praat_addMenuCommand (U"Picture", U"Pen", U"Grey", nullptr, praat_CHECKBUTTON, DO_Grey);
-
-	praat_addMenuCommand (U"Picture", U"Font", U"Font size...", nullptr, 0, DO_Font_size);
-	praatButton_10 = praat_addMenuCommand (U"Picture", U"Font", U"10", nullptr, praat_CHECKBUTTON, DO_10);
-	praatButton_12 = praat_addMenuCommand (U"Picture", U"Font", U"12", nullptr, praat_CHECKBUTTON, DO_12);
-	praatButton_14 = praat_addMenuCommand (U"Picture", U"Font", U"14", nullptr, praat_CHECKBUTTON, DO_14);
-	praatButton_18 = praat_addMenuCommand (U"Picture", U"Font", U"18", nullptr, praat_CHECKBUTTON, DO_18);
-	praatButton_24 = praat_addMenuCommand (U"Picture", U"Font", U"24", nullptr, praat_CHECKBUTTON, DO_24);
+	praat_addMenuCommand (U"Picture", U"Pen", U"Colour...", nullptr, 0, GRAPHICS_Colour);
+	praatButton_black = praat_addMenuCommand (U"Picture", U"Pen", U"Black", nullptr, praat_CHECKBUTTON, GRAPHICS_Black);
+	praatButton_white = praat_addMenuCommand (U"Picture", U"Pen", U"White", nullptr, praat_CHECKBUTTON, GRAPHICS_White);
+	praatButton_red = praat_addMenuCommand (U"Picture", U"Pen", U"Red", nullptr, praat_CHECKBUTTON, GRAPHICS_Red);
+	praatButton_green = praat_addMenuCommand (U"Picture", U"Pen", U"Green", nullptr, praat_CHECKBUTTON, GRAPHICS_Green);
+	praatButton_blue = praat_addMenuCommand (U"Picture", U"Pen", U"Blue", nullptr, praat_CHECKBUTTON, GRAPHICS_Blue);
+	praatButton_yellow = praat_addMenuCommand (U"Picture", U"Pen", U"Yellow", nullptr, praat_CHECKBUTTON, GRAPHICS_Yellow);
+	praatButton_cyan = praat_addMenuCommand (U"Picture", U"Pen", U"Cyan", nullptr, praat_CHECKBUTTON, GRAPHICS_Cyan);
+	praatButton_magenta = praat_addMenuCommand (U"Picture", U"Pen", U"Magenta", nullptr, praat_CHECKBUTTON, GRAPHICS_Magenta);
+	praatButton_maroon = praat_addMenuCommand (U"Picture", U"Pen", U"Maroon", nullptr, praat_CHECKBUTTON, GRAPHICS_Maroon);
+	praatButton_lime = praat_addMenuCommand (U"Picture", U"Pen", U"Lime", nullptr, praat_CHECKBUTTON, GRAPHICS_Lime);
+	praatButton_navy = praat_addMenuCommand (U"Picture", U"Pen", U"Navy", nullptr, praat_CHECKBUTTON, GRAPHICS_Navy);
+	praatButton_teal = praat_addMenuCommand (U"Picture", U"Pen", U"Teal", nullptr, praat_CHECKBUTTON, GRAPHICS_Teal);
+	praatButton_purple = praat_addMenuCommand (U"Picture", U"Pen", U"Purple", nullptr, praat_CHECKBUTTON, GRAPHICS_Purple);
+	praatButton_olive = praat_addMenuCommand (U"Picture", U"Pen", U"Olive", nullptr, praat_CHECKBUTTON, GRAPHICS_Olive);
+	praatButton_pink = praat_addMenuCommand (U"Picture", U"Pen", U"Pink", nullptr, praat_CHECKBUTTON, GRAPHICS_Pink);
+	praatButton_silver = praat_addMenuCommand (U"Picture", U"Pen", U"Silver", nullptr, praat_CHECKBUTTON, GRAPHICS_Silver);
+	praatButton_grey = praat_addMenuCommand (U"Picture", U"Pen", U"Grey", nullptr, praat_CHECKBUTTON, GRAPHICS_Grey);
+
+	praat_addMenuCommand (U"Picture", U"Font", U"Font size...", nullptr, 0, GRAPHICS_Font_size);
+	praatButton_10 = praat_addMenuCommand (U"Picture", U"Font", U"10", nullptr, praat_CHECKBUTTON | praat_NO_API, GRAPHICS_10);
+	praatButton_12 = praat_addMenuCommand (U"Picture", U"Font", U"12", nullptr, praat_CHECKBUTTON | praat_NO_API, GRAPHICS_12);
+	praatButton_14 = praat_addMenuCommand (U"Picture", U"Font", U"14", nullptr, praat_CHECKBUTTON | praat_NO_API, GRAPHICS_14);
+	praatButton_18 = praat_addMenuCommand (U"Picture", U"Font", U"18", nullptr, praat_CHECKBUTTON | praat_NO_API, GRAPHICS_18);
+	praatButton_24 = praat_addMenuCommand (U"Picture", U"Font", U"24", nullptr, praat_CHECKBUTTON | praat_NO_API, GRAPHICS_24);
 	praat_addMenuCommand (U"Picture", U"Font", U"-- font ---", nullptr, 0, nullptr);
-	praatButton_fonts [kGraphics_font_TIMES] = praat_addMenuCommand (U"Picture", U"Font", U"Times", nullptr, praat_RADIO_FIRST, DO_Times);
-	praatButton_fonts [kGraphics_font_HELVETICA] = praat_addMenuCommand (U"Picture", U"Font", U"Helvetica", nullptr, praat_RADIO_NEXT, DO_Helvetica);
-	praatButton_fonts [kGraphics_font_PALATINO] = praat_addMenuCommand (U"Picture", U"Font", U"Palatino", nullptr, praat_RADIO_NEXT, DO_Palatino);
-	praatButton_fonts [kGraphics_font_COURIER] = praat_addMenuCommand (U"Picture", U"Font", U"Courier", nullptr, praat_RADIO_NEXT, DO_Courier);
-
-	praat_addMenuCommand (U"Picture", U"Help", U"Picture window help", nullptr, '?', DO_PictureWindowHelp);
-	praat_addMenuCommand (U"Picture", U"Help", U"About special symbols", nullptr, 0, DO_AboutSpecialSymbols);
-	praat_addMenuCommand (U"Picture", U"Help", U"About text styles", nullptr, 0, DO_AboutTextStyles);
-	praat_addMenuCommand (U"Picture", U"Help", U"Phonetic symbols", nullptr, 0, DO_PhoneticSymbols);
+	praatButton_fonts [kGraphics_font_TIMES] = praat_addMenuCommand (U"Picture", U"Font", U"Times", nullptr, praat_RADIO_FIRST, GRAPHICS_Times);
+	praatButton_fonts [kGraphics_font_HELVETICA] = praat_addMenuCommand (U"Picture", U"Font", U"Helvetica", nullptr, praat_RADIO_NEXT, GRAPHICS_Helvetica);
+	praatButton_fonts [kGraphics_font_PALATINO] = praat_addMenuCommand (U"Picture", U"Font", U"Palatino", nullptr, praat_RADIO_NEXT, GRAPHICS_Palatino);
+	praatButton_fonts [kGraphics_font_COURIER] = praat_addMenuCommand (U"Picture", U"Font", U"Courier", nullptr, praat_RADIO_NEXT, GRAPHICS_Courier);
+
+	praat_addMenuCommand (U"Picture", U"Help", U"Picture window help", nullptr, '?', HELP_PictureWindowHelp);
+	praat_addMenuCommand (U"Picture", U"Help", U"About special symbols", nullptr, 0, HELP_AboutSpecialSymbols);
+	praat_addMenuCommand (U"Picture", U"Help", U"About text styles", nullptr, 0, HELP_AboutTextStyles);
+	praat_addMenuCommand (U"Picture", U"Help", U"Phonetic symbols", nullptr, 0, HELP_PhoneticSymbols);
 	praat_addMenuCommand (U"Picture", U"Help", U"-- manual --", nullptr, 0, nullptr);
 	praat_addMenuCommand (U"Picture", U"Help",
 		Melder_cat (U"Search ", praatP.title, U" manual..."),
-		nullptr, 'M', DO_SearchManual);
+		nullptr, 'M', HELP_SearchManual_Picture);
 
 	if (! theCurrentPraatApplication -> batch) {
 		width = height = resolution * 12;
diff --git a/sys/praat_statistics.cpp b/sys/praat_statistics.cpp
index 5eda802..814b696 100644
--- a/sys/praat_statistics.cpp
+++ b/sys/praat_statistics.cpp
@@ -1,6 +1,6 @@
 /* praat_statistics.cpp
  *
- * Copyright (C) 1992-2012,2014,2015 Paul Boersma
+ * Copyright (C) 1992-2012,2014,2015,2016 Paul Boersma
  *
  * This code is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/sys/praat_version.h b/sys/praat_version.h
index 3886ba7..af9f391 100644
--- a/sys/praat_version.h
+++ b/sys/praat_version.h
@@ -1,5 +1,5 @@
-#define PRAAT_VERSION_STR 6.0.21
-#define PRAAT_VERSION_NUM 6021
+#define PRAAT_VERSION_STR 6.0.22
+#define PRAAT_VERSION_NUM 6022
 #define PRAAT_YEAR 2016
-#define PRAAT_MONTH September
-#define PRAAT_DAY 25
+#define PRAAT_MONTH November
+#define PRAAT_DAY 15
diff --git a/test/contrib/kNN.praat b/test/contrib/kNN.praat
index 30ba278..1df8b31 100644
--- a/test/contrib/kNN.praat
+++ b/test/contrib/kNN.praat
@@ -6,17 +6,17 @@ for i from 1 to 30
 	select FFNet 4-3
 	select Pattern iris
 	plus Categories iris
-	To KNN Classifier... Classifier Sequential
-	temp = Get accuracy estimate... "Leave one out" 10 Inversed squared distance
+	To KNN Classifier: "Classifier", "Sequential"
+	temp = Get accuracy estimate: "Leave one out", 10, "Inverse squared distance"
 	a1 = a1 + (temp - a1) / i
 	Shuffle
-	temp = Get accuracy estimate... "10-fold cross-validation" 10 Inversed squared distance
+	temp = Get accuracy estimate: "10-fold cross-validation", 10, "Inverse squared distance"
 	a2 = a2 + (temp - a2) / i
 	Prune... 1 1 10
 	select Pattern iris
 	plus Categories iris
 	plus KNN Classifier
-	temp = Evaluate... 10 Inversed squared distance
+	temp = Evaluate: 10, "Inverse squared distance"
 	a3 = a3 + (temp - a3) / i
 	select FFNet 4-3
 	plus Pattern iris
diff --git a/test/fon Exp/Sounds/M1F1-float32-AFsp.wav b/test/fon ExperimentMFC/Sounds/M1F1-float32-AFsp.wav
similarity index 100%
rename from test/fon Exp/Sounds/M1F1-float32-AFsp.wav
rename to test/fon ExperimentMFC/Sounds/M1F1-float32-AFsp.wav
diff --git a/test/fon Exp/Sounds/again.wav b/test/fon ExperimentMFC/Sounds/again.wav
similarity index 100%
rename from test/fon Exp/Sounds/again.wav
rename to test/fon ExperimentMFC/Sounds/again.wav
diff --git a/test/fon Exp/Sounds/heed.wav b/test/fon ExperimentMFC/Sounds/heed.wav
similarity index 100%
rename from test/fon Exp/Sounds/heed.wav
rename to test/fon ExperimentMFC/Sounds/heed.wav
diff --git a/test/fon Exp/Sounds/hid.wav b/test/fon ExperimentMFC/Sounds/hid.wav
similarity index 100%
rename from test/fon Exp/Sounds/hid.wav
rename to test/fon ExperimentMFC/Sounds/hid.wav
diff --git a/test/fon Exp/Sounds/hood.wav b/test/fon ExperimentMFC/Sounds/hood.wav
similarity index 100%
rename from test/fon Exp/Sounds/hood.wav
rename to test/fon ExperimentMFC/Sounds/hood.wav
diff --git a/test/fon Exp/Sounds/hud.wav b/test/fon ExperimentMFC/Sounds/hud.wav
similarity index 100%
rename from test/fon Exp/Sounds/hud.wav
rename to test/fon ExperimentMFC/Sounds/hud.wav
diff --git a/test/fon Exp/Sounds/weSayTheWord.wav b/test/fon ExperimentMFC/Sounds/weSayTheWord.wav
similarity index 100%
rename from test/fon Exp/Sounds/weSayTheWord.wav
rename to test/fon ExperimentMFC/Sounds/weSayTheWord.wav
diff --git a/test/fon Exp/continuousGoodness.ExperimentMFC b/test/fon ExperimentMFC/continuousGoodness.ExperimentMFC
similarity index 100%
rename from test/fon Exp/continuousGoodness.ExperimentMFC
rename to test/fon ExperimentMFC/continuousGoodness.ExperimentMFC
diff --git a/test/fon Exp/csl.ExperimentMFC b/test/fon ExperimentMFC/csl.ExperimentMFC
similarity index 100%
rename from test/fon Exp/csl.ExperimentMFC
rename to test/fon ExperimentMFC/csl.ExperimentMFC
diff --git a/test/fon Exp/experimentMFC.praat b/test/fon ExperimentMFC/experimentMFC.praat
similarity index 100%
rename from test/fon Exp/experimentMFC.praat
rename to test/fon ExperimentMFC/experimentMFC.praat
diff --git a/test/fon Exp/hoofdletters.ExperimentMFC b/test/fon ExperimentMFC/hoofdletters.ExperimentMFC
similarity index 100%
rename from test/fon Exp/hoofdletters.ExperimentMFC
rename to test/fon ExperimentMFC/hoofdletters.ExperimentMFC
diff --git a/test/fon Exp/pictures.ExperimentMFC b/test/fon ExperimentMFC/pictures.ExperimentMFC
similarity index 100%
rename from test/fon Exp/pictures.ExperimentMFC
rename to test/fon ExperimentMFC/pictures.ExperimentMFC
diff --git a/test/fon Exp/pictures/paul.jpg b/test/fon ExperimentMFC/pictures/paul.jpg
similarity index 100%
rename from test/fon Exp/pictures/paul.jpg
rename to test/fon ExperimentMFC/pictures/paul.jpg
diff --git a/test/fon Exp/pictures/silke.jpg b/test/fon ExperimentMFC/pictures/silke.jpg
similarity index 100%
rename from test/fon Exp/pictures/silke.jpg
rename to test/fon ExperimentMFC/pictures/silke.jpg
diff --git a/test/fon Exp/simplest.ExperimentMFC b/test/fon ExperimentMFC/simplest.ExperimentMFC
similarity index 100%
rename from test/fon Exp/simplest.ExperimentMFC
rename to test/fon ExperimentMFC/simplest.ExperimentMFC
diff --git a/test/fon Exp/simplest_broken.ExperimentMFC b/test/fon ExperimentMFC/simplest_broken.ExperimentMFC
similarity index 100%
rename from test/fon Exp/simplest_broken.ExperimentMFC
rename to test/fon ExperimentMFC/simplest_broken.ExperimentMFC
diff --git a/test/fon Exp/simplest_missing.ExperimentMFC b/test/fon ExperimentMFC/simplest_missing.ExperimentMFC
similarity index 100%
rename from test/fon Exp/simplest_missing.ExperimentMFC
rename to test/fon ExperimentMFC/simplest_missing.ExperimentMFC
diff --git a/test/fon Exp/stereo.ExperimentMFC b/test/fon ExperimentMFC/stereo.ExperimentMFC
similarity index 100%
rename from test/fon Exp/stereo.ExperimentMFC
rename to test/fon ExperimentMFC/stereo.ExperimentMFC
diff --git a/test/fon Exp/test.ExperimentMFC b/test/fon ExperimentMFC/test.ExperimentMFC
similarity index 100%
rename from test/fon Exp/test.ExperimentMFC
rename to test/fon ExperimentMFC/test.ExperimentMFC
diff --git a/test/fon Exp/version3.ExperimentMFC b/test/fon ExperimentMFC/version3.ExperimentMFC
similarity index 100%
rename from test/fon Exp/version3.ExperimentMFC
rename to test/fon ExperimentMFC/version3.ExperimentMFC
diff --git a/test/fon Exp/version4.ExperimentMFC b/test/fon ExperimentMFC/version4.ExperimentMFC
similarity index 100%
rename from test/fon Exp/version4.ExperimentMFC
rename to test/fon ExperimentMFC/version4.ExperimentMFC
diff --git a/test/fon Exp/version6.ExperimentMFC b/test/fon ExperimentMFC/version6.ExperimentMFC
similarity index 100%
rename from test/fon Exp/version6.ExperimentMFC
rename to test/fon ExperimentMFC/version6.ExperimentMFC

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/praat.git



More information about the debian-med-commit mailing list