@siteed/audio-studio 3.1.1 → 3.2.0

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.
Files changed (96) hide show
  1. package/CHANGELOG.md +375 -4
  2. package/android/src/main/java/net/siteed/audiostudio/AudioStreamDecoder.kt +852 -0
  3. package/android/src/main/java/net/siteed/audiostudio/AudioStudioModule.kt +167 -3
  4. package/android/src/main/java/net/siteed/audiostudio/Constants.kt +4 -0
  5. package/build/cjs/errors/AudioStreamError.js +161 -0
  6. package/build/cjs/errors/AudioStreamError.js.map +1 -0
  7. package/build/cjs/errors/AudioStreamError.test.js +82 -0
  8. package/build/cjs/errors/AudioStreamError.test.js.map +1 -0
  9. package/build/cjs/index.js +7 -1
  10. package/build/cjs/index.js.map +1 -1
  11. package/build/cjs/streamAudioData.js +534 -0
  12. package/build/cjs/streamAudioData.js.map +1 -0
  13. package/build/cjs/utils/audioProcessing.js +14 -10
  14. package/build/cjs/utils/audioProcessing.js.map +1 -1
  15. package/build/esm/errors/AudioStreamError.js +156 -0
  16. package/build/esm/errors/AudioStreamError.js.map +1 -0
  17. package/build/esm/errors/AudioStreamError.test.js +80 -0
  18. package/build/esm/errors/AudioStreamError.test.js.map +1 -0
  19. package/build/esm/index.js +3 -1
  20. package/build/esm/index.js.map +1 -1
  21. package/build/esm/streamAudioData.js +527 -0
  22. package/build/esm/streamAudioData.js.map +1 -0
  23. package/build/esm/utils/audioProcessing.js +14 -10
  24. package/build/esm/utils/audioProcessing.js.map +1 -1
  25. package/build/types/errors/AudioStreamError.d.ts +25 -0
  26. package/build/types/errors/AudioStreamError.d.ts.map +1 -0
  27. package/build/types/errors/AudioStreamError.test.d.ts +2 -0
  28. package/build/types/errors/AudioStreamError.test.d.ts.map +1 -0
  29. package/build/types/index.d.ts +5 -1
  30. package/build/types/index.d.ts.map +1 -1
  31. package/build/types/streamAudioData.d.ts +119 -0
  32. package/build/types/streamAudioData.d.ts.map +1 -0
  33. package/build/types/utils/audioProcessing.d.ts +2 -2
  34. package/build/types/utils/audioProcessing.d.ts.map +1 -1
  35. package/ios/AudioProcessingHelpers.swift +10 -5
  36. package/ios/AudioStreamDecoder.swift +614 -0
  37. package/ios/AudioStudioModule.swift +186 -3
  38. package/package.json +163 -146
  39. package/scripts/README.md +58 -0
  40. package/src/errors/AudioStreamError.test.ts +92 -0
  41. package/src/errors/AudioStreamError.ts +199 -0
  42. package/src/index.ts +24 -0
  43. package/src/streamAudioData.ts +758 -0
  44. package/src/utils/audioProcessing.ts +25 -14
  45. package/android/src/androidTest/assets/chorus.wav +0 -0
  46. package/android/src/androidTest/assets/jfk.wav +0 -0
  47. package/android/src/androidTest/assets/osr_us_000_0010_8k.wav +0 -0
  48. package/android/src/androidTest/assets/recorder_hello_world.wav +0 -0
  49. package/android/src/androidTest/java/net/siteed/audiostudio/AudioFinalMetadataContractInstrumentedTest.kt +0 -190
  50. package/android/src/androidTest/java/net/siteed/audiostudio/AudioProcessorInstrumentedTest.kt +0 -197
  51. package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderInstrumentedTest.kt +0 -487
  52. package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderPerformanceInstrumentedTest.kt +0 -250
  53. package/android/src/androidTest/java/net/siteed/audiostudio/OpusRangeDecodeRegressionInstrumentedTest.kt +0 -186
  54. package/android/src/androidTest/java/net/siteed/audiostudio/integration/AudioFocusStrategyIntegrationTest.kt +0 -332
  55. package/android/src/androidTest/java/net/siteed/audiostudio/integration/BufferDurationIntegrationTest.kt +0 -324
  56. package/android/src/androidTest/java/net/siteed/audiostudio/integration/CompressedOnlyOutputTest.kt +0 -253
  57. package/android/src/androidTest/java/net/siteed/audiostudio/integration/DeviceDisconnectionFallbackTest.kt +0 -218
  58. package/android/src/androidTest/java/net/siteed/audiostudio/integration/EventEmissionIntervalTest.kt +0 -120
  59. package/android/src/androidTest/java/net/siteed/audiostudio/integration/M4aFormatTest.kt +0 -345
  60. package/android/src/androidTest/java/net/siteed/audiostudio/integration/OutputControlIntegrationTest.kt +0 -340
  61. package/android/src/androidTest/java/net/siteed/audiostudio/integration/PcmStreamingDurationTest.kt +0 -252
  62. package/android/src/androidTest/java/net/siteed/audiostudio/integration/README.md +0 -95
  63. package/android/src/androidTest/java/net/siteed/audiostudio/integration/run_integration_tests.sh +0 -43
  64. package/android/src/test/java/net/siteed/audiostudio/AndroidCallStateTest.kt +0 -37
  65. package/android/src/test/java/net/siteed/audiostudio/AndroidEventEmitterTest.kt +0 -28
  66. package/android/src/test/java/net/siteed/audiostudio/AudioFileHandlerTest.kt +0 -279
  67. package/android/src/test/java/net/siteed/audiostudio/AudioFocusStrategyTest.kt +0 -249
  68. package/android/src/test/java/net/siteed/audiostudio/AudioFormatTest.kt +0 -151
  69. package/android/src/test/java/net/siteed/audiostudio/AudioFormatUtilsTest.kt +0 -273
  70. package/android/src/test/java/net/siteed/audiostudio/DeviceDisconnectionFallbackUnitTest.kt +0 -140
  71. package/android/src/test/java/net/siteed/audiostudio/InterruptionAutoResumePolicyTest.kt +0 -49
  72. package/android/src/test/resources/chorus.wav +0 -0
  73. package/android/src/test/resources/generate_test_audio.py +0 -94
  74. package/android/src/test/resources/jfk.wav +0 -0
  75. package/android/src/test/resources/osr_us_000_0010_8k.wav +0 -0
  76. package/android/src/test/resources/recorder_hello_world.wav +0 -0
  77. package/ios/AudioStudioTests/AudioFileHandlerTests.swift +0 -338
  78. package/ios/AudioStudioTests/AudioFormatUtilsTests.swift +0 -331
  79. package/ios/AudioStudioTests/AudioTestHelpers.swift +0 -130
  80. package/ios/AudioStudioTests/CompressedOnlyOutputTests.swift +0 -334
  81. package/ios/AudioStudioTests/EventEmissionIntervalTests.swift +0 -105
  82. package/ios/AudioStudioTests/Info.plist +0 -22
  83. package/ios/AudioStudioTests/README.md +0 -39
  84. package/ios/AudioStudioTests/SimpleAudioTest.swift +0 -98
  85. package/ios/AudioStudioTests/TestAudioGenerator.swift +0 -75
  86. package/ios/tests/README.md +0 -41
  87. package/ios/tests/integration/buffer_and_fallback_test.swift +0 -178
  88. package/ios/tests/integration/buffer_duration_test.swift +0 -185
  89. package/ios/tests/integration/compressed_only_output_test.swift +0 -271
  90. package/ios/tests/integration/output_control_test.swift +0 -322
  91. package/ios/tests/integration/run_integration_tests.sh +0 -37
  92. package/ios/tests/opus_support_test_macos.swift +0 -154
  93. package/ios/tests/standalone/audio_processing_test.swift +0 -144
  94. package/ios/tests/standalone/audio_recording_test.swift +0 -277
  95. package/ios/tests/standalone/audio_streaming_test.swift +0 -249
  96. package/ios/tests/standalone/standalone_test.swift +0 -144
