Formant Excitation_to_Formant (Excitation me, int maxnFormants) { Formant thee = NULL; long i, nfreq = my nx, nform = 0; double *p = my z [1]; thee = Formant_create (0, 1, 1, 1, 0.5, maxnFormants); if (! thee) return NULL; thy frame [1]. formant = NUMstructvector (Formant_Formant, 1, maxnFormants); for (i = 2; i < nfreq; i ++) if (p [i] > p [i - 1] && p [i] >= p [i + 1]) { double min3phon, left, right; double firstDerivative = p [i+1] - p [i-1], secondDerivative = 2 * p [i] - p [i-1] - p [i+1]; long j; Formant_Formant formant = & thy frame [1]. formant [++ nform]; formant -> frequency = Excitation_barkToHertz ( my x1 + my dx * (i - 1 + 0.5 * firstDerivative / secondDerivative)); min3phon = p [i] + 0.125 * firstDerivative * firstDerivative / secondDerivative - 3.0; /* Search left. */ j = i - 1; while (p [j] > min3phon && j > 1) j --; left = Excitation_barkToHertz ( p [j] > min3phon ? my xmin : my x1 + my dx * (j - 1 + (min3phon - p [j]) / (p [j + 1] - p [j]))); /* Search right. */ j = i + 1; while (p [j] > min3phon && j < nfreq) j ++; right = Excitation_barkToHertz ( p [j] > min3phon ? my xmax : my x1 + my dx * (j - 1 - (min3phon - p [j]) / (p [j - 1] - p [j]))); formant -> bandwidth = right - left; if (nform == thy maxnFormants) break; } thy frame [1]. nFormants = nform; return thee; }
autoFormant Excitation_to_Formant (Excitation me, int maxnFormants) { try { long nfreq = my nx, nform = 0; double *p = my z [1]; autoFormant thee = Formant_create (0, 1, 1, 1, 0.5, maxnFormants); thy d_frames [1]. formant = NUMvector <structFormant_Formant> (1, maxnFormants); for (long i = 2; i < nfreq; i ++) if (p [i] > p [i - 1] && p [i] >= p [i + 1]) { double min3phon, left, right; double firstDerivative = p [i+1] - p [i-1], secondDerivative = 2 * p [i] - p [i-1] - p [i+1]; long j; Formant_Formant formant = & thy d_frames [1]. formant [++ nform]; formant -> frequency = Excitation_barkToHertz ( my x1 + my dx * (i - 1 + 0.5 * firstDerivative / secondDerivative)); min3phon = p [i] + 0.125 * firstDerivative * firstDerivative / secondDerivative - 3.0; /* Search left. */ j = i - 1; while (p [j] > min3phon && j > 1) j --; left = Excitation_barkToHertz ( p [j] > min3phon ? my xmin : my x1 + my dx * (j - 1 + (min3phon - p [j]) / (p [j + 1] - p [j]))); /* Search right. */ j = i + 1; while (p [j] > min3phon && j < nfreq) j ++; right = Excitation_barkToHertz ( p [j] > min3phon ? my xmax : my x1 + my dx * (j - 1 - (min3phon - p [j]) / (p [j - 1] - p [j]))); formant -> bandwidth = right - left; if (nform == thy maxnFormants) break; } thy d_frames [1]. nFormants = nform; return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Formant."); } }
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."); } }
Cochleagram Sound_to_Cochleagram_edb (Sound me, double dtime, double dfreq, int hasSynapse, double replenishmentRate, double lossRate, double returnRate, double reprocessingRate) { try { double duration_seconds = my xmax; if (dtime < my dx) dtime = my dx; long ntime = floor (duration_seconds / dtime + 0.5); if (ntime < 2) return NULL; long nfreq = floor (25.6 / dfreq + 0.5); // 25.6 Bark = highest frequency autoCochleagram thee = Cochleagram_create (my xmin, my xmax, ntime, dtime, 0.5 * dtime, dfreq, nfreq); /* Stages 1 and 2: outer- and middle-ear filtering. */ /* From acoustic sound to oval window. */ for (long ifreq = 1; ifreq <= nfreq; ifreq ++) { double *response = thy z [ifreq]; /* Stage 3: basilar membrane filtering by gammatones. */ /* From oval window to basilar membrane response. */ double midFrequency_Bark = (ifreq - 0.5) * dfreq; double midFrequency_Hertz = Excitation_barkToHertz (midFrequency_Bark); autoSound gammatone = createGammatone (midFrequency_Hertz, 1 / my dx); autoSound basil = Sounds_convolve (me, gammatone.peek(), kSounds_convolve_scaling_SUM, kSounds_convolve_signalOutsideTimeDomain_ZERO); /* Stage 4: detection = rectify + integrate + low-pass 500 Hz. */ /* From basilar membrane response to firing rate. */ if (hasSynapse) { double dt = my dx; double M = 1; /* Maximum free transmitter. */ double A = 5, B = 300, g = 2000; /* Determine permeability. */ double y = replenishmentRate; /* Meddis: 5.05 */ double l = lossRate, r = returnRate; /* Meddis: 2500, 6580 */ double x = reprocessingRate; /* Meddis: 66.31 */ double h = 50000; /* Convert cleft contents to firing rate. */ double gdt = 1 - exp (- g * dt), ydt = 1 - exp (- y * dt), ldt = (1 - exp (- (l + r) * dt)) * l / (l + r), rdt = (1 - exp (- (l + r) * dt)) * r / (l + r), xdt = 1 - exp (- x * dt); double kt = g * A / (A + B); /* Membrane permeability. */ double c = M * y * kt / (l * kt + y * (l + r)); /* Cleft contents. */ double q = c * (l + r) / kt; /* Free transmitter. */ double w = c * r / x; /* Reprocessing store. */ for (long itime = 1; itime <= basil -> nx; itime ++) { double splusA = basil -> z [1] [itime] * 10 + A; double replenish = M > q ? ydt * (M - q) : 0; double eject, loss, reuptake, reprocess; kt = splusA > 0 ? gdt * splusA / (splusA + B) : 0; eject = kt * q; loss = ldt * c; reuptake = rdt * c; reprocess = xdt * w; q = q + replenish - eject + reprocess; c = c + eject - loss - reuptake; w = w + reuptake - reprocess; basil -> z [1] [itime] = h * c; } } if (dtime == my dx) { for (long itime = 1; itime <= ntime; itime ++) response [itime] = basil -> z [1] [itime]; } else { double d = dtime / basil -> dx / 2; double factor = -6 / d / d; double area = d * sqrt (NUMpi / 6); double expmin6 = exp (-6), onebyoneminexpmin6 = 1 / (1 - expmin6); for (long itime = 1; itime <= ntime; itime ++) { double t1 = (itime - 1) * dtime, t2 = t1 + dtime, mean = 0; long i1, i2; long n = Matrix_getWindowSamplesX (basil.peek(), t1, t2, & i1, & i2); Melder_assert (n >= 1); if (n <= 2) { for (long isamp = i1; isamp <= i2; isamp ++) mean += basil -> z [1] [isamp]; mean /= n; } else { double mu = floor ((i1 + i2) / 2.0); long muint = mu, dint = d; for (long isamp = muint - dint; isamp <= muint + dint; isamp ++) { double y = 0; if (isamp < 1 || isamp > basil -> nx) Melder_casual ("isamp %ld", isamp); else y = basil -> z [1] [isamp]; mean += y * onebyoneminexpmin6 * (exp (factor * (isamp - muint) * (isamp - muint)) - expmin6); } mean /= area; } response [itime] = mean; } } } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not converted to Cochleagram (edb)."); } }