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

Side by Side Diff: media/audio/audio_input_controller.cc

Issue 9702019: Adds Analog Gain Control (AGC) to the WebRTC client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added audio_input_stream_impl.h/.cc Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/audio/audio_input_controller.h" 5 #include "media/audio/audio_input_controller.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/threading/thread_restrictions.h" 8 #include "base/threading/thread_restrictions.h"
9 #include "media/base/limits.h" 9 #include "media/base/limits.h"
10 10
(...skipping 10 matching lines...) Expand all
21 AudioInputController::AudioInputController(EventHandler* handler, 21 AudioInputController::AudioInputController(EventHandler* handler,
22 SyncWriter* sync_writer) 22 SyncWriter* sync_writer)
23 : creator_loop_(base::MessageLoopProxy::current()), 23 : creator_loop_(base::MessageLoopProxy::current()),
24 handler_(handler), 24 handler_(handler),
25 stream_(NULL), 25 stream_(NULL),
26 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE, 26 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE,
27 base::TimeDelta::FromSeconds(kTimerResetInterval), 27 base::TimeDelta::FromSeconds(kTimerResetInterval),
28 this, 28 this,
29 &AudioInputController::DoReportNoDataError)), 29 &AudioInputController::DoReportNoDataError)),
30 state_(kEmpty), 30 state_(kEmpty),
31 sync_writer_(sync_writer) { 31 sync_writer_(sync_writer),
32 max_volume_(0.0) {
32 DCHECK(creator_loop_); 33 DCHECK(creator_loop_);
33 } 34 }
34 35
35 AudioInputController::~AudioInputController() { 36 AudioInputController::~AudioInputController() {
36 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); 37 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
37 } 38 }
38 39
39 // static 40 // static
40 scoped_refptr<AudioInputController> AudioInputController::Create( 41 scoped_refptr<AudioInputController> AudioInputController::Create(
41 AudioManager* audio_manager, 42 AudioManager* audio_manager,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 message_loop_->PostTask(FROM_HERE, base::Bind( 101 message_loop_->PostTask(FROM_HERE, base::Bind(
101 &AudioInputController::DoRecord, this)); 102 &AudioInputController::DoRecord, this));
102 } 103 }
103 104
104 void AudioInputController::Close(const base::Closure& closed_task) { 105 void AudioInputController::Close(const base::Closure& closed_task) {
105 DCHECK(!closed_task.is_null()); 106 DCHECK(!closed_task.is_null());
106 message_loop_->PostTask(FROM_HERE, base::Bind( 107 message_loop_->PostTask(FROM_HERE, base::Bind(
107 &AudioInputController::DoClose, this, closed_task)); 108 &AudioInputController::DoClose, this, closed_task));
108 } 109 }
109 110
111 void AudioInputController::SetVolume(double volume) {
112 message_loop_->PostTask(FROM_HERE, base::Bind(
113 &AudioInputController::DoSetVolume, this, volume));
114 }
115
116 void AudioInputController::SetAutomaticGainControl(bool enabled) {
117 message_loop_->PostTask(FROM_HERE, base::Bind(
118 &AudioInputController::DoSetAutomaticGainControl, this, enabled));
119 }
120
110 void AudioInputController::DoCreate(AudioManager* audio_manager, 121 void AudioInputController::DoCreate(AudioManager* audio_manager,
111 const AudioParameters& params, 122 const AudioParameters& params,
112 const std::string& device_id) { 123 const std::string& device_id) {
113 DCHECK(message_loop_->BelongsToCurrentThread()); 124 DCHECK(message_loop_->BelongsToCurrentThread());
114 125
115 stream_ = audio_manager->MakeAudioInputStream(params, device_id); 126 stream_ = audio_manager->MakeAudioInputStream(params, device_id);
116 127
117 if (!stream_) { 128 if (!stream_) {
118 // TODO(satish): Define error types. 129 // TODO(satish): Define error types.
119 handler_->OnError(this, 0); 130 handler_->OnError(this, 0);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } 175 }
165 176
166 closed_task.Run(); 177 closed_task.Run();
167 } 178 }
168 179
169 void AudioInputController::DoReportError(int code) { 180 void AudioInputController::DoReportError(int code) {
170 DCHECK(message_loop_->BelongsToCurrentThread()); 181 DCHECK(message_loop_->BelongsToCurrentThread());
171 handler_->OnError(this, code); 182 handler_->OnError(this, code);
172 } 183 }
173 184
185 void AudioInputController::DoSetVolume(double volume) {
186 DCHECK(message_loop_->BelongsToCurrentThread());
187 DCHECK_GE(volume, 0);
188 DCHECK_LE(volume, 1.0);
189
190 if (state_ != kCreated && state_ != kRecording)
191 return;
192
193 // Only ask for the maximum volume at first call and use cached value
194 // for remaining function calls.
195 if (!max_volume_) {
196 max_volume_ = stream_->GetMaxVolume();
197 }
198
199 if (max_volume_ == 0.0) {
200 DLOG(WARNING) << "Failed to access input volume control";
201 return;
202 }
203
204 // Set the stream volume and scale to a range matched to the platform.
205 stream_->SetVolume(max_volume_ * volume);
206 }
207
208 void AudioInputController::DoSetAutomaticGainControl(bool enabled) {
209 DCHECK(message_loop_->BelongsToCurrentThread());
210 DCHECK_NE(state_, kRecording);
211
212 // Ensure that the AGC state only can be modified before streaming starts.
213 if (state_ != kCreated || state_ == kRecording)
214 return;
215
216 stream_->SetAutomaticGainControl(enabled);
217 }
218
174 void AudioInputController::DoReportNoDataError() { 219 void AudioInputController::DoReportNoDataError() {
175 DCHECK(creator_loop_->BelongsToCurrentThread()); 220 DCHECK(creator_loop_->BelongsToCurrentThread());
176 221
177 // Error notifications should be sent on the audio-manager thread. 222 // Error notifications should be sent on the audio-manager thread.
178 int code = 0; 223 int code = 0;
179 message_loop_->PostTask(FROM_HERE, base::Bind( 224 message_loop_->PostTask(FROM_HERE, base::Bind(
180 &AudioInputController::DoReportError, this, code)); 225 &AudioInputController::DoReportError, this, code));
181 } 226 }
182 227
183 void AudioInputController::DoResetNoDataTimer() { 228 void AudioInputController::DoResetNoDataTimer() {
184 DCHECK(creator_loop_->BelongsToCurrentThread()); 229 DCHECK(creator_loop_->BelongsToCurrentThread());
185 no_data_timer_.Reset(); 230 no_data_timer_.Reset();
186 } 231 }
187 232
188 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, 233 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
189 uint32 size, uint32 hardware_delay_bytes) { 234 uint32 size, uint32 hardware_delay_bytes,
235 double volume) {
190 { 236 {
191 base::AutoLock auto_lock(lock_); 237 base::AutoLock auto_lock(lock_);
192 if (state_ != kRecording) 238 if (state_ != kRecording)
193 return; 239 return;
194 } 240 }
195 241
196 creator_loop_->PostTask(FROM_HERE, base::Bind( 242 creator_loop_->PostTask(FROM_HERE, base::Bind(
197 &AudioInputController::DoResetNoDataTimer, this)); 243 &AudioInputController::DoResetNoDataTimer, this));
198 244
199 // Use SyncSocket if we are in a low-latency mode. 245 // Use SyncSocket if we are in a low-latency mode.
200 if (LowLatencyMode()) { 246 if (LowLatencyMode()) {
201 sync_writer_->Write(data, size); 247 sync_writer_->Write(data, size, volume);
202 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 248 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
203 return; 249 return;
204 } 250 }
205 251
206 handler_->OnData(this, data, size); 252 handler_->OnData(this, data, size);
207 } 253 }
208 254
209 void AudioInputController::OnClose(AudioInputStream* stream) { 255 void AudioInputController::OnClose(AudioInputStream* stream) {
210 DVLOG(1) << "AudioInputController::OnClose()"; 256 DVLOG(1) << "AudioInputController::OnClose()";
211 // TODO(satish): Sometimes the device driver closes the input stream without 257 // TODO(satish): Sometimes the device driver closes the input stream without
(...skipping 17 matching lines...) Expand all
229 stream_->Close(); 275 stream_->Close();
230 stream_ = NULL; 276 stream_ = NULL;
231 } 277 }
232 278
233 // Should be last in the method, do not touch "this" from here on. 279 // Should be last in the method, do not touch "this" from here on.
234 if (done != NULL) 280 if (done != NULL)
235 done->Signal(); 281 done->Signal();
236 } 282 }
237 283
238 } // namespace media 284 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698