Index: media/audio/mac/audio_synchronized_mac.h |
=================================================================== |
--- media/audio/mac/audio_synchronized_mac.h (revision 0) |
+++ media/audio/mac/audio_synchronized_mac.h (revision 0) |
@@ -0,0 +1,177 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+// |
+// AudioSynchronizedStream allows arbitrary combinations of input and output |
+// devices running off different clocks and using different drivers, with |
+// potentially differing sample-rates. It implements AudioOutputStream |
+// and shuttles its synchronized I/O data using AudioSourceCallback. |
+// |
+// It is required to first acquire the native sample rate of the selected |
+// output device and then use the same rate when creating this object. |
+// |
+ |
+// ............................................................................ |
+// Theory of Operation: |
+// . |
+// INPUT THREAD . OUTPUT THREAD |
+// +-----------------+ +------+ . |
+// | Input AudioUnit | --> | | . |
+// +-----------------+ | | . |
+// | FIFO | . |
+// | | +-----------+ |
+// | | -----> | Varispeed | |
+// | | +-----------+ |
+// +------+ . | |
+// . | +-----------+ |
+// . OnMoreIOData() --> | Output AU | |
+// . +-----------+ |
+// |
+// The input AudioUnit's InputProc is called on one thread which feeds the |
+// FIFO. The output AudioUnit's OutputProc is called on a second thread |
+// which pulls on the varispeed to get the current input data. The varispeed |
+// handles mismatches between input and output sample-rate and also clock drift |
no longer working on chromium
2012/09/12 09:11:56
So the FIFO is thread safe?
Chris Rogers
2012/09/13 01:03:05
Good catch! The AudioFifo is currently *not* thre
|
+// between the input and output drivers. The varispeed consumes its data from |
+// the FIFO and adjusts its rate dynamically according to the amount |
+// of data buffered in the FIFO. If the FIFO starts getting too much data |
+// buffered then the varispeed will speed up slightly to compensate |
+// and similarly if the FIFO doesn't have enough data buffered then the |
+// varispeed will slow down slightly. |
scherkus (not reviewing)
2012/09/12 14:05:29
can you move comment to be next to class?
Chris Rogers
2012/09/13 01:03:05
Done.
|
+// |
+// Finally, once the input data is available then OnMoreIOData() is called |
+// which is given this input, and renders the output which is finally sent |
+// to the Output AudioUnit. |
+ |
+#ifndef MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_ |
+#define MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_ |
+ |
+#include <AudioToolbox/AudioToolbox.h> |
+#include <AudioUnit/AudioUnit.h> |
+#include <CoreAudio/CoreAudio.h> |
+ |
+#define CHROME 0 |
+ |
+#if CHROME |
no longer working on chromium
2012/09/12 09:11:56
what is this?
Chris Rogers
2012/09/13 01:03:05
Sorry, this is temporary which I need for testing
|
+ #include "base/compiler_specific.h" |
+ #include "media/audio/audio_io.h" |
+ #include "media/audio/audio_parameters.h" |
+ #include "media/base/audio_fifo.h" |
+#else |
+ #include "audio_parameters.h" |
+ #include "AudioFIFO.h" |
+#endif |
+ |
+namespace media { |
+ |
+class AudioManagerMac; |
+ |
+class AudioSynchronizedStream : public AudioOutputStream { |
+ public: |
+ // The ctor takes all the usual parameters, plus |manager| which is the |
+ // the audio manager who is creating this object. |
+ AudioSynchronizedStream(AudioManagerMac* manager, |
+ const AudioParameters& params, |
+ AudioDeviceID input_id, |
+ AudioDeviceID output_id); |
+ |
+ virtual ~AudioSynchronizedStream(); |
+ |
+ // Implementation of AudioOutputStream. |
+ virtual bool Open() OVERRIDE; |
+ virtual void Close() OVERRIDE; |
+ virtual void Start(AudioSourceCallback* callback) OVERRIDE; |
+ virtual void Stop() OVERRIDE; |
+ |
+ // TODO(crogers): |
+ // implement - or remove SetVolume()/GetVolume() from AudioOutputStream. |
scherkus (not reviewing)
2012/09/12 14:05:29
agreed :)
|
+ virtual void SetVolume(double volume) OVERRIDE {} |
scherkus (not reviewing)
2012/09/12 14:05:29
de-inline virtual methods
Chris Rogers
2012/09/13 01:03:05
Done.
|
+ virtual void GetVolume(double* volume) OVERRIDE {} |
+ |
+ OSStatus SetInputDeviceAsCurrent(AudioDeviceID input_id); |
+ OSStatus SetOutputDeviceAsCurrent(AudioDeviceID output_id); |
+ AudioDeviceID GetInputDeviceID() { return input_info_.id_; } |
+ AudioDeviceID GetOutputDeviceID() { return output_info_.id_; } |
+ |
+ bool IsRunning(); |
+ |
+ private: |
+ // Initialization. |
+ OSStatus CreateAudioUnits(); |
+ OSStatus SetupInput(AudioDeviceID input_id); |
+ OSStatus EnableIO(); |
+ OSStatus SetupOutput(AudioDeviceID output_id); |
+ OSStatus SetupCallbacks(); |
+ OSStatus SetupStreamFormats(); |
+ |
+ void ComputeThruOffset(); |
+ |
+ // AudioUnit callbacks. |
+ static OSStatus InputProc(void* user_data, |
+ AudioUnitRenderActionFlags* io_action_flags, |
+ const AudioTimeStamp* time_stamp, |
+ UInt32 bus_number, |
+ UInt32 number_of_frames, |
+ AudioBufferList* io_data); |
+ |
+ static OSStatus VarispeedProc(void* user_data, |
+ AudioUnitRenderActionFlags* io_action_flags, |
+ const AudioTimeStamp* time_stamp, |
+ UInt32 bus_number, |
+ UInt32 number_of_frames, |
+ AudioBufferList* io_data); |
+ |
+ static OSStatus OutputProc(void* user_data, |
+ AudioUnitRenderActionFlags* io_action_flags, |
+ const AudioTimeStamp* time_stamp, |
+ UInt32 bus_number, |
+ UInt32 number_of_frames, |
+ AudioBufferList* io_data); |
+ |
+ // Our creator. |
+ AudioManagerMac* manager_; |
+ |
+ // Pointer to the object that will provide the audio samples. |
+ AudioSourceCallback* source_; |
+ |
+ // Values used in Open(). |
+ AudioDeviceID input_id_; |
+ AudioDeviceID output_id_; |
+ |
+ AudioBufferList* input_buffer_; |
+ |
+ struct AudioDeviceInfo { |
no longer working on chromium
2012/09/12 09:11:56
it contains member functions in this struct, we sh
Chris Rogers
2012/09/13 01:03:05
Done.
|
+ AudioDeviceInfo() : id_(kAudioDeviceUnknown) {} |
+ void Initialize(AudioDeviceID inID, bool isInput); |
+ bool IsInitialized() const { return id_ != kAudioDeviceUnknown; } |
+ |
+ AudioDeviceID id_; |
+ bool is_input_; |
+ UInt32 buffer_size_frames_; |
no longer working on chromium
2012/09/12 09:11:56
initialize these values in the constructor.
Chris Rogers
2012/09/13 01:03:05
Done.
|
+ }; |
+ |
+ AudioDeviceInfo input_info_; |
+ AudioDeviceInfo output_info_; |
+ |
+ // Used for input to output buffering. |
+ AudioFifo fifo_; |
+ bool is_fifo_initialized_; |
+ double fifo_rate_compensation_; |
+ double output_sample_rate_; |
+ |
+ // AudioUnits |
scherkus (not reviewing)
2012/09/12 14:05:29
period
Chris Rogers
2012/09/13 01:03:05
Done.
|
+ AudioUnit input_unit_; |
+ AudioUnit varispeed_unit_; |
+ AudioUnit output_unit_; |
+ |
+ // Initial latency estimation. |
+ Float64 first_input_time_; |
scherkus (not reviewing)
2012/09/12 14:05:29
are we required to use these types vs. double?
Chris Rogers
2012/09/13 01:03:05
You're right - not in this case -- switched to dou
|
+ Float64 first_output_time_; |
+ Float64 in_to_out_sample_offset_; |
+ |
+ bool is_running_; |
+ UInt32 hardware_frame_size_; |
+}; |
scherkus (not reviewing)
2012/09/12 14:05:29
DISALLOW etc
Chris Rogers
2012/09/13 01:03:05
Done.
|
+ |
+} // namespace media |
+ |
+#endif // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_ |