react-native-audio-api 0.11.0-nightly-568a154-20251222 → 0.11.0-nightly-94b7f30-20251224

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 (207) hide show
  1. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +1 -1
  2. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +11 -3
  3. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.cpp +47 -79
  4. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h +3 -2
  5. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -0
  6. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +9 -1
  7. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +1 -0
  8. package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.cpp +6 -2
  9. package/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.cpp +72 -0
  10. package/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.h +23 -0
  11. package/common/cpp/audioapi/core/AudioContext.cpp +15 -13
  12. package/common/cpp/audioapi/core/AudioContext.h +2 -1
  13. package/common/cpp/audioapi/core/AudioNode.cpp +39 -24
  14. package/common/cpp/audioapi/core/AudioNode.h +3 -3
  15. package/common/cpp/audioapi/core/AudioParam.cpp +9 -6
  16. package/common/cpp/audioapi/core/AudioParam.h +2 -2
  17. package/common/cpp/audioapi/core/BaseAudioContext.cpp +32 -21
  18. package/common/cpp/audioapi/core/BaseAudioContext.h +5 -1
  19. package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +8 -11
  20. package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -1
  21. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +9 -3
  22. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +1 -1
  23. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +18 -9
  24. package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -1
  25. package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +3 -3
  26. package/common/cpp/audioapi/core/effects/ConvolverNode.h +1 -1
  27. package/common/cpp/audioapi/core/effects/DelayNode.cpp +20 -11
  28. package/common/cpp/audioapi/core/effects/DelayNode.h +1 -1
  29. package/common/cpp/audioapi/core/effects/GainNode.cpp +12 -4
  30. package/common/cpp/audioapi/core/effects/GainNode.h +1 -1
  31. package/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +6 -3
  32. package/common/cpp/audioapi/core/effects/IIRFilterNode.h +1 -1
  33. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +7 -4
  34. package/common/cpp/audioapi/core/effects/StereoPannerNode.h +1 -1
  35. package/common/cpp/audioapi/core/effects/WaveShaperNode.cpp +79 -0
  36. package/common/cpp/audioapi/core/effects/WaveShaperNode.h +66 -0
  37. package/common/cpp/audioapi/core/effects/WorkletNode.cpp +2 -2
  38. package/common/cpp/audioapi/core/effects/WorkletNode.h +2 -2
  39. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +7 -4
  40. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +6 -2
  41. package/common/cpp/audioapi/core/sources/AudioBuffer.cpp +2 -3
  42. package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -1
  43. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +59 -25
  44. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +4 -2
  45. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +18 -11
  46. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +3 -1
  47. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +37 -21
  48. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +3 -3
  49. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +11 -11
  50. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +4 -2
  51. package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +16 -8
  52. package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +1 -1
  53. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +30 -18
  54. package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -1
  55. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +4 -4
  56. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +1 -1
  57. package/common/cpp/audioapi/core/sources/StreamerNode.cpp +24 -10
  58. package/common/cpp/audioapi/core/sources/StreamerNode.h +4 -3
  59. package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +11 -4
  60. package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +6 -2
  61. package/common/cpp/audioapi/core/types/OverSampleType.h +7 -0
  62. package/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp +1 -0
  63. package/common/cpp/audioapi/dsp/Resampler.cpp +200 -0
  64. package/common/cpp/audioapi/dsp/Resampler.h +65 -0
  65. package/common/cpp/audioapi/dsp/WaveShaper.cpp +105 -0
  66. package/common/cpp/audioapi/dsp/WaveShaper.h +46 -0
  67. package/common/cpp/audioapi/utils/AudioArray.cpp +5 -0
  68. package/common/cpp/audioapi/utils/AudioArray.h +6 -0
  69. package/common/cpp/test/RunTests.sh +1 -1
  70. package/common/cpp/test/src/AudioParamTest.cpp +10 -10
  71. package/common/cpp/test/src/AudioScheduledSourceTest.cpp +31 -15
  72. package/common/cpp/test/src/ConstantSourceTest.cpp +16 -14
  73. package/common/cpp/test/src/DelayTest.cpp +14 -13
  74. package/common/cpp/test/src/GainTest.cpp +10 -9
  75. package/common/cpp/test/src/IIRFilterTest.cpp +4 -4
  76. package/common/cpp/test/src/OscillatorTest.cpp +2 -2
  77. package/common/cpp/test/src/StereoPannerTest.cpp +14 -12
  78. package/common/cpp/test/src/biquad/BiquadFilterTest.cpp +25 -25
  79. package/common/cpp/test/src/biquad/BiquadFilterTest.h +3 -5
  80. package/common/cpp/test/src/core/effects/WaveShaperNodeTest.cpp +76 -0
  81. package/common/cpp/test/src/dsp/ResamplerTest.cpp +117 -0
  82. package/ios/audioapi/ios/AudioAPIModule.mm +4 -4
  83. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +1 -1
  84. package/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +9 -3
  85. package/lib/commonjs/AudioAPIModule/AudioAPIModule.js +0 -3
  86. package/lib/commonjs/AudioAPIModule/AudioAPIModule.js.map +1 -1
  87. package/lib/commonjs/AudioAPIModule/AudioAPIModule.web.js +20 -0
  88. package/lib/commonjs/AudioAPIModule/AudioAPIModule.web.js.map +1 -0
  89. package/lib/commonjs/AudioAPIModule/ModuleInterfaces.js +6 -0
  90. package/lib/commonjs/AudioAPIModule/ModuleInterfaces.js.map +1 -0
  91. package/lib/commonjs/api.js +16 -0
  92. package/lib/commonjs/api.js.map +1 -1
  93. package/lib/commonjs/api.web.js +23 -0
  94. package/lib/commonjs/api.web.js.map +1 -1
  95. package/lib/commonjs/core/BaseAudioContext.js +4 -0
  96. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  97. package/lib/commonjs/core/WaveShaperNode.js +38 -0
  98. package/lib/commonjs/core/WaveShaperNode.js.map +1 -0
  99. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  100. package/lib/commonjs/specs/NativeAudioAPIModule.web.js +47 -0
  101. package/lib/commonjs/specs/NativeAudioAPIModule.web.js.map +1 -0
  102. package/lib/commonjs/system/AudioManager.js.map +1 -1
  103. package/lib/commonjs/system/types.js +4 -0
  104. package/lib/commonjs/web-core/AudioContext.js +4 -0
  105. package/lib/commonjs/web-core/AudioContext.js.map +1 -1
  106. package/lib/commonjs/web-core/OfflineAudioContext.js +4 -0
  107. package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -1
  108. package/lib/commonjs/web-core/WaveShaperNode.js +38 -0
  109. package/lib/commonjs/web-core/WaveShaperNode.js.map +1 -0
  110. package/lib/commonjs/web-system/AudioManager.js +30 -0
  111. package/lib/commonjs/web-system/AudioManager.js.map +1 -0
  112. package/lib/commonjs/web-system/index.js +12 -0
  113. package/lib/commonjs/web-system/index.js.map +1 -1
  114. package/lib/module/AudioAPIModule/AudioAPIModule.js +0 -4
  115. package/lib/module/AudioAPIModule/AudioAPIModule.js.map +1 -1
  116. package/lib/module/AudioAPIModule/AudioAPIModule.web.js +16 -0
  117. package/lib/module/AudioAPIModule/AudioAPIModule.web.js.map +1 -0
  118. package/lib/module/AudioAPIModule/ModuleInterfaces.js +4 -0
  119. package/lib/module/AudioAPIModule/ModuleInterfaces.js.map +1 -0
  120. package/lib/module/AudioAPIModule/index.js +1 -1
  121. package/lib/module/AudioAPIModule/index.js.map +1 -1
  122. package/lib/module/api.js +2 -0
  123. package/lib/module/api.js.map +1 -1
  124. package/lib/module/api.web.js +3 -1
  125. package/lib/module/api.web.js.map +1 -1
  126. package/lib/module/core/BaseAudioContext.js +4 -0
  127. package/lib/module/core/BaseAudioContext.js.map +1 -1
  128. package/lib/module/core/WaveShaperNode.js +32 -0
  129. package/lib/module/core/WaveShaperNode.js.map +1 -0
  130. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  131. package/lib/module/specs/NativeAudioAPIModule.web.js +44 -0
  132. package/lib/module/specs/NativeAudioAPIModule.web.js.map +1 -0
  133. package/lib/module/specs/index.js +1 -1
  134. package/lib/module/specs/index.js.map +1 -1
  135. package/lib/module/system/AudioManager.js.map +1 -1
  136. package/lib/module/system/types.js +2 -0
  137. package/lib/module/web-core/AudioContext.js +4 -0
  138. package/lib/module/web-core/AudioContext.js.map +1 -1
  139. package/lib/module/web-core/OfflineAudioContext.js +4 -0
  140. package/lib/module/web-core/OfflineAudioContext.js.map +1 -1
  141. package/lib/module/web-core/WaveShaperNode.js +32 -0
  142. package/lib/module/web-core/WaveShaperNode.js.map +1 -0
  143. package/lib/module/web-system/AudioManager.js +26 -0
  144. package/lib/module/web-system/AudioManager.js.map +1 -0
  145. package/lib/module/web-system/index.js +1 -0
  146. package/lib/module/web-system/index.js.map +1 -1
  147. package/lib/typescript/AudioAPIModule/AudioAPIModule.d.ts +2 -10
  148. package/lib/typescript/AudioAPIModule/AudioAPIModule.d.ts.map +1 -1
  149. package/lib/typescript/AudioAPIModule/AudioAPIModule.web.d.ts +13 -0
  150. package/lib/typescript/AudioAPIModule/AudioAPIModule.web.d.ts.map +1 -0
  151. package/lib/typescript/AudioAPIModule/ModuleInterfaces.d.ts +18 -0
  152. package/lib/typescript/AudioAPIModule/ModuleInterfaces.d.ts.map +1 -0
  153. package/lib/typescript/api.d.ts +2 -0
  154. package/lib/typescript/api.d.ts.map +1 -1
  155. package/lib/typescript/api.web.d.ts +3 -1
  156. package/lib/typescript/api.web.d.ts.map +1 -1
  157. package/lib/typescript/core/BaseAudioContext.d.ts +2 -0
  158. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  159. package/lib/typescript/core/WaveShaperNode.d.ts +9 -0
  160. package/lib/typescript/core/WaveShaperNode.d.ts.map +1 -0
  161. package/lib/typescript/interfaces.d.ts +8 -2
  162. package/lib/typescript/interfaces.d.ts.map +1 -1
  163. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +1 -1
  164. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  165. package/lib/typescript/specs/NativeAudioAPIModule.web.d.ts +34 -0
  166. package/lib/typescript/specs/NativeAudioAPIModule.web.d.ts.map +1 -0
  167. package/lib/typescript/system/AudioManager.d.ts +2 -2
  168. package/lib/typescript/system/AudioManager.d.ts.map +1 -1
  169. package/lib/typescript/system/notification/types.d.ts +1 -1
  170. package/lib/typescript/system/notification/types.d.ts.map +1 -1
  171. package/lib/typescript/system/types.d.ts +17 -0
  172. package/lib/typescript/system/types.d.ts.map +1 -1
  173. package/lib/typescript/types.d.ts +1 -0
  174. package/lib/typescript/types.d.ts.map +1 -1
  175. package/lib/typescript/web-core/AudioContext.d.ts +2 -0
  176. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  177. package/lib/typescript/web-core/BaseAudioContext.d.ts +3 -1
  178. package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
  179. package/lib/typescript/web-core/OfflineAudioContext.d.ts +2 -0
  180. package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -1
  181. package/lib/typescript/web-core/WaveShaperNode.d.ts +9 -0
  182. package/lib/typescript/web-core/WaveShaperNode.d.ts.map +1 -0
  183. package/lib/typescript/web-system/AudioManager.d.ts +24 -0
  184. package/lib/typescript/web-system/AudioManager.d.ts.map +1 -0
  185. package/lib/typescript/web-system/index.d.ts +1 -0
  186. package/lib/typescript/web-system/index.d.ts.map +1 -1
  187. package/package.json +1 -1
  188. package/src/AudioAPIModule/AudioAPIModule.ts +6 -17
  189. package/src/AudioAPIModule/AudioAPIModule.web.ts +18 -0
  190. package/src/AudioAPIModule/ModuleInterfaces.ts +25 -0
  191. package/src/api.ts +2 -0
  192. package/src/api.web.ts +3 -0
  193. package/src/core/BaseAudioContext.ts +5 -0
  194. package/src/core/WaveShaperNode.ts +43 -0
  195. package/src/interfaces.ts +9 -1
  196. package/src/specs/NativeAudioAPIModule.ts +5 -3
  197. package/src/specs/NativeAudioAPIModule.web.ts +93 -0
  198. package/src/system/AudioManager.ts +19 -14
  199. package/src/system/notification/types.ts +1 -1
  200. package/src/system/types.ts +22 -0
  201. package/src/types.ts +2 -0
  202. package/src/web-core/AudioContext.tsx +5 -0
  203. package/src/web-core/BaseAudioContext.tsx +3 -1
  204. package/src/web-core/OfflineAudioContext.tsx +5 -0
  205. package/src/web-core/WaveShaperNode.tsx +42 -0
  206. package/src/web-system/AudioManager.ts +33 -0
  207. package/src/web-system/index.ts +1 -0
