From 59205c76783b47c9980ab7a805d637e3c56bab6c Mon Sep 17 00:00:00 2001 From: Brian West <brian@freeswitch.org> Date: Thu, 20 Dec 2012 20:15:24 -0600 Subject: [PATCH] sigh... git you failed --- libs/libcodec2/unittest/vqtrainjnd.c | 254 +++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 libs/libcodec2/unittest/vqtrainjnd.c diff --git a/libs/libcodec2/unittest/vqtrainjnd.c b/libs/libcodec2/unittest/vqtrainjnd.c new file mode 100644 index 0000000000..f0fb18a329 --- /dev/null +++ b/libs/libcodec2/unittest/vqtrainjnd.c @@ -0,0 +1,254 @@ +/*--------------------------------------------------------------------------*\ + + FILE........: vqtrainjnd.c + AUTHOR......: David Rowe + DATE CREATED: 10 Nov 2011 + + This program trains vector quantisers for LSPs using an + experimental, but very simple Just Noticable Difference (JND) + algorithm: + + - we quantise each training vector to JND steps (say 100Hz for LSPs + 5-10) + - we then use the most popular training vectors as our VQ codebook + +\*--------------------------------------------------------------------------*/ + +/* + Copyright (C) 2011 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, 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/>. +*/ + +/*-----------------------------------------------------------------------*\ + + INCLUDES + +\*-----------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ctype.h> + +/*-----------------------------------------------------------------------*\ + + DEFINES + +\*-----------------------------------------------------------------------*/ + +#define PI 3.141592654 /* mathematical constant */ +#define MAX_POP 10 + +/*-----------------------------------------------------------------------*\ + + FUNCTION PROTOTYPES + +\*-----------------------------------------------------------------------*/ + +void zero(float v[], int k); +void acc(float v1[], float v2[], int k); +void norm(float v[], int k, long n); +void locate_lsps_jnd_steps(float lsps[], float step, int k); + +/*-----------------------------------------------------------------------* \ + + MAIN + +\*-----------------------------------------------------------------------*/ + +int main(int argc, char *argv[]) { + int k; /* dimension and codebook size */ + float *vec; /* current vector */ + int *n; /* number of vectors in this interval */ + int J; /* number of vectors in training set */ + int i,j; + FILE *ftrain; /* file containing training set */ + float *train; /* training database */ + //float *pend_train; /* last entry */ + float *pt; + int ntrain, match, vec_exists, vec_index=0, entry; + int popular[MAX_POP], pop_thresh; + FILE *fvq; + float jnd; + + /* Interpret command line arguments */ + + if (argc != 6) { + printf("usage: %s TrainFile K(dimension) JND popThresh VQFile\n", + argv[0]); + exit(1); + } + + /* 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]); + jnd = atof(argv[3]); + pop_thresh = atol(argv[4]); + printf("dimension K=%d popThresh=%d JND=%3.1f Hz\n", + k, pop_thresh, jnd); + vec = (float*)malloc(sizeof(float)*k); + if (vec == NULL) { + printf("Error in malloc.\n"); + exit(1); + } + + /* determine size of training set */ + + J = 0; + while(fread(vec, sizeof(float), k, ftrain) == (size_t)k) + J++; + printf("J=%d entries in training set\n", J); + train = (float*)malloc(sizeof(float)*k*J); + if (train == NULL) { + printf("Error in malloc.\n"); + exit(1); + } + printf("training array is %d bytes\n", sizeof(float)*k*J); + + n = (int*)malloc(sizeof(int)*J); + if (n == NULL) { + printf("Error in malloc.\n"); + exit(1); + } + for(i=0; i<J; i++) + n[i] = 0; + + /* now load up train data base and quantise */ + + rewind(ftrain); + ntrain = 0; + entry = 0; + while(fread(vec, sizeof(float), k, ftrain) == (size_t)k) { + + /* convert to Hz */ + + for(j=0; j<k; j++) + vec[j] *= 4000.0/PI; + + /* quantise to JND steps */ + + locate_lsps_jnd_steps(vec, jnd, k); + + /* see if a match already exists in database */ + + pt = train; + vec_exists = 0; + for(i=0; i<ntrain; i++) { + match = 1; + for(j=0; j<k; j++) + if (vec[j] != pt[j]) + match = 0; + if (match) { + vec_exists = 1; + vec_index = i; + } + pt += k; + } + + if (vec_exists) + n[vec_index]++; + else { + /* add to database */ + + for(j=0; j<k; j++) { + train[ntrain*k + j] = vec[j]; + } + ntrain++; + + } + entry++; + if ((entry % 100) == 0) + printf("\rtrain input vectors: %d unique vectors: %d", + entry, ntrain); + } + printf("\n"); + + for(i=0; i<MAX_POP; i++) + popular[i] = 0; + for(i=0; i<ntrain; i++) { + if (n[i] < MAX_POP) + popular[n[i]]++; + } + + for(i=0; i<MAX_POP; i++) + printf("popular[%d] = %d\n", i, popular[i]); + + /* dump result */ + + fvq = fopen(argv[5],"wt"); + if (fvq == NULL) { + printf("Error opening VQ file: %s\n",argv[4]); + exit(1); + } + + fprintf(fvq,"%d %d\n", k, popular[pop_thresh]); + for(i=0; i<ntrain; i++) { + if (n[i] > pop_thresh) { + for(j=0; j<k; j++) + fprintf(fvq, "%4.1f ",train[i*k+j]); + fprintf(fvq,"\n"); + } + } + fclose(fvq); + + return 0; +} + +/*-----------------------------------------------------------------------*\ + + FUNCTIONS + +\*-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: locate_lsps_jnd_steps() + AUTHOR......: David Rowe + DATE CREATED: 27/10/2011 + + Applies a form of Bandwidth Expansion (BW) to a vector of LSPs. + Listening tests have determined that "quantising" the position of + each LSP (say to 100Hz steps for LSPs 5..10) introduces a "just + noticable difference" in the synthesised speech. + + This operation can be used before quantisation to limit the input + data to the quantiser to a number of discrete steps. + +\*---------------------------------------------------------------------------*/ + +void locate_lsps_jnd_steps(float lsps[], float step, int k) +{ + int i; + + for(i=0; i<k; i++) { + lsps[i] = floor(lsps[i]/step + 0.5)*step; + if (i) { + if (lsps[i] == lsps[i-1]) + lsps[i] += step; + + } + } + +} +