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