15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of AudioInputStream for Mac OS X using the special AUHAL
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// input Audio Unit present in OS 10.4 and later.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The AUHAL input Audio Unit is for low-latency audio I/O.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Overview of operation:
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - An object of AUAudioInputStream is created by the AudioManager
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   factory: audio_man->MakeAudioInputStream().
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Next some thread will call Open(), at that point the underlying
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   AUHAL output Audio Unit is created and configured.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Then some thread will call Start(sink).
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Then the Audio Unit is started which creates its own thread which
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   periodically will provide the sink with more data as buffers are being
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   produced/recorded.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - At some point some thread will call Stop(), which we handle by directly
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   stopping the AUHAL output Audio Unit.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The same thread that called stop will call Close() where we cleanup
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   and notify the audio manager, which likely will destroy this object.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation notes:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - It is recommended to first acquire the native sample rate of the default
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   input device and then use the same rate when creating this object.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Use AUAudioInputStream::HardwareSampleRate() to retrieve the sample rate.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Calling Close() also leads to self destruction.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The latency consists of two parts:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   1) Hardware latency, which includes Audio Unit latency, audio device
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      latency;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   2) The delay between the actual recording instant and the time when the
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      data packet is provided as a callback.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <AudioUnit/AudioUnit.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CoreAudio/CoreAudio.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/cancelable_callback.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/audio/agc_audio_stream.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)class AudioBus;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioManagerMac;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DataBuffer;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class AUAudioInputStream : public AgcAudioStream<AudioInputStream> {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ctor takes all the usual parameters, plus |manager| which is the
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the audio manager who is creating this object.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AUAudioInputStream(AudioManagerMac* manager,
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const AudioParameters& input_params,
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     const AudioParameters& output_params,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     AudioDeviceID audio_device_id);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The dtor is typically called by the AudioManager only and it is usually
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // triggered by calling AudioInputStream::Close().
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AUAudioInputStream();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of AudioInputStream.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Open() OVERRIDE;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start(AudioInputCallback* callback) OVERRIDE;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Stop() OVERRIDE;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Close() OVERRIDE;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual double GetMaxVolume() OVERRIDE;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetVolume(double volume) OVERRIDE;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual double GetVolume() OVERRIDE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current hardware sample rate for the default input device.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MEDIA_EXPORT static int HardwareSampleRate();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool started() const { return started_; }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioUnit audio_unit() { return audio_unit_; }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioBufferList* audio_buffer_list() { return &audio_buffer_list_; }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AudioOutputUnit callback.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static OSStatus InputProc(void* user_data,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            AudioUnitRenderActionFlags* flags,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const AudioTimeStamp* time_stamp,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            UInt32 bus_number,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            UInt32 number_of_frames,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            AudioBufferList* io_data);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pushes recorded data to consumer of the input audio stream.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSStatus Provide(UInt32 number_of_frames, AudioBufferList* io_data,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const AudioTimeStamp* time_stamp);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the fixed capture hardware latency and store it during initialization.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns 0 if not available.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double GetHardwareLatency();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the current capture delay value.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double GetCaptureLatency(const AudioTimeStamp* input_time_stamp);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the number of channels for a stream of audio data.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetNumberOfChannelsFromStream();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Issues the OnError() callback to the |sink_|.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleError(OSStatus err);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper function to check if the volume control is avialable on specific
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // channel.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsVolumeSettableOnChannel(int channel);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our creator, the audio manager needs to be notified when we close.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioManagerMac* manager_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Contains the desired number of audio frames in each callback.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t number_of_frames_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pointer to the object that will receive the recorded audio samples.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioInputCallback* sink_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Structure that holds the desired output format of the stream.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that, this format can differ from the device(=input) format.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioStreamBasicDescription format_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The special Audio Unit called AUHAL, which allows us to pass audio data
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directly from a microphone, through the HAL, and to our application.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The AUHAL also enables selection of non default devices.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioUnit audio_unit_;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The UID refers to the current input audio device.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioDeviceID input_device_id_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Provides a mechanism for encapsulating one or more buffers of audio data.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioBufferList audio_buffer_list_;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Temporary storage for recorded data. The InputProc() renders into this
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // array as soon as a frame of the desired buffer size has been recorded.
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> audio_data_buffer_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True after successfull Start(), false after successful Stop().
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool started_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fixed capture hardware latency in frames.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double hardware_latency_frames_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Delay due to the FIFO in bytes.
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int fifo_delay_bytes_;
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of channels in each frame of audio data, which is used
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when querying the volume of each channel.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number_of_channels_in_frame_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Accumulates recorded data packets until the requested size has been stored.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<media::SeekableBuffer> fifo_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   // Intermediate storage of data from the FIFO before sending it to the
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   // client using the OnData() callback.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<media::DataBuffer> data_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The client requests that the recorded data shall be delivered using
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnData() callbacks where each callback contains this amount of bytes.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int requested_size_bytes_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Used to defer Start() to workaround http://crbug.com/160920.
1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::CancelableClosure deferred_start_cb_;
1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1696d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Extra audio bus used for storage of deinterleaved data for the OnData
1706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // callback.
1716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  scoped_ptr<media::AudioBus> audio_bus_;
1726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AUAudioInputStream);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // MEDIA_AUDIO_MAC_AUDIO_LOW_LATENCY_INPUT_MAC_H_
179