/*************************************************************************/ /* */ /* LD-CELP G.728 */ /* */ /* Low-Delay Code Excitation Linear Prediction speech compression. */ /* */ /* Code edited by Michael Concannon. */ /* Based on code written by Alex Zatsman, Analog Devices 1993 */ /* */ /*************************************************************************/ #include #include #include "common.h" #include "parm.h" #include "prototyp.h" extern void init_output(); void init_decoder(); void decoder(); void decode_vector(int); void adapt_decoder(); #ifdef NOPF int postfiltering_p = 0; #else int postfiltering_p = 1; #endif static int d_vec_start; /* Index of the start of the decoded speech vector */ static int d_vec_end; /* Index of the end of the decoded speech vector */ static int w_vec_start; /* Index of the start of vector being written */ static int w_vec_end; /* Index of the end of vector being written */ int VOLATILE decoder_done = 0; #ifdef MAIN extern char *ofile_name; extern char *xfile_name; static void usaged(char*); void main (int argc, char *argv[]) { if (argc != 3) usaged(argv[0]); xfile_name = argv[1]; ofile_name = argv[2]; init_decoder(); ffase = 1; decoder(); } static void usaged(char *name) { fprintf(stderr, "Usage: %s \n", name); exit(0); } #endif real thequeue[QSIZE]; real *vector_end; void decoder() { int i; for(i=0; i= QSIZE) w_vec_start = 0; w_vec_end = w_vec_start; vector_end = thequeue + w_vec_end; decode_vector(0); w_vec_end = w_vec_start + IDIM; if(! decoder_done) { if (w_vec_end >= QSIZE) w_vec_end = 0; write_sound_buffer(IDIM, thequeue + w_vec_end); adapt_decoder(); } } } void init_decoder() { init_bsf_adapter(sf_coeff); sf_coeff_next[0] = 1.0; sf_coeff_obsolete_p = 0; init_gain_adapter(gp_coeff); init_gain_buf(); gp_coeff_next[0] = 1.0; gp_coeff_next[1] = -1.0; gp_coeff_obsolete_p = 0; init_output(); vector_end=thequeue; } void decode_vector(int ignore) { int ix; /* Computed Codebook Index */ int lgx; /* Log Gains INdex */ static real zero_response[IDIM], cb_vec[IDIM]; static real pf_speech[IDIM]; real qs[NUPDATE*IDIM]; static real gain = 1.0; w_vec_end = vector_end - thequeue; d_vec_start = w_vec_end + IDIM; if (d_vec_start >= QSIZE) d_vec_start -= QSIZE; ix = get_index(); if (ix < 0) decoder_done = 1; UPDATE(sf_coeff); zresp(zero_response); cb_excitation(ix, cb_vec); UPDATE(gp_coeff); gain = predict_gain(); sig_scale(gain, cb_vec, qspeech+d_vec_start); lgx = d_vec_start/IDIM; update_gain(qspeech+d_vec_start, log_gains+lgx); mem_update(qspeech+d_vec_start, synspeech+d_vec_start); d_vec_end = d_vec_start + IDIM; if (d_vec_end >= QSIZE) d_vec_end -= QSIZE; if (postfiltering_p) { inv_filter(synspeech+d_vec_start); FFASE(3) { CIRCOPY(qs, synspeech, d_vec_end, NUPDATE*IDIM, QSIZE); psf_adapter(qs); } FFASE(1) compute_sh_coeff(); postfilter(synspeech+d_vec_start, pf_speech); RCOPY(pf_speech, thequeue+d_vec_start, IDIM); } else { RCOPY(synspeech+d_vec_start, thequeue+d_vec_start, IDIM); } NEXT_FFASE; } void adapt_decoder() { real synth [NUPDATE*IDIM], lg [NUPDATE]; int gx; /* gain index */ FFASE(1) { CIRCOPY(synth, synspeech, d_vec_end, NUPDATE*IDIM, QSIZE); bsf_adapter (synth, sf_coeff_next); } FFASE(2) { gx = d_vec_end / IDIM; CIRCOPY(lg, log_gains, gx, NUPDATE, QSIZE/IDIM); gain_adapter(lg, gp_coeff_next); gp_coeff_obsolete_p = 1; } FFASE(3) sf_coeff_obsolete_p = 1; }