blob: 98a8dae4690a6b07d26d9f5b8550f479eae90128 [file] [log] [blame]
ekm35b72fb2015-07-10 14:11:52 -07001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
ekm35b72fb2015-07-10 14:11:52 -070011#include <math.h>
12#include <stdlib.h>
kwiberg88788ad2016-02-19 07:04:49 -080013
ekm35b72fb2015-07-10 14:11:52 -070014#include <algorithm>
kwiberg88788ad2016-02-19 07:04:49 -080015#include <memory>
ekm35b72fb2015-07-10 14:11:52 -070016#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/array_view.h"
19#include "common_audio/signal_processing/include/signal_processing_library.h"
20#include "modules/audio_processing/audio_buffer.h"
21#include "modules/audio_processing/intelligibility/intelligibility_enhancer.h"
22#include "modules/audio_processing/noise_suppression_impl.h"
23#include "modules/audio_processing/test/audio_buffer_tools.h"
24#include "modules/audio_processing/test/bitexactness_tools.h"
25#include "rtc_base/arraysize.h"
26#include "test/gtest.h"
ekm35b72fb2015-07-10 14:11:52 -070027
28namespace webrtc {
29
30namespace {
31
32// Target output for ERB create test. Generated with matlab.
33const float kTestCenterFreqs[] = {
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -080034 14.5213f, 29.735f, 45.6781f, 62.3884f, 79.9058f, 98.2691f, 117.521f,
35 137.708f, 158.879f, 181.084f, 204.378f, 228.816f, 254.459f, 281.371f,
36 309.618f, 339.273f, 370.411f, 403.115f, 437.469f, 473.564f, 511.497f,
37 551.371f, 593.293f, 637.386f, 683.77f, 732.581f, 783.96f, 838.06f,
38 895.046f, 955.09f, 1018.38f, 1085.13f, 1155.54f, 1229.85f, 1308.32f,
39 1391.22f, 1478.83f, 1571.5f, 1669.55f, 1773.37f, 1883.37f, 2000.f};
40const float kTestFilterBank[][33] = {
41 {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
42 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
43 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
44 {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
45 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
46 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
47 {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
48 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
49 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
50 {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
51 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
52 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
53 {0.2f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
54 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
55 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
56 {0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
57 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
58 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
59 {0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
60 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
61 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
62 {0.f, 0.25f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
63 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
64 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
65 {0.f, 0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
66 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
67 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
68 {0.f, 0.f, 0.25f, 0.142857f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
69 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
70 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
71 {0.f, 0.f, 0.25f, 0.285714f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
72 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
73 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
74 {0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
75 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
76 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
77 {0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
78 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
79 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
80 {0.f, 0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f, 0.f, 0.f,
81 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
82 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
83 {0.f, 0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.f, 0.f, 0.f, 0.f, 0.f,
84 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
85 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
86 {0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f, 0.f,
87 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
88 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
89 {0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.f, 0.f, 0.f, 0.f,
90 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
91 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
92 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f,
93 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
94 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
95 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.157895f, 0.f, 0.f,
96 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
97 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
98 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.210526f, 0.117647f, 0.f,
99 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
100 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
101 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.315789f, 0.176471f, 0.f,
102 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
103 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
104 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.315789f, 0.352941f, 0.142857f,
105 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
106 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
107 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.352941f, 0.285714f,
108 0.157895f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
109 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
110 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f,
111 0.210526f, 0.111111f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
112 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
113 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
114 0.f, 0.285714f, 0.315789f, 0.222222f, 0.111111f, 0.f, 0.f, 0.f, 0.f,
115 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
116 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
117 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
118 0.f, 0.f, 0.315789f, 0.333333f, 0.222222f, 0.111111f, 0.f, 0.f, 0.f,
119 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
120 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
121 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
122 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f, 0.111111f, 0.f, 0.f,
123 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
124 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
125 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
126 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f, 0.111111f, 0.f,
127 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
128 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
129 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
130 0.f, 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f, 0.111111f,
131 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
132 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
133 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
134 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f,
135 0.108108f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
136 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
137 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
138 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f,
139 0.243243f, 0.153846f, 0.0833333f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
140 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
141 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
142 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.333333f,
143 0.324324f, 0.230769f, 0.166667f, 0.0909091f, 0.f, 0.f, 0.f, 0.f, 0.f,
144 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
145 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
146 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
147 0.324324f, 0.307692f, 0.25f, 0.181818f, 0.0833333f, 0.f, 0.f, 0.f, 0.f,
148 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
149 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
150 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
151 0.f, 0.f, 0.f, 0.f, 0.f, 0.307692f, 0.333333f,
152 0.363636f, 0.25f, 0.151515f, 0.0793651f, 0.f, 0.f, 0.f,
153 0.f, 0.f, 0.f, 0.f, 0.f},
154 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
155 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
156 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
157 0.f, 0.f, 0.166667f, 0.363636f, 0.333333f, 0.242424f,
158 0.190476f, 0.133333f, 0.0689655f, 0.f, 0.f, 0.f,
159 0.f, 0.f, 0.f},
160 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
161 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
162 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.30303f, 0.253968f, 0.2f, 0.137931f,
163 0.0714286f, 0.f, 0.f, 0.f, 0.f, 0.f},
164 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
165 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
166 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
167 0.f, 0.f, 0.30303f, 0.31746f, 0.333333f, 0.275862f, 0.214286f,
168 0.125f, 0.0655738f, 0.f, 0.f, 0.f},
169 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
170 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
171 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
172 0.f, 0.f, 0.f, 0.15873f, 0.333333f, 0.344828f, 0.357143f,
173 0.25f, 0.196721f, 0.137931f, 0.0816327f, 0.f},
174 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
175 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
176 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
177 0.f, 0.f, 0.f, 0.f, 0.f, 0.172414f, 0.357143f,
178 0.3125f, 0.245902f, 0.172414f, 0.102041f, 0.f},
179 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
180 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
181 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
182 0.f, 0.3125f, 0.327869f, 0.344828f, 0.204082f, 0.f},
183 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
184 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
185 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.163934f, 0.344828f, 0.408163f, 0.5f},
186 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
187 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
188 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.204082f, 0.5f}};
ekm35b72fb2015-07-10 14:11:52 -0700189static_assert(arraysize(kTestCenterFreqs) == arraysize(kTestFilterBank),
190 "Test filterbank badly initialized.");
191
192// Target output for gain solving test. Generated with matlab.
Peter Kastingdce40cf2015-08-24 14:52:23 -0700193const size_t kTestStartFreq = 12; // Lowest integral frequency for ERBs.
aluebsf99af6b2016-02-24 17:25:42 -0800194const float kTestZeroVar = 1.f;
ekm35b72fb2015-07-10 14:11:52 -0700195const float kTestNonZeroVarLambdaTop[] = {
aluebsf99af6b2016-02-24 17:25:42 -0800196 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f,
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -0800197 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
aluebsf99af6b2016-02-24 17:25:42 -0800198 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
ekm35b72fb2015-07-10 14:11:52 -0700199static_assert(arraysize(kTestCenterFreqs) ==
200 arraysize(kTestNonZeroVarLambdaTop),
Alejandro Luebs32348192016-02-17 20:04:19 -0800201 "Power test data badly initialized.");
ekm35b72fb2015-07-10 14:11:52 -0700202const float kMaxTestError = 0.005f;
203
204// Enhancer initialization parameters.
Alejandro Luebsef009252016-09-20 14:51:56 -0700205const int kSamples = 10000;
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -0800206const int kSampleRate = 4000;
ekm35b72fb2015-07-10 14:11:52 -0700207const int kNumChannels = 1;
ekmeyerson60d9b332015-08-14 10:35:55 -0700208const int kFragmentSize = kSampleRate / 100;
Alex Luebs57ae8292016-03-09 16:24:34 +0100209const size_t kNumNoiseBins = 129;
Alejandro Luebsef009252016-09-20 14:51:56 -0700210const size_t kNumBands = 1;
ekm35b72fb2015-07-10 14:11:52 -0700211
peah4b0c7412016-03-28 23:43:49 -0700212// Number of frames to process in the bitexactness tests.
213const size_t kNumFramesToProcess = 1000;
214
215int IntelligibilityEnhancerSampleRate(int sample_rate_hz) {
216 return (sample_rate_hz > AudioProcessing::kSampleRate16kHz
217 ? AudioProcessing::kSampleRate16kHz
218 : sample_rate_hz);
219}
220
221// Process one frame of data and produce the output.
222void ProcessOneFrame(int sample_rate_hz,
223 AudioBuffer* render_audio_buffer,
224 AudioBuffer* capture_audio_buffer,
225 NoiseSuppressionImpl* noise_suppressor,
226 IntelligibilityEnhancer* intelligibility_enhancer) {
227 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
228 render_audio_buffer->SplitIntoFrequencyBands();
229 capture_audio_buffer->SplitIntoFrequencyBands();
230 }
231
Alejandro Luebsef009252016-09-20 14:51:56 -0700232 intelligibility_enhancer->ProcessRenderAudio(render_audio_buffer);
peah4b0c7412016-03-28 23:43:49 -0700233
234 noise_suppressor->AnalyzeCaptureAudio(capture_audio_buffer);
235 noise_suppressor->ProcessCaptureAudio(capture_audio_buffer);
236
237 intelligibility_enhancer->SetCaptureNoiseEstimate(
aluebs11d4a422016-04-28 14:58:32 -0700238 noise_suppressor->NoiseEstimate(), 0);
peah4b0c7412016-03-28 23:43:49 -0700239
240 if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
241 render_audio_buffer->MergeFrequencyBands();
242 }
243}
244
245// Processes a specified amount of frames, verifies the results and reports
246// any errors.
247void RunBitexactnessTest(int sample_rate_hz,
248 size_t num_channels,
249 rtc::ArrayView<const float> output_reference) {
250 const StreamConfig render_config(sample_rate_hz, num_channels, false);
251 AudioBuffer render_buffer(
252 render_config.num_frames(), render_config.num_channels(),
253 render_config.num_frames(), render_config.num_channels(),
254 render_config.num_frames());
255 test::InputAudioFile render_file(
256 test::GetApmRenderTestVectorFileName(sample_rate_hz));
257 std::vector<float> render_input(render_buffer.num_frames() *
258 render_buffer.num_channels());
259
260 const StreamConfig capture_config(sample_rate_hz, num_channels, false);
261 AudioBuffer capture_buffer(
262 capture_config.num_frames(), capture_config.num_channels(),
263 capture_config.num_frames(), capture_config.num_channels(),
264 capture_config.num_frames());
265 test::InputAudioFile capture_file(
266 test::GetApmCaptureTestVectorFileName(sample_rate_hz));
267 std::vector<float> capture_input(render_buffer.num_frames() *
268 capture_buffer.num_channels());
269
270 rtc::CriticalSection crit_capture;
271 NoiseSuppressionImpl noise_suppressor(&crit_capture);
272 noise_suppressor.Initialize(capture_config.num_channels(), sample_rate_hz);
273 noise_suppressor.Enable(true);
274
275 IntelligibilityEnhancer intelligibility_enhancer(
276 IntelligibilityEnhancerSampleRate(sample_rate_hz),
Alejandro Luebsef009252016-09-20 14:51:56 -0700277 render_config.num_channels(), kNumBands,
278 NoiseSuppressionImpl::num_noise_bins());
peah4b0c7412016-03-28 23:43:49 -0700279
280 for (size_t frame_no = 0u; frame_no < kNumFramesToProcess; ++frame_no) {
281 ReadFloatSamplesFromStereoFile(render_buffer.num_frames(),
282 render_buffer.num_channels(), &render_file,
283 render_input);
284 ReadFloatSamplesFromStereoFile(capture_buffer.num_frames(),
285 capture_buffer.num_channels(), &capture_file,
286 capture_input);
287
288 test::CopyVectorToAudioBuffer(render_config, render_input, &render_buffer);
289 test::CopyVectorToAudioBuffer(capture_config, capture_input,
290 &capture_buffer);
291
292 ProcessOneFrame(sample_rate_hz, &render_buffer, &capture_buffer,
293 &noise_suppressor, &intelligibility_enhancer);
294 }
295
296 // Extract and verify the test results.
297 std::vector<float> render_output;
298 test::ExtractVectorFromAudioBuffer(render_config, &render_buffer,
299 &render_output);
300
peah7ea928e2016-03-30 08:13:57 -0700301 const float kElementErrorBound = 1.f / static_cast<float>(1 << 15);
peah4b0c7412016-03-28 23:43:49 -0700302
303 // Compare the output with the reference. Only the first values of the output
304 // from last frame processed are compared in order not having to specify all
305 // preceeding frames as testvectors. As the algorithm being tested has a
306 // memory, testing only the last frame implicitly also tests the preceeding
307 // frames.
peah7ea928e2016-03-30 08:13:57 -0700308 EXPECT_TRUE(test::VerifyDeinterleavedArray(
309 render_buffer.num_frames(), render_config.num_channels(),
310 output_reference, render_output, kElementErrorBound));
peah4b0c7412016-03-28 23:43:49 -0700311}
312
aluebs11d4a422016-04-28 14:58:32 -0700313float float_rand() {
314 return std::rand() * 2.f / RAND_MAX - 1;
315}
316
ekm35b72fb2015-07-10 14:11:52 -0700317} // namespace
318
ekm35b72fb2015-07-10 14:11:52 -0700319class IntelligibilityEnhancerTest : public ::testing::Test {
320 protected:
321 IntelligibilityEnhancerTest()
Alejandro Luebsef009252016-09-20 14:51:56 -0700322 : clear_buffer_(kFragmentSize,
323 kNumChannels,
324 kFragmentSize,
325 kNumChannels,
326 kFragmentSize),
327 stream_config_(kSampleRate, kNumChannels),
328 clear_data_(kSamples),
329 noise_data_(kNumNoiseBins),
330 orig_data_(kSamples) {
aluebs11d4a422016-04-28 14:58:32 -0700331 std::srand(1);
Alejandro Luebsef009252016-09-20 14:51:56 -0700332 enh_.reset(new IntelligibilityEnhancer(kSampleRate, kNumChannels, kNumBands,
333 kNumNoiseBins));
ekmeyerson60d9b332015-08-14 10:35:55 -0700334 }
ekm35b72fb2015-07-10 14:11:52 -0700335
Alejandro Luebs32348192016-02-17 20:04:19 -0800336 bool CheckUpdate() {
Alejandro Luebsef009252016-09-20 14:51:56 -0700337 enh_.reset(new IntelligibilityEnhancer(kSampleRate, kNumChannels, kNumBands,
338 kNumNoiseBins));
aluebs0a007592016-02-26 17:17:38 -0800339 float* clear_cursor = clear_data_.data();
ekm35b72fb2015-07-10 14:11:52 -0700340 for (int i = 0; i < kSamples; i += kFragmentSize) {
Alejandro Luebsef009252016-09-20 14:51:56 -0700341 enh_->SetCaptureNoiseEstimate(noise_data_, 1);
342 clear_buffer_.CopyFrom(&clear_cursor, stream_config_);
343 enh_->ProcessRenderAudio(&clear_buffer_);
344 clear_buffer_.CopyTo(stream_config_, &clear_cursor);
ekm35b72fb2015-07-10 14:11:52 -0700345 clear_cursor += kFragmentSize;
ekm35b72fb2015-07-10 14:11:52 -0700346 }
Alejandro Luebsef009252016-09-20 14:51:56 -0700347 for (int i = initial_delay_; i < kSamples; i++) {
348 if (std::fabs(clear_data_[i] - orig_data_[i - initial_delay_]) >
349 kMaxTestError) {
ekm35b72fb2015-07-10 14:11:52 -0700350 return true;
351 }
352 }
353 return false;
354 }
355
kwiberg88788ad2016-02-19 07:04:49 -0800356 std::unique_ptr<IntelligibilityEnhancer> enh_;
Alejandro Luebsef009252016-09-20 14:51:56 -0700357 // Render clean speech buffer.
358 AudioBuffer clear_buffer_;
359 StreamConfig stream_config_;
Alejandro Luebs32348192016-02-17 20:04:19 -0800360 std::vector<float> clear_data_;
361 std::vector<float> noise_data_;
362 std::vector<float> orig_data_;
Alejandro Luebsef009252016-09-20 14:51:56 -0700363 size_t initial_delay_;
ekm35b72fb2015-07-10 14:11:52 -0700364};
365
Alejandro Luebs32348192016-02-17 20:04:19 -0800366// For each class of generated data, tests that render stream is updated when
367// it should be.
ekm35b72fb2015-07-10 14:11:52 -0700368TEST_F(IntelligibilityEnhancerTest, TestRenderUpdate) {
Alejandro Luebsef009252016-09-20 14:51:56 -0700369 initial_delay_ = enh_->render_mangler_->initial_delay();
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -0800370 std::fill(noise_data_.begin(), noise_data_.end(), 0.f);
371 std::fill(orig_data_.begin(), orig_data_.end(), 0.f);
372 std::fill(clear_data_.begin(), clear_data_.end(), 0.f);
Alejandro Luebs32348192016-02-17 20:04:19 -0800373 EXPECT_FALSE(CheckUpdate());
Alejandro Luebsef009252016-09-20 14:51:56 -0700374 std::generate(clear_data_.begin(), clear_data_.end(), float_rand);
375 orig_data_ = clear_data_;
Alejandro Luebs32348192016-02-17 20:04:19 -0800376 EXPECT_FALSE(CheckUpdate());
377 std::generate(clear_data_.begin(), clear_data_.end(), float_rand);
378 orig_data_ = clear_data_;
Alejandro Luebsef009252016-09-20 14:51:56 -0700379 std::generate(noise_data_.begin(), noise_data_.end(), float_rand);
380 FloatToFloatS16(noise_data_.data(), noise_data_.size(), noise_data_.data());
Alejandro Luebs32348192016-02-17 20:04:19 -0800381 EXPECT_TRUE(CheckUpdate());
ekm35b72fb2015-07-10 14:11:52 -0700382}
383
384// Tests ERB bank creation, comparing against matlab output.
385TEST_F(IntelligibilityEnhancerTest, TestErbCreation) {
Peter Kastingdce40cf2015-08-24 14:52:23 -0700386 ASSERT_EQ(arraysize(kTestCenterFreqs), enh_->bank_size_);
387 for (size_t i = 0; i < enh_->bank_size_; ++i) {
ekmeyerson60d9b332015-08-14 10:35:55 -0700388 EXPECT_NEAR(kTestCenterFreqs[i], enh_->center_freqs_[i], kMaxTestError);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700389 ASSERT_EQ(arraysize(kTestFilterBank[0]), enh_->freqs_);
390 for (size_t j = 0; j < enh_->freqs_; ++j) {
aluebsc466bad2016-02-10 12:03:00 -0800391 EXPECT_NEAR(kTestFilterBank[i][j], enh_->render_filter_bank_[i][j],
ekm35b72fb2015-07-10 14:11:52 -0700392 kMaxTestError);
393 }
394 }
395}
396
397// Tests analytic solution for optimal gains, comparing
398// against matlab output.
399TEST_F(IntelligibilityEnhancerTest, TestSolveForGains) {
ekmeyerson60d9b332015-08-14 10:35:55 -0700400 ASSERT_EQ(kTestStartFreq, enh_->start_freq_);
Alejandro Luebs32348192016-02-17 20:04:19 -0800401 std::vector<float> sols(enh_->bank_size_);
ekm35b72fb2015-07-10 14:11:52 -0700402 float lambda = -0.001f;
Peter Kastingdce40cf2015-08-24 14:52:23 -0700403 for (size_t i = 0; i < enh_->bank_size_; i++) {
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -0800404 enh_->filtered_clear_pow_[i] = 0.f;
405 enh_->filtered_noise_pow_[i] = 0.f;
ekm35b72fb2015-07-10 14:11:52 -0700406 }
aluebs0a007592016-02-26 17:17:38 -0800407 enh_->SolveForGainsGivenLambda(lambda, enh_->start_freq_, sols.data());
Peter Kastingdce40cf2015-08-24 14:52:23 -0700408 for (size_t i = 0; i < enh_->bank_size_; i++) {
aluebsf99af6b2016-02-24 17:25:42 -0800409 EXPECT_NEAR(kTestZeroVar, sols[i], kMaxTestError);
ekm35b72fb2015-07-10 14:11:52 -0700410 }
Peter Kastingdce40cf2015-08-24 14:52:23 -0700411 for (size_t i = 0; i < enh_->bank_size_; i++) {
Alejandro Luebs32348192016-02-17 20:04:19 -0800412 enh_->filtered_clear_pow_[i] = static_cast<float>(i + 1);
413 enh_->filtered_noise_pow_[i] = static_cast<float>(enh_->bank_size_ - i);
ekm35b72fb2015-07-10 14:11:52 -0700414 }
aluebs0a007592016-02-26 17:17:38 -0800415 enh_->SolveForGainsGivenLambda(lambda, enh_->start_freq_, sols.data());
Peter Kastingdce40cf2015-08-24 14:52:23 -0700416 for (size_t i = 0; i < enh_->bank_size_; i++) {
ekm35b72fb2015-07-10 14:11:52 -0700417 EXPECT_NEAR(kTestNonZeroVarLambdaTop[i], sols[i], kMaxTestError);
418 }
Alejandro Luebs18fcbcf2016-02-22 15:57:38 -0800419 lambda = -1.f;
aluebs0a007592016-02-26 17:17:38 -0800420 enh_->SolveForGainsGivenLambda(lambda, enh_->start_freq_, sols.data());
Peter Kastingdce40cf2015-08-24 14:52:23 -0700421 for (size_t i = 0; i < enh_->bank_size_; i++) {
aluebsf99af6b2016-02-24 17:25:42 -0800422 EXPECT_NEAR(kTestNonZeroVarLambdaTop[i], sols[i], kMaxTestError);
ekm35b72fb2015-07-10 14:11:52 -0700423 }
424}
425
aluebs11d4a422016-04-28 14:58:32 -0700426TEST_F(IntelligibilityEnhancerTest, TestNoiseGainHasExpectedResult) {
Alejandro Luebs50411102016-06-30 15:35:41 -0700427 const float kGain = 2.f;
aluebs7bd5f252016-06-21 11:30:25 -0700428 const float kTolerance = 0.007f;
aluebs11d4a422016-04-28 14:58:32 -0700429 std::vector<float> noise(kNumNoiseBins);
430 std::vector<float> noise_psd(kNumNoiseBins);
431 std::generate(noise.begin(), noise.end(), float_rand);
432 for (size_t i = 0; i < kNumNoiseBins; ++i) {
Alejandro Luebs50411102016-06-30 15:35:41 -0700433 noise_psd[i] = kGain * kGain * noise[i] * noise[i];
aluebs11d4a422016-04-28 14:58:32 -0700434 }
435 float* clear_cursor = clear_data_.data();
436 for (size_t i = 0; i < kNumFramesToProcess; ++i) {
Alejandro Luebs50411102016-06-30 15:35:41 -0700437 enh_->SetCaptureNoiseEstimate(noise, kGain);
Alejandro Luebsef009252016-09-20 14:51:56 -0700438 clear_buffer_.CopyFrom(&clear_cursor, stream_config_);
439 enh_->ProcessRenderAudio(&clear_buffer_);
aluebs11d4a422016-04-28 14:58:32 -0700440 }
441 const std::vector<float>& estimated_psd =
442 enh_->noise_power_estimator_.power();
443 for (size_t i = 0; i < kNumNoiseBins; ++i) {
444 EXPECT_LT(std::abs(estimated_psd[i] - noise_psd[i]) / noise_psd[i],
445 kTolerance);
446 }
447}
448
Alejandro Luebsef009252016-09-20 14:51:56 -0700449TEST_F(IntelligibilityEnhancerTest, TestAllBandsHaveSameDelay) {
450 const int kTestSampleRate = AudioProcessing::kSampleRate32kHz;
451 const int kTestSplitRate = AudioProcessing::kSampleRate16kHz;
452 const size_t kTestNumBands =
453 rtc::CheckedDivExact(kTestSampleRate, kTestSplitRate);
454 const size_t kTestFragmentSize = rtc::CheckedDivExact(kTestSampleRate, 100);
455 const size_t kTestSplitFragmentSize =
456 rtc::CheckedDivExact(kTestSplitRate, 100);
457 enh_.reset(new IntelligibilityEnhancer(kTestSplitRate, kNumChannels,
458 kTestNumBands, kNumNoiseBins));
459 size_t initial_delay = enh_->render_mangler_->initial_delay();
460 std::vector<float> rand_gen_buf(kTestFragmentSize);
461 AudioBuffer original_buffer(kTestFragmentSize, kNumChannels,
462 kTestFragmentSize, kNumChannels,
463 kTestFragmentSize);
464 AudioBuffer audio_buffer(kTestFragmentSize, kNumChannels, kTestFragmentSize,
465 kNumChannels, kTestFragmentSize);
466 for (size_t i = 0u; i < kTestNumBands; ++i) {
467 std::generate(rand_gen_buf.begin(), rand_gen_buf.end(), float_rand);
468 original_buffer.split_data_f()->SetDataForTesting(rand_gen_buf.data(),
469 rand_gen_buf.size());
470 audio_buffer.split_data_f()->SetDataForTesting(rand_gen_buf.data(),
471 rand_gen_buf.size());
472 }
473 enh_->ProcessRenderAudio(&audio_buffer);
474 for (size_t i = 0u; i < kTestNumBands; ++i) {
475 const float* original_ptr = original_buffer.split_bands_const_f(0)[i];
476 const float* audio_ptr = audio_buffer.split_bands_const_f(0)[i];
477 for (size_t j = initial_delay; j < kTestSplitFragmentSize; ++j) {
478 EXPECT_LT(std::fabs(original_ptr[j - initial_delay] - audio_ptr[j]),
479 kMaxTestError);
480 }
481 }
482}
483
peah4b0c7412016-03-28 23:43:49 -0700484TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono8kHz) {
485 const float kOutputReference[] = {-0.001892f, -0.003296f, -0.001953f};
486
487 RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 1, kOutputReference);
488}
489
490TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono16kHz) {
491 const float kOutputReference[] = {-0.000977f, -0.003296f, -0.002441f};
492
493 RunBitexactnessTest(AudioProcessing::kSampleRate16kHz, 1, kOutputReference);
494}
495
496TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono32kHz) {
497 const float kOutputReference[] = {0.003021f, -0.011780f, -0.008209f};
498
499 RunBitexactnessTest(AudioProcessing::kSampleRate32kHz, 1, kOutputReference);
500}
501
502TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono48kHz) {
503 const float kOutputReference[] = {-0.027696f, -0.026253f, -0.018001f};
504
505 RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 1, kOutputReference);
506}
507
508TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo8kHz) {
509 const float kOutputReference[] = {0.021454f, 0.035919f, 0.026428f,
510 -0.000641f, 0.000366f, 0.000641f};
511
512 RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 2, kOutputReference);
513}
514
515TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo16kHz) {
516 const float kOutputReference[] = {0.021362f, 0.035736f, 0.023895f,
517 -0.001404f, -0.001465f, 0.000549f};
518
519 RunBitexactnessTest(AudioProcessing::kSampleRate16kHz, 2, kOutputReference);
520}
521
522TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo32kHz) {
523 const float kOutputReference[] = {0.030641f, 0.027406f, 0.028321f,
524 -0.001343f, -0.004578f, 0.000977f};
525
526 RunBitexactnessTest(AudioProcessing::kSampleRate32kHz, 2, kOutputReference);
527}
528
529TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo48kHz) {
530 const float kOutputReference[] = {-0.009276f, -0.001601f, -0.008255f,
531 -0.012975f, -0.015940f, -0.017820f};
532
533 RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 2, kOutputReference);
534}
535
ekm35b72fb2015-07-10 14:11:52 -0700536} // namespace webrtc