15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of AudioInputStream for Mac OS X using the special AUHAL 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// input Audio Unit present in OS 10.4 and later. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The AUHAL input Audio Unit is for low-latency audio I/O. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Overview of operation: 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - An object of AUAudioInputStream is created by the AudioManager 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// factory: audio_man->MakeAudioInputStream(). 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Next some thread will call Open(), at that point the underlying 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AUHAL output Audio Unit is created and configured. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Then some thread will call Start(sink). 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Then the Audio Unit is started which creates its own thread which 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// periodically will provide the sink with more data as buffers are being 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// produced/recorded. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - At some point some thread will call Stop(), which we handle by directly 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stopping the AUHAL output Audio Unit. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The same thread that called stop will call Close() where we cleanup 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and notify the audio manager, which likely will destroy this object. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation notes: 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - It is recommended to first acquire the native sample rate of the default 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// input device and then use the same rate when creating this object. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use AUAudioInputStream::HardwareSampleRate() to retrieve the sample rate. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Calling Close() also leads to self destruction. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The latency consists of two parts: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1) Hardware latency, which includes Audio Unit latency, audio device 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// latency; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2) The delay between the actual recording instant and the time when the 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data packet is provided as a callback. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_ 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <AudioUnit/AudioUnit.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CoreAudio/CoreAudio.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/cancelable_callback.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/audio/agc_audio_stream.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)class AudioBus; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioManagerMac; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DataBuffer; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class AUAudioInputStream : public AgcAudioStream<AudioInputStream> { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The ctor takes all the usual parameters, plus |manager| which is the 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the audio manager who is creating this object. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AUAudioInputStream(AudioManagerMac* manager, 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const AudioParameters& input_params, 6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const AudioParameters& output_params, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioDeviceID audio_device_id); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The dtor is typically called by the AudioManager only and it is usually 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered by calling AudioInputStream::Close(). 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~AUAudioInputStream(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Implementation of AudioInputStream. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool Open() OVERRIDE; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Start(AudioInputCallback* callback) OVERRIDE; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Stop() OVERRIDE; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Close() OVERRIDE; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual double GetMaxVolume() OVERRIDE; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetVolume(double volume) OVERRIDE; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual double GetVolume() OVERRIDE; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the current hardware sample rate for the default input device. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEDIA_EXPORT static int HardwareSampleRate(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool started() const { return started_; } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioUnit audio_unit() { return audio_unit_; } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBufferList* audio_buffer_list() { return &audio_buffer_list_; } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioOutputUnit callback. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static OSStatus InputProc(void* user_data, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioUnitRenderActionFlags* flags, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioTimeStamp* time_stamp, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 bus_number, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 number_of_frames, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBufferList* io_data); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pushes recorded data to consumer of the input audio stream. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSStatus Provide(UInt32 number_of_frames, AudioBufferList* io_data, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AudioTimeStamp* time_stamp); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the fixed capture hardware latency and store it during initialization. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns 0 if not available. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double GetHardwareLatency(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the current capture delay value. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double GetCaptureLatency(const AudioTimeStamp* input_time_stamp); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the number of channels for a stream of audio data. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetNumberOfChannelsFromStream(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Issues the OnError() callback to the |sink_|. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleError(OSStatus err); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helper function to check if the volume control is avialable on specific 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // channel. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsVolumeSettableOnChannel(int channel); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our creator, the audio manager needs to be notified when we close. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioManagerMac* manager_; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Contains the desired number of audio frames in each callback. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t number_of_frames_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pointer to the object that will receive the recorded audio samples. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioInputCallback* sink_; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Structure that holds the desired output format of the stream. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that, this format can differ from the device(=input) format. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioStreamBasicDescription format_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The special Audio Unit called AUHAL, which allows us to pass audio data 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // directly from a microphone, through the HAL, and to our application. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The AUHAL also enables selection of non default devices. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioUnit audio_unit_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The UID refers to the current input audio device. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioDeviceID input_device_id_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provides a mechanism for encapsulating one or more buffers of audio data. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBufferList audio_buffer_list_; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Temporary storage for recorded data. The InputProc() renders into this 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // array as soon as a frame of the desired buffer size has been recorded. 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<uint8[]> audio_data_buffer_; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True after successfull Start(), false after successful Stop(). 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool started_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fixed capture hardware latency in frames. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double hardware_latency_frames_; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Delay due to the FIFO in bytes. 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int fifo_delay_bytes_; 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of channels in each frame of audio data, which is used 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when querying the volume of each channel. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int number_of_channels_in_frame_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Accumulates recorded data packets until the requested size has been stored. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<media::SeekableBuffer> fifo_; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Intermediate storage of data from the FIFO before sending it to the 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // client using the OnData() callback. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DataBuffer> data_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client requests that the recorded data shall be delivered using 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnData() callbacks where each callback contains this amount of bytes. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int requested_size_bytes_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Used to defer Start() to workaround http://crbug.com/160920. 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::CancelableClosure deferred_start_cb_; 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Extra audio bus used for storage of deinterleaved data for the OnData 1706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // callback. 1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) scoped_ptr<media::AudioBus> audio_bus_; 1726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AUAudioInputStream); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_ 179