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 #ifndef MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
      6 #define MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
      7 
      8 #include <AudioToolbox/AudioToolbox.h>
      9 #include <AudioUnit/AudioUnit.h>
     10 #include <CoreAudio/CoreAudio.h>
     11 
     12 #include "base/compiler_specific.h"
     13 #include "base/synchronization/lock.h"
     14 #include "media/audio/audio_io.h"
     15 #include "media/audio/audio_parameters.h"
     16 #include "media/base/audio_bus.h"
     17 #include "media/base/audio_fifo.h"
     18 
     19 namespace media {
     20 
     21 class AudioManagerMac;
     22 class ChannelMixer;
     23 
     24 // AudioSynchronizedStream allows arbitrary combinations of input and output
     25 // devices running off different clocks and using different drivers, with
     26 // potentially differing sample-rates.  It implements AudioOutputStream
     27 // and shuttles its synchronized I/O data using AudioSourceCallback.
     28 //
     29 // It is required to first acquire the native sample rate of the selected
     30 // output device and then use the same rate when creating this object.
     31 //
     32 // ............................................................................
     33 // Theory of Operation:
     34 //                                       .
     35 //      INPUT THREAD                     .             OUTPUT THREAD
     36 //   +-----------------+     +------+    .
     37 //   | Input AudioUnit | --> |      |    .
     38 //   +-----------------+     |      |    .
     39 //                           | FIFO |    .
     40 //                           |      |        +-----------+
     41 //                           |      | -----> | Varispeed |
     42 //                           |      |        +-----------+
     43 //                           +------+    .         |
     44 //                                       .         |              +-----------+
     45 //                                       .    OnMoreIOData() -->  | Output AU |
     46 //                                       .                        +-----------+
     47 //
     48 // The input AudioUnit's InputProc is called on one thread which feeds the
     49 // FIFO.  The output AudioUnit's OutputProc is called on a second thread
     50 // which pulls on the varispeed to get the current input data.  The varispeed
     51 // handles mismatches between input and output sample-rate and also clock drift
     52 // between the input and output drivers.  The varispeed consumes its data from
     53 // the FIFO and adjusts its rate dynamically according to the amount
     54 // of data buffered in the FIFO.  If the FIFO starts getting too much data
     55 // buffered then the varispeed will speed up slightly to compensate
     56 // and similarly if the FIFO doesn't have enough data buffered then the
     57 // varispeed will slow down slightly.
     58 //
     59 // Finally, once the input data is available then OnMoreIOData() is called
     60 // which is given this input, and renders the output which is finally sent
     61 // to the Output AudioUnit.
     62 class AudioSynchronizedStream : public AudioOutputStream {
     63  public:
     64   // The ctor takes all the usual parameters, plus |manager| which is the
     65   // the audio manager who is creating this object.
     66   AudioSynchronizedStream(AudioManagerMac* manager,
     67                           const AudioParameters& params,
     68                           AudioDeviceID input_id,
     69                           AudioDeviceID output_id);
     70 
     71   virtual ~AudioSynchronizedStream();
     72 
     73   // Implementation of AudioOutputStream.
     74   virtual bool Open() OVERRIDE;
     75   virtual void Close() OVERRIDE;
     76   virtual void Start(AudioSourceCallback* callback) OVERRIDE;
     77   virtual void Stop() OVERRIDE;
     78 
     79   virtual void SetVolume(double volume) OVERRIDE;
     80   virtual void GetVolume(double* volume) OVERRIDE;
     81 
     82   OSStatus SetInputDeviceAsCurrent(AudioDeviceID input_id);
     83   OSStatus SetOutputDeviceAsCurrent(AudioDeviceID output_id);
     84   AudioDeviceID GetInputDeviceID() { return input_info_.id_;  }
     85   AudioDeviceID GetOutputDeviceID() { return output_info_.id_; }
     86 
     87   bool IsRunning();
     88 
     89  private:
     90   // Initialization.
     91   OSStatus CreateAudioUnits();
     92   OSStatus SetupInput(AudioDeviceID input_id);
     93   OSStatus EnableIO();
     94   OSStatus SetupOutput(AudioDeviceID output_id);
     95   OSStatus SetupCallbacks();
     96   OSStatus SetupStreamFormats();
     97   void AllocateInputData();
     98 
     99   // Handlers for the AudioUnit callbacks.
    100   OSStatus HandleInputCallback(AudioUnitRenderActionFlags* io_action_flags,
    101                                const AudioTimeStamp* time_stamp,
    102                                UInt32 bus_number,
    103                                UInt32 number_of_frames,
    104                                AudioBufferList* io_data);
    105 
    106   OSStatus HandleVarispeedCallback(AudioUnitRenderActionFlags* io_action_flags,
    107                                    const AudioTimeStamp* time_stamp,
    108                                    UInt32 bus_number,
    109                                    UInt32 number_of_frames,
    110                                    AudioBufferList* io_data);
    111 
    112   OSStatus HandleOutputCallback(AudioUnitRenderActionFlags* io_action_flags,
    113                                 const AudioTimeStamp* time_stamp,
    114                                 UInt32 bus_number,
    115                                 UInt32 number_of_frames,
    116                                 AudioBufferList* io_data);
    117 
    118   // AudioUnit callbacks.
    119   static OSStatus InputProc(void* user_data,
    120                             AudioUnitRenderActionFlags* io_action_flags,
    121                             const AudioTimeStamp* time_stamp,
    122                             UInt32 bus_number,
    123                             UInt32 number_of_frames,
    124                             AudioBufferList* io_data);
    125 
    126   static OSStatus VarispeedProc(void* user_data,
    127                                 AudioUnitRenderActionFlags* io_action_flags,
    128                                 const AudioTimeStamp* time_stamp,
    129                                 UInt32 bus_number,
    130                                 UInt32 number_of_frames,
    131                                 AudioBufferList* io_data);
    132 
    133   static OSStatus OutputProc(void* user_data,
    134                              AudioUnitRenderActionFlags* io_action_flags,
    135                              const AudioTimeStamp* time_stamp,
    136                              UInt32 bus_number,
    137                              UInt32 number_of_frames,
    138                              AudioBufferList*  io_data);
    139 
    140   // Our creator.
    141   AudioManagerMac* manager_;
    142 
    143   // Client parameters.
    144   AudioParameters params_;
    145 
    146   double input_sample_rate_;
    147   double output_sample_rate_;
    148 
    149   // Pointer to the object that will provide the audio samples.
    150   AudioSourceCallback* source_;
    151 
    152   // Values used in Open().
    153   AudioDeviceID input_id_;
    154   AudioDeviceID output_id_;
    155 
    156   // The input AudioUnit renders its data here.
    157   AudioBufferList* input_buffer_list_;
    158 
    159   // Holds the actual data for |input_buffer_list_|.
    160   scoped_ptr<AudioBus> input_bus_;
    161 
    162   // Used to overlay AudioBufferLists.
    163   scoped_ptr<AudioBus> wrapper_bus_;
    164 
    165   class AudioDeviceInfo {
    166    public:
    167     AudioDeviceInfo()
    168         : id_(kAudioDeviceUnknown),
    169           is_input_(false),
    170           buffer_size_frames_(0) {}
    171     void Initialize(AudioDeviceID inID, bool isInput);
    172     bool IsInitialized() const { return id_ != kAudioDeviceUnknown; }
    173 
    174     AudioDeviceID id_;
    175     bool is_input_;
    176     UInt32 buffer_size_frames_;
    177   };
    178 
    179   AudioDeviceInfo input_info_;
    180   AudioDeviceInfo output_info_;
    181 
    182   // Used for input to output buffering.
    183   AudioFifo fifo_;
    184 
    185   // The optimal number of frames we'd like to keep in the FIFO at all times.
    186   int target_fifo_frames_;
    187 
    188   // A running average of the measured delta between actual number of frames
    189   // in the FIFO versus |target_fifo_frames_|.
    190   double average_delta_;
    191 
    192   // A varispeed rate scalar which is calculated based on FIFO drift.
    193   double fifo_rate_compensation_;
    194 
    195   // AudioUnits.
    196   AudioUnit input_unit_;
    197   AudioUnit varispeed_unit_;
    198   AudioUnit output_unit_;
    199 
    200   double first_input_time_;
    201 
    202   bool is_running_;
    203   int hardware_buffer_size_;
    204   int channels_;
    205 
    206   // Channel mixer used to transform mono to stereo data. It is only created
    207   // if the input_hardware_channels is mono.
    208   scoped_ptr<ChannelMixer> channel_mixer_;
    209   scoped_ptr<AudioBus> mixer_bus_;
    210 
    211   DISALLOW_COPY_AND_ASSIGN(AudioSynchronizedStream);
    212 };
    213 
    214 }  // namespace media
    215 
    216 #endif  // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
    217