Chromium Code Reviews| 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_ |