static void IntervalTier_removeEmptyIntervals (IntervalTier me, IntervalTier boss) { IntervalTier_removeBoundariesBetweenIdenticallyLabeledIntervals (me, L""); if (my intervals -> size < 2) return; TextInterval firstInterval = my interval (1); if (Melder_wcsequ (firstInterval -> text, L"")) { IntervalTier_removeLeftBoundary (me, 2); } if (my numberOfIntervals () < 2) return; TextInterval lastInterval = my interval (my numberOfIntervals ()); if (Melder_wcsequ (lastInterval -> text, L"")) { IntervalTier_removeLeftBoundary (me, my numberOfIntervals ()); } if (my numberOfIntervals () < 3) return; for (long iinterval = my numberOfIntervals () - 1; iinterval >= 2; iinterval --) { TextInterval interval = my interval (iinterval); if (Melder_wcsequ (interval -> text, L"")) { /* * Distribute the empty interval between its neigbours. */ double newBoundaryTime = boss ? IntervalTier_boundaryTimeClosestTo (boss, interval -> xmin, interval -> xmax) : 0.5 * (interval -> xmin + interval -> xmax); TextInterval previous = my interval (iinterval - 1); TextInterval next = my interval (iinterval + 1); previous -> xmax = newBoundaryTime; next -> xmin = newBoundaryTime; Collection_removeItem (my intervals, iinterval); } } }
void IntervalTier_removeBoundariesBetweenIdenticallyLabeledIntervals (IntervalTier me, const wchar_t *label) { try { for (long iint = my intervals -> size; iint > 1; iint--) { TextInterval ti = (TextInterval) my intervals -> item[iint]; if (Melder_wcsequ (ti -> text, label)) { TextInterval tim1 = (TextInterval) my intervals -> item[iint - 1]; if (Melder_wcsequ (tim1 -> text, label)) { Melder_free (tim1 -> text); IntervalTier_removeLeftBoundary (me, iint); } } } } catch (MelderError) { Melder_throw (me, ": boundaries not removed."); } }
void EditDistanceTable_drawEditOperations (EditDistanceTable me, Graphics graphics) { const wchar_t *oinsertion = L"i", *insertion = L"*", *odeletion = L"d", *deletion = L"*", *osubstitution = L"s", *oequal = L""; Graphics_setWindow (graphics, 0.5, my d_warpingPath -> d_pathLength - 0.5, 0, 1); // pathLength-1 symbols double lineSpacing = getLineSpacing (graphics); double ytarget = 1 - lineSpacing, ysource = ytarget - 2 * lineSpacing, yoper = ysource - lineSpacing; Graphics_setTextAlignment (graphics, Graphics_CENTRE, Graphics_BOTTOM); for (long i = 2; i <= my d_warpingPath -> d_pathLength; i++) { structPairOfInteger p = my d_warpingPath -> d_path[i], p1 = my d_warpingPath -> d_path[i - 1]; double x = i - 1; if (p.x == p1.x) { // insertion Graphics_text (graphics, x, ytarget, my rowLabels[p.y]); Graphics_text (graphics, x, ysource, deletion); Graphics_text (graphics, x, yoper, oinsertion); } else if (p.y == p1.y) { // deletion Graphics_text (graphics, x, ytarget, insertion); Graphics_text (graphics, x, ysource, my columnLabels[p.x]); Graphics_text (graphics, x, yoper, odeletion); } else { // substitution ? Graphics_text (graphics, x, ytarget, my rowLabels[p.y]); Graphics_text (graphics, x, ysource, my columnLabels[p.x]); Graphics_text (graphics, x, yoper, (Melder_wcsequ (my rowLabels[p.y], my columnLabels[p.x]) ? oequal : osubstitution)); } Graphics_line (graphics, x, ysource + lineSpacing, x, ytarget - 0.1 * lineSpacing); } }
long ERP_getChannelNumber (ERP me, const wchar_t *channelName) { for (long ichan = 1; ichan <= my ny; ichan ++) { if (Melder_wcsequ (my channelNames [ichan], channelName)) { return ichan; } } return 0; }
long Regression_getFactorIndexFromFactorName_e (I, const wchar *factorName) { iam (Regression); for (long iparm = 1; iparm <= my parameters -> size; iparm ++) { RegressionParameter parm = static_cast<RegressionParameter> (my parameters -> item [iparm]); if (Melder_wcsequ (factorName, parm -> label)) return iparm; } Melder_throw (Thing_messageName (me), L" has no parameter named \"", factorName, L"\"."); }
static long *EEG_channelNames_to_channelNumbers (EEG me, wchar_t **channelNames, long numberOfChannelNames) { try { autoNUMvector<long> channelNumbers (1, numberOfChannelNames); for (long i = 1; i <= numberOfChannelNames; i++) { for (long j = 1; j <= my d_numberOfChannels; j++) { if (Melder_wcsequ (channelNames[i], my d_channelNames[j])) { channelNumbers[i] = j; } } if (channelNumbers[i] == 0) { Melder_throw ("Channel name \"", channelNames[i], "\" not found."); } } return channelNumbers.transfer(); } catch (MelderError) { Melder_throw (me, ": channelNames not found."); } }
void structERPWindow :: v_drawSelectionViewer () { ERP erp = (ERP) data; Graphics_setWindow (d_graphics, -1.1, 1.1, -1.01, 1.19); Graphics_setGrey (d_graphics, 0.85); Graphics_fillRectangle (d_graphics, -1.1, 1.1, -1.01, 1.19); Graphics_setColour (d_graphics, Graphics_BLACK); long numberOfDrawableChannels = erp -> ny >= 64 && Melder_wcsequ (erp -> d_channelNames [64], L"O2") ? 64 : erp -> ny >= 32 && Melder_wcsequ (erp -> d_channelNames [32], L"Cz") ? 32 : 0; BiosemiLocationData *biosemiLocationData = numberOfDrawableChannels == 64 ? biosemiCapCoordinates64 : numberOfDrawableChannels == 32 ? biosemiCapCoordinates32 : 0; for (long ichan = 1; ichan <= numberOfDrawableChannels; ichan ++) { double inclination = (double) biosemiLocationData [ichan]. inclination; double azimuth = (double) biosemiLocationData [ichan]. azimuth; bool rightHemisphere = inclination >= 0.0; double r = fabs (inclination / 115.0); double theta = rightHemisphere ? azimuth * (NUMpi / 180.0) : (azimuth + 180.0) * (NUMpi / 180.0); biosemiLocationData [ichan]. topX = r * cos (theta); biosemiLocationData [ichan]. topY = r * sin (theta); } long n = 201; double d = 2.0 / (n - 1); autoNUMvector <double> mean (1, numberOfDrawableChannels); for (long ichan = 1; ichan <= numberOfDrawableChannels; ichan ++) { mean [ichan] = d_startSelection == d_endSelection ? Sampled_getValueAtX (erp, d_startSelection, ichan, 0, true) : Vector_getMean (erp, d_startSelection, d_endSelection, ichan); } autoNUMmatrix <double> image (1, n, 1, n); for (long irow = 1; irow <= n; irow ++) { double y = -1.0 + (irow - 1) * d; for (long icol = 1; icol <= n; icol ++) { double x = -1.0 + (icol - 1) * d; if (x * x + y * y <= 1.0) { double value = NUMundefined, sum = 0.0, weight = 0.0; for (long ichan = 1; ichan <= numberOfDrawableChannels; ichan ++) { double dx = x - biosemiLocationData [ichan]. topX; double dy = y - biosemiLocationData [ichan]. topY; double distance = sqrt (dx * dx + dy * dy); if (distance < 1e-12) { value = mean [ichan]; break; } distance = distance * distance * distance * distance * distance * distance; sum += mean [ichan] / distance; weight += 1.0 / distance; } if (value == NUMundefined) value = ( sum == 0.0 ? 0.0 : sum / weight ); image [irow] [icol] = value; } } } double minimum = 0.0, maximum = 0.0; for (long irow = 1; irow <= n; irow ++) { for (long icol = 1; icol <= n; icol ++) { double value = image [irow] [icol]; if (value < minimum) minimum = value; else if (value > maximum) maximum = value; } } double absoluteExtremum = - minimum > maximum ? - minimum : maximum; if (d_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_FIXED_RANGE) { minimum = d_sound_scaling_minimum; maximum = d_sound_scaling_maximum; } else if (d_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_FIXED_HEIGHT) { double mean = 0.5 * (minimum + maximum); minimum = mean - 0.5 * d_sound_scaling_height; maximum = mean + 0.5 * d_sound_scaling_height; } else { minimum = - absoluteExtremum; maximum = absoluteExtremum; } for (long irow = 1; irow <= n; irow ++) { double y = -1.0 + (irow - 1) * d; for (long icol = 1; icol <= n; icol ++) { double x = -1.0 + (icol - 1) * d; if (x * x + y * y > 1.0) { image [irow] [icol] = minimum + 0.1875 * (maximum - minimum); // -0.625 * absoluteExtremum; } } } Graphics_image (d_graphics, image.peek(), 1, n, -1.0-0.5/n, 1.0+0.5/n, 1, n, -1.0-0.5/n, 1.0+0.5/n, minimum, maximum); Graphics_setLineWidth (d_graphics, 2.0); /* * Nose. */ Graphics_setGrey (d_graphics, 0.5); {// scope double x [3] = { -0.08, 0.0, 0.08 }, y [3] = { 0.99, 1.18, 0.99 }; Graphics_fillArea (d_graphics, 3, x, y); } Graphics_setColour (d_graphics, Graphics_BLACK); Graphics_line (d_graphics, -0.08, 0.99, 0.0, 1.18); Graphics_line (d_graphics, 0.08, 0.99, 0.0, 1.18); /* * Ears. */ Graphics_setGrey (d_graphics, 0.5); Graphics_fillRectangle (d_graphics, -1.09, -1.00, -0.08, 0.08); Graphics_fillRectangle (d_graphics, 1.09, 1.00, -0.08, 0.08); Graphics_setColour (d_graphics, Graphics_BLACK); Graphics_line (d_graphics, -0.99, 0.08, -1.09, 0.08); Graphics_line (d_graphics, -1.09, 0.08, -1.09, -0.08); Graphics_line (d_graphics, -1.09, -0.08, -0.99, -0.08); Graphics_line (d_graphics, 0.99, 0.08, 1.09, 0.08); Graphics_line (d_graphics, 1.09, 0.08, 1.09, -0.08); Graphics_line (d_graphics, 1.09, -0.08, 0.99, -0.08); /* * Scalp. */ Graphics_ellipse (d_graphics, -1.0, 1.0, -1.0, 1.0); Graphics_setLineWidth (d_graphics, 1.0); }
void structERP :: f_drawScalp (Graphics graphics, double tmin, double tmax, double vmin, double vmax, bool garnish) { Graphics_setInner (graphics); Graphics_setWindow (graphics, -1.0, 1.0, -1.0, 1.0); //Graphics_setGrey (graphics, 1.0); //Graphics_fillRectangle (graphics, -1.1, 1.1, -1.01, 1.19); //Graphics_setColour (graphics, Graphics_BLACK); long numberOfDrawableChannels = this -> ny >= 64 && Melder_wcsequ (this -> d_channelNames [64], L"O2") ? 64 : this -> ny >= 32 && Melder_wcsequ (this -> d_channelNames [32], L"Cz") ? 32 : 0; BiosemiLocationData *biosemiLocationData = numberOfDrawableChannels == 64 ? biosemiCapCoordinates64 : numberOfDrawableChannels == 32 ? biosemiCapCoordinates32 : 0; for (long ichan = 1; ichan <= numberOfDrawableChannels; ichan ++) { double inclination = (double) biosemiLocationData [ichan]. inclination; double azimuth = (double) biosemiLocationData [ichan]. azimuth; bool rightHemisphere = inclination >= 0.0; double r = fabs (inclination / 115.0); double theta = rightHemisphere ? azimuth * (NUMpi / 180.0) : (azimuth + 180.0) * (NUMpi / 180.0); biosemiLocationData [ichan]. topX = r * cos (theta); biosemiLocationData [ichan]. topY = r * sin (theta); } long n = 201; double d = 2.0 / (n - 1); autoNUMvector <double> mean (1, numberOfDrawableChannels); for (long ichan = 1; ichan <= numberOfDrawableChannels; ichan ++) { mean [ichan] = tmin == tmax ? Sampled_getValueAtX (this, tmin, ichan, 0, true) : Vector_getMean (this, tmin, tmax, ichan); } autoNUMmatrix <double> image (1, n, 1, n); for (long irow = 1; irow <= n; irow ++) { double y = -1.0 + (irow - 1) * d; for (long icol = 1; icol <= n; icol ++) { double x = -1.0 + (icol - 1) * d; if (x * x + y * y <= 1.0) { double value = NUMundefined, sum = 0.0, weight = 0.0; for (long ichan = 1; ichan <= numberOfDrawableChannels; ichan ++) { double dx = x - biosemiLocationData [ichan]. topX; double dy = y - biosemiLocationData [ichan]. topY; double distance = sqrt (dx * dx + dy * dy); if (distance < 1e-12) { value = mean [ichan]; break; } distance = distance * distance * distance * distance * distance * distance; sum += mean [ichan] / distance; weight += 1.0 / distance; } if (value == NUMundefined) value = ( sum == 0.0 ? 0.0 : sum / weight ); image [irow] [icol] = value; } } } for (long irow = 1; irow <= n; irow ++) { double y = -1.0 + (irow - 1) * d; for (long icol = 1; icol <= n; icol ++) { double x = -1.0 + (icol - 1) * d; if (x * x + y * y > 1.0) { image [irow] [icol] = vmin; } } } Graphics_image (graphics, image.peek(), 1, n, -1.0-0.5/n, 1.0+0.5/n, 1, n, -1.0-0.5/n, 1.0+0.5/n, vmin, vmax); Graphics_setLineWidth (graphics, 2.0); /* * Nose. */ Graphics_setGrey (graphics, 0.5); {// scope double x [3] = { -0.08, 0.0, 0.08 }, y [3] = { 0.99, 1.18, 0.99 }; Graphics_fillArea (graphics, 3, x, y); } Graphics_setColour (graphics, Graphics_BLACK); Graphics_line (graphics, -0.08, 0.99, 0.0, 1.18); Graphics_line (graphics, 0.08, 0.99, 0.0, 1.18); /* * Ears. */ Graphics_setGrey (graphics, 0.5); Graphics_fillRectangle (graphics, -1.09, -1.00, -0.08, 0.08); Graphics_fillRectangle (graphics, 1.09, 1.00, -0.08, 0.08); Graphics_setColour (graphics, Graphics_BLACK); Graphics_line (graphics, -0.99, 0.08, -1.09, 0.08); Graphics_line (graphics, -1.09, 0.08, -1.09, -0.08); Graphics_line (graphics, -1.09, -0.08, -0.99, -0.08); Graphics_line (graphics, 0.99, 0.08, 1.09, 0.08); Graphics_line (graphics, 1.09, 0.08, 1.09, -0.08); Graphics_line (graphics, 1.09, -0.08, 0.99, -0.08); /* * Scalp. */ Graphics_ellipse (graphics, -1.0, 1.0, -1.0, 1.0); Graphics_setLineWidth (graphics, 1.0); Graphics_unsetInner (graphics); if (garnish) { autoNUMmatrix <double> legend (1, n, 1, 2); for (long irow = 1; irow <= n; irow ++) { for (long icol = 1; icol <= 2; icol ++) { legend [irow] [icol] = (irow - 1) / (n - 1.0); } } Graphics_image (graphics, legend.peek(), 1, 2, 0.78, 0.98, 1, n, -0.8, +0.8, 0.0, 1.0); Graphics_rectangle (graphics, 0.78, 0.98, -0.8, +0.8); Graphics_setTextAlignment (graphics, Graphics_RIGHT, Graphics_TOP); Graphics_text2 (graphics, 1.0, -0.8, Melder_double (vmin * 1e6), L" \\muV"); Graphics_setTextAlignment (graphics, Graphics_RIGHT, Graphics_BOTTOM); Graphics_text2 (graphics, 1.0, +0.8, Melder_double (vmax * 1e6), L" \\muV"); } }
bool structEditCostsTable :: v_matchTargetWithSourceSymbol (const wchar_t *targetSymbol, const wchar_t *sourceSymbol) { return Melder_wcsequ (targetSymbol, sourceSymbol); }
bool structEditCostsTable :: v_matchSourceSymbol (const wchar_t *sourceSymbol, const wchar_t *symbol) { return Melder_wcsequ (sourceSymbol, symbol); }
void TextGrid_anySound_alignInterval (TextGrid me, Function anySound, long tierNumber, long intervalNumber, const wchar_t *languageName, bool includeWords, bool includePhonemes) { try { IntervalTier headTier = TextGrid_checkSpecifiedTierIsIntervalTier (me, tierNumber); if (intervalNumber < 1 || intervalNumber > headTier -> numberOfIntervals ()) Melder_throw ("Interval ", intervalNumber, " does not exist."); TextInterval interval = headTier -> interval (intervalNumber); if (! includeWords && ! includePhonemes) Melder_throw ("Nothing to be done, because you asked neither for word alignment nor for phoneme alignment."); if (wcsstr (headTier -> name, L"/") ) Melder_throw ("The current tier already has a slash (\"/\") in its name. Cannot create a word or phoneme tier from it."); autoSound part = anySound -> classInfo == classLongSound ? LongSound_extractPart (static_cast <LongSound> (anySound), interval -> xmin, interval -> xmax, true) : Sound_extractPart (static_cast <Sound> (anySound), interval -> xmin, interval -> xmax, kSound_windowShape_RECTANGULAR, 1.0, true); autoSpeechSynthesizer synthesizer = SpeechSynthesizer_create (languageName, L"default"); double silenceThreshold = -35, minSilenceDuration = 0.1, minSoundingDuration = 0.1; autoTextGrid analysis = NULL; if (! Melder_wcsequ (interval -> text, L"")) { try { analysis.reset (SpeechSynthesizer_and_Sound_and_TextInterval_align (synthesizer.peek(), part.peek(), interval, silenceThreshold, minSilenceDuration, minSoundingDuration)); } catch (MelderError) { Melder_clearError (); // ignore all error messages from DTW and the like } } if (analysis.peek()) { /* * Clean up the analysis. */ Melder_assert (analysis -> xmin == interval -> xmin); Melder_assert (analysis -> xmax == interval -> xmax); Melder_assert (analysis -> numberOfTiers () == 4); Thing_cast (IntervalTier, analysisWordTier, analysis -> tier (3)); if (! IntervalTier_check (analysisWordTier)) Melder_throw (L"Analysis word tier out of order."); IntervalTier_removeEmptyIntervals (analysisWordTier, NULL); Melder_assert (analysisWordTier -> xmax == analysis -> xmax); Melder_assert (analysisWordTier -> numberOfIntervals () >= 1); TextInterval firstInterval = analysisWordTier -> interval (1); TextInterval lastInterval = analysisWordTier -> interval (analysisWordTier -> numberOfIntervals ()); firstInterval -> xmin = analysis -> xmin; lastInterval -> xmax = analysis -> xmax; if (lastInterval -> xmax != analysis -> xmax) Melder_fatal ("analysis ends at %ls, but last interval at %ls seconds", Melder_double (analysis -> xmax), Melder_double (lastInterval -> xmax)); if (! IntervalTier_check (analysisWordTier)) Melder_throw (L"Analysis word tier out of order (2)."); Thing_cast (IntervalTier, analysisPhonemeTier, analysis -> tier (4)); if (! IntervalTier_check (analysisPhonemeTier)) Melder_throw (L"Analysis phoneme tier out of order."); IntervalTier_removeEmptyIntervals (analysisPhonemeTier, analysisWordTier); Melder_assert (analysisPhonemeTier -> xmax == analysis -> xmax); Melder_assert (analysisPhonemeTier -> numberOfIntervals () >= 1); firstInterval = analysisPhonemeTier -> interval (1); lastInterval = analysisPhonemeTier -> interval (analysisPhonemeTier -> numberOfIntervals ()); firstInterval -> xmin = analysis -> xmin; lastInterval -> xmax = analysis -> xmax; Melder_assert (lastInterval -> xmax == analysis -> xmax); if (! IntervalTier_check (analysisPhonemeTier)) Melder_throw (L"Analysis phoneme tier out of order (2)."); } long wordTierNumber = 0, phonemeTierNumber = 0; IntervalTier wordTier = NULL, phonemeTier = NULL; /* * Include a word tier. */ if (includeWords) { /* * Make sure that the word tier exists. */ autoMelderString newWordTierName; MelderString_copy (& newWordTierName, headTier -> name); MelderString_append (& newWordTierName, L"/word"); for (long itier = 1; itier <= my numberOfTiers (); itier ++) { IntervalTier tier = static_cast <IntervalTier> (my tier (itier)); if (Melder_wcsequ (newWordTierName.string, tier -> name)) { if (tier -> classInfo != classIntervalTier) Melder_throw ("A tier with the prospective word tier name (", tier -> name, ") already exists, but it is not an interval tier." "\nPlease change its name or remove it."); wordTierNumber = itier; break; } } if (! wordTierNumber) { autoIntervalTier newWordTier = IntervalTier_create (my xmin, my xmax); Thing_setName (newWordTier.peek(), newWordTierName.string); Ordered_addItemPos (my tiers, newWordTier.transfer(), wordTierNumber = tierNumber + 1); } Melder_assert (wordTierNumber >= 1 && wordTierNumber <= my tiers -> size); wordTier = static_cast <IntervalTier> (my tier (wordTierNumber)); /* * Make sure that the word tier has boundaries at the edges of the interval. */ IntervalTier_insertIntervalDestructively (wordTier, interval -> xmin, interval -> xmax); /* * Copy the contents of the word analysis into the interval in the word tier. */ long wordIntervalNumber = IntervalTier_hasTime (wordTier, interval -> xmin); Melder_assert (wordIntervalNumber != 0); if (analysis.peek()) { Thing_cast (IntervalTier, analysisWordTier, analysis -> tier (3)); if (! IntervalTier_check (analysisWordTier)) Melder_throw (L"Analysis word tier out of order (3)."); if (! IntervalTier_check (wordTier)) Melder_throw (L"Word tier out of order (3)."); for (long ianalysisInterval = 1; ianalysisInterval <= analysisWordTier -> numberOfIntervals (); ianalysisInterval ++) { TextInterval analysisInterval = analysisWordTier -> interval (ianalysisInterval); TextInterval wordInterval = NULL; double tmin = analysisInterval -> xmin, tmax = analysisInterval -> xmax; if (tmax == analysis -> xmax) { wordInterval = wordTier -> interval (wordIntervalNumber); TextInterval_setText (wordInterval, analysisInterval -> text); } else { wordInterval = wordTier -> interval (wordIntervalNumber); autoTextInterval newInterval = TextInterval_create (tmin, tmax, analysisInterval -> text); wordInterval -> xmin = tmax; Collection_addItem (wordTier -> intervals, newInterval.transfer()); wordIntervalNumber ++; } } if (! IntervalTier_check (analysisWordTier)) Melder_throw (L"Analysis word tier out of order (4)."); if (! IntervalTier_check (wordTier)) Melder_throw (L"Word tier out of order (4)."); } } /* * Include a phoneme tier. */ if (includePhonemes) { /* * Make sure that the phoneme tier exists. */ autoMelderString newPhonemeTierName; MelderString_copy (& newPhonemeTierName, headTier -> name); MelderString_append (& newPhonemeTierName, L"/phon"); for (long itier = 1; itier <= my numberOfTiers (); itier ++) { IntervalTier tier = static_cast <IntervalTier> (my tier (itier)); if (Melder_wcsequ (newPhonemeTierName.string, tier -> name)) { if (tier -> classInfo != classIntervalTier) Melder_throw ("A tier with the prospective phoneme tier name (", tier -> name, ") already exists, but it is not an interval tier." "\nPlease change its name or remove it."); phonemeTierNumber = itier; break; } } if (! phonemeTierNumber) { autoIntervalTier newPhonemeTier = IntervalTier_create (my xmin, my xmax); Thing_setName (newPhonemeTier.peek(), newPhonemeTierName.string); Ordered_addItemPos (my tiers, newPhonemeTier.transfer(), phonemeTierNumber = wordTierNumber ? wordTierNumber + 1 : tierNumber + 1); } Melder_assert (phonemeTierNumber >= 1 && phonemeTierNumber <= my tiers -> size); phonemeTier = static_cast <IntervalTier> (my tiers -> item [phonemeTierNumber]); /* * Make sure that the phoneme tier has boundaries at the edges of the interval. */ IntervalTier_insertIntervalDestructively (phonemeTier, interval -> xmin, interval -> xmax); /* * Copy the contents of the phoneme analysis into the interval in the phoneme tier. */ long phonemeIntervalNumber = IntervalTier_hasTime (phonemeTier, interval -> xmin); Melder_assert (phonemeIntervalNumber != 0); if (analysis.peek()) { Thing_cast (IntervalTier, analysisPhonemeTier, analysis -> tiers -> item [4]); for (long ianalysisInterval = 1; ianalysisInterval <= analysisPhonemeTier -> numberOfIntervals (); ianalysisInterval ++) { TextInterval analysisInterval = analysisPhonemeTier -> interval (ianalysisInterval); TextInterval phonemeInterval = NULL; double tmin = analysisInterval -> xmin, tmax = analysisInterval -> xmax; if (tmax == analysis -> xmax) { phonemeInterval = phonemeTier -> interval (phonemeIntervalNumber); TextInterval_setText (phonemeInterval, analysisInterval -> text); } else { phonemeInterval = phonemeTier -> interval (phonemeIntervalNumber); autoTextInterval newInterval = TextInterval_create (tmin, tmax, analysisInterval -> text); phonemeInterval -> xmin = tmax; Collection_addItem (phonemeTier -> intervals, newInterval.transfer()); phonemeIntervalNumber ++; } } } if (includeWords) { /* * Synchronize the boundaries between the word tier and the phoneme tier. */ //for (long iinterval = 1; iinterval <= } } } catch (MelderError) { Melder_throw (me, " & ", anySound, ": interval not aligned."); } }