| /* Copyright (C) 2002 Jean-Marc Valin |
| File: sb_celp.c |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| |
| #include "speex.h" |
| #include "sb_celp.h" |
| #include "stdlib.h" |
| #include "filters.h" |
| #include <math.h> |
| #include "lpc.h" |
| #include "lsp.h" |
| #include <stdio.h> |
| #include "stack_alloc.h" |
| #include "cb_search.h" |
| #include "quant_lsp.h" |
| #include "vq.h" |
| #include <string.h> |
| |
| #ifndef M_PI |
| #define M_PI 3.14159265358979323846 /* pi */ |
| #endif |
| |
| extern float stoc[]; |
| |
| #define sqr(x) ((x)*(x)) |
| |
| float quant_high_gain[16]={ |
| -2.387860, |
| -1.504710, |
| -0.988013, |
| -0.610249, |
| -0.310298, |
| -0.050495, |
| 0.188963, |
| 0.413744, |
| 0.628971, |
| 0.840555, |
| 1.055630, |
| 1.283410, |
| 1.544990, |
| 1.855790, |
| 2.281910, |
| 3.002660 |
| }; |
| |
| |
| float quant_high_gain2[8] = { |
| -1.51541, |
| -0.70324, |
| -0.17024, |
| 0.26748, |
| 0.67232, |
| 1.08402, |
| 1.56110, |
| 2.25160, |
| }; |
| |
| |
| #if 0 |
| #define QMF_ORDER 32 |
| static float h0[32] = { |
| 0.0006910579, -0.001403793, |
| -0.001268303, 0.004234195, |
| 0.001414246, -0.009458318, |
| -0.0001303859, 0.01798145, |
| -0.004187483, -0.03123862, |
| 0.01456844, 0.05294745, |
| -0.03934878, -0.09980243, |
| 0.1285579, 0.4664053, |
| 0.4664053, 0.1285579, |
| -0.09980243, -0.03934878, |
| 0.05294745, 0.01456844, |
| -0.03123862, -0.004187483, |
| 0.01798145, -0.0001303859, |
| -0.009458318, 0.001414246, |
| 0.004234195, -0.001268303, |
| -0.001403793, 0.0006910579 |
| }; |
| |
| static float h1[32] = { |
| 0.0006910579, 0.001403793, |
| -0.001268303, -0.004234195, |
| 0.001414246, 0.009458318, |
| -0.0001303859, -0.01798145, |
| -0.004187483, 0.03123862, |
| 0.01456844, -0.05294745, |
| -0.03934878, 0.09980243, |
| 0.1285579, -0.4664053, |
| 0.4664053, -0.1285579, |
| -0.09980243, 0.03934878, |
| 0.05294745, -0.01456844, |
| -0.03123862, 0.004187483, |
| 0.01798145, 0.0001303859, |
| -0.009458318, -0.001414246, |
| 0.004234195, 0.001268303, |
| -0.001403793, -0.0006910579 |
| }; |
| #else |
| #define QMF_ORDER 64 |
| static float h0[64] = { |
| 3.596189e-05, -0.0001123515, |
| -0.0001104587, 0.0002790277, |
| 0.0002298438, -0.0005953563, |
| -0.0003823631, 0.00113826, |
| 0.0005308539, -0.001986177, |
| -0.0006243724, 0.003235877, |
| 0.0005743159, -0.004989147, |
| -0.0002584767, 0.007367171, |
| -0.0004857935, -0.01050689, |
| 0.001894714, 0.01459396, |
| -0.004313674, -0.01994365, |
| 0.00828756, 0.02716055, |
| -0.01485397, -0.03764973, |
| 0.026447, 0.05543245, |
| -0.05095487, -0.09779096, |
| 0.1382363, 0.4600981, |
| 0.4600981, 0.1382363, |
| -0.09779096, -0.05095487, |
| 0.05543245, 0.026447, |
| -0.03764973, -0.01485397, |
| 0.02716055, 0.00828756, |
| -0.01994365, -0.004313674, |
| 0.01459396, 0.001894714, |
| -0.01050689, -0.0004857935, |
| 0.007367171, -0.0002584767, |
| -0.004989147, 0.0005743159, |
| 0.003235877, -0.0006243724, |
| -0.001986177, 0.0005308539, |
| 0.00113826, -0.0003823631, |
| -0.0005953563, 0.0002298438, |
| 0.0002790277, -0.0001104587, |
| -0.0001123515, 3.596189e-05 |
| }; |
| |
| static float h1[64] = { |
| 3.596189e-05, 0.0001123515, |
| -0.0001104587, -0.0002790277, |
| 0.0002298438, 0.0005953563, |
| -0.0003823631, -0.00113826, |
| 0.0005308539, 0.001986177, |
| -0.0006243724, -0.003235877, |
| 0.0005743159, 0.004989147, |
| -0.0002584767, -0.007367171, |
| -0.0004857935, 0.01050689, |
| 0.001894714, -0.01459396, |
| -0.004313674, 0.01994365, |
| 0.00828756, -0.02716055, |
| -0.01485397, 0.03764973, |
| 0.026447, -0.05543245, |
| -0.05095487, 0.09779096, |
| 0.1382363, -0.4600981, |
| 0.4600981, -0.1382363, |
| -0.09779096, 0.05095487, |
| 0.05543245, -0.026447, |
| -0.03764973, 0.01485397, |
| 0.02716055, -0.00828756, |
| -0.01994365, 0.004313674, |
| 0.01459396, -0.001894714, |
| -0.01050689, 0.0004857935, |
| 0.007367171, 0.0002584767, |
| -0.004989147, -0.0005743159, |
| 0.003235877, 0.0006243724, |
| -0.001986177, -0.0005308539, |
| 0.00113826, 0.0003823631, |
| -0.0005953563, -0.0002298438, |
| 0.0002790277, 0.0001104587, |
| -0.0001123515, -3.596189e-05 |
| }; |
| #endif |
| |
| void sb_encoder_init(SBEncState *st, SpeexMode *mode) |
| { |
| int i; |
| encoder_init(&st->st_low, mode); |
| st->full_frame_size = 2*st->st_low.frameSize; |
| st->frame_size = st->st_low.frameSize; |
| st->subframeSize = st->st_low.subframeSize; |
| st->nbSubframes = st->st_low.nbSubframes; |
| st->windowSize = mode->windowSize; |
| st->lpcSize=8; |
| st->bufSize=st->st_low.bufSize; |
| |
| st->lag_factor = .002; |
| st->lpc_floor = 1.0001; |
| st->gamma1=.9; |
| st->gamma2=.6; |
| st->first=1; |
| st->stack = calloc(10000, sizeof(float)); |
| |
| st->x0=calloc(st->full_frame_size, sizeof(float)); |
| st->x1=calloc(st->full_frame_size, sizeof(float)); |
| st->x0d=calloc(st->frame_size, sizeof(float)); |
| st->x1d=calloc(st->frame_size, sizeof(float)); |
| st->high=calloc(st->full_frame_size, sizeof(float)); |
| st->y0=calloc(st->full_frame_size, sizeof(float)); |
| st->y1=calloc(st->full_frame_size, sizeof(float)); |
| |
| st->h0_mem=calloc(QMF_ORDER, sizeof(float)); |
| st->h1_mem=calloc(QMF_ORDER, sizeof(float)); |
| st->g0_mem=calloc(QMF_ORDER, sizeof(float)); |
| st->g1_mem=calloc(QMF_ORDER, sizeof(float)); |
| |
| st->buf=calloc(st->windowSize, sizeof(float)); |
| st->excBuf=calloc(st->bufSize, sizeof(float)); |
| st->exc = st->excBuf + st->bufSize - st->windowSize; |
| /*st->exc=st->excBuf+st->frame_size;*/ |
| |
| st->res=calloc(st->frame_size, sizeof(float)); |
| st->sw=calloc(st->frame_size, sizeof(float)); |
| st->target=calloc(st->frame_size, sizeof(float)); |
| st->window=calloc(st->windowSize, sizeof(float)); |
| for (i=0;i<st->windowSize;i++) |
| st->window[i]=.5*(1-cos(2*M_PI*i/st->windowSize)); |
| |
| st->lagWindow = malloc((st->lpcSize+1)*sizeof(float)); |
| for (i=0;i<st->lpcSize+1;i++) |
| st->lagWindow[i]=exp(-.5*sqr(2*M_PI*st->lag_factor*i)); |
| |
| st->rc = malloc(st->lpcSize*sizeof(float)); |
| st->autocorr = malloc((st->lpcSize+1)*sizeof(float)); |
| st->lpc = malloc((st->lpcSize+1)*sizeof(float)); |
| st->bw_lpc1 = malloc((st->lpcSize+1)*sizeof(float)); |
| st->bw_lpc2 = malloc((st->lpcSize+1)*sizeof(float)); |
| st->lsp = malloc(st->lpcSize*sizeof(float)); |
| st->qlsp = malloc(st->lpcSize*sizeof(float)); |
| st->old_lsp = malloc(st->lpcSize*sizeof(float)); |
| st->old_qlsp = malloc(st->lpcSize*sizeof(float)); |
| st->interp_lsp = malloc(st->lpcSize*sizeof(float)); |
| st->interp_qlsp = malloc(st->lpcSize*sizeof(float)); |
| st->interp_lpc = malloc((st->lpcSize+1)*sizeof(float)); |
| st->interp_qlpc = malloc((st->lpcSize+1)*sizeof(float)); |
| |
| st->mem_sp = calloc(st->lpcSize, sizeof(float)); |
| st->mem_sp2 = calloc(st->lpcSize, sizeof(float)); |
| st->mem_sw = calloc(st->lpcSize, sizeof(float)); |
| |
| } |
| |
| void sb_encoder_destroy(SBEncState *st) |
| { |
| encoder_destroy(&st->st_low); |
| free(st->x0); |
| free(st->x0d); |
| free(st->x1); |
| free(st->x1d); |
| free(st->high); |
| free(st->y0); |
| free(st->y1); |
| free(st->h0_mem); |
| free(st->h1_mem); |
| free(st->g0_mem); |
| free(st->g1_mem); |
| |
| free(st->buf); |
| free(st->window); |
| free(st->excBuf); |
| free(st->sw); |
| free(st->res); |
| free(st->target); |
| free(st->lagWindow); |
| free(st->rc); |
| free(st->autocorr); |
| free(st->lpc); |
| free(st->bw_lpc1); |
| free(st->bw_lpc2); |
| free(st->lsp); |
| free(st->qlsp); |
| free(st->old_lsp); |
| free(st->old_qlsp); |
| free(st->interp_lsp); |
| free(st->interp_qlsp); |
| free(st->interp_lpc); |
| free(st->interp_qlpc); |
| |
| free(st->mem_sp); |
| free(st->mem_sp2); |
| free(st->mem_sw); |
| |
| free(st->stack); |
| |
| } |
| |
| extern float hexc_table[]; |
| split_cb_params split_cb_high = { |
| 8, /*subvect_size*/ |
| 5, /*nb_subvect*/ |
| hexc_table, /*shape_cb*/ |
| 8, /*shape_bits*/ |
| }; |
| |
| void sb_encode(SBEncState *st, float *in, FrameBits *bits) |
| { |
| int i, roots, sub; |
| /* Compute the two sub-bands by filtering with h0 and h1*/ |
| fir_mem(in, h0, st->x0, st->full_frame_size, QMF_ORDER, st->h0_mem); |
| fir_mem(in, h1, st->x1, st->full_frame_size, QMF_ORDER, st->h1_mem); |
| /* Down-sample x0 and x1 */ |
| for (i=0;i<st->frame_size;i++) |
| { |
| st->x0d[i]=st->x0[i<<1]; |
| st->x1d[i]=st->x1[i<<1]; |
| } |
| /* Encode the narrowband part*/ |
| encode(&st->st_low, st->x0d, bits); |
| |
| /* High-band buffering / sync with low band */ |
| for (i=0;i<st->frame_size;i++) |
| { |
| /*st->excBuf[i]=st->exc[i];*/ |
| st->high[i]=st->high[st->frame_size+i]; |
| st->high[st->frame_size+i]=st->x1d[i]; |
| } |
| |
| memmove(st->excBuf, st->excBuf+st->frame_size, (st->bufSize-st->frame_size)*sizeof(float)); |
| |
| /* Start encoding the high-band */ |
| |
| for (i=0;i<st->windowSize;i++) |
| st->buf[i] = st->high[i] * st->window[i]; |
| |
| /* Compute auto-correlation */ |
| autocorr(st->buf, st->autocorr, st->lpcSize+1, st->windowSize); |
| |
| st->autocorr[0] += 1; /* prevents NANs */ |
| st->autocorr[0] *= st->lpc_floor; /* Noise floor in auto-correlation domain */ |
| /* Lag windowing: equivalent to filtering in the power-spectrum domain */ |
| for (i=0;i<st->lpcSize+1;i++) |
| st->autocorr[i] *= st->lagWindow[i]; |
| |
| /* Levinson-Durbin */ |
| wld(st->lpc+1, st->autocorr, st->rc, st->lpcSize); |
| st->lpc[0]=1; |
| |
| /* LPC to LSPs (x-domain) transform */ |
| roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 6, 0.002, st->stack); |
| if (roots!=st->lpcSize) |
| { |
| fprintf (stderr, "roots!=st->lpcSize (found only %d roots)\n", roots); |
| exit(1); |
| } |
| |
| /* x-domain to angle domain*/ |
| for (i=0;i<st->lpcSize;i++) |
| st->lsp[i] = acos(st->lsp[i]); |
| |
| /* LSP quantization */ |
| lsp_quant_high(st->lsp, st->qlsp, st->lpcSize, bits); |
| |
| /*printf ("high_lsp:"); |
| for (i=0;i<st->lpcSize;i++) |
| printf (" %f", st->lsp[i]); |
| printf ("\n"); |
| for (i=0;i<st->lpcSize;i++) |
| st->qlsp[i]=st->lsp[i];*/ |
| |
| |
| if (st->first) |
| { |
| for (i=0;i<st->lpcSize;i++) |
| st->old_lsp[i] = st->lsp[i]; |
| for (i=0;i<st->lpcSize;i++) |
| st->old_qlsp[i] = st->qlsp[i]; |
| } |
| |
| for (sub=0;sub<st->nbSubframes;sub++) |
| { |
| float *exc, *sp, *mem, *res, *target, *sw, tmp, filter_ratio; |
| int offset; |
| float rl, rh; |
| |
| offset = st->subframeSize*sub; |
| sp=st->high+offset; |
| exc=st->excBuf+offset; |
| res=st->res+offset; |
| target=st->target+offset; |
| sw=st->sw+offset; |
| |
| mem=PUSH(st->stack, st->lpcSize); |
| |
| /* LSP interpolation (quantized and unquantized) */ |
| tmp = (.5 + sub)/st->nbSubframes; |
| for (i=0;i<st->lpcSize;i++) |
| st->interp_lsp[i] = (1-tmp)*st->old_lsp[i] + tmp*st->lsp[i]; |
| for (i=0;i<st->lpcSize;i++) |
| st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i]; |
| |
| /* Compute interpolated LPCs (quantized and unquantized) */ |
| for (i=0;i<st->lpcSize;i++) |
| st->interp_lsp[i] = cos(st->interp_lsp[i]); |
| lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,st->stack); |
| |
| for (i=0;i<st->lpcSize;i++) |
| st->interp_qlsp[i] = cos(st->interp_qlsp[i]); |
| lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, st->stack); |
| |
| bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize); |
| bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize); |
| |
| /* Compute mid-band (4000 for wideband) response of low-band and high-band |
| filters */ |
| rl=rh=0; |
| tmp=1; |
| for (i=0;i<=st->lpcSize;i++) |
| { |
| rh += tmp*st->interp_qlpc[i]; |
| tmp = -tmp; |
| } |
| rl = st->st_low.pi_gain[sub]; |
| rl=1/(fabs(rl)+.001); |
| rh=1/(fabs(rh)+.001); |
| /* Compute ratio, will help predict the gain */ |
| filter_ratio=fabs(.001+rh)/(.001+fabs(rl)); |
| |
| |
| if (0) {/* 1 for spectral folding excitation, 0 for stochastic */ |
| float el=0,eh=0,g; |
| /* Backup memory */ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| /* Compute "real excitation" */ |
| residue_mem(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp); |
| |
| #if 1 |
| /* Compute energy of low-band and high-band excitation */ |
| for (i=0;i<st->subframeSize;i++) |
| eh+=sqr(exc[i]); |
| for (i=0;i<st->subframeSize;i++) |
| el+=sqr(st->st_low.exc[offset+i]); |
| |
| for (i=0;i<st->subframeSize;i++) |
| { |
| float p=(.1+exc[i])*filter_ratio/(1+sqrt(el/st->subframeSize)); |
| if (i%8==0) |
| printf ("\nhexc: "); |
| printf ("%f ", p); |
| } |
| printf ("\n"); |
| |
| /* Gain to use if we want to use the low-band excitation for high-band */ |
| g=eh/(.01+el); |
| g=sqrt(g); |
| |
| /* High-band excitation using the low-band excitation and a gain */ |
| for (i=0;i<st->subframeSize;i++) |
| exc[i]=g*st->st_low.exc[offset+i]; |
| |
| /* FIXME: Should encode the gain here */ |
| #endif |
| /* Update the input signal using the non-coded memory */ |
| syn_filt_mem(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, mem); |
| } else if (0) {/* Stochastic split-VQ excitation */ |
| int k,N=4; |
| float el=0,eh=0,eb=0,g; |
| int *index; |
| float *gains; |
| gains = PUSH(st->stack, N); |
| index = (int*) PUSH(st->stack, N); |
| |
| /* Reset excitation */ |
| for (i=0;i<st->subframeSize;i++) |
| exc[i]=0; |
| |
| /* Compute zero response (ringing) of A(z/g1) / ( A(z/g2) * Aq(z) ) */ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| syn_filt_mem(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem); |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| residue_mem(exc, st->bw_lpc1, res, st->subframeSize, st->lpcSize, mem); |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sw[i]; |
| syn_filt_mem(res, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem); |
| |
| /* Compute weighted signal */ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| residue_mem(sp, st->bw_lpc1, sw, st->subframeSize, st->lpcSize, mem); |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sw[i]; |
| syn_filt_mem(sw, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem); |
| |
| /* Compute target signal */ |
| for (i=0;i<st->subframeSize;i++) |
| target[i]=sw[i]-res[i]; |
| |
| |
| /* Compute "real excitation" */ |
| residue_mem(sp, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, st->mem_sp2); |
| /* Energy of "real excitation" */ |
| for (i=0;i<st->subframeSize;i++) |
| eh+=sqr(exc[i]); |
| |
| for (i=0;i<st->subframeSize;i++) |
| exc[i]=0; |
| /* |
| st->st_low.ltp_quant(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, |
| exc, st->st_low.ltp_params, st->st_low.min_pitch, st->st_low.max_pitch, |
| st->lpcSize, st->subframeSize, bits, st->stack, exc); |
| */ |
| /* For all sub-vectors, find best gain and codeword/shape */ |
| for (k=0;k<N;k++) |
| { |
| int of=k*st->subframeSize/N; |
| overlap_cb_search(target+of, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, |
| &stoc[0], 64, &gains[k], &index[k], st->lpcSize, |
| st->subframeSize/N, st->stack); |
| |
| frame_bits_pack(bits,index[k],6); |
| |
| /* Compute response */ |
| for (i=0;i<st->subframeSize;i++) |
| res[i]=0; |
| for (i=0;i<st->subframeSize/N;i++) |
| res[of+i]=gains[k]*stoc[index[k]+i]; |
| residue_zero(res, st->bw_lpc1, res, st->subframeSize, st->lpcSize); |
| syn_filt_zero(res, st->interp_qlpc, res, st->subframeSize, st->lpcSize); |
| syn_filt_zero(res, st->bw_lpc2, res, st->subframeSize, st->lpcSize); |
| /* Update target */ |
| for (i=0;i<st->subframeSize;i++) |
| target[i]-=res[i]; |
| |
| /* Update excitation */ |
| for (i=0;i<st->subframeSize/N;i++) |
| exc[of+i]+=gains[k]*stoc[index[k]+i]; |
| } |
| /* Compute energy of best excitation found */ |
| for (i=0;i<st->subframeSize;i++) |
| eb+=sqr(exc[i]); |
| |
| /* Compute adjustment gain for the new excitation to have the same energy |
| as the "real" one */ |
| g=sqrt(eh/(eb+.001)); |
| |
| /* Compute low-band excitation energy*/ |
| for (i=0;i<st->subframeSize;i++) |
| el+=sqr(st->st_low.exc[offset+i]); |
| |
| /* Quantize all gains */ |
| for (k=0;k<N;k++) |
| { |
| int sign=0; |
| float quant; |
| int best_ind; |
| int of=k*st->subframeSize/N; |
| gains[k]*=g; |
| |
| /* Get sign separately */ |
| if (gains[k]<0) |
| { |
| sign=1; |
| gains[k] = -gains[k]; |
| } |
| /* Use prediction with low-band energy and filter pi-response ratio and |
| then convert to the log domain */ |
| quant = log((1+gains[k])*filter_ratio/(1+sqrt(el/st->subframeSize))); |
| |
| /* Quantize the gain */ |
| best_ind = vq_index(&quant, quant_high_gain2, 1, 8); |
| quant=quant_high_gain2[best_ind]; |
| |
| frame_bits_pack(bits,sign,1); |
| frame_bits_pack(bits,best_ind,3); |
| |
| gains[k]=exp(quant)*(1+sqrt(el/st->subframeSize))/filter_ratio; |
| if (sign) |
| gains[k] = -gains[k]; |
| |
| /* FIXME: Should we use the "adjusted excitation" in the encoder? */ |
| for (i=0;i<st->subframeSize/N;i++) |
| exc[of+i]=gains[k]*stoc[index[k]+i]; |
| |
| } |
| POP(st->stack); |
| POP(st->stack); |
| |
| |
| /*Keep the previous memory*/ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| /* Final signal synthesis from excitation */ |
| syn_filt_mem(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp); |
| |
| /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ |
| residue_mem(sp, st->bw_lpc1, sw, st->subframeSize, st->lpcSize, mem); |
| syn_filt_mem(sw, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw); |
| } else { |
| float el=0; |
| float gc; |
| |
| for (i=0;i<st->subframeSize;i++) |
| el+=sqr(st->st_low.exc[offset+i]); |
| |
| gc = (.01+filter_ratio)/(1+sqrt(el/st->subframeSize)); |
| |
| /* Reset excitation */ |
| for (i=0;i<st->subframeSize;i++) |
| exc[i]=0; |
| |
| /* Compute zero response (ringing) of A(z/g1) / ( A(z/g2) * Aq(z) ) */ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| syn_filt_mem(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem); |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| residue_mem(exc, st->bw_lpc1, res, st->subframeSize, st->lpcSize, mem); |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sw[i]; |
| syn_filt_mem(res, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem); |
| |
| /* Compute weighted signal */ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| residue_mem(sp, st->bw_lpc1, sw, st->subframeSize, st->lpcSize, mem); |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sw[i]; |
| syn_filt_mem(sw, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem); |
| |
| /* Compute target signal */ |
| for (i=0;i<st->subframeSize;i++) |
| target[i]=gc*(sw[i]-res[i]); |
| |
| /* Reset excitation */ |
| for (i=0;i<st->subframeSize;i++) |
| exc[i]=0; |
| |
| print_vec(target, st->subframeSize, "\ntarget"); |
| split_cb_search_nogain(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, |
| &split_cb_high, st->lpcSize, st->subframeSize, |
| exc, bits, st->stack); |
| print_vec(target, st->subframeSize, "after"); |
| |
| for (i=0;i<st->subframeSize;i++) |
| exc[i] *= 1/gc; |
| #if 1 |
| /*Keep the previous memory*/ |
| for (i=0;i<st->lpcSize;i++) |
| mem[i]=st->mem_sp[i]; |
| /* Final signal synthesis from excitation */ |
| syn_filt_mem(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp); |
| |
| /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */ |
| residue_mem(sp, st->bw_lpc1, sw, st->subframeSize, st->lpcSize, mem); |
| syn_filt_mem(sw, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw); |
| #endif |
| } |
| |
| POP(st->stack); |
| } |
| |
| |
| #ifndef RELEASE |
| /* Up-sample coded low-band and high-band*/ |
| for (i=0;i<st->frame_size;i++) |
| { |
| st->x0[(i<<1)]=st->x0d[i]; |
| st->x1[(i<<1)]=st->high[i]; |
| st->x0[(i<<1)+1]=0; |
| st->x1[(i<<1)+1]=0; |
| } |
| /* Reconstruct the original */ |
| fir_mem(st->x0, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem); |
| fir_mem(st->x1, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem); |
| for (i=0;i<st->full_frame_size;i++) |
| in[i]=2*(st->y0[i]-st->y1[i]); |
| #endif |
| for (i=0;i<st->lpcSize;i++) |
| st->old_lsp[i] = st->lsp[i]; |
| for (i=0;i<st->lpcSize;i++) |
| st->old_qlsp[i] = st->qlsp[i]; |
| |
| st->first=0; |
| } |
| |
| |
| |
| |
| |
| void sb_decoder_init(SBDecState *st, SpeexMode *mode) |
| { |
| decoder_init(&st->st_low, mode); |
| st->full_frame_size = 2*st->st_low.frameSize; |
| st->frame_size = st->st_low.frameSize; |
| st->subframeSize = 40; |
| st->nbSubframes = 4; |
| st->lpcSize=8; |
| |
| st->first=1; |
| st->stack = calloc(10000, sizeof(float)); |
| |
| st->x0=calloc(st->full_frame_size, sizeof(float)); |
| st->x1=calloc(st->full_frame_size, sizeof(float)); |
| st->x0d=calloc(st->frame_size, sizeof(float)); |
| st->x1d=calloc(st->frame_size, sizeof(float)); |
| st->high=calloc(st->full_frame_size, sizeof(float)); |
| st->y0=calloc(st->full_frame_size, sizeof(float)); |
| st->y1=calloc(st->full_frame_size, sizeof(float)); |
| |
| st->h0_mem=calloc(QMF_ORDER, sizeof(float)); |
| st->h1_mem=calloc(QMF_ORDER, sizeof(float)); |
| st->g0_mem=calloc(QMF_ORDER, sizeof(float)); |
| st->g1_mem=calloc(QMF_ORDER, sizeof(float)); |
| |
| st->exc=calloc(st->frame_size, sizeof(float)); |
| |
| st->qlsp = malloc(st->lpcSize*sizeof(float)); |
| st->old_qlsp = malloc(st->lpcSize*sizeof(float)); |
| st->interp_qlsp = malloc(st->lpcSize*sizeof(float)); |
| st->interp_qlpc = malloc((st->lpcSize+1)*sizeof(float)); |
| |
| st->mem_sp = calloc(st->lpcSize, sizeof(float)); |
| st->mem_sw = calloc(st->lpcSize, sizeof(float)); |
| |
| } |
| |
| void sb_decoder_destroy(SBDecState *st) |
| { |
| decoder_destroy(&st->st_low); |
| free(st->x0); |
| free(st->x0d); |
| free(st->x1); |
| free(st->x1d); |
| free(st->high); |
| free(st->y0); |
| free(st->y1); |
| free(st->h0_mem); |
| free(st->h1_mem); |
| free(st->g0_mem); |
| free(st->g1_mem); |
| |
| free(st->exc); |
| free(st->qlsp); |
| free(st->old_qlsp); |
| free(st->interp_qlsp); |
| free(st->interp_qlpc); |
| |
| free(st->mem_sp); |
| free(st->mem_sw); |
| |
| free(st->stack); |
| |
| } |
| |
| |
| void sb_decode(SBDecState *st, FrameBits *bits, float *out) |
| { |
| int i, sub; |
| |
| /* Decode the low-band */ |
| decode(&st->st_low, bits, st->x0d); |
| |
| for (i=0;i<st->frame_size;i++) |
| st->exc[i]=0; |
| |
| lsp_unquant_high(st->qlsp, st->lpcSize, bits); |
| |
| if (st->first) |
| { |
| for (i=0;i<st->lpcSize;i++) |
| st->old_qlsp[i] = st->qlsp[i]; |
| } |
| |
| for (sub=0;sub<st->nbSubframes;sub++) |
| { |
| float *exc, *sp, tmp, filter_ratio; |
| int offset; |
| |
| offset = st->subframeSize*sub; |
| sp=st->high+offset; |
| exc=st->exc+offset; |
| |
| /* LSP interpolation */ |
| tmp = (.5 + sub)/st->nbSubframes; |
| for (i=0;i<st->lpcSize;i++) |
| st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i]; |
| |
| /* LSPs to x-domain */ |
| for (i=0;i<st->lpcSize;i++) |
| st->interp_qlsp[i] = cos(st->interp_qlsp[i]); |
| |
| /* LSP to LPC */ |
| lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, st->stack); |
| |
| { |
| float rl=0, rh=0; |
| tmp=1; |
| for (i=0;i<=st->lpcSize;i++) |
| { |
| rh += tmp*st->interp_qlpc[i]; |
| tmp = -tmp; |
| } |
| rl = st->st_low.pi_gain[sub]; |
| rl=1/(fabs(rl)+.001); |
| rh=1/(fabs(rh)+.001); |
| filter_ratio=fabs(.001+rh)/(.001+fabs(rl)); |
| } |
| |
| { |
| int k,N=4,el=0; |
| int *index; |
| float *gains; |
| int of; |
| gains = PUSH(st->stack, N); |
| index = (int*) PUSH(st->stack, N); |
| |
| for (i=0;i<st->subframeSize;i++) |
| el+=sqr(st->st_low.exc[offset+i]); |
| |
| for (k=0;k<N;k++) |
| index[k] = frame_bits_unpack_unsigned(bits,6); |
| |
| for (k=0;k<N;k++) |
| { |
| int sign, gain_ind; |
| sign = frame_bits_unpack_unsigned(bits,1); |
| gain_ind = frame_bits_unpack_unsigned(bits,3); |
| gains[k]=exp(quant_high_gain2[gain_ind])*(1+sqrt(el/st->subframeSize))/filter_ratio; |
| if (sign) |
| gains[k] =- gains[k]; |
| } |
| |
| for (k=0;k<N;k++) |
| { |
| of=k*st->subframeSize/N; |
| for (i=0;i<st->subframeSize/N;i++) |
| exc[of+i]=gains[k]*stoc[index[k]+i]; |
| } |
| |
| POP(st->stack); |
| POP(st->stack); |
| } |
| |
| syn_filt_mem(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp); |
| |
| } |
| |
| /* Up-sample coded low-band and high-band*/ |
| for (i=0;i<st->frame_size;i++) |
| { |
| st->x0[(i<<1)]=st->x0d[i]; |
| st->x1[(i<<1)]=st->high[i]; |
| st->x0[(i<<1)+1]=0; |
| st->x1[(i<<1)+1]=0; |
| } |
| /* Reconstruct the original */ |
| fir_mem(st->x0, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem); |
| fir_mem(st->x1, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem); |
| for (i=0;i<st->full_frame_size;i++) |
| out[i]=2*(st->y0[i]-st->y1[i]); |
| |
| for (i=0;i<st->lpcSize;i++) |
| st->old_qlsp[i] = st->qlsp[i]; |
| |
| st->first=0; |
| |
| } |