1 /* ====================================================================
2 * Copyright (c) 1995-2004 Carnegie Mellon University. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * This work was supported in part by funding from the Defense Advanced
18 * Research Projects Agency and the National Science Foundation of the
19 * United States of America, and the CMU Sphinx Speech Consortium.
20 *
21 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
22 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
25 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * ====================================================================
34 *
35 */
36 /*
37 * mllr.c -- Application of MLLR regression matrices to codebook means
38 *
39 * **********************************************
40 * CMU ARPA Speech Project
41 *
42 * Copyright (c) 1996 Carnegie Mellon University.
43 * ALL RIGHTS RESERVED.
44 * **********************************************
45 *
46 * HISTORY
47 * $Log$
48 * Revision 1.4 2005/06/21 18:50:45 arthchan2003
49 * Log. 1, Fixed doxygen documentation, 2, Added $Log$ keyword.
50 *
51 * Revision 1.4 2005/06/19 19:41:21 archan
52 * Sphinx3 to s3.generic: Added multiple regression class for single stream MLLR. Enabled MLLR for livepretend and decode.
53 *
54 * Revision 1.3 2005/03/30 01:22:47 archan
55 * Fixed mistakes in last updates. Add
56 *
57 *
58 * 24-Jul-04 ARCHAN (archan@cs.cmu.edu) at Carnegie Mellon University
59 * First checked in from sphinx 3.0 to sphinx 3.5
60 *
61 * 02-Dec-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
62 * Added reading of MLLR classes in transformation file. Currently must
63 * be 1.
64 *
65 * 26-Sep-96 M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
66 * Started (copied from Vipul Parikh's implementation).
67 */
68
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <string.h>
72 #include <assert.h>
73
74 #include "mllr.h"
75
76 void
mllr_dump(float32 *** A,float32 ** B,int32 veclen,int32 nclass)77 mllr_dump(float32 *** A, float32 ** B, int32 veclen, int32 nclass)
78 {
79 int32 i, j, k;
80 char *tmpstr;
81 assert(A != NULL);
82 assert(B != NULL);
83
84 tmpstr = ckd_calloc((veclen * 20), sizeof(char));
85
86 for (i = 0; i < nclass; i++) {
87 E_INFO("%d:\n", i);
88 for (j = 0; j < veclen; j++) {
89 sprintf(tmpstr, "A %d ", j);
90 for (k = 0; k < veclen; k++) {
91 sprintf(tmpstr, "%s %f ", tmpstr, A[i][j][k]);
92 }
93 sprintf(tmpstr, "%s\n", tmpstr);
94 E_INFO("%s\n", tmpstr);
95 }
96
97 sprintf(tmpstr, "B\n");
98 for (j = 0; j < veclen; j++) {
99 sprintf(tmpstr, "%s %f ", tmpstr, B[i][j]);
100 }
101 sprintf(tmpstr, "%s \n", tmpstr);
102 E_INFO("%s\n", tmpstr);
103 }
104
105 ckd_free(tmpstr);
106 }
107
108 int32
mllr_read_regmat(const char * regmatfile,float32 **** A,float32 *** B,int32 * nclass,int32 ceplen)109 mllr_read_regmat(const char *regmatfile,
110 float32 **** A,
111 float32 *** B, int32 * nclass, int32 ceplen)
112 {
113 int32 i, j, k, n, lnclass;
114 FILE *fp;
115 float32 ***lA, **lB;
116
117 if ((fp = fopen(regmatfile, "r")) == NULL) {
118 E_ERROR("fopen(%s,r) failed\n", regmatfile);
119 return -1;
120 }
121 else
122 E_INFO("Reading MLLR transformation file %s\n", regmatfile);
123
124 lA = NULL;
125 lB = NULL;
126
127 if ((fscanf(fp, "%d", &n) != 1) || (n < 1))
128 goto readerror;
129 lnclass = n;
130
131 /* The number of stream must be 1 for now (archan@cs.cmu.edu 24-Jul-2004) */
132 if ((fscanf(fp, "%d", &n) != 1) || (n != 1))
133 goto readerror;
134
135 lA = (float32 ***) ckd_calloc_3d(lnclass, ceplen, ceplen,
136 sizeof(float32));
137 lB = (float32 **) ckd_calloc_2d(lnclass, ceplen, sizeof(float32));
138
139 for (i = 0; i < lnclass; i++) {
140 /* We definitely do not allow different classes to have different
141 feature vector lengths! (that would be silly) */
142 if ((fscanf(fp, "%d", &n) != 1) || (ceplen != n))
143 goto readerror;
144 for (j = 0; j < ceplen; j++) {
145 for (k = 0; k < ceplen; ++k) {
146 if (fscanf(fp, "%f ", &lA[i][j][k]) != 1)
147 goto readerror;
148 }
149 }
150 for (j = 0; j < ceplen; j++) {
151 if (fscanf(fp, "%f ", &lB[i][j]) != 1)
152 goto readerror;
153 }
154 }
155
156 *A = lA;
157 *B = lB;
158 if (nclass)
159 *nclass = lnclass;
160
161 fclose(fp);
162
163 return 0;
164
165 readerror:
166 E_ERROR("Error reading MLLR file %s\n", regmatfile);
167 ckd_free_3d((void ***) lA);
168 ckd_free_2d((void **) lB);
169
170 fclose(fp);
171
172 *A = NULL;
173 *B = NULL;
174
175 return -1;
176 }
177
178
179 int32
mllr_free_regmat(float32 *** A,float32 ** B)180 mllr_free_regmat(float32 *** A, float32 ** B)
181 {
182 ckd_free_3d((void ***) A);
183 ckd_free_2d((void **) B);
184 return 0;
185 }
186
187
188
189 int32
mllr_norm_mgau(mgau_model_t * mgauset,float32 *** A,float32 ** B,int32 nclass,int32 * cb2mllr)190 mllr_norm_mgau(mgau_model_t * mgauset,
191 float32 *** A, float32 ** B, int32 nclass, int32 * cb2mllr)
192 {
193 int32 d, c, l, m;
194 int32 class;
195 float32 *temp;
196
197 int32 n_density = mgauset->n_mgau;
198 int32 n_mix = mgauset->max_comp;
199 int32 ceplen = mgauset->veclen;
200 mgau_t *mgau;
201
202 /* Transform codebook for each stream s */
203 temp = (float32 *) ckd_calloc(ceplen, sizeof(float32));
204
205 /* Transform each density d in selected codebook */
206 mgau = mgauset->mgau;
207
208 for (d = 0; d < n_density; d++) {
209 if (cb2mllr)
210 class = cb2mllr[d];
211 else
212 class = 0;
213 if (class == -1)
214 continue;
215
216 for (c = 0; c < n_mix; c++) {
217 for (l = 0; l < ceplen; l++) {
218 temp[l] = 0.0;
219 for (m = 0; m < ceplen; m++) {
220 temp[l] += A[class][l][m] * mgau[d].mean[c][m];
221 }
222 temp[l] += B[class][l];
223 }
224
225 for (l = 0; l < ceplen; l++) {
226 mgau[d].mean[c][l] = temp[l];
227 }
228 }
229 }
230
231 ckd_free(temp);
232
233 return 0;
234 }
235