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