198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Copyright (C) 2003 Epic Games (written by Jean-Marc Valin)
298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Copyright (C) 2004-2006 Epic Games
398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   File: preprocess.c
598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Preprocessor with denoising based on the algorithm by Ephraim and Malah
698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Redistribution and use in source and binary forms, with or without
898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   modification, are permitted provided that the following conditions are
998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   met:
1098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   1. Redistributions of source code must retain the above copyright notice,
1298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   this list of conditions and the following disclaimer.
1398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   2. Redistributions in binary form must reproduce the above copyright
1598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   notice, this list of conditions and the following disclaimer in the
1698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   documentation and/or other materials provided with the distribution.
1798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   3. The name of the author may not be used to endorse or promote products
1998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   derived from this software without specific prior written permission.
2098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
2198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   POSSIBILITY OF SUCH DAMAGE.
3298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
3398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/*
3698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Recommended papers:
3798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error
3998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   short-time spectral amplitude estimator". IEEE Transactions on Acoustics,
4098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Speech and Signal Processing, vol. ASSP-32, no. 6, pp. 1109-1121, 1984.
4198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Y. Ephraim and D. Malah, "Speech enhancement using minimum mean-square error
4398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   log-spectral amplitude estimator". IEEE Transactions on Acoustics, Speech and
4498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Signal Processing, vol. ASSP-33, no. 2, pp. 443-445, 1985.
4598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   I. Cohen and B. Berdugo, "Speech enhancement for non-stationary noise environments".
4798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Signal Processing, vol. 81, no. 2, pp. 2403-2418, 2001.
4898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Stefan Gustafsson, Rainer Martin, Peter Jax, and Peter Vary. "A psychoacoustic
5098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   approach to combined acoustic echo cancellation and noise reduction". IEEE
5198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Transactions on Speech and Audio Processing, 2002.
5298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
5398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   J.-M. Valin, J. Rouat, and F. Michaud, "Microphone array post-filter for separation
5498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   of simultaneous non-stationary sources". In Proceedings IEEE International
5598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Conference on Acoustics, Speech, and Signal Processing, 2004.
5698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
5798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
5898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef HAVE_CONFIG_H
5998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "config.h"
6098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
6198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
6298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <math.h>
6398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "speex/speex_preprocess.h"
6498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "speex/speex_echo.h"
6598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "arch.h"
6698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "fftwrap.h"
6798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "filterbank.h"
6898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "math_approx.h"
6998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "os_support.h"
7098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
7198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef M_PI
7298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define M_PI 3.14159263
7398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
7498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
7598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define LOUDNESS_EXP 5.f
7698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define AMP_SCALE .001f
7798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define AMP_SCALE_1 1000.f
7898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
7998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NB_BANDS 24
8098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
8198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SPEECH_PROB_START_DEFAULT       QCONST16(0.35f,15)
8298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SPEECH_PROB_CONTINUE_DEFAULT    QCONST16(0.20f,15)
8398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NOISE_SUPPRESS_DEFAULT       -15
8498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define ECHO_SUPPRESS_DEFAULT        -40
8598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define ECHO_SUPPRESS_ACTIVE_DEFAULT -15
8698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
8798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef NULL
8898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NULL 0
8998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
9098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
9198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SQR(x) ((x)*(x))
9298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SQR16(x) (MULT16_16((x),(x)))
9398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SQR16_Q15(x) (MULT16_16_Q15((x),(x)))
9498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
9598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
9698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word16_t DIV32_16_Q8(spx_word32_t a, spx_word32_t b)
9798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
9898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (SHR32(a,7) >= b)
9998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
10098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return 32767;
10198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
10298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (b>=QCONST32(1,23))
10398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
10498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         a = SHR32(a,8);
10598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         b = SHR32(b,8);
10698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
10798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (b>=QCONST32(1,19))
10898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
10998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         a = SHR32(a,4);
11098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         b = SHR32(b,4);
11198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
11298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (b>=QCONST32(1,15))
11398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
11498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         a = SHR32(a,4);
11598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         b = SHR32(b,4);
11698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
11798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      a = SHL32(a,8);
11898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return PDIV32_16(a,b);
11998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
12098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
12198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
12298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word16_t DIV32_16_Q15(spx_word32_t a, spx_word32_t b)
12398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
12498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (SHR32(a,15) >= b)
12598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
12698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return 32767;
12798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
12898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (b>=QCONST32(1,23))
12998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
13098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         a = SHR32(a,8);
13198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         b = SHR32(b,8);
13298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
13398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (b>=QCONST32(1,19))
13498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
13598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         a = SHR32(a,4);
13698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         b = SHR32(b,4);
13798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
13898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (b>=QCONST32(1,15))
13998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
14098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         a = SHR32(a,4);
14198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         b = SHR32(b,4);
14298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
14398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      a = SHL32(a,15)-a;
14498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return DIV32_16(a,b);
14598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
14698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
14798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SNR_SCALING 256.f
14898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SNR_SCALING_1 0.0039062f
14998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SNR_SHIFT 8
15098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
15198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FRAC_SCALING 32767.f
15298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FRAC_SCALING_1 3.0518e-05
15398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FRAC_SHIFT 1
15498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
15598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPIN_SCALING 2048.f
15698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPIN_SCALING_1 0.00048828f
15798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPIN_SHIFT 11
15898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPOUT_SCALING_1 1.5259e-05
15998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
16098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NOISE_SHIFT 7
16198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
16298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
16398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
16498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define DIV32_16_Q8(a,b) ((a)/(b))
16598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define DIV32_16_Q15(a,b) ((a)/(b))
16698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SNR_SCALING 1.f
16798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SNR_SCALING_1 1.f
16898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define SNR_SHIFT 0
16998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FRAC_SCALING 1.f
17098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FRAC_SCALING_1 1.f
17198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define FRAC_SHIFT 0
17298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NOISE_SHIFT 0
17398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
17498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPIN_SCALING 1.f
17598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPIN_SCALING_1 1.f
17698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define EXPOUT_SCALING_1 1.f
17798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
17898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
17998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
18098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/** Speex pre-processor state. */
18198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstruct SpeexPreprocessState_ {
18298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Basic info */
18398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    frame_size;        /**< Number of samples processed each time */
18498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    ps_size;           /**< Number of points in the power spectrum */
18598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    sampling_rate;     /**< Sampling rate of the input/output */
18698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    nbands;
18798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   FilterBank *bank;
18898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
18998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Parameters */
19098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    denoise_enabled;
19198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    vad_enabled;
19298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    dereverb_enabled;
19398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t  reverb_decay;
19498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t  reverb_level;
19598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t speech_prob_start;
19698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t speech_prob_continue;
19798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    noise_suppress;
19898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    echo_suppress;
19998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    echo_suppress_active;
20098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SpeexEchoState *echo_state;
20198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
20298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t	speech_prob;  /**< Probability last frame was speech */
20398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
20498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* DSP-related arrays */
20598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *frame;      /**< Processing frame (2*ps_size) */
20698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *ft;         /**< Processing frame in freq domain (2*ps_size) */
20798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *ps;         /**< Current power spectrum */
20898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *gain2;      /**< Adjusted gains */
20998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *gain_floor; /**< Minimum gain allowed */
21098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *window;     /**< Analysis/Synthesis window */
21198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *noise;      /**< Noise estimate */
21298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *reverb_estimate; /**< Estimate of reverb energy */
21398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *old_ps;     /**< Power spectrum for last frame */
21498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *gain;       /**< Ephraim Malah gain */
21598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *prior;      /**< A-priori SNR */
21698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *post;       /**< A-posteriori SNR */
21798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
21898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *S;          /**< Smoothed power spectrum */
21998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *Smin;       /**< See Cohen paper */
22098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *Stmp;       /**< See Cohen paper */
22198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int *update_prob;         /**< Probability of speech presence for noise update */
22298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
22398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *zeta;       /**< Smoothed a priori SNR */
22498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *echo_noise;
22598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *residual_echo;
22698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
22798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Misc */
22898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *inbuf;      /**< Input buffer (overlapped analysis) */
22998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *outbuf;     /**< Output buffer (for overlap and add) */
23098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
23198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* AGC stuff, only for floating point for now */
23298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
23398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    agc_enabled;
23498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  agc_level;
23598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  loudness_accum;
23698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *loudness_weight;   /**< Perceptual loudness curve */
23798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  loudness;          /**< Loudness estimate */
23898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  agc_gain;          /**< Current AGC gain */
23998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  max_gain;          /**< Maximum gain allowed */
24098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  max_increase_step; /**< Maximum increase in gain from one frame to another */
24198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  max_decrease_step; /**< Maximum decrease in gain from one frame to another */
24298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  prev_loudness;     /**< Loudness of previous frame */
24398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float  init_max;          /**< Current gain limit during initialisation */
24498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
24598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    nb_adapt;          /**< Number of frames used for adaptation so far */
24698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    was_speech;
24798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    min_count;         /**< Number of frames processed so far */
24898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   void  *fft_lookup;        /**< Lookup table for the FFT */
24998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
25098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    frame_shift;
25198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
25298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project};
25398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
25498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
25598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void conj_window(spx_word16_t *w, int len)
25698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
25798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
25898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<len;i++)
25998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
26098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t tmp;
26198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
26298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t x = DIV32_16(MULT16_16(32767,i),len);
26398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
26498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t x = DIV32_16(MULT16_16(QCONST16(4.f,13),i),len);
26598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
26698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int inv=0;
26798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (x<QCONST16(1.f,13))
26898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
26998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      } else if (x<QCONST16(2.f,13))
27098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
27198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x=QCONST16(2.f,13)-x;
27298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         inv=1;
27398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      } else if (x<QCONST16(3.f,13))
27498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
27598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x=x-QCONST16(2.f,13);
27698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         inv=1;
27798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      } else {
27898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x=QCONST16(2.f,13)-x+QCONST16(2.f,13); /* 4 - x */
27998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
28098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      x = MULT16_16_Q14(QCONST16(1.271903f,14), x);
28198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      tmp = SQR16_Q15(QCONST16(.5f,15)-MULT16_16_P15(QCONST16(.5f,15),spx_cos_norm(SHL32(EXTEND32(x),2))));
28298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (inv)
28398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp=SUB16(Q15_ONE,tmp);
28498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      w[i]=spx_sqrt(SHL32(EXTEND32(tmp),15));
28598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
28698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
28798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
28898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
28998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
29098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* This function approximates the gain function
29198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)
29298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   which multiplied by xi/(1+xi) is the optimal gain
29398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   in the loudness domain ( sqrt[amplitude] )
29498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Input in Q11 format, output in Q15
29598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
29698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word32_t hypergeom_gain(spx_word32_t xx)
29798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
29898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int ind;
29998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t frac;
30098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Q13 table */
30198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   static const spx_word16_t table[21] = {
30298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project       6730,  8357,  9868, 11267, 12563, 13770, 14898,
30398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      15959, 16961, 17911, 18816, 19682, 20512, 21311,
30498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      22082, 22827, 23549, 24250, 24931, 25594, 26241};
30598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ind = SHR32(xx,10);
30698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ind<0)
30798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         return Q15_ONE;
30898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ind>19)
30998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         return ADD32(EXTEND32(Q15_ONE),EXTEND32(DIV32_16(QCONST32(.1296,23), SHR32(xx,EXPIN_SHIFT-SNR_SHIFT))));
31098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      frac = SHL32(xx-SHL32(ind,10),5);
31198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return SHL32(DIV32_16(PSHR32(MULT16_16(Q15_ONE-frac,table[ind]) + MULT16_16(frac,table[ind+1]),7),(spx_sqrt(SHL32(xx,15)+6711))),7);
31298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
31398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
31498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word16_t qcurve(spx_word16_t x)
31598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
31698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   x = MAX16(x, 1);
31798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return DIV32_16(SHL32(EXTEND32(32767),9),ADD16(512,MULT16_16_Q15(QCONST16(.60f,15),DIV32_16(32767,x))));
31898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
31998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
32098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Compute the gain floor based on different floors for the background noise and residual echo */
32198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len)
32298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
32398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
32498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
32598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (noise_suppress > effective_echo_suppress)
32698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
32798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t noise_gain, gain_ratio;
32898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      noise_gain = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(0.11513,11),noise_suppress)),1)));
32998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain_ratio = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(.2302585f,11),effective_echo_suppress-noise_suppress)),1)));
33098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
33198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* gain_floor = sqrt [ (noise*noise_floor + echo*echo_floor) / (noise+echo) ] */
33298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<len;i++)
33398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         gain_floor[i] = MULT16_16_Q15(noise_gain,
33498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                                       spx_sqrt(SHL32(EXTEND32(DIV32_16_Q15(PSHR32(noise[i],NOISE_SHIFT) + MULT16_32_Q15(gain_ratio,echo[i]),
33598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                                             (1+PSHR32(noise[i],NOISE_SHIFT) + echo[i]) )),15)));
33698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
33798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t echo_gain, gain_ratio;
33898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      echo_gain = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(0.11513,11),effective_echo_suppress)),1)));
33998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain_ratio = EXTRACT16(MIN32(Q15_ONE,SHR32(spx_exp(MULT16_16(QCONST16(.2302585f,11),noise_suppress-effective_echo_suppress)),1)));
34098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
34198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* gain_floor = sqrt [ (noise*noise_floor + echo*echo_floor) / (noise+echo) ] */
34298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<len;i++)
34398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         gain_floor[i] = MULT16_16_Q15(echo_gain,
34498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                                       spx_sqrt(SHL32(EXTEND32(DIV32_16_Q15(MULT16_32_Q15(gain_ratio,PSHR32(noise[i],NOISE_SHIFT)) + echo[i],
34598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                                             (1+PSHR32(noise[i],NOISE_SHIFT) + echo[i]) )),15)));
34698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
34798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
34898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
34998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
35098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* This function approximates the gain function
35198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   y = gamma(1.25)^2 * M(-.25;1;-x) / sqrt(x)
35298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   which multiplied by xi/(1+xi) is the optimal gain
35398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   in the loudness domain ( sqrt[amplitude] )
35498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
35598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word32_t hypergeom_gain(spx_word32_t xx)
35698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
35798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int ind;
35898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float integer, frac;
35998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float x;
36098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   static const float table[21] = {
36198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      0.82157f, 1.02017f, 1.20461f, 1.37534f, 1.53363f, 1.68092f, 1.81865f,
36298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      1.94811f, 2.07038f, 2.18638f, 2.29688f, 2.40255f, 2.50391f, 2.60144f,
36398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      2.69551f, 2.78647f, 2.87458f, 2.96015f, 3.04333f, 3.12431f, 3.20326f};
36498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      x = EXPIN_SCALING_1*xx;
36598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      integer = floor(2*x);
36698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ind = (int)integer;
36798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ind<0)
36898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         return FRAC_SCALING;
36998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ind>19)
37098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         return FRAC_SCALING*(1+.1296/x);
37198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      frac = 2*x-integer;
37298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return FRAC_SCALING*((1-frac)*table[ind] + frac*table[ind+1])/sqrt(x+.0001f);
37398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
37498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
37598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word16_t qcurve(spx_word16_t x)
37698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
37798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return 1.f/(1.f+.15f/(SNR_SCALING_1*x));
37898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
37998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
38098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void compute_gain_floor(int noise_suppress, int effective_echo_suppress, spx_word32_t *noise, spx_word32_t *echo, spx_word16_t *gain_floor, int len)
38198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
38298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
38398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float echo_floor;
38498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float noise_floor;
38598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
38698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   noise_floor = exp(.2302585f*noise_suppress);
38798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   echo_floor = exp(.2302585f*effective_echo_suppress);
38898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
38998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Compute the gain floor based on different floors for the background noise and residual echo */
39098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<len;i++)
39198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain_floor[i] = FRAC_SCALING*sqrt(noise_floor*PSHR32(noise[i],NOISE_SHIFT) + echo_floor*echo[i])/sqrt(1+PSHR32(noise[i],NOISE_SHIFT) + echo[i]);
39298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
39398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
39498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
39598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate)
39698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
39798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
39898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N, N3, N4, M;
39998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
40098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SpeexPreprocessState *st = (SpeexPreprocessState *)speex_alloc(sizeof(SpeexPreprocessState));
40198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->frame_size = frame_size;
40298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
40398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Round ps_size down to the nearest power of two */
40498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#if 0
40598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   i=1;
40698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ps_size = st->frame_size;
40798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   while(1)
40898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
40998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->ps_size & ~i)
41098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
41198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->ps_size &= ~i;
41298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         i<<=1;
41398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      } else {
41498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         break;
41598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
41698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
41798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
41898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
41998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->ps_size < 3*st->frame_size/4)
42098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->ps_size = st->ps_size * 3 / 2;
42198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
42298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ps_size = st->frame_size;
42398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
42498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
42598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   N = st->ps_size;
42698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   N3 = 2*N - st->frame_size;
42798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   N4 = st->frame_size - N3;
42898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
42998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->sampling_rate = sampling_rate;
43098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->denoise_enabled = 1;
43198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->vad_enabled = 0;
43298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->dereverb_enabled = 0;
43398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->reverb_decay = 0;
43498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->reverb_level = 0;
43598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->noise_suppress = NOISE_SUPPRESS_DEFAULT;
43698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->echo_suppress = ECHO_SUPPRESS_DEFAULT;
43798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->echo_suppress_active = ECHO_SUPPRESS_ACTIVE_DEFAULT;
43898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
43998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->speech_prob_start = SPEECH_PROB_START_DEFAULT;
44098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->speech_prob_continue = SPEECH_PROB_CONTINUE_DEFAULT;
44198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
44298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->echo_state = NULL;
44398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
44498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->nbands = NB_BANDS;
44598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   M = st->nbands;
44698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->bank = filterbank_new(M, sampling_rate, N, 1);
44798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
44898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->frame = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
44998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->window = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
45098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ft = (spx_word16_t*)speex_alloc(2*N*sizeof(spx_word16_t));
45198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
45298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
45398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
45498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->echo_noise = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
45598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->residual_echo = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
45698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->reverb_estimate = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
45798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->old_ps = (spx_word32_t*)speex_alloc((N+M)*sizeof(spx_word32_t));
45898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->prior = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
45998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->post = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
46098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->gain = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
46198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->gain2 = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
46298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->gain_floor = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
46398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->zeta = (spx_word16_t*)speex_alloc((N+M)*sizeof(spx_word16_t));
46498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
46598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->S = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
46698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->Smin = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
46798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->Stmp = (spx_word32_t*)speex_alloc(N*sizeof(spx_word32_t));
46898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->update_prob = (int*)speex_alloc(N*sizeof(int));
46998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
47098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->inbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t));
47198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->outbuf = (spx_word16_t*)speex_alloc(N3*sizeof(spx_word16_t));
47298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
47398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   conj_window(st->window, 2*N3);
47498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=2*N3;i<2*st->ps_size;i++)
47598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->window[i]=Q15_ONE;
47698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
47798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (N4>0)
47898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
47998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=N3-1;i>=0;i--)
48098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
48198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->window[i+N3+N4]=st->window[i+N3];
48298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->window[i+N3]=1;
48398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
48498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
48598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N+M;i++)
48698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
48798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->noise[i]=QCONST32(1.f,NOISE_SHIFT);
48898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->reverb_estimate[i]=0;
48998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->old_ps[i]=1;
49098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->gain[i]=Q15_ONE;
49198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->post[i]=SHL16(1, SNR_SHIFT);
49298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->prior[i]=SHL16(1, SNR_SHIFT);
49398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
49498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
49598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
49698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->update_prob[i] = 1;
49798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N3;i++)
49898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
49998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->inbuf[i]=0;
50098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->outbuf[i]=0;
50198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
50298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
50398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->agc_enabled = 0;
50498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->agc_level = 8000;
50598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->loudness_weight = (float*)speex_alloc(N*sizeof(float));
50698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
50798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
50898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float ff=((float)i)*.5*sampling_rate/((float)N);
50998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*st->loudness_weight[i] = .5f*(1.f/(1.f+ff/8000.f))+1.f*exp(-.5f*(ff-3800.f)*(ff-3800.f)/9e5f);*/
51098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->loudness_weight[i] = .35f-.35f*ff/16000.f+.73f*exp(-.5f*(ff-3800)*(ff-3800)/9e5f);
51198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->loudness_weight[i]<.01f)
51298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->loudness_weight[i]=.01f;
51398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->loudness_weight[i] *= st->loudness_weight[i];
51498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
51598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*st->loudness = pow(AMP_SCALE*st->agc_level,LOUDNESS_EXP);*/
51698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->loudness = 1e-15;
51798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->agc_gain = 1;
51898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->max_gain = 30;
51998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->max_increase_step = exp(0.11513f * 12.*st->frame_size / st->sampling_rate);
52098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->max_decrease_step = exp(-0.11513f * 40.*st->frame_size / st->sampling_rate);
52198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->prev_loudness = 1;
52298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->init_max = 1;
52398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
52498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->was_speech = 0;
52598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
52698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->fft_lookup = spx_fft_init(2*N);
52798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
52898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->nb_adapt=0;
52998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->min_count=0;
53098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return st;
53198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
53298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
53398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_preprocess_state_destroy(SpeexPreprocessState *st)
53498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
53598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->frame);
53698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->ft);
53798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->ps);
53898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->gain2);
53998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->gain_floor);
54098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->window);
54198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->noise);
54298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->reverb_estimate);
54398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->old_ps);
54498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->gain);
54598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->prior);
54698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->post);
54798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
54898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->loudness_weight);
54998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
55098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->echo_noise);
55198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->residual_echo);
55298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
55398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->S);
55498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->Smin);
55598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->Stmp);
55698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->update_prob);
55798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->zeta);
55898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
55998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->inbuf);
56098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->outbuf);
56198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
56298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_fft_destroy(st->fft_lookup);
56398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   filterbank_destroy(st->bank);
56498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st);
56598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
56698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
56798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* FIXME: The AGC doesn't work yet with fixed-point*/
56898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
56998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx_word16_t *ft)
57098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
57198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
57298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N = st->ps_size;
57398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float target_gain;
57498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float loudness=1.f;
57598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float rate;
57698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
57798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=2;i<N;i++)
57898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
57998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      loudness += 2.f*N*st->ps[i]* st->loudness_weight[i];
58098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
58198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   loudness=sqrt(loudness);
58298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*if (loudness < 2*pow(st->loudness, 1.0/LOUDNESS_EXP) &&
58398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   loudness*2 > pow(st->loudness, 1.0/LOUDNESS_EXP))*/
58498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (Pframe>.3f)
58598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
58698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*rate=2.0f*Pframe*Pframe/(1+st->nb_loudness_adapt);*/
58798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      rate = .03*Pframe*Pframe;
58898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP);
58998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->loudness_accum = (1-rate)*st->loudness_accum + rate;
59098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->init_max < st->max_gain && st->nb_adapt > 20)
59198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->init_max *= 1.f + .1f*Pframe*Pframe;
59298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
59398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*printf ("%f %f %f %f\n", Pframe, loudness, pow(st->loudness, 1.0f/LOUDNESS_EXP), st->loudness2);*/
59498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
59598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP);
59698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
59798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if ((Pframe>.5  && st->nb_adapt > 20) || target_gain < st->agc_gain)
59898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
59998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (target_gain > st->max_increase_step*st->agc_gain)
60098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         target_gain = st->max_increase_step*st->agc_gain;
60198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (target_gain < st->max_decrease_step*st->agc_gain && loudness < 10*st->prev_loudness)
60298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         target_gain = st->max_decrease_step*st->agc_gain;
60398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (target_gain > st->max_gain)
60498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         target_gain = st->max_gain;
60598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (target_gain > st->init_max)
60698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         target_gain = st->init_max;
60798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
60898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->agc_gain = target_gain;
60998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
61098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*fprintf (stderr, "%f %f %f\n", loudness, (float)AMP_SCALE_1*pow(st->loudness, 1.0f/LOUDNESS_EXP), st->agc_gain);*/
61198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
61298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<2*N;i++)
61398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ft[i] *= st->agc_gain;
61498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->prev_loudness = loudness;
61598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
61698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
61798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
61898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void preprocess_analysis(SpeexPreprocessState *st, spx_int16_t *x)
61998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
62098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
62198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N = st->ps_size;
62298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N3 = 2*N - st->frame_size;
62398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N4 = st->frame_size - N3;
62498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *ps=st->ps;
62598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
62698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* 'Build' input frame */
62798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N3;i++)
62898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->frame[i]=st->inbuf[i];
62998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<st->frame_size;i++)
63098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->frame[N3+i]=x[i];
63198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
63298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Update inbuf */
63398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N3;i++)
63498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->inbuf[i]=x[N4+i];
63598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
63698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Windowing */
63798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<2*N;i++)
63898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]);
63998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
64098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
64198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
64298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t max_val=0;
64398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<2*N;i++)
64498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         max_val = MAX16(max_val, ABS16(st->frame[i]));
64598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->frame_shift = 14-spx_ilog2(EXTEND32(max_val));
64698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<2*N;i++)
64798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->frame[i] = SHL16(st->frame[i], st->frame_shift);
64898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
64998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
65098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
65198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Perform FFT */
65298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_fft(st->fft_lookup, st->frame, st->ft);
65398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
65498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Power spectrum */
65598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ps[0]=MULT16_16(st->ft[0],st->ft[0]);
65698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=1;i<N;i++)
65798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ps[i]=MULT16_16(st->ft[2*i-1],st->ft[2*i-1]) + MULT16_16(st->ft[2*i],st->ft[2*i]);
65898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
65998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->ps[i] = PSHR32(st->ps[i], 2*st->frame_shift);
66098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
66198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   filterbank_compute_bank32(st->bank, ps, ps+N);
66298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
66398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
66498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic void update_noise_prob(SpeexPreprocessState *st)
66598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
66698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
66798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int min_range;
66898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N = st->ps_size;
66998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
67098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=1;i<N-1;i++)
67198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->S[i] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i-1])
67298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                      + MULT16_32_Q15(QCONST16(.1f,15),st->ps[i]) + MULT16_32_Q15(QCONST16(.05f,15),st->ps[i+1]);
67398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->S[0] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[0]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[0]);
67498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->S[N-1] =  MULT16_32_Q15(QCONST16(.8f,15),st->S[N-1]) + MULT16_32_Q15(QCONST16(.2f,15),st->ps[N-1]);
67598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
67698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->nb_adapt==1)
67798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
67898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N;i++)
67998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->Smin[i] = st->Stmp[i] = 0;
68098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
68198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
68298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->nb_adapt < 100)
68398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      min_range = 15;
68498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   else if (st->nb_adapt < 1000)
68598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      min_range = 50;
68698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   else if (st->nb_adapt < 10000)
68798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      min_range = 150;
68898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   else
68998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      min_range = 300;
69098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->min_count > min_range)
69198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
69298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->min_count = 0;
69398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N;i++)
69498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
69598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->Smin[i] = MIN32(st->Stmp[i], st->S[i]);
69698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->Stmp[i] = st->S[i];
69798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
69898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
69998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N;i++)
70098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
70198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->Smin[i] = MIN32(st->Smin[i], st->S[i]);
70298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->Stmp[i] = MIN32(st->Stmp[i], st->S[i]);
70398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
70498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
70598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
70698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
70798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (MULT16_32_Q15(QCONST16(.4f,15),st->S[i]) > st->Smin[i])
70898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->update_prob[i] = 1;
70998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      else
71098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->update_prob[i] = 0;
71198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*fprintf (stderr, "%f ", st->S[i]/st->Smin[i]);*/
71298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*fprintf (stderr, "%f ", st->update_prob[i]);*/
71398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
71498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
71598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
71698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
71798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NOISE_OVERCOMPENS 1.
71898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
71998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *Yout, int len);
72098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
72198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo)
72298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
72398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return speex_preprocess_run(st, x);
72498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
72598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
72698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x)
72798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
72898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
72998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int M;
73098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N = st->ps_size;
73198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N3 = 2*N - st->frame_size;
73298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N4 = st->frame_size - N3;
73398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *ps=st->ps;
73498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t Zframe;
73598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t Pframe;
73698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t beta, beta_1;
73798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t effective_echo_suppress;
73898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
73998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->nb_adapt++;
74098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->nb_adapt>20000)
74198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->nb_adapt = 20000;
74298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->min_count++;
74398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
74498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   beta = MAX16(QCONST16(.03,15),DIV32_16(Q15_ONE,st->nb_adapt));
74598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   beta_1 = Q15_ONE-beta;
74698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   M = st->nbands;
74798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Deal with residual echo if provided */
74898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->echo_state)
74998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
75098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      speex_echo_get_residual(st->echo_state, st->residual_echo, N);
75198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
75298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* If there are NaNs or ridiculous values, it'll show up in the DC and we just reset everything to zero */
75398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (!(st->residual_echo[0] >=0 && st->residual_echo[0]<N*1e9f))
75498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
75598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         for (i=0;i<N;i++)
75698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            st->residual_echo[i] = 0;
75798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
75898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
75998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N;i++)
76098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->echo_noise[i] = MAX32(MULT16_32_Q15(QCONST16(.6f,15),st->echo_noise[i]), st->residual_echo[i]);
76198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      filterbank_compute_bank32(st->bank, st->echo_noise, st->echo_noise+N);
76298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
76398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N+M;i++)
76498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->echo_noise[i] = 0;
76598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
76698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   preprocess_analysis(st, x);
76798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
76898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   update_noise_prob(st);
76998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
77098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Noise estimation always updated for the 10 first frames */
77198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*if (st->nb_adapt<10)
77298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
77398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=1;i<N-1;i++)
77498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->update_prob[i] = 0;
77598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
77698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   */
77798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
77898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Update the noise estimate for the frequencies where it can be */
77998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
78098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
78198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i], NOISE_SHIFT))
78298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->noise[i] = MAX32(EXTEND32(0),MULT16_32_Q15(beta_1,st->noise[i]) + MULT16_32_Q15(beta,SHL32(st->ps[i],NOISE_SHIFT)));
78398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
78498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   filterbank_compute_bank32(st->bank, st->noise, st->noise+N);
78598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
78698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Special case for first frame */
78798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->nb_adapt==1)
78898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N+M;i++)
78998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->old_ps[i] = ps[i];
79098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
79198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Compute a posteriori SNR */
79298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N+M;i++)
79398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
79498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t gamma;
79598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
79698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Total noise estimate including residual echo and reverberation */
79798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(st->noise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]);
79898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
79998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* A posteriori SNR = ps/noise - 1*/
80098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT));
80198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT));
80298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
80398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Computing update gamma = .1 + .9*(old/(old+noise))^2 */
80498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise))));
80598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
80698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* A priori SNR update = gamma*max(0,post) + (1-gamma)*old/noise */
80798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15));
80898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT));
80998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
81098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
81198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*print_vec(st->post, N+M, "");*/
81298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
81398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Recursive average of the a priori SNR. A bit smoothed for the psd components */
81498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->zeta[0] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[0]), MULT16_16(QCONST16(.3f,15),st->prior[0])),15);
81598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=1;i<N-1;i++)
81698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->zeta[i] = PSHR32(ADD32(ADD32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.15f,15),st->prior[i])),
81798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                           MULT16_16(QCONST16(.075f,15),st->prior[i-1])), MULT16_16(QCONST16(.075f,15),st->prior[i+1])),15);
81898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=N-1;i<N+M;i++)
81998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->zeta[i] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.3f,15),st->prior[i])),15);
82098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
82198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Speech probability of presence for the entire frame is based on the average filterbank a priori SNR */
82298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Zframe = 0;
82398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=N;i<N+M;i++)
82498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      Zframe = ADD32(Zframe, EXTEND32(st->zeta[i]));
82598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands)));
82698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
82798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15));
82898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
82998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M);
83098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
83198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Compute Ephraim & Malah gain speech probability of presence for each critical band (Bark scale)
83298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      Technically this is actually wrong because the EM gaim assumes a slightly different probability
83398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      distribution */
83498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=N;i<N+M;i++)
83598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
83698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* See EM and Cohen papers*/
83798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t theta;
83898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Gain from hypergeometric function */
83998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t MM;
84098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Weiner filter gain */
84198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t prior_ratio;
84298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* a priority probability of speech presence based on Bark sub-band alone */
84398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t P1;
84498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Speech absence a priori probability (considering sub-band and frame) */
84598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t q;
84698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
84798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t tmp;
84898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
84998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
85098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
85198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));
85298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
85398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      MM = hypergeom_gain(theta);
85498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Gain with bound */
85598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->gain[i] = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
85698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Save old Bark power spectrum */
85798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]);
85898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
85998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      P1 = QCONST16(.199f,15)+MULT16_16_Q15(QCONST16(.8f,15),qcurve (st->zeta[i]));
86098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      q = Q15_ONE-MULT16_16_Q15(Pframe,P1);
86198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
86298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      theta = MIN32(theta, EXTEND32(32767));
86398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/*Q8*/tmp = MULT16_16_Q15((SHL32(1,SNR_SHIFT)+st->prior[i]),EXTRACT16(MIN32(Q15ONE,SHR32(spx_exp(-EXTRACT16(theta)),1))));
86498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      tmp = MIN16(QCONST16(3.,SNR_SHIFT), tmp); /* Prevent overflows in the next line*/
86598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/*Q8*/tmp = EXTRACT16(PSHR32(MULT16_16(PDIV32_16(SHL32(EXTEND32(q),8),(Q15_ONE-q)),tmp),8));
86698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->gain2[i]=DIV32_16(SHL32(EXTEND32(32767),SNR_SHIFT), ADD16(256,tmp));
86798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
86898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->gain2[i]=1/(1.f + (q/(1.f-q))*(1+st->prior[i])*exp(-theta));
86998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
87098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
87198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Convert the EM gains and speech prob to linear frequency */
87298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
87398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   filterbank_compute_psd16(st->bank,st->gain+N, st->gain);
87498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
87598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Use 1 for linear gain resolution (best) or 0 for Bark gain resolution (faster) */
87698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (1)
87798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
87898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      filterbank_compute_psd16(st->bank,st->gain_floor+N, st->gain_floor);
87998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
88098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Compute gain according to the Ephraim-Malah algorithm -- linear frequency */
88198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N;i++)
88298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
88398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word32_t MM;
88498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word32_t theta;
88598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t prior_ratio;
88698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t tmp;
88798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t p;
88898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t g;
88998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
89098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Wiener filter gain */
89198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
89298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));
89398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
89498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Optimal estimator for loudness domain */
89598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         MM = hypergeom_gain(theta);
89698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* EM gain with bound */
89798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         g = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
89898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Interpolated speech probability of presence */
89998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         p = st->gain2[i];
90098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
90198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Constrain the gain to be close to the Bark scale gain */
90298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i])
90398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            g = MULT16_16(3,st->gain[i]);
90498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->gain[i] = g;
90598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
90698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Save old power spectrum */
90798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]);
90898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
90998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Apply gain floor */
91098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (st->gain[i] < st->gain_floor[i])
91198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            st->gain[i] = st->gain_floor[i];
91298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
91398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Exponential decay model for reverberation (unused) */
91498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /*st->reverb_estimate[i] = st->reverb_decay*st->reverb_estimate[i] + st->reverb_decay*st->reverb_level*st->gain[i]*st->gain[i]*st->ps[i];*/
91598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
91698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Take into account speech probability of presence (loudness domain MMSE estimator) */
91798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* gain2 = [p*sqrt(gain)+(1-p)*sqrt(gain _floor) ]^2 */
91898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
91998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->gain2[i]=SQR16_Q15(tmp);
92098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
92198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Use this if you want a log-domain MMSE estimator instead */
92298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /*st->gain2[i] = pow(st->gain[i], p) * pow(st->gain_floor[i],1.f-p);*/
92398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
92498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
92598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=N;i<N+M;i++)
92698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
92798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t tmp;
92898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t p = st->gain2[i];
92998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->gain[i] = MAX16(st->gain[i], st->gain_floor[i]);
93098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
93198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->gain2[i]=SQR16_Q15(tmp);
93298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
93398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
93498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
93598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
93698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* If noise suppression is off, don't apply the gain (but then why call this in the first place!) */
93798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (!st->denoise_enabled)
93898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
93998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<N+M;i++)
94098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->gain2[i]=Q15_ONE;
94198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
94298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
94398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Apply computed gain */
94498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=1;i<N;i++)
94598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
94698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->ft[2*i-1] = MULT16_16_P15(st->gain2[i],st->ft[2*i-1]);
94798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->ft[2*i] = MULT16_16_P15(st->gain2[i],st->ft[2*i]);
94898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
94998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ft[0] = MULT16_16_P15(st->gain2[0],st->ft[0]);
95098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ft[2*N-1] = MULT16_16_P15(st->gain2[N-1],st->ft[2*N-1]);
95198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
95298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*FIXME: This *will* not work for fixed-point */
95398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
95498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->agc_enabled)
95598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      speex_compute_agc(st, Pframe, st->ft);
95698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
95798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
95898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Inverse FFT with 1/N scaling */
95998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_ifft(st->fft_lookup, st->ft, st->frame);
96098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Scale back to original (lower) amplitude */
96198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<2*N;i++)
96298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->frame[i] = PSHR16(st->frame[i], st->frame_shift);
96398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
96498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*FIXME: This *will* not work for fixed-point */
96598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
96698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->agc_enabled)
96798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
96898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float max_sample=0;
96998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<2*N;i++)
97098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (fabs(st->frame[i])>max_sample)
97198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            max_sample = fabs(st->frame[i]);
97298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (max_sample>28000.f)
97398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
97498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         float damp = 28000.f/max_sample;
97598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         for (i=0;i<2*N;i++)
97698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            st->frame[i] *= damp;
97798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
97898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
97998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
98098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
98198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Synthesis window (for WOLA) */
98298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<2*N;i++)
98398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->frame[i] = MULT16_16_Q15(st->frame[i], st->window[i]);
98498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
98598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Perform overlap and add */
98698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N3;i++)
98798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      x[i] = st->outbuf[i] + st->frame[i];
98898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N4;i++)
98998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      x[N3+i] = st->frame[N3+i];
99098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
99198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Update outbuf */
99298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N3;i++)
99398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->outbuf[i] = st->frame[st->frame_size+i];
99498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
99598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* FIXME: This VAD is a kludge */
99698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->speech_prob = Pframe;
99798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (st->vad_enabled)
99898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
99998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->speech_prob > st->speech_prob_start || (st->was_speech && st->speech_prob > st->speech_prob_continue))
100098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
100198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->was_speech=1;
100298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         return 1;
100398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      } else
100498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
100598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->was_speech=0;
100698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         return 0;
100798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
100898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   } else {
100998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return 1;
101098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
101198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
101298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
101398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x)
101498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
101598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
101698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N = st->ps_size;
101798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N3 = 2*N - st->frame_size;
101898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int M;
101998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *ps=st->ps;
102098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
102198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   M = st->nbands;
102298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->min_count++;
102398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
102498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   preprocess_analysis(st, x);
102598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
102698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   update_noise_prob(st);
102798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
102898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=1;i<N-1;i++)
102998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
103098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i],NOISE_SHIFT))
103198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
103298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->noise[i] = MULT16_32_Q15(QCONST16(.95f,15),st->noise[i]) + MULT16_32_Q15(QCONST16(.05f,15),SHL32(st->ps[i],NOISE_SHIFT));
103398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
103498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
103598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
103698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N3;i++)
103798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->outbuf[i] = MULT16_16_Q15(x[st->frame_size-N3+i],st->window[st->frame_size+i]);
103898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
103998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Save old power spectrum */
104098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N+M;i++)
104198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->old_ps[i] = ps[i];
104298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
104398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
104498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->reverb_estimate[i] = MULT16_32_Q15(st->reverb_decay, st->reverb_estimate[i]);
104598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
104698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
104798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
104898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT int speex_preprocess_ctl(SpeexPreprocessState *state, int request, void *ptr)
104998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
105098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
105198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SpeexPreprocessState *st;
105298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st=(SpeexPreprocessState*)state;
105398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   switch(request)
105498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
105598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_DENOISE:
105698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->denoise_enabled = (*(spx_int32_t*)ptr);
105798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
105898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_DENOISE:
105998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->denoise_enabled;
106098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
106198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
106298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_AGC:
106398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->agc_enabled = (*(spx_int32_t*)ptr);
106498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
106598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC:
106698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->agc_enabled;
106798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
106898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef DISABLE_FLOAT_API
106998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_AGC_LEVEL:
107098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->agc_level = (*(float*)ptr);
107198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->agc_level<1)
107298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->agc_level=1;
107398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->agc_level>32768)
107498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->agc_level=32768;
107598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
107698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_LEVEL:
107798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(float*)ptr) = st->agc_level;
107898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
107998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif /* #ifndef DISABLE_FLOAT_API */
108098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_AGC_INCREMENT:
108198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->max_increase_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate);
108298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
108398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_INCREMENT:
108498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_increase_step)*st->sampling_rate/st->frame_size);
108598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
108698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_AGC_DECREMENT:
108798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->max_decrease_step = exp(0.11513f * (*(spx_int32_t*)ptr)*st->frame_size / st->sampling_rate);
108898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
108998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_DECREMENT:
109098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_decrease_step)*st->sampling_rate/st->frame_size);
109198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
109298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_AGC_MAX_GAIN:
109398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->max_gain = exp(0.11513f * (*(spx_int32_t*)ptr));
109498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
109598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_MAX_GAIN:
109698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->max_gain));
109798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
109898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
109998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_VAD:
110098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      // Disabled by mlebeau, we don't want this in the launched Google Mobile App for iPhone.
110198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      //speex_warning("The VAD has been replaced by a hack pending a complete rewrite");
110298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->vad_enabled = (*(spx_int32_t*)ptr);
110398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
110498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_VAD:
110598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->vad_enabled;
110698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
110798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
110898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_DEREVERB:
110998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->dereverb_enabled = (*(spx_int32_t*)ptr);
111098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<st->ps_size;i++)
111198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->reverb_estimate[i]=0;
111298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
111398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_DEREVERB:
111498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->dereverb_enabled;
111598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
111698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
111798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_DEREVERB_LEVEL:
111898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* FIXME: Re-enable when de-reverberation is actually enabled again */
111998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*st->reverb_level = (*(float*)ptr);*/
112098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
112198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_DEREVERB_LEVEL:
112298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* FIXME: Re-enable when de-reverberation is actually enabled again */
112398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*(*(float*)ptr) = st->reverb_level;*/
112498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
112598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
112698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_DEREVERB_DECAY:
112798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* FIXME: Re-enable when de-reverberation is actually enabled again */
112898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*st->reverb_decay = (*(float*)ptr);*/
112998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
113098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_DEREVERB_DECAY:
113198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* FIXME: Re-enable when de-reverberation is actually enabled again */
113298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*(*(float*)ptr) = st->reverb_decay;*/
113398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
113498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
113598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_PROB_START:
113698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr));
113798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->speech_prob_start = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100);
113898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
113998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_PROB_START:
114098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_start, 100);
114198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
114298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
114398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_PROB_CONTINUE:
114498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      *(spx_int32_t*)ptr = MIN32(100,MAX32(0, *(spx_int32_t*)ptr));
114598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->speech_prob_continue = DIV32_16(MULT16_16(Q15ONE,*(spx_int32_t*)ptr), 100);
114698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
114798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_PROB_CONTINUE:
114898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob_continue, 100);
114998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
115098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
115198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_NOISE_SUPPRESS:
115298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->noise_suppress = -ABS(*(spx_int32_t*)ptr);
115398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
115498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_NOISE_SUPPRESS:
115598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->noise_suppress;
115698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
115798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_ECHO_SUPPRESS:
115898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->echo_suppress = -ABS(*(spx_int32_t*)ptr);
115998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
116098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_ECHO_SUPPRESS:
116198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->echo_suppress;
116298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
116398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE:
116498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->echo_suppress_active = -ABS(*(spx_int32_t*)ptr);
116598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
116698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE:
116798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->echo_suppress_active;
116898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
116998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_ECHO_STATE:
117098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->echo_state = (SpeexEchoState*)ptr;
117198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
117298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_ECHO_STATE:
117398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(SpeexEchoState**)ptr) = (SpeexEchoState*)st->echo_state;
117498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
117598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
117698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_LOUDNESS:
117798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = pow(st->loudness, 1.0/LOUDNESS_EXP);
117898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
117998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_GAIN:
118098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = floor(.5+8.6858*log(st->agc_gain));
118198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
118298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
118398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_PSD_SIZE:
118498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE:
118598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->ps_size;
118698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
118798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_PSD:
118898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for(i=0;i<st->ps_size;i++)
118998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      	((spx_int32_t *)ptr)[i] = (spx_int32_t) st->ps[i];
119098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
119198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_NOISE_PSD:
119298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for(i=0;i<st->ps_size;i++)
119398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      	((spx_int32_t *)ptr)[i] = (spx_int32_t) PSHR32(st->noise[i], NOISE_SHIFT);
119498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
119598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_PROB:
119698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = MULT16_16_Q15(st->speech_prob, 100);
119798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
119898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef FIXED_POINT
119998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_SET_AGC_TARGET:
120098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->agc_level = (*(spx_int32_t*)ptr);
120198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->agc_level<1)
120298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->agc_level=1;
120398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (st->agc_level>32768)
120498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->agc_level=32768;
120598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
120698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   case SPEEX_PREPROCESS_GET_AGC_TARGET:
120798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      (*(spx_int32_t*)ptr) = st->agc_level;
120898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      break;
120998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
121098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   default:
121198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      speex_warning_int("Unknown speex_preprocess_ctl request: ", request);
121298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return -1;
121398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
121498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return 0;
121598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
121698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
121798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_DEBUG
121898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectlong long spx_mips=0;
121998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
122098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1221