xref: /aosp_15_r20/external/webrtc/modules/audio_device/mac/audio_device_mac.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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