| 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 115   } | 115   } | 
| 116 | 116 | 
| 117   return result; | 117   return result; | 
| 118 } | 118 } | 
| 119 | 119 | 
| 120 // Works for positive numbers only. | 120 // Works for positive numbers only. | 
| 121 size_t Round(float x) { | 121 size_t Round(float x) { | 
| 122   return static_cast<size_t>(std::floor(x + 0.5f)); | 122   return static_cast<size_t>(std::floor(x + 0.5f)); | 
| 123 } | 123 } | 
| 124 | 124 | 
| 125 // Calculates the sum of absolute values of a complex matrix. |  | 
| 126 float SumAbs(const ComplexMatrix<float>& mat) { |  | 
| 127   float sum_abs = 0.f; |  | 
| 128   const complex<float>* const* mat_els = mat.elements(); |  | 
| 129   for (size_t i = 0; i < mat.num_rows(); ++i) { |  | 
| 130     for (size_t j = 0; j < mat.num_columns(); ++j) { |  | 
| 131       sum_abs += std::abs(mat_els[i][j]); |  | 
| 132     } |  | 
| 133   } |  | 
| 134   return sum_abs; |  | 
| 135 } |  | 
| 136 |  | 
| 137 // Calculates the sum of squares of a complex matrix. | 125 // Calculates the sum of squares of a complex matrix. | 
| 138 float SumSquares(const ComplexMatrix<float>& mat) { | 126 float SumSquares(const ComplexMatrix<float>& mat) { | 
| 139   float sum_squares = 0.f; | 127   float sum_squares = 0.f; | 
| 140   const complex<float>* const* mat_els = mat.elements(); | 128   const complex<float>* const* mat_els = mat.elements(); | 
| 141   for (size_t i = 0; i < mat.num_rows(); ++i) { | 129   for (size_t i = 0; i < mat.num_rows(); ++i) { | 
| 142     for (size_t j = 0; j < mat.num_columns(); ++j) { | 130     for (size_t j = 0; j < mat.num_columns(); ++j) { | 
| 143       float abs_value = std::abs(mat_els[i][j]); | 131       float abs_value = std::abs(mat_els[i][j]); | 
| 144       sum_squares += abs_value * abs_value; | 132       sum_squares += abs_value * abs_value; | 
| 145     } | 133     } | 
| 146   } | 134   } | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 176   return array_geometry; | 164   return array_geometry; | 
| 177 } | 165 } | 
| 178 | 166 | 
| 179 }  // namespace | 167 }  // namespace | 
| 180 | 168 | 
| 181 const float NonlinearBeamformer::kHalfBeamWidthRadians = DegreesToRadians(20.f); | 169 const float NonlinearBeamformer::kHalfBeamWidthRadians = DegreesToRadians(20.f); | 
| 182 | 170 | 
| 183 // static | 171 // static | 
| 184 const size_t NonlinearBeamformer::kNumFreqBins; | 172 const size_t NonlinearBeamformer::kNumFreqBins; | 
| 185 | 173 | 
|  | 174 PostFilterTransform::PostFilterTransform(size_t num_channels, | 
|  | 175                                          size_t chunk_length, | 
|  | 176                                          float* window, | 
|  | 177                                          size_t fft_size) | 
|  | 178     : transform_(num_channels, | 
|  | 179                  num_channels, | 
|  | 180                  chunk_length, | 
|  | 181                  window, | 
|  | 182                  fft_size, | 
|  | 183                  fft_size / 2, | 
|  | 184                  this), | 
|  | 185       num_freq_bins_(fft_size / 2 + 1) {} | 
|  | 186 | 
|  | 187 void PostFilterTransform::ProcessChunk(float* const* data, float* final_mask) { | 
|  | 188   final_mask_ = final_mask; | 
|  | 189   transform_.ProcessChunk(data, data); | 
|  | 190 } | 
|  | 191 | 
|  | 192 void PostFilterTransform::ProcessAudioBlock(const complex<float>* const* input, | 
|  | 193                                             size_t num_input_channels, | 
|  | 194                                             size_t num_freq_bins, | 
|  | 195                                             size_t num_output_channels, | 
|  | 196                                             complex<float>* const* output) { | 
|  | 197   RTC_DCHECK_EQ(num_freq_bins_, num_freq_bins); | 
|  | 198   RTC_DCHECK_EQ(num_input_channels, num_output_channels); | 
|  | 199 | 
|  | 200   for (size_t ch = 0; ch < num_input_channels; ++ch) { | 
|  | 201     for (size_t f_ix = 0; f_ix < num_freq_bins_; ++f_ix) { | 
|  | 202       output[ch][f_ix] = | 
|  | 203           kCompensationGain * final_mask_[f_ix] * input[ch][f_ix]; | 
|  | 204     } | 
|  | 205   } | 
|  | 206 } | 
|  | 207 | 
| 186 NonlinearBeamformer::NonlinearBeamformer( | 208 NonlinearBeamformer::NonlinearBeamformer( | 
| 187     const std::vector<Point>& array_geometry, | 209     const std::vector<Point>& array_geometry, | 
|  | 210     size_t num_postfilter_channels, | 
| 188     SphericalPointf target_direction) | 211     SphericalPointf target_direction) | 
| 189     : num_input_channels_(array_geometry.size()), | 212     : num_input_channels_(array_geometry.size()), | 
|  | 213       num_postfilter_channels_(num_postfilter_channels), | 
| 190       array_geometry_(GetCenteredArray(array_geometry)), | 214       array_geometry_(GetCenteredArray(array_geometry)), | 
| 191       array_normal_(GetArrayNormalIfExists(array_geometry)), | 215       array_normal_(GetArrayNormalIfExists(array_geometry)), | 
| 192       min_mic_spacing_(GetMinimumSpacing(array_geometry)), | 216       min_mic_spacing_(GetMinimumSpacing(array_geometry)), | 
| 193       target_angle_radians_(target_direction.azimuth()), | 217       target_angle_radians_(target_direction.azimuth()), | 
| 194       away_radians_(std::min( | 218       away_radians_(std::min( | 
| 195           static_cast<float>(M_PI), | 219           static_cast<float>(M_PI), | 
| 196           std::max(kMinAwayRadians, | 220           std::max(kMinAwayRadians, | 
| 197                    kAwaySlope * static_cast<float>(M_PI) / min_mic_spacing_))) { | 221                    kAwaySlope * static_cast<float>(M_PI) / min_mic_spacing_))) { | 
| 198   WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_); | 222   WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_); | 
| 199 } | 223 } | 
| 200 | 224 | 
| 201 void NonlinearBeamformer::Initialize(int chunk_size_ms, int sample_rate_hz) { | 225 void NonlinearBeamformer::Initialize(int chunk_size_ms, int sample_rate_hz) { | 
| 202   chunk_length_ = | 226   chunk_length_ = | 
| 203       static_cast<size_t>(sample_rate_hz / (1000.f / chunk_size_ms)); | 227       static_cast<size_t>(sample_rate_hz / (1000.f / chunk_size_ms)); | 
| 204   sample_rate_hz_ = sample_rate_hz; | 228   sample_rate_hz_ = sample_rate_hz; | 
| 205 | 229 | 
| 206   high_pass_postfilter_mask_ = 1.f; | 230   high_pass_postfilter_mask_ = 1.f; | 
| 207   is_target_present_ = false; | 231   is_target_present_ = false; | 
| 208   hold_target_blocks_ = kHoldTargetSeconds * 2 * sample_rate_hz / kFftSize; | 232   hold_target_blocks_ = kHoldTargetSeconds * 2 * sample_rate_hz / kFftSize; | 
| 209   interference_blocks_count_ = hold_target_blocks_; | 233   interference_blocks_count_ = hold_target_blocks_; | 
| 210 | 234 | 
| 211   lapped_transform_.reset(new LappedTransform(num_input_channels_, | 235   process_transform_.reset(new LappedTransform(num_input_channels_, | 
| 212                                               1, | 236                                                0u, | 
| 213                                               chunk_length_, | 237                                                chunk_length_, | 
| 214                                               window_, | 238                                                window_, | 
| 215                                               kFftSize, | 239                                                kFftSize, | 
| 216                                               kFftSize / 2, | 240                                                kFftSize / 2, | 
| 217                                               this)); | 241                                                this)); | 
|  | 242   postfilter_transform_.reset(new PostFilterTransform( | 
|  | 243       num_postfilter_channels_, chunk_length_, window_, kFftSize)); | 
|  | 244   const float wave_number_step = | 
|  | 245       (2.f * M_PI * sample_rate_hz_) / (kFftSize * kSpeedOfSoundMeterSeconds); | 
| 218   for (size_t i = 0; i < kNumFreqBins; ++i) { | 246   for (size_t i = 0; i < kNumFreqBins; ++i) { | 
| 219     time_smooth_mask_[i] = 1.f; | 247     time_smooth_mask_[i] = 1.f; | 
| 220     final_mask_[i] = 1.f; | 248     final_mask_[i] = 1.f; | 
| 221     float freq_hz = (static_cast<float>(i) / kFftSize) * sample_rate_hz_; | 249     wave_numbers_[i] = i * wave_number_step; | 
| 222     wave_numbers_[i] = 2 * M_PI * freq_hz / kSpeedOfSoundMeterSeconds; |  | 
| 223   } | 250   } | 
| 224 | 251 | 
| 225   InitLowFrequencyCorrectionRanges(); | 252   InitLowFrequencyCorrectionRanges(); | 
| 226   InitDiffuseCovMats(); | 253   InitDiffuseCovMats(); | 
| 227   AimAt(SphericalPointf(target_angle_radians_, 0.f, 1.f)); | 254   AimAt(SphericalPointf(target_angle_radians_, 0.f, 1.f)); | 
| 228 } | 255 } | 
| 229 | 256 | 
| 230 // These bin indexes determine the regions over which a mean is taken. This is | 257 // These bin indexes determine the regions over which a mean is taken. This is | 
| 231 // applied as a constant value over the adjacent end "frequency correction" | 258 // applied as a constant value over the adjacent end "frequency correction" | 
| 232 // regions. | 259 // regions. | 
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 299 void NonlinearBeamformer::InitDelaySumMasks() { | 326 void NonlinearBeamformer::InitDelaySumMasks() { | 
| 300   for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { | 327   for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { | 
| 301     delay_sum_masks_[f_ix].Resize(1, num_input_channels_); | 328     delay_sum_masks_[f_ix].Resize(1, num_input_channels_); | 
| 302     CovarianceMatrixGenerator::PhaseAlignmentMasks( | 329     CovarianceMatrixGenerator::PhaseAlignmentMasks( | 
| 303         f_ix, kFftSize, sample_rate_hz_, kSpeedOfSoundMeterSeconds, | 330         f_ix, kFftSize, sample_rate_hz_, kSpeedOfSoundMeterSeconds, | 
| 304         array_geometry_, target_angle_radians_, &delay_sum_masks_[f_ix]); | 331         array_geometry_, target_angle_radians_, &delay_sum_masks_[f_ix]); | 
| 305 | 332 | 
| 306     complex_f norm_factor = sqrt( | 333     complex_f norm_factor = sqrt( | 
| 307         ConjugateDotProduct(delay_sum_masks_[f_ix], delay_sum_masks_[f_ix])); | 334         ConjugateDotProduct(delay_sum_masks_[f_ix], delay_sum_masks_[f_ix])); | 
| 308     delay_sum_masks_[f_ix].Scale(1.f / norm_factor); | 335     delay_sum_masks_[f_ix].Scale(1.f / norm_factor); | 
| 309     normalized_delay_sum_masks_[f_ix].CopyFrom(delay_sum_masks_[f_ix]); |  | 
| 310     normalized_delay_sum_masks_[f_ix].Scale(1.f / SumAbs( |  | 
| 311         normalized_delay_sum_masks_[f_ix])); |  | 
| 312   } | 336   } | 
| 313 } | 337 } | 
| 314 | 338 | 
| 315 void NonlinearBeamformer::InitTargetCovMats() { | 339 void NonlinearBeamformer::InitTargetCovMats() { | 
| 316   for (size_t i = 0; i < kNumFreqBins; ++i) { | 340   for (size_t i = 0; i < kNumFreqBins; ++i) { | 
| 317     target_cov_mats_[i].Resize(num_input_channels_, num_input_channels_); | 341     target_cov_mats_[i].Resize(num_input_channels_, num_input_channels_); | 
| 318     TransposedConjugatedProduct(delay_sum_masks_[i], &target_cov_mats_[i]); | 342     TransposedConjugatedProduct(delay_sum_masks_[i], &target_cov_mats_[i]); | 
| 319   } | 343   } | 
| 320 } | 344 } | 
| 321 | 345 | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 359 void NonlinearBeamformer::NormalizeCovMats() { | 383 void NonlinearBeamformer::NormalizeCovMats() { | 
| 360   for (size_t i = 0; i < kNumFreqBins; ++i) { | 384   for (size_t i = 0; i < kNumFreqBins; ++i) { | 
| 361     rxiws_[i] = Norm(target_cov_mats_[i], delay_sum_masks_[i]); | 385     rxiws_[i] = Norm(target_cov_mats_[i], delay_sum_masks_[i]); | 
| 362     rpsiws_[i].clear(); | 386     rpsiws_[i].clear(); | 
| 363     for (size_t j = 0; j < interf_angles_radians_.size(); ++j) { | 387     for (size_t j = 0; j < interf_angles_radians_.size(); ++j) { | 
| 364       rpsiws_[i].push_back(Norm(*interf_cov_mats_[i][j], delay_sum_masks_[i])); | 388       rpsiws_[i].push_back(Norm(*interf_cov_mats_[i][j], delay_sum_masks_[i])); | 
| 365     } | 389     } | 
| 366   } | 390   } | 
| 367 } | 391 } | 
| 368 | 392 | 
|  | 393 void NonlinearBeamformer::AnalyzeChunk(const ChannelBuffer<float>& data) { | 
|  | 394   RTC_DCHECK_EQ(data.num_channels(), num_input_channels_); | 
|  | 395   RTC_DCHECK_EQ(data.num_frames_per_band(), chunk_length_); | 
|  | 396 | 
|  | 397   old_high_pass_mask_ = high_pass_postfilter_mask_; | 
|  | 398   process_transform_->ProcessChunk(data.channels(0), nullptr); | 
|  | 399 } | 
|  | 400 | 
|  | 401 void NonlinearBeamformer::PostFilter(ChannelBuffer<float>* data) { | 
|  | 402   RTC_DCHECK_EQ(data->num_frames_per_band(), chunk_length_); | 
|  | 403   // TODO(aluebs): Change to RTC_CHECK_EQ once the ChannelBuffer is updated. | 
|  | 404   RTC_DCHECK_GE(data->num_channels(), num_postfilter_channels_); | 
|  | 405 | 
|  | 406   postfilter_transform_->ProcessChunk(data->channels(0), final_mask_); | 
|  | 407 | 
|  | 408   // Ramp up/down for smoothing is needed in order to avoid discontinuities in | 
|  | 409   // the transitions between 10 ms frames. | 
|  | 410   const float ramp_increment = | 
|  | 411       (high_pass_postfilter_mask_ - old_high_pass_mask_) / | 
|  | 412       data->num_frames_per_band(); | 
|  | 413   for (size_t i = 1; i < data->num_bands(); ++i) { | 
|  | 414     float smoothed_mask = old_high_pass_mask_; | 
|  | 415     for (size_t j = 0; j < data->num_frames_per_band(); ++j) { | 
|  | 416       smoothed_mask += ramp_increment; | 
|  | 417       for (size_t k = 0; k < num_postfilter_channels_; ++k) { | 
|  | 418         data->channels(i)[k][j] *= smoothed_mask; | 
|  | 419       } | 
|  | 420     } | 
|  | 421   } | 
|  | 422 } | 
|  | 423 | 
| 369 void NonlinearBeamformer::ProcessChunk(const ChannelBuffer<float>& input, | 424 void NonlinearBeamformer::ProcessChunk(const ChannelBuffer<float>& input, | 
| 370                                        ChannelBuffer<float>* output) { | 425                                        ChannelBuffer<float>* output) { | 
| 371   RTC_DCHECK_EQ(input.num_channels(), num_input_channels_); | 426   RTC_DCHECK_GT(output->num_channels(), 0u); | 
| 372   RTC_DCHECK_EQ(input.num_frames_per_band(), chunk_length_); | 427   RTC_DCHECK_EQ(output->num_frames_per_band(), input.num_frames_per_band()); | 
| 373 | 428   AnalyzeChunk(input); | 
| 374   float old_high_pass_mask = high_pass_postfilter_mask_; | 429   for (size_t i = 0u; i < input.num_bands(); ++i) { | 
| 375   lapped_transform_->ProcessChunk(input.channels(0), output->channels(0)); | 430     std::memcpy(output->channels(i)[0], input.channels(i)[0], | 
| 376   // Ramp up/down for smoothing. 1 mask per 10ms results in audible | 431         sizeof(input.channels(0)[0][0]) * input.num_frames_per_band()); | 
| 377   // discontinuities. |  | 
| 378   const float ramp_increment = |  | 
| 379       (high_pass_postfilter_mask_ - old_high_pass_mask) / |  | 
| 380       input.num_frames_per_band(); |  | 
| 381   // Apply the smoothed high-pass mask to the first channel of each band. |  | 
| 382   // This can be done because the effect of the linear beamformer is negligible |  | 
| 383   // compared to the post-filter. |  | 
| 384   for (size_t i = 1; i < input.num_bands(); ++i) { |  | 
| 385     float smoothed_mask = old_high_pass_mask; |  | 
| 386     for (size_t j = 0; j < input.num_frames_per_band(); ++j) { |  | 
| 387       smoothed_mask += ramp_increment; |  | 
| 388       output->channels(i)[0][j] = input.channels(i)[0][j] * smoothed_mask; |  | 
| 389     } |  | 
| 390   } | 432   } | 
|  | 433   PostFilter(output); | 
| 391 } | 434 } | 
| 392 | 435 | 
| 393 void NonlinearBeamformer::AimAt(const SphericalPointf& target_direction) { | 436 void NonlinearBeamformer::AimAt(const SphericalPointf& target_direction) { | 
| 394   target_angle_radians_ = target_direction.azimuth(); | 437   target_angle_radians_ = target_direction.azimuth(); | 
| 395   InitHighFrequencyCorrectionRanges(); | 438   InitHighFrequencyCorrectionRanges(); | 
| 396   InitInterfAngles(); | 439   InitInterfAngles(); | 
| 397   InitDelaySumMasks(); | 440   InitDelaySumMasks(); | 
| 398   InitTargetCovMats(); | 441   InitTargetCovMats(); | 
| 399   InitInterfCovMats(); | 442   InitInterfCovMats(); | 
| 400   NormalizeCovMats(); | 443   NormalizeCovMats(); | 
| 401 } | 444 } | 
| 402 | 445 | 
| 403 bool NonlinearBeamformer::IsInBeam(const SphericalPointf& spherical_point) { | 446 bool NonlinearBeamformer::IsInBeam(const SphericalPointf& spherical_point) { | 
| 404   // If more than half-beamwidth degrees away from the beam's center, | 447   // If more than half-beamwidth degrees away from the beam's center, | 
| 405   // you are out of the beam. | 448   // you are out of the beam. | 
| 406   return fabs(spherical_point.azimuth() - target_angle_radians_) < | 449   return fabs(spherical_point.azimuth() - target_angle_radians_) < | 
| 407          kHalfBeamWidthRadians; | 450          kHalfBeamWidthRadians; | 
| 408 } | 451 } | 
| 409 | 452 | 
| 410 void NonlinearBeamformer::ProcessAudioBlock(const complex_f* const* input, | 453 void NonlinearBeamformer::ProcessAudioBlock(const complex_f* const* input, | 
| 411                                             size_t num_input_channels, | 454                                             size_t num_input_channels, | 
| 412                                             size_t num_freq_bins, | 455                                             size_t num_freq_bins, | 
| 413                                             size_t num_output_channels, | 456                                             size_t num_output_channels, | 
| 414                                             complex_f* const* output) { | 457                                             complex_f* const* output) { | 
| 415   RTC_CHECK_EQ(kNumFreqBins, num_freq_bins); | 458   RTC_CHECK_EQ(kNumFreqBins, num_freq_bins); | 
| 416   RTC_CHECK_EQ(num_input_channels_, num_input_channels); | 459   RTC_CHECK_EQ(num_input_channels_, num_input_channels); | 
| 417   RTC_CHECK_EQ(1u, num_output_channels); | 460   RTC_CHECK_EQ(0u, num_output_channels); | 
| 418 | 461 | 
| 419   // Calculating the post-filter masks. Note that we need two for each | 462   // Calculating the post-filter masks. Note that we need two for each | 
| 420   // frequency bin to account for the positive and negative interferer | 463   // frequency bin to account for the positive and negative interferer | 
| 421   // angle. | 464   // angle. | 
| 422   for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { | 465   for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { | 
| 423     eig_m_.CopyFromColumn(input, i, num_input_channels_); | 466     eig_m_.CopyFromColumn(input, i, num_input_channels_); | 
| 424     float eig_m_norm_factor = std::sqrt(SumSquares(eig_m_)); | 467     float eig_m_norm_factor = std::sqrt(SumSquares(eig_m_)); | 
| 425     if (eig_m_norm_factor != 0.f) { | 468     if (eig_m_norm_factor != 0.f) { | 
| 426       eig_m_.Scale(1.f / eig_m_norm_factor); | 469       eig_m_.Scale(1.f / eig_m_norm_factor); | 
| 427     } | 470     } | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 449         new_mask_[i] = tmp_mask; | 492         new_mask_[i] = tmp_mask; | 
| 450       } | 493       } | 
| 451     } | 494     } | 
| 452   } | 495   } | 
| 453 | 496 | 
| 454   ApplyMaskTimeSmoothing(); | 497   ApplyMaskTimeSmoothing(); | 
| 455   EstimateTargetPresence(); | 498   EstimateTargetPresence(); | 
| 456   ApplyLowFrequencyCorrection(); | 499   ApplyLowFrequencyCorrection(); | 
| 457   ApplyHighFrequencyCorrection(); | 500   ApplyHighFrequencyCorrection(); | 
| 458   ApplyMaskFrequencySmoothing(); | 501   ApplyMaskFrequencySmoothing(); | 
| 459   ApplyMasks(input, output); |  | 
| 460 } | 502 } | 
| 461 | 503 | 
| 462 float NonlinearBeamformer::CalculatePostfilterMask( | 504 float NonlinearBeamformer::CalculatePostfilterMask( | 
| 463     const ComplexMatrixF& interf_cov_mat, | 505     const ComplexMatrixF& interf_cov_mat, | 
| 464     float rpsiw, | 506     float rpsiw, | 
| 465     float ratio_rxiw_rxim, | 507     float ratio_rxiw_rxim, | 
| 466     float rmw_r) { | 508     float rmw_r) { | 
| 467   float rpsim = Norm(interf_cov_mat, eig_m_); | 509   float rpsim = Norm(interf_cov_mat, eig_m_); | 
| 468 | 510 | 
| 469   float ratio = 0.f; | 511   float ratio = 0.f; | 
| 470   if (rpsim > 0.f) { | 512   if (rpsim > 0.f) { | 
| 471     ratio = rpsiw / rpsim; | 513     ratio = rpsiw / rpsim; | 
| 472   } | 514   } | 
| 473 | 515 | 
| 474   float numerator = 1.f - kCutOffConstant; | 516   float numerator = 1.f - kCutOffConstant; | 
| 475   if (rmw_r > 0.f) { | 517   if (rmw_r > 0.f) { | 
| 476     numerator = 1.f - std::min(kCutOffConstant, ratio / rmw_r); | 518     numerator = 1.f - std::min(kCutOffConstant, ratio / rmw_r); | 
| 477   } | 519   } | 
| 478 | 520 | 
| 479   float denominator = 1.f - kCutOffConstant; | 521   float denominator = 1.f - kCutOffConstant; | 
| 480   if (ratio_rxiw_rxim > 0.f) { | 522   if (ratio_rxiw_rxim > 0.f) { | 
| 481     denominator = 1.f - std::min(kCutOffConstant, ratio / ratio_rxiw_rxim); | 523     denominator = 1.f - std::min(kCutOffConstant, ratio / ratio_rxiw_rxim); | 
| 482   } | 524   } | 
| 483 | 525 | 
| 484   return numerator / denominator; | 526   return numerator / denominator; | 
| 485 } | 527 } | 
| 486 | 528 | 
| 487 void NonlinearBeamformer::ApplyMasks(const complex_f* const* input, |  | 
| 488                                      complex_f* const* output) { |  | 
| 489   complex_f* output_channel = output[0]; |  | 
| 490   for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { |  | 
| 491     output_channel[f_ix] = complex_f(0.f, 0.f); |  | 
| 492 |  | 
| 493     const complex_f* delay_sum_mask_els = |  | 
| 494         normalized_delay_sum_masks_[f_ix].elements()[0]; |  | 
| 495     for (size_t c_ix = 0; c_ix < num_input_channels_; ++c_ix) { |  | 
| 496       output_channel[f_ix] += input[c_ix][f_ix] * delay_sum_mask_els[c_ix]; |  | 
| 497     } |  | 
| 498 |  | 
| 499     output_channel[f_ix] *= kCompensationGain * final_mask_[f_ix]; |  | 
| 500   } |  | 
| 501 } |  | 
| 502 |  | 
| 503 // Smooth new_mask_ into time_smooth_mask_. | 529 // Smooth new_mask_ into time_smooth_mask_. | 
| 504 void NonlinearBeamformer::ApplyMaskTimeSmoothing() { | 530 void NonlinearBeamformer::ApplyMaskTimeSmoothing() { | 
| 505   for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { | 531   for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { | 
| 506     time_smooth_mask_[i] = kMaskTimeSmoothAlpha * new_mask_[i] + | 532     time_smooth_mask_[i] = kMaskTimeSmoothAlpha * new_mask_[i] + | 
| 507                            (1 - kMaskTimeSmoothAlpha) * time_smooth_mask_[i]; | 533                            (1 - kMaskTimeSmoothAlpha) * time_smooth_mask_[i]; | 
| 508   } | 534   } | 
| 509 } | 535 } | 
| 510 | 536 | 
| 511 // Copy time_smooth_mask_ to final_mask_ and smooth over frequency. | 537 // Copy time_smooth_mask_ to final_mask_ and smooth over frequency. | 
| 512 void NonlinearBeamformer::ApplyMaskFrequencySmoothing() { | 538 void NonlinearBeamformer::ApplyMaskFrequencySmoothing() { | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 570                    new_mask_ + high_mean_end_bin_ + 1); | 596                    new_mask_ + high_mean_end_bin_ + 1); | 
| 571   if (new_mask_[quantile] > kMaskTargetThreshold) { | 597   if (new_mask_[quantile] > kMaskTargetThreshold) { | 
| 572     is_target_present_ = true; | 598     is_target_present_ = true; | 
| 573     interference_blocks_count_ = 0; | 599     interference_blocks_count_ = 0; | 
| 574   } else { | 600   } else { | 
| 575     is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; | 601     is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; | 
| 576   } | 602   } | 
| 577 } | 603 } | 
| 578 | 604 | 
| 579 }  // namespace webrtc | 605 }  // namespace webrtc | 
| OLD | NEW | 
|---|