14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------*
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  spec_anl.c  *
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the 'License');          *
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  you may not use this file except in compliance with the License.         *
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  You may obtain a copy of the License at                                  *
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0                           *
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software      *
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  distributed under the License is distributed on an 'AS IS' BASIS,        *
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  See the License for the specific language governing permissions and      *
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *  limitations under the License.                                           *
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                                                                           *
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <stdlib.h>
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef _RTT
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <stdio.h>
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <string.h>
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <math.h>
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <limits.h>
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <assert.h>
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "hmm_desc.h"
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "front.h"
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "pendian.h"
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "portable.h"
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "LCHAR.h"
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "../clib/memmove.h"
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define DEBUG           0
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "sh_down.h"
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int sort_ints_unique(int *list, int *num);
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//static void mask_fft_taps(fftdata *data, int num, front_freq *freqobj);
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid peakpick(front_freq *freqobj, fftdata *density, int num_freq);
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid magsq(fftdata *x, fftdata *y, fftdata *z, int ns);
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid preemph(fftdata *data, int window_len, samdata *wav_data,
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             int num_samples, coefdata pre_mel,
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             bigdata *last_sample);
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid filtbank(front_freq *freqobj, fftdata *density, cepdata *fbo);
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid filterbank_emulation(front_channel * channel, front_wave *waveobj,
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                          front_freq *freqobj, front_cep *cepobj, samdata *income,
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                          samdata *outgo, int num_samples)
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  Part II. Mel cepstrum coefficients
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  **
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  **  Maintain parameter queue */
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  MEMMOVE(channel->cep + (channel->mel_dim + 1), channel->cep,
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          (Q2 - 1) *(channel->mel_dim + 1), sizeof(cepdata));
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  channel->shift = 0;
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  2.01 Pre-emphasize waveform
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  Only the new samples are preemphasized.  To carry on from the previous call,
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  the last sample value is stored in lastx.
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  */
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  preemph(channel->prebuff, freqobj->window_length, income, num_samples,
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project          waveobj->pre_mel, &channel->lastx);
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DEBUG
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  log_report("preemphasized data\n");
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  write_scaled_frames(freqobj->window_length, 1, channel->prebuff, D_FIXED, (float) 1 / (0x01 << WAVE_SHIFT));
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /******************************************************************************
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  **  The "NEW" fft performs shifting operations in fixed point, to maximise
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  **  precision.
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  **
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  *******************************************************************************/
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  channel->shift += place_sample_data(&freqobj->fft, channel->prebuff,
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                      freqobj->ham, freqobj->window_length);
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DEBUG
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  log_report("windowed data\n");
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (channel->shift >= 0)
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, freqobj->fft.real, D_FIXED, (float)(0x01 << channel->shift));
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, freqobj->fft.imag, D_FIXED, (float)(0x01 << channel->shift));
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, freqobj->fft.real, D_FIXED, (float)1 / (0x01 << -channel->shift));
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, freqobj->fft.imag, D_FIXED, (float)1 / (0x01 << -channel->shift));
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  channel->shift *= 2;
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  channel->shift += fft_perform_and_magsq(&freqobj->fft);
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DEBUG
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  log_report("After magnitude squared (%d)\n", channel->frame_count);
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (channel->shift >= 0)
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, freqobj->fft.real, D_FIXED, (float)(0x01 << (channel->shift)));
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, freqobj->fft.real, D_FIXED, (float)1 / (0x01 << (- channel->shift)));
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DEBUG
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  log_report("After magnitude squared: ");
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (channel->shift >= 0)
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, (void *)freqobj->fft.real, D_FIXED, (float)(0x01 <<  channel->shift));
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size, 1, (void *)freqobj->fft.real, D_FIXED, (float)1 / (0x01 <<  -channel->shift));
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (freqobj->do_nonlinear_filter)
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    peakpick(freqobj, freqobj->fft.real, freqobj->fft.size + 1);
1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DEBUG
1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  log_report("After peakpick: ");
1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (channel->shift >= 0)
1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size + 1, 1, (void *)freqobj->fft.real, D_FIXED, (float)(0x01 << channel->shift));
1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->fft.size + 1, 1, (void *)freqobj->fft.real, D_FIXED, (float)1 / (0x01 << -channel->shift));
1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  2.23 Apply filterbank emulation */
1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  channel->shift += RAMP_SHIFT;
1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  filtbank(freqobj, freqobj->fft.real, channel->filterbank);
1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if DEBUG
1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  log_report("After filterbanked: ");
1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (channel->shift >= 0)
1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->nf, 1, channel->filterbank, D_FIXED, (float)(0x01 << channel->shift));
1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  else
1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    write_scaled_frames(freqobj->nf, 1, channel->filterbank, D_FIXED, (float)1 / (0x01 << -channel->shift));
1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif
1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return;
1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid preemph(fftdata *data, int window_len, samdata *wav_data,
1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             int num_samples, coefdata pre_mel,
1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project             bigdata *last_sample)
1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project**  pre-emphasize on speech data, check for end of data */
1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*  SCALE: In this stage we're introducing a scale factor of 2 */
1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bigdata temp;
1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(data);
1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(last_sample);
1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(wav_data);
1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(num_samples >= 0);
1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (num_samples > window_len)
1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    num_samples = window_len;
1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (num_samples < window_len)
1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    MEMMOVE(data, data + num_samples, (window_len - num_samples),
1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project            sizeof(fftdata));
1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  data += window_len - num_samples;
1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  If no preemphasis to do
1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  */
1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (pre_mel == 0)
1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  { /* dont't shift */
1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = 0; i < num_samples; i++)
1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      data[i] = (fftdata) wav_data[i];
1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return;
1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  Otherwise do the preemphasis
1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  */
1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < num_samples; i++)
1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    temp = SHIFT_UP((bigdata)wav_data[i], COEFDATA_SHIFT);
1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    data[i] = (fftdata)(SHIFT_DOWN(temp - (*last_sample), COEFDATA_SHIFT));
1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    *last_sample = (bigdata)pre_mel * wav_data[i];
1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return;
1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid magsq(fftdata *x, fftdata *y, fftdata *z, int ns)
1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project**  magnitude squared, tailored for TI FFT routines
1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project**  The dynamic range should fit 32 - RAMP_SHIFT */
1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT((float)x[0] *(float)x[0] < LONG_MAX);
1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT((float)x[0] *(float)x[0] > LONG_MIN);
1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  z[0] = (fftdata)((bigdata)x[0] * (bigdata)x[0]);
1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 1; i < ns; i++)
1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((fftdata)x[i] *(fftdata)x[i]) >= 0);
1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((fftdata)y[i] *(fftdata)y[i]) >= 0);
2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT((float)x[i] *(float)x[i] < LONG_MAX);
2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT((float)x[i] *(float)x[i] > LONG_MIN);
2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT((float)y[i] *(float)y[i] < LONG_MAX);
2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT((float)y[i] *(float)y[i] > LONG_MIN);
2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /*    z[i]= (fftdata) SHIFT_DOWN ((bigdata)x[i] * (bigdata)x[i] + (bigdata)y[i] * (bigdata)y[i], RAMP_SHIFT);
2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    */
2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    z[i] = (fftdata)(((bigdata)x[i] * (bigdata)x[i])
2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                     + ((bigdata)y[i] * (bigdata)y[i]));
2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (z[i] <= 0)
2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      z[i] = (fftdata) 1;
2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return;
2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid peakpick(front_freq *freqobj, fftdata *density, int num_freq)
2154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
2174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fftdata peak;
2184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fftdata bdecay;
2194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fftdata fdecay;
2204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int first;
2214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int last;
2224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj);
2244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* Fixed pt requires scale up of COEFDATA_SHIFT on these pars (coefdata) */
2254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bdecay = freqobj->peakpickdown;
2264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fdecay = freqobj->peakpickup;
2274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if ((bdecay <= (fftdata) 0.0) && (fdecay <= (fftdata) 0.0))
2294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return;
2304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  first = freqobj->cut_off_below;
2324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  last  = freqobj->cut_off_above;
2334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* this filters from cut_off_below to       */
2344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* cut_off_above inclusive          */
2354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (last >= num_freq)
2374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    last = num_freq - 1;
2384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* as most routines seem to check both      */
2394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* limits                           */
2404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (bdecay > 0.0)
2424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(density[last] >= 0);
2444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    peak = density[last];
2454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = last - 1; i >= first; i--)
2464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
2474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      peak = (fftdata)(SHIFT_DOWN((bigdata)peak, COEFDATA_SHIFT) * (bigdata)bdecay);
2484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT(peak >= 0);
2494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (density[i] > peak)
2504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        peak = density[i];
2514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
2524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        density[i] = peak;
2534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (fdecay > 0.0)
2564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    peak = density[first];
2584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (i = first + 1; i <= last; i++)
2594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
2604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      peak = (fftdata)(SHIFT_DOWN((bigdata)peak, COEFDATA_SHIFT) * (bigdata)fdecay);
2614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (density[i] > peak)
2624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        peak = density[i];
2634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      else
2644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        density[i] = peak;
2654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
2664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return;
2684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
2694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid filtbank(front_freq *freqobj, fftdata *density, cepdata *fbo)
2714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*
2724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project**  pwr spect -> filter bank output (linear) */
2734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
2744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i, j, k;
2754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  bigdata t, sum, mom, nxt;
2764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  Scale down before starting mel-filterbank operations
2784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  */
2794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < freqobj->cut_off_above; i++)
2804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    density[i] = SHIFT_DOWN(density[i], RAMP_SHIFT);
2814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  j = MAX(freqobj->fcmid[0], freqobj->cut_off_below);
2834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nxt = 0;
2844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (; j < freqobj->fcmid[1]; j++)
2854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((float)nxt + (float)freqobj->framp[j] *(float)density[j]) < LONG_MAX);
2874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((float)nxt + (float)freqobj->framp[j] *(float)density[j]) > -LONG_MAX);
2884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    nxt += (bigdata) SHIFT_DOWN((bigdata)freqobj->framp[j] * (bigdata)density[j], RAMP_SHIFT);
2894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
2904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0, k = 2; i < freqobj->nf; i++, k++)
2914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
2924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    sum = mom = 0;
2934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (; j < freqobj->fcmid[k]; j++)
2944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
2954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      /* TODO: Tidy up this fixed pt shifting. BP */
2964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
2974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT((float) freqobj->framp[j] *(float) density[j] < LONG_MAX);
2984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT((float) freqobj->framp[j] *(float) density[j] > LONG_MIN);
2994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT((float) sum + (float)density[j] < LONG_MAX);
3004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT((float) sum + (float)density[j] > LONG_MIN);
3014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      sum += (bigdata) density[j];
3024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT((float) mom + (float) freqobj->framp[j] *(float) density[j] < LONG_MAX);
3034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ASSERT((float) mom + (float) freqobj->framp[j] *(float) density[j] > LONG_MIN);
3044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      mom += (bigdata)(long) SHIFT_DOWN((bigdata)freqobj->framp[j] * (bigdata)density[j], RAMP_SHIFT);
3064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((float)nxt + (float)sum - (float)mom) < LONG_MAX);
3094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ASSERT(((float)nxt + (float)sum - (float)mom) > LONG_MIN);
3104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* TODO: refine this expression. Shift down fcscl in advance.  */
3124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    t = (bigdata)((SHIFT_UP(nxt + sum - mom, HALF_RAMP_SHIFT)
3134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   + SHIFT_DOWN(freqobj->fcscl[i+1], HALF_RAMP_SHIFT + 1))
3144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                  / SHIFT_DOWN(freqobj->fcscl[i+1], HALF_RAMP_SHIFT));
3154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* TODO: cleanup and also check for division by zero */
3164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    nxt = mom;
3174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    fbo[i] = (cepdata) t;
3184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return;
3204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint create_spectrum_filter(front_freq *freqobj, int *freq, int *spread)
3234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int ii, jj, freq_step;
3254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int lo, hi;
3264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj);
3274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj->spectrum_filter_num == 0);
3284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj->samplerate > 0);
3294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* Convert to FFT taps. Mark adjacent taps as well as taps within spread */
3304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  freq_step = (freqobj->samplerate << 12) / (2 * freqobj->fft.size);
3314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  freqobj->spectrum_filter = (int *) CALLOC_CLR(freqobj->fft.size + 1, sizeof(int), "cfront.spectrum_filter");
3324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  freqobj->spectrum_filter_num = 0;
3334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (ii = 0 ; ii < MAX_FILTER_NUM; ii++)
3344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (freq[ii] == 0)
3364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      continue;
3374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    lo = (((freq[ii] - spread[ii]) * 2 * freqobj->fft.size) + freqobj->samplerate / 2) / freqobj->samplerate;
3384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    hi = (((freq[ii] + spread[ii]) * 2 * freqobj->fft.size) + freqobj->samplerate / 2) / freqobj->samplerate;
3394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (jj = lo; jj <= hi;jj++)
3424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
3434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (freqobj->spectrum_filter_num >= (int) freqobj->fft.size)
3444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        SERVICE_ERROR(MAX_FILTER_POINTS_EXCEEDED);
3454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      freqobj->spectrum_filter[freqobj->spectrum_filter_num++] = jj;
3464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    /* jj=0;
3484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     while (((jj+1)*freq_step)>>12 <= freq[ii]-spread[ii])
3494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         jj++;
3504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     while (((jj-1)*freq_step>>12) < freq[ii]+spread[ii]){
3514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         if (freqobj->spectrum_filter_num >= (int) freqobj->fft.size)
3524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      SERVICE_ERROR (MAX_FILTER_POINTS_EXCEEDED);
3534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         freqobj->spectrum_filter[freqobj->spectrum_filter_num++]= jj;
3544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         jj++;
3554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project     }
3564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    */
3574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  sort_ints_unique(freqobj->spectrum_filter, &freqobj->spectrum_filter_num);
3594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return (freqobj->spectrum_filter_num);
3604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid clear_spectrum_filter(front_freq *freqobj)
3634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj->spectrum_filter);
3654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (freqobj->spectrum_filter)
3664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    FREE((char *) freqobj->spectrum_filter);
3674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  freqobj->spectrum_filter = NULL;
3684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  freqobj->spectrum_filter_num = 0;
3694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return;
3704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int sort_ints_unique(int *list, int *num)
3734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
3744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /*  Sort a list of ints and make unique */
3754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int ii, jj, temp;
3764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (ii = 1; ii < *num; ii++)
3774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
3784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (jj = 0; jj < ii; jj++)
3794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
3804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      temp = list[ii];
3814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (temp < list[jj])
3824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
3834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        MEMMOVE(&list[jj+1], &list[jj], (ii - jj), sizeof(int));
3844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        list[jj] = temp;
3854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        break;
3864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (temp == list[jj])
3884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      {
3894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        MEMMOVE(&list[ii], &list[ii+1], (*num - ii), sizeof(int));
3904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
3934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        (*num)--;
3944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
3954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
3964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
3974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  return *num;
3984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
3994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//static void mask_fft_taps(fftdata *data, int num, front_freq *freqobj)
4014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//{
4024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//  for (int i = 0; i < freqobj->spectrum_filter_num; ++i)
4034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//  {
4044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//    ASSERT(freqobj->spectrum_filter[i] < num);
4054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//    data[freqobj->spectrum_filter[i]] = 0;
4064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//  }
4074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//}
4084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/* --------------------------------------------------
4104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project freq_warp will do pure linear warping if the warp
4114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project scale > 1.0. Otherwise it will do piecewise warp
4124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project which means warping the second part, from xstart
4134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project to the bandwidth with another scale which is
4144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project determined by b and c in the formulation.
4154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project In general, 0.7 < wscale < 1.4, and xstart <= 1
4164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 08/15/01, Puming Zhan
4174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project --------------------------------------------------- */
4184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectvoid freq_warp(front_freq *freqobj, fftdata *inbuf, int ns)
4194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{
4204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int i;
4214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  int nsE;
4224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  float x1, y1, b, c, wscale;
4234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  fftdata *tmpbuf;
4244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj && inbuf);
4264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  ASSERT(freqobj->warp_scale != 0);
4284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  wscale = freqobj->warp_scale;
4304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  x1     = freqobj->piecewise_start;
4314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  tmpbuf = (fftdata *) CALLOC(ns, sizeof(fftdata), "cfront.tmpbuf");
4324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (wscale < MIN_WARP_SCALE || wscale > MAX_WARP_SCALE)
4344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SERVICE_ERROR(WARP_SCALE);
4364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (x1 > 1.0 || x1 < 0.5)
4384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    SERVICE_ERROR(PIECEWISE_START);
4404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  y1 = x1 < wscale ? (float)x1 / wscale : (float)1.0;
4434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  b = y1 < 1.0 ? (float)((1.0 - x1) / (1.0 - y1)) : (float)0.0;
4454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  c = (float)((1.0 - b) * (ns - 1));
4474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  nsE = (int)(y1 * (ns - 1));
4494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < ns; i++)
4514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  {
4524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    float x = i > nsE ? b * i + c : wscale * i;
4534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int   u = (int)ceil((double)x);
4544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    int   l = (int)floor((double)x);
4554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    float w1 = x - l;
4564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    float w2 = 1 - w1;
4574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (u < ns)
4594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
4604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      tmpbuf[i] = (int)(w1 * inbuf[u] + w2 * inbuf[l]);
4614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    else
4634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    {
4644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      tmpbuf[i] = inbuf[ns-1];
4654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
4664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
4674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* need to copy the warped fft into inbuf    */
4694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* because the following function filtbank() */
4704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* will take inbuf as input                  */
4714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* considering that this function will be    */
4724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* for every frame, it may not be a good idea*/
4734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  /* to do malloc here                         */
4744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (i = 0; i < ns; i++)
4764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    inbuf[i] = tmpbuf[i];
4774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
4784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  FREE((char *) tmpbuf);
4794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
480