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
3 // found in the LICENSE file.
5 #include "media/audio/mac/audio_low_latency_input_mac.h"
7 #include <CoreServices/CoreServices.h>
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/mac/mac_logging.h"
12 #include "media/audio/audio_util.h"
13 #include "media/audio/mac/audio_manager_mac.h"
14 #include "media/base/data_buffer.h"
18 static const int kMinIntervalBetweenVolumeUpdatesMs
= 1000;
20 static std::ostream
& operator<<(std::ostream
& os
,
21 const AudioStreamBasicDescription
& format
) {
22 os
<< "sample rate : " << format
.mSampleRate
<< std::endl
23 << "format ID : " << format
.mFormatID
<< std::endl
24 << "format flags : " << format
.mFormatFlags
<< std::endl
25 << "bytes per packet : " << format
.mBytesPerPacket
<< std::endl
26 << "frames per packet : " << format
.mFramesPerPacket
<< std::endl
27 << "bytes per frame : " << format
.mBytesPerFrame
<< std::endl
28 << "channels per frame: " << format
.mChannelsPerFrame
<< std::endl
29 << "bits per channel : " << format
.mBitsPerChannel
;
33 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit"
34 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html
35 // for more details and background regarding this implementation.
37 AUAudioInputStream::AUAudioInputStream(
38 AudioManagerMac
* manager
, const AudioParameters
& params
,
39 AudioDeviceID audio_device_id
)
43 input_device_id_(audio_device_id
),
45 hardware_latency_frames_(0),
46 number_of_channels_in_frame_(0) {
49 // Set up the desired (output) format specified by the client.
50 format_
.mSampleRate
= params
.sample_rate();
51 format_
.mFormatID
= kAudioFormatLinearPCM
;
52 format_
.mFormatFlags
= kLinearPCMFormatFlagIsPacked
|
53 kLinearPCMFormatFlagIsSignedInteger
;
54 format_
.mBitsPerChannel
= params
.bits_per_sample();
55 format_
.mChannelsPerFrame
= params
.channels();
56 format_
.mFramesPerPacket
= 1; // uncompressed audio
57 format_
.mBytesPerPacket
= (format_
.mBitsPerChannel
*
58 params
.channels()) / 8;
59 format_
.mBytesPerFrame
= format_
.mBytesPerPacket
;
60 format_
.mReserved
= 0;
62 DVLOG(1) << "Desired ouput format: " << format_
;
64 // Set number of sample frames per callback used by the internal audio layer.
65 // An internal FIFO is then utilized to adapt the internal size to the size
66 // requested by the client.
67 // Note that we use the same native buffer size as for the output side here
68 // since the AUHAL implementation requires that both capture and render side
69 // use the same buffer size. See http://crbug.com/154352 for more details.
70 // TODO(xians): Get the audio parameters from the right device.
71 const AudioParameters parameters
=
72 manager_
->GetInputStreamParameters(AudioManagerBase::kDefaultDeviceId
);
73 number_of_frames_
= parameters
.frames_per_buffer();
74 DVLOG(1) << "Size of data buffer in frames : " << number_of_frames_
;
76 // Derive size (in bytes) of the buffers that we will render to.
77 UInt32 data_byte_size
= number_of_frames_
* format_
.mBytesPerFrame
;
78 DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size
;
80 // Allocate AudioBuffers to be used as storage for the received audio.
81 // The AudioBufferList structure works as a placeholder for the
82 // AudioBuffer structure, which holds a pointer to the actual data buffer.
83 audio_data_buffer_
.reset(new uint8
[data_byte_size
]);
84 audio_buffer_list_
.mNumberBuffers
= 1;
86 AudioBuffer
* audio_buffer
= audio_buffer_list_
.mBuffers
;
87 audio_buffer
->mNumberChannels
= params
.channels();
88 audio_buffer
->mDataByteSize
= data_byte_size
;
89 audio_buffer
->mData
= audio_data_buffer_
.get();
91 // Set up an internal FIFO buffer that will accumulate recorded audio frames
92 // until a requested size is ready to be sent to the client.
93 // It is not possible to ask for less than |kAudioFramesPerCallback| number of
95 const size_t requested_size_frames
=
96 params
.GetBytesPerBuffer() / format_
.mBytesPerPacket
;
97 DCHECK_GE(requested_size_frames
, number_of_frames_
);
98 requested_size_bytes_
= requested_size_frames
* format_
.mBytesPerFrame
;
99 DVLOG(1) << "Requested buffer size in bytes : " << requested_size_bytes_
;
100 DLOG_IF(INFO
, requested_size_frames
> number_of_frames_
) << "FIFO is used";
102 // Allocate some extra memory to avoid memory reallocations.
103 // Ensure that the size is an even multiple of |number_of_frames_ and
104 // larger than |requested_size_frames|.
105 // Example: number_of_frames_=128, requested_size_frames=480 =>
106 // allocated space equals 4*128=512 audio frames
107 const int max_forward_capacity
= format_
.mBytesPerFrame
* number_of_frames_
*
108 ((requested_size_frames
/ number_of_frames_
) + 1);
109 fifo_
.reset(new media::SeekableBuffer(0, max_forward_capacity
));
111 data_
= new media::DataBuffer(requested_size_bytes_
);
114 AUAudioInputStream::~AUAudioInputStream() {}
116 // Obtain and open the AUHAL AudioOutputUnit for recording.
117 bool AUAudioInputStream::Open() {
118 // Verify that we are not already opened.
122 // Verify that we have a valid device.
123 if (input_device_id_
== kAudioObjectUnknown
) {
124 NOTREACHED() << "Device ID is unknown";
128 // Start by obtaining an AudioOuputUnit using an AUHAL component description.
131 ComponentDescription desc
;
133 // Description for the Audio Unit we want to use (AUHAL in this case).
134 desc
.componentType
= kAudioUnitType_Output
;
135 desc
.componentSubType
= kAudioUnitSubType_HALOutput
;
136 desc
.componentManufacturer
= kAudioUnitManufacturer_Apple
;
137 desc
.componentFlags
= 0;
138 desc
.componentFlagsMask
= 0;
139 comp
= FindNextComponent(0, &desc
);
142 // Get access to the service provided by the specified Audio Unit.
143 OSStatus result
= OpenAComponent(comp
, &audio_unit_
);
149 // Enable IO on the input scope of the Audio Unit.
151 // After creating the AUHAL object, we must enable IO on the input scope
152 // of the Audio Unit to obtain the device input. Input must be explicitly
153 // enabled with the kAudioOutputUnitProperty_EnableIO property on Element 1
154 // of the AUHAL. Beacause the AUHAL can be used for both input and output,
155 // we must also disable IO on the output scope.
159 // Enable input on the AUHAL.
160 result
= AudioUnitSetProperty(audio_unit_
,
161 kAudioOutputUnitProperty_EnableIO
,
162 kAudioUnitScope_Input
,
163 1, // input element 1
171 // Disable output on the AUHAL.
173 result
= AudioUnitSetProperty(audio_unit_
,
174 kAudioOutputUnitProperty_EnableIO
,
175 kAudioUnitScope_Output
,
176 0, // output element 0
177 &enableIO
, // disable
184 // Next, set the audio device to be the Audio Unit's current device.
185 // Note that, devices can only be set to the AUHAL after enabling IO.
186 result
= AudioUnitSetProperty(audio_unit_
,
187 kAudioOutputUnitProperty_CurrentDevice
,
188 kAudioUnitScope_Global
,
191 sizeof(input_device_id_
));
197 // Register the input procedure for the AUHAL.
198 // This procedure will be called when the AUHAL has received new data
199 // from the input device.
200 AURenderCallbackStruct callback
;
201 callback
.inputProc
= InputProc
;
202 callback
.inputProcRefCon
= this;
203 result
= AudioUnitSetProperty(audio_unit_
,
204 kAudioOutputUnitProperty_SetInputCallback
,
205 kAudioUnitScope_Global
,
214 // Set up the the desired (output) format.
215 // For obtaining input from a device, the device format is always expressed
216 // on the output scope of the AUHAL's Element 1.
217 result
= AudioUnitSetProperty(audio_unit_
,
218 kAudioUnitProperty_StreamFormat
,
219 kAudioUnitScope_Output
,
228 // Set the desired number of frames in the IO buffer (output scope).
229 // WARNING: Setting this value changes the frame size for all audio units in
230 // the current process. It's imperative that the input and output frame sizes
231 // be the same as the frames_per_buffer() returned by
232 // GetInputStreamParameters().
233 // TODO(henrika): Due to http://crrev.com/159666 this is currently not true
234 // and should be fixed, a CHECK() should be added at that time.
235 result
= AudioUnitSetProperty(audio_unit_
,
236 kAudioDevicePropertyBufferFrameSize
,
237 kAudioUnitScope_Output
,
239 &number_of_frames_
, // size is set in the ctor
240 sizeof(number_of_frames_
));
246 // Finally, initialize the audio unit and ensure that it is ready to render.
247 // Allocates memory according to the maximum number of audio frames
248 // it can produce in response to a single render call.
249 result
= AudioUnitInitialize(audio_unit_
);
255 // The hardware latency is fixed and will not change during the call.
256 hardware_latency_frames_
= GetHardwareLatency();
258 // The master channel is 0, Left and right are channels 1 and 2.
259 // And the master channel is not counted in |number_of_channels_in_frame_|.
260 number_of_channels_in_frame_
= GetNumberOfChannelsFromStream();
265 void AUAudioInputStream::Start(AudioInputCallback
* callback
) {
267 DLOG_IF(ERROR
, !audio_unit_
) << "Open() has not been called successfully";
268 if (started_
|| !audio_unit_
)
271 OSStatus result
= AudioOutputUnitStart(audio_unit_
);
272 if (result
== noErr
) {
275 OSSTATUS_DLOG_IF(ERROR
, result
!= noErr
, result
)
276 << "Failed to start acquiring data";
279 void AUAudioInputStream::Stop() {
282 OSStatus result
= AudioOutputUnitStop(audio_unit_
);
283 if (result
== noErr
) {
286 OSSTATUS_DLOG_IF(ERROR
, result
!= noErr
, result
)
287 << "Failed to stop acquiring data";
290 void AUAudioInputStream::Close() {
291 // It is valid to call Close() before calling open or Start().
292 // It is also valid to call Close() after Start() has been called.
297 // Deallocate the audio unit’s resources.
298 AudioUnitUninitialize(audio_unit_
);
300 // Terminates our connection to the AUHAL component.
301 CloseComponent(audio_unit_
);
305 sink_
->OnClose(this);
309 // Inform the audio manager that we have been closed. This can cause our
311 manager_
->ReleaseInputStream(this);
314 double AUAudioInputStream::GetMaxVolume() {
315 // Verify that we have a valid device.
316 if (input_device_id_
== kAudioObjectUnknown
) {
317 NOTREACHED() << "Device ID is unknown";
321 // Query if any of the master, left or right channels has volume control.
322 for (int i
= 0; i
<= number_of_channels_in_frame_
; ++i
) {
323 // If the volume is settable, the valid volume range is [0.0, 1.0].
324 if (IsVolumeSettableOnChannel(i
))
328 // Volume control is not available for the audio stream.
332 void AUAudioInputStream::SetVolume(double volume
) {
333 DVLOG(1) << "SetVolume(volume=" << volume
<< ")";
334 DCHECK_GE(volume
, 0.0);
335 DCHECK_LE(volume
, 1.0);
337 // Verify that we have a valid device.
338 if (input_device_id_
== kAudioObjectUnknown
) {
339 NOTREACHED() << "Device ID is unknown";
343 Float32 volume_float32
= static_cast<Float32
>(volume
);
344 AudioObjectPropertyAddress property_address
= {
345 kAudioDevicePropertyVolumeScalar
,
346 kAudioDevicePropertyScopeInput
,
347 kAudioObjectPropertyElementMaster
350 // Try to set the volume for master volume channel.
351 if (IsVolumeSettableOnChannel(kAudioObjectPropertyElementMaster
)) {
352 OSStatus result
= AudioObjectSetPropertyData(input_device_id_
,
356 sizeof(volume_float32
),
358 if (result
!= noErr
) {
359 DLOG(WARNING
) << "Failed to set volume to " << volume_float32
;
364 // There is no master volume control, try to set volume for each channel.
365 int successful_channels
= 0;
366 for (int i
= 1; i
<= number_of_channels_in_frame_
; ++i
) {
367 property_address
.mElement
= static_cast<UInt32
>(i
);
368 if (IsVolumeSettableOnChannel(i
)) {
369 OSStatus result
= AudioObjectSetPropertyData(input_device_id_
,
373 sizeof(volume_float32
),
376 ++successful_channels
;
380 DLOG_IF(WARNING
, successful_channels
== 0)
381 << "Failed to set volume to " << volume_float32
;
383 // Update the AGC volume level based on the last setting above. Note that,
384 // the volume-level resolution is not infinite and it is therefore not
385 // possible to assume that the volume provided as input parameter can be
386 // used directly. Instead, a new query to the audio hardware is required.
387 // This method does nothing if AGC is disabled.
391 double AUAudioInputStream::GetVolume() {
392 // Verify that we have a valid device.
393 if (input_device_id_
== kAudioObjectUnknown
){
394 NOTREACHED() << "Device ID is unknown";
398 AudioObjectPropertyAddress property_address
= {
399 kAudioDevicePropertyVolumeScalar
,
400 kAudioDevicePropertyScopeInput
,
401 kAudioObjectPropertyElementMaster
404 if (AudioObjectHasProperty(input_device_id_
, &property_address
)) {
405 // The device supports master volume control, get the volume from the
407 Float32 volume_float32
= 0.0;
408 UInt32 size
= sizeof(volume_float32
);
409 OSStatus result
= AudioObjectGetPropertyData(input_device_id_
,
416 return static_cast<double>(volume_float32
);
418 // There is no master volume control, try to get the average volume of
420 Float32 volume_float32
= 0.0;
421 int successful_channels
= 0;
422 for (int i
= 1; i
<= number_of_channels_in_frame_
; ++i
) {
423 property_address
.mElement
= static_cast<UInt32
>(i
);
424 if (AudioObjectHasProperty(input_device_id_
, &property_address
)) {
425 Float32 channel_volume
= 0;
426 UInt32 size
= sizeof(channel_volume
);
427 OSStatus result
= AudioObjectGetPropertyData(input_device_id_
,
433 if (result
== noErr
) {
434 volume_float32
+= channel_volume
;
435 ++successful_channels
;
440 // Get the average volume of the channels.
441 if (successful_channels
!= 0)
442 return static_cast<double>(volume_float32
/ successful_channels
);
445 DLOG(WARNING
) << "Failed to get volume";
449 // AUHAL AudioDeviceOutput unit callback
450 OSStatus
AUAudioInputStream::InputProc(void* user_data
,
451 AudioUnitRenderActionFlags
* flags
,
452 const AudioTimeStamp
* time_stamp
,
454 UInt32 number_of_frames
,
455 AudioBufferList
* io_data
) {
456 // Verify that the correct bus is used (Input bus/Element 1)
457 DCHECK_EQ(bus_number
, static_cast<UInt32
>(1));
458 AUAudioInputStream
* audio_input
=
459 reinterpret_cast<AUAudioInputStream
*>(user_data
);
462 return kAudioUnitErr_InvalidElement
;
464 // Receive audio from the AUHAL from the output scope of the Audio Unit.
465 OSStatus result
= AudioUnitRender(audio_input
->audio_unit(),
470 audio_input
->audio_buffer_list());
474 // Deliver recorded data to the consumer as a callback.
475 return audio_input
->Provide(number_of_frames
,
476 audio_input
->audio_buffer_list(),
480 OSStatus
AUAudioInputStream::Provide(UInt32 number_of_frames
,
481 AudioBufferList
* io_data
,
482 const AudioTimeStamp
* time_stamp
) {
483 // Update the capture latency.
484 double capture_latency_frames
= GetCaptureLatency(time_stamp
);
486 // Update the AGC volume level once every second. Note that, |volume| is
487 // also updated each time SetVolume() is called through IPC by the
489 double normalized_volume
= 0.0;
490 QueryAgcVolume(&normalized_volume
);
492 AudioBuffer
& buffer
= io_data
->mBuffers
[0];
493 uint8
* audio_data
= reinterpret_cast<uint8
*>(buffer
.mData
);
494 uint32 capture_delay_bytes
= static_cast<uint32
>
495 ((capture_latency_frames
+ 0.5) * format_
.mBytesPerFrame
);
498 return kAudioUnitErr_InvalidElement
;
500 // Accumulate captured audio in FIFO until we can match the output size
501 // requested by the client.
502 fifo_
->Append(audio_data
, buffer
.mDataByteSize
);
504 // Deliver recorded data to the client as soon as the FIFO contains a
505 // sufficient amount.
506 while (fifo_
->forward_bytes() >= requested_size_bytes_
) {
507 // Read from FIFO into temporary data buffer.
508 fifo_
->Read(data_
->GetWritableData(), requested_size_bytes_
);
510 // Deliver data packet, delay estimation and volume level to the user.
513 requested_size_bytes_
,
521 int AUAudioInputStream::HardwareSampleRate() {
522 // Determine the default input device's sample-rate.
523 AudioDeviceID device_id
= kAudioObjectUnknown
;
524 UInt32 info_size
= sizeof(device_id
);
526 AudioObjectPropertyAddress default_input_device_address
= {
527 kAudioHardwarePropertyDefaultInputDevice
,
528 kAudioObjectPropertyScopeGlobal
,
529 kAudioObjectPropertyElementMaster
531 OSStatus result
= AudioObjectGetPropertyData(kAudioObjectSystemObject
,
532 &default_input_device_address
,
540 Float64 nominal_sample_rate
;
541 info_size
= sizeof(nominal_sample_rate
);
543 AudioObjectPropertyAddress nominal_sample_rate_address
= {
544 kAudioDevicePropertyNominalSampleRate
,
545 kAudioObjectPropertyScopeGlobal
,
546 kAudioObjectPropertyElementMaster
548 result
= AudioObjectGetPropertyData(device_id
,
549 &nominal_sample_rate_address
,
553 &nominal_sample_rate
);
557 return static_cast<int>(nominal_sample_rate
);
560 double AUAudioInputStream::GetHardwareLatency() {
561 if (!audio_unit_
|| input_device_id_
== kAudioObjectUnknown
) {
562 DLOG(WARNING
) << "Audio unit object is NULL or device ID is unknown";
566 // Get audio unit latency.
567 Float64 audio_unit_latency_sec
= 0.0;
568 UInt32 size
= sizeof(audio_unit_latency_sec
);
569 OSStatus result
= AudioUnitGetProperty(audio_unit_
,
570 kAudioUnitProperty_Latency
,
571 kAudioUnitScope_Global
,
573 &audio_unit_latency_sec
,
575 OSSTATUS_DLOG_IF(WARNING
, result
!= noErr
, result
)
576 << "Could not get audio unit latency";
578 // Get input audio device latency.
579 AudioObjectPropertyAddress property_address
= {
580 kAudioDevicePropertyLatency
,
581 kAudioDevicePropertyScopeInput
,
582 kAudioObjectPropertyElementMaster
584 UInt32 device_latency_frames
= 0;
585 size
= sizeof(device_latency_frames
);
586 result
= AudioObjectGetPropertyData(input_device_id_
,
591 &device_latency_frames
);
592 DLOG_IF(WARNING
, result
!= noErr
) << "Could not get audio device latency.";
594 return static_cast<double>((audio_unit_latency_sec
*
595 format_
.mSampleRate
) + device_latency_frames
);
598 double AUAudioInputStream::GetCaptureLatency(
599 const AudioTimeStamp
* input_time_stamp
) {
600 // Get the delay between between the actual recording instant and the time
601 // when the data packet is provided as a callback.
602 UInt64 capture_time_ns
= AudioConvertHostTimeToNanos(
603 input_time_stamp
->mHostTime
);
604 UInt64 now_ns
= AudioConvertHostTimeToNanos(AudioGetCurrentHostTime());
605 double delay_frames
= static_cast<double>
606 (1e-9 * (now_ns
- capture_time_ns
) * format_
.mSampleRate
);
608 // Total latency is composed by the dynamic latency and the fixed
610 return (delay_frames
+ hardware_latency_frames_
);
613 int AUAudioInputStream::GetNumberOfChannelsFromStream() {
614 // Get the stream format, to be able to read the number of channels.
615 AudioObjectPropertyAddress property_address
= {
616 kAudioDevicePropertyStreamFormat
,
617 kAudioDevicePropertyScopeInput
,
618 kAudioObjectPropertyElementMaster
620 AudioStreamBasicDescription stream_format
;
621 UInt32 size
= sizeof(stream_format
);
622 OSStatus result
= AudioObjectGetPropertyData(input_device_id_
,
628 if (result
!= noErr
) {
629 DLOG(WARNING
) << "Could not get stream format";
633 return static_cast<int>(stream_format
.mChannelsPerFrame
);
636 void AUAudioInputStream::HandleError(OSStatus err
) {
637 NOTREACHED() << "error " << GetMacOSStatusErrorString(err
)
638 << " (" << err
<< ")";
640 sink_
->OnError(this);
643 bool AUAudioInputStream::IsVolumeSettableOnChannel(int channel
) {
644 Boolean is_settable
= false;
645 AudioObjectPropertyAddress property_address
= {
646 kAudioDevicePropertyVolumeScalar
,
647 kAudioDevicePropertyScopeInput
,
648 static_cast<UInt32
>(channel
)
650 OSStatus result
= AudioObjectIsPropertySettable(input_device_id_
,
653 return (result
== noErr
) ? is_settable
: false;