1c55a96383497a772a307b346368133960b02ad03Eric Laurent/* 2c55a96383497a772a307b346368133960b02ad03Eric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3c55a96383497a772a307b346368133960b02ad03Eric Laurent * 4c55a96383497a772a307b346368133960b02ad03Eric Laurent * Use of this source code is governed by a BSD-style license 5c55a96383497a772a307b346368133960b02ad03Eric Laurent * that can be found in the LICENSE file in the root of the source 6c55a96383497a772a307b346368133960b02ad03Eric Laurent * tree. An additional intellectual property rights grant can be found 7c55a96383497a772a307b346368133960b02ad03Eric Laurent * in the file PATENTS. All contributing project authors may 8c55a96383497a772a307b346368133960b02ad03Eric Laurent * be found in the AUTHORS file in the root of the source tree. 9c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 10c55a96383497a772a307b346368133960b02ad03Eric Laurent 11c55a96383497a772a307b346368133960b02ad03Eric Laurent/* 12c55a96383497a772a307b346368133960b02ad03Eric Laurent * This file includes the implementation of the internal filterbank associated functions. 13c55a96383497a772a307b346368133960b02ad03Eric Laurent * For function description, see vad_filterbank.h. 14c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 15c55a96383497a772a307b346368133960b02ad03Eric Laurent 16c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "vad_filterbank.h" 17c55a96383497a772a307b346368133960b02ad03Eric Laurent 18c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "signal_processing_library.h" 19c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "typedefs.h" 20c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "vad_defines.h" 21c55a96383497a772a307b346368133960b02ad03Eric Laurent 22c55a96383497a772a307b346368133960b02ad03Eric Laurent// Constant 160*log10(2) in Q9 23c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const int16_t kLogConst = 24660; 24c55a96383497a772a307b346368133960b02ad03Eric Laurent 25c55a96383497a772a307b346368133960b02ad03Eric Laurent// Coefficients used by WebRtcVad_HpOutput, Q14 26c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const int16_t kHpZeroCoefs[3] = { 6631, -13262, 6631 }; 27c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const int16_t kHpPoleCoefs[3] = { 16384, -7756, 5620 }; 28c55a96383497a772a307b346368133960b02ad03Eric Laurent 29c55a96383497a772a307b346368133960b02ad03Eric Laurent// Allpass filter coefficients, upper and lower, in Q15 30c55a96383497a772a307b346368133960b02ad03Eric Laurent// Upper: 0.64, Lower: 0.17 31c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const int16_t kAllPassCoefsQ15[2] = { 20972, 5571 }; 32c55a96383497a772a307b346368133960b02ad03Eric Laurent 33c55a96383497a772a307b346368133960b02ad03Eric Laurent// Adjustment for division with two in WebRtcVad_SplitFilter 34c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const int16_t kOffsetVector[6] = { 368, 368, 272, 176, 176, 176 }; 35c55a96383497a772a307b346368133960b02ad03Eric Laurent 36c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcVad_HpOutput(int16_t* in_vector, 37c55a96383497a772a307b346368133960b02ad03Eric Laurent int in_vector_length, 38c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* filter_state, 39c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* out_vector) { 40c55a96383497a772a307b346368133960b02ad03Eric Laurent int i; 41c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* in_ptr = in_vector; 42c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* out_ptr = out_vector; 43c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t tmp32 = 0; 44c55a96383497a772a307b346368133960b02ad03Eric Laurent 45c55a96383497a772a307b346368133960b02ad03Eric Laurent 46c55a96383497a772a307b346368133960b02ad03Eric Laurent // The sum of the absolute values of the impulse response: 47c55a96383497a772a307b346368133960b02ad03Eric Laurent // The zero/pole-filter has a max amplification of a single sample of: 1.4546 48c55a96383497a772a307b346368133960b02ad03Eric Laurent // Impulse response: 0.4047 -0.6179 -0.0266 0.1993 0.1035 -0.0194 49c55a96383497a772a307b346368133960b02ad03Eric Laurent // The all-zero section has a max amplification of a single sample of: 1.6189 50c55a96383497a772a307b346368133960b02ad03Eric Laurent // Impulse response: 0.4047 -0.8094 0.4047 0 0 0 51c55a96383497a772a307b346368133960b02ad03Eric Laurent // The all-pole section has a max amplification of a single sample of: 1.9931 52c55a96383497a772a307b346368133960b02ad03Eric Laurent // Impulse response: 1.0000 0.4734 -0.1189 -0.2187 -0.0627 0.04532 53c55a96383497a772a307b346368133960b02ad03Eric Laurent 54c55a96383497a772a307b346368133960b02ad03Eric Laurent for (i = 0; i < in_vector_length; i++) { 55c55a96383497a772a307b346368133960b02ad03Eric Laurent // all-zero section (filter coefficients in Q14) 56c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp32 = (int32_t) WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[0], (*in_ptr)); 57c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp32 += (int32_t) WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[1], filter_state[0]); 58c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp32 += (int32_t) WEBRTC_SPL_MUL_16_16(kHpZeroCoefs[2], 59c55a96383497a772a307b346368133960b02ad03Eric Laurent filter_state[1]); // Q14 60c55a96383497a772a307b346368133960b02ad03Eric Laurent filter_state[1] = filter_state[0]; 61c55a96383497a772a307b346368133960b02ad03Eric Laurent filter_state[0] = *in_ptr++; 62c55a96383497a772a307b346368133960b02ad03Eric Laurent 63c55a96383497a772a307b346368133960b02ad03Eric Laurent // all-pole section 64c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp32 -= (int32_t) WEBRTC_SPL_MUL_16_16(kHpPoleCoefs[1], 65c55a96383497a772a307b346368133960b02ad03Eric Laurent filter_state[2]); // Q14 66c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp32 -= (int32_t) WEBRTC_SPL_MUL_16_16(kHpPoleCoefs[2], filter_state[3]); 67c55a96383497a772a307b346368133960b02ad03Eric Laurent filter_state[3] = filter_state[2]; 68c55a96383497a772a307b346368133960b02ad03Eric Laurent filter_state[2] = (int16_t) WEBRTC_SPL_RSHIFT_W32 (tmp32, 14); 69c55a96383497a772a307b346368133960b02ad03Eric Laurent *out_ptr++ = filter_state[2]; 70c55a96383497a772a307b346368133960b02ad03Eric Laurent } 71c55a96383497a772a307b346368133960b02ad03Eric Laurent} 72c55a96383497a772a307b346368133960b02ad03Eric Laurent 73c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcVad_Allpass(int16_t* in_vector, 74c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t filter_coefficients, 75c55a96383497a772a307b346368133960b02ad03Eric Laurent int vector_length, 76c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* filter_state, 77c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* out_vector) { 78c55a96383497a772a307b346368133960b02ad03Eric Laurent // The filter can only cause overflow (in the w16 output variable) 79c55a96383497a772a307b346368133960b02ad03Eric Laurent // if more than 4 consecutive input numbers are of maximum value and 80c55a96383497a772a307b346368133960b02ad03Eric Laurent // has the the same sign as the impulse responses first taps. 81c55a96383497a772a307b346368133960b02ad03Eric Laurent // First 6 taps of the impulse response: 0.6399 0.5905 -0.3779 82c55a96383497a772a307b346368133960b02ad03Eric Laurent // 0.2418 -0.1547 0.0990 83c55a96383497a772a307b346368133960b02ad03Eric Laurent 84c55a96383497a772a307b346368133960b02ad03Eric Laurent int i; 85c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t tmp16 = 0; 86c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t tmp32 = 0, in32 = 0; 87c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t state32 = WEBRTC_SPL_LSHIFT_W32((int32_t) (*filter_state), 16); // Q31 88c55a96383497a772a307b346368133960b02ad03Eric Laurent 89c55a96383497a772a307b346368133960b02ad03Eric Laurent for (i = 0; i < vector_length; i++) { 90c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp32 = state32 + WEBRTC_SPL_MUL_16_16(filter_coefficients, (*in_vector)); 91c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32, 16); 92c55a96383497a772a307b346368133960b02ad03Eric Laurent *out_vector++ = tmp16; 93c55a96383497a772a307b346368133960b02ad03Eric Laurent in32 = WEBRTC_SPL_LSHIFT_W32(((int32_t) (*in_vector)), 14); 94c55a96383497a772a307b346368133960b02ad03Eric Laurent state32 = in32 - WEBRTC_SPL_MUL_16_16(filter_coefficients, tmp16); 95c55a96383497a772a307b346368133960b02ad03Eric Laurent state32 = WEBRTC_SPL_LSHIFT_W32(state32, 1); 96c55a96383497a772a307b346368133960b02ad03Eric Laurent in_vector += 2; 97c55a96383497a772a307b346368133960b02ad03Eric Laurent } 98c55a96383497a772a307b346368133960b02ad03Eric Laurent 99c55a96383497a772a307b346368133960b02ad03Eric Laurent *filter_state = (int16_t) WEBRTC_SPL_RSHIFT_W32(state32, 16); 100c55a96383497a772a307b346368133960b02ad03Eric Laurent} 101c55a96383497a772a307b346368133960b02ad03Eric Laurent 102c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcVad_SplitFilter(int16_t* in_vector, 103c55a96383497a772a307b346368133960b02ad03Eric Laurent int in_vector_length, 104c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* upper_state, 105c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* lower_state, 106c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* out_vector_hp, 107c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* out_vector_lp) { 108c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t tmp_out; 109c55a96383497a772a307b346368133960b02ad03Eric Laurent int i; 110c55a96383497a772a307b346368133960b02ad03Eric Laurent int half_length = WEBRTC_SPL_RSHIFT_W16(in_vector_length, 1); 111c55a96383497a772a307b346368133960b02ad03Eric Laurent 112c55a96383497a772a307b346368133960b02ad03Eric Laurent // All-pass filtering upper branch 113c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_Allpass(&in_vector[0], kAllPassCoefsQ15[0], half_length, 114c55a96383497a772a307b346368133960b02ad03Eric Laurent upper_state, out_vector_hp); 115c55a96383497a772a307b346368133960b02ad03Eric Laurent 116c55a96383497a772a307b346368133960b02ad03Eric Laurent // All-pass filtering lower branch 117c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_Allpass(&in_vector[1], kAllPassCoefsQ15[1], half_length, 118c55a96383497a772a307b346368133960b02ad03Eric Laurent lower_state, out_vector_lp); 119c55a96383497a772a307b346368133960b02ad03Eric Laurent 120c55a96383497a772a307b346368133960b02ad03Eric Laurent // Make LP and HP signals 121c55a96383497a772a307b346368133960b02ad03Eric Laurent for (i = 0; i < half_length; i++) { 122c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp_out = *out_vector_hp; 123c55a96383497a772a307b346368133960b02ad03Eric Laurent *out_vector_hp++ -= *out_vector_lp; 124c55a96383497a772a307b346368133960b02ad03Eric Laurent *out_vector_lp++ += tmp_out; 125c55a96383497a772a307b346368133960b02ad03Eric Laurent } 126c55a96383497a772a307b346368133960b02ad03Eric Laurent} 127c55a96383497a772a307b346368133960b02ad03Eric Laurent 128c55a96383497a772a307b346368133960b02ad03Eric Laurentint16_t WebRtcVad_get_features(VadInstT* inst, 129c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* in_vector, 130c55a96383497a772a307b346368133960b02ad03Eric Laurent int frame_size, 131c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* out_vector) { 132c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t power = 0; 133c55a96383497a772a307b346368133960b02ad03Eric Laurent // We expect |frame_size| to be 80, 160 or 240 samples, which corresponds to 134c55a96383497a772a307b346368133960b02ad03Eric Laurent // 10, 20 or 30 ms in 8 kHz. Therefore, the intermediate downsampled data will 135c55a96383497a772a307b346368133960b02ad03Eric Laurent // have at most 120 samples after the first split and at most 60 samples after 136c55a96383497a772a307b346368133960b02ad03Eric Laurent // the second split. 137c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t hp_120[120], lp_120[120]; 138c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t hp_60[60], lp_60[60]; 139c55a96383497a772a307b346368133960b02ad03Eric Laurent // Initialize variables for the first SplitFilter(). 140c55a96383497a772a307b346368133960b02ad03Eric Laurent int length = frame_size; 141c55a96383497a772a307b346368133960b02ad03Eric Laurent int frequency_band = 0; 142c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* in_ptr = in_vector; 143c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* hp_out_ptr = hp_120; 144c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* lp_out_ptr = lp_120; 145c55a96383497a772a307b346368133960b02ad03Eric Laurent 146c55a96383497a772a307b346368133960b02ad03Eric Laurent // Split at 2000 Hz and downsample 147c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_SplitFilter(in_ptr, length, &inst->upper_state[frequency_band], 148c55a96383497a772a307b346368133960b02ad03Eric Laurent &inst->lower_state[frequency_band], hp_out_ptr, 149c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr); 150c55a96383497a772a307b346368133960b02ad03Eric Laurent 151c55a96383497a772a307b346368133960b02ad03Eric Laurent // Split at 3000 Hz and downsample 152c55a96383497a772a307b346368133960b02ad03Eric Laurent frequency_band = 1; 153c55a96383497a772a307b346368133960b02ad03Eric Laurent in_ptr = hp_120; 154c55a96383497a772a307b346368133960b02ad03Eric Laurent hp_out_ptr = hp_60; 155c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr = lp_60; 156c55a96383497a772a307b346368133960b02ad03Eric Laurent length = WEBRTC_SPL_RSHIFT_W16(frame_size, 1); 157c55a96383497a772a307b346368133960b02ad03Eric Laurent 158c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_SplitFilter(in_ptr, length, &inst->upper_state[frequency_band], 159c55a96383497a772a307b346368133960b02ad03Eric Laurent &inst->lower_state[frequency_band], hp_out_ptr, 160c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr); 161c55a96383497a772a307b346368133960b02ad03Eric Laurent 162c55a96383497a772a307b346368133960b02ad03Eric Laurent // Energy in 3000 Hz - 4000 Hz 163c55a96383497a772a307b346368133960b02ad03Eric Laurent length = WEBRTC_SPL_RSHIFT_W16(length, 1); 164c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_LogOfEnergy(hp_60, length, kOffsetVector[5], &power, 165c55a96383497a772a307b346368133960b02ad03Eric Laurent &out_vector[5]); 166c55a96383497a772a307b346368133960b02ad03Eric Laurent 167c55a96383497a772a307b346368133960b02ad03Eric Laurent // Energy in 2000 Hz - 3000 Hz 168c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_LogOfEnergy(lp_60, length, kOffsetVector[4], &power, 169c55a96383497a772a307b346368133960b02ad03Eric Laurent &out_vector[4]); 170c55a96383497a772a307b346368133960b02ad03Eric Laurent 171c55a96383497a772a307b346368133960b02ad03Eric Laurent // Split at 1000 Hz and downsample 172c55a96383497a772a307b346368133960b02ad03Eric Laurent frequency_band = 2; 173c55a96383497a772a307b346368133960b02ad03Eric Laurent in_ptr = lp_120; 174c55a96383497a772a307b346368133960b02ad03Eric Laurent hp_out_ptr = hp_60; 175c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr = lp_60; 176c55a96383497a772a307b346368133960b02ad03Eric Laurent length = WEBRTC_SPL_RSHIFT_W16(frame_size, 1); 177c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_SplitFilter(in_ptr, length, &inst->upper_state[frequency_band], 178c55a96383497a772a307b346368133960b02ad03Eric Laurent &inst->lower_state[frequency_band], hp_out_ptr, 179c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr); 180c55a96383497a772a307b346368133960b02ad03Eric Laurent 181c55a96383497a772a307b346368133960b02ad03Eric Laurent // Energy in 1000 Hz - 2000 Hz 182c55a96383497a772a307b346368133960b02ad03Eric Laurent length = WEBRTC_SPL_RSHIFT_W16(length, 1); 183c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_LogOfEnergy(hp_60, length, kOffsetVector[3], &power, 184c55a96383497a772a307b346368133960b02ad03Eric Laurent &out_vector[3]); 185c55a96383497a772a307b346368133960b02ad03Eric Laurent 186c55a96383497a772a307b346368133960b02ad03Eric Laurent // Split at 500 Hz 187c55a96383497a772a307b346368133960b02ad03Eric Laurent frequency_band = 3; 188c55a96383497a772a307b346368133960b02ad03Eric Laurent in_ptr = lp_60; 189c55a96383497a772a307b346368133960b02ad03Eric Laurent hp_out_ptr = hp_120; 190c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr = lp_120; 191c55a96383497a772a307b346368133960b02ad03Eric Laurent 192c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_SplitFilter(in_ptr, length, &inst->upper_state[frequency_band], 193c55a96383497a772a307b346368133960b02ad03Eric Laurent &inst->lower_state[frequency_band], hp_out_ptr, 194c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr); 195c55a96383497a772a307b346368133960b02ad03Eric Laurent 196c55a96383497a772a307b346368133960b02ad03Eric Laurent // Energy in 500 Hz - 1000 Hz 197c55a96383497a772a307b346368133960b02ad03Eric Laurent length = WEBRTC_SPL_RSHIFT_W16(length, 1); 198c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_LogOfEnergy(hp_120, length, kOffsetVector[2], &power, 199c55a96383497a772a307b346368133960b02ad03Eric Laurent &out_vector[2]); 200c55a96383497a772a307b346368133960b02ad03Eric Laurent 201c55a96383497a772a307b346368133960b02ad03Eric Laurent // Split at 250 Hz 202c55a96383497a772a307b346368133960b02ad03Eric Laurent frequency_band = 4; 203c55a96383497a772a307b346368133960b02ad03Eric Laurent in_ptr = lp_120; 204c55a96383497a772a307b346368133960b02ad03Eric Laurent hp_out_ptr = hp_60; 205c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr = lp_60; 206c55a96383497a772a307b346368133960b02ad03Eric Laurent 207c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_SplitFilter(in_ptr, length, &inst->upper_state[frequency_band], 208c55a96383497a772a307b346368133960b02ad03Eric Laurent &inst->lower_state[frequency_band], hp_out_ptr, 209c55a96383497a772a307b346368133960b02ad03Eric Laurent lp_out_ptr); 210c55a96383497a772a307b346368133960b02ad03Eric Laurent 211c55a96383497a772a307b346368133960b02ad03Eric Laurent // Energy in 250 Hz - 500 Hz 212c55a96383497a772a307b346368133960b02ad03Eric Laurent length = WEBRTC_SPL_RSHIFT_W16(length, 1); 213c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_LogOfEnergy(hp_60, length, kOffsetVector[1], &power, 214c55a96383497a772a307b346368133960b02ad03Eric Laurent &out_vector[1]); 215c55a96383497a772a307b346368133960b02ad03Eric Laurent 216c55a96383497a772a307b346368133960b02ad03Eric Laurent // Remove DC and LFs 217c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_HpOutput(lp_60, length, inst->hp_filter_state, hp_120); 218c55a96383497a772a307b346368133960b02ad03Eric Laurent 219c55a96383497a772a307b346368133960b02ad03Eric Laurent // Power in 80 Hz - 250 Hz 220c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtcVad_LogOfEnergy(hp_120, length, kOffsetVector[0], &power, 221c55a96383497a772a307b346368133960b02ad03Eric Laurent &out_vector[0]); 222c55a96383497a772a307b346368133960b02ad03Eric Laurent 223c55a96383497a772a307b346368133960b02ad03Eric Laurent return power; 224c55a96383497a772a307b346368133960b02ad03Eric Laurent} 225c55a96383497a772a307b346368133960b02ad03Eric Laurent 226c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcVad_LogOfEnergy(int16_t* vector, 227c55a96383497a772a307b346368133960b02ad03Eric Laurent int vector_length, 228c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t offset, 229c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* power, 230c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t* log_energy) { 231c55a96383497a772a307b346368133960b02ad03Eric Laurent int shfts = 0, shfts2 = 0; 232c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t energy_s16 = 0; 233c55a96383497a772a307b346368133960b02ad03Eric Laurent int16_t zeros = 0, frac = 0, log2 = 0; 234c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t energy = WebRtcSpl_Energy(vector, vector_length, &shfts); 235c55a96383497a772a307b346368133960b02ad03Eric Laurent 236c55a96383497a772a307b346368133960b02ad03Eric Laurent if (energy > 0) { 237c55a96383497a772a307b346368133960b02ad03Eric Laurent 238c55a96383497a772a307b346368133960b02ad03Eric Laurent shfts2 = 16 - WebRtcSpl_NormW32(energy); 239c55a96383497a772a307b346368133960b02ad03Eric Laurent shfts += shfts2; 240c55a96383497a772a307b346368133960b02ad03Eric Laurent // "shfts" is the total number of right shifts that has been done to 241c55a96383497a772a307b346368133960b02ad03Eric Laurent // energy_s16. 242c55a96383497a772a307b346368133960b02ad03Eric Laurent energy_s16 = (int16_t) WEBRTC_SPL_SHIFT_W32(energy, -shfts2); 243c55a96383497a772a307b346368133960b02ad03Eric Laurent 244c55a96383497a772a307b346368133960b02ad03Eric Laurent // Find: 245c55a96383497a772a307b346368133960b02ad03Eric Laurent // 160*log10(energy_s16*2^shfts) = 160*log10(2)*log2(energy_s16*2^shfts) = 246c55a96383497a772a307b346368133960b02ad03Eric Laurent // 160*log10(2)*(log2(energy_s16) + log2(2^shfts)) = 247c55a96383497a772a307b346368133960b02ad03Eric Laurent // 160*log10(2)*(log2(energy_s16) + shfts) 248c55a96383497a772a307b346368133960b02ad03Eric Laurent 249c55a96383497a772a307b346368133960b02ad03Eric Laurent zeros = WebRtcSpl_NormU32(energy_s16); 250c55a96383497a772a307b346368133960b02ad03Eric Laurent frac = (int16_t) (((uint32_t) ((int32_t) (energy_s16) << zeros) 251c55a96383497a772a307b346368133960b02ad03Eric Laurent & 0x7FFFFFFF) >> 21); 252c55a96383497a772a307b346368133960b02ad03Eric Laurent log2 = (int16_t) (((31 - zeros) << 10) + frac); 253c55a96383497a772a307b346368133960b02ad03Eric Laurent 254c55a96383497a772a307b346368133960b02ad03Eric Laurent *log_energy = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(kLogConst, log2, 19) 255c55a96383497a772a307b346368133960b02ad03Eric Laurent + (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(shfts, kLogConst, 9); 256c55a96383497a772a307b346368133960b02ad03Eric Laurent 257c55a96383497a772a307b346368133960b02ad03Eric Laurent if (*log_energy < 0) { 258c55a96383497a772a307b346368133960b02ad03Eric Laurent *log_energy = 0; 259c55a96383497a772a307b346368133960b02ad03Eric Laurent } 260c55a96383497a772a307b346368133960b02ad03Eric Laurent } else { 261c55a96383497a772a307b346368133960b02ad03Eric Laurent *log_energy = 0; 262c55a96383497a772a307b346368133960b02ad03Eric Laurent shfts = -15; 263c55a96383497a772a307b346368133960b02ad03Eric Laurent energy_s16 = 0; 264c55a96383497a772a307b346368133960b02ad03Eric Laurent } 265c55a96383497a772a307b346368133960b02ad03Eric Laurent 266c55a96383497a772a307b346368133960b02ad03Eric Laurent *log_energy += offset; 267c55a96383497a772a307b346368133960b02ad03Eric Laurent 268c55a96383497a772a307b346368133960b02ad03Eric Laurent // Total power in frame 269c55a96383497a772a307b346368133960b02ad03Eric Laurent if (*power <= MIN_ENERGY) { 270c55a96383497a772a307b346368133960b02ad03Eric Laurent if (shfts > 0) { 271c55a96383497a772a307b346368133960b02ad03Eric Laurent *power += MIN_ENERGY + 1; 272c55a96383497a772a307b346368133960b02ad03Eric Laurent } else if (WEBRTC_SPL_SHIFT_W16(energy_s16, shfts) > MIN_ENERGY) { 273c55a96383497a772a307b346368133960b02ad03Eric Laurent *power += MIN_ENERGY + 1; 274c55a96383497a772a307b346368133960b02ad03Eric Laurent } else { 275c55a96383497a772a307b346368133960b02ad03Eric Laurent *power += WEBRTC_SPL_SHIFT_W16(energy_s16, shfts); 276c55a96383497a772a307b346368133960b02ad03Eric Laurent } 277c55a96383497a772a307b346368133960b02ad03Eric Laurent } 278c55a96383497a772a307b346368133960b02ad03Eric Laurent} 279