react-native-audio-api 0.3.0-rc1 → 0.3.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 (121) hide show
  1. package/android/CMakeLists.txt +4 -4
  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 +10 -12
  5. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +16 -9
  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.h +26 -27
  12. package/common/cpp/HostObjects/AudioBufferHostObject.h +79 -13
  13. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +93 -14
  14. package/common/cpp/HostObjects/AudioContextHostObject.h +10 -19
  15. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +3 -16
  16. package/common/cpp/HostObjects/AudioNodeHostObject.h +48 -11
  17. package/common/cpp/HostObjects/AudioParamHostObject.h +56 -14
  18. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +23 -16
  19. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +131 -13
  20. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +76 -18
  21. package/common/cpp/HostObjects/Constants.h +2 -0
  22. package/common/cpp/HostObjects/GainNodeHostObject.h +10 -15
  23. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +40 -17
  24. package/common/cpp/HostObjects/PeriodicWaveHostObject.h +4 -17
  25. package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +10 -17
  26. package/common/cpp/core/AudioBufferSourceNode.cpp +180 -73
  27. package/common/cpp/core/AudioBufferSourceNode.h +41 -1
  28. package/common/cpp/core/AudioDestinationNode.cpp +1 -0
  29. package/common/cpp/core/AudioDestinationNode.h +1 -1
  30. package/common/cpp/core/AudioScheduledSourceNode.cpp +86 -21
  31. package/common/cpp/core/AudioScheduledSourceNode.h +12 -4
  32. package/common/cpp/core/BaseAudioContext.cpp +8 -5
  33. package/common/cpp/core/BaseAudioContext.h +5 -3
  34. package/common/cpp/core/OscillatorNode.cpp +7 -2
  35. package/common/cpp/jsi/JsiHostObject.cpp +85 -0
  36. package/common/cpp/jsi/JsiHostObject.h +94 -0
  37. package/common/cpp/jsi/JsiPromise.cpp +65 -0
  38. package/common/cpp/jsi/JsiPromise.h +48 -0
  39. package/common/cpp/utils/AudioUtils.cpp +26 -0
  40. package/common/cpp/utils/AudioUtils.h +16 -0
  41. package/ios/AudioAPIModule.mm +3 -6
  42. package/ios/AudioDecoder/AudioDecoder.h +1 -1
  43. package/ios/AudioDecoder/AudioDecoder.m +14 -102
  44. package/ios/AudioDecoder/IOSAudioDecoder.h +2 -0
  45. package/ios/AudioDecoder/IOSAudioDecoder.mm +7 -1
  46. package/ios/AudioPlayer/AudioPlayer.m +3 -1
  47. package/lib/module/core/AudioBufferSourceNode.js +15 -0
  48. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  49. package/lib/module/core/BaseAudioContext.js +2 -3
  50. package/lib/module/core/BaseAudioContext.js.map +1 -1
  51. package/lib/module/index.js +18 -3
  52. package/lib/module/index.js.map +1 -1
  53. package/lib/typescript/core/AudioBufferSourceNode.d.ts +7 -0
  54. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
  55. package/lib/typescript/core/BaseAudioContext.d.ts +2 -2
  56. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  57. package/lib/typescript/core/types.d.ts +0 -6
  58. package/lib/typescript/core/types.d.ts.map +1 -1
  59. package/lib/typescript/index.d.ts +8 -4
  60. package/lib/typescript/index.d.ts.map +1 -1
  61. package/lib/typescript/interfaces.d.ts +5 -1
  62. package/lib/typescript/interfaces.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/src/core/AudioBufferSourceNode.ts +23 -0
  65. package/src/core/BaseAudioContext.ts +3 -8
  66. package/src/core/types.ts +0 -7
  67. package/src/index.ts +26 -12
  68. package/src/interfaces.ts +6 -1
  69. package/android/libs/fftw3/x86/libfftw3.a +0 -0
  70. package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
  71. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +0 -54
  72. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +0 -38
  73. package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +0 -16
  74. package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +0 -12
  75. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +0 -149
  76. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +0 -79
  77. package/common/cpp/HostObjects/AudioContextHostObject.cpp +0 -54
  78. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +0 -33
  79. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -102
  80. package/common/cpp/HostObjects/AudioParamHostObject.cpp +0 -115
  81. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +0 -73
  82. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +0 -240
  83. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +0 -125
  84. package/common/cpp/HostObjects/GainNodeHostObject.cpp +0 -41
  85. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +0 -88
  86. package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +0 -33
  87. package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +0 -41
  88. package/common/cpp/utils/JsiPromise.cpp +0 -59
  89. package/common/cpp/utils/JsiPromise.h +0 -42
  90. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +0 -45
  91. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +0 -26
  92. package/common/cpp/wrappers/AudioBufferWrapper.cpp +0 -46
  93. package/common/cpp/wrappers/AudioBufferWrapper.h +0 -30
  94. package/common/cpp/wrappers/AudioContextWrapper.cpp +0 -17
  95. package/common/cpp/wrappers/AudioContextWrapper.h +0 -19
  96. package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +0 -16
  97. package/common/cpp/wrappers/AudioNodeWrapper.cpp +0 -37
  98. package/common/cpp/wrappers/AudioNodeWrapper.h +0 -25
  99. package/common/cpp/wrappers/AudioParamWrapper.cpp +0 -42
  100. package/common/cpp/wrappers/AudioParamWrapper.h +0 -25
  101. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +0 -23
  102. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +0 -23
  103. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +0 -83
  104. package/common/cpp/wrappers/BaseAudioContextWrapper.h +0 -50
  105. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +0 -60
  106. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +0 -37
  107. package/common/cpp/wrappers/GainNodeWrapper.cpp +0 -14
  108. package/common/cpp/wrappers/GainNodeWrapper.h +0 -20
  109. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +0 -44
  110. package/common/cpp/wrappers/OscillatorNodeWrapper.h +0 -31
  111. package/common/cpp/wrappers/PeriodicWaveWrapper.h +0 -17
  112. package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +0 -16
  113. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +0 -21
  114. package/lib/module/utils/resolveAudioSource.js +0 -10
  115. package/lib/module/utils/resolveAudioSource.js.map +0 -1
  116. package/lib/typescript/utils/resolveAudioSource.d.ts +0 -3
  117. package/lib/typescript/utils/resolveAudioSource.d.ts.map +0 -1
  118. package/src/utils/resolveAudioSource.ts +0 -14
  119. /package/android/libs/{fftw3/arm64-v8a → arm64-v8a}/libfftw3.a +0 -0
  120. /package/android/libs/{fftw3/armeabi-v7a → armeabi-v7a}/libfftw3.a +0 -0
  121. /package/android/libs/include/{fftw3/fftw3.h → fftw3.h} +0 -0
