react-native-audio-api 0.8.3 → 0.9.0-nightly-96a5bcd-20251007

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/README.md +40 -39
  2. package/RNAudioAPI.podspec +17 -12
  3. package/android/build.gradle +44 -4
  4. package/android/src/main/cpp/audioapi/CMakeLists.txt +65 -0
  5. package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +29 -1
  6. package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +14 -0
  7. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +7 -1
  8. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +6 -1
  9. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +1 -1
  10. package/android/src/main/cpp/audioapi/android/core/NativeAudioRecorder.hpp +36 -0
  11. package/android/src/main/cpp/audioapi/android/core/{AudioDecoder.cpp → utils/AudioDecoder.cpp} +79 -75
  12. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +11 -1
  13. package/android/src/main/java/com/swmansion/audioapi/core/NativeAudioRecorder.kt +24 -0
  14. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +15 -2
  15. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +129 -38
  16. package/common/cpp/audioapi/HostObjects/AudioContextHostObject.cpp +57 -0
  17. package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +6 -46
  18. package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.cpp +70 -6
  19. package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +10 -66
  20. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp +105 -0
  21. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +17 -91
  22. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +262 -6
  23. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +26 -241
  24. package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.cpp +70 -0
  25. package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.h +6 -50
  26. package/common/cpp/audioapi/HostObjects/WorkletNodeHostObject.h +18 -0
  27. package/common/cpp/audioapi/HostObjects/WorkletProcessingNodeHostObject.h +18 -0
  28. package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.cpp +148 -0
  29. package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.h +37 -0
  30. package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +92 -0
  31. package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.h +29 -0
  32. package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.cpp +20 -0
  33. package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.h +19 -0
  34. package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.cpp +21 -0
  35. package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.h +21 -0
  36. package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp +41 -0
  37. package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h +28 -0
  38. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +69 -0
  39. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +33 -0
  40. package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.cpp +73 -0
  41. package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.h +29 -0
  42. package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +94 -0
  43. package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h +46 -0
  44. package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp +60 -0
  45. package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.h +25 -0
  46. package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +152 -0
  47. package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.h +37 -0
  48. package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.cpp +52 -0
  49. package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.h +25 -0
  50. package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.cpp +19 -0
  51. package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.h +21 -0
  52. package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.cpp +55 -0
  53. package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.h +27 -0
  54. package/common/cpp/audioapi/HostObjects/{RecorderAdapterNodeHostObject.h → sources/RecorderAdapterNodeHostObject.h} +1 -2
  55. package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.cpp +22 -0
  56. package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h +28 -0
  57. package/common/cpp/audioapi/HostObjects/sources/WorkletSourceNodeHostObject.h +18 -0
  58. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +107 -0
  59. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +28 -0
  60. package/common/cpp/audioapi/core/AudioContext.cpp +3 -4
  61. package/common/cpp/audioapi/core/AudioContext.h +2 -1
  62. package/common/cpp/audioapi/core/AudioNode.cpp +3 -3
  63. package/common/cpp/audioapi/core/AudioNode.h +2 -2
  64. package/common/cpp/audioapi/core/AudioParam.cpp +2 -2
  65. package/common/cpp/audioapi/core/AudioParam.h +1 -1
  66. package/common/cpp/audioapi/core/BaseAudioContext.cpp +47 -38
  67. package/common/cpp/audioapi/core/BaseAudioContext.h +17 -16
  68. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +4 -5
  69. package/common/cpp/audioapi/core/OfflineAudioContext.h +2 -1
  70. package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +3 -1
  71. package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -1
  72. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +1 -1
  73. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +3 -1
  74. package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -1
  75. package/common/cpp/audioapi/core/effects/GainNode.cpp +3 -1
  76. package/common/cpp/audioapi/core/effects/GainNode.h +1 -1
  77. package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +1 -1
  78. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +18 -13
  79. package/common/cpp/audioapi/core/effects/StereoPannerNode.h +1 -1
  80. package/common/cpp/audioapi/core/effects/WorkletNode.cpp +89 -0
  81. package/common/cpp/audioapi/core/effects/WorkletNode.h +65 -0
  82. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +91 -0
  83. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +52 -0
  84. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +1 -1
  85. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +2 -2
  86. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +47 -10
  87. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +18 -3
  88. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +98 -14
  89. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +9 -3
  90. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +37 -44
  91. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +7 -9
  92. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +1 -6
  93. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +1 -1
  94. package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +53 -0
  95. package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +26 -0
  96. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +7 -2
  97. package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -1
  98. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +3 -1
  99. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +1 -1
  100. package/common/cpp/audioapi/core/sources/StreamerNode.cpp +9 -1
  101. package/common/cpp/audioapi/core/sources/StreamerNode.h +1 -9
  102. package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +84 -0
  103. package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +47 -0
  104. package/common/cpp/audioapi/core/types/AudioFormat.h +16 -0
  105. package/common/cpp/audioapi/core/utils/AudioDecoder.h +36 -90
  106. package/common/cpp/audioapi/core/{AudioParamEventQueue.cpp → utils/AudioParamEventQueue.cpp} +13 -7
  107. package/common/cpp/audioapi/core/{Constants.h → utils/Constants.h} +5 -0
  108. package/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +52 -0
  109. package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.cpp +9 -0
  110. package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.h +73 -0
  111. package/common/cpp/audioapi/dsp/Windows.cpp +1 -1
  112. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +1 -1
  113. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +2 -1
  114. package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +14 -1
  115. package/common/cpp/audioapi/jsi/JsiHostObject.h +6 -12
  116. package/common/cpp/audioapi/jsi/JsiPromise.cpp +49 -0
  117. package/common/cpp/audioapi/jsi/JsiPromise.h +29 -1
  118. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +241 -282
  119. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +57 -19
  120. package/common/cpp/audioapi/utils/AudioBus.cpp +1 -1
  121. package/common/cpp/audioapi/utils/ThreadPool.hpp +104 -0
  122. package/common/cpp/test/AudioParamTest.cpp +204 -0
  123. package/common/cpp/test/CMakeLists.txt +13 -4
  124. package/common/cpp/test/GainTest.cpp +11 -10
  125. package/common/cpp/test/OscillatorTest.cpp +2 -1
  126. package/common/cpp/test/StereoPannerTest.cpp +129 -0
  127. package/ios/audioapi/ios/AudioAPIModule.mm +32 -5
  128. package/ios/audioapi/ios/core/IOSAudioPlayer.mm +1 -1
  129. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +1 -1
  130. package/ios/audioapi/ios/core/utils/AudioDecoder.mm +160 -0
  131. package/lib/commonjs/api.js +50 -3
  132. package/lib/commonjs/api.js.map +1 -1
  133. package/lib/commonjs/api.web.js +8 -0
  134. package/lib/commonjs/api.web.js.map +1 -1
  135. package/lib/commonjs/core/AudioBufferBaseSourceNode.js +7 -7
  136. package/lib/commonjs/core/AudioBufferBaseSourceNode.js.map +1 -1
  137. package/lib/commonjs/core/AudioBufferQueueSourceNode.js +1 -6
  138. package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -1
  139. package/lib/commonjs/core/AudioBufferSourceNode.js +15 -0
  140. package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
  141. package/lib/commonjs/core/AudioContext.js +10 -1
  142. package/lib/commonjs/core/AudioContext.js.map +1 -1
  143. package/lib/commonjs/core/AudioDecoder.js +48 -0
  144. package/lib/commonjs/core/AudioDecoder.js.map +1 -0
  145. package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -4
  146. package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
  147. package/lib/commonjs/core/BaseAudioContext.js +76 -28
  148. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  149. package/lib/commonjs/core/ConstantSourceNode.js +17 -0
  150. package/lib/commonjs/core/ConstantSourceNode.js.map +1 -0
  151. package/lib/commonjs/core/OfflineAudioContext.js +11 -2
  152. package/lib/commonjs/core/OfflineAudioContext.js.map +1 -1
  153. package/lib/commonjs/core/OscillatorNode.js +6 -0
  154. package/lib/commonjs/core/OscillatorNode.js.map +1 -1
  155. package/lib/commonjs/core/WorkletNode.js +11 -0
  156. package/lib/commonjs/core/WorkletNode.js.map +1 -0
  157. package/lib/commonjs/core/WorkletProcessingNode.js +11 -0
  158. package/lib/commonjs/core/WorkletProcessingNode.js.map +1 -0
  159. package/lib/commonjs/core/WorkletSourceNode.js +11 -0
  160. package/lib/commonjs/core/WorkletSourceNode.js.map +1 -0
  161. package/lib/commonjs/hooks/{useSytemVolume.js → useSystemVolume.js} +1 -1
  162. package/lib/commonjs/hooks/useSystemVolume.js.map +1 -0
  163. package/lib/commonjs/utils/index.js +9 -0
  164. package/lib/commonjs/utils/index.js.map +1 -1
  165. package/lib/commonjs/web-core/AudioContext.js +4 -0
  166. package/lib/commonjs/web-core/AudioContext.js.map +1 -1
  167. package/lib/commonjs/web-core/AudioScheduledSourceNode.js +1 -1
  168. package/lib/commonjs/web-core/AudioScheduledSourceNode.js.map +1 -1
  169. package/lib/commonjs/web-core/ConstantSourceNode.js +17 -0
  170. package/lib/commonjs/web-core/ConstantSourceNode.js.map +1 -0
  171. package/lib/commonjs/web-core/OfflineAudioContext.js +4 -0
  172. package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -1
  173. package/lib/module/api.js +8 -3
  174. package/lib/module/api.js.map +1 -1
  175. package/lib/module/api.web.js +1 -0
  176. package/lib/module/api.web.js.map +1 -1
  177. package/lib/module/core/AudioBufferBaseSourceNode.js +7 -7
  178. package/lib/module/core/AudioBufferBaseSourceNode.js.map +1 -1
  179. package/lib/module/core/AudioBufferQueueSourceNode.js +1 -6
  180. package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -1
  181. package/lib/module/core/AudioBufferSourceNode.js +15 -0
  182. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  183. package/lib/module/core/AudioContext.js +10 -1
  184. package/lib/module/core/AudioContext.js.map +1 -1
  185. package/lib/module/core/AudioDecoder.js +42 -0
  186. package/lib/module/core/AudioDecoder.js.map +1 -0
  187. package/lib/module/core/AudioScheduledSourceNode.js +4 -4
  188. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  189. package/lib/module/core/BaseAudioContext.js +76 -28
  190. package/lib/module/core/BaseAudioContext.js.map +1 -1
  191. package/lib/module/core/ConstantSourceNode.js +11 -0
  192. package/lib/module/core/ConstantSourceNode.js.map +1 -0
  193. package/lib/module/core/OfflineAudioContext.js +11 -2
  194. package/lib/module/core/OfflineAudioContext.js.map +1 -1
  195. package/lib/module/core/OscillatorNode.js +6 -0
  196. package/lib/module/core/OscillatorNode.js.map +1 -1
  197. package/lib/module/core/WorkletNode.js +5 -0
  198. package/lib/module/core/WorkletNode.js.map +1 -0
  199. package/lib/module/core/WorkletProcessingNode.js +5 -0
  200. package/lib/module/core/WorkletProcessingNode.js.map +1 -0
  201. package/lib/module/core/WorkletSourceNode.js +5 -0
  202. package/lib/module/core/WorkletSourceNode.js.map +1 -0
  203. package/lib/module/hooks/{useSytemVolume.js → useSystemVolume.js} +1 -1
  204. package/lib/module/hooks/useSystemVolume.js.map +1 -0
  205. package/lib/module/utils/index.js +8 -0
  206. package/lib/module/utils/index.js.map +1 -1
  207. package/lib/module/web-core/AudioContext.js +4 -0
  208. package/lib/module/web-core/AudioContext.js.map +1 -1
  209. package/lib/module/web-core/AudioScheduledSourceNode.js +1 -1
  210. package/lib/module/web-core/AudioScheduledSourceNode.js.map +1 -1
  211. package/lib/module/web-core/ConstantSourceNode.js +11 -0
  212. package/lib/module/web-core/ConstantSourceNode.js.map +1 -0
  213. package/lib/module/web-core/OfflineAudioContext.js +4 -0
  214. package/lib/module/web-core/OfflineAudioContext.js.map +1 -1
  215. package/lib/typescript/api.d.ts +11 -5
  216. package/lib/typescript/api.d.ts.map +1 -1
  217. package/lib/typescript/api.web.d.ts +1 -0
  218. package/lib/typescript/api.web.d.ts.map +1 -1
  219. package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts +2 -2
  220. package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts.map +1 -1
  221. package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +1 -1
  222. package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -1
  223. package/lib/typescript/core/AudioBufferSourceNode.d.ts +4 -0
  224. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
  225. package/lib/typescript/core/AudioContext.d.ts +1 -0
  226. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  227. package/lib/typescript/core/AudioDecoder.d.ts +4 -0
  228. package/lib/typescript/core/AudioDecoder.d.ts.map +1 -0
  229. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +1 -1
  230. package/lib/typescript/core/BaseAudioContext.d.ts +21 -16
  231. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  232. package/lib/typescript/core/ConstantSourceNode.d.ts +9 -0
  233. package/lib/typescript/core/ConstantSourceNode.d.ts.map +1 -0
  234. package/lib/typescript/core/OfflineAudioContext.d.ts +1 -0
  235. package/lib/typescript/core/OfflineAudioContext.d.ts.map +1 -1
  236. package/lib/typescript/core/OscillatorNode.d.ts +3 -0
  237. package/lib/typescript/core/OscillatorNode.d.ts.map +1 -1
  238. package/lib/typescript/core/WorkletNode.d.ts +4 -0
  239. package/lib/typescript/core/WorkletNode.d.ts.map +1 -0
  240. package/lib/typescript/core/WorkletProcessingNode.d.ts +4 -0
  241. package/lib/typescript/core/WorkletProcessingNode.d.ts.map +1 -0
  242. package/lib/typescript/core/WorkletSourceNode.d.ts +4 -0
  243. package/lib/typescript/core/WorkletSourceNode.d.ts.map +1 -0
  244. package/lib/typescript/events/types.d.ts +2 -0
  245. package/lib/typescript/events/types.d.ts.map +1 -1
  246. package/lib/typescript/hooks/{useSytemVolume.d.ts → useSystemVolume.d.ts} +1 -1
  247. package/lib/typescript/hooks/useSystemVolume.d.ts.map +1 -0
  248. package/lib/typescript/interfaces.d.ts +27 -6
  249. package/lib/typescript/interfaces.d.ts.map +1 -1
  250. package/lib/typescript/types.d.ts +2 -1
  251. package/lib/typescript/types.d.ts.map +1 -1
  252. package/lib/typescript/utils/index.d.ts +8 -0
  253. package/lib/typescript/utils/index.d.ts.map +1 -1
  254. package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +1 -1
  255. package/lib/typescript/web-core/AudioContext.d.ts +4 -2
  256. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  257. package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts +1 -1
  258. package/lib/typescript/web-core/BaseAudioContext.d.ts +2 -0
  259. package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
  260. package/lib/typescript/web-core/ConstantSourceNode.d.ts +8 -0
  261. package/lib/typescript/web-core/ConstantSourceNode.d.ts.map +1 -0
  262. package/lib/typescript/web-core/OfflineAudioContext.d.ts +4 -2
  263. package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -1
  264. package/package.json +3 -2
  265. package/src/api.ts +17 -3
  266. package/src/api.web.ts +1 -0
  267. package/src/core/AudioBufferBaseSourceNode.ts +9 -9
  268. package/src/core/AudioBufferQueueSourceNode.ts +1 -9
  269. package/src/core/AudioBufferSourceNode.ts +28 -0
  270. package/src/core/AudioContext.ts +12 -1
  271. package/src/core/AudioDecoder.ts +78 -0
  272. package/src/core/AudioScheduledSourceNode.ts +5 -5
  273. package/src/core/BaseAudioContext.ts +174 -41
  274. package/src/core/ConstantSourceNode.ts +13 -0
  275. package/src/core/OfflineAudioContext.ts +18 -2
  276. package/src/core/OscillatorNode.ts +11 -0
  277. package/src/core/WorkletNode.ts +3 -0
  278. package/src/core/WorkletProcessingNode.ts +3 -0
  279. package/src/core/WorkletSourceNode.ts +3 -0
  280. package/src/events/types.ts +2 -0
  281. package/src/interfaces.ts +77 -11
  282. package/src/types.ts +3 -1
  283. package/src/utils/index.ts +21 -0
  284. package/src/web-core/AudioBufferSourceNode.tsx +1 -1
  285. package/src/web-core/AudioContext.tsx +7 -2
  286. package/src/web-core/AudioScheduledSourceNode.tsx +1 -1
  287. package/src/web-core/BaseAudioContext.tsx +2 -0
  288. package/src/web-core/ConstantSourceNode.tsx +12 -0
  289. package/src/web-core/OfflineAudioContext.tsx +7 -2
  290. package/common/cpp/audioapi/HostObjects/AnalyserNodeHostObject.h +0 -149
  291. package/common/cpp/audioapi/HostObjects/AudioBufferBaseSourceNodeHostObject.h +0 -76
  292. package/common/cpp/audioapi/HostObjects/AudioBufferHostObject.h +0 -120
  293. package/common/cpp/audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h +0 -67
  294. package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +0 -142
  295. package/common/cpp/audioapi/HostObjects/AudioRecorderHostObject.h +0 -86
  296. package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +0 -56
  297. package/common/cpp/audioapi/HostObjects/BiquadFilterNodeHostObject.h +0 -89
  298. package/common/cpp/audioapi/HostObjects/GainNodeHostObject.h +0 -27
  299. package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +0 -65
  300. package/common/cpp/audioapi/HostObjects/StereoPannerNodeHostObject.h +0 -29
  301. package/common/cpp/audioapi/HostObjects/StreamerNodeHostObject.h +0 -30
  302. package/common/cpp/audioapi/events/AudioEventHandlerRegistryHostObject.h +0 -48
  303. package/ios/audioapi/ios/core/AudioDecoder.mm +0 -156
  304. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.h +0 -7
  305. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.mm +0 -12
  306. package/lib/commonjs/hooks/useSytemVolume.js.map +0 -1
  307. package/lib/module/hooks/useSytemVolume.js.map +0 -1
  308. package/lib/typescript/hooks/useSytemVolume.d.ts.map +0 -1
  309. /package/common/cpp/audioapi/HostObjects/{AudioDestinationNodeHostObject.h → destinations/AudioDestinationNodeHostObject.h} +0 -0
  310. /package/common/cpp/audioapi/HostObjects/{PeriodicWaveHostObject.h → effects/PeriodicWaveHostObject.h} +0 -0
  311. /package/common/cpp/audioapi/core/{AudioParamEventQueue.h → utils/AudioParamEventQueue.h} +0 -0
  312. /package/src/hooks/{useSytemVolume.ts → useSystemVolume.ts} +0 -0
