Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1689)

Side by Side Diff: webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.cc

Issue 1394103003: Make the nonlinear beamformer steerable (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@highfreq
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 11 matching lines...) Expand all
22 #include "webrtc/modules/audio_processing/beamformer/covariance_matrix_generator .h" 22 #include "webrtc/modules/audio_processing/beamformer/covariance_matrix_generator .h"
23 23
24 namespace webrtc { 24 namespace webrtc {
25 namespace { 25 namespace {
26 26
27 // Alpha for the Kaiser Bessel Derived window. 27 // Alpha for the Kaiser Bessel Derived window.
28 const float kKbdAlpha = 1.5f; 28 const float kKbdAlpha = 1.5f;
29 29
30 const float kSpeedOfSoundMeterSeconds = 343; 30 const float kSpeedOfSoundMeterSeconds = 343;
31 31
32 // For both target and interference angles, PI / 2 is perpendicular to the
33 // microphone array, facing forwards. The positive direction goes
34 // counterclockwise.
35 // The angle at which we amplify sound.
36 // TODO(aluebs): Make the target angle dynamically settable.
37 const float kTargetAngleRadians = static_cast<float>(M_PI) / 2.f;
38
39 // The minimum separation in radians between the target direction and a 32 // The minimum separation in radians between the target direction and a
40 // interferer scenario. 33 // interferer scenario.
41 const float kMinAwayRadians = 0.2f; 34 const float kMinAwayRadians = 0.2f;
42 35
43 // The separation between the target direction and the closest interferer 36 // The separation between the target direction and the closest interferer
44 // scenario is proportional to this constant. 37 // scenario is proportional to this constant.
45 const float kAwaySlope = 0.008f; 38 const float kAwaySlope = 0.008f;
46 39
47 // When calculating the interference covariance matrix, this is the weight for 40 // When calculating the interference covariance matrix, this is the weight for
48 // the weighted average between the uniform covariance matrix and the angled 41 // the weighted average between the uniform covariance matrix and the angled
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 for (size_t j = i + 1; j < array_geometry.size(); ++j) { 185 for (size_t j = i + 1; j < array_geometry.size(); ++j) {
193 float distance = Distance(array_geometry[i], array_geometry[j]); 186 float distance = Distance(array_geometry[i], array_geometry[j]);
194 if (distance < mic_spacing) { 187 if (distance < mic_spacing) {
195 mic_spacing = distance; 188 mic_spacing = distance;
196 } 189 }
197 } 190 }
198 } 191 }
199 return mic_spacing; 192 return mic_spacing;
200 } 193 }
201 194
195 float DotProduct(std::vector<float> a, std::vector<float> b) {
Andrew MacDonald 2015/10/14 22:12:30 const references.
Andrew MacDonald 2015/10/20 03:00:08 Looks like you missed the remainder of the comment
aluebs-webrtc 2015/10/21 01:41:40 I totally missed them, sorry about that. Addressin
aluebs-webrtc 2015/10/21 01:41:40 Done.
196 RTC_DCHECK_EQ(a.size(), b.size());
197 float dot_product = 0.f;
198 for (size_t i = 0u; i < a.size(); ++i) {
199 dot_product += a[i] * b[i];
200 }
201 return dot_product;
202 }
203
204 float NormalizedDotProduct(std::vector<float> a, std::vector<float> b) {
Andrew MacDonald 2015/10/14 22:12:31 const references.
aluebs-webrtc 2015/10/21 01:41:40 Removed this function.
205 const float kMinNorm = 1e-6f;
206 float norm_a = DotProduct(a, a);
Andrew MacDonald 2015/10/14 22:12:30 You're repeatedly computing this for first_pair_di
aluebs-webrtc 2015/10/21 01:41:40 I removed the NormalizedDotProduct and did the nor
207 float norm_b = DotProduct(b, b);
208 if (norm_a > kMinNorm && norm_b > kMinNorm) {
209 return DotProduct(a, b) / std::sqrt(norm_a * norm_b);
210 } else {
211 return 0.f;
212 }
213 }
214
215 bool IsGeometryLinear(std::vector<Point> array_geometry) {
216 const float kMinDotProduct = 0.9999f;
217 bool is_geometry_linear = true;
218 std::vector<float> directiona;
Andrew MacDonald 2015/10/14 22:12:31 first_pair_direction
aluebs-webrtc 2015/10/21 01:41:39 Done.
219 directiona.push_back(array_geometry[1].x() - array_geometry[0].x());
220 directiona.push_back(array_geometry[1].y() - array_geometry[0].y());
221 directiona.push_back(array_geometry[1].z() - array_geometry[0].z());
Andrew MacDonald 2015/10/14 22:12:31 Write a helper for this, something like: std::vect
aluebs-webrtc 2015/10/21 01:41:40 I though about using Point, but I thought it was s
222 for (size_t i = 2u; i < array_geometry.size(); ++i) {
223 std::vector<float> directionb;
224 directionb.push_back(array_geometry[i].x() - array_geometry[i - 1].x());
Andrew MacDonald 2015/10/14 22:12:31 pair_direction
aluebs-webrtc 2015/10/21 01:41:40 Done.
225 directionb.push_back(array_geometry[i].y() - array_geometry[i - 1].y());
226 directionb.push_back(array_geometry[i].z() - array_geometry[i - 1].z());
227 is_geometry_linear &=
228 std::abs(NormalizedDotProduct(directiona, directionb)) > kMinDotProduct;
Andrew MacDonald 2015/10/14 22:12:31 Instead, short circuit: if (std::abs(Normalized
aluebs-webrtc 2015/10/21 01:41:40 I believe that function with only one return state
229 }
230 return is_geometry_linear;
231 }
232
202 } // namespace 233 } // namespace
203 234
204 // static 235 // static
205 const size_t NonlinearBeamformer::kNumFreqBins; 236 const size_t NonlinearBeamformer::kNumFreqBins;
206 237
207 NonlinearBeamformer::NonlinearBeamformer( 238 NonlinearBeamformer::NonlinearBeamformer(
208 const std::vector<Point>& array_geometry) 239 const std::vector<Point>& array_geometry,
240 float target_angle_radians)
209 : num_input_channels_(array_geometry.size()), 241 : num_input_channels_(array_geometry.size()),
210 array_geometry_(GetCenteredArray(array_geometry)), 242 array_geometry_(GetCenteredArray(array_geometry)),
211 mic_spacing_(GetMinimumSpacing(array_geometry)) { 243 mic_spacing_(GetMinimumSpacing(array_geometry)),
244 target_angle_radians_(target_angle_radians) {
212 WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_); 245 WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_);
213 } 246 }
214 247
215 void NonlinearBeamformer::Initialize(int chunk_size_ms, int sample_rate_hz) { 248 void NonlinearBeamformer::Initialize(int chunk_size_ms, int sample_rate_hz) {
216 chunk_length_ = 249 chunk_length_ =
217 static_cast<size_t>(sample_rate_hz / (1000.f / chunk_size_ms)); 250 static_cast<size_t>(sample_rate_hz / (1000.f / chunk_size_ms));
218 sample_rate_hz_ = sample_rate_hz; 251 sample_rate_hz_ = sample_rate_hz;
219 InitFrequencyCorrectionRanges();
220 252
221 high_pass_postfilter_mask_ = 1.f; 253 high_pass_postfilter_mask_ = 1.f;
222 is_target_present_ = false; 254 is_target_present_ = false;
223 hold_target_blocks_ = kHoldTargetSeconds * 2 * sample_rate_hz / kFftSize; 255 hold_target_blocks_ = kHoldTargetSeconds * 2 * sample_rate_hz / kFftSize;
224 interference_blocks_count_ = hold_target_blocks_; 256 interference_blocks_count_ = hold_target_blocks_;
225 257
226 lapped_transform_.reset(new LappedTransform(num_input_channels_, 258 lapped_transform_.reset(new LappedTransform(num_input_channels_,
227 1, 259 1,
228 chunk_length_, 260 chunk_length_,
229 window_, 261 window_,
230 kFftSize, 262 kFftSize,
231 kFftSize / 2, 263 kFftSize / 2,
232 this)); 264 this));
233 for (size_t i = 0; i < kNumFreqBins; ++i) { 265 for (size_t i = 0; i < kNumFreqBins; ++i) {
234 time_smooth_mask_[i] = 1.f; 266 time_smooth_mask_[i] = 1.f;
235 final_mask_[i] = 1.f; 267 final_mask_[i] = 1.f;
236 float freq_hz = (static_cast<float>(i) / kFftSize) * sample_rate_hz_; 268 float freq_hz = (static_cast<float>(i) / kFftSize) * sample_rate_hz_;
237 wave_numbers_[i] = 2 * M_PI * freq_hz / kSpeedOfSoundMeterSeconds; 269 wave_numbers_[i] = 2 * M_PI * freq_hz / kSpeedOfSoundMeterSeconds;
238 } 270 }
239 271
240 // Initialize all nonadaptive values before looping through the frames. 272 InitLowFrequencyCorrectionRanges();
241 InitInterfAngles(); 273 InitDifuseCovMats();
Andrew MacDonald 2015/10/14 22:12:31 Diffuse
aluebs-webrtc 2015/10/21 01:41:40 Done.
242 InitDelaySumMasks(); 274 SteerBeam(target_angle_radians_);
243 InitTargetCovMats();
244 InitInterfCovMats();
245
246 for (size_t i = 0; i < kNumFreqBins; ++i) {
247 rxiws_[i] = Norm(target_cov_mats_[i], delay_sum_masks_[i]);
248 rpsiws_[i].clear();
249 for (size_t j = 0; j < interf_angles_radians_.size(); ++j) {
250 rpsiws_[i].push_back(Norm(*interf_cov_mats_[i][j], delay_sum_masks_[i]));
251 }
252 }
253 } 275 }
254 276
255 void NonlinearBeamformer::InitFrequencyCorrectionRanges() { 277 // These bin indexes determine the regions over which a mean is taken. This is
278 // applied as a constant value over the adjacent end "frequency correction"
279 // regions.
280 //
281 // low_mean_start_bin_ high_mean_start_bin_
282 // v v constant
283 // |----------------|--------|----------------|-------|----------------|
284 // constant ^ ^
285 // low_mean_end_bin_ high_mean_end_bin_
286 //
287 void NonlinearBeamformer::InitLowFrequencyCorrectionRanges() {
288 low_mean_start_bin_ = Round(kLowMeanStartHz * kFftSize / sample_rate_hz_);
289 low_mean_end_bin_ = Round(kLowMeanEndHz * kFftSize / sample_rate_hz_);
290
291 RTC_DCHECK_GT(low_mean_start_bin_, 0U);
292 RTC_DCHECK_LT(low_mean_start_bin_, low_mean_end_bin_);
293 }
294
295 void NonlinearBeamformer::InitHighFrequencyCorrectionRanges() {
256 const float kAliasingFreqHz = 296 const float kAliasingFreqHz =
257 kSpeedOfSoundMeterSeconds / 297 kSpeedOfSoundMeterSeconds /
258 (mic_spacing_ * (1.f + std::abs(std::cos(kTargetAngleRadians)))); 298 (mic_spacing_ * (1.f + std::abs(std::cos(target_angle_radians_))));
259 const float kHighMeanStartHz = std::min(0.5f * kAliasingFreqHz, 299 const float kHighMeanStartHz = std::min(0.5f * kAliasingFreqHz,
260 sample_rate_hz_ / 2.f); 300 sample_rate_hz_ / 2.f);
261 const float kHighMeanEndHz = std::min(0.75f * kAliasingFreqHz, 301 const float kHighMeanEndHz = std::min(0.75f * kAliasingFreqHz,
262 sample_rate_hz_ / 2.f); 302 sample_rate_hz_ / 2.f);
263
264 low_mean_start_bin_ = Round(kLowMeanStartHz * kFftSize / sample_rate_hz_);
265 low_mean_end_bin_ = Round(kLowMeanEndHz * kFftSize / sample_rate_hz_);
266 high_mean_start_bin_ = Round(kHighMeanStartHz * kFftSize / sample_rate_hz_); 303 high_mean_start_bin_ = Round(kHighMeanStartHz * kFftSize / sample_rate_hz_);
267 high_mean_end_bin_ = Round(kHighMeanEndHz * kFftSize / sample_rate_hz_); 304 high_mean_end_bin_ = Round(kHighMeanEndHz * kFftSize / sample_rate_hz_);
268 // These bin indexes determine the regions over which a mean is taken. This 305
269 // is applied as a constant value over the adjacent end "frequency correction"
270 // regions.
271 //
272 // low_mean_start_bin_ high_mean_start_bin_
273 // v v constant
274 // |----------------|--------|----------------|-------|----------------|
275 // constant ^ ^
276 // low_mean_end_bin_ high_mean_end_bin_
277 //
278 RTC_DCHECK_GT(low_mean_start_bin_, 0U);
279 RTC_DCHECK_LT(low_mean_start_bin_, low_mean_end_bin_);
280 RTC_DCHECK_LT(low_mean_end_bin_, high_mean_end_bin_); 306 RTC_DCHECK_LT(low_mean_end_bin_, high_mean_end_bin_);
281 RTC_DCHECK_LT(high_mean_start_bin_, high_mean_end_bin_); 307 RTC_DCHECK_LT(high_mean_start_bin_, high_mean_end_bin_);
282 RTC_DCHECK_LT(high_mean_end_bin_, kNumFreqBins - 1); 308 RTC_DCHECK_LT(high_mean_end_bin_, kNumFreqBins - 1);
283 } 309 }
284 310
285
286 void NonlinearBeamformer::InitInterfAngles() { 311 void NonlinearBeamformer::InitInterfAngles() {
287 const float kAway = 312 const float kAway =
288 std::min(static_cast<float>(M_PI), 313 std::min(static_cast<float>(M_PI),
289 std::max(kMinAwayRadians, 314 std::max(kMinAwayRadians,
290 kAwaySlope * static_cast<float>(M_PI) / mic_spacing_)); 315 kAwaySlope * static_cast<float>(M_PI) / mic_spacing_));
291 316
292 interf_angles_radians_.clear(); 317 interf_angles_radians_.clear();
293 // TODO(aluebs): When the target angle is settable, make sure the interferer 318 if (IsGeometryLinear(array_geometry_)) {
294 // scenarios aren't reflected over the target one for linear geometries. 319 if (target_angle_radians_ - kAway >= 0.f) {
Andrew MacDonald 2015/10/14 22:12:30 These values depend on the array being parallel wi
aluebs-webrtc 2015/10/21 01:41:40 Great Point. Now I generalized it.
295 interf_angles_radians_.push_back(kTargetAngleRadians - kAway); 320 interf_angles_radians_.push_back(target_angle_radians_ - kAway);
296 interf_angles_radians_.push_back(kTargetAngleRadians + kAway); 321 } else {
322 interf_angles_radians_.push_back(M_PI);
323 }
324 if (target_angle_radians_ + kAway <= M_PI) {
325 interf_angles_radians_.push_back(target_angle_radians_ + kAway);
326 } else {
327 interf_angles_radians_.push_back(0.f);
328 }
329 } else {
330 interf_angles_radians_.push_back(target_angle_radians_ - kAway);
331 interf_angles_radians_.push_back(target_angle_radians_ + kAway);
332 }
297 } 333 }
298 334
299 void NonlinearBeamformer::InitDelaySumMasks() { 335 void NonlinearBeamformer::InitDelaySumMasks() {
300 for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { 336 for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) {
301 delay_sum_masks_[f_ix].Resize(1, num_input_channels_); 337 delay_sum_masks_[f_ix].Resize(1, num_input_channels_);
302 CovarianceMatrixGenerator::PhaseAlignmentMasks(f_ix, 338 CovarianceMatrixGenerator::PhaseAlignmentMasks(f_ix,
303 kFftSize, 339 kFftSize,
304 sample_rate_hz_, 340 sample_rate_hz_,
305 kSpeedOfSoundMeterSeconds, 341 kSpeedOfSoundMeterSeconds,
306 array_geometry_, 342 array_geometry_,
307 kTargetAngleRadians, 343 target_angle_radians_,
308 &delay_sum_masks_[f_ix]); 344 &delay_sum_masks_[f_ix]);
309 345
310 complex_f norm_factor = sqrt( 346 complex_f norm_factor = sqrt(
311 ConjugateDotProduct(delay_sum_masks_[f_ix], delay_sum_masks_[f_ix])); 347 ConjugateDotProduct(delay_sum_masks_[f_ix], delay_sum_masks_[f_ix]));
312 delay_sum_masks_[f_ix].Scale(1.f / norm_factor); 348 delay_sum_masks_[f_ix].Scale(1.f / norm_factor);
313 normalized_delay_sum_masks_[f_ix].CopyFrom(delay_sum_masks_[f_ix]); 349 normalized_delay_sum_masks_[f_ix].CopyFrom(delay_sum_masks_[f_ix]);
314 normalized_delay_sum_masks_[f_ix].Scale(1.f / SumAbs( 350 normalized_delay_sum_masks_[f_ix].Scale(1.f / SumAbs(
315 normalized_delay_sum_masks_[f_ix])); 351 normalized_delay_sum_masks_[f_ix]));
316 } 352 }
317 } 353 }
318 354
319 void NonlinearBeamformer::InitTargetCovMats() { 355 void NonlinearBeamformer::InitTargetCovMats() {
320 for (size_t i = 0; i < kNumFreqBins; ++i) { 356 for (size_t i = 0; i < kNumFreqBins; ++i) {
321 target_cov_mats_[i].Resize(num_input_channels_, num_input_channels_); 357 target_cov_mats_[i].Resize(num_input_channels_, num_input_channels_);
322 TransposedConjugatedProduct(delay_sum_masks_[i], &target_cov_mats_[i]); 358 TransposedConjugatedProduct(delay_sum_masks_[i], &target_cov_mats_[i]);
323 } 359 }
324 } 360 }
325 361
362 void NonlinearBeamformer::InitDifuseCovMats() {
363 for (size_t i = 0; i < kNumFreqBins; ++i) {
364 uniform_cov_mat_[i].Resize(num_input_channels_, num_input_channels_);
365 CovarianceMatrixGenerator::UniformCovarianceMatrix(wave_numbers_[i],
366 array_geometry_,
367 &uniform_cov_mat_[i]);
368 complex_f normalization_factor = uniform_cov_mat_[i].elements()[0][0];
369 uniform_cov_mat_[i].Scale(1.f / normalization_factor);
370 uniform_cov_mat_[i].Scale(1 - kBalance);
371 }
372 }
373
326 void NonlinearBeamformer::InitInterfCovMats() { 374 void NonlinearBeamformer::InitInterfCovMats() {
327 for (size_t i = 0; i < kNumFreqBins; ++i) { 375 for (size_t i = 0; i < kNumFreqBins; ++i) {
328 ComplexMatrixF uniform_cov_mat(num_input_channels_, num_input_channels_);
329 CovarianceMatrixGenerator::UniformCovarianceMatrix(wave_numbers_[i],
330 array_geometry_,
331 &uniform_cov_mat);
332 complex_f normalization_factor = uniform_cov_mat.elements()[0][0];
333 uniform_cov_mat.Scale(1.f / normalization_factor);
334 uniform_cov_mat.Scale(1 - kBalance);
335 interf_cov_mats_[i].clear(); 376 interf_cov_mats_[i].clear();
336 for (size_t j = 0; j < interf_angles_radians_.size(); ++j) { 377 for (size_t j = 0; j < interf_angles_radians_.size(); ++j) {
337 interf_cov_mats_[i].push_back(new ComplexMatrixF(num_input_channels_, 378 interf_cov_mats_[i].push_back(new ComplexMatrixF(num_input_channels_,
338 num_input_channels_)); 379 num_input_channels_));
339 ComplexMatrixF angled_cov_mat(num_input_channels_, num_input_channels_); 380 ComplexMatrixF angled_cov_mat(num_input_channels_, num_input_channels_);
340 CovarianceMatrixGenerator::AngledCovarianceMatrix( 381 CovarianceMatrixGenerator::AngledCovarianceMatrix(
341 kSpeedOfSoundMeterSeconds, 382 kSpeedOfSoundMeterSeconds,
342 interf_angles_radians_[j], 383 interf_angles_radians_[j],
343 i, 384 i,
344 kFftSize, 385 kFftSize,
345 kNumFreqBins, 386 kNumFreqBins,
346 sample_rate_hz_, 387 sample_rate_hz_,
347 array_geometry_, 388 array_geometry_,
348 &angled_cov_mat); 389 &angled_cov_mat);
349 // Normalize matrices before averaging them. 390 // Normalize matrices before averaging them.
350 normalization_factor = angled_cov_mat.elements()[0][0]; 391 complex_f normalization_factor = angled_cov_mat.elements()[0][0];
351 angled_cov_mat.Scale(1.f / normalization_factor); 392 angled_cov_mat.Scale(1.f / normalization_factor);
352 // Weighted average of matrices. 393 // Weighted average of matrices.
353 angled_cov_mat.Scale(kBalance); 394 angled_cov_mat.Scale(kBalance);
354 interf_cov_mats_[i][j]->Add(uniform_cov_mat, angled_cov_mat); 395 interf_cov_mats_[i][j]->Add(uniform_cov_mat_[i], angled_cov_mat);
355 } 396 }
356 } 397 }
357 } 398 }
399
400 void NonlinearBeamformer::NormalizeCovMats() {
401 for (size_t i = 0; i < kNumFreqBins; ++i) {
402 rxiws_[i] = Norm(target_cov_mats_[i], delay_sum_masks_[i]);
403 rpsiws_[i].clear();
404 for (size_t j = 0; j < interf_angles_radians_.size(); ++j) {
405 rpsiws_[i].push_back(Norm(*interf_cov_mats_[i][j], delay_sum_masks_[i]));
406 }
407 }
408 }
358 409
359 void NonlinearBeamformer::ProcessChunk(const ChannelBuffer<float>& input, 410 void NonlinearBeamformer::ProcessChunk(const ChannelBuffer<float>& input,
360 ChannelBuffer<float>* output) { 411 ChannelBuffer<float>* output) {
361 RTC_DCHECK_EQ(input.num_channels(), num_input_channels_); 412 RTC_DCHECK_EQ(input.num_channels(), num_input_channels_);
362 RTC_DCHECK_EQ(input.num_frames_per_band(), chunk_length_); 413 RTC_DCHECK_EQ(input.num_frames_per_band(), chunk_length_);
363 414
364 float old_high_pass_mask = high_pass_postfilter_mask_; 415 float old_high_pass_mask = high_pass_postfilter_mask_;
365 lapped_transform_->ProcessChunk(input.channels(0), output->channels(0)); 416 lapped_transform_->ProcessChunk(input.channels(0), output->channels(0));
366 // Ramp up/down for smoothing. 1 mask per 10ms results in audible 417 // Ramp up/down for smoothing. 1 mask per 10ms results in audible
367 // discontinuities. 418 // discontinuities.
(...skipping 11 matching lines...) Expand all
379 // averaging). 430 // averaging).
380 float sum = 0.f; 431 float sum = 0.f;
381 for (int k = 0; k < input.num_channels(); ++k) { 432 for (int k = 0; k < input.num_channels(); ++k) {
382 sum += input.channels(i)[k][j]; 433 sum += input.channels(i)[k][j];
383 } 434 }
384 output->channels(i)[0][j] = sum / input.num_channels() * smoothed_mask; 435 output->channels(i)[0][j] = sum / input.num_channels() * smoothed_mask;
385 } 436 }
386 } 437 }
387 } 438 }
388 439
440 void NonlinearBeamformer::SteerBeam(float target_angle_radians) {
441 target_angle_radians_ = target_angle_radians;
442 InitHighFrequencyCorrectionRanges();
443 InitInterfAngles();
444 InitDelaySumMasks();
445 InitTargetCovMats();
446 InitInterfCovMats();
447 NormalizeCovMats();
448 }
449
389 bool NonlinearBeamformer::IsInBeam(const SphericalPointf& spherical_point) { 450 bool NonlinearBeamformer::IsInBeam(const SphericalPointf& spherical_point) {
390 // If more than half-beamwidth degrees away from the beam's center, 451 // If more than half-beamwidth degrees away from the beam's center,
391 // you are out of the beam. 452 // you are out of the beam.
392 return fabs(spherical_point.azimuth() - kTargetAngleRadians) < 453 return fabs(spherical_point.azimuth() - target_angle_radians_) <
393 kHalfBeamWidthRadians; 454 kHalfBeamWidthRadians;
394 } 455 }
395 456
396 void NonlinearBeamformer::ProcessAudioBlock(const complex_f* const* input, 457 void NonlinearBeamformer::ProcessAudioBlock(const complex_f* const* input,
397 int num_input_channels, 458 int num_input_channels,
398 size_t num_freq_bins, 459 size_t num_freq_bins,
399 int num_output_channels, 460 int num_output_channels,
400 complex_f* const* output) { 461 complex_f* const* output) {
401 RTC_CHECK_EQ(num_freq_bins, kNumFreqBins); 462 RTC_CHECK_EQ(num_freq_bins, kNumFreqBins);
402 RTC_CHECK_EQ(num_input_channels, num_input_channels_); 463 RTC_CHECK_EQ(num_input_channels, num_input_channels_);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 new_mask_ + high_mean_end_bin_ + 1); 608 new_mask_ + high_mean_end_bin_ + 1);
548 if (new_mask_[quantile] > kMaskTargetThreshold) { 609 if (new_mask_[quantile] > kMaskTargetThreshold) {
549 is_target_present_ = true; 610 is_target_present_ = true;
550 interference_blocks_count_ = 0; 611 interference_blocks_count_ = 0;
551 } else { 612 } else {
552 is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; 613 is_target_present_ = interference_blocks_count_++ < hold_target_blocks_;
553 } 614 }
554 } 615 }
555 616
556 } // namespace webrtc 617 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698