| 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/mac/audio_low_latency_input_mac.h" | 5 #include "media/audio/mac/audio_low_latency_input_mac.h" |
| 6 | 6 |
| 7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/mac/mac_logging.h" | 11 #include "base/mac/mac_logging.h" |
| 12 #include "media/audio/audio_util.h" | 12 #include "media/audio/audio_util.h" |
| 13 #include "media/audio/mac/audio_manager_mac.h" | 13 #include "media/audio/mac/audio_manager_mac.h" |
| 14 | 14 |
| 15 static const int kMinIntervalBetweenVolumeUpdatesMs = 1000; |
| 16 |
| 15 static std::ostream& operator<<(std::ostream& os, | 17 static std::ostream& operator<<(std::ostream& os, |
| 16 const AudioStreamBasicDescription& format) { | 18 const AudioStreamBasicDescription& format) { |
| 17 os << "sample rate : " << format.mSampleRate << std::endl | 19 os << "sample rate : " << format.mSampleRate << std::endl |
| 18 << "format ID : " << format.mFormatID << std::endl | 20 << "format ID : " << format.mFormatID << std::endl |
| 19 << "format flags : " << format.mFormatFlags << std::endl | 21 << "format flags : " << format.mFormatFlags << std::endl |
| 20 << "bytes per packet : " << format.mBytesPerPacket << std::endl | 22 << "bytes per packet : " << format.mBytesPerPacket << std::endl |
| 21 << "frames per packet : " << format.mFramesPerPacket << std::endl | 23 << "frames per packet : " << format.mFramesPerPacket << std::endl |
| 22 << "bytes per frame : " << format.mBytesPerFrame << std::endl | 24 << "bytes per frame : " << format.mBytesPerFrame << std::endl |
| 23 << "channels per frame: " << format.mChannelsPerFrame << std::endl | 25 << "channels per frame: " << format.mChannelsPerFrame << std::endl |
| 24 << "bits per channel : " << format.mBitsPerChannel; | 26 << "bits per channel : " << format.mBitsPerChannel; |
| 25 return os; | 27 return os; |
| 26 } | 28 } |
| 27 | 29 |
| 28 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" | 30 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" |
| 29 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html | 31 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html |
| 30 // for more details and background regarding this implementation. | 32 // for more details and background regarding this implementation. |
| 31 | 33 |
| 32 AUAudioInputStream::AUAudioInputStream( | 34 AUAudioInputStream::AUAudioInputStream( |
| 33 AudioManagerMac* manager, const AudioParameters& params, | 35 AudioManagerMac* manager, const AudioParameters& params, |
| 34 AudioDeviceID audio_device_id) | 36 AudioDeviceID audio_device_id) |
| 35 : manager_(manager), | 37 : manager_(manager), |
| 36 sink_(NULL), | 38 sink_(NULL), |
| 37 audio_unit_(0), | 39 audio_unit_(0), |
| 38 input_device_id_(audio_device_id), | 40 input_device_id_(audio_device_id), |
| 39 started_(false), | 41 started_(false), |
| 40 hardware_latency_frames_(0), | 42 hardware_latency_frames_(0), |
| 41 number_of_channels_in_frame_(0) { | 43 number_of_channels_in_frame_(0), |
| 44 volume_(0.0), |
| 45 agc_is_enabled_(0) { |
| 42 DCHECK(manager_); | 46 DCHECK(manager_); |
| 43 | 47 |
| 44 // Set up the desired (output) format specified by the client. | 48 // Set up the desired (output) format specified by the client. |
| 45 format_.mSampleRate = params.sample_rate; | 49 format_.mSampleRate = params.sample_rate; |
| 46 format_.mFormatID = kAudioFormatLinearPCM; | 50 format_.mFormatID = kAudioFormatLinearPCM; |
| 47 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | | 51 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | |
| 48 kLinearPCMFormatFlagIsSignedInteger; | 52 kLinearPCMFormatFlagIsSignedInteger; |
| 49 format_.mBitsPerChannel = params.bits_per_sample; | 53 format_.mBitsPerChannel = params.bits_per_sample; |
| 50 format_.mChannelsPerFrame = params.channels; | 54 format_.mChannelsPerFrame = params.channels; |
| 51 format_.mFramesPerPacket = 1; // uncompressed audio | 55 format_.mFramesPerPacket = 1; // uncompressed audio |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 // If the volume is settable, the valid volume range is [0.0, 1.0]. | 286 // If the volume is settable, the valid volume range is [0.0, 1.0]. |
| 283 if (IsVolumeSettableOnChannel(i)) | 287 if (IsVolumeSettableOnChannel(i)) |
| 284 return 1.0; | 288 return 1.0; |
| 285 } | 289 } |
| 286 | 290 |
| 287 // Volume control is not available for the audio stream. | 291 // Volume control is not available for the audio stream. |
| 288 return 0.0; | 292 return 0.0; |
| 289 } | 293 } |
| 290 | 294 |
| 291 void AUAudioInputStream::SetVolume(double volume) { | 295 void AUAudioInputStream::SetVolume(double volume) { |
| 292 DCHECK(volume <= 1.0 && volume >= 0.0); | 296 DCHECK_GE(volume, 0.0); |
| 297 DCHECK_LE(volume, 1.0); |
| 293 | 298 |
| 294 // Verify that we have a valid device. | 299 // Verify that we have a valid device. |
| 295 if (input_device_id_ == kAudioObjectUnknown) { | 300 if (input_device_id_ == kAudioObjectUnknown) { |
| 296 NOTREACHED() << "Device ID is unknown"; | 301 NOTREACHED() << "Device ID is unknown"; |
| 297 return; | 302 return; |
| 298 } | 303 } |
| 299 | 304 |
| 300 Float32 volume_float32 = static_cast<Float32>(volume); | 305 Float32 volume_float32 = static_cast<Float32>(volume); |
| 301 AudioObjectPropertyAddress property_address = { | 306 AudioObjectPropertyAddress property_address = { |
| 302 kAudioDevicePropertyVolumeScalar, | 307 kAudioDevicePropertyVolumeScalar, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 329 NULL, | 334 NULL, |
| 330 sizeof(volume_float32), | 335 sizeof(volume_float32), |
| 331 &volume_float32); | 336 &volume_float32); |
| 332 if (result == noErr) | 337 if (result == noErr) |
| 333 ++successful_channels; | 338 ++successful_channels; |
| 334 } | 339 } |
| 335 } | 340 } |
| 336 | 341 |
| 337 DLOG_IF(WARNING, successful_channels == 0) | 342 DLOG_IF(WARNING, successful_channels == 0) |
| 338 << "Failed to set volume to " << volume_float32; | 343 << "Failed to set volume to " << volume_float32; |
| 344 |
| 345 // We take new volume samples once every second when the AGC is enabled. |
| 346 // To ensure that a new setting has an immediate effect, the new volume |
| 347 // setting is cached here. It will ensure that the next OnData() callback |
| 348 // will contain a new valid volume level. If this approach was not taken, |
| 349 // we could report invalid volume levels to the client for a time period |
| 350 // of up to one second. |
| 351 if (GetAutomaticGainControl()) { |
| 352 volume_ = GetVolume(); |
| 353 } |
| 339 } | 354 } |
| 340 | 355 |
| 341 double AUAudioInputStream::GetVolume() { | 356 double AUAudioInputStream::GetVolume() { |
| 342 // Verify that we have a valid device. | 357 // Verify that we have a valid device. |
| 343 if (input_device_id_ == kAudioObjectUnknown){ | 358 if (input_device_id_ == kAudioObjectUnknown){ |
| 344 NOTREACHED() << "Device ID is unknown"; | 359 NOTREACHED() << "Device ID is unknown"; |
| 345 return 0.0; | 360 return 0.0; |
| 346 } | 361 } |
| 347 | 362 |
| 348 AudioObjectPropertyAddress property_address = { | 363 AudioObjectPropertyAddress property_address = { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 | 404 |
| 390 // Get the average volume of the channels. | 405 // Get the average volume of the channels. |
| 391 if (successful_channels != 0) | 406 if (successful_channels != 0) |
| 392 return static_cast<double>(volume_float32 / successful_channels); | 407 return static_cast<double>(volume_float32 / successful_channels); |
| 393 } | 408 } |
| 394 | 409 |
| 395 DLOG(WARNING) << "Failed to get volume"; | 410 DLOG(WARNING) << "Failed to get volume"; |
| 396 return 0.0; | 411 return 0.0; |
| 397 } | 412 } |
| 398 | 413 |
| 414 void AUAudioInputStream::SetAutomaticGainControl(bool enabled) { |
| 415 base::subtle::Release_Store(&agc_is_enabled_, enabled); |
| 416 } |
| 417 |
| 418 bool AUAudioInputStream::GetAutomaticGainControl() { |
| 419 return (base::subtle::Acquire_Load(&agc_is_enabled_) == 1); |
| 420 } |
| 421 |
| 399 // AUHAL AudioDeviceOutput unit callback | 422 // AUHAL AudioDeviceOutput unit callback |
| 400 OSStatus AUAudioInputStream::InputProc(void* user_data, | 423 OSStatus AUAudioInputStream::InputProc(void* user_data, |
| 401 AudioUnitRenderActionFlags* flags, | 424 AudioUnitRenderActionFlags* flags, |
| 402 const AudioTimeStamp* time_stamp, | 425 const AudioTimeStamp* time_stamp, |
| 403 UInt32 bus_number, | 426 UInt32 bus_number, |
| 404 UInt32 number_of_frames, | 427 UInt32 number_of_frames, |
| 405 AudioBufferList* io_data) { | 428 AudioBufferList* io_data) { |
| 406 // Verify that the correct bus is used (Input bus/Element 1) | 429 // Verify that the correct bus is used (Input bus/Element 1) |
| 407 DCHECK_EQ(bus_number, static_cast<UInt32>(1)); | 430 DCHECK_EQ(bus_number, static_cast<UInt32>(1)); |
| 408 AUAudioInputStream* audio_input = | 431 AUAudioInputStream* audio_input = |
| (...skipping 25 matching lines...) Expand all Loading... |
| 434 double capture_latency_frames = GetCaptureLatency(time_stamp); | 457 double capture_latency_frames = GetCaptureLatency(time_stamp); |
| 435 | 458 |
| 436 AudioBuffer& buffer = io_data->mBuffers[0]; | 459 AudioBuffer& buffer = io_data->mBuffers[0]; |
| 437 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); | 460 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); |
| 438 uint32 capture_delay_bytes = static_cast<uint32> | 461 uint32 capture_delay_bytes = static_cast<uint32> |
| 439 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); | 462 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); |
| 440 DCHECK(audio_data); | 463 DCHECK(audio_data); |
| 441 if (!audio_data) | 464 if (!audio_data) |
| 442 return kAudioUnitErr_InvalidElement; | 465 return kAudioUnitErr_InvalidElement; |
| 443 | 466 |
| 444 sink_->OnData(this, audio_data, buffer.mDataByteSize, capture_delay_bytes); | 467 // Query a new volume level if AGC is enabled and if it is time to update |
| 468 // the old value. |
| 469 if (GetAutomaticGainControl()) { |
| 470 base::Time now = base::Time::Now(); |
| 471 if ((now - last_volume_update_time_).InMilliseconds() > |
| 472 kMinIntervalBetweenVolumeUpdatesMs) { |
| 473 // Retrieve the current volume level. Range is [0.0,1.0]. |
| 474 volume_ = static_cast<double>(GetVolume()); |
| 475 last_volume_update_time_ = now; |
| 476 } |
| 477 } |
| 478 |
| 479 // Deliver data packet, delay estimation and volume level to the user. |
| 480 sink_->OnData(this, |
| 481 audio_data, |
| 482 buffer.mDataByteSize, |
| 483 capture_delay_bytes, |
| 484 volume_); |
| 445 | 485 |
| 446 return noErr; | 486 return noErr; |
| 447 } | 487 } |
| 448 | 488 |
| 449 double AUAudioInputStream::HardwareSampleRate() { | 489 double AUAudioInputStream::HardwareSampleRate() { |
| 450 // Determine the default input device's sample-rate. | 490 // Determine the default input device's sample-rate. |
| 451 AudioDeviceID device_id = kAudioObjectUnknown; | 491 AudioDeviceID device_id = kAudioObjectUnknown; |
| 452 UInt32 info_size = sizeof(device_id); | 492 UInt32 info_size = sizeof(device_id); |
| 453 | 493 |
| 454 AudioObjectPropertyAddress default_input_device_address = { | 494 AudioObjectPropertyAddress default_input_device_address = { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 AudioObjectPropertyAddress property_address = { | 615 AudioObjectPropertyAddress property_address = { |
| 576 kAudioDevicePropertyVolumeScalar, | 616 kAudioDevicePropertyVolumeScalar, |
| 577 kAudioDevicePropertyScopeInput, | 617 kAudioDevicePropertyScopeInput, |
| 578 static_cast<UInt32>(channel) | 618 static_cast<UInt32>(channel) |
| 579 }; | 619 }; |
| 580 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, | 620 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, |
| 581 &property_address, | 621 &property_address, |
| 582 &is_settable); | 622 &is_settable); |
| 583 return (result == noErr) ? is_settable : false; | 623 return (result == noErr) ? is_settable : false; |
| 584 } | 624 } |
| OLD | NEW |