react-native-audio-api 0.4.10 → 0.4.12-beta.1

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 (116) hide show
  1. package/android/build.gradle +2 -0
  2. package/android/src/main/cpp/{core/AudioAPIInstaller.cpp → AudioAPIModule.cpp} +12 -11
  3. package/android/src/main/cpp/{core/AudioAPIInstaller.h → AudioAPIModule.h} +9 -11
  4. package/android/src/main/cpp/OnLoad.cpp +2 -2
  5. package/android/src/main/cpp/core/AudioDecoder.cpp +5 -5
  6. package/android/src/main/cpp/core/AudioPlayer.cpp +12 -0
  7. package/android/src/main/cpp/core/AudioPlayer.h +2 -0
  8. package/android/src/main/java/com/swmansion/audioapi/{module/AudioAPIInstaller.kt → AudioAPIModule.kt} +22 -10
  9. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +31 -6
  10. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +37 -0
  11. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +1 -2
  12. package/common/cpp/HostObjects/AudioContextHostObject.h +34 -1
  13. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +8 -0
  14. package/common/cpp/HostObjects/GainNodeHostObject.h +2 -2
  15. package/common/cpp/HostObjects/StretcherNodeHostObject.h +35 -0
  16. package/common/cpp/core/AnalyserNode.cpp +2 -2
  17. package/common/cpp/core/AnalyserNode.h +1 -1
  18. package/common/cpp/core/AudioBuffer.cpp +4 -2
  19. package/common/cpp/core/AudioBuffer.h +1 -1
  20. package/common/cpp/core/AudioBufferSourceNode.cpp +3 -3
  21. package/common/cpp/core/AudioBufferSourceNode.h +3 -3
  22. package/common/cpp/core/AudioBus.cpp +8 -0
  23. package/common/cpp/core/AudioBus.h +3 -0
  24. package/common/cpp/core/AudioContext.cpp +10 -0
  25. package/common/cpp/core/AudioContext.h +2 -0
  26. package/common/cpp/core/AudioDecoder.h +2 -1
  27. package/common/cpp/core/AudioDestinationNode.cpp +1 -1
  28. package/common/cpp/core/AudioDestinationNode.h +1 -1
  29. package/common/cpp/core/AudioNode.cpp +10 -6
  30. package/common/cpp/core/AudioNode.h +5 -3
  31. package/common/cpp/core/AudioScheduledSourceNode.cpp +1 -1
  32. package/common/cpp/core/AudioScheduledSourceNode.h +1 -1
  33. package/common/cpp/core/BaseAudioContext.cpp +7 -0
  34. package/common/cpp/core/BaseAudioContext.h +2 -0
  35. package/common/cpp/core/BiquadFilterNode.cpp +1 -1
  36. package/common/cpp/core/BiquadFilterNode.h +1 -1
  37. package/common/cpp/core/GainNode.cpp +3 -1
  38. package/common/cpp/core/GainNode.h +1 -1
  39. package/common/cpp/core/OscillatorNode.cpp +3 -1
  40. package/common/cpp/core/OscillatorNode.h +1 -1
  41. package/common/cpp/core/StereoPannerNode.cpp +1 -1
  42. package/common/cpp/core/StereoPannerNode.h +1 -1
  43. package/common/cpp/core/StretcherNode.cpp +96 -0
  44. package/common/cpp/core/StretcherNode.h +63 -0
  45. package/common/cpp/installer/AudioAPIModuleInstaller.h +49 -0
  46. package/common/cpp/libs/dsp/LICENSE.txt +21 -0
  47. package/common/cpp/libs/dsp/README.md +40 -0
  48. package/common/cpp/libs/dsp/common.h +47 -0
  49. package/common/cpp/libs/dsp/curves.h +371 -0
  50. package/common/cpp/libs/dsp/delay.h +717 -0
  51. package/common/cpp/libs/dsp/envelopes.h +523 -0
  52. package/common/cpp/libs/dsp/fft.h +523 -0
  53. package/common/cpp/libs/dsp/filters.h +436 -0
  54. package/common/cpp/libs/dsp/mix.h +218 -0
  55. package/common/cpp/libs/dsp/perf.h +84 -0
  56. package/common/cpp/libs/dsp/rates.h +184 -0
  57. package/common/cpp/libs/dsp/spectral.h +496 -0
  58. package/common/cpp/libs/dsp/windows.h +219 -0
  59. package/common/cpp/libs/signalsmith-stretch.h +637 -0
  60. package/common/cpp/types/TimeStretchType.h +6 -0
  61. package/ios/AudioAPIModule.h +1 -1
  62. package/ios/AudioAPIModule.mm +10 -3
  63. package/ios/core/AudioDecoder.mm +2 -3
  64. package/ios/core/AudioPlayer.h +14 -0
  65. package/ios/core/AudioPlayer.m +86 -25
  66. package/ios/core/IOSAudioPlayer.h +2 -0
  67. package/ios/core/IOSAudioPlayer.mm +10 -0
  68. package/lib/module/core/AudioContext.js +7 -1
  69. package/lib/module/core/AudioContext.js.map +1 -1
  70. package/lib/module/core/BaseAudioContext.js +4 -0
  71. package/lib/module/core/BaseAudioContext.js.map +1 -1
  72. package/lib/module/core/StretcherNode.js +12 -0
  73. package/lib/module/core/StretcherNode.js.map +1 -0
  74. package/lib/module/index.js +12 -3
  75. package/lib/module/index.js.map +1 -1
  76. package/lib/module/index.web.js +1 -1
  77. package/lib/module/index.web.js.map +1 -1
  78. package/lib/module/specs/NativeAudioAPIModule.js +5 -0
  79. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -0
  80. package/lib/module/web-core/AudioContext.js +6 -0
  81. package/lib/module/web-core/AudioContext.js.map +1 -1
  82. package/lib/typescript/core/AudioContext.d.ts +2 -0
  83. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  84. package/lib/typescript/core/BaseAudioContext.d.ts +2 -0
  85. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  86. package/lib/typescript/core/StretcherNode.d.ts +10 -0
  87. package/lib/typescript/core/StretcherNode.d.ts.map +1 -0
  88. package/lib/typescript/index.d.ts +5 -0
  89. package/lib/typescript/index.d.ts.map +1 -1
  90. package/lib/typescript/index.web.d.ts +1 -1
  91. package/lib/typescript/index.web.d.ts.map +1 -1
  92. package/lib/typescript/interfaces.d.ts +11 -1
  93. package/lib/typescript/interfaces.d.ts.map +1 -1
  94. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +7 -0
  95. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -0
  96. package/lib/typescript/web-core/AudioContext.d.ts +3 -1
  97. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  98. package/package.json +9 -7
  99. package/src/core/AudioContext.ts +9 -1
  100. package/src/core/BaseAudioContext.ts +5 -0
  101. package/src/core/StretcherNode.ts +15 -0
  102. package/src/index.ts +17 -3
  103. package/src/index.web.ts +1 -0
  104. package/src/interfaces.ts +13 -1
  105. package/src/specs/NativeAudioAPIModule.ts +7 -0
  106. package/src/web-core/AudioContext.tsx +9 -1
  107. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +0 -26
  108. package/common/cpp/HostObjects/AudioAPIInstallerHostObject.h +0 -56
  109. package/lib/module/specs/global.d.js +0 -4
  110. package/lib/module/specs/global.d.js.map +0 -1
  111. package/lib/module/specs/install.js +0 -18
  112. package/lib/module/specs/install.js.map +0 -1
  113. package/lib/typescript/specs/install.d.ts +0 -7
  114. package/lib/typescript/specs/install.d.ts.map +0 -1
  115. package/src/specs/global.d.ts +0 -12
  116. package/src/specs/install.ts +0 -32