@@ -1,11 +1,11 @@
1
1
  /*
2
- * This file dynamically links to the FFmpeg library, which is licensed under the
3
- * GNU Lesser General Public License (LGPL) version 2.1 or later.
2
+ * This file dynamically links to the FFmpeg library, which is licensed under
3
+ * the GNU Lesser General Public License (LGPL) version 2.1 or later.
4
4
  *
5
- * Our own code in this file is licensed under the MIT License and dynamic linking
6
- * allows you to use this code without your entire project being subject to the
7
- * terms of the LGPL. However, note that if you link statically to FFmpeg, you must
8
- * comply with the terms of the LGPL for FFmpeg itself.
5
+ * Our own code in this file is licensed under the MIT License and dynamic
6
+ * linking allows you to use this code without your entire project being subject
7
+ * to the terms of the LGPL. However, note that if you link statically to
8
+ * FFmpeg, you must comply with the terms of the LGPL for FFmpeg itself.
9
9
  */
10
10
 
11
11
  #include <audioapi/utils/AudioBus.h>
@@ -14,24 +14,62 @@
14
14
  #include <vector>
15
15
 
16
16
  extern "C" {
17
- #include <libavcodec/avcodec.h>
18
- #include <libavformat/avformat.h>
19
- #include <libavutil/opt.h>
20
- #include <libswresample/swresample.h>
17
+ #include <libavcodec/avcodec.h>
18
+ #include <libavformat/avformat.h>
19
+ #include <libavutil/opt.h>
20
+ #include <libswresample/swresample.h>
21
21
  }
