react-native-audio-api 0.6.1-rc.1 → 0.6.1-rc.10
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/README.md +6 -11
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +13 -8
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +3 -2
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +27 -10
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +12 -3
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +2 -2
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +4 -6
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +1 -1
- package/android/src/main/res/drawable/skip_backward_10.xml +9 -0
- package/android/src/main/res/drawable/skip_forward_10.xml +9 -0
- package/android/src/oldarch/NativeAudioAPIModuleSpec.java +68 -64
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -1
- package/common/cpp/audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h +94 -0
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +7 -7
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +9 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +29 -4
- package/common/cpp/audioapi/core/AudioContext.h +2 -1
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +12 -0
- package/common/cpp/audioapi/core/BaseAudioContext.h +4 -3
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -0
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +236 -0
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +72 -0
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +2 -2
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +3 -4
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +2 -1
- package/ios/audioapi/ios/AudioAPIModule.mm +23 -11
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +3 -2
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +21 -10
- package/ios/audioapi/ios/core/NativeAudioPlayer.h +4 -0
- package/ios/audioapi/ios/core/NativeAudioPlayer.m +15 -0
- package/ios/audioapi/ios/system/AudioEngine.h +1 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +11 -1
- package/ios/audioapi/ios/system/AudioSessionManager.mm +1 -1
- package/ios/audioapi/ios/system/LockScreenManager.mm +13 -1
- package/ios/audioapi/ios/system/NotificationManager.mm +1 -1
- package/lib/commonjs/api.js +7 -0
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js +46 -0
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -0
- package/lib/commonjs/core/AudioContext.js +2 -2
- package/lib/commonjs/core/AudioContext.js.map +1 -1
- package/lib/commonjs/core/AudioNode.js +5 -1
- package/lib/commonjs/core/AudioNode.js.map +1 -1
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +4 -0
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/hooks/useSytemVolume.js +1 -1
- package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
- package/lib/commonjs/plugin/withAudioAPI.js +15 -14
- package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/commonjs/system/AudioManager.js +12 -10
- package/lib/commonjs/system/AudioManager.js.map +1 -1
- package/lib/commonjs/web-core/AudioBufferSourceNode.js +4 -4
- package/lib/commonjs/web-core/AudioBufferSourceNode.js.map +1 -1
- package/lib/commonjs/web-core/AudioContext.js +5 -3
- package/lib/commonjs/web-core/AudioContext.js.map +1 -1
- package/lib/commonjs/web-core/AudioNode.js +8 -2
- package/lib/commonjs/web-core/AudioNode.js.map +1 -1
- package/lib/commonjs/web-core/AudioParam.js +2 -1
- package/lib/commonjs/web-core/AudioParam.js.map +1 -1
- package/lib/commonjs/web-core/BiquadFilterNode.js +4 -4
- package/lib/commonjs/web-core/BiquadFilterNode.js.map +1 -1
- package/lib/commonjs/web-core/GainNode.js +1 -1
- package/lib/commonjs/web-core/GainNode.js.map +1 -1
- package/lib/commonjs/web-core/OscillatorNode.js +2 -2
- package/lib/commonjs/web-core/OscillatorNode.js.map +1 -1
- package/lib/commonjs/web-core/StereoPannerNode.js +1 -1
- package/lib/commonjs/web-core/StereoPannerNode.js.map +1 -1
- package/lib/module/api.js +1 -0
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioBufferQueueSourceNode.js +40 -0
- package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -0
- package/lib/module/core/AudioContext.js +2 -2
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/core/AudioNode.js +5 -1
- package/lib/module/core/AudioNode.js.map +1 -1
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +4 -0
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/hooks/useSytemVolume.js +1 -1
- package/lib/module/hooks/useSytemVolume.js.map +1 -1
- package/lib/module/plugin/withAudioAPI.js +15 -14
- package/lib/module/plugin/withAudioAPI.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/module/system/AudioManager.js +12 -10
- package/lib/module/system/AudioManager.js.map +1 -1
- package/lib/module/web-core/AudioBufferSourceNode.js +4 -4
- package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +5 -3
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/AudioNode.js +7 -2
- package/lib/module/web-core/AudioNode.js.map +1 -1
- package/lib/module/web-core/AudioParam.js +2 -1
- package/lib/module/web-core/AudioParam.js.map +1 -1
- package/lib/module/web-core/BiquadFilterNode.js +4 -4
- package/lib/module/web-core/BiquadFilterNode.js.map +1 -1
- package/lib/module/web-core/GainNode.js +1 -1
- package/lib/module/web-core/GainNode.js.map +1 -1
- package/lib/module/web-core/OscillatorNode.js +2 -2
- package/lib/module/web-core/OscillatorNode.js.map +1 -1
- package/lib/module/web-core/StereoPannerNode.js +1 -1
- package/lib/module/web-core/StereoPannerNode.js.map +1 -1
- package/lib/typescript/api.d.ts +2 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +16 -0
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts +1 -1
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +4 -3
- package/lib/typescript/core/AudioScheduledSourceNode.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/events/types.d.ts +18 -9
- package/lib/typescript/events/types.d.ts.map +1 -1
- package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +9 -0
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/plugin/withAudioAPI.d.ts +7 -6
- package/lib/typescript/plugin/withAudioAPI.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts +3 -2
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
- package/lib/typescript/system/AudioManager.d.ts +6 -4
- package/lib/typescript/system/AudioManager.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +2 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioNode.d.ts +2 -1
- package/lib/typescript/web-core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioParam.d.ts +4 -2
- package/lib/typescript/web-core/AudioParam.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/api.ts +5 -1
- package/src/core/AudioBufferQueueSourceNode.ts +71 -0
- package/src/core/AudioContext.ts +7 -2
- package/src/core/AudioNode.ts +6 -2
- package/src/core/AudioScheduledSourceNode.ts +3 -3
- package/src/core/BaseAudioContext.ts +8 -0
- package/src/events/types.ts +29 -9
- package/src/hooks/useSytemVolume.ts +6 -3
- package/src/interfaces.ts +18 -0
- package/src/plugin/withAudioAPI.ts +36 -29
- package/src/specs/NativeAudioAPIModule.ts +14 -6
- package/src/system/AudioManager.ts +21 -16
- package/src/types.ts +2 -1
- package/src/web-core/AudioBufferSourceNode.tsx +9 -4
- package/src/web-core/AudioContext.tsx +7 -3
- package/src/web-core/AudioNode.tsx +10 -3
- package/src/web-core/AudioParam.tsx +5 -2
- package/src/web-core/BiquadFilterNode.tsx +4 -4
- package/src/web-core/GainNode.tsx +1 -1
- package/src/web-core/OscillatorNode.tsx +2 -2
- package/src/web-core/StereoPannerNode.tsx +1 -1
- package/android/src/main/res/drawable/skip_backward_5.xml +0 -9
- package/android/src/main/res/drawable/skip_forward_5.xml +0 -9
package/src/core/AudioContext.ts
CHANGED
|
@@ -6,7 +6,11 @@ import { NotSupportedError } from '../errors';
|
|
|
6
6
|
|
|
7
7
|
export default class AudioContext extends BaseAudioContext {
|
|
8
8
|
constructor(options?: AudioContextOptions) {
|
|
9
|
-
if (
|
|
9
|
+
if (
|
|
10
|
+
options &&
|
|
11
|
+
options.sampleRate &&
|
|
12
|
+
(options.sampleRate < 8000 || options.sampleRate > 96000)
|
|
13
|
+
) {
|
|
10
14
|
throw new NotSupportedError(
|
|
11
15
|
`The provided sampleRate is not supported: ${options.sampleRate}`
|
|
12
16
|
);
|
|
@@ -14,7 +18,8 @@ export default class AudioContext extends BaseAudioContext {
|
|
|
14
18
|
|
|
15
19
|
super(
|
|
16
20
|
global.createAudioContext(
|
|
17
|
-
options?.sampleRate || AudioManager.getDevicePreferredSampleRate()
|
|
21
|
+
options?.sampleRate || AudioManager.getDevicePreferredSampleRate(),
|
|
22
|
+
options?.initSuspended || false
|
|
18
23
|
)
|
|
19
24
|
);
|
|
20
25
|
}
|
package/src/core/AudioNode.ts
CHANGED
|
@@ -39,7 +39,11 @@ export default class AudioNode {
|
|
|
39
39
|
return destination;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
public disconnect(destination?: AudioNode): void {
|
|
43
|
-
|
|
42
|
+
public disconnect(destination?: AudioNode | AudioParam): void {
|
|
43
|
+
if (destination instanceof AudioParam) {
|
|
44
|
+
this.node.disconnect(destination.audioParam);
|
|
45
|
+
} else {
|
|
46
|
+
this.node.disconnect(destination?.node);
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { IAudioScheduledSourceNode } from '../interfaces';
|
|
2
2
|
import AudioNode from './AudioNode';
|
|
3
3
|
import { InvalidStateError, RangeError } from '../errors';
|
|
4
|
-
import {
|
|
4
|
+
import { OnEndedEventType } from '../events/types';
|
|
5
5
|
import { AudioEventEmitter } from '../events';
|
|
6
6
|
|
|
7
7
|
export default class AudioScheduledSourceNode extends AudioNode {
|
|
8
8
|
protected hasBeenStarted: boolean = false;
|
|
9
|
-
|
|
9
|
+
protected readonly audioEventEmitter = new AudioEventEmitter(
|
|
10
10
|
global.AudioEventEmitter
|
|
11
11
|
);
|
|
12
12
|
|
|
@@ -42,7 +42,7 @@ export default class AudioScheduledSourceNode extends AudioNode {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// eslint-disable-next-line accessor-pairs
|
|
45
|
-
public set onended(callback: (event:
|
|
45
|
+
public set onended(callback: (event: OnEndedEventType) => void) {
|
|
46
46
|
const subscription = this.audioEventEmitter.addAudioEventListener(
|
|
47
47
|
'ended',
|
|
48
48
|
callback
|
|
@@ -13,6 +13,7 @@ import AudioBufferSourceNode from './AudioBufferSourceNode';
|
|
|
13
13
|
import AudioBuffer from './AudioBuffer';
|
|
14
14
|
import PeriodicWave from './PeriodicWave';
|
|
15
15
|
import AnalyserNode from './AnalyserNode';
|
|
16
|
+
import AudioBufferQueueSourceNode from './AudioBufferQueueSourceNode';
|
|
16
17
|
import { InvalidAccessError, NotSupportedError } from '../errors';
|
|
17
18
|
|
|
18
19
|
export default class BaseAudioContext {
|
|
@@ -61,6 +62,13 @@ export default class BaseAudioContext {
|
|
|
61
62
|
);
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
createBufferQueueSource(): AudioBufferQueueSourceNode {
|
|
66
|
+
return new AudioBufferQueueSourceNode(
|
|
67
|
+
this,
|
|
68
|
+
this.context.createBufferQueueSource()
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
createBuffer(
|
|
65
73
|
numOfChannels: number,
|
|
66
74
|
length: number,
|
package/src/events/types.ts
CHANGED
|
@@ -6,9 +6,15 @@ export interface EventTypeWithValue {
|
|
|
6
6
|
value: number;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface OnEndedEventType {
|
|
10
10
|
value: number;
|
|
11
11
|
state: 'stopped' | 'ended';
|
|
12
|
+
bufferId: number | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface OnPositionChangedEventType {
|
|
16
|
+
value: number;
|
|
17
|
+
bufferId: number;
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
interface OnInterruptionEventType {
|
|
@@ -17,10 +23,18 @@ interface OnInterruptionEventType {
|
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
interface OnRouteChangeEventType {
|
|
20
|
-
reason:
|
|
26
|
+
reason:
|
|
27
|
+
| 'Unknown'
|
|
28
|
+
| 'Override'
|
|
29
|
+
| 'CategoryChange'
|
|
30
|
+
| 'WakeFromSleep'
|
|
31
|
+
| 'NewDeviceAvailable'
|
|
32
|
+
| 'OldDeviceUnavailable'
|
|
33
|
+
| 'ConfigurationChange'
|
|
34
|
+
| 'NoSuitableRouteForCategory';
|
|
21
35
|
}
|
|
22
36
|
|
|
23
|
-
interface
|
|
37
|
+
interface RemoteCommandEvents {
|
|
24
38
|
remotePlay: EventEmptyType;
|
|
25
39
|
remotePause: EventEmptyType;
|
|
26
40
|
remoteStop: EventEmptyType;
|
|
@@ -28,15 +42,18 @@ interface SystemEvents {
|
|
|
28
42
|
remoteChangePlaybackRate: EventTypeWithValue;
|
|
29
43
|
remoteNextTrack: EventEmptyType;
|
|
30
44
|
remotePreviousTrack: EventEmptyType;
|
|
31
|
-
remoteSkipForward:
|
|
32
|
-
remoteSkipBackward:
|
|
33
|
-
remoteSeekForward:
|
|
34
|
-
remoteSeekBackward:
|
|
45
|
+
remoteSkipForward: EventTypeWithValue;
|
|
46
|
+
remoteSkipBackward: EventTypeWithValue;
|
|
47
|
+
remoteSeekForward: EventEmptyType;
|
|
48
|
+
remoteSeekBackward: EventEmptyType;
|
|
35
49
|
remoteChangePlaybackPosition: EventTypeWithValue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type SystemEvents = RemoteCommandEvents & {
|
|
36
53
|
volumeChange: EventTypeWithValue;
|
|
37
54
|
interruption: OnInterruptionEventType;
|
|
38
55
|
routeChange: OnRouteChangeEventType;
|
|
39
|
-
}
|
|
56
|
+
};
|
|
40
57
|
|
|
41
58
|
export interface OnAudioReadyEventType {
|
|
42
59
|
buffer: AudioBuffer;
|
|
@@ -45,14 +62,17 @@ export interface OnAudioReadyEventType {
|
|
|
45
62
|
}
|
|
46
63
|
|
|
47
64
|
interface AudioAPIEvents {
|
|
48
|
-
ended:
|
|
65
|
+
ended: OnEndedEventType;
|
|
49
66
|
audioReady: OnAudioReadyEventType;
|
|
67
|
+
positionChanged: OnPositionChangedEventType;
|
|
50
68
|
audioError: EventEmptyType; // to change
|
|
51
69
|
systemStateChanged: EventEmptyType; // to change
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
type AudioEvents = SystemEvents & AudioAPIEvents;
|
|
55
73
|
|
|
74
|
+
export type RemoteCommandEventName = keyof RemoteCommandEvents;
|
|
75
|
+
|
|
56
76
|
export type SystemEventName = keyof SystemEvents;
|
|
57
77
|
export type SystemEventCallback<Name extends SystemEventName> = (
|
|
58
78
|
event: SystemEvents[Name]
|
|
@@ -6,9 +6,12 @@ export default function useSystemVolume() {
|
|
|
6
6
|
|
|
7
7
|
useEffect(() => {
|
|
8
8
|
AudioManager.observeVolumeChanges(true);
|
|
9
|
-
const listener = AudioManager.
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const listener = AudioManager.addSystemEventListener(
|
|
10
|
+
'volumeChange',
|
|
11
|
+
(e) => {
|
|
12
|
+
setVolume(parseFloat(e.value.toFixed(2)));
|
|
13
|
+
}
|
|
14
|
+
);
|
|
12
15
|
return () => {
|
|
13
16
|
listener?.remove();
|
|
14
17
|
|
package/src/interfaces.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface IBaseAudioContext {
|
|
|
19
19
|
createStereoPanner(): IStereoPannerNode;
|
|
20
20
|
createBiquadFilter: () => IBiquadFilterNode;
|
|
21
21
|
createBufferSource: (pitchCorrection: boolean) => IAudioBufferSourceNode;
|
|
22
|
+
createBufferQueueSource: () => IAudioBufferQueueSourceNode;
|
|
22
23
|
createBuffer: (
|
|
23
24
|
channels: number,
|
|
24
25
|
length: number,
|
|
@@ -109,6 +110,23 @@ export interface IAudioBufferSourceNode extends IAudioScheduledSourceNode {
|
|
|
109
110
|
start: (when?: number, offset?: number, duration?: number) => void;
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
export interface IAudioBufferQueueSourceNode extends IAudioScheduledSourceNode {
|
|
114
|
+
detune: IAudioParam;
|
|
115
|
+
playbackRate: IAudioParam;
|
|
116
|
+
|
|
117
|
+
enqueueBuffer: (
|
|
118
|
+
audioBuffer: IAudioBuffer,
|
|
119
|
+
bufferId: number,
|
|
120
|
+
isLastBuffer: boolean
|
|
121
|
+
) => void;
|
|
122
|
+
start: (when?: number, offset?: number) => void;
|
|
123
|
+
|
|
124
|
+
// passing subscriptionId(uint_64 in cpp, string in js) to the cpp
|
|
125
|
+
onPositionChanged: string;
|
|
126
|
+
// set how often the onPositionChanged event is called
|
|
127
|
+
onPositionChangedInterval: number;
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
export interface IAudioBuffer {
|
|
113
131
|
readonly length: number;
|
|
114
132
|
readonly duration: number;
|
|
@@ -5,9 +5,28 @@ import {
|
|
|
5
5
|
withInfoPlist,
|
|
6
6
|
withAndroidManifest,
|
|
7
7
|
} from '@expo/config-plugins';
|
|
8
|
-
|
|
9
8
|
const pkg = require('react-native-audio-api/package.json');
|
|
10
9
|
|
|
10
|
+
interface Options {
|
|
11
|
+
iosBackgroundMode: boolean;
|
|
12
|
+
androidForegroundService: boolean;
|
|
13
|
+
androidFSPermissions: string[];
|
|
14
|
+
androidFSTypes: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const withDefaultOptions = (options: Partial<Options>): Options => {
|
|
18
|
+
return {
|
|
19
|
+
iosBackgroundMode: true,
|
|
20
|
+
androidForegroundService: true,
|
|
21
|
+
androidFSPermissions: [
|
|
22
|
+
'android.permission.FOREGROUND_SERVICE',
|
|
23
|
+
'android.permission.WAKE_LOCK',
|
|
24
|
+
],
|
|
25
|
+
androidFSTypes: ['mediaPlayback'],
|
|
26
|
+
...options,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
11
30
|
const withBackgroundAudio: ConfigPlugin = (config) => {
|
|
12
31
|
return withInfoPlist(config, (iosConfig) => {
|
|
13
32
|
iosConfig.modResults.UIBackgroundModes = [
|
|
@@ -20,18 +39,20 @@ const withBackgroundAudio: ConfigPlugin = (config) => {
|
|
|
20
39
|
});
|
|
21
40
|
};
|
|
22
41
|
|
|
23
|
-
const withAndroidPermissions: ConfigPlugin<
|
|
24
|
-
|
|
25
|
-
|
|
42
|
+
const withAndroidPermissions: ConfigPlugin<Options> = (
|
|
43
|
+
config,
|
|
44
|
+
{ androidFSPermissions }: Options
|
|
45
|
+
) => {
|
|
26
46
|
return AndroidConfig.Permissions.withPermissions(
|
|
27
47
|
config,
|
|
28
48
|
androidFSPermissions
|
|
29
49
|
);
|
|
30
50
|
};
|
|
31
51
|
|
|
32
|
-
const withForegroundService: ConfigPlugin<
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
const withForegroundService: ConfigPlugin<Options> = (
|
|
53
|
+
config,
|
|
54
|
+
{ androidFSTypes }: Options
|
|
55
|
+
) => {
|
|
35
56
|
return withAndroidManifest(config, (mod) => {
|
|
36
57
|
const manifest = mod.modResults;
|
|
37
58
|
const mainApplication =
|
|
@@ -59,30 +80,16 @@ const withForegroundService: ConfigPlugin<{
|
|
|
59
80
|
});
|
|
60
81
|
};
|
|
61
82
|
|
|
62
|
-
const withAudioAPI: ConfigPlugin<{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
androidFSTypes?: string[];
|
|
67
|
-
}> = (
|
|
68
|
-
config,
|
|
69
|
-
{
|
|
70
|
-
iosBackgroundMode = true,
|
|
71
|
-
androidForegroundService = true,
|
|
72
|
-
androidFSPermissions = [],
|
|
73
|
-
androidFSTypes = [],
|
|
74
|
-
}
|
|
75
|
-
) => {
|
|
76
|
-
if (iosBackgroundMode) {
|
|
83
|
+
const withAudioAPI: ConfigPlugin<Options> = (config, optionsIn) => {
|
|
84
|
+
const options = withDefaultOptions(optionsIn ?? {});
|
|
85
|
+
|
|
86
|
+
if (options.iosBackgroundMode) {
|
|
77
87
|
config = withBackgroundAudio(config);
|
|
78
88
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
config = withForegroundService(config, {
|
|
84
|
-
androidFSTypes,
|
|
85
|
-
});
|
|
89
|
+
|
|
90
|
+
if (options.androidForegroundService) {
|
|
91
|
+
config = withAndroidPermissions(config, options);
|
|
92
|
+
config = withForegroundService(config, options);
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
return config;
|
|
@@ -5,20 +5,28 @@ import { PermissionStatus } from '../system/types';
|
|
|
5
5
|
|
|
6
6
|
interface Spec extends TurboModule {
|
|
7
7
|
install(): boolean;
|
|
8
|
+
getDevicePreferredSampleRate(): number;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}): void;
|
|
12
|
-
resetLockScreenInfo(): void;
|
|
13
|
-
enableRemoteCommand(name: string, enabled: boolean): void;
|
|
10
|
+
// AVAudioSession management
|
|
11
|
+
setAudioSessionActivity(enabled: boolean): Promise<boolean>;
|
|
14
12
|
setAudioSessionOptions(
|
|
15
13
|
category: string,
|
|
16
14
|
mode: string,
|
|
17
15
|
options: Array<string>
|
|
18
16
|
): void;
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
// Lock Screen Info
|
|
19
|
+
setLockScreenInfo(info: {
|
|
20
|
+
[key: string]: string | boolean | number | undefined;
|
|
21
|
+
}): void;
|
|
22
|
+
resetLockScreenInfo(): void;
|
|
23
|
+
|
|
24
|
+
// Remote commands, system events and interruptions
|
|
25
|
+
enableRemoteCommand(name: string, enabled: boolean): void;
|
|
20
26
|
observeAudioInterruptions(enabled: boolean): void;
|
|
21
27
|
observeVolumeChanges(enabled: boolean): void;
|
|
28
|
+
|
|
29
|
+
// Permissions
|
|
22
30
|
requestRecordingPermissions(): Promise<PermissionStatus>;
|
|
23
31
|
checkRecordingPermissions(): Promise<PermissionStatus>;
|
|
24
32
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { SessionOptions, LockScreenInfo, PermissionStatus } from './types';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SystemEventName,
|
|
4
|
+
SystemEventCallback,
|
|
5
|
+
RemoteCommandEventName,
|
|
6
|
+
} from '../events/types';
|
|
3
7
|
import { NativeAudioAPIModule } from '../specs';
|
|
4
8
|
import { AudioEventEmitter, AudioEventSubscription } from '../events';
|
|
5
9
|
|
|
@@ -19,12 +23,12 @@ class AudioManager {
|
|
|
19
23
|
this.audioEventEmitter = new AudioEventEmitter(global.AudioEventEmitter);
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
NativeAudioAPIModule!.
|
|
26
|
+
getDevicePreferredSampleRate(): number {
|
|
27
|
+
return NativeAudioAPIModule!.getDevicePreferredSampleRate();
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
NativeAudioAPIModule!.
|
|
30
|
+
setAudioSessionActivity(enabled: boolean): Promise<boolean> {
|
|
31
|
+
return NativeAudioAPIModule!.setAudioSessionActivity(enabled);
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
setAudioSessionOptions(options: SessionOptions) {
|
|
@@ -35,8 +39,12 @@ class AudioManager {
|
|
|
35
39
|
);
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
setLockScreenInfo(info: LockScreenInfo) {
|
|
43
|
+
NativeAudioAPIModule!.setLockScreenInfo(info);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
resetLockScreenInfo() {
|
|
47
|
+
NativeAudioAPIModule!.resetLockScreenInfo();
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
observeAudioInterruptions(enabled: boolean) {
|
|
@@ -47,17 +55,14 @@ class AudioManager {
|
|
|
47
55
|
NativeAudioAPIModule!.observeVolumeChanges(enabled);
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
name: Name,
|
|
52
|
-
callback?: SystemEventCallback<Name>,
|
|
53
|
-
enabled = true
|
|
54
|
-
): AudioEventSubscription | null {
|
|
58
|
+
enableRemoteCommand(name: RemoteCommandEventName, enabled: boolean) {
|
|
55
59
|
NativeAudioAPIModule!.enableRemoteCommand(name, enabled);
|
|
60
|
+
}
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
addSystemEventListener<Name extends SystemEventName>(
|
|
63
|
+
name: Name,
|
|
64
|
+
callback: SystemEventCallback<Name>
|
|
65
|
+
): AudioEventSubscription {
|
|
61
66
|
return this.audioEventEmitter.addAudioEventListener(name, callback);
|
|
62
67
|
}
|
|
63
68
|
|
package/src/types.ts
CHANGED
|
@@ -210,7 +210,8 @@ export default class AudioBufferSourceNode<
|
|
|
210
210
|
-1200,
|
|
211
211
|
1200,
|
|
212
212
|
0
|
|
213
|
-
)
|
|
213
|
+
),
|
|
214
|
+
context
|
|
214
215
|
);
|
|
215
216
|
|
|
216
217
|
this.playbackRate = new AudioParam(
|
|
@@ -221,11 +222,15 @@ export default class AudioBufferSourceNode<
|
|
|
221
222
|
0,
|
|
222
223
|
Infinity,
|
|
223
224
|
1
|
|
224
|
-
)
|
|
225
|
+
),
|
|
226
|
+
context
|
|
225
227
|
);
|
|
226
228
|
} else {
|
|
227
|
-
this.detune = new AudioParam((node as DefaultSource).detune);
|
|
228
|
-
this.playbackRate = new AudioParam(
|
|
229
|
+
this.detune = new AudioParam((node as DefaultSource).detune, context);
|
|
230
|
+
this.playbackRate = new AudioParam(
|
|
231
|
+
(node as DefaultSource).playbackRate,
|
|
232
|
+
context
|
|
233
|
+
);
|
|
229
234
|
}
|
|
230
235
|
}
|
|
231
236
|
|
|
@@ -24,14 +24,18 @@ export default class AudioContext implements BaseAudioContext {
|
|
|
24
24
|
readonly destination: AudioDestinationNode;
|
|
25
25
|
readonly sampleRate: number;
|
|
26
26
|
|
|
27
|
-
constructor(options?: AudioContextOptions) {
|
|
28
|
-
if (
|
|
27
|
+
constructor(options?: AudioContextOptions, _initSuspended: boolean = false) {
|
|
28
|
+
if (
|
|
29
|
+
options &&
|
|
30
|
+
options.sampleRate &&
|
|
31
|
+
(options.sampleRate < 8000 || options.sampleRate > 96000)
|
|
32
|
+
) {
|
|
29
33
|
throw new NotSupportedError(
|
|
30
34
|
`The provided sampleRate is not supported: ${options.sampleRate}`
|
|
31
35
|
);
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
this.context = new window.AudioContext(options);
|
|
38
|
+
this.context = new window.AudioContext({ sampleRate: options?.sampleRate });
|
|
35
39
|
|
|
36
40
|
this.sampleRate = this.context.sampleRate;
|
|
37
41
|
this.destination = new AudioDestinationNode(this, this.context.destination);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BaseAudioContext from './BaseAudioContext';
|
|
2
2
|
import { ChannelCountMode, ChannelInterpretation } from '../types';
|
|
3
|
+
import AudioParam from './AudioParam';
|
|
3
4
|
|
|
4
5
|
export default class AudioNode {
|
|
5
6
|
readonly context: BaseAudioContext;
|
|
@@ -21,12 +22,18 @@ export default class AudioNode {
|
|
|
21
22
|
this.channelInterpretation = this.node.channelInterpretation;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
public connect(destination: AudioNode): AudioNode {
|
|
25
|
+
public connect(destination: AudioNode | AudioParam): AudioNode | AudioParam {
|
|
25
26
|
if (this.context !== destination.context) {
|
|
26
|
-
throw new Error(
|
|
27
|
+
throw new Error(
|
|
28
|
+
'Source and destination are from different BaseAudioContexts'
|
|
29
|
+
);
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
if (destination instanceof AudioParam) {
|
|
33
|
+
this.node.connect(destination.param);
|
|
34
|
+
} else {
|
|
35
|
+
this.node.connect(destination.node);
|
|
36
|
+
}
|
|
30
37
|
|
|
31
38
|
return destination;
|
|
32
39
|
}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { RangeError, InvalidStateError } from '../errors';
|
|
2
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
2
3
|
|
|
3
4
|
export default class AudioParam {
|
|
4
5
|
readonly defaultValue: number;
|
|
5
6
|
readonly minValue: number;
|
|
6
7
|
readonly maxValue: number;
|
|
8
|
+
readonly context: BaseAudioContext;
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
readonly param: globalThis.AudioParam;
|
|
9
11
|
|
|
10
|
-
constructor(param: globalThis.AudioParam) {
|
|
12
|
+
constructor(param: globalThis.AudioParam, context: BaseAudioContext) {
|
|
11
13
|
this.param = param;
|
|
12
14
|
this.defaultValue = param.defaultValue;
|
|
13
15
|
this.minValue = param.minValue;
|
|
14
16
|
this.maxValue = param.maxValue;
|
|
17
|
+
this.context = context;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
public get value(): number {
|
|
@@ -15,10 +15,10 @@ export default class BiquadFilterNode extends AudioNode {
|
|
|
15
15
|
biquadFilter: globalThis.BiquadFilterNode
|
|
16
16
|
) {
|
|
17
17
|
super(context, biquadFilter);
|
|
18
|
-
this.frequency = new AudioParam(biquadFilter.frequency);
|
|
19
|
-
this.detune = new AudioParam(biquadFilter.detune);
|
|
20
|
-
this.Q = new AudioParam(biquadFilter.Q);
|
|
21
|
-
this.gain = new AudioParam(biquadFilter.gain);
|
|
18
|
+
this.frequency = new AudioParam(biquadFilter.frequency, context);
|
|
19
|
+
this.detune = new AudioParam(biquadFilter.detune, context);
|
|
20
|
+
this.Q = new AudioParam(biquadFilter.Q, context);
|
|
21
|
+
this.gain = new AudioParam(biquadFilter.gain, context);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
public get type(): BiquadFilterType {
|
|
@@ -12,8 +12,8 @@ export default class OscillatorNode extends AudioScheduledSourceNode {
|
|
|
12
12
|
constructor(context: BaseAudioContext, node: globalThis.OscillatorNode) {
|
|
13
13
|
super(context, node);
|
|
14
14
|
|
|
15
|
-
this.detune = new AudioParam(node.detune);
|
|
16
|
-
this.frequency = new AudioParam(node.frequency);
|
|
15
|
+
this.detune = new AudioParam(node.detune, context);
|
|
16
|
+
this.frequency = new AudioParam(node.frequency, context);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
public get type(): OscillatorType {
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
android:width="24dp"
|
|
3
|
-
android:height="24dp"
|
|
4
|
-
android:viewportWidth="24.0"
|
|
5
|
-
android:viewportHeight="24.0">
|
|
6
|
-
<path
|
|
7
|
-
android:fillColor="#FFFFFFFF"
|
|
8
|
-
android:pathData="M12,5L12,1L7,6l5,5L12,7c3.3,0 6,2.7 6,6s-2.7,6 -6,6 -6,-2.7 -6,-6L4,13c0,4.4 3.6,8 8,8s8,-3.6 8,-8 -3.6,-8 -8,-8zM10.7,13.9l0.2,-2.2h2.4v0.7h-1.7l-0.1,0.9s0.1,0 0.1,-0.1 0.1,0 0.1,-0.1 0.1,0 0.2,0h0.2c0.2,0 0.4,0 0.5,0.1s0.3,0.2 0.4,0.3 0.2,0.3 0.3,0.5 0.1,0.4 0.1,0.6c0,0.2 0,0.4 -0.1,0.5s-0.1,0.3 -0.3,0.5 -0.3,0.2 -0.4,0.3 -0.4,0.1 -0.6,0.1c-0.2,0 -0.4,0 -0.5,-0.1s-0.3,-0.1 -0.5,-0.2 -0.2,-0.2 -0.3,-0.4 -0.1,-0.3 -0.1,-0.5h0.8c0,0.2 0.1,0.3 0.2,0.4s0.2,0.1 0.4,0.1c0.1,0 0.2,0 0.3,-0.1l0.2,-0.2s0.1,-0.2 0.1,-0.3v-0.6l-0.1,-0.2 -0.2,-0.2s-0.2,-0.1 -0.3,-0.1h-0.2s-0.1,0 -0.2,0.1 -0.1,0 -0.1,0.1 -0.1,0.1 -0.1,0.1h-0.7z"/>
|
|
9
|
-
</vector>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
android:width="24dp"
|
|
3
|
-
android:height="24dp"
|
|
4
|
-
android:viewportWidth="24.0"
|
|
5
|
-
android:viewportHeight="24.0">
|
|
6
|
-
<path
|
|
7
|
-
android:fillColor="#FFFFFFFF"
|
|
8
|
-
android:pathData="M4,13c0,4.4 3.6,8 8,8s8,-3.6 8,-8h-2c0,3.3 -2.7,6 -6,6s-6,-2.7 -6,-6 2.7,-6 6,-6v4l5,-5 -5,-5v4c-4.4,0 -8,3.6 -8,8zM10.7,13.9l0.2,-2.2h2.4v0.7h-1.7l-0.1,0.9s0.1,0 0.1,-0.1 0.1,0 0.1,-0.1 0.1,0 0.2,0h0.2c0.2,0 0.4,0 0.5,0.1s0.3,0.2 0.4,0.3 0.2,0.3 0.3,0.5 0.1,0.4 0.1,0.6c0,0.2 0,0.4 -0.1,0.5s-0.1,0.3 -0.3,0.5 -0.3,0.2 -0.5,0.3 -0.4,0.1 -0.6,0.1c-0.2,0 -0.4,0 -0.5,-0.1s-0.3,-0.1 -0.5,-0.2 -0.2,-0.2 -0.3,-0.4 -0.1,-0.3 -0.1,-0.5h0.8c0,0.2 0.1,0.3 0.2,0.4s0.2,0.1 0.4,0.1c0.1,0 0.2,0 0.3,-0.1l0.2,-0.2s0.1,-0.2 0.1,-0.3v-0.6l-0.1,-0.2 -0.2,-0.2s-0.2,-0.1 -0.3,-0.1h-0.2s-0.1,0 -0.2,0.1 -0.1,0 -0.1,0.1 -0.1,0.1 -0.1,0.1h-0.6z"/>
|
|
9
|
-
</vector>
|