• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2015 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 "audio/audio_state.h"
12 
13 #include <memory>
14 #include <vector>
15 
16 #include "call/test/mock_audio_send_stream.h"
17 #include "modules/audio_device/include/mock_audio_device.h"
18 #include "modules/audio_mixer/audio_mixer_impl.h"
19 #include "modules/audio_processing/include/mock_audio_processing.h"
20 #include "rtc_base/ref_counted_object.h"
21 #include "test/gtest.h"
22 
23 namespace webrtc {
24 namespace test {
25 namespace {
26 
27 using ::testing::_;
28 using ::testing::Matcher;
29 
30 constexpr int kSampleRate = 16000;
31 constexpr int kNumberOfChannels = 1;
32 
33 struct ConfigHelper {
ConfigHelperwebrtc::test::__anonbcae15140111::ConfigHelper34   explicit ConfigHelper(bool use_null_audio_processing)
35       : audio_mixer(AudioMixerImpl::Create()) {
36     audio_state_config.audio_mixer = audio_mixer;
37     audio_state_config.audio_processing =
38         use_null_audio_processing
39             ? nullptr
40             : new rtc::RefCountedObject<
41                   testing::NiceMock<MockAudioProcessing>>();
42     audio_state_config.audio_device_module =
43         new rtc::RefCountedObject<MockAudioDeviceModule>();
44   }
configwebrtc::test::__anonbcae15140111::ConfigHelper45   AudioState::Config& config() { return audio_state_config; }
mixerwebrtc::test::__anonbcae15140111::ConfigHelper46   rtc::scoped_refptr<AudioMixer> mixer() { return audio_mixer; }
47 
48  private:
49   AudioState::Config audio_state_config;
50   rtc::scoped_refptr<AudioMixer> audio_mixer;
51 };
52 
53 class FakeAudioSource : public AudioMixer::Source {
54  public:
55   // TODO(aleloi): Valid overrides commented out, because the gmock
56   // methods don't use any override declarations, and we want to avoid
57   // warnings from -Winconsistent-missing-override. See
58   // http://crbug.com/428099.
Ssrc() const59   int Ssrc() const /*override*/ { return 0; }
60 
PreferredSampleRate() const61   int PreferredSampleRate() const /*override*/ { return kSampleRate; }
62 
63   MOCK_METHOD(AudioFrameInfo,
64               GetAudioFrameWithInfo,
65               (int sample_rate_hz, AudioFrame*),
66               (override));
67 };
68 
Create10msTestData(int sample_rate_hz,size_t num_channels)69 std::vector<int16_t> Create10msTestData(int sample_rate_hz,
70                                         size_t num_channels) {
71   const int samples_per_channel = sample_rate_hz / 100;
72   std::vector<int16_t> audio_data(samples_per_channel * num_channels, 0);
73   // Fill the first channel with a 1kHz sine wave.
74   const float inc = (2 * 3.14159265f * 1000) / sample_rate_hz;
75   float w = 0.f;
76   for (int i = 0; i < samples_per_channel; ++i) {
77     audio_data[i * num_channels] = static_cast<int16_t>(32767.f * std::sin(w));
78     w += inc;
79   }
80   return audio_data;
81 }
82 
ComputeChannelLevels(AudioFrame * audio_frame)83 std::vector<uint32_t> ComputeChannelLevels(AudioFrame* audio_frame) {
84   const size_t num_channels = audio_frame->num_channels_;
85   const size_t samples_per_channel = audio_frame->samples_per_channel_;
86   std::vector<uint32_t> levels(num_channels, 0);
87   for (size_t i = 0; i < samples_per_channel; ++i) {
88     for (size_t j = 0; j < num_channels; ++j) {
89       levels[j] += std::abs(audio_frame->data()[i * num_channels + j]);
90     }
91   }
92   return levels;
93 }
94 }  // namespace
95 
TEST(AudioStateTest,Create)96 TEST(AudioStateTest, Create) {
97   for (bool use_null_audio_processing : {false, true}) {
98     ConfigHelper helper(use_null_audio_processing);
99     auto audio_state = AudioState::Create(helper.config());
100     EXPECT_TRUE(audio_state.get());
101   }
102 }
103 
TEST(AudioStateTest,ConstructDestruct)104 TEST(AudioStateTest, ConstructDestruct) {
105   for (bool use_null_audio_processing : {false, true}) {
106     ConfigHelper helper(use_null_audio_processing);
107     rtc::scoped_refptr<internal::AudioState> audio_state(
108         new rtc::RefCountedObject<internal::AudioState>(helper.config()));
109   }
110 }
111 
TEST(AudioStateTest,RecordedAudioArrivesAtSingleStream)112 TEST(AudioStateTest, RecordedAudioArrivesAtSingleStream) {
113   for (bool use_null_audio_processing : {false, true}) {
114     ConfigHelper helper(use_null_audio_processing);
115     rtc::scoped_refptr<internal::AudioState> audio_state(
116         new rtc::RefCountedObject<internal::AudioState>(helper.config()));
117 
118     MockAudioSendStream stream;
119     audio_state->AddSendingStream(&stream, 8000, 2);
120 
121     EXPECT_CALL(
122         stream,
123         SendAudioDataForMock(::testing::AllOf(
124             ::testing::Field(&AudioFrame::sample_rate_hz_, ::testing::Eq(8000)),
125             ::testing::Field(&AudioFrame::num_channels_, ::testing::Eq(2u)))))
126         .WillOnce(
127             // Verify that channels are not swapped by default.
128             ::testing::Invoke([](AudioFrame* audio_frame) {
129               auto levels = ComputeChannelLevels(audio_frame);
130               EXPECT_LT(0u, levels[0]);
131               EXPECT_EQ(0u, levels[1]);
132             }));
133     MockAudioProcessing* ap = use_null_audio_processing
134                                   ? nullptr
135                                   : static_cast<MockAudioProcessing*>(
136                                         audio_state->audio_processing());
137     if (ap) {
138       EXPECT_CALL(*ap, set_stream_delay_ms(0));
139       EXPECT_CALL(*ap, set_stream_key_pressed(false));
140       EXPECT_CALL(*ap, ProcessStream(_, _, _, Matcher<int16_t*>(_)));
141     }
142 
143     constexpr int kSampleRate = 16000;
144     constexpr size_t kNumChannels = 2;
145     auto audio_data = Create10msTestData(kSampleRate, kNumChannels);
146     uint32_t new_mic_level = 667;
147     audio_state->audio_transport()->RecordedDataIsAvailable(
148         &audio_data[0], kSampleRate / 100, kNumChannels * 2, kNumChannels,
149         kSampleRate, 0, 0, 0, false, new_mic_level);
150     EXPECT_EQ(667u, new_mic_level);
151 
152     audio_state->RemoveSendingStream(&stream);
153   }
154 }
155 
TEST(AudioStateTest,RecordedAudioArrivesAtMultipleStreams)156 TEST(AudioStateTest, RecordedAudioArrivesAtMultipleStreams) {
157   for (bool use_null_audio_processing : {false, true}) {
158     ConfigHelper helper(use_null_audio_processing);
159     rtc::scoped_refptr<internal::AudioState> audio_state(
160         new rtc::RefCountedObject<internal::AudioState>(helper.config()));
161 
162     MockAudioSendStream stream_1;
163     MockAudioSendStream stream_2;
164     audio_state->AddSendingStream(&stream_1, 8001, 2);
165     audio_state->AddSendingStream(&stream_2, 32000, 1);
166 
167     EXPECT_CALL(
168         stream_1,
169         SendAudioDataForMock(::testing::AllOf(
170             ::testing::Field(&AudioFrame::sample_rate_hz_,
171                              ::testing::Eq(16000)),
172             ::testing::Field(&AudioFrame::num_channels_, ::testing::Eq(1u)))))
173         .WillOnce(
174             // Verify that there is output signal.
175             ::testing::Invoke([](AudioFrame* audio_frame) {
176               auto levels = ComputeChannelLevels(audio_frame);
177               EXPECT_LT(0u, levels[0]);
178             }));
179     EXPECT_CALL(
180         stream_2,
181         SendAudioDataForMock(::testing::AllOf(
182             ::testing::Field(&AudioFrame::sample_rate_hz_,
183                              ::testing::Eq(16000)),
184             ::testing::Field(&AudioFrame::num_channels_, ::testing::Eq(1u)))))
185         .WillOnce(
186             // Verify that there is output signal.
187             ::testing::Invoke([](AudioFrame* audio_frame) {
188               auto levels = ComputeChannelLevels(audio_frame);
189               EXPECT_LT(0u, levels[0]);
190             }));
191     MockAudioProcessing* ap =
192         static_cast<MockAudioProcessing*>(audio_state->audio_processing());
193     if (ap) {
194       EXPECT_CALL(*ap, set_stream_delay_ms(5));
195       EXPECT_CALL(*ap, set_stream_key_pressed(true));
196       EXPECT_CALL(*ap, ProcessStream(_, _, _, Matcher<int16_t*>(_)));
197     }
198 
199     constexpr int kSampleRate = 16000;
200     constexpr size_t kNumChannels = 1;
201     auto audio_data = Create10msTestData(kSampleRate, kNumChannels);
202     uint32_t new_mic_level = 667;
203     audio_state->audio_transport()->RecordedDataIsAvailable(
204         &audio_data[0], kSampleRate / 100, kNumChannels * 2, kNumChannels,
205         kSampleRate, 5, 0, 0, true, new_mic_level);
206     EXPECT_EQ(667u, new_mic_level);
207 
208     audio_state->RemoveSendingStream(&stream_1);
209     audio_state->RemoveSendingStream(&stream_2);
210   }
211 }
212 
TEST(AudioStateTest,EnableChannelSwap)213 TEST(AudioStateTest, EnableChannelSwap) {
214   constexpr int kSampleRate = 16000;
215   constexpr size_t kNumChannels = 2;
216 
217   for (bool use_null_audio_processing : {false, true}) {
218     ConfigHelper helper(use_null_audio_processing);
219     rtc::scoped_refptr<internal::AudioState> audio_state(
220         new rtc::RefCountedObject<internal::AudioState>(helper.config()));
221 
222     audio_state->SetStereoChannelSwapping(true);
223 
224     MockAudioSendStream stream;
225     audio_state->AddSendingStream(&stream, kSampleRate, kNumChannels);
226 
227     EXPECT_CALL(stream, SendAudioDataForMock(_))
228         .WillOnce(
229             // Verify that channels are swapped.
230             ::testing::Invoke([](AudioFrame* audio_frame) {
231               auto levels = ComputeChannelLevels(audio_frame);
232               EXPECT_EQ(0u, levels[0]);
233               EXPECT_LT(0u, levels[1]);
234             }));
235 
236     auto audio_data = Create10msTestData(kSampleRate, kNumChannels);
237     uint32_t new_mic_level = 667;
238     audio_state->audio_transport()->RecordedDataIsAvailable(
239         &audio_data[0], kSampleRate / 100, kNumChannels * 2, kNumChannels,
240         kSampleRate, 0, 0, 0, false, new_mic_level);
241     EXPECT_EQ(667u, new_mic_level);
242 
243     audio_state->RemoveSendingStream(&stream);
244   }
245 }
246 
TEST(AudioStateTest,QueryingTransportForAudioShouldResultInGetAudioCallOnMixerSource)247 TEST(AudioStateTest,
248      QueryingTransportForAudioShouldResultInGetAudioCallOnMixerSource) {
249   for (bool use_null_audio_processing : {false, true}) {
250     ConfigHelper helper(use_null_audio_processing);
251     auto audio_state = AudioState::Create(helper.config());
252 
253     FakeAudioSource fake_source;
254     helper.mixer()->AddSource(&fake_source);
255 
256     EXPECT_CALL(fake_source, GetAudioFrameWithInfo(_, _))
257         .WillOnce(
258             ::testing::Invoke([](int sample_rate_hz, AudioFrame* audio_frame) {
259               audio_frame->sample_rate_hz_ = sample_rate_hz;
260               audio_frame->samples_per_channel_ = sample_rate_hz / 100;
261               audio_frame->num_channels_ = kNumberOfChannels;
262               return AudioMixer::Source::AudioFrameInfo::kNormal;
263             }));
264 
265     int16_t audio_buffer[kSampleRate / 100 * kNumberOfChannels];
266     size_t n_samples_out;
267     int64_t elapsed_time_ms;
268     int64_t ntp_time_ms;
269     audio_state->audio_transport()->NeedMorePlayData(
270         kSampleRate / 100, kNumberOfChannels * 2, kNumberOfChannels,
271         kSampleRate, audio_buffer, n_samples_out, &elapsed_time_ms,
272         &ntp_time_ms);
273   }
274 }
275 }  // namespace test
276 }  // namespace webrtc
277