1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/audio_processing/ns/include/noise_suppression_x.h" 12 13 #include <assert.h> 14 #include <math.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include "webrtc/common_audio/signal_processing/include/real_fft.h" 19 #include "webrtc/modules/audio_processing/ns/nsx_core.h" 20 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" 21 22 #if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON) 23 /* Tables are defined in ARM assembly files. */ 24 extern const int16_t WebRtcNsx_kLogTable[9]; 25 extern const int16_t WebRtcNsx_kCounterDiv[201]; 26 extern const int16_t WebRtcNsx_kLogTableFrac[256]; 27 #else 28 static const int16_t WebRtcNsx_kLogTable[9] = { 29 0, 177, 355, 532, 710, 887, 1065, 1242, 1420 30 }; 31 32 static const int16_t WebRtcNsx_kCounterDiv[201] = { 33 32767, 16384, 10923, 8192, 6554, 5461, 4681, 4096, 3641, 3277, 2979, 2731, 34 2521, 2341, 2185, 2048, 1928, 1820, 1725, 1638, 1560, 1489, 1425, 1365, 1311, 35 1260, 1214, 1170, 1130, 1092, 1057, 1024, 993, 964, 936, 910, 886, 862, 840, 36 819, 799, 780, 762, 745, 728, 712, 697, 683, 669, 655, 643, 630, 618, 607, 37 596, 585, 575, 565, 555, 546, 537, 529, 520, 512, 504, 496, 489, 482, 475, 38 468, 462, 455, 449, 443, 437, 431, 426, 420, 415, 410, 405, 400, 395, 390, 39 386, 381, 377, 372, 368, 364, 360, 356, 352, 349, 345, 341, 338, 334, 331, 40 328, 324, 321, 318, 315, 312, 309, 306, 303, 301, 298, 295, 293, 290, 287, 41 285, 282, 280, 278, 275, 273, 271, 269, 266, 264, 262, 260, 258, 256, 254, 42 252, 250, 248, 246, 245, 243, 241, 239, 237, 236, 234, 232, 231, 229, 228, 43 226, 224, 223, 221, 220, 218, 217, 216, 214, 213, 211, 210, 209, 207, 206, 44 205, 204, 202, 201, 200, 199, 197, 196, 195, 194, 193, 192, 191, 189, 188, 45 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 46 172, 172, 171, 170, 169, 168, 167, 166, 165, 165, 164, 163 47 }; 48 49 static const int16_t WebRtcNsx_kLogTableFrac[256] = { 50 0, 1, 3, 4, 6, 7, 9, 10, 11, 13, 14, 16, 17, 18, 20, 21, 51 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 52 44, 45, 46, 47, 49, 50, 51, 52, 54, 55, 56, 57, 59, 60, 61, 62, 53 63, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 54 82, 84, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 97, 98, 99, 55 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 116, 56 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 57 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 58 147, 148, 149, 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 160, 59 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 174, 60 175, 176, 177, 178, 178, 179, 180, 181, 182, 183, 184, 185, 185, 186, 187, 61 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, 197, 198, 198, 199, 200, 62 201, 202, 203, 203, 204, 205, 206, 207, 208, 208, 209, 210, 211, 212, 212, 63 213, 214, 215, 216, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224, 64 225, 226, 227, 228, 228, 229, 230, 231, 231, 232, 233, 234, 234, 235, 236, 65 237, 238, 238, 239, 240, 241, 241, 242, 243, 244, 244, 245, 246, 247, 247, 66 248, 249, 249, 250, 251, 252, 252, 253, 254, 255, 255 67 }; 68 #endif // WEBRTC_DETECT_ARM_NEON || WEBRTC_ARCH_ARM_NEON 69 70 // Skip first frequency bins during estimation. (0 <= value < 64) 71 static const int kStartBand = 5; 72 73 // hybrib Hanning & flat window 74 static const int16_t kBlocks80w128x[128] = { 75 0, 536, 1072, 1606, 2139, 2669, 3196, 3720, 4240, 4756, 5266, 76 5771, 6270, 6762, 7246, 7723, 8192, 8652, 9102, 9543, 9974, 10394, 77 10803, 11200, 11585, 11958, 12318, 12665, 12998, 13318, 13623, 13913, 14189, 78 14449, 14694, 14924, 15137, 15334, 15515, 15679, 15826, 15956, 16069, 16165, 79 16244, 16305, 16349, 16375, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 80 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 81 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 82 16384, 16384, 16384, 16384, 16375, 16349, 16305, 16244, 16165, 16069, 15956, 83 15826, 15679, 15515, 15334, 15137, 14924, 14694, 14449, 14189, 13913, 13623, 84 13318, 12998, 12665, 12318, 11958, 11585, 11200, 10803, 10394, 9974, 9543, 85 9102, 8652, 8192, 7723, 7246, 6762, 6270, 5771, 5266, 4756, 4240, 86 3720, 3196, 2669, 2139, 1606, 1072, 536 87 }; 88 89 // hybrib Hanning & flat window 90 static const int16_t kBlocks160w256x[256] = { 91 0, 268, 536, 804, 1072, 1339, 1606, 1872, 92 2139, 2404, 2669, 2933, 3196, 3459, 3720, 3981, 93 4240, 4499, 4756, 5012, 5266, 5520, 5771, 6021, 94 6270, 6517, 6762, 7005, 7246, 7486, 7723, 7959, 95 8192, 8423, 8652, 8878, 9102, 9324, 9543, 9760, 96 9974, 10185, 10394, 10600, 10803, 11003, 11200, 11394, 97 11585, 11773, 11958, 12140, 12318, 12493, 12665, 12833, 98 12998, 13160, 13318, 13472, 13623, 13770, 13913, 14053, 99 14189, 14321, 14449, 14574, 14694, 14811, 14924, 15032, 100 15137, 15237, 15334, 15426, 15515, 15599, 15679, 15754, 101 15826, 15893, 15956, 16015, 16069, 16119, 16165, 16207, 102 16244, 16277, 16305, 16329, 16349, 16364, 16375, 16382, 103 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 104 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 105 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 106 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 107 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 108 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 109 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 110 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 111 16384, 16382, 16375, 16364, 16349, 16329, 16305, 16277, 112 16244, 16207, 16165, 16119, 16069, 16015, 15956, 15893, 113 15826, 15754, 15679, 15599, 15515, 15426, 15334, 15237, 114 15137, 15032, 14924, 14811, 14694, 14574, 14449, 14321, 115 14189, 14053, 13913, 13770, 13623, 13472, 13318, 13160, 116 12998, 12833, 12665, 12493, 12318, 12140, 11958, 11773, 117 11585, 11394, 11200, 11003, 10803, 10600, 10394, 10185, 118 9974, 9760, 9543, 9324, 9102, 8878, 8652, 8423, 119 8192, 7959, 7723, 7486, 7246, 7005, 6762, 6517, 120 6270, 6021, 5771, 5520, 5266, 5012, 4756, 4499, 121 4240, 3981, 3720, 3459, 3196, 2933, 2669, 2404, 122 2139, 1872, 1606, 1339, 1072, 804, 536, 268 123 }; 124 125 // Gain factor1 table: Input value in Q8 and output value in Q13 126 // original floating point code 127 // if (gain > blim) { 128 // factor1 = 1.0 + 1.3 * (gain - blim); 129 // if (gain * factor1 > 1.0) { 130 // factor1 = 1.0 / gain; 131 // } 132 // } else { 133 // factor1 = 1.0; 134 // } 135 static const int16_t kFactor1Table[257] = { 136 8192, 8192, 8192, 8192, 8192, 8192, 8192, 137 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 138 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 139 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 140 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 141 8192, 8192, 8233, 8274, 8315, 8355, 8396, 8436, 8475, 8515, 8554, 8592, 8631, 8669, 142 8707, 8745, 8783, 8820, 8857, 8894, 8931, 8967, 9003, 9039, 9075, 9111, 9146, 9181, 143 9216, 9251, 9286, 9320, 9354, 9388, 9422, 9456, 9489, 9523, 9556, 9589, 9622, 9655, 144 9687, 9719, 9752, 9784, 9816, 9848, 9879, 9911, 9942, 9973, 10004, 10035, 10066, 145 10097, 10128, 10158, 10188, 10218, 10249, 10279, 10308, 10338, 10368, 10397, 10426, 146 10456, 10485, 10514, 10543, 10572, 10600, 10629, 10657, 10686, 10714, 10742, 10770, 147 10798, 10826, 10854, 10882, 10847, 10810, 10774, 10737, 10701, 10666, 10631, 10596, 148 10562, 10527, 10494, 10460, 10427, 10394, 10362, 10329, 10297, 10266, 10235, 10203, 149 10173, 10142, 10112, 10082, 10052, 10023, 9994, 9965, 9936, 9908, 9879, 9851, 9824, 150 9796, 9769, 9742, 9715, 9689, 9662, 9636, 9610, 9584, 9559, 9534, 9508, 9484, 9459, 151 9434, 9410, 9386, 9362, 9338, 9314, 9291, 9268, 9245, 9222, 9199, 9176, 9154, 9132, 152 9110, 9088, 9066, 9044, 9023, 9002, 8980, 8959, 8939, 8918, 8897, 8877, 8857, 8836, 153 8816, 8796, 8777, 8757, 8738, 8718, 8699, 8680, 8661, 8642, 8623, 8605, 8586, 8568, 154 8550, 8532, 8514, 8496, 8478, 8460, 8443, 8425, 8408, 8391, 8373, 8356, 8339, 8323, 155 8306, 8289, 8273, 8256, 8240, 8224, 8208, 8192 156 }; 157 158 // For Factor2 tables 159 // original floating point code 160 // if (gain > blim) { 161 // factor2 = 1.0; 162 // } else { 163 // factor2 = 1.0 - 0.3 * (blim - gain); 164 // if (gain <= inst->denoiseBound) { 165 // factor2 = 1.0 - 0.3 * (blim - inst->denoiseBound); 166 // } 167 // } 168 // 169 // Gain factor table: Input value in Q8 and output value in Q13 170 static const int16_t kFactor2Aggressiveness1[257] = { 171 7577, 7577, 7577, 7577, 7577, 7577, 172 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7577, 7596, 7614, 7632, 173 7650, 7667, 7683, 7699, 7715, 7731, 7746, 7761, 7775, 7790, 7804, 7818, 7832, 7845, 174 7858, 7871, 7884, 7897, 7910, 7922, 7934, 7946, 7958, 7970, 7982, 7993, 8004, 8016, 175 8027, 8038, 8049, 8060, 8070, 8081, 8091, 8102, 8112, 8122, 8132, 8143, 8152, 8162, 176 8172, 8182, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 177 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 178 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 179 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 180 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 181 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 182 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 183 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 184 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 185 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 186 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 187 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 188 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 189 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192 190 }; 191 192 // Gain factor table: Input value in Q8 and output value in Q13 193 static const int16_t kFactor2Aggressiveness2[257] = { 194 7270, 7270, 7270, 7270, 7270, 7306, 195 7339, 7369, 7397, 7424, 7448, 7472, 7495, 7517, 7537, 7558, 7577, 7596, 7614, 7632, 196 7650, 7667, 7683, 7699, 7715, 7731, 7746, 7761, 7775, 7790, 7804, 7818, 7832, 7845, 197 7858, 7871, 7884, 7897, 7910, 7922, 7934, 7946, 7958, 7970, 7982, 7993, 8004, 8016, 198 8027, 8038, 8049, 8060, 8070, 8081, 8091, 8102, 8112, 8122, 8132, 8143, 8152, 8162, 199 8172, 8182, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 200 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 201 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 202 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 203 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 204 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 205 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 206 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 207 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 208 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 209 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 210 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 211 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 212 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192 213 }; 214 215 // Gain factor table: Input value in Q8 and output value in Q13 216 static const int16_t kFactor2Aggressiveness3[257] = { 217 7184, 7184, 7184, 7229, 7270, 7306, 218 7339, 7369, 7397, 7424, 7448, 7472, 7495, 7517, 7537, 7558, 7577, 7596, 7614, 7632, 219 7650, 7667, 7683, 7699, 7715, 7731, 7746, 7761, 7775, 7790, 7804, 7818, 7832, 7845, 220 7858, 7871, 7884, 7897, 7910, 7922, 7934, 7946, 7958, 7970, 7982, 7993, 8004, 8016, 221 8027, 8038, 8049, 8060, 8070, 8081, 8091, 8102, 8112, 8122, 8132, 8143, 8152, 8162, 222 8172, 8182, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 223 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 224 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 225 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 226 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 227 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 228 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 229 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 230 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 231 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 232 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 233 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 234 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 235 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192 236 }; 237 238 // sum of log2(i) from table index to inst->anaLen2 in Q5 239 // Note that the first table value is invalid, since log2(0) = -infinity 240 static const int16_t kSumLogIndex[66] = { 241 0, 22917, 22917, 22885, 22834, 22770, 22696, 22613, 242 22524, 22428, 22326, 22220, 22109, 21994, 21876, 21754, 243 21629, 21501, 21370, 21237, 21101, 20963, 20822, 20679, 244 20535, 20388, 20239, 20089, 19937, 19783, 19628, 19470, 245 19312, 19152, 18991, 18828, 18664, 18498, 18331, 18164, 246 17994, 17824, 17653, 17480, 17306, 17132, 16956, 16779, 247 16602, 16423, 16243, 16063, 15881, 15699, 15515, 15331, 248 15146, 14960, 14774, 14586, 14398, 14209, 14019, 13829, 249 13637, 13445 250 }; 251 252 // sum of log2(i)^2 from table index to inst->anaLen2 in Q2 253 // Note that the first table value is invalid, since log2(0) = -infinity 254 static const int16_t kSumSquareLogIndex[66] = { 255 0, 16959, 16959, 16955, 16945, 16929, 16908, 16881, 256 16850, 16814, 16773, 16729, 16681, 16630, 16575, 16517, 257 16456, 16392, 16325, 16256, 16184, 16109, 16032, 15952, 258 15870, 15786, 15700, 15612, 15521, 15429, 15334, 15238, 259 15140, 15040, 14938, 14834, 14729, 14622, 14514, 14404, 260 14292, 14179, 14064, 13947, 13830, 13710, 13590, 13468, 261 13344, 13220, 13094, 12966, 12837, 12707, 12576, 12444, 262 12310, 12175, 12039, 11902, 11763, 11624, 11483, 11341, 263 11198, 11054 264 }; 265 266 // log2(table index) in Q12 267 // Note that the first table value is invalid, since log2(0) = -infinity 268 static const int16_t kLogIndex[129] = { 269 0, 0, 4096, 6492, 8192, 9511, 10588, 11499, 270 12288, 12984, 13607, 14170, 14684, 15157, 15595, 16003, 271 16384, 16742, 17080, 17400, 17703, 17991, 18266, 18529, 272 18780, 19021, 19253, 19476, 19691, 19898, 20099, 20292, 273 20480, 20662, 20838, 21010, 21176, 21338, 21496, 21649, 274 21799, 21945, 22087, 22226, 22362, 22495, 22625, 22752, 275 22876, 22998, 23117, 23234, 23349, 23462, 23572, 23680, 276 23787, 23892, 23994, 24095, 24195, 24292, 24388, 24483, 277 24576, 24668, 24758, 24847, 24934, 25021, 25106, 25189, 278 25272, 25354, 25434, 25513, 25592, 25669, 25745, 25820, 279 25895, 25968, 26041, 26112, 26183, 26253, 26322, 26390, 280 26458, 26525, 26591, 26656, 26721, 26784, 26848, 26910, 281 26972, 27033, 27094, 27154, 27213, 27272, 27330, 27388, 282 27445, 27502, 27558, 27613, 27668, 27722, 27776, 27830, 283 27883, 27935, 27988, 28039, 28090, 28141, 28191, 28241, 284 28291, 28340, 28388, 28437, 28484, 28532, 28579, 28626, 285 28672 286 }; 287 288 // determinant of estimation matrix in Q0 corresponding to the log2 tables above 289 // Note that the first table value is invalid, since log2(0) = -infinity 290 static const int16_t kDeterminantEstMatrix[66] = { 291 0, 29814, 25574, 22640, 20351, 18469, 16873, 15491, 292 14277, 13199, 12233, 11362, 10571, 9851, 9192, 8587, 293 8030, 7515, 7038, 6596, 6186, 5804, 5448, 5115, 294 4805, 4514, 4242, 3988, 3749, 3524, 3314, 3116, 295 2930, 2755, 2590, 2435, 2289, 2152, 2022, 1900, 296 1785, 1677, 1575, 1478, 1388, 1302, 1221, 1145, 297 1073, 1005, 942, 881, 825, 771, 721, 674, 298 629, 587, 547, 510, 475, 442, 411, 382, 299 355, 330 300 }; 301 302 // Update the noise estimation information. 303 static void UpdateNoiseEstimate(NsxInst_t* inst, int offset) { 304 int32_t tmp32no1 = 0; 305 int32_t tmp32no2 = 0; 306 int16_t tmp16 = 0; 307 const int16_t kExp2Const = 11819; // Q13 308 309 int i = 0; 310 311 tmp16 = WebRtcSpl_MaxValueW16(inst->noiseEstLogQuantile + offset, 312 inst->magnLen); 313 // Guarantee a Q-domain as high as possible and still fit in int16 314 inst->qNoise = 14 - (int) WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 315 kExp2Const, tmp16, 21); 316 for (i = 0; i < inst->magnLen; i++) { 317 // inst->quantile[i]=exp(inst->lquantile[offset+i]); 318 // in Q21 319 tmp32no2 = WEBRTC_SPL_MUL_16_16(kExp2Const, 320 inst->noiseEstLogQuantile[offset + i]); 321 tmp32no1 = (0x00200000 | (tmp32no2 & 0x001FFFFF)); // 2^21 + frac 322 tmp16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32no2, 21); 323 tmp16 -= 21;// shift 21 to get result in Q0 324 tmp16 += (int16_t) inst->qNoise; //shift to get result in Q(qNoise) 325 if (tmp16 < 0) { 326 tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no1, -tmp16); 327 } else { 328 tmp32no1 = WEBRTC_SPL_LSHIFT_W32(tmp32no1, tmp16); 329 } 330 inst->noiseEstQuantile[i] = WebRtcSpl_SatW32ToW16(tmp32no1); 331 } 332 } 333 334 // Noise Estimation 335 static void NoiseEstimationC(NsxInst_t* inst, 336 uint16_t* magn, 337 uint32_t* noise, 338 int16_t* q_noise) { 339 int16_t lmagn[HALF_ANAL_BLOCKL], counter, countDiv; 340 int16_t countProd, delta, zeros, frac; 341 int16_t log2, tabind, logval, tmp16, tmp16no1, tmp16no2; 342 const int16_t log2_const = 22713; // Q15 343 const int16_t width_factor = 21845; 344 345 int i, s, offset; 346 347 tabind = inst->stages - inst->normData; 348 assert(tabind < 9); 349 assert(tabind > -9); 350 if (tabind < 0) { 351 logval = -WebRtcNsx_kLogTable[-tabind]; 352 } else { 353 logval = WebRtcNsx_kLogTable[tabind]; 354 } 355 356 // lmagn(i)=log(magn(i))=log(2)*log2(magn(i)) 357 // magn is in Q(-stages), and the real lmagn values are: 358 // real_lmagn(i)=log(magn(i)*2^stages)=log(magn(i))+log(2^stages) 359 // lmagn in Q8 360 for (i = 0; i < inst->magnLen; i++) { 361 if (magn[i]) { 362 zeros = WebRtcSpl_NormU32((uint32_t)magn[i]); 363 frac = (int16_t)((((uint32_t)magn[i] << zeros) 364 & 0x7FFFFFFF) >> 23); 365 // log2(magn(i)) 366 assert(frac < 256); 367 log2 = (int16_t)(((31 - zeros) << 8) 368 + WebRtcNsx_kLogTableFrac[frac]); 369 // log2(magn(i))*log(2) 370 lmagn[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(log2, log2_const, 15); 371 // + log(2^stages) 372 lmagn[i] += logval; 373 } else { 374 lmagn[i] = logval;//0; 375 } 376 } 377 378 // loop over simultaneous estimates 379 for (s = 0; s < SIMULT; s++) { 380 offset = s * inst->magnLen; 381 382 // Get counter values from state 383 counter = inst->noiseEstCounter[s]; 384 assert(counter < 201); 385 countDiv = WebRtcNsx_kCounterDiv[counter]; 386 countProd = (int16_t)WEBRTC_SPL_MUL_16_16(counter, countDiv); 387 388 // quant_est(...) 389 for (i = 0; i < inst->magnLen; i++) { 390 // compute delta 391 if (inst->noiseEstDensity[offset + i] > 512) { 392 // Get the value for delta by shifting intead of dividing. 393 int factor = WebRtcSpl_NormW16(inst->noiseEstDensity[offset + i]); 394 delta = (int16_t)(FACTOR_Q16 >> (14 - factor)); 395 } else { 396 delta = FACTOR_Q7; 397 if (inst->blockIndex < END_STARTUP_LONG) { 398 // Smaller step size during startup. This prevents from using 399 // unrealistic values causing overflow. 400 delta = FACTOR_Q7_STARTUP; 401 } 402 } 403 404 // update log quantile estimate 405 tmp16 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(delta, countDiv, 14); 406 if (lmagn[i] > inst->noiseEstLogQuantile[offset + i]) { 407 // +=QUANTILE*delta/(inst->counter[s]+1) QUANTILE=0.25, =1 in Q2 408 // CounterDiv=1/(inst->counter[s]+1) in Q15 409 tmp16 += 2; 410 tmp16no1 = WEBRTC_SPL_RSHIFT_W16(tmp16, 2); 411 inst->noiseEstLogQuantile[offset + i] += tmp16no1; 412 } else { 413 tmp16 += 1; 414 tmp16no1 = WEBRTC_SPL_RSHIFT_W16(tmp16, 1); 415 // *(1-QUANTILE), in Q2 QUANTILE=0.25, 1-0.25=0.75=3 in Q2 416 tmp16no2 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, 3, 1); 417 inst->noiseEstLogQuantile[offset + i] -= tmp16no2; 418 if (inst->noiseEstLogQuantile[offset + i] < logval) { 419 // This is the smallest fixed point representation we can 420 // have, hence we limit the output. 421 inst->noiseEstLogQuantile[offset + i] = logval; 422 } 423 } 424 425 // update density estimate 426 if (WEBRTC_SPL_ABS_W16(lmagn[i] - inst->noiseEstLogQuantile[offset + i]) 427 < WIDTH_Q8) { 428 tmp16no1 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 429 inst->noiseEstDensity[offset + i], countProd, 15); 430 tmp16no2 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 431 width_factor, countDiv, 15); 432 inst->noiseEstDensity[offset + i] = tmp16no1 + tmp16no2; 433 } 434 } // end loop over magnitude spectrum 435 436 if (counter >= END_STARTUP_LONG) { 437 inst->noiseEstCounter[s] = 0; 438 if (inst->blockIndex >= END_STARTUP_LONG) { 439 UpdateNoiseEstimate(inst, offset); 440 } 441 } 442 inst->noiseEstCounter[s]++; 443 444 } // end loop over simultaneous estimates 445 446 // Sequentially update the noise during startup 447 if (inst->blockIndex < END_STARTUP_LONG) { 448 UpdateNoiseEstimate(inst, offset); 449 } 450 451 for (i = 0; i < inst->magnLen; i++) { 452 noise[i] = (uint32_t)(inst->noiseEstQuantile[i]); // Q(qNoise) 453 } 454 (*q_noise) = (int16_t)inst->qNoise; 455 } 456 457 // Filter the data in the frequency domain, and create spectrum. 458 static void PrepareSpectrumC(NsxInst_t* inst, int16_t* freq_buf) { 459 int i = 0, j = 0; 460 461 for (i = 0; i < inst->magnLen; i++) { 462 inst->real[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(inst->real[i], 463 (int16_t)(inst->noiseSupFilter[i]), 14); // Q(normData-stages) 464 inst->imag[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(inst->imag[i], 465 (int16_t)(inst->noiseSupFilter[i]), 14); // Q(normData-stages) 466 } 467 468 freq_buf[0] = inst->real[0]; 469 freq_buf[1] = -inst->imag[0]; 470 for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { 471 freq_buf[j] = inst->real[i]; 472 freq_buf[j + 1] = -inst->imag[i]; 473 } 474 freq_buf[inst->anaLen] = inst->real[inst->anaLen2]; 475 freq_buf[inst->anaLen + 1] = -inst->imag[inst->anaLen2]; 476 } 477 478 // Denormalize the real-valued signal |in|, the output from inverse FFT. 479 static void DenormalizeC(NsxInst_t* inst, int16_t* in, int factor) { 480 int i = 0; 481 int32_t tmp32 = 0; 482 for (i = 0; i < inst->anaLen; i += 1) { 483 tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t)in[i], 484 factor - inst->normData); 485 inst->real[i] = WebRtcSpl_SatW32ToW16(tmp32); // Q0 486 } 487 } 488 489 // For the noise supression process, synthesis, read out fully processed 490 // segment, and update synthesis buffer. 491 static void SynthesisUpdateC(NsxInst_t* inst, 492 int16_t* out_frame, 493 int16_t gain_factor) { 494 int i = 0; 495 int16_t tmp16a = 0; 496 int16_t tmp16b = 0; 497 int32_t tmp32 = 0; 498 499 // synthesis 500 for (i = 0; i < inst->anaLen; i++) { 501 tmp16a = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 502 inst->window[i], inst->real[i], 14); // Q0, window in Q14 503 tmp32 = WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(tmp16a, gain_factor, 13); // Q0 504 // Down shift with rounding 505 tmp16b = WebRtcSpl_SatW32ToW16(tmp32); // Q0 506 inst->synthesisBuffer[i] = WebRtcSpl_AddSatW16(inst->synthesisBuffer[i], 507 tmp16b); // Q0 508 } 509 510 // read out fully processed segment 511 for (i = 0; i < inst->blockLen10ms; i++) { 512 out_frame[i] = inst->synthesisBuffer[i]; // Q0 513 } 514 515 // update synthesis buffer 516 WEBRTC_SPL_MEMCPY_W16(inst->synthesisBuffer, 517 inst->synthesisBuffer + inst->blockLen10ms, 518 inst->anaLen - inst->blockLen10ms); 519 WebRtcSpl_ZerosArrayW16(inst->synthesisBuffer 520 + inst->anaLen - inst->blockLen10ms, inst->blockLen10ms); 521 } 522 523 // Update analysis buffer for lower band, and window data before FFT. 524 static void AnalysisUpdateC(NsxInst_t* inst, 525 int16_t* out, 526 int16_t* new_speech) { 527 int i = 0; 528 529 // For lower band update analysis buffer. 530 WEBRTC_SPL_MEMCPY_W16(inst->analysisBuffer, 531 inst->analysisBuffer + inst->blockLen10ms, 532 inst->anaLen - inst->blockLen10ms); 533 WEBRTC_SPL_MEMCPY_W16(inst->analysisBuffer 534 + inst->anaLen - inst->blockLen10ms, new_speech, inst->blockLen10ms); 535 536 // Window data before FFT. 537 for (i = 0; i < inst->anaLen; i++) { 538 out[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 539 inst->window[i], inst->analysisBuffer[i], 14); // Q0 540 } 541 } 542 543 // Normalize the real-valued signal |in|, the input to forward FFT. 544 static void NormalizeRealBufferC(NsxInst_t* inst, 545 const int16_t* in, 546 int16_t* out) { 547 int i = 0; 548 for (i = 0; i < inst->anaLen; ++i) { 549 out[i] = WEBRTC_SPL_LSHIFT_W16(in[i], inst->normData); // Q(normData) 550 } 551 } 552 553 // Declare function pointers. 554 NoiseEstimation WebRtcNsx_NoiseEstimation; 555 PrepareSpectrum WebRtcNsx_PrepareSpectrum; 556 SynthesisUpdate WebRtcNsx_SynthesisUpdate; 557 AnalysisUpdate WebRtcNsx_AnalysisUpdate; 558 Denormalize WebRtcNsx_Denormalize; 559 NormalizeRealBuffer WebRtcNsx_NormalizeRealBuffer; 560 561 #if (defined WEBRTC_DETECT_ARM_NEON || defined WEBRTC_ARCH_ARM_NEON) 562 // Initialize function pointers for ARM Neon platform. 563 static void WebRtcNsx_InitNeon(void) { 564 WebRtcNsx_NoiseEstimation = WebRtcNsx_NoiseEstimationNeon; 565 WebRtcNsx_PrepareSpectrum = WebRtcNsx_PrepareSpectrumNeon; 566 WebRtcNsx_SynthesisUpdate = WebRtcNsx_SynthesisUpdateNeon; 567 WebRtcNsx_AnalysisUpdate = WebRtcNsx_AnalysisUpdateNeon; 568 } 569 #endif 570 571 #if defined(MIPS32_LE) 572 // Initialize function pointers for MIPS platform. 573 static void WebRtcNsx_InitMips(void) { 574 WebRtcNsx_PrepareSpectrum = WebRtcNsx_PrepareSpectrum_mips; 575 WebRtcNsx_SynthesisUpdate = WebRtcNsx_SynthesisUpdate_mips; 576 WebRtcNsx_AnalysisUpdate = WebRtcNsx_AnalysisUpdate_mips; 577 WebRtcNsx_NormalizeRealBuffer = WebRtcNsx_NormalizeRealBuffer_mips; 578 #if defined(MIPS_DSP_R1_LE) 579 WebRtcNsx_Denormalize = WebRtcNsx_Denormalize_mips; 580 #endif 581 } 582 #endif 583 584 void WebRtcNsx_CalcParametricNoiseEstimate(NsxInst_t* inst, 585 int16_t pink_noise_exp_avg, 586 int32_t pink_noise_num_avg, 587 int freq_index, 588 uint32_t* noise_estimate, 589 uint32_t* noise_estimate_avg) { 590 int32_t tmp32no1 = 0; 591 int32_t tmp32no2 = 0; 592 593 int16_t int_part = 0; 594 int16_t frac_part = 0; 595 596 // Use pink noise estimate 597 // noise_estimate = 2^(pinkNoiseNumerator + pinkNoiseExp * log2(j)) 598 assert(freq_index >= 0); 599 assert(freq_index < 129); 600 tmp32no2 = WEBRTC_SPL_MUL_16_16(pink_noise_exp_avg, kLogIndex[freq_index]); // Q26 601 tmp32no2 = WEBRTC_SPL_RSHIFT_W32(tmp32no2, 15); // Q11 602 tmp32no1 = pink_noise_num_avg - tmp32no2; // Q11 603 604 // Calculate output: 2^tmp32no1 605 // Output in Q(minNorm-stages) 606 tmp32no1 += WEBRTC_SPL_LSHIFT_W32((int32_t)(inst->minNorm - inst->stages), 11); 607 if (tmp32no1 > 0) { 608 int_part = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 11); 609 frac_part = (int16_t)(tmp32no1 & 0x000007ff); // Q11 610 // Piecewise linear approximation of 'b' in 611 // 2^(int_part+frac_part) = 2^int_part * (1 + b) 612 // 'b' is given in Q11 and below stored in frac_part. 613 if (WEBRTC_SPL_RSHIFT_W16(frac_part, 10)) { 614 // Upper fractional part 615 tmp32no2 = WEBRTC_SPL_MUL_16_16(2048 - frac_part, 1244); // Q21 616 tmp32no2 = 2048 - WEBRTC_SPL_RSHIFT_W32(tmp32no2, 10); 617 } else { 618 // Lower fractional part 619 tmp32no2 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(frac_part, 804), 10); 620 } 621 // Shift fractional part to Q(minNorm-stages) 622 tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, int_part - 11); 623 *noise_estimate_avg = (1 << int_part) + (uint32_t)tmp32no2; 624 // Scale up to initMagnEst, which is not block averaged 625 *noise_estimate = (*noise_estimate_avg) * (uint32_t)(inst->blockIndex + 1); 626 } 627 } 628 629 // Initialize state 630 int32_t WebRtcNsx_InitCore(NsxInst_t* inst, uint32_t fs) { 631 int i; 632 633 //check for valid pointer 634 if (inst == NULL) { 635 return -1; 636 } 637 // 638 639 // Initialization of struct 640 if (fs == 8000 || fs == 16000 || fs == 32000) { 641 inst->fs = fs; 642 } else { 643 return -1; 644 } 645 646 if (fs == 8000) { 647 inst->blockLen10ms = 80; 648 inst->anaLen = 128; 649 inst->stages = 7; 650 inst->window = kBlocks80w128x; 651 inst->thresholdLogLrt = 131072; //default threshold for LRT feature 652 inst->maxLrt = 0x0040000; 653 inst->minLrt = 52429; 654 } else if (fs == 16000) { 655 inst->blockLen10ms = 160; 656 inst->anaLen = 256; 657 inst->stages = 8; 658 inst->window = kBlocks160w256x; 659 inst->thresholdLogLrt = 212644; //default threshold for LRT feature 660 inst->maxLrt = 0x0080000; 661 inst->minLrt = 104858; 662 } else if (fs == 32000) { 663 inst->blockLen10ms = 160; 664 inst->anaLen = 256; 665 inst->stages = 8; 666 inst->window = kBlocks160w256x; 667 inst->thresholdLogLrt = 212644; //default threshold for LRT feature 668 inst->maxLrt = 0x0080000; 669 inst->minLrt = 104858; 670 } 671 inst->anaLen2 = WEBRTC_SPL_RSHIFT_W16(inst->anaLen, 1); 672 inst->magnLen = inst->anaLen2 + 1; 673 674 if (inst->real_fft != NULL) { 675 WebRtcSpl_FreeRealFFT(inst->real_fft); 676 } 677 inst->real_fft = WebRtcSpl_CreateRealFFT(inst->stages); 678 if (inst->real_fft == NULL) { 679 return -1; 680 } 681 682 WebRtcSpl_ZerosArrayW16(inst->analysisBuffer, ANAL_BLOCKL_MAX); 683 WebRtcSpl_ZerosArrayW16(inst->synthesisBuffer, ANAL_BLOCKL_MAX); 684 685 // for HB processing 686 WebRtcSpl_ZerosArrayW16(inst->dataBufHBFX, ANAL_BLOCKL_MAX); 687 // for quantile noise estimation 688 WebRtcSpl_ZerosArrayW16(inst->noiseEstQuantile, HALF_ANAL_BLOCKL); 689 for (i = 0; i < SIMULT * HALF_ANAL_BLOCKL; i++) { 690 inst->noiseEstLogQuantile[i] = 2048; // Q8 691 inst->noiseEstDensity[i] = 153; // Q9 692 } 693 for (i = 0; i < SIMULT; i++) { 694 inst->noiseEstCounter[i] = (int16_t)(END_STARTUP_LONG * (i + 1)) / SIMULT; 695 } 696 697 // Initialize suppression filter with ones 698 WebRtcSpl_MemSetW16((int16_t*)inst->noiseSupFilter, 16384, HALF_ANAL_BLOCKL); 699 700 // Set the aggressiveness: default 701 inst->aggrMode = 0; 702 703 //initialize variables for new method 704 inst->priorNonSpeechProb = 8192; // Q14(0.5) prior probability for speech/noise 705 for (i = 0; i < HALF_ANAL_BLOCKL; i++) { 706 inst->prevMagnU16[i] = 0; 707 inst->prevNoiseU32[i] = 0; //previous noise-spectrum 708 inst->logLrtTimeAvgW32[i] = 0; //smooth LR ratio 709 inst->avgMagnPause[i] = 0; //conservative noise spectrum estimate 710 inst->initMagnEst[i] = 0; //initial average magnitude spectrum 711 } 712 713 //feature quantities 714 inst->thresholdSpecDiff = 50; //threshold for difference feature: determined on-line 715 inst->thresholdSpecFlat = 20480; //threshold for flatness: determined on-line 716 inst->featureLogLrt = inst->thresholdLogLrt; //average LRT factor (= threshold) 717 inst->featureSpecFlat = inst->thresholdSpecFlat; //spectral flatness (= threshold) 718 inst->featureSpecDiff = inst->thresholdSpecDiff; //spectral difference (= threshold) 719 inst->weightLogLrt = 6; //default weighting par for LRT feature 720 inst->weightSpecFlat = 0; //default weighting par for spectral flatness feature 721 inst->weightSpecDiff = 0; //default weighting par for spectral difference feature 722 723 inst->curAvgMagnEnergy = 0; //window time-average of input magnitude spectrum 724 inst->timeAvgMagnEnergy = 0; //normalization for spectral difference 725 inst->timeAvgMagnEnergyTmp = 0; //normalization for spectral difference 726 727 //histogram quantities: used to estimate/update thresholds for features 728 WebRtcSpl_ZerosArrayW16(inst->histLrt, HIST_PAR_EST); 729 WebRtcSpl_ZerosArrayW16(inst->histSpecDiff, HIST_PAR_EST); 730 WebRtcSpl_ZerosArrayW16(inst->histSpecFlat, HIST_PAR_EST); 731 732 inst->blockIndex = -1; //frame counter 733 734 //inst->modelUpdate = 500; //window for update 735 inst->modelUpdate = (1 << STAT_UPDATES); //window for update 736 inst->cntThresUpdate = 0; //counter feature thresholds updates 737 738 inst->sumMagn = 0; 739 inst->magnEnergy = 0; 740 inst->prevQMagn = 0; 741 inst->qNoise = 0; 742 inst->prevQNoise = 0; 743 744 inst->energyIn = 0; 745 inst->scaleEnergyIn = 0; 746 747 inst->whiteNoiseLevel = 0; 748 inst->pinkNoiseNumerator = 0; 749 inst->pinkNoiseExp = 0; 750 inst->minNorm = 15; // Start with full scale 751 inst->zeroInputSignal = 0; 752 753 //default mode 754 WebRtcNsx_set_policy_core(inst, 0); 755 756 #ifdef NS_FILEDEBUG 757 inst->infile = fopen("indebug.pcm", "wb"); 758 inst->outfile = fopen("outdebug.pcm", "wb"); 759 inst->file1 = fopen("file1.pcm", "wb"); 760 inst->file2 = fopen("file2.pcm", "wb"); 761 inst->file3 = fopen("file3.pcm", "wb"); 762 inst->file4 = fopen("file4.pcm", "wb"); 763 inst->file5 = fopen("file5.pcm", "wb"); 764 #endif 765 766 // Initialize function pointers. 767 WebRtcNsx_NoiseEstimation = NoiseEstimationC; 768 WebRtcNsx_PrepareSpectrum = PrepareSpectrumC; 769 WebRtcNsx_SynthesisUpdate = SynthesisUpdateC; 770 WebRtcNsx_AnalysisUpdate = AnalysisUpdateC; 771 WebRtcNsx_Denormalize = DenormalizeC; 772 WebRtcNsx_NormalizeRealBuffer = NormalizeRealBufferC; 773 774 #ifdef WEBRTC_DETECT_ARM_NEON 775 uint64_t features = WebRtc_GetCPUFeaturesARM(); 776 if ((features & kCPUFeatureNEON) != 0) { 777 WebRtcNsx_InitNeon(); 778 } 779 #elif defined(WEBRTC_ARCH_ARM_NEON) 780 WebRtcNsx_InitNeon(); 781 #endif 782 783 #if defined(MIPS32_LE) 784 WebRtcNsx_InitMips(); 785 #endif 786 787 inst->initFlag = 1; 788 789 return 0; 790 } 791 792 int WebRtcNsx_set_policy_core(NsxInst_t* inst, int mode) { 793 // allow for modes:0,1,2,3 794 if (mode < 0 || mode > 3) { 795 return -1; 796 } 797 798 inst->aggrMode = mode; 799 if (mode == 0) { 800 inst->overdrive = 256; // Q8(1.0) 801 inst->denoiseBound = 8192; // Q14(0.5) 802 inst->gainMap = 0; // No gain compensation 803 } else if (mode == 1) { 804 inst->overdrive = 256; // Q8(1.0) 805 inst->denoiseBound = 4096; // Q14(0.25) 806 inst->factor2Table = kFactor2Aggressiveness1; 807 inst->gainMap = 1; 808 } else if (mode == 2) { 809 inst->overdrive = 282; // ~= Q8(1.1) 810 inst->denoiseBound = 2048; // Q14(0.125) 811 inst->factor2Table = kFactor2Aggressiveness2; 812 inst->gainMap = 1; 813 } else if (mode == 3) { 814 inst->overdrive = 320; // Q8(1.25) 815 inst->denoiseBound = 1475; // ~= Q14(0.09) 816 inst->factor2Table = kFactor2Aggressiveness3; 817 inst->gainMap = 1; 818 } 819 return 0; 820 } 821 822 // Extract thresholds for feature parameters 823 // histograms are computed over some window_size (given by window_pars) 824 // thresholds and weights are extracted every window 825 // flag 0 means update histogram only, flag 1 means compute the thresholds/weights 826 // threshold and weights are returned in: inst->priorModelPars 827 void WebRtcNsx_FeatureParameterExtraction(NsxInst_t* inst, int flag) { 828 uint32_t tmpU32; 829 uint32_t histIndex; 830 uint32_t posPeak1SpecFlatFX, posPeak2SpecFlatFX; 831 uint32_t posPeak1SpecDiffFX, posPeak2SpecDiffFX; 832 833 int32_t tmp32; 834 int32_t fluctLrtFX, thresFluctLrtFX; 835 int32_t avgHistLrtFX, avgSquareHistLrtFX, avgHistLrtComplFX; 836 837 int16_t j; 838 int16_t numHistLrt; 839 840 int i; 841 int useFeatureSpecFlat, useFeatureSpecDiff, featureSum; 842 int maxPeak1, maxPeak2; 843 int weightPeak1SpecFlat, weightPeak2SpecFlat; 844 int weightPeak1SpecDiff, weightPeak2SpecDiff; 845 846 //update histograms 847 if (!flag) { 848 // LRT 849 // Type casting to UWord32 is safe since negative values will not be wrapped to larger 850 // values than HIST_PAR_EST 851 histIndex = (uint32_t)(inst->featureLogLrt); 852 if (histIndex < HIST_PAR_EST) { 853 inst->histLrt[histIndex]++; 854 } 855 // Spectral flatness 856 // (inst->featureSpecFlat*20)>>10 = (inst->featureSpecFlat*5)>>8 857 histIndex = WEBRTC_SPL_RSHIFT_U32(inst->featureSpecFlat * 5, 8); 858 if (histIndex < HIST_PAR_EST) { 859 inst->histSpecFlat[histIndex]++; 860 } 861 // Spectral difference 862 histIndex = HIST_PAR_EST; 863 if (inst->timeAvgMagnEnergy > 0) { 864 // Guard against division by zero 865 // If timeAvgMagnEnergy == 0 we have no normalizing statistics and 866 // therefore can't update the histogram 867 histIndex = ((inst->featureSpecDiff * 5) >> inst->stages) / 868 inst->timeAvgMagnEnergy; 869 } 870 if (histIndex < HIST_PAR_EST) { 871 inst->histSpecDiff[histIndex]++; 872 } 873 } 874 875 // extract parameters for speech/noise probability 876 if (flag) { 877 useFeatureSpecDiff = 1; 878 //for LRT feature: 879 // compute the average over inst->featureExtractionParams.rangeAvgHistLrt 880 avgHistLrtFX = 0; 881 avgSquareHistLrtFX = 0; 882 numHistLrt = 0; 883 for (i = 0; i < BIN_SIZE_LRT; i++) { 884 j = (2 * i + 1); 885 tmp32 = WEBRTC_SPL_MUL_16_16(inst->histLrt[i], j); 886 avgHistLrtFX += tmp32; 887 numHistLrt += inst->histLrt[i]; 888 avgSquareHistLrtFX += tmp32 * j; 889 } 890 avgHistLrtComplFX = avgHistLrtFX; 891 for (; i < HIST_PAR_EST; i++) { 892 j = (2 * i + 1); 893 tmp32 = WEBRTC_SPL_MUL_16_16(inst->histLrt[i], j); 894 avgHistLrtComplFX += tmp32; 895 avgSquareHistLrtFX += tmp32 * j; 896 } 897 fluctLrtFX = WEBRTC_SPL_MUL(avgSquareHistLrtFX, numHistLrt); 898 fluctLrtFX -= WEBRTC_SPL_MUL(avgHistLrtFX, avgHistLrtComplFX); 899 thresFluctLrtFX = THRES_FLUCT_LRT * numHistLrt; 900 // get threshold for LRT feature: 901 tmpU32 = (FACTOR_1_LRT_DIFF * (uint32_t)avgHistLrtFX); 902 if ((fluctLrtFX < thresFluctLrtFX) || (numHistLrt == 0) || 903 (tmpU32 > (uint32_t)(100 * numHistLrt))) { 904 //very low fluctuation, so likely noise 905 inst->thresholdLogLrt = inst->maxLrt; 906 } else { 907 tmp32 = (int32_t)((tmpU32 << (9 + inst->stages)) / numHistLrt / 908 25); 909 // check if value is within min/max range 910 inst->thresholdLogLrt = WEBRTC_SPL_SAT(inst->maxLrt, 911 tmp32, 912 inst->minLrt); 913 } 914 if (fluctLrtFX < thresFluctLrtFX) { 915 // Do not use difference feature if fluctuation of LRT feature is very low: 916 // most likely just noise state 917 useFeatureSpecDiff = 0; 918 } 919 920 // for spectral flatness and spectral difference: compute the main peaks of histogram 921 maxPeak1 = 0; 922 maxPeak2 = 0; 923 posPeak1SpecFlatFX = 0; 924 posPeak2SpecFlatFX = 0; 925 weightPeak1SpecFlat = 0; 926 weightPeak2SpecFlat = 0; 927 928 // peaks for flatness 929 for (i = 0; i < HIST_PAR_EST; i++) { 930 if (inst->histSpecFlat[i] > maxPeak1) { 931 // Found new "first" peak 932 maxPeak2 = maxPeak1; 933 weightPeak2SpecFlat = weightPeak1SpecFlat; 934 posPeak2SpecFlatFX = posPeak1SpecFlatFX; 935 936 maxPeak1 = inst->histSpecFlat[i]; 937 weightPeak1SpecFlat = inst->histSpecFlat[i]; 938 posPeak1SpecFlatFX = (uint32_t)(2 * i + 1); 939 } else if (inst->histSpecFlat[i] > maxPeak2) { 940 // Found new "second" peak 941 maxPeak2 = inst->histSpecFlat[i]; 942 weightPeak2SpecFlat = inst->histSpecFlat[i]; 943 posPeak2SpecFlatFX = (uint32_t)(2 * i + 1); 944 } 945 } 946 947 // for spectral flatness feature 948 useFeatureSpecFlat = 1; 949 // merge the two peaks if they are close 950 if ((posPeak1SpecFlatFX - posPeak2SpecFlatFX < LIM_PEAK_SPACE_FLAT_DIFF) 951 && (weightPeak2SpecFlat * LIM_PEAK_WEIGHT_FLAT_DIFF > weightPeak1SpecFlat)) { 952 weightPeak1SpecFlat += weightPeak2SpecFlat; 953 posPeak1SpecFlatFX = (posPeak1SpecFlatFX + posPeak2SpecFlatFX) >> 1; 954 } 955 //reject if weight of peaks is not large enough, or peak value too small 956 if (weightPeak1SpecFlat < THRES_WEIGHT_FLAT_DIFF || posPeak1SpecFlatFX 957 < THRES_PEAK_FLAT) { 958 useFeatureSpecFlat = 0; 959 } else { // if selected, get the threshold 960 // compute the threshold and check if value is within min/max range 961 inst->thresholdSpecFlat = WEBRTC_SPL_SAT(MAX_FLAT_Q10, FACTOR_2_FLAT_Q10 962 * posPeak1SpecFlatFX, MIN_FLAT_Q10); //Q10 963 } 964 // done with flatness feature 965 966 if (useFeatureSpecDiff) { 967 //compute two peaks for spectral difference 968 maxPeak1 = 0; 969 maxPeak2 = 0; 970 posPeak1SpecDiffFX = 0; 971 posPeak2SpecDiffFX = 0; 972 weightPeak1SpecDiff = 0; 973 weightPeak2SpecDiff = 0; 974 // peaks for spectral difference 975 for (i = 0; i < HIST_PAR_EST; i++) { 976 if (inst->histSpecDiff[i] > maxPeak1) { 977 // Found new "first" peak 978 maxPeak2 = maxPeak1; 979 weightPeak2SpecDiff = weightPeak1SpecDiff; 980 posPeak2SpecDiffFX = posPeak1SpecDiffFX; 981 982 maxPeak1 = inst->histSpecDiff[i]; 983 weightPeak1SpecDiff = inst->histSpecDiff[i]; 984 posPeak1SpecDiffFX = (uint32_t)(2 * i + 1); 985 } else if (inst->histSpecDiff[i] > maxPeak2) { 986 // Found new "second" peak 987 maxPeak2 = inst->histSpecDiff[i]; 988 weightPeak2SpecDiff = inst->histSpecDiff[i]; 989 posPeak2SpecDiffFX = (uint32_t)(2 * i + 1); 990 } 991 } 992 993 // merge the two peaks if they are close 994 if ((posPeak1SpecDiffFX - posPeak2SpecDiffFX < LIM_PEAK_SPACE_FLAT_DIFF) 995 && (weightPeak2SpecDiff * LIM_PEAK_WEIGHT_FLAT_DIFF > weightPeak1SpecDiff)) { 996 weightPeak1SpecDiff += weightPeak2SpecDiff; 997 posPeak1SpecDiffFX = (posPeak1SpecDiffFX + posPeak2SpecDiffFX) >> 1; 998 } 999 // get the threshold value and check if value is within min/max range 1000 inst->thresholdSpecDiff = WEBRTC_SPL_SAT(MAX_DIFF, FACTOR_1_LRT_DIFF 1001 * posPeak1SpecDiffFX, MIN_DIFF); //5x bigger 1002 //reject if weight of peaks is not large enough 1003 if (weightPeak1SpecDiff < THRES_WEIGHT_FLAT_DIFF) { 1004 useFeatureSpecDiff = 0; 1005 } 1006 // done with spectral difference feature 1007 } 1008 1009 // select the weights between the features 1010 // inst->priorModelPars[4] is weight for LRT: always selected 1011 featureSum = 6 / (1 + useFeatureSpecFlat + useFeatureSpecDiff); 1012 inst->weightLogLrt = featureSum; 1013 inst->weightSpecFlat = useFeatureSpecFlat * featureSum; 1014 inst->weightSpecDiff = useFeatureSpecDiff * featureSum; 1015 1016 // set histograms to zero for next update 1017 WebRtcSpl_ZerosArrayW16(inst->histLrt, HIST_PAR_EST); 1018 WebRtcSpl_ZerosArrayW16(inst->histSpecDiff, HIST_PAR_EST); 1019 WebRtcSpl_ZerosArrayW16(inst->histSpecFlat, HIST_PAR_EST); 1020 } // end of flag == 1 1021 } 1022 1023 1024 // Compute spectral flatness on input spectrum 1025 // magn is the magnitude spectrum 1026 // spectral flatness is returned in inst->featureSpecFlat 1027 void WebRtcNsx_ComputeSpectralFlatness(NsxInst_t* inst, uint16_t* magn) { 1028 uint32_t tmpU32; 1029 uint32_t avgSpectralFlatnessNum, avgSpectralFlatnessDen; 1030 1031 int32_t tmp32; 1032 int32_t currentSpectralFlatness, logCurSpectralFlatness; 1033 1034 int16_t zeros, frac, intPart; 1035 1036 int i; 1037 1038 // for flatness 1039 avgSpectralFlatnessNum = 0; 1040 avgSpectralFlatnessDen = inst->sumMagn - (uint32_t)magn[0]; // Q(normData-stages) 1041 1042 // compute log of ratio of the geometric to arithmetic mean: check for log(0) case 1043 // flatness = exp( sum(log(magn[i]))/N - log(sum(magn[i])/N) ) 1044 // = exp( sum(log(magn[i]))/N ) * N / sum(magn[i]) 1045 // = 2^( sum(log2(magn[i]))/N - (log2(sum(magn[i])) - log2(N)) ) [This is used] 1046 for (i = 1; i < inst->magnLen; i++) { 1047 // First bin is excluded from spectrum measures. Number of bins is now a power of 2 1048 if (magn[i]) { 1049 zeros = WebRtcSpl_NormU32((uint32_t)magn[i]); 1050 frac = (int16_t)(((uint32_t)((uint32_t)(magn[i]) << zeros) 1051 & 0x7FFFFFFF) >> 23); 1052 // log2(magn(i)) 1053 assert(frac < 256); 1054 tmpU32 = (uint32_t)(((31 - zeros) << 8) 1055 + WebRtcNsx_kLogTableFrac[frac]); // Q8 1056 avgSpectralFlatnessNum += tmpU32; // Q8 1057 } else { 1058 //if at least one frequency component is zero, treat separately 1059 tmpU32 = WEBRTC_SPL_UMUL_32_16(inst->featureSpecFlat, SPECT_FLAT_TAVG_Q14); // Q24 1060 inst->featureSpecFlat -= WEBRTC_SPL_RSHIFT_U32(tmpU32, 14); // Q10 1061 return; 1062 } 1063 } 1064 //ratio and inverse log: check for case of log(0) 1065 zeros = WebRtcSpl_NormU32(avgSpectralFlatnessDen); 1066 frac = (int16_t)(((avgSpectralFlatnessDen << zeros) & 0x7FFFFFFF) >> 23); 1067 // log2(avgSpectralFlatnessDen) 1068 assert(frac < 256); 1069 tmp32 = (int32_t)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); // Q8 1070 logCurSpectralFlatness = (int32_t)avgSpectralFlatnessNum; 1071 logCurSpectralFlatness += ((int32_t)(inst->stages - 1) << (inst->stages + 7)); // Q(8+stages-1) 1072 logCurSpectralFlatness -= (tmp32 << (inst->stages - 1)); 1073 logCurSpectralFlatness = WEBRTC_SPL_LSHIFT_W32(logCurSpectralFlatness, 10 - inst->stages); // Q17 1074 tmp32 = (int32_t)(0x00020000 | (WEBRTC_SPL_ABS_W32(logCurSpectralFlatness) 1075 & 0x0001FFFF)); //Q17 1076 intPart = -(int16_t)WEBRTC_SPL_RSHIFT_W32(logCurSpectralFlatness, 17); 1077 intPart += 7; // Shift 7 to get the output in Q10 (from Q17 = -17+10) 1078 if (intPart > 0) { 1079 currentSpectralFlatness = WEBRTC_SPL_RSHIFT_W32(tmp32, intPart); 1080 } else { 1081 currentSpectralFlatness = WEBRTC_SPL_LSHIFT_W32(tmp32, -intPart); 1082 } 1083 1084 //time average update of spectral flatness feature 1085 tmp32 = currentSpectralFlatness - (int32_t)inst->featureSpecFlat; // Q10 1086 tmp32 *= SPECT_FLAT_TAVG_Q14; // Q24 1087 inst->featureSpecFlat = (uint32_t)((int32_t)inst->featureSpecFlat 1088 + WEBRTC_SPL_RSHIFT_W32(tmp32, 14)); // Q10 1089 // done with flatness feature 1090 } 1091 1092 1093 // Compute the difference measure between input spectrum and a template/learned noise spectrum 1094 // magn_tmp is the input spectrum 1095 // the reference/template spectrum is inst->magn_avg_pause[i] 1096 // returns (normalized) spectral difference in inst->featureSpecDiff 1097 void WebRtcNsx_ComputeSpectralDifference(NsxInst_t* inst, uint16_t* magnIn) { 1098 // This is to be calculated: 1099 // avgDiffNormMagn = var(magnIn) - cov(magnIn, magnAvgPause)^2 / var(magnAvgPause) 1100 1101 uint32_t tmpU32no1, tmpU32no2; 1102 uint32_t varMagnUFX, varPauseUFX, avgDiffNormMagnUFX; 1103 1104 int32_t tmp32no1, tmp32no2; 1105 int32_t avgPauseFX, avgMagnFX, covMagnPauseFX; 1106 int32_t maxPause, minPause; 1107 1108 int16_t tmp16no1; 1109 1110 int i, norm32, nShifts; 1111 1112 avgPauseFX = 0; 1113 maxPause = 0; 1114 minPause = inst->avgMagnPause[0]; // Q(prevQMagn) 1115 // compute average quantities 1116 for (i = 0; i < inst->magnLen; i++) { 1117 // Compute mean of magn_pause 1118 avgPauseFX += inst->avgMagnPause[i]; // in Q(prevQMagn) 1119 maxPause = WEBRTC_SPL_MAX(maxPause, inst->avgMagnPause[i]); 1120 minPause = WEBRTC_SPL_MIN(minPause, inst->avgMagnPause[i]); 1121 } 1122 // normalize by replacing div of "inst->magnLen" with "inst->stages-1" shifts 1123 avgPauseFX = WEBRTC_SPL_RSHIFT_W32(avgPauseFX, inst->stages - 1); 1124 avgMagnFX = (int32_t)WEBRTC_SPL_RSHIFT_U32(inst->sumMagn, inst->stages - 1); 1125 // Largest possible deviation in magnPause for (co)var calculations 1126 tmp32no1 = WEBRTC_SPL_MAX(maxPause - avgPauseFX, avgPauseFX - minPause); 1127 // Get number of shifts to make sure we don't get wrap around in varPause 1128 nShifts = WEBRTC_SPL_MAX(0, 10 + inst->stages - WebRtcSpl_NormW32(tmp32no1)); 1129 1130 varMagnUFX = 0; 1131 varPauseUFX = 0; 1132 covMagnPauseFX = 0; 1133 for (i = 0; i < inst->magnLen; i++) { 1134 // Compute var and cov of magn and magn_pause 1135 tmp16no1 = (int16_t)((int32_t)magnIn[i] - avgMagnFX); 1136 tmp32no2 = inst->avgMagnPause[i] - avgPauseFX; 1137 varMagnUFX += (uint32_t)WEBRTC_SPL_MUL_16_16(tmp16no1, tmp16no1); // Q(2*qMagn) 1138 tmp32no1 = tmp32no2 * tmp16no1; // Q(prevQMagn+qMagn) 1139 covMagnPauseFX += tmp32no1; // Q(prevQMagn+qMagn) 1140 tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no2, nShifts); // Q(prevQMagn-minPause) 1141 varPauseUFX += (uint32_t)WEBRTC_SPL_MUL(tmp32no1, tmp32no1); // Q(2*(prevQMagn-minPause)) 1142 } 1143 //update of average magnitude spectrum: Q(-2*stages) and averaging replaced by shifts 1144 inst->curAvgMagnEnergy += WEBRTC_SPL_RSHIFT_U32(inst->magnEnergy, 2 * inst->normData 1145 + inst->stages - 1); 1146 1147 avgDiffNormMagnUFX = varMagnUFX; // Q(2*qMagn) 1148 if ((varPauseUFX) && (covMagnPauseFX)) { 1149 tmpU32no1 = (uint32_t)WEBRTC_SPL_ABS_W32(covMagnPauseFX); // Q(prevQMagn+qMagn) 1150 norm32 = WebRtcSpl_NormU32(tmpU32no1) - 16; 1151 if (norm32 > 0) { 1152 tmpU32no1 <<= norm32; // Q(prevQMagn+qMagn+norm32) 1153 } else { 1154 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, -norm32); // Q(prevQMagn+qMagn+norm32) 1155 } 1156 tmpU32no2 = WEBRTC_SPL_UMUL(tmpU32no1, tmpU32no1); // Q(2*(prevQMagn+qMagn-norm32)) 1157 1158 nShifts += norm32; 1159 nShifts <<= 1; 1160 if (nShifts < 0) { 1161 varPauseUFX >>= (-nShifts); // Q(2*(qMagn+norm32+minPause)) 1162 nShifts = 0; 1163 } 1164 if (varPauseUFX > 0) { 1165 // Q(2*(qMagn+norm32-16+minPause)) 1166 tmpU32no1 = tmpU32no2 / varPauseUFX; 1167 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, nShifts); 1168 1169 // Q(2*qMagn) 1170 avgDiffNormMagnUFX -= WEBRTC_SPL_MIN(avgDiffNormMagnUFX, tmpU32no1); 1171 } else { 1172 avgDiffNormMagnUFX = 0; 1173 } 1174 } 1175 //normalize and compute time average update of difference feature 1176 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(avgDiffNormMagnUFX, 2 * inst->normData); 1177 if (inst->featureSpecDiff > tmpU32no1) { 1178 tmpU32no2 = WEBRTC_SPL_UMUL_32_16(inst->featureSpecDiff - tmpU32no1, 1179 SPECT_DIFF_TAVG_Q8); // Q(8-2*stages) 1180 inst->featureSpecDiff -= WEBRTC_SPL_RSHIFT_U32(tmpU32no2, 8); // Q(-2*stages) 1181 } else { 1182 tmpU32no2 = WEBRTC_SPL_UMUL_32_16(tmpU32no1 - inst->featureSpecDiff, 1183 SPECT_DIFF_TAVG_Q8); // Q(8-2*stages) 1184 inst->featureSpecDiff += WEBRTC_SPL_RSHIFT_U32(tmpU32no2, 8); // Q(-2*stages) 1185 } 1186 } 1187 1188 // Transform input (speechFrame) to frequency domain magnitude (magnU16) 1189 void WebRtcNsx_DataAnalysis(NsxInst_t* inst, short* speechFrame, uint16_t* magnU16) { 1190 1191 uint32_t tmpU32no1, tmpU32no2; 1192 1193 int32_t tmp_1_w32 = 0; 1194 int32_t tmp_2_w32 = 0; 1195 int32_t sum_log_magn = 0; 1196 int32_t sum_log_i_log_magn = 0; 1197 1198 uint16_t sum_log_magn_u16 = 0; 1199 uint16_t tmp_u16 = 0; 1200 1201 int16_t sum_log_i = 0; 1202 int16_t sum_log_i_square = 0; 1203 int16_t frac = 0; 1204 int16_t log2 = 0; 1205 int16_t matrix_determinant = 0; 1206 int16_t maxWinData; 1207 1208 int i, j; 1209 int zeros; 1210 int net_norm = 0; 1211 int right_shifts_in_magnU16 = 0; 1212 int right_shifts_in_initMagnEst = 0; 1213 1214 int16_t winData_buff[ANAL_BLOCKL_MAX * 2 + 16]; 1215 int16_t realImag_buff[ANAL_BLOCKL_MAX * 2 + 16]; 1216 1217 // Align the structures to 32-byte boundary for the FFT function. 1218 int16_t* winData = (int16_t*) (((uintptr_t)winData_buff + 31) & ~31); 1219 int16_t* realImag = (int16_t*) (((uintptr_t) realImag_buff + 31) & ~31); 1220 1221 // Update analysis buffer for lower band, and window data before FFT. 1222 WebRtcNsx_AnalysisUpdate(inst, winData, speechFrame); 1223 1224 // Get input energy 1225 inst->energyIn = WebRtcSpl_Energy(winData, (int)inst->anaLen, &(inst->scaleEnergyIn)); 1226 1227 // Reset zero input flag 1228 inst->zeroInputSignal = 0; 1229 // Acquire norm for winData 1230 maxWinData = WebRtcSpl_MaxAbsValueW16(winData, inst->anaLen); 1231 inst->normData = WebRtcSpl_NormW16(maxWinData); 1232 if (maxWinData == 0) { 1233 // Treat zero input separately. 1234 inst->zeroInputSignal = 1; 1235 return; 1236 } 1237 1238 // Determine the net normalization in the frequency domain 1239 net_norm = inst->stages - inst->normData; 1240 // Track lowest normalization factor and use it to prevent wrap around in shifting 1241 right_shifts_in_magnU16 = inst->normData - inst->minNorm; 1242 right_shifts_in_initMagnEst = WEBRTC_SPL_MAX(-right_shifts_in_magnU16, 0); 1243 inst->minNorm -= right_shifts_in_initMagnEst; 1244 right_shifts_in_magnU16 = WEBRTC_SPL_MAX(right_shifts_in_magnU16, 0); 1245 1246 // create realImag as winData interleaved with zeros (= imag. part), normalize it 1247 WebRtcNsx_NormalizeRealBuffer(inst, winData, realImag); 1248 1249 // FFT output will be in winData[]. 1250 WebRtcSpl_RealForwardFFT(inst->real_fft, realImag, winData); 1251 1252 inst->imag[0] = 0; // Q(normData-stages) 1253 inst->imag[inst->anaLen2] = 0; 1254 inst->real[0] = winData[0]; // Q(normData-stages) 1255 inst->real[inst->anaLen2] = winData[inst->anaLen]; 1256 // Q(2*(normData-stages)) 1257 inst->magnEnergy = (uint32_t)WEBRTC_SPL_MUL_16_16(inst->real[0], inst->real[0]); 1258 inst->magnEnergy += (uint32_t)WEBRTC_SPL_MUL_16_16(inst->real[inst->anaLen2], 1259 inst->real[inst->anaLen2]); 1260 magnU16[0] = (uint16_t)WEBRTC_SPL_ABS_W16(inst->real[0]); // Q(normData-stages) 1261 magnU16[inst->anaLen2] = (uint16_t)WEBRTC_SPL_ABS_W16(inst->real[inst->anaLen2]); 1262 inst->sumMagn = (uint32_t)magnU16[0]; // Q(normData-stages) 1263 inst->sumMagn += (uint32_t)magnU16[inst->anaLen2]; 1264 1265 if (inst->blockIndex >= END_STARTUP_SHORT) { 1266 for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { 1267 inst->real[i] = winData[j]; 1268 inst->imag[i] = -winData[j + 1]; 1269 // magnitude spectrum 1270 // energy in Q(2*(normData-stages)) 1271 tmpU32no1 = (uint32_t)WEBRTC_SPL_MUL_16_16(winData[j], winData[j]); 1272 tmpU32no1 += (uint32_t)WEBRTC_SPL_MUL_16_16(winData[j + 1], winData[j + 1]); 1273 inst->magnEnergy += tmpU32no1; // Q(2*(normData-stages)) 1274 1275 magnU16[i] = (uint16_t)WebRtcSpl_SqrtFloor(tmpU32no1); // Q(normData-stages) 1276 inst->sumMagn += (uint32_t)magnU16[i]; // Q(normData-stages) 1277 } 1278 } else { 1279 // 1280 // Gather information during startup for noise parameter estimation 1281 // 1282 1283 // Switch initMagnEst to Q(minNorm-stages) 1284 inst->initMagnEst[0] = WEBRTC_SPL_RSHIFT_U32(inst->initMagnEst[0], 1285 right_shifts_in_initMagnEst); 1286 inst->initMagnEst[inst->anaLen2] = 1287 WEBRTC_SPL_RSHIFT_U32(inst->initMagnEst[inst->anaLen2], 1288 right_shifts_in_initMagnEst); // Q(minNorm-stages) 1289 1290 // Shift magnU16 to same domain as initMagnEst 1291 tmpU32no1 = WEBRTC_SPL_RSHIFT_W32((uint32_t)magnU16[0], 1292 right_shifts_in_magnU16); // Q(minNorm-stages) 1293 tmpU32no2 = WEBRTC_SPL_RSHIFT_W32((uint32_t)magnU16[inst->anaLen2], 1294 right_shifts_in_magnU16); // Q(minNorm-stages) 1295 1296 // Update initMagnEst 1297 inst->initMagnEst[0] += tmpU32no1; // Q(minNorm-stages) 1298 inst->initMagnEst[inst->anaLen2] += tmpU32no2; // Q(minNorm-stages) 1299 1300 log2 = 0; 1301 if (magnU16[inst->anaLen2]) { 1302 // Calculate log2(magnU16[inst->anaLen2]) 1303 zeros = WebRtcSpl_NormU32((uint32_t)magnU16[inst->anaLen2]); 1304 frac = (int16_t)((((uint32_t)magnU16[inst->anaLen2] << zeros) & 1305 0x7FFFFFFF) >> 23); // Q8 1306 // log2(magnU16(i)) in Q8 1307 assert(frac < 256); 1308 log2 = (int16_t)(((31 - zeros) << 8) + WebRtcNsx_kLogTableFrac[frac]); 1309 } 1310 1311 sum_log_magn = (int32_t)log2; // Q8 1312 // sum_log_i_log_magn in Q17 1313 sum_log_i_log_magn = (WEBRTC_SPL_MUL_16_16(kLogIndex[inst->anaLen2], log2) >> 3); 1314 1315 for (i = 1, j = 2; i < inst->anaLen2; i += 1, j += 2) { 1316 inst->real[i] = winData[j]; 1317 inst->imag[i] = -winData[j + 1]; 1318 // magnitude spectrum 1319 // energy in Q(2*(normData-stages)) 1320 tmpU32no1 = (uint32_t)WEBRTC_SPL_MUL_16_16(winData[j], winData[j]); 1321 tmpU32no1 += (uint32_t)WEBRTC_SPL_MUL_16_16(winData[j + 1], winData[j + 1]); 1322 inst->magnEnergy += tmpU32no1; // Q(2*(normData-stages)) 1323 1324 magnU16[i] = (uint16_t)WebRtcSpl_SqrtFloor(tmpU32no1); // Q(normData-stages) 1325 inst->sumMagn += (uint32_t)magnU16[i]; // Q(normData-stages) 1326 1327 // Switch initMagnEst to Q(minNorm-stages) 1328 inst->initMagnEst[i] = WEBRTC_SPL_RSHIFT_U32(inst->initMagnEst[i], 1329 right_shifts_in_initMagnEst); 1330 1331 // Shift magnU16 to same domain as initMagnEst, i.e., Q(minNorm-stages) 1332 tmpU32no1 = WEBRTC_SPL_RSHIFT_W32((uint32_t)magnU16[i], 1333 right_shifts_in_magnU16); 1334 // Update initMagnEst 1335 inst->initMagnEst[i] += tmpU32no1; // Q(minNorm-stages) 1336 1337 if (i >= kStartBand) { 1338 // For pink noise estimation. Collect data neglecting lower frequency band 1339 log2 = 0; 1340 if (magnU16[i]) { 1341 zeros = WebRtcSpl_NormU32((uint32_t)magnU16[i]); 1342 frac = (int16_t)((((uint32_t)magnU16[i] << zeros) & 1343 0x7FFFFFFF) >> 23); 1344 // log2(magnU16(i)) in Q8 1345 assert(frac < 256); 1346 log2 = (int16_t)(((31 - zeros) << 8) 1347 + WebRtcNsx_kLogTableFrac[frac]); 1348 } 1349 sum_log_magn += (int32_t)log2; // Q8 1350 // sum_log_i_log_magn in Q17 1351 sum_log_i_log_magn += (WEBRTC_SPL_MUL_16_16(kLogIndex[i], log2) >> 3); 1352 } 1353 } 1354 1355 // 1356 //compute simplified noise model during startup 1357 // 1358 1359 // Estimate White noise 1360 1361 // Switch whiteNoiseLevel to Q(minNorm-stages) 1362 inst->whiteNoiseLevel = WEBRTC_SPL_RSHIFT_U32(inst->whiteNoiseLevel, 1363 right_shifts_in_initMagnEst); 1364 1365 // Update the average magnitude spectrum, used as noise estimate. 1366 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(inst->sumMagn, inst->overdrive); 1367 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, inst->stages + 8); 1368 1369 // Replacing division above with 'stages' shifts 1370 // Shift to same Q-domain as whiteNoiseLevel 1371 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, right_shifts_in_magnU16); 1372 // This operation is safe from wrap around as long as END_STARTUP_SHORT < 128 1373 assert(END_STARTUP_SHORT < 128); 1374 inst->whiteNoiseLevel += tmpU32no1; // Q(minNorm-stages) 1375 1376 // Estimate Pink noise parameters 1377 // Denominator used in both parameter estimates. 1378 // The value is only dependent on the size of the frequency band (kStartBand) 1379 // and to reduce computational complexity stored in a table (kDeterminantEstMatrix[]) 1380 assert(kStartBand < 66); 1381 matrix_determinant = kDeterminantEstMatrix[kStartBand]; // Q0 1382 sum_log_i = kSumLogIndex[kStartBand]; // Q5 1383 sum_log_i_square = kSumSquareLogIndex[kStartBand]; // Q2 1384 if (inst->fs == 8000) { 1385 // Adjust values to shorter blocks in narrow band. 1386 tmp_1_w32 = (int32_t)matrix_determinant; 1387 tmp_1_w32 += WEBRTC_SPL_MUL_16_16_RSFT(kSumLogIndex[65], sum_log_i, 9); 1388 tmp_1_w32 -= WEBRTC_SPL_MUL_16_16_RSFT(kSumLogIndex[65], kSumLogIndex[65], 10); 1389 tmp_1_w32 -= WEBRTC_SPL_LSHIFT_W32((int32_t)sum_log_i_square, 4); 1390 tmp_1_w32 -= WEBRTC_SPL_MUL_16_16_RSFT((int16_t) 1391 (inst->magnLen - kStartBand), kSumSquareLogIndex[65], 2); 1392 matrix_determinant = (int16_t)tmp_1_w32; 1393 sum_log_i -= kSumLogIndex[65]; // Q5 1394 sum_log_i_square -= kSumSquareLogIndex[65]; // Q2 1395 } 1396 1397 // Necessary number of shifts to fit sum_log_magn in a word16 1398 zeros = 16 - WebRtcSpl_NormW32(sum_log_magn); 1399 if (zeros < 0) { 1400 zeros = 0; 1401 } 1402 tmp_1_w32 = WEBRTC_SPL_LSHIFT_W32(sum_log_magn, 1); // Q9 1403 sum_log_magn_u16 = (uint16_t)WEBRTC_SPL_RSHIFT_W32(tmp_1_w32, zeros);//Q(9-zeros) 1404 1405 // Calculate and update pinkNoiseNumerator. Result in Q11. 1406 tmp_2_w32 = WEBRTC_SPL_MUL_16_U16(sum_log_i_square, sum_log_magn_u16); // Q(11-zeros) 1407 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32((uint32_t)sum_log_i_log_magn, 12); // Q5 1408 1409 // Shift the largest value of sum_log_i and tmp32no3 before multiplication 1410 tmp_u16 = ((uint16_t)sum_log_i << 1); // Q6 1411 if ((uint32_t)sum_log_i > tmpU32no1) { 1412 tmp_u16 >>= zeros; 1413 } else { 1414 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, zeros); 1415 } 1416 tmp_2_w32 -= (int32_t)WEBRTC_SPL_UMUL_32_16(tmpU32no1, tmp_u16); // Q(11-zeros) 1417 matrix_determinant = WEBRTC_SPL_RSHIFT_W16(matrix_determinant, zeros); // Q(-zeros) 1418 tmp_2_w32 = WebRtcSpl_DivW32W16(tmp_2_w32, matrix_determinant); // Q11 1419 tmp_2_w32 += WEBRTC_SPL_LSHIFT_W32((int32_t)net_norm, 11); // Q11 1420 if (tmp_2_w32 < 0) { 1421 tmp_2_w32 = 0; 1422 } 1423 inst->pinkNoiseNumerator += tmp_2_w32; // Q11 1424 1425 // Calculate and update pinkNoiseExp. Result in Q14. 1426 tmp_2_w32 = WEBRTC_SPL_MUL_16_U16(sum_log_i, sum_log_magn_u16); // Q(14-zeros) 1427 tmp_1_w32 = WEBRTC_SPL_RSHIFT_W32(sum_log_i_log_magn, 3 + zeros); 1428 tmp_1_w32 = WEBRTC_SPL_MUL((int32_t)(inst->magnLen - kStartBand), 1429 tmp_1_w32); 1430 tmp_2_w32 -= tmp_1_w32; // Q(14-zeros) 1431 if (tmp_2_w32 > 0) { 1432 // If the exponential parameter is negative force it to zero, which means a 1433 // flat spectrum. 1434 tmp_1_w32 = WebRtcSpl_DivW32W16(tmp_2_w32, matrix_determinant); // Q14 1435 inst->pinkNoiseExp += WEBRTC_SPL_SAT(16384, tmp_1_w32, 0); // Q14 1436 } 1437 } 1438 } 1439 1440 void WebRtcNsx_DataSynthesis(NsxInst_t* inst, short* outFrame) { 1441 int32_t energyOut; 1442 1443 int16_t realImag_buff[ANAL_BLOCKL_MAX * 2 + 16]; 1444 int16_t rfft_out_buff[ANAL_BLOCKL_MAX * 2 + 16]; 1445 1446 // Align the structures to 32-byte boundary for the FFT function. 1447 int16_t* realImag = (int16_t*) (((uintptr_t)realImag_buff + 31) & ~31); 1448 int16_t* rfft_out = (int16_t*) (((uintptr_t) rfft_out_buff + 31) & ~31); 1449 1450 int16_t tmp16no1, tmp16no2; 1451 int16_t energyRatio; 1452 int16_t gainFactor, gainFactor1, gainFactor2; 1453 1454 int i; 1455 int outCIFFT; 1456 int scaleEnergyOut = 0; 1457 1458 if (inst->zeroInputSignal) { 1459 // synthesize the special case of zero input 1460 // read out fully processed segment 1461 for (i = 0; i < inst->blockLen10ms; i++) { 1462 outFrame[i] = inst->synthesisBuffer[i]; // Q0 1463 } 1464 // update synthesis buffer 1465 WEBRTC_SPL_MEMCPY_W16(inst->synthesisBuffer, 1466 inst->synthesisBuffer + inst->blockLen10ms, 1467 inst->anaLen - inst->blockLen10ms); 1468 WebRtcSpl_ZerosArrayW16(inst->synthesisBuffer + inst->anaLen - inst->blockLen10ms, 1469 inst->blockLen10ms); 1470 return; 1471 } 1472 1473 // Filter the data in the frequency domain, and create spectrum. 1474 WebRtcNsx_PrepareSpectrum(inst, realImag); 1475 1476 // Inverse FFT output will be in rfft_out[]. 1477 outCIFFT = WebRtcSpl_RealInverseFFT(inst->real_fft, realImag, rfft_out); 1478 1479 WebRtcNsx_Denormalize(inst, rfft_out, outCIFFT); 1480 1481 //scale factor: only do it after END_STARTUP_LONG time 1482 gainFactor = 8192; // 8192 = Q13(1.0) 1483 if (inst->gainMap == 1 && 1484 inst->blockIndex > END_STARTUP_LONG && 1485 inst->energyIn > 0) { 1486 energyOut = WebRtcSpl_Energy(inst->real, (int)inst->anaLen, &scaleEnergyOut); // Q(-scaleEnergyOut) 1487 if (scaleEnergyOut == 0 && !(energyOut & 0x7f800000)) { 1488 energyOut = WEBRTC_SPL_SHIFT_W32(energyOut, 8 + scaleEnergyOut 1489 - inst->scaleEnergyIn); 1490 } else { 1491 inst->energyIn = WEBRTC_SPL_RSHIFT_W32(inst->energyIn, 8 + scaleEnergyOut 1492 - inst->scaleEnergyIn); // Q(-8-scaleEnergyOut) 1493 } 1494 1495 assert(inst->energyIn > 0); 1496 energyRatio = (energyOut + inst->energyIn / 2) / inst->energyIn; // Q8 1497 // Limit the ratio to [0, 1] in Q8, i.e., [0, 256] 1498 energyRatio = WEBRTC_SPL_SAT(256, energyRatio, 0); 1499 1500 // all done in lookup tables now 1501 assert(energyRatio < 257); 1502 gainFactor1 = kFactor1Table[energyRatio]; // Q8 1503 gainFactor2 = inst->factor2Table[energyRatio]; // Q8 1504 1505 //combine both scales with speech/noise prob: note prior (priorSpeechProb) is not frequency dependent 1506 1507 // factor = inst->priorSpeechProb*factor1 + (1.0-inst->priorSpeechProb)*factor2; // original code 1508 tmp16no1 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(16384 - inst->priorNonSpeechProb, 1509 gainFactor1, 14); // Q13 16384 = Q14(1.0) 1510 tmp16no2 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(inst->priorNonSpeechProb, 1511 gainFactor2, 14); // Q13; 1512 gainFactor = tmp16no1 + tmp16no2; // Q13 1513 } // out of flag_gain_map==1 1514 1515 // Synthesis, read out fully processed segment, and update synthesis buffer. 1516 WebRtcNsx_SynthesisUpdate(inst, outFrame, gainFactor); 1517 } 1518 1519 int WebRtcNsx_ProcessCore(NsxInst_t* inst, short* speechFrame, short* speechFrameHB, 1520 short* outFrame, short* outFrameHB) { 1521 // main routine for noise suppression 1522 1523 uint32_t tmpU32no1, tmpU32no2, tmpU32no3; 1524 uint32_t satMax, maxNoiseU32; 1525 uint32_t tmpMagnU32, tmpNoiseU32; 1526 uint32_t nearMagnEst; 1527 uint32_t noiseUpdateU32; 1528 uint32_t noiseU32[HALF_ANAL_BLOCKL]; 1529 uint32_t postLocSnr[HALF_ANAL_BLOCKL]; 1530 uint32_t priorLocSnr[HALF_ANAL_BLOCKL]; 1531 uint32_t prevNearSnr[HALF_ANAL_BLOCKL]; 1532 uint32_t curNearSnr; 1533 uint32_t priorSnr; 1534 uint32_t noise_estimate = 0; 1535 uint32_t noise_estimate_avg = 0; 1536 uint32_t numerator = 0; 1537 1538 int32_t tmp32no1, tmp32no2; 1539 int32_t pink_noise_num_avg = 0; 1540 1541 uint16_t tmpU16no1; 1542 uint16_t magnU16[HALF_ANAL_BLOCKL]; 1543 uint16_t prevNoiseU16[HALF_ANAL_BLOCKL]; 1544 uint16_t nonSpeechProbFinal[HALF_ANAL_BLOCKL]; 1545 uint16_t gammaNoise, prevGammaNoise; 1546 uint16_t noiseSupFilterTmp[HALF_ANAL_BLOCKL]; 1547 1548 int16_t qMagn, qNoise; 1549 int16_t avgProbSpeechHB, gainModHB, avgFilterGainHB, gainTimeDomainHB; 1550 int16_t pink_noise_exp_avg = 0; 1551 1552 int i; 1553 int nShifts, postShifts; 1554 int norm32no1, norm32no2; 1555 int flag, sign; 1556 int q_domain_to_use = 0; 1557 1558 // Code for ARMv7-Neon platform assumes the following: 1559 assert(inst->anaLen > 0); 1560 assert(inst->anaLen2 > 0); 1561 assert(inst->anaLen % 16 == 0); 1562 assert(inst->anaLen2 % 8 == 0); 1563 assert(inst->blockLen10ms > 0); 1564 assert(inst->blockLen10ms % 16 == 0); 1565 assert(inst->magnLen == inst->anaLen2 + 1); 1566 1567 #ifdef NS_FILEDEBUG 1568 if (fwrite(spframe, sizeof(short), 1569 inst->blockLen10ms, inst->infile) != inst->blockLen10ms) { 1570 return -1; 1571 } 1572 #endif 1573 1574 // Check that initialization has been done 1575 if (inst->initFlag != 1) { 1576 return -1; 1577 } 1578 // Check for valid pointers based on sampling rate 1579 if ((inst->fs == 32000) && (speechFrameHB == NULL)) { 1580 return -1; 1581 } 1582 1583 // Store speechFrame and transform to frequency domain 1584 WebRtcNsx_DataAnalysis(inst, speechFrame, magnU16); 1585 1586 if (inst->zeroInputSignal) { 1587 WebRtcNsx_DataSynthesis(inst, outFrame); 1588 1589 if (inst->fs == 32000) { 1590 // update analysis buffer for H band 1591 // append new data to buffer FX 1592 WEBRTC_SPL_MEMCPY_W16(inst->dataBufHBFX, inst->dataBufHBFX + inst->blockLen10ms, 1593 inst->anaLen - inst->blockLen10ms); 1594 WEBRTC_SPL_MEMCPY_W16(inst->dataBufHBFX + inst->anaLen - inst->blockLen10ms, 1595 speechFrameHB, inst->blockLen10ms); 1596 for (i = 0; i < inst->blockLen10ms; i++) { 1597 outFrameHB[i] = inst->dataBufHBFX[i]; // Q0 1598 } 1599 } // end of H band gain computation 1600 return 0; 1601 } 1602 1603 // Update block index when we have something to process 1604 inst->blockIndex++; 1605 // 1606 1607 // Norm of magn 1608 qMagn = inst->normData - inst->stages; 1609 1610 // Compute spectral flatness on input spectrum 1611 WebRtcNsx_ComputeSpectralFlatness(inst, magnU16); 1612 1613 // quantile noise estimate 1614 WebRtcNsx_NoiseEstimation(inst, magnU16, noiseU32, &qNoise); 1615 1616 //noise estimate from previous frame 1617 for (i = 0; i < inst->magnLen; i++) { 1618 prevNoiseU16[i] = (uint16_t)WEBRTC_SPL_RSHIFT_U32(inst->prevNoiseU32[i], 11); // Q(prevQNoise) 1619 } 1620 1621 if (inst->blockIndex < END_STARTUP_SHORT) { 1622 // Noise Q-domain to be used later; see description at end of section. 1623 q_domain_to_use = WEBRTC_SPL_MIN((int)qNoise, inst->minNorm - inst->stages); 1624 1625 // Calculate frequency independent parts in parametric noise estimate and calculate 1626 // the estimate for the lower frequency band (same values for all frequency bins) 1627 if (inst->pinkNoiseExp) { 1628 pink_noise_exp_avg = (int16_t)WebRtcSpl_DivW32W16(inst->pinkNoiseExp, 1629 (int16_t)(inst->blockIndex + 1)); // Q14 1630 pink_noise_num_avg = WebRtcSpl_DivW32W16(inst->pinkNoiseNumerator, 1631 (int16_t)(inst->blockIndex + 1)); // Q11 1632 WebRtcNsx_CalcParametricNoiseEstimate(inst, 1633 pink_noise_exp_avg, 1634 pink_noise_num_avg, 1635 kStartBand, 1636 &noise_estimate, 1637 &noise_estimate_avg); 1638 } else { 1639 // Use white noise estimate if we have poor pink noise parameter estimates 1640 noise_estimate = inst->whiteNoiseLevel; // Q(minNorm-stages) 1641 noise_estimate_avg = noise_estimate / (inst->blockIndex + 1); // Q(minNorm-stages) 1642 } 1643 for (i = 0; i < inst->magnLen; i++) { 1644 // Estimate the background noise using the pink noise parameters if permitted 1645 if ((inst->pinkNoiseExp) && (i >= kStartBand)) { 1646 // Reset noise_estimate 1647 noise_estimate = 0; 1648 noise_estimate_avg = 0; 1649 // Calculate the parametric noise estimate for current frequency bin 1650 WebRtcNsx_CalcParametricNoiseEstimate(inst, 1651 pink_noise_exp_avg, 1652 pink_noise_num_avg, 1653 i, 1654 &noise_estimate, 1655 &noise_estimate_avg); 1656 } 1657 // Calculate parametric Wiener filter 1658 noiseSupFilterTmp[i] = inst->denoiseBound; 1659 if (inst->initMagnEst[i]) { 1660 // numerator = (initMagnEst - noise_estimate * overdrive) 1661 // Result in Q(8+minNorm-stages) 1662 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(noise_estimate, inst->overdrive); 1663 numerator = inst->initMagnEst[i] << 8; 1664 if (numerator > tmpU32no1) { 1665 // Suppression filter coefficient larger than zero, so calculate. 1666 numerator -= tmpU32no1; 1667 1668 // Determine number of left shifts in numerator for best accuracy after 1669 // division 1670 nShifts = WebRtcSpl_NormU32(numerator); 1671 nShifts = WEBRTC_SPL_SAT(6, nShifts, 0); 1672 1673 // Shift numerator to Q(nShifts+8+minNorm-stages) 1674 numerator <<= nShifts; 1675 1676 // Shift denominator to Q(nShifts-6+minNorm-stages) 1677 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(inst->initMagnEst[i], 6 - nShifts); 1678 if (tmpU32no1 == 0) { 1679 // This is only possible if numerator = 0, in which case 1680 // we don't need any division. 1681 tmpU32no1 = 1; 1682 } 1683 tmpU32no2 = numerator / tmpU32no1; // Q14 1684 noiseSupFilterTmp[i] = (uint16_t)WEBRTC_SPL_SAT(16384, tmpU32no2, 1685 (uint32_t)(inst->denoiseBound)); // Q14 1686 } 1687 } 1688 // Weight quantile noise 'noiseU32' with modeled noise 'noise_estimate_avg' 1689 // 'noiseU32 is in Q(qNoise) and 'noise_estimate' in Q(minNorm-stages) 1690 // To guarantee that we do not get wrap around when shifting to the same domain 1691 // we use the lowest one. Furthermore, we need to save 6 bits for the weighting. 1692 // 'noise_estimate_avg' can handle this operation by construction, but 'noiseU32' 1693 // may not. 1694 1695 // Shift 'noiseU32' to 'q_domain_to_use' 1696 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(noiseU32[i], (int)qNoise - q_domain_to_use); 1697 // Shift 'noise_estimate_avg' to 'q_domain_to_use' 1698 tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(noise_estimate_avg, inst->minNorm - inst->stages 1699 - q_domain_to_use); 1700 // Make a simple check to see if we have enough room for weighting 'tmpU32no1' 1701 // without wrap around 1702 nShifts = 0; 1703 if (tmpU32no1 & 0xfc000000) { 1704 tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 6); 1705 tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, 6); 1706 nShifts = 6; 1707 } 1708 tmpU32no1 *= inst->blockIndex; 1709 tmpU32no2 *= (END_STARTUP_SHORT - inst->blockIndex); 1710 // Add them together and divide by startup length 1711 noiseU32[i] = WebRtcSpl_DivU32U16(tmpU32no1 + tmpU32no2, END_STARTUP_SHORT); 1712 // Shift back if necessary 1713 noiseU32[i] <<= nShifts; 1714 } 1715 // Update new Q-domain for 'noiseU32' 1716 qNoise = q_domain_to_use; 1717 } 1718 // compute average signal during END_STARTUP_LONG time: 1719 // used to normalize spectral difference measure 1720 if (inst->blockIndex < END_STARTUP_LONG) { 1721 // substituting division with shift ending up in Q(-2*stages) 1722 inst->timeAvgMagnEnergyTmp 1723 += WEBRTC_SPL_RSHIFT_U32(inst->magnEnergy, 1724 2 * inst->normData + inst->stages - 1); 1725 inst->timeAvgMagnEnergy = WebRtcSpl_DivU32U16(inst->timeAvgMagnEnergyTmp, 1726 inst->blockIndex + 1); 1727 } 1728 1729 //start processing at frames == converged+1 1730 // STEP 1: compute prior and post SNR based on quantile noise estimates 1731 1732 // compute direct decision (DD) estimate of prior SNR: needed for new method 1733 satMax = (uint32_t)1048575;// Largest possible value without getting overflow despite shifting 12 steps 1734 postShifts = 6 + qMagn - qNoise; 1735 nShifts = 5 - inst->prevQMagn + inst->prevQNoise; 1736 for (i = 0; i < inst->magnLen; i++) { 1737 // FLOAT: 1738 // post SNR 1739 // postLocSnr[i] = 0.0; 1740 // if (magn[i] > noise[i]) 1741 // { 1742 // postLocSnr[i] = magn[i] / (noise[i] + 0.0001); 1743 // } 1744 // // previous post SNR 1745 // // previous estimate: based on previous frame with gain filter (smooth is previous filter) 1746 // 1747 // prevNearSnr[i] = inst->prevMagnU16[i] / (inst->noisePrev[i] + 0.0001) * (inst->smooth[i]); 1748 // 1749 // // DD estimate is sum of two terms: current estimate and previous estimate 1750 // // directed decision update of priorSnr (or we actually store [2*priorSnr+1]) 1751 // 1752 // priorLocSnr[i] = DD_PR_SNR * prevNearSnr[i] + (1.0 - DD_PR_SNR) * (postLocSnr[i] - 1.0); 1753 1754 // calculate post SNR: output in Q11 1755 postLocSnr[i] = 2048; // 1.0 in Q11 1756 tmpU32no1 = (uint32_t)magnU16[i] << 6; // Q(6+qMagn) 1757 if (postShifts < 0) { 1758 tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(noiseU32[i], -postShifts); // Q(6+qMagn) 1759 } else { 1760 tmpU32no2 = noiseU32[i] << postShifts; // Q(6+qMagn) 1761 } 1762 if (tmpU32no1 > tmpU32no2) { 1763 // Current magnitude larger than noise 1764 tmpU32no1 <<= 11; // Q(17+qMagn) 1765 if (tmpU32no2 > 0) { 1766 tmpU32no1 /= tmpU32no2; // Q11 1767 postLocSnr[i] = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 1768 } else { 1769 postLocSnr[i] = satMax; 1770 } 1771 } 1772 1773 // calculate prevNearSnr[i] and save for later instead of recalculating it later 1774 // |nearMagnEst| in Q(prevQMagn + 14) 1775 nearMagnEst = inst->prevMagnU16[i] * inst->noiseSupFilter[i]; 1776 tmpU32no1 = nearMagnEst << 3; // Q(prevQMagn+17) 1777 tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->prevNoiseU32[i], nShifts); // Q(prevQMagn+6) 1778 1779 if (tmpU32no2 > 0) { 1780 tmpU32no1 /= tmpU32no2; // Q11 1781 tmpU32no1 = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 1782 } else { 1783 tmpU32no1 = satMax; // Q11 1784 } 1785 prevNearSnr[i] = tmpU32no1; // Q11 1786 1787 //directed decision update of priorSnr 1788 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(prevNearSnr[i], DD_PR_SNR_Q11); // Q22 1789 tmpU32no2 = WEBRTC_SPL_UMUL_32_16(postLocSnr[i] - 2048, ONE_MINUS_DD_PR_SNR_Q11); // Q22 1790 priorSnr = tmpU32no1 + tmpU32no2 + 512; // Q22 (added 512 for rounding) 1791 // priorLocSnr = 1 + 2*priorSnr 1792 priorLocSnr[i] = 2048 + WEBRTC_SPL_RSHIFT_U32(priorSnr, 10); // Q11 1793 } // end of loop over frequencies 1794 // done with step 1: DD computation of prior and post SNR 1795 1796 // STEP 2: compute speech/noise likelihood 1797 1798 //compute difference of input spectrum with learned/estimated noise spectrum 1799 WebRtcNsx_ComputeSpectralDifference(inst, magnU16); 1800 //compute histograms for determination of parameters (thresholds and weights for features) 1801 //parameters are extracted once every window time (=inst->modelUpdate) 1802 //counter update 1803 inst->cntThresUpdate++; 1804 flag = (int)(inst->cntThresUpdate == inst->modelUpdate); 1805 //update histogram 1806 WebRtcNsx_FeatureParameterExtraction(inst, flag); 1807 //compute model parameters 1808 if (flag) { 1809 inst->cntThresUpdate = 0; // Reset counter 1810 //update every window: 1811 // get normalization for spectral difference for next window estimate 1812 1813 // Shift to Q(-2*stages) 1814 inst->curAvgMagnEnergy = WEBRTC_SPL_RSHIFT_U32(inst->curAvgMagnEnergy, STAT_UPDATES); 1815 1816 tmpU32no1 = (inst->curAvgMagnEnergy + inst->timeAvgMagnEnergy + 1) >> 1; //Q(-2*stages) 1817 // Update featureSpecDiff 1818 if ((tmpU32no1 != inst->timeAvgMagnEnergy) && (inst->featureSpecDiff) && 1819 (inst->timeAvgMagnEnergy > 0)) { 1820 norm32no1 = 0; 1821 tmpU32no3 = tmpU32no1; 1822 while (0xFFFF0000 & tmpU32no3) { 1823 tmpU32no3 >>= 1; 1824 norm32no1++; 1825 } 1826 tmpU32no2 = inst->featureSpecDiff; 1827 while (0xFFFF0000 & tmpU32no2) { 1828 tmpU32no2 >>= 1; 1829 norm32no1++; 1830 } 1831 tmpU32no3 = WEBRTC_SPL_UMUL(tmpU32no3, tmpU32no2); 1832 tmpU32no3 /= inst->timeAvgMagnEnergy; 1833 if (WebRtcSpl_NormU32(tmpU32no3) < norm32no1) { 1834 inst->featureSpecDiff = 0x007FFFFF; 1835 } else { 1836 inst->featureSpecDiff = WEBRTC_SPL_MIN(0x007FFFFF, 1837 tmpU32no3 << norm32no1); 1838 } 1839 } 1840 1841 inst->timeAvgMagnEnergy = tmpU32no1; // Q(-2*stages) 1842 inst->curAvgMagnEnergy = 0; 1843 } 1844 1845 //compute speech/noise probability 1846 WebRtcNsx_SpeechNoiseProb(inst, nonSpeechProbFinal, priorLocSnr, postLocSnr); 1847 1848 //time-avg parameter for noise update 1849 gammaNoise = NOISE_UPDATE_Q8; // Q8 1850 1851 maxNoiseU32 = 0; 1852 postShifts = inst->prevQNoise - qMagn; 1853 nShifts = inst->prevQMagn - qMagn; 1854 for (i = 0; i < inst->magnLen; i++) { 1855 // temporary noise update: use it for speech frames if update value is less than previous 1856 // the formula has been rewritten into: 1857 // noiseUpdate = noisePrev[i] + (1 - gammaNoise) * nonSpeechProb * (magn[i] - noisePrev[i]) 1858 1859 if (postShifts < 0) { 1860 tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(magnU16[i], -postShifts); // Q(prevQNoise) 1861 } else { 1862 tmpU32no2 = (uint32_t)magnU16[i] << postShifts; // Q(prevQNoise) 1863 } 1864 if (prevNoiseU16[i] > tmpU32no2) { 1865 sign = -1; 1866 tmpU32no1 = prevNoiseU16[i] - tmpU32no2; 1867 } else { 1868 sign = 1; 1869 tmpU32no1 = tmpU32no2 - prevNoiseU16[i]; 1870 } 1871 noiseUpdateU32 = inst->prevNoiseU32[i]; // Q(prevQNoise+11) 1872 tmpU32no3 = 0; 1873 if ((tmpU32no1) && (nonSpeechProbFinal[i])) { 1874 // This value will be used later, if gammaNoise changes 1875 tmpU32no3 = WEBRTC_SPL_UMUL_32_16(tmpU32no1, nonSpeechProbFinal[i]); // Q(prevQNoise+8) 1876 if (0x7c000000 & tmpU32no3) { 1877 // Shifting required before multiplication 1878 tmpU32no2 1879 = WEBRTC_SPL_UMUL_32_16(WEBRTC_SPL_RSHIFT_U32(tmpU32no3, 5), gammaNoise); // Q(prevQNoise+11) 1880 } else { 1881 // We can do shifting after multiplication 1882 tmpU32no2 1883 = WEBRTC_SPL_RSHIFT_U32(WEBRTC_SPL_UMUL_32_16(tmpU32no3, gammaNoise), 5); // Q(prevQNoise+11) 1884 } 1885 if (sign > 0) { 1886 noiseUpdateU32 += tmpU32no2; // Q(prevQNoise+11) 1887 } else { 1888 // This operation is safe. We can never get wrap around, since worst 1889 // case scenario means magnU16 = 0 1890 noiseUpdateU32 -= tmpU32no2; // Q(prevQNoise+11) 1891 } 1892 } 1893 1894 //increase gamma (i.e., less noise update) for frame likely to be speech 1895 prevGammaNoise = gammaNoise; 1896 gammaNoise = NOISE_UPDATE_Q8; 1897 //time-constant based on speech/noise state 1898 //increase gamma (i.e., less noise update) for frames likely to be speech 1899 if (nonSpeechProbFinal[i] < ONE_MINUS_PROB_RANGE_Q8) { 1900 gammaNoise = GAMMA_NOISE_TRANS_AND_SPEECH_Q8; 1901 } 1902 1903 if (prevGammaNoise != gammaNoise) { 1904 // new noise update 1905 // this line is the same as above, only that the result is stored in a different variable and the gammaNoise 1906 // has changed 1907 // 1908 // noiseUpdate = noisePrev[i] + (1 - gammaNoise) * nonSpeechProb * (magn[i] - noisePrev[i]) 1909 1910 if (0x7c000000 & tmpU32no3) { 1911 // Shifting required before multiplication 1912 tmpU32no2 1913 = WEBRTC_SPL_UMUL_32_16(WEBRTC_SPL_RSHIFT_U32(tmpU32no3, 5), gammaNoise); // Q(prevQNoise+11) 1914 } else { 1915 // We can do shifting after multiplication 1916 tmpU32no2 1917 = WEBRTC_SPL_RSHIFT_U32(WEBRTC_SPL_UMUL_32_16(tmpU32no3, gammaNoise), 5); // Q(prevQNoise+11) 1918 } 1919 if (sign > 0) { 1920 tmpU32no1 = inst->prevNoiseU32[i] + tmpU32no2; // Q(prevQNoise+11) 1921 } else { 1922 tmpU32no1 = inst->prevNoiseU32[i] - tmpU32no2; // Q(prevQNoise+11) 1923 } 1924 if (noiseUpdateU32 > tmpU32no1) { 1925 noiseUpdateU32 = tmpU32no1; // Q(prevQNoise+11) 1926 } 1927 } 1928 noiseU32[i] = noiseUpdateU32; // Q(prevQNoise+11) 1929 if (noiseUpdateU32 > maxNoiseU32) { 1930 maxNoiseU32 = noiseUpdateU32; 1931 } 1932 1933 // conservative noise update 1934 // // original FLOAT code 1935 // if (prob_speech < PROB_RANGE) { 1936 // inst->avgMagnPause[i] = inst->avgMagnPause[i] + (1.0 - gamma_pause)*(magn[i] - inst->avgMagnPause[i]); 1937 // } 1938 1939 tmp32no2 = WEBRTC_SPL_SHIFT_W32(inst->avgMagnPause[i], -nShifts); 1940 if (nonSpeechProbFinal[i] > ONE_MINUS_PROB_RANGE_Q8) { 1941 if (nShifts < 0) { 1942 tmp32no1 = (int32_t)magnU16[i] - tmp32no2; // Q(qMagn) 1943 tmp32no1 *= ONE_MINUS_GAMMA_PAUSE_Q8; // Q(8+prevQMagn+nShifts) 1944 tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no1 + 128, 8); // Q(qMagn) 1945 } else { 1946 tmp32no1 = WEBRTC_SPL_LSHIFT_W32((int32_t)magnU16[i], nShifts) 1947 - inst->avgMagnPause[i]; // Q(qMagn+nShifts) 1948 tmp32no1 *= ONE_MINUS_GAMMA_PAUSE_Q8; // Q(8+prevQMagn+nShifts) 1949 tmp32no1 = WEBRTC_SPL_RSHIFT_W32(tmp32no1 + (128 << nShifts), 8 + nShifts); // Q(qMagn) 1950 } 1951 tmp32no2 += tmp32no1; // Q(qMagn) 1952 } 1953 inst->avgMagnPause[i] = tmp32no2; 1954 } // end of frequency loop 1955 1956 norm32no1 = WebRtcSpl_NormU32(maxNoiseU32); 1957 qNoise = inst->prevQNoise + norm32no1 - 5; 1958 // done with step 2: noise update 1959 1960 // STEP 3: compute dd update of prior snr and post snr based on new noise estimate 1961 nShifts = inst->prevQNoise + 11 - qMagn; 1962 for (i = 0; i < inst->magnLen; i++) { 1963 // FLOAT code 1964 // // post and prior SNR 1965 // curNearSnr = 0.0; 1966 // if (magn[i] > noise[i]) 1967 // { 1968 // curNearSnr = magn[i] / (noise[i] + 0.0001) - 1.0; 1969 // } 1970 // // DD estimate is sum of two terms: current estimate and previous estimate 1971 // // directed decision update of snrPrior 1972 // snrPrior = DD_PR_SNR * prevNearSnr[i] + (1.0 - DD_PR_SNR) * curNearSnr; 1973 // // gain filter 1974 // tmpFloat1 = inst->overdrive + snrPrior; 1975 // tmpFloat2 = snrPrior / tmpFloat1; 1976 // theFilter[i] = tmpFloat2; 1977 1978 // calculate curNearSnr again, this is necessary because a new noise estimate has been made since then. for the original 1979 curNearSnr = 0; // Q11 1980 if (nShifts < 0) { 1981 // This case is equivalent with magn < noise which implies curNearSnr = 0; 1982 tmpMagnU32 = (uint32_t)magnU16[i]; // Q(qMagn) 1983 tmpNoiseU32 = noiseU32[i] << -nShifts; // Q(qMagn) 1984 } else if (nShifts > 17) { 1985 tmpMagnU32 = (uint32_t)magnU16[i] << 17; // Q(qMagn+17) 1986 tmpNoiseU32 = WEBRTC_SPL_RSHIFT_U32(noiseU32[i], nShifts - 17); // Q(qMagn+17) 1987 } else { 1988 tmpMagnU32 = (uint32_t)magnU16[i] << nShifts; // Q(qNoise_prev+11) 1989 tmpNoiseU32 = noiseU32[i]; // Q(qNoise_prev+11) 1990 } 1991 if (tmpMagnU32 > tmpNoiseU32) { 1992 tmpU32no1 = tmpMagnU32 - tmpNoiseU32; // Q(qCur) 1993 norm32no2 = WEBRTC_SPL_MIN(11, WebRtcSpl_NormU32(tmpU32no1)); 1994 tmpU32no1 <<= norm32no2; // Q(qCur+norm32no2) 1995 tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpNoiseU32, 11 - norm32no2); // Q(qCur+norm32no2-11) 1996 if (tmpU32no2 > 0) { 1997 tmpU32no1 /= tmpU32no2; // Q11 1998 } 1999 curNearSnr = WEBRTC_SPL_MIN(satMax, tmpU32no1); // Q11 2000 } 2001 2002 //directed decision update of priorSnr 2003 // FLOAT 2004 // priorSnr = DD_PR_SNR * prevNearSnr + (1.0-DD_PR_SNR) * curNearSnr; 2005 2006 tmpU32no1 = WEBRTC_SPL_UMUL_32_16(prevNearSnr[i], DD_PR_SNR_Q11); // Q22 2007 tmpU32no2 = WEBRTC_SPL_UMUL_32_16(curNearSnr, ONE_MINUS_DD_PR_SNR_Q11); // Q22 2008 priorSnr = tmpU32no1 + tmpU32no2; // Q22 2009 2010 //gain filter 2011 tmpU32no1 = (uint32_t)(inst->overdrive) 2012 + WEBRTC_SPL_RSHIFT_U32(priorSnr + 8192, 14); // Q8 2013 assert(inst->overdrive > 0); 2014 tmpU16no1 = (priorSnr + tmpU32no1 / 2) / tmpU32no1; // Q14 2015 inst->noiseSupFilter[i] = WEBRTC_SPL_SAT(16384, tmpU16no1, inst->denoiseBound); // 16384 = Q14(1.0) // Q14 2016 2017 // Weight in the parametric Wiener filter during startup 2018 if (inst->blockIndex < END_STARTUP_SHORT) { 2019 // Weight the two suppression filters 2020 tmpU32no1 = inst->noiseSupFilter[i] * inst->blockIndex; 2021 tmpU32no2 = noiseSupFilterTmp[i] * 2022 (END_STARTUP_SHORT - inst->blockIndex); 2023 tmpU32no1 += tmpU32no2; 2024 inst->noiseSupFilter[i] = (uint16_t)WebRtcSpl_DivU32U16(tmpU32no1, 2025 END_STARTUP_SHORT); 2026 } 2027 } // end of loop over frequencies 2028 //done with step3 2029 2030 // save noise and magnitude spectrum for next frame 2031 inst->prevQNoise = qNoise; 2032 inst->prevQMagn = qMagn; 2033 if (norm32no1 > 5) { 2034 for (i = 0; i < inst->magnLen; i++) { 2035 inst->prevNoiseU32[i] = noiseU32[i] << (norm32no1 - 5); // Q(qNoise+11) 2036 inst->prevMagnU16[i] = magnU16[i]; // Q(qMagn) 2037 } 2038 } else { 2039 for (i = 0; i < inst->magnLen; i++) { 2040 inst->prevNoiseU32[i] = WEBRTC_SPL_RSHIFT_U32(noiseU32[i], 5 - norm32no1); // Q(qNoise+11) 2041 inst->prevMagnU16[i] = magnU16[i]; // Q(qMagn) 2042 } 2043 } 2044 2045 WebRtcNsx_DataSynthesis(inst, outFrame); 2046 #ifdef NS_FILEDEBUG 2047 if (fwrite(outframe, sizeof(short), 2048 inst->blockLen10ms, inst->outfile) != inst->blockLen10ms) { 2049 return -1; 2050 } 2051 #endif 2052 2053 //for H band: 2054 // only update data buffer, then apply time-domain gain is applied derived from L band 2055 if (inst->fs == 32000) { 2056 // update analysis buffer for H band 2057 // append new data to buffer FX 2058 WEBRTC_SPL_MEMCPY_W16(inst->dataBufHBFX, inst->dataBufHBFX + inst->blockLen10ms, inst->anaLen - inst->blockLen10ms); 2059 WEBRTC_SPL_MEMCPY_W16(inst->dataBufHBFX + inst->anaLen - inst->blockLen10ms, speechFrameHB, inst->blockLen10ms); 2060 // range for averaging low band quantities for H band gain 2061 2062 gainTimeDomainHB = 16384; // 16384 = Q14(1.0) 2063 //average speech prob from low band 2064 //average filter gain from low band 2065 //avg over second half (i.e., 4->8kHz) of freq. spectrum 2066 tmpU32no1 = 0; // Q12 2067 tmpU16no1 = 0; // Q8 2068 for (i = inst->anaLen2 - (inst->anaLen2 >> 2); i < inst->anaLen2; i++) { 2069 tmpU16no1 += nonSpeechProbFinal[i]; // Q8 2070 tmpU32no1 += (uint32_t)(inst->noiseSupFilter[i]); // Q14 2071 } 2072 assert(inst->stages >= 7); 2073 avgProbSpeechHB = (4096 - (tmpU16no1 >> (inst->stages - 7))); // Q12 2074 avgFilterGainHB = (int16_t)WEBRTC_SPL_RSHIFT_U32( 2075 tmpU32no1, inst->stages - 3); // Q14 2076 2077 // // original FLOAT code 2078 // // gain based on speech probability: 2079 // avg_prob_speech_tt=(float)2.0*avg_prob_speech-(float)1.0; 2080 // gain_mod=(float)0.5*((float)1.0+(float)tanh(avg_prob_speech_tt)); // between 0 and 1 2081 2082 // gain based on speech probability: 2083 // original expression: "0.5 * (1 + tanh(2x-1))" 2084 // avgProbSpeechHB has been anyway saturated to a value between 0 and 1 so the other cases don't have to be dealt with 2085 // avgProbSpeechHB and gainModHB are in Q12, 3607 = Q12(0.880615234375) which is a zero point of 2086 // |0.5 * (1 + tanh(2x-1)) - x| - |0.5 * (1 + tanh(2x-1)) - 0.880615234375| meaning that from that point the error of approximating 2087 // the expression with f(x) = x would be greater than the error of approximating the expression with f(x) = 0.880615234375 2088 // error: "|0.5 * (1 + tanh(2x-1)) - x| from x=0 to 0.880615234375" -> http://www.wolframalpha.com/input/?i=|0.5+*+(1+%2B+tanh(2x-1))+-+x|+from+x%3D0+to+0.880615234375 2089 // and: "|0.5 * (1 + tanh(2x-1)) - 0.880615234375| from x=0.880615234375 to 1" -> http://www.wolframalpha.com/input/?i=+|0.5+*+(1+%2B+tanh(2x-1))+-+0.880615234375|+from+x%3D0.880615234375+to+1 2090 gainModHB = WEBRTC_SPL_MIN(avgProbSpeechHB, 3607); 2091 2092 // // original FLOAT code 2093 // //combine gain with low band gain 2094 // if (avg_prob_speech < (float)0.5) { 2095 // gain_time_domain_HB=(float)0.5*gain_mod+(float)0.5*avg_filter_gain; 2096 // } 2097 // else { 2098 // gain_time_domain_HB=(float)0.25*gain_mod+(float)0.75*avg_filter_gain; 2099 // } 2100 2101 2102 //combine gain with low band gain 2103 if (avgProbSpeechHB < 2048) { 2104 // 2048 = Q12(0.5) 2105 // the next two lines in float are "gain_time_domain = 0.5 * gain_mod + 0.5 * avg_filter_gain"; Q2(0.5) = 2 equals one left shift 2106 gainTimeDomainHB = (gainModHB << 1) + (avgFilterGainHB >> 1); // Q14 2107 } else { 2108 // "gain_time_domain = 0.25 * gain_mod + 0.75 * agv_filter_gain;" 2109 gainTimeDomainHB = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(3, avgFilterGainHB, 2); // 3 = Q2(0.75); Q14 2110 gainTimeDomainHB += gainModHB; // Q14 2111 } 2112 //make sure gain is within flooring range 2113 gainTimeDomainHB 2114 = WEBRTC_SPL_SAT(16384, gainTimeDomainHB, (int16_t)(inst->denoiseBound)); // 16384 = Q14(1.0) 2115 2116 2117 //apply gain 2118 for (i = 0; i < inst->blockLen10ms; i++) { 2119 outFrameHB[i] 2120 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(gainTimeDomainHB, inst->dataBufHBFX[i], 14); // Q0 2121 } 2122 } // end of H band gain computation 2123 2124 return 0; 2125 } 2126