[med-svn] [Git][med-team/praat][upstream] New upstream version 6.1.13

Rafael Laboissiere gitlab at salsa.debian.org
Tue Apr 21 16:17:33 BST 2020



Rafael Laboissiere pushed to branch upstream at Debian Med / praat


Commits:
748195cc by Rafael Laboissière at 2020-04-20T07:27:40-03:00
New upstream version 6.1.13
- - - - -


30 changed files:

- LPC/manual_LPC.cpp
- README.md
- dwsys/FileInMemoryManager.cpp
- dwsys/FileInMemoryManager.h
- dwtest/runAllTests_batch.praat
- dwtest/test_Discriminant.praat
- dwtest/test_LPC.praat
- dwtools/VowelEditor.cpp
- external/clapack/lapack/dlamch.cpp
- fon/Vector.cpp
- fon/manual_tutorials.cpp
- makefiles/makefile.defs.linux.alsa
- makefiles/makefile.defs.linux.barren
- makefiles/makefile.defs.linux.jack
- makefiles/makefile.defs.linux.nogui
- makefiles/makefile.defs.linux.pulse
- makefiles/makefile.defs.linux.rpi
- makefiles/makefile.defs.linux.silent
- makefiles/makefile.defs.mingw32
- sys/DataEditor.cpp
- sys/praat_version.h
- test/dwtools/CPPS.praat
- test/fon/stereoFormula.praat
- test/kar/unicode16.praat
- test/num/fisherQ.praat
- test/num/norm.praat
- test/runAllTests_batch.praat
- test/script/text100MB.praat
- test/stat/logisticRegression.praat
- + test/sys/bits.praat


Changes:

=====================================
LPC/manual_LPC.cpp
=====================================
@@ -768,8 +768,8 @@ DEFINITION (U"the maximum frequency subject to analysis.")
 TAG (U"##Pre-emphasis from (Hz)")
 ENTRY (U"Algorithm")
 NORMAL (U"The sound will first be resampled to twice the value of the %%Maximum frequency%, with "
-	"the algorithm described at @@Sound: Resample...|Sound: Resample at . After this, pre-emphasis is applied with the "
-	"algorithm described at @@Sound: Pre-emphasize (in-place)...|Sound: Pre-emphasize (in-place)@. For each analysis window a Gaussian "
+	"the algorithm described at @@Sound: Resample... at . After this, pre-emphasis is applied with the "
+	"algorithm described at @@Sound: Pre-emphasize (in-place)... at . For each analysis window a Gaussian "
 	"window is applied and the ##Spectrum# is calculated. The Spectrum is then transformed to a ##PowerCepstrum# with the procedure described at @@Spectrum: To PowerCepstrum at . Finally the values from the PowerCepstrum are stored in the vertical slice of the PowerCepstrogram.")
 
 MAN_END


=====================================
README.md
=====================================
@@ -229,7 +229,7 @@ so that the `bash` shell will automatically execute them whenever you start your
 
     # in Cygwin:~/.profile
     PRAAT_SOURCES="/cygdrive/z/Praats/src"
-    PRAAT_EXCLUDES='--exclude="*.xcodeproj" --exclude="Icon*" --exclude=".*"'
+    PRAAT_EXCLUDES='--exclude="*.xcodeproj" --exclude="Icon*" --exclude=".*" --exclude="*kanweg*"'
     alias praat-build="( cd ~/praats &&\
         rsync -rptvz $PRAAT_SOURCES/ $PRAAT_EXCLUDES . &&\
         cp makefiles/makefile.defs.mingw64 makefile.defs &&\
@@ -273,7 +273,7 @@ assuming that it uses the `bash` shell):
 
     # in Ubuntu:~/.bash_aliases
     PRAAT_SOURCES="/media/psf/Home/Praats/src"
-    PRAAT_EXCLUDES='--exclude="*.xcodeproj" --exclude="Icon*" --exclude=".*"'
+    PRAAT_EXCLUDES='--exclude="*.xcodeproj" --exclude="Icon*" --exclude=".*" --exclude="*kanweg*"'
     alias praat-build="( cd ~/praats &&\
         rsync -rptvz $PRAAT_SOURCES/ $PRAAT_EXCLUDES . &&\
         cp makefiles/makefile.defs.linux.pulse makefile.defs &&\
@@ -397,25 +397,29 @@ If any reader of these lines has precise instructions, we would like to know abo
 (the main problem is how to install the GTK etc libraries in the Raspberry Pi toolchain,
 or how to get `dpkg` under Ubuntu-buster to actually find `armhf` libraries).
 
