Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "base/time/time.h" | |
| 9 #include "media/base/limits.h" | 10 #include "media/base/limits.h" |
| 10 #include "media/base/scoped_histogram_timer.h" | 11 #include "media/base/scoped_histogram_timer.h" |
| 11 #include "media/base/user_input_monitor.h" | 12 #include "media/base/user_input_monitor.h" |
| 12 | 13 |
| 14 using base::TimeDelta; | |
| 15 | |
| 13 namespace { | 16 namespace { |
| 14 const int kMaxInputChannels = 3; | 17 const int kMaxInputChannels = 3; |
| 15 | 18 |
| 16 // TODO(henrika): remove usage of timers and add support for proper | 19 // TODO(henrika): remove usage of timers and add support for proper |
| 17 // notification of when the input device is removed. This was originally added | 20 // notification of when the input device is removed. This was originally added |
| 18 // to resolve http://crbug.com/79936 for Windows platforms. This then caused | 21 // to resolve http://crbug.com/79936 for Windows platforms. This then caused |
| 19 // breakage (very hard to repro bugs!) on other platforms: See | 22 // breakage (very hard to repro bugs!) on other platforms: See |
| 20 // http://crbug.com/226327 and http://crbug.com/230972. | 23 // http://crbug.com/226327 and http://crbug.com/230972. |
| 21 // See also that the timer has been disabled on Mac now due to | 24 // See also that the timer has been disabled on Mac now due to |
| 22 // crbug.com/357501. | 25 // crbug.com/357501. |
| 23 const int kTimerResetIntervalSeconds = 1; | 26 const int kTimerResetIntervalSeconds = 1; |
| 24 // We have received reports that the timer can be too trigger happy on some | 27 // We have received reports that the timer can be too trigger happy on some |
| 25 // Mac devices and the initial timer interval has therefore been increased | 28 // Mac devices and the initial timer interval has therefore been increased |
| 26 // from 1 second to 5 seconds. | 29 // from 1 second to 5 seconds. |
| 27 const int kTimerInitialIntervalSeconds = 5; | 30 const int kTimerInitialIntervalSeconds = 5; |
| 31 | |
| 32 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for | |
| 33 // semantics. This value was arbitrarily chosen, but seems to work well. | |
| 34 const int kPowerMeasurementTimeConstantMillis = 10; | |
| 35 | |
| 36 // Time between two successive measurements of audio power levels. | |
| 37 const int kPowerMonitorLogIntervalMilliSeconds = 500; | |
| 28 } | 38 } |
| 29 | 39 |
| 30 namespace media { | 40 namespace media { |
| 31 | 41 |
| 32 // static | 42 // static |
| 33 AudioInputController::Factory* AudioInputController::factory_ = NULL; | 43 AudioInputController::Factory* AudioInputController::factory_ = NULL; |
| 34 | 44 |
| 35 AudioInputController::AudioInputController(EventHandler* handler, | 45 AudioInputController::AudioInputController(EventHandler* handler, |
| 36 SyncWriter* sync_writer, | 46 SyncWriter* sync_writer, |
| 37 UserInputMonitor* user_input_monitor) | 47 UserInputMonitor* user_input_monitor) |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 void AudioInputController::SetAutomaticGainControl(bool enabled) { | 176 void AudioInputController::SetAutomaticGainControl(bool enabled) { |
| 167 task_runner_->PostTask(FROM_HERE, base::Bind( | 177 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 168 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); | 178 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); |
| 169 } | 179 } |
| 170 | 180 |
| 171 void AudioInputController::DoCreate(AudioManager* audio_manager, | 181 void AudioInputController::DoCreate(AudioManager* audio_manager, |
| 172 const AudioParameters& params, | 182 const AudioParameters& params, |
| 173 const std::string& device_id) { | 183 const std::string& device_id) { |
| 174 DCHECK(task_runner_->BelongsToCurrentThread()); | 184 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 175 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); | 185 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); |
| 186 | |
| 187 // Create the audio (power) level meter given the provided audio parameters. | |
| 188 audio_level_.reset(new media::AudioPowerMonitor(params.sample_rate(), | |
| 189 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis))); | |
| 190 audio_bus_ = AudioBus::Create(params); | |
| 191 audio_params_ = params; | |
| 192 | |
| 176 // TODO(miu): See TODO at top of file. Until that's resolved, assume all | 193 // TODO(miu): See TODO at top of file. Until that's resolved, assume all |
| 177 // platform audio input requires the |no_data_timer_| be used to auto-detect | 194 // platform audio input requires the |no_data_timer_| be used to auto-detect |
| 178 // errors. In reality, probably only Windows needs to be treated as | 195 // errors. In reality, probably only Windows needs to be treated as |
| 179 // unreliable here. | 196 // unreliable here. |
| 180 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), | 197 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), |
| 181 true); | 198 true); |
| 182 } | 199 } |
| 183 | 200 |
| 184 void AudioInputController::DoCreateForStream( | 201 void AudioInputController::DoCreateForStream( |
| 185 AudioInputStream* stream_to_control, bool enable_nodata_timer) { | 202 AudioInputStream* stream_to_control, bool enable_nodata_timer) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 void AudioInputController::DoClose() { | 276 void AudioInputController::DoClose() { |
| 260 DCHECK(task_runner_->BelongsToCurrentThread()); | 277 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 261 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); | 278 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); |
| 262 | 279 |
| 263 if (state_ == CLOSED) | 280 if (state_ == CLOSED) |
| 264 return; | 281 return; |
| 265 | 282 |
| 266 // Delete the timer on the same thread that created it. | 283 // Delete the timer on the same thread that created it. |
| 267 no_data_timer_.reset(); | 284 no_data_timer_.reset(); |
| 268 | 285 |
| 286 if (audio_level_) | |
|
no longer working on chromium
2014/05/19 15:15:48
skip if
henrika (OOO until Aug 14)
2014/05/19 15:25:46
It can be NULL.
| |
| 287 audio_level_->Reset(); | |
| 288 | |
| 269 DoStopCloseAndClearStream(); | 289 DoStopCloseAndClearStream(); |
| 270 SetDataIsActive(false); | 290 SetDataIsActive(false); |
| 271 | 291 |
| 272 if (SharedMemoryAndSyncSocketMode()) | 292 if (SharedMemoryAndSyncSocketMode()) |
| 273 sync_writer_->Close(); | 293 sync_writer_->Close(); |
| 274 | 294 |
| 275 if (user_input_monitor_) | 295 if (user_input_monitor_) |
| 276 user_input_monitor_->DisableKeyPressMonitoring(); | 296 user_input_monitor_->DisableKeyPressMonitoring(); |
| 277 | 297 |
| 278 state_ = CLOSED; | 298 state_ = CLOSED; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 key_pressed = current_count != prev_key_down_count_; | 390 key_pressed = current_count != prev_key_down_count_; |
| 371 prev_key_down_count_ = current_count; | 391 prev_key_down_count_ = current_count; |
| 372 DVLOG_IF(6, key_pressed) << "Detected keypress."; | 392 DVLOG_IF(6, key_pressed) << "Detected keypress."; |
| 373 } | 393 } |
| 374 | 394 |
| 375 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. | 395 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. |
| 376 // Used by all low-latency clients except WebSpeech. | 396 // Used by all low-latency clients except WebSpeech. |
| 377 if (SharedMemoryAndSyncSocketMode()) { | 397 if (SharedMemoryAndSyncSocketMode()) { |
| 378 sync_writer_->Write(data, size, volume, key_pressed); | 398 sync_writer_->Write(data, size, volume, key_pressed); |
| 379 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 399 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
| 400 | |
| 401 if (!audio_level_) | |
|
no longer working on chromium
2014/05/19 15:15:48
can audio_level be NULL?
henrika (OOO until Aug 14)
2014/05/19 15:25:46
Yes, using new ctor. I can modify and create when
| |
| 402 return; | |
| 403 | |
| 404 // Perform periodic audio (power) level measurements. | |
| 405 if ((base::TimeTicks::Now() - last_audio_level_log_time_).InMilliseconds() > | |
| 406 kPowerMonitorLogIntervalMilliSeconds) { | |
| 407 last_audio_level_log_time_ = base::TimeTicks::Now(); | |
| 408 audio_bus_->FromInterleaved( | |
| 409 data, audio_bus_->frames(), audio_params_.bits_per_sample() / 8); | |
| 410 audio_level_->Scan(*audio_bus_, audio_bus_->frames()); | |
| 411 std::pair<float, bool> result = audio_level_->ReadCurrentPowerAndClip(); | |
| 412 | |
| 413 // Get the audible level in the range [0.0,1.0], where 0.0 means | |
| 414 // the audio signal is silent and 1.0 means it is at maximum volume. | |
| 415 float level_dbfs = result.first; | |
| 416 float level = 0; | |
| 417 static const float kSilenceThresholdDBFS = -72.24719896f; | |
| 418 if (level_dbfs < kSilenceThresholdDBFS) | |
| 419 level = 0.0f; | |
| 420 else if (level_dbfs > 0.0f) | |
| 421 level = 1.0f; | |
| 422 else | |
| 423 level = 1.0f - level_dbfs / kSilenceThresholdDBFS; | |
| 424 DVLOG(1) << "audio_level: " << level; | |
| 425 | |
| 426 audio_level_->Reset(); | |
| 427 } | |
| 428 | |
| 380 return; | 429 return; |
| 381 } | 430 } |
| 382 | 431 |
| 383 // TODO(henrika): Investigate if we can avoid the extra copy here. | 432 // TODO(henrika): Investigate if we can avoid the extra copy here. |
| 384 // (see http://crbug.com/249316 for details). AFAIK, this scope is only | 433 // (see http://crbug.com/249316 for details). AFAIK, this scope is only |
| 385 // active for WebSpeech clients. | 434 // active for WebSpeech clients. |
| 386 scoped_ptr<uint8[]> audio_data(new uint8[size]); | 435 scoped_ptr<uint8[]> audio_data(new uint8[size]); |
| 387 memcpy(audio_data.get(), data, size); | 436 memcpy(audio_data.get(), data, size); |
| 388 | 437 |
| 389 // Ownership of the audio buffer will be with the callback until it is run, | 438 // Ownership of the audio buffer will be with the callback until it is run, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 420 | 469 |
| 421 void AudioInputController::SetDataIsActive(bool enabled) { | 470 void AudioInputController::SetDataIsActive(bool enabled) { |
| 422 base::subtle::Release_Store(&data_is_active_, enabled); | 471 base::subtle::Release_Store(&data_is_active_, enabled); |
| 423 } | 472 } |
| 424 | 473 |
| 425 bool AudioInputController::GetDataIsActive() { | 474 bool AudioInputController::GetDataIsActive() { |
| 426 return (base::subtle::Acquire_Load(&data_is_active_) != false); | 475 return (base::subtle::Acquire_Load(&data_is_active_) != false); |
| 427 } | 476 } |
| 428 | 477 |
| 429 } // namespace media | 478 } // namespace media |
| OLD | NEW |