/* This is for multi-channel "sounds" like EEG signals. The cross-correlation between channel i and channel j is defined as sum(k=1..nsamples, (z[i][k] - mean[i])(z[j][k + tau] - mean[j]))*samplingTime */ autoCrossCorrelationTable Sound_to_CrossCorrelationTable (Sound me, double startTime, double endTime, double lagStep) { try { if (endTime <= startTime) { startTime = my xmin; endTime = my xmax; } long lag = (long) floor (lagStep / my dx); // ppgb: voor al dit soort dingen geldt: waarom afronden naar beneden? long i1 = Sampled_xToNearestIndex (me, startTime); if (i1 < 1) { i1 = 1; } long i2 = Sampled_xToNearestIndex (me, endTime); if (i2 > my nx) { i2 = my nx; } i2 -= lag; long nsamples = i2 - i1 + 1; if (nsamples <= my ny) { Melder_throw (U"Not enough samples, choose a longer interval."); } autoCrossCorrelationTable thee = CrossCorrelationTable_create (my ny); NUMcrossCorrelate_rows (my z, my ny, i1, i2, lag, thy data, thy centroid, my dx); thy numberOfObservations = nsamples; return thee; } catch (MelderError) { Melder_throw (me, U": CrossCorrelationTable not created."); } }
/* This is for multi-channel "sounds" like EEG signals. The cross-correlation between channel i and channel j is defined as sum(k=1..nsamples, (z[i][k] - mean[i])(z[j][k + tau] - mean[j]))*samplingTime */ CrossCorrelationTable Sound_to_CrossCorrelationTable (Sound me, double startTime, double endTime, double lagTime) { try { if (endTime <= startTime) { startTime = my xmin; endTime = my xmax; } long lag = lagTime / my dx; long i1 = Sampled_xToNearestIndex (me, startTime); if (i1 < 1) { i1 = 1; } long i2 = Sampled_xToNearestIndex (me, endTime); if (i2 > my nx) { i2 = my nx; } i2 -= lag; long nsamples = i2 - i1 + 1; if (nsamples <= my ny) { Melder_throw ("Not enough samples, choose a longer interval."); } autoCrossCorrelationTable thee = CrossCorrelationTable_create (my ny); NUMcrossCorrelate_rows (my z, my ny, i1, i2, lag, thy data, thy centroid, my dx); thy numberOfObservations = nsamples; return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": CrossCorrelationTable not 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); } }
static double Sound_findMaximumCorrelation (Sound me, double t1, double windowLength, double tmin2, double tmax2, double *tout, double *peak) { double maximumCorrelation = -1.0, r1 = 0.0, r2 = 0.0, r3 = 0.0, r1_best, r3_best, ir; double halfWindowLength = 0.5 * windowLength; long i1, i2, ileft2; long ileft1 = Sampled_xToNearestIndex ((Sampled) me, t1 - halfWindowLength); long iright1 = Sampled_xToNearestIndex ((Sampled) me, t1 + halfWindowLength); long ileft2min = Sampled_xToLowIndex ((Sampled) me, tmin2 - halfWindowLength); long ileft2max = Sampled_xToHighIndex ((Sampled) me, tmax2 - halfWindowLength); *peak = 0.0; /* Default. */ for (ileft2 = ileft2min; ileft2 <= ileft2max; ileft2 ++) { double norm1 = 0.0, norm2 = 0.0, product = 0.0, localPeak = 0.0; if (my ny == 1) { for (i1 = ileft1, i2 = ileft2; i1 <= iright1; i1 ++, i2 ++) { if (i1 < 1 || i1 > my nx || i2 < 1 || i2 > my nx) continue; double amp1 = my z [1] [i1], amp2 = my z [1] [i2]; norm1 += amp1 * amp1; norm2 += amp2 * amp2; product += amp1 * amp2; if (fabs (amp2) > localPeak) localPeak = fabs (amp2); } } else { for (i1 = ileft1, i2 = ileft2; i1 <= iright1; i1 ++, i2 ++) { if (i1 < 1 || i1 > my nx || i2 < 1 || i2 > my nx) continue; double amp1 = 0.5 * (my z [1] [i1] + my z [2] [i1]), amp2 = 0.5 * (my z [1] [i2] + my z [2] [i2]); norm1 += amp1 * amp1; norm2 += amp2 * amp2; product += amp1 * amp2; if (fabs (amp2) > localPeak) localPeak = fabs (amp2); } } r1 = r2; r2 = r3; r3 = product ? product / (sqrt (norm1 * norm2)) : 0.0; if (r2 > maximumCorrelation && r2 >= r1 && r2 >= r3) { r1_best = r1; maximumCorrelation = r2; r3_best = r3; ir = ileft2 - 1; *peak = localPeak; } } /* * Improve the result by means of parabolic interpolation. */ if (maximumCorrelation > -1.0) { double d2r = 2 * maximumCorrelation - r1_best - r3_best; if (d2r != 0.0) { double dr = 0.5 * (r3_best - r1_best); maximumCorrelation += 0.5 * dr * dr / d2r; ir += dr / d2r; } *tout = t1 + (ir - ileft1) * my dx; } return maximumCorrelation; }
Spectrum FormantFilter_to_Spectrum_slice (FormantFilter me, double t) { try { double sqrtref = sqrt (FilterBank_DBREF); double factor2 = 2 * 10 * FilterBank_DBFAC; autoSpectrum thee = Spectrum_create (my ymax, my ny); thy xmin = my ymin; thy xmax = my ymax; thy x1 = my y1; thy dx = my dy; /* Frequency step. */ long frame = Sampled_xToNearestIndex (me, t); if (frame < 1) { frame = 1; } if (frame > my nx) { frame = my nx; } for (long i = 1; i <= my ny; i++) { /* power = ref * 10 ^ (value / 10) sqrt(power) = sqrt(ref) * 10 ^ (value / (2*10)) */ thy z[1][i] = sqrtref * pow (10, my z[i][frame] / factor2); thy z[2][i] = 0.0; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": Spectral slice not created."); } }
double CC_getValue (CC me, double t, long index) { long iframe = Sampled_xToNearestIndex (me, t); if (iframe < 1 || iframe > my nx) { return NUMundefined; } CC_Frame cf = & me -> frame[iframe]; return index > cf -> numberOfCoefficients ? NUMundefined : cf -> c[index]; }
bool structSpectrogramEditor :: v_click (double xWC, double yWC, bool shiftKeyPressed) { Spectrogram spectrogram = (Spectrogram) our data; /*double frequency = yWC * our maximum;*/ long bestFrame; bestFrame = Sampled_xToNearestIndex (spectrogram, xWC); if (bestFrame < 1) bestFrame = 1; else if (bestFrame > spectrogram -> nx) bestFrame = spectrogram -> nx; return our SpectrogramEditor_Parent :: v_click (xWC, yWC, shiftKeyPressed); }
/* Calculate the CrossCorrelationTable between the channels of two multichannel sounds irrespective of the domains. * Both sounds are treated as if their domain runs from 0 to duration. * Outside the chosen interval the sounds are assumed to be zero */ autoCrossCorrelationTable Sounds_to_CrossCorrelationTable_combined (Sound me, Sound thee, double relativeStartTime, double relativeEndTime, double lagStep) { try { if (my dx != thy dx) { Melder_throw (U"Sampling frequencies must be equal."); } if (relativeEndTime <= relativeStartTime) { relativeStartTime = my xmin; relativeEndTime = my xmax; } long ndelta = (long) floor (lagStep / my dx), nchannels = my ny + thy ny; long i1 = Sampled_xToNearestIndex (me, relativeStartTime); if (i1 < 1) { i1 = 1; } long i2 = Sampled_xToNearestIndex (me, relativeEndTime); if (i2 > my nx) { i2 = my nx; } i2 -= ndelta; long nsamples = i2 - i1 + 1; if (nsamples <= nchannels) { Melder_throw (U"Not enough samples"); } autoCrossCorrelationTable him = CrossCorrelationTable_create (nchannels); autoNUMvector<double *> data (1, nchannels); for (long i = 1; i <= my ny; i++) { data[i] = my z[i]; } for (long i = 1; i <= thy ny; i++) { data[i + my ny] = thy z[i]; } NUMcrossCorrelate_rows (data.peek(), nchannels, i1, i2, ndelta, his data, his centroid, my dx); his numberOfObservations = nsamples; return him; } catch (MelderError) { Melder_throw (me, U": CrossCorrelationTable not 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."); } }
PowerCepstrum PowerCepstrogram_to_PowerCepstrum_slice (PowerCepstrogram me, double time) { try { long iframe = Sampled_xToNearestIndex (me, time); iframe = iframe < 1 ? 1 : iframe > my nx ? my nx : iframe; autoPowerCepstrum thee = PowerCepstrum_create (my ymax, my ny); for (long i = 1; i <= my ny; i++) { thy z[1][i] = my z[i][iframe]; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": Cepstrum not extracted."); } }
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 }
Sound PointProcess_to_Sound_pulseTrain (PointProcess me, double samplingFrequency, double adaptFactor, double adaptTime, long interpolationDepth) { try { long sound_nt = 1 + floor ((my xmax - my xmin) * samplingFrequency); // >= 1 double dt = 1.0 / samplingFrequency; double tmid = (my xmin + my xmax) / 2; double t1 = tmid - 0.5 * (sound_nt - 1) * dt; autoSound thee = Sound_create (1, my xmin, my xmax, sound_nt, dt, t1); double *sound = thy z [1]; for (long it = 1; it <= my nt; it ++) { double t = my t [it], amplitude = 0.9, angle, halfampsinangle; long mid = Sampled_xToNearestIndex (thee.peek(), t); if (it <= 2 || my t [it - 2] < my t [it] - adaptTime) { amplitude *= adaptFactor; if (it == 1 || my t [it - 1] < my t [it] - adaptTime) amplitude *= adaptFactor; } long begin = mid - interpolationDepth, end = mid + interpolationDepth; if (begin < 1) begin = 1; if (end > thy nx) end = thy nx; angle = NUMpi * (Sampled_indexToX (thee.peek(), begin) - t) / thy dx; halfampsinangle = 0.5 * amplitude * sin (angle); for (long j = begin; j <= end; j ++) { if (fabs (angle) < 1e-6) sound [j] += amplitude; else if (angle < 0.0) sound [j] += halfampsinangle * (1 + cos (angle / (mid - begin + 1))) / angle; else sound [j] += halfampsinangle * (1 + cos (angle / (end - mid + 1))) / angle; angle += NUMpi; halfampsinangle = - halfampsinangle; } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": pulse train not synthesized."); } }
double Sampled_getValueAtX (Sampled me, double x, long ilevel, int unit, int interpolate) { if (x < my xmin || x > my xmax) return NUMundefined; if (interpolate) { double ireal = Sampled_xToIndex (me, x); long ileft = floor (ireal), inear, ifar; double phase = ireal - ileft; if (phase < 0.5) { inear = ileft, ifar = ileft + 1; } else { ifar = ileft, inear = ileft + 1; phase = 1.0 - phase; } if (inear < 1 || inear > my nx) return NUMundefined; // x out of range? double fnear = my v_getValueAtSample (inear, ilevel, unit); if (fnear == NUMundefined) return NUMundefined; // function value not defined? if (ifar < 1 || ifar > my nx) return fnear; // at edge? Extrapolate double ffar = my v_getValueAtSample (ifar, ilevel, unit); if (ffar == NUMundefined) return fnear; // neighbour undefined? Extrapolate return fnear + phase * (ffar - fnear); // interpolate } return Sampled_getValueAtSample (me, Sampled_xToNearestIndex (me, x), ilevel, unit); }
void LPC_and_Sound_filterWithFilterAtTime_inline (LPC me, Sound thee, int channel, double time) { long frameIndex = Sampled_xToNearestIndex (me, time); if (frameIndex < 1) { frameIndex = 1; } if (frameIndex > my nx) { frameIndex = my nx; } if (channel > thy ny) { channel = 1; } if (frameIndex < 1 || frameIndex > my nx) { Melder_throw (U"Frame number out of range."); } if (channel > 0) { LPC_Frame_and_Sound_filter (& (my d_frames[frameIndex]), thee, channel); } else { for (long ichan = 1; ichan <= thy ny; ichan++) { LPC_Frame_and_Sound_filter (& (my d_frames[frameIndex]), thee, ichan); } } }
double Sampled_getValueAtX (I, double x, long ilevel, int unit, int interpolate) { iam (Sampled); if (x < my xmin || x > my xmax) return NUMundefined; if (interpolate) { double ireal = Sampled_xToIndex (me, x), phase, fnear, ffar; long ileft = floor (ireal), inear, ifar; phase = ireal - ileft; if (phase < 0.5) { inear = ileft, ifar = ileft + 1; } else { ifar = ileft, inear = ileft + 1; phase = 1.0 - phase; } if (inear < 1 || inear > my nx) return NUMundefined; /* X out of range? */ fnear = our getValueAtSample (me, inear, ilevel, unit); if (fnear == NUMundefined) return NUMundefined; /* Function value not defined? */ if (ifar < 1 || ifar > my nx) return fnear; /* At edge? Extrapolate. */ ffar = our getValueAtSample (me, ifar, ilevel, unit); if (ffar == NUMundefined) return fnear; /* Neighbour undefined? Extrapolate. */ return fnear + phase * (ffar - fnear); /* Interpolate. */ } return Sampled_getValueAtSample (me, Sampled_xToNearestIndex (me, x), ilevel, unit); }
void LPC_and_Sound_filterInverseWithFilterAtTime_inline (LPC me, Sound thee, int channel, double time) { try { long frameIndex = Sampled_xToNearestIndex (me, time); if (frameIndex < 1) { frameIndex = 1; } if (frameIndex > my nx) { frameIndex = my nx; } if (channel > thy ny) { channel = 1; } if (channel > 0) { LPC_Frame_and_Sound_filterInverse (& (my d_frames[frameIndex]), thee, channel); } else { for (long ichan = 1; ichan <= thy ny; ichan++) { LPC_Frame_and_Sound_filterInverse (& (my d_frames[frameIndex]), thee, ichan); } } } catch (MelderError) { Melder_throw (thee, U": not inverse filtered."); } }
Spectrum LPC_to_Spectrum (LPC me, double t, double dfMin, double bandwidthReduction, double deEmphasisFrequency) { try { double samplingFrequency = 1.0 / my samplingPeriod; long nfft = 2, index = Sampled_xToNearestIndex (me, t); if (index < 1) { index = 1; } if (index > my nx) { index = my nx; } if (dfMin <= 0) { nfft = 512; dfMin = samplingFrequency / nfft; } while (samplingFrequency / nfft > dfMin || nfft <= my d_frames[index].nCoefficients) { nfft *= 2; } autoSpectrum thee = Spectrum_create (samplingFrequency / 2, nfft / 2 + 1); LPC_Frame_into_Spectrum (& my d_frames[index], thee.peek(), bandwidthReduction, deEmphasisFrequency); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no Spectrum created."); } }
autoSound AmplitudeTier_to_Sound (AmplitudeTier me, double samplingFrequency, long interpolationDepth) { try { long sound_nt = 1 + (long) floor ((my xmax - my xmin) * samplingFrequency); // >= 1 double dt = 1.0 / samplingFrequency; double tmid = (my xmin + my xmax) / 2; double t1 = tmid - 0.5 * (sound_nt - 1) * dt; double *sound; autoSound thee = Sound_create (1, my xmin, my xmax, sound_nt, dt, t1); sound = thy z [1]; for (long it = 1; it <= my points -> size; it ++) { RealPoint point = (RealPoint) my points -> item [it]; double t = point -> number, amplitude = point -> value, angle, halfampsinangle; long mid = Sampled_xToNearestIndex (thee.peek(), t), j; long begin = mid - interpolationDepth, end = mid + interpolationDepth; if (begin < 1) begin = 1; if (end > thy nx) end = thy nx; angle = NUMpi * (Sampled_indexToX (thee.peek(), begin) - t) / thy dx; halfampsinangle = 0.5 * amplitude * sin (angle); for (j = begin; j <= end; j ++) { if (fabs (angle) < 1e-6) sound [j] += amplitude; else if (angle < 0.0) sound [j] += halfampsinangle * (1 + cos (angle / (mid - begin + 1))) / angle; else sound [j] += halfampsinangle * (1 + cos (angle / (end - mid + 1))) / angle; angle += NUMpi; halfampsinangle = - halfampsinangle; } } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Sound."); } }
Spectrum Spectrogram_to_Spectrum (I, double tim) { iam (Spectrogram); try { autoSpectrum thee = Spectrum_create (my ymax, my ny); /* Override stupid Spectrum values. */ thy xmin = my ymin; thy xmax = my ymax; thy x1 = my y1; // centre of first band, instead of 0 (makes it unFFTable) thy dx = my dy; // frequency step long itime = Sampled_xToNearestIndex (me, tim); if (itime < 1 ) itime = 1; if (itime > my nx) itime = my nx; for (long ifreq = 1; ifreq <= my ny; ifreq ++) { double value = my z [ifreq] [itime]; if (value < 0.0) Melder_throw (U"Negative values in spectrogram."); thy z [1] [ifreq] = sqrt (value); thy z [2] [ifreq] = 0.0; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": spectral slice not extracted."); } }
Sound PointProcess_to_Sound_phonation (PointProcess me, double samplingFrequency, double adaptFactor, double maximumPeriod, double openPhase, double collisionPhase, double power1, double power2) { try { long sound_nt = 1 + floor ((my xmax - my xmin) * samplingFrequency); // >= 1 double dt = 1.0 / samplingFrequency; double tmid = (my xmin + my xmax) / 2; double t1 = tmid - 0.5 * (sound_nt - 1) * dt; double a = (power1 + power2 + 1.0) / (power2 - power1); double re = openPhase - collisionPhase; autoSound thee = Sound_create (1, my xmin, my xmax, sound_nt, dt, t1); /* * Compute "re" by iteration. */ if (collisionPhase <= 0.0) { re = openPhase; } else { double xmaxFlow = pow (power1 / power2, 1.0 / (power2 - power1)); double xleft = xmaxFlow; double gleft = pow (xleft, power1) - pow (xleft, power2); double gderivleft = power1 * pow (xleft, power1 - 1.0) - power2 * pow (xleft, power2 - 1.0); double fleft = - gleft / gderivleft; double xright = 1.0; double gright = pow (xright, power1) - pow (xright, power2); double gderivright = power1 * pow (xright, power1 - 1.0) - power2 * pow (xright, power2 - 1.0); double fright = - gright / gderivright; for (int i = 1; i <= 50; i ++) { double xmid = 0.5 * (xleft + xright); double gmid = pow (xmid, power1) - pow (xmid, power2); double gderivmid = power1 * pow (xmid, power1 - 1.0) - power2 * pow (xmid, power2 - 1.0); double fmid = - gmid / gderivmid; if (fmid > collisionPhase / openPhase) { xleft = xmid; fleft = fmid; } else { xright = xmid; fright = fmid; } re = xmid * openPhase; } } /* * Cycle through the points. Each will become a period. */ double *sound = thy z [1]; for (long it = 1; it <= my nt; it ++) { double t = my t [it], amplitude = a; double period = NUMundefined, te, phase, flow; long midSample = Sampled_xToNearestIndex (thee.peek(), t); /* * Determine the period: first look left (because that's where the open phase is), * then right. */ if (it >= 2) { period = my t [it] - my t [it - 1]; if (period > maximumPeriod) { period = NUMundefined; } } if (period == NUMundefined) { if (it < my nt) { period = my t [it + 1] - my t [it]; if (period > maximumPeriod) { period = NUMundefined; } } if (period == NUMundefined) { period = 0.5 * maximumPeriod; /* Some default value. */ } } te = re * period; /* * Determine the amplitude of this peak. */ amplitude /= period * openPhase; if (it == 1 || my t [it - 1] < my t [it] - maximumPeriod) { amplitude *= adaptFactor * adaptFactor; } else if (it == 2 || my t [it - 2] < my t [it - 1] - maximumPeriod) { amplitude *= adaptFactor; } /* * Fill in the samples to the left of the current point. */ {// scope long beginSample = midSample - floor (te / thy dx); if (beginSample < 1) beginSample = 1; long endSample = midSample; if (endSample > thy nx) endSample = thy nx; for (long isamp = beginSample; isamp <= endSample; isamp ++) { double tsamp = thy x1 + (isamp - 1) * thy dx; phase = (tsamp - (t - te)) / (period * openPhase); if (phase > 0.0) sound [isamp] += amplitude * (power1 * pow (phase, power1 - 1.0) - power2 * pow (phase, power2 - 1.0)); } } /* * Determine the signal parameters at the current point. */ phase = te / (period * openPhase); flow = amplitude * (period * openPhase) * (pow (phase, power1) - pow (phase, power2)); /* * Fill in the samples to the right of the current point. */ if (flow > 0.0) { double flowDerivative = amplitude * (power1 * pow (phase, power1 - 1.0) - power2 * pow (phase, power2 - 1.0)); double ta = - flow / flowDerivative; double factorPerSample = exp (- thy dx / ta); double value = flowDerivative * factorPerSample; long beginSample = midSample + 1; if (beginSample < 1) beginSample = 1; long endSample = midSample + floor (20 * ta / thy dx); if (endSample > thy nx) endSample = thy nx; for (long isamp = beginSample; isamp <= endSample; isamp ++) { sound [isamp] += value; value *= factorPerSample; } } } Vector_scale (thee.peek(), 0.9); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Sound (phonation)."); } }
double CC_getC0ValueAtTime (CC me, double t) { long iframe = Sampled_xToNearestIndex (me, t); return CC_getC0ValueInFrame (me, iframe); }
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."); } }