123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /*--------------------------------------------------------------------------*\
- 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;
- }
- }
- }
|