- add sources.
[platform/framework/web/crosswalk.git] / src / media / audio / mac / audio_synchronized_mac.h
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_