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

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

Issue 2776113002: Send data from mixer to APM limiter more often. (Closed)
Patch Set: Test 1 not needed. Created 3 years, 8 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) 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2017 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 "webrtc/modules/audio_mixer/frame_combiner.h" 11 #include "webrtc/modules/audio_mixer/frame_combiner.h"
12 12
13 #include <numeric> 13 #include <numeric>
14 #include <sstream> 14 #include <sstream>
15 #include <string> 15 #include <string>
16 16
17 #include "webrtc/audio/utility/audio_frame_operations.h"
17 #include "webrtc/base/checks.h" 18 #include "webrtc/base/checks.h"
19 #include "webrtc/modules/audio_mixer/frame_combiner_test_tools.h"
18 #include "webrtc/test/gtest.h" 20 #include "webrtc/test/gtest.h"
19 21
20 namespace webrtc { 22 namespace webrtc {
21 23
22 namespace { 24 namespace {
23 std::string ProduceDebugText(int sample_rate_hz, 25 std::string ProduceDebugText(int sample_rate_hz,
24 int number_of_channels, 26 int number_of_channels,
25 int number_of_sources) { 27 int number_of_sources) {
26 std::ostringstream ss; 28 std::ostringstream ss;
27 ss << "Sample rate: " << sample_rate_hz << " "; 29 ss << "Sample rate: " << sample_rate_hz << " ,";
28 ss << "Number of channels: " << number_of_channels << " "; 30 ss << "number of channels: " << number_of_channels << " ,";
29 ss << "Number of sources: " << number_of_sources; 31 ss << "number of sources: " << number_of_sources;
30 return ss.str(); 32 return ss.str();
31 } 33 }
32 34
35 std::string ProduceDebugText(int sample_rate_hz,
36 int number_of_channels,
37 int number_of_sources,
38 bool limiter_active,
39 float wave_frequency) {
40 std::ostringstream ss;
41 ss << "Sample rate: " << sample_rate_hz << " ,";
42 ss << "number of channels: " << number_of_channels << " ,";
43 ss << "number of sources: " << number_of_sources << " ,";
44 ss << "limiter active: " << limiter_active << " ,";
45 ss << "wave frequency: " << wave_frequency << " ,";
46 return ss.str();
47 }
48
33 AudioFrame frame1; 49 AudioFrame frame1;
34 AudioFrame frame2; 50 AudioFrame frame2;
35 AudioFrame audio_frame_for_mixing; 51 AudioFrame audio_frame_for_mixing;
36 52
37 void SetUpFrames(int sample_rate_hz, int number_of_channels) { 53 void SetUpFrames(int sample_rate_hz, int number_of_channels) {
38 for (auto* frame : {&frame1, &frame2}) { 54 for (auto* frame : {&frame1, &frame2}) {
39 frame->UpdateFrame(-1, 0, nullptr, 55 frame->UpdateFrame(-1, 0, nullptr,
40 rtc::CheckedDivExact(sample_rate_hz, 100), 56 rtc::CheckedDivExact(sample_rate_hz, 100),
41 sample_rate_hz, AudioFrame::kNormalSpeech, 57 sample_rate_hz, AudioFrame::kNormalSpeech,
42 AudioFrame::kVadActive, number_of_channels); 58 AudioFrame::kVadActive, number_of_channels);
43 } 59 }
44 } 60 }
45 } // namespace 61 } // namespace
46 62
47 TEST(FrameCombiner, BasicApiCallsLimiter) { 63 TEST(FrameCombiner, BasicApiCallsLimiter) {
48 FrameCombiner combiner(true); 64 FrameCombiner combiner(true);
49 for (const int rate : {8000, 16000, 32000, 48000}) { 65 for (const int rate : {8000, 16000, 32000, 48000}) {
50 for (const int number_of_channels : {1, 2}) { 66 for (const int number_of_channels : {1, 2}) {
51 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2}; 67 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2};
52 SetUpFrames(rate, number_of_channels); 68 SetUpFrames(rate, number_of_channels);
53 69
54 for (const int number_of_frames : {0, 1, 2}) { 70 for (const int number_of_frames : {0, 1, 2}) {
55 SCOPED_TRACE( 71 SCOPED_TRACE(
56 ProduceDebugText(rate, number_of_channels, number_of_frames)); 72 ProduceDebugText(rate, number_of_channels, number_of_frames));
57 const std::vector<AudioFrame*> frames_to_combine( 73 const std::vector<AudioFrame*> frames_to_combine(
58 all_frames.begin(), all_frames.begin() + number_of_frames); 74 all_frames.begin(), all_frames.begin() + number_of_frames);
59 combiner.Combine(frames_to_combine, number_of_channels, rate, 75 combiner.Combine(frames_to_combine, number_of_channels, rate,
60 &audio_frame_for_mixing); 76 frames_to_combine.size(), &audio_frame_for_mixing);
61 } 77 }
62 } 78 }
63 } 79 }
64 } 80 }
65 81
66 // No APM limiter means no AudioProcessing::NativeRate restriction 82 // No APM limiter means no AudioProcessing::NativeRate restriction
67 // on rate. The rate has to be divisible by 100 since we use 83 // on rate. The rate has to be divisible by 100 since we use
68 // 10 ms frames, though. 84 // 10 ms frames, though.
69 TEST(FrameCombiner, BasicApiCallsNoLimiter) { 85 TEST(FrameCombiner, BasicApiCallsNoLimiter) {
70 FrameCombiner combiner(false); 86 FrameCombiner combiner(false);
71 for (const int rate : {8000, 10000, 11000, 32000, 44100}) { 87 for (const int rate : {8000, 10000, 11000, 32000, 44100}) {
72 for (const int number_of_channels : {1, 2}) { 88 for (const int number_of_channels : {1, 2}) {
73 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2}; 89 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2};
74 SetUpFrames(rate, number_of_channels); 90 SetUpFrames(rate, number_of_channels);
75 91
76 for (const int number_of_frames : {0, 1, 2}) { 92 for (const int number_of_frames : {0, 1, 2}) {
77 SCOPED_TRACE( 93 SCOPED_TRACE(
78 ProduceDebugText(rate, number_of_channels, number_of_frames)); 94 ProduceDebugText(rate, number_of_channels, number_of_frames));
79 const std::vector<AudioFrame*> frames_to_combine( 95 const std::vector<AudioFrame*> frames_to_combine(
80 all_frames.begin(), all_frames.begin() + number_of_frames); 96 all_frames.begin(), all_frames.begin() + number_of_frames);
81 combiner.Combine(frames_to_combine, number_of_channels, rate, 97 combiner.Combine(frames_to_combine, number_of_channels, rate,
82 &audio_frame_for_mixing); 98 frames_to_combine.size(), &audio_frame_for_mixing);
83 } 99 }
84 } 100 }
85 } 101 }
86 } 102 }
87 103
88 TEST(FrameCombiner, CombiningZeroFramesShouldProduceSilence) { 104 TEST(FrameCombiner, CombiningZeroFramesShouldProduceSilence) {
89 FrameCombiner combiner(false); 105 FrameCombiner combiner(false);
90 for (const int rate : {8000, 10000, 11000, 32000, 44100}) { 106 for (const int rate : {8000, 10000, 11000, 32000, 44100}) {
91 for (const int number_of_channels : {1, 2}) { 107 for (const int number_of_channels : {1, 2}) {
92 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 0)); 108 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 0));
93 109
94 const std::vector<AudioFrame*> frames_to_combine; 110 const std::vector<AudioFrame*> frames_to_combine;
95 combiner.Combine(frames_to_combine, number_of_channels, rate, 111 combiner.Combine(frames_to_combine, number_of_channels, rate,
96 &audio_frame_for_mixing); 112 frames_to_combine.size(), &audio_frame_for_mixing);
97 113
98 const std::vector<int16_t> mixed_data( 114 const std::vector<int16_t> mixed_data(
99 audio_frame_for_mixing.data_, 115 audio_frame_for_mixing.data_,
100 audio_frame_for_mixing.data_ + number_of_channels * rate / 100); 116 audio_frame_for_mixing.data_ + number_of_channels * rate / 100);
101 117
102 const std::vector<int16_t> expected(number_of_channels * rate / 100, 0); 118 const std::vector<int16_t> expected(number_of_channels * rate / 100, 0);
103 EXPECT_EQ(mixed_data, expected); 119 EXPECT_EQ(mixed_data, expected);
104 } 120 }
105 } 121 }
106 } 122 }
107 123
108 TEST(FrameCombiner, CombiningOneFrameShouldNotChangeFrame) { 124 TEST(FrameCombiner, CombiningOneFrameShouldNotChangeFrame) {
109 FrameCombiner combiner(false); 125 FrameCombiner combiner(false);
110 for (const int rate : {8000, 10000, 11000, 32000, 44100}) { 126 for (const int rate : {8000, 10000, 11000, 32000, 44100}) {
111 for (const int number_of_channels : {1, 2}) { 127 for (const int number_of_channels : {1, 2}) {
112 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 1)); 128 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 1));
113 129
114 SetUpFrames(rate, number_of_channels); 130 SetUpFrames(rate, number_of_channels);
115 std::iota(frame1.data_, frame1.data_ + number_of_channels * rate / 100, 131 std::iota(frame1.data_, frame1.data_ + number_of_channels * rate / 100,
116 0); 132 0);
117 const std::vector<AudioFrame*> frames_to_combine = {&frame1}; 133 const std::vector<AudioFrame*> frames_to_combine = {&frame1};
118 combiner.Combine(frames_to_combine, number_of_channels, rate, 134 combiner.Combine(frames_to_combine, number_of_channels, rate,
119 &audio_frame_for_mixing); 135 frames_to_combine.size(), &audio_frame_for_mixing);
120 136
121 const std::vector<int16_t> mixed_data( 137 const std::vector<int16_t> mixed_data(
122 audio_frame_for_mixing.data_, 138 audio_frame_for_mixing.data_,
123 audio_frame_for_mixing.data_ + number_of_channels * rate / 100); 139 audio_frame_for_mixing.data_ + number_of_channels * rate / 100);
124 140
125 std::vector<int16_t> expected(number_of_channels * rate / 100); 141 std::vector<int16_t> expected(number_of_channels * rate / 100);
126 std::iota(expected.begin(), expected.end(), 0); 142 std::iota(expected.begin(), expected.end(), 0);
127 EXPECT_EQ(mixed_data, expected); 143 EXPECT_EQ(mixed_data, expected);
128 } 144 }
129 } 145 }
130 } 146 }
131 147
148 // Send a sine curve through the FrameCombiner, and check that the
149 // difference between input and output varies smoothly. This is to
150 // catch issues like chromium:695993.
151 TEST(FrameCombiner, GainCurveIsSmoothForAlternatingNumberOfStreams) {
152 // Test doesn't work with rates requiring a band split, because it
153 // introduces a small delay measured in single samples, and this
154 // test cannot handle it.
155 //
156 // TODO(aleloi): Add more rates when APM limiter doesn't use band
157 // split.
158 for (const bool use_limiter : {true, false}) {
159 for (const int rate : {8000, 16000}) {
160 for (const int number_of_channels : {1, 2}) {
161 for (const float wave_frequency :
162 {50, 100, 200, 400, 800, 1600, 3200}) {
ivoc 2017/03/28 16:11:06 I don't think it's really necessary to test every
163 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 1,
164 use_limiter, wave_frequency));
165
166 FrameCombiner combiner(use_limiter);
167
168 constexpr int16_t wave_amplitude = 30000;
169 SineWaveGenerator wave_generator(wave_frequency, wave_amplitude);
170
171 GainChangeCalculator change_calculator;
172 float cumulative_change = 0.f;
173
174 constexpr int16_t iterations = 100;
175
176 for (int i = 0; i < iterations; ++i) {
177 SetUpFrames(rate, number_of_channels);
178 wave_generator.GenerateNextFrame(&frame1);
179 AudioFrameOperations::Mute(&frame2);
180
181 std::vector<AudioFrame*> frames_to_combine = {&frame1};
182 if (i % 2 == 0) {
183 frames_to_combine.push_back(&frame2);
184 }
185 const size_t number_of_samples =
186 frame1.samples_per_channel_ * number_of_channels;
187
188 // Ensures limiter is on if 'use_limiter'.
189 const size_t number_of_streams = 2;
190 combiner.Combine(frames_to_combine, number_of_channels, rate,
191 number_of_streams, &audio_frame_for_mixing);
192 cumulative_change += change_calculator.CalculateGainChange(
193 rtc::ArrayView<const int16_t>(frame1.data_, number_of_samples),
194 rtc::ArrayView<const int16_t>(audio_frame_for_mixing.data_,
195 number_of_samples));
196 }
197 RTC_DCHECK_LT(cumulative_change, 10);
198 }
199 }
200 }
201 }
202 }
132 } // namespace webrtc 203 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698