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