Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: media/audio/mac/audio_synchronized_mac.h

Issue 10909185: Add Mac OS X synchronized audio I/O back-end (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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_fifo.h"
17
18 namespace media {
19
20 class AudioManagerMac;
21
22 // AudioSynchronizedStream allows arbitrary combinations of input and output
23 // devices running off different clocks and using different drivers, with
24 // potentially differing sample-rates. It implements AudioOutputStream
25 // and shuttles its synchronized I/O data using AudioSourceCallback.
26 //
27 // It is required to first acquire the native sample rate of the selected
28 // output device and then use the same rate when creating this object.
29 //
30 // ............................................................................
31 // Theory of Operation:
32 // .
33 // INPUT THREAD . OUTPUT THREAD
34 // +-----------------+ +------+ .
35 // | Input AudioUnit | --> | | .
36 // +-----------------+ | | .
37 // | FIFO | .
38 // | | +-----------+
39 // | | -----> | Varispeed |
40 // | | +-----------+
41 // +------+ . |
42 // . | +-----------+
43 // . OnMoreIOData() --> | Output AU |
44 // . +-----------+
45 //
46 // The input AudioUnit's InputProc is called on one thread which feeds the
47 // FIFO. The output AudioUnit's OutputProc is called on a second thread
48 // which pulls on the varispeed to get the current input data. The varispeed
49 // handles mismatches between input and output sample-rate and also clock drift
50 // between the input and output drivers. The varispeed consumes its data from
51 // the FIFO and adjusts its rate dynamically according to the amount
52 // of data buffered in the FIFO. If the FIFO starts getting too much data
53 // buffered then the varispeed will speed up slightly to compensate
54 // and similarly if the FIFO doesn't have enough data buffered then the
55 // varispeed will slow down slightly.
56 //
57 // Finally, once the input data is available then OnMoreIOData() is called
58 // which is given this input, and renders the output which is finally sent
59 // to the Output AudioUnit.
60 //
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 void ComputeThruOffset();
99
100 // Handlers for the AudioUnit callbacks.
101 OSStatus HandleInputCallback(AudioUnitRenderActionFlags* io_action_flags,
102 const AudioTimeStamp* time_stamp,
103 UInt32 bus_number,
104 UInt32 number_of_frames,
105 AudioBufferList* io_data);
106
107 OSStatus HandleVarispeedCallback(AudioUnitRenderActionFlags* io_action_flags,
108 const AudioTimeStamp* time_stamp,
109 UInt32 bus_number,
110 UInt32 number_of_frames,
111 AudioBufferList* io_data);
112
113 OSStatus HandleOutputCallback(AudioUnitRenderActionFlags* io_action_flags,
114 const AudioTimeStamp* time_stamp,
115 UInt32 bus_number,
116 UInt32 number_of_frames,
117 AudioBufferList* io_data);
118
119 // AudioUnit callbacks.
120 static OSStatus InputProc(void* user_data,
121 AudioUnitRenderActionFlags* io_action_flags,
122 const AudioTimeStamp* time_stamp,
123 UInt32 bus_number,
124 UInt32 number_of_frames,
125 AudioBufferList* io_data);
126
127 static OSStatus VarispeedProc(void* user_data,
128 AudioUnitRenderActionFlags* io_action_flags,
129 const AudioTimeStamp* time_stamp,
130 UInt32 bus_number,
131 UInt32 number_of_frames,
132 AudioBufferList* io_data);
133
134 static OSStatus OutputProc(void* user_data,
135 AudioUnitRenderActionFlags* io_action_flags,
136 const AudioTimeStamp* time_stamp,
137 UInt32 bus_number,
138 UInt32 number_of_frames,
139 AudioBufferList* io_data);
140
141 // Our creator.
142 AudioManagerMac* manager_;
143
144 // Pointer to the object that will provide the audio samples.
145 AudioSourceCallback* source_;
146
147 // Values used in Open().
148 AudioDeviceID input_id_;
149 AudioDeviceID output_id_;
150
151 // The input AudioUnit renders its data here.
152 AudioBufferList* input_data_;
153
154 class AudioDeviceInfo {
155 public:
156 AudioDeviceInfo()
157 : id_(kAudioDeviceUnknown),
scherkus (not reviewing) 2012/09/13 13:06:03 should be indented by two more spaces
Chris Rogers 2012/09/15 00:06:08 Done.
158 is_input_(false),
159 buffer_size_frames_(0) {}
160 void Initialize(AudioDeviceID inID, bool isInput);
161 bool IsInitialized() const { return id_ != kAudioDeviceUnknown; }
162
163 AudioDeviceID id_;
164 bool is_input_;
165 UInt32 buffer_size_frames_;
166 };
167
168 AudioDeviceInfo input_info_;
169 AudioDeviceInfo output_info_;
170
171 // Used for input to output buffering.
172 AudioFifo fifo_;
173
174 // Protect FIFO access.
175 // TODO(crogers): the correct solution is to make AudioFifo thread-safe.
176 // This lock is just a stop-gap, and is not good since it can cause glitches
177 // if the lock is contended.
178 base::Lock fifo_lock_;
179
180 bool is_fifo_initialized_;
181 double fifo_rate_compensation_;
182 double output_sample_rate_;
183
184 // AudioUnits.
185 AudioUnit input_unit_;
186 AudioUnit varispeed_unit_;
187 AudioUnit output_unit_;
188
189 // Initial latency estimation.
190 double first_input_time_;
191 double first_output_time_;
192 double in_to_out_sample_offset_;
193
194 bool is_running_;
195 UInt32 hardware_buffer_size_;
scherkus (not reviewing) 2012/09/13 13:06:03 any chance we can swap UInt32 for int, size_t, uin
Chris Rogers 2012/09/15 00:06:08 Removed here and in a few other places. But there
196 int channels_;
197
198 DISALLOW_COPY_AND_ASSIGN(AudioSynchronizedStream);
199 };
200
201 } // namespace media
202
203 #endif // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698