react-native-audio-api 0.3.0-rc1 → 0.3.0-rc2

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 (57) hide show
  1. package/android/CMakeLists.txt +2 -2
  2. package/android/build.gradle +1 -3
  3. package/android/libs/include/miniaudio.h +92621 -0
  4. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +8 -4
  5. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +16 -7
  6. package/android/src/main/cpp/AudioDecoder/AudioDecoder.cpp +64 -0
  7. package/android/src/main/cpp/AudioDecoder/AudioDecoder.h +21 -0
  8. package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +2 -2
  9. package/android/src/main/java/com/swmansion/audioapi/module/AudioAPIInstaller.kt +14 -4
  10. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +2 -3
  11. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +8 -4
  12. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +10 -8
  13. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +3 -2
  14. package/common/cpp/HostObjects/AudioContextHostObject.cpp +2 -1
  15. package/common/cpp/HostObjects/AudioContextHostObject.h +5 -3
  16. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +24 -14
  17. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +3 -2
  18. package/common/cpp/core/AudioDestinationNode.cpp +1 -0
  19. package/common/cpp/core/BaseAudioContext.cpp +8 -5
  20. package/common/cpp/core/BaseAudioContext.h +5 -3
  21. package/common/cpp/utils/JsiPromise.cpp +37 -32
  22. package/common/cpp/utils/JsiPromise.h +13 -7
  23. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +2 -2
  24. package/common/cpp/wrappers/BaseAudioContextWrapper.h +2 -1
  25. package/ios/AudioAPIModule.mm +3 -2
  26. package/ios/AudioDecoder/AudioDecoder.h +1 -1
  27. package/ios/AudioDecoder/AudioDecoder.m +5 -92
  28. package/ios/AudioDecoder/IOSAudioDecoder.h +2 -0
  29. package/ios/AudioDecoder/IOSAudioDecoder.mm +7 -1
  30. package/ios/AudioPlayer/AudioPlayer.m +2 -1
  31. package/lib/module/core/BaseAudioContext.js +2 -3
  32. package/lib/module/core/BaseAudioContext.js.map +1 -1
  33. package/lib/module/index.js +0 -3
  34. package/lib/module/index.js.map +1 -1
  35. package/lib/typescript/core/BaseAudioContext.d.ts +2 -2
  36. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  37. package/lib/typescript/core/types.d.ts +0 -6
  38. package/lib/typescript/core/types.d.ts.map +1 -1
  39. package/lib/typescript/index.d.ts +2 -2
  40. package/lib/typescript/index.d.ts.map +1 -1
  41. package/lib/typescript/interfaces.d.ts +1 -1
  42. package/lib/typescript/interfaces.d.ts.map +1 -1
  43. package/package.json +1 -1
  44. package/src/core/BaseAudioContext.ts +3 -8
  45. package/src/core/types.ts +0 -7
  46. package/src/index.ts +2 -12
  47. package/src/interfaces.ts +1 -1
  48. package/android/libs/fftw3/x86/libfftw3.a +0 -0
  49. package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
  50. package/lib/module/utils/resolveAudioSource.js +0 -10
  51. package/lib/module/utils/resolveAudioSource.js.map +0 -1
  52. package/lib/typescript/utils/resolveAudioSource.d.ts +0 -3
  53. package/lib/typescript/utils/resolveAudioSource.d.ts.map +0 -1
  54. package/src/utils/resolveAudioSource.ts +0 -14
  55. /package/android/libs/{fftw3/arm64-v8a → arm64-v8a}/libfftw3.a +0 -0
  56. /package/android/libs/{fftw3/armeabi-v7a → armeabi-v7a}/libfftw3.a +0 -0
  57. /package/android/libs/include/{fftw3/fftw3.h → fftw3.h} +0 -0
