react-native-audio-api 0.4.13 → 0.5.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 (115) hide show
  1. package/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp +87 -5
  2. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +7 -6
  3. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +25 -24
  4. package/common/cpp/audioapi/HostObjects/AnalyserNodeHostObject.h +17 -41
  5. package/common/cpp/audioapi/HostObjects/AudioBufferHostObject.h +25 -34
  6. package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +2 -17
  7. package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +14 -4
  8. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +5 -8
  9. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +38 -9
  10. package/common/cpp/audioapi/HostObjects/BiquadFilterNodeHostObject.h +8 -19
  11. package/common/cpp/audioapi/core/AudioContext.cpp +14 -4
  12. package/common/cpp/audioapi/core/AudioContext.h +2 -2
  13. package/common/cpp/audioapi/core/BaseAudioContext.cpp +16 -2
  14. package/common/cpp/audioapi/core/BaseAudioContext.h +2 -1
  15. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +5 -6
  16. package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +4 -3
  17. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +5 -11
  18. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +3 -31
  19. package/common/cpp/audioapi/core/utils/AudioDecoder.h +2 -1
  20. package/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp +13 -0
  21. package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +23 -0
  22. package/ios/audioapi/ios/core/AudioDecoder.mm +45 -1
  23. package/lib/module/api.js +1 -1
  24. package/lib/module/api.js.map +1 -1
  25. package/lib/module/api.web.js +1 -2
  26. package/lib/module/api.web.js.map +1 -1
  27. package/lib/module/core/AnalyserNode.js.map +1 -1
  28. package/lib/module/core/AudioBuffer.js.map +1 -1
  29. package/lib/module/core/AudioBufferSourceNode.js +0 -6
  30. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  31. package/lib/module/core/AudioParam.js.map +1 -1
  32. package/lib/module/core/BaseAudioContext.js +6 -2
  33. package/lib/module/core/BaseAudioContext.js.map +1 -1
  34. package/lib/module/core/BiquadFilterNode.js.map +1 -1
  35. package/lib/module/utils/index.js +6 -0
  36. package/lib/module/utils/index.js.map +1 -0
  37. package/lib/module/web-core/AnalyserNode.js +4 -20
  38. package/lib/module/web-core/AnalyserNode.js.map +1 -1
  39. package/lib/module/web-core/AudioBuffer.js +2 -6
  40. package/lib/module/web-core/AudioBuffer.js.map +1 -1
  41. package/lib/module/web-core/AudioBufferSourceNode.js +161 -21
  42. package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -1
  43. package/lib/module/web-core/AudioContext.js +10 -8
  44. package/lib/module/web-core/AudioContext.js.map +1 -1
  45. package/lib/module/web-core/AudioParam.js +1 -1
  46. package/lib/module/web-core/AudioParam.js.map +1 -1
  47. package/lib/module/web-core/BiquadFilterNode.js +1 -9
  48. package/lib/module/web-core/BiquadFilterNode.js.map +1 -1
  49. package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +2 -2
  50. package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs.map +1 -1
  51. package/lib/typescript/api.d.ts +1 -1
  52. package/lib/typescript/api.d.ts.map +1 -1
  53. package/lib/typescript/api.web.d.ts +1 -2
  54. package/lib/typescript/api.web.d.ts.map +1 -1
  55. package/lib/typescript/core/AnalyserNode.d.ts +4 -4
  56. package/lib/typescript/core/AnalyserNode.d.ts.map +1 -1
  57. package/lib/typescript/core/AudioBuffer.d.ts +3 -3
  58. package/lib/typescript/core/AudioBuffer.d.ts.map +1 -1
  59. package/lib/typescript/core/AudioBufferSourceNode.d.ts +0 -3
  60. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
  61. package/lib/typescript/core/AudioParam.d.ts +1 -1
  62. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  63. package/lib/typescript/core/BaseAudioContext.d.ts +4 -3
  64. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  65. package/lib/typescript/core/BiquadFilterNode.d.ts +1 -1
  66. package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -1
  67. package/lib/typescript/interfaces.d.ts +13 -13
  68. package/lib/typescript/interfaces.d.ts.map +1 -1
  69. package/lib/typescript/types.d.ts +3 -1
  70. package/lib/typescript/types.d.ts.map +1 -1
  71. package/lib/typescript/utils/index.d.ts +2 -0
  72. package/lib/typescript/utils/index.d.ts.map +1 -0
  73. package/lib/typescript/web-core/AnalyserNode.d.ts +4 -4
  74. package/lib/typescript/web-core/AnalyserNode.d.ts.map +1 -1
  75. package/lib/typescript/web-core/AudioBuffer.d.ts +2 -2
  76. package/lib/typescript/web-core/AudioBuffer.d.ts.map +1 -1
  77. package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +58 -6
  78. package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -1
  79. package/lib/typescript/web-core/AudioContext.d.ts +4 -5
  80. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  81. package/lib/typescript/web-core/AudioParam.d.ts +1 -1
  82. package/lib/typescript/web-core/AudioParam.d.ts.map +1 -1
  83. package/lib/typescript/web-core/BaseAudioContext.d.ts +3 -2
  84. package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
  85. package/lib/typescript/web-core/BiquadFilterNode.d.ts +1 -1
  86. package/lib/typescript/web-core/BiquadFilterNode.d.ts.map +1 -1
  87. package/package.json +6 -6
  88. package/src/api.ts +0 -1
  89. package/src/api.web.ts +0 -2
  90. package/src/core/AnalyserNode.ts +4 -4
  91. package/src/core/AudioBuffer.ts +3 -3
  92. package/src/core/AudioBufferSourceNode.ts +0 -9
  93. package/src/core/AudioParam.ts +1 -1
  94. package/src/core/BaseAudioContext.ts +22 -5
  95. package/src/core/BiquadFilterNode.ts +3 -3
  96. package/src/interfaces.ts +15 -16
  97. package/src/types.ts +3 -1
  98. package/src/utils/index.ts +3 -0
  99. package/src/web-core/AnalyserNode.tsx +8 -30
  100. package/src/web-core/AudioBuffer.tsx +4 -14
  101. package/src/web-core/AudioBufferSourceNode.tsx +357 -31
  102. package/src/web-core/AudioContext.tsx +23 -13
  103. package/src/web-core/AudioParam.tsx +2 -6
  104. package/src/web-core/BaseAudioContext.tsx +4 -3
  105. package/src/web-core/BiquadFilterNode.tsx +6 -16
  106. package/src/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +4 -3
  107. package/common/cpp/audioapi/core/types/TimeStretchType.h +0 -7
  108. package/lib/module/web-core/StretcherNode.js +0 -81
  109. package/lib/module/web-core/StretcherNode.js.map +0 -1
  110. package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.js +0 -823
  111. package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.js.map +0 -1
  112. package/lib/typescript/web-core/StretcherNode.d.ts +0 -48
  113. package/lib/typescript/web-core/StretcherNode.d.ts.map +0 -1
  114. package/src/web-core/StretcherNode.tsx +0 -145
  115. package/src/web-core/custom/signalsmithStretch/SignalsmithStretch.js +0 -946
