static LPC _Sound_to_LPC (Sound me, int predictionOrder, double analysisWidth, double dt, double preEmphasisFrequency, int method, double tol1, double tol2) { double t1, samplingFrequency = 1.0 / my dx; double windowDuration = 2 * analysisWidth; /* gaussian window */ long nFrames, frameErrorCount = 0; if (floor (windowDuration / my dx) < predictionOrder + 1) Melder_throw ("Analysis window duration too short.\n" "For a prediction order of ", predictionOrder, " the analysis window duration has to be greater than ", my dx * (predictionOrder + 1), "Please increase the analysis window duration or lower the prediction order."); // Convenience: analyse the whole sound into one LPC_frame if (windowDuration > my dx * my nx) { windowDuration = my dx * my nx; } Sampled_shortTermAnalysis (me, windowDuration, dt, & nFrames, & t1); autoSound sound = Data_copy (me); autoSound sframe = Sound_createSimple (1, windowDuration, samplingFrequency); autoSound window = Sound_createGaussian (windowDuration, samplingFrequency); autoLPC thee = LPC_create (my xmin, my xmax, nFrames, dt, t1, predictionOrder, my dx); autoMelderProgress progress (L"LPC analysis"); if (preEmphasisFrequency < samplingFrequency / 2) { Sound_preEmphasis (sound.peek(), preEmphasisFrequency); } for (long i = 1; i <= nFrames; i++) { LPC_Frame lpcframe = (LPC_Frame) & thy d_frames[i]; double t = Sampled_indexToX (thee.peek(), i); LPC_Frame_init (lpcframe, predictionOrder); Sound_into_Sound (sound.peek(), sframe.peek(), t - windowDuration / 2); Vector_subtractMean (sframe.peek()); Sounds_multiply (sframe.peek(), window.peek()); if (method == LPC_METHOD_AUTO) { if (! Sound_into_LPC_Frame_auto (sframe.peek(), lpcframe)) { frameErrorCount++; } } else if (method == LPC_METHOD_COVAR) { if (! Sound_into_LPC_Frame_covar (sframe.peek(), lpcframe)) { frameErrorCount++; } } else if (method == LPC_METHOD_BURG) { if (! Sound_into_LPC_Frame_burg (sframe.peek(), lpcframe)) { frameErrorCount++; } } else if (method == LPC_METHOD_MARPLE) { if (! Sound_into_LPC_Frame_marple (sframe.peek(), lpcframe, tol1, tol2)) { frameErrorCount++; } } if ( (i % 10) == 1) { Melder_progress ( (double) i / nFrames, L"LPC analysis of frame ", Melder_integer (i), L" out of ", Melder_integer (nFrames), L"."); } } return thee.transfer(); }
autoLPC Cepstrumc_to_LPC (Cepstrumc me) { try { autoLPC thee = LPC_create (my xmin, my xmax, my nx, my dx, my x1, my maxnCoefficients, 1.0 / my samplingFrequency); for (long i = 1; i <= my nx; i++) { LPC_Frame_init (& thy d_frames[i], my frame[i].nCoefficients); Cepstrumc_Frame_into_LPC_Frame (& my frame[i], & thy d_frames[i]); } return thee; } catch (MelderError) { Melder_throw (me, U":no LPC created."); } }
LPC Formant_to_LPC (Formant me, double samplingPeriod) { try { autoLPC thee = LPC_create (my xmin, my xmax, my nx, my dx, my x1, 2 * my maxnFormants, samplingPeriod); for (long i = 1; i <= my nx; i++) { Formant_Frame f = & my d_frames[i]; LPC_Frame lpc = & thy d_frames[i]; long m = 2 * f -> nFormants; LPC_Frame_init (lpc, m); Formant_Frame_into_LPC_Frame (f, lpc, samplingPeriod); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": no LPC created."); } }
LPC LFCC_to_LPC (LFCC me, long numberOfCoefficients) { try { if (numberOfCoefficients < 1) { numberOfCoefficients = my maximumNumberOfCoefficients; } numberOfCoefficients = MIN (numberOfCoefficients, my maximumNumberOfCoefficients); autoLPC thee = LPC_create (my xmin, my xmax, my nx, my dx, my x1, numberOfCoefficients, 0.5 / my fmax); for (long i = 1; i <= my nx; i++) { LPC_Frame_init (& thy d_frames[i], numberOfCoefficients); CC_Frame_into_LPC_Frame (& my frame[i], & thy d_frames[i]); } return thee.transfer(); } catch (MelderError) { Melder_throw (me, U": no LPC created."); } }
autoLPC VocalTractTier_to_LPC (VocalTractTier me, double timeStep) { try { if (my d_vocalTracts -> size == 0) { Melder_throw (U"Empty VocalTractTier"); } long numberOfFrames = (long) floor ((my xmax - my xmin) / timeStep); VocalTractPoint vtp = (VocalTractPoint) my d_vocalTracts -> item[1]; long numberOfSections = vtp -> d_vocalTract -> nx; double samplingPeriod = 1.0 / (1000.0 * numberOfSections); autoNUMmatrix<double> area (1, numberOfFrames, 1, numberOfSections + 1); autoNUMvector<double> areavec (1, numberOfSections + 1); autoLPC thee = LPC_create (my xmin, my xmax, numberOfFrames, timeStep, timeStep / 2, numberOfSections, samplingPeriod); // interpolate each section for (long isection = 1; isection <= numberOfSections; isection++) { autoRealTier sectioni = RealTier_create (my xmin, my xmax); for (long i = 1; i <= my d_vocalTracts -> size; i++) { VocalTractPoint vtpi = (VocalTractPoint) my d_vocalTracts -> item[i]; double areai = vtpi -> d_vocalTract -> z[1][isection]; RealTier_addPoint (sectioni.peek(), vtpi -> number, areai); } for (long iframe = 1; iframe <= numberOfFrames; iframe++) { double time = thy x1 + (iframe - 1) * thy dx; area[iframe][isection] = RealTier_getValueAtTime (sectioni.peek(), time); area[iframe][numberOfSections + 1] = 0.0001; // normalisation is area[n+1] = 0.0001 } } for (long iframe = 1; iframe <= numberOfFrames; iframe++) { LPC_Frame frame = &thy d_frames[iframe]; LPC_Frame_init (frame, numberOfSections); for (long i = 1; i <= numberOfSections + 1; i++) { areavec[i] = area[iframe][numberOfSections + 1 - i]; } NUMlpc_area_to_lpc (areavec.peek(), numberOfSections + 1, frame -> a); frame -> gain = 1e-6; // something } return thee; } catch (MelderError) { Melder_throw (U": not converted to LPC."); } }
double LPC_Frame_getVTL_wakita (LPC_Frame me, double samplingPeriod, double refLength) { struct structLPC_Frame lpc_struct; LPC_Frame lpc = & lpc_struct; struct structFormant_Frame f_struct; Formant_Frame f = & f_struct; struct structTube_Frame rc_struct, af_struct; Tube_Frame rc = & rc_struct, af = & af_struct; try { long m = my nCoefficients; double length, dlength = 0.001, wakita_length = NUMundefined; double varMin = 1e308; memset (& lpc_struct, 0, sizeof (lpc_struct)); memset (& f_struct, 0, sizeof (f_struct)); memset (& rc_struct, 0, sizeof (rc_struct)); memset (& af_struct, 0, sizeof (af_struct)); LPC_Frame_init (lpc, m); Tube_Frame_init (rc, m, refLength); Tube_Frame_init (af, m, refLength); // Step 2 LPC_Frame_into_Formant_Frame (me, f, samplingPeriod, 0); // LPC_Frame_into_Formant_Frame performs the Formant_Frame_init !! if (f -> nFormants < 1) { Melder_throw (U"Not enough formants."); } double *area = af -> c; double lmin = length = 0.10; double plength = refLength; while (length <= 0.25) { // Step 3 double fscale = plength / length; for (long i = 1; i <= f -> nFormants; i++) { f -> formant[i].frequency *= fscale; f -> formant[i].bandwidth *= fscale; } /* 20000125: Bovenstaande schaling van f1/b1 kan ook gedaan worden door MGfb_to_a (f, b, nf, samplingFrequency*length/refLength, a1) De berekening is extreem gevoelig voor de samplefrequentie: een zelfde stel f,b waardes geven andere lengtes afhankelijk van Fs. Ook het weglaten van een hogere formant heeft consekwenties. De refLength zou eigenlijk vast moeten liggen op refLength=c*aantalFormanten/Fs waarbij c=340 m/s (geluidssnelheid). Bij Fs=10000 zou aantalFormanten=5 zijn en refLength -> 0.17 m */ // step 4 Formant_Frame_into_LPC_Frame (f, lpc, samplingPeriod); // step 5 rc -> length = length; LPC_Frame_into_Tube_Frame_rc (lpc, rc); // step 6.1 Tube_Frames_rc_into_area (rc, af); // step 6.2 Log(areas) double logSum = 0.0; for (long i = 1; i <= af -> nSegments; i++) { area[i] = log (area[i]); logSum += area[i]; } // step 6.3 and 7 double var = 0.0; for (long i = 1; i <= af -> nSegments; i++) { double delta = area[i] - logSum / af -> nSegments; var += delta * delta; } if (var < varMin) { lmin = length; varMin = var; } plength = length; length += dlength; } wakita_length = lmin; f -> destroy (); lpc -> destroy (); rc -> destroy (); af -> destroy (); return wakita_length; } catch (MelderError) { f -> destroy (); lpc -> destroy (); rc -> destroy (); af -> destroy (); return NUMundefined; } }
double LPC_Frame_getVTL_wakita (LPC_Frame me, double samplingPeriod, double refLength) { struct structLPC_Frame lpc_struct; LPC_Frame lpc = & lpc_struct; struct structFormant_Frame f_struct; Formant_Frame f = & f_struct; struct structTube_Frame rc_struct, af_struct; Tube_Frame rc = & rc_struct, af = & af_struct; long i, m = my nCoefficients; double lmin, length, dlength = 0.001, plength, wakita_length = NUMundefined; double *area, var, varMin = 1e38, logSum; double fscale = 1; memset(& lpc_struct, 0, sizeof(lpc_struct)); memset(& f_struct, 0, sizeof(f_struct)); memset(& rc_struct, 0, sizeof(rc_struct)); memset(& af_struct, 0, sizeof(af_struct)); if (! LPC_Frame_init (lpc, m) || ! Tube_Frame_init (rc, m, refLength) || ! Tube_Frame_init (af, m, refLength) || /* Step 2 */ ! LPC_Frame_into_Formant_Frame (me, f, samplingPeriod, 0) || /* LPC_Frame_into_Formant_Frame performs the Formant_Frame_init !! */ f -> nFormants < 1) goto end; area = af -> c; lmin = length = 0.10; plength = refLength; while (length <= 0.25) { /* Step 3 */ fscale = plength / length; for (i = 1; i <= f -> nFormants; i++) { f -> formant[i].frequency *= fscale; f -> formant[i].bandwidth *= fscale; } /* 20000125: Bovenstaande schaling van f1/b1 kan ook gedaan worden door MGfb_to_a (f, b, nf, samplingFrequency*length/refLength, a1) De berekening is extreem gevoelig voor de samplefrequentie: een zelfde stel f,b waardes geven andere lengtes afhankelijk van Fs. Ook het weglaten van een hogere formant heeft consekwenties. De refLength zou eigenlijk vast moeten liggen op refLength=c*aantalFormanten/Fs waarbij c=340 m/s (geluidssnelheid). Bij Fs=10000 zou aantalFormanten=5 zijn en refLength -> 0.17 m */ /* step 4 */ if (! Formant_Frame_into_LPC_Frame (f, lpc, samplingPeriod)) goto end; /* step 5 */ rc -> length = length; if (! LPC_Frame_into_Tube_Frame_rc (lpc, rc)) goto end; /* step 6.1 */ if (! Tube_Frames_rc_into_area (rc, af)) goto end; /* step 6.2 Log(areas) */ for (logSum = 0, i = 1; i <= af -> nSegments; i++) { area[i] = log (area[i]); logSum += area[i]; } /* step 6.3 and 7*/ for (var = 0, i = 1; i <= af -> nSegments; i++) { double delta = area[i] - logSum / af -> nSegments; var += delta * delta; } if (var < varMin) { lmin = length; varMin = var; } plength = length; length += dlength; } wakita_length = lmin; end: Formant_Frame_destroy (f); LPC_Frame_destroy (lpc); Tube_Frame_destroy (rc); Tube_Frame_destroy (af); return wakita_length; }