void lspvq_quantise( float lsp[], float lsp_[], int order ) { int i,k,m,ncb, nlsp; float wt[LPC_ORD], lsp_hz[LPC_ORD]; const float *cb; float se; int index; for(i=0; i<LPC_ORD; i++) { wt[i] = 1.0; lsp_hz[i] = 4000.0*lsp[i]/PI; } /* scalar quantise LSPs 1,2,3,4 */ /* simple uniform scalar quantisers */ for(i=0; i<4; i++) { k = lsp_cb[i].k; m = lsp_cb[i].m; cb = lsp_cb[i].cb; index = quantise(cb, &lsp_hz[i], wt, k, m, &se); lsp_[i] = cb[index*k]*PI/4000.0; } //#define WGHT #ifdef WGHT for(i=4; i<9; i++) { wt[i] = 1.0/(lsp[i]-lsp[i-1]) + 1.0/(lsp[i+1]-lsp[i]); //printf("wt[%d] = %f\n", i, wt[i]); } wt[9] = 1.0/(lsp[i]-lsp[i-1]); #endif /* VQ LSPs 5,6,7,8,9,10 */ ncb = 4; nlsp = 4; k = lsp_cbjnd[ncb].k; m = lsp_cbjnd[ncb].m; cb = lsp_cbjnd[ncb].cb; index = quantise(cb, &lsp_hz[nlsp], &wt[nlsp], k, m, &se); for(i=4; i<LPC_ORD; i++) { lsp_[i] = cb[index*k+i-4]*(PI/4000.0); //printf("%4.f (%4.f) ", lsp_hz[i], cb[index*k+i-4]); } }
void encode_lsps_diff_freq_vq(int indexes[], float lsp[], int order) { int i,k,m; float lsp_hz[LPC_MAX]; float lsp__hz[LPC_MAX]; float dlsp[LPC_MAX]; float dlsp_[LPC_MAX]; float wt[LPC_MAX]; const float * cb; float se; for(i=0; i<LPC_ORD; i++) { wt[i] = 1.0; } /* convert from radians to Hz so we can use human readable frequencies */ for(i=0; i<order; i++) lsp_hz[i] = (4000.0/PI)*lsp[i]; /* scalar quantisers for LSP differences 1..4 */ wt[0] = 1.0; for(i=0; i<4; i++) { if (i) dlsp[i] = lsp_hz[i] - lsp__hz[i-1]; else dlsp[0] = lsp_hz[0]; k = lsp_cbd[i].k; m = lsp_cbd[i].m; cb = lsp_cbd[i].cb; indexes[i] = quantise(cb, &dlsp[i], wt, k, m, &se); dlsp_[i] = cb[indexes[i]*k]; if (i) lsp__hz[i] = lsp__hz[i-1] + dlsp_[i]; else lsp__hz[0] = dlsp_[0]; } /* VQ LSPs 5,6,7,8,9,10 */ k = lsp_cbjnd[4].k; m = lsp_cbjnd[4].m; cb = lsp_cbjnd[4].cb; indexes[4] = quantise(cb, &lsp_hz[4], &wt[4], k, m, &se); }
void encode_lsps_diff_time(int indexes[], float lsps[], float lsps__prev[], int order) { int i,k,m; float lsps_dt[LPC_ORD]; float wt[LPC_MAX]; const float * cb; float se; /* Determine difference in time and convert from radians to Hz so we can use human readable frequencies */ for(i=0; i<LPC_ORD; i++) { lsps_dt[i] = (4000/PI)*(lsps[i] - lsps__prev[i]); } /* scalar quantisers */ wt[0] = 1.0; for(i=0; i<order; i++) { k = lsp_cbdt[i].k; m = lsp_cbdt[i].m; cb = lsp_cbdt[i].cb; indexes[i] = quantise(cb, &lsps_dt[i], wt, k, m, &se); } }
void lspjnd_quantise(float lsps[], float lsps_[], int order) { int i,k,m; float wt[LPC_ORD], lsps_hz[LPC_ORD]; const float *cb; float se = 0.0; int index; for(i=0; i<LPC_ORD; i++) { wt[i] = 1.0; } /* convert to Hz */ for(i=0; i<LPC_ORD; i++) { lsps_hz[i] = lsps[i]*(4000.0/PI); lsps_[i] = lsps[i]; } /* simple uniform scalar quantisers */ for(i=0; i<4; i++) { k = lsp_cbjnd[i].k; m = lsp_cbjnd[i].m; cb = lsp_cbjnd[i].cb; index = quantise(cb, &lsps_hz[i], wt, k, m, &se); lsps_[i] = cb[index*k]*(PI/4000.0); } /* VQ LSPs 5,6,7,8,9,10 */ k = lsp_cbjnd[4].k; m = lsp_cbjnd[4].m; cb = lsp_cbjnd[4].cb; index = quantise(cb, &lsps_hz[4], &wt[4], k, m, &se); //printf("k = %d m = %d c[0] %f cb[k] %f\n", k,m,cb[0],cb[k]); //printf("index = %4d: ", index); for(i=4; i<LPC_ORD; i++) { lsps_[i] = cb[index*k+i-4]*(PI/4000.0); //printf("%4.f (%4.f) ", lsps_hz[i], cb[index*k+i-4]); } //printf("\n"); }
void encode_lspds_scalar( int indexes[], float lsp[], int order ) { int i,k,m; float lsp_hz[LPC_MAX]; float lsp__hz[LPC_MAX]; float dlsp[LPC_MAX]; float dlsp_[LPC_MAX]; float wt[LPC_MAX]; const float *cb; float se; assert(order == LPC_ORD); for(i=0; i<order; i++) { wt[i] = 1.0; } /* convert from radians to Hz so we can use human readable frequencies */ for(i=0; i<order; i++) lsp_hz[i] = (4000.0/PI)*lsp[i]; //printf("\n"); wt[0] = 1.0; for(i=0; i<order; i++) { /* find difference from previous qunatised lsp */ if (i) dlsp[i] = lsp_hz[i] - lsp__hz[i-1]; else dlsp[0] = lsp_hz[0]; k = lsp_cbd[i].k; m = lsp_cbd[i].m; cb = lsp_cbd[i].cb; indexes[i] = quantise(cb, &dlsp[i], wt, k, m, &se); dlsp_[i] = cb[indexes[i]*k]; if (i) lsp__hz[i] = lsp__hz[i-1] + dlsp_[i]; else lsp__hz[0] = dlsp_[0]; //printf("%d lsp %3.2f dlsp %3.2f dlsp_ %3.2f lsp_ %3.2f\n", i, lsp_hz[i], dlsp[i], dlsp_[i], lsp__hz[i]); } }
void lspd_quantise( float lsp[], float lsp_[], int order ) { int i,k,m; float lsp_hz[LPC_MAX]; float lsp__hz[LPC_MAX]; float dlsp[LPC_MAX]; float dlsp_[LPC_MAX]; float wt[1]; const float *cb; float se; int indexes[LPC_MAX]; /* convert from radians to Hz so we can use human readable frequencies */ for(i=0; i<order; i++) lsp_hz[i] = (4000.0/PI)*lsp[i]; dlsp[0] = lsp_hz[0]; for(i=1; i<order; i++) dlsp[i] = lsp_hz[i] - lsp_hz[i-1]; /* simple uniform scalar quantisers */ wt[0] = 1.0; for(i=0; i<order; i++) { if (i) dlsp[i] = lsp_hz[i] - lsp__hz[i-1]; else dlsp[0] = lsp_hz[0]; k = lsp_cbd[i].k; m = lsp_cbd[i].m; cb = lsp_cbd[i].cb; indexes[i] = quantise(cb, &dlsp[i], wt, k, m, &se); dlsp_[i] = cb[indexes[i]*k]; if (i) lsp__hz[i] = lsp__hz[i-1] + dlsp_[i]; else lsp__hz[0] = dlsp_[0]; } for(; i<order; i++) lsp__hz[i] = lsp__hz[i-1] + dlsp[i]; /* convert back to radians */ for(i=0; i<order; i++) lsp_[i] = (PI/4000.0)*lsp__hz[i]; }
void lspdt_quantise(float lsps[], float lsps_[], float lsps__prev[], int mode) { int i; float wt[LPC_ORD]; float lsps_dt[LPC_ORD]; #ifdef TRY_LSPDT_VQ int k,m; int index; const float *cb; float se = 0.0; #endif // TRY_LSPDT_VQ //compute_weights(lsps, wt, LPC_ORD); for(i=0; i<LPC_ORD; i++) { wt[i] = 1.0; } //compute_weights(lsps, wt, LPC_ORD ); for(i=0; i<LPC_ORD; i++) { lsps_dt[i] = lsps[i] - lsps__prev[i]; lsps_[i] = lsps__prev[i]; } //#define TRY_LSPDT_VQ #ifdef TRY_LSPDT_VQ /* this actually improves speech a bit, but 40ms updates works surprsingly well.... */ k = lsp_cbdt[0].k; m = lsp_cbdt[0].m; cb = lsp_cbdt[0].cb; index = quantise(cb, lsps_dt, wt, k, m, &se); for(i=0; i<LPC_ORD; i++) { lsps_[i] += cb[index*k + i]; } #endif }
void encode_lsps_scalar(int indexes[], float lsp[], int order) { int i,k,m; float wt[1]; float lsp_hz[LPC_MAX]; const float * cb; float se; /* convert from radians to Hz so we can use human readable frequencies */ for(i=0; i<order; i++) lsp_hz[i] = (4000.0/PI)*lsp[i]; /* scalar quantisers */ wt[0] = 1.0; for(i=0; i<order; i++) { k = lsp_cb[i].k; m = lsp_cb[i].m; cb = lsp_cb[i].cb; indexes[i] = quantise(cb, &lsp_hz[i], wt, k, m, &se); } }
int main(int argc, char *argv[]) { long k,m; /* dimension and codebook size */ float *vec; /* current vector */ float *cb; /* vector codebook */ float *cent; /* centroids for each codebook entry */ long *n; /* number of vectors in this interval */ long J; /* number of vectors in training set */ long i,j; long ind; /* index of current vector */ float se; /* squared error for this iteration */ float Dn,Dn_1; /* current and previous iterations distortion */ float delta; /* improvement in distortion */ FILE *ftrain; /* file containing training set */ FILE *fvq; /* file containing vector quantiser */ /* Interpret command line arguments */ if (argc != 5) { printf("usage: vqtrain TrainFile K M VQFile\n"); exit(0); } /* Open training file */ ftrain = fopen(argv[1],"rb"); if (ftrain == NULL) { printf("Error opening training database file: %s\n",argv[1]); exit(1); } /* determine k and m, and allocate arrays */ k = atol(argv[2]); m = atol(argv[3]); printf("dimension K=%ld number of entries M=%ld\n", k,m); vec = (float*)malloc(sizeof(float)*k); cb = (float*)malloc(sizeof(float)*k*m); cent = (float*)malloc(sizeof(float)*k*m); n = (long*)malloc(sizeof(long)*m); if (cb == NULL || cb == NULL || cent == NULL || vec == NULL) { printf("Error in malloc.\n"); exit(1); } /* determine size of training set */ J = 0; while(fread(vec, sizeof(float), k, ftrain) == k) J++; printf("J=%ld entries in training set\n", J); /* set up initial codebook state from samples of training set */ rewind(ftrain); fread(cb, sizeof(float), k*m, ftrain); /* main loop */ Dn = 1E32; j = 1; do { Dn_1 = Dn; /* zero centroids */ for(i=0; i<m; i++) { zero(¢[i*k], k); n[i] = 0; } /* quantise training set */ se = 0.0; rewind(ftrain); for(i=0; i<J; i++) { fread(vec, sizeof(float), k, ftrain); ind = quantise(cb, vec, k, m, &se); n[ind]++; acc(¢[ind*k], vec, k); } Dn = se/J; delta = (Dn_1-Dn)/Dn; printf("\r Iteration %ld, Dn = %f, Delta = %e\n", j, Dn, delta); j++; /* determine new codebook from centriods */ if (delta > DELTAQ) for(i=0; i<m; i++) { if (n[i] != 0) { norm(¢[i*k], k, n[i]); memcpy(&cb[i*k], ¢[i*k], k*sizeof(float)); } } } while (delta > DELTAQ); /* save codebook to disk */ fvq = fopen(argv[4],"wt"); if (fvq == NULL) { printf("Error opening VQ file: %s\n",argv[4]); exit(1); } for(j=0; j<m; j++) { for(i=0; i<k; i++) fprintf(fvq,"%f ",cb[j*k+i]); fprintf(fvq,"\n"); } fclose(fvq); return 0; }
float lpc_model_amplitudes( float Sn[], /* Input frame of speech samples */ float w[], MODEL *model, /* sinusoidal model parameters */ int order, /* LPC model order */ int lsp_quant, /* optional LSP quantisation if non-zero */ float ak[] /* output aks */ ) { float Wn[M]; float R[LPC_MAX+1]; float E; int i,j; float snr; float lsp[LPC_MAX]; float lsp_hz[LPC_MAX]; float lsp_[LPC_MAX]; int roots; /* number of LSP roots found */ int index; float se; int k,m; const float * cb; float wt[LPC_MAX]; for(i=0; i<M; i++) Wn[i] = Sn[i]*w[i]; autocorrelate(Wn,R,M,order); levinson_durbin(R,ak,order); E = 0.0; for(i=0; i<=order; i++) E += ak[i]*R[i]; for(i=0; i<order; i++) wt[i] = 1.0; if (lsp_quant) { roots = lpc_to_lsp(ak, order, lsp, 5, LSP_DELTA1); if (roots != order) printf("LSP roots not found\n"); /* convert from radians to Hz to make quantisers more human readable */ for(i=0; i<order; i++) lsp_hz[i] = (4000.0/PI)*lsp[i]; /* simple uniform scalar quantisers */ for(i=0; i<10; i++) { k = lsp_cb[i].k; m = lsp_cb[i].m; cb = lsp_cb[i].cb; index = quantise(cb, &lsp_hz[i], wt, k, m, &se); lsp_hz[i] = cb[index*k]; } /* experiment: simulating uniform quantisation error for(i=0; i<order; i++) lsp[i] += PI*(12.5/4000.0)*(1.0 - 2.0*(float)rand()/RAND_MAX); */ for(i=0; i<order; i++) lsp[i] = (PI/4000.0)*lsp_hz[i]; /* Bandwidth Expansion (BW). Prevents any two LSPs getting too close together after quantisation. We know from experiment that LSP quantisation errors < 12.5Hz (25Hz setp size) are inaudible so we use that as the minimum LSP separation. */ for(i=1; i<5; i++) { if (lsp[i] - lsp[i-1] < PI*(12.5/4000.0)) lsp[i] = lsp[i-1] + PI*(12.5/4000.0); } /* as quantiser gaps increased, larger BW expansion was required to prevent twinkly noises */ for(i=5; i<8; i++) { if (lsp[i] - lsp[i-1] < PI*(25.0/4000.0)) lsp[i] = lsp[i-1] + PI*(25.0/4000.0); } for(i=8; i<order; i++) { if (lsp[i] - lsp[i-1] < PI*(75.0/4000.0)) lsp[i] = lsp[i-1] + PI*(75.0/4000.0); } for(j=0; j<order; j++) lsp_[j] = lsp[j]; lsp_to_lpc(lsp_, ak, order); #ifdef DUMP dump_lsp(lsp); #endif } #ifdef DUMP dump_E(E); #endif #ifdef SIM_QUANT /* simulated LPC energy quantisation */ { float e = 10.0*log10(E); e += 2.0*(1.0 - 2.0*(float)rand()/RAND_MAX); E = pow(10.0,e/10.0); } #endif aks_to_M2(ak,order,model,E,&snr, 1); /* {ak} -> {Am} LPC decode */ return snr; }
void lspdvq_quantise( float lsp[], float lsp_[], int order ) { int i,k,m,ncb, nlsp; float dlsp[LPC_MAX]; float dlsp_[LPC_MAX]; float wt[LPC_ORD]; const float *cb; float se; int index; dlsp[0] = lsp[0]; for(i=1; i<order; i++) dlsp[i] = lsp[i] - lsp[i-1]; for(i=0; i<order; i++) dlsp_[i] = dlsp[i]; for(i=0; i<order; i++) wt[i] = 1.0; /* scalar quantise dLSPs 1,2,3,4,5 */ for(i=0; i<5; i++) { if (i) dlsp[i] = (lsp[i] - lsp_[i-1])*4000.0/PI; else dlsp[0] = lsp[0]*4000.0/PI; k = lsp_cbdvq[i].k; m = lsp_cbdvq[i].m; cb = lsp_cbdvq[i].cb; index = quantise(cb, &dlsp[i], wt, k, m, &se); dlsp_[i] = cb[index*k]*PI/4000.0; if (i) lsp_[i] = lsp_[i-1] + dlsp_[i]; else lsp_[0] = dlsp_[0]; } dlsp[i] = lsp[i] - lsp_[i-1]; dlsp_[i] = dlsp[i]; //printf("lsp[0] %f lsp_[0] %f\n", lsp[0], lsp_[0]); //printf("lsp[1] %f lsp_[1] %f\n", lsp[1], lsp_[1]); #ifdef TT /* VQ dLSPs 3,4,5 */ ncb = 2; nlsp = 2; k = lsp_cbdvq[ncb].k; m = lsp_cbdvq[ncb].m; cb = lsp_cbdvq[ncb].cb; index = quantise(cb, &dlsp[nlsp], wt, k, m, &se); dlsp_[nlsp] = cb[index*k]; dlsp_[nlsp+1] = cb[index*k+1]; dlsp_[nlsp+2] = cb[index*k+2]; lsp_[0] = dlsp_[0]; for(i=1; i<5; i++) lsp_[i] = lsp_[i-1] + dlsp_[i]; dlsp[i] = lsp[i] - lsp_[i-1]; dlsp_[i] = dlsp[i]; #endif /* VQ dLSPs 6,7,8,9,10 */ ncb = 5; nlsp = 5; k = lsp_cbdvq[ncb].k; m = lsp_cbdvq[ncb].m; cb = lsp_cbdvq[ncb].cb; index = quantise(cb, &dlsp[nlsp], wt, k, m, &se); dlsp_[nlsp] = cb[index*k]; dlsp_[nlsp+1] = cb[index*k+1]; dlsp_[nlsp+2] = cb[index*k+2]; dlsp_[nlsp+3] = cb[index*k+3]; dlsp_[nlsp+4] = cb[index*k+4]; /* rebuild LSPs for dLSPs */ lsp_[0] = dlsp_[0]; for(i=1; i<order; i++) lsp_[i] = lsp_[i-1] + dlsp_[i]; }