1 /*
2  *  Copyright (c) 2013 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 "test/fake_audio_device.h"
12 
13 #include <algorithm>
14 #include <utility>
15 
16 #include "common_audio/wav_file.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/random.h"
19 #include "system_wrappers/include/event_wrapper.h"
20 
21 namespace webrtc {
22 
23 namespace {
24 
25 constexpr int kFrameLengthMs = 10;
26 constexpr int kFramesPerSecond = 1000 / kFrameLengthMs;
27 
28 // Assuming 10ms audio packets..
29 class PulsedNoiseCapturer final : public test::FakeAudioDevice::Capturer {
30  public:
PulsedNoiseCapturer(int16_t max_amplitude,int sampling_frequency_in_hz)31   PulsedNoiseCapturer(int16_t max_amplitude, int sampling_frequency_in_hz)
32       : sampling_frequency_in_hz_(sampling_frequency_in_hz),
33         fill_with_zero_(false),
34         random_generator_(1),
35         max_amplitude_(max_amplitude) {
36     RTC_DCHECK_GT(max_amplitude, 0);
37   }
38 
SamplingFrequency() const39   int SamplingFrequency() const override {
40     return sampling_frequency_in_hz_;
41   }
42 
Capture(rtc::BufferT<int16_t> * buffer)43   bool Capture(rtc::BufferT<int16_t>* buffer) override {
44     fill_with_zero_ = !fill_with_zero_;
45     buffer->SetData(
46         test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
47         [&](rtc::ArrayView<int16_t> data) {
48       if (fill_with_zero_) {
49         std::fill(data.begin(), data.end(), 0);
50       } else {
51         std::generate(data.begin(), data.end(), [&]() {
52           return random_generator_.Rand(-max_amplitude_, max_amplitude_);
53         });
54       }
55       return data.size();
56     });
57     return true;
58   }
59 
60  private:
61   int sampling_frequency_in_hz_;
62   bool fill_with_zero_;
63   Random random_generator_;
64   const int16_t max_amplitude_;
65 };
66 
67 class WavFileReader final : public test::FakeAudioDevice::Capturer {
68  public:
WavFileReader(std::string filename,int sampling_frequency_in_hz)69   WavFileReader(std::string filename, int sampling_frequency_in_hz)
70       : sampling_frequency_in_hz_(sampling_frequency_in_hz),
71         wav_reader_(filename) {
72     RTC_CHECK_EQ(wav_reader_.sample_rate(), sampling_frequency_in_hz);
73     RTC_CHECK_EQ(wav_reader_.num_channels(), 1);
74   }
75 
SamplingFrequency() const76   int SamplingFrequency() const override {
77     return sampling_frequency_in_hz_;
78   }
79 
Capture(rtc::BufferT<int16_t> * buffer)80   bool Capture(rtc::BufferT<int16_t>* buffer) override {
81     buffer->SetData(
82         test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
83         [&](rtc::ArrayView<int16_t> data) {
84       return wav_reader_.ReadSamples(data.size(), data.data());
85     });
86     return buffer->size() > 0;
87   }
88 
89  private:
90   int sampling_frequency_in_hz_;
91   WavReader wav_reader_;
92 };
93 
94 class WavFileWriter final : public test::FakeAudioDevice::Renderer {
95  public:
WavFileWriter(std::string filename,int sampling_frequency_in_hz)96   WavFileWriter(std::string filename, int sampling_frequency_in_hz)
97       : sampling_frequency_in_hz_(sampling_frequency_in_hz),
98         wav_writer_(filename, sampling_frequency_in_hz, 1) {}
99 
SamplingFrequency() const100   int SamplingFrequency() const override {
101     return sampling_frequency_in_hz_;
102   }
103 
Render(rtc::ArrayView<const int16_t> data)104   bool Render(rtc::ArrayView<const int16_t> data) override {
105     wav_writer_.WriteSamples(data.data(), data.size());
106     return true;
107   }
108 
109  private:
110   int sampling_frequency_in_hz_;
111   WavWriter wav_writer_;
112 };
113 
114 class BoundedWavFileWriter : public test::FakeAudioDevice::Renderer {
115  public:
BoundedWavFileWriter(std::string filename,int sampling_frequency_in_hz)116   BoundedWavFileWriter(std::string filename, int sampling_frequency_in_hz)
117       : sampling_frequency_in_hz_(sampling_frequency_in_hz),
118         wav_writer_(filename, sampling_frequency_in_hz, 1),
119         silent_audio_(test::FakeAudioDevice::SamplesPerFrame(
120             sampling_frequency_in_hz), 0),
121         started_writing_(false),
122         trailing_zeros_(0) {}
123 
SamplingFrequency() const124   int SamplingFrequency() const override {
125     return sampling_frequency_in_hz_;
126   }
127 
Render(rtc::ArrayView<const int16_t> data)128   bool Render(rtc::ArrayView<const int16_t> data) override {
129     const int16_t kAmplitudeThreshold = 5;
130 
131     const int16_t* begin = data.begin();
132     const int16_t* end = data.end();
133     if (!started_writing_) {
134       // Cut off silence at the beginning.
135       while (begin < end) {
136         if (std::abs(*begin) > kAmplitudeThreshold) {
137           started_writing_ = true;
138           break;
139         }
140         ++begin;
141       }
142     }
143     if (started_writing_) {
144       // Cut off silence at the end.
145       while (begin < end) {
146         if (*(end - 1) != 0) {
147           break;
148         }
149         --end;
150       }
151       if (begin < end) {
152         // If it turns out that the silence was not final, need to write all the
153         // skipped zeros and continue writing audio.
154         while (trailing_zeros_ > 0) {
155           const size_t zeros_to_write = std::min(trailing_zeros_,
156                                                  silent_audio_.size());
157           wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write);
158           trailing_zeros_ -= zeros_to_write;
159         }
160         wav_writer_.WriteSamples(begin, end - begin);
161       }
162       // Save the number of zeros we skipped in case this needs to be restored.
163       trailing_zeros_ += data.end() - end;
164     }
165     return true;
166   }
167 
168  private:
169   int sampling_frequency_in_hz_;
170   WavWriter wav_writer_;
171   std::vector<int16_t> silent_audio_;
172   bool started_writing_;
173   size_t trailing_zeros_;
174 };
175 
176 
177 class DiscardRenderer final : public test::FakeAudioDevice::Renderer {
178  public:
DiscardRenderer(int sampling_frequency_in_hz)179   explicit DiscardRenderer(int sampling_frequency_in_hz)
180       : sampling_frequency_in_hz_(sampling_frequency_in_hz) {}
181 
SamplingFrequency() const182   int SamplingFrequency() const override {
183     return sampling_frequency_in_hz_;
184   }
185 
Render(rtc::ArrayView<const int16_t> data)186   bool Render(rtc::ArrayView<const int16_t> data) override {
187     return true;
188   }
189 
190  private:
191   int sampling_frequency_in_hz_;
192 };
193 
194 }  // namespace
195 namespace test {
196 
SamplesPerFrame(int sampling_frequency_in_hz)197 size_t FakeAudioDevice::SamplesPerFrame(int sampling_frequency_in_hz) {
198   return rtc::CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond);
199 }
200 
201 std::unique_ptr<FakeAudioDevice::Capturer>
CreatePulsedNoiseCapturer(int16_t max_amplitude,int sampling_frequency_in_hz)202     FakeAudioDevice::CreatePulsedNoiseCapturer(
203         int16_t max_amplitude, int sampling_frequency_in_hz) {
204   return std::unique_ptr<FakeAudioDevice::Capturer>(
205       new PulsedNoiseCapturer(max_amplitude, sampling_frequency_in_hz));
206 }
207 
CreateWavFileReader(std::string filename,int sampling_frequency_in_hz)208 std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
209     std::string filename, int sampling_frequency_in_hz) {
210   return std::unique_ptr<FakeAudioDevice::Capturer>(
211       new WavFileReader(filename, sampling_frequency_in_hz));
212 }
213 
CreateWavFileReader(std::string filename)214 std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
215     std::string filename) {
216   int sampling_frequency_in_hz = WavReader(filename).sample_rate();
217   return std::unique_ptr<FakeAudioDevice::Capturer>(
218       new WavFileReader(filename, sampling_frequency_in_hz));
219 }
220 
CreateWavFileWriter(std::string filename,int sampling_frequency_in_hz)221 std::unique_ptr<FakeAudioDevice::Renderer> FakeAudioDevice::CreateWavFileWriter(
222     std::string filename, int sampling_frequency_in_hz) {
223   return std::unique_ptr<FakeAudioDevice::Renderer>(
224       new WavFileWriter(filename, sampling_frequency_in_hz));
225 }
226 
227 std::unique_ptr<FakeAudioDevice::Renderer>
CreateBoundedWavFileWriter(std::string filename,int sampling_frequency_in_hz)228     FakeAudioDevice::CreateBoundedWavFileWriter(
229         std::string filename, int sampling_frequency_in_hz) {
230   return std::unique_ptr<FakeAudioDevice::Renderer>(
231       new BoundedWavFileWriter(filename, sampling_frequency_in_hz));
232 }
233 
234 std::unique_ptr<FakeAudioDevice::Renderer>
CreateDiscardRenderer(int sampling_frequency_in_hz)235     FakeAudioDevice::CreateDiscardRenderer(int sampling_frequency_in_hz) {
236   return std::unique_ptr<FakeAudioDevice::Renderer>(
237       new DiscardRenderer(sampling_frequency_in_hz));
238 }
239 
240 
FakeAudioDevice(std::unique_ptr<Capturer> capturer,std::unique_ptr<Renderer> renderer,float speed)241 FakeAudioDevice::FakeAudioDevice(std::unique_ptr<Capturer> capturer,
242                                  std::unique_ptr<Renderer> renderer,
243                                  float speed)
244     : capturer_(std::move(capturer)),
245       renderer_(std::move(renderer)),
246       speed_(speed),
247       audio_callback_(nullptr),
248       rendering_(false),
249       capturing_(false),
250       done_rendering_(true, true),
251       done_capturing_(true, true),
252       tick_(EventTimerWrapper::Create()),
253       thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") {
254   auto good_sample_rate = [](int sr) {
255     return sr == 8000 || sr == 16000 || sr == 32000
256         || sr == 44100 || sr == 48000;
257   };
258 
259   if (renderer_) {
260     const int sample_rate = renderer_->SamplingFrequency();
261     playout_buffer_.resize(SamplesPerFrame(sample_rate), 0);
262     RTC_CHECK(good_sample_rate(sample_rate));
263   }
264   if (capturer_) {
265     RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency()));
266   }
267 }
268 
~FakeAudioDevice()269 FakeAudioDevice::~FakeAudioDevice() {
270   StopPlayout();
271   StopRecording();
272   thread_.Stop();
273 }
274 
StartPlayout()275 int32_t FakeAudioDevice::StartPlayout() {
276   rtc::CritScope cs(&lock_);
277   RTC_CHECK(renderer_);
278   rendering_ = true;
279   done_rendering_.Reset();
280   return 0;
281 }
282 
StopPlayout()283 int32_t FakeAudioDevice::StopPlayout() {
284   rtc::CritScope cs(&lock_);
285   rendering_ = false;
286   done_rendering_.Set();
287   return 0;
288 }
289 
StartRecording()290 int32_t FakeAudioDevice::StartRecording() {
291   rtc::CritScope cs(&lock_);
292   RTC_CHECK(capturer_);
293   capturing_ = true;
294   done_capturing_.Reset();
295   return 0;
296 }
297 
StopRecording()298 int32_t FakeAudioDevice::StopRecording() {
299   rtc::CritScope cs(&lock_);
300   capturing_ = false;
301   done_capturing_.Set();
302   return 0;
303 }
304 
Init()305 int32_t FakeAudioDevice::Init() {
306   RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_));
307   thread_.Start();
308   thread_.SetPriority(rtc::kHighPriority);
309   return 0;
310 }
311 
RegisterAudioCallback(AudioTransport * callback)312 int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) {
313   rtc::CritScope cs(&lock_);
314   RTC_DCHECK(callback || audio_callback_);
315   audio_callback_ = callback;
316   return 0;
317 }
318 
Playing() const319 bool FakeAudioDevice::Playing() const {
320   rtc::CritScope cs(&lock_);
321   return rendering_;
322 }
323 
Recording() const324 bool FakeAudioDevice::Recording() const {
325   rtc::CritScope cs(&lock_);
326   return capturing_;
327 }
328 
WaitForPlayoutEnd(int timeout_ms)329 bool FakeAudioDevice::WaitForPlayoutEnd(int timeout_ms) {
330   return done_rendering_.Wait(timeout_ms);
331 }
332 
WaitForRecordingEnd(int timeout_ms)333 bool FakeAudioDevice::WaitForRecordingEnd(int timeout_ms) {
334   return done_capturing_.Wait(timeout_ms);
335 }
336 
Run(void * obj)337 bool FakeAudioDevice::Run(void* obj) {
338   static_cast<FakeAudioDevice*>(obj)->ProcessAudio();
339   return true;
340 }
341 
ProcessAudio()342 void FakeAudioDevice::ProcessAudio() {
343   {
344     rtc::CritScope cs(&lock_);
345     if (capturing_) {
346       // Capture 10ms of audio. 2 bytes per sample.
347       const bool keep_capturing = capturer_->Capture(&recording_buffer_);
348       uint32_t new_mic_level;
349       if (recording_buffer_.size() > 0) {
350         audio_callback_->RecordedDataIsAvailable(
351             recording_buffer_.data(), recording_buffer_.size(), 2, 1,
352             capturer_->SamplingFrequency(), 0, 0, 0, false, new_mic_level);
353       }
354       if (!keep_capturing) {
355         capturing_ = false;
356         done_capturing_.Set();
357       }
358     }
359     if (rendering_) {
360       size_t samples_out;
361       int64_t elapsed_time_ms;
362       int64_t ntp_time_ms;
363       const int sampling_frequency = renderer_->SamplingFrequency();
364       audio_callback_->NeedMorePlayData(
365           SamplesPerFrame(sampling_frequency), 2, 1, sampling_frequency,
366           playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms);
367       const bool keep_rendering = renderer_->Render(
368           rtc::ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
369       if (!keep_rendering) {
370         rendering_ = false;
371         done_rendering_.Set();
372       }
373     }
374   }
375   tick_->Wait(WEBRTC_EVENT_INFINITE);
376 }
377 
378 
379 }  // namespace test
380 }  // namespace webrtc
381