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
20namespace webrtc {
21
22class 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.
37class 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