xref: /aosp_15_r20/external/webrtc/sdk/objc/components/audio/RTCAudioDevice.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2022 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 #import <AudioUnit/AudioUnit.h>
12 #import <Foundation/Foundation.h>
13 
14 #import "RTCMacros.h"
15 
16 NS_ASSUME_NONNULL_BEGIN
17 
18 typedef OSStatus (^RTC_OBJC_TYPE(RTCAudioDeviceGetPlayoutDataBlock))(
19     AudioUnitRenderActionFlags *_Nonnull actionFlags,
20     const AudioTimeStamp *_Nonnull timestamp,
21     NSInteger inputBusNumber,
22     UInt32 frameCount,
23     AudioBufferList *_Nonnull outputData);
24 
25 typedef OSStatus (^RTC_OBJC_TYPE(RTCAudioDeviceRenderRecordedDataBlock))(
26     AudioUnitRenderActionFlags *_Nonnull actionFlags,
27     const AudioTimeStamp *_Nonnull timestamp,
28     NSInteger inputBusNumber,
29     UInt32 frameCount,
30     AudioBufferList *_Nonnull inputData,
31     void *_Nullable renderContext);
32 
33 typedef OSStatus (^RTC_OBJC_TYPE(RTCAudioDeviceDeliverRecordedDataBlock))(
34     AudioUnitRenderActionFlags *_Nonnull actionFlags,
35     const AudioTimeStamp *_Nonnull timestamp,
36     NSInteger inputBusNumber,
37     UInt32 frameCount,
38     const AudioBufferList *_Nullable inputData,
39     void *_Nullable renderContext,
40     NS_NOESCAPE RTC_OBJC_TYPE(RTCAudioDeviceRenderRecordedDataBlock) _Nullable renderBlock);
41 
42 /**
43  * Delegate object provided by native ADM during RTCAudioDevice initialization.
44  * Provides blocks to poll playback audio samples from native ADM and to feed
45  * recorded audio samples into native ADM.
46  */
47 RTC_OBJC_EXPORT @protocol RTC_OBJC_TYPE
48 (RTCAudioDeviceDelegate)<NSObject>
49     /**
50      * Implementation of RTCAudioSource should call this block to feed recorded PCM (16-bit integer)
51      * into native ADM. Stereo data is expected to be interleaved starting with the left channel.
52      * Either `inputData` with pre-filled audio data must be provided during block
53      * call or `renderBlock` must be provided which must fill provided audio buffer with recorded
54      * samples.
55      *
56      * NOTE: Implementation of RTCAudioDevice is expected to call the block on the same thread until
57      * `notifyAudioInterrupted` is called. When `notifyAudioInterrupted` is called implementation
58      * can call the block on a different thread.
59      */
60     @property(readonly, nonnull)
61         RTC_OBJC_TYPE(RTCAudioDeviceDeliverRecordedDataBlock) deliverRecordedData;
62 
63 /**
64  * Provides input sample rate preference as it preferred by native ADM.
65  */
66 @property(readonly) double preferredInputSampleRate;
67 
68 /**
69  * Provides input IO buffer duration preference as it preferred by native ADM.
70  */
71 @property(readonly) NSTimeInterval preferredInputIOBufferDuration;
72 
73 /**
74  * Provides output sample rate preference as it preferred by native ADM.
75  */
76 @property(readonly) double preferredOutputSampleRate;
77 
78 /**
79  * Provides output IO buffer duration preference as it preferred by native ADM.
80  */
81 @property(readonly) NSTimeInterval preferredOutputIOBufferDuration;
82 
83 /**
84  * Implementation of RTCAudioDevice should call this block to request PCM (16-bit integer)
85  * from native ADM to play. Stereo data is interleaved starting with the left channel.
86  *
87  * NOTE: Implementation of RTCAudioDevice is expected to invoke of this block on the
88  * same thread until `notifyAudioInterrupted` is called. When `notifyAudioInterrupted` is called
89  * implementation can call the block from a different thread.
90  */
91 @property(readonly, nonnull) RTC_OBJC_TYPE(RTCAudioDeviceGetPlayoutDataBlock) getPlayoutData;
92 
93 /**
94  * Notifies native ADM that some of the audio input parameters of RTCAudioDevice like
95  * samle rate and/or IO buffer duration and/or IO latency had possibly changed.
96  * Native ADM will adjust its audio input buffer to match current parameters of audio device.
97  *
98  * NOTE: Must be called within block executed via `dispatchAsync` or `dispatchSync`.
99  */
100 - (void)notifyAudioInputParametersChange;
101 
102 /**
103  * Notifies native ADM that some of the audio output parameters of RTCAudioDevice like
104  * samle rate and/or IO buffer duration and/or IO latency had possibly changed.
105  * Native ADM will adjust its audio output buffer to match current parameters of audio device.
106  *
107  * NOTE: Must be called within block executed via `dispatchAsync` or `dispatchSync`.
108  */
109 - (void)notifyAudioOutputParametersChange;
110 
111 /**
112  * Notifies native ADM that audio input is interrupted and further audio playout
113  * and recording might happen on a different thread.
114  *
115  * NOTE: Must be called within block executed via `dispatchAsync` or `dispatchSync`.
116  */
117 - (void)notifyAudioInputInterrupted;
118 
119 /**
120  * Notifies native ADM that audio output is interrupted and further audio playout
121  * and recording might happen on a different thread.
122  *
123  * NOTE: Must be called within block executed via `dispatchAsync` or `dispatchSync`.
124  */
125 - (void)notifyAudioOutputInterrupted;
126 
127 /**
128  * Asynchronously execute block of code within the context of
129  * thread which owns native ADM.
130  *
131  * NOTE: Intended to be used to invoke `notifyAudioInputParametersChange`,
132  * `notifyAudioOutputParametersChange`, `notifyAudioInputInterrupted`,
133  * `notifyAudioOutputInterrupted` on native ADM thread.
134  * Also could be used by `RTCAudioDevice` implementation to tie
135  * mutations of underlying audio objects (AVAudioEngine, AudioUnit, etc)
136  * to the native ADM thread. Could be useful to handle events like audio route change, which
137  * could lead to audio parameters change.
138  */
139 - (void)dispatchAsync:(dispatch_block_t)block;
140 
141 /**
142  * Synchronously execute block of code within the context of
143  * thread which owns native ADM. Allows reentrancy.
144  *
145  * NOTE: Intended to be used to invoke `notifyAudioInputParametersChange`,
146  * `notifyAudioOutputParametersChange`, `notifyAudioInputInterrupted`,
147  * `notifyAudioOutputInterrupted` on native ADM thread and make sure
148  * aforementioned is completed before `dispatchSync` returns. Could be useful
149  * when implementation of `RTCAudioDevice` tie mutation to underlying audio objects (AVAudioEngine,
150  * AudioUnit, etc) to own thread to satisfy requirement that native ADM audio parameters
151  * must be kept in sync with current audio parameters before audio is actually played or recorded.
152  */
153 - (void)dispatchSync:(dispatch_block_t)block;
154 
155 @end
156 
157 /**
158  * Protocol to abstract platform specific ways to implement playback and recording.
159  *
160  * NOTE: All the members of protocol are called by native ADM from the same thread
161  * between calls to `initializeWithDelegate` and `terminate`.
162  * NOTE: Implementation is fully responsible for configuring application's AVAudioSession.
163  * An example implementation of RTCAudioDevice: https://github.com/mstyura/RTCAudioDevice
164  * TODO(yura.yaroshevich): Implement custom RTCAudioDevice for AppRTCMobile demo app.
165  */
166 RTC_OBJC_EXPORT @protocol RTC_OBJC_TYPE
167 (RTCAudioDevice)<NSObject>
168 
169     /**
170      * Indicates current sample rate of audio recording. Changes to this property
171      * must be notified back to native ADM via `-[RTCAudioDeviceDelegate
172      * notifyAudioParametersChange]`.
173      */
174     @property(readonly) double deviceInputSampleRate;
175 
176 /**
177  * Indicates current size of record buffer. Changes to this property
178  * must be notified back to native ADM via `-[RTCAudioDeviceDelegate notifyAudioParametersChange]`.
179  */
180 @property(readonly) NSTimeInterval inputIOBufferDuration;
181 
182 /**
183  * Indicates current number of recorded audio channels. Changes to this property
184  * must be notified back to native ADM via `-[RTCAudioDeviceDelegate notifyAudioParametersChange]`.
185  */
186 @property(readonly) NSInteger inputNumberOfChannels;
187 
188 /**
189  * Indicates current input latency
190  */
191 @property(readonly) NSTimeInterval inputLatency;
192 
193 /**
194  * Indicates current sample rate of audio playback. Changes to this property
195  * must be notified back to native ADM via `-[RTCAudioDeviceDelegate notifyAudioParametersChange]`.
196  */
197 @property(readonly) double deviceOutputSampleRate;
198 
199 /**
200  * Indicates current size of playback buffer. Changes to this property
201  * must be notified back to native ADM via `-[RTCAudioDeviceDelegate notifyAudioParametersChange]`.
202  */
203 @property(readonly) NSTimeInterval outputIOBufferDuration;
204 
205 /**
206  * Indicates current number of playback audio channels. Changes to this property
207  * must be notified back to WebRTC via `[RTCAudioDeviceDelegate notifyAudioParametersChange]`.
208  */
209 @property(readonly) NSInteger outputNumberOfChannels;
210 
211 /**
212  * Indicates current output latency
213  */
214 @property(readonly) NSTimeInterval outputLatency;
215 
216 /**
217  * Indicates if invocation of `initializeWithDelegate` required before usage of RTCAudioDevice.
218  * YES indicates that `initializeWithDelegate` was called earlier without subsequent call to
219  * `terminate`. NO indicates that either `initializeWithDelegate` not called or `terminate` called.
220  */
221 @property(readonly) BOOL isInitialized;
222 
223 /**
224  * Initializes RTCAudioDevice with RTCAudioDeviceDelegate.
225  * Implementation must return YES if RTCAudioDevice initialized successfully and NO otherwise.
226  */
227 - (BOOL)initializeWithDelegate:(id<RTC_OBJC_TYPE(RTCAudioDeviceDelegate)>)delegate;
228 
229 /**
230  * De-initializes RTCAudioDevice. Implementation should forget about `delegate` provided in
231  * `initializeWithDelegate`.
232  */
233 - (BOOL)terminateDevice;
234 
235 /**
236  * Property to indicate if `initializePlayout` call required before invocation of `startPlayout`.
237  * YES indicates that `initializePlayout` was successfully invoked earlier or not necessary,
238  * NO indicates that `initializePlayout` invocation required.
239  */
240 @property(readonly) BOOL isPlayoutInitialized;
241 
242 /**
243  * Prepares RTCAudioDevice to play audio.
244  * Called by native ADM before invocation of `startPlayout`.
245  * Implementation is expected to return YES in case of successful playout initialization and NO
246  * otherwise.
247  */
248 - (BOOL)initializePlayout;
249 
250 /**
251  * Property to indicate if RTCAudioDevice should be playing according to
252  * earlier calls of `startPlayout` and `stopPlayout`.
253  */
254 @property(readonly) BOOL isPlaying;
255 
256 /**
257  * Method is called when native ADM wants to play audio.
258  * Implementation is expected to return YES if playback start request
259  * successfully handled and NO otherwise.
260  */
261 - (BOOL)startPlayout;
262 
263 /**
264  * Method is called when native ADM no longer needs to play audio.
265  * Implementation is expected to return YES if playback stop request
266  * successfully handled and NO otherwise.
267  */
268 - (BOOL)stopPlayout;
269 
270 /**
271  * Property to indicate if `initializeRecording` call required before usage of `startRecording`.
272  * YES indicates that `initializeRecording` was successfully invoked earlier or not necessary,
273  * NO indicates that `initializeRecording` invocation required.
274  */
275 @property(readonly) BOOL isRecordingInitialized;
276 
277 /**
278  * Prepares RTCAudioDevice to record audio.
279  * Called by native ADM before invocation of `startRecording`.
280  * Implementation may use this method to prepare resources required to record audio.
281  * Implementation is expected to return YES in case of successful record initialization and NO
282  * otherwise.
283  */
284 - (BOOL)initializeRecording;
285 
286 /**
287  * Property to indicate if RTCAudioDevice should record audio according to
288  * earlier calls to `startRecording` and `stopRecording`.
289  */
290 @property(readonly) BOOL isRecording;
291 
292 /**
293  * Method is called when native ADM wants to record audio.
294  * Implementation is expected to return YES if recording start request
295  * successfully handled and NO otherwise.
296  */
297 - (BOOL)startRecording;
298 
299 /**
300  * Method is called when native ADM no longer needs to record audio.
301  * Implementation is expected to return YES if recording stop request
302  * successfully handled and NO otherwise.
303  */
304 - (BOOL)stopRecording;
305 
306 @end
307 
308 NS_ASSUME_NONNULL_END
309