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_affine.c 00040 * 00041 * Description: 00042 * Warp the frequency axis according to an affine function, i.e.: 00043 * 00044 * w' = a * w + b 00045 * 00046 *********************************************************************/ 00047 00048 /* static char rcsid[] = "@(#)$Id: fe_warp_affine.c,v 1.2 2006/02/17 00:31:34 egouvea 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_affine.h" 00064 00065 #define N_PARAM 2 00066 #define YES 1 00067 #define NO 0 00068 00069 /* 00070 * params[0] : a 00071 * params[1] : b 00072 */ 00073 static float params[N_PARAM] = { 1.0f, 0.0f }; 00074 static int32 is_neutral = YES; 00075 static char p_str[256] = ""; 00076 static float nyquist_frequency = 0.0f; 00077 00078 00079 const char * 00080 fe_warp_affine_doc() 00081 { 00082 return "affine :== < w' = a * x + b >"; 00083 } 00084 00085 uint32 00086 fe_warp_affine_id() 00087 { 00088 return FE_WARP_ID_AFFINE; 00089 } 00090 00091 uint32 00092 fe_warp_affine_n_param() 00093 { 00094 return N_PARAM; 00095 } 00096 00097 void 00098 fe_warp_affine_set_parameters(char const *param_str, float sampling_rate) 00099 { 00100 char *tok; 00101 char *seps = " \t"; 00102 char temp_param_str[256]; 00103 int param_index = 0; 00104 00105 nyquist_frequency = sampling_rate / 2; 00106 if (param_str == NULL) { 00107 is_neutral = YES; 00108 return; 00109 } 00110 /* The new parameters are the same as the current ones, so do nothing. */ 00111 if (strcmp(param_str, p_str) == 0) { 00112 return; 00113 } 00114 is_neutral = NO; 00115 strcpy(temp_param_str, param_str); 00116 memset(params, 0, N_PARAM * sizeof(float)); 00117 strcpy(p_str, param_str); 00118 /* FIXME: strtok() is not re-entrant... */ 00119 tok = strtok(temp_param_str, seps); 00120 while (tok != NULL) { 00121 params[param_index++] = (float) atof_c(tok); 00122 tok = strtok(NULL, seps); 00123 if (param_index >= N_PARAM) { 00124 break; 00125 } 00126 } 00127 if (tok != NULL) { 00128 E_INFO 00129 ("Affine warping takes up to two arguments, %s ignored.\n", 00130 tok); 00131 } 00132 if (params[0] == 0) { 00133 is_neutral = YES; 00134 E_INFO 00135 ("Affine warping cannot have slope zero, warping not applied.\n"); 00136 } 00137 } 00138 00139 float 00140 fe_warp_affine_warped_to_unwarped(float nonlinear) 00141 { 00142 if (is_neutral) { 00143 return nonlinear; 00144 } 00145 else { 00146 /* linear = (nonlinear - b) / a */ 00147 float temp = nonlinear - params[1]; 00148 temp /= params[0]; 00149 if (temp > nyquist_frequency) { 00150 E_WARN 00151 ("Warp factor %g results in frequency (%.1f) higher than Nyquist (%.1f)\n", 00152 params[0], temp, nyquist_frequency); 00153 } 00154 return temp; 00155 } 00156 } 00157 00158 float 00159 fe_warp_affine_unwarped_to_warped(float linear) 00160 { 00161 if (is_neutral) { 00162 return linear; 00163 } 00164 else { 00165 /* nonlinear = a * linear - b */ 00166 float temp = linear * params[0]; 00167 temp += params[1]; 00168 return temp; 00169 } 00170 } 00171 00172 void 00173 fe_warp_affine_print(const char *label) 00174 { 00175 uint32 i; 00176 00177 for (i = 0; i < N_PARAM; i++) { 00178 printf("%s[%04u]: %6.3f ", label, i, params[i]); 00179 } 00180 printf("\n"); 00181 } 00182 00183 /* 00184 * Log record. Maintained by RCS. 00185 * 00186 * $Log: fe_warp_affine.c,v $ 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 */