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 |