@@ -194,6 +194,8 @@ android {
194
194
  // This is needed to build Kotlin project with NewArch enabled
195
195
  "${project.buildDir}/generated/source/codegen/java"
196
196
  ]
197
+ } else {
198
+ java.srcDirs += ["src/oldarch"]
197
199
  }
198
200
  }
199
201
  }
@@ -1,18 +1,21 @@
1
- #include "AudioAPIInstaller.h"
1
+ #include "AudioAPIModule.h"
2
+
3
+ #include "AudioContext.h"
4
+ #include "AudioContextHostObject.h"
2
5
 
3
6
  namespace audioapi {
4
7
 
5
8
  using namespace facebook::jni;
6
9
 
7
- AudioAPIInstaller::AudioAPIInstaller(
8
- jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis,
10
+ AudioAPIModule::AudioAPIModule(
11
+ jni::alias_ref<AudioAPIModule::jhybridobject> &jThis,
9
12
  jsi::Runtime *jsiRuntime,
10
13
  const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker)
11
14
  : javaPart_(make_global(jThis)),
12
15
  jsiRuntime_(jsiRuntime),
13
16
  jsCallInvoker_(jsCallInvoker) {}
14
17
 
15
- jni::local_ref<AudioAPIInstaller::jhybriddata> AudioAPIInstaller::initHybrid(
18
+ jni::local_ref<AudioAPIModule::jhybriddata> AudioAPIModule::initHybrid(
16
19
  jni::alias_ref<jhybridobject> jThis,
17
20
  jlong jsContext,
18
21
  jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
@@ -22,16 +25,14 @@ jni::local_ref<AudioAPIInstaller::jhybriddata> AudioAPIInstaller::initHybrid(
22
25
  return makeCxxInstance(jThis, rnRuntime, jsCallInvoker);
23
26
  }
24
27
 
25
- void AudioAPIInstaller::registerNatives() {
28
+ void AudioAPIModule::registerNatives() {
26
29
  registerHybrid({
27
- makeNativeMethod("initHybrid", AudioAPIInstaller::initHybrid),
28
- makeNativeMethod("install", AudioAPIInstaller::install),
30
+ makeNativeMethod("initHybrid", AudioAPIModule::initHybrid),
31
+ makeNativeMethod("injectJSIBindings", AudioAPIModule::injectJSIBindings),
29
32
  });
30
33
  }
31
34
 
32
- void AudioAPIInstaller::install() {
33
- auto hostObject = std::make_shared<AudioAPIInstallerHostObject>(
34
- jsiRuntime_, jsCallInvoker_);
35
- hostObject->install();
35
+ void AudioAPIModule::injectJSIBindings() {
36
+ AudioAPIModuleInstaller::injectJSIBindings(jsiRuntime_, jsCallInvoker_);
36
37
  }
37
38
  } // namespace audioapi
@@ -6,21 +6,19 @@
6
6
  #include <react/jni/JMessageQueueThread.h>
7
7
  #include <memory>
8
8
  #include <utility>
9
-
10
- #include "AudioAPIInstallerHostObject.h"
11
- #include "AudioContext.h"
9
+ #include "AudioAPIModuleInstaller.h"
12
10
 
13
11
  namespace audioapi {
14
12
 
15
13
  using namespace facebook;
16
14
  using namespace react;
17
15
 
18
- class AudioAPIInstaller : public jni::HybridClass<AudioAPIInstaller> {
16
+ class AudioAPIModule : public jni::HybridClass<AudioAPIModule> {
19
17
  public:
20
18
  static auto constexpr kJavaDescriptor =
21
- "Lcom/swmansion/audioapi/module/AudioAPIInstaller;";
19
+ "Lcom/swmansion/audioapi/AudioAPIModule;";
22
20
 
23
- static jni::local_ref<AudioAPIInstaller::jhybriddata> initHybrid(
21
+ static jni::local_ref<AudioAPIModule::jhybriddata> initHybrid(
24
22
  jni::alias_ref<jhybridobject> jThis,
25
23
  jlong jsContext,
26
24
  jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
@@ -28,18 +26,18 @@ class AudioAPIInstaller : public jni::HybridClass<AudioAPIInstaller> {
28
26
 
29
27
  static void registerNatives();
30
28
 
31
- void install();
29
+ void injectJSIBindings();
32
30
 
33
31
  private:
34
32
  friend HybridBase;
35
33
 
36
- jni::global_ref<AudioAPIInstaller::javaobject> javaPart_;
34
+ jni::global_ref<AudioAPIModule::javaobject> javaPart_;
37
35
  jsi::Runtime *jsiRuntime_;
38
36
  std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker_;
39
37
 
40
- explicit AudioAPIInstaller(
41
- jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis,
42
- jsi::Runtime *rnRuntime,
38
+ explicit AudioAPIModule(
39
+ jni::alias_ref<AudioAPIModule::jhybridobject> &jThis,
40
+ jsi::Runtime *jsiRuntime,
43
41
  const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker);
44
42
  };
45
43
 
@@ -1,9 +1,9 @@
1
1
  #include <fbjni/fbjni.h>
2
- #include "AudioAPIInstaller.h"
2
+ #include "AudioAPIModule.h"
3
3
 
4
4
  using namespace audioapi;
5
5
 
6
6
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
7
7
  return facebook::jni::initialize(
8
- vm, [] { AudioAPIInstaller::registerNatives(); });
8
+ vm, [] { AudioAPIModule::registerNatives(); });
9
9
  }
@@ -9,7 +9,8 @@
9
9
 
10
10
  namespace audioapi {
11
11
 
12
- AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const {
12
+ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
13
+ const std::string &path) const {
13
14
  ma_decoder decoder;
14
15
  ma_decoder_config config =
15
16
  ma_decoder_config_init(ma_format_f32, 2, sampleRate_);
@@ -29,8 +30,8 @@ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const {
29
30
  ma_uint64 totalFrameCount;
30
31
  ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
31
32
 
32
- auto *audioBus =
33
- new AudioBus(static_cast<int>(totalFrameCount), 2, sampleRate_);
33
+ auto audioBus = std::make_shared<AudioBus>(
34
+ static_cast<int>(totalFrameCount), 2, sampleRate_);
34
35
  auto *buffer = new float[totalFrameCount * 2];
35
36
 
36
37
  ma_uint64 framesDecoded;
@@ -43,14 +44,13 @@ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const {
43
44
  path.c_str());
44
45
 
45
46
  delete[] buffer;
46
- delete audioBus;
47
47
  ma_decoder_uninit(&decoder);
48
48
 
49
49
  return nullptr;
50
50
  }
51
51
 
52
52
  for (int i = 0; i < decoder.outputChannels; ++i) {
53
- float *channelData = audioBus->getChannel(i)->getData();
53
+ auto channelData = audioBus->getChannel(i)->getData();
54
54
 
55
55
  for (ma_uint64 j = 0; j < framesDecoded; ++j) {
56
56
  channelData[j] = buffer[j * decoder.outputChannels + i];
@@ -70,6 +70,18 @@ void AudioPlayer::stop() {
70
70
  }
71
71
  }
72
72
 
73
+ void AudioPlayer::resume() {
74
+ if (mStream_) {
75
+ mStream_->requestStart();
76
+ }
77
+ }
78
+
79
+ void AudioPlayer::suspend() {
80
+ if (mStream_) {
81
+ mStream_->requestPause();
82
+ }
83
+ }
84
+
73
85
  DataCallbackResult AudioPlayer::onAudioReady(
74
86
  AudioStream *oboeStream,
75
87
  void *audioData,
@@ -22,6 +22,8 @@ class AudioPlayer : public AudioStreamDataCallback {
22
22
  [[nodiscard]] float getSampleRate() const;
23
23
  void start();
24
24
  void stop();
25
+ void resume();
26
+ void suspend();
25
27
 
26
28
  DataCallbackResult onAudioReady(
27
29
  AudioStream *oboeStream,
@@ -1,31 +1,43 @@
1
- package com.swmansion.audioapi.module
1
+ package com.swmansion.audioapi
2
2
 
3
3
  import com.facebook.jni.HybridData
4
4
  import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.bridge.ReactMethod
5
6
  import com.facebook.react.common.annotations.FrameworkAPI
7
+ import com.facebook.react.module.annotations.ReactModule
6
8
  import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
7
9
 
8
10
  @OptIn(FrameworkAPI::class)
9
- class AudioAPIInstaller(
11
+ @ReactModule(name = AudioAPIModule.NAME)
12
+ class AudioAPIModule(
10
13
  reactContext: ReactApplicationContext,
11
- ) {
12
- private val mHybridData: HybridData?
13
-
14
+ ) : NativeAudioAPIModuleSpec(reactContext) {
14
15
  companion object {
15
16
  init {
16
17
  System.loadLibrary("react-native-audio-api")
17
18
  }
19
+
20
+ const val NAME = NativeAudioAPIModuleSpec.NAME
18
21
  }
19
22
 
23
+ private val mHybridData: HybridData
24
+
25
+ external fun initHybrid(
26
+ jsContext: Long,
27
+ callInvoker: CallInvokerHolderImpl,
28
+ ): HybridData
29
+
30
+ private external fun injectJSIBindings()
31
+
20
32
  init {
21
33
  val jsCallInvokerHolder = reactContext.jsCallInvokerHolder as CallInvokerHolderImpl
22
34
  mHybridData = initHybrid(reactContext.javaScriptContextHolder!!.get(), jsCallInvokerHolder)
23
35
  }
24
36
 
25
- external fun initHybrid(
26
- jsContext: Long,
27
- callInvoker: CallInvokerHolderImpl,
28
- ): HybridData?
37
+ @ReactMethod(isBlockingSynchronousMethod = true)
38
+ override fun install(): Boolean {
39
+ injectJSIBindings()
29
40
 
30
- external fun install()
41
+ return true
42
+ }
31
43
  }
@@ -1,16 +1,41 @@
1
1
  package com.swmansion.audioapi
2
2
 
3
+ import com.facebook.react.BaseReactPackage
3
4
  import com.facebook.react.ReactPackage
4
5
  import com.facebook.react.bridge.NativeModule
5
6
  import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.common.annotations.UnstableReactNativeAPI
6
8
  import com.facebook.react.module.annotations.ReactModuleList
7
- import com.facebook.react.uimanager.ViewManager
8
- import com.swmansion.audioapi.nativemodules.AudioAPIModule
9
+ import com.facebook.react.module.model.ReactModuleInfo
10
+ import com.facebook.react.module.model.ReactModuleInfoProvider
9
11
 
10
12
  @ReactModuleList(nativeModules = [AudioAPIModule::class])
11
- class AudioAPIPackage : ReactPackage {
12
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
13
- listOf<NativeModule>(AudioAPIModule(reactContext))
13
+ class AudioAPIPackage :
14
+ BaseReactPackage(),
15
+ ReactPackage {
16
+ @UnstableReactNativeAPI
17
+ override fun getModule(
18
+ name: String,
19
+ reactContext: ReactApplicationContext,
20
+ ): NativeModule? =
21
+ when (name) {
22
+ AudioAPIModule.NAME -> AudioAPIModule(reactContext)
23
+ else -> null
24
+ }
14
25
 
15
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
26
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider =
27
+ ReactModuleInfoProvider(
28
+ fun (): Map<String, ReactModuleInfo> =
29
+ mapOf(
30
+ AudioAPIModule.NAME to
31
+ ReactModuleInfo(
32
+ AudioAPIModule.NAME,
33
+ AudioAPIModule::class.java.simpleName,
34
+ _canOverrideExistingModule = true,
35
+ _needsEagerInit = false,
36
+ isCxxModule = false,
37
+ isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
38
+ ),
39
+ ),
40
+ )
16
41
  }
@@ -0,0 +1,37 @@
1
+
2
+ /**
3
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
4
+ *
5
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
6
+ * once the code is regenerated.
7
+ *
8
+ * @generated by codegen project: GenerateModuleJavaSpec.js
9
+ *
10
+ * @nolint
11
+ */
12
+
13
+ package com.swmansion.audioapi;
14
+
15
+ import com.facebook.proguard.annotations.DoNotStrip;
16
+ import com.facebook.react.bridge.ReactApplicationContext;
17
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
18
+ import com.facebook.react.bridge.ReactMethod;
19
+ import com.facebook.react.turbomodule.core.interfaces.TurboModule;
20
+ import javax.annotation.Nonnull;
21
+
22
+ public abstract class NativeAudioAPIModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
23
+ public static final String NAME = "AudioAPIModule";
24
+
25
+ public NativeAudioAPIModuleSpec(ReactApplicationContext reactContext) {
26
+ super(reactContext);
27
+ }
28
+
29
+ @Override
30
+ public @Nonnull String getName() {
31
+ return NAME;
32
+ }
33
+
34
+ @ReactMethod(isBlockingSynchronousMethod = true)
35
+ @DoNotStrip
36
+ public abstract boolean install();
37
+ }
@@ -23,8 +23,7 @@ class AudioBufferSourceNodeHostObject
23
23
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, loopStart),
24
24
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, loopEnd),
25
25
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, detune),
26
- JSI_EXPORT_PROPERTY_GETTER(
27
- AudioBufferSourceNodeHostObject, playbackRate));
26
+ JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, playbackRate));
28
27
 
29
28
  addSetters(
30
29
  JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, loop),
@@ -17,7 +17,10 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
17
17
  const std::shared_ptr<AudioContext> &audioContext,
18
18
  const std::shared_ptr<PromiseVendor> &promiseVendor)
19
19
  : BaseAudioContextHostObject(audioContext, promiseVendor) {
20
- addFunctions(JSI_EXPORT_FUNCTION(AudioContextHostObject, close));
20
+ addFunctions(
21
+ JSI_EXPORT_FUNCTION(AudioContextHostObject, close),
22
+ JSI_EXPORT_FUNCTION(AudioContextHostObject, resume),
23
+ JSI_EXPORT_FUNCTION(AudioContextHostObject, suspend));
21
24
  }
22
25
 
23
26
  JSI_HOST_FUNCTION(close) {
@@ -34,5 +37,35 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
34
37
 
35
38
  return promise;
36
39
  }
40
+
41
+ JSI_HOST_FUNCTION(resume) {
42
+ auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
43
+ std::thread([this, promise = std::move(promise)]() {
44
+ auto audioContext = std::static_pointer_cast<AudioContext>(context_);
45
+ audioContext->resume();
46
+
47
+ promise->resolve([](jsi::Runtime &runtime) {
48
+ return jsi::Value::undefined();
49
+ });
50
+ }).detach();
51
+ });
52
+
53
+ return promise;
54
+ }
55
+
56
+ JSI_HOST_FUNCTION(suspend) {
57
+ auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
58
+ std::thread([this, promise = std::move(promise)]() {
59
+ auto audioContext = std::static_pointer_cast<AudioContext>(context_);
60
+ audioContext->suspend();
61
+
62
+ promise->resolve([](jsi::Runtime &runtime) {
63
+ return jsi::Value::undefined();
64
+ });
65
+ }).detach();
66
+ });
67
+
68
+ return promise;
69
+ }
37
70
  };
38
71
  } // namespace audioapi
@@ -19,6 +19,7 @@
19
19
  #include "PeriodicWaveHostObject.h"
20
20
  #include "StereoPannerNodeHostObject.h"
21
21
  #include "AnalyserNodeHostObject.h"
22
+ #include "StretcherNodeHostObject.h"
22
23
 
23
24
  namespace audioapi {
24
25
  using namespace facebook;
@@ -44,6 +45,7 @@ class BaseAudioContextHostObject : public JsiHostObject {
44
45
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBuffer),
45
46
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createPeriodicWave),
46
47
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createAnalyser),
48
+ JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createStretcher),
47
49
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, decodeAudioDataSource));
48
50
  }
