Chromium Code Reviews| 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 <memory> | 11 #include <memory> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "testing/gmock/include/gmock/gmock.h" | 14 #include "testing/gmock/include/gmock/gmock.h" |
| 15 | |
| 16 #include "webrtc/modules/audio_conference_mixer/include/audio_conference_mixer.h " | |
| 17 #include "webrtc/modules/audio_conference_mixer/include/audio_conference_mixer_d efines.h" | |
| 18 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h " | |
| 19 #include "webrtc/modules/audio_mixer/audio_mixer.h" | 15 #include "webrtc/modules/audio_mixer/audio_mixer.h" |
| 20 #include "webrtc/modules/audio_mixer/audio_mixer_defines.h" | 16 #include "webrtc/modules/audio_mixer/audio_mixer_defines.h" |
| 21 #include "webrtc/modules/audio_mixer/new_audio_conference_mixer.h" | 17 #include "webrtc/modules/audio_mixer/new_audio_conference_mixer.h" |
| 22 #include "webrtc/modules/audio_mixer/new_audio_conference_mixer_impl.h" | |
| 23 | 18 |
| 24 using testing::_; | 19 using testing::_; |
| 25 using testing::Exactly; | 20 using testing::Exactly; |
| 26 using testing::Invoke; | 21 using testing::Invoke; |
| 27 using testing::Return; | 22 using testing::Return; |
| 28 | 23 |
| 29 using webrtc::voe::AudioMixer; | 24 using webrtc::voe::AudioMixer; |
| 30 | 25 |
| 31 namespace webrtc { | 26 namespace webrtc { |
| 32 class MockAudioMixerParticipant : public MixerParticipant { | |
| 33 public: | |
| 34 MockAudioMixerParticipant() | |
| 35 : fake_audio_frame_info_(MixerParticipant::AudioFrameInfo::kNormal) { | |
| 36 ON_CALL(*this, GetAudioFrameWithMuted(_, _)) | |
| 37 .WillByDefault( | |
| 38 Invoke(this, &MockAudioMixerParticipant::FakeAudioFrameWithMuted)); | |
| 39 } | |
| 40 | 27 |
| 41 MOCK_METHOD2(GetAudioFrameWithMuted, | 28 namespace { |
| 42 AudioFrameInfo(const int32_t id, AudioFrame* audio_frame)); | |
| 43 MOCK_CONST_METHOD1(NeededFrequency, int32_t(const int32_t id)); | |
| 44 | 29 |
| 45 AudioFrame* fake_frame() { return &fake_frame_; } | 30 constexpr int kDefaultSampleRateHz = 48000; |
| 46 AudioFrameInfo fake_info() { return this->fake_audio_frame_info_; } | 31 constexpr int kId = 1; |
| 47 void set_fake_info(const AudioFrameInfo audio_frame_info) { | |
| 48 fake_audio_frame_info_ = audio_frame_info; | |
| 49 } | |
| 50 | 32 |
| 51 private: | 33 // Utility function that resets the frame member variables with |
| 52 AudioFrame fake_frame_; | 34 // sensible defaults. |
| 53 AudioFrameInfo fake_audio_frame_info_; | 35 void ResetFrame(AudioFrame* frame) { |
| 54 AudioFrameInfo FakeAudioFrameWithMuted(const int32_t id, | 36 frame->id_ = kId; |
| 55 AudioFrame* audio_frame) { | 37 frame->sample_rate_hz_ = kDefaultSampleRateHz; |
| 56 audio_frame->CopyFrom(*fake_frame()); | 38 frame->num_channels_ = 1; |
| 57 return fake_info(); | 39 |
| 58 } | 40 // Frame duration 10ms. |
| 59 }; | 41 frame->samples_per_channel_ = kDefaultSampleRateHz / 100; |
|
aleloi
2016/08/18 09:21:14
This class was used for testing against the old Au
| |
| 42 frame->vad_activity_ = AudioFrame::kVadActive; | |
| 43 frame->speech_type_ = AudioFrame::kNormalSpeech; | |
| 44 } | |
| 45 | |
| 46 AudioFrame frame_for_mixing; | |
| 47 | |
| 48 } // namespace | |
| 60 | 49 |
| 61 class MockMixerAudioSource : public MixerAudioSource { | 50 class MockMixerAudioSource : public MixerAudioSource { |
| 62 public: | 51 public: |
| 63 MockMixerAudioSource() | 52 MockMixerAudioSource() |
| 64 : fake_audio_frame_info_(MixerAudioSource::AudioFrameInfo::kNormal) { | 53 : fake_audio_frame_info_(MixerAudioSource::AudioFrameInfo::kNormal) { |
| 65 ON_CALL(*this, GetAudioFrameWithMuted(_, _)) | 54 ON_CALL(*this, GetAudioFrameWithMuted(_, _)) |
| 66 .WillByDefault( | 55 .WillByDefault( |
| 67 Invoke(this, &MockMixerAudioSource::FakeAudioFrameWithMuted)); | 56 Invoke(this, &MockMixerAudioSource::FakeAudioFrameWithMuted)); |
| 68 } | 57 } |
| 69 | 58 |
| 70 MOCK_METHOD2(GetAudioFrameWithMuted, | 59 MOCK_METHOD2(GetAudioFrameWithMuted, |
| 71 AudioFrameWithMuted(const int32_t id, int sample_rate_hz)); | 60 AudioFrameWithMuted(const int32_t id, int sample_rate_hz)); |
| 72 | 61 |
| 73 AudioFrame* fake_frame() { return &fake_frame_; } | 62 AudioFrame* fake_frame() { return &fake_frame_; } |
| 74 AudioFrameInfo fake_info() { return fake_audio_frame_info_; } | 63 AudioFrameInfo fake_info() { return fake_audio_frame_info_; } |
| 75 void set_fake_info(const AudioFrameInfo audio_frame_info) { | 64 void set_fake_info(const AudioFrameInfo audio_frame_info) { |
| 76 fake_audio_frame_info_ = audio_frame_info; | 65 fake_audio_frame_info_ = audio_frame_info; |
| 77 } | 66 } |
| 78 | 67 |
| 79 private: | 68 private: |
| 80 AudioFrame fake_frame_, output_frame_; | 69 AudioFrame fake_frame_, fake_output_frame_; |
| 81 AudioFrameInfo fake_audio_frame_info_; | 70 AudioFrameInfo fake_audio_frame_info_; |
| 82 AudioFrameWithMuted FakeAudioFrameWithMuted(const int32_t id, | 71 AudioFrameWithMuted FakeAudioFrameWithMuted(const int32_t id, |
| 83 int sample_rate_hz) { | 72 int sample_rate_hz) { |
| 84 output_frame_.CopyFrom(fake_frame_); | 73 fake_output_frame_.CopyFrom(fake_frame_); |
| 85 return { | 74 return { |
| 86 &output_frame_, // audio_frame_pointer | 75 &fake_output_frame_, // audio_frame_pointer |
| 87 fake_info(), // audio_frame_info | 76 fake_info(), // audio_frame_info |
|
aleloi
2016/08/18 09:21:14
Instead of returning the fake frame, now returns a
| |
| 88 }; | 77 }; |
| 89 } | 78 } |
| 90 }; | 79 }; |
| 91 | 80 |
| 92 // Keeps two identical sets of participants and two mixers to test | 81 // Creates participants from |frames| and |frame_info| and adds them |
| 93 // that the same participants are chosen for mixing. | 82 // to the mixer. Compares mixed status with |expected_status| |
| 94 class CompareWithOldMixerTest : public testing::Test, AudioMixerOutputReceiver { | 83 void MixAndCompare( |
| 95 protected: | 84 const std::vector<AudioFrame>& frames, |
| 96 constexpr static int kId = 1; | 85 const std::vector<MixerAudioSource::AudioFrameInfo>& frame_info, |
| 97 constexpr static int kSampleRateHz = 32000; | 86 const std::vector<bool>& expected_status) { |
| 87 size_t num_audio_sources = frames.size(); | |
| 88 RTC_DCHECK(frames.size() == frame_info.size() && | |
| 89 frame_info.size() == expected_status.size()); | |
| 98 | 90 |
| 99 CompareWithOldMixerTest() | 91 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 100 : old_mixer_(AudioConferenceMixer::Create(kId)), | 92 NewAudioConferenceMixer::Create(kId)); |
| 101 new_mixer_(NewAudioConferenceMixer::Create(kId)) {} | 93 std::vector<MockMixerAudioSource> participants(num_audio_sources); |
| 102 | 94 |
| 103 ~CompareWithOldMixerTest() { Reset(); } | 95 for (size_t i = 0; i < num_audio_sources; i++) { |
| 104 | 96 participants[i].fake_frame()->CopyFrom(frames[i]); |
| 105 // Mixes with both mixers and compares results: resulting frames and | 97 participants[i].set_fake_info(frame_info[i]); |
| 106 // mix statuses. | |
| 107 void MixAndCompare() { | |
| 108 old_mixer_->Process(); | |
| 109 new_mixer_->Mix(kSampleRateHz, | |
| 110 1, // number of channels | |
| 111 &new_mixer_frame_); | |
| 112 EXPECT_EQ(0, memcmp(old_mixer_frame_.data_, new_mixer_frame_.data_, | |
| 113 sizeof(old_mixer_frame_.data_))); | |
| 114 | |
| 115 for (auto& participant_pair : participants_) { | |
| 116 EXPECT_EQ(participant_pair.first->IsMixed(), | |
| 117 participant_pair.second->IsMixed()); | |
| 118 } | |
| 119 } | 98 } |
| 120 | 99 |
| 121 std::unique_ptr<AudioFrame> last_mixed_audio_old() { | 100 for (size_t i = 0; i < num_audio_sources; i++) { |
| 122 std::unique_ptr<AudioFrame> result(new AudioFrame); | 101 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true)); |
| 123 result->CopyFrom(old_mixer_frame_); | 102 EXPECT_CALL(participants[i], |
| 124 return result; | 103 GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) |
| 104 .Times(Exactly(1)); | |
| 125 } | 105 } |
| 126 | 106 |
| 127 void Reset() { | 107 mixer->Mix(kDefaultSampleRateHz, 1, &frame_for_mixing); |
| 128 old_mixer_.reset(AudioConferenceMixer::Create(kId)); | 108 |
| 129 new_mixer_.reset(NewAudioConferenceMixer::Create(kId)); | 109 for (size_t i = 0; i < num_audio_sources; i++) { |
| 130 for (auto& participant_pair : participants_) { | 110 EXPECT_EQ(participants[i].IsMixed(), expected_status[i]) |
| 131 delete participant_pair.first; | 111 << "Mixed status of AudioSource #" << i << " wrong."; |
| 132 delete participant_pair.second; | |
| 133 } | |
| 134 participants_.clear(); | |
| 135 } | 112 } |
| 136 | 113 } |
|
aleloi
2016/08/18 09:21:14
Utility function for testing mixing priority order
| |
| 137 void ResetFrame(AudioFrame* audio_frame) { | |
| 138 audio_frame->sample_rate_hz_ = kSampleRateHz; | |
| 139 audio_frame->speech_type_ = AudioFrame::kNormalSpeech; | |
| 140 audio_frame->vad_activity_ = AudioFrame::kVadActive; | |
| 141 audio_frame->num_channels_ = 1; | |
| 142 } | |
| 143 | |
| 144 void AddParticipant(AudioFrame* audio_frame, | |
| 145 MixerParticipant::AudioFrameInfo audio_frame_info) { | |
| 146 auto old_participant = new MockAudioMixerParticipant; | |
| 147 auto new_participant = new MockMixerAudioSource; | |
| 148 old_participant->fake_frame()->CopyFrom(*audio_frame); | |
| 149 new_participant->fake_frame()->CopyFrom(*audio_frame); | |
| 150 old_participant->set_fake_info(audio_frame_info); | |
| 151 MixerAudioSource::AudioFrameInfo new_audio_frame_info; | |
| 152 switch (audio_frame_info) { | |
| 153 case MixerParticipant::AudioFrameInfo::kNormal: | |
| 154 new_audio_frame_info = MixerAudioSource::AudioFrameInfo::kNormal; | |
| 155 break; | |
| 156 case MixerParticipant::AudioFrameInfo::kMuted: | |
| 157 new_audio_frame_info = MixerAudioSource::AudioFrameInfo::kMuted; | |
| 158 break; | |
| 159 default: | |
| 160 new_audio_frame_info = MixerAudioSource::AudioFrameInfo::kError; | |
| 161 } | |
| 162 new_participant->set_fake_info(new_audio_frame_info); | |
| 163 participants_.emplace_back(old_participant, new_participant); | |
| 164 } | |
| 165 | |
| 166 void NewMixedAudio(const int32_t id, | |
| 167 const AudioFrame& generalAudioFrame, | |
| 168 const AudioFrame** uniqueAudioFrames, | |
| 169 const uint32_t size) override { | |
| 170 old_mixer_frame_.CopyFrom(generalAudioFrame); | |
| 171 } | |
| 172 | |
| 173 AudioFrame old_mixer_frame_; | |
| 174 AudioFrame new_mixer_frame_; | |
| 175 | |
| 176 std::vector<std::pair<MockAudioMixerParticipant*, MockMixerAudioSource*>> | |
| 177 participants_; | |
| 178 std::unique_ptr<AudioConferenceMixer> old_mixer_; | |
| 179 std::unique_ptr<NewAudioConferenceMixer> new_mixer_; | |
| 180 }; | |
|
aleloi
2016/08/18 09:21:14
Removed test class that compared mixing decisions
| |
| 181 | |
| 182 class BothMixersTest : public testing::Test { | |
| 183 protected: | |
| 184 BothMixersTest() { | |
| 185 // Create an OutputMixer. | |
| 186 AudioMixer::Create(audio_mixer_, kId); | |
| 187 | |
| 188 // Create one mixer participant and add it to the mixer. | |
| 189 EXPECT_EQ(0, audio_mixer_->SetMixabilityStatus(participant_, true)); | |
| 190 | |
| 191 // Each iteration, the participant will return a frame with this content: | |
| 192 participant_.fake_frame()->id_ = 1; | |
| 193 participant_.fake_frame()->sample_rate_hz_ = kSampleRateHz; | |
| 194 participant_.fake_frame()->speech_type_ = AudioFrame::kNormalSpeech; | |
| 195 participant_.fake_frame()->vad_activity_ = AudioFrame::kVadActive; | |
| 196 participant_.fake_frame()->num_channels_ = 1; | |
| 197 | |
| 198 // We modify one sample within the RampIn window and one sample | |
| 199 // outside of it. | |
| 200 participant_.fake_frame()->data_[10] = 100; | |
| 201 participant_.fake_frame()->data_[20] = -200; | |
| 202 participant_.fake_frame()->data_[30] = 300; | |
| 203 participant_.fake_frame()->data_[90] = -400; | |
| 204 | |
| 205 // Frame duration 10ms. | |
| 206 participant_.fake_frame()->samples_per_channel_ = kSampleRateHz / 100; | |
| 207 } | |
| 208 | |
| 209 ~BothMixersTest() { AudioMixer::Destroy(audio_mixer_); } | |
| 210 | |
| 211 // Mark the participant as 'unmixed' last round. | |
| 212 void ResetAudioSource() { participant_._mixHistory->SetIsMixed(false); } | |
| 213 | |
| 214 AudioMixer* audio_mixer_; | |
| 215 MockMixerAudioSource participant_; | |
| 216 AudioFrame mixing_round_frame, mixed_results_frame_; | |
| 217 | |
| 218 constexpr static int kSampleRateHz = 48000; | |
| 219 constexpr static int kId = 1; | |
| 220 }; | |
|
aleloi
2016/08/18 09:21:14
Removed the former OutputMixer (now AudioMixer) te
| |
| 221 | 114 |
| 222 TEST(AudioMixer, AnonymousAndNamed) { | 115 TEST(AudioMixer, AnonymousAndNamed) { |
| 223 constexpr int kId = 1; | |
| 224 // Should not matter even if partipants are more than | 116 // Should not matter even if partipants are more than |
| 225 // kMaximumAmountOfMixedAudioSources. | 117 // kMaximumAmountOfMixedAudioSources. |
| 226 constexpr int kNamed = | 118 constexpr int kNamed = |
| 227 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; | 119 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; |
| 228 constexpr int kAnonymous = | 120 constexpr int kAnonymous = |
| 229 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; | 121 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; |
| 230 | 122 |
| 231 std::unique_ptr<NewAudioConferenceMixer> mixer( | 123 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 232 NewAudioConferenceMixer::Create(kId)); | 124 NewAudioConferenceMixer::Create(kId)); |
| 233 | 125 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 } | 160 } |
| 269 | 161 |
| 270 // SetMixabilityStatus(anonymous, false) will remove anonymous from both | 162 // SetMixabilityStatus(anonymous, false) will remove anonymous from both |
| 271 // anonymous and named groups. | 163 // anonymous and named groups. |
| 272 EXPECT_EQ(0, mixer->SetMixabilityStatus(&anonymous[kAnonymous - 1], false)); | 164 EXPECT_EQ(0, mixer->SetMixabilityStatus(&anonymous[kAnonymous - 1], false)); |
| 273 EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[kAnonymous - 1])); | 165 EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[kAnonymous - 1])); |
| 274 EXPECT_FALSE(mixer->MixabilityStatus(anonymous[kAnonymous - 1])); | 166 EXPECT_FALSE(mixer->MixabilityStatus(anonymous[kAnonymous - 1])); |
| 275 } | 167 } |
| 276 | 168 |
| 277 TEST(AudioMixer, LargestEnergyVadActiveMixed) { | 169 TEST(AudioMixer, LargestEnergyVadActiveMixed) { |
| 278 const int kId = 1; | |
| 279 const int kAudioSources = | 170 const int kAudioSources = |
| 280 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 3; | 171 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 3; |
| 281 const int kSampleRateHz = 32000; | |
| 282 | 172 |
| 283 std::unique_ptr<NewAudioConferenceMixer> mixer( | 173 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 284 NewAudioConferenceMixer::Create(kId)); | 174 NewAudioConferenceMixer::Create(kId)); |
| 285 | 175 |
| 286 MockMixerAudioSource participants[kAudioSources]; | 176 MockMixerAudioSource participants[kAudioSources]; |
| 287 | 177 |
| 288 for (int i = 0; i < kAudioSources; ++i) { | 178 for (int i = 0; i < kAudioSources; ++i) { |
| 289 participants[i].fake_frame()->id_ = i; | 179 ResetFrame(participants[i].fake_frame()); |
| 290 participants[i].fake_frame()->sample_rate_hz_ = kSampleRateHz; | |
| 291 participants[i].fake_frame()->speech_type_ = AudioFrame::kNormalSpeech; | |
| 292 participants[i].fake_frame()->vad_activity_ = AudioFrame::kVadActive; | |
| 293 participants[i].fake_frame()->num_channels_ = 1; | |
| 294 | |
| 295 // Frame duration 10ms. | |
| 296 participants[i].fake_frame()->samples_per_channel_ = kSampleRateHz / 100; | |
| 297 | 180 |
| 298 // We set the 80-th sample value since the first 80 samples may be | 181 // We set the 80-th sample value since the first 80 samples may be |
| 299 // modified by a ramped-in window. | 182 // modified by a ramped-in window. |
| 300 participants[i].fake_frame()->data_[80] = i; | 183 participants[i].fake_frame()->data_[80] = i; |
| 301 | 184 |
| 302 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true)); | 185 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true)); |
| 303 EXPECT_CALL(participants[i], GetAudioFrameWithMuted(_, _)) | 186 EXPECT_CALL(participants[i], GetAudioFrameWithMuted(_, _)) |
| 304 .Times(Exactly(1)); | 187 .Times(Exactly(1)); |
| 305 } | 188 } |
| 306 | 189 |
| 307 // Last participant gives audio frame with passive VAD, although it has the | 190 // Last participant gives audio frame with passive VAD, although it has the |
| 308 // largest energy. | 191 // largest energy. |
| 309 participants[kAudioSources - 1].fake_frame()->vad_activity_ = | 192 participants[kAudioSources - 1].fake_frame()->vad_activity_ = |
| 310 AudioFrame::kVadPassive; | 193 AudioFrame::kVadPassive; |
| 311 | 194 |
| 312 AudioFrame audio_frame; | 195 AudioFrame audio_frame; |
| 313 mixer->Mix(kSampleRateHz, | 196 mixer->Mix(kDefaultSampleRateHz, |
| 314 1, // number of channels | 197 1, // number of channels |
| 315 &audio_frame); | 198 &audio_frame); |
| 316 | 199 |
| 317 for (int i = 0; i < kAudioSources; ++i) { | 200 for (int i = 0; i < kAudioSources; ++i) { |
| 318 bool is_mixed = participants[i].IsMixed(); | 201 bool is_mixed = participants[i].IsMixed(); |
| 319 if (i == kAudioSources - 1 || | 202 if (i == kAudioSources - 1 || |
| 320 i < kAudioSources - 1 - | 203 i < kAudioSources - 1 - |
| 321 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources) { | 204 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources) { |
| 322 EXPECT_FALSE(is_mixed) << "Mixing status of AudioSource #" << i | 205 EXPECT_FALSE(is_mixed) << "Mixing status of AudioSource #" << i |
| 323 << " wrong."; | 206 << " wrong."; |
| 324 } else { | 207 } else { |
| 325 EXPECT_TRUE(is_mixed) << "Mixing status of AudioSource #" << i | 208 EXPECT_TRUE(is_mixed) << "Mixing status of AudioSource #" << i |
| 326 << " wrong."; | 209 << " wrong."; |
| 327 } | 210 } |
| 328 } | 211 } |
| 329 } | 212 } |
| 330 | 213 |
| 331 TEST(AudioMixer, ParticipantSampleRate) { | 214 TEST(AudioMixer, ParticipantSampleRate) { |
| 332 const int kId = 1; | |
| 333 std::unique_ptr<NewAudioConferenceMixer> mixer( | 215 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 334 NewAudioConferenceMixer::Create(kId)); | 216 NewAudioConferenceMixer::Create(kId)); |
| 335 AudioFrame frame_for_mixing; | |
| 336 | 217 |
| 337 MockMixerAudioSource participant; | 218 MockMixerAudioSource participant; |
| 338 participant.fake_frame()->sample_rate_hz_ = 8000; | 219 ResetFrame(participant.fake_frame()); |
| 339 participant.fake_frame()->num_channels_ = 1; | |
| 340 | |
| 341 // Frame duration 10ms. | |
| 342 participant.fake_frame()->samples_per_channel_ = 8000 / 100; | |
| 343 | 220 |
| 344 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); | 221 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); |
| 345 for (auto frequency : {8000, 16000, 32000, 48000}) { | 222 for (auto frequency : {8000, 16000, 32000, 48000}) { |
| 346 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, frequency)) | 223 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, frequency)) |
| 347 .Times(Exactly(1)); | 224 .Times(Exactly(1)); |
| 348 mixer->Mix(frequency, 1, &frame_for_mixing); | 225 mixer->Mix(frequency, 1, &frame_for_mixing); |
| 349 EXPECT_EQ(frequency, frame_for_mixing.sample_rate_hz_); | 226 EXPECT_EQ(frequency, frame_for_mixing.sample_rate_hz_); |
| 350 } | 227 } |
| 351 } | 228 } |
| 352 | 229 |
| 353 TEST(AudioMixer, ParticipantNumberOfChannels) { | 230 TEST(AudioMixer, ParticipantNumberOfChannels) { |
| 354 const int kId = 1; | |
| 355 std::unique_ptr<NewAudioConferenceMixer> mixer( | 231 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 356 NewAudioConferenceMixer::Create(kId)); | 232 NewAudioConferenceMixer::Create(kId)); |
| 357 AudioFrame frame_for_mixing; | |
| 358 | 233 |
| 359 MockMixerAudioSource participant; | 234 MockMixerAudioSource participant; |
| 360 participant.fake_frame()->sample_rate_hz_ = 8000; | 235 ResetFrame(participant.fake_frame()); |
| 361 participant.fake_frame()->num_channels_ = 1; | |
| 362 | |
| 363 // Frame duration 10ms. | |
| 364 participant.fake_frame()->samples_per_channel_ = 8000 / 100; | |
| 365 | 236 |
| 366 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); | 237 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); |
| 367 for (size_t number_of_channels : {1, 2}) { | 238 for (size_t number_of_channels : {1, 2}) { |
| 368 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, 8000)).Times(Exactly(1)); | 239 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) |
| 369 mixer->Mix(8000, number_of_channels, &frame_for_mixing); | 240 .Times(Exactly(1)); |
| 241 mixer->Mix(kDefaultSampleRateHz, number_of_channels, &frame_for_mixing); | |
| 370 EXPECT_EQ(number_of_channels, frame_for_mixing.num_channels_); | 242 EXPECT_EQ(number_of_channels, frame_for_mixing.num_channels_); |
| 371 } | 243 } |
| 372 } | 244 } |
| 373 | 245 |
| 374 // Test that the volume is reported as zero when the mixer input | 246 // Test that the volume is reported as zero when the mixer input |
| 375 // comprises only zero values. | 247 // comprises only zero values. |
| 376 TEST(AudioMixer, LevelIsZeroWhenMixingZeroes) { | 248 TEST(AudioMixer, LevelIsZeroWhenMixingZeroes) { |
| 377 const int kId = 1; | |
| 378 const int kSampleRateHz = 8000; | |
| 379 std::unique_ptr<NewAudioConferenceMixer> mixer( | 249 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 380 NewAudioConferenceMixer::Create(kId)); | 250 NewAudioConferenceMixer::Create(kId)); |
| 381 AudioFrame frame_for_mixing; | |
| 382 | 251 |
| 383 MockMixerAudioSource participant; | 252 MockMixerAudioSource participant; |
| 384 participant.fake_frame()->sample_rate_hz_ = kSampleRateHz; | 253 ResetFrame(participant.fake_frame()); |
| 385 participant.fake_frame()->num_channels_ = 1; | |
| 386 | |
| 387 // Frame duration 10ms. | |
| 388 participant.fake_frame()->samples_per_channel_ = kSampleRateHz / 100; | |
| 389 | 254 |
| 390 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); | 255 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); |
| 391 for (size_t i = 0; i < 11; i++) { | 256 for (size_t i = 0; i < 11; i++) { |
| 392 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, kSampleRateHz)) | 257 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) |
| 393 .Times(Exactly(1)); | 258 .Times(Exactly(1)); |
| 394 mixer->Mix(8000, 1, &frame_for_mixing); | 259 mixer->Mix(kDefaultSampleRateHz, 1, &frame_for_mixing); |
| 395 } | 260 } |
| 396 | 261 |
| 397 EXPECT_EQ(static_cast<uint32_t>(0), mixer->GetOutputAudioLevel()); | 262 EXPECT_EQ(static_cast<uint32_t>(0), mixer->GetOutputAudioLevel()); |
| 398 EXPECT_EQ(static_cast<uint32_t>(0), mixer->GetOutputAudioLevelFullRange()); | 263 EXPECT_EQ(static_cast<uint32_t>(0), mixer->GetOutputAudioLevelFullRange()); |
| 399 } | 264 } |
| 400 | 265 |
| 401 // Test that the reported volume is maximal as full when the mixer | 266 // Test that the reported volume is maximal as full when the mixer |
| 402 // input comprises frames with maximal values. | 267 // input comprises frames with maximal values. |
| 403 TEST(AudioMixer, LevelIsMaximalWhenMixingMaximalValues) { | 268 TEST(AudioMixer, LevelIsMaximalWhenMixingMaximalValues) { |
| 404 const int kId = 1; | |
| 405 const int kSampleRateHz = 8000; | |
| 406 std::unique_ptr<NewAudioConferenceMixer> mixer( | 269 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 407 NewAudioConferenceMixer::Create(kId)); | 270 NewAudioConferenceMixer::Create(kId)); |
| 408 AudioFrame frame_for_mixing; | |
| 409 | 271 |
| 410 MockMixerAudioSource participant; | 272 MockMixerAudioSource participant; |
| 411 participant.fake_frame()->sample_rate_hz_ = kSampleRateHz; | 273 ResetFrame(participant.fake_frame()); |
| 412 participant.fake_frame()->num_channels_ = 1; | |
| 413 | |
| 414 // Frame duration 10ms. | |
| 415 participant.fake_frame()->samples_per_channel_ = kSampleRateHz / 100; | |
| 416 | 274 |
| 417 // Fill participant frame data with maximal sound. | 275 // Fill participant frame data with maximal sound. |
| 418 std::fill(participant.fake_frame()->data_, | 276 std::fill(participant.fake_frame()->data_, |
| 419 participant.fake_frame()->data_ + kSampleRateHz / 100, | 277 participant.fake_frame()->data_ + kDefaultSampleRateHz / 100, |
| 420 std::numeric_limits<int16_t>::max()); | 278 std::numeric_limits<int16_t>::max()); |
| 421 | 279 |
| 422 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); | 280 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant, true)); |
| 423 for (size_t i = 0; i < 11; i++) { | 281 for (size_t i = 0; i < 11; i++) { |
| 424 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, kSampleRateHz)) | 282 EXPECT_CALL(participant, GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) |
| 425 .Times(Exactly(1)); | 283 .Times(Exactly(1)); |
| 426 mixer->Mix(8000, 1, &frame_for_mixing); | 284 mixer->Mix(kDefaultSampleRateHz, 1, &frame_for_mixing); |
| 427 } | 285 } |
| 428 | 286 |
| 429 // 9 is the highest possible audio level | 287 // 9 is the highest possible audio level |
| 430 EXPECT_EQ(static_cast<uint32_t>(9), mixer->GetOutputAudioLevel()); | 288 EXPECT_EQ(static_cast<uint32_t>(9), mixer->GetOutputAudioLevel()); |
| 431 | 289 |
| 432 // 0x7fff = 32767 is the highest full range audio level. | 290 // 0x7fff = 32767 is the highest full range audio level. |
| 433 EXPECT_EQ(static_cast<uint32_t>(std::numeric_limits<int16_t>::max()), | 291 EXPECT_EQ(static_cast<uint32_t>(std::numeric_limits<int16_t>::max()), |
| 434 mixer->GetOutputAudioLevelFullRange()); | 292 mixer->GetOutputAudioLevelFullRange()); |
| 435 } | 293 } |
| 436 | 294 |
| 437 TEST_F(BothMixersTest, CompareInitialFrameAudio) { | 295 // Test that the reported volume is maximal as full when the mixer |
| 438 EXPECT_CALL(participant_, GetAudioFrameWithMuted(_, _)).Times(Exactly(1)); | 296 // input comprises frames with maximal values. |
| 297 TEST(AudioMixer, VolumeTwoParticipants) { | |
| 298 std::unique_ptr<NewAudioConferenceMixer> mixer( | |
| 299 NewAudioConferenceMixer::Create(kId)); | |
| 439 | 300 |
| 440 // Make sure the participant is marked as 'non-mixed' so that it is | 301 MockMixerAudioSource participant1, participant2; |
| 441 // ramped in next round. | 302 ResetFrame(participant1.fake_frame()); |
| 442 ResetAudioSource(); | 303 ResetFrame(participant2.fake_frame()); |
| 443 | 304 |
| 444 // Construct the expected sound for the first mixing round. | 305 // Fill participant1 frame data with maximal sound. |
| 445 mixing_round_frame.CopyFrom(*participant_.fake_frame()); | 306 std::fill(participant1.fake_frame()->data_, |
| 446 RampIn(mixing_round_frame); | 307 participant1.fake_frame()->data_ + kDefaultSampleRateHz / 100, 0); |
| 308 std::fill(participant2.fake_frame()->data_, | |
| 309 participant2.fake_frame()->data_ + kDefaultSampleRateHz / 100, | |
| 310 std::numeric_limits<int16_t>::max()); | |
| 447 | 311 |
| 448 // Mix frames and put the result into a frame. | 312 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant1, true)); |
| 449 audio_mixer_->GetMixedAudio(kSampleRateHz, 1, &mixed_results_frame_); | 313 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participant2, true)); |
| 450 | 314 for (size_t i = 0; i < 11; i++) { |
| 451 // Compare the received frame with the expected. | 315 EXPECT_CALL(participant1, GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) |
| 452 EXPECT_EQ(mixing_round_frame.sample_rate_hz_, | 316 .Times(Exactly(1)); |
| 453 mixed_results_frame_.sample_rate_hz_); | 317 EXPECT_CALL(participant2, GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) |
| 454 EXPECT_EQ(mixing_round_frame.num_channels_, | 318 .Times(Exactly(1)); |
| 455 mixed_results_frame_.num_channels_); | 319 mixer->Mix(kDefaultSampleRateHz, 1, &frame_for_mixing); |
| 456 EXPECT_EQ(mixing_round_frame.samples_per_channel_, | |
| 457 mixed_results_frame_.samples_per_channel_); | |
| 458 EXPECT_EQ(0, memcmp(mixing_round_frame.data_, mixed_results_frame_.data_, | |
| 459 sizeof(mixing_round_frame.data_))); | |
| 460 } | |
| 461 | |
| 462 TEST_F(BothMixersTest, CompareSecondFrameAudio) { | |
| 463 EXPECT_CALL(participant_, GetAudioFrameWithMuted(_, _)).Times(Exactly(2)); | |
| 464 | |
| 465 // Make sure the participant is marked as 'non-mixed' so that it is | |
| 466 // ramped in next round. | |
| 467 ResetAudioSource(); | |
| 468 | |
| 469 // Do one mixing iteration. | |
| 470 audio_mixer_->GetMixedAudio(kSampleRateHz, 1, &mixed_results_frame_); | |
| 471 | |
| 472 // Mix frames a second time and compare with the expected frame | |
| 473 // (which is the participant's frame). | |
| 474 audio_mixer_->GetMixedAudio(kSampleRateHz, 1, &mixed_results_frame_); | |
| 475 EXPECT_EQ(0, | |
| 476 memcmp(participant_.fake_frame()->data_, mixed_results_frame_.data_, | |
| 477 sizeof(mixing_round_frame.data_))); | |
| 478 } | |
| 479 | |
| 480 TEST_F(CompareWithOldMixerTest, TwoParticipantsNormalFrames) { | |
| 481 Reset(); | |
| 482 AudioFrame first_frame, second_frame; | |
| 483 | |
| 484 ResetFrame(&first_frame); | |
| 485 ResetFrame(&second_frame); | |
| 486 | |
| 487 first_frame.id_ = 1; | |
| 488 second_frame.id_ = 2; | |
| 489 | |
| 490 AddParticipant(&first_frame, MixerParticipant::AudioFrameInfo::kNormal); | |
| 491 AddParticipant(&second_frame, MixerParticipant::AudioFrameInfo::kNormal); | |
| 492 | |
| 493 for (int i = 0; i < 3; ++i) { | |
| 494 MixAndCompare(); | |
| 495 } | 320 } |
| 496 } | 321 } |
| 497 | 322 |
| 498 TEST_F(CompareWithOldMixerTest, ThreeParticipantsDifferentFrames) { | 323 // Maximal amount of participants are mixed one iteration, then |
| 499 Reset(); | 324 // another participant with higher energy is added. |
| 500 AudioFrame first_frame, second_frame, third_frame; | 325 TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) { |
| 326 const int kAudioSources = | |
| 327 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; | |
| 501 | 328 |
| 502 ResetFrame(&first_frame); | 329 std::unique_ptr<NewAudioConferenceMixer> mixer( |
| 503 ResetFrame(&second_frame); | 330 NewAudioConferenceMixer::Create(kId)); |
| 504 ResetFrame(&third_frame); | 331 MockMixerAudioSource participants[kAudioSources]; |
| 505 | 332 |
| 506 first_frame.id_ = 1; | 333 for (size_t i = 0; i < kAudioSources; i++) { |
| 507 second_frame.id_ = 2; | 334 ResetFrame(participants[i].fake_frame()); |
| 508 third_frame.id_ = 3; | 335 participants[i].fake_frame()->data_[0] = 100 * i; |
| 509 second_frame.vad_activity_ = AudioFrame::kVadPassive; | 336 } |
| 510 | 337 |
| 511 AddParticipant(&first_frame, MixerParticipant::AudioFrameInfo::kNormal); | 338 for (size_t i = 0; i < kAudioSources - 1; i++) { |
| 512 AddParticipant(&second_frame, MixerParticipant::AudioFrameInfo::kMuted); | 339 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true)); |
| 513 AddParticipant(&third_frame, MixerParticipant::AudioFrameInfo::kMuted); | 340 EXPECT_CALL(participants[i], |
| 341 GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) | |
| 342 .Times(Exactly(1)); | |
| 343 } | |
| 514 | 344 |
| 515 for (int i = 0; i < 3; ++i) { | 345 // First mixer iteration |
| 516 MixAndCompare(); | 346 mixer->Mix(kDefaultSampleRateHz, 1, &frame_for_mixing); |
| 347 | |
| 348 // All participants should have been mixed. | |
| 349 for (size_t i = 0; i < kAudioSources - 1; i++) { | |
| 350 EXPECT_TRUE(participants[i].IsMixed()) << "Mixed status of AudioSource #" | |
| 351 << i << " wrong."; | |
| 352 } | |
| 353 | |
| 354 // Add new participant with higher energy. | |
| 355 EXPECT_EQ(0, | |
| 356 mixer->SetMixabilityStatus(&participants[kAudioSources - 1], true)); | |
| 357 for (size_t i = 0; i < kAudioSources; i++) { | |
| 358 EXPECT_CALL(participants[i], | |
| 359 GetAudioFrameWithMuted(_, kDefaultSampleRateHz)) | |
| 360 .Times(Exactly(1)); | |
| 361 } | |
| 362 | |
| 363 mixer->Mix(kDefaultSampleRateHz, 1, &frame_for_mixing); | |
| 364 EXPECT_FALSE(participants[0].IsMixed()) | |
| 365 << "Mixed status of AudioSource #0 wrong."; | |
| 366 | |
| 367 for (size_t i = 1; i < kAudioSources; i++) { | |
| 368 EXPECT_EQ(participants[i].IsMixed(), true) | |
| 369 << "Mixed status of AudioSource #" << i << " wrong."; | |
| 517 } | 370 } |
| 518 } | 371 } |
| 519 | 372 |
| 520 TEST_F(CompareWithOldMixerTest, ManyParticipantsDifferentFrames) { | 373 TEST(AudioMixer, MutedShouldMixAfterUnmuted) { |
| 521 Reset(); | 374 const int kAudioSources = |
| 522 constexpr int kNumParticipants = 20; | 375 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; |
| 523 AudioFrame audio_frames[kNumParticipants]; | |
| 524 | 376 |
| 525 for (int i = 0; i < kNumParticipants; ++i) { | 377 std::vector<AudioFrame> frames(kAudioSources); |
| 526 ResetFrame(&audio_frames[i]); | 378 for (auto& frame : frames) { |
| 527 audio_frames[i].id_ = 1; | 379 ResetFrame(&frame); |
| 528 audio_frames[i].data_[10] = 100 * (i % 5); | |
| 529 audio_frames[i].data_[100] = 100 * (i % 5); | |
| 530 if (i % 2 == 0) { | |
| 531 audio_frames[i].vad_activity_ = AudioFrame::kVadPassive; | |
| 532 } | |
| 533 } | 380 } |
| 534 | 381 |
| 535 for (int i = 0; i < kNumParticipants; ++i) { | 382 std::vector<MixerAudioSource::AudioFrameInfo> frame_info( |
| 536 if (i % 2 == 0) { | 383 kAudioSources, MixerAudioSource::AudioFrameInfo::kNormal); |
| 537 AddParticipant(&audio_frames[i], | 384 frame_info[0] = MixerAudioSource::AudioFrameInfo::kMuted; |
| 538 MixerParticipant::AudioFrameInfo::kMuted); | 385 std::vector<bool> expected_status(kAudioSources, true); |
| 539 } else { | 386 expected_status[0] = false; |
| 540 AddParticipant(&audio_frames[i], | 387 |
| 541 MixerParticipant::AudioFrameInfo::kNormal); | 388 MixAndCompare(frames, frame_info, expected_status); |
| 542 } | |
| 543 MixAndCompare(); | |
| 544 } | |
| 545 } | 389 } |
| 546 | 390 |
| 391 TEST(AudioMixer, PassiveShouldMixAfterNormal) { | |
| 392 const int kAudioSources = | |
| 393 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; | |
| 394 | |
| 395 std::vector<AudioFrame> frames(kAudioSources); | |
| 396 for (auto& frame : frames) { | |
| 397 ResetFrame(&frame); | |
| 398 } | |
| 399 | |
| 400 std::vector<MixerAudioSource::AudioFrameInfo> frame_info( | |
| 401 kAudioSources, MixerAudioSource::AudioFrameInfo::kNormal); | |
| 402 frames[0].vad_activity_ = AudioFrame::kVadPassive; | |
| 403 std::vector<bool> expected_status(kAudioSources, true); | |
| 404 expected_status[0] = false; | |
| 405 | |
| 406 MixAndCompare(frames, frame_info, expected_status); | |
| 407 } | |
| 408 | |
| 409 TEST(AudioMixer, ActiveShouldMixBeforeLoud) { | |
| 410 const int kAudioSources = | |
| 411 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; | |
| 412 | |
| 413 std::vector<AudioFrame> frames(kAudioSources); | |
| 414 for (auto& frame : frames) { | |
| 415 ResetFrame(&frame); | |
| 416 } | |
| 417 | |
| 418 std::vector<MixerAudioSource::AudioFrameInfo> frame_info( | |
| 419 kAudioSources, MixerAudioSource::AudioFrameInfo::kNormal); | |
| 420 frames[0].vad_activity_ = AudioFrame::kVadPassive; | |
| 421 std::fill(frames[0].data_, frames[0].data_ + kDefaultSampleRateHz / 100, | |
| 422 std::numeric_limits<int16_t>::max()); | |
| 423 std::vector<bool> expected_status(kAudioSources, true); | |
| 424 expected_status[0] = false; | |
| 425 | |
| 426 MixAndCompare(frames, frame_info, expected_status); | |
| 427 } | |
| 428 | |
| 429 TEST(AudioMixer, UnmutedShouldMixBeforeLoud) { | |
| 430 const int kAudioSources = | |
| 431 NewAudioConferenceMixer::kMaximumAmountOfMixedAudioSources + 1; | |
| 432 | |
| 433 std::vector<AudioFrame> frames(kAudioSources); | |
| 434 for (auto& frame : frames) { | |
| 435 ResetFrame(&frame); | |
| 436 } | |
| 437 | |
| 438 std::vector<MixerAudioSource::AudioFrameInfo> frame_info( | |
| 439 kAudioSources, MixerAudioSource::AudioFrameInfo::kNormal); | |
| 440 frame_info[0] = MixerAudioSource::AudioFrameInfo::kMuted; | |
| 441 std::fill(frames[0].data_, frames[0].data_ + kDefaultSampleRateHz / 100, | |
| 442 std::numeric_limits<int16_t>::max()); | |
| 443 std::vector<bool> expected_status(kAudioSources, true); | |
| 444 expected_status[0] = false; | |
| 445 | |
| 446 MixAndCompare(frames, frame_info, expected_status); | |
| 447 } | |
| 547 } // namespace webrtc | 448 } // namespace webrtc |
| OLD | NEW |