@@ -21,14 +21,17 @@ import kotlinx.coroutines.cancelChildren
21
21
  import kotlinx.coroutines.launch
22
22
  import kotlinx.coroutines.withContext
23
23
 
24
- class AudioStudioModule : Module(), EventSender {
24
+ class AudioStudioModule : Module(), EventSender, AudioStreamDecoderDelegate {
25
25
  companion object {
26
26
  private const val CLASS_NAME = "AudioStudioModule"
27
27
  }
28
-
28
+
29
29
  private lateinit var audioRecorderManager: AudioRecorderManager
30
30
  private lateinit var audioProcessor: AudioProcessor
31
31
  private lateinit var audioDeviceManager: AudioDeviceManager
32
+
33
+ private val streamDecoders = mutableMapOf<String, AudioStreamDecoder>()
34
+ private val streamDecodersLock = Object()
32
35
  private var enablePhoneStateHandling: Boolean = false // Default to false until we check manifest
33
36
  private var enableNotificationHandling: Boolean = false // Default to false until we check manifest
34
37
  private var enableBackgroundAudio: Boolean = false // Default to false until we check manifest
@@ -88,7 +91,11 @@ class AudioStudioModule : Module(), EventSender {
88
91
  Constants.AUDIO_ANALYSIS_EVENT_NAME,
89
92
  Constants.RECORDING_INTERRUPTED_EVENT_NAME,
90
93
  Constants.TRIM_PROGRESS_EVENT,
91
- Constants.DEVICE_CHANGED_EVENT // Add device changed event name
94
+ Constants.DEVICE_CHANGED_EVENT, // Add device changed event name
95
+ Constants.AUDIO_STREAM_CHUNK_EVENT,
96
+ Constants.AUDIO_STREAM_PROGRESS_EVENT,
97
+ Constants.AUDIO_STREAM_COMPLETE_EVENT,
98
+ Constants.AUDIO_STREAM_ERROR_EVENT
92
99
  )
93
100
 
94
101
  // Initialize Managers
@@ -657,6 +664,21 @@ class AudioStudioModule : Module(), EventSender {
657
664
  // while keeping the same module instance, and a fully cancelled
658
665
  // scope would silently no-op every subsequent launch.
659
666
  coroutineScope.coroutineContext.cancelChildren()
667
+ // Cancel any in-flight streamAudioData decoders before teardown.
668
+ // Their worker threads are not children of `coroutineScope` and
669
+ // would otherwise keep running, emitting events through a
670
+ // destroyed module. We clear the map *before* cancelling so that
671
+ // any terminal events the worker emits after observing
672
+ // `cancel()` are dropped by `streamDecoderEmit` (which gates on
673
+ // map membership). The map itself stays usable so Expo can
674
+ // recreate decoders on a dev-client reload without resetting any
675
+ // global flag.
676
+ val inflight = synchronized(streamDecodersLock) {
677
+ val snapshot = streamDecoders.values.toList()
678
+ streamDecoders.clear()
679
+ snapshot
680
+ }
681
+ inflight.forEach { it.cancel() }
660
682
  AudioRecorderManager.destroy()
661
683
  }
662
684
 
@@ -994,6 +1016,148 @@ class AudioStudioModule : Module(), EventSender {
994
1016
  }
995
1017
  }
996
1018
  }
