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