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_inverse_linear.c 00040 * 00041 * Description: 00042 * Warp the frequency axis according to an inverse_linear function, i.e.: 00043 * 00044 * w' = w / a 00045 * 00046 *********************************************************************/ 00047 00048 /* static char rcsid[] = "@(#)$Id: fe_warp_inverse_linear.c,v 1.3 2006/02/23 19:40:11 eht Exp $"; */ 00049 00050 #include <stdio.h> 00051 #include <stdlib.h> 00052 #include <math.h> 00053 #include <string.h> 00054 00055 #ifdef _MSC_VER 00056 #pragma warning (disable: 4996) 00057 #endif 00058 00059 #include "sphinxbase/strfuncs.h" 00060 #include "sphinxbase/err.h" 00061 00062 #include "fe_warp.h" 00063 #include "fe_warp_inverse_linear.h" 00064 00065 #define N_PARAM 1 00066 #define YES 1 00067 #define NO 0 00068 00069 /* 00070 * params[0] : a 00071 */ 00072 static float params[N_PARAM] = { 1.0f }; 00073 static int32 is_neutral = YES; 00074 static char p_str[256] = ""; 00075 static float nyquist_frequency = 0.0f; 00076 00077 00078 const char * 00079 fe_warp_inverse_linear_doc() 00080 { 00081 return "inverse_linear :== < w' = x / a >"; 00082 } 00083 00084 uint32 00085 fe_warp_inverse_linear_id() 00086 { 00087 return FE_WARP_ID_INVERSE_LINEAR; 00088 } 00089 00090 uint32 00091 fe_warp_inverse_linear_n_param() 00092 { 00093 return N_PARAM; 00094 } 00095 00096 void 00097 fe_warp_inverse_linear_set_parameters(char const *param_str, float sampling_rate) 00098 { 00099 char *tok; 00100 char *seps = " \t"; 00101 char temp_param_str[256]; 00102 int param_index = 0; 00103 00104 nyquist_frequency = sampling_rate / 2; 00105 if (param_str == NULL) { 00106 is_neutral = YES; 00107 return; 00108 } 00109 /* The new parameters are the same as the current ones, so do nothing. */ 00110 if (strcmp(param_str, p_str) == 0) { 00111 return; 00112 } 00113 is_neutral = NO; 00114 strcpy(temp_param_str, param_str); 00115 memset(params, 0, N_PARAM * sizeof(float)); 00116 strcpy(p_str, param_str); 00117 /* FIXME: strtok() is not re-entrant... */ 00118 tok = strtok(temp_param_str, seps); 00119 while (tok != NULL) { 00120 params[param_index++] = (float) atof_c(tok); 00121 tok = strtok(NULL, seps); 00122 if (param_index >= N_PARAM) { 00123 break; 00124 } 00125 } 00126 if (tok != NULL) { 00127 E_INFO 00128 ("Inverse linear warping takes only one argument, %s ignored.\n", 00129 tok); 00130 } 00131 if (params[0] == 0) { 00132 is_neutral = YES; 00133 E_INFO 00134 ("Inverse linear warping cannot have slope zero, warping not applied.\n"); 00135 } 00136 } 00137 00138 float 00139 fe_warp_inverse_linear_warped_to_unwarped(float nonlinear) 00140 { 00141 if (is_neutral) { 00142 return nonlinear; 00143 } 00144 else { 00145 /* linear = nonlinear * a */ 00146 float temp = nonlinear * params[0]; 00147 if (temp > nyquist_frequency) { 00148 E_WARN 00149 ("Warp factor %g results in frequency (%.1f) higher than Nyquist (%.1f)\n", 00150 params[0], temp, nyquist_frequency); 00151 } 00152 return temp; 00153 } 00154 } 00155 00156 float 00157 fe_warp_inverse_linear_unwarped_to_warped(float linear) 00158 { 00159 if (is_neutral) { 00160 return linear; 00161 } 00162 else { 00163 /* nonlinear = a / linear */ 00164 float temp = linear / params[0]; 00165 return temp; 00166 } 00167 } 00168 00169 void 00170 fe_warp_inverse_linear_print(const char *label) 00171 { 00172 uint32 i; 00173 00174 for (i = 0; i < N_PARAM; i++) { 00175 printf("%s[%04u]: %6.3f ", label, i, params[i]); 00176 } 00177 printf("\n"); 00178 } 00179 00180 /* 00181 * Log record. Maintained by RCS. 00182 * 00183 * $Log: fe_warp_inverse_linear.c,v $ 00184 * Revision 1.3 2006/02/23 19:40:11 eht 00185 * corrected the doc string for the inverse linear warp function. 00186 * 00187 * Revision 1.2 2006/02/17 00:31:34 egouvea 00188 * Removed switch -melwarp. Changed the default for window length to 00189 * 0.025625 from 0.256 (so that a window at 16kHz sampling rate has 00190 * exactly 410 samples). Cleaned up include's. Replaced some E_FATAL() 00191 * with E_WARN() and return. 00192 * 00193 * Revision 1.1 2006/02/16 00:18:26 egouvea 00194 * Implemented flexible warping function. The user can specify at run 00195 * time which of several shapes they want to use. Currently implemented 00196 * are an affine function (y = ax + b), an inverse linear (y = a/x) and a 00197 * piecewise linear (y = ax, up to a frequency F, and then it "breaks" so 00198 * Nyquist frequency matches in both scales. 00199 * 00200 * Added two switches, -warp_type and -warp_params. The first specifies 00201 * the type, which valid values: 00202 * 00203 * -inverse or inverse_linear 00204 * -linear or affine 00205 * -piecewise or piecewise_linear 00206 * 00207 * The inverse_linear is the same as implemented by EHT. The -mel_warp 00208 * switch was kept for compatibility (maybe remove it in the 00209 * future?). The code is compatible with EHT's changes: cepstra created 00210 * from code after his changes should be the same as now. Scripts that 00211 * worked with his changes should work now without changes. Tested a few 00212 * cases, same results. 00213 * 00214 */