16f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/*
26f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
36f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
46f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  Use of this source code is governed by a BSD-style license
56f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  that can be found in the LICENSE file in the root of the source
66f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  tree. An additional intellectual property rights grant can be found
76f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  in the file PATENTS.  All contributing project authors may
86f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  be found in the AUTHORS file in the root of the source tree.
96f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include "pitch_estimator.h"
126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include <math.h>
146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include <memory.h>
156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include <stdlib.h>
166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include "os_specific_inline.h"
186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/*
206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * We are implementing the following filters;
216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Pre-filtering:
236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   y(z) = x(z) + damper(z) * gain * (x(z) + y(z)) * z ^ (-lag);
246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Post-filtering:
266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   y(z) = x(z) - damper(z) * gain * (x(z) + y(z)) * z ^ (-lag);
276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Note that |lag| is a floating number so we perform an interpolation to
296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * obtain the correct |lag|.
306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinstatic const double kDampFilter[PITCH_DAMPORDER] = {-0.07, 0.25, 0.64, 0.25,
346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    -0.07};
356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/* interpolation coefficients; generated by design_pitch_filter.m */
376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinstatic const double kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {-0.02239172458614,  0.06653315052934, -0.16515880017569,  0.60701333734125,
396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.64671399919202, -0.20249000396417,  0.09926548334755, -0.04765933793109,
406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.01754159521746},
416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {-0.01985640750434,  0.05816126837866, -0.13991265473714,  0.44560418147643,
426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.79117042386876, -0.20266133815188,  0.09585268418555, -0.04533310458084,
436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.01654127246314},
446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {-0.01463300534216,  0.04229888475060, -0.09897034715253,  0.28284326017787,
456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.90385267956632, -0.16976950138649,  0.07704272393639, -0.03584218578311,
466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.01295781500709},
476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {-0.00764851320885,  0.02184035544377, -0.04985561057281,  0.13083306574393,
486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.97545011664662, -0.10177807997561,  0.04400901776474, -0.02010737175166,
496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.00719783432422},
506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {-0.00000000000000,  0.00000000000000, -0.00000000000001,  0.00000000000001,
516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.99999999999999,  0.00000000000001, -0.00000000000001,  0.00000000000000,
526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     -0.00000000000000},
536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {0.00719783432422, -0.02010737175166,  0.04400901776474, -0.10177807997562,
546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.97545011664663,  0.13083306574393, -0.04985561057280,  0.02184035544377,
556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     -0.00764851320885},
566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {0.01295781500710, -0.03584218578312,  0.07704272393640, -0.16976950138650,
576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.90385267956634,  0.28284326017785, -0.09897034715252,  0.04229888475059,
586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     -0.01463300534216},
596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {0.01654127246315, -0.04533310458085,  0.09585268418557, -0.20266133815190,
606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     0.79117042386878,  0.44560418147640, -0.13991265473712,  0.05816126837865,
616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     -0.01985640750433}
626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin};
636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/*
656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Enumerating the operation of the filter.
666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * iSAC has 4 different pitch-filter which are very similar in their structure.
676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * kPitchFilterPre     : In this mode the filter is operating as pitch
696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       pre-filter. This is used at the encoder.
706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * kPitchFilterPost    : In this mode the filter is operating as pitch
716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       post-filter. This is the inverse of pre-filter and used
726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       in the decoder.
736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * kPitchFilterPreLa   : This is, in structure, similar to pre-filtering but
746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       utilizing 3 millisecond lookahead. It is used to
756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       obtain the signal for LPC analysis.
766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * kPitchFilterPreGain : This is, in structure, similar to pre-filtering but
776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       differential changes in gain is considered. This is
786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                       used to find the optimal gain.
796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkintypedef enum {
816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  kPitchFilterPre, kPitchFilterPost, kPitchFilterPreLa, kPitchFilterPreGain
826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin} PitchFilterOperation;
836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/*
856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Structure with parameters used for pitch-filtering.
866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * buffer           : a buffer where the sum of previous inputs and outputs
876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                    are stored.
886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * damper_state     : the state of the damping filter. The filter is defined by
896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                    |kDampFilter|.
906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * interpol_coeff   : pointer to a set of coefficient which are used to utilize
916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                    fractional pitch by interpolation.
926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * gain             : pitch-gain to be applied to the current segment of input.
936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * lag              : pitch-lag for the current segment of input.
946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * lag_offset       : the offset of lag w.r.t. current sample.
956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * sub_frame        : sub-frame index, there are 4 pitch sub-frames in an iSAC
966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                    frame.
976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                    This specifies the usage of the filter. See
986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                    'PitchFilterOperation' for operational modes.
996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * num_samples      : number of samples to be processed in each segment.
1006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * index            : index of the input and output sample.
1016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * damper_state_dg  : state of damping filter for different trial gains.
1026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * gain_mult        : differential changes to gain.
1036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
1046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkintypedef struct {
1056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double buffer[PITCH_INTBUFFSIZE + QLOOKAHEAD];
1066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double damper_state[PITCH_DAMPORDER];
1076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double *interpol_coeff;
1086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double gain;
1096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double lag;
1106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int lag_offset;
1116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int sub_frame;
1136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  PitchFilterOperation mode;
1146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int num_samples;
1156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int index;
1166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double damper_state_dg[4][PITCH_DAMPORDER];
1186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double gain_mult[4];
1196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin} PitchFilterParam;
1206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/**********************************************************************
1226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * FilterSegment()
1236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Filter one segment, a quarter of a frame.
1246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
1256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Inputs
1266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   in_data      : pointer to the input signal of 30 ms at 8 kHz sample-rate.
1276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   filter_param : pitch filter parameters.
1286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
1296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Outputs
1306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   out_data     : pointer to a buffer where the filtered signal is written to.
1316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   out_dg       : [only used in kPitchFilterPreGain] pointer to a buffer
1326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                  where the output of different gain values (differential
1336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                  change to gain) is written.
1346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
1356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinstatic void FilterSegment(const double* in_data, PitchFilterParam* parameters,
1366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                          double* out_data,
1376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                          double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) {
1386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int n;
1396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int m;
1406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int j;
1416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double sum;
1426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double sum2;
1436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Index of |parameters->buffer| where the output is written to. */
1446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int pos = parameters->index + PITCH_BUFFSIZE;
1456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Index of |parameters->buffer| where samples are read for fractional-lag
1466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin   * computation. */
1476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int pos_lag = pos - parameters->lag_offset;
1486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (n = 0; n < parameters->num_samples; ++n) {
1506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Shift low pass filter states. */
1516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (m = PITCH_DAMPORDER - 1; m > 0; --m) {
1526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      parameters->damper_state[m] = parameters->damper_state[m - 1];
1536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
1546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Filter to get fractional pitch. */
1556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    sum = 0.0;
1566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (m = 0; m < PITCH_FRACORDER; ++m) {
1576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      sum += parameters->buffer[pos_lag + m] * parameters->interpol_coeff[m];
1586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
1596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Multiply with gain. */
1606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    parameters->damper_state[0] = parameters->gain * sum;
1616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if (parameters->mode == kPitchFilterPreGain) {
1636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      int lag_index = parameters->index - parameters->lag_offset;
1646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      int m_tmp = (lag_index < 0) ? -lag_index : 0;
1656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* Update the damper state for the new sample. */
1666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (m = PITCH_DAMPORDER - 1; m > 0; --m) {
1676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        for (j = 0; j < 4; ++j) {
1686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin          parameters->damper_state_dg[j][m] =
1696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin              parameters->damper_state_dg[j][m - 1];
1706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        }
1716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
1726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (j = 0; j < parameters->sub_frame + 1; ++j) {
1746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        /* Filter for fractional pitch. */
1756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        sum2 = 0.0;
1766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        for (m = PITCH_FRACORDER-1; m >= m_tmp; --m) {
1776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin          /* |lag_index + m| is always larger than or equal to zero, see how
1786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin           * m_tmp is computed. This is equivalent to assume samples outside
1796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin           * |out_dg[j]| are zero. */
1806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin          sum2 += out_dg[j][lag_index + m] * parameters->interpol_coeff[m];
1816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        }
1826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        /* Add the contribution of differential gain change. */
1836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        parameters->damper_state_dg[j][0] = parameters->gain_mult[j] * sum +
1846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin            parameters->gain * sum2;
1856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
1866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* Filter with damping filter, and store the results. */
1886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (j = 0; j < parameters->sub_frame + 1; ++j) {
1896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        sum = 0.0;
1906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        for (m = 0; m < PITCH_DAMPORDER; ++m) {
1916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin          sum -= parameters->damper_state_dg[j][m] * kDampFilter[m];
1926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        }
1936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        out_dg[j][parameters->index] = sum;
1946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
1956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
1966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Filter with damping filter. */
1976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    sum = 0.0;
1986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (m = 0; m < PITCH_DAMPORDER; ++m) {
1996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      sum += parameters->damper_state[m] * kDampFilter[m];
2006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Subtract from input and update buffer. */
2036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    out_data[parameters->index] = in_data[parameters->index] - sum;
2046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    parameters->buffer[pos] = in_data[parameters->index] +
2056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        out_data[parameters->index];
2066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    ++parameters->index;
2086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    ++pos;
2096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    ++pos_lag;
2106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
2116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  return;
2126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
2136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/* Update filter parameters based on the pitch-gains and pitch-lags. */
2156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinstatic void Update(PitchFilterParam* parameters) {
2166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double fraction;
2176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int fraction_index;
2186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Compute integer lag-offset. */
2196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  parameters->lag_offset = WebRtcIsac_lrint(parameters->lag + PITCH_FILTDELAY +
2206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                            0.5);
2216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Find correct set of coefficients for computing fractional pitch. */
2226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  fraction = parameters->lag_offset - (parameters->lag + PITCH_FILTDELAY);
2236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  fraction_index = WebRtcIsac_lrint(PITCH_FRACS * fraction - 0.5);
2246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  parameters->interpol_coeff = kIntrpCoef[fraction_index];
2256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  if (parameters->mode == kPitchFilterPreGain) {
2276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* If in this mode make a differential change to pitch gain. */
2286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    parameters->gain_mult[parameters->sub_frame] += 0.2;
2296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if (parameters->gain_mult[parameters->sub_frame] > 1.0) {
2306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      parameters->gain_mult[parameters->sub_frame] = 1.0;
2316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if (parameters->sub_frame > 0) {
2336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      parameters->gain_mult[parameters->sub_frame - 1] -= 0.2;
2346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
2366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
2376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/******************************************************************************
2396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * FilterFrame()
2406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Filter a frame of 30 millisecond, given pitch-lags and pitch-gains.
2416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
2426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Inputs
2436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   in_data     : pointer to the input signal of 30 ms at 8 kHz sample-rate.
2446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   lags        : pointer to pitch-lags, 4 lags per frame.
2456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   gains       : pointer to pitch-gians, 4 gains per frame.
2466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   mode        : defining the functionality of the filter. It takes the
2476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 following values.
2486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 kPitchFilterPre:     Pitch pre-filter, used at encoder.
2496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 kPitchFilterPost:    Pitch post-filter, used at decoder.
2506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 kPitchFilterPreLa:   Pitch pre-filter with lookahead.
2516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 kPitchFilterPreGain: Pitch pre-filter used to otain optimal
2526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                                      pitch-gains.
2536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
2546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Outputs
2556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   out_data    : pointer to a buffer where the filtered signal is written to.
2566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *   out_dg      : [only used in kPitchFilterPreGain] pointer to a buffer
2576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 where the output of different gain values (differential
2586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                 change to gain) is written.
2596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
2606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinstatic void FilterFrame(const double* in_data, PitchFiltstr* filter_state,
2616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                        double* lags, double* gains, PitchFilterOperation mode,
2626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                        double* out_data,
2636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                        double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD]) {
2646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  PitchFilterParam filter_parameters;
2656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double gain_delta, lag_delta;
2666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double old_lag, old_gain;
2676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int n;
2686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int m;
2696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double kEnhancer = 1.3;
2706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Set up buffer and states. */
2726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  filter_parameters.index = 0;
2736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  filter_parameters.lag_offset = 0;
2746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  filter_parameters.mode = mode;
2756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Copy states to local variables. */
2766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  memcpy(filter_parameters.buffer, filter_state->ubuf,
2776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin         sizeof(filter_state->ubuf));
2786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  memcpy(filter_parameters.damper_state, filter_state->ystate,
2796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin         sizeof(filter_state->ystate));
2806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  if (mode == kPitchFilterPreGain) {
2826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Clear buffers. */
2836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    memset(filter_parameters.gain_mult, 0, sizeof(filter_parameters.gain_mult));
2846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    memset(filter_parameters.damper_state_dg, 0,
2856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin           sizeof(filter_parameters.damper_state_dg));
2866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n < PITCH_SUBFRAMES; ++n) {
2876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      //memset(out_dg[n], 0, sizeof(double) * (PITCH_FRAME_LEN + QLOOKAHEAD));
2886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      memset(out_dg[n], 0, sizeof(out_dg[n]));
2896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  } else if (mode == kPitchFilterPost) {
2916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Make output more periodic. Negative sign is to change the structure
2926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     * of the filter. */
2936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n < PITCH_SUBFRAMES; ++n) {
2946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      gains[n] *= -kEnhancer;
2956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
2976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  old_lag = *filter_state->oldlagp;
2996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  old_gain = *filter_state->oldgainp;
3006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* No interpolation if pitch lag step is big. */
3026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  if ((lags[0] > (PITCH_UPSTEP * old_lag)) ||
3036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      (lags[0] < (PITCH_DOWNSTEP * old_lag))) {
3046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    old_lag = lags[0];
3056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    old_gain = gains[0];
3066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if (mode == kPitchFilterPreGain) {
3086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      filter_parameters.gain_mult[0] = 1.0;
3096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
3116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  filter_parameters.num_samples = PITCH_UPDATE;
3136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (m = 0; m < PITCH_SUBFRAMES; ++m) {
3146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Set the sub-frame value. */
3156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    filter_parameters.sub_frame = m;
3166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Calculate interpolation steps for pitch-lag and pitch-gain. */
3176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    lag_delta = (lags[m] - old_lag) / PITCH_GRAN_PER_SUBFRAME;
3186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    filter_parameters.lag = old_lag;
3196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    gain_delta = (gains[m] - old_gain) / PITCH_GRAN_PER_SUBFRAME;
3206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    filter_parameters.gain = old_gain;
3216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Store for the next sub-frame. */
3226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    old_lag = lags[m];
3236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    old_gain = gains[m];
3246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n < PITCH_GRAN_PER_SUBFRAME; ++n) {
3266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* Step-wise interpolation of pitch gains and lags. As pitch-lag changes,
3276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin       * some parameters of filter need to be update. */
3286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      filter_parameters.gain += gain_delta;
3296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      filter_parameters.lag += lag_delta;
3306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* Update parameters according to new lag value. */
3316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      Update(&filter_parameters);
3326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* Filter a segment of input. */
3336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      FilterSegment(in_data, &filter_parameters, out_data, out_dg);
3346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
3366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  if (mode != kPitchFilterPreGain) {
3386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Export buffer and states. */
3396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    memcpy(filter_state->ubuf, &filter_parameters.buffer[PITCH_FRAME_LEN],
3406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin           sizeof(filter_state->ubuf));
3416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    memcpy(filter_state->ystate, filter_parameters.damper_state,
3426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin           sizeof(filter_state->ystate));
3436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Store for the next frame. */
3456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    *filter_state->oldlagp = old_lag;
3466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    *filter_state->oldgainp = old_gain;
3476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
3486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  if ((mode == kPitchFilterPreGain) || (mode == kPitchFilterPreLa)) {
3506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Filter the lookahead segment, this is treated as the last sub-frame. So
3516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     * set |pf_param| to last sub-frame. */
3526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    filter_parameters.sub_frame = PITCH_SUBFRAMES - 1;
3536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    filter_parameters.num_samples = QLOOKAHEAD;
3546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    FilterSegment(in_data, &filter_parameters, out_data, out_dg);
3556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
3566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
3576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid WebRtcIsac_PitchfilterPre(double* in_data, double* out_data,
3596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                               PitchFiltstr* pf_state, double* lags,
3606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                               double* gains) {
3616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPre, out_data, NULL);
3626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
3636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid WebRtcIsac_PitchfilterPre_la(double* in_data, double* out_data,
3656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                  PitchFiltstr* pf_state, double* lags,
3666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                  double* gains) {
3676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreLa, out_data,
3686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin              NULL);
3696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
3706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid WebRtcIsac_PitchfilterPre_gains(
3726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double* in_data, double* out_data,
3736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double out_dg[][PITCH_FRAME_LEN + QLOOKAHEAD], PitchFiltstr *pf_state,
3746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double* lags, double* gains) {
3756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPreGain, out_data,
3766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin              out_dg);
3776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
3786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid WebRtcIsac_PitchfilterPost(double* in_data, double* out_data,
3806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                PitchFiltstr* pf_state, double* lags,
3816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                double* gains) {
3826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  FilterFrame(in_data, pf_state, lags, gains, kPitchFilterPost, out_data, NULL);
3836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
384