@@ -2,18 +2,18 @@
2
2
  #include <audioapi/utils/AudioArray.h>
3
3
  #include <audioapi/utils/AudioBus.h>
4
4
 
5
- #include <android/log.h>
6
-
7
5
  #define MINIAUDIO_IMPLEMENTATION
8
6
  #include <audioapi/libs/miniaudio/miniaudio.h>
9
7
 
8
+ #include <android/log.h>
9
+
10
10
  namespace audioapi {
11
11
 
12
12
  std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
13
13
  const std::string &path) const {
14
14
  ma_decoder decoder;
15
15
  ma_decoder_config config =
16
- ma_decoder_config_init(ma_format_f32, 2, sampleRate_);
16
+ ma_decoder_config_init(ma_format_f32, 2, static_cast<int>(sampleRate_));
17
17
  ma_result result = ma_decoder_init_file(path.c_str(), &config, &decoder);
18
18
  if (result != MA_SUCCESS) {
19
19
  __android_log_print(
@@ -37,11 +37,57 @@ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
37
37
  ma_uint64 framesDecoded;
38
38
  ma_decoder_read_pcm_frames(&decoder, buffer, totalFrameCount, &framesDecoded);
39
39
  if (framesDecoded == 0) {
40
+ __android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
41
+
42
+ delete[] buffer;
43
+ ma_decoder_uninit(&decoder);
44
+
45
+ return nullptr;
46
+ }
47
+
48
+ for (int i = 0; i < decoder.outputChannels; ++i) {
49
+ auto channelData = audioBus->getChannel(i)->getData();
50
+
51
+ for (ma_uint64 j = 0; j < framesDecoded; ++j) {
52
+ channelData[j] = buffer[j * decoder.outputChannels + i];
53
+ }
54
+ }
55
+
56
+ delete[] buffer;
57
+ ma_decoder_uninit(&decoder);
58
+
59
+ return audioBus;
60
+ }
61
+
62
+ std::shared_ptr<AudioBus> AudioDecoder::decodeWithMemoryBlock(
63
+ const void *data,
64
+ size_t size) const {
65
+ ma_decoder decoder;
66
+ ma_decoder_config config =
67
+ ma_decoder_config_init(ma_format_f32, 2, static_cast<int>(sampleRate_));
68
+ ma_result result = ma_decoder_init_memory(data, size, &config, &decoder);
69
+ if (result != MA_SUCCESS) {
40
70
  __android_log_print(
41
71
  ANDROID_LOG_ERROR,
42
72
  "AudioDecoder",
43
- "Failed to decode audio file: %s",
44
- path.c_str());
73
+ "Failed to initialize decoder for memory block");
74
+
75
+ ma_decoder_uninit(&decoder);
76
+
77
+ return nullptr;
78
+ }
79
+
80
+ ma_uint64 totalFrameCount;
81
+ ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
82
+
83
+ auto audioBus = std::make_shared<AudioBus>(
84
+ static_cast<int>(totalFrameCount), 2, sampleRate_);
85
+ auto *buffer = new float[totalFrameCount * 2];
86
+
87
+ ma_uint64 framesDecoded;
88
+ ma_decoder_read_pcm_frames(&decoder, buffer, totalFrameCount, &framesDecoded);
89
+ if (framesDecoded == 0) {
90
+ __android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
45
91
 
46
92
  delete[] buffer;
47
93
  ma_decoder_uninit(&decoder);
@@ -62,4 +108,40 @@ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
62
108
 
63
109
  return audioBus;
64
110
  }
111
+
112
+ // std::shared_ptr<AudioBus> AudioDecoder::decode(ma_decoder &decoder) const {
113
+ // ma_uint64 totalFrameCount;
114
+ // ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
115
+ //
116
+ // auto audioBus = std::make_shared<AudioBus>(
117
+ // static_cast<int>(totalFrameCount), 2, sampleRate_);
118
+ // auto *buffer = new float[totalFrameCount * 2];
119
+ //
120
+ // ma_uint64 framesDecoded;
121
+ // ma_decoder_read_pcm_frames(&decoder, buffer, totalFrameCount,
122
+ // &framesDecoded); if (framesDecoded == 0) {
123
+ // __android_log_print(
124
+ // ANDROID_LOG_ERROR,
125
+ // "AudioDecoder",
126
+ // "Failed to decode");
127
+ //
128
+ // delete[] buffer;
129
+ // ma_decoder_uninit(&decoder);
130
+ //
131
+ // return nullptr;
132
+ // }
133
+ //
134
+ // for (int i = 0; i < decoder.outputChannels; ++i) {
135
+ // auto channelData = audioBus->getChannel(i)->getData();
136
+ //
137
+ // for (ma_uint64 j = 0; j < framesDecoded; ++j) {
138
+ // channelData[j] = buffer[j * decoder.outputChannels + i];
139
+ // }
140
+ // }
141
+ //
142
+ // delete[] buffer;
143
+ // ma_decoder_uninit(&decoder);
144
+ //
145
+ // return audioBus;
146
+ // }
65
147
  } // namespace audioapi
@@ -13,10 +13,6 @@ class AudioAPIModule(
13
13
  reactContext: ReactApplicationContext,
14
14
  ) : NativeAudioAPIModuleSpec(reactContext) {
15
15
  companion object {
16
- init {
17
- System.loadLibrary("react-native-audio-api")
18
- }
19
-
20
16
  const val NAME = NativeAudioAPIModuleSpec.NAME
21
17
  }
22
18
 
@@ -30,8 +26,13 @@ class AudioAPIModule(
30
26
  private external fun injectJSIBindings()
31
27
 
32
28
  init {
33
- val jsCallInvokerHolder = reactContext.jsCallInvokerHolder as CallInvokerHolderImpl
34
- mHybridData = initHybrid(reactContext.javaScriptContextHolder!!.get(), jsCallInvokerHolder)
29
+ try {
30
+ System.loadLibrary("react-native-audio-api")
31
+ val jsCallInvokerHolder = reactContext.jsCallInvokerHolder as CallInvokerHolderImpl
32
+ mHybridData = initHybrid(reactContext.javaScriptContextHolder!!.get(), jsCallInvokerHolder)
33
+ } catch (exception: UnsatisfiedLinkError) {
34
+ throw RuntimeException("Could not load native module AudioAPIModule", exception)
35
+ }
35
36
  }
36
37
 
37
38
  @ReactMethod(isBlockingSynchronousMethod = true)
@@ -1,41 +1,42 @@
1
1
  package com.swmansion.audioapi
2
2
 
3
3
  import com.facebook.react.BaseReactPackage
4
- import com.facebook.react.ReactPackage
5
4
  import com.facebook.react.bridge.NativeModule
6
5
  import com.facebook.react.bridge.ReactApplicationContext
7
- import com.facebook.react.common.annotations.UnstableReactNativeAPI
8
6
  import com.facebook.react.module.annotations.ReactModuleList
9
7
  import com.facebook.react.module.model.ReactModuleInfo
10
8
  import com.facebook.react.module.model.ReactModuleInfoProvider
11
9
 
12
- @ReactModuleList(nativeModules = [AudioAPIModule::class])
13
- class AudioAPIPackage :
14
- BaseReactPackage(),
15
- ReactPackage {
16
- @UnstableReactNativeAPI
10
+ @ReactModuleList(
11
+ nativeModules = [
12
+ AudioAPIModule::class,
13
+ ],
14
+ )
15
+ class AudioAPIPackage : BaseReactPackage() {
17
16
  override fun getModule(
18
17
  name: String,
19
18
  reactContext: ReactApplicationContext,
20
- ): NativeModule? =
19
+ ): NativeModule? {
21
20
  when (name) {
22
- AudioAPIModule.NAME -> AudioAPIModule(reactContext)
23
- else -> null
21
+ AudioAPIModule.NAME -> return AudioAPIModule(reactContext)
24
22
  }
23
+ return null
24
+ }
25
25
 
26
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
- )
27
+ ReactModuleInfoProvider {
28
+ val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
29
+ val isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
30
+ moduleInfos[AudioAPIModule.NAME] =
31
+ ReactModuleInfo(
32
+ AudioAPIModule.NAME,
33
+ AudioAPIModule.NAME,
34
+ canOverrideExistingModule = true,
35
+ needsEagerInit = false,
36
+ hasConstants = true,
37
+ isCxxModule = false,
38
+ isTurboModule = isTurboModule,
39
+ )
40
+ moduleInfos
41
+ }
41
42
  }
@@ -73,71 +73,47 @@ class AnalyserNodeHostObject : public AudioNodeHostObject {
73
73
  }
74
74
 
75
75
  JSI_HOST_FUNCTION(getFloatFrequencyData) {
76
- auto destination = args[0].getObject(runtime).asArray(runtime);
77
- auto length = static_cast<int>(destination.getProperty(runtime, "length").asNumber());
78
- auto data = new float[length];
76
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
77
+ auto data = reinterpret_cast<float *>(arrayBuffer.data(runtime));
78
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
79
79
 
80
80
  auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
81
81
  analyserNode->getFloatFrequencyData(data, length);
82
82
 
83
- for (int i = 0; i < length; i++) {
84
- destination.setValueAtIndex(runtime, i, jsi::Value(data[i]));
85
- }
86
-
87
- delete[] data;
88
-
89
83
  return jsi::Value::undefined();
90
84
  }
91
85
 
92
86
  JSI_HOST_FUNCTION(getByteFrequencyData) {
93
- auto destination = args[0].getObject(runtime).asArray(runtime);
94
- auto length = static_cast<int>(destination.getProperty(runtime, "length").asNumber());
95
- auto data = new uint8_t[length];
87
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
88
+ auto data = arrayBuffer.data(runtime);
89
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
96
90
 
97
91
  auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
98
92
  analyserNode->getByteFrequencyData(data, length);
99
93
 
100
- for (int i = 0; i < length; i++) {
101
- destination.setValueAtIndex(runtime, i, jsi::Value(data[i]));
102
- }
103
-
104
- delete[] data;
105
-
106
94
  return jsi::Value::undefined();
107
95
  }
108
96
 
109
97
  JSI_HOST_FUNCTION(getFloatTimeDomainData) {
110
- auto destination = args[0].getObject(runtime).asArray(runtime);
111
- auto length = static_cast<int>(destination.getProperty(runtime, "length").asNumber());
112
- auto data = new float[length];
113
-
114
- auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
115
- analyserNode->getFloatTimeDomainData(data, length);
116
-
117
- for (int i = 0; i < length; i++) {
118
- destination.setValueAtIndex(runtime, i, jsi::Value(data[i]));
119
- }
98
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
99
+ auto data = reinterpret_cast<float *>(arrayBuffer.data(runtime));
100
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
120
101
 
121
- delete[] data;
102
+ auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
103
+ analyserNode->getFloatTimeDomainData(data, length);
122
104
 
123
105
  return jsi::Value::undefined();
124
106
  }
125
107
 
126
108
  JSI_HOST_FUNCTION(getByteTimeDomainData) {
127
- auto destination = args[0].getObject(runtime).asArray(runtime);
128
- auto length = static_cast<int>(destination.getProperty(runtime, "length").asNumber());
129
- auto data = new uint8_t[length];
130
-
131
- auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
132
- analyserNode->getByteTimeDomainData(data, length);
133
-
134
- for (int i = 0; i < length; i++) {
135
- destination.setValueAtIndex(runtime, i, jsi::Value(data[i]));
136
- }
109
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
110
+ auto data = arrayBuffer.data(runtime);
111
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
137
112
 
138
- delete[] data;
113
+ auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
114
+ analyserNode->getByteTimeDomainData(data, length);
139
115
 
140
- return jsi::Value::undefined();
116
+ return jsi::Value::undefined();
141
117
  }
142
118
 
143
119
  JSI_PROPERTY_SETTER(fftSize) {
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
 
3
3
  #include <audioapi/jsi/JsiHostObject.h>
4
+ #include <audioapi/jsi/AudioArrayBuffer.h>
4
5
  #include <audioapi/core/sources/AudioBuffer.h>
5
6
 
6
7
  #include <jsi/jsi.h>
@@ -47,56 +48,46 @@ class AudioBufferHostObject : public JsiHostObject {
47
48
  }
48
49
 
49
50
  JSI_HOST_FUNCTION(getChannelData) {
50
- int channel = static_cast<int>(args[0].getNumber());
51
- float *channelData = audioBuffer_->getChannelData(channel);
52
-
53
- auto array = jsi::Array(runtime, audioBuffer_->getLength());
54
- for (int i = 0; i < audioBuffer_->getLength(); i++) {
55
- array.setValueAtIndex(runtime, i, jsi::Value(channelData[i]));
56
- }
57
-
58
- return array;
51
+ // this method could cause a crash if channelData is already deallocated,
52
+ // but we handle deallocation internally so it should be safe
53
+ auto channel = static_cast<int>(args[0].getNumber());
54
+ auto channelData = reinterpret_cast<uint8_t *>(audioBuffer_->getChannelData(channel));
55
+ auto length = static_cast<int>(audioBuffer_->getLength());
56
+ auto size = static_cast<int>(length * sizeof(float));
57
+
58
+ // reading or writing from this ArrayBuffer could cause a crash
59
+ // if underlying channelData is deallocated
60
+ auto audioArrayBuffer = std::make_shared<AudioArrayBuffer>(channelData, size);
61
+ auto arrayBuffer = jsi::ArrayBuffer(runtime, audioArrayBuffer);
62
+
63
+ auto float32ArrayCtor = runtime.global().getPropertyAsFunction(runtime, "Float32Array");
64
+ auto float32Array = float32ArrayCtor.callAsConstructor(runtime, arrayBuffer).getObject(runtime);
65
+
66
+ return float32Array;
59
67
  }
60
68
 
61
69
  JSI_HOST_FUNCTION(copyFromChannel) {
62
- auto destination = args[0].getObject(runtime).asArray(runtime);
63
- auto destinationLength =
64
- static_cast<size_t>(destination.getProperty(runtime, "length").asNumber());
70
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
71
+ auto destination = reinterpret_cast<float *>(arrayBuffer.data(runtime));
72
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
65
73
  auto channelNumber = static_cast<int>(args[1].getNumber());
66
74
  auto startInChannel = static_cast<size_t>(args[2].getNumber());
67
75
 
68
- auto *destinationData = new float[destinationLength];
69
-
70
76
  audioBuffer_->copyFromChannel(
71
- destinationData, destinationLength, channelNumber, startInChannel);
72
-
73
- for (int i = 0; i < destinationLength; i++) {
74
- destination.setValueAtIndex(runtime, i, jsi::Value(destinationData[i]));
75
- }
76
-
77
- delete[] destinationData;
77
+ destination, length, channelNumber, startInChannel);
78
78
 
79
79
  return jsi::Value::undefined();
80
80
  }
81
81
 
82
82
  JSI_HOST_FUNCTION(copyToChannel) {
83
- auto source = args[0].getObject(runtime).asArray(runtime);
84
- auto sourceLength =
85
- static_cast<size_t>(source.getProperty(runtime, "length").asNumber());
83
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
84
+ auto source = reinterpret_cast<float *>(arrayBuffer.data(runtime));
85
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
86
86
  auto channelNumber = static_cast<int>(args[1].getNumber());
87
87
  auto startInChannel = static_cast<size_t>(args[2].getNumber());
88
88
 
89
- auto *sourceData = new float[sourceLength];
90
-
91
- for (int i = 0; i < sourceLength; i++) {
92
- sourceData[i] =
93
- static_cast<float>(source.getValueAtIndex(runtime, i).getNumber());
94
- }
95
-
96
89
  audioBuffer_->copyToChannel(
97
- sourceData, sourceLength, channelNumber, startInChannel);
98
-
99
- delete[] sourceData;
90
+ source, length, channelNumber, startInChannel);
100
91
 
101
92
  return jsi::Value::undefined();
102
93
  }
@@ -24,15 +24,13 @@ class AudioBufferSourceNodeHostObject
24
24
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, loopStart),
25
25
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, loopEnd),
26
26
  JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, detune),
