Home | History | Annotate | Download | only in mac
      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