| 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_
 | 
| 
 |