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.
- package/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp +87 -5
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +7 -6
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +25 -24
- package/common/cpp/audioapi/HostObjects/AnalyserNodeHostObject.h +17 -41
- package/common/cpp/audioapi/HostObjects/AudioBufferHostObject.h +25 -34
- package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +2 -17
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +14 -4
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +5 -8
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +38 -9
- package/common/cpp/audioapi/HostObjects/BiquadFilterNodeHostObject.h +8 -19
- package/common/cpp/audioapi/core/AudioContext.cpp +14 -4
- package/common/cpp/audioapi/core/AudioContext.h +2 -2
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +16 -2
- package/common/cpp/audioapi/core/BaseAudioContext.h +2 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +5 -6
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +4 -3
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +5 -11
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +3 -31
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +2 -1
- package/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp +13 -0
- package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +23 -0
- package/ios/audioapi/ios/core/AudioDecoder.mm +45 -1
- package/lib/module/api.js +1 -1
- package/lib/module/api.js.map +1 -1
- package/lib/module/api.web.js +1 -2
- package/lib/module/api.web.js.map +1 -1
- package/lib/module/core/AnalyserNode.js.map +1 -1
- package/lib/module/core/AudioBuffer.js.map +1 -1
- package/lib/module/core/AudioBufferSourceNode.js +0 -6
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/core/AudioParam.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +6 -2
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/core/BiquadFilterNode.js.map +1 -1
- package/lib/module/utils/index.js +6 -0
- package/lib/module/utils/index.js.map +1 -0
- package/lib/module/web-core/AnalyserNode.js +4 -20
- package/lib/module/web-core/AnalyserNode.js.map +1 -1
- package/lib/module/web-core/AudioBuffer.js +2 -6
- package/lib/module/web-core/AudioBuffer.js.map +1 -1
- package/lib/module/web-core/AudioBufferSourceNode.js +161 -21
- package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +10 -8
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/AudioParam.js +1 -1
- package/lib/module/web-core/AudioParam.js.map +1 -1
- package/lib/module/web-core/BiquadFilterNode.js +1 -9
- package/lib/module/web-core/BiquadFilterNode.js.map +1 -1
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +2 -2
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs.map +1 -1
- package/lib/typescript/api.d.ts +1 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/api.web.d.ts +1 -2
- package/lib/typescript/api.web.d.ts.map +1 -1
- package/lib/typescript/core/AnalyserNode.d.ts +4 -4
- package/lib/typescript/core/AnalyserNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioBuffer.d.ts +3 -3
- package/lib/typescript/core/AudioBuffer.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferSourceNode.d.ts +0 -3
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioParam.d.ts +1 -1
- package/lib/typescript/core/AudioParam.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +4 -3
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/BiquadFilterNode.d.ts +1 -1
- package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +13 -13
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +3 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils/index.d.ts +2 -0
- package/lib/typescript/utils/index.d.ts.map +1 -0
- package/lib/typescript/web-core/AnalyserNode.d.ts +4 -4
- package/lib/typescript/web-core/AnalyserNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBuffer.d.ts +2 -2
- package/lib/typescript/web-core/AudioBuffer.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +58 -6
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +4 -5
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioParam.d.ts +1 -1
- package/lib/typescript/web-core/AudioParam.d.ts.map +1 -1
- package/lib/typescript/web-core/BaseAudioContext.d.ts +3 -2
- package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/BiquadFilterNode.d.ts +1 -1
- package/lib/typescript/web-core/BiquadFilterNode.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/api.ts +0 -1
- package/src/api.web.ts +0 -2
- package/src/core/AnalyserNode.ts +4 -4
- package/src/core/AudioBuffer.ts +3 -3
- package/src/core/AudioBufferSourceNode.ts +0 -9
- package/src/core/AudioParam.ts +1 -1
- package/src/core/BaseAudioContext.ts +22 -5
- package/src/core/BiquadFilterNode.ts +3 -3
- package/src/interfaces.ts +15 -16
- package/src/types.ts +3 -1
- package/src/utils/index.ts +3 -0
- package/src/web-core/AnalyserNode.tsx +8 -30
- package/src/web-core/AudioBuffer.tsx +4 -14
- package/src/web-core/AudioBufferSourceNode.tsx +357 -31
- package/src/web-core/AudioContext.tsx +23 -13
- package/src/web-core/AudioParam.tsx +2 -6
- package/src/web-core/BaseAudioContext.tsx +4 -3
- package/src/web-core/BiquadFilterNode.tsx +6 -16
- package/src/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +4 -3
- package/common/cpp/audioapi/core/types/TimeStretchType.h +0 -7
- package/lib/module/web-core/StretcherNode.js +0 -81
- package/lib/module/web-core/StretcherNode.js.map +0 -1
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.js +0 -823
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.js.map +0 -1
- package/lib/typescript/web-core/StretcherNode.d.ts +0 -48
- package/lib/typescript/web-core/StretcherNode.d.ts.map +0 -1
- package/src/web-core/StretcherNode.tsx +0 -145
- 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
|
|
44
|
-
|
|
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
|
-
|
|
34
|
-
|
|
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(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
77
|
-
auto
|
|
78
|
-
auto
|
|
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
|
|
94
|
-
auto
|
|
95
|
-
auto
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
113
|
+
auto analyserNode = std::static_pointer_cast<AnalyserNode>(node_);
|
|
114
|
+
analyserNode->getByteTimeDomainData(data, length);
|
|
139
115
|
|
|
140
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
auto
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
63
|
-
auto
|
|
64
|
-
|
|
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
|
-
|
|
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
|
|
84
|
-
auto
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
83
|
-
auto
|
|
84
|
-
auto
|
|
85
|
-
|
|
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(
|
|
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
|
|
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
|
|
115
|
-
auto
|
|
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 <
|
|
127
|
+
for (size_t i = 0; i < length; i++) {
|
|
123
128
|
complexData[i] = std::complex<float>(
|
|
124
|
-
static_cast<float>(real
|
|
125
|
-
static_cast<float>(imag
|
|
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
|
|
68
|
-
auto
|
|
69
|
-
auto
|
|
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
|
-
|
|
72
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)>
|