react-native-audio-api 0.6.0-rc.5 → 0.6.0

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 (201) hide show
  1. package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +35 -2
  2. package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +4 -0
  3. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +31 -17
  4. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +1 -3
  5. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +56 -2
  6. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +0 -12
  7. package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +35 -12
  8. package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +30 -29
  9. package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +20 -22
  10. package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +19 -9
  11. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +30 -11
  12. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +34 -27
  13. package/android/src/main/java/com/swmansion/audioapi/system/VolumeChangeListener.kt +10 -5
  14. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +39 -0
  15. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +20 -14
  16. package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +2 -3
  17. package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +24 -11
  18. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +1 -0
  19. package/common/cpp/audioapi/HostObjects/AudioRecorderHostObject.h +10 -89
  20. package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +3 -24
  21. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +2 -2
  22. package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +2 -3
  23. package/common/cpp/audioapi/core/AudioContext.cpp +4 -1
  24. package/common/cpp/audioapi/core/AudioContext.h +1 -1
  25. package/common/cpp/audioapi/core/AudioNode.cpp +31 -2
  26. package/common/cpp/audioapi/core/AudioNode.h +7 -1
  27. package/common/cpp/audioapi/core/AudioParam.cpp +84 -2
  28. package/common/cpp/audioapi/core/AudioParam.h +14 -1
  29. package/common/cpp/audioapi/core/BaseAudioContext.cpp +6 -1
  30. package/common/cpp/audioapi/core/BaseAudioContext.h +7 -1
  31. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +3 -2
  32. package/common/cpp/audioapi/core/OfflineAudioContext.h +1 -1
  33. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +28 -26
  34. package/common/cpp/audioapi/core/effects/GainNode.cpp +9 -9
  35. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +5 -2
  36. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +56 -0
  37. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +13 -13
  38. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +14 -10
  39. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
  40. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +7 -6
  41. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +5 -3
  42. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +15 -10
  43. package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +35 -1
  44. package/common/cpp/audioapi/core/utils/AudioNodeManager.h +15 -1
  45. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +108 -0
  46. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +62 -0
  47. package/common/cpp/audioapi/events/AudioEventHandlerRegistryHostObject.h +48 -0
  48. package/common/cpp/audioapi/jsi/JsiPromise.cpp +3 -4
  49. package/ios/audioapi/ios/AudioAPIModule.h +13 -0
  50. package/ios/audioapi/ios/AudioAPIModule.mm +115 -6
  51. package/ios/audioapi/ios/core/IOSAudioRecorder.h +2 -10
  52. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +6 -17
  53. package/ios/audioapi/ios/core/NativeAudioPlayer.m +2 -0
  54. package/ios/audioapi/ios/core/NativeAudioRecorder.m +7 -3
  55. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.h +7 -0
  56. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.mm +12 -0
  57. package/ios/audioapi/ios/system/AudioEngine.h +5 -0
  58. package/ios/audioapi/ios/system/AudioEngine.mm +7 -15
  59. package/ios/audioapi/ios/system/AudioSessionManager.h +1 -1
  60. package/ios/audioapi/ios/system/AudioSessionManager.mm +2 -18
  61. package/ios/audioapi/ios/system/LockScreenManager.h +3 -3
  62. package/ios/audioapi/ios/system/LockScreenManager.mm +36 -48
  63. package/ios/audioapi/ios/system/NotificationManager.h +3 -3
  64. package/ios/audioapi/ios/system/NotificationManager.mm +21 -29
  65. package/lib/commonjs/api.js +4 -4
  66. package/lib/commonjs/api.js.map +1 -1
  67. package/lib/commonjs/core/AudioBufferSourceNode.js +2 -2
  68. package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
  69. package/lib/commonjs/core/AudioNode.js +8 -2
  70. package/lib/commonjs/core/AudioNode.js.map +1 -1
  71. package/lib/commonjs/core/AudioParam.js +2 -1
  72. package/lib/commonjs/core/AudioParam.js.map +1 -1
  73. package/lib/commonjs/core/AudioRecorder.js +11 -28
  74. package/lib/commonjs/core/AudioRecorder.js.map +1 -1
  75. package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -1
  76. package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
  77. package/lib/commonjs/core/BiquadFilterNode.js +4 -4
  78. package/lib/commonjs/core/BiquadFilterNode.js.map +1 -1
  79. package/lib/commonjs/core/GainNode.js +1 -1
  80. package/lib/commonjs/core/GainNode.js.map +1 -1
  81. package/lib/commonjs/core/OscillatorNode.js +2 -2
  82. package/lib/commonjs/core/OscillatorNode.js.map +1 -1
  83. package/lib/commonjs/core/StereoPannerNode.js +1 -1
  84. package/lib/commonjs/core/StereoPannerNode.js.map +1 -1
  85. package/lib/commonjs/events/AudioEventEmitter.js +22 -0
  86. package/lib/commonjs/events/AudioEventEmitter.js.map +1 -0
  87. package/lib/commonjs/events/AudioEventSubscription.js +20 -0
  88. package/lib/commonjs/events/AudioEventSubscription.js.map +1 -0
  89. package/lib/commonjs/events/index.js +21 -0
  90. package/lib/commonjs/events/index.js.map +1 -0
  91. package/lib/commonjs/events/types.js +6 -0
  92. package/lib/commonjs/events/types.js.map +1 -0
  93. package/lib/commonjs/hooks/useSytemVolume.js +1 -1
  94. package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
  95. package/lib/commonjs/specs/NativeAudioAPIModule.js +3 -3
  96. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  97. package/lib/commonjs/specs/index.js +2 -16
  98. package/lib/commonjs/specs/index.js.map +1 -1
  99. package/lib/commonjs/system/AudioManager.js +22 -28
  100. package/lib/commonjs/system/AudioManager.js.map +1 -1
  101. package/lib/module/api.js +2 -2
  102. package/lib/module/api.js.map +1 -1
  103. package/lib/module/core/AudioBufferSourceNode.js +2 -2
  104. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  105. package/lib/module/core/AudioNode.js +7 -2
  106. package/lib/module/core/AudioNode.js.map +1 -1
  107. package/lib/module/core/AudioParam.js +2 -1
  108. package/lib/module/core/AudioParam.js.map +1 -1
  109. package/lib/module/core/AudioRecorder.js +11 -28
  110. package/lib/module/core/AudioRecorder.js.map +1 -1
  111. package/lib/module/core/AudioScheduledSourceNode.js +4 -1
  112. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  113. package/lib/module/core/BiquadFilterNode.js +4 -4
  114. package/lib/module/core/BiquadFilterNode.js.map +1 -1
  115. package/lib/module/core/GainNode.js +1 -1
  116. package/lib/module/core/GainNode.js.map +1 -1
  117. package/lib/module/core/OscillatorNode.js +2 -2
  118. package/lib/module/core/OscillatorNode.js.map +1 -1
  119. package/lib/module/core/StereoPannerNode.js +1 -1
  120. package/lib/module/core/StereoPannerNode.js.map +1 -1
  121. package/lib/module/events/AudioEventEmitter.js +16 -0
  122. package/lib/module/events/AudioEventEmitter.js.map +1 -0
  123. package/lib/module/events/AudioEventSubscription.js +15 -0
  124. package/lib/module/events/AudioEventSubscription.js.map +1 -0
  125. package/lib/module/events/index.js +6 -0
  126. package/lib/module/events/index.js.map +1 -0
  127. package/lib/module/events/types.js +4 -0
  128. package/lib/module/events/types.js.map +1 -0
  129. package/lib/module/hooks/useSytemVolume.js +1 -1
  130. package/lib/module/hooks/useSytemVolume.js.map +1 -1
  131. package/lib/module/specs/NativeAudioAPIModule.js +3 -2
  132. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  133. package/lib/module/specs/index.js +2 -3
  134. package/lib/module/specs/index.js.map +1 -1
  135. package/lib/module/system/AudioManager.js +23 -29
  136. package/lib/module/system/AudioManager.js.map +1 -1
  137. package/lib/typescript/api.d.ts +2 -1
  138. package/lib/typescript/api.d.ts.map +1 -1
  139. package/lib/typescript/core/AudioNode.d.ts +2 -1
  140. package/lib/typescript/core/AudioNode.d.ts.map +1 -1
  141. package/lib/typescript/core/AudioParam.d.ts +4 -2
  142. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  143. package/lib/typescript/core/AudioRecorder.d.ts +4 -14
  144. package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
  145. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +3 -1
  146. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
  147. package/lib/typescript/events/AudioEventEmitter.d.ts +10 -0
  148. package/lib/typescript/events/AudioEventEmitter.d.ts.map +1 -0
  149. package/lib/typescript/events/AudioEventSubscription.d.ts +11 -0
  150. package/lib/typescript/events/AudioEventSubscription.d.ts.map +1 -0
  151. package/lib/typescript/events/index.d.ts +4 -0
  152. package/lib/typescript/events/index.d.ts.map +1 -0
  153. package/lib/typescript/events/types.d.ts +50 -0
  154. package/lib/typescript/events/types.d.ts.map +1 -0
  155. package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
  156. package/lib/typescript/interfaces.d.ts +10 -10
  157. package/lib/typescript/interfaces.d.ts.map +1 -1
  158. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +15 -3
  159. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  160. package/lib/typescript/specs/index.d.ts +2 -3
  161. package/lib/typescript/specs/index.d.ts.map +1 -1
  162. package/lib/typescript/system/AudioManager.d.ts +6 -4
  163. package/lib/typescript/system/AudioManager.d.ts.map +1 -1
  164. package/lib/typescript/system/types.d.ts +0 -34
  165. package/lib/typescript/system/types.d.ts.map +1 -1
  166. package/lib/typescript/types.d.ts +0 -1
  167. package/lib/typescript/types.d.ts.map +1 -1
  168. package/package.json +3 -3
  169. package/src/api.ts +6 -3
  170. package/src/core/AudioBufferSourceNode.ts +2 -2
  171. package/src/core/AudioNode.ts +8 -3
  172. package/src/core/AudioParam.ts +5 -2
  173. package/src/core/AudioRecorder.ts +22 -62
  174. package/src/core/AudioScheduledSourceNode.ts +13 -2
  175. package/src/core/BiquadFilterNode.ts +4 -4
  176. package/src/core/GainNode.ts +1 -1
  177. package/src/core/OscillatorNode.ts +2 -2
  178. package/src/core/StereoPannerNode.ts +1 -1
  179. package/src/events/AudioEventEmitter.ts +29 -0
  180. package/src/events/AudioEventSubscription.ts +26 -0
  181. package/src/events/index.ts +4 -0
  182. package/src/events/types.ts +64 -0
  183. package/src/hooks/useSytemVolume.ts +2 -1
  184. package/src/interfaces.ts +19 -20
  185. package/src/specs/NativeAudioAPIModule.ts +23 -2
  186. package/src/specs/index.ts +2 -4
  187. package/src/system/AudioManager.ts +35 -43
  188. package/src/system/types.ts +0 -42
  189. package/src/types.ts +0 -8
  190. package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +0 -77
  191. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionEventEmitter.kt +0 -88
  192. package/android/src/oldarch/NativeAudioManagerModuleSpec.java +0 -99
  193. package/ios/audioapi/ios/AudioManagerModule.h +0 -18
  194. package/ios/audioapi/ios/AudioManagerModule.mm +0 -108
  195. package/lib/commonjs/specs/NativeAudioManagerModule.js +0 -42
  196. package/lib/commonjs/specs/NativeAudioManagerModule.js.map +0 -1
  197. package/lib/module/specs/NativeAudioManagerModule.js +0 -39
  198. package/lib/module/specs/NativeAudioManagerModule.js.map +0 -1
  199. package/lib/typescript/specs/NativeAudioManagerModule.d.ts +0 -18
  200. package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +0 -1
  201. package/src/specs/NativeAudioManagerModule.ts +0 -53