27
- JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, playbackRate),
28
- JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, timeStretch));
27
+ JSI_EXPORT_PROPERTY_GETTER(AudioBufferSourceNodeHostObject, playbackRate));
29
28
 
30
29
  addSetters(
31
30
  JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, loop),
32
31
  JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, buffer),
33
32
  JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, loopStart),
34
- JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, loopEnd),
35
- JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, timeStretch));
33
+ JSI_EXPORT_PROPERTY_SETTER(AudioBufferSourceNodeHostObject, loopEnd));
36
34
 
37
35
  // start method is overridden in this class
38
36
  functions_->erase("start");
@@ -92,13 +90,6 @@ class AudioBufferSourceNodeHostObject
92
90
  return jsi::Object::createFromHostObject(runtime, playbackRateHostObject);
93
91
  }
94
92
 
95
- JSI_PROPERTY_GETTER(timeStretch) {
96
- auto audioBufferSourceNode =
97
- std::static_pointer_cast<AudioBufferSourceNode>(node_);
98
- auto timeStretch = audioBufferSourceNode->getTimeStretchType();
99
- return jsi::String::createFromUtf8(runtime, timeStretch);
100
- }
101
-
102
93
  JSI_PROPERTY_SETTER(loop) {
103
94
  auto audioBufferSourceNode =
104
95
  std::static_pointer_cast<AudioBufferSourceNode>(node_);
@@ -130,12 +121,6 @@ class AudioBufferSourceNodeHostObject
130
121
  audioBufferSourceNode->setLoopEnd(value.getNumber());
131
122
  }
