void LPC_Frame_into_Tube_Frame_area (LPC_Frame me, Tube_Frame thee) { struct structTube_Frame rc_struct = { 0 }; Tube_Frame rc = & rc_struct; Tube_Frame_init (rc, my nCoefficients, thy length); LPC_Frame_into_Tube_Frame_rc (me, rc); Tube_Frames_rc_into_area (rc, thee); rc -> destroy (); }
int LPC_Frame_into_Tube_Frame_area (LPC_Frame me, Tube_Frame thee) { struct structTube_Frame rc_struct = { 0 }; Tube_Frame rc = & rc_struct; int status; memset (& rc_struct, 0, sizeof(rc_struct)); status = Tube_Frame_init (rc, my nCoefficients, thy length) && LPC_Frame_into_Tube_Frame_rc (me, rc) && Tube_Frames_rc_into_area (rc, thee); Tube_Frame_destroy (rc); return status; }
VocalTract LPC_to_VocalTract (LPC me, double time, double length, int wakita) { VocalTract thee = NULL; struct structTube_Frame area_struct; Tube_Frame area = & area_struct; LPC_Frame lpc; long i, m, iframe = Sampled_xToIndex (me, time); if (iframe < 1) iframe = 1; if (iframe > my nx) iframe = my nx; memset (& area_struct, 0, sizeof(area_struct)); lpc = & my frame[iframe]; m = lpc -> nCoefficients; if (! Tube_Frame_init (area, m, length) || ! LPC_Frame_into_Tube_Frame_area (lpc, area)) goto end; thee = VocalTract_create (m, area -> length / m); if (thee == NULL) goto end; /* area[lips..glottis] (m^2) to VocalTract[glottis..lips] (m^2) */ for (i = 1; i <= m; i++) { thy z[1][i] = area -> c[m + 1 - i]; } if (wakita) { double wakita_length = LPC_Frame_getVTL_wakita (lpc, my samplingPeriod, length); if (wakita_length == NUMundefined) { Melder_warning1 (L"Vocal tract length could not be calculated.\nRelevant tract dimensions will be undefined."); thy xmax = thy x1 = thy dx = NUMundefined; } } end: Tube_Frame_destroy (area); return thee; }
static autoVocalTract LPC_Frame_to_VocalTract2 (LPC_Frame me, double length) { struct structTube_Frame area_struct = { 0 }; Tube_Frame area = & area_struct; try { long m = my nCoefficients; Tube_Frame_init (area, m, length); LPC_Frame_into_Tube_Frame_area (me, area); autoVocalTract thee = VocalTract_create (m, area -> length / m); // area[lips..glottis] (m^2) to VocalTract[glottis..lips] (m^2) for (long i = 1; i <= m; i++) { thy z[1][i] = area -> c[m + 1 - i]; } area -> destroy (); return thee; } catch (MelderError) { area -> destroy (); Melder_throw (U"No VocalTract created from LPC_Frame."); } }
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; }