• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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