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

Side by Side Diff: components/audio_modem/audio_recorder_impl.cc

Issue 940123004: Convert audio samples in Whispernet. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: test fix. Created 5 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 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/audio_modem/audio_recorder_impl.h" 5 #include "components/audio_modem/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"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 content::BrowserThread::UI, FROM_HERE, base::Bind(callback, samples)); 47 content::BrowserThread::UI, FROM_HERE, base::Bind(callback, samples));
48 } 48 }
49 49
50 } // namespace 50 } // namespace
51 51
52 // Public methods. 52 // Public methods.
53 53
54 AudioRecorderImpl::AudioRecorderImpl() 54 AudioRecorderImpl::AudioRecorderImpl()
55 : is_recording_(false), 55 : is_recording_(false),
56 stream_(nullptr), 56 stream_(nullptr),
57 temp_conversion_buffer_(nullptr),
58 total_buffer_frames_(0), 57 total_buffer_frames_(0),
59 buffer_frame_index_(0) { 58 buffer_frame_index_(0) {
60 } 59 }
61 60
62 void AudioRecorderImpl::Initialize( 61 void AudioRecorderImpl::Initialize(
63 const RecordedSamplesCallback& decode_callback) { 62 const RecordedSamplesCallback& decode_callback) {
64 decode_callback_ = decode_callback; 63 decode_callback_ = decode_callback;
65 media::AudioManager::Get()->GetTaskRunner()->PostTask( 64 media::AudioManager::Get()->GetTaskRunner()->PostTask(
66 FROM_HERE, 65 FROM_HERE,
67 base::Bind(&AudioRecorderImpl::InitializeOnAudioThread, 66 base::Bind(&AudioRecorderImpl::InitializeOnAudioThread,
(...skipping 28 matching lines...) Expand all
96 95
97 void AudioRecorderImpl::InitializeOnAudioThread() { 96 void AudioRecorderImpl::InitializeOnAudioThread() {
98 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 97 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
99 98
100 media::AudioParameters params = 99 media::AudioParameters params =
101 params_for_testing_ 100 params_for_testing_
102 ? *params_for_testing_ 101 ? *params_for_testing_
103 : media::AudioManager::Get()->GetInputStreamParameters( 102 : media::AudioManager::Get()->GetInputStreamParameters(
104 media::AudioManagerBase::kDefaultDeviceId); 103 media::AudioManagerBase::kDefaultDeviceId);
105 104
106 const media::AudioParameters dest_params(params.format(), 105 total_buffer_frames_ = kProcessIntervalMs * params.sample_rate() / 1000;
107 kDefaultChannelLayout, 106 buffer_ = media::AudioBus::Create(params.channels(), total_buffer_frames_);
108 kDefaultSampleRate,
109 kDefaultBitsPerSample,
110 params.frames_per_buffer(),
111 media::AudioParameters::NO_EFFECTS);
112
113 converter_.reset(new media::AudioConverter(
114 params, dest_params, params.sample_rate() == dest_params.sample_rate()));
115 converter_->AddInput(this);
116
117 total_buffer_frames_ = kProcessIntervalMs * dest_params.sample_rate() / 1000;
118 buffer_ =
119 media::AudioBus::Create(dest_params.channels(), total_buffer_frames_);
120 buffer_frame_index_ = 0; 107 buffer_frame_index_ = 0;
121 108
122 stream_ = input_stream_for_testing_ 109 stream_ = input_stream_for_testing_
123 ? input_stream_for_testing_.get() 110 ? input_stream_for_testing_.get()
124 : media::AudioManager::Get()->MakeAudioInputStream( 111 : media::AudioManager::Get()->MakeAudioInputStream(
125 params, media::AudioManagerBase::kDefaultDeviceId); 112 params, media::AudioManagerBase::kDefaultDeviceId);
126 113
127 if (!stream_ || !stream_->Open()) { 114 if (!stream_ || !stream_->Open()) {
128 LOG(ERROR) << "Failed to open an input stream."; 115 LOG(ERROR) << "Failed to open an input stream.";
129 if (stream_) { 116 if (stream_) {
130 stream_->Close(); 117 stream_->Close();
131 stream_ = nullptr; 118 stream_ = nullptr;
132 } 119 }
133 return; 120 return;
134 } 121 }
135 stream_->SetVolume(stream_->GetMaxVolume()); 122 stream_->SetVolume(stream_->GetMaxVolume());
136 } 123 }
137 124
138 void AudioRecorderImpl::RecordOnAudioThread() { 125 void AudioRecorderImpl::RecordOnAudioThread() {
139 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 126 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
140 if (!stream_ || is_recording_) 127 if (!stream_ || is_recording_)
141 return; 128 return;
142 129
143 VLOG(3) << "Starting recording."; 130 VLOG(3) << "Starting recording.";
144 converter_->Reset();
145 stream_->Start(this); 131 stream_->Start(this);
146 is_recording_ = true; 132 is_recording_ = true;
147 } 133 }
148 134
149 void AudioRecorderImpl::StopOnAudioThread() { 135 void AudioRecorderImpl::StopOnAudioThread() {
150 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 136 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
151 if (!stream_ || !is_recording_) 137 if (!stream_ || !is_recording_)
152 return; 138 return;
153 139
154 VLOG(3) << "Stopping recording."; 140 VLOG(3) << "Stopping recording.";
(...skipping 14 matching lines...) Expand all
169 void AudioRecorderImpl::FinalizeOnAudioThread() { 155 void AudioRecorderImpl::FinalizeOnAudioThread() {
170 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 156 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
171 StopAndCloseOnAudioThread(); 157 StopAndCloseOnAudioThread();
172 delete this; 158 delete this;
173 } 159 }
174 160
175 void AudioRecorderImpl::OnData(media::AudioInputStream* stream, 161 void AudioRecorderImpl::OnData(media::AudioInputStream* stream,
176 const media::AudioBus* source, 162 const media::AudioBus* source,
177 uint32 /* hardware_delay_bytes */, 163 uint32 /* hardware_delay_bytes */,
178 double /* volume */) { 164 double /* volume */) {
179 temp_conversion_buffer_ = source; 165 // source->frames() == source_params.frames_per_buffer(), so we only have
180 while (temp_conversion_buffer_) { 166 // one chunk of data in the source; correspondingly set the destination
181 // source->frames() == source_params.frames_per_buffer(), so we only have 167 // size to one chunk.
182 // one chunk of data in the source; correspondingly set the destination
183 // size to one chunk.
184 // TODO(rkc): Optimize this to directly write into buffer_ so we can avoid
185 // the copy into this buffer and then the copy back into buffer_.
186 scoped_ptr<media::AudioBus> converted_source =
187 media::AudioBus::Create(kDefaultChannels, converter_->ChunkSize());
188 168
189 // Convert accumulated samples into converted_source. Note: One call may not 169 int remaining_buffer_frames = buffer_->frames() - buffer_frame_index_;
190 // be enough to consume the samples from |source|. The converter may have 170 int frames_to_copy = std::min(remaining_buffer_frames, source->frames());
191 // accumulated samples over time due to a fractional input:output sample 171 source->CopyPartialFramesTo(0, frames_to_copy, buffer_frame_index_,
192 // rate ratio. Since |source| is ephemeral, Convert() must be called until 172 buffer_.get());
193 // |source| is at least buffered into the converter. Once |source| is 173 buffer_frame_index_ += frames_to_copy;
194 // consumed during ProvideInput(), |temp_conversion_buffer_| will be set to
195 // NULL, which will break the conversion loop.
196 converter_->Convert(converted_source.get());
197 174
198 int remaining_buffer_frames = buffer_->frames() - buffer_frame_index_; 175 // Buffer full, send it for processing.
199 int frames_to_copy = 176 if (buffer_->frames() == buffer_frame_index_) {
200 std::min(remaining_buffer_frames, converted_source->frames()); 177 ProcessSamples(buffer_.Pass(), decode_callback_);
201 converted_source->CopyPartialFramesTo( 178 buffer_ = media::AudioBus::Create(kDefaultChannels, total_buffer_frames_);
202 0, frames_to_copy, buffer_frame_index_, buffer_.get()); 179 buffer_frame_index_ = 0;
203 buffer_frame_index_ += frames_to_copy;
204 180
205 // Buffer full, send it for processing. 181 // Copy any remaining frames in the source to our buffer.
206 if (buffer_->frames() == buffer_frame_index_) { 182 int remaining_source_frames = source->frames() - frames_to_copy;
207 ProcessSamples(buffer_.Pass(), decode_callback_); 183 source->CopyPartialFramesTo(frames_to_copy, remaining_source_frames,
208 buffer_ = media::AudioBus::Create(kDefaultChannels, total_buffer_frames_); 184 buffer_frame_index_, buffer_.get());
209 buffer_frame_index_ = 0; 185 buffer_frame_index_ += remaining_source_frames;
210
211 // Copy any remaining frames in the source to our buffer.
212 int remaining_source_frames = converted_source->frames() - frames_to_copy;
213 converted_source->CopyPartialFramesTo(frames_to_copy,
214 remaining_source_frames,
215 buffer_frame_index_,
216 buffer_.get());
217 buffer_frame_index_ += remaining_source_frames;
218 }
219 } 186 }
220 } 187 }
221 188
222 void AudioRecorderImpl::OnError(media::AudioInputStream* /* stream */) { 189 void AudioRecorderImpl::OnError(media::AudioInputStream* /* stream */) {
223 LOG(ERROR) << "Error during sound recording."; 190 LOG(ERROR) << "Error during sound recording.";
224 media::AudioManager::Get()->GetTaskRunner()->PostTask( 191 media::AudioManager::Get()->GetTaskRunner()->PostTask(
225 FROM_HERE, 192 FROM_HERE,
226 base::Bind(&AudioRecorderImpl::StopAndCloseOnAudioThread, 193 base::Bind(&AudioRecorderImpl::StopAndCloseOnAudioThread,
227 base::Unretained(this))); 194 base::Unretained(this)));
228 } 195 }
229 196
230 double AudioRecorderImpl::ProvideInput(media::AudioBus* dest,
231 base::TimeDelta /* buffer_delay */) {
232 DCHECK(temp_conversion_buffer_);
233 DCHECK_LE(temp_conversion_buffer_->frames(), dest->frames());
234 temp_conversion_buffer_->CopyTo(dest);
235 temp_conversion_buffer_ = nullptr;
236 return 1.0;
237 }
238
239 void AudioRecorderImpl::FlushAudioLoopForTesting() { 197 void AudioRecorderImpl::FlushAudioLoopForTesting() {
240 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()) 198 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread())
241 return; 199 return;
242 200
243 // Queue task on the audio thread, when it is executed, that means we've 201 // Queue task on the audio thread, when it is executed, that means we've
244 // successfully executed all the tasks before us. 202 // successfully executed all the tasks before us.
245 base::RunLoop rl; 203 base::RunLoop rl;
246 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply( 204 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply(
247 FROM_HERE, 205 FROM_HERE,
248 base::Bind( 206 base::Bind(
249 base::IgnoreResult(&AudioRecorderImpl::FlushAudioLoopForTesting), 207 base::IgnoreResult(&AudioRecorderImpl::FlushAudioLoopForTesting),
250 base::Unretained(this)), 208 base::Unretained(this)),
251 rl.QuitClosure()); 209 rl.QuitClosure());
252 rl.Run(); 210 rl.Run();
253 } 211 }
254 212
255 } // namespace audio_modem 213 } // namespace audio_modem
OLDNEW
« no previous file with comments | « components/audio_modem/audio_recorder_impl.h ('k') | components/audio_modem/audio_recorder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698