1019
+
1020
+ AsyncFunction("streamAudioData") { options: Map<String, Any?>, promise: Promise ->
1021
+ try {
1022
+ val requestId = options["requestId"] as? String
1023
+ ?: throw IllegalArgumentException("requestId is required")
1024
+ val fileUri = options["fileUri"] as? String
1025
+ ?: throw IllegalArgumentException("fileUri is required")
1026
+ val streamFormat = (options["streamFormat"] as? String) ?: "float32"
1027
+ if (streamFormat != "float32") {
1028
+ promise.reject(
1029
+ "ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT",
1030
+ "Only streamFormat='float32' is supported",
1031
+ null
1032
+ )
1033
+ return@AsyncFunction
1034
+ }
1035
+
1036
+ val context = appContext.reactContext
1037
+ ?: throw IllegalStateException("React context not available")
1038
+
1039
+ val chunkDurationMs = (options["chunkDurationMs"] as? Number)?.toInt() ?: 1000
1040
+ if (chunkDurationMs !in 10..60000) {
1041
+ promise.reject(
1042
+ "ERR_AUDIO_STREAM_INVALID_RANGE",
1043
+ "chunkDurationMs must be in [10, 60000]",
1044
+ null
1045
+ )
1046
+ return@AsyncFunction
1047
+ }
1048
+
1049
+ val decoderOptions = AudioStreamDecoder.Options(
1050
+ requestId = requestId,
1051
+ fileUri = fileUri,
1052
+ startTimeMs = (options["startTimeMs"] as? Number)?.toLong(),
1053
+ endTimeMs = (options["endTimeMs"] as? Number)?.toLong(),
1054
+ targetSampleRate = (options["targetSampleRate"] as? Number)?.toInt(),
1055
+ channels = (options["channels"] as? Number)?.toInt(),
1056
+ normalizeAudio = (options["normalizeAudio"] as? Boolean) ?: true,
1057
+ chunkDurationMs = chunkDurationMs,
1058
+ maxChunkBytes = (options["maxChunkBytes"] as? Number)?.toInt(),
1059
+ maxBufferedChunks = ((options["maxBufferedChunks"] as? Number)?.toInt() ?: 4)
1060
+ .coerceAtLeast(1),
1061
+ backpressureTimeoutMs = (options["backpressureTimeoutMs"] as? Number)?.toLong(),
1062
+ )
1063
+
1064
+ val decoder = AudioStreamDecoder(context, decoderOptions, this@AudioStudioModule)
1065
+ synchronized(streamDecodersLock) {
1066
+ if (streamDecoders.containsKey(requestId)) {
1067
+ promise.reject(
1068
+ "ERR_AUDIO_STREAM_BUSY",
1069
+ "requestId already in use",
1070
+ null
1071
+ )
1072
+ return@AsyncFunction
1073
+ }
1074
+ streamDecoders[requestId] = decoder
1075
+ }
1076
+ decoder.start()
1077
+ promise.resolve(bundleOf("requestId" to requestId))
1078
+ } catch (e: Exception) {
1079
+ LogUtils.e(CLASS_NAME, "streamAudioData failed: ${e.message}", e)
1080
+ promise.reject(
1081
+ "ERR_AUDIO_STREAM_DECODE_FAILED",
1082
+ e.message ?: "streamAudioData failed",
1083
+ e
1084
+ )
1085
+ }
1086
+ }
1087
+
1088
+ AsyncFunction("cancelStreamAudioData") { requestId: String, promise: Promise ->
1089
+ val decoder = synchronized(streamDecodersLock) {
1090
+ streamDecoders[requestId]
1091
+ }
1092
+ decoder?.cancel()
1093
+ promise.resolve(bundleOf(
1094
+ "requestId" to requestId,
1095
+ "cancelled" to (decoder != null)
1096
+ ))
1097
+ }
1098
+
1099
+ Function("acknowledgeStreamAudioChunk") { requestId: String, chunkIndex: Int ->
1100
+ val decoder = synchronized(streamDecodersLock) {
1101
+ streamDecoders[requestId]
1102
+ }
1103
+ decoder?.acknowledgeChunk(chunkIndex)
1104
+ }
1105
+
1106
+ AsyncFunction("getAudioDecodeCapabilities") { promise: Promise ->
1107
+ promise.resolve(bundleOf(
1108
+ "platform" to "android",
1109
+ "supportedInputFormats" to listOf(
1110
+ "audio/wav",
1111
+ "audio/mpeg",
1112
+ "audio/mp4",
1113
+ "audio/aac",
1114
+ "audio/ogg",
1115
+ "audio/opus",
1116
+ "audio/webm",
1117
+ "audio/flac",
1118
+ "audio/amr-wb",
1119
+ ),
1120
+ "supportedOutputFormats" to listOf("float32"),
1121
+ "supportsCancellation" to true,
1122
+ "supportsBackpressure" to true,
1123
+ "supportsTimeRange" to true,
1124
+ "supportsTargetSampleRate" to true,
1125
+ "supportsChannelMixing" to true,
1126
+ "knownLimitations" to listOf(
1127
+ "MediaCodec output rate may differ from extractor metadata for some encoders; output is resampled via linear interpolation."
1128
+ )
1129
+ ))
1130
+ }
1131
+ }
1132
+
1133
+ private fun releaseStreamDecoder(requestId: String) {
1134
+ synchronized(streamDecodersLock) {
1135
+ streamDecoders.remove(requestId)
1136
+ }
1137
+ }
1138
+
1139
+ override fun streamDecoderEmit(eventName: String, payload: Bundle) {
1140
+ // Drop events from decoders that are no longer tracked. This catches
1141
+ // both the OnDestroy teardown path (map cleared before `cancel()`) and
1142
+ // post-completion stragglers, without depending on a one-way shutdown
1143
+ // flag that would survive Expo's `definition()` re-runs.
1144
+ val requestId = payload.getString("requestId") ?: return
1145
+ val isActive = synchronized(streamDecodersLock) {
1146
+ streamDecoders.containsKey(requestId)
1147
+ }
1148
+ if (!isActive) return
1149
+ when (eventName) {
1150
+ Constants.AUDIO_STREAM_COMPLETE_EVENT -> {
1151
+ releaseStreamDecoder(requestId)
1152
+ }
1153
+ Constants.AUDIO_STREAM_ERROR_EVENT -> {
1154
+ val code = payload.getString("code") ?: ""
1155
+ if (code != "ERR_AUDIO_STREAM_CANCELLED") {
1156
+ releaseStreamDecoder(requestId)
1157
+ }
1158
+ }
1159
+ }
1160
+ safeSendEvent(eventName, payload)
997
1161
  }
998
1162
 
