static autoSpectrum Cepstrum_to_Spectrum2 (Cepstrum me) { //TODO power cepstrum try { autoNUMfft_Table fftTable; long numberOfSamples = 2 * my nx - 2; autoNUMvector<double> fftbuf (1, numberOfSamples); autoSpectrum thee = Spectrum_create (0.5 / my dx, my nx); fftbuf[1] = sqrt (my z[1][1]); for (long i = 2; i <= my nx; i++) { fftbuf[i] = 2.0 * sqrt (my z[1][i]); } // fftbuf[my nx+1 ... numberOfSamples] = 0 NUMfft_Table_init (&fftTable, numberOfSamples); NUMfft_forward (&fftTable, fftbuf.peek()); thy z[1][1] = fabs (fftbuf[1]); for (long i = 2; i < my nx; i++) { double br = fftbuf[i + i - 2], bi = fftbuf[i + i - 1]; thy z[1][i] = sqrt (br * br + bi * bi); } thy z[1][my nx] = fabs (fftbuf[numberOfSamples]); for (long i = 1; i <= my nx; i++) { thy z[1][i] = exp (NUMln10 * thy z[1][i] / 20.0) * 2e-5 / sqrt (2 * thy dx); thy z[2][i] = 0.0; } return thee; } catch (MelderError) { Melder_throw (me, U": no Spectrum created."); } }
autoSpectrum Spectrum_compressFrequencyDomain (Spectrum me, double fmax, long interpolationDepth, int freqscale, int method) { try { double fdomain = my xmax - my xmin, factor = fdomain / fmax ; //long numberOfFrequencies = 1.0 + fmax / my dx; // keep dx the same, otherwise the "duration" changes double xmax = my xmax / factor; long numberOfFrequencies = (long) floor (my nx / factor); // keep dx the same, otherwise the "duration" changes autoSpectrum thee = Spectrum_create (xmax, numberOfFrequencies); thy z[1][1] = my z[1][1]; thy z[2][1] = my z[2][1]; double df = freqscale == 1 ? factor * my dx : log10 (fdomain) / (numberOfFrequencies - 1); for (long i = 2; i <= numberOfFrequencies; i++) { double f = my xmin + (freqscale == 1 ? (i - 1) * df : pow (10.0, (i - 1) * df)); double x, y, index = (f - my x1) / my dx + 1; if (index > my nx) { break; } if (method == 1) { x = NUM_interpolate_sinc (my z[1], my nx, index, interpolationDepth); y = NUM_interpolate_sinc (my z[2], my nx, index, interpolationDepth); } else { x = NUMundefined; // ppgb: better than data from random memory y = NUMundefined; } thy z[1][i] = x; thy z[2][i] = y; } return thee; } catch (MelderError) { Melder_throw (me, U": not compressed."); } }
Spectrum FormantFilter_to_Spectrum_slice (FormantFilter me, double t) { try { double sqrtref = sqrt (FilterBank_DBREF); double factor2 = 2 * 10 * FilterBank_DBFAC; autoSpectrum thee = Spectrum_create (my ymax, my ny); thy xmin = my ymin; thy xmax = my ymax; thy x1 = my y1; thy dx = my dy; /* Frequency step. */ long frame = Sampled_xToNearestIndex (me, t); if (frame < 1) { frame = 1; } if (frame > my nx) { frame = my nx; } for (long i = 1; i <= my ny; i++) { /* power = ref * 10 ^ (value / 10) sqrt(power) = sqrt(ref) * 10 ^ (value / (2*10)) */ thy z[1][i] = sqrtref * pow (10, my z[i][frame] / factor2); thy z[2][i] = 0.0; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": Spectral slice not created."); } }
autoSpectrum Spectrum_shiftFrequencies (Spectrum me, double shiftBy, double newMaximumFrequency, long interpolationDepth) { try { double xmax = my xmax; long numberOfFrequencies = my nx; if (newMaximumFrequency != 0) { numberOfFrequencies = (long) floor (newMaximumFrequency / my dx) + 1; xmax = newMaximumFrequency; } autoSpectrum thee = Spectrum_create (xmax, numberOfFrequencies); // shiftBy >= 0 for (long i = 1; i <= thy nx; i++) { double thyf = thy x1 + (i - 1) * thy dx; double myf = thyf - shiftBy; if (myf >= my xmin && myf <= my xmax) { double index = Sampled_xToIndex (me, myf); thy z[1][i] = NUM_interpolate_sinc (my z[1], my nx, index, interpolationDepth); thy z[2][i] = NUM_interpolate_sinc (my z[2], my nx, index, interpolationDepth); } } // Make imaginary part of first and last sample zero // so Spectrum_to_Sound uses FFT if numberOfSamples was power of 2! double amp = sqrt (thy z[1][1] * thy z[1][1] + thy z[2][1] * thy z[2][1]); thy z[1][1] = amp; thy z[2][1] = 0; amp = sqrt (thy z[1][thy nx] * thy z[1][thy nx] + thy z[2][thy nx] * thy z[2][thy nx]); thy z[1][thy nx] = amp; thy z[2][thy nx] = 0; return thee; } catch (MelderError) { Melder_throw (me, U": not shifted."); } }
autoSpectrum Spectrum_resample (Spectrum me, long numberOfFrequencies) { try { double newSamplingFrequency = (1 / my dx) * numberOfFrequencies / my nx; // resample real and imaginary part ! autoSound thee = Sound_resample ((Sound) me, newSamplingFrequency, 50); autoSpectrum him = Spectrum_create (my xmax, numberOfFrequencies); NUMmatrix_copyElements<double> (thy z, his z, 1, 2, 1, numberOfFrequencies); return him; } catch (MelderError) { Melder_throw (me, U": not resampled."); } }
autoSpectrum ComplexSpectrogram_to_Spectrum (ComplexSpectrogram me, double time) { try { long iframe = Sampled_xToLowIndex (me, time); // ppgb: geen Sampled_xToIndex gebruiken voor integers (afrondingen altijd expliciet maken) iframe = iframe < 1 ? 1 : (iframe > my nx ? my nx : iframe); autoSpectrum thee = Spectrum_create (my ymax, my ny); for (long ifreq = 1; ifreq <= my ny; ifreq++) { double a = sqrt (my z[ifreq][iframe]); double phi = my phase[ifreq][iframe]; thy z[1][ifreq] = a * cos (phi); thy z[2][ifreq] = a * sin (phi); } return thee; } catch (MelderError) { Melder_throw (me, U": no Spectrum created."); } }
static autoSound ComplexSpectrogram_to_Sound2 (ComplexSpectrogram me, double stretchFactor) { try { /* original number of samples is odd: imaginary part of last spectral value is zero -> * phase is either zero or pi */ double pi = atan2 (0.0, - 0.5); double samplingFrequency = 2.0 * my ymax; double lastFrequency = my y1 + (my ny - 1) * my dy; int originalNumberOfSamplesProbablyOdd = (my phase [my ny][1] != 0.0 && my phase[my ny][1] != pi) || my ymax - lastFrequency > 0.25 * my dx; if (my y1 != 0.0) { Melder_throw (U"A Fourier-transformable Spectrum must have a first frequency of 0 Hz, not ", my y1, U" Hz."); } long numberOfSamples = 2 * my ny - (originalNumberOfSamplesProbablyOdd ? 1 : 2 ); double synthesisWindowDuration = numberOfSamples / samplingFrequency; autoSpectrum spectrum = Spectrum_create (my ymax, my ny); autoSound synthesisWindow = Sound_createSimple (1, synthesisWindowDuration, samplingFrequency); long stepSizeSamples = my dx * samplingFrequency * stretchFactor; double newDuration = (my xmax - my xmin) * stretchFactor + 0.05; autoSound thee = Sound_createSimple (1, newDuration, samplingFrequency); //TODO long istart = 1, iend = istart + stepSizeSamples - 1; for (long iframe = 1; iframe <= my nx; iframe++) { spectrum -> z[1][1] = sqrt (my z[1][iframe]); for (long ifreq = 2; ifreq <= my ny; ifreq++) { double f = my y1 + (ifreq - 1) * my dy; double a = sqrt (my z[ifreq][iframe]); double phi = my phase[ifreq][iframe]; double extraPhase = 2.0 * pi * (stretchFactor - 1.0) * my dx * f; phi += extraPhase; spectrum -> z[1][ifreq] = a * cos (phi); spectrum -> z[2][ifreq] = a * sin (phi); } autoSound synthesis = Spectrum_to_Sound (spectrum.get()); for (long j = istart; j <= iend; j++) { thy z[1][j] = synthesis -> z[1][j - istart + 1]; } istart = iend + 1; iend = istart + stepSizeSamples - 1; } return thee; } catch (MelderError) { Melder_throw (me, U": no Sound created."); } }
double VocalTract_and_LPC_Frame_getMatchingLength (VocalTract me, LPC_Frame thee, double glottalDamping, bool radiationDamping, bool internalDamping) { try { // match the average distance between the first two formants in the VocaTract and the LPC spectrum long numberOfFrequencies = 1000; double maximumFrequency = 5000.0; autoSpectrum vts = VocalTract_to_Spectrum (me, numberOfFrequencies, maximumFrequency, glottalDamping, radiationDamping, internalDamping); double samplingFrequency = 1000.0 * my nx; autoSpectrum lps = Spectrum_create (0.5 * samplingFrequency, numberOfFrequencies); LPC_Frame_into_Spectrum (thee, lps.peek(), 0, 50); autoSpectrumTier vtst = Spectrum_to_SpectrumTier_peaks (vts.peek()); autoSpectrumTier lpst = Spectrum_to_SpectrumTier_peaks (lps.peek()); double vt_f1 = vtst -> points.at [1] -> number, vt_f2 = vtst -> points.at [2] -> number; double lp_f1 = lpst -> points.at [1] -> number, lp_f2 = lpst -> points.at [2] -> number; double df1 = lp_f1 - vt_f1, df2 = lp_f2 - vt_f2, df = 0.5 * (df1 + df2); double dl = - df / lp_f2; return my dx * my nx * (1 + dl); } catch (MelderError) { Melder_throw (U"Length could not be determined from VocalTract and LPC_Frame."); } }
autoSpectrum Sound_to_Spectrum (Sound me, int fast) { try { long numberOfSamples = my nx; if (fast) { numberOfSamples = 2; while (numberOfSamples < my nx) numberOfSamples *= 2; } long numberOfFrequencies = numberOfSamples / 2 + 1; // 4 samples -> cos0 cos1 sin1 cos2; 5 samples -> cos0 cos1 sin1 cos2 sin2 autoNUMvector <double> data (1, numberOfSamples); autoNUMfft_Table fourierTable; NUMfft_Table_init (& fourierTable, numberOfSamples); for (long i = 1; i <= my nx; i ++) data [i] = my ny == 1 ? my z [1] [i] : 0.5 * (my z [1] [i] + my z [2] [i]); NUMfft_forward (& fourierTable, data.peek()); autoSpectrum thee = Spectrum_create (0.5 / my dx, numberOfFrequencies); thy dx = 1.0 / (my dx * numberOfSamples); // override double *re = thy z [1]; double *im = thy z [2]; double scaling = my dx; re [1] = data [1] * scaling; im [1] = 0.0; for (long i = 2; i < numberOfFrequencies; i ++) { re [i] = data [i + i - 2] * scaling; im [i] = data [i + i - 1] * scaling; } if ((numberOfSamples & 1) != 0) { if (numberOfSamples > 1) { re [numberOfFrequencies] = data [numberOfSamples - 1] * scaling; im [numberOfFrequencies] = data [numberOfSamples] * scaling; } } else { re [numberOfFrequencies] = data [numberOfSamples] * scaling; im [numberOfFrequencies] = 0.0; } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Spectrum."); } }
Spectrum Spectrogram_to_Spectrum (I, double tim) { iam (Spectrogram); try { autoSpectrum thee = Spectrum_create (my ymax, my ny); /* Override stupid Spectrum values. */ thy xmin = my ymin; thy xmax = my ymax; thy x1 = my y1; // centre of first band, instead of 0 (makes it unFFTable) thy dx = my dy; // frequency step long itime = Sampled_xToNearestIndex (me, tim); if (itime < 1 ) itime = 1; if (itime > my nx) itime = my nx; for (long ifreq = 1; ifreq <= my ny; ifreq ++) { double value = my z [ifreq] [itime]; if (value < 0.0) Melder_throw (U"Negative values in spectrogram."); thy z [1] [ifreq] = sqrt (value); thy z [2] [ifreq] = 0.0; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": spectral slice not extracted."); } }
Spectrum LPC_to_Spectrum (LPC me, double t, double dfMin, double bandwidthReduction, double deEmphasisFrequency) { try { double samplingFrequency = 1.0 / my samplingPeriod; long nfft = 2, index = Sampled_xToNearestIndex (me, t); if (index < 1) { index = 1; } if (index > my nx) { index = my nx; } if (dfMin <= 0) { nfft = 512; dfMin = samplingFrequency / nfft; } while (samplingFrequency / nfft > dfMin || nfft <= my d_frames[index].nCoefficients) { nfft *= 2; } autoSpectrum thee = Spectrum_create (samplingFrequency / 2, nfft / 2 + 1); LPC_Frame_into_Spectrum (& my d_frames[index], thee.peek(), bandwidthReduction, deEmphasisFrequency); return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no Spectrum created."); } }
static autoSpectrum Spectrum_shiftFrequencies2 (Spectrum me, double shiftBy, bool changeMaximumFrequency) { try { double xmax = my xmax; long numberOfFrequencies = my nx, interpolationDepth = 50; if (changeMaximumFrequency) { xmax += shiftBy; numberOfFrequencies += (xmax - my xmax) / my dx; } autoSpectrum thee = Spectrum_create (xmax, numberOfFrequencies); // shiftBy >= 0 for (long i = 1; i <= thy nx; i++) { double thyf = thy x1 + (i - 1) * thy dx; double myf = thyf - shiftBy; if (myf >= my xmin && myf <= my xmax) { double index = Sampled_xToIndex (me, myf); thy z[1][i] = NUM_interpolate_sinc (my z[1], my nx, index, interpolationDepth); thy z[2][i] = NUM_interpolate_sinc (my z[2], my nx, index, interpolationDepth); } } return thee; } catch (MelderError) { Melder_throw (me, U": not shifted."); } }
autoSpectrum Sound_to_Spectrum (Sound me, int fast) { try { long numberOfSamples = my nx; const long numberOfChannels = my ny; if (fast) { numberOfSamples = 2; while (numberOfSamples < my nx) numberOfSamples *= 2; } long numberOfFrequencies = numberOfSamples / 2 + 1; // 4 samples -> cos0 cos1 sin1 cos2; 5 samples -> cos0 cos1 sin1 cos2 sin2 autoNUMvector <double> data (1, numberOfSamples); if (numberOfChannels == 1) { const double *channel = my z [1]; for (long i = 1; i <= my nx; i ++) { data [i] = channel [i]; } /* All samples from `my nx + 1` through `numberOfSamples` should be set to zero, but they are already zero. */ // so do nothing } else { for (long ichan = 1; ichan <= numberOfChannels; ichan ++) { const double *channel = my z [ichan]; for (long i = 1; i <= my nx; i ++) { data [i] += channel [i]; } } for (long i = 1; i <= my nx; i ++) { data [i] /= numberOfChannels; } } autoNUMfft_Table fourierTable; NUMfft_Table_init (& fourierTable, numberOfSamples); NUMfft_forward (& fourierTable, data.peek()); autoSpectrum thee = Spectrum_create (0.5 / my dx, numberOfFrequencies); thy dx = 1.0 / (my dx * numberOfSamples); // override double *re = thy z [1]; double *im = thy z [2]; double scaling = my dx; re [1] = data [1] * scaling; im [1] = 0.0; for (long i = 2; i < numberOfFrequencies; i ++) { re [i] = data [i + i - 2] * scaling; // data [2], data [4], ... im [i] = data [i + i - 1] * scaling; // data [3], data [5], ... } if ((numberOfSamples & 1) != 0) { if (numberOfSamples > 1) { re [numberOfFrequencies] = data [numberOfSamples - 1] * scaling; im [numberOfFrequencies] = data [numberOfSamples] * scaling; } } else { re [numberOfFrequencies] = data [numberOfSamples] * scaling; im [numberOfFrequencies] = 0.0; } return thee; } catch (MelderError) { Melder_throw (me, U": not converted to Spectrum."); } }
autoSound ComplexSpectrogram_to_Sound (ComplexSpectrogram me, double stretchFactor) { try { /* original number of samples is odd: imaginary part of last spectral value is zero -> * phase is either zero or +/-pi */ double pi = atan2 (0.0, - 0.5); double samplingFrequency = 2.0 * my ymax; double lastFrequency = my y1 + (my ny - 1) * my dy, lastPhase = my phase[my ny][1]; int originalNumberOfSamplesProbablyOdd = (lastPhase != 0.0 && lastPhase != pi && lastPhase != -pi) || my ymax - lastFrequency > 0.25 * my dx; if (my y1 != 0.0) { Melder_throw (U"A Fourier-transformable ComplexSpectrogram must have a first frequency of 0 Hz, not ", my y1, U" Hz."); } long nsamp_window = 2 * my ny - (originalNumberOfSamplesProbablyOdd ? 1 : 2 ); long halfnsamp_window = nsamp_window / 2; double synthesisWindowDuration = nsamp_window / samplingFrequency; autoSpectrum spectrum = Spectrum_create (my ymax, my ny); autoSound synthesisWindow = Sound_createSimple (1, synthesisWindowDuration, samplingFrequency); double newDuration = (my xmax - my xmin) * stretchFactor; autoSound thee = Sound_createSimple (1, newDuration, samplingFrequency); //TODO double thyStartTime; for (long iframe = 1; iframe <= my nx; iframe++) { // "original" sound : double tmid = Sampled_indexToX (me, iframe); long leftSample = Sampled_xToLowIndex (thee.get(), tmid); long rightSample = leftSample + 1; long startSample = rightSample - halfnsamp_window; double startTime = Sampled_indexToX (thee.get(), startSample); if (iframe == 1) { thyStartTime = Sampled_indexToX (thee.get(), startSample); } //long endSample = leftSample + halfnsamp_window; // New Sound with stretch long thyStartSample = Sampled_xToLowIndex (thee.get(),thyStartTime); double thyEndTime = thyStartTime + my dx * stretchFactor; long thyEndSample = Sampled_xToLowIndex (thee.get(), thyEndTime); long stretchedStepSizeSamples = thyEndSample - thyStartSample + 1; //double extraTime = (thyStartSample - startSample + 1) * thy dx; double extraTime = (thyStartTime - startTime); spectrum -> z[1][1] = sqrt (my z[1][iframe]); for (long ifreq = 2; ifreq <= my ny; ifreq++) { double f = my y1 + (ifreq - 1) * my dy; double a = sqrt (my z[ifreq][iframe]); double phi = my phase[ifreq][iframe], intPart; double extraPhase = 2.0 * pi * modf (extraTime * f, &intPart); // fractional part phi += extraPhase; spectrum -> z[1][ifreq] = a * cos (phi); spectrum -> z[2][ifreq] = a * sin (phi); } autoSound synthesis = Spectrum_to_Sound (spectrum.get()); // Where should the sound be placed? long thyEndSampleP = (long) floor (fmin (thyStartSample + synthesis -> nx - 1, thyStartSample + stretchedStepSizeSamples - 1)); // guard against extreme stretches if (iframe == my nx) { thyEndSampleP = (long) floor (fmin (thy nx, thyStartSample + synthesis -> nx - 1)); // ppgb: waarom naar beneden afgerond? } for (long j = thyStartSample; j <= thyEndSampleP; j++) { thy z[1][j] = synthesis -> z[1][j - thyStartSample + 1]; } thyStartTime += my dx * stretchFactor; } return thee; } catch (MelderError) { Melder_throw (me, U": no Sound created."); } }