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 18 matching lines...) Expand all Loading... | |
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 | 32 // For both target and interference angles, PI / 2 is perpendicular to the |
33 // microphone array, facing forwards. The positive direction goes | 33 // microphone array, facing forwards. The positive direction goes |
34 // counterclockwise. | 34 // counterclockwise. |
35 // The angle at which we amplify sound. | 35 // The angle at which we amplify sound. |
36 // TODO(aluebs): Make the target angle dynamically settable. | 36 // TODO(aluebs): Make the target angle dynamically settable. |
37 const float kTargetAngleRadians = static_cast<float>(M_PI) / 2.f; | 37 const float kTargetAngleRadians = static_cast<float>(M_PI) / 2.f; |
38 | 38 |
39 // The minimum separation in radians between the target direction and a | |
Andrew MacDonald
2015/10/14 23:38:53
and an interferer
aluebs-webrtc
2015/10/17 00:54:49
Done.
| |
40 // interferer scenario. | |
41 const float kMinAwayRadians = 0.2f; | |
42 | |
43 // The separation between the target direction and the closest interferer | |
44 // scenario is proportional to this constant. | |
45 const float kAwaySlope = 0.008f; | |
46 | |
39 // When calculating the interference covariance matrix, this is the weight for | 47 // When calculating the interference covariance matrix, this is the weight for |
40 // the weighted average between the uniform covariance matrix and the angled | 48 // the weighted average between the uniform covariance matrix and the angled |
41 // covariance matrix. | 49 // covariance matrix. |
42 // Rpsi = Rpsi_angled * kBalance + Rpsi_uniform * (1 - kBalance) | 50 // Rpsi = Rpsi_angled * kBalance + Rpsi_uniform * (1 - kBalance) |
43 const float kBalance = 0.95f; | 51 const float kBalance = 0.95f; |
44 | 52 |
45 const float kHalfBeamWidthRadians = static_cast<float>(M_PI) * 20.f / 180.f; | 53 const float kHalfBeamWidthRadians = static_cast<float>(M_PI) * 20.f / 180.f; |
46 | 54 |
47 // Alpha coefficients for mask smoothing. | 55 // Alpha coefficients for mask smoothing. |
48 const float kMaskTimeSmoothAlpha = 0.2f; | 56 const float kMaskTimeSmoothAlpha = 0.2f; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 center += array_geometry[i].c[dim]; | 184 center += array_geometry[i].c[dim]; |
177 } | 185 } |
178 center /= array_geometry.size(); | 186 center /= array_geometry.size(); |
179 for (size_t i = 0; i < array_geometry.size(); ++i) { | 187 for (size_t i = 0; i < array_geometry.size(); ++i) { |
180 array_geometry[i].c[dim] -= center; | 188 array_geometry[i].c[dim] -= center; |
181 } | 189 } |
182 } | 190 } |
183 return array_geometry; | 191 return array_geometry; |
184 } | 192 } |
185 | 193 |
194 float GetMinimumSpacing(std::vector<Point> array_geometry) { | |
Andrew MacDonald
2015/10/14 23:38:53
const reference
aluebs-webrtc
2015/10/17 00:54:50
Done.
| |
195 float mic_spacing = Distance(array_geometry[0], array_geometry[1]); | |
196 for (size_t i = 0; i < (array_geometry.size() - 1); ++i) { | |
197 for (size_t j = i + 1; j < array_geometry.size(); ++j) { | |
198 float distance = Distance(array_geometry[i], array_geometry[j]); | |
Andrew MacDonald
2015/10/14 23:38:53
Not a big deal, but you're computing the first dis
aluebs-webrtc
2015/10/17 00:54:49
Good suggestion. Done.
| |
199 if (distance < mic_spacing) { | |
200 mic_spacing = distance; | |
201 } | |
202 } | |
203 } | |
204 return mic_spacing; | |
205 } | |
206 | |
186 } // namespace | 207 } // namespace |
187 | 208 |
188 // static | 209 // static |
189 const size_t NonlinearBeamformer::kNumFreqBins; | 210 const size_t NonlinearBeamformer::kNumFreqBins; |
190 | 211 |
191 NonlinearBeamformer::NonlinearBeamformer( | 212 NonlinearBeamformer::NonlinearBeamformer( |
192 const std::vector<Point>& array_geometry) | 213 const std::vector<Point>& array_geometry) |
193 : num_input_channels_(array_geometry.size()), | 214 : num_input_channels_(array_geometry.size()), |
194 array_geometry_(GetCenteredArray(array_geometry)) { | 215 array_geometry_(GetCenteredArray(array_geometry)), |
216 mic_spacing_(GetMinimumSpacing(array_geometry)) { | |
195 WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_); | 217 WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_); |
196 } | 218 } |
197 | 219 |
198 void NonlinearBeamformer::Initialize(int chunk_size_ms, int sample_rate_hz) { | 220 void NonlinearBeamformer::Initialize(int chunk_size_ms, int sample_rate_hz) { |
199 chunk_length_ = | 221 chunk_length_ = |
200 static_cast<size_t>(sample_rate_hz / (1000.f / chunk_size_ms)); | 222 static_cast<size_t>(sample_rate_hz / (1000.f / chunk_size_ms)); |
201 sample_rate_hz_ = sample_rate_hz; | 223 sample_rate_hz_ = sample_rate_hz; |
202 low_mean_start_bin_ = Round(kLowMeanStartHz * kFftSize / sample_rate_hz_); | 224 low_mean_start_bin_ = Round(kLowMeanStartHz * kFftSize / sample_rate_hz_); |
203 low_mean_end_bin_ = Round(kLowMeanEndHz * kFftSize / sample_rate_hz_); | 225 low_mean_end_bin_ = Round(kLowMeanEndHz * kFftSize / sample_rate_hz_); |
204 high_mean_start_bin_ = Round(kHighMeanStartHz * kFftSize / sample_rate_hz_); | 226 high_mean_start_bin_ = Round(kHighMeanStartHz * kFftSize / sample_rate_hz_); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 for (size_t i = 0; i < kNumFreqBins; ++i) { | 269 for (size_t i = 0; i < kNumFreqBins; ++i) { |
248 rxiws_[i] = Norm(target_cov_mats_[i], delay_sum_masks_[i]); | 270 rxiws_[i] = Norm(target_cov_mats_[i], delay_sum_masks_[i]); |
249 rpsiws_[i].clear(); | 271 rpsiws_[i].clear(); |
250 for (size_t j = 0; j < interf_angles_radians_.size(); ++j) { | 272 for (size_t j = 0; j < interf_angles_radians_.size(); ++j) { |
251 rpsiws_[i].push_back(Norm(*interf_cov_mats_[i][j], delay_sum_masks_[i])); | 273 rpsiws_[i].push_back(Norm(*interf_cov_mats_[i][j], delay_sum_masks_[i])); |
252 } | 274 } |
253 } | 275 } |
254 } | 276 } |
255 | 277 |
256 void NonlinearBeamformer::InitInterfAngles() { | 278 void NonlinearBeamformer::InitInterfAngles() { |
257 // TODO(aluebs): Make kAway dependent on the mic spacing. | 279 const float kAway = |
258 const float kAway = 0.5; | 280 std::min(static_cast<float>(M_PI), |
281 std::max(kMinAwayRadians, | |
282 kAwaySlope * static_cast<float>(M_PI) / mic_spacing_)); | |
259 | 283 |
260 interf_angles_radians_.clear(); | 284 interf_angles_radians_.clear(); |
261 // TODO(aluebs): When the target angle is settable, make sure the interferer | 285 // TODO(aluebs): When the target angle is settable, make sure the interferer |
262 // scenarios aren't reflected over the target one for linear geometries. | 286 // scenarios aren't reflected over the target one for linear geometries. |
263 interf_angles_radians_.push_back(kTargetAngleRadians - kAway); | 287 interf_angles_radians_.push_back(kTargetAngleRadians - kAway); |
264 interf_angles_radians_.push_back(kTargetAngleRadians + kAway); | 288 interf_angles_radians_.push_back(kTargetAngleRadians + kAway); |
265 } | 289 } |
266 | 290 |
267 void NonlinearBeamformer::InitDelaySumMasks() { | 291 void NonlinearBeamformer::InitDelaySumMasks() { |
268 for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { | 292 for (size_t f_ix = 0; f_ix < kNumFreqBins; ++f_ix) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 new_mask_ + high_mean_end_bin_ + 1); | 539 new_mask_ + high_mean_end_bin_ + 1); |
516 if (new_mask_[quantile] > kMaskTargetThreshold) { | 540 if (new_mask_[quantile] > kMaskTargetThreshold) { |
517 is_target_present_ = true; | 541 is_target_present_ = true; |
518 interference_blocks_count_ = 0; | 542 interference_blocks_count_ = 0; |
519 } else { | 543 } else { |
520 is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; | 544 is_target_present_ = interference_blocks_count_++ < hold_target_blocks_; |
521 } | 545 } |
522 } | 546 } |
523 | 547 |
524 } // namespace webrtc | 548 } // namespace webrtc |
OLD | NEW |