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

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 AGC comments 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_->PostTaskAndReply( 107 message_loop_->PostTaskAndReply(
107 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); 108 FROM_HERE, base::Bind(&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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 173
163 state_ = kClosed; 174 state_ = kClosed;
164 } 175 }
165 } 176 }
166 177
167 void AudioInputController::DoReportError(int code) { 178 void AudioInputController::DoReportError(int code) {
168 DCHECK(message_loop_->BelongsToCurrentThread()); 179 DCHECK(message_loop_->BelongsToCurrentThread());
169 handler_->OnError(this, code); 180 handler_->OnError(this, code);
170 } 181 }
171 182
183 void AudioInputController::DoSetVolume(double volume) {
184 DCHECK(message_loop_->BelongsToCurrentThread());
185 DCHECK_GE(volume, 0);
186 DCHECK_LE(volume, 1.0);
187
188 if (state_ != kCreated && state_ != kRecording)
189 return;
190
191 // Only ask for the maximum volume at first call and use cached value
192 // for remaining function calls.
193 if (!max_volume_) {
194 max_volume_ = stream_->GetMaxVolume();
195 }
196
197 if (max_volume_ == 0.0) {
198 DLOG(WARNING) << "Failed to access input volume control";
199 return;
200 }
201
202 // Set the stream volume and scale to a range matched to the platform.
203 stream_->SetVolume(max_volume_ * volume);
204 }
205
206 void AudioInputController::DoSetAutomaticGainControl(bool enabled) {
207 DCHECK(message_loop_->BelongsToCurrentThread());
208 DCHECK_NE(state_, kRecording);
209
210 // Ensure that the AGC state only can be modified before streaming starts.
211 if (state_ != kCreated || state_ == kRecording)
212 return;
213
214 stream_->SetAutomaticGainControl(enabled);
215 }
216
172 void AudioInputController::DoReportNoDataError() { 217 void AudioInputController::DoReportNoDataError() {
173 DCHECK(creator_loop_->BelongsToCurrentThread()); 218 DCHECK(creator_loop_->BelongsToCurrentThread());
174 219
175 // Error notifications should be sent on the audio-manager thread. 220 // Error notifications should be sent on the audio-manager thread.
176 int code = 0; 221 int code = 0;
177 message_loop_->PostTask(FROM_HERE, base::Bind( 222 message_loop_->PostTask(FROM_HERE, base::Bind(
178 &AudioInputController::DoReportError, this, code)); 223 &AudioInputController::DoReportError, this, code));
179 } 224 }
180 225
181 void AudioInputController::DoResetNoDataTimer() { 226 void AudioInputController::DoResetNoDataTimer() {
182 DCHECK(creator_loop_->BelongsToCurrentThread()); 227 DCHECK(creator_loop_->BelongsToCurrentThread());
183 no_data_timer_.Reset(); 228 no_data_timer_.Reset();
184 } 229 }
185 230
186 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, 231 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
187 uint32 size, uint32 hardware_delay_bytes) { 232 uint32 size, uint32 hardware_delay_bytes,
233 double volume) {
188 { 234 {
189 base::AutoLock auto_lock(lock_); 235 base::AutoLock auto_lock(lock_);
190 if (state_ != kRecording) 236 if (state_ != kRecording)
191 return; 237 return;
192 } 238 }
193 239
194 creator_loop_->PostTask(FROM_HERE, base::Bind( 240 creator_loop_->PostTask(FROM_HERE, base::Bind(
195 &AudioInputController::DoResetNoDataTimer, this)); 241 &AudioInputController::DoResetNoDataTimer, this));
196 242
197 // Use SyncSocket if we are in a low-latency mode. 243 // Use SyncSocket if we are in a low-latency mode.
198 if (LowLatencyMode()) { 244 if (LowLatencyMode()) {
199 sync_writer_->Write(data, size); 245 sync_writer_->Write(data, size, volume);
200 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 246 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
201 return; 247 return;
202 } 248 }
203 249
204 handler_->OnData(this, data, size); 250 handler_->OnData(this, data, size);
205 } 251 }
206 252
207 void AudioInputController::OnClose(AudioInputStream* stream) { 253 void AudioInputController::OnClose(AudioInputStream* stream) {
208 DVLOG(1) << "AudioInputController::OnClose()"; 254 DVLOG(1) << "AudioInputController::OnClose()";
209 // TODO(satish): Sometimes the device driver closes the input stream without 255 // TODO(satish): Sometimes the device driver closes the input stream without
(...skipping 17 matching lines...) Expand all
227 stream_->Close(); 273 stream_->Close();
228 stream_ = NULL; 274 stream_ = NULL;
229 } 275 }
230 276
231 // Should be last in the method, do not touch "this" from here on. 277 // Should be last in the method, do not touch "this" from here on.
232 if (done != NULL) 278 if (done != NULL)
233 done->Signal(); 279 done->Signal();
234 } 280 }
235 281
236 } // namespace media 282 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698