@siteed/expo-audio-stream 1.3.0 → 1.4.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 (87) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/android/build/.transforms/0588d516016bbd2e5b51abc80cc3d78d/transformed/classes/classes_dex/classes.dex +0 -0
  3. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  4. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  5. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  6. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  7. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  8. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  9. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  10. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  11. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  12. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  13. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  14. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  15. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  16. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  17. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  18. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  19. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  20. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  21. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  22. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  23. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
  24. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  25. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  26. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  27. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  28. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  29. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  30. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  31. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  32. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  33. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  34. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  35. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  36. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s +1 -0
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  41. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  42. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  43. package/android/build.gradle +13 -5
  44. package/build/AudioAnalysis/extractAudioAnalysis.d.ts +3 -1
  45. package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -1
  46. package/build/AudioAnalysis/extractAudioAnalysis.js +9 -11
  47. package/build/AudioAnalysis/extractAudioAnalysis.js.map +1 -1
  48. package/build/AudioAnalysis/extractWaveform.d.ts.map +1 -1
  49. package/build/AudioAnalysis/extractWaveform.js +0 -3
  50. package/build/AudioAnalysis/extractWaveform.js.map +1 -1
  51. package/build/ExpoAudioStream.types.d.ts +6 -0
  52. package/build/ExpoAudioStream.types.d.ts.map +1 -1
  53. package/build/ExpoAudioStream.types.js.map +1 -1
  54. package/build/ExpoAudioStream.web.d.ts +4 -2
  55. package/build/ExpoAudioStream.web.d.ts.map +1 -1
  56. package/build/ExpoAudioStream.web.js +6 -6
  57. package/build/ExpoAudioStream.web.js.map +1 -1
  58. package/build/WebRecorder.web.d.ts +4 -2
  59. package/build/WebRecorder.web.d.ts.map +1 -1
  60. package/build/WebRecorder.web.js +14 -13
  61. package/build/WebRecorder.web.js.map +1 -1
  62. package/build/events.d.ts.map +1 -1
  63. package/build/events.js +0 -4
  64. package/build/events.js.map +1 -1
  65. package/build/useAudioRecorder.d.ts +3 -3
  66. package/build/useAudioRecorder.d.ts.map +1 -1
  67. package/build/useAudioRecorder.js +26 -28
  68. package/build/useAudioRecorder.js.map +1 -1
  69. package/build/utils/convertPCMToFloat32.d.ts +3 -1
  70. package/build/utils/convertPCMToFloat32.d.ts.map +1 -1
  71. package/build/utils/convertPCMToFloat32.js +3 -5
  72. package/build/utils/convertPCMToFloat32.js.map +1 -1
  73. package/package.json +1 -3
  74. package/plugin/src/index.ts +5 -4
  75. package/src/AudioAnalysis/extractAudioAnalysis.ts +13 -13
  76. package/src/AudioAnalysis/extractWaveform.ts +0 -3
  77. package/src/ExpoAudioStream.types.ts +7 -0
  78. package/src/ExpoAudioStream.web.ts +8 -6
  79. package/src/WebRecorder.web.ts +15 -14
  80. package/src/events.ts +0 -4
  81. package/src/useAudioRecorder.tsx +32 -36
  82. package/src/utils/convertPCMToFloat32.ts +5 -5
  83. package/build/logger.d.ts +0 -9
  84. package/build/logger.d.ts.map +0 -1
  85. package/build/logger.js +0 -13
  86. package/build/logger.js.map +0 -1
  87. package/src/logger.ts +0 -22
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioRecorder.js","sourceRoot":"","sources":["../src/useAudioRecorder.tsx"],"names":[],"mappings":"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","sourcesContent":["// src/useAudioRecorder.ts\nimport { Platform, EventSubscription } from 'expo-modules-core'\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioDataEvent,\n AudioRecording,\n AudioStreamStatus,\n RecordingConfig,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport ExpoAudioStreamModule from './ExpoAudioStreamModule'\nimport {\n addAudioAnalysisListener,\n addAudioEventListener,\n AudioEventPayload,\n} from './events'\nimport { getLogger } from './logger'\n\nconst TAG = 'useAudioRecorder'\nconst logger = getLogger(TAG)\nexport interface UseAudioRecorderProps {\n debug?: boolean\n audioWorkletUrl?: string\n featuresExtratorUrl?: string\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording>\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 analysisData?: AudioAnalysis\n}\n\ninterface RecorderReducerState {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n analysisData?: AudioAnalysis\n}\n\ntype RecorderAction =\n | { type: 'START' | 'STOP' | 'PAUSE' | 'RESUME' }\n | {\n type: 'UPDATE_RECORDING_STATE'\n payload: {\n isRecording: boolean\n isPaused: boolean\n }\n }\n | { type: 'UPDATE_STATUS'; payload: { durationMs: number; size: number } }\n | { type: 'UPDATE_ANALYSIS'; payload: AudioAnalysis }\n\nconst defaultAnalysis: AudioAnalysis = {\n pointsPerSecond: 10,\n bitDepth: 32,\n numberOfChannels: 1,\n durationMs: 0,\n sampleRate: 44100,\n samples: 0,\n dataPoints: [],\n amplitudeAlgorithm: 'rms',\n speakerChanges: [],\n amplitudeRange: {\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY,\n },\n}\n\nfunction audioRecorderReducer(\n state: RecorderReducerState,\n action: RecorderAction\n): RecorderReducerState {\n switch (action.type) {\n case 'START':\n return {\n ...state,\n isRecording: true,\n isPaused: false,\n durationMs: 0,\n size: 0,\n analysisData: defaultAnalysis, // Reset analysis data\n }\n case 'STOP':\n return { ...state, isRecording: false, isPaused: false }\n case 'PAUSE':\n return { ...state, isPaused: true, isRecording: false }\n case 'RESUME':\n return { ...state, isPaused: false, isRecording: true }\n case 'UPDATE_RECORDING_STATE':\n return {\n ...state,\n isPaused: action.payload.isPaused,\n isRecording: action.payload.isRecording,\n }\n case 'UPDATE_STATUS':\n return {\n ...state,\n durationMs: action.payload.durationMs,\n size: action.payload.size,\n }\n case 'UPDATE_ANALYSIS':\n return {\n ...state,\n analysisData: action.payload,\n }\n default:\n return state\n }\n}\n\ninterface HandleAudioAnalysisProps {\n analysis: AudioAnalysis\n visualizationDuration: number\n}\n\nexport function useAudioRecorder({\n debug = false,\n audioWorkletUrl,\n featuresExtratorUrl,\n}: UseAudioRecorderProps = {}): UseAudioRecorderState {\n const [state, dispatch] = useReducer(audioRecorderReducer, {\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n analysisData: undefined,\n })\n\n const analysisListenerRef = useRef<EventSubscription | null>(null)\n // analysisRef is the current analysis data (last 10 seconds by default)\n const analysisRef = useRef<AudioAnalysis>({ ...defaultAnalysis })\n // fullAnalysisRef is the full analysis data (all data points)\n const fullAnalysisRef = useRef<AudioAnalysis>({\n ...defaultAnalysis,\n })\n const globalIdRef = useRef(0);\n\n // Instantiate the module for web with URLs\n const ExpoAudioStream =\n Platform.OS === 'web'\n ? ExpoAudioStreamModule({ audioWorkletUrl, featuresExtratorUrl })\n : ExpoAudioStreamModule\n\n const onAudioStreamRef = useRef<\n ((_: AudioDataEvent) => Promise<void>) | null\n >(null)\n\n const handleAudioAnalysis = useCallback(\n async ({\n analysis,\n visualizationDuration,\n }: HandleAudioAnalysisProps) => {\n const savedAnalysisData = analysisRef.current || {\n ...defaultAnalysis,\n }\n\n const maxDuration = visualizationDuration\n\n logger.debug(\n `[handleAudioAnalysis] Received audio analysis: maxDuration=${maxDuration} analysis.dataPoints=${analysis.dataPoints.length} analysisData.dataPoints=${savedAnalysisData.dataPoints.length}`,\n analysis\n )\n\n // Combine data points\n const combinedDataPoints = [\n ...savedAnalysisData.dataPoints,\n ...analysis.dataPoints,\n ]\n\n const fullCombinedDataPoints = [\n ...(fullAnalysisRef.current?.dataPoints ?? []),\n ...analysis.dataPoints,\n ]\n\n // Calculate the new duration\n const pointsPerSecond =\n analysis.pointsPerSecond || savedAnalysisData.pointsPerSecond\n const maxDataPoints =\n (pointsPerSecond * visualizationDuration) / 1000\n\n logger.debug(\n `[handleAudioAnalysis] Combined data points before trimming: pointsPerSecond=${pointsPerSecond} visualizationDuration=${visualizationDuration} combinedDataPointsLength=${combinedDataPoints.length} vs maxDataPoints=${maxDataPoints}`\n )\n\n // Trim data points to keep within the maximum number of data points\n if (combinedDataPoints.length > maxDataPoints) {\n combinedDataPoints.splice(\n 0,\n combinedDataPoints.length - maxDataPoints\n )\n }\n\n // Keep the full data points\n fullAnalysisRef.current = {\n ...fullAnalysisRef.current,\n dataPoints: fullCombinedDataPoints,\n }\n fullAnalysisRef.current.durationMs =\n fullCombinedDataPoints.length * (1000 / pointsPerSecond)\n savedAnalysisData.dataPoints = combinedDataPoints\n savedAnalysisData.bitDepth =\n analysis.bitDepth || savedAnalysisData.bitDepth\n savedAnalysisData.durationMs =\n combinedDataPoints.length * (1000 / pointsPerSecond)\n\n // Update amplitude range\n const newMin = Math.min(\n savedAnalysisData.amplitudeRange.min,\n analysis.amplitudeRange.min\n )\n const newMax = Math.max(\n savedAnalysisData.amplitudeRange.max,\n analysis.amplitudeRange.max\n )\n\n savedAnalysisData.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n fullAnalysisRef.current.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n\n logger.debug(\n `[handleAudioAnalysis] Updated analysis data: durationMs=${savedAnalysisData.durationMs}`,\n savedAnalysisData\n )\n\n // Update the ref\n analysisRef.current = savedAnalysisData\n\n // Dispatch the updated analysis data to state to trigger re-render\n // need to use spread operator otherwise it doesnt trigger update.\n dispatch({\n type: 'UPDATE_ANALYSIS',\n payload: { ...savedAnalysisData },\n })\n },\n [dispatch]\n )\n\n const handleAudioEvent = useCallback(\n async (eventData: AudioEventPayload) => {\n const {\n fileUri,\n deltaSize,\n totalSize,\n lastEmittedSize,\n position,\n streamUuid,\n encoded,\n mimeType,\n buffer,\n } = eventData\n logger.debug(`[handleAudioEvent] Received audio event:`, {\n fileUri,\n deltaSize,\n totalSize,\n position,\n mimeType,\n lastEmittedSize,\n streamUuid,\n encodedLength: encoded?.length,\n })\n if (deltaSize === 0) {\n // Ignore packet with no data\n return\n }\n try {\n // Coming from native ( ios / android ) otherwise buffer is set\n if (Platform.OS !== 'web') {\n // Read the audio file as a base64 string for comparison\n if (!encoded) {\n console.error(`${TAG} Encoded audio data is missing`)\n throw new Error('Encoded audio data is missing')\n }\n onAudioStreamRef.current?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n })\n } else if (buffer) {\n // Coming from web\n const webEvent: AudioDataEvent = {\n data: buffer,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n }\n onAudioStreamRef.current?.(webEvent)\n logger.debug(\n `[handleAudioEvent] Audio data sent to onAudioStream`,\n webEvent\n )\n }\n } catch (error) {\n console.error(`${TAG} Error processing audio event:`, error)\n }\n },\n []\n )\n\n const checkStatus = useCallback(async () => {\n try {\n const status: AudioStreamStatus = ExpoAudioStream.status()\n if (debug) {\n logger.debug(\n `Status: paused: ${status.isPaused} durationMs: ${status.durationMs} size: ${status.size}`\n )\n }\n\n // Check and update recording state\n if (\n status.isRecording !== state.isRecording ||\n status.isPaused !== state.isPaused\n ) {\n dispatch({\n type: 'UPDATE_RECORDING_STATE',\n payload: {\n isRecording: status.isRecording,\n isPaused: status.isPaused,\n },\n })\n }\n\n // Check and update recording progress\n if (\n status.durationMs !== state.durationMs ||\n status.size !== state.size\n ) {\n dispatch({\n type: 'UPDATE_STATUS',\n payload: {\n durationMs: status.durationMs,\n size: status.size,\n },\n })\n }\n } catch (error) {\n console.error(`${TAG} Error getting status:`, error)\n }\n }, [state.isRecording])\n\n const startRecording = useCallback(\n async (recordingOptions: RecordingConfig) => {\n logger.debug(`start recoding`, recordingOptions)\n\n analysisRef.current = { ...defaultAnalysis } // Reset analysis data\n fullAnalysisRef.current = { ...defaultAnalysis }\n const { onAudioStream, ...options } = recordingOptions\n const { enableProcessing } = options\n\n const maxRecentDataDuration = 10000 // TODO compute maxRecentDataDuration based on screen dimensions\n if (typeof onAudioStream === 'function') {\n onAudioStreamRef.current = onAudioStream\n } else {\n console.warn(\n `${TAG} onAudioStream is not a function`,\n onAudioStream\n )\n onAudioStreamRef.current = null\n }\n const startResult: StartRecordingResult =\n await ExpoAudioStream.startRecording(options)\n dispatch({ type: 'START' })\n\n if (enableProcessing) {\n logger.debug(`Enabling audio analysis listener`)\n const listener = addAudioAnalysisListener(\n async (analysisData) => {\n try {\n await handleAudioAnalysis({\n analysis: analysisData,\n visualizationDuration: maxRecentDataDuration,\n })\n } catch (error) {\n console.warn(\n `${TAG} Error processing audio analysis:`,\n error\n )\n }\n }\n )\n\n analysisListenerRef.current = listener\n }\n\n return startResult\n },\n [handleAudioAnalysis, dispatch]\n )\n\n const stopRecording = useCallback(async () => {\n logger.debug(`stoping recording`)\n\n const stopResult: AudioRecording = await ExpoAudioStream.stopRecording()\n stopResult.analysisData = fullAnalysisRef.current\n\n if (analysisListenerRef.current) {\n analysisListenerRef.current.remove()\n analysisListenerRef.current = null\n }\n onAudioStreamRef.current = null\n logger.debug(`recording stopped`, stopResult)\n dispatch({ type: 'STOP' })\n return stopResult\n }, [dispatch])\n\n const pauseRecording = useCallback(async () => {\n logger.debug(`pause recording`)\n const pauseResult = await ExpoAudioStream.pauseRecording()\n dispatch({ type: 'PAUSE' })\n return pauseResult\n }, [dispatch])\n\n const resumeRecording = useCallback(async () => {\n logger.debug(`resume recording`)\n const resumeResult = await ExpoAudioStream.resumeRecording()\n dispatch({ type: 'RESUME' })\n return resumeResult\n }, [dispatch])\n\n useEffect(() => {\n let interval: ReturnType<typeof setTimeout>\n if (state.isRecording || state.isPaused) {\n interval = setInterval(checkStatus, 1000)\n }\n return () => {\n if (interval) {\n clearInterval(interval)\n }\n }\n }, [checkStatus, state.isRecording, state.isPaused])\n\n useEffect(() => {\n logger.debug(`Registering audio event listener`)\n const subscribeAudio = addAudioEventListener(handleAudioEvent)\n\n logger.debug(\n `Subscribed to audio event listener and analysis listener`,\n {\n subscribeAudio,\n }\n )\n\n return () => {\n logger.debug(`Removing audio event listener`)\n subscribeAudio.remove()\n }\n }, [handleAudioEvent, handleAudioAnalysis])\n\n return {\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n isPaused: state.isPaused,\n isRecording: state.isRecording,\n durationMs: state.durationMs,\n size: state.size,\n analysisData: state.analysisData,\n }\n}\n"]}
1
+ {"version":3,"file":"useAudioRecorder.js","sourceRoot":"","sources":["../src/useAudioRecorder.tsx"],"names":[],"mappings":"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","sourcesContent":["// src/useAudioRecorder.ts\nimport { EventSubscription, Platform } from 'expo-modules-core'\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\nimport { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'\nimport {\n AudioDataEvent,\n AudioRecording,\n AudioStreamStatus,\n ConsoleLike,\n RecordingConfig,\n StartRecordingResult,\n} from './ExpoAudioStream.types'\nimport ExpoAudioStreamModule from './ExpoAudioStreamModule'\nimport {\n addAudioAnalysisListener,\n addAudioEventListener,\n AudioEventPayload,\n} from './events'\n\nexport interface UseAudioRecorderProps {\n logger?: ConsoleLike\n audioWorkletUrl?: string\n featuresExtratorUrl?: string\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording>\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 analysisData?: AudioAnalysis\n}\n\ninterface RecorderReducerState {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n analysisData?: AudioAnalysis\n}\n\ntype RecorderAction =\n | { type: 'START' | 'STOP' | 'PAUSE' | 'RESUME' }\n | {\n type: 'UPDATE_RECORDING_STATE'\n payload: {\n isRecording: boolean\n isPaused: boolean\n }\n }\n | { type: 'UPDATE_STATUS'; payload: { durationMs: number; size: number } }\n | { type: 'UPDATE_ANALYSIS'; payload: AudioAnalysis }\n\nconst defaultAnalysis: AudioAnalysis = {\n pointsPerSecond: 10,\n bitDepth: 32,\n numberOfChannels: 1,\n durationMs: 0,\n sampleRate: 44100,\n samples: 0,\n dataPoints: [],\n amplitudeAlgorithm: 'rms',\n speakerChanges: [],\n amplitudeRange: {\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY,\n },\n}\n\nfunction audioRecorderReducer(\n state: RecorderReducerState,\n action: RecorderAction\n): RecorderReducerState {\n switch (action.type) {\n case 'START':\n return {\n ...state,\n isRecording: true,\n isPaused: false,\n durationMs: 0,\n size: 0,\n analysisData: defaultAnalysis, // Reset analysis data\n }\n case 'STOP':\n return { ...state, isRecording: false, isPaused: false }\n case 'PAUSE':\n return { ...state, isPaused: true, isRecording: false }\n case 'RESUME':\n return { ...state, isPaused: false, isRecording: true }\n case 'UPDATE_RECORDING_STATE':\n return {\n ...state,\n isPaused: action.payload.isPaused,\n isRecording: action.payload.isRecording,\n }\n case 'UPDATE_STATUS':\n return {\n ...state,\n durationMs: action.payload.durationMs,\n size: action.payload.size,\n }\n case 'UPDATE_ANALYSIS':\n return {\n ...state,\n analysisData: action.payload,\n }\n default:\n return state\n }\n}\n\ninterface HandleAudioAnalysisProps {\n analysis: AudioAnalysis\n visualizationDuration: number\n}\n\nexport function useAudioRecorder({\n logger,\n audioWorkletUrl,\n featuresExtratorUrl,\n}: UseAudioRecorderProps = {}): UseAudioRecorderState {\n const [state, dispatch] = useReducer(audioRecorderReducer, {\n isRecording: false,\n isPaused: false,\n durationMs: 0,\n size: 0,\n analysisData: undefined,\n })\n\n const analysisListenerRef = useRef<EventSubscription | null>(null)\n // analysisRef is the current analysis data (last 10 seconds by default)\n const analysisRef = useRef<AudioAnalysis>({ ...defaultAnalysis })\n // fullAnalysisRef is the full analysis data (all data points)\n const fullAnalysisRef = useRef<AudioAnalysis>({\n ...defaultAnalysis,\n })\n\n // Instantiate the module for web with URLs\n const ExpoAudioStream =\n Platform.OS === 'web'\n ? ExpoAudioStreamModule({\n audioWorkletUrl,\n featuresExtratorUrl,\n logger,\n })\n : ExpoAudioStreamModule\n\n const onAudioStreamRef = useRef<\n ((_: AudioDataEvent) => Promise<void>) | null\n >(null)\n\n const handleAudioAnalysis = useCallback(\n async ({\n analysis,\n visualizationDuration,\n }: HandleAudioAnalysisProps) => {\n const savedAnalysisData = analysisRef.current || {\n ...defaultAnalysis,\n }\n\n const maxDuration = visualizationDuration\n\n logger?.debug(\n `[handleAudioAnalysis] Received audio analysis: maxDuration=${maxDuration} analysis.dataPoints=${analysis.dataPoints.length} analysisData.dataPoints=${savedAnalysisData.dataPoints.length}`,\n analysis\n )\n\n // Combine data points\n const combinedDataPoints = [\n ...savedAnalysisData.dataPoints,\n ...analysis.dataPoints,\n ]\n\n const fullCombinedDataPoints = [\n ...(fullAnalysisRef.current?.dataPoints ?? []),\n ...analysis.dataPoints,\n ]\n\n // Calculate the new duration\n const pointsPerSecond =\n analysis.pointsPerSecond || savedAnalysisData.pointsPerSecond\n const maxDataPoints =\n (pointsPerSecond * visualizationDuration) / 1000\n\n logger?.debug(\n `[handleAudioAnalysis] Combined data points before trimming: pointsPerSecond=${pointsPerSecond} visualizationDuration=${visualizationDuration} combinedDataPointsLength=${combinedDataPoints.length} vs maxDataPoints=${maxDataPoints}`\n )\n\n // Trim data points to keep within the maximum number of data points\n if (combinedDataPoints.length > maxDataPoints) {\n combinedDataPoints.splice(\n 0,\n combinedDataPoints.length - maxDataPoints\n )\n }\n\n // Keep the full data points\n fullAnalysisRef.current = {\n ...fullAnalysisRef.current,\n dataPoints: fullCombinedDataPoints,\n }\n fullAnalysisRef.current.durationMs =\n fullCombinedDataPoints.length * (1000 / pointsPerSecond)\n savedAnalysisData.dataPoints = combinedDataPoints\n savedAnalysisData.bitDepth =\n analysis.bitDepth || savedAnalysisData.bitDepth\n savedAnalysisData.durationMs =\n combinedDataPoints.length * (1000 / pointsPerSecond)\n\n // Update amplitude range\n const newMin = Math.min(\n savedAnalysisData.amplitudeRange.min,\n analysis.amplitudeRange.min\n )\n const newMax = Math.max(\n savedAnalysisData.amplitudeRange.max,\n analysis.amplitudeRange.max\n )\n\n savedAnalysisData.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n fullAnalysisRef.current.amplitudeRange = {\n min: newMin,\n max: newMax,\n }\n\n logger?.debug(\n `[handleAudioAnalysis] Updated analysis data: durationMs=${savedAnalysisData.durationMs}`,\n savedAnalysisData\n )\n\n // Update the ref\n analysisRef.current = savedAnalysisData\n\n // Dispatch the updated analysis data to state to trigger re-render\n // need to use spread operator otherwise it doesnt trigger update.\n dispatch({\n type: 'UPDATE_ANALYSIS',\n payload: { ...savedAnalysisData },\n })\n },\n [dispatch]\n )\n\n const handleAudioEvent = useCallback(\n async (eventData: AudioEventPayload) => {\n const {\n fileUri,\n deltaSize,\n totalSize,\n lastEmittedSize,\n position,\n streamUuid,\n encoded,\n mimeType,\n buffer,\n } = eventData\n logger?.debug(`[handleAudioEvent] Received audio event:`, {\n fileUri,\n deltaSize,\n totalSize,\n position,\n mimeType,\n lastEmittedSize,\n streamUuid,\n encodedLength: encoded?.length,\n })\n if (deltaSize === 0) {\n // Ignore packet with no data\n return\n }\n try {\n // Coming from native ( ios / android ) otherwise buffer is set\n if (Platform.OS !== 'web') {\n // Read the audio file as a base64 string for comparison\n if (!encoded) {\n logger?.error(`Encoded audio data is missing`)\n throw new Error('Encoded audio data is missing')\n }\n onAudioStreamRef.current?.({\n data: encoded,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n })\n } else if (buffer) {\n // Coming from web\n const webEvent: AudioDataEvent = {\n data: buffer,\n position,\n fileUri,\n eventDataSize: deltaSize,\n totalSize,\n }\n onAudioStreamRef.current?.(webEvent)\n logger?.debug(\n `[handleAudioEvent] Audio data sent to onAudioStream`,\n webEvent\n )\n }\n } catch (error) {\n logger?.error(`Error processing audio event:`, error)\n }\n },\n []\n )\n\n const checkStatus = useCallback(async () => {\n try {\n const status: AudioStreamStatus = ExpoAudioStream.status()\n logger?.debug(\n `Status: paused: ${status.isPaused} durationMs: ${status.durationMs} size: ${status.size}`\n )\n\n // Check and update recording state\n if (\n status.isRecording !== state.isRecording ||\n status.isPaused !== state.isPaused\n ) {\n dispatch({\n type: 'UPDATE_RECORDING_STATE',\n payload: {\n isRecording: status.isRecording,\n isPaused: status.isPaused,\n },\n })\n }\n\n // Check and update recording progress\n if (\n status.durationMs !== state.durationMs ||\n status.size !== state.size\n ) {\n dispatch({\n type: 'UPDATE_STATUS',\n payload: {\n durationMs: status.durationMs,\n size: status.size,\n },\n })\n }\n } catch (error) {\n logger?.error(`Error getting status:`, error)\n }\n }, [state.isRecording])\n\n const startRecording = useCallback(\n async (recordingOptions: RecordingConfig) => {\n logger?.debug(`start recoding`, recordingOptions)\n\n analysisRef.current = { ...defaultAnalysis } // Reset analysis data\n fullAnalysisRef.current = { ...defaultAnalysis }\n const { onAudioStream, ...options } = recordingOptions\n const { enableProcessing } = options\n\n const maxRecentDataDuration = 10000 // TODO compute maxRecentDataDuration based on screen dimensions\n if (typeof onAudioStream === 'function') {\n onAudioStreamRef.current = onAudioStream\n } else {\n logger?.warn(`onAudioStream is not a function`, onAudioStream)\n onAudioStreamRef.current = null\n }\n const startResult: StartRecordingResult =\n await ExpoAudioStream.startRecording(options)\n dispatch({ type: 'START' })\n\n if (enableProcessing) {\n logger?.debug(`Enabling audio analysis listener`)\n const listener = addAudioAnalysisListener(\n async (analysisData) => {\n try {\n await handleAudioAnalysis({\n analysis: analysisData,\n visualizationDuration: maxRecentDataDuration,\n })\n } catch (error) {\n logger?.warn(\n `Error processing audio analysis:`,\n error\n )\n }\n }\n )\n\n analysisListenerRef.current = listener\n }\n\n return startResult\n },\n [handleAudioAnalysis, dispatch]\n )\n\n const stopRecording = useCallback(async () => {\n logger?.debug(`stoping recording`)\n\n const stopResult: AudioRecording = await ExpoAudioStream.stopRecording()\n stopResult.analysisData = fullAnalysisRef.current\n\n if (analysisListenerRef.current) {\n analysisListenerRef.current.remove()\n analysisListenerRef.current = null\n }\n onAudioStreamRef.current = null\n logger?.debug(`recording stopped`, stopResult)\n dispatch({ type: 'STOP' })\n return stopResult\n }, [dispatch])\n\n const pauseRecording = useCallback(async () => {\n logger?.debug(`pause recording`)\n const pauseResult = await ExpoAudioStream.pauseRecording()\n dispatch({ type: 'PAUSE' })\n return pauseResult\n }, [dispatch])\n\n const resumeRecording = useCallback(async () => {\n logger?.debug(`resume recording`)\n const resumeResult = await ExpoAudioStream.resumeRecording()\n dispatch({ type: 'RESUME' })\n return resumeResult\n }, [dispatch])\n\n useEffect(() => {\n let interval: ReturnType<typeof setTimeout>\n if (state.isRecording || state.isPaused) {\n interval = setInterval(checkStatus, 1000)\n }\n return () => {\n if (interval) {\n clearInterval(interval)\n }\n }\n }, [checkStatus, state.isRecording, state.isPaused])\n\n useEffect(() => {\n logger?.debug(`Registering audio event listener`)\n const subscribeAudio = addAudioEventListener(handleAudioEvent)\n\n logger?.debug(\n `Subscribed to audio event listener and analysis listener`,\n {\n subscribeAudio,\n }\n )\n\n return () => {\n logger?.debug(`Removing audio event listener`)\n subscribeAudio.remove()\n }\n }, [handleAudioEvent, handleAudioAnalysis])\n\n return {\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n isPaused: state.isPaused,\n isRecording: state.isRecording,\n durationMs: state.durationMs,\n size: state.size,\n analysisData: state.analysisData,\n }\n}\n"]}
@@ -1,8 +1,10 @@
1
+ import { ConsoleLike } from '../ExpoAudioStream.types';
1
2
  export declare const WAV_HEADER_SIZE = 44;
