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