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; Initialized()46 bool Initialized() const override { return initialized_; } 47 48 int32_t InitPlayout() override; PlayoutIsInitialized()49 bool PlayoutIsInitialized() const override { return play_is_initialized_; } 50 51 int32_t InitRecording() override; RecordingIsInitialized()52 bool RecordingIsInitialized() const override { return rec_is_initialized_; } 53 54 int32_t StartPlayout() override; 55 int32_t StopPlayout() override; Playing()56 bool Playing() const override { return playing_; } 57 58 int32_t StartRecording() override; 59 int32_t StopRecording() override; Recording()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; ClearPlayoutWarning()148 void ClearPlayoutWarning() override {} ClearPlayoutError()149 void ClearPlayoutError() override {} ClearRecordingWarning()150 void ClearRecordingWarning() override {} ClearRecordingError()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