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