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

Side by Side Diff: components/copresence/mediums/audio/audio_recorder_impl.cc

Issue 637223011: Redesign the copresence audio handlers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git/+/master
Patch Set: Created 6 years, 2 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 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/copresence/mediums/audio/audio_recorder.h" 5 #include "components/copresence/mediums/audio/audio_recorder_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/run_loop.h" 13 #include "base/run_loop.h"
14 #include "base/synchronization/waitable_event.h" 14 #include "base/synchronization/waitable_event.h"
15 #include "components/copresence/public/copresence_constants.h" 15 #include "components/copresence/public/copresence_constants.h"
(...skipping 15 matching lines...) Expand all
31 const int channels = source->channels(); 31 const int channels = source->channels();
32 for (int ch = 0; ch < channels; ++ch) { 32 for (int ch = 0; ch < channels; ++ch) {
33 for (int si = 0, di = ch; si < source->frames(); ++si, di += channels) 33 for (int si = 0, di = ch; si < source->frames(); ++si, di += channels)
34 buffer_view[di] = source->channel(ch)[si]; 34 buffer_view[di] = source->channel(ch)[si];
35 } 35 }
36 } 36 }
37 37
38 // Called every kProcessIntervalMs to process the recorded audio. This 38 // Called every kProcessIntervalMs to process the recorded audio. This
39 // converts our samples to the required sample rate, interleaves the samples 39 // converts our samples to the required sample rate, interleaves the samples
40 // and sends them to the whispernet decoder to process. 40 // and sends them to the whispernet decoder to process.
41 void ProcessSamples(scoped_ptr<media::AudioBus> bus, 41 void ProcessSamples(
42 const AudioRecorder::DecodeSamplesCallback& callback) { 42 scoped_ptr<media::AudioBus> bus,
43 const AudioRecorderImpl::RecordedSamplesCallback& callback) {
43 std::string samples; 44 std::string samples;
44 AudioBusToString(bus.Pass(), &samples); 45 AudioBusToString(bus.Pass(), &samples);
45 content::BrowserThread::PostTask( 46 content::BrowserThread::PostTask(
46 content::BrowserThread::UI, FROM_HERE, base::Bind(callback, samples)); 47 content::BrowserThread::UI, FROM_HERE, base::Bind(callback, samples));
47 } 48 }
48 49
49 } // namespace 50 } // namespace
50 51
51 // Public methods. 52 // Public methods.
52 53
53 AudioRecorder::AudioRecorder(const DecodeSamplesCallback& decode_callback) 54 AudioRecorderImpl::AudioRecorderImpl()
54 : is_recording_(false), 55 : is_recording_(false),
55 stream_(NULL), 56 stream_(NULL),
56 decode_callback_(decode_callback), 57 temp_conversion_buffer_(NULL),
57 total_buffer_frames_(0), 58 total_buffer_frames_(0),
58 buffer_frame_index_(0) { 59 buffer_frame_index_(0) {
59 } 60 }
60 61
61 void AudioRecorder::Initialize() { 62 void AudioRecorderImpl::Initialize(
63 const RecordedSamplesCallback& decode_callback) {
64 decode_callback_ = decode_callback;
62 media::AudioManager::Get()->GetTaskRunner()->PostTask( 65 media::AudioManager::Get()->GetTaskRunner()->PostTask(
63 FROM_HERE, 66 FROM_HERE,
64 base::Bind(&AudioRecorder::InitializeOnAudioThread, 67 base::Bind(&AudioRecorderImpl::InitializeOnAudioThread,
65 base::Unretained(this))); 68 base::Unretained(this)));
66 } 69 }
67 70
68 AudioRecorder::~AudioRecorder() { 71 AudioRecorderImpl::~AudioRecorderImpl() {
69 } 72 }
70 73
71 void AudioRecorder::Record() { 74 void AudioRecorderImpl::Record() {
72 media::AudioManager::Get()->GetTaskRunner()->PostTask( 75 media::AudioManager::Get()->GetTaskRunner()->PostTask(
73 FROM_HERE, 76 FROM_HERE,
74 base::Bind(&AudioRecorder::RecordOnAudioThread, base::Unretained(this))); 77 base::Bind(&AudioRecorderImpl::RecordOnAudioThread,
78 base::Unretained(this)));
75 } 79 }
76 80
77 void AudioRecorder::Stop() { 81 void AudioRecorderImpl::Stop() {
78 media::AudioManager::Get()->GetTaskRunner()->PostTask( 82 media::AudioManager::Get()->GetTaskRunner()->PostTask(
79 FROM_HERE, 83 FROM_HERE,
80 base::Bind(&AudioRecorder::StopOnAudioThread, base::Unretained(this))); 84 base::Bind(&AudioRecorderImpl::StopOnAudioThread,
85 base::Unretained(this)));
81 } 86 }
82 87
83 bool AudioRecorder::IsRecording() { 88 bool AudioRecorderImpl::IsRecording() {
84 return is_recording_; 89 return is_recording_;
85 } 90 }
86 91
87 void AudioRecorder::Finalize() { 92 void AudioRecorderImpl::Finalize() {
88 media::AudioManager::Get()->GetTaskRunner()->PostTask( 93 media::AudioManager::Get()->GetTaskRunner()->PostTask(
89 FROM_HERE, 94 FROM_HERE,
90 base::Bind(&AudioRecorder::FinalizeOnAudioThread, 95 base::Bind(&AudioRecorderImpl::FinalizeOnAudioThread,
91 base::Unretained(this))); 96 base::Unretained(this)));
92 } 97 }
93 98
94 // Private methods. 99 // Private methods.
95 100
96 void AudioRecorder::InitializeOnAudioThread() { 101 void AudioRecorderImpl::InitializeOnAudioThread() {
97 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 102 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
98 103
99 media::AudioParameters params = 104 media::AudioParameters params =
100 params_for_testing_ 105 params_for_testing_
101 ? *params_for_testing_ 106 ? *params_for_testing_
102 : media::AudioManager::Get()->GetInputStreamParameters( 107 : media::AudioManager::Get()->GetInputStreamParameters(
103 media::AudioManagerBase::kDefaultDeviceId); 108 media::AudioManagerBase::kDefaultDeviceId);
104 109
105 const media::AudioParameters dest_params(params.format(), 110 const media::AudioParameters dest_params(params.format(),
106 kDefaultChannelLayout, 111 kDefaultChannelLayout,
(...skipping 20 matching lines...) Expand all
127 LOG(ERROR) << "Failed to open an input stream."; 132 LOG(ERROR) << "Failed to open an input stream.";
128 if (stream_) { 133 if (stream_) {
129 stream_->Close(); 134 stream_->Close();
130 stream_ = NULL; 135 stream_ = NULL;
131 } 136 }
132 return; 137 return;
133 } 138 }
134 stream_->SetVolume(stream_->GetMaxVolume()); 139 stream_->SetVolume(stream_->GetMaxVolume());
135 } 140 }
136 141
137 void AudioRecorder::RecordOnAudioThread() { 142 void AudioRecorderImpl::RecordOnAudioThread() {
138 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 143 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
139 if (!stream_ || is_recording_) 144 if (!stream_ || is_recording_)
140 return; 145 return;
141 146
142 converter_->Reset(); 147 converter_->Reset();
143 stream_->Start(this); 148 stream_->Start(this);
144 is_recording_ = true; 149 is_recording_ = true;
145 } 150 }
146 151
147 void AudioRecorder::StopOnAudioThread() { 152 void AudioRecorderImpl::StopOnAudioThread() {
148 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 153 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
149 if (!stream_ || !is_recording_) 154 if (!stream_ || !is_recording_)
150 return; 155 return;
151 156
152 stream_->Stop(); 157 stream_->Stop();
153 is_recording_ = false; 158 is_recording_ = false;
154 } 159 }
155 160
156 void AudioRecorder::StopAndCloseOnAudioThread() { 161 void AudioRecorderImpl::StopAndCloseOnAudioThread() {
157 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 162 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
158 if (!stream_) 163 if (!stream_)
159 return; 164 return;
160 165
161 StopOnAudioThread(); 166 StopOnAudioThread();
162 stream_->Close(); 167 stream_->Close();
163 stream_ = NULL; 168 stream_ = NULL;
164 } 169 }
165 170
166 void AudioRecorder::FinalizeOnAudioThread() { 171 void AudioRecorderImpl::FinalizeOnAudioThread() {
167 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 172 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
168 StopAndCloseOnAudioThread(); 173 StopAndCloseOnAudioThread();
169 delete this; 174 delete this;
170 } 175 }
171 176
172 void AudioRecorder::OnData(media::AudioInputStream* stream, 177 void AudioRecorderImpl::OnData(media::AudioInputStream* stream,
173 const media::AudioBus* source, 178 const media::AudioBus* source,
174 uint32 /* hardware_delay_bytes */, 179 uint32 /* hardware_delay_bytes */,
175 double /* volume */) { 180 double /* volume */) {
176 temp_conversion_buffer_ = source; 181 temp_conversion_buffer_ = source;
177 while (temp_conversion_buffer_) { 182 while (temp_conversion_buffer_) {
178 // source->frames() == source_params.frames_per_buffer(), so we only have 183 // source->frames() == source_params.frames_per_buffer(), so we only have
179 // one chunk of data in the source; correspondingly set the destination 184 // one chunk of data in the source; correspondingly set the destination
180 // size to one chunk. 185 // size to one chunk.
181 // TODO(rkc): Optimize this to directly write into buffer_ so we can avoid 186 // TODO(rkc): Optimize this to directly write into buffer_ so we can avoid
182 // the copy into this buffer and then the copy back into buffer_. 187 // the copy into this buffer and then the copy back into buffer_.
183 scoped_ptr<media::AudioBus> converted_source = 188 scoped_ptr<media::AudioBus> converted_source =
184 media::AudioBus::Create(kDefaultChannels, converter_->ChunkSize()); 189 media::AudioBus::Create(kDefaultChannels, converter_->ChunkSize());
185 190
(...skipping 23 matching lines...) Expand all
209 int remaining_source_frames = converted_source->frames() - frames_to_copy; 214 int remaining_source_frames = converted_source->frames() - frames_to_copy;
210 converted_source->CopyPartialFramesTo(frames_to_copy, 215 converted_source->CopyPartialFramesTo(frames_to_copy,
211 remaining_source_frames, 216 remaining_source_frames,
212 buffer_frame_index_, 217 buffer_frame_index_,
213 buffer_.get()); 218 buffer_.get());
214 buffer_frame_index_ += remaining_source_frames; 219 buffer_frame_index_ += remaining_source_frames;
215 } 220 }
216 } 221 }
217 } 222 }
218 223
219 void AudioRecorder::OnError(media::AudioInputStream* /* stream */) { 224 void AudioRecorderImpl::OnError(media::AudioInputStream* /* stream */) {
220 LOG(ERROR) << "Error during sound recording."; 225 LOG(ERROR) << "Error during sound recording.";
221 media::AudioManager::Get()->GetTaskRunner()->PostTask( 226 media::AudioManager::Get()->GetTaskRunner()->PostTask(
222 FROM_HERE, 227 FROM_HERE,
223 base::Bind(&AudioRecorder::StopAndCloseOnAudioThread, 228 base::Bind(&AudioRecorderImpl::StopAndCloseOnAudioThread,
224 base::Unretained(this))); 229 base::Unretained(this)));
225 } 230 }
226 231
227 double AudioRecorder::ProvideInput(media::AudioBus* dest, 232 double AudioRecorderImpl::ProvideInput(media::AudioBus* dest,
228 base::TimeDelta /* buffer_delay */) { 233 base::TimeDelta /* buffer_delay */) {
229 DCHECK(temp_conversion_buffer_); 234 DCHECK(temp_conversion_buffer_);
230 DCHECK_LE(temp_conversion_buffer_->frames(), dest->frames()); 235 DCHECK_LE(temp_conversion_buffer_->frames(), dest->frames());
231 temp_conversion_buffer_->CopyTo(dest); 236 temp_conversion_buffer_->CopyTo(dest);
232 temp_conversion_buffer_ = NULL; 237 temp_conversion_buffer_ = NULL;
233 return 1.0; 238 return 1.0;
234 } 239 }
235 240
236 void AudioRecorder::FlushAudioLoopForTesting() { 241 void AudioRecorderImpl::FlushAudioLoopForTesting() {
237 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()) 242 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread())
238 return; 243 return;
239 244
240 // Queue task on the audio thread, when it is executed, that means we've 245 // Queue task on the audio thread, when it is executed, that means we've
241 // successfully executed all the tasks before us. 246 // successfully executed all the tasks before us.
242 base::RunLoop rl; 247 base::RunLoop rl;
243 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply( 248 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply(
244 FROM_HERE, 249 FROM_HERE,
245 base::Bind(base::IgnoreResult(&AudioRecorder::FlushAudioLoopForTesting), 250 base::Bind(
246 base::Unretained(this)), 251 base::IgnoreResult(&AudioRecorderImpl::FlushAudioLoopForTesting),
252 base::Unretained(this)),
247 rl.QuitClosure()); 253 rl.QuitClosure());
248 rl.Run(); 254 rl.Run();
249 } 255 }
250 256
251 } // namespace copresence 257 } // namespace copresence
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698