22
+ class AudioBuffer;
22
23
 
23
- namespace audioapi::ffmpegdecoding {
24
+ namespace audioapi::ffmpegdecoder {
24
25
  // Custom IO context for reading from memory
25
26
  struct MemoryIOContext {
26
- const uint8_t *data;
27
- size_t size;
28
- size_t pos;
29
- };
27
+ const uint8_t *data;
28
+ size_t size;
29
+ size_t pos;
30
+ };
31
+
32
+ struct AudioStreamContext {
33
+ AVFormatContext *fmt_ctx = nullptr;
34
+ AVCodecContext *codec_ctx = nullptr;
35
+ int audio_stream_index = -1;
36
+ };
30
37
 
31
38
  int read_packet(void *opaque, uint8_t *buf, int buf_size);
32
39
  int64_t seek_packet(void *opaque, int64_t offset, int whence);
33
- std::vector<int16_t> readAllPcmFrames(AVFormatContext *fmt_ctx, AVCodecContext *codec_ctx, int out_sample_rate, int audio_stream_index, int channels, size_t &framesRead);
34
- std::vector<int16_t> decodeWithMemoryBlock(const void *data, size_t size, const int channel_count, int sample_rate);
35
- std::vector<int16_t> decodeWithFilePath(const std::string &path, const int channel_count, int sample_rate);
40
+ inline int findAudioStreamIndex(AVFormatContext *fmt_ctx);
41
+ std::vector<float> readAllPcmFrames(
42
+ AVFormatContext *fmt_ctx,
43
+ AVCodecContext *codec_ctx,
44
+ int out_sample_rate,
45
+ int output_channel_count,
46
+ int audio_stream_index,
47
+ size_t &framesRead);
48
+
49
+ void convertFrameToBuffer(
50
+ SwrContext *swr,
51
+ AVFrame *frame,
52
+ int output_channel_count,
53
+ std::vector<float> &buffer,
54
+ size_t &framesRead,
55
+ uint8_t **&resampled_data,
56
+ int &max_resampled_samples);
57
+ bool setupDecoderContext(
58
+ AVFormatContext *fmt_ctx,
59
+ int &audio_stream_index,
60
+ std::unique_ptr<AVCodecContext, decltype(&avcodec_free_context)>
61
+ &codec_ctx);
62
+ std::shared_ptr<AudioBuffer> decodeAudioFrames(
63
+ AVFormatContext *fmt_ctx,
64
+ AVCodecContext *codec_ctx,
65
+ int audio_stream_index,
66
+ int sample_rate);
67
+
68
+ std::shared_ptr<AudioBuffer>
69
+ decodeWithMemoryBlock(const void *data, size_t size, int sample_rate);
70
+
71
+ std::shared_ptr<AudioBuffer> decodeWithFilePath(
72
+ const std::string &path,
73
+ int sample_rate);
36
74
 
37
- } // namespace audioapi::ffmpegdecoder
75
+ } // namespace audioapi::ffmpegdecoder
@@ -1,4 +1,4 @@
1
- #include <audioapi/core/Constants.h>
1
+ #include <audioapi/core/utils/Constants.h>
2
2
  #include <audioapi/dsp/VectorMath.h>
