OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 |
11 #include <string.h> | 11 #include <string.h> |
12 | 12 |
13 #include <limits> | 13 #include <limits> |
14 #include <memory> | 14 #include <memory> |
| 15 #include <sstream> |
| 16 #include <string> |
15 #include <utility> | 17 #include <utility> |
16 | 18 |
17 #include "webrtc/api/audio/audio_mixer.h" | 19 #include "webrtc/api/audio/audio_mixer.h" |
18 #include "webrtc/base/bind.h" | 20 #include "webrtc/base/bind.h" |
| 21 #include "webrtc/base/checks.h" |
19 #include "webrtc/base/thread.h" | 22 #include "webrtc/base/thread.h" |
20 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" | 23 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" |
21 #include "webrtc/modules/audio_mixer/default_output_rate_calculator.h" | 24 #include "webrtc/modules/audio_mixer/default_output_rate_calculator.h" |
22 #include "webrtc/test/gmock.h" | 25 #include "webrtc/test/gmock.h" |
23 | 26 |
24 using testing::_; | 27 using testing::_; |
25 using testing::Exactly; | 28 using testing::Exactly; |
26 using testing::Invoke; | 29 using testing::Invoke; |
27 using testing::Return; | 30 using testing::Return; |
28 | 31 |
(...skipping 10 matching lines...) Expand all Loading... |
39 frame->id_ = kId; | 42 frame->id_ = kId; |
40 frame->sample_rate_hz_ = kDefaultSampleRateHz; | 43 frame->sample_rate_hz_ = kDefaultSampleRateHz; |
41 frame->num_channels_ = 1; | 44 frame->num_channels_ = 1; |
42 | 45 |
43 // Frame duration 10ms. | 46 // Frame duration 10ms. |
44 frame->samples_per_channel_ = kDefaultSampleRateHz / 100; | 47 frame->samples_per_channel_ = kDefaultSampleRateHz / 100; |
45 frame->vad_activity_ = AudioFrame::kVadActive; | 48 frame->vad_activity_ = AudioFrame::kVadActive; |
46 frame->speech_type_ = AudioFrame::kNormalSpeech; | 49 frame->speech_type_ = AudioFrame::kNormalSpeech; |
47 } | 50 } |
48 | 51 |
| 52 std::string ProduceDebugText(int sample_rate_hz, |
| 53 int number_of_channels, |
| 54 int number_of_sources) { |
| 55 std::ostringstream ss; |
| 56 ss << "Sample rate: " << sample_rate_hz << " "; |
| 57 ss << "Number of channels: " << number_of_channels << " "; |
| 58 ss << "Number of sources: " << number_of_sources; |
| 59 return ss.str(); |
| 60 } |
| 61 |
49 AudioFrame frame_for_mixing; | 62 AudioFrame frame_for_mixing; |
50 | 63 |
51 } // namespace | 64 } // namespace |
52 | 65 |
53 class MockMixerAudioSource : public AudioMixer::Source { | 66 class MockMixerAudioSource : public AudioMixer::Source { |
54 public: | 67 public: |
55 MockMixerAudioSource() | 68 MockMixerAudioSource() |
56 : fake_audio_frame_info_(AudioMixer::Source::AudioFrameInfo::kNormal) { | 69 : fake_audio_frame_info_(AudioMixer::Source::AudioFrameInfo::kNormal) { |
57 ON_CALL(*this, GetAudioFrameWithInfo(_, _)) | 70 ON_CALL(*this, GetAudioFrameWithInfo(_, _)) |
58 .WillByDefault( | 71 .WillByDefault( |
(...skipping 12 matching lines...) Expand all Loading... |
71 AudioFrameInfo fake_info() { return fake_audio_frame_info_; } | 84 AudioFrameInfo fake_info() { return fake_audio_frame_info_; } |
72 void set_fake_info(const AudioFrameInfo audio_frame_info) { | 85 void set_fake_info(const AudioFrameInfo audio_frame_info) { |
73 fake_audio_frame_info_ = audio_frame_info; | 86 fake_audio_frame_info_ = audio_frame_info; |
74 } | 87 } |
75 | 88 |
76 private: | 89 private: |
77 AudioFrameInfo FakeAudioFrameWithInfo(int sample_rate_hz, | 90 AudioFrameInfo FakeAudioFrameWithInfo(int sample_rate_hz, |
78 AudioFrame* audio_frame) { | 91 AudioFrame* audio_frame) { |
79 audio_frame->CopyFrom(fake_frame_); | 92 audio_frame->CopyFrom(fake_frame_); |
80 audio_frame->sample_rate_hz_ = sample_rate_hz; | 93 audio_frame->sample_rate_hz_ = sample_rate_hz; |
81 audio_frame->samples_per_channel_ = sample_rate_hz / 100; | 94 audio_frame->samples_per_channel_ = |
| 95 rtc::CheckedDivExact(sample_rate_hz, 100); |
82 return fake_info(); | 96 return fake_info(); |
83 } | 97 } |
84 | 98 |
85 AudioFrame fake_frame_; | 99 AudioFrame fake_frame_; |
86 AudioFrameInfo fake_audio_frame_info_; | 100 AudioFrameInfo fake_audio_frame_info_; |
87 }; | 101 }; |
88 | 102 |
89 class CustomRateCalculator : public OutputRateCalculator { | 103 class CustomRateCalculator : public OutputRateCalculator { |
90 public: | 104 public: |
91 explicit CustomRateCalculator(int rate) : rate_(rate) {} | 105 explicit CustomRateCalculator(int rate) : rate_(rate) {} |
92 int CalculateOutputRate(const std::vector<int>& preferred_rates) { | 106 int CalculateOutputRate(const std::vector<int>& preferred_rates) override { |
93 return rate_; | 107 return rate_; |
94 } | 108 } |
95 | 109 |
96 private: | 110 private: |
97 const int rate_; | 111 const int rate_; |
98 }; | 112 }; |
99 | 113 |
100 // Creates participants from |frames| and |frame_info| and adds them | 114 // Creates participants from |frames| and |frame_info| and adds them |
101 // to the mixer. Compares mixed status with |expected_status| | 115 // to the mixer. Compares mixed status with |expected_status| |
102 void MixAndCompare( | 116 void MixAndCompare( |
103 const std::vector<AudioFrame>& frames, | 117 const std::vector<AudioFrame>& frames, |
104 const std::vector<AudioMixer::Source::AudioFrameInfo>& frame_info, | 118 const std::vector<AudioMixer::Source::AudioFrameInfo>& frame_info, |
105 const std::vector<bool>& expected_status) { | 119 const std::vector<bool>& expected_status) { |
106 int num_audio_sources = frames.size(); | 120 const size_t num_audio_sources = frames.size(); |
107 RTC_DCHECK(frames.size() == frame_info.size()); | 121 RTC_DCHECK(frames.size() == frame_info.size()); |
108 RTC_DCHECK(frame_info.size() == expected_status.size()); | 122 RTC_DCHECK(frame_info.size() == expected_status.size()); |
109 | 123 |
110 const auto mixer = AudioMixerImpl::Create(); | 124 const auto mixer = AudioMixerImpl::Create(); |
111 std::vector<MockMixerAudioSource> participants(num_audio_sources); | 125 std::vector<MockMixerAudioSource> participants(num_audio_sources); |
112 | 126 |
113 for (int i = 0; i < num_audio_sources; i++) { | 127 for (size_t i = 0; i < num_audio_sources; ++i) { |
114 participants[i].fake_frame()->CopyFrom(frames[i]); | 128 participants[i].fake_frame()->CopyFrom(frames[i]); |
115 participants[i].set_fake_info(frame_info[i]); | 129 participants[i].set_fake_info(frame_info[i]); |
116 } | 130 } |
117 | 131 |
118 for (int i = 0; i < num_audio_sources; i++) { | 132 for (size_t i = 0; i < num_audio_sources; ++i) { |
119 EXPECT_TRUE(mixer->AddSource(&participants[i])); | 133 EXPECT_TRUE(mixer->AddSource(&participants[i])); |
120 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _)) | 134 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _)) |
121 .Times(Exactly(1)); | 135 .Times(Exactly(1)); |
122 } | 136 } |
123 | 137 |
124 mixer->Mix(1, &frame_for_mixing); | 138 mixer->Mix(1, &frame_for_mixing); |
125 | 139 |
126 for (int i = 0; i < num_audio_sources; i++) { | 140 for (size_t i = 0; i < num_audio_sources; ++i) { |
127 EXPECT_EQ(expected_status[i], | 141 EXPECT_EQ(expected_status[i], |
128 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i])) | 142 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i])) |
129 << "Mixed status of AudioSource #" << i << " wrong."; | 143 << "Mixed status of AudioSource #" << i << " wrong."; |
130 } | 144 } |
131 } | 145 } |
132 | 146 |
133 void MixMonoAtGivenNativeRate(int native_sample_rate, | 147 void MixMonoAtGivenNativeRate(int native_sample_rate, |
134 AudioFrame* mix_frame, | 148 AudioFrame* mix_frame, |
135 rtc::scoped_refptr<AudioMixer> mixer, | 149 rtc::scoped_refptr<AudioMixer> mixer, |
136 MockMixerAudioSource* audio_source) { | 150 MockMixerAudioSource* audio_source) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 } | 198 } |
185 } | 199 } |
186 } | 200 } |
187 | 201 |
188 TEST(AudioMixer, FrameNotModifiedForSingleParticipant) { | 202 TEST(AudioMixer, FrameNotModifiedForSingleParticipant) { |
189 const auto mixer = AudioMixerImpl::Create(); | 203 const auto mixer = AudioMixerImpl::Create(); |
190 | 204 |
191 MockMixerAudioSource participant; | 205 MockMixerAudioSource participant; |
192 | 206 |
193 ResetFrame(participant.fake_frame()); | 207 ResetFrame(participant.fake_frame()); |
194 const int n_samples = participant.fake_frame()->samples_per_channel_; | 208 const size_t n_samples = participant.fake_frame()->samples_per_channel_; |
195 | 209 |
196 // Modify the frame so that it's not zero. | 210 // Modify the frame so that it's not zero. |
197 for (int j = 0; j < n_samples; j++) { | 211 for (size_t j = 0; j < n_samples; ++j) { |
198 participant.fake_frame()->data_[j] = j; | 212 participant.fake_frame()->data_[j] = static_cast<int16_t>(j); |
199 } | 213 } |
200 | 214 |
201 EXPECT_TRUE(mixer->AddSource(&participant)); | 215 EXPECT_TRUE(mixer->AddSource(&participant)); |
202 EXPECT_CALL(participant, GetAudioFrameWithInfo(_, _)).Times(Exactly(2)); | 216 EXPECT_CALL(participant, GetAudioFrameWithInfo(_, _)).Times(Exactly(2)); |
203 | 217 |
204 AudioFrame audio_frame; | 218 AudioFrame audio_frame; |
205 // Two mix iteration to compare after the ramp-up step. | 219 // Two mix iteration to compare after the ramp-up step. |
206 for (int i = 0; i < 2; i++) { | 220 for (int i = 0; i < 2; ++i) { |
207 mixer->Mix(1, // number of channels | 221 mixer->Mix(1, // number of channels |
208 &audio_frame); | 222 &audio_frame); |
209 } | 223 } |
210 | 224 |
211 EXPECT_EQ( | 225 EXPECT_EQ( |
212 0, memcmp(participant.fake_frame()->data_, audio_frame.data_, n_samples)); | 226 0, memcmp(participant.fake_frame()->data_, audio_frame.data_, n_samples)); |
213 } | 227 } |
214 | 228 |
215 TEST(AudioMixer, SourceAtNativeRateShouldNeverResample) { | 229 TEST(AudioMixer, SourceAtNativeRateShouldNeverResample) { |
216 const auto mixer = AudioMixerImpl::Create(); | 230 const auto mixer = AudioMixerImpl::Create(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 317 |
304 // Maximal amount of participants are mixed one iteration, then | 318 // Maximal amount of participants are mixed one iteration, then |
305 // another participant with higher energy is added. | 319 // another participant with higher energy is added. |
306 TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) { | 320 TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) { |
307 constexpr int kAudioSources = | 321 constexpr int kAudioSources = |
308 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1; | 322 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1; |
309 | 323 |
310 const auto mixer = AudioMixerImpl::Create(); | 324 const auto mixer = AudioMixerImpl::Create(); |
311 MockMixerAudioSource participants[kAudioSources]; | 325 MockMixerAudioSource participants[kAudioSources]; |
312 | 326 |
313 for (int i = 0; i < kAudioSources; i++) { | 327 for (int i = 0; i < kAudioSources; ++i) { |
314 ResetFrame(participants[i].fake_frame()); | 328 ResetFrame(participants[i].fake_frame()); |
315 // Set the participant audio energy to increase with the index | 329 // Set the participant audio energy to increase with the index |
316 // |i|. | 330 // |i|. |
317 participants[i].fake_frame()->data_[0] = 100 * i; | 331 participants[i].fake_frame()->data_[0] = 100 * i; |
318 } | 332 } |
319 | 333 |
320 // Add all participants but the loudest for mixing. | 334 // Add all participants but the loudest for mixing. |
321 for (int i = 0; i < kAudioSources - 1; i++) { | 335 for (int i = 0; i < kAudioSources - 1; ++i) { |
322 EXPECT_TRUE(mixer->AddSource(&participants[i])); | 336 EXPECT_TRUE(mixer->AddSource(&participants[i])); |
323 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _)) | 337 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _)) |
324 .Times(Exactly(1)); | 338 .Times(Exactly(1)); |
325 } | 339 } |
326 | 340 |
327 // First mixer iteration | 341 // First mixer iteration |
328 mixer->Mix(1, &frame_for_mixing); | 342 mixer->Mix(1, &frame_for_mixing); |
329 | 343 |
330 // All participants but the loudest should have been mixed. | 344 // All participants but the loudest should have been mixed. |
331 for (int i = 0; i < kAudioSources - 1; i++) { | 345 for (int i = 0; i < kAudioSources - 1; ++i) { |
332 EXPECT_TRUE(mixer->GetAudioSourceMixabilityStatusForTest(&participants[i])) | 346 EXPECT_TRUE(mixer->GetAudioSourceMixabilityStatusForTest(&participants[i])) |
333 << "Mixed status of AudioSource #" << i << " wrong."; | 347 << "Mixed status of AudioSource #" << i << " wrong."; |
334 } | 348 } |
335 | 349 |
336 // Add new participant with higher energy. | 350 // Add new participant with higher energy. |
337 EXPECT_TRUE(mixer->AddSource(&participants[kAudioSources - 1])); | 351 EXPECT_TRUE(mixer->AddSource(&participants[kAudioSources - 1])); |
338 for (int i = 0; i < kAudioSources; i++) { | 352 for (int i = 0; i < kAudioSources; ++i) { |
339 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _)) | 353 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _)) |
340 .Times(Exactly(1)); | 354 .Times(Exactly(1)); |
341 } | 355 } |
342 | 356 |
343 mixer->Mix(1, &frame_for_mixing); | 357 mixer->Mix(1, &frame_for_mixing); |
344 | 358 |
345 // The most quiet participant should not have been mixed. | 359 // The most quiet participant should not have been mixed. |
346 EXPECT_FALSE(mixer->GetAudioSourceMixabilityStatusForTest(&participants[0])) | 360 EXPECT_FALSE(mixer->GetAudioSourceMixabilityStatusForTest(&participants[0])) |
347 << "Mixed status of AudioSource #0 wrong."; | 361 << "Mixed status of AudioSource #0 wrong."; |
348 | 362 |
349 // The loudest participants should have been mixed. | 363 // The loudest participants should have been mixed. |
350 for (int i = 1; i < kAudioSources; i++) { | 364 for (int i = 1; i < kAudioSources; ++i) { |
351 EXPECT_EQ(true, | 365 EXPECT_EQ(true, |
352 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i])) | 366 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i])) |
353 << "Mixed status of AudioSource #" << i << " wrong."; | 367 << "Mixed status of AudioSource #" << i << " wrong."; |
354 } | 368 } |
355 } | 369 } |
356 | 370 |
357 // This test checks that the initialization and participant addition | 371 // This test checks that the initialization and participant addition |
358 // can be done on a different thread. | 372 // can be done on a different thread. |
359 TEST(AudioMixer, ConstructFromOtherThread) { | 373 TEST(AudioMixer, ConstructFromOtherThread) { |
360 std::unique_ptr<rtc::Thread> init_thread = rtc::Thread::Create(); | 374 std::unique_ptr<rtc::Thread> init_thread = rtc::Thread::Create(); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 std::fill(frames[0].data_, frames[0].data_ + kDefaultSampleRateHz / 100, | 463 std::fill(frames[0].data_, frames[0].data_ + kDefaultSampleRateHz / 100, |
450 std::numeric_limits<int16_t>::max()); | 464 std::numeric_limits<int16_t>::max()); |
451 std::vector<bool> expected_status(kAudioSources, true); | 465 std::vector<bool> expected_status(kAudioSources, true); |
452 expected_status[0] = false; | 466 expected_status[0] = false; |
453 | 467 |
454 MixAndCompare(frames, frame_info, expected_status); | 468 MixAndCompare(frames, frame_info, expected_status); |
455 } | 469 } |
456 | 470 |
457 TEST(AudioMixer, MixingRateShouldBeDecidedByRateCalculator) { | 471 TEST(AudioMixer, MixingRateShouldBeDecidedByRateCalculator) { |
458 constexpr int kOutputRate = 22000; | 472 constexpr int kOutputRate = 22000; |
459 const auto mixer = AudioMixerImpl::CreateWithOutputRateCalculator( | 473 const auto mixer = AudioMixerImpl::CreateWithOutputRateCalculatorAndLimiter( |
460 std::unique_ptr<OutputRateCalculator>( | 474 std::unique_ptr<OutputRateCalculator>( |
461 new CustomRateCalculator(kOutputRate))); | 475 new CustomRateCalculator(kOutputRate)), |
| 476 true); |
462 MockMixerAudioSource audio_source; | 477 MockMixerAudioSource audio_source; |
463 mixer->AddSource(&audio_source); | 478 mixer->AddSource(&audio_source); |
464 ResetFrame(audio_source.fake_frame()); | 479 ResetFrame(audio_source.fake_frame()); |
465 | 480 |
466 EXPECT_CALL(audio_source, GetAudioFrameWithInfo(kOutputRate, _)) | 481 EXPECT_CALL(audio_source, GetAudioFrameWithInfo(kOutputRate, _)) |
467 .Times(Exactly(1)); | 482 .Times(Exactly(1)); |
468 | 483 |
469 mixer->Mix(1, &frame_for_mixing); | 484 mixer->Mix(1, &frame_for_mixing); |
470 } | 485 } |
471 | 486 |
472 TEST(AudioMixer, ZeroSourceRateShouldBeDecidedByRateCalculator) { | 487 TEST(AudioMixer, ZeroSourceRateShouldBeDecidedByRateCalculator) { |
473 constexpr int kOutputRate = 8000; | 488 constexpr int kOutputRate = 8000; |
474 const auto mixer = AudioMixerImpl::CreateWithOutputRateCalculator( | 489 const auto mixer = AudioMixerImpl::CreateWithOutputRateCalculatorAndLimiter( |
475 std::unique_ptr<OutputRateCalculator>( | 490 std::unique_ptr<OutputRateCalculator>( |
476 new CustomRateCalculator(kOutputRate))); | 491 new CustomRateCalculator(kOutputRate)), |
| 492 true); |
477 | 493 |
478 mixer->Mix(1, &frame_for_mixing); | 494 mixer->Mix(1, &frame_for_mixing); |
479 | 495 |
480 EXPECT_EQ(kOutputRate, frame_for_mixing.sample_rate_hz_); | 496 EXPECT_EQ(kOutputRate, frame_for_mixing.sample_rate_hz_); |
481 } | 497 } |
| 498 |
| 499 TEST(AudioMixer, NoLimiterBasicApiCalls) { |
| 500 const auto mixer = AudioMixerImpl::CreateWithOutputRateCalculatorAndLimiter( |
| 501 std::unique_ptr<OutputRateCalculator>(new DefaultOutputRateCalculator()), |
| 502 false); |
| 503 mixer->Mix(1, &frame_for_mixing); |
| 504 } |
| 505 |
| 506 TEST(AudioMixer, AnyRateIsPossibleWithNoLimiter) { |
| 507 // No APM limiter means no AudioProcessing::NativeRate restriction |
| 508 // on mixing rate. The rate has to be divisible by 100 since we use |
| 509 // 10 ms frames, though. |
| 510 for (const auto rate : {8000, 20000, 24000, 32000, 44100}) { |
| 511 for (const size_t number_of_channels : {1, 2}) { |
| 512 for (const auto number_of_sources : {0, 1, 2, 3, 4}) { |
| 513 SCOPED_TRACE( |
| 514 ProduceDebugText(rate, number_of_sources, number_of_sources)); |
| 515 const auto mixer = |
| 516 AudioMixerImpl::CreateWithOutputRateCalculatorAndLimiter( |
| 517 std::unique_ptr<OutputRateCalculator>( |
| 518 new CustomRateCalculator(rate)), |
| 519 false); |
| 520 |
| 521 std::vector<MockMixerAudioSource> sources(number_of_sources); |
| 522 for (auto& source : sources) { |
| 523 mixer->AddSource(&source); |
| 524 } |
| 525 |
| 526 mixer->Mix(number_of_channels, &frame_for_mixing); |
| 527 EXPECT_EQ(rate, frame_for_mixing.sample_rate_hz_); |
| 528 EXPECT_EQ(number_of_channels, frame_for_mixing.num_channels_); |
| 529 } |
| 530 } |
| 531 } |
| 532 } |
482 } // namespace webrtc | 533 } // namespace webrtc |
OLD | NEW |