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

Rafael Laboissiere gitlab at salsa.debian.org
Sun Nov 1 22:45:42 GMT 2020



Rafael Laboissiere pushed to branch upstream at Debian Med / praat


Commits:
0f3f6d38 by Rafael Laboissière at 2020-10-31T04:07:51-03:00
New upstream version 6.1.29
- - - - -


21 changed files:

- LPC/FormantPath.cpp
- LPC/FormantPathEditor.cpp
- LPC/manual_LPC.cpp
- dwtools/SSCP.cpp
- dwtools/VowelEditor.cpp
- external/clapack/lapack.cpp
- external/clapack/lapack_dlaq.cpp
- external/clapack/lapack_dt.cpp
- fon/Sound_and_Spectrum.cpp
- fon/manual_tutorials.cpp
- gram/NoulliGridEditor.cpp
- melder/MelderString.h
- melder/NUM.cpp
- sys/GuiButton.cpp
- sys/GuiLabel.cpp
- sys/praat.cpp
- sys/praat_script.cpp
- sys/praat_version.h
- + test/fon/Harmonicity.praat
- + test/manually/bold.praat
- + test/manually/test2.praat


Changes:

=====================================
LPC/FormantPath.cpp
=====================================
@@ -100,8 +100,9 @@ autoINTVEC FormantPath_getOptimumPath (FormantPath me, double qWeight, double fr
 			stresses = FormantPath_to_Matrix_stress (me, windowLength, parameters, powerf);
 
 		/*
+			Some options for assigning costs/benefits to states and state transitions:
 			We have states s[i], where i = 1..  S (= my formants.size)
-			Whithin each state we can have j=1..F formant frequencies f[i][j] and bandwidths b[i][j].
+			Whithin each state i we can have j=1..F formant frequencies f[i][j] and bandwidths b[i][j].
 			Benefits of a state could be expressed as:
 			1. sum (j=1..F, 0.1*f[j]/b[j])/F, this has the advantage that states with large Q values (sharp peaks) have larger benefits
 			(2?). -|log(min(max(f1-f2, 100),300)|, keep sufficient distance between f1 and f2
@@ -421,6 +422,8 @@ void FormantPath_drawAsGrid_inside (FormantPath me, Graphics g, double tmin, dou
 	double xCursor, double yCursor, integer iselected, MelderColour selected, constINTVEC const & parameters,
 	bool markWithinPath, bool showStress, double powerf, bool showEstimatedModels, bool garnish)
 {
+	MelderColour singleSelectionColour = MelderColour (0.984,0.984, 0.7);
+	MelderColour multipleSelectionsColour = MelderColour (0.984,0.984, 0.9);
 	constexpr double fmin = 0.0;
 	if (nrow <= 0 || ncol <= 0)
 		NUMgetGridDimensions (my formants.size, & nrow, & ncol);
@@ -430,19 +433,22 @@ void FormantPath_drawAsGrid_inside (FormantPath me, Graphics g, double tmin, dou
 	const double vp_width = x2NDC - x1NDC, vp_height = y2NDC - y1NDC;
 	const double vpi_width = vp_width / (ncol + (ncol - 1) * spaceBetweenFraction_x);
 	const double vpi_height = vp_height / (nrow + (nrow - 1) * spaceBetweenFraction_y);
-	double markedBorderThickness = 1.0;
+	integer numberOfCeilingInInterval = 1;
 	integer itmin, itmax;
-	INTVECVU path; 
+	autoBOOLVEC ceilingInInterval = newBOOLVECzero (my formants.size);
 	if (markWithinPath && Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) {
 		/*
 			If the path in the interval (tmin, tmax) is constant, then we have only one of
-			the candidates chosen in the whole interval and the box around this one will be
-			drawn thicker.
+			the candidates chosen in the whole interval.
 		*/
-		path = my path.part(itmin, itmax); 
-		const integer minimum = NUMmin (path);
-		const integer maximum = NUMmax (path);
-		markedBorderThickness = ( minimum == maximum ? 3.0 : 1.0 );
+		numberOfCeilingInInterval = 0;
+		for (integer iformant = 1; iformant <= my formants.size; iformant ++)
+			for (integer i = itmin; i <= itmax; i ++)
+				if (my path [i] == iformant) {
+					ceilingInInterval [iformant] = true;
+					numberOfCeilingInInterval ++;
+					break;
+				}
 	}
 	
 	for (integer iformant = 1; iformant <= my formants.size; iformant ++) {
@@ -456,57 +462,42 @@ void FormantPath_drawAsGrid_inside (FormantPath me, Graphics g, double tmin, dou
 		autoFormantModeler fm = Formant_to_FormantModeler (formant, tmin, tmax, parameters);
 		Graphics_setViewport (g, vpi_x1, vpi_x2, vpi_y1, vpi_y2);
 		Graphics_setWindow (g, tmin, tmax, fmin, fmax);
+		if (garnish && markWithinPath) {
+			if (ceilingInInterval [iformant]) {
+				MelderColour colour = Graphics_inqColour (g);
+				MelderColour fillColour = (numberOfCeilingInInterval == 1 ? singleSelectionColour : multipleSelectionsColour);
+				Graphics_setColour (g, fillColour);
+				Graphics_fillRectangle (g, tmin, tmax, 0.0, fmax);
+				Graphics_setColour (g, colour);
+			}
+		}
 		Formant_speckles_inside (formant, g, tmin, tmax, fmin, fmax, fromFormant, toFormant, 100.0, showBandwidths, odd, even);
 		if (showEstimatedModels)
-			FormantModeler_drawModel_inside (fm.get(), g, tmin, tmax, fmax, fromFormant, toFormant, odd, even, 1000_integer);
-		if (garnish) {
-			double lineWidth = 2.0;
-			MelderColour colour = Melder_BLACK;
-			if (iformant == iselected) {
-				colour = selected;
-				lineWidth = 3.0;
-			} else if (markWithinPath) {
-				/*
-					If the path in the interval (tmin, tmax) contains this formant, then mark
-					the box with a special colour. The line width depends on whether this formant
-					is the only one in the interval or not.
-				*/
-				for (integer i = itmin; i <= itmax; i ++)
-					if (my path [i] == iformant) {
-						lineWidth = markedBorderThickness;
-						colour = selected;
-						break;
-					}
-			}
-			Graphics_setLineWidth (g, lineWidth);
-			Graphics_setColour (g, colour);
+			FormantModeler_drawModel_inside (fm.get(), g, tmin, tmax, fmax, fromFormant, toFormant, odd, even, 100_integer);
+		Graphics_setColour (g, Melder_BLACK);
+		if (garnish)
 			Graphics_rectangle (g, tmin, tmax, fmin, fmax);
-		}
+		
 		Graphics_setLineType (g, Graphics_DRAWN);
-		Graphics_setColour (g, Melder_BLACK);
 		Graphics_setLineWidth (g, 1.0);
 		/*
-			Mark name & stress
+			Mark ceiling & stress
 		*/
+		autoMelderString info;
+		const double tLeftPos = tmin - 0.01 * (tmax - tmin), tRightPos = tmax + 0.01 * (tmax - tmin);
 		if (garnish) {
-			Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::RIGHT, Graphics_HALF);
-			Graphics_text (g, tmax - 0.05 * (tmax - tmin),
-				fmax - 0.05 * fmax, Melder_fixed (my ceilings [iformant], 0));
-		}
-		if (showStress) {
-			const double stress = FormantModeler_getStress (fm.get(), fromFormant, toFormant, 0, powerf);
-			Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::LEFT, Graphics_HALF);
-			Graphics_text (g, tmin + 0.05 * (tmax - tmin), fmax - 0.05 * fmax, Melder_fixed (stress, 2));
+			if (showStress) {
+				const double stress = FormantModeler_getStress (fm.get(), fromFormant, toFormant, 0, powerf);
+				MelderString_append (& info, U"Fit=", Melder_fixed (stress, 2));
+				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::LEFT, Graphics_BOTTOM);
+				Graphics_text (g, tLeftPos, fmax, info.string);
+			}
+			MelderString_empty (& info);
+			Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::RIGHT, Graphics_BOTTOM);
+			MelderString_append (& info, U"Ceiling=", Melder_fixed (my ceilings [iformant], 0), U" Hz");
+			Graphics_text (g, tRightPos, fmax, info.string);
 		}
 		Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::CENTRE, Graphics_HALF);