2
- export declare const convertPCMToFloat32: ({ bitDepth, buffer, skipWavHeader, }: {
3
+ export declare const convertPCMToFloat32: ({ bitDepth, buffer, skipWavHeader, logger, }: {
3
4
  buffer: ArrayBuffer;
4
5
  bitDepth: number;
5
6
  skipWavHeader?: boolean;
7
+ logger?: ConsoleLike;
6
8
  }) => Promise<{
7
9
  pcmValues: Float32Array;
8
10
  min: number;
@@ -1 +1 @@
1
- {"version":3,"file":"convertPCMToFloat32.d.ts","sourceRoot":"","sources":["../../src/utils/convertPCMToFloat32.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,KAAK,CAAA;AA8BjC,eAAO,MAAM,mBAAmB,yCAI7B;IACC,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,OAAO,CAAA;CAC1B,KAAG,OAAO,CAAC;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAiChE,CAAA"}
1
+ {"version":3,"file":"convertPCMToFloat32.d.ts","sourceRoot":"","sources":["../../src/utils/convertPCMToFloat32.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAGtD,eAAO,MAAM,eAAe,KAAK,CAAA;AA4BjC,eAAO,MAAM,mBAAmB,iDAK7B;IACC,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB,KAAG,OAAO,CAAC;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAiChE,CAAA"}
@@ -1,7 +1,5 @@
1
1
  import { getWavFileInfo } from './getWavFileInfo';
2
- import { getLogger } from '../logger';
3
2
  export const WAV_HEADER_SIZE = 44;
4
- const logger = getLogger('convertPCMToFloat32');
5
3
  const convertSample = (dataView, offset, bitDepth) => {
6
4
  switch (bitDepth) {
7
5
  case 8:
@@ -21,9 +19,9 @@ const convertSample = (dataView, offset, bitDepth) => {
21
19
  throw new Error(`Unsupported bit depth: ${bitDepth}`);
22
20
  }
23
21
  };
24
- export const convertPCMToFloat32 = async ({ bitDepth, buffer, skipWavHeader = false, }) => {
22
+ export const convertPCMToFloat32 = async ({ bitDepth, buffer, skipWavHeader = false, logger, }) => {
25
23
  try {
26
- logger.debug(`Converting PCM to Float32: bitDepth: ${bitDepth}, buffer.byteLength: ${buffer.byteLength}`);
24
+ logger?.debug(`Converting PCM to Float32: bitDepth: ${bitDepth}, buffer.byteLength: ${buffer.byteLength}`);
27
25
  const dataView = new DataView(buffer);
28
26
  let headerOffset = 0;
29
27
  if (skipWavHeader) {
@@ -47,7 +45,7 @@ export const convertPCMToFloat32 = async ({ bitDepth, buffer, skipWavHeader = fa
47
45
  return { pcmValues: float32Array, min, max };
48
46
  }
49
47
  catch (error) {
50
- logger.error(`Error converting PCM to Float32`, error);
48
+ logger?.error(`Error converting PCM to Float32`, error);
51
49
  return { pcmValues: new Float32Array(), min: 0, max: 0 };
52
50
  }
53
51
  };
@@ -1 +1 @@
1
- {"version":3,"file":"convertPCMToFloat32.js","sourceRoot":"","sources":["../../src/utils/convertPCMToFloat32.ts"],"names":[],"mappings":"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","sourcesContent":["import { getWavFileInfo, WavFileInfo } from './getWavFileInfo'\nimport { getLogger } from '../logger'\n\nexport const WAV_HEADER_SIZE = 44\n\nconst logger = getLogger('convertPCMToFloat32')\n\nconst convertSample = (\n dataView: DataView,\n offset: number,\n bitDepth: number\n): number => {\n switch (bitDepth) {\n case 8:\n return (dataView.getUint8(offset) - 128) / 128\n case 16:\n return dataView.getInt16(offset, true) / 32768\n case 24:\n return (\n ((dataView.getUint8(offset) |\n (dataView.getUint8(offset + 1) << 8) |\n (dataView.getUint8(offset + 2) << 16)) /\n 8388608) *\n 2 -\n 1\n )\n case 32:\n return dataView.getFloat32(offset, true)\n default:\n throw new Error(`Unsupported bit depth: ${bitDepth}`)\n }\n}\n\nexport const convertPCMToFloat32 = async ({\n bitDepth,\n buffer,\n skipWavHeader = false,\n}: {\n buffer: ArrayBuffer\n bitDepth: number\n skipWavHeader?: boolean\n}): Promise<{ pcmValues: Float32Array; min: number; max: number }> => {\n try {\n logger.debug(\n `Converting PCM to Float32: bitDepth: ${bitDepth}, buffer.byteLength: ${buffer.byteLength}`\n )\n const dataView = new DataView(buffer)\n let headerOffset = 0\n if (skipWavHeader) {\n const wavFileInfo: WavFileInfo = await getWavFileInfo(buffer)\n headerOffset = wavFileInfo.dataChunkOffset\n }\n\n const dataLength = buffer.byteLength - headerOffset\n const sampleLength = Math.floor(dataLength / (bitDepth / 8))\n const float32Array = new Float32Array(sampleLength)\n let min = Infinity\n let max = -Infinity\n\n for (let i = 0; i < sampleLength; i++) {\n const offset = headerOffset + i * (bitDepth / 8)\n const value = convertSample(dataView, offset, bitDepth)\n\n if (value < min) min = value\n if (value > max) max = value\n\n float32Array[i] = value\n }\n\n return { pcmValues: float32Array, min, max }\n } catch (error: unknown) {\n logger.error(`Error converting PCM to Float32`, error)\n return { pcmValues: new Float32Array(), min: 0, max: 0 }\n }\n}\n"]}
1
+ {"version":3,"file":"convertPCMToFloat32.js","sourceRoot":"","sources":["../../src/utils/convertPCMToFloat32.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConsoleLike } from '../ExpoAudioStream.types'\nimport { getWavFileInfo, WavFileInfo } from './getWavFileInfo'\n\nexport const WAV_HEADER_SIZE = 44\n\nconst convertSample = (\n dataView: DataView,\n offset: number,\n bitDepth: number\n): number => {\n switch (bitDepth) {\n case 8:\n return (dataView.getUint8(offset) - 128) / 128\n case 16:\n return dataView.getInt16(offset, true) / 32768\n case 24:\n return (\n ((dataView.getUint8(offset) |\n (dataView.getUint8(offset + 1) << 8) |\n (dataView.getUint8(offset + 2) << 16)) /\n 8388608) *\n 2 -\n 1\n )\n case 32:\n return dataView.getFloat32(offset, true)\n default:\n throw new Error(`Unsupported bit depth: ${bitDepth}`)\n }\n}\n\nexport const convertPCMToFloat32 = async ({\n bitDepth,\n buffer,\n skipWavHeader = false,\n logger,\n}: {\n buffer: ArrayBuffer\n bitDepth: number\n skipWavHeader?: boolean\n logger?: ConsoleLike\n}): Promise<{ pcmValues: Float32Array; min: number; max: number }> => {\n try {\n logger?.debug(\n `Converting PCM to Float32: bitDepth: ${bitDepth}, buffer.byteLength: ${buffer.byteLength}`\n )\n const dataView = new DataView(buffer)\n let headerOffset = 0\n if (skipWavHeader) {\n const wavFileInfo: WavFileInfo = await getWavFileInfo(buffer)\n headerOffset = wavFileInfo.dataChunkOffset\n }\n\n const dataLength = buffer.byteLength - headerOffset\n const sampleLength = Math.floor(dataLength / (bitDepth / 8))\n const float32Array = new Float32Array(sampleLength)\n let min = Infinity\n let max = -Infinity\n\n for (let i = 0; i < sampleLength; i++) {\n const offset = headerOffset + i * (bitDepth / 8)\n const value = convertSample(dataView, offset, bitDepth)\n\n if (value < min) min = value\n if (value > max) max = value\n\n float32Array[i] = value\n }\n\n return { pcmValues: float32Array, min, max }\n } catch (error: unknown) {\n logger?.error(`Error converting PCM to Float32`, error)\n return { pcmValues: new Float32Array(), min: 0, max: 0 }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siteed/expo-audio-stream",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "stream audio crossplatform",
5
5
  "license": "MIT",
6
6
  "main": "build/index.js",
@@ -39,7 +39,6 @@
39
39
  "devDependencies": {
40
40
  "@expo/config-plugins": "~8.0.0",
41
41
  "@siteed/publisher": "^0.4.15",
42
- "@siteed/react-native-logger": "^0.10.0",
43
42
  "@size-limit/preset-big-lib": "^11.1.4",
44
43
  "@types/jest": "^29.5.12",
45
44
  "@types/node": "^20.12.7",
@@ -67,7 +66,6 @@
67
66
  "typescript": "~5.3.3"
68
67
  },
69
68
  "peerDependencies": {
70
- "@siteed/react-native-logger": "*",
71
69
  "expo": "*",
72
70
  "react": "*",
73
71
  "react-native": "*"
@@ -1,16 +1,17 @@
1
1
  import {
2
- AndroidConfig,
3
2
  ConfigPlugin,
4
3
  withAndroidManifest,
5
4
  withInfoPlist,
5
+ AndroidConfig,
6
6
  } from '@expo/config-plugins'
7
+ import { ExpoConfig } from '@expo/config-types'
7
8
 
8
9
  const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone'
9
10
  const NOTIFICATION_USAGE = 'Show recording notifications and controls'
10
11
 
11
- const withRecordingPermission: ConfigPlugin = (config) => {
12
+ const withRecordingPermission: ConfigPlugin = (config: ExpoConfig) => {
12
13
  // iOS Configuration
13
- config = withInfoPlist(config as any, (config) => {
14
+ config = withInfoPlist(config, (config) => {
14
15
  // Existing microphone permission
15
16
  config.modResults['NSMicrophoneUsageDescription'] =
16
17
  config.modResults['NSMicrophoneUsageDescription'] ||
@@ -38,7 +39,7 @@ const withRecordingPermission: ConfigPlugin = (config) => {
38
39
  })
39
40
 
40
41
  // Android Configuration
41
- config = withAndroidManifest(config as any, (config) => {
42
+ config = withAndroidManifest(config, (config) => {
42
43
  const androidManifest = config.modResults
43
44
  if (!androidManifest.manifest) {
44
45
  console.warn(
@@ -1,18 +1,16 @@
1
1
  // packages/expo-audio-stream/src/AudioAnalysis/extractAudioAnalysis.ts
2
+ import { ConsoleLike } from '../ExpoAudioStream.types'
3
+ import ExpoAudioStreamModule from '../ExpoAudioStreamModule'
4
+ import { isWeb } from '../constants'
2
5
  import {
3
6
  AmplitudeAlgorithm,
4
7
  AudioAnalysis,
5
8
  AudioFeaturesOptions,
6
9
  } from './AudioAnalysis.types'
7
- import ExpoAudioStreamModule from '../ExpoAudioStreamModule'
8
- import { isWeb } from '../constants'
9
- import { getLogger } from '../logger'
10
10
  import { convertPCMToFloat32 } from '../utils/convertPCMToFloat32'
11
11
  import { getWavFileInfo, WavFileInfo } from '../utils/getWavFileInfo'
12
12
  import { InlineFeaturesExtractor } from '../workers/InlineFeaturesExtractor.web'
13
13
 
14
- const logger = getLogger('extractAudioAnalysis')
15
-
16
14
  export interface ExtractAudioAnalysisProps {
17
15
  fileUri?: string // should provide either fileUri or arrayBuffer
18
16
  wavMetadata?: WavFileInfo
@@ -28,6 +26,7 @@ export interface ExtractAudioAnalysisProps {
28
26
  pointsPerSecond?: number // Optional number of points per second. Use to reduce the number of points and compute the number of datapoints to return.
29
27
  features?: AudioFeaturesOptions
30
28
  featuresExtratorUrl?: string
29
+ logger?: ConsoleLike
31
30
  }
32
31
 
33
32
  export const extractAudioAnalysis = async ({
@@ -42,6 +41,7 @@ export const extractAudioAnalysis = async ({
42
41
  algorithm = 'rms',
43
42
  features,
44
43
  featuresExtratorUrl,
44
+ logger,
45
45
  }: ExtractAudioAnalysisProps): Promise<AudioAnalysis> => {
46
46
  if (isWeb) {
47
47
  if (!arrayBuffer && !fileUri) {
@@ -49,7 +49,7 @@ export const extractAudioAnalysis = async ({
49
49
  }
50
50
 
51
51
  if (!arrayBuffer) {
52
- logger.log(`fetching fileUri`, fileUri)
52
+ logger?.log(`fetching fileUri`, fileUri)
53
53
  const response = await fetch(fileUri!)
54
54
 
55
55
  if (!response.ok) {
@@ -59,25 +59,25 @@ export const extractAudioAnalysis = async ({
59
59
  }
60
60
 
61
61
  arrayBuffer = await response.arrayBuffer()
62
- logger.log(`fetched fileUri`, arrayBuffer.byteLength, arrayBuffer)
62
+ logger?.log(`fetched fileUri`, arrayBuffer.byteLength, arrayBuffer)
63
63
  }
64
64
 
65
65
  // Create a new copy of the ArrayBuffer to avoid detachment issues
66
66
  const bufferCopy = arrayBuffer.slice(0)
67
- logger.log(
67
+ logger?.log(
68
68
  `extractAudioAnalysis skipWavHeader=${skipWavHeader} bitDepth=${bitDepth} len=${bufferCopy.byteLength}`,
69
69
  bufferCopy.slice(0, 100)
70
70
  )
71
71
 
72
72
  let actualBitDepth = bitDepth
73
73
  if (!actualBitDepth) {
74
- logger.log(
74
+ logger?.log(
75
75
  `extractAudioAnalysis bitDepth not provided -- getting wav file info`
76
76
  )
77
77
  const fileInfo = await getWavFileInfo(bufferCopy)
78
78
  actualBitDepth = fileInfo.bitDepth
79
79
  }
80
- logger.log(`extractAudioAnalysis actualBitDepth=${actualBitDepth}`)
80
+ logger?.log(`extractAudioAnalysis actualBitDepth=${actualBitDepth}`)
81
81
 
82
82
  const {
83
83
  pcmValues: channelData,
@@ -88,7 +88,7 @@ export const extractAudioAnalysis = async ({
88
88
  bitDepth: actualBitDepth,
89
89
  skipWavHeader,
90
90
  })
91
- logger.log(
91
+ logger?.log(
92
92
  `extractAudioAnalysis skipWaveHeader=${skipWavHeader} convertPCMToFloat32 length=${channelData.length} range: [ ${min} :: ${max} ]`
93
93
  )
94
94
 
@@ -129,7 +129,7 @@ export const extractAudioAnalysis = async ({
129
129
  if (!fileUri) {
130
130
  throw new Error('fileUri is required')
131
131
  }
132
- logger.log(`extractAudioAnalysis`, {
132
+ logger?.log(`extractAudioAnalysis`, {
133
133
  fileUri,
134
134
  pointsPerSecond,
135
135
  algorithm,
@@ -141,7 +141,7 @@ export const extractAudioAnalysis = async ({
141
141
  algorithm,
142
142
  features,
143
143
  })
144
- logger.log(`extractAudioAnalysis`, res)
144
+ logger?.log(`extractAudioAnalysis`, res)
145
145
  return res
146
146
  }
147
147
  }
@@ -1,7 +1,5 @@
1
1
  import ExpoAudioStreamModule from '../ExpoAudioStreamModule'
2
- import { getLogger } from '../logger'
3
2
 
4
- const logger = getLogger('extractWaveform')
5
3
  export interface ExtractWaveformProps {
6
4
  fileUri: string
7
5
  numberOfSamples: number
@@ -20,6 +18,5 @@ export const extractWaveform = async ({
20
18
  offset,
21
19
  length,
22
20
  })
23
- logger.log(`extractWaveform`, res)
24
21
  return res
25
22
  }
@@ -27,6 +27,13 @@ export type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'
27
27
  export type SampleRate = 16000 | 44100 | 48000
28
28
  export type BitDepth = 8 | 16 | 32
29
29
 
30
+ export type ConsoleLike = {
31
+ log: (message: string, ...args: unknown[]) => void
32
+ debug: (message: string, ...args: unknown[]) => void
33
+ warn: (message: string, ...args: unknown[]) => void
34
+ error: (message: string, ...args: unknown[]) => void
35
+ }
36
+
30
37
  export interface Chunk {
31
38
  text: string
32
39
  timestamp: [number, number | null]
@@ -6,12 +6,12 @@ import {
6
6
  AudioRecording,
7
7
  AudioStreamStatus,
8
8
  BitDepth,
9
+ ConsoleLike,
9
10
  RecordingConfig,
10
11
  StartRecordingResult,
11
12
  } from './ExpoAudioStream.types'
12
13
  import { WebRecorder } from './WebRecorder.web'
13
14
  import { AudioEventPayload } from './events'
14
- import { getLogger } from './logger'
15
15
  import { encodingToBitDepth } from './utils/encodingToBitDepth'
16
16
  import { WavHeaderOptions, writeWavHeader } from './utils/writeWavHeader'
17
17
 
@@ -23,12 +23,11 @@ export type EmitAudioEventFunction = (_: EmitAudioEventProps) => void
23
23
  export type EmitAudioAnalysisFunction = (_: AudioAnalysis) => void
24
24
 
25
25
  export interface ExpoAudioStreamWebProps {
26
+ logger?: ConsoleLike
26
27
  audioWorkletUrl: string
27
28
  featuresExtratorUrl: string
28
29
  }
29
30
 
30
- const logger = getLogger('ExpoAudioStreamWeb')
31
-
32
31
  export class ExpoAudioStreamWeb extends LegacyEventEmitter {
33
32
  customRecorder: WebRecorder | null
34
33
  audioChunks: ArrayBuffer[]
@@ -47,10 +46,12 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
47
46
  bitDepth: BitDepth // Bit depth of the audio
48
47
  audioWorkletUrl: string
49
48
  featuresExtratorUrl: string
49
+ logger?: ConsoleLike
50
50
 
51
51
  constructor({
52
52
  audioWorkletUrl,
53
53
  featuresExtratorUrl,
54
+ logger,
54
55
  }: ExpoAudioStreamWebProps) {
55
56
  const mockNativeModule = {
56
57
  addListener: () => {
@@ -62,6 +63,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
62
63
  }
63
64
  super(mockNativeModule) // Pass the mock native module to the parent class
64
65
 
66
+ this.logger = logger
65
67
  this.customRecorder = null
66
68
  this.audioChunks = []
67
69
  this.isRecording = false
@@ -123,7 +125,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
123
125
  this.lastEmittedSize = this.currentSize
124
126
  },
125
127
  emitAudioAnalysisCallback: (audioAnalysisData: AudioAnalysis) => {
126
- logger.log(`Emitted AudioAnalysis:`, audioAnalysisData)
128
+ this.logger?.log(`Emitted AudioAnalysis:`, audioAnalysisData)
127
129
  this.emit('AudioAnalysis', audioAnalysisData)
128
130
  },
129
131
  })
@@ -181,7 +183,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
181
183
  const fullPcmBufferArray = await this.customRecorder.stop()
182
184
 
183
185
  // concat all audio chunks
184
- logger.debug(`Stopped recording`, fullPcmBufferArray)
186
+ this.logger?.debug(`Stopped recording`, fullPcmBufferArray)
185
187
  this.isRecording = false
186
188
  this.isPaused = false
187
189
  this.currentDurationMs = Date.now() - this.recordingStartTime
@@ -193,7 +195,7 @@ export class ExpoAudioStreamWeb extends LegacyEventEmitter {
193
195
  numChannels: this.recordingConfig?.channels ?? 1,
194
196
  bitDepth: this.bitDepth,
195
197
  }
196
- logger.debug(`Writing wav header`, wavConfig)
198
+ this.logger?.debug(`Writing wav header`, wavConfig)
197
199
  const wavBuffer = writeWavHeader(wavConfig).slice(0)
198
200
 
199
201
  // Create blob fileUri from audio chunks
@@ -1,13 +1,11 @@
1
1
  // src/WebRecorder.ts
2
- import { buffer } from 'stream/consumers'
3
2
 
4
3
  import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
5
- import { RecordingConfig } from './ExpoAudioStream.types'
4
+ import { ConsoleLike, RecordingConfig } from './ExpoAudioStream.types'
6
5
  import {
7
6
  EmitAudioAnalysisFunction,
8
7
  EmitAudioEventFunction,
9
8
  } from './ExpoAudioStream.web'
10
- import { getLogger } from './logger'
11
9
  import { convertPCMToFloat32 } from './utils/convertPCMToFloat32'
12
10
  import { encodingToBitDepth } from './utils/encodingToBitDepth'
13
11
  import { writeWavHeader } from './utils/writeWavHeader'
@@ -36,7 +34,6 @@ const DEFAULT_WEB_NUMBER_OF_CHANNELS = 1
36
34
  const DEFAULT_ALGORITHM = 'rms'
37
35
 
38
36
  const TAG = 'WebRecorder'
39
- const logger = getLogger(TAG)
40
37
 
41
38
  export class WebRecorder {
42
39
  private audioContext: AudioContext
@@ -55,6 +52,7 @@ export class WebRecorder {
55
52
  private audioBufferSize: number // Keep track of the buffer size
56
53
  private audioAnalysisData: AudioAnalysis // Keep updating the full audio analysis data with latest events
57
54
  private packetCount: number = 0
55
+ private logger?: ConsoleLike
58
56
 
59
57
  constructor({
60
58
  audioContext,
@@ -63,6 +61,7 @@ export class WebRecorder {
63
61
  audioWorkletUrl,
64
62
  emitAudioEventCallback,
65
63
  emitAudioAnalysisCallback,
64
+ logger,
66
65
  }: {
67
66
  audioContext: AudioContext
68
67
  source: MediaStreamAudioSourceNode
@@ -70,6 +69,7 @@ export class WebRecorder {
70
69
  audioWorkletUrl: string
71
70
  emitAudioEventCallback: EmitAudioEventFunction
72
71
  emitAudioAnalysisCallback: EmitAudioAnalysisFunction
72
+ logger?: ConsoleLike
73
73
  }) {
74
74
  this.audioContext = audioContext
75
75
  this.source = source
@@ -78,11 +78,12 @@ export class WebRecorder {
78
78
  this.emitAudioAnalysisCallback = emitAudioAnalysisCallback
79
79
  this.config = recordingConfig
80
80
  this.position = 0
81
+ this.logger = logger
81
82
 
82
83
  const audioContextFormat = this.checkAudioContextFormat({
83
84
  sampleRate: this.audioContext.sampleRate,
84
85
  })
85
- logger.debug('Initialized WebRecorder with config:', {
86
+ this.logger?.debug('Initialized WebRecorder with config:', {
86
87
  sampleRate: audioContextFormat.sampleRate,
87
88
  bitDepth: audioContextFormat.bitDepth,
88
89
  numberOfChannels: audioContextFormat.numberOfChannels,
@@ -150,12 +151,12 @@ export class WebRecorder {
150
151
  const pcmBufferFloat = event.data.recordedData
151
152
 
152
153
  if (!pcmBufferFloat) {
153
- logger.warn('Received empty audio buffer', event)
154
+ this.logger?.warn('Received empty audio buffer', event)
154
155
  return
155
156
  }
156
157
 
157
158
  // Handle the audio blob (e.g., send it to the server or process it further)
158
- logger.debug(
159
+ this.logger?.debug(
159
160
  `Received audio blob from processor len:${pcmBufferFloat?.length}`,
160
161
  event
161
162
  )
@@ -220,7 +221,7 @@ export class WebRecorder {
220
221
  )
221
222
  }
222
223
 
223
- logger.debug(
224
+ this.logger?.debug(
224
225
  `WebRecorder initialized -- recordSampleRate=${this.audioContext.sampleRate}`,
225
226
  this.config
226
227
  )
@@ -281,7 +282,7 @@ export class WebRecorder {
281
282
  this.featureExtractorWorker.onerror = (error) => {
282
283
  console.error(`[${TAG}] Default Inline worker failed`, error)
283
284
  }
284
- logger.log('Inline worker initialized successfully')
285
+ this.logger?.log('Inline worker initialized successfully')
285
286
  } catch (error) {
286
287
  console.error(
287
288
  `[${TAG}] Failed to initialize Inline Feature Extractor worker`,
@@ -317,8 +318,8 @@ export class WebRecorder {
317
318
  }
318
319
  }
319
320
  // Handle the extracted features (e.g., emit an event or log them)
320
- logger.debug('features event segmentResult', segmentResult)
321
- logger.debug(
321
+ this.logger?.debug('features event segmentResult', segmentResult)
322
+ this.logger?.debug(
322
323
  `features event audioAnalysisData duration=${this.audioAnalysisData.durationMs}`,
323
324
  this.audioAnalysisData
324
325
  )
@@ -373,10 +374,10 @@ export class WebRecorder {
373
374
  (this.audioContext.sampleRate *
374
375
  (this.exportBitDepth /
375
376
  this.numberOfChannels))
376
- logger.debug(
377
+ this.logger?.debug(
377
378
  `Received recorded data -- Duration: ${duration} vs ${rawPCMDataFull.byteLength / this.audioContext.sampleRate} seconds`
378
379
  )
379
- logger.debug(
380
+ this.logger?.debug(
380
381
  `recordedData.length=${rawPCMDataFull.byteLength} vs transmittedData.length=${this.audioBufferSize}`
381
382
  )
382
383
 
@@ -448,7 +449,7 @@ export class WebRecorder {
448
449
  bufferSource.buffer = audioBuffer
449
450
  bufferSource.connect(this.audioContext.destination)
450
451
  bufferSource.start()
451
- logger.debug('Playing recorded data', recordedData)
452
+ this.logger?.debug('Playing recorded data', recordedData)
452
453
  } catch (error) {
453
454
  console.error(`[${TAG}] Failed to play recorded data:`, error)
454
455
  }
package/src/events.ts CHANGED
@@ -4,10 +4,8 @@ import { LegacyEventEmitter, type EventSubscription } from 'expo-modules-core'
4
4
 
5
5
  import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
6
6
  import ExpoAudioStreamModule from './ExpoAudioStreamModule'
7
- import { getLogger } from './logger'
8
7
 
9
8
  const emitter = new LegacyEventEmitter(ExpoAudioStreamModule)
10
- const logger = getLogger('events')
11
9
 
12
10
  export interface AudioEventPayload {
13
11
  encoded?: string
@@ -24,7 +22,6 @@ export interface AudioEventPayload {
24
22
  export function addAudioEventListener(
25
23
  listener: (event: AudioEventPayload) => Promise<void>
26
24
  ): EventSubscription {
27
- logger.log('Adding listener for AudioData event')
28
25
  return emitter.addListener<AudioEventPayload>('AudioData', listener)
29
26
  }
30
27
 
@@ -34,6 +31,5 @@ export interface AudioAnalysisEvent extends AudioAnalysis {}
34
31
  export function addAudioAnalysisListener(
35
32
  listener: (event: AudioAnalysisEvent) => Promise<void>
36
33
  ): EventSubscription {
37
- logger.log('Adding listener for AudioAnalysis event')
38
34
  return emitter.addListener<AudioAnalysisEvent>('AudioAnalysis', listener)
39
35
  }