@siteed/expo-audio-studio 2.4.0 → 2.5.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.
- package/CHANGELOG.md +14 -1
- package/README.md +25 -0
- package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +22 -0
- package/android/src/main/java/net/siteed/audiostream/AudioDeviceManager.kt +1501 -0
- package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +10 -5
- package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +27 -25
- package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +73 -71
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +581 -255
- package/android/src/main/java/net/siteed/audiostream/Constants.kt +17 -1
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +435 -158
- package/android/src/main/java/net/siteed/audiostream/LogUtils.kt +65 -0
- package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +14 -5
- package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +9 -1
- package/build/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
- package/build/AudioDeviceManager.d.ts +107 -0
- package/build/AudioDeviceManager.d.ts.map +1 -0
- package/build/AudioDeviceManager.js +493 -0
- package/build/AudioDeviceManager.js.map +1 -0
- package/build/AudioRecorder.provider.d.ts.map +1 -1
- package/build/AudioRecorder.provider.js +3 -0
- package/build/AudioRecorder.provider.js.map +1 -1
- package/build/ExpoAudioStream.types.d.ts +90 -1
- package/build/ExpoAudioStream.types.d.ts.map +1 -1
- package/build/ExpoAudioStream.types.js +7 -1
- package/build/ExpoAudioStream.types.js.map +1 -1
- package/build/ExpoAudioStream.web.d.ts +37 -0
- package/build/ExpoAudioStream.web.d.ts.map +1 -1
- package/build/ExpoAudioStream.web.js +399 -54
- package/build/ExpoAudioStream.web.js.map +1 -1
- package/build/ExpoAudioStreamModule.d.ts.map +1 -1
- package/build/ExpoAudioStreamModule.js +20 -0
- package/build/ExpoAudioStreamModule.js.map +1 -1
- package/build/WebRecorder.web.d.ts +63 -10
- package/build/WebRecorder.web.d.ts.map +1 -1
- package/build/WebRecorder.web.js +277 -68
- package/build/WebRecorder.web.js.map +1 -1
- package/build/hooks/useAudioDevices.d.ts +14 -0
- package/build/hooks/useAudioDevices.d.ts.map +1 -0
- package/build/hooks/useAudioDevices.js +151 -0
- package/build/hooks/useAudioDevices.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -0
- package/build/index.js.map +1 -1
- package/build/useAudioRecorder.d.ts +1 -0
- package/build/useAudioRecorder.d.ts.map +1 -1
- package/build/useAudioRecorder.js +20 -1
- package/build/useAudioRecorder.js.map +1 -1
- package/build/utils/BlobFix.d.ts.map +1 -1
- package/build/utils/BlobFix.js +2 -2
- package/build/utils/BlobFix.js.map +1 -1
- package/build/workers/InlineFeaturesExtractor.web.d.ts +1 -1
- package/build/workers/InlineFeaturesExtractor.web.d.ts.map +1 -1
- package/build/workers/InlineFeaturesExtractor.web.js +27 -26
- package/build/workers/InlineFeaturesExtractor.web.js.map +1 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts +1 -1
- package/build/workers/inlineAudioWebWorker.web.d.ts.map +1 -1
- package/build/workers/inlineAudioWebWorker.web.js +25 -1
- package/build/workers/inlineAudioWebWorker.web.js.map +1 -1
- package/ios/AudioDeviceManager.swift +654 -0
- package/ios/AudioStreamManager.swift +964 -760
- package/ios/ExpoAudioStreamModule.swift +174 -19
- package/ios/Features.swift +1 -1
- package/ios/ISSUE_IOS.md +45 -0
- package/ios/Logger.swift +13 -1
- package/ios/RecordingSettings.swift +12 -0
- package/package.json +2 -2
- package/src/AudioAnalysis/AudioAnalysis.types.ts +2 -2
- package/src/AudioDeviceManager.ts +571 -0
- package/src/AudioRecorder.provider.tsx +3 -0
- package/src/ExpoAudioStream.types.ts +97 -1
- package/src/ExpoAudioStream.web.ts +513 -63
- package/src/ExpoAudioStreamModule.ts +23 -0
- package/src/WebRecorder.web.ts +346 -81
- package/src/hooks/useAudioDevices.ts +180 -0
- package/src/index.ts +6 -0
- package/src/types/crc-32.d.ts +6 -6
- package/src/useAudioRecorder.tsx +27 -1
- package/src/utils/BlobFix.ts +6 -4
- package/src/workers/InlineFeaturesExtractor.web.tsx +27 -26
- package/src/workers/inlineAudioWebWorker.web.tsx +25 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.web.js","sourceRoot":"","sources":["../src/ExpoAudioStream.web.ts"],"names":[],"mappings":"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","sourcesContent":["// src/ExpoAudioStreamModule.web.ts\nimport { LegacyEventEmitter } from 'expo-modules-core'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioRecording,\n AudioStreamStatus,\n BitDepth,\n ConsoleLike,\n RecordingConfig,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport { WebRecorder } from './WebRecorder.web'\nimport { AudioEventPayload } from './events'\nimport { encodingToBitDepth } from './utils/encodingToBitDepth'\n\nexport interface EmitAudioEventProps {\n data: Float32Array\n position: number\n compression?: {\n data: Blob\n size: number\n totalSize: number\n mimeType: string\n format: string\n bitrate: number\n }\n}\nexport type EmitAudioEventFunction = (_: EmitAudioEventProps) => void\nexport type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void\n\nexport interface ExpoAudioStreamWebProps {\n logger?: ConsoleLike\n audioWorkletUrl: string\n featuresExtratorUrl: string\n maxBufferSize?: number // Maximum number of chunks to keep in memory\n}\n\nexport class ExpoAudioStreamWeb extends LegacyEventEmitter {\n customRecorder: WebRecorder | null\n audioChunks: Float32Array[]\n isRecording: boolean\n isPaused: boolean\n recordingStartTime: number\n pausedTime: number\n currentDurationMs: number\n currentSize: number\n currentInterval: number\n currentIntervalAnalysis: number\n lastEmittedSize: number\n lastEmittedTime: number\n lastEmittedCompressionSize: number\n lastEmittedAnalysisTime: number\n streamUuid: string | null\n extension: 'webm' | 'wav' = 'wav' // Default extension is 'wav'\n recordingConfig?: RecordingConfig\n bitDepth: BitDepth // Bit depth of the audio\n audioWorkletUrl: string\n featuresExtratorUrl: string\n logger?: ConsoleLike\n latestPosition: number = 0\n totalCompressedSize: number = 0\n private readonly maxBufferSize: number\n\n constructor({\n audioWorkletUrl,\n featuresExtratorUrl,\n logger,\n maxBufferSize = 100, // Default to storing last 100 chunks (1 chunk = 0.5 seconds)\n }: ExpoAudioStreamWebProps) {\n const mockNativeModule = {\n addListener: () => {\n // Not used on web\n },\n removeListeners: () => {\n // Not used on web\n },\n }\n super(mockNativeModule) // Pass the mock native module to the parent class\n\n this.logger = logger\n this.customRecorder = null\n this.audioChunks = []\n this.isRecording = false\n this.isPaused = false\n this.recordingStartTime = 0\n this.pausedTime = 0\n this.currentDurationMs = 0\n this.currentSize = 0\n this.bitDepth = 32 // Default\n this.currentInterval = 1000 // Default interval in ms\n this.currentIntervalAnalysis = 500 // Default analysis interval in ms\n this.lastEmittedSize = 0\n this.lastEmittedTime = 0\n this.latestPosition = 0\n this.lastEmittedCompressionSize = 0\n this.lastEmittedAnalysisTime = 0\n this.streamUuid = null // Initialize UUID on first recording start\n this.audioWorkletUrl = audioWorkletUrl\n this.featuresExtratorUrl = featuresExtratorUrl\n this.maxBufferSize = maxBufferSize\n }\n\n // Utility to handle user media stream\n async getMediaStream() {\n try {\n return await navigator.mediaDevices.getUserMedia({ audio: true })\n } catch (error) {\n this.logger?.error('Failed to get media stream:', error)\n throw error\n }\n }\n\n // Start recording with options\n async startRecording(\n recordingConfig: RecordingConfig = {}\n ): Promise<StartRecordingResult> {\n if (this.isRecording) {\n throw new Error('Recording is already in progress')\n }\n\n this.bitDepth = encodingToBitDepth({\n encoding: recordingConfig.encoding ?? 'pcm_32bit',\n })\n\n const audioContext = new (window.AudioContext ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Allow webkitAudioContext for Safari\n window.webkitAudioContext)()\n const stream = await this.getMediaStream()\n\n const source = audioContext.createMediaStreamSource(stream)\n\n this.customRecorder = new WebRecorder({\n logger: this.logger,\n audioContext,\n source,\n recordingConfig,\n emitAudioEventCallback: ({\n data,\n position,\n compression,\n }: EmitAudioEventProps) => {\n // Keep only the latest chunks based on maxBufferSize\n this.audioChunks.push(new Float32Array(data))\n if (this.audioChunks.length > this.maxBufferSize) {\n this.audioChunks.shift() // Remove oldest chunk\n }\n this.currentSize += data.byteLength\n this.emitAudioEvent({ data, position, compression })\n this.lastEmittedTime = Date.now()\n this.lastEmittedSize = this.currentSize\n this.lastEmittedCompressionSize = compression?.size ?? 0\n },\n emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysis) => {\n this.logger?.log(`Emitted AudioAnalysis:`, audioAnalysisData)\n this.emit('AudioAnalysis', audioAnalysisData)\n },\n })\n await this.customRecorder.init()\n this.customRecorder.start()\n\n // // Set a timer to stop recording after 5 seconds\n // setTimeout(() => {\n // logger.log(\"AUTO Stopping recording\");\n // this.customRecorder?.stopAndPlay();\n // this.isRecording = false;\n // }, 3000);\n\n this.isRecording = true\n this.recordingConfig = recordingConfig\n this.recordingStartTime = Date.now()\n this.pausedTime = 0\n this.isPaused = false\n this.lastEmittedSize = 0\n this.lastEmittedTime = 0\n this.lastEmittedCompressionSize = 0\n this.currentInterval = recordingConfig.interval ?? 1000\n this.currentIntervalAnalysis = recordingConfig.intervalAnalysis ?? 500\n this.lastEmittedAnalysisTime = Date.now()\n\n // Use custom filename if provided, otherwise fallback to timestamp\n if (recordingConfig.filename) {\n // Remove any existing extension from the filename\n this.streamUuid = recordingConfig.filename.replace(/\\.[^/.]+$/, '')\n } else {\n this.streamUuid = Date.now().toString()\n }\n\n const fileUri = `${this.streamUuid}.${this.extension}`\n const streamConfig: StartRecordingResult = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n bitDepth: this.bitDepth,\n channels: recordingConfig.channels ?? 1,\n sampleRate: recordingConfig.sampleRate ?? 44100,\n compression: recordingConfig.compression\n ? {\n ...recordingConfig.compression,\n bitrate: recordingConfig.compression?.bitrate ?? 128000,\n size: 0,\n mimeType: 'audio/webm',\n format: recordingConfig.compression?.format ?? 'opus',\n compressedFileUri: '',\n }\n : undefined,\n }\n return streamConfig\n }\n\n emitAudioEvent({ data, position, compression }: EmitAudioEventProps) {\n const fileUri = `${this.streamUuid}.${this.extension}`\n if (compression?.size) {\n this.lastEmittedCompressionSize = compression.size\n this.totalCompressedSize = compression.totalSize\n }\n this.latestPosition = position\n this.currentDurationMs = position * 1000 // Convert position (in seconds) to ms\n\n const audioEventPayload: AudioEventPayload = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n lastEmittedSize: this.lastEmittedSize,\n deltaSize: data.byteLength,\n position,\n totalSize: this.currentSize,\n buffer: data,\n streamUuid: this.streamUuid ?? '',\n compression: compression\n ? {\n data: compression?.data,\n totalSize: this.totalCompressedSize,\n eventDataSize: compression?.size ?? 0,\n position,\n }\n : undefined,\n }\n\n this.emit('AudioData', audioEventPayload)\n }\n\n // Stop recording\n async stopRecording(): Promise<AudioRecording> {\n if (!this.customRecorder) {\n throw new Error('Recorder is not initialized')\n }\n\n this.logger?.debug('[Stop] Starting stop process')\n const startTime = performance.now()\n\n try {\n this.logger?.debug('[Stop] Stopping recorder')\n const { compressedBlob } = await this.customRecorder.stop()\n\n this.isRecording = false\n this.isPaused = false\n this.currentDurationMs = Date.now() - this.recordingStartTime\n\n let compression: AudioRecording['compression']\n let fileUri = `${this.streamUuid}.${this.extension}`\n let mimeType = `audio/${this.extension}`\n\n if (compressedBlob && this.recordingConfig?.compression?.enabled) {\n const compressedUri = URL.createObjectURL(compressedBlob)\n compression = {\n compressedFileUri: compressedUri,\n size: compressedBlob.size,\n mimeType: 'audio/webm',\n format: 'opus',\n bitrate: this.recordingConfig.compression.bitrate ?? 128000,\n }\n // Use compressed values when compression is enabled\n fileUri = compressedUri\n mimeType = 'audio/webm'\n }\n\n this.logger?.debug(\n `[Stop] Completed stop process in ${performance.now() - startTime}ms`,\n {\n durationMs: this.currentDurationMs,\n compressedSize: compression?.size,\n }\n )\n\n // Use the stored streamUuid (which contains our custom filename) for the final filename\n const filename = `${this.streamUuid}.${this.extension}`\n const result: AudioRecording = {\n fileUri,\n filename, // This will now use our custom filename\n bitDepth: this.bitDepth,\n createdAt: this.recordingStartTime,\n channels: this.recordingConfig?.channels ?? 1,\n sampleRate: this.recordingConfig?.sampleRate ?? 44100,\n durationMs: this.currentDurationMs,\n size: this.currentSize,\n mimeType,\n compression,\n }\n\n // Reset after creating the result\n this.streamUuid = null\n\n return result\n } catch (error) {\n this.logger?.error('[Stop] Error stopping recording:', error)\n throw error\n }\n }\n\n // Pause recording\n async pauseRecording() {\n if (!this.isRecording || this.isPaused) {\n throw new Error('Recording is not active or already paused')\n }\n\n if (this.customRecorder) {\n this.customRecorder.pause()\n }\n this.isPaused = true\n this.pausedTime = Date.now()\n }\n\n // Resume recording\n async resumeRecording() {\n if (!this.isPaused) {\n throw new Error('Recording is not paused')\n }\n\n if (this.customRecorder) {\n this.customRecorder.resume()\n }\n this.isPaused = false\n this.recordingStartTime += Date.now() - this.pausedTime\n }\n\n // Get current status\n status() {\n const status: AudioStreamStatus = {\n isRecording: this.isRecording,\n isPaused: this.isPaused,\n durationMs: this.currentDurationMs,\n size: this.currentSize,\n interval: this.currentInterval,\n intervalAnalysis: this.currentIntervalAnalysis,\n mimeType: `audio/${this.extension}`,\n compression: this.recordingConfig?.compression?.enabled\n ? {\n size: this.totalCompressedSize,\n mimeType: 'audio/webm',\n format: this.recordingConfig.compression.format ?? 'opus',\n bitrate:\n this.recordingConfig.compression.bitrate ?? 128000,\n compressedFileUri: `${this.streamUuid}.webm`,\n }\n : undefined,\n }\n return status\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.web.js","sourceRoot":"","sources":["../src/ExpoAudioStream.web.ts"],"names":[],"mappings":"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","sourcesContent":["// src/ExpoAudioStreamModule.web.ts\nimport { LegacyEventEmitter } from 'expo-modules-core'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioRecording,\n AudioStreamStatus,\n BitDepth,\n ConsoleLike,\n RecordingConfig,\n RecordingInterruptionReason,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport { WebRecorder } from './WebRecorder.web'\nimport { AudioEventPayload } from './events'\nimport { encodingToBitDepth } from './utils/encodingToBitDepth'\n\nexport interface AudioStreamEvent {\n type: string\n device?: string\n timestamp: Date\n}\n\nexport interface ExpoAudioStreamOptions {\n logger?: ConsoleLike\n eventCallback?: (event: AudioStreamEvent) => void\n}\n\nexport interface EmitAudioEventProps {\n data: Float32Array\n position: number\n compression?: {\n data: Blob\n size: number\n totalSize: number\n mimeType: string\n format: string\n bitrate: number\n }\n}\nexport type EmitAudioEventFunction = (_: EmitAudioEventProps) => void\nexport type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void\n\nexport interface ExpoAudioStreamWebProps {\n logger?: ConsoleLike\n audioWorkletUrl: string\n featuresExtratorUrl: string\n maxBufferSize?: number // Maximum number of chunks to keep in memory\n}\n\nexport class ExpoAudioStreamWeb extends LegacyEventEmitter {\n customRecorder: WebRecorder | null\n audioChunks: Float32Array[]\n isRecording: boolean\n isPaused: boolean\n recordingStartTime: number\n pausedTime: number\n currentDurationMs: number\n currentSize: number\n currentInterval: number\n currentIntervalAnalysis: number\n lastEmittedSize: number\n lastEmittedTime: number\n lastEmittedCompressionSize: number\n lastEmittedAnalysisTime: number\n streamUuid: string | null\n extension: 'webm' | 'wav' = 'wav' // Default extension is 'wav'\n recordingConfig?: RecordingConfig\n bitDepth: BitDepth // Bit depth of the audio\n audioWorkletUrl: string\n featuresExtratorUrl: string\n logger?: ConsoleLike\n latestPosition: number = 0\n totalCompressedSize: number = 0\n private readonly maxBufferSize: number\n private eventCallback?: (event: AudioStreamEvent) => void\n\n constructor({\n audioWorkletUrl,\n featuresExtratorUrl,\n logger,\n maxBufferSize = 100, // Default to storing last 100 chunks (1 chunk = 0.5 seconds)\n }: ExpoAudioStreamWebProps) {\n const mockNativeModule = {\n addListener: () => {},\n removeListeners: () => {},\n }\n super(mockNativeModule) // Pass the mock native module to the parent class\n\n this.logger = logger\n this.customRecorder = null\n this.audioChunks = []\n this.isRecording = false\n this.isPaused = false\n this.recordingStartTime = 0\n this.pausedTime = 0\n this.currentDurationMs = 0\n this.currentSize = 0\n this.bitDepth = 32 // Default\n this.currentInterval = 1000 // Default interval in ms\n this.currentIntervalAnalysis = 500 // Default analysis interval in ms\n this.lastEmittedSize = 0\n this.lastEmittedTime = 0\n this.latestPosition = 0\n this.lastEmittedCompressionSize = 0\n this.lastEmittedAnalysisTime = 0\n this.streamUuid = null // Initialize UUID on first recording start\n this.audioWorkletUrl = audioWorkletUrl\n this.featuresExtratorUrl = featuresExtratorUrl\n this.maxBufferSize = maxBufferSize\n }\n\n // Utility to handle user media stream\n async getMediaStream() {\n try {\n return await navigator.mediaDevices.getUserMedia({ audio: true })\n } catch (error) {\n this.logger?.error('Failed to get media stream:', error)\n throw error\n }\n }\n\n // Prepare recording with options\n async prepareRecording(\n recordingConfig: RecordingConfig = {}\n ): Promise<boolean> {\n if (this.isRecording) {\n this.logger?.warn(\n 'Cannot prepare: Recording is already in progress'\n )\n return false\n }\n\n try {\n // Check permissions and initialize basic settings\n await this.getMediaStream().then((stream) => {\n // Just verify we can access the microphone by getting a stream, then release it\n stream.getTracks().forEach((track) => track.stop())\n })\n\n this.bitDepth = encodingToBitDepth({\n encoding: recordingConfig.encoding ?? 'pcm_32bit',\n })\n\n // Store recording configuration for later use\n this.recordingConfig = recordingConfig\n\n // Use custom filename if provided, otherwise fallback to timestamp\n if (recordingConfig.filename) {\n // Remove any existing extension from the filename\n this.streamUuid = recordingConfig.filename.replace(\n /\\.[^/.]+$/,\n ''\n )\n } else {\n this.streamUuid = Date.now().toString()\n }\n\n this.logger?.debug('Recording preparation completed successfully')\n return true\n } catch (error) {\n this.logger?.error('Error preparing recording:', error)\n return false\n }\n }\n\n // Start recording with options\n async startRecording(\n recordingConfig: RecordingConfig = {}\n ): Promise<StartRecordingResult> {\n if (this.isRecording) {\n throw new Error('Recording is already in progress')\n }\n\n // If we haven't prepared or have different settings, prepare now\n if (\n !this.recordingConfig ||\n this.recordingConfig.sampleRate !== recordingConfig.sampleRate ||\n this.recordingConfig.channels !== recordingConfig.channels ||\n this.recordingConfig.encoding !== recordingConfig.encoding\n ) {\n await this.prepareRecording(recordingConfig)\n } else {\n this.logger?.debug(\n 'Using previously prepared recording configuration'\n )\n }\n\n // Save recording config for reference\n this.recordingConfig = recordingConfig\n\n const audioContext = new (window.AudioContext ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Allow webkitAudioContext for Safari\n window.webkitAudioContext)()\n const stream = await this.getMediaStream()\n\n const source = audioContext.createMediaStreamSource(stream)\n\n this.customRecorder = new WebRecorder({\n logger: this.logger,\n audioContext,\n source,\n recordingConfig,\n emitAudioEventCallback: this.customRecorderEventCallback.bind(this),\n emitAudioAnalysisCallback:\n this.customRecorderAnalysisCallback.bind(this),\n onInterruption: this.handleRecordingInterruption.bind(this),\n })\n await this.customRecorder.init()\n this.customRecorder.start()\n\n this.isRecording = true\n this.recordingStartTime = Date.now()\n this.pausedTime = 0\n this.isPaused = false\n this.lastEmittedSize = 0\n this.lastEmittedTime = 0\n this.lastEmittedCompressionSize = 0\n this.currentInterval = recordingConfig.interval ?? 1000\n this.currentIntervalAnalysis = recordingConfig.intervalAnalysis ?? 500\n this.lastEmittedAnalysisTime = Date.now()\n\n // Use custom filename if provided, otherwise fallback to timestamp\n if (recordingConfig.filename) {\n // Remove any existing extension from the filename\n this.streamUuid = recordingConfig.filename.replace(/\\.[^/.]+$/, '')\n } else {\n this.streamUuid = Date.now().toString()\n }\n\n const fileUri = `${this.streamUuid}.${this.extension}`\n const streamConfig: StartRecordingResult = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n bitDepth: this.bitDepth,\n channels: recordingConfig.channels ?? 1,\n sampleRate: recordingConfig.sampleRate ?? 44100,\n compression: recordingConfig.compression\n ? {\n ...recordingConfig.compression,\n bitrate: recordingConfig.compression?.bitrate ?? 128000,\n size: 0,\n mimeType: 'audio/webm',\n format: recordingConfig.compression?.format ?? 'opus',\n compressedFileUri: '',\n }\n : undefined,\n }\n return streamConfig\n }\n\n /**\n * Centralized handler for recording interruptions\n */\n private handleRecordingInterruption(event: {\n reason: RecordingInterruptionReason | string\n isPaused: boolean\n timestamp: number\n message?: string\n }): void {\n this.logger?.debug(`Received recording interruption: ${event.reason}`)\n\n // Update local state if the interruption should pause recording\n if (event.isPaused) {\n this.isPaused = true\n\n // If this is a device disconnection, handle according to behavior setting\n if (event.reason === 'deviceDisconnected') {\n this.pausedTime = Date.now()\n\n // Check if we should try fallback to another device\n if (\n this.recordingConfig?.deviceDisconnectionBehavior ===\n 'fallback'\n ) {\n this.logger?.debug(\n 'Device disconnected with fallback behavior - attempting to switch to default device'\n )\n\n // Try to restart with default device\n this.handleDeviceFallback().catch((error) => {\n // If fallback fails, emit warning\n this.logger?.error('Device fallback failed:', error)\n this.emit('onRecordingInterrupted', {\n reason: 'deviceSwitchFailed',\n isPaused: true,\n timestamp: Date.now(),\n message:\n 'Failed to switch to fallback device. Recording paused.',\n })\n })\n } else {\n // Just warn about disconnection if fallback not enabled\n this.logger?.warn(\n 'Device disconnected - recording paused automatically'\n )\n this.emit('onRecordingInterrupted', event)\n }\n } else {\n // For other interruption types, just emit the event\n this.emit('onRecordingInterrupted', event)\n }\n } else {\n // If not causing a pause, just forward the event\n this.emit('onRecordingInterrupted', event)\n }\n }\n\n /**\n * Handler for audio events from the WebRecorder\n */\n private customRecorderEventCallback({\n data,\n position,\n compression,\n }: EmitAudioEventProps): void {\n // Keep only the latest chunks based on maxBufferSize\n this.audioChunks.push(new Float32Array(data))\n if (this.audioChunks.length > this.maxBufferSize) {\n this.audioChunks.shift() // Remove oldest chunk\n }\n this.currentSize += data.byteLength\n this.emitAudioEvent({ data, position, compression })\n this.lastEmittedTime = Date.now()\n this.lastEmittedSize = this.currentSize\n this.lastEmittedCompressionSize = compression?.size ?? 0\n }\n\n /**\n * Handler for audio analysis events from the WebRecorder\n */\n private customRecorderAnalysisCallback(\n audioAnalysisData: AudioAnalysis\n ): void {\n this.emit('AudioAnalysis', audioAnalysisData)\n }\n\n // Get recording duration\n private getRecordingDuration(): number {\n if (!this.isRecording) {\n return 0\n }\n\n return this.currentDurationMs\n }\n\n emitAudioEvent({ data, position, compression }: EmitAudioEventProps) {\n const fileUri = `${this.streamUuid}.${this.extension}`\n if (compression?.size) {\n this.lastEmittedCompressionSize = compression.size\n this.totalCompressedSize = compression.totalSize\n }\n\n // Update latest position for tracking\n this.latestPosition = position\n\n // Calculate duration of this chunk in ms\n const sampleRate = this.recordingConfig?.sampleRate || 44100\n const chunkDurationMs = (data.length / sampleRate) * 1000\n\n // Handle duration calculation\n if (this.customRecorder?.isFirstChunkAfterSwitch) {\n this.logger?.debug(\n `Processing first chunk after device switch, duration preserved at ${this.currentDurationMs}ms`\n )\n this.customRecorder.isFirstChunkAfterSwitch = false\n } else {\n this.currentDurationMs += chunkDurationMs\n }\n\n const audioEventPayload: AudioEventPayload = {\n fileUri,\n mimeType: `audio/${this.extension}`,\n lastEmittedSize: this.lastEmittedSize,\n deltaSize: data.byteLength,\n position,\n totalSize: this.currentSize,\n buffer: data,\n streamUuid: this.streamUuid ?? '',\n compression: compression\n ? {\n data: compression?.data,\n totalSize: this.totalCompressedSize,\n eventDataSize: compression?.size ?? 0,\n position,\n }\n : undefined,\n }\n\n this.emit('AudioData', audioEventPayload)\n }\n\n // Stop recording\n async stopRecording(): Promise<AudioRecording> {\n if (!this.customRecorder) {\n throw new Error('Recorder is not initialized')\n }\n\n this.logger?.debug('Starting stop process')\n\n try {\n const { compressedBlob } = await this.customRecorder.stop()\n\n this.isRecording = false\n this.isPaused = false\n\n let compression: AudioRecording['compression']\n let fileUri = `${this.streamUuid}.${this.extension}`\n let mimeType = `audio/${this.extension}`\n\n // Process compressed audio if available\n if (compressedBlob && this.recordingConfig?.compression?.enabled) {\n const compressedUri = URL.createObjectURL(compressedBlob)\n compression = {\n compressedFileUri: compressedUri,\n size: compressedBlob.size,\n mimeType: 'audio/webm',\n format: 'opus',\n bitrate: this.recordingConfig.compression.bitrate ?? 128000,\n }\n\n // Use compressed values when compression is enabled\n fileUri = compressedUri\n mimeType = 'audio/webm'\n }\n\n // Use the stored streamUuid for the final filename\n const filename = `${this.streamUuid}.${this.extension}`\n const result: AudioRecording = {\n fileUri,\n filename,\n bitDepth: this.bitDepth,\n createdAt: this.recordingStartTime,\n channels: this.recordingConfig?.channels ?? 1,\n sampleRate: this.recordingConfig?.sampleRate ?? 44100,\n durationMs: this.currentDurationMs,\n size: this.currentSize,\n mimeType,\n compression,\n }\n\n // Reset after creating the result\n this.streamUuid = null\n\n return result\n } catch (error) {\n this.logger?.error('Error stopping recording:', error)\n throw error\n }\n }\n\n // Pause recording\n async pauseRecording() {\n if (!this.isRecording) {\n throw new Error('Recording is not active')\n }\n\n if (this.isPaused) {\n this.logger?.debug('Recording already paused, skipping')\n return\n }\n\n try {\n if (this.customRecorder) {\n this.customRecorder.pause()\n }\n this.isPaused = true\n this.pausedTime = Date.now()\n } catch (error) {\n this.logger?.error('Error in pauseRecording', error)\n // Even if the pause operation failed, make sure our state is consistent\n this.isPaused = true\n this.pausedTime = Date.now()\n }\n }\n\n // Resume recording\n async resumeRecording() {\n if (!this.isPaused) {\n throw new Error('Recording is not paused')\n }\n\n this.logger?.debug('Resuming recording', {\n deviceDisconnectionBehavior:\n this.recordingConfig?.deviceDisconnectionBehavior,\n isDeviceDisconnected: this.customRecorder?.isDeviceDisconnected,\n })\n\n try {\n // If we have no recorder, or if the device is disconnected, always attempt fallback\n if (\n !this.customRecorder ||\n this.customRecorder.isDeviceDisconnected\n ) {\n this.logger?.debug(\n 'No recorder exists or device disconnected - attempting fallback on resume'\n )\n await this.handleDeviceFallback()\n // handleDeviceFallback will manage resuming if successful, or emit error if failed.\n return\n }\n\n // Normal resume path - device is still connected\n this.customRecorder.resume()\n this.isPaused = false\n\n // Adjust the recording start time to account for the pause duration\n const pauseDuration = Date.now() - this.pausedTime\n this.recordingStartTime += pauseDuration\n this.pausedTime = 0\n\n this.emit('onRecordingInterrupted', {\n reason: 'userResumed',\n isPaused: false,\n timestamp: Date.now(),\n })\n } catch (error) {\n this.logger?.error('Resume failed:', error)\n // Fallback to emitting a general failure if resume fails unexpectedly\n this.emit('onRecordingInterrupted', {\n reason: 'resumeFailed', // Use a more specific reason\n isPaused: true, // Remain paused if resume fails\n timestamp: Date.now(),\n message:\n 'Failed to resume recording. Please stop and start again.',\n })\n }\n }\n\n // Get current status\n status() {\n const durationMs = this.getRecordingDuration()\n\n const status: AudioStreamStatus = {\n isRecording: this.isRecording,\n isPaused: this.isPaused,\n durationMs,\n size: this.currentSize,\n interval: this.currentInterval,\n intervalAnalysis: this.currentIntervalAnalysis,\n mimeType: `audio/${this.extension}`,\n compression: this.recordingConfig?.compression?.enabled\n ? {\n size: this.totalCompressedSize,\n mimeType: 'audio/webm',\n format: this.recordingConfig.compression.format ?? 'opus',\n bitrate:\n this.recordingConfig.compression.bitrate ?? 128000,\n compressedFileUri: `${this.streamUuid}.webm`,\n }\n : undefined,\n }\n return status\n }\n\n /**\n * Handles device fallback when the current device is disconnected\n */\n private async handleDeviceFallback(): Promise<boolean> {\n this.logger?.debug('Starting device fallback procedure')\n\n if (!this.isRecording) {\n return false\n }\n\n try {\n // Save important state before switching\n const currentPosition = this.latestPosition\n const existingAudioChunks = [...this.audioChunks]\n\n // Save compressed chunks if available\n let compressedChunks: Blob[] = []\n if (this.customRecorder) {\n try {\n compressedChunks = this.customRecorder.getCompressedChunks()\n } catch (err) {\n this.logger?.warn('Failed to get compressed chunks:', err)\n }\n }\n\n // Save the current counter value for continuity\n let currentDataPointCounter = 0\n if (this.customRecorder) {\n currentDataPointCounter =\n this.customRecorder.getDataPointCounter()\n }\n\n // Clean up existing recorder\n if (this.customRecorder) {\n try {\n this.customRecorder.cleanup()\n } catch (cleanupError) {\n this.logger?.warn('Error during cleanup:', cleanupError)\n }\n }\n\n // Keep recording state true but mark as paused\n this.isPaused = true\n this.pausedTime = Date.now()\n\n // Store current size and other stats\n const previousTotalSize = this.currentSize\n const previousLastEmittedSize = this.lastEmittedSize\n const previousCompressedSize = this.totalCompressedSize\n\n // Try to get a fallback device\n const fallbackDeviceInfo = await this.getFallbackDevice()\n if (!fallbackDeviceInfo) {\n this.emit('onRecordingInterrupted', {\n reason: 'deviceSwitchFailed',\n isPaused: true,\n timestamp: Date.now(),\n message:\n 'Failed to switch to fallback device. Recording paused.',\n })\n return false\n }\n\n // Start recording with the new device\n try {\n const stream = await this.requestPermissionsAndGetUserMedia(\n fallbackDeviceInfo.deviceId\n )\n const audioContext = new (window.AudioContext ||\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Allow webkitAudioContext for Safari\n window.webkitAudioContext)()\n\n const source = audioContext.createMediaStreamSource(stream)\n\n // Create a new recorder with the fallback device\n this.customRecorder = new WebRecorder({\n logger: this.logger,\n audioContext,\n source,\n recordingConfig: this.recordingConfig || {},\n emitAudioEventCallback:\n this.customRecorderEventCallback.bind(this),\n emitAudioAnalysisCallback:\n this.customRecorderAnalysisCallback.bind(this),\n onInterruption: this.handleRecordingInterruption.bind(this),\n })\n\n await this.customRecorder.init()\n\n // Set the initial position to continue from the previous device\n this.customRecorder.setPosition(currentPosition)\n\n // Reset the data point counter to continue from where the previous device left off\n if (currentDataPointCounter > 0) {\n this.customRecorder.resetDataPointCounter(\n currentDataPointCounter\n )\n }\n\n // Prepare the recorder to handle the device switch properly\n this.customRecorder.prepareForDeviceSwitch()\n\n // Restore the existing audio chunks\n if (existingAudioChunks.length > 0) {\n this.audioChunks = existingAudioChunks\n }\n\n // Restore compressed chunks if available\n if (compressedChunks.length > 0) {\n this.customRecorder.setCompressedChunks(compressedChunks)\n }\n\n // Start the new recorder while preserving counters\n this.customRecorder.start(true)\n\n // Update recording state\n this.isPaused = false\n this.recordingStartTime = Date.now()\n\n // Restore size counters to maintain continuity\n this.currentSize = previousTotalSize\n this.lastEmittedSize = previousLastEmittedSize\n this.totalCompressedSize = previousCompressedSize\n\n // Notify that we switched to a fallback device\n if (this.eventCallback) {\n this.eventCallback({\n type: 'deviceFallback',\n device: fallbackDeviceInfo.deviceId,\n timestamp: new Date(),\n })\n }\n return true\n } catch (error) {\n this.logger?.error(\n 'Failed to start recording with fallback device',\n error\n )\n this.isPaused = true\n this.emit('onRecordingInterrupted', {\n reason: 'deviceSwitchFailed',\n isPaused: true,\n timestamp: Date.now(),\n message:\n 'Failed to switch to fallback device. Recording paused.',\n })\n return false\n }\n } catch (error) {\n this.logger?.error('Failed to use fallback device', error)\n this.isPaused = true\n this.emit('onRecordingInterrupted', {\n reason: 'deviceSwitchFailed',\n isPaused: true,\n timestamp: Date.now(),\n message:\n 'Failed to switch to fallback device. Recording paused.',\n })\n return false\n }\n }\n\n /**\n * Attempts to get a fallback audio device\n */\n private async getFallbackDevice(): Promise<MediaDeviceInfo | null> {\n try {\n // Get list of available audio input devices\n const devices = await navigator.mediaDevices.enumerateDevices()\n const audioInputDevices = devices.filter(\n (device) => device.kind === 'audioinput'\n )\n\n if (audioInputDevices.length === 0) {\n return null\n }\n\n // Try to find a device that's not the current one\n if (this.customRecorder) {\n try {\n // Use mediaDevices.enumerateDevices to find the current active device\n const tracks = navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then((stream) => {\n const track = stream.getAudioTracks()[0]\n return track ? track.label : ''\n })\n .catch(() => '')\n\n const currentTrackLabel = await tracks\n\n if (currentTrackLabel) {\n // Find a device with a different label\n const differentDevice = audioInputDevices.find(\n (device) =>\n device.label &&\n device.label !== currentTrackLabel\n )\n\n if (differentDevice) {\n return differentDevice\n }\n }\n } catch (err) {\n this.logger?.warn(\n 'Error determining current device, using default'\n )\n }\n }\n\n // Return the first available device (default device)\n return audioInputDevices[0]\n } catch (error) {\n this.logger?.error('Error finding fallback device:', error)\n return null\n }\n }\n\n /**\n * Gets user media with specific device ID\n */\n private async requestPermissionsAndGetUserMedia(\n deviceId: string\n ): Promise<MediaStream> {\n try {\n // Request the specific device\n return await navigator.mediaDevices.getUserMedia({\n audio: {\n deviceId: { exact: deviceId },\n },\n })\n } catch (error) {\n this.logger?.error(\n `Failed to get media for device ${deviceId}`,\n error\n )\n // Try with default constraints as fallback\n return await navigator.mediaDevices.getUserMedia({ audio: true })\n }\n }\n\n init(options?: ExpoAudioStreamOptions): Promise<void> {\n try {\n this.logger = options?.logger\n this.eventCallback = options?.eventCallback\n return Promise.resolve()\n } catch (error) {\n this.logger?.error('Error initializing ExpoAudioStream', error)\n return Promise.reject(error)\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStreamModule.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAmBA,QAAA,IAAI,qBAAqB,EAAE,GAAG,CAAA;
|
|
1
|
+
{"version":3,"file":"ExpoAudioStreamModule.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"AAmBA,QAAA,IAAI,qBAAqB,EAAE,GAAG,CAAA;AA08B9B,eAAe,qBAAqB,CAAA"}
|
|
@@ -573,6 +573,26 @@ if (Platform.OS === 'web') {
|
|
|
573
573
|
delete ExpoAudioStreamModule.listeners[eventName];
|
|
574
574
|
}
|
|
575
575
|
};
|
|
576
|
+
ExpoAudioStreamModule.prepareRecording = async (options) => {
|
|
577
|
+
// For web platform, we'll implement a simplified version that just checks permissions
|
|
578
|
+
// and does minimal setup. The actual recording setup will still happen in startRecording.
|
|
579
|
+
try {
|
|
580
|
+
// Check for microphone permissions
|
|
581
|
+
const permissionsResult = await ExpoAudioStreamModule.getPermissionsAsync();
|
|
582
|
+
if (!permissionsResult.granted) {
|
|
583
|
+
throw new Error('Microphone permission not granted');
|
|
584
|
+
}
|
|
585
|
+
// If using a web instance, call its prepareRecording method
|
|
586
|
+
if (instance) {
|
|
587
|
+
return await instance.prepareRecording(options);
|
|
588
|
+
}
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
console.error('Error preparing recording:', error);
|
|
593
|
+
throw error;
|
|
594
|
+
}
|
|
595
|
+
};
|
|
576
596
|
}
|
|
577
597
|
// Move the encodeCompressedAudio function outside the if block to fix the ESLint error
|
|
578
598
|
async function encodeCompressedAudio(buffer, format, bitrate) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStreamModule.js","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeModule } from 'expo-modules-core'\nimport { Platform } from 'react-native'\n\nimport {\n ExtractAudioDataOptions,\n ExtractedAudioData,\n BitDepth,\n TrimAudioOptions,\n TrimAudioResult,\n} from './ExpoAudioStream.types'\nimport {\n ExpoAudioStreamWeb,\n ExpoAudioStreamWebProps,\n} from './ExpoAudioStream.web'\nimport { processAudioBuffer } from './utils/audioProcessing'\nimport crc32 from './utils/crc32'\nimport { writeWavHeader } from './utils/writeWavHeader'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet ExpoAudioStreamModule: any\n\nif (Platform.OS === 'web') {\n let instance: ExpoAudioStreamWeb | null = null\n\n ExpoAudioStreamModule = (webProps: ExpoAudioStreamWebProps) => {\n if (!instance) {\n instance = new ExpoAudioStreamWeb(webProps)\n }\n return instance\n }\n ExpoAudioStreamModule.requestPermissionsAsync = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n })\n stream.getTracks().forEach((track) => track.stop())\n return {\n status: 'granted',\n expires: 'never',\n canAskAgain: true,\n granted: true,\n }\n } catch {\n return {\n status: 'denied',\n expires: 'never',\n canAskAgain: true,\n granted: false,\n }\n }\n }\n ExpoAudioStreamModule.getPermissionsAsync = async () => {\n let maybeStatus: string | null = null\n\n if (navigator?.permissions?.query) {\n try {\n const { state } = await navigator.permissions.query({\n name: 'microphone' as PermissionName,\n })\n maybeStatus = state\n } catch {\n maybeStatus = null\n }\n }\n\n switch (maybeStatus) {\n case 'granted':\n return {\n status: 'granted',\n expires: 'never',\n canAskAgain: true,\n granted: true,\n }\n case 'denied':\n return {\n status: 'denied',\n expires: 'never',\n canAskAgain: true,\n granted: false,\n }\n default:\n return await ExpoAudioStreamModule.requestPermissionsAsync()\n }\n }\n ExpoAudioStreamModule.extractAudioData = async (\n options: ExtractAudioDataOptions\n ): Promise<ExtractedAudioData> => {\n try {\n const {\n fileUri,\n position,\n length,\n startTimeMs,\n endTimeMs,\n decodingOptions,\n includeNormalizedData,\n includeBase64Data,\n includeWavHeader = false,\n logger,\n } = options\n\n logger?.debug('EXTRACT AUDIO - Step 1: Initial request', {\n fileUri,\n extractionParams: {\n position,\n length,\n startTimeMs,\n endTimeMs,\n },\n decodingOptions: {\n targetSampleRate:\n decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n targetBitDepth: decodingOptions?.targetBitDepth ?? 16,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n },\n outputOptions: {\n includeNormalizedData,\n includeBase64Data,\n includeWavHeader,\n },\n })\n\n // Process the audio using shared helper function\n const processedBuffer = await processAudioBuffer({\n fileUri,\n targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n position,\n length,\n startTimeMs,\n endTimeMs,\n logger,\n })\n\n logger?.debug('EXTRACT AUDIO - Step 2: Audio processing complete', {\n processedData: {\n samples: processedBuffer.samples,\n sampleRate: processedBuffer.sampleRate,\n channels: processedBuffer.channels,\n durationMs: processedBuffer.durationMs,\n },\n })\n\n const channelData = processedBuffer.channelData\n const bitDepth = (decodingOptions?.targetBitDepth ?? 16) as BitDepth\n const bytesPerSample = bitDepth / 8\n const numSamples = processedBuffer.samples\n\n logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion setup', {\n channelData: {\n length: channelData.length,\n first: channelData[0],\n last: channelData[channelData.length - 1],\n },\n calculation: {\n bitDepth,\n bytesPerSample,\n numSamples,\n expectedBytes: numSamples * bytesPerSample,\n },\n })\n\n // Create PCM data with correct length based on original byte length\n const pcmData = new Uint8Array(numSamples * bytesPerSample)\n let offset = 0\n\n // Convert Float32 samples to PCM format\n for (let i = 0; i < numSamples; i++) {\n const sample = channelData[i]\n const value = Math.max(-1, Math.min(1, sample))\n // Convert to 16-bit signed integer\n let intValue = Math.round(value * 32767)\n\n // Handle negative values correctly\n if (intValue < 0) {\n intValue = 65536 + intValue\n }\n\n // Write as little-endian\n pcmData[offset++] = intValue & 255 // Low byte\n pcmData[offset++] = (intValue >> 8) & 255 // High byte\n }\n\n const durationMs = Math.round(\n (numSamples / processedBuffer.sampleRate) * 1000\n )\n\n logger?.debug('EXTRACT AUDIO - Step 4: Final output', {\n pcmData: {\n length: pcmData.length,\n first: pcmData[0],\n last: pcmData[pcmData.length - 1],\n },\n timing: {\n numSamples,\n sampleRate: processedBuffer.sampleRate,\n durationMs,\n shouldBe3000ms: endTimeMs\n ? endTimeMs - (startTimeMs ?? 0) === 3000\n : undefined,\n },\n })\n\n const result: ExtractedAudioData = {\n pcmData: new Uint8Array(pcmData.buffer),\n sampleRate: processedBuffer.sampleRate,\n channels: processedBuffer.channels,\n bitDepth,\n durationMs,\n format: `pcm_${bitDepth}bit` as const,\n samples: numSamples,\n }\n\n // Add WAV header if requested\n if (includeWavHeader) {\n logger?.debug('EXTRACT AUDIO - Step 4: Adding WAV header', {\n originalLength: pcmData.length,\n newLength: result.pcmData.length,\n firstBytes: Array.from(result.pcmData.slice(0, 44)), // WAV header is 44 bytes\n })\n const wavBuffer = writeWavHeader({\n buffer: pcmData.buffer.slice(0, pcmData.length),\n sampleRate: processedBuffer.sampleRate,\n numChannels: processedBuffer.channels,\n bitDepth,\n })\n result.pcmData = new Uint8Array(wavBuffer)\n result.hasWavHeader = true\n }\n\n if (includeNormalizedData) {\n // // Simple approach: Create normalized data directly from the PCM data\n // // Just convert to -1 to 1 range without any amplification\n // const normalizedData = new Float32Array(numSamples)\n\n // // Convert the PCM data to float values\n // for (let i = 0; i < numSamples; i++) {\n // // Get the 16-bit PCM value (little endian)\n // const lowByte = pcmData[i * 2]\n // const highByte = pcmData[i * 2 + 1]\n // const pcmValue = (highByte << 8) | lowByte\n\n // // Convert to signed 16-bit value\n // const signedValue =\n // pcmValue > 32767 ? pcmValue - 65536 : pcmValue\n\n // // Normalize to float between -1 and 1\n // normalizedData[i] = signedValue / 32768.0\n // }\n // Store the normalized data in the result\n result.normalizedData = channelData\n }\n\n if (includeBase64Data) {\n // Convert the PCM data to a base64 string\n const binary = Array.from(new Uint8Array(pcmData.buffer))\n .map((b) => String.fromCharCode(b))\n .join('')\n result.base64Data = btoa(binary)\n }\n\n if (options.computeChecksum) {\n result.checksum = crc32.buf(pcmData)\n }\n\n logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion complete', {\n pcmStats: {\n length: pcmData.length,\n bytesPerSample,\n totalSamples: numSamples,\n firstBytes: Array.from(pcmData.slice(0, 16)),\n lastBytes: Array.from(pcmData.slice(-16)),\n },\n })\n\n return result\n } catch (error) {\n options.logger?.error('EXTRACT AUDIO - Error:', error)\n throw error\n }\n }\n\n ExpoAudioStreamModule.trimAudio = async (\n options: TrimAudioOptions\n ): Promise<TrimAudioResult> => {\n try {\n const startTime = performance.now()\n const {\n fileUri,\n mode = 'single',\n startTimeMs,\n endTimeMs,\n ranges,\n outputFileName,\n outputFormat,\n } = options\n\n // Validate inputs\n if (!fileUri) {\n throw new Error('fileUri is required')\n }\n\n if (\n mode === 'single' &&\n startTimeMs === undefined &&\n endTimeMs === undefined\n ) {\n throw new Error(\n 'At least one of startTimeMs or endTimeMs must be provided in single mode'\n )\n }\n\n if (\n (mode === 'keep' || mode === 'remove') &&\n (!ranges || ranges.length === 0)\n ) {\n throw new Error(\n 'ranges must be provided and non-empty for keep or remove modes'\n )\n }\n\n // Create AudioContext\n const audioContext = new (window.AudioContext ||\n (window as any).webkitAudioContext)()\n\n // First, load the entire audio file to get its properties\n const response = await fetch(fileUri)\n const arrayBuffer = await response.arrayBuffer()\n const originalAudioBuffer =\n await audioContext.decodeAudioData(arrayBuffer)\n\n // Get original audio properties\n const originalSampleRate = originalAudioBuffer.sampleRate\n const originalChannels = originalAudioBuffer.numberOfChannels\n\n // Add more detailed logging\n console.log(`Original audio details:`, {\n sampleRate: originalSampleRate,\n channels: originalChannels,\n duration: originalAudioBuffer.duration,\n length: originalAudioBuffer.length,\n // Log a few samples to verify content\n firstSamples: Array.from(\n originalAudioBuffer.getChannelData(0).slice(0, 5)\n ),\n })\n\n // Determine output format - use original values as defaults if not specified\n let format = outputFormat?.format || 'wav'\n const targetSampleRate =\n outputFormat?.sampleRate || originalSampleRate\n const targetChannels = outputFormat?.channels || originalChannels\n const targetBitDepth = outputFormat?.bitDepth || 16\n\n // Get file info from the URL\n const filename =\n outputFileName ||\n fileUri.split('/').pop() ||\n 'trimmed-audio.wav'\n\n // Process based on mode\n let resultBuffer: AudioBuffer\n\n // Report initial progress\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 10,\n })\n\n if (mode === 'single') {\n // Single mode: extract a single range\n // Use original sample rate and channels for extraction to preserve quality\n const { buffer } = await processAudioBuffer({\n fileUri,\n targetSampleRate, // Use the requested sample rate\n targetChannels,\n normalizeAudio: false,\n startTimeMs,\n endTimeMs,\n audioContext,\n })\n\n console.log(`Processed buffer details:`, {\n sampleRate: buffer.sampleRate,\n channels: buffer.numberOfChannels,\n duration: buffer.duration,\n length: buffer.length,\n // Log a few samples to verify content\n firstSamples: Array.from(\n buffer.getChannelData(0).slice(0, 5)\n ),\n })\n\n resultBuffer = buffer\n\n // If we need to change sample rate or channels, do it after extraction\n if (\n targetSampleRate !== originalSampleRate ||\n targetChannels !== originalChannels\n ) {\n console.log(\n `Resampling from ${originalSampleRate}Hz to ${targetSampleRate}Hz`\n )\n resultBuffer = await resampleAudioBuffer(\n audioContext,\n buffer,\n targetSampleRate,\n targetChannels\n )\n }\n } else {\n // For keep or remove modes\n const fullDuration = originalAudioBuffer.duration * 1000 // in ms\n\n type ProcessSegment = {\n startTimeMs: number\n endTimeMs: number\n }\n\n let segmentsToProcess: ProcessSegment[] = []\n\n if (mode === 'keep') {\n // For keep mode, use the ranges directly\n segmentsToProcess = ranges!\n } else {\n // mode === 'remove'\n // For remove mode, invert the ranges\n const sortedRanges = [...ranges!].sort(\n (a, b) => a.startTimeMs - b.startTimeMs\n )\n\n // Add segment from start to first range if needed\n if (\n sortedRanges.length > 0 &&\n sortedRanges[0].startTimeMs > 0\n ) {\n segmentsToProcess.push({\n startTimeMs: 0,\n endTimeMs: sortedRanges[0].startTimeMs,\n })\n }\n\n // Add segments between ranges\n for (let i = 0; i < sortedRanges.length - 1; i++) {\n segmentsToProcess.push({\n startTimeMs: sortedRanges[i].endTimeMs,\n endTimeMs: sortedRanges[i + 1].startTimeMs,\n })\n }\n\n // Add segment from last range to end if needed\n if (\n sortedRanges.length > 0 &&\n sortedRanges[sortedRanges.length - 1].endTimeMs <\n fullDuration\n ) {\n segmentsToProcess.push({\n startTimeMs:\n sortedRanges[sortedRanges.length - 1].endTimeMs,\n endTimeMs: fullDuration,\n })\n }\n }\n\n // Filter out empty or invalid segments\n segmentsToProcess = segmentsToProcess.filter(\n (segment) =>\n segment.startTimeMs < segment.endTimeMs &&\n segment.endTimeMs - segment.startTimeMs > 1\n ) // 1ms minimum\n\n if (segmentsToProcess.length === 0) {\n throw new Error(\n 'No valid segments to process after filtering ranges'\n )\n }\n\n // Process each segment using original sample rate and channels\n const segmentBuffers: AudioBuffer[] = []\n\n for (let i = 0; i < segmentsToProcess.length; i++) {\n const segment = segmentsToProcess[i]\n\n // Report progress for each segment\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress:\n 10 +\n Math.round((i / segmentsToProcess.length) * 40),\n })\n\n // Use processAudioBuffer to extract this segment\n const { buffer: segmentBuffer } = await processAudioBuffer({\n fileUri,\n targetSampleRate: originalSampleRate, // Use original sample rate\n targetChannels: originalChannels, // Use original channels\n normalizeAudio: false,\n startTimeMs: segment.startTimeMs,\n endTimeMs: segment.endTimeMs,\n audioContext,\n })\n\n segmentBuffers.push(segmentBuffer)\n }\n\n // Concatenate all segments\n const totalSamples = segmentBuffers.reduce(\n (sum, buffer) => sum + buffer.length,\n 0\n )\n\n // Create buffer with original properties first\n const concatenatedBuffer = audioContext.createBuffer(\n originalChannels,\n totalSamples,\n originalSampleRate\n )\n\n let offset = 0\n for (const segmentBuffer of segmentBuffers) {\n for (\n let channel = 0;\n channel < originalChannels;\n channel++\n ) {\n const outputData =\n concatenatedBuffer.getChannelData(channel)\n const segmentData =\n segmentBuffer.getChannelData(channel)\n\n for (let i = 0; i < segmentBuffer.length; i++) {\n outputData[offset + i] = segmentData[i]\n }\n }\n offset += segmentBuffer.length\n }\n\n resultBuffer = concatenatedBuffer\n\n // If we need to change sample rate or channels, do it after concatenation\n if (\n targetSampleRate !== originalSampleRate ||\n targetChannels !== originalChannels\n ) {\n console.log(\n `Resampling concatenated buffer from ${originalSampleRate}Hz to ${targetSampleRate}Hz`\n )\n resultBuffer = await resampleAudioBuffer(\n audioContext,\n concatenatedBuffer,\n targetSampleRate,\n targetChannels\n )\n }\n }\n\n // Report progress (50% - processing complete)\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 50,\n })\n\n // Encode the result based on the requested format\n let outputData: ArrayBuffer\n let outputMimeType: string\n let compressionInfo: any = null\n\n // Check if AAC was requested on web and show a warning\n if (format === 'aac' && Platform.OS === 'web') {\n console.warn(\n 'AAC format is not supported on web platforms. Falling back to OPUS format.'\n )\n format = 'opus'\n }\n\n if (format === 'wav') {\n // Create a properly interleaved buffer for WAV format\n // For WAV, we need to convert Float32Array to Int16Array (for 16-bit audio)\n const numSamples =\n resultBuffer.length * resultBuffer.numberOfChannels\n const interleavedData = new Int16Array(numSamples)\n\n // Log detailed information about the buffer before encoding\n console.log(`Creating WAV file:`, {\n bufferSampleRate: resultBuffer.sampleRate,\n bufferChannels: resultBuffer.numberOfChannels,\n bufferLength: resultBuffer.length,\n targetSampleRate,\n targetChannels,\n targetBitDepth,\n // Log a few samples to verify content\n firstSamples: Array.from(\n resultBuffer.getChannelData(0).slice(0, 5)\n ),\n })\n\n // Interleave channels properly\n for (let i = 0; i < resultBuffer.length; i++) {\n for (\n let channel = 0;\n channel < resultBuffer.numberOfChannels;\n channel++\n ) {\n // Convert float (-1.0 to 1.0) to int16 (-32768 to 32767)\n const floatSample =\n resultBuffer.getChannelData(channel)[i]\n // Clamp the value to -1.0 to 1.0\n const clampedSample = Math.max(\n -1.0,\n Math.min(1.0, floatSample)\n )\n // Convert to int16\n const intSample = Math.round(clampedSample * 32767)\n // Store in interleaved buffer\n interleavedData[\n i * resultBuffer.numberOfChannels + channel\n ] = intSample\n }\n }\n\n // Convert Int16Array to ArrayBuffer for WAV header\n const rawBuffer = interleavedData.buffer\n\n // IMPORTANT: Make sure we're using the ACTUAL sample rate of the buffer\n // not just what was requested in the options\n console.log(\n `Creating WAV with ${resultBuffer.numberOfChannels} channels at ${resultBuffer.sampleRate}Hz`\n )\n\n outputData = writeWavHeader({\n buffer: rawBuffer as ArrayBuffer,\n sampleRate: resultBuffer.sampleRate, // Use the actual buffer's sample rate\n numChannels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth as BitDepth,\n })\n outputMimeType = 'audio/wav'\n } else if (format === 'opus' || format === 'aac') {\n try {\n // Try to use MediaRecorder for compressed formats\n const { data, bitrate } = await encodeCompressedAudio(\n resultBuffer,\n format,\n outputFormat?.bitrate\n )\n\n outputData = data\n outputMimeType =\n format === 'opus' ? 'audio/webm' : 'audio/aac'\n compressionInfo = {\n format,\n bitrate,\n size: data.byteLength,\n }\n } catch (error) {\n console.warn(\n `Failed to encode to ${format}, falling back to WAV: ${error}`\n )\n\n // Same WAV encoding as above\n const wavData = new Float32Array(\n resultBuffer.length * resultBuffer.numberOfChannels\n )\n\n for (let i = 0; i < resultBuffer.length; i++) {\n for (\n let channel = 0;\n channel < resultBuffer.numberOfChannels;\n channel++\n ) {\n wavData[\n i * resultBuffer.numberOfChannels + channel\n ] = resultBuffer.getChannelData(channel)[i]\n }\n }\n\n outputData = writeWavHeader({\n buffer: wavData.buffer as ArrayBuffer,\n sampleRate: resultBuffer.sampleRate,\n numChannels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth as BitDepth,\n })\n outputMimeType = 'audio/wav'\n }\n } else {\n // Default to WAV for unsupported formats\n console.warn(\n `Format ${format} not supported on web, using WAV instead`\n )\n\n // Same WAV encoding as above\n const wavData = new Float32Array(\n resultBuffer.length * resultBuffer.numberOfChannels\n )\n\n for (let i = 0; i < resultBuffer.length; i++) {\n for (\n let channel = 0;\n channel < resultBuffer.numberOfChannels;\n channel++\n ) {\n wavData[i * resultBuffer.numberOfChannels + channel] =\n resultBuffer.getChannelData(channel)[i]\n }\n }\n\n outputData = writeWavHeader({\n buffer: wavData.buffer as ArrayBuffer,\n sampleRate: resultBuffer.sampleRate,\n numChannels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth as BitDepth,\n })\n outputMimeType = 'audio/wav'\n }\n\n // Report progress (90% - encoding complete)\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 90,\n })\n\n // Create a blob and URL for the result\n const blob = new Blob([outputData], { type: outputMimeType })\n const outputUri = URL.createObjectURL(blob)\n\n // Calculate processing time\n const processingTimeMs = performance.now() - startTime\n\n // Report progress (100% - complete)\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 100,\n })\n\n // Create result object\n const result: TrimAudioResult = {\n uri: outputUri,\n filename,\n durationMs: Math.round(resultBuffer.duration * 1000),\n size: outputData.byteLength,\n sampleRate: resultBuffer.sampleRate,\n channels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth,\n mimeType: outputMimeType,\n processingInfo: {\n durationMs: processingTimeMs,\n },\n }\n\n // Add compression info if available\n if (compressionInfo) {\n result.compression = compressionInfo\n }\n\n return result\n } catch (error) {\n console.error('Error in trimAudio:', error)\n throw error\n }\n }\n\n // Add a sendEvent method for web\n ExpoAudioStreamModule.sendEvent = (eventName: string, params: any) => {\n // This will be picked up by the LegacyEventEmitter in trimAudio.ts\n if (\n ExpoAudioStreamModule.listeners &&\n ExpoAudioStreamModule.listeners[eventName]\n ) {\n ExpoAudioStreamModule.listeners[eventName].forEach(\n (listener: Function) => {\n listener(params)\n }\n )\n }\n }\n\n // Initialize listeners object\n ExpoAudioStreamModule.listeners = {}\n\n // Add methods for event listeners that LegacyEventEmitter will use\n ExpoAudioStreamModule.addListener = (\n eventName: string,\n listener: Function\n ) => {\n if (!ExpoAudioStreamModule.listeners[eventName]) {\n ExpoAudioStreamModule.listeners[eventName] = []\n }\n ExpoAudioStreamModule.listeners[eventName].push(listener)\n\n // Return an object with a remove method\n return {\n remove: () => {\n const index =\n ExpoAudioStreamModule.listeners[eventName].indexOf(listener)\n if (index !== -1) {\n ExpoAudioStreamModule.listeners[eventName].splice(index, 1)\n }\n },\n }\n }\n\n ExpoAudioStreamModule.removeAllListeners = (eventName: string) => {\n if (ExpoAudioStreamModule.listeners[eventName]) {\n delete ExpoAudioStreamModule.listeners[eventName]\n }\n }\n}\n\n// Move the encodeCompressedAudio function outside the if block to fix the ESLint error\nasync function encodeCompressedAudio(\n buffer: AudioBuffer,\n format: 'opus' | 'aac',\n bitrate?: number\n): Promise<{ data: ArrayBuffer; bitrate: number }> {\n return new Promise((resolve, reject) => {\n try {\n // On web, always use opus if aac is requested\n const actualFormat =\n Platform.OS === 'web' && format === 'aac' ? 'opus' : format\n\n // Check if MediaRecorder supports the requested format\n const mimeType =\n actualFormat === 'opus' ? 'audio/webm;codecs=opus' : 'audio/aac'\n if (!MediaRecorder.isTypeSupported(mimeType)) {\n throw new Error(`MediaRecorder does not support ${mimeType}`)\n }\n\n // Create a new AudioContext and source\n const ctx = new (window.AudioContext ||\n (window as any).webkitAudioContext)()\n const source = ctx.createBufferSource()\n source.buffer = buffer\n\n // Create a MediaStreamDestination to capture the audio\n const destination = ctx.createMediaStreamDestination()\n source.connect(destination)\n\n // Create a MediaRecorder with the requested format\n const recorder = new MediaRecorder(destination.stream, {\n mimeType,\n audioBitsPerSecond:\n bitrate || (actualFormat === 'opus' ? 32000 : 64000),\n })\n\n const chunks: Blob[] = []\n\n recorder.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunks.push(e.data)\n }\n }\n\n recorder.onstop = async () => {\n try {\n const blob = new Blob(chunks, { type: mimeType })\n const arrayBuffer = await blob.arrayBuffer()\n\n // Get the actual bitrate used\n const actualBitrate = Math.round(\n (arrayBuffer.byteLength * 8) / buffer.duration\n )\n\n resolve({\n data: arrayBuffer,\n bitrate: actualBitrate / 1000, // Convert to kbps\n })\n\n // Clean up\n ctx.close()\n } catch (error) {\n reject(error)\n }\n }\n\n // Start recording and playback\n recorder.start()\n source.start(0)\n\n // Stop recording when the buffer finishes playing\n setTimeout(() => {\n recorder.stop()\n source.stop()\n }, buffer.duration * 1000)\n } catch (error) {\n reject(error)\n }\n })\n}\n\n// Improved resampleAudioBuffer function\nasync function resampleAudioBuffer(\n context: AudioContext,\n buffer: AudioBuffer,\n targetSampleRate: number,\n targetChannels: number\n): Promise<AudioBuffer> {\n // If no change needed, return the original buffer\n if (\n buffer.sampleRate === targetSampleRate &&\n buffer.numberOfChannels === targetChannels\n ) {\n return buffer\n }\n\n console.log(\n `Resampling: ${buffer.sampleRate}Hz → ${targetSampleRate}Hz, ${buffer.numberOfChannels} → ${targetChannels} channels`\n )\n\n // Calculate the new length based on the sample rate change\n const newLength = Math.round(\n (buffer.length * targetSampleRate) / buffer.sampleRate\n )\n\n // Create an offline context for resampling\n const offlineContext = new OfflineAudioContext(\n targetChannels,\n newLength,\n targetSampleRate\n )\n\n // Create a source node\n const source = offlineContext.createBufferSource()\n source.buffer = buffer\n\n // If we need to change channel count\n if (buffer.numberOfChannels !== targetChannels) {\n if (targetChannels === 1 && buffer.numberOfChannels > 1) {\n // Downmix to mono\n const merger = offlineContext.createChannelMerger(1)\n\n // Create a gain node to reduce volume when downmixing to prevent clipping\n const gainNode = offlineContext.createGain()\n gainNode.gain.value = 1.0 / buffer.numberOfChannels\n\n source.connect(gainNode)\n gainNode.connect(merger)\n merger.connect(offlineContext.destination)\n } else if (targetChannels === 2 && buffer.numberOfChannels === 1) {\n // Upmix mono to stereo (duplicate the channel)\n const splitter = offlineContext.createChannelSplitter(1)\n const merger = offlineContext.createChannelMerger(2)\n\n source.connect(splitter)\n splitter.connect(merger, 0, 0)\n splitter.connect(merger, 0, 1)\n merger.connect(offlineContext.destination)\n } else {\n // For other cases, just connect and let the system handle it\n source.connect(offlineContext.destination)\n }\n } else {\n // No channel conversion needed\n source.connect(offlineContext.destination)\n }\n\n // Start rendering\n source.start(0)\n const resampledBuffer = await offlineContext.startRendering()\n\n console.log(\n `Resampling complete: ${resampledBuffer.length} samples at ${resampledBuffer.sampleRate}Hz`\n )\n\n return resampledBuffer\n}\n\nif (Platform.OS !== 'web') {\n ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')\n}\n\nexport default ExpoAudioStreamModule\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoAudioStreamModule.js","sourceRoot":"","sources":["../src/ExpoAudioStreamModule.ts"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeModule } from 'expo-modules-core'\nimport { Platform } from 'react-native'\n\nimport {\n ExtractAudioDataOptions,\n ExtractedAudioData,\n BitDepth,\n TrimAudioOptions,\n TrimAudioResult,\n} from './ExpoAudioStream.types'\nimport {\n ExpoAudioStreamWeb,\n ExpoAudioStreamWebProps,\n} from './ExpoAudioStream.web'\nimport { processAudioBuffer } from './utils/audioProcessing'\nimport crc32 from './utils/crc32'\nimport { writeWavHeader } from './utils/writeWavHeader'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet ExpoAudioStreamModule: any\n\nif (Platform.OS === 'web') {\n let instance: ExpoAudioStreamWeb | null = null\n\n ExpoAudioStreamModule = (webProps: ExpoAudioStreamWebProps) => {\n if (!instance) {\n instance = new ExpoAudioStreamWeb(webProps)\n }\n return instance\n }\n ExpoAudioStreamModule.requestPermissionsAsync = async () => {\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n })\n stream.getTracks().forEach((track) => track.stop())\n return {\n status: 'granted',\n expires: 'never',\n canAskAgain: true,\n granted: true,\n }\n } catch {\n return {\n status: 'denied',\n expires: 'never',\n canAskAgain: true,\n granted: false,\n }\n }\n }\n ExpoAudioStreamModule.getPermissionsAsync = async () => {\n let maybeStatus: string | null = null\n\n if (navigator?.permissions?.query) {\n try {\n const { state } = await navigator.permissions.query({\n name: 'microphone' as PermissionName,\n })\n maybeStatus = state\n } catch {\n maybeStatus = null\n }\n }\n\n switch (maybeStatus) {\n case 'granted':\n return {\n status: 'granted',\n expires: 'never',\n canAskAgain: true,\n granted: true,\n }\n case 'denied':\n return {\n status: 'denied',\n expires: 'never',\n canAskAgain: true,\n granted: false,\n }\n default:\n return await ExpoAudioStreamModule.requestPermissionsAsync()\n }\n }\n ExpoAudioStreamModule.extractAudioData = async (\n options: ExtractAudioDataOptions\n ): Promise<ExtractedAudioData> => {\n try {\n const {\n fileUri,\n position,\n length,\n startTimeMs,\n endTimeMs,\n decodingOptions,\n includeNormalizedData,\n includeBase64Data,\n includeWavHeader = false,\n logger,\n } = options\n\n logger?.debug('EXTRACT AUDIO - Step 1: Initial request', {\n fileUri,\n extractionParams: {\n position,\n length,\n startTimeMs,\n endTimeMs,\n },\n decodingOptions: {\n targetSampleRate:\n decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n targetBitDepth: decodingOptions?.targetBitDepth ?? 16,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n },\n outputOptions: {\n includeNormalizedData,\n includeBase64Data,\n includeWavHeader,\n },\n })\n\n // Process the audio using shared helper function\n const processedBuffer = await processAudioBuffer({\n fileUri,\n targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,\n targetChannels: decodingOptions?.targetChannels ?? 1,\n normalizeAudio: decodingOptions?.normalizeAudio ?? false,\n position,\n length,\n startTimeMs,\n endTimeMs,\n logger,\n })\n\n logger?.debug('EXTRACT AUDIO - Step 2: Audio processing complete', {\n processedData: {\n samples: processedBuffer.samples,\n sampleRate: processedBuffer.sampleRate,\n channels: processedBuffer.channels,\n durationMs: processedBuffer.durationMs,\n },\n })\n\n const channelData = processedBuffer.channelData\n const bitDepth = (decodingOptions?.targetBitDepth ?? 16) as BitDepth\n const bytesPerSample = bitDepth / 8\n const numSamples = processedBuffer.samples\n\n logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion setup', {\n channelData: {\n length: channelData.length,\n first: channelData[0],\n last: channelData[channelData.length - 1],\n },\n calculation: {\n bitDepth,\n bytesPerSample,\n numSamples,\n expectedBytes: numSamples * bytesPerSample,\n },\n })\n\n // Create PCM data with correct length based on original byte length\n const pcmData = new Uint8Array(numSamples * bytesPerSample)\n let offset = 0\n\n // Convert Float32 samples to PCM format\n for (let i = 0; i < numSamples; i++) {\n const sample = channelData[i]\n const value = Math.max(-1, Math.min(1, sample))\n // Convert to 16-bit signed integer\n let intValue = Math.round(value * 32767)\n\n // Handle negative values correctly\n if (intValue < 0) {\n intValue = 65536 + intValue\n }\n\n // Write as little-endian\n pcmData[offset++] = intValue & 255 // Low byte\n pcmData[offset++] = (intValue >> 8) & 255 // High byte\n }\n\n const durationMs = Math.round(\n (numSamples / processedBuffer.sampleRate) * 1000\n )\n\n logger?.debug('EXTRACT AUDIO - Step 4: Final output', {\n pcmData: {\n length: pcmData.length,\n first: pcmData[0],\n last: pcmData[pcmData.length - 1],\n },\n timing: {\n numSamples,\n sampleRate: processedBuffer.sampleRate,\n durationMs,\n shouldBe3000ms: endTimeMs\n ? endTimeMs - (startTimeMs ?? 0) === 3000\n : undefined,\n },\n })\n\n const result: ExtractedAudioData = {\n pcmData: new Uint8Array(pcmData.buffer),\n sampleRate: processedBuffer.sampleRate,\n channels: processedBuffer.channels,\n bitDepth,\n durationMs,\n format: `pcm_${bitDepth}bit` as const,\n samples: numSamples,\n }\n\n // Add WAV header if requested\n if (includeWavHeader) {\n logger?.debug('EXTRACT AUDIO - Step 4: Adding WAV header', {\n originalLength: pcmData.length,\n newLength: result.pcmData.length,\n firstBytes: Array.from(result.pcmData.slice(0, 44)), // WAV header is 44 bytes\n })\n const wavBuffer = writeWavHeader({\n buffer: pcmData.buffer.slice(0, pcmData.length),\n sampleRate: processedBuffer.sampleRate,\n numChannels: processedBuffer.channels,\n bitDepth,\n })\n result.pcmData = new Uint8Array(wavBuffer)\n result.hasWavHeader = true\n }\n\n if (includeNormalizedData) {\n // // Simple approach: Create normalized data directly from the PCM data\n // // Just convert to -1 to 1 range without any amplification\n // const normalizedData = new Float32Array(numSamples)\n\n // // Convert the PCM data to float values\n // for (let i = 0; i < numSamples; i++) {\n // // Get the 16-bit PCM value (little endian)\n // const lowByte = pcmData[i * 2]\n // const highByte = pcmData[i * 2 + 1]\n // const pcmValue = (highByte << 8) | lowByte\n\n // // Convert to signed 16-bit value\n // const signedValue =\n // pcmValue > 32767 ? pcmValue - 65536 : pcmValue\n\n // // Normalize to float between -1 and 1\n // normalizedData[i] = signedValue / 32768.0\n // }\n // Store the normalized data in the result\n result.normalizedData = channelData\n }\n\n if (includeBase64Data) {\n // Convert the PCM data to a base64 string\n const binary = Array.from(new Uint8Array(pcmData.buffer))\n .map((b) => String.fromCharCode(b))\n .join('')\n result.base64Data = btoa(binary)\n }\n\n if (options.computeChecksum) {\n result.checksum = crc32.buf(pcmData)\n }\n\n logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion complete', {\n pcmStats: {\n length: pcmData.length,\n bytesPerSample,\n totalSamples: numSamples,\n firstBytes: Array.from(pcmData.slice(0, 16)),\n lastBytes: Array.from(pcmData.slice(-16)),\n },\n })\n\n return result\n } catch (error) {\n options.logger?.error('EXTRACT AUDIO - Error:', error)\n throw error\n }\n }\n\n ExpoAudioStreamModule.trimAudio = async (\n options: TrimAudioOptions\n ): Promise<TrimAudioResult> => {\n try {\n const startTime = performance.now()\n const {\n fileUri,\n mode = 'single',\n startTimeMs,\n endTimeMs,\n ranges,\n outputFileName,\n outputFormat,\n } = options\n\n // Validate inputs\n if (!fileUri) {\n throw new Error('fileUri is required')\n }\n\n if (\n mode === 'single' &&\n startTimeMs === undefined &&\n endTimeMs === undefined\n ) {\n throw new Error(\n 'At least one of startTimeMs or endTimeMs must be provided in single mode'\n )\n }\n\n if (\n (mode === 'keep' || mode === 'remove') &&\n (!ranges || ranges.length === 0)\n ) {\n throw new Error(\n 'ranges must be provided and non-empty for keep or remove modes'\n )\n }\n\n // Create AudioContext\n const audioContext = new (window.AudioContext ||\n (window as any).webkitAudioContext)()\n\n // First, load the entire audio file to get its properties\n const response = await fetch(fileUri)\n const arrayBuffer = await response.arrayBuffer()\n const originalAudioBuffer =\n await audioContext.decodeAudioData(arrayBuffer)\n\n // Get original audio properties\n const originalSampleRate = originalAudioBuffer.sampleRate\n const originalChannels = originalAudioBuffer.numberOfChannels\n\n // Add more detailed logging\n console.log(`Original audio details:`, {\n sampleRate: originalSampleRate,\n channels: originalChannels,\n duration: originalAudioBuffer.duration,\n length: originalAudioBuffer.length,\n // Log a few samples to verify content\n firstSamples: Array.from(\n originalAudioBuffer.getChannelData(0).slice(0, 5)\n ),\n })\n\n // Determine output format - use original values as defaults if not specified\n let format = outputFormat?.format || 'wav'\n const targetSampleRate =\n outputFormat?.sampleRate || originalSampleRate\n const targetChannels = outputFormat?.channels || originalChannels\n const targetBitDepth = outputFormat?.bitDepth || 16\n\n // Get file info from the URL\n const filename =\n outputFileName ||\n fileUri.split('/').pop() ||\n 'trimmed-audio.wav'\n\n // Process based on mode\n let resultBuffer: AudioBuffer\n\n // Report initial progress\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 10,\n })\n\n if (mode === 'single') {\n // Single mode: extract a single range\n // Use original sample rate and channels for extraction to preserve quality\n const { buffer } = await processAudioBuffer({\n fileUri,\n targetSampleRate, // Use the requested sample rate\n targetChannels,\n normalizeAudio: false,\n startTimeMs,\n endTimeMs,\n audioContext,\n })\n\n console.log(`Processed buffer details:`, {\n sampleRate: buffer.sampleRate,\n channels: buffer.numberOfChannels,\n duration: buffer.duration,\n length: buffer.length,\n // Log a few samples to verify content\n firstSamples: Array.from(\n buffer.getChannelData(0).slice(0, 5)\n ),\n })\n\n resultBuffer = buffer\n\n // If we need to change sample rate or channels, do it after extraction\n if (\n targetSampleRate !== originalSampleRate ||\n targetChannels !== originalChannels\n ) {\n console.log(\n `Resampling from ${originalSampleRate}Hz to ${targetSampleRate}Hz`\n )\n resultBuffer = await resampleAudioBuffer(\n audioContext,\n buffer,\n targetSampleRate,\n targetChannels\n )\n }\n } else {\n // For keep or remove modes\n const fullDuration = originalAudioBuffer.duration * 1000 // in ms\n\n type ProcessSegment = {\n startTimeMs: number\n endTimeMs: number\n }\n\n let segmentsToProcess: ProcessSegment[] = []\n\n if (mode === 'keep') {\n // For keep mode, use the ranges directly\n segmentsToProcess = ranges!\n } else {\n // mode === 'remove'\n // For remove mode, invert the ranges\n const sortedRanges = [...ranges!].sort(\n (a, b) => a.startTimeMs - b.startTimeMs\n )\n\n // Add segment from start to first range if needed\n if (\n sortedRanges.length > 0 &&\n sortedRanges[0].startTimeMs > 0\n ) {\n segmentsToProcess.push({\n startTimeMs: 0,\n endTimeMs: sortedRanges[0].startTimeMs,\n })\n }\n\n // Add segments between ranges\n for (let i = 0; i < sortedRanges.length - 1; i++) {\n segmentsToProcess.push({\n startTimeMs: sortedRanges[i].endTimeMs,\n endTimeMs: sortedRanges[i + 1].startTimeMs,\n })\n }\n\n // Add segment from last range to end if needed\n if (\n sortedRanges.length > 0 &&\n sortedRanges[sortedRanges.length - 1].endTimeMs <\n fullDuration\n ) {\n segmentsToProcess.push({\n startTimeMs:\n sortedRanges[sortedRanges.length - 1].endTimeMs,\n endTimeMs: fullDuration,\n })\n }\n }\n\n // Filter out empty or invalid segments\n segmentsToProcess = segmentsToProcess.filter(\n (segment) =>\n segment.startTimeMs < segment.endTimeMs &&\n segment.endTimeMs - segment.startTimeMs > 1\n ) // 1ms minimum\n\n if (segmentsToProcess.length === 0) {\n throw new Error(\n 'No valid segments to process after filtering ranges'\n )\n }\n\n // Process each segment using original sample rate and channels\n const segmentBuffers: AudioBuffer[] = []\n\n for (let i = 0; i < segmentsToProcess.length; i++) {\n const segment = segmentsToProcess[i]\n\n // Report progress for each segment\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress:\n 10 +\n Math.round((i / segmentsToProcess.length) * 40),\n })\n\n // Use processAudioBuffer to extract this segment\n const { buffer: segmentBuffer } = await processAudioBuffer({\n fileUri,\n targetSampleRate: originalSampleRate, // Use original sample rate\n targetChannels: originalChannels, // Use original channels\n normalizeAudio: false,\n startTimeMs: segment.startTimeMs,\n endTimeMs: segment.endTimeMs,\n audioContext,\n })\n\n segmentBuffers.push(segmentBuffer)\n }\n\n // Concatenate all segments\n const totalSamples = segmentBuffers.reduce(\n (sum, buffer) => sum + buffer.length,\n 0\n )\n\n // Create buffer with original properties first\n const concatenatedBuffer = audioContext.createBuffer(\n originalChannels,\n totalSamples,\n originalSampleRate\n )\n\n let offset = 0\n for (const segmentBuffer of segmentBuffers) {\n for (\n let channel = 0;\n channel < originalChannels;\n channel++\n ) {\n const outputData =\n concatenatedBuffer.getChannelData(channel)\n const segmentData =\n segmentBuffer.getChannelData(channel)\n\n for (let i = 0; i < segmentBuffer.length; i++) {\n outputData[offset + i] = segmentData[i]\n }\n }\n offset += segmentBuffer.length\n }\n\n resultBuffer = concatenatedBuffer\n\n // If we need to change sample rate or channels, do it after concatenation\n if (\n targetSampleRate !== originalSampleRate ||\n targetChannels !== originalChannels\n ) {\n console.log(\n `Resampling concatenated buffer from ${originalSampleRate}Hz to ${targetSampleRate}Hz`\n )\n resultBuffer = await resampleAudioBuffer(\n audioContext,\n concatenatedBuffer,\n targetSampleRate,\n targetChannels\n )\n }\n }\n\n // Report progress (50% - processing complete)\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 50,\n })\n\n // Encode the result based on the requested format\n let outputData: ArrayBuffer\n let outputMimeType: string\n let compressionInfo: any = null\n\n // Check if AAC was requested on web and show a warning\n if (format === 'aac' && Platform.OS === 'web') {\n console.warn(\n 'AAC format is not supported on web platforms. Falling back to OPUS format.'\n )\n format = 'opus'\n }\n\n if (format === 'wav') {\n // Create a properly interleaved buffer for WAV format\n // For WAV, we need to convert Float32Array to Int16Array (for 16-bit audio)\n const numSamples =\n resultBuffer.length * resultBuffer.numberOfChannels\n const interleavedData = new Int16Array(numSamples)\n\n // Log detailed information about the buffer before encoding\n console.log(`Creating WAV file:`, {\n bufferSampleRate: resultBuffer.sampleRate,\n bufferChannels: resultBuffer.numberOfChannels,\n bufferLength: resultBuffer.length,\n targetSampleRate,\n targetChannels,\n targetBitDepth,\n // Log a few samples to verify content\n firstSamples: Array.from(\n resultBuffer.getChannelData(0).slice(0, 5)\n ),\n })\n\n // Interleave channels properly\n for (let i = 0; i < resultBuffer.length; i++) {\n for (\n let channel = 0;\n channel < resultBuffer.numberOfChannels;\n channel++\n ) {\n // Convert float (-1.0 to 1.0) to int16 (-32768 to 32767)\n const floatSample =\n resultBuffer.getChannelData(channel)[i]\n // Clamp the value to -1.0 to 1.0\n const clampedSample = Math.max(\n -1.0,\n Math.min(1.0, floatSample)\n )\n // Convert to int16\n const intSample = Math.round(clampedSample * 32767)\n // Store in interleaved buffer\n interleavedData[\n i * resultBuffer.numberOfChannels + channel\n ] = intSample\n }\n }\n\n // Convert Int16Array to ArrayBuffer for WAV header\n const rawBuffer = interleavedData.buffer\n\n // IMPORTANT: Make sure we're using the ACTUAL sample rate of the buffer\n // not just what was requested in the options\n console.log(\n `Creating WAV with ${resultBuffer.numberOfChannels} channels at ${resultBuffer.sampleRate}Hz`\n )\n\n outputData = writeWavHeader({\n buffer: rawBuffer as ArrayBuffer,\n sampleRate: resultBuffer.sampleRate, // Use the actual buffer's sample rate\n numChannels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth as BitDepth,\n })\n outputMimeType = 'audio/wav'\n } else if (format === 'opus' || format === 'aac') {\n try {\n // Try to use MediaRecorder for compressed formats\n const { data, bitrate } = await encodeCompressedAudio(\n resultBuffer,\n format,\n outputFormat?.bitrate\n )\n\n outputData = data\n outputMimeType =\n format === 'opus' ? 'audio/webm' : 'audio/aac'\n compressionInfo = {\n format,\n bitrate,\n size: data.byteLength,\n }\n } catch (error) {\n console.warn(\n `Failed to encode to ${format}, falling back to WAV: ${error}`\n )\n\n // Same WAV encoding as above\n const wavData = new Float32Array(\n resultBuffer.length * resultBuffer.numberOfChannels\n )\n\n for (let i = 0; i < resultBuffer.length; i++) {\n for (\n let channel = 0;\n channel < resultBuffer.numberOfChannels;\n channel++\n ) {\n wavData[\n i * resultBuffer.numberOfChannels + channel\n ] = resultBuffer.getChannelData(channel)[i]\n }\n }\n\n outputData = writeWavHeader({\n buffer: wavData.buffer as ArrayBuffer,\n sampleRate: resultBuffer.sampleRate,\n numChannels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth as BitDepth,\n })\n outputMimeType = 'audio/wav'\n }\n } else {\n // Default to WAV for unsupported formats\n console.warn(\n `Format ${format} not supported on web, using WAV instead`\n )\n\n // Same WAV encoding as above\n const wavData = new Float32Array(\n resultBuffer.length * resultBuffer.numberOfChannels\n )\n\n for (let i = 0; i < resultBuffer.length; i++) {\n for (\n let channel = 0;\n channel < resultBuffer.numberOfChannels;\n channel++\n ) {\n wavData[i * resultBuffer.numberOfChannels + channel] =\n resultBuffer.getChannelData(channel)[i]\n }\n }\n\n outputData = writeWavHeader({\n buffer: wavData.buffer as ArrayBuffer,\n sampleRate: resultBuffer.sampleRate,\n numChannels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth as BitDepth,\n })\n outputMimeType = 'audio/wav'\n }\n\n // Report progress (90% - encoding complete)\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 90,\n })\n\n // Create a blob and URL for the result\n const blob = new Blob([outputData], { type: outputMimeType })\n const outputUri = URL.createObjectURL(blob)\n\n // Calculate processing time\n const processingTimeMs = performance.now() - startTime\n\n // Report progress (100% - complete)\n ExpoAudioStreamModule.sendEvent('TrimProgress', {\n progress: 100,\n })\n\n // Create result object\n const result: TrimAudioResult = {\n uri: outputUri,\n filename,\n durationMs: Math.round(resultBuffer.duration * 1000),\n size: outputData.byteLength,\n sampleRate: resultBuffer.sampleRate,\n channels: resultBuffer.numberOfChannels,\n bitDepth: targetBitDepth,\n mimeType: outputMimeType,\n processingInfo: {\n durationMs: processingTimeMs,\n },\n }\n\n // Add compression info if available\n if (compressionInfo) {\n result.compression = compressionInfo\n }\n\n return result\n } catch (error) {\n console.error('Error in trimAudio:', error)\n throw error\n }\n }\n\n // Add a sendEvent method for web\n ExpoAudioStreamModule.sendEvent = (eventName: string, params: any) => {\n // This will be picked up by the LegacyEventEmitter in trimAudio.ts\n if (\n ExpoAudioStreamModule.listeners &&\n ExpoAudioStreamModule.listeners[eventName]\n ) {\n ExpoAudioStreamModule.listeners[eventName].forEach(\n (listener: Function) => {\n listener(params)\n }\n )\n }\n }\n\n // Initialize listeners object\n ExpoAudioStreamModule.listeners = {}\n\n // Add methods for event listeners that LegacyEventEmitter will use\n ExpoAudioStreamModule.addListener = (\n eventName: string,\n listener: Function\n ) => {\n if (!ExpoAudioStreamModule.listeners[eventName]) {\n ExpoAudioStreamModule.listeners[eventName] = []\n }\n ExpoAudioStreamModule.listeners[eventName].push(listener)\n\n // Return an object with a remove method\n return {\n remove: () => {\n const index =\n ExpoAudioStreamModule.listeners[eventName].indexOf(listener)\n if (index !== -1) {\n ExpoAudioStreamModule.listeners[eventName].splice(index, 1)\n }\n },\n }\n }\n\n ExpoAudioStreamModule.removeAllListeners = (eventName: string) => {\n if (ExpoAudioStreamModule.listeners[eventName]) {\n delete ExpoAudioStreamModule.listeners[eventName]\n }\n }\n\n ExpoAudioStreamModule.prepareRecording = async (options: any) => {\n // For web platform, we'll implement a simplified version that just checks permissions\n // and does minimal setup. The actual recording setup will still happen in startRecording.\n try {\n // Check for microphone permissions\n const permissionsResult =\n await ExpoAudioStreamModule.getPermissionsAsync()\n if (!permissionsResult.granted) {\n throw new Error('Microphone permission not granted')\n }\n\n // If using a web instance, call its prepareRecording method\n if (instance) {\n return await instance.prepareRecording(options)\n }\n\n return true\n } catch (error) {\n console.error('Error preparing recording:', error)\n throw error\n }\n }\n}\n\n// Move the encodeCompressedAudio function outside the if block to fix the ESLint error\nasync function encodeCompressedAudio(\n buffer: AudioBuffer,\n format: 'opus' | 'aac',\n bitrate?: number\n): Promise<{ data: ArrayBuffer; bitrate: number }> {\n return new Promise((resolve, reject) => {\n try {\n // On web, always use opus if aac is requested\n const actualFormat =\n Platform.OS === 'web' && format === 'aac' ? 'opus' : format\n\n // Check if MediaRecorder supports the requested format\n const mimeType =\n actualFormat === 'opus' ? 'audio/webm;codecs=opus' : 'audio/aac'\n if (!MediaRecorder.isTypeSupported(mimeType)) {\n throw new Error(`MediaRecorder does not support ${mimeType}`)\n }\n\n // Create a new AudioContext and source\n const ctx = new (window.AudioContext ||\n (window as any).webkitAudioContext)()\n const source = ctx.createBufferSource()\n source.buffer = buffer\n\n // Create a MediaStreamDestination to capture the audio\n const destination = ctx.createMediaStreamDestination()\n source.connect(destination)\n\n // Create a MediaRecorder with the requested format\n const recorder = new MediaRecorder(destination.stream, {\n mimeType,\n audioBitsPerSecond:\n bitrate || (actualFormat === 'opus' ? 32000 : 64000),\n })\n\n const chunks: Blob[] = []\n\n recorder.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunks.push(e.data)\n }\n }\n\n recorder.onstop = async () => {\n try {\n const blob = new Blob(chunks, { type: mimeType })\n const arrayBuffer = await blob.arrayBuffer()\n\n // Get the actual bitrate used\n const actualBitrate = Math.round(\n (arrayBuffer.byteLength * 8) / buffer.duration\n )\n\n resolve({\n data: arrayBuffer,\n bitrate: actualBitrate / 1000, // Convert to kbps\n })\n\n // Clean up\n ctx.close()\n } catch (error) {\n reject(error)\n }\n }\n\n // Start recording and playback\n recorder.start()\n source.start(0)\n\n // Stop recording when the buffer finishes playing\n setTimeout(() => {\n recorder.stop()\n source.stop()\n }, buffer.duration * 1000)\n } catch (error) {\n reject(error)\n }\n })\n}\n\n// Improved resampleAudioBuffer function\nasync function resampleAudioBuffer(\n context: AudioContext,\n buffer: AudioBuffer,\n targetSampleRate: number,\n targetChannels: number\n): Promise<AudioBuffer> {\n // If no change needed, return the original buffer\n if (\n buffer.sampleRate === targetSampleRate &&\n buffer.numberOfChannels === targetChannels\n ) {\n return buffer\n }\n\n console.log(\n `Resampling: ${buffer.sampleRate}Hz → ${targetSampleRate}Hz, ${buffer.numberOfChannels} → ${targetChannels} channels`\n )\n\n // Calculate the new length based on the sample rate change\n const newLength = Math.round(\n (buffer.length * targetSampleRate) / buffer.sampleRate\n )\n\n // Create an offline context for resampling\n const offlineContext = new OfflineAudioContext(\n targetChannels,\n newLength,\n targetSampleRate\n )\n\n // Create a source node\n const source = offlineContext.createBufferSource()\n source.buffer = buffer\n\n // If we need to change channel count\n if (buffer.numberOfChannels !== targetChannels) {\n if (targetChannels === 1 && buffer.numberOfChannels > 1) {\n // Downmix to mono\n const merger = offlineContext.createChannelMerger(1)\n\n // Create a gain node to reduce volume when downmixing to prevent clipping\n const gainNode = offlineContext.createGain()\n gainNode.gain.value = 1.0 / buffer.numberOfChannels\n\n source.connect(gainNode)\n gainNode.connect(merger)\n merger.connect(offlineContext.destination)\n } else if (targetChannels === 2 && buffer.numberOfChannels === 1) {\n // Upmix mono to stereo (duplicate the channel)\n const splitter = offlineContext.createChannelSplitter(1)\n const merger = offlineContext.createChannelMerger(2)\n\n source.connect(splitter)\n splitter.connect(merger, 0, 0)\n splitter.connect(merger, 0, 1)\n merger.connect(offlineContext.destination)\n } else {\n // For other cases, just connect and let the system handle it\n source.connect(offlineContext.destination)\n }\n } else {\n // No channel conversion needed\n source.connect(offlineContext.destination)\n }\n\n // Start rendering\n source.start(0)\n const resampledBuffer = await offlineContext.startRendering()\n\n console.log(\n `Resampling complete: ${resampledBuffer.length} samples at ${resampledBuffer.sampleRate}Hz`\n )\n\n return resampledBuffer\n}\n\nif (Platform.OS !== 'web') {\n ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream')\n}\n\nexport default ExpoAudioStreamModule\n"]}
|