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