Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: webrtc/modules/audio_mixer/audio_mixer_impl_unittest.cc

Issue 2692333002: Optionally disable APM limiter in AudioMixer. (Closed)
Patch Set: Fix int16_t <-> size_t compilation warnings. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « webrtc/modules/audio_mixer/audio_mixer_impl.cc ('k') | webrtc/modules/audio_mixer/frame_combiner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698