diff options
Diffstat (limited to 'gr-vocoder/lib/codec2/phaseexp.c')
-rw-r--r-- | gr-vocoder/lib/codec2/phaseexp.c | 1455 |
1 files changed, 1455 insertions, 0 deletions
diff --git a/gr-vocoder/lib/codec2/phaseexp.c b/gr-vocoder/lib/codec2/phaseexp.c new file mode 100644 index 0000000000..61b240df49 --- /dev/null +++ b/gr-vocoder/lib/codec2/phaseexp.c @@ -0,0 +1,1455 @@ +/*---------------------------------------------------------------------------*\ + + FILE........: phaseexp.c + AUTHOR......: David Rowe + DATE CREATED: June 2012 + + Experimental functions for quantising, modelling and synthesising phase. + +\*---------------------------------------------------------------------------*/ + +/* + 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 "defines.h" +#include "phase.h" +#include "kiss_fft.h" +#include "comp.h" + +#include <assert.h> +#include <ctype.h> +#include <math.h> +#include <string.h> +#include <stdlib.h> + +/* Bruce Perens' funcs to load codebook files */ + +struct codebook { + unsigned int k; + unsigned int log2m; + unsigned int m; + COMP *cb; + unsigned int offset; +}; + +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"; + +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; + float angle; + + 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 = (COMP *)malloc(size * sizeof(COMP)); + + for ( i = 0; i < size; i++ ) { + angle = get_float(file, name, &cursor, line, sizeof(line)); + b->cb[i].real = cos(angle); + b->cb[i].imag = sin(angle); + } + + fclose(file); + + return b; +} + + +/* states for phase experiments */ + +struct PEXP { + float phi1; + float phi_prev[MAX_AMP]; + float Wo_prev; + int frames; + float snr; + float var; + int var_n; + struct codebook *vq1,*vq2,*vq3,*vq4,*vq5; + float vq_var; + int vq_var_n; + MODEL prev_model; + int state; +}; + + +/*---------------------------------------------------------------------------* \ + + phase_experiment_create() + + Inits states for phase quantisation experiments. + +\*---------------------------------------------------------------------------*/ + +struct PEXP * phase_experiment_create() { + struct PEXP *pexp; + int i; + + pexp = (struct PEXP *)malloc(sizeof(struct PEXP)); + assert (pexp != NULL); + + pexp->phi1 = 0; + for(i=0; i<MAX_AMP; i++) + pexp->phi_prev[i] = 0.0; + pexp->Wo_prev = 0.0; + pexp->frames = 0; + pexp->snr = 0.0; + pexp->var = 0.0; + pexp->var_n = 0; + + /* smoothed 10th order for 1st 1 khz */ + //pexp->vq1 = load("../unittest/ph1_10_1024.txt"); + //pexp->vq1->offset = 0; + + /* load experimental phase VQ */ + + //pexp->vq1 = load("../unittest/testn1_20_1024.txt"); + pexp->vq1 = load("../unittest/test.txt"); + //pexp->vq2 = load("../unittest/testn21_40_1024.txt"); + pexp->vq2 = load("../unittest/test11_20_1024.txt"); + pexp->vq3 = load("../unittest/test21_30_1024.txt"); + pexp->vq4 = load("../unittest/test31_40_1024.txt"); + pexp->vq5 = load("../unittest/test41_60_1024.txt"); + pexp->vq1->offset = 0; + pexp->vq2->offset = 10; + pexp->vq3->offset = 20; + pexp->vq4->offset = 30; + pexp->vq5->offset = 40; + + pexp->vq_var = 0.0; + pexp->vq_var_n = 0; + + pexp->state = 0; + + return pexp; +} + + +/*---------------------------------------------------------------------------* \ + + phase_experiment_destroy() + +\*---------------------------------------------------------------------------*/ + +void phase_experiment_destroy(struct PEXP *pexp) { + assert(pexp != NULL); + if (pexp->snr != 0.0) + printf("snr: %4.2f dB\n", pexp->snr/pexp->frames); + if (pexp->var != 0.0) + printf("var...: %4.3f std dev...: %4.3f (%d non zero phases)\n", + pexp->var/pexp->var_n, sqrt(pexp->var/pexp->var_n), pexp->var_n); + if (pexp->vq_var != 0.0) + printf("vq var: %4.3f vq std dev: %4.3f (%d non zero phases)\n", + pexp->vq_var/pexp->vq_var_n, sqrt(pexp->vq_var/pexp->vq_var_n), pexp->vq_var_n); + free(pexp); +} + + +/*---------------------------------------------------------------------------* \ + + Various test and experimental functions ................ + +\*---------------------------------------------------------------------------*/ + +/* Bubblesort to find highest amplitude harmonics */ + +struct AMPINDEX { + float amp; + int index; +}; + +static void bubbleSort(struct AMPINDEX numbers[], int array_size) +{ + int i, j; + struct AMPINDEX temp; + + for (i = (array_size - 1); i > 0; i--) + { + for (j = 1; j <= i; j++) + { + //printf("i %d j %d %f %f \n", i, j, numbers[j-1].amp, numbers[j].amp); + if (numbers[j-1].amp < numbers[j].amp) + { + temp = numbers[j-1]; + numbers[j-1] = numbers[j]; + numbers[j] = temp; + } + } + } +} + + +static void print_pred_error(struct PEXP *pexp, MODEL *model, int start, int end, float mag_thresh) { + int i; + float mag; + + mag = 0.0; + for(i=start; i<=end; i++) + mag += model->A[i]*model->A[i]; + mag = 10*log10(mag/(end-start)); + + if (mag > mag_thresh) { + for(i=start; i<=end; i++) { + float pred = pexp->phi_prev[i] + N*i*(model->Wo + pexp->Wo_prev)/2.0; + float err = pred - model->phi[i]; + err = atan2(sin(err),cos(err)); + printf("%f\n",err); + } + //printf("\n"); + } + +} + + +static void predict_phases(struct PEXP *pexp, MODEL *model, int start, int end) { + int i; + + for(i=start; i<=end; i++) { + model->phi[i] = pexp->phi_prev[i] + N*i*model->Wo; + } + +} +static float refine_Wo(struct PEXP *pexp, + MODEL *model, + int start, + int end); + +/* Fancy state based phase prediction. Actually works OK on most utterances, + but could use some tuning. Breaks down a bit on mmt1. */ + +static void predict_phases_state(struct PEXP *pexp, MODEL *model, int start, int end) { + int i, next_state; + float best_Wo, dWo; + + //best_Wo = refine_Wo(pexp, model, start, end); + //best_Wo = (model->Wo + pexp->Wo_prev)/2.0; + best_Wo = model->Wo; + + dWo = fabs(model->Wo - pexp->Wo_prev)/model->Wo; + next_state = pexp->state; + switch(pexp->state) { + case 0: + if (dWo < 0.1) { + /* UV -> V transition, so start with phases in lock. They will + drift a bit over voiced track which is kinda what we want, so + we don't get clicky speech. + */ + next_state = 1; + for(i=start; i<=end; i++) + pexp->phi_prev[i] = i*pexp->phi1; + } + + break; + case 1: + if (dWo > 0.1) + next_state = 0; + break; + } + pexp->state = next_state; + + if (pexp->state == 0) + for(i=start; i<=end; i++) { + model->phi[i] = PI*(1.0 - 2.0*rand()/RAND_MAX); + } + else + for(i=start; i<=end; i++) { + model->phi[i] = pexp->phi_prev[i] + N*i*best_Wo; + } + printf("state %d\n", pexp->state); +} + +static void struct_phases(struct PEXP *pexp, MODEL *model, int start, int end) { + int i; + + for(i=start; i<=end; i++) + model->phi[i] = pexp->phi1*i; + +} + + +static void predict_phases2(struct PEXP *pexp, MODEL *model, int start, int end) { + int i; + float pred, str, diff; + + for(i=start; i<=end; i++) { + pred = pexp->phi_prev[i] + N*i*model->Wo; + str = pexp->phi1*i; + diff = str - pred; + diff = atan2(sin(diff), cos(diff)); + if (diff > 0) + pred += PI/16; + else + pred -= PI/16; + model->phi[i] = pred; + } + +} + +static void rand_phases(MODEL *model, int start, int end) { + int i; + + for(i=start; i<=end; i++) + model->phi[i] = PI*(1.0 - 2.0*(float)rand()/RAND_MAX); + +} + +static void quant_phase(float *phase, float min, float max, int bits) { + int levels = 1 << bits; + int index; + float norm, step; + + norm = (*phase - min)/(max - min); + index = floor(levels*norm); + + //printf("phase %f norm %f index %d ", *phase, norm, index); + if (index < 0 ) index = 0; + if (index > (levels-1)) index = levels-1; + //printf("index %d ", index); + step = (max - min)/levels; + *phase = min + step*index + 0.5*step; + //printf("step %f phase %f\n", step, *phase); +} + +static void quant_phases(MODEL *model, int start, int end, int bits) { + int i; + + for(i=start; i<=end; i++) { + quant_phase(&model->phi[i], -PI, PI, bits); + } +} + +static void fixed_bits_per_frame(struct PEXP *pexp, MODEL *model, int m, int budget) { + int res, finished; + + res = 3; + finished = 0; + + while(!finished) { + if (m > model->L/2) + res = 2; + if (((budget - res) < 0) || (m > model->L)) + finished = 1; + else { + quant_phase(&model->phi[m], -PI, PI, res); + budget -= res; + m++; + } + } + printf("m: %d L: %d budget: %d\n", m, model->L, budget); + predict_phases(pexp, model, m, model->L); + //rand_phases(model, m, model->L); +} + +/* used to plot histogram of quantisation error, for 3 bits, 8 levels, + should be uniform between +/- PI/8 */ + +static void check_phase_quant(MODEL *model, float tol) +{ + int m; + float phi_before[MAX_AMP]; + + for(m=1; m<=model->L; m++) + phi_before[m] = model->phi[m]; + + quant_phases(model, 1, model->L, 3); + + for(m=1; m<=model->L; m++) { + float err = phi_before[m] - model->phi[m]; + printf("%f\n", err); + if (fabs(err) > tol) + exit(0); + } +} + + +static float est_phi1(MODEL *model, int start, int end) +{ + int m; + float delta, s, c, phi1_est; + + if (end > model->L) + end = model->L; + + s = c = 0.0; + for(m=start; m<end; m++) { + delta = model->phi[m+1] - model->phi[m]; + s += sin(delta); + c += cos(delta); + } + + phi1_est = atan2(s,c); + + return phi1_est; +} + +static void print_phi1_pred_error(MODEL *model, int start, int end) +{ + int m; + float phi1_est; + + phi1_est = est_phi1(model, start, end); + + for(m=start; m<end; m++) { + float err = model->phi[m+1] - model->phi[m] - phi1_est; + err = atan2(sin(err),cos(err)); + printf("%f\n", err); + } +} + + +static void first_order_band(MODEL *model, int start, int end, float phi1_est) +{ + int m; + float pred_err, av_pred_err; + float c,s; + + s = c = 0.0; + for(m=start; m<end; m++) { + pred_err = model->phi[m] - phi1_est*m; + s += sin(pred_err); + c += cos(pred_err); + } + + av_pred_err = atan2(s,c); + for(m=start; m<end; m++) { + model->phi[m] = av_pred_err + phi1_est*m; + model->phi[m] = atan2(sin(model->phi[m]), cos(model->phi[m])); + } + +} + + +static void sub_linear(MODEL *model, int start, int end, float phi1_est) +{ + int m; + + for(m=start; m<end; m++) { + model->phi[m] = m*phi1_est; + } +} + + +static void top_amp(struct PEXP *pexp, MODEL *model, int start, int end, int n_harm, int pred) +{ + int removed = 0, not_removed = 0; + int top, i, j; + struct AMPINDEX sorted[MAX_AMP]; + + /* sort into ascending order of amplitude */ + + printf("\n"); + for(i=start,j=0; i<end; i++,j++) { + sorted[j].amp = model->A[i]; + sorted[j].index = i; + printf("%f ", model->A[i]); + } + bubbleSort(sorted, end-start); + + printf("\n"); + for(j=0; j<n_harm; j++) + printf("%d %f\n", j, sorted[j].amp); + + /* keep phase of top n_harm, predict others */ + + for(i=start; i<end; i++) { + top = 0; + for(j=0; j<n_harm; j++) { + if (model->A[i] == sorted[j].amp) { + top = 1; + assert(i == sorted[j].index); + } + } + + #define ALTTOP + #ifdef ALTTOP + model->phi[i] = 0.0; /* make sure */ + if (top) { + model->phi[i] = i*pexp->phi1; + removed++; + } + else { + model->phi[i] = PI*(1.0 - 2.0*(float)rand()/RAND_MAX); // note: try rand for higher harms + removed++; + } + #else + if (!top) { + model->phi[i] = 0.0; /* make sure */ + if (pred) { + //model->phi[i] = pexp->phi_prev[i] + i*N*(model->Wo + pexp->Wo_prev)/2.0; + model->phi[i] = i*model->phi[1]; + } + else + model->phi[i] = PI*(1.0 - 2.0*(float)rand()/RAND_MAX); // note: try rand for higher harms + removed++; + } + else { + /* need to make this work thru budget of bits */ + quant_phase(&model->phi[i], -PI, PI, 3); + not_removed++; + } + #endif + } + printf("dim: %d rem %d not_rem %d\n", end-start, removed, not_removed); + +} + + +static void limit_prediction_error(struct PEXP *pexp, MODEL *model, int start, int end, float limit) +{ + int i; + float pred, pred_error, error; + + for(i=start; i<=end; i++) { + pred = pexp->phi_prev[i] + N*i*(model->Wo + pexp->Wo_prev)/2.0; + pred_error = pred - model->phi[i]; + pred_error -= TWO_PI*floor((pred_error+PI)/TWO_PI); + quant_phase(&pred_error, -limit, limit, 2); + + error = pred - pred_error - model->phi[i]; + error -= TWO_PI*floor((error+PI)/TWO_PI); + printf("%f\n", pred_error); + model->phi[i] = pred - pred_error; + } +} + + +static void quant_prediction_error(struct PEXP *pexp, MODEL *model, int start, int end, float limit) +{ + int i; + float pred, pred_error; + + for(i=start; i<=end; i++) { + pred = pexp->phi_prev[i] + N*i*(model->Wo + pexp->Wo_prev)/2.0; + pred_error = pred - model->phi[i]; + pred_error -= TWO_PI*floor((pred_error+PI)/TWO_PI); + + printf("%f\n", pred_error); + model->phi[i] = pred - pred_error; + } +} + + +static void print_sparse_pred_error(struct PEXP *pexp, MODEL *model, int start, int end, float mag_thresh) +{ + int i, index; + float mag, pred, error; + float sparse_pe[MAX_AMP]; + + mag = 0.0; + for(i=start; i<=end; i++) + mag += model->A[i]*model->A[i]; + mag = 10*log10(mag/(end-start)); + + if (mag > mag_thresh) { + for(i=0; i<MAX_AMP; i++) { + sparse_pe[i] = 0.0; + } + + for(i=start; i<=end; i++) { + pred = pexp->phi_prev[i] + N*i*(model->Wo + pexp->Wo_prev)/2.0; + error = pred - model->phi[i]; + error = atan2(sin(error),cos(error)); + + index = MAX_AMP*i*model->Wo/PI; + assert(index < MAX_AMP); + sparse_pe[index] = error; + } + + /* dump spare phase vector in polar format */ + + for(i=0; i<MAX_AMP; i++) + printf("%f ", sparse_pe[i]); + printf("\n"); + } +} + + +static void update_snr_calc(struct PEXP *pexp, MODEL *model, float before[]) +{ + int m; + float signal, noise, diff; + + signal = 0.0; noise = 0.0; + for(m=1; m<=model->L; m++) { + signal += model->A[m]*model->A[m]; + diff = cos(model->phi[m]) - cos(before[m]); + noise += pow(model->A[m]*diff, 2.0); + diff = sin(model->phi[m]) - sin(before[m]); + noise += pow(model->A[m]*diff, 2.0); + //printf("%f %f\n", before[m], model->phi[m]); + } + //printf("%f %f snr = %f\n", signal, noise, 10.0*log10(signal/noise)); + pexp->snr += 10.0*log10(signal/noise); +} + + +static void update_variance_calc(struct PEXP *pexp, MODEL *model, float before[]) +{ + int m; + float diff; + + for(m=1; m<model->L; m++) { + diff = model->phi[m] - before[m]; + diff = atan2(sin(diff), cos(diff)); + pexp->var += diff*diff; + } + pexp->var_n += model->L; +} + +void print_vec(COMP cb[], int d, int e) +{ + int i,j; + + for(j=0; j<e; j++) { + for(i=0; i<d; i++) + printf("%f %f ", cb[j*d+i].real, cb[j*d+i].imag); + printf("\n"); + } +} + +static COMP cconj(COMP a) +{ + COMP res; + + res.real = a.real; + res.imag = -a.imag; + + return res; +} + +static COMP cadd(COMP a, COMP b) +{ + COMP res; + + res.real = a.real + b.real; + res.imag = a.imag + b.imag; + + return res; +} + +static COMP cmult(COMP a, COMP b) +{ + COMP res; + + res.real = a.real*b.real - a.imag*b.imag; + res.imag = a.real*b.imag + a.imag*b.real; + + return res; +} + +static int vq_phase(COMP cb[], COMP 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; + int ignore; + COMP diffr; + float diffp, metric, best_metric; + + besti = 0; + best_metric = best_error = 1E32; + for(j=0; j<e; j++) { + error = 0.0; + metric = 0.0; + for(i=0; i<d; i++) { + ignore = (vec[i].real == 0.0) && (vec[i].imag == 0.0); + if (!ignore) { + diffr = cmult(cb[j*d+i], cconj(vec[i])); + diffp = atan2(diffr.imag, diffr.real); + error += diffp*diffp; + metric += weights[i]*weights[i]*diffp*diffp; + //metric += weights[i]*diffp*diffp; + //metric = log10(weights[i]*fabs(diffp)); + //printf("diffp %f metric %f\n", diffp, metric); + //if (metric < log10(PI/(8.0*sqrt(3.0)))) + // metric = log10(PI/(8.0*sqrt(3.0))); + } + } + if (metric < best_metric) { + best_metric = metric; + best_error = error; + besti = j; + } + } + + *se += best_error; + + return(besti); +} + + +static float refine_Wo(struct PEXP *pexp, + MODEL *model, + int start, + int end) + +{ + int i; + float Wo_est, best_var, Wo, var, pred, error, best_Wo; + + /* test variance over a range of Wo values */ + + Wo_est = (model->Wo + pexp->Wo_prev)/2.0; + best_var = 1E32; + for(Wo=0.97*Wo_est; Wo<=1.03*Wo_est; Wo+=0.001*Wo_est) { + + /* predict phase and sum differences between harmonics */ + + var = 0.0; + for(i=start; i<=end; i++) { + pred = pexp->phi_prev[i] + N*i*Wo; + error = pred - model->phi[i]; + error = atan2(sin(error),cos(error)); + var += error*error; + } + + if (var < best_var) { + best_var = var; + best_Wo = Wo; + } + } + + return best_Wo; +} + + +static void split_vq(COMP sparse_pe_out[], struct PEXP *pexp, struct codebook *vq, float weights[], COMP sparse_pe_in[]) +{ + int i, j, non_zero, vq_ind; + + //printf("\n offset %d k %d m %d j: ", vq->offset, vq->k, vq->m); + vq_ind = vq_phase(vq->cb, &sparse_pe_in[vq->offset], &weights[vq->offset], vq->k, vq->m, &pexp->vq_var); + + non_zero = 0; + for(i=0, j=vq->offset; i<vq->k; i++,j++) { + //printf("%f ", atan2(sparse_pe[i].imag, sparse_pe[i].real)); + if ((sparse_pe_in[j].real != 0.0) && (sparse_pe_in[j].imag != 0.0)) { + //printf("%d ", j); + sparse_pe_out[j] = vq->cb[vq->k * vq_ind + i]; + non_zero++; + } + } + pexp->vq_var_n += non_zero; +} + + +static void sparse_vq_pred_error(struct PEXP *pexp, + MODEL *model +) +{ + int i, index; + float pred, error, error_q_angle, best_Wo; + COMP sparse_pe_in[MAX_AMP], sparse_pe_out[MAX_AMP]; + float weights[MAX_AMP]; + COMP error_q_rect; + + best_Wo = refine_Wo(pexp, model, 1, model->L); + //best_Wo = (model->Wo + pexp->Wo_prev)/2.0; + + /* transform to sparse pred error vector */ + + for(i=0; i<MAX_AMP; i++) { + sparse_pe_in[i].real = 0.0; + sparse_pe_in[i].imag = 0.0; + sparse_pe_out[i].real = 0.0; + sparse_pe_out[i].imag = 0.0; + } + + //printf("\n"); + for(i=1; i<=model->L; i++) { + pred = pexp->phi_prev[i] + N*i*best_Wo; + error = pred - model->phi[i]; + + index = MAX_AMP*i*model->Wo/PI; + assert(index < MAX_AMP); + sparse_pe_in[index].real = cos(error); + sparse_pe_in[index].imag = sin(error); + sparse_pe_out[index] = sparse_pe_in[index]; + weights[index] = model->A[i]; + //printf("%d ", index); + } + + /* vector quantise */ + + split_vq(sparse_pe_out, pexp, pexp->vq1, weights, sparse_pe_in); + split_vq(sparse_pe_out, pexp, pexp->vq2, weights, sparse_pe_in); + split_vq(sparse_pe_out, pexp, pexp->vq3, weights, sparse_pe_in); + split_vq(sparse_pe_out, pexp, pexp->vq4, weights, sparse_pe_in); + split_vq(sparse_pe_out, pexp, pexp->vq5, weights, sparse_pe_in); + + /* transform quantised phases back */ + + for(i=1; i<=model->L; i++) { + pred = pexp->phi_prev[i] + N*i*best_Wo; + + index = MAX_AMP*i*model->Wo/PI; + assert(index < MAX_AMP); + error_q_rect = sparse_pe_out[index]; + error_q_angle = atan2(error_q_rect.imag, error_q_rect.real); + model->phi[i] = pred - error_q_angle; + model->phi[i] = atan2(sin(model->phi[i]), cos(model->phi[i])); + } +} + + +static void predict_phases1(struct PEXP *pexp, MODEL *model, int start, int end) { + int i; + float best_Wo; + + best_Wo = refine_Wo(pexp, model, 1, model->L); + + for(i=start; i<=end; i++) { + model->phi[i] = pexp->phi_prev[i] + N*i*best_Wo; + } +} + + +/* + 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_phase(struct PEXP *pexp, MODEL *model, int mode) +{ + int m, i, j, index, step, v, en, nav, st; + COMP sparse_pe_in[MAX_AMP], av; + COMP sparse_pe_out[MAX_AMP]; + COMP smoothed[MAX_AMP]; + float best_Wo, pred, err; + float weights[MAX_AMP]; + float avw, smoothed_weights[MAX_AMP]; + COMP smoothed_in[MAX_AMP], smoothed_out[MAX_AMP]; + + best_Wo = refine_Wo(pexp, model, 1, model->L); + + for(m=0; m<MAX_AMP; m++) { + sparse_pe_in[m].real = sparse_pe_in[m].imag = 0.0; + sparse_pe_out[m].real = sparse_pe_out[m].imag = 0.0; + } + + /* set up sparse array */ + + for(m=1; m<=model->L; m++) { + pred = pexp->phi_prev[m] + N*m*best_Wo; + err = model->phi[m] - pred; + err = atan2(sin(err),cos(err)); + + index = MAX_AMP*m*model->Wo/PI; + assert(index < MAX_AMP); + sparse_pe_in[index].real = model->A[m]*cos(err); + sparse_pe_in[index].imag = model->A[m]*sin(err); + sparse_pe_out[index] = sparse_pe_in[index]; + weights[index] = model->A[m]; + } + + /* now combine samples at high frequencies to reduce dimension */ + + step = 2; + st = 0; + for(i=st,v=0; i<MAX_AMP; i+=step,v++) { + + /* average over one band */ + + av.real = 0.0; av.imag = 0.0; avw = 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].real != 0.0) &&(sparse_pe_in[j].imag != 0.0) ) { + av = cadd(av, sparse_pe_in[j]); + avw += weights[j]; + nav++; + } + } + if (nav) { + smoothed[v] = av; + smoothed_weights[v] = avw/nav; + } + else + smoothed[v].real = smoothed[v].imag = 0.0; + } + + if (mode == 2) { + for(i=0; i<MAX_AMP; i++) { + smoothed_in[i] = smoothed[i]; + smoothed_out[i] = smoothed_in[i]; + } + split_vq(smoothed_out, pexp, pexp->vq1, smoothed_weights, smoothed_in); + for(i=0; i<MAX_AMP; i++) + smoothed[i] = smoothed_out[i]; + } + + /* set all samples to smoothed average */ + + for(i=st,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]; + if (mode == 1) + printf("%f ", atan2(smoothed[v].imag, smoothed[v].real)); + } + if (mode == 1) + printf("\n"); + + /* convert back to Am */ + + for(m=1; m<=model->L; m++) { + index = MAX_AMP*m*model->Wo/PI; + assert(index < MAX_AMP); + pred = pexp->phi_prev[m] + N*m*best_Wo; + err = atan2(sparse_pe_out[index].imag, sparse_pe_out[index].real); + model->phi[m] = pred + err; + } + +} + +/* + Another version of a functions that tests the 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_phase2(struct PEXP *pexp, MODEL *model) { + float m; + float step; + int a,b,h,i; + float best_Wo, pred, err, s,c, phi1_; + + best_Wo = refine_Wo(pexp, model, 1, model->L); + + step = (float)model->L/30; + printf("\nL: %d step: %3.2f am,bm: ", model->L, step); + for(m=(float)model->L/4; m<=model->L; m+=step) { + a = floor(m); + b = floor(m+step); + if (b > model->L) b = model->L; + h = b-a; + + printf("%d,%d,(%d) ", a, b, h); + c = s = 0.0; + if (h>1) { + for(i=a; i<b; i++) { + pred = pexp->phi_prev[i] + N*i*best_Wo; + err = model->phi[i] - pred; + c += cos(err); s += sin(err); + } + phi1_ = atan2(s,c); + for(i=a; i<b; i++) { + pred = pexp->phi_prev[i] + N*i*best_Wo; + printf("%d: %4.3f -> ", i, model->phi[i]); + model->phi[i] = pred + phi1_; + model->phi[i] = atan2(sin(model->phi[i]),cos(model->phi[i])); + printf("%4.3f ", model->phi[i]); + } + } + } +} + + +#define MAX_BINS 40 +//static float bins[] = {2600.0, 2800.0, 3000.0, 3200.0, 3400.0, 3600.0, 3800.0, 4000.0}; +static float bins[] = {/* + + 1000.0, 1100.0, 1200.0, 1300.0, 1400.0, + 1500.0, 1600.0, 1700.0, 1800.0, 1900.0,*/ + + 2000.0, 2400.0, 2800.0, + 3000.0, 3400.0, 3600.0, 4000.0}; + +void smooth_phase3(struct PEXP *pexp, MODEL *model) { + int m, i; + int nbins; + int b; + float f, best_Wo, pred, err; + COMP av[MAX_BINS]; + + nbins = sizeof(bins)/sizeof(float); + best_Wo = refine_Wo(pexp, model, 1, model->L); + + /* clear all bins */ + + for(i=0; i<MAX_BINS; i++) { + av[i].real = 0.0; + av[i].imag = 0.0; + } + + /* add phases 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); + + /* est predicted phase from average */ + + pred = pexp->phi_prev[m] + N*m*best_Wo; + err = model->phi[m] - pred; + av[b].real += cos(err); av[b].imag += sin(err); + } + + } + + /* use averages to est phases */ + + 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); + + pred = pexp->phi_prev[m] + N*m*best_Wo; + err = atan2(av[b].imag, av[b].real); + printf(" %d: %4.3f -> ", m, model->phi[m]); + model->phi[m] = pred + err; + model->phi[m] = atan2(sin(model->phi[m]),cos(model->phi[m])); + printf("%4.3f\n", model->phi[m]); + } + } + printf("\n"); +} + + +/* + Try to code the phase of the largest amplitude in each band. Randomise the + phase of the other harmonics. The theory is that only the largest harmonic + will be audible. +*/ + +void cb_phase1(struct PEXP *pexp, MODEL *model) { + int m, i; + int nbins; + int b; + float f, best_Wo; + float max_val[MAX_BINS]; + int max_ind[MAX_BINS]; + + nbins = sizeof(bins)/sizeof(float); + best_Wo = refine_Wo(pexp, model, 1, model->L); + + for(i=0; i<nbins; i++) + max_val[i] = 0.0; + + /* determine max amplitude for 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); + + if (model->A[m] > max_val[b]) { + max_val[b] = model->A[m]; + max_ind[b] = m; + } + } + + } + + /* randomise phase of other harmonics */ + + 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); + + if (m != max_ind[b]) + model->phi[m] = pexp->phi_prev[m] + N*m*best_Wo; + } + } +} + + +/* + Theory is only the phase of the envelope of signal matters within a + Critical Band. So we estimate the position of an impulse that + approximates the envelope of the signal. +*/ + +void cb_phase2(struct PEXP *pexp, MODEL *model) { + int st, m, i, a, b, step; + float diff,w,c,s,phi1_; + float A[MAX_AMP]; + + for(m=1; m<=model->L; m++) { + A[m] = model->A[m]; + model->A[m] = 0; + } + + st = 2*model->L/4; + step = 3; + model->phi[1] = pexp->phi_prev[1] + (pexp->Wo_prev+model->Wo)*N/2.0; + + printf("L=%d ", model->L); + for(m=st; m<st+step*2; m+=step) { + a = m; b=a+step; + if (b > model->L) + b = model->L; + + c = s = 0; + for(i=a; i<b-1; i++) { + printf("diff %d,%d ", i, i+1); + diff = model->phi[i+1] - model->phi[i]; + //w = (model->A[i+1] + model->A[i])/2; + w = 1.0; + c += w*cos(diff); s += w*sin(diff); + } + phi1_ = atan2(s,c); + printf("replacing: "); + for(i=a; i<b; i++) { + //model->phi[i] = i*phi1_; + //model->phi[i] = i*model->phi[1]; + //model->phi[i] = m*(pexp->Wo_prev+model->Wo)*N/2.0; + model->A[m] = A[m]; + printf("%d ", i); + } + printf(" . "); + } + printf("\n"); +} + + +static void smooth_phase4(MODEL *model) { + int m; + float phi_m, phi_m_1; + + if (model->L > 25) { + printf("\nL %d\n", model->L); + for(m=model->L/2; m<=model->L; m+=2) { + if ((m+1) <= model->L) { + phi_m = (model->phi[m] - model->phi[m+1])/2.0; + phi_m_1 = (model->phi[m+1] - model->phi[m])/2.0; + model->phi[m] = phi_m; + model->phi[m+1] = phi_m_1; + printf("%d %4.3f %4.3f ", m, phi_m, phi_m_1); + } + } + } + +} + +/* try repeating last frame, just advance phases to account for time shift */ + +static void repeat_phases(struct PEXP *pexp, MODEL *model) { + int m; + + *model = pexp->prev_model; + for(m=1; m<=model->L; m++) + model->phi[m] += N*m*model->Wo; + +} + +/*---------------------------------------------------------------------------*\ + + phase_experiment() + + Phase quantisation experiments. + +\*---------------------------------------------------------------------------*/ + +void phase_experiment(struct PEXP *pexp, MODEL *model, char *arg) { + int m; + float before[MAX_AMP]; + + assert(pexp != NULL); + memcpy(before, &model->phi[0], sizeof(float)*MAX_AMP); + + if (strcmp(arg,"q3") == 0) { + quant_phases(model, 1, model->L, 3); + update_snr_calc(pexp, model, before); + update_variance_calc(pexp, model, before); + } + + if (strcmp(arg,"dec2") == 0) { + if ((pexp->frames % 2) != 0) { + predict_phases(pexp, model, 1, model->L); + update_snr_calc(pexp, model, before); + update_variance_calc(pexp, model, before); + } + } + + if (strcmp(arg,"repeat") == 0) { + if ((pexp->frames % 2) != 0) { + repeat_phases(pexp, model); + update_snr_calc(pexp, model, before); + update_variance_calc(pexp, model, before); + } + } + + if (strcmp(arg,"vq") == 0) { + sparse_vq_pred_error(pexp, model); + update_snr_calc(pexp, model, before); + update_variance_calc(pexp, model, before); + } + + if (strcmp(arg,"pred") == 0) + predict_phases_state(pexp, model, 1, model->L); + + if (strcmp(arg,"pred1k") == 0) + predict_phases(pexp, model, 1, model->L/4); + + if (strcmp(arg,"smooth") == 0) { + smooth_phase(pexp, model,0); + update_snr_calc(pexp, model, before); + } + if (strcmp(arg,"smoothtrain") == 0) + smooth_phase(pexp, model,1); + if (strcmp(arg,"smoothvq") == 0) { + smooth_phase(pexp, model,2); + update_snr_calc(pexp, model, before); + } + + if (strcmp(arg,"smooth2") == 0) + smooth_phase2(pexp, model); + if (strcmp(arg,"smooth3") == 0) + smooth_phase3(pexp, model); + if (strcmp(arg,"smooth4") == 0) + smooth_phase4(model); + if (strcmp(arg,"vqsmooth3") == 0) { + sparse_vq_pred_error(pexp, model); + smooth_phase3(pexp, model); + } + + if (strcmp(arg,"cb1") == 0) { + cb_phase1(pexp, model); + update_snr_calc(pexp, model, before); + } + + if (strcmp(arg,"top") == 0) { + //top_amp(pexp, model, 1, model->L/4, 4, 1); + //top_amp(pexp, model, model->L/4, model->L/3, 4, 1); + //top_amp(pexp, model, model->L/3+1, model->L/2, 4, 1); + //top_amp(pexp, model, model->L/2, model->L, 6, 1); + //rand_phases(model, model->L/2, 3*model->L/4); + //struct_phases(pexp, model, model->L/2, 3*model->L/4); + //update_snr_calc(pexp, model, before); + } + + if (strcmp(arg,"pred23") == 0) { + predict_phases2(pexp, model, model->L/2, model->L); + update_snr_calc(pexp, model, before); + } + + if (strcmp(arg,"struct23") == 0) { + struct_phases(pexp, model, model->L/2, 3*model->L/4 ); + update_snr_calc(pexp, model, before); + } + + if (strcmp(arg,"addnoise") == 0) { + int m; + float max; + + max = 0; + for(m=1; m<=model->L; m++) + if (model->A[m] > max) + max = model->A[m]; + max = 20.0*log10(max); + for(m=1; m<=model->L; m++) + if (20.0*log10(model->A[m]) < (max-20)) { + model->phi[m] += (PI/4)*(1.0 -2.0*rand()/RAND_MAX); + //printf("m %d\n", m); + } + } + + /* normalise phases */ + + for(m=1; m<=model->L; m++) + model->phi[m] = atan2(sin(model->phi[m]), cos(model->phi[m])); + + /* update states */ + + //best_Wo = refine_Wo(pexp, model, model->L/2, model->L); + pexp->phi1 += N*model->Wo; + + for(m=1; m<=model->L; m++) + pexp->phi_prev[m] = model->phi[m]; + pexp->Wo_prev = model->Wo; + pexp->frames++; + pexp->prev_model = *model; +} + +#ifdef OLD_STUFF + //quant_phases(model, 1, model->L, 3); + //update_variance_calc(pexp, model, before); + //print_sparse_pred_error(pexp, model, 1, model->L, 40.0); + + //sparse_vq_pred_error(pexp, model); + + //quant_phases(model, model->L/4+1, model->L, 3); + + //predict_phases1(pexp, model, 1, model->L/4); + //quant_phases(model, model->L/4+1, model->L, 3); + + //quant_phases(model, 1, model->L/8, 3); + + //update_snr_calc(pexp, model, before); + //update_variance_calc(pexp, model, before); + + //fixed_bits_per_frame(pexp, model, 40); + //struct_phases(pexp, model, 1, model->L/4); + //rand_phases(model, 10, model->L); + //for(m=1; m<=model->L; m++) + // model->A[m] = 0.0; + //model->A[model->L/2] = 1000; + //repeat_phases(model, 20); + //predict_phases(pexp, model, 1, model->L/4); + //quant_phases(model, 1, 10, 3); + //quant_phases(model, 10, 20, 2); + //repeat_phases(model, 20); + //rand_phases(model, 3*model->L/4, model->L); + // print_phi1_pred_error(model, 1, model->L); + //predict_phases(pexp, model, 1, model->L/4); + //first_order_band(model, model->L/4, model->L/2); + //first_order_band(model, model->L/2, 3*model->L/4); + //if (fabs(model->Wo - pexp->Wo_prev)< 0.1*model->Wo) + + //print_pred_error(pexp, model, 1, model->L, 40.0); + //print_sparse_pred_error(pexp, model, 1, model->L, 40.0); + + //phi1_est = est_phi1(model, 1, model->L/4); + //print_phi1_pred_error(model, 1, model->L/4); + + //first_order_band(model, 1, model->L/4, phi1_est); + //sub_linear(model, 1, model->L/4, phi1_est); + + //top_amp(pexp, model, 1, model->L/4, 4); + //top_amp(pexp, model, model->L/4, model->L/2, 4); + + //first_order_band(model, 1, model->L/4, phi1_est); + //first_order_band(model, model->L/4, model->L/2, phi1_est); + + //if (fabs(model->Wo - pexp->Wo_prev) > 0.2*model->Wo) + // rand_phases(model, model->L/2, model->L); + + //top_amp(pexp, model, 1, model->L/4, 4); + //top_amp(pexp, model, model->L/4, model->L/2, 8); + //top_amp(pexp, model, model->L/4+1, model->L/2, 10, 1); + //top_amp(pexp, model, 1, model->L/4, 10, 1); + //top_amp(pexp, model, model->L/4+1, 3*model->L/4, 10, 1); + //top_amp(pexp, model, 1, 3*model->L/4, 20, 1); + + #ifdef REAS_CAND1 + predict_phases(pexp, model, 1, model->L/4); + top_amp(pexp, model, model->L/4+1, 3*model->L/4, 10, 1); + rand_phases(model, 3*model->L/4+1, model->L); + #endif + + #ifdef REAS_CAND2 + if ((pexp->frames % 2) == 0) { + //printf("quant\n"); + predict_phases(pexp, model, 1, model->L/4); + //top_amp(pexp, model, model->L/4+1, 3*model->L/4, 20, 1); + top_amp(pexp, model, model->L/4+1, 7*model->L/8, 20, 1); + rand_phases(model, 7*model->L/8+1, model->L); + } + else { + //printf("predict\n"); + predict_phases(pexp, model, 1, model->L); + } + #endif + + //#define REAS_CAND3 + #ifdef REAS_CAND3 + if ((pexp->frames % 3) != 0) { + printf("pred\n"); + predict_phases(pexp, model, 1, model->L); + } + else { + predict_phases(pexp, model, 1, model->L/4); + fixed_bits_per_frame(pexp, model, model->L/4+1, 60); + } + #endif + //predict_phases(pexp, model, model->L/4, model->L); + + + //print_pred_error(pexp, model, 1, model->L); + //limit_prediction_error(pexp, model, model->L/2, model->L, PI/2); +#endif |