aboutsummaryrefslogtreecommitdiff
path: root/misc/tquant.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/tquant.c')
-rw-r--r--misc/tquant.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/misc/tquant.c b/misc/tquant.c
new file mode 100644
index 0000000..2492123
--- /dev/null
+++ b/misc/tquant.c
@@ -0,0 +1,214 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: tquant.c
+ AUTHOR......: David Rowe
+ DATE CREATED: 22/8/10
+
+ Generates quantisation curves for plotting on Octave.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2010 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "defines.h"
+#include "dump.h"
+#include "quantise.h"
+
+int test_Wo_quant();
+int test_lsp_quant();
+int test_lsp(int lsp_number, int levels, float max_error_hz);
+int test_energy_quant(int levels, float max_error_dB);
+
+int main() {
+ quantise_init();
+ test_Wo_quant();
+ test_lsp_quant();
+ test_energy_quant(E_LEVELS, 0.5*(E_MAX_DB - E_MIN_DB)/E_LEVELS);
+
+ return 0;
+}
+
+int test_lsp_quant() {
+ test_lsp( 1, 16, 12.5);
+ test_lsp( 2, 16, 12.5);
+ test_lsp( 3, 16, 25);
+ test_lsp( 4, 16, 50);
+ test_lsp( 5, 16, 50);
+ test_lsp( 6, 16, 50);
+ test_lsp( 7, 16, 50);
+ test_lsp( 8, 8, 50);
+ test_lsp( 9, 8, 50);
+ test_lsp(10, 4, 100);
+
+ return 0;
+}
+
+int test_energy_quant(int levels, float max_error_dB) {
+ FILE *fe;
+ float e,e_dec, error, low_e, high_e;
+ int index, index_in, index_out, i;
+
+ /* check 1:1 match between input and output levels */
+
+ for(i=0; i<levels; i++) {
+ index_in = i;
+ e = decode_energy(index_in, E_BITS);
+ index_out = encode_energy(e, E_BITS);
+ if (index_in != index_out) {
+ printf("edB: %f index_in: %d index_out: %d\n",
+ 10.0*log10(e), index_in, index_out);
+ exit(0);
+ }
+ }
+
+ /* check error over range of quantiser */
+
+ low_e = decode_energy(0, E_BITS);
+ high_e = decode_energy(levels-1, E_BITS);
+ fe = fopen("energy_err.txt", "wt");
+
+ for(e=low_e; e<high_e; e +=(high_e-low_e)/1000.0) {
+ index = encode_energy(e, E_BITS);
+ e_dec = decode_energy(index, E_BITS);
+ error = 10.0*log10(e) - 10.0*log10(e_dec);
+ fprintf(fe, "%f\n", error);
+ if (fabs(error) > max_error_dB) {
+ printf("error: %f %f\n", error, max_error_dB);
+ exit(0);
+ }
+ }
+
+ fclose(fe);
+ return 0;
+}
+
+int test_lsp(int lsp_number, int levels, float max_error_hz) {
+ float lsp[LPC_ORD];
+ int indexes_in[LPC_ORD];
+ int indexes_out[LPC_ORD];
+ int indexes[LPC_ORD];
+ int i;
+ float lowf, highf, f, error;
+ char s[MAX_STR];
+ FILE *flsp;
+ float max_error_rads;
+
+ lsp_number--;
+ max_error_rads = max_error_hz*TWO_PI/FS;
+
+ for(i=0; i<LPC_ORD; i++)
+ indexes_in[i] = 0;
+
+ for(i=0; i<levels; i++) {
+ indexes_in[lsp_number] = i;
+ decode_lsps_scalar(lsp, indexes_in, LPC_ORD);
+ encode_lsps_scalar(indexes_out, lsp,LPC_ORD);
+ if (indexes_in[lsp_number] != indexes_out[lsp_number]) {
+ printf("freq: %f index_in: %d index_out: %d\n",
+ lsp[lsp_number]+1, indexes_in[lsp_number],
+ indexes_out[lsp_number]);
+ exit(0);
+ }
+ }
+
+ for(i=0; i<LPC_ORD; i++)
+ indexes[i] = 0;
+ indexes[lsp_number] = 0;
+ decode_lsps_scalar(lsp, indexes, LPC_ORD);
+ lowf = lsp[lsp_number];
+ indexes[lsp_number] = levels - 1;
+ decode_lsps_scalar(lsp, indexes, LPC_ORD);
+ highf = lsp[lsp_number];
+ sprintf(s,"lsp%d_err.txt", lsp_number+1);
+ flsp = fopen(s, "wt");
+
+ for(f=lowf; f<highf; f +=(highf-lowf)/1000.0) {
+ lsp[lsp_number] = f;
+ encode_lsps_scalar(indexes, lsp, LPC_ORD);
+ decode_lsps_scalar(lsp, indexes, LPC_ORD);
+ error = f - lsp[lsp_number];
+ fprintf(flsp, "%f\n", error);
+ if (fabs(error) > max_error_rads) {
+ printf("%d error: %f %f\n", lsp_number+1, error, max_error_rads);
+ exit(0);
+ }
+ }
+
+ fclose(flsp);
+
+ printf("OK\n");
+
+ return 0;
+}
+
+int test_Wo_quant() {
+ int c;
+ FILE *f;
+ float Wo,Wo_dec, error, step_size;
+ int index, index_in, index_out;
+
+ /* output Wo quant curve for plotting */
+
+ f = fopen("quant_pitch.txt","wt");
+
+ for(Wo=0.9*(TWO_PI/P_MAX); Wo<=1.1*(TWO_PI/P_MIN); Wo += 0.001) {
+ index = encode_Wo(Wo, WO_BITS);
+ fprintf(f, "%f %d\n", Wo, index);
+ }
+
+ fclose(f);
+
+ /* check for all Wo codes we get 1:1 match between encoder
+ and decoder Wo levels */
+
+ for(c=0; c<WO_LEVELS; c++) {
+ index_in = c;
+ Wo = decode_Wo(index_in, WO_BITS);
+ index_out = encode_Wo(Wo, WO_BITS);
+ if (index_in != index_out)
+ printf(" Wo %f index_in %d index_out %d\n", Wo,
+ index_in, index_out);
+ }
+
+ /* measure quantisation error stats and compare to expected. Also
+ plot histogram of error file to check. */
+
+ f = fopen("quant_pitch_err.txt","wt");
+ step_size = ((TWO_PI/P_MIN) - (TWO_PI/P_MAX))/WO_LEVELS;
+
+ for(Wo=TWO_PI/P_MAX; Wo<0.99*TWO_PI/P_MIN; Wo += 0.0001) {
+ index = encode_Wo(Wo, WO_BITS);
+ Wo_dec = decode_Wo(index, WO_BITS);
+ error = Wo - Wo_dec;
+ if (fabs(error) > (step_size/2.0)) {
+ printf("error: %f step_size/2: %f\n", error, step_size/2.0);
+ exit(0);
+ }
+ fprintf(f,"%f\n",error);
+ }
+ printf("OK\n");
+
+ fclose(f);
+ return 0;
+}