-		conststring32 midTopText = U"";
-		if (midTopText && midTopText [0]) {
-			Graphics_setColour (g, Melder_BLUE);
-			Graphics_text (g, tmin + 0.5 * (tmax - tmin),
-				fmax - 0.05 * fmax, midTopText);
-			Graphics_setColour (g, Melder_BLACK);
-		}
-
 		if (garnish) {
 			auto getXtick = [] (Graphics gg, double fontSize) {
 				const double margin = 2.8 * fontSize * gg -> resolution / 72.0;
@@ -527,29 +518,28 @@ void FormantPath_drawAsGrid_inside (FormantPath me, Graphics g, double tmin, dou
 			};
 			const double xTick = (double) getXtick (g, newFontSize) * (tmax - tmin);
 			const double yTick = (double) getYtick (g, newFontSize) * (fmax - fmin);
-			if (icol == 1 && irow % 2 == 1) {
-				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::RIGHT, Graphics_HALF);
-				Graphics_line (g, tmin - xTick, fmax, tmin, fmax);
-				Graphics_text (g, tmin - xTick, fmax, Melder_iround (fmax));
-				Graphics_line (g, tmin - xTick, fmin, tmin, fmin);
-				Graphics_text (g, tmin - xTick, fmin, Melder_fixed (fmin, 0));
-			} else if (icol == ncol && irow % 2 == 0) {
-				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::LEFT, Graphics_HALF);
-				Graphics_text (g, tmax, fmax, Melder_iround (fmax));
-				Graphics_text (g, tmax, fmin, Melder_fixed (fmin, 0));
-			}
-			if (irow == 1 && icol % 2 == 0) {
-				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::CENTRE, Graphics_BOTTOM);
-				Graphics_line (g, tmin, fmax, tmin, fmax + yTick);
-				Graphics_text (g, tmin, fmax + yTick, Melder_fixed (tmin, 3));
-				Graphics_line (g, tmax, fmax, tmax, fmax + yTick);
-				Graphics_text (g, tmax, fmax + yTick, Melder_fixed (tmax, 3));
-			} else if (irow == nrow && icol % 2 == 1) {
-				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::CENTRE, Graphics_TOP);
+			if (irow == nrow) {
+				MelderString_empty (& info);
+				MelderString_append (& info, Melder_fixed (tmin, 3), U" s");
+				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::LEFT, Graphics_TOP);
 				Graphics_line (g, tmin, fmin, tmin, fmin - yTick);
-				Graphics_text (g, tmin, fmin - yTick, Melder_fixed (tmin, 3));
+				Graphics_text (g, tmin , fmin - yTick, info.string);
+				MelderString_empty (& info);
+				MelderString_append (& info, Melder_fixed (tmax, 3), U" s");
 				Graphics_line (g, tmax, fmin, tmax, fmin - yTick);
-				Graphics_text (g, tmax, fmin - yTick, Melder_fixed (tmax, 3));
+				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::RIGHT, Graphics_TOP);
+				Graphics_text (g, tmax, fmin - yTick, info.string);
+			}
+			if (icol == 1) {
+				MelderString_empty (& info);
+				MelderString_append (& info, Melder_iround (fmin), U" Hz");
+				Graphics_line (g, tmin - xTick, fmin, tmin, fmin);
+				Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::RIGHT, Graphics_HALF);
+				Graphics_text (g, tmin - xTick, fmin, info.string);
+				MelderString_empty (& info);
+				MelderString_append (& info, Melder_iround (fmax), U" Hz");
+				Graphics_text (g, tmin - xTick, fmax, info.string);
+				
 			}
 			double yGridLine_Hz = yGridLineEvery_Hz;
 			Graphics_setLineType (g, Graphics_DOTTED);


