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

Unified 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 side-by-side diff with in-line comments
Download patch
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,210 @@
+// 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.
+
+#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>
+
+#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_fifo.h"
+
+namespace media {
+
+class AudioManagerMac;
+
+// 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
+// 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.
+//
+// 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.
+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;
+
+ virtual void SetVolume(double volume) OVERRIDE;
+ 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 AllocateInputData();
+
+ // Handlers for the AudioUnit callbacks.
+ OSStatus HandleInputCallback(AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* time_stamp,
+ UInt32 bus_number,
+ UInt32 number_of_frames,
+ AudioBufferList* io_data);
+
+ OSStatus HandleVarispeedCallback(AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* time_stamp,
+ UInt32 bus_number,
+ UInt32 number_of_frames,
+ AudioBufferList* io_data);
+
+ OSStatus HandleOutputCallback(AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* time_stamp,
+ UInt32 bus_number,
+ UInt32 number_of_frames,
+ AudioBufferList* io_data);
+
+ // 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_;
+
+ // Client parameters.
+ AudioParameters params_;
+
+ double input_sample_rate_;
+ double output_sample_rate_;
+
+ // Pointer to the object that will provide the audio samples.
+ AudioSourceCallback* source_;
+
+ // Values used in Open().
+ AudioDeviceID input_id_;
+ AudioDeviceID output_id_;
+
+ // The input AudioUnit renders its data here.
+ AudioBufferList* input_buffer_list_;
+
+ // Holds the actual data for |input_buffer_list_|.
+ scoped_ptr<AudioBus> input_bus_;
+
+ // Used to overlay AudioBufferLists.
+ scoped_ptr<AudioBus> wrapper_bus_;
+
+ class AudioDeviceInfo {
+ public:
+ AudioDeviceInfo()
+ : id_(kAudioDeviceUnknown),
+ is_input_(false),
+ buffer_size_frames_(0) {}
+ void Initialize(AudioDeviceID inID, bool isInput);
+ bool IsInitialized() const { return id_ != kAudioDeviceUnknown; }
+
+ AudioDeviceID id_;
+ bool is_input_;
+ UInt32 buffer_size_frames_;
+ };
+
+ AudioDeviceInfo input_info_;
+ AudioDeviceInfo output_info_;
+
+ // Used for input to output buffering.
+ AudioFifo fifo_;
+
+ // The optimal number of frames we'd like to keep in the FIFO at all times.
+ int target_fifo_frames_;
+
+ // A running average of the measured delta between actual number of frames
+ // in the FIFO versus |target_fifo_frames_|.
+ double average_delta_;
+
+ // A varispeed rate scalar which is calculated based on FIFO drift.
+ double fifo_rate_compensation_;
+
+ // AudioUnits.
+ AudioUnit input_unit_;
+ AudioUnit varispeed_unit_;
+ AudioUnit output_unit_;
+
+ double first_input_time_;
+
+ bool is_running_;
+ int hardware_buffer_size_;
+ int channels_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioSynchronizedStream);
+};
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_MAC_AUDIO_SYNCHRONIZED_MAC_H_

Powered by Google App Engine
This is Rietveld 408576698