132
123
 
133
- JSI_PROPERTY_SETTER(timeStretch) {
134
- auto audioBufferSourceNode =
135
- std::static_pointer_cast<AudioBufferSourceNode>(node_);
136
- audioBufferSourceNode->setTimeStretchType(value.getString(runtime).utf8(runtime));
137
- }
138
-
139
124
  JSI_HOST_FUNCTION(start) {
140
125
  auto when = args[0].getNumber();
141
126
  auto offset = args[1].getNumber();
@@ -43,10 +43,15 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
43
43
  auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
44
44
  std::thread([this, promise = std::move(promise)]() {
45
45
  auto audioContext = std::static_pointer_cast<AudioContext>(context_);
46
- audioContext->resume();
46
+ auto result = audioContext->resume();
47
+
48
+ if (!result) {
49
+ promise->reject("Failed to resume audio context, because it is already closed.");
50
+ return;
51
+ }
47
52
 
48
53
  promise->resolve([](jsi::Runtime &runtime) {
49
- return jsi::Value::undefined();
54
+ return jsi::Value::undefined();
50
55
  });
51
56
  }).detach();
52
57
  });
@@ -58,10 +63,15 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
58
63
  auto promise = promiseVendor_->createPromise([this](std::shared_ptr<Promise> promise) {
59
64
  std::thread([this, promise = std::move(promise)]() {
60
65
  auto audioContext = std::static_pointer_cast<AudioContext>(context_);
61
- audioContext->suspend();
66
+ auto result = audioContext->suspend();
67
+
68
+ if (!result) {
69
+ promise->reject("Failed to resume audio context, because it is already closed.");
70
+ return;
71
+ }
62
72
 
63
73
  promise->resolve([](jsi::Runtime &runtime) {
64
- return jsi::Value::undefined();
74
+ return jsi::Value::undefined();
65
75
  });
66
76
  }).detach();
67
77
  });
