codebook.c
2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "tabledesign.h"
void
split(double **codebook, double *dir, int order, int n_entries, double delta)
{
/*
* Double the size of the codebook by splitting each entry
* along the direction 'dir'
*/
int i, j;
for (i=0; i<n_entries; i++)
for (j=0; j<=order; j++)
codebook[i+n_entries][j] = codebook[i][j] + delta*dir[j];
}
void
refine(double **codebook, int order, int n_entries, double **training, int nframes,
int iterations, double converge)
{
/*
* Standard Lloyd algorithm for iterative refinement
* of the codebook
*/
int i, j, tv, iter, ne;
int *count;
double **centroids;
double *ac;
double e2, min, dist;
centroids = (double **) malloc(n_entries*sizeof(double *));
for (i=0; i<n_entries; i++)
centroids[i] = (double *) malloc((order+1)*sizeof(double));
count = (int *) malloc(n_entries*sizeof(int));
ac = (double *) malloc((order+1)*sizeof(double));
for (iter=0; iter<iterations; iter++){
/*
* Go through each training vector and find the nearest neighbour
*/
for (j=0; j<n_entries; j++){
count[j] = 0;
for (i=0; i<=order; i++)
centroids[j][i] = 0.0;
}
for (tv=0; tv<nframes; tv++){
ne = 0;
min = 1e30;
for (i=0; i<n_entries; i++){
dist = model_dist(codebook[i], training[tv], order);
if (dist<min){
min = dist;
ne = i;
}
}
/*
* Add the autocorrelation of this training vector to the centroid
*/
count[ne] += 1;
rfroma(training[tv], order, ac);
for (i=0; i<=order; i++)
centroids[ne][i] += ac[i];
}
/*
* Get the average
*/
for (i=0; i<n_entries; i++)
if (count[i]>0)
for (j=0; j<=order; j++)
centroids[i][j] = centroids[i][j]/count[i];
/*
* Redefine the codebook
*/
for (i=0; i<n_entries; i++){
durbin(centroids[i], order, ac, codebook[i], &e2);
/*
* Stabilize - could put this in durbin
*/
for (j=1; j<=order; j++){
if (ac[j]>=1.0)
ac[j] = 1.0 - TINY;
if (ac[j]<=-1.0)
ac[j] = -1.0 + TINY;
}
afromk(ac, codebook[i], order);
}
}
free(count);
for (i=0; i<n_entries; i++)
free(centroids[i]);
free(centroids);
free(ac);
}