@siteed/audio-studio 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +535 -0
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/android/build.gradle +143 -0
- package/android/src/androidTest/assets/chorus.wav +0 -0
- package/android/src/androidTest/assets/jfk.wav +0 -0
- package/android/src/androidTest/assets/osr_us_000_0010_8k.wav +0 -0
- package/android/src/androidTest/assets/recorder_hello_world.wav +0 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/AudioProcessorInstrumentedTest.kt +197 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderInstrumentedTest.kt +541 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderPerformanceInstrumentedTest.kt +234 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/AudioFocusStrategyIntegrationTest.kt +332 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/BufferDurationIntegrationTest.kt +324 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/CompressedOnlyOutputTest.kt +253 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/DeviceDisconnectionFallbackTest.kt +218 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/EventEmissionIntervalTest.kt +120 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/M4aFormatTest.kt +345 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/OutputControlIntegrationTest.kt +340 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/PcmStreamingDurationTest.kt +252 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/README.md +95 -0
- package/android/src/androidTest/java/net/siteed/audiostudio/integration/run_integration_tests.sh +43 -0
- package/android/src/main/AndroidManifest.xml +30 -0
- package/android/src/main/CMakeLists.txt +29 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioAnalysisData.kt +188 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioDataEncoder.kt +9 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioDeviceManager.kt +1741 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioFeaturesNative.kt +26 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioFileHandler.kt +136 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioFormatUtils.kt +354 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioNotificationsManager.kt +439 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioProcessor.kt +2237 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioRecorderManager.kt +2163 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioRecordingService.kt +167 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioStudioModule.kt +1112 -0
- package/android/src/main/java/net/siteed/audiostudio/AudioTrimmer.kt +1099 -0
- package/android/src/main/java/net/siteed/audiostudio/Constants.kt +37 -0
- package/android/src/main/java/net/siteed/audiostudio/EventSender.kt +7 -0
- package/android/src/main/java/net/siteed/audiostudio/FFT.kt +100 -0
- package/android/src/main/java/net/siteed/audiostudio/Features.kt +98 -0
- package/android/src/main/java/net/siteed/audiostudio/LogUtils.kt +93 -0
- package/android/src/main/java/net/siteed/audiostudio/MelSpectrogramNative.kt +36 -0
- package/android/src/main/java/net/siteed/audiostudio/NotificationConfig.kt +72 -0
- package/android/src/main/java/net/siteed/audiostudio/PermissionUtils.kt +68 -0
- package/android/src/main/java/net/siteed/audiostudio/RecordingActionReceiver.kt +59 -0
- package/android/src/main/java/net/siteed/audiostudio/RecordingConfig.kt +259 -0
- package/android/src/main/java/net/siteed/audiostudio/WaveformConfig.kt +19 -0
- package/android/src/main/java/net/siteed/audiostudio/WaveformRenderer.kt +159 -0
- package/android/src/main/jni/AudioFeaturesJNI.cpp +152 -0
- package/android/src/main/jni/MelSpectrogramJNI.cpp +165 -0
- package/android/src/main/res/drawable/ic_default_action_icon.xml +16 -0
- package/android/src/main/res/drawable/ic_microphone.xml +13 -0
- package/android/src/main/res/drawable/ic_pause.xml +10 -0
- package/android/src/main/res/drawable/ic_play.xml +10 -0
- package/android/src/main/res/drawable/ic_stop.xml +10 -0
- package/android/src/main/res/layout/notification_recording.xml +37 -0
- package/android/src/test/java/net/siteed/audiostudio/AudioFileHandlerTest.kt +279 -0
- package/android/src/test/java/net/siteed/audiostudio/AudioFocusStrategyTest.kt +249 -0
- package/android/src/test/java/net/siteed/audiostudio/AudioFormatTest.kt +151 -0
- package/android/src/test/java/net/siteed/audiostudio/AudioFormatUtilsTest.kt +273 -0
- package/android/src/test/java/net/siteed/audiostudio/DeviceDisconnectionFallbackUnitTest.kt +140 -0
- package/android/src/test/resources/chorus.wav +0 -0
- package/android/src/test/resources/generate_test_audio.py +94 -0
- package/android/src/test/resources/jfk.wav +0 -0
- package/android/src/test/resources/osr_us_000_0010_8k.wav +0 -0
- package/android/src/test/resources/recorder_hello_world.wav +0 -0
- package/app.plugin.js +3 -0
- package/build/cjs/AudioAnalysis/AudioAnalysis.types.js +4 -0
- package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
- package/build/cjs/AudioAnalysis/audioFeaturesWasm.js +164 -0
- package/build/cjs/AudioAnalysis/audioFeaturesWasm.js.map +1 -0
- package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +213 -0
- package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
- package/build/cjs/AudioAnalysis/extractAudioData.js +21 -0
- package/build/cjs/AudioAnalysis/extractAudioData.js.map +1 -0
- package/build/cjs/AudioAnalysis/extractMelSpectrogram.js +90 -0
- package/build/cjs/AudioAnalysis/extractMelSpectrogram.js.map +1 -0
- package/build/cjs/AudioAnalysis/extractPreview.js +28 -0
- package/build/cjs/AudioAnalysis/extractPreview.js.map +1 -0
- package/build/cjs/AudioAnalysis/extractWaveform.js +18 -0
- package/build/cjs/AudioAnalysis/extractWaveform.js.map +1 -0
- package/build/cjs/AudioAnalysis/melSpectrogramWasm.js +149 -0
- package/build/cjs/AudioAnalysis/melSpectrogramWasm.js.map +1 -0
- package/build/cjs/AudioDeviceManager.js +688 -0
- package/build/cjs/AudioDeviceManager.js.map +1 -0
- package/build/cjs/AudioRecorder.provider.js +78 -0
- package/build/cjs/AudioRecorder.provider.js.map +1 -0
- package/build/cjs/AudioStudio.native.js +8 -0
- package/build/cjs/AudioStudio.native.js.map +1 -0
- package/build/cjs/AudioStudio.types.js +11 -0
- package/build/cjs/AudioStudio.types.js.map +1 -0
- package/build/cjs/AudioStudio.web.js +708 -0
- package/build/cjs/AudioStudio.web.js.map +1 -0
- package/build/cjs/AudioStudioModule.js +718 -0
- package/build/cjs/AudioStudioModule.js.map +1 -0
- package/build/cjs/WebRecorder.web.js +865 -0
- package/build/cjs/WebRecorder.web.js.map +1 -0
- package/build/cjs/constants/platformLimitations.js +99 -0
- package/build/cjs/constants/platformLimitations.js.map +1 -0
- package/build/cjs/constants.js +20 -0
- package/build/cjs/constants.js.map +1 -0
- package/build/cjs/events.js +29 -0
- package/build/cjs/events.js.map +1 -0
- package/build/cjs/hooks/useAudioDevices.js +179 -0
- package/build/cjs/hooks/useAudioDevices.js.map +1 -0
- package/build/cjs/index.js +64 -0
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/trimAudio.js +76 -0
- package/build/cjs/trimAudio.js.map +1 -0
- package/build/cjs/useAudioRecorder.js +535 -0
- package/build/cjs/useAudioRecorder.js.map +1 -0
- package/build/cjs/utils/BlobFix.js +502 -0
- package/build/cjs/utils/BlobFix.js.map +1 -0
- package/build/cjs/utils/audioProcessing.js +136 -0
- package/build/cjs/utils/audioProcessing.js.map +1 -0
- package/build/cjs/utils/cleanNativeOptions.js +22 -0
- package/build/cjs/utils/cleanNativeOptions.js.map +1 -0
- package/build/cjs/utils/concatenateBuffers.js +25 -0
- package/build/cjs/utils/concatenateBuffers.js.map +1 -0
- package/build/cjs/utils/convertPCMToFloat32.js +124 -0
- package/build/cjs/utils/convertPCMToFloat32.js.map +1 -0
- package/build/cjs/utils/crc32.js +52 -0
- package/build/cjs/utils/crc32.js.map +1 -0
- package/build/cjs/utils/encodingToBitDepth.js +17 -0
- package/build/cjs/utils/encodingToBitDepth.js.map +1 -0
- package/build/cjs/utils/getWavFileInfo.js +96 -0
- package/build/cjs/utils/getWavFileInfo.js.map +1 -0
- package/build/cjs/utils/writeWavHeader.js +88 -0
- package/build/cjs/utils/writeWavHeader.js.map +1 -0
- package/build/cjs/workers/InlineFeaturesExtractor.web.js +294 -0
- package/build/cjs/workers/InlineFeaturesExtractor.web.js.map +1 -0
- package/build/cjs/workers/inlineAudioWebWorker.web.js +190 -0
- package/build/cjs/workers/inlineAudioWebWorker.web.js.map +1 -0
- package/build/cjs/workers/wasmGlueString.web.js +27 -0
- package/build/cjs/workers/wasmGlueString.web.js.map +1 -0
- package/build/esm/AudioAnalysis/AudioAnalysis.types.js +3 -0
- package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
- package/build/esm/AudioAnalysis/audioFeaturesWasm.js +126 -0
- package/build/esm/AudioAnalysis/audioFeaturesWasm.js.map +1 -0
- package/build/esm/AudioAnalysis/extractAudioAnalysis.js +205 -0
- package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
- package/build/esm/AudioAnalysis/extractAudioData.js +14 -0
- package/build/esm/AudioAnalysis/extractAudioData.js.map +1 -0
- package/build/esm/AudioAnalysis/extractMelSpectrogram.js +86 -0
- package/build/esm/AudioAnalysis/extractMelSpectrogram.js.map +1 -0
- package/build/esm/AudioAnalysis/extractPreview.js +25 -0
- package/build/esm/AudioAnalysis/extractPreview.js.map +1 -0
- package/build/esm/AudioAnalysis/extractWaveform.js +11 -0
- package/build/esm/AudioAnalysis/extractWaveform.js.map +1 -0
- package/build/esm/AudioAnalysis/melSpectrogramWasm.js +111 -0
- package/build/esm/AudioAnalysis/melSpectrogramWasm.js.map +1 -0
- package/build/esm/AudioDeviceManager.js +681 -0
- package/build/esm/AudioDeviceManager.js.map +1 -0
- package/build/esm/AudioRecorder.provider.js +40 -0
- package/build/esm/AudioRecorder.provider.js.map +1 -0
- package/build/esm/AudioStudio.native.js +6 -0
- package/build/esm/AudioStudio.native.js.map +1 -0
- package/build/esm/AudioStudio.types.js +8 -0
- package/build/esm/AudioStudio.types.js.map +1 -0
- package/build/esm/AudioStudio.web.js +704 -0
- package/build/esm/AudioStudio.web.js.map +1 -0
- package/build/esm/AudioStudioModule.js +713 -0
- package/build/esm/AudioStudioModule.js.map +1 -0
- package/build/esm/WebRecorder.web.js +861 -0
- package/build/esm/WebRecorder.web.js.map +1 -0
- package/build/esm/constants/platformLimitations.js +90 -0
- package/build/esm/constants/platformLimitations.js.map +1 -0
- package/build/esm/constants.js +17 -0
- package/build/esm/constants.js.map +1 -0
- package/build/esm/events.js +21 -0
- package/build/esm/events.js.map +1 -0
- package/build/esm/hooks/useAudioDevices.js +176 -0
- package/build/esm/hooks/useAudioDevices.js.map +1 -0
- package/build/esm/index.js +23 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/trimAudio.js +69 -0
- package/build/esm/trimAudio.js.map +1 -0
- package/build/esm/useAudioRecorder.js +529 -0
- package/build/esm/useAudioRecorder.js.map +1 -0
- package/build/esm/utils/BlobFix.js +498 -0
- package/build/esm/utils/BlobFix.js.map +1 -0
- package/build/esm/utils/audioProcessing.js +133 -0
- package/build/esm/utils/audioProcessing.js.map +1 -0
- package/build/esm/utils/cleanNativeOptions.js +19 -0
- package/build/esm/utils/cleanNativeOptions.js.map +1 -0
- package/build/esm/utils/concatenateBuffers.js +21 -0
- package/build/esm/utils/concatenateBuffers.js.map +1 -0
- package/build/esm/utils/convertPCMToFloat32.js +120 -0
- package/build/esm/utils/convertPCMToFloat32.js.map +1 -0
- package/build/esm/utils/crc32.js +50 -0
- package/build/esm/utils/crc32.js.map +1 -0
- package/build/esm/utils/encodingToBitDepth.js +13 -0
- package/build/esm/utils/encodingToBitDepth.js.map +1 -0
- package/build/esm/utils/getWavFileInfo.js +92 -0
- package/build/esm/utils/getWavFileInfo.js.map +1 -0
- package/build/esm/utils/writeWavHeader.js +84 -0
- package/build/esm/utils/writeWavHeader.js.map +1 -0
- package/build/esm/workers/InlineFeaturesExtractor.web.js +291 -0
- package/build/esm/workers/InlineFeaturesExtractor.web.js.map +1 -0
- package/build/esm/workers/inlineAudioWebWorker.web.js +187 -0
- package/build/esm/workers/inlineAudioWebWorker.web.js.map +1 -0
- package/build/esm/workers/wasmGlueString.web.js +24 -0
- package/build/esm/workers/wasmGlueString.web.js.map +1 -0
- package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +198 -0
- package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -0
- package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts +24 -0
- package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts.map +1 -0
- package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts +74 -0
- package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -0
- package/build/types/AudioAnalysis/extractAudioData.d.ts +3 -0
- package/build/types/AudioAnalysis/extractAudioData.d.ts.map +1 -0
- package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts +20 -0
- package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts.map +1 -0
- package/build/types/AudioAnalysis/extractPreview.d.ts +11 -0
- package/build/types/AudioAnalysis/extractPreview.d.ts.map +1 -0
- package/build/types/AudioAnalysis/extractWaveform.d.ts +8 -0
- package/build/types/AudioAnalysis/extractWaveform.d.ts.map +1 -0
- package/build/types/AudioAnalysis/melSpectrogramWasm.d.ts +16 -0
- package/build/types/AudioAnalysis/melSpectrogramWasm.d.ts.map +1 -0
- package/build/types/AudioDeviceManager.d.ts +187 -0
- package/build/types/AudioDeviceManager.d.ts.map +1 -0
- package/build/types/AudioRecorder.provider.d.ts +11 -0
- package/build/types/AudioRecorder.provider.d.ts.map +1 -0
- package/build/types/AudioStudio.native.d.ts +3 -0
- package/build/types/AudioStudio.native.d.ts.map +1 -0
- package/build/types/AudioStudio.types.d.ts +760 -0
- package/build/types/AudioStudio.types.d.ts.map +1 -0
- package/build/types/AudioStudio.web.d.ts +96 -0
- package/build/types/AudioStudio.web.d.ts.map +1 -0
- package/build/types/AudioStudioModule.d.ts +3 -0
- package/build/types/AudioStudioModule.d.ts.map +1 -0
- package/build/types/WebRecorder.web.d.ts +208 -0
- package/build/types/WebRecorder.web.d.ts.map +1 -0
- package/build/types/constants/platformLimitations.d.ts +40 -0
- package/build/types/constants/platformLimitations.d.ts.map +1 -0
- package/build/types/constants.d.ts +14 -0
- package/build/types/constants.d.ts.map +1 -0
- package/build/types/events.d.ts +29 -0
- package/build/types/events.d.ts.map +1 -0
- package/build/types/hooks/useAudioDevices.d.ts +15 -0
- package/build/types/hooks/useAudioDevices.d.ts.map +1 -0
- package/build/types/index.d.ts +21 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/trimAudio.d.ts +25 -0
- package/build/types/trimAudio.d.ts.map +1 -0
- package/build/types/useAudioRecorder.d.ts +22 -0
- package/build/types/useAudioRecorder.d.ts.map +1 -0
- package/build/types/utils/BlobFix.d.ts +9 -0
- package/build/types/utils/BlobFix.d.ts.map +1 -0
- package/build/types/utils/audioProcessing.d.ts +24 -0
- package/build/types/utils/audioProcessing.d.ts.map +1 -0
- package/build/types/utils/cleanNativeOptions.d.ts +15 -0
- package/build/types/utils/cleanNativeOptions.d.ts.map +1 -0
- package/build/types/utils/concatenateBuffers.d.ts +8 -0
- package/build/types/utils/concatenateBuffers.d.ts.map +1 -0
- package/build/types/utils/convertPCMToFloat32.d.ts +13 -0
- package/build/types/utils/convertPCMToFloat32.d.ts.map +1 -0
- package/build/types/utils/crc32.d.ts +7 -0
- package/build/types/utils/crc32.d.ts.map +1 -0
- package/build/types/utils/encodingToBitDepth.d.ts +5 -0
- package/build/types/utils/encodingToBitDepth.d.ts.map +1 -0
- package/build/types/utils/getWavFileInfo.d.ts +26 -0
- package/build/types/utils/getWavFileInfo.d.ts.map +1 -0
- package/build/types/utils/writeWavHeader.d.ts +34 -0
- package/build/types/utils/writeWavHeader.d.ts.map +1 -0
- package/build/types/workers/InlineFeaturesExtractor.web.d.ts +2 -0
- package/build/types/workers/InlineFeaturesExtractor.web.d.ts.map +1 -0
- package/build/types/workers/inlineAudioWebWorker.web.d.ts +2 -0
- package/build/types/workers/inlineAudioWebWorker.web.d.ts.map +1 -0
- package/build/types/workers/wasmGlueString.web.d.ts +2 -0
- package/build/types/workers/wasmGlueString.web.d.ts.map +1 -0
- package/cpp/AudioFeatures.cpp +274 -0
- package/cpp/AudioFeatures.h +85 -0
- package/cpp/AudioFeaturesBridge.cpp +146 -0
- package/cpp/AudioFeaturesBridge.h +47 -0
- package/cpp/MelSpectrogram.cpp +227 -0
- package/cpp/MelSpectrogram.h +82 -0
- package/cpp/MelSpectrogramBridge.cpp +112 -0
- package/cpp/MelSpectrogramBridge.h +33 -0
- package/cpp/kiss_fft/COPYING +11 -0
- package/cpp/kiss_fft/_kiss_fft_guts.h +167 -0
- package/cpp/kiss_fft/kiss_fft.c +424 -0
- package/cpp/kiss_fft/kiss_fft.h +160 -0
- package/cpp/kiss_fft/kiss_fft_log.h +36 -0
- package/cpp/kiss_fft/kiss_fftr.c +155 -0
- package/cpp/kiss_fft/kiss_fftr.h +54 -0
- package/expo-module.config.json +10 -0
- package/ios/AudioAnalysisData.swift +74 -0
- package/ios/AudioDeviceManager.swift +670 -0
- package/ios/AudioFeaturesWrapper.h +21 -0
- package/ios/AudioFeaturesWrapper.mm +63 -0
- package/ios/AudioNotificationManager.swift +154 -0
- package/ios/AudioProcessingHelpers.swift +797 -0
- package/ios/AudioProcessor.swift +1191 -0
- package/ios/AudioStreamError.swift +7 -0
- package/ios/AudioStreamManager.swift +2369 -0
- package/ios/AudioStreamManagerDelegate.swift +16 -0
- package/ios/AudioStudio.podspec +39 -0
- package/ios/AudioStudioModule.swift +1111 -0
- package/ios/AudioStudioTests/AudioFileHandlerTests.swift +338 -0
- package/ios/AudioStudioTests/AudioFormatUtilsTests.swift +331 -0
- package/ios/AudioStudioTests/AudioTestHelpers.swift +130 -0
- package/ios/AudioStudioTests/CompressedOnlyOutputTests.swift +294 -0
- package/ios/AudioStudioTests/EventEmissionIntervalTests.swift +105 -0
- package/ios/AudioStudioTests/Info.plist +22 -0
- package/ios/AudioStudioTests/README.md +39 -0
- package/ios/AudioStudioTests/SimpleAudioTest.swift +98 -0
- package/ios/AudioStudioTests/TestAudioGenerator.swift +75 -0
- package/ios/DataPoint.swift +54 -0
- package/ios/DecodingConfig.swift +59 -0
- package/ios/FFT.swift +62 -0
- package/ios/Features.swift +95 -0
- package/ios/ISSUE_IOS.md +68 -0
- package/ios/Logger.swift +39 -0
- package/ios/MelSpectrogramWrapper.h +30 -0
- package/ios/MelSpectrogramWrapper.mm +97 -0
- package/ios/NotificationExtension.swift +15 -0
- package/ios/RecordingResult.swift +22 -0
- package/ios/RecordingSettings.swift +311 -0
- package/ios/WaveformExtractor.swift +105 -0
- package/ios/tests/README.md +41 -0
- package/ios/tests/integration/buffer_and_fallback_test.swift +178 -0
- package/ios/tests/integration/buffer_duration_test.swift +185 -0
- package/ios/tests/integration/compressed_only_output_test.swift +271 -0
- package/ios/tests/integration/output_control_test.swift +322 -0
- package/ios/tests/integration/run_integration_tests.sh +37 -0
- package/ios/tests/opus_support_test_macos.swift +154 -0
- package/ios/tests/standalone/audio_processing_test.swift +144 -0
- package/ios/tests/standalone/audio_recording_test.swift +277 -0
- package/ios/tests/standalone/audio_streaming_test.swift +249 -0
- package/ios/tests/standalone/standalone_test.swift +144 -0
- package/package.json +146 -0
- package/plugin/build/index.cjs +194 -0
- package/plugin/build/index.d.cts +22 -0
- package/plugin/build/index.js +194 -0
- package/plugin/src/index.ts +285 -0
- package/plugin/tsconfig.json +10 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/prebuilt/wasm/mel-spectrogram.js +18 -0
- package/src/AudioAnalysis/AudioAnalysis.types.ts +226 -0
- package/src/AudioAnalysis/audio-features-wasm.d.ts +37 -0
- package/src/AudioAnalysis/audioFeaturesWasm.ts +200 -0
- package/src/AudioAnalysis/extractAudioAnalysis.ts +350 -0
- package/src/AudioAnalysis/extractAudioData.ts +17 -0
- package/src/AudioAnalysis/extractMelSpectrogram.ts +140 -0
- package/src/AudioAnalysis/extractPreview.ts +34 -0
- package/src/AudioAnalysis/extractWaveform.ts +22 -0
- package/src/AudioAnalysis/mel-spectrogram-wasm.d.ts +48 -0
- package/src/AudioAnalysis/melSpectrogramWasm.ts +179 -0
- package/src/AudioDeviceManager.ts +800 -0
- package/src/AudioRecorder.provider.tsx +57 -0
- package/src/AudioStudio.native.ts +6 -0
- package/src/AudioStudio.types.ts +899 -0
- package/src/AudioStudio.web.ts +911 -0
- package/src/AudioStudioModule.ts +984 -0
- package/src/WebRecorder.web.ts +1114 -0
- package/src/constants/platformLimitations.ts +118 -0
- package/src/constants.ts +21 -0
- package/src/events.ts +63 -0
- package/src/hooks/useAudioDevices.ts +213 -0
- package/src/index.ts +67 -0
- package/src/trimAudio.ts +94 -0
- package/src/types/crc-32.d.ts +9 -0
- package/src/useAudioRecorder.tsx +784 -0
- package/src/utils/BlobFix.ts +561 -0
- package/src/utils/audioProcessing.ts +205 -0
- package/src/utils/cleanNativeOptions.ts +18 -0
- package/src/utils/concatenateBuffers.ts +24 -0
- package/src/utils/convertPCMToFloat32.ts +170 -0
- package/src/utils/crc32.ts +59 -0
- package/src/utils/encodingToBitDepth.ts +18 -0
- package/src/utils/getWavFileInfo.ts +132 -0
- package/src/utils/writeWavHeader.ts +115 -0
- package/src/workers/InlineFeaturesExtractor.web.tsx +291 -0
- package/src/workers/inlineAudioWebWorker.web.tsx +186 -0
- package/src/workers/wasmGlueString.web.ts +23 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-specific audio recording limitations and capabilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Platform } from 'react-native'
|
|
6
|
+
|
|
7
|
+
import { EncodingType, BitDepth } from '../AudioStudio.types'
|
|
8
|
+
|
|
9
|
+
export interface PlatformCapabilities {
|
|
10
|
+
supportedEncodings: EncodingType[]
|
|
11
|
+
supportedBitDepths: BitDepth[]
|
|
12
|
+
notes: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const PLATFORM_CAPABILITIES: Record<string, PlatformCapabilities> = {
|
|
16
|
+
ios: {
|
|
17
|
+
supportedEncodings: ['pcm_16bit', 'pcm_32bit'],
|
|
18
|
+
supportedBitDepths: [16, 32],
|
|
19
|
+
notes: [
|
|
20
|
+
'8-bit PCM is not natively supported by iOS AVAudioFormat',
|
|
21
|
+
'Recording with 8-bit will fallback to 16-bit',
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
android: {
|
|
25
|
+
supportedEncodings: ['pcm_8bit', 'pcm_16bit', 'pcm_32bit'],
|
|
26
|
+
supportedBitDepths: [8, 16, 32],
|
|
27
|
+
notes: ['All PCM formats are fully supported'],
|
|
28
|
+
},
|
|
29
|
+
web: {
|
|
30
|
+
supportedEncodings: ['pcm_16bit', 'pcm_32bit'],
|
|
31
|
+
supportedBitDepths: [16, 32],
|
|
32
|
+
notes: [
|
|
33
|
+
'Web Audio API typically works with 32-bit float',
|
|
34
|
+
'8-bit is not commonly supported in browsers',
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get the current platform's audio capabilities
|
|
41
|
+
*/
|
|
42
|
+
export function getPlatformCapabilities(): PlatformCapabilities {
|
|
43
|
+
return PLATFORM_CAPABILITIES[Platform.OS] || PLATFORM_CAPABILITIES.web
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check if a specific encoding is supported on the current platform
|
|
48
|
+
*/
|
|
49
|
+
export function isEncodingSupported(encoding: EncodingType): boolean {
|
|
50
|
+
const capabilities = getPlatformCapabilities()
|
|
51
|
+
return capabilities.supportedEncodings.includes(encoding)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if a specific bit depth is supported on the current platform
|
|
56
|
+
*/
|
|
57
|
+
export function isBitDepthSupported(bitDepth: BitDepth): boolean {
|
|
58
|
+
const capabilities = getPlatformCapabilities()
|
|
59
|
+
return capabilities.supportedBitDepths.includes(bitDepth)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get a fallback encoding if the requested one is not supported
|
|
64
|
+
*/
|
|
65
|
+
export function getFallbackEncoding(
|
|
66
|
+
requestedEncoding: EncodingType
|
|
67
|
+
): EncodingType {
|
|
68
|
+
if (isEncodingSupported(requestedEncoding)) {
|
|
69
|
+
return requestedEncoding
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Default fallback is 16-bit PCM (supported on all platforms)
|
|
73
|
+
return 'pcm_16bit'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get a fallback bit depth if the requested one is not supported
|
|
78
|
+
*/
|
|
79
|
+
export function getFallbackBitDepth(requestedBitDepth: BitDepth): BitDepth {
|
|
80
|
+
if (isBitDepthSupported(requestedBitDepth)) {
|
|
81
|
+
return requestedBitDepth
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Default fallback is 16-bit (supported on all platforms)
|
|
85
|
+
return 16
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validate and adjust recording configuration based on platform limitations
|
|
90
|
+
*/
|
|
91
|
+
export function validateRecordingConfig(config: { encoding?: EncodingType }): {
|
|
92
|
+
encoding: EncodingType
|
|
93
|
+
warnings: string[]
|
|
94
|
+
} {
|
|
95
|
+
const warnings: string[] = []
|
|
96
|
+
const capabilities = getPlatformCapabilities()
|
|
97
|
+
|
|
98
|
+
let encoding = config.encoding || 'pcm_16bit'
|
|
99
|
+
|
|
100
|
+
// Check if encoding is supported
|
|
101
|
+
if (!isEncodingSupported(encoding)) {
|
|
102
|
+
const fallback = getFallbackEncoding(encoding)
|
|
103
|
+
warnings.push(
|
|
104
|
+
`${encoding} is not supported on ${Platform.OS}. Using ${fallback} instead.`
|
|
105
|
+
)
|
|
106
|
+
encoding = fallback
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add platform-specific notes if there were changes
|
|
110
|
+
if (warnings.length > 0) {
|
|
111
|
+
warnings.push(...capabilities.notes)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
encoding,
|
|
116
|
+
warnings,
|
|
117
|
+
}
|
|
118
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// packages/audio-studio/src/constants.ts
|
|
2
|
+
import { Platform } from 'react-native'
|
|
3
|
+
|
|
4
|
+
import { BitDepth, SampleRate } from './AudioStudio.types'
|
|
5
|
+
|
|
6
|
+
export const isWeb = Platform.OS === 'web'
|
|
7
|
+
export const DEBUG_NAMESPACE = 'audio-studio'
|
|
8
|
+
|
|
9
|
+
// Constants for identifying chunks in a WAV file
|
|
10
|
+
export const RIFF_HEADER = 0x52494646 // "RIFF"
|
|
11
|
+
export const WAVE_HEADER = 0x57415645 // "WAVE"
|
|
12
|
+
export const FMT_CHUNK_ID = 0x666d7420 // "fmt "
|
|
13
|
+
export const DATA_CHUNK_ID = 0x64617461 // "data"
|
|
14
|
+
export const INFO_CHUNK_ID = 0x494e464f // "INFO"
|
|
15
|
+
|
|
16
|
+
// Default values
|
|
17
|
+
export const DEFAULT_SAMPLE_RATE: SampleRate = 16000
|
|
18
|
+
export const DEFAULT_BIT_DEPTH: BitDepth = 32
|
|
19
|
+
export const DEFAULT_INTERVAL_MS = 1000
|
|
20
|
+
export const DEFAULT_ANALYSIS_INTERVAL_MS = 500
|
|
21
|
+
export const DEFAULT_MAX_BUFFER_SIZE = 100
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// packages/audio-studio/src/events.ts
|
|
2
|
+
|
|
3
|
+
import { LegacyEventEmitter, type EventSubscription } from 'expo-modules-core'
|
|
4
|
+
|
|
5
|
+
import { AudioAnalysis } from './AudioAnalysis/AudioAnalysis.types'
|
|
6
|
+
import { RecordingInterruptionEvent } from './AudioStudio.types'
|
|
7
|
+
import AudioStudioModule from './AudioStudioModule'
|
|
8
|
+
|
|
9
|
+
const emitter = new LegacyEventEmitter(AudioStudioModule)
|
|
10
|
+
|
|
11
|
+
// Internal event payload from native module
|
|
12
|
+
export interface AudioEventPayload {
|
|
13
|
+
encoded?: string
|
|
14
|
+
/** Float32 samples in [-1, 1] — sent by native when streamFormat='float32'.
|
|
15
|
+
* Android new arch delivers Float32Array; iOS delivers number[]. */
|
|
16
|
+
pcmFloat32?: Float32Array | number[]
|
|
17
|
+
buffer?: Float32Array
|
|
18
|
+
fileUri: string
|
|
19
|
+
lastEmittedSize: number
|
|
20
|
+
position: number
|
|
21
|
+
deltaSize: number
|
|
22
|
+
totalSize: number
|
|
23
|
+
mimeType: string
|
|
24
|
+
streamUuid: string
|
|
25
|
+
compression?: {
|
|
26
|
+
data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk
|
|
27
|
+
position: number
|
|
28
|
+
eventDataSize: number
|
|
29
|
+
totalSize: number
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function addAudioEventListener(
|
|
34
|
+
listener: (event: AudioEventPayload) => Promise<void>
|
|
35
|
+
): EventSubscription {
|
|
36
|
+
return emitter.addListener<AudioEventPayload>('AudioData', listener)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Only aliasing the AudioAnalysis type for the event payload
|
|
40
|
+
export interface AudioAnalysisEvent extends AudioAnalysis {}
|
|
41
|
+
|
|
42
|
+
export function addAudioAnalysisListener(
|
|
43
|
+
listener: (event: AudioAnalysisEvent) => Promise<void>
|
|
44
|
+
): EventSubscription {
|
|
45
|
+
return emitter.addListener<AudioAnalysisEvent>('AudioAnalysis', listener)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function addRecordingInterruptionListener(
|
|
49
|
+
listener: (event: RecordingInterruptionEvent) => void
|
|
50
|
+
): EventSubscription {
|
|
51
|
+
// Add debug logging
|
|
52
|
+
console.debug('Adding recording interruption listener')
|
|
53
|
+
|
|
54
|
+
const subscription = emitter.addListener<RecordingInterruptionEvent>(
|
|
55
|
+
'onRecordingInterrupted', // Make sure this matches the native event name
|
|
56
|
+
(event) => {
|
|
57
|
+
console.debug('Recording interruption event received:', event)
|
|
58
|
+
listener(event)
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return subscription
|
|
63
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState, useId } from 'react'
|
|
2
|
+
|
|
3
|
+
import { audioDeviceManager } from '../AudioDeviceManager'
|
|
4
|
+
import { AudioDevice } from '../AudioStudio.types'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* React hook for managing audio input devices
|
|
8
|
+
*/
|
|
9
|
+
export function useAudioDevices() {
|
|
10
|
+
const [devices, setDevices] = useState<AudioDevice[]>([])
|
|
11
|
+
const [currentDevice, setCurrentDevice] = useState<AudioDevice | null>(null)
|
|
12
|
+
const [loading, setLoading] = useState(true)
|
|
13
|
+
const [error, setError] = useState<Error | null>(null)
|
|
14
|
+
|
|
15
|
+
// Generate unique instance ID for debugging
|
|
16
|
+
const instanceId = useId().replace(/:/g, '').slice(0, 5)
|
|
17
|
+
|
|
18
|
+
// Load devices on mount
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
let isMounted = true
|
|
21
|
+
|
|
22
|
+
const loadDevices = async () => {
|
|
23
|
+
try {
|
|
24
|
+
setLoading(true)
|
|
25
|
+
setError(null)
|
|
26
|
+
|
|
27
|
+
// Load available devices
|
|
28
|
+
const availableDevices =
|
|
29
|
+
await audioDeviceManager.getAvailableDevices()
|
|
30
|
+
if (isMounted) setDevices(availableDevices)
|
|
31
|
+
|
|
32
|
+
// Get current device
|
|
33
|
+
const device = await audioDeviceManager.getCurrentDevice()
|
|
34
|
+
if (isMounted) setCurrentDevice(device)
|
|
35
|
+
} catch (err) {
|
|
36
|
+
audioDeviceManager
|
|
37
|
+
.getLogger()
|
|
38
|
+
?.error('Failed to load audio devices:', err)
|
|
39
|
+
if (isMounted)
|
|
40
|
+
setError(
|
|
41
|
+
err instanceof Error
|
|
42
|
+
? err
|
|
43
|
+
: new Error('Failed to load audio devices')
|
|
44
|
+
)
|
|
45
|
+
} finally {
|
|
46
|
+
if (isMounted) setLoading(false)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
loadDevices()
|
|
51
|
+
|
|
52
|
+
// Set up device change listener
|
|
53
|
+
const removeListener = audioDeviceManager.addDeviceChangeListener(
|
|
54
|
+
(updatedDevices: AudioDevice[]) => {
|
|
55
|
+
audioDeviceManager
|
|
56
|
+
.getLogger()
|
|
57
|
+
?.debug(
|
|
58
|
+
`🎛️ useAudioDevices [${instanceId}] received device change. Count: ${updatedDevices.length}`
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if (isMounted) {
|
|
62
|
+
setDevices(updatedDevices)
|
|
63
|
+
|
|
64
|
+
// If our current device is no longer available, update it
|
|
65
|
+
if (
|
|
66
|
+
currentDevice &&
|
|
67
|
+
!updatedDevices.some(
|
|
68
|
+
(d: AudioDevice) => d.id === currentDevice.id
|
|
69
|
+
)
|
|
70
|
+
) {
|
|
71
|
+
audioDeviceManager
|
|
72
|
+
.getLogger()
|
|
73
|
+
?.debug(
|
|
74
|
+
`🎛️ useAudioDevices [${instanceId}] Current device ${currentDevice.id} no longer available, updating`
|
|
75
|
+
)
|
|
76
|
+
audioDeviceManager
|
|
77
|
+
.getCurrentDevice()
|
|
78
|
+
.then((newDevice: AudioDevice | null) => {
|
|
79
|
+
if (isMounted) {
|
|
80
|
+
setCurrentDevice(newDevice)
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
return () => {
|
|
89
|
+
isMounted = false
|
|
90
|
+
removeListener()
|
|
91
|
+
}
|
|
92
|
+
}, [])
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Select a specific audio input device
|
|
96
|
+
* @param deviceId The ID of the device to select
|
|
97
|
+
* @returns Promise resolving to a boolean indicating success
|
|
98
|
+
*/
|
|
99
|
+
const selectDevice = useCallback(
|
|
100
|
+
async (deviceId: string): Promise<boolean> => {
|
|
101
|
+
try {
|
|
102
|
+
setLoading(true)
|
|
103
|
+
setError(null)
|
|
104
|
+
|
|
105
|
+
const success = await audioDeviceManager.selectDevice(deviceId)
|
|
106
|
+
|
|
107
|
+
if (success) {
|
|
108
|
+
// Get the updated current device after selection
|
|
109
|
+
const device = await audioDeviceManager.getCurrentDevice()
|
|
110
|
+
setCurrentDevice(device)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return success
|
|
114
|
+
} catch (err) {
|
|
115
|
+
audioDeviceManager
|
|
116
|
+
.getLogger()
|
|
117
|
+
?.error('Failed to select audio device:', err)
|
|
118
|
+
setError(
|
|
119
|
+
err instanceof Error
|
|
120
|
+
? err
|
|
121
|
+
: new Error('Failed to select audio device')
|
|
122
|
+
)
|
|
123
|
+
return false
|
|
124
|
+
} finally {
|
|
125
|
+
setLoading(false)
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
[]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Reset to the default audio input device
|
|
133
|
+
* @returns Promise resolving to a boolean indicating success
|
|
134
|
+
*/
|
|
135
|
+
const resetToDefaultDevice = useCallback(async (): Promise<boolean> => {
|
|
136
|
+
try {
|
|
137
|
+
setLoading(true)
|
|
138
|
+
setError(null)
|
|
139
|
+
|
|
140
|
+
const success = await audioDeviceManager.resetToDefaultDevice()
|
|
141
|
+
|
|
142
|
+
if (success) {
|
|
143
|
+
// Get the updated current device after reset
|
|
144
|
+
const device = await audioDeviceManager.getCurrentDevice()
|
|
145
|
+
setCurrentDevice(device)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return success
|
|
149
|
+
} catch (err) {
|
|
150
|
+
audioDeviceManager
|
|
151
|
+
.getLogger()
|
|
152
|
+
?.error('Failed to reset to default audio device:', err)
|
|
153
|
+
setError(
|
|
154
|
+
err instanceof Error
|
|
155
|
+
? err
|
|
156
|
+
: new Error('Failed to reset to default audio device')
|
|
157
|
+
)
|
|
158
|
+
return false
|
|
159
|
+
} finally {
|
|
160
|
+
setLoading(false)
|
|
161
|
+
}
|
|
162
|
+
}, [])
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Refresh the list of available devices
|
|
166
|
+
*/
|
|
167
|
+
const refreshDevices = useCallback(async (): Promise<AudioDevice[]> => {
|
|
168
|
+
try {
|
|
169
|
+
setLoading(true)
|
|
170
|
+
setError(null)
|
|
171
|
+
|
|
172
|
+
const updatedDevices = await audioDeviceManager.refreshDevices()
|
|
173
|
+
setDevices(updatedDevices)
|
|
174
|
+
|
|
175
|
+
// Also refresh the current device
|
|
176
|
+
const device = await audioDeviceManager.getCurrentDevice()
|
|
177
|
+
setCurrentDevice(device)
|
|
178
|
+
|
|
179
|
+
return updatedDevices
|
|
180
|
+
} catch (err) {
|
|
181
|
+
audioDeviceManager
|
|
182
|
+
.getLogger()
|
|
183
|
+
?.error('Failed to refresh audio devices:', err)
|
|
184
|
+
setError(
|
|
185
|
+
err instanceof Error
|
|
186
|
+
? err
|
|
187
|
+
: new Error('Failed to refresh audio devices')
|
|
188
|
+
)
|
|
189
|
+
return []
|
|
190
|
+
} finally {
|
|
191
|
+
setLoading(false)
|
|
192
|
+
}
|
|
193
|
+
}, [])
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Initialize device detection
|
|
197
|
+
* Useful for restarting device detection if it failed initially
|
|
198
|
+
*/
|
|
199
|
+
const initializeDeviceDetection = useCallback(() => {
|
|
200
|
+
audioDeviceManager.initializeDeviceDetection()
|
|
201
|
+
}, [])
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
devices,
|
|
205
|
+
currentDevice,
|
|
206
|
+
loading,
|
|
207
|
+
error,
|
|
208
|
+
selectDevice,
|
|
209
|
+
resetToDefaultDevice,
|
|
210
|
+
refreshDevices,
|
|
211
|
+
initializeDeviceDetection,
|
|
212
|
+
}
|
|
213
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
extractRawWavAnalysis,
|
|
5
|
+
extractAudioAnalysis,
|
|
6
|
+
} from './AudioAnalysis/extractAudioAnalysis'
|
|
7
|
+
import { extractAudioData } from './AudioAnalysis/extractAudioData'
|
|
8
|
+
import {
|
|
9
|
+
extractMelSpectrogram,
|
|
10
|
+
MAX_DURATION_MS,
|
|
11
|
+
} from './AudioAnalysis/extractMelSpectrogram'
|
|
12
|
+
import { extractPreview } from './AudioAnalysis/extractPreview'
|
|
13
|
+
import {
|
|
14
|
+
initMelStreamingWasm,
|
|
15
|
+
computeMelFrameWasm,
|
|
16
|
+
} from './AudioAnalysis/melSpectrogramWasm'
|
|
17
|
+
import {
|
|
18
|
+
AudioRecorderProvider,
|
|
19
|
+
useSharedAudioRecorder,
|
|
20
|
+
} from './AudioRecorder.provider'
|
|
21
|
+
import AudioStudioModule from './AudioStudioModule'
|
|
22
|
+
import { trimAudio } from './trimAudio'
|
|
23
|
+
import { useAudioRecorder } from './useAudioRecorder'
|
|
24
|
+
|
|
25
|
+
export * from './utils/convertPCMToFloat32'
|
|
26
|
+
export * from './utils/getWavFileInfo'
|
|
27
|
+
export * from './utils/writeWavHeader'
|
|
28
|
+
|
|
29
|
+
// Export platform capabilities
|
|
30
|
+
export {
|
|
31
|
+
getPlatformCapabilities,
|
|
32
|
+
isEncodingSupported,
|
|
33
|
+
isBitDepthSupported,
|
|
34
|
+
getFallbackEncoding,
|
|
35
|
+
getFallbackBitDepth,
|
|
36
|
+
validateRecordingConfig,
|
|
37
|
+
type PlatformCapabilities,
|
|
38
|
+
} from './constants/platformLimitations'
|
|
39
|
+
|
|
40
|
+
// Export AudioDeviceManager
|
|
41
|
+
export { AudioDeviceManager, audioDeviceManager } from './AudioDeviceManager'
|
|
42
|
+
|
|
43
|
+
// Export useAudioDevices hook
|
|
44
|
+
export { useAudioDevices } from './hooks/useAudioDevices'
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
AudioRecorderProvider,
|
|
48
|
+
AudioStudioModule,
|
|
49
|
+
extractRawWavAnalysis,
|
|
50
|
+
extractAudioAnalysis,
|
|
51
|
+
extractPreview,
|
|
52
|
+
trimAudio,
|
|
53
|
+
extractAudioData,
|
|
54
|
+
extractMelSpectrogram,
|
|
55
|
+
initMelStreamingWasm,
|
|
56
|
+
computeMelFrameWasm,
|
|
57
|
+
MAX_DURATION_MS,
|
|
58
|
+
useAudioRecorder,
|
|
59
|
+
useSharedAudioRecorder,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Export all types
|
|
63
|
+
export type * from './AudioAnalysis/AudioAnalysis.types'
|
|
64
|
+
export type * from './AudioStudio.types'
|
|
65
|
+
|
|
66
|
+
/** @deprecated Use AudioStudioModule instead */
|
|
67
|
+
export const ExpoAudioStreamModule = AudioStudioModule
|
package/src/trimAudio.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { LegacyEventEmitter, type EventSubscription } from 'expo-modules-core'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
TrimAudioOptions,
|
|
5
|
+
TrimAudioResult,
|
|
6
|
+
TrimProgressEvent,
|
|
7
|
+
} from './AudioStudio.types'
|
|
8
|
+
import AudioStudioModule from './AudioStudioModule'
|
|
9
|
+
import { cleanNativeOptions } from './utils/cleanNativeOptions'
|
|
10
|
+
|
|
11
|
+
// Create a single emitter instance
|
|
12
|
+
const emitter = new LegacyEventEmitter(AudioStudioModule)
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Trims an audio file based on the provided options.
|
|
16
|
+
*
|
|
17
|
+
* @experimental This API is experimental and not fully optimized for production use.
|
|
18
|
+
* Performance may vary based on file size and device capabilities.
|
|
19
|
+
* Future versions may include breaking changes.
|
|
20
|
+
*
|
|
21
|
+
* @param options Configuration options for the trimming operation
|
|
22
|
+
* @param progressCallback Optional callback to receive progress updates
|
|
23
|
+
* @returns Promise resolving to the trimmed audio file information, including processing time
|
|
24
|
+
*/
|
|
25
|
+
export async function trimAudio(
|
|
26
|
+
options: TrimAudioOptions,
|
|
27
|
+
progressCallback?: (event: TrimProgressEvent) => void
|
|
28
|
+
): Promise<TrimAudioResult> {
|
|
29
|
+
// Validation
|
|
30
|
+
if (!options.fileUri) {
|
|
31
|
+
throw new Error('fileUri is required')
|
|
32
|
+
}
|
|
33
|
+
const mode = options.mode ?? 'single'
|
|
34
|
+
if (mode === 'single') {
|
|
35
|
+
if (
|
|
36
|
+
options.startTimeMs === undefined &&
|
|
37
|
+
options.endTimeMs === undefined
|
|
38
|
+
) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
'At least one of startTimeMs or endTimeMs must be provided in single mode'
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
} else if (mode === 'keep' || mode === 'remove') {
|
|
44
|
+
if (!options.ranges || options.ranges.length === 0) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'ranges must be provided and non-empty for keep or remove modes'
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Invalid mode: ${mode}. Must be 'single', 'keep', or 'remove'`
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Set up progress event listener if callback is provided
|
|
56
|
+
let subscription: EventSubscription | undefined
|
|
57
|
+
if (progressCallback) {
|
|
58
|
+
subscription = emitter.addListener(
|
|
59
|
+
'TrimProgress',
|
|
60
|
+
(event: TrimProgressEvent) => {
|
|
61
|
+
progressCallback(event)
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
// Clean non-serializable/undefined values to avoid Android Kotlin bridge crash
|
|
68
|
+
const result = await AudioStudioModule.trimAudio(
|
|
69
|
+
cleanNativeOptions(options)
|
|
70
|
+
)
|
|
71
|
+
return result
|
|
72
|
+
} finally {
|
|
73
|
+
if (subscription) {
|
|
74
|
+
subscription.remove()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Simplified version of trimAudio that returns only the URI of the trimmed file.
|
|
81
|
+
*
|
|
82
|
+
* @experimental This API is experimental and not fully optimized for production use.
|
|
83
|
+
* Performance may vary based on file size and device capabilities.
|
|
84
|
+
* Future versions may include breaking changes.
|
|
85
|
+
*
|
|
86
|
+
* @param options Configuration options for the trimming operation
|
|
87
|
+
* @returns Promise resolving to the URI of the trimmed audio file
|
|
88
|
+
*/
|
|
89
|
+
export async function trimAudioSimple(
|
|
90
|
+
options: TrimAudioOptions
|
|
91
|
+
): Promise<string> {
|
|
92
|
+
const result = await trimAudio(options)
|
|
93
|
+
return result.uri
|
|
94
|
+
}
|