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. 4 // 5 // Implementation of AudioInputStream for Mac OS X using the special AUHAL 6 // input Audio Unit present in OS 10.4 and later. 7 // The AUHAL input Audio Unit is for low-latency audio I/O. 8 // 9 // Overview of operation: 10 // 11 // - An object of AUAudioInputStream is created by the AudioManager 12 // factory: audio_man->MakeAudioInputStream(). 13 // - Next some thread will call Open(), at that point the underlying 14 // AUHAL output Audio Unit is created and configured. 15 // - Then some thread will call Start(sink). 16 // Then the Audio Unit is started which creates its own thread which 17 // periodically will provide the sink with more data as buffers are being 18 // produced/recorded. 19 // - At some point some thread will call Stop(), which we handle by directly 20 // stopping the AUHAL output Audio Unit. 21 // - The same thread that called stop will call Close() where we cleanup 22 // and notify the audio manager, which likely will destroy this object. 23 // 24 // Implementation notes: 25 // 26 // - It is recommended to first acquire the native sample rate of the default 27 // input device and then use the same rate when creating this object. 28 // Use AUAudioInputStream::HardwareSampleRate() to retrieve the sample rate. 29 // - Calling Close() also leads to self destruction. 30 // - The latency consists of two parts: 31 // 1) Hardware latency, which includes Audio Unit latency, audio device 32 // latency; 33 // 2) The delay between the actual recording instant and the time when the 34 // data packet is provided as a callback. 35 // 36 #ifndef MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_ 37 #define MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_ 38 39 #include <AudioUnit/AudioUnit.h> 40 #include <CoreAudio/CoreAudio.h> 41 42 #include "base/atomicops.h" 43 #include "base/memory/scoped_ptr.h" 44 #include "base/synchronization/lock.h" 45 #include "media/audio/agc_audio_stream.h" 46 #include "media/audio/audio_io.h" 47 #include "media/audio/audio_parameters.h" 48 #include "media/base/seekable_buffer.h" 49 50 namespace media { 51 52 class AudioManagerMac; 53 class DataBuffer; 54 55 class AUAudioInputStream : public AgcAudioStream<AudioInputStream> { 56 public: 57 // The ctor takes all the usual parameters, plus |manager| which is the 58 // the audio manager who is creating this object. 59 AUAudioInputStream(AudioManagerMac* manager, 60 const AudioParameters& params, 61 AudioDeviceID audio_device_id); 62 // The dtor is typically called by the AudioManager only and it is usually 63 // triggered by calling AudioInputStream::Close(). 64 virtual ~AUAudioInputStream(); 65 66 // Implementation of AudioInputStream. 67 virtual bool Open() OVERRIDE; 68 virtual void Start(AudioInputCallback* callback) OVERRIDE; 69 virtual void Stop() OVERRIDE; 70 virtual void Close() OVERRIDE; 71 virtual double GetMaxVolume() OVERRIDE; 72 virtual void SetVolume(double volume) OVERRIDE; 73 virtual double GetVolume() OVERRIDE; 74 75 // Returns the current hardware sample rate for the default input device. 76 MEDIA_EXPORT static int HardwareSampleRate(); 77 78 bool started() const { return started_; } 79 AudioUnit audio_unit() { return audio_unit_; } 80 AudioBufferList* audio_buffer_list() { return &audio_buffer_list_; } 81 82 private: 83 // AudioOutputUnit callback. 84 static OSStatus InputProc(void* user_data, 85 AudioUnitRenderActionFlags* flags, 86 const AudioTimeStamp* time_stamp, 87 UInt32 bus_number, 88 UInt32 number_of_frames, 89 AudioBufferList* io_data); 90 91 // Pushes recorded data to consumer of the input audio stream. 92 OSStatus Provide(UInt32 number_of_frames, AudioBufferList* io_data, 93 const AudioTimeStamp* time_stamp); 94 95 // Gets the fixed capture hardware latency and store it during initialization. 96 // Returns 0 if not available. 97 double GetHardwareLatency(); 98 99 // Gets the current capture delay value. 100 double GetCaptureLatency(const AudioTimeStamp* input_time_stamp); 101 102 // Gets the number of channels for a stream of audio data. 103 int GetNumberOfChannelsFromStream(); 104 105 // Issues the OnError() callback to the |sink_|. 106 void HandleError(OSStatus err); 107 108 // Helper function to check if the volume control is avialable on specific 109 // channel. 110 bool IsVolumeSettableOnChannel(int channel); 111 112 // Our creator, the audio manager needs to be notified when we close. 113 AudioManagerMac* manager_; 114 115 // Contains the desired number of audio frames in each callback. 116 size_t number_of_frames_; 117 118 // Pointer to the object that will receive the recorded audio samples. 119 AudioInputCallback* sink_; 120 121 // Structure that holds the desired output format of the stream. 122 // Note that, this format can differ from the device(=input) format. 123 AudioStreamBasicDescription format_; 124 125 // The special Audio Unit called AUHAL, which allows us to pass audio data 126 // directly from a microphone, through the HAL, and to our application. 127 // The AUHAL also enables selection of non default devices. 128 AudioUnit audio_unit_; 129 130 // The UID refers to the current input audio device. 131 AudioDeviceID input_device_id_; 132 133 // Provides a mechanism for encapsulating one or more buffers of audio data. 134 AudioBufferList audio_buffer_list_; 135 136 // Temporary storage for recorded data. The InputProc() renders into this 137 // array as soon as a frame of the desired buffer size has been recorded. 138 scoped_ptr<uint8[]> audio_data_buffer_; 139 140 // True after successfull Start(), false after successful Stop(). 141 bool started_; 142 143 // Fixed capture hardware latency in frames. 144 double hardware_latency_frames_; 145 146 // Delay due to the FIFO in bytes. 147 int fifo_delay_bytes_; 148 149 // The number of channels in each frame of audio data, which is used 150 // when querying the volume of each channel. 151 int number_of_channels_in_frame_; 152 153 // Accumulates recorded data packets until the requested size has been stored. 154 scoped_ptr<media::SeekableBuffer> fifo_; 155 156 // Intermediate storage of data from the FIFO before sending it to the 157 // client using the OnData() callback. 158 scoped_refptr<media::DataBuffer> data_; 159 160 // The client requests that the recorded data shall be delivered using 161 // OnData() callbacks where each callback contains this amount of bytes. 162 int requested_size_bytes_; 163 164 DISALLOW_COPY_AND_ASSIGN(AUAudioInputStream); 165 }; 166 167 } // namespace media 168 169 #endif // MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_ 170