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