999
1163
  private fun initializeManager() {
@@ -11,6 +11,10 @@ object Constants {
11
11
  const val RECORDING_INTERRUPTED_EVENT_NAME = "onRecordingInterrupted"
12
12
  const val TRIM_PROGRESS_EVENT = "TrimProgress"
13
13
  const val DEVICE_CHANGED_EVENT = "deviceChangedEvent"
14
+ const val AUDIO_STREAM_CHUNK_EVENT = "AudioDataStreamChunk"
15
+ const val AUDIO_STREAM_PROGRESS_EVENT = "AudioDataStreamProgress"
16
+ const val AUDIO_STREAM_COMPLETE_EVENT = "AudioDataStreamComplete"
17
+ const val AUDIO_STREAM_ERROR_EVENT = "AudioDataStreamError"
14
18
 
15
19
  // Audio constants
16
20
  const val DEFAULT_SAMPLE_RATE = 16000 // Default sample rate for audio recording
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AudioStreamError = void 0;
4
+ exports.mapStreamError = mapStreamError;
5
+ const RECOVERABLE = [
6
+ 'ERR_AUDIO_STREAM_CANCELLED',
7
+ 'ERR_AUDIO_STREAM_BUSY',
8
+ 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT',
9
+ 'ERR_AUDIO_STREAM_PERMISSION_DENIED',
10
+ ];
11
+ class AudioStreamError extends Error {
12
+ code;
13
+ recoverable;
14
+ fileUri;
15
+ platform;
16
+ nativeCode;
17
+ nativeMessage;
18
+ constructor(payload) {
19
+ super(payload.message);
20
+ this.name = 'AudioStreamError';
21
+ this.code = payload.code;
22
+ this.recoverable = payload.recoverable;
23
+ this.fileUri = payload.fileUri;
24
+ this.platform = payload.platform;
25
+ this.nativeCode = payload.nativeCode;
26
+ this.nativeMessage = payload.nativeMessage;
27
+ }
28
+ toJSON() {
29
+ return {
30
+ code: this.code,
31
+ message: this.message,
32
+ recoverable: this.recoverable,
33
+ fileUri: this.fileUri,
34
+ platform: this.platform,
35
+ nativeCode: this.nativeCode,
36
+ nativeMessage: this.nativeMessage,
37
+ };
38
+ }
39
+ }
40
+ exports.AudioStreamError = AudioStreamError;
41
+ function getNativeMessage(err) {
42
+ if (err instanceof Error)
43
+ return err.message;
44
+ if (typeof err === 'string')
45
+ return err;
46
+ try {
47
+ return JSON.stringify(err) ?? String(err);
48
+ }
49
+ catch {
50
+ return String(err);
51
+ }
52
+ }
53
+ function getNativeCode(err) {
54
+ if (err && typeof err === 'object' && 'code' in err) {
55
+ const code = err.code;
56
+ if (typeof code === 'string')
57
+ return code;
58
+ }
59
+ return undefined;
60
+ }
61
+ function isUnknownAudioStreamCode(raw) {
62
+ if (!raw)
63
+ return false;
64
+ return (raw.toUpperCase().startsWith('ERR_AUDIO_STREAM_') &&
65
+ normalizeCode(raw) === null);
66
+ }
67
+ function normalizeCode(raw) {
68
+ if (!raw)
69
+ return null;
70
+ const upper = raw.toUpperCase();
71
+ if (upper.startsWith('ERR_AUDIO_STREAM_')) {
72
+ const known = [
73
+ 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT',
74
+ 'ERR_AUDIO_STREAM_INVALID_RANGE',
75
+ 'ERR_AUDIO_STREAM_DECODE_FAILED',
76
+ 'ERR_AUDIO_STREAM_CANCELLED',
77
+ 'ERR_AUDIO_STREAM_PERMISSION_DENIED',
78
+ 'ERR_AUDIO_STREAM_FILE_NOT_FOUND',
79
+ 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT',
80
+ 'ERR_AUDIO_STREAM_NATIVE_UNAVAILABLE',
81
+ 'ERR_AUDIO_STREAM_BUSY',
82
+ 'ERR_AUDIO_STREAM_UNKNOWN',
83
+ ];
84
+ if (known.includes(upper)) {
85
+ return upper;
86
+ }
87
+ }
88
+ if (upper.includes('FILE_NOT_FOUND') || upper === 'ENOENT') {
89
+ return 'ERR_AUDIO_STREAM_FILE_NOT_FOUND';
90
+ }
91
+ if (upper.includes('PERMISSION') || upper === 'EACCES') {
92
+ return 'ERR_AUDIO_STREAM_PERMISSION_DENIED';
93
+ }
94
+ if (upper.includes('UNSUPPORTED') ||
95
+ upper.includes('NO_SUITABLE_CODEC') ||
96
+ upper.includes('NO SUITABLE CODEC') ||
97
+ upper.includes('NOT SUPPORTED')) {
98
+ return 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT';
99
+ }
100
+ if (upper.includes('INVALID_RANGE') ||
101
+ upper.includes('OUT_OF_RANGE') ||
102
+ upper.includes('INVALID_TIME')) {
103
+ return 'ERR_AUDIO_STREAM_INVALID_RANGE';
104
+ }
105
+ if (upper.includes('CANCELLED') || upper.includes('CANCELED')) {
106
+ return 'ERR_AUDIO_STREAM_CANCELLED';
107
+ }
108
+ if (upper.includes('BUSY')) {
109
+ return 'ERR_AUDIO_STREAM_BUSY';
110
+ }
111
+ if (upper.includes('BACKPRESSURE')) {
112
+ return 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT';
113
+ }
114
+ if (upper.includes('DECODE') ||
115
+ upper.includes('CODEC') ||
116
+ upper.includes('MALFORMED')) {
117
+ return 'ERR_AUDIO_STREAM_DECODE_FAILED';
118
+ }
119
+ return null;
120
+ }
121
+ function mapStreamError(err, fileUri, platform) {
122
+ if (err instanceof AudioStreamError)
123
+ return err;
124
+ const nativeMessage = getNativeMessage(err);
125
+ const nativeCode = getNativeCode(err);
126
+ const lower = nativeMessage.toLowerCase();
127
+ if (isUnknownAudioStreamCode(nativeCode)) {
128
+ console.warn(`[AudioStreamError] Unknown native audio stream error code: ${nativeCode}`);
129
+ }
130
+ let code = normalizeCode(nativeCode) ??
131
+ normalizeCode(nativeMessage) ??
132
+ 'ERR_AUDIO_STREAM_UNKNOWN';
133
+ if (code === 'ERR_AUDIO_STREAM_UNKNOWN') {
134
+ if (lower.includes('not found') || lower.includes('does not exist')) {
135
+ code = 'ERR_AUDIO_STREAM_FILE_NOT_FOUND';
136
+ }
137
+ else if (lower.includes('unsupported') ||
138
+ lower.includes('no suitable codec')) {
139
+ code = 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT';
140
+ }
141
+ else if (lower.includes('permission') || lower.includes('denied')) {
142
+ code = 'ERR_AUDIO_STREAM_PERMISSION_DENIED';
143
+ }
144
+ else if (lower.includes('decode') || lower.includes('codec')) {
145
+ code = 'ERR_AUDIO_STREAM_DECODE_FAILED';
146
+ }
147
+ else if (lower.includes('cancel')) {
148
+ code = 'ERR_AUDIO_STREAM_CANCELLED';
149
+ }
150
+ }
151
+ return new AudioStreamError({
152
+ code,
153
+ message: `Audio stream failed (${code}): ${nativeMessage}`,
154
+ recoverable: RECOVERABLE.includes(code),
155
+ fileUri,
156
+ platform,
157
+ nativeCode,
158
+ nativeMessage,
159
+ });
160
+ }
161
+ //# sourceMappingURL=AudioStreamError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioStreamError.js","sourceRoot":"","sources":["../../../src/errors/AudioStreamError.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Stable typed errors for `streamAudioData`. Callers can switch on `code`.\n */\nexport type AudioStreamErrorCode =\n | 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT'\n | 'ERR_AUDIO_STREAM_INVALID_RANGE'\n | 'ERR_AUDIO_STREAM_DECODE_FAILED'\n | 'ERR_AUDIO_STREAM_CANCELLED'\n | 'ERR_AUDIO_STREAM_PERMISSION_DENIED'\n | 'ERR_AUDIO_STREAM_FILE_NOT_FOUND'\n | 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT'\n | 'ERR_AUDIO_STREAM_NATIVE_UNAVAILABLE'\n | 'ERR_AUDIO_STREAM_BUSY'\n | 'ERR_AUDIO_STREAM_UNKNOWN'\n\nexport interface AudioStreamErrorPayload {\n code: AudioStreamErrorCode\n message: string\n recoverable: boolean\n fileUri?: string\n platform?: string\n nativeCode?: string\n nativeMessage?: string\n}\n\nconst RECOVERABLE: AudioStreamErrorCode[] = [\n 'ERR_AUDIO_STREAM_CANCELLED',\n 'ERR_AUDIO_STREAM_BUSY',\n 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT',\n 'ERR_AUDIO_STREAM_PERMISSION_DENIED',\n]\n\nexport class AudioStreamError extends Error {\n readonly code: AudioStreamErrorCode\n readonly recoverable: boolean\n readonly fileUri?: string\n readonly platform?: string\n readonly nativeCode?: string\n readonly nativeMessage?: string\n\n constructor(payload: AudioStreamErrorPayload) {\n super(payload.message)\n this.name = 'AudioStreamError'\n this.code = payload.code\n this.recoverable = payload.recoverable\n this.fileUri = payload.fileUri\n this.platform = payload.platform\n this.nativeCode = payload.nativeCode\n this.nativeMessage = payload.nativeMessage\n }\n\n toJSON(): AudioStreamErrorPayload {\n return {\n code: this.code,\n message: this.message,\n recoverable: this.recoverable,\n fileUri: this.fileUri,\n platform: this.platform,\n nativeCode: this.nativeCode,\n nativeMessage: this.nativeMessage,\n }\n }\n}\n\nfunction getNativeMessage(err: unknown): string {\n if (err instanceof Error) return err.message\n if (typeof err === 'string') return err\n try {\n return JSON.stringify(err) ?? String(err)\n } catch {\n return String(err)\n }\n}\n\nfunction getNativeCode(err: unknown): string | undefined {\n if (err && typeof err === 'object' && 'code' in err) {\n const code = (err as { code?: unknown }).code\n if (typeof code === 'string') return code\n }\n return undefined\n}\n\nfunction isUnknownAudioStreamCode(raw: string | undefined): boolean {\n if (!raw) return false\n return (\n raw.toUpperCase().startsWith('ERR_AUDIO_STREAM_') &&\n normalizeCode(raw) === null\n )\n}\n\nfunction normalizeCode(raw: string | undefined): AudioStreamErrorCode | null {\n if (!raw) return null\n const upper = raw.toUpperCase()\n if (upper.startsWith('ERR_AUDIO_STREAM_')) {\n const known: AudioStreamErrorCode[] = [\n 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT',\n 'ERR_AUDIO_STREAM_INVALID_RANGE',\n 'ERR_AUDIO_STREAM_DECODE_FAILED',\n 'ERR_AUDIO_STREAM_CANCELLED',\n 'ERR_AUDIO_STREAM_PERMISSION_DENIED',\n 'ERR_AUDIO_STREAM_FILE_NOT_FOUND',\n 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT',\n 'ERR_AUDIO_STREAM_NATIVE_UNAVAILABLE',\n 'ERR_AUDIO_STREAM_BUSY',\n 'ERR_AUDIO_STREAM_UNKNOWN',\n ]\n if ((known as string[]).includes(upper)) {\n return upper as AudioStreamErrorCode\n }\n }\n if (upper.includes('FILE_NOT_FOUND') || upper === 'ENOENT') {\n return 'ERR_AUDIO_STREAM_FILE_NOT_FOUND'\n }\n if (upper.includes('PERMISSION') || upper === 'EACCES') {\n return 'ERR_AUDIO_STREAM_PERMISSION_DENIED'\n }\n if (\n upper.includes('UNSUPPORTED') ||\n upper.includes('NO_SUITABLE_CODEC') ||\n upper.includes('NO SUITABLE CODEC') ||\n upper.includes('NOT SUPPORTED')\n ) {\n return 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT'\n }\n if (\n upper.includes('INVALID_RANGE') ||\n upper.includes('OUT_OF_RANGE') ||\n upper.includes('INVALID_TIME')\n ) {\n return 'ERR_AUDIO_STREAM_INVALID_RANGE'\n }\n if (upper.includes('CANCELLED') || upper.includes('CANCELED')) {\n return 'ERR_AUDIO_STREAM_CANCELLED'\n }\n if (upper.includes('BUSY')) {\n return 'ERR_AUDIO_STREAM_BUSY'\n }\n if (upper.includes('BACKPRESSURE')) {\n return 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT'\n }\n if (\n upper.includes('DECODE') ||\n upper.includes('CODEC') ||\n upper.includes('MALFORMED')\n ) {\n return 'ERR_AUDIO_STREAM_DECODE_FAILED'\n }\n return null\n}\n\nexport function mapStreamError(\n err: unknown,\n fileUri?: string,\n platform?: string\n): AudioStreamError {\n if (err instanceof AudioStreamError) return err\n\n const nativeMessage = getNativeMessage(err)\n const nativeCode = getNativeCode(err)\n const lower = nativeMessage.toLowerCase()\n\n if (isUnknownAudioStreamCode(nativeCode)) {\n console.warn(\n `[AudioStreamError] Unknown native audio stream error code: ${nativeCode}`\n )\n }\n\n let code =\n normalizeCode(nativeCode) ??\n normalizeCode(nativeMessage) ??\n 'ERR_AUDIO_STREAM_UNKNOWN'\n\n if (code === 'ERR_AUDIO_STREAM_UNKNOWN') {\n if (lower.includes('not found') || lower.includes('does not exist')) {\n code = 'ERR_AUDIO_STREAM_FILE_NOT_FOUND'\n } else if (\n lower.includes('unsupported') ||\n lower.includes('no suitable codec')\n ) {\n code = 'ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT'\n } else if (lower.includes('permission') || lower.includes('denied')) {\n code = 'ERR_AUDIO_STREAM_PERMISSION_DENIED'\n } else if (lower.includes('decode') || lower.includes('codec')) {\n code = 'ERR_AUDIO_STREAM_DECODE_FAILED'\n } else if (lower.includes('cancel')) {\n code = 'ERR_AUDIO_STREAM_CANCELLED'\n }\n }\n\n return new AudioStreamError({\n code,\n message: `Audio stream failed (${code}): ${nativeMessage}`,\n recoverable: RECOVERABLE.includes(code),\n fileUri,\n platform,\n nativeCode,\n nativeMessage,\n })\n}\n"]}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const AudioStreamError_1 = require("./AudioStreamError");
4
+ describe('AudioStreamError', () => {
5
+ it('passes through an existing AudioStreamError unchanged', () => {
6
+ const original = new AudioStreamError_1.AudioStreamError({
7
+ code: 'ERR_AUDIO_STREAM_CANCELLED',
8
+ message: 'aborted',
9
+ recoverable: true,
10
+ });
11
+ expect((0, AudioStreamError_1.mapStreamError)(original)).toBe(original);
12
+ });
13
+ it('maps native FILE_NOT_FOUND code', () => {
14
+ const mapped = (0, AudioStreamError_1.mapStreamError)({
15
+ code: 'FILE_NOT_FOUND',
16
+ message: 'gone',
17
+ });
18
+ expect(mapped.code).toBe('ERR_AUDIO_STREAM_FILE_NOT_FOUND');
19
+ expect(mapped.recoverable).toBe(false);
20
+ });
21
+ it('maps unsupported codec text', () => {
22
+ const mapped = (0, AudioStreamError_1.mapStreamError)(new Error('No suitable codec for audio/opus'));
23
+ expect(mapped.code).toBe('ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT');
24
+ });
25
+ it('marks cancellation as recoverable', () => {
26
+ const mapped = (0, AudioStreamError_1.mapStreamError)({
27
+ code: 'ERR_AUDIO_STREAM_CANCELLED',
28
+ message: 'user cancelled',
29
+ });
30
+ expect(mapped.code).toBe('ERR_AUDIO_STREAM_CANCELLED');
31
+ expect(mapped.recoverable).toBe(true);
32
+ });
33
+ it('maps backpressure timeout as recoverable', () => {
34
+ const mapped = (0, AudioStreamError_1.mapStreamError)({
35
+ code: 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT',
36
+ message: 'ack timed out',
37
+ });
38
+ expect(mapped.code).toBe('ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT');
39
+ expect(mapped.recoverable).toBe(true);
40
+ });
41
+ it('falls back to UNKNOWN', () => {
42
+ const mapped = (0, AudioStreamError_1.mapStreamError)({});
43
+ expect(mapped.code).toBe('ERR_AUDIO_STREAM_UNKNOWN');
44
+ });
45
+ it('warns when native returns an unknown audio stream code', () => {
46
+ const warn = jest.spyOn(console, 'warn').mockImplementation(() => { });
47
+ const mapped = (0, AudioStreamError_1.mapStreamError)({
48
+ code: 'ERR_AUDIO_STREAM_FOOBAR',
49
+ message: 'new native code',
50
+ });
51
+ expect(mapped.code).toBe('ERR_AUDIO_STREAM_UNKNOWN');
52
+ expect(warn).toHaveBeenCalledWith('[AudioStreamError] Unknown native audio stream error code: ERR_AUDIO_STREAM_FOOBAR');
53
+ warn.mockRestore();
54
+ });
55
+ it('preserves nativeCode and nativeMessage', () => {
56
+ const mapped = (0, AudioStreamError_1.mapStreamError)({
57
+ code: 'WEIRD_NATIVE_CODE',
58
+ message: 'something went wrong on the bridge',
59
+ });
60
+ expect(mapped.nativeCode).toBe('WEIRD_NATIVE_CODE');
61
+ expect(mapped.nativeMessage).toContain('bridge');
62
+ });
63
+ it('serialises to a stable JSON payload', () => {
64
+ const err = new AudioStreamError_1.AudioStreamError({
65
+ code: 'ERR_AUDIO_STREAM_DECODE_FAILED',
66
+ message: 'decoder bust',
67
+ recoverable: false,
68
+ fileUri: 'file:///a.m4a',
69
+ platform: 'ios',
70
+ });
71
+ expect(err.toJSON()).toEqual({
72
+ code: 'ERR_AUDIO_STREAM_DECODE_FAILED',
73
+ message: 'decoder bust',
74
+ recoverable: false,
75
+ fileUri: 'file:///a.m4a',
76
+ platform: 'ios',
77
+ nativeCode: undefined,
78
+ nativeMessage: undefined,
79
+ });
80
+ });
81
+ });
82
+ //# sourceMappingURL=AudioStreamError.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioStreamError.test.js","sourceRoot":"","sources":["../../../src/errors/AudioStreamError.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { AudioStreamError, mapStreamError } from './AudioStreamError'\n\ndescribe('AudioStreamError', () => {\n it('passes through an existing AudioStreamError unchanged', () => {\n const original = new AudioStreamError({\n code: 'ERR_AUDIO_STREAM_CANCELLED',\n message: 'aborted',\n recoverable: true,\n })\n expect(mapStreamError(original)).toBe(original)\n })\n\n it('maps native FILE_NOT_FOUND code', () => {\n const mapped = mapStreamError({\n code: 'FILE_NOT_FOUND',\n message: 'gone',\n })\n expect(mapped.code).toBe('ERR_AUDIO_STREAM_FILE_NOT_FOUND')\n expect(mapped.recoverable).toBe(false)\n })\n\n it('maps unsupported codec text', () => {\n const mapped = mapStreamError(\n new Error('No suitable codec for audio/opus')\n )\n expect(mapped.code).toBe('ERR_AUDIO_STREAM_UNSUPPORTED_FORMAT')\n })\n\n it('marks cancellation as recoverable', () => {\n const mapped = mapStreamError({\n code: 'ERR_AUDIO_STREAM_CANCELLED',\n message: 'user cancelled',\n })\n expect(mapped.code).toBe('ERR_AUDIO_STREAM_CANCELLED')\n expect(mapped.recoverable).toBe(true)\n })\n\n it('maps backpressure timeout as recoverable', () => {\n const mapped = mapStreamError({\n code: 'ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT',\n message: 'ack timed out',\n })\n expect(mapped.code).toBe('ERR_AUDIO_STREAM_BACKPRESSURE_TIMEOUT')\n expect(mapped.recoverable).toBe(true)\n })\n\n it('falls back to UNKNOWN', () => {\n const mapped = mapStreamError({})\n expect(mapped.code).toBe('ERR_AUDIO_STREAM_UNKNOWN')\n })\n\n it('warns when native returns an unknown audio stream code', () => {\n const warn = jest.spyOn(console, 'warn').mockImplementation(() => {})\n const mapped = mapStreamError({\n code: 'ERR_AUDIO_STREAM_FOOBAR',\n message: 'new native code',\n })\n expect(mapped.code).toBe('ERR_AUDIO_STREAM_UNKNOWN')\n expect(warn).toHaveBeenCalledWith(\n '[AudioStreamError] Unknown native audio stream error code: ERR_AUDIO_STREAM_FOOBAR'\n )\n warn.mockRestore()\n })\n\n it('preserves nativeCode and nativeMessage', () => {\n const mapped = mapStreamError({\n code: 'WEIRD_NATIVE_CODE',\n message: 'something went wrong on the bridge',\n })\n expect(mapped.nativeCode).toBe('WEIRD_NATIVE_CODE')\n expect(mapped.nativeMessage).toContain('bridge')\n })\n\n it('serialises to a stable JSON payload', () => {\n const err = new AudioStreamError({\n code: 'ERR_AUDIO_STREAM_DECODE_FAILED',\n message: 'decoder bust',\n recoverable: false,\n fileUri: 'file:///a.m4a',\n platform: 'ios',\n })\n expect(err.toJSON()).toEqual({\n code: 'ERR_AUDIO_STREAM_DECODE_FAILED',\n message: 'decoder bust',\n recoverable: false,\n fileUri: 'file:///a.m4a',\n platform: 'ios',\n nativeCode: undefined,\n nativeMessage: undefined,\n })\n })\n})\n"]}
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.ExpoAudioStreamModule = exports.mapExtractionError = exports.AudioExtractionError = exports.useSharedAudioRecorder = exports.useAudioRecorder = exports.MAX_DURATION_MS = exports.computeMelFrameWasm = exports.initMelStreamingWasm = exports.extractMelSpectrogram = exports.extractAudioData = exports.trimAudio = exports.extractPreview = exports.extractAudioAnalysis = exports.extractRawWavAnalysis = exports.AudioStudioModule = exports.AudioRecorderProvider = exports.extractPreviewBars = exports.setMelSpectrogramWasmUrl = exports.useAudioDevices = exports.audioDeviceManager = exports.AudioDeviceManager = exports.validateRecordingConfig = exports.getFallbackBitDepth = exports.getFallbackEncoding = exports.isBitDepthSupported = exports.isEncodingSupported = exports.getPlatformCapabilities = void 0;
21
+ exports.ExpoAudioStreamModule = exports.mapStreamError = exports.AudioStreamError = exports.mapExtractionError = exports.AudioExtractionError = exports.useSharedAudioRecorder = exports.useAudioRecorder = exports.MAX_DURATION_MS = exports.computeMelFrameWasm = exports.initMelStreamingWasm = exports.extractMelSpectrogram = exports.getAudioDecodeCapabilities = exports.streamAudioData = exports.extractAudioData = exports.trimAudio = exports.extractPreview = exports.extractAudioAnalysis = exports.extractRawWavAnalysis = exports.AudioStudioModule = exports.AudioRecorderProvider = exports.extractPreviewBars = exports.setMelSpectrogramWasmUrl = exports.useAudioDevices = exports.audioDeviceManager = exports.AudioDeviceManager = exports.validateRecordingConfig = exports.getFallbackBitDepth = exports.getFallbackEncoding = exports.isBitDepthSupported = exports.isEncodingSupported = exports.getPlatformCapabilities = void 0;
22
22
  const extractAudioAnalysis_1 = require("./AudioAnalysis/extractAudioAnalysis");
23
23
  Object.defineProperty(exports, "extractRawWavAnalysis", { enumerable: true, get: function () { return extractAudioAnalysis_1.extractRawWavAnalysis; } });
24
24
  Object.defineProperty(exports, "extractAudioAnalysis", { enumerable: true, get: function () { return extractAudioAnalysis_1.extractAudioAnalysis; } });
@@ -37,6 +37,9 @@ Object.defineProperty(exports, "AudioRecorderProvider", { enumerable: true, get:
37
37
  Object.defineProperty(exports, "useSharedAudioRecorder", { enumerable: true, get: function () { return AudioRecorder_provider_1.useSharedAudioRecorder; } });
38
38
  const AudioStudioModule_1 = __importDefault(require("./AudioStudioModule"));
39
39
  exports.AudioStudioModule = AudioStudioModule_1.default;
40
+ const streamAudioData_1 = require("./streamAudioData");
41
+ Object.defineProperty(exports, "getAudioDecodeCapabilities", { enumerable: true, get: function () { return streamAudioData_1.getAudioDecodeCapabilities; } });
42
+ Object.defineProperty(exports, "streamAudioData", { enumerable: true, get: function () { return streamAudioData_1.streamAudioData; } });
40
43
  const trimAudio_1 = require("./trimAudio");
41
44
  Object.defineProperty(exports, "trimAudio", { enumerable: true, get: function () { return trimAudio_1.trimAudio; } });
42
45
  const useAudioRecorder_1 = require("./useAudioRecorder");
@@ -66,6 +69,9 @@ Object.defineProperty(exports, "extractPreviewBars", { enumerable: true, get: fu
66
69
  var AudioExtractionError_1 = require("./errors/AudioExtractionError");
67
70
  Object.defineProperty(exports, "AudioExtractionError", { enumerable: true, get: function () { return AudioExtractionError_1.AudioExtractionError; } });
68
71
  Object.defineProperty(exports, "mapExtractionError", { enumerable: true, get: function () { return AudioExtractionError_1.mapExtractionError; } });
72
+ var AudioStreamError_1 = require("./errors/AudioStreamError");
73
+ Object.defineProperty(exports, "AudioStreamError", { enumerable: true, get: function () { return AudioStreamError_1.AudioStreamError; } });
74
+ Object.defineProperty(exports, "mapStreamError", { enumerable: true, get: function () { return AudioStreamError_1.mapStreamError; } });
69
75
  /** @deprecated Use AudioStudioModule instead */
70
76
  exports.ExpoAudioStreamModule = AudioStudioModule_1.default;
71
77
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,eAAe;;;;;;;;;;;;;;;;;;;;AAEf,+EAG6C;AA8CzC,sGAhDA,4CAAqB,OAgDA;AACrB,qGAhDA,2CAAoB,OAgDA;AA9CxB,uEAAmE;AAiD/D,iGAjDK,mCAAgB,OAiDL;AAhDpB,iFAG8C;AA8C1C,sGAhDA,6CAAqB,OAgDA;AAGrB,gGAlDA,uCAAe,OAkDA;AAhDnB,mEAA+D;AA0C3D,+FA1CK,+BAAc,OA0CL;AAzClB,2EAG2C;AA0CvC,qGA5CA,yCAAoB,OA4CA;AACpB,oGA5CA,wCAAmB,OA4CA;AA1CvB,qEAGiC;AA8B7B,sGAhCA,8CAAqB,OAgCA;AAYrB,uGA3CA,+CAAsB,OA2CA;AAzC1B,4EAAmD;AA8B/C,4BA9BG,2BAAiB,CA8BH;AA7BrB,2CAAuC;AAiCnC,0FAjCK,qBAAS,OAiCL;AAhCb,yDAAqD;AAsCjD,iGAtCK,mCAAgB,OAsCL;AApCpB,8DAA2C;AAC3C,yDAAsC;AACtC,yDAAsC;AAEtC,+BAA+B;AAC/B,uEAQwC;AAPpC,8HAAA,uBAAuB,OAAA;AACvB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AACnB,8HAAA,uBAAuB,OAAA;AAI3B,4BAA4B;AAC5B,2DAA6E;AAApE,wHAAA,kBAAkB,OAAA;AAAE,wHAAA,kBAAkB,OAAA;AAE/C,8BAA8B;AAC9B,2DAAyD;AAAhD,kHAAA,eAAe,OAAA;AAExB,yDAAqE;AAA5D,sHAAA,wBAAwB,OAAA;AACjC,yEAAuE;AAA9D,wHAAA,kBAAkB,OAAA;AAkB3B,sEAGsC;AAFlC,4HAAA,oBAAoB,OAAA;AACpB,0HAAA,kBAAkB,OAAA;AAWtB,gDAAgD;AACnC,QAAA,qBAAqB,GAAG,2BAAiB,CAAA","sourcesContent":["// src/index.ts\n\nimport {\n extractRawWavAnalysis,\n extractAudioAnalysis,\n} from './AudioAnalysis/extractAudioAnalysis'\nimport { extractAudioData } from './AudioAnalysis/extractAudioData'\nimport {\n extractMelSpectrogram,\n MAX_DURATION_MS,\n} from './AudioAnalysis/extractMelSpectrogram'\nimport { extractPreview } from './AudioAnalysis/extractPreview'\nimport {\n initMelStreamingWasm,\n computeMelFrameWasm,\n} from './AudioAnalysis/melSpectrogramWasm'\nimport {\n AudioRecorderProvider,\n useSharedAudioRecorder,\n} from './AudioRecorder.provider'\nimport AudioStudioModule from './AudioStudioModule'\nimport { trimAudio } from './trimAudio'\nimport { useAudioRecorder } from './useAudioRecorder'\n\nexport * from './utils/convertPCMToFloat32'\nexport * from './utils/getWavFileInfo'\nexport * from './utils/writeWavHeader'\n\n// Export platform capabilities\nexport {\n getPlatformCapabilities,\n isEncodingSupported,\n isBitDepthSupported,\n getFallbackEncoding,\n getFallbackBitDepth,\n validateRecordingConfig,\n type PlatformCapabilities,\n} from './constants/platformLimitations'\n\n// Export AudioDeviceManager\nexport { AudioDeviceManager, audioDeviceManager } from './AudioDeviceManager'\n\n// Export useAudioDevices hook\nexport { useAudioDevices } from './hooks/useAudioDevices'\n\nexport { setMelSpectrogramWasmUrl } from './AudioAnalysis/wasmConfig'\nexport { extractPreviewBars } from './AudioAnalysis/extractPreviewBars'\n\nexport {\n AudioRecorderProvider,\n AudioStudioModule,\n extractRawWavAnalysis,\n extractAudioAnalysis,\n extractPreview,\n trimAudio,\n extractAudioData,\n extractMelSpectrogram,\n initMelStreamingWasm,\n computeMelFrameWasm,\n MAX_DURATION_MS,\n useAudioRecorder,\n useSharedAudioRecorder,\n}\n\nexport {\n AudioExtractionError,\n mapExtractionError,\n} from './errors/AudioExtractionError'\nexport type {\n AudioExtractionErrorCode,\n AudioExtractionErrorPayload,\n} from './errors/AudioExtractionError'\n\n// Export all types\nexport type * from './AudioAnalysis/AudioAnalysis.types'\nexport type * from './AudioStudio.types'\n\n/** @deprecated Use AudioStudioModule instead */\nexport const ExpoAudioStreamModule = AudioStudioModule\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,eAAe;;;;;;;;;;;;;;;;;;;;AAEf,+EAG6C;AAkDzC,sGApDA,4CAAqB,OAoDA;AACrB,qGApDA,2CAAoB,OAoDA;AAlDxB,uEAAmE;AAqD/D,iGArDK,mCAAgB,OAqDL;AApDpB,iFAG8C;AAoD1C,sGAtDA,6CAAqB,OAsDA;AAGrB,gGAxDA,uCAAe,OAwDA;AAtDnB,mEAA+D;AA8C3D,+FA9CK,+BAAc,OA8CL;AA7ClB,2EAG2C;AAgDvC,qGAlDA,yCAAoB,OAkDA;AACpB,oGAlDA,wCAAmB,OAkDA;AAhDvB,qEAGiC;AAkC7B,sGApCA,8CAAqB,OAoCA;AAcrB,uGAjDA,+CAAsB,OAiDA;AA/C1B,4EAAmD;AAkC/C,4BAlCG,2BAAiB,CAkCH;AAjCrB,uDAG0B;AAqCtB,2GAvCA,4CAA0B,OAuCA;AAD1B,gGArCA,iCAAe,OAqCA;AAnCnB,2CAAuC;AAiCnC,0FAjCK,qBAAS,OAiCL;AAhCb,yDAAqD;AAwCjD,iGAxCK,mCAAgB,OAwCL;AAtCpB,8DAA2C;AAC3C,yDAAsC;AACtC,yDAAsC;AAEtC,+BAA+B;AAC/B,uEAQwC;AAPpC,8HAAA,uBAAuB,OAAA;AACvB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AACnB,8HAAA,uBAAuB,OAAA;AAI3B,4BAA4B;AAC5B,2DAA6E;AAApE,wHAAA,kBAAkB,OAAA;AAAE,wHAAA,kBAAkB,OAAA;AAE/C,8BAA8B;AAC9B,2DAAyD;AAAhD,kHAAA,eAAe,OAAA;AAExB,yDAAqE;AAA5D,sHAAA,wBAAwB,OAAA;AACjC,yEAAuE;AAA9D,wHAAA,kBAAkB,OAAA;AAoB3B,sEAGsC;AAFlC,4HAAA,oBAAoB,OAAA;AACpB,0HAAA,kBAAkB,OAAA;AAOtB,8DAGkC;AAF9B,oHAAA,gBAAgB,OAAA;AAChB,kHAAA,cAAc,OAAA;AAoBlB,gDAAgD;AACnC,QAAA,qBAAqB,GAAG,2BAAiB,CAAA","sourcesContent":["// src/index.ts\n\nimport {\n extractRawWavAnalysis,\n extractAudioAnalysis,\n} from './AudioAnalysis/extractAudioAnalysis'\nimport { extractAudioData } from './AudioAnalysis/extractAudioData'\nimport {\n extractMelSpectrogram,\n MAX_DURATION_MS,\n} from './AudioAnalysis/extractMelSpectrogram'\nimport { extractPreview } from './AudioAnalysis/extractPreview'\nimport {\n initMelStreamingWasm,\n computeMelFrameWasm,\n} from './AudioAnalysis/melSpectrogramWasm'\nimport {\n AudioRecorderProvider,\n useSharedAudioRecorder,\n} from './AudioRecorder.provider'\nimport AudioStudioModule from './AudioStudioModule'\nimport {\n getAudioDecodeCapabilities,\n streamAudioData,\n} from './streamAudioData'\nimport { trimAudio } from './trimAudio'\nimport { useAudioRecorder } from './useAudioRecorder'\n\nexport * from './utils/convertPCMToFloat32'\nexport * from './utils/getWavFileInfo'\nexport * from './utils/writeWavHeader'\n\n// Export platform capabilities\nexport {\n getPlatformCapabilities,\n isEncodingSupported,\n isBitDepthSupported,\n getFallbackEncoding,\n getFallbackBitDepth,\n validateRecordingConfig,\n type PlatformCapabilities,\n} from './constants/platformLimitations'\n\n// Export AudioDeviceManager\nexport { AudioDeviceManager, audioDeviceManager } from './AudioDeviceManager'\n\n// Export useAudioDevices hook\nexport { useAudioDevices } from './hooks/useAudioDevices'\n\nexport { setMelSpectrogramWasmUrl } from './AudioAnalysis/wasmConfig'\nexport { extractPreviewBars } from './AudioAnalysis/extractPreviewBars'\n\nexport {\n AudioRecorderProvider,\n AudioStudioModule,\n extractRawWavAnalysis,\n extractAudioAnalysis,\n extractPreview,\n trimAudio,\n extractAudioData,\n streamAudioData,\n getAudioDecodeCapabilities,\n extractMelSpectrogram,\n initMelStreamingWasm,\n computeMelFrameWasm,\n MAX_DURATION_MS,\n useAudioRecorder,\n useSharedAudioRecorder,\n}\n\nexport {\n AudioExtractionError,\n mapExtractionError,\n} from './errors/AudioExtractionError'\nexport type {\n AudioExtractionErrorCode,\n AudioExtractionErrorPayload,\n} from './errors/AudioExtractionError'\n\nexport {\n AudioStreamError,\n mapStreamError,\n} from './errors/AudioStreamError'\nexport type {\n AudioStreamErrorCode,\n AudioStreamErrorPayload,\n} from './errors/AudioStreamError'\n\nexport type {\n StreamAudioDataOptions,\n StreamAudioDataChunk,\n StreamAudioDataProgress,\n StreamAudioDataResult,\n StreamAudioDataCallbacks,\n AudioDecodeCapabilities,\n} from './streamAudioData'\n\n// Export all types\nexport type * from './AudioAnalysis/AudioAnalysis.types'\nexport type * from './AudioStudio.types'\n\n/** @deprecated Use AudioStudioModule instead */\nexport const ExpoAudioStreamModule = AudioStudioModule\n"]}