Home | History | Annotate | Download | only in ios
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifndef WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_
     12 #define WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_
     13 
     14 #include <AudioUnit/AudioUnit.h>
     15 
     16 #include "webrtc/base/scoped_ptr.h"
     17 #include "webrtc/base/thread_checker.h"
     18 #include "webrtc/modules/audio_device/audio_device_generic.h"
     19 
     20 namespace webrtc {
     21 
     22 class FineAudioBuffer;
     23 
     24 // Implements full duplex 16-bit mono PCM audio support for iOS using a
     25 // Voice-Processing (VP) I/O audio unit in Core Audio. The VP I/O audio unit
     26 // supports audio echo cancellation. It also adds automatic gain control,
     27 // adjustment of voice-processing quality and muting.
     28 //
     29 // An instance must be created and destroyed on one and the same thread.
     30 // All supported public methods must also be called on the same thread.
     31 // A thread checker will RTC_DCHECK if any supported method is called on an
     32 // invalid thread.
     33 //
     34 // Recorded audio will be delivered on a real-time internal I/O thread in the
     35 // audio unit. The audio unit will also ask for audio data to play out on this
     36 // same thread.
     37 class AudioDeviceIOS : public AudioDeviceGeneric {
     38  public:
     39   AudioDeviceIOS();
     40   ~AudioDeviceIOS();
     41 
     42   void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
     43 
     44   int32_t Init() override;
     45   int32_t Terminate() override;
     46   bool Initialized() const override { return initialized_; }
     47 
     48   int32_t InitPlayout() override;
     49   bool PlayoutIsInitialized() const override { return play_is_initialized_; }
     50 
     51   int32_t InitRecording() override;
     52   bool RecordingIsInitialized() const override { return rec_is_initialized_; }
     53 
     54   int32_t StartPlayout() override;
     55   int32_t StopPlayout() override;
     56   bool Playing() const override { return playing_; }
     57 
     58   int32_t StartRecording() override;
     59   int32_t StopRecording() override;
     60   bool Recording() const override { return recording_; }
     61 
     62   int32_t SetLoudspeakerStatus(bool enable) override;
     63   int32_t GetLoudspeakerStatus(bool& enabled) const override;
     64 
     65   // These methods returns hard-coded delay values and not dynamic delay
     66   // estimates. The reason is that iOS supports a built-in AEC and the WebRTC
     67   // AEC will always be disabled in the Libjingle layer to avoid running two
     68   // AEC implementations at the same time. And, it saves resources to avoid
     69   // updating these delay values continuously.
     70   // TODO(henrika): it would be possible to mark these two methods as not
     71   // implemented since they are only called for A/V-sync purposes today and
     72   // A/V-sync is not supported on iOS. However, we avoid adding error messages
     73   // the log by using these dummy implementations instead.
     74   int32_t PlayoutDelay(uint16_t& delayMS) const override;
     75   int32_t RecordingDelay(uint16_t& delayMS) const override;
     76 
     77   // Native audio parameters stored during construction.
     78   // These methods are unique for the iOS implementation.
     79   int GetPlayoutAudioParameters(AudioParameters* params) const override;
     80   int GetRecordAudioParameters(AudioParameters* params) const override;
     81 
     82   // These methods are currently not fully implemented on iOS:
     83 
     84   // See audio_device_not_implemented.cc for trivial implementations.
     85   int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type,
     86                         uint16_t& sizeMS) const override;
     87   int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const;
     88   int32_t ResetAudioDevice() override;
     89   int32_t PlayoutIsAvailable(bool& available) override;
     90   int32_t RecordingIsAvailable(bool& available) override;
     91   int32_t SetAGC(bool enable) override;
     92   bool AGC() const override;
     93   int16_t PlayoutDevices() override;
     94   int16_t RecordingDevices() override;
     95   int32_t PlayoutDeviceName(uint16_t index,
     96                             char name[kAdmMaxDeviceNameSize],
     97                             char guid[kAdmMaxGuidSize]) override;
     98   int32_t RecordingDeviceName(uint16_t index,
     99                               char name[kAdmMaxDeviceNameSize],
    100                               char guid[kAdmMaxGuidSize]) override;
    101   int32_t SetPlayoutDevice(uint16_t index) override;
    102   int32_t SetPlayoutDevice(
    103       AudioDeviceModule::WindowsDeviceType device) override;
    104   int32_t SetRecordingDevice(uint16_t index) override;
    105   int32_t SetRecordingDevice(
    106       AudioDeviceModule::WindowsDeviceType device) override;
    107   int32_t SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight) override;
    108   int32_t WaveOutVolume(uint16_t& volumeLeft,
    109                         uint16_t& volumeRight) const override;
    110   int32_t InitSpeaker() override;
    111   bool SpeakerIsInitialized() const override;
    112   int32_t InitMicrophone() override;
    113   bool MicrophoneIsInitialized() const override;
    114   int32_t SpeakerVolumeIsAvailable(bool& available) override;
    115   int32_t SetSpeakerVolume(uint32_t volume) override;
    116   int32_t SpeakerVolume(uint32_t& volume) const override;
    117   int32_t MaxSpeakerVolume(uint32_t& maxVolume) const override;
    118   int32_t MinSpeakerVolume(uint32_t& minVolume) const override;
    119   int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const override;
    120   int32_t MicrophoneVolumeIsAvailable(bool& available) override;
    121   int32_t SetMicrophoneVolume(uint32_t volume) override;
    122   int32_t MicrophoneVolume(uint32_t& volume) const override;
    123   int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const override;
    124   int32_t MinMicrophoneVolume(uint32_t& minVolume) const override;
    125   int32_t MicrophoneVolumeStepSize(uint16_t& stepSize) const override;
    126   int32_t MicrophoneMuteIsAvailable(bool& available) override;
    127   int32_t SetMicrophoneMute(bool enable) override;
    128   int32_t MicrophoneMute(bool& enabled) const override;
    129   int32_t SpeakerMuteIsAvailable(bool& available) override;
    130   int32_t SetSpeakerMute(bool enable) override;
    131   int32_t SpeakerMute(bool& enabled) const override;
    132   int32_t MicrophoneBoostIsAvailable(bool& available) override;
    133   int32_t SetMicrophoneBoost(bool enable) override;
    134   int32_t MicrophoneBoost(bool& enabled) const override;
    135   int32_t StereoPlayoutIsAvailable(bool& available) override;
    136   int32_t SetStereoPlayout(bool enable) override;
    137   int32_t StereoPlayout(bool& enabled) const override;
    138   int32_t StereoRecordingIsAvailable(bool& available) override;
    139   int32_t SetStereoRecording(bool enable) override;
    140   int32_t StereoRecording(bool& enabled) const override;
    141   int32_t SetPlayoutBuffer(const AudioDeviceModule::BufferType type,
    142                            uint16_t sizeMS) override;
    143   int32_t CPULoad(uint16_t& load) const override;
    144   bool PlayoutWarning() const override;
    145   bool PlayoutError() const override;
    146   bool RecordingWarning() const override;
    147   bool RecordingError() const override;
    148   void ClearPlayoutWarning() override {}
    149   void ClearPlayoutError() override {}
    150   void ClearRecordingWarning() override {}
    151   void ClearRecordingError() override {}
    152 
    153  private:
    154   // Uses current |playout_parameters_| and |record_parameters_| to inform the
    155   // audio device buffer (ADB) about our internal audio parameters.
    156   void UpdateAudioDeviceBuffer();
    157 
    158   // Registers observers for the AVAudioSessionRouteChangeNotification and
    159   // AVAudioSessionInterruptionNotification notifications.
    160   void RegisterNotificationObservers();
    161   void UnregisterNotificationObservers();
    162 
    163   // Since the preferred audio parameters are only hints to the OS, the actual
    164   // values may be different once the AVAudioSession has been activated.
    165   // This method asks for the current hardware parameters and takes actions
    166   // if they should differ from what we have asked for initially. It also
    167   // defines |playout_parameters_| and |record_parameters_|.
    168   void SetupAudioBuffersForActiveAudioSession();
    169 
    170   // Creates a Voice-Processing I/O unit and configures it for full-duplex
    171   // audio. The selected stream format is selected to avoid internal resampling
    172   // and to match the 10ms callback rate for WebRTC as well as possible.
    173   // This method also initializes the created audio unit.
    174   bool SetupAndInitializeVoiceProcessingAudioUnit();
    175 
    176   // Restarts active audio streams using a new sample rate. Required when e.g.
    177   // a BT headset is enabled or disabled.
    178   bool RestartAudioUnitWithNewFormat(float sample_rate);
    179 
    180   // Activates our audio session, creates and initializes the voice-processing
    181   // audio unit and verifies that we got the preferred native audio parameters.
    182   bool InitPlayOrRecord();
    183 
    184   // Closes and deletes the voice-processing I/O unit.
    185   void ShutdownPlayOrRecord();
    186 
    187   // Helper method for destroying the existing audio unit.
    188   void DisposeAudioUnit();
    189 
    190   // Callback function called on a real-time priority I/O thread from the audio
    191   // unit. This method is used to signal that recorded audio is available.
    192   static OSStatus RecordedDataIsAvailable(
    193       void* in_ref_con,
    194       AudioUnitRenderActionFlags* io_action_flags,
    195       const AudioTimeStamp* time_stamp,
    196       UInt32 in_bus_number,
    197       UInt32 in_number_frames,
    198       AudioBufferList* io_data);
    199   OSStatus OnRecordedDataIsAvailable(
    200       AudioUnitRenderActionFlags* io_action_flags,
    201       const AudioTimeStamp* time_stamp,
    202       UInt32 in_bus_number,
    203       UInt32 in_number_frames);
    204 
    205   // Callback function called on a real-time priority I/O thread from the audio
    206   // unit. This method is used to provide audio samples to the audio unit.
    207   static OSStatus GetPlayoutData(void* in_ref_con,
    208                                  AudioUnitRenderActionFlags* io_action_flags,
    209                                  const AudioTimeStamp* time_stamp,
    210                                  UInt32 in_bus_number,
    211                                  UInt32 in_number_frames,
    212                                  AudioBufferList* io_data);
    213   OSStatus OnGetPlayoutData(AudioUnitRenderActionFlags* io_action_flags,
    214                             UInt32 in_number_frames,
    215                             AudioBufferList* io_data);
    216 
    217   // Ensures that methods are called from the same thread as this object is
    218   // created on.
    219   rtc::ThreadChecker thread_checker_;
    220 
    221   // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the
    222   // AudioDeviceModuleImpl class and called by AudioDeviceModuleImpl::Create().
    223   // The AudioDeviceBuffer is a member of the AudioDeviceModuleImpl instance
    224   // and therefore outlives this object.
    225   AudioDeviceBuffer* audio_device_buffer_;
    226 
    227   // Contains audio parameters (sample rate, #channels, buffer size etc.) for
    228   // the playout and recording sides. These structure is set in two steps:
    229   // first, native sample rate and #channels are defined in Init(). Next, the
    230   // audio session is activated and we verify that the preferred parameters
    231   // were granted by the OS. At this stage it is also possible to add a third
    232   // component to the parameters; the native I/O buffer duration.
    233   // A RTC_CHECK will be hit if we for some reason fail to open an audio session
    234   // using the specified parameters.
    235   AudioParameters playout_parameters_;
    236   AudioParameters record_parameters_;
    237 
    238   // The Voice-Processing I/O unit has the same characteristics as the
    239   // Remote I/O unit (supports full duplex low-latency audio input and output)
    240   // and adds AEC for for two-way duplex communication. It also adds AGC,
    241   // adjustment of voice-processing quality, and muting. Hence, ideal for
    242   // VoIP applications.
    243   AudioUnit vpio_unit_;
    244 
    245   // FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data
    246   // in chunks of 10ms. It then allows for this data to be pulled in
    247   // a finer or coarser granularity. I.e. interacting with this class instead
    248   // of directly with the AudioDeviceBuffer one can ask for any number of
    249   // audio data samples. Is also supports a similar scheme for the recording
    250   // side.
    251   // Example: native buffer size can be 128 audio frames at 16kHz sample rate.
    252   // WebRTC will provide 480 audio frames per 10ms but iOS asks for 128
    253   // in each callback (one every 8ms). This class can then ask for 128 and the
    254   // FineAudioBuffer will ask WebRTC for new data only when needed and also
    255   // cache non-utilized audio between callbacks. On the recording side, iOS
    256   // can provide audio data frames of size 128 and these are accumulated until
    257   // enough data to supply one 10ms call exists. This 10ms chunk is then sent
    258   // to WebRTC and the remaining part is stored.
    259   rtc::scoped_ptr<FineAudioBuffer> fine_audio_buffer_;
    260 
    261   // Extra audio buffer to be used by the playout side for rendering audio.
    262   // The buffer size is given by FineAudioBuffer::RequiredBufferSizeBytes().
    263   rtc::scoped_ptr<SInt8[]> playout_audio_buffer_;
    264 
    265   // Provides a mechanism for encapsulating one or more buffers of audio data.
    266   // Only used on the recording side.
    267   AudioBufferList audio_record_buffer_list_;
    268 
    269   // Temporary storage for recorded data. AudioUnitRender() renders into this
    270   // array as soon as a frame of the desired buffer size has been recorded.
    271   rtc::scoped_ptr<SInt8[]> record_audio_buffer_;
    272 
    273   // Set to 1 when recording is active and 0 otherwise.
    274   volatile int recording_;
    275 
    276   // Set to 1 when playout is active and 0 otherwise.
    277   volatile int playing_;
    278 
    279   // Set to true after successful call to Init(), false otherwise.
    280   bool initialized_;
    281 
    282   // Set to true after successful call to InitRecording(), false otherwise.
    283   bool rec_is_initialized_;
    284 
    285   // Set to true after successful call to InitPlayout(), false otherwise.
    286   bool play_is_initialized_;
    287 
    288   // Audio interruption observer instance.
    289   void* audio_interruption_observer_;
    290   void* route_change_observer_;
    291 
    292   // Contains the audio data format specification for a stream of audio.
    293   AudioStreamBasicDescription application_format_;
    294 };
    295 
    296 }  // namespace webrtc
    297 
    298 #endif  // WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_
    299