double Function_window (double tim, int windowType) { static double one_by_bessi_0_12, one_by_bessi_0_20; switch (windowType) { case Function_RECTANGULAR: if (tim < -0.5 || tim > 0.5) return 0.0; return 1; case Function_TRIANGULAR: if (tim < -0.5 || tim > 0.5) return 0.0; return 1 - tim - tim; case Function_PARABOLIC: if (tim < -0.5 || tim > 0.5) return 0.0; return 1 - 4 * tim * tim; case Function_HANNING: if (tim < -0.5 || tim > 0.5) return 0.0; return 0.5 + 0.5 * cos (2 * NUMpi * tim); case Function_HAMMING: if (tim < -0.5 || tim > 0.5) return 0.0; return 0.54 + 0.46 * cos (2 * NUMpi * tim); case Function_POTTER: if (tim < -0.77 || tim > 0.77) return 0.0; return 0.54 + 0.46 * cos (2 * NUMpi * tim); case Function_KAISER12: if (tim < -0.77 || tim > 0.77) return 0.0; if (one_by_bessi_0_12 == 0.0) one_by_bessi_0_12 = 1.0 / NUMbessel_i0_f (12); return NUMbessel_i0_f (12 * sqrt (1 - (1.0 / 0.77 / 0.77) * tim * tim)) * one_by_bessi_0_12; case Function_KAISER20: if (tim <= -1 || tim >= 1) return 0.0; if (one_by_bessi_0_20 == 0.0) one_by_bessi_0_20 = 1.0 / NUMbessel_i0_f (20.24); return NUMbessel_i0_f (20.24 * sqrt (1 - tim * tim)) * one_by_bessi_0_20; case Function_GAUSSIAN: return exp ((- NUMpi * NUMpi) * tim * tim); default: return 0.0; } }
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."); } }
void Sound_multiplyByWindow (Sound me, enum kSound_windowShape windowShape) { for (long channel = 1; channel <= my ny; channel ++) { long i, n = my nx; double *amp = my z [channel]; double imid, edge, onebyedge1, factor; switch (windowShape) { case kSound_windowShape_RECTANGULAR: ; break; case kSound_windowShape_TRIANGULAR: /* "Bartlett" */ for (i = 1; i <= n; i ++) { double phase = (double) i / n; /* 0..1 */ amp [i] *= 1.0 - fabs ((2.0 * phase - 1.0)); } break; case kSound_windowShape_PARABOLIC: /* "Welch" */ for (i = 1; i <= n; i ++) { double phase = (double) i / n; amp [i] *= 1.0 - (2.0 * phase - 1.0) * (2.0 * phase - 1.0); } break; case kSound_windowShape_HANNING: for (i = 1; i <= n; i ++) { double phase = (double) i / n; amp [i] *= 0.5 * (1.0 - cos (2.0 * NUMpi * phase)); } break; case kSound_windowShape_HAMMING: for (i = 1; i <= n; i ++) { double phase = (double) i / n; amp [i] *= 0.54 - 0.46 * cos (2.0 * NUMpi * phase); } break; case kSound_windowShape_GAUSSIAN_1: imid = 0.5 * (n + 1), edge = exp (-3.0), onebyedge1 = 1 / (1.0 - edge); /* -0.5..+0.5 */ for (i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n; amp [i] *= (exp (-12.0 * phase * phase) - edge) * onebyedge1; } break; case kSound_windowShape_GAUSSIAN_2: imid = 0.5 * (double) (n + 1), edge = exp (-12.0), onebyedge1 = 1 / (1.0 - edge); for (i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n; amp [i] *= (exp (-48.0 * phase * phase) - edge) * onebyedge1; } break; case kSound_windowShape_GAUSSIAN_3: imid = 0.5 * (double) (n + 1), edge = exp (-27.0), onebyedge1 = 1 / (1.0 - edge); for (i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n; amp [i] *= (exp (-108.0 * phase * phase) - edge) * onebyedge1; } break; case kSound_windowShape_GAUSSIAN_4: imid = 0.5 * (double) (n + 1), edge = exp (-48.0), onebyedge1 = 1 / (1.0 - edge); for (i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n; amp [i] *= (exp (-192.0 * phase * phase) - edge) * onebyedge1; } break; case kSound_windowShape_GAUSSIAN_5: imid = 0.5 * (double) (n + 1), edge = exp (-75.0), onebyedge1 = 1 / (1.0 - edge); for (i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n; amp [i] *= (exp (-300.0 * phase * phase) - edge) * onebyedge1; } break; case kSound_windowShape_KAISER_1: imid = 0.5 * (double) (n + 1); factor = 1 / NUMbessel_i0_f (2 * NUMpi); for (i = 1; i <= n; i ++) { double phase = 2 * ((double) i - imid) / n; /* -1..+1 */ double root = 1 - phase * phase; amp [i] *= root <= 0.0 ? 0.0 : factor * NUMbessel_i0_f (2 * NUMpi * sqrt (root)); } break; case kSound_windowShape_KAISER_2: imid = 0.5 * (double) (n + 1); factor = 1 / NUMbessel_i0_f (2 * NUMpi * NUMpi + 0.5); for (i = 1; i <= n; i ++) { double phase = 2 * ((double) i - imid) / n; /* -1..+1 */ double root = 1 - phase * phase; amp [i] *= root <= 0.0 ? 0.0 : factor * NUMbessel_i0_f ((2 * NUMpi * NUMpi + 0.5) * sqrt (root)); } break; default: break; } } }