/* Analog formant filter response : H(f) = i f B / (f1^2 - f^2 + i f B) */ static int Sound_into_FormantFilter_frame (Sound me, FormantFilter thee, long frame, double bw) { Melder_assert (bw > 0); autoMatrix pv = Sound_to_spectralpower (me); double z1 = pv -> x1; double dz = pv -> dx; long nf = pv -> nx; for (long i = 1; i <= thy ny; i++) { double p = 0; double fc = thy y1 + (i - 1) * thy dy; double *pow = pv -> z[1]; for (long j = 1; j <= nf; j++) { // H(f) = ifB / (fc^2 - f^2 + ifB) // H(f)| = fB / sqrt ((fc^2 - f^2)^2 + f^2B^2) //|H(f)|^2 = f^2B^2 / ((fc^2 - f^2)^2 + f^2B^2) // = 1 / (((fc^2 - f^2) /fB)^2 + 1) double f = z1 + (j - 1) * dz; double a = NUMformantfilter_amplitude (fc, bw, f); p += a * pow[j]; } thy z[i][frame] = p; } return 1; }
void FormantFilter_drawFilterFunctions (FormantFilter me, Graphics g, double bandwidth, int toFreqScale, int fromFilter, int toFilter, double zmin, double zmax, int dbScale, double ymin, double ymax, int garnish) { if (! checkLimits (me, FilterBank_HERTZ, toFreqScale, & fromFilter, & toFilter, & zmin, & zmax, dbScale, & ymin, & ymax)) { return; } if (bandwidth <= 0) { Melder_warning (U"Bandwidth must be greater than zero."); } long n = 1000; autoNUMvector<double>a (1, n); Graphics_setInner (g); Graphics_setWindow (g, zmin, zmax, ymin, ymax); for (long j = fromFilter; j <= toFilter; j++) { double df = (zmax - zmin) / (n - 1); double fc = my y1 + (j - 1) * my dy; long ibegin, iend; for (long i = 1; i <= n; i++) { double f = zmin + (i - 1) * df; double z = scaleFrequency (f, toFreqScale, FilterBank_HERTZ); if (z == NUMundefined) { a[i] = NUMundefined; } else { a[i] = NUMformantfilter_amplitude (fc, bandwidth, z); if (dbScale) { a[i] = to_dB (a[i], 10, ymin); } } } setDrawingLimits (a.peek(), n, ymin, ymax, &ibegin, &iend); if (ibegin <= iend) { double fmin = zmin + (ibegin - 1) * df; double fmax = zmax - (n - iend) * df; Graphics_function (g, a.peek(), ibegin, iend, fmin, fmax); } } Graphics_unsetInner (g); if (garnish) { double distance = dbScale ? 10 : 1; char32 const *ytext = dbScale ? U"Amplitude (dB)" : U"Amplitude"; Graphics_drawInnerBox (g); Graphics_marksBottom (g, 2, 1, 1, 0); Graphics_marksLeftEvery (g, 1, distance, 1, 1, 0); Graphics_textLeft (g, 1, ytext); Graphics_textBottom (g, 1, GetFreqScaleText (toFreqScale)); } }
/* Analog formant filter response : H(f) = i f B / (f1^2 - f^2 + i f B) */ static int Sound_into_Spectrogram_frame (Sound me, Spectrogram thee, long frame, double bw) { Melder_assert (bw > 0); autoSpectrum him = Sound_to_Spectrum_power (me); for (long ifilter = 1; ifilter <= thy ny; ifilter ++) { double p = 0; double fc = thy y1 + (ifilter - 1) * thy dy; double *pow = his z [1]; for (long ifreq = 1; ifreq <= his nx; ifreq ++) { // H(f) = ifB / (fc^2 - f^2 + ifB) // H(f)| = fB / sqrt ((fc^2 - f^2)^2 + f^2B^2) //|H(f)|^2 = f^2B^2 / ((fc^2 - f^2)^2 + f^2B^2) // = 1 / (((fc^2 - f^2) /fB)^2 + 1) double f = his x1 + (ifreq - 1) * his dx; double a = NUMformantfilter_amplitude (fc, bw, f); p += a * pow[ifreq]; } thy z[ifilter][frame] = p; } return 1; }