@siteed/expo-audio-stream 1.17.0 → 2.0.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 (72) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/README.md +1 -1
  3. package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +68 -22
  4. package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +24 -0
  5. package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +836 -386
  6. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -2
  7. package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +35 -29
  8. package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +236 -96
  9. package/android/src/main/java/net/siteed/audiostream/FFT.kt +55 -0
  10. package/android/src/main/java/net/siteed/audiostream/Features.kt +49 -7
  11. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +2 -4
  12. package/build/AudioAnalysis/AudioAnalysis.types.d.ts +55 -47
  13. package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -1
  14. package/build/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
  15. package/build/AudioAnalysis/extractAudioAnalysis.d.ts +60 -13
  16. package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -1
  17. package/build/AudioAnalysis/extractAudioAnalysis.js +147 -162
  18. package/build/AudioAnalysis/extractAudioAnalysis.js.map +1 -1
  19. package/build/ExpoAudioStream.types.d.ts +47 -3
  20. package/build/ExpoAudioStream.types.d.ts.map +1 -1
  21. package/build/ExpoAudioStream.types.js.map +1 -1
  22. package/build/ExpoAudioStream.web.d.ts.map +1 -1
  23. package/build/ExpoAudioStream.web.js +0 -1
  24. package/build/ExpoAudioStream.web.js.map +1 -1
  25. package/build/ExpoAudioStreamModule.d.ts.map +1 -1
  26. package/build/ExpoAudioStreamModule.js +216 -12
  27. package/build/ExpoAudioStreamModule.js.map +1 -1
  28. package/build/WebRecorder.web.d.ts +67 -13
  29. package/build/WebRecorder.web.d.ts.map +1 -1
  30. package/build/WebRecorder.web.js +177 -173
  31. package/build/WebRecorder.web.js.map +1 -1
  32. package/build/index.d.ts +3 -3
  33. package/build/index.d.ts.map +1 -1
  34. package/build/index.js +2 -2
  35. package/build/index.js.map +1 -1
  36. package/build/useAudioRecorder.d.ts.map +1 -1
  37. package/build/useAudioRecorder.js +12 -8
  38. package/build/useAudioRecorder.js.map +1 -1
  39. package/build/utils/audioProcessing.d.ts +24 -0
  40. package/build/utils/audioProcessing.d.ts.map +1 -0
  41. package/build/utils/audioProcessing.js +133 -0
  42. package/build/utils/audioProcessing.js.map +1 -0
  43. package/build/workers/InlineFeaturesExtractor.web.d.ts +1 -1
  44. package/build/workers/InlineFeaturesExtractor.web.d.ts.map +1 -1
  45. package/build/workers/InlineFeaturesExtractor.web.js +694 -194
  46. package/build/workers/InlineFeaturesExtractor.web.js.map +1 -1
  47. package/build/workers/inlineAudioWebWorker.web.d.ts +1 -1
  48. package/build/workers/inlineAudioWebWorker.web.d.ts.map +1 -1
  49. package/build/workers/inlineAudioWebWorker.web.js +3 -2
  50. package/build/workers/inlineAudioWebWorker.web.js.map +1 -1
  51. package/ios/AudioAnalysisData.swift +51 -16
  52. package/ios/AudioProcessingHelpers.swift +710 -26
  53. package/ios/AudioProcessor.swift +334 -185
  54. package/ios/AudioStreamManager.swift +2 -3
  55. package/ios/DataPoint.swift +25 -12
  56. package/ios/DecodingConfig.swift +47 -0
  57. package/ios/ExpoAudioStreamModule.swift +187 -103
  58. package/ios/FFT.swift +62 -0
  59. package/ios/Features.swift +24 -3
  60. package/ios/RecordingSettings.swift +7 -7
  61. package/package.json +2 -1
  62. package/src/AudioAnalysis/AudioAnalysis.types.ts +68 -52
  63. package/src/AudioAnalysis/extractAudioAnalysis.ts +223 -219
  64. package/src/ExpoAudioStream.types.ts +53 -7
  65. package/src/ExpoAudioStream.web.ts +0 -1
  66. package/src/ExpoAudioStreamModule.ts +255 -10
  67. package/src/WebRecorder.web.ts +231 -244
  68. package/src/index.ts +5 -3
  69. package/src/useAudioRecorder.tsx +14 -10
  70. package/src/utils/audioProcessing.ts +205 -0
  71. package/src/workers/InlineFeaturesExtractor.web.tsx +694 -194
  72. package/src/workers/inlineAudioWebWorker.web.tsx +3 -2
@@ -1,131 +1,130 @@
1
+ // packages/expo-audio-stream/src/AudioAnalysis/extractAudioAnalysis.ts
2
+ /**
3
+ * This module provides functions for extracting and analyzing audio data.
4
+ * - `extractAudioAnalysis`: For detailed analysis with customizable ranges and decoding options.
5
+ * - `extractWavAudioAnalysis`: For analyzing WAV files without decoding, preserving original PCM values.
6
+ * - `extractPreview`: For generating quick previews of audio waveforms, optimized for UI rendering.
7
+ */
8
+ import crc32 from 'crc-32';
1
9
  import ExpoAudioStreamModule from '../ExpoAudioStreamModule';
2
10
  import { isWeb } from '../constants';
11
+ import { processAudioBuffer } from '../utils/audioProcessing';
3
12
  import { convertPCMToFloat32 } from '../utils/convertPCMToFloat32';
4
13
  import { getWavFileInfo } from '../utils/getWavFileInfo';
5
14
  import { InlineFeaturesExtractor } from '../workers/InlineFeaturesExtractor.web';