@@ -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_;
@@ -40,15 +40,20 @@ void OscillatorNode::setPeriodicWave(
40
40
  }
41
41
 
42
42
  void OscillatorNode::processNode(AudioBus *processingBus, int framesToProcess) {
43
+ size_t startOffset = 0;
44
+ size_t offsetLength = 0;
45
+
46
+ updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength);
47
+
43
48
  if (!isPlaying()) {
44
49
  processingBus->zero();
45
50
  return;
46
51
  }
47
52
 
48
- double time = context_->getCurrentTime();
49
53
  double deltaTime = 1.0 / context_->getSampleRate();
54
+ double time = context_->getCurrentTime() + startOffset * deltaTime;
50
55
 
51
- for (int i = 0; i < framesToProcess; i += 1) {
56
+ for (size_t i = startOffset; i < offsetLength; i += 1) {
52
57
  auto detuneRatio =
53
58
  std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
54
59
  auto detunedFrequency =
@@ -0,0 +1,85 @@
1
+ #include "JsiHostObject.h"
2
+
3
+ namespace audioapi {
4
+ JsiHostObject::JsiHostObject() {
5
+ propertyGetters_ = std::make_unique<std::unordered_map<
6
+ std::string,
7
+ jsi::Value (JsiHostObject::*)(jsi::Runtime &)>>();
8
+ propertyFunctions_ = std::make_unique<std::unordered_map<
9
+ std::string,
10
+ jsi::Value (JsiHostObject::*)(
11
+ jsi::Runtime &, const jsi::Value &, const jsi::Value *, size_t)>>();
12
+ propertySetters_ = std::make_unique<std::unordered_map<
13
+ std::string,
14
+ void (JsiHostObject::*)(jsi::Runtime &, const jsi::Value &)>>();
15
+ }
16
+
17
+ std::vector<jsi::PropNameID> JsiHostObject::getPropertyNames(jsi::Runtime &rt) {
18
+ std::vector<jsi::PropNameID> propertyNames;
19
+ propertyNames.reserve(
20
+ propertyGetters_->size() + propertyFunctions_->size() +
21
+ propertySetters_->size());
22
+
23
+ for (const auto &it : *propertyGetters_) {
24
+ propertyNames.push_back(jsi::PropNameID::forUtf8(rt, it.first));
25
+ }
26
+
27
+ for (const auto &it : *propertyFunctions_) {
28
+ propertyNames.push_back(jsi::PropNameID::forAscii(rt, it.first));
29
+ }
30
+
31
+ for (const auto &it : *propertySetters_) {
32
+ propertyNames.push_back(jsi::PropNameID::forAscii(rt, it.first));
33
+ }
34
+
35
+ return propertyNames;
36
+ }
37
+
38
+ jsi::Value JsiHostObject::get(
39
+ jsi::Runtime &runtime,
40
+ const jsi::PropNameID &name) {
41
+ auto nameAsString = name.utf8(runtime);
42
+
43
+ auto propertyGetter = propertyGetters_->find(nameAsString);
44
+ if (propertyGetter != propertyGetters_->end()) {
45
+ auto dispatcher = [this, &propertyGetter](jsi::Runtime &runtime) {
46
+ return (this->*(propertyGetter->second))(runtime);
47
+ };
48
+
49
+ return dispatcher(runtime);
50
+ }
51
+
52
+ auto propertyFunction = propertyFunctions_->find(nameAsString);
53
+ if (propertyFunction != propertyFunctions_->end()) {
54
+ auto dispatcher = [this, &propertyFunction](
55
+ jsi::Runtime &runtime,
56
+ const jsi::Value &thisVal,
57
+ const jsi::Value *args,
58
+ size_t count) -> jsi::Value {
59
+ return (this->*(propertyFunction->second))(runtime, thisVal, args, count);
60
+ };
61
+
62
+ return jsi::Function::createFromHostFunction(runtime, name, 0, dispatcher);
63
+ }
64
+
65
+ return jsi::Value::undefined();
66
+ }
67
+
68
+ void JsiHostObject::set(
69
+ jsi::Runtime &runtime,
70
+ const jsi::PropNameID &name,
71
+ const jsi::Value &value) {
72
+ auto nameAsString = name.utf8(runtime);
73
+
74
+ auto propertySetter = propertySetters_->find(nameAsString);
75
+
76
+ if (propertySetter != propertySetters_->end()) {
77
+ auto dispatcher = [this, &propertySetter](
78
+ jsi::Runtime &runtime, const jsi::Value &value) {
79
+ return (this->*(propertySetter->second))(runtime, value);
80
+ };
81
+
82
+ return dispatcher(runtime, value);
83
+ }
84
+ }
85
+ } // namespace audioapi
@@ -0,0 +1,94 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <memory>
5
+ #include <string>
6
+ #include <unordered_map>
7
+ #include <utility>
8
+ #include <vector>
9
+
10
+ #define JSI_HOST_FUNCTION(NAME) \
11
+ jsi::Value NAME( \
12
+ jsi::Runtime &runtime, \
13
+ const jsi::Value &thisVal, \
14
+ const jsi::Value *args, \
15
+ size_t count)
16
+
17
+ #define JSI_EXPORT_FUNCTION(CLASS, FUNCTION) \
18
+ std::make_pair( \
19
+ std::string(#FUNCTION), \
20
+ static_cast<jsi::Value (JsiHostObject::*)( \
21
+ jsi::Runtime &, const jsi::Value &, const jsi::Value *, size_t)>( \
22
+ &CLASS::FUNCTION))
23
+
24
+ #define JSI_PROPERTY_GETTER(name) jsi::Value name(jsi::Runtime &runtime)
25
+
26
+ #define JSI_EXPORT_PROPERTY_GETTER(CLASS, FUNCTION) \
27
+ std::make_pair( \
28
+ std::string(#FUNCTION), \
29
+ static_cast<jsi::Value (JsiHostObject::*)(jsi::Runtime &)>( \
30
+ &CLASS::FUNCTION))
31
+
32
+ #define JSI_PROPERTY_SETTER(name) \
33
+ void name(jsi::Runtime &runtime, const jsi::Value &value)
34
+
35
+ #define JSI_EXPORT_PROPERTY_SETTER(CLASS, FUNCTION) \
36
+ std::make_pair( \
37
+ std::string(#FUNCTION), \
38
+ static_cast<void (JsiHostObject::*)( \
39
+ jsi::Runtime &, const jsi::Value &)>(&CLASS::FUNCTION))
40
+
41
+ namespace audioapi {
42
+
43
+ using namespace facebook;
44
+
45
+ class JsiHostObject : public jsi::HostObject {
46
+ public:
47
+ JsiHostObject();
48
+
49
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
50
+
51
+ jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
52
+
53
+ void set(
54
+ jsi::Runtime &runtime,
55
+ const jsi::PropNameID &name,
56
+ const jsi::Value &value) override;
57
+
58
+ template <typename... Args>
59
+ void addGetters(Args... args) {
60
+ (propertyGetters_->insert(args), ...);
61
+ }
62
+
63
+ template <typename... Args>
64
+ void addSetters(Args... args) {
65
+ (propertySetters_->insert(args), ...);
66
+ }
67
+
68
+ template <typename... Args>
69
+ void addFunctions(Args... args) {
70
+ (propertyFunctions_->insert(args), ...);
71
+ }
72
+
73
+ protected:
74
+ std::unique_ptr<std::unordered_map<
75
+ std::string,
76
+ jsi::Value (JsiHostObject::*)(jsi::Runtime &)>>
77
+ propertyGetters_;
78
+
79
+ std::unique_ptr<std::unordered_map<
80
+ std::string,
81
+ jsi::Value (JsiHostObject::*)(
82
+ jsi::Runtime &,
83
+ const jsi::Value &,
84
+ const jsi::Value *,
85
+ size_t)>>
86
+ propertyFunctions_;
87
+
88
+ std::unique_ptr<std::unordered_map<
89
+ std::string,
90
+ void (JsiHostObject::*)(jsi::Runtime &, const jsi::Value &)>>
91
+ propertySetters_;
92
+ };
93
+
94
+ } // namespace audioapi
@@ -0,0 +1,65 @@
1
+ #include "JsiPromise.h"
2
+
3
+ #include <ReactCommon/CallInvoker.h>
4
+ #include <jsi/jsi.h>
5
+ #include <functional>
6
+
7
+ namespace audioapi {
8
+
9
+ using namespace facebook;
10
+
11
+ jsi::Value PromiseVendor::createPromise(
12
+ const std::function<void(std::shared_ptr<Promise>)> &function) {
13
+ if (runtime_ == nullptr) {
14
+ throw std::runtime_error("Runtime was null!");
15
+ }
16
+
17
+ auto &runtime = *runtime_;
18
+ auto callInvoker = callInvoker_;
19
+
20
+ // get Promise constructor
21
+ auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
22
+
23
+ // create a "run" function (first Promise arg)
24
+ auto runPromise = jsi::Function::createFromHostFunction(
25
+ runtime,
26
+ jsi::PropNameID::forUtf8(runtime, "runPromise"),
27
+ 2,
28
+ [callInvoker, function](
29
+ jsi::Runtime &runtime,
30
+ const jsi::Value &thisValue,
31
+ const jsi::Value *arguments,
32
+ size_t count) -> jsi::Value {
33
+ auto resolveLocal = arguments[0].asObject(runtime).asFunction(runtime);
34
+ auto resolve = std::make_shared<jsi::Function>(std::move(resolveLocal));
35
+ auto rejectLocal = arguments[1].asObject(runtime).asFunction(runtime);
36
+ auto reject = std::make_shared<jsi::Function>(std::move(rejectLocal));
37
+
38
+ auto resolveWrapper =
39
+ [resolve, &runtime, callInvoker](jsi::Value value) -> void {
40
+ auto valueShared = std::make_shared<jsi::Value>(std::move(value));
41
+ callInvoker->invokeAsync([resolve, &runtime, valueShared]() -> void {
42
+ resolve->call(runtime, *valueShared);
43
+ });
44
+ };
45
+
46
+ auto rejectWrapper = [reject, &runtime, callInvoker](
47
+ const std::string &errorMessage) -> void {
48
+ auto error = jsi::JSError(runtime, errorMessage);
49
+ auto errorShared = std::make_shared<jsi::JSError>(error);
50
+ callInvoker->invokeAsync([reject, &runtime, errorShared]() -> void {
51
+ reject->call(runtime, errorShared->value());
52
+ });
53
+ };
54
+
55
+ auto promise = std::make_shared<Promise>(resolveWrapper, rejectWrapper);
56
+ function(promise);
57
+
58
+ return jsi::Value::undefined();
59
+ });
60
+
61
+ // return new Promise((resolve, reject) => ...)
62
+ return promiseCtor.callAsConstructor(runtime, runPromise);
63
+ }
64
+
65
+ } // namespace audioapi
@@ -0,0 +1,48 @@
1
+ #pragma once
2
+
3
+ #include <ReactCommon/CallInvoker.h>
4
+ #include <jsi/jsi.h>
5
+ #include <memory>
6
+ #include <string>
7
+ #include <utility>
8
+
9
+ namespace audioapi {
10
+
11
+ using namespace facebook;
12
+
13
+ class Promise {
14
+ public:
15
+ Promise(
16
+ std::function<void(jsi::Value)> resolve,
17
+ std::function<void(const std::string &)> reject)
18
+ : resolve_(std::move(resolve)), reject_(std::move(reject)) {}
19
+
20
+ void resolve(jsi::Value &&value) {
21
+ resolve_(std::forward<jsi::Value>(value));
22
+ }
23
+ void reject(const std::string &errorMessage) {
24
+ reject_(errorMessage);
25
+ }
26
+
27
+ private:
28
+ std::function<void(jsi::Value)> resolve_;
29
+ std::function<void(const std::string &)> reject_;
30
+ };
31
+
32
+ class PromiseVendor {
33
+ public:
34
+ PromiseVendor(
35
+ jsi::Runtime *runtime,
36
+ const std::shared_ptr<react::CallInvoker> &callInvoker)
37
+ : runtime_(runtime), callInvoker_(callInvoker) {}
38
+
39
+ public:
40
+ jsi::Value createPromise(
41
+ const std::function<void(std::shared_ptr<Promise>)> &function);
42
+
43
+ private:
44
+ jsi::Runtime *runtime_;
45
+ std::shared_ptr<react::CallInvoker> callInvoker_;
46
+ };
47
+
48
+ } // namespace audioapi
@@ -0,0 +1,26 @@
1
+ #include "AudioUtils.h"
2
+
3
+ namespace audioapi::AudioUtils {
4
+ size_t timeToSampleFrame(double time, int sampleRate) {
5
+ return static_cast<size_t>(time * sampleRate);
6
+ }
7
+
8
+ double sampleFrameToTime(int sampleFrame, int sampleRate) {
9
+ return static_cast<double>(sampleFrame) / sampleRate;
10
+ }
11
+
12
+ float linearInterpolate(
13
+ const float *source,
14
+ size_t firstIndex,
15
+ size_t secondIndex,
16
+ float factor) {
17
+ if (firstIndex == secondIndex && firstIndex >= 1) {
18
+ return source[firstIndex] +
19
+ factor * (source[firstIndex] - source[firstIndex - 1]);
20
+ }
21
+
22
+ return source[firstIndex] +
23
+ factor * (source[secondIndex] - source[firstIndex]);
24
+ }
25
+
26
+ } // namespace audioapi::AudioUtils
@@ -0,0 +1,16 @@
1
+ #pragma once
2
+
3
+ #include <cstddef>
4
+
5
+ namespace audioapi::AudioUtils {
6
+ size_t timeToSampleFrame(double time, int sampleRate);
7
+
8
+ double sampleFrameToTime(int sampleFrame, int sampleRate);
9
+
10
+ float linearInterpolate(
11
+ const float *source,
12
+ size_t firstIndex,
13
+ size_t secondIndex,
14
+ float factor);
15
+
16
+ } // namespace audioapi::AudioUtils
@@ -1,13 +1,12 @@
1
1
  #import "AudioAPIModule.h"
2
2
 
3
- #import <ReactCommon/RCTTurboModule.h>
4
3
  #import <React/RCTBridge+Private.h>
5
4
  #import <React/RCTBridge.h>
6
5
  #import <React/RCTUtils.h>
6
+ #import <ReactCommon/RCTTurboModule.h>
7
7
  #import <jsi/jsi.h>
8
8
 
9
9
  #import "AudioAPIInstallerHostObject.h"
10
- #import "AudioAPIInstallerWrapper.h"
11
10
 
12
11
  @implementation AudioAPIModule
13
12
 
@@ -34,10 +33,8 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
34
33
 
35
34
  auto &runtime = *jsRuntime;
36
35
 
37
- auto wrapper = std::make_shared<audioapi::AudioAPIInstallerWrapper>();
38
- auto hostObject = std::make_shared<audioapi::AudioAPIInstallerHostObject>(wrapper, jsRuntime, cxxBridge.jsCallInvoker);
39
- auto object = jsi::Object::createFromHostObject(runtime, hostObject);
40
- runtime.global().setProperty(runtime, "__AudioAPIInstaller", std::move(object));
36
+ auto hostObject = std::make_shared<audioapi::AudioAPIInstallerHostObject>(jsRuntime, cxxBridge.jsCallInvoker);
37
+ hostObject->install();
41
38
 
42
39
  NSLog(@"Successfully installed JSI bindings for react-native-audio-api!");
43
40
  return @true;
@@ -10,7 +10,7 @@
10
10
 
11
11
  - (instancetype)initWithSampleRate:(int)sampleRate;
12
12
 
13
- - (const AudioBufferList *)decode:(NSString *)pathOrURL;
13
+ - (const AudioBufferList *)decodeWithFile:(NSString *)path;
14
14
 
15
15
  - (void)cleanup;
16
16
 
@@ -10,21 +10,7 @@
10
10
  return self;
11
11
  }
12
12
 
13
- - (const AudioBufferList *)decode:(NSString *)pathOrURL
14
- {
15
- // check if the input is a URL or a local file path
16
- NSURL *url = [NSURL URLWithString:pathOrURL];
17
-
18
- if (url && url.scheme) {
19
- self.buffer = [self decodeWithURL:url];
20
- } else {
21
- self.buffer = [self decodeWithFilePath:pathOrURL];
22
- }
23
-
24
- return self.buffer.audioBufferList;
25
- }
26
-
27
- - (AVAudioPCMBuffer *)decodeWithFilePath:(NSString *)path
13
+ - (const AudioBufferList *)decodeWithFile:(NSString *)path
28
14
  {
29
15
  NSError *error = nil;
30
16
  NSURL *fileURL = [NSURL fileURLWithPath:path];
@@ -49,85 +35,12 @@
49
35
  }
50
36
 
51
37
  if (self.sampleRate != audioFile.processingFormat.sampleRate) {
52
- return [self convertBuffer:buffer ToFormat:format];
53
- }
54
-
55
- return buffer;
56
- }
57
-
58
- - (AVAudioPCMBuffer *)decodeWithURL:(NSURL *)url
59
- {
60
- __block NSURL *tempFileURL = nil;
61
-
62
- dispatch_group_t group = dispatch_group_create();
63
-
64
- dispatch_group_enter(group);
65
-
66
- [self downloadFileFromURL:url
67
- completion:^(NSURL *downloadedFileURL, NSError *downloadError) {
68
- if (downloadError) {
69
- NSLog(@"Error downloading file: %@", downloadError.localizedDescription);
70
- tempFileURL = nil;
71
- } else {
72
- tempFileURL = downloadedFileURL;
73
- }
74
-
75
- dispatch_group_leave(group);
76
- }];
77
-
78
- dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
79
-
80
- if (!tempFileURL) {
81
- NSLog(@"Cannot process given url");
82
- return nil;
38
+ self.buffer = [self convertBuffer:buffer ToFormat:format];
39
+ } else {
40
+ self.buffer = buffer;
83
41
  }
84
42
 
85
- return [self decodeWithFilePath:tempFileURL.path];
86
- }
87
-
88
- - (void)downloadFileFromURL:(NSURL *)url completion:(void (^)(NSURL *tempFileURL, NSError *error))completion
89
- {
90
- // get unique file path in temporary dir
91
- NSString *tempDirectory = NSTemporaryDirectory();
92
- NSString *timestamp = [NSString stringWithFormat:@"_%@", @((long long)[[NSDate date] timeIntervalSince1970])];
93
- NSString *fileNameWithTimestamp = [url.lastPathComponent stringByDeletingPathExtension];
94
- fileNameWithTimestamp = [fileNameWithTimestamp stringByAppendingString:timestamp];
95
- NSString *fileExtension =
96
- [url.pathExtension length] > 0 ? [NSString stringWithFormat:@".%@", url.pathExtension] : @"";
97
- NSString *tempFilePath =
98
- [tempDirectory stringByAppendingPathComponent:[fileNameWithTimestamp stringByAppendingString:fileExtension]];
99
- NSURL *tempFileURL = [NSURL fileURLWithPath:tempFilePath];
100
-
101
- // download file
102
- NSURLSession *session = [NSURLSession sharedSession];
103
- NSURLSessionDownloadTask *downloadTask = [session
104
- downloadTaskWithURL:url
105
- completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
106
- if (error) {
107
- NSLog(@"Error downloading file: %@", error.localizedDescription);
108
- if (completion) {
109
- completion(nil, error);
110
- }
111
- return;
112
- }
113
-
114
- // move to generated file path in temporary dir
115
- NSError *fileError = nil;
116
- BOOL success = [[NSFileManager defaultManager] moveItemAtURL:location toURL:tempFileURL error:&fileError];
117
- if (success) {
118
- NSLog(@"File downloaded successfully to %@", tempFileURL.path);
119
- if (completion) {
120
- completion(tempFileURL, nil);
121
- }
122
- } else {
123
- NSLog(@"Error moving downloaded file: %@", fileError.localizedDescription);
124
- if (completion) {
125
- completion(nil, fileError);
126
- }
127
- }
128
- }];
129
-
130
- [downloadTask resume];
43
+ return self.buffer.audioBufferList;
131
44
  }
132
45
 
133
46
  - (AVAudioPCMBuffer *)convertBuffer:(AVAudioPCMBuffer *)buffer ToFormat:(AVAudioFormat *)format
@@ -138,16 +51,15 @@
138
51
  [[AVAudioPCMBuffer alloc] initWithPCMFormat:format frameCapacity:(AVAudioFrameCount)buffer.frameCapacity];
139
52
 
140
53
  AVAudioConverterInputBlock inputBlock =
141
- ^AVAudioBuffer *(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus)
142
- {
143
- if (buffer.frameLength > 0) {
144
- *outStatus = AVAudioConverterInputStatus_HaveData;
145
- return buffer;
146
- } else {
147
- *outStatus = AVAudioConverterInputStatus_NoDataNow;
148
- return nil;
149
- }
150
- };
54
+ ^AVAudioBuffer *(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus) {
55
+ if (buffer.frameLength > 0) {
56
+ *outStatus = AVAudioConverterInputStatus_HaveData;
57
+ return buffer;
58
+ } else {
59
+ *outStatus = AVAudioConverterInputStatus_NoDataNow;
60
+ return nil;
61
+ }
62
+ };
151
63
 
152
64
  [converter convertToBuffer:convertedBuffer error:&error withInputFromBlock:inputBlock];
153
65
 
@@ -22,5 +22,7 @@ class IOSAudioDecoder {
22
22
  ~IOSAudioDecoder();
23
23
 
24
24
  AudioBus *decodeWithFilePath(const std::string &path);
25
+ // TODO: implement this
26
+ AudioBus *decodeWithArrayBuffer();
25
27
  };
26
28
  } // namespace audioapi
@@ -19,7 +19,7 @@ IOSAudioDecoder::~IOSAudioDecoder()
19
19
 
20
20
  AudioBus *IOSAudioDecoder::decodeWithFilePath(const std::string &path)
21
21
  {
22
- auto bufferList = [audioDecoder_ decode:[NSString stringWithUTF8String:path.c_str()]];
22
+ auto bufferList = [audioDecoder_ decodeWithFile:[NSString stringWithUTF8String:path.c_str()]];
23
23
  AudioBus *audioBus;
24
24
  if (bufferList) {
25
25
  auto numberOfChannels = bufferList->mNumberBuffers;
@@ -37,4 +37,10 @@ AudioBus *IOSAudioDecoder::decodeWithFilePath(const std::string &path)
37
37
 
38
38
  return audioBus;
39
39
  }
40
+
41
+ AudioBus *IOSAudioDecoder::decodeWithArrayBuffer()
42
+ {
43
+ // TODO: implement his
44
+ return new AudioBus(sampleRate_, 1, 1);
45
+ }
40
46
  } // namespace audioapi
@@ -62,7 +62,9 @@
62
62
  // which is safer to base our internal AudioBus sizes.
63
63
  // Buut no documentation => no guarantee :)
64
64
  // If something is crackling when it should play silence, start here 📻
65
- return (int)(self.audioSession.preferredIOBufferDuration * self.audioSession.sampleRate);
65
+ double maxBufferDuration =
66
+ fmax(0.02, fmax(self.audioSession.IOBufferDuration, self.audioSession.preferredIOBufferDuration));
67
+ return (int)(maxBufferDuration * self.audioSession.sampleRate + 1);
66
68
  }
