audio_device_mac.h (12348B)
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(LoggingSeverity sev, const char* msg, const char* err); 174 175 int32_t GetNumberDevices(AudioObjectPropertyScope scope, 176 AudioDeviceID scopedDeviceIds[], 177 uint32_t deviceListLength); 178 179 int32_t GetDeviceName(AudioObjectPropertyScope scope, 180 uint16_t index, 181 ArrayView<char> name); 182 183 int32_t InitDevice(uint16_t userDeviceIndex, 184 AudioDeviceID& deviceId, 185 bool isInput); 186 187 // Always work with our preferred playout format inside VoE. 188 // Then convert the output to the OS setting using an AudioConverter. 189 OSStatus SetDesiredPlayoutFormat(); 190 191 static OSStatus objectListenerProc( 192 AudioObjectID objectId, 193 UInt32 numberAddresses, 194 const AudioObjectPropertyAddress addresses[], 195 void* clientData); 196 197 OSStatus implObjectListenerProc(AudioObjectID objectId, 198 UInt32 numberAddresses, 199 const AudioObjectPropertyAddress addresses[]); 200 201 int32_t HandleDeviceChange(); 202 203 int32_t HandleStreamFormatChange(AudioObjectID objectId, 204 AudioObjectPropertyAddress propertyAddress); 205 206 int32_t HandleDataSourceChange(AudioObjectID objectId, 207 AudioObjectPropertyAddress propertyAddress); 208 209 int32_t HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress); 210 211 static OSStatus deviceIOProc(AudioDeviceID device, 212 const AudioTimeStamp* now, 213 const AudioBufferList* inputData, 214 const AudioTimeStamp* inputTime, 215 AudioBufferList* outputData, 216 const AudioTimeStamp* outputTime, 217 void* clientData); 218 219 static OSStatus outConverterProc( 220 AudioConverterRef audioConverter, 221 UInt32* numberDataPackets, 222 AudioBufferList* data, 223 AudioStreamPacketDescription** dataPacketDescription, 224 void* userData); 225 226 static OSStatus inDeviceIOProc(AudioDeviceID device, 227 const AudioTimeStamp* now, 228 const AudioBufferList* inputData, 229 const AudioTimeStamp* inputTime, 230 AudioBufferList* outputData, 231 const AudioTimeStamp* outputTime, 232 void* clientData); 233 234 static OSStatus inConverterProc( 235 AudioConverterRef audioConverter, 236 UInt32* numberDataPackets, 237 AudioBufferList* data, 238 AudioStreamPacketDescription** dataPacketDescription, 239 void* inUserData); 240 241 OSStatus implDeviceIOProc(const AudioBufferList* inputData, 242 const AudioTimeStamp* inputTime, 243 AudioBufferList* outputData, 244 const AudioTimeStamp* outputTime) 245 RTC_LOCKS_EXCLUDED(mutex_); 246 247 OSStatus implOutConverterProc(UInt32* numberDataPackets, 248 AudioBufferList* data); 249 250 OSStatus implInDeviceIOProc(const AudioBufferList* inputData, 251 const AudioTimeStamp* inputTime) 252 RTC_LOCKS_EXCLUDED(mutex_); 253 254 OSStatus implInConverterProc(UInt32* numberDataPackets, 255 AudioBufferList* data); 256 257 static void RunCapture(void*); 258 static void RunRender(void*); 259 bool CaptureWorkerThread(); 260 bool RenderWorkerThread(); 261 262 bool KeyPressed(); 263 264 AudioDeviceBuffer* _ptrAudioBuffer; 265 266 Mutex mutex_; 267 268 Event _stopEventRec; 269 Event _stopEvent; 270 271 // Only valid/running between calls to StartRecording and StopRecording. 272 PlatformThread capture_worker_thread_; 273 274 // Only valid/running between calls to StartPlayout and StopPlayout. 275 PlatformThread render_worker_thread_; 276 277 AudioMixerManagerMac _mixerManager; 278 279 uint16_t _inputDeviceIndex; 280 uint16_t _outputDeviceIndex; 281 AudioDeviceID _inputDeviceID; 282 AudioDeviceID _outputDeviceID; 283 AudioDeviceIOProcID _inDeviceIOProcID; 284 AudioDeviceIOProcID _deviceIOProcID; 285 bool _inputDeviceIsSpecified; 286 bool _outputDeviceIsSpecified; 287 288 uint8_t _recChannels; 289 uint8_t _playChannels; 290 291 Float32* _captureBufData; 292 SInt16* _renderBufData; 293 294 SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES]; 295 296 bool _initialized; 297 bool _isShutDown; 298 bool _recording; 299 bool _playing; 300 bool _recIsInitialized; 301 bool _playIsInitialized; 302 303 // Atomically set varaibles 304 std::atomic<int32_t> _renderDeviceIsAlive; 305 std::atomic<int32_t> _captureDeviceIsAlive; 306 307 bool _twoDevices; 308 bool _doStop; // For play if not shared device or play+rec if shared device 309 bool _doStopRec; // For rec if not shared device 310 bool _macBookPro; 311 bool _macBookProPanRight; 312 313 AudioConverterRef _captureConverter; 314 AudioConverterRef _renderConverter; 315 316 AudioStreamBasicDescription _outStreamFormat; 317 AudioStreamBasicDescription _outDesiredFormat; 318 AudioStreamBasicDescription _inStreamFormat; 319 AudioStreamBasicDescription _inDesiredFormat; 320 321 uint32_t _captureLatencyUs; 322 uint32_t _renderLatencyUs; 323 324 // Atomically set variables 325 mutable std::atomic<int32_t> _captureDelayUs; 326 mutable std::atomic<int32_t> _renderDelayUs; 327 328 int32_t _renderDelayOffsetSamples; 329 330 PaUtilRingBuffer* _paCaptureBuffer; 331 PaUtilRingBuffer* _paRenderBuffer; 332 333 semaphore_t _renderSemaphore; 334 semaphore_t _captureSemaphore; 335 336 int _captureBufSizeSamples; 337 int _renderBufSizeSamples; 338 339 // Typing detection 340 // 0x5c is key "9", after that comes function keys. 341 bool prev_key_state_[0x5d]; 342 }; 343 344 } // namespace webrtc 345 346 #endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_