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

Side by Side Diff: webrtc/voice_engine/test/auto_test/standard/mixing_test.cc

Issue 2756263002: Remove mixing_test.cc. (Closed)
Patch Set: rebase Created 3 years, 9 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
« no previous file with comments | « webrtc/voice_engine/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 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
11 #include <stdio.h>
12 #include <string>
13
14 #include "webrtc/system_wrappers/include/sleep.h"
15 #include "webrtc/test/testsupport/fileutils.h"
16 #include "webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixtu re.h"
17
18 namespace webrtc {
19 namespace {
20
21 const int16_t kLimiterHeadroom = 29204; // == -1 dbFS
22 const int16_t kInt16Max = 0x7fff;
23 const int kPayloadType = 105;
24 const int kInSampleRateHz = 16000; // Input file taken as 16 kHz by default.
25 const int kRecSampleRateHz = 16000; // Recorded with 16 kHz L16.
26 const int kTestDurationMs = 3000;
27 const CodecInst kCodecL16 = {kPayloadType, "L16", 16000, 160, 1, 256000};
28 const CodecInst kCodecOpus = {kPayloadType, "opus", 48000, 960, 1, 32000};
29
30 } // namespace
31
32 class MixingTest : public AfterInitializationFixture {
33 protected:
34 MixingTest()
35 : output_filename_(test::OutputPath() + "mixing_test_output.pcm") {
36 }
37 void SetUp() {
38 transport_ = new LoopBackTransport(voe_network_, 0);
39 }
40 void TearDown() {
41 delete transport_;
42 }
43
44 // Creates and mixes |num_remote_streams| which play a file "as microphone"
45 // with |num_local_streams| which play a file "locally", using a constant
46 // amplitude of |input_value|. The local streams manifest as "anonymous"
47 // mixing participants, meaning they will be mixed regardless of the number
48 // of participants. (A stream is a VoiceEngine "channel").
49 //
50 // The mixed output is verified to always fall between |max_output_value| and
51 // |min_output_value|, after a startup phase.
52 //
53 // |num_remote_streams_using_mono| of the remote streams use mono, with the
54 // remainder using stereo.
55 void RunMixingTest(int num_remote_streams,
56 int num_local_streams,
57 int num_remote_streams_using_mono,
58 bool real_audio,
59 int16_t input_value,
60 int16_t max_output_value,
61 int16_t min_output_value,
62 const CodecInst& codec_inst) {
63 ASSERT_LE(num_remote_streams_using_mono, num_remote_streams);
64
65 if (real_audio) {
66 input_filename_ = test::ResourcePath("voice_engine/audio_long16", "pcm");
67 } else {
68 input_filename_ = test::OutputPath() + "mixing_test_input.pcm";
69 GenerateInputFile(input_value);
70 }
71
72 std::vector<int> local_streams(num_local_streams);
73 for (size_t i = 0; i < local_streams.size(); ++i) {
74 local_streams[i] = voe_base_->CreateChannel();
75 EXPECT_NE(-1, local_streams[i]);
76 }
77 StartLocalStreams(local_streams);
78 TEST_LOG("Playing %d local streams.\n", num_local_streams);
79
80 std::vector<int> remote_streams(num_remote_streams);
81 for (size_t i = 0; i < remote_streams.size(); ++i) {
82 remote_streams[i] = voe_base_->CreateChannel();
83 EXPECT_NE(-1, remote_streams[i]);
84 }
85 StartRemoteStreams(remote_streams, num_remote_streams_using_mono,
86 codec_inst);
87 TEST_LOG("Playing %d remote streams.\n", num_remote_streams);
88
89 // Give it plenty of time to get started.
90 SleepMs(1000);
91
92 // Start recording the mixed output and wait.
93 EXPECT_EQ(0, voe_file_->StartRecordingPlayout(-1 /* record meeting */,
94 output_filename_.c_str()));
95 SleepMs(kTestDurationMs);
96 while (GetFileDurationMs(output_filename_.c_str()) < kTestDurationMs) {
97 SleepMs(200);
98 }
99 EXPECT_EQ(0, voe_file_->StopRecordingPlayout(-1));
100
101 StopLocalStreams(local_streams);
102 StopRemoteStreams(remote_streams);
103
104 if (!real_audio) {
105 VerifyMixedOutput(max_output_value, min_output_value);
106 }
107 }
108
109 private:
110 // Generate input file with constant values equal to |input_value|. The file
111 // will be twice the duration of the test.
112 void GenerateInputFile(int16_t input_value) {
113 FILE* input_file = fopen(input_filename_.c_str(), "wb");
114 ASSERT_TRUE(input_file != NULL);
115 for (int i = 0; i < kInSampleRateHz / 1000 * (kTestDurationMs * 2); i++) {
116 ASSERT_EQ(1u, fwrite(&input_value, sizeof(input_value), 1, input_file));
117 }
118 ASSERT_EQ(0, fclose(input_file));
119 }
120
121 void VerifyMixedOutput(int16_t max_output_value, int16_t min_output_value) {
122 // Verify the mixed output.
123 FILE* output_file = fopen(output_filename_.c_str(), "rb");
124 ASSERT_TRUE(output_file != NULL);
125 int16_t output_value = 0;
126 int samples_read = 0;
127 while (fread(&output_value, sizeof(output_value), 1, output_file) == 1) {
128 samples_read++;
129 std::ostringstream trace_stream;
130 trace_stream << samples_read << " samples read";
131 SCOPED_TRACE(trace_stream.str());
132 ASSERT_LE(output_value, max_output_value);
133 ASSERT_GE(output_value, min_output_value);
134 }
135 // Ensure we've at least recorded half as much file as the duration of the
136 // test. We have to use a relaxed tolerance here due to filesystem flakiness
137 // on the bots.
138 ASSERT_GE((samples_read * 1000.0) / kRecSampleRateHz, kTestDurationMs);
139 // Ensure we read the entire file.
140 ASSERT_NE(0, feof(output_file));
141 ASSERT_EQ(0, fclose(output_file));
142 }
143
144 // Start up local streams ("anonymous" participants).
145 void StartLocalStreams(const std::vector<int>& streams) {
146 for (size_t i = 0; i < streams.size(); ++i) {
147 EXPECT_EQ(0, voe_base_->StartPlayout(streams[i]));
148 EXPECT_EQ(0, voe_file_->StartPlayingFileLocally(streams[i],
149 input_filename_.c_str(), true));
150 }
151 }
152
153 void StopLocalStreams(const std::vector<int>& streams) {
154 for (size_t i = 0; i < streams.size(); ++i) {
155 EXPECT_EQ(0, voe_base_->StopPlayout(streams[i]));
156 EXPECT_EQ(0, voe_base_->DeleteChannel(streams[i]));
157 }
158 }
159
160 // Start up remote streams ("normal" participants).
161 void StartRemoteStreams(const std::vector<int>& streams,
162 int num_remote_streams_using_mono,
163 const CodecInst& codec_inst) {
164 for (int i = 0; i < num_remote_streams_using_mono; ++i) {
165 // Add some delay between starting up the channels in order to give them
166 // different energies in the "real audio" test and hopefully exercise
167 // more code paths.
168 SleepMs(50);
169 StartRemoteStream(streams[i], codec_inst, 1234 + 2 * i);
170 }
171
172 // The remainder of the streams will use stereo.
173 CodecInst codec_inst_stereo = codec_inst;
174 codec_inst_stereo.channels = 2;
175 codec_inst_stereo.pltype++;
176 for (size_t i = num_remote_streams_using_mono; i < streams.size(); ++i) {
177 StartRemoteStream(streams[i], codec_inst_stereo, 1234 + 2 * i);
178 }
179 }
180
181 // Start up a single remote stream.
182 void StartRemoteStream(int stream, const CodecInst& codec_inst, int port) {
183 EXPECT_EQ(0, voe_codec_->SetRecPayloadType(stream, codec_inst));
184 EXPECT_EQ(0, voe_network_->RegisterExternalTransport(stream, *transport_));
185 EXPECT_EQ(0, voe_rtp_rtcp_->SetLocalSSRC(
186 stream, static_cast<unsigned int>(stream)));
187 transport_->AddChannel(stream, stream);
188 EXPECT_EQ(0, voe_base_->StartPlayout(stream));
189 EXPECT_EQ(0, voe_codec_->SetSendCodec(stream, codec_inst));
190 EXPECT_EQ(0, voe_base_->StartSend(stream));
191 EXPECT_EQ(0, voe_file_->StartPlayingFileAsMicrophone(stream,
192 input_filename_.c_str(), true));
193 }
194
195 void StopRemoteStreams(const std::vector<int>& streams) {
196 for (size_t i = 0; i < streams.size(); ++i) {
197 EXPECT_EQ(0, voe_base_->StopSend(streams[i]));
198 EXPECT_EQ(0, voe_base_->StopPlayout(streams[i]));
199 EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(streams[i]));
200 EXPECT_EQ(0, voe_base_->DeleteChannel(streams[i]));
201 }
202 }
203
204 int GetFileDurationMs(const char* file_name) {
205 FILE* fid = fopen(file_name, "rb");
206 EXPECT_FALSE(fid == NULL);
207 fseek(fid, 0, SEEK_END);
208 int size = ftell(fid);
209 EXPECT_NE(-1, size);
210 fclose(fid);
211 // Divided by 2 due to 2 bytes/sample.
212 return size * 1000 / kRecSampleRateHz / 2;
213 }
214
215 std::string input_filename_;
216 const std::string output_filename_;
217 LoopBackTransport* transport_;
218 };
219
220 // This test has no verification, but exercises additional code paths in a
221 // somewhat more realistic scenario using real audio. It can at least hunt for
222 // asserts and crashes.
223 TEST_F(MixingTest, MixManyChannelsForStress) {
224 RunMixingTest(10, 0, 10, true, 0, 0, 0, kCodecL16);
225 }
226
227 TEST_F(MixingTest, MixManyChannelsForStressOpus) {
228 RunMixingTest(10, 0, 10, true, 0, 0, 0, kCodecOpus);
229 }
230
231 // These tests assume a maximum of three mixed participants. We typically allow
232 // a +/- 10% range around the expected output level to account for distortion
233 // from coding and processing in the loopback chain.
234 TEST_F(MixingTest, FourChannelsWithOnlyThreeMixed) {
235 const int16_t kInputValue = 1000;
236 const int16_t kExpectedOutput = kInputValue * 3;
237 RunMixingTest(4, 0, 4, false, kInputValue, 1.1 * kExpectedOutput,
238 0.9 * kExpectedOutput, kCodecL16);
239 }
240
241 // Ensure the mixing saturation protection is working. We can do this because
242 // the mixing limiter is given some headroom, so the expected output is less
243 // than full scale.
244 TEST_F(MixingTest, VerifySaturationProtection) {
245 const int16_t kInputValue = 20000;
246 const int16_t kExpectedOutput = kLimiterHeadroom;
247 // If this isn't satisfied, we're not testing anything.
248 ASSERT_GT(kInputValue * 3, kInt16Max);
249 ASSERT_LT(1.1 * kExpectedOutput, kInt16Max);
250 RunMixingTest(3, 0, 3, false, kInputValue, 1.1 * kExpectedOutput,
251 0.9 * kExpectedOutput, kCodecL16);
252 }
253
254 TEST_F(MixingTest, SaturationProtectionHasNoEffectOnOneChannel) {
255 const int16_t kInputValue = kInt16Max;
256 const int16_t kExpectedOutput = kInt16Max;
257 // If this isn't satisfied, we're not testing anything.
258 ASSERT_GT(0.95 * kExpectedOutput, kLimiterHeadroom);
259 // Tighter constraints are required here to properly test this.
260 RunMixingTest(1, 0, 1, false, kInputValue, kExpectedOutput,
261 0.95 * kExpectedOutput, kCodecL16);
262 }
263
264 TEST_F(MixingTest, VerifyAnonymousAndNormalParticipantMixing) {
265 const int16_t kInputValue = 1000;
266 const int16_t kExpectedOutput = kInputValue * 2;
267 RunMixingTest(1, 1, 1, false, kInputValue, 1.1 * kExpectedOutput,
268 0.9 * kExpectedOutput, kCodecL16);
269 }
270
271 TEST_F(MixingTest, AnonymousParticipantsAreAlwaysMixed) {
272 const int16_t kInputValue = 1000;
273 const int16_t kExpectedOutput = kInputValue * 4;
274 RunMixingTest(3, 1, 3, false, kInputValue, 1.1 * kExpectedOutput,
275 0.9 * kExpectedOutput, kCodecL16);
276 }
277
278 TEST_F(MixingTest, VerifyStereoAndMonoMixing) {
279 const int16_t kInputValue = 1000;
280 const int16_t kExpectedOutput = kInputValue * 2;
281 RunMixingTest(2, 0, 1, false, kInputValue, 1.1 * kExpectedOutput,
282 // Lower than 0.9 due to observed flakiness on bots.
283 0.8 * kExpectedOutput, kCodecL16);
284 }
285
286 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/voice_engine/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698