49
51
 
@@ -140,6 +142,12 @@ class BaseAudioContextHostObject : public JsiHostObject {
140
142
  return jsi::Object::createFromHostObject(runtime, analyserHostObject);
141
143
  }
142
144
 
145
+ JSI_HOST_FUNCTION(createStretcher) {
146
+ auto stretcher = context_->createStretcher();
147
+ auto stretcherHostObject = std::make_shared<StretcherNodeHostObject>(stretcher);
148
+ return jsi::Object::createFromHostObject(runtime, stretcherHostObject);
149
+ }
150
+
143
151
  JSI_HOST_FUNCTION(decodeAudioDataSource) {
144
152
  auto sourcePath = args[0].getString(runtime).utf8(runtime);
145
153
 
@@ -19,9 +19,9 @@ class GainNodeHostObject : public AudioNodeHostObject {
19
19
 
20
20
  JSI_PROPERTY_GETTER(gain) {
21
21
  auto gainNode = std::static_pointer_cast<GainNode>(node_);
22
- auto gainParam_ =
22
+ auto gainParam =
23
23
  std::make_shared<AudioParamHostObject>(gainNode->getGainParam());
24
- return jsi::Object::createFromHostObject(runtime, gainParam_);
24
+ return jsi::Object::createFromHostObject(runtime, gainParam);
25
25
  }
26
26
  };
27
27
  } // namespace audioapi
