1 /*
2 * Copyright (c) 2018 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 #include "modules/audio_device/include/test_audio_device.h"
11
12 #include <algorithm>
13 #include <cstdint>
14 #include <cstdlib>
15 #include <memory>
16 #include <string>
17 #include <type_traits>
18 #include <utility>
19 #include <vector>
20
21 #include "absl/strings/string_view.h"
22 #include "api/array_view.h"
23 #include "api/make_ref_counted.h"
24 #include "common_audio/wav_file.h"
25 #include "modules/audio_device/include/audio_device_default.h"
26 #include "rtc_base/buffer.h"
27 #include "rtc_base/checks.h"
28 #include "rtc_base/event.h"
29 #include "rtc_base/logging.h"
30 #include "rtc_base/numerics/safe_conversions.h"
31 #include "rtc_base/platform_thread.h"
32 #include "rtc_base/random.h"
33 #include "rtc_base/synchronization/mutex.h"
34 #include "rtc_base/task_queue.h"
35 #include "rtc_base/task_utils/repeating_task.h"
36 #include "rtc_base/thread_annotations.h"
37 #include "rtc_base/time_utils.h"
38
39 namespace webrtc {
40
41 namespace {
42
43 constexpr int kFrameLengthUs = 10000;
44 constexpr int kFramesPerSecond = rtc::kNumMicrosecsPerSec / kFrameLengthUs;
45
46 // TestAudioDeviceModule implements an AudioDevice module that can act both as a
47 // capturer and a renderer. It will use 10ms audio frames.
48 class TestAudioDeviceModuleImpl
49 : public webrtc_impl::AudioDeviceModuleDefault<TestAudioDeviceModule> {
50 public:
51 // Creates a new TestAudioDeviceModule. When capturing or playing, 10 ms audio
52 // frames will be processed every 10ms / `speed`.
53 // `capturer` is an object that produces audio data. Can be nullptr if this
54 // device is never used for recording.
55 // `renderer` is an object that receives audio data that would have been
56 // played out. Can be nullptr if this device is never used for playing.
57 // Use one of the Create... functions to get these instances.
TestAudioDeviceModuleImpl(TaskQueueFactory * task_queue_factory,std::unique_ptr<Capturer> capturer,std::unique_ptr<Renderer> renderer,float speed=1)58 TestAudioDeviceModuleImpl(TaskQueueFactory* task_queue_factory,
59 std::unique_ptr<Capturer> capturer,
60 std::unique_ptr<Renderer> renderer,
61 float speed = 1)
62 : task_queue_factory_(task_queue_factory),
63 capturer_(std::move(capturer)),
64 renderer_(std::move(renderer)),
65 process_interval_us_(kFrameLengthUs / speed),
66 audio_callback_(nullptr),
67 rendering_(false),
68 capturing_(false) {
69 auto good_sample_rate = [](int sr) {
70 return sr == 8000 || sr == 16000 || sr == 32000 || sr == 44100 ||
71 sr == 48000;
72 };
73
74 if (renderer_) {
75 const int sample_rate = renderer_->SamplingFrequency();
76 playout_buffer_.resize(
77 SamplesPerFrame(sample_rate) * renderer_->NumChannels(), 0);
78 RTC_CHECK(good_sample_rate(sample_rate));
79 }
80 if (capturer_) {
81 RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency()));
82 }
83 }
84
~TestAudioDeviceModuleImpl()85 ~TestAudioDeviceModuleImpl() override {
86 StopPlayout();
87 StopRecording();
88 }
89
Init()90 int32_t Init() override {
91 task_queue_ =
92 std::make_unique<rtc::TaskQueue>(task_queue_factory_->CreateTaskQueue(
93 "TestAudioDeviceModuleImpl", TaskQueueFactory::Priority::NORMAL));
94
95 RepeatingTaskHandle::Start(task_queue_->Get(), [this]() {
96 ProcessAudio();
97 return TimeDelta::Micros(process_interval_us_);
98 });
99 return 0;
100 }
101
RegisterAudioCallback(AudioTransport * callback)102 int32_t RegisterAudioCallback(AudioTransport* callback) override {
103 MutexLock lock(&lock_);
104 RTC_DCHECK(callback || audio_callback_);
105 audio_callback_ = callback;
106 return 0;
107 }
108
StartPlayout()109 int32_t StartPlayout() override {
110 MutexLock lock(&lock_);
111 RTC_CHECK(renderer_);
112 rendering_ = true;
113 return 0;
114 }
115
StopPlayout()116 int32_t StopPlayout() override {
117 MutexLock lock(&lock_);
118 rendering_ = false;
119 return 0;
120 }
121
StartRecording()122 int32_t StartRecording() override {
123 MutexLock lock(&lock_);
124 RTC_CHECK(capturer_);
125 capturing_ = true;
126 return 0;
127 }
128
StopRecording()129 int32_t StopRecording() override {
130 MutexLock lock(&lock_);
131 capturing_ = false;
132 return 0;
133 }
134
Playing() const135 bool Playing() const override {
136 MutexLock lock(&lock_);
137 return rendering_;
138 }
139
Recording() const140 bool Recording() const override {
141 MutexLock lock(&lock_);
142 return capturing_;
143 }
144
145 // Blocks forever until the Recorder stops producing data.
WaitForRecordingEnd()146 void WaitForRecordingEnd() override {
147 done_capturing_.Wait(rtc::Event::kForever);
148 }
149
150 private:
ProcessAudio()151 void ProcessAudio() {
152 MutexLock lock(&lock_);
153 if (capturing_) {
154 // Capture 10ms of audio. 2 bytes per sample.
155 const bool keep_capturing = capturer_->Capture(&recording_buffer_);
156 uint32_t new_mic_level = 0;
157 if (recording_buffer_.size() > 0) {
158 audio_callback_->RecordedDataIsAvailable(
159 recording_buffer_.data(),
160 recording_buffer_.size() / capturer_->NumChannels(),
161 2 * capturer_->NumChannels(), capturer_->NumChannels(),
162 capturer_->SamplingFrequency(), 0, 0, 0, false, new_mic_level);
163 }
164 if (!keep_capturing) {
165 capturing_ = false;
166 done_capturing_.Set();
167 }
168 }
169 if (rendering_) {
170 size_t samples_out = 0;
171 int64_t elapsed_time_ms = -1;
172 int64_t ntp_time_ms = -1;
173 const int sampling_frequency = renderer_->SamplingFrequency();
174 audio_callback_->NeedMorePlayData(
175 SamplesPerFrame(sampling_frequency), 2 * renderer_->NumChannels(),
176 renderer_->NumChannels(), sampling_frequency, playout_buffer_.data(),
177 samples_out, &elapsed_time_ms, &ntp_time_ms);
178 const bool keep_rendering = renderer_->Render(
179 rtc::ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
180 if (!keep_rendering) {
181 rendering_ = false;
182 done_rendering_.Set();
183 }
184 }
185 }
186 TaskQueueFactory* const task_queue_factory_;
187 const std::unique_ptr<Capturer> capturer_ RTC_GUARDED_BY(lock_);
188 const std::unique_ptr<Renderer> renderer_ RTC_GUARDED_BY(lock_);
189 const int64_t process_interval_us_;
190
191 mutable Mutex lock_;
192 AudioTransport* audio_callback_ RTC_GUARDED_BY(lock_);
193 bool rendering_ RTC_GUARDED_BY(lock_);
194 bool capturing_ RTC_GUARDED_BY(lock_);
195 rtc::Event done_rendering_;
196 rtc::Event done_capturing_;
197
198 std::vector<int16_t> playout_buffer_ RTC_GUARDED_BY(lock_);
199 rtc::BufferT<int16_t> recording_buffer_ RTC_GUARDED_BY(lock_);
200 std::unique_ptr<rtc::TaskQueue> task_queue_;
201 };
202
203 // A fake capturer that generates pulses with random samples between
204 // -max_amplitude and +max_amplitude.
205 class PulsedNoiseCapturerImpl final
206 : public TestAudioDeviceModule::PulsedNoiseCapturer {
207 public:
208 // Assuming 10ms audio packets.
PulsedNoiseCapturerImpl(int16_t max_amplitude,int sampling_frequency_in_hz,int num_channels)209 PulsedNoiseCapturerImpl(int16_t max_amplitude,
210 int sampling_frequency_in_hz,
211 int num_channels)
212 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
213 fill_with_zero_(false),
214 random_generator_(1),
215 max_amplitude_(max_amplitude),
216 num_channels_(num_channels) {
217 RTC_DCHECK_GT(max_amplitude, 0);
218 }
219
SamplingFrequency() const220 int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
221
NumChannels() const222 int NumChannels() const override { return num_channels_; }
223
Capture(rtc::BufferT<int16_t> * buffer)224 bool Capture(rtc::BufferT<int16_t>* buffer) override {
225 fill_with_zero_ = !fill_with_zero_;
226 int16_t max_amplitude;
227 {
228 MutexLock lock(&lock_);
229 max_amplitude = max_amplitude_;
230 }
231 buffer->SetData(
232 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) *
233 num_channels_,
234 [&](rtc::ArrayView<int16_t> data) {
235 if (fill_with_zero_) {
236 std::fill(data.begin(), data.end(), 0);
237 } else {
238 std::generate(data.begin(), data.end(), [&]() {
239 return random_generator_.Rand(-max_amplitude, max_amplitude);
240 });
241 }
242 return data.size();
243 });
244 return true;
245 }
246
SetMaxAmplitude(int16_t amplitude)247 void SetMaxAmplitude(int16_t amplitude) override {
248 MutexLock lock(&lock_);
249 max_amplitude_ = amplitude;
250 }
251
252 private:
253 int sampling_frequency_in_hz_;
254 bool fill_with_zero_;
255 Random random_generator_;
256 Mutex lock_;
257 int16_t max_amplitude_ RTC_GUARDED_BY(lock_);
258 const int num_channels_;
259 };
260
261 class WavFileReader final : public TestAudioDeviceModule::Capturer {
262 public:
WavFileReader(absl::string_view filename,int sampling_frequency_in_hz,int num_channels,bool repeat)263 WavFileReader(absl::string_view filename,
264 int sampling_frequency_in_hz,
265 int num_channels,
266 bool repeat)
267 : WavFileReader(std::make_unique<WavReader>(filename),
268 sampling_frequency_in_hz,
269 num_channels,
270 repeat) {}
271
SamplingFrequency() const272 int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
273
NumChannels() const274 int NumChannels() const override { return num_channels_; }
275
Capture(rtc::BufferT<int16_t> * buffer)276 bool Capture(rtc::BufferT<int16_t>* buffer) override {
277 buffer->SetData(
278 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) *
279 num_channels_,
280 [&](rtc::ArrayView<int16_t> data) {
281 size_t read = wav_reader_->ReadSamples(data.size(), data.data());
282 if (read < data.size() && repeat_) {
283 do {
284 wav_reader_->Reset();
285 size_t delta = wav_reader_->ReadSamples(
286 data.size() - read, data.subview(read).data());
287 RTC_CHECK_GT(delta, 0) << "No new data read from file";
288 read += delta;
289 } while (read < data.size());
290 }
291 return read;
292 });
293 return buffer->size() > 0;
294 }
295
296 private:
WavFileReader(std::unique_ptr<WavReader> wav_reader,int sampling_frequency_in_hz,int num_channels,bool repeat)297 WavFileReader(std::unique_ptr<WavReader> wav_reader,
298 int sampling_frequency_in_hz,
299 int num_channels,
300 bool repeat)
301 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
302 num_channels_(num_channels),
303 wav_reader_(std::move(wav_reader)),
304 repeat_(repeat) {
305 RTC_CHECK_EQ(wav_reader_->sample_rate(), sampling_frequency_in_hz);
306 RTC_CHECK_EQ(wav_reader_->num_channels(), num_channels);
307 }
308
309 const int sampling_frequency_in_hz_;
310 const int num_channels_;
311 std::unique_ptr<WavReader> wav_reader_;
312 const bool repeat_;
313 };
314
315 class WavFileWriter final : public TestAudioDeviceModule::Renderer {
316 public:
WavFileWriter(absl::string_view filename,int sampling_frequency_in_hz,int num_channels)317 WavFileWriter(absl::string_view filename,
318 int sampling_frequency_in_hz,
319 int num_channels)
320 : WavFileWriter(std::make_unique<WavWriter>(filename,
321 sampling_frequency_in_hz,
322 num_channels),
323 sampling_frequency_in_hz,
324 num_channels) {}
325
SamplingFrequency() const326 int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
327
NumChannels() const328 int NumChannels() const override { return num_channels_; }
329
Render(rtc::ArrayView<const int16_t> data)330 bool Render(rtc::ArrayView<const int16_t> data) override {
331 wav_writer_->WriteSamples(data.data(), data.size());
332 return true;
333 }
334
335 private:
WavFileWriter(std::unique_ptr<WavWriter> wav_writer,int sampling_frequency_in_hz,int num_channels)336 WavFileWriter(std::unique_ptr<WavWriter> wav_writer,
337 int sampling_frequency_in_hz,
338 int num_channels)
339 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
340 wav_writer_(std::move(wav_writer)),
341 num_channels_(num_channels) {}
342
343 int sampling_frequency_in_hz_;
344 std::unique_ptr<WavWriter> wav_writer_;
345 const int num_channels_;
346 };
347
348 class BoundedWavFileWriter : public TestAudioDeviceModule::Renderer {
349 public:
BoundedWavFileWriter(absl::string_view filename,int sampling_frequency_in_hz,int num_channels)350 BoundedWavFileWriter(absl::string_view filename,
351 int sampling_frequency_in_hz,
352 int num_channels)
353 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
354 wav_writer_(filename, sampling_frequency_in_hz, num_channels),
355 num_channels_(num_channels),
356 silent_audio_(
357 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) *
358 num_channels,
359 0),
360 started_writing_(false),
361 trailing_zeros_(0) {}
362
SamplingFrequency() const363 int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
364
NumChannels() const365 int NumChannels() const override { return num_channels_; }
366
Render(rtc::ArrayView<const int16_t> data)367 bool Render(rtc::ArrayView<const int16_t> data) override {
368 const int16_t kAmplitudeThreshold = 5;
369
370 const int16_t* begin = data.begin();
371 const int16_t* end = data.end();
372 if (!started_writing_) {
373 // Cut off silence at the beginning.
374 while (begin < end) {
375 if (std::abs(*begin) > kAmplitudeThreshold) {
376 started_writing_ = true;
377 break;
378 }
379 ++begin;
380 }
381 }
382 if (started_writing_) {
383 // Cut off silence at the end.
384 while (begin < end) {
385 if (*(end - 1) != 0) {
386 break;
387 }
388 --end;
389 }
390 if (begin < end) {
391 // If it turns out that the silence was not final, need to write all the
392 // skipped zeros and continue writing audio.
393 while (trailing_zeros_ > 0) {
394 const size_t zeros_to_write =
395 std::min(trailing_zeros_, silent_audio_.size());
396 wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write);
397 trailing_zeros_ -= zeros_to_write;
398 }
399 wav_writer_.WriteSamples(begin, end - begin);
400 }
401 // Save the number of zeros we skipped in case this needs to be restored.
402 trailing_zeros_ += data.end() - end;
403 }
404 return true;
405 }
406
407 private:
408 int sampling_frequency_in_hz_;
409 WavWriter wav_writer_;
410 const int num_channels_;
411 std::vector<int16_t> silent_audio_;
412 bool started_writing_;
413 size_t trailing_zeros_;
414 };
415
416 class DiscardRenderer final : public TestAudioDeviceModule::Renderer {
417 public:
DiscardRenderer(int sampling_frequency_in_hz,int num_channels)418 explicit DiscardRenderer(int sampling_frequency_in_hz, int num_channels)
419 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
420 num_channels_(num_channels) {}
421
SamplingFrequency() const422 int SamplingFrequency() const override { return sampling_frequency_in_hz_; }
423
NumChannels() const424 int NumChannels() const override { return num_channels_; }
425
Render(rtc::ArrayView<const int16_t> data)426 bool Render(rtc::ArrayView<const int16_t> data) override { return true; }
427
428 private:
429 int sampling_frequency_in_hz_;
430 const int num_channels_;
431 };
432
433 } // namespace
434
SamplesPerFrame(int sampling_frequency_in_hz)435 size_t TestAudioDeviceModule::SamplesPerFrame(int sampling_frequency_in_hz) {
436 return rtc::CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond);
437 }
438
Create(TaskQueueFactory * task_queue_factory,std::unique_ptr<TestAudioDeviceModule::Capturer> capturer,std::unique_ptr<TestAudioDeviceModule::Renderer> renderer,float speed)439 rtc::scoped_refptr<TestAudioDeviceModule> TestAudioDeviceModule::Create(
440 TaskQueueFactory* task_queue_factory,
441 std::unique_ptr<TestAudioDeviceModule::Capturer> capturer,
442 std::unique_ptr<TestAudioDeviceModule::Renderer> renderer,
443 float speed) {
444 return rtc::make_ref_counted<TestAudioDeviceModuleImpl>(
445 task_queue_factory, std::move(capturer), std::move(renderer), speed);
446 }
447
448 std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer>
CreatePulsedNoiseCapturer(int16_t max_amplitude,int sampling_frequency_in_hz,int num_channels)449 TestAudioDeviceModule::CreatePulsedNoiseCapturer(int16_t max_amplitude,
450 int sampling_frequency_in_hz,
451 int num_channels) {
452 return std::make_unique<PulsedNoiseCapturerImpl>(
453 max_amplitude, sampling_frequency_in_hz, num_channels);
454 }
455
456 std::unique_ptr<TestAudioDeviceModule::Renderer>
CreateDiscardRenderer(int sampling_frequency_in_hz,int num_channels)457 TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz,
458 int num_channels) {
459 return std::make_unique<DiscardRenderer>(sampling_frequency_in_hz,
460 num_channels);
461 }
462
463 std::unique_ptr<TestAudioDeviceModule::Capturer>
CreateWavFileReader(absl::string_view filename,int sampling_frequency_in_hz,int num_channels)464 TestAudioDeviceModule::CreateWavFileReader(absl::string_view filename,
465 int sampling_frequency_in_hz,
466 int num_channels) {
467 return std::make_unique<WavFileReader>(filename, sampling_frequency_in_hz,
468 num_channels, false);
469 }
470
471 std::unique_ptr<TestAudioDeviceModule::Capturer>
CreateWavFileReader(absl::string_view filename,bool repeat)472 TestAudioDeviceModule::CreateWavFileReader(absl::string_view filename,
473 bool repeat) {
474 WavReader reader(filename);
475 int sampling_frequency_in_hz = reader.sample_rate();
476 int num_channels = rtc::checked_cast<int>(reader.num_channels());
477 return std::make_unique<WavFileReader>(filename, sampling_frequency_in_hz,
478 num_channels, repeat);
479 }
480
481 std::unique_ptr<TestAudioDeviceModule::Renderer>
CreateWavFileWriter(absl::string_view filename,int sampling_frequency_in_hz,int num_channels)482 TestAudioDeviceModule::CreateWavFileWriter(absl::string_view filename,
483 int sampling_frequency_in_hz,
484 int num_channels) {
485 return std::make_unique<WavFileWriter>(filename, sampling_frequency_in_hz,
486 num_channels);
487 }
488
489 std::unique_ptr<TestAudioDeviceModule::Renderer>
CreateBoundedWavFileWriter(absl::string_view filename,int sampling_frequency_in_hz,int num_channels)490 TestAudioDeviceModule::CreateBoundedWavFileWriter(absl::string_view filename,
491 int sampling_frequency_in_hz,
492 int num_channels) {
493 return std::make_unique<BoundedWavFileWriter>(
494 filename, sampling_frequency_in_hz, num_channels);
495 }
496
497 } // namespace webrtc
498