RTCAudioDevice.h 12 KB

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