67
69
 
68
70
  - (void)start
@@ -1,8 +1,11 @@
1
1
  import AudioScheduledSourceNode from './AudioScheduledSourceNode';
2
2
  import AudioBuffer from './AudioBuffer';
3
+ import AudioParam from './AudioParam';
3
4
  export default class AudioBufferSourceNode extends AudioScheduledSourceNode {
4
5
  constructor(context, node) {
5
6
  super(context, node);
7
+ this.detune = new AudioParam(node.detune);
8
+ this.playbackRate = new AudioParam(node.playbackRate);
6
9
  }
7
10
  get buffer() {
8
11
  const buffer = this.node.buffer;
@@ -24,5 +27,17 @@ export default class AudioBufferSourceNode extends AudioScheduledSourceNode {
24
27
  set loop(value) {
25
28
  this.node.loop = value;
26
29
  }
30
+ get loopStart() {
31
+ return this.node.loopStart;
32
+ }
33
+ set loopStart(value) {
34
+ this.node.loopStart = value;
35
+ }
36
+ get loopEnd() {
37
+ return this.node.loopEnd;
38
+ }
39
+ set loopEnd(value) {
40
+ this.node.loopEnd = value;
41
+ }
27
42
  }
28
43
  //# sourceMappingURL=AudioBufferSourceNode.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["AudioScheduledSourceNode","AudioBuffer","AudioBufferSourceNode","constructor","context","node","buffer","loop","value"],"sourceRoot":"../../../src","sources":["core/AudioBufferSourceNode.ts"],"mappings":"AACA,OAAOA,wBAAwB,MAAM,4BAA4B;AAEjE,OAAOC,WAAW,MAAM,eAAe;AAEvC,eAAe,MAAMC,qBAAqB,SAASF,wBAAwB,CAAC;EAC1EG,WAAWA,CAACC,OAAyB,EAAEC,IAA4B,EAAE;IACnE,KAAK,CAACD,OAAO,EAAEC,IAAI,CAAC;EACtB;EAEA,IAAWC,MAAMA,CAAA,EAAuB;IACtC,MAAMA,MAAM,GAAI,IAAI,CAACD,IAAI,CAA4BC,MAAM;IAC3D,IAAI,CAACA,MAAM,EAAE;MACX,OAAO,IAAI;IACb;IACA,OAAO,IAAIL,WAAW,CAACK,MAAM,CAAC;EAChC;EAEA,IAAWA,MAAMA,CAACA,MAA0B,EAAE;IAC5C,IAAI,CAACA,MAAM,EAAE;MACV,IAAI,CAACD,IAAI,CAA4BC,MAAM,GAAG,IAAI;MACnD;IACF;IAEC,IAAI,CAACD,IAAI,CAA4BC,MAAM,GAAGA,MAAM,CAACA,MAAM;EAC9D;EAEA,IAAWC,IAAIA,CAAA,EAAY;IACzB,OAAQ,IAAI,CAACF,IAAI,CAA4BE,IAAI;EACnD;EAEA,IAAWA,IAAIA,CAACC,KAAc,EAAE;IAC7B,IAAI,CAACH,IAAI,CAA4BE,IAAI,GAAGC,KAAK;EACpD;AACF","ignoreList":[]}
1
+ {"version":3,"names":["AudioScheduledSourceNode","AudioBuffer","AudioParam","AudioBufferSourceNode","constructor","context","node","detune","playbackRate","buffer","loop","value","loopStart","loopEnd"],"sourceRoot":"../../../src","sources":["core/AudioBufferSourceNode.ts"],"mappings":"AACA,OAAOA,wBAAwB,MAAM,4BAA4B;AAEjE,OAAOC,WAAW,MAAM,eAAe;AACvC,OAAOC,UAAU,MAAM,cAAc;AAErC,eAAe,MAAMC,qBAAqB,SAASH,wBAAwB,CAAC;EAI1EI,WAAWA,CAACC,OAAyB,EAAEC,IAA4B,EAAE;IACnE,KAAK,CAACD,OAAO,EAAEC,IAAI,CAAC;IAEpB,IAAI,CAACC,MAAM,GAAG,IAAIL,UAAU,CAACI,IAAI,CAACC,MAAM,CAAC;IACzC,IAAI,CAACC,YAAY,GAAG,IAAIN,UAAU,CAACI,IAAI,CAACE,YAAY,CAAC;EACvD;EAEA,IAAWC,MAAMA,CAAA,EAAuB;IACtC,MAAMA,MAAM,GAAI,IAAI,CAACH,IAAI,CAA4BG,MAAM;IAC3D,IAAI,CAACA,MAAM,EAAE;MACX,OAAO,IAAI;IACb;IACA,OAAO,IAAIR,WAAW,CAACQ,MAAM,CAAC;EAChC;EAEA,IAAWA,MAAMA,CAACA,MAA0B,EAAE;IAC5C,IAAI,CAACA,MAAM,EAAE;MACV,IAAI,CAACH,IAAI,CAA4BG,MAAM,GAAG,IAAI;MACnD;IACF;IAEC,IAAI,CAACH,IAAI,CAA4BG,MAAM,GAAGA,MAAM,CAACA,MAAM;EAC9D;EAEA,IAAWC,IAAIA,CAAA,EAAY;IACzB,OAAQ,IAAI,CAACJ,IAAI,CAA4BI,IAAI;EACnD;EAEA,IAAWA,IAAIA,CAACC,KAAc,EAAE;IAC7B,IAAI,CAACL,IAAI,CAA4BI,IAAI,GAAGC,KAAK;EACpD;EAEA,IAAWC,SAASA,CAAA,EAAW;IAC7B,OAAQ,IAAI,CAACN,IAAI,CAA4BM,SAAS;EACxD;EAEA,IAAWA,SAASA,CAACD,KAAa,EAAE;IACjC,IAAI,CAACL,IAAI,CAA4BM,SAAS,GAAGD,KAAK;EACzD;EAEA,IAAWE,OAAOA,CAAA,EAAW;IAC3B,OAAQ,IAAI,CAACP,IAAI,CAA4BO,OAAO;EACtD;EAEA,IAAWA,OAAOA,CAACF,KAAa,EAAE;IAC/B,IAAI,CAACL,IAAI,CAA4BO,OAAO,GAAGF,KAAK;EACvD;AACF","ignoreList":[]}
@@ -7,7 +7,6 @@ import AudioBufferSourceNode from './AudioBufferSourceNode';
7
7
  import AudioBuffer from './AudioBuffer';
8
8
  import PeriodicWave from './PeriodicWave';
9
9
  import { InvalidAccessError } from '../errors';
10
- import { resolveAudioSource } from '../utils/resolveAudioSource';
11
10
  export default class BaseAudioContext {
12
11
  constructor(context) {
13
12
  this.context = context;
@@ -54,8 +53,8 @@ export default class BaseAudioContext {
54
53
  const disableNormalization = constraints?.disableNormalization ?? false;
55
54
  return new PeriodicWave(this.context.createPeriodicWave(real, imag, disableNormalization));
56
55
  }
57
- async decodeAudioDataSource(source) {
58
- const buffer = await this.context.decodeAudioDataSource(resolveAudioSource(source));
56
+ async decodeAudioDataSource(sourcePath) {
57
+ const buffer = await this.context.decodeAudioDataSource(sourcePath);
59
58
  return new AudioBuffer(buffer);
60
59
  }
61
60
  }