AUTHOR......: David Rowe
DATE CREATED: 20/8/2010
- Codec2 simulation. Combines encoder and decoder and allows switching in
- out various algorithms and quantisation steps.
+ Codec2 simulation. Combines encoder and decoder and allows
+ switching in and out various algorithms and quantisation
+ steps. Primary program for algorithm developments.
\*---------------------------------------------------------------------------*/
float sum_snr;
int lpc_model, order = LPC_ORD;
- int lsp, lspd, lspvq, lsp_quantiser, lspres, lspdt;
+ int lsp, lspd, lspvq, lsp_quantiser, lspres, lspdt, lspdt_mode;
float ak[LPC_MAX];
COMP Sw_[FFT_ENC];
COMP Ew[FFT_ENC];
"\t[--lspvq]\n"
"\t[--lspres]\n"
"\t[--lspdt]\n"
+ "\t[--lspdt_mode all|high|low]\n"
"\t[--phase0]\n"
"\t[--postfilter]\n"
"\t[--hand_voicing]\n"
assert(order == LPC_ORD);
lspres = switch_present("--lspres",argc,argv);
+
lspdt = switch_present("--lspdt",argc,argv);
+ if ( (arg = switch_present("--lspdt_mode",argc,argv))) {
+ if (strcmp(argv[arg+1],"all") == 0)
+ lspdt_mode = LSPDT_ALL;
+ else if (strcmp(argv[arg+1],"low") == 0)
+ lspdt_mode = LSPDT_LOW;
+ else if (strcmp(argv[arg+1],"high") == 0)
+ lspdt_mode = LSPDT_HIGH;
+ else {
+ fprintf(stderr, "Error in lspdt_mode: %d\n", lspdt_mode);
+ exit(1);
+ }
+ }
+ else
+ lspdt_mode = LSPDT_ALL;
phase0 = switch_present("--phase0",argc,argv);
if (phase0) {
if (lspd) {
//locate_lsps_jnd_steps(lsps, LPC_ORD);
lspd_quantise(lsps, lsps_, LPC_ORD);
- locate_lsps_jnd_steps(lsps_, LPC_ORD);
+ bw_expand_lsps(lsps_, LPC_ORD);
lsp_to_lpc(lsps_, ak, LPC_ORD);
}
locate_lsps_jnd_steps(lsps_, LPC_ORD);
lsp_to_lpc(lsps_, ak, LPC_ORD);
}
+
+ /* we need lsp__prev[] for lspdt. If no other
+ LSP quantisation is used we use original LSPs
+ rather than quantised version. */
+
+ if (!lsp && !lspd && !lspvq && !lspres)
+ for(i=0; i<LPC_ORD; i++)
+ lsps_[i] = lsps[i];
+ /* Odd frames are generated by quantising the difference
+ between the previous frames LSPs and this frames */
+
if (lspdt && !decimate) {
if (frames%2) {
- lspdt_quantise(lsps, lsps_, lsps__prev);
+ lspdt_quantise(lsps, lsps_, lsps__prev, lspdt_mode);
bw_expand_lsps(lsps_, LPC_ORD);
lsp_to_lpc(lsps_, ak, LPC_ORD);
}
- for(i=0; i<LPC_ORD; i++) {
- lsps__prev[i] = lsps_[i];
- }
+ for(i=0; i<LPC_ORD; i++)
+ lsps__prev[i] = lsps_[i];
}
+ /*
+ When decimation is enabled we only send LSPs to the decoder
+ on odd frames. In this case we encode every second off
+ frame (i.e. every 3rd frame) by quantising the difference
+ between the 1st frames LSPs and this frames:
+
+ 10ms, frame 1: send "full" LSP frame
+ 20ms, frame 2: discard (interpolate at decoder)
+ 30ms, frame 3: send LSPs differences between frame 3 and frame 1
+ 40ms, frame 4: discard (interpolate at decoder)
+ */
+
if (lspdt && decimate) {
if ((frames%4) == 3) {
- lspdt_quantise(lsps, lsps_, lsps__prev2);
+ lspdt_quantise(lsps, lsps_, lsps__prev2, lspdt_mode);
bw_expand_lsps(lsps_, LPC_ORD);
lsp_to_lpc(lsps_, ak, LPC_ORD);
}
exit(0);
}
- /* odd frame - interpolate */
+ /*
+ Each 20ms we synthesise two 10ms frames:
+
+ frame 1: interpolate frame 0 LSPs from frame -1 and frame 1
+ synthesis frame 0 and frame 1 speech
+ frame 2: discard except for voicing bit
+ frame 3: interpolate frame 2 LSPs from frame 1 and frame 3
+ synthesis frame 2 and frame 3 speech
+ frame 4: discard except for voicing bit
+ */
if (frames%2) {
lspdt_quantise
- LSP difference in time quantiser.
+ LSP difference in time quantiser. Split VQ, encoding LSPs 1-4 with
+ one VQ, and LSPs 5-10 with a second. Update of previous lsp memory
+ is done outside of this function to handle dT between 10 or 20ms
+ frames.
+
+ mode action
+ ------------------
+
+ LSPDT_ALL VQ LSPs 1-4 and 5-10
+ LSPDT_LOW Just VQ LSPs 1-4, for LSPs 5-10 just copy previous
+ LSPDT_HIGH Just VQ LSPs 5-10, for LSPs 1-4 just copy previous
\*---------------------------------------------------------------------------*/
-void lspdt_quantise(float lsps[], float lsps_[], float lsps__prev[])
+void lspdt_quantise(float lsps[], float lsps_[], float lsps__prev[], int mode)
{
int i,k,m;
float wt[LPC_ORD];
for(i=0; i<LPC_ORD; i++) {
wt[i] = 1.0;
- lsps_[i] = lsps[i];
}
for(i=0; i<LPC_ORD; i++) {
lsps_dt[i] = (4000/PI)*(lsps[i] - lsps__prev[i]);
- // printf("%f ", lsps_dt[i]);
+ lsps_[i] = lsps__prev[i];
}
- //printf("\n");
- k = lsp_cbdt[0].k;
- m = lsp_cbdt[0].m;
- cb = lsp_cbdt[0].cb;
- //printf("k %d m %d cb[0]\n", k, m, cb[0]);
- index = quantise(cb, lsps_dt, wt, k, m, &se);
- //printf("index %d\n", index);
- for(i=0; i<4; i++) {
- lsps_[i] = lsps__prev[i] + (PI/4000.0)*cb[index*k + i];
- }
+ /* VQ LSP dTs 1 to 4 */
- k = lsp_cbdt[1].k;
- m = lsp_cbdt[1].m;
- cb = lsp_cbdt[1].cb;
- index = quantise(cb, &lsps_dt[4], wt, k, m, &se);
- //printf("index %d\n", index);
- for(i=4; i<10; i++) {
- //printf("%f ", cb[index*k + i - 4]);
- lsps_[i] = lsps__prev[i] + (PI/4000.0)*cb[index*k + i - 4];
+ if (mode != LSPDT_HIGH) {
+ 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<4; i++) {
+ lsps_[i] += (PI/4000.0)*cb[index*k + i];
+ }
}
- //printf("\n");
+ /* VQ LSP dTs 6 to 10 */
+
+ if (mode != LSPDT_LOW) {
+ k = lsp_cbdt[1].k;
+ m = lsp_cbdt[1].m;
+ cb = lsp_cbdt[1].cb;
+ index = quantise(cb, &lsps_dt[4], wt, k, m, &se);
+ for(i=4; i<10; i++) {
+ lsps_[i] += (PI/4000.0)*cb[index*k + i - 4];
+ }
+ }
}
void check_lsp_order(float lsp[], int lpc_order)
roots = lpc_to_lsp(ak, order, lsp, 5, LSP_DELTA1);
if (roots != order) {
- /* for some reason LSP roots could not be found */
- /* some alpha testers are reporting this condition */
- fprintf(stderr, "LSP roots not found!\nroots = %d\n", roots);
- for(i=0; i<=order; i++)
- fprintf(stderr, "a[%d] = %f\n", i, ak[i]);
-
- /* some benign LSP values we can use instead */
+ /* use some benign LSP values we can use instead */
for(i=0; i<order; i++)
lsp[i] = (PI/order)*(float)i;
}