diff options
Diffstat (limited to 'gr-vocoder/lib/codec2/ampexp.c')
-rw-r--r-- | gr-vocoder/lib/codec2/ampexp.c | 1093 |
1 files changed, 0 insertions, 1093 deletions
diff --git a/gr-vocoder/lib/codec2/ampexp.c b/gr-vocoder/lib/codec2/ampexp.c deleted file mode 100644 index ccec6dce8e..0000000000 --- a/gr-vocoder/lib/codec2/ampexp.c +++ /dev/null @@ -1,1093 +0,0 @@ -/*---------------------------------------------------------------------------*\ - - FILE........: ampexp.c - AUTHOR......: David Rowe - DATE CREATED: 7 August 2012 - - Functions for experimenting with amplitude quantisation. - -\*---------------------------------------------------------------------------*/ - -/* - Copyright (C) 2012 David Rowe - - All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 2.1, as - published by the Free Software Foundation. This program 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 General Public - License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not,see <http://www.gnu.org/licenses/>. -*/ - - -#include <assert.h> -#include <ctype.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ampexp.h" - - -#define PRED_COEFF 0.9 - -/* states for amplitude experiments */ - -struct codebook { - unsigned int k; - unsigned int log2m; - unsigned int m; - float *cb; - unsigned int offset; -}; - -struct AEXP { - float A_prev[MAX_AMP]; - int frames; - float snr; - int snr_n; - float var; - int var_n; - float vq_var; - int vq_var_n; - struct codebook *vq1,*vq2,*vq3,*vq4,*vq5; - - int indexes[5][3]; - MODEL model[3]; - float mag[3]; - MODEL model_uq[3]; -}; - - -/*---------------------------------------------------------------------------*\ - - Bruce Perens' funcs to load codebook files - -\*---------------------------------------------------------------------------*/ - - -static const char format[] = -"The table format must be:\n" -"\tTwo integers describing the dimensions of the codebook.\n" -"\tThen, enough numbers to fill the specified dimensions.\n"; - -static float get_float(FILE * in, const char * name, char * * cursor, char * buffer, int size) -{ - for ( ; ; ) { - char * s = *cursor; - char c; - - while ( (c = *s) != '\0' && !isdigit(c) && c != '-' && c != '.' ) - s++; - - /* Comments start with "#" and continue to the end of the line. */ - if ( c != '\0' && c != '#' ) { - char * end = 0; - float f = 0; - - f = strtod(s, &end); - - if ( end != s ) - *cursor = end; - return f; - } - - if ( fgets(buffer, size, in) == NULL ) { - fprintf(stderr, "%s: Format error. %s\n", name, format); - exit(1); - } - *cursor = buffer; - } -} - -static struct codebook *load(const char * name) -{ - FILE *file; - char line[2048]; - char *cursor = line; - struct codebook *b = malloc(sizeof(struct codebook)); - int i; - int size; - - file = fopen(name, "rt"); - assert(file != NULL); - - *cursor = '\0'; - - b->k = (int)get_float(file, name, &cursor, line, sizeof(line)); - b->m = (int)get_float(file, name ,&cursor, line, sizeof(line)); - size = b->k * b->m; - - b->cb = (float *)malloc(size * sizeof(float)); - - for ( i = 0; i < size; i++ ) { - b->cb[i] = get_float(file, name, &cursor, line, sizeof(line)); - } - - fclose(file); - - return b; -} - - -/*---------------------------------------------------------------------------* \ - - amp_experiment_create() - - Inits states for amplitude quantisation experiments. - -\*---------------------------------------------------------------------------*/ - -struct AEXP *amp_experiment_create() { - struct AEXP *aexp; - int i,j,m; - - aexp = (struct AEXP *)malloc(sizeof(struct AEXP)); - assert (aexp != NULL); - - for(i=0; i<MAX_AMP; i++) - aexp->A_prev[i] = 1.0; - aexp->frames = 0; - aexp->snr = 0.0; - aexp->snr_n = 0; - aexp->var = 0.0; - aexp->var_n = 0; - aexp->vq_var = 0.0; - aexp->vq_var_n = 0; - - //aexp->vq1 = load("amp_1_80_1024a.txt"); - //aexp->vq1 = load("../unittest/st1_10_1024.txt"); - //aexp->vq1 = load("../unittest/amp41_80_1024.txt"); - //aexp->vq1->offset = 40; - aexp->vq1 = load("../unittest/amp1_10_1024.txt"); - aexp->vq1->offset = 0; - aexp->vq2 = load("../unittest/amp11_20_1024.txt"); - aexp->vq2->offset = 10; - - aexp->vq3 = load("../unittest/amp21_40_1024.txt"); - aexp->vq3->offset = 20; - aexp->vq4 = load("../unittest/amp41_60_1024.txt"); - aexp->vq4->offset = 40; - aexp->vq5 = load("../unittest/amp61_80_256.txt"); - aexp->vq5->offset = 60; - - #ifdef CAND2_GS - //aexp->vq1 = load("../unittest/t1_amp1_20_1024.txt"); - //aexp->vq1 = load("../unittest/t2_amp1_20_1024.txt"); - aexp->vq1 = load("../unittest/amp1_20_1024.txt"); - aexp->vq1->offset = 0; - aexp->vq2 = load("../unittest/amp21_40_1024.txt"); - aexp->vq2->offset = 20; - aexp->vq3 = load("../unittest/amp41_60_1024.txt"); - aexp->vq3->offset = 40; - aexp->vq4 = load("../unittest/amp61_80_32.txt"); - aexp->vq4->offset = 60; - #endif - - //#define CAND2_GS - #ifdef CAND2_GS - aexp->vq1 = load("../unittest/amp1_20_1024.txt"); - aexp->vq2 = load("../unittest/amp21_40_1024.txt"); - aexp->vq3 = load("../unittest/amp41_80_1024.txt"); - aexp->vq4 = load("../unittest/amp61_80_32.txt"); - aexp->vq1->offset = 0; - aexp->vq2->offset = 20; - aexp->vq3->offset = 40; - aexp->vq4->offset = 60; - #endif - - //#define CAND1 - #ifdef CAND1 - aexp->vq1 = load("../unittest/amp1_10_128.txt"); - aexp->vq2 = load("../unittest/amp11_20_512.txt"); - aexp->vq3 = load("../unittest/amp21_40_1024.txt"); - aexp->vq4 = load("../unittest/amp41_60_1024.txt"); - aexp->vq5 = load("../unittest/amp61_80_32.txt"); - aexp->vq1->offset = 0; - aexp->vq2->offset = 10; - aexp->vq3->offset = 20; - aexp->vq4->offset = 40; - aexp->vq5->offset = 60; - #endif - - for(i=0; i<3; i++) { - for(j=0; j<5; j++) - aexp->indexes[j][i] = 0; - aexp->mag[i] = 1.0; - aexp->model[i].Wo = TWO_PI*100.0/8000.0; - aexp->model[i].L = floor(PI/aexp->model[i].Wo); - for(m=1; m<=MAX_AMP; m++) - aexp->model[i].A[m] = 10.0; - aexp->model_uq[i] = aexp->model[i]; - } - - return aexp; -} - - -/*---------------------------------------------------------------------------* \ - - amp_experiment_destroy() - -\*---------------------------------------------------------------------------*/ - -void amp_experiment_destroy(struct AEXP *aexp) { - assert(aexp != NULL); - if (aexp->snr != 0.0) - printf("snr: %4.2f dB\n", aexp->snr/aexp->snr_n); - if (aexp->var != 0.0) - printf("var...: %4.3f std dev...: %4.3f (%d amplitude samples)\n", - aexp->var/aexp->var_n, sqrt(aexp->var/aexp->var_n), aexp->var_n); - if (aexp->vq_var != 0.0) - printf("vq var: %4.3f std dev...: %4.3f (%d amplitude samples)\n", - aexp->vq_var/aexp->vq_var_n, sqrt(aexp->vq_var/aexp->vq_var_n), aexp->vq_var_n); - free(aexp); -} - - -/*---------------------------------------------------------------------------*\ - - Various test and experimental functions ................ - -\*---------------------------------------------------------------------------*/ - -/* - Quantisation noise simulation. Assume noise on amplitudes is a uniform - distribution, of +/- x dB. This means x = sqrt(3)*sigma. - - Note: for uniform distribution var = = sigma * sigma = (b-a)*(b-a)/12. -*/ - -static void add_quant_noise(struct AEXP *aexp, MODEL *model, int start, int end, float sigma_dB) -{ - int m; - float x_dB; - float noise_sam_dB; - float noise_sam_lin; - - x_dB = sqrt(3.0) * sigma_dB; - - for(m=start; m<=end; m++) { - noise_sam_dB = x_dB*(1.0 - 2.0*rand()/RAND_MAX); - //printf("%f\n", noise_sam_dB); - noise_sam_lin = pow(10.0, noise_sam_dB/20.0); - model->A[m] *= noise_sam_lin; - aexp->var += noise_sam_dB*noise_sam_dB; - aexp->var_n++; - } - -} - -/* - void print_sparse_pred_error() - - use to check pred error stats (e.g. of first 1kHz) in Octave: - - $ ./c2sim ../raw/hts1a.raw --ampexp > amppe.txt - - octave> load ../src/amppe.txt - octave> std(nonzeros(amppe(:,1:20))) - octave> hist(nonzeros(amppe(:,1:20)),20); - - */ - - -static void print_sparse_pred_error(struct AEXP *aexp, MODEL *model, float mag_thresh) -{ - int m, index; - float mag, error; - float sparse_pe[MAX_AMP]; - - mag = 0.0; - for(m=1; m<=model->L; m++) - mag += model->A[m]*model->A[m]; - mag = 10*log10(mag/model->L); - - if (mag > mag_thresh) { - for(m=0; m<MAX_AMP; m++) { - sparse_pe[m] = 0.0; - } - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - error = PRED_COEFF*20.0*log10(aexp->A_prev[m]) - 20.0*log10(model->A[m]); - //error = 20.0*log10(model->A[m]) - mag; - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe[index] = error; - } - - /* dump sparse amp vector */ - - for(m=0; m<MAX_AMP; m++) - printf("%f ", sparse_pe[m]); - printf("\n"); - } -} - - -static float frame_energy(MODEL *model, float *enormdB) { - int m; - float e, edB; - - e = 0.0; - for(m=1; m<=model->L; m++) - e += model->A[m]*model->A[m]; - edB = 10*log10(e); - - #define VER_E0 - - #ifdef VER_E0 - *enormdB = 10*log10(e/model->L); /* make high and low pitches have similar amps */ - #endif - - #ifdef VER_E1 - e = 0.0; - for(m=1; m<=model->L; m++) - e += 10*log10(model->A[m]*model->A[m]); - *enormdB = e; - #endif - - #ifdef VER_E2 - e = 0.0; - for(m=1; m<=model->L; m++) - e += 10*log10(model->A[m]*model->A[m]); - *enormdB = e/model->L; - #endif - //printf("%f\n", enormdB); - - return edB; -} - -static void print_sparse_amp_error(struct AEXP *aexp, MODEL *model, float edB_thresh) -{ - int m, index; - float edB, enormdB, error, dWo; - float sparse_pe[MAX_AMP]; - - edB = frame_energy(model, &enormdB); - //printf("%f\n", enormdB); - dWo = fabs((aexp->model_uq[2].Wo - aexp->model_uq[1].Wo)/aexp->model_uq[2].Wo); - - if ((edB > edB_thresh) && (dWo < 0.1)) { - for(m=0; m<MAX_AMP; m++) { - sparse_pe[m] = 0.0; - } - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - error = 20.0*log10(model->A[m]) - enormdB; - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe[index] = error; - } - - /* dump sparse amp vector */ - - for(m=0; m<MAX_AMP; m++) - printf("%f ", sparse_pe[m]); - printf("\n"); - } -} - - -int vq_amp(float cb[], float vec[], float weights[], int d, int e, float *se) -{ - float error; /* current error */ - int besti; /* best index so far */ - float best_error; /* best error so far */ - int i,j; - float diff, metric, best_metric; - - besti = 0; - best_metric = best_error = 1E32; - for(j=0; j<e; j++) { - metric = error = 0.0; - for(i=0; i<d; i++) { - if (vec[i] != 0.0) { - diff = (cb[j*d+i] - vec[i]); - error += diff*diff; - metric += weights[i]*diff*diff; - } - } - if (metric < best_metric) { - best_error = error; - best_metric = metric; - besti = j; - } - } - - *se += best_error; - - return(besti); -} - - -static int split_vq(float sparse_pe_out[], struct AEXP *aexp, struct codebook *vq, float weights[], float sparse_pe_in[]) -{ - int i, j, non_zero, vq_ind; - float se; - - vq_ind = vq_amp(vq->cb, &sparse_pe_in[vq->offset], &weights[vq->offset], vq->k, vq->m, &se); - printf("\n offset %d k %d m %d vq_ind %d j: ", vq->offset, vq->k, vq->m, vq_ind); - - non_zero = 0; - for(i=0, j=vq->offset; i<vq->k; i++,j++) { - if (sparse_pe_in[j] != 0.0) { - printf("%d ", j); - sparse_pe_in[j] -= vq->cb[vq->k * vq_ind + i]; - sparse_pe_out[j] += vq->cb[vq->k * vq_ind + i]; - non_zero++; - } - } - aexp->vq_var_n += non_zero; - return vq_ind; -} - - -static void sparse_vq_pred_error(struct AEXP *aexp, - MODEL *model -) -{ - int m, index; - float error, amp_dB, edB, enormdB; - float sparse_pe_in[MAX_AMP]; - float sparse_pe_out[MAX_AMP]; - float weights[MAX_AMP]; - - edB = frame_energy(model, &enormdB); - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_in[m] = 0.0; - sparse_pe_out[m] = 0.0; - } - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - error = PRED_COEFF*20.0*log10(aexp->A_prev[m]) - 20.0*log10(model->A[m]); - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe_in[index] = error; - weights[index] = model->A[m]; - } - - /* vector quantise */ - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_out[m] = sparse_pe_in[m]; - } - - //#define SIM_VQ - #ifndef SIM_VQ - split_vq(sparse_pe_out, aexp, aexp->vq1, weights, sparse_pe_in); - #else - for(m=aexp->vq->offset; m<aexp->vq->offset+aexp->vq->k; m++) { - if (sparse_pe_in[m] != 0.0) { - float error = 8*(1.0 - 2.0*rand()/RAND_MAX); - aexp->vq_var += error*error; - aexp->vq_var_n++; - sparse_pe_out[m] = sparse_pe_in[m] + error; - } - } - #endif - - if (edB > -100.0) - for(m=0; m<MAX_AMP; m++) { - if (sparse_pe_in[m] != 0.0) - aexp->vq_var += pow(sparse_pe_out[m] - sparse_pe_in[m], 2.0); - } - - /* transform quantised amps back */ - - for(m=1; m<=model->L; m++) { - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - amp_dB = PRED_COEFF*20.0*log10(aexp->A_prev[m]) - sparse_pe_out[index]; - //printf("in: %f out: %f\n", sparse_pe_in[index], sparse_pe_out[index]); - //printf("amp_dB: %f A[m] (dB) %f\n", amp_dB, 20.0*log10(model->A[m])); - model->A[m] = pow(10.0, amp_dB/20.0); - } - //exit(0); -} - - -static void split_error(struct AEXP *aexp, struct codebook *vq, float sparse_pe_in[], int ind) -{ - int i, j; - - for(i=0, j=vq->offset; i<vq->k; i++,j++) { - if (sparse_pe_in[j] != 0.0) { - sparse_pe_in[j] -= vq->cb[vq->k * ind + i]; - } - } -} - - -static void sparse_vq_amp(struct AEXP *aexp, MODEL *model) -{ - int m, index; - float error, amp_dB, enormdB; - float sparse_pe_in[MAX_AMP]; - float sparse_pe_out[MAX_AMP]; - float weights[MAX_AMP]; - - frame_energy(model, &enormdB); - - aexp->mag[2] = enormdB; - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_in[m] = 0.0; - sparse_pe_out[m] = 0.0; - } - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - error = 20.0*log10(model->A[m]) - enormdB; - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe_in[index] = error; - weights[index] = pow(model->A[m],0.8); - } - - /* vector quantise */ - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_out[m] = sparse_pe_in[m]; - } - - for(m=0; m<80; m++) - sparse_pe_out[m] = 0; - - #define SPLIT - #ifdef SPLIT - aexp->indexes[0][2] = split_vq(sparse_pe_out, aexp, aexp->vq1, weights, sparse_pe_in); - - aexp->indexes[1][2] = split_vq(sparse_pe_out, aexp, aexp->vq2, weights, sparse_pe_in); - aexp->indexes[2][2] = split_vq(sparse_pe_out, aexp, aexp->vq3, weights, sparse_pe_in); - aexp->indexes[3][2] = split_vq(sparse_pe_out, aexp, aexp->vq4, weights, sparse_pe_in); - aexp->indexes[4][2] = split_vq(sparse_pe_out, aexp, aexp->vq5, weights, sparse_pe_in); - #endif - //#define MULTISTAGE - #ifdef MULTISTAGE - aexp->indexes[0][2] = split_vq(sparse_pe_out, aexp, aexp->vq1, weights, sparse_pe_in); - aexp->indexes[1][2] = split_vq(sparse_pe_out, aexp, aexp->vq2, weights, sparse_pe_in); - aexp->indexes[2][2] = split_vq(sparse_pe_out, aexp, aexp->vq3, weights, sparse_pe_in); - //aexp->indexes[3][2] = split_vq(sparse_pe_out, aexp, aexp->vq4, weights, sparse_pe_in); - #endif - - for(m=0; m<MAX_AMP; m++) { - if (sparse_pe_in[m] != 0.0) - aexp->vq_var += pow(sparse_pe_out[m] - sparse_pe_in[m], 2.0); - } - - /* transform quantised amps back */ - - for(m=1; m<=model->L; m++) { - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - amp_dB = sparse_pe_out[index] + enormdB; - model->A[m] = pow(10.0, amp_dB/20.0); - } - //exit(0); -} - - -static void update_snr_calc(struct AEXP *aexp, MODEL *m1, MODEL *m2) -{ - int m; - float signal, noise, signal_dB; - - assert(m1->L == m2->L); - - signal = 0.0; noise = 1E-32; - for(m=1; m<=m1->L; m++) { - signal += m1->A[m]*m1->A[m]; - noise += pow(m1->A[m] - m2->A[m], 2.0); - //printf("%f %f\n", before[m], model->phi[m]); - } - signal_dB = 10*log10(signal); - if (signal_dB > -100.0) { - aexp->snr += 10.0*log10(signal/noise); - aexp->snr_n++; - } -} - - -/* gain/shape vq search. Returns index of best gain. Gain is additive (as we use log quantisers) */ - -int gain_shape_vq_amp(float cb[], float vec[], float weights[], int d, int e, float *se, float *best_gain) -{ - float error; /* current error */ - int besti; /* best index so far */ - float best_error; /* best error so far */ - int i,j,m; - float diff, metric, best_metric, gain, sumAm, sumCb; - - besti = 0; - best_metric = best_error = 1E32; - for(j=0; j<e; j++) { - - /* compute optimum gain */ - - sumAm = sumCb = 0.0; - m = 0; - for(i=0; i<d; i++) { - if (vec[i] != 0.0) { - m++; - sumAm += vec[i]; - sumCb += cb[j*d+i]; - } - } - gain = (sumAm - sumCb)/m; - - /* compute error */ - - metric = error = 0.0; - for(i=0; i<d; i++) { - if (vec[i] != 0.0) { - diff = vec[i] - cb[j*d+i] - gain; - error += diff*diff; - metric += weights[i]*diff*diff; - } - } - if (metric < best_metric) { - best_error = error; - best_metric = metric; - *best_gain = gain; - besti = j; - } - } - - *se += best_error; - - return(besti); -} - - -static void gain_shape_split_vq(float sparse_pe_out[], struct AEXP *aexp, struct codebook *vq, float weights[], float sparse_pe_in[], float *best_gain) -{ - int i, j, non_zero, vq_ind; - float se; - - vq_ind = gain_shape_vq_amp(vq->cb, &sparse_pe_in[vq->offset], &weights[vq->offset], vq->k, vq->m, &se, best_gain); - //printf("\n offset %d k %d m %d vq_ind %d gain: %4.2f j: ", vq->offset, vq->k, vq->m, vq_ind, *best_gain); - - non_zero = 0; - for(i=0, j=vq->offset; i<vq->k; i++,j++) { - if (sparse_pe_in[j] != 0.0) { - //printf("%d ", j); - sparse_pe_out[j] = vq->cb[vq->k * vq_ind + i] + *best_gain; - non_zero++; - } - } - aexp->vq_var_n += non_zero; -} - - -static void gain_shape_sparse_vq_amp(struct AEXP *aexp, MODEL *model) -{ - int m, index; - float amp_dB, best_gain; - float sparse_pe_in[MAX_AMP]; - float sparse_pe_out[MAX_AMP]; - float weights[MAX_AMP]; - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_in[m] = 0.0; - sparse_pe_out[m] = 0.0; - } - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe_in[index] = 20.0*log10(model->A[m]); - weights[index] = model->A[m]; - } - - /* vector quantise */ - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_out[m] = sparse_pe_in[m]; - } - - gain_shape_split_vq(sparse_pe_out, aexp, aexp->vq1, weights, sparse_pe_in, &best_gain); - gain_shape_split_vq(sparse_pe_out, aexp, aexp->vq2, weights, sparse_pe_in, &best_gain); - gain_shape_split_vq(sparse_pe_out, aexp, aexp->vq3, weights, sparse_pe_in, &best_gain); - gain_shape_split_vq(sparse_pe_out, aexp, aexp->vq4, weights, sparse_pe_in, &best_gain); - - for(m=0; m<MAX_AMP; m++) { - if (sparse_pe_in[m] != 0.0) - aexp->vq_var += pow(sparse_pe_out[m] - sparse_pe_in[m], 2.0); - } - - /* transform quantised amps back */ - - for(m=1; m<=model->L; m++) { - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - amp_dB = sparse_pe_out[index]; - model->A[m] = pow(10.0, amp_dB/20.0); - } - //exit(0); -} - - -static void interp_split_vq(float sparse_pe_out[], struct AEXP *aexp, struct codebook *vq, float sparse_pe_in[], int ind) -{ - int i, j; - float amp_dB; - - for(i=0, j=vq->offset; i<vq->k; i++,j++) { - if (sparse_pe_in[j] != 0.0) { - amp_dB = 0.5*(aexp->mag[0] + vq->cb[vq->k * aexp->indexes[ind][0] + i]); - amp_dB += 0.5*(aexp->mag[2] + vq->cb[vq->k * aexp->indexes[ind][2] + i]); - sparse_pe_out[j] = amp_dB; - } - } -} - - -static void vq_interp(struct AEXP *aexp, MODEL *model, int on) -{ - int i, j, m, index; - float amp_dB; - //struct codebook *vq = aexp->vq1; - float sparse_pe_in[MAX_AMP]; - float sparse_pe_out[MAX_AMP]; - - /* replace odd frames with interp */ - /* once we get an even input frame we can interpolate and output odd */ - /* using VQ to interpolate. This assumes some correlation in - adjacent VQ samples */ - - memcpy(&aexp->model[2], model, sizeof(MODEL)); - - /* once we get an even input frame we have enough information to - replace prev odd frame with interpolated version */ - - if (on && ((aexp->frames % 2) == 0)) { - - /* copy Wo, L, and phases */ - - memcpy(model, &aexp->model[1], sizeof(MODEL)); - //printf("mags: %4.2f %4.2f %4.2f Am: \n", aexp->mag[0], aexp->mag[1], aexp->mag[2]); - - /* now replace Am by interpolation, use similar design to VQ - to handle different bands */ - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe_in[index] = 20.0*log10(model->A[m]); - } - - /* this can be used for when just testing partial interpolation */ - - for(m=0; m<MAX_AMP; m++) { - //sparse_pe_out[m] = sparse_pe_in[m]; - sparse_pe_out[m] = 0; - } - - interp_split_vq(sparse_pe_out, aexp, aexp->vq1, sparse_pe_in, 0); - interp_split_vq(sparse_pe_out, aexp, aexp->vq2, sparse_pe_in, 1); - interp_split_vq(sparse_pe_out, aexp, aexp->vq3, sparse_pe_in, 2); - interp_split_vq(sparse_pe_out, aexp, aexp->vq4, sparse_pe_in, 3); - interp_split_vq(sparse_pe_out, aexp, aexp->vq5, sparse_pe_in, 4); - - for(m=1; m<=model->L; m++) { - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - amp_dB = sparse_pe_out[index]; - //printf(" %4.2f", 10.0*log10(model->A[m])); - model->A[m] = pow(10.0, amp_dB/20.0); - //printf(" %4.2f\n", 10.0*log10(model->A[m])); - } - - #ifdef INITIAL_VER - - for(m=1; m<=model->L; m++) { - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - - if (index < vq->k) { - amp_dB = 0.5*(aexp->mag[0] + vq->cb[vq->k * aexp->indexes[0] + index]); - amp_dB += 0.5*(aexp->mag[2] + vq->cb[vq->k * aexp->indexes[2] + index]); - //printf(" %4.2f", 10.0*log10(model->A[m])); - //amp_dB = 10; - model->A[m] = pow(10.0, amp_dB/20.0); - printf(" %4.2f\n", 10.0*log10(model->A[m])); - } - } - - #endif - } - else - memcpy(model, &aexp->model[1], sizeof(MODEL)); - - /* update memories */ - - for(i=0; i<2; i++) { - memcpy(&aexp->model[i], &aexp->model[i+1], sizeof(MODEL)); - for(j=0; j<5; j++) - aexp->indexes[j][i] = aexp->indexes[j][i+1]; - aexp->mag[i] = aexp->mag[i+1]; - } - -} - - -/* - This functions tests theory that some bands can be combined together - due to less frequency resolution at higher frequencies. This will - reduce the amount of information we need to encode. -*/ - -void smooth_samples(struct AEXP *aexp, MODEL *model, int mode) -{ - int m, i, j, index, step, nav, v, en; - float sparse_pe_in[MAX_AMP], av, amp_dB; - float sparse_pe_out[MAX_AMP]; - float smoothed[MAX_AMP], smoothed_out[MAX_AMP]; - float weights[MAX_AMP]; - float enormdB; - - frame_energy(model, &enormdB); - - for(m=0; m<MAX_AMP; m++) { - sparse_pe_in[m] = 0.0; - sparse_pe_out[m] = 0.0; - } - - /* set up sparse array */ - - for(m=1; m<=model->L; m++) { - assert(model->A[m] > 0.0); - - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - sparse_pe_out[index] = sparse_pe_in[index] = 20.0*log10(model->A[m]) - enormdB; - } - - /* now combine samples at high frequencies to reduce dimension */ - - step=4; - for(i=MAX_AMP/2,v=0; i<MAX_AMP; i+=step,v++) { - - /* average over one band */ - - av = 0.0; nav = 0; - en = i+step; - if (en > (MAX_AMP-1)) - en = MAX_AMP-1; - for(j=i; j<en; j++) { - if (sparse_pe_in[j] != 0.0) { - av += sparse_pe_in[j]; - nav++; - } - } - if (nav) { - av /= nav; - smoothed[v] = av; - weights[v] = pow(10.0,av/20.0); - //weights[v] = 1.0; - } - else - smoothed[v] = 0.0; - - } - - if (mode == 1) { - for(i=0; i<v; i++) - printf("%5.2f ", smoothed[i]); - printf("\n"); - } - - if (mode == 2) { - for(i=0; i<v; i++) - smoothed_out[i] = 0; - split_vq(smoothed_out, aexp, aexp->vq1, weights, smoothed); - for(i=0; i<v; i++) - smoothed[i] = smoothed_out[i]; - } - - /* set all samples to smoothed average */ - - step = 4; - for(i=MAX_AMP/2,v=0; i<MAX_AMP; i+=step,v++) { - en = i+step; - if (en > (MAX_AMP-1)) - en = MAX_AMP-1; - for(j=i; j<en; j++) - sparse_pe_out[j] = smoothed[v]; - } - - /* convert back to Am */ - - for(m=1; m<=model->L; m++) { - index = MAX_AMP*m*model->Wo/PI; - assert(index < MAX_AMP); - amp_dB = sparse_pe_out[index] + enormdB; - //printf("%d %4.2f %4.2f\n", m, 10.0*log10(model->A[m]), amp_dB); - model->A[m] = pow(10.0, amp_dB/20.0); - } - -} - -#define MAX_BINS 40 -static float bins[] = { - /*1000.0, 1200.0, 1400.0, 1600.0, 1800,*/ - 2000.0, 2400.0, 2800.0, - 3000.0, 3400.0, 3600.0, 4000.0}; - -void smooth_amp(struct AEXP *aexp, MODEL *model) { - int m, i; - int nbins; - int b; - float f; - float av[MAX_BINS]; - int nav[MAX_BINS]; - - nbins = sizeof(bins)/sizeof(float); - - /* clear all bins */ - - for(i=0; i<MAX_BINS; i++) { - av[i] = 0.0; - nav[i] = 0; - } - - /* add amps into each bin */ - - for(m=1; m<=model->L; m++) { - f = m*model->Wo*FS/TWO_PI; - if (f > bins[0]) { - - /* find bin */ - - for(i=0; i<nbins; i++) - if ((f > bins[i]) && (f <= bins[i+1])) - b = i; - assert(b < MAX_BINS); - - av[b] += model->A[m]*model->A[m]; - nav[b]++; - } - - } - - /* use averages to est amps */ - - for(m=1; m<=model->L; m++) { - f = m*model->Wo*FS/TWO_PI; - if (f > bins[0]) { - - /* find bin */ - - for(i=0; i<nbins; i++) - if ((f > bins[i]) && (f <= bins[i+1])) - b = i; - assert(b < MAX_BINS); - - /* add predicted phase error to this bin */ - - printf("L %d m %d f %4.f b %d\n", model->L, m, f, b); - - printf(" %d: %4.3f -> ", m, 20*log10(model->A[m])); - model->A[m] = sqrt(av[b]/nav[b]); - printf("%4.3f\n", 20*log10(model->A[m])); - } - } - printf("\n"); -} - -/*---------------------------------------------------------------------------* \ - - amp_experiment() - - Amplitude quantisation experiments. - -\*---------------------------------------------------------------------------*/ - -void amp_experiment(struct AEXP *aexp, MODEL *model, char *arg) { - int m,i; - - memcpy(&aexp->model_uq[2], model, sizeof(MODEL)); - - if (strcmp(arg, "qn") == 0) { - add_quant_noise(aexp, model, 1, model->L, 1); - update_snr_calc(aexp, &aexp->model_uq[2], model); - } - - /* print training samples that can be > train.txt for training VQ */ - - if (strcmp(arg, "train") == 0) - print_sparse_amp_error(aexp, model, 00.0); - - /* VQ of amplitudes, no interpolation (ie 10ms rate) */ - - if (strcmp(arg, "vq") == 0) { - sparse_vq_amp(aexp, model); - vq_interp(aexp, model, 0); - update_snr_calc(aexp, &aexp->model_uq[1], model); - } - - /* VQ of amplitudes, interpolation (ie 20ms rate) */ - - if (strcmp(arg, "vqi") == 0) { - sparse_vq_amp(aexp, model); - vq_interp(aexp, model, 1); - update_snr_calc(aexp, &aexp->model_uq[1], model); - } - - /* gain/shape VQ of amplitudes, 10ms rate (doesn't work that well) */ - - if (strcmp(arg, "gsvq") == 0) { - gain_shape_sparse_vq_amp(aexp, model); - vq_interp(aexp, model, 0); - update_snr_calc(aexp, &aexp->model_uq[1], model); - } - - if (strcmp(arg, "smooth") == 0) { - smooth_samples(aexp, model, 0); - update_snr_calc(aexp, &aexp->model_uq[2], model); - } - - if (strcmp(arg, "smoothtrain") == 0) { - smooth_samples(aexp, model, 1); - //update_snr_calc(aexp, &aexp->model_uq[2], model); - } - - if (strcmp(arg, "smoothvq") == 0) { - smooth_samples(aexp, model, 2); - update_snr_calc(aexp, &aexp->model_uq[2], model); - } - - if (strcmp(arg, "smoothamp") == 0) { - smooth_amp(aexp, model); - update_snr_calc(aexp, &aexp->model_uq[2], model); - } - - /* update states */ - - for(m=1; m<=model->L; m++) - aexp->A_prev[m] = model->A[m]; - aexp->frames++; - for(i=0; i<3; i++) - aexp->model_uq[i] = aexp->model_uq[i+1]; -} - |