@@ -1,28 +1,26 @@
1
1
  #pragma once
2
2
 
3
3
  #include <memory>
4
- #include <functional>
5
4
 
6
5
  namespace audioapi {
7
6
  class AudioBus;
7
+ class CircularAudioArray;
8
+ class AudioEventHandlerRegistry;
8
9
 
9
10
  class AudioRecorder {
10
11
  public:
11
12
  explicit AudioRecorder(
12
13
  float sampleRate,
13
14
  int bufferLength,
14
- const std::function<void(void)> &onError,
15
- const std::function<void(void)> &onStatusChange,
16
- const std::function<void(std::shared_ptr<AudioBus>, int, double)> &onAudioReady
17
- )
18
- : sampleRate_(sampleRate),
19
- bufferLength_(bufferLength),
20
- onError_(onError),
21
- onStatusChange_(onStatusChange),
22
- onAudioReady_(onAudioReady) {}
15
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry
16
+ );
23
17
 
24
18
  virtual ~AudioRecorder() = default;
25
19
 
20
+ void setOnAudioReadyCallbackId(uint64_t callbackId);
21
+ void invokeOnAudioReadyCallback(const std::shared_ptr<AudioBus> &bus, int numFrames, double when);
22
+ void sendRemainingData();
23
+
26
24
  virtual void start() = 0;
27
25
  virtual void stop() = 0;
28
26
 
@@ -30,9 +28,11 @@ class AudioRecorder {
30
28
  float sampleRate_;
31
29
  int bufferLength_;
32
30
 
33
- std::function<void(void)> onError_;
34
- std::function<void(void)> onStatusChange_;
35
- std::function<void(std::shared_ptr<AudioBus>, int, double)> onAudioReady_;
31
+ std::atomic<bool> isRunning_;
32
+ std::shared_ptr<CircularAudioArray> circularBuffer_;
33
+
34
+ std::shared_ptr<AudioEventHandlerRegistry> audioEventHandlerRegistry_;
35
+ uint64_t onAudioReadyCallbackId_ = 0;
36
36
  };
37
37
 
38
38
  } // namespace audioapi