@@ -0,0 +1,35 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <vector>
5
+
6
+ #include "AudioNodeHostObject.h"
7
+ #include "AudioParamHostObject.h"
8
+ #include "StretcherNode.h"
9
+
10
+ namespace audioapi {
11
+ using namespace facebook;
12
+
13
+ class StretcherNodeHostObject : public AudioNodeHostObject {
14
+ public:
15
+ explicit StretcherNodeHostObject(const std::shared_ptr<StretcherNode> &node)
16
+ : AudioNodeHostObject(node) {
17
+ addGetters(JSI_EXPORT_PROPERTY_GETTER(StretcherNodeHostObject, rate),
18
+ JSI_EXPORT_PROPERTY_GETTER(StretcherNodeHostObject, semitones));
19
+ }
20
+
21
+ JSI_PROPERTY_GETTER(rate) {
22
+ auto stretcherNode = std::static_pointer_cast<StretcherNode>(node_);
23
+ auto rateParam =
24
+ std::make_shared<AudioParamHostObject>(stretcherNode->getRateParam());
25
+ return jsi::Object::createFromHostObject(runtime, rateParam);
26
+ }
27
+
28
+ JSI_PROPERTY_GETTER(semitones) {
29
+ auto stretcherNode = std::static_pointer_cast<StretcherNode>(node_);
30
+ auto semitonesParam =
31
+ std::make_shared<AudioParamHostObject>(stretcherNode->getSemitonesParam());
32
+ return jsi::Object::createFromHostObject(runtime, semitonesParam);
33
+ }
34
+ };
35
+ } // namespace audioapi
@@ -147,13 +147,13 @@ void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) {
147
147
  }