@@ -5,14 +5,18 @@ namespace audioapi {
5
5
  using namespace facebook::jni;
6
6
 
7
7
  AudioAPIInstaller::AudioAPIInstaller(
8
- jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis)
9
- : javaPart_(make_global(jThis)) {}
8
+ jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis,
9
+ jsi::Runtime *rnRuntime,
10
+ const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker)
11
+ : javaPart_(make_global(jThis)),
12
+ rnRuntime_(rnRuntime),
13
+ jsCallInvoker_(jsCallInvoker) {}
10
14
 
11
- void AudioAPIInstaller::install(jlong jsContext) {
15
+ void AudioAPIInstaller::install() {
12
16
  auto audioAPIInstallerWrapper =
13
17
  std::make_shared<AudioAPIInstallerWrapper>(this);
14
18
  AudioAPIInstallerHostObject::createAndInstallFromWrapper(
15
- audioAPIInstallerWrapper, jsContext);
19
+ audioAPIInstallerWrapper, rnRuntime_, jsCallInvoker_);
16
20
  }
17
21
 
18
22
  std::shared_ptr<AudioContext> AudioAPIInstaller::createAudioContext() {
@@ -1,7 +1,7 @@
1
1
  #pragma once
2
2
 
3
+ #include <ReactCommon/CallInvokerHolder.h>
3
4
  #include <fbjni/fbjni.h>
4
- #include <jsi/jsi.h>
5
5
  #include <react/jni/CxxModuleWrapper.h>
6
6
  #include <react/jni/JMessageQueueThread.h>
7
7
  #include <memory>
@@ -14,7 +14,7 @@
14
14
  namespace audioapi {
15
15
 
16
16
  using namespace facebook;
17
- using namespace facebook::jni;
17
+ using namespace react;
18
18
 
19
19
  class AudioAPIInstaller : public jni::HybridClass<AudioAPIInstaller> {
20
20
  public:
@@ -22,8 +22,13 @@ class AudioAPIInstaller : public jni::HybridClass<AudioAPIInstaller> {
22
22
  "Lcom/swmansion/audioapi/module/AudioAPIInstaller;";
23
23
 
24
24
  static jni::local_ref<AudioAPIInstaller::jhybriddata> initHybrid(
25
- jni::alias_ref<jhybridobject> jThis) {
26
- return makeCxxInstance(jThis);
25
+ jni::alias_ref<jhybridobject> jThis,
26
+ jlong jsContext,
27
+ jni::alias_ref<facebook::react::CallInvokerHolder::javaobject>
28
+ jsCallInvokerHolder) {
29
+ auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker();
30
+ auto rnRuntime = reinterpret_cast<jsi::Runtime *>(jsContext);
31
+ return makeCxxInstance(jThis, rnRuntime, jsCallInvoker);
27
32
  }
28
33
 
29
34
  static void registerNatives() {
@@ -34,15 +39,19 @@ class AudioAPIInstaller : public jni::HybridClass<AudioAPIInstaller> {
34
39
  }
35
40
 
36
41
  std::shared_ptr<AudioContext> createAudioContext();
37
- void install(jlong jsContext);
42
+ void install();
38
43
 
39
44
  private:
40
45
  friend HybridBase;
41
46
 
42
- global_ref<AudioAPIInstaller::javaobject> javaPart_;
47
+ jni::global_ref<AudioAPIInstaller::javaobject> javaPart_;
48
+ jsi::Runtime *rnRuntime_;
49
+ std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker_;
43
50
 
44
51
  explicit AudioAPIInstaller(
45
- jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis);
52
+ jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis,
53
+ jsi::Runtime *rnRuntime,
54
+ const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker);
46
55
  };
47
56
 
48
57
  } // namespace audioapi
@@ -0,0 +1,64 @@
1
+ #include "AudioDecoder.h"
2
+
3
+ #define MINIAUDIO_IMPLEMENTATION
4
+ #include <android/log.h>
5
+ #include <miniaudio.h>
6
+
7
+ #include "AudioArray.h"
8
+ #include "AudioBus.h"
9
+
10
+ namespace audioapi {
11
+
12
+ AudioDecoder::AudioDecoder(int sampleRate) : sampleRate_(sampleRate) {}
13
+
14
+ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const {
15
+ ma_decoder decoder;
16
+ ma_decoder_config config =
17
+ ma_decoder_config_init(ma_format_f32, 2, sampleRate_);
18
+ ma_result result = ma_decoder_init_file(path.c_str(), &config, &decoder);
19
+ if (result != MA_SUCCESS) {
20
+ __android_log_print(
21
+ ANDROID_LOG_ERROR,
22
+ "AudioDecoder",
23
+ "Failed to initialize decoder for file: %s",
24
+ path.c_str());
25
+ return new AudioBus(1, 1, 1);
26
+ }
27
+
28
+ ma_uint64 totalFrameCount;
29
+ ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
30
+
31
+ auto *audioBus =
32
+ new AudioBus(sampleRate_, static_cast<int>(totalFrameCount), 2);
33
+ auto *buffer = new float[totalFrameCount * 2];
34
+
35
+ ma_uint64 framesDecoded;
36
+ ma_decoder_read_pcm_frames(&decoder, buffer, totalFrameCount, &framesDecoded);
37
+ if (framesDecoded == 0) {
38
+ __android_log_print(
39
+ ANDROID_LOG_ERROR,
40
+ "AudioDecoder",
41
+ "Failed to decode audio file: %s",
42
+ path.c_str());
43
+ }
44
+
45
+ for (int i = 0; i < decoder.outputChannels; ++i) {
46
+ float *channelData = audioBus->getChannel(i)->getData();
47
+
48
+ for (ma_uint64 j = 0; j < framesDecoded; ++j) {
49
+ channelData[j] = buffer[j * decoder.outputChannels + i];
50
+ }
51
+ }
52
+
53
+ delete[] buffer;
54
+ ma_decoder_uninit(&decoder);
55
+
56
+ return audioBus;
57
+ }
58
+
59
+ AudioBus *AudioDecoder::decodeWithArrayBuffer() const {
60
+ // TODO: implement this
61
+ return new AudioBus(1, 1, 1);
62
+ }
63
+
64
+ } // namespace audioapi
@@ -0,0 +1,21 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ namespace audioapi {
6
+
7
+ class AudioBus;
8
+
9
+ class AudioDecoder {
10
+ public:
11
+ explicit AudioDecoder(int sampleRate);
12
+
13
+ [[nodiscard]] AudioBus *decodeWithFilePath(const std::string &path) const;
14
+ // TODO: implement this
15
+ [[nodiscard]] AudioBus *decodeWithArrayBuffer() const;
16
+
17
+ private:
18
+ int sampleRate_;
19
+ };
20
+
21
+ } // namespace audioapi
@@ -14,8 +14,8 @@ class AudioPlayer : public AudioStreamDataCallback {
14
14
  public:
15
15
  explicit AudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio);
16
16
 
17
- int getSampleRate() const;
18
- int getBufferSizeInFrames() const;
17
+ [[nodiscard]] int getSampleRate() const;
18
+ [[nodiscard]] int getBufferSizeInFrames() const;
19
19
  void start();
20
20
  void stop();
21
21
 
@@ -1,8 +1,14 @@
1
1
  package com.swmansion.audioapi.module
2
2
 
3
3
  import com.facebook.jni.HybridData
4
+ import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.common.annotations.FrameworkAPI
6
+ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
4
7
 
5
- class AudioAPIInstaller {
8
+ @OptIn(FrameworkAPI::class)
9
+ class AudioAPIInstaller(
10
+ reactContext: ReactApplicationContext,
11
+ ) {
6
12
  private val mHybridData: HybridData?
7
13
 
8
14
  companion object {
@@ -12,10 +18,14 @@ class AudioAPIInstaller {
12
18
  }
13
19
 
14
20
  init {
15
- mHybridData = initHybrid()
21
+ val jsCallInvokerHolder = reactContext.jsCallInvokerHolder as CallInvokerHolderImpl
22
+ mHybridData = initHybrid(reactContext.javaScriptContextHolder!!.get(), jsCallInvokerHolder)
16
23
  }
17
24
 
18
- external fun initHybrid(): HybridData?
25
+ external fun initHybrid(
26
+ jsContext: Long,
27
+ callInvoker: CallInvokerHolderImpl,
28
+ ): HybridData?
19
29
 
20
- external fun install(jsContext: Long)
30
+ external fun install()
21
31
  }
@@ -12,9 +12,8 @@ class AudioAPIModule(
12
12
 
13
13
  @ReactMethod(isBlockingSynchronousMethod = true)
14
14
  fun install(): Boolean {
15
- val audioAPIInstaller = AudioAPIInstaller()
16
- val jsContext = reactContext.javaScriptContextHolder!!.get()
17
- audioAPIInstaller.install(jsContext)
15
+ val audioAPIInstaller = AudioAPIInstaller(reactContext)
16
+ audioAPIInstaller.install()
18
17
 
19
18
  return true
20
19
  }
@@ -4,10 +4,13 @@ namespace audioapi {
4
4
  using namespace facebook;
5
5
 
6
6
  AudioAPIInstallerHostObject::AudioAPIInstallerHostObject(
7
- const std::shared_ptr<AudioAPIInstallerWrapper> &wrapper, jsi::Runtime* runtime, const std::shared_ptr<facebook::react::CallInvoker> &jsInvoker)
7
+ const std::shared_ptr<AudioAPIInstallerWrapper> &wrapper,
8
+ jsi::Runtime *runtime,
9
+ const std::shared_ptr<facebook::react::CallInvoker> &jsInvoker)
8
10
  : wrapper_(wrapper) {
9
- promiseVendor_ = std::make_shared<JsiPromise::PromiseVendor>(runtime, jsInvoker);
10
- }
11
+ promiseVendor_ =
12
+ std::make_shared<JsiPromise::PromiseVendor>(runtime, jsInvoker);
13
+ }
11
14
 
12
15
  std::vector<jsi::PropNameID> AudioAPIInstallerHostObject::getPropertyNames(
13
16
  jsi::Runtime &runtime) {
@@ -34,7 +37,8 @@ jsi::Value AudioAPIInstallerHostObject::get(
34
37
  size_t count) -> jsi::Value {
35
38
  auto audioContext = wrapper_->createAudioContext();
36
39
  auto audioContextHostObject =
37
- AudioContextHostObject::createFromWrapper(audioContext, promiseVendor_);
40
+ AudioContextHostObject::createFromWrapper(
41
+ audioContext, promiseVendor_);
38
42
  return jsi::Object::createFromHostObject(
39
43
  runtime, audioContextHostObject);
40
44
  });
@@ -6,7 +6,6 @@
6
6
  #include <utility>
7
7
  #include <vector>
8
8
 
9
-
10
9
  #include "AudioAPIInstallerWrapper.h"
11
10
  #include "AudioContextHostObject.h"
12
11
  #include "JsiPromise.h"
@@ -19,17 +18,20 @@ class AudioAPIInstallerWrapper;
19
18
  class AudioAPIInstallerHostObject : public jsi::HostObject {
20
19
  public:
21
20
  explicit AudioAPIInstallerHostObject(
22
- const std::shared_ptr<AudioAPIInstallerWrapper> &wrapper, jsi::Runtime* runtime, const std::shared_ptr<react::CallInvoker> &jsInvoker);
21
+ const std::shared_ptr<AudioAPIInstallerWrapper> &wrapper,
22
+ jsi::Runtime *runtime,
23
+ const std::shared_ptr<react::CallInvoker> &jsInvoker);
23
24
 
24
25
  #ifdef ANDROID
25
26
  static void createAndInstallFromWrapper(
26
27
  const std::shared_ptr<AudioAPIInstallerWrapper> &wrapper,
27
- jlong jsContext) {
28
- auto runtime = reinterpret_cast<jsi::Runtime *>(jsContext);
29
- auto hostObject = std::make_shared<AudioAPIInstallerHostObject>(wrapper);
30
- auto object = jsi::Object::createFromHostObject(*runtime, hostObject);
31
- runtime->global().setProperty(
32
- *runtime, "__AudioAPIInstaller", std::move(object));
28
+ jsi::Runtime *rnRuntime,
29
+ const std::shared_ptr<react::CallInvoker> &jsInvoker) {
30
+ auto hostObject = std::make_shared<AudioAPIInstallerHostObject>(
31
+ wrapper, rnRuntime, jsInvoker);
32
+ auto object = jsi::Object::createFromHostObject(*rnRuntime, hostObject);
33
+ rnRuntime->global().setProperty(
34
+ *rnRuntime, "__AudioAPIInstaller", std::move(object));
33
35
  }
34
36
  #endif
35
37
 
@@ -128,8 +128,9 @@ jsi::Value AudioBufferHostObject::get(
128
128
  });
129
129
  }
130
130
 
131
- // `decodeAudioData` is a method that returns a promise to AudioBufferHostObject
132
- // It seems that async/await checks for the presence of `then` method on the object
131
+ // `decodeAudioData` is a method that returns a promise to
132
+ // AudioBufferHostObject It seems that async/await checks for the presence of
133
+ // `then` method on the object
133
134
  if (propName == "then") {
134
135
  return jsi::Value::undefined();
135
136
  }
@@ -4,7 +4,8 @@ namespace audioapi {
4
4
  using namespace facebook;
5
5
 
6
6
  AudioContextHostObject::AudioContextHostObject(
7
- const std::shared_ptr<AudioContextWrapper> &wrapper, std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor)
7
+ const std::shared_ptr<AudioContextWrapper> &wrapper,
8
+ std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor)
8
9
  : BaseAudioContextHostObject(wrapper, promiseVendor) {}
9
10
 
10
11
  std::vector<jsi::PropNameID> AudioContextHostObject::getPropertyNames(
@@ -4,9 +4,9 @@
4
4
  #include <memory>
5
5
  #include <vector>
6
6
 
7
- #include"JsiPromise.h"
8
7
  #include "AudioContextWrapper.h"
9
8
  #include "BaseAudioContextHostObject.h"
9
+ #include "JsiPromise.h"
10
10
 
11
11
  namespace audioapi {
12
12
  using namespace facebook;
@@ -14,7 +14,8 @@ using namespace facebook;
14
14
  class AudioContextHostObject : public BaseAudioContextHostObject {
15
15
  public:
16
16
  explicit AudioContextHostObject(
17
- const std::shared_ptr<AudioContextWrapper> &wrapper, std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor);
17
+ const std::shared_ptr<AudioContextWrapper> &wrapper,
18
+ std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor);
18
19
 
19
20
  jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
20
21
 
@@ -26,7 +27,8 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
26
27
  std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
27
28
 
28
29
  static std::shared_ptr<AudioContextHostObject> createFromWrapper(
29
- const std::shared_ptr<AudioContextWrapper> &wrapper, std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor) {
30
+ const std::shared_ptr<AudioContextWrapper> &wrapper,
31
+ std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor) {
30
32
  return std::make_shared<AudioContextHostObject>(wrapper, promiseVendor);
31
33
  }
32
34
 
@@ -6,7 +6,8 @@ namespace audioapi {
6
6
  using namespace facebook;
7
7
 
8
8
  BaseAudioContextHostObject::BaseAudioContextHostObject(
9
- const std::shared_ptr<BaseAudioContextWrapper> &wrapper, std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor)
9
+ const std::shared_ptr<BaseAudioContextWrapper> &wrapper,
10
+ std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor)
10
11
  : wrapper_(wrapper), promiseVendor_(promiseVendor) {
11
12
  auto destinationNodeWrapper = wrapper_->getDestination();
12
13
  destination_ =
@@ -205,25 +206,34 @@ jsi::Value BaseAudioContextHostObject::get(
205
206
  }
206
207
 
207
208
  if (propName == "decodeAudioDataSource") {
208
- auto decode = [this](jsi::Runtime& runtime,
209
- const jsi::Value&,
210
- const jsi::Value* arguments,
211
- size_t count) -> jsi::Value {
209
+ auto decode = [this](
210
+ jsi::Runtime &runtime,
211
+ const jsi::Value &,
212
+ const jsi::Value *arguments,
213
+ size_t count) -> jsi::Value {
212
214
  auto sourcePath = arguments[0].getString(runtime).utf8(runtime);
213
215
 
214
- auto promise = promiseVendor_->createPromise([this, &runtime, sourcePath](std::shared_ptr<JsiPromise::Promise> promise) {
215
- std::thread([this, &runtime, sourcePath, promise = std::move(promise)]() {
216
- auto results = wrapper_->decodeAudioDataSource(sourcePath);
217
- auto audioBufferHostObject = AudioBufferHostObject::createFromWrapper(results);
218
-
219
- promise->resolve(jsi::Object::createFromHostObject(runtime, audioBufferHostObject));
220
- }).detach();
221
- });
216
+ auto promise = promiseVendor_->createPromise(
217
+ [this, &runtime, sourcePath](
218
+ std::shared_ptr<JsiPromise::Promise> promise) {
219
+ std::thread([this,
220
+ &runtime,
221
+ sourcePath,
222
+ promise = std::move(promise)]() {
223
+ auto results = wrapper_->decodeAudioDataSource(sourcePath);
224
+ auto audioBufferHostObject =
225
+ AudioBufferHostObject::createFromWrapper(results);
226
+
227
+ promise->resolve(jsi::Object::createFromHostObject(
228
+ runtime, audioBufferHostObject));
229
+ }).detach();
230
+ });
222
231
 
223
232
  return promise;
224
233
  };
225
234
 
226
- return jsi::Function::createFromHostFunction(runtime, propNameId, 1, decode);
235
+ return jsi::Function::createFromHostFunction(
236
+ runtime, propNameId, 1, decode);
227
237
  }
228
238
 
229
239
  throw std::runtime_error("Not yet implemented!");
@@ -5,13 +5,13 @@
5
5
  #include <utility>
6
6
  #include <vector>
7
7
 
8
- #include "JsiPromise.h"
9
8
  #include "AudioBufferHostObject.h"
10
9
  #include "AudioBufferSourceNodeHostObject.h"
11
10
  #include "AudioDestinationNodeHostObject.h"
12
11
  #include "BaseAudioContextWrapper.h"
13
12
  #include "BiquadFilterNodeHostObject.h"
14
13
  #include "GainNodeHostObject.h"
14
+ #include "JsiPromise.h"
15
15
  #include "OscillatorNodeHostObject.h"
16
16
  #include "PeriodicWaveHostObject.h"
17
17
  #include "StereoPannerNodeHostObject.h"
@@ -22,7 +22,8 @@ using namespace facebook;
22
22
  class BaseAudioContextHostObject : public jsi::HostObject {
23
23
  public:
24
24
  explicit BaseAudioContextHostObject(
25
- const std::shared_ptr<BaseAudioContextWrapper> &wrapper, std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor);
25
+ const std::shared_ptr<BaseAudioContextWrapper> &wrapper,
26
+ std::shared_ptr<JsiPromise::PromiseVendor> promiseVendor);
26
27
 
27
28
  jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
28
29
 
@@ -31,6 +31,7 @@ void AudioDestinationNode::renderAudio(
31
31
  }
32
32
 
33
33
  context_->getNodeManager()->preProcessGraph();
34
+
34
35
  destinationBus->zero();
35
36
 
36
37
  AudioBus *processedBus = processAudio(destinationBus, numFrames);
@@ -1,4 +1,5 @@
1
1
  #ifdef ANDROID
2
+ #include "AudioDecoder.h"
2
3
  #include "AudioPlayer.h"
3
4
  #else
4
5
  #include "IOSAudioDecoder.h"
@@ -24,6 +25,7 @@ namespace audioapi {
24
25
  BaseAudioContext::BaseAudioContext() {
25
26
  #ifdef ANDROID
26
27
  audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
28
+ audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
27
29
  #else
28
30
  audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
29
31
  audioDecoder_ =
@@ -108,19 +110,20 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
108
110
 
109
111
  #ifdef ANDROID
110
112
  std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
111
- const std::string &source) {
112
- return {nullptr};
113
+ const std::string &path) {
114
+ auto audioBus = audioDecoder_->decodeWithFilePath(path);
115
+ return std::make_shared<AudioBuffer>(audioBus);
113
116
  }
114
117
  #else
115
118
  std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
116
- const std::string &source) {
117
- auto audioBus = audioDecoder_->decodeWithFilePath(source);
119
+ const std::string &path) {
120
+ auto audioBus = audioDecoder_->decodeWithFilePath(path);
118
121
  return std::make_shared<AudioBuffer>(audioBus);
119
122
  }
120
123
  #endif
121
124
 
122
125
  std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
123
- if (isClosed()) {
126
+ if (!isRunning()) {
124
127
  return [](AudioBus *, int) {};
125
128
  }
126
129
 
@@ -24,6 +24,7 @@ class AudioBufferSourceNode;
24
24
 
25
25
  #ifdef ANDROID
26
26
  class AudioPlayer;
27
+ class AudioDecoder;
27
28
  #else
28
29
  class IOSAudioPlayer;
29
30
  class IOSAudioDecoder;
@@ -33,13 +34,14 @@ class BaseAudioContext {
33
34
  public:
34
35
  BaseAudioContext();
35
36
  ~BaseAudioContext();
37
+
36
38
  std::string getState();
37
39
  [[nodiscard]] int getSampleRate() const;
38
40
  [[nodiscard]] double getCurrentTime() const;
39
41
  [[nodiscard]] int getBufferSizeInFrames() const;
40
42
  [[nodiscard]] std::size_t getCurrentSampleFrame() const;
41
-
42
43
  std::shared_ptr<AudioDestinationNode> getDestination();
44
+
43
45
  std::shared_ptr<OscillatorNode> createOscillator();
44
46
  std::shared_ptr<GainNode> createGain();
45
47
  std::shared_ptr<StereoPannerNode> createStereoPanner();
@@ -52,11 +54,10 @@ class BaseAudioContext {
52
54
  float *imag,
53
55
  bool disableNormalization,
54
56
  int length);
55
- std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &source);
56
57
 
58
+ std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
57
59
  std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
58
60
  std::function<void(AudioBus *, int)> renderAudio();
59
-
60
61
  AudioNodeManager *getNodeManager();
61
62
  [[nodiscard]] bool isRunning() const;
62
63
  [[nodiscard]] bool isClosed() const;
@@ -67,6 +68,7 @@ class BaseAudioContext {
67
68
 
68
69
  #ifdef ANDROID
69
70
  std::shared_ptr<AudioPlayer> audioPlayer_;
71
+ std::shared_ptr<AudioDecoder> audioDecoder_;
70
72
  #else
71
73
  std::shared_ptr<IOSAudioPlayer> audioPlayer_;
72
74
  std::shared_ptr<IOSAudioDecoder> audioDecoder_;
@@ -1,56 +1,61 @@
1
1
  #include "JsiPromise.h"
2
2
 
3
- #include <jsi/jsi.h>
4
3
  #include <ReactCommon/CallInvoker.h>
4
+ #include <jsi/jsi.h>
5
5
  #include <functional>
6
6
 
7
7
  namespace JsiPromise {
8
8
 
9
9
  using namespace facebook;
10
10
 
11
- jsi::Value PromiseVendor::createPromise(std::function<void(std::shared_ptr<Promise>)> func) {
11
+ jsi::Value PromiseVendor::createPromise(
12
+ std::function<void(std::shared_ptr<Promise>)> func) {
12
13
  if (_runtime == nullptr) {
13
14
  throw new std::runtime_error("Runtime was null!");
14
15
  }
15
- auto& runtime = *_runtime;
16
+ auto &runtime = *_runtime;
16
17
  auto callInvoker = _callInvoker;
17
18
 
18
19
  // get Promise constructor
19
20
  auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
20
21
 
21
22
  // create a "run" function (first Promise arg)
22
- auto runPromise = jsi::Function::createFromHostFunction(runtime,
23
- jsi::PropNameID::forUtf8(runtime, "runPromise"),
24
- 2,
25
- [callInvoker, func](jsi::Runtime& runtime,
26
- const jsi::Value& thisValue,
27
- const jsi::Value* arguments,
28
- size_t count) -> jsi::Value {
29
- auto resolveLocal = arguments[0].asObject(runtime).asFunction(runtime);
30
- auto resolve = std::make_shared<jsi::Function>(std::move(resolveLocal));
31
- auto rejectLocal = arguments[1].asObject(runtime).asFunction(runtime);
32
- auto reject = std::make_shared<jsi::Function>(std::move(rejectLocal));
33
-
34
- auto resolveWrapper = [resolve, &runtime, callInvoker](jsi::Value value) -> void {
35
- auto valueShared = std::make_shared<jsi::Value>(std::move(value));
36
- callInvoker->invokeAsync([resolve, &runtime, valueShared]() -> void {
37
- resolve->call(runtime, *valueShared);
38
- });
39
- };
23
+ auto runPromise = jsi::Function::createFromHostFunction(
24
+ runtime,
25
+ jsi::PropNameID::forUtf8(runtime, "runPromise"),
26
+ 2,
27
+ [callInvoker, func](
28
+ jsi::Runtime &runtime,
29
+ const jsi::Value &thisValue,
30
+ const jsi::Value *arguments,
31
+ size_t count) -> jsi::Value {
32
+ auto resolveLocal = arguments[0].asObject(runtime).asFunction(runtime);
33
+ auto resolve = std::make_shared<jsi::Function>(std::move(resolveLocal));
34
+ auto rejectLocal = arguments[1].asObject(runtime).asFunction(runtime);
35
+ auto reject = std::make_shared<jsi::Function>(std::move(rejectLocal));
40
36
 
41
- auto rejectWrapper = [reject, &runtime, callInvoker](const std::string& errorMessage) -> void {
42
- auto error = jsi::JSError(runtime, errorMessage);
43
- auto errorShared = std::make_shared<jsi::JSError>(error);
44
- callInvoker->invokeAsync([reject, &runtime, errorShared]() -> void {
45
- reject->call(runtime, errorShared->value());
46
- });
47
- };
37
+ auto resolveWrapper =
38
+ [resolve, &runtime, callInvoker](jsi::Value value) -> void {
39
+ auto valueShared = std::make_shared<jsi::Value>(std::move(value));
40
+ callInvoker->invokeAsync([resolve, &runtime, valueShared]() -> void {
41
+ resolve->call(runtime, *valueShared);
42
+ });
43
+ };
44
+
45
+ auto rejectWrapper = [reject, &runtime, callInvoker](
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());
51
+ });
52
+ };
48
53
 
49
- auto promise = std::make_shared<Promise>(resolveWrapper, rejectWrapper);
50
- func(promise);
54
+ auto promise = std::make_shared<Promise>(resolveWrapper, rejectWrapper);
55
+ func(promise);
51
56
 
52
- return jsi::Value::undefined();
53
- });
57
+ return jsi::Value::undefined();
58
+ });
54
59
 
55
60
  // return new Promise((resolve, reject) => ...)
56
61
  return promiseCtor.callAsConstructor(runtime, runPromise);