=====================================
LPC/FormantPathEditor.cpp
=====================================
@@ -718,19 +718,28 @@ void FormantPathEditor_drawCeilings (FormantPathEditor me, Graphics g, double tm
 	Graphics_setColour (g, Melder_RED);
 	Graphics_setLineWidth (g, 3.0);
 	const double dx2 = 0.5 * formantPath -> dx;
-	double tmid1 = Sampled_indexToX (formantPath, itmin);
-	double ceiling1 = formantPath -> ceilings [formantPath -> path [itmin]];
-	for (integer iframe = itmin + 1; iframe <= itmax; iframe ++) {
-		double ceiling2 = formantPath -> ceilings [formantPath -> path [iframe]];
-		if (ceiling2 == ceiling1)
-			continue;
-		double tmid2 = Sampled_indexToX (formantPath, iframe);
-		Graphics_line (g, tmid1 - dx2, ceiling1, tmid2 - dx2, ceiling1);
-		tmid1 = tmid2;
-		ceiling1 = ceiling2;
+	integer iframe = itmin, iframe2 = itmin + 1;
+	double ceiling = formantPath -> ceilings [formantPath -> path [itmin]];
+	while (iframe2 <= itmax) {
+		double ceiling2;
+		while (iframe2 <= itmax) {
+			ceiling2 = formantPath -> ceilings [formantPath -> path [iframe2]];
+			if (ceiling2 != ceiling)
+				break;
+			iframe2 ++;
+		}
+		const double tmid = Sampled_indexToX (formantPath, iframe);
+		const double tmid2 = Sampled_indexToX (formantPath, iframe2 - 1);
+		Graphics_line (g, tmid - dx2, ceiling, tmid2 + dx2, ceiling);
+		Graphics_setTextAlignment (g, kGraphics_horizontalAlignment::CENTRE, Graphics_BASELINE);
+		Graphics_text (g, 0.5 * (tmid + tmid2), ceiling + 50.0, ((integer) ceiling));
+		ceiling = ceiling2;
+		iframe = iframe2;
+	}
+	if (iframe == itmax) {
+		const double tmid = Sampled_indexToX (formantPath, iframe);
+		Graphics_line (g, tmid - dx2, ceiling, tmid + dx2, ceiling);
 	}
-	double tmid2 = Sampled_indexToX (formantPath, itmax);
-	Graphics_line (g, tmid1 - dx2, ceiling1, tmid2 + dx2, ceiling1);
 	Graphics_setLineWidth (g, 1.0);
 }
 


=====================================
LPC/manual_LPC.cpp
=====================================
@@ -104,24 +104,37 @@ CODE (U"To FormantPath (burg): 0.005, 5.0, 5000.0, 0.025, 50.0, 0.05, 4")
 NORMAL (U"To choose your own path through the alternatives you can use Praat's @@FormantPathEditor at .")
 MAN_END
 
-MAN_BEGIN (U"Sound: To FormantPath (burg)...", U"djmw", 20201013)
+MAN_BEGIN (U"Sound: To FormantPath (burg)...", U"djmw", 20201026)
 INTRO (U"A command that creates a @@FormantPath@ object from each selected @@Sound@ . ")
 ENTRY (U"##Settings")
 NORMAL (U"The settings for ##Time step (s)#, ##Maximum number of formants#, ##Window length (s)# and ##Pre-emphasis from (Hz)# "
-	"are exacly as you would set them in the @@Sound: To Formant (burg)...@ method. "
-	"Therefore you can use 0.005 seconds, 5.0 formants, 0.025 seconds, and 50.0 Hz, respectively.")
-NORMAL (U"For ##Middle formant ceiling (Hz)#, you should use 5500.0 Hz for the average female voice and 5000.0 Hz for the average "
-	"male voice, in the same way as you would do for the ##Formant ceiling (Hz)# setting in ##To Formant (burg)...#. "
-	"Instead of performing only one analysis, as in ##To Formant (burg)...#, we perform multiple analyses, "
-	"each one with a different value for its ceiling. "
-	"Each analysis result, which is of type @@Formant@, is stored in the ##FormantPath# object. "
-	"Therefore, after the analyses are done, the FormantPath object contains a collection of ##Formant# objects.")
+	"are as you would set them with the @@Sound: To Formant (burg)...@ method. "
+	"The defaults are 0.005 seconds, 5.0 formants, 0.025 seconds, and 50.0 Hz, respectively.")
+TAG (U"##Middle formant ceiling (Hz)")
+DEFINITION (U"determines the middle formant ceiling frequency in Hz. You normaly would use 5500.0 Hz for an average female voice "
+	"and 5000.0 Hz for an average male voice as you would do for the ##Formant ceiling (Hz)# setting in ##To Formant (burg)...#. "
+	"However, instead of performing only one analysis with a fixed ceiling, we perform in a number of steps "
+	"multiple analyses, each with a different ceiling frequency. The number of analyses with a %lower formant ceiling than the "
+	"%%middle formant ceiling% is equal to the number of analyses with a %higher formant ceiling than the %%middle formant ceiling%. ")
 TAG (U"##Ceiling step size#")
-DEFINITION (U"defines the increase / decrease in the formant ceiling betweeen two successive analyses as exp(\\+-%ceilingStepSize).")
+DEFINITION (U"defines the increase or decrease in the formant ceiling between two successive analyses as exp(%ceilingStepSize) "
+	"when we step up or as exp(-%ceilingStepSize) when we step down.")
 TAG (U"##Number of steps up / down")
-DEFINITION (U"determines the number steps we go up or down with respect to the %%middle formant ceiling%."
-	"The ceiling frequency for the %ith step down is %middleCeiling\\.cexp (-%i\\.c%ceilingStepSize) and for the i-th step up "
-	"is %middleCeiling\\.cexp (-%i\\.c%ceilingStepSize).")
+DEFINITION (U"determines the number steps we go up as well as the number of steps we go down with respect to the %middle formant ceiling%. "
+	"The ceiling frequency for the %i^^th^ step down is %middleFormantCeiling\\.cexp (-%i\\.c%ceilingStepSize) and for the %i^^th^ step up "
+	"is %middleFormantCeiling\\.cexp (+%i\\.c%ceilingStepSize). The total number of analyses is always 2\\.c%numberOfStepsUpOrDown+1.")
+ENTRY (U"Algorithm")
+NORMAL (U"The following algorithm describes what is going on. ")
+CODE (U"ceiling [numberOfStepsUpOrDown + 1] = middleCeiling")
+CODE (U"for istep from 1 to 2 * numberOfStepsUpOrDown + 1")
+CODE (U"    if istep <= numberOfStepsUpOrDown")
+CODE (U"        ceiling [istep] = middleFormantCeiling * exp (-(numberOfStepsUpOrDown - istep + 1) * ceilingStepSize)")
+CODE (U"    elsif istep > numberOfStepsUpOrDown + 1")
+CODE (U"        ceiling [istep] = middleFormantCeiling * exp ((istep - numberOfStepsUpOrDown - 1) * ceilingStepSize)")
+CODE (U"    selectObject: sound")
+CODE (U"    formant [istep] = To Formant (burg): timeStep, maxNumberOfFormants, ceiling [istep], windowLength, preEmphasis")
+CODE (U"endfor")
+NORMAL (U"This description is approximate because in the \"To Formant\" step we have to guarantee that all the Formant objects get the same time sampling.")
 MAN_END
 
 MAN_BEGIN (U"FormantPathEditor", U"djmw", 20201004)


