@siteed/expo-audio-stream 1.0.5 → 1.1.2
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 +21 -5
- package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +47 -7
- package/android/src/main/java/net/siteed/audiostream/Constants.kt +5 -0
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +12 -3
- package/build/index.js +3 -2
- package/ios/AudioProcessor.swift +7 -5
- package/ios/ExpoAudioStream.podspec +1 -1
- package/ios/ExpoAudioStreamModule.swift +35 -0
- package/package.json +26 -3
- package/src/ExpoAudioStream.types.ts +3 -0
- package/src/ExpoAudioStream.web.ts +0 -1
- package/src/ExpoAudioStreamModule.ts +8 -2
- package/src/index.ts +3 -1
- package/src/logger.ts +0 -1
- package/src/utils/writeWavHeader.ts +5 -0
- package/src/workers/InlineFeaturesExtractor.web.tsx +295 -285
- package/src/workers/inlineAudioWebWorker.web.tsx +229 -221
- package/.eslintrc.js +0 -2
- package/.size-limit.json +0 -6
- package/android/.gradle/8.1.1/checksums/checksums.lock +0 -0
- package/android/.gradle/8.1.1/dependencies-accessors/dependencies-accessors.lock +0 -0
- package/android/.gradle/8.1.1/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.1.1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.1.1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.1.1/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/app.plugin.js +0 -1
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts +0 -74
- package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
- package/build/AudioAnalysis/AudioAnalysis.types.js +0 -3
- package/build/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts +0 -20
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
- package/build/AudioAnalysis/extractAudioAnalysis.js +0 -88
- package/build/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
- package/build/AudioAnalysis/extractWaveform.d.ts +0 -8
- package/build/AudioAnalysis/extractWaveform.d.ts.map +0 -1
- package/build/AudioAnalysis/extractWaveform.js +0 -14
- package/build/AudioAnalysis/extractWaveform.js.map +0 -1
- package/build/AudioRecorder.provider.d.ts +0 -23
- package/build/AudioRecorder.provider.d.ts.map +0 -1
- package/build/AudioRecorder.provider.js +0 -36
- package/build/AudioRecorder.provider.js.map +0 -1
- package/build/ExpoAudioStream.native.d.ts +0 -3
- package/build/ExpoAudioStream.native.d.ts.map +0 -1
- package/build/ExpoAudioStream.native.js +0 -6
- package/build/ExpoAudioStream.native.js.map +0 -1
- package/build/ExpoAudioStream.types.d.ts +0 -62
- package/build/ExpoAudioStream.types.d.ts.map +0 -1
- package/build/ExpoAudioStream.types.js +0 -2
- package/build/ExpoAudioStream.types.js.map +0 -1
- package/build/ExpoAudioStream.web.d.ts +0 -42
- package/build/ExpoAudioStream.web.d.ts.map +0 -1
- package/build/ExpoAudioStream.web.js +0 -203
- package/build/ExpoAudioStream.web.js.map +0 -1
- package/build/ExpoAudioStreamModule.d.ts +0 -3
- package/build/ExpoAudioStreamModule.d.ts.map +0 -1
- package/build/ExpoAudioStreamModule.js +0 -19
- package/build/ExpoAudioStreamModule.js.map +0 -1
- package/build/WebRecorder.web.d.ts +0 -51
- package/build/WebRecorder.web.d.ts.map +0 -1
- package/build/WebRecorder.web.js +0 -298
- package/build/WebRecorder.web.js.map +0 -1
- package/build/constants.d.ts +0 -11
- package/build/constants.d.ts.map +0 -1
- package/build/constants.js +0 -14
- package/build/constants.js.map +0 -1
- package/build/events.d.ts +0 -18
- package/build/events.d.ts.map +0 -1
- package/build/events.js +0 -15
- package/build/events.js.map +0 -1
- package/build/index.d.ts +0 -10
- package/build/index.d.ts.map +0 -1
- package/build/index.js.map +0 -1
- package/build/logger.d.ts +0 -9
- package/build/logger.d.ts.map +0 -1
- package/build/logger.js +0 -13
- package/build/logger.js.map +0 -1
- package/build/useAudioRecorder.d.ts +0 -20
- package/build/useAudioRecorder.d.ts.map +0 -1
- package/build/useAudioRecorder.js +0 -271
- package/build/useAudioRecorder.js.map +0 -1
- package/build/utils/BlobFix.d.ts +0 -9
- package/build/utils/BlobFix.d.ts.map +0 -1
- package/build/utils/BlobFix.js +0 -494
- package/build/utils/BlobFix.js.map +0 -1
- package/build/utils/concatenateBuffers.d.ts +0 -8
- package/build/utils/concatenateBuffers.d.ts.map +0 -1
- package/build/utils/concatenateBuffers.js +0 -21
- package/build/utils/concatenateBuffers.js.map +0 -1
- package/build/utils/convertPCMToFloat32.d.ts +0 -11
- package/build/utils/convertPCMToFloat32.d.ts.map +0 -1
- package/build/utils/convertPCMToFloat32.js +0 -54
- package/build/utils/convertPCMToFloat32.js.map +0 -1
- package/build/utils/encodingToBitDepth.d.ts +0 -5
- package/build/utils/encodingToBitDepth.d.ts.map +0 -1
- package/build/utils/encodingToBitDepth.js +0 -13
- package/build/utils/encodingToBitDepth.js.map +0 -1
- package/build/utils/getWavFileInfo.d.ts +0 -26
- package/build/utils/getWavFileInfo.d.ts.map +0 -1
- package/build/utils/getWavFileInfo.js +0 -92
- package/build/utils/getWavFileInfo.js.map +0 -1
- package/build/utils/writeWavHeader.d.ts +0 -9
- package/build/utils/writeWavHeader.d.ts.map +0 -1
- package/build/utils/writeWavHeader.js +0 -41
- package/build/utils/writeWavHeader.js.map +0 -1
- package/build/workers/InlineFeaturesExtractor.web.d.ts +0 -2
- package/build/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
- package/build/workers/InlineFeaturesExtractor.web.js +0 -303
- package/build/workers/InlineFeaturesExtractor.web.js.map +0 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts +0 -2
- package/build/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
- package/build/workers/inlineAudioWebWorker.web.js +0 -243
- package/build/workers/inlineAudioWebWorker.web.js.map +0 -1
- package/expo-module.config.json +0 -9
- package/plugin/build/index.d.ts +0 -5
- package/plugin/build/index.js +0 -28
- package/plugin/src/index.ts +0 -53
- package/plugin/tsconfig.json +0 -9
- package/publish.sh +0 -8
- package/tsconfig.json +0 -14
package/README.md
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
|
+
# @siteed/expo-audio-stream
|
|
2
|
+
|
|
3
|
+
[](https://kandi.openweaver.com/typescript/siteed/expo-audio-stream)
|
|
4
|
+
[](https://www.npmjs.com/package/@siteed/expo-audio-stream)
|
|
5
|
+
[](https://www.npmjs.com/package/@siteed/expo-audio-stream)
|
|
6
|
+
[](https://www.npmjs.com/package/@siteed/expo-audio-stream)
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
<div align="center">
|
|
2
|
-
<
|
|
3
|
-
@siteed/expo-audio-stream
|
|
10
|
+
<h2 align="center">
|
|
4
11
|
<br />
|
|
5
|
-
<
|
|
6
|
-
<strong>@siteed/expo-audio-stream<strong> is a comprehensive library designed to facilitate real-time audio processing and streaming across iOS, Android, and web platforms.
|
|
12
|
+
<strong>Comprehensive library designed to facilitate real-time audio processing and streaming across iOS, Android, and web platforms.
|
|
7
13
|
<br />
|
|
8
14
|
<br />
|
|
9
15
|
<a href="https://deeeed.github.io/expo-audio-stream/playground/">
|
|
10
16
|
<img src="../../docs/demo.gif" alt="Screenshot Playground">
|
|
11
17
|
</a>
|
|
12
|
-
|
|
18
|
+
<br/><br/>
|
|
19
|
+
<a href="https://deeeed.github.io/expo-audio-stream/playground" style="text-decoration:none;">
|
|
20
|
+
<div style="display:inline-block; padding:10px 20px; background-color:#007bff; color:white; border-radius:5px; font-size:16px;">
|
|
21
|
+
Try it out
|
|
22
|
+
</div>
|
|
23
|
+
</a>
|
|
24
|
+
<br/>
|
|
25
|
+
</h2>
|
|
13
26
|
</div>
|
|
14
27
|
|
|
28
|
+
**Give it a GitHub star 🌟, if you found this repo useful.**
|
|
29
|
+
[](https://github.com/deeeed/expo-audio-stream)
|
|
30
|
+
|
|
15
31
|
|
|
16
32
|
## Features
|
|
17
33
|
|
|
@@ -56,13 +56,53 @@ class AudioProcessor(private val filesDir: File) {
|
|
|
56
56
|
return null
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
val
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
// Read the WAV header
|
|
60
|
+
val riffHeader = String(fileData.sliceArray(0..3))
|
|
61
|
+
if (riffHeader != "RIFF") {
|
|
62
|
+
Log.e("AudioProcessor", "Invalid RIFF header")
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
val format = String(fileData.sliceArray(8..11))
|
|
67
|
+
if (format != "WAVE") {
|
|
68
|
+
Log.e("AudioProcessor", "Invalid WAVE format")
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var offset = 12
|
|
73
|
+
var dataSize = 0
|
|
74
|
+
var sampleRate = 0
|
|
75
|
+
var channels = 0
|
|
76
|
+
var bitDepth = 0
|
|
77
|
+
|
|
78
|
+
// Parse chunks until we find the 'data' chunk
|
|
79
|
+
while (offset < fileData.size - 8) {
|
|
80
|
+
val chunkId = String(fileData.sliceArray(offset until offset + 4))
|
|
81
|
+
val chunkSize = ByteBuffer.wrap(fileData.sliceArray(offset + 4 until offset + 8)).order(ByteOrder.LITTLE_ENDIAN).int
|
|
82
|
+
|
|
83
|
+
when (chunkId) {
|
|
84
|
+
"fmt " -> {
|
|
85
|
+
channels = ByteBuffer.wrap(fileData.sliceArray(offset + 10 until offset + 12)).order(ByteOrder.LITTLE_ENDIAN).short.toInt()
|
|
86
|
+
sampleRate = ByteBuffer.wrap(fileData.sliceArray(offset + 12 until offset + 16)).order(ByteOrder.LITTLE_ENDIAN).int
|
|
87
|
+
bitDepth = ByteBuffer.wrap(fileData.sliceArray(offset + 22 until offset + 24)).order(ByteOrder.LITTLE_ENDIAN).short.toInt()
|
|
88
|
+
}
|
|
89
|
+
"data" -> {
|
|
90
|
+
dataSize = chunkSize
|
|
91
|
+
offset += 8 // Skip chunk ID and size
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
offset += chunkSize + 8 // Move to the next chunk
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (dataSize == 0) {
|
|
100
|
+
Log.e("AudioProcessor", "No data chunk found in WAV file")
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
63
103
|
|
|
64
104
|
val audioData = if (skipWavHeader) {
|
|
65
|
-
fileData.sliceArray(
|
|
105
|
+
fileData.sliceArray(offset until offset + dataSize)
|
|
66
106
|
} else {
|
|
67
107
|
fileData
|
|
68
108
|
}
|
|
@@ -158,8 +198,8 @@ class AudioProcessor(private val filesDir: File) {
|
|
|
158
198
|
val rms = features.rms
|
|
159
199
|
val silent = rms < 0.01
|
|
160
200
|
val dB = if (featureOptions["dB"] == true) 20 * log10(rms.toDouble()).toFloat() else 0f
|
|
161
|
-
minAmplitude = min(minAmplitude,
|
|
162
|
-
maxAmplitude = max(maxAmplitude,
|
|
201
|
+
minAmplitude = min(minAmplitude, localMinAmplitude)
|
|
202
|
+
maxAmplitude = max(maxAmplitude, localMaxAmplitude)
|
|
163
203
|
|
|
164
204
|
val bytesPerSample = bitDepth / 8
|
|
165
205
|
val startPosition = start * bytesPerSample * config.channels
|
|
@@ -9,5 +9,10 @@ object Constants {
|
|
|
9
9
|
const val DEFAULT_INTERVAL = 1000L
|
|
10
10
|
const val MIN_INTERVAL = 100L // Minimum interval in ms for emitting audio data
|
|
11
11
|
const val WAV_HEADER_SIZE = 44
|
|
12
|
+
const val RIFF_HEADER = 0x52494646 // "RIFF"
|
|
13
|
+
const val WAVE_HEADER = 0x57415645 // "WAVE"
|
|
14
|
+
const val FMT_CHUNK_ID = 0x666d7420 // "fmt "
|
|
15
|
+
const val DATA_CHUNK_ID = 0x64617461 // "data"
|
|
16
|
+
const val INFO_CHUNK_ID = 0x494E464F // "info"
|
|
12
17
|
const val TAG = "AudioRecorderModule"
|
|
13
18
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package net.siteed.audiostream
|
|
2
2
|
|
|
3
|
+
import android.Manifest
|
|
3
4
|
import android.os.Build
|
|
4
5
|
import android.os.Bundle
|
|
5
6
|
import android.util.Log
|
|
@@ -7,6 +8,7 @@ import androidx.annotation.RequiresApi
|
|
|
7
8
|
import expo.modules.kotlin.Promise
|
|
8
9
|
import expo.modules.kotlin.modules.Module
|
|
9
10
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
11
|
+
import expo.modules.interfaces.permissions.Permissions
|
|
10
12
|
|
|
11
13
|
class ExpoAudioStreamModule() : Module(), EventSender {
|
|
12
14
|
private lateinit var audioRecorderManager: AudioRecorderManager
|
|
@@ -44,18 +46,17 @@ class ExpoAudioStreamModule() : Module(), EventSender {
|
|
|
44
46
|
audioRecorderManager.pauseRecording(promise)
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
48
49
|
AsyncFunction("extractAudioAnalysis") { options: Map<String, Any>, promise: Promise ->
|
|
49
50
|
val fileUri = options["fileUri"] as? String
|
|
50
51
|
val pointsPerSecond = (options["pointsPerSecond"] as? Double) ?: 20.0
|
|
51
|
-
val algorithm = options["algorithm"] as? String ?: "
|
|
52
|
+
val algorithm = options["algorithm"] as? String ?: "peak"
|
|
52
53
|
val featuresMap = options["features"] as? Map<*, *>
|
|
53
54
|
val features = featuresMap?.filterKeys { it is String }
|
|
54
55
|
?.filterValues { it is Boolean }
|
|
55
56
|
?.mapKeys { it.key as String }
|
|
56
57
|
?.mapValues { it.value as Boolean }
|
|
57
58
|
?: emptyMap()
|
|
58
|
-
val skipWavHeader = (options["skipWavHeader"] as? Boolean) ?:
|
|
59
|
+
val skipWavHeader = (options["skipWavHeader"] as? Boolean) ?: true
|
|
59
60
|
|
|
60
61
|
if (fileUri == null) {
|
|
61
62
|
promise.reject("INVALID_ARGUMENTS", "fileUri is required", null)
|
|
@@ -94,6 +95,14 @@ class ExpoAudioStreamModule() : Module(), EventSender {
|
|
|
94
95
|
AsyncFunction("stopRecording") { promise: Promise ->
|
|
95
96
|
audioRecorderManager.stopRecording(promise)
|
|
96
97
|
}
|
|
98
|
+
|
|
99
|
+
AsyncFunction("requestPermissionsAsync") { promise: Promise ->
|
|
100
|
+
Permissions.askForPermissionsWithPermissionsManager(appContext.permissions, promise, Manifest.permission.RECORD_AUDIO)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
AsyncFunction("getPermissionsAsync") { promise: Promise ->
|
|
104
|
+
Permissions.getPermissionsWithPermissionsManager(appContext.permissions, promise, Manifest.permission.RECORD_AUDIO)
|
|
105
|
+
}
|
|
97
106
|
}
|
|
98
107
|
|
|
99
108
|
private fun initializeManager() {
|
package/build/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { extractAudioAnalysis } from './AudioAnalysis/extractAudioAnalysis';
|
|
3
3
|
import { AudioRecorderProvider, useSharedAudioRecorder, } from './AudioRecorder.provider';
|
|
4
|
+
import ExpoAudioStreamModule from './ExpoAudioStreamModule';
|
|
4
5
|
import { useAudioRecorder } from './useAudioRecorder';
|
|
5
|
-
export * from './utils/getWavFileInfo';
|
|
6
6
|
export * from './utils/convertPCMToFloat32';
|
|
7
|
+
export * from './utils/getWavFileInfo';
|
|
7
8
|
export * from './utils/writeWavHeader';
|
|
8
|
-
export { AudioRecorderProvider, extractAudioAnalysis, useAudioRecorder, useSharedAudioRecorder, };
|
|
9
|
+
export { AudioRecorderProvider, ExpoAudioStreamModule, extractAudioAnalysis, useAudioRecorder, useSharedAudioRecorder, };
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
package/ios/AudioProcessor.swift
CHANGED
|
@@ -202,12 +202,14 @@ public class AudioProcessor {
|
|
|
202
202
|
updateSegmentData(channelData: channelData, index: i, sumSquares: &sumSquares, zeroCrossings: &zeroCrossings, prevValue: &prevValue, localMinAmplitude: &localMinAmplitude, localMaxAmplitude: &localMaxAmplitude, segmentData: &segmentData)
|
|
203
203
|
|
|
204
204
|
if (i + 1) % pointInterval == 0 || i == length - 1 {
|
|
205
|
-
|
|
205
|
+
var features = computeFeatures(segmentData: segmentData, sampleRate: sampleRate, sumSquares: sumSquares, zeroCrossings: zeroCrossings, segmentLength: (i % pointInterval) + 1, featureOptions: featureOptions)
|
|
206
|
+
features.minAmplitude = localMinAmplitude
|
|
207
|
+
features.maxAmplitude = localMaxAmplitude
|
|
206
208
|
let rms = features.rms
|
|
207
209
|
let silent = rms < 0.01
|
|
208
210
|
let dB = featureOptions["dB"] == true ? 20 * log10(rms) : 0
|
|
209
|
-
minAmplitude = min(minAmplitude,
|
|
210
|
-
maxAmplitude = max(maxAmplitude,
|
|
211
|
+
minAmplitude = min(minAmplitude, localMinAmplitude)
|
|
212
|
+
maxAmplitude = max(maxAmplitude, localMaxAmplitude)
|
|
211
213
|
|
|
212
214
|
let segmentSize = segmentData.count
|
|
213
215
|
let segmentDuration = Float(segmentSize) / sampleRate
|
|
@@ -294,8 +296,8 @@ public class AudioProcessor {
|
|
|
294
296
|
energy: energy,
|
|
295
297
|
mfcc: mfcc,
|
|
296
298
|
rms: rms,
|
|
297
|
-
minAmplitude: 0,
|
|
298
|
-
maxAmplitude: 0,
|
|
299
|
+
minAmplitude: 0, // computed before and will be overwritten
|
|
300
|
+
maxAmplitude: 0, // computed before and will be overwritten
|
|
299
301
|
zcr: zcr,
|
|
300
302
|
spectralCentroid: spectralCentroid,
|
|
301
303
|
spectralFlatness: spectralFlatness,
|
|
@@ -225,6 +225,41 @@ public class ExpoAudioStreamModule: Module, AudioStreamManagerDelegate {
|
|
|
225
225
|
Function("clearAudioFiles") {
|
|
226
226
|
clearAudioFiles()
|
|
227
227
|
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
/// Requests audio recording permissions.
|
|
231
|
+
///
|
|
232
|
+
/// - Parameters:
|
|
233
|
+
/// - promise: A promise to resolve with the permission status or reject with an error.
|
|
234
|
+
/// - Returns: Promise to be resolved with the permission status.
|
|
235
|
+
AsyncFunction("requestPermissionsAsync") { (promise: Promise) in
|
|
236
|
+
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
237
|
+
if granted {
|
|
238
|
+
promise.resolve(["status": "granted"])
|
|
239
|
+
} else {
|
|
240
|
+
promise.resolve(["status": "denied"])
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// Gets the current audio recording permissions.
|
|
246
|
+
///
|
|
247
|
+
/// - Parameters:
|
|
248
|
+
/// - promise: A promise to resolve with the permission status or reject with an error.
|
|
249
|
+
/// - Returns: Promise to be resolved with the permission status.
|
|
250
|
+
AsyncFunction("getPermissionsAsync") { (promise: Promise) in
|
|
251
|
+
let permissionStatus = AVAudioSession.sharedInstance().recordPermission
|
|
252
|
+
switch permissionStatus {
|
|
253
|
+
case .granted:
|
|
254
|
+
promise.resolve(["status": "granted"])
|
|
255
|
+
case .denied:
|
|
256
|
+
promise.resolve(["status": "denied"])
|
|
257
|
+
case .undetermined:
|
|
258
|
+
promise.resolve(["status": "undetermined"])
|
|
259
|
+
@unknown default:
|
|
260
|
+
promise.reject("UNKNOWN_ERROR", "Unknown permission status")
|
|
261
|
+
}
|
|
262
|
+
}
|
|
228
263
|
}
|
|
229
264
|
|
|
230
265
|
/// Handles the reception of audio data from the AudioStreamManager.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@siteed/expo-audio-stream",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "stream audio crossplatform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "build/index.js",
|
|
@@ -21,12 +21,33 @@
|
|
|
21
21
|
"expo-audio-stream",
|
|
22
22
|
"ExpoAudioStream"
|
|
23
23
|
],
|
|
24
|
+
"files": [
|
|
25
|
+
"src",
|
|
26
|
+
"android",
|
|
27
|
+
"ios",
|
|
28
|
+
"cpp",
|
|
29
|
+
"generated",
|
|
30
|
+
"README.md",
|
|
31
|
+
"package.json",
|
|
32
|
+
"*.podspec",
|
|
33
|
+
"!ios/build",
|
|
34
|
+
"!android/build",
|
|
35
|
+
"!android/gradle",
|
|
36
|
+
"!android/gradlew",
|
|
37
|
+
"!android/gradlew.bat",
|
|
38
|
+
"!android/local.properties",
|
|
39
|
+
"!**/__tests__",
|
|
40
|
+
"!**/__fixtures__",
|
|
41
|
+
"!**/__mocks__",
|
|
42
|
+
"!**/.*"
|
|
43
|
+
],
|
|
24
44
|
"scripts": {
|
|
25
45
|
"build": "expo-module build",
|
|
26
46
|
"clean": "expo-module clean",
|
|
27
47
|
"lint": "expo-module lint",
|
|
28
48
|
"test": "expo-module test",
|
|
29
49
|
"typecheck": "tsc --noEmit",
|
|
50
|
+
"docgen": "typedoc src/index.ts --plugin typedoc-plugin-markdown --readme none --out ../../documentation_site/docs/api-reference/API",
|
|
30
51
|
"prepare": "expo-module prepare",
|
|
31
52
|
"prepublishOnly": "expo-module prepublishOnly",
|
|
32
53
|
"expo-module": "expo-module",
|
|
@@ -55,8 +76,10 @@
|
|
|
55
76
|
"expo-modules-core": "^1.12.19",
|
|
56
77
|
"jest": "^29.7.0",
|
|
57
78
|
"prettier": "^3.2.5",
|
|
58
|
-
"react-native": "^0.74.
|
|
79
|
+
"react-native": "^0.74.4",
|
|
59
80
|
"size-limit": "^11.1.4",
|
|
81
|
+
"typedoc": "^0.26.5",
|
|
82
|
+
"typedoc-plugin-markdown": "^4.2.3",
|
|
60
83
|
"typescript": "^5.5.4"
|
|
61
84
|
},
|
|
62
85
|
"peerDependencies": {
|
|
@@ -69,6 +92,6 @@
|
|
|
69
92
|
"registry": "https://registry.npmjs.org"
|
|
70
93
|
},
|
|
71
94
|
"dependencies": {
|
|
72
|
-
"@siteed/react-native-logger": "^0.9.
|
|
95
|
+
"@siteed/react-native-logger": "^0.9.3"
|
|
73
96
|
}
|
|
74
97
|
}
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
import { WebRecorder } from './WebRecorder.web'
|
|
13
13
|
import { AudioEventPayload } from './events'
|
|
14
14
|
import { getLogger } from './logger'
|
|
15
|
-
import { concatenateBuffers } from './utils/concatenateBuffers'
|
|
16
15
|
import { encodingToBitDepth } from './utils/encodingToBitDepth'
|
|
17
16
|
import { writeWavHeader } from './utils/writeWavHeader'
|
|
18
17
|
|
|
@@ -12,12 +12,18 @@ let ExpoAudioStreamModule: any
|
|
|
12
12
|
if (Platform.OS === 'web') {
|
|
13
13
|
let instance: ExpoAudioStreamWeb | null = null
|
|
14
14
|
|
|
15
|
-
ExpoAudioStreamModule = (
|
|
15
|
+
ExpoAudioStreamModule = (webProps: ExpoAudioStreamWebProps) => {
|
|
16
16
|
if (!instance) {
|
|
17
17
|
instance = new ExpoAudioStreamWeb(webProps)
|
|
18
18
|
}
|
|
19
19
|
return instance
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
|
+
ExpoAudioStreamModule.requestPermissionsAsync = async () => {
|
|
22
|
+
return { status: 'granted' }
|
|
23
|
+
}
|
|
24
|
+
ExpoAudioStreamModule.getPermissionsAsync = async () => {
|
|
25
|
+
return { status: 'granted' }
|
|
26
|
+
}
|
|
21
27
|
} else {
|
|
22
28
|
ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')
|
|
23
29
|
}
|
package/src/index.ts
CHANGED
|
@@ -5,14 +5,16 @@ import {
|
|
|
5
5
|
AudioRecorderProvider,
|
|
6
6
|
useSharedAudioRecorder,
|
|
7
7
|
} from './AudioRecorder.provider'
|
|
8
|
+
import ExpoAudioStreamModule from './ExpoAudioStreamModule'
|
|
8
9
|
import { useAudioRecorder } from './useAudioRecorder'
|
|
9
10
|
|
|
10
|
-
export * from './utils/getWavFileInfo'
|
|
11
11
|
export * from './utils/convertPCMToFloat32'
|
|
12
|
+
export * from './utils/getWavFileInfo'
|
|
12
13
|
export * from './utils/writeWavHeader'
|
|
13
14
|
|
|
14
15
|
export {
|
|
15
16
|
AudioRecorderProvider,
|
|
17
|
+
ExpoAudioStreamModule,
|
|
16
18
|
extractAudioAnalysis,
|
|
17
19
|
useAudioRecorder,
|
|
18
20
|
useSharedAudioRecorder,
|
package/src/logger.ts
CHANGED
|
@@ -29,6 +29,11 @@ export const writeWavHeader = ({
|
|
|
29
29
|
const existingHeader = view.getUint32(0, false) === 0x52494646 // "RIFF" in ASCII
|
|
30
30
|
|
|
31
31
|
if (!existingHeader) {
|
|
32
|
+
// Ensure the buffer is large enough for the WAV header
|
|
33
|
+
if (buffer.byteLength < 44) {
|
|
34
|
+
throw new Error('Buffer is too small to contain a valid WAV header')
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
// Write the WAV header
|
|
33
38
|
writeString(view, 0, 'RIFF') // ChunkID
|
|
34
39
|
view.setUint32(4, 36 + numSamples * blockAlign, true) // ChunkSize
|