• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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