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