148
148
 
149
149
  void AnalyserNode::processNode(
150
- audioapi::AudioBus *processingBus,
150
+ const std::shared_ptr<AudioBus> &processingBus,
151
151
  int framesToProcess) {
152
152
  // Analyser should behave like a sniffer node, it should not modify the
153
153
  // processingBus but instead copy the data to its own input buffer.
154
154
 
155
155
  // Down mix the input bus to mono
156
- downMixBus_->copy(processingBus);
156
+ downMixBus_->copy(processingBus.get());
157
157
 
158
158
  if (vWriteIndex_ + framesToProcess > inputBuffer_->getSize()) {
159
159
  auto framesToCopy =
@@ -36,7 +36,7 @@ class AnalyserNode : public AudioNode {
36
36
  void getByteTimeDomainData(uint8_t *data, int length);
37
37
 
38
38
  protected:
39
- void processNode(AudioBus *processingBus, int framesToProcess) override;
39
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
40
40
 
41
41
  private:
42
42
  int fftSize_;
@@ -1,4 +1,6 @@
1
1
  #include "AudioBuffer.h"
2
+
3
+ #include <utility>
2
4
  #include "AudioArray.h"
3
5
  #include "AudioBus.h"
4
6
 
@@ -11,8 +13,8 @@ AudioBuffer::AudioBuffer(
11
13
  bus_ = std::make_shared<AudioBus>(length, numberOfChannels, sampleRate);
12
14
  }
13
15
 
14
- AudioBuffer::AudioBuffer(AudioBus *bus) {
15
- bus_ = std::shared_ptr<AudioBus>(bus);
16
+ AudioBuffer::AudioBuffer(std::shared_ptr<AudioBus> bus) {
17
+ bus_ = std::move(bus);
16
18
  }
17
19
 
18
20
  size_t AudioBuffer::getLength() const {
@@ -13,7 +13,7 @@ class AudioBus;
13
13
  class AudioBuffer : public std::enable_shared_from_this<AudioBuffer> {
14
14
  public:
15
15
  explicit AudioBuffer(int numberOfChannels, size_t length, float sampleRate);
16
- explicit AudioBuffer(AudioBus *bus);
16
+ explicit AudioBuffer(std::shared_ptr<AudioBus> bus);
17
17
 
18
18
  [[nodiscard]] size_t getLength() const;
19
19
  [[nodiscard]] float getSampleRate() const;
@@ -117,7 +117,7 @@ std::mutex &AudioBufferSourceNode::getBufferLock() {
117
117
  }
118
118
 
119
119
  void AudioBufferSourceNode::processNode(
120
- AudioBus *processingBus,
120
+ const std::shared_ptr<AudioBus> &processingBus,
121
121
  int framesToProcess) {
122
122
  // No audio data to fill, zero the output and return.
123
123
  if (!buffer_) {
@@ -158,7 +158,7 @@ void AudioBufferSourceNode::processNode(
158
158
  */
159
159
 
160
160
  void AudioBufferSourceNode::processWithoutInterpolation(
161
- AudioBus *processingBus,
161
+ const std::shared_ptr<AudioBus> &processingBus,
162
162
  size_t startOffset,
163
163
  size_t offsetLength,
164
164
  float playbackRate) {
@@ -216,7 +216,7 @@ void AudioBufferSourceNode::processWithoutInterpolation(
216
216
  }
217
217
 
218
218
  void AudioBufferSourceNode::processWithInterpolation(
219
- AudioBus *processingBus,
219
+ const std::shared_ptr<AudioBus> &processingBus,
220
220
  size_t startOffset,
221
221
  size_t offsetLength,
222
222
  float playbackRate) {
@@ -31,7 +31,7 @@ class AudioBufferSourceNode : public AudioScheduledSourceNode {
31
31
 
32
32
  protected:
33
33
  std::mutex &getBufferLock();
34
- void processNode(AudioBus *processingBus, int framesToProcess) override;
34
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
35
35
 
36
36
  private:
37
37
  // Looping related properties
@@ -57,13 +57,13 @@ class AudioBufferSourceNode : public AudioScheduledSourceNode {
57
57
  double getVirtualEndFrame();
58
58
 
59
59
  void processWithoutInterpolation(
60
- AudioBus *processingBus,
60
+ const std::shared_ptr<AudioBus>& processingBus,
61
61
  size_t startOffset,
62
62
  size_t offsetLength,
63
63
  float playbackRate);
64
64
 
65
65
  void processWithInterpolation(
66
- AudioBus *processingBus,
66
+ const std::shared_ptr<AudioBus>& processingBus,
67
67
  size_t startOffset,
68
68
  size_t offsetLength,
69
69
  float playbackRate);
@@ -119,6 +119,14 @@ AudioArray *AudioBus::getChannelByType(int channelType) const {
119
119
  }
120
120
  }
121
121
 
122
+ AudioArray &AudioBus::operator[](size_t index) {
123
+ return *channels_[index];
124
+ }
125
+
126
+ const AudioArray &AudioBus::operator[](size_t index) const {
127
+ return *channels_[index];
128
+ }
129
+
122
130
  /**
123
131
  * Public interfaces - audio processing and setters
124
132
  */
@@ -34,6 +34,9 @@ class AudioBus {
34
34
  [[nodiscard]] AudioArray *getChannel(int index) const;
35
35
  [[nodiscard]] AudioArray *getChannelByType(int channelType) const;
36
36
 
37
+ AudioArray &operator[](size_t index);
38
+ const AudioArray &operator[](size_t index) const;
39
+
37
40
  void normalize();
38
41
  void scale(float value);
39
42
  [[nodiscard]] float maxAbsValue() const;
@@ -48,6 +48,16 @@ void AudioContext::close() {
48
48
  audioPlayer_->stop();
49
49
  }
50
50
 
51
+ void AudioContext::resume() {
52
+ state_ = ContextState::RUNNING;
53
+ audioPlayer_->resume();
54
+ }
55
+
56
+ void AudioContext::suspend() {
57
+ state_ = ContextState::SUSPENDED;
58
+ audioPlayer_->suspend();
59
+ }
60
+
51
61
  std::function<void(std::shared_ptr<AudioBus>, int)>
52
62
  AudioContext::renderAudio() {
53
63
  if (!isRunning() || !destination_) {
@@ -19,6 +19,8 @@ class AudioContext : public BaseAudioContext {
19
19
  ~AudioContext() override;
20
20
 
21
21
  void close();
22
+ void resume();
23
+ void suspend();
22
24
 
23
25
  private:
24
26
  #ifdef ANDROID
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include <memory>
3
4
  #include <string>
4
5
 
5
6
  namespace audioapi {
@@ -10,7 +11,7 @@ class AudioDecoder {
10
11
  public:
11
12
  explicit AudioDecoder(float sampleRate) : sampleRate_(sampleRate) {}
12
13
 
13
- [[nodiscard]] AudioBus *decodeWithFilePath(const std::string &path) const;
14
+ [[nodiscard]] std::shared_ptr<AudioBus> decodeWithFilePath(const std::string &path) const;
14
15
 
15
16
  private:
16
17
  float sampleRate_;
@@ -33,7 +33,7 @@ void AudioDestinationNode::renderAudio(
33
33
 
34
34
  destinationBus->zero();
35
35
 
36
- auto processedBus = processAudio(destinationBus, numFrames);
36
+ auto processedBus = processAudio(destinationBus, numFrames, true);
37
37
 
38
38
  if (processedBus && processedBus != destinationBus) {
39
39
  destinationBus->copy(processedBus.get());
@@ -24,7 +24,7 @@ class AudioDestinationNode : public AudioNode {
24
24
  protected:
25
25
  // DestinationNode is triggered by AudioContext using renderAudio
26
26
  // processNode function is not necessary and is never called.
27
- void processNode(AudioBus *, int) final {};
27
+ void processNode(const std::shared_ptr<AudioBus>& processingBus, int) final {};
28
28
 
29
29
  private:
30
30
  std::size_t currentSampleFrame_;