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