void structPointEditor :: v_draw () { PointProcess point = (PointProcess) data; Sound sound = d_sound.data; Graphics_setColour (d_graphics, Graphics_WHITE); Graphics_setWindow (d_graphics, 0, 1, 0, 1); Graphics_fillRectangle (d_graphics, 0, 1, 0, 1); double minimum = -1.0, maximum = +1.0; if (sound != NULL && (d_sound.scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW || d_sound.scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW_AND_CHANNEL)) { long first, last; if (Sampled_getWindowSamples (sound, d_startWindow, d_endWindow, & first, & last) >= 1) { Matrix_getWindowExtrema (sound, first, last, 1, 1, & minimum, & maximum); } } Graphics_setWindow (d_graphics, d_startWindow, d_endWindow, minimum, maximum); Graphics_setColour (d_graphics, Graphics_BLACK); if (sound != NULL) { long first, last; if (Sampled_getWindowSamples (sound, d_startWindow, d_endWindow, & first, & last) > 1) { Graphics_setLineType (d_graphics, Graphics_DOTTED); Graphics_line (d_graphics, d_startWindow, 0.0, d_endWindow, 0.0); Graphics_setLineType (d_graphics, Graphics_DRAWN); Graphics_function (d_graphics, sound -> z [1], first, last, Sampled_indexToX (sound, first), Sampled_indexToX (sound, last)); } } Graphics_setColour (d_graphics, Graphics_BLUE); Graphics_setWindow (d_graphics, d_startWindow, d_endWindow, -1.0, +1.0); for (long i = 1; i <= point -> nt; i ++) { double t = point -> t [i]; if (t >= d_startWindow && t <= d_endWindow) Graphics_line (d_graphics, t, -0.9, t, +0.9); } Graphics_setColour (d_graphics, Graphics_BLACK); v_updateMenuItems_file (); }
static void cellArrayOrImage (Matrix me, Graphics g, double xmin, double xmax, double ymin, double ymax, double minimum, double maximum, bool interpolate) { if (xmax <= xmin) { xmin = my xmin; xmax = my xmax; } if (ymax <= ymin) { ymin = my ymin; ymax = my ymax; } long ixmin, ixmax, iymin, iymax; (void) Matrix_getWindowSamplesX (me, xmin - 0.49999 * my dx, xmax + 0.49999 * my dx, & ixmin, & ixmax); (void) Matrix_getWindowSamplesY (me, ymin - 0.49999 * my dy, ymax + 0.49999 * my dy, & iymin, & iymax); if (maximum <= minimum) (void) Matrix_getWindowExtrema (me, ixmin, ixmax, iymin, iymax, & minimum, & maximum); if (maximum <= minimum) { minimum -= 1.0; maximum += 1.0; } if (xmin >= xmax || ymin >= ymax) return; Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); if (interpolate) Graphics_image (g, my z, ixmin, ixmax, Sampled_indexToX (me, ixmin - 0.5), Sampled_indexToX (me, ixmax + 0.5), iymin, iymax, SampledXY_indexToY (me, iymin - 0.5), SampledXY_indexToY (me, iymax + 0.5), minimum, maximum); else Graphics_cellArray (g, my z, ixmin, ixmax, Sampled_indexToX (me, ixmin - 0.5), Sampled_indexToX (me, ixmax + 0.5), iymin, iymax, SampledXY_indexToY (me, iymin - 0.5), SampledXY_indexToY (me, iymax + 0.5), minimum, maximum); Graphics_rectangle (g, xmin, xmax, ymin, ymax); Graphics_unsetInner (g); }
Sound Sound_resample (Sound me, double samplingFrequency, long precision) { double upfactor = samplingFrequency * my dx; if (fabs (upfactor - 2) < 1e-6) return Sound_upsample (me); if (fabs (upfactor - 1) < 1e-6) return Data_copy (me); try { long numberOfSamples = lround ((my xmax - my xmin) * samplingFrequency); if (numberOfSamples < 1) Melder_throw (U"The resampled Sound would have no samples."); autoSound filtered = NULL; if (upfactor < 1.0) { // need anti-aliasing filter? long nfft = 1, antiTurnAround = 1000; while (nfft < my nx + antiTurnAround * 2) nfft *= 2; autoNUMvector <double> data (1, nfft); filtered.reset (Sound_create (my ny, my xmin, my xmax, my nx, my dx, my x1)); for (long channel = 1; channel <= my ny; channel ++) { for (long i = 1; i <= nfft; i ++) { data [i] = 0; } NUMvector_copyElements (my z [channel], & data [antiTurnAround], 1, my nx); NUMrealft (data.peek(), nfft, 1); // go to the frequency domain for (long i = (long) floor (upfactor * nfft); i <= nfft; i ++) { data [i] = 0; // filter away high frequencies } data [2] = 0.0; NUMrealft (data.peek(), nfft, -1); // return to the time domain double factor = 1.0 / nfft; double *to = filtered -> z [channel]; for (long i = 1; i <= my nx; i ++) { to [i] = data [i + antiTurnAround] * factor; } } me = filtered.peek(); // reference copy; remove at end } autoSound thee = Sound_create (my ny, my xmin, my xmax, numberOfSamples, 1.0 / samplingFrequency, 0.5 * (my xmin + my xmax - (numberOfSamples - 1) / samplingFrequency)); for (long channel = 1; channel <= my ny; channel ++) { double *from = my z [channel]; double *to = thy z [channel]; if (precision <= 1) { for (long i = 1; i <= numberOfSamples; i ++) { double x = Sampled_indexToX (thee.peek(), i); double index = Sampled_xToIndex (me, x); long leftSample = (long) floor (index); double fraction = index - leftSample; to [i] = leftSample < 1 || leftSample >= my nx ? 0.0 : (1 - fraction) * from [leftSample] + fraction * from [leftSample + 1]; } } else { for (long i = 1; i <= numberOfSamples; i ++) { double x = Sampled_indexToX (thee.peek(), i); double index = Sampled_xToIndex (me, x); to [i] = NUM_interpolate_sinc (my z [channel], my nx, index, precision); } } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": not resampled."); } }
void FilterBank_paint (FilterBank me, Graphics g, double xmin, double xmax, double ymin, double ymax, double minimum, double maximum, int garnish) { if (xmax <= xmin) { xmin = my xmin; xmax = my xmax; } if (ymax <= ymin) { ymin = my ymin; ymax = my ymax; } long ixmin, ixmax, iymin, iymax; (void) Matrix_getWindowSamplesX (me, xmin - 0.49999 * my dx, xmax + 0.49999 * my dx, &ixmin, &ixmax); (void) Matrix_getWindowSamplesY (me, ymin - 0.49999 * my dy, ymax + 0.49999 * my dy, &iymin, &iymax); if (maximum <= minimum) { (void) Matrix_getWindowExtrema (me, ixmin, ixmax, iymin, iymax, &minimum, &maximum); } if (maximum <= minimum) { minimum -= 1.0; maximum += 1.0; } if (xmin >= xmax || ymin >= ymax) { return; } Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); Graphics_image (g, my z, ixmin, ixmax, Sampled_indexToX (me, ixmin - 0.5), Sampled_indexToX (me, ixmax + 0.5), iymin, iymax, SampledXY_indexToY (me, iymin - 0.5), SampledXY_indexToY (me, iymax + 0.5), minimum, maximum); Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_marksLeft (g, 2, 1, 1, 0); Graphics_textLeft (g, 1, GetFreqScaleText (my v_getFrequencyScale ())); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_textBottom (g, 1, U"Time (s)"); } }
void Formant_drawTracks (Formant me, Graphics g, double tmin, double tmax, double fmax, int garnish) { long itmin, itmax, ntrack = Formant_getMinNumFormants (me); if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return; Graphics_setInner (g); Graphics_setWindow (g, tmin, tmax, 0.0, fmax); for (long itrack = 1; itrack <= ntrack; itrack ++) { for (long iframe = itmin; iframe < itmax; iframe ++) { Formant_Frame curFrame = & my d_frames [iframe], nextFrame = & my d_frames [iframe + 1]; double x1 = Sampled_indexToX (me, iframe), x2 = Sampled_indexToX (me, iframe + 1); double f1 = curFrame -> formant [itrack]. frequency; double f2 = nextFrame -> formant [itrack]. frequency; if (NUMdefined (x1) && NUMdefined (f1) && NUMdefined (x2) && NUMdefined (f2)) Graphics_line (g, x1, f1, x2, f2); } } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_textBottom (g, 1, U"Time (s)"); Graphics_textLeft (g, 1, U"Formant frequency (Hz)"); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_marksLeftEvery (g, 1.0, 1000.0, 1, 1, 1); } }
static double interpolate (Sound me, long i1, long channel) /* Precondition: my z [1] [i1] != my z [1] [i1 + 1]; */ { long i2 = i1 + 1; double x1 = Sampled_indexToX (me, i1), x2 = Sampled_indexToX (me, i2); double y1 = my z [channel] [i1], y2 = my z [channel] [i2]; return x1 + (x2 - x1) * y1 / (y1 - y2); /* Linear. */ }
Spectrogram LPC_to_Spectrogram (LPC me, double dfMin, double bandwidthReduction, double deEmphasisFrequency) { try { double samplingFrequency = 1.0 / my samplingPeriod; long nfft = 2; if (dfMin <= 0) { nfft = 512; dfMin = samplingFrequency / nfft; } while (samplingFrequency / nfft > dfMin || nfft <= my maxnCoefficients) { nfft *= 2; } double freqStep = samplingFrequency / nfft; autoSpectrogram thee = (Spectrogram) Spectrogram_create (my xmin, my xmax, my nx, my dx, my x1, 0, samplingFrequency / 2, nfft / 2 + 1, freqStep, 0); for (long i = 1; i <= my nx; i++) { double t = Sampled_indexToX (me, i); autoSpectrum spec = LPC_to_Spectrum (me, t, dfMin, bandwidthReduction, deEmphasisFrequency); for (long j = 1; j <= spec -> nx; j++) { double re = spec -> z[1][j], im = spec -> z[2][j]; thy z[j][i] = re * re + im * im; } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no Spectrogram created."); } }
static void Pitch_line (Pitch me, Graphics g, double tmin, double fleft, double tmax, double fright, int nonPeriodicLineType) { /* * f = fleft + (t - tmin) * (fright - fleft) / (tmax - tmin); */ int lineType = Graphics_inqLineType (g); double lineWidth = Graphics_inqLineWidth (g); double slope = (fright - fleft) / (tmax - tmin); long imin = Sampled_xToNearestIndex (me, tmin); if (imin < 1) imin = 1; long imax = Sampled_xToNearestIndex (me, tmax); if (imax > my nx) imax = my nx; for (long i = imin; i <= imax; i ++) { double tleft, tright; if (! Pitch_isVoiced_i (me, i)) { if (nonPeriodicLineType == 2) continue; Graphics_setLineType (g, Graphics_DOTTED); Graphics_setLineWidth (g, 0.67 * lineWidth); } else if (nonPeriodicLineType != 2) { Graphics_setLineWidth (g, 2 * lineWidth); } tleft = Sampled_indexToX (me, i) - 0.5 * my dx, tright = tleft + my dx; if (tleft < tmin) tleft = tmin; if (tright > tmax) tright = tmax; Graphics_line (g, tleft, fleft + (tleft - tmin) * slope, tright, fleft + (tright - tmin) * slope); Graphics_setLineType (g, lineType); Graphics_setLineWidth (g, lineWidth); } }
void Pitch_difference (Pitch me, Pitch thee) { long nuvtov = 0, nvtouv = 0, ndfdown = 0, ndfup = 0; if (my nx != thy nx || my dx != thy dx || my x1 != thy x1) { Melder_flushError ("Pitch_difference: these Pitches are not aligned."); return; } for (long i = 1; i <= my nx; i ++) { double myf = my frame [i]. candidate [1]. frequency, thyf = thy frame [i]. candidate [1]. frequency; int myUnvoiced = myf == 0 || myf > my ceiling; int thyUnvoiced = thyf == 0 || thyf > thy ceiling; double t = Sampled_indexToX (me, i); if (myUnvoiced && ! thyUnvoiced) { Melder_casual ("Frame %ld time %f: unvoiced to voiced.", i, t); nuvtov ++; } else if (! myUnvoiced && thyUnvoiced) { Melder_casual ("Frame %ld time %f: voiced to unvoiced.", i, t); nvtouv ++; } else if (! myUnvoiced && ! thyUnvoiced) { if (myf > thyf) { //Melder_casual ("Frame %ld time %f: downward frequency jump from %.5g Hz to %.5g Hz.", i, t, myf, thyf); ndfdown ++; } else if (myf < thyf) { //Melder_casual ("Frame %ld time %f: upward frequency jump from %.5g Hz to %.5g Hz.", i, t, myf, thyf); ndfup ++; } } } MelderInfo_open (); MelderInfo_writeLine (L"Difference between two Pitches:"); MelderInfo_writeLine (L"Unvoiced to voiced: ", Melder_integer (nuvtov), L" frames."); MelderInfo_writeLine (L"Voiced to unvoiced: ", Melder_integer (nvtouv), L" frames."); MelderInfo_writeLine (L"Downward frequency jump: ", Melder_integer (ndfdown), L" frames."); MelderInfo_writeLine (L"Upward frequency jump: ", Melder_integer (ndfup), L" frames."); MelderInfo_close (); }
void Formant_drawSpeckles_inside (Formant me, Graphics g, double tmin, double tmax, double fmin, double fmax, double suppress_dB) { long itmin, itmax; double maximumIntensity = 0.0, minimumIntensity; if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) return; Graphics_setWindow (g, tmin, tmax, fmin, fmax); for (long iframe = itmin; iframe <= itmax; iframe ++) { Formant_Frame frame = & my d_frames [iframe]; if (frame -> intensity > maximumIntensity) maximumIntensity = frame -> intensity; } if (maximumIntensity == 0.0 || suppress_dB <= 0.0) minimumIntensity = 0.0; /* Ignore. */ else minimumIntensity = maximumIntensity / pow (10.0, suppress_dB / 10.0); for (long iframe = itmin; iframe <= itmax; iframe ++) { Formant_Frame frame = & my d_frames [iframe]; double x = Sampled_indexToX (me, iframe); if (frame -> intensity < minimumIntensity) continue; for (long iformant = 1; iformant <= frame -> nFormants; iformant ++) { double frequency = frame -> formant [iformant]. frequency; if (frequency >= fmin && frequency <= fmax) Graphics_speckle (g, x, frequency); } } }
autoComplexSpectrogram Sound_to_ComplexSpectrogram (Sound me, double windowLength, double timeStep) { try { double samplingFrequency = 1.0 / my dx, myDuration = my xmax - my xmin, t1; if (windowLength > myDuration) { Melder_throw (U"Your sound is too short:\nit should be at least as long as one window length."); } long nsamp_window = (long) floor (windowLength / my dx); long halfnsamp_window = nsamp_window / 2 - 1; nsamp_window = halfnsamp_window * 2; if (nsamp_window < 2) { Melder_throw (U"Your analysis window is too short: less than two samples."); } long numberOfFrames; Sampled_shortTermAnalysis (me, windowLength, timeStep, &numberOfFrames, &t1); // Compute sampling of the spectrum long numberOfFrequencies = halfnsamp_window + 1; double df = samplingFrequency / (numberOfFrequencies - 1); autoComplexSpectrogram thee = ComplexSpectrogram_create (my xmin, my xmax, numberOfFrames, timeStep, t1, 0.0, 0.5 * samplingFrequency, numberOfFrequencies, df, 0.0); // autoSound analysisWindow = Sound_create (1, 0.0, nsamp_window * my dx, nsamp_window, my dx, 0.5 * my dx); for (long iframe = 1; iframe <= numberOfFrames; iframe++) { double t = Sampled_indexToX (thee.get(), iframe); long leftSample = Sampled_xToLowIndex (me, t), rightSample = leftSample + 1; long startSample = rightSample - halfnsamp_window; long endSample = leftSample + halfnsamp_window; Melder_assert (startSample >= 1); Melder_assert (endSample <= my nx); for (long j = 1; j <= nsamp_window; j++) { analysisWindow -> z[1][j] = my z[1][startSample - 1 + j]; } // window ? autoSpectrum spec = Sound_to_Spectrum (analysisWindow.get(), 0); thy z[1][iframe] = spec -> z[1][1] * spec -> z[1][1]; thy phase[1][iframe] = 0.0; for (long ifreq = 2; ifreq <= numberOfFrequencies - 1; ifreq++) { double x = spec -> z[1][ifreq], y = spec -> z[2][ifreq]; thy z[ifreq][iframe] = x * x + y * y; // power thy phase[ifreq][iframe] = atan2 (y, x); // phase [-pi,+pi] } // even number of samples thy z[numberOfFrequencies][iframe] = spec -> z[1][numberOfFrequencies] * spec -> z[1][numberOfFrequencies]; thy phase[numberOfFrequencies][iframe] = 0.0; } return thee; } catch (MelderError) { Melder_throw (me, U": no ComplexSpectrogram created."); } }
static LPC _Sound_to_LPC (Sound me, int predictionOrder, double analysisWidth, double dt, double preEmphasisFrequency, int method, double tol1, double tol2) { double t1, samplingFrequency = 1.0 / my dx; double windowDuration = 2 * analysisWidth; /* gaussian window */ long nFrames, frameErrorCount = 0; if (floor (windowDuration / my dx) < predictionOrder + 1) Melder_throw ("Analysis window duration too short.\n" "For a prediction order of ", predictionOrder, " the analysis window duration has to be greater than ", my dx * (predictionOrder + 1), "Please increase the analysis window duration or lower the prediction order."); // Convenience: analyse the whole sound into one LPC_frame if (windowDuration > my dx * my nx) { windowDuration = my dx * my nx; } Sampled_shortTermAnalysis (me, windowDuration, dt, & nFrames, & t1); autoSound sound = Data_copy (me); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); autoLPC thee = LPC_create (my xmin, my xmax, nFrames, dt, t1, predictionOrder, my dx); autoMelderProgress progress (L"LPC analysis"); if (preEmphasisFrequency < samplingFrequency / 2) { Sound_preEmphasis (sound.peek(), preEmphasisFrequency); } for (long i = 1; i <= nFrames; i++) { LPC_Frame lpcframe = (LPC_Frame) & thy d_frames[i]; double t = Sampled_indexToX (thee.peek(), i); LPC_Frame_init (lpcframe, predictionOrder); Sound_into_Sound (sound.peek(), sframe.peek(), t - windowDuration / 2); Vector_subtractMean (sframe.peek()); Sounds_multiply (sframe.peek(), window.peek()); if (method == LPC_METHOD_AUTO) { if (! Sound_into_LPC_Frame_auto (sframe.peek(), lpcframe)) { frameErrorCount++; } } else if (method == LPC_METHOD_COVAR) { if (! Sound_into_LPC_Frame_covar (sframe.peek(), lpcframe)) { frameErrorCount++; } } else if (method == LPC_METHOD_BURG) { if (! Sound_into_LPC_Frame_burg (sframe.peek(), lpcframe)) { frameErrorCount++; } } else if (method == LPC_METHOD_MARPLE) { if (! Sound_into_LPC_Frame_marple (sframe.peek(), lpcframe, tol1, tol2)) { frameErrorCount++; } } if ( (i % 10) == 1) { Melder_progress ( (double) i / nFrames, L"LPC analysis of frame ", Melder_integer (i), L" out of ", Melder_integer (nFrames), L"."); } } return thee.transfer(); }
autoRealTier Vector_to_RealTier (Vector me, long channel, ClassInfo klas) { try { autoRealTier thee = RealTier_createWithClass (my xmin, my xmax, klas); for (long i = 1; i <= my nx; i ++) { RealTier_addPoint (thee.get(), Sampled_indexToX (me, i), my z [channel] [i]); } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to ", klas -> className, U"."); } }
autoMelSpectrogram Sound_to_MelSpectrogram (Sound me, double analysisWidth, double dt, double f1_mel, double fmax_mel, double df_mel) { try { double t1, samplingFrequency = 1.0 / my dx, nyquist = 0.5 * samplingFrequency; double windowDuration = 2.0 * analysisWidth; // gaussian window double fmin_mel = 0.0; double fbottom = NUMhertzToMel2 (100.0), fceiling = NUMhertzToMel2 (nyquist); long numberOfFrames; // Check defaults. if (fmax_mel <= 0.0 || fmax_mel > fceiling) { fmax_mel = fceiling; } if (fmax_mel <= f1_mel) { f1_mel = fbottom; fmax_mel = fceiling; } if (f1_mel <= 0.0) { f1_mel = fbottom; } if (df_mel <= 0.0) { df_mel = 100.0; } // Determine the number of filters. long numberOfFilters = lround ((fmax_mel - f1_mel) / df_mel); fmax_mel = f1_mel + numberOfFilters * df_mel; Sampled_shortTermAnalysis (me, windowDuration, dt, &numberOfFrames, &t1); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); autoMelSpectrogram thee = MelSpectrogram_create (my xmin, my xmax, numberOfFrames, dt, t1, fmin_mel, fmax_mel, numberOfFilters, df_mel, f1_mel); autoMelderProgress progress (U"MelSpectrograms analysis"); for (long iframe = 1; iframe <= numberOfFrames; iframe++) { double t = Sampled_indexToX (thee.get(), iframe); Sound_into_Sound (me, sframe.get(), t - windowDuration / 2.0); Sounds_multiply (sframe.get(), window.get()); Sound_into_MelSpectrogram_frame (sframe.get(), thee.get(), iframe); if (iframe % 10 == 1) { Melder_progress ((double) iframe / numberOfFrames, U"Frame ", iframe, U" out of ", numberOfFrames, U"."); } } _Spectrogram_windowCorrection ((Spectrogram) thee.get(), window -> nx); return thee; } catch (MelderError) { Melder_throw (me, U": no MelSpectrogram created."); } }
autoBarkSpectrogram Sound_to_BarkSpectrogram (Sound me, double analysisWidth, double dt, double f1_bark, double fmax_bark, double df_bark) { try { double nyquist = 0.5 / my dx, samplingFrequency = 2 * nyquist; double windowDuration = 2 * analysisWidth; /* gaussian window */ double zmax = NUMhertzToBark2 (nyquist); double fmin_bark = 0; // Check defaults. if (f1_bark <= 0) { f1_bark = 1; } if (fmax_bark <= 0) { fmax_bark = zmax; } if (df_bark <= 0) { df_bark = 1; } fmax_bark = MIN (fmax_bark, zmax); long numberOfFilters = lround ( (fmax_bark - f1_bark) / df_bark); if (numberOfFilters <= 0) { Melder_throw (U"The combination of filter parameters is not valid."); } long numberOfFrames; double t1; Sampled_shortTermAnalysis (me, windowDuration, dt, & numberOfFrames, & t1); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); autoBarkSpectrogram thee = BarkSpectrogram_create (my xmin, my xmax, numberOfFrames, dt, t1, fmin_bark, fmax_bark, numberOfFilters, df_bark, f1_bark); autoMelderProgress progess (U"BarkSpectrogram analysis"); for (long iframe = 1; iframe <= numberOfFrames; iframe++) { double t = Sampled_indexToX (thee.get(), iframe); Sound_into_Sound (me, sframe.get(), t - windowDuration / 2.0); Sounds_multiply (sframe.get(), window.get()); Sound_into_BarkSpectrogram_frame (sframe.get(), thee.get(), iframe); if (iframe % 10 == 1) { Melder_progress ( (double) iframe / numberOfFrames, U"BarkSpectrogram analysis: frame ", iframe, U" from ", numberOfFrames, U"."); } } _Spectrogram_windowCorrection ((Spectrogram) thee.get(), window -> nx); return thee; } catch (MelderError) { Melder_throw (me, U": no BarkSpectrogram created."); } }
autoExcitation Spectrum_to_Excitation (Spectrum me, double dbark) { try { long nbark = (int) floor (25.6 / dbark + 0.5); double *re = my z [1], *im = my z [2]; autoNUMvector <double> auditoryFilter (1, nbark); double filterArea = 0; for (long i = 1; i <= nbark; i ++) { double bark = dbark * (i - nbark/2) + 0.474; filterArea += auditoryFilter [i] = pow (10, (1.581 + 0.75 * bark - 1.75 * sqrt (1 + bark * bark))); } /*for (long i = 1; i <= nbark; i ++) auditoryFilter [i] /= filterArea;*/ autoNUMvector <double> rFreqs (1, nbark + 1); autoNUMvector <long> iFreqs (1, nbark + 1); for (long i = 1; i <= nbark + 1; i ++) { rFreqs [i] = Excitation_barkToHertz (dbark * (i - 1)); iFreqs [i] = Sampled_xToNearestIndex (me, rFreqs [i]); } autoNUMvector <double> inSig (1, nbark); for (long i = 1; i <= nbark; i ++) { long low = iFreqs [i], high = iFreqs [i + 1] - 1; if (low < 1) low = 1; if (high > my nx) high = my nx; for (long j = low; j <= high; j ++) { inSig [i] += re [j] * re [j] + im [j] * im [j]; // Pa2 s2 } /* An anti-undersampling correction. */ if (high >= low) inSig [i] *= 2.0 * (rFreqs [i + 1] - rFreqs [i]) / (high - low + 1) * my dx; // Pa2: power density in this band } /* Convolution with auditory (masking) filter. */ autoNUMvector <double> outSig (1, 2 * nbark); for (long i = 1; i <= nbark; i ++) { for (long j = 1; j <= nbark; j ++) { outSig [i + j] += inSig [i] * auditoryFilter [j]; } } autoExcitation thee = Excitation_create (dbark, nbark); for (long i = 1; i <= nbark; i ++) { thy z [1] [i] = Excitation_soundPressureToPhon (sqrt (outSig [i + nbark/2]), Sampled_indexToX (thee.get(), i)); } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Excitation."); } }
static int Pitch_getVoicedIntervalAfter (Pitch me, double after, double *tleft, double *tright) { long ileft = Sampled_xToHighIndex (me, after), iright; if (ileft > my nx) return 0; /* Offright. */ if (ileft < 1) ileft = 1; /* Offleft. */ /* Search for first voiced frame. */ for (; ileft <= my nx; ileft ++) if (Pitch_isVoiced_i (me, ileft)) break; if (ileft > my nx) return 0; /* Offright. */ /* Search for last voiced frame. */ for (iright = ileft; iright <= my nx; iright ++) if (! Pitch_isVoiced_i (me, iright)) break; iright --; *tleft = Sampled_indexToX (me, ileft) - 0.5 * my dx; /* The whole frame is considered voiced. */ *tright = Sampled_indexToX (me, iright) + 0.5 * my dx; if (*tleft >= my xmax - 0.5 * my dx) return 0; if (*tleft < my xmin) *tleft = my xmin; if (*tright > my xmax) *tright = my xmax; return 1; }
autoCochleagram Sound_to_Cochleagram (Sound me, double dt, double df, double dt_window, double forwardMaskingTime) { try { double duration = my nx * my dx; long nFrames = 1 + (long) floor ((duration - dt_window) / dt); long nsamp_window = (long) floor (dt_window / my dx), halfnsamp_window = nsamp_window / 2 - 1; long nf = lround (25.6 / df); double dampingFactor = forwardMaskingTime > 0.0 ? exp (- dt / forwardMaskingTime) : 0.0; // default 30 ms double integrationCorrection = 1.0 - dampingFactor; nsamp_window = halfnsamp_window * 2; if (nFrames < 2) return autoCochleagram (); double t1 = my x1 + 0.5 * (duration - my dx - (nFrames - 1) * dt); // centre of first frame autoCochleagram thee = Cochleagram_create (my xmin, my xmax, nFrames, dt, t1, df, nf); autoSound window = Sound_createSimple (1, nsamp_window * my dx, 1.0 / my dx); for (long iframe = 1; iframe <= nFrames; iframe ++) { double t = Sampled_indexToX (thee.get(), iframe); long leftSample = Sampled_xToLowIndex (me, t); long rightSample = leftSample + 1; long startSample = rightSample - halfnsamp_window; long endSample = rightSample + halfnsamp_window; if (startSample < 1) { Melder_casual (U"Start sample too small: ", startSample, U" instead of 1."); startSample = 1; } if (endSample > my nx) { Melder_casual (U"End sample too small: ", endSample, U" instead of ", my nx, U"."); endSample = my nx; } /* Copy a window to a frame. */ for (long i = 1; i <= nsamp_window; i ++) window -> z [1] [i] = ( my ny == 1 ? my z[1][i+startSample-1] : 0.5 * (my z[1][i+startSample-1] + my z[2][i+startSample-1]) ) * (0.5 - 0.5 * cos (2.0 * NUMpi * i / (nsamp_window + 1))); autoSpectrum spec = Sound_to_Spectrum (window.get(), true); autoExcitation excitation = Spectrum_to_Excitation (spec.get(), df); for (long ifreq = 1; ifreq <= nf; ifreq ++) thy z [ifreq] [iframe] = excitation -> z [1] [ifreq] + ( iframe > 1 ? dampingFactor * thy z [ifreq] [iframe - 1] : 0 ); } for (long iframe = 1; iframe <= nFrames; iframe ++) for (long ifreq = 1; ifreq <= nf; ifreq ++) thy z [ifreq] [iframe] *= integrationCorrection; return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Cochleagram."); } }
void BandFilterSpectrogram_paintImage (BandFilterSpectrogram me, Graphics g, double xmin, double xmax, double ymin, double ymax, double minimum, double maximum, int garnish) { if (xmax <= xmin) { xmin = my xmin; xmax = my xmax; } if (ymax <= ymin) { ymin = my ymin; ymax = my ymax; } long ixmin, ixmax, iymin, iymax; (void) Matrix_getWindowSamplesX (me, xmin - 0.49999 * my dx, xmax + 0.49999 * my dx, &ixmin, &ixmax); (void) Matrix_getWindowSamplesY (me, ymin - 0.49999 * my dy, ymax + 0.49999 * my dy, &iymin, &iymax); autoMatrix thee = Spectrogram_to_Matrix_dB ((Spectrogram) me, 4e-10, 10, -100); if (maximum <= minimum) { (void) Matrix_getWindowExtrema (thee.peek(), ixmin, ixmax, iymin, iymax, &minimum, &maximum); } if (maximum <= minimum) { minimum -= 1.0; maximum += 1.0; } if (xmin >= xmax || ymin >= ymax) { return; } Graphics_setInner (g); Graphics_setWindow (g, xmin, xmax, ymin, ymax); Graphics_image (g, thy z, ixmin, ixmax, Sampled_indexToX (thee.peek(), ixmin - 0.5), Sampled_indexToX (thee.peek(), ixmax + 0.5), iymin, iymax, SampledXY_indexToY (thee.peek(), iymin - 0.5), SampledXY_indexToY (thee.peek(), iymax + 0.5), minimum, maximum); 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"Time (s)"); } }
FormantGrid Formant_downto_FormantGrid (Formant me) { FormantGrid thee = FormantGrid_createEmpty (my xmin, my xmax, my maxnFormants); cherror for (long iframe = 1; iframe <= my nx; iframe ++) { Formant_Frame frame = & my frame [iframe]; double t = Sampled_indexToX (me, iframe); for (long iformant = 1; iformant <= frame -> nFormants; iformant ++) { Formant_Formant pair = & frame -> formant [iformant]; FormantGrid_addFormantPoint (thee, iformant, t, pair -> frequency); cherror FormantGrid_addBandwidthPoint (thee, iformant, t, pair -> bandwidth); cherror } } end: iferror forget (thee); return thee; }
void structPointEditor :: v_draw () { PointProcess point = static_cast <PointProcess> (our data); Sound sound = d_sound.data; Graphics_setColour (our graphics.get(), Graphics_WHITE); Graphics_setWindow (our graphics.get(), 0.0, 1.0, 0.0, 1.0); Graphics_fillRectangle (our graphics.get(), 0.0, 1.0, 0.0, 1.0); double minimum = -1.0, maximum = +1.0; if (sound && (p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW || p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW_AND_CHANNEL)) { long first, last; if (Sampled_getWindowSamples (sound, our startWindow, our endWindow, & first, & last) >= 1) { Matrix_getWindowExtrema (sound, first, last, 1, 1, & minimum, & maximum); if (minimum == maximum) minimum -= 1.0, maximum += 1.0; } } Graphics_setWindow (our graphics.get(), our startWindow, our endWindow, minimum, maximum); Graphics_setColour (our graphics.get(), Graphics_BLACK); if (sound) { long first, last; if (Sampled_getWindowSamples (sound, our startWindow, our endWindow, & first, & last) > 1) { Graphics_setLineType (our graphics.get(), Graphics_DOTTED); Graphics_line (our graphics.get(), our startWindow, 0.0, our endWindow, 0.0); Graphics_setLineType (our graphics.get(), Graphics_DRAWN); Graphics_function (our graphics.get(), sound -> z [1], first, last, Sampled_indexToX (sound, first), Sampled_indexToX (sound, last)); } } Graphics_setColour (our graphics.get(), Graphics_BLUE); Graphics_setWindow (our graphics.get(), our startWindow, our endWindow, -1.0, +1.0); for (long i = 1; i <= point -> nt; i ++) { double t = point -> t [i]; if (t >= our startWindow && t <= our endWindow) Graphics_line (our graphics.get(), t, -0.9, t, +0.9); } Graphics_setColour (our graphics.get(), Graphics_BLACK); v_updateMenuItems_file (); }
Sound Sound_createFromToneComplex (double startingTime, double endTime, double sampleRate, int phase, double frequencyStep, double firstFrequency, double ceiling, long numberOfComponents) { try { if (frequencyStep == 0.0) Melder_throw (U"Frequency step must not be zero."); /* * Translate default firstFrequency. */ if (firstFrequency <= 0.0) firstFrequency = frequencyStep; double firstOmega = 2 * NUMpi * firstFrequency; /* * Translate default ceiling. */ double omegaStep = 2 * NUMpi * frequencyStep, nyquistFrequency = 0.5 * sampleRate; if (ceiling <= 0.0 || ceiling > nyquistFrequency) ceiling = nyquistFrequency; /* * Translate number of components. */ long maximumNumberOfComponents = (long) floor ((ceiling - firstFrequency) / frequencyStep) + 1; if (numberOfComponents <= 0 || numberOfComponents > maximumNumberOfComponents) numberOfComponents = maximumNumberOfComponents; if (numberOfComponents < 1) Melder_throw (U"Zero sine waves."); /* * Generate the Sound. */ double factor = 0.99 / numberOfComponents; autoSound me = Sound_create (1, startingTime, endTime, lround ((endTime - startingTime) * sampleRate), 1 / sampleRate, startingTime + 0.5 / sampleRate); double *amplitude = my z [1]; for (long isamp = 1; isamp <= my nx; isamp ++) { double value = 0.0, t = Sampled_indexToX (me.peek(), isamp); double omegaStepT = omegaStep * t, firstOmegaT = firstOmega * t; if (phase == Sound_TONE_COMPLEX_SINE) for (long icomp = 1; icomp <= numberOfComponents; icomp ++) value += sin (firstOmegaT + (icomp - 1) * omegaStepT); else for (long icomp = 1; icomp <= numberOfComponents; icomp ++) value += cos (firstOmegaT + (icomp - 1) * omegaStepT); amplitude [isamp] = value * factor; } return me.transfer(); } catch (MelderError) { Melder_throw (U"Sound not created from tone complex."); } }
FormantGrid Formant_downto_FormantGrid (Formant me) { try { autoFormantGrid thee = FormantGrid_createEmpty (my xmin, my xmax, my maxnFormants); for (long iframe = 1; iframe <= my nx; iframe ++) { Formant_Frame frame = & my d_frames [iframe]; double t = Sampled_indexToX (me, iframe); for (long iformant = 1; iformant <= frame -> nFormants; iformant ++) { Formant_Formant pair = & frame -> formant [iformant]; FormantGrid_addFormantPoint (thee.peek(), iformant, t, pair -> frequency); FormantGrid_addBandwidthPoint (thee.peek(), iformant, t, pair -> bandwidth); } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to FormantGrid."); } }
PowerCepstrogram Sound_to_PowerCepstrogram (Sound me, double pitchFloor, double dt, double maximumFrequency, double preEmphasisFrequency) { try { // minimum analysis window has 3 periods of lowest pitch double analysisWidth = 3 / pitchFloor; double windowDuration = 2 * analysisWidth; /* gaussian window */ long nFrames; // Convenience: analyse the whole sound into one Cepstrogram_frame if (windowDuration > my dx * my nx) { windowDuration = my dx * my nx; } double t1, samplingFrequency = 2 * maximumFrequency; autoSound sound = Sound_resample (me, samplingFrequency, 50); Sound_preEmphasis (sound.peek(), preEmphasisFrequency); Sampled_shortTermAnalysis (me, windowDuration, dt, & nFrames, & t1); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); // find out the size of the FFT long nfft = 2; while (nfft < sframe -> nx) nfft *= 2; long nq = nfft / 2 + 1; double qmax = 0.5 * nfft / samplingFrequency, dq = qmax / (nq - 1); autoPowerCepstrogram thee = PowerCepstrogram_create (my xmin, my xmax, nFrames, dt, t1, 0, qmax, nq, dq, 0); autoMelderProgress progress (L"Cepstrogram analysis"); for (long iframe = 1; iframe <= nFrames; iframe++) { double t = Sampled_indexToX (thee.peek(), iframe); Sound_into_Sound (sound.peek(), sframe.peek(), t - windowDuration / 2); Vector_subtractMean (sframe.peek()); Sounds_multiply (sframe.peek(), window.peek()); autoSpectrum spec = Sound_to_Spectrum (sframe.peek(), 1); // FFT yes autoPowerCepstrum cepstrum = Spectrum_to_PowerCepstrum (spec.peek()); for (long i = 1; i <= nq; i++) { thy z[i][iframe] = cepstrum -> z[1][i]; } if ((iframe % 10) == 1) { Melder_progress ((double) iframe / nFrames, L"PowerCepstrogram analysis of frame ", Melder_integer (iframe), L" out of ", Melder_integer (nFrames), L"."); } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no PowerCepstrogram created."); } }
Cepstrogram Sound_to_Cepstrogram (Sound me, double analysisWidth, double dt, double maximumFrequency) { try { double windowDuration = 2 * analysisWidth; /* gaussian window */ long nFrames; // Convenience: analyse the whole sound into one Cepstrogram_frame if (windowDuration > my dx * my nx) { windowDuration = my dx * my nx; } double t1, samplingFrequency = 2 * maximumFrequency; autoSound sound = Sound_resample (me, samplingFrequency, 50); Sampled_shortTermAnalysis (me, windowDuration, dt, & nFrames, & t1); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); double qmin, qmax, dq, q1; long nq; { // laziness: find out the proper dimensions autoSpectrum spec = Sound_to_Spectrum (sframe.peek(), 1); autoCepstrum cepstrum = Spectrum_to_Cepstrum (spec.peek()); qmin = cepstrum -> xmin; qmax = cepstrum -> xmax; dq = cepstrum -> dx; q1 = cepstrum -> x1; nq = cepstrum -> nx; } autoCepstrogram thee = Cepstrogram_create (my xmin, my xmax, nFrames, dt, t1, qmin, qmax, nq, dq, q1); autoMelderProgress progress (L"Cepstrogram analysis"); for (long iframe = 1; iframe <= nFrames; iframe++) { double t = Sampled_indexToX (thee.peek(), iframe); Sound_into_Sound (sound.peek(), sframe.peek(), t - windowDuration / 2); Vector_subtractMean (sframe.peek()); Sounds_multiply (sframe.peek(), window.peek()); autoSpectrum spec = Sound_to_Spectrum (sframe.peek(), 1); autoCepstrum cepstrum = Spectrum_to_Cepstrum (spec.peek()); for (long i = 1; i <= nq; i++) { thy z[i][iframe] = cepstrum -> z[1][i]; } if ((iframe % 10) == 1) { Melder_progress ((double) iframe / nFrames, L"Cepstrogram analysis of frame ", Melder_integer (iframe), L" out of ", Melder_integer (nFrames), L"."); } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no Cepstrogram created."); } }
autoPitch Pitch_PitchTier_to_Pitch (Pitch me, PitchTier tier) { try { if (tier -> points.size == 0) Melder_throw (U"No pitch points."); autoPitch thee = Data_copy (me); for (long iframe = 1; iframe <= my nx; iframe ++) { Pitch_Frame frame = & thy frame [iframe]; Pitch_Candidate cand = & frame -> candidate [1]; if (cand -> frequency > 0.0 && cand -> frequency <= my ceiling) cand -> frequency = RealTier_getValueAtTime (tier, Sampled_indexToX (me, iframe)); cand -> strength = 0.9; frame -> nCandidates = 1; } return thee; } catch (MelderError) { Melder_throw (me, U" & ", tier, U": not converted to Pitch."); } }
int structPitchEditor :: v_click (double xWC, double yWC, bool dummy) { Pitch pitch = (Pitch) our data; double dyUnv = Graphics_dyMMtoWC (d_graphics, HEIGHT_UNV); double dyIntens = Graphics_dyMMtoWC (d_graphics, HEIGHT_INTENS); double frequency = (yWC - dyUnv) / (1 - dyIntens - dyUnv) * pitch -> ceiling, tmid; double minimumDf = 1e30; int cand, bestCandidate = -1; long ibestFrame; Pitch_Frame bestFrame; ibestFrame = Sampled_xToNearestIndex (pitch, xWC); if (ibestFrame < 1) ibestFrame = 1; if (ibestFrame > pitch -> nx) ibestFrame = pitch -> nx; bestFrame = & pitch -> frame [ibestFrame]; tmid = Sampled_indexToX (pitch, ibestFrame); for (cand = 1; cand <= bestFrame -> nCandidates; cand ++) { double df = frequency - bestFrame -> candidate [cand]. frequency; if (fabs (df) < minimumDf) { minimumDf = fabs (df); bestCandidate = cand; } } if (bestCandidate != -1) { double bestFrequency = bestFrame -> candidate [bestCandidate]. frequency; double distanceWC = (frequency - bestFrequency) / pitch -> ceiling * (1 - dyIntens - dyUnv); double dx_mm = Graphics_dxWCtoMM (our d_graphics, xWC - tmid), dy_mm = Graphics_dyWCtoMM (our d_graphics, distanceWC); if (bestFrequency < pitch -> ceiling && // above ceiling: ignore ((bestFrequency <= 0.0 && fabs (xWC - tmid) <= 0.5 * pitch -> dx && frequency <= 0.0) || // voiceless: click within frame (bestFrequency > 0.0 && dx_mm * dx_mm + dy_mm * dy_mm <= RADIUS * RADIUS))) // voiced: click within circle { struct structPitch_Candidate help = bestFrame -> candidate [1]; Editor_save (this, L"Change path"); bestFrame -> candidate [1] = bestFrame -> candidate [bestCandidate]; bestFrame -> candidate [bestCandidate] = help; FunctionEditor_redraw (this); our broadcastDataChanged (); our d_startSelection = our d_endSelection = tmid; // cursor will snap to candidate return 1; } else { return PitchEditor_Parent :: v_click (xWC, yWC, dummy); // move cursor or drag selection } } return PitchEditor_Parent :: v_click (xWC, yWC, dummy); // move cursor or drag selection }
void LineSpectralFrequencies_drawFrequencies (LineSpectralFrequencies me, Graphics g, double tmin, double tmax, double fmin, double fmax, bool garnish) { if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } long itmin, itmax; if (! Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax)) { return; } if (fmax <= fmin) { double f1max, f2min; autoNUMvector<double> f1 (itmin, itmax), f2 (itmin, itmax); for (long iframe = itmin; iframe <= itmax; iframe++) { f1[iframe] = my d_frames[iframe].frequencies[1]; f2[iframe] = my d_frames[iframe].frequencies[my d_frames[iframe].numberOfFrequencies]; } NUMvector_extrema (f1.peek(), itmin, itmax, & fmin, & f1max); NUMvector_extrema (f2.peek(), itmin, itmax, & f2min, & fmax); } if (fmax == fmin) { fmin = 0; fmax += 0.5; } Graphics_setInner (g); Graphics_setWindow (g, tmin, tmax, fmin, fmax); for (long iframe = itmin; iframe <= itmax; iframe++) { LineSpectralFrequencies_Frame lsf = & my d_frames[iframe]; double x = Sampled_indexToX (me, iframe); for (long ifreq = 1; ifreq <= lsf -> numberOfFrequencies; ifreq++) { double y = lsf -> frequencies [ifreq]; if (y >= fmin && y <= fmax) { Graphics_speckle (g, x, y); } } } Graphics_unsetInner (g); if (garnish) { Graphics_drawInnerBox (g); Graphics_textBottom (g, true, U"Time (seconds)"); Graphics_textLeft (g, true, U"Frequency (Hz)"); Graphics_marksBottom (g, 2, true, true, false); Graphics_marksLeft (g, 2, true, true, false); } }
autoFormantTier Formant_downto_FormantTier (Formant me) { try { autoFormantTier thee = FormantTier_create (my xmin, my xmax); for (long i = 1; i <= my nx; i ++) { Formant_Frame frame = & my d_frames [i]; autoFormantPoint point = FormantPoint_create (Sampled_indexToX (me, i)); point -> numberOfFormants = frame -> nFormants > 10 ? 10 : frame -> nFormants; for (long j = 1; j <= point -> numberOfFormants; j ++) { Formant_Formant pair = & frame -> formant [j]; point -> formant [j-1] = pair -> frequency; point -> bandwidth [j-1] = pair -> bandwidth; } Collection_addItem_move (thy points, point.move()); } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to FormantTier."); } }
autoPitchTier Pitch_to_PitchTier (Pitch me) { try { autoPitchTier thee = PitchTier_create (my xmin, my xmax); for (long i = 1; i <= my nx; i ++) { double frequency = my frame [i]. candidate [1]. frequency; /* * Count only voiced frames. */ if (frequency > 0.0 && frequency < my ceiling) { double time = Sampled_indexToX (me, i); RealTier_addPoint (thee.get(), time, frequency); } } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to PitchTier."); } }