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 |