@@ -79,16 +79,13 @@ class AudioParamHostObject : public JsiHostObject {
79
79
  }
80
80
 
81
81
  JSI_HOST_FUNCTION(setValueCurveAtTime) {
82
- auto values = args[0].getObject(runtime).asArray(runtime);
83
- auto length = static_cast<size_t>(values.length(runtime));
84
- auto valuesData = new float[length];
85
- for (size_t i = 0; i < values.length(runtime); i++) {
86
- valuesData[i] =
87
- static_cast<float>(values.getValueAtIndex(runtime, i).getNumber());
88
- }
82
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
83
+ auto values = reinterpret_cast<float *>(arrayBuffer.data(runtime));
84
+ auto length = static_cast<int>(arrayBuffer.size(runtime));
85
+
89
86
  double startTime = args[1].getNumber();
90
87
  double duration = args[2].getNumber();
91
- param_->setValueCurveAtTime(valuesData, length, startTime, duration);
88
+ param_->setValueCurveAtTime(values, length, startTime, duration);
92
89
  return jsi::Value::undefined();
93
90
  }
94
91
 
@@ -46,6 +46,7 @@ class BaseAudioContextHostObject : public JsiHostObject {
46
46
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBuffer),
47
47
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createPeriodicWave),
48
48
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createAnalyser),
49
+ JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, decodeAudioData),
49
50
  JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, decodeAudioDataSource));
