예제 #1
0
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;
}
예제 #2
0
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.");
	}
}
예제 #3
0
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).");
	}
}