OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 29 matching lines...) Loading... | |
40 const float kLambdaTop = -10e-18f; // search for lamda. | 40 const float kLambdaTop = -10e-18f; // search for lamda. |
41 | 41 |
42 } // namespace | 42 } // namespace |
43 | 43 |
44 using std::complex; | 44 using std::complex; |
45 using std::max; | 45 using std::max; |
46 using std::min; | 46 using std::min; |
47 using VarianceType = intelligibility::VarianceArray::StepType; | 47 using VarianceType = intelligibility::VarianceArray::StepType; |
48 | 48 |
49 IntelligibilityEnhancer::TransformCallback::TransformCallback( | 49 IntelligibilityEnhancer::TransformCallback::TransformCallback( |
50 IntelligibilityEnhancer* parent, | 50 IntelligibilityEnhancer* parent) |
51 IntelligibilityEnhancer::AudioSource source) | 51 : parent_(parent) { |
52 : parent_(parent), source_(source) { | |
53 } | 52 } |
54 | 53 |
55 void IntelligibilityEnhancer::TransformCallback::ProcessAudioBlock( | 54 void IntelligibilityEnhancer::TransformCallback::ProcessAudioBlock( |
56 const complex<float>* const* in_block, | 55 const complex<float>* const* in_block, |
57 size_t in_channels, | 56 size_t in_channels, |
58 size_t frames, | 57 size_t frames, |
59 size_t /* out_channels */, | 58 size_t /* out_channels */, |
60 complex<float>* const* out_block) { | 59 complex<float>* const* out_block) { |
61 RTC_DCHECK_EQ(parent_->freqs_, frames); | 60 RTC_DCHECK_EQ(parent_->freqs_, frames); |
62 for (size_t i = 0; i < in_channels; ++i) { | 61 for (size_t i = 0; i < in_channels; ++i) { |
63 parent_->DispatchAudio(source_, in_block[i], out_block[i]); | 62 parent_->ProcessClearBlock(in_block[i], out_block[i]); |
64 } | 63 } |
65 } | 64 } |
66 | 65 |
67 IntelligibilityEnhancer::IntelligibilityEnhancer() | 66 IntelligibilityEnhancer::IntelligibilityEnhancer() |
68 : IntelligibilityEnhancer(IntelligibilityEnhancer::Config()) { | 67 : IntelligibilityEnhancer(IntelligibilityEnhancer::Config()) { |
69 } | 68 } |
70 | 69 |
71 IntelligibilityEnhancer::IntelligibilityEnhancer(const Config& config) | 70 IntelligibilityEnhancer::IntelligibilityEnhancer(const Config& config) |
72 : freqs_(RealFourier::ComplexLength( | 71 : freqs_(RealFourier::ComplexLength( |
73 RealFourier::FftOrder(config.sample_rate_hz * kWindowSizeMs / 1000))), | 72 RealFourier::FftOrder(config.sample_rate_hz * kWindowSizeMs / 1000))), |
74 window_size_(static_cast<size_t>(1 << RealFourier::FftOrder(freqs_))), | 73 window_size_(static_cast<size_t>(1 << RealFourier::FftOrder(freqs_))), |
75 chunk_length_( | 74 chunk_length_( |
76 static_cast<size_t>(config.sample_rate_hz * kChunkSizeMs / 1000)), | 75 static_cast<size_t>(config.sample_rate_hz * kChunkSizeMs / 1000)), |
77 bank_size_(GetBankSize(config.sample_rate_hz, kErbResolution)), | 76 bank_size_(GetBankSize(config.sample_rate_hz, kErbResolution)), |
78 sample_rate_hz_(config.sample_rate_hz), | 77 sample_rate_hz_(config.sample_rate_hz), |
79 erb_resolution_(kErbResolution), | 78 erb_resolution_(kErbResolution), |
80 num_capture_channels_(config.num_capture_channels), | 79 num_capture_channels_(config.num_capture_channels), |
81 num_render_channels_(config.num_render_channels), | 80 num_render_channels_(config.num_render_channels), |
82 analysis_rate_(config.analysis_rate), | 81 analysis_rate_(config.analysis_rate), |
83 active_(true), | 82 active_(true), |
84 clear_variance_(freqs_, | 83 clear_variance_(freqs_, |
85 config.var_type, | 84 config.var_type, |
86 config.var_window_size, | 85 config.var_window_size, |
87 config.var_decay_rate), | 86 config.var_decay_rate), |
88 noise_variance_(freqs_, | |
89 config.var_type, | |
90 config.var_window_size, | |
91 config.var_decay_rate), | |
92 filtered_clear_var_(new float[bank_size_]), | 87 filtered_clear_var_(new float[bank_size_]), |
93 filtered_noise_var_(new float[bank_size_]), | 88 filtered_noise_var_(new float[bank_size_]), |
94 filter_bank_(bank_size_), | |
95 center_freqs_(new float[bank_size_]), | 89 center_freqs_(new float[bank_size_]), |
90 render_filter_bank_(CreateErbBank(freqs_)), | |
96 rho_(new float[bank_size_]), | 91 rho_(new float[bank_size_]), |
97 gains_eq_(new float[bank_size_]), | 92 gains_eq_(new float[bank_size_]), |
98 gain_applier_(freqs_, config.gain_change_limit), | 93 gain_applier_(freqs_, config.gain_change_limit), |
99 temp_render_out_buffer_(chunk_length_, num_render_channels_), | 94 temp_render_out_buffer_(chunk_length_, num_render_channels_), |
100 temp_capture_out_buffer_(chunk_length_, num_capture_channels_), | |
101 kbd_window_(new float[window_size_]), | 95 kbd_window_(new float[window_size_]), |
102 render_callback_(this, AudioSource::kRenderStream), | 96 render_callback_(this), |
103 capture_callback_(this, AudioSource::kCaptureStream), | |
104 block_count_(0), | 97 block_count_(0), |
105 analysis_step_(0) { | 98 analysis_step_(0) { |
106 RTC_DCHECK_LE(config.rho, 1.0f); | 99 RTC_DCHECK_LE(config.rho, 1.0f); |
107 | 100 |
108 CreateErbBank(); | 101 memset(filtered_clear_var_.get(), |
102 0, | |
103 bank_size_ * sizeof(filtered_clear_var_[0])); | |
104 memset(filtered_noise_var_.get(), | |
105 0, | |
106 bank_size_ * sizeof(filtered_noise_var_[0])); | |
109 | 107 |
110 // Assumes all rho equal. | 108 // Assumes all rho equal. |
111 for (size_t i = 0; i < bank_size_; ++i) { | 109 for (size_t i = 0; i < bank_size_; ++i) { |
112 rho_[i] = config.rho * config.rho; | 110 rho_[i] = config.rho * config.rho; |
113 } | 111 } |
114 | 112 |
115 float freqs_khz = kClipFreq / 1000.0f; | 113 float freqs_khz = kClipFreq / 1000.0f; |
116 size_t erb_index = static_cast<size_t>(ceilf( | 114 size_t erb_index = static_cast<size_t>(ceilf( |
117 11.17f * logf((freqs_khz + 0.312f) / (freqs_khz + 14.6575f)) + 43.0f)); | 115 11.17f * logf((freqs_khz + 0.312f) / (freqs_khz + 14.6575f)) + 43.0f)); |
118 start_freq_ = std::max(static_cast<size_t>(1), erb_index * erb_resolution_); | 116 start_freq_ = std::max(static_cast<size_t>(1), erb_index * erb_resolution_); |
119 | 117 |
120 WindowGenerator::KaiserBesselDerived(kKbdAlpha, window_size_, | 118 WindowGenerator::KaiserBesselDerived(kKbdAlpha, window_size_, |
121 kbd_window_.get()); | 119 kbd_window_.get()); |
122 render_mangler_.reset(new LappedTransform( | 120 render_mangler_.reset(new LappedTransform( |
123 num_render_channels_, num_render_channels_, chunk_length_, | 121 num_render_channels_, num_render_channels_, chunk_length_, |
124 kbd_window_.get(), window_size_, window_size_ / 2, &render_callback_)); | 122 kbd_window_.get(), window_size_, window_size_ / 2, &render_callback_)); |
125 capture_mangler_.reset(new LappedTransform( | 123 } |
126 num_capture_channels_, num_capture_channels_, chunk_length_, | 124 |
127 kbd_window_.get(), window_size_, window_size_ / 2, &capture_callback_)); | 125 void IntelligibilityEnhancer::SetCaptureNoiseEstimate( |
126 const std::vector<float>& noise) { | |
127 if (capture_filter_bank_.size() != bank_size_ || | |
hlundin-webrtc
2016/02/08 10:29:28
What kind of events lead up to capture_filter_bank
aluebs-webrtc
2016/02/09 00:19:15
Because the input length of the noise vector is no
| |
128 capture_filter_bank_[0].size() != noise.size()) { | |
129 capture_filter_bank_ = CreateErbBank(noise.size()); | |
130 } | |
131 if (noise_power_.size() != noise.size()) { | |
132 noise_power_.resize(noise.size()); | |
133 } | |
134 for (size_t i = 0; i < noise.size(); ++i) { | |
135 noise_power_[i] = noise[i] * noise[i]; | |
136 } | |
137 FilterVariance(&noise_power_[0], | |
138 capture_filter_bank_, | |
139 filtered_noise_var_.get()); | |
128 } | 140 } |
129 | 141 |
130 void IntelligibilityEnhancer::ProcessRenderAudio(float* const* audio, | 142 void IntelligibilityEnhancer::ProcessRenderAudio(float* const* audio, |
131 int sample_rate_hz, | 143 int sample_rate_hz, |
132 size_t num_channels) { | 144 size_t num_channels) { |
133 RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz); | 145 RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz); |
134 RTC_CHECK_EQ(num_render_channels_, num_channels); | 146 RTC_CHECK_EQ(num_render_channels_, num_channels); |
135 | 147 |
136 if (active_) { | 148 if (active_) { |
137 render_mangler_->ProcessChunk(audio, temp_render_out_buffer_.channels()); | 149 render_mangler_->ProcessChunk(audio, temp_render_out_buffer_.channels()); |
138 } | 150 } |
139 | 151 |
140 if (active_) { | 152 if (active_) { |
141 for (size_t i = 0; i < num_render_channels_; ++i) { | 153 for (size_t i = 0; i < num_render_channels_; ++i) { |
142 memcpy(audio[i], temp_render_out_buffer_.channels()[i], | 154 memcpy(audio[i], temp_render_out_buffer_.channels()[i], |
143 chunk_length_ * sizeof(**audio)); | 155 chunk_length_ * sizeof(**audio)); |
144 } | 156 } |
145 } | 157 } |
146 } | 158 } |
147 | 159 |
148 void IntelligibilityEnhancer::AnalyzeCaptureAudio(float* const* audio, | |
149 int sample_rate_hz, | |
150 size_t num_channels) { | |
151 RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz); | |
152 RTC_CHECK_EQ(num_capture_channels_, num_channels); | |
153 | |
154 capture_mangler_->ProcessChunk(audio, temp_capture_out_buffer_.channels()); | |
155 } | |
156 | |
157 void IntelligibilityEnhancer::DispatchAudio( | |
158 IntelligibilityEnhancer::AudioSource source, | |
159 const complex<float>* in_block, | |
160 complex<float>* out_block) { | |
161 switch (source) { | |
162 case kRenderStream: | |
163 ProcessClearBlock(in_block, out_block); | |
164 break; | |
165 case kCaptureStream: | |
166 ProcessNoiseBlock(in_block, out_block); | |
167 break; | |
168 } | |
169 } | |
170 | |
171 void IntelligibilityEnhancer::ProcessClearBlock(const complex<float>* in_block, | 160 void IntelligibilityEnhancer::ProcessClearBlock(const complex<float>* in_block, |
172 complex<float>* out_block) { | 161 complex<float>* out_block) { |
173 if (block_count_ < 2) { | 162 if (block_count_ < 2) { |
174 memset(out_block, 0, freqs_ * sizeof(*out_block)); | 163 memset(out_block, 0, freqs_ * sizeof(*out_block)); |
175 ++block_count_; | 164 ++block_count_; |
176 return; | 165 return; |
177 } | 166 } |
178 | 167 |
179 // TODO(ekm): Use VAD to |Step| and |AnalyzeClearBlock| only if necessary. | 168 // TODO(ekm): Use VAD to |Step| and |AnalyzeClearBlock| only if necessary. |
180 if (true) { | 169 if (true) { |
181 clear_variance_.Step(in_block, false); | 170 clear_variance_.Step(in_block, false); |
182 if (block_count_ % analysis_rate_ == analysis_rate_ - 1) { | 171 if (block_count_ % analysis_rate_ == analysis_rate_ - 1) { |
183 const float power_target = std::accumulate( | 172 const float power_target = std::accumulate( |
184 clear_variance_.variance(), clear_variance_.variance() + freqs_, 0.f); | 173 clear_variance_.variance(), clear_variance_.variance() + freqs_, 0.f); |
185 AnalyzeClearBlock(power_target); | 174 AnalyzeClearBlock(power_target); |
186 ++analysis_step_; | 175 ++analysis_step_; |
187 } | 176 } |
188 ++block_count_; | 177 ++block_count_; |
189 } | 178 } |
190 | 179 |
191 if (active_) { | 180 if (active_) { |
192 gain_applier_.Apply(in_block, out_block); | 181 gain_applier_.Apply(in_block, out_block); |
193 } | 182 } |
194 } | 183 } |
195 | 184 |
196 void IntelligibilityEnhancer::AnalyzeClearBlock(float power_target) { | 185 void IntelligibilityEnhancer::AnalyzeClearBlock(float power_target) { |
197 FilterVariance(clear_variance_.variance(), filtered_clear_var_.get()); | 186 FilterVariance(clear_variance_.variance(), |
198 FilterVariance(noise_variance_.variance(), filtered_noise_var_.get()); | 187 render_filter_bank_, |
199 | 188 filtered_clear_var_.get()); |
200 SolveForGainsGivenLambda(kLambdaTop, start_freq_, gains_eq_.get()); | 189 SolveForGainsGivenLambda(kLambdaTop, start_freq_, gains_eq_.get()); |
201 const float power_top = | 190 const float power_top = |
202 DotProduct(gains_eq_.get(), filtered_clear_var_.get(), bank_size_); | 191 DotProduct(gains_eq_.get(), filtered_clear_var_.get(), bank_size_); |
203 SolveForGainsGivenLambda(kLambdaBot, start_freq_, gains_eq_.get()); | 192 SolveForGainsGivenLambda(kLambdaBot, start_freq_, gains_eq_.get()); |
204 const float power_bot = | 193 const float power_bot = |
205 DotProduct(gains_eq_.get(), filtered_clear_var_.get(), bank_size_); | 194 DotProduct(gains_eq_.get(), filtered_clear_var_.get(), bank_size_); |
206 if (power_target >= power_bot && power_target <= power_top) { | 195 if (power_target >= power_bot && power_target <= power_top) { |
207 SolveForLambda(power_target, power_bot, power_top); | 196 SolveForLambda(power_target, power_bot, power_top); |
208 UpdateErbGains(); | 197 UpdateErbGains(); |
209 } // Else experiencing variance underflow, so do nothing. | 198 } // Else experiencing variance underflow, so do nothing. |
(...skipping 25 matching lines...) Loading... | |
235 ++iters; | 224 ++iters; |
236 } | 225 } |
237 } | 226 } |
238 | 227 |
239 void IntelligibilityEnhancer::UpdateErbGains() { | 228 void IntelligibilityEnhancer::UpdateErbGains() { |
240 // (ERB gain) = filterbank' * (freq gain) | 229 // (ERB gain) = filterbank' * (freq gain) |
241 float* gains = gain_applier_.target(); | 230 float* gains = gain_applier_.target(); |
242 for (size_t i = 0; i < freqs_; ++i) { | 231 for (size_t i = 0; i < freqs_; ++i) { |
243 gains[i] = 0.0f; | 232 gains[i] = 0.0f; |
244 for (size_t j = 0; j < bank_size_; ++j) { | 233 for (size_t j = 0; j < bank_size_; ++j) { |
245 gains[i] = fmaf(filter_bank_[j][i], gains_eq_[j], gains[i]); | 234 gains[i] = fmaf(render_filter_bank_[j][i], gains_eq_[j], gains[i]); |
246 } | 235 } |
247 } | 236 } |
248 } | 237 } |
249 | 238 |
250 void IntelligibilityEnhancer::ProcessNoiseBlock(const complex<float>* in_block, | |
251 complex<float>* /*out_block*/) { | |
252 noise_variance_.Step(in_block); | |
253 } | |
254 | |
255 size_t IntelligibilityEnhancer::GetBankSize(int sample_rate, | 239 size_t IntelligibilityEnhancer::GetBankSize(int sample_rate, |
256 size_t erb_resolution) { | 240 size_t erb_resolution) { |
257 float freq_limit = sample_rate / 2000.0f; | 241 float freq_limit = sample_rate / 2000.0f; |
258 size_t erb_scale = static_cast<size_t>(ceilf( | 242 size_t erb_scale = static_cast<size_t>(ceilf( |
259 11.17f * logf((freq_limit + 0.312f) / (freq_limit + 14.6575f)) + 43.0f)); | 243 11.17f * logf((freq_limit + 0.312f) / (freq_limit + 14.6575f)) + 43.0f)); |
260 return erb_scale * erb_resolution; | 244 return erb_scale * erb_resolution; |
261 } | 245 } |
262 | 246 |
263 void IntelligibilityEnhancer::CreateErbBank() { | 247 std::vector<std::vector<float>> IntelligibilityEnhancer::CreateErbBank( |
248 size_t num_freqs) { | |
249 std::vector<std::vector<float>> filter_bank(bank_size_); | |
264 size_t lf = 1, rf = 4; | 250 size_t lf = 1, rf = 4; |
265 | 251 |
266 for (size_t i = 0; i < bank_size_; ++i) { | 252 for (size_t i = 0; i < bank_size_; ++i) { |
267 float abs_temp = fabsf((i + 1.0f) / static_cast<float>(erb_resolution_)); | 253 float abs_temp = fabsf((i + 1.0f) / static_cast<float>(erb_resolution_)); |
268 center_freqs_[i] = 676170.4f / (47.06538f - expf(0.08950404f * abs_temp)); | 254 center_freqs_[i] = 676170.4f / (47.06538f - expf(0.08950404f * abs_temp)); |
269 center_freqs_[i] -= 14678.49f; | 255 center_freqs_[i] -= 14678.49f; |
270 } | 256 } |
271 float last_center_freq = center_freqs_[bank_size_ - 1]; | 257 float last_center_freq = center_freqs_[bank_size_ - 1]; |
272 for (size_t i = 0; i < bank_size_; ++i) { | 258 for (size_t i = 0; i < bank_size_; ++i) { |
273 center_freqs_[i] *= 0.5f * sample_rate_hz_ / last_center_freq; | 259 center_freqs_[i] *= 0.5f * sample_rate_hz_ / last_center_freq; |
274 } | 260 } |
275 | 261 |
276 for (size_t i = 0; i < bank_size_; ++i) { | 262 for (size_t i = 0; i < bank_size_; ++i) { |
277 filter_bank_[i].resize(freqs_); | 263 filter_bank[i].resize(num_freqs); |
278 } | 264 } |
279 | 265 |
280 for (size_t i = 1; i <= bank_size_; ++i) { | 266 for (size_t i = 1; i <= bank_size_; ++i) { |
281 size_t lll, ll, rr, rrr; | 267 size_t lll, ll, rr, rrr; |
282 static const size_t kOne = 1; // Avoids repeated static_cast<>s below. | 268 static const size_t kOne = 1; // Avoids repeated static_cast<>s below. |
283 lll = static_cast<size_t>(round( | 269 lll = static_cast<size_t>(round( |
284 center_freqs_[max(kOne, i - lf) - 1] * freqs_ / | 270 center_freqs_[max(kOne, i - lf) - 1] * num_freqs / |
285 (0.5f * sample_rate_hz_))); | 271 (0.5f * sample_rate_hz_))); |
286 ll = static_cast<size_t>(round( | 272 ll = static_cast<size_t>(round( |
287 center_freqs_[max(kOne, i) - 1] * freqs_ / (0.5f * sample_rate_hz_))); | 273 center_freqs_[max(kOne, i) - 1] * num_freqs / |
288 lll = min(freqs_, max(lll, kOne)) - 1; | 274 (0.5f * sample_rate_hz_))); |
289 ll = min(freqs_, max(ll, kOne)) - 1; | 275 lll = min(num_freqs, max(lll, kOne)) - 1; |
276 ll = min(num_freqs, max(ll, kOne)) - 1; | |
290 | 277 |
291 rrr = static_cast<size_t>(round( | 278 rrr = static_cast<size_t>(round( |
292 center_freqs_[min(bank_size_, i + rf) - 1] * freqs_ / | 279 center_freqs_[min(bank_size_, i + rf) - 1] * num_freqs / |
293 (0.5f * sample_rate_hz_))); | 280 (0.5f * sample_rate_hz_))); |
294 rr = static_cast<size_t>(round( | 281 rr = static_cast<size_t>(round( |
295 center_freqs_[min(bank_size_, i + 1) - 1] * freqs_ / | 282 center_freqs_[min(bank_size_, i + 1) - 1] * num_freqs / |
296 (0.5f * sample_rate_hz_))); | 283 (0.5f * sample_rate_hz_))); |
297 rrr = min(freqs_, max(rrr, kOne)) - 1; | 284 rrr = min(num_freqs, max(rrr, kOne)) - 1; |
298 rr = min(freqs_, max(rr, kOne)) - 1; | 285 rr = min(num_freqs, max(rr, kOne)) - 1; |
299 | 286 |
300 float step, element; | 287 float step, element; |
301 | 288 |
302 step = 1.0f / (ll - lll); | 289 step = 1.0f / (ll - lll); |
303 element = 0.0f; | 290 element = 0.0f; |
304 for (size_t j = lll; j <= ll; ++j) { | 291 for (size_t j = lll; j <= ll; ++j) { |
305 filter_bank_[i - 1][j] = element; | 292 filter_bank[i - 1][j] = element; |
306 element += step; | 293 element += step; |
307 } | 294 } |
308 step = 1.0f / (rrr - rr); | 295 step = 1.0f / (rrr - rr); |
309 element = 1.0f; | 296 element = 1.0f; |
310 for (size_t j = rr; j <= rrr; ++j) { | 297 for (size_t j = rr; j <= rrr; ++j) { |
311 filter_bank_[i - 1][j] = element; | 298 filter_bank[i - 1][j] = element; |
312 element -= step; | 299 element -= step; |
313 } | 300 } |
314 for (size_t j = ll; j <= rr; ++j) { | 301 for (size_t j = ll; j <= rr; ++j) { |
315 filter_bank_[i - 1][j] = 1.0f; | 302 filter_bank[i - 1][j] = 1.0f; |
316 } | 303 } |
317 } | 304 } |
318 | 305 |
319 float sum; | 306 float sum; |
320 for (size_t i = 0; i < freqs_; ++i) { | 307 for (size_t i = 0; i < num_freqs; ++i) { |
321 sum = 0.0f; | 308 sum = 0.0f; |
322 for (size_t j = 0; j < bank_size_; ++j) { | 309 for (size_t j = 0; j < bank_size_; ++j) { |
323 sum += filter_bank_[j][i]; | 310 sum += filter_bank[j][i]; |
324 } | 311 } |
325 for (size_t j = 0; j < bank_size_; ++j) { | 312 for (size_t j = 0; j < bank_size_; ++j) { |
326 filter_bank_[j][i] /= sum; | 313 filter_bank[j][i] /= sum; |
327 } | 314 } |
328 } | 315 } |
316 return filter_bank; | |
329 } | 317 } |
330 | 318 |
331 void IntelligibilityEnhancer::SolveForGainsGivenLambda(float lambda, | 319 void IntelligibilityEnhancer::SolveForGainsGivenLambda(float lambda, |
332 size_t start_freq, | 320 size_t start_freq, |
333 float* sols) { | 321 float* sols) { |
334 bool quadratic = (kConfigRho < 1.0f); | 322 bool quadratic = (kConfigRho < 1.0f); |
335 const float* var_x0 = filtered_clear_var_.get(); | 323 const float* var_x0 = filtered_clear_var_.get(); |
336 const float* var_n0 = filtered_noise_var_.get(); | 324 const float* var_n0 = filtered_noise_var_.get(); |
337 | 325 |
338 for (size_t n = 0; n < start_freq; ++n) { | 326 for (size_t n = 0; n < start_freq; ++n) { |
(...skipping 10 matching lines...) Loading... | |
349 alpha0 = lambda * var_x0[n] * (1 - rho_[n]) * var_x0[n] * var_x0[n]; | 337 alpha0 = lambda * var_x0[n] * (1 - rho_[n]) * var_x0[n] * var_x0[n]; |
350 sols[n] = | 338 sols[n] = |
351 (-beta0 - sqrtf(beta0 * beta0 - 4 * alpha0 * gamma0)) / (2 * alpha0); | 339 (-beta0 - sqrtf(beta0 * beta0 - 4 * alpha0 * gamma0)) / (2 * alpha0); |
352 } else { | 340 } else { |
353 sols[n] = -gamma0 / beta0; | 341 sols[n] = -gamma0 / beta0; |
354 } | 342 } |
355 sols[n] = fmax(0, sols[n]); | 343 sols[n] = fmax(0, sols[n]); |
356 } | 344 } |
357 } | 345 } |
358 | 346 |
359 void IntelligibilityEnhancer::FilterVariance(const float* var, float* result) { | 347 void IntelligibilityEnhancer::FilterVariance( |
hlundin-webrtc
2016/02/08 10:29:28
This method no longer uses any class members, righ
aluebs-webrtc
2016/02/09 00:19:15
Done.
| |
360 RTC_DCHECK_GT(freqs_, 0u); | 348 const float* var, |
349 const std::vector<std::vector<float>>& filter_bank, | |
350 float* result) { | |
361 for (size_t i = 0; i < bank_size_; ++i) { | 351 for (size_t i = 0; i < bank_size_; ++i) { |
362 result[i] = DotProduct(&filter_bank_[i][0], var, freqs_); | 352 RTC_DCHECK_GT(filter_bank[i].size(), 0u); |
353 result[i] = DotProduct(&filter_bank[i][0], var, filter_bank[i].size()); | |
363 } | 354 } |
364 } | 355 } |
365 | 356 |
366 float IntelligibilityEnhancer::DotProduct(const float* a, | 357 float IntelligibilityEnhancer::DotProduct(const float* a, |
367 const float* b, | 358 const float* b, |
368 size_t length) { | 359 size_t length) { |
369 float ret = 0.0f; | 360 float ret = 0.0f; |
370 | 361 |
371 for (size_t i = 0; i < length; ++i) { | 362 for (size_t i = 0; i < length; ++i) { |
372 ret = fmaf(a[i], b[i], ret); | 363 ret = fmaf(a[i], b[i], ret); |
373 } | 364 } |
374 return ret; | 365 return ret; |
375 } | 366 } |
376 | 367 |
377 bool IntelligibilityEnhancer::active() const { | 368 bool IntelligibilityEnhancer::active() const { |
378 return active_; | 369 return active_; |
379 } | 370 } |
380 | 371 |
381 } // namespace webrtc | 372 } // namespace webrtc |
OLD | NEW |