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