6
- export async function extractAudioFromAnyFormat({ fileUri, arrayBuffer, mimeType, decodingOptions, startTime, endTime, ...restProps }) {
15
+ function calculateCRC32ForDataPoint(data) {
16
+ // Convert float array to byte array for CRC32
17
+ const byteArray = new Uint8Array(data.length * 4);
18
+ const dataView = new DataView(byteArray.buffer);
19
+ for (let i = 0; i < data.length; i++) {
20
+ dataView.setFloat32(i * 4, data[i], true);
21
+ }
22
+ return crc32.buf(byteArray);
23
+ }
24
+ /**
25
+ * Extracts detailed audio analysis from the specified audio file or buffer.
26
+ * Supports either time-based or byte-based ranges for flexibility in analysis.
27
+ *
28
+ * @param props - The options for extraction, including file URI, ranges, and decoding settings.
29
+ * @returns A promise that resolves to the audio analysis data.
30
+ * @throws {Error} If both time and byte ranges are provided or if required parameters are missing.
31
+ */
32
+ export async function extractAudioAnalysis(props) {
33
+ const { fileUri, arrayBuffer, decodingOptions, logger, segmentDurationMs = 100, features, } = props;
7
34
  if (isWeb) {
8
35
  try {
9
- // Get the audio data
10
- let audioBuffer;
11
- if (arrayBuffer) {
12
- audioBuffer = arrayBuffer;
13
- }
14
- else if (fileUri) {
15
- const response = await fetch(fileUri);
16
- if (!response.ok) {
17
- throw new Error(`Failed to fetch fileUri: ${response.statusText}`);
18
- }
19
- audioBuffer = await response.arrayBuffer();
20
- }
21
- else {
22
- throw new Error('Either arrayBuffer or fileUri must be provided');
23
- }
24
- // Create audio context with target sample rate if specified
36
+ // Create AudioContext here
25
37
  const audioContext = new (window.AudioContext ||
26
38
  window.webkitAudioContext)({
27
- sampleRate: decodingOptions?.targetSampleRate,
28
- });
29
- // Decode the audio data
30
- const decodedAudioBuffer = await audioContext.decodeAudioData(audioBuffer);
31
- // Calculate the actual duration in milliseconds
32
- const fullDurationMs = decodedAudioBuffer.duration * 1000;
33
- const effectiveDurationMs = endTime
34
- ? endTime - (startTime || 0)
35
- : fullDurationMs - (startTime || 0);
36
- // Create a new buffer for the selected range
37
- const rangeLength = decodedAudioBuffer.length;
38
- const rangeBuffer = new AudioBuffer({
39
- length: rangeLength,
40
- numberOfChannels: decodedAudioBuffer.numberOfChannels,
41
- sampleRate: decodedAudioBuffer.sampleRate,
39
+ sampleRate: decodingOptions?.targetSampleRate ?? 16000,
42
40
  });
43
- // Copy the selected range
44
- for (let channel = 0; channel < decodedAudioBuffer.numberOfChannels; channel++) {
45
- const channelData = decodedAudioBuffer.getChannelData(channel);
46
- const rangeData = channelData.slice(0, rangeLength);
47
- rangeBuffer.copyToChannel(rangeData, channel);
48
- }
49
- // Use the range buffer instead of the full buffer
50
- let processedBuffer = rangeBuffer;
51
- // Get original properties
52
- const originalSampleRate = processedBuffer.sampleRate;
53
- const length = processedBuffer.length;
54
- // Determine target format
55
- const targetChannels = decodingOptions?.targetChannels ??
56
- processedBuffer.numberOfChannels;
57
- const targetSampleRate = decodingOptions?.targetSampleRate ?? processedBuffer.sampleRate;
58
- // Create offline context for resampling if needed
59
- if (targetSampleRate !== originalSampleRate) {
60
- const offlineCtx = new OfflineAudioContext(targetChannels, (length * targetSampleRate) / originalSampleRate, targetSampleRate);
61
- const source = offlineCtx.createBufferSource();
62
- source.buffer = processedBuffer;
63
- source.connect(offlineCtx.destination);
64
- source.start();
65
- processedBuffer = await offlineCtx.startRendering();
66
- }
67
- // Convert to the desired format
68
- const newLength = processedBuffer.length;
69
- let wavBuffer;
70
- // Create appropriate buffer based on target bit depth
71
- switch (decodingOptions?.targetBitDepth) {
72
- case 16:
73
- wavBuffer = new Int16Array(newLength * targetChannels);
74
- break;
75
- case 8:
76
- wavBuffer = new Int8Array(newLength * targetChannels);
77
- break;
78
- case 32:
79
- default:
80
- wavBuffer = new Float32Array(newLength * targetChannels);
81
- break;
41
+ try {
42
+ const processedBuffer = await processAudioBuffer({
43
+ arrayBuffer,
44
+ fileUri,
45
+ targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,
46
+ targetChannels: decodingOptions?.targetChannels ?? 1,
47
+ normalizeAudio: decodingOptions?.normalizeAudio ?? false,
48
+ startTimeMs: 'startTimeMs' in props ? props.startTimeMs : undefined,
49
+ endTimeMs: 'endTimeMs' in props ? props.endTimeMs : undefined,
50
+ position: 'position' in props ? props.position : undefined,
51
+ length: 'length' in props ? props.length : undefined,
52
+ audioContext, // Pass the context we created
53
+ logger,
54
+ });
55
+ const channelData = processedBuffer.buffer.getChannelData(0);
56
+ // Create and initialize the worker
57
+ const blob = new Blob([InlineFeaturesExtractor], {
58
+ type: 'application/javascript',
59
+ });
60
+ const workerUrl = URL.createObjectURL(blob);
61
+ const worker = new Worker(workerUrl);
62
+ return new Promise((resolve, reject) => {
63
+ worker.onmessage = (event) => {
64
+ if (event.data.error) {
65
+ reject(new Error(event.data.error));
66
+ return;
67
+ }
68
+ const result = event.data.result;
69
+ // Calculate CRC32 after worker completes if requested
70
+ if (features?.crc32) {
71
+ const samplesPerSegment = Math.floor((processedBuffer.sampleRate *
72
+ segmentDurationMs) /
73
+ 1000);
74
+ result.dataPoints = result.dataPoints.map((point, index) => {
75
+ const startSample = index * samplesPerSegment;
76
+ const segmentData = channelData.slice(startSample, startSample + samplesPerSegment);
77
+ return {
78
+ ...point,
79
+ features: {
80
+ ...point.features,
81
+ crc32: calculateCRC32ForDataPoint(segmentData),
82
+ },
83
+ };
84
+ });
85
+ }
86
+ URL.revokeObjectURL(workerUrl);
87
+ worker.terminate();
88
+ resolve(result);
89
+ };
90
+ worker.onerror = (error) => {
91
+ URL.revokeObjectURL(workerUrl);
92
+ worker.terminate();
93
+ reject(error);
94
+ };
95
+ worker.postMessage({
96
+ channelData,
97
+ sampleRate: processedBuffer.sampleRate,
98
+ segmentDurationMs,
99
+ bitDepth: decodingOptions?.targetBitDepth ?? 32,
100
+ numberOfChannels: processedBuffer.channels,
101
+ // enableLogging: !!logger,
102
+ features,
103
+ });
104
+ });
82
105
  }
83
- // Interleave channels and handle bit depth conversion
84
- const numChannels = Math.min(processedBuffer.numberOfChannels, targetChannels);
85
- for (let channel = 0; channel < numChannels; channel++) {
86
- const channelData = processedBuffer.getChannelData(channel);
87
- for (let i = 0; i < newLength; i++) {
88
- let sample = channelData[i];
89
- // Normalize if requested
90
- if (decodingOptions?.normalizeAudio) {
91
- sample = Math.max(-1, Math.min(1, sample));
92
- }
93
- // Convert sample based on target bit depth
94
- if (decodingOptions?.targetBitDepth === 16) {
95
- sample = sample * 32767; // Convert to 16-bit range
96
- }
97
- else if (decodingOptions?.targetBitDepth === 8) {
98
- sample = sample * 127; // Convert to 8-bit range
99
- }
100
- wavBuffer[i * targetChannels + channel] = sample;
101
- }
106
+ finally {
107
+ await audioContext.close();
102
108
  }
103
- // Pass the duration to extractAudioAnalysis
104
- return await extractAudioAnalysis({
105
- arrayBuffer: wavBuffer.buffer,
106
- bitDepth: decodingOptions?.targetBitDepth ?? 32,
107
- skipWavHeader: true,
108
- sampleRate: targetSampleRate,
109
- numberOfChannels: targetChannels,
110
- durationMs: effectiveDurationMs,
111
- ...restProps,
112
- });
113
109
  }
114
110
  catch (error) {
115
- console.error('Failed to process audio:', error);
111
+ logger?.error('Failed to process audio:', error);
116
112
  throw error;
117
113
  }
118
114
  }
119
115
  else {
120
- // For native platforms, pass through all options
121
- return await extractAudioAnalysis({
122
- fileUri,
123
- decodingOptions,
124
- ...restProps,
125
- });
116
+ return await ExpoAudioStreamModule.extractAudioAnalysis(props);
126
117
  }
127
118
  }
128
- export const extractAudioAnalysis = async ({ fileUri, pointsPerSecond = 20, arrayBuffer, bitDepth, skipWavHeader = true, durationMs, sampleRate, numberOfChannels, algorithm = 'rms', features, featuresExtratorUrl, logger, }) => {
119
+ /**
120
+ * Analyzes WAV files without decoding, preserving original PCM values.
121
+ * Use this function when you need to ensure the analysis matches other software by avoiding any transformations.
122
+ *
123
+ * @param props - The options for WAV analysis, including file URI and range.
124
+ * @returns A promise that resolves to the audio analysis data.
125
+ */
126
+ export const extractRawWavAnalysis = async ({ fileUri, segmentDurationMs = 100, // Default to 100ms
127
+ arrayBuffer, bitDepth, durationMs, sampleRate, numberOfChannels, features, logger, position = 0, length, }) => {
129
128
  if (isWeb) {
130
129
  if (!arrayBuffer && !fileUri) {
131
130
  throw new Error('Either arrayBuffer or fileUri must be provided');
@@ -141,7 +140,7 @@ export const extractAudioAnalysis = async ({ fileUri, pointsPerSecond = 20, arra
141
140
  }
142
141
  // Create a new copy of the ArrayBuffer to avoid detachment issues
143
142
  const bufferCopy = arrayBuffer.slice(0);
144
- logger?.log(`extractAudioAnalysis skipWavHeader=${skipWavHeader} bitDepth=${bitDepth} len=${bufferCopy.byteLength}`, bufferCopy.slice(0, 100));
143
+ logger?.log(`extractAudioAnalysis bitDepth=${bitDepth} len=${bufferCopy.byteLength}`, bufferCopy.slice(0, 100));
145
144
  let actualBitDepth = bitDepth;
146
145
  if (!actualBitDepth) {
147
146
  logger?.log(`extractAudioAnalysis bitDepth not provided -- getting wav file info`);
@@ -152,21 +151,18 @@ export const extractAudioAnalysis = async ({ fileUri, pointsPerSecond = 20, arra
152
151
  const { pcmValues: channelData, min, max, } = await convertPCMToFloat32({
153
152
  buffer: arrayBuffer,
154
153
  bitDepth: actualBitDepth,
155
- skipWavHeader,
156
154
  });
157
- logger?.log(`extractAudioAnalysis skipWaveHeader=${skipWavHeader} convertPCMToFloat32 length=${channelData.length} range: [ ${min} :: ${max} ]`);
155
+ logger?.log(`extractAudioAnalysis convertPCMToFloat32 length=${channelData.length} range: [ ${min} :: ${max} ]`);
156
+ // Apply position and length constraints to channelData if specified
157
+ const startIndex = position;
158
+ const endIndex = length ? startIndex + length : channelData.length;
159
+ const constrainedChannelData = channelData.slice(startIndex, endIndex);
158
160
  return new Promise((resolve, reject) => {
159
- let worker;
160
- if (featuresExtratorUrl) {
161
- worker = new Worker(new URL(featuresExtratorUrl, window.location.href));
162
- }
163
- else {
164
- const blob = new Blob([InlineFeaturesExtractor], {
165
- type: 'application/javascript',
166
- });
167
- const url = URL.createObjectURL(blob);
168
- worker = new Worker(url);
169
- }
161
+ const blob = new Blob([InlineFeaturesExtractor], {
162
+ type: 'application/javascript',
163
+ });
164
+ const url = URL.createObjectURL(blob);
165
+ const worker = new Worker(url);
170
166
  worker.onmessage = (event) => {
171
167
  resolve(event.data.result);
172
168
  };
@@ -175,10 +171,10 @@ export const extractAudioAnalysis = async ({ fileUri, pointsPerSecond = 20, arra
175
171
  };
176
172
  worker.postMessage({
177
173
  command: 'process',
178
- channelData,
174
+ channelData: constrainedChannelData,
179
175
  sampleRate,
180
- pointsPerSecond,
181
- algorithm,
176
+ segmentDurationMs,
177
+ logger,
182
178
  bitDepth,
183
179
  fullAudioDurationMs: durationMs,
184
180
  numberOfChannels,
@@ -191,54 +187,43 @@ export const extractAudioAnalysis = async ({ fileUri, pointsPerSecond = 20, arra
191
187
  }
192
188
  logger?.log(`extractAudioAnalysis`, {
193
189
  fileUri,
194
- pointsPerSecond,
195
- algorithm,
190
+ segmentDurationMs,
196
191
  });
197
192
  const res = await ExpoAudioStreamModule.extractAudioAnalysis({
198
193
  fileUri,
199
- pointsPerSecond,
200
- skipWavHeader,
201
- algorithm,
194
+ segmentDurationMs,
202
195
  features,
196
+ position,
197
+ length,
203
198
  });
204
199
  logger?.log(`extractAudioAnalysis`, res);
205
200
  return res;
206
201
  }
207
202
  };
208
- export async function extractPreview({ fileUri, numberOfPoints, algorithm = 'rms', startTime, endTime, decodingOptions, }) {
209
- if (isWeb) {
210
- // For web, we can reuse the existing extractAudioFromAnyFormat with modified parameters
211
- const analysis = await extractAudioFromAnyFormat({
212
- fileUri,
213
- algorithm,
214
- decodingOptions,
215
- startTime, // Pass startTime
216
- endTime, // Pass endTime
217
- pointsPerSecond: (numberOfPoints ?? 100) /
218
- ((endTime ? endTime - (startTime || 0) : 1000) / 1000), // Adjust points per second calculation
219
- });
220
- // Convert AudioAnalysis to AudioPreview format and adjust duration
221
- return {
222
- pointsPerSecond: analysis.pointsPerSecond,
223
- durationMs: endTime
224
- ? endTime - (startTime || 0)
225
- : analysis.durationMs, // Use range duration if specified
226
- amplitudeRange: analysis.amplitudeRange,
227
- dataPoints: analysis.dataPoints.map((point) => ({
228
- id: point.id,
229
- amplitude: point.amplitude,
230
- startTime: point.startTime,
231
- endTime: point.endTime,
232
- })),
233
- };
234
- }
235
- return await ExpoAudioStreamModule.extractPreview({
203
+ /**
204
+ * Generates a simplified preview of the audio waveform for quick visualization.
205
+ * Ideal for UI rendering with a specified number of points.
206
+ *
207
+ * @param options - The options for the preview, including file URI and time range.
208
+ * @returns A promise that resolves to the audio preview data.
209
+ */
210
+ export async function extractPreview({ fileUri, numberOfPoints = 100, startTimeMs = 0, endTimeMs = 30000, // First 30 seconds
211
+ decodingOptions, logger, }) {
212
+ const durationMs = endTimeMs - startTimeMs;
213
+ const segmentDurationMs = Math.floor(durationMs / numberOfPoints);
214
+ // Call extractAudioAnalysis with calculated parameters
215
+ const analysis = await extractAudioAnalysis({
236
216
  fileUri,
237
- numberOfPoints,
238
- algorithm,
239
- startTime,
240
- endTime,
217
+ startTimeMs,
218
+ endTimeMs,
219
+ logger,
220
+ segmentDurationMs,
241
221
  decodingOptions,
242
222
  });
223
+ // Transform the result into AudioPreview format
224
+ return analysis;
243
225
  }
226
+ export const extractAudioData = async (props) => {
227
+ return await ExpoAudioStreamModule.extractAudioData(props);
228
+ };
244
229
  //# sourceMappingURL=extractAudioAnalysis.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extractAudioAnalysis.js","sourceRoot":"","sources":["../../src/AudioAnalysis/extractAudioAnalysis.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/expo-audio-stream/src/AudioAnalysis/extractAudioAnalysis.ts\nimport { ConsoleLike } from '../ExpoAudioStream.types'\nimport ExpoAudioStreamModule from '../ExpoAudioStreamModule'\nimport { isWeb } from '../constants'\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n AudioPreview,\n DecodingConfig,\n PreviewOptions,\n} from './AudioAnalysis.types'\nimport { convertPCMToFloat32 } from '../utils/convertPCMToFloat32'\nimport { getWavFileInfo, WavFileInfo } from '../utils/getWavFileInfo'\nimport { InlineFeaturesExtractor } from '../workers/InlineFeaturesExtractor.web'\n\nexport interface ExtractAudioAnalysisProps {\n fileUri?: string // should provide either fileUri or arrayBuffer\n wavMetadata?: WavFileInfo\n arrayBuffer?: ArrayBuffer\n bitDepth?: number\n skipWavHeader?: boolean\n durationMs?: number\n sampleRate?: number\n numberOfChannels?: number\n algorithm?: AmplitudeAlgorithm\n position?: number // Optional number of bytes to skip. Default is 0\n length?: number // Optional number of bytes to read.\n pointsPerSecond?: number // Optional number of points per second. Use to reduce the number of points and compute the number of datapoints to return.\n features?: AudioFeaturesOptions\n featuresExtratorUrl?: string\n logger?: ConsoleLike\n decodingOptions?: DecodingConfig\n}\n\nexport interface ExtractAudioFromAnyFormatProps\n extends ExtractAudioAnalysisProps {\n mimeType?: string\n decodingOptions?: DecodingConfig\n startTime?: number // Add start time in milliseconds\n endTime?: number // Add end time in milliseconds\n}\n\nexport async function extractAudioFromAnyFormat({\n fileUri,\n arrayBuffer,\n mimeType,\n decodingOptions,\n startTime,\n endTime,\n ...restProps\n}: ExtractAudioFromAnyFormatProps): Promise<AudioAnalysis> {\n if (isWeb) {\n try {\n // Get the audio data\n let audioBuffer: ArrayBuffer\n if (arrayBuffer) {\n audioBuffer = arrayBuffer\n } else if (fileUri) {\n const response = await fetch(fileUri)\n if (!response.ok) {\n throw new Error(\n `Failed to fetch fileUri: ${response.statusText}`\n )\n }\n audioBuffer = await response.arrayBuffer()\n } else {\n throw new Error(\n 'Either arrayBuffer or fileUri must be provided'\n )\n }\n\n // Create audio context with target sample rate if specified\n const audioContext = new (window.AudioContext ||\n (window as any).webkitAudioContext)({\n sampleRate: decodingOptions?.targetSampleRate,\n })\n\n // Decode the audio data\n const decodedAudioBuffer =\n await audioContext.decodeAudioData(audioBuffer)\n\n // Calculate the actual duration in milliseconds\n const fullDurationMs = decodedAudioBuffer.duration * 1000\n const effectiveDurationMs = endTime\n ? endTime - (startTime || 0)\n : fullDurationMs - (startTime || 0)\n\n // Create a new buffer for the selected range\n const rangeLength = decodedAudioBuffer.length\n const rangeBuffer = new AudioBuffer({\n length: rangeLength,\n numberOfChannels: decodedAudioBuffer.numberOfChannels,\n sampleRate: decodedAudioBuffer.sampleRate,\n })\n\n // Copy the selected range\n for (\n let channel = 0;\n channel < decodedAudioBuffer.numberOfChannels;\n channel++\n ) {\n const channelData = decodedAudioBuffer.getChannelData(channel)\n const rangeData = channelData.slice(0, rangeLength)\n rangeBuffer.copyToChannel(rangeData, channel)\n }\n\n // Use the range buffer instead of the full buffer\n let processedBuffer = rangeBuffer\n\n // Get original properties\n const originalSampleRate = processedBuffer.sampleRate\n const length = processedBuffer.length\n\n // Determine target format\n const targetChannels =\n decodingOptions?.targetChannels ??\n processedBuffer.numberOfChannels\n const targetSampleRate =\n decodingOptions?.targetSampleRate ?? processedBuffer.sampleRate\n\n // Create offline context for resampling if needed\n if (targetSampleRate !== originalSampleRate) {\n const offlineCtx = new OfflineAudioContext(\n targetChannels,\n (length * targetSampleRate) / originalSampleRate,\n targetSampleRate\n )\n const source = offlineCtx.createBufferSource()\n source.buffer = processedBuffer\n source.connect(offlineCtx.destination)\n source.start()\n processedBuffer = await offlineCtx.startRendering()\n }\n\n // Convert to the desired format\n const newLength = processedBuffer.length\n let wavBuffer: Float32Array | Int16Array | Int8Array\n\n // Create appropriate buffer based on target bit depth\n switch (decodingOptions?.targetBitDepth) {\n case 16:\n wavBuffer = new Int16Array(newLength * targetChannels)\n break\n case 8:\n wavBuffer = new Int8Array(newLength * targetChannels)\n break\n case 32:\n default:\n wavBuffer = new Float32Array(newLength * targetChannels)\n break\n }\n\n // Interleave channels and handle bit depth conversion\n const numChannels = Math.min(\n processedBuffer.numberOfChannels,\n targetChannels\n )\n for (let channel = 0; channel < numChannels; channel++) {\n const channelData = processedBuffer.getChannelData(channel)\n for (let i = 0; i < newLength; i++) {\n let sample = channelData[i]\n\n // Normalize if requested\n if (decodingOptions?.normalizeAudio) {\n sample = Math.max(-1, Math.min(1, sample))\n }\n\n // Convert sample based on target bit depth\n if (decodingOptions?.targetBitDepth === 16) {\n sample = sample * 32767 // Convert to 16-bit range\n } else if (decodingOptions?.targetBitDepth === 8) {\n sample = sample * 127 // Convert to 8-bit range\n }\n\n wavBuffer[i * targetChannels + channel] = sample\n }\n }\n\n // Pass the duration to extractAudioAnalysis\n return await extractAudioAnalysis({\n arrayBuffer: wavBuffer.buffer as ArrayBuffer,\n bitDepth: decodingOptions?.targetBitDepth ?? 32,\n skipWavHeader: true,\n sampleRate: targetSampleRate,\n numberOfChannels: targetChannels,\n durationMs: effectiveDurationMs,\n ...restProps,\n })\n } catch (error) {\n console.error('Failed to process audio:', error)\n throw error\n }\n } else {\n // For native platforms, pass through all options\n return await extractAudioAnalysis({\n fileUri,\n decodingOptions,\n ...restProps,\n })\n }\n}\n\nexport const extractAudioAnalysis = async ({\n fileUri,\n pointsPerSecond = 20,\n arrayBuffer,\n bitDepth,\n skipWavHeader = true,\n durationMs,\n sampleRate,\n numberOfChannels,\n algorithm = 'rms',\n features,\n featuresExtratorUrl,\n logger,\n}: ExtractAudioAnalysisProps): Promise<AudioAnalysis> => {\n if (isWeb) {\n if (!arrayBuffer && !fileUri) {\n throw new Error('Either arrayBuffer or fileUri must be provided')\n }\n\n if (!arrayBuffer) {\n logger?.log(`fetching fileUri`, fileUri)\n const response = await fetch(fileUri!)\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch fileUri: ${response.statusText}`\n )\n }\n\n arrayBuffer = await response.arrayBuffer()\n logger?.log(`fetched fileUri`, arrayBuffer.byteLength, arrayBuffer)\n }\n\n // Create a new copy of the ArrayBuffer to avoid detachment issues\n const bufferCopy = arrayBuffer.slice(0)\n logger?.log(\n `extractAudioAnalysis skipWavHeader=${skipWavHeader} bitDepth=${bitDepth} len=${bufferCopy.byteLength}`,\n bufferCopy.slice(0, 100)\n )\n\n let actualBitDepth = bitDepth\n if (!actualBitDepth) {\n logger?.log(\n `extractAudioAnalysis bitDepth not provided -- getting wav file info`\n )\n const fileInfo = await getWavFileInfo(bufferCopy)\n actualBitDepth = fileInfo.bitDepth\n }\n logger?.log(`extractAudioAnalysis actualBitDepth=${actualBitDepth}`)\n\n const {\n pcmValues: channelData,\n min,\n max,\n } = await convertPCMToFloat32({\n buffer: arrayBuffer,\n bitDepth: actualBitDepth,\n skipWavHeader,\n })\n logger?.log(\n `extractAudioAnalysis skipWaveHeader=${skipWavHeader} convertPCMToFloat32 length=${channelData.length} range: [ ${min} :: ${max} ]`\n )\n\n return new Promise((resolve, reject) => {\n let worker: Worker\n if (featuresExtratorUrl) {\n worker = new Worker(\n new URL(featuresExtratorUrl, window.location.href)\n )\n } else {\n const blob = new Blob([InlineFeaturesExtractor], {\n type: 'application/javascript',\n })\n const url = URL.createObjectURL(blob)\n worker = new Worker(url)\n }\n\n worker.onmessage = (event) => {\n resolve(event.data.result)\n }\n\n worker.onerror = (error) => {\n reject(error)\n }\n\n worker.postMessage({\n command: 'process',\n channelData,\n sampleRate,\n pointsPerSecond,\n algorithm,\n bitDepth,\n fullAudioDurationMs: durationMs,\n numberOfChannels,\n })\n })\n } else {\n if (!fileUri) {\n throw new Error('fileUri is required')\n }\n logger?.log(`extractAudioAnalysis`, {\n fileUri,\n pointsPerSecond,\n algorithm,\n })\n const res = await ExpoAudioStreamModule.extractAudioAnalysis({\n fileUri,\n pointsPerSecond,\n skipWavHeader,\n algorithm,\n features,\n })\n logger?.log(`extractAudioAnalysis`, res)\n return res\n }\n}\n\nexport async function extractPreview({\n fileUri,\n numberOfPoints,\n algorithm = 'rms',\n startTime,\n endTime,\n decodingOptions,\n}: PreviewOptions): Promise<AudioPreview> {\n if (isWeb) {\n // For web, we can reuse the existing extractAudioFromAnyFormat with modified parameters\n const analysis = await extractAudioFromAnyFormat({\n fileUri,\n algorithm,\n decodingOptions,\n startTime, // Pass startTime\n endTime, // Pass endTime\n pointsPerSecond:\n (numberOfPoints ?? 100) /\n ((endTime ? endTime - (startTime || 0) : 1000) / 1000), // Adjust points per second calculation\n })\n\n // Convert AudioAnalysis to AudioPreview format and adjust duration\n return {\n pointsPerSecond: analysis.pointsPerSecond,\n durationMs: endTime\n ? endTime - (startTime || 0)\n : analysis.durationMs, // Use range duration if specified\n amplitudeRange: analysis.amplitudeRange,\n dataPoints: analysis.dataPoints.map((point) => ({\n id: point.id,\n amplitude: point.amplitude,\n startTime: point.startTime,\n endTime: point.endTime,\n })),\n }\n }\n\n return await ExpoAudioStreamModule.extractPreview({\n fileUri,\n numberOfPoints,\n algorithm,\n startTime,\n endTime,\n decodingOptions,\n })\n}\n"]}
1
+ {"version":3,"file":"extractAudioAnalysis.js","sourceRoot":"","sources":["../../src/AudioAnalysis/extractAudioAnalysis.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/expo-audio-stream/src/AudioAnalysis/extractAudioAnalysis.ts\n/**\n * This module provides functions for extracting and analyzing audio data.\n * - `extractAudioAnalysis`: For detailed analysis with customizable ranges and decoding options.\n * - `extractWavAudioAnalysis`: For analyzing WAV files without decoding, preserving original PCM values.\n * - `extractPreview`: For generating quick previews of audio waveforms, optimized for UI rendering.\n */\nimport crc32 from 'crc-32'\n\nimport { ConsoleLike, ExtractAudioDataOptions } from '../ExpoAudioStream.types'\nimport ExpoAudioStreamModule from '../ExpoAudioStreamModule'\nimport { isWeb } from '../constants'\nimport {\n AudioAnalysis,\n AudioFeaturesOptions,\n DataPoint,\n DecodingConfig,\n PreviewOptions,\n} from './AudioAnalysis.types'\nimport { processAudioBuffer } from '../utils/audioProcessing'\nimport { convertPCMToFloat32 } from '../utils/convertPCMToFloat32'\nimport { getWavFileInfo, WavFileInfo } from '../utils/getWavFileInfo'\nimport { InlineFeaturesExtractor } from '../workers/InlineFeaturesExtractor.web'\n\nfunction calculateCRC32ForDataPoint(data: Float32Array): number {\n // Convert float array to byte array for CRC32\n const byteArray = new Uint8Array(data.length * 4)\n const dataView = new DataView(byteArray.buffer)\n\n for (let i = 0; i < data.length; i++) {\n dataView.setFloat32(i * 4, data[i], true)\n }\n\n return crc32.buf(byteArray)\n}\n\nexport interface ExtractWavAudioAnalysisProps {\n fileUri?: string // should provide either fileUri or arrayBuffer\n wavMetadata?: WavFileInfo\n arrayBuffer?: ArrayBuffer\n bitDepth?: number\n durationMs?: number\n sampleRate?: number\n numberOfChannels?: number\n position?: number // Optional number of bytes to skip. Default is 0\n length?: number // Optional number of bytes to read.\n segmentDurationMs?: number // Optional number of points per second. Use to reduce the number of points and compute the number of datapoints to return.\n features?: AudioFeaturesOptions\n featuresExtratorUrl?: string\n logger?: ConsoleLike\n decodingOptions?: DecodingConfig\n}\n\n// Define base options interface with common properties\ninterface BaseExtractOptions {\n fileUri?: string\n arrayBuffer?: ArrayBuffer\n /**\n * Duration of each analysis segment in milliseconds. Defaults to 100ms if not specified.\n */\n segmentDurationMs?: number\n features?: AudioFeaturesOptions\n decodingOptions?: DecodingConfig\n logger?: ConsoleLike\n}\n\n// Time-based range options\ninterface TimeRangeOptions extends BaseExtractOptions {\n startTimeMs?: number\n endTimeMs?: number\n position?: never\n length?: never\n}\n\n// Byte-based range options\ninterface ByteRangeOptions extends BaseExtractOptions {\n position?: number\n length?: number\n startTimeMs?: never\n endTimeMs?: never\n}\n\n/**\n * Options for extracting audio analysis.\n * - For time-based analysis, provide `startTimeMs` and `endTimeMs`.\n * - For byte-based analysis, provide `position` and `length`.\n * - Do not mix time and byte ranges.\n */\nexport type ExtractAudioAnalysisProps = TimeRangeOptions | ByteRangeOptions\n\n/**\n * Extracts detailed audio analysis from the specified audio file or buffer.\n * Supports either time-based or byte-based ranges for flexibility in analysis.\n *\n * @param props - The options for extraction, including file URI, ranges, and decoding settings.\n * @returns A promise that resolves to the audio analysis data.\n * @throws {Error} If both time and byte ranges are provided or if required parameters are missing.\n */\nexport async function extractAudioAnalysis(\n props: ExtractAudioAnalysisProps\n): Promise<AudioAnalysis> {\n const {\n fileUri,\n arrayBuffer,\n decodingOptions,\n logger,\n segmentDurationMs = 100,\n features,\n } = props\n\n if (isWeb) {\n try {\n // Create AudioContext here\n const audioContext = new (window.AudioContext ||\n (window as any).webkitAudioContext)({\n sampleRate: decodingOptions?.targetSampleRate ?? 16000,\n })\n\n try {\n const processedBuffer = await processAudioBuffer({\n arrayBuffer,\n fileUri,\n targetSampleRate:\n decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n startTimeMs:\n 'startTimeMs' in props ? props.startTimeMs : undefined,\n endTimeMs:\n 'endTimeMs' in props ? props.endTimeMs : undefined,\n position: 'position' in props ? props.position : undefined,\n length: 'length' in props ? props.length : undefined,\n audioContext, // Pass the context we created\n logger,\n })\n\n const channelData = processedBuffer.buffer.getChannelData(0)\n\n // Create and initialize the worker\n const blob = new Blob([InlineFeaturesExtractor], {\n type: 'application/javascript',\n })\n const workerUrl = URL.createObjectURL(blob)\n const worker = new Worker(workerUrl)\n\n return new Promise((resolve, reject) => {\n worker.onmessage = (event) => {\n if (event.data.error) {\n reject(new Error(event.data.error))\n return\n }\n\n const result: AudioAnalysis = event.data.result\n // Calculate CRC32 after worker completes if requested\n if (features?.crc32) {\n const samplesPerSegment = Math.floor(\n (processedBuffer.sampleRate *\n segmentDurationMs) /\n 1000\n )\n\n result.dataPoints = result.dataPoints.map(\n (point: DataPoint, index: number) => {\n const startSample =\n index * samplesPerSegment\n const segmentData = channelData.slice(\n startSample,\n startSample + samplesPerSegment\n )\n\n return {\n ...point,\n features: {\n ...point.features,\n crc32: calculateCRC32ForDataPoint(\n segmentData\n ),\n },\n }\n }\n )\n }\n\n URL.revokeObjectURL(workerUrl)\n worker.terminate()\n resolve(result)\n }\n\n worker.onerror = (error) => {\n URL.revokeObjectURL(workerUrl)\n worker.terminate()\n reject(error)\n }\n\n worker.postMessage({\n channelData,\n sampleRate: processedBuffer.sampleRate,\n segmentDurationMs,\n bitDepth: decodingOptions?.targetBitDepth ?? 32,\n numberOfChannels: processedBuffer.channels,\n // enableLogging: !!logger,\n features,\n })\n })\n } finally {\n await audioContext.close()\n }\n } catch (error) {\n logger?.error('Failed to process audio:', error)\n throw error\n }\n } else {\n return await ExpoAudioStreamModule.extractAudioAnalysis(props)\n }\n}\n\n/**\n * Analyzes WAV files without decoding, preserving original PCM values.\n * Use this function when you need to ensure the analysis matches other software by avoiding any transformations.\n *\n * @param props - The options for WAV analysis, including file URI and range.\n * @returns A promise that resolves to the audio analysis data.\n */\nexport const extractRawWavAnalysis = async ({\n fileUri,\n segmentDurationMs = 100, // Default to 100ms\n arrayBuffer,\n bitDepth,\n durationMs,\n sampleRate,\n numberOfChannels,\n features,\n logger,\n position = 0,\n length,\n}: ExtractWavAudioAnalysisProps): Promise<AudioAnalysis> => {\n if (isWeb) {\n if (!arrayBuffer && !fileUri) {\n throw new Error('Either arrayBuffer or fileUri must be provided')\n }\n\n if (!arrayBuffer) {\n logger?.log(`fetching fileUri`, fileUri)\n const response = await fetch(fileUri!)\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch fileUri: ${response.statusText}`\n )\n }\n\n arrayBuffer = await response.arrayBuffer()\n logger?.log(`fetched fileUri`, arrayBuffer.byteLength, arrayBuffer)\n }\n\n // Create a new copy of the ArrayBuffer to avoid detachment issues\n const bufferCopy = arrayBuffer.slice(0)\n logger?.log(\n `extractAudioAnalysis bitDepth=${bitDepth} len=${bufferCopy.byteLength}`,\n bufferCopy.slice(0, 100)\n )\n\n let actualBitDepth = bitDepth\n if (!actualBitDepth) {\n logger?.log(\n `extractAudioAnalysis bitDepth not provided -- getting wav file info`\n )\n const fileInfo = await getWavFileInfo(bufferCopy)\n actualBitDepth = fileInfo.bitDepth\n }\n logger?.log(`extractAudioAnalysis actualBitDepth=${actualBitDepth}`)\n\n const {\n pcmValues: channelData,\n min,\n max,\n } = await convertPCMToFloat32({\n buffer: arrayBuffer,\n bitDepth: actualBitDepth,\n })\n logger?.log(\n `extractAudioAnalysis convertPCMToFloat32 length=${channelData.length} range: [ ${min} :: ${max} ]`\n )\n\n // Apply position and length constraints to channelData if specified\n const startIndex = position\n const endIndex = length ? startIndex + length : channelData.length\n const constrainedChannelData = channelData.slice(startIndex, endIndex)\n\n return new Promise((resolve, reject) => {\n const blob = new Blob([InlineFeaturesExtractor], {\n type: 'application/javascript',\n })\n const url = URL.createObjectURL(blob)\n const worker = new Worker(url)\n\n worker.onmessage = (event) => {\n resolve(event.data.result)\n }\n\n worker.onerror = (error) => {\n reject(error)\n }\n\n worker.postMessage({\n command: 'process',\n channelData: constrainedChannelData,\n sampleRate,\n segmentDurationMs,\n logger,\n bitDepth,\n fullAudioDurationMs: durationMs,\n numberOfChannels,\n })\n })\n } else {\n if (!fileUri) {\n throw new Error('fileUri is required')\n }\n logger?.log(`extractAudioAnalysis`, {\n fileUri,\n segmentDurationMs,\n })\n const res = await ExpoAudioStreamModule.extractAudioAnalysis({\n fileUri,\n segmentDurationMs,\n features,\n position,\n length,\n })\n logger?.log(`extractAudioAnalysis`, res)\n return res\n }\n}\n\n/**\n * Generates a simplified preview of the audio waveform for quick visualization.\n * Ideal for UI rendering with a specified number of points.\n *\n * @param options - The options for the preview, including file URI and time range.\n * @returns A promise that resolves to the audio preview data.\n */\nexport async function extractPreview({\n fileUri,\n numberOfPoints = 100,\n startTimeMs = 0,\n endTimeMs = 30000, // First 30 seconds\n decodingOptions,\n logger,\n}: PreviewOptions): Promise<AudioAnalysis> {\n const durationMs = endTimeMs - startTimeMs\n const segmentDurationMs = Math.floor(durationMs / numberOfPoints)\n\n // Call extractAudioAnalysis with calculated parameters\n const analysis = await extractAudioAnalysis({\n fileUri,\n startTimeMs,\n endTimeMs,\n logger,\n segmentDurationMs,\n decodingOptions,\n })\n\n // Transform the result into AudioPreview format\n return analysis\n}\n\nexport const extractAudioData = async (props: ExtractAudioDataOptions) => {\n return await ExpoAudioStreamModule.extractAudioData(props)\n}"]}
@@ -1,4 +1,4 @@
1
- import { AmplitudeAlgorithm, AudioAnalysis, AudioFeaturesOptions } from './AudioAnalysis/AudioAnalysis.types';
1
+ import { AudioAnalysis, AudioFeaturesOptions, DecodingConfig } from './AudioAnalysis/AudioAnalysis.types';
2
2
  import { AudioAnalysisEvent } from './events';
3
3
  export interface CompressionInfo {
4
4
  size: number;
@@ -30,9 +30,11 @@ export interface AudioDataEvent {
30
30
  export type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit';
31
31
  export type SampleRate = 16000 | 44100 | 48000;
32
32
  export type BitDepth = 8 | 16 | 32;
33
+ export type PCMFormat = `pcm_${BitDepth}bit`;
33
34
  export type ConsoleLike = {
34
35
  log: (message: string, ...args: unknown[]) => void;
35
36
  debug: (message: string, ...args: unknown[]) => void;
37
+ info: (message: string, ...args: unknown[]) => void;
36
38
  warn: (message: string, ...args: unknown[]) => void;
37
39
  error: (message: string, ...args: unknown[]) => void;
38
40
  };
@@ -99,8 +101,7 @@ export interface RecordingConfig {
99
101
  notification?: NotificationConfig;
100
102
  enableProcessing?: boolean;
101
103
  ios?: IOSConfig;
102
- pointsPerSecond?: number;
103
- algorithm?: AmplitudeAlgorithm;
104
+ segmentDurationMs?: number;
104
105
  features?: AudioFeaturesOptions;
105
106
  onAudioStream?: (_: AudioDataEvent) => Promise<void>;
106
107
  onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>;
@@ -146,6 +147,49 @@ export interface WaveformConfig {
146
147
  mirror?: boolean;
147
148
  height?: number;
148
149
  }
150
+ export interface ExtractAudioDataOptions {
151
+ fileUri: string;
152
+ startTimeMs?: number;
153
+ endTimeMs?: number;
154
+ position?: number;
155
+ length?: number;
156
+ /** Include normalized audio data in [-1, 1] range */
157
+ includeNormalizedData?: boolean;
158
+ /** Include base64 encoded string representation of the audio data */
159
+ includeBase64Data?: boolean;
160
+ /** Include WAV header in the PCM data (makes it a valid WAV file) */
161
+ includeWavHeader?: boolean;
162
+ /** Logger for debugging - can pass console directly. */
163
+ logger?: ConsoleLike;
164
+ /** Compute the checksum of the pcm data */
165
+ computeChecksum?: boolean;
166
+ /** Target config for the normalized audio (Android and Web) */
167
+ decodingOptions?: DecodingConfig;
168
+ }
169
+ export interface ExtractedAudioData {
170
+ /** Raw PCM audio data */
171
+ pcmData: Uint8Array;
172
+ /** Normalized audio data in [-1, 1] range (when includeNormalizedData is true) */
173
+ normalizedData?: Float32Array;
174
+ /** Base64 encoded string representation of the audio data (when includeBase64Data is true) */
175
+ base64Data?: string;
176
+ /** Sample rate in Hz (e.g., 44100, 48000) */
177
+ sampleRate: number;
178
+ /** Number of audio channels (1 for mono, 2 for stereo) */
179
+ channels: number;
180
+ /** Bits per sample (8, 16, or 32) */
181
+ bitDepth: BitDepth;
182
+ /** Duration of the audio in milliseconds */
183
+ durationMs: number;
184
+ /** PCM format identifier (e.g., "pcm_16bit") */
185
+ format: PCMFormat;
186
+ /** Total number of audio samples per channel */
187
+ samples: number;
188
+ /** Whether the pcmData includes a WAV header */
189
+ hasWavHeader?: boolean;
190
+ /** CRC32 Checksum of pcm data */
191
+ checksum?: number;
192
+ }
149
193
  export interface UseAudioRecorderState {
150
194
  startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>;
151
195
  stopRecording: () => Promise<AudioRecording | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n compressedFileUri?: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n intervalAnalysis: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000 \nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n createdAt?: number\n transcripts?: TranscriberData[]\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\n// Add new type for interruption reasons\nexport type RecordingInterruptionReason =\n | 'audioFocusLoss'\n | 'audioFocusGain'\n | 'phoneCall'\n | 'phoneCallEnded'\n | 'recordingStopped'\n\n// Add new interface for interruption events\nexport interface RecordingInterruptionEvent {\n reason: RecordingInterruptionReason\n isPaused: boolean\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Interval in milliseconds at which to emit analysis data\n intervalAnalysis?: number\n\n // Keep the device awake while recording (default is false)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus'\n bitrate?: number\n }\n\n // Whether to automatically resume recording after an interruption (default is false)\n autoResumeAfterInterruption?: boolean\n\n // Optional callback to handle recording interruptions\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n\n // Optional output configuration\n outputDirectory?: string // If not provided, uses default app directory\n filename?: string // If not provided, uses UUID\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n}\n"]}
1
+ {"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AudioAnalysis,\n AudioFeaturesOptions,\n DecodingConfig,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n compressedFileUri?: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n intervalAnalysis: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\nexport type PCMFormat = `pcm_${BitDepth}bit`\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n info: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n createdAt?: number\n transcripts?: TranscriberData[]\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\n// Add new type for interruption reasons\nexport type RecordingInterruptionReason =\n | 'audioFocusLoss'\n | 'audioFocusGain'\n | 'phoneCall'\n | 'phoneCallEnded'\n | 'recordingStopped'\n\n// Add new interface for interruption events\nexport interface RecordingInterruptionEvent {\n reason: RecordingInterruptionReason\n isPaused: boolean\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Interval in milliseconds at which to emit analysis data\n intervalAnalysis?: number\n\n // Keep the device awake while recording (default is false)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Duration of each segment in milliseconds (default: 100)\n segmentDurationMs?: number\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus'\n bitrate?: number\n }\n\n // Whether to automatically resume recording after an interruption (default is false)\n autoResumeAfterInterruption?: boolean\n\n // Optional callback to handle recording interruptions\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n\n // Optional output configuration\n outputDirectory?: string // If not provided, uses default app directory\n filename?: string // If not provided, uses UUID\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface ExtractAudioDataOptions {\n fileUri: string\n // Time-based range (mutually exclusive with byte-based range)\n startTimeMs?: number\n endTimeMs?: number\n // Byte-based range (mutually exclusive with time-based range)\n position?: number\n length?: number\n /** Include normalized audio data in [-1, 1] range */\n includeNormalizedData?: boolean\n /** Include base64 encoded string representation of the audio data */\n includeBase64Data?: boolean\n /** Include WAV header in the PCM data (makes it a valid WAV file) */\n includeWavHeader?: boolean\n /** Logger for debugging - can pass console directly. */\n logger?: ConsoleLike\n /** Compute the checksum of the pcm data */\n computeChecksum?: boolean\n /** Target config for the normalized audio (Android and Web) */\n decodingOptions?: DecodingConfig\n}\n\nexport interface ExtractedAudioData {\n /** Raw PCM audio data */\n pcmData: Uint8Array\n /** Normalized audio data in [-1, 1] range (when includeNormalizedData is true) */\n normalizedData?: Float32Array\n /** Base64 encoded string representation of the audio data (when includeBase64Data is true) */\n base64Data?: string\n /** Sample rate in Hz (e.g., 44100, 48000) */\n sampleRate: number\n /** Number of audio channels (1 for mono, 2 for stereo) */\n channels: number\n /** Bits per sample (8, 16, or 32) */\n bitDepth: BitDepth\n /** Duration of the audio in milliseconds */\n durationMs: number\n /** PCM format identifier (e.g., \"pcm_16bit\") */\n format: PCMFormat\n /** Total number of audio samples per channel */\n samples: number\n /** Whether the pcmData includes a WAV header */\n hasWavHeader?: boolean\n /** CRC32 Checksum of pcm data */\n checksum?: number\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n}\n"]}