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

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

Issue 2652803002: Refactor FakeAudioDevice to have separate methods for starting recording and playout. (Closed)
Patch Set: Addressed review comments. Created 3 years, 10 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 14
15 #include "webrtc/base/platform_thread.h" 15 #include "webrtc/base/array_view.h"
16 #include "webrtc/modules/media_file/media_file_utility.h" 16 #include "webrtc/base/random.h"
17 #include "webrtc/system_wrappers/include/clock.h" 17 #include "webrtc/system_wrappers/include/clock.h"
18 #include "webrtc/system_wrappers/include/event_wrapper.h" 18 #include "webrtc/system_wrappers/include/event_wrapper.h"
19 #include "webrtc/system_wrappers/include/file_wrapper.h"
20 #include "webrtc/test/gtest.h"
21 19
22 namespace webrtc { 20 namespace webrtc {
peah-webrtc 2017/01/26 13:20:11 If you here add namespace { constexpr size_t kFra
perkj_webrtc 2017/01/29 13:25:19 ok, but will use int https://google.github.io/styl
23 namespace test { 21 namespace test {
24 22
23 class FakeAudioDevice::PulsedNoiseCapturer {
24 public:
25 PulsedNoiseCapturer(size_t num_samples, int16_t max_amplitude)
26 : fill_with_zero_(false),
27 random_generator_(1),
28 max_amplitude_(max_amplitude),
29 random_audio_(num_samples),
30 null_audio_(num_samples, 0) {
31 RTC_DCHECK_GT(max_amplitude, 0);
32 }
33
34 rtc::ArrayView<const int16_t> Capture() {
35 fill_with_zero_ = !fill_with_zero_;
36 if (!fill_with_zero_) {
37 std::generate(random_audio_.begin(), random_audio_.end(), [&]() {
38 return random_generator_.Rand(-max_amplitude_, max_amplitude_);
39 });
40 }
41 return fill_with_zero_ ? null_audio_ : random_audio_;
42 }
43
44 private:
45 bool fill_with_zero_;
46 webrtc::Random random_generator_;
47 const int16_t max_amplitude_;
48 std::vector<int16_t> random_audio_;
49 std::vector<int16_t> null_audio_;
peah-webrtc 2017/01/26 13:20:11 You probably should rename this to silent_audio_,
perkj_webrtc 2017/01/29 13:25:19 Done.
50 };
51
25 FakeAudioDevice::FakeAudioDevice(Clock* clock, 52 FakeAudioDevice::FakeAudioDevice(Clock* clock,
26 const std::string& filename, 53 float speed,
27 float speed) 54 int sampling_frequency_in_hz)
28 : audio_callback_(NULL), 55 : sampling_frequency_in_hz_(sampling_frequency_in_hz),
29 capturing_(false), 56 audio_callback_(NULL),
30 captured_audio_(), 57 rendering_(false),
31 playout_buffer_(), 58 // Assuming 10ms audio packets.
peah-webrtc 2017/01/26 13:20:11 This should be documented in the header file as it
perkj_webrtc 2017/01/29 13:25:20 Done.
59 playout_buffer_(sampling_frequency_in_hz_ / 100, 0),
peah-webrtc 2017/01/26 13:20:11 playout_buffer_(rtc::CheckedDivExact(sampling_freq
perkj_webrtc 2017/01/29 13:25:20 Done.
32 speed_(speed), 60 speed_(speed),
33 last_playout_ms_(-1), 61 last_playout_ms_(-1),
34 clock_(clock, speed), 62 clock_(clock, speed),
35 tick_(EventTimerWrapper::Create()), 63 tick_(EventTimerWrapper::Create()),
36 thread_(FakeAudioDevice::Run, this, "FakeAudioDevice"), 64 thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") {}
peah-webrtc 2017/01/26 13:20:11 Please add RTC_DCHECK(clock); (because clock sho
perkj_webrtc 2017/01/29 13:25:19 now only used by the drifting clock and that check
37 file_utility_(new ModuleFileUtility(0)),
38 input_stream_(FileWrapper::Create()) {
39 memset(captured_audio_, 0, sizeof(captured_audio_));
40 memset(playout_buffer_, 0, sizeof(playout_buffer_));
41 // Open audio input file as read-only and looping.
42 EXPECT_TRUE(input_stream_->OpenFile(filename.c_str(), true)) << filename;
43 }
44 65
45 FakeAudioDevice::~FakeAudioDevice() { 66 FakeAudioDevice::~FakeAudioDevice() {
46 Stop(); 67 StopPlayout();
47 68 StopRecording();
48 thread_.Stop(); 69 thread_.Stop();
49 } 70 }
50 71
72 int32_t FakeAudioDevice::StartPlayout() {
73 rtc::CritScope cs(&lock_);
74 rendering_ = true;
75 return 0;
76 }
77
78 int32_t FakeAudioDevice::StopPlayout() {
79 rtc::CritScope cs(&lock_);
80 rendering_ = false;
81 return 0;
82 }
83
84 void FakeAudioDevice::StartRecordingPulsedNoise(int16_t max_amplitude) {
85 rtc::CritScope cs(&lock_);
86 // Assuming 10ms audio packets.
87 capturer_.reset(new FakeAudioDevice::PulsedNoiseCapturer(
88 sampling_frequency_in_hz_ / 100, max_amplitude));
peah-webrtc 2017/01/26 13:20:11 rtc::CheckedDivExact(sampling_frequency_in_hz_, kF
perkj_webrtc 2017/01/29 13:25:20 Done.
89 }
90
91 int32_t FakeAudioDevice::StopRecording() {
92 rtc::CritScope cs(&lock_);
93 capturer_.reset();
94 return 0;
95 }
96
51 int32_t FakeAudioDevice::Init() { 97 int32_t FakeAudioDevice::Init() {
52 rtc::CritScope cs(&lock_); 98 RTC_CHECK(tick_->StartTimer(true, 10 / speed_));
peah-webrtc 2017/01/26 13:20:11 RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs /
perkj_webrtc 2017/01/29 13:25:19 Done.
53 if (file_utility_->InitPCMReading(*input_stream_.get()) != 0)
54 return -1;
55
56 if (!tick_->StartTimer(true, 10 / speed_))
57 return -1;
58 thread_.Start(); 99 thread_.Start();
59 thread_.SetPriority(rtc::kHighPriority); 100 thread_.SetPriority(rtc::kHighPriority);
60 return 0; 101 return 0;
61 } 102 }
62 103
63 int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) { 104 int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) {
peah-webrtc 2017/01/26 13:20:11 Is a callback allowed to be null? If it is not, pl
perkj_webrtc 2017/01/29 13:25:19 seems like its called with null to reconfigure. a
64 rtc::CritScope cs(&lock_); 105 rtc::CritScope cs(&lock_);
65 audio_callback_ = callback; 106 audio_callback_ = callback;
66 return 0; 107 return 0;
67 } 108 }
68 109
69 bool FakeAudioDevice::Playing() const { 110 bool FakeAudioDevice::Playing() const {
70 rtc::CritScope cs(&lock_); 111 rtc::CritScope cs(&lock_);
71 return capturing_; 112 return rendering_;
72 } 113 }
73 114
74 int32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const { 115 int32_t FakeAudioDevice::PlayoutDelay(uint16_t* delay_ms) const {
75 *delay_ms = 0; 116 *delay_ms = 0;
peah-webrtc 2017/01/26 13:20:11 Please add RTC_DCHECK(delay_ms);
perkj_webrtc 2017/01/29 13:25:19 A chrome reviewer would say no since it will gener
peah-webrtc 2017/01/30 06:45:08 That is interesting. Can one always rely on this c
76 return 0; 117 return 0;
77 } 118 }
78 119
79 bool FakeAudioDevice::Recording() const { 120 bool FakeAudioDevice::Recording() const {
80 rtc::CritScope cs(&lock_); 121 rtc::CritScope cs(&lock_);
81 return capturing_; 122 return !!capturer_;
82 } 123 }
83 124
84 bool FakeAudioDevice::Run(void* obj) { 125 bool FakeAudioDevice::Run(void* obj) {
85 static_cast<FakeAudioDevice*>(obj)->CaptureAudio(); 126 static_cast<FakeAudioDevice*>(obj)->ProcessAudio();
86 return true; 127 return true;
87 } 128 }
88 129
89 void FakeAudioDevice::CaptureAudio() { 130 void FakeAudioDevice::ProcessAudio() {
90 { 131 {
91 rtc::CritScope cs(&lock_); 132 rtc::CritScope cs(&lock_);
92 if (capturing_) { 133 if (capturer_) {
93 int bytes_read = file_utility_->ReadPCMData( 134 // Capture 10ms of audio. 2 bytes per sample.
94 *input_stream_.get(), captured_audio_, kBufferSizeBytes); 135 rtc::ArrayView<const int16_t> audio_data = capturer_->Capture();
95 if (bytes_read <= 0)
96 return;
97 // 2 bytes per sample.
98 size_t num_samples = static_cast<size_t>(bytes_read / 2);
99 uint32_t new_mic_level; 136 uint32_t new_mic_level;
peah-webrtc 2017/01/26 13:25:18 Please initialize new_mic_level.
perkj_webrtc 2017/01/29 13:25:20 Done.
100 EXPECT_EQ(0, 137 RTC_CHECK_EQ(
101 audio_callback_->RecordedDataIsAvailable(captured_audio_, 138 0, audio_callback_->RecordedDataIsAvailable(
102 num_samples, 139 audio_data.data(), audio_data.size(), 2, 1,
103 2, 140 sampling_frequency_in_hz_, 0, 0, 0, false, new_mic_level));
104 1, 141 }
105 kFrequencyHz, 142 if (rendering_) {
106 0, 143 // Assuming 10ms audio packet size.
107 0, 144 size_t samples_needed = sampling_frequency_in_hz_ / 100;
peah-webrtc 2017/01/26 13:20:12 With the code construct below, you can skip the co
perkj_webrtc 2017/01/29 13:25:20 I removed all this weird stuff since the clock has
108 0,
109 false,
110 new_mic_level));
111 size_t samples_needed = kFrequencyHz / 100;
112 int64_t now_ms = clock_.TimeInMilliseconds(); 145 int64_t now_ms = clock_.TimeInMilliseconds();
113 uint32_t time_since_last_playout_ms = now_ms - last_playout_ms_; 146 uint32_t time_since_last_playout_ms = now_ms - last_playout_ms_;
peah-webrtc 2017/01/26 13:20:12 I don't see you ever updating last_playout_ms_. Ho
perkj_webrtc 2017/01/29 13:25:19 Acknowledged.
114 if (last_playout_ms_ > 0 && time_since_last_playout_ms > 0) { 147 if (last_playout_ms_ > 0 && time_since_last_playout_ms > 0) {
peah-webrtc 2017/01/26 13:20:11 It would actually be fine to initialize last_play
perkj_webrtc 2017/01/29 13:25:20 Acknowledged.
115 samples_needed = std::min( 148 samples_needed =
116 static_cast<size_t>(kFrequencyHz / time_since_last_playout_ms), 149 std::min(static_cast<size_t>(sampling_frequency_in_hz_ /
peah-webrtc 2017/01/26 13:20:11 If you change sampling_frequency_in_hz_ to be size
perkj_webrtc 2017/01/29 13:25:19 NeedMorePlayData actually use size_t but style gui
peah-webrtc 2017/01/30 06:45:08 I think the style guide leaves some room for inter
117 kBufferSizeBytes / 2); 150 time_since_last_playout_ms),
151 playout_buffer_.size());
118 } 152 }
119 size_t samples_out = 0; 153 size_t samples_out = 0;
120 int64_t elapsed_time_ms = -1; 154 int64_t elapsed_time_ms = -1;
121 int64_t ntp_time_ms = -1; 155 int64_t ntp_time_ms = -1;
122 EXPECT_EQ(0, 156 RTC_CHECK_EQ(0, audio_callback_->NeedMorePlayData(
123 audio_callback_->NeedMorePlayData(samples_needed, 157 samples_needed, 2, 1, sampling_frequency_in_hz_,
124 2, 158 playout_buffer_.data(), samples_out, &elapsed_time_ms,
125 1, 159 &ntp_time_ms));
126 kFrequencyHz,
127 playout_buffer_,
128 samples_out,
129 &elapsed_time_ms,
130 &ntp_time_ms));
131 } 160 }
132 } 161 }
133 tick_->Wait(WEBRTC_EVENT_INFINITE); 162 tick_->Wait(WEBRTC_EVENT_INFINITE);
134 } 163 }
135 164
136 void FakeAudioDevice::Start() {
137 rtc::CritScope cs(&lock_);
138 capturing_ = true;
139 }
140 165
141 void FakeAudioDevice::Stop() {
142 rtc::CritScope cs(&lock_);
143 capturing_ = false;
144 }
145 } // namespace test 166 } // namespace test
146 } // namespace webrtc 167 } // 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