| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 // To compensate for the attenuation this algorithm introduces to the target | 72 // To compensate for the attenuation this algorithm introduces to the target |
| 73 // signal. It was estimated empirically from a low-noise low-reverberation | 73 // signal. It was estimated empirically from a low-noise low-reverberation |
| 74 // recording from broadside. | 74 // recording from broadside. |
| 75 const float kCompensationGain = 2.f; | 75 const float kCompensationGain = 2.f; |
| 76 | 76 |
| 77 // Does conjugate(|norm_mat|) * |mat| * transpose(|norm_mat|). No extra space is | 77 // Does conjugate(|norm_mat|) * |mat| * transpose(|norm_mat|). No extra space is |
| 78 // used; to accomplish this, we compute both multiplications in the same loop. | 78 // used; to accomplish this, we compute both multiplications in the same loop. |
| 79 // The returned norm is clamped to be non-negative. | 79 // The returned norm is clamped to be non-negative. |
| 80 float Norm(const ComplexMatrix<float>& mat, | 80 float Norm(const ComplexMatrix<float>& mat, |
| 81 const ComplexMatrix<float>& norm_mat) { | 81 const ComplexMatrix<float>& norm_mat) { |
| 82 RTC_CHECK_EQ(norm_mat.num_rows(), 1); | 82 RTC_CHECK_EQ(1u, norm_mat.num_rows()); |
| 83 RTC_CHECK_EQ(norm_mat.num_columns(), mat.num_rows()); | 83 RTC_CHECK_EQ(norm_mat.num_columns(), mat.num_rows()); |
| 84 RTC_CHECK_EQ(norm_mat.num_columns(), mat.num_columns()); | 84 RTC_CHECK_EQ(norm_mat.num_columns(), mat.num_columns()); |
| 85 | 85 |
| 86 complex<float> first_product = complex<float>(0.f, 0.f); | 86 complex<float> first_product = complex<float>(0.f, 0.f); |
| 87 complex<float> second_product = complex<float>(0.f, 0.f); | 87 complex<float> second_product = complex<float>(0.f, 0.f); |
| 88 | 88 |
| 89 const complex<float>* const* mat_els = mat.elements(); | 89 const complex<float>* const* mat_els = mat.elements(); |
| 90 const complex<float>* const* norm_mat_els = norm_mat.elements(); | 90 const complex<float>* const* norm_mat_els = norm_mat.elements(); |
| 91 | 91 |
| 92 for (int i = 0; i < norm_mat.num_columns(); ++i) { | 92 for (size_t i = 0; i < norm_mat.num_columns(); ++i) { |
| 93 for (int j = 0; j < norm_mat.num_columns(); ++j) { | 93 for (size_t j = 0; j < norm_mat.num_columns(); ++j) { |
| 94 first_product += conj(norm_mat_els[0][j]) * mat_els[j][i]; | 94 first_product += conj(norm_mat_els[0][j]) * mat_els[j][i]; |
| 95 } | 95 } |
| 96 second_product += first_product * norm_mat_els[0][i]; | 96 second_product += first_product * norm_mat_els[0][i]; |
| 97 first_product = 0.f; | 97 first_product = 0.f; |
| 98 } | 98 } |
| 99 return std::max(second_product.real(), 0.f); | 99 return std::max(second_product.real(), 0.f); |
| 100 } | 100 } |
| 101 | 101 |
| 102 // Does conjugate(|lhs|) * |rhs| for row vectors |lhs| and |rhs|. | 102 // Does conjugate(|lhs|) * |rhs| for row vectors |lhs| and |rhs|. |
| 103 complex<float> ConjugateDotProduct(const ComplexMatrix<float>& lhs, | 103 complex<float> ConjugateDotProduct(const ComplexMatrix<float>& lhs, |
| 104 const ComplexMatrix<float>& rhs) { | 104 const ComplexMatrix<float>& rhs) { |
| 105 RTC_CHECK_EQ(lhs.num_rows(), 1); | 105 RTC_CHECK_EQ(1u, lhs.num_rows()); |
| 106 RTC_CHECK_EQ(rhs.num_rows(), 1); | 106 RTC_CHECK_EQ(1u, rhs.num_rows()); |
| 107 RTC_CHECK_EQ(lhs.num_columns(), rhs.num_columns()); | 107 RTC_CHECK_EQ(lhs.num_columns(), rhs.num_columns()); |
| 108 | 108 |
| 109 const complex<float>* const* lhs_elements = lhs.elements(); | 109 const complex<float>* const* lhs_elements = lhs.elements(); |
| 110 const complex<float>* const* rhs_elements = rhs.elements(); | 110 const complex<float>* const* rhs_elements = rhs.elements(); |
| 111 | 111 |
| 112 complex<float> result = complex<float>(0.f, 0.f); | 112 complex<float> result = complex<float>(0.f, 0.f); |
| 113 for (int i = 0; i < lhs.num_columns(); ++i) { | 113 for (size_t i = 0; i < lhs.num_columns(); ++i) { |
| 114 result += conj(lhs_elements[0][i]) * rhs_elements[0][i]; | 114 result += conj(lhs_elements[0][i]) * rhs_elements[0][i]; |
| 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. | 125 // Calculates the sum of absolute values of a complex matrix. |
| 126 float SumAbs(const ComplexMatrix<float>& mat) { | 126 float SumAbs(const ComplexMatrix<float>& mat) { |
| 127 float sum_abs = 0.f; | 127 float sum_abs = 0.f; |
| 128 const complex<float>* const* mat_els = mat.elements(); | 128 const complex<float>* const* mat_els = mat.elements(); |
| 129 for (int i = 0; i < mat.num_rows(); ++i) { | 129 for (size_t i = 0; i < mat.num_rows(); ++i) { |
| 130 for (int j = 0; j < mat.num_columns(); ++j) { | 130 for (size_t j = 0; j < mat.num_columns(); ++j) { |
| 131 sum_abs += std::abs(mat_els[i][j]); | 131 sum_abs += std::abs(mat_els[i][j]); |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 return sum_abs; | 134 return sum_abs; |
| 135 } | 135 } |
| 136 | 136 |
| 137 // Calculates the sum of squares of a complex matrix. | 137 // Calculates the sum of squares of a complex matrix. |
| 138 float SumSquares(const ComplexMatrix<float>& mat) { | 138 float SumSquares(const ComplexMatrix<float>& mat) { |
| 139 float sum_squares = 0.f; | 139 float sum_squares = 0.f; |
| 140 const complex<float>* const* mat_els = mat.elements(); | 140 const complex<float>* const* mat_els = mat.elements(); |
| 141 for (int i = 0; i < mat.num_rows(); ++i) { | 141 for (size_t i = 0; i < mat.num_rows(); ++i) { |
| 142 for (int j = 0; j < mat.num_columns(); ++j) { | 142 for (size_t j = 0; j < mat.num_columns(); ++j) { |
| 143 float abs_value = std::abs(mat_els[i][j]); | 143 float abs_value = std::abs(mat_els[i][j]); |
| 144 sum_squares += abs_value * abs_value; | 144 sum_squares += abs_value * abs_value; |
| 145 } | 145 } |
| 146 } | 146 } |
| 147 return sum_squares; | 147 return sum_squares; |
| 148 } | 148 } |
| 149 | 149 |
| 150 // Does |out| = |in|.' * conj(|in|) for row vector |in|. | 150 // Does |out| = |in|.' * conj(|in|) for row vector |in|. |
| 151 void TransposedConjugatedProduct(const ComplexMatrix<float>& in, | 151 void TransposedConjugatedProduct(const ComplexMatrix<float>& in, |
| 152 ComplexMatrix<float>* out) { | 152 ComplexMatrix<float>* out) { |
| 153 RTC_CHECK_EQ(in.num_rows(), 1); | 153 RTC_CHECK_EQ(1u, in.num_rows()); |
| 154 RTC_CHECK_EQ(out->num_rows(), in.num_columns()); | 154 RTC_CHECK_EQ(out->num_rows(), in.num_columns()); |
| 155 RTC_CHECK_EQ(out->num_columns(), in.num_columns()); | 155 RTC_CHECK_EQ(out->num_columns(), in.num_columns()); |
| 156 const complex<float>* in_elements = in.elements()[0]; | 156 const complex<float>* in_elements = in.elements()[0]; |
| 157 complex<float>* const* out_elements = out->elements(); | 157 complex<float>* const* out_elements = out->elements(); |
| 158 for (int i = 0; i < out->num_rows(); ++i) { | 158 for (size_t i = 0; i < out->num_rows(); ++i) { |
| 159 for (int j = 0; j < out->num_columns(); ++j) { | 159 for (size_t j = 0; j < out->num_columns(); ++j) { |
| 160 out_elements[i][j] = in_elements[i] * conj(in_elements[j]); | 160 out_elements[i][j] = in_elements[i] * conj(in_elements[j]); |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 } | 163 } |
| 164 | 164 |
| 165 std::vector<Point> GetCenteredArray(std::vector<Point> array_geometry) { | 165 std::vector<Point> GetCenteredArray(std::vector<Point> array_geometry) { |
| 166 for (size_t dim = 0; dim < 3; ++dim) { | 166 for (size_t dim = 0; dim < 3; ++dim) { |
| 167 float center = 0.f; | 167 float center = 0.f; |
| 168 for (size_t i = 0; i < array_geometry.size(); ++i) { | 168 for (size_t i = 0; i < array_geometry.size(); ++i) { |
| 169 center += array_geometry[i].c[dim]; | 169 center += array_geometry[i].c[dim]; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 } | 401 } |
| 402 | 402 |
| 403 bool NonlinearBeamformer::IsInBeam(const SphericalPointf& spherical_point) { | 403 bool NonlinearBeamformer::IsInBeam(const SphericalPointf& spherical_point) { |
| 404 // If more than half-beamwidth degrees away from the beam's center, | 404 // If more than half-beamwidth degrees away from the beam's center, |
| 405 // you are out of the beam. | 405 // you are out of the beam. |
| 406 return fabs(spherical_point.azimuth() - target_angle_radians_) < | 406 return fabs(spherical_point.azimuth() - target_angle_radians_) < |
| 407 kHalfBeamWidthRadians; | 407 kHalfBeamWidthRadians; |
| 408 } | 408 } |
| 409 | 409 |
| 410 void NonlinearBeamformer::ProcessAudioBlock(const complex_f* const* input, | 410 void NonlinearBeamformer::ProcessAudioBlock(const complex_f* const* input, |
| 411 int num_input_channels, | 411 size_t num_input_channels, |
| 412 size_t num_freq_bins, | 412 size_t num_freq_bins, |
| 413 int num_output_channels, | 413 size_t num_output_channels, |
| 414 complex_f* const* output) { | 414 complex_f* const* output) { |
| 415 RTC_CHECK_EQ(kNumFreqBins, num_freq_bins); | 415 RTC_CHECK_EQ(kNumFreqBins, num_freq_bins); |
| 416 RTC_CHECK_EQ(num_input_channels_, num_input_channels); | 416 RTC_CHECK_EQ(num_input_channels_, num_input_channels); |
| 417 RTC_CHECK_EQ(1, num_output_channels); | 417 RTC_CHECK_EQ(1u, num_output_channels); |
| 418 | 418 |
| 419 // Calculating the post-filter masks. Note that we need two for each | 419 // Calculating the post-filter masks. Note that we need two for each |
| 420 // frequency bin to account for the positive and negative interferer | 420 // frequency bin to account for the positive and negative interferer |
| 421 // angle. | 421 // angle. |
| 422 for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { | 422 for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { |
| 423 eig_m_.CopyFromColumn(input, i, num_input_channels_); | 423 eig_m_.CopyFromColumn(input, i, num_input_channels_); |
| 424 float eig_m_norm_factor = std::sqrt(SumSquares(eig_m_)); | 424 float eig_m_norm_factor = std::sqrt(SumSquares(eig_m_)); |
| 425 if (eig_m_norm_factor != 0.f) { | 425 if (eig_m_norm_factor != 0.f) { |
| 426 eig_m_.Scale(1.f / eig_m_norm_factor); | 426 eig_m_.Scale(1.f / eig_m_norm_factor); |
| 427 } | 427 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 } | 476 } |
| 477 | 477 |
| 478 void NonlinearBeamformer::ApplyMasks(const complex_f* const* input, | 478 void NonlinearBeamformer::ApplyMasks(const complex_f* const* input, |
| 479 complex_f* const* output) { | 479 complex_f* const* output) { |
| 480 complex_f* output_channel = output[0]; | 480 complex_f* output_channel = output[0]; |
| 481 for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { | 481 for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { |
| 482 output_channel[f_ix] = complex_f(0.f, 0.f); | 482 output_channel[f_ix] = complex_f(0.f, 0.f); |
| 483 | 483 |
| 484 const complex_f* delay_sum_mask_els = | 484 const complex_f* delay_sum_mask_els = |
| 485 normalized_delay_sum_masks_[f_ix].elements()[0]; | 485 normalized_delay_sum_masks_[f_ix].elements()[0]; |
| 486 for (int c_ix = 0; c_ix < num_input_channels_; ++c_ix) { | 486 for (size_t c_ix = 0; c_ix < num_input_channels_; ++c_ix) { |
| 487 output_channel[f_ix] += input[c_ix][f_ix] * delay_sum_mask_els[c_ix]; | 487 output_channel[f_ix] += input[c_ix][f_ix] * delay_sum_mask_els[c_ix]; |
| 488 } | 488 } |
| 489 | 489 |
| 490 output_channel[f_ix] *= kCompensationGain * final_mask_[f_ix]; | 490 output_channel[f_ix] *= kCompensationGain * final_mask_[f_ix]; |
| 491 } | 491 } |
| 492 } | 492 } |
| 493 | 493 |
| 494 // Smooth new_mask_ into time_smooth_mask_. | 494 // Smooth new_mask_ into time_smooth_mask_. |
| 495 void NonlinearBeamformer::ApplyMaskTimeSmoothing() { | 495 void NonlinearBeamformer::ApplyMaskTimeSmoothing() { |
| 496 for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { | 496 for (size_t i = low_mean_start_bin_; i <= high_mean_end_bin_; ++i) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 new_mask_ + high_mean_end_bin_ + 1); | 561 new_mask_ + high_mean_end_bin_ + 1); |
| 562 if (new_mask_[quantile] > kMaskTargetThreshold) { | 562 if (new_mask_[quantile] > kMaskTargetThreshold) { |
| 563 is_target_present_ = true; | 563 is_target_present_ = true; |
| 564 interference_blocks_count_ = 0; | 564 interference_blocks_count_ = 0; |
| 565 } else { | 565 } else { |
| 566 is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; | 566 is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; |
| 567 } | 567 } |
| 568 } | 568 } |
| 569 | 569 |
| 570 } // namespace webrtc | 570 } // namespace webrtc |
| OLD | NEW |