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.
5 #ifndef MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
6 #define MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
8 #include <AudioToolbox/AudioToolbox.h>
9 #include <AudioUnit/AudioUnit.h>
10 #include <CoreAudio/CoreAudio.h>
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"
21 class AudioManagerMac
;
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.
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.
32 // ............................................................................
33 // Theory of Operation:
35 // INPUT THREAD . OUTPUT THREAD
36 // +-----------------+ +------+ .
37 // | Input AudioUnit | --> | | .
38 // +-----------------+ | | .
41 // | | -----> | Varispeed |
45 // . OnMoreIOData() --> | Output AU |
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.
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
{
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
);
71 virtual ~AudioSynchronizedStream();
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
;
79 virtual void SetVolume(double volume
) OVERRIDE
;
80 virtual void GetVolume(double* volume
) OVERRIDE
;
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_
; }
91 OSStatus
CreateAudioUnits();
92 OSStatus
SetupInput(AudioDeviceID input_id
);
94 OSStatus
SetupOutput(AudioDeviceID output_id
);
95 OSStatus
SetupCallbacks();
96 OSStatus
SetupStreamFormats();
97 void AllocateInputData();
99 // Handlers for the AudioUnit callbacks.
100 OSStatus
HandleInputCallback(AudioUnitRenderActionFlags
* io_action_flags
,
101 const AudioTimeStamp
* time_stamp
,
103 UInt32 number_of_frames
,
104 AudioBufferList
* io_data
);
106 OSStatus
HandleVarispeedCallback(AudioUnitRenderActionFlags
* io_action_flags
,
107 const AudioTimeStamp
* time_stamp
,
109 UInt32 number_of_frames
,
110 AudioBufferList
* io_data
);
112 OSStatus
HandleOutputCallback(AudioUnitRenderActionFlags
* io_action_flags
,
113 const AudioTimeStamp
* time_stamp
,
115 UInt32 number_of_frames
,
116 AudioBufferList
* io_data
);
118 // AudioUnit callbacks.
119 static OSStatus
InputProc(void* user_data
,
120 AudioUnitRenderActionFlags
* io_action_flags
,
121 const AudioTimeStamp
* time_stamp
,
123 UInt32 number_of_frames
,
124 AudioBufferList
* io_data
);
126 static OSStatus
VarispeedProc(void* user_data
,
127 AudioUnitRenderActionFlags
* io_action_flags
,
128 const AudioTimeStamp
* time_stamp
,
130 UInt32 number_of_frames
,
131 AudioBufferList
* io_data
);
133 static OSStatus
OutputProc(void* user_data
,
134 AudioUnitRenderActionFlags
* io_action_flags
,
135 const AudioTimeStamp
* time_stamp
,
137 UInt32 number_of_frames
,
138 AudioBufferList
* io_data
);
141 AudioManagerMac
* manager_
;
143 // Client parameters.
144 AudioParameters params_
;
146 double input_sample_rate_
;
147 double output_sample_rate_
;
149 // Pointer to the object that will provide the audio samples.
150 AudioSourceCallback
* source_
;
152 // Values used in Open().
153 AudioDeviceID input_id_
;
154 AudioDeviceID output_id_
;
156 // The input AudioUnit renders its data here.
157 AudioBufferList
* input_buffer_list_
;
159 // Holds the actual data for |input_buffer_list_|.
160 scoped_ptr
<AudioBus
> input_bus_
;
162 // Used to overlay AudioBufferLists.
163 scoped_ptr
<AudioBus
> wrapper_bus_
;
165 class AudioDeviceInfo
{
168 : id_(kAudioDeviceUnknown
),
170 buffer_size_frames_(0) {}
171 void Initialize(AudioDeviceID inID
, bool isInput
);
172 bool IsInitialized() const { return id_
!= kAudioDeviceUnknown
; }
176 UInt32 buffer_size_frames_
;
179 AudioDeviceInfo input_info_
;
180 AudioDeviceInfo output_info_
;
182 // Used for input to output buffering.
185 // The optimal number of frames we'd like to keep in the FIFO at all times.
186 int target_fifo_frames_
;
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_
;
192 // A varispeed rate scalar which is calculated based on FIFO drift.
193 double fifo_rate_compensation_
;
196 AudioUnit input_unit_
;
197 AudioUnit varispeed_unit_
;
198 AudioUnit output_unit_
;
200 double first_input_time_
;
203 int hardware_buffer_size_
;
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_
;
211 DISALLOW_COPY_AND_ASSIGN(AudioSynchronizedStream
);
216 #endif // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_