react-native-audio-api 0.4.10-rc.1 → 0.4.11
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 +15 -3
- package/android/src/main/cpp/core/AudioPlayer.h +6 -3
- 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/AudioContextHostObject.h +34 -1
- 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/AudioContext.cpp +14 -3
- package/common/cpp/core/AudioContext.h +3 -1
- package/common/cpp/core/AudioDecoder.h +2 -1
- package/common/cpp/core/AudioDestinationNode.cpp +3 -3
- package/common/cpp/core/AudioDestinationNode.h +3 -3
- package/common/cpp/core/AudioNode.cpp +16 -11
- package/common/cpp/core/AudioNode.h +6 -6
- package/common/cpp/core/AudioScheduledSourceNode.cpp +1 -1
- package/common/cpp/core/AudioScheduledSourceNode.h +1 -1
- 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/installer/AudioAPIModuleInstaller.cpp +49 -0
- package/common/cpp/installer/AudioAPIModuleInstaller.h +49 -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 +85 -24
- package/ios/core/IOSAudioPlayer.h +6 -4
- package/ios/core/IOSAudioPlayer.mm +14 -7
- package/lib/module/core/AudioContext.js +7 -1
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/index.js +11 -3
- package/lib/module/index.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/index.d.ts +4 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +6 -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/index.ts +16 -3
- package/src/interfaces.ts +7 -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];
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
namespace audioapi {
|
|
10
10
|
|
|
11
11
|
AudioPlayer::AudioPlayer(
|
|
12
|
-
const std::function<void(AudioBus
|
|
12
|
+
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio)
|
|
13
13
|
: renderAudio_(renderAudio) {
|
|
14
14
|
AudioStreamBuilder builder;
|
|
15
15
|
|
|
@@ -29,7 +29,7 @@ AudioPlayer::AudioPlayer(
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
AudioPlayer::AudioPlayer(
|
|
32
|
-
const std::function<void(AudioBus
|
|
32
|
+
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
|
|
33
33
|
float sampleRate)
|
|
34
34
|
: renderAudio_(renderAudio) {
|
|
35
35
|
AudioStreamBuilder builder;
|
|
@@ -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,
|
|
@@ -86,7 +98,7 @@ DataCallbackResult AudioPlayer::onAudioReady(
|
|
|
86
98
|
while (processedFrames < numFrames) {
|
|
87
99
|
int framesToProcess =
|
|
88
100
|
std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
|
|
89
|
-
renderAudio_(mBus_
|
|
101
|
+
renderAudio_(mBus_, framesToProcess);
|
|
90
102
|
|
|
91
103
|
// TODO: optimize this with SIMD?
|
|
92
104
|
for (int i = 0; i < framesToProcess; i++) {
|
|
@@ -13,14 +13,17 @@ class AudioBus;
|
|
|
13
13
|
|
|
14
14
|
class AudioPlayer : public AudioStreamDataCallback {
|
|
15
15
|
public:
|
|
16
|
-
explicit AudioPlayer(
|
|
16
|
+
explicit AudioPlayer(
|
|
17
|
+
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio);
|
|
17
18
|
AudioPlayer(
|
|
18
|
-
const std::function<void(AudioBus
|
|
19
|
+
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
|
|
19
20
|
float sampleRate);
|
|
20
21
|
|
|
21
22
|
[[nodiscard]] float getSampleRate() const;
|
|
22
23
|
void start();
|
|
23
24
|
void stop();
|
|
25
|
+
void resume();
|
|
26
|
+
void suspend();
|
|
24
27
|
|
|
25
28
|
DataCallbackResult onAudioReady(
|
|
26
29
|
AudioStream *oboeStream,
|
|
@@ -28,7 +31,7 @@ class AudioPlayer : public AudioStreamDataCallback {
|
|
|
28
31
|
int32_t numFrames) override;
|
|
29
32
|
|
|
30
33
|
private:
|
|
31
|
-
std::function<void(AudioBus
|
|
34
|
+
std::function<void(std::shared_ptr<AudioBus>, int)> renderAudio_;
|
|
32
35
|
std::shared_ptr<AudioStream> mStream_;
|
|
33
36
|
std::shared_ptr<AudioBus> mBus_;
|
|
34
37
|
bool isInitialized_ = false;
|
|
@@ -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
|
+
}
|
|
@@ -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
|
|
@@ -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);
|
|
@@ -48,12 +48,23 @@ void AudioContext::close() {
|
|
|
48
48
|
audioPlayer_->stop();
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
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
|
+
|
|
61
|
+
std::function<void(std::shared_ptr<AudioBus>, int)>
|
|
62
|
+
AudioContext::renderAudio() {
|
|
52
63
|
if (!isRunning() || !destination_) {
|
|
53
|
-
return [](AudioBus
|
|
64
|
+
return [](const std::shared_ptr<AudioBus> &, int) {};
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
return [this](AudioBus
|
|
67
|
+
return [this](const std::shared_ptr<AudioBus> &data, int frames) {
|
|
57
68
|
destination_->renderAudio(data, frames);
|
|
58
69
|
};
|
|
59
70
|
}
|
|
@@ -19,6 +19,8 @@ class AudioContext : public BaseAudioContext {
|
|
|
19
19
|
~AudioContext() override;
|
|
20
20
|
|
|
21
21
|
void close();
|
|
22
|
+
void resume();
|
|
23
|
+
void suspend();
|
|
22
24
|
|
|
23
25
|
private:
|
|
24
26
|
#ifdef ANDROID
|
|
@@ -27,7 +29,7 @@ class AudioContext : public BaseAudioContext {
|
|
|
27
29
|
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
|
|
28
30
|
#endif
|
|
29
31
|
|
|
30
|
-
std::function<void(AudioBus
|
|
32
|
+
std::function<void(std::shared_ptr<AudioBus>, int)> renderAudio();
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
} // namespace audioapi
|
|
@@ -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_;
|
|
@@ -23,7 +23,7 @@ double AudioDestinationNode::getCurrentTime() const {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
void AudioDestinationNode::renderAudio(
|
|
26
|
-
AudioBus
|
|
26
|
+
const std::shared_ptr<AudioBus> &destinationBus,
|
|
27
27
|
int numFrames) {
|
|
28
28
|
if (numFrames < 0 || !destinationBus || !isInitialized_) {
|
|
29
29
|
return;
|
|
@@ -33,10 +33,10 @@ void AudioDestinationNode::renderAudio(
|
|
|
33
33
|
|
|
34
34
|
destinationBus->zero();
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
auto processedBus = processAudio(destinationBus, numFrames);
|
|
37
37
|
|
|
38
38
|
if (processedBus && processedBus != destinationBus) {
|
|
39
|
-
destinationBus->copy(processedBus);
|
|
39
|
+
destinationBus->copy(processedBus.get());
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
destinationBus->normalize();
|
|
@@ -16,15 +16,15 @@ class AudioDestinationNode : public AudioNode {
|
|
|
16
16
|
public:
|
|
17
17
|
explicit AudioDestinationNode(BaseAudioContext *context);
|
|
18
18
|
|
|
19
|
-
void renderAudio(AudioBus *audioData, int numFrames);
|
|
20
|
-
|
|
21
19
|
std::size_t getCurrentSampleFrame() const;
|
|
22
20
|
double getCurrentTime() const;
|
|
23
21
|
|
|
22
|
+
void renderAudio(const std::shared_ptr<AudioBus>& audioData, int numFrames);
|
|
23
|
+
|
|
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_;
|