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

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: Improved volume updating on Mac 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(volume >= 0 && volume <= 1.0);
scherkus (not reviewing) 2012/03/20 13:49:41 nit: if you split these DCHECKs into DCHECK_GE() a
henrika (OOO until Aug 14) 2012/03/21 10:16:04 Nice. Thanks.
188
189 if (state_ != kCreated && state_ != kRecording)
190 return;
191
192 // Only ask for the maximum volume at first call and use cached value
193 // for remaining function calls.
194 if (!max_volume_) {
195 max_volume_ = stream_->GetMaxVolume();
196 }
197
198 if (max_volume_ == 0.0) {
199 DLOG(WARNING) << "Failed to access input volume control";
200 return;
201 }
202
203 // Set the stream volume and scale to a range matched to the platform.
204 stream_->SetVolume(max_volume_ * volume);
205 }
206
207 void AudioInputController::DoSetAutomaticGainControl(bool enabled) {
208 DCHECK(message_loop_->BelongsToCurrentThread());
209
210 if (state_ != kCreated)
211 return;
212
213 stream_->SetAutomaticGainControl(enabled);
214 }
215
174 void AudioInputController::DoReportNoDataError() { 216 void AudioInputController::DoReportNoDataError() {
175 DCHECK(creator_loop_->BelongsToCurrentThread()); 217 DCHECK(creator_loop_->BelongsToCurrentThread());
176 218
177 // Error notifications should be sent on the audio-manager thread. 219 // Error notifications should be sent on the audio-manager thread.
178 int code = 0; 220 int code = 0;
179 message_loop_->PostTask(FROM_HERE, base::Bind( 221 message_loop_->PostTask(FROM_HERE, base::Bind(
180 &AudioInputController::DoReportError, this, code)); 222 &AudioInputController::DoReportError, this, code));
181 } 223 }
182 224
183 void AudioInputController::DoResetNoDataTimer() { 225 void AudioInputController::DoResetNoDataTimer() {
184 DCHECK(creator_loop_->BelongsToCurrentThread()); 226 DCHECK(creator_loop_->BelongsToCurrentThread());
185 no_data_timer_.Reset(); 227 no_data_timer_.Reset();
186 } 228 }
187 229
188 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, 230 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
189 uint32 size, uint32 hardware_delay_bytes) { 231 uint32 size, uint32 hardware_delay_bytes,
232 double volume) {
190 { 233 {
191 base::AutoLock auto_lock(lock_); 234 base::AutoLock auto_lock(lock_);
192 if (state_ != kRecording) 235 if (state_ != kRecording)
193 return; 236 return;
194 } 237 }
195 238
196 creator_loop_->PostTask(FROM_HERE, base::Bind( 239 creator_loop_->PostTask(FROM_HERE, base::Bind(
197 &AudioInputController::DoResetNoDataTimer, this)); 240 &AudioInputController::DoResetNoDataTimer, this));
198 241
199 // Use SyncSocket if we are in a low-latency mode. 242 // Use SyncSocket if we are in a low-latency mode.
200 if (LowLatencyMode()) { 243 if (LowLatencyMode()) {
201 sync_writer_->Write(data, size); 244 sync_writer_->Write(data, size, volume);
202 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 245 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
203 return; 246 return;
204 } 247 }
205 248
206 handler_->OnData(this, data, size); 249 handler_->OnData(this, data, size);
207 } 250 }
208 251
209 void AudioInputController::OnClose(AudioInputStream* stream) { 252 void AudioInputController::OnClose(AudioInputStream* stream) {
210 DVLOG(1) << "AudioInputController::OnClose()"; 253 DVLOG(1) << "AudioInputController::OnClose()";
211 // TODO(satish): Sometimes the device driver closes the input stream without 254 // TODO(satish): Sometimes the device driver closes the input stream without
(...skipping 17 matching lines...) Expand all
229 stream_->Close(); 272 stream_->Close();
230 stream_ = NULL; 273 stream_ = NULL;
231 } 274 }
232 275
233 // Should be last in the method, do not touch "this" from here on. 276 // Should be last in the method, do not touch "this" from here on.
234 if (done != NULL) 277 if (done != NULL)
235 done->Signal(); 278 done->Signal();
236 } 279 }
237 280
238 } // namespace media 281 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698