@@ -0,0 +1,79 @@
1
+ #include <audioapi/core/BaseAudioContext.h>
2
+ #include <audioapi/core/effects/WaveShaperNode.h>
3
+ #include <audioapi/dsp/VectorMath.h>
4
+ #include <audioapi/utils/AudioArray.h>
5
+ #include <audioapi/utils/AudioBus.h>
6
+
7
+ #include <algorithm>
8
+ #include <memory>
9
+ #include <string>
10
+
11
+ namespace audioapi {
12
+
13
+ WaveShaperNode::WaveShaperNode(std::shared_ptr<BaseAudioContext> context)
14
+ : AudioNode(context), oversample_(OverSampleType::OVERSAMPLE_NONE) {
15
+
16
+ waveShapers_.reserve(6);
17
+ for (int i = 0; i < channelCount_; i++) {
18
+ waveShapers_.emplace_back(std::make_unique<WaveShaper>(nullptr));
19
+ }
20
+
21
+ // to change after graph processing improvement - should be max
22
+ channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
23
+ isInitialized_ = true;
24
+ }
25
+
26
+ std::string WaveShaperNode::getOversample() const {
27
+ return overSampleTypeToString(oversample_.load(std::memory_order_acquire));
28
+ }
29
+
30
+ void WaveShaperNode::setOversample(const std::string &type) {
31
+ std::scoped_lock<std::mutex> lock(mutex_);
32
+ oversample_.store(overSampleTypeFromString(type), std::memory_order_release);
33
+
34
+ for (int i = 0; i < waveShapers_.size(); i++) {
35
+ waveShapers_[i]->setOversample(overSampleTypeFromString(type));
36
+ }
37
+ }
38
+
39
+ std::shared_ptr<AudioArray> WaveShaperNode::getCurve() const {
40
+ std::scoped_lock<std::mutex> lock(mutex_);
41
+ return curve_;
42
+ }
43
+
44
+ void WaveShaperNode::setCurve(const std::shared_ptr<AudioArray> &curve) {
45
+ std::scoped_lock<std::mutex> lock(mutex_);
46
+ curve_ = curve;
47
+
48
+ for (int i = 0; i < waveShapers_.size(); i++) {
49
+ waveShapers_[i]->setCurve(curve);
50
+ }
51
+ }
52
+
53
+ std::shared_ptr<AudioBus> WaveShaperNode::processNode(
54
+ const std::shared_ptr<AudioBus> &processingBus,
55
+ int framesToProcess) {
56
+ if (!isInitialized_) {
57
+ return processingBus;
58
+ }
59
+
60
+ std::unique_lock<std::mutex> lock(mutex_, std::try_to_lock);
61
+
62
+ if (!lock.owns_lock()) {
63
+ return processingBus;
64
+ }
65
+
66
+ if (curve_ == nullptr) {
67
+ return processingBus;
68
+ }
69
+
70
+ for (int channel = 0; channel < processingBus->getNumberOfChannels(); channel++) {
71
+ auto channelData = processingBus->getSharedChannel(channel);
72
+
73
+ waveShapers_[channel]->process(channelData, framesToProcess);
74
+ }
75
+
76
+ return processingBus;
77
+ }
78
+
79
+ } // namespace audioapi
@@ -0,0 +1,66 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/core/AudioNode.h>
4
+ #include <audioapi/core/types/OverSampleType.h>
5
+ #include <audioapi/dsp/Resampler.h>
6
+ #include <audioapi/dsp/WaveShaper.h>
7
+
8
+ #include <algorithm>
9
+ #include <atomic>
10
+ #include <memory>
11
+ #include <mutex>
12
+ #include <string>
13
+ #include <vector>
14
+
15
+ namespace audioapi {
16
+
17
+ class AudioBus;
18
+ class AudioArray;
19
+
20
+ class WaveShaperNode : public AudioNode {
21
+ public:
22
+ explicit WaveShaperNode(std::shared_ptr<BaseAudioContext> context);
23
+
24
+ [[nodiscard]] std::string getOversample() const;
25
+ [[nodiscard]] std::shared_ptr<AudioArray> getCurve() const;
26
+
27
+ void setOversample(const std::string &type);
28
+ void setCurve(const std::shared_ptr<AudioArray> &curve);
29
+
30
+ protected:
31
+ std::shared_ptr<AudioBus> processNode(
32
+ const std::shared_ptr<AudioBus> &processingBus,
33
+ int framesToProcess) override;
34
+
35
+ private:
36
+ std::atomic<OverSampleType> oversample_;
37
+ std::shared_ptr<AudioArray> curve_{};
38
+ mutable std::mutex mutex_;
39
+
40
+ std::vector<std::unique_ptr<WaveShaper>> waveShapers_{};
41
+
42
+ static OverSampleType overSampleTypeFromString(const std::string &type) {
43
+ std::string lowerType = type;
44
+ std::transform(lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
45
+
46
+ if (lowerType == "2x")
47
+ return OverSampleType::OVERSAMPLE_2X;
48
+ if (lowerType == "4x")
49
+ return OverSampleType::OVERSAMPLE_4X;
50
+
51
+ return OverSampleType::OVERSAMPLE_NONE;
52
+ }
53
+
54
+ static std::string overSampleTypeToString(OverSampleType type) {
55
+ switch (type) {
56
+ case OverSampleType::OVERSAMPLE_2X:
57
+ return "2x";
58
+ case OverSampleType::OVERSAMPLE_4X:
59
+ return "4x";
60
+ default:
61
+ return "none";
62
+ }
63
+ }
64
+ };
65
+
66
+ } // namespace audioapi
@@ -7,16 +7,16 @@
7
7
  namespace audioapi {
8
8
 
9
9
  WorkletNode::WorkletNode(
10
- BaseAudioContext *context,
10
+ std::shared_ptr<BaseAudioContext> context,
11
11
  size_t bufferLength,
12
12
  size_t inputChannelCount,
13
13
  WorkletsRunner &&runtime)
14
14
  : AudioNode(context),
15
15
  workletRunner_(std::move(runtime)),
16
+ bus_(std::make_shared<AudioBus>(bufferLength, inputChannelCount, context->getSampleRate())),
16
17
  bufferLength_(bufferLength),
17
18
  inputChannelCount_(inputChannelCount),
18
19
  curBuffIndex_(0) {
19
- bus_ = std::make_shared<AudioBus>(bufferLength, inputChannelCount, context->getSampleRate());
20
20
  isInitialized_ = true;
21
21
  }
22
22
 
@@ -17,7 +17,7 @@ namespace audioapi {
17
17
  class WorkletNode : public AudioNode {
18
18
  public:
19
19
  explicit WorkletNode(
20
- BaseAudioContext *context,
20
+ std::shared_ptr<BaseAudioContext> context,
21
21
  size_t bufferLength,
22
22
  size_t inputChannelCount,
23
23
  WorkletsRunner &&workletRunner)
@@ -37,7 +37,7 @@ using namespace facebook;
37
37
  class WorkletNode : public AudioNode {
38
38
  public:
39
39
  explicit WorkletNode(
40
- BaseAudioContext *context,
40
+ std::shared_ptr<BaseAudioContext> context,
41
41
  size_t bufferLength,
42
42
  size_t inputChannelCount,
43
43
  WorkletsRunner &&workletRunner);
@@ -6,11 +6,9 @@
6
6
  namespace audioapi {
7
7
 
8
8
  WorkletProcessingNode::WorkletProcessingNode(
9
- BaseAudioContext *context,
9
+ std::shared_ptr<BaseAudioContext> context,
10
10
  WorkletsRunner &&workletRunner)
11
11
  : AudioNode(context), workletRunner_(std::move(workletRunner)) {
12
- isInitialized_ = true;
13
-
14
12
  // Pre-allocate buffers for max 128 frames and 2 channels (stereo)
15
13
  size_t maxChannelCount = 2;
16
14
  inputBuffsHandles_.resize(maxChannelCount);
@@ -23,6 +21,7 @@ WorkletProcessingNode::WorkletProcessingNode(
23
21
  auto outputAudioArray = std::make_shared<AudioArray>(RENDER_QUANTUM_SIZE);
24
22
  outputBuffsHandles_[i] = std::make_shared<AudioArrayBuffer>(outputAudioArray);
25
23
  }
24
+ isInitialized_ = true;
26
25
  }
27
26
 
28
27
  std::shared_ptr<AudioBus> WorkletProcessingNode::processNode(
@@ -60,11 +59,15 @@ std::shared_ptr<AudioBus> WorkletProcessingNode::processNode(
60
59
  // We call unsafely here because we are already on the runtime thread
61
60
  // and the runtime is locked by executeOnRuntimeSync (if
62
61
  // shouldLockRuntime is true)
62
+ float time = 0.0f;
63
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
64
+ time = context->getCurrentTime();
65
+ }
63
66
  return workletRunner_.callUnsafe(
64
67
  inputJsArray,
65
68
  outputJsArray,
66
69
  jsi::Value(rt, static_cast<int>(framesToProcess)),
67
- jsi::Value(rt, this->context_->getCurrentTime()));
70
+ jsi::Value(rt, time));
68
71
  });
69
72
 
70
73
  // Copy processed output data back to the processing bus or zero on failure
@@ -16,7 +16,9 @@ namespace audioapi {
16
16
  #if RN_AUDIO_API_TEST
17
17
  class WorkletProcessingNode : public AudioNode {
18
18
  public:
19
- explicit WorkletProcessingNode(BaseAudioContext *context, WorkletsRunner &&workletRunner)
19
+ explicit WorkletProcessingNode(
20
+ std::shared_ptr<BaseAudioContext> context,
21
+ WorkletsRunner &&workletRunner)
20
22
  : AudioNode(context) {}
21
23
 
22
24
  protected:
@@ -32,7 +34,9 @@ using namespace facebook;
32
34
 
33
35
  class WorkletProcessingNode : public AudioNode {
34
36
  public:
35
- explicit WorkletProcessingNode(BaseAudioContext *context, WorkletsRunner &&workletRunner);
37
+ explicit WorkletProcessingNode(
38
+ std::shared_ptr<BaseAudioContext> context,
39
+ WorkletsRunner &&workletRunner);
36
40
 
37
41
  protected:
38
42
  std::shared_ptr<AudioBus> processNode(
@@ -8,9 +8,8 @@
8
8
 
9
9
  namespace audioapi {
10
10
 
11
- AudioBuffer::AudioBuffer(int numberOfChannels, size_t length, float sampleRate) {
12
- bus_ = std::make_shared<AudioBus>(length, numberOfChannels, sampleRate);
13
- }
11
+ AudioBuffer::AudioBuffer(int numberOfChannels, size_t length, float sampleRate)
12
+ : bus_(std::make_shared<AudioBus>(length, numberOfChannels, sampleRate)) {}
14
13
 
15
14
  AudioBuffer::AudioBuffer(std::shared_ptr<AudioBus> bus) {
16
15
  bus_ = std::move(bus);
@@ -11,7 +11,7 @@ namespace audioapi {
11
11
 
12
12
  class AudioBus;
13
13
 
14
- class AudioBuffer : public std::enable_shared_from_this<AudioBuffer> {
14
+ class AudioBuffer {
15
15
  public:
16
16
  explicit AudioBuffer(int numberOfChannels, size_t length, float sampleRate);
17
17
  explicit AudioBuffer(std::shared_ptr<AudioBus> bus);
@@ -11,21 +11,30 @@
11
11
 
12
12
  namespace audioapi {
13
13
  AudioBufferBaseSourceNode::AudioBufferBaseSourceNode(
14
- BaseAudioContext *context,
14
+ std::shared_ptr<BaseAudioContext> context,
15
15
  bool pitchCorrection)
16
- : AudioScheduledSourceNode(context), pitchCorrection_(pitchCorrection), vReadIndex_(0.0) {
17
- onPositionChangedInterval_ = static_cast<int>(context->getSampleRate() * 0.1);
18
-
19
- detuneParam_ = std::make_shared<AudioParam>(
20
- 0.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context);
21
- playbackRateParam_ = std::make_shared<AudioParam>(
22
- 1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context);
23
-
24
- playbackRateBus_ =
25
- std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE * 3, channelCount_, context_->getSampleRate());
26
-
27
- stretch_ = std::make_shared<signalsmith::stretch::SignalsmithStretch<float>>();
28
- }
16
+ : AudioScheduledSourceNode(context),
17
+ pitchCorrection_(pitchCorrection),
18
+ stretch_(std::make_shared<signalsmith::stretch::SignalsmithStretch<float>>()),
19
+ playbackRateBus_(
20
+ std::make_shared<AudioBus>(
21
+ RENDER_QUANTUM_SIZE * 3,
22
+ channelCount_,
23
+ context->getSampleRate())),
24
+ detuneParam_(
25
+ std::make_shared<AudioParam>(
26
+ 0.0,
27
+ MOST_NEGATIVE_SINGLE_FLOAT,
28
+ MOST_POSITIVE_SINGLE_FLOAT,
29
+ context)),
30
+ playbackRateParam_(
31
+ std::make_shared<AudioParam>(
32
+ 1.0,
33
+ MOST_NEGATIVE_SINGLE_FLOAT,
34
+ MOST_POSITIVE_SINGLE_FLOAT,
35
+ context)),
36
+ vReadIndex_(0.0),
37
+ onPositionChangedInterval_(static_cast<int>(context->getSampleRate() * 0.1f)) {}
29
38
 
30
39
  std::shared_ptr<AudioParam> AudioBufferBaseSourceNode::getDetuneParam() const {
31
40
  return detuneParam_;
@@ -44,8 +53,10 @@ void AudioBufferBaseSourceNode::setOnPositionChangedCallbackId(uint64_t callback
44
53
  }
45
54
 
46
55
  void AudioBufferBaseSourceNode::setOnPositionChangedInterval(int interval) {
47
- onPositionChangedInterval_ =
48
- static_cast<int>(context_->getSampleRate() * static_cast<float>(interval) / 1000);
56
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
57
+ onPositionChangedInterval_ =
58
+ static_cast<int>(context->getSampleRate() * static_cast<float>(interval) / 1000);
59
+ }
49
60
  }
50
61
 
51
62
  int AudioBufferBaseSourceNode::getOnPositionChangedInterval() const {
@@ -58,14 +69,22 @@ std::mutex &AudioBufferBaseSourceNode::getBufferLock() {
58
69
 
59
70
  double AudioBufferBaseSourceNode::getInputLatency() const {
60
71
  if (pitchCorrection_) {
61
- return static_cast<double>(stretch_->inputLatency()) / context_->getSampleRate();
72
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
73
+ return static_cast<double>(stretch_->inputLatency()) / context->getSampleRate();
74
+ } else {
75
+ return 0;
76
+ }
62
77
  }
63
78
  return 0;
64
79
  }
65
80
 
66
81
  double AudioBufferBaseSourceNode::getOutputLatency() const {
67
82
  if (pitchCorrection_) {
68
- return static_cast<double>(stretch_->outputLatency()) / context_->getSampleRate();
83
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
84
+ return static_cast<double>(stretch_->outputLatency()) / context->getSampleRate();
85
+ } else {
86
+ return 0;
87
+ }
69
88
  }
70
89
  return 0;
71
90
  }
@@ -91,7 +110,12 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection(
91
110
  size_t startOffset = 0;
92
111
  size_t offsetLength = 0;
93
112
 
94
- auto time = context_->getCurrentTime();
113
+ std::shared_ptr<BaseAudioContext> context = context_.lock();
114
+ if (context == nullptr) {
115
+ processingBus->zero();
116
+ return;
117
+ }
118
+ auto time = context->getCurrentTime();
95
119
  auto playbackRate =
96
120
  std::clamp(playbackRateParam_->processKRateParam(framesToProcess, time), 0.0f, 3.0f);
97
121
  auto detune =
@@ -101,7 +125,13 @@ void AudioBufferBaseSourceNode::processWithPitchCorrection(
101
125
 
102
126
  auto framesNeededToStretch = static_cast<int>(playbackRate * static_cast<float>(framesToProcess));
103
127
 
104
- updatePlaybackInfo(playbackRateBus_, framesNeededToStretch, startOffset, offsetLength);
128
+ updatePlaybackInfo(
129
+ playbackRateBus_,
130
+ framesNeededToStretch,
131
+ startOffset,
132
+ offsetLength,
133
+ context->getSampleRate(),
134
+ context->getCurrentSampleFrame());
105
135
 
106
136
  if (playbackRate == 0.0f || (!isPlaying() && !isStopScheduled())) {
107
137
  processingBus->zero();
@@ -126,8 +156,14 @@ void AudioBufferBaseSourceNode::processWithoutPitchCorrection(
126
156
  size_t startOffset = 0;
127
157
  size_t offsetLength = 0;
128
158
 
129
- auto computedPlaybackRate = getComputedPlaybackRateValue(framesToProcess);
130
- updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength);
159
+ std::shared_ptr<BaseAudioContext> context = context_.lock();
160
+ if (context == nullptr) {
161
+ processingBus->zero();
162
+ return;
163
+ }
164
+ auto computedPlaybackRate =
165
+ getComputedPlaybackRateValue(framesToProcess, context->getCurrentTime());
166
+ updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength, context->getSampleRate(), context->getCurrentSampleFrame());
131
167
 
132
168
  if (computedPlaybackRate == 0.0f || (!isPlaying() && !isStopScheduled())) {
133
169
  processingBus->zero();
@@ -143,9 +179,7 @@ void AudioBufferBaseSourceNode::processWithoutPitchCorrection(
143
179
  sendOnPositionChangedEvent();
144
180
  }
145
181
 
146
- float AudioBufferBaseSourceNode::getComputedPlaybackRateValue(int framesToProcess) {
147
- auto time = context_->getCurrentTime();
148
-
182
+ float AudioBufferBaseSourceNode::getComputedPlaybackRateValue(int framesToProcess, double time) {
149
183
  auto playbackRate = playbackRateParam_->processKRateParam(framesToProcess, time);
150
184
  auto detune = std::pow(2.0f, detuneParam_->processKRateParam(framesToProcess, time) / 1200.0f);
151
185
 
@@ -14,7 +14,9 @@ class AudioParam;
14
14
 
15
15
  class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
16
16
  public:
17
- explicit AudioBufferBaseSourceNode(BaseAudioContext *context, bool pitchCorrection);
17
+ explicit AudioBufferBaseSourceNode(
18
+ std::shared_ptr<BaseAudioContext> context,
19
+ bool pitchCorrection);
18
20
 
19
21
  [[nodiscard]] std::shared_ptr<AudioParam> getDetuneParam() const;
20
22
  [[nodiscard]] std::shared_ptr<AudioParam> getPlaybackRateParam() const;
@@ -58,7 +60,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
58
60
  const std::shared_ptr<AudioBus> &processingBus,
59
61
  int framesToProcess);
60
62
 
61
- float getComputedPlaybackRateValue(int framesToProcess);
63
+ float getComputedPlaybackRateValue(int framesToProcess, double time);
62
64
 
63
65
  virtual void processWithoutInterpolation(
64
66
  const std::shared_ptr<AudioBus> &processingBus,
@@ -18,11 +18,10 @@
18
18
  namespace audioapi {
19
19
 
20
20
  AudioBufferQueueSourceNode::AudioBufferQueueSourceNode(
21
- BaseAudioContext *context,
21
+ std::shared_ptr<BaseAudioContext> context,
22
22
  bool pitchCorrection)
23
- : AudioBufferBaseSourceNode(context, pitchCorrection) {
24
- buffers_ = {};
25
- stretch_->presetDefault(channelCount_, context_->getSampleRate());
23
+ : AudioBufferBaseSourceNode(context, pitchCorrection), buffers_() {
24
+ stretch_->presetDefault(channelCount_, context->getSampleRate());
26
25
 
27
26
  if (pitchCorrection) {
28
27
  // If pitch correction is enabled, add extra frames at the end
@@ -31,7 +30,7 @@ AudioBufferQueueSourceNode::AudioBufferQueueSourceNode(
31
30
 
32
31
  int extraTailFrames = static_cast<int>(stretch_->inputLatency() + stretch_->outputLatency());
33
32
  tailBuffer_ =
34
- std::make_shared<AudioBuffer>(channelCount_, extraTailFrames, context_->getSampleRate());
33
+ std::make_shared<AudioBuffer>(channelCount_, extraTailFrames, context->getSampleRate());
35
34
 
36
35
  tailBuffer_->bus_->zero();
37
36
  }
@@ -148,8 +147,12 @@ std::shared_ptr<AudioBus> AudioBufferQueueSourceNode::processNode(
148
147
  }
149
148
 
150
149
  double AudioBufferQueueSourceNode::getCurrentPosition() const {
151
- return dsp::sampleFrameToTime(static_cast<int>(vReadIndex_), context_->getSampleRate()) +
152
- playedBuffersDuration_;
150
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
151
+ return dsp::sampleFrameToTime(static_cast<int>(vReadIndex_), context->getSampleRate()) +
152
+ playedBuffersDuration_;
153
+ } else {
154
+ return 0.0;
155
+ }
153
156
  }
154
157
 
155
158
  /**
@@ -192,8 +195,10 @@ void AudioBufferQueueSourceNode::processWithoutInterpolation(
192
195
 
193
196
  std::unordered_map<std::string, EventValue> body = {
194
197
  {"bufferId", std::to_string(bufferId)}, {"isLast", buffers_.empty()}};
195
- context_->audioEventHandlerRegistry_->invokeHandlerWithEventBody(
196
- "ended", onEndedCallbackId_, body);
198
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
199
+ context->audioEventHandlerRegistry_->invokeHandlerWithEventBody(
200
+ "ended", onEndedCallbackId_, body);
201
+ }
197
202
 
198
203
  if (buffers_.empty()) {
199
204
  if (addExtraTailFrames_) {
@@ -277,8 +282,10 @@ void AudioBufferQueueSourceNode::processWithInterpolation(
277
282
  buffers_.pop();
278
283
 
279
284
  std::unordered_map<std::string, EventValue> body = {{"bufferId", std::to_string(bufferId)}};
280
- context_->audioEventHandlerRegistry_->invokeHandlerWithEventBody(
281
- "ended", onEndedCallbackId_, body);
285
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
286
+ context->audioEventHandlerRegistry_->invokeHandlerWithEventBody(
287
+ "ended", onEndedCallbackId_, body);
288
+ }
282
289
 
283
290
  if (buffers_.empty()) {
284
291
  processingBus->zero(writeIndex, framesLeft);
@@ -17,7 +17,9 @@ class AudioParam;
17
17
 
18
18
  class AudioBufferQueueSourceNode : public AudioBufferBaseSourceNode {
19
19
  public:
20
- explicit AudioBufferQueueSourceNode(BaseAudioContext *context, bool pitchCorrection);
20
+ explicit AudioBufferQueueSourceNode(
21
+ std::shared_ptr<BaseAudioContext> context,
22
+ bool pitchCorrection);
21
23
  ~AudioBufferQueueSourceNode() override;
22
24
 
23
25
  void stop(double when) override;
@@ -12,15 +12,16 @@
12
12
 
13
13
  namespace audioapi {
14
14
 
15
- AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext *context, bool pitchCorrection)
15
+ AudioBufferSourceNode::AudioBufferSourceNode(
16
+ std::shared_ptr<BaseAudioContext> context,
17
+ bool pitchCorrection)
16
18
  : AudioBufferBaseSourceNode(context, pitchCorrection),
17
19
  loop_(false),
18
20
  loopSkip_(false),
19
21
  loopStart_(0),
20
- loopEnd_(0) {
21
- buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
22
- alignedBus_ = std::shared_ptr<AudioBus>(nullptr);
23
-
22
+ loopEnd_(0),
23
+ buffer_(nullptr),
24
+ alignedBus_(nullptr) {
24
25
  isInitialized_ = true;
25
26
  }
26
27
 
@@ -61,7 +62,9 @@ void AudioBufferSourceNode::setLoopSkip(bool loopSkip) {
61
62
 
62
63
  void AudioBufferSourceNode::setLoopStart(double loopStart) {
63
64
  if (loopSkip_) {
64
- vReadIndex_ = loopStart * context_->getSampleRate();
65
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
66
+ vReadIndex_ = loopStart * context->getSampleRate();
67
+ }
65
68
  }
66
69
  loopStart_ = loopStart;
67
70
  }
@@ -72,8 +75,9 @@ void AudioBufferSourceNode::setLoopEnd(double loopEnd) {
72
75
 
73
76
  void AudioBufferSourceNode::setBuffer(const std::shared_ptr<AudioBuffer> &buffer) {
74
77
  Locker locker(getBufferLock());
78
+ std::shared_ptr<BaseAudioContext> context = context_.lock();
75
79
 
76
- if (!buffer) {
80
+ if (buffer == nullptr || context == nullptr) {
77
81
  buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
78
82
  alignedBus_ = std::shared_ptr<AudioBus>(nullptr);
79
83
  loopEnd_ = 0;
@@ -87,7 +91,7 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr<AudioBuffer> &buffer
87
91
 
88
92
  if (pitchCorrection_) {
89
93
  int extraTailFrames =
90
- static_cast<int>((getInputLatency() + getOutputLatency()) * context_->getSampleRate());
94
+ static_cast<int>((getInputLatency() + getOutputLatency()) * context->getSampleRate());
91
95
  size_t totalSize = buffer_->getLength() + extraTailFrames;
92
96
 
93
97
  alignedBus_ = std::make_shared<AudioBus>(totalSize, channelCount_, buffer_->getSampleRate());
@@ -97,11 +101,10 @@ void AudioBufferSourceNode::setBuffer(const std::shared_ptr<AudioBuffer> &buffer
97
101
  } else {
98
102
  alignedBus_ = std::make_shared<AudioBus>(*buffer_->bus_);
99
103
  }
100
-
101
104
  audioBus_ =
102
- std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, context_->getSampleRate());
103
- playbackRateBus_ =
104
- std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE * 3, channelCount_, context_->getSampleRate());
105
+ std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
106
+ playbackRateBus_ = std::make_shared<AudioBus>(
107
+ RENDER_QUANTUM_SIZE * 3, channelCount_, context->getSampleRate());
105
108
 
106
109
  loopEnd_ = buffer_->getDuration();
107
110
  }
@@ -189,8 +192,15 @@ void AudioBufferSourceNode::processWithoutInterpolation(
189
192
  auto readIndex = static_cast<size_t>(vReadIndex_);
190
193
  size_t writeIndex = startOffset;
191
194
 
192
- auto frameStart = static_cast<size_t>(getVirtualStartFrame());
193
- auto frameEnd = static_cast<size_t>(getVirtualEndFrame());
195
+ size_t frameStart;
196
+ size_t frameEnd;
197
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
198
+ frameStart = static_cast<size_t>(getVirtualStartFrame(context->getSampleRate()));
199
+ frameEnd = static_cast<size_t>(getVirtualEndFrame(context->getSampleRate()));
200
+ } else {
201
+ processingBus->zero();
202
+ return;
203
+ }
194
204
  size_t frameDelta = frameEnd - frameStart;
195
205
 
196
206
  size_t framesLeft = offsetLength;
@@ -257,8 +267,15 @@ void AudioBufferSourceNode::processWithInterpolation(
257
267
 
258
268
  size_t writeIndex = startOffset;
259
269
 
260
- auto vFrameStart = getVirtualStartFrame();
261
- auto vFrameEnd = getVirtualEndFrame();
270
+ double vFrameStart;
271
+ double vFrameEnd;
272
+ if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
273
+ vFrameStart = getVirtualStartFrame(context->getSampleRate());
274
+ vFrameEnd = getVirtualEndFrame(context->getSampleRate());
275
+ } else {
276
+ processingBus->zero();
277
+ return;
278
+ }
262
279
  auto vFrameDelta = vFrameEnd - vFrameStart;
263
280
 
264
281
  auto frameStart = static_cast<size_t>(vFrameStart);
@@ -305,15 +322,14 @@ void AudioBufferSourceNode::processWithInterpolation(
305
322
  }
306
323
  }
307
324
 
308
- double AudioBufferSourceNode::getVirtualStartFrame() {
309
- auto loopStartFrame = loopStart_ * context_->getSampleRate();
310
-
325
+ double AudioBufferSourceNode::getVirtualStartFrame(float sampleRate) {
326
+ auto loopStartFrame = loopStart_ * sampleRate;
311
327
  return loop_ && loopStartFrame >= 0 && loopStart_ < loopEnd_ ? loopStartFrame : 0.0;
312
328
  }
313
329
 
314
- double AudioBufferSourceNode::getVirtualEndFrame() {
330
+ double AudioBufferSourceNode::getVirtualEndFrame(float sampleRate) {
315
331
  auto inputBufferLength = static_cast<double>(alignedBus_->getSize());
316
- auto loopEndFrame = loopEnd_ * context_->getSampleRate();
332
+ auto loopEndFrame = loopEnd_ * sampleRate;
317
333
 
318
334
  return loop_ && loopEndFrame > 0 && loopStart_ < loopEnd_
319
335
  ? std::min(loopEndFrame, inputBufferLength)
@@ -16,7 +16,7 @@ class AudioParam;
16
16
 
17
17
  class AudioBufferSourceNode : public AudioBufferBaseSourceNode {
18
18
  public:
19
- explicit AudioBufferSourceNode(BaseAudioContext *context, bool pitchCorrection);
19
+ explicit AudioBufferSourceNode(std::shared_ptr<BaseAudioContext> context, bool pitchCorrection);
20
20
  ~AudioBufferSourceNode() override;
21
21
 
22
22
  [[nodiscard]] bool getLoop() const;
@@ -69,8 +69,8 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode {
69
69
  size_t offsetLength,
70
70
  float playbackRate) override;
71
71
 
72
- double getVirtualStartFrame();
73
- double getVirtualEndFrame();
72
+ double getVirtualStartFrame(float sampleRate);
73
+ double getVirtualEndFrame(float sampleRate);
74
74
  };
75
75
 
76
76
  } // namespace audioapi