SphinxBase 0.6
src/libsphinxbase/fe/fe_interface.c
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
00002 /* ====================================================================
00003  * Copyright (c) 1996-2004 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 #include <stdio.h>
00038 #include <string.h>
00039 #include <math.h>
00040 #include <stdlib.h>
00041 #include <assert.h>
00042 #ifdef _WIN32_WCE
00043 #include <windows.h>
00044 #else
00045 #include <time.h>
00046 #endif
00047 
00048 #ifdef HAVE_CONFIG_H
00049 #include <config.h>
00050 #endif
00051 
00052 #include "sphinxbase/prim_type.h"
00053 #include "sphinxbase/byteorder.h"
00054 #include "sphinxbase/fixpoint.h"
00055 #include "sphinxbase/genrand.h"
00056 #include "sphinxbase/err.h"
00057 #include "sphinxbase/cmd_ln.h"
00058 #include "sphinxbase/ckd_alloc.h"
00059 
00060 #include "fe_internal.h"
00061 #include "fe_warp.h"
00062 
00063 static const arg_t fe_args[] = {
00064     waveform_to_cepstral_command_line_macro(),
00065     { NULL, 0, NULL, NULL }
00066 };
00067 
00068 int
00069 fe_parse_general_params(cmd_ln_t *config, fe_t * fe)
00070 {
00071     int j;
00072 
00073     fe->config = config;
00074     fe->sampling_rate = cmd_ln_float32_r(config, "-samprate");
00075     fe->frame_rate = (int16)cmd_ln_int32_r(config, "-frate");
00076     if (cmd_ln_boolean_r(config, "-dither")) {
00077         fe->dither = 1;
00078         fe->seed = cmd_ln_int32_r(config, "-seed");
00079     }
00080 #ifdef WORDS_BIGENDIAN
00081     fe->swap = strcmp("big", cmd_ln_str_r(config, "-input_endian")) == 0 ? 0 : 1;
00082 #else        
00083     fe->swap = strcmp("little", cmd_ln_str_r(config, "-input_endian")) == 0 ? 0 : 1;
00084 #endif
00085     fe->window_length = cmd_ln_float32_r(config, "-wlen");
00086     fe->pre_emphasis_alpha = cmd_ln_float32_r(config, "-alpha");
00087 
00088     fe->num_cepstra = (uint8)cmd_ln_int32_r(config, "-ncep");
00089     fe->fft_size = (int16)cmd_ln_int32_r(config, "-nfft");
00090 
00091     /* Check FFT size, compute FFT order (log_2(n)) */
00092     for (j = fe->fft_size, fe->fft_order = 0; j > 1; j >>= 1, fe->fft_order++) {
00093         if (((j % 2) != 0) || (fe->fft_size <= 0)) {
00094             E_ERROR("fft: number of points must be a power of 2 (is %d)\n",
00095                     fe->fft_size);
00096             return -1;
00097         }
00098     }
00099     /* Verify that FFT size is greater or equal to window length. */
00100     if (fe->fft_size < (int)(fe->window_length * fe->sampling_rate)) {
00101         E_ERROR("FFT: Number of points must be greater or equal to frame size (%d samples)\n",
00102                 (int)(fe->window_length * fe->sampling_rate));
00103         return -1;
00104     }
00105 
00106     fe->remove_dc = cmd_ln_boolean_r(config, "-remove_dc");
00107 
00108     if (0 == strcmp(cmd_ln_str_r(config, "-transform"), "dct"))
00109         fe->transform = DCT_II;
00110     else if (0 == strcmp(cmd_ln_str_r(config, "-transform"), "legacy"))
00111         fe->transform = LEGACY_DCT;
00112     else if (0 == strcmp(cmd_ln_str_r(config, "-transform"), "htk"))
00113         fe->transform = DCT_HTK;
00114     else {
00115         E_ERROR("Invalid transform type (values are 'dct', 'legacy', 'htk')\n");
00116         return -1;
00117     }
00118 
00119     if (cmd_ln_boolean_r(config, "-logspec"))
00120         fe->log_spec = RAW_LOG_SPEC;
00121     if (cmd_ln_boolean_r(config, "-smoothspec"))
00122         fe->log_spec = SMOOTH_LOG_SPEC;
00123 
00124     return 0;
00125 }
00126 
00127 static int
00128 fe_parse_melfb_params(cmd_ln_t *config, fe_t *fe, melfb_t * mel)
00129 {
00130     mel->sampling_rate = fe->sampling_rate;
00131     mel->fft_size = fe->fft_size;
00132     mel->num_cepstra = fe->num_cepstra;
00133     mel->num_filters = cmd_ln_int32_r(config, "-nfilt");
00134 
00135     if (fe->log_spec)
00136         fe->feature_dimension = mel->num_filters;
00137     else
00138         fe->feature_dimension = fe->num_cepstra;
00139 
00140     mel->upper_filt_freq = cmd_ln_float32_r(config, "-upperf");
00141     mel->lower_filt_freq = cmd_ln_float32_r(config, "-lowerf");
00142 
00143     mel->doublewide = cmd_ln_boolean_r(config, "-doublebw");
00144 
00145     mel->warp_type = cmd_ln_str_r(config, "-warp_type");
00146     mel->warp_params = cmd_ln_str_r(config, "-warp_params");
00147     mel->lifter_val = cmd_ln_int32_r(config, "-lifter");
00148 
00149     mel->unit_area = cmd_ln_boolean_r(config, "-unit_area");
00150     mel->round_filters = cmd_ln_boolean_r(config, "-round_filters");
00151 
00152     if (fe_warp_set(mel, mel->warp_type) != FE_SUCCESS) {
00153         E_ERROR("Failed to initialize the warping function.\n");
00154         return -1;
00155     }
00156     fe_warp_set_parameters(mel, mel->warp_params, mel->sampling_rate);
00157     return 0;
00158 }
00159 
00160 void
00161 fe_print_current(fe_t const *fe)
00162 {
00163     E_INFO("Current FE Parameters:\n");
00164     E_INFO("\tSampling Rate:             %f\n", fe->sampling_rate);
00165     E_INFO("\tFrame Size:                %d\n", fe->frame_size);
00166     E_INFO("\tFrame Shift:               %d\n", fe->frame_shift);
00167     E_INFO("\tFFT Size:                  %d\n", fe->fft_size);
00168     E_INFO("\tLower Frequency:           %g\n",
00169            fe->mel_fb->lower_filt_freq);
00170     E_INFO("\tUpper Frequency:           %g\n",
00171            fe->mel_fb->upper_filt_freq);
00172     E_INFO("\tNumber of filters:         %d\n", fe->mel_fb->num_filters);
00173     E_INFO("\tNumber of Overflow Samps:  %d\n", fe->num_overflow_samps);
00174     E_INFO("\tStart Utt Status:          %d\n", fe->start_flag);
00175     E_INFO("Will %sremove DC offset at frame level\n",
00176            fe->remove_dc ? "" : "not ");
00177     if (fe->dither) {
00178         E_INFO("Will add dither to audio\n");
00179         E_INFO("Dither seeded with %d\n", fe->seed);
00180     }
00181     else {
00182         E_INFO("Will not add dither to audio\n");
00183     }
00184     if (fe->mel_fb->lifter_val) {
00185         E_INFO("Will apply sine-curve liftering, period %d\n",
00186                fe->mel_fb->lifter_val);
00187     }
00188     E_INFO("Will %snormalize filters to unit area\n",
00189            fe->mel_fb->unit_area ? "" : "not ");
00190     E_INFO("Will %sround filter frequencies to DFT points\n",
00191            fe->mel_fb->round_filters ? "" : "not ");
00192     E_INFO("Will %suse double bandwidth in mel filter\n",
00193            fe->mel_fb->doublewide ? "" : "not ");
00194 }
00195 
00196 fe_t *
00197 fe_init_auto()
00198 {
00199     return fe_init_auto_r(cmd_ln_retain(cmd_ln_get()));
00200 }
00201 
00202 fe_t *
00203 fe_init_auto_r(cmd_ln_t *config)
00204 {
00205     fe_t *fe;
00206 
00207     fe = ckd_calloc(1, sizeof(*fe));
00208     fe->refcount = 1;
00209 
00210     /* transfer params to front end */
00211     if (fe_parse_general_params(config, fe) < 0) {
00212         fe_free(fe);
00213         return NULL;
00214     }
00215 
00216     /* compute remaining fe parameters */
00217     /* We add 0.5 so approximate the float with the closest
00218      * integer. E.g., 2.3 is truncate to 2, whereas 3.7 becomes 4
00219      */
00220     fe->frame_shift = (int32) (fe->sampling_rate / fe->frame_rate + 0.5);
00221     fe->frame_size = (int32) (fe->window_length * fe->sampling_rate + 0.5);
00222     fe->prior = 0;
00223     fe->frame_counter = 0;
00224 
00225     if (fe->frame_size > (fe->fft_size)) {
00226         E_WARN
00227             ("Number of FFT points has to be a power of 2 higher than %d\n",
00228              (fe->frame_size));
00229         fe_free(fe);
00230         return (NULL);
00231     }
00232 
00233     if (fe->dither)
00234         fe_init_dither(fe->seed);
00235 
00236     /* establish buffers for overflow samps and hamming window */
00237     fe->overflow_samps = ckd_calloc(fe->frame_size, sizeof(int16));
00238     fe->hamming_window = ckd_calloc(fe->frame_size/2, sizeof(window_t));
00239 
00240     /* create hamming window */
00241     fe_create_hamming(fe->hamming_window, fe->frame_size);
00242 
00243     /* init and fill appropriate filter structure */
00244     fe->mel_fb = ckd_calloc(1, sizeof(*fe->mel_fb));
00245 
00246     /* transfer params to mel fb */
00247     fe_parse_melfb_params(config, fe, fe->mel_fb);
00248     fe_build_melfilters(fe->mel_fb);
00249     fe_compute_melcosine(fe->mel_fb);
00250 
00251     /* Create temporary FFT, spectrum and mel-spectrum buffers. */
00252     /* FIXME: Gosh there are a lot of these. */
00253     fe->spch = ckd_calloc(fe->frame_size, sizeof(*fe->spch));
00254     fe->frame = ckd_calloc(fe->fft_size, sizeof(*fe->frame));
00255     fe->spec = ckd_calloc(fe->fft_size, sizeof(*fe->spec));
00256     fe->mfspec = ckd_calloc(fe->mel_fb->num_filters, sizeof(*fe->mfspec));
00257 
00258     /* create twiddle factors */
00259     fe->ccc = ckd_calloc(fe->fft_size / 4, sizeof(*fe->ccc));
00260     fe->sss = ckd_calloc(fe->fft_size / 4, sizeof(*fe->sss));
00261     fe_create_twiddle(fe);
00262 
00263     if (cmd_ln_boolean_r(config, "-verbose")) {
00264         fe_print_current(fe);
00265     }
00266 
00267     /*** Z.A.B. ***/
00268     /*** Initialize the overflow buffers ***/
00269     fe_start_utt(fe);
00270     return fe;
00271 }
00272 
00273 arg_t const *
00274 fe_get_args(void)
00275 {
00276     return fe_args;
00277 }
00278 
00279 cmd_ln_t *
00280 fe_get_config(fe_t *fe)
00281 {
00282     return fe->config;
00283 }
00284 
00285 void
00286 fe_init_dither(int32 seed)
00287 {
00288     if (seed < 0) {
00289         E_INFO("You are using the internal mechanism to generate the seed.\n");
00290 #ifdef _WIN32_WCE
00291         s3_rand_seed(GetTickCount());
00292 #else
00293         s3_rand_seed((long) time(0));
00294 #endif
00295     }
00296     else {
00297         E_INFO("You are using %d as the seed.\n", seed);
00298         s3_rand_seed(seed);
00299     }
00300 }
00301 
00302 int32
00303 fe_start_utt(fe_t * fe)
00304 {
00305     fe->num_overflow_samps = 0;
00306     memset(fe->overflow_samps, 0, fe->frame_size * sizeof(int16));
00307     fe->start_flag = 1;
00308     fe->prior = 0;
00309     return 0;
00310 }
00311 
00312 int
00313 fe_get_output_size(fe_t *fe)
00314 {
00315     return (int)fe->feature_dimension;
00316 }
00317 
00318 void
00319 fe_get_input_size(fe_t *fe, int *out_frame_shift,
00320                   int *out_frame_size)
00321 {
00322     if (out_frame_shift)
00323         *out_frame_shift = fe->frame_shift;
00324     if (out_frame_size)
00325         *out_frame_size = fe->frame_size;
00326 }
00327 
00328 int32
00329 fe_process_frame(fe_t * fe, int16 const *spch, int32 nsamps, mfcc_t * fr_cep)
00330 {
00331     fe_read_frame(fe, spch, nsamps);
00332     return fe_write_frame(fe, fr_cep);
00333 }
00334 
00335 int
00336 fe_process_frames(fe_t *fe,
00337                   int16 const **inout_spch,
00338                   size_t *inout_nsamps,
00339                   mfcc_t **buf_cep,
00340                   int32 *inout_nframes)
00341 {
00342     int32 frame_count;
00343     int outidx, i, n, n_overflow, orig_n_overflow;
00344     int16 const *orig_spch;
00345 
00346     /* In the special case where there is no output buffer, return the
00347      * maximum number of frames which would be generated. */
00348     if (buf_cep == NULL) {
00349         if (*inout_nsamps + fe->num_overflow_samps < (size_t)fe->frame_size)
00350             *inout_nframes = 0;
00351         else 
00352             *inout_nframes = 1
00353                 + ((*inout_nsamps + fe->num_overflow_samps - fe->frame_size)
00354                    / fe->frame_shift);
00355         return *inout_nframes;
00356     }
00357 
00358     /* Are there not enough samples to make at least 1 frame? */
00359     if (*inout_nsamps + fe->num_overflow_samps < (size_t)fe->frame_size) {
00360         if (*inout_nsamps > 0) {
00361             /* Append them to the overflow buffer. */
00362             memcpy(fe->overflow_samps + fe->num_overflow_samps,
00363                    *inout_spch, *inout_nsamps * (sizeof(int16)));
00364             fe->num_overflow_samps += *inout_nsamps;
00365             /* Update input-output pointers and counters. */
00366             *inout_spch += *inout_nsamps;
00367             *inout_nsamps = 0;
00368         }
00369         /* We produced no frames of output, sorry! */
00370         *inout_nframes = 0;
00371         return 0;
00372     }
00373 
00374     /* Can't write a frame?  Then do nothing! */
00375     if (*inout_nframes < 1) {
00376         *inout_nframes = 0;
00377         return 0;
00378     }
00379 
00380     /* Keep track of the original start of the buffer. */
00381     orig_spch = *inout_spch;
00382     orig_n_overflow = fe->num_overflow_samps;
00383     /* How many frames will we be able to get? */
00384     frame_count = 1
00385         + ((*inout_nsamps + fe->num_overflow_samps - fe->frame_size)
00386            / fe->frame_shift);
00387     /* Limit it to the number of output frames available. */
00388     if (frame_count > *inout_nframes)
00389         frame_count = *inout_nframes;
00390     /* Index of output frame. */
00391     outidx = 0;
00392 
00393     /* Start processing, taking care of any incoming overflow. */
00394     if (fe->num_overflow_samps) {
00395         int offset = fe->frame_size - fe->num_overflow_samps;
00396 
00397         /* Append start of spch to overflow samples to make a full frame. */
00398         memcpy(fe->overflow_samps + fe->num_overflow_samps,
00399                *inout_spch, offset * sizeof(**inout_spch));
00400         fe_read_frame(fe, fe->overflow_samps, fe->frame_size);
00401         assert(outidx < frame_count);
00402         if ((n = fe_write_frame(fe, buf_cep[outidx])) < 0)
00403             return -1;
00404         outidx += n;
00405         /* Update input-output pointers and counters. */
00406         *inout_spch += offset;
00407         *inout_nsamps -= offset;
00408         fe->num_overflow_samps -= fe->frame_shift;
00409     }
00410     else {
00411         fe_read_frame(fe, *inout_spch, fe->frame_size);
00412         assert(outidx < frame_count);
00413         if ((n = fe_write_frame(fe, buf_cep[outidx])) < 0)
00414             return -1;
00415         outidx += n;
00416         /* Update input-output pointers and counters. */
00417         *inout_spch += fe->frame_size;
00418         *inout_nsamps -= fe->frame_size;
00419     }
00420 
00421     /* Process all remaining frames. */
00422     for (i = 1; i < frame_count; ++i) {
00423         assert(*inout_nsamps >= (size_t)fe->frame_shift);
00424 
00425         fe_shift_frame(fe, *inout_spch, fe->frame_shift);
00426         assert(outidx < frame_count);
00427         if ((n = fe_write_frame(fe, buf_cep[outidx])) < 0)
00428             return -1;
00429         outidx += n;
00430         /* Update input-output pointers and counters. */
00431         *inout_spch += fe->frame_shift;
00432         *inout_nsamps -= fe->frame_shift;
00433         /* Amount of data behind the original input which is still needed. */
00434         if (fe->num_overflow_samps > 0)
00435             fe->num_overflow_samps -= fe->frame_shift;
00436     }
00437 
00438     /* How many relevant overflow samples are there left? */
00439     if (fe->num_overflow_samps <= 0) {
00440         /* Maximum number of overflow samples past *inout_spch to save. */
00441         n_overflow = *inout_nsamps;
00442         if (n_overflow > fe->frame_shift)
00443             n_overflow = fe->frame_shift;
00444         fe->num_overflow_samps = fe->frame_size - fe->frame_shift;
00445         /* Make sure this isn't an illegal read! */
00446         if (fe->num_overflow_samps > *inout_spch - orig_spch)
00447             fe->num_overflow_samps = *inout_spch - orig_spch;
00448         fe->num_overflow_samps += n_overflow;
00449         if (fe->num_overflow_samps > 0) {
00450             memcpy(fe->overflow_samps,
00451                    *inout_spch - (fe->frame_size - fe->frame_shift),
00452                    fe->num_overflow_samps * sizeof(**inout_spch));
00453             /* Update the input pointer to cover this stuff. */
00454             *inout_spch += n_overflow;
00455             *inout_nsamps -= n_overflow;
00456         }
00457     }
00458     else {
00459         /* There is still some relevant data left in the overflow buffer. */
00460         /* Shift existing data to the beginning. */
00461         memmove(fe->overflow_samps,
00462                 fe->overflow_samps + orig_n_overflow - fe->num_overflow_samps,
00463                 fe->num_overflow_samps * sizeof(*fe->overflow_samps));
00464         /* Copy in whatever we had in the original speech buffer. */
00465         n_overflow = *inout_spch - orig_spch + *inout_nsamps;
00466         if (n_overflow > fe->frame_size - fe->num_overflow_samps)
00467             n_overflow = fe->frame_size - fe->num_overflow_samps;
00468         memcpy(fe->overflow_samps + fe->num_overflow_samps,
00469                orig_spch, n_overflow * sizeof(*orig_spch));
00470         fe->num_overflow_samps += n_overflow;
00471         /* Advance the input pointers. */
00472         if (n_overflow > *inout_spch - orig_spch) {
00473             n_overflow -= (*inout_spch - orig_spch);
00474             *inout_spch += n_overflow;
00475             *inout_nsamps -= n_overflow;
00476         }
00477     }
00478 
00479     /* Finally update the frame counter with the number of frames we procesed. */
00480     *inout_nframes = outidx; /* FIXME: Not sure why I wrote it this way... */
00481     return 0;
00482 }
00483 
00484 int
00485 fe_process_utt(fe_t * fe, int16 const * spch, size_t nsamps,
00486                mfcc_t *** cep_block, int32 * nframes)
00487 {
00488     mfcc_t **cep;
00489     int rv;
00490 
00491     /* Figure out how many frames we will need. */
00492     fe_process_frames(fe, NULL, &nsamps, NULL, nframes);
00493     /* Create the output buffer (it has to exist, even if there are no output frames). */
00494     if (*nframes)
00495         cep = (mfcc_t **)ckd_calloc_2d(*nframes, fe->feature_dimension, sizeof(**cep));
00496     else
00497         cep = (mfcc_t **)ckd_calloc_2d(1, fe->feature_dimension, sizeof(**cep));
00498     /* Now just call fe_process_frames() with the allocated buffer. */
00499     rv = fe_process_frames(fe, &spch, &nsamps, cep, nframes);
00500     *cep_block = cep;
00501 
00502     return rv;
00503 }
00504 
00505 
00506 int32
00507 fe_end_utt(fe_t * fe, mfcc_t * cepvector, int32 * nframes)
00508 {
00509     /* Process any remaining data. */
00510     if (fe->num_overflow_samps > 0) {
00511         fe_read_frame(fe, fe->overflow_samps, fe->num_overflow_samps);
00512         *nframes = fe_write_frame(fe, cepvector);
00513     }
00514     else {
00515         *nframes = 0;
00516     }
00517 
00518     /* reset overflow buffers... */
00519     fe->num_overflow_samps = 0;
00520     fe->start_flag = 0;
00521 
00522     return 0;
00523 }
00524 
00525 fe_t *
00526 fe_retain(fe_t *fe)
00527 {
00528     ++fe->refcount;
00529     return fe;
00530 }
00531 
00532 int
00533 fe_free(fe_t * fe)
00534 {
00535     if (fe == NULL)
00536         return 0;
00537     if (--fe->refcount > 0)
00538         return fe->refcount;
00539 
00540     /* kill FE instance - free everything... */
00541     if (fe->mel_fb) {
00542         if (fe->mel_fb->mel_cosine)
00543             fe_free_2d((void *) fe->mel_fb->mel_cosine);
00544         ckd_free(fe->mel_fb->lifter);
00545         ckd_free(fe->mel_fb->spec_start);
00546         ckd_free(fe->mel_fb->filt_start);
00547         ckd_free(fe->mel_fb->filt_width);
00548         ckd_free(fe->mel_fb->filt_coeffs);
00549         ckd_free(fe->mel_fb);
00550     }
00551     ckd_free(fe->spch);
00552     ckd_free(fe->frame);
00553     ckd_free(fe->ccc);
00554     ckd_free(fe->sss);
00555     ckd_free(fe->spec);
00556     ckd_free(fe->mfspec);
00557     ckd_free(fe->overflow_samps);
00558     ckd_free(fe->hamming_window);
00559     cmd_ln_free_r(fe->config);
00560     ckd_free(fe);
00561 
00562     return 0;
00563 }
00564 
00568 int32
00569 fe_mfcc_to_float(fe_t * fe,
00570                  mfcc_t ** input, float32 ** output, int32 nframes)
00571 {
00572     int32 i;
00573 
00574 #ifndef FIXED_POINT
00575     if ((void *) input == (void *) output)
00576         return nframes * fe->feature_dimension;
00577 #endif
00578     for (i = 0; i < nframes * fe->feature_dimension; ++i)
00579         output[0][i] = MFCC2FLOAT(input[0][i]);
00580 
00581     return i;
00582 }
00583 
00587 int32
00588 fe_float_to_mfcc(fe_t * fe,
00589                  float32 ** input, mfcc_t ** output, int32 nframes)
00590 {
00591     int32 i;
00592 
00593 #ifndef FIXED_POINT
00594     if ((void *) input == (void *) output)
00595         return nframes * fe->feature_dimension;
00596 #endif
00597     for (i = 0; i < nframes * fe->feature_dimension; ++i)
00598         output[0][i] = FLOAT2MFCC(input[0][i]);
00599 
00600     return i;
00601 }
00602 
00603 int32
00604 fe_logspec_to_mfcc(fe_t * fe, const mfcc_t * fr_spec, mfcc_t * fr_cep)
00605 {
00606 #ifdef FIXED_POINT
00607     fe_spec2cep(fe, fr_spec, fr_cep);
00608 #else                           /* ! FIXED_POINT */
00609     powspec_t *powspec;
00610     int32 i;
00611 
00612     powspec = ckd_malloc(fe->mel_fb->num_filters * sizeof(powspec_t));
00613     for (i = 0; i < fe->mel_fb->num_filters; ++i)
00614         powspec[i] = (powspec_t) fr_spec[i];
00615     fe_spec2cep(fe, powspec, fr_cep);
00616     ckd_free(powspec);
00617 #endif                          /* ! FIXED_POINT */
00618     return 0;
00619 }
00620 
00621 int32
00622 fe_logspec_dct2(fe_t * fe, const mfcc_t * fr_spec, mfcc_t * fr_cep)
00623 {
00624 #ifdef FIXED_POINT
00625     fe_dct2(fe, fr_spec, fr_cep, 0);
00626 #else                           /* ! FIXED_POINT */
00627     powspec_t *powspec;
00628     int32 i;
00629 
00630     powspec = ckd_malloc(fe->mel_fb->num_filters * sizeof(powspec_t));
00631     for (i = 0; i < fe->mel_fb->num_filters; ++i)
00632         powspec[i] = (powspec_t) fr_spec[i];
00633     fe_dct2(fe, powspec, fr_cep, 0);
00634     ckd_free(powspec);
00635 #endif                          /* ! FIXED_POINT */
00636     return 0;
00637 }
00638 
00639 int32
00640 fe_mfcc_dct3(fe_t * fe, const mfcc_t * fr_cep, mfcc_t * fr_spec)
00641 {
00642 #ifdef FIXED_POINT
00643     fe_dct3(fe, fr_cep, fr_spec);
00644 #else                           /* ! FIXED_POINT */
00645     powspec_t *powspec;
00646     int32 i;
00647 
00648     powspec = ckd_malloc(fe->mel_fb->num_filters * sizeof(powspec_t));
00649     fe_dct3(fe, fr_cep, powspec);
00650     for (i = 0; i < fe->mel_fb->num_filters; ++i)
00651         fr_spec[i] = (mfcc_t) powspec[i];
00652     ckd_free(powspec);
00653 #endif                          /* ! FIXED_POINT */
00654     return 0;
00655 }