Sound FilterBanks_convolve (FilterBank me, FilterBank thee, enum kSounds_convolve_scaling scaling, enum kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
	try {
		autoSound cc = Sounds_convolve ((Sound) me, (Sound) thee, scaling, signalOutsideTimeDomain);
		return cc.transfer();
	} catch (MelderError) {
		Melder_throw (me, " and ", thee, " not convolved.");
	}
}
autoSound BandFilterSpectrograms_convolve (BandFilterSpectrogram me, BandFilterSpectrogram thee, enum kSounds_convolve_scaling scaling, enum kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
	try {
		autoSound sme = BandFilterSpectrogram_as_Sound (me, 1);   // to dB
		autoSound sthee = BandFilterSpectrogram_as_Sound (thee, 1);
		autoSound cc = Sounds_convolve (sme.get(), sthee.get(), scaling, signalOutsideTimeDomain);
		return cc;
	} catch (MelderError) {
		Melder_throw (me, U" and ", thee, U" not convolved.");
	}
}
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).");
	}
}
Beispiel #4
0
SPINET Sound_to_SPINET (Sound me, double timeStep, double windowDuration,
	double minimumFrequencyHz, double maximumFrequencyHz, long nFilters,
	double excitationErbProportion, double inhibitionErbProportion)
{
	Sound window = NULL, frame = NULL; SPINET thee = NULL;
	long i, j, k, numberOfFrames;
	double firstTime, b = 1.02, samplingFrequency = 1 / my dx;
	double *f = NULL, *bw = NULL, *aex = NULL, *ain = NULL;

	if (timeStep < my dx) timeStep = my dx;
	if (maximumFrequencyHz > samplingFrequency / 2) maximumFrequencyHz = samplingFrequency / 2;

	if (! Sampled_shortTermAnalysis (me, windowDuration, timeStep, &numberOfFrames, &firstTime) ||
		! (thee = SPINET_create (my xmin, my xmax, numberOfFrames, timeStep, firstTime,
			minimumFrequencyHz, maximumFrequencyHz, nFilters,
			excitationErbProportion, inhibitionErbProportion)) ||
		! (window = Sound_createGaussian (windowDuration, samplingFrequency)) ||
		! (frame = Sound_createSimple (1, windowDuration, samplingFrequency)) ||
		! (f = NUMdvector (1, nFilters)) || ! (bw = NUMdvector (1, nFilters)) ||
		! (aex = NUMdvector (1, nFilters)) || ! (ain = NUMdvector (1, nFilters))) goto cleanup;

	/*
		Cochlear filterbank: gammatone
	*/

	for (i=1; i <= nFilters; i++)
	{
		f[i] = NUMerbToHertz (thy y1 + (i - 1) * thy dy);
		bw[i] = 2 * NUMpi * b * (f[i] * (6.23e-6 * f[i] + 93.39e-3) + 28.52);
	}

	Melder_progress1 (0.0, L"SPINET analysis");

	for (i=1; i <= nFilters; i++)
	{
		Sound gammaTone = NULL, filtered = NULL;
		/* Contribution of outer & middle ear and phase locking */
		double bb = (f[i] / 1000) * exp (- f[i] / 1000);
		/* Time where gammafunction envelope has its maximum */
		double tgammaMax = (thy gamma - 1) / bw[i];
		/* Amplitude at tgammaMax */
		double gammaMaxAmplitude = pow ((thy gamma - 1) / (NUMe * bw[i]), (thy gamma - 1));
		double timeCorrection = tgammaMax - windowDuration / 2;
		if (! (gammaTone = Sound_createGammaTone (0, 0.1, samplingFrequency,
				thy gamma, b, f[i], 0, 0, 0)) ||
			/* filtering can be made 30% faster by taking Spectrum(me) outside the loop */
			! (filtered = Sounds_convolve (me, gammaTone, kSounds_convolve_scaling_SUM, kSounds_convolve_signalOutsideTimeDomain_ZERO))) { forget (gammaTone); goto cleanup; }
		/*
			To energy measure: weigh with broad-band transfer function
		*/
		for (j=1; j <= numberOfFrames; j++)
		{
			Sound_into_Sound (filtered, frame, Sampled_indexToX (thee, j) + timeCorrection);
			Sounds_multiply (frame, window);
			thy y[i][j] = Sound_power (frame) * bb / gammaMaxAmplitude;
		}
		forget (filtered); forget (gammaTone);
		if (! Melder_progress5 ((double)i / nFilters, L"SPINET: filter ", Melder_integer (i), L" from ",
			Melder_integer (nFilters), L".")) goto cleanup;
	}

	/*
		Excitatory and inhibitory area functions
	*/

	for (i=1; i <= nFilters; i++)
	{
		for (k=1; k <= nFilters; k++)
		{
			double fr = (f[k] - f[i]) / bw[i];
			aex[i] += fgamma (fr / thy excitationErbProportion, thy gamma);
			ain[i] += fgamma (fr / thy inhibitionErbProportion, thy gamma);
		}
	}

	/*
		On-center off-surround interactions
	*/

	for (j=1; j <= numberOfFrames; j++)
		for (i=1; i <= nFilters; i++)
		{
			double a = 0;
			for (k=1; k <= nFilters; k++)
			{
				double fr = (f[k] - f[i]) / bw[i];
				double hexsq = fgamma (fr / thy excitationErbProportion, thy gamma);
				double hinsq = fgamma (fr / thy inhibitionErbProportion, thy gamma);
				a += thy y[k][j] * (hexsq / aex[i] - hinsq / ain[i]);
			}
			thy s[i][j] = a > 0 ? a : 0;
		}
	Melder_progress1 (1.0, NULL);
cleanup:
	NUMdvector_free (aex, 1); NUMdvector_free (ain, 1);
	NUMdvector_free (f, 1); NUMdvector_free (bw, 1);
	forget (window); forget (frame);
	if (! Melder_hasError()) return thee;
	forget (thee);
	return Melder_errorp1 (L"Sound_to_SPINET: not performed.");
}
Beispiel #5
0
SPINET Sound_to_SPINET (Sound me, double timeStep, double windowDuration,
                        double minimumFrequencyHz, double maximumFrequencyHz, long nFilters,
                        double excitationErbProportion, double inhibitionErbProportion) {
	try {
		double firstTime, b = 1.02, samplingFrequency = 1 / my dx;

		if (timeStep < my dx) {
			timeStep = my dx;
		}
		if (maximumFrequencyHz > samplingFrequency / 2) {
			maximumFrequencyHz = samplingFrequency / 2;
		}

		long numberOfFrames;
		Sampled_shortTermAnalysis (me, windowDuration, timeStep, &numberOfFrames, &firstTime);
		autoSPINET thee = SPINET_create (my xmin, my xmax, numberOfFrames, timeStep, firstTime,
		                                 minimumFrequencyHz, maximumFrequencyHz, nFilters, excitationErbProportion, inhibitionErbProportion);
		autoSound window = Sound_createGaussian (windowDuration, samplingFrequency);
		autoSound frame = Sound_createSimple (1, windowDuration, samplingFrequency);
		autoNUMvector<double> f (1, nFilters);
		autoNUMvector<double> bw (1, nFilters);
		autoNUMvector<double> aex (1, nFilters);
		autoNUMvector<double> ain (1, nFilters);

		// Cochlear filterbank: gammatone

		for (long i = 1; i <= nFilters; i++) {
			f[i] = NUMerbToHertz (thy y1 + (i - 1) * thy dy);
			bw[i] = 2 * NUMpi * b * (f[i] * (6.23e-6 * f[i] + 93.39e-3) + 28.52);
		}

		autoMelderProgress progress (L"SPINET analysis");

		for (long i = 1; i <= nFilters; i++) {
			double bb = (f[i] / 1000) * exp (- f[i] / 1000); // outer & middle ear and phase locking
			double tgammaMax = (thy gamma - 1) / bw[i]; // Time where gammafunction envelope has maximum
			double gammaMaxAmplitude = pow ( (thy gamma - 1) / (NUMe * bw[i]), (thy gamma - 1)); // tgammaMax
			double timeCorrection = tgammaMax - windowDuration / 2;

			autoSound gammaTone = Sound_createGammaTone (0, 0.1, samplingFrequency,
			                      thy gamma, b, f[i], 0, 0, 0);
			autoSound filtered = Sounds_convolve (me, gammaTone.peek(), kSounds_convolve_scaling_SUM, kSounds_convolve_signalOutsideTimeDomain_ZERO);

			// To energy measure: weigh with broad-band transfer function

			for (long j = 1; j <= numberOfFrames; j++) {
				Sound_into_Sound (filtered.peek(), frame.peek(), Sampled_indexToX (thee.peek(), j) + timeCorrection);
				Sounds_multiply (frame.peek(), window.peek());
				thy y[i][j] = Sound_power (frame.peek()) * bb / gammaMaxAmplitude;
			}
			Melder_progress ( (double) i / nFilters, L"SPINET: filter ", Melder_integer (i), L" from ",
			                   Melder_integer (nFilters), L".");
		}

		// Excitatory and inhibitory area functions

		for (long i = 1; i <= nFilters; i++) {
			for (long k = 1; k <= nFilters; k++) {
				double fr = (f[k] - f[i]) / bw[i];
				aex[i] += fgamma (fr / thy excitationErbProportion, thy gamma);
				ain[i] += fgamma (fr / thy inhibitionErbProportion, thy gamma);
			}
		}

		// On-center off-surround interactions

		for (long j = 1; j <= numberOfFrames; j++)
			for (long i = 1; i <= nFilters; i++) {
				double a = 0;
				for (long k = 1; k <= nFilters; k++) {
					double fr = (f[k] - f[i]) / bw[i];
					double hexsq = fgamma (fr / thy excitationErbProportion, thy gamma);
					double hinsq = fgamma (fr / thy inhibitionErbProportion, thy gamma);
					a += thy y[k][j] * (hexsq / aex[i] - hinsq / ain[i]);
				}
				thy s[i][j] = a > 0 ? a : 0;
			}
		return thee.transfer();
	} catch (MelderError) {
		Melder_throw (me, ":  no SPINET created.");
	}
}