Initial import to Tizen
[profile/ivi/sphinxbase.git] / src / libsphinxbase / fe / fe_warp.c
1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 2006 Carnegie Mellon University.  All rights 
4  * reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer. 
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * This work was supported in part by funding from the Defense Advanced 
19  * Research Projects Agency and the National Science Foundation of the 
20  * United States of America, and the CMU Sphinx Speech Consortium.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 
23  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * ====================================================================
35  *
36  */
37 /*********************************************************************
38  *
39  * File: fe_warp.c
40  * 
41  * Description: 
42  *      Allows a caller to choose a warping function.
43  *********************************************************************/
44
45 /* static char rcsid[] = "@(#)$Id: fe_warp.c,v 1.2 2006/02/17 00:31:34 egouvea Exp $";*/
46 \f
47 #include "fe_warp_inverse_linear.h"
48 #include "fe_warp_affine.h"
49 #include "fe_warp_piecewise_linear.h"
50 #include "fe_warp.h"
51
52 #include "sphinxbase/err.h"
53
54 #include <stdio.h>
55 #include <string.h>
56 #include <assert.h>
57 #include <stdlib.h>
58
59 /* This is for aliases for each of the entries below. Currently not
60    used.
61 */
62 static char *__name2id[] = {
63     "inverse",
64     "linear",
65     "piecewise",
66     NULL
67 };
68
69 static char *name2id[] = {
70     "inverse_linear",
71     "affine",
72     "piecewise_linear",
73     NULL
74 };
75 \f
76 static fe_warp_conf_t fe_warp_conf[FE_WARP_ID_MAX + 1] = {
77     {fe_warp_inverse_linear_set_parameters,
78      fe_warp_inverse_linear_doc,
79      fe_warp_inverse_linear_id,
80      fe_warp_inverse_linear_n_param,
81      fe_warp_inverse_linear_warped_to_unwarped,
82      fe_warp_inverse_linear_unwarped_to_warped,
83      fe_warp_inverse_linear_print},     /* Inverse linear warping */
84     {fe_warp_affine_set_parameters,
85      fe_warp_affine_doc,
86      fe_warp_affine_id,
87      fe_warp_affine_n_param,
88      fe_warp_affine_warped_to_unwarped,
89      fe_warp_affine_unwarped_to_warped,
90      fe_warp_affine_print},     /* Affine warping */
91     {fe_warp_piecewise_linear_set_parameters,
92      fe_warp_piecewise_linear_doc,
93      fe_warp_piecewise_linear_id,
94      fe_warp_piecewise_linear_n_param,
95      fe_warp_piecewise_linear_warped_to_unwarped,
96      fe_warp_piecewise_linear_unwarped_to_warped,
97      fe_warp_piecewise_linear_print},   /* Piecewise_Linear warping */
98 };
99
100 int
101 fe_warp_set(melfb_t *mel, const char *id_name)
102 {
103     uint32 i;
104
105     for (i = 0; name2id[i]; i++) {
106         if (strcmp(id_name, name2id[i]) == 0) {
107             mel->warp_id = i;
108             break;
109         }
110     }
111
112     if (name2id[i] == NULL) {
113         for (i = 0; __name2id[i]; i++) {
114             if (strcmp(id_name, __name2id[i]) == 0) {
115                 mel->warp_id = i;
116                 break;
117             }
118         }
119         if (__name2id[i] == NULL) {
120             E_ERROR("Unimplemented warping function %s\n", id_name);
121             E_ERROR("Implemented functions are:\n");
122             for (i = 0; name2id[i]; i++) {
123                 fprintf(stderr, "\t%s\n", name2id[i]);
124             }
125             mel->warp_id = FE_WARP_ID_NONE;
126
127             return FE_START_ERROR;
128         }
129     }
130
131     return FE_SUCCESS;
132 }
133 \f
134 void
135 fe_warp_set_parameters(melfb_t *mel, char const *param_str, float sampling_rate)
136 {
137     if (mel->warp_id <= FE_WARP_ID_MAX) {
138         fe_warp_conf[mel->warp_id].set_parameters(param_str, sampling_rate);
139     }
140     else if (mel->warp_id == FE_WARP_ID_NONE) {
141         E_FATAL("feat module must be configured w/ a valid ID\n");
142     }
143     else {
144         E_FATAL
145             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
146              mel->warp_id);
147     }
148 }
149 \f
150 const char *
151 fe_warp_doc(melfb_t *mel)
152 {
153     if (mel->warp_id <= FE_WARP_ID_MAX) {
154         return fe_warp_conf[mel->warp_id].doc();
155     }
156     else if (mel->warp_id == FE_WARP_ID_NONE) {
157         E_FATAL("fe_warp module must be configured w/ a valid ID\n");
158     }
159     else {
160         E_FATAL
161             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
162              mel->warp_id);
163     }
164
165     return NULL;
166 }
167 \f
168 uint32
169 fe_warp_id(melfb_t *mel)
170 {
171     if (mel->warp_id <= FE_WARP_ID_MAX) {
172         assert(mel->warp_id == fe_warp_conf[mel->warp_id].id());
173         return mel->warp_id;
174     }
175     else if (mel->warp_id != FE_WARP_ID_NONE) {
176         E_FATAL
177             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
178              mel->warp_id);
179     }
180
181     return FE_WARP_ID_NONE;
182 }
183 \f
184 uint32
185 fe_warp_n_param(melfb_t *mel)
186 {
187     if (mel->warp_id <= FE_WARP_ID_MAX) {
188         return fe_warp_conf[mel->warp_id].n_param();
189     }
190     else if (mel->warp_id == FE_WARP_ID_NONE) {
191         E_FATAL("fe_warp module must be configured w/ a valid ID\n");
192     }
193     else {
194         E_FATAL
195             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
196              mel->warp_id);
197     }
198
199     return 0;
200 }
201 \f
202 float
203 fe_warp_warped_to_unwarped(melfb_t *mel, float nonlinear)
204 {
205     if (mel->warp_id <= FE_WARP_ID_MAX) {
206         return fe_warp_conf[mel->warp_id].warped_to_unwarped(nonlinear);
207     }
208     else if (mel->warp_id == FE_WARP_ID_NONE) {
209         E_FATAL("fe_warp module must be configured w/ a valid ID\n");
210     }
211     else {
212         E_FATAL
213             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
214              mel->warp_id);
215     }
216
217     return 0;
218 }
219 \f
220 float
221 fe_warp_unwarped_to_warped(melfb_t *mel,float linear)
222 {
223     if (mel->warp_id <= FE_WARP_ID_MAX) {
224         return fe_warp_conf[mel->warp_id].unwarped_to_warped(linear);
225     }
226     else if (mel->warp_id == FE_WARP_ID_NONE) {
227         E_FATAL("fe_warp module must be configured w/ a valid ID\n");
228     }
229     else {
230         E_FATAL
231             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
232              mel->warp_id);
233     }
234
235     return 0;
236 }
237 \f
238 void
239 fe_warp_print(melfb_t *mel, const char *label)
240 {
241     if (mel->warp_id <= FE_WARP_ID_MAX) {
242         fe_warp_conf[mel->warp_id].print(label);
243     }
244     else if (mel->warp_id == FE_WARP_ID_NONE) {
245         E_FATAL("fe_warp module must be configured w/ a valid ID\n");
246     }
247     else {
248         E_FATAL
249             ("fe_warp module misconfigured with invalid fe_warp_id %u\n",
250              mel->warp_id);
251     }
252 }
253 \f
254 /*
255  * Log record.  Maintained by RCS.
256  *
257  * $Log: fe_warp.c,v $
258  * Revision 1.2  2006/02/17 00:31:34  egouvea
259  * Removed switch -melwarp. Changed the default for window length to
260  * 0.025625 from 0.256 (so that a window at 16kHz sampling rate has
261  * exactly 410 samples). Cleaned up include's. Replaced some E_FATAL()
262  * with E_WARN() and return.
263  *
264  * Revision 1.1  2006/02/16 00:18:26  egouvea
265  * Implemented flexible warping function. The user can specify at run
266  * time which of several shapes they want to use. Currently implemented
267  * are an affine function (y = ax + b), an inverse linear (y = a/x) and a
268  * piecewise linear (y = ax, up to a frequency F, and then it "breaks" so
269  * Nyquist frequency matches in both scales.
270  *
271  * Added two switches, -warp_type and -warp_params. The first specifies
272  * the type, which valid values:
273  *
274  * -inverse or inverse_linear
275  * -linear or affine
276  * -piecewise or piecewise_linear
277  *
278  * The inverse_linear is the same as implemented by EHT. The -mel_warp
279  * switch was kept for compatibility (maybe remove it in the
280  * future?). The code is compatible with EHT's changes: cepstra created
281  * from code after his changes should be the same as now. Scripts that
282  * worked with his changes should work now without changes. Tested a few
283  * cases, same results.
284  *
285  */