diff options
Diffstat (limited to 'gr-vocoder/lib/codec2/interp.c')
-rw-r--r-- | gr-vocoder/lib/codec2/interp.c | 397 |
1 files changed, 123 insertions, 274 deletions
diff --git a/gr-vocoder/lib/codec2/interp.c b/gr-vocoder/lib/codec2/interp.c index fad4554f43..be89fc3154 100644 --- a/gr-vocoder/lib/codec2/interp.c +++ b/gr-vocoder/lib/codec2/interp.c @@ -29,13 +29,11 @@ #include <math.h> #include <string.h> #include <stdio.h> -#include <stdlib.h> #include "defines.h" #include "interp.h" #include "lsp.h" #include "quantise.h" -#include "dump.h" float sample_log_amp(MODEL *model, float w); @@ -113,23 +111,19 @@ float sample_log_amp(MODEL *model, float w) assert(w > 0.0); assert (w <= PI); - m = 0; - while ((m+1)*model->Wo < w) m++; - f = (w - m*model->Wo)/model->Wo; + m = floorf(w/model->Wo + 0.5); + f = (w - m*model->Wo)/w; assert(f <= 1.0); if (m < 1) { - log_amp = f*log10(model->A[1] + 1E-6); + log_amp = f*log10f(model->A[1] + 1E-6); } else if ((m+1) > model->L) { - log_amp = (1.0-f)*log10(model->A[model->L] + 1E-6); + log_amp = (1.0-f)*log10f(model->A[model->L] + 1E-6); } else { - log_amp = (1.0-f)*log10(model->A[m] + 1E-6) + - f*log10(model->A[m+1] + 1E-6); - //printf("m=%d A[m] %f A[m+1] %f x %f %f %f\n", m, model->A[m], - // model->A[m+1], pow(10.0, log_amp), - // (1-f), f); + log_amp = (1.0-f)*log10f(model->A[m] + 1E-6) + + f*log10f(model->A[m+1] + 1E-6); } return log_amp; @@ -137,338 +131,193 @@ float sample_log_amp(MODEL *model, float w) /*---------------------------------------------------------------------------*\ - FUNCTION....: sample_log_amp_quad() + FUNCTION....: interp_lsp() AUTHOR......: David Rowe - DATE CREATED: 9 March 2011 - - Samples the amplitude envelope at an arbitrary frequency w. Uses - quadratic interpolation in the log domain to sample between harmonic - amplitudes. - - y(x) = ax*x + bx + c + DATE CREATED: 10 Nov 2010 - We assume three points are x=-1, x=0, x=1, which we map to m-1,m,m+1 + Given two frames decribed by model parameters 20ms apart, determines + the model parameters of the 10ms frame between them. Assumes + voicing is available for middle (interpolated) frame. Outputs are + amplitudes and Wo for the interpolated frame. - c = y(0) - b = (y(1) - y(-1))/2 - a = y(-1) + b - y(0) + This version uses interpolation of LSPs, seems to do a better job + with bg noise. \*---------------------------------------------------------------------------*/ -float sample_log_amp_quad(MODEL *model, float w) +void interpolate_lsp( + kiss_fft_cfg fft_fwd_cfg, + MODEL *interp, /* interpolated model params */ + MODEL *prev, /* previous frames model params */ + MODEL *next, /* next frames model params */ + float *prev_lsps, /* previous frames LSPs */ + float prev_e, /* previous frames LPC energy */ + float *next_lsps, /* next frames LSPs */ + float next_e, /* next frames LPC energy */ + float *ak_interp, /* interpolated aks for this frame */ + float *lsps_interp/* interpolated lsps for this frame */ +) { - int m; - float a,b,c,x, log_amp; + int i; + float e; + float snr; - assert(w > 0.0); assert (w <= PI); + /* trap corner case where V est is probably wrong */ - m = floor(w/model->Wo + 0.5); - if (m < 2) m = 2; - if (m > (model->L-1)) m = model->L-1; - c = log10(model->A[m]+1E-6); - b = (log10(model->A[m+1]+1E-6) - log10(model->A[m-1]+1E-6))/2.0; - a = log10(model->A[m-1]+1E-6) + b - c; - x = (w - m*model->Wo)/model->Wo; - - log_amp = a*x*x + b*x + c; - //printf("m=%d A[m-1] %f A[m] %f A[m+1] %f w %f x %f log_amp %f\n", m, - // model->A[m-1], - // model->A[m], model->A[m+1], w, x, pow(10.0, log_amp)); - return log_amp; -} + if (interp->voiced && !prev->voiced && !next->voiced) { + interp->voiced = 0; + } -/*---------------------------------------------------------------------------*\ + /* Wo depends on voicing of this and adjacent frames */ - FUNCTION....: sample_log_amp_quad_nl() - AUTHOR......: David Rowe - DATE CREATED: 10 March 2011 + if (interp->voiced) { + if (prev->voiced && next->voiced) + interp->Wo = (prev->Wo + next->Wo)/2.0; + if (!prev->voiced && next->voiced) + interp->Wo = next->Wo; + if (prev->voiced && !next->voiced) + interp->Wo = prev->Wo; + } + else { + interp->Wo = TWO_PI/P_MAX; + } + interp->L = PI/interp->Wo; - Samples the amplitude envelope at an arbitrary frequency w. Uses - quadratic interpolation in the log domain to sample between harmonic - amplitudes. This version can handle non-linear steps along a freq - axis defined by arbitrary steps. + //printf(" interp: prev_v: %d next_v: %d prev_Wo: %f next_Wo: %f\n", + // prev->voiced, next->voiced, prev->Wo, next->Wo); + //printf(" interp: Wo: %1.5f L: %d\n", interp->Wo, interp->L); - y(x) = ax*x + bx + c + /* interpolate LSPs */ - We assume three points are (x_1,y_1), (0,y0) and (x1,y1). + for(i=0; i<LPC_ORD; i++) { + lsps_interp[i] = (prev_lsps[i] + next_lsps[i])/2.0; + } -\*---------------------------------------------------------------------------*/ + /* Interpolate LPC energy in log domain */ -float sample_log_amp_quad_nl( - float w[], /* frequency points */ - float A[], /* for these amplitude samples */ - int np, /* number of frequency points */ - float w_sample /* frequency of new samples */ -) -{ - int m,i; - float a,b,c,x, log_amp, best_dist; - float x_1, x1; - float y_1, y0, y1; - - //printf("w_sample %f\n", w_sample); - assert(w_sample >= 0.0); assert (w_sample <= 1.1*PI); - - /* find closest point to centre quadratic interpolator */ - - best_dist = 1E32; - m = 0; - for (i=0; i<np; i++) - if (fabs(w[i] - w_sample) < best_dist) { - best_dist = fabs(w[i] - w_sample); - m = i; - } - - /* stay one point away from edge of array */ - - if (m < 1) m = 1; - if (m > (np-2)) m = np - 2; - - /* find polynomial coeffs */ - - x_1 = w[m-1]- w[m]; x1 = w[m+1] - w[m]; - y_1 = log10(A[m-1]+1E-6); - y0 = log10(A[m]+1E-6); - y1 = log10(A[m+1]+1E-6); - - c = y0; - a = (y_1*x1 - y1*x_1 + c*x_1 - c*x1)/(x_1*x_1*x1 - x1*x1*x_1); - b = (y1 -a*x1*x1 - c)/x1; - x = w_sample - w[m]; - - //printf("%f %f %f\n", w[0], w[1], w[2]); - //printf("%f %f %f %f %f %f\n", x_1, y_1, 0.0, y0, x1, y1); - log_amp = a*x*x + b*x + c; - //printf("a %f b %f c %f\n", a, b, c); - //printf("m=%d A[m-1] %f A[m] %f A[m+1] %f w_sample %f w[m] %f x %f log_amp %f\n", m, - // A[m-1], - // A[m], A[m+1], w_sample, w[m], x, log_amp); - //exit(0); - return log_amp; -} + e = powf(10.0, (log10f(prev_e) + log10f(next_e))/2.0); + //printf(" interp: e: %f\n", e); -#define M_MAX 40 + /* convert back to amplitudes */ + + lsp_to_lpc(lsps_interp, ak_interp, LPC_ORD); + aks_to_M2(fft_fwd_cfg, ak_interp, LPC_ORD, interp, e, &snr, 0, 0, 1, 1, LPCPF_BETA, LPCPF_GAMMA); + //printf(" interp: ak[1]: %f A[1] %f\n", ak_interp[1], interp->A[1]); +} -float fres[] = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, - 1200, 1400, 1600, 1850, 2100, 2350, 2600, 2900, 3400, 3800}; /*---------------------------------------------------------------------------*\ - FUNCTION....: resample_amp_nl() + FUNCTION....: interp_Wo() AUTHOR......: David Rowe - DATE CREATED: 7 March 2011 + DATE CREATED: 22 May 2012 - Converts the current model with L {Am} samples spaced Wo apart to - RES_POINTS samples spaced Wo/RES_POINTS apart. Then subtracts - from the previous frames samples to get the delta. + Interpolates centre 10ms sample of Wo and L samples given two + samples 20ms apart. Assumes voicing is available for centre + (interpolated) frame. \*---------------------------------------------------------------------------*/ -void resample_amp_fixed(MODEL *model, - float w[], float A[], - float wres[], float Ares[], - float AresdB_prev[], - float AresdB[], - float deltat[]) +void interp_Wo( + MODEL *interp, /* interpolated model params */ + MODEL *prev, /* previous frames model params */ + MODEL *next /* next frames model params */ + ) { - int i; - - for(i=1; i<=model->L; i++) { - w[i-1] = i*model->Wo; - A[i-1] = model->A[i]; - } - - for(i=0; i<RES_POINTS; i++) { - wres[i] = fres[i]*PI/4000.0; - } - - for(i=0; i<RES_POINTS; i++) { - Ares[i] = pow(10.0,sample_log_amp_quad_nl(w, A, model->L, wres[i])); - } - - /* work out delta T vector for this frame */ - - for(i=0; i<RES_POINTS; i++) { - AresdB[i] = 20.0*log10(Ares[i]); - deltat[i] = AresdB[i] - AresdB_prev[i]; - } - + interp_Wo2(interp, prev, next, 0.5); } /*---------------------------------------------------------------------------*\ - FUNCTION....: resample_amp_nl() + FUNCTION....: interp_Wo2() AUTHOR......: David Rowe - DATE CREATED: 7 March 2011 - - Converts the current model with L {Am} samples spaced Wo apart to M - samples spaced Wo/M apart. Then converts back to L {Am} samples. - used to prototype constant rate Amplitude encoding ideas. + DATE CREATED: 22 May 2012 - Returns the SNR in dB. + Weighted interpolation of two Wo samples. \*---------------------------------------------------------------------------*/ -float resample_amp_nl(MODEL *model, int m, float AresdB_prev[]) +void interp_Wo2( + MODEL *interp, /* interpolated model params */ + MODEL *prev, /* previous frames model params */ + MODEL *next, /* next frames model params */ + float weight +) { - int i; - float w[MAX_AMP], A[MAX_AMP]; - float wres[MAX_AMP], Ares[MAX_AMP], AresdB[MAX_AMP]; - float signal, noise, snr; - float new_A; - float deltat[MAX_AMP], deltat_q[MAX_AMP], AresdB_q[MAX_AMP]; - - resample_amp_fixed(model, w, A, wres, Ares, AresdB_prev, AresdB, deltat); - - /* quantise delta T vector */ - - for(i=0; i<RES_POINTS; i++) { - noise = 3.0*(1.0 - 2.0*rand()/RAND_MAX); - //noise = 0.0; - deltat_q[i] = deltat[i] + noise; - } + /* trap corner case where voicing est is probably wrong */ - /* recover Ares vector */ - - for(i=0; i<RES_POINTS; i++) { - AresdB_q[i] = AresdB_prev[i] + deltat_q[i]; - Ares[i] = pow(10.0, AresdB_q[i]/20.0); - //printf("%d %f %f\n", i, AresdB[i], AresdB_q[i]); + if (interp->voiced && !prev->voiced && !next->voiced) { + interp->voiced = 0; } - /* update memory based on version at decoder */ + /* Wo depends on voicing of this and adjacent frames */ - for(i=0; i<RES_POINTS; i++) { - AresdB_prev[i] = AresdB_q[i]; + if (interp->voiced) { + if (prev->voiced && next->voiced) + interp->Wo = (1.0 - weight)*prev->Wo + weight*next->Wo; + if (!prev->voiced && next->voiced) + interp->Wo = next->Wo; + if (prev->voiced && !next->voiced) + interp->Wo = prev->Wo; } - -#ifdef DUMP - dump_resample(wres,Ares,M_MAX); -#endif - - signal = noise = 0.0; - - for(i=1; i<model->L; i++) { - new_A = pow(10.0,sample_log_amp_quad_nl(wres, Ares, RES_POINTS, model->Wo*i)); - signal += pow(model->A[i], 2.0); - noise += pow(model->A[i] - new_A, 2.0); - //printf("%f %f\n", model->A[i], new_A); - model->A[i] = new_A; + else { + interp->Wo = TWO_PI/P_MAX; } - - snr = 10.0*log10(signal/noise); - printf("snr = %3.2f\n", snr); - //exit(0); - return snr; + interp->L = PI/interp->Wo; } + /*---------------------------------------------------------------------------*\ - FUNCTION....: resample_amp() + FUNCTION....: interp_energy() AUTHOR......: David Rowe - DATE CREATED: 10 March 2011 - - Converts the current model with L {Am} samples spaced Wo apart to M - samples with a non-linear spacing. Then converts back to L {Am} - samples. used to prototype constant rate Amplitude encoding ideas. + DATE CREATED: 22 May 2012 - Returns the SNR in dB. + Interpolates centre 10ms sample of energy given two samples 20ms + apart. \*---------------------------------------------------------------------------*/ -float resample_amp(MODEL *model, int m) +float interp_energy(float prev_e, float next_e) { - int i; - MODEL model_m; - float new_A, signal, noise, snr, log_amp_dB; - float n_db = 0.0; - - model_m.Wo = PI/(float)m; - model_m.L = PI/model_m.Wo; - - for(i=1; i<=model_m.L; i++) { - log_amp_dB = 20.0*sample_log_amp_quad(model, i*model_m.Wo); - log_amp_dB += n_db*(1.0 - 2.0*rand()/RAND_MAX); - model_m.A[i] = pow(10,log_amp_dB/20.0); - } - - //dump_resample(&model_m); - - signal = noise = 0.0; + return powf(10.0, (log10f(prev_e) + log10f(next_e))/2.0); - for(i=1; i<model->L/4; i++) { - new_A = pow(10,sample_log_amp_quad(&model_m, i*model->Wo)); - signal += pow(model->A[i], 2.0); - noise += pow(model->A[i] - new_A, 2.0); - //printf("%f %f\n", model->A[i], new_A); - model->A[i] = new_A; - } - - snr = 10.0*log10(signal/noise); - //printf("snr = %3.2f\n", snr); - //exit(0); - return snr; } + /*---------------------------------------------------------------------------*\ - FUNCTION....: interp_lsp() + FUNCTION....: interp_energy2() AUTHOR......: David Rowe - DATE CREATED: 10 Nov 2010 - - Given two frames decribed by model parameters 20ms apart, determines - the model parameters of the 10ms frame between them. Assumes - voicing is available for middle (interpolated) frame. Outputs are - amplitudes and Wo for the interpolated frame. + DATE CREATED: 22 May 2012 - This version uses interpolation of LSPs, seems to do a better job - with bg noise. + Interpolates centre 10ms sample of energy given two samples 20ms + apart. \*---------------------------------------------------------------------------*/ -void interpolate_lsp( - MODEL *interp, /* interpolated model params */ - MODEL *prev, /* previous frames model params */ - MODEL *next, /* next frames model params */ - float *prev_lsps, /* previous frames LSPs */ - float prev_e, /* previous frames LPC energy */ - float *next_lsps, /* next frames LSPs */ - float next_e, /* next frames LPC energy */ - float *ak_interp /* interpolated aks for this frame */ - ) +float interp_energy2(float prev_e, float next_e, float weight) { - //int l,i; - int i; - float lsps[LPC_ORD],e; - float snr; + return powf(10.0, (1.0 - weight)*log10f(prev_e) + weight*log10f(next_e)); - /* Wo depends on voicing of this and adjacent frames */ +} - if (interp->voiced) { - if (prev->voiced && next->voiced) - interp->Wo = (prev->Wo + next->Wo)/2.0; - if (!prev->voiced && next->voiced) - interp->Wo = next->Wo; - if (prev->voiced && !next->voiced) - interp->Wo = prev->Wo; - } - else { - interp->Wo = TWO_PI/P_MAX; - } - interp->L = PI/interp->Wo; - /* interpolate LSPs */ +/*---------------------------------------------------------------------------*\ - for(i=0; i<LPC_ORD; i++) { - lsps[i] = (prev_lsps[i] + next_lsps[i])/2.0; - } + FUNCTION....: interpolate_lsp_ver2() + AUTHOR......: David Rowe + DATE CREATED: 22 May 2012 - /* Interpolate LPC energy in log domain */ + Weighted interpolation of LSPs. - e = pow(10.0, (log10(prev_e) + log10(next_e))/2.0); +\*---------------------------------------------------------------------------*/ - /* convert back to amplitudes */ +void interpolate_lsp_ver2(float interp[], float prev[], float next[], float weight) +{ + int i; - lsp_to_lpc(lsps, ak_interp, LPC_ORD); - aks_to_M2(ak_interp, LPC_ORD, interp, e, &snr, 0); + for(i=0; i<LPC_ORD; i++) + interp[i] = (1.0 - weight)*prev[i] + weight*next[i]; } + |