-Till then, you build on the Raspberry Pi itself. On your intermediary computer, you created a folder `~/sources`.
-You send the sources there from your Mac with
+Till then, you build on the Raspberry Pi itself. Your could do that via an intermediary computer
+(analogously to what we described above for Chromebook), but you can also do it directly
+if you include your Raspberry Pi in the same local network as your Mac and switch on SSH
+on your Raspberry Pi (via Raspberry ->  `Preferences` -> `Raspberry Pi Configuration`
+-> `Interfaces` -> `SSH` -> `Enable`. You add your Mac’s public SSH key to your Raspberry Pi with
 
-    # in Mac:~/.bash_profile
-    PRAAT_SOURCES="~/Praats/src"
-    PRAAT_EXCLUDES='--exclude="*.xcodeproj" --exclude="Icon*" --exclude=".*"'
-    alias praats-mid="rsync -rptvz -e ssh $PRAAT_EXCLUDES \
-        $PRAAT_SOURCES/ yourname at fon.hum.uva.nl:~/sources"
+    # on Mac command line
+    ssh-keygen   # only if you have no SSH key yet
+    ssh-copy-id pi at 192.168.1.2   # or whatever your Pi’s static IP address is
 
-and
+On your Raspberry Pi, you create a folder `~/praats`,
+after which you can push the sources from your Mac to your Raspberry Pi with
 
-    # on Mac command line
-    praats-mid
+    # in Mac:~/.bash_profile
+    PRAAT_SOURCES="~/Praats/src"
+    PRAAT_EXCLUDES='--exclude="*.xcodeproj" --exclude="Icon*" --exclude=".*" --exclude="*kanweg*"'
+    alias praats-putpi="rsync -rptvz -e ssh $PRAAT_EXCLUDES \
+        $PRAAT_SOURCES/ pi at 192.168.1.2:~/praats"
 
-On your Raspberry Pi, you create a folder `~/praats`, and you fetch the sources there with
+On the Raspberry Pi, you define
 
     # in RaspberryPi:~/.bash_aliases
     alias praat-build="( cd ~/praats &&\
-        rsync -rptvz -e ssh yourname at fon.hum.uva.nl:~/sources/ . &&\
         cp makefiles/makefile.defs.linux.rpi makefile.defs &&\
         make -j4 )"
     alias praat="~/praats/praat"
@@ -426,11 +430,11 @@ after which you can build and run Praat with
     # on Raspberry Pi command line
     praat-run
 
-Thus, the cycle from editing Praat on the Mac to running it on your Chromebook therefore takes three steps:
+Thus, the cycle from editing Praat on the Mac to running it on your Raspberry Pi therefore takes three steps:
 
 1. edit and save the source code in Xcode on your Mac;
-2. type `praats-mid` on your Mac;
-3. type `praat-run` on your Raspberry Pi.
+2. type `praats-putpi` on your Mac;
+3. type `praat-run` on your Raspberry Pi, perhaps via `ssh -X pi at 192.168.1.2` in your Mac terminal.
 
 From clean sources this takes around 19 minutes (on a Raspberry Pi 4B),
 but if no header files change, then it can be done in approximately 20 seconds.
@@ -498,22 +502,10 @@ so that you can “upload” the four executables to the Mac with
     praatn-dist
     praatc-dist
 
-On the Raspberry Pi, you send the executable to the intermediary computer,
-which has a folder `~/builds/rpi_armv7`. On your Raspberry Pi, you define
-
-    # in RaspberryPi:~/.bash_aliases
-    alias praat-mid="rsync -tpvz ~/praats/praat yourname at fon.hum.uva.nl:/builds/rpi_armv7"
-
-so that you can “upload” the executable to the computer-in-the-middle with
-
-    # on Raspberry Pi command line
-    praat-mid
-
-After all this, you execute the following lines in the Mac `Terminal`.
-First you fetch the Raspberry Pi edition from the intermediary computer:
+You can fetch the Raspberry Pi edition directly from your Raspberry Pi:
 
     # on Mac command line
-    rsync -tpvz yourname at fon.hum.uva.nl:~/builds/rpi_armv7/praat ~/builds/rpi_armv7
+    rsync -tpvz pi at 192.168.1.2:~/praats/praat ~/builds/rpi_armv7
 
 When the folders under `~/builds`, namely `win64`, `win32`, `linux64`, `chrome64` and `rpi_armv7`
 all contain enough new executables (there should be 1, 1, 3, 1 and 1, respectively),


=====================================
dwsys/FileInMemoryManager.cpp
=====================================
@@ -679,24 +679,14 @@ int FileInMemoryManager_ungetc (FileInMemoryManager me, int character, FILE * st
 int FileInMemoryManager_fprintf (FileInMemoryManager me, FILE * stream, const char *format, ... ) {
 	(void) me;
 	va_list args;
-	size_t bufferSize = -1;
 	if (stream == stderr) {
 		va_start (args, format);
-		bufferSize = 256;
-		autovector<char> buf = newvectorraw <char> (bufferSize);
-		int sizeNeeded = vsnprintf (buf.asArgumentToFunctionThatExpectsZeroBasedArray (), bufferSize, format, args); // find the size of the needed buffer (without terminating null byte)
+		int sizeNeeded = vsnprintf (nullptr, 0, format, args); // find size of needed buffer (without final null byte)
+		const size_t bufferSize = sizeNeeded + 1;
 		va_end (args);
-		if (++ sizeNeeded > bufferSize) { 
-			buf.resize (sizeNeeded);
-			va_start (args, format);
-			(void) vsnprintf (buf.asArgumentToFunctionThatExpectsZeroBasedArray (), sizeNeeded, format, args);
-			va_end (args);
-		}
-		bufferSize = sizeNeeded;
-	} else {
-		//integer openFilesIndex = _FileInMemoryManager_getIndexInOpenFiles (me, stream); // 
+		return bufferSize;
 	}
-	return bufferSize;
+	return -1;
 }
 
 void test_FileInMemoryManager_io (void) {


=====================================
dwsys/FileInMemoryManager.h
=====================================
@@ -2,7 +2,7 @@
 #define _FileInMemoryManager_h_
 /* FileInMemoryManager.h
  *
- * Copyright (C) 2017 David Weenink
+ * Copyright (C) 2017-2020 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
@@ -57,6 +57,7 @@ size_t FileInMemoryManager_fread (FileInMemoryManager me, void *ptr, size_t size
 int FileInMemoryManager_fgetc (FileInMemoryManager me, FILE *stream);
 
 int FileInMemoryManager_fprintf (FileInMemoryManager me, FILE * stream, const char * format, ... );
+/* only returns number of bytes that would have been written or -1 in case of failure */
 
 int FileInMemoryManager_ungetc (FileInMemoryManager me, int character, FILE * stream);
 


=====================================
dwtest/runAllTests_batch.praat
=====================================
@@ -1,16 +1,26 @@
 # Praat script runAllTests_batch.praat
-# Paul Boersma 2020-04-13
+# Paul Boersma 2020-04-18
 #
 # This script runs all Praat scripts in its subdirectories.
 # This script is to be called from the command line:
-#     praat --run runAllTests.praat
+#     praat --run runAllTests_batch.praat
 #
 # Scripts containing `_GUI_` in their names are ignored.
+#
 
+#
+# Some tests require standard settings for the text input encoding:
+# files in UTF-8 format should always be readable.
+#
+Text writing preferences: "try ASCII, then UTF-16"
 if macintosh
-	executable$ = "~/builds/mac_products/Configuration64/Praat.app/Contents/MacOS/Praat --no-pref-files"
+	Text reading preferences: "try UTF-8, then MacRoman"
+elif windows
+	Text reading preferences: "try UTF-8, then Windows Latin-1"
+elif unix
+	Text reading preferences: "try UTF-8, then ISO Latin-1"
 else
-	executable$ = "../praat --no-pref-files"
+	exitScript: "Unknown operating system."
 endif
 
 writeInfoLine: "Running all tests..."
@@ -22,7 +32,9 @@ for file to numberOfFiles
 		file$ = Get string: file
 		if not index (file$, "runAllTests") and not index (file$, "_GUI_")
 			appendInfoLine: "### executing ", file$, ":"
-			runSystem: executable$, " --run """, file$, """"
+			random_initializeWithSeedUnsafelyButPredictably (5489)
+			runScript: file$
+			random_initializeSafelyAndUnpredictably()
 		endif
 	endfor
 	removeObject: files


=====================================
dwtest/test_Discriminant.praat
=====================================
@@ -19,7 +19,7 @@ appendInfoLine: tab$ + "Query old and new Discriminant"
 appendInfoLine: tab$ + "Assert old and new Discriminant classify the same"
 @classify: discriminant[1], tableOfReal, 1
 @classify: discriminant[2], tableOfReal, 2
-assert classify.fc[1] = classify.fc[2]
+assert classify.fc[1] = classify.fc[2]   ; 'classify.fc[1]' 'classify.fc[2]'
 
 procedure classify: .discriminant, .tableOfReal, .index
 	selectObject: .discriminant, .tableOfReal
@@ -32,7 +32,7 @@ endproc
 
 procedure query: .discriminant
 	for .ieigen to 3
-		.eigenvalue[.ieigen] = Get eigenvalue: .ieigen
+		.eigenvalue[.ieigen] = Get eigenvalue: .ieigen   ; 
 	endfor
 	.numberOfEigenvectors = Get number of eigenvectors
 	.dimension = Get eigenvector dimension


=====================================
dwtest/test_LPC.praat
=====================================
@@ -57,7 +57,7 @@ for imethod to 4
 	call get_formants lpcr 'method$':robust
 	deltaf2 = deltaf
 	deltab2 = deltab
-	assert deltaf2 < 0.005 and deltab2 < 0.2; ('method$':robust) 'deltaf2' 'deltab2'
+	assert deltaf2 < 0.01 and deltab2 < 0.2; ('method$':robust) 'deltaf2' 'deltab2'
 	select lpc
 	plus lpcr
 	Remove


=====================================
dwtools/VowelEditor.cpp
=====================================
@@ -549,7 +549,7 @@ static void VowelEditor_getVowelMarksFromFile (VowelEditor me) {
 
 static void VowelEditor_getMarks (VowelEditor me) {
 	autoTable te;
-	if (my p_marks_dataSet == kVowelEditor_marksDataSet::AMERICAN_ENGLISH) {   // American-English
+	if (my p_marks_dataSet == kVowelEditor_marksDataSet::AMERICAN_ENGLISH) {
 		const autoTable thee = Table_create_petersonBarney1952 ();
 		te = Table_extractRowsWhereColumn_string (thee.get(), 1, kMelder_string::EQUAL_TO,
 		  ( my p_marks_speakerType == kVowelEditor_speakerType::MAN ? U"m" :
@@ -887,7 +887,7 @@ static void menu_cb_vowelMarks (VowelEditor me, EDITOR_ARGS_FORM) {
 	EDITOR_END
 }
 
-static void menu_cb_vowelMarksFromTableFile (VowelEditor me, EDITOR_ARGS_FORM) {  // deprecated 20200404
+static void menu_cb_vowelMarksFromTableFile (VowelEditor me, EDITOR_ARGS_FORM) {
 	EDITOR_FORM_READ (U"VowelEditor: Show vowel marks from Table file", U"VowelEditor: Show vowel marks from Table file...");
 	EDITOR_DO_READ
 		pref_str32cpy2 (my pref_marks_fileName (), my p_marks_fileName, Melder_fileToPath (file));


=====================================
external/clapack/lapack/dlamch.cpp
=====================================
@@ -649,7 +649,7 @@ L10:
 double dlamc3_(double *a, double *b)
 {
     /* System generated locals */
-    double ret_val;
+    volatile double ret_val;
 
 
 /*  -- LAPACK auxiliary routine (version 3.1) -- */


=====================================
fon/Vector.cpp
=====================================
@@ -1,6 +1,6 @@
 /* Vector.cpp
  *
- * Copyright (C) 1992-2009,2011,2012,2014-2018 Paul Boersma
+ * Copyright (C) 1992-2009,2011,2012,2014-2018,2020 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,63 +22,63 @@
 // Vector::getVector () returns a channel or the average of all the channels.
 //
 double structVector :: v_getVector (integer irow, integer icol) {
-	if (icol < 1 || icol > nx)
+	if (icol < 1 || icol > our nx)
 		return 0.0;
 	if (ny == 1)
-		return z [1] [icol];   // optimization
+		return our z [1] [icol];   // optimization
 	if (irow == 0) {
-		if (ny == 2)
-			return 0.5 * (z [1] [icol] + z [2] [icol]);   // optimization
+		if (our ny == 2)
+			return 0.5 * (our z [1] [icol] + our z [2] [icol]);   // optimization
 		longdouble sum = 0.0;
-		for (integer channel = 1; channel <= ny; channel ++)
-			sum += z [channel] [icol];
-		return double (sum / ny);
+		for (integer channel = 1; channel <= our ny; channel ++)
+			sum += our z [channel] [icol];
+		return double (sum / our ny);
 	}
-	Melder_assert (irow > 0 && irow <= ny);
-	return z [irow] [icol];
+	Melder_assert (irow > 0 && irow <= our ny);
+	return our z [irow] [icol];
 }
 
 //
 // Vector::getFunction1 () returns a channel or the average of all the channels.
 //
 double structVector :: v_getFunction1 (integer irow, double x) {
-	double rcol = (x - x1) / dx + 1.0;
+	double rcol = (x - our x1) / our dx + 1.0;
 	integer icol = Melder_ifloor (rcol);
 	double dcol = rcol - icol;
 	double z1;
-	if (icol < 1 || icol > nx) {
+	if (icol < 1 || icol > our nx) {
 		z1 = 0.0;   // outside the definition region, Formula is expected to return zero
-	} else if (ny == 1) {
+	} else if (our ny == 1) {
 		z1 = z [1] [icol];   // optimization
 	} else if (irow == 0) {
-		if (ny == 2) {
-			z1 = 0.5 * (z [1] [icol] + z [2] [icol]);   // optimization
+		if (our ny == 2) {
+			z1 = 0.5 * (our z [1] [icol] + our z [2] [icol]);   // optimization
 		} else {
 			longdouble sum = 0.0;
 			for (integer channel = 1; channel <= ny; channel ++)
-				sum += z [channel] [icol];
-			z1 = double (sum / ny);
+				sum += our z [channel] [icol];
+			z1 = double (sum / our ny);
 		}
 	} else {
-		Melder_assert (irow > 0 && irow <= ny);
-		z1 = z [irow] [icol];
+		Melder_assert (irow > 0 && irow <= our ny);
+		z1 = our z [irow] [icol];
 	}
 	double z2;
-	if (icol < 0 || icol >= nx) {
+	if (icol < 0 || icol >= our nx) {
 		z2 = 0.0;   // outside the definition region, Formula is expected to return zero
-	} else if (ny == 1) {
+	} else if (our ny == 1) {
 		z2 = z [1] [icol + 1];   // optimization
 	} else if (irow == 0) {
-		if (ny == 2) {
-			z2 = 0.5 * (z [1] [icol + 1] + z [2] [icol + 1]);   // optimization
+		if (our ny == 2) {
+			z2 = 0.5 * (our z [1] [icol + 1] + our z [2] [icol + 1]);   // optimization
 		} else {
 			longdouble sum = 0.0;
-			for (integer channel = 1; channel <= ny; channel ++)
-				sum += z [channel] [icol + 1];
-			z2 = double (sum / ny);
+			for (integer channel = 1; channel <= our ny; channel ++)
+				sum += our z [channel] [icol + 1];
+			z2 = double (sum / our ny);
 		}
 	} else {
-		Melder_assert (irow > 0 && irow <= ny);
+		Melder_assert (irow > 0 && irow <= our ny);
 		z2 = z [irow] [icol + 1];
 	}
 	return (1.0 - dcol) * z1 + dcol * z2;
@@ -90,18 +90,18 @@ double structVector :: v_getValueAtSample (integer isamp, integer ilevel, int un
 //    0 <= ilevel <= my ny
 	double value;
 	if (ilevel > Vector_CHANNEL_AVERAGE) {
-		value = z [ilevel] [isamp];
-	} else if (ny == 1) {
-		value = z [1] [isamp];   // optimization
-	} else if (ny == 2) {
-		value = 0.5 * (z [1] [isamp] + z [2] [isamp]);   // optimization
+		value = our z [ilevel] [isamp];
+	} else if (our ny == 1) {
+		value = our z [1] [isamp];   // optimization
+	} else if (our ny == 2) {
+		value = 0.5 * (our z [1] [isamp] + our z [2] [isamp]);   // optimization
 	} else {
 		longdouble sum = 0.0;
-		for (integer channel = 1; channel <= ny; channel ++)
-			sum += z [channel] [isamp];
-		value = double (sum / ny);
+		for (integer channel = 1; channel <= our ny; channel ++)
+			sum += our z [channel] [isamp];
+		value = double (sum / our ny);
 	}
-	return isdefined (value) ? v_convertStandardToSpecialUnit (value, ilevel, unit) : undefined;
+	return isdefined (value) ? our v_convertStandardToSpecialUnit (value, ilevel, unit) : undefined;
 }
 
 Thing_implement (Vector, Matrix, 2);
@@ -117,14 +117,16 @@ double Vector_getValueAtX (Vector me, double x, integer ilevel, int interpolatio
 		return undefined;
 	if (ilevel > Vector_CHANNEL_AVERAGE) {
 		Melder_assert (ilevel <= my ny);
-		return NUM_interpolate_sinc (my z.row (ilevel), Sampled_xToIndex (me, x),
+		double index_real = (x - my x1) / my dx + 1.0;
+		return NUM_interpolate_sinc (my z.row (ilevel), index_real,
 			interpolation == Vector_VALUE_INTERPOLATION_SINC70 ? NUM_VALUE_INTERPOLATE_SINC70 :
 			interpolation == Vector_VALUE_INTERPOLATION_SINC700 ? NUM_VALUE_INTERPOLATE_SINC700 :
 			interpolation);
 	}
 	longdouble sum = 0.0;
 	for (integer ichan = 1; ichan <= my ny; ichan ++) {
-		sum += NUM_interpolate_sinc (my z.row (ichan), Sampled_xToIndex (me, x),
+		double index_real = (x - my x1) / my dx + 1.0;
+		sum += NUM_interpolate_sinc (my z.row (ichan), index_real,
 			interpolation == Vector_VALUE_INTERPOLATION_SINC70 ? NUM_VALUE_INTERPOLATE_SINC70 :
 			interpolation == Vector_VALUE_INTERPOLATION_SINC700 ? NUM_VALUE_INTERPOLATE_SINC700 :
 			interpolation);


=====================================
fon/manual_tutorials.cpp
=====================================
@@ -1,6 +1,6 @@
 /* manual_tutorials.cpp
  *
- * Copyright (C) 1992-2019 Paul Boersma
+ * Copyright (C) 1992-2020 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,8 +22,12 @@
 void manual_tutorials_init (ManPages me);
 void manual_tutorials_init (ManPages me) {
 
-MAN_BEGIN (U"What's new?", U"ppgb", 20200413)
+MAN_BEGIN (U"What's new?", U"ppgb", 20200419)
 INTRO (U"Latest changes in Praat.")
+NORMAL (U"##6.1.13# (19 April 2020)")
+LIST_ITEM (U"• Repaired discriminant analysis on i386 processors.")
+LIST_ITEM (U"• Scripting: enabled predictability by setting random seeds.")
+LIST_ITEM (U"• Automated batch testing on x86_64, i386 and ARMv7 processors.")
 NORMAL (U"##6.1.12# (13 April 2020)")
 LIST_ITEM (U"• All non-GUI tests can be automated from batch.")
 LIST_ITEM (U"• Repaired a bug introduced in 6.0 whereby a KlattGrid-generated Sound would always be peak-scaled.")


=====================================
makefiles/makefile.defs.linux.alsa
=====================================
@@ -1,13 +1,15 @@
 # File: makefile.defs.linux.alsa
 
 # System: Linux
-# Paul Boersma, 23 March 2020
+# Paul Boersma 2020-04-16
 
 CC = gcc
 
 CXX = g++
 
-COMMONFLAGS = -DUNIX -Dlinux -DALSA -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
+PKG_CONFIG ?= "pkg-config"
+
+COMMONFLAGS = -DUNIX -Dlinux -DALSA -D_FILE_OFFSET_BITS=64 `$(PKG_CONFIG) --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
 
 CFLAGS = -std=gnu99 $(COMMONFLAGS) -Werror=missing-prototypes -Werror=implicits
 
@@ -17,7 +19,7 @@ LINK = g++
 
 EXECUTABLE = praat
 
-LIBS = `pkg-config --libs gtk+-2.0` -lm -lasound -lpthread
+LIBS = `$(PKG_CONFIG) --libs gtk+-2.0` -lm -lasound -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.linux.barren
=====================================
@@ -1,7 +1,7 @@
 # File: makefile.defs.linux.barren
 
 # System: Linux without GUI, network, graphics, and sound
-# Paul Boersma, 23 March 2020
+# Paul Boersma 2020-04-16
 
 CC = gcc
 
@@ -17,7 +17,7 @@ LINK = g++
 
 EXECUTABLE = praat_barren
 
-LIBS = -lm -lpthread -static -static-libgcc -static-libstdc++
+LIBS = -lm -static -static-libgcc -static-libstdc++ -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.linux.jack
=====================================
@@ -1,13 +1,15 @@
 # File: makefile.defs.linux.jack
 
 # System: Linux
-# Paul Boersma, 23 March 2020
+# Paul Boersma 2020-04-16
 
 CC = gcc
 
 CXX = g++
 
-COMMONFLAGS = -DUNIX -Dlinux -DJACK -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
+PKG_CONFIG ?= "pkg-config"
+
+COMMONFLAGS = -DUNIX -Dlinux -DJACK -D_FILE_OFFSET_BITS=64 `$(PKG_CONFIG) --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
 
 CFLAGS = -std=gnu99 $(COMMONFLAGS) -Werror=missing-prototypes -Werror=implicit
 
@@ -17,7 +19,7 @@ LINK = g++
 
 EXECUTABLE = praat
 
-LIBS = `pkg-config --libs gtk+-2.0` -lm -ljack -lpthread
+LIBS = `$(PKG_CONFIG) --libs gtk+-2.0` -lm -ljack -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.linux.nogui
=====================================
@@ -1,13 +1,15 @@
 # File: makefile.defs.linux.nogui
 
 # System: Linux without GUI, network, and sound
-# Paul Boersma, 23 March 2020
+# Paul Boersma 2020-04-16
 
 CC = gcc
 
 CXX = g++
 
-COMMONFLAGS = -DNO_GUI -DNO_NETWORK -D_FILE_OFFSET_BITS=64 `pkg-config --cflags pangocairo` -DUNIX -Dlinux -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O3 -g1 -pthread
+PKG_CONFIG ?= "pkg-config"
+
+COMMONFLAGS = -DNO_GUI -DNO_NETWORK -D_FILE_OFFSET_BITS=64 `$(PKG_CONFIG) --cflags pangocairo` -DUNIX -Dlinux -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O3 -g1 -pthread
 
 CFLAGS = -std=gnu99 $(COMMONFLAGS) -Werror=missing-prototypes -Werror=implicit
 
@@ -17,7 +19,7 @@ LINK = g++
 
 EXECUTABLE = praat_nogui
 
-LIBS = `pkg-config --libs pangocairo` -lm -static-libgcc -static-libstdc++ -lpthread
+LIBS = `$(PKG_CONFIG) --libs pangocairo` -lm -static-libgcc -static-libstdc++ -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.linux.pulse
=====================================
@@ -1,23 +1,25 @@
 # File: makefile.defs.linux.pulse
 
 # System: Linux
-# David Weenink and Paul Boersma, 23 March 2020
+# David Weenink and Paul Boersma 2020-04-16
 
 CC = gcc
 
 CXX = g++
 
-COMMONFLAGS = -DUNIX -Dlinux -DALSA -DHAVE_PULSEAUDIO -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O3 -g1 -pthread
+PKG_CONFIG ?= "pkg-config"
+
+COMMONFLAGS = -DUNIX -Dlinux -DALSA -DHAVE_PULSEAUDIO -D_FILE_OFFSET_BITS=64 `$(PKG_CONFIG) --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O3 -g1 -pthread
 
 CFLAGS = -std=gnu99 $(COMMONFLAGS) -Werror=missing-prototypes -Werror=implicit
 
 CXXFLAGS = -std=c++17 $(COMMONFLAGS) -Wshadow
 
-LINK = g++
+LINK = $(CXX)
 
 EXECUTABLE = praat
 
-LIBS = `pkg-config --libs gtk+-2.0` -lm -lpulse -lasound -static-libgcc -static-libstdc++ -lpthread
+LIBS = `$(PKG_CONFIG) --libs gtk+-2.0` -lm -lpulse -lasound -static-libgcc -static-libstdc++ -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.linux.rpi
=====================================
@@ -1,13 +1,15 @@
 # File: makefile.defs.linux.rpi
 
 # System: Raspberry Pi
-# Paul Boersma, 23 March 2020
+# Paul Boersma 2020-04-16
 
 CC = gcc
 
 CXX = g++
 
-COMMONFLAGS = -DUNIX -Dlinux -DJACK -DPA_LITTLE_ENDIAN -Draspberrypi -D_FILE_OFFSET_BITS=64 `pkg-config --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
+PKG_CONFIG ?= "pkg-config"
+
+COMMONFLAGS = -DUNIX -Dlinux -DJACK -DPA_LITTLE_ENDIAN -Draspberrypi -D_FILE_OFFSET_BITS=64 `$(PKG_CONFIG) --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
 
 CFLAGS = -std=gnu99 $(COMMONFLAGS) -Werror=missing-prototypes -Werror=implicit
 
@@ -17,7 +19,7 @@ LINK = g++
 
 EXECUTABLE = praat
 
-LIBS = `pkg-config --libs gtk+-2.0` -lm -ljack -static-libgcc -static-libstdc++ -lpthread
+LIBS = `$(PKG_CONFIG) --libs gtk+-2.0` -lm -ljack -static-libgcc -static-libstdc++ -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.linux.silent
=====================================
@@ -1,13 +1,15 @@
 # File: makefile.defs.linux.silent
 
 # System: Linux without sound
-# Paul Boersma, 23 March 2020
+# Paul Boersma 2020-04-16
 
 CC = gcc
 
 CXX = g++
 
-COMMONFLAGS = -D_FILE_OFFSET_BITS=64 -DUNIX -Dlinux `pkg-config --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
+PKG_CONFIG ?= "pkg-config"
+
+COMMONFLAGS = -D_FILE_OFFSET_BITS=64 -DUNIX -Dlinux `$(PKG_CONFIG) --cflags gtk+-2.0` -Wreturn-type -Wunused -Wunused-parameter -Wuninitialized -O1 -g1 -pthread
 
 CFLAGS = -std=gnu99 $(COMMONFLAGS) -Werror=missing-prototypes -Werror=implicit
 
@@ -17,7 +19,7 @@ LINK = g++
 
 EXECUTABLE = praat
 
-LIBS = `pkg-config --libs gtk+-2.0` -lm -lpthread -static-libgcc -static-libstdc++
+LIBS = `$(PKG_CONFIG) --libs gtk+-2.0` -lm -static-libgcc -static-libstdc++ -lpthread
 
 AR = ar
 RANLIB = ls


=====================================
makefiles/makefile.defs.mingw32
=====================================
@@ -1,7 +1,7 @@
 # File: makefile.defs.mingw32
 
 # System: MinGW on Windows under Cygwin
-# Paul Boersma, 8 November 2019
+# Paul Boersma 2020-04-18
 
 PREFIX = i686-w64-mingw32-
 
@@ -17,7 +17,7 @@ CFLAGS = -std=gnu99 $(COMMONFLAGS)
 # gnu++17 instead of c++17 is necessary to define M_PI in external code
 CXXFLAGS = -std=gnu++17 $(COMMONFLAGS) -Wshadow
 
-LINK = $(PREFIX)g++
+LINK = $(CXX)
 
 EXECUTABLE = Praat.exe
 


=====================================
sys/DataEditor.cpp
=====================================
@@ -223,10 +223,11 @@ static void gui_button_cb_change (DataSubEditor me, GuiButtonEvent /* event */)
 			}
 		}
 	}
-	/* Several collaborators have to be notified of this change:
-	 * 1. The owner (creator) of our root DataEditor: so that she can notify other editors, if any.
-	 * 2. All our sibling DataSubEditors.
-	 */
+	/*
+		Several collaborators have to be notified of this change:
+		1. The owner (creator) of our root DataEditor: so that she can notify other editors, if any.
+		2. All our sibling DataSubEditors.
+	*/
 	Editor_broadcastDataChanged (my root);
 	update (me);
 	for (int isub = 1; isub <= my root -> children.size; isub ++) {
@@ -248,7 +249,7 @@ static void gui_cb_scroll (DataSubEditor me, GuiScrollBarEvent event) {
 }
 
 static void gui_button_cb_open (DataSubEditor me, GuiButtonEvent event) {
-	int ifield = 0;
+	integer ifield = 0;
 	static MelderString name;
 	MelderString_empty (& name);
 
@@ -271,28 +272,28 @@ static void gui_button_cb_open (DataSubEditor me, GuiButtonEvent event) {
 
 	if (fieldData -> description -> rank == 1 || fieldData -> description -> rank == 3 || fieldData -> description -> rank < 0) {
 		MelderString_append (& name, fieldData -> history.get(), U". ", strip_d (fieldData -> description -> name),
-			U" [", fieldData -> minimum, U"..", fieldData -> maximum, U"]");
+				U" [", fieldData -> minimum, U"..", fieldData -> maximum, U"]");
 		VectorEditor_create (my root, name.string, fieldData -> address,
-			fieldData -> description, fieldData -> minimum, fieldData -> maximum);
+				fieldData -> description, fieldData -> minimum, fieldData -> maximum);
 	} else if (fieldData -> description -> rank == 2) {
 		MelderString_append (& name, fieldData -> history.get(), U". ", strip_d (fieldData -> description -> name),
-			U" [", fieldData -> minimum, U"..", fieldData -> maximum, U"]");
+				U" [", fieldData -> minimum, U"..", fieldData -> maximum, U"]");
 		MelderString_append (& name, U" [", fieldData -> min2, U"..", fieldData -> max2, U"]");
 		MatrixEditor_create (my root, name.string, fieldData -> address, fieldData -> description,
-			fieldData -> minimum, fieldData -> maximum, fieldData -> min2, fieldData -> max2);
+				fieldData -> minimum, fieldData -> maximum, fieldData -> min2, fieldData -> max2);
 	} else if (fieldData -> description -> type == structwa) {
 		MelderString_append (& name, fieldData -> history.get(), U". ", strip_d (fieldData -> description -> name));
 		StructEditor_create (my root, name.string, fieldData -> address,
-			* (Data_Description *) fieldData -> description -> tagType);
+				* (Data_Description *) fieldData -> description -> tagType);
 	} else if (fieldData -> description -> type == objectwa ||
 	           fieldData -> description -> type == collectionofwa ||
 			   fieldData -> description -> type == collectionwa) {
 		MelderString_append (& name, fieldData -> history.get(), U". ", strip_d (fieldData -> description -> name));
 		ClassEditor_create (my root, name.string, fieldData -> address,
-			Class_getDescription ((ClassInfo) fieldData -> description -> tagType));
+				Class_getDescription ((ClassInfo) fieldData -> description -> tagType));
 	} else /*if (fieldData -> description -> type == inheritwa)*/ {
 		ClassEditor_create (my root, fieldData -> history.get(), fieldData -> address,
-			fieldData -> description);
+				fieldData -> description);
 /*	} else {
 		Melder_casual (
 			U"Strange editor \"", strip_d (fieldData -> description -> name),
@@ -307,22 +308,23 @@ void structDataSubEditor :: v_createChildren () {
 	int x = Gui_LEFT_DIALOG_SPACING, y = Gui_TOP_DIALOG_SPACING + Machine_getMenuBarHeight (), buttonWidth = 120;
 
 	GuiButton_createShown (our windowForm, x, x + buttonWidth, y, y + Gui_PUSHBUTTON_HEIGHT,
-		U"Change", gui_button_cb_change, this, 0);
+			U"Change", gui_button_cb_change, this, 0);
 	x += buttonWidth + Gui_HORIZONTAL_DIALOG_SPACING;
 	GuiButton_createShown (our windowForm, x, x + buttonWidth, y, y + Gui_PUSHBUTTON_HEIGHT,
-		U"Cancel", gui_button_cb_cancel, this, 0);
+			U"Cancel", gui_button_cb_cancel, this, 0);
 
 	y = LIST_Y + Machine_getMenuBarHeight ();
 	d_scrollBar = GuiScrollBar_createShown (our windowForm,
 		- SCROLL_BAR_WIDTH, 0, y, 0,
 		0, d_numberOfFields, 0, d_numberOfFields < kDataSubEditor_MAXNUM_ROWS ? d_numberOfFields : kDataSubEditor_MAXNUM_ROWS, 1, kDataSubEditor_MAXNUM_ROWS - 1,
-		gui_cb_scroll, this, 0);
+		gui_cb_scroll, this, 0
+	);
 
 	y += 10;
 	for (int i = 1; i <= kDataSubEditor_MAXNUM_ROWS; i ++) {
 		d_fieldData [i]. label = GuiLabel_create (our windowForm, 0, 200, y, y + Gui_TEXTFIELD_HEIGHT, U"label", 0);   // no fixed x value: sometimes indent
 		d_fieldData [i]. button = GuiButton_create (our windowForm, BUTTON_X, BUTTON_X + buttonWidth, y, y + Gui_TEXTFIELD_HEIGHT,
-			U"Open", gui_button_cb_open, this, 0);
+				U"Open", gui_button_cb_open, this, 0);
 		d_fieldData [i]. text = GuiText_create (our windowForm, TEXT_X, -30, y, y + Gui_TEXTFIELD_HEIGHT, 0);
 		d_fieldData [i]. y = y;
 		y += ROW_HEIGHT;
@@ -338,9 +340,8 @@ void structDataSubEditor :: v_createHelpMenuItems (EditorMenu menu) {
 
 static void DataSubEditor_init (DataSubEditor me, DataEditor root, conststring32 title, void *address, Data_Description description) {
 	my root = root;
-	if (me != root) {
+	if (me != root)
 		root -> children.addItem_ref (me);
-	}
 	my d_address = address;
 	my d_description = description;
 	my d_topField = 1;
@@ -376,7 +377,10 @@ static conststring32 singleTypeToText (void *address, int type, void *tagType, M
 		case stringwa:
 		case lstringwa: {
 			char32 *string = * (char32 **) address;
-			if (! string) { MelderString_empty (buffer); return buffer -> string; }   // convert null string to empty string
+			if (! string) {
+				MelderString_empty (buffer);   // convert null string to empty string
+				return buffer -> string;
+			}
 			return string;   // may be much longer than the usual size of 'buffer'
 		} break;
 		default: return U"(unknown)";
@@ -391,7 +395,8 @@ static void showStructMember (
 	DataSubEditor_FieldData fieldData,   /* The widgets in which to show the info about the current member. */
 	char32 *history)
 {
-	int type = memberDescription -> type, rank = memberDescription -> rank, isSingleType = type <= maxsingletypewa && rank == 0;
+	int type = memberDescription -> type, rank = memberDescription -> rank;
+	bool isSingleType = ( type <= maxsingletypewa && rank == 0 );
 	unsigned char *memberAddress = (unsigned char *) structAddress + memberDescription -> offset;
 	if (type == inheritwa) {
 		GuiLabel_setText (fieldData -> label,
@@ -419,12 +424,14 @@ static void showStructMember (
 	} else if (rank == 1) {
 		void *arrayAddress = * (void **) memberAddress;
 		integer minimum, maximum;
-		if (! arrayAddress) return;   // no button for empty fields
+		if (! arrayAddress)
+			return;   // no button for empty fields
 		Data_Description_evaluateInteger (structAddress, structDescription,
 			memberDescription -> min1, & minimum);
 		Data_Description_evaluateInteger (structAddress, structDescription,
 			memberDescription -> max1, & maximum);
-		if (maximum < minimum) return;   // no button if no elements
+		if (maximum < minimum)
+			return;   // no button if no elements
 		fieldData -> address = arrayAddress;   // indirect
 		fieldData -> description = memberDescription;
 		fieldData -> minimum = minimum;   // normally 1
@@ -434,23 +441,24 @@ static void showStructMember (
 		GuiThing_show (fieldData -> button);
 	} else if (rank < 0) {
 		/*
-		 * This represents an in-line array.
-		 */
+			This represents an in-line array.
+		*/
 		integer maximum;   /* But: capacity = - rank */
 		Data_Description_evaluateInteger (structAddress, structDescription,
 			memberDescription -> max1, & maximum);
-		if (-- maximum < 0) return;   /* Subtract one for zero-based array; no button if no elements. */
+		if (-- maximum < 0)
+			return;   // subtract one for zero-based array; no button if no elements
 		fieldData -> address = memberAddress;   /* Direct. */
 		fieldData -> description = memberDescription;
-		fieldData -> minimum = 0;   /* In-line arrays start with index 0. */
-		fieldData -> maximum = maximum;   /* Probably between -1 and capacity - 1. */
+		fieldData -> minimum = 0;   // in-line arrays start with index 0
+		fieldData -> maximum = maximum;   // probably between -1 and capacity - 1
 		fieldData -> rank = rank;
 		fieldData -> history = Melder_dup_f (history);
 		GuiThing_show (fieldData -> button);
 	} else if (rank == 3) {
 		/*
-		 * This represents an in-line set.
-		 */
+			This represents an in-line set.
+		*/
 		fieldData -> address = memberAddress;   // direct
 		fieldData -> description = memberDescription;
 		fieldData -> minimum = str32equ (((conststring32 (*) (int)) memberDescription -> min1) (0), U"_") ? 1 : 0;
@@ -461,17 +469,19 @@ static void showStructMember (
 	} else if (rank == 2) {
 		constMAT mat = * (constMAT *) memberAddress;
 		//Melder_casual (U"Showing matrix member with ", mat.nrow, U" rows and ", mat.ncol, U" columns.");
-		if (NUMisEmpty (mat)) return;   // no button for empty fields
+		if (NUMisEmpty (mat))
+			return;   // no button for empty fields
 		integer min1, max1, min2, max2;
 		Data_Description_evaluateInteger (structAddress, structDescription,
-			memberDescription -> min1,  & min1);
+			memberDescription -> min1, & min1);
 		Data_Description_evaluateInteger (structAddress, structDescription,
 			memberDescription -> max1, & max1);
 		Data_Description_evaluateInteger (structAddress, structDescription,
-			memberDescription -> min2,  & min2);
+			memberDescription -> min2, & min2);
 		Data_Description_evaluateInteger (structAddress, structDescription,
 			memberDescription -> max2, & max2);
-		if (max1 < min1 || max2 < min2) return;   // no button if no elements
+		if (max1 < min1 || max2 < min2)
+			return;   // no button if no elements
 		fieldData -> address = memberAddress;   // direct
 		fieldData -> description = memberDescription;
 		fieldData -> minimum = min1;   // normally 1
@@ -489,16 +499,18 @@ static void showStructMember (
 		GuiThing_show (fieldData -> button);
 	} else if (type == objectwa || type == collectionwa) {
 		fieldData -> address = * (Daata *) memberAddress;   // indirect  // FIXME: not guaranteed for auto objects
-		if (! fieldData -> address) return;   // no button if no object
+		if (! fieldData -> address)
+			return;   // no button if no object
 		fieldData -> description = memberDescription;
 		fieldData -> rank = 0;
 		fieldData -> history = Melder_dup_f (history);
 		GuiThing_show (fieldData -> button);
 	} else if (type == collectionofwa) {
 		fieldData -> address = (Daata) memberAddress;   // direct  // FIXME: not guaranteed for auto objects
-		Melder_casual (U"Daata ", Melder_pointer (fieldData -> address));
-		Melder_casual (U"Class ", ((Daata) fieldData -> address) -> classInfo -> className);
-		if (! fieldData -> address) return;   // no button if no object
+		//Melder_casual (U"Daata ", Melder_pointer (fieldData -> address));
+		//Melder_casual (U"Class ", ((Daata) fieldData -> address) -> classInfo -> className);
+		if (! fieldData -> address)
+			return;   // no button if no object
 		fieldData -> description = memberDescription;
 		fieldData -> rank = 0;
 		fieldData -> history = Melder_dup_f (history);
@@ -507,12 +519,13 @@ static void showStructMember (
 }
 
 static void showStructMembers (DataSubEditor me, void *structAddress, Data_Description structDescription, int fromMember, char32 *history) {
-	int i = 1;
+	integer i = 1;
 	Data_Description memberDescription = structDescription;
 	for (; i < fromMember && memberDescription -> name != nullptr; i ++, memberDescription ++)
 		(void) 0;
 	for (; memberDescription -> name != nullptr; memberDescription ++) {
-		if (++ my d_irow > kDataSubEditor_MAXNUM_ROWS) return;
+		if (++ my d_irow > kDataSubEditor_MAXNUM_ROWS)
+			return;
 		showStructMember (structAddress, structDescription, memberDescription, & my d_fieldData [my d_irow], history);
 	}
 }
@@ -548,19 +561,26 @@ integer structVectorEditor :: v_countFields () {
 }
 
 void structVectorEditor :: v_showMembers () {
-	int type = our d_description -> type, isSingleType = type <= maxsingletypewa;
-	int elementSize = type == structwa ?
-		Data_Description_countMembers (* (Data_Description *) d_description -> tagType) + 1 : 1;
+	int type = our d_description -> type;
+	bool isSingleType = ( type <= maxsingletypewa );
+	integer elementSize = ( type == structwa ?
+		Data_Description_countMembers (* (Data_Description *) d_description -> tagType) + 1 : 1 );
 	integer firstElement = d_minimum + (d_topField - 1) / elementSize;
 
 	for (integer ielement = firstElement; ielement <= d_maximum; ielement ++) {
-		unsigned char *elementAddress = (unsigned char *) our d_address + (ielement - 1) * our d_description -> size;
 		int skip = ielement == firstElement ? (our d_topField - 1) % elementSize : 0;
 
 		if (++ our d_irow > kDataSubEditor_MAXNUM_ROWS) return;
 		DataSubEditor_FieldData fieldData = & our d_fieldData [d_irow];
 
 		if (isSingleType) {
+			/*
+				TODO: assume the address refers to a constVEC;
+				this is not yet true of Collections, and
+				indirect has to be changed to direct in showStructMember()
+			*/
+			unsigned char *elementAddress = (unsigned char *) our d_address + (ielement - 1) * our d_description -> size;
+
 			GuiControl_move (fieldData -> label, 0, fieldData -> y);
 			GuiLabel_setText (fieldData -> label,
 				Melder_cat (strip_d (our d_description -> name), U" [",
@@ -578,6 +598,13 @@ void structVectorEditor :: v_showMembers () {
 			fieldData -> address = elementAddress;
 			fieldData -> description = d_description;
 		} else if (type == structwa) {
+			/*
+				TODO: assume the address refers to a constVEC;
+				this is not yet true of Collections, and
+				indirect has to be changed to direct in showStructMember()
+			*/
+			unsigned char *elementAddress = (unsigned char *) our d_address + (ielement - 1) * our d_description -> size;
+
 			static MelderString history;
 			MelderString_copy (& history, our name.get());
 
@@ -601,6 +628,11 @@ void structVectorEditor :: v_showMembers () {
 			}
 			showStructMembers (this, elementAddress, * (Data_Description *) d_description -> tagType, skip, history.string);
 		} else if (type == objectwa) {
+			/*
+				TODO: assume the address refers to the items of a Collection (?)
+			*/
+			unsigned char *elementAddress = (unsigned char *) our d_address + ielement * our d_description -> size;
+
 			static MelderString history;
 			MelderString_copy (& history, our name.get());
 			if (history.string [history.length - 1] == U']') {
@@ -616,8 +648,10 @@ void structVectorEditor :: v_showMembers () {
 			GuiThing_show (fieldData -> label);
 
 			Daata object = * (Daata *) elementAddress;
-			if (! object) return;   // no button if no object
-			if (! Class_getDescription (object -> classInfo)) return;   // no button if no description for this class
+			if (! object)
+				return;   // no button if no object
+			if (! Class_getDescription (object -> classInfo))
+				return;   // no button if no description for this class
 			fieldData -> address = object;
 			fieldData -> description = Class_getDescription (object -> classInfo);
 			fieldData -> rank = 0;
@@ -654,10 +688,10 @@ integer structMatrixEditor :: v_countFields () {
 }
 
 void structMatrixEditor :: v_showMembers () {
-	int type = d_description -> type;
+	int type = our d_description -> type;
 	bool isSingleType = ( type <= maxsingletypewa );
 	Melder_assert (isSingleType);   // allow no struct matrices
-	integer rowSize = d_max2 - d_min2 + 1;
+	integer rowSize = our d_max2 - our d_min2 + 1;
 	constMAT mat = * (constMAT *) d_address;   // HACK: this could be a MAT or an INTMAT
 	Melder_assert (rowSize == mat.ncol);   // HACK: this should work correctly even for an INTMAT
 	integer firstRow = d_minimum + (d_topField - 1) / rowSize;
@@ -668,7 +702,8 @@ void structMatrixEditor :: v_showMembers () {
 		unsigned char *elementAddress = (unsigned char *) mat.cells + ((irow - 1) * rowSize + (icolumn - 1)) * d_description -> size;
 			// not & mat [irow] [icol], because that HACK would not work for an INTMAT
 
-		if (++ d_irow > kDataSubEditor_MAXNUM_ROWS) return;
+		if (++ d_irow > kDataSubEditor_MAXNUM_ROWS)
+			return;
 		DataSubEditor_FieldData fieldData = & d_fieldData [d_irow];
 		
 		if (isSingleType) {


=====================================
sys/praat_version.h
=====================================
@@ -1,5 +1,5 @@
-#define PRAAT_VERSION_STR 6.1.12
-#define PRAAT_VERSION_NUM 6112
+#define PRAAT_VERSION_STR 6.1.13
+#define PRAAT_VERSION_NUM 6113
 #define PRAAT_YEAR 2020
 #define PRAAT_MONTH April
-#define PRAAT_DAY 13
+#define PRAAT_DAY 19


=====================================
test/dwtools/CPPS.praat
=====================================
@@ -1,5 +1,21 @@
-sound = Create Sound from formula: "sineWithNoise", 1, 0, 1, 44100, "1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)"
-ceps = To PowerCepstrogram: 60, 0.002, 5000, 50
+writeInfoLine: "CPPS"
+sound = Create Sound as tone complex: "toneComplex", 0, 1, 44100, "cosine", 100, 0, 0, 0
+ceps = noprogress To PowerCepstrogram: 60, 0.0020001, 5000, 50
 cpps = Get CPPS: "yes", 0.02, 0.0005, 60, 330, 0.05, "Parabolic", 0.001, 0, "Exponential decay", "Robust"
-assert 4.0 < cpps and cpps < 4.9 ; 'cpps'
+appendInfoLine: "cpps = ", cpps, " dB"
+if fixed$ (cpps, 5) <> "32.77551"
+	appendInfoLine: "WARNING: should have been 32.77551 dB"
+endif
 removeObject: sound, ceps
+
+for i to 3
+	sound = Create Sound from formula: "sineWithNoise", 1, 0, 1, 44100, "1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)"
+	ceps = noprogress To PowerCepstrogram: 60, 0.0020001, 5000, 50
+	cpps = Get CPPS: "yes", 0.02, 0.0005, 60, 330, 0.05, "Parabolic", 0.001, 0, "Exponential decay", "Robust"
+	appendInfoLine: cpps
+	if not (4.0 < cpps and cpps < 4.9)
+		appendInfoLine: "WARNING: should have been between 4.0 and 4.9 dB"
+	endif
+	removeObject: sound, ceps
+endfor
+appendInfoLine: "CPPS OK"


=====================================
test/fon/stereoFormula.praat
=====================================
@@ -31,6 +31,10 @@ a = Get value at time... Average 0.5 Linear
 printline 'a'
 b = Get value at time... Left 0.5 Linear
 printline 'b'
+leftAmplitude = Get value at sample number: 1, 22050
+rightAmplitude = Get value at sample number: 1, 22051
+average = 0.5 * (leftAmplitude + rightAmplitude)
+appendInfoLine: "by hand: ", average
 c = Get value at time... Right 0.5 Linear
 printline 'c'
 d = Sound_test (0.5)
@@ -45,13 +49,13 @@ printline 'ee'   'ee2'
 f = Sound_test (0.5, 2)
 f2 = object ("Sound test", 0.5, 2)
 printline 'f'   'f2'
-assert a = d
-assert b = ee
-assert c = f
-assert d = dd
-assert a = d2
-assert b = ee2
-assert c = f2
-assert d = dd2
+assert abs (a - d) < 1e-12
+assert abs (b - ee) < 1e-12
+assert abs (c - f) < 1e-12
+assert abs (d - dd) < 1e-12
+assert abs (a - d2) < 1e-12
+assert abs (b - ee2) < 1e-12
+assert abs (c - f2) < 1e-12
+assert abs (d - dd2) < 1e-12
 Remove
 printline OK


=====================================
test/kar/unicode16.praat
=====================================
Binary files a/test/kar/unicode16.praat and b/test/kar/unicode16.praat differ


=====================================
test/num/fisherQ.praat
=====================================
@@ -1,29 +1,32 @@
 # fisherQ
-# Paul Boersma, August 27, 2003
-# April 7, 2008: more accuracy in fisherQ because of GSL (n.b. GSL not to be used in invFisherQ)
+# Paul Boersma 2003-08-23
+# 2008-04-07: more accuracy in fisherQ because of GSL (n.b. GSL not to be used in invFisherQ)
 # Computes a significance from zero, given a measured F value.
+# 2020-04-17: checks on behalf of i386
+
 df1 = 2
 df2 = 70
 f = 33.59
 fisherQ = fisherQ (f, df1, df2)
 fisherQ$ = fixed$ (fisherQ, 20)
-echo fisherQ test: 'fisherQ' 'fisherQ$'
+writeInfoLine: "fisherQ test: ", fisherQ, " ", fisherQ$
 assert fisherQ$ = "0.00000000005932714540"
 for i to 10000
-   assert fisherQ (randomUniform (3, 4), 1, 100000) <> undefined
+	a = randomUniform (3, 4)
+	assert fisherQ (a, 1, 100000) <> undefined   ; 'i' 'a'
 endfor
 
-echo invFisherQ
-call invFisherQ 2 70 1e-14
-call invFisherQ 70 2 1e-14
-call invFisherQ 1 if(windows)then(100)else(100000)fi 1e-11
+appendInfoLine: "invFisherQ"
+ at invFisherQ: 2, 70, 1e-14
+ at invFisherQ: 70, 2, 1e-14
+ at invFisherQ: 1, if windows then 100 else 100000 fi, 1e-11
 if not windows
-	call invFisherQ 1 1 1e-14
-	call invFisherQ 100000 1 1e-11
+	@invFisherQ: 1, 1, 1e-14
+	@invFisherQ: 100000, 1, 1e-11
 endif
-call invFisherQ 100 100 1e-9
-procedure invFisherQ df1 df2 precision
-   # Known values.
+ at invFisherQ: 100, 100, 1e-9
+procedure invFisherQ: df1, df2, precision
+	# Known values.
    assert invFisherQ (0, 'df1', 'df2') = undefined
    assert invFisherQ (1, 'df1', 'df2') = 0
    # We should be able to draw a curve of invFisherQ.
@@ -42,7 +45,7 @@ procedure invFisherQ df1 df2 precision
       q = 10 ^ -power
       f = invFisherQ (q, df1, df2)
       if f = undefined and not mentioned
-         printline 'df1' 'df2' 'power'
+         appendInfoLine: "stopped at invFisherQ (", q, ", ", df1, ", ", df2, ")"
          mentioned = 1
       endif
       assert f = undefined or abs (fisherQ (f, 'df1', 'df2') - 'q') < 'q'*'precision'*300 ; 'power' 'f'
@@ -82,15 +85,24 @@ assert invFisherQ (0.159, 2, 70) <> undefined ; used to exceed 60 iterations
 #
 # Things that still go wrong.
 #
-assert fisherQ (1, 1e19, 1e19) = undefined
+a = fisherQ (1, 1e19, 1e19)
+if a = undefined
+	appendInfoLine: "WARNING: fisherQ (1, 1e19, 1e19) is still undefined"
+else
+	appendInfoLine: "fisherQ (1, 1e19, 1e19) = ", a
+endif
 #
 # Check that we invert better than GSL does.
 #
-Debug... no 29   ; set invFisherQ to GSL
+Debug: "no", 29   ; set invFisherQ to GSL
 f = invFisherQ (0.01, 1, 10000)   ; not such an unusual case
-Debug... no 0   ; quickly (i.e. before the assert!) undo the debug-29 option
-assert "'f'" = "--undefined--" or "'f:5'" = "6.63743"
+Debug: "no", 0   ; quickly (i.e. before the assert!) undo the debug-29 option
+if f = undefined
+	appendInfoLine: "WARNING: GSL would still have computed invFisherQ (0.01, 1, 10000) as undefined"
+else
+	assert "'f:5'" = "6.63743"
+endif
 f = invFisherQ (0.01, 1, 10000)   ; same case, but using our corrected NUMridders again
 assert "'f:5'" = "6.63743"
 #
-printline OK
+appendInfoLine: "OK"


=====================================
test/num/norm.praat
=====================================
@@ -1,7 +1,7 @@
 #! Praat test script norm.praat
-# Paul Boersma 20190319
+# Paul Boersma 20200419
 
-echo norm
+writeInfoLine: "norm"
 
 assert norm ({ 3, 4 }, 1) = 7
 assert norm ({ 3, -4 }, 1) = 7
@@ -10,14 +10,14 @@ assert norm ({ 3, 4 }) = 5
 assert norm ({ 3, 4 }, 2) = 5
 assert norm ({ -3, 4 }, 2) = 5
 
-assert norm ({ 3, 3, 2, 1, 1 }, 3) = 4
-assert norm ({ -3, 3, 2, -1, 1 }, 3) = 4
+assert abs (norm ({ 3, 3, 2, 1, 1 }, 3) - 4) < 1e-15
+assert abs (norm ({ -3, 3, 2, -1, 1 }, 3) - 4) < 1e-15
 
 assert norm ({ { 3 , -4 } }, 1) = 7
 assert norm ({ { 3 }, { -4 } }, 1) = 7
 assert norm ({ { -3, 4 } }, 2) = 5
 assert norm ({ { -3 }, { 4 } }, 2) = 5
-assert norm ({ { -3, 3, 2 }, { -1, 0, 1 } }, 3) = 4
-assert norm ({ { -3, 3 }, { 2, -1 }, { 0, 1 } }, 3) = 4
+assert abs (norm ({ { -3, 3, 2 }, { -1, 0, 1 } }, 3) - 4) < 1e-15
+assert abs (norm ({ { -3, 3 }, { 2, -1 }, { 0, 1 } }, 3) - 4) < 1e-15
 
-printline OK
\ No newline at end of file
+appendInfoLine: "OK"
\ No newline at end of file


=====================================
test/runAllTests_batch.praat
=====================================
@@ -1,17 +1,27 @@
 # Praat script runAllTests_batch.praat
-# Paul Boersma 2020-04-09
+# Paul Boersma 2020-04-16
 #
 # This script runs all Praat scripts in its subdirectories.
 # This script is to be called from the command line:
-#     praat --run runAllTests.praat
+#     praat --run runAllTests_batch.praat
 #
-# The subdirectories `manual` and `speed` are ignored,
+# The subdirectories `manually` and `speed` are ignored,
 # and scripts containing `_GUI_` in their names are ignored.
+#
 
+#
+# Some tests require standard settings for the text input encoding:
+# files in UTF-8 format should always be readable.
+#
+Text writing preferences: "try ASCII, then UTF-16"
 if macintosh
-	executable$ = "~/builds/mac_products/Configuration64/Praat.app/Contents/MacOS/Praat --no-pref-files"
+	Text reading preferences: "try UTF-8, then MacRoman"
+elif windows
+	Text reading preferences: "try UTF-8, then Windows Latin-1"
+elif unix
+	Text reading preferences: "try UTF-8, then ISO Latin-1"
 else
-	executable$ = "../praat --no-pref-files"
+	exitScript: "Unknown operating system."
 endif
 
 writeInfoLine: "Running all tests..."
@@ -30,7 +40,9 @@ for directory to numberOfDirectories
 			if not index (file$, "_GUI_")
 				path$ = directory$ + "/" + file$
 				appendInfoLine: "### executing ", path$, ":"
-				runSystem: executable$, " --run """, path$, """"
+				random_initializeWithSeedUnsafelyButPredictably (5489)
+				runScript: path$
+				random_initializeSafelyAndUnpredictably()
 			endif
 		endfor
 		removeObject: files
@@ -57,7 +69,9 @@ for directory1 to numberOfDirectories1
 				if not index (file$, "_GUI_")
 					path$ = directory1$ + "/" + directory2$ + "/" + file$
 					appendInfoLine: "### executing ", path$, ":"
-					runSystem: executable$, " --run """, path$, """"
+					random_initializeWithSeedUnsafelyButPredictably (5489)
+					runScript: path$
+					random_initializeSafelyAndUnpredictably()
 				endif
 			endfor
 			removeObject: files


=====================================
test/script/text100MB.praat
=====================================
@@ -1,10 +1,13 @@
 # text100MB.praat
-# Paul Boersma, 9 November 2008
+# Paul Boersma 2020-04-19
+
+integerProperties$ = Report integer properties
+bits = extractNumber (integerProperties$, "A pointer is")
 
 echo Text 100 MB:
 stopwatch
 a$ = "a"
-for i to 8
+for i to if bits = 32 then 7 else 8 fi
 	a$ = a$ + a$ + a$ + a$ + a$ + a$ + a$ + a$ + a$ + a$
 endfor
 t = stopwatch


=====================================
test/stat/logisticRegression.praat
=====================================
@@ -1,11 +1,10 @@
 echo Logistic regression
-# Paul Boersma, 16 December 2015
+# Paul Boersma 2020-04-19
 
-printline Spec & Dur table
-table = Read Table from table file... logisticRegression/rh.Table
+writeInfoLine: "Spec & Dur table:"
+table = Read Table from table file: "logisticRegression/rh.Table"
 logreg = To logistic regression: "Spec Dur", "/I/", "/i/"
 logreg2 = Read from file: "logisticRegression/rh.LogisticRegression"
-assert objectsAreIdentical (logreg, logreg2)
 info$ = Info
 intercept = extractNumber (info$, "Intercept: ")
 assert fixed$ (intercept, 4) = "-8.7028"   ; 'intercept'
@@ -15,4 +14,4 @@ dur = extractNumber (info$, "Coefficient of factor Dur: ")
 assert fixed$ (dur, 4) = "0.6041"   ; 'dur'
 removeObject: table, logreg, logreg2
 
-printline OK
+appendInfoLine: "OK"


=====================================
test/sys/bits.praat
=====================================
@@ -0,0 +1,3 @@
+integerProperties$ = Report integer properties
+bits = extractNumber (integerProperties$, "A pointer is")
+writeInfoLine: "This computer is ", bits, "-bits"
\ No newline at end of file



View it on GitLab: https://salsa.debian.org/med-team/praat/-/commit/748195ccd181511f5da219d6f8de9342b54a6c51

-- 
View it on GitLab: https://salsa.debian.org/med-team/praat/-/commit/748195ccd181511f5da219d6f8de9342b54a6c51
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20200421/6ee3856e/attachment-0001.html>


More information about the debian-med-commit mailing list