1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org#include "webrtc/modules/audio_processing/aecm/aecm_core.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <assert.h> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stddef.h> 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdlib.h> 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 17c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org#include "webrtc/common_audio/signal_processing/include/real_fft.h" 18c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org#include "webrtc/modules/audio_processing/aecm/include/echo_control_mobile.h" 199fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" 20c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org#include "webrtc/modules/audio_processing/utility/ring_buffer.h" 21221798a7c4ad83ba7fb8b3ae39b99d44278bbe5aandrew@webrtc.org#include "webrtc/system_wrappers/interface/compile_assert_c.h" 22c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org#include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" 23c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org#include "webrtc/typedefs.h" 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef AEC_DEBUG 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgFILE *dfile; 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgFILE *testfile; 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 30ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgconst int16_t WebRtcAecm_kCosTable[] = { 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8192, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112, 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8091, 8067, 8041, 8012, 7982, 7948, 7912, 7874, 7834, 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7791, 7745, 7697, 7647, 7595, 7540, 7483, 7424, 7362, 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7299, 7233, 7164, 7094, 7021, 6947, 6870, 6791, 6710, 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6627, 6542, 6455, 6366, 6275, 6182, 6087, 5991, 5892, 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5792, 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 3845, 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3719, 3591, 3462, 3331, 3200, 3068, 2935, 2801, 2667, 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2531, 2395, 2258, 2120, 1981, 1842, 1703, 1563, 1422, 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1281, 1140, 998, 856, 713, 571, 428, 285, 142, 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, -142, -285, -428, -571, -713, -856, -998, -1140, 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395, 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591, 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -3719, -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698, 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, -5690, 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455, -6542, 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233, 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745, 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7791, -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067, 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -8091, -8112, -8130, -8147, -8160, -8172, -8180, -8187, -8190, 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -8191, -8190, -8187, -8180, -8172, -8160, -8147, -8130, -8112, 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834, 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362, 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710, 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -6627, -6542, -6455, -6366, -6275, -6182, -6087, -5991, -5892, 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -5792, -5690, -5586, -5481, -5374, -5265, -5155, -5043, -4930, 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971, -3845, 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667, 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -1281, -1140, -998, -856, -713, -571, -428, -285, -142, 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 142, 285, 428, 571, 713, 856, 998, 1140, 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1281, 1422, 1563, 1703, 1842, 1981, 2120, 2258, 2395, 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2531, 2667, 2801, 2935, 3068, 3200, 3331, 3462, 3591, 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3719, 3845, 3971, 4095, 4219, 4341, 4461, 4580, 4698, 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4815, 4930, 5043, 5155, 5265, 5374, 5481, 5586, 5690, 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5792, 5892, 5991, 6087, 6182, 6275, 6366, 6455, 6542, 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6627, 6710, 6791, 6870, 6947, 7021, 7094, 7164, 7233, 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7299, 7362, 7424, 7483, 7540, 7595, 7647, 7697, 7745, 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 8067, 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8091, 8112, 8130, 8147, 8160, 8172, 8180, 8187, 8190 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 73ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgconst int16_t WebRtcAecm_kSinTable[] = { 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0, 142, 285, 428, 571, 713, 856, 998, 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1140, 1281, 1422, 1563, 1703, 1842, 1981, 2120, 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2258, 2395, 2531, 2667, 2801, 2935, 3068, 3200, 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3331, 3462, 3591, 3719, 3845, 3971, 4095, 4219, 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4341, 4461, 4580, 4698, 4815, 4930, 5043, 5155, 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5265, 5374, 5481, 5586, 5690, 5792, 5892, 5991, 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6087, 6182, 6275, 6366, 6455, 6542, 6627, 6710, 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6791, 6870, 6947, 7021, 7094, 7164, 7233, 7299, 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7362, 7424, 7483, 7540, 7595, 7647, 7697, 7745, 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8067, 8091, 8112, 8130, 8147, 8160, 8172, 8180, 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8187, 8190, 8191, 8190, 8187, 8180, 8172, 8160, 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 8147, 8130, 8112, 8091, 8067, 8041, 8012, 7982, 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7948, 7912, 7874, 7834, 7791, 7745, 7697, 7647, 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7595, 7540, 7483, 7424, 7362, 7299, 7233, 7164, 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7094, 7021, 6947, 6870, 6791, 6710, 6627, 6542, 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6455, 6366, 6275, 6182, 6087, 5991, 5892, 5792, 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3845, 3719, 3591, 3462, 3331, 3200, 3068, 2935, 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2801, 2667, 2531, 2395, 2258, 2120, 1981, 1842, 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1703, 1563, 1422, 1281, 1140, 998, 856, 713, 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 571, 428, 285, 142, 0, -142, -285, -428, 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -571, -713, -856, -998, -1140, -1281, -1422, -1563, 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -1703, -1842, -1981, -2120, -2258, -2395, -2531, -2667, 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -2801, -2935, -3068, -3200, -3331, -3462, -3591, -3719, 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -3845, -3971, -4095, -4219, -4341, -4461, -4580, -4698, 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -4815, -4930, -5043, -5155, -5265, -5374, -5481, -5586, 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -5690, -5792, -5892, -5991, -6087, -6182, -6275, -6366, 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -6455, -6542, -6627, -6710, -6791, -6870, -6947, -7021, 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7094, -7164, -7233, -7299, -7362, -7424, -7483, -7540, 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7595, -7647, -7697, -7745, -7791, -7834, -7874, -7912, 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7948, -7982, -8012, -8041, -8067, -8091, -8112, -8130, 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -8147, -8160, -8172, -8180, -8187, -8190, -8191, -8190, 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -8187, -8180, -8172, -8160, -8147, -8130, -8112, -8091, 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834, 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -7362, -7299, -7233, -7164, -7094, -7021, -6947, -6870, 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -6791, -6710, -6627, -6542, -6455, -6366, -6275, -6182, 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -6087, -5991, -5892, -5792, -5690, -5586, -5481, -5374, 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -5265, -5155, -5043, -4930, -4815, -4698, -4580, -4461, 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -4341, -4219, -4096, -3971, -3845, -3719, -3591, -3462, 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -3331, -3200, -3068, -2935, -2801, -2667, -2531, -2395, 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -2258, -2120, -1981, -1842, -1703, -1563, -1422, -1281, 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -1140, -998, -856, -713, -571, -428, -285, -142 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 121ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org// Initialization table for echo channel in 8 kHz 122ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgstatic const int16_t kChannelStored8kHz[PART_LEN1] = { 123ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 2040, 1815, 1590, 1498, 1405, 1395, 1385, 1418, 124ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1451, 1506, 1562, 1644, 1726, 1804, 1882, 1918, 125ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1953, 1982, 2010, 2025, 2040, 2034, 2027, 2021, 126ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 2014, 1997, 1980, 1925, 1869, 1800, 1732, 1683, 127ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1635, 1604, 1572, 1545, 1517, 1481, 1444, 1405, 128ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1367, 1331, 1294, 1270, 1245, 1239, 1233, 1247, 129ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1260, 1282, 1303, 1338, 1373, 1407, 1441, 1470, 130ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1499, 1524, 1549, 1565, 1582, 1601, 1621, 1649, 131ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1676 132ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org}; 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 134ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org// Initialization table for echo channel in 16 kHz 135ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgstatic const int16_t kChannelStored16kHz[PART_LEN1] = { 136ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 2040, 1590, 1405, 1385, 1451, 1562, 1726, 1882, 137ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1953, 2010, 2040, 2027, 2014, 1980, 1869, 1732, 138ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1635, 1572, 1517, 1444, 1367, 1294, 1245, 1233, 139ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1260, 1303, 1373, 1441, 1499, 1549, 1582, 1621, 140ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 1676, 1741, 1802, 1861, 1921, 1983, 2040, 2102, 141ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 2170, 2265, 2375, 2515, 2651, 2781, 2922, 3075, 142ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 3253, 3471, 3738, 3976, 4151, 4258, 4308, 4288, 143ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 4270, 4253, 4237, 4179, 4086, 3947, 3757, 3484, 144ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 3153 145ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org}; 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Moves the pointer to the next entry and inserts |far_spectrum| and 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// corresponding Q-domain in its buffer. 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Inputs: 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - self : Pointer to the delay estimation instance 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - far_spectrum : Pointer to the far end spectrum 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - far_q : Q-domain of far end spectrum 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 155ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgvoid WebRtcAecm_UpdateFarHistory(AecmCore_t* self, 156ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org uint16_t* far_spectrum, 157ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org int far_q) { 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get new buffer position 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org self->far_history_pos++; 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (self->far_history_pos >= MAX_DELAY) { 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org self->far_history_pos = 0; 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update Q-domain buffer 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org self->far_q_domains[self->far_history_pos] = far_q; 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update far end spectrum buffer 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(&(self->far_history[self->far_history_pos * PART_LEN1]), 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum, 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sizeof(uint16_t) * PART_LEN1); 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Returns a pointer to the far end spectrum aligned to current near end 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// called before AlignedFarend(...). Otherwise, you get the pointer to the 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// previous frame. The memory is only valid until the next call of 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WebRtc_DelayEstimatorProcessFix(...). 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Inputs: 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - self : Pointer to the AECM instance. 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - delay : Current delay estimate. 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Output: 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - far_q : The Q-domain of the aligned far end spectrum 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Return value: 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - far_spectrum : Pointer to the aligned far end spectrum 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// NULL - Error 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 188ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgconst uint16_t* WebRtcAecm_AlignedFarend(AecmCore_t* self, 189ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org int* far_q, 190ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org int delay) { 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int buffer_position = 0; 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(self != NULL); 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer_position = self->far_history_pos - delay; 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check buffer position 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (buffer_position < 0) { 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer_position += MAX_DELAY; 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get Q-domain 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *far_q = self->far_q_domains[buffer_position]; 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Return far end spectrum 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return &(self->far_history[buffer_position * PART_LEN1]); 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Declare function pointers. 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgCalcLinearEnergies WebRtcAecm_CalcLinearEnergies; 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgStoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel; 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel; 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcAecm_CreateCore(AecmCore_t **aecmInst) 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AecmCore_t *aecm = malloc(sizeof(AecmCore_t)); 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *aecmInst = aecm; 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm == NULL) 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 219db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org aecm->farFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 220db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org sizeof(int16_t)); 221db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org if (!aecm->farFrameBuf) 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FreeCore(aecm); 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm = NULL; 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 228db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org aecm->nearNoisyFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 229db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org sizeof(int16_t)); 230db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org if (!aecm->nearNoisyFrameBuf) 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FreeCore(aecm); 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm = NULL; 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 237db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org aecm->nearCleanFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 238db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org sizeof(int16_t)); 239db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org if (!aecm->nearCleanFrameBuf) 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FreeCore(aecm); 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm = NULL; 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 246db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org aecm->outFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, 247db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org sizeof(int16_t)); 248db32d60125dfe78a1eb475f39672484c63b034b1andrew@webrtc.org if (!aecm->outFrameBuf) 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FreeCore(aecm); 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm = NULL; 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 255c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org aecm->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1, 256c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org MAX_DELAY); 257c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org if (aecm->delay_estimator_farend == NULL) { 258c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org WebRtcAecm_FreeCore(aecm); 259c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org aecm = NULL; 260c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org return -1; 261c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org } 262c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org aecm->delay_estimator = 263b5a182a9321ff847a24620c5e991e1749362549abjornv@webrtc.org WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0); 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->delay_estimator == NULL) { 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FreeCore(aecm); 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm = NULL; 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 269b7c1e03761e4f90f48f36140ba6ff17d51c01e7bbjornv@webrtc.org // TODO(bjornv): Explicitly disable robust delay validation until no 270b7c1e03761e4f90f48f36140ba6ff17d51c01e7bbjornv@webrtc.org // performance regression has been established. Then remove the line. 271b7c1e03761e4f90f48f36140ba6ff17d51c01e7bbjornv@webrtc.org WebRtc_enable_robust_validation(aecm->delay_estimator, 0); 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->real_fft = WebRtcSpl_CreateRealFFT(PART_LEN_SHIFT); 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->real_fft == NULL) { 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FreeCore(aecm); 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm = NULL; 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Init some aecm pointers. 16 and 32 byte alignment is only necessary 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for Neon code currently. 2823f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->xBuf = (int16_t*) (((uintptr_t)aecm->xBuf_buf + 31) & ~ 31); 2833f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->dBufClean = (int16_t*) (((uintptr_t)aecm->dBufClean_buf + 31) & ~ 31); 2843f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->dBufNoisy = (int16_t*) (((uintptr_t)aecm->dBufNoisy_buf + 31) & ~ 31); 2853f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->outBuf = (int16_t*) (((uintptr_t)aecm->outBuf_buf + 15) & ~ 15); 2863f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->channelStored = (int16_t*) (((uintptr_t) 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelStored_buf + 15) & ~ 15); 2883f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->channelAdapt16 = (int16_t*) (((uintptr_t) 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt16_buf + 15) & ~ 15); 2903f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->channelAdapt32 = (int32_t*) (((uintptr_t) 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32_buf + 31) & ~ 31); 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2963f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgvoid WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const int16_t* echo_path) 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i = 0; 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset the stored channel 3013f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org memcpy(aecm->channelStored, echo_path, sizeof(int16_t) * PART_LEN1); 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset the adapted channels 3033f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org memcpy(aecm->channelAdapt16, echo_path, sizeof(int16_t) * PART_LEN1); 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32( 3073f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (int32_t)(aecm->channelAdapt16[i]), 16); 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset channel storing variables 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseAdaptOld = 1000; 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseStoredOld = 1000; 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX; 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseChannelCount = 0; 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void CalcLinearEnergiesC(AecmCore_t* aecm, 3183f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const uint16_t* far_spectrum, 3193f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t* echo_est, 3203f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t* far_energy, 3213f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t* echo_energy_adapt, 3223f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t* echo_energy_stored) 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i; 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get energy for the delayed far end signal and estimated 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // echo using both stored and adapted channels. 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 3323f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (*far_energy) += (uint32_t)(far_spectrum[i]); 333ea2257fc3adfe9d4bd174426a5b09b1c78bdbca5bjornv@webrtc.org *echo_energy_adapt += aecm->channelAdapt16[i] * far_spectrum[i]; 3343f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (*echo_energy_stored) += (uint32_t)echo_est[i]; 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void StoreAdaptiveChannelC(AecmCore_t* aecm, 3393f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const uint16_t* far_spectrum, 3403f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t* echo_est) 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i; 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // During startup we store the channel every block. 3453f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(int16_t) * PART_LEN1); 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Recalculate echo estimate 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < PART_LEN; i += 4) 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org echo_est[i + 1] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1], 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i + 1]); 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org echo_est[i + 2] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2], 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i + 2]); 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org echo_est[i + 3] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3], 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i + 3]); 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void ResetAdaptiveChannelC(AecmCore_t* aecm) 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i; 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The stored channel has a significantly lower MSE than the adaptive one for 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // two consecutive calculations. Reset the adaptive channel. 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(aecm->channelAdapt16, aecm->channelStored, 3693f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * PART_LEN1); 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Restore the W32 channel 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < PART_LEN; i += 4) 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32( 3743f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (int32_t)aecm->channelStored[i], 16); 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32[i + 1] = WEBRTC_SPL_LSHIFT_W32( 3763f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (int32_t)aecm->channelStored[i + 1], 16); 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32[i + 2] = WEBRTC_SPL_LSHIFT_W32( 3783f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (int32_t)aecm->channelStored[i + 2], 16); 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32[i + 3] = WEBRTC_SPL_LSHIFT_W32( 3803f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org (int32_t)aecm->channelStored[i + 3], 16); 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3823f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)aecm->channelStored[i], 16); 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Initialize function pointers for ARM Neon platform. 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON) 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void WebRtcAecm_InitNeon(void) 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon; 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon; 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon; 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 395ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org// Initialize function pointers for MIPS platform. 396ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org#if defined(MIPS32_LE) 397ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgstatic void WebRtcAecm_InitMips(void) 398ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org{ 399ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org#if defined(MIPS_DSP_R1_LE) 400ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips; 401ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips; 402ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org#endif 403ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips; 404ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org} 405ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org#endif 406ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WebRtcAecm_InitCore(...) 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This function initializes the AECM instant created with WebRtcAecm_CreateCore(...) 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Input: 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - aecm : Pointer to the Echo Suppression instance 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - samplingFreq : Sampling Frequency 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Output: 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - aecm : Initialized instance 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Return value : 0 - Ok 418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// -1 - Error 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq) 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i = 0; 4233f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t tmp32 = PART_LEN1 * PART_LEN1; 4243f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t tmp16 = PART_LEN1; 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (samplingFreq != 8000 && samplingFreq != 16000) 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org samplingFreq = 8000; 429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // sanity check of sampling frequency 4323f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->mult = (int16_t)samplingFreq / 8000; 433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufWritePos = 0; 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufReadPos = 0; 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->knownDelay = 0; 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->lastKnownDelay = 0; 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_InitBuffer(aecm->farFrameBuf); 440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_InitBuffer(aecm->nearNoisyFrameBuf); 441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_InitBuffer(aecm->nearCleanFrameBuf); 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_InitBuffer(aecm->outFrameBuf); 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf)); 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf)); 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf)); 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf)); 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->seed = 666; 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->totCount = 0; 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 452c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) { 453c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org return -1; 454c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org } 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) { 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set far end histories to zero 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY); 460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY); 461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->far_history_pos = MAX_DELAY; 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->nlpFlag = 1; 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->fixedDelay = -1; 465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->dfaCleanQDomain = 0; 467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->dfaCleanQDomainOld = 0; 468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->dfaNoisyQDomain = 0; 469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->dfaNoisyQDomainOld = 0; 470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy)); 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farLogEnergy = 0; 473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy)); 474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy)); 475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize the echo channels with a stored shape. 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (samplingFreq == 8000) 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz); 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz); 484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt)); 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt)); 488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->noiseEstCtr = 0; 489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->cngMode = AecmTrue; 491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr)); 493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr)); 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Shape the initial noise level to an approximate pink noise. 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < (PART_LEN1 >> 1) - 1; i++) 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->noiseEst[i] = (tmp32 << 8); 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16--; 4993f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32 -= (int32_t)((tmp16 << 1) + 1); 500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (; i < PART_LEN1; i++) 502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->noiseEst[i] = (tmp32 << 8); 504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX; 507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN; 508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMaxMin = 0; 509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection at the 510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // beginning. 511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMSE = 0; 512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->currentVADValue = 0; 513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->vadUpdateCount = 0; 514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->firstVAD = 1; 515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->startupState = 0; 517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGain = SUPGAIN_DEFAULT; 518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGainOld = SUPGAIN_DEFAULT; 519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A; 521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D; 522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B; 523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D; 524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Assert a preprocessor definition at compile-time. It's an assumption 526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // used in assembly code, so check the assembly files before any change. 527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org COMPILE_ASSERT(PART_LEN % 16 == 0); 528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Initialize function pointers. 530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC; 531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC; 532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC; 533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef WEBRTC_DETECT_ARM_NEON 535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uint64_t features = WebRtc_GetCPUFeaturesARM(); 536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((features & kCPUFeatureNEON) != 0) 537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_InitNeon(); 539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#elif defined(WEBRTC_ARCH_ARM_NEON) 541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_InitNeon(); 542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 544ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org#if defined(MIPS32_LE) 545ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org WebRtcAecm_InitMips(); 546ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.org#endif 547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(bjornv): This function is currently not used. Add support for these 551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// parameters from a higher level 552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag) 553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->nlpFlag = nlpFlag; 555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->fixedDelay = delay; 556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcAecm_FreeCore(AecmCore_t *aecm) 561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm == NULL) 563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_FreeBuffer(aecm->farFrameBuf); 568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf); 569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_FreeBuffer(aecm->nearCleanFrameBuf); 570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_FreeBuffer(aecm->outFrameBuf); 571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_FreeDelayEstimator(aecm->delay_estimator); 573c7beae5a7f10192712a5d1a901f41a90f42daaffbjornv@webrtc.org WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend); 574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcSpl_FreeRealFFT(aecm->real_fft); 575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org free(aecm); 577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcAecm_ProcessFrame(AecmCore_t * aecm, 5823f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t * farend, 5833f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t * nearendNoisy, 5843f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t * nearendClean, 5853f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t * out) 586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 5873f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary. 5883f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t* outBlock = (int16_t*) (((uintptr_t) outBlock_buf + 15) & ~ 15); 589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 5903f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t farFrame[FRAME_LEN]; 591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int16_t* out_ptr = NULL; 592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int size = 0; 593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Buffer the current frame. 595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Fetch an older one corresponding to the delay. 596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN); 597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay); 598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Buffer the synchronized far and near frames, 600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // to pass the smaller blocks individually. 601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN); 602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN); 603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (nearendClean != NULL) 604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN); 606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Process as many blocks as possible. 609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN) 610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int16_t far_block[PART_LEN]; 612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int16_t* far_block_ptr = NULL; 613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int16_t near_noisy_block[PART_LEN]; 614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int16_t* near_noisy_block_ptr = NULL; 615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_ReadBuffer(aecm->farFrameBuf, (void**) &far_block_ptr, far_block, 617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PART_LEN); 618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf, 619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**) &near_noisy_block_ptr, 620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org near_noisy_block, 621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PART_LEN); 622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (nearendClean != NULL) 623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int16_t near_clean_block[PART_LEN]; 625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int16_t* near_clean_block_ptr = NULL; 626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_ReadBuffer(aecm->nearCleanFrameBuf, 628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**) &near_clean_block_ptr, 629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org near_clean_block, 630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org PART_LEN); 631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtcAecm_ProcessBlock(aecm, 632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_block_ptr, 633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org near_noisy_block_ptr, 634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org near_clean_block_ptr, 635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org outBlock) == -1) 636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtcAecm_ProcessBlock(aecm, 642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_block_ptr, 643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org near_noisy_block_ptr, 644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL, 645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org outBlock) == -1) 646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN); 652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Stuff the out buffer if we have less than a frame to output. 655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This should only happen for the first frame. 656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org size = (int) WebRtc_available_read(aecm->outFrameBuf); 657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (size < FRAME_LEN) 658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN); 660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Obtain an output frame. 663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtc_ReadBuffer(aecm->outFrameBuf, (void**) &out_ptr, out, FRAME_LEN); 664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (out_ptr != out) { 665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // ReadBuffer() hasn't copied to |out| in this case. 666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t)); 667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WebRtcAecm_AsymFilt(...) 673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Performs asymmetric filtering. 675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Inputs: 677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - filtOld : Previous filtered value. 678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - inVal : New input value. 679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - stepSizePos : Step size when we have a positive contribution. 680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// - stepSizeNeg : Step size when we have a negative contribution. 681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Output: 683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Return: - Filtered value. 685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 6863f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgint16_t WebRtcAecm_AsymFilt(const int16_t filtOld, const int16_t inVal, 6873f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t stepSizePos, 6883f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t stepSizeNeg) 689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 6903f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t retVal; 691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN)) 693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return inVal; 695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org retVal = filtOld; 697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (filtOld > inVal) 698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org retVal -= WEBRTC_SPL_RSHIFT_W16(filtOld - inVal, stepSizeNeg); 700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org retVal += WEBRTC_SPL_RSHIFT_W16(inVal - filtOld, stepSizePos); 703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return retVal; 706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 70892e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org// ExtractFractionPart(a, zeros) 70992e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org// 71092e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org// returns the fraction part of |a|, with |zeros| number of leading zeros, as an 71192e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org// int16_t scaled to Q8. There is no sanity check of |a| in the sense that the 71292e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org// number of zeros match. 71392e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.orgstatic int16_t ExtractFractionPart(uint32_t a, int zeros) { 71492e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org return (int16_t)(((a << zeros) & 0x7FFFFFFF) >> 23); 71592e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org} 71692e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org 717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WebRtcAecm_CalcEnergies(...) 718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This function calculates the log of energies for nearend, farend and estimated 720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// echoes. There is also an update of energy decision levels, i.e. internal VAD. 721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param aecm [i/o] Handle of the AECM instance. 724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param far_spectrum [in] Pointer to farend spectrum. 725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param far_q [in] Q-domain of farend spectrum. 726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param nearEner [in] Near end energy for current block in 727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Q(aecm->dfaQDomain). 728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param echoEst [out] Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16). 729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcAecm_CalcEnergies(AecmCore_t * aecm, 7313f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const uint16_t* far_spectrum, 7323f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t far_q, 7333f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const uint32_t nearEner, 7343f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t * echoEst) 735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Local variables 7373f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t tmpAdapt = 0; 7383f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t tmpStored = 0; 7393f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t tmpFar = 0; 740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i; 742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 7433f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t zeros, frac; 7443f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t tmp16; 7453f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t increase_max_shifts = 4; 7463f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t decrease_max_shifts = 11; 7473f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t increase_min_shifts = 11; 7483f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t decrease_min_shifts = 3; 7493f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t kLogLowValue = WEBRTC_SPL_LSHIFT_W16(PART_LEN_SHIFT, 7); 750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get log of near end energy and store in buffer 752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Shift buffer 754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy, 7553f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * (MAX_BUF_LEN - 1)); 756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Logarithm of integrated magnitude spectrum (nearEner) 758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = kLogLowValue; 759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (nearEner) 760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zeros = WebRtcSpl_NormU32(nearEner); 76292e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org frac = ExtractFractionPart(nearEner, zeros); 763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // log2 in Q8 764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 -= WEBRTC_SPL_LSHIFT_W16(aecm->dfaNoisyQDomain, 8); 766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->nearLogEnergy[0] = tmp16; 768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // END: Get log of near end energy 769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt, &tmpStored); 771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Shift buffers 773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy, 7743f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * (MAX_BUF_LEN - 1)); 775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy, 7763f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * (MAX_BUF_LEN - 1)); 777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Logarithm of delayed far end energy 779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = kLogLowValue; 780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmpFar) 781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zeros = WebRtcSpl_NormU32(tmpFar); 78392e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org frac = ExtractFractionPart(tmpFar, zeros); 784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // log2 in Q8 785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 -= WEBRTC_SPL_LSHIFT_W16(far_q, 8); 787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farLogEnergy = tmp16; 789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Logarithm of estimated echo energy through adapted channel 791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = kLogLowValue; 792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmpAdapt) 793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zeros = WebRtcSpl_NormU32(tmpAdapt); 79592e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org frac = ExtractFractionPart(tmpAdapt, zeros); 796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //log2 in Q8 797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8); 799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->echoAdaptLogEnergy[0] = tmp16; 801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Logarithm of estimated echo energy through stored channel 803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = kLogLowValue; 804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmpStored) 805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zeros = WebRtcSpl_NormU32(tmpStored); 80792e07ae02c00648f1a298eaaaa07d2407859db1ebjornv@webrtc.org frac = ExtractFractionPart(tmpStored, zeros); 808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //log2 in Q8 809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 += WEBRTC_SPL_LSHIFT_W16((31 - zeros), 8) + frac; 810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 -= WEBRTC_SPL_LSHIFT_W16(RESOLUTION_CHANNEL16 + far_q, 8); 811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->echoStoredLogEnergy[0] = tmp16; 813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update farend energy levels (min, max, vad, mse) 815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->farLogEnergy > FAR_ENERGY_MIN) 816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->startupState == 0) 818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org increase_max_shifts = 2; 820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org decrease_min_shifts = 2; 821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org increase_min_shifts = 8; 822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMin = WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy, 825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org increase_min_shifts, decrease_min_shifts); 826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMax = WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy, 827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org increase_max_shifts, decrease_max_shifts); 828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin); 829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Dynamic VAD region size 831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = 2560 - aecm->farEnergyMin; 832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmp16 > 0) 833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 8343f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16, FAR_ENERGY_VAD_REGION, 9); 835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = 0; 838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 += FAR_ENERGY_VAD_REGION; 840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024)) 842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // In startup phase or VAD update halted 844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyVAD = aecm->farEnergyMin + tmp16; 845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->farEnergyVAD > aecm->farLogEnergy) 848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyVAD += WEBRTC_SPL_RSHIFT_W16(aecm->farLogEnergy + 850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 - 851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyVAD, 852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 6); 853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->vadUpdateCount = 0; 854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->vadUpdateCount++; 857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put MSE threshold higher than VAD 860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8); 861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update VAD variables 864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->farLogEnergy > aecm->farEnergyVAD) 865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF)) 867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We are in startup or have significant dynamics in input speech level 869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->currentVADValue = 1; 870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->currentVADValue = 0; 874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((aecm->currentVADValue) && (aecm->firstVAD)) 876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->firstVAD = 0; 878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0]) 879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The estimated echo has higher energy than the near end signal. 881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This means that the initialization was too aggressive. Scale 882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // down by a factor 8 883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt16[i] >>= 3; 886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compensate the adapted echo energy level accordingly. 888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->echoAdaptLogEnergy[0] -= (3 << 8); 889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->firstVAD = 1; 890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WebRtcAecm_CalcStepSize(...) 895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This function calculates the step size used in channel estimation 897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param aecm [in] Handle of the AECM instance. 900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param mu [out] (Return value) Stepsize in log2(), i.e. number of shifts. 901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 9033f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgint16_t WebRtcAecm_CalcStepSize(AecmCore_t * const aecm) 904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 9063f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t tmp32; 9073f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t tmp16; 9083f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t mu = MU_MAX; 909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Here we calculate the step size mu used in the 911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // following NLMS based Channel estimation algorithm 912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!aecm->currentVADValue) 913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Far end energy level too low, no channel update 915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mu = 0; 916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (aecm->startupState > 0) 917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->farEnergyMin >= aecm->farEnergyMax) 919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mu = MU_MIN; 921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin); 924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, MU_DIFF); 925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin); 9263f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org mu = MU_MIN - 1 - (int16_t)(tmp32); 927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The -1 is an alternative to rounding. This way we get a larger 928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // stepsize, so we in some sense compensate for truncation in NLMS 929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mu < MU_MAX) 931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX 933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return mu; 937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// WebRtcAecm_UpdateChannel(...) 940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This function performs channel estimation. NLMS and decision on channel storage. 942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param aecm [i/o] Handle of the AECM instance. 945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param far_spectrum [in] Absolute value of the farend signal in Q(far_q) 946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param far_q [in] Q-domain of the farend signal 947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param dfa [in] Absolute value of the nearend signal (Q[aecm->dfaQDomain]) 948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param mu [in] NLMS step size. 949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param echoEst [i/o] Estimated echo in Q(far_q+RESOLUTION_CHANNEL16). 950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcAecm_UpdateChannel(AecmCore_t * aecm, 9523f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const uint16_t* far_spectrum, 9533f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t far_q, 9543f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const uint16_t * const dfa, 9553f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t mu, 9563f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t * echoEst) 957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 9593f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint32_t tmpU32no1, tmpU32no2; 9603f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t tmp32no1, tmp32no2; 9613f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t mseStored; 9623f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t mseAdapt; 963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i; 965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 9663f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t zerosFar, zerosNum, zerosCh, zerosDfa; 9673f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t shiftChFar, shiftNum, shift2ResChan; 9683f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t tmp16no1; 9693f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t xfaQ, dfaQ; 970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This is the channel estimation algorithm. It is base on NLMS but has a variable step 972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // length, which was calculated above. 973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mu) 974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Determine norm of channel and farend to make sure we don't get overflow in 978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // multiplication 979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]); 9803f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org zerosFar = WebRtcSpl_NormU32((uint32_t)far_spectrum[i]); 981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (zerosCh + zerosFar > 31) 982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Multiplication is safe 984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpU32no1 = WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i], 985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org shiftChFar = 0; 987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We need to shift down before multiplication 990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org shiftChFar = 32 - zerosCh - zerosFar; 991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpU32no1 = WEBRTC_SPL_UMUL_32_16( 992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], shiftChFar), 993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Determine Q-domain of numerator 996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zerosNum = WebRtcSpl_NormU32(tmpU32no1); 997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dfa[i]) 998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 9993f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org zerosDfa = WebRtcSpl_NormU32((uint32_t)dfa[i]); 1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zerosDfa = 32; 1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain - 1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RESOLUTION_CHANNEL32 - far_q + shiftChFar; 1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (zerosNum > tmp16no1 + 1) 1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org xfaQ = tmp16no1; 1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dfaQ = zerosDfa - 2; 1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org xfaQ = zerosNum - 2; 1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain - 1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org shiftChFar + xfaQ; 1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Add in the same Q-domain 1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ); 10183f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmpU32no2 = WEBRTC_SPL_SHIFT_W32((uint32_t)dfa[i], dfaQ); 10193f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no1 = (int32_t)tmpU32no2 - (int32_t)tmpU32no1; 1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org zerosNum = WebRtcSpl_NormW32(tmp32no1); 1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q))) 1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update is needed 1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This is what we would like to compute 1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i]) 1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // tmp32norm = (i + 1) 1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // aecm->channelAdapt[i] += (2^mu) * tmp32no1 1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // / (tmp32norm * far_spectrum[i]) 1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure we don't get overflow in multiplication. 1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (zerosNum + zerosFar > 31) 1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmp32no1 > 0) 1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 10393f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16(tmp32no1, 1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 10433f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16(-tmp32no1, 1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org shiftNum = 0; 1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org shiftNum = 32 - (zerosNum + zerosFar); 1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmp32no1 > 0) 1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 10523f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no2 = (int32_t)WEBRTC_SPL_UMUL_32_16( 1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_SPL_RSHIFT_W32(tmp32no1, shiftNum), 1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 10573f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no2 = -(int32_t)WEBRTC_SPL_UMUL_32_16( 1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_SPL_RSHIFT_W32(-tmp32no1, shiftNum), 1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org far_spectrum[i]); 1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Normalize with respect to frequency bin 1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1); 1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure we are in the right Q-domain 1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org shift2ResChan = shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1); 1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan) 1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no2 = WEBRTC_SPL_WORD32_MAX; 1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan); 1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1073347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org aecm->channelAdapt32[i] = 1074347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org WebRtcSpl_AddSatW32(aecm->channelAdapt32[i], tmp32no2); 1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->channelAdapt32[i] < 0) 1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We can never have negative channel gain 1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt32[i] = 0; 1079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->channelAdapt16[i] 10813f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org = (int16_t)WEBRTC_SPL_RSHIFT_W32(aecm->channelAdapt32[i], 16); 1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // END: Adaptive channel update 1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Determine if we should store or restore the channel 1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((aecm->startupState == 0) & (aecm->currentVADValue)) 1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // During startup we store the channel every block, 1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and we recalculate echo estimate 1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst); 1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->farLogEnergy < aecm->farEnergyMSE) 1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseChannelCount = 0; 1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseChannelCount++; 1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Enough data for validation. Store channel if we can. 1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10)) 1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We have enough data. 1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Calculate MSE of "Adapt" and "Stored" versions. 1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // It is actually not MSE, but average absolute error. 1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mseStored = 0; 1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mseAdapt = 0; 1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < MIN_MSE_COUNT; i++) 1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 11123f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no1 = ((int32_t)aecm->echoStoredLogEnergy[i] 11133f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org - (int32_t)aecm->nearLogEnergy[i]); 1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1); 1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mseStored += tmp32no2; 1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11173f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp32no1 = ((int32_t)aecm->echoAdaptLogEnergy[i] 11183f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org - (int32_t)aecm->nearLogEnergy[i]); 1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1); 1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mseAdapt += tmp32no2; 1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt)) 1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org & ((aecm->mseStoredOld << MSE_RESOLUTION) < (MIN_MSE_DIFF 1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * aecm->mseAdaptOld))) 1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The stored channel has a significantly lower MSE than the adaptive one for 1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // two consecutive calculations. Reset the adaptive channel. 1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_ResetAdaptiveChannel(aecm); 1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) & (mseAdapt 1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org < aecm->mseThreshold) & (aecm->mseAdaptOld < aecm->mseThreshold)) 1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The adaptive channel has a significantly lower MSE than the stored one. 1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The MSE for the adaptive channel has also been low for two consecutive 1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // calculations. Store the adaptive channel. 1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst); 1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update threshold 1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX) 1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld); 1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseThreshold += WEBRTC_SPL_MUL_16_16_RSFT(mseAdapt 1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org - WEBRTC_SPL_MUL_16_16_RSFT(aecm->mseThreshold, 5, 3), 205, 8); 1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reset counter 1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseChannelCount = 0; 1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store the MSE values. 1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseStoredOld = mseStored; 1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->mseAdaptOld = mseAdapt; 1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // END: Determine if we should store or reset channel estimate. 1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// CalcSuppressionGain(...) 1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This function calculates the suppression gain that is used in the Wiener filter. 1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param aecm [i/n] Handle of the AECM instance. 1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// @param supGain [out] (Return value) Suppression gain with which to scale the noise 1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// level (Q14). 1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// 1170ff4fc2b37cf95b67e77d5d66003409606cefbc43andrew@webrtc.orgint16_t WebRtcAecm_CalcSuppressionGain(AecmCore_t * const aecm) 1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 11723f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t tmp32no1; 1173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11743f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t supGain = SUPGAIN_DEFAULT; 11753f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t tmp16no1; 11763f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int16_t dE = 0; 1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Determine suppression gain used in the Wiener filter. The gain is based on a mix of far 1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // end energy and echo estimation error. 1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Adjust for the far end signal level. A low signal level indicates no far end signal, 1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // hence we set the suppression gain to 0 1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!aecm->currentVADValue) 1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org supGain = 0; 1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Adjust for possible double talk. If we have large variations in estimation error we 1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // likely have double talk (or poor channel). 1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] - ENERGY_DEV_OFFSET); 1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org dE = WEBRTC_SPL_ABS_W16(tmp16no1); 1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dE < ENERGY_DEV_TOL) 1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Likely no double talk. The better estimation, the more we can suppress signal. 1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update counters 1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (dE < SUPGAIN_EPC_DT) 1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffAB, dE); 1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no1 += (SUPGAIN_EPC_DT >> 1); 12003f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT); 1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org supGain = aecm->supGainErrParamA - tmp16no1; 1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no1 = WEBRTC_SPL_MUL_16_16(aecm->supGainErrParamDiffBD, 1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (ENERGY_DEV_TOL - dE)); 1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1); 12073f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, (ENERGY_DEV_TOL 1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org - SUPGAIN_EPC_DT)); 1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org supGain = aecm->supGainErrParamD + tmp16no1; 1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Likely in double talk. Use default value 1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org supGain = aecm->supGainErrParamD; 1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (supGain > aecm->supGainOld) 1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16no1 = supGain; 1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmp16no1 = aecm->supGainOld; 1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->supGainOld = supGain; 1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (tmp16no1 < aecm->supGain) 1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 12283f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4); 1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 12313f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4); 1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // END: Update suppression gain 1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return aecm->supGain; 1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcAecm_BufferFarFrame(AecmCore_t* const aecm, 12403f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org const int16_t* const farend, 1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int farLen) 1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int writeLen = farLen, writePos = 0; 1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if the write position must be wrapped 1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN) 1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Write to remaining buffer space before wrapping 1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org writeLen = FAR_BUF_LEN - aecm->farBufWritePos; 1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos, 12513f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * writeLen); 1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufWritePos = 0; 1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org writePos = writeLen; 1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org writeLen = farLen - writeLen; 1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos, 12583f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * writeLen); 1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufWritePos += writeLen; 1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 12623f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgvoid WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, int16_t * const farend, 1263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int farLen, const int knownDelay) 1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int readLen = farLen; 1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int readPos = 0; 1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int delayChange = knownDelay - aecm->lastKnownDelay; 1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufReadPos -= delayChange; 1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if delay forces a read position wrap 1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (aecm->farBufReadPos < 0) 1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufReadPos += FAR_BUF_LEN; 1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (aecm->farBufReadPos > FAR_BUF_LEN - 1) 1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufReadPos -= FAR_BUF_LEN; 1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->lastKnownDelay = knownDelay; 1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check if read position must be wrapped 1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (aecm->farBufReadPos + readLen > FAR_BUF_LEN) 1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Read from remaining buffer space before wrapping 1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org readLen = FAR_BUF_LEN - aecm->farBufReadPos; 1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos, 12903f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * readLen); 1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufReadPos = 0; 1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org readPos = readLen; 1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org readLen = farLen - readLen; 1294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos, 12963f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org sizeof(int16_t) * readLen); 1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org aecm->farBufReadPos += readLen; 1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 1299