Chromium Code Reviews| Index: webrtc/test/file_audio_device.cc |
| diff --git a/webrtc/test/file_audio_device.cc b/webrtc/test/file_audio_device.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5c8fb37845a94aa53bf88a8f9cc4fa17ea4dc319 |
| --- /dev/null |
| +++ b/webrtc/test/file_audio_device.cc |
| @@ -0,0 +1,186 @@ |
| +/* |
| + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
| + * |
| + * Use of this source code is governed by a BSD-style license |
| + * that can be found in the LICENSE file in the root of the source |
| + * tree. An additional intellectual property rights grant can be found |
| + * in the file PATENTS. All contributing project authors may |
| + * be found in the AUTHORS file in the root of the source tree. |
| + */ |
| + |
| +#include "webrtc/test/file_audio_device.h" |
| + |
| +#include <algorithm> |
| + |
| +#include "webrtc/base/checks.h" |
| +#include "webrtc/system_wrappers/include/event_wrapper.h" |
| + |
| +namespace webrtc { |
| + |
| +namespace { |
| + |
| +constexpr int kFrameLengthMs = 10; |
| +constexpr int kFramesPerSecond = 1000 / kFrameLengthMs; |
| + |
| +int NumSamplesPerFrame(int sample_rate_hz) { |
| + return rtc::CheckedDivExact(sample_rate_hz, kFramesPerSecond); |
| +} |
| + |
| +} // namespace |
| +namespace test { |
| + |
| +FileReaderAudioDevice::FileReaderAudioDevice(std::string filename, float speed, |
| + int sample_rate_hz) |
| + : filename_(filename), |
| + sample_rate_hz_(sample_rate_hz), |
| + speed_(speed), |
| + audio_callback_(nullptr), |
| + wav_reader_(nullptr), |
|
kwiberg-webrtc
2017/03/07 10:11:57
unique_ptrs are null by default, so you don't need
|
| + playout_buffer_(NumSamplesPerFrame(sample_rate_hz), 0), |
| + tick_(EventTimerWrapper::Create()), |
| + thread_(FileReaderAudioDevice::Run, this, "FileReaderAudioDevice"), |
| + done_reading_(true, true) { |
| + RTC_CHECK( |
| + sample_rate_hz == 8000 || sample_rate_hz == 16000 || |
| + sample_rate_hz == 32000 || sample_rate_hz == 44100 || |
| + sample_rate_hz == 48000); |
| +} |
| + |
| +FileReaderAudioDevice::~FileReaderAudioDevice() { |
| + StopRecording(); |
| +} |
| + |
| +int32_t FileReaderAudioDevice::StartRecording() { |
| + rtc::CritScope cs(&lock_); |
| + RTC_CHECK(!wav_reader_); |
| + wav_reader_.reset(new WavReader(filename_)); |
| + RTC_CHECK(wav_reader_->sample_rate() == sample_rate_hz_); |
| + RTC_CHECK(wav_reader_->num_channels() == 1); |
|
kwiberg-webrtc
2017/03/07 10:11:57
RTC_CHECK_EQ for these two.
oprypin_webrtc
2017/03/09 08:23:24
Done.
|
| + |
| + RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_)); |
| + thread_.Start(); |
| + thread_.SetPriority(rtc::kHighPriority); |
| + done_reading_.Reset(); |
| + return 0; |
| +} |
| + |
| +int32_t FileReaderAudioDevice::StopRecording() { |
| + rtc::CritScope cs(&lock_); |
| + wav_reader_.reset(); |
| + thread_.Stop(); |
| + return 0; |
| +} |
| + |
| +int32_t FileReaderAudioDevice::RegisterAudioCallback(AudioTransport* callback) { |
| + rtc::CritScope cs(&lock_); |
| + RTC_DCHECK(callback || audio_callback_ != nullptr); |
|
kwiberg-webrtc
2017/03/07 10:11:57
Test code, so CHECK instead of DCHECK everywhere?
oprypin_webrtc
2017/03/09 08:23:24
Done.
|
| + audio_callback_ = callback; |
| + return 0; |
| +} |
| + |
| +bool FileReaderAudioDevice::Recording() const { |
| + rtc::CritScope cs(&lock_); |
| + return static_cast<bool>(wav_reader_); |
| +} |
| + |
| +bool FileReaderAudioDevice::WaitForFileEnd(int timeout_ms) { |
| + RTC_DCHECK(Recording()); |
| + return done_reading_.Wait(timeout_ms); |
| +} |
| + |
| +bool FileReaderAudioDevice::Run(void* obj) { |
| + static_cast<FileReaderAudioDevice*>(obj)->ProcessAudio(); |
| + return true; |
| +} |
| + |
| +void FileReaderAudioDevice::ProcessAudio() { |
| + { |
| + rtc::CritScope cs(&lock_); |
| + // Capture 10ms of audio. 2 bytes per sample. |
| + const size_t samples_out = wav_reader_->ReadSamples( |
| + playout_buffer_.size(), playout_buffer_.data()); |
| + if (samples_out) { |
|
kwiberg-webrtc
2017/03/07 10:11:57
if (samples_out > 0)
to emphasize that samples_ou
oprypin_webrtc
2017/03/09 08:23:24
Done.
|
| + RTC_CHECK(samples_out <= playout_buffer_.size()); |
|
kwiberg-webrtc
2017/03/07 10:11:57
RTC_CHECK_LE
Also, move this check before line 10
oprypin_webrtc
2017/03/09 08:23:24
Done.
|
| + uint32_t new_mic_level; |
| + audio_callback_->RecordedDataIsAvailable( |
| + playout_buffer_.data(), samples_out, 2, 1, |
| + sample_rate_hz_, 0, 0, 0, false, new_mic_level); |
| + } else { |
| + done_reading_.Set(); |
| + } |
| + } |
| + tick_->Wait(WEBRTC_EVENT_INFINITE); |
| +} |
| + |
| + |
| +FileWriterAudioDevice::FileWriterAudioDevice(std::string filename, float speed, |
| + int sample_rate_hz) |
| + : filename_(filename), |
| + sample_rate_hz_(sample_rate_hz), |
| + speed_(speed), |
| + audio_callback_(nullptr), |
| + wav_writer_(nullptr), |
| + playout_buffer_(NumSamplesPerFrame(sample_rate_hz), 0), |
| + tick_(EventTimerWrapper::Create()), |
| + thread_(FileWriterAudioDevice::Run, this, "FileWriterAudioDevice") { |
| + RTC_CHECK( |
| + sample_rate_hz == 8000 || sample_rate_hz == 16000 || |
| + sample_rate_hz == 32000 || sample_rate_hz == 44100 || |
| + sample_rate_hz == 48000); |
| +} |
| + |
| +FileWriterAudioDevice::~FileWriterAudioDevice() { |
| + StopPlayout(); |
| +} |
| + |
| +int32_t FileWriterAudioDevice::StartPlayout() { |
| + rtc::CritScope cs(&lock_); |
| + RTC_CHECK(!wav_writer_); |
| + wav_writer_.reset(new WavWriter(filename_, sample_rate_hz_, 1)); |
| + |
| + RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_)); |
| + thread_.Start(); |
| + thread_.SetPriority(rtc::kHighPriority); |
| + return 0; |
| +} |
| + |
| +int32_t FileWriterAudioDevice::StopPlayout() { |
| + rtc::CritScope cs(&lock_); |
| + wav_writer_.reset(); // This also finalizes and closes the file |
| + thread_.Stop(); |
| + return 0; |
| +} |
| + |
| +int32_t FileWriterAudioDevice::RegisterAudioCallback(AudioTransport* callback) { |
| + rtc::CritScope cs(&lock_); |
| + RTC_DCHECK(callback || audio_callback_ != nullptr); |
| + audio_callback_ = callback; |
| + return 0; |
| +} |
| + |
| +bool FileWriterAudioDevice::Playing() const { |
| + rtc::CritScope cs(&lock_); |
| + return static_cast<bool>(wav_writer_); |
| +} |
| + |
| +bool FileWriterAudioDevice::Run(void* obj) { |
| + static_cast<FileWriterAudioDevice*>(obj)->ProcessAudio(); |
| + return true; |
| +} |
| + |
| +void FileWriterAudioDevice::ProcessAudio() { |
| + { |
| + rtc::CritScope cs(&lock_); |
| + size_t samples_out; |
| + int64_t elapsed_time_ms; |
| + int64_t ntp_time_ms; |
| + audio_callback_->NeedMorePlayData( |
| + playout_buffer_.size(), 2, 1, sample_rate_hz_, |
| + playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms); |
| + wav_writer_->WriteSamples(playout_buffer_.data(), samples_out); |
| + } |
| + tick_->Wait(WEBRTC_EVENT_INFINITE); |
| +} |
| + |
| +} // namespace test |
| +} // namespace webrtc |