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/cancelable_callback.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/audio_block_fifo.h"
     49 
     50 namespace media {
     51 
     52 class AudioBus;
     53 class AudioManagerMac;
     54 class DataBuffer;
     55 
     56 class AUAudioInputStream : public AgcAudioStream<AudioInputStream> {
     57  public:
     58   // The ctor takes all the usual parameters, plus |manager| which is the
     59   // the audio manager who is creating this object.
     60   AUAudioInputStream(AudioManagerMac* manager,
     61                      const AudioParameters& input_params,
     62                      AudioDeviceID audio_device_id);
     63   // The dtor is typically called by the AudioManager only and it is usually
     64   // triggered by calling AudioInputStream::Close().
     65   virtual ~AUAudioInputStream();
     66 
     67   // Implementation of AudioInputStream.
     68   virtual bool Open() OVERRIDE;
     69   virtual void Start(AudioInputCallback* callback) OVERRIDE;
     70   virtual void Stop() OVERRIDE;
     71   virtual void Close() OVERRIDE;
     72   virtual double GetMaxVolume() OVERRIDE;
     73   virtual void SetVolume(double volume) OVERRIDE;
     74   virtual double GetVolume() OVERRIDE;
     75   virtual bool IsMuted() OVERRIDE;
     76 
     77   // Returns the current hardware sample rate for the default input device.
     78   MEDIA_EXPORT static int HardwareSampleRate();
     79 
     80   bool started() const { return started_; }
     81   AudioUnit audio_unit() { return audio_unit_; }
     82   AudioBufferList* audio_buffer_list() { return &audio_buffer_list_; }
     83 
     84  private:
     85   // AudioOutputUnit callback.
     86   static OSStatus InputProc(void* user_data,
     87                             AudioUnitRenderActionFlags* flags,
     88                             const AudioTimeStamp* time_stamp,
     89                             UInt32 bus_number,
     90                             UInt32 number_of_frames,
     91                             AudioBufferList* io_data);
     92 
     93   // Pushes recorded data to consumer of the input audio stream.
     94   OSStatus Provide(UInt32 number_of_frames, AudioBufferList* io_data,
     95                    const AudioTimeStamp* time_stamp);
     96 
     97   // Gets the fixed capture hardware latency and store it during initialization.
     98   // Returns 0 if not available.
     99   double GetHardwareLatency();
    100 
    101   // Gets the current capture delay value.
    102   double GetCaptureLatency(const AudioTimeStamp* input_time_stamp);
    103 
    104   // Gets the number of channels for a stream of audio data.
    105   int GetNumberOfChannelsFromStream();
    106 
    107   // Issues the OnError() callback to the |sink_|.
    108   void HandleError(OSStatus err);
    109 
    110   // Helper function to check if the volume control is avialable on specific
    111   // channel.
    112   bool IsVolumeSettableOnChannel(int channel);
    113 
    114   // Our creator, the audio manager needs to be notified when we close.
    115   AudioManagerMac* manager_;
    116 
    117   // Contains the desired number of audio frames in each callback.
    118   const size_t number_of_frames_;
    119 
    120   // Pointer to the object that will receive the recorded audio samples.
    121   AudioInputCallback* sink_;
    122 
    123   // Structure that holds the desired output format of the stream.
    124   // Note that, this format can differ from the device(=input) format.
    125   AudioStreamBasicDescription format_;
    126 
    127   // The special Audio Unit called AUHAL, which allows us to pass audio data
    128   // directly from a microphone, through the HAL, and to our application.
    129   // The AUHAL also enables selection of non default devices.
    130   AudioUnit audio_unit_;
    131 
    132   // The UID refers to the current input audio device.
    133   AudioDeviceID input_device_id_;
    134 
    135   // Provides a mechanism for encapsulating one or more buffers of audio data.
    136   AudioBufferList audio_buffer_list_;
    137 
    138   // Temporary storage for recorded data. The InputProc() renders into this
    139   // array as soon as a frame of the desired buffer size has been recorded.
    140   scoped_ptr<uint8[]> audio_data_buffer_;
    141 
    142   // True after successfull Start(), false after successful Stop().
    143   bool started_;
    144 
    145   // Fixed capture hardware latency in frames.
    146   double hardware_latency_frames_;
    147 
    148   // The number of channels in each frame of audio data, which is used
    149   // when querying the volume of each channel.
    150   int number_of_channels_in_frame_;
    151 
    152   // FIFO used to accumulates recorded data.
    153   media::AudioBlockFifo fifo_;
    154 
    155   // Used to defer Start() to workaround http://crbug.com/160920.
    156   base::CancelableClosure deferred_start_cb_;
    157 
    158   DISALLOW_COPY_AND_ASSIGN(AUAudioInputStream);
    159 };
    160 
    161 }  // namespace media
    162 
    163 #endif  // MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_
    164