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 AUDIO_DEVICE_AUDIO_DEVICE_MAC_H_ 12 #define AUDIO_DEVICE_AUDIO_DEVICE_MAC_H_ 13 14 #include <AudioToolbox/AudioConverter.h> 15 #include <CoreAudio/CoreAudio.h> 16 #include <mach/semaphore.h> 17 18 #include <atomic> 19 #include <memory> 20 21 #include "absl/strings/string_view.h" 22 #include "modules/audio_device/audio_device_generic.h" 23 #include "modules/audio_device/mac/audio_mixer_manager_mac.h" 24 #include "rtc_base/event.h" 25 #include "rtc_base/logging.h" 26 #include "rtc_base/platform_thread.h" 27 #include "rtc_base/synchronization/mutex.h" 28 #include "rtc_base/thread_annotations.h" 29 30 struct PaUtilRingBuffer; 31 32 namespace webrtc { 33 34 const uint32_t N_REC_SAMPLES_PER_SEC = 48000; 35 const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000; 36 37 const uint32_t N_REC_CHANNELS = 1; // default is mono recording 38 const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout 39 const uint32_t N_DEVICE_CHANNELS = 64; 40 41 const int kBufferSizeMs = 10; 42 43 const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES = 44 N_REC_SAMPLES_PER_SEC * kBufferSizeMs / 1000; 45 const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES = 46 N_PLAY_SAMPLES_PER_SEC * kBufferSizeMs / 1000; 47 48 const int N_BLOCKS_IO = 2; 49 const int N_BUFFERS_IN = 2; // Must be at least N_BLOCKS_IO. 50 const int N_BUFFERS_OUT = 3; // Must be at least N_BLOCKS_IO. 51 52 const uint32_t TIMER_PERIOD_MS = 2 * 10 * N_BLOCKS_IO * 1000000; 53 54 const uint32_t REC_BUF_SIZE_IN_SAMPLES = 55 ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN; 56 const uint32_t PLAY_BUF_SIZE_IN_SAMPLES = 57 ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT; 58 59 const int kGetMicVolumeIntervalMs = 1000; 60 61 class AudioDeviceMac : public AudioDeviceGeneric { 62 public: 63 AudioDeviceMac(); 64 ~AudioDeviceMac(); 65 66 // Retrieve the currently utilized audio layer 67 virtual int32_t ActiveAudioLayer( 68 AudioDeviceModule::AudioLayer& audioLayer) const; 69 70 // Main initializaton and termination 71 virtual InitStatus Init() RTC_LOCKS_EXCLUDED(mutex_); 72 virtual int32_t Terminate() RTC_LOCKS_EXCLUDED(mutex_); 73 virtual bool Initialized() const; 74 75 // Device enumeration 76 virtual int16_t PlayoutDevices(); 77 virtual int16_t RecordingDevices(); 78 virtual int32_t PlayoutDeviceName(uint16_t index, 79 char name[kAdmMaxDeviceNameSize], 80 char guid[kAdmMaxGuidSize]); 81 virtual int32_t RecordingDeviceName(uint16_t index, 82 char name[kAdmMaxDeviceNameSize], 83 char guid[kAdmMaxGuidSize]); 84 85 // Device selection 86 virtual int32_t SetPlayoutDevice(uint16_t index) RTC_LOCKS_EXCLUDED(mutex_); 87 virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device); 88 virtual int32_t SetRecordingDevice(uint16_t index); 89 virtual int32_t SetRecordingDevice( 90 AudioDeviceModule::WindowsDeviceType device); 91 92 // Audio transport initialization 93 virtual int32_t PlayoutIsAvailable(bool& available); 94 virtual int32_t InitPlayout() RTC_LOCKS_EXCLUDED(mutex_); 95 virtual bool PlayoutIsInitialized() const; 96 virtual int32_t RecordingIsAvailable(bool& available); 97 virtual int32_t InitRecording() RTC_LOCKS_EXCLUDED(mutex_); 98 virtual bool RecordingIsInitialized() const; 99 100 // Audio transport control 101 virtual int32_t StartPlayout() RTC_LOCKS_EXCLUDED(mutex_); 102 virtual int32_t StopPlayout() RTC_LOCKS_EXCLUDED(mutex_); 103 virtual bool Playing() const; 104 virtual int32_t StartRecording() RTC_LOCKS_EXCLUDED(mutex_); 105 virtual int32_t StopRecording() RTC_LOCKS_EXCLUDED(mutex_); 106 virtual bool Recording() const; 107 108 // Audio mixer initialization 109 virtual int32_t InitSpeaker() RTC_LOCKS_EXCLUDED(mutex_); 110 virtual bool SpeakerIsInitialized() const; 111 virtual int32_t InitMicrophone() RTC_LOCKS_EXCLUDED(mutex_); 112 virtual bool MicrophoneIsInitialized() const; 113 114 // Speaker volume controls 115 virtual int32_t SpeakerVolumeIsAvailable(bool& available) 116 RTC_LOCKS_EXCLUDED(mutex_); 117 virtual int32_t SetSpeakerVolume(uint32_t volume); 118 virtual int32_t SpeakerVolume(uint32_t& volume) const; 119 virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const; 120 virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const; 121 122 // Microphone volume controls 123 virtual int32_t MicrophoneVolumeIsAvailable(bool& available) 124 RTC_LOCKS_EXCLUDED(mutex_); 125 virtual int32_t SetMicrophoneVolume(uint32_t volume); 126 virtual int32_t MicrophoneVolume(uint32_t& volume) const; 127 virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const; 128 virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const; 129 130 // Microphone mute control 131 virtual int32_t MicrophoneMuteIsAvailable(bool& available) 132 RTC_LOCKS_EXCLUDED(mutex_); 133 virtual int32_t SetMicrophoneMute(bool enable); 134 virtual int32_t MicrophoneMute(bool& enabled) const; 135 136 // Speaker mute control 137 virtual int32_t SpeakerMuteIsAvailable(bool& available) 138 RTC_LOCKS_EXCLUDED(mutex_); 139 virtual int32_t SetSpeakerMute(bool enable); 140 virtual int32_t SpeakerMute(bool& enabled) const; 141 142 // Stereo support 143 virtual int32_t StereoPlayoutIsAvailable(bool& available) 144 RTC_LOCKS_EXCLUDED(mutex_); 145 virtual int32_t SetStereoPlayout(bool enable); 146 virtual int32_t StereoPlayout(bool& enabled) const; 147 virtual int32_t StereoRecordingIsAvailable(bool& available); 148 virtual int32_t SetStereoRecording(bool enable); 149 virtual int32_t StereoRecording(bool& enabled) const; 150 151 // Delay information and control 152 virtual int32_t PlayoutDelay(uint16_t& delayMS) const; 153 154 virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) 155 RTC_LOCKS_EXCLUDED(mutex_); 156 157 private: 158 int32_t InitSpeakerLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 159 int32_t InitMicrophoneLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 160 161 virtual int32_t MicrophoneIsAvailable(bool& available) 162 RTC_LOCKS_EXCLUDED(mutex_); 163 virtual int32_t MicrophoneIsAvailableLocked(bool& available) 164 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 165 virtual int32_t SpeakerIsAvailable(bool& available) 166 RTC_LOCKS_EXCLUDED(mutex_); 167 virtual int32_t SpeakerIsAvailableLocked(bool& available) 168 RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); 169 170 static void AtomicSet32(int32_t* theValue, int32_t newValue); 171 static int32_t AtomicGet32(int32_t* theValue); 172 173 static void logCAMsg(rtc::LoggingSeverity sev, 174 const char* msg, 175 const char* err); 176 177 int32_t GetNumberDevices(AudioObjectPropertyScope scope, 178 AudioDeviceID scopedDeviceIds[], 179 uint32_t deviceListLength); 180 181 int32_t GetDeviceName(AudioObjectPropertyScope scope, 182 uint16_t index, 183 rtc::ArrayView<char> name); 184 185 int32_t InitDevice(uint16_t userDeviceIndex, 186 AudioDeviceID& deviceId, 187 bool isInput); 188 189 // Always work with our preferred playout format inside VoE. 190 // Then convert the output to the OS setting using an AudioConverter. 191 OSStatus SetDesiredPlayoutFormat(); 192 193 static OSStatus objectListenerProc( 194 AudioObjectID objectId, 195 UInt32 numberAddresses, 196 const AudioObjectPropertyAddress addresses[], 197 void* clientData); 198 199 OSStatus implObjectListenerProc(AudioObjectID objectId, 200 UInt32 numberAddresses, 201 const AudioObjectPropertyAddress addresses[]); 202 203 int32_t HandleDeviceChange(); 204 205 int32_t HandleStreamFormatChange(AudioObjectID objectId, 206 AudioObjectPropertyAddress propertyAddress); 207 208 int32_t HandleDataSourceChange(AudioObjectID objectId, 209 AudioObjectPropertyAddress propertyAddress); 210 211 int32_t HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress); 212 213 static OSStatus deviceIOProc(AudioDeviceID device, 214 const AudioTimeStamp* now, 215 const AudioBufferList* inputData, 216 const AudioTimeStamp* inputTime, 217 AudioBufferList* outputData, 218 const AudioTimeStamp* outputTime, 219 void* clientData); 220 221 static OSStatus outConverterProc( 222 AudioConverterRef audioConverter, 223 UInt32* numberDataPackets, 224 AudioBufferList* data, 225 AudioStreamPacketDescription** dataPacketDescription, 226 void* userData); 227 228 static OSStatus inDeviceIOProc(AudioDeviceID device, 229 const AudioTimeStamp* now, 230 const AudioBufferList* inputData, 231 const AudioTimeStamp* inputTime, 232 AudioBufferList* outputData, 233 const AudioTimeStamp* outputTime, 234 void* clientData); 235 236 static OSStatus inConverterProc( 237 AudioConverterRef audioConverter, 238 UInt32* numberDataPackets, 239 AudioBufferList* data, 240 AudioStreamPacketDescription** dataPacketDescription, 241 void* inUserData); 242 243 OSStatus implDeviceIOProc(const AudioBufferList* inputData, 244 const AudioTimeStamp* inputTime, 245 AudioBufferList* outputData, 246 const AudioTimeStamp* outputTime) 247 RTC_LOCKS_EXCLUDED(mutex_); 248 249 OSStatus implOutConverterProc(UInt32* numberDataPackets, 250 AudioBufferList* data); 251 252 OSStatus implInDeviceIOProc(const AudioBufferList* inputData, 253 const AudioTimeStamp* inputTime) 254 RTC_LOCKS_EXCLUDED(mutex_); 255 256 OSStatus implInConverterProc(UInt32* numberDataPackets, 257 AudioBufferList* data); 258 259 static void RunCapture(void*); 260 static void RunRender(void*); 261 bool CaptureWorkerThread(); 262 bool RenderWorkerThread(); 263 264 bool KeyPressed(); 265 266 AudioDeviceBuffer* _ptrAudioBuffer; 267 268 Mutex mutex_; 269 270 rtc::Event _stopEventRec; 271 rtc::Event _stopEvent; 272 273 // Only valid/running between calls to StartRecording and StopRecording. 274 rtc::PlatformThread capture_worker_thread_; 275 276 // Only valid/running between calls to StartPlayout and StopPlayout. 277 rtc::PlatformThread render_worker_thread_; 278 279 AudioMixerManagerMac _mixerManager; 280 281 uint16_t _inputDeviceIndex; 282 uint16_t _outputDeviceIndex; 283 AudioDeviceID _inputDeviceID; 284 AudioDeviceID _outputDeviceID; 285 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 286 AudioDeviceIOProcID _inDeviceIOProcID; 287 AudioDeviceIOProcID _deviceIOProcID; 288 #endif 289 bool _inputDeviceIsSpecified; 290 bool _outputDeviceIsSpecified; 291 292 uint8_t _recChannels; 293 uint8_t _playChannels; 294 295 Float32* _captureBufData; 296 SInt16* _renderBufData; 297 298 SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES]; 299 300 bool _initialized; 301 bool _isShutDown; 302 bool _recording; 303 bool _playing; 304 bool _recIsInitialized; 305 bool _playIsInitialized; 306 307 // Atomically set varaibles 308 std::atomic<int32_t> _renderDeviceIsAlive; 309 std::atomic<int32_t> _captureDeviceIsAlive; 310 311 bool _twoDevices; 312 bool _doStop; // For play if not shared device or play+rec if shared device 313 bool _doStopRec; // For rec if not shared device 314 bool _macBookPro; 315 bool _macBookProPanRight; 316 317 AudioConverterRef _captureConverter; 318 AudioConverterRef _renderConverter; 319 320 AudioStreamBasicDescription _outStreamFormat; 321 AudioStreamBasicDescription _outDesiredFormat; 322 AudioStreamBasicDescription _inStreamFormat; 323 AudioStreamBasicDescription _inDesiredFormat; 324 325 uint32_t _captureLatencyUs; 326 uint32_t _renderLatencyUs; 327 328 // Atomically set variables 329 mutable std::atomic<int32_t> _captureDelayUs; 330 mutable std::atomic<int32_t> _renderDelayUs; 331 332 int32_t _renderDelayOffsetSamples; 333 334 PaUtilRingBuffer* _paCaptureBuffer; 335 PaUtilRingBuffer* _paRenderBuffer; 336 337 semaphore_t _renderSemaphore; 338 semaphore_t _captureSemaphore; 339 340 int _captureBufSizeSamples; 341 int _renderBufSizeSamples; 342 343 // Typing detection 344 // 0x5c is key "9", after that comes function keys. 345 bool prev_key_state_[0x5d]; 346 }; 347 348 } // namespace webrtc 349 350 #endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_ 351