analog_agc.c revision c55a96383497a772a307b346368133960b02ad03
1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Use of this source code is governed by a BSD-style license 5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * that can be found in the LICENSE file in the root of the source 6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * tree. An additional intellectual property rights grant can be found 7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * in the file PATENTS. All contributing project authors may 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * be found in the AUTHORS file in the root of the source tree. 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* analog_agc.c 12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Using a feedback system, determines an appropriate analog volume level 14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * given an input signal and current volume level. Targets a conservative 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * signal level and is intended for use with a digital AGC to apply 16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * additional gain. 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <assert.h> 21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <stdlib.h> 22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <stdio.h> 24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "analog_agc.h" 26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* The slope of in Q13*/ 28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word16 kSlope1[8] = {21793, 12517, 7189, 4129, 2372, 1362, 472, 78}; 29e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* The offset in Q14 */ 31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word16 kOffset1[8] = {25395, 23911, 22206, 20737, 19612, 18805, 17951, 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 17367}; 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* The slope of in Q13*/ 35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word16 kSlope2[8] = {2063, 1731, 1452, 1218, 1021, 857, 597, 337}; 36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* The offset in Q14 */ 38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word16 kOffset2[8] = {18432, 18379, 18290, 18177, 18052, 17920, 17670, 39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 17286}; 40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word16 kMuteGuardTimeMs = 8000; 42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word16 kInitCheck = 42; 43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Default settings if config is not used */ 45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define AGC_DEFAULT_TARGET_LEVEL 3 46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define AGC_DEFAULT_COMP_GAIN 9 47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* This is the target level for the analog part in ENV scale. To convert to RMS scale you 48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * have to add OFFSET_ENV_TO_RMS. 49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define ANALOG_TARGET_LEVEL 11 51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define ANALOG_TARGET_LEVEL_2 5 // ANALOG_TARGET_LEVEL / 2 52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Offset between RMS scale (analog part) and ENV scale (digital part). This value actually 53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * varies with the FIXED_ANALOG_TARGET_LEVEL, hence we should in the future replace it with 54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * a table. 55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define OFFSET_ENV_TO_RMS 9 57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* The reference input level at which the digital part gives an output of targetLevelDbfs 58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * (desired level) if we have no compression gain. This level should be set high enough not 59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * to compress the peaks due to the dynamics. 60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define DIGITAL_REF_AT_0_COMP_GAIN 4 62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Speed of reference level decrease. 63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define DIFF_REF_TO_ANALOG 5 65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET 7 68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Size of analog gain table */ 70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define GAIN_TBL_LEN 32 71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Matlab code: 72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * fprintf(1, '\t%i, %i, %i, %i,\n', round(10.^(linspace(0,10,32)/20) * 2^12)); 73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Q12 */ 75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_UWord16 kGainTableAnalog[GAIN_TBL_LEN] = {4096, 4251, 4412, 4579, 4752, 76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 4932, 5118, 5312, 5513, 5722, 5938, 6163, 6396, 6638, 6889, 7150, 7420, 7701, 7992, 77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 8295, 8609, 8934, 9273, 9623, 9987, 10365, 10758, 11165, 11587, 12025, 12480, 12953}; 78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Gain/Suppression tables for virtual Mic (in Q10) */ 80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_UWord16 kGainTableVirtualMic[128] = {1052, 1081, 1110, 1141, 1172, 1204, 81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1237, 1271, 1305, 1341, 1378, 1416, 1454, 1494, 1535, 1577, 1620, 1664, 1710, 1757, 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1805, 1854, 1905, 1957, 2010, 2065, 2122, 2180, 2239, 2301, 2364, 2428, 2495, 2563, 83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 2633, 2705, 2779, 2855, 2933, 3013, 3096, 3180, 3267, 3357, 3449, 3543, 3640, 3739, 84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 3842, 3947, 4055, 4166, 4280, 4397, 4517, 4640, 4767, 4898, 5032, 5169, 5311, 5456, 85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 5605, 5758, 5916, 6078, 6244, 6415, 6590, 6770, 6956, 7146, 7341, 7542, 7748, 7960, 86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 8178, 8402, 8631, 8867, 9110, 9359, 9615, 9878, 10148, 10426, 10711, 11004, 11305, 87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11614, 11932, 12258, 12593, 12938, 13292, 13655, 14029, 14412, 14807, 15212, 15628, 88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 16055, 16494, 16945, 17409, 17885, 18374, 18877, 19393, 19923, 20468, 21028, 21603, 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 22194, 22801, 23425, 24065, 24724, 25400, 26095, 26808, 27541, 28295, 29069, 29864, 90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 30681, 31520, 32382}; 91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_UWord16 kSuppressionTableVirtualMic[128] = {1024, 1006, 988, 970, 952, 92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 935, 918, 902, 886, 870, 854, 839, 824, 809, 794, 780, 766, 752, 739, 726, 713, 700, 93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 687, 675, 663, 651, 639, 628, 616, 605, 594, 584, 573, 563, 553, 543, 533, 524, 514, 94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 505, 496, 487, 478, 470, 461, 453, 445, 437, 429, 421, 414, 406, 399, 392, 385, 378, 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 371, 364, 358, 351, 345, 339, 333, 327, 321, 315, 309, 304, 298, 293, 288, 283, 278, 96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 273, 268, 263, 258, 254, 249, 244, 240, 236, 232, 227, 223, 219, 215, 211, 208, 204, 97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 200, 197, 193, 190, 186, 183, 180, 176, 173, 170, 167, 164, 161, 158, 155, 153, 150, 98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 147, 145, 142, 139, 137, 134, 132, 130, 127, 125, 123, 121, 118, 116, 114, 112, 110, 99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 108, 106, 104, 102}; 100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* Table for target energy levels. Values in Q(-7) 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Matlab code 103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * targetLevelTable = fprintf('%d,\t%d,\t%d,\t%d,\n', round((32767*10.^(-(0:63)'/20)).^2*16/2^7) */ 104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const WebRtc_Word32 kTargetLevelTable[64] = {134209536, 106606424, 84680493, 67264106, 106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 53429779, 42440782, 33711911, 26778323, 21270778, 16895980, 13420954, 10660642, 107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 8468049, 6726411, 5342978, 4244078, 3371191, 2677832, 2127078, 1689598, 1342095, 108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1066064, 846805, 672641, 534298, 424408, 337119, 267783, 212708, 168960, 134210, 109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 106606, 84680, 67264, 53430, 42441, 33712, 26778, 21271, 16896, 13421, 10661, 8468, 110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 6726, 5343, 4244, 3371, 2678, 2127, 1690, 1342, 1066, 847, 673, 534, 424, 337, 268, 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 213, 169, 134, 107, 85, 67}; 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_AddMic(void *state, WebRtc_Word16 *in_mic, WebRtc_Word16 *in_mic_H, 114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 samples) 115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 nrg, max_nrg, sample, tmp32; 117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 *ptr; 118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord16 targetGainIdx, gain; 119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 i, n, L, M, subFrames, tmp16, tmp_speech[16]; 120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)state; 122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //default/initial values corresponding to 10ms for wb and swb 124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent M = 10; 125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L = 16; 126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 8000) 129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (samples == 80) 131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 80; 133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent M = 10; 134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L = 8; 135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (samples == 160) 136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 80; 138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent M = 20; 139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L = 8; 140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_mic, frame %d: Invalid number of samples\n\n", 145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent (stt->fcount + 1)); 146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->fs == 16000) 150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (samples == 160) 152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent M = 10; 155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L = 16; 156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (samples == 320) 157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent M = 20; 160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L = 16; 161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_mic, frame %d: Invalid number of samples\n\n", 166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent (stt->fcount + 1)); 167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->fs == 32000) 171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* SWB is processed as 160 sample for L and H bands */ 173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (samples == 160) 174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent M = 10; 177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L = 16; 178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG 181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_mic, frame %d: Invalid sample rate\n\n", 183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent (stt->fcount + 1)); 184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check for valid pointers based on sampling rate */ 190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((stt->fs == 32000) && (in_mic_H == NULL)) 191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check for valid pointer for low band */ 195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (in_mic == NULL) 196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* apply slowly varying digital gain */ 201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > stt->maxAnalog) 202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 203c55a96383497a772a307b346368133960b02ad03Eric Laurent /* |maxLevel| is strictly >= |micVol|, so this condition should be 204c55a96383497a772a307b346368133960b02ad03Eric Laurent * satisfied here, ensuring there is no divide-by-zero. */ 205c55a96383497a772a307b346368133960b02ad03Eric Laurent assert(stt->maxLevel > stt->maxAnalog); 206c55a96383497a772a307b346368133960b02ad03Eric Laurent 207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Q1 */ 208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp16 = (WebRtc_Word16)(stt->micVol - stt->maxAnalog); 209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_MUL_16_16(GAIN_TBL_LEN - 1, tmp16); 210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp16 = (WebRtc_Word16)(stt->maxLevel - stt->maxAnalog); 211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent targetGainIdx = (WebRtc_UWord16)WEBRTC_SPL_DIV(tmp32, tmp16); 212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(targetGainIdx < GAIN_TBL_LEN); 213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Increment through the table towards the target gain. 215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * If micVol drops below maxAnalog, we allow the gain 216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * to be dropped immediately. */ 217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->gainTableIdx < targetGainIdx) 218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->gainTableIdx++; 220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->gainTableIdx > targetGainIdx) 221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->gainTableIdx--; 223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Q12 */ 226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kGainTableAnalog[stt->gainTableIdx]; 227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < samples; i++) 229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // For lower band 231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_MUL_16_U16(in_mic[i], gain); 232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent sample = WEBRTC_SPL_RSHIFT_W32(tmp32, 12); 233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (sample > 32767) 234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_mic[i] = 32767; 236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (sample < -32768) 237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_mic[i] = -32768; 239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_mic[i] = (WebRtc_Word16)sample; 242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // For higher band 245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 32000) 246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_MUL_16_U16(in_mic_H[i], gain); 248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent sample = WEBRTC_SPL_RSHIFT_W32(tmp32, 12); 249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (sample > 32767) 250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_mic_H[i] = 32767; 252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (sample < -32768) 253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_mic_H[i] = -32768; 255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_mic_H[i] = (WebRtc_Word16)sample; 258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->gainTableIdx = 0; 264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* compute envelope */ 267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((M == 10) && (stt->inQueue > 0)) 268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ptr = stt->env[1]; 270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ptr = stt->env[0]; 273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < M; i++) 276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* iterate over samples */ 278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent max_nrg = 0; 279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (n = 0; n < L; n++) 280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent nrg = WEBRTC_SPL_MUL_16_16(in_mic[i * L + n], in_mic[i * L + n]); 282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (nrg > max_nrg) 283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent max_nrg = nrg; 285e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 287e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ptr[i] = max_nrg; 288e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* compute energy */ 291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((M == 10) && (stt->inQueue > 0)) 292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ptr = stt->Rxx16w32_array[1]; 294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ptr = stt->Rxx16w32_array[0]; 297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 299e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < WEBRTC_SPL_RSHIFT_W16(M, 1); i++) 300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 16000) 302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcSpl_DownsampleBy2(&in_mic[i * 32], 32, tmp_speech, stt->filterState); 304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent memcpy(tmp_speech, &in_mic[i * 16], 16 * sizeof(short)); 307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Compute energy in blocks of 16 samples */ 309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ptr[i] = WebRtcSpl_DotProductWithScale(tmp_speech, tmp_speech, 16, 4); 310e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* update queue information */ 313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((stt->inQueue == 0) && (M == 10)) 314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->inQueue = 1; 316e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 317e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 318e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->inQueue = 2; 319e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* call VAD (use low band only) */ 322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < samples; i += subFrames) 323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_ProcessVad(&stt->vadMic, &in_mic[i], subFrames); 325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_AddFarend(void *state, const WebRtc_Word16 *in_far, WebRtc_Word16 samples) 331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 errHandle = 0; 333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 i, subFrames; 334e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 335e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)state; 336e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt == NULL) 338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 339e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 8000) 343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((samples != 80) && (samples != 160)) 345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_far_end, frame %d: Invalid number of samples\n\n", 349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount); 350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 351e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 80; 354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->fs == 16000) 355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((samples != 160) && (samples != 320)) 357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_far_end, frame %d: Invalid number of samples\n\n", 361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount); 362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 363e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->fs == 32000) 367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 368e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((samples != 160) && (samples != 320)) 369e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 370e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 371e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 372e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_far_end, frame %d: Invalid number of samples\n\n", 373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount); 374e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->add_far_end, frame %d: Invalid sample rate\n\n", 383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount + 1); 384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < samples; i += subFrames) 389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent errHandle += WebRtcAgc_AddFarendToDigital(&stt->digitalAgc, &in_far[i], subFrames); 391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return errHandle; 394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 395e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 396e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_VirtualMic(void *agcInst, WebRtc_Word16 *in_near, WebRtc_Word16 *in_near_H, 397e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 samples, WebRtc_Word32 micLevelIn, 398e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 *micLevelOut) 399e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 400e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 tmpFlt, micLevelTmp, gainIdx; 401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord16 gain; 402e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 ii; 403e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 404e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 405e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord32 nrg; 406e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 sampleCntr; 407e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord32 frameNrg = 0; 408e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord32 frameNrgLimit = 5500; 409e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 numZeroCrossing = 0; 410e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word16 kZeroCrossingLowLim = 15; 411e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word16 kZeroCrossingHighLim = 20; 412e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 413e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)agcInst; 414e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 415e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* 416e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Before applying gain decide if this is a low-level signal. 417e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * The idea is that digital AGC will not adapt to low-level 418e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * signals. 419e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 420e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs != 8000) 421e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 422e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent frameNrgLimit = frameNrgLimit << 1; 423e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 424e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 425e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent frameNrg = WEBRTC_SPL_MUL_16_16(in_near[0], in_near[0]); 426e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (sampleCntr = 1; sampleCntr < samples; sampleCntr++) 427e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 428e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 429e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // increment frame energy if it is less than the limit 430e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // the correct value of the energy is not important 431e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (frameNrg < frameNrgLimit) 432e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 433e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent nrg = WEBRTC_SPL_MUL_16_16(in_near[sampleCntr], in_near[sampleCntr]); 434e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent frameNrg += nrg; 435e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 436e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 437e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Count the zero crossings 438e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent numZeroCrossing += ((in_near[sampleCntr] ^ in_near[sampleCntr - 1]) < 0); 439e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 440e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 441e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((frameNrg < 500) || (numZeroCrossing <= 5)) 442e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 443e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowLevelSignal = 1; 444e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (numZeroCrossing <= kZeroCrossingLowLim) 445e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 446e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowLevelSignal = 0; 447e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (frameNrg <= frameNrgLimit) 448e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 449e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowLevelSignal = 1; 450e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (numZeroCrossing >= kZeroCrossingHighLim) 451e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 452e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowLevelSignal = 1; 453e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 454e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 455e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowLevelSignal = 0; 456e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 457e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 458e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent micLevelTmp = WEBRTC_SPL_LSHIFT_W32(micLevelIn, stt->scale); 459e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Set desired level */ 460e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gainIdx = stt->micVol; 461e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > stt->maxAnalog) 462e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 463e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gainIdx = stt->maxAnalog; 464e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 465e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (micLevelTmp != stt->micRef) 466e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 467e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Something has happened with the physical level, restart. */ 468e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micRef = micLevelTmp; 469e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = 127; 470e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *micLevelOut = 127; 471e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micGainIdx = 127; 472e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gainIdx = 127; 473e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 474e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Pre-process the signal to emulate the microphone level. */ 475e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Take one step at a time in the gain table. */ 476e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (gainIdx > 127) 477e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 478e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kGainTableVirtualMic[gainIdx - 128]; 479e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 480e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 481e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kSuppressionTableVirtualMic[127 - gainIdx]; 482e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 483e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (ii = 0; ii < samples; ii++) 484e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 485e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_U16(in_near[ii], gain), 10); 486e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (tmpFlt > 32767) 487e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 488e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = 32767; 489e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gainIdx--; 490e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (gainIdx >= 127) 491e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 492e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kGainTableVirtualMic[gainIdx - 127]; 493e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 494e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 495e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kSuppressionTableVirtualMic[127 - gainIdx]; 496e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 497e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 498e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (tmpFlt < -32768) 499e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 500e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = -32768; 501e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gainIdx--; 502e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (gainIdx >= 127) 503e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 504e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kGainTableVirtualMic[gainIdx - 127]; 505e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 506e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 507e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent gain = kSuppressionTableVirtualMic[127 - gainIdx]; 508e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 509e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 510e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_near[ii] = (WebRtc_Word16)tmpFlt; 511e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 32000) 512e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 513e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = WEBRTC_SPL_MUL_16_U16(in_near_H[ii], gain); 514e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = WEBRTC_SPL_RSHIFT_W32(tmpFlt, 10); 515e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (tmpFlt > 32767) 516e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 517e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = 32767; 518e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 519e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (tmpFlt < -32768) 520e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 521e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpFlt = -32768; 522e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 523e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent in_near_H[ii] = (WebRtc_Word16)tmpFlt; 524e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 525e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 526e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Set the level we (finally) used */ 527e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micGainIdx = gainIdx; 528e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// *micLevelOut = stt->micGainIdx; 529e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *micLevelOut = WEBRTC_SPL_RSHIFT_W32(stt->micGainIdx, stt->scale); 530e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Add to Mic as if it was the output from a true microphone */ 531e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAgc_AddMic(agcInst, in_near, in_near_H, samples) != 0) 532e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 533e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 534e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 535e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 536e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 537e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 538e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid WebRtcAgc_UpdateAgcThresholds(Agc_t *stt) 539e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 540e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 541e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 tmp16; 542e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 543e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int zeros; 544e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 545e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micLvlSat) 546e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 547e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Lower the analog target level since we have reached its maximum */ 548e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent zeros = WebRtcSpl_NormW32(stt->Rxx160_LPw32); 549e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->targetIdxOffset = WEBRTC_SPL_RSHIFT_W16((3 * zeros) - stt->targetIdx - 2, 2); 550e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 551e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 552e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 553e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Set analog target level in envelope dBOv scale */ 554e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp16 = (DIFF_REF_TO_ANALOG * stt->compressionGaindB) + ANALOG_TARGET_LEVEL_2; 555e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp16 = WebRtcSpl_DivW32W16ResW16((WebRtc_Word32)tmp16, ANALOG_TARGET_LEVEL); 556e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->analogTarget = DIGITAL_REF_AT_0_COMP_GAIN + tmp16; 557e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->analogTarget < DIGITAL_REF_AT_0_COMP_GAIN) 558e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 559e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->analogTarget = DIGITAL_REF_AT_0_COMP_GAIN; 560e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 561e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->agcMode == kAgcModeFixedDigital) 562e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 563e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Adjust for different parameter interpretation in FixedDigital mode */ 564e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->analogTarget = stt->compressionGaindB; 565e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 566e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 567e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->analogTarget += stt->targetIdxOffset; 568e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 569e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Since the offset between RMS and ENV is not constant, we should make this into a 570e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * table, but for now, we'll stick with a constant, tuned for the chosen analog 571e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * target level. 572e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 573e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->targetIdx = ANALOG_TARGET_LEVEL + OFFSET_ENV_TO_RMS; 574e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 575e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->targetIdx += stt->targetIdxOffset; 576e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 577e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Analog adaptation limits */ 578e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* analogTargetLevel = round((32767*10^(-targetIdx/20))^2*16/2^7) */ 579e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->analogTargetLevel = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx]; /* ex. -20 dBov */ 580e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->startUpperLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 1];/* -19 dBov */ 581e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->startLowerLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 1];/* -21 dBov */ 582e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->upperPrimaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 2];/* -18 dBov */ 583e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowerPrimaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 2];/* -22 dBov */ 584e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->upperSecondaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx - 5];/* -15 dBov */ 585e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowerSecondaryLimit = RXX_BUFFER_LEN * kTargetLevelTable[stt->targetIdx + 5];/* -25 dBov */ 586e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->upperLimit = stt->startUpperLimit; 587e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowerLimit = stt->startLowerLimit; 588e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 589e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 590e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid WebRtcAgc_SaturationCtrl(Agc_t *stt, WebRtc_UWord8 *saturated, WebRtc_Word32 *env) 591e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 592e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 i, tmpW16; 593e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 594e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check if the signal is saturated */ 595e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < 10; i++) 596e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 597e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpW16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(env[i], 20); 598e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (tmpW16 > 875) 599e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 600e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->envSum += tmpW16; 601e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 602e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 603e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 604e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->envSum > 25000) 605e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 606e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *saturated = 1; 607e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->envSum = 0; 608e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 609e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 610e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* stt->envSum *= 0.99; */ 611e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->envSum = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(stt->envSum, 612e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent (WebRtc_Word16)32440, 15); 613e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 614e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 615e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid WebRtcAgc_ZeroCtrl(Agc_t *stt, WebRtc_Word32 *inMicLevel, WebRtc_Word32 *env) 616e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 617e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 i; 618e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 tmp32 = 0; 619e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 midVal; 620e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 621e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Is the input signal zero? */ 622e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < 10; i++) 623e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 624e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 += env[i]; 625e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 626e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 627e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Each block is allowed to have a few non-zero 628e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * samples. 629e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 630e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (tmp32 < 500) 631e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 632e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msZero += 10; 633e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 634e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 635e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msZero = 0; 636e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 637e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 638e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->muteGuardMs > 0) 639e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 640e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->muteGuardMs -= 10; 641e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 642e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 643e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->msZero > 500) 644e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 645e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msZero = 0; 646e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 647e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Increase microphone level only if it's less than 50% */ 648e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent midVal = WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog + stt->minLevel + 1, 1); 649e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (*inMicLevel < midVal) 650e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 651e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* *inMicLevel *= 1.1; */ 652e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_MUL(1126, *inMicLevel); 653e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *inMicLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 10); 654e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Reduces risk of a muted mic repeatedly triggering excessive levels due 655e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * to zero signal detection. */ 656e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *inMicLevel = WEBRTC_SPL_MIN(*inMicLevel, stt->zeroCtrlMax); 657e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = *inMicLevel; 658e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 659e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 660e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 661e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 662e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\t\tAGC->zeroCntrl, frame %d: 500 ms under threshold, micVol:\n", 663e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount, stt->micVol); 664e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 665e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 666e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->activeSpeech = 0; 667e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32Max = 0; 668e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 669e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* The AGC has a tendency (due to problems with the VAD parameters), to 670e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * vastly increase the volume after a muting event. This timer prevents 671e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * upwards adaptation for a short period. */ 672e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->muteGuardMs = kMuteGuardTimeMs; 673e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 674e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 675e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 676e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid WebRtcAgc_SpeakerInactiveCtrl(Agc_t *stt) 677e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 678e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check if the near end speaker is inactive. 679e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * If that is the case the VAD threshold is 680e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * increased since the VAD speech model gets 681e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * more sensitive to any sound after a long 682e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * silence. 683e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 684e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 685e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 tmp32; 686e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 vadThresh; 687e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 688e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->vadMic.stdLongTerm < 2500) 689e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 690e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->vadThreshold = 1500; 691e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 692e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 693e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent vadThresh = kNormalVadThreshold; 694e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->vadMic.stdLongTerm < 4500) 695e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 696e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Scale between min and max threshold */ 697e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent vadThresh += WEBRTC_SPL_RSHIFT_W16(4500 - stt->vadMic.stdLongTerm, 1); 698e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 699e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 700e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* stt->vadThreshold = (31 * stt->vadThreshold + vadThresh) / 32; */ 701e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = (WebRtc_Word32)vadThresh; 702e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 += WEBRTC_SPL_MUL_16_16((WebRtc_Word16)31, stt->vadThreshold); 703e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->vadThreshold = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 5); 704e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 705e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 706e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 707e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid WebRtcAgc_ExpCurve(WebRtc_Word16 volume, WebRtc_Word16 *index) 708e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 709e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // volume in Q14 710e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // index in [0-7] 711e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* 8 different curves */ 712e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 5243) 713e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 714e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 7864) 715e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 716e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 12124) 717e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 718e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 7; 719e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 720e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 721e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 6; 722e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 723e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 724e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 725e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 6554) 726e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 727e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 5; 728e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 729e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 730e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 4; 731e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 732e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 733e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 734e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 735e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 2621) 736e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 737e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 3932) 738e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 739e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 3; 740e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 741e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 742e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 2; 743e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 744e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 745e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 746e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (volume > 1311) 747e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 748e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 1; 749e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 750e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 751e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *index = 0; 752e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 753e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 754e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 755e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 756e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 757e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word32 WebRtcAgc_ProcessAnalog(void *state, WebRtc_Word32 inMicLevel, 758e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 *outMicLevel, 759e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 vadLogRatio, 760e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 echo, WebRtc_UWord8 *saturationWarning) 761e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 762e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord32 tmpU32; 763e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 Rxx16w32, tmp32; 764e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 inMicLevelTmp, lastMicVol; 765e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 i; 766e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord8 saturated = 0; 767e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 768e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 769e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)state; 770e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = WEBRTC_SPL_LSHIFT_W32(inMicLevel, stt->scale); 771e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 772e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (inMicLevelTmp > stt->maxAnalog) 773e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 774e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 775e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "\tAGC->ProcessAnalog, frame %d: micLvl > maxAnalog\n", stt->fcount); 776e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 777e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 778e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (inMicLevelTmp < stt->minLevel) 779e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 780e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 781e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel\n", stt->fcount); 782e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 783e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 784e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 785e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 786e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->firstCall == 0) 787e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 788e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 tmpVol; 789e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->firstCall = 1; 790e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (WebRtc_Word32)51, 9); 791e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpVol = (stt->minLevel + tmp32); 792e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 793e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* If the mic level is very low at start, increase it! */ 794e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((inMicLevelTmp < tmpVol) && (stt->agcMode == kAgcModeAdaptiveAnalog)) 795e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 796e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = tmpVol; 797e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 798e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = inMicLevelTmp; 799e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 800e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 801e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Set the mic level to the previous output value if there is digital input gain */ 802e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((inMicLevelTmp == stt->maxAnalog) && (stt->micVol > stt->maxAnalog)) 803e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 804e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = stt->micVol; 805e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 806e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 807e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* If the mic level was manually changed to a very low value raise it! */ 808e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((inMicLevelTmp != stt->micVol) && (inMicLevelTmp < stt->minOutput)) 809e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 810e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (WebRtc_Word32)51, 9); 811e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = (stt->minLevel + tmp32); 812e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = inMicLevelTmp; 813e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 814e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //stt->numBlocksMicLvlSat = 0; 815e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 816e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 817e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 818e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\tAGC->ProcessAnalog, frame %d: micLvl < minLevel by manual decrease, raise vol\n", 819e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount); 820e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 821e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 822e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 823e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (inMicLevelTmp != stt->micVol) 824e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 825e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Incoming level mismatch; update our level. 826e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // This could be the case if the volume is changed manually, or if the 827e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // sound device has a low volume resolution. 828e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = inMicLevelTmp; 829e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 830e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 831e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (inMicLevelTmp > stt->maxLevel) 832e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 833e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Always allow the user to raise the volume above the maxLevel. 834e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxLevel = inMicLevelTmp; 835e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 836e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 837e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Store last value here, after we've taken care of manual updates etc. 838e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent lastMicVol = stt->micVol; 839e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 840e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Checks if the signal is saturated. Also a check if individual samples 841e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * are larger than 12000 is done. If they are the counter for increasing 842e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * the volume level is set to -100ms 843e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 844e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_SaturationCtrl(stt, &saturated, stt->env[0]); 845e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 846e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* The AGC is always allowed to lower the level if the signal is saturated */ 847e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (saturated == 1) 848e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 849e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Lower the recording level 850e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Rxx160_LP is adjusted down because it is so slow it could 851e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * cause the AGC to make wrong decisions. */ 852e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* stt->Rxx160_LPw32 *= 0.875; */ 853e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 3), 7); 854e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 855e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->zeroCtrlMax = stt->micVol; 856e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 857e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* stt->micVol *= 0.903; */ 858e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = inMicLevelTmp - stt->minLevel; 859e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpU32 = WEBRTC_SPL_UMUL(29591, (WebRtc_UWord32)(tmp32)); 860e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel; 861e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > lastMicVol - 2) 862e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 863e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = lastMicVol - 2; 864e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 865e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = stt->micVol; 866e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 867e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 868e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 869e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\tAGC->ProcessAnalog, frame %d: saturated, micVol = %d\n", 870e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount, stt->micVol); 871e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 872e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 873e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol < stt->minOutput) 874e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 875e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *saturationWarning = 1; 876e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 877e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 878e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Reset counter for decrease of volume level to avoid 879e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * decreasing too much. The saturation control can still 880e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * lower the level if needed. */ 881e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = -100; 882e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 883e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Enable the control mechanism to ensure that our measure, 884e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Rxx160_LP, is in the correct range. This must be done since 885e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * the measure is very slow. */ 886e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->activeSpeech = 0; 887e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32Max = 0; 888e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 889e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Reset to initial values */ 890e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msecSpeechInnerChange = kMsecSpeechInner; 891e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msecSpeechOuterChange = kMsecSpeechOuter; 892e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode = 0; 893e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 894e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->muteGuardMs = 0; 895e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 896e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->upperLimit = stt->startUpperLimit; 897e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowerLimit = stt->startLowerLimit; 898e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 899e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //stt->numBlocksMicLvlSat = 0; 900e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 901e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 902e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 903e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check if the input speech is zero. If so the mic volume 904e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * is increased. On some computers the input is zero up as high 905e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * level as 17% */ 906e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_ZeroCtrl(stt, &inMicLevelTmp, stt->env[0]); 907e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 908e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check if the near end speaker is inactive. 909e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * If that is the case the VAD threshold is 910e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * increased since the VAD speech model gets 911e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * more sensitive to any sound after a long 912e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * silence. 913e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 914e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_SpeakerInactiveCtrl(stt); 915e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 916e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < 5; i++) 917e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 918e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Computed on blocks of 16 samples */ 919e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 920e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Rxx16w32 = stt->Rxx16w32_array[0][i]; 921e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 922e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Rxx160w32 in Q(-7) */ 923e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(Rxx16w32 - stt->Rxx16_vectorw32[stt->Rxx16pos], 3); 924e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160w32 = stt->Rxx160w32 + tmp32; 925e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_vectorw32[stt->Rxx16pos] = Rxx16w32; 926e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 927e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Circular buffer */ 928c55a96383497a772a307b346368133960b02ad03Eric Laurent stt->Rxx16pos++; 929c55a96383497a772a307b346368133960b02ad03Eric Laurent if (stt->Rxx16pos == RXX_BUFFER_LEN) 930e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 931e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16pos = 0; 932e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 933e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 934e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Rxx16_LPw32 in Q(-4) */ 935e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(Rxx16w32 - stt->Rxx16_LPw32, kAlphaShortTerm); 936e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32 = (stt->Rxx16_LPw32) + tmp32; 937e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 938e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (vadLogRatio > stt->vadThreshold) 939e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 940e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Speech detected! */ 941e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 942e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check if Rxx160_LP is in the correct range. If 943e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * it is too high/low then we set it to the maximum of 944e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Rxx16_LPw32 during the first 200ms of speech. 945e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 946e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->activeSpeech < 250) 947e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 948e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->activeSpeech += 2; 949e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 950e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->Rxx16_LPw32 > stt->Rxx16_LPw32Max) 951e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 952e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32Max = stt->Rxx16_LPw32; 953e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 954e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->activeSpeech == 250) 955e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 956e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->activeSpeech += 2; 957e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx16_LPw32Max, 3); 958e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, RXX_BUFFER_LEN); 959e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 960e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 961e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160w32 - stt->Rxx160_LPw32, kAlphaLongTerm); 962e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = stt->Rxx160_LPw32 + tmp32; 963e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 964e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->Rxx160_LPw32 > stt->upperSecondaryLimit) 965e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 966e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh += 2; 967e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow = 0; 968e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode = 0; 969e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 970e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->msTooHigh > stt->msecSpeechOuterChange) 971e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 972e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = 0; 973e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 974e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Lower the recording level */ 975e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */ 976e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 977e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 53); 978e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 979e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Reduce the max gain to avoid excessive oscillation 980e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * (but never drop below the maximum analog level). 981e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16; 982e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 983e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = (15 * stt->maxLevel) + stt->micVol; 984e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 4); 985e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog); 986e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 987e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->zeroCtrlMax = stt->micVol; 988e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 989e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* 0.95 in Q15 */ 990e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = inMicLevelTmp - stt->minLevel; 991e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpU32 = WEBRTC_SPL_UMUL(31130, (WebRtc_UWord32)(tmp32)); 992e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel; 993e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > lastMicVol - 1) 994e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 995e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = lastMicVol - 1; 996e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 997e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = stt->micVol; 998e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 999e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Enable the control mechanism to ensure that our measure, 1000e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Rxx160_LP, is in the correct range. 1001e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 1002e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->activeSpeech = 0; 1003e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32Max = 0; 1004e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1005e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //stt->numBlocksMicLvlSat = 0; 1006e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1007e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1008e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1009e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\tAGC->ProcessAnalog, frame %d: measure > 2ndUpperLim, micVol = %d, maxLevel = %d\n", 1010e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount, stt->micVol, stt->maxLevel); 1011e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1012e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1013e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->Rxx160_LPw32 > stt->upperLimit) 1014e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1015e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh += 2; 1016e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow = 0; 1017e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode = 0; 1018e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1019e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->msTooHigh > stt->msecSpeechInnerChange) 1020e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1021e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Lower the recording level */ 1022e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = 0; 1023e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Multiply by 0.828125 which corresponds to decreasing ~0.8dB */ 1024e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 1025e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 53); 1026e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1027e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Reduce the max gain to avoid excessive oscillation 1028e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * (but never drop below the maximum analog level). 1029e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * stt->maxLevel = (15 * stt->maxLevel + stt->micVol) / 16; 1030e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 1031e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = (15 * stt->maxLevel) + stt->micVol; 1032e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxLevel = WEBRTC_SPL_RSHIFT_W32(tmp32, 4); 1033e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxLevel = WEBRTC_SPL_MAX(stt->maxLevel, stt->maxAnalog); 1034e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1035e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->zeroCtrlMax = stt->micVol; 1036e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1037e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* 0.965 in Q15 */ 1038e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = inMicLevelTmp - stt->minLevel; 1039e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpU32 = WEBRTC_SPL_UMUL(31621, (WebRtc_UWord32)(inMicLevelTmp - stt->minLevel)); 1040e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 15) + stt->minLevel; 1041e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > lastMicVol - 1) 1042e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1043e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = lastMicVol - 1; 1044e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1045e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = stt->micVol; 1046e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1047e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1048e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //stt->numBlocksMicLvlSat = 0; 1049e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1050e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1051e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1052e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\tAGC->ProcessAnalog, frame %d: measure > UpperLim, micVol = %d, maxLevel = %d\n", 1053e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount, stt->micVol, stt->maxLevel); 1054e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1055e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1056e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->Rxx160_LPw32 < stt->lowerSecondaryLimit) 1057e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1058e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = 0; 1059e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode = 0; 1060e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow += 2; 1061e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1062e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->msTooLow > stt->msecSpeechOuterChange) 1063e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1064e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Raise the recording level */ 1065e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 index, weightFIX; 1066e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 volNormFIX = 16384; // =1 in Q14. 1067e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1068e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow = 0; 1069e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1070e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Normalize the volume level */ 1071e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_LSHIFT_W32(inMicLevelTmp - stt->minLevel, 14); 1072e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->maxInit != stt->minLevel) 1073e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1074e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent volNormFIX = (WebRtc_Word16)WEBRTC_SPL_DIV(tmp32, 1075e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent (stt->maxInit - stt->minLevel)); 1076e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1077e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1078e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Find correct curve */ 1079e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_ExpCurve(volNormFIX, &index); 1080e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1081e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Compute weighting factor for the volume increase, 32^(-2*X)/2+1.05 */ 1082e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent weightFIX = kOffset1[index] 1083e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent - (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(kSlope1[index], 1084e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent volNormFIX, 13); 1085e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1086e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */ 1087e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 1088e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 67); 1089e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1090e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = inMicLevelTmp - stt->minLevel; 1091e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpU32 = ((WebRtc_UWord32)weightFIX * (WebRtc_UWord32)(inMicLevelTmp - stt->minLevel)); 1092e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 14) + stt->minLevel; 1093e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol < lastMicVol + 2) 1094e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1095e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = lastMicVol + 2; 1096e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1097e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1098e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = stt->micVol; 1099e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Count ms in level saturation */ 1102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //if (stt->micVol > stt->maxAnalog) { 1103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > 150) 1104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* mic level is saturated */ 1106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->numBlocksMicLvlSat++; 1107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat); 1108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\tAGC->ProcessAnalog, frame %d: measure < 2ndLowerLim, micVol = %d\n", 1113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount, stt->micVol); 1114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->Rxx160_LPw32 < stt->lowerLimit) 1117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = 0; 1119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode = 0; 1120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow += 2; 1121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->msTooLow > stt->msecSpeechInnerChange) 1123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Raise the recording level */ 1125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 index, weightFIX; 1126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 volNormFIX = 16384; // =1 in Q14. 1127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow = 0; 1129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Normalize the volume level */ 1131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_LSHIFT_W32(inMicLevelTmp - stt->minLevel, 14); 1132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->maxInit != stt->minLevel) 1133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent volNormFIX = (WebRtc_Word16)WEBRTC_SPL_DIV(tmp32, 1135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent (stt->maxInit - stt->minLevel)); 1136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Find correct curve */ 1139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_ExpCurve(volNormFIX, &index); 1140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Compute weighting factor for the volume increase, (3.^(-2.*X))/8+1 */ 1142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent weightFIX = kOffset2[index] 1143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent - (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(kSlope2[index], 1144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent volNormFIX, 13); 1145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* stt->Rxx160_LPw32 *= 1.047 [~0.2 dB]; */ 1147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32(stt->Rxx160_LPw32, 6); 1148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = WEBRTC_SPL_MUL(tmp32, 67); 1149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = inMicLevelTmp - stt->minLevel; 1151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpU32 = ((WebRtc_UWord32)weightFIX * (WebRtc_UWord32)(inMicLevelTmp - stt->minLevel)); 1152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = (WebRtc_Word32)WEBRTC_SPL_RSHIFT_U32(tmpU32, 14) + stt->minLevel; 1153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol < lastMicVol + 1) 1154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = lastMicVol + 1; 1156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = stt->micVol; 1159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Count ms in level saturation */ 1162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //if (stt->micVol > stt->maxAnalog) { 1163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > 150) 1164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* mic level is saturated */ 1166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->numBlocksMicLvlSat++; 1167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stderr, "Sat mic Level: %d\n", stt->numBlocksMicLvlSat); 1168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "\tAGC->ProcessAnalog, frame %d: measure < LowerLim, micVol = %d\n", 1173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount, stt->micVol); 1174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 1178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* The signal is inside the desired range which is: 1180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * lowerLimit < Rxx160_LP/640 < upperLimit 1181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 1182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->changeToSlowMode > 4000) 1183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msecSpeechInnerChange = 1000; 1185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msecSpeechOuterChange = 500; 1186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->upperLimit = stt->upperPrimaryLimit; 1187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowerLimit = stt->lowerPrimaryLimit; 1188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 1189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode += 2; // in milliseconds 1191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow = 0; 1193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = 0; 1194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = inMicLevelTmp; 1196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->numBlocksMicLvlSat > NUM_BLOCKS_IN_SAT_BEFORE_CHANGE_TARGET) 1200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micLvlSat = 1; 1202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stderr, "target before = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx); 1203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_UpdateAgcThresholds(stt); 1204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]), 1205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->compressionGaindB, stt->targetLevelDbfs, stt->limiterEnable, 1206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->analogTarget); 1207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->numBlocksMicLvlSat = 0; 1208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micLvlSat = 0; 1209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stderr, "target offset = %d\n", stt->targetIdxOffset); 1210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stderr, "target after = %d (%d)\n", stt->analogTargetLevel, stt->targetIdx); 1211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Ensure gain is not increased in presence of echo or after a mute event 1217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * (but allow the zeroCtrl() increase on the frame of a mute detection). 1218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 1219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (echo == 1 || (stt->muteGuardMs > 0 && stt->muteGuardMs < kMuteGuardTimeMs)) 1220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > lastMicVol) 1222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = lastMicVol; 1224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* limit the gain */ 1228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->micVol > stt->maxLevel) 1229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = stt->maxLevel; 1231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->micVol < stt->minOutput) 1232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = stt->minOutput; 1234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *outMicLevel = WEBRTC_SPL_RSHIFT_W32(stt->micVol, stt->scale); 1237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (*outMicLevel > WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog, stt->scale)) 1238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *outMicLevel = WEBRTC_SPL_RSHIFT_W32(stt->maxAnalog, stt->scale); 1240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_Process(void *agcInst, const WebRtc_Word16 *in_near, 1246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word16 *in_near_H, WebRtc_Word16 samples, 1247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 *out, WebRtc_Word16 *out_H, WebRtc_Word32 inMicLevel, 1248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 *outMicLevel, WebRtc_Word16 echo, 1249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord8 *saturationWarning) 1250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 1252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 inMicLevelTmp; 1253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 subFrames, i; 1254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_UWord8 satWarningTmp = 0; 1255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)agcInst; 1257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // 1259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt == NULL) 1260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // 1264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 8000) 1267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((samples != 80) && (samples != 160)) 1269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->Process, frame %d: Invalid number of samples\n\n", stt->fcount); 1273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 80; 1277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->fs == 16000) 1278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((samples != 160) && (samples != 320)) 1280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->Process, frame %d: Invalid number of samples\n\n", stt->fcount); 1284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1285e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1287e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 1288e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else if (stt->fs == 32000) 1289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((samples != 160) && (samples != 320)) 1291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG //test log 1293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->Process, frame %d: Invalid number of samples\n\n", stt->fcount); 1295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent subFrames = 160; 1299e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 1300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG// test log 1302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->Process, frame %d: Invalid sample rate\n\n", stt->fcount); 1304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check for valid pointers based on sampling rate */ 1309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 32000 && in_near_H == NULL) 1310e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Check for valid pointers for low band */ 1314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (in_near == NULL) 1315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1316e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1317e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1318e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1319e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *saturationWarning = 0; 1320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent //TODO: PUT IN RANGE CHECKING FOR INPUT LEVELS 1321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *outMicLevel = inMicLevel; 1322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = inMicLevel; 1323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1324c55a96383497a772a307b346368133960b02ad03Eric Laurent // TODO(andrew): clearly we don't need input and output pointers... 1325c55a96383497a772a307b346368133960b02ad03Eric Laurent // Change the interface to take a shared input/output. 1326c55a96383497a772a307b346368133960b02ad03Eric Laurent if (in_near != out) 1327c55a96383497a772a307b346368133960b02ad03Eric Laurent { 1328c55a96383497a772a307b346368133960b02ad03Eric Laurent // Only needed if they don't already point to the same place. 1329c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(out, in_near, samples * sizeof(WebRtc_Word16)); 1330c55a96383497a772a307b346368133960b02ad03Eric Laurent } 1331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->fs == 32000) 1332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1333c55a96383497a772a307b346368133960b02ad03Eric Laurent if (in_near_H != out_H) 1334c55a96383497a772a307b346368133960b02ad03Eric Laurent { 1335c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(out_H, in_near_H, samples * sizeof(WebRtc_Word16)); 1336c55a96383497a772a307b346368133960b02ad03Eric Laurent } 1337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1339e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount++; 1341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < samples; i += subFrames) 1344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAgc_ProcessDigital(&stt->digitalAgc, &in_near[i], &in_near_H[i], &out[i], &out_H[i], 1346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fs, stt->lowLevelSignal) == -1) 1347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "AGC->Process, frame %d: Error from DigAGC\n\n", stt->fcount); 1350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1351e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((stt->agcMode < kAgcModeFixedDigital) && ((stt->lowLevelSignal == 0) 1354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent || (stt->agcMode != kAgcModeAdaptiveDigital))) 1355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAgc_ProcessAnalog(agcInst, inMicLevelTmp, outMicLevel, 1357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->vadMic.logRatio, echo, saturationWarning) == -1) 1358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1363e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->agcLog, "%5d\t%d\t%d\t%d\n", stt->fcount, inMicLevelTmp, *outMicLevel, stt->maxLevel, stt->micVol); 1364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* update queue */ 1367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->inQueue > 1) 1368e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1369e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent memcpy(stt->env[0], stt->env[1], 10 * sizeof(WebRtc_Word32)); 1370e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent memcpy(stt->Rxx16w32_array[0], stt->Rxx16w32_array[1], 5 * sizeof(WebRtc_Word32)); 1371e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1372e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->inQueue > 0) 1374e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->inQueue--; 1376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* If 20ms frames are used the input mic level must be updated so that 1379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * the analog AGC does not think that there has been a manual volume 1380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * change. */ 1381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent inMicLevelTmp = *outMicLevel; 1382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Store a positive saturation warning. */ 1384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (*saturationWarning == 1) 1385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent satWarningTmp = 1; 1387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Trigger the saturation warning if displayed by any of the frames. */ 1391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *saturationWarning = satWarningTmp; 1392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1395e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1396e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_set_config(void *agcInst, WebRtcAgc_config_t agcConfig) 1397e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1398e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 1399e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)agcInst; 1400e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt == NULL) 1402e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1403e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1404e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1405e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1406e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->initFlag != kInitCheck) 1407e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1408e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_UNINITIALIZED_ERROR; 1409e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1410e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1411e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1412e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (agcConfig.limiterEnable != kAgcFalse && agcConfig.limiterEnable != kAgcTrue) 1413e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1414e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_BAD_PARAMETER_ERROR; 1415e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1416e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1417e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->limiterEnable = agcConfig.limiterEnable; 1418e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->compressionGaindB = agcConfig.compressionGaindB; 1419e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((agcConfig.targetLevelDbfs < 0) || (agcConfig.targetLevelDbfs > 31)) 1420e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1421e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_BAD_PARAMETER_ERROR; 1422e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1423e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1424e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->targetLevelDbfs = agcConfig.targetLevelDbfs; 1425e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1426e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->agcMode == kAgcModeFixedDigital) 1427e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1428e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Adjust for different parameter interpretation in FixedDigital mode */ 1429e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->compressionGaindB += agcConfig.targetLevelDbfs; 1430e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1431e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1432e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Update threshold levels for analog adaptation */ 1433e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_UpdateAgcThresholds(stt); 1434e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1435e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Recalculate gain table */ 1436e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAgc_CalculateGainTable(&(stt->digitalAgc.gainTable[0]), stt->compressionGaindB, 1437e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->targetLevelDbfs, stt->limiterEnable, stt->analogTarget) == -1) 1438e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1439e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1440e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "AGC->set_config, frame %d: Error from calcGainTable\n\n", stt->fcount); 1441e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1442e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1443e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1444e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Store the config in a WebRtcAgc_config_t */ 1445e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->usedConfig.compressionGaindB = agcConfig.compressionGaindB; 1446e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->usedConfig.limiterEnable = agcConfig.limiterEnable; 1447e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->usedConfig.targetLevelDbfs = agcConfig.targetLevelDbfs; 1448e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1449e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1450e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1451e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1452e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_get_config(void *agcInst, WebRtcAgc_config_t *config) 1453e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1454e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 1455e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)agcInst; 1456e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1457e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt == NULL) 1458e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1459e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1460e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1461e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1462e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (config == NULL) 1463e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1464e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_NULL_POINTER_ERROR; 1465e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1466e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1467e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1468e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->initFlag != kInitCheck) 1469e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1470e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_UNINITIALIZED_ERROR; 1471e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1472e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1473e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1474e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config->limiterEnable = stt->usedConfig.limiterEnable; 1475e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config->targetLevelDbfs = stt->usedConfig.targetLevelDbfs; 1476e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config->compressionGaindB = stt->usedConfig.compressionGaindB; 1477e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1478e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1479e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1480e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1481e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_Create(void **agcInst) 1482e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1483e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 1484e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (agcInst == NULL) 1485e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1486e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1487e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1488e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)malloc(sizeof(Agc_t)); 1489e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1490e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *agcInst = stt; 1491e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt == NULL) 1492e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1493e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1494e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1495e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1496e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG 1497e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fpt = fopen("./agc_test_log.txt", "wt"); 1498e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->agcLog = fopen("./agc_debug_log.txt", "wt"); 1499e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->digitalAgc.logFile = fopen("./agc_log.txt", "wt"); 1500e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1501e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1502e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->initFlag = 0; 1503e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = 0; 1504e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1505e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1506e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1507e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1508e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_Free(void *state) 1509e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1510e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 1511e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1512e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)state; 1513e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG 1514e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fclose(stt->fpt); 1515e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fclose(stt->agcLog); 1516e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fclose(stt->digitalAgc.logFile); 1517e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1518e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent free(stt); 1519e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1520e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1521e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1522e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1523e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* minLevel - Minimum volume level 1524e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * maxLevel - Maximum volume level 1525e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 1526e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_Init(void *agcInst, WebRtc_Word32 minLevel, WebRtc_Word32 maxLevel, 1527e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 agcMode, WebRtc_UWord32 fs) 1528e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1529e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 max_add, tmp32; 1530e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 i; 1531e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int tmpNorm; 1532e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Agc_t *stt; 1533e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1534e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* typecast state pointer */ 1535e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt = (Agc_t *)agcInst; 1536e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1537e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAgc_InitDigital(&stt->digitalAgc, agcMode) != 0) 1538e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1539e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_UNINITIALIZED_ERROR; 1540e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1541e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1542e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1543e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Analog AGC variables */ 1544e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->envSum = 0; 1545e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1546e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* mode = 0 - Only saturation protection 1547e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 1 - Analog Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)] 1548e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 2 - Digital Automatic Gain Control [-targetLevelDbfs (default -3 dBOv)] 1549e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 3 - Fixed Digital Gain [compressionGaindB (default 8 dB)] 1550e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 1551e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1552e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fcount = 0; 1553e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "AGC->Init\n"); 1554e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1555e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (agcMode < kAgcModeUnchanged || agcMode > kAgcModeFixedDigital) 1556e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1557e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1558e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "AGC->Init: error, incorrect mode\n\n"); 1559e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1560e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1561e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1562e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->agcMode = agcMode; 1563e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->fs = fs; 1564e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1565e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* initialize input VAD */ 1566e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcAgc_InitVad(&stt->vadMic); 1567e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1568e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* If the volume range is smaller than 0-256 then 1569e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * the levels are shifted up to Q8-domain */ 1570e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpNorm = WebRtcSpl_NormU32((WebRtc_UWord32)maxLevel); 1571e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->scale = tmpNorm - 23; 1572e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->scale < 0) 1573e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1574e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->scale = 0; 1575e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1576e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // TODO(bjornv): Investigate if we really need to scale up a small range now when we have 1577e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // a guard against zero-increments. For now, we do not support scale up (scale = 0). 1578e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->scale = 0; 1579e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent maxLevel = WEBRTC_SPL_LSHIFT_W32(maxLevel, stt->scale); 1580e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent minLevel = WEBRTC_SPL_LSHIFT_W32(minLevel, stt->scale); 1581e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1582e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Make minLevel and maxLevel static in AdaptiveDigital */ 1583e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->agcMode == kAgcModeAdaptiveDigital) 1584e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1585e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent minLevel = 0; 1586e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent maxLevel = 255; 1587e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->scale = 0; 1588e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1589e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* The maximum supplemental volume range is based on a vague idea 1590e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * of how much lower the gain will be than the real analog gain. */ 1591e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent max_add = WEBRTC_SPL_RSHIFT_W32(maxLevel - minLevel, 2); 1592e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1593e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Minimum/maximum volume level that can be set */ 1594e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->minLevel = minLevel; 1595e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxAnalog = maxLevel; 1596e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxLevel = maxLevel + max_add; 1597e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->maxInit = stt->maxLevel; 1598e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1599e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->zeroCtrlMax = stt->maxAnalog; 1600e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1601e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Initialize micVol parameter */ 1602e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = stt->maxAnalog; 1603e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (stt->agcMode == kAgcModeAdaptiveDigital) 1604e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1605e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micVol = 127; /* Mid-point of mic level */ 1606e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1607e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micRef = stt->micVol; 1608e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micGainIdx = 127; 1609e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1610e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->numBlocksMicLvlSat = 0; 1611e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->micLvlSat = 0; 1612e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1613e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1614e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, 1615e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "AGC->Init: minLevel = %d, maxAnalog = %d, maxLevel = %d\n", 1616e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->minLevel, stt->maxAnalog, stt->maxLevel); 1617e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1618e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1619e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Minimum output volume is 4% higher than the available lowest volume level */ 1620e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp32 = WEBRTC_SPL_RSHIFT_W32((stt->maxLevel - stt->minLevel) * (WebRtc_Word32)10, 8); 1621e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->minOutput = (stt->minLevel + tmp32); 1622e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1623e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooLow = 0; 1624e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msTooHigh = 0; 1625e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->changeToSlowMode = 0; 1626e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->firstCall = 0; 1627e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msZero = 0; 1628e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->muteGuardMs = 0; 1629e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->gainTableIdx = 0; 1630e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1631e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msecSpeechInnerChange = kMsecSpeechInner; 1632e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->msecSpeechOuterChange = kMsecSpeechOuter; 1633e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1634e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->activeSpeech = 0; 1635e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32Max = 0; 1636e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1637e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->vadThreshold = kNormalVadThreshold; 1638e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->inActive = 0; 1639e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1640e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < RXX_BUFFER_LEN; i++) 1641e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1642e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_vectorw32[i] = (WebRtc_Word32)1000; /* -54dBm0 */ 1643e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1644e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160w32 = 125 * RXX_BUFFER_LEN; /* (stt->Rxx16_vectorw32[0]>>3) = 125 */ 1645e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1646e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16pos = 0; 1647e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16_LPw32 = (WebRtc_Word32)16284; /* Q(-4) */ 1648e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1649e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < 5; i++) 1650e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1651e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx16w32_array[0][i] = 0; 1652e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1653e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (i = 0; i < 20; i++) 1654e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1655e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->env[0][i] = 0; 1656e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1657e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->inQueue = 0; 1658e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1659e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef MIC_LEVEL_FEEDBACK 1660e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->targetIdxOffset = 0; 1661e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1662e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1663e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtcSpl_MemSetW32(stt->filterState, 0, 8); 1664e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1665e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->initFlag = kInitCheck; 1666e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Default config settings. 1667e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->defaultConfig.limiterEnable = kAgcTrue; 1668e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->defaultConfig.targetLevelDbfs = AGC_DEFAULT_TARGET_LEVEL; 1669e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->defaultConfig.compressionGaindB = AGC_DEFAULT_COMP_GAIN; 1670e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1671e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAgc_set_config(stt, stt->defaultConfig) == -1) 1672e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1673e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lastError = AGC_UNSPECIFIED_ERROR; 1674e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1675e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1676e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->Rxx160_LPw32 = stt->analogTargetLevel; // Initialize rms value 1677e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1678e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stt->lowLevelSignal = 0; 1679e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1680e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent /* Only positive values are allowed that are not too large */ 1681e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((minLevel >= maxLevel) || (maxLevel & 0xFC000000)) 1682e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1683e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1684e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "minLevel, maxLevel value(s) are invalid\n\n"); 1685e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1686e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1687e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 1688e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1689e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef AGC_DEBUG//test log 1690e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent fprintf(stt->fpt, "\n"); 1691e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 1692e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1693e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1694e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1695e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1696e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAgc_Version(WebRtc_Word8 *versionStr, WebRtc_Word16 length) 1697e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 1698e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word8 version[] = "AGC 1.7.0"; 1699e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const WebRtc_Word16 versionLen = (WebRtc_Word16)strlen(version) + 1; 1700e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1701e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (versionStr == NULL) 1702e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1703e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1704e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1705e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1706e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (versionLen > length) 1707e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 1708e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 1709e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 1710e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 1711e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent strncpy(versionStr, version, versionLen); 1712e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 1713e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 1714