blob: e14b69e984f6efbe0d8619725ee76c5ac5f354fc [file] [log] [blame]
aleloi09f45102016-07-28 03:52:15 -07001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
aleloi311525e2016-09-07 06:13:12 -070011#include <string.h>
12
aleloi116ec6d2016-10-12 06:07:07 -070013#include <limits>
aleloi09f45102016-07-28 03:52:15 -070014#include <memory>
aleloi24899e52017-02-21 05:06:29 -080015#include <string>
aleloif3882572016-07-29 02:12:41 -070016#include <utility>
aleloi09f45102016-07-28 03:52:15 -070017
Alex Loikob4977de2019-01-28 16:38:38 +010018#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "api/audio/audio_mixer.h"
20#include "modules/audio_mixer/audio_mixer_impl.h"
21#include "modules/audio_mixer/default_output_rate_calculator.h"
22#include "rtc_base/bind.h"
23#include "rtc_base/checks.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020024#include "rtc_base/strings/string_builder.h"
Tommi68561562018-02-13 19:47:50 +010025#include "rtc_base/task_queue_for_test.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "test/gmock.h"
Alex Loikob4977de2019-01-28 16:38:38 +010027#include "test/gtest.h"
aleloi09f45102016-07-28 03:52:15 -070028
Mirko Bonadei6a489f22019-04-09 15:11:12 +020029using ::testing::_;
30using ::testing::Exactly;
31using ::testing::Invoke;
32using ::testing::Return;
aleloi09f45102016-07-28 03:52:15 -070033
aleloi09f45102016-07-28 03:52:15 -070034namespace webrtc {
aleloif3882572016-07-29 02:12:41 -070035
aleloi30be5d72016-08-24 01:38:44 -070036namespace {
aleloif3882572016-07-29 02:12:41 -070037
aleloi30be5d72016-08-24 01:38:44 -070038constexpr int kDefaultSampleRateHz = 48000;
aleloif3882572016-07-29 02:12:41 -070039
aleloi30be5d72016-08-24 01:38:44 -070040// Utility function that resets the frame member variables with
41// sensible defaults.
42void ResetFrame(AudioFrame* frame) {
aleloi30be5d72016-08-24 01:38:44 -070043 frame->sample_rate_hz_ = kDefaultSampleRateHz;
44 frame->num_channels_ = 1;
45
46 // Frame duration 10ms.
47 frame->samples_per_channel_ = kDefaultSampleRateHz / 100;
48 frame->vad_activity_ = AudioFrame::kVadActive;
49 frame->speech_type_ = AudioFrame::kNormalSpeech;
50}
51
aleloi24899e52017-02-21 05:06:29 -080052std::string ProduceDebugText(int sample_rate_hz,
53 int number_of_channels,
54 int number_of_sources) {
Jonas Olsson366a50c2018-09-06 13:41:30 +020055 rtc::StringBuilder ss;
aleloi24899e52017-02-21 05:06:29 -080056 ss << "Sample rate: " << sample_rate_hz << " ";
57 ss << "Number of channels: " << number_of_channels << " ";
58 ss << "Number of sources: " << number_of_sources;
Jonas Olsson84df1c72018-09-14 16:59:32 +020059 return ss.Release();
aleloi24899e52017-02-21 05:06:29 -080060}
61
aleloi30be5d72016-08-24 01:38:44 -070062AudioFrame frame_for_mixing;
63
64} // namespace
aleloif3882572016-07-29 02:12:41 -070065
Mirko Bonadei6a489f22019-04-09 15:11:12 +020066class MockMixerAudioSource : public ::testing::NiceMock<AudioMixer::Source> {
aleloi09f45102016-07-28 03:52:15 -070067 public:
aleloif3882572016-07-29 02:12:41 -070068 MockMixerAudioSource()
aleloie8914152016-10-11 06:18:31 -070069 : fake_audio_frame_info_(AudioMixer::Source::AudioFrameInfo::kNormal) {
aleloi6c278492016-10-20 14:24:39 -070070 ON_CALL(*this, GetAudioFrameWithInfo(_, _))
aleloia0db81f2016-07-28 06:36:22 -070071 .WillByDefault(
aleloie8914152016-10-11 06:18:31 -070072 Invoke(this, &MockMixerAudioSource::FakeAudioFrameWithInfo));
aleloi95611832016-11-08 06:39:50 -080073 ON_CALL(*this, PreferredSampleRate())
74 .WillByDefault(Return(kDefaultSampleRateHz));
aleloi09f45102016-07-28 03:52:15 -070075 }
aleloif3882572016-07-29 02:12:41 -070076
aleloi6c278492016-10-20 14:24:39 -070077 MOCK_METHOD2(GetAudioFrameWithInfo,
78 AudioFrameInfo(int sample_rate_hz, AudioFrame* audio_frame));
aleloia0db81f2016-07-28 06:36:22 -070079
aleloi051f6782016-10-31 03:26:40 -070080 MOCK_CONST_METHOD0(PreferredSampleRate, int());
81 MOCK_CONST_METHOD0(Ssrc, int());
aleloi116ec6d2016-10-12 06:07:07 -070082
aleloi09f45102016-07-28 03:52:15 -070083 AudioFrame* fake_frame() { return &fake_frame_; }
aleloif3882572016-07-29 02:12:41 -070084 AudioFrameInfo fake_info() { return fake_audio_frame_info_; }
85 void set_fake_info(const AudioFrameInfo audio_frame_info) {
86 fake_audio_frame_info_ = audio_frame_info;
87 }
aleloi09f45102016-07-28 03:52:15 -070088
89 private:
aleloi6c278492016-10-20 14:24:39 -070090 AudioFrameInfo FakeAudioFrameWithInfo(int sample_rate_hz,
91 AudioFrame* audio_frame) {
92 audio_frame->CopyFrom(fake_frame_);
aleloi95611832016-11-08 06:39:50 -080093 audio_frame->sample_rate_hz_ = sample_rate_hz;
aleloi24899e52017-02-21 05:06:29 -080094 audio_frame->samples_per_channel_ =
95 rtc::CheckedDivExact(sample_rate_hz, 100);
aleloi6c278492016-10-20 14:24:39 -070096 return fake_info();
aleloi09f45102016-07-28 03:52:15 -070097 }
aleloi95611832016-11-08 06:39:50 -080098
99 AudioFrame fake_frame_;
100 AudioFrameInfo fake_audio_frame_info_;
aleloi09f45102016-07-28 03:52:15 -0700101};
102
aleloi623427c2016-12-08 02:37:58 -0800103class CustomRateCalculator : public OutputRateCalculator {
104 public:
105 explicit CustomRateCalculator(int rate) : rate_(rate) {}
aleloi24899e52017-02-21 05:06:29 -0800106 int CalculateOutputRate(const std::vector<int>& preferred_rates) override {
aleloi623427c2016-12-08 02:37:58 -0800107 return rate_;
108 }
109
110 private:
111 const int rate_;
112};
113
aleloi30be5d72016-08-24 01:38:44 -0700114// Creates participants from |frames| and |frame_info| and adds them
115// to the mixer. Compares mixed status with |expected_status|
116void MixAndCompare(
117 const std::vector<AudioFrame>& frames,
aleloie8914152016-10-11 06:18:31 -0700118 const std::vector<AudioMixer::Source::AudioFrameInfo>& frame_info,
aleloi30be5d72016-08-24 01:38:44 -0700119 const std::vector<bool>& expected_status) {
aleloi24899e52017-02-21 05:06:29 -0800120 const size_t num_audio_sources = frames.size();
aleloi30be5d72016-08-24 01:38:44 -0700121 RTC_DCHECK(frames.size() == frame_info.size());
122 RTC_DCHECK(frame_info.size() == expected_status.size());
aleloif3882572016-07-29 02:12:41 -0700123
aleloi116ec6d2016-10-12 06:07:07 -0700124 const auto mixer = AudioMixerImpl::Create();
aleloi30be5d72016-08-24 01:38:44 -0700125 std::vector<MockMixerAudioSource> participants(num_audio_sources);
aleloif3882572016-07-29 02:12:41 -0700126
aleloi24899e52017-02-21 05:06:29 -0800127 for (size_t i = 0; i < num_audio_sources; ++i) {
aleloi30be5d72016-08-24 01:38:44 -0700128 participants[i].fake_frame()->CopyFrom(frames[i]);
129 participants[i].set_fake_info(frame_info[i]);
aleloif3882572016-07-29 02:12:41 -0700130 }
131
aleloi24899e52017-02-21 05:06:29 -0800132 for (size_t i = 0; i < num_audio_sources; ++i) {
aleloi116ec6d2016-10-12 06:07:07 -0700133 EXPECT_TRUE(mixer->AddSource(&participants[i]));
aleloi6c278492016-10-20 14:24:39 -0700134 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _))
aleloi30be5d72016-08-24 01:38:44 -0700135 .Times(Exactly(1));
aleloif3882572016-07-29 02:12:41 -0700136 }
137
aleloi95611832016-11-08 06:39:50 -0800138 mixer->Mix(1, &frame_for_mixing);
aleloi30be5d72016-08-24 01:38:44 -0700139
aleloi24899e52017-02-21 05:06:29 -0800140 for (size_t i = 0; i < num_audio_sources; ++i) {
aleloi36542512016-10-07 05:28:32 -0700141 EXPECT_EQ(expected_status[i],
142 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i]))
aleloi30be5d72016-08-24 01:38:44 -0700143 << "Mixed status of AudioSource #" << i << " wrong.";
aleloif3882572016-07-29 02:12:41 -0700144 }
aleloi30be5d72016-08-24 01:38:44 -0700145}
aleloi09f45102016-07-28 03:52:15 -0700146
aleloi95611832016-11-08 06:39:50 -0800147void MixMonoAtGivenNativeRate(int native_sample_rate,
148 AudioFrame* mix_frame,
149 rtc::scoped_refptr<AudioMixer> mixer,
150 MockMixerAudioSource* audio_source) {
151 ON_CALL(*audio_source, PreferredSampleRate())
152 .WillByDefault(Return(native_sample_rate));
153 audio_source->fake_frame()->sample_rate_hz_ = native_sample_rate;
154 audio_source->fake_frame()->samples_per_channel_ = native_sample_rate / 100;
155
156 mixer->Mix(1, mix_frame);
157}
158
aleloi09f45102016-07-28 03:52:15 -0700159TEST(AudioMixer, LargestEnergyVadActiveMixed) {
aleloi616df1e2016-08-24 01:17:12 -0700160 constexpr int kAudioSources =
aleloi116ec6d2016-10-12 06:07:07 -0700161 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 3;
aleloi09f45102016-07-28 03:52:15 -0700162
aleloi116ec6d2016-10-12 06:07:07 -0700163 const auto mixer = AudioMixerImpl::Create();
aleloi09f45102016-07-28 03:52:15 -0700164
165 MockMixerAudioSource participants[kAudioSources];
166
167 for (int i = 0; i < kAudioSources; ++i) {
aleloi30be5d72016-08-24 01:38:44 -0700168 ResetFrame(participants[i].fake_frame());
aleloi09f45102016-07-28 03:52:15 -0700169
170 // We set the 80-th sample value since the first 80 samples may be
171 // modified by a ramped-in window.
yujo36b1a5f2017-06-12 12:45:32 -0700172 participants[i].fake_frame()->mutable_data()[80] = i;
aleloi09f45102016-07-28 03:52:15 -0700173
aleloi116ec6d2016-10-12 06:07:07 -0700174 EXPECT_TRUE(mixer->AddSource(&participants[i]));
aleloi6c278492016-10-20 14:24:39 -0700175 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(_, _)).Times(Exactly(1));
aleloi09f45102016-07-28 03:52:15 -0700176 }
177
178 // Last participant gives audio frame with passive VAD, although it has the
179 // largest energy.
180 participants[kAudioSources - 1].fake_frame()->vad_activity_ =
181 AudioFrame::kVadPassive;
182
183 AudioFrame audio_frame;
aleloi95611832016-11-08 06:39:50 -0800184 mixer->Mix(1, // number of channels
aleloi44968092016-08-08 10:18:58 -0700185 &audio_frame);
aleloi09f45102016-07-28 03:52:15 -0700186
187 for (int i = 0; i < kAudioSources; ++i) {
aleloi36542512016-10-07 05:28:32 -0700188 bool is_mixed =
189 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i]);
aleloi09f45102016-07-28 03:52:15 -0700190 if (i == kAudioSources - 1 ||
aleloi116ec6d2016-10-12 06:07:07 -0700191 i < kAudioSources - 1 -
192 AudioMixerImpl::kMaximumAmountOfMixedAudioSources) {
Yves Gerey665174f2018-06-19 15:03:05 +0200193 EXPECT_FALSE(is_mixed)
194 << "Mixing status of AudioSource #" << i << " wrong.";
aleloi09f45102016-07-28 03:52:15 -0700195 } else {
Yves Gerey665174f2018-06-19 15:03:05 +0200196 EXPECT_TRUE(is_mixed)
197 << "Mixing status of AudioSource #" << i << " wrong.";
aleloi09f45102016-07-28 03:52:15 -0700198 }
199 }
200}
201
aleloi311525e2016-09-07 06:13:12 -0700202TEST(AudioMixer, FrameNotModifiedForSingleParticipant) {
aleloi116ec6d2016-10-12 06:07:07 -0700203 const auto mixer = AudioMixerImpl::Create();
aleloi311525e2016-09-07 06:13:12 -0700204
205 MockMixerAudioSource participant;
206
207 ResetFrame(participant.fake_frame());
aleloi24899e52017-02-21 05:06:29 -0800208 const size_t n_samples = participant.fake_frame()->samples_per_channel_;
aleloi311525e2016-09-07 06:13:12 -0700209
210 // Modify the frame so that it's not zero.
yujo36b1a5f2017-06-12 12:45:32 -0700211 int16_t* fake_frame_data = participant.fake_frame()->mutable_data();
aleloi24899e52017-02-21 05:06:29 -0800212 for (size_t j = 0; j < n_samples; ++j) {
yujo36b1a5f2017-06-12 12:45:32 -0700213 fake_frame_data[j] = static_cast<int16_t>(j);
aleloi311525e2016-09-07 06:13:12 -0700214 }
215
aleloi116ec6d2016-10-12 06:07:07 -0700216 EXPECT_TRUE(mixer->AddSource(&participant));
aleloi6c278492016-10-20 14:24:39 -0700217 EXPECT_CALL(participant, GetAudioFrameWithInfo(_, _)).Times(Exactly(2));
aleloi311525e2016-09-07 06:13:12 -0700218
219 AudioFrame audio_frame;
220 // Two mix iteration to compare after the ramp-up step.
aleloi24899e52017-02-21 05:06:29 -0800221 for (int i = 0; i < 2; ++i) {
aleloi95611832016-11-08 06:39:50 -0800222 mixer->Mix(1, // number of channels
aleloi311525e2016-09-07 06:13:12 -0700223 &audio_frame);
224 }
225
Yves Gerey665174f2018-06-19 15:03:05 +0200226 EXPECT_EQ(0, memcmp(participant.fake_frame()->data(), audio_frame.data(),
227 n_samples));
aleloi311525e2016-09-07 06:13:12 -0700228}
229
aleloi95611832016-11-08 06:39:50 -0800230TEST(AudioMixer, SourceAtNativeRateShouldNeverResample) {
231 const auto mixer = AudioMixerImpl::Create();
232
233 MockMixerAudioSource audio_source;
234 ResetFrame(audio_source.fake_frame());
235
236 mixer->AddSource(&audio_source);
237
238 for (auto frequency : {8000, 16000, 32000, 48000}) {
239 EXPECT_CALL(audio_source, GetAudioFrameWithInfo(frequency, _))
240 .Times(Exactly(1));
241
242 MixMonoAtGivenNativeRate(frequency, &frame_for_mixing, mixer,
243 &audio_source);
244 }
245}
246
247TEST(AudioMixer, MixerShouldMixAtNativeSourceRate) {
248 const auto mixer = AudioMixerImpl::Create();
249
250 MockMixerAudioSource audio_source;
251 ResetFrame(audio_source.fake_frame());
252
253 mixer->AddSource(&audio_source);
254
255 for (auto frequency : {8000, 16000, 32000, 48000}) {
256 MixMonoAtGivenNativeRate(frequency, &frame_for_mixing, mixer,
257 &audio_source);
258
259 EXPECT_EQ(frequency, frame_for_mixing.sample_rate_hz_);
260 }
261}
262
263TEST(AudioMixer, MixerShouldAlwaysMixAtNativeRate) {
aleloi116ec6d2016-10-12 06:07:07 -0700264 const auto mixer = AudioMixerImpl::Create();
aleloi44968092016-08-08 10:18:58 -0700265
266 MockMixerAudioSource participant;
aleloi30be5d72016-08-24 01:38:44 -0700267 ResetFrame(participant.fake_frame());
aleloi95611832016-11-08 06:39:50 -0800268 mixer->AddSource(&participant);
aleloi44968092016-08-08 10:18:58 -0700269
aleloi95611832016-11-08 06:39:50 -0800270 const int needed_frequency = 44100;
271 ON_CALL(participant, PreferredSampleRate())
272 .WillByDefault(Return(needed_frequency));
273
274 // We expect mixing frequency to be native and >= needed_frequency.
275 const int expected_mix_frequency = 48000;
276 EXPECT_CALL(participant, GetAudioFrameWithInfo(expected_mix_frequency, _))
277 .Times(Exactly(1));
278 participant.fake_frame()->sample_rate_hz_ = expected_mix_frequency;
279 participant.fake_frame()->samples_per_channel_ = expected_mix_frequency / 100;
280
281 mixer->Mix(1, &frame_for_mixing);
282
283 EXPECT_EQ(48000, frame_for_mixing.sample_rate_hz_);
284}
285
286// Check that the mixing rate is always >= participants preferred rate.
287TEST(AudioMixer, ShouldNotCauseQualityLossForMultipleSources) {
288 const auto mixer = AudioMixerImpl::Create();
289
290 std::vector<MockMixerAudioSource> audio_sources(2);
291 const std::vector<int> source_sample_rates = {8000, 16000};
292 for (int i = 0; i < 2; ++i) {
293 auto& source = audio_sources[i];
294 ResetFrame(source.fake_frame());
295 mixer->AddSource(&source);
296 const auto sample_rate = source_sample_rates[i];
297 EXPECT_CALL(source, PreferredSampleRate()).WillOnce(Return(sample_rate));
298
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200299 EXPECT_CALL(source, GetAudioFrameWithInfo(::testing::Ge(sample_rate), _));
aleloi44968092016-08-08 10:18:58 -0700300 }
aleloi95611832016-11-08 06:39:50 -0800301 mixer->Mix(1, &frame_for_mixing);
aleloi44968092016-08-08 10:18:58 -0700302}
303
304TEST(AudioMixer, ParticipantNumberOfChannels) {
aleloi116ec6d2016-10-12 06:07:07 -0700305 const auto mixer = AudioMixerImpl::Create();
aleloi44968092016-08-08 10:18:58 -0700306
307 MockMixerAudioSource participant;
aleloi30be5d72016-08-24 01:38:44 -0700308 ResetFrame(participant.fake_frame());
aleloi44968092016-08-08 10:18:58 -0700309
aleloi116ec6d2016-10-12 06:07:07 -0700310 EXPECT_TRUE(mixer->AddSource(&participant));
aleloi44968092016-08-08 10:18:58 -0700311 for (size_t number_of_channels : {1, 2}) {
aleloi6c278492016-10-20 14:24:39 -0700312 EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz, _))
aleloi30be5d72016-08-24 01:38:44 -0700313 .Times(Exactly(1));
aleloi95611832016-11-08 06:39:50 -0800314 mixer->Mix(number_of_channels, &frame_for_mixing);
aleloi44968092016-08-08 10:18:58 -0700315 EXPECT_EQ(number_of_channels, frame_for_mixing.num_channels_);
316 }
317}
318
aleloi30be5d72016-08-24 01:38:44 -0700319// Maximal amount of participants are mixed one iteration, then
320// another participant with higher energy is added.
321TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) {
322 constexpr int kAudioSources =
aleloi116ec6d2016-10-12 06:07:07 -0700323 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
aleloi09f45102016-07-28 03:52:15 -0700324
aleloi116ec6d2016-10-12 06:07:07 -0700325 const auto mixer = AudioMixerImpl::Create();
aleloi30be5d72016-08-24 01:38:44 -0700326 MockMixerAudioSource participants[kAudioSources];
aleloi09f45102016-07-28 03:52:15 -0700327
aleloi24899e52017-02-21 05:06:29 -0800328 for (int i = 0; i < kAudioSources; ++i) {
aleloi30be5d72016-08-24 01:38:44 -0700329 ResetFrame(participants[i].fake_frame());
330 // Set the participant audio energy to increase with the index
331 // |i|.
yujo36b1a5f2017-06-12 12:45:32 -0700332 participants[i].fake_frame()->mutable_data()[0] = 100 * i;
aleloi30be5d72016-08-24 01:38:44 -0700333 }
aleloi09f45102016-07-28 03:52:15 -0700334
aleloi30be5d72016-08-24 01:38:44 -0700335 // Add all participants but the loudest for mixing.
aleloi24899e52017-02-21 05:06:29 -0800336 for (int i = 0; i < kAudioSources - 1; ++i) {
aleloi116ec6d2016-10-12 06:07:07 -0700337 EXPECT_TRUE(mixer->AddSource(&participants[i]));
aleloi6c278492016-10-20 14:24:39 -0700338 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _))
aleloi30be5d72016-08-24 01:38:44 -0700339 .Times(Exactly(1));
340 }
aleloi09f45102016-07-28 03:52:15 -0700341
aleloi30be5d72016-08-24 01:38:44 -0700342 // First mixer iteration
aleloi95611832016-11-08 06:39:50 -0800343 mixer->Mix(1, &frame_for_mixing);
aleloi09f45102016-07-28 03:52:15 -0700344
aleloi30be5d72016-08-24 01:38:44 -0700345 // All participants but the loudest should have been mixed.
aleloi24899e52017-02-21 05:06:29 -0800346 for (int i = 0; i < kAudioSources - 1; ++i) {
aleloi36542512016-10-07 05:28:32 -0700347 EXPECT_TRUE(mixer->GetAudioSourceMixabilityStatusForTest(&participants[i]))
348 << "Mixed status of AudioSource #" << i << " wrong.";
aleloi30be5d72016-08-24 01:38:44 -0700349 }
aleloi09f45102016-07-28 03:52:15 -0700350
aleloi30be5d72016-08-24 01:38:44 -0700351 // Add new participant with higher energy.
aleloi116ec6d2016-10-12 06:07:07 -0700352 EXPECT_TRUE(mixer->AddSource(&participants[kAudioSources - 1]));
aleloi24899e52017-02-21 05:06:29 -0800353 for (int i = 0; i < kAudioSources; ++i) {
aleloi6c278492016-10-20 14:24:39 -0700354 EXPECT_CALL(participants[i], GetAudioFrameWithInfo(kDefaultSampleRateHz, _))
aleloi30be5d72016-08-24 01:38:44 -0700355 .Times(Exactly(1));
356 }
aleloi09f45102016-07-28 03:52:15 -0700357
aleloi95611832016-11-08 06:39:50 -0800358 mixer->Mix(1, &frame_for_mixing);
aleloif3882572016-07-29 02:12:41 -0700359
aleloi30be5d72016-08-24 01:38:44 -0700360 // The most quiet participant should not have been mixed.
aleloi36542512016-10-07 05:28:32 -0700361 EXPECT_FALSE(mixer->GetAudioSourceMixabilityStatusForTest(&participants[0]))
aleloi30be5d72016-08-24 01:38:44 -0700362 << "Mixed status of AudioSource #0 wrong.";
aleloif3882572016-07-29 02:12:41 -0700363
aleloi30be5d72016-08-24 01:38:44 -0700364 // The loudest participants should have been mixed.
aleloi24899e52017-02-21 05:06:29 -0800365 for (int i = 1; i < kAudioSources; ++i) {
aleloi36542512016-10-07 05:28:32 -0700366 EXPECT_EQ(true,
367 mixer->GetAudioSourceMixabilityStatusForTest(&participants[i]))
aleloi30be5d72016-08-24 01:38:44 -0700368 << "Mixed status of AudioSource #" << i << " wrong.";
aleloif3882572016-07-29 02:12:41 -0700369 }
370}
371
aleloi311525e2016-09-07 06:13:12 -0700372// This test checks that the initialization and participant addition
373// can be done on a different thread.
374TEST(AudioMixer, ConstructFromOtherThread) {
Danil Chapovalovd26a9162019-03-19 18:08:37 +0100375 TaskQueueForTest init_queue("init");
tommic45d6d92017-07-11 06:17:10 -0700376 rtc::scoped_refptr<AudioMixer> mixer;
Tommi68561562018-02-13 19:47:50 +0100377 init_queue.SendTask([&mixer]() { mixer = AudioMixerImpl::Create(); });
tommic45d6d92017-07-11 06:17:10 -0700378
aleloi311525e2016-09-07 06:13:12 -0700379 MockMixerAudioSource participant;
tommic45d6d92017-07-11 06:17:10 -0700380 EXPECT_CALL(participant, PreferredSampleRate())
381 .WillRepeatedly(Return(kDefaultSampleRateHz));
aleloi311525e2016-09-07 06:13:12 -0700382
383 ResetFrame(participant.fake_frame());
384
Danil Chapovalovd26a9162019-03-19 18:08:37 +0100385 TaskQueueForTest participant_queue("participant");
Tommi68561562018-02-13 19:47:50 +0100386 participant_queue.SendTask(
387 [&mixer, &participant]() { mixer->AddSource(&participant); });
aleloi311525e2016-09-07 06:13:12 -0700388
aleloi6c278492016-10-20 14:24:39 -0700389 EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz, _))
aleloi311525e2016-09-07 06:13:12 -0700390 .Times(Exactly(1));
391
392 // Do one mixer iteration
aleloi95611832016-11-08 06:39:50 -0800393 mixer->Mix(1, &frame_for_mixing);
aleloi311525e2016-09-07 06:13:12 -0700394}
395
aleloi30be5d72016-08-24 01:38:44 -0700396TEST(AudioMixer, MutedShouldMixAfterUnmuted) {
397 constexpr int kAudioSources =
aleloi116ec6d2016-10-12 06:07:07 -0700398 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
aleloif3882572016-07-29 02:12:41 -0700399
aleloi30be5d72016-08-24 01:38:44 -0700400 std::vector<AudioFrame> frames(kAudioSources);
401 for (auto& frame : frames) {
402 ResetFrame(&frame);
aleloif3882572016-07-29 02:12:41 -0700403 }
aleloi30be5d72016-08-24 01:38:44 -0700404
aleloie8914152016-10-11 06:18:31 -0700405 std::vector<AudioMixer::Source::AudioFrameInfo> frame_info(
406 kAudioSources, AudioMixer::Source::AudioFrameInfo::kNormal);
407 frame_info[0] = AudioMixer::Source::AudioFrameInfo::kMuted;
aleloi30be5d72016-08-24 01:38:44 -0700408 std::vector<bool> expected_status(kAudioSources, true);
409 expected_status[0] = false;
410
411 MixAndCompare(frames, frame_info, expected_status);
aleloif3882572016-07-29 02:12:41 -0700412}
413
aleloi30be5d72016-08-24 01:38:44 -0700414TEST(AudioMixer, PassiveShouldMixAfterNormal) {
415 constexpr int kAudioSources =
aleloi116ec6d2016-10-12 06:07:07 -0700416 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
aleloif3882572016-07-29 02:12:41 -0700417
aleloi30be5d72016-08-24 01:38:44 -0700418 std::vector<AudioFrame> frames(kAudioSources);
419 for (auto& frame : frames) {
420 ResetFrame(&frame);
aleloif3882572016-07-29 02:12:41 -0700421 }
422
aleloie8914152016-10-11 06:18:31 -0700423 std::vector<AudioMixer::Source::AudioFrameInfo> frame_info(
424 kAudioSources, AudioMixer::Source::AudioFrameInfo::kNormal);
aleloi30be5d72016-08-24 01:38:44 -0700425 frames[0].vad_activity_ = AudioFrame::kVadPassive;
426 std::vector<bool> expected_status(kAudioSources, true);
427 expected_status[0] = false;
428
429 MixAndCompare(frames, frame_info, expected_status);
aleloif3882572016-07-29 02:12:41 -0700430}
431
aleloi30be5d72016-08-24 01:38:44 -0700432TEST(AudioMixer, ActiveShouldMixBeforeLoud) {
433 constexpr int kAudioSources =
aleloi116ec6d2016-10-12 06:07:07 -0700434 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
aleloi30be5d72016-08-24 01:38:44 -0700435
436 std::vector<AudioFrame> frames(kAudioSources);
437 for (auto& frame : frames) {
438 ResetFrame(&frame);
439 }
440
aleloie8914152016-10-11 06:18:31 -0700441 std::vector<AudioMixer::Source::AudioFrameInfo> frame_info(
442 kAudioSources, AudioMixer::Source::AudioFrameInfo::kNormal);
aleloi30be5d72016-08-24 01:38:44 -0700443 frames[0].vad_activity_ = AudioFrame::kVadPassive;
yujo36b1a5f2017-06-12 12:45:32 -0700444 int16_t* frame_data = frames[0].mutable_data();
445 std::fill(frame_data, frame_data + kDefaultSampleRateHz / 100,
aleloi30be5d72016-08-24 01:38:44 -0700446 std::numeric_limits<int16_t>::max());
447 std::vector<bool> expected_status(kAudioSources, true);
448 expected_status[0] = false;
449
450 MixAndCompare(frames, frame_info, expected_status);
451}
452
453TEST(AudioMixer, UnmutedShouldMixBeforeLoud) {
454 constexpr int kAudioSources =
aleloi116ec6d2016-10-12 06:07:07 -0700455 AudioMixerImpl::kMaximumAmountOfMixedAudioSources + 1;
aleloi30be5d72016-08-24 01:38:44 -0700456
457 std::vector<AudioFrame> frames(kAudioSources);
458 for (auto& frame : frames) {
459 ResetFrame(&frame);
460 }
461
aleloie8914152016-10-11 06:18:31 -0700462 std::vector<AudioMixer::Source::AudioFrameInfo> frame_info(
463 kAudioSources, AudioMixer::Source::AudioFrameInfo::kNormal);
464 frame_info[0] = AudioMixer::Source::AudioFrameInfo::kMuted;
yujo36b1a5f2017-06-12 12:45:32 -0700465 int16_t* frame_data = frames[0].mutable_data();
466 std::fill(frame_data, frame_data + kDefaultSampleRateHz / 100,
aleloi30be5d72016-08-24 01:38:44 -0700467 std::numeric_limits<int16_t>::max());
468 std::vector<bool> expected_status(kAudioSources, true);
469 expected_status[0] = false;
470
471 MixAndCompare(frames, frame_info, expected_status);
472}
aleloi623427c2016-12-08 02:37:58 -0800473
474TEST(AudioMixer, MixingRateShouldBeDecidedByRateCalculator) {
475 constexpr int kOutputRate = 22000;
aleloi087613c2017-02-21 08:27:08 -0800476 const auto mixer =
477 AudioMixerImpl::Create(std::unique_ptr<OutputRateCalculator>(
478 new CustomRateCalculator(kOutputRate)),
479 true);
aleloi623427c2016-12-08 02:37:58 -0800480 MockMixerAudioSource audio_source;
481 mixer->AddSource(&audio_source);
482 ResetFrame(audio_source.fake_frame());
483
484 EXPECT_CALL(audio_source, GetAudioFrameWithInfo(kOutputRate, _))
485 .Times(Exactly(1));
486
487 mixer->Mix(1, &frame_for_mixing);
488}
489
490TEST(AudioMixer, ZeroSourceRateShouldBeDecidedByRateCalculator) {
491 constexpr int kOutputRate = 8000;
aleloi087613c2017-02-21 08:27:08 -0800492 const auto mixer =
493 AudioMixerImpl::Create(std::unique_ptr<OutputRateCalculator>(
494 new CustomRateCalculator(kOutputRate)),
495 true);
aleloi623427c2016-12-08 02:37:58 -0800496
497 mixer->Mix(1, &frame_for_mixing);
498
499 EXPECT_EQ(kOutputRate, frame_for_mixing.sample_rate_hz_);
500}
aleloi24899e52017-02-21 05:06:29 -0800501
502TEST(AudioMixer, NoLimiterBasicApiCalls) {
aleloi087613c2017-02-21 08:27:08 -0800503 const auto mixer = AudioMixerImpl::Create(
aleloi24899e52017-02-21 05:06:29 -0800504 std::unique_ptr<OutputRateCalculator>(new DefaultOutputRateCalculator()),
505 false);
506 mixer->Mix(1, &frame_for_mixing);
507}
508
509TEST(AudioMixer, AnyRateIsPossibleWithNoLimiter) {
510 // No APM limiter means no AudioProcessing::NativeRate restriction
511 // on mixing rate. The rate has to be divisible by 100 since we use
512 // 10 ms frames, though.
513 for (const auto rate : {8000, 20000, 24000, 32000, 44100}) {
514 for (const size_t number_of_channels : {1, 2}) {
515 for (const auto number_of_sources : {0, 1, 2, 3, 4}) {
516 SCOPED_TRACE(
517 ProduceDebugText(rate, number_of_sources, number_of_sources));
518 const auto mixer =
aleloi087613c2017-02-21 08:27:08 -0800519 AudioMixerImpl::Create(std::unique_ptr<OutputRateCalculator>(
520 new CustomRateCalculator(rate)),
521 false);
aleloi24899e52017-02-21 05:06:29 -0800522
523 std::vector<MockMixerAudioSource> sources(number_of_sources);
524 for (auto& source : sources) {
Alex Loikob4977de2019-01-28 16:38:38 +0100525 ResetFrame(source.fake_frame());
aleloi24899e52017-02-21 05:06:29 -0800526 mixer->AddSource(&source);
527 }
528
529 mixer->Mix(number_of_channels, &frame_for_mixing);
530 EXPECT_EQ(rate, frame_for_mixing.sample_rate_hz_);
531 EXPECT_EQ(number_of_channels, frame_for_mixing.num_channels_);
532 }
533 }
534 }
535}
Alex Loikob4977de2019-01-28 16:38:38 +0100536
537TEST(AudioMixer, MultipleChannelsOneParticipant) {
538 // Set up a participant with a 6-channel frame, and make sure a 6-channel
539 // frame with the right sample values comes out from the mixer. There are 2
540 // Mix calls because of ramp-up.
541 constexpr size_t kNumberOfChannels = 6;
542 MockMixerAudioSource source;
543 ResetFrame(source.fake_frame());
544 const auto mixer = AudioMixerImpl::Create();
545 mixer->AddSource(&source);
546 mixer->Mix(1, &frame_for_mixing);
547 auto* frame = source.fake_frame();
548 frame->num_channels_ = kNumberOfChannels;
549 std::fill(frame->mutable_data(),
550 frame->mutable_data() + AudioFrame::kMaxDataSizeSamples, 0);
551 for (size_t i = 0; i < kNumberOfChannels; ++i) {
552 frame->mutable_data()[100 * frame->num_channels_ + i] = 1000 * i;
553 }
554
555 mixer->Mix(kNumberOfChannels, &frame_for_mixing);
556
557 EXPECT_EQ(frame_for_mixing.num_channels_, kNumberOfChannels);
558 for (size_t i = 0; i < kNumberOfChannels; ++i) {
559 EXPECT_EQ(frame_for_mixing.data()[100 * frame_for_mixing.num_channels_ + i],
560 static_cast<int16_t>(1000 * i));
561 }
562}
563
564TEST(AudioMixer, MultipleChannelsManyParticipants) {
565 // Sets up 2 participants. One has a 6-channel frame. Make sure a 6-channel
566 // frame with the right sample values comes out from the mixer. There are 2
567 // Mix calls because of ramp-up.
568 constexpr size_t kNumberOfChannels = 6;
569 MockMixerAudioSource source;
570 const auto mixer = AudioMixerImpl::Create();
571 mixer->AddSource(&source);
572 ResetFrame(source.fake_frame());
573 mixer->Mix(1, &frame_for_mixing);
574 auto* frame = source.fake_frame();
575 frame->num_channels_ = kNumberOfChannels;
576 std::fill(frame->mutable_data(),
577 frame->mutable_data() + AudioFrame::kMaxDataSizeSamples, 0);
578 for (size_t i = 0; i < kNumberOfChannels; ++i) {
579 frame->mutable_data()[100 * frame->num_channels_ + i] = 1000 * i;
580 }
581 MockMixerAudioSource other_source;
582 ResetFrame(other_source.fake_frame());
583 mixer->AddSource(&other_source);
584
585 mixer->Mix(kNumberOfChannels, &frame_for_mixing);
586
587 EXPECT_EQ(frame_for_mixing.num_channels_, kNumberOfChannels);
588 for (size_t i = 0; i < kNumberOfChannels; ++i) {
589 EXPECT_EQ(frame_for_mixing.data()[100 * frame_for_mixing.num_channels_ + i],
590 static_cast<int16_t>(1000 * i));
591 }
592}
593
594class HighOutputRateCalculator : public OutputRateCalculator {
595 public:
596 static const int kDefaultFrequency = 76000;
597 int CalculateOutputRate(
598 const std::vector<int>& preferred_sample_rates) override {
599 return kDefaultFrequency;
600 }
601 ~HighOutputRateCalculator() override {}
602};
603const int HighOutputRateCalculator::kDefaultFrequency;
604
605TEST(AudioMixer, MultipleChannelsAndHighRate) {
606 constexpr size_t kSamplesPerChannel =
607 HighOutputRateCalculator::kDefaultFrequency / 100;
608 // As many channels as an AudioFrame can fit:
609 constexpr size_t kNumberOfChannels =
610 AudioFrame::kMaxDataSizeSamples / kSamplesPerChannel;
611 MockMixerAudioSource source;
612 const auto mixer = AudioMixerImpl::Create(
613 absl::make_unique<HighOutputRateCalculator>(), true);
614 mixer->AddSource(&source);
615 ResetFrame(source.fake_frame());
616 mixer->Mix(1, &frame_for_mixing);
617 auto* frame = source.fake_frame();
618 frame->num_channels_ = kNumberOfChannels;
619 frame->sample_rate_hz_ = HighOutputRateCalculator::kDefaultFrequency;
620 frame->samples_per_channel_ = kSamplesPerChannel;
621
622 std::fill(frame->mutable_data(),
623 frame->mutable_data() + AudioFrame::kMaxDataSizeSamples, 0);
624 MockMixerAudioSource other_source;
625 ResetFrame(other_source.fake_frame());
626 auto* other_frame = other_source.fake_frame();
627 other_frame->num_channels_ = kNumberOfChannels;
628 other_frame->sample_rate_hz_ = HighOutputRateCalculator::kDefaultFrequency;
629 other_frame->samples_per_channel_ = kSamplesPerChannel;
630 mixer->AddSource(&other_source);
631
632#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
633 EXPECT_DEATH(mixer->Mix(kNumberOfChannels, &frame_for_mixing), "");
634#elif !RTC_DCHECK_IS_ON
635 mixer->Mix(kNumberOfChannels, &frame_for_mixing);
636 EXPECT_EQ(frame_for_mixing.num_channels_, kNumberOfChannels);
637 EXPECT_EQ(frame_for_mixing.sample_rate_hz_,
638 HighOutputRateCalculator::kDefaultFrequency);
639#endif
640}
641
aleloi09f45102016-07-28 03:52:15 -0700642} // namespace webrtc