SphinxBase
0.6
|
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ 00002 /* ==================================================================== 00003 * Copyright (c) 2006 Carnegie Mellon University. All rights 00004 * reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * This work was supported in part by funding from the Defense Advanced 00019 * Research Projects Agency and the National Science Foundation of the 00020 * United States of America, and the CMU Sphinx Speech Consortium. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 00023 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00024 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00025 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 00026 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00030 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00032 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 * 00034 * ==================================================================== 00035 * 00036 */ 00037 /********************************************************************* 00038 * 00039 * File: fe_warp.c 00040 * 00041 * Description: 00042 * Allows a caller to choose a warping function. 00043 *********************************************************************/ 00044 00045 /* static char rcsid[] = "@(#)$Id: fe_warp.c,v 1.2 2006/02/17 00:31:34 egouvea Exp $";*/ 00046 00047 #include "fe_warp_inverse_linear.h" 00048 #include "fe_warp_affine.h" 00049 #include "fe_warp_piecewise_linear.h" 00050 #include "fe_warp.h" 00051 00052 #include "sphinxbase/err.h" 00053 00054 #include <stdio.h> 00055 #include <string.h> 00056 #include <assert.h> 00057 #include <stdlib.h> 00058 00059 /* This is for aliases for each of the entries below. Currently not 00060 used. 00061 */ 00062 static char *__name2id[] = { 00063 "inverse", 00064 "linear", 00065 "piecewise", 00066 NULL 00067 }; 00068 00069 static char *name2id[] = { 00070 "inverse_linear", 00071 "affine", 00072 "piecewise_linear", 00073 NULL 00074 }; 00075 00076 static fe_warp_conf_t fe_warp_conf[FE_WARP_ID_MAX + 1] = { 00077 {fe_warp_inverse_linear_set_parameters, 00078 fe_warp_inverse_linear_doc, 00079 fe_warp_inverse_linear_id, 00080 fe_warp_inverse_linear_n_param, 00081 fe_warp_inverse_linear_warped_to_unwarped, 00082 fe_warp_inverse_linear_unwarped_to_warped, 00083 fe_warp_inverse_linear_print}, /* Inverse linear warping */ 00084 {fe_warp_affine_set_parameters, 00085 fe_warp_affine_doc, 00086 fe_warp_affine_id, 00087 fe_warp_affine_n_param, 00088 fe_warp_affine_warped_to_unwarped, 00089 fe_warp_affine_unwarped_to_warped, 00090 fe_warp_affine_print}, /* Affine warping */ 00091 {fe_warp_piecewise_linear_set_parameters, 00092 fe_warp_piecewise_linear_doc, 00093 fe_warp_piecewise_linear_id, 00094 fe_warp_piecewise_linear_n_param, 00095 fe_warp_piecewise_linear_warped_to_unwarped, 00096 fe_warp_piecewise_linear_unwarped_to_warped, 00097 fe_warp_piecewise_linear_print}, /* Piecewise_Linear warping */ 00098 }; 00099 00100 int 00101 fe_warp_set(melfb_t *mel, const char *id_name) 00102 { 00103 uint32 i; 00104 00105 for (i = 0; name2id[i]; i++) { 00106 if (strcmp(id_name, name2id[i]) == 0) { 00107 mel->warp_id = i; 00108 break; 00109 } 00110 } 00111 00112 if (name2id[i] == NULL) { 00113 for (i = 0; __name2id[i]; i++) { 00114 if (strcmp(id_name, __name2id[i]) == 0) { 00115 mel->warp_id = i; 00116 break; 00117 } 00118 } 00119 if (__name2id[i] == NULL) { 00120 E_ERROR("Unimplemented warping function %s\n", id_name); 00121 E_ERROR("Implemented functions are:\n"); 00122 for (i = 0; name2id[i]; i++) { 00123 fprintf(stderr, "\t%s\n", name2id[i]); 00124 } 00125 mel->warp_id = FE_WARP_ID_NONE; 00126 00127 return FE_START_ERROR; 00128 } 00129 } 00130 00131 return FE_SUCCESS; 00132 } 00133 00134 void 00135 fe_warp_set_parameters(melfb_t *mel, char const *param_str, float sampling_rate) 00136 { 00137 if (mel->warp_id <= FE_WARP_ID_MAX) { 00138 fe_warp_conf[mel->warp_id].set_parameters(param_str, sampling_rate); 00139 } 00140 else if (mel->warp_id == FE_WARP_ID_NONE) { 00141 E_FATAL("feat module must be configured w/ a valid ID\n"); 00142 } 00143 else { 00144 E_FATAL 00145 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00146 mel->warp_id); 00147 } 00148 } 00149 00150 const char * 00151 fe_warp_doc(melfb_t *mel) 00152 { 00153 if (mel->warp_id <= FE_WARP_ID_MAX) { 00154 return fe_warp_conf[mel->warp_id].doc(); 00155 } 00156 else if (mel->warp_id == FE_WARP_ID_NONE) { 00157 E_FATAL("fe_warp module must be configured w/ a valid ID\n"); 00158 } 00159 else { 00160 E_FATAL 00161 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00162 mel->warp_id); 00163 } 00164 00165 return NULL; 00166 } 00167 00168 uint32 00169 fe_warp_id(melfb_t *mel) 00170 { 00171 if (mel->warp_id <= FE_WARP_ID_MAX) { 00172 assert(mel->warp_id == fe_warp_conf[mel->warp_id].id()); 00173 return mel->warp_id; 00174 } 00175 else if (mel->warp_id != FE_WARP_ID_NONE) { 00176 E_FATAL 00177 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00178 mel->warp_id); 00179 } 00180 00181 return FE_WARP_ID_NONE; 00182 } 00183 00184 uint32 00185 fe_warp_n_param(melfb_t *mel) 00186 { 00187 if (mel->warp_id <= FE_WARP_ID_MAX) { 00188 return fe_warp_conf[mel->warp_id].n_param(); 00189 } 00190 else if (mel->warp_id == FE_WARP_ID_NONE) { 00191 E_FATAL("fe_warp module must be configured w/ a valid ID\n"); 00192 } 00193 else { 00194 E_FATAL 00195 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00196 mel->warp_id); 00197 } 00198 00199 return 0; 00200 } 00201 00202 float 00203 fe_warp_warped_to_unwarped(melfb_t *mel, float nonlinear) 00204 { 00205 if (mel->warp_id <= FE_WARP_ID_MAX) { 00206 return fe_warp_conf[mel->warp_id].warped_to_unwarped(nonlinear); 00207 } 00208 else if (mel->warp_id == FE_WARP_ID_NONE) { 00209 E_FATAL("fe_warp module must be configured w/ a valid ID\n"); 00210 } 00211 else { 00212 E_FATAL 00213 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00214 mel->warp_id); 00215 } 00216 00217 return 0; 00218 } 00219 00220 float 00221 fe_warp_unwarped_to_warped(melfb_t *mel,float linear) 00222 { 00223 if (mel->warp_id <= FE_WARP_ID_MAX) { 00224 return fe_warp_conf[mel->warp_id].unwarped_to_warped(linear); 00225 } 00226 else if (mel->warp_id == FE_WARP_ID_NONE) { 00227 E_FATAL("fe_warp module must be configured w/ a valid ID\n"); 00228 } 00229 else { 00230 E_FATAL 00231 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00232 mel->warp_id); 00233 } 00234 00235 return 0; 00236 } 00237 00238 void 00239 fe_warp_print(melfb_t *mel, const char *label) 00240 { 00241 if (mel->warp_id <= FE_WARP_ID_MAX) { 00242 fe_warp_conf[mel->warp_id].print(label); 00243 } 00244 else if (mel->warp_id == FE_WARP_ID_NONE) { 00245 E_FATAL("fe_warp module must be configured w/ a valid ID\n"); 00246 } 00247 else { 00248 E_FATAL 00249 ("fe_warp module misconfigured with invalid fe_warp_id %u\n", 00250 mel->warp_id); 00251 } 00252 } 00253 00254 /* 00255 * Log record. Maintained by RCS. 00256 * 00257 * $Log: fe_warp.c,v $ 00258 * Revision 1.2 2006/02/17 00:31:34 egouvea 00259 * Removed switch -melwarp. Changed the default for window length to 00260 * 0.025625 from 0.256 (so that a window at 16kHz sampling rate has 00261 * exactly 410 samples). Cleaned up include's. Replaced some E_FATAL() 00262 * with E_WARN() and return. 00263 * 00264 * Revision 1.1 2006/02/16 00:18:26 egouvea 00265 * Implemented flexible warping function. The user can specify at run 00266 * time which of several shapes they want to use. Currently implemented 00267 * are an affine function (y = ax + b), an inverse linear (y = a/x) and a 00268 * piecewise linear (y = ax, up to a frequency F, and then it "breaks" so 00269 * Nyquist frequency matches in both scales. 00270 * 00271 * Added two switches, -warp_type and -warp_params. The first specifies 00272 * the type, which valid values: 00273 * 00274 * -inverse or inverse_linear 00275 * -linear or affine 00276 * -piecewise or piecewise_linear 00277 * 00278 * The inverse_linear is the same as implemented by EHT. The -mel_warp 00279 * switch was kept for compatibility (maybe remove it in the 00280 * future?). The code is compatible with EHT's changes: cepstra created 00281 * from code after his changes should be the same as now. Scripts that 00282 * worked with his changes should work now without changes. Tested a few 00283 * cases, same results. 00284 * 00285 */