=====================================
dwtools/SSCP.cpp
=====================================
@@ -210,29 +210,42 @@ void SSCP_drawTwoDimensionalEllipse_inside (SSCP me, Graphics g, double scale, c
 		autoVEC x = newVECraw (nsteps + 1);
 		autoVEC y = newVECraw (nsteps + 1);
 		/*
-			Get principal axes and orientation for the ellipse by performing the
-			eigen decomposition of a symmetric 2-by-2 matrix.
-			Principal axes are a and b with eigenvector/orientation (cs, sn).
+			From the eigenvalues and eigenvectors of the symmetrical sscp matrix we
+			can calculate the length and directions of the principal axes of the ellipse.
 		*/
-		double a, b, cs, sn;
-		NUMeigencmp22 (my data [1] [1], my data [1] [2], my data [2] [2], & a, & b, & cs, & sn);
+		double eval1, eval2, cosine, sine;
+		NUMeigencmp22 (my data [1] [1], my data [1] [2], my data [2] [2], & eval1, & eval2, & cosine, & sine);
 		/*
-			1. Take sqrt to get units of 'std_dev'
+			1. Parametrize as standard ellipse with horizontal radius a and vertical radius b and origin at (0,0) as
+				x = a cos(phi)
+				y = b sin(phi)
 		*/
-		const double axisLength_a = scale * sqrt (a) / 2.0;
-		const double axisLength_b = scale * sqrt (b) / 2.0;
-		x [nsteps + 1] = x [1] = my centroid [1] + cs * axisLength_a;
-		y [nsteps + 1] = y [1] = my centroid [2] + sn * axisLength_a; // axisLength_a is no mistake!
+		const double a = scale * sqrt (eval1) / 2.0;
+		const double b = scale * sqrt (eval2) / 2.0;
 		const double angle_inc = NUM2pi / nsteps;
-		double angle = 0.0;
-		for (integer i = 2; i <= nsteps; i ++, angle += angle_inc) {
-			const double xc = axisLength_a * cos (angle);
-			const double yc = axisLength_b * sin (angle);
-			const double xt = xc * cs - yc * sn;
-			y [i] = my centroid [2] + xc * sn + yc * cs;
-			x [i] = my centroid [1] + xt;
+		for (integer i = 1; i <= nsteps + 1; i ++) {
+			const double phi = (i - 1) * angle_inc;
+			x [i] = a * cos (phi);
+			y [i] = b * sin (phi);
 		}
+		/*
+			2. Rotate x axis to the eigenvector 1 (cosine, sine)
+			|x'|   | cosine -sine |   |x|
+			|  | = |              | * | |
+			|y'|   | sine  cosine |   |y|
+		*/
+		for (integer i = 1; i <= nsteps + 1; i ++) {
+			double xp =  cosine * x [i] -   sine * y [i];			
+			y [i]     =    sine * x [i] + cosine * y[i];
+			x [i] = xp;
+		}
+		/*
+			3. Translate to the centroid
+		*/
+		x.get()  +=  my centroid [1];
+		y.get()  +=  my centroid [2];
 		Graphics_polyline (g, nsteps + 1, & x [1], & y [1]);
+		
 		if (label && fontSize > 0.0) {
 			const double oldFontSize = Graphics_inqFontSize (g);
 			Graphics_setFontSize (g, fontSize);


=====================================
dwtools/VowelEditor.cpp
=====================================
@@ -473,20 +473,18 @@ static void VowelEditor_drawF1F2Trajectory (VowelEditor me, Graphics g) {
 	{
 		const integer n = my trajectory -> points.size;
 		const double savedArrowSize = Graphics_inqArrowSize (g), arrowSize = 1.0;
-		const double size = 10.0 * arrowSize * Graphics_getResolution (g) / 75.0 / my width;
-		const double sizeSquared = size * size;
+		double resolution = Graphics_getResolution (g);
 		Graphics_setArrowSize (g, arrowSize);
-		integer it = 1;
+		integer it = 0;
 		const TrajectoryPoint lastPoint = my trajectory -> points.at [n];
 		TrajectoryPoint point;
-		while (it <= n - 1) {
+		while (++ it <= (n - 1)) {
 			point = my trajectory -> points.at [n - it];
-			const double dx = getx (lastPoint -> f2) - getx (point -> f2);
-			const double dy = gety (lastPoint -> f1) - gety (point -> f1);
+			const double dx = resolution * (getx (lastPoint -> f2) - getx (point -> f2));
+			const double dy = resolution * (gety (lastPoint -> f1) - gety (point -> f1));
 			const double d2 = dx * dx + dy * dy;
-			if (d2 > sizeSquared)
+			if (sqrt (d2) > arrowSize)
 				break;
-			it ++;
 		}
 		Graphics_arrow (g, getx (point -> f2), gety (point -> f1), getx (lastPoint -> f2), gety (lastPoint -> f1));
 		Graphics_setArrowSize (g, savedArrowSize);
@@ -1211,7 +1209,7 @@ void structVowelEditor :: v_createHelpMenuItems (EditorMenu menu) {
 
 void structVowelEditor :: v_createChildren ()
 {
-	const int button_width = 90, text_width = 95, status_info_width = 330;
+	const int button_width = 90, text_width = 95, status_info_width = 400;
 	int top, bottom, bottom_widgets_top, bottom_widgets_bottom, bottom_widgets_halfway;
 
 	// Three buttons on a row: Play, Reverse, Publish
@@ -1365,10 +1363,10 @@ autoVowelEditor VowelEditor_create (conststring32 title, Daata data) {
 	/*
 		This exdents because it's a hack:
 	*/
-	struct structGuiDrawingArea_ResizeEvent event { my drawingArea, 0 };
+	/*struct structGuiDrawingArea_ResizeEvent event { my drawingArea, 0 };
 	event. width  = GuiControl_getWidth  (my drawingArea);
 	event. height = GuiControl_getHeight (my drawingArea);
-	gui_drawingarea_cb_resize (me.get(), & event);
+	gui_drawingarea_cb_resize (me.get(), & event);*/
 }
 		updateWidgets (me.get());
 		trace (U"exit");


=====================================
external/clapack/lapack.cpp
=====================================
@@ -21166,10 +21166,10 @@ L10:
     integer nbmin;
     bool sname;
     char subnam[1];
-    integer name_len, opts_len;
+    integer name_len;//, opts_len;
 
     name_len = strlen (name__);
-    opts_len = strlen (opts);
+   // opts_len = strlen (opts);
 
 /*  -- LAPACK auxiliary routine (version 3.2) -- */
 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */


=====================================
external/clapack/lapack_dlaq.cpp
=====================================
@@ -13898,8 +13898,8 @@ L90:
 
 double dlamch_(const char *cmach)
 {
-	/* Table of constant values */
-	static double c_b32 = 0.;
+	/* Table of constant values 
+	static double c_b32 = 0.;*/
 
     /* Initialized data */
     static bool first = true;


=====================================
external/clapack/lapack_dt.cpp
=====================================
@@ -2189,7 +2189,7 @@ int dtfttp_(const char *transr, const char *uplo, integer *n, double *arf, doubl
     integer i__1, i__2, i__3;
 
     /* Local variables */
-    integer i__, j, k, n1, n2, ij, jp, js, nt, lda, ijp;
+    integer i__, j, k, n1, n2, ij, jp, js, lda, ijp;
     bool normaltransr, lower, nisodd;
 
 
@@ -2373,7 +2373,7 @@ int dtfttp_(const char *transr, const char *uplo, integer *n, double *arf, doubl
 
 /*     Size of array ARF(0:NT-1) */
 
-    nt = *n * (*n + 1) / 2;
+   // nt = *n * (*n + 1) / 2;
 
 /*     Set N1 and N2 depending on LOWER */
 
@@ -10518,7 +10518,7 @@ int dtpttf_(const char *transr, const char *uplo, integer *n, double *ap, double
     integer i__1, i__2, i__3;
 
     /* Local variables */
-    integer i__, j, k, n1, n2, ij, jp, js, nt, lda, ijp;
+    integer i__, j, k, n1, n2, ij, jp, js, lda, ijp;
     bool normaltransr, lower, nisodd;
 
 
@@ -10703,7 +10703,7 @@ int dtpttf_(const char *transr, const char *uplo, integer *n, double *ap, double
 
 /*     Size of array ARF(0:NT-1) */
 
-    nt = *n * (*n + 1) / 2;
+   // nt = *n * (*n + 1) / 2;
 
 /*     Set N1 and N2 depending on LOWER */
 


=====================================
fon/Sound_and_Spectrum.cpp
=====================================
@@ -104,7 +104,7 @@ autoSound Spectrum_to_Sound (Spectrum me) {
 		bool originalNumberOfSamplesProbablyOdd = ( im [my nx] != 0.0 || my xmax - lastFrequency > 0.25 * my dx );
 		if (my x1 != 0.0)
 			Melder_throw (U"A Fourier-transformable Spectrum must have a first frequency of 0 Hz, not ", my x1, U" Hz.");
-		integer numberOfSamples = 2 * my nx - ( originalNumberOfSamplesProbablyOdd ? 1 : 2 );
+		const integer numberOfSamples = 2 * my nx - ( originalNumberOfSamplesProbablyOdd ? 1 : 2 );
 		autoSound thee = Sound_createSimple (1, 1.0 / my dx, numberOfSamples * my dx);
 		VEC amp = thy z.row (1);
 		double scaling = my dx;
@@ -115,7 +115,8 @@ autoSound Spectrum_to_Sound (Spectrum me) {
 		}
 		if (originalNumberOfSamplesProbablyOdd) {
 			amp [numberOfSamples] = re [my nx] * scaling;
-			if (numberOfSamples > 1) amp [2] = im [my nx] * scaling;
+			if (numberOfSamples > 1)
+				amp [2] = im [my nx] * scaling;
 		} else {
 			amp [2] = re [my nx] * scaling;
 		}
@@ -128,30 +129,31 @@ autoSound Spectrum_to_Sound (Spectrum me) {
 
 autoSpectrum Spectrum_lpcSmoothing (Spectrum me, int numberOfPeaks, double preemphasisFrequency) {
 	try {
-		integer numberOfCoefficients = 2 * numberOfPeaks;
+		const integer numberOfCoefficients = 2 * numberOfPeaks;
 
 		autoSound sound = Spectrum_to_Sound (me);
 		VECpreemphasize_f_inplace (sound -> z.row (1), sound -> dx, preemphasisFrequency);
 		autoVEC a = newVECraw (numberOfCoefficients);
-		double gain = VECburg (a.get(), sound -> z.row(1));
-		for (integer i = 1; i <= numberOfCoefficients; i ++) a [i] = - a [i];
+		const double gain = VECburg (a.get(), sound -> z.row(1));
+		for (integer i = 1; i <= numberOfCoefficients; i ++)
+			a [i] = - a [i];
 		autoSpectrum thee = Data_copy (me);
 
-		integer nfft = 2 * (thy nx - 1);
-		integer ndata = numberOfCoefficients < nfft ? numberOfCoefficients : nfft - 1;
-		double scale = 10.0 * (gain > 0.0 ? sqrt (gain) : 1.0) / numberOfCoefficients;
+		const integer nfft = 2 * (thy nx - 1);
+		const integer ndata = Melder_clippedRight (numberOfCoefficients, nfft - 1);
+		const double scale = 10.0 * (gain > 0.0 ? sqrt (gain) : 1.0) / numberOfCoefficients;
 		autoVEC data = newVECzero (nfft);
 		data [1] = 1.0;
 		for (integer i = 1; i <= ndata; i ++)
 			data [i + 1] = a [i];
 		NUMrealft (data.get(), 1);
-		VEC re = thy z.row (1);
-		VEC im = thy z.row (2);
+		const VEC re = thy z.row (1);
+		const VEC im = thy z.row (2);
 		re [1] = scale / data [1];
 		im [1] = 0.0;
-		integer halfnfft = nfft / 2;
+		const integer halfnfft = nfft / 2;
 		for (integer i = 2; i <= halfnfft; i ++) {
-			double realPart = data [i + i - 1], imaginaryPart = data [i + i];
+			const double realPart = data [i + i - 1], imaginaryPart = data [i + i];
 			re [i] = scale / sqrt (realPart * realPart + imaginaryPart * imaginaryPart) / (1.0 + thy dx * (i - 1) / preemphasisFrequency);
 			im [i] = 0.0;
 		}


=====================================
fon/manual_tutorials.cpp
=====================================
@@ -22,8 +22,11 @@
 void manual_tutorials_init (ManPages me);
 void manual_tutorials_init (ManPages me) {
 
-MAN_BEGIN (U"What's new?", U"ppgb", 20201020)
+MAN_BEGIN (U"What's new?", U"ppgb", 20201027)
 INTRO (U"Latest changes in Praat.")
+NORMAL (U"##6.1.29# (27 October 2020)")
+LIST_ITEM (U"• Mac: corrected a bug revealed by Xcode 12 since 6.1.22 that could cause Praat to crash when using empty vectors, "
+	"such as when querying a Harmonicity for its mean in regions without frames.")
 NORMAL (U"##6.1.28# (20 October 2020)")
 LIST_ITEM (U"• Pause forms: text fields can be multi-line.")
 LIST_ITEM (U"• Removed a bug that caused Praat to crash when editing a PitchTier.")


=====================================
gram/NoulliGridEditor.cpp
=====================================
@@ -39,9 +39,8 @@ Thing_implement (NoulliGridEditor, TimeSoundEditor, 0);
 
 void structNoulliGridEditor :: v_draw () {
 	NoulliGrid data = (NoulliGrid) our data;
-	Graphics_Viewport viewport;
 	if (our d_sound.data) {
-		viewport = Graphics_insetViewport (our graphics.get(), 0.0, 1.0, 1.0 - SOUND_HEIGHT, 1.0);
+		Graphics_Viewport viewport = Graphics_insetViewport (our graphics.get(), 0.0, 1.0, 1.0 - SOUND_HEIGHT, 1.0);
 		Graphics_setColour (our graphics.get(), Melder_WHITE);
 		Graphics_setWindow (our graphics.get(), 0.0, 1.0, 0.0, 1.0);
 		Graphics_fillRectangle (our graphics.get(), 0.0, 1.0, 0.0, 1.0);
@@ -59,9 +58,10 @@ void structNoulliGridEditor :: v_draw () {
 			NoulliTier tier = data -> tiers.at [itier];
 			for (integer ipoint = 1; ipoint < tier -> points.size; ipoint ++) {
 				NoulliPoint point = tier -> points.at [ipoint], nextPoint = tier -> points.at [ipoint + 1];
-				double time = 0.5 * (point -> xmin + point -> xmax), nextTime = 0.5 * (nextPoint -> xmin + nextPoint -> xmax);
+				const double time = 0.5 * (point -> xmin + point -> xmax);
+				const double nextTime = 0.5 * (nextPoint -> xmin + nextPoint -> xmax);
 				if (time > our startWindow && nextTime < our endWindow) {
-					double prob = point -> probabilities [1], nextProb = nextPoint -> probabilities [1];
+					const double prob = point -> probabilities [1], nextProb = nextPoint -> probabilities [1];
 					Graphics_setColour (our graphics.get(), Melder_cyclingBackgroundColour (itier));
 					Graphics_line (our graphics.get(), time, prob, nextTime, nextProb);
 				}
@@ -72,18 +72,19 @@ void structNoulliGridEditor :: v_draw () {
 		Graphics_setWindow (our graphics.get(), our startWindow, our endWindow, 0.0, data -> tiers.size);
 		for (integer itier = 1; itier <= data -> tiers.size; itier ++) {
 			NoulliTier tier = data -> tiers.at [itier];
-			double ymin = data -> tiers.size - itier, ymax = ymin + 1;
+			const double ymin = data -> tiers.size - itier, ymax = ymin + 1;
 			for (integer ipoint = 1; ipoint <= tier -> points.size; ipoint ++) {
 				NoulliPoint point = tier -> points.at [ipoint];
 				if (point -> xmax > our startWindow && point -> xmin < our endWindow) {
-					double xmin = point -> xmin > our startWindow ? point -> xmin : our startWindow;
-					double xmax = point -> xmax < our endWindow ? point -> xmax : our endWindow;
-					double prob1 = 1.0, prob2;
+					const double xmin = Melder_clippedLeft (our startWindow, point -> xmin);
+					const double xmax = Melder_clippedRight (point -> xmax, our endWindow);
+					double prob1 = 1.0;
 					for (integer icategory = 1; icategory <= point -> numberOfCategories; icategory ++) {
-						prob2 = prob1;
+						const double prob2 = prob1;
 						prob1 -= point -> probabilities [icategory];
 						Graphics_setColour (our graphics.get(), Melder_cyclingBackgroundColour (icategory));
-						Graphics_fillRectangle (our graphics.get(), xmin, xmax, ymin + prob1 * (ymax - ymin), ymin + prob2 * (ymax - ymin));
+						Graphics_fillRectangle (our graphics.get(), xmin, xmax,
+								ymin + prob1 * (ymax - ymin), ymin + prob2 * (ymax - ymin));
 					}
 				}
 			}


=====================================
melder/MelderString.h
=====================================
@@ -27,16 +27,16 @@
 		- automatically convert numbers, objects, file names, vectors, and matrices to strings
 */
 
-typedef struct {
+struct MelderString16 {
 	int64 length = 0;
 	int64 bufferSize = 0;
 	char16 *string = nullptr;   // a growing buffer, rarely shrunk (can only be freed by MelderString16_free)
-} MelderString16;
-typedef struct {
+};
+struct MelderString {
 	int64 length = 0;
 	int64 bufferSize = 0;
 	char32 *string = nullptr;   // a growing buffer, rarely shrunk (can only be freed by MelderString_free)
-} MelderString;
+};
 
 void MelderString16_free (MelderString16 *me);   // frees the buffer (and sets other attributes to zero)
 void MelderString_free (MelderString *me);   // frees the buffer (and sets other attributes to zero)


=====================================
melder/NUM.cpp
=====================================
@@ -23,11 +23,25 @@
 */
 
 static longdouble NUMsum_longdouble (constVECVU const& vec) {
+	/*
+		This function started to crash on October 27, 2020.
+		The cause was that if `vec.firstCell == nullptr`,
+		`& vec [1]` is a "null reference" (see the definition of constvectorview::operator[]).
+		This causes "undefined behaviour", even if `p` is never read from that address
+		(which it isn't, because if `vec.firstCell == nullptr`, then `vec.size` must be 0).
+		What precisely happened was that although `vec.size` was null,
+		the processor would branch-predict into the `if (_n & 1)` branch of PAIRWISE_SUM,
+		thereby pre-fetching `p` from the address `& vec [1]`,
+		which would lead to a Bad Access exception.
+
+		A possible repair is to use a pointer instead of a reference.
+	*/
 	if (vec.stride == 1) {
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			//const double *p = & vec [1],   // valid C++ only if vec is well-defined
+			const double *p = & vec. firstCell [1 - 1],   // null *pointers* are fine
 			longdouble (*p),
 			p += 1
 		)
@@ -36,7 +50,8 @@ static longdouble NUMsum_longdouble (constVECVU const& vec) {
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			//const double *p = & vec [1],   // valid C++ only if vec is well-defined
+			const double *p = & vec. firstCell [1 - 1],   // null *pointers* are fine
 			longdouble (*p),
 			p += vec.stride
 		)
@@ -69,7 +84,7 @@ static longdouble NUMsumOfSquaredDifferences_longdouble (constVECVU const& vec,
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (*p - mean) * longdouble (*p - mean),
 			p += 1
 		)
@@ -78,7 +93,7 @@ static longdouble NUMsumOfSquaredDifferences_longdouble (constVECVU const& vec,
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (*p - mean) * longdouble (*p - mean),
 			p += vec.stride
 		)
@@ -90,7 +105,7 @@ static longdouble NUMsum2_longdouble (constVECVU const& vec) {
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (*p) * longdouble (*p),
 			p += 1
 		)
@@ -99,7 +114,7 @@ static longdouble NUMsum2_longdouble (constVECVU const& vec) {
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (*p) * longdouble (*p),
 			p += vec.stride
 		)
@@ -132,7 +147,7 @@ static longdouble NUMsumAbs_longdouble (constVECVU const& vec) {
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (fabs (*p)),
 			p += 1
 		)
@@ -141,7 +156,7 @@ static longdouble NUMsumAbs_longdouble (constVECVU const& vec) {
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (fabs (*p)),
 			p += vec.stride
 		)
@@ -174,7 +189,7 @@ static longdouble NUMsumPower_longdouble (constVECVU const& vec, longdouble powe
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			powl (longdouble (fabs (*p)), power),
 			p += 1
 		)
@@ -183,7 +198,7 @@ static longdouble NUMsumPower_longdouble (constVECVU const& vec, longdouble powe
 		PAIRWISE_SUM (
 			longdouble, sum,
 			integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			powl (longdouble (fabs (*p)), power),
 			p += vec.stride
 		)
@@ -222,14 +237,14 @@ static MelderMeanSumsq_longdouble NUMmeanSumsq (constVECVU const& vec) noexcept
 	double mean = double (result.mean);
 	if (vec.stride == 1) {
 		PAIRWISE_SUM (longdouble, sumsq, integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (*p - mean) * longdouble (*p - mean),
 			p += 1
 		)
 		result.sumsq = sumsq;
 	} else {
 		PAIRWISE_SUM (longdouble, sumsq, integer, vec.size,
-			const double *p = & vec [1],
+			const double *p = vec. firstCell,
 			longdouble (*p - mean) * longdouble (*p - mean),
 			p += vec.stride
 		)
@@ -276,16 +291,16 @@ double NUMinner (constVECVU const& x, constVECVU const& y) noexcept {
 	if (x.stride == 1) {
 		if (y.stride == 1) {
 			PAIRWISE_SUM (longdouble, sum, integer, x.size,
-				const double *px = & x [1];
-				const double *py = & y [1],
+				const double *px = x. firstCell;
+				const double *py = y. firstCell,
 				longdouble (*px) * longdouble (*py),
 				(px += 1, py += 1)
 			)
 			return double (sum);
 		} else {
 			PAIRWISE_SUM (longdouble, sum, integer, x.size,
-				const double *px = & x [1];
-				const double *py = & y [1],
+				const double *px = x. firstCell;
+				const double *py = y. firstCell,
 				longdouble (*px) * longdouble (*py),
 				(px += 1, py += y.stride)
 			)
@@ -293,16 +308,16 @@ double NUMinner (constVECVU const& x, constVECVU const& y) noexcept {
 		}
 	} else if (y.stride == 1) {
 		PAIRWISE_SUM (longdouble, sum, integer, x.size,
-			const double *px = & x [1];
-			const double *py = & y [1],
+			const double *px = x. firstCell;
+			const double *py = y. firstCell,
 			longdouble (*px) * longdouble (*py),
 			(px += x.stride, py += 1)
 		)
 		return double (sum);
 	} else {
 		PAIRWISE_SUM (longdouble, sum, integer, x.size,
-			const double *px = & x [1];
-			const double *py = & y [1],
+			const double *px = x. firstCell;
+			const double *py = y. firstCell,
 			longdouble (*px) * longdouble (*py),
 			(px += x.stride, py += y.stride)
 		)
@@ -311,12 +326,14 @@ double NUMinner (constVECVU const& x, constVECVU const& y) noexcept {
 }
 
 double NUMmean (constVECVU const& vec) {
-		//Melder_require (vec.size >= 1,
-		//	U"mean(vector#): the size of the vector should be greater than 0.");
-		longdouble sum = NUMsum_longdouble (vec);
-		return double (sum / vec.size);
+	if (vec.size <= 0)
+		return undefined;
+	longdouble sum = NUMsum_longdouble (vec);
+	return double (sum / vec.size);
 }
 double NUMmean (constMATVU const& mat) noexcept {
+	if (mat.nrow * mat.ncol <= 0)
+		return undefined;
 	longdouble sum = NUMsum_longdouble (mat);
 	return double (sum / (mat.nrow * mat.ncol));
 }


=====================================
sys/GuiButton.cpp
=====================================
@@ -122,7 +122,11 @@ GuiButton GuiButton_create (GuiForm parent, int left, int right, int top, int bo
 	my d_activateBoss = activateBoss;
 	#if gtk
 		my d_widget = gtk_button_new_with_label (Melder_peek32to8 (buttonText));
-		gtk_button_set_relief (GTK_BUTTON (my d_widget), GTK_RELIEF_HALF);
+		#if ALLOW_GDK_DRAWING
+			gtk_button_set_relief (GTK_BUTTON (my d_widget), GTK_RELIEF_HALF);
+		#else
+			gtk_button_set_relief (GTK_BUTTON (my d_widget), GTK_RELIEF_NORMAL);
+		#endif
 		_GuiObject_setUserData (my d_widget, me.get());
 		my v_positionInForm (my d_widget, left, right, top, bottom, parent);
 		if (flags & GuiButton_DEFAULT || flags & GuiButton_ATTRACTIVE) {


=====================================
sys/GuiLabel.cpp
=====================================
@@ -71,7 +71,12 @@ GuiLabel GuiLabel_create (GuiForm parent, int left, int right, int top, int bott
 		_GuiObject_setUserData (my d_widget, me.get());
 		my v_positionInForm (my d_widget, left, right, top, bottom, parent);
 		g_signal_connect (G_OBJECT (my d_widget), "destroy", G_CALLBACK (_GuiGtkLabel_destroyCallback), me.get());
-		gtk_misc_set_alignment (GTK_MISC (my d_widget), flags & GuiLabel_RIGHT ? 1.0 : flags & GuiLabel_CENTRE ? 0.5 : 0.0, 0.5);
+		#if ALLOW_GDK_DRAWING
+			gtk_misc_set_alignment (GTK_MISC (my d_widget), flags & GuiLabel_RIGHT ? 1.0 : flags & GuiLabel_CENTRE ? 0.5 : 0.0, 0.5);
+		#else
+			gtk_widget_set_halign (GTK_WIDGET (my d_widget), (flags & GuiLabel_RIGHT ? GTK_ALIGN_END : (flags & GuiLabel_CENTRE ? GTK_ALIGN_CENTER : GTK_ALIGN_START)));
+			gtk_widget_set_valign (GTK_WIDGET (my d_widget), GTK_ALIGN_BASELINE);
+		#endif
 	#elif motif
 		my d_widget = _Gui_initializeWidget (xmLabelWidgetClass, parent -> d_widget, labelText);
 		_GuiObject_setUserData (my d_widget, me.get());


=====================================
sys/praat.cpp
=====================================
@@ -1078,6 +1078,7 @@ void praat_init (conststring32 title, int argc, char **argv)
 	while (praatP.argumentNumber < argc && argv [praatP.argumentNumber] [0] == '-') {
 		if (strequ (argv [praatP.argumentNumber], "-")) {
 			praatP.hasCommandLineInput = true;
+			praatP.argumentNumber += 1;
 		} else if (strequ (argv [praatP.argumentNumber], "--open")) {
 			foundTheOpenOption = true;
 			praatP.argumentNumber += 1;
@@ -1573,6 +1574,12 @@ void praat_run () {
 	Melder_assert (Melder_isHorizontalOrVerticalSpace ('\f'));
 	Melder_assert (Melder_isHorizontalOrVerticalSpace ('\v'));
 
+	{
+		double *a = nullptr;
+		double *b = & a [0];
+		Melder_assert (! b);
+	}
+
 	/*
 		According to ISO 30112, a non-breaking space is not a space.
 		We do not agree, as long as spaces are assumed to be word breakers:


=====================================
sys/praat_script.cpp
=====================================
@@ -546,7 +546,7 @@ void praat_executeCommandFromStandardInput (conststring32 programName) {
 		try {
 			praat_executeCommand (nullptr, command32.get());
 		} catch (MelderError) {
-			Melder_flushError (programName, U": command \"", Melder_peek8to32 (command8), U"\" not executed.");
+			Melder_flushError (programName, U": Command \"", Melder_peek8to32 (command8), U"\" not executed.");
 		}
 	}
 }


=====================================
sys/praat_version.h
=====================================
@@ -1,5 +1,5 @@
-#define PRAAT_VERSION_STR 6.1.28
-#define PRAAT_VERSION_NUM 6128
+#define PRAAT_VERSION_STR 6.1.29
+#define PRAAT_VERSION_NUM 6129
 #define PRAAT_YEAR 2020
 #define PRAAT_MONTH October
-#define PRAAT_DAY 20
+#define PRAAT_DAY 27


=====================================
test/fon/Harmonicity.praat
=====================================
@@ -0,0 +1,6 @@
+my.Sound = Create Sound from formula: "sineWithNoise", 1, 0, 1, 44100, "1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)"
+my.Harmonicity = To Harmonicity (cc): 0.01, 75.0, 0.1, 1.0
+mean = Get mean: 0.0, 0.005
+writeInfoLine: mean
+removeObject: my.Sound, my.Harmonicity
+


=====================================
test/manually/bold.praat
=====================================
@@ -0,0 +1,5 @@
+target = Create Strings as characters: "intention"
+source = Create Strings as characters: "execution"
+plusObject: target
+edt = To EditDistanceTable
+Draw: "decimal", 1, 0


=====================================
test/manually/test2.praat
=====================================
@@ -0,0 +1,2 @@
+pauseScript: "simply ignored on the command line?"
+writeInfoLine: "hoi"
\ No newline at end of file



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

-- 
View it on GitLab: https://salsa.debian.org/med-team/praat/-/commit/0f3f6d3815b825b73cad40c83244ff22df3f7d9e
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/20201101/e52356ef/attachment-0001.html>


More information about the debian-med-commit mailing list