示例#1
0
void PitchTier_shiftFrequencies (PitchTier me, double tmin, double tmax, double shift, int unit) {
	try {
		for (long i = 1; i <= my points -> size; i ++) {
			RealPoint point = (RealPoint) my points -> item [i];
			double frequency = point -> value;
			if (point -> number < tmin || point -> number > tmax) continue;
			switch (unit) {
				case kPitch_unit_HERTZ: {	
					frequency += shift;
					if (frequency <= 0.0)
						Melder_throw ("The resulting frequency has to be greater than 0 Hz.");
				} break; case kPitch_unit_MEL: {
					frequency = NUMhertzToMel (frequency) + shift;
					if (frequency <= 0.0)
						Melder_throw ("The resulting frequency has to be greater than 0 mel.");
					frequency = NUMmelToHertz (frequency);
				} break; case kPitch_unit_LOG_HERTZ: {
					frequency = pow (10.0, log10 (frequency) + shift);
				} break; case kPitch_unit_SEMITONES_1: {
					frequency = NUMsemitonesToHertz (NUMhertzToSemitones (frequency) + shift);
				} break; case kPitch_unit_ERB: {
					frequency = NUMhertzToErb (frequency) + shift;
					if (frequency <= 0.0)
						Melder_throw ("The resulting frequency has to be greater than 0 ERB.");
					frequency = NUMerbToHertz (frequency);
				}
			}
			point -> value = frequency;
		}
	} catch (MelderError) {
		Melder_throw (me, ": not all frequencies were shifted.");
	}
}
示例#2
0
static double SpecialToHertz (double value, int pitchUnit) {
	return	pitchUnit == kPitch_unit_HERTZ ? value :
	        pitchUnit == kPitch_unit_HERTZ_LOGARITHMIC ? pow (10.0, value) :
	        pitchUnit == kPitch_unit_MEL ? NUMmelToHertz (value) :
	        pitchUnit == kPitch_unit_LOG_HERTZ ? pow (10.0, value) :
	        pitchUnit == kPitch_unit_SEMITONES_1 ? 1.0 * exp (value * (NUMln2 / 12.0)) :
	        pitchUnit == kPitch_unit_SEMITONES_100 ? 100.0 * exp (value * (NUMln2 / 12.0)) :
	        pitchUnit == kPitch_unit_SEMITONES_200 ? 200.0 * exp (value * (NUMln2 / 12.0)) :
	        pitchUnit == kPitch_unit_SEMITONES_440 ? 440.0 * exp (value * (NUMln2 / 12.0)) :
	        pitchUnit == kPitch_unit_ERB ? NUMerbToHertz (value) : NUMundefined;
}
示例#3
0
文件: Pitch.cpp 项目: DsRQuicke/praat
double structPitch :: v_convertSpecialToStandardUnit (double value, long ilevel, int unit) {
	if (ilevel == Pitch_LEVEL_FREQUENCY) {
		return
			unit == kPitch_unit_HERTZ ? value :
			unit == kPitch_unit_HERTZ_LOGARITHMIC ? pow (10.0, value) :
			unit == kPitch_unit_MEL ? NUMmelToHertz (value) :
			unit == kPitch_unit_LOG_HERTZ ? pow (10.0, value) :
			unit == kPitch_unit_SEMITONES_1 ? 1.0 * exp (value * (NUMln2 / 12.0)):
			unit == kPitch_unit_SEMITONES_100 ? 100.0 * exp (value * (NUMln2 / 12.0)):
			unit == kPitch_unit_SEMITONES_200 ? 200.0 * exp (value * (NUMln2 / 12.0)):
			unit == kPitch_unit_SEMITONES_440 ? 440.0 * exp (value * (NUMln2 / 12.0)):
			unit == kPitch_unit_ERB ? NUMerbToHertz (value) :
			NUMundefined;
	} else {
		return NUMundefined;
	}
}
示例#4
0
autoPitch SPINET_to_Pitch (SPINET me, double harmonicFallOffSlope, double ceiling, int maxnCandidates) {
	try {
		long nPointsPerOctave = 48;
		double fmin = NUMerbToHertz (Sampled2_rowToY (me, 1));
		double fmax = NUMerbToHertz (Sampled2_rowToY (me, my ny));
		double fminl2 = NUMlog2 (fmin), fmaxl2 = NUMlog2 (fmax);
		double points = (fmaxl2 - fminl2) * nPointsPerOctave;
		double dfl2 = (fmaxl2 - fminl2) / (points - 1);
		long nFrequencyPoints = (long) floor (points);
		long maxHarmonic = (long) floor (fmax / fmin);
		double maxStrength = 0.0, unvoicedCriterium = 0.45, maxPower = 0.0;

		if (nFrequencyPoints < 2) {
			Melder_throw (U"Frequency range too small.");
		}
		if (ceiling <= fmin) {
			Melder_throw (U"Ceiling is smaller than centre frequency of lowest filter.");
		}

		autoPitch thee = Pitch_create (my xmin, my xmax, my nx, my dx, my x1, ceiling, maxnCandidates);
		autoNUMvector<double> power (1, my nx);
		autoNUMvector<double> pitch (1, nFrequencyPoints);
		autoNUMvector<double> sumspec (1, nFrequencyPoints);
		autoNUMvector<double> y (1, my ny);
		autoNUMvector<double> yv2 (1, my ny);
		autoNUMvector<double> fl2 (1, my ny);

		// From ERB's to log (f)

		for (long i = 1; i <= my ny; i++) {
			double f = NUMerbToHertz (my y1 + (i - 1) * my dy);
			fl2[i] = NUMlog2 (f);
		}

		// Determine global maximum power in frame

		for (long j = 1; j <= my nx; j++) {
			double p = 0.0;
			for (long i = 1; i <= my ny; i++) {
				p += my s[i][j];
			}
			if (p > maxPower) {
				maxPower = p;
			}
			power[j] = p;
		}
		if (maxPower == 0.0) {
			Melder_throw (U"No power");
		}

		for (long j = 1; j <= my nx; j++) {
			Pitch_Frame pitchFrame = &thy frame[j];

			pitchFrame -> intensity = power[j] / maxPower;
			for (long i = 1; i <= my ny; i++) {
				y[i] = my s[i][j];
			}
			NUMspline (fl2.peek(), y.peek(), my ny, 1e30, 1e30, yv2.peek());
			for (long k = 1; k <= nFrequencyPoints; k++) {
				double f = fminl2 + (k - 1) * dfl2;
				NUMsplint (fl2.peek(), y.peek(), yv2.peek(), my ny, f, & pitch[k]);
				sumspec[k] = 0.0;
			}

			// Formula (8): weighted harmonic summation.

			for (long m = 1; m <= maxHarmonic; m++) {
				double hm = 1 - harmonicFallOffSlope * NUMlog2 (m);
				long kb = 1 + (long) floor (nPointsPerOctave * NUMlog2 (m));
				for (long k = kb; k <= nFrequencyPoints; k++) {
					if (pitch[k] > 0.0) {
						sumspec[k - kb + 1] += pitch[k] * hm;
					}
				}
			}

			// into Pitch object

			Pitch_Frame_init (pitchFrame, maxnCandidates);
			pitchFrame -> nCandidates = 0; /* !!!!! */
			Pitch_Frame_addPitch (pitchFrame, 0, 0, maxnCandidates); /* unvoiced */

			for (long k = 2; k <= nFrequencyPoints - 1; k++) {
				double y1 = sumspec[k - 1], y2 = sumspec[k], y3 = sumspec[k + 1];
				if (y2 > y1 && y2 >= y3) {
					double denum = y1 - 2.0 * y2 + y3, tmp = y3 - 4.0 * y2;
					double x = dfl2 * (y1 - y3) / (2 * denum);
					double f = pow (2.0, fminl2 + (k - 1) * dfl2 + x);
					double strength = (2.0 * y1 * (4.0 * y2 + y3) - y1 * y1 - tmp * tmp) / (8.0 * denum);
					if (strength > maxStrength) {
						maxStrength = strength;
					}
					Pitch_Frame_addPitch (pitchFrame, f, strength, maxnCandidates);
				}
			}
		}

		// Scale the pitch strengths

		for (long j = 1; j <= my nx; j++) {
			double f0, localStrength;
			Pitch_Frame_getPitch (&thy frame[j], &f0, &localStrength);
			Pitch_Frame_resizeStrengths (&thy frame[j], localStrength / maxStrength, unvoicedCriterium);
		}
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": no Pitch created.");
	}
}
示例#5
0
Pitch SPINET_to_Pitch (SPINET me, double harmonicFallOffSlope, double ceiling, int maxnCandidates)
{
	Pitch thee = NULL;
	long i, j, k, m, nPointsPerOctave = 48;
	double fmin = NUMerbToHertz (Sampled2_rowToY (me, 1));
	double fmax = NUMerbToHertz (Sampled2_rowToY (me, my ny));
	double fminl2 = NUMlog2 (fmin), fmaxl2 = NUMlog2 (fmax);
	double points = (fmaxl2 - fminl2) * nPointsPerOctave;
	double dfl2 = (fmaxl2 - fminl2) / (points - 1);
	long nFrequencyPoints = points;
	long maxHarmonic = fmax / fmin;
	double maxStrength = 0, unvoicedCriterium = 0.45;
	double maxPower = 0, *sumspec = NULL, *power = NULL;
	double *y = NULL, *y2 = NULL, *pitch = NULL, *fl2 = NULL;
	
	if (nFrequencyPoints < 2) return Melder_errorp1 (L"SPINET_to_Pitch: frequency range too small.");
	if (ceiling <= fmin) return Melder_errorp1 (L"SPINET_to_Pitch: ceiling is smaller than centre "
		"frequency of lowest filter.");

	if (! (thee = Pitch_create (my xmin, my xmax, my nx, my dx, my x1,
				ceiling, maxnCandidates)) ||
		! (power = NUMdvector (1, my nx)) ||
		! (pitch = NUMdvector (1, nFrequencyPoints)) ||
		! (sumspec = NUMdvector (1, nFrequencyPoints)) ||
		! (y = NUMdvector (1, my ny)) ||
		! (y2 = NUMdvector (1, my ny)) ||
		! (fl2 = NUMdvector (1, my ny))) goto cleanup;
				
	/*
		From ERB's to log (f)
	*/
	
	for (i=1; i <= my ny; i++)
	{
		double f = NUMerbToHertz (my y1 + (i - 1) * my dy);
		fl2[i] = NUMlog2 (f);
	}
		
	/*
		Determine global maximum power in frame
	*/
	
	for (j=1; j <= my nx; j++)
	{
		double p = 0;
		for (i=1; i <= my ny; i++) p += my s[i][j];
		if (p > maxPower) maxPower = p;
		power[j] = p;
	}
	if (maxPower == 0) goto cleanup;
	
	for (j=1; j <= my nx; j++)
	{
		Pitch_Frame pitchFrame = &thy frame[j];
		
		pitchFrame->intensity = power[j] / maxPower;
		for (i=1; i <= my ny; i++) y[i] = my s[i][j];
		if (! NUMspline (fl2, y, my ny, 1e30, 1e30, y2)) goto cleanup; 
		for (k=1; k <= nFrequencyPoints; k++)
		{
			double f = fminl2 + (k-1) * dfl2;
			NUMsplint (fl2, y, y2, my ny, f, & pitch[k]);
			sumspec[k] = 0;
		}
		
		/*
			Formula (8): weighted harmonic summation.
		*/
		
		for (m=1; m <= maxHarmonic; m++)
		{
			double hm = 1 - harmonicFallOffSlope * NUMlog2 (m);
			long kb = 1 + floor (nPointsPerOctave * NUMlog2 (m));
			for (k=kb; k <= nFrequencyPoints; k++) 
			{
				if (pitch[k] > 0) sumspec[k-kb+1] += pitch[k] * hm;
			}
		}

		/*
			into Pitch object
		*/
		
		if (! Pitch_Frame_init (pitchFrame, maxnCandidates)) goto cleanup;
		pitchFrame->nCandidates = 0; /* !!!!! */
		Pitch_Frame_addPitch (pitchFrame, 0, 0, maxnCandidates); /* unvoiced */
			
		for (k=2; k <= nFrequencyPoints-1; k++)
		{
			double y1 = sumspec[k-1], y2 = sumspec[k], y3 = sumspec[k+1];
			if (y2 > y1 && y2 >= y3)
			{
				double denum = y1 - 2 * y2 + y3, tmp = y3 - 4 * y2;
				double x = dfl2 * (y1 - y3) / (2 * denum);
				double f = pow (2, fminl2 + (k - 1) * dfl2 + x);
				double strength = (2 * y1 * (4 * y2 + y3) - y1 * y1 - tmp * tmp) / (8 * denum);
				if (strength > maxStrength) maxStrength = strength;
				Pitch_Frame_addPitch (pitchFrame, f, strength, maxnCandidates);
			}	
		}
	}
	
	/*
		Scale the pitch strengths
	*/
	
	for (j=1; j <= my nx; j++)
	{
		double f0, localStrength;
		Pitch_Frame_getPitch (&thy frame[j], &f0, &localStrength);
		Pitch_Frame_resizeStrengths (&thy frame[j], localStrength / maxStrength, unvoicedCriterium);
	}
	
cleanup:
	NUMdvector_free (pitch, 1); NUMdvector_free (sumspec, 1);
	NUMdvector_free (y, 1); NUMdvector_free (y2, 1);
	NUMdvector_free (fl2, 1);NUMdvector_free (power, 1);
	if (! Melder_hasError()) return thee;
	forget (thee);
	return Melder_errorp1 (L"SPINET_to_Pitch: not performed.");
}
示例#6
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.");
}
示例#7
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.");
	}
}