@@ -22,9 +22,9 @@ AudioBufferSourceNode::AudioBufferSourceNode(
22
22
  alignedBus_ = std::shared_ptr<AudioBus>(nullptr);
23
23
 
24
24
  detuneParam_ = std::make_shared<AudioParam>(
25
- 0.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);
25
+ 0.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context);
26
26
  playbackRateParam_ = std::make_shared<AudioParam>(
27
- 1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);
27
+ 1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context);
28
28
 
29
29
  playbackRateBus_ = std::make_shared<AudioBus>(
30
30
  RENDER_QUANTUM_SIZE * 3, channelCount_, context_->getSampleRate());
@@ -173,7 +173,7 @@ void AudioBufferSourceNode::processWithoutPitchCorrection(
173
173
  size_t startOffset = 0;
174
174
  size_t offsetLength = 0;
175
175
 
176
- auto computedPlaybackRate = getComputedPlaybackRateValue();
176
+ auto computedPlaybackRate = getComputedPlaybackRateValue(framesToProcess);
177
177
  updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength);
178
178
 
179
179
  if (computedPlaybackRate == 0.0f || (!isPlaying() && !isStopScheduled())) {
@@ -197,10 +197,12 @@ void AudioBufferSourceNode::processWithPitchCorrection(
197
197
  size_t offsetLength = 0;
198
198
 
199
199
  auto time = context_->getCurrentTime();
200
- auto playbackRate =
201
- std::clamp(playbackRateParam_->getValueAtTime(time), 0.0f, 3.0f);
202
- auto detune =
203
- std::clamp(detuneParam_->getValueAtTime(time) / 100.0f, -12.0f, 12.0f);
200
+ auto playbackRate = std::clamp(
201
+ playbackRateParam_->processKRateParam(framesToProcess, time), 0.0f, 3.0f);
202
+ auto detune = std::clamp(
203
+ detuneParam_->processKRateParam(framesToProcess, time) / 100.0f,
204
+ -12.0f,
205
+ 12.0f);
204
206
 
205
207
  playbackRateBus_->zero();
206
208
 
@@ -349,13 +351,15 @@ void AudioBufferSourceNode::processWithInterpolation(
349
351
  }
350
352
  }
351
353
 
352
- float AudioBufferSourceNode::getComputedPlaybackRateValue() {
354
+ float AudioBufferSourceNode::getComputedPlaybackRateValue(int framesToProcess) {
353
355
  auto time = context_->getCurrentTime();
354
356
 
355
357
  auto sampleRateFactor =
356
358
  alignedBus_->getSampleRate() / context_->getSampleRate();
357
- auto playbackRate = playbackRateParam_->getValueAtTime(time);
358
- auto detune = std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
359
+ auto playbackRate =
360
+ playbackRateParam_->processKRateParam(framesToProcess, time);
361
+ auto detune = std::pow(
362
+ 2.0f, detuneParam_->processKRateParam(framesToProcess, time) / 1200.0f);
359
363
 
360
364
  return playbackRate * sampleRateFactor * detune;
361
365
  }
@@ -81,7 +81,7 @@ class AudioBufferSourceNode : public AudioScheduledSourceNode {
81
81
  size_t offsetLength,
82
82
  float playbackRate);
83
83
 
84
- float getComputedPlaybackRateValue();
84
+ float getComputedPlaybackRateValue(int framesToProcess);
85
85
 
86
86
  double getVirtualStartFrame();
87
87
  double getVirtualEndFrame();
@@ -2,6 +2,7 @@
2
2
  #include <audioapi/core/sources/AudioScheduledSourceNode.h>
3
3
  #include <audioapi/core/utils/AudioNodeManager.h>
4
4
  #include <audioapi/dsp/AudioUtils.h>
5
+ #include <audioapi/events/AudioEventHandlerRegistry.h>
5
6
  #include <audioapi/utils/AudioArray.h>
6
7
  #include <audioapi/utils/AudioBus.h>
7
8
 
@@ -44,9 +45,8 @@ bool AudioScheduledSourceNode::isStopScheduled() {
44
45
  return playbackState_ == PlaybackState::STOP_SCHEDULED;
45
46
  }
46
47
 
47
- void AudioScheduledSourceNode::setOnendedCallback(
48
- const std::function<void(double)> &onendedCallback) {
49
- onendedCallback_ = onendedCallback;
48
+ void AudioScheduledSourceNode::setOnEndedCallbackId(const uint64_t callbackId) {
49
+ onEndedCallbackId_ = callbackId;
50
50
  }
51
51
 
52
52
  void AudioScheduledSourceNode::updatePlaybackInfo(
@@ -144,9 +144,10 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
144
144
  void AudioScheduledSourceNode::disable() {
145
145
  AudioNode::disable();
146
146
 
147
- if (onendedCallback_) {
148
- onendedCallback_(getStopTime());
149
- }
147
+ std::unordered_map<std::string, EventValue> body = {{"value", getStopTime()}};
148
+
149
+ context_->audioEventHandlerRegistry_->invokeHandlerWithEventBody(
150
+ "ended", onEndedCallbackId_, body);
150
151
  }
151
152
 
152
153
  void AudioScheduledSourceNode::handleStopScheduled() {
@@ -16,6 +16,8 @@
16
16
 
17
17
  namespace audioapi {
18
18
 
19
+ class AudioEventHandlerRegistry;
20
+
19
21
  class AudioScheduledSourceNode : public AudioNode {
20
22
  public:
21
23
  // UNSCHEDULED: The node is not scheduled to play.
@@ -35,7 +37,7 @@ class AudioScheduledSourceNode : public AudioNode {
35
37
  bool isFinished();
36
38
  bool isStopScheduled();
37
39
 
38
- void setOnendedCallback(const std::function<void(double)> &onendedCallback);
40
+ void setOnEndedCallbackId(uint64_t callbackId);
39
41
 
40
42
  virtual double getStopTime() const = 0;
41
43
  void disable() override;
@@ -43,8 +45,6 @@ class AudioScheduledSourceNode : public AudioNode {
43
45
  protected:
44
46
  PlaybackState playbackState_;
45
47
 
46
- std::function<void(double)> onendedCallback_;
47
-
48
48
  void updatePlaybackInfo(
49
49
  const std::shared_ptr<AudioBus>& processingBus,
50
50
  int framesToProcess,
@@ -56,6 +56,8 @@ class AudioScheduledSourceNode : public AudioNode {
56
56
  private:
57
57
  double startTime_;
58
58
  double stopTime_;
59
+
60
+ uint64_t onEndedCallbackId_ = 0;
59
61
  };
60
62
 
61
63
  } // namespace audioapi
@@ -9,11 +9,15 @@ namespace audioapi {
9
9
  OscillatorNode::OscillatorNode(BaseAudioContext *context)
10
10
  : AudioScheduledSourceNode(context) {
11
11
  frequencyParam_ = std::make_shared<AudioParam>(
12
- 444.0, -context_->getNyquistFrequency(), context_->getNyquistFrequency());
12
+ 444.0,
13
+ -context_->getNyquistFrequency(),
14
+ context_->getNyquistFrequency(),
15
+ context);
13
16
  detuneParam_ = std::make_shared<AudioParam>(
14
17
  0.0,
15
18
  -1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT,
16
- 1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT);
19
+ 1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT,
20
+ context);
17
21
  type_ = OscillatorType::SINE;
18
22
  periodicWave_ = context_->getBasicWaveForm(type_);
19
23
 
@@ -56,15 +60,18 @@ void OscillatorNode::processNode(
56
60
  return;
57
61
  }
58
62
 
59
- auto deltaTime = 1.0 / context_->getSampleRate();
60
- auto time =
61
- context_->getCurrentTime() + static_cast<double>(startOffset) * deltaTime;
63
+ auto time = context_->getCurrentTime() +
64
+ static_cast<double>(startOffset) * 1.0 / context_->getSampleRate();
65
+ auto detuneParamValues =
66
+ detuneParam_->processARateParam(framesToProcess, time);
67
+ auto frequencyParamValues =
68
+ frequencyParam_->processARateParam(framesToProcess, time);
62
69
 
63
70
  for (size_t i = startOffset; i < offsetLength; i += 1) {
64
- auto detuneRatio =
65
- std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
71
+ auto detuneRatio = std::pow(
72
+ 2.0f, detuneParamValues->getChannel(0)->getData()[i] / 1200.0f);
66
73
  auto detunedFrequency =
67
- round(frequencyParam_->getValueAtTime(time) * detuneRatio);
74
+ frequencyParamValues->getChannel(0)->getData()[i] * detuneRatio;
68
75
  auto phaseIncrement = detunedFrequency * periodicWave_->getScale();
69
76
 
70
77
  float sample =
@@ -79,8 +86,6 @@ void OscillatorNode::processNode(
79
86
  floor(
80
87
  phase_ / static_cast<float>(periodicWave_->getPeriodicWaveSize())) *
81
88
  static_cast<float>(periodicWave_->getPeriodicWaveSize());
82
-
83
- time += deltaTime;
84
89
  }
85
90
 
86
91
  handleStopScheduled();
@@ -1,4 +1,5 @@
1
1
  #include <audioapi/core/AudioNode.h>
2
+ #include <audioapi/core/AudioParam.h>
2
3
  #include <audioapi/core/sources/AudioScheduledSourceNode.h>
3
4
  #include <audioapi/core/utils/AudioNodeManager.h>
4
5
  #include <audioapi/core/utils/Locker.h>
@@ -9,7 +10,7 @@ AudioNodeManager::~AudioNodeManager() {
9
10
  cleanup();
10
11
  }
11
12
 
12
- void AudioNodeManager::addPendingConnection(
13
+ void AudioNodeManager::addPendingNodeConnection(
13
14
  const std::shared_ptr<AudioNode> &from,
14
15
  const std::shared_ptr<AudioNode> &to,
15
16
  ConnectionType type) {
@@ -18,6 +19,15 @@ void AudioNodeManager::addPendingConnection(
18
19
  audioNodesToConnect_.emplace_back(from, to, type);
19
20
  }
20
21
 
22
+ void AudioNodeManager::addPendingParamConnection(
23
+ const std::shared_ptr<AudioNode> &from,
24
+ const std::shared_ptr<AudioParam> &to,
25
+ ConnectionType type) {
26
+ Locker lock(getGraphLock());
27
+
28
+ audioParamToConnect_.emplace_back(from, to, type);
29
+ }
30
+
21
31
  void AudioNodeManager::preProcessGraph() {
22
32
  if (auto locker = Locker::tryLock(getGraphLock())) {
23
33
  settlePendingConnections();
@@ -41,6 +51,11 @@ void AudioNodeManager::addSourceNode(
41
51
  sourceNodes_.insert(node);
42
52
  }
43
53
 
54
+ void AudioNodeManager::addAudioParam(const std::shared_ptr<AudioParam> &param) {
55
+ Locker lock(getGraphLock());
56
+ audioParams_.insert(param);
57
+ }
58
+
44
59
  void AudioNodeManager::settlePendingConnections() {
45
60
  for (auto it = audioNodesToConnect_.begin(), end = audioNodesToConnect_.end();
46
61
  it != end;
@@ -60,6 +75,25 @@ void AudioNodeManager::settlePendingConnections() {
60
75
  }
61
76
 
62
77
  audioNodesToConnect_.clear();
78
+
79
+ for (auto it = audioParamToConnect_.begin(), end = audioParamToConnect_.end();
80
+ it != end;
81
+ ++it) {
82
+ std::shared_ptr<AudioNode> from = std::get<0>(*it);
83
+ std::shared_ptr<AudioParam> to = std::get<1>(*it);
84
+ ConnectionType type = std::get<2>(*it);
85
+
86
+ assert(from != nullptr);
87
+ assert(to != nullptr);
88
+
89
+ if (type == ConnectionType::CONNECT) {
90
+ from->connectParam(to);
91
+ } else {
92
+ from->disconnectParam(to);
93
+ }
94
+ }
95
+
96
+ audioParamToConnect_.clear();
63
97
  }
64
98
 
65
99
  void AudioNodeManager::cleanupNode(const std::shared_ptr<AudioNode> &node) {
@@ -12,6 +12,7 @@ namespace audioapi {
12
12
 
13
13
  class AudioNode;
14
14
  class AudioScheduledSourceNode;
15
+ class AudioParam;
15
16
 
16
17
  class AudioNodeManager {
17
18
  public:
@@ -23,13 +24,19 @@ class AudioNodeManager {
23
24
 
24
25
  void preProcessGraph();
25
26
 
26
- void addPendingConnection(
27
+ void addPendingNodeConnection(
27
28
  const std::shared_ptr<AudioNode> &from,
28
29
  const std::shared_ptr<AudioNode> &to,
29
30
  ConnectionType type);
30
31
 
32
+ void addPendingParamConnection(
33
+ const std::shared_ptr<AudioNode> &from,
34
+ const std::shared_ptr<AudioParam> &to,
35
+ ConnectionType type);
36
+
31
37
  void addProcessingNode(const std::shared_ptr<AudioNode> &node);
32
38
  void addSourceNode(const std::shared_ptr<AudioScheduledSourceNode> &node);
39
+ void addAudioParam(const std::shared_ptr<AudioParam> &param);
33
40
 
34
41
  void cleanup();
35
42
 
@@ -40,6 +47,7 @@ class AudioNodeManager {
40
47
  // all nodes created in the context
41
48
  std::unordered_set<std::shared_ptr<AudioScheduledSourceNode>> sourceNodes_;
42
49
  std::unordered_set<std::shared_ptr<AudioNode>> processingNodes_;
50
+ std::unordered_set<std::shared_ptr<AudioParam>> audioParams_;
43
51
 
44
52
  // connections to be settled
45
53
  std::vector<std::tuple<
@@ -48,6 +56,12 @@ class AudioNodeManager {
48
56
  ConnectionType>>
49
57
  audioNodesToConnect_;
50
58
 
59
+ std::vector<std::tuple<
60
+ std::shared_ptr<AudioNode>,
61
+ std::shared_ptr<AudioParam>,
62
+ ConnectionType>>
63
+ audioParamToConnect_;
64
+
51
65
  void settlePendingConnections();
52
66
  void cleanupNode(const std::shared_ptr<AudioNode> &node);
53
67
  void prepareNodesForDestruction();
@@ -0,0 +1,108 @@
1
+ #include <audioapi/events/AudioEventHandlerRegistry.h>
2
+
3
+ namespace audioapi {
4
+
5
+ AudioEventHandlerRegistry::AudioEventHandlerRegistry(
6
+ jsi::Runtime *runtime,
7
+ const std::shared_ptr<react::CallInvoker> &callInvoker) {
8
+ runtime_ = runtime;
9
+ callInvoker_ = callInvoker;
10
+
11
+ for (const auto &eventName : SYSTEM_EVENT_NAMES) {
12
+ eventHandlers_[std::string(eventName)] = {};
13
+ }
14
+
15
+ for (const auto &eventName : AUDIO_API_EVENT_NAMES) {
16
+ eventHandlers_[std::string(eventName)] = {};
17
+ }
18
+ }
19
+
20
+ AudioEventHandlerRegistry::~AudioEventHandlerRegistry() {
21
+ eventHandlers_.clear();
22
+ }
23
+
24
+ uint64_t AudioEventHandlerRegistry::registerHandler(
25
+ const std::string &eventName,
26
+ const std::shared_ptr<jsi::Function> &handler) {
27
+ static uint64_t LISTENER_ID = 0;
28
+
29
+ eventHandlers_[eventName][LISTENER_ID] = handler;
30
+
31
+ return LISTENER_ID++;
32
+ }
33
+
34
+ void AudioEventHandlerRegistry::unregisterHandler(
35
+ const std::string &eventName,
36
+ uint64_t listenerId) {
37
+ auto it = eventHandlers_.find(eventName);
38
+ if (it != eventHandlers_.end()) {
39
+ it->second.erase(listenerId);
40
+ }
41
+ }
42
+
43
+ void AudioEventHandlerRegistry::invokeHandlerWithEventBody(
44
+ const std::string &eventName,
45
+ const std::unordered_map<std::string, EventValue> &body) {
46
+ auto it = eventHandlers_.find(eventName);
47
+ if (it != eventHandlers_.end()) {
48
+ for (const auto &pair : it->second) {
49
+ auto handler = pair.second;
50
+ if (handler) {
51
+ callInvoker_->invokeAsync([this, handler, body]() {
52
+ auto eventObject = createEventObject(body);
53
+ handler->call(*runtime_, eventObject);
54
+ });
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ void AudioEventHandlerRegistry::invokeHandlerWithEventBody(
61
+ const std::string &eventName,
62
+ uint64_t listenerId,
63
+ const std::unordered_map<std::string, EventValue> &body) {
64
+ auto it = eventHandlers_.find(eventName);
65
+ if (it != eventHandlers_.end()) {
66
+ auto handlersMap = it->second;
67
+ auto handlerIt = handlersMap.find(listenerId);
68
+ if (handlerIt != handlersMap.end()) {
69
+ auto handler = handlerIt->second;
70
+ if (handler) {
71
+ callInvoker_->invokeAsync([this, handler, body]() {
72
+ auto eventObject = createEventObject(body);
73
+ handler->call(*runtime_, eventObject);
74
+ });
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ jsi::Object AudioEventHandlerRegistry::createEventObject(
81
+ const std::unordered_map<std::string, EventValue> &body) {
82
+ auto eventObject = jsi::Object(*runtime_);
83
+
84
+ for (const auto &pair : body) {
85
+ const auto name = pair.first.data();
86
+ const auto &value = pair.second;
87
+
88
+ if (holds_alternative<int>(value)) {
89
+ eventObject.setProperty(*runtime_, name, get<int>(value));
90
+ } else if (holds_alternative<double>(value)) {
91
+ eventObject.setProperty(*runtime_, name, get<double>(value));
92
+ } else if (holds_alternative<float>(value)) {
93
+ eventObject.setProperty(*runtime_, name, get<float>(value));
94
+ } else if (holds_alternative<bool>(value)) {
95
+ eventObject.setProperty(*runtime_, name, get<bool>(value));
96
+ } else if (holds_alternative<std::string>(value)) {
97
+ eventObject.setProperty(*runtime_, name, get<std::string>(value));
98
+ } else if (holds_alternative<std::shared_ptr<jsi::HostObject>>(value)) {
99
+ auto hostObject = jsi::Object::createFromHostObject(
100
+ *runtime_, get<std::shared_ptr<jsi::HostObject>>(value));
101
+ eventObject.setProperty(*runtime_, name, hostObject);
102
+ }
103
+ }
104
+
105
+ return eventObject;
106
+ }
107
+
108
+ } // namespace audioapi
@@ -0,0 +1,62 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <ReactCommon/CallInvoker.h>
5
+ #include <memory>
6
+ #include <unordered_map>
7
+ #include <array>
8
+ #include <string>
9
+ #include <variant>
10
+
11
+ namespace audioapi {
12
+ using namespace facebook;
13
+
14
+ using EventValue = std::variant<int, float, double, std::string, bool, std::shared_ptr<jsi::HostObject>>;
15
+
16
+ class AudioEventHandlerRegistry {
17
+ public:
18
+ explicit AudioEventHandlerRegistry(
19
+ jsi::Runtime *runtime,
20
+ const std::shared_ptr<react::CallInvoker> &callInvoker);
21
+ ~AudioEventHandlerRegistry();
22
+
23
+ uint64_t registerHandler(const std::string &eventName, const std::shared_ptr<jsi::Function> &handler);
24
+ void unregisterHandler(const std::string &eventName, uint64_t listenerId);
25
+
26
+ void invokeHandlerWithEventBody(const std::string &eventName, const std::unordered_map<std::string, EventValue> &body);
27
+ void invokeHandlerWithEventBody(const std::string &eventName, uint64_t listenerId, const std::unordered_map<std::string, EventValue> &body);
28
+
29
+ private:
30
+ std::shared_ptr<react::CallInvoker> callInvoker_;
31
+ jsi::Runtime *runtime_;
32
+ std::unordered_map<std::string, std::unordered_map<uint64_t, std::shared_ptr<jsi::Function>>> eventHandlers_;
33
+
34
+ static constexpr std::array<std::string_view, 15> SYSTEM_EVENT_NAMES = {
35
+ "remotePlay",
36
+ "remotePause",
37
+ "remoteStop",
38
+ "remoteTogglePlayPause",
39
+ "remoteChangePlaybackRate",
40
+ "remoteNextTrack",
41
+ "remotePreviousTrack",
42
+ "remoteSkipForward",
43
+ "remoteSkipBackward",
44
+ "remoteSeekForward",
45
+ "remoteSeekBackward",
46
+ "remoteChangePlaybackPosition",
47
+ "routeChange",
48
+ "interruption",
49
+ "volumeChange",
50
+ };
51
+
52
+ static constexpr std::array<std::string_view, 4> AUDIO_API_EVENT_NAMES = {
53
+ "ended",
54
+ "audioReady",
55
+ "audioError",
56
+ "systemStateChanged"
57
+ };
58
+
59
+ jsi::Object createEventObject(const std::unordered_map<std::string, EventValue> &body);
60
+ };
61
+
62
+ } // namespace audioapi
@@ -0,0 +1,48 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/jsi/JsiHostObject.h>
4
+ #include <audioapi/events/AudioEventHandlerRegistry.h>
5
+
6
+ #include <jsi/jsi.h>
7
+ #include <ReactCommon/CallInvoker.h>
8
+ #include <memory>
9
+ #include <unordered_map>
10
+ #include <vector>
11
+ #include <string>
12
+
13
+ namespace audioapi {
14
+ using namespace facebook;
15
+
16
+ class AudioEventHandlerRegistryHostObject : public JsiHostObject {
17
+ public:
18
+ explicit AudioEventHandlerRegistryHostObject(const std::shared_ptr<AudioEventHandlerRegistry>& eventHandlerRegistry) {
19
+ eventHandlerRegistry_ = eventHandlerRegistry;
20
+
21
+ addFunctions(
22
+ JSI_EXPORT_FUNCTION(AudioEventHandlerRegistryHostObject, addAudioEventListener),
23
+ JSI_EXPORT_FUNCTION(AudioEventHandlerRegistryHostObject, removeAudioEventListener));
24
+ }
25
+
26
+ JSI_HOST_FUNCTION(addAudioEventListener) {
27
+ auto eventName = args[0].getString(runtime).utf8(runtime);
28
+ auto callback = std::make_shared<jsi::Function>(args[1].getObject(runtime).getFunction(runtime));
29
+
30
+ auto listenerId = eventHandlerRegistry_->registerHandler(eventName, callback);
31
+
32
+ return jsi::String::createFromUtf8(runtime, std::to_string(listenerId));
33
+ }
34
+
35
+ JSI_HOST_FUNCTION(removeAudioEventListener) {
36
+ auto eventName = args[0].getString(runtime).utf8(runtime);
37
+ uint64_t listenerId = std::stoull(args[1].getString(runtime).utf8(runtime));
38
+
39
+ eventHandlerRegistry_->unregisterHandler(eventName, listenerId);
40
+
41
+ return jsi::Value::undefined();
42
+ }
43
+
44
+ private:
45
+ std::shared_ptr<AudioEventHandlerRegistry> eventHandlerRegistry_;
46
+ };
47
+ } // namespace audioapi
48
+
@@ -44,10 +44,9 @@ jsi::Value PromiseVendor::createPromise(
44
44
 
45
45
  auto rejectWrapper = [reject, &runtime, callInvoker](
46
46
  const std::string &errorMessage) -> void {
47
- auto error = jsi::JSError(runtime, errorMessage);
48
- auto errorShared = std::make_shared<jsi::JSError>(error);
49
- callInvoker->invokeAsync([reject, &runtime, errorShared]() -> void {
50
- reject->call(runtime, errorShared->value());
47
+ callInvoker->invokeAsync([reject, &runtime, errorMessage]() -> void {
48
+ auto error = jsi::JSError(runtime, errorMessage);
49
+ reject->call(runtime, error.value());
51
50
  });
52
51
  };
53
52
 
@@ -7,10 +7,23 @@
7
7
 
8
8
  #import <React/RCTEventEmitter.h>
9
9
 
10
+ @class AudioEngine;
11
+ @class NotificationManager;
12
+ @class AudioSessionManager;
13
+ @class LockScreenManager;
14
+
10
15
  @interface AudioAPIModule : RCTEventEmitter
11
16
  #ifdef RCT_NEW_ARCH_ENABLED
12
17
  <NativeAudioAPIModuleSpec, RCTCallInvokerModule>
13
18
  #else
14
19
  <RCTBridgeModule>
15
20
  #endif // RCT_NEW_ARCH_ENABLED
21
+
22
+ @property (nonatomic, strong) AudioEngine *audioEngine;
23
+ @property (nonatomic, strong) NotificationManager *notificationManager;
24
+ @property (nonatomic, strong) AudioSessionManager *audioSessionManager;
25
+ @property (nonatomic, strong) LockScreenManager *lockScreenManager;
26
+
27
+ - (void)invokeHandlerWithEventName:(NSString *)eventName eventBody:(NSDictionary *)eventBody;
28
+
16
29
  @end