blob: 1f151acecbbdc6f9841e2bdc7bc2f21f79bdfbb2 [file] [log] [blame]
/*-----------------------------------------------------------------------*\
FILE........: GAINSHAPE.C
TYPE........: C Module
AUTHOR......: David Rowe
COMPANY.....: Voicetronix
DATE CREATED: 19/2/02
General gain-shape codebook search.
\*-----------------------------------------------------------------------*/
/* Modified by Jean-Marc Valin 2002
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 <stdlib.h>
#include <cb_search.h>
#include "filters.h"
#include <math.h>
#define min(a,b) ((a) < (b) ? (a) : (b))
/*---------------------------------------------------------------------------*\
void overlap_cb_search()
Searches a gain/shape codebook consisting of overlapping entries for the
closest vector to the target. Gives identical results to search() above
buts uses fast end correction algorithm for the synthesis of response
vectors.
\*---------------------------------------------------------------------------*/
float overlap_cb_search(
float target[], /* target vector */
float ak[], /* LPCs for this subframe */
float awk1[], /* Weighted LPCs for this subframe */
float awk2[], /* Weighted LPCs for this subframe */
float codebook[], /* overlapping codebook */
int entries, /* number of overlapping entries to search */
float *gain, /* gain of optimum entry */
int *index, /* index of optimum entry */
int p, /* number of LPC coeffs */
int nsf /* number of samples in subframe */
)
{
float *resp; /* zero state response to current entry */
float *h; /* impulse response of synthesis filter */
float *impulse; /* excitation vector containing one impulse */
float d,e,g,score; /* codebook searching variables */
float bscore; /* score of "best" vector so far */
int i,k; /* loop variables */
/* Initialise */
resp = (float*)malloc(sizeof(float)*nsf);
h = (float*)malloc(sizeof(float)*nsf);
impulse = (float*)malloc(sizeof(float)*nsf);
for(i=0; i<nsf; i++)
impulse[i] = 0.0;
*gain = 0.0;
*index = 0;
bscore = 0.0;
impulse[0] = 1.0;
/* Calculate impulse response of A(z/g2) / ( A(z)*(z/g1) ) */
residue_zero(impulse, awk1, h, nsf, p);
syn_filt_zero(h, ak, h, nsf, p);
syn_filt_zero(h, awk2, h, nsf,p);
/* Calculate codebook zero-response */
residue_zero(&codebook[entries-1],awk1,resp,nsf,p);
syn_filt_zero(resp,ak,resp,nsf,p);
syn_filt_zero(resp,awk2,resp,nsf,p);
/* Search codebook backwards using end correction for synthesis */
for(k=entries-1; k>=0; k--) {
d = 0.0; e = 0.0;
for(i=0; i<nsf; i++) {
d += target[i]*resp[i];
e += resp[i]*resp[i];
}
g = d/(e+.1);
score = g*d;
/*printf ("score: %f %f %f %f\n", target[0],d,e,score);*/
if (score >= bscore) {
bscore = score;
*gain = g;
*index = k;
}
/* Synthesise next entry */
if (k) {
for(i=nsf-1; i>=1; i--)
resp[i] = resp[i-1] + codebook[k-1]*h[i];
resp[0] = codebook[k-1]*h[0];
}
}
free(resp);
free(h);
free(impulse);
return bscore;
}
float split_cb_search(
float target[], /* target vector */
float ak[], /* LPCs for this subframe */
float awk1[], /* Weighted LPCs for this subframe */
float awk2[], /* Weighted LPCs for this subframe */
float codebook[][8], /* overlapping codebook */
int entries, /* number of entries to search */
float *gain, /* gain of optimum entries */
int *index, /* index of optimum entries */
int p, /* number of LPC coeffs */
int nsf, /* number of samples in subframe */
float *exc
)
{
int i,j;
float resp[64][8], E[64];
float t[40], r[40], e[40];
float gains[5];
for (i=0;i<40;i++)
t[i]=target[i];
for (i=0;i<64;i++)
{
residue_zero(codebook[i], awk1, resp[i], 8, p);
syn_filt_zero(resp[i], ak, resp[i], 8, p);
syn_filt_zero(resp[i], awk2, resp[i], 8,p);
E[i]=0;
for(j=0;j<8;j++)
E[i]+=resp[i][j]*resp[i][j];
}
for (i=0;i<5;i++)
{
int best_index;
float corr, best_gain, score, best_score=-1;
for (j=0;j<64;j++)
{
corr=xcorr(resp[j],t+8*i,8);
score=corr*corr/(.001+E[j]);
if (score>best_score)
{
best_index=j;
best_score=score;
best_gain=corr/(.001+E[j]);
}
}
if (1) { /* Simulating scalar quantization of the gain*/
float sign=1;
printf("before: %f\n", best_gain);
if (best_gain<0)
sign=-1;
best_gain = abs(best_gain)+.1;
best_gain = log(best_gain);
if (best_gain>8)
best_gain=8;
if (best_gain<0)
best_gain=0;
/*best_gain=.25*rint(4*best_gain);*/
best_gain=.25*floor(4*best_gain+.5);
best_gain=sign*exp(best_gain);
printf("after: %f\n", best_gain);
}
gains[i]=best_gain;
printf ("search: %d %f %f %f\n", best_index, best_gain, best_gain*best_gain*E[best_index], best_score);
for (j=0;j<40;j++)
e[j]=0;
for (j=0;j<8;j++)
e[8*i+j]=best_gain*codebook[best_index][j];
residue_zero(e, awk1, r, 40, p);
syn_filt_zero(r, ak, r, 40, p);
syn_filt_zero(r, awk2, r, 40,p);
for (j=0;j<40;j++)
t[j]-=r[j];
/*FIXME: Should move that out of the loop if we are to vector-quantize the gains*/
for (j=0;j<40;j++)
exc[j]+=e[j];
}
for (i=0;i<5;i++)
printf ("%f ", gains[i]);
printf ("cbgains: \n");
/*TODO: Perform joint optimization of gains and quantization with prediction*/
for (i=0;i<40;i++)
target[i]=t[i];
}