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

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: Minor changes in response to hlundin@'s comments. 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/gain_change_calculator.h"
20 #include "webrtc/modules/audio_mixer/sine_wave_generator.h"
18 #include "webrtc/test/gtest.h" 21 #include "webrtc/test/gtest.h"
19 22
20 namespace webrtc { 23 namespace webrtc {
21 24
22 namespace { 25 namespace {
23 std::string ProduceDebugText(int sample_rate_hz, 26 std::string ProduceDebugText(int sample_rate_hz,
24 int number_of_channels, 27 int number_of_channels,
25 int number_of_sources) { 28 int number_of_sources) {
26 std::ostringstream ss; 29 std::ostringstream ss;
27 ss << "Sample rate: " << sample_rate_hz << " "; 30 ss << "Sample rate: " << sample_rate_hz << " ,";
28 ss << "Number of channels: " << number_of_channels << " "; 31 ss << "number of channels: " << number_of_channels << " ,";
29 ss << "Number of sources: " << number_of_sources; 32 ss << "number of sources: " << number_of_sources;
30 return ss.str(); 33 return ss.str();
31 } 34 }
32 35
36 std::string ProduceDebugText(int sample_rate_hz,
37 int number_of_channels,
38 int number_of_sources,
39 bool limiter_active,
40 float wave_frequency) {
41 std::ostringstream ss;
42 ss << "Sample rate: " << sample_rate_hz << " ,";
43 ss << "number of channels: " << number_of_channels << " ,";
44 ss << "number of sources: " << number_of_sources << " ,";
45 ss << "limiter active: " << (limiter_active ? "true" : "false") << " ,";
46 ss << "wave frequency: " << wave_frequency << " ,";
47 return ss.str();
48 }
49
33 AudioFrame frame1; 50 AudioFrame frame1;
34 AudioFrame frame2; 51 AudioFrame frame2;
35 AudioFrame audio_frame_for_mixing; 52 AudioFrame audio_frame_for_mixing;
36 53
37 void SetUpFrames(int sample_rate_hz, int number_of_channels) { 54 void SetUpFrames(int sample_rate_hz, int number_of_channels) {
38 for (auto* frame : {&frame1, &frame2}) { 55 for (auto* frame : {&frame1, &frame2}) {
39 frame->UpdateFrame(-1, 0, nullptr, 56 frame->UpdateFrame(-1, 0, nullptr,
40 rtc::CheckedDivExact(sample_rate_hz, 100), 57 rtc::CheckedDivExact(sample_rate_hz, 100),
41 sample_rate_hz, AudioFrame::kNormalSpeech, 58 sample_rate_hz, AudioFrame::kNormalSpeech,
42 AudioFrame::kVadActive, number_of_channels); 59 AudioFrame::kVadActive, number_of_channels);
43 } 60 }
44 } 61 }
45 } // namespace 62 } // namespace
46 63
47 TEST(FrameCombiner, BasicApiCallsLimiter) { 64 TEST(FrameCombiner, BasicApiCallsLimiter) {
48 FrameCombiner combiner(true); 65 FrameCombiner combiner(true);
49 for (const int rate : {8000, 16000, 32000, 48000}) { 66 for (const int rate : {8000, 16000, 32000, 48000}) {
50 for (const int number_of_channels : {1, 2}) { 67 for (const int number_of_channels : {1, 2}) {
51 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2}; 68 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2};
52 SetUpFrames(rate, number_of_channels); 69 SetUpFrames(rate, number_of_channels);
53 70
54 for (const int number_of_frames : {0, 1, 2}) { 71 for (const int number_of_frames : {0, 1, 2}) {
55 SCOPED_TRACE( 72 SCOPED_TRACE(
56 ProduceDebugText(rate, number_of_channels, number_of_frames)); 73 ProduceDebugText(rate, number_of_channels, number_of_frames));
57 const std::vector<AudioFrame*> frames_to_combine( 74 const std::vector<AudioFrame*> frames_to_combine(
58 all_frames.begin(), all_frames.begin() + number_of_frames); 75 all_frames.begin(), all_frames.begin() + number_of_frames);
59 combiner.Combine(frames_to_combine, number_of_channels, rate, 76 combiner.Combine(frames_to_combine, number_of_channels, rate,
60 &audio_frame_for_mixing); 77 frames_to_combine.size(), &audio_frame_for_mixing);
61 } 78 }
62 } 79 }
63 } 80 }
64 } 81 }
65 82
66 // No APM limiter means no AudioProcessing::NativeRate restriction 83 // No APM limiter means no AudioProcessing::NativeRate restriction
67 // on rate. The rate has to be divisible by 100 since we use 84 // on rate. The rate has to be divisible by 100 since we use
68 // 10 ms frames, though. 85 // 10 ms frames, though.
69 TEST(FrameCombiner, BasicApiCallsNoLimiter) { 86 TEST(FrameCombiner, BasicApiCallsNoLimiter) {
70 FrameCombiner combiner(false); 87 FrameCombiner combiner(false);
71 for (const int rate : {8000, 10000, 11000, 32000, 44100}) { 88 for (const int rate : {8000, 10000, 11000, 32000, 44100}) {
72 for (const int number_of_channels : {1, 2}) { 89 for (const int number_of_channels : {1, 2}) {
73 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2}; 90 const std::vector<AudioFrame*> all_frames = {&frame1, &frame2};
74 SetUpFrames(rate, number_of_channels); 91 SetUpFrames(rate, number_of_channels);
75 92
76 for (const int number_of_frames : {0, 1, 2}) { 93 for (const int number_of_frames : {0, 1, 2}) {
77 SCOPED_TRACE( 94 SCOPED_TRACE(
78 ProduceDebugText(rate, number_of_channels, number_of_frames)); 95 ProduceDebugText(rate, number_of_channels, number_of_frames));
79 const std::vector<AudioFrame*> frames_to_combine( 96 const std::vector<AudioFrame*> frames_to_combine(
80 all_frames.begin(), all_frames.begin() + number_of_frames); 97 all_frames.begin(), all_frames.begin() + number_of_frames);
81 combiner.Combine(frames_to_combine, number_of_channels, rate, 98 combiner.Combine(frames_to_combine, number_of_channels, rate,
82 &audio_frame_for_mixing); 99 frames_to_combine.size(), &audio_frame_for_mixing);
83 } 100 }
84 } 101 }
85 } 102 }
86 } 103 }
87 104
88 TEST(FrameCombiner, CombiningZeroFramesShouldProduceSilence) { 105 TEST(FrameCombiner, CombiningZeroFramesShouldProduceSilence) {
89 FrameCombiner combiner(false); 106 FrameCombiner combiner(false);
90 for (const int rate : {8000, 10000, 11000, 32000, 44100}) { 107 for (const int rate : {8000, 10000, 11000, 32000, 44100}) {
91 for (const int number_of_channels : {1, 2}) { 108 for (const int number_of_channels : {1, 2}) {
92 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 0)); 109 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 0));
93 110
94 const std::vector<AudioFrame*> frames_to_combine; 111 const std::vector<AudioFrame*> frames_to_combine;
95 combiner.Combine(frames_to_combine, number_of_channels, rate, 112 combiner.Combine(frames_to_combine, number_of_channels, rate,
96 &audio_frame_for_mixing); 113 frames_to_combine.size(), &audio_frame_for_mixing);
97 114
98 const std::vector<int16_t> mixed_data( 115 const std::vector<int16_t> mixed_data(
99 audio_frame_for_mixing.data_, 116 audio_frame_for_mixing.data_,
100 audio_frame_for_mixing.data_ + number_of_channels * rate / 100); 117 audio_frame_for_mixing.data_ + number_of_channels * rate / 100);
101 118
102 const std::vector<int16_t> expected(number_of_channels * rate / 100, 0); 119 const std::vector<int16_t> expected(number_of_channels * rate / 100, 0);
103 EXPECT_EQ(mixed_data, expected); 120 EXPECT_EQ(mixed_data, expected);
104 } 121 }
105 } 122 }
106 } 123 }
107 124
108 TEST(FrameCombiner, CombiningOneFrameShouldNotChangeFrame) { 125 TEST(FrameCombiner, CombiningOneFrameShouldNotChangeFrame) {
109 FrameCombiner combiner(false); 126 FrameCombiner combiner(false);
110 for (const int rate : {8000, 10000, 11000, 32000, 44100}) { 127 for (const int rate : {8000, 10000, 11000, 32000, 44100}) {
111 for (const int number_of_channels : {1, 2}) { 128 for (const int number_of_channels : {1, 2}) {
112 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 1)); 129 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 1));
113 130
114 SetUpFrames(rate, number_of_channels); 131 SetUpFrames(rate, number_of_channels);
115 std::iota(frame1.data_, frame1.data_ + number_of_channels * rate / 100, 132 std::iota(frame1.data_, frame1.data_ + number_of_channels * rate / 100,
116 0); 133 0);
117 const std::vector<AudioFrame*> frames_to_combine = {&frame1}; 134 const std::vector<AudioFrame*> frames_to_combine = {&frame1};
118 combiner.Combine(frames_to_combine, number_of_channels, rate, 135 combiner.Combine(frames_to_combine, number_of_channels, rate,
119 &audio_frame_for_mixing); 136 frames_to_combine.size(), &audio_frame_for_mixing);
120 137
121 const std::vector<int16_t> mixed_data( 138 const std::vector<int16_t> mixed_data(
122 audio_frame_for_mixing.data_, 139 audio_frame_for_mixing.data_,
123 audio_frame_for_mixing.data_ + number_of_channels * rate / 100); 140 audio_frame_for_mixing.data_ + number_of_channels * rate / 100);
124 141
125 std::vector<int16_t> expected(number_of_channels * rate / 100); 142 std::vector<int16_t> expected(number_of_channels * rate / 100);
126 std::iota(expected.begin(), expected.end(), 0); 143 std::iota(expected.begin(), expected.end(), 0);
127 EXPECT_EQ(mixed_data, expected); 144 EXPECT_EQ(mixed_data, expected);
128 } 145 }
129 } 146 }
130 } 147 }
131 148
149 // Send a sine wave through the FrameCombiner, and check that the
150 // difference between input and output varies smoothly. This is to
151 // catch issues like chromium:695993.
152 TEST(FrameCombiner, GainCurveIsSmoothForAlternatingNumberOfStreams) {
153 // Test doesn't work with rates requiring a band split, because it
154 // introduces a small delay measured in single samples, and this
155 // test cannot handle it.
156 //
157 // TODO(aleloi): Add more rates when APM limiter doesn't use band
158 // split.
159 for (const bool use_limiter : {true, false}) {
160 for (const int rate : {8000, 16000}) {
161 constexpr int number_of_channels = 2;
162 for (const float wave_frequency : {50, 400, 3200}) {
163 SCOPED_TRACE(ProduceDebugText(rate, number_of_channels, 1, use_limiter,
164 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 size_t iterations = 100;
175
176 for (size_t 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 constexpr 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 }
132 } // namespace webrtc 202 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_mixer/frame_combiner.cc ('k') | webrtc/modules/audio_mixer/gain_change_calculator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698