Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(765)

Side by Side Diff: webrtc/test/fake_audio_device.cc

Issue 2717623003: Add the ability to read/write to WAV files in FakeAudioDevice (Closed)
Patch Set: Remove obsolete files from build Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/test/fake_audio_device.h" 11 #include "webrtc/test/fake_audio_device.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <utility>
14 15
15 #include "webrtc/base/array_view.h"
16 #include "webrtc/base/checks.h" 16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/random.h" 17 #include "webrtc/base/random.h"
18 #include "webrtc/common_audio/wav_file.h"
18 #include "webrtc/system_wrappers/include/event_wrapper.h" 19 #include "webrtc/system_wrappers/include/event_wrapper.h"
19 20
20 namespace webrtc { 21 namespace webrtc {
21 22
22 namespace { 23 namespace {
23 24
24 constexpr int kFrameLengthMs = 10; 25 constexpr int kFrameLengthMs = 10;
25 constexpr int kFramesPerSecond = 1000 / kFrameLengthMs; 26 constexpr int kFramesPerSecond = 1000 / kFrameLengthMs;
26 27
27 } // namespace 28 } // namespace
kwiberg-webrtc 2017/03/09 10:04:10 The Capturers and Renderers should be in an anonym
oprypin_webrtc 2017/03/10 10:44:27 Done.
28 namespace test { 29 namespace test {
29 30
31 FakeAudioDevice::Streamer::Streamer(int sampling_frequency_in_hz)
32 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
33 num_samples_per_frame_(
34 rtc::CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond)) {
35 RTC_CHECK(
36 sampling_frequency_in_hz == 8000 || sampling_frequency_in_hz == 16000 ||
37 sampling_frequency_in_hz == 32000 || sampling_frequency_in_hz == 44100 ||
38 sampling_frequency_in_hz == 48000);
39 }
40
30 // Assuming 10ms audio packets.. 41 // Assuming 10ms audio packets..
31 class FakeAudioDevice::PulsedNoiseCapturer { 42 class FakeAudioDevice::PulsedNoiseCapturer : public FakeAudioDevice::Capturer {
32 public: 43 public:
33 PulsedNoiseCapturer(size_t num_samples_per_frame, int16_t max_amplitude) 44 PulsedNoiseCapturer(int sampling_frequency_in_hz, int16_t max_amplitude)
34 : fill_with_zero_(false), 45 : Capturer(sampling_frequency_in_hz),
46 fill_with_zero_(false),
35 random_generator_(1), 47 random_generator_(1),
36 max_amplitude_(max_amplitude), 48 max_amplitude_(max_amplitude),
37 random_audio_(num_samples_per_frame), 49 random_audio_(SamplesPerFrame()),
38 silent_audio_(num_samples_per_frame, 0) { 50 silent_audio_(SamplesPerFrame(), 0) {
39 RTC_DCHECK_GT(max_amplitude, 0); 51 RTC_DCHECK_GT(max_amplitude, 0);
40 } 52 }
41 53
42 rtc::ArrayView<const int16_t> Capture() { 54 rtc::ArrayView<const int16_t> Capture() override {
43 fill_with_zero_ = !fill_with_zero_; 55 fill_with_zero_ = !fill_with_zero_;
44 if (!fill_with_zero_) { 56 if (!fill_with_zero_) {
45 std::generate(random_audio_.begin(), random_audio_.end(), [&]() { 57 std::generate(random_audio_.begin(), random_audio_.end(), [&]() {
46 return random_generator_.Rand(-max_amplitude_, max_amplitude_); 58 return random_generator_.Rand(-max_amplitude_, max_amplitude_);
47 }); 59 });
48 } 60 }
49 return fill_with_zero_ ? silent_audio_ : random_audio_; 61 return fill_with_zero_ ? silent_audio_ : random_audio_;
50 } 62 }
51 63
52 private: 64 private:
53 bool fill_with_zero_; 65 bool fill_with_zero_;
54 Random random_generator_; 66 Random random_generator_;
55 const int16_t max_amplitude_; 67 const int16_t max_amplitude_;
56 std::vector<int16_t> random_audio_; 68 std::vector<int16_t> random_audio_;
57 std::vector<int16_t> silent_audio_; 69 std::vector<int16_t> silent_audio_;
58 }; 70 };
59 71
72 class FakeAudioDevice::WavFileReader : public FakeAudioDevice::Capturer {
kwiberg-webrtc 2017/03/09 10:04:10 This class (and the other three) can be final.
oprypin_webrtc 2017/03/10 10:44:27 Done.
73 public:
74 WavFileReader(std::string filename, int sampling_frequency_in_hz)
75 : FakeAudioDevice::Capturer(sampling_frequency_in_hz),
76 wav_reader_(filename),
77 buffer_(SamplesPerFrame(), 0) {
78 RTC_CHECK_EQ(wav_reader_.sample_rate(), sampling_frequency_in_hz);
79 RTC_CHECK_EQ(wav_reader_.num_channels(), 1);
80 }
81
82 rtc::ArrayView<const int16_t> Capture() override {
83 const size_t samples_out = wav_reader_.ReadSamples(buffer_.size(),
84 buffer_.data());
85 RTC_CHECK_LE(samples_out, buffer_.size());
86 return rtc::ArrayView<const int16_t>(buffer_.data(), samples_out);
87 }
88
89 private:
90 WavReader wav_reader_;
91 std::vector<int16_t> buffer_;
92 // This event is set when the input audio file ends
kwiberg-webrtc 2017/03/09 10:04:10 Orphaned comment.
oprypin_webrtc 2017/03/10 10:44:27 Done. Removed.
93 };
94
95 class FakeAudioDevice::WavFileWriter : public FakeAudioDevice::Renderer {
96 public:
97 WavFileWriter(std::string filename, int sampling_frequency_in_hz)
98 : FakeAudioDevice::Renderer(sampling_frequency_in_hz),
99 wav_writer_(filename, sampling_frequency_in_hz, 1) {}
100
101 bool Render(rtc::ArrayView<const int16_t> data) {
kwiberg-webrtc 2017/03/09 10:04:10 override?
oprypin_webrtc 2017/03/10 10:44:27 Done.
102 wav_writer_.WriteSamples(data.data(), data.size());
103 return true;
104 }
105
106 private:
107 WavWriter wav_writer_;
108 };
109
110 class FakeAudioDevice::Discarder : public FakeAudioDevice::Renderer {
111 public:
112 using Renderer::Renderer;
113
114 bool Render(rtc::ArrayView<const int16_t> data) {
115 return true;
116 }
117 };
118
119 std::unique_ptr<FakeAudioDevice::Capturer>
120 FakeAudioDevice::CreatePulsedNoiseCapturer(
121 int sampling_frequency_in_hz, int16_t max_amplitude) {
122 return std::unique_ptr<FakeAudioDevice::Capturer>(
123 new FakeAudioDevice::PulsedNoiseCapturer(
124 sampling_frequency_in_hz, max_amplitude));
125 }
126
127 std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
128 std::string filename, int sampling_frequency_in_hz) {
129 return std::unique_ptr<FakeAudioDevice::Capturer>(
130 new FakeAudioDevice::WavFileReader(filename, sampling_frequency_in_hz));
131 }
132
133 std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
134 std::string filename) {
135 int sampling_frequency_in_hz = WavReader(filename).sample_rate();
136 return std::unique_ptr<FakeAudioDevice::Capturer>(
137 new FakeAudioDevice::WavFileReader(filename, sampling_frequency_in_hz));
138 }
139
140 std::unique_ptr<FakeAudioDevice::Renderer> FakeAudioDevice::CreateWavFileWriter(
141 std::string filename, int sampling_frequency_in_hz) {
142 return std::unique_ptr<FakeAudioDevice::Renderer>(
143 new FakeAudioDevice::WavFileWriter(filename, sampling_frequency_in_hz));
144 }
145
146 std::unique_ptr<FakeAudioDevice::Renderer> FakeAudioDevice::CreateDiscarder(
147 int sampling_frequency_in_hz) {
148 return std::unique_ptr<FakeAudioDevice::Renderer>(
149 new FakeAudioDevice::Discarder(sampling_frequency_in_hz));
150 }
151
152
153 FakeAudioDevice::FakeAudioDevice(std::unique_ptr<Capturer> capturer,
154 std::unique_ptr<Renderer> renderer,
155 float speed)
156 : capturer_(std::move(capturer)),
157 renderer_(std::move(renderer)),
158 speed_(speed),
159 audio_callback_(nullptr),
160 rendering_(false),
161 capturing_(false),
162 done_rendering_(true, true),
163 done_capturing_(true, true),
164 tick_(EventTimerWrapper::Create()),
165 thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") {
166 if (renderer_) {
167 playout_buffer_.resize(renderer_->SamplesPerFrame(), 0);
168 }
169 }
170
60 FakeAudioDevice::FakeAudioDevice(float speed, 171 FakeAudioDevice::FakeAudioDevice(float speed,
61 int sampling_frequency_in_hz, 172 int sampling_frequency_in_hz,
62 int16_t max_amplitude) 173 int16_t max_amplitude)
63 : sampling_frequency_in_hz_(sampling_frequency_in_hz), 174 : FakeAudioDevice(
64 num_samples_per_frame_( 175 CreatePulsedNoiseCapturer(sampling_frequency_in_hz, max_amplitude),
65 rtc::CheckedDivExact(sampling_frequency_in_hz_, kFramesPerSecond)), 176 CreateDiscarder(sampling_frequency_in_hz), speed) {}
66 speed_(speed),
67 audio_callback_(nullptr),
68 rendering_(false),
69 capturing_(false),
70 capturer_(new FakeAudioDevice::PulsedNoiseCapturer(num_samples_per_frame_,
71 max_amplitude)),
72 playout_buffer_(num_samples_per_frame_, 0),
73 tick_(EventTimerWrapper::Create()),
74 thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") {
75 RTC_DCHECK(
76 sampling_frequency_in_hz == 8000 || sampling_frequency_in_hz == 16000 ||
77 sampling_frequency_in_hz == 32000 || sampling_frequency_in_hz == 44100 ||
78 sampling_frequency_in_hz == 48000);
79 }
80 177
81 FakeAudioDevice::~FakeAudioDevice() { 178 FakeAudioDevice::~FakeAudioDevice() {
82 StopPlayout(); 179 StopPlayout();
83 StopRecording(); 180 StopRecording();
84 thread_.Stop(); 181 thread_.Stop();
85 } 182 }
86 183
87 int32_t FakeAudioDevice::StartPlayout() { 184 int32_t FakeAudioDevice::StartPlayout() {
88 rtc::CritScope cs(&lock_); 185 rtc::CritScope cs(&lock_);
186 RTC_CHECK(renderer_);
89 rendering_ = true; 187 rendering_ = true;
188 done_rendering_.Reset();
90 return 0; 189 return 0;
91 } 190 }
92 191
93 int32_t FakeAudioDevice::StopPlayout() { 192 int32_t FakeAudioDevice::StopPlayout() {
94 rtc::CritScope cs(&lock_); 193 rtc::CritScope cs(&lock_);
95 rendering_ = false; 194 rendering_ = false;
195 done_rendering_.Set();
96 return 0; 196 return 0;
97 } 197 }
98 198
99 int32_t FakeAudioDevice::StartRecording() { 199 int32_t FakeAudioDevice::StartRecording() {
100 rtc::CritScope cs(&lock_); 200 rtc::CritScope cs(&lock_);
201 RTC_CHECK(capturer_);
101 capturing_ = true; 202 capturing_ = true;
203 done_capturing_.Reset();
102 return 0; 204 return 0;
103 } 205 }
104 206
105 int32_t FakeAudioDevice::StopRecording() { 207 int32_t FakeAudioDevice::StopRecording() {
106 rtc::CritScope cs(&lock_); 208 rtc::CritScope cs(&lock_);
107 capturing_ = false; 209 capturing_ = false;
210 done_capturing_.Set();
108 return 0; 211 return 0;
109 } 212 }
110 213
111 int32_t FakeAudioDevice::Init() { 214 int32_t FakeAudioDevice::Init() {
112 RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_)); 215 RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_));
113 thread_.Start(); 216 thread_.Start();
114 thread_.SetPriority(rtc::kHighPriority); 217 thread_.SetPriority(rtc::kHighPriority);
115 return 0; 218 return 0;
116 } 219 }
117 220
118 int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { 221 int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) {
119 rtc::CritScope cs(&lock_); 222 rtc::CritScope cs(&lock_);
120 RTC_DCHECK(callback || audio_callback_ != nullptr); 223 RTC_DCHECK(callback || audio_callback_);
121 audio_callback_ = callback; 224 audio_callback_ = callback;
122 return 0; 225 return 0;
123 } 226 }
124 227
125 bool FakeAudioDevice::Playing() const { 228 bool FakeAudioDevice::Playing() const {
126 rtc::CritScope cs(&lock_); 229 rtc::CritScope cs(&lock_);
127 return rendering_; 230 return rendering_;
128 } 231 }
129 232
130 bool FakeAudioDevice::Recording() const { 233 bool FakeAudioDevice::Recording() const {
131 rtc::CritScope cs(&lock_); 234 rtc::CritScope cs(&lock_);
132 return capturing_; 235 return capturing_;
133 } 236 }
134 237
238 bool FakeAudioDevice::WaitForPlayoutEnd(int timeout_ms) {
239 return done_rendering_.Wait(timeout_ms);
240 }
241
242 bool FakeAudioDevice::WaitForRecordingEnd(int timeout_ms) {
243 return done_capturing_.Wait(timeout_ms);
244 }
245
135 bool FakeAudioDevice::Run(void* obj) { 246 bool FakeAudioDevice::Run(void* obj) {
136 static_cast<FakeAudioDevice*>(obj)->ProcessAudio(); 247 static_cast<FakeAudioDevice*>(obj)->ProcessAudio();
137 return true; 248 return true;
138 } 249 }
139 250
140 void FakeAudioDevice::ProcessAudio() { 251 void FakeAudioDevice::ProcessAudio() {
141 { 252 {
142 rtc::CritScope cs(&lock_); 253 rtc::CritScope cs(&lock_);
143 if (capturing_) { 254 if (capturing_) {
144 // Capture 10ms of audio. 2 bytes per sample. 255 // Capture 10ms of audio. 2 bytes per sample.
145 rtc::ArrayView<const int16_t> audio_data = capturer_->Capture(); 256 rtc::ArrayView<const int16_t> audio_data = capturer_->Capture();
146 uint32_t new_mic_level = 0; 257 uint32_t new_mic_level = 0;
147 audio_callback_->RecordedDataIsAvailable( 258 if (audio_data.size() > 0) {
148 audio_data.data(), audio_data.size(), 2, 1, sampling_frequency_in_hz_, 259 audio_callback_->RecordedDataIsAvailable(
149 0, 0, 0, false, new_mic_level); 260 audio_data.data(), audio_data.size(), 2, 1,
261 capturer_->SamplingFrequency(), 0, 0, 0, false, new_mic_level);
262 } else {
263 StopRecording();
264 }
150 } 265 }
151 if (rendering_) { 266 if (rendering_) {
152 size_t samples_out = 0; 267 size_t samples_out;
153 int64_t elapsed_time_ms = -1; 268 int64_t elapsed_time_ms;
154 int64_t ntp_time_ms = -1; 269 int64_t ntp_time_ms;
155 audio_callback_->NeedMorePlayData( 270 audio_callback_->NeedMorePlayData(
156 num_samples_per_frame_, 2, 1, sampling_frequency_in_hz_, 271 renderer_->SamplesPerFrame(), 2, 1, renderer_->SamplingFrequency(),
157 playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms); 272 playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms);
273 bool keep_rendering = renderer_->Render(
kwiberg-webrtc 2017/03/09 10:04:10 const?
oprypin_webrtc 2017/03/10 10:44:27 Done.
274 rtc::ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
275 if (!keep_rendering) {
276 StopPlayout();
277 }
158 } 278 }
159 } 279 }
160 tick_->Wait(WEBRTC_EVENT_INFINITE); 280 tick_->Wait(WEBRTC_EVENT_INFINITE);
161 } 281 }
162 282
163 283
164 } // namespace test 284 } // namespace test
165 } // namespace webrtc 285 } // namespace webrtc
OLDNEW
« webrtc/test/fake_audio_device.h ('K') | « webrtc/test/fake_audio_device.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698