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
;
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.
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.
31 // ............................................................................
32 // Theory of Operation:
34 // INPUT THREAD . OUTPUT THREAD
35 // +-----------------+ +------+ .
36 // | Input AudioUnit | --> | | .
37 // +-----------------+ | | .
40 // | | -----> | Varispeed |
44 // . OnMoreIOData() --> | Output AU |
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.
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
{
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
);
70 virtual ~AudioSynchronizedStream();
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
;
78 virtual void SetVolume(double volume
) OVERRIDE
;
79 virtual void GetVolume(double* volume
) OVERRIDE
;
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_
; }
90 OSStatus
CreateAudioUnits();
91 OSStatus
SetupInput(AudioDeviceID input_id
);
93 OSStatus
SetupOutput(AudioDeviceID output_id
);
94 OSStatus
SetupCallbacks();
95 OSStatus
SetupStreamFormats();
96 void AllocateInputData();
98 // Handlers for the AudioUnit callbacks.
99 OSStatus
HandleInputCallback(AudioUnitRenderActionFlags
* io_action_flags
,
100 const AudioTimeStamp
* time_stamp
,
102 UInt32 number_of_frames
,
103 AudioBufferList
* io_data
);
105 OSStatus
HandleVarispeedCallback(AudioUnitRenderActionFlags
* io_action_flags
,
106 const AudioTimeStamp
* time_stamp
,
108 UInt32 number_of_frames
,
109 AudioBufferList
* io_data
);
111 OSStatus
HandleOutputCallback(AudioUnitRenderActionFlags
* io_action_flags
,
112 const AudioTimeStamp
* time_stamp
,
114 UInt32 number_of_frames
,
115 AudioBufferList
* io_data
);
117 // AudioUnit callbacks.
118 static OSStatus
InputProc(void* user_data
,
119 AudioUnitRenderActionFlags
* io_action_flags
,
120 const AudioTimeStamp
* time_stamp
,
122 UInt32 number_of_frames
,
123 AudioBufferList
* io_data
);
125 static OSStatus
VarispeedProc(void* user_data
,
126 AudioUnitRenderActionFlags
* io_action_flags
,
127 const AudioTimeStamp
* time_stamp
,
129 UInt32 number_of_frames
,
130 AudioBufferList
* io_data
);
132 static OSStatus
OutputProc(void* user_data
,
133 AudioUnitRenderActionFlags
* io_action_flags
,
134 const AudioTimeStamp
* time_stamp
,
136 UInt32 number_of_frames
,
137 AudioBufferList
* io_data
);
140 AudioManagerMac
* manager_
;
142 // Client parameters.
143 AudioParameters params_
;
145 double input_sample_rate_
;
146 double output_sample_rate_
;
148 // Pointer to the object that will provide the audio samples.
149 AudioSourceCallback
* source_
;
151 // Values used in Open().
152 AudioDeviceID input_id_
;
153 AudioDeviceID output_id_
;
155 // The input AudioUnit renders its data here.
156 AudioBufferList
* input_buffer_list_
;
158 // Holds the actual data for |input_buffer_list_|.
159 scoped_ptr
<AudioBus
> input_bus_
;
161 // Used to overlay AudioBufferLists.
162 scoped_ptr
<AudioBus
> wrapper_bus_
;
164 class AudioDeviceInfo
{
167 : id_(kAudioDeviceUnknown
),
169 buffer_size_frames_(0) {}
170 void Initialize(AudioDeviceID inID
, bool isInput
);
171 bool IsInitialized() const { return id_
!= kAudioDeviceUnknown
; }
175 UInt32 buffer_size_frames_
;
178 AudioDeviceInfo input_info_
;
179 AudioDeviceInfo output_info_
;
181 // Used for input to output buffering.
184 // The optimal number of frames we'd like to keep in the FIFO at all times.
185 int target_fifo_frames_
;
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_
;
191 // A varispeed rate scalar which is calculated based on FIFO drift.
192 double fifo_rate_compensation_
;
195 AudioUnit input_unit_
;
196 AudioUnit varispeed_unit_
;
197 AudioUnit output_unit_
;
199 double first_input_time_
;
202 int hardware_buffer_size_
;
205 DISALLOW_COPY_AND_ASSIGN(AudioSynchronizedStream
);
210 #endif // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_