react-native-audio-api 0.11.4 → 0.11.6
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/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +40 -14
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +2 -1
- package/ios/audioapi/ios/AudioAPIModule.mm +5 -0
- package/ios/audioapi/ios/core/NativeAudioRecorder.m +1 -1
- package/ios/audioapi/ios/core/utils/IOSFileWriter.mm +1 -1
- package/ios/audioapi/ios/system/AudioEngine.h +1 -1
- package/ios/audioapi/ios/system/AudioEngine.mm +1 -3
- package/lib/commonjs/core/AudioDecoder.js +42 -22
- package/lib/commonjs/core/AudioDecoder.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/module/core/AudioDecoder.js +43 -23
- package/lib/module/core/AudioDecoder.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/typescript/core/AudioDecoder.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts +1 -0
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/AudioDecoder.ts +70 -36
- package/src/specs/NativeAudioAPIModule.ts +1 -0
|
@@ -29,14 +29,16 @@ class AudioAPIModule(
|
|
|
29
29
|
|
|
30
30
|
val reactContext: WeakReference<ReactApplicationContext> = WeakReference(reactContext)
|
|
31
31
|
|
|
32
|
-
private
|
|
32
|
+
private lateinit var mHybridData: HybridData
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
@OptIn(markerClass = [FrameworkAPI::class])
|
|
35
|
+
private external fun initHybrid(
|
|
35
36
|
workletsModule: Any?,
|
|
36
37
|
jsContext: Long,
|
|
37
38
|
callInvoker: CallInvokerHolderImpl,
|
|
38
39
|
): HybridData
|
|
39
40
|
|
|
41
|
+
@OptIn(markerClass = [FrameworkAPI::class])
|
|
40
42
|
private external fun injectJSIBindings()
|
|
41
43
|
|
|
42
44
|
external fun invokeHandlerWithEventNameAndEventBody(
|
|
@@ -47,23 +49,29 @@ class AudioAPIModule(
|
|
|
47
49
|
init {
|
|
48
50
|
try {
|
|
49
51
|
System.loadLibrary("react-native-audio-api")
|
|
50
|
-
val jsCallInvokerHolder = reactContext.jsCallInvokerHolder as CallInvokerHolderImpl
|
|
51
|
-
|
|
52
|
-
var workletsModule: Any? = null
|
|
53
|
-
if (BuildConfig.RN_AUDIO_API_ENABLE_WORKLETS) {
|
|
54
|
-
try {
|
|
55
|
-
workletsModule = reactContext.getNativeModule("WorkletsModule")
|
|
56
|
-
} catch (ex: Exception) {
|
|
57
|
-
throw RuntimeException("WorkletsModule not found - make sure react-native-worklets is properly installed")
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
mHybridData = initHybrid(workletsModule, reactContext.javaScriptContextHolder!!.get(), jsCallInvokerHolder)
|
|
61
52
|
} catch (exception: UnsatisfiedLinkError) {
|
|
62
53
|
throw RuntimeException("Could not load native module AudioAPIModule", exception)
|
|
63
54
|
}
|
|
64
55
|
}
|
|
65
56
|
|
|
57
|
+
@OptIn(markerClass = [FrameworkAPI::class])
|
|
66
58
|
override fun install(): Boolean {
|
|
59
|
+
val context = reactContext.get() ?: return false
|
|
60
|
+
context.assertOnJSQueueThread()
|
|
61
|
+
|
|
62
|
+
val jsContext = context.javaScriptContextHolder!!.get()
|
|
63
|
+
val jsCallInvokerHolder = context.jsCallInvokerHolder as CallInvokerHolderImpl
|
|
64
|
+
|
|
65
|
+
var workletsModule: Any? = null
|
|
66
|
+
if (BuildConfig.RN_AUDIO_API_ENABLE_WORKLETS) {
|
|
67
|
+
try {
|
|
68
|
+
workletsModule = context.getNativeModule("WorkletsModule")
|
|
69
|
+
} catch (_: Exception) {
|
|
70
|
+
throw RuntimeException("WorkletsModule not found - make sure react-native-worklets is properly installed")
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
mHybridData = initHybrid(workletsModule, jsContext, jsCallInvokerHolder)
|
|
67
75
|
MediaSessionManager.initialize(WeakReference(this), reactContext)
|
|
68
76
|
NativeFileInfo.initialize(reactContext)
|
|
69
77
|
injectJSIBindings()
|
|
@@ -226,8 +234,26 @@ class AudioAPIModule(
|
|
|
226
234
|
|
|
227
235
|
val isActive = MediaSessionManager.isNotificationActive(key)
|
|
228
236
|
promise?.resolve(isActive)
|
|
229
|
-
} catch (
|
|
237
|
+
} catch (_: Exception) {
|
|
230
238
|
promise?.resolve(false)
|
|
231
239
|
}
|
|
232
240
|
}
|
|
241
|
+
|
|
242
|
+
override fun resolveAndroidReleaseAsset(assetPath: String?): String? {
|
|
243
|
+
val context = reactContext.get() ?: return null
|
|
244
|
+
val packageName = context.packageName
|
|
245
|
+
|
|
246
|
+
val resourceId =
|
|
247
|
+
context.resources.getIdentifier(
|
|
248
|
+
assetPath,
|
|
249
|
+
"raw",
|
|
250
|
+
packageName,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
return if (resourceId != 0) {
|
|
254
|
+
"android.resource://$packageName/$resourceId"
|
|
255
|
+
} else {
|
|
256
|
+
null
|
|
257
|
+
}
|
|
258
|
+
}
|
|
233
259
|
}
|
|
@@ -61,7 +61,8 @@ JSI_HOST_FUNCTION_IMPL(BiquadFilterNodeHostObject, getFrequencyResponse) {
|
|
|
61
61
|
auto arrayBufferFrequency =
|
|
62
62
|
args[0].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
|
|
63
63
|
auto frequencyArray = reinterpret_cast<float *>(arrayBufferFrequency.data(runtime));
|
|
64
|
-
|
|
64
|
+
// arrayBufferFrequency is Float32Array from JS and size is in bytes thus hardcoded division by 4
|
|
65
|
+
auto length = static_cast<size_t>(arrayBufferFrequency.size(runtime) / 4);
|
|
65
66
|
|
|
66
67
|
auto arrayBufferMag =
|
|
67
68
|
args[1].getObject(runtime).getPropertyAsObject(runtime, "buffer").getArrayBuffer(runtime);
|
|
@@ -118,6 +118,11 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getDevicePreferredSampleRate)
|
|
|
118
118
|
return [self.audioSessionManager getDevicePreferredSampleRate];
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(resolveAndroidReleaseAsset : (NSString *)assetPath)
|
|
122
|
+
{
|
|
123
|
+
return NULL; //noop
|
|
124
|
+
}
|
|
125
|
+
|
|
121
126
|
RCT_EXPORT_METHOD(
|
|
122
127
|
setAudioSessionActivity : (BOOL)enabled resolve : (RCTPromiseResolveBlock)
|
|
123
128
|
resolve reject : (RCTPromiseRejectBlock)reject)
|
|
@@ -88,7 +88,7 @@ static inline uint32_t nextPowerOfTwo(uint32_t x)
|
|
|
88
88
|
// Currently we are restarting because we do not see any significant performance issue and case when
|
|
89
89
|
// you will need to start and stop recorder very frequently
|
|
90
90
|
[audioEngine stopIfNecessary];
|
|
91
|
-
[audioEngine attachInputNode:self.sinkNode];
|
|
91
|
+
[audioEngine attachInputNode:self.sinkNode format:self.getInputFormat];
|
|
92
92
|
[audioEngine startIfNecessary];
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -135,7 +135,7 @@ CloseFileResult IOSFileWriter::closeFile()
|
|
|
135
135
|
fileURL_ = nil;
|
|
136
136
|
framesWritten_.store(0, std::memory_order_release);
|
|
137
137
|
|
|
138
|
-
return CloseFileResult::Ok(std::make_tuple(
|
|
138
|
+
return CloseFileResult::Ok(std::make_tuple(fileSizeBytesMb, fileDuration));
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -29,7 +29,7 @@ typedef NS_ENUM(NSInteger, AudioEngineState) {
|
|
|
29
29
|
- (NSString *)attachSourceNode:(AVAudioSourceNode *)sourceNode format:(AVAudioFormat *)format;
|
|
30
30
|
- (void)detachSourceNodeWithId:(NSString *)sourceNodeId;
|
|
31
31
|
|
|
32
|
-
- (void)attachInputNode:(AVAudioSinkNode *)inputNode;
|
|
32
|
+
- (void)attachInputNode:(AVAudioSinkNode *)inputNode format:(AVAudioFormat *)format;
|
|
33
33
|
- (void)detachInputNode;
|
|
34
34
|
|
|
35
35
|
- (void)onInterruptionBegin;
|
|
@@ -70,11 +70,9 @@ static AudioEngine *_sharedInstance = nil;
|
|
|
70
70
|
[self.sourceFormats removeObjectForKey:sourceNodeId];
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
- (void)attachInputNode:(AVAudioSinkNode *)inputNode
|
|
73
|
+
- (void)attachInputNode:(AVAudioSinkNode *)inputNode format:(AVAudioFormat *)format
|
|
74
74
|
{
|
|
75
75
|
self.inputNode = inputNode;
|
|
76
|
-
AVAudioFormat *format = [self.audioEngine.inputNode inputFormatForBus:0];
|
|
77
|
-
|
|
78
76
|
[self.audioEngine attachNode:inputNode];
|
|
79
77
|
[self.audioEngine connect:self.audioEngine.inputNode to:inputNode format:format];
|
|
80
78
|
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.decodeAudioData = decodeAudioData;
|
|
7
7
|
exports.decodePCMInBase64 = decodePCMInBase64;
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
|
+
var _specs = require("../specs");
|
|
9
10
|
var _errors = require("../errors");
|
|
10
11
|
var _paths = require("../utils/paths");
|
|
11
12
|
var _AudioBuffer = _interopRequireDefault(require("./AudioBuffer"));
|
|
@@ -16,35 +17,54 @@ class AudioDecoder {
|
|
|
16
17
|
this.decoder = global.createAudioDecoder();
|
|
17
18
|
}
|
|
18
19
|
async decodeAudioDataImplementation(input, sampleRate, fetchOptions) {
|
|
20
|
+
const rate = sampleRate ?? 0;
|
|
19
21
|
if (input instanceof ArrayBuffer) {
|
|
20
|
-
|
|
21
|
-
return new _AudioBuffer.default(buffer);
|
|
22
|
+
return this.decodeFromArrayBuffer(input, rate);
|
|
22
23
|
}
|
|
23
|
-
const stringSource =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const stringSource = this.resolveStringSource(input);
|
|
25
|
+
this.assertSupportedStringSource(stringSource);
|
|
26
|
+
if ((0, _paths.isRemoteSource)(stringSource)) {
|
|
27
|
+
return this.decodeFromRemoteUrl(stringSource, rate, fetchOptions);
|
|
28
|
+
}
|
|
29
|
+
return this.decodeFromLocalFile(stringSource, rate);
|
|
30
|
+
}
|
|
31
|
+
async decodeFromArrayBuffer(arrayBuffer, sampleRate) {
|
|
32
|
+
const buffer = await this.decoder.decodeWithMemoryBlock(
|
|
33
|
+
// @ts-ignore internal function
|
|
34
|
+
new Uint8Array(arrayBuffer), sampleRate);
|
|
35
|
+
return new _AudioBuffer.default(buffer);
|
|
36
|
+
}
|
|
37
|
+
resolveStringSource(input) {
|
|
38
|
+
return typeof input === 'number' ? _reactNative.Image.resolveAssetSource(input).uri : input;
|
|
39
|
+
}
|
|
40
|
+
assertSupportedStringSource(source) {
|
|
41
|
+
if (typeof source !== 'string') {
|
|
42
|
+
throw new TypeError('Input must be a module, uri or ArrayBuffer');
|
|
43
|
+
}
|
|
44
|
+
if ((0, _paths.isBase64Source)(source)) {
|
|
27
45
|
throw new _errors.AudioApiError('Base64 source decoding is not currently supported, to decode raw PCM base64 strings use decodePCMInBase64 method.');
|
|
28
46
|
}
|
|
29
|
-
|
|
30
|
-
// input is blob:...
|
|
31
|
-
if ((0, _paths.isDataBlobString)(stringSource)) {
|
|
47
|
+
if ((0, _paths.isDataBlobString)(source)) {
|
|
32
48
|
throw new _errors.AudioApiError('Data Blob string decoding is not currently supported.');
|
|
33
49
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
|
|
50
|
+
}
|
|
51
|
+
async decodeFromRemoteUrl(url, sampleRate, fetchOptions) {
|
|
52
|
+
const arrayBuffer = await fetch(url, fetchOptions).then(res => res.arrayBuffer());
|
|
53
|
+
return this.decodeFromArrayBuffer(arrayBuffer, sampleRate);
|
|
54
|
+
}
|
|
55
|
+
resolveLocalFilePath(stringSource) {
|
|
56
|
+
let filePath = stringSource.startsWith('file://') ? stringSource.replace('file://', '') : stringSource;
|
|
57
|
+
if (_reactNative.Platform.OS === 'android' && !__DEV__) {
|
|
58
|
+
filePath = _specs.NativeAudioAPIModule.resolveAndroidReleaseAsset(filePath);
|
|
59
|
+
if (!filePath) {
|
|
60
|
+
throw new _errors.AudioApiError('Failed to resolve asset for android release build.');
|
|
61
|
+
}
|
|
43
62
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
63
|
+
return filePath;
|
|
64
|
+
}
|
|
65
|
+
async decodeFromLocalFile(stringSource, sampleRate) {
|
|
66
|
+
const filePath = this.resolveLocalFilePath(stringSource);
|
|
67
|
+
const buffer = await this.decoder.decodeWithFilePath(filePath, sampleRate);
|
|
48
68
|
return new _AudioBuffer.default(buffer);
|
|
49
69
|
}
|
|
50
70
|
static getInstance() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_errors","_paths","_AudioBuffer","_interopRequireDefault","e","__esModule","default","AudioDecoder","instance","constructor","decoder","global","createAudioDecoder","decodeAudioDataImplementation","input","sampleRate","fetchOptions","ArrayBuffer","buffer","decodeWithMemoryBlock","Uint8Array","AudioBuffer","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_specs","_errors","_paths","_AudioBuffer","_interopRequireDefault","e","__esModule","default","AudioDecoder","instance","constructor","decoder","global","createAudioDecoder","decodeAudioDataImplementation","input","sampleRate","fetchOptions","rate","ArrayBuffer","decodeFromArrayBuffer","stringSource","resolveStringSource","assertSupportedStringSource","isRemoteSource","decodeFromRemoteUrl","decodeFromLocalFile","arrayBuffer","buffer","decodeWithMemoryBlock","Uint8Array","AudioBuffer","Image","resolveAssetSource","uri","source","TypeError","isBase64Source","AudioApiError","isDataBlobString","url","fetch","then","res","resolveLocalFilePath","filePath","startsWith","replace","Platform","OS","__DEV__","NativeAudioAPIModule","resolveAndroidReleaseAsset","decodeWithFilePath","getInstance","decodeAudioDataInstance","audioBuffer","decodePCMInBase64Instance","base64String","inputSampleRate","inputChannelCount","interleaved","decodeWithPCMInBase64","decodeAudioData","decodePCMInBase64","isInterleaved"],"sourceRoot":"../../../src","sources":["core/AudioDecoder.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Object","defineProperty","exports","value","NativeAudioAPIModule","_reactNative","require","TurboModuleRegistry","get"],"sourceRoot":"../../../src","sources":["specs/NativeAudioAPIModule.ts"],"mappings":"AAAA,YAAY;;AAACA,MAAA,CAAAC,cAAA,CAAAC,OAAA;EAAAC,KAAA;AAAA;AAAAD,OAAA,CAAAE,oBAAA;AAEb,IAAAC,YAAA,GAAAC,OAAA;
|
|
1
|
+
{"version":3,"names":["Object","defineProperty","exports","value","NativeAudioAPIModule","_reactNative","require","TurboModuleRegistry","get"],"sourceRoot":"../../../src","sources":["specs/NativeAudioAPIModule.ts"],"mappings":"AAAA,YAAY;;AAACA,MAAA,CAAAC,cAAA,CAAAC,OAAA;EAAAC,KAAA;AAAA;AAAAD,OAAA,CAAAE,oBAAA;AAEb,IAAAC,YAAA,GAAAC,OAAA;AA+CA,MAAMF,oBAAoB,GAAAF,OAAA,CAAAE,oBAAA,GAAGG,gCAAmB,CAACC,GAAG,CAAO,gBAAgB,CAAE","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { Image } from 'react-native';
|
|
3
|
+
import { Image, Platform } from 'react-native';
|
|
4
|
+
import { NativeAudioAPIModule } from "../specs/index.js";
|
|
4
5
|
import { AudioApiError } from "../errors/index.js";
|
|
5
6
|
import { isBase64Source, isDataBlobString, isRemoteSource } from "../utils/paths.js";
|
|
6
7
|
import AudioBuffer from "./AudioBuffer.js";
|
|
@@ -10,35 +11,54 @@ class AudioDecoder {
|
|
|
10
11
|
this.decoder = global.createAudioDecoder();
|
|
11
12
|
}
|
|
12
13
|
async decodeAudioDataImplementation(input, sampleRate, fetchOptions) {
|
|
14
|
+
const rate = sampleRate ?? 0;
|
|
13
15
|
if (input instanceof ArrayBuffer) {
|
|
14
|
-
|
|
15
|
-
return new AudioBuffer(buffer);
|
|
16
|
+
return this.decodeFromArrayBuffer(input, rate);
|
|
16
17
|
}
|
|
17
|
-
const stringSource =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const stringSource = this.resolveStringSource(input);
|
|
19
|
+
this.assertSupportedStringSource(stringSource);
|
|
20
|
+
if (isRemoteSource(stringSource)) {
|
|
21
|
+
return this.decodeFromRemoteUrl(stringSource, rate, fetchOptions);
|
|
22
|
+
}
|
|
23
|
+
return this.decodeFromLocalFile(stringSource, rate);
|
|
24
|
+
}
|
|
25
|
+
async decodeFromArrayBuffer(arrayBuffer, sampleRate) {
|
|
26
|
+
const buffer = await this.decoder.decodeWithMemoryBlock(
|
|
27
|
+
// @ts-ignore internal function
|
|
28
|
+
new Uint8Array(arrayBuffer), sampleRate);
|
|
29
|
+
return new AudioBuffer(buffer);
|
|
30
|
+
}
|
|
31
|
+
resolveStringSource(input) {
|
|
32
|
+
return typeof input === 'number' ? Image.resolveAssetSource(input).uri : input;
|
|
33
|
+
}
|
|
34
|
+
assertSupportedStringSource(source) {
|
|
35
|
+
if (typeof source !== 'string') {
|
|
36
|
+
throw new TypeError('Input must be a module, uri or ArrayBuffer');
|
|
37
|
+
}
|
|
38
|
+
if (isBase64Source(source)) {
|
|
21
39
|
throw new AudioApiError('Base64 source decoding is not currently supported, to decode raw PCM base64 strings use decodePCMInBase64 method.');
|
|
22
40
|
}
|
|
23
|
-
|
|
24
|
-
// input is blob:...
|
|
25
|
-
if (isDataBlobString(stringSource)) {
|
|
41
|
+
if (isDataBlobString(source)) {
|
|
26
42
|
throw new AudioApiError('Data Blob string decoding is not currently supported.');
|
|
27
43
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
44
|
+
}
|
|
45
|
+
async decodeFromRemoteUrl(url, sampleRate, fetchOptions) {
|
|
46
|
+
const arrayBuffer = await fetch(url, fetchOptions).then(res => res.arrayBuffer());
|
|
47
|
+
return this.decodeFromArrayBuffer(arrayBuffer, sampleRate);
|
|
48
|
+
}
|
|
49
|
+
resolveLocalFilePath(stringSource) {
|
|
50
|
+
let filePath = stringSource.startsWith('file://') ? stringSource.replace('file://', '') : stringSource;
|
|
51
|
+
if (Platform.OS === 'android' && !__DEV__) {
|
|
52
|
+
filePath = NativeAudioAPIModule.resolveAndroidReleaseAsset(filePath);
|
|
53
|
+
if (!filePath) {
|
|
54
|
+
throw new AudioApiError('Failed to resolve asset for android release build.');
|
|
55
|
+
}
|
|
37
56
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
57
|
+
return filePath;
|
|
58
|
+
}
|
|
59
|
+
async decodeFromLocalFile(stringSource, sampleRate) {
|
|
60
|
+
const filePath = this.resolveLocalFilePath(stringSource);
|
|
61
|
+
const buffer = await this.decoder.decodeWithFilePath(filePath, sampleRate);
|
|
42
62
|
return new AudioBuffer(buffer);
|
|
43
63
|
}
|
|
44
64
|
static getInstance() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Image","AudioApiError","isBase64Source","isDataBlobString","isRemoteSource","AudioBuffer","AudioDecoder","instance","constructor","decoder","global","createAudioDecoder","decodeAudioDataImplementation","input","sampleRate","fetchOptions","ArrayBuffer","buffer","decodeWithMemoryBlock","Uint8Array","
|
|
1
|
+
{"version":3,"names":["Image","Platform","NativeAudioAPIModule","AudioApiError","isBase64Source","isDataBlobString","isRemoteSource","AudioBuffer","AudioDecoder","instance","constructor","decoder","global","createAudioDecoder","decodeAudioDataImplementation","input","sampleRate","fetchOptions","rate","ArrayBuffer","decodeFromArrayBuffer","stringSource","resolveStringSource","assertSupportedStringSource","decodeFromRemoteUrl","decodeFromLocalFile","arrayBuffer","buffer","decodeWithMemoryBlock","Uint8Array","resolveAssetSource","uri","source","TypeError","url","fetch","then","res","resolveLocalFilePath","filePath","startsWith","replace","OS","__DEV__","resolveAndroidReleaseAsset","decodeWithFilePath","getInstance","decodeAudioDataInstance","audioBuffer","decodePCMInBase64Instance","base64String","inputSampleRate","inputChannelCount","interleaved","decodeWithPCMInBase64","decodeAudioData","decodePCMInBase64","isInterleaved"],"sourceRoot":"../../../src","sources":["core/AudioDecoder.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","NativeAudioAPIModule","get"],"sourceRoot":"../../../src","sources":["specs/NativeAudioAPIModule.ts"],"mappings":"AAAA,YAAY;;AAEZ,SAASA,mBAAmB,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","NativeAudioAPIModule","get"],"sourceRoot":"../../../src","sources":["specs/NativeAudioAPIModule.ts"],"mappings":"AAAA,YAAY;;AAEZ,SAASA,mBAAmB,QAAQ,cAAc;AA+ClD,MAAMC,oBAAoB,GAAGD,mBAAmB,CAACE,GAAG,CAAO,gBAAgB,CAAE;AAE7E,SAASD,oBAAoB","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioDecoder.d.ts","sourceRoot":"","sources":["../../../src/core/AudioDecoder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AudioDecoder.d.ts","sourceRoot":"","sources":["../../../src/core/AudioDecoder.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAM3C,OAAO,WAAW,MAAM,eAAe,CAAC;AAkJxC,wBAAsB,eAAe,CACnC,KAAK,EAAE,eAAe,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,WAAW,GACzB,OAAO,CAAC,WAAW,CAAC,CAMtB;AAED,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,EACzB,aAAa,GAAE,OAAc,GAC5B,OAAO,CAAC,WAAW,CAAC,CAOtB"}
|
|
@@ -26,6 +26,7 @@ interface Spec extends TurboModule {
|
|
|
26
26
|
showNotification(type: NotificationType, key: string, options: OptionsMap): Promise<NotificationOpResponse>;
|
|
27
27
|
hideNotification(key: string): Promise<NotificationOpResponse>;
|
|
28
28
|
isNotificationActive(key: string): Promise<boolean>;
|
|
29
|
+
resolveAndroidReleaseAsset(assetPath: string): string;
|
|
29
30
|
}
|
|
30
31
|
declare const NativeAudioAPIModule: Spec;
|
|
31
32
|
export { NativeAudioAPIModule };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeAudioAPIModule.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeAudioAPIModule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAErE,KAAK,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAC3E,KAAK,sBAAsB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACnE,KAAK,gBAAgB,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D,UAAU,IAAK,SAAQ,WAAW;IAChC,OAAO,IAAI,OAAO,CAAC;IACnB,4BAA4B,IAAI,MAAM,CAAC;IAGvC,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,sBAAsB,CACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EACtB,YAAY,EAAE,OAAO,GACpB,IAAI,CAAC;IACR,wBAAwB,IAAI,IAAI,CAAC;IAGjC,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAClD,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAG7C,2BAA2B,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzD,yBAAyB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,8BAA8B,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5D,4BAA4B,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAG1D,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAGnD,gBAAgB,CACd,IAAI,EAAE,gBAAgB,EACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/D,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeAudioAPIModule.d.ts","sourceRoot":"","sources":["../../../src/specs/NativeAudioAPIModule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAErE,KAAK,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAC3E,KAAK,sBAAsB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACnE,KAAK,gBAAgB,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D,UAAU,IAAK,SAAQ,WAAW;IAChC,OAAO,IAAI,OAAO,CAAC;IACnB,4BAA4B,IAAI,MAAM,CAAC;IAGvC,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,sBAAsB,CACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EACtB,YAAY,EAAE,OAAO,GACpB,IAAI,CAAC;IACR,wBAAwB,IAAI,IAAI,CAAC;IAGjC,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAClD,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAG7C,2BAA2B,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzD,yBAAyB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,8BAA8B,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5D,4BAA4B,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAG1D,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAGnD,gBAAgB,CACd,IAAI,EAAE,gBAAgB,EACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/D,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACvD;AAED,QAAA,MAAM,oBAAoB,MAAmD,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audio-api",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.6",
|
|
4
4
|
"description": "react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification",
|
|
5
5
|
"bin": {
|
|
6
6
|
"setup-rn-audio-api-web": "./scripts/setup-rn-audio-api-web.js"
|
package/src/core/AudioDecoder.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Image } from 'react-native';
|
|
1
|
+
import { Image, Platform } from 'react-native';
|
|
2
|
+
import { NativeAudioAPIModule } from '../specs';
|
|
2
3
|
|
|
3
4
|
import { AudioApiError } from '../errors';
|
|
4
5
|
import { IAudioDecoder } from '../interfaces';
|
|
@@ -23,59 +24,92 @@ class AudioDecoder {
|
|
|
23
24
|
sampleRate?: number,
|
|
24
25
|
fetchOptions?: RequestInit
|
|
25
26
|
): Promise<AudioBuffer | null | undefined> {
|
|
27
|
+
const rate = sampleRate ?? 0;
|
|
28
|
+
|
|
26
29
|
if (input instanceof ArrayBuffer) {
|
|
27
|
-
|
|
28
|
-
new Uint8Array(input),
|
|
29
|
-
sampleRate ?? 0
|
|
30
|
-
);
|
|
31
|
-
return new AudioBuffer(buffer);
|
|
30
|
+
return this.decodeFromArrayBuffer(input, rate);
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
const stringSource =
|
|
35
|
-
|
|
33
|
+
const stringSource = this.resolveStringSource(input);
|
|
34
|
+
this.assertSupportedStringSource(stringSource);
|
|
35
|
+
|
|
36
|
+
if (isRemoteSource(stringSource)) {
|
|
37
|
+
return this.decodeFromRemoteUrl(stringSource, rate, fetchOptions);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return this.decodeFromLocalFile(stringSource, rate);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private async decodeFromArrayBuffer(
|
|
44
|
+
arrayBuffer: ArrayBuffer,
|
|
45
|
+
sampleRate: number
|
|
46
|
+
): Promise<AudioBuffer> {
|
|
47
|
+
const buffer = await this.decoder.decodeWithMemoryBlock(
|
|
48
|
+
// @ts-ignore internal function
|
|
49
|
+
new Uint8Array(arrayBuffer),
|
|
50
|
+
sampleRate
|
|
51
|
+
);
|
|
52
|
+
return new AudioBuffer(buffer);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private resolveStringSource(input: number | string): string | number {
|
|
56
|
+
return typeof input === 'number'
|
|
57
|
+
? Image.resolveAssetSource(input).uri
|
|
58
|
+
: input;
|
|
59
|
+
}
|
|
36
60
|
|
|
37
|
-
|
|
38
|
-
|
|
61
|
+
private assertSupportedStringSource(
|
|
62
|
+
source: string | number
|
|
63
|
+
): asserts source is string {
|
|
64
|
+
if (typeof source !== 'string') {
|
|
65
|
+
throw new TypeError('Input must be a module, uri or ArrayBuffer');
|
|
66
|
+
}
|
|
67
|
+
if (isBase64Source(source)) {
|
|
39
68
|
throw new AudioApiError(
|
|
40
69
|
'Base64 source decoding is not currently supported, to decode raw PCM base64 strings use decodePCMInBase64 method.'
|
|
41
70
|
);
|
|
42
71
|
}
|
|
43
|
-
|
|
44
|
-
// input is blob:...
|
|
45
|
-
if (isDataBlobString(stringSource)) {
|
|
72
|
+
if (isDataBlobString(source)) {
|
|
46
73
|
throw new AudioApiError(
|
|
47
74
|
'Data Blob string decoding is not currently supported.'
|
|
48
75
|
);
|
|
49
76
|
}
|
|
77
|
+
}
|
|
50
78
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return new AudioBuffer(buffer);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (!(typeof stringSource === 'string')) {
|
|
66
|
-
throw new TypeError('Input must be a module, uri or ArrayBuffer');
|
|
67
|
-
}
|
|
79
|
+
private async decodeFromRemoteUrl(
|
|
80
|
+
url: string,
|
|
81
|
+
sampleRate: number,
|
|
82
|
+
fetchOptions?: RequestInit
|
|
83
|
+
): Promise<AudioBuffer> {
|
|
84
|
+
const arrayBuffer = await fetch(url, fetchOptions).then((res) =>
|
|
85
|
+
res.arrayBuffer()
|
|
86
|
+
);
|
|
87
|
+
return this.decodeFromArrayBuffer(arrayBuffer, sampleRate);
|
|
88
|
+
}
|
|
68
89
|
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
private resolveLocalFilePath(stringSource: string): string {
|
|
91
|
+
let filePath = stringSource.startsWith('file://')
|
|
71
92
|
? stringSource.replace('file://', '')
|
|
72
93
|
: stringSource;
|
|
73
94
|
|
|
74
|
-
|
|
75
|
-
filePath
|
|
76
|
-
|
|
77
|
-
|
|
95
|
+
if (Platform.OS === 'android' && !__DEV__) {
|
|
96
|
+
filePath = NativeAudioAPIModule.resolveAndroidReleaseAsset(filePath);
|
|
97
|
+
if (!filePath) {
|
|
98
|
+
throw new AudioApiError(
|
|
99
|
+
'Failed to resolve asset for android release build.'
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return filePath;
|
|
105
|
+
}
|
|
78
106
|
|
|
107
|
+
private async decodeFromLocalFile(
|
|
108
|
+
stringSource: string,
|
|
109
|
+
sampleRate: number
|
|
110
|
+
): Promise<AudioBuffer> {
|
|
111
|
+
const filePath = this.resolveLocalFilePath(stringSource);
|
|
112
|
+
const buffer = await this.decoder.decodeWithFilePath(filePath, sampleRate);
|
|
79
113
|
return new AudioBuffer(buffer);
|
|
80
114
|
}
|
|
81
115
|
|
|
@@ -44,6 +44,7 @@ interface Spec extends TurboModule {
|
|
|
44
44
|
): Promise<NotificationOpResponse>;
|
|
45
45
|
hideNotification(key: string): Promise<NotificationOpResponse>;
|
|
46
46
|
isNotificationActive(key: string): Promise<boolean>;
|
|
47
|
+
resolveAndroidReleaseAsset(assetPath: string): string;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
const NativeAudioAPIModule = TurboModuleRegistry.get<Spec>('AudioAPIModule')!;
|