3
3
  #include <audioapi/utils/AudioArray.h>
4
4
  #include <audioapi/utils/AudioBus.h>
@@ -0,0 +1,104 @@
1
+ #pragma once
2
+ #include <thread>
3
+ #include <vector>
4
+ #include <functional>
5
+ #include <variant>
6
+ #include <audioapi/utils/SpscChannel.hpp>
7
+
8
+ namespace audioapi {
9
+
10
+ /// @brief A simple thread pool implementation using lock-free SPSC channels for task scheduling and execution.
11
+ /// @note The thread pool consists of a load balancer thread and multiple worker threads.
12
+ /// @note The load balancer receives tasks and distributes them to worker threads in a round-robin fashion.
13
+ /// @note Each worker thread has its own SPSC channel to receive tasks from the load balancer.
14
+ /// @note The thread pool can be shut down gracefully by sending a stop event to the load balancer, which then propagates the stop event to all worker threads.
15
+ /// @note IMPORTANT: ThreadPool is not thread-safe and events should be scheduled from a single thread only.
16
+ class ThreadPool {
17
+ struct StopEvent {};
18
+ struct TaskEvent { std::function<void()> task; };
19
+ using Event = std::variant<TaskEvent, StopEvent>;
20
+
21
+ using Sender = channels::spsc::Sender<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>;
22
+ using Receiver = channels::spsc::Receiver<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>;
23
+ public:
24
+ /// @brief Construct a new ThreadPool
25
+ /// @param numThreads The number of worker threads to create
26
+ /// @param loadBalancerQueueSize The size of the load balancer's queue
27
+ /// @param workerQueueSize The size of each worker thread's queue
28
+ ThreadPool(size_t numThreads, size_t loadBalancerQueueSize = 32, size_t workerQueueSize = 32) {
29
+ auto [sender, receiver] = channels::spsc::channel<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>(loadBalancerQueueSize);
30
+ loadBalancerSender = std::move(sender);
31
+ std::vector<Sender> workerSenders;
32
+ workerSenders.reserve(numThreads);
33
+ for (size_t i = 0; i < numThreads; ++i) {
34
+ auto [workerSender, workerReceiver] = channels::spsc::channel<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>(workerQueueSize);
35
+ workers.emplace_back(&ThreadPool::workerThreadFunc, this, std::move(workerReceiver));
36
+ workerSenders.emplace_back(std::move(workerSender));
37
+ }
38
+ loadBalancerThread = std::thread(&ThreadPool::loadBalancerThreadFunc, this, std::move(receiver), std::move(workerSenders));
39
+ }
40
+ ~ThreadPool() {
41
+ loadBalancerSender.send(StopEvent{});
42
+ loadBalancerThread.join();
43
+ for (auto& worker : workers) {
44
+ worker.join();
45
+ }
46
+ }
47
+
48
+ /// @brief Schedule a task to be executed by the thread pool
49
+ /// @param task The task to be executed
50
+ /// @note This function is lock-free and most of the time wait-free, but may block if the load balancer queue is full.
51
+ /// @note Please remember that the task will be executed in a different thread, so make sure to capture any required variables by value.
52
+ /// @note The task should not throw exceptions, as they will not be caught.
53
+ /// @note The task should end at some point, otherwise the thread pool will never be able to shut down.
54
+ /// @note IMPORTANT: This function is not thread-safe and should be called from a single thread only.
55
+ void schedule(std::function<void()> &&task) noexcept {
56
+ loadBalancerSender.send(TaskEvent{std::move(task)});
57
+ }
58
+
59
+ private:
60
+ std::thread loadBalancerThread;
61
+ std::vector<std::thread> workers;
62
+ Sender loadBalancerSender;
63
+
64
+ void workerThreadFunc(Receiver &&receiver) {
65
+ Receiver localReceiver = std::move(receiver);
66
+ while (true) {
67
+ auto event = localReceiver.receive();
68
+ /// We use [[unlikely]] and [[likely]] attributes to help the compiler optimize the branching.
69
+ /// we expect most of the time to receive TaskEvent, and rarely StopEvent.
70
+ /// and whenever we receive StopEvent we can burn some cycles as it will not be expected to execute fast.
71
+ if (std::holds_alternative<StopEvent>(event)) [[ unlikely ]] {
72
+ break;
73
+ } else if (std::holds_alternative<TaskEvent>(event)) [[ likely ]] {
74
+ std::get<TaskEvent>(event).task();
75
+ }
76
+ }
77
+ }
78
+
79
+ void loadBalancerThreadFunc(Receiver &&receiver, std::vector<Sender> &&workerSenders) {
80
+ Receiver localReceiver = std::move(receiver);
81
+ std::vector<Sender> localWorkerSenders = std::move(workerSenders);
82
+ size_t nextWorker = 0;
83
+ while (true) {
84
+ auto event = localReceiver.receive();
85
+ /// We use [[unlikely]] and [[likely]] attributes to help the compiler optimize the branching.
86
+ /// we expect most of the time to receive TaskEvent, and rarely StopEvent.
87
+ /// and whenever we receive StopEvent we can burn some cycles as it will not be expected to execute fast.
88
+ if (std::holds_alternative<StopEvent>(event)) [[ unlikely ]] {
89
+ // Propagate stop event to all workers
90
+ for (size_t i = 0; i < localWorkerSenders.size(); ++i) {
91
+ localWorkerSenders[i].send(StopEvent{});
92
+ }
93
+ break;
94
+ } else if (std::holds_alternative<TaskEvent>(event)) [[ likely ]] {
95
+ // Dispatch task to the next worker in round-robin fashion
96
+ auto& taskEvent = std::get<TaskEvent>(event);
97
+ localWorkerSenders[nextWorker].send(std::move(taskEvent));
98
+ nextWorker = (nextWorker + 1) % localWorkerSenders.size();
99
+ }
100
+ }
101
+ }
102
+ };
103
+
104
+ }; // namespace audioapi
@@ -0,0 +1,204 @@
1
+ #include <audioapi/core/AudioParam.h>
2
+ #include <audioapi/core/OfflineAudioContext.h>
3
+ #include <audioapi/core/utils/worklets/SafeIncludes.h>
4
+ #include <gtest/gtest.h>
5
+ #include "MockAudioEventHandlerRegistry.h"
6
+
7
+ using namespace audioapi;
8
+
9
+ class AudioParamTest : public ::testing::Test {
10
+ protected:
11
+ std::shared_ptr<IAudioEventHandlerRegistry> eventRegistry;
12
+ std::unique_ptr<OfflineAudioContext> context;
13
+ static constexpr int sampleRate = 44100;
14
+
15
+ void SetUp() override {
16
+ eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
17
+ context = std::make_unique<OfflineAudioContext>(
18
+ 2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
19
+ }
20
+ };
21
+
22
+ TEST_F(AudioParamTest, ValueSetters) {
23
+ AudioParam param = AudioParam(0.5, 0.0, 1.0, context.get());
24
+ param.setValue(0.8);
25
+ EXPECT_FLOAT_EQ(param.getValue(), 0.8);
26
+ param.setValue(-0.5);
27
+ EXPECT_FLOAT_EQ(param.getValue(), 0.0);
28
+ param.setValue(1.5);
29
+ EXPECT_FLOAT_EQ(param.getValue(), 1.0);
30
+ }
31
+
32
+ TEST_F(AudioParamTest, SetValueAtTime) {
33
+ AudioParam param = AudioParam(0.5, 0.0, 1.0, context.get());
34
+ param.setValueAtTime(0.8, 0.1);
35
+ param.setValueAtTime(0.3, 0.2);
36
+
37
+ float value = param.processKRateParam(1, 0.05);
38
+ EXPECT_FLOAT_EQ(value, 0.5);
39
+
40
+ value = param.processKRateParam(1, 0.1);
41
+ EXPECT_FLOAT_EQ(value, 0.8);
42
+
43
+ value = param.processKRateParam(1, 0.15);
44
+ EXPECT_FLOAT_EQ(value, 0.8);
45
+
46
+ value = param.processKRateParam(1, 0.2);
47
+ EXPECT_FLOAT_EQ(value, 0.3);
48
+
49
+ value = param.processKRateParam(1, 0.25);
50
+ EXPECT_FLOAT_EQ(value, 0.3);
51
+ }
52
+
53
+ TEST_F(AudioParamTest, LinearRampToValueAtTime) {
54
+ AudioParam param = AudioParam(0, 0, 1.0, context.get());
55
+ param.linearRampToValueAtTime(1.0, 0.2);
56
+
57
+ float value = param.processKRateParam(1, 0.05);
58
+ EXPECT_FLOAT_EQ(value, 0.25);
59
+
60
+ value = param.processKRateParam(1, 0.1);
61
+ EXPECT_FLOAT_EQ(value, 0.5);
62
+
63
+ value = param.processKRateParam(1, 0.15);
64
+ EXPECT_FLOAT_EQ(value, 0.75);
65
+
66
+ value = param.processKRateParam(1, 0.2);
67
+ EXPECT_FLOAT_EQ(value, 1.0);
68
+
69
+ value = param.processKRateParam(1, 0.25);
70
+ EXPECT_FLOAT_EQ(value, 1.0);
71
+ }
72
+
73
+ TEST_F(AudioParamTest, ExponentialRampToValueAtTime) {
74
+ AudioParam param = AudioParam(0.1, 0.0, 1.0, context.get());
75
+ param.exponentialRampToValueAtTime(1.0, 0.2);
76
+ // value(time) = startValue * (endValue/startValue)^((time -
77
+ // startTime)/(endTime - startTime)) value(time) = 0.1 * (1.0/0.1)^((time -
78
+ // 0.0)/(0.2 - 0.0))
79
+ float value = param.processKRateParam(1, 0.05);
80
+ EXPECT_NEAR(value, 0.17783, 1e-5);
81
+
82
+ value = param.processKRateParam(1, 0.1);
83
+ EXPECT_NEAR(value, 0.316228, 1e-5);
84
+
85
+ value = param.processKRateParam(1, 0.15);
86
+ EXPECT_NEAR(value, 0.562341, 1e-5);
87
+
88
+ value = param.processKRateParam(1, 0.2);
89
+ EXPECT_FLOAT_EQ(value, 1.0);
90
+
91
+ value = param.processKRateParam(1, 0.25);
92
+ EXPECT_FLOAT_EQ(value, 1.0);
93
+ }
94
+
95
+ TEST_F(AudioParamTest, SetTargetAtTime) {
96
+ AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
97
+ param.setTargetAtTime(1.0, 0.1, 0.1);
98
+ // value(time) = target + (startValue - target) * exp(-(time -
99
+ // startTime)/timeConstant) value(time) = 1.0 + (0.0 - 1.0) * exp(-time/0.1)
100
+ float value = param.processKRateParam(1, 0.05);
101
+ EXPECT_FLOAT_EQ(value, 0.0);
102
+
103
+ value = param.processKRateParam(1, 0.1);
104
+ EXPECT_FLOAT_EQ(value, 0.0);
105
+
106
+ value = param.processKRateParam(1, 0.15);
107
+ EXPECT_NEAR(value, 0.393469, 1e-5);
108
+
109
+ value = param.processKRateParam(1, 0.2);
110
+ EXPECT_NEAR(value, 0.632120, 1e-5);
111
+
112
+ value = param.processKRateParam(1, 0.25);
113
+ EXPECT_NEAR(value, 0.776869, 1e-5);
114
+
115
+ value = param.processKRateParam(1, 0.5);
116
+ EXPECT_NEAR(value, 0.981684, 1e-5);
117
+ }
118
+
119
+ TEST_F(AudioParamTest, SetValueCurveAtTime) {
120
+ AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
121
+ param.setValue(0.5);
122
+ auto curve = std::make_shared<std::vector<float>>(
123
+ std::vector<float>{0.1, 0.4, 0.2, 0.8, 0.5});
124
+ param.setValueCurveAtTime(curve, curve->size(), 0.1, 0.2);
125
+ // 5 elements over 0.2s => each element is 0.04s apart
126
+
127
+ float value = param.processKRateParam(1, 0.05);
128
+ EXPECT_FLOAT_EQ(value, 0.0);
129
+
130
+ value = param.processKRateParam(1, 0.1);
131
+ EXPECT_FLOAT_EQ(value, 0.1);
132
+
133
+ // k = 4/0.2 * (0.14 - 0.1) = 0.8 -> floor is 0
134
+ // linear interpolation between 0 and 1 -> 0.1 + (0.4 - 0.1) * 0.8 = 0.34
135
+ value = param.processKRateParam(1, 0.14);
136
+ EXPECT_FLOAT_EQ(value, 0.34);
137
+
138
+ // k = 4/0.2 * (0.18 - 0.1) = 1.6 -> floor is 1
139
+ // linear interpolation between 1 and 2 -> 0.4 + (0.2 - 0.4) * 0.6 = 0.28
140
+ value = param.processKRateParam(1, 0.18);
141
+ EXPECT_FLOAT_EQ(value, 0.28);
142
+
143
+ // k = 4/0.2 * (0.22 - 0.1) = 2.4 -> floor is 2
144
+ // linear interpolation between 2 and 3 -> 0.2 + (0.8 - 0.2) * 0.4 = 0.44
145
+ value = param.processKRateParam(1, 0.22);
146
+ EXPECT_FLOAT_EQ(value, 0.44);
147
+
148
+ // k = 4/0.2 * (0.26 - 0.1) = 3.2 -> floor is 3
149
+ // linear interpolation between 3 and 4 -> 0.8 + (0.5 - 0.8) * 0.2 = 0.74
150
+ value = param.processKRateParam(1, 0.26);
151
+ EXPECT_FLOAT_EQ(value, 0.74);
152
+
153
+ // k = 4/0.2 * (0.3 - 0.1) = 4.0 -> floor is 4
154
+ // at or after end of curve -> last value
155
+ value = param.processKRateParam(1, 0.35);
156
+ EXPECT_FLOAT_EQ(value, 0.5);
157
+ }
158
+
159
+ TEST_F(AudioParamTest, CancelScheduledValues) {
160
+ AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
161
+ param.setValueAtTime(0.8, 0.1);
162
+ param.setValueAtTime(0.3, 0.2);
163
+ param.linearRampToValueAtTime(1.0, 0.4);
164
+ param.cancelScheduledValues(0.15);
165
+
166
+ float value = param.processKRateParam(1, 0.05);
167
+ EXPECT_FLOAT_EQ(value, 0.0);
168
+
169
+ value = param.processKRateParam(1, 0.1);
170
+ EXPECT_FLOAT_EQ(value, 0.8);
171
+
172
+ value = param.processKRateParam(1, 0.15);
173
+ EXPECT_FLOAT_EQ(value, 0.8);
174
+
175
+ // Events after cancel time are removed -> stays at last value
176
+ value = param.processKRateParam(1, 0.2);
177
+ EXPECT_FLOAT_EQ(value, 0.8);
178
+
179
+ value = param.processKRateParam(1, 0.25);
180
+ EXPECT_FLOAT_EQ(value, 0.8);
181
+ }
182
+
183
+ TEST_F(AudioParamTest, CancelAndHoldAtTime) {
184
+ AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
185
+ param.setValueAtTime(0.8, 0.1);
186
+ param.linearRampToValueAtTime(1.0, 0.2);
187
+ param.cancelAndHoldAtTime(0.15);
188
+
189
+ float value = param.processKRateParam(1, 0.05);
190
+ EXPECT_FLOAT_EQ(value, 0.0);
191
+
192
+ value = param.processKRateParam(1, 0.1);
193
+ EXPECT_FLOAT_EQ(value, 0.8);
194
+
195
+ value = param.processKRateParam(1, 0.15);
196
+ EXPECT_FLOAT_EQ(value, 0.9);
197
+
198
+ // Events after cancel time are removed -> stays at last value
199
+ value = param.processKRateParam(1, 0.2);
200
+ EXPECT_FLOAT_EQ(value, 0.9);
201
+
202
+ value = param.processKRateParam(1, 0.25);
203
+ EXPECT_FLOAT_EQ(value, 0.9);
204
+ }
@@ -21,11 +21,17 @@ enable_testing()
21
21
  file(GLOB_RECURSE RNAUDIOAPI_SRC
22
22
  CONFIGURE_DEPENDS
23
23
  "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/*.cpp"
24
- "${ROOT}/node_modules/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp"
24
+ "${ROOT}/node_modules/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp"
25
25
  )
26
26
 
27
- list(REMOVE_ITEM RNAUDIOAPI_SRC
27
+ # exclude HostObjects from tests
28
+ list(FILTER RNAUDIOAPI_SRC EXCLUDE REGEX ".*/audioapi/HostObjects/.*\\.cpp$")
29
+
30
+ list(REMOVE_ITEM RNAUDIOAPI_SRC
28
31
  "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp"
32
+ "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp"
33
+ "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp"
34
+ "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp"
29
35
  "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp"
30
36
  "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h"
31
37
  "${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp"
@@ -56,14 +62,17 @@ target_include_directories(rnaudioapi PUBLIC
56
62
  target_include_directories(rnaudioapi_libs PUBLIC
57
63
  ${ROOT}/packages/react-native-audio-api/common/cpp
58
64
  )
59
-
60
65
  add_executable(
61
66
  tests
62
67
  OscillatorTest.cpp
63
68
  GainTest.cpp
69
+ AudioParamTest.cpp
70
+ StereoPannerTest.cpp
64
71
  )
65
72
 
66
73
  add_compile_definitions(AUDIO_API_TEST_SUITE)
74
+ add_compile_definitions(RN_AUDIO_API_ENABLE_WORKLETS=0)
75
+ add_compile_definitions(RN_AUDIO_API_TEST=1)
67
76
 
68
77
  target_link_libraries(tests
69
78
  rnaudioapi
@@ -73,4 +82,4 @@ target_link_libraries(tests
73
82
  )
74
83
 
75
84
  include(GoogleTest)
76
- gtest_discover_tests(tests)
85
+ gtest_discover_tests(tests)
@@ -1,5 +1,6 @@
1
1
  #include <audioapi/core/OfflineAudioContext.h>
2
2
  #include <audioapi/core/effects/GainNode.h>
3
+ #include <audioapi/core/utils/worklets/SafeIncludes.h>
3
4
  #include <audioapi/utils/AudioArray.h>
4
5
  #include <audioapi/utils/AudioBus.h>
5
6
  #include <gtest/gtest.h>
@@ -14,7 +15,7 @@ class GainTest : public ::testing::Test {
14
15
  void SetUp() override {
15
16
  eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
16
17
  context = std::make_unique<audioapi::OfflineAudioContext>(
17
- 2, 5 * sampleRate, sampleRate, eventRegistry);
18
+ 2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
18
19
  }
19
20
  };
20
21
 
@@ -27,10 +28,10 @@ class TestableGainNode : public audioapi::GainNode {
27
28
  getGainParam()->setValue(value);
28
29
  }
29
30
 
30
- void processNode(
31
+ std::shared_ptr<audioapi::AudioBus> processNode(
31
32
  const std::shared_ptr<audioapi::AudioBus> &processingBus,
32
33
  int framesToProcess) override {
33
- audioapi::GainNode::processNode(processingBus, framesToProcess);
34
+ return audioapi::GainNode::processNode(processingBus, framesToProcess);
34
35
  }
35
36
  };
36
37
 
@@ -51,9 +52,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectly) {
51
52
  bus->getChannel(0)->getData()[i] = i + 1;
52
53
  }
53
54
 
54
- gainNode->processNode(bus, FRAMES_TO_PROCESS);
55
- for (size_t i = 0; i < bus->getSize(); ++i) {
56
- EXPECT_FLOAT_EQ((*bus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
55
+ auto resultBus = gainNode->processNode(bus, FRAMES_TO_PROCESS);
56
+ for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
57
+ EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
57
58
  }
58
59
  }
59
60
 
@@ -70,9 +71,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectlyMultiChannel) {
70
71
  bus->getChannel(1)->getData()[i] = -i - 1;
71
72
  }
72
73
 
73
- gainNode->processNode(bus, FRAMES_TO_PROCESS);
74
- for (size_t i = 0; i < bus->getSize(); ++i) {
75
- EXPECT_FLOAT_EQ((*bus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
76
- EXPECT_FLOAT_EQ((*bus->getChannel(1))[i], (-i - 1) * GAIN_VALUE);
74
+ auto resultBus = gainNode->processNode(bus, FRAMES_TO_PROCESS);
75
+ for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
76
+ EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
77
+ EXPECT_FLOAT_EQ((*resultBus->getChannel(1))[i], (-i - 1) * GAIN_VALUE);
77
78
  }
78
79
  }
@@ -1,5 +1,6 @@
1
1
  #include <audioapi/core/OfflineAudioContext.h>
2
2
  #include <audioapi/core/sources/OscillatorNode.h>
3
+ #include <audioapi/core/utils/worklets/SafeIncludes.h>
3
4
  #include <gtest/gtest.h>
4
5
  #include "MockAudioEventHandlerRegistry.h"
5
6
 
@@ -12,7 +13,7 @@ class OscillatorTest : public ::testing::Test {
12
13
  void SetUp() override {
13
14
  eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
14
15
  context = std::make_unique<audioapi::OfflineAudioContext>(
15
- 2, 5 * sampleRate, sampleRate, eventRegistry);
16
+ 2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
16
17
  }
17
18
  };
18
19
 
@@ -0,0 +1,129 @@
1
+ #include <audioapi/core/OfflineAudioContext.h>
2
+ #include <audioapi/core/effects/StereoPannerNode.h>
3
+ #include <audioapi/core/utils/worklets/SafeIncludes.h>
4
+ #include <audioapi/utils/AudioArray.h>
5
+ #include <audioapi/utils/AudioBus.h>
6
+ #include <gtest/gtest.h>
7
+ #include "MockAudioEventHandlerRegistry.h"
8
+
9
+ using namespace audioapi;
10
+
11
+ class StereoPannerTest : public ::testing::Test {
12
+ protected:
13
+ std::shared_ptr<IAudioEventHandlerRegistry> eventRegistry;
14
+ std::unique_ptr<OfflineAudioContext> context;
15
+ static constexpr int sampleRate = 44100;
16
+
17
+ void SetUp() override {
18
+ eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
19
+ context = std::make_unique<OfflineAudioContext>(
20
+ 2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
21
+ }
22
+ };
23
+
24
+ class TestableStereoPannerNode : public StereoPannerNode {
25
+ public:
26
+ explicit TestableStereoPannerNode(BaseAudioContext *context)
27
+ : StereoPannerNode(context) {}
28
+
29
+ void setPanParam(float value) {
30
+ getPanParam()->setValue(value);
31
+ }
32
+
33
+ std::shared_ptr<AudioBus> processNode(
34
+ const std::shared_ptr<AudioBus> &processingBus,
35
+ int framesToProcess) override {
36
+ return StereoPannerNode::processNode(processingBus, framesToProcess);
37
+ }
38
+ };
39
+
40
+ TEST_F(StereoPannerTest, StereoPannerCanBeCreated) {
41
+ auto panner = context->createStereoPanner();
42
+ ASSERT_NE(panner, nullptr);
43
+ }
44
+
45
+ TEST_F(StereoPannerTest, PanModulatesInputMonoCorrectly) {
46
+ static constexpr float PAN_VALUE = 0.5;
47
+ static constexpr int FRAMES_TO_PROCESS = 4;
48
+ auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
49
+ panNode->setPanParam(PAN_VALUE);
50
+
51
+ auto bus =
52
+ std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 1, sampleRate);
53
+ for (size_t i = 0; i < bus->getSize(); ++i) {
54
+ (*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
55
+ }
56
+
57
+ auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
58
+ // x = (0.5 + 1) / 2 = 0.75
59
+ // gainL = cos(x * (π / 2)) = cos(0.75 * (π / 2)) = 0.38268343236508984
60
+ // gainR = sin(x * (π / 2)) = sin(0.75 * (π / 2)) = 0.9238795325112867
61
+ for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
62
+ EXPECT_NEAR(
63
+ (*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
64
+ (i + 1) * 0.38268343236508984,
65
+ 1e-4);
66
+ EXPECT_NEAR(
67
+ (*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
68
+ (i + 1) * 0.9238795325112867,
69
+ 1e-4);
70
+ }
71
+ }
72
+
73
+ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithNegativePan) {
74
+ static constexpr float PAN_VALUE = -0.5;
75
+ static constexpr int FRAMES_TO_PROCESS = 4;
76
+ auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
77
+ panNode->setPanParam(PAN_VALUE);
78
+
79
+ auto bus =
80
+ std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 2, sampleRate);
81
+ for (size_t i = 0; i < bus->getSize(); ++i) {
82
+ (*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
83
+ (*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1;
84
+ }
85
+
86
+ auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
87
+ // x = -0.5 + 1 = 0.5
88
+ // gainL = cos(x * (π / 2)) = cos(0.5 * (π / 2)) = 0.7071067811865476
89
+ // gainR = sin(x * (π / 2)) = sin(0.5 * (π / 2)) = 0.7071067811865476
90
+ for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
91
+ EXPECT_NEAR(
92
+ (*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
93
+ (i + 1) + (i + 1) * 0.7071067811865476,
94
+ 1e-4);
95
+ EXPECT_NEAR(
96
+ (*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
97
+ (i + 1) * 0.7071067811865476,
98
+ 1e-4);
99
+ }
100
+ }
101
+
102
+ TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) {
103
+ static constexpr float PAN_VALUE = 0.75;
104
+ static constexpr int FRAMES_TO_PROCESS = 4;
105
+ auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
106
+ panNode->setPanParam(PAN_VALUE);
107
+
108
+ auto bus =
109
+ std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 2, sampleRate);
110
+ for (size_t i = 0; i < bus->getSize(); ++i) {
111
+ (*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
112
+ (*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1;
113
+ }
114
+
115
+ auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
116
+ // x = 0.75
117
+ // gainL = cos(x * (π / 2)) = cos(0.75 * (π / 2)) = 0.38268343236508984
118
+ // gainR = sin(x * (π / 2)) = sin(0.75 * (π / 2)) = 0.9238795325112867
119
+ for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
120
+ EXPECT_NEAR(
121
+ (*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
122
+ (i + 1) * 0.38268343236508984,
123
+ 1e-4);
124
+ EXPECT_NEAR(
125
+ (*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
126
+ (i + 1) + (i + 1) * 0.9238795325112867,
127
+ 1e-4);
128
+ }
129
+ }