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