test_audio_device.cc (18228B)
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 <cstring> 16 #include <memory> 17 #include <string> 18 #include <utility> 19 #include <vector> 20 21 #include "absl/strings/string_view.h" 22 #include "api/array_view.h" 23 #include "api/audio/audio_device.h" 24 #include "api/environment/environment.h" 25 #include "api/make_ref_counted.h" 26 #include "api/scoped_refptr.h" 27 #include "common_audio/wav_file.h" 28 #include "modules/audio_device/audio_device_impl.h" 29 #include "modules/audio_device/test_audio_device_impl.h" 30 #include "rtc_base/buffer.h" 31 #include "rtc_base/checks.h" 32 #include "rtc_base/numerics/safe_conversions.h" 33 #include "rtc_base/random.h" 34 #include "rtc_base/synchronization/mutex.h" 35 #include "rtc_base/system/file_wrapper.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 = kNumMicrosecsPerSec / kFrameLengthUs; 45 46 // A fake capturer that generates pulses with random samples between 47 // -max_amplitude and +max_amplitude. 48 class PulsedNoiseCapturerImpl final 49 : public TestAudioDeviceModule::PulsedNoiseCapturer { 50 public: 51 // Assuming 10ms audio packets. 52 PulsedNoiseCapturerImpl(int16_t max_amplitude, 53 int sampling_frequency_in_hz, 54 int num_channels) 55 : sampling_frequency_in_hz_(sampling_frequency_in_hz), 56 fill_with_zero_(false), 57 random_generator_(1), 58 max_amplitude_(max_amplitude), 59 num_channels_(num_channels) { 60 RTC_DCHECK_GT(max_amplitude, 0); 61 } 62 63 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 64 65 int NumChannels() const override { return num_channels_; } 66 67 bool Capture(BufferT<int16_t>* buffer) override { 68 fill_with_zero_ = !fill_with_zero_; 69 int16_t max_amplitude; 70 { 71 MutexLock lock(&lock_); 72 max_amplitude = max_amplitude_; 73 } 74 buffer->SetData( 75 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) * 76 num_channels_, 77 [&](ArrayView<int16_t> data) { 78 if (fill_with_zero_) { 79 std::fill(data.begin(), data.end(), 0); 80 } else { 81 std::generate(data.begin(), data.end(), [&]() { 82 return random_generator_.Rand(-max_amplitude, max_amplitude); 83 }); 84 } 85 return data.size(); 86 }); 87 return true; 88 } 89 90 void SetMaxAmplitude(int16_t amplitude) override { 91 MutexLock lock(&lock_); 92 max_amplitude_ = amplitude; 93 } 94 95 private: 96 int sampling_frequency_in_hz_; 97 bool fill_with_zero_; 98 Random random_generator_; 99 Mutex lock_; 100 int16_t max_amplitude_ RTC_GUARDED_BY(lock_); 101 const int num_channels_; 102 }; 103 104 class WavFileReader final : public TestAudioDeviceModule::Capturer { 105 public: 106 WavFileReader(absl::string_view filename, 107 int sampling_frequency_in_hz, 108 int num_channels, 109 bool repeat) 110 : WavFileReader(std::make_unique<WavReader>(filename), 111 sampling_frequency_in_hz, 112 num_channels, 113 repeat) {} 114 115 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 116 117 int NumChannels() const override { return num_channels_; } 118 119 bool Capture(BufferT<int16_t>* buffer) override { 120 buffer->SetData( 121 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz_) * 122 num_channels_, 123 [&](ArrayView<int16_t> data) { 124 size_t read = wav_reader_->ReadSamples(data.size(), data.data()); 125 if (read < data.size() && repeat_) { 126 do { 127 wav_reader_->Reset(); 128 size_t delta = wav_reader_->ReadSamples( 129 data.size() - read, data.subview(read).data()); 130 RTC_CHECK_GT(delta, 0) << "No new data read from file"; 131 read += delta; 132 } while (read < data.size()); 133 } 134 return read; 135 }); 136 return !buffer->empty(); 137 } 138 139 private: 140 WavFileReader(std::unique_ptr<WavReader> wav_reader, 141 int sampling_frequency_in_hz, 142 int num_channels, 143 bool repeat) 144 : sampling_frequency_in_hz_(sampling_frequency_in_hz), 145 num_channels_(num_channels), 146 wav_reader_(std::move(wav_reader)), 147 repeat_(repeat) { 148 RTC_CHECK_EQ(wav_reader_->sample_rate(), sampling_frequency_in_hz); 149 RTC_CHECK_EQ(wav_reader_->num_channels(), num_channels); 150 } 151 152 const int sampling_frequency_in_hz_; 153 const int num_channels_; 154 std::unique_ptr<WavReader> wav_reader_; 155 const bool repeat_; 156 }; 157 158 class WavFileWriter final : public TestAudioDeviceModule::Renderer { 159 public: 160 WavFileWriter(absl::string_view filename, 161 int sampling_frequency_in_hz, 162 int num_channels) 163 : WavFileWriter(std::make_unique<WavWriter>(filename, 164 sampling_frequency_in_hz, 165 num_channels), 166 sampling_frequency_in_hz, 167 num_channels) {} 168 169 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 170 171 int NumChannels() const override { return num_channels_; } 172 173 bool Render(ArrayView<const int16_t> data) override { 174 wav_writer_->WriteSamples(data.data(), data.size()); 175 return true; 176 } 177 178 private: 179 WavFileWriter(std::unique_ptr<WavWriter> wav_writer, 180 int sampling_frequency_in_hz, 181 int num_channels) 182 : sampling_frequency_in_hz_(sampling_frequency_in_hz), 183 wav_writer_(std::move(wav_writer)), 184 num_channels_(num_channels) {} 185 186 int sampling_frequency_in_hz_; 187 std::unique_ptr<WavWriter> wav_writer_; 188 const int num_channels_; 189 }; 190 191 class BoundedWavFileWriter : public TestAudioDeviceModule::Renderer { 192 public: 193 BoundedWavFileWriter(absl::string_view filename, 194 int sampling_frequency_in_hz, 195 int num_channels) 196 : sampling_frequency_in_hz_(sampling_frequency_in_hz), 197 wav_writer_(filename, sampling_frequency_in_hz, num_channels), 198 num_channels_(num_channels), 199 silent_audio_( 200 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) * 201 num_channels, 202 0), 203 started_writing_(false), 204 trailing_zeros_(0) {} 205 206 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 207 208 int NumChannels() const override { return num_channels_; } 209 210 bool Render(ArrayView<const int16_t> data) override { 211 const int16_t kAmplitudeThreshold = 5; 212 213 const int16_t* begin = data.begin(); 214 const int16_t* end = data.end(); 215 if (!started_writing_) { 216 // Cut off silence at the beginning. 217 while (begin < end) { 218 if (std::abs(*begin) > kAmplitudeThreshold) { 219 started_writing_ = true; 220 break; 221 } 222 ++begin; 223 } 224 } 225 if (started_writing_) { 226 // Cut off silence at the end. 227 while (begin < end) { 228 if (*(end - 1) != 0) { 229 break; 230 } 231 --end; 232 } 233 if (begin < end) { 234 // If it turns out that the silence was not final, need to write all the 235 // skipped zeros and continue writing audio. 236 while (trailing_zeros_ > 0) { 237 const size_t zeros_to_write = 238 std::min(trailing_zeros_, silent_audio_.size()); 239 wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write); 240 trailing_zeros_ -= zeros_to_write; 241 } 242 wav_writer_.WriteSamples(begin, end - begin); 243 } 244 // Save the number of zeros we skipped in case this needs to be restored. 245 trailing_zeros_ += data.end() - end; 246 } 247 return true; 248 } 249 250 private: 251 int sampling_frequency_in_hz_; 252 WavWriter wav_writer_; 253 const int num_channels_; 254 std::vector<int16_t> silent_audio_; 255 bool started_writing_; 256 size_t trailing_zeros_; 257 }; 258 259 class DiscardRenderer final : public TestAudioDeviceModule::Renderer { 260 public: 261 explicit DiscardRenderer(int sampling_frequency_in_hz, int num_channels) 262 : sampling_frequency_in_hz_(sampling_frequency_in_hz), 263 num_channels_(num_channels) {} 264 265 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 266 267 int NumChannels() const override { return num_channels_; } 268 269 bool Render(ArrayView<const int16_t> /* data */) override { return true; } 270 271 private: 272 int sampling_frequency_in_hz_; 273 const int num_channels_; 274 }; 275 276 class RawFileReader final : public TestAudioDeviceModule::Capturer { 277 public: 278 RawFileReader(absl::string_view input_file_name, 279 int sampling_frequency_in_hz, 280 int num_channels, 281 bool repeat) 282 : input_file_name_(input_file_name), 283 sampling_frequency_in_hz_(sampling_frequency_in_hz), 284 num_channels_(num_channels), 285 repeat_(repeat), 286 read_buffer_( 287 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) * 288 num_channels * 2, 289 0) { 290 input_file_ = FileWrapper::OpenReadOnly(input_file_name_); 291 RTC_CHECK(input_file_.is_open()) 292 << "Failed to open audio input file: " << input_file_name_; 293 } 294 295 ~RawFileReader() override { input_file_.Close(); } 296 297 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 298 299 int NumChannels() const override { return num_channels_; } 300 301 bool Capture(BufferT<int16_t>* buffer) override { 302 buffer->SetData( 303 TestAudioDeviceModule::SamplesPerFrame(SamplingFrequency()) * 304 NumChannels(), 305 [&](ArrayView<int16_t> data) { 306 ArrayView<int8_t> read_buffer_view = ReadBufferView(); 307 size_t size = data.size() * 2; 308 size_t read = input_file_.Read(read_buffer_view.data(), size); 309 if (read < size && repeat_) { 310 do { 311 input_file_.Rewind(); 312 size_t delta = input_file_.Read( 313 read_buffer_view.subview(read).data(), size - read); 314 RTC_CHECK_GT(delta, 0) << "No new data to read from file"; 315 read += delta; 316 } while (read < size); 317 } 318 memcpy(data.data(), read_buffer_view.data(), size); 319 return read / 2; 320 }); 321 return !buffer->empty(); 322 } 323 324 private: 325 ArrayView<int8_t> ReadBufferView() { return read_buffer_; } 326 327 const std::string input_file_name_; 328 const int sampling_frequency_in_hz_; 329 const int num_channels_; 330 const bool repeat_; 331 FileWrapper input_file_; 332 std::vector<int8_t> read_buffer_; 333 }; 334 335 class RawFileWriter : public TestAudioDeviceModule::Renderer { 336 public: 337 RawFileWriter(absl::string_view output_file_name, 338 int sampling_frequency_in_hz, 339 int num_channels) 340 : output_file_name_(output_file_name), 341 sampling_frequency_in_hz_(sampling_frequency_in_hz), 342 num_channels_(num_channels), 343 silent_audio_( 344 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) * 345 num_channels * 2, 346 0), 347 write_buffer_( 348 TestAudioDeviceModule::SamplesPerFrame(sampling_frequency_in_hz) * 349 num_channels * 2, 350 0), 351 started_writing_(false), 352 trailing_zeros_(0) { 353 output_file_ = FileWrapper::OpenWriteOnly(output_file_name_); 354 RTC_CHECK(output_file_.is_open()) 355 << "Failed to open playout file" << output_file_name_; 356 } 357 ~RawFileWriter() override { output_file_.Close(); } 358 359 int SamplingFrequency() const override { return sampling_frequency_in_hz_; } 360 361 int NumChannels() const override { return num_channels_; } 362 363 bool Render(ArrayView<const int16_t> data) override { 364 const int16_t kAmplitudeThreshold = 5; 365 366 const int16_t* begin = data.begin(); 367 const int16_t* end = data.end(); 368 if (!started_writing_) { 369 // Cut off silence at the beginning. 370 while (begin < end) { 371 if (std::abs(*begin) > kAmplitudeThreshold) { 372 started_writing_ = true; 373 break; 374 } 375 ++begin; 376 } 377 } 378 if (started_writing_) { 379 // Cut off silence at the end. 380 while (begin < end) { 381 if (*(end - 1) != 0) { 382 break; 383 } 384 --end; 385 } 386 if (begin < end) { 387 // If it turns out that the silence was not final, need to write all the 388 // skipped zeros and continue writing audio. 389 while (trailing_zeros_ > 0) { 390 const size_t zeros_to_write = 391 std::min(trailing_zeros_, silent_audio_.size()); 392 output_file_.Write(silent_audio_.data(), zeros_to_write * 2); 393 trailing_zeros_ -= zeros_to_write; 394 } 395 WriteInt16(begin, end); 396 } 397 // Save the number of zeros we skipped in case this needs to be restored. 398 trailing_zeros_ += data.end() - end; 399 } 400 return true; 401 } 402 403 private: 404 void WriteInt16(const int16_t* begin, const int16_t* end) { 405 int size = (end - begin) * sizeof(int16_t); 406 memcpy(write_buffer_.data(), begin, size); 407 output_file_.Write(write_buffer_.data(), size); 408 } 409 410 const std::string output_file_name_; 411 const int sampling_frequency_in_hz_; 412 const int num_channels_; 413 FileWrapper output_file_; 414 std::vector<int8_t> silent_audio_; 415 std::vector<int8_t> write_buffer_; 416 bool started_writing_; 417 size_t trailing_zeros_; 418 }; 419 420 } // namespace 421 422 size_t TestAudioDeviceModule::SamplesPerFrame(int sampling_frequency_in_hz) { 423 return CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond); 424 } 425 426 scoped_refptr<AudioDeviceModule> TestAudioDeviceModule::Create( 427 const Environment& env, 428 std::unique_ptr<TestAudioDeviceModule::Capturer> capturer, 429 std::unique_ptr<TestAudioDeviceModule::Renderer> renderer, 430 float speed) { 431 auto audio_device = make_ref_counted<AudioDeviceModuleImpl>( 432 env, AudioDeviceModule::AudioLayer::kDummyAudio, 433 std::make_unique<TestAudioDevice>(env, std::move(capturer), 434 std::move(renderer), speed), 435 /*create_detached=*/true); 436 437 // Ensure that the current platform is supported. 438 if (audio_device->CheckPlatform() == -1) { 439 return nullptr; 440 } 441 442 // Create the platform-dependent implementation. 443 if (audio_device->CreatePlatformSpecificObjects(env) == -1) { 444 return nullptr; 445 } 446 447 // Ensure that the generic audio buffer can communicate with the platform 448 // specific parts. 449 if (audio_device->AttachAudioBuffer() == -1) { 450 return nullptr; 451 } 452 453 return audio_device; 454 } 455 456 std::unique_ptr<TestAudioDeviceModule::PulsedNoiseCapturer> 457 TestAudioDeviceModule::CreatePulsedNoiseCapturer(int16_t max_amplitude, 458 int sampling_frequency_in_hz, 459 int num_channels) { 460 return std::make_unique<PulsedNoiseCapturerImpl>( 461 max_amplitude, sampling_frequency_in_hz, num_channels); 462 } 463 464 std::unique_ptr<TestAudioDeviceModule::Renderer> 465 TestAudioDeviceModule::CreateDiscardRenderer(int sampling_frequency_in_hz, 466 int num_channels) { 467 return std::make_unique<DiscardRenderer>(sampling_frequency_in_hz, 468 num_channels); 469 } 470 471 std::unique_ptr<TestAudioDeviceModule::Capturer> 472 TestAudioDeviceModule::CreateWavFileReader(absl::string_view filename, 473 int sampling_frequency_in_hz, 474 int num_channels) { 475 return std::make_unique<WavFileReader>(filename, sampling_frequency_in_hz, 476 num_channels, false); 477 } 478 479 std::unique_ptr<TestAudioDeviceModule::Capturer> 480 TestAudioDeviceModule::CreateWavFileReader(absl::string_view filename, 481 bool repeat) { 482 WavReader reader(filename); 483 int sampling_frequency_in_hz = reader.sample_rate(); 484 int num_channels = checked_cast<int>(reader.num_channels()); 485 return std::make_unique<WavFileReader>(filename, sampling_frequency_in_hz, 486 num_channels, repeat); 487 } 488 489 std::unique_ptr<TestAudioDeviceModule::Renderer> 490 TestAudioDeviceModule::CreateWavFileWriter(absl::string_view filename, 491 int sampling_frequency_in_hz, 492 int num_channels) { 493 return std::make_unique<WavFileWriter>(filename, sampling_frequency_in_hz, 494 num_channels); 495 } 496 497 std::unique_ptr<TestAudioDeviceModule::Renderer> 498 TestAudioDeviceModule::CreateBoundedWavFileWriter(absl::string_view filename, 499 int sampling_frequency_in_hz, 500 int num_channels) { 501 return std::make_unique<BoundedWavFileWriter>( 502 filename, sampling_frequency_in_hz, num_channels); 503 } 504 505 std::unique_ptr<TestAudioDeviceModule::Capturer> 506 TestAudioDeviceModule::CreateRawFileReader(absl::string_view filename, 507 int sampling_frequency_in_hz, 508 int num_channels, 509 bool repeat) { 510 return std::make_unique<RawFileReader>(filename, sampling_frequency_in_hz, 511 num_channels, repeat); 512 } 513 514 std::unique_ptr<TestAudioDeviceModule::Renderer> 515 TestAudioDeviceModule::CreateRawFileWriter(absl::string_view filename, 516 int sampling_frequency_in_hz, 517 int num_channels) { 518 return std::make_unique<RawFileWriter>(filename, sampling_frequency_in_hz, 519 num_channels); 520 } 521 522 } // namespace webrtc