react-native-audio-api 0.5.7 → 0.6.0-rc.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/RNAudioAPI.podspec +1 -1
- package/android/CMakeLists.txt +6 -3
- package/android/build.gradle +1 -0
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +0 -20
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +0 -2
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +13 -0
- package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +62 -0
- package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +60 -0
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +294 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +279 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +46 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +39 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionEventEmitter.kt +84 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +144 -0
- package/android/src/main/res/drawable/next.xml +9 -0
- package/android/src/main/res/drawable/pause.xml +9 -0
- package/android/src/main/res/drawable/play.xml +9 -0
- package/android/src/main/res/drawable/previous.xml +9 -0
- package/android/src/main/res/drawable/skip_backward_5.xml +9 -0
- package/android/src/main/res/drawable/skip_forward_5.xml +9 -0
- package/android/src/main/res/drawable/stop.xml +9 -0
- package/android/src/oldarch/NativeAudioManagerModuleSpec.java +99 -0
- package/app.plugin.js +1 -0
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -6
- package/common/cpp/audioapi/core/AudioContext.cpp +1 -12
- package/common/cpp/audioapi/core/AudioContext.h +0 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +1 -6
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +8 -4
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +1 -0
- package/common/cpp/audioapi/core/utils/AudioNodeDestructor.cpp +3 -3
- package/ios/audioapi/ios/AudioAPIModule.mm +2 -3
- package/ios/audioapi/ios/AudioManagerModule.h +18 -0
- package/ios/audioapi/ios/AudioManagerModule.mm +94 -0
- package/ios/audioapi/ios/core/AudioPlayer.h +4 -12
- package/ios/audioapi/ios/core/AudioPlayer.m +26 -108
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +1 -3
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +4 -28
- package/ios/audioapi/ios/system/AudioEngine.h +23 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +137 -0
- package/ios/audioapi/ios/system/AudioSessionManager.h +22 -0
- package/ios/audioapi/ios/system/AudioSessionManager.mm +183 -0
- package/ios/audioapi/ios/system/LockScreenManager.h +23 -0
- package/ios/audioapi/ios/system/LockScreenManager.mm +295 -0
- package/ios/audioapi/ios/system/NotificationManager.h +22 -0
- package/ios/audioapi/ios/system/NotificationManager.mm +173 -0
- package/lib/commonjs/api.js +197 -0
- package/lib/commonjs/api.js.map +1 -0
- package/lib/commonjs/api.web.js +219 -0
- package/lib/commonjs/api.web.js.map +1 -0
- package/lib/commonjs/core/AnalyserNode.js +71 -0
- package/lib/commonjs/core/AnalyserNode.js.map +1 -0
- package/lib/commonjs/core/AudioBuffer.js +44 -0
- package/lib/commonjs/core/AudioBuffer.js.map +1 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js +68 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -0
- package/lib/commonjs/core/AudioContext.js +29 -0
- package/lib/commonjs/core/AudioContext.js.map +1 -0
- package/lib/commonjs/core/AudioDestinationNode.js +11 -0
- package/lib/commonjs/core/AudioDestinationNode.js.map +1 -0
- package/lib/commonjs/core/AudioNode.js +30 -0
- package/lib/commonjs/core/AudioNode.js.map +1 -0
- package/lib/commonjs/core/AudioParam.js +82 -0
- package/lib/commonjs/core/AudioParam.js.map +1 -0
- package/lib/commonjs/core/AudioScheduledSourceNode.js +38 -0
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/commonjs/core/BaseAudioContext.js +80 -0
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -0
- package/lib/commonjs/core/BiquadFilterNode.js +33 -0
- package/lib/commonjs/core/BiquadFilterNode.js.map +1 -0
- package/lib/commonjs/core/GainNode.js +17 -0
- package/lib/commonjs/core/GainNode.js.map +1 -0
- package/lib/commonjs/core/OfflineAudioContext.js +63 -0
- package/lib/commonjs/core/OfflineAudioContext.js.map +1 -0
- package/lib/commonjs/core/OscillatorNode.js +32 -0
- package/lib/commonjs/core/OscillatorNode.js.map +1 -0
- package/lib/commonjs/core/PeriodicWave.js +15 -0
- package/lib/commonjs/core/PeriodicWave.js.map +1 -0
- package/lib/commonjs/core/StereoPannerNode.js +17 -0
- package/lib/commonjs/core/StereoPannerNode.js.map +1 -0
- package/lib/commonjs/errors/IndexSizeError.js +14 -0
- package/lib/commonjs/errors/IndexSizeError.js.map +1 -0
- package/lib/commonjs/errors/InvalidAccessError.js +14 -0
- package/lib/commonjs/errors/InvalidAccessError.js.map +1 -0
- package/lib/commonjs/errors/InvalidStateError.js +14 -0
- package/lib/commonjs/errors/InvalidStateError.js.map +1 -0
- package/lib/commonjs/errors/NotSupportedError.js +14 -0
- package/lib/commonjs/errors/NotSupportedError.js.map +1 -0
- package/lib/commonjs/errors/RangeError.js +14 -0
- package/lib/commonjs/errors/RangeError.js.map +1 -0
- package/lib/commonjs/errors/index.js +42 -0
- package/lib/commonjs/errors/index.js.map +1 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/interfaces.js +6 -0
- package/lib/commonjs/interfaces.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/plugin/withAudioAPI.js +62 -0
- package/lib/commonjs/plugin/withAudioAPI.js.map +1 -0
- package/lib/commonjs/specs/NativeAudioAPIModule.js +9 -0
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -0
- package/lib/commonjs/specs/NativeAudioManagerModule.js +33 -0
- package/lib/commonjs/specs/NativeAudioManagerModule.js.map +1 -0
- package/lib/commonjs/specs/index.js +27 -0
- package/lib/commonjs/specs/index.js.map +1 -0
- package/lib/commonjs/system/AudioManager.js +79 -0
- package/lib/commonjs/system/AudioManager.js.map +1 -0
- package/lib/commonjs/system/index.js +14 -0
- package/lib/commonjs/system/index.js.map +1 -0
- package/lib/commonjs/system/types.js +2 -0
- package/lib/commonjs/system/types.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/index.js +10 -0
- package/lib/commonjs/utils/index.js.map +1 -0
- package/lib/commonjs/web-core/AnalyserNode.js +38 -0
- package/lib/commonjs/web-core/AnalyserNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioBuffer.js +44 -0
- package/lib/commonjs/web-core/AudioBuffer.js.map +1 -0
- package/lib/commonjs/web-core/AudioBufferSourceNode.js +214 -0
- package/lib/commonjs/web-core/AudioBufferSourceNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioContext.js +93 -0
- package/lib/commonjs/web-core/AudioContext.js.map +1 -0
- package/lib/commonjs/web-core/AudioDestinationNode.js +11 -0
- package/lib/commonjs/web-core/AudioDestinationNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioNode.js +33 -0
- package/lib/commonjs/web-core/AudioNode.js.map +1 -0
- package/lib/commonjs/web-core/AudioParam.js +81 -0
- package/lib/commonjs/web-core/AudioParam.js.map +1 -0
- package/lib/commonjs/web-core/AudioScheduledSourceNode.js +41 -0
- package/lib/commonjs/web-core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/commonjs/web-core/BaseAudioContext.js +2 -0
- package/lib/commonjs/web-core/BaseAudioContext.js.map +1 -0
- package/lib/commonjs/web-core/BiquadFilterNode.js +33 -0
- package/lib/commonjs/web-core/BiquadFilterNode.js.map +1 -0
- package/lib/commonjs/web-core/GainNode.js +17 -0
- package/lib/commonjs/web-core/GainNode.js.map +1 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js +96 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -0
- package/lib/commonjs/web-core/OscillatorNode.js +31 -0
- package/lib/commonjs/web-core/OscillatorNode.js.map +1 -0
- package/lib/commonjs/web-core/PeriodicWave.js +15 -0
- package/lib/commonjs/web-core/PeriodicWave.js.map +1 -0
- package/lib/commonjs/web-core/StereoPannerNode.js +17 -0
- package/lib/commonjs/web-core/StereoPannerNode.js.map +1 -0
- package/lib/commonjs/web-core/custom/LoadCustomWasm.js +37 -0
- package/lib/commonjs/web-core/custom/LoadCustomWasm.js.map +1 -0
- package/lib/commonjs/web-core/custom/index.js +14 -0
- package/lib/commonjs/web-core/custom/index.js.map +1 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/LICENSE.txt +21 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/README.md +46 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +826 -0
- package/lib/commonjs/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs.map +1 -0
- package/lib/module/api.js +1 -0
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioContext.js +2 -1
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/plugin/withAudioAPI.js +58 -0
- package/lib/module/plugin/withAudioAPI.js.map +1 -0
- package/lib/module/specs/NativeAudioManagerModule.js +30 -0
- package/lib/module/specs/NativeAudioManagerModule.js.map +1 -0
- package/lib/module/specs/index.js +6 -0
- package/lib/module/specs/index.js.map +1 -0
- package/lib/module/system/AudioManager.js +75 -0
- package/lib/module/system/AudioManager.js.map +1 -0
- package/lib/module/system/index.js +4 -0
- package/lib/module/system/index.js.map +1 -0
- package/lib/module/system/types.js +2 -0
- package/lib/module/system/types.js.map +1 -0
- package/lib/typescript/api.d.ts +1 -0
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/plugin/withAudioAPI.d.ts +9 -0
- package/lib/typescript/plugin/withAudioAPI.d.ts.map +1 -0
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts +14 -0
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +1 -0
- package/lib/typescript/specs/index.d.ts +4 -0
- package/lib/typescript/specs/index.d.ts.map +1 -0
- package/lib/typescript/system/AudioManager.d.ts +14 -0
- package/lib/typescript/system/AudioManager.d.ts.map +1 -0
- package/lib/typescript/system/index.d.ts +2 -0
- package/lib/typescript/system/index.d.ts.map +1 -0
- package/lib/typescript/system/types.d.ts +40 -0
- package/lib/typescript/system/types.d.ts.map +1 -0
- package/package.json +7 -4
- package/src/api.ts +1 -0
- package/src/core/AudioContext.ts +6 -1
- package/src/plugin/withAudioAPI.ts +90 -0
- package/src/specs/NativeAudioManagerModule.ts +48 -0
- package/src/specs/index.ts +6 -0
- package/src/system/AudioManager.ts +149 -0
- package/src/system/index.ts +1 -0
- package/src/system/types.ts +84 -0
|
@@ -0,0 +1,99 @@
|
|
|
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.bridge.ReadableArray;
|
|
20
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
21
|
+
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
|
22
|
+
import javax.annotation.Nonnull;
|
|
23
|
+
|
|
24
|
+
public abstract class NativeAudioManagerModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
|
|
25
|
+
public static final String NAME = "AudioManagerModule";
|
|
26
|
+
|
|
27
|
+
public NativeAudioManagerModuleSpec(ReactApplicationContext reactContext) {
|
|
28
|
+
super(reactContext);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Override
|
|
32
|
+
public @Nonnull String getName() {
|
|
33
|
+
return NAME;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
protected final void emitOnRemotePlay() {
|
|
37
|
+
mEventEmitterCallback.invoke("onRemotePlay");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
protected final void emitOnRemotePause() {
|
|
41
|
+
mEventEmitterCallback.invoke("onRemotePause");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected final void emitOnStop() {
|
|
45
|
+
mEventEmitterCallback.invoke("onStop");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected final void emitOnTogglePlayPause() {
|
|
49
|
+
mEventEmitterCallback.invoke("onTogglePlayPause");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected final void emitOnChangePlaybackRate(double value) {
|
|
53
|
+
mEventEmitterCallback.invoke("onChangePlaybackRate", value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected final void emitOnNextTrack() {
|
|
57
|
+
mEventEmitterCallback.invoke("onNextTrack");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected final void emitOnPreviousTrack() {
|
|
61
|
+
mEventEmitterCallback.invoke("onPreviousTrack");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected final void emitOnSkipForward(double value) {
|
|
65
|
+
mEventEmitterCallback.invoke("onSkipForward", value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected final void emitOnSkipBackward(double value) {
|
|
69
|
+
mEventEmitterCallback.invoke("onSkipBackward", value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
protected final void emitOnSeekForward() {
|
|
73
|
+
mEventEmitterCallback.invoke("onSeekForward");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected final void emitOnSeekBackward() {
|
|
77
|
+
mEventEmitterCallback.invoke("onSeekBackward");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
protected final void emitOnChangePlaybackPosition(double value) {
|
|
81
|
+
mEventEmitterCallback.invoke("onChangePlaybackPosition", value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@ReactMethod
|
|
85
|
+
@DoNotStrip
|
|
86
|
+
public abstract void setLockScreenInfo(ReadableMap info);
|
|
87
|
+
|
|
88
|
+
@ReactMethod
|
|
89
|
+
@DoNotStrip
|
|
90
|
+
public abstract void resetLockScreenInfo();
|
|
91
|
+
|
|
92
|
+
@ReactMethod
|
|
93
|
+
@DoNotStrip
|
|
94
|
+
public abstract void setSessionOptions(String category, String mode, ReadableArray options);
|
|
95
|
+
|
|
96
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
97
|
+
@DoNotStrip
|
|
98
|
+
public abstract double getDevicePreferredSampleRate();
|
|
99
|
+
}
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./lib/commonjs/plugin/withAudioAPI');
|
|
@@ -35,12 +35,8 @@ class AudioAPIModuleInstaller {
|
|
|
35
35
|
const jsi::Value *args,
|
|
36
36
|
size_t count) -> jsi::Value {
|
|
37
37
|
std::shared_ptr<AudioContext> audioContext;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
} else {
|
|
41
|
-
auto sampleRate = static_cast<float>(args[0].getNumber());
|
|
42
|
-
audioContext = std::make_shared<AudioContext>(sampleRate);
|
|
43
|
-
}
|
|
38
|
+
auto sampleRate = static_cast<float>(args[0].getNumber());
|
|
39
|
+
audioContext = std::make_shared<AudioContext>(sampleRate);
|
|
44
40
|
|
|
45
41
|
auto audioContextHostObject = std::make_shared<AudioContextHostObject>(
|
|
46
42
|
audioContext, &runtime, jsCallInvoker);
|
|
@@ -10,18 +10,6 @@
|
|
|
10
10
|
#include <audioapi/core/utils/AudioNodeManager.h>
|
|
11
11
|
|
|
12
12
|
namespace audioapi {
|
|
13
|
-
AudioContext::AudioContext() : BaseAudioContext() {
|
|
14
|
-
#ifdef ANDROID
|
|
15
|
-
audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
|
|
16
|
-
#else
|
|
17
|
-
audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
|
|
18
|
-
#endif
|
|
19
|
-
sampleRate_ = audioPlayer_->getSampleRate();
|
|
20
|
-
audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate_);
|
|
21
|
-
|
|
22
|
-
audioPlayer_->start();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
13
|
AudioContext::AudioContext(float sampleRate) : BaseAudioContext() {
|
|
26
14
|
#ifdef ANDROID
|
|
27
15
|
audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio(), sampleRate);
|
|
@@ -29,6 +17,7 @@ AudioContext::AudioContext(float sampleRate) : BaseAudioContext() {
|
|
|
29
17
|
audioPlayer_ =
|
|
30
18
|
std::make_shared<IOSAudioPlayer>(this->renderAudio(), sampleRate);
|
|
31
19
|
#endif
|
|
20
|
+
|
|
32
21
|
sampleRate_ = audioPlayer_->getSampleRate();
|
|
33
22
|
audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate_);
|
|
34
23
|
|
|
@@ -128,12 +128,7 @@ void AudioBufferSourceNode::start(double when, double offset, double duration) {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
void AudioBufferSourceNode::disable() {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (onendedCallback_) {
|
|
134
|
-
onendedCallback_(getStopTime());
|
|
135
|
-
}
|
|
136
|
-
|
|
131
|
+
AudioScheduledSourceNode::disable();
|
|
137
132
|
alignedBus_.reset();
|
|
138
133
|
}
|
|
139
134
|
|
|
@@ -141,12 +141,16 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
|
141
141
|
nonSilentFramesToProcess = framesToProcess;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
void AudioScheduledSourceNode::disable() {
|
|
145
|
+
AudioNode::disable();
|
|
146
|
+
|
|
147
|
+
if (onendedCallback_) {
|
|
148
|
+
onendedCallback_(getStopTime());
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
144
152
|
void AudioScheduledSourceNode::handleStopScheduled() {
|
|
145
153
|
if (isStopScheduled()) {
|
|
146
|
-
if (onendedCallback_) {
|
|
147
|
-
onendedCallback_(getStopTime());
|
|
148
|
-
}
|
|
149
|
-
|
|
150
154
|
playbackState_ = PlaybackState::FINISHED;
|
|
151
155
|
disable();
|
|
152
156
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
namespace audioapi {
|
|
6
6
|
|
|
7
|
-
AudioNodeDestructor::AudioNodeDestructor()
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
AudioNodeDestructor::AudioNodeDestructor() : isExiting_(false) {
|
|
8
|
+
thread_ = std::thread(&AudioNodeDestructor::process, this);
|
|
9
|
+
}
|
|
10
10
|
|
|
11
11
|
AudioNodeDestructor::~AudioNodeDestructor() {
|
|
12
12
|
isExiting_ = true;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
6
6
|
#import <React/RCTCallInvoker.h>
|
|
7
|
-
#import <ReactCommon/RCTTurboModule.h>
|
|
8
7
|
#endif // RCT_NEW_ARCH_ENABLED
|
|
9
8
|
|
|
10
9
|
#include <audioapi/AudioAPIModuleInstaller.h>
|
|
@@ -16,9 +15,9 @@ using namespace facebook::react;
|
|
|
16
15
|
- (void *)runtime;
|
|
17
16
|
@end
|
|
18
17
|
|
|
19
|
-
#if defined(RCT_NEW_ARCH_ENABLED)
|
|
18
|
+
#if defined(RCT_NEW_ARCH_ENABLED)
|
|
20
19
|
// nothing
|
|
21
|
-
#else // defined(RCT_NEW_ARCH_ENABLED)
|
|
20
|
+
#else // defined(RCT_NEW_ARCH_ENABLED)
|
|
22
21
|
@interface RCTBridge (RCTTurboModule)
|
|
23
22
|
- (std::shared_ptr<facebook::react::CallInvoker>)jsCallInvoker;
|
|
24
23
|
- (void)_tryAndHandleError:(dispatch_block_t)block;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
#import <React/RCTEventEmitter.h>
|
|
5
|
+
|
|
6
|
+
@class AudioEngine;
|
|
7
|
+
@class NotificationManager;
|
|
8
|
+
@class AudioSessionManager;
|
|
9
|
+
@class LockScreenManager;
|
|
10
|
+
|
|
11
|
+
@interface AudioManagerModule : RCTEventEmitter <RCTBridgeModule>
|
|
12
|
+
|
|
13
|
+
@property (nonatomic, strong) AudioEngine *audioEngine;
|
|
14
|
+
@property (nonatomic, strong) NotificationManager *notificationManager;
|
|
15
|
+
@property (nonatomic, strong) AudioSessionManager *audioSessionManager;
|
|
16
|
+
@property (nonatomic, strong) LockScreenManager *lockScreenManager;
|
|
17
|
+
|
|
18
|
+
@end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#import <audioapi/ios/AudioManagerModule.h>
|
|
2
|
+
|
|
3
|
+
#import <audioapi/ios/system/AudioEngine.h>
|
|
4
|
+
#import <audioapi/ios/system/AudioSessionManager.h>
|
|
5
|
+
#import <audioapi/ios/system/LockScreenManager.h>
|
|
6
|
+
#import <audioapi/ios/system/NotificationManager.h>
|
|
7
|
+
|
|
8
|
+
@implementation AudioManagerModule
|
|
9
|
+
|
|
10
|
+
RCT_EXPORT_MODULE(AudioManagerModule);
|
|
11
|
+
|
|
12
|
+
- (id)init
|
|
13
|
+
{
|
|
14
|
+
if (self == [super init]) {
|
|
15
|
+
self.audioEngine = [AudioEngine sharedInstance];
|
|
16
|
+
self.audioSessionManager = [AudioSessionManager sharedInstance];
|
|
17
|
+
self.notificationManager = [NotificationManager sharedInstanceWithAudioManagerModule:self];
|
|
18
|
+
self.lockScreenManager = [LockScreenManager sharedInstanceWithAudioManagerModule:self];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return self;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- (void)cleanup
|
|
25
|
+
{
|
|
26
|
+
[self.audioEngine cleanup];
|
|
27
|
+
[self.notificationManager cleanup];
|
|
28
|
+
[self.audioSessionManager cleanup];
|
|
29
|
+
[self.lockScreenManager cleanup];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
- (void)dealloc
|
|
33
|
+
{
|
|
34
|
+
[self cleanup];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
RCT_EXPORT_METHOD(setLockScreenInfo : (NSDictionary *)info)
|
|
38
|
+
{
|
|
39
|
+
[self.lockScreenManager setLockScreenInfo:info];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
RCT_EXPORT_METHOD(resetLockScreenInfo)
|
|
43
|
+
{
|
|
44
|
+
[self.lockScreenManager resetLockScreenInfo];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
RCT_EXPORT_METHOD(enableRemoteCommand : (NSString *)name enabled : (BOOL)enabled)
|
|
48
|
+
{
|
|
49
|
+
[self.lockScreenManager enableRemoteCommand:name enabled:enabled];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
RCT_EXPORT_METHOD(setAudioSessionOptions : (NSString *)category mode : (NSString *)mode options : (NSArray *)
|
|
53
|
+
options active : (BOOL)active)
|
|
54
|
+
{
|
|
55
|
+
NSError *error = nil;
|
|
56
|
+
|
|
57
|
+
if (active) {
|
|
58
|
+
[self.audioSessionManager setAudioSessionOptions:category mode:mode options:options];
|
|
59
|
+
} else {
|
|
60
|
+
[self.audioSessionManager setActive:false error:&error];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
RCT_EXPORT_METHOD(observeAudioInterruptions : (BOOL)enabled)
|
|
65
|
+
{
|
|
66
|
+
[self.notificationManager observeAudioInterruptions:enabled];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getDevicePreferredSampleRate)
|
|
70
|
+
{
|
|
71
|
+
return [self.audioSessionManager getDevicePreferredSampleRate];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
- (NSArray<NSString *> *)supportedEvents
|
|
75
|
+
{
|
|
76
|
+
return @[
|
|
77
|
+
@"onRemotePlay",
|
|
78
|
+
@"onRemotePause",
|
|
79
|
+
@"onRemoteStop",
|
|
80
|
+
@"onRemoteTogglePlayPause",
|
|
81
|
+
@"onRemoteChangePlaybackRate",
|
|
82
|
+
@"onRemoteNextTrack",
|
|
83
|
+
@"onRemotePreviousTrack",
|
|
84
|
+
@"onRemoteSkipForward",
|
|
85
|
+
@"onRemoteSkipBackward",
|
|
86
|
+
@"onRemoteSeekForward",
|
|
87
|
+
@"onRemoteSeekBackward",
|
|
88
|
+
@"onRemoteChangePlaybackPosition",
|
|
89
|
+
@"onInterruption",
|
|
90
|
+
@"onRouteChange"
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@end
|
|
@@ -7,22 +7,18 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
|
|
|
7
7
|
|
|
8
8
|
@interface AudioPlayer : NSObject
|
|
9
9
|
|
|
10
|
-
@property (nonatomic, strong) AVAudioEngine *audioEngine;
|
|
11
|
-
@property (nonatomic, weak) AVAudioSession *audioSession;
|
|
12
|
-
@property (nonatomic, weak) NSNotificationCenter *notificationCenter;
|
|
13
10
|
@property (nonatomic, strong) AVAudioFormat *format;
|
|
14
11
|
@property (nonatomic, strong) AVAudioSourceNode *sourceNode;
|
|
15
12
|
@property (nonatomic, copy) RenderAudioBlock renderAudio;
|
|
16
13
|
@property (nonatomic, assign) float sampleRate;
|
|
17
14
|
@property (nonatomic, assign) int channelCount;
|
|
18
15
|
@property (nonatomic, assign) bool isRunning;
|
|
16
|
+
@property (nonatomic, strong) NSString *sourceNodeId;
|
|
19
17
|
@property (nonatomic, strong) AVAudioSourceNodeRenderBlock renderBlock;
|
|
20
18
|
|
|
21
|
-
- (instancetype)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
sampleRate:(float)sampleRate
|
|
25
|
-
channelCount:(int)channelCount;
|
|
19
|
+
- (instancetype)initWithRenderAudio:(RenderAudioBlock)renderAudio
|
|
20
|
+
sampleRate:(float)sampleRate
|
|
21
|
+
channelCount:(int)channelCount;
|
|
26
22
|
|
|
27
23
|
- (float)getSampleRate;
|
|
28
24
|
|
|
@@ -36,8 +32,4 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
|
|
|
36
32
|
|
|
37
33
|
- (void)cleanup;
|
|
38
34
|
|
|
39
|
-
- (void)setupAndInitAudioSession;
|
|
40
|
-
|
|
41
|
-
- (void)connectAudioEngine;
|
|
42
|
-
|
|
43
35
|
@end
|
|
@@ -1,52 +1,17 @@
|
|
|
1
1
|
#import <audioapi/ios/core/AudioPlayer.h>
|
|
2
|
+
#import <audioapi/ios/system/AudioEngine.h>
|
|
2
3
|
|
|
3
4
|
@implementation AudioPlayer
|
|
4
5
|
|
|
5
|
-
- (instancetype)
|
|
6
|
+
- (instancetype)initWithRenderAudio:(RenderAudioBlock)renderAudio
|
|
7
|
+
sampleRate:(float)sampleRate
|
|
8
|
+
channelCount:(int)channelCount
|
|
6
9
|
{
|
|
7
10
|
if (self = [super init]) {
|
|
8
|
-
self.
|
|
9
|
-
self.audioEngine = [[AVAudioEngine alloc] init];
|
|
10
|
-
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
11
|
-
self.isRunning = true;
|
|
12
|
-
|
|
13
|
-
[self setupAndInitAudioSession];
|
|
11
|
+
self.sampleRate = sampleRate;
|
|
14
12
|
|
|
15
|
-
self.sampleRate = [self.audioSession sampleRate];
|
|
16
13
|
self.channelCount = channelCount;
|
|
17
|
-
|
|
18
|
-
__weak typeof(self) weakSelf = self;
|
|
19
|
-
self.renderBlock = ^OSStatus(
|
|
20
|
-
BOOL *isSilence, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, AudioBufferList *outputData) {
|
|
21
|
-
if (outputData->mNumberBuffers != weakSelf.channelCount) {
|
|
22
|
-
return kAudioServicesBadPropertySizeError;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
weakSelf.renderAudio(outputData, frameCount);
|
|
26
|
-
return kAudioServicesNoError;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
_format = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:self.sampleRate channels:self.channelCount];
|
|
30
|
-
_sourceNode = [[AVAudioSourceNode alloc] initWithFormat:self.format renderBlock:self.renderBlock];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return self;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
- (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio
|
|
37
|
-
sampleRate:(float)sampleRate
|
|
38
|
-
channelCount:(int)channelCount
|
|
39
|
-
{
|
|
40
|
-
if (self = [super init]) {
|
|
41
14
|
self.renderAudio = [renderAudio copy];
|
|
42
|
-
self.audioEngine = [[AVAudioEngine alloc] init];
|
|
43
|
-
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
44
|
-
self.isRunning = true;
|
|
45
|
-
|
|
46
|
-
[self setupAndInitAudioSession];
|
|
47
|
-
|
|
48
|
-
self.sampleRate = sampleRate;
|
|
49
|
-
self.channelCount = channelCount;
|
|
50
15
|
|
|
51
16
|
__weak typeof(self) weakSelf = self;
|
|
52
17
|
self.renderBlock = ^OSStatus(
|
|
@@ -73,96 +38,49 @@
|
|
|
73
38
|
|
|
74
39
|
- (void)start
|
|
75
40
|
{
|
|
41
|
+
NSLog(@"[AudioPlayer] start");
|
|
42
|
+
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
76
43
|
self.isRunning = true;
|
|
77
|
-
[self
|
|
44
|
+
self.sourceNodeId = [audioEngine attachSourceNode:self.sourceNode format:self.format];
|
|
78
45
|
}
|
|
79
46
|
|
|
80
47
|
- (void)stop
|
|
81
48
|
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (self.audioEngine.isRunning) {
|
|
86
|
-
[self.audioEngine stop];
|
|
49
|
+
NSLog(@"[AudioPlayer] stop");
|
|
50
|
+
if (!self.isRunning) {
|
|
51
|
+
return;
|
|
87
52
|
}
|
|
88
53
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
NSLog(@"Error while deactivating audio session: %@", [error debugDescription]);
|
|
94
|
-
}
|
|
54
|
+
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
55
|
+
self.isRunning = false;
|
|
56
|
+
[audioEngine detachSourceNodeWithId:self.sourceNodeId];
|
|
57
|
+
self.sourceNodeId = nil;
|
|
95
58
|
}
|
|
96
59
|
|
|
97
60
|
- (void)suspend
|
|
98
61
|
{
|
|
99
|
-
[
|
|
62
|
+
NSLog(@"[AudioPlayer] suspend");
|
|
63
|
+
if (!self.isRunning) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
100
68
|
self.isRunning = false;
|
|
69
|
+
[audioEngine detachSourceNodeWithId:self.sourceNodeId];
|
|
70
|
+
self.sourceNodeId = nil;
|
|
101
71
|
}
|
|
102
72
|
|
|
103
73
|
- (void)resume
|
|
104
74
|
{
|
|
75
|
+
NSLog(@"[AudioPlayer] resume");
|
|
76
|
+
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
105
77
|
self.isRunning = true;
|
|
106
|
-
[self
|
|
107
|
-
[self connectAudioEngine];
|
|
78
|
+
self.sourceNodeId = [audioEngine attachSourceNode:self.sourceNode format:self.format];
|
|
108
79
|
}
|
|
109
80
|
|
|
110
81
|
- (void)cleanup
|
|
111
82
|
{
|
|
112
|
-
self.audioEngine = nil;
|
|
113
|
-
self.audioSession = nil;
|
|
114
83
|
self.renderAudio = nil;
|
|
115
84
|
}
|
|
116
85
|
|
|
117
|
-
- (void)setupAndInitAudioSession
|
|
118
|
-
{
|
|
119
|
-
NSError *error = nil;
|
|
120
|
-
|
|
121
|
-
if (!self.audioSession) {
|
|
122
|
-
self.audioSession = [AVAudioSession sharedInstance];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
[self.audioSession setCategory:AVAudioSessionCategoryPlayback
|
|
126
|
-
mode:AVAudioSessionModeDefault
|
|
127
|
-
options:AVAudioSessionCategoryOptionDuckOthers | AVAudioSessionCategoryOptionAllowAirPlay
|
|
128
|
-
error:&error];
|
|
129
|
-
|
|
130
|
-
if (error != nil) {
|
|
131
|
-
NSLog(@"Error while configuring audio session: %@", [error debugDescription]);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
[self.audioSession setPreferredIOBufferDuration:0.022 error:&error];
|
|
136
|
-
|
|
137
|
-
if (error != nil) {
|
|
138
|
-
NSLog(@"Error while setting buffer size in audio session: %@", [error debugDescription]);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
[self.audioSession setActive:true error:&error];
|
|
143
|
-
|
|
144
|
-
if (error != nil) {
|
|
145
|
-
NSLog(@"Error while activating audio session: %@", [error debugDescription]);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
- (void)connectAudioEngine
|
|
151
|
-
{
|
|
152
|
-
if ([self.audioEngine isRunning]) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
[self.audioEngine attachNode:self.sourceNode];
|
|
157
|
-
[self.audioEngine connect:self.sourceNode to:self.audioEngine.mainMixerNode format:self.format];
|
|
158
|
-
|
|
159
|
-
if (![self.audioEngine isRunning]) {
|
|
160
|
-
NSError *error = nil;
|
|
161
|
-
|
|
162
|
-
if (![self.audioEngine startAndReturnError:&error]) {
|
|
163
|
-
NSLog(@"Error starting audio engine: %@", [error debugDescription]);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
86
|
@end
|
|
@@ -10,8 +10,8 @@ typedef struct objc_object AudioPlayer;
|
|
|
10
10
|
|
|
11
11
|
namespace audioapi {
|
|
12
12
|
|
|
13
|
-
class AudioContext;
|
|
14
13
|
class AudioBus;
|
|
14
|
+
class AudioContext;
|
|
15
15
|
|
|
16
16
|
class IOSAudioPlayer {
|
|
17
17
|
protected:
|
|
@@ -21,8 +21,6 @@ class IOSAudioPlayer {
|
|
|
21
21
|
int channelCount_;
|
|
22
22
|
|
|
23
23
|
public:
|
|
24
|
-
explicit IOSAudioPlayer(
|
|
25
|
-
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio);
|
|
26
24
|
IOSAudioPlayer(
|
|
27
25
|
const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio,
|
|
28
26
|
float sampleRate);
|
|
@@ -8,31 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
namespace audioapi {
|
|
10
10
|
|
|
11
|
-
IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio)
|
|
12
|
-
: channelCount_(2), renderAudio_(renderAudio), audioBus_(0)
|
|
13
|
-
{
|
|
14
|
-
RenderAudioBlock renderAudioBlock = ^(AudioBufferList *outputData, int numFrames) {
|
|
15
|
-
int processedFrames = 0;
|
|
16
|
-
|
|
17
|
-
while (processedFrames < numFrames) {
|
|
18
|
-
int framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
|
|
19
|
-
renderAudio_(audioBus_, framesToProcess);
|
|
20
|
-
|
|
21
|
-
for (int channel = 0; channel < channelCount_; channel += 1) {
|
|
22
|
-
float *outputChannel = (float *)outputData->mBuffers[channel].mData;
|
|
23
|
-
auto *inputChannel = audioBus_->getChannel(channel)->getData();
|
|
24
|
-
|
|
25
|
-
memcpy(outputChannel + processedFrames, inputChannel, framesToProcess * sizeof(float));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
processedFrames += framesToProcess;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock channelCount:channelCount_];
|
|
33
|
-
audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, getSampleRate());
|
|
34
|
-
}
|
|
35
|
-
|
|
36
11
|
IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus>, int)> &renderAudio, float sampleRate)
|
|
37
12
|
: channelCount_(2), renderAudio_(renderAudio), audioBus_(0)
|
|
38
13
|
{
|
|
@@ -54,9 +29,10 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(std::shared_ptr<AudioBus
|
|
|
54
29
|
}
|
|
55
30
|
};
|
|
56
31
|
|
|
57
|
-
audioPlayer_ = [[AudioPlayer alloc]
|
|
58
|
-
|
|
59
|
-
|
|
32
|
+
audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudio:renderAudioBlock
|
|
33
|
+
sampleRate:sampleRate
|
|
34
|
+
channelCount:channelCount_];
|
|
35
|
+
|
|
60
36
|
audioBus_ = std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, getSampleRate());
|
|
61
37
|
}
|
|
62
38
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
|
|
6
|
+
@interface AudioEngine : NSObject
|
|
7
|
+
|
|
8
|
+
@property (nonatomic, strong) AVAudioEngine *audioEngine;
|
|
9
|
+
@property (nonatomic, strong) NSMutableDictionary *sourceNodes;
|
|
10
|
+
@property (nonatomic, strong) NSMutableDictionary *sourceFormats;
|
|
11
|
+
|
|
12
|
+
+ (instancetype)sharedInstance;
|
|
13
|
+
- (void)cleanup;
|
|
14
|
+
|
|
15
|
+
- (bool)rebuildAudioEngine;
|
|
16
|
+
- (void)startEngine;
|
|
17
|
+
- (void)stopEngine;
|
|
18
|
+
- (bool)isRunning;
|
|
19
|
+
|
|
20
|
+
- (NSString *)attachSourceNode:(AVAudioSourceNode *)sourceNode format:(AVAudioFormat *)format;
|
|
21
|
+
- (void)detachSourceNodeWithId:(NSString *)sourceNodeId;
|
|
22
|
+
|
|
23
|
+
@end
|