void praat_addAction4 (ClassInfo class1, int n1, ClassInfo class2, int n2, ClassInfo class3, int n3, ClassInfo class4, int n4,
	const char32 *title, const char32 *after, unsigned long flags, UiCallback callback)
{
	try {
		int depth = flags, key = 0;
		bool unhidable = false, hidden = false, attractive = false;
		unsigned long motifFlags = 0;
		if (flags > 7) {
			depth = ((flags & praat_DEPTH_7) >> 16);
			unhidable = (flags & praat_UNHIDABLE) != 0;
			hidden = (flags & praat_HIDDEN) != 0 && ! unhidable;
			key = flags & 0x000000FF;
			motifFlags = key ? flags & (0x002000FF | GuiMenu_BUTTON_STATE_MASK) : flags & GuiMenu_BUTTON_STATE_MASK;
			attractive = (motifFlags & praat_ATTRACTIVE) != 0;
		}
		fixSelectionSpecification (& class1, & n1, & class2, & n2, & class3, & n3);

		if (callback && ! title)
			Melder_throw (U"An action command with callback has no title. Classes: ",
				class1 ? class1 -> className : U"", U" ",
				class2 ? class2 -> className : U"", U" ",
				class3 ? class3 -> className : U"", U" ",
				class4 ? class4 -> className : U"", U".");

		if (! class1)
			Melder_throw (U"The action command \"", title, U"\" has no first class.");

		/*
		 * Determine the position of the new command.
		 */
		long position;
		if (after) {   // search for existing command with same selection
			long found = lookUpMatchingAction (class1, class2, class3, class4, after);
			if (found == 0)
				Melder_throw (U"The action command \"", title, U"\" cannot be put after \"", after, U"\",\n"
					U"because the latter command does not exist.");
			position = found + 1;   // after 'after'
		} else {
			position = theActions -> size + 1;   // at end
		}

		/*
		 * Make new command.
		 */
		autoPraat_Command action = Thing_new (Praat_Command);
		action -> class1 = class1;
		action -> n1 = n1;
		action -> class2 = class2;
		action -> n2 = n2;
		action -> class3 = class3;
		action -> n3 = n3;
		action -> class4 = class4;
		action -> n4 = n4;
		action -> title = Melder_dup_f (title);
		action -> depth = depth;
		action -> callback = callback;   // null for a separator
		action -> button = nullptr;
		action -> script = nullptr;
		action -> hidden = hidden;
		action -> unhidable = unhidable;
		action -> attractive = attractive;

		/*
		 * Insert new command.
		 */
		Ordered_addItemAtPosition_move (theActions, action.move(), position);
	} catch (MelderError) {
Beispiel #2
0
void Data_writeText (Daata me, MelderFile openFile) {
	my v_writeText (openFile);
	if (ferror (openFile -> filePointer))
		Melder_throw (U"I/O error.");
}
Beispiel #3
0
Sound Sound_recordFixedTime (int inputSource, double gain, double balance, double sampleRate, double duration) {
	bool inputUsesPortAudio = MelderAudio_getInputUsesPortAudio ();
	PaStream *portaudioStream = NULL;
	#if defined (macintosh)
	#elif defined (_WIN32)
		HWAVEIN hWaveIn = 0;
	#else
		int fd = -1;   /* Other systems use stream I/O with a file descriptor. */
		int fd_mixer = -1;
	#endif
	try {
		long numberOfSamples, i;
		int mulaw = FALSE;
		int can16bit = TRUE;
		int fakeMonoByStereo = FALSE;   /* Will be set to TRUE for systems (like MacOS X) that do not allow direct mono recording. */

		/* Declare system-dependent data structures. */

		static bool paInitialized = false;
		volatile struct Sound_recordFixedTime_Info info = { 0 };
		PaStreamParameters streamParameters = { 0 };
		#if defined (macintosh)
			(void) gain;
			(void) balance;
		#elif defined (_WIN32)
			WAVEFORMATEX waveFormat;
			WAVEHDR waveHeader;
			MMRESULT err;
			(void) inputSource;
			(void) gain;
			(void) balance;
		#elif defined (linux)
			#define min(a,b) a > b ? b : a
			int dev_mask;
			int fd_mixer = -1;
			int val;
		#endif

		/* Check representation of shorts. */

		if (sizeof (short) != 2)
			Melder_throw (U"Cannot record a sound on this computer.");

		/* Check sampling frequency. */

		bool supportsSamplingFrequency = true;
		if (inputUsesPortAudio) {
			#if defined (macintosh)
				if (sampleRate != 44100 && sampleRate != 48000 && sampleRate != 96000) supportsSamplingFrequency = false;
			#endif
		} else {
			#if defined (macintosh)
				if (sampleRate != 44100) supportsSamplingFrequency = false;
			#elif defined (linux)
				if (sampleRate != 8000 && sampleRate != 11025 &&
						sampleRate != 16000 && sampleRate != 22050 &&
						sampleRate != 32000 && sampleRate != 44100 &&
						sampleRate != 48000) supportsSamplingFrequency = false;
			#elif defined (_WIN32)
				if (sampleRate != 8000 && sampleRate != 11025 &&
						sampleRate != 16000 && sampleRate != 22050 &&
						sampleRate != 32000 && sampleRate != 44100 &&
						sampleRate != 48000 && sampleRate != 96000) supportsSamplingFrequency = false;
			#endif
		}
		if (! supportsSamplingFrequency)
			Melder_throw (U"Your audio hardware does not support a sampling frequency of ", sampleRate, U" Hz.");

		/*
		 * Open phase 1.
		 * On some systems, the info is filled in before the audio port is opened.
		 * On other systems, the info is filled in after the port is opened.
		 */
		if (inputUsesPortAudio) {
			if (! paInitialized) {
				PaError err = Pa_Initialize ();
				if (err)
					Melder_throw (U"Pa_Initialize: ", Melder_peek8to32 (Pa_GetErrorText (err)));
				paInitialized = true;
			}
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
			#else
				/* We must open the port now, because we use an ioctl to set the info to an open port. */
				fd = open (DEV_AUDIO, O_RDONLY);
				if (fd == -1) {
					if (errno == EBUSY)
						Melder_throw (U"Audio device in use by another program.");
					else
						#ifdef linux
							Melder_throw (U"Cannot open audio device.\nPlease switch on PortAudio in the Sound Recording Preferences.");
						#else
							Melder_throw (U"Cannot open audio device.");
						#endif
				}
				/* The device immediately started recording into its buffer, but probably at the wrong rate etc. */
				/* Pause and flush this rubbish. */
				#if defined (linux)
					ioctl (fd, SNDCTL_DSP_RESET, NULL);
				#endif
			#endif
		}

		/* Set the input source; the default is the microphone. */

		if (inputUsesPortAudio) {
			if (inputSource < 1 || inputSource > Pa_GetDeviceCount ())
				Melder_throw (U"Unknown device #", inputSource, U".");
			streamParameters. device = inputSource - 1;
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				fd_mixer = open ("/dev/mixer", O_WRONLY);		
				if (fd_mixer == -1)
					Melder_throw (U"Cannot open /dev/mixer.");
				dev_mask = inputSource == 1 ? SOUND_MASK_MIC : SOUND_MASK_LINE;
				if (ioctl (fd_mixer, SOUND_MIXER_WRITE_RECSRC, & dev_mask) == -1)
					Melder_throw (U"Cannot set recording device in mixer");
			#endif
		}

		/* Set gain and balance. */

		if (inputUsesPortAudio) {
			/* Taken from Audio Control Panel. */
		} else {
			#if defined (macintosh) || defined (_WIN32)
				/* Taken from Audio Control Panel. */
			#elif defined (linux)
				val = (gain <= 0.0 ? 0 : gain >= 1.0 ? 100 : floor (gain * 100 + 0.5));  
				balance = balance <= 0 ? 0 : balance >= 1 ? 1 : balance;
				if (balance >= 0.5) {
					val = (int)(((int)(val*balance/(1-balance)) << 8) | val);
				} else {
					val = (int)(val | ((int)(val*(1-balance)/balance) << 8));
				}
				val = (int)((min(2-2*balance,1))*val) | ((int)((min(2*balance,1))*val) << 8);
				if (inputSource == 1) {			
					/* MIC */		       
					if (ioctl (fd_mixer, MIXER_WRITE (SOUND_MIXER_MIC), & val) == -1)
						Melder_throw (U"Cannot set gain and balance.");
				} else {
					/* LINE */
					if (ioctl (fd_mixer, MIXER_WRITE (SOUND_MIXER_LINE), & val) == -1)
						Melder_throw (U"Cannot set gain and balance.");
				}
				close (fd_mixer);
				fd_mixer = -1;
			#endif
		}

		/* Set the sampling frequency. */

		if (inputUsesPortAudio) {
			// Set while opening.
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				int sampleRate_int = (int) sampleRate;
				if (ioctl (fd, SNDCTL_DSP_SPEED, & sampleRate_int) == -1)
					Melder_throw (U"Cannot set sampling frequency to ", sampleRate, U" Hz.");
			#elif defined (_WIN32)
				waveFormat. nSamplesPerSec = sampleRate;
			#endif
		}

		/* Set the number of channels to 1 (mono), if possible. */

		if (inputUsesPortAudio) {
			streamParameters. channelCount = 1;
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				val = 1;
				if (ioctl (fd, SNDCTL_DSP_CHANNELS, & val) == -1)
					Melder_throw (U"Cannot set to mono.");
			#elif defined (_WIN32)
				waveFormat. nChannels = 1;
			#endif
		}

		/* Set the encoding to 16-bit linear (or to 8-bit linear, if 16-bit is not available). */

		if (inputUsesPortAudio) {
			streamParameters. sampleFormat = paInt16;
		} else {
			#if defined (macintosh)
			#elif defined (linux)
				#if __BYTE_ORDER == __BIG_ENDIAN
					val = AFMT_S16_BE;
				#else
					val = AFMT_S16_LE;
				#endif
				if (ioctl (fd, SNDCTL_DSP_SETFMT, & val) == -1)
					Melder_throw (U"Cannot set 16-bit linear.");
			#elif defined (_WIN32)
				waveFormat. wFormatTag = WAVE_FORMAT_PCM;
				waveFormat. wBitsPerSample = 16;
				waveFormat. nBlockAlign = waveFormat. nChannels * waveFormat. wBitsPerSample / 8;
				waveFormat. nAvgBytesPerSec = waveFormat. nBlockAlign * waveFormat. nSamplesPerSec;
			#endif
		}

		/* Create a buffer for recording, and the resulting sound. */

		numberOfSamples = lround (sampleRate * duration);
		if (numberOfSamples < 1)
			Melder_throw (U"Duration too short.");
		autoNUMvector <short> buffer (1, numberOfSamples * (fakeMonoByStereo ? 2 : 1));
		autoSound me = Sound_createSimple (1, numberOfSamples / sampleRate, sampleRate);   // STEREO BUG
		Melder_assert (my nx == numberOfSamples);

		/*
		 * Open phase 2.
		 * This starts recording now.
		 */

		if (inputUsesPortAudio) {
			streamParameters. suggestedLatency = Pa_GetDeviceInfo (inputSource - 1) -> defaultLowInputLatency;
			#if defined (macintosh)
				PaMacCoreStreamInfo macCoreStreamInfo = { 0 };
				macCoreStreamInfo. size = sizeof (PaMacCoreStreamInfo);
				macCoreStreamInfo. hostApiType = paCoreAudio;
				macCoreStreamInfo. version = 0x01;
				macCoreStreamInfo. flags = paMacCoreChangeDeviceParameters | paMacCoreFailIfConversionRequired;
				streamParameters. hostApiSpecificStreamInfo = & macCoreStreamInfo;
			#endif
			info. numberOfSamples = numberOfSamples;
			info. numberOfSamplesRead = 0;
			info. buffer = buffer.peek();
			PaError err = Pa_OpenStream (& portaudioStream, & streamParameters, NULL,
				sampleRate, 0, paNoFlag, portaudioStreamCallback, (void *) & info);
			if (err)
				Melder_throw (U"open ", Melder_peek8to32 (Pa_GetErrorText (err)));
			Pa_StartStream (portaudioStream);
			if (err)
				Melder_throw (U"start ", Melder_peek8to32 (Pa_GetErrorText (err)));
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				waveFormat. cbSize = 0;
				err = waveInOpen (& hWaveIn, WAVE_MAPPER, & waveFormat, 0, 0, CALLBACK_NULL);
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while opening.");
			#endif
		}
for (i = 1; i <= numberOfSamples; i ++) trace (U"Started ", buffer [i]);

		/* Read the sound into the buffer. */

		if (inputUsesPortAudio) {
			// The callback will do this. Just wait.
			while (/*getNumberOfSamplesRead (& info)*/ info. numberOfSamplesRead < numberOfSamples) {
				//Pa_Sleep (1);
				//Melder_casual ("filled %ld/%ld", getNumberOfSamplesRead (& info), numberOfSamples);
			}
for (i = 1; i <= numberOfSamples; i ++) trace (U"Recorded ", buffer [i]);
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				waveHeader. dwFlags = 0;
				waveHeader. lpData = (char *) & buffer [1];
				waveHeader. dwBufferLength = numberOfSamples * 2;
				waveHeader. dwLoops = 0;
				waveHeader. lpNext = NULL;
				waveHeader. reserved = 0;
				err = waveInPrepareHeader (hWaveIn, & waveHeader, sizeof (WAVEHDR));
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while preparing header.");
				err = waveInAddBuffer (hWaveIn, & waveHeader, sizeof (WAVEHDR));
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while listening.");
				err = waveInStart (hWaveIn);
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while starting.");
					while (! (waveHeader. dwFlags & WHDR_DONE)) { Pa_Sleep (1); }
				err = waveInUnprepareHeader (hWaveIn, & waveHeader, sizeof (WAVEHDR));
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while unpreparing header.");
			#else
				if (mulaw)
					read (fd, (char *) & buffer [1], numberOfSamples);
				else {
					long bytesLeft = 2 * numberOfSamples, dbytes, bytesRead = 0;
					while (bytesLeft) {
						//Melder_casual ("Reading %ld bytes", bytesLeft > 4000 ? 4000 : bytesLeft);
						dbytes = read (fd, & ((char *) buffer.peek()) [2 + bytesRead], bytesLeft > 4000 ? 4000 : bytesLeft);
						//Melder_casual("Read %ld bytes", dbytes);
						if (dbytes <= 0) break;
						bytesLeft -= dbytes;
						bytesRead += dbytes;
					};
				}
			#endif
		}

		/* Copy the buffered data to the sound object, and discard the buffer. */

		if (fakeMonoByStereo)
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = ((long) buffer [i + i - 1] + buffer [i + i]) * (1.0 / 65536);
		else if (mulaw)
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = ulaw2linear [((unsigned char *) buffer.peek()) [i]] * (1.0 / 32768);
		else if (can16bit)
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = buffer [i] * (1.0 / 32768);
		else
			for (i = 1; i <= numberOfSamples; i ++)
				my z [1] [i] = ((int) ((unsigned char *) buffer.peek()) [i + 1] - 128) * (1.0 / 128);

		/* Close the audio device. */

		if (inputUsesPortAudio) {
			Pa_StopStream (portaudioStream);
			Pa_CloseStream (portaudioStream);
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				err = waveInClose (hWaveIn);
				if (err != MMSYSERR_NOERROR)
					Melder_throw (U"Error ", err, U" while closing.");
			#else
				close (fd);
			#endif
		}

		/* Hand the resulting sound to the caller. */

		return me.transfer();
	} catch (MelderError) {
		if (inputUsesPortAudio) {
			if (portaudioStream) Pa_StopStream (portaudioStream);
			if (portaudioStream) Pa_CloseStream (portaudioStream);
		} else {
			#if defined (macintosh)
			#elif defined (_WIN32)
				if (hWaveIn != 0) waveInClose (hWaveIn);
			#else
				if (fd_mixer != -1) close (fd_mixer);
				if (fd != -1) close (fd);
			#endif
		}
		Melder_throw (U"Sound not recorded.");
	}
}
static void Diagonalizer_and_CrossCorrelationTable_qdiag (Diagonalizer me, CrossCorrelationTables thee, double *cweights, long maxNumberOfIterations, double delta) {
	try {
		CrossCorrelationTable c0 = (CrossCorrelationTable) thy item[1];
		double **w = my data;
		long dimension = c0 -> numberOfColumns;

		autoEigen eigen = Thing_new (Eigen);
		autoCrossCorrelationTables ccts = Data_copy (thee);
		autoNUMmatrix<double> pinv (1, dimension, 1, dimension);
		autoNUMmatrix<double> d (1, dimension, 1, dimension);
		autoNUMmatrix<double> p (1, dimension, 1, dimension);
		autoNUMmatrix<double> m1 (1, dimension, 1, dimension);
		autoNUMmatrix<double> wc (1, dimension, 1, dimension);
		autoNUMvector<double> wvec (1, dimension);
		autoNUMvector<double> wnew (1, dimension);
		autoNUMvector<double> mvec (1, dimension);

		for (long i = 1; i <= dimension; i++) // Transpose W
			for (long j = 1; j <= dimension; j++) {
				wc[i][j] = w[j][i];
			}

		// d = diag(diag(W'*C0*W));
		// W = W*d^(-1/2);

		NUMdmatrix_normalizeColumnVectors (wc.peek(), dimension, dimension, c0 -> data);

		// scale eigenvectors for sphering
		// [vb,db] = eig(C0);
		// P = db^(-1/2)*vb';

		Eigen_initFromSymmetricMatrix (eigen.peek(), c0 -> data, dimension);
		for (long i = 1; i <= dimension; i++) {
			if (eigen -> eigenvalues[i] < 0) {
				Melder_throw ("Covariance matrix not positive definite, eigenvalue[", Melder_integer(i), "] is negative.");
			}
			double scalef = 1 / sqrt (eigen -> eigenvalues[i]);
			for (long j = 1; j <= dimension; j++) {
				p[dimension - i + 1][j] = scalef * eigen -> eigenvectors[i][j];
			}
		}

		// P*C[i]*P'

		for (long ic = 1; ic <= thy size; ic++) {
			CrossCorrelationTable cov1 = (CrossCorrelationTable) thy item[ic];
			CrossCorrelationTable cov2 = (CrossCorrelationTable) ccts -> item[ic];
			NUMdmatrices_multiply_VCVp (cov2 -> data, p.peek(), dimension, dimension, cov1 -> data, 1);
		}

		// W = P'\W == inv(P') * W

		NUMpseudoInverse (p.peek(), dimension, dimension, pinv.peek(), 0);

		NUMdmatrices_multiply_VpC (w, pinv.peek(), dimension, dimension, wc.peek(), dimension);

		// initialisation for order KN^3

		for (long ic = 2; ic <= thy size; ic++) {
			CrossCorrelationTable cov = (CrossCorrelationTable) ccts -> item[ic];
			// C * W
			NUMdmatrices_multiply_VC (m1.peek(), cov -> data, dimension, dimension, w, dimension);
			// D += scalef * M1*M1'
			NUMdmatrices_multiplyScaleAdd (d.peek(), m1.peek(), dimension, dimension, 2 * cweights[ic]);
		}

		long iter = 0;
		double delta_w;

		autoMelderProgress progress (L"Simultaneous diagonalization of many CrossCorrelationTables...");
		try {
			do {
				// the standard diagonality measure is rather expensive to calculate so we compare the norms of
				// differences of eigenvectors.

				delta_w = 0;
				for (long kol = 1; kol <= dimension; kol++) {
					for (long i = 1; i <= dimension; i++) {
						wvec[i] = w[i][kol];
					}

					update_one_column (ccts.peek(), d.peek(), cweights, wvec.peek(), -1, mvec.peek());

					Eigen_initFromSymmetricMatrix (eigen.peek(), d.peek(), dimension);

					// Eigenvalues already sorted; get eigenvector of smallest !

					for (long i = 1; i <= dimension; i++) {
						wnew[i] = eigen -> eigenvectors[dimension][i];
					}

					update_one_column (ccts.peek(), d.peek(), cweights, wnew.peek(), 1, mvec.peek());
					for (long i = 1; i <= dimension; i++) {
						w[i][kol] = wnew[i];
					}

					// compare norms of eigenvectors. We have to compare ||wvec +/- w_new|| because eigenvectors
					//  may change sign.

					double normp = 0, normm = 0;
					for (long j = 1; j <= dimension; j++) {
						double dm = wvec[j] - wnew[j], dp = wvec[j] + wnew[j];
						normp += dm * dm; normm += dp * dp;
					}

					normp = normp < normm ? normp : normm;
					normp = sqrt (normp);
					delta_w = normp > delta_w ? normp : delta_w;
				}
				iter++;

				Melder_progress ((double) iter / (double) (maxNumberOfIterations + 1), L"Iteration: ", Melder_integer (iter), L", norm: ",
					Melder_double (delta_w));
			} while (delta_w > delta && iter < maxNumberOfIterations);
		} catch (MelderError) {
			Melder_clearError ();
		}

		// Revert the sphering W = P'*W;
		// Take transpose to make W*C[i]W' diagonal instead of W'*C[i]*W => (P'*W)'=W'*P

		NUMmatrix_copyElements (w, wc.peek(), 1, dimension, 1, dimension);
		NUMdmatrices_multiply_VpC (w, wc.peek(), dimension, dimension, p.peek(), dimension); // W = W'*P: final result

		// Calculate the "real" diagonality measure
	//	double dm = CrossCorrelationTables_and_Diagonalizer_getDiagonalityMeasure (thee, me, cweights, 1, thy size);

	} catch (MelderError) {
		Melder_throw (me, " & ", thee, ": no joint diagonalization (qdiag).");
	}
}
TextGrid TextGrid_readFromTIMITLabelFile (MelderFile file, int phnFile) {
	try {
		double dt = 1.0 / 16000; /* 1 / (TIMIT samplingFrequency) */
		double xmax = dt;
		autofile f = Melder_fopen (file, "r");

		// Ending time will only be known after all labels have been read.
		// We start with a sufficiently long duration (one hour) and correct this later.

		autoTextGrid me = TextGrid_create (0, 3600, L"wrd", 0);
		IntervalTier timit = (IntervalTier) my tiers -> item[1];
		long linesRead = 0;
		char line[200], label[200];
		while (fgets (line, 199, f)) {
			long it1, it2;
			linesRead++;
			if (sscanf (line, "%ld%ld%s", &it1, &it2, label) != 3) {
				Melder_throw ("Incorrect number of items.");
			}
			if (it1 < 0 || it2 <= it1) {
				Melder_throw (L"Incorrect time at line ", linesRead);
			}
			xmax = it2 * dt;
			double xmin = it1 * dt;
			long ni = timit -> intervals -> size - 1;
			if (ni < 1) {
				ni = 1;
				// Some files do not start with a first line "0 <number2> h#".
				// Instead they start with "<number1> <number2> h#", where number1 > 0.
				// We override number1 with 0. */

				if (xmin > 0 && phnFile) {
					xmin = 0;
				}
			}
			TextInterval interval = (TextInterval) timit -> intervals -> item[ni];
			if (xmin < interval -> xmax && linesRead > 1) {
				xmin = interval -> xmax;
				Melder_warning (L"File \"", MelderFile_messageName (file), L"\": Start time set to previous end "
				                 "time for label at line ", Melder_integer (linesRead), L".");
			}
			// standard: new TextInterval
			const char *labelstring = (strncmp (label, "h#", 2) ? label : TIMIT_DELIMITER);
			IntervalTier_add (timit, xmin, xmax, Melder_peekUtf8ToWcs (labelstring));
		}

		// Now correct the end times, based on last read interval.
		// (end time was set to large value!)

		if (timit -> intervals -> size < 2) {
			Melder_throw ("Empty TextGrid");
		}
		Collection_removeItem (timit -> intervals, timit -> intervals -> size);
		TextInterval interval = (TextInterval) timit -> intervals -> item[timit -> intervals -> size];
		timit -> xmax = interval -> xmax;
		my xmax = xmax;
		if (phnFile) { // Create tier 2 with IPA symbols
			autoIntervalTier ipa = Data_copy (timit);
			Thing_setName (ipa.peek(), L"ipa");
			// First change the data in ipa
			for (long i = 1; i <= ipa -> intervals -> size; i++) {
				interval = (TextInterval) timit -> intervals -> item[i];

				TextInterval_setText ( (TextInterval) ipa -> intervals -> item[i],
				                       Melder_peekUtf8ToWcs (timitLabelToIpaLabel (Melder_peekWcsToUtf8 (interval -> text))));
			}
			Collection_addItem (my tiers, ipa.transfer()); // Then: add to collection
			Thing_setName (timit, L"phn");  // rename wrd
		}
		f.close (file);
		return me.transfer();
	} catch (MelderError) {
		Melder_throw ("TextGrid not read from file ", file, ".");
	}
}
void LongSounds_appendToExistingSoundFile (Collection me, MelderFile file) {
	long pre_append_endpos = 0, numberOfBitsPerSamplePoint = 16;
	try {
		if (my size < 1) {
			Melder_throw (U"No Sound or LongSound objects to append.");
		}

		/*
			We have to open with "r+" mode because this will position the stream
			at the beginning of the file. The "a" mode does not allow us to
			seek before the end-of-file.

			For Linux: If the file is already opened (e.g. by a LongSound) object we
			should deny access!
			Under Windows deny access is default?!
		*/

		autofile f = Melder_fopen (file, "r+b");
		file -> filePointer = f; // essential !!
		double sampleRate_d;
		long startOfData;
		int32 numberOfSamples;
		int numberOfChannels, encoding;
		int audioFileType = MelderFile_checkSoundFile (file, &numberOfChannels,
		                    &encoding, &sampleRate_d, &startOfData, &numberOfSamples);

		if (audioFileType == 0) {
			Melder_throw (U"Not a sound file.");
		}

		// Check whether all the sample rates and channels match.

		long sampleRate = (long) floor (sampleRate_d);
		for (long i = 1; i <= my size; i++) {
			int sampleRatesMatch, numbersOfChannelsMatch;
			Sampled data = (Sampled) my item [i];
			if (data -> classInfo == classSound) {
				Sound sound = (Sound) data;
				sampleRatesMatch = floor (1.0 / sound -> dx + 0.5) == sampleRate;
				numbersOfChannelsMatch = sound -> ny == numberOfChannels;
				numberOfSamples += sound -> nx;
			} else {
				LongSound longSound = (LongSound) data;
				sampleRatesMatch = longSound -> sampleRate == sampleRate;
				numbersOfChannelsMatch = longSound -> numberOfChannels == numberOfChannels;
				numberOfSamples += longSound -> nx;
			}
			if (! sampleRatesMatch) {
				Melder_throw (U"Sample rates do not match.");
			}
			if (! numbersOfChannelsMatch) {
				Melder_throw (U"Cannot mix stereo and mono.");
			}
		}

		// Search the end of the file, count the number of bytes and append.

		MelderFile_seek (file, 0, SEEK_END);

		pre_append_endpos = MelderFile_tell (file);

		errno = 0;
		for (long i = 1; i <= my size; i++) {
			Sampled data = (Sampled) my item [i];
			if (data -> classInfo == classSound) {
				Sound sound = (Sound) data;
				MelderFile_writeFloatToAudio (file, sound -> ny, Melder_defaultAudioFileEncoding
				    (audioFileType, numberOfBitsPerSamplePoint), sound -> z, sound -> nx, true);
			} else {
				LongSound longSound = (LongSound) data;
				writePartToOpenFile16 (longSound, audioFileType, 1, longSound -> nx, file);
			}
			if (errno != 0) {
				Melder_throw (U"Error during writing.");
			}
		}

		// Update header

		MelderFile_rewind (file);
		MelderFile_writeAudioFileHeader (file, audioFileType, sampleRate, numberOfSamples, numberOfChannels, numberOfBitsPerSamplePoint);
		MelderFile_writeAudioFileTrailer (file, audioFileType, sampleRate, numberOfSamples, numberOfChannels, numberOfBitsPerSamplePoint);
		f.close (file);
		return;
	} catch (MelderError) {
		if (errno != 0 && pre_append_endpos > 0) {
			// Restore file at original size
			int error = errno;
			MelderFile_truncate (file, pre_append_endpos);
			Melder_throw (U"File ", MelderFile_messageName (file), U" restored to original size (", Melder_peek8to32 (strerror (error)), U").");
		} throw;
	}
}
Beispiel #7
0
autoEEG EEG_readFromBdfFile (MelderFile file) {
	try {
		autofile f = Melder_fopen (file, "rb");
		char buffer [81];
		fread (buffer, 1, 8, f); buffer [8] = '\0';
		bool is24bit = buffer [0] == (char) 255;
		fread (buffer, 1, 80, f); buffer [80] = '\0';
		trace (U"Local subject identification: \"", Melder_peek8to32 (buffer), U"\"");
		fread (buffer, 1, 80, f); buffer [80] = '\0';
		trace (U"Local recording identification: \"", Melder_peek8to32 (buffer), U"\"");
		fread (buffer, 1, 8, f); buffer [8] = '\0';
		trace (U"Start date of recording: \"", Melder_peek8to32 (buffer), U"\"");
		fread (buffer, 1, 8, f); buffer [8] = '\0';
		trace (U"Start time of recording: \"", Melder_peek8to32 (buffer), U"\"");
		fread (buffer, 1, 8, f); buffer [8] = '\0';
		long numberOfBytesInHeaderRecord = atol (buffer);
		trace (U"Number of bytes in header record: ", numberOfBytesInHeaderRecord);
		fread (buffer, 1, 44, f); buffer [44] = '\0';
		trace (U"Version of data format: \"", Melder_peek8to32 (buffer), U"\"");
		fread (buffer, 1, 8, f); buffer [8] = '\0';
		long numberOfDataRecords = strtol (buffer, nullptr, 10);
		trace (U"Number of data records: ", numberOfDataRecords);
		fread (buffer, 1, 8, f); buffer [8] = '\0';
		double durationOfDataRecord = atof (buffer);
		trace (U"Duration of a data record: ", durationOfDataRecord);
		fread (buffer, 1, 4, f); buffer [4] = '\0';
		long numberOfChannels = atol (buffer);
		trace (U"Number of channels in data record: ", numberOfChannels);
		if (numberOfBytesInHeaderRecord != (numberOfChannels + 1) * 256)
			Melder_throw (U"Number of bytes in header record (", numberOfBytesInHeaderRecord,
				U") doesn't match number of channels (", numberOfChannels, U").");
		autostring32vector channelNames (1, numberOfChannels);
		for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			fread (buffer, 1, 16, f); buffer [16] = '\0';   // labels of the channels
			/*
			 * Strip all final spaces.
			 */
			for (int i = 15; i >= 0; i --) {
				if (buffer [i] == ' ') {
					buffer [i] = '\0';
				} else {
					break;
				}
			}
			channelNames [ichannel] = Melder_8to32 (buffer);
			trace (U"Channel <<", channelNames [ichannel], U">>");
		}
		bool hasLetters = str32equ (channelNames [numberOfChannels], U"EDF Annotations");
		double samplingFrequency = NUMundefined;
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			fread (buffer, 1, 80, f); buffer [80] = '\0';   // transducer type
		}
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			fread (buffer, 1, 8, f); buffer [8] = '\0';   // physical dimension of channels
		}
		autoNUMvector <double> physicalMinimum (1, numberOfChannels);
		for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			fread (buffer, 1, 8, f); buffer [8] = '\0';
			physicalMinimum [ichannel] = atof (buffer);
		}
		autoNUMvector <double> physicalMaximum (1, numberOfChannels);
		for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			fread (buffer, 1, 8, f); buffer [8] = '\0';
			physicalMaximum [ichannel] = atof (buffer);
		}
		autoNUMvector <double> digitalMinimum (1, numberOfChannels);
		for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			fread (buffer, 1, 8, f); buffer [8] = '\0';
			digitalMinimum [ichannel] = atof (buffer);
		}
		autoNUMvector <double> digitalMaximum (1, numberOfChannels);
		for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			fread (buffer, 1, 8, f); buffer [8] = '\0';
			digitalMaximum [ichannel] = atof (buffer);
		}
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			fread (buffer, 1, 80, f); buffer [80] = '\0';   // prefiltering
		}
		long numberOfSamplesPerDataRecord = 0;
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			fread (buffer, 1, 8, f); buffer [8] = '\0';   // number of samples in each data record
			long numberOfSamplesInThisDataRecord = atol (buffer);
			if (samplingFrequency == NUMundefined) {
				numberOfSamplesPerDataRecord = numberOfSamplesInThisDataRecord;
				samplingFrequency = numberOfSamplesInThisDataRecord / durationOfDataRecord;
			}
			if (numberOfSamplesInThisDataRecord / durationOfDataRecord != samplingFrequency)
				Melder_throw (U"Number of samples per data record in channel ", channel,
					U" (", numberOfSamplesInThisDataRecord,
					U") doesn't match sampling frequency of channel 1 (", samplingFrequency, U").");
		}
		for (long channel = 1; channel <= numberOfChannels; channel ++) {
			fread (buffer, 1, 32, f); buffer [32] = '\0';   // reserved
		}
		double duration = numberOfDataRecords * durationOfDataRecord;
		autoEEG him = EEG_create (0, duration);
		his numberOfChannels = numberOfChannels;
		autoSound me = Sound_createSimple (numberOfChannels, duration, samplingFrequency);
		Melder_assert (my nx == numberOfSamplesPerDataRecord * numberOfDataRecords);
		autoNUMvector <unsigned char> dataBuffer (0L, 3 * numberOfSamplesPerDataRecord - 1);
		for (long record = 1; record <= numberOfDataRecords; record ++) {
			for (long channel = 1; channel <= numberOfChannels; channel ++) {
				double factor = channel == numberOfChannels ? 1.0 : physicalMinimum [channel] / digitalMinimum [channel];
				if (channel < numberOfChannels - EEG_getNumberOfExtraSensors (him.peek())) factor /= 1000000.0;
				if (is24bit) {
					fread (& dataBuffer [0], 3, numberOfSamplesPerDataRecord, f);
					unsigned char *p = & dataBuffer [0];
					for (long i = 1; i <= numberOfSamplesPerDataRecord; i ++) {
						long sample = i + (record - 1) * numberOfSamplesPerDataRecord;
						Melder_assert (sample <= my nx);
						uint8_t lowByte = *p ++, midByte = *p ++, highByte = *p ++;
						uint32_t externalValue = ((uint32_t) highByte << 16) | ((uint32_t) midByte << 8) | (uint32_t) lowByte;
						if ((highByte & 128) != 0)   // is the 24-bit sign bit on?
							externalValue |= 0xFF000000;   // extend negative sign to 32 bits
						my z [channel] [sample] = (int32_t) externalValue * factor;
					}
				} else {
					fread (& dataBuffer [0], 2, numberOfSamplesPerDataRecord, f);
					unsigned char *p = & dataBuffer [0];
					for (long i = 1; i <= numberOfSamplesPerDataRecord; i ++) {
						long sample = i + (record - 1) * numberOfSamplesPerDataRecord;
						Melder_assert (sample <= my nx);
						uint8 lowByte = *p ++, highByte = *p ++;
						uint16 externalValue = (uint16) ((uint16) highByte << 8) | (uint16) lowByte;
						my z [channel] [sample] = (int16) externalValue * factor;
					}
				}
			}
		}
		int numberOfStatusBits = 8;
		for (long i = 1; i <= my nx; i ++) {
			unsigned long value = (long) my z [numberOfChannels] [i];
			if (value & 0x0000FF00) {
				numberOfStatusBits = 16;
			}
		}
		autoTextGrid thee;
		if (hasLetters) {
			thee = TextGrid_create (0, duration, U"Mark Trigger", U"Mark Trigger");
			autoMelderString letters;
			double time = NUMundefined;
			for (long i = 1; i <= my nx; i ++) {
				unsigned long value = (long) my z [numberOfChannels] [i];
				for (int byte = 1; byte <= numberOfStatusBits / 8; byte ++) {
					unsigned long mask = byte == 1 ? 0x000000ff : 0x0000ff00;
					char32 kar = byte == 1 ? (value & mask) : (value & mask) >> 8;
					if (kar != U'\0' && kar != 20) {
						MelderString_appendCharacter (& letters, kar);
					} else if (letters. string [0] != U'\0') {
						if (letters. string [0] == U'+') {
							if (NUMdefined (time)) {
								try {
									TextGrid_insertPoint (thee.peek(), 1, time, U"");
								} catch (MelderError) {
									Melder_throw (U"Did not insert empty mark (", letters. string, U") on Mark tier.");
								}
								time = NUMundefined;   // defensive
							}
							time = Melder_atof (& letters. string [1]);
							MelderString_empty (& letters);
						} else {
							if (! NUMdefined (time)) {
								Melder_throw (U"Undefined time for label at sample ", i, U".");
							}
							try {
								if (Melder_nequ (letters. string, U"Trigger-", 8)) {
									try {
										TextGrid_insertPoint (thee.peek(), 2, time, & letters. string [8]);
									} catch (MelderError) {
										Melder_clearError ();
										trace (U"Duplicate trigger at ", time, U" seconds: ", & letters. string [8]);
									}
								} else {
									TextGrid_insertPoint (thee.peek(), 1, time, & letters. string [0]);
								}
							} catch (MelderError) {
								Melder_throw (U"Did not insert mark (", letters. string, U") on Trigger tier.");
							}
							time = NUMundefined;   // crucial
							MelderString_empty (& letters);
						}
					}
				}
			}
			if (NUMdefined (time)) {
				TextGrid_insertPoint (thee.peek(), 1, time, U"");
				time = NUMundefined;   // defensive
			}
		} else {
			thee = TextGrid_create (0, duration,
				numberOfStatusBits == 8 ? U"S1 S2 S3 S4 S5 S6 S7 S8" : U"S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12 S13 S14 S15 S16", U"");
			for (int bit = 1; bit <= numberOfStatusBits; bit ++) {
				unsigned long bitValue = 1 << (bit - 1);
				IntervalTier tier = (IntervalTier) thy tiers -> item [bit];
				for (long i = 1; i <= my nx; i ++) {
					unsigned long previousValue = i == 1 ? 0 : (long) my z [numberOfChannels] [i - 1];
					unsigned long thisValue = (long) my z [numberOfChannels] [i];
					if ((thisValue & bitValue) != (previousValue & bitValue)) {
						double time = i == 1 ? 0.0 : my x1 + (i - 1.5) * my dx;
						if (time != 0.0)
							TextGrid_insertBoundary (thee.peek(), bit, time);
						if ((thisValue & bitValue) != 0)
							TextGrid_setIntervalText (thee.peek(), bit, tier -> intervals -> size, U"1");
					}
				}
			}
		}
		f.close (file);
		his channelNames = channelNames.transfer();
		his sound = me.move();
		his textgrid = thee.move();
		if (EEG_getNumberOfCapElectrodes (him.peek()) == 32) {
			EEG_setChannelName (him.peek(), 1, U"Fp1");
			EEG_setChannelName (him.peek(), 2, U"AF3");
			EEG_setChannelName (him.peek(), 3, U"F7");
			EEG_setChannelName (him.peek(), 4, U"F3");
			EEG_setChannelName (him.peek(), 5, U"FC1");
			EEG_setChannelName (him.peek(), 6, U"FC5");
			EEG_setChannelName (him.peek(), 7, U"T7");
			EEG_setChannelName (him.peek(), 8, U"C3");
			EEG_setChannelName (him.peek(), 9, U"CP1");
			EEG_setChannelName (him.peek(), 10, U"CP5");
			EEG_setChannelName (him.peek(), 11, U"P7");
			EEG_setChannelName (him.peek(), 12, U"P3");
			EEG_setChannelName (him.peek(), 13, U"Pz");
			EEG_setChannelName (him.peek(), 14, U"PO3");
			EEG_setChannelName (him.peek(), 15, U"O1");
			EEG_setChannelName (him.peek(), 16, U"Oz");
			EEG_setChannelName (him.peek(), 17, U"O2");
			EEG_setChannelName (him.peek(), 18, U"PO4");
			EEG_setChannelName (him.peek(), 19, U"P4");
			EEG_setChannelName (him.peek(), 20, U"P8");
			EEG_setChannelName (him.peek(), 21, U"CP6");
			EEG_setChannelName (him.peek(), 22, U"CP2");
			EEG_setChannelName (him.peek(), 23, U"C4");
			EEG_setChannelName (him.peek(), 24, U"T8");
			EEG_setChannelName (him.peek(), 25, U"FC6");
			EEG_setChannelName (him.peek(), 26, U"FC2");
			EEG_setChannelName (him.peek(), 27, U"F4");
			EEG_setChannelName (him.peek(), 28, U"F8");
			EEG_setChannelName (him.peek(), 29, U"AF4");
			EEG_setChannelName (him.peek(), 30, U"Fp2");
			EEG_setChannelName (him.peek(), 31, U"Fz");
			EEG_setChannelName (him.peek(), 32, U"Cz");
		} else if (EEG_getNumberOfCapElectrodes (him.peek()) == 64) {
			EEG_setChannelName (him.peek(), 1, U"Fp1");
			EEG_setChannelName (him.peek(), 2, U"AF7");
			EEG_setChannelName (him.peek(), 3, U"AF3");
			EEG_setChannelName (him.peek(), 4, U"F1");
			EEG_setChannelName (him.peek(), 5, U"F3");
			EEG_setChannelName (him.peek(), 6, U"F5");
			EEG_setChannelName (him.peek(), 7, U"F7");
			EEG_setChannelName (him.peek(), 8, U"FT7");
			EEG_setChannelName (him.peek(), 9, U"FC5");
			EEG_setChannelName (him.peek(), 10, U"FC3");
			EEG_setChannelName (him.peek(), 11, U"FC1");
			EEG_setChannelName (him.peek(), 12, U"C1");
			EEG_setChannelName (him.peek(), 13, U"C3");
			EEG_setChannelName (him.peek(), 14, U"C5");
			EEG_setChannelName (him.peek(), 15, U"T7");
			EEG_setChannelName (him.peek(), 16, U"TP7");
			EEG_setChannelName (him.peek(), 17, U"CP5");
			EEG_setChannelName (him.peek(), 18, U"CP3");
			EEG_setChannelName (him.peek(), 19, U"CP1");
			EEG_setChannelName (him.peek(), 20, U"P1");
			EEG_setChannelName (him.peek(), 21, U"P3");
			EEG_setChannelName (him.peek(), 22, U"P5");
			EEG_setChannelName (him.peek(), 23, U"P7");
			EEG_setChannelName (him.peek(), 24, U"P9");
			EEG_setChannelName (him.peek(), 25, U"PO7");
			EEG_setChannelName (him.peek(), 26, U"PO3");
			EEG_setChannelName (him.peek(), 27, U"O1");
			EEG_setChannelName (him.peek(), 28, U"Iz");
			EEG_setChannelName (him.peek(), 29, U"Oz");
			EEG_setChannelName (him.peek(), 30, U"POz");
			EEG_setChannelName (him.peek(), 31, U"Pz");
			EEG_setChannelName (him.peek(), 32, U"CPz");
			EEG_setChannelName (him.peek(), 33, U"Fpz");
			EEG_setChannelName (him.peek(), 34, U"Fp2");
			EEG_setChannelName (him.peek(), 35, U"AF8");
			EEG_setChannelName (him.peek(), 36, U"AF4");
			EEG_setChannelName (him.peek(), 37, U"AFz");
			EEG_setChannelName (him.peek(), 38, U"Fz");
			EEG_setChannelName (him.peek(), 39, U"F2");
			EEG_setChannelName (him.peek(), 40, U"F4");
			EEG_setChannelName (him.peek(), 41, U"F6");
			EEG_setChannelName (him.peek(), 42, U"F8");
			EEG_setChannelName (him.peek(), 43, U"FT8");
			EEG_setChannelName (him.peek(), 44, U"FC6");
			EEG_setChannelName (him.peek(), 45, U"FC4");
			EEG_setChannelName (him.peek(), 46, U"FC2");
			EEG_setChannelName (him.peek(), 47, U"FCz");
			EEG_setChannelName (him.peek(), 48, U"Cz");
			EEG_setChannelName (him.peek(), 49, U"C2");
			EEG_setChannelName (him.peek(), 50, U"C4");
			EEG_setChannelName (him.peek(), 51, U"C6");
			EEG_setChannelName (him.peek(), 52, U"T8");
			EEG_setChannelName (him.peek(), 53, U"TP8");
			EEG_setChannelName (him.peek(), 54, U"CP6");
			EEG_setChannelName (him.peek(), 55, U"CP4");
			EEG_setChannelName (him.peek(), 56, U"CP2");
			EEG_setChannelName (him.peek(), 57, U"P2");
			EEG_setChannelName (him.peek(), 58, U"P4");
			EEG_setChannelName (him.peek(), 59, U"P6");
			EEG_setChannelName (him.peek(), 60, U"P8");
			EEG_setChannelName (him.peek(), 61, U"P10");
			EEG_setChannelName (him.peek(), 62, U"PO8");
			EEG_setChannelName (him.peek(), 63, U"PO4");
			EEG_setChannelName (him.peek(), 64, U"O2");
		}
		return him;
	} catch (MelderError) {
Beispiel #8
0
void NUMlinprog_run (NUMlinprog me) {
	try {
		glp_smcp parm;
		glp_init_smcp (& parm);
		parm. msg_lev = GLP_MSG_OFF;
		my status = glp_simplex (my linearProgram, & parm);
		switch (my status) {
			case GLP_EBADB: Melder_throw (U"Unable to start the search, because the initial basis is invalid.");
			case GLP_ESING: Melder_throw (U"Unable to start the search, because the basis matrix is singular.");
			case GLP_ECOND: Melder_throw (U"Unable to start the search, because the basis matrix is ill-conditioned.");
			case GLP_EBOUND: Melder_throw (U"Unable to start the search, because some variables have incorrect bounds.");
			case GLP_EFAIL: Melder_throw (U"Search prematurely terminated due to solver failure.");
			case GLP_EOBJLL: Melder_throw (U"Search prematurely terminated: lower limit reached.");
			case GLP_EOBJUL: Melder_throw (U"Search prematurely terminated: upper limit reached.");
			case GLP_EITLIM: Melder_throw (U"Search prematurely terminated: iteration limit exceeded.");
			case GLP_ETMLIM: Melder_throw (U"Search prematurely terminated: time limit exceeded.");
			case GLP_ENOPFS: Melder_throw (U"The problem has no primal feasible solution.");
			case GLP_ENODFS: Melder_throw (U"The problem has no dual feasible solution.");
			default: break;
		}
		my status = glp_get_status (my linearProgram);
		switch (my status) {
			case GLP_INFEAS: Melder_throw (U"Solution is infeasible.");
			case GLP_NOFEAS: Melder_throw (U"Problem has no feasible solution.");
			case GLP_UNBND: Melder_throw (U"Problem has unbounded solution.");
			case GLP_UNDEF: Melder_throw (U"Solution is undefined.");
			default: break;
		}
		if (my status == GLP_FEAS) {
			Melder_warning (U"Linear programming solution is feasible but not optimal.");
		}
	} catch (MelderError) {
		Melder_throw (U"Linear programming: not run.");
	}
}
Beispiel #9
0
static Intensity Sound_to_Intensity_ (Sound me, double minimumPitch, double timeStep, int subtractMeanPressure) {
	try {
		/*
		 * Preconditions.
		 */
		if (! NUMdefined (minimumPitch)) Melder_throw ("(Sound-to-Intensity:) Minimum pitch undefined.");
		if (! NUMdefined (timeStep)) Melder_throw ("(Sound-to-Intensity:) Time step undefined.");
		if (timeStep < 0.0) Melder_throw ("(Sound-to-Intensity:) Time step should be zero or positive instead of ", timeStep, ".");
		if (my dx <= 0.0) Melder_throw ("(Sound-to-Intensity:) The Sound's time step should be positive.");
		if (minimumPitch <= 0.0) Melder_throw ("(Sound-to-Intensity:) Minimum pitch should be positive.");
		/*
		 * Defaults.
		 */
		if (timeStep == 0.0) timeStep = 0.8 / minimumPitch;   // default: four times oversampling Hanning-wise

		double windowDuration = 6.4 / minimumPitch;
		Melder_assert (windowDuration > 0.0);
		double halfWindowDuration = 0.5 * windowDuration;
		long halfWindowSamples = halfWindowDuration / my dx;
		autoNUMvector <double> amplitude (- halfWindowSamples, halfWindowSamples);
		autoNUMvector <double> window (- halfWindowSamples, halfWindowSamples);

		for (long i = - halfWindowSamples; i <= halfWindowSamples; i ++) {
			double x = i * my dx / halfWindowDuration, root = 1 - x * x;
			window [i] = root <= 0.0 ? 0.0 : NUMbessel_i0_f ((2 * NUMpi * NUMpi + 0.5) * sqrt (root));
		}

		long numberOfFrames;
		double thyFirstTime;
		try {
			Sampled_shortTermAnalysis (me, windowDuration, timeStep, & numberOfFrames, & thyFirstTime);
		} catch (MelderError) {
			Melder_throw ("The duration of the sound in an intensity analysis should be at least 6.4 divided by the minimum pitch (", minimumPitch, " Hz), "
				"i.e. at least ", 6.4 / minimumPitch, " s, instead of ", my xmax - my xmin, " s.");
		}
		autoIntensity thee = Intensity_create (my xmin, my xmax, numberOfFrames, timeStep, thyFirstTime);
		for (long iframe = 1; iframe <= numberOfFrames; iframe ++) {
			double midTime = Sampled_indexToX (thee.peek(), iframe);
			long midSample = Sampled_xToNearestIndex (me, midTime);
			long leftSample = midSample - halfWindowSamples, rightSample = midSample + halfWindowSamples;
			double sumxw = 0.0, sumw = 0.0, intensity;
			if (leftSample < 1) leftSample = 1;
			if (rightSample > my nx) rightSample = my nx;

			for (long channel = 1; channel <= my ny; channel ++) {
				for (long i = leftSample; i <= rightSample; i ++) {
					amplitude [i - midSample] = my z [channel] [i];
				}
				if (subtractMeanPressure) {
					double sum = 0.0;
					for (long i = leftSample; i <= rightSample; i ++) {
						sum += amplitude [i - midSample];
					}
					double mean = sum / (rightSample - leftSample + 1);
					for (long i = leftSample; i <= rightSample; i ++) {
						amplitude [i - midSample] -= mean;
					}
				}
				for (long i = leftSample; i <= rightSample; i ++) {
					sumxw += amplitude [i - midSample] * amplitude [i - midSample] * window [i - midSample];
					sumw += window [i - midSample];
				}
			}
			intensity = sumxw / sumw;
			if (intensity != 0.0) intensity /= 4e-10;
			thy z [1] [iframe] = intensity < 1e-30 ? -300 : 10 * log10 (intensity);
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, ": intensity analysis not performed.");
	}
}
autoSpectrum Sound_to_Spectrum (Sound me, int fast) {
	try {
		long numberOfSamples = my nx;
		const long numberOfChannels = my ny;
		if (fast) {
			numberOfSamples = 2;
			while (numberOfSamples < my nx) numberOfSamples *= 2;
		}
		long numberOfFrequencies = numberOfSamples / 2 + 1;   // 4 samples -> cos0 cos1 sin1 cos2; 5 samples -> cos0 cos1 sin1 cos2 sin2

		autoNUMvector <double> data (1, numberOfSamples);
		if (numberOfChannels == 1) {
			const double *channel = my z [1];
			for (long i = 1; i <= my nx; i ++) {
				data [i] = channel [i];
			}
			/*
				All samples from `my nx + 1` through `numberOfSamples`
				should be set to zero, but they are already zero.
			*/
			// so do nothing
		} else {
			for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
				const double *channel = my z [ichan];
				for (long i = 1; i <= my nx; i ++) {
					data [i] += channel [i];
				}
			}
			for (long i = 1; i <= my nx; i ++) {
				data [i] /= numberOfChannels;
			}
		}

		autoNUMfft_Table fourierTable;
		NUMfft_Table_init (& fourierTable, numberOfSamples);
		NUMfft_forward (& fourierTable, data.peek());

		autoSpectrum thee = Spectrum_create (0.5 / my dx, numberOfFrequencies);
		thy dx = 1.0 / (my dx * numberOfSamples);   // override
		double *re = thy z [1];
		double *im = thy z [2];
		double scaling = my dx;
		re [1] = data [1] * scaling;
		im [1] = 0.0;
		for (long i = 2; i < numberOfFrequencies; i ++) {
			re [i] = data [i + i - 2] * scaling;   // data [2], data [4], ...
			im [i] = data [i + i - 1] * scaling;   // data [3], data [5], ...
		}
		if ((numberOfSamples & 1) != 0) {
			if (numberOfSamples > 1) {
				re [numberOfFrequencies] = data [numberOfSamples - 1] * scaling;
				im [numberOfFrequencies] = data [numberOfSamples] * scaling;
			}
		} else {
			re [numberOfFrequencies] = data [numberOfSamples] * scaling;
			im [numberOfFrequencies] = 0.0;
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": not converted to Spectrum.");
	}
}
Beispiel #11
0
Ltas PointProcess_Sound_to_Ltas (PointProcess pulses, Sound sound,
	double maximumFrequency, double bandWidth,
	double shortestPeriod, double longestPeriod, double maximumPeriodFactor)
{
	try {
		long numberOfPeriods = pulses -> nt - 2, totalNumberOfEnergies = 0;
		autoLtas ltas = Ltas_create (maximumFrequency / bandWidth, bandWidth);
		ltas -> xmax = maximumFrequency;
		autoLtas numbers = Data_copy (ltas.peek());
		if (numberOfPeriods < 1)
			Melder_throw ("Cannot compute an Ltas if there are no periods in the point process.");
		autoMelderProgress progress (L"Ltas analysis...");
		for (long ipulse = 2; ipulse < pulses -> nt; ipulse ++) {
			double leftInterval = pulses -> t [ipulse] - pulses -> t [ipulse - 1];
			double rightInterval = pulses -> t [ipulse + 1] - pulses -> t [ipulse];
			double intervalFactor = leftInterval > rightInterval ? leftInterval / rightInterval : rightInterval / leftInterval;
			Melder_progress ((double) ipulse / pulses -> nt, L"Sound & PointProcess: To Ltas: pulse ", Melder_integer (ipulse), L" out of ", Melder_integer (pulses -> nt));
			if (leftInterval >= shortestPeriod && leftInterval <= longestPeriod &&
				rightInterval >= shortestPeriod && rightInterval <= longestPeriod &&
				intervalFactor <= maximumPeriodFactor)
			{
				/*
				 * We have a period! Compute the spectrum.
				 */
				autoSound period = Sound_extractPart (sound,
					pulses -> t [ipulse] - 0.5 * leftInterval, pulses -> t [ipulse] + 0.5 * rightInterval,
					kSound_windowShape_RECTANGULAR, 1.0, FALSE);
				autoSpectrum spectrum = Sound_to_Spectrum (period.peek(), FALSE);
				for (long ifreq = 1; ifreq <= spectrum -> nx; ifreq ++) {
					double frequency = spectrum -> xmin + (ifreq - 1) * spectrum -> dx;
					double realPart = spectrum -> z [1] [ifreq];
					double imaginaryPart = spectrum -> z [2] [ifreq];
					double energy = (realPart * realPart + imaginaryPart * imaginaryPart) * 2.0 * spectrum -> dx /* OLD: * sound -> nx */;
					long iband = ceil (frequency / bandWidth);
					if (iband >= 1 && iband <= ltas -> nx) {
						ltas -> z [1] [iband] += energy;
						numbers -> z [1] [iband] += 1;
						totalNumberOfEnergies += 1;
					}
				}
			} else {
				numberOfPeriods -= 1;
			}
		}
		if (numberOfPeriods < 1)
			Melder_throw ("There are no periods in the point process.");
		for (long iband = 1; iband <= ltas -> nx; iband ++) {
			if (numbers -> z [1] [iband] == 0.0) {
				ltas -> z [1] [iband] = NUMundefined;
			} else {
				/*
				 * Each bin now contains a total energy in Pa2 sec.
				 * To convert this to power density, we
				 */
				double totalEnergyInThisBand = ltas -> z [1] [iband];
				if (0 /* i.e. if you just want to have a spectrum of the voiced parts... */) {
					double energyDensityInThisBand = totalEnergyInThisBand / ltas -> dx;
					double powerDensityInThisBand = energyDensityInThisBand / (sound -> xmax - sound -> xmin);
					ltas -> z [1] [iband] = 10.0 * log10 (powerDensityInThisBand / 4.0e-10);
				} else {
					/*
					 * And this is what we really want. The total energy has to be redistributed.
					 */
					double meanEnergyInThisBand = totalEnergyInThisBand / numbers -> z [1] [iband];
					double meanNumberOfEnergiesPerBand = (double) totalNumberOfEnergies / ltas -> nx;
					double redistributedEnergyInThisBand = meanEnergyInThisBand * meanNumberOfEnergiesPerBand;
					double redistributedEnergyDensityInThisBand = redistributedEnergyInThisBand / ltas -> dx;
					double redistributedPowerDensityInThisBand = redistributedEnergyDensityInThisBand / (sound -> xmax - sound -> xmin);
					ltas -> z [1] [iband] = 10.0 * log10 (redistributedPowerDensityInThisBand / 4.0e-10);
					/* OLD: ltas -> z [1] [iband] = 10.0 * log10 (ltas -> z [1] [iband] / numbers -> z [1] [iband] * sound -> nx);*/
				}
			}
		}
		for (long iband = 1; iband <= ltas -> nx; iband ++) {
			if (ltas -> z [1] [iband] == NUMundefined) {
				long ibandleft = iband - 1, ibandright = iband + 1;
				while (ibandleft >= 1 && ltas -> z [1] [ibandleft] == NUMundefined) ibandleft --;
				while (ibandright <= ltas -> nx && ltas -> z [1] [ibandright] == NUMundefined) ibandright ++;
				if (ibandleft < 1 && ibandright > ltas -> nx)
					Melder_throw ("Cannot create an Ltas without energy in any bins.");
				if (ibandleft < 1) {
					ltas -> z [1] [iband] = ltas -> z [1] [ibandright];
				} else if (ibandright > ltas -> nx) {
					ltas -> z [1] [iband] = ltas -> z [1] [ibandleft];
				} else {
					double frequency = ltas -> x1 + (iband - 1) * ltas -> dx;
					double fleft = ltas -> x1 + (ibandleft - 1) * ltas -> dx;
					double fright = ltas -> x1 + (ibandright - 1) * ltas -> dx;
					ltas -> z [1] [iband] = ((fright - frequency) * ltas -> z [1] [ibandleft]
						+ (frequency - fleft) * ltas -> z [1] [ibandright]) / (fright - fleft);
				}
			}
		}
		return ltas.transfer();
	} catch (MelderError) {
		Melder_throw (sound, " & ", pulses, ": LTAS analysis not performed.");
	}
}
FeatureWeights FeatureWeights_computeWrapperExt
(
    ///////////////////////////////
    // Parameters                //
    ///////////////////////////////

    KNN nn,         // Classifier
                    //
    Pattern pp,     // test pattern
                    //
    Categories c,   // test categories
                    //
    long k,         // k(!)
                    //
    int d,          // distance weighting
                    //
    long nseeds,    // the number of seeds
                    //
    double alfa,    // shrinkage factor
                    //
    double stop,    // stop at
                    //
    int mode        // mode (co/serial)
                    //
)