50
51
  }
51
52
 
@@ -95,7 +96,8 @@ class BaseAudioContextHostObject : public JsiHostObject {
95
96
  }
96
97
 
97
98
  JSI_HOST_FUNCTION(createBufferSource) {
98
- auto bufferSource = context_->createBufferSource();
99
+ auto pitchCorrection = args[0].asBool();
100
+ auto bufferSource = context_->createBufferSource(pitchCorrection);
99
101
  auto bufferSourceHostObject =
100
102
  std::make_shared<AudioBufferSourceNodeHostObject>(bufferSource, callInvoker_);
101
103
  return jsi::Object::createFromHostObject(runtime, bufferSourceHostObject);
@@ -111,18 +113,21 @@ class BaseAudioContextHostObject : public JsiHostObject {
111
113
  }
112
114
 
113
115
  JSI_HOST_FUNCTION(createPeriodicWave) {
114
- auto real = args[0].getObject(runtime).getArray(runtime);
115
- auto imag = args[1].getObject(runtime).getArray(runtime);
116
+ auto arrayBufferReal = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
117
+ auto real = reinterpret_cast<float *>(arrayBufferReal.data(runtime));
118
+ auto length = static_cast<int>(arrayBufferReal.size(runtime));
119
+
120
+ auto arrayBufferImag = args[1].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
121
+ auto imag = reinterpret_cast<float *>(arrayBufferReal.data(runtime));
122
+
116
123
  auto disableNormalization = args[2].getBool();
117
- auto length =
118
- static_cast<int>(real.getProperty(runtime, "length").asNumber());
119
124
 
120
125
  auto complexData = std::vector<std::complex<float>>(length);
121
126
 
122
- for (size_t i = 0; i < real.length(runtime); i++) {
127
+ for (size_t i = 0; i < length; i++) {
123
128
  complexData[i] = std::complex<float>(
124
- static_cast<float>(real.getValueAtIndex(runtime, i).getNumber()),
125
- static_cast<float>(imag.getValueAtIndex(runtime, i).getNumber()));
129
+ static_cast<float>(real[i]),
130
+ static_cast<float>(imag[i]));
126
131
  }
127
132
 
128
133
  auto periodicWave = context_->createPeriodicWave(
@@ -148,7 +153,7 @@ class BaseAudioContextHostObject : public JsiHostObject {
148
153
  auto audioBufferHostObject = std::make_shared<AudioBufferHostObject>(results);
149
154
 
150
155
  if (!results) {
151
- promise->reject("Failed to decode audio data source");
156
+ promise->reject("Failed to decode audio data source.");
152
157
  return;
153
158
  }
154
159
 
@@ -161,6 +166,30 @@ class BaseAudioContextHostObject : public JsiHostObject {
161
166
  return promise;
162
167
  }
163
168
 
169
+ JSI_HOST_FUNCTION(decodeAudioData) {
170
+ auto arrayBuffer = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
171
+ auto data = arrayBuffer.data(runtime);
172
+ auto size = static_cast<int>(arrayBuffer.size(runtime));
173
+
174
+ auto promise = promiseVendor_->createPromise([this, data, size](std::shared_ptr<Promise> promise) {
175
+ std::thread([this, data, size, promise = std::move(promise)]() {
176
+ auto results = context_->decodeAudioData(data, size);
177
+ auto audioBufferHostObject = std::make_shared<AudioBufferHostObject>(results);
178
+
179
+ if (!results) {
180
+ promise->reject("Failed to decode audio data source.");
181
+ return;
182
+ }
183
+
184
+ promise->resolve([audioBufferHostObject = std::move(audioBufferHostObject)](jsi::Runtime &runtime) {
185
+ return jsi::Object::createFromHostObject(runtime, audioBufferHostObject);
186
+ });
187
+ }).detach();
188
+ });
189
+
190
+ return promise;
191
+ }
192
+
164
193
  protected:
165
194
  std::shared_ptr<BaseAudioContext> context_;
166
195
  std::shared_ptr<PromiseVendor> promiseVendor_;
@@ -64,30 +64,19 @@ class BiquadFilterNodeHostObject : public AudioNodeHostObject {
64
64
  }
65
65
 
66
66
  JSI_HOST_FUNCTION(getFrequencyResponse) {
67
- auto frequencyArray = args[0].getObject(runtime).asArray(runtime);
68
- auto magResponseOut = args[1].getObject(runtime).asArray(runtime);
69
- auto phaseResponseOut = args[2].getObject(runtime).asArray(runtime);
67
+ auto arrayBufferFrequency = args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
68
+ auto frequencyArray = reinterpret_cast<float *>(arrayBufferFrequency.data(runtime));
69
+ auto length = static_cast<int>(arrayBufferFrequency.size(runtime));
70
70
 
71
- std::vector<float> frequencyArrayVector(frequencyArray.length(runtime));
72
- for (size_t i = 0; i < frequencyArray.length(runtime); i++) {
73
- frequencyArrayVector[i] = static_cast<float>(
74
- frequencyArray.getValueAtIndex(runtime, i).getNumber());
75
- }
71
+ auto arrayBufferMag = args[1].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
72
+ auto magResponseOut = reinterpret_cast<float *>(arrayBufferMag.data(runtime));
76
73
 
77
- std::vector<float> magResponseOutVector(magResponseOut.length(runtime));
78
- std::vector<float> phaseResponseOutVector(phaseResponseOut.length(runtime));
74
+ auto arrayBufferPhase = args[2].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
75
+ auto phaseResponseOut = reinterpret_cast<float *>(arrayBufferPhase.data(runtime));
79
76
 
80
77
  auto biquadFilterNode = std::static_pointer_cast<BiquadFilterNode>(node_);
81
78
  biquadFilterNode->getFrequencyResponse(
82
- frequencyArrayVector, magResponseOutVector, phaseResponseOutVector);
83
-
84
- for (size_t i = 0; i < magResponseOutVector.size(); i++) {
85
- magResponseOut.setValueAtIndex(runtime, i, magResponseOutVector[i]);
86
- }
87
-
88
- for (size_t i = 0; i < phaseResponseOutVector.size(); i++) {
89
- phaseResponseOut.setValueAtIndex(runtime, i, phaseResponseOutVector[i]);
90
- }
79
+ frequencyArray, magResponseOut, phaseResponseOut, length);
91
80
 
92
81
  return jsi::Value::undefined();
93
82
  }
@@ -39,23 +39,33 @@ AudioContext::~AudioContext() {
39
39
  if (!isClosed()) {
40
40
  close();
41
41
  }
42
-
43
- nodeManager_->cleanup();
44
42
  }
45
43
 
46
44
  void AudioContext::close() {
47
45
  state_ = ContextState::CLOSED;
48
46
  audioPlayer_->stop();
47
+
48
+ nodeManager_->cleanup();
49
49
  }
50
50
 
51
- void AudioContext::resume() {
51
+ bool AudioContext::resume() {
52
+ if (isClosed()) {
53
+ return false;
54
+ }
55
+
52
56
  state_ = ContextState::RUNNING;
53
57
  audioPlayer_->resume();
58
+ return true;
54
59
  }
55
60
 
56
- void AudioContext::suspend() {
61
+ bool AudioContext::suspend() {
62
+ if (isClosed()) {
63
+ return false;
64
+ }
65
+
57
66
  state_ = ContextState::SUSPENDED;
58
67
  audioPlayer_->suspend();
68
+ return true;
59
69
  }
60
70
 
61
71
  std::function<void(std::shared_ptr<AudioBus>, int)>