static void menu_cb_addPointAtCursor (RealTierEditor me, EDITOR_ARGS_DIRECT) { if (NUMdefined (my v_minimumLegalValue ()) && my ycursor < my v_minimumLegalValue ()) Melder_throw (U"Cannot add a point below ", my v_minimumLegalValue (), my v_rightTickUnits (), U"."); if (NUMdefined (my v_maximumLegalValue ()) && my ycursor > my v_maximumLegalValue ()) Melder_throw (U"Cannot add a point above ", my v_maximumLegalValue (), my v_rightTickUnits (), U"."); Editor_save (me, U"Add point"); RealTier_addPoint ((RealTier) my data, 0.5 * (my d_startSelection + my d_endSelection), my ycursor); RealTierEditor_updateScaling (me); FunctionEditor_redraw (me); Editor_broadcastDataChanged (me); }
static double Sound_findExtremum (Sound me, double tmin, double tmax, int includeMaxima, int includeMinima) { long imin = Sampled_xToLowIndex (me, tmin), imax = Sampled_xToHighIndex (me, tmax); double iextremum; Melder_assert (NUMdefined (tmin)); Melder_assert (NUMdefined (tmax)); if (imin < 1) imin = 1; if (imax > my nx) imax = my nx; iextremum = findExtremum_3 (my z [1], my ny > 1 ? my z [2] : NULL, imin - 1, imax - imin + 1, includeMaxima, includeMinima); if (iextremum) return my x1 + (imin - 1 + iextremum - 1) * my dx; else return (tmin + tmax) / 2; }
static void menu_cb_MoveCursorToZero (SoundEditor me, EDITOR_ARGS_DIRECT) { double zero = Sound_getNearestZeroCrossing ((Sound) my data, 0.5 * (my d_startSelection + my d_endSelection), 1); // STEREO BUG if (NUMdefined (zero)) { my d_startSelection = my d_endSelection = zero; FunctionEditor_marksChanged (me, true); } }
int SoundEditor::menu_cb_MoveCursorToZero (EDITOR_ARGS) { SoundEditor *editor = (SoundEditor *)editor_me; double zero = Sound_getNearestZeroCrossing ((Sound) editor->_data, 0.5 * (editor->_startSelection + editor->_endSelection), 1); // STEREO BUG if (NUMdefined (zero)) { editor->_startSelection = editor->_endSelection = zero; editor->marksChanged (); } return 1; }
static bool PointProcess_isPeriod (PointProcess me, long ileft, double minimumPeriod, double maximumPeriod, double maximumPeriodFactor) { /* * This function answers the question: is the interval from point 'ileft' to point 'ileft+1' a period? */ long iright = ileft + 1; /* * Period condition 1: both 'ileft' and 'iright' have to be within the point process. */ if (ileft < 1 || iright > my nt) { return false; } else { /* * Period condition 2: the interval has to be within the boundaries, if specified. */ if (minimumPeriod == maximumPeriod) { return true; // all intervals count as periods, irrespective of absolute size and relative size } else { double interval = my t [iright] - my t [ileft]; if (interval <= 0.0 || interval < minimumPeriod || interval > maximumPeriod) { return false; } else if (! NUMdefined (maximumPeriodFactor) || maximumPeriodFactor < 1.0) { return true; } else { /* * Period condition 3: the interval cannot be too different from both of its neigbours, if any. */ double previousInterval = ileft <= 1 ? NUMundefined : my t [ileft] - my t [ileft - 1]; double nextInterval = iright >= my nt ? NUMundefined : my t [iright + 1] - my t [iright]; double previousIntervalFactor = NUMdefined (previousInterval) && previousInterval > 0.0 ? interval / previousInterval : NUMundefined; double nextIntervalFactor = NUMdefined (nextInterval) && nextInterval > 0.0 ? interval / nextInterval : NUMundefined; if (! NUMdefined (previousIntervalFactor) && ! NUMdefined (nextIntervalFactor)) { return true; // no neighbours: this is a period } if (NUMdefined (previousIntervalFactor) && previousIntervalFactor > 0.0 && previousIntervalFactor < 1.0) { previousIntervalFactor = 1.0 / previousIntervalFactor; } if (NUMdefined (nextIntervalFactor) && nextIntervalFactor > 0.0 && nextIntervalFactor < 1.0) { nextIntervalFactor = 1.0 / nextIntervalFactor; } if (NUMdefined (previousIntervalFactor) && previousIntervalFactor > maximumPeriodFactor && NUMdefined (nextIntervalFactor) && nextIntervalFactor > maximumPeriodFactor) { return false; } } } } return true; }
// xmin, xmax in hz versus bark/mel or lin void BandFilterSpectrogram_drawFrequencyScale (BandFilterSpectrogram me, Graphics g, double xmin, double xmax, double ymin, double ymax, int garnish) { if (xmin < 0 || xmax < 0 || ymin < 0 || ymax < 0) { Melder_warning (U"Frequencies must be >= 0."); return; } // scale is in hertz if (xmin >= xmax) { // autoscaling xmin = 0; xmax = my v_frequencyToHertz (my ymax); } if (ymin >= ymax) { // autoscaling ymin = my ymin; ymax = my ymax; } long n = 2000; Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); double dx = (xmax - xmin) / (n - 1); double x1 = xmin, y1 = my v_hertzToFrequency (x1); for (long i = 2; i <= n; i++) { double x2 = x1 + dx, y2 = my v_hertzToFrequency (x2); if (NUMdefined (y1) && NUMdefined (y2)) { double xo1, yo1, xo2, yo2; if (NUMclipLineWithinRectangle (x1, y1, x2, y2, xmin, ymin, xmax, ymax, &xo1, &yo1, &xo2, &yo2)) { Graphics_line (g, xo1, yo1, xo2, yo2); } } x1 = x2; y1 = y2; } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_marksLeft (g, 2, 1, 1, 0); Graphics_textLeft (g, 1, Melder_cat (U"Frequency (", my v_getFrequencyUnit (), U")")); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_textBottom (g, 1, U"Frequency (Hz)"); } }
static void menu_cb_MoveEtoZero (SoundEditor me, EDITOR_ARGS_DIRECT) { double zero = Sound_getNearestZeroCrossing ((Sound) my data, my d_endSelection, 1); // STEREO BUG if (NUMdefined (zero)) { my d_endSelection = zero; if (my d_startSelection > my d_endSelection) { double dummy = my d_startSelection; my d_startSelection = my d_endSelection; my d_endSelection = dummy; } FunctionEditor_marksChanged (me, true); } }
int SoundEditor::menu_cb_MoveEtoZero (EDITOR_ARGS) { SoundEditor *editor = (SoundEditor *)editor_me; double zero = Sound_getNearestZeroCrossing ((Sound) editor->_data, editor->_endSelection, 1); // STEREO BUG if (NUMdefined (zero)) { editor->_endSelection = zero; if (editor->_startSelection > editor->_endSelection) { double dummy = editor->_startSelection; editor->_startSelection = editor->_endSelection; editor->_endSelection = dummy; } editor->marksChanged (); } return 1; }
autoAmplitudeTier PointProcess_Sound_to_AmplitudeTier_point (PointProcess me, Sound thee) { try { long imin, imax, numberOfPeaks = PointProcess_getWindowPoints (me, my xmin, my xmax, & imin, & imax); if (numberOfPeaks < 3) return nullptr; autoAmplitudeTier him = AmplitudeTier_create (my xmin, my xmax); for (long i = imin; i <= imax; i ++) { double value = Vector_getValueAtX (thee, my t [i], Vector_CHANNEL_AVERAGE, Vector_VALUE_INTERPOLATION_SINC700); if (NUMdefined (value)) RealTier_addPoint (him.peek(), my t [i], value); } return him; } catch (MelderError) { Melder_throw (me, U" & ", thee, U": not converted to AmplitudeTier."); } }
void Sound_FormantGrid_filter_inline (Sound me, FormantGrid formantGrid) { double dt = my dx; if (formantGrid -> formants -> size && formantGrid -> bandwidths -> size) for (long iformant = 1; iformant <= formantGrid -> formants -> size; iformant ++) { RealTier formantTier = (RealTier) formantGrid -> formants -> item [iformant]; RealTier bandwidthTier = (RealTier) formantGrid -> bandwidths -> item [iformant]; for (long isamp = 1; isamp <= my nx; isamp ++) { double t = my x1 + (isamp - 1) * my dx; /* * Compute LP coefficients. */ double formant, bandwidth; formant = RealTier_getValueAtTime (formantTier, t); bandwidth = RealTier_getValueAtTime (bandwidthTier, t); if (NUMdefined (formant) && NUMdefined (bandwidth)) { double cosomdt = cos (2 * NUMpi * formant * dt); double r = exp (- NUMpi * bandwidth * dt); /* Formants at 0 Hz or the Nyquist are single poles, others are double poles. */ if (fabs (cosomdt) > 0.999999) { /* Allow for round-off errors. */ /* single pole: D(z) = 1 - r z^-1 */ for (long channel = 1; channel <= my ny; channel ++) { if (isamp > 1) my z [channel] [isamp] += r * my z [channel] [isamp - 1]; } } else { /* double pole: D(z) = 1 + p z^-1 + q z^-2 */ double p = - 2 * r * cosomdt; double q = r * r; for (long channel = 1; channel <= my ny; channel ++) { if (isamp > 1) my z [channel] [isamp] -= p * my z [channel] [isamp - 1]; if (isamp > 2) my z [channel] [isamp] -= q * my z [channel] [isamp - 2]; } } } } } }
double structVector :: v_getValueAtSample (long isamp, long ilevel, int unit) { // Preconditions: // 1 <= isamp <= my nx // 0 <= ilevel <= my ny double value; if (ilevel > Vector_CHANNEL_AVERAGE) { value = z [ilevel] [isamp]; } else if (ny == 1) { value = z [1] [isamp]; // optimization } else if (ny == 2) { value = 0.5 * (z [1] [isamp] + z [2] [isamp]); // optimization } else { double sum = 0.0; for (long channel = 1; channel <= ny; channel ++) { sum += z [channel] [isamp]; } value = sum / ny; } return NUMdefined (value) ? v_convertStandardToSpecialUnit (value, ilevel, unit) : NUMundefined; }
double Sampled_getQuantile (I, double xmin, double xmax, double quantile, long ilevel, int unit) { iam (Sampled); long i, imin, imax, numberOfDefinedSamples = 0; double *values = NUMdvector (1, my nx), result = NUMundefined; iferror return NUMundefined; Function_unidirectionalAutowindow (me, & xmin, & xmax); if (! Function_intersectRangeWithDomain (me, & xmin, & xmax)) return NUMundefined; Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax); for (i = imin; i <= imax; i ++) { double value = our getValueAtSample (me, i, ilevel, unit); if (NUMdefined (value)) { values [++ numberOfDefinedSamples] = value; } } if (numberOfDefinedSamples >= 1) { NUMsort_d (numberOfDefinedSamples, values); result = NUMquantile (numberOfDefinedSamples, values, quantile); } NUMdvector_free (values, 1); return result; }
void Pitch_Intensity_draw (Pitch pitch, Intensity intensity, Graphics g, double f1, double f2, double s1, double s2, int garnish, int connect) { if (f2 <= f1) Pitch_getExtrema (pitch, & f1, & f2); if (f1 == 0.0) return; /* All voiceless. */ if (f1 == f2) { f1 -= 1.0; f2 += 1.0; } if (s2 <= s1) Matrix_getWindowExtrema (intensity, 0, 0, 1, 1, & s1, & s2); if (s1 == s2) { s1 -= 1.0; s2 += 1.0; } Graphics_setWindow (g, f1, f2, s1, s2); Graphics_setInner (g); long previousI = 0; double previousX = NUMundefined, previousY = NUMundefined; for (long i = 1; i <= pitch -> nx; i ++) { double t = Sampled_indexToX (pitch, i); double x = pitch -> frame [i]. candidate [1]. frequency; double y = Sampled_getValueAtX (intensity, t, Pitch_LEVEL_FREQUENCY, kPitch_unit_HERTZ, TRUE); if (x == 0) { continue; /* Voiceless. */ } if (connect & 1) Graphics_speckle (g, x, y); if ((connect & 2) && NUMdefined (previousX)) { if (previousI >= 1 && previousI < i - 1) { Graphics_setLineType (g, Graphics_DOTTED); } Graphics_line (g, previousX, previousY, x, y); Graphics_setLineType (g, Graphics_DRAWN); } previousX = x; previousY = y; previousI = i; } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_textBottom (g, 1, L"Fundamental frequency (Hz)"); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_textLeft (g, 1, L"Intensity (dB)"); Graphics_marksLeft (g, 2, 1, 1, 0); } }
static void Sampled_speckleInside (Sampled me, Graphics g, double xmin, double xmax, double ymin, double ymax, double speckle_mm, long ilevel, int unit) { Function_unidirectionalAutowindow (me, & xmin, & xmax); long ixmin, ixmax; Sampled_getWindowSamples (me, xmin, xmax, & ixmin, & ixmax); if (Function_isUnitLogarithmic (me, ilevel, unit)) { ymin = Function_convertStandardToSpecialUnit (me, ymin, ilevel, unit); ymax = Function_convertStandardToSpecialUnit (me, ymax, ilevel, unit); } if (ymax <= ymin) return; Graphics_setWindow (g, xmin, xmax, ymin, ymax); for (long ix = ixmin; ix <= ixmax; ix ++) { double value = Sampled_getValueAtSample (me, ix, ilevel, unit); if (NUMdefined (value)) { double x = Sampled_indexToX (me, ix); if (value >= ymin && value <= ymax) { Graphics_fillCircle_mm (g, x, value, speckle_mm); } } } }
double Sampled_getQuantile (Sampled me, double xmin, double xmax, double quantile, long ilevel, int unit) { try { autoNUMvector <double> values (1, my nx); Function_unidirectionalAutowindow (me, & xmin, & xmax); if (! Function_intersectRangeWithDomain (me, & xmin, & xmax)) return NUMundefined; long imin, imax, numberOfDefinedSamples = 0; Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax); for (long i = imin; i <= imax; i ++) { double value = my v_getValueAtSample (i, ilevel, unit); if (NUMdefined (value)) { values [++ numberOfDefinedSamples] = value; } } double result = NUMundefined; if (numberOfDefinedSamples >= 1) { NUMsort_d (numberOfDefinedSamples, values.peek()); result = NUMquantile (numberOfDefinedSamples, values.peek(), quantile); } return result; } catch (MelderError) { Melder_throw (me, ": quantile not computed."); } }
autoAmplitudeTier PointProcess_Sound_to_AmplitudeTier_period (PointProcess me, Sound thee, double tmin, double tmax, double pmin, double pmax, double maximumPeriodFactor) { try { if (tmax <= tmin) tmin = my xmin, tmax = my xmax; long imin, imax; long numberOfPeaks = PointProcess_getWindowPoints (me, tmin, tmax, & imin, & imax); if (numberOfPeaks < 3) Melder_throw (U"Too few pulses between ", tmin, U" and ", tmax, U" seconds."); autoAmplitudeTier him = AmplitudeTier_create (tmin, tmax); for (long i = imin + 1; i < imax; i ++) { double p1 = my t [i] - my t [i - 1], p2 = my t [i + 1] - my t [i]; double intervalFactor = p1 > p2 ? p1 / p2 : p2 / p1; if (pmin == pmax || (p1 >= pmin && p1 <= pmax && p2 >= pmin && p2 <= pmax && intervalFactor <= maximumPeriodFactor)) { double peak = Sound_getHannWindowedRms (thee, my t [i], 0.2 * p1, 0.2 * p2); if (NUMdefined (peak) && peak > 0.0) RealTier_addPoint (him.peek(), my t [i], peak); } } return him; } catch (MelderError) { Melder_throw (me, U" & ", thee, U": not converted to AmplitudeTier."); } }
void structPitchEditor :: v_draw () { Pitch pitch = (Pitch) our data; long it, it1, it2; double dyUnv, dyIntens; Graphics_setWindow (our d_graphics, 0, 1, 0, 1); Graphics_setColour (our d_graphics, Graphics_WHITE); Graphics_fillRectangle (our d_graphics, 0, 1, 0, 1); Graphics_setColour (our d_graphics, Graphics_BLACK); Graphics_rectangle (our d_graphics, 0, 1, 0, 1); dyUnv = Graphics_dyMMtoWC (our d_graphics, HEIGHT_UNV); dyIntens = Graphics_dyMMtoWC (our d_graphics, HEIGHT_INTENS); Sampled_getWindowSamples (pitch, our d_startWindow, our d_endWindow, & it1, & it2); /* * Show pitch. */ { long df = pitch -> ceiling > 10000 ? 2000 : pitch -> ceiling > 5000 ? 1000 : pitch -> ceiling > 2000 ? 500 : pitch -> ceiling > 800 ? 200 : pitch -> ceiling > 400 ? 100 : 50; double radius; Graphics_Viewport previous; previous = Graphics_insetViewport (our d_graphics, 0, 1, dyUnv, 1 - dyIntens); Graphics_setWindow (our d_graphics, our d_startWindow, our d_endWindow, 0, pitch -> ceiling); radius = Graphics_dxMMtoWC (our d_graphics, RADIUS); /* Horizontal hair at current pitch. */ if (our d_startSelection == our d_endSelection && our d_startSelection >= our d_startWindow && our d_startSelection <= our d_endWindow) { double f = Pitch_getValueAtTime (pitch, our d_startSelection, kPitch_unit_HERTZ, Pitch_LINEAR); if (NUMdefined (f)) { Graphics_setColour (our d_graphics, Graphics_RED); Graphics_line (our d_graphics, our d_startWindow - radius, f, our d_endWindow, f); Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF); Graphics_text1 (our d_graphics, our d_startWindow - radius, f, Melder_fixed (f, 2)); } } /* Horizontal scaling lines. */ Graphics_setColour (our d_graphics, Graphics_BLUE); Graphics_setLineType (our d_graphics, Graphics_DOTTED); Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF); for (long f = df; f <= pitch -> ceiling; f += df) { Graphics_line (our d_graphics, our d_startWindow, f, our d_endWindow, f); Graphics_text2 (our d_graphics, our d_endWindow + radius/2, f, Melder_integer (f), L" Hz"); } Graphics_setLineType (our d_graphics, Graphics_DRAWN); /* Show candidates. */ for (it = it1; it <= it2; it ++) { Pitch_Frame frame = & pitch -> frame [it]; double t = Sampled_indexToX (pitch, it); double f = frame -> candidate [1]. frequency; if (f > 0.0 && f < pitch -> ceiling) { Graphics_setColour (our d_graphics, Graphics_MAGENTA); Graphics_fillCircle_mm (our d_graphics, t, f, RADIUS * 2); } Graphics_setColour (our d_graphics, Graphics_BLACK); Graphics_setTextAlignment (our d_graphics, Graphics_CENTRE, Graphics_HALF); for (int icand = 1; icand <= frame -> nCandidates; icand ++) { int strength = (int) floor (10 * frame -> candidate [icand]. strength + 0.5); f = frame -> candidate [icand]. frequency; if (strength > 9) strength = 9; if (f > 0 && f <= pitch -> ceiling) Graphics_text1 (our d_graphics, t, f, Melder_integer (strength)); } } Graphics_resetViewport (our d_graphics, previous); } /* * Show intensity. */ { Graphics_Viewport previous = Graphics_insetViewport (our d_graphics, 0, 1, 1 - dyIntens, 1); Graphics_setWindow (our d_graphics, our d_startWindow, our d_endWindow, 0, 1); Graphics_setColour (our d_graphics, Graphics_BLACK); Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF); Graphics_text (our d_graphics, our d_startWindow, 0.5, L"intens"); Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF); Graphics_text (our d_graphics, our d_endWindow, 0.5, L"intens"); Graphics_setTextAlignment (our d_graphics, Graphics_CENTRE, Graphics_HALF); for (it = it1; it <= it2; it ++) { Pitch_Frame frame = & pitch -> frame [it]; double t = Sampled_indexToX (pitch, it); int strength = (int) floor (10 * frame -> intensity + 0.5); // map 0.0-1.0 to 0-9 if (strength > 9) strength = 9; Graphics_text1 (our d_graphics, t, 0.5, Melder_integer (strength)); } Graphics_resetViewport (our d_graphics, previous); } if (it1 > 1) it1 -= 1; if (it2 < pitch -> nx) it2 += 1; /* * Show voicelessness. */ { Graphics_Viewport previous = Graphics_insetViewport (our d_graphics, 0, 1, 0, dyUnv); Graphics_setColour (our d_graphics, Graphics_BLUE); Graphics_line (our d_graphics, our d_startWindow, 1, our d_endWindow, 1); Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF); Graphics_text (our d_graphics, our d_startWindow, 0.5, L"Unv"); Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF); Graphics_text (our d_graphics, our d_endWindow, 0.5, L"Unv"); for (it = it1; it <= it2; it ++) { Pitch_Frame frame = & pitch -> frame [it]; double t = Sampled_indexToX (pitch, it), tleft = t - 0.5 * pitch -> dx, tright = t + 0.5 * pitch -> dx; double f = frame -> candidate [1]. frequency; if ((f > 0.0 && f < pitch -> ceiling) || tright <= our d_startWindow || tleft >= our d_endWindow) continue; if (tleft < our d_startWindow) tleft = our d_startWindow; if (tright > our d_endWindow) tright = our d_endWindow; Graphics_fillRectangle (our d_graphics, tleft, tright, 0, 1); } Graphics_setColour (our d_graphics, Graphics_BLACK); Graphics_resetViewport (our d_graphics, previous); } }
static autoIntensity Sound_to_Intensity_ (Sound me, double minimumPitch, double timeStep, int subtractMeanPressure) { try { /* * Preconditions. */ if (! NUMdefined (minimumPitch)) Melder_throw (U"(Sound-to-Intensity:) Minimum pitch undefined."); if (! NUMdefined (timeStep)) Melder_throw (U"(Sound-to-Intensity:) Time step undefined."); if (timeStep < 0.0) Melder_throw (U"(Sound-to-Intensity:) Time step should be zero or positive instead of ", timeStep, U"."); if (my dx <= 0.0) Melder_throw (U"(Sound-to-Intensity:) The Sound's time step should be positive."); if (minimumPitch <= 0.0) Melder_throw (U"(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 = (long) floor (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 (U"The duration of the sound in an intensity analysis should be at least 6.4 divided by the minimum pitch (", minimumPitch, U" Hz), " U"i.e. at least ", 6.4 / minimumPitch, U" s, instead of ", my xmax - my xmin, U" 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; intensity /= 4e-10; thy z [1] [iframe] = intensity < 1e-30 ? -300 : 10 * log10 (intensity); } return thee; } catch (MelderError) { Melder_throw (me, U": intensity analysis not performed."); } }
double Sound_getPowerInAir (Sound me) { long n; double sum2 = getSumOfSquares (me, 0, 0, & n); return NUMdefined (sum2) ? sum2 / (n * my ny) / 400 : NUMundefined; }
void Sampled_getMaximumAndX (Sampled me, double xmin, double xmax, long ilevel, int unit, int interpolate, double *return_maximum, double *return_xOfMaximum) { long imin, imax, i; double maximum = -1e301, xOfMaximum = 0.0; if (xmin == NUMundefined || xmax == NUMundefined) { maximum = xOfMaximum = NUMundefined; goto end; } Function_unidirectionalAutowindow (me, & xmin, & xmax); if (! Function_intersectRangeWithDomain (me, & xmin, & xmax)) { maximum = xOfMaximum = NUMundefined; // requested range and logical domain do not intersect goto end; } if (! Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax)) { /* * No sample centres between tmin and tmax. * Try to return the greater of the values at these two points. */ double fleft = Sampled_getValueAtX (me, xmin, ilevel, unit, interpolate); double fright = Sampled_getValueAtX (me, xmax, ilevel, unit, interpolate); if (NUMdefined (fleft) && fleft > maximum) maximum = fleft, xOfMaximum = xmin; if (NUMdefined (fright) && fright > maximum) maximum = fright, xOfMaximum = xmax; } else { for (i = imin; i <= imax; i ++) { double fmid = my v_getValueAtSample (i, ilevel, unit); if (fmid == NUMundefined) continue; if (interpolate == FALSE) { if (fmid > maximum) maximum = fmid, xOfMaximum = i; } else { /* * Try an interpolation, possibly even taking into account a sample just outside the selection. */ double fleft = i <= 1 ? NUMundefined : my v_getValueAtSample (i - 1, ilevel, unit); double fright = i >= my nx ? NUMundefined : my v_getValueAtSample (i + 1, ilevel, unit); if (fleft == NUMundefined || fright == NUMundefined) { if (fmid > maximum) maximum = fmid, xOfMaximum = i; } else if (fmid > fleft && fmid >= fright) { double y [4], i_real, localMaximum; y [1] = fleft, y [2] = fmid, y [3] = fright; localMaximum = NUMimproveMaximum (y, 3, 2, NUM_PEAK_INTERPOLATE_PARABOLIC, & i_real); if (localMaximum > maximum) maximum = localMaximum, xOfMaximum = i_real + i - 2; } } } xOfMaximum = my x1 + (xOfMaximum - 1) * my dx; /* From index plus phase to time. */ /* Check boundary values. */ if (interpolate) { double fleft = Sampled_getValueAtX (me, xmin, ilevel, unit, TRUE); double fright = Sampled_getValueAtX (me, xmax, ilevel, unit, TRUE); if (NUMdefined (fleft) && fleft > maximum) maximum = fleft, xOfMaximum = xmin; if (NUMdefined (fright) && fright > maximum) maximum = fright, xOfMaximum = xmax; } if (xOfMaximum < xmin) xOfMaximum = xmin; if (xOfMaximum > xmax) xOfMaximum = xmax; } if (maximum == -1e301) maximum = xOfMaximum = NUMundefined; end: if (return_maximum) *return_maximum = maximum; if (return_xOfMaximum) *return_xOfMaximum = xOfMaximum; }
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 Sampled_drawInside (Sampled me, Graphics g, double xmin, double xmax, double ymin, double ymax, double speckle_mm, long ilevel, int unit) { try { if (speckle_mm != 0.0) { Sampled_speckleInside (me, g, xmin, xmax, ymin, ymax, speckle_mm, ilevel, unit); return; } Function_unidirectionalAutowindow (me, & xmin, & xmax); long ixmin, ixmax, startOfDefinedStretch = -1; Sampled_getWindowSamples (me, xmin, xmax, & ixmin, & ixmax); if (Function_isUnitLogarithmic (me, ilevel, unit)) { ymin = Function_convertStandardToSpecialUnit (me, ymin, ilevel, unit); ymax = Function_convertStandardToSpecialUnit (me, ymax, ilevel, unit); } if (ymax <= ymin) return; Graphics_setWindow (g, xmin, xmax, ymin, ymax); autoNUMvector <double> xarray (ixmin - 1, ixmax + 1); autoNUMvector <double> yarray (ixmin - 1, ixmax + 1); double previousValue = Sampled_getValueAtSample (me, ixmin - 1, ilevel, unit); if (NUMdefined (previousValue)) { startOfDefinedStretch = ixmin - 1; xarray [ixmin - 1] = Sampled_indexToX (me, ixmin - 1); yarray [ixmin - 1] = previousValue; } for (long ix = ixmin; ix <= ixmax; ix ++) { double x = Sampled_indexToX (me, ix), value = Sampled_getValueAtSample (me, ix, ilevel, unit); if (NUMdefined (value)) { if (NUMdefined (previousValue)) { xarray [ix] = x; yarray [ix] = value; } else { startOfDefinedStretch = ix - 1; xarray [ix - 1] = x - 0.5 * my dx; yarray [ix - 1] = value; xarray [ix] = x; yarray [ix] = value; } } else if (NUMdefined (previousValue)) { Melder_assert (startOfDefinedStretch >= ixmin - 1); if (ix > ixmin) { xarray [ix] = x - 0.5 * my dx; yarray [ix] = previousValue; if (xarray [startOfDefinedStretch] < xmin) { double phase = (xmin - xarray [startOfDefinedStretch]) / my dx; xarray [startOfDefinedStretch] = xmin; yarray [startOfDefinedStretch] = phase * yarray [startOfDefinedStretch + 1] + (1.0 - phase) * yarray [startOfDefinedStretch]; } Graphics_polyline (g, ix + 1 - startOfDefinedStretch, & xarray [startOfDefinedStretch], & yarray [startOfDefinedStretch]); } startOfDefinedStretch = -1; } previousValue = value; } if (startOfDefinedStretch > -1) { double x = Sampled_indexToX (me, ixmax + 1), value = Sampled_getValueAtSample (me, ixmax + 1, ilevel, unit); Melder_assert (NUMdefined (previousValue)); if (NUMdefined (value)) { xarray [ixmax + 1] = x; yarray [ixmax + 1] = value; } else { xarray [ixmax + 1] = x - 0.5 * my dx; yarray [ixmax + 1] = previousValue; } if (xarray [startOfDefinedStretch] < xmin) { double phase = (xmin - xarray [startOfDefinedStretch]) / my dx; xarray [startOfDefinedStretch] = xmin; yarray [startOfDefinedStretch] = phase * yarray [startOfDefinedStretch + 1] + (1.0 - phase) * yarray [startOfDefinedStretch]; } if (xarray [ixmax + 1] > xmax) { double phase = (xarray [ixmax + 1] - xmax) / my dx; xarray [ixmax + 1] = xmax; yarray [ixmax + 1] = phase * yarray [ixmax] + (1.0 - phase) * yarray [ixmax + 1]; } Graphics_polyline (g, ixmax + 2 - startOfDefinedStretch, & xarray [startOfDefinedStretch], & yarray [startOfDefinedStretch]); } } catch (MelderError) { Melder_clearError (); } }
bool Pitch_isVoiced_i (Pitch me, long iframe) { return NUMdefined (Sampled_getValueAtSample (me, iframe, Pitch_LEVEL_FREQUENCY, kPitch_unit_HERTZ)); }
void BarkSpectrogram_drawSekeyHansonFilterFunctions (BarkSpectrogram me, Graphics g, bool xIsHertz, int fromFilter, int toFilter, double zmin, double zmax, bool yscale_dB, double ymin, double ymax, int garnish) { double xmin = zmin, xmax = zmax; if (zmin >= zmax) { zmin = my ymin; zmax = my ymax; xmin = xIsHertz ? my v_frequencyToHertz (zmin) : zmin; xmax = xIsHertz ? my v_frequencyToHertz (zmax) : zmax; } if (xIsHertz) { zmin = my v_hertzToFrequency (xmin); zmax = my v_hertzToFrequency (xmax); } if (ymin >= ymax) { ymin = yscale_dB ? -60 : 0; ymax = yscale_dB ? 0 : 1; } fromFilter = fromFilter <= 0 ? 1 : fromFilter; toFilter = toFilter <= 0 || toFilter > my ny ? my ny : toFilter; if (fromFilter > toFilter) { fromFilter = 1; toFilter = my ny; } long n = xIsHertz ? 1000 : 500; autoNUMvector<double> xz (1, n), xhz (1,n), y (1, n); Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); double dz = (zmax - zmin) / (n - 1); for (long iz = 1; iz <= n; iz++) { double f = zmin + (iz - 1) * dz; xz[iz] = f; xhz[iz] = my v_frequencyToHertz (f); // just in case we need the linear scale } for (long ifilter = fromFilter; ifilter <= toFilter; ifilter++) { double zMid = Matrix_rowToY (me, ifilter); for (long iz = 1; iz <= n; iz++) { double z = xz[iz] - (zMid - 0.215); double amp = 7 - 7.5 * z - 17.5 * sqrt (0.196 + z * z); y[iz] = yscale_dB ? amp : pow (10, amp / 10); } // the drawing double x1 = xIsHertz ? xhz[1] : xz[1], y1 = y[1]; for (long iz = 2; iz <= n; iz++) { double x2 = xIsHertz ? xhz[iz] : xz[iz], y2 = y[iz]; if (NUMdefined (x1) && NUMdefined (x2)) { double xo1, yo1, xo2, yo2; if (NUMclipLineWithinRectangle (x1, y1, x2, y2, xmin, ymin, xmax, ymax, &xo1, &yo1, &xo2, &yo2)) { Graphics_line (g, xo1, yo1, xo2, yo2); } } x1 = x2; y1 = y2; } } Graphics_unsetInner (g); if (garnish) { double distance = yscale_dB ? 10 : 0.5; Graphics_drawInnerBox (g); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_marksLeftEvery (g, 1, distance, 1, 1, 0); Graphics_textLeft (g, 1, yscale_dB ? U"Amplitude (dB)" : U"Amplitude"); Graphics_textBottom (g, 1, Melder_cat (U"Frequency (", xIsHertz ? U"Hz" : my v_getFrequencyUnit (), U")")); } }
bool Pitch_isVoiced_t (Pitch me, double time) { return NUMdefined (Sampled_getValueAtX (me, time, Pitch_LEVEL_FREQUENCY, kPitch_unit_HERTZ, false)); }
void MelSpectrogram_drawTriangularFilterFunctions (MelSpectrogram me, Graphics g, bool xIsHertz, int fromFilter, int toFilter, double zmin, double zmax, bool yscale_dB, double ymin, double ymax, int garnish) { double xmin = zmin, xmax = zmax; if (zmin >= zmax) { zmin = my ymin; zmax = my ymax; // mel xmin = xIsHertz ? my v_frequencyToHertz (zmin) : zmin; xmax = xIsHertz ? my v_frequencyToHertz (zmax) : zmax; } if (xIsHertz) { zmin = my v_hertzToFrequency (xmin); zmax = my v_hertzToFrequency (xmax); } if (ymin >= ymax) { ymin = yscale_dB ? -60 : 0; ymax = yscale_dB ? 0 : 1; } fromFilter = fromFilter <= 0 ? 1 : fromFilter; toFilter = toFilter <= 0 || toFilter > my ny ? my ny : toFilter; if (fromFilter > toFilter) { fromFilter = 1; toFilter = my ny; } long n = xIsHertz ? 1000 : 500; autoNUMvector<double> xz (1, n), xhz (1,n), y (1, n); Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); double dz = (zmax - zmin) / (n - 1); for (long iz = 1; iz <= n; iz++) { double f = zmin + (iz - 1) * dz; xz[iz] = f; xhz[iz] = my v_frequencyToHertz (f); // just in case we need the linear scale } for (long ifilter = fromFilter; ifilter <= toFilter; ifilter++) { double zc = Matrix_rowToY (me, ifilter), zl = zc - my dy, zh = zc + my dy; double xo1, yo1, xo2, yo2; if (yscale_dB) { for (long iz = 1; iz <= n; iz++) { double z = xz[iz]; double amp = NUMtriangularfilter_amplitude (zl, zc, zh, z); y[iz] = yscale_dB ? (amp > 0 ? 20 * log10 (amp) : ymin - 10) : amp; } double x1 = xIsHertz ? xhz[1] : xz[1], y1 = y[1]; if (NUMdefined (y1)) { for (long iz = 1; iz <= n; iz++) { double x2 = xIsHertz ? xhz[iz] : xz[iz], y2 = y[iz]; if (NUMdefined (y2)) { if (NUMclipLineWithinRectangle (x1, y1, x2, y2, xmin, ymin, xmax, ymax, &xo1, &yo1, &xo2, &yo2)) { Graphics_line (g, xo1, yo1, xo2, yo2); } } x1 = x2; y1 = y2; } } } else { double x1 = xIsHertz ? my v_frequencyToHertz (zl) : zl; double x2 = xIsHertz ? my v_frequencyToHertz (zc) : zc; if (NUMclipLineWithinRectangle (x1, 0, x2, 1, xmin, ymin, xmax, ymax, &xo1, &yo1, &xo2, &yo2)) { Graphics_line (g, xo1, yo1, xo2, yo2); } double x3 = xIsHertz ? my v_frequencyToHertz (zh) : zh; if (NUMclipLineWithinRectangle (x2, 1, x3, 0, xmin, ymin, xmax, ymax, &xo1, &yo1, &xo2, &yo2)) { Graphics_line (g, xo1, yo1, xo2, yo2); } } } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_marksLeftEvery (g, 1, yscale_dB ? 10 : 0.5, 1, 1, 0); Graphics_textLeft (g, 1, yscale_dB ? U"Amplitude (dB)" : U"Amplitude"); Graphics_textBottom (g, 1, Melder_cat (U"Frequency (", ( xIsHertz ? U"Hz" : my v_getFrequencyUnit () ), U")")); } }
double Function_convertSpecialToStandardUnit (Function me, double value, long ilevel, int unit) { return NUMdefined (value) ? my v_convertSpecialToStandardUnit (value, ilevel, unit) : NUMundefined; }
static void Sampled_getSum2AndDefinitionRange (Sampled me, double xmin, double xmax, long ilevel, int unit, double mean, int interpolate, double *return_sum2, double *return_definitionRange) { /* This function computes the area under the linearly interpolated squared difference curve between xmin and xmax. Outside [x1-dx/2, xN+dx/2], the curve is undefined and neither times nor values are counted. In [x1-dx/2,x1] and [xN,xN+dx/2], the curve is linearly extrapolated. */ long imin, imax, isamp; double sum2 = 0.0, definitionRange = 0.0; Function_unidirectionalAutowindow (me, & xmin, & xmax); if (Function_intersectRangeWithDomain (me, & xmin, & xmax)) { if (interpolate) { if (Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax)) { double leftEdge = my x1 - 0.5 * my dx, rightEdge = leftEdge + my nx * my dx; for (isamp = imin; isamp <= imax; isamp ++) { double value = my v_getValueAtSample (isamp, ilevel, unit); // a fast way to integrate a linearly interpolated curve; works everywhere except at the edges if (NUMdefined (value)) { value -= mean; value *= value; definitionRange += 1.0; sum2 += value; } } /* * Corrections within the first and last sampling intervals. */ if (xmin > leftEdge) { // otherwise, constant extrapolation over 0.5 sample is OK double phase = (my x1 + (imin - 1) * my dx - xmin) / my dx; // this fraction of sampling interval is still to be determined double rightValue = Sampled_getValueAtSample (me, imin, ilevel, unit); double leftValue = Sampled_getValueAtSample (me, imin - 1, ilevel, unit); if (NUMdefined (rightValue)) { rightValue -= mean; rightValue *= rightValue; definitionRange -= 0.5; // delete constant extrapolation over 0.5 sample sum2 -= 0.5 * rightValue; if (NUMdefined (leftValue)) { leftValue -= mean; leftValue *= leftValue; definitionRange += phase; // add current fraction sum2 += phase * (rightValue + 0.5 * phase * (leftValue - rightValue)); // interpolate to outside sample } else { if (phase > 0.5) phase = 0.5; definitionRange += phase; // add current fraction, but never more than 0.5 sum2 += phase * rightValue; } } else if (NUMdefined (leftValue) && phase > 0.5) { leftValue -= mean; leftValue *= leftValue; definitionRange += phase - 0.5; sum2 += (phase - 0.5) * leftValue; } } if (xmax < rightEdge) { // otherwise, constant extrapolation is OK double phase = (xmax - (my x1 + (imax - 1) * my dx)) / my dx; // this fraction of sampling interval is still to be determined double leftValue = Sampled_getValueAtSample (me, imax, ilevel, unit); double rightValue = Sampled_getValueAtSample (me, imax + 1, ilevel, unit); if (NUMdefined (leftValue)) { leftValue -= mean; leftValue *= leftValue; definitionRange -= 0.5; // delete constant extrapolation over 0.5 sample sum2 -= 0.5 * leftValue; if (NUMdefined (rightValue)) { rightValue -= mean; rightValue *= rightValue; definitionRange += phase; // add current fraction sum2 += phase * (leftValue + 0.5 * phase * (rightValue - leftValue)); // interpolate to outside sample } else { if (phase > 0.5) phase = 0.5; definitionRange += phase; // add current fraction, but never more than 0.5 sum2 += phase * leftValue; } } else if (NUMdefined (rightValue) && phase > 0.5) { rightValue -= mean; rightValue *= rightValue; definitionRange += phase - 0.5; sum2 += (phase - 0.5) * rightValue; } } } else { // no sample centres between xmin and xmax /* * Try to return the mean of the interpolated values at these two points. * Thus, a small (xmin, xmax) range gives the same value as the (xmin+xmax)/2 point. */ double leftValue = Sampled_getValueAtSample (me, imax, ilevel, unit); double rightValue = Sampled_getValueAtSample (me, imin, ilevel, unit); double phase1 = (xmin - (my x1 + (imax - 1) * my dx)) / my dx; double phase2 = (xmax - (my x1 + (imax - 1) * my dx)) / my dx; if (imin == imax + 1) { // not too far from sample definition region if (NUMdefined (leftValue)) { leftValue -= mean; leftValue *= leftValue; if (NUMdefined (rightValue)) { rightValue -= mean; rightValue *= rightValue; definitionRange += phase2 - phase1; sum2 += (phase2 - phase1) * (leftValue + 0.5 * (phase1 + phase2) * (rightValue - leftValue)); } else if (phase1 < 0.5) { if (phase2 > 0.5) phase2 = 0.5; definitionRange += phase2 - phase1; sum2 += (phase2 - phase1) * leftValue; } } else if (NUMdefined (rightValue) && phase2 > 0.5) { rightValue -= mean; rightValue *= rightValue; if (phase1 < 0.5) phase1 = 0.5; definitionRange += phase2 - phase1; sum2 += (phase2 - phase1) * rightValue; } } } } else { // no interpolation double rimin = Sampled_xToIndex (me, xmin), rimax = Sampled_xToIndex (me, xmax); if (rimax >= 0.5 && rimin < my nx + 0.5) { imin = rimin < 0.5 ? 0 : (long) floor (rimin + 0.5); imax = rimax >= my nx + 0.5 ? my nx + 1 : (long) floor (rimax + 0.5); for (isamp = imin + 1; isamp < imax; isamp ++) { double value = my v_getValueAtSample (isamp, ilevel, unit); if (NUMdefined (value)) { value -= mean; value *= value; definitionRange += 1.0; sum2 += value; } } if (imin == imax) { double value = my v_getValueAtSample (imin, ilevel, unit); if (NUMdefined (value)) { double phase = rimax - rimin; value -= mean; value *= value; definitionRange += phase; sum2 += phase * value; } } else { if (imin >= 1) { double value = my v_getValueAtSample (imin, ilevel, unit); if (NUMdefined (value)) { double phase = imin - rimin + 0.5; value -= mean; value *= value; definitionRange += phase; sum2 += phase * value; } } if (imax <= my nx) { double value = my v_getValueAtSample (imax, ilevel, unit); if (NUMdefined (value)) { double phase = rimax - imax + 0.5; value -= mean; value *= value; definitionRange += phase; sum2 += phase * value; } } } } } } if (return_sum2) *return_sum2 = sum2; if (return_definitionRange) *return_definitionRange = definitionRange; }
double AmplitudeTier_getShimmer_dda (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) { double apq3 = AmplitudeTier_getShimmer_apq3 (me, pmin, pmax, maximumAmplitudeFactor); return NUMdefined (apq3) ? 3.0 * apq3 : NUMundefined; }
double Function_convertToNonlogarithmic (Function me, double value, long ilevel, int unit) { return NUMdefined (value) && my v_isUnitLogarithmic (ilevel, unit) ? pow (10.0, value) : value; }