{
	if (! nn) return nullptr;

	try {
		double pivot = 0.5;
		double range = 0.5;
		autoNUMvector <double> results (0L, nseeds);

		autoThingVector <FeatureWeights> cs (0L, nseeds);
		for (long y = 0; y <= nseeds; y++) {
			cs [y] = FeatureWeights_create (pp -> nx);
		}

		for (long x = 1; x <= pp -> nx; x ++)
			cs [nseeds] -> fweights -> data [1] [x] = pivot;

		results [nseeds] = FeatureWeights_evaluate (cs [nseeds], nn, pp, c, k, d);

		while (range > 0 && results [nseeds] < stop)
		{
			long best = nseeds;

			if (mode == 2)
			{
				for (long x = 1; x <= pp->nx; x++)
				{
					for (long y = 0; y < nseeds; y++)
					{
						cs[y]->fweights->data[1][x] = NUMrandomUniform(OlaMAX(0, cs[nseeds]->fweights->data[1][x] - range),
													  OlaMIN(1, cs[nseeds]->fweights->data[1][x] + range));
						results[y] = FeatureWeights_evaluate(cs[y], nn, pp, c, k, d);
					}
					for (long q = 0; q < nseeds; q++)
						if (results[q] > results[best]) best = q;

					if (results[best] > results[nseeds])
					{
						for (long x = 1; x <= pp->nx; x++)
							cs[nseeds]->fweights->data[1][x] = cs[best]->fweights->data[1][x];
						results[nseeds] = results[best];
					}
				}
			}
			else
			{
				for (long y = 0; y < nseeds; y++)
				{
					for (long x = 1; x <= pp->nx; x++)
					{
						cs[y]->fweights->data[1][x] = NUMrandomUniform(OlaMAX(0, cs[nseeds]->fweights->data[1][x] - range),
													  OlaMIN(1, cs[nseeds]->fweights->data[1][x] + range));
					}
					results[y] = FeatureWeights_evaluate (cs [y], nn, pp, c, k, d);
				}

				for (long q = 0; q < nseeds; q++)
					if (results[q] > results[best]) best = q;

				if (results[best] > results[nseeds])
				{
					for (long x = 1; x <= pp->nx; x++)
						cs[nseeds]->fweights->data[1][x] = cs[best]->fweights->data[1][x];
					results[nseeds] = results[best];
				}
			}
			range -= alfa;
		}

		FeatureWeights result = cs [nseeds];
		cs [nseeds] = nullptr;   // prevent destruction
		return result;
	} catch (MelderError) {
		Melder_throw (U"FeatureWeights: wrapper not computed.");
	}
}
Beispiel #13
0
autoSound ComplexSpectrogram_to_Sound (ComplexSpectrogram me, double stretchFactor) {
	try {
		/* original number of samples is odd: imaginary part of last spectral value is zero -> 
		 * phase is either zero or +/-pi
		 */
		double pi = atan2 (0.0, - 0.5);
		double samplingFrequency = 2.0 * my ymax;
		double lastFrequency = my y1 + (my ny - 1) * my dy, lastPhase = my phase[my ny][1];
		int originalNumberOfSamplesProbablyOdd = (lastPhase != 0.0 && lastPhase != pi && lastPhase != -pi) || 
			my ymax - lastFrequency > 0.25 * my dx;
		if (my y1 != 0.0) {
			Melder_throw (U"A Fourier-transformable ComplexSpectrogram must have a first frequency of 0 Hz, not ", my y1, U" Hz.");
		}
		long nsamp_window = 2 * my ny - (originalNumberOfSamplesProbablyOdd ? 1 : 2 );
		long halfnsamp_window = nsamp_window / 2;
		double synthesisWindowDuration = nsamp_window / samplingFrequency;
		autoSpectrum spectrum = Spectrum_create (my ymax, my ny);
		autoSound synthesisWindow = Sound_createSimple (1, synthesisWindowDuration, samplingFrequency);
		double newDuration = (my xmax - my xmin) * stretchFactor;
		autoSound thee = Sound_createSimple (1, newDuration, samplingFrequency); //TODO
		double thyStartTime;
		for (long iframe = 1; iframe <= my nx; iframe++) {
			// "original" sound :
			double tmid = Sampled_indexToX (me, iframe);
			long leftSample = Sampled_xToLowIndex (thee.get(), tmid);
			long rightSample = leftSample + 1;
			long startSample = rightSample - halfnsamp_window;
			double startTime = Sampled_indexToX (thee.get(), startSample);
			if (iframe == 1) {
				thyStartTime = Sampled_indexToX (thee.get(), startSample);
			}
			//long endSample = leftSample + halfnsamp_window;
			// New Sound with stretch
			long thyStartSample = Sampled_xToLowIndex (thee.get(),thyStartTime);
			double thyEndTime = thyStartTime + my dx * stretchFactor;
			long thyEndSample = Sampled_xToLowIndex (thee.get(), thyEndTime);
			long stretchedStepSizeSamples = thyEndSample - thyStartSample + 1;
			//double extraTime = (thyStartSample - startSample + 1) * thy dx;
			double extraTime = (thyStartTime - startTime);
			spectrum -> z[1][1] = sqrt (my z[1][iframe]);
			for (long ifreq = 2; ifreq <= my ny; ifreq++) {
				double f = my y1 + (ifreq - 1) * my dy;
				double a = sqrt (my z[ifreq][iframe]);
				double phi = my phase[ifreq][iframe], intPart;
				double extraPhase = 2.0 * pi * modf (extraTime * f, &intPart); // fractional part
				phi += extraPhase;
				spectrum -> z[1][ifreq] = a * cos (phi);
				spectrum -> z[2][ifreq] = a * sin (phi);
			}

			autoSound synthesis = Spectrum_to_Sound (spectrum.get());

			// Where should the sound be placed?

			long thyEndSampleP = (long) floor (fmin (thyStartSample + synthesis -> nx - 1, thyStartSample + stretchedStepSizeSamples - 1)); // guard against extreme stretches
			if (iframe == my nx) {
				thyEndSampleP = (long) floor (fmin (thy nx, thyStartSample + synthesis -> nx - 1));   // ppgb: waarom naar beneden afgerond?
			}
			for (long j = thyStartSample; j <= thyEndSampleP; j++) {
				thy z[1][j] = synthesis -> z[1][j - thyStartSample + 1];
			}
			thyStartTime += my dx * stretchFactor;
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": no Sound created.");
	}
}
Beispiel #14
0
autoSound Sound_Point_Pitch_Duration_to_Sound (Sound me, PointProcess pulses,
	PitchTier pitch, DurationTier duration, double maxT)
{
	try {
		long ipointleft, ipointright;
		double deltat = 0, handledTime = my xmin;
		double startOfSourceNoise, endOfSourceNoise, startOfTargetNoise, endOfTargetNoise;
		double durationOfSourceNoise, durationOfTargetNoise;
		double startOfSourceVoice, endOfSourceVoice, startOfTargetVoice, endOfTargetVoice;
		double durationOfSourceVoice, durationOfTargetVoice;
		double startingPeriod, finishingPeriod, ttarget, voicelessPeriod;
		if (duration -> points.size == 0)
			Melder_throw (U"No duration points.");

		/*
		 * Create a Sound long enough to hold the longest possible duration-manipulated sound.
		 */
		autoSound thee = Sound_create (1, my xmin, my xmin + 3 * (my xmax - my xmin), 3 * my nx, my dx, my x1);

		/*
		 * Below, I'll abbreviate the voiced interval as "voice" and the voiceless interval as "noise".
		 */
		if (pitch && pitch -> points.size) for (ipointleft = 1; ipointleft <= pulses -> nt; ipointleft = ipointright + 1) {
			/*
			 * Find the beginning of the voice.
			 */
			startOfSourceVoice = pulses -> t [ipointleft];   /* The first pulse of the voice. */
			startingPeriod = 1.0 / RealTier_getValueAtTime (pitch, startOfSourceVoice);
			startOfSourceVoice -= 0.5 * startingPeriod;   /* The first pulse is in the middle of a period. */

			/*
			 * Measure one noise.
			 */
			startOfSourceNoise = handledTime;
			endOfSourceNoise = startOfSourceVoice;
			durationOfSourceNoise = endOfSourceNoise - startOfSourceNoise;
			startOfTargetNoise = startOfSourceNoise + deltat;
			endOfTargetNoise = startOfTargetNoise + RealTier_getArea (duration, startOfSourceNoise, endOfSourceNoise);
			durationOfTargetNoise = endOfTargetNoise - startOfTargetNoise;

			/*
			 * Copy the noise.
			 */
			voicelessPeriod = NUMrandomUniform (0.008, 0.012);
			ttarget = startOfTargetNoise + 0.5 * voicelessPeriod;
			while (ttarget < endOfTargetNoise) {
				double tsource;
				double tleft = startOfSourceNoise, tright = endOfSourceNoise;
				int i;
				for (i = 1; i <= 15; i ++) {
					double tsourcemid = 0.5 * (tleft + tright);
					double ttargetmid = startOfTargetNoise + RealTier_getArea (duration,
						startOfSourceNoise, tsourcemid);
					if (ttargetmid < ttarget) tleft = tsourcemid; else tright = tsourcemid;
				}
				tsource = 0.5 * (tleft + tright);
				copyBell (me, tsource, voicelessPeriod, voicelessPeriod, thee.peek(), ttarget);
				voicelessPeriod = NUMrandomUniform (0.008, 0.012);
				ttarget += voicelessPeriod;
			}
			deltat += durationOfTargetNoise - durationOfSourceNoise;

			/*
			 * Find the end of the voice.
			 */
			for (ipointright = ipointleft + 1; ipointright <= pulses -> nt; ipointright ++)
				if (pulses -> t [ipointright] - pulses -> t [ipointright - 1] > maxT)
					break;
			ipointright --;
			endOfSourceVoice = pulses -> t [ipointright];   /* The last pulse of the voice. */
			finishingPeriod = 1.0 / RealTier_getValueAtTime (pitch, endOfSourceVoice);
			endOfSourceVoice += 0.5 * finishingPeriod;   /* The last pulse is in the middle of a period. */
			/*
			 * Measure one voice.
			 */
			durationOfSourceVoice = endOfSourceVoice - startOfSourceVoice;

			/*
			 * This will be copied to an interval with a different location and duration.
			 */
			startOfTargetVoice = startOfSourceVoice + deltat;
			endOfTargetVoice = startOfTargetVoice +
				RealTier_getArea (duration, startOfSourceVoice, endOfSourceVoice);
			durationOfTargetVoice = endOfTargetVoice - startOfTargetVoice;

			/*
			 * Copy the voiced part.
			 */
			ttarget = startOfTargetVoice + 0.5 * startingPeriod;
			while (ttarget < endOfTargetVoice) {
				double tsource, period;
				long isourcepulse;
				double tleft = startOfSourceVoice, tright = endOfSourceVoice;
				int i;
				for (i = 1; i <= 15; i ++) {
					double tsourcemid = 0.5 * (tleft + tright);
					double ttargetmid = startOfTargetVoice + RealTier_getArea (duration,
						startOfSourceVoice, tsourcemid);
					if (ttargetmid < ttarget) tleft = tsourcemid; else tright = tsourcemid;
				}
				tsource = 0.5 * (tleft + tright);
				period = 1.0 / RealTier_getValueAtTime (pitch, tsource);
				isourcepulse = PointProcess_getNearestIndex (pulses, tsource);
				copyBell2 (me, pulses, isourcepulse, period, period, thee.peek(), ttarget, maxT);
				ttarget += period;
			}
			deltat += durationOfTargetVoice - durationOfSourceVoice;
			handledTime = endOfSourceVoice;
		}

		/*
		 * Copy the remaining unvoiced part, if we are at the end.
		 */
		startOfSourceNoise = handledTime;
		endOfSourceNoise = my xmax;
		durationOfSourceNoise = endOfSourceNoise - startOfSourceNoise;
		startOfTargetNoise = startOfSourceNoise + deltat;
		endOfTargetNoise = startOfTargetNoise + RealTier_getArea (duration, startOfSourceNoise, endOfSourceNoise);
		durationOfTargetNoise = endOfTargetNoise - startOfTargetNoise;
		voicelessPeriod = NUMrandomUniform (0.008, 0.012);
		ttarget = startOfTargetNoise + 0.5 * voicelessPeriod;
		while (ttarget < endOfTargetNoise) {
			double tsource;
			double tleft = startOfSourceNoise, tright = endOfSourceNoise;
			for (int i = 1; i <= 15; i ++) {
				double tsourcemid = 0.5 * (tleft + tright);
				double ttargetmid = startOfTargetNoise + RealTier_getArea (duration,
					startOfSourceNoise, tsourcemid);
				if (ttargetmid < ttarget) tleft = tsourcemid; else tright = tsourcemid;
			}
			tsource = 0.5 * (tleft + tright);
			copyBell (me, tsource, voicelessPeriod, voicelessPeriod, thee.peek(), ttarget);
			voicelessPeriod = NUMrandomUniform (0.008, 0.012);
			ttarget += voicelessPeriod;
		}

		/*
		 * Find the number of trailing zeroes and hack the sound's time domain.
		 */
		thy xmax = thy xmin + RealTier_getArea (duration, my xmin, my xmax);
		if (fabs (thy xmax - my xmax) < 1e-12) thy xmax = my xmax;   /* Common situation. */
		thy nx = Sampled_xToLowIndex (thee.peek(), thy xmax);
		if (thy nx > 3 * my nx) thy nx = 3 * my nx;

		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": not manipulated.");
	}
}
Beispiel #15
0
CCA TableOfReal_to_CCA (TableOfReal me, long ny) {
	try {
		long n = my numberOfRows, nx = my numberOfColumns - ny;

		if (ny < 1 || ny > my numberOfColumns - 1) {
			Melder_throw (U"Dimension of first part not correct.");
		}
		if (ny > nx) Melder_throw (U"The dimension of the dependent part (", ny, U") must be less than or equal to "
			                           "the dimension of the independent part (", nx, U").");
		if (n < ny) {
			Melder_throw (U"The number of observations must be larger then ", ny, U".");
		}

		TableOfReal_areAllCellsDefined (me, 0, 0, 0, 0);
		// Use svd as (temporary) storage, and copy data

		autoSVD svdy = SVD_create (n, ny);
		autoSVD svdx = SVD_create (n, nx);

		for (long i = 1; i <= n; i++) {
			for (long j = 1; j <= ny; j++) {
				svdy -> u[i][j] = my data[i][j];
			}
			for (long j = 1; j <= nx; j++) {
				svdx -> u[i][j] = my data[i][ny + j];
			}
		}

		double **uy = svdy -> u;
		double **vy = svdy -> v;
		double **ux = svdx -> u;
		double **vx = svdx -> v;
		double fnormy = NUMfrobeniusnorm (n, ny, uy);
		double fnormx = NUMfrobeniusnorm (n, nx, ux);
		if (fnormy == 0 || fnormx == 0) {
			Melder_throw (U"One of the parts of the table contains only zeros.");
		}

		/*
			Centre the data and svd it.
		*/

		NUMcentreColumns (uy, 1, n, 1, ny, NULL);
		NUMcentreColumns (ux, 1, n, 1, nx, NULL);

		SVD_compute (svdy.peek()); SVD_compute (svdx.peek());

		long numberOfZeroedy = SVD_zeroSmallSingularValues (svdy.peek(), 0);
		long numberOfZeroedx = SVD_zeroSmallSingularValues (svdx.peek(), 0);

		/*
			Form the matrix C = ux' uy (use svd-object storage)
		*/

		autoSVD svdc = SVD_create (nx, ny);
		double **uc = svdc -> u;
		double **vc = svdc -> v;

		for (long i = 1; i <= nx; i++) {
			for (long j = 1; j <= ny; j++) {
				double t = 0;
				for (long q = 1; q <= n; q++) {
					t += ux[q][i] * uy[q][j];
				}
				uc[i][j] = t;
			}
		}

		SVD_compute (svdc.peek());
		long numberOfZeroedc = SVD_zeroSmallSingularValues (svdc.peek(), 0);
		long numberOfCoefficients = ny - numberOfZeroedc;

		autoCCA thee = CCA_create (numberOfCoefficients, ny, nx);
		thy yLabels = strings_to_Strings (my columnLabels, 1, ny);
		thy xLabels = strings_to_Strings (my columnLabels, ny + 1, my numberOfColumns);

		double **evecy = thy y -> eigenvectors;
		double **evecx = thy x -> eigenvectors;
		thy numberOfObservations = n;

		/*
			Y = Vy * inv(Dy) * Vc
			X = Vx * inv(Dx) * Uc
			For the eigenvectors we want a row representation:
			colums(Y) = rows(Y') = rows(Vc' * inv(Dy) * Vy')
			colums(X) = rows(X') = rows(Uc' * inv(Dx) * Vx')
			rows(Y') = evecy[i][j] = Vc[k][i] * Vy[j][k] / Dy[k]
			rows(X') = evecx[i][j] = Uc[k][i] * Vx[j][k] / Dx[k]
		*/

		for (long i = 1; i <= numberOfCoefficients; i++) {
			double ccc = svdc -> d[i];
			thy y -> eigenvalues[i] = thy x -> eigenvalues[i] = ccc * ccc;
			for (long j = 1; j <= ny; j++) {
				double t = 0;
				for (long q = 1; q <= ny - numberOfZeroedy; q++) {
					t += vc[q][i] * vy[j][q] / svdy -> d[q];
				}
				evecy[i][j] = t;
			}
			for (long j = 1; j <= nx; j++) {
				double t = 0;
				for (long q = 1; q <= nx - numberOfZeroedx; q++) {
					t += uc[q][i] * vx[j][q] / svdx -> d[q];
				}
				evecx[i][j] = t;
			}
		}

		/*
			Normalize eigenvectors.
		*/
		NUMnormalizeRows (thy y -> eigenvectors, numberOfCoefficients, ny, 1);
		NUMnormalizeRows (thy x -> eigenvectors, numberOfCoefficients, nx, 1);
		Melder_assert (thy x -> dimension == thy xLabels -> numberOfStrings &&
		               thy y -> dimension == thy yLabels -> numberOfStrings);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": CCA not created.");
	}
}
Beispiel #16
0
Pitch Sound_to_Pitch_shs (Sound me, double timeStep, double minimumPitch,
                          double maximumFrequency, double ceiling, long maxnSubharmonics, long maxnCandidates,
                          double compressionFactor, long nPointsPerOctave) {
	try {
		double firstTime, newSamplingFrequency = 2 * maximumFrequency;
		double windowDuration = 2 / minimumPitch, halfWindow = windowDuration / 2;
		double atans = nPointsPerOctave * NUMlog2 (65.0 / 50.0) - 1;
		// Number of speech samples in the downsampled signal in each frame:
		// 100 for windowDuration == 0.04 and newSamplingFrequency == 2500
		long nx = lround (windowDuration * newSamplingFrequency);

		// The minimum number of points for the fft is 256.
		long nfft = 1;
		while ( (nfft *= 2) < nx || nfft <= 128) {
			;
		}
		long nfft2 = nfft / 2 + 1;
		double frameDuration = nfft / newSamplingFrequency;
		double df = newSamplingFrequency / nfft;

		// The number of points on the octave scale

		double fminl2 = NUMlog2 (minimumPitch), fmaxl2 = NUMlog2 (maximumFrequency);
		long nFrequencyPoints = (long) floor ((fmaxl2 - fminl2) * nPointsPerOctave);
		double dfl2 = (fmaxl2 - fminl2) / (nFrequencyPoints - 1);

		autoSound sound = Sound_resample (me, newSamplingFrequency, 50);
		long numberOfFrames;
		Sampled_shortTermAnalysis (sound.peek(), windowDuration, timeStep, &numberOfFrames, &firstTime);
		autoSound frame = Sound_createSimple (1, frameDuration, newSamplingFrequency);
		autoSound hamming = Sound_createHamming (nx / newSamplingFrequency, newSamplingFrequency);
		autoPitch thee = Pitch_create (my xmin, my xmax, numberOfFrames, timeStep, firstTime,
		                               ceiling, maxnCandidates);
		autoNUMvector<double> cc (1, numberOfFrames);
		autoNUMvector<double> specAmp (1, nfft2);
		autoNUMvector<double> fl2 (1, nfft2);
		autoNUMvector<double> yv2 (1, nfft2);
		autoNUMvector<double> arctg (1, nFrequencyPoints);
		autoNUMvector<double> al2 (1, nFrequencyPoints);

		Melder_assert (frame->nx >= nx);
		Melder_assert (hamming->nx == nx);

		// Compute the absolute value of the globally largest amplitude w.r.t. the global mean.

		double globalMean, globalPeak;
		Sound_localMean (sound.peek(), sound -> xmin, sound -> xmax, &globalMean);
		Sound_localPeak (sound.peek(), sound -> xmin, sound -> xmax, globalMean, &globalPeak);

		/*
			For the cubic spline interpolation we need the frequencies on an octave
			scale, i.e., a log2 scale. All frequencies must be DIFFERENT, otherwise
			the cubic spline interpolation will give corrupt results.
			Because log2(f==0) is not defined, we use the heuristic: f[2]-f[1] == f[3]-f[2].
		*/

		for (long i = 2; i <= nfft2; i++) {
			fl2[i] = NUMlog2 ( (i - 1) * df);
		}
		fl2[1] = 2 * fl2[2] - fl2[3];

		// Calculate frequencies regularly spaced on a log2-scale and
		// the frequency weighting function.

		for (long i = 1; i <= nFrequencyPoints; i++) {
			arctg[i] = 0.5 + atan (3 * (i - atans) / nPointsPerOctave) / NUMpi;
		}

		// Perform the analysis on all frames.

		for (long i = 1; i <= numberOfFrames; i++) {
			Pitch_Frame pitchFrame = &thy frame[i];
			double hm = 1, f0, pitch_strength, localMean, localPeak;
			double tmid = Sampled_indexToX (thee.peek(), i); /* The center of this frame */
			long nx_tmp = frame -> nx;

			// Copy a frame from the sound, apply a hamming window. Get local 'intensity'


			frame -> nx = nx; /*begin vies */
			Sound_into_Sound (sound.peek(), frame.peek(), tmid - halfWindow);
			Sounds_multiply (frame.peek(), hamming.peek());
			Sound_localMean (sound.peek(), tmid - 3 * halfWindow, tmid + 3 * halfWindow, &localMean);
			Sound_localPeak (sound.peek(), tmid - halfWindow, tmid + halfWindow, localMean, &localPeak);
			pitchFrame -> intensity = localPeak > globalPeak ? 1 : localPeak / globalPeak;
			frame -> nx = nx_tmp; /* einde vies */

			// Get the Fourier spectrum.

			autoSpectrum spec = Sound_to_Spectrum (frame.peek(), 1);
			Melder_assert (spec->nx == nfft2);

			// From complex spectrum to amplitude spectrum.

			for (long j = 1; j <= nfft2; j++) {
				double rs = spec -> z[1][j], is = spec -> z[2][j];
				specAmp[j] = sqrt (rs * rs + is * is);
			}

			// Enhance the peaks in the spectrum.

			spec_enhance_SHS (specAmp.peek(), nfft2);

			// Smooth the enhanced spectrum.

			spec_smoooth_SHS (specAmp.peek(), nfft2);

			// Go to a logarithmic scale and perform cubic spline interpolation to get
			// spectral values for the increased number of frequency points.

			NUMspline (fl2.peek(), specAmp.peek(), nfft2, 1e30, 1e30, yv2.peek());
			for (long j = 1; j <= nFrequencyPoints; j++) {
				double f = fminl2 + (j - 1) * dfl2;
				NUMsplint (fl2.peek(), specAmp.peek(), yv2.peek(), nfft2, f, &al2[j]);
			}

			// Multiply by frequency selectivity of the auditory system.

			for (long j = 1; j <= nFrequencyPoints; j++) al2[j] = al2[j] > 0 ?
				        al2[j] * arctg[j] : 0;

			// The subharmonic summation. Shift spectra in octaves and sum.

			Pitch_Frame_init (pitchFrame, maxnCandidates);
			autoNUMvector<double> sumspec (1, nFrequencyPoints);
			pitchFrame -> nCandidates = 0; /* !!!!! */

			for (long m = 1; m <= maxnSubharmonics + 1; m++) {
				long kb = 1 + (long) floor (nPointsPerOctave * NUMlog2 (m));
				for (long k = kb; k <= nFrequencyPoints; k++) {
					sumspec[k - kb + 1] += al2[k] * hm;
				}
				hm *= compressionFactor;
			}

			// First register the voiceless candidate (always present).

			Pitch_Frame_addPitch (pitchFrame, 0, 0, maxnCandidates);

			/*
				Get the best local estimates for the pitch as the maxima of the
				subharmonic sum spectrum by parabolic interpolation on three points:
				The formula for a parabole with a maximum is:
					y(x) = a - b (x - c)^2 with a, b, c >= 0
				The three points are (-x, y1), (0, y2) and (x, y3).
				The solution for a (the maximum) and c (the position) is:
				a = (2 y1 (4 y2 + y3) - y1^2 - (y3 - 4 y2)^2)/( 8 (y1 - 2 y2 + y3)
				c = dx (y1 - y3) / (2 (y1 - 2 y2 + y3))
				(b = (2 y2 - y1 - y3) / (2 dx^2) )
			*/

			for (long k = 2; k <= nFrequencyPoints - 1; k++) {
				double y1 = sumspec[k - 1], y2 = sumspec[k], y3 = sumspec[k + 1];
				if (y2 > y1 && y2 >= y3) {
					double denum = y1 - 2 * y2 + y3, tmp = y3 - 4 * y2;
					double x =  dfl2 * (y1 - y3) / (2 * denum);
					double f = pow (2, fminl2 + (k - 1) * dfl2 + x);
					double strength = (2 * y1 * (4 * y2 + y3) - y1 * y1 - tmp * tmp) / (8 * denum);
					Pitch_Frame_addPitch (pitchFrame, f, strength, maxnCandidates);
				}
			}

			/*
				Check whether f0 corresponds to an actual periodicity T = 1 / f0:
				correlate two signal periods of duration T, one starting at the
				middle of the interval and one starting T seconds before.
				If there is periodicity the correlation coefficient should be high.

				However, some sounds do not show any regularity, or very low
				frequency and regularity, and nevertheless have a definite
				pitch, e.g. Shepard sounds.
			*/

			Pitch_Frame_getPitch (pitchFrame, &f0, &pitch_strength);
			if (f0 > 0) {
				cc[i] = Sound_correlateParts (sound.peek(), tmid - 1.0 / f0, tmid, 1.0 / f0);
			}
		}

		// Base V/UV decision on correlation coefficients.
		// Resize the pitch strengths w.r.t. the cc.

		double vuvCriterium = 0.52;
		for (long i = 1; i <= numberOfFrames; i++) {
			Pitch_Frame_resizeStrengths (& thy frame[i], cc[i], vuvCriterium);
		}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, U": no Pitch (shs) created.");
	}
}
Transition Distributions_to_Transition (Distributions underlying, Distributions surface, long environment,
	Transition adjacency, int greedy)
{
	try {
		if (underlying == NULL) return NULL;

		/*
		 * Preconditions: range check and matrix matching.
		 */
		if (environment < 1 || environment > underlying -> numberOfColumns)
			Melder_throw ("Environment (", environment, ") out of range (1-", underlying -> numberOfColumns, ").");
		if (surface && (underlying -> numberOfColumns != surface -> numberOfColumns || underlying -> numberOfRows != surface -> numberOfRows))
			Melder_throw ("Sizes of underlying and surface distributions do not match.");
		if (adjacency && adjacency -> numberOfStates != underlying -> numberOfColumns)
			Melder_throw ("Number of states (", adjacency -> numberOfStates, ") in adjacency matrix "
				"does not match number of distributions (", underlying -> numberOfColumns, ")");

		/*
		 * Defaults.
		 */
		if (surface == NULL) surface = underlying;

		/*
		 * Create the output object.
		 */
		autoTransition thee = Transition_create (underlying -> numberOfColumns);

		/*
		 * Copy labels and set name.
		 */
		for (long i = 1; i <= thy numberOfStates; i ++) {
			thy stateLabels [i] = Melder_wcsdup (underlying -> columnLabels [i]);
		}
		Thing_setName (thee.peek(), underlying -> columnLabels [environment]);

		/*
		 * Compute the off-diagonal elements of the transition matrix in environment 'environment'.
		 */
		for (long i = 1; i <= thy numberOfStates; i ++) {

			/*
			 * How many states are available for the learner to step to (excluding current state)?
			 */
			long numberOfAdjacentStates;
			if (adjacency) {
				numberOfAdjacentStates = 0;
				for (long j = 1; j <= thy numberOfStates; j ++)
					if (i != j && adjacency -> data [i] [j])
						numberOfAdjacentStates ++;
			} else {
				numberOfAdjacentStates = thy numberOfStates - 1;
			}

			/*
			 * Try all possible steps to adjacent states.
			 */
			for (long j = 1; j <= thy numberOfStates; j ++) if (i != j) {

				/*
				 * Local: grammar step only possible to adjacent grammar.
				 */
				if (adjacency && adjacency -> data [i] [j] == 0) continue;

				/*
				 * Compute element (i, j): sum over all possible data.
				 */
				for (long m = 1; m <= underlying -> numberOfRows; m ++) {

					/*
					 * Error-driven: grammar step only triggered by positive evidence.
					 * If the datum does not conflict with the current hypothesis (i), ignore it.
					 */
					if (underlying -> data [m] [i]) continue;

					/*
					 * Greedy: grammar step only taken if new grammar accepts datum.
					 */
					if (greedy && underlying -> data [m] [j] == 0) continue;

					/*
					 * The step is taken if this datum occurs and this grammar (j) is chosen.
					 */
					thy data [i] [j] += surface -> data [m] [environment] / numberOfAdjacentStates;
				}
			}
		}

		/*
		 * Compute the elements on the diagonal, so that the sum of each row is unity.
		 */
		for (long i = 1; i <= thy numberOfStates; i ++) {
			double sum = 0.0;
			for (long j = 1; j <= thy numberOfStates; j ++) if (j != i)
				sum += thy data [i] [j];
			thy data [i] [i] = sum > 1.0 ? 0.0 : 1.0 - sum;   // guard against rounding errors
		}

		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (underlying, ": Transition not computed.");
	}
}
OTGrammar OTGrammar_create_tongueRoot_grammar (int small_large, int equal_random_infant_Wolof) {
	try {
		int ncons = small_large == 1 ? 5 : 9, itab, v1, v2;
		autoOTGrammar me = Thing_new (OTGrammar);
		my constraints = NUMvector <structOTGrammarConstraint> (1, my numberOfConstraints = ncons);
		my constraints [1]. name = Melder_dup (U"*[rtr / hi]");
		my constraints [2]. name = Melder_dup (U"*[atr / lo]");
		my constraints [3]. name = Melder_dup (U"P\\s{ARSE}\n(rtr)");
		my constraints [4]. name = Melder_dup (U"P\\s{ARSE}\n(atr)");
		my constraints [5]. name = Melder_dup (U"*G\\s{ESTURE}\n(contour)");
		if (ncons == 9) {
			my constraints [6]. name = Melder_dup (U"*[rtr / mid]");
			my constraints [7]. name = Melder_dup (U"*[rtr / lo]");
			my constraints [8]. name = Melder_dup (U"*[atr / mid]");
			my constraints [9]. name = Melder_dup (U"*[atr / hi]");
		}
		if (equal_random_infant_Wolof == 1) {   // equal?
			for (long icons = 1; icons <= ncons; icons ++)
				my constraints [icons]. ranking = 100.0;
		} else if (equal_random_infant_Wolof == 2) {   // random?
			for (long icons = 1; icons <= ncons; icons ++)
				my constraints [icons]. ranking = NUMrandomGauss (100.0, 10.0);
		} else if (equal_random_infant_Wolof == 3) {   // infant (= cannot speak) ?
			for (long icons = 1; icons <= ncons; icons ++)
				my constraints [icons]. ranking = 100.0;   // structural constraints
			my constraints [3]. ranking = 50.0;   // faithfulness constraints
			my constraints [4]. ranking = 50.0;
		} else {   // adult Wolof
			my constraints [1]. ranking = 100.0;
			my constraints [2]. ranking =  10.0;
			my constraints [3]. ranking =  50.0;
			my constraints [4]. ranking =  20.0;
			my constraints [5]. ranking =  30.0;
			if (ncons == 9) {
				my constraints [6]. ranking =   0.0;
				my constraints [7]. ranking = -10.0;
				my constraints [8]. ranking =   0.0;
				my constraints [9]. ranking = -10.0;
			}
		}
		if (ncons == 9) {
			my fixedRankings = NUMvector <structOTGrammarFixedRanking> (1, my numberOfFixedRankings = 4);
			my fixedRankings [1]. higher = 1, my fixedRankings [1]. lower = 6;
			my fixedRankings [2]. higher = 6, my fixedRankings [2]. lower = 7;
			my fixedRankings [3]. higher = 2, my fixedRankings [3]. lower = 8;
			my fixedRankings [4]. higher = 8, my fixedRankings [4]. lower = 9;
		}
		my tableaus = NUMvector <structOTGrammarTableau> (1, my numberOfTableaus = 36);
		itab = 1;
		for (v1 = 0; v1 < 6; v1 ++) for (v2 = 0; v2 < 6; v2 ++) {
			OTGrammarTableau tableau = & my tableaus [itab];
			tableau -> input = Melder_dup (Melder_cat (vowels [v1], U"t", vowels [v2]));
			tableau -> candidates = NUMvector <structOTGrammarCandidate> (1, tableau -> numberOfCandidates = 4);
			/*
			 * Generate the four tongue-root variants as output candidates.
			 */
			OTGrammarCandidate_init (& tableau -> candidates [1], ncons, v1, v2);
				/* Faithful: no PARSE constraints violated. */
			OTGrammarCandidate_init (& tableau -> candidates [2], ncons, fliptr (v1), v2);
				/* First vowel flipped: violated one PARSE constraint. */
			OTGrammarCandidate_init (& tableau -> candidates [3], ncons, v1, fliptr (v2));
				/* Second vowel flipped. */
			OTGrammarCandidate_init (& tableau -> candidates [4], ncons, fliptr (v1), fliptr (v2));
				/* Both vowels flipped. */
			/*
			 * Count PARSE violations.
			 */
			if (isatr (v1)) {
				tableau -> candidates [2]. marks [4] ++;
				tableau -> candidates [4]. marks [4] ++;
			} else {
				tableau -> candidates [2]. marks [3] ++;
				tableau -> candidates [4]. marks [3] ++;
			}
			if (isatr (v2)) {
				tableau -> candidates [3]. marks [4] ++;
				tableau -> candidates [4]. marks [4] ++;
			} else {
				tableau -> candidates [3]. marks [3] ++;
				tableau -> candidates [4]. marks [3] ++;
			}
			itab ++;
		}
		OTGrammar_checkIndex (me.peek());
		OTGrammar_newDisharmonies (me.peek(), 0.0);
		for (long icons = 1; icons <= my numberOfConstraints; icons ++)
			my constraints [icons]. plasticity = 1.0;
		return me.transfer();
	} catch (MelderError) {
		Melder_throw (U"Tongue root grammar not created.");
	}
}
Beispiel #19
0
static autoStrings Strings_createAsFileOrDirectoryList (const char32 *path /* cattable */, int type) {
	#if USE_STAT
		/*
		 * Initialize.
		 */
		DIR *d = nullptr;
		try {
			autoMelderString filePath, searchDirectory, left, right;
			/*
			 * Parse the path.
			 * Example: in /Users/paul/sounds/h*.wav",
			 * the search directory is "/Users/paul/sounds",
			 * the left environment is "h", and the right environment is ".wav".
			 */
			MelderString_copy (& searchDirectory, path);
			char32 *asterisk = str32rchr (searchDirectory. string, '*');
			if (asterisk) {
				*asterisk = '\0';
				searchDirectory. length = asterisk - searchDirectory. string;   // probably superfluous, but correct
				char32 *lastSlash = str32rchr (searchDirectory. string, Melder_DIRECTORY_SEPARATOR);
				if (lastSlash) {
					*lastSlash = '\0';   // This fixes searchDirectory.
					searchDirectory. length = lastSlash - searchDirectory. string;   // probably superfluous, but correct
					MelderString_copy (& left, lastSlash + 1);
				} else {
					MelderString_copy (& left, searchDirectory. string);   // quickly save...
					MelderString_empty (& searchDirectory);   // ...before destruction
				}
				MelderString_copy (& right, asterisk + 1);
			}
			char buffer8 [kMelder_MAXPATH+1];
			Melder_str32To8bitFileRepresentation_inline (searchDirectory. string, buffer8);
			d = opendir (buffer8 [0] ? buffer8 : ".");
			if (! d)
				Melder_throw (U"Cannot open directory ", searchDirectory. string, U".");
			//Melder_casual (U"opened");
			autoStrings me = Thing_new (Strings);
			my strings = NUMvector <char32 *> (1, 1000000);
			struct dirent *entry;
			while (!! (entry = readdir (d))) {
				MelderString_copy (& filePath, searchDirectory. string [0] ? searchDirectory. string : U".");
				MelderString_appendCharacter (& filePath, Melder_DIRECTORY_SEPARATOR);
				char32 buffer32 [kMelder_MAXPATH+1];
				Melder_8bitFileRepresentationToStr32_inline (entry -> d_name, buffer32);
				MelderString_append (& filePath, buffer32);
				//Melder_casual (U"read ", filePath. string);
				Melder_str32To8bitFileRepresentation_inline (filePath. string, buffer8);
				struct stat stats;
				if (stat (buffer8, & stats) != 0) {
					//Melder_throw (U"Cannot look at file ", filePath. string, U".");
					//stats. st_mode = -1L;
				}
				//Melder_casual (U"statted ", filePath. string);
				//Melder_casual (U"file ", filePath. string, U" mode ", stats. st_mode / 4096);
				if ((type == Strings_createAsFileOrDirectoryList_TYPE_FILE && S_ISREG (stats. st_mode)) ||
					(type == Strings_createAsFileOrDirectoryList_TYPE_DIRECTORY && S_ISDIR (stats. st_mode)))
				{
					Melder_8bitFileRepresentationToStr32_inline (entry -> d_name, buffer32);
					int64 length = str32len (buffer32);
					if (buffer32 [0] != U'.' &&
						(left. length == 0 || str32nequ (buffer32, left. string, left. length)) &&
						(right. length == 0 || (length >= right. length && str32equ (buffer32 + (length - right. length), right. string))))
					{
						my strings [++ my numberOfStrings] = Melder_dup (buffer32);
					}
				}
			}
			closedir (d);
			Strings_sort (me.get());
			return me;
		} catch (MelderError) {
			if (d) closedir (d);   // "finally"
			throw;
		}
	#elif defined (_WIN32)
		try {
			char32 searchPath [kMelder_MAXPATH+1];
			int len = str32len (path);
			bool hasAsterisk = !! str32chr (path, U'*');
			bool endsInSeparator = ( len != 0 && path [len - 1] == U'\\' );
			autoStrings me = Thing_new (Strings);
			my strings = NUMvector <char32 *> (1, 1000000);
			Melder_sprint (searchPath, kMelder_MAXPATH+1, path, hasAsterisk || endsInSeparator ? U"" : U"\\", hasAsterisk ? U"" : U"*");
			WIN32_FIND_DATAW findData;
			HANDLE searchHandle = FindFirstFileW (Melder_peek32toW (searchPath), & findData);
			if (searchHandle != INVALID_HANDLE_VALUE) {
				do {
					if ((type == Strings_createAsFileOrDirectoryList_TYPE_FILE &&
							(findData. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
					 || (type == Strings_createAsFileOrDirectoryList_TYPE_DIRECTORY && 
							(findData. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
					{
						if (findData. cFileName [0] != L'.') {
							my strings [++ my numberOfStrings] = Melder_dup (Melder_peekWto32 (findData. cFileName));
						}
					}
				} while (FindNextFileW (searchHandle, & findData));
				FindClose (searchHandle);
			}
			Strings_sort (me.get());
			return me;
		} catch (MelderError) {
			throw;
		}
	#endif
}
Beispiel #20
0
Sound PointProcess_to_Sound_phonation
	(PointProcess me, double samplingFrequency, double adaptFactor, double maximumPeriod,
	 double openPhase, double collisionPhase, double power1, double power2)
{
	try {
		long sound_nt = 1 + floor ((my xmax - my xmin) * samplingFrequency);   // >= 1
		double dt = 1.0 / samplingFrequency;
		double tmid = (my xmin + my xmax) / 2;
		double t1 = tmid - 0.5 * (sound_nt - 1) * dt;
		double a = (power1 + power2 + 1.0) / (power2 - power1);
		double re = openPhase - collisionPhase;
		autoSound thee = Sound_create (1, my xmin, my xmax, sound_nt, dt, t1);
		/*
		 * Compute "re" by iteration.
		 */
		if (collisionPhase <= 0.0) {
			re = openPhase;
		} else {
			double xmaxFlow = pow (power1 / power2, 1.0 / (power2 - power1));
			double xleft = xmaxFlow;
			double gleft = pow (xleft, power1) - pow (xleft, power2);
			double gderivleft = power1 * pow (xleft, power1 - 1.0) - power2 * pow (xleft, power2 - 1.0);
			double fleft = - gleft / gderivleft;
			double xright = 1.0;
			double gright = pow (xright, power1) - pow (xright, power2);
			double gderivright = power1 * pow (xright, power1 - 1.0) - power2 * pow (xright, power2 - 1.0);
			double fright = - gright / gderivright;
			for (int i = 1; i <= 50; i ++) {
				double xmid = 0.5 * (xleft + xright);
				double gmid = pow (xmid, power1) - pow (xmid, power2);
				double gderivmid = power1 * pow (xmid, power1 - 1.0) - power2 * pow (xmid, power2 - 1.0);
				double fmid = - gmid / gderivmid;
				if (fmid > collisionPhase / openPhase) {
					xleft = xmid;
					fleft = fmid;
				} else {
					xright = xmid;
					fright = fmid;
				}
				re = xmid * openPhase;
			}
		}
		/*
		 * Cycle through the points. Each will become a period.
		 */
		double *sound = thy z [1];
		for (long it = 1; it <= my nt; it ++) {
			double t = my t [it], amplitude = a;
			double period = NUMundefined, te, phase, flow;
			long midSample = Sampled_xToNearestIndex (thee.peek(), t);
			/*
			 * Determine the period: first look left (because that's where the open phase is),
			 * then right.
			 */
			if (it >= 2) {
				period = my t [it] - my t [it - 1];
				if (period > maximumPeriod) {
					period = NUMundefined;
				}
			}
			if (period == NUMundefined) {
				if (it < my nt) {
					period = my t [it + 1] - my t [it];
					if (period > maximumPeriod) {
						period = NUMundefined;
					}
				}
				if (period == NUMundefined) {
					period = 0.5 * maximumPeriod;   /* Some default value. */
				}
			}
			te = re * period;
			/*
			 * Determine the amplitude of this peak.
			 */
			amplitude /= period * openPhase;
			if (it == 1 || my t [it - 1] < my t [it] - maximumPeriod) {
				amplitude *= adaptFactor * adaptFactor;
			} else if (it == 2 || my t [it - 2] < my t [it - 1] - maximumPeriod) {
				amplitude *= adaptFactor;
			}
			/*
			 * Fill in the samples to the left of the current point.
			 */
			{// scope
				long beginSample = midSample - floor (te / thy dx);
				if (beginSample < 1) beginSample = 1;
				long endSample = midSample;
				if (endSample > thy nx) endSample = thy nx;
				for (long isamp = beginSample; isamp <= endSample; isamp ++) {
					double tsamp = thy x1 + (isamp - 1) * thy dx;
					phase = (tsamp - (t - te)) / (period * openPhase);
					if (phase > 0.0)
						sound [isamp] += amplitude * (power1 * pow (phase, power1 - 1.0) - power2 * pow (phase, power2 - 1.0));
				}
			}
			/*
			 * Determine the signal parameters at the current point.
			 */
			phase = te / (period * openPhase);
			flow = amplitude * (period * openPhase) * (pow (phase, power1) - pow (phase, power2));
			/*
			 * Fill in the samples to the right of the current point.
			 */
			if (flow > 0.0) {
				double flowDerivative = amplitude * (power1 * pow (phase, power1 - 1.0) - power2 * pow (phase, power2 - 1.0));
				double ta = - flow / flowDerivative;
				double factorPerSample = exp (- thy dx / ta);
				double value = flowDerivative * factorPerSample;
				long beginSample = midSample + 1;
				if (beginSample < 1) beginSample = 1;
				long endSample = midSample + floor (20 * ta / thy dx);
				if (endSample > thy nx) endSample = thy nx;
				for (long isamp = beginSample; isamp <= endSample; isamp ++) {
					sound [isamp] += value;
					value *= factorPerSample;
				}
			}
		}
		Vector_scale (thee.peek(), 0.9);
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, ": not converted to Sound (phonation).");
	}
}
/*
	This routine is modeled after qdiag.m from Andreas Ziehe, Pavel Laskov, Guido Nolte, Klaus-Robert Müller,
	A Fast Algorithm for Joint Diagonalization with Non-orthogonal Transformations and its Application to
	Blind Source Separation, Journal of Machine Learning Research 5 (2004), 777–800.
*/
static void Diagonalizer_and_CrossCorrelationTables_ffdiag (Diagonalizer me, CrossCorrelationTables thee, long maxNumberOfIterations, double delta) {
	try {
		long iter = 0, dimension = my numberOfRows;
		double **v = my data;

		autoCrossCorrelationTables ccts = CrossCorrelationTables_and_Diagonalizer_diagonalize (thee, me);
		autoNUMmatrix<double> w (1, dimension, 1, dimension);
		autoNUMmatrix<double> vnew (1, dimension, 1, dimension);
		autoNUMmatrix<double> cc (1, dimension, 1, dimension);

		for (long i = 1; i <= dimension; i++) {
			w[i][i] = 1;
		}

		autoMelderProgress progress (L"Simultaneous diagonalization of many CrossCorrelationTables...");
		double dm_new = CrossCorrelationTables_getDiagonalityMeasure (ccts.peek(), NULL, 0, 0);
		try {
			double dm_old, theta = 1, dm_start = dm_new;
			do {
				dm_old = dm_new;
				for (long i = 1; i <= dimension; i++) {
					for (long j = i + 1; j <= dimension; j++) {
						double zii = 0, zij = 0, zjj = 0, yij = 0, yji = 0; // zij = zji
						for (long k = 1; k <= ccts -> size; k++) {
							CrossCorrelationTable ct = (CrossCorrelationTable) ccts -> item [k];
							zii += ct -> data[i][i] * ct -> data[i][i];
							zij += ct -> data[i][i] * ct -> data[j][j];
							zjj += ct -> data[j][j] * ct -> data[j][j];
							yij += ct -> data[j][j] * ct -> data[i][j];
							yji += ct -> data[i][i] * ct -> data[i][j];
						}
						double denom = zjj * zii - zij * zij;
						if (denom != 0) {
							w[i][j] = (zij * yji - zii * yij) / denom;
							w[j][i] = (zij * yij - zjj * yji) / denom;
						}
					}
				}
				double norma = 0;
				for (long i = 1; i <= dimension; i++) {
					double normai = 0;
					for (long j = 1; j <= dimension; j++) {
						if (i != j) {
							normai += fabs (w[i][j]);
						}
					}
					if (normai > norma) {
						norma = normai;
					}
				}
				// evaluate the norm
				if (norma > theta) {
					double normf = 0;
					for (long i = 1; i <= dimension; i++)
						for (long j = 1; j <= dimension; j++)
							if (i != j) {
								normf += w[i][j] * w[i][j];
							}
					double scalef = theta / sqrt (normf);
					for (long i = 1; i <= dimension; i++) {
						for (long j = 1; j <= dimension; j++) {
							if (i != j) {
								w[i][j] *= scalef;
							}
						}
					}
				}
				// update V
				NUMmatrix_copyElements (v, vnew.peek(), 1, dimension, 1, dimension);
				NUMdmatrices_multiply_VC (v, w.peek(), dimension, dimension, vnew.peek(), dimension);
				for (long k = 1; k <= ccts -> size; k++) {
					CrossCorrelationTable ct = (CrossCorrelationTable) ccts -> item[k];
					NUMmatrix_copyElements (ct -> data, cc.peek(), 1, dimension, 1, dimension);
					NUMdmatrices_multiply_VCVp (ct -> data, w.peek(), dimension, dimension, cc.peek(), 1);
				}
				dm_new = CrossCorrelationTables_getDiagonalityMeasure (ccts.peek(), 0, 0, 0);
				iter++;
				Melder_progress ((double) iter / (double) maxNumberOfIterations, L"Iteration: ", Melder_integer (iter), L", measure: ", Melder_double (dm_new), L"\n fractional measure: ", Melder_double (dm_new / dm_start));
			} while (fabs ((dm_old - dm_new) / dm_new) > delta && iter < maxNumberOfIterations);
		} catch (MelderError) {
			Melder_clearError ();
		}
	} catch (MelderError) {
		Melder_throw (me, " & ", thee, ": no joint diagonalization (ffdiag).");
	}
}
LPC LPC_and_Sound_to_LPC_robust (LPC thee, Sound me, double analysisWidth, double preEmphasisFrequency, double k,
	int itermax, double tol, int wantlocation) {
	struct huber_struct struct_huber = { 0 };
	try {
		double t1, samplingFrequency = 1.0 / my dx, tol_svd = 0.000001;
		double location = 0, windowDuration = 2 * analysisWidth; /* Gaussian window */
		long nFrames, frameErrorCount = 0, iter = 0;
		long p = thy maxnCoefficients;

		if (my xmin != thy xmin || my xmax != thy xmax) {
			Melder_throw ("Time domains differ.");
		}
		if (my dx != thy samplingPeriod) {
			Melder_throw ("Sampling intervals differ.");
		}
		if (floor (windowDuration / my dx) < p + 1) {
			Melder_throw ("Analysis window too short.");
		}
		Sampled_shortTermAnalysis (me, windowDuration, thy dx, & nFrames, & t1);
		if (nFrames != thy nx || t1 != thy x1) {
			Melder_throw ("Incorrect retrieved analysis width");
		}

		autoSound sound = Data_copy (me);
		autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency);
		autoSound window = Sound_createGaussian (windowDuration, samplingFrequency);
		autoLPC him = Data_copy (thee);
		huber_struct_init (&struct_huber, windowDuration, p, samplingFrequency, location, wantlocation);

		struct_huber.k = k;
		struct_huber.tol = tol;
		struct_huber.tol_svd = tol_svd;
		struct_huber.itermax = itermax;

		autoMelderProgress progess (L"LPC analysis");

		Sound_preEmphasis (sound.peek(), preEmphasisFrequency);

		for (long i = 1; i <= nFrames; i++) {
			LPC_Frame lpc = (LPC_Frame) & thy d_frames[i];
			LPC_Frame lpcto = (LPC_Frame) & his d_frames[i];
			double t = Sampled_indexToX (thee, i);

			Sound_into_Sound (sound.peek(), sframe.peek(), t - windowDuration / 2);
			Vector_subtractMean (sframe.peek());
			Sounds_multiply (sframe.peek(), window.peek());

			try {
				LPC_Frames_and_Sound_huber (lpc, sframe.peek(), lpcto, & struct_huber);
			} catch (MelderError) {
				frameErrorCount++;
			}

			iter += struct_huber.iter;

			if ( (i % 10) == 1) {
				Melder_progress ( (double) i / nFrames, L"LPC analysis of frame ",
				                   Melder_integer (i), L" out of ", Melder_integer (nFrames), L".");
			}
		}

		if (frameErrorCount) Melder_warning (L"Results of ", Melder_integer (frameErrorCount),
			L" frame(s) out of ", Melder_integer (nFrames), L" could not be optimised.");
		MelderInfo_writeLine4 (L"Number of iterations: ", Melder_integer (iter),
			L"\n   Average per frame: ", Melder_double (((double) iter) / nFrames));
		huber_struct_destroy (&struct_huber);
		return him.transfer();
	} catch (MelderError) {
		huber_struct_destroy (&struct_huber);
		Melder_throw (me, ": no robust LPC created.");
	}
}
Beispiel #23
0
void LPC_Frame_into_Spectrum (LPC_Frame me, Spectrum thee, double bandwidthReduction,
                              double deEmphasisFrequency) {
	if (my nCoefficients == 0) {
		for (long i = 1; i <= thy nx; i++) {
			thy z[1][i] = thy z[2][i] = 0;
		}
		return;
	}

	// When deEmphasisFrequency is effective we need 1 extra position in the fftbuffer.

	long nfft = 2 * (thy nx - 1), ndata = my nCoefficients + 1;
	double scale = 1.0 / sqrt (2 * thy xmax * thy dx);
	if (ndata >= nfft - 1 && (deEmphasisFrequency < thy xmax || ndata > nfft)) {
		Melder_throw (U"Spectrum size not large enough.");
	}

	autoNUMvector<double> fftbuffer (1, nfft);

	// Copy 1, a[1], ... a[p] into fftbuffer

	fftbuffer[1] = 1;
	for (long i = 2; i <= ndata; i++) {
		fftbuffer[i] = my a[i - 1];
	}

	if (deEmphasisFrequency < thy xmax) {
		// Multiply (1, a[1] z^-1, ... a[p] z^-p) by (1 - b z^-1)

		double b = exp (- 2.0 * NUMpi * deEmphasisFrequency / thy xmax);
		ndata ++;
		for (long i = ndata; i > 1; i--) {
			fftbuffer[i] -= b * fftbuffer[i - 1];
		}
	}

	/*
		Calculate sum (k=0..ndata; a[k] (z)^-k) along a contour with radius r:
		sum (k=0..ndata; a[k] (rz)^-k) = sum (k=0..ndata; (a[k]r^-k) z^-k)
	*/

	double g = exp (NUMpi * bandwidthReduction / (thy dx * nfft)); /* r = 1/g */
	for (long i = 2; i <= ndata; i++) {
		fftbuffer[i] *= pow (g, i - 1);
	}

	/*
		Perform the fft.
		The LPC spectrum is obtained by inverting this spectrum.
		The imaginary parts of the frequencies 0 and Nyquist are 0.
	*/

	NUMforwardRealFastFourierTransform (fftbuffer.peek(), nfft);
	if (my gain > 0) {
		scale *= sqrt (my gain);
	}
	thy z[1][1] = scale / fftbuffer[1];
	thy z[2][1] = 0;
	for (long i = 2; i <= nfft / 2; i++) {
		// We use: 1 / (a + ib) = (a - ib) / (a^2 + b^2)

		double re = fftbuffer[i + i - 1], im = fftbuffer[i + i];
		double invSquared = scale / (re * re + im * im);
		thy z[1][i] =  re * invSquared;
		thy z[2][i] = -im * invSquared;
	}
	thy z[1][thy nx] = scale / fftbuffer[2];
	thy z[2][thy nx] = 0;
}
Beispiel #24
0
void EditDistanceTable_findPath (EditDistanceTable me, TableOfReal *directions) {
	try {
		/* What do we have to do to source to get target?
		 * Origin [0][0] is at bottom-left corner
		 * Target vertical, source horizontal
		 * Going in the vertical direction is a deletion, horizontal is insertion, diagonal is substitution
		 */
		long numberOfSources = my numberOfColumns - 1, numberOfTargets = my numberOfRows - 1;
		autoNUMmatrix<short> psi (0, numberOfTargets, 0, numberOfSources);
		autoNUMmatrix<double> delta (0, numberOfTargets, 0, numberOfSources);

		for (long j = 1; j <= numberOfSources; j++) {
			delta[0][j] = delta[0][j - 1] + EditCostsTable_getDeletionCost (my editCostsTable, my columnLabels[j+1]);
			psi[0][j] = WARPING_fromLeft;
		}
		for (long i = 1; i <= numberOfTargets; i++) {
			delta[i][0] = delta[i - 1][0] + EditCostsTable_getInsertionCost (my editCostsTable, my rowLabels[i+1]);
			psi[i][0] = WARPING_fromBelow;
		}
		for (long j = 1; j <= numberOfSources; j++) {
			for (long i = 1; i <= numberOfTargets; i++) {
				// the substitution, deletion and insertion costs.
				double left = delta[i][j - 1] + EditCostsTable_getInsertionCost (my editCostsTable, my rowLabels[i+1]);
				double bottom = delta[i - 1][j] + EditCostsTable_getDeletionCost (my editCostsTable, my columnLabels[j+1]);
				double mindist = delta[i - 1][j - 1] + EditCostsTable_getSubstitutionCost (my editCostsTable, my rowLabels[i+1], my columnLabels[j+1]); // diag
				psi[i][j] = WARPING_fromDiag;
				if (bottom < mindist) {
					mindist = bottom;
					psi[i][j] = WARPING_fromBelow;
				}
				if (left < mindist) {
					mindist = left;
					psi[i][j] = WARPING_fromLeft;
				}
				delta[i][j] = mindist;
			}
		}
		// find minimum distance in last column
		long iy = numberOfTargets, ix = numberOfSources;

		WarpingPath_reset (my warpingPath);

		WarpingPath_getPath (my warpingPath, psi.peek(), iy, ix);

		WarpingPath_shiftPathByOne (my warpingPath);

		for (long i = 0; i <= numberOfTargets; i++) {
			for (long j = 0; j <= numberOfSources; j++) {
				my data[i+1][j+1] = delta[i][j];
			}
		}
		if (directions != 0) {
			autoTableOfReal him = EditDistanceTable_to_TableOfReal (me);
			for (long i = 0; i <= numberOfTargets; i++) {
				for (long j = 0; j <= numberOfSources; j++) {
					his data[i+1][j+1] = psi[i][j];
				}
			}
			*directions = him.transfer();
		}
	} catch (MelderError) {
		Melder_throw (me, ": minimum path not found.");
	}
}
Beispiel #25
0
void Data_writeBinary (Daata me, FILE *f) {
	my v_writeBinary (f);
	if (ferror (f))
		Melder_throw (U"I/O error.");
}
Beispiel #26
0
static void menu_cb_getJitter_ddp (PointEditor me, EDITOR_ARGS_DIRECT) {
	if (my d_startSelection == my d_endSelection) Melder_throw (U"To measure jitter, make a selection first.");
	Melder_informationReal (PointProcess_getJitter_ddp ((PointProcess) my data, my d_startSelection, my d_endSelection, 1e-4, 0.02, 1.3), nullptr);
}
Beispiel #27
0
void Pitch_pathFinder (Pitch me, double silenceThreshold, double voicingThreshold,
	double octaveCost, double octaveJumpCost, double voicedUnvoicedCost,
	double ceiling, int pullFormants)
{
	if (Melder_debug == 33) Melder_casual ("Pitch path finder:\nSilence threshold = %g\nVoicing threshold = %g\nOctave cost = %g\nOctave jump cost = %g\n"
		"Voiced/unvoiced cost = %g\nCeiling = %g\nPull formants = %d", silenceThreshold, voicingThreshold, octaveCost, octaveJumpCost, voicedUnvoicedCost,
		ceiling, pullFormants);
	try {
		long maxnCandidates = Pitch_getMaxnCandidates (me);
		long place;
		volatile double maximum, value;
		double ceiling2 = pullFormants ? 2 * ceiling : ceiling;
		/* Next three lines 20011015 */
		double timeStepCorrection = 0.01 / my dx;
		octaveJumpCost *= timeStepCorrection;
		voicedUnvoicedCost *= timeStepCorrection;

		my ceiling = ceiling;
		autoNUMmatrix <double> delta (1, my nx, 1, maxnCandidates);
		autoNUMmatrix <long> psi (1, my nx, 1, maxnCandidates);

		for (long iframe = 1; iframe <= my nx; iframe ++) {
			Pitch_Frame frame = & my frame [iframe];
			double unvoicedStrength = silenceThreshold <= 0 ? 0 :
				2 - frame->intensity / (silenceThreshold / (1 + voicingThreshold));
			unvoicedStrength = voicingThreshold + (unvoicedStrength > 0 ? unvoicedStrength : 0);
			for (long icand = 1; icand <= frame->nCandidates; icand ++) {
				Pitch_Candidate candidate = & frame->candidate [icand];
				int voiceless = candidate->frequency == 0 || candidate->frequency > ceiling2;
				delta [iframe] [icand] = voiceless ? unvoicedStrength :
					candidate->strength - octaveCost * NUMlog2 (ceiling / candidate->frequency);
			}
		}

		/* Look for the most probable path through the maxima. */
		/* There is a cost for the voiced/unvoiced transition, */
		/* and a cost for a frequency jump. */

		for (long iframe = 2; iframe <= my nx; iframe ++) {
			Pitch_Frame prevFrame = & my frame [iframe - 1], curFrame = & my frame [iframe];
			double *prevDelta = delta [iframe - 1], *curDelta = delta [iframe];
			long *curPsi = psi [iframe];
			for (long icand2 = 1; icand2 <= curFrame -> nCandidates; icand2 ++) {
				double f2 = curFrame -> candidate [icand2]. frequency;
				maximum = -1e30;
				place = 0;
				for (long icand1 = 1; icand1 <= prevFrame -> nCandidates; icand1 ++) {
					double f1 = prevFrame -> candidate [icand1]. frequency;
					double transitionCost;
					bool previousVoiceless = f1 <= 0 || f1 >= ceiling2;
					bool currentVoiceless = f2 <= 0 || f2 >= ceiling2;
					if (currentVoiceless) {
						if (previousVoiceless) {
							transitionCost = 0;   // both voiceless
						} else {
							transitionCost = voicedUnvoicedCost;   // voiced-to-unvoiced transition
						}
					} else {
						if (previousVoiceless) {
							transitionCost = voicedUnvoicedCost;   // unvoiced-to-voiced transition
							if (Melder_debug == 30) {
								/*
								 * Try to take into account a frequency jump across a voiceless stretch.
								 */
								long place1 = icand1;
								for (long jframe = iframe - 2; jframe >= 1; jframe --) {
									place1 = psi [jframe + 1] [place1];
									f1 = my frame [jframe]. candidate [place1]. frequency;
									if (f1 > 0 && f1 < ceiling) {
										transitionCost += octaveJumpCost * fabs (NUMlog2 (f1 / f2)) / (iframe - jframe);
										break;
									}
								}
							}
						} else {
							transitionCost = octaveJumpCost * fabs (NUMlog2 (f1 / f2));   // both voiced
						}
					}
					value = prevDelta [icand1] - transitionCost + curDelta [icand2];
					//if (Melder_debug == 33) Melder_casual ("Frame %ld, current candidate %ld (delta %g), previous candidate %ld (delta %g), "
					//	"transition cost %g, value %g, maximum %g", iframe, icand2, curDelta [icand2], icand1, prevDelta [icand1], transitionCost, value, maximum);
					if (value > maximum) {
						maximum = value;
						place = icand1;
					} else if (value == maximum) {
						if (Melder_debug == 33) Melder_casual ("A tie in frame %ld, current candidate %ld, previous candidate %ld", iframe, icand2, icand1);
					}
				}
				curDelta [icand2] = maximum;
				curPsi [icand2] = place;
			}
		}

		/* Find the end of the most probable path. */

		place = 1;
		maximum = delta [my nx] [place];
		for (long icand = 2; icand <= my frame [my nx]. nCandidates; icand ++) {
			if (delta [my nx] [icand] > maximum) {
				place = icand;
				maximum = delta [my nx] [place];
			}
		}

		/* Backtracking: follow the path backwards. */

		for (long iframe = my nx; iframe >= 1; iframe --) {
			if (Melder_debug == 33) Melder_casual ("Frame %ld: swapping candidates 1 and %ld", iframe, place);
			Pitch_Frame frame = & my frame [iframe];
			structPitch_Candidate help = frame -> candidate [1];
			frame -> candidate [1] = frame -> candidate [place];
			frame -> candidate [place] = help;
			place = psi [iframe] [place];   // This assignment is challenging to CodeWarrior 11.
		}

		/* Pull formants: devoice frames with frequencies between ceiling and ceiling2. */

		if (ceiling2 > ceiling) {
			if (Melder_debug == 33) Melder_casual ("Pulling formants...");
			for (long iframe = my nx; iframe >= 1; iframe --) {
				Pitch_Frame frame = & my frame [iframe];
				Pitch_Candidate winner = & frame -> candidate [1];
				double f = winner -> frequency;
				if (f > ceiling && f <= ceiling2) {
					for (long icand = 2; icand <= frame -> nCandidates; icand ++) {
						Pitch_Candidate loser = & frame -> candidate [icand];
						if (loser -> frequency == 0.0) {
							structPitch_Candidate help = * winner;
							* winner = * loser;
							* loser = help;
							break;
						}
					}
				}
			}
		}
	} catch (MelderError) {
		Melder_throw (me, ": path not found.");
	}
}
Beispiel #28
0
static void menu_cb_getShimmer_dda (PointEditor me, EDITOR_ARGS_DIRECT) {
	if (my d_startSelection == my d_endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
	Melder_informationReal (PointProcess_Sound_getShimmer_dda ((PointProcess) my data, my d_sound.data, my d_startSelection, my d_endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
}
// Cut parts from me marked by labels in thee
autoIntervalTier IntervalTier_and_IntervalTier_cutPartsMatchingLabel (IntervalTier me, IntervalTier thee, const char32 *label, double precision) {
    try {
        if (my xmin != thy xmin || my xmax != thy xmax) {
            Melder_throw (U"Domains must be equal.");
        }
        autoNUMvector<double> durations (1, my intervals.size);
        for (long i = 1; i <= my intervals.size; i ++) {
            TextInterval ti = my intervals.at [i];
            durations[i] = ti -> xmax - ti -> xmin;
        }
        long myInterval = 1;
        for (long j = 1; j <= thy intervals.size; j ++) {
            TextInterval cut = thy intervals.at [j];
            if (Melder_equ (cut -> text, label)) { // trim
                while (myInterval <= my intervals.size) {
                    TextInterval ti = my intervals.at [myInterval];
                    if (ti -> xmin > cut -> xmin - precision && ti -> xmax < cut -> xmax + precision) {
                        // 1. interval completely within cut
                        durations[myInterval] = 0;
                        myInterval++;
                    } else if (ti -> xmin < cut -> xmin + precision && cut -> xmin < ti -> xmax + precision) {
                        // 2. cut start is within interval
                        if (cut -> xmax > ti -> xmax - precision) {
                            // interval end is in cut, interval start before
                            durations[myInterval] -= ti -> xmax - cut -> xmin;
                            myInterval++;
                        } else {
                            // 3. cut completely within interval
                            durations[myInterval] -= cut -> xmax - cut -> xmin;
                            break;
                        }
                    } else if (cut -> xmax > ti -> xmin - precision && cut -> xmin < ti -> xmax + precision) {
                        // +1+2 : cut end is within interval, cut start before
                        durations[myInterval] -= cut -> xmax - ti -> xmin;
                        break;
                    } else if (ti -> xmax < cut -> xmin + precision) {
                        myInterval++;
                    }
                }
            }
        }
        double totalDuration = 0;
        for (long i = 1; i <= my intervals.size; i ++) {
            if (durations[i] < precision) {
                durations[i] = 0;
            }
            totalDuration += durations[i];
        }
        autoIntervalTier him = IntervalTier_create (0, totalDuration);
        double time = 0; long hisInterval = 1;
        for (long i = 1; i <= my intervals.size; i ++) {
            if (durations[i] <= 0) continue;
            TextInterval ti = my intervals.at [i];
            time += durations[i];
            if (fabs (time - totalDuration) > precision) {
                IntervalTier_splitInterval (him.peek(), time, ti -> text, hisInterval, precision);
                hisInterval++;
            } else { // last interval
                TextInterval histi = his intervals.at [hisInterval];
                TextInterval_setText (histi, ti -> text);
            }
        }
        return him;
    } catch (MelderError) {
        Melder_throw (me, U": parts not cut.");
    }
}
Beispiel #30
0
autoPowerCepstrogram Sound_to_PowerCepstrogram_hillenbrand (Sound me, double minimumPitch, double dt) {
	try {
		// minimum analysis window has 3 periods of lowest pitch
		double analysisWidth = 3  / minimumPitch;
		if (analysisWidth > my dx * my nx) {
			analysisWidth = my dx * my nx;
		}
		double samplingFrequency = 1.0 / my dx;
		autoSound thee;
		if (samplingFrequency > 30000) {
			samplingFrequency = samplingFrequency / 2.0;
			thee = Sound_resample (me, samplingFrequency, 1);
		} else {
			thee = Data_copy (me);
		}
		// pre-emphasis with fixed coefficient 0.9
		for (long i = thy nx; i > 1; i--) {
			thy z[1][i] -= 0.9 * thy z[1][i - 1];
		}
		long nosInWindow = (long) floor (analysisWidth * samplingFrequency), nFrames;
		if (nosInWindow < 8) {
			Melder_throw (U"Analysis window too short.");
		}
		double t1;
		Sampled_shortTermAnalysis (thee.get(), analysisWidth, dt, & nFrames, & t1);
		autoNUMvector<double> hamming (1, nosInWindow);
		for (long i = 1; i <= nosInWindow; i++) {
			hamming[i] = 0.54 -0.46 * cos(2 * NUMpi * (i - 1) / (nosInWindow - 1));
		}
		long nfft = 8; // minimum possible
		while (nfft < nosInWindow) { nfft *= 2; }
		long nfftdiv2 = nfft / 2;
		autoNUMvector<double> fftbuf (1, nfft); // "complex" array
		autoNUMvector<double> spectrum (1, nfftdiv2 + 1); // +1 needed 
		autoNUMfft_Table fftTable;
		NUMfft_Table_init (&fftTable, nfft); // sound to spectrum
		
		double qmax = 0.5 * nfft / samplingFrequency, dq = qmax / (nfftdiv2 + 1);
		autoPowerCepstrogram him = PowerCepstrogram_create (my xmin, my xmax, nFrames, dt, t1, 0, qmax, nfftdiv2+1, dq, 0);
		
		autoMelderProgress progress (U"Cepstrogram analysis");
		
		for (long iframe = 1; iframe <= nFrames; iframe++) {
			double tbegin = t1 + (iframe - 1) * dt - analysisWidth / 2;
			tbegin = tbegin < thy xmin ? thy xmin : tbegin;
			long istart = Sampled_xToLowIndex (thee.get(), tbegin);   // ppgb: afronding naar beneden?
			istart = istart < 1 ? 1 : istart;
			long iend = istart + nosInWindow - 1;
			iend = iend > thy nx ? thy nx : iend;
			for (long i = 1; i <= nosInWindow; i++) {
				fftbuf[i] = thy z[1][istart + i - 1] * hamming[i];
			}
			for (long i = nosInWindow + 1; i <= nfft; i++) { 
				fftbuf[i] = 0;
			}
			NUMfft_forward (&fftTable, fftbuf.peek());
			complexfftoutput_to_power (fftbuf.peek(), nfft, spectrum.peek(), true); // log10(|fft|^2)
			// subtract average
			double specmean = spectrum[1];
			for (long i = 2; i <= nfftdiv2 + 1; i++) {
				specmean += spectrum[i];
			}
			specmean /= nfftdiv2 + 1;
			for (long i = 1; i <= nfftdiv2 + 1; i++) {
				spectrum[i] -= specmean;
			}
			/*
			 * Here we diverge from Hillenbrand as he takes the fft of half of the spectral values.
			 * H. forgets that the actual spectrum has nfft/2+1 values. Thefore, we take the inverse
			 * transform because this keeps the number of samples a power of 2.
			 * At the same time this results in twice as many numbers in the quefrency domain, i.e. we end up with nfft/2+1
			 * numbers while H. has only nfft/4!
			 */
			fftbuf[1] = spectrum[1];
			for (long i = 2; i < nfftdiv2 + 1; i++) {
				fftbuf[i+i-2] = spectrum[i];
				fftbuf[i+i-1] = 0;
			}
			fftbuf[nfft] = spectrum[nfftdiv2 + 1];
			NUMfft_backward (&fftTable, fftbuf.peek());
			for (long i = 1; i <= nfftdiv2 + 1; i++) {
				his z[i][iframe] = fftbuf[i] * fftbuf[i];
			}
			if ((iframe % 10) == 1) {
				Melder_progress ((double) iframe / nFrames, U"Cepstrogram analysis of frame ",
					 iframe, U" out of ", nFrames, U".");
			}
		}
		return him;
	} catch (MelderError) {
		Melder_throw (me, U": no Cepstrogram created.");
	}
}