void structExcitation :: v_info () { double *y = z [1]; long numberOfMaxima = 0; structData :: v_info (); MelderInfo_writeLine (L"Loudness: ", Melder_half (Excitation_getLoudness (this)), L" sones"); for (long i = 2; i < nx; i ++) if (y [i] > y [i - 1] && y [i] >= y [i + 1]) { double i_real, formant_bark, strength; if (++ numberOfMaxima > 15) break; strength = NUMimproveMaximum (z [1], nx, i, NUM_PEAK_INTERPOLATE_SINC70, & i_real); formant_bark = x1 + (i_real - 1) * dx; MelderInfo_write (L"Peak at ", Melder_single (formant_bark), L" Bark"); MelderInfo_write (L", ", Melder_integer ((long) NUMbarkToHertz (formant_bark)), L" Hz"); MelderInfo_writeLine (L", ", Melder_half (strength), L" phon."); } }
static double PairDistributions_getTotalWeight_checkPositive (PairDistribution me) throw (MelderError) { double totalWeight = 0.0; for (long ipair = 1; ipair <= my pairs -> size; ipair ++) { PairProbability prob = static_cast <PairProbability> (my pairs -> item [ipair]); totalWeight += prob -> weight; } if (totalWeight <= 0.0) { Melder_throw (me, U": the total probability weight is ", Melder_half (totalWeight), U" but should be greater than zero for this operation."); } return totalWeight; }
void structOTGrammarEditor :: v_draw () { OTGrammar ot = (OTGrammar) data; static char32 text [1000]; Graphics_clearWs (g); if (ot -> decisionStrategy == kOTGrammar_decisionStrategy_EXPONENTIAL_HG || ot -> decisionStrategy == kOTGrammar_decisionStrategy_EXPONENTIAL_MAXIMUM_ENTROPY) { HyperPage_listItem (this, U"\t\t %%ranking value\t %disharmony\t %plasticity\t %%e^^disharmony"); } else { HyperPage_listItem (this, U"\t\t %%ranking value\t %disharmony\t %plasticity"); } for (long icons = 1; icons <= ot -> numberOfConstraints; icons ++) { OTGrammarConstraint constraint = & ot -> constraints [ot -> index [icons]]; if (ot -> decisionStrategy == kOTGrammar_decisionStrategy_EXPONENTIAL_HG || ot -> decisionStrategy == kOTGrammar_decisionStrategy_EXPONENTIAL_MAXIMUM_ENTROPY) { Melder_sprint (text,1000, U"\t", icons == selected ? U"♠︎ " : U" ", U"@@", icons, U"|", constraint -> name, U"@\t ", Melder_fixed (constraint -> ranking, 3), U"\t ", Melder_fixed (constraint -> disharmony, 3), U"\t ", Melder_fixed (constraint -> plasticity, 6), U"\t ", Melder_float (Melder_half (exp (constraint -> disharmony)))); } else { Melder_sprint (text,1000, U"\t", icons == selected ? U"♠︎ " : U" ", U"@@", icons, U"|", constraint -> name, U"@\t ", Melder_fixed (constraint -> ranking, 3), U"\t ", Melder_fixed (constraint -> disharmony, 3), U"\t ", Melder_fixed (constraint -> plasticity, 6)); } HyperPage_listItem (this, text); } Graphics_setAtSignIsLink (g, FALSE); for (long itab = 1; itab <= ot -> numberOfTableaus; itab ++) { OTGrammarTableau tableau = & ot -> tableaus [itab]; double rowHeight = 0.25; double tableauHeight = rowHeight * (tableau -> numberOfCandidates + 2); drawTableau_ot = ot; drawTableau_input = tableau -> input; drawTableau_constraintsAreDrawnVertically = d_constraintsAreDrawnVertically; HyperPage_picture (this, 20, tableauHeight, drawTableau); } Graphics_setAtSignIsLink (g, TRUE); }
void structFormantGridEditor :: v_draw () { FormantGrid grid = (FormantGrid) our data; Ordered tiers = our editingBandwidths ? grid -> bandwidths : grid -> formants; RealTier selectedTier = (RealTier) tiers -> item [selectedFormant]; double ymin = our editingBandwidths ? our p_bandwidthFloor : our p_formantFloor; double ymax = our editingBandwidths ? our p_bandwidthCeiling : our p_formantCeiling; Graphics_setColour (our d_graphics, Graphics_WHITE); Graphics_setWindow (our d_graphics, 0, 1, 0, 1); Graphics_fillRectangle (our d_graphics, 0, 1, 0, 1); Graphics_setWindow (our d_graphics, our d_startWindow, our d_endWindow, ymin, ymax); Graphics_setColour (our d_graphics, Graphics_RED); Graphics_line (our d_graphics, our d_startWindow, our ycursor, our d_endWindow, our ycursor); Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF); Graphics_text (our d_graphics, our d_startWindow, our ycursor, Melder_float (Melder_half (our ycursor))); Graphics_setColour (our d_graphics, Graphics_BLUE); Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_TOP); Graphics_text (our d_graphics, our d_endWindow, ymax, Melder_float (Melder_half (ymax)), U" Hz"); Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF); Graphics_text (our d_graphics, our d_endWindow, ymin, Melder_float (Melder_half (ymin)), U" Hz"); Graphics_setLineWidth (our d_graphics, 1); Graphics_setColour (our d_graphics, Graphics_GREY); for (long iformant = 1; iformant <= grid -> formants -> size; iformant ++) if (iformant != our selectedFormant) { RealTier tier = (RealTier) tiers -> item [iformant]; long imin = AnyTier_timeToHighIndex (tier, our d_startWindow); long imax = AnyTier_timeToLowIndex (tier, our d_endWindow); long n = tier -> points -> size; if (n == 0) { } else if (imax < imin) { double yleft = RealTier_getValueAtTime (tier, our d_startWindow); double yright = RealTier_getValueAtTime (tier, our d_endWindow); Graphics_line (our d_graphics, our d_startWindow, yleft, our d_endWindow, yright); } else for (long i = imin; i <= imax; i ++) { RealPoint point = (RealPoint) tier -> points -> item [i]; double t = point -> number, y = point -> value; Graphics_fillCircle_mm (our d_graphics, t, y, 2); if (i == 1) Graphics_line (our d_graphics, our d_startWindow, y, t, y); else if (i == imin) Graphics_line (our d_graphics, t, y, our d_startWindow, RealTier_getValueAtTime (tier, our d_startWindow)); if (i == n) Graphics_line (our d_graphics, t, y, our d_endWindow, y); else if (i == imax) Graphics_line (our d_graphics, t, y, our d_endWindow, RealTier_getValueAtTime (tier, our d_endWindow)); else { RealPoint pointRight = (RealPoint) tier -> points -> item [i + 1]; Graphics_line (our d_graphics, t, y, pointRight -> number, pointRight -> value); } } } Graphics_setColour (our d_graphics, Graphics_BLUE); long ifirstSelected = AnyTier_timeToHighIndex (selectedTier, our d_startSelection); long ilastSelected = AnyTier_timeToLowIndex (selectedTier, our d_endSelection); long n = selectedTier -> points -> size; long imin = AnyTier_timeToHighIndex (selectedTier, our d_startWindow); long imax = AnyTier_timeToLowIndex (selectedTier, our d_endWindow); Graphics_setLineWidth (our d_graphics, 2); if (n == 0) { Graphics_setTextAlignment (our d_graphics, Graphics_CENTRE, Graphics_HALF); Graphics_text (our d_graphics, 0.5 * (our d_startWindow + our d_endWindow), 0.5 * (ymin + ymax), U"(no points in selected formant tier)"); } else if (imax < imin) { double yleft = RealTier_getValueAtTime (selectedTier, our d_startWindow); double yright = RealTier_getValueAtTime (selectedTier, our d_endWindow); Graphics_line (our d_graphics, our d_startWindow, yleft, our d_endWindow, yright); } else for (long i = imin; i <= imax; i ++) { RealPoint point = (RealPoint) selectedTier -> points -> item [i]; double t = point -> number, y = point -> value; if (i >= ifirstSelected && i <= ilastSelected) Graphics_setColour (our d_graphics, Graphics_RED); Graphics_fillCircle_mm (our d_graphics, t, y, 3); Graphics_setColour (our d_graphics, Graphics_BLUE); if (i == 1) Graphics_line (our d_graphics, our d_startWindow, y, t, y); else if (i == imin) Graphics_line (our d_graphics, t, y, our d_startWindow, RealTier_getValueAtTime (selectedTier, our d_startWindow)); if (i == n) Graphics_line (our d_graphics, t, y, our d_endWindow, y); else if (i == imax) Graphics_line (our d_graphics, t, y, our d_endWindow, RealTier_getValueAtTime (selectedTier, our d_endWindow)); else { RealPoint pointRight = (RealPoint) selectedTier -> points -> item [i + 1]; Graphics_line (our d_graphics, t, y, pointRight -> number, pointRight -> value); } } Graphics_setLineWidth (our d_graphics, 1); Graphics_setColour (our d_graphics, Graphics_BLACK); }
void structPitch :: v_info () { long nVoiced; autoNUMvector <double> frequencies (Sampled_getSortedValues (this, Pitch_LEVEL_FREQUENCY, kPitch_unit_HERTZ, & nVoiced), 1); structDaata :: v_info (); MelderInfo_writeLine (U"Time domain:"); MelderInfo_writeLine (U" Start time: ", xmin, U" seconds"); MelderInfo_writeLine (U" End time: ", xmax, U" seconds"); MelderInfo_writeLine (U" Total duration: ", xmax - xmin, U" seconds"); MelderInfo_writeLine (U"Time sampling:"); MelderInfo_writeLine (U" Number of frames: ", nx, U" (", nVoiced, U" voiced)"); MelderInfo_writeLine (U" Time step: ", dx, U" seconds"); MelderInfo_writeLine (U" First frame centred at: ", x1, U" seconds"); MelderInfo_writeLine (U"Ceiling at: ", ceiling, U" Hz"); if (nVoiced >= 1) { // quantiles double quantile10, quantile16, quantile50, quantile84, quantile90; quantile10 = NUMquantile (nVoiced, frequencies.peek(), 0.10); quantile16 = NUMquantile (nVoiced, frequencies.peek(), 0.16); quantile50 = NUMquantile (nVoiced, frequencies.peek(), 0.50); // median quantile84 = NUMquantile (nVoiced, frequencies.peek(), 0.84); quantile90 = NUMquantile (nVoiced, frequencies.peek(), 0.90); MelderInfo_writeLine (U"\nEstimated quantiles:"); MelderInfo_write (U" 10% = ", Melder_single (quantile10), U" Hz = ", Melder_single (MEL (quantile10)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (quantile10)), U" semitones above 100 Hz = ", Melder_single (ERB (quantile10)), U" ERB"); MelderInfo_write (U" 16% = ", Melder_single (quantile16), U" Hz = ", Melder_single (MEL (quantile16)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (quantile16)), U" semitones above 100 Hz = ", Melder_single (ERB (quantile16)), U" ERB"); MelderInfo_write (U" 50% = ", Melder_single (quantile50), U" Hz = ", Melder_single (MEL (quantile50)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (quantile50)), U" semitones above 100 Hz = ", Melder_single (ERB (quantile50)), U" ERB"); MelderInfo_write (U" 84% = ", Melder_single (quantile84), U" Hz = ", Melder_single (MEL (quantile84)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (quantile84)), U" semitones above 100 Hz = ", Melder_single (ERB (quantile84)), U" ERB"); MelderInfo_write (U" 90% = ", Melder_single (quantile90), U" Hz = ", Melder_single (MEL (quantile90)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (quantile90)), U" semitones above 100 Hz = ", Melder_single (ERB (quantile90)), U" ERB"); if (nVoiced > 1) { double corr = sqrt (nVoiced / (nVoiced - 1.0)); MelderInfo_writeLine (U"\nEstimated spreading:"); MelderInfo_write (U" 84%-median = ", Melder_half ((quantile84 - quantile50) * corr), U" Hz = ", Melder_half ((MEL (quantile84) - MEL (quantile50)) * corr), U" Mel = "); MelderInfo_writeLine (Melder_half ((SEMITONES (quantile84) - SEMITONES (quantile50)) * corr), U" semitones = ", Melder_half ((ERB (quantile84) - ERB (quantile50)) * corr), U" ERB"); MelderInfo_write (U" median-16% = ", Melder_half ((quantile50 - quantile16) * corr), U" Hz = ", Melder_half ((MEL (quantile50) - MEL (quantile16)) * corr), U" Mel = "); MelderInfo_writeLine (Melder_half ((SEMITONES (quantile50) - SEMITONES (quantile16)) * corr), U" semitones = ", Melder_half ((ERB (quantile50) - ERB (quantile16)) * corr), U" ERB"); MelderInfo_write (U" 90%-10% = ", Melder_half ((quantile90 - quantile10) * corr), U" Hz = ", Melder_half ((MEL (quantile90) - MEL (quantile10)) * corr), U" Mel = "); MelderInfo_writeLine (Melder_half ((SEMITONES (quantile90) - SEMITONES (quantile10)) * corr), U" semitones = ", Melder_half ((ERB (quantile90) - ERB (quantile10)) * corr), U" ERB"); } } if (nVoiced >= 1) { // extrema, range, mean and standard deviation double minimum = Pitch_getMinimum (this, xmin, xmax, kPitch_unit_HERTZ, false); double maximum = Pitch_getMaximum (this, xmin, xmax, kPitch_unit_HERTZ, false); double meanHertz, meanMel, meanSemitones, meanErb; MelderInfo_write (U"\nMinimum ", Melder_single (minimum), U" Hz = ", Melder_single (MEL (minimum)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (minimum)), U" semitones above 100 Hz = ", Melder_single (ERB (minimum)), U" ERB"); MelderInfo_write (U"Maximum ", Melder_single (maximum), U" Hz = ", Melder_single (MEL (maximum)), U" Mel = "); MelderInfo_writeLine (Melder_single (SEMITONES (maximum)), U" semitones above 100 Hz = ", Melder_single (ERB (maximum)), U" ERB"); MelderInfo_write (U"Range ", Melder_half (maximum - minimum), U" Hz = ", Melder_single (MEL (maximum) - MEL (minimum)), U" Mel = "); MelderInfo_writeLine (Melder_half (SEMITONES (maximum) - SEMITONES (minimum)), U" semitones = ", Melder_half (ERB (maximum) - ERB (minimum)), U" ERB"); meanHertz = Pitch_getMean (this, 0, 0, kPitch_unit_HERTZ); meanMel = Pitch_getMean (this, 0, 0, kPitch_unit_MEL); meanSemitones = Pitch_getMean (this, 0, 0, kPitch_unit_SEMITONES_100); meanErb = Pitch_getMean (this, 0, 0, kPitch_unit_ERB); MelderInfo_write (U"Average: ", Melder_single (meanHertz), U" Hz = ", Melder_single (meanMel), U" Mel = "); MelderInfo_writeLine (Melder_single (meanSemitones), U" semitones above 100 Hz = ", Melder_single (meanErb), U" ERB"); if (nVoiced >= 2) { double stdevHertz = Pitch_getStandardDeviation (this, 0, 0, kPitch_unit_HERTZ); double stdevMel = Pitch_getStandardDeviation (this, 0, 0, kPitch_unit_MEL); double stdevSemitones = Pitch_getStandardDeviation (this, 0, 0, kPitch_unit_SEMITONES_100); double stdevErb = Pitch_getStandardDeviation (this, 0, 0, kPitch_unit_ERB); MelderInfo_write (U"Standard deviation: ", Melder_half (stdevHertz), U" Hz = ", Melder_half (stdevMel), U" Mel = "); MelderInfo_writeLine (Melder_half (stdevSemitones), U" semitones = ", Melder_half (stdevErb), U" ERB"); } } if (nVoiced > 1) { // variability: mean absolute slope double slopeHertz, slopeMel, slopeSemitones, slopeErb, slopeWithoutOctaveJumps; Pitch_getMeanAbsoluteSlope (this, & slopeHertz, & slopeMel, & slopeSemitones, & slopeErb, & slopeWithoutOctaveJumps); MelderInfo_write (U"\nMean absolute slope: ", Melder_half (slopeHertz), U" Hz/s = ", Melder_half (slopeMel), U" Mel/s = "); MelderInfo_writeLine (Melder_half (slopeSemitones), U" semitones/s = ", Melder_half (slopeErb), U" ERB/s"); MelderInfo_writeLine (U"Mean absolute slope without octave jumps: ", Melder_half (slopeWithoutOctaveJumps), U" semitones/s"); } }
void TimeSoundEditor_drawSound (TimeSoundEditor me, double globalMinimum, double globalMaximum) { Sound sound = my d_sound.data; LongSound longSound = my d_longSound.data; Melder_assert (!! sound != !! longSound); int nchan = sound ? sound -> ny : longSound -> numberOfChannels; bool cursorVisible = my d_startSelection == my d_endSelection && my d_startSelection >= my d_startWindow && my d_startSelection <= my d_endWindow; Graphics_setColour (my d_graphics, Graphics_BLACK); bool fits; try { fits = sound ? true : LongSound_haveWindow (longSound, my d_startWindow, my d_endWindow); } catch (MelderError) { bool outOfMemory = !! str32str (Melder_getError (), U"memory"); if (Melder_debug == 9) Melder_flushError (); else Melder_clearError (); Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0); Graphics_setTextAlignment (my d_graphics, Graphics_CENTRE, Graphics_HALF); Graphics_text (my d_graphics, 0.5, 0.5, outOfMemory ? U"(out of memory)" : U"(cannot read sound file)"); return; } if (! fits) { Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0); Graphics_setTextAlignment (my d_graphics, Graphics_CENTRE, Graphics_HALF); Graphics_text (my d_graphics, 0.5, 0.5, U"(window too large; zoom in to see the data)"); return; } long first, last; if (Sampled_getWindowSamples (sound ? (Sampled) sound : (Sampled) longSound, my d_startWindow, my d_endWindow, & first, & last) <= 1) { Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0); Graphics_setTextAlignment (my d_graphics, Graphics_CENTRE, Graphics_HALF); Graphics_text (my d_graphics, 0.5, 0.5, U"(zoom out to see the data)"); return; } const int numberOfVisibleChannels = nchan > 8 ? 8 : nchan; const int firstVisibleChannel = my d_sound.channelOffset + 1; int lastVisibleChannel = my d_sound.channelOffset + numberOfVisibleChannels; if (lastVisibleChannel > nchan) lastVisibleChannel = nchan; double maximumExtent = 0.0, visibleMinimum = 0.0, visibleMaximum = 0.0; if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW) { if (longSound) LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, firstVisibleChannel, & visibleMinimum, & visibleMaximum); else Matrix_getWindowExtrema (sound, first, last, firstVisibleChannel, firstVisibleChannel, & visibleMinimum, & visibleMaximum); for (int ichan = firstVisibleChannel + 1; ichan <= lastVisibleChannel; ichan ++) { double visibleChannelMinimum, visibleChannelMaximum; if (longSound) LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & visibleChannelMinimum, & visibleChannelMaximum); else Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & visibleChannelMinimum, & visibleChannelMaximum); if (visibleChannelMinimum < visibleMinimum) visibleMinimum = visibleChannelMinimum; if (visibleChannelMaximum > visibleMaximum) visibleMaximum = visibleChannelMaximum; } maximumExtent = visibleMaximum - visibleMinimum; } for (int ichan = firstVisibleChannel; ichan <= lastVisibleChannel; ichan ++) { double cursorFunctionValue = longSound ? 0.0 : Vector_getValueAtX (sound, 0.5 * (my d_startSelection + my d_endSelection), ichan, 70); /* * BUG: this will only work for mono or stereo, until Graphics_function16 handles quadro. */ double ymin = (double) (numberOfVisibleChannels - ichan + my d_sound.channelOffset) / numberOfVisibleChannels; double ymax = (double) (numberOfVisibleChannels + 1 - ichan + my d_sound.channelOffset) / numberOfVisibleChannels; Graphics_Viewport vp = Graphics_insetViewport (my d_graphics, 0, 1, ymin, ymax); bool horizontal = false; double minimum = sound ? globalMinimum : -1.0, maximum = sound ? globalMaximum : 1.0; if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW) { if (nchan > 2) { if (longSound) { LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & minimum, & maximum); } else { Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & minimum, & maximum); } if (maximumExtent > 0.0) { double middle = 0.5 * (minimum + maximum); minimum = middle - 0.5 * maximumExtent; maximum = middle + 0.5 * maximumExtent; } } else { minimum = visibleMinimum; maximum = visibleMaximum; } } else if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW_AND_CHANNEL) { if (longSound) { LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & minimum, & maximum); } else { Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & minimum, & maximum); } } else if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_FIXED_HEIGHT) { if (longSound) { LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & minimum, & maximum); } else { Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & minimum, & maximum); } double channelExtent = my p_sound_scaling_height; double middle = 0.5 * (minimum + maximum); minimum = middle - 0.5 * channelExtent; maximum = middle + 0.5 * channelExtent; } else if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_FIXED_RANGE) { minimum = my p_sound_scaling_minimum; maximum = my p_sound_scaling_maximum; } if (minimum == maximum) { horizontal = true; minimum -= 1.0; maximum += 1.0;} Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, minimum, maximum); if (horizontal) { Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_HALF); double mid = 0.5 * (minimum + maximum); Graphics_text (my d_graphics, my d_startWindow, mid, Melder_float (Melder_half (mid))); } else { if (! cursorVisible || ! NUMdefined (cursorFunctionValue) || Graphics_dyWCtoMM (my d_graphics, cursorFunctionValue - minimum) > 5.0) { Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_BOTTOM); Graphics_text (my d_graphics, my d_startWindow, minimum, Melder_float (Melder_half (minimum))); } if (! cursorVisible || ! NUMdefined (cursorFunctionValue) || Graphics_dyWCtoMM (my d_graphics, maximum - cursorFunctionValue) > 5.0) { Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_TOP); Graphics_text (my d_graphics, my d_startWindow, maximum, Melder_float (Melder_half (maximum))); } } if (minimum < 0 && maximum > 0 && ! horizontal) { Graphics_setWindow (my d_graphics, 0, 1, minimum, maximum); if (! cursorVisible || ! NUMdefined (cursorFunctionValue) || fabs (Graphics_dyWCtoMM (my d_graphics, cursorFunctionValue - 0.0)) > 3.0) { Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_HALF); Graphics_text (my d_graphics, 0, 0, U"0"); } Graphics_setColour (my d_graphics, Graphics_CYAN); Graphics_setLineType (my d_graphics, Graphics_DOTTED); Graphics_line (my d_graphics, 0, 0, 1, 0); Graphics_setLineType (my d_graphics, Graphics_DRAWN); } /* * Garnish the drawing area of each channel. */ Graphics_setWindow (my d_graphics, 0, 1, 0, 1); Graphics_setColour (my d_graphics, Graphics_CYAN); Graphics_innerRectangle (my d_graphics, 0, 1, 0, 1); Graphics_setColour (my d_graphics, Graphics_BLACK); if (nchan > 1) { Graphics_setTextAlignment (my d_graphics, Graphics_LEFT, Graphics_HALF); const char32 *channelName = my v_getChannelName (ichan); static MelderString channelLabel; MelderString_copy (& channelLabel, ( channelName ? U"ch" : U"Channel " ), ichan); if (channelName) MelderString_append (& channelLabel, U": ", channelName); if (ichan > 8 && ichan - my d_sound.channelOffset == 1) { MelderString_append (& channelLabel, U" " UNITEXT_UPWARDS_ARROW); } else if (ichan >= 8 && ichan - my d_sound.channelOffset == 8 && ichan < nchan) { MelderString_append (& channelLabel, U" " UNITEXT_DOWNWARDS_ARROW); } Graphics_text (my d_graphics, 1, 0.5, channelLabel.string); } /* * Draw a very thin separator line underneath. */ if (ichan < nchan) { /*Graphics_setColour (d_graphics, Graphics_BLACK);*/ Graphics_line (my d_graphics, 0, 0, 1, 0); } /* * Draw the samples. */ /*if (ichan == 1) FunctionEditor_SoundAnalysis_drawPulses (this);*/ if (sound) { Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, minimum, maximum); if (cursorVisible && NUMdefined (cursorFunctionValue)) FunctionEditor_drawCursorFunctionValue (me, cursorFunctionValue, Melder_float (Melder_half (cursorFunctionValue)), U""); Graphics_setColour (my d_graphics, Graphics_BLACK); Graphics_function (my d_graphics, sound -> z [ichan], first, last, Sampled_indexToX (sound, first), Sampled_indexToX (sound, last)); } else { Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, minimum * 32768, maximum * 32768); Graphics_function16 (my d_graphics, longSound -> buffer - longSound -> imin * nchan + (ichan - 1), nchan - 1, first, last, Sampled_indexToX (longSound, first), Sampled_indexToX (longSound, last)); } Graphics_resetViewport (my d_graphics, vp); } Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0); Graphics_rectangle (my d_graphics, 0.0, 1.0, 0.0, 1.0); }
void structSound :: v_info () { structData :: v_info (); const double rho_c = 400; /* rho = 1.14 kg m-3; c = 353 m s-1; [rho c] = kg m-2 s-1 */ double minimum = z [1] [1], maximum = minimum; MelderInfo_writeLine (U"Number of channels: ", ny, ny == 1 ? U" (mono)" : ny == 2 ? U" (stereo)" : U""); MelderInfo_writeLine (U"Time domain:"); MelderInfo_writeLine (U" Start time: ", xmin, U" seconds"); MelderInfo_writeLine (U" End time: ", xmax, U" seconds"); MelderInfo_writeLine (U" Total duration: ", xmax - xmin, U" seconds"); MelderInfo_writeLine (U"Time sampling:"); MelderInfo_writeLine (U" Number of samples: ", nx); MelderInfo_writeLine (U" Sampling period: ", dx, U" seconds"); MelderInfo_writeLine (U" Sampling frequency: ", Melder_single (1.0 / dx), U" Hz"); MelderInfo_writeLine (U" First sample centred at: ", x1, U" seconds"); {// scope double sum = 0.0, sumOfSquares = 0.0; for (long channel = 1; channel <= ny; channel ++) { double *amplitude = z [channel]; for (long i = 1; i <= nx; i ++) { double value = amplitude [i]; sum += value; sumOfSquares += value * value; if (value < minimum) minimum = value; if (value > maximum) maximum = value; } } MelderInfo_writeLine (U"Amplitude:"); MelderInfo_writeLine (U" Minimum: ", Melder_single (minimum), U" Pascal"); MelderInfo_writeLine (U" Maximum: ", Melder_single (maximum), U" Pascal"); double mean = sum / (nx * ny); MelderInfo_writeLine (U" Mean: ", Melder_single (mean), U" Pascal"); MelderInfo_writeLine (U" Root-mean-square: ", Melder_single (sqrt (sumOfSquares / (nx * ny))), U" Pascal"); double penergy = sumOfSquares * dx / ny; /* Pa2 s = kg2 m-2 s-3 */ MelderInfo_write (U"Total energy: ", Melder_single (penergy), U" Pascal\u00B2 sec"); double energy = penergy / rho_c; /* kg s-2 = Joule m-2 */ MelderInfo_writeLine (U" (energy in air: ", Melder_single (energy), U" Joule/m\u00B2)"); double power = energy / (dx * nx); /* kg s-3 = Watt/m2 */ MelderInfo_write (U"Mean power (intensity) in air: ", Melder_single (power), U" Watt/m\u00B2"); if (power != 0.0) { MelderInfo_writeLine (U" = ", Melder_half (10 * log10 (power / 1e-12)), U" dB"); } else { MelderInfo_writeLine (U""); } } if (nx > 1) { for (long channel = 1; channel <= ny; channel ++) { double *amplitude = z [channel]; double sum = 0.0; for (long i = 1; i <= nx; i ++) { double value = amplitude [i]; sum += value; } double mean = sum / nx, stdev = 0.0; for (long i = 1; i <= nx; i ++) { double value = amplitude [i] - mean; stdev += value * value; } stdev = sqrt (stdev / (nx - 1)); MelderInfo_writeLine (U"Standard deviation in channel ", channel, U": ", Melder_single (stdev), U" Pascal"); } } }
static void info (I) { iam (Sound); const double rho_c = 400; /* rho = 1.14 kg m-3; c = 353 m s-1; [rho c] = kg m-2 s-1 */ long numberOfSamples = my nx; double minimum = my z [1] [1], maximum = minimum; classData -> info (me); MelderInfo_writeLine3 (L"Number of channels: ", Melder_integer (my ny), my ny == 1 ? L" (mono)" : my ny == 2 ? L" (stereo)" : L""); MelderInfo_writeLine1 (L"Time domain:"); MelderInfo_writeLine3 (L" Start time: ", Melder_double (my xmin), L" seconds"); MelderInfo_writeLine3 (L" End time: ", Melder_double (my xmax), L" seconds"); MelderInfo_writeLine3 (L" Total duration: ", Melder_double (my xmax - my xmin), L" seconds"); MelderInfo_writeLine1 (L"Time sampling:"); MelderInfo_writeLine2 (L" Number of samples: ", Melder_integer (my nx)); MelderInfo_writeLine3 (L" Sampling period: ", Melder_double (my dx), L" seconds"); MelderInfo_writeLine3 (L" Sampling frequency: ", Melder_single (1.0 / my dx), L" Hz"); MelderInfo_writeLine3 (L" First sample centred at: ", Melder_double (my x1), L" seconds"); double sum = 0.0, sumOfSquares = 0.0; for (long channel = 1; channel <= my ny; channel ++) { double *amplitude = my z [channel]; for (long i = 1; i <= numberOfSamples; i ++) { double value = amplitude [i]; sum += value; sumOfSquares += value * value; if (value < minimum) minimum = value; if (value > maximum) maximum = value; } } MelderInfo_writeLine1 (L"Amplitude:"); MelderInfo_writeLine3 (L" Minimum: ", Melder_single (minimum), L" Pascal"); MelderInfo_writeLine3 (L" Maximum: ", Melder_single (maximum), L" Pascal"); double mean = sum / (my nx * my ny); MelderInfo_writeLine3 (L" Mean: ", Melder_single (mean), L" Pascal"); MelderInfo_writeLine3 (L" Root-mean-square: ", Melder_single (sqrt (sumOfSquares / (my nx * my ny))), L" Pascal"); double penergy = sumOfSquares * my dx / my ny; /* Pa2 s = kg2 m-2 s-3 */ MelderInfo_write3 (L"Total energy: ", Melder_single (penergy), L" Pascal\u00B2 sec"); double energy = penergy / rho_c; /* kg s-2 = Joule m-2 */ MelderInfo_writeLine3 (L" (energy in air: ", Melder_single (energy), L" Joule/m\u00B2)"); double power = energy / (my dx * my nx); /* kg s-3 = Watt/m2 */ MelderInfo_write3 (L"Mean power (intensity) in air: ", Melder_single (power), L" Watt/m\u00B2"); if (power != 0.0) { MelderInfo_writeLine3 (L" = ", Melder_half (10 * log10 (power / 1e-12)), L" dB"); } else { MelderInfo_writeLine1 (L""); } if (my nx > 1) { for (long channel = 1; channel <= my ny; channel ++) { double *amplitude = my z [channel]; double sum = 0.0; for (long i = 1; i <= numberOfSamples; i ++) { double value = amplitude [i]; sum += value; } double mean = sum / my nx, stdev = 0.0; for (long i = 1; i <= numberOfSamples; i ++) { double value = amplitude [i] - mean; stdev += value * value; } stdev = sqrt (stdev / (my nx - 1)); MelderInfo_writeLine5 (L"Standard deviation in channel ", Melder_integer (channel), L": ", Melder_single (stdev), L" Pascal"); } } }
Sound Artword_Speaker_to_Sound (Artword artword, Speaker speaker, double fsamp, int oversampling, Sound *out_w1, int iw1, Sound *out_w2, int iw2, Sound *out_w3, int iw3, Sound *out_p1, int ip1, Sound *out_p2, int ip2, Sound *out_p3, int ip3, Sound *out_v1, int iv1, Sound *out_v2, int iv2, Sound *out_v3, int iv3) { try { autoSound result = Sound_createSimple (1, artword -> totalTime, fsamp); long numberOfSamples = result -> nx; double minTract [1+78], maxTract [1+78]; /* For drawing. */ double Dt = 1 / fsamp / oversampling, rho0 = 1.14, c = 353, onebyc2 = 1.0 / (c * c), rho0c2 = rho0 * c * c, halfDt = 0.5 * Dt, twoDt = 2 * Dt, halfc2Dt = 0.5 * c * c * Dt, twoc2Dt = 2 * c * c * Dt, onebytworho0 = 1.0 / (2.0 * rho0), Dtbytworho0 = Dt / (2.0 * rho0); double tension, rrad, onebygrad, totalVolume; autoArt art = Art_create (); long sample; int n, m, M; autoDelta delta = Speaker_to_Delta (speaker); autoMelderMonitor monitor (U"Articulatory synthesis"); Artword_intoArt (artword, art.peek(), 0.0); Art_Speaker_intoDelta (art.peek(), speaker, delta.peek()); M = delta -> numberOfTubes; autoSound w1, w2, w3, p1, p2, p3, v1, v2, v3; if (iw1 > 0 && iw1 <= M) w1.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iw1 = 0; if (iw2 > 0 && iw2 <= M) w2.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iw2 = 0; if (iw3 > 0 && iw3 <= M) w3.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iw3 = 0; if (ip1 > 0 && ip1 <= M) p1.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else ip1 = 0; if (ip2 > 0 && ip2 <= M) p2.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else ip2 = 0; if (ip3 > 0 && ip3 <= M) p3.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else ip3 = 0; if (iv1 > 0 && iv1 <= M) v1.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iv1 = 0; if (iv2 > 0 && iv2 <= M) v2.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iv2 = 0; if (iv3 > 0 && iv3 <= M) v3.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iv3 = 0; /* Initialize drawing. */ { int i; for (i = 1; i <= 78; i ++) { minTract [i] = 100; maxTract [i] = -100; } } totalVolume = 0.0; for (m = 1; m <= M; m ++) { Delta_Tube t = delta->tube + m; if (! t -> left1 && ! t -> right1) continue; t->Dx = t->Dxeq; t->dDxdt = 0; /* 5.113 */ t->Dy = t->Dyeq; t->dDydt = 0; /* 5.113 */ t->Dz = t->Dzeq; /* 5.113 */ t->A = t->Dz * ( t->Dy >= t->dy ? t->Dy + Dymin : t->Dy <= - t->dy ? Dymin : (t->dy + t->Dy) * (t->dy + t->Dy) / (4 * t->dy) + Dymin ); /* 4.4, 4.5 */ #if EQUAL_TUBE_WIDTHS t->A = 0.0001; #endif t->Jleft = t->Jright = 0; /* 5.113 */ t->Qleft = t->Qright = rho0c2; /* 5.113 */ t->pleft = t->pright = 0; /* 5.114 */ t->Kleft = t->Kright = 0; /* 5.114 */ t->V = t->A * t->Dx; /* 5.114 */ totalVolume += t->V; } //Melder_casual (U"Starting volume: ", totalVolume * 1000, U" litres."); for (sample = 1; sample <= numberOfSamples; sample ++) { double time = (sample - 1) / fsamp; Artword_intoArt (artword, art.peek(), time); Art_Speaker_intoDelta (art.peek(), speaker, delta.peek()); if (sample % MONITOR_SAMPLES == 0 && monitor.graphics()) { // because we can be in batch Graphics graphics = monitor.graphics(); double area [1+78]; Graphics_Viewport vp; for (int i = 1; i <= 78; i ++) { area [i] = delta -> tube [i]. A; if (area [i] < minTract [i]) minTract [i] = area [i]; if (area [i] > maxTract [i]) maxTract [i] = area [i]; } Graphics_clearWs (graphics); vp = Graphics_insetViewport (monitor.graphics(), 0, 0.5, 0.5, 1); Graphics_setWindow (graphics, 0, 1, 0, 0.05); Graphics_setColour (graphics, Graphics_RED); Graphics_function (graphics, minTract, 1, 35, 0, 0.9); Graphics_function (graphics, maxTract, 1, 35, 0, 0.9); Graphics_setColour (graphics, Graphics_BLACK); Graphics_function (graphics, area, 1, 35, 0, 0.9); Graphics_setLineType (graphics, Graphics_DOTTED); Graphics_line (graphics, 0, 0, 1, 0); Graphics_setLineType (graphics, Graphics_DRAWN); Graphics_resetViewport (graphics, vp); vp = Graphics_insetViewport (graphics, 0, 0.5, 0, 0.5); Graphics_setWindow (graphics, 0, 1, -0.000003, 0.00001); Graphics_setColour (graphics, Graphics_RED); Graphics_function (graphics, minTract, 36, 37, 0.2, 0.8); Graphics_function (graphics, maxTract, 36, 37, 0.2, 0.8); Graphics_setColour (graphics, Graphics_BLACK); Graphics_function (graphics, area, 36, 37, 0.2, 0.8); Graphics_setLineType (graphics, Graphics_DOTTED); Graphics_line (graphics, 0, 0, 1, 0); Graphics_setLineType (graphics, Graphics_DRAWN); Graphics_resetViewport (graphics, vp); vp = Graphics_insetViewport (graphics, 0.5, 1, 0.5, 1); Graphics_setWindow (graphics, 0, 1, 0, 0.001); Graphics_setColour (graphics, Graphics_RED); Graphics_function (graphics, minTract, 38, 64, 0, 1); Graphics_function (graphics, maxTract, 38, 64, 0, 1); Graphics_setColour (graphics, Graphics_BLACK); Graphics_function (graphics, area, 38, 64, 0, 1); Graphics_setLineType (graphics, Graphics_DOTTED); Graphics_line (graphics, 0, 0, 1, 0); Graphics_setLineType (graphics, Graphics_DRAWN); Graphics_resetViewport (graphics, vp); vp = Graphics_insetViewport (graphics, 0.5, 1, 0, 0.5); Graphics_setWindow (graphics, 0, 1, 0.001, 0); Graphics_setColour (graphics, Graphics_RED); Graphics_function (graphics, minTract, 65, 78, 0.5, 1); Graphics_function (graphics, maxTract, 65, 78, 0.5, 1); Graphics_setColour (graphics, Graphics_BLACK); Graphics_function (graphics, area, 65, 78, 0.5, 1); Graphics_setLineType (graphics, Graphics_DRAWN); Graphics_resetViewport (graphics, vp); Melder_monitor ((double) sample / numberOfSamples, U"Articulatory synthesis: ", Melder_half (time), U" seconds"); } for (n = 1; n <= oversampling; n ++) { for (m = 1; m <= M; m ++) { Delta_Tube t = delta -> tube + m; if (! t -> left1 && ! t -> right1) continue; /* New geometry. */ #if CONSTANT_TUBE_LENGTHS t->Dxnew = t->Dx; #else t->dDxdtnew = (t->dDxdt + Dt * 10000 * (t->Dxeq - t->Dx)) / (1 + 200 * Dt); /* Critical damping, 10 ms. */ t->Dxnew = t->Dx + t->dDxdtnew * Dt; #endif /* 3-way: equal lengths. */ /* This requires left tubes to be processed before right tubes. */ if (t->left1 && t->left1->right2) t->Dxnew = t->left1->Dxnew; t->Dz = t->Dzeq; /* immediate... */ t->eleft = (t->Qleft - t->Kleft) * t->V; /* 5.115 */ t->eright = (t->Qright - t->Kright) * t->V; /* 5.115 */ t->e = 0.5 * (t->eleft + t->eright); /* 5.116 */ t->p = 0.5 * (t->pleft + t->pright); /* 5.116 */ t->DeltaP = t->e / t->V - rho0c2; /* 5.117 */ t->v = t->p / (rho0 + onebyc2 * t->DeltaP); /* 5.118 */ { double dDy = t->Dyeq - t->Dy; double cubic = t->k3 * dDy * dDy; Delta_Tube l1 = t->left1, l2 = t->left2, r1 = t->right1, r2 = t->right2; tension = dDy * (t->k1 + cubic); t->B = 2 * t->Brel * sqrt (t->mass * (t->k1 + 3 * cubic)); if (t->k1left1 != 0.0 && l1) tension += t->k1left1 * t->k1 * (dDy - (l1->Dyeq - l1->Dy)); if (t->k1left2 != 0.0 && l2) tension += t->k1left2 * t->k1 * (dDy - (l2->Dyeq - l2->Dy)); if (t->k1right1 != 0.0 && r1) tension += t->k1right1 * t->k1 * (dDy - (r1->Dyeq - r1->Dy)); if (t->k1right2 != 0.0 && r2) tension += t->k1right2 * t->k1 * (dDy - (r2->Dyeq - r2->Dy)); } if (t->Dy < t->dy) { if (t->Dy >= - t->dy) { double dDy = t->dy - t->Dy, dDy2 = dDy * dDy; tension += dDy2 / (4 * t->dy) * (t->s1 + 0.5 * t->s3 * dDy2); t->B += 2 * dDy / (2 * t->dy) * sqrt (t->mass * (t->s1 + t->s3 * dDy2)); } else { tension -= t->Dy * (t->s1 + t->s3 * (t->Dy * t->Dy + t->dy * t->dy)); t->B += 2 * sqrt (t->mass * (t->s1 + t->s3 * (3 * t->Dy * t->Dy + t->dy * t->dy))); } } t->dDydtnew = (t->dDydt + Dt / t->mass * (tension + 2 * t->DeltaP * t->Dz * t->Dx)) / (1 + t->B * Dt / t->mass); /* 5.119 */ t->Dynew = t->Dy + t->dDydtnew * Dt; /* 5.119 */ #if NO_MOVING_WALLS t->Dynew = t->Dy; #endif t->Anew = t->Dz * ( t->Dynew >= t->dy ? t->Dynew + Dymin : t->Dynew <= - t->dy ? Dymin : (t->dy + t->Dynew) * (t->dy + t->Dynew) / (4 * t->dy) + Dymin ); /* 4.4, 4.5 */ #if EQUAL_TUBE_WIDTHS t->Anew = 0.0001; #endif t->Ahalf = 0.5 * (t->A + t->Anew); /* 5.120 */ t->Dxhalf = 0.5 * (t->Dxnew + t->Dx); /* 5.121 */ t->Vnew = t->Anew * t->Dxnew; /* 5.128 */ { double oneByDyav = t->Dz / t->A; /*t->R = 12 * 1.86e-5 * t->parallel * t->parallel * oneByDyav * oneByDyav;*/ if (t->Dy < 0) t->R = 12 * 1.86e-5 / (Dymin * Dymin + t->dy * t->dy); else t->R = 12 * 1.86e-5 * t->parallel * t->parallel / ((t->Dy + Dymin) * (t->Dy + Dymin) + t->dy * t->dy); t->R += 0.3 * t->parallel * oneByDyav; /* 5.23 */ } t->r = (1 + t->R * Dt / rho0) * t->Dxhalf / t->Anew; /* 5.122 */ t->ehalf = t->e + halfc2Dt * (t->Jleft - t->Jright); /* 5.123 */ t->phalf = (t->p + halfDt * (t->Qleft - t->Qright) / t->Dx) / (1 + Dtbytworho0 * t->R); /* 5.123 */ #if MASS_LEAPFROG t->ehalf = t->ehalfold + 2 * halfc2Dt * (t->Jleft - t->Jright); #endif t->Jhalf = t->phalf * t->Ahalf; /* 5.124 */ t->Qhalf = t->ehalf / (t->Ahalf * t->Dxhalf) + onebytworho0 * t->phalf * t->phalf; /* 5.124 */ #if NO_BERNOULLI_EFFECT t->Qhalf = t->ehalf / (t->Ahalf * t->Dxhalf); #endif } for (m = 1; m <= M; m ++) { /* Compute Jleftnew and Qleftnew. */ Delta_Tube l = delta->tube + m, r1 = l -> right1, r2 = l -> right2, r = r1; Delta_Tube l1 = l, l2 = r ? r -> left2 : NULL; if (l->left1 == NULL) { /* Closed boundary at the left side (diaphragm)? */ if (r == NULL) continue; /* Tube not connected at all. */ l->Jleftnew = 0; /* 5.132. */ l->Qleftnew = (l->eleft - twoc2Dt * l->Jhalf) / l->Vnew; /* 5.132. */ } else /* Left boundary open to another tube will be handled... */ (void) 0; /* ...together with the right boundary of the tube to the left. */ if (r == NULL) { /* Open boundary at the right side (lips, nostrils)? */ rrad = 1 - c * Dt / 0.02; /* Radiation resistance, 5.135. */ onebygrad = 1 / (1 + c * Dt / 0.02); /* Radiation conductance, 5.135. */ #if NO_RADIATION_DAMPING rrad = 0; onebygrad = 0; #endif l->prightnew = ((l->Dxhalf / Dt + c * onebygrad) * l->pright + 2 * ((l->Qhalf - rho0c2) - (l->Qright - rho0c2) * onebygrad)) / (l->r * l->Anew / Dt + c * onebygrad); /* 5.136 */ l->Jrightnew = l->prightnew * l->Anew; /* 5.136 */ l->Qrightnew = (rrad * (l->Qright - rho0c2) + c * (l->prightnew - l->pright)) * onebygrad + rho0c2; /* 5.136 */ } else if (l2 == NULL && r2 == NULL) { /* Two-way boundary. */ if (l->v > criticalVelocity && l->A < r->A) { l->Pturbrightnew = -0.5 * rho0 * (l->v - criticalVelocity) * (1 - l->A / r->A) * (1 - l->A / r->A) * l->v; if (l->Pturbrightnew != 0.0) l->Pturbrightnew *= 1 + NUMrandomGauss (0, noiseFactor) /* * l->A */; } if (r->v < - criticalVelocity && r->A < l->A) { l->Pturbrightnew = 0.5 * rho0 * (r->v + criticalVelocity) * (1 - r->A / l->A) * (1 - r->A / l->A) * r->v; if (l->Pturbrightnew != 0.0) l->Pturbrightnew *= 1 + NUMrandomGauss (0, noiseFactor) /* * r->A */; } #if NO_TURBULENCE l->Pturbrightnew = 0; #endif l->Jrightnew = r->Jleftnew = (l->Dxhalf * l->pright + r->Dxhalf * r->pleft + twoDt * (l->Qhalf - r->Qhalf + l->Pturbright)) / (l->r + r->r); /* 5.127 */ #if B91 l->Jrightnew = r->Jleftnew = (l->pright + r->pleft + 2 * twoDt * (l->Qhalf - r->Qhalf + l->Pturbright) / (l->Dxhalf + r->Dxhalf)) / (l->r / l->Dxhalf + r->r / r->Dxhalf); #endif l->prightnew = l->Jrightnew / l->Anew; /* 5.128 */ r->pleftnew = r->Jleftnew / r->Anew; /* 5.128 */ l->Krightnew = onebytworho0 * l->prightnew * l->prightnew; /* 5.128 */ r->Kleftnew = onebytworho0 * r->pleftnew * r->pleftnew; /* 5.128 */ #if NO_BERNOULLI_EFFECT l->Krightnew = r->Kleftnew = 0; #endif l->Qrightnew = (l->eright + r->eleft + twoc2Dt * (l->Jhalf - r->Jhalf) + l->Krightnew * l->Vnew + (r->Kleftnew - l->Pturbrightnew) * r->Vnew) / (l->Vnew + r->Vnew); /* 5.131 */ r->Qleftnew = l->Qrightnew + l->Pturbrightnew; /* 5.131 */ } else if (r2) { /* Two adjacent tubes at the right side (velic). */ r1->Jleftnew = (r1->Jleft * r1->Dxhalf * (1 / (l->A + r2->A) + 1 / r1->A) + twoDt * ((l->Ahalf * l->Qhalf + r2->Ahalf * r2->Qhalf ) / (l->Ahalf + r2->Ahalf) - r1->Qhalf)) / (1 / (1 / l->r + 1 / r2->r) + r1->r); /* 5.138 */ r2->Jleftnew = (r2->Jleft * r2->Dxhalf * (1 / (l->A + r1->A) + 1 / r2->A) + twoDt * ((l->Ahalf * l->Qhalf + r1->Ahalf * r1->Qhalf ) / (l->Ahalf + r1->Ahalf) - r2->Qhalf)) / (1 / (1 / l->r + 1 / r1->r) + r2->r); /* 5.138 */ l->Jrightnew = r1->Jleftnew + r2->Jleftnew; /* 5.139 */ l->prightnew = l->Jrightnew / l->Anew; /* 5.128 */ r1->pleftnew = r1->Jleftnew / r1->Anew; /* 5.128 */ r2->pleftnew = r2->Jleftnew / r2->Anew; /* 5.128 */ l->Krightnew = onebytworho0 * l->prightnew * l->prightnew; /* 5.128 */ r1->Kleftnew = onebytworho0 * r1->pleftnew * r1->pleftnew; /* 5.128 */ r2->Kleftnew = onebytworho0 * r2->pleftnew * r2->pleftnew; /* 5.128 */ #if NO_BERNOULLI_EFFECT l->Krightnew = r1->Kleftnew = r2->Kleftnew = 0; #endif l->Qrightnew = r1->Qleftnew = r2->Qleftnew = (l->eright + r1->eleft + r2->eleft + twoc2Dt * (l->Jhalf - r1->Jhalf - r2->Jhalf) + l->Krightnew * l->Vnew + r1->Kleftnew * r1->Vnew + r2->Kleftnew * r2->Vnew) / (l->Vnew + r1->Vnew + r2->Vnew); /* 5.137 */ } else { Melder_assert (l2 != NULL); l1->Jrightnew = (l1->Jright * l1->Dxhalf * (1 / (r->A + l2->A) + 1 / l1->A) - twoDt * ((r->Ahalf * r->Qhalf + l2->Ahalf * l2->Qhalf ) / (r->Ahalf + l2->Ahalf) - l1->Qhalf)) / (1 / (1 / r->r + 1 / l2->r) + l1->r); /* 5.138 */ l2->Jrightnew = (l2->Jright * l2->Dxhalf * (1 / (r->A + l1->A) + 1 / l2->A) - twoDt * ((r->Ahalf * r->Qhalf + l1->Ahalf * l1->Qhalf ) / (r->Ahalf + l1->Ahalf) - l2->Qhalf)) / (1 / (1 / r->r + 1 / l1->r) + l2->r); /* 5.138 */ r->Jleftnew = l1->Jrightnew + l2->Jrightnew; /* 5.139 */ r->pleftnew = r->Jleftnew / r->Anew; /* 5.128 */ l1->prightnew = l1->Jrightnew / l1->Anew; /* 5.128 */ l2->prightnew = l2->Jrightnew / l2->Anew; /* 5.128 */ r->Kleftnew = onebytworho0 * r->pleftnew * r->pleftnew; /* 5.128 */ l1->Krightnew = onebytworho0 * l1->prightnew * l1->prightnew; /* 5.128 */ l2->Krightnew = onebytworho0 * l2->prightnew * l2->prightnew; /* 5.128 */ #if NO_BERNOULLI_EFFECT r->Kleftnew = l1->Krightnew = l2->Krightnew = 0; #endif r->Qleftnew = l1->Qrightnew = l2->Qrightnew = (r->eleft + l1->eright + l2->eright + twoc2Dt * (l1->Jhalf + l2->Jhalf - r->Jhalf) + r->Kleftnew * r->Vnew + l1->Krightnew * l1->Vnew + l2->Krightnew * l2->Vnew) / (r->Vnew + l1->Vnew + l2->Vnew); /* 5.137 */ } } /* Save some results. */ if (n == (oversampling + 1) / 2) { double out = 0.0; for (m = 1; m <= M; m ++) { Delta_Tube t = delta->tube + m; out += rho0 * t->Dx * t->Dz * t->dDydt * Dt * 1000; /* Radiation of wall movement, 5.140. */ if (t->right1 == NULL) out += t->Jrightnew - t->Jright; /* Radiation of open tube end. */ } result -> z [1] [sample] = out /= 4 * NUMpi * 0.4 * Dt; /* At 0.4 metres. */ if (iw1) w1 -> z [1] [sample] = delta->tube[iw1].Dy; if (iw2) w2 -> z [1] [sample] = delta->tube[iw2].Dy; if (iw3) w3 -> z [1] [sample] = delta->tube[iw3].Dy; if (ip1) p1 -> z [1] [sample] = delta->tube[ip1].DeltaP; if (ip2) p2 -> z [1] [sample] = delta->tube[ip2].DeltaP; if (ip3) p3 -> z [1] [sample] = delta->tube[ip3].DeltaP; if (iv1) v1 -> z [1] [sample] = delta->tube[iv1].v; if (iv2) v2 -> z [1] [sample] = delta->tube[iv2].v; if (iv3) v3 -> z [1] [sample] = delta->tube[iv3].v; } for (m = 1; m <= M; m ++) { Delta_Tube t = delta->tube + m; t->Jleft = t->Jleftnew; t->Jright = t->Jrightnew; t->Qleft = t->Qleftnew; t->Qright = t->Qrightnew; t->Dy = t->Dynew; t->dDydt = t->dDydtnew; t->A = t->Anew; t->Dx = t->Dxnew; t->dDxdt = t->dDxdtnew; t->eleft = t->eleftnew; t->eright = t->erightnew; #if MASS_LEAPFROG t->ehalfold = t->ehalf; #endif t->pleft = t->pleftnew; t->pright = t->prightnew; t->Kleft = t->Kleftnew; t->Kright = t->Krightnew; t->V = t->Vnew; t->Pturbright = t->Pturbrightnew; } } } totalVolume = 0.0; for (m = 1; m <= M; m ++) totalVolume += delta->tube [m]. V; //Melder_casual (U"Ending volume: ", totalVolume * 1000, U" litres."); if (out_w1) *out_w1 = w1.transfer(); if (out_w2) *out_w2 = w2.transfer(); if (out_w3) *out_w3 = w3.transfer(); if (out_p1) *out_p1 = p1.transfer(); if (out_p2) *out_p2 = p2.transfer(); if (out_p3) *out_p3 = p3.transfer(); if (out_v1) *out_v1 = v1.transfer(); if (out_v2) *out_v2 = v2.transfer(); if (out_v3) *out_v3 = v3.transfer(); return result.transfer(); } catch (MelderError) { Melder_throw (artword, U" & ", speaker, U": articulatory synthesis not performed."); } }