1 /* praat_Sound.cpp
2  *
3  * Copyright (C) 1992-2021 Paul Boersma
4  *
5  * This code is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  *
10  * This code is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this work. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "Ltas.h"
20 #include "Manipulation.h"
21 #include "ParamCurve.h"
22 #include "Sound_and_Spectrogram.h"
23 #include "Sound_and_Spectrum.h"
24 #include "Sound_extensions.h"
25 #include "Sound_to_Cochleagram.h"
26 #include "Sound_to_Formant.h"
27 #include "Sound_to_Harmonicity.h"
28 #include "Sound_to_Intensity.h"
29 #include "Sound_to_Pitch.h"
30 #include "Sound_to_PointProcess.h"
31 #include "SoundEditor.h"
32 #include "SoundRecorder.h"
33 #include "SoundSet.h"
34 #include "SpectrumEditor.h"
35 #include "TextGrid_Sound.h"
36 #include "mp3.h"
37 
38 #include "praat_Sound.h"
39 
40 /***** LONGSOUND *****/
41 
DIRECT(INFO_NONE__LongSound_concatenate)42 DIRECT (INFO_NONE__LongSound_concatenate) {
43 	INFO_NONE
44 		Melder_information (U"To concatenate LongSound objects, "
45 			"select them in the list\nand choose \"Save as WAV file...\" or a similar command.\n"
46 			"The result will be a sound file that contains\nthe concatenation of the selected sounds."
47 		);
48 	INFO_NONE_END
49 }
50 
51 FORM (NEW_LongSound_extractPart, U"LongSound: Extract part", nullptr) {
52 	REAL (fromTime, U"left Time range (s)", U"0.0")
53 	REAL (toTime, U"right Time range (s)", U"1.0")
54 	BOOLEAN (preserveTimes, U"Preserve times", true)
55 	OK
56 DO
57 	CONVERT_EACH_TO_ONE (LongSound)
58 		autoSound result = LongSound_extractPart (me, fromTime, toTime, preserveTimes);
59 	CONVERT_EACH_TO_ONE_END (my name.get())
60 }
61 
62 FORM (REAL_LongSound_getIndexFromTime, U"LongSound: Get sample index from time", U"Sound: Get index from time...") {
63 	REAL (time, U"Time (s)", U"0.5")
64 	OK
65 DO
66 	QUERY_ONE_FOR_REAL (LongSound)
67 		const double result = Sampled_xToIndex (me, time);
68 	QUERY_ONE_FOR_REAL_END (U" (index at ", time, U" seconds)")
69 }
70 
DIRECT(REAL_LongSound_getSamplePeriod)71 DIRECT (REAL_LongSound_getSamplePeriod) {
72 	QUERY_ONE_FOR_REAL (LongSound)
73 		const double result = my dx;
74 	QUERY_ONE_FOR_REAL_END (U" seconds");
75 }
76 
DIRECT(REAL_LongSound_getSampleRate)77 DIRECT (REAL_LongSound_getSampleRate) {
78 	QUERY_ONE_FOR_REAL (LongSound)
79 		const double result = 1.0 / my dx;
80 	QUERY_ONE_FOR_REAL_END (U" Hz")
81 }
82 
83 FORM (REAL_LongSound_getTimeFromIndex, U"LongSound: Get time from sample index", U"Sound: Get time from index...") {
84 	INTEGER (sampleIndex, U"Sample index", U"100")
85 	OK
86 DO
87 	QUERY_ONE_FOR_REAL (LongSound)
88 		const double result = Sampled_indexToX (me, sampleIndex);
89 	QUERY_ONE_FOR_REAL_END (U" seconds")
90 }
91 
DIRECT(INTEGER_LongSound_getNumberOfSamples)92 DIRECT (INTEGER_LongSound_getNumberOfSamples) {
93 	QUERY_ONE_FOR_REAL (LongSound)
94 		const integer result = my nx;
95 	QUERY_ONE_FOR_REAL_END (U" samples")
96 }
97 
DIRECT(HELP__LongSound_help)98 DIRECT (HELP__LongSound_help) {
99 	HELP (U"LongSound")
100 }
101 
102 FORM_READ (READ1_LongSound_open, U"Open long sound file", nullptr, true) {
103 	READ_ONE
104 		autoLongSound result = LongSound_open (file);
105 	READ_ONE_END
106 }
107 
108 FORM (PLAY_LongSound_playPart, U"LongSound: Play part", nullptr) {
109 	REAL (fromTime, U"left Time range (s)", U"0.0")
110 	REAL (toTime, U"right Time range (s)", U"10.0")
111 	OK
112 DO
113 	PLAY_EACH (LongSound)
114 		LongSound_playPart (me, fromTime, toTime, nullptr, nullptr);
115 	PLAY_EACH_END
116 }
117 
118 FORM (SAVE_ONE__LongSound_savePartAsAudioFile, U"LongSound: Save part as audio file", nullptr) {
119 	OUTFILE (audioFile, U"Audio file:", U"")
120 	RADIO (type, U"Type", 3)
121 	{ int i; for (i = 1; i <= Melder_NUMBER_OF_AUDIO_FILE_TYPES; i ++) {
122 		RADIOBUTTON (Melder_audioFileTypeString (i))
123 	}}
124 	REAL (fromTime, U"left Time range (s)", U"0.0")
125 	REAL (toTime, U"right Time range (s)", U"10.0")
126 	OK
127 DO
SAVE_ONE(LongSound)128 	SAVE_ONE (LongSound)
129 		structMelderFile file { };
130 		Melder_relativePathToFile (audioFile, & file);
131 		LongSound_savePartAsAudioFile (me, type, fromTime, toTime, & file, 16);
132 	SAVE_ONE_END
133 }
134 
135 FORM (NEW_LongSound_to_TextGrid, U"LongSound: To TextGrid...", U"LongSound: To TextGrid...") {
136 	SENTENCE (tierNames, U"Tier names", U"Mary John bell")
137 	SENTENCE (pointTiers, U"Point tiers", U"bell")
138 	OK
139 DO
140 	CONVERT_EACH_TO_ONE (LongSound)
141 		autoTextGrid result = TextGrid_create (my xmin, my xmax, tierNames, pointTiers);
142 	CONVERT_EACH_TO_ONE_END (my name.get())
143 }
144 
DIRECT(EDITOR_ONE__LongSound_view)145 DIRECT (EDITOR_ONE__LongSound_view) {
146 	EDITOR_ONE (a,LongSound)
147 		autoSoundEditor editor = SoundEditor_create (ID_AND_FULL_NAME, me);
148 	EDITOR_ONE_END
149 }
150 
151 FORM_SAVE (SAVE_ALL__LongSound_saveAsAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
152 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
153 		LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
154 	SAVE_ALL_LISTED_END
155 }
156 
157 FORM_SAVE (SAVE_ALL__LongSound_saveAsAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
158 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
159 		LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
160 	SAVE_ALL_LISTED_END
161 }
162 
163 FORM_SAVE (SAVE_ALL__LongSound_saveAsNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
164 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
165 		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
166 	SAVE_ALL_LISTED_END
167 }
168 
169 FORM_SAVE (SAVE_ALL__LongSound_saveAsNistFile, U"Save as NIST file", nullptr, U"nist") {
170 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
171 		LongSound_concatenate (list.get(), file, Melder_NIST, 16);
172 	SAVE_ALL_LISTED_END
173 }
174 
175 FORM_SAVE (SAVE_ALL__LongSound_saveAsFlacFile, U"Save as FLAC file", nullptr, U"flac") {
176 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
177 		LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
178 	SAVE_ALL_LISTED_END
179 }
180 
181 FORM_SAVE (SAVE_ALL__LongSound_saveAsWavFile, U"Save as WAV file", nullptr, U"wav") {
182 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
183 		LongSound_concatenate (list.get(), file, Melder_WAV, 16);
184 	SAVE_ALL_LISTED_END
185 }
186 
187 FORM_SAVE (SAVE_ONE__LongSound_saveLeftChannelAsAifcFile, U"Save left channel as AIFC file", nullptr, U"aifc") {
188 	SAVE_ONE (LongSound)
189 		LongSound_saveChannelAsAudioFile (me, Melder_AIFC, 0, file);
190 	SAVE_ONE_END
191 }
192 
193 FORM_SAVE (SAVE_ONE__LongSound_saveLeftChannelAsAiffFile, U"Save left channel as AIFF file", nullptr, U"aiff") {
194 	SAVE_ONE (LongSound)
195 		LongSound_saveChannelAsAudioFile (me, Melder_AIFF, 0, file);
196 	SAVE_ONE_END
197 }
198 
199 FORM_SAVE (SAVE_ONE__LongSound_saveLeftChannelAsNextSunFile, U"Save left channel as NeXT/Sun file", nullptr, U"au") {
200 	SAVE_ONE (LongSound)
201 		LongSound_saveChannelAsAudioFile (me, Melder_NEXT_SUN, 0, file);
202 	SAVE_ONE_END
203 }
204 
205 FORM_SAVE (SAVE_ONE__LongSound_saveLeftChannelAsNistFile, U"Save left channel as NIST file", nullptr, U"nist") {
206 	SAVE_ONE (LongSound)
207 		LongSound_saveChannelAsAudioFile (me, Melder_NIST, 0, file);
208 	SAVE_ONE_END
209 }
210 
211 FORM_SAVE (SAVE_ONE__LongSound_saveLeftChannelAsFlacFile, U"Save left channel as FLAC file", nullptr, U"flac") {
212 	SAVE_ONE (LongSound)
213 		LongSound_saveChannelAsAudioFile (me, Melder_FLAC, 0, file);
214 	SAVE_ONE_END
215 }
216 
217 FORM_SAVE (SAVE_ONE__LongSound_saveLeftChannelAsWavFile, U"Save left channel as WAV file", nullptr, U"wav") {
218 	SAVE_ONE (LongSound)
219 		LongSound_saveChannelAsAudioFile (me, Melder_WAV, 0, file);
220 	SAVE_ONE_END
221 }
222 
223 FORM_SAVE (SAVE_ONE__LongSound_saveRightChannelAsAifcFile, U"Save right channel as AIFC file", nullptr, U"aifc") {
224 	SAVE_ONE (LongSound)
225 		LongSound_saveChannelAsAudioFile (me, Melder_AIFC, 1, file);
226 	SAVE_ONE_END
227 }
228 
229 FORM_SAVE (SAVE_ONE__LongSound_saveRightChannelAsAiffFile, U"Save right channel as AIFF file", nullptr, U"aiff") {
230 	SAVE_ONE (LongSound)
231 		LongSound_saveChannelAsAudioFile (me, Melder_AIFF, 1, file);
232 	SAVE_ONE_END
233 }
234 
235 FORM_SAVE (SAVE_ONE__LongSound_saveRightChannelAsNextSunFile, U"Save right channel as NeXT/Sun file", nullptr, U"au") {
236 	SAVE_ONE (LongSound)
237 		LongSound_saveChannelAsAudioFile (me, Melder_NEXT_SUN, 1, file);
238 	SAVE_ONE_END
239 }
240 
241 FORM_SAVE (SAVE_ONE__LongSound_saveRightChannelAsNistFile, U"Save right channel as NIST file", nullptr, U"nist") {
242 	SAVE_ONE (LongSound)
243 		LongSound_saveChannelAsAudioFile (me, Melder_NIST, 1, file);
244 	SAVE_ONE_END
245 }
246 
247 FORM_SAVE (SAVE_ONE__LongSound_saveRightChannelAsFlacFile, U"Save right channel as FLAC file", 0, U"flac") {
248 	SAVE_ONE (LongSound)
249 		LongSound_saveChannelAsAudioFile (me, Melder_FLAC, 1, file);
250 	SAVE_ONE_END
251 }
252 
253 FORM_SAVE (SAVE_ONE__LongSound_saveRightChannelAsWavFile, U"Save right channel as WAV file", 0, U"wav") {
254 	SAVE_ONE (LongSound)
255 		LongSound_saveChannelAsAudioFile (me, Melder_WAV, 1, file);
256 	SAVE_ONE_END
257 }
258 
259 FORM (PREFS__LongSoundPrefs, U"LongSound preferences", U"LongSound") {
260 	LABEL (U"This setting determines the maximum number of seconds")
261 	LABEL (U"for viewing the waveform and playing a sound in the LongSound window.")
262 	LABEL (U"The LongSound window can become very slow if you set it too high.")
263 	NATURAL (maximumViewablePart, U"Maximum viewable part (seconds)", U"60")
264 	LABEL (U"Note: this setting works for the next long sound file that you open,")
265 	LABEL (U"not for currently existing LongSound objects.")
266 OK
267 	SET_INTEGER (maximumViewablePart, LongSound_getBufferSizePref_seconds ())
268 DO
269 	PREFS
270 		LongSound_setBufferSizePref_seconds (maximumViewablePart);
271 	PREFS_END
272 }
273 
274 /********** LONGSOUND & SOUND **********/
275 
276 FORM_SAVE (SAVE_ALL__LongSound_Sound_saveAsAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
277 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
278 		LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
279 	SAVE_ALL_LISTED_END
280 }
281 
282 FORM_SAVE (SAVE_ALL__LongSound_Sound_saveAsAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
283 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
284 		LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
285 	SAVE_ALL_LISTED_END
286 }
287 
288 FORM_SAVE (SAVE_ALL__LongSound_Sound_saveAsNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
289 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
290 		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
291 	SAVE_ALL_LISTED_END
292 }
293 
294 FORM_SAVE (SAVE_ALL__LongSound_Sound_saveAsNistFile, U"Save as NIST file", nullptr, U"nist") {
295 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
296 		LongSound_concatenate (list.get(), file, Melder_NIST, 16);
297 	SAVE_ALL_LISTED_END
298 }
299 
300 FORM_SAVE (SAVE_ALL__LongSound_Sound_saveAsFlacFile, U"Save as FLAC file", nullptr, U"flac") {
301 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
302 		LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
303 	SAVE_ALL_LISTED_END
304 }
305 
306 FORM_SAVE (SAVE_ALL__LongSound_Sound_saveAsWavFile, U"Save as WAV file", nullptr, U"wav") {
307 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
308 		LongSound_concatenate (list.get(), file, Melder_WAV, 16);
309 	SAVE_ALL_LISTED_END
310 }
311 
312 /********** SOUND **********/
313 
314 FORM (MODIFY_Sound_add, U"Sound: Add", nullptr) {
315 	LABEL (U"The following number will be added to the amplitudes of ")
316 	LABEL (U"all samples of the sound.")
317 	REAL (number, U"Number", U"0.1")
318 	OK
319 DO
320 	MODIFY_EACH (Sound)
321 		Vector_addScalar (me, number);
322 	MODIFY_EACH_END
323 }
324 
325 FORM (CONVERT_EACH_TO_ONE__Sound_autoCorrelate, U"Sound: autocorrelate", U"Sound: Autocorrelate...") {
326 	RADIO_ENUM (kSounds_convolve_scaling, amplitudeScaling,
327 			U"Amplitude scaling", kSounds_convolve_scaling::DEFAULT)
328 	RADIO_ENUM (kSounds_convolve_signalOutsideTimeDomain, signalOutsideTimeDomainIs,
329 			U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain::DEFAULT)
330  	OK
331 DO
332 	CONVERT_EACH_TO_ONE (Sound)
333 		autoSound result = Sound_autoCorrelate (me, amplitudeScaling, signalOutsideTimeDomainIs);
334 	CONVERT_EACH_TO_ONE_END (U"ac_", my name.get())
335 }
336 
DIRECT(COMBINE_ALL_TO_ONE__Sounds_combineToStereo)337 DIRECT (COMBINE_ALL_TO_ONE__Sounds_combineToStereo) {
338 	COMBINE_ALL_TO_ONE (Sound)
339 		autoSound result = Sounds_combineToStereo (& list);
340 		const integer numberOfChannels = result -> ny;   // dereference before transferring
341 	COMBINE_ALL_TO_ONE_END (U"combined_", numberOfChannels)
342 }
343 
DIRECT(COMBINE_ALL_TO_ONE__Sounds_combineIntoSoundList)344 DIRECT (COMBINE_ALL_TO_ONE__Sounds_combineIntoSoundList) {
345 	COMBINE_ALL_TO_ONE (Sound)
346 		autoSoundList result = SoundList_create ();
347 		for (integer iobject = 1; iobject <= list.size; iobject ++)
348 			result -> addItem_move (Data_copy (list.at [iobject]));
349 	COMBINE_ALL_TO_ONE_END (U"list")
350 }
351 
DIRECT(COMBINE_ALL_TO_ONE__Sounds_combineIntoSoundSet)352 DIRECT (COMBINE_ALL_TO_ONE__Sounds_combineIntoSoundSet) {
353 	COMBINE_ALL_TO_ONE (Sound)
354 		autoSoundSet result = SoundSet_create ();
355 		for (integer iobject = 1; iobject <= list.size; iobject ++)
356 			result -> addItem_move (Data_copy (list.at [iobject]));
357 	COMBINE_ALL_TO_ONE_END (U"ensemble")
358 }
359 
DIRECT(COMBINE_ALL_TO_ONE__Sounds_concatenate)360 DIRECT (COMBINE_ALL_TO_ONE__Sounds_concatenate) {
361 	COMBINE_ALL_TO_ONE (Sound)
362 		autoSound result = Sounds_concatenate (list, 0.0);
363 	COMBINE_ALL_TO_ONE_END (U"chain")
364 }
365 
366 FORM (COMBINE_ALL_TO_ONE__Sounds_concatenateWithOverlap, U"Sounds: Concatenate with overlap", U"Sounds: Concatenate with overlap...") {
367 	POSITIVE (overlap, U"Overlap (s)", U"0.01")
368 	OK
369 DO
370 	COMBINE_ALL_TO_ONE (Sound)
371 		autoSound result = Sounds_concatenate (list, overlap);
372 	COMBINE_ALL_TO_ONE_END (U"chain")
373 }
374 
DIRECT(CONVERT_ALL_TO_MULTIPLE__Sounds_concatenateRecoverably)375 DIRECT (CONVERT_ALL_TO_MULTIPLE__Sounds_concatenateRecoverably) {
376 	CONVERT_ALL_LISTED_TO_MULTIPLE (Sound, SoundList)
377 		integer numberOfChannels = 0, nx = 0, iinterval = 0;
378 		double dx = 0.0, tmin = 0.0;
379 		for (integer isound = 1; isound <= list->size; isound ++) {
380 			Sound me = list->at [isound];
381 			if (numberOfChannels == 0) {
382 				numberOfChannels = my ny;
383 			} else if (my ny != numberOfChannels) {
384 				Melder_throw (U"To concatenate sounds, their numbers of channels (mono, stereo) should be equal.");
385 			}
386 			if (dx == 0.0) {
387 				dx = my dx;
388 			} else if (my dx != dx) {
389 				Melder_throw (U"To concatenate sounds, their sampling frequencies should be equal.\n"
390 						"You could resample one or more of the sounds before concatenating.");
391 			}
392 			nx += my nx;
393 		}
394 		autoSound thee = Sound_create (numberOfChannels, 0.0, nx * dx, nx, dx, 0.5 * dx);
395 		autoTextGrid him = TextGrid_create (0.0, nx * dx, U"labels", U"");
396 		nx = 0;
397 		for (integer isound = 1; isound <= list->size; isound ++) {
398 			Sound me = list->at [isound];
399 			const double tmax = tmin + my nx * dx;
400 			thy z.verticalBand (nx + 1, nx + my nx)  <<=  my z.all();
401 			iinterval ++;
402 			if (iinterval > 1)
403 				TextGrid_insertBoundary (him.get(), 1, tmin);
404 			TextGrid_setIntervalText (him.get(), 1, iinterval, my name.get());
405 			nx += my nx;
406 			tmin = tmax;
407 		}
408 		praat_new (thee.move(), U"chain");
409 		praat_new (him.move(), U"chain");
410 	CONVERT_ALL_LISTED_TO_MULTIPLE_END
411 }
412 
DIRECT(CONVERT_EACH_TO_ONE__Sound_convertToMono)413 DIRECT (CONVERT_EACH_TO_ONE__Sound_convertToMono) {
414 	CONVERT_EACH_TO_ONE (Sound)
415 		autoSound result = Sound_convertToMono (me);
416 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_mono")
417 }
418 
DIRECT(CONVERT_EACH_TO_ONE__Sound_convertToStereo)419 DIRECT (CONVERT_EACH_TO_ONE__Sound_convertToStereo) {
420 	CONVERT_EACH_TO_ONE (Sound)
421 		autoSound result = Sound_convertToStereo (me);
422 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_stereo")
423 }
424 
DIRECT(CONVERT_TWO_TO_ONE__Sounds_convolve_old)425 DIRECT (CONVERT_TWO_TO_ONE__Sounds_convolve_old) {
426 	CONVERT_TWO_TO_ONE (Sound)
427 		autoSound result = Sounds_convolve (me, you,
428 			kSounds_convolve_scaling::SUM, kSounds_convolve_signalOutsideTimeDomain::ZERO);
429 	CONVERT_TWO_TO_ONE_END (my name.get(), U"_", your name.get())
430 }
431 
432 FORM (CONVERT_TWO_TO_ONE__Sounds_convolve, U"Sounds: Convolve", U"Sounds: Convolve...") {
433 	RADIO_ENUM (kSounds_convolve_scaling, amplitudeScaling,
434 			U"Amplitude scaling", kSounds_convolve_scaling::DEFAULT)
435 	RADIO_ENUM (kSounds_convolve_signalOutsideTimeDomain, signalOutsideTimeDomainIs,
436 			U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain::DEFAULT)
437 	OK
438 DO
439 	CONVERT_TWO_TO_ONE (Sound)
440 		autoSound result = Sounds_convolve (me, you, amplitudeScaling, signalOutsideTimeDomainIs);
441 	CONVERT_TWO_TO_ONE_END (my name.get(), U"_", your name.get())
442 }
443 
common_Sound_create(integer numberOfChannels,double startTime,double endTime,double samplingFrequency,conststring32 formula,Interpreter interpreter)444 static autoSound common_Sound_create (integer numberOfChannels, double startTime, double endTime,
445 	double samplingFrequency, conststring32 formula, Interpreter interpreter)
446 {
447 	const double numberOfSamples_real = round ((endTime - startTime) * samplingFrequency);
448 	if (endTime <= startTime) {
449 		if (endTime == startTime)
450 			Melder_appendError (U"A Sound cannot have a duration of zero.");
451 		else
452 			Melder_appendError (U"A Sound cannot have a duration less than zero.");
453 		if (startTime == 0.0)
454 			Melder_throw (U"Please set the end time to something greater than 0 seconds.");
455 		else
456 			Melder_throw (U"Please lower the start time or raise the end time.");
457 	}
458 	if (samplingFrequency <= 0.0) {
459 		Melder_appendError (U"A Sound cannot have a negative sampling frequency.");
460 		Melder_throw (U"Please set the sampling frequency to something greater than zero, e.g. 44100 Hz.");
461 	}
462 	if (numberOfChannels < 1)
463 		Melder_throw (U"A Sound cannot have zero channels.");
464 	if (numberOfSamples_real < 1.0) {
465 		Melder_appendError (U"A Sound cannot have zero samples.");
466 		if (startTime == 0.0)
467 			Melder_throw (U"Please raise the end time.");
468 		else
469 			Melder_throw (U"Please lower the start time or raise the end time.");
470 	}
471 	if (numberOfSamples_real > INT54_MAX) {
472 		Melder_appendError (U"A Sound cannot have ", numberOfSamples_real, U" samples; the maximum is ",
473 				Melder_bigInteger (INT54_MAX), U" samples (or less, depending on your computer's memory).");
474 		if (startTime == 0.0)
475 			Melder_throw (U"Please lower the end time or the sampling frequency.");
476 		else
477 			Melder_throw (U"Please raise the start time, lower the end time, or lower the sampling frequency.");
478 	}
479 	const integer numberOfSamples = (int64) numberOfSamples_real;
480 	autoSound sound;
481 	try {
482 		sound = Sound_create (numberOfChannels, startTime, endTime, numberOfSamples, 1.0 / samplingFrequency,
483 				startTime + 0.5 * (endTime - startTime - (numberOfSamples - 1) / samplingFrequency));
484 	} catch (MelderError) {
485 		if (str32str (Melder_getError (), U"memory")) {
486 			Melder_clearError ();
487 			Melder_appendError (U"There is not enough memory to create a Sound that contains ", Melder_bigInteger (numberOfSamples), U" samples.");
488 			if (startTime == 0.0)
489 				Melder_throw (U"You could lower the end time or the sampling frequency and try again.");
490 			else
491 				Melder_throw (U"You could raise the start time or lower the end time or the sampling frequency, and try again.");
492 		} else {
493 			throw;   // unexpected error; wait for generic message
494 		}
495 	}
496 	Matrix_formula (sound.get(), formula, interpreter, nullptr);
497 	return sound;
498 }
499 
500 FORM (CREATE_ONE__Sound_create, U"Create mono Sound", U"Create Sound from formula...") {
501 	WORD (name, U"Name", U"sineWithNoise")
502 	REAL (startTime, U"Start time (s)", U"0.0")
503 	REAL (endTime, U"End time (s)", U"1.0")
504 	REAL (samplingFrequency, U"Sampling frequency (Hz)", U"44100")
505 	FORMULA (formula, U"Formula", U"1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)")
506 	OK
507 DO
508 	CREATE_ONE
509 		autoSound result = common_Sound_create (1, startTime, endTime, samplingFrequency, formula, interpreter);
510 	CREATE_ONE_END (name)
511 }
512 
513 FORM (CREATE_ONE__Sound_createFromFormula, U"Create Sound from formula", U"Create Sound from formula...") {
514 	WORD (name, U"Name", U"sineWithNoise")
515 	CHANNEL (numberOfChannels, U"Number of channels", U"1 (= mono)")
516 	REAL (startTime, U"Start time (s)", U"0.0")
517 	REAL (endTime, U"End time (s)", U"1.0")
518 	REAL (samplingFrequency, U"Sampling frequency (Hz)", U"44100")
519 	FORMULA (formula, U"Formula", U"1/2 * sin(2*pi*377*x) + randomGauss(0,0.1)")
520 	OK
521 DO
522 	CREATE_ONE
523 		autoSound result = common_Sound_create (numberOfChannels, startTime, endTime, samplingFrequency, formula, interpreter);
524 	CREATE_ONE_END (name)
525 }
526 
527 FORM (CREATE_ONE__Sound_createAsPureTone, U"Create Sound as pure tone", U"Create Sound as pure tone...") {
528 	WORD (name, U"Name", U"tone")
529 	CHANNEL (numberOfChannels, U"Number of channels", U"1 (= mono)")
530 	REAL (startTime, U"Start time (s)", U"0.0")
531 	REAL (endTime, U"End time (s)", U"0.4")
532 	POSITIVE (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
533 	POSITIVE (toneFrequency, U"Tone frequency (Hz)", U"440.0")
534 	POSITIVE (amplitude, U"Amplitude (Pa)", U"0.2")
535 	POSITIVE (fadeInDuration, U"Fade-in duration (s)", U"0.01")
536 	POSITIVE (fadeOutDuration, U"Fade-out duration (s)", U"0.01")
537 	OK
538 DO
539 	CREATE_ONE
540 		autoSound result = Sound_createAsPureTone (numberOfChannels, startTime, endTime,
541 				samplingFrequency, toneFrequency, amplitude, fadeInDuration, fadeOutDuration);
542 	CREATE_ONE_END (name)
543 }
544 
545 FORM (CREATE_ONE__Sound_createAsToneComplex, U"Create Sound as tone complex", U"Create Sound as tone complex...") {
546 	WORD (name, U"Name", U"toneComplex")
547 	REAL (startTime, U"Start time (s)", U"0.0")
548 	REAL (endTime, U"End time (s)", U"1.0")
549 	POSITIVE (samplingFrequency, U"Sampling frequency (Hz)", U"44100.0")
550 	RADIOx (phase, U"Phase", 2, Sound_TONE_COMPLEX_SINE)
551 		RADIOBUTTON (U"sine")
552 		RADIOBUTTON (U"cosine")
553 	POSITIVE (frequencyStep, U"Frequency step (Hz)", U"100.0")
554 	REAL (firstFrequency, U"First frequency (Hz)", U"0.0 (= frequency step)")
555 	REAL (ceiling, U"Ceiling (Hz)", U"0.0 (= Nyquist)")
556 	INTEGER (numberOfComponents, U"Number of components", U"0 (= maximum)")
557 	OK
558 DO
559 	CREATE_ONE
560 		autoSound result = Sound_createAsToneComplex (startTime, endTime,
561 				samplingFrequency, phase, frequencyStep, firstFrequency, ceiling, numberOfComponents);
562 	CREATE_ONE_END (name)
563 }
564 
565 FORM (CONVERT_TWO_TO_ONE__old_Sounds_crossCorrelate, U"Cross-correlate (short)", nullptr) {
566 	REAL (fromLag, U"From lag (s)", U"-0.1")
567 	REAL (toLag, U"To lag (s)", U"0.1")
568 	BOOLEAN (normalize, U"Normalize", true)
569 	OK
570 DO
571 	CONVERT_TWO_TO_ONE (Sound)
572 		autoSound result = Sounds_crossCorrelate_short (me, you, fromLag, toLag, normalize);
573 	CONVERT_TWO_TO_ONE_END (U"cc_", my name.get(), U"_", your name.get())
574 }
575 
576 FORM (CONVERT_TWO_TO_ONE__Sounds_crossCorrelate, U"Sounds: Cross-correlate", U"Sounds: Cross-correlate...") {
577 	RADIO_ENUM (kSounds_convolve_scaling, amplitudeScaling,
578 			U"Amplitude scaling", kSounds_convolve_scaling::DEFAULT)
579 	RADIO_ENUM (kSounds_convolve_signalOutsideTimeDomain, signalOutsideTimeDomainIs,
580 			U"Signal outside time domain is...", kSounds_convolve_signalOutsideTimeDomain::DEFAULT)
581 	OK
582 DO_ALTERNATIVE (CONVERT_TWO_TO_ONE__old_Sounds_crossCorrelate)
583 	CONVERT_TWO_TO_ONE (Sound)
584 		autoSound result = Sounds_crossCorrelate (me, you, amplitudeScaling, signalOutsideTimeDomainIs);
585 	CONVERT_TWO_TO_ONE_END (U"cc_", my name.get(), U"_", your name.get())
586 }
587 
588 FORM (MODIFY_Sound_deemphasizeInplace, U"Sound: De-emphasize (in-place)", U"Sound: De-emphasize (in-place)...") {
589 	REAL (fromFrequency, U"From frequency (Hz)", U"50.0")
590 	OK
591 DO
592 	MODIFY_EACH (Sound)
593 		Sound_deEmphasis (me, fromFrequency);
594 		Vector_scale (me, 0.99);
595 	MODIFY_EACH_END
596 }
597 
598 FORM (CONVERT_EACH_TO_ONE__Sound_deepenBandModulation, U"Deepen band modulation", U"Sound: Deepen band modulation...") {
599 	POSITIVE (enhancement, U"Enhancement (dB)", U"20.0")
600 	POSITIVE (fromFrequency, U"From frequency (Hz)", U"300.0")
601 	POSITIVE (toFrequency, U"To frequency (Hz)", U"8000.0")
602 	POSITIVE (slowModulation, U"Slow modulation (Hz)", U"3.0")
603 	POSITIVE (fastModulation, U"Fast modulation (Hz)", U"30.0")
604 	POSITIVE (bandSmoothing, U"Band smoothing (Hz)", U"100.0")
605 	OK
606 DO
607 	CONVERT_EACH_TO_ONE (Sound)
608 		autoSound result = Sound_deepenBandModulation (me, enhancement, fromFrequency, toFrequency,
609 				slowModulation, fastModulation, bandSmoothing);
610 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_", Melder_roundTowardsZero (enhancement))
611 }
612 
613 FORM (GRAPHICS_EACH__old_Sound_draw, U"Sound: Draw", nullptr) {
614 	REAL (fromTime, U"left Time range (s)", U"0.0")
615 	REAL (toTime, U"right Time range", U"0.0 (= all)")
616 	REAL (fromAmplitude, U"left Amplitude range", U"0.0")
617 	REAL (toAmplitude, U"right Amplitude range", U"0.0 (= auto)")
618 	BOOLEAN (garnish, U"Garnish", true)
619 	OK
620 DO
621 	GRAPHICS_EACH (Sound)
622 		Sound_draw (me, GRAPHICS, fromTime, toTime,
623 				fromAmplitude, toAmplitude, garnish, U"curve");
624 	GRAPHICS_EACH_END
625 }
626 
627 FORM (GRAPHICS_EACH__Sound_draw, U"Sound: Draw", nullptr) {
628 	REAL (fromTime, U"left Time range (s)", U"0.0")
629 	REAL (toTime, U"right Time range", U"0.0 (= all)")
630 	REAL (fromAmplitude, U"left Amplitude range", U"0.0")
631 	REAL (toAmplitude, U"right Amplitude range", U"0.0 (= auto)")
632 	BOOLEAN (garnish, U"Garnish", true)
633 	LABEL (U"")
634 	OPTIONMENUSTR (drawingMethod, U"Drawing method", 1)
635 		OPTION (U"curve")
636 		OPTION (U"bars")
637 		OPTION (U"poles")
638 		OPTION (U"speckles")
639 	OK
640 DO_ALTERNATIVE (GRAPHICS_EACH__old_Sound_draw)
641 	GRAPHICS_EACH (Sound)
642 		Sound_draw (me, GRAPHICS, fromTime, toTime,
643 				fromAmplitude, toAmplitude, garnish, drawingMethod);
644 	GRAPHICS_EACH_END
645 }
646 
cb_SoundEditor_publication(Editor,autoDaata publication)647 static void cb_SoundEditor_publication (Editor /* me */, autoDaata publication) {
648 	/*
649 	 * Keep the gate for error handling.
650 	 */
651 	try {
652 		const bool isaSpectrum = Thing_isa (publication.get(), classSpectrum);
653 		praat_new (publication.move(), U"");
654 		praat_updateSelection ();
655 		if (isaSpectrum) {
656 			int IOBJECT;
657 			FIND_ONE_WITH_IOBJECT (Spectrum)
658 			autoSpectrumEditor editor2 = SpectrumEditor_create (ID_AND_FULL_NAME, me);
659 			praat_installEditor (editor2.get(), IOBJECT);
660 			editor2.releaseToUser();
661 		}
662 	} catch (MelderError) {
663 		Melder_flushError ();
664 	}
665 }
DIRECT(EDITOR_ONE__Sound_viewAndEdit)666 DIRECT (EDITOR_ONE__Sound_viewAndEdit) {
667 	EDITOR_ONE (a,Sound)
668 		autoSoundEditor editor = SoundEditor_create (ID_AND_FULL_NAME, me);
669 		Editor_setPublicationCallback (editor.get(), cb_SoundEditor_publication);
670 	EDITOR_ONE_END
671 }
672 
DIRECT(CONVERT_ONE_TO_MULTIPLE__Sound_extractAllChannels)673 DIRECT (CONVERT_ONE_TO_MULTIPLE__Sound_extractAllChannels) {
674 	CONVERT_ONE_TO_MULTIPLE (Sound)
675 		for (integer channel = 1; channel <= my ny; channel ++) {
676 			autoSound thee = Sound_extractChannel (me, channel);
677 			praat_new (thee.move(), my name.get(), U"_ch", channel);
678 		}
679 	CONVERT_ONE_TO_MULTIPLE_END
680 }
681 
682 FORM (CONVERT_EACH_TO_ONE__Sound_extractChannel, U"Sound: Extract channel", nullptr) {
683 	CHANNEL (channel, U"Channel (number, Left, or Right)", U"1")
684 	OK
685 DO
686 	CONVERT_EACH_TO_ONE (Sound)
687 		autoSound result = Sound_extractChannel (me, channel);
688 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_ch", channel)
689 }
690 
691 FORM (CONVERT_EACH_TO_ONE__Sound_extractChannels, U"Sound: Extract channels", nullptr) {
692 	NATURALVECTOR (channels, U"Channel numbers", RANGES_, U"1:64")
693 	OK
694 DO
695 	CONVERT_EACH_TO_ONE (Sound)
696 		autoSound result = Sound_extractChannels (me, channels);
697 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_ch")
698 }
699 
DIRECT(CONVERT_EACH_TO_ONE__Sound_extractLeftChannel)700 DIRECT (CONVERT_EACH_TO_ONE__Sound_extractLeftChannel) {
701 	CONVERT_EACH_TO_ONE (Sound)
702 		autoSound result = Sound_extractChannel (me, 1);
703 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_left")
704 }
705 
706 FORM (CONVERT_EACH_TO_ONE__Sound_extractPart, U"Sound: Extract part", nullptr) {
707 	REAL (fromTime, U"left Time range (s)", U"0.0")
708 	REAL (toTime, U"right Time range (s)", U"0.1")
709 	OPTIONMENU_ENUM (kSound_windowShape, windowShape, U"Window shape", kSound_windowShape::DEFAULT)
710 	POSITIVE (relativeWidth, U"Relative width", U"1.0")
711 	BOOLEAN (preserveTimes, U"Preserve times", false)
712 	OK
713 DO
714 	CONVERT_EACH_TO_ONE (Sound)
715 		autoSound result = Sound_extractPart (me, fromTime, toTime,
716 				windowShape, relativeWidth, preserveTimes);
717 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_part")
718 }
719 
720 FORM (CONVERT_EACH_TO_ONE__Sound_extractPartForOverlap, U"Sound: Extract part for overlap", nullptr) {
721 	REAL (fromTime, U"left Time range (s)", U"0.0")
722 	REAL (toTime, U"right Time range (s)", U"0.1")
723 	POSITIVE (overlap, U"Overlap (s)", U"0.01")
724 	OK
725 DO
726 	CONVERT_EACH_TO_ONE (Sound)
727 		autoSound result = Sound_extractPartForOverlap (me, fromTime, toTime, overlap);
728 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_part")
729 }
730 
DIRECT(CONVERT_EACH_TO_ONE__Sound_extractRightChannel)731 DIRECT (CONVERT_EACH_TO_ONE__Sound_extractRightChannel) {
732 	CONVERT_EACH_TO_ONE (Sound)
733 		autoSound result = Sound_extractChannel (me, 2);
734 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_right")
735 }
736 
737 FORM (CONVERT_EACH_TO_ONE__Sound_filter_deemphasis, U"Sound: Filter (de-emphasis)", U"Sound: Filter (de-emphasis)...") {
738 	REAL (fromFrequency, U"From frequency (Hz)", U"50.0")
739 	OK
740 DO
741 	CONVERT_EACH_TO_ONE (Sound)
742 		autoSound result = Sound_filter_deemphasis (me, fromFrequency);
743 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_deemp")
744 }
745 
746 FORM (CONVERT_EACH_TO_ONE__Sound_filter_formula, U"Sound: Filter (formula)...", U"Formula...") {
747 	LABEL (U"Frequency-domain filtering with a formula (uses Sound-to-Spectrum and Spectrum-to-Sound): x is frequency in hertz")
748 	FORMULA (formula, U"Formula", U"if x<500 or x>1000 then 0 else self fi; rectangular band filter")
749 	OK
750 DO
751 	CONVERT_EACH_TO_ONE (Sound)
752 		autoSound result = Sound_filter_formula (me, formula, interpreter);
753 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_filt")
754 }
755 
756 FORM (CONVERT_EACH_TO_ONE__Sound_filter_oneFormant, U"Sound: Filter (one formant)", U"Sound: Filter (one formant)...") {
757 	REAL (frequency, U"Frequency (Hz)", U"1000.0")
758 	POSITIVE (bandwidth, U"Bandwidth (Hz)", U"100.0")
759 	OK
760 DO
761 	CONVERT_EACH_TO_ONE (Sound)
762 		autoSound result = Sound_filter_oneFormant (me, frequency, bandwidth);
763 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_filt")
764 }
765 
766 FORM (MODIFY_Sound_filterWithOneFormantInplace, U"Sound: Filter with one formant (in-place)", U"Sound: Filter with one formant (in-place)...") {
767 	REAL (frequency, U"Frequency (Hz)", U"1000.0")
768 	POSITIVE (bandwidth, U"Bandwidth (Hz)", U"100.0")
769 	OK
770 DO
771 	MODIFY_EACH (Sound)
772 		Sound_filterWithOneFormantInplace (me, frequency, bandwidth);
773 	MODIFY_EACH_END
774 }
775 
776 FORM (CONVERT_EACH_TO_ONE__Sound_filter_passHannBand, U"Sound: Filter (pass Hann band)", U"Sound: Filter (pass Hann band)...") {
777 	REAL (fromFrequency, U"From frequency (Hz)", U"500.0")
778 	REAL (toFrequency, U"To frequency (Hz)", U"1000.0")
779 	POSITIVE (smoothing, U"Smoothing (Hz)", U"100.0")
780 	OK
781 DO
782 	CONVERT_EACH_TO_ONE (Sound)
783 		autoSound result = Sound_filter_passHannBand (me, fromFrequency, toFrequency, smoothing);
784 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_band")
785 }
786 
787 FORM (CONVERT_EACH_TO_ONE__Sound_filter_preemphasis, U"Sound: Filter (pre-emphasis)", U"Sound: Filter (pre-emphasis)...") {
788 	REAL (fromFrequency, U"From frequency (Hz)", U"50.0")
789 	OK
790 DO
791 	CONVERT_EACH_TO_ONE (Sound)
792 		autoSound result = Sound_filter_preemphasis (me, fromFrequency);
793 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_preemp")
794 }
795 
796 FORM (CONVERT_EACH_TO_ONE__Sound_filter_stopHannBand, U"Sound: Filter (stop Hann band)", U"Sound: Filter (stop Hann band)...") {
797 	REAL (fromFrequency, U"From frequency (Hz)", U"500.0")
798 	REAL (toFrequency, U"To frequency (Hz)", U"1000.0")
799 	POSITIVE (smoothing, U"Smoothing (Hz)", U"100.0")
800 	OK
801 DO
802 	CONVERT_EACH_TO_ONE (Sound)
803 		autoSound result = Sound_filter_stopHannBand (me, fromFrequency, toFrequency, smoothing);
804 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_band")
805 }
806 
807 FORM (MODIFY_Sound_formula, U"Sound: Formula", U"Sound: Formula...") {
808 	LABEL (U"# `x` is the time in seconds, `col` is the sample number.")
809 	LABEL (U"x = x1   ! time associated with first sample")
810 	LABEL (U"for col from 1 to ncol")
811 	LABEL (U"   self [col] = ...")
812 	FORMULA (formula, U"Formula", U"self")
813 	LABEL (U"   x = x + dx")
814 	LABEL (U"endfor")
815 	OK
816 DO
817 	MODIFY_EACH_WEAK (Sound)
818 		Matrix_formula (me, formula, interpreter, nullptr);
819 	MODIFY_EACH_WEAK_END
820 }
821 
822 FORM (MODIFY_Sound_formula_part, U"Sound: Formula (part)", U"Sound: Formula...") {
823 	REAL (fromTime, U"From time", U"0.0")
824 	REAL (toTime, U"To time", U"0.0 (= all)")
825 	NATURAL (fromChannel, U"From channel", U"1")
826 	NATURAL (toChannel, U"To channel", U"2")
827 	FORMULA (formula, U"Formula", U"2 * self")
828 	OK
829 DO
830 	MODIFY_EACH_WEAK (Sound)
831 		Matrix_formula_part (me, fromTime, toTime, fromChannel - 0.5, toChannel + 0.5,
832 				formula, interpreter, nullptr);
833 	MODIFY_EACH_WEAK_END
834 }
835 
836 FORM (QUERY_ONE_FOR_REAL__Sound_getAbsoluteExtremum, U"Sound: Get absolute extremum", U"Sound: Get absolute extremum...") {
837 	REAL (fromTime, U"left Time range (s)", U"0.0")
838 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
839 	RADIO_ENUM (kVector_peakInterpolation, peakInterpolationType,
840 			U"Interpolation", kVector_peakInterpolation::SINC70)
841 	OK
842 DO
843 	QUERY_ONE_FOR_REAL (Sound)
844 		const double result = Vector_getAbsoluteExtremum (me, fromTime, toTime, peakInterpolationType);
845 	QUERY_ONE_FOR_REAL_END (U" Pascal")
846 }
847 
848 FORM (QUERY_ONE_FOR_REAL__Sound_getEnergy, U"Sound: Get energy", U"Sound: Get energy...") {
849 	REAL (fromTime, U"left Time range (s)", U"0.0")
850 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
851 	OK
852 DO
853 	QUERY_ONE_FOR_REAL (Sound)
854 		const double result = Sound_getEnergy (me, fromTime, toTime);
855 	QUERY_ONE_FOR_REAL_END (U" Pa2 sec")
856 }
857 
DIRECT(QUERY_ONE_FOR_REAL__Sound_getEnergyInAir)858 DIRECT (QUERY_ONE_FOR_REAL__Sound_getEnergyInAir) {
859 	QUERY_ONE_FOR_REAL (Sound)
860 		const double result = Sound_getEnergyInAir (me);
861 	QUERY_ONE_FOR_REAL_END (U" Joule/m2")
862 }
863 
864 FORM (QUERY_ONE_FOR_REAL__Sound_getIndexFromTime, U"Get sample number from time", U"Get sample number from time...") {
865 	REAL (time, U"Time (s)", U"0.5")
866 	OK
867 DO
868 	QUERY_ONE_FOR_REAL (Sound)
869 		const double result = Sampled_xToIndex (me, time);
870 	QUERY_ONE_FOR_REAL_END (U" (index at time ", time, U" seconds)")
871 }
872 
DIRECT(QUERY_ONE_FOR_REAL__Sound_getIntensity_dB)873 DIRECT (QUERY_ONE_FOR_REAL__Sound_getIntensity_dB) {
874 	QUERY_ONE_FOR_REAL (Sound)
875 		const double result = Sound_getIntensity_dB (me);
876 	QUERY_ONE_FOR_REAL_END (U" dB")
877 }
878 
879 FORM (QUERY_ONE_FOR_REAL__Sound_getMaximum, U"Sound: Get maximum", U"Sound: Get maximum...") {
880 	REAL (fromTime, U"left Time range (s)", U"0.0")
881 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
882 	RADIO_ENUM (kVector_peakInterpolation, peakInterpolationType,
883 			U"Interpolation", kVector_peakInterpolation::SINC70)
884 	OK
885 DO
886 	QUERY_ONE_FOR_REAL (Sound)
887 		const double result = Vector_getMaximum (me, fromTime, toTime, peakInterpolationType);
888 	QUERY_ONE_FOR_REAL_END (U" Pascal")
889 }
890 
891 FORM (QUERY_ONE_FOR_REAL__old_Sound_getMean, U"Sound: Get mean", U"Sound: Get mean...") {
892 	REAL (fromTime, U"left Time range (s)", U"0.0")
893 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
894 	OK
895 DO
896 	QUERY_ONE_FOR_REAL (Sound)
897 		const double result = Vector_getMean (me, fromTime, toTime, Vector_CHANNEL_AVERAGE);
898 	QUERY_ONE_FOR_REAL_END (U" Pascal")
899 }
900 
901 FORM (QUERY_ONE_FOR_REAL__Sound_getMean, U"Sound: Get mean", U"Sound: Get mean...") {
902 	CHANNEL (channel, U"Channel", U"0 (= all)")
903 	REAL (fromTime, U"left Time range (s)", U"0.0")
904 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
905 	OK
906 DO_ALTERNATIVE (QUERY_ONE_FOR_REAL__old_Sound_getMean)
907 	QUERY_ONE_FOR_REAL (Sound)
908 		if (channel > my ny) channel = 1;
909 		const double result = Vector_getMean (me, fromTime, toTime, channel);
910 	QUERY_ONE_FOR_REAL_END (U" Pascal")
911 }
912 
913 FORM (QUERY_ONE_FOR_REAL__Sound_getMinimum, U"Sound: Get minimum", U"Sound: Get minimum...") {
914 	REAL (fromTime, U"left Time range (s)", U"0.0")
915 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
916 	RADIO_ENUM (kVector_peakInterpolation, peakInterpolationType,
917 			U"Interpolation", kVector_peakInterpolation::SINC70)
918 	OK
919 DO
920 	QUERY_ONE_FOR_REAL (Sound)
921 		const double result = Vector_getMinimum (me, fromTime, toTime, peakInterpolationType);
922 	QUERY_ONE_FOR_REAL_END (U" Pascal")
923 }
924 
925 FORM (QUERY_ONE_FOR_REAL__old_Sound_getNearestZeroCrossing, U"Sound: Get nearest zero crossing", U"Sound: Get nearest zero crossing...") {
926 	REAL (time, U"Time (s)", U"0.5")
927 	OK
928 DO
929 	QUERY_ONE_FOR_REAL (Sound)
930 		if (my ny > 1) Melder_throw (U"Cannot determine a zero crossing for a stereo sound.");
931 		const double result = Sound_getNearestZeroCrossing (me, time, 1);
932 	QUERY_ONE_FOR_REAL_END (U" seconds")
933 }
934 
935 FORM (QUERY_ONE_FOR_REAL__Sound_getNearestZeroCrossing, U"Sound: Get nearest zero crossing", U"Sound: Get nearest zero crossing...") {
936 	CHANNEL (channel, U"Channel (number, Left, or Right)", U"1")
937 	REAL (time, U"Time (s)", U"0.5")
938 	OK
939 DO_ALTERNATIVE (QUERY_ONE_FOR_REAL__old_Sound_getNearestZeroCrossing)
940 	QUERY_ONE_FOR_REAL (Sound)
941 		if (channel > my ny) channel = 1;
942 		const double result = Sound_getNearestZeroCrossing (me, time, channel);
943 	QUERY_ONE_FOR_REAL_END (U" seconds")
944 }
945 
DIRECT(QUERY_ONE_FOR_INTEGER__Sound_getNumberOfChannels)946 DIRECT (QUERY_ONE_FOR_INTEGER__Sound_getNumberOfChannels) {
947 	QUERY_ONE_FOR_INTEGER (Sound)
948 		const integer result = my ny;
949 	QUERY_ONE_FOR_INTEGER_END (result == 1 ? U" channel (mono)" : result == 2 ? U" channels (stereo)" : U" channels")
950 }
951 
DIRECT(QUERY_ONE_FOR_INTEGER__Sound_getNumberOfSamples)952 DIRECT (QUERY_ONE_FOR_INTEGER__Sound_getNumberOfSamples) {
953 	QUERY_ONE_FOR_INTEGER (Sound)
954 		const integer result = my nx;
955 	QUERY_ONE_FOR_INTEGER_END (U" samples")
956 }
957 
958 FORM (QUERY_ONE_FOR_REAL__Sound_getPower, U"Sound: Get power", U"Sound: Get power...") {
959 	REAL (fromTime, U"left Time range (s)", U"0.0")
960 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
961 	OK
962 DO
963 	QUERY_ONE_FOR_REAL (Sound)
964 		const double result = Sound_getPower (me, fromTime, toTime);
965 	QUERY_ONE_FOR_REAL_END (U" Pa2")
966 }
967 
DIRECT(QUERY_ONE_FOR_REAL__Sound_getPowerInAir)968 DIRECT (QUERY_ONE_FOR_REAL__Sound_getPowerInAir) {
969 	QUERY_ONE_FOR_REAL (Sound)
970 		const double result = Sound_getPowerInAir (me);
971 	QUERY_ONE_FOR_REAL_END (U" Watt/m2")
972 }
973 
974 FORM (QUERY_ONE_FOR_REAL__Sound_getRootMeanSquare, U"Sound: Get root-mean-square", U"Sound: Get root-mean-square...") {
975 	REAL (fromTime, U"left Time range (s)", U"0.0")
976 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
977 	OK
978 DO
979 	QUERY_ONE_FOR_REAL (Sound)
980 		const double result = Sound_getRootMeanSquare (me, fromTime, toTime);
981 	QUERY_ONE_FOR_REAL_END (U" Pascal")
982 }
983 
DIRECT(QUERY_ONE_FOR_REAL__Sound_getSamplePeriod)984 DIRECT (QUERY_ONE_FOR_REAL__Sound_getSamplePeriod) {
985 	QUERY_ONE_FOR_REAL (Sound)
986 		const double result = my dx;
987 	QUERY_ONE_FOR_REAL_END (U" seconds")
988 }
989 
DIRECT(QUERY_ONE_FOR_REAL__Sound_getSampleRate)990 DIRECT (QUERY_ONE_FOR_REAL__Sound_getSampleRate) {
991 	QUERY_ONE_FOR_REAL (Sound)
992 		const double result = 1.0 / my dx;
993 	QUERY_ONE_FOR_REAL_END (U" Hz")
994 }
995 
996 FORM (QUERY_ONE_FOR_REAL__old_Sound_getStandardDeviation, U"Sound: Get standard deviation", U"Sound: Get standard deviation...") {
997 	REAL (fromTime, U"left Time range (s)", U"0.0")
998 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
999 	OK
1000 DO
1001 	QUERY_ONE_FOR_REAL (Sound)
1002 		const double result = Vector_getStandardDeviation (me, fromTime, toTime, Vector_CHANNEL_AVERAGE);
1003 	QUERY_ONE_FOR_REAL_END (U" Pascal")
1004 }
1005 
1006 FORM (QUERY_ONE_FOR_REAL__Sound_getStandardDeviation, U"Sound: Get standard deviation", U"Sound: Get standard deviation...") {
1007 	CHANNEL (channel, U"Channel", U"0 (= average)")
1008 	REAL (fromTime, U"left Time range (s)", U"0.0")
1009 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
1010 	OK
1011 DO_ALTERNATIVE (QUERY_ONE_FOR_REAL__old_Sound_getStandardDeviation)
1012 	QUERY_ONE_FOR_REAL (Sound)
1013 		if (channel > my ny) channel = 1;
1014 		const double result = Vector_getStandardDeviation (me, fromTime, toTime, channel);
1015 	QUERY_ONE_FOR_REAL_END (U" Pascal")
1016 }
1017 
1018 FORM (QUERY_ONE_FOR_REAL__Sound_getTimeFromIndex, U"Get time from sample number", U"Get time from sample number...") {
1019 	INTEGER (sampleNumber, U"Sample number", U"100")
1020 	OK
1021 DO
1022 	QUERY_ONE_FOR_REAL (Sound)
1023 		const double result = Sampled_indexToX (me, sampleNumber);
1024 	QUERY_ONE_FOR_REAL_END (U" seconds")
1025 }
1026 
DIRECT(NUMVEC_Sound_listAllSampleTimes)1027 DIRECT (NUMVEC_Sound_listAllSampleTimes) {
1028 	QUERY_ONE_FOR_REAL_VECTOR (Sound)
1029 		autoVEC result = Sampled_listAllXValues (me);
1030 	QUERY_ONE_FOR_REAL_VECTOR_END
1031 }
1032 
1033 FORM (QUERY_ONE_FOR_REAL__Sound_getTimeOfMaximum, U"Sound: Get time of maximum", U"Sound: Get time of maximum...") {
1034 	REAL (fromTime, U"left Time range (s)", U"0.0")
1035 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
1036 	RADIO_ENUM (kVector_peakInterpolation, peakInterpolationType,
1037 			U"Interpolation", kVector_peakInterpolation::SINC70)
1038 	OK
1039 DO
1040 	QUERY_ONE_FOR_REAL (Sound)
1041 		const double result = Vector_getXOfMaximum (me, fromTime, toTime, peakInterpolationType);
1042 	QUERY_ONE_FOR_REAL_END (U" seconds")
1043 }
1044 
1045 FORM (QUERY_ONE_FOR_REAL__Sound_getTimeOfMinimum, U"Sound: Get time of minimum", U"Sound: Get time of minimum...") {
1046 	REAL (fromTime, U"left Time range (s)", U"0.0")
1047 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
1048 	RADIO_ENUM (kVector_peakInterpolation, peakInterpolationType,
1049 			U"Interpolation", kVector_peakInterpolation::SINC70)
1050 	OK
1051 DO
1052 	QUERY_ONE_FOR_REAL (Sound)
1053 		const double result = Vector_getXOfMinimum (me, fromTime, toTime, peakInterpolationType);
1054 	QUERY_ONE_FOR_REAL_END (U" seconds")
1055 }
1056 
1057 FORM (QUERY_ONE_FOR_REAL__old_Sound_getValueAtIndex, U"Sound: Get value at sample number", U"Sound: Get value at sample number...") {
1058 	INTEGER (sampleNumber, U"Sample number", U"100")
1059 	OK
1060 DO
1061 	QUERY_ONE_FOR_REAL (Sound)
1062 		const double result = sampleNumber < 1 || sampleNumber > my nx ? undefined :
1063 				my ny == 1 ? my z [1] [sampleNumber] : 0.5 * (my z [1] [sampleNumber] + my z [2] [sampleNumber]);
1064 	QUERY_ONE_FOR_REAL_END (U" Pascal")
1065 }
1066 
1067 FORM (QUERY_ONE_FOR_REAL__Sound_getValueAtIndex, U"Sound: Get value at sample number", U"Sound: Get value at sample number...") {
1068 	CHANNEL (channel, U"Channel", U"0 (= average)")
1069 	INTEGER (sampleNumber, U"Sample number", U"100")
1070 	OK
1071 DO_ALTERNATIVE (QUERY_ONE_FOR_REAL__old_Sound_getValueAtIndex)
1072 	QUERY_ONE_FOR_REAL (Sound)
1073 		if (channel > my ny) channel = 1;
1074 		const double result = sampleNumber < 1 || sampleNumber > my nx ? undefined :
1075 				Sampled_getValueAtSample (me, sampleNumber, channel, 0);
1076 	QUERY_ONE_FOR_REAL_END (U" Pascal")
1077 }
1078 
1079 FORM (QUERY_ONE_FOR_REAL__old_Sound_getValueAtTime, U"Sound: Get value at time", U"Sound: Get value at time...") {
1080 	REAL (time, U"Time (s)", U"0.5")
1081 	RADIO_ENUM (kVector_valueInterpolation, valueInterpolationType,
1082 			U"Interpolation", kVector_valueInterpolation::SINC70)
1083 	OK
1084 DO
1085 	QUERY_ONE_FOR_REAL (Sound)
1086 		const double result = Vector_getValueAtX (me, time, Vector_CHANNEL_AVERAGE, valueInterpolationType);
1087 	QUERY_ONE_FOR_REAL_END (U" Pascal")
1088 }
1089 
1090 FORM (QUERY_ONE_FOR_REAL__Sound_getValueAtTime, U"Sound: Get value at time", U"Sound: Get value at time...") {
1091 	CHANNEL (channel, U"Channel", U"0 (= average)")
1092 	REAL (time, U"Time (s)", U"0.5")
1093 	RADIO_ENUM (kVector_valueInterpolation, valueInterpolationType,
1094 			U"Interpolation", kVector_valueInterpolation::SINC70)
1095 	OK
1096 DO_ALTERNATIVE (QUERY_ONE_FOR_REAL__old_Sound_getValueAtTime)
1097 	QUERY_ONE_FOR_REAL (Sound)
1098 		if (channel > my ny) channel = 1;
1099 		const double result = Vector_getValueAtX (me, time, channel, valueInterpolationType);
1100 	QUERY_ONE_FOR_REAL_END (U" Pascal")
1101 }
1102 
DIRECT(HELP__Sound_help)1103 DIRECT (HELP__Sound_help) {
1104 	HELP (U"Sound")
1105 }
1106 
1107 FORM (CONVERT_EACH_TO_ONE__Sound_lengthen_overlapAdd, U"Sound: Lengthen (overlap-add)", U"Sound: Lengthen (overlap-add)...") {
1108 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1109 	POSITIVE (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
1110 	POSITIVE (factor, U"Factor", U"1.5")
1111 	OK
1112 DO
1113 	Melder_require (minimumPitch < maximumPitch,
1114 		U"Maximum pitch should be greater than minimum pitch.");
1115 	CONVERT_EACH_TO_ONE (Sound)
1116 		autoSound result = Sound_lengthen_overlapAdd (me, minimumPitch, maximumPitch, factor);
1117 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_", Melder_fixed (factor, 2));
1118 }
1119 
1120 FORM (MODIFY_Sound_multiply, U"Sound: Multiply", nullptr) {
1121 	REAL (multiplicationFactor, U"Multiplication factor", U"1.5")
1122 	OK
1123 DO
1124 	MODIFY_EACH (Sound)
1125 		Vector_multiplyByScalar (me, multiplicationFactor);
1126 	MODIFY_EACH_END
1127 }
1128 
1129 FORM (MODIFY_Sound_multiplyByWindow, U"Sound: Multiply by window", nullptr) {
1130 	OPTIONMENU_ENUM (kSound_windowShape, windowShape, U"Window shape", kSound_windowShape::HANNING)
1131 	OK
1132 DO
1133 	MODIFY_EACH (Sound)
1134 		Sound_multiplyByWindow (me, windowShape);
1135 	MODIFY_EACH_END
1136 }
1137 
1138 FORM (MODIFY_Sound_overrideSamplingFrequency, U"Sound: Override sampling frequency", nullptr) {
1139 	POSITIVE (newSamplingFrequency, U"New sampling frequency (Hz)", U"16000.0")
1140 	OK
1141 DO
1142 	MODIFY_EACH (Sound)
1143 		Sound_overrideSamplingFrequency (me, newSamplingFrequency);
1144 	MODIFY_EACH_END
1145 }
1146 
DIRECT(PLAY_EACH__Sound_play)1147 DIRECT (PLAY_EACH__Sound_play) {
1148 	PLAY_EACH (Sound)
1149 		Sound_play (me, nullptr, nullptr);   // BUG: exception-safe?
1150 	PLAY_EACH_END
1151 }
1152 
1153 FORM (MODIFY_Sound_preemphasizeInplace, U"Sound: Pre-emphasize (in-place)", U"Sound: Pre-emphasize (in-place)...") {
1154 	REAL (fromFrequency, U"From frequency (Hz)", U"50.0")
1155 	OK
1156 DO
1157 	MODIFY_EACH (Sound)
1158 		Sound_preEmphasis (me, fromFrequency);
1159 		Vector_scale (me, 0.99);
1160 	MODIFY_EACH_END
1161 }
1162 
1163 FORM_READ (READ_MULTIPLE__Sound_readSeparateChannelsFromSoundFile, U"Read separate channels from sound file", nullptr, true) {
1164 	READ_MULTIPLE
1165 		autoSound sound = Sound_readFromSoundFile (file);
1166 		char32 name [300];
1167 		Melder_sprint (name,300, MelderFile_name (file));
1168 		char32 *lastPeriod = str32rchr (name, U'.');
1169 		if (lastPeriod)
1170 			*lastPeriod = U'\0';
1171 		for (integer ichan = 1; ichan <= sound -> ny; ichan ++) {
1172 			autoSound thee = Sound_extractChannel (sound.get(), ichan);
1173 			praat_new (thee.move(), name, U"_ch", ichan);
1174 		}
1175 	READ_MULTIPLE_END
1176 }
1177 
1178 FORM_READ (READ1_Sound_readFromRawAlawFile, U"Read Sound from raw Alaw file", nullptr, true) {
1179 	READ_ONE
1180 		autoSound result = Sound_readFromRawAlawFile (file);
1181 	READ_ONE_END
1182 }
1183 
1184 static SoundRecorder theReferenceToTheOnlySoundRecorder;
1185 static int thePreviousNumberOfChannels;
1186 
cb_SoundRecorder_destruction(SoundRecorder)1187 static void cb_SoundRecorder_destruction (SoundRecorder /* me */) {
1188 	theReferenceToTheOnlySoundRecorder = nullptr;
1189 }
cb_SoundRecorder_publication(Editor,autoDaata publication)1190 static void cb_SoundRecorder_publication (Editor /* me */, autoDaata publication) {
1191 	try {
1192 		praat_new (publication.move());
1193 	} catch (MelderError) {
1194 		Melder_flushError ();
1195 	}
1196 	praat_updateSelection ();
1197 }
do_Sound_record(int numberOfChannels)1198 static void do_Sound_record (int numberOfChannels) {
1199 	if (theReferenceToTheOnlySoundRecorder && numberOfChannels == thePreviousNumberOfChannels) {
1200 		Editor_raise (theReferenceToTheOnlySoundRecorder);
1201 	} else {
1202 		forget (theReferenceToTheOnlySoundRecorder);
1203 		autoSoundRecorder recorder = SoundRecorder_create (numberOfChannels);
1204 		Editor_setDestructionCallback (recorder.get(), cb_SoundRecorder_destruction);
1205 		Editor_setPublicationCallback (recorder.get(), cb_SoundRecorder_publication);
1206 		theReferenceToTheOnlySoundRecorder = recorder.get();
1207 		recorder.releaseToUser();
1208 		thePreviousNumberOfChannels = numberOfChannels;
1209 	}
1210 }
DIRECT(SINGLETON_CREATION_WINDOW__Sound_recordMono)1211 DIRECT (SINGLETON_CREATION_WINDOW__Sound_recordMono) {
1212 	SINGLETON_CREATION_WINDOW (a,Sound)
1213 		do_Sound_record (1);
1214 	SINGLETON_CREATION_WINDOW_END
1215 }
DIRECT(SINGLETON_CREATION_WINDOW__Sound_recordStereo)1216 DIRECT (SINGLETON_CREATION_WINDOW__Sound_recordStereo) {
1217 	SINGLETON_CREATION_WINDOW (a,Sound)
1218 		do_Sound_record (2);
1219 	SINGLETON_CREATION_WINDOW_END
1220 }
1221 
1222 FORM (RECORD_ONE__Sound_record_fixedTime, U"Record Sound", nullptr) {
1223 	LABEL (U"This menu command is usually hidden,")
1224 	LABEL (U"   because its behaviour is platform-dependent.")
1225 	LABEL (U"The combination of “microphone” and “44100 Hz” is likely")
1226 	LABEL (U"   to work on all computers.")
1227 	LABEL (U"The “Gain” and “Balance” settings tend to be obsolete")
1228 	LABEL (U"   and may not work at all on your computer.")
1229 	RADIO (inputSource, U"Input source", 1)
1230 		OPTION (U"microphone")
1231 		OPTION (U"line")
1232 	REAL (gain, U"Gain (0-1)", U"1.0")
1233 	REAL (balance, U"Balance (0-1)", U"0.5")
1234 	OPTIONMENUSTR (samplingFrequency, U"Sampling frequency (Hz)", 6)
1235 		OPTION (U"8000")
1236 		OPTION (U"11025")
1237 		OPTION (U"16000")
1238 		OPTION (U"22050")
1239 		OPTION (U"32000")
1240 		OPTION (U"44100")
1241 		OPTION (U"48000")
1242 		OPTION (U"96000")
1243 	POSITIVE (duration, U"Duration (seconds)", U"1.0")
1244 	OK
1245 DO
1246 	RECORD_ONE
1247 		autoSound result = Sound_record_fixedTime (inputSource,
1248 				gain, balance, Melder_atof (samplingFrequency), duration);
1249 	RECORD_ONE_END (U"untitled")
1250 }
1251 
1252 extern "C" void* Praat_Sound_resample (void* sound, double newSamplingFrequency, int precision);
1253 #if 0
1254 void* Praat_Sound_resample (void* sound, double newSamplingFrequency, int precision) {
1255 	try {
1256 		if (newSamplingFrequency <= 0.0) Melder_throw (U"`newSamplingFrequency` should be positive.");
1257 		if (precision <= 0) Melder_throw (U"`precision` should be greater than 0.");
1258 		autoSound thee = Sound_resample ((Sound) sound, newSamplingFrequency, precision);
1259 		return (void*) thee.releaseToAmbiguousOwner();
1260 	} catch (MelderError) {
1261 		Melder_flushError (U"Praat: Sound_resample: not performed.");
1262 		return NULL;
1263 	}
1264 }
1265 #elif 0
1266 typedef struct {
1267 	int type;
1268 	union { void* _object; double _double; int _int; };
1269 } PraatLibArg;
1270 #define PraatLibArg_OBJECT  0
1271 #define PraatLibArg_DOUBLE  1
1272 #define PraatLibArg_INT  2
1273 extern "C" void* praatlib_do (const char *commandTitle, PraatLibArg args [], int narg);
Praat_Sound_resample(void * sound,double newSamplingFrequency,int precision)1274 void* Praat_Sound_resample (void* sound, double newSamplingFrequency, int precision) {
1275 	PraatLibArg args [3];
1276 	args [0]. type = PraatLibArg_OBJECT;
1277 	args [0]. _object = sound;
1278 	args [1]. type = PraatLibArg_DOUBLE;
1279 	args [1]. _double = newSamplingFrequency;
1280 	args [2]. type = PraatLibArg_INT;
1281 	args [2]. _int = precision;
1282 	return praatlib_do ("Sound: Resample...", args, 3);
1283 }
1284 #endif
1285 
1286 FORM (CONVERT_EACH_TO_ONE__Sound_resample, U"Sound: Resample", U"Sound: Resample...") {
1287 	POSITIVE (newSamplingFrequency, U"New sampling frequency (Hz)", U"10000.0")
1288 	NATURAL (precision, U"Precision (samples)", U"50")
1289 	OK
1290 DO
1291 	CONVERT_EACH_TO_ONE (Sound)
1292 		autoSound result = Sound_resample (me, newSamplingFrequency, precision);
1293 	CONVERT_EACH_TO_ONE_END (my name.get(), U"_", Melder_iround (newSamplingFrequency));
1294 }
1295 
DIRECT(MODIFY_Sound_reverse)1296 DIRECT (MODIFY_Sound_reverse) {
1297 	MODIFY_EACH (Sound)
1298 		Sound_reverse (me, 0.0, 0.0);
1299 	MODIFY_EACH_END
1300 }
1301 
1302 FORM_SAVE (SAVE_ALL__Sound_saveAs24BitWavFile, U"Save as 24-bit WAV file", nullptr, U"wav") {
1303 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1304 		LongSound_concatenate (list.get(), file, Melder_WAV, 24);
1305 	SAVE_ALL_LISTED_END
1306 }
1307 
1308 FORM_SAVE (SAVE_ALL__Sound_saveAs32BitWavFile, U"Save as 32-bit WAV file", nullptr, U"wav") {
1309 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1310 		LongSound_concatenate (list.get(), file, Melder_WAV, 32);
1311 	SAVE_ALL_LISTED_END
1312 }
1313 
1314 FORM (MODIFY_Sound_scalePeak, U"Sound: Scale peak", U"Sound: Scale peak...") {
1315 	POSITIVE (newAbsolutePeak, U"New absolute peak", U"0.99")
1316 	OK
1317 DO
1318 	MODIFY_EACH (Sound)
1319 		Vector_scale (me, newAbsolutePeak);
1320 	MODIFY_EACH_END
1321 }
1322 
1323 FORM (MODIFY_Sound_scaleIntensity, U"Sound: Scale intensity", U"Sound: Scale intensity...") {
1324 	POSITIVE (newAverageIntensity, U"New average intensity (dB SPL)", U"70.0")
1325 	OK
1326 DO
1327 	MODIFY_EACH (Sound)
1328 		Sound_scaleIntensity (me, newAverageIntensity);
1329 	MODIFY_EACH_END
1330 }
1331 
1332 FORM (MODIFY_old_Sound_setValueAtIndex, U"Sound: Set value at sample number", U"Sound: Set value at sample number...") {
1333 	NATURAL (sampleNumber, U"Sample number", U"100")
1334 	REAL (newValue, U"New value", U"0.0")
1335 	OK
1336 DO
1337 	MODIFY_EACH (Sound)
1338 		if (sampleNumber > my nx)
1339 			Melder_throw (U"The sample number should not exceed the number of samples, which is ", my nx, U".");
1340 		for (integer channel = 1; channel <= my ny; channel ++)
1341 			my z [channel] [sampleNumber] = newValue;
1342 	MODIFY_EACH_END
1343 }
1344 
1345 FORM (MODIFY_Sound_setValueAtIndex, U"Sound: Set value at sample number", U"Sound: Set value at sample number...") {
1346 	CHANNEL (channel, U"Channel", U"0 (= all)")
1347 	NATURAL (sampleNumber, U"Sample number", U"100")
1348 	REAL (newValue, U"New value", U"0.0")
1349 	OK
1350 DO_ALTERNATIVE (MODIFY_old_Sound_setValueAtIndex)
1351 	MODIFY_EACH (Sound)
1352 		if (sampleNumber > my nx)
1353 			Melder_throw (U"The sample number should not exceed the number of samples, which is ", my nx, U".");
1354 		if (channel > my ny) channel = 1;
1355 		if (channel > 0) {
1356 			my z [channel] [sampleNumber] = newValue;
1357 		} else {
1358 			for (channel = 1; channel <= my ny; channel ++)
1359 				my z [channel] [sampleNumber] = newValue;
1360 		}
1361 	MODIFY_EACH_END
1362 }
1363 
1364 FORM (MODIFY_Sound_setPartToZero, U"Sound: Set part to zero", nullptr) {
1365 	REAL (fromTime, U"left Time range (s)", U"0.0")
1366 	REAL (toTime, U"right Time range (s)", U"0.0 (= all)")
1367 	RADIOx (cut, U"Cut", 2, 0)
1368 		OPTION (U"at exactly these times")
1369 		OPTION (U"at nearest zero crossing")
1370 	OK
1371 DO
1372 	MODIFY_EACH (Sound)
1373 		Sound_setZero (me, fromTime, toTime, cut);
1374 	MODIFY_EACH_END
1375 }
1376 
DIRECT(MODIFY_Sound_subtractMean)1377 DIRECT (MODIFY_Sound_subtractMean) {
1378 	MODIFY_EACH (Sound)
1379 		Vector_subtractMean (me);
1380 	MODIFY_EACH_END
1381 }
1382 
1383 FORM (CONVERT_EACH_TO_ONE__Sound_to_Manipulation, U"Sound: To Manipulation", U"Manipulation") {
1384 	POSITIVE (timeStep, U"Time step (s)", U"0.01")
1385 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1386 	POSITIVE (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
1387 	OK
1388 DO
1389 	Melder_require (maximumPitch > minimumPitch,
1390 		U"The maximum pitch should be greater than the minimum pitch.");
1391 	CONVERT_EACH_TO_ONE (Sound)
1392 		autoManipulation result = Sound_to_Manipulation (me, timeStep, minimumPitch, maximumPitch);
1393 	CONVERT_EACH_TO_ONE_END (my name.get())
1394 }
1395 
1396 FORM (CONVERT_EACH_TO_ONE__Sound_to_Cochleagram, U"Sound: To Cochleagram", nullptr) {
1397 	POSITIVE (timeStep, U"Time step (s)", U"0.01")
1398 	POSITIVE (frequencyResolution, U"Frequency resolution (Bark)", U"0.1")
1399 	POSITIVE (windowLength, U"Window length (s)", U"0.03")
1400 	REAL (forwardMaskingTime, U"Forward-masking time (s)", U"0.03")
1401 	OK
1402 DO
1403 	CONVERT_EACH_TO_ONE (Sound)
1404 		autoCochleagram result = Sound_to_Cochleagram (me, timeStep,
1405 			frequencyResolution, windowLength, forwardMaskingTime);
1406 	CONVERT_EACH_TO_ONE_END (my name.get())
1407 }
1408 
1409 FORM (CONVERT_EACH_TO_ONE__Sound_to_Cochleagram_edb, U"Sound: To Cochleagram (De Boer, Meddis & Hewitt)", nullptr) {
1410 	POSITIVE (timeStep, U"Time step (s)", U"0.01")
1411 	POSITIVE (frequencyResolution, U"Frequency resolution (Bark)", U"0.1")
1412 	BOOLEAN (hasSynapse, U"Has synapse", true)
1413 	LABEL (U"Meddis synapse properties")
1414 	POSITIVE (replenishmentRate, U"   replenishment rate (/sec)", U"5.05")
1415 	POSITIVE (lossRate, U"   loss rate (/sec)", U"2500.0")
1416 	POSITIVE (returnRate, U"   return rate (/sec)", U"6580.0")
1417 	POSITIVE (reprocessingRate, U"   reprocessing rate (/sec)", U"66.31")
1418 	OK
1419 DO
1420 	CONVERT_EACH_TO_ONE (Sound)
1421 		autoCochleagram result = Sound_to_Cochleagram_edb (me, timeStep, frequencyResolution, hasSynapse,
1422 				replenishmentRate, lossRate, returnRate, reprocessingRate);
1423 	CONVERT_EACH_TO_ONE_END (my name.get())
1424 }
1425 
1426 FORM (CONVERT_EACH_TO_ONE__Sound_to_Formant_burg, U"Sound: To Formant (Burg method)", U"Sound: To Formant (burg)...") {
1427 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1428 	POSITIVE (maximumNumberOfFormants, U"Max. number of formants", U"5.0")
1429 	REAL (formantCeiling, U"Formant ceiling (Hz)", U"5500.0 (= adult female)")
1430 	POSITIVE (windowLength, U"Window length (s)", U"0.025")
1431 	POSITIVE (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
1432 	OK
1433 DO
1434 	CONVERT_EACH_TO_ONE (Sound)
1435 		autoFormant result = Sound_to_Formant_burg (me, timeStep,
1436 				maximumNumberOfFormants, formantCeiling, windowLength, preEmphasisFrom);
1437 	CONVERT_EACH_TO_ONE_END (my name.get())
1438 }
1439 
1440 FORM (CONVERT_EACH_TO_ONE__Sound_to_Formant_keepAll, U"Sound: To Formant (keep all)", U"Sound: To Formant (keep all)...") {
1441 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1442 	POSITIVE (maximumNumberOfFormants, U"Max. number of formants", U"5.0")
1443 	REAL (formantCeiling, U"Formant ceiling (Hz)", U"5500.0 (= adult female)")
1444 	POSITIVE (windowLength, U"Window length (s)", U"0.025")
1445 	POSITIVE (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
1446 	OK
1447 DO
1448 	CONVERT_EACH_TO_ONE (Sound)
1449 		autoFormant result = Sound_to_Formant_keepAll (me, timeStep,
1450 				maximumNumberOfFormants, formantCeiling, windowLength, preEmphasisFrom);
1451 	CONVERT_EACH_TO_ONE_END (my name.get())
1452 }
1453 
1454 FORM (CONVERT_EACH_TO_ONE__Sound_to_Formant_willems, U"Sound: To Formant (split Levinson (Willems))", U"Sound: To Formant (sl)...") {
1455 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1456 	POSITIVE (numberOfFormants, U"Number of formants", U"5.0")
1457 	REAL (formantCeiling, U"Formant ceiling (Hz)", U"5500.0 (= adult female)")
1458 	POSITIVE (windowLength, U"Window length (s)", U"0.025")
1459 	POSITIVE (preEmphasisFrom, U"Pre-emphasis from (Hz)", U"50.0")
1460 	OK
1461 DO
1462 	CONVERT_EACH_TO_ONE (Sound)
1463 		autoFormant result = Sound_to_Formant_willems (me, timeStep,
1464 				numberOfFormants, formantCeiling, windowLength, preEmphasisFrom);
1465 	CONVERT_EACH_TO_ONE_END (my name.get())
1466 }
1467 
1468 FORM (CONVERT_EACH_TO_ONE__Sound_to_Harmonicity_ac, U"Sound: To Harmonicity (ac)", U"Sound: To Harmonicity (ac)...") {
1469 	POSITIVE (timeStep, U"Time step (s)", U"0.01")
1470 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1471 	REAL (silenceThreshold, U"Silence threshold", U"0.1")
1472 	POSITIVE (periodsPerWindow, U"Periods per window", U"4.5")
1473 	OK
1474 DO
1475 	Melder_require (periodsPerWindow >= 3.0,
1476 		U"Number of periods per window must be at least 3.0.");
1477 	CONVERT_EACH_TO_ONE (Sound)
1478 		autoHarmonicity result = Sound_to_Harmonicity_ac (me, timeStep,
1479 				minimumPitch, silenceThreshold, periodsPerWindow);
1480 	CONVERT_EACH_TO_ONE_END (my name.get())
1481 }
1482 
1483 FORM (CONVERT_EACH_TO_ONE__Sound_to_Harmonicity_cc, U"Sound: To Harmonicity (cc)", U"Sound: To Harmonicity (cc)...") {
1484 	POSITIVE (timeStep, U"Time step (s)", U"0.01")
1485 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1486 	REAL (silenceThreshold, U"Silence threshold", U"0.1")
1487 	POSITIVE (periodsPerWindow, U"Periods per window", U"1.0")
1488 	OK
1489 DO
1490 	CONVERT_EACH_TO_ONE (Sound)
1491 		autoHarmonicity result = Sound_to_Harmonicity_cc (me, timeStep,
1492 				minimumPitch, silenceThreshold, periodsPerWindow);
1493 	CONVERT_EACH_TO_ONE_END (my name.get())
1494 }
1495 
1496 FORM (CONVERT_EACH_TO_ONE__Sound_to_Harmonicity_gne, U"Sound: To Harmonicity (gne)", nullptr) {
1497 	POSITIVE (minimumFrequency, U"Minimum frequency (Hz)", U"500.0")
1498 	POSITIVE (maximumFrequency, U"Maximum frequency (Hz)", U"4500.0")
1499 	POSITIVE (bandwidth, U"Bandwidth (Hz)", U"1000.0")
1500 	POSITIVE (step, U"Step (Hz)", U"80.0")
1501 	OK
1502 DO
1503 	CONVERT_EACH_TO_ONE (Sound)
1504 		autoMatrix result = Sound_to_Harmonicity_GNE (me, minimumFrequency,
1505 				maximumFrequency, bandwidth, step);
1506 	CONVERT_EACH_TO_ONE_END (my name.get())
1507 }
1508 
1509 FORM (CONVERT_EACH_TO_ONE__old_Sound_to_Intensity, U"Sound: To Intensity", U"Sound: To Intensity...") {
1510 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
1511 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1512 	OK
1513 DO
1514 	CONVERT_EACH_TO_ONE (Sound)
1515 		autoIntensity result = Sound_to_Intensity (me,
1516 				minimumPitch, timeStep, false);
1517 	CONVERT_EACH_TO_ONE_END (my name.get())
1518 }
1519 
1520 FORM (CONVERT_EACH_TO_ONE__Sound_to_Intensity, U"Sound: To Intensity", U"Sound: To Intensity...") {
1521 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
1522 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1523 	BOOLEAN (subtractMean, U"Subtract mean", true)
1524 	OK
1525 DO_ALTERNATIVE (CONVERT_EACH_TO_ONE__old_Sound_to_Intensity)
1526 	CONVERT_EACH_TO_ONE (Sound)
1527 		autoIntensity result = Sound_to_Intensity (me,
1528 				minimumPitch, timeStep, subtractMean);
1529 	CONVERT_EACH_TO_ONE_END (my name.get())
1530 }
1531 
1532 FORM (CONVERT_EACH_TO_ONE__Sound_to_IntensityTier, U"Sound: To IntensityTier", nullptr) {
1533 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"100.0")
1534 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1535 	BOOLEAN (subtractMean, U"Subtract mean", true)
1536 	OK
1537 DO
1538 	CONVERT_EACH_TO_ONE (Sound)
1539 		autoIntensityTier result = Sound_to_IntensityTier (me,
1540 				minimumPitch, timeStep, subtractMean);
1541 	CONVERT_EACH_TO_ONE_END (my name.get())
1542 }
1543 
DIRECT(CONVERT_EACH_TO_ONE__Sound_to_IntervalTier)1544 DIRECT (CONVERT_EACH_TO_ONE__Sound_to_IntervalTier) {
1545 	CONVERT_EACH_TO_ONE (Sound)
1546 		autoIntervalTier result = IntervalTier_create (my xmin, my xmax);
1547 	CONVERT_EACH_TO_ONE_END (my name.get())
1548 }
1549 
1550 FORM (CONVERT_EACH_TO_ONE__Sound_to_Ltas, U"Sound: To long-term average spectrum", nullptr) {
1551 	POSITIVE (bandwidth, U"Bandwidth (Hz)", U"100")
1552 	OK
1553 DO
1554 	CONVERT_EACH_TO_ONE (Sound)
1555 		autoLtas result = Sound_to_Ltas (me, bandwidth);
1556 	CONVERT_EACH_TO_ONE_END (my name.get())
1557 }
1558 
1559 FORM (CONVERT_EACH_TO_ONE__Sound_to_Ltas_pitchCorrected, U"Sound: To Ltas (pitch-corrected)", U"Sound: To Ltas (pitch-corrected)...") {
1560 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1561 	POSITIVE (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
1562 	POSITIVE (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
1563 	POSITIVE (bandwidth, U"Bandwidth (Hz)", U"100.0")
1564 	REAL (shortestPeriod, U"Shortest period (s)", U"0.0001")
1565 	REAL (longestPeriod, U"Longest period (s)", U"0.02")
1566 	POSITIVE (maximumPeriodFactor, U"Maximum period factor", U"1.3")
1567 	OK
1568 DO
1569 	Melder_require (maximumPitch > minimumPitch,
1570 		U"Your maximum pitch should be greater than your minimum pitch.");
1571 	CONVERT_EACH_TO_ONE (Sound)
1572 		autoLtas result = Sound_to_Ltas_pitchCorrected (me, minimumPitch, maximumPitch,
1573 				maximumFrequency, bandwidth, shortestPeriod, longestPeriod, maximumPeriodFactor);
1574 	CONVERT_EACH_TO_ONE_END (my name.get())
1575 }
1576 
DIRECT(CONVERT_EACH_TO_ONE__Sound_downto_Matrix)1577 DIRECT (CONVERT_EACH_TO_ONE__Sound_downto_Matrix) {
1578 	CONVERT_EACH_TO_ONE (Sound)
1579 		autoMatrix result = Sound_to_Matrix (me);
1580 	CONVERT_EACH_TO_ONE_END (my name.get())
1581 }
1582 
DIRECT(CONVERT_TWO_TO_ONE__Sounds_to_ParamCurve)1583 DIRECT (CONVERT_TWO_TO_ONE__Sounds_to_ParamCurve) {
1584 	CONVERT_TWO_TO_ONE (Sound)
1585 		autoParamCurve result = ParamCurve_create (me, you);
1586 	CONVERT_TWO_TO_ONE_END (my name.get(), U"_", your name.get())
1587 }
1588 
1589 FORM (CONVERT_EACH_TO_ONE__Sound_to_Pitch, U"Sound: To Pitch", U"Sound: To Pitch...") {
1590 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1591 	POSITIVE (pitchFloor, U"Pitch floor (Hz)", U"75.0")
1592 	POSITIVE (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
1593 	OK
1594 DO
1595 	CONVERT_EACH_TO_ONE (Sound)
1596 		autoPitch result = Sound_to_Pitch (me, timeStep, pitchFloor, pitchCeiling);
1597 	CONVERT_EACH_TO_ONE_END (my name.get())
1598 }
1599 
1600 FORM (CONVERT_EACH_TO_ONE__Sound_to_Pitch_ac, U"Sound: To Pitch (ac)", U"Sound: To Pitch (ac)...") {
1601 	LABEL (U"Finding the candidates")
1602 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1603 	POSITIVE (pitchFloor, U"Pitch floor (Hz)", U"75.0")
1604 	NATURAL (maximumNumberOfCandidates, U"Max. number of candidates", U"15")
1605 	BOOLEAN (veryAccurate, U"Very accurate", false)
1606 	LABEL (U"Finding a path")
1607 	REAL (silenceThreshold, U"Silence threshold", U"0.03")
1608 	REAL (voicingThreshold, U"Voicing threshold", U"0.45")
1609 	REAL (octaveCost, U"Octave cost", U"0.01")
1610 	REAL (octaveJumpCost, U"Octave-jump cost", U"0.35")
1611 	REAL (voicedUnvoicedCost, U"Voiced / unvoiced cost", U"0.14")
1612 	POSITIVE (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
1613 	OK
1614 DO
1615 	Melder_require (maximumNumberOfCandidates > 1,
1616 		U"Your maximum number of candidates should be greater than 1.");
1617 	CONVERT_EACH_TO_ONE (Sound)
1618 		autoPitch result = Sound_to_Pitch_ac (me, timeStep,
1619 			pitchFloor, 3.0, maximumNumberOfCandidates, veryAccurate,
1620 			silenceThreshold, voicingThreshold, octaveCost, octaveJumpCost, voicedUnvoicedCost, pitchCeiling
1621 		);
1622 	CONVERT_EACH_TO_ONE_END (my name.get())
1623 }
1624 
1625 FORM (CONVERT_EACH_TO_ONE__Sound_to_Pitch_cc, U"Sound: To Pitch (cc)", U"Sound: To Pitch (cc)...") {
1626 	LABEL (U"Finding the candidates")
1627 	REAL (timeStep, U"Time step (s)", U"0.0 (= auto)")
1628 	POSITIVE (pitchFloor, U"Pitch floor (Hz)", U"75.0")
1629 	NATURAL (maximumNumberOfCandidates, U"Max. number of candidates", U"15")
1630 	BOOLEAN (veryAccurate, U"Very accurate", false)
1631 	LABEL (U"Finding a path")
1632 	REAL (silenceThreshold, U"Silence threshold", U"0.03")
1633 	REAL (voicingThreshold, U"Voicing threshold", U"0.45")
1634 	REAL (octaveCost, U"Octave cost", U"0.01")
1635 	REAL (octaveJumpCost, U"Octave-jump cost", U"0.35")
1636 	REAL (voicedUnvoicedCost, U"Voiced / unvoiced cost", U"0.14")
1637 	POSITIVE (pitchCeiling, U"Pitch ceiling (Hz)", U"600.0")
1638 	OK
1639 DO
1640 	Melder_require (maximumNumberOfCandidates > 1,
1641 		U"Your maximum number of candidates should be greater than 1.");
1642 	CONVERT_EACH_TO_ONE (Sound)
1643 		autoPitch result = Sound_to_Pitch_cc (me, timeStep,
1644 			pitchFloor, 1.0, maximumNumberOfCandidates, veryAccurate,
1645 			silenceThreshold, voicingThreshold, octaveCost, octaveJumpCost, voicedUnvoicedCost, pitchCeiling
1646 		);
1647 	CONVERT_EACH_TO_ONE_END (my name.get())
1648 }
1649 
1650 FORM (CONVERT_EACH_TO_ONE__Sound_to_PointProcess_extrema, U"Sound: To PointProcess (extrema)", nullptr) {
1651 	CHANNEL (channel, U"Channel (number, Left, or Right)", U"1")
1652 	BOOLEAN (includeMaxima, U"Include maxima", true)
1653 	BOOLEAN (includeMinima, U"Include minima", false)
1654 	RADIO_ENUM (kVector_peakInterpolation, peakInterpolationType,
1655 		U"Interpolation", kVector_peakInterpolation::SINC70)
1656 	OK
1657 DO
1658 	CONVERT_EACH_TO_ONE (Sound)
1659 		autoPointProcess result = Sound_to_PointProcess_extrema (me, channel > my ny ? 1 : channel,
1660 				peakInterpolationType, includeMaxima, includeMinima);
1661 	CONVERT_EACH_TO_ONE_END (my name.get())
1662 }
1663 
1664 FORM (CONVERT_EACH_TO_ONE__Sound_to_PointProcess_periodic_cc, U"Sound: To PointProcess (periodic, cc)", U"Sound: To PointProcess (periodic, cc)...") {
1665 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1666 	POSITIVE (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
1667 	OK
1668 DO
1669 	Melder_require (maximumPitch > minimumPitch,
1670 		U"Your maximum pitch should be greater than your minimum pitch.");
1671 	CONVERT_EACH_TO_ONE (Sound)
1672 		autoPointProcess result = Sound_to_PointProcess_periodic_cc (me, minimumPitch, maximumPitch);
1673 	CONVERT_EACH_TO_ONE_END (my name.get())
1674 }
1675 
1676 FORM (CONVERT_EACH_TO_ONE__Sound_to_PointProcess_periodic_peaks, U"Sound: To PointProcess (periodic, peaks)", U"Sound: To PointProcess (periodic, peaks)...") {
1677 	POSITIVE (minimumPitch, U"Minimum pitch (Hz)", U"75.0")
1678 	POSITIVE (maximumPitch, U"Maximum pitch (Hz)", U"600.0")
1679 	BOOLEAN (includeMaxima, U"Include maxima", true)
1680 	BOOLEAN (includeMinima, U"Include minima", false)
1681 	OK
1682 DO
1683 	Melder_require (maximumPitch > minimumPitch,
1684 		U"Your maximum pitch should be greater than your minimum pitch.");
1685 	CONVERT_EACH_TO_ONE (Sound)
1686 		autoPointProcess result = Sound_to_PointProcess_periodic_peaks (me,
1687 				minimumPitch, maximumPitch, includeMaxima, includeMinima);
1688 	CONVERT_EACH_TO_ONE_END (my name.get())
1689 }
1690 
1691 FORM (CONVERT_EACH_TO_ONE__Sound_to_PointProcess_zeroes, U"Get zeroes", nullptr) {
1692 	CHANNEL (channel, U"Channel (number, Left, or Right)", U"1")
1693 	BOOLEAN (includeRaisers, U"Include raisers", true)
1694 	BOOLEAN (includeFallers, U"Include fallers", false)
1695 	OK
1696 DO
1697 	CONVERT_EACH_TO_ONE (Sound)
1698 		autoPointProcess result = Sound_to_PointProcess_zeroes (me, channel > my ny ? 1 : channel,
1699 				includeRaisers, includeFallers);
1700 	CONVERT_EACH_TO_ONE_END (my name.get())
1701 }
1702 
1703 FORM (CONVERT_EACH_TO_ONE__Sound_to_Spectrogram, U"Sound: To Spectrogram", U"Sound: To Spectrogram...") {
1704 	POSITIVE (windowLength, U"Window length (s)", U"0.005")
1705 	POSITIVE (maximumFrequency, U"Maximum frequency (Hz)", U"5000.0")
1706 	POSITIVE (timeStep, U"Time step (s)", U"0.002")
1707 	POSITIVE (frequencyStep, U"Frequency step (Hz)", U"20.0")
1708 	RADIO_ENUM (kSound_to_Spectrogram_windowShape, windowShape,
1709 			U"Window shape", kSound_to_Spectrogram_windowShape::DEFAULT)
1710 	OK
1711 DO
1712 	CONVERT_EACH_TO_ONE (Sound)
1713 		autoSpectrogram result = Sound_to_Spectrogram (me, windowLength,
1714 				maximumFrequency, timeStep, frequencyStep, windowShape, 8.0, 8.0);
1715 	CONVERT_EACH_TO_ONE_END (my name.get())
1716 }
1717 
1718 FORM (CONVERT_EACH_TO_ONE__Sound_to_Spectrum, U"Sound: To Spectrum", U"Sound: To Spectrum...") {
1719 	BOOLEAN (fast, U"Fast", true)
1720 	OK
1721 DO
1722 	CONVERT_EACH_TO_ONE (Sound)
1723 		autoSpectrum result = Sound_to_Spectrum (me, fast);
1724 	CONVERT_EACH_TO_ONE_END (my name.get())
1725 }
1726 
DIRECT(CONVERT_EACH_TO_ONE__Sound_to_Spectrum_dft)1727 DIRECT (CONVERT_EACH_TO_ONE__Sound_to_Spectrum_dft) {
1728 	CONVERT_EACH_TO_ONE (Sound)
1729 		autoSpectrum result = Sound_to_Spectrum (me, false);
1730 	CONVERT_EACH_TO_ONE_END (my name.get())
1731 }
1732 
DIRECT(CONVERT_EACH_TO_ONE__Sound_to_Spectrum_fft)1733 DIRECT (CONVERT_EACH_TO_ONE__Sound_to_Spectrum_fft) {
1734 	CONVERT_EACH_TO_ONE (Sound)
1735 		autoSpectrum result = Sound_to_Spectrum (me, true);
1736 	CONVERT_EACH_TO_ONE_END (my name.get())
1737 }
1738 
1739 FORM (CONVERT_EACH_TO_ONE__Sound_to_TextGrid, U"Sound: To TextGrid", U"Sound: To TextGrid...") {
1740 	SENTENCE (allTierNames, U"All tier names", U"Mary John bell")
1741 	SENTENCE (whichOfTheseArePointTiers, U"Which of these are point tiers?", U"bell")
1742 	OK
1743 DO
1744 	CONVERT_EACH_TO_ONE (Sound)
1745 		autoTextGrid result = TextGrid_create (my xmin, my xmax, allTierNames, whichOfTheseArePointTiers);
1746 	CONVERT_EACH_TO_ONE_END (my name.get())
1747 }
1748 
DIRECT(CONVERT_EACH_TO_ONE__Sound_to_TextTier)1749 DIRECT (CONVERT_EACH_TO_ONE__Sound_to_TextTier) {
1750 	CONVERT_EACH_TO_ONE (Sound)
1751 		autoTextTier result = TextTier_create (my xmin, my xmax);
1752 	CONVERT_EACH_TO_ONE_END (my name.get())
1753 }
1754 
1755 FORM (PREFS__SoundInputPrefs, U"Sound recording preferences", U"SoundRecorder") {
1756 	NATURAL (bufferSize, U"Buffer size (MB)", U"60")
1757 	OPTIONMENU_ENUM (kMelder_inputSoundSystem, inputSoundSystem,
1758 			U"Input sound system", kMelder_inputSoundSystem::DEFAULT)
1759 OK
1760 	SET_INTEGER (bufferSize, SoundRecorder_getBufferSizePref_MB ())
1761 	SET_ENUM (inputSoundSystem, kMelder_inputSoundSystem, MelderAudio_getInputSoundSystem())
1762 DO
1763 	PREFS
1764 		if (bufferSize > 1000)
1765 			Melder_throw (U"Buffer size cannot exceed 1000 megabytes.");
1766 		SoundRecorder_setBufferSizePref_MB (bufferSize);
1767 		MelderAudio_setInputSoundSystem (inputSoundSystem);
1768 	PREFS_END
1769 }
1770 
1771 FORM (PREFS__SoundOutputPrefs, U"Sound playing preferences", nullptr) {
1772 	LABEL (U"The following determines how sounds are played.")
1773 	LABEL (U"Between parentheses, you find what you can do simultaneously.")
1774 	LABEL (U"Decrease asynchronicity if sound plays with discontinuities.")
1775 	OPTIONMENU_ENUM (kMelder_asynchronicityLevel, maximumAsynchronicity,
1776 			U"Maximum asynchronicity", kMelder_asynchronicityLevel::DEFAULT)
1777 	#define xstr(s) str(s)
1778 	#define str(s) #s
1779 	REAL (silenceBefore, U"Silence before (s)", U"" xstr (kMelderAudio_outputSilenceBefore_DEFAULT))
1780 	REAL (silenceAfter, U"Silence after (s)", U"" xstr (kMelderAudio_outputSilenceAfter_DEFAULT))
1781 	OPTIONMENU_ENUM (kMelder_outputSoundSystem, outputSoundSystem,
1782 			U"Output sound system", kMelder_outputSoundSystem::DEFAULT)
1783 OK
1784 	SET_ENUM (maximumAsynchronicity, kMelder_asynchronicityLevel, MelderAudio_getOutputMaximumAsynchronicity ())
1785 	SET_REAL (silenceBefore, MelderAudio_getOutputSilenceBefore ())
1786 	SET_REAL (silenceAfter, MelderAudio_getOutputSilenceAfter ())
1787 	SET_ENUM (outputSoundSystem, kMelder_outputSoundSystem, MelderAudio_getOutputSoundSystem())
1788 DO
1789 	PREFS
1790 		MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
1791 		MelderAudio_setOutputMaximumAsynchronicity (maximumAsynchronicity);
1792 		MelderAudio_setOutputSilenceBefore (silenceBefore);
1793 		MelderAudio_setOutputSilenceAfter (silenceAfter);
1794 		MelderAudio_setOutputSoundSystem (outputSoundSystem);
1795 	PREFS_END
1796 }
1797 
1798 #ifdef HAVE_PULSEAUDIO
1799 void pulseAudio_serverReport ();
DIRECT(INFO_NONE__Praat_reportSoundServerProperties)1800 DIRECT (INFO_NONE__Praat_reportSoundServerProperties) {
1801 	INFO_NONE
1802 		pulseAudio_serverReport ();
1803 	INFO_NONE_END
1804 }
1805 #endif
1806 
1807 FORM_SAVE (SAVE_ALL__Sound_saveAsAifcFile, U"Save as AIFC file", nullptr, U"aifc") {
1808 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1809 		LongSound_concatenate (list.get(), file, Melder_AIFC, 16);
1810 	SAVE_ALL_LISTED_END
1811 }
1812 
1813 FORM_SAVE (SAVE_ALL__Sound_saveAsAiffFile, U"Save as AIFF file", nullptr, U"aiff") {
1814 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1815 		LongSound_concatenate (list.get(), file, Melder_AIFF, 16);
1816 	SAVE_ALL_LISTED_END
1817 }
1818 
1819 FORM_SAVE (SAVE_ALL__Sound_saveAsFlacFile, U"Save as FLAC file", nullptr, U"flac") {
1820 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1821 		LongSound_concatenate (list.get(), file, Melder_FLAC, 16);
1822 	SAVE_ALL_LISTED_END
1823 }
1824 
1825 FORM_SAVE (SAVE_ONE__Sound_saveAsKayFile, U"Save as Kay sound file", nullptr, U"kay") {
1826 	SAVE_ONE (Sound)
1827 		Sound_saveAsKayFile (me, file);
1828 	SAVE_ONE_END
1829 }
1830 
1831 FORM_SAVE (SAVE_ALL__Sound_saveAsNextSunFile, U"Save as NeXT/Sun file", nullptr, U"au") {
1832 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1833 		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
1834 	SAVE_ALL_LISTED_END
1835 }
1836 
1837 FORM_SAVE (SAVE_ALL__Sound_saveAsNistFile, U"Save as NIST file", nullptr, U"nist") {
1838 	SAVE_ALL_LISTED (Sampled, SoundAndLongSoundList)
1839 		LongSound_concatenate (list.get(), file, Melder_NIST, 16);
1840 	SAVE_ALL_LISTED_END
1841 }
1842 
1843 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw8bitSignedFile, U"Save as raw 8-bit signed sound file", nullptr, U"8sig") {
1844 	SAVE_ONE (Sound)
1845 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_8_SIGNED);
1846 	SAVE_ONE_END
1847 }
1848 
1849 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw8bitUnsignedFile, U"Save as raw 8-bit unsigned sound file", nullptr, U"8uns") {
1850 	SAVE_ONE (Sound)
1851 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_8_UNSIGNED);
1852 	SAVE_ONE_END
1853 }
1854 
1855 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw16bitBigEndianFile, U"Save as raw 16-bit big-endian sound file", nullptr, U"16be") {
1856 	SAVE_ONE (Sound)
1857 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_16_BIG_ENDIAN);
1858 	SAVE_ONE_END
1859 }
1860 
1861 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw16bitLittleEndianFile, U"Save as raw 16-bit little-endian sound file", nullptr, U"16le") {
1862 	SAVE_ONE (Sound)
1863 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_16_LITTLE_ENDIAN);
1864 	SAVE_ONE_END
1865 }
1866 
1867 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw24bitBigEndianFile, U"Save as raw 24-bit big-endian sound file", nullptr, U"24be") {
1868 	SAVE_ONE (Sound)
1869 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_24_BIG_ENDIAN);
1870 	SAVE_ONE_END
1871 }
1872 
1873 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw24bitLittleEndianFile, U"Save as raw 24-bit little-endian sound file", nullptr, U"24le") {
1874 	SAVE_ONE (Sound)
1875 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_24_LITTLE_ENDIAN);
1876 	SAVE_ONE_END
1877 }
1878 
1879 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw32bitBigEndianFile, U"Save as raw 32-bit big-endian sound file", nullptr, U"32be") {
1880 	SAVE_ONE (Sound)
1881 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_32_BIG_ENDIAN);
1882 	SAVE_ONE_END
1883 }
1884 
1885 FORM_SAVE (SAVE_ONE__Sound_saveAsRaw32bitLittleEndianFile, U"Save as raw 32-bit little-endian sound file", nullptr, U"32le") {
1886 	SAVE_ONE (Sound)
1887 		Sound_saveAsRawSoundFile (me, file, Melder_LINEAR_32_LITTLE_ENDIAN);
1888 	SAVE_ONE_END
1889 }
1890 
1891 FORM_SAVE (SAVE_ONE__Sound_saveAsSesamFile, U"Save as Sesam file", nullptr, U"sdf") {
1892 	SAVE_ONE (Sound)
1893 		Sound_saveAsSesamFile (me, file);
1894 	SAVE_ONE_END
1895 }
1896 
1897 FORM_SAVE (SAVE_ALL__Sound_saveAsStereoAifcFile, U"Save as stereo AIFC file", nullptr, U"aifc") {
1898 	SAVE_ALL (Sound)
1899 		autoSound stereo = Sounds_combineToStereo (& list);
1900 		Sound_saveAsAudioFile (stereo.get(), file, Melder_AIFC, 16);
1901 	SAVE_ALL_END
1902 }
1903 
1904 FORM_SAVE (SAVE_ALL__Sound_saveAsStereoAiffFile, U"Save as stereo AIFF file", nullptr, U"aiff") {
1905 	SAVE_ALL (Sound)
1906 		autoSound stereo = Sounds_combineToStereo (& list);
1907 		Sound_saveAsAudioFile (stereo.get(), file, Melder_AIFF, 16);
1908 	SAVE_ALL_END
1909 }
1910 
1911 FORM_SAVE (SAVE_ALL__Sound_saveAsStereoNextSunFile, U"Save as stereo NeXT/Sun file", nullptr, U"au") {
1912 	SAVE_ALL (Sound)
1913 		autoSound stereo = Sounds_combineToStereo (& list);
1914 		Sound_saveAsAudioFile (stereo.get(), file, Melder_NEXT_SUN, 16);
1915 	SAVE_ALL_END
1916 }
1917 
1918 FORM_SAVE (SAVE_ALL__Sound_saveAsStereoNistFile, U"Save as stereo NIST file", nullptr, U"nist") {
1919 	SAVE_ALL (Sound)
1920 		autoSound stereo = Sounds_combineToStereo (& list);
1921 		Sound_saveAsAudioFile (stereo.get(), file, Melder_NIST, 16);
1922 	SAVE_ALL_END
1923 }
1924 
1925 FORM_SAVE (SAVE_ALL__Sound_saveAsStereoFlacFile, U"Save as stereo FLAC file", nullptr, U"flac") {
1926 	SAVE_ALL (Sound)
1927 		autoSound stereo = Sounds_combineToStereo (& list);
1928 		Sound_saveAsAudioFile (stereo.get(), file, Melder_FLAC, 16);
1929 	SAVE_ALL_END
1930 }
1931 
1932 FORM_SAVE (SAVE_ALL__Sound_saveAsStereoWavFile, U"Save as stereo WAV file", nullptr, U"wav") {
1933 	SAVE_ALL (Sound)
1934 		autoSound stereo = Sounds_combineToStereo (& list);
1935 		Sound_saveAsAudioFile (stereo.get(), file, Melder_WAV, 16);
1936 	SAVE_ALL_END
1937 }
1938 
1939 FORM_SAVE (SAVE_ALL__Sound_saveAsSunAudioFile, U"Save as NeXT/Sun file", nullptr, U"au") {
1940 	SAVE_ALL_LISTED (Sound, SoundAndLongSoundList)
1941 		LongSound_concatenate (list.get(), file, Melder_NEXT_SUN, 16);
1942 	SAVE_ALL_LISTED_END
1943 }
1944 
1945 FORM_SAVE (SAVE_ALL__Sound_saveAsWavFile, U"Save as WAV file", nullptr, U"wav") {
1946 	SAVE_ALL_LISTED (Sound, SoundAndLongSoundList)
1947 		LongSound_concatenate (list.get(), file, Melder_WAV, 16);
1948 	SAVE_ALL_LISTED_END
1949 }
1950 
1951 /***** SOUNDLIST *****/
1952 
DIRECT(CONVERT_EACH_TO_MULTIPLE__SoundList_extractAllSounds)1953 DIRECT (CONVERT_EACH_TO_MULTIPLE__SoundList_extractAllSounds) {
1954 	CONVERT_EACH_TO_MULTIPLE (SoundList)
1955 		autoSoundList result = Data_copy (me);
1956 		result -> classInfo = classCollection;   // YUCK, in order to force automatic unpacking
1957 		praat_new (result.move(), U"dummy");
1958 	CONVERT_EACH_TO_MULTIPLE_END
1959 }
1960 
1961 /***** SOUNDSET *****/
1962 
DIRECT(CONVERT_EACH_TO_MULTIPLE__SoundSet_extractAllSounds)1963 DIRECT (CONVERT_EACH_TO_MULTIPLE__SoundSet_extractAllSounds) {
1964 	CONVERT_EACH_TO_MULTIPLE (SoundSet)
1965 		autoSoundSet result = Data_copy (me);
1966 		result -> classInfo = classCollection;   // YUCK, in order to force automatic unpacking
1967 		praat_new (result.move(), U"dummy");
1968 	CONVERT_EACH_TO_MULTIPLE_END
1969 }
1970 
1971 FORM (CONVERT_ONE_AND_ONE_TO_MULTIPLE__SoundSet_Table_getRandomizedPatterns, U"SoundSet & Table: Get randomized patterns", nullptr) {
1972 	SENTENCE (columnName, U"Column name", U"")
1973 	NATURAL (numberOfPatterns, U"Number of patterns", U"1000")
1974 	NATURAL (inputSize, U"Input size (number of samples)", U"8000")
1975 	NATURAL (outputSize, U"Output size (number of classes)", U"5")
1976 	OK
1977 DO
1978 	CONVERT_ONE_AND_ONE_TO_MULTIPLE (SoundSet, Table)
1979 		autoPatternList inputs, outputs;
1980 		SoundSet_Table_getRandomizedPatterns (me, you, columnName, numberOfPatterns, inputSize, outputSize,
1981 				& inputs, & outputs);
1982 		praat_new (inputs.move(), U"inputs");
1983 		praat_new (outputs.move(), U"outputs");
1984 	CONVERT_ONE_AND_ONE_TO_MULTIPLE_END
1985 }
1986 
1987 /***** STOP *****/
1988 
DIRECT(PLAY__stopPlayingSound)1989 DIRECT (PLAY__stopPlayingSound) {
1990 	PLAY_NONE
1991 		MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
1992 	PLAY_NONE_END
1993 }
1994 
1995 /***** Help menus *****/
1996 
DIRECT(HELP__AnnotationTutorial)1997 DIRECT (HELP__AnnotationTutorial) {
1998 	HELP (U"Intro 7. Annotation")
1999 }
2000 
DIRECT(HELP__FilteringTutorial)2001 DIRECT (HELP__FilteringTutorial) {
2002 	HELP (U"Filtering")
2003 }
2004 
2005 /***** file recognizers *****/
2006 
macSoundOrEmptyFileRecognizer(integer nread,const char *,MelderFile file)2007 static autoDaata macSoundOrEmptyFileRecognizer (integer nread, const char * /* header */, MelderFile file) {
2008 	/***** No data in file? This may be a Macintosh sound file with only a resource fork. *****/
2009 	if (nread > 0)
2010 		return autoDaata ();
2011 	Melder_throw (U"File ", file, U" contains no audio data.");   // !!!
2012 }
2013 
soundFileRecognizer(integer nread,const char * header,MelderFile file)2014 static autoDaata soundFileRecognizer (integer nread, const char *header, MelderFile file) {
2015 	if (nread < 16)
2016 		return autoDaata ();
2017 	if (strnequ (header, "FORM", 4) && strnequ (header + 8, "AIF", 3))
2018 		return Sound_readFromSoundFile (file);
2019 	if (strnequ (header, "RIFF", 4) && (strnequ (header + 8, "WAVE", 4) || strnequ (header + 8, "CDDA", 4)))
2020 		return Sound_readFromSoundFile (file);
2021 	if (strnequ (header, ".snd", 4))
2022 		return Sound_readFromSoundFile (file);
2023 	if (strnequ (header, "NIST_1A", 7))
2024 		return Sound_readFromSoundFile (file);
2025 	if (strnequ (header, "fLaC", 4))
2026 		return Sound_readFromSoundFile (file);   // Erez Volk, March 2007
2027 	if ((Melder_stringMatchesCriterion (MelderFile_name (file), kMelder_string::ENDS_WITH, U".mp3", false))
2028 			&& mp3_recognize (nread, header))
2029 		return Sound_readFromSoundFile (file);   // Erez Volk, May 2007
2030 	return autoDaata ();
2031 }
2032 
movieFileRecognizer(integer nread,const char *,MelderFile file)2033 static autoDaata movieFileRecognizer (integer nread, const char * /* header */, MelderFile file) {
2034 	conststring32 fileName = MelderFile_name (file);
2035 	if (nread < 512 || (! Melder_stringMatchesCriterion (fileName, kMelder_string::ENDS_WITH, U".mov", false) &&
2036 	                    ! Melder_stringMatchesCriterion (fileName, kMelder_string::ENDS_WITH, U".avi", false)))
2037 		return autoDaata ();
2038 	Melder_throw (U"This Praat version cannot open movie files.");
2039 	return autoDaata ();
2040 }
2041 
sesamFileRecognizer(integer nread,const char *,MelderFile file)2042 static autoDaata sesamFileRecognizer (integer nread, const char * /* header */, MelderFile file) {
2043 	conststring32 fileName = MelderFile_name (file);
2044 	if (nread < 512 || (! Melder_stringMatchesCriterion (fileName, kMelder_string::ENDS_WITH, U".sdf", false)))
2045 		return autoDaata ();
2046 	return Sound_readFromSesamFile (file);
2047 }
2048 
bellLabsFileRecognizer(integer nread,const char * header,MelderFile file)2049 static autoDaata bellLabsFileRecognizer (integer nread, const char *header, MelderFile file) {
2050 	if (nread < 16 || ! strnequ (& header [0], "SIG\n", 4))
2051 		return autoDaata ();
2052 	return Sound_readFromBellLabsFile (file);
2053 }
2054 
kayFileRecognizer(integer nread,const char * header,MelderFile file)2055 static autoDaata kayFileRecognizer (integer nread, const char *header, MelderFile file) {
2056 	if (nread <= 12 || ! strnequ (& header [0], "FORMDS16", 8))
2057 		return autoDaata ();
2058 	return Sound_readFromKayFile (file);
2059 }
2060 
2061 /***** override play and record buttons in manuals *****/
2062 
2063 static autoSound melderSound, melderSoundFromFile;
2064 static Sound last;
recordProc(double duration)2065 static int recordProc (double duration) {
2066 	if (last == melderSound.get())
2067 		last = nullptr;
2068 	MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
2069 	melderSound = Sound_record_fixedTime (1, 1.0, 0.5, 44100, duration);
2070 	if (! melderSound)
2071 		return 0;
2072 	last = melderSound.get();
2073 	return 1;
2074 }
recordFromFileProc(MelderFile file)2075 static int recordFromFileProc (MelderFile file) {
2076 	if (last == melderSoundFromFile.get())
2077 		last = nullptr;
2078 	Melder_warningOff ();   // like "missing samples"
2079 	melderSoundFromFile = Data_readFromFile (file). static_cast_move<structSound>();
2080 	Melder_warningOn ();
2081 	if (! melderSoundFromFile)
2082 		return 0;
2083 	if (! Thing_isa (melderSoundFromFile.get(), classSound)) {
2084 		melderSoundFromFile.reset();
2085 		return 0;
2086 	}
2087 	last = melderSoundFromFile.get();
2088 	Sound_play (melderSoundFromFile.get(), nullptr, nullptr);
2089 	return 1;
2090 }
playProc()2091 static void playProc () {
2092 	if (melderSound) {
2093 		Sound_play (melderSound.get(), nullptr, nullptr);
2094 		last = melderSound.get();
2095 	}
2096 }
playReverseProc()2097 static void playReverseProc () {
2098 	/*if (melderSound) Sound_playReverse (melderSound);*/
2099 }
publishPlayedProc()2100 static int publishPlayedProc () {
2101 	if (! last)
2102 		return 0;
2103 	autoSound sound = Data_copy (last);
2104 	return Data_publish (sound.move());
2105 }
2106 
2107 /***** buttons *****/
2108 
praat_Sound_init()2109 void praat_Sound_init () {
2110 	Thing_recognizeClassesByName (classSound, classLongSound, classSoundList, classSoundSet, nullptr);
2111 
2112 	Data_recognizeFileType (macSoundOrEmptyFileRecognizer);
2113 	Data_recognizeFileType (soundFileRecognizer);
2114 	Data_recognizeFileType (movieFileRecognizer);
2115 	Data_recognizeFileType (sesamFileRecognizer);
2116 	Data_recognizeFileType (bellLabsFileRecognizer);
2117 	Data_recognizeFileType (kayFileRecognizer);
2118 
2119 	SoundRecorder_preferences ();
2120 	structSoundRecorder           :: f_preferences ();
2121 	structFunctionEditor          :: f_preferences ();
2122 	LongSound_preferences ();
2123 	structTimeSoundEditor         :: f_preferences ();
2124 	structTimeSoundAnalysisEditor :: f_preferences ();
2125 
2126 	Melder_setRecordProc (recordProc);
2127 	Melder_setRecordFromFileProc (recordFromFileProc);
2128 	Melder_setPlayProc (playProc);
2129 	Melder_setPlayReverseProc (playReverseProc);
2130 	Melder_setPublishPlayedProc (publishPlayedProc);
2131 
2132 	praat_addMenuCommand (U"Objects", U"New", U"Record mono Sound...", nullptr, praat_ATTRACTIVE | 'R' | praat_NO_API,
2133 			SINGLETON_CREATION_WINDOW__Sound_recordMono);
2134 	praat_addMenuCommand (U"Objects", U"New", U"Record stereo Sound...", nullptr, praat_NO_API,
2135 			SINGLETON_CREATION_WINDOW__Sound_recordStereo);
2136 	praat_addMenuCommand (U"Objects", U"New", U"Record Sound (fixed time)...", nullptr, praat_HIDDEN | praat_FORCE_API,
2137 			RECORD_ONE__Sound_record_fixedTime);
2138 	praat_addMenuCommand (U"Objects", U"New", U"Sound", nullptr, 0, nullptr);
2139 		praat_addMenuCommand (U"Objects", U"New", U"Create Sound as pure tone...", nullptr, 1,
2140 				CREATE_ONE__Sound_createAsPureTone);
2141 		praat_addMenuCommand (U"Objects", U"New", U"Create Sound from formula...", nullptr, 1,
2142 				CREATE_ONE__Sound_createFromFormula);
2143 		praat_addMenuCommand (U"Objects", U"New",   U"Create Sound...", U"*Create Sound from formula...", praat_DEPTH_1 | praat_DEPRECATED_2007,
2144 				CREATE_ONE__Sound_create);
2145 		praat_addMenuCommand (U"Objects", U"New", U"-- create sound advanced --", nullptr, 1, nullptr);
2146 		praat_addMenuCommand (U"Objects", U"New", U"Create Sound as tone complex...", nullptr, 1,
2147 				CREATE_ONE__Sound_createAsToneComplex);
2148 		praat_addMenuCommand (U"Objects", U"New",   U"Create Sound from tone complex...", U"*Create Sound as tone complex...", praat_DEPTH_1 | praat_DEPRECATED_2013,
2149 				CREATE_ONE__Sound_createAsToneComplex);
2150 
2151 	praat_addMenuCommand (U"Objects", U"Open", U"-- read sound --", nullptr, 0, nullptr);
2152 	praat_addMenuCommand (U"Objects", U"Open", U"Open long sound file...", nullptr, 'L', READ1_LongSound_open);
2153 	praat_addMenuCommand (U"Objects", U"Open", U"Read separate channels from sound file...", nullptr, 0,
2154 			READ_MULTIPLE__Sound_readSeparateChannelsFromSoundFile);
2155 	praat_addMenuCommand (U"Objects", U"Open", U"Read two Sounds from stereo file...", nullptr, praat_DEPRECATED_2010,
2156 			READ_MULTIPLE__Sound_readSeparateChannelsFromSoundFile);
2157 	praat_addMenuCommand (U"Objects", U"Open", U"Read from special sound file", nullptr, 0, nullptr);
2158 		praat_addMenuCommand (U"Objects", U"Open", U"Read Sound from raw Alaw file...", nullptr, praat_DEPTH_1, READ1_Sound_readFromRawAlawFile);
2159 
2160 	praat_addMenuCommand (U"Objects", U"Goodies", U"Stop playing sound", nullptr, GuiMenu_ESCAPE,
2161 			PLAY__stopPlayingSound);
2162 	praat_addMenuCommand (U"Objects", U"Preferences", U"-- sound prefs --", nullptr, 0, nullptr);
2163 	praat_addMenuCommand (U"Objects", U"Preferences", U"Sound recording preferences...", nullptr, 0,
2164 			PREFS__SoundInputPrefs);
2165 	praat_addMenuCommand (U"Objects", U"Preferences", U"Sound playing preferences...", nullptr, 0,
2166 			PREFS__SoundOutputPrefs);
2167 	praat_addMenuCommand (U"Objects", U"Preferences", U"LongSound preferences...", nullptr, 0,
2168 			PREFS__LongSoundPrefs);
2169 #ifdef HAVE_PULSEAUDIO
2170 	praat_addMenuCommand (U"Objects", U"Technical", U"Report sound server properties", U"Report system properties", 0,
2171 			INFO_NONE__Praat_reportSoundServerProperties);
2172 #endif
2173 
2174 	praat_addAction1 (classLongSound, 0, U"LongSound help", nullptr, 0,
2175 			HELP__LongSound_help);
2176 	praat_addAction1 (classLongSound, 1, U"View", nullptr, praat_ATTRACTIVE,
2177 			EDITOR_ONE__LongSound_view);
2178 	praat_addAction1 (classLongSound, 1,   U"Open", U"*View", praat_DEPRECATED_2011,
2179 			EDITOR_ONE__LongSound_view);
2180 	praat_addAction1 (classLongSound, 0, U"Play part...", nullptr, 0, PLAY_LongSound_playPart);
2181 	praat_addAction1 (classLongSound, 1, U"Query -", nullptr, 0, nullptr);
2182 		praat_TimeFunction_query_init (classLongSound);
2183 		praat_addAction1 (classLongSound, 1, U"Sampling", nullptr, 1, nullptr);
2184 		praat_addAction1 (classLongSound, 1, U"Get number of samples", nullptr, 2, INTEGER_LongSound_getNumberOfSamples);
2185 		praat_addAction1 (classLongSound, 1, U"Get sampling period", nullptr, 2, REAL_LongSound_getSamplePeriod);
2186 		praat_addAction1 (classLongSound, 1,   U"Get sample duration", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getSamplePeriod);
2187 		praat_addAction1 (classLongSound, 1,   U"Get sample period", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getSamplePeriod);
2188 		praat_addAction1 (classLongSound, 1, U"Get sampling frequency", nullptr, 2, REAL_LongSound_getSampleRate);
2189 		praat_addAction1 (classLongSound, 1,   U"Get sample rate", U"*Get sampling frequency", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getSampleRate);
2190 		praat_addAction1 (classLongSound, 1, U"-- get time discretization --", nullptr, 2, nullptr);
2191 		praat_addAction1 (classLongSound, 1, U"Get time from sample number...", nullptr, 2, REAL_LongSound_getTimeFromIndex);
2192 		praat_addAction1 (classLongSound, 1,   U"Get time from index...", U"*Get time from sample number...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getTimeFromIndex);
2193 		praat_addAction1 (classLongSound, 1, U"Get sample number from time...", nullptr, 2, REAL_LongSound_getIndexFromTime);
2194 		praat_addAction1 (classLongSound, 1,   U"Get index from time...", U"*Get sample number from time...", praat_DEPTH_2 | praat_DEPRECATED_2004, REAL_LongSound_getIndexFromTime);
2195 	praat_addAction1 (classLongSound, 0, U"Annotate -", nullptr, 0, nullptr);
2196 		praat_addAction1 (classLongSound, 0, U"Annotation tutorial", nullptr, 1,
2197 				HELP__AnnotationTutorial);
2198 		praat_addAction1 (classLongSound, 0, U"-- to text grid --", nullptr, 1, nullptr);
2199 		praat_addAction1 (classLongSound, 0, U"To TextGrid...", nullptr, 1, NEW_LongSound_to_TextGrid);
2200 	praat_addAction1 (classLongSound, 0, U"Convert to Sound", nullptr, 0, nullptr);
2201 	praat_addAction1 (classLongSound, 0, U"Extract part...", nullptr, 0, NEW_LongSound_extractPart);
2202 	praat_addAction1 (classLongSound, 0, U"Concatenate?", nullptr, 0,
2203 			INFO_NONE__LongSound_concatenate);
2204 	praat_addAction1 (classLongSound, 0, U"Save as WAV file...", nullptr, 0,
2205 			SAVE_ALL__LongSound_saveAsWavFile);
2206 	praat_addAction1 (classLongSound, 0,   U"Write to WAV file...", U"*Save as WAV file...", praat_DEPRECATED_2011,
2207 			SAVE_ALL__LongSound_saveAsWavFile);
2208 	praat_addAction1 (classLongSound, 0, U"Save as AIFF file...", nullptr, 0,
2209 			SAVE_ALL__LongSound_saveAsAiffFile);
2210 	praat_addAction1 (classLongSound, 0,   U"Write to AIFF file...", U"*Save as AIFF file...", praat_DEPRECATED_2011,
2211 			SAVE_ALL__LongSound_saveAsAiffFile);
2212 	praat_addAction1 (classLongSound, 0, U"Save as AIFC file...", nullptr, 0,
2213 			SAVE_ALL__LongSound_saveAsAifcFile);
2214 	praat_addAction1 (classLongSound, 0,   U"Write to AIFC file...", U"*Save as AIFC file...", praat_DEPRECATED_2011,
2215 			SAVE_ALL__LongSound_saveAsAifcFile);
2216 	praat_addAction1 (classLongSound, 0, U"Save as NeXT/Sun file...", nullptr, 0,
2217 			SAVE_ALL__LongSound_saveAsNextSunFile);
2218 	praat_addAction1 (classLongSound, 0,   U"Write to NeXT/Sun file...", U"*Save as NeXT/Sun file...", praat_DEPRECATED_2011,
2219 			SAVE_ALL__LongSound_saveAsNextSunFile);
2220 	praat_addAction1 (classLongSound, 0, U"Save as NIST file...", nullptr, 0,
2221 			SAVE_ALL__LongSound_saveAsNistFile);
2222 	praat_addAction1 (classLongSound, 0,   U"Write to NIST file...", U"*Save as NIST file...", praat_DEPRECATED_2011,
2223 			SAVE_ALL__LongSound_saveAsNistFile);
2224 	praat_addAction1 (classLongSound, 0, U"Save as FLAC file...", nullptr, 0,
2225 			SAVE_ALL__LongSound_saveAsFlacFile);
2226 	praat_addAction1 (classLongSound, 0,   U"Write to FLAC file...", U"*Save as FLAC file...", praat_DEPRECATED_2011,
2227 			SAVE_ALL__LongSound_saveAsFlacFile);
2228 	praat_addAction1 (classLongSound, 1, U"Save left channel as WAV file...", nullptr, 0,
2229 			SAVE_ONE__LongSound_saveLeftChannelAsWavFile);
2230 	praat_addAction1 (classLongSound, 1,   U"Write left channel to WAV file...", U"*Save left channel as WAV file...", praat_DEPRECATED_2011,
2231 			SAVE_ONE__LongSound_saveLeftChannelAsWavFile);
2232 	praat_addAction1 (classLongSound, 1, U"Save left channel as AIFF file...", nullptr, 0,
2233 			SAVE_ONE__LongSound_saveLeftChannelAsAiffFile);
2234 	praat_addAction1 (classLongSound, 1,   U"Write left channel to AIFF file...", U"*Save left channel as AIFF file...", praat_DEPRECATED_2011,
2235 			SAVE_ONE__LongSound_saveLeftChannelAsAiffFile);
2236 	praat_addAction1 (classLongSound, 1, U"Save left channel as AIFC file...", nullptr, 0,
2237 			SAVE_ONE__LongSound_saveLeftChannelAsAifcFile);
2238 	praat_addAction1 (classLongSound, 1,   U"Write left channel to AIFC file...", U"*Save left channel as AIFC file...", praat_DEPRECATED_2011,
2239 			SAVE_ONE__LongSound_saveLeftChannelAsAifcFile);
2240 	praat_addAction1 (classLongSound, 1, U"Save left channel as NeXT/Sun file...", nullptr, 0,
2241 			SAVE_ONE__LongSound_saveLeftChannelAsNextSunFile);
2242 	praat_addAction1 (classLongSound, 1,   U"Write left channel to NeXT/Sun file...", U"*Save left channel as NeXT/Sun file...", praat_DEPRECATED_2011,
2243 			SAVE_ONE__LongSound_saveLeftChannelAsNextSunFile);
2244 	praat_addAction1 (classLongSound, 1, U"Save left channel as NIST file...", nullptr, 0,
2245 			SAVE_ONE__LongSound_saveLeftChannelAsNistFile);
2246 	praat_addAction1 (classLongSound, 1,   U"Write left channel to NIST file...", U"*Save left channel as NIST file...", praat_DEPRECATED_2011,
2247 			SAVE_ONE__LongSound_saveLeftChannelAsNistFile);
2248 	praat_addAction1 (classLongSound, 1, U"Save left channel as FLAC file...", nullptr, 0,
2249 			SAVE_ONE__LongSound_saveLeftChannelAsFlacFile);
2250 	praat_addAction1 (classLongSound, 1,   U"Write left channel to FLAC file...", U"*Save left channel as FLAC file...", praat_DEPRECATED_2011,
2251 			SAVE_ONE__LongSound_saveLeftChannelAsFlacFile);
2252 	praat_addAction1 (classLongSound, 1, U"Save right channel as WAV file...", nullptr, 0,
2253 			SAVE_ONE__LongSound_saveRightChannelAsWavFile);
2254 	praat_addAction1 (classLongSound, 1,   U"Write right channel to WAV file...", U"*Save right channel as WAV file...", praat_DEPRECATED_2011,
2255 			SAVE_ONE__LongSound_saveRightChannelAsWavFile);
2256 	praat_addAction1 (classLongSound, 1, U"Save right channel as AIFF file...", nullptr, 0,
2257 			SAVE_ONE__LongSound_saveRightChannelAsAiffFile);
2258 	praat_addAction1 (classLongSound, 1,   U"Write right channel to AIFF file...", U"*Save right channel as AIFF file...", praat_DEPRECATED_2011,
2259 			SAVE_ONE__LongSound_saveRightChannelAsAiffFile);
2260 	praat_addAction1 (classLongSound, 1, U"Save right channel as AIFC file...", nullptr, 0,
2261 			SAVE_ONE__LongSound_saveRightChannelAsAifcFile);
2262 	praat_addAction1 (classLongSound, 1,   U"Write right channel to AIFC file...", U"*Save right channel as AIFC file...", praat_DEPRECATED_2011,
2263 			SAVE_ONE__LongSound_saveRightChannelAsAifcFile);
2264 	praat_addAction1 (classLongSound, 1, U"Save right channel as NeXT/Sun file...", nullptr, 0,
2265 			SAVE_ONE__LongSound_saveRightChannelAsNextSunFile);
2266 	praat_addAction1 (classLongSound, 1,   U"Write right channel to NeXT/Sun file...", U"*Save right channel as NeXT/Sun file...", praat_DEPRECATED_2011,
2267 			SAVE_ONE__LongSound_saveRightChannelAsNextSunFile);
2268 	praat_addAction1 (classLongSound, 1, U"Save right channel as NIST file...", nullptr, 0,
2269 			SAVE_ONE__LongSound_saveRightChannelAsNistFile);
2270 	praat_addAction1 (classLongSound, 1,   U"Write right channel to NIST file...", U"*Save right channel as NIST file...", praat_DEPRECATED_2011,
2271 			SAVE_ONE__LongSound_saveRightChannelAsNistFile);
2272 	praat_addAction1 (classLongSound, 1, U"Save right channel as FLAC file...", nullptr, 0,
2273 			SAVE_ONE__LongSound_saveRightChannelAsFlacFile);
2274 	praat_addAction1 (classLongSound, 1,   U"Write right channel to FLAC file...", U"*Save right channel as FLAC file...", praat_DEPRECATED_2011,
2275 			SAVE_ONE__LongSound_saveRightChannelAsFlacFile);
2276 	praat_addAction1 (classLongSound, 1, U"Save part as audio file...", nullptr, 0,
2277 			SAVE_ONE__LongSound_savePartAsAudioFile);
2278 	praat_addAction1 (classLongSound, 1,   U"Write part to audio file...", U"*Save part as audio file...", praat_DEPRECATED_2011,
2279 			SAVE_ONE__LongSound_savePartAsAudioFile);
2280 
2281 	praat_addAction1 (classSound, 0, U"Save as WAV file...", nullptr, 0,
2282 			SAVE_ALL__Sound_saveAsWavFile);
2283 	praat_addAction1 (classSound, 0,   U"Write to WAV file...", U"*Save as WAV file...", praat_DEPRECATED_2011,
2284 			SAVE_ALL__Sound_saveAsWavFile);
2285 	praat_addAction1 (classSound, 0, U"Save as AIFF file...", nullptr, 0,
2286 			SAVE_ALL__Sound_saveAsAiffFile);
2287 	praat_addAction1 (classSound, 0,   U"Write to AIFF file...", U"*Save as AIFF file...", praat_DEPRECATED_2011,
2288 			SAVE_ALL__Sound_saveAsAiffFile);
2289 	praat_addAction1 (classSound, 0, U"Save as AIFC file...", nullptr, 0,
2290 			SAVE_ALL__Sound_saveAsAifcFile);
2291 	praat_addAction1 (classSound, 0,   U"Write to AIFC file...", U"*Save as AIFC file...", praat_DEPRECATED_2011,
2292 			SAVE_ALL__Sound_saveAsAifcFile);
2293 	praat_addAction1 (classSound, 0, U"Save as NeXT/Sun file...", nullptr, 0,
2294 			SAVE_ALL__Sound_saveAsNextSunFile);
2295 	praat_addAction1 (classSound, 0,   U"Write to NeXT/Sun file...", U"*Save as NeXT/Sun file...", praat_DEPRECATED_2011,
2296 			SAVE_ALL__Sound_saveAsNextSunFile);
2297 	praat_addAction1 (classSound, 0, U"Save as Sun audio file...", nullptr, praat_HIDDEN,
2298 			SAVE_ALL__Sound_saveAsSunAudioFile);
2299 	praat_addAction1 (classSound, 0,   U"Write to Sun audio file...", U"*Save as Sun audio file...", praat_DEPRECATED_2011,
2300 			SAVE_ALL__Sound_saveAsSunAudioFile);
2301 	praat_addAction1 (classSound, 0, U"Save as NIST file...", nullptr, 0,
2302 			SAVE_ALL__Sound_saveAsNistFile);
2303 	praat_addAction1 (classSound, 0,   U"Write to NIST file...", U"*Save as NIST file...", praat_DEPRECATED_2011,
2304 			SAVE_ALL__Sound_saveAsNistFile);
2305 	praat_addAction1 (classSound, 0, U"Save as FLAC file...", nullptr, 0,
2306 			SAVE_ALL__Sound_saveAsFlacFile);
2307 	praat_addAction1 (classSound, 0,   U"Write to FLAC file...", U"*Save as FLAC file...", praat_DEPRECATED_2011,
2308 			SAVE_ALL__Sound_saveAsFlacFile);
2309 	praat_addAction1 (classSound, 1, U"Save as Kay sound file...", nullptr, 0,
2310 			SAVE_ONE__Sound_saveAsKayFile);
2311 	praat_addAction1 (classSound, 1,   U"Write to Kay sound file...", U"*Save as Kay sound file...", praat_DEPRECATED_2011,
2312 			SAVE_ONE__Sound_saveAsKayFile);
2313 	praat_addAction1 (classSound, 1, U"Save as Sesam file...", nullptr, praat_HIDDEN,
2314 			SAVE_ONE__Sound_saveAsSesamFile);
2315 	praat_addAction1 (classSound, 1,   U"Write to Sesam file...", U"*Save as Sesam file...", praat_DEPRECATED_2011,
2316 			SAVE_ONE__Sound_saveAsSesamFile);
2317 	praat_addAction1 (classSound, 0, U"Save as 24-bit WAV file...", nullptr, 0,
2318 			SAVE_ALL__Sound_saveAs24BitWavFile);
2319 	praat_addAction1 (classSound, 0, U"Save as 32-bit WAV file...", nullptr, 0,
2320 			SAVE_ALL__Sound_saveAs32BitWavFile);
2321 	praat_addAction1 (classSound, 2,   U"Write to stereo WAV file...", U"* \"Combine to stereo\" and \"Save to WAV file...\"", praat_DEPRECATED_2007,
2322 			SAVE_ALL__Sound_saveAsStereoWavFile);
2323 	praat_addAction1 (classSound, 2,   U"Write to stereo AIFF file...", U"* \"Combine to stereo\" and \"Save to AIFF file...\"", praat_DEPRECATED_2007,
2324 			SAVE_ALL__Sound_saveAsStereoAiffFile);
2325 	praat_addAction1 (classSound, 2,   U"Write to stereo AIFC file...", U"* \"Combine to stereo\" and \"Save to AIFC file...\"", praat_DEPRECATED_2007,
2326 			SAVE_ALL__Sound_saveAsStereoAifcFile);
2327 	praat_addAction1 (classSound, 2,   U"Write to stereo NeXT/Sun file...", U"* \"Combine to stereo\" and \"Save to NeXT/Sun file...\"", praat_DEPRECATED_2007,
2328 			SAVE_ALL__Sound_saveAsStereoNextSunFile);
2329 	praat_addAction1 (classSound, 2,   U"Write to stereo NIST file...", U"* \"Combine to stereo\" and \"Save to NIST file...\"", praat_DEPRECATED_2007,
2330 			SAVE_ALL__Sound_saveAsStereoNistFile);
2331 	praat_addAction1 (classSound, 2,   U"Write to stereo FLAC file...", U"* \"Combine to stereo\" and \"Save to FLAC file...\"", praat_DEPRECATED_2007,
2332 			SAVE_ALL__Sound_saveAsStereoFlacFile);
2333 	//praat_addAction1 (classSound, 1, U"Save as raw sound file", nullptr, 0, nullptr);
2334 	praat_addAction1 (classSound, 1, U"Save as raw 8-bit signed file...", nullptr, 0,
2335 			SAVE_ONE__Sound_saveAsRaw8bitSignedFile);
2336 	praat_addAction1 (classSound, 1,   U"Write to raw 8-bit signed file...", U"*Save as raw 8-bit signed file...", praat_DEPRECATED_2011,
2337 			SAVE_ONE__Sound_saveAsRaw8bitSignedFile);
2338 	praat_addAction1 (classSound, 1, U"Save as raw 8-bit unsigned file...", nullptr, 0,
2339 			SAVE_ONE__Sound_saveAsRaw8bitUnsignedFile);
2340 	praat_addAction1 (classSound, 1,   U"Write to raw 8-bit unsigned file...", U"*Save as raw 8-bit unsigned file...", praat_DEPRECATED_2011,
2341 			SAVE_ONE__Sound_saveAsRaw8bitUnsignedFile);
2342 	praat_addAction1 (classSound, 1, U"Save as raw 16-bit big-endian file...", nullptr, 0,
2343 			SAVE_ONE__Sound_saveAsRaw16bitBigEndianFile);
2344 	praat_addAction1 (classSound, 1, U"Save as raw 16-bit little-endian file...", nullptr, 0,
2345 			SAVE_ONE__Sound_saveAsRaw16bitLittleEndianFile);
2346 	praat_addAction1 (classSound, 1, U"Save as raw 24-bit big-endian file...", nullptr, 0,
2347 			SAVE_ONE__Sound_saveAsRaw24bitBigEndianFile);
2348 	praat_addAction1 (classSound, 1, U"Save as raw 24-bit little-endian file...", nullptr, 0,
2349 			SAVE_ONE__Sound_saveAsRaw24bitLittleEndianFile);
2350 	praat_addAction1 (classSound, 1, U"Save as raw 32-bit big-endian file...", nullptr, 0,
2351 			SAVE_ONE__Sound_saveAsRaw32bitBigEndianFile);
2352 	praat_addAction1 (classSound, 1, U"Save as raw 32-bit little-endian file...", nullptr, 0,
2353 			SAVE_ONE__Sound_saveAsRaw32bitLittleEndianFile);
2354 	praat_addAction1 (classSound, 0, U"Sound help", nullptr, 0,
2355 			HELP__Sound_help);
2356 	praat_addAction1 (classSound, 1, U"View & Edit", 0, praat_ATTRACTIVE | praat_NO_API,
2357 			EDITOR_ONE__Sound_viewAndEdit);
2358 	praat_addAction1 (classSound, 1,   U"Edit", U"*View & Edit", praat_DEPRECATED_2011 | praat_NO_API,
2359 			EDITOR_ONE__Sound_viewAndEdit);
2360 	praat_addAction1 (classSound, 1,   U"Open", U"*View & Edit", praat_DEPRECATED_2011 | praat_NO_API,
2361 			EDITOR_ONE__Sound_viewAndEdit);
2362 	praat_addAction1 (classSound, 0, U"Play", nullptr, 0,
2363 			PLAY_EACH__Sound_play);
2364 	praat_addAction1 (classSound, 1, U"Draw -", nullptr, 0, nullptr);
2365 		praat_addAction1 (classSound, 0, U"Draw...", nullptr, 1,
2366 				GRAPHICS_EACH__Sound_draw);
2367 	praat_addAction1 (classSound, 1, U"Query -", nullptr, 0, nullptr);
2368 		praat_TimeFunction_query_init (classSound);
2369 		praat_addAction1 (classSound, 1, U"Get number of channels", nullptr, 1,
2370 				QUERY_ONE_FOR_INTEGER__Sound_getNumberOfChannels);
2371 		praat_addAction1 (classSound, 1, U"Query time sampling", nullptr, 1, nullptr);
2372 		praat_addAction1 (classSound, 1, U"Get number of samples", nullptr, 2,
2373 				QUERY_ONE_FOR_INTEGER__Sound_getNumberOfSamples);
2374 		praat_addAction1 (classSound, 1, U"Get sampling period", nullptr, 2,
2375 				QUERY_ONE_FOR_REAL__Sound_getSamplePeriod);
2376 		praat_addAction1 (classSound, 1,   U"Get sample duration", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004,
2377 				QUERY_ONE_FOR_REAL__Sound_getSamplePeriod);
2378 		praat_addAction1 (classSound, 1,   U"Get sample period", U"*Get sampling period", praat_DEPTH_2 | praat_DEPRECATED_2004,
2379 				QUERY_ONE_FOR_REAL__Sound_getSamplePeriod);
2380 		praat_addAction1 (classSound, 1, U"Get sampling frequency", nullptr, 2,
2381 				QUERY_ONE_FOR_REAL__Sound_getSampleRate);
2382 		praat_addAction1 (classSound, 1,   U"Get sample rate", U"*Get sampling frequency", praat_DEPTH_2 | praat_DEPRECATED_2004,
2383 				QUERY_ONE_FOR_REAL__Sound_getSampleRate);
2384 		praat_addAction1 (classSound, 1, U"-- get time discretization --", nullptr, 2, nullptr);
2385 		praat_addAction1 (classSound, 1, U"Get time from sample number...", nullptr, 2,
2386 				QUERY_ONE_FOR_REAL__Sound_getTimeFromIndex);
2387 		praat_addAction1 (classSound, 1,   U"Get time from index...", U"*Get time from sample number...", praat_DEPTH_2 | praat_DEPRECATED_2004,
2388 				QUERY_ONE_FOR_REAL__Sound_getTimeFromIndex);
2389 		praat_addAction1 (classSound, 1, U"List all sample times", nullptr, 2, NUMVEC_Sound_listAllSampleTimes);
2390 		praat_addAction1 (classSound, 1,   U"Get sample times", U"*List all sample times", praat_DEPTH_2 | praat_DEPRECATED_2019, NUMVEC_Sound_listAllSampleTimes);
2391 		praat_addAction1 (classSound, 1, U"Get sample number from time...", nullptr, 2,
2392 				QUERY_ONE_FOR_REAL__Sound_getIndexFromTime);
2393 		praat_addAction1 (classSound, 1,   U"Get index from time...", U"*Get sample number from time...", praat_DEPTH_2 | praat_DEPRECATED_2004,
2394 				QUERY_ONE_FOR_REAL__Sound_getIndexFromTime);
2395 		praat_addAction1 (classSound, 1, U"-- get content --", nullptr, 1, nullptr);
2396 		praat_addAction1 (classSound, 1, U"Get value at time...", nullptr, 1,
2397 				QUERY_ONE_FOR_REAL__Sound_getValueAtTime);
2398 		praat_addAction1 (classSound, 1, U"Get value at sample number...", nullptr, 1,
2399 				QUERY_ONE_FOR_REAL__Sound_getValueAtIndex);
2400 		praat_addAction1 (classSound, 1,   U"Get value at index...", U"*Get value at sample number...", praat_DEPTH_1 | praat_DEPRECATED_2004,
2401 				QUERY_ONE_FOR_REAL__Sound_getValueAtIndex);
2402 		praat_addAction1 (classSound, 1, U"-- get shape --", nullptr, 1, nullptr);
2403 		praat_addAction1 (classSound, 1, U"Get minimum...", nullptr, 1,
2404 				QUERY_ONE_FOR_REAL__Sound_getMinimum);
2405 		praat_addAction1 (classSound, 1, U"Get time of minimum...", nullptr, 1,
2406 				QUERY_ONE_FOR_REAL__Sound_getTimeOfMinimum);
2407 		praat_addAction1 (classSound, 1, U"Get maximum...", nullptr, 1,
2408 				QUERY_ONE_FOR_REAL__Sound_getMaximum);
2409 		praat_addAction1 (classSound, 1, U"Get time of maximum...", nullptr, 1,
2410 				QUERY_ONE_FOR_REAL__Sound_getTimeOfMaximum);
2411 		praat_addAction1 (classSound, 1, U"Get absolute extremum...", nullptr, 1,
2412 				QUERY_ONE_FOR_REAL__Sound_getAbsoluteExtremum);
2413 		praat_addAction1 (classSound, 1, U"Get nearest zero crossing...", nullptr, 1,
2414 				QUERY_ONE_FOR_REAL__Sound_getNearestZeroCrossing);
2415 		praat_addAction1 (classSound, 1, U"-- get statistics --", nullptr, 1, nullptr);
2416 		praat_addAction1 (classSound, 1, U"Get mean...", nullptr, 1,
2417 				QUERY_ONE_FOR_REAL__Sound_getMean);
2418 		praat_addAction1 (classSound, 1, U"Get root-mean-square...", nullptr, 1,
2419 				QUERY_ONE_FOR_REAL__Sound_getRootMeanSquare);
2420 		praat_addAction1 (classSound, 1, U"Get standard deviation...", nullptr, 1,
2421 				QUERY_ONE_FOR_REAL__Sound_getStandardDeviation);
2422 		praat_addAction1 (classSound, 1, U"-- get energy --", nullptr, 1, nullptr);
2423 		praat_addAction1 (classSound, 1, U"Get energy...", nullptr, 1,
2424 				QUERY_ONE_FOR_REAL__Sound_getEnergy);
2425 		praat_addAction1 (classSound, 1, U"Get power...", nullptr, 1,
2426 				QUERY_ONE_FOR_REAL__Sound_getPower);
2427 		praat_addAction1 (classSound, 1, U"-- get energy in air --", nullptr, 1, nullptr);
2428 		praat_addAction1 (classSound, 1, U"Get energy in air", nullptr, 1,
2429 				QUERY_ONE_FOR_REAL__Sound_getEnergyInAir);
2430 		praat_addAction1 (classSound, 1, U"Get power in air", nullptr, 1,
2431 				QUERY_ONE_FOR_REAL__Sound_getPowerInAir);
2432 		praat_addAction1 (classSound, 1, U"Get intensity (dB)", nullptr, 1,
2433 				QUERY_ONE_FOR_REAL__Sound_getIntensity_dB);
2434 	praat_addAction1 (classSound, 0, U"Modify -", nullptr, 0, nullptr);
2435 		praat_TimeFunction_modify_init (classSound);
2436 		praat_addAction1 (classSound, 0, U"-- modify generic --", nullptr, 1, nullptr);
2437 		praat_addAction1 (classSound, 0, U"Reverse", nullptr, 1, MODIFY_Sound_reverse);
2438 		praat_addAction1 (classSound, 0, U"Formula...", nullptr, 1, MODIFY_Sound_formula);
2439 		praat_addAction1 (classSound, 0, U"Formula (part)...", nullptr, 1, MODIFY_Sound_formula_part);
2440 		praat_addAction1 (classSound, 0, U"-- add & mul --", nullptr, 1, nullptr);
2441 		praat_addAction1 (classSound, 0, U"Add...", nullptr, 1, MODIFY_Sound_add);
2442 		praat_addAction1 (classSound, 0, U"Subtract mean", nullptr, 1, MODIFY_Sound_subtractMean);
2443 		praat_addAction1 (classSound, 0, U"Multiply...", nullptr, 1, MODIFY_Sound_multiply);
2444 		praat_addAction1 (classSound, 0, U"Multiply by window...", nullptr, 1, MODIFY_Sound_multiplyByWindow);
2445 		praat_addAction1 (classSound, 0, U"Scale peak...", nullptr, 1, MODIFY_Sound_scalePeak);
2446 		praat_addAction1 (classSound, 0,   U"Scale...", nullptr, praat_DEPTH_1 | praat_DEPRECATED_2004, MODIFY_Sound_scalePeak);
2447 		praat_addAction1 (classSound, 0, U"Scale intensity...", nullptr, 1, MODIFY_Sound_scaleIntensity);
2448 		praat_addAction1 (classSound, 0, U"-- set --", nullptr, 1, nullptr);
2449 		praat_addAction1 (classSound, 0, U"Set value at sample number...", nullptr, 1, MODIFY_Sound_setValueAtIndex);
2450 		praat_addAction1 (classSound, 0,   U"Set value at index...", U"*Set value at sample number...", praat_DEPTH_1 | praat_DEPRECATED_2004, MODIFY_Sound_setValueAtIndex);
2451 		praat_addAction1 (classSound, 0, U"Set part to zero...", nullptr, 1, MODIFY_Sound_setPartToZero);
2452 		praat_addAction1 (classSound, 0, U"-- modify hack --", nullptr, 1, nullptr);
2453 		praat_addAction1 (classSound, 0, U"Override sampling frequency...", nullptr, 1, MODIFY_Sound_overrideSamplingFrequency);
2454 		praat_addAction1 (classSound, 0,   U"Override sample rate...", U"*Override sampling frequency...", praat_DEPTH_1 | praat_DEPRECATED_2004, MODIFY_Sound_overrideSamplingFrequency);
2455 		praat_addAction1 (classSound, 0, U"-- in-place filters --", nullptr, 1, nullptr);
2456 		praat_addAction1 (classSound, 0, U"In-place filters", nullptr, 1, nullptr);
2457 		praat_addAction1 (classSound, 0, U"Filter with one formant (in-place)...", nullptr, 2, MODIFY_Sound_filterWithOneFormantInplace);
2458 		praat_addAction1 (classSound, 0, U"Filter with one formant (in-line)...", nullptr, praat_DEPTH_2 | praat_DEPRECATED_2017, MODIFY_Sound_filterWithOneFormantInplace);
2459 		praat_addAction1 (classSound, 0, U"Pre-emphasize (in-place)...", nullptr, 2, MODIFY_Sound_preemphasizeInplace);
2460 		praat_addAction1 (classSound, 0, U"Pre-emphasize (in-line)...", nullptr, praat_DEPTH_2 | praat_DEPRECATED_2017, MODIFY_Sound_preemphasizeInplace);
2461 		praat_addAction1 (classSound, 0, U"De-emphasize (in-place)...", nullptr, 2, MODIFY_Sound_deemphasizeInplace);
2462 		praat_addAction1 (classSound, 0, U"De-emphasize (in-line)...", nullptr, praat_DEPTH_2 | praat_DEPRECATED_2017, MODIFY_Sound_deemphasizeInplace);
2463 	praat_addAction1 (classSound, 0, U"Annotate -", nullptr, 0, nullptr);
2464 		praat_addAction1 (classSound, 0, U"Annotation tutorial", nullptr, 1,
2465 				HELP__AnnotationTutorial);
2466 		praat_addAction1 (classSound, 0, U"-- to text grid --", nullptr, 1, nullptr);
2467 		praat_addAction1 (classSound, 0, U"To TextGrid...", nullptr, 1,
2468 				CONVERT_EACH_TO_ONE__Sound_to_TextGrid);
2469 		praat_addAction1 (classSound, 0, U"To TextTier", nullptr, praat_DEPTH_1 | praat_HIDDEN,
2470 				CONVERT_EACH_TO_ONE__Sound_to_TextTier);
2471 		praat_addAction1 (classSound, 0, U"To IntervalTier", nullptr, praat_DEPTH_1 | praat_HIDDEN,
2472 				CONVERT_EACH_TO_ONE__Sound_to_IntervalTier);
2473 	praat_addAction1 (classSound, 0, U"Analyse periodicity -", nullptr, 0, nullptr);
2474 		praat_addAction1 (classSound, 0, U"To Pitch...", nullptr, 1,
2475 				CONVERT_EACH_TO_ONE__Sound_to_Pitch);
2476 		praat_addAction1 (classSound, 0, U"To Pitch (ac)...", nullptr, 1,
2477 				CONVERT_EACH_TO_ONE__Sound_to_Pitch_ac);
2478 		praat_addAction1 (classSound, 0, U"To Pitch (cc)...", nullptr, 1,
2479 				CONVERT_EACH_TO_ONE__Sound_to_Pitch_cc);
2480 		praat_addAction1 (classSound, 0, U"To PointProcess (periodic, cc)...", nullptr, 1,
2481 				CONVERT_EACH_TO_ONE__Sound_to_PointProcess_periodic_cc);
2482 		praat_addAction1 (classSound, 0, U"To PointProcess (periodic, peaks)...", nullptr, 1,
2483 				CONVERT_EACH_TO_ONE__Sound_to_PointProcess_periodic_peaks);
2484 		praat_addAction1 (classSound, 0, U"-- points --", nullptr, 1, nullptr);
2485 		praat_addAction1 (classSound, 0, U"To PointProcess (extrema)...", nullptr, 1,
2486 				CONVERT_EACH_TO_ONE__Sound_to_PointProcess_extrema);
2487 		praat_addAction1 (classSound, 0, U"To PointProcess (zeroes)...", nullptr, 1,
2488 				CONVERT_EACH_TO_ONE__Sound_to_PointProcess_zeroes);
2489 		praat_addAction1 (classSound, 0, U"-- hnr --", nullptr, 1, nullptr);
2490 		praat_addAction1 (classSound, 0, U"To Harmonicity (cc)...", nullptr, 1,
2491 				CONVERT_EACH_TO_ONE__Sound_to_Harmonicity_cc);
2492 		praat_addAction1 (classSound, 0, U"To Harmonicity (ac)...", nullptr, 1,
2493 				CONVERT_EACH_TO_ONE__Sound_to_Harmonicity_ac);
2494 		praat_addAction1 (classSound, 0, U"To Harmonicity (gne)...", nullptr, 1,
2495 				CONVERT_EACH_TO_ONE__Sound_to_Harmonicity_gne);
2496 		praat_addAction1 (classSound, 0, U"-- autocorrelation --", nullptr, 1, nullptr);
2497 		praat_addAction1 (classSound, 0, U"Autocorrelate...", nullptr, 1,
2498 				CONVERT_EACH_TO_ONE__Sound_autoCorrelate);
2499 	praat_addAction1 (classSound, 0, U"Analyse spectrum -", nullptr, 0, nullptr);
2500 		praat_addAction1 (classSound, 0, U"To Spectrum...", nullptr, 1,
2501 				CONVERT_EACH_TO_ONE__Sound_to_Spectrum);
2502 		praat_addAction1 (classSound, 0,   U"To Spectrum (fft)", U"*To Spectrum...", praat_DEPTH_1 | praat_DEPRECATED_2004,
2503 				CONVERT_EACH_TO_ONE__Sound_to_Spectrum_fft);
2504 		praat_addAction1 (classSound, 0,   U"To Spectrum", U"*To Spectrum...", praat_DEPTH_1 | praat_DEPRECATED_2004,
2505 				CONVERT_EACH_TO_ONE__Sound_to_Spectrum_fft);
2506 		praat_addAction1 (classSound, 0,   U"To Spectrum (dft)", U"*To Spectrum...", praat_DEPTH_1 | praat_DEPRECATED_2004,
2507 				CONVERT_EACH_TO_ONE__Sound_to_Spectrum_dft);
2508 		praat_addAction1 (classSound, 0, U"To Ltas...", nullptr, 1,
2509 				CONVERT_EACH_TO_ONE__Sound_to_Ltas);
2510 		praat_addAction1 (classSound, 0, U"To Ltas (pitch-corrected)...", nullptr, 1,
2511 				CONVERT_EACH_TO_ONE__Sound_to_Ltas_pitchCorrected);
2512 		praat_addAction1 (classSound, 0, U"-- spectrotemporal --", nullptr, 1, nullptr);
2513 		praat_addAction1 (classSound, 0, U"To Spectrogram...", nullptr, 1,
2514 				CONVERT_EACH_TO_ONE__Sound_to_Spectrogram);
2515 		praat_addAction1 (classSound, 0, U"To Cochleagram...", nullptr, 1,
2516 				CONVERT_EACH_TO_ONE__Sound_to_Cochleagram);
2517 		praat_addAction1 (classSound, 0, U"To Cochleagram (edb)...", nullptr, praat_DEPTH_1 | praat_HIDDEN,
2518 				CONVERT_EACH_TO_ONE__Sound_to_Cochleagram_edb);
2519 		praat_addAction1 (classSound, 0, U"-- formants --", nullptr, 1, nullptr);
2520 		praat_addAction1 (classSound, 0, U"To Formant (burg)...", nullptr, 1,
2521 				CONVERT_EACH_TO_ONE__Sound_to_Formant_burg);
2522 		praat_addAction1 (classSound, 0, U"To Formant (hack)", nullptr, 1, nullptr);
2523 		praat_addAction1 (classSound, 0, U"To Formant (keep all)...", nullptr, 2,
2524 				CONVERT_EACH_TO_ONE__Sound_to_Formant_keepAll);
2525 		praat_addAction1 (classSound, 0, U"To Formant (sl)...", nullptr, 2,
2526 				CONVERT_EACH_TO_ONE__Sound_to_Formant_willems);
2527 	praat_addAction1 (classSound, 0, U"To Intensity...", nullptr, 0,
2528 			CONVERT_EACH_TO_ONE__Sound_to_Intensity);
2529 	praat_addAction1 (classSound, 0, U"To IntensityTier...", nullptr, praat_HIDDEN,
2530 			CONVERT_EACH_TO_ONE__Sound_to_IntensityTier);
2531 	praat_addAction1 (classSound, 0, U"Manipulate -", nullptr, 0, nullptr);
2532 		praat_addAction1 (classSound, 0, U"To Manipulation...", nullptr, 1,
2533 				CONVERT_EACH_TO_ONE__Sound_to_Manipulation);
2534 	praat_addAction1 (classSound, 0, U"Convert -", nullptr, 0, nullptr);
2535 		praat_addAction1 (classSound, 0, U"Convert to mono", nullptr, 1,
2536 				CONVERT_EACH_TO_ONE__Sound_convertToMono);
2537 		praat_addAction1 (classSound, 0, U"Convert to stereo", nullptr, 1,
2538 				CONVERT_EACH_TO_ONE__Sound_convertToStereo);
2539 		praat_addAction1 (classSound, 0, U"Extract all channels", nullptr, 1,
2540 				CONVERT_ONE_TO_MULTIPLE__Sound_extractAllChannels);
2541 		praat_addAction1 (classSound, 0, U"Extract one channel...", nullptr, 1,
2542 				CONVERT_EACH_TO_ONE__Sound_extractChannel);
2543 		praat_addAction1 (classSound, 0,   U"Extract left channel", U"*Extract one channel...", praat_DEPTH_1 | praat_DEPRECATED_2010,
2544 				CONVERT_EACH_TO_ONE__Sound_extractLeftChannel);
2545 		praat_addAction1 (classSound, 0,   U"Extract right channel", U"*Extract one channel...", praat_DEPTH_1 | praat_DEPRECATED_2010,
2546 				CONVERT_EACH_TO_ONE__Sound_extractRightChannel);
2547 		praat_addAction1 (classSound, 0, U"Extract channels...", nullptr, 1,
2548 				CONVERT_EACH_TO_ONE__Sound_extractChannels);
2549 		praat_addAction1 (classSound, 0, U"Extract part...", nullptr, 1,
2550 				CONVERT_EACH_TO_ONE__Sound_extractPart);
2551 		praat_addAction1 (classSound, 0, U"Extract part for overlap...", nullptr, 1,
2552 				CONVERT_EACH_TO_ONE__Sound_extractPartForOverlap);
2553 		praat_addAction1 (classSound, 0, U"Resample...", nullptr, 1,
2554 				CONVERT_EACH_TO_ONE__Sound_resample);
2555 		praat_addAction1 (classSound, 0, U"-- enhance --", nullptr, 1, nullptr);
2556 		praat_addAction1 (classSound, 0, U"Lengthen (overlap-add)...", nullptr, 1,
2557 				CONVERT_EACH_TO_ONE__Sound_lengthen_overlapAdd);
2558 		praat_addAction1 (classSound, 0,   U"Lengthen (PSOLA)...", U"*Lengthen (overlap-add)...", praat_DEPTH_1 | praat_DEPRECATED_2007,
2559 				CONVERT_EACH_TO_ONE__Sound_lengthen_overlapAdd);
2560 		praat_addAction1 (classSound, 0, U"Deepen band modulation...", nullptr, 1,
2561 				CONVERT_EACH_TO_ONE__Sound_deepenBandModulation);
2562 		praat_addAction1 (classSound, 0, U"-- cast --", nullptr, 1, nullptr);
2563 		praat_addAction1 (classSound, 0, U"Down to Matrix", nullptr, 1,
2564 				CONVERT_EACH_TO_ONE__Sound_downto_Matrix);
2565 	praat_addAction1 (classSound, 0, U"Filter -", nullptr, 0, nullptr);
2566 		praat_addAction1 (classSound, 0, U"Filtering tutorial", nullptr, 1,
2567 				HELP__FilteringTutorial);
2568 		praat_addAction1 (classSound, 0, U"-- frequency-domain filter --", nullptr, 1, nullptr);
2569 		praat_addAction1 (classSound, 0, U"Filter (pass Hann band)...", nullptr, 1,
2570 				CONVERT_EACH_TO_ONE__Sound_filter_passHannBand);
2571 		praat_addAction1 (classSound, 0, U"Filter (stop Hann band)...", nullptr, 1,
2572 				CONVERT_EACH_TO_ONE__Sound_filter_stopHannBand);
2573 		praat_addAction1 (classSound, 0, U"Filter (formula)...", nullptr, 1,
2574 				CONVERT_EACH_TO_ONE__Sound_filter_formula);
2575 		praat_addAction1 (classSound, 0, U"-- time-domain filter --", nullptr, 1, nullptr);
2576 		praat_addAction1 (classSound, 0, U"Filter (one formant)...", nullptr, 1,
2577 				CONVERT_EACH_TO_ONE__Sound_filter_oneFormant);
2578 		praat_addAction1 (classSound, 0, U"Filter (pre-emphasis)...", nullptr, 1,
2579 				CONVERT_EACH_TO_ONE__Sound_filter_preemphasis);
2580 		praat_addAction1 (classSound, 0, U"Filter (de-emphasis)...", nullptr, 1,
2581 				CONVERT_EACH_TO_ONE__Sound_filter_deemphasis);
2582 	praat_addAction1 (classSound, 0, U"Combine -", nullptr, 0, nullptr);
2583 		praat_addAction1 (classSound, 0, U"Combine to stereo", nullptr, 1,
2584 				COMBINE_ALL_TO_ONE__Sounds_combineToStereo);
2585 		praat_addAction1 (classSound, 0, U"Combine into SoundList", nullptr, 1,
2586 				COMBINE_ALL_TO_ONE__Sounds_combineIntoSoundList);
2587 		praat_addAction1 (classSound, 0, U"Combine into SoundSet", nullptr, 1,
2588 				COMBINE_ALL_TO_ONE__Sounds_combineIntoSoundSet);
2589 		praat_addAction1 (classSound, 0, U"Concatenate", nullptr, 1,
2590 				COMBINE_ALL_TO_ONE__Sounds_concatenate);
2591 		praat_addAction1 (classSound, 0, U"Concatenate recoverably", nullptr, 1,
2592 				CONVERT_ALL_TO_MULTIPLE__Sounds_concatenateRecoverably);
2593 		praat_addAction1 (classSound, 0, U"Concatenate with overlap...", nullptr, 1,
2594 				COMBINE_ALL_TO_ONE__Sounds_concatenateWithOverlap);
2595 		praat_addAction1 (classSound, 2, U"Convolve...", nullptr, 1,
2596 				CONVERT_TWO_TO_ONE__Sounds_convolve);
2597 		praat_addAction1 (classSound, 2,   U"Convolve", U"*Convolve...", praat_DEPTH_1 | praat_DEPRECATED_2010,
2598 				CONVERT_TWO_TO_ONE__Sounds_convolve_old);
2599 		praat_addAction1 (classSound, 2, U"Cross-correlate...", nullptr, 1,
2600 				CONVERT_TWO_TO_ONE__Sounds_crossCorrelate);
2601 		praat_addAction1 (classSound, 2, U"To ParamCurve", nullptr, 1,
2602 				CONVERT_TWO_TO_ONE__Sounds_to_ParamCurve);
2603 
2604 	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as WAV file...", nullptr, 0,
2605 			SAVE_ALL__LongSound_Sound_saveAsWavFile);
2606 	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to WAV file...", U"*Save as WAV file...", praat_DEPRECATED_2011,
2607 			SAVE_ALL__LongSound_Sound_saveAsWavFile);
2608 	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as AIFF file...", nullptr, 0,
2609 			SAVE_ALL__LongSound_Sound_saveAsAiffFile);
2610 	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to AIFF file...", U"*Save as AIFF file...", praat_DEPRECATED_2011,
2611 			SAVE_ALL__LongSound_Sound_saveAsAiffFile);
2612 	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as AIFC file...", nullptr, 0,
2613 			SAVE_ALL__LongSound_Sound_saveAsAifcFile);
2614 	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to AIFC file...", U"*Save as AIFC file...", praat_DEPRECATED_2011,
2615 			SAVE_ALL__LongSound_Sound_saveAsAifcFile);
2616 	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as NeXT/Sun file...", nullptr, 0,
2617 			SAVE_ALL__LongSound_Sound_saveAsNextSunFile);
2618 	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to NeXT/Sun file...", U"*Save as NeXT/Sun file...", praat_DEPRECATED_2011,
2619 			SAVE_ALL__LongSound_Sound_saveAsNextSunFile);
2620 	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as NIST file...", nullptr, 0,
2621 			SAVE_ALL__LongSound_Sound_saveAsNistFile);
2622 	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to NIST file...", U"*Save as NIST file...", praat_DEPRECATED_2011,
2623 			SAVE_ALL__LongSound_Sound_saveAsNistFile);
2624 	praat_addAction2 (classLongSound, 0, classSound, 0, U"Save as FLAC file...", nullptr, 0,
2625 			SAVE_ALL__LongSound_Sound_saveAsFlacFile);
2626 	praat_addAction2 (classLongSound, 0, classSound, 0,   U"Write to FLAC file...", U"*Save as FLAC file...", praat_DEPRECATED_2011,
2627 			SAVE_ALL__LongSound_Sound_saveAsFlacFile);
2628 
2629 	praat_addAction1 (classSoundList, 1, U"Extract all Sounds", nullptr, 0,
2630 			CONVERT_EACH_TO_MULTIPLE__SoundList_extractAllSounds);
2631 
2632 	praat_addAction1 (classSoundSet, 1, U"Extract all Sounds", nullptr, 0,
2633 			CONVERT_EACH_TO_MULTIPLE__SoundSet_extractAllSounds);
2634 	praat_addAction2 (classSoundSet, 1, classTable, 1, U"Get randomized patterns...", nullptr, 0,
2635 			CONVERT_ONE_AND_ONE_TO_MULTIPLE__SoundSet_Table_getRandomizedPatterns);
2636 }
2637 
2638 /* End of file praat_Sound.cpp */
2639