@siteed/expo-audio-studio 2.18.5 → 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/README.md +13 -297
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +6 -135
- package/CHANGELOG.md +0 -493
- package/LICENSE +0 -21
- package/android/build.gradle +0 -129
- 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/audiostream/AudioProcessorInstrumentedTest.kt +0 -197
- package/android/src/androidTest/java/net/siteed/audiostream/AudioRecorderInstrumentedTest.kt +0 -541
- package/android/src/androidTest/java/net/siteed/audiostream/AudioRecorderPerformanceInstrumentedTest.kt +0 -234
- package/android/src/androidTest/java/net/siteed/audiostream/integration/AudioFocusStrategyIntegrationTest.kt +0 -332
- package/android/src/androidTest/java/net/siteed/audiostream/integration/BufferDurationIntegrationTest.kt +0 -324
- package/android/src/androidTest/java/net/siteed/audiostream/integration/CompressedOnlyOutputTest.kt +0 -253
- package/android/src/androidTest/java/net/siteed/audiostream/integration/DeviceDisconnectionFallbackTest.kt +0 -218
- package/android/src/androidTest/java/net/siteed/audiostream/integration/EventEmissionIntervalTest.kt +0 -120
- package/android/src/androidTest/java/net/siteed/audiostream/integration/M4aFormatTest.kt +0 -345
- package/android/src/androidTest/java/net/siteed/audiostream/integration/OutputControlIntegrationTest.kt +0 -340
- package/android/src/androidTest/java/net/siteed/audiostream/integration/PcmStreamingDurationTest.kt +0 -252
- package/android/src/androidTest/java/net/siteed/audiostream/integration/README.md +0 -95
- package/android/src/androidTest/java/net/siteed/audiostream/integration/run_integration_tests.sh +0 -43
- package/android/src/main/AndroidManifest.xml +0 -30
- package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +0 -188
- package/android/src/main/java/net/siteed/audiostream/AudioDataEncoder.kt +0 -9
- package/android/src/main/java/net/siteed/audiostream/AudioDeviceManager.kt +0 -1741
- package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +0 -136
- package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +0 -354
- package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +0 -439
- package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +0 -2237
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -2141
- package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +0 -167
- package/android/src/main/java/net/siteed/audiostream/AudioTrimmer.kt +0 -1099
- package/android/src/main/java/net/siteed/audiostream/Constants.kt +0 -37
- package/android/src/main/java/net/siteed/audiostream/EventSender.kt +0 -7
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +0 -1113
- package/android/src/main/java/net/siteed/audiostream/FFT.kt +0 -99
- package/android/src/main/java/net/siteed/audiostream/Features.kt +0 -98
- package/android/src/main/java/net/siteed/audiostream/LogUtils.kt +0 -93
- package/android/src/main/java/net/siteed/audiostream/NotificationConfig.kt +0 -72
- package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +0 -68
- package/android/src/main/java/net/siteed/audiostream/RecordingActionReceiver.kt +0 -59
- package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +0 -257
- package/android/src/main/java/net/siteed/audiostream/WaveformConfig.kt +0 -19
- package/android/src/main/java/net/siteed/audiostream/WaveformRenderer.kt +0 -159
- package/android/src/main/res/drawable/ic_default_action_icon.xml +0 -16
- package/android/src/main/res/drawable/ic_microphone.xml +0 -13
- package/android/src/main/res/drawable/ic_pause.xml +0 -10
- package/android/src/main/res/drawable/ic_play.xml +0 -10
- package/android/src/main/res/drawable/ic_stop.xml +0 -10
- package/android/src/main/res/layout/notification_recording.xml +0 -37
- package/android/src/test/java/net/siteed/audiostream/AudioFileHandlerTest.kt +0 -279
- package/android/src/test/java/net/siteed/audiostream/AudioFocusStrategyTest.kt +0 -249
- package/android/src/test/java/net/siteed/audiostream/AudioFormatTest.kt +0 -151
- package/android/src/test/java/net/siteed/audiostream/AudioFormatUtilsTest.kt +0 -273
- package/android/src/test/java/net/siteed/audiostream/DeviceDisconnectionFallbackUnitTest.kt +0 -140
- package/android/src/test/resources/chorus.wav +0 -0
- package/android/src/test/resources/generate_test_audio.py +0 -94
- 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 +0 -3
- package/build/cjs/AudioAnalysis/AudioAnalysis.types.js +0 -4
- package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
- package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +0 -210
- package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
- package/build/cjs/AudioAnalysis/extractAudioData.js +0 -21
- package/build/cjs/AudioAnalysis/extractAudioData.js.map +0 -1
- package/build/cjs/AudioAnalysis/extractMelSpectrogram.js +0 -92
- package/build/cjs/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
- package/build/cjs/AudioAnalysis/extractPreview.js +0 -28
- package/build/cjs/AudioAnalysis/extractPreview.js.map +0 -1
- package/build/cjs/AudioAnalysis/extractWaveform.js +0 -18
- package/build/cjs/AudioAnalysis/extractWaveform.js.map +0 -1
- package/build/cjs/AudioDeviceManager.js +0 -689
- package/build/cjs/AudioDeviceManager.js.map +0 -1
- package/build/cjs/AudioRecorder.provider.js +0 -78
- package/build/cjs/AudioRecorder.provider.js.map +0 -1
- package/build/cjs/ExpoAudioStream.native.js +0 -8
- package/build/cjs/ExpoAudioStream.native.js.map +0 -1
- package/build/cjs/ExpoAudioStream.types.js +0 -11
- package/build/cjs/ExpoAudioStream.types.js.map +0 -1
- package/build/cjs/ExpoAudioStream.web.js +0 -708
- package/build/cjs/ExpoAudioStream.web.js.map +0 -1
- package/build/cjs/ExpoAudioStreamModule.js +0 -718
- package/build/cjs/ExpoAudioStreamModule.js.map +0 -1
- package/build/cjs/WebRecorder.web.js +0 -777
- package/build/cjs/WebRecorder.web.js.map +0 -1
- package/build/cjs/constants/platformLimitations.js +0 -99
- package/build/cjs/constants/platformLimitations.js.map +0 -1
- package/build/cjs/constants.js +0 -17
- package/build/cjs/constants.js.map +0 -1
- package/build/cjs/events.js +0 -29
- package/build/cjs/events.js.map +0 -1
- package/build/cjs/hooks/useAudioDevices.js +0 -179
- package/build/cjs/hooks/useAudioDevices.js.map +0 -1
- package/build/cjs/index.js +0 -58
- package/build/cjs/index.js.map +0 -1
- package/build/cjs/trimAudio.js +0 -76
- package/build/cjs/trimAudio.js.map +0 -1
- package/build/cjs/useAudioRecorder.js +0 -518
- package/build/cjs/useAudioRecorder.js.map +0 -1
- package/build/cjs/utils/BlobFix.js +0 -502
- package/build/cjs/utils/BlobFix.js.map +0 -1
- package/build/cjs/utils/audioProcessing.js +0 -136
- package/build/cjs/utils/audioProcessing.js.map +0 -1
- package/build/cjs/utils/cleanNativeOptions.js +0 -22
- package/build/cjs/utils/cleanNativeOptions.js.map +0 -1
- package/build/cjs/utils/concatenateBuffers.js +0 -25
- package/build/cjs/utils/concatenateBuffers.js.map +0 -1
- package/build/cjs/utils/convertPCMToFloat32.js +0 -124
- package/build/cjs/utils/convertPCMToFloat32.js.map +0 -1
- package/build/cjs/utils/crc32.js +0 -52
- package/build/cjs/utils/crc32.js.map +0 -1
- package/build/cjs/utils/encodingToBitDepth.js +0 -17
- package/build/cjs/utils/encodingToBitDepth.js.map +0 -1
- package/build/cjs/utils/getWavFileInfo.js +0 -96
- package/build/cjs/utils/getWavFileInfo.js.map +0 -1
- package/build/cjs/utils/writeWavHeader.js +0 -88
- package/build/cjs/utils/writeWavHeader.js.map +0 -1
- package/build/cjs/workers/InlineFeaturesExtractor.web.js +0 -859
- package/build/cjs/workers/InlineFeaturesExtractor.web.js.map +0 -1
- package/build/cjs/workers/inlineAudioWebWorker.web.js +0 -184
- package/build/cjs/workers/inlineAudioWebWorker.web.js.map +0 -1
- package/build/esm/AudioAnalysis/AudioAnalysis.types.js +0 -3
- package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
- package/build/esm/AudioAnalysis/extractAudioAnalysis.js +0 -202
- package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
- package/build/esm/AudioAnalysis/extractAudioData.js +0 -14
- package/build/esm/AudioAnalysis/extractAudioData.js.map +0 -1
- package/build/esm/AudioAnalysis/extractMelSpectrogram.js +0 -89
- package/build/esm/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
- package/build/esm/AudioAnalysis/extractPreview.js +0 -25
- package/build/esm/AudioAnalysis/extractPreview.js.map +0 -1
- package/build/esm/AudioAnalysis/extractWaveform.js +0 -11
- package/build/esm/AudioAnalysis/extractWaveform.js.map +0 -1
- package/build/esm/AudioDeviceManager.js +0 -682
- package/build/esm/AudioDeviceManager.js.map +0 -1
- package/build/esm/AudioRecorder.provider.js +0 -40
- package/build/esm/AudioRecorder.provider.js.map +0 -1
- package/build/esm/ExpoAudioStream.native.js +0 -6
- package/build/esm/ExpoAudioStream.native.js.map +0 -1
- package/build/esm/ExpoAudioStream.types.js +0 -8
- package/build/esm/ExpoAudioStream.types.js.map +0 -1
- package/build/esm/ExpoAudioStream.web.js +0 -704
- package/build/esm/ExpoAudioStream.web.js.map +0 -1
- package/build/esm/ExpoAudioStreamModule.js +0 -713
- package/build/esm/ExpoAudioStreamModule.js.map +0 -1
- package/build/esm/WebRecorder.web.js +0 -773
- package/build/esm/WebRecorder.web.js.map +0 -1
- package/build/esm/constants/platformLimitations.js +0 -90
- package/build/esm/constants/platformLimitations.js.map +0 -1
- package/build/esm/constants.js +0 -14
- package/build/esm/constants.js.map +0 -1
- package/build/esm/events.js +0 -21
- package/build/esm/events.js.map +0 -1
- package/build/esm/hooks/useAudioDevices.js +0 -176
- package/build/esm/hooks/useAudioDevices.js.map +0 -1
- package/build/esm/index.js +0 -20
- package/build/esm/index.js.map +0 -1
- package/build/esm/trimAudio.js +0 -69
- package/build/esm/trimAudio.js.map +0 -1
- package/build/esm/useAudioRecorder.js +0 -512
- package/build/esm/useAudioRecorder.js.map +0 -1
- package/build/esm/utils/BlobFix.js +0 -498
- package/build/esm/utils/BlobFix.js.map +0 -1
- package/build/esm/utils/audioProcessing.js +0 -133
- package/build/esm/utils/audioProcessing.js.map +0 -1
- package/build/esm/utils/cleanNativeOptions.js +0 -19
- package/build/esm/utils/cleanNativeOptions.js.map +0 -1
- package/build/esm/utils/concatenateBuffers.js +0 -21
- package/build/esm/utils/concatenateBuffers.js.map +0 -1
- package/build/esm/utils/convertPCMToFloat32.js +0 -120
- package/build/esm/utils/convertPCMToFloat32.js.map +0 -1
- package/build/esm/utils/crc32.js +0 -50
- package/build/esm/utils/crc32.js.map +0 -1
- package/build/esm/utils/encodingToBitDepth.js +0 -13
- package/build/esm/utils/encodingToBitDepth.js.map +0 -1
- package/build/esm/utils/getWavFileInfo.js +0 -92
- package/build/esm/utils/getWavFileInfo.js.map +0 -1
- package/build/esm/utils/writeWavHeader.js +0 -84
- package/build/esm/utils/writeWavHeader.js.map +0 -1
- package/build/esm/workers/InlineFeaturesExtractor.web.js +0 -856
- package/build/esm/workers/InlineFeaturesExtractor.web.js.map +0 -1
- package/build/esm/workers/inlineAudioWebWorker.web.js +0 -181
- package/build/esm/workers/inlineAudioWebWorker.web.js.map +0 -1
- package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +0 -196
- package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
- package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts +0 -74
- package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
- package/build/types/AudioAnalysis/extractAudioData.d.ts +0 -3
- package/build/types/AudioAnalysis/extractAudioData.d.ts.map +0 -1
- package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts +0 -14
- package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts.map +0 -1
- package/build/types/AudioAnalysis/extractPreview.d.ts +0 -11
- package/build/types/AudioAnalysis/extractPreview.d.ts.map +0 -1
- package/build/types/AudioAnalysis/extractWaveform.d.ts +0 -8
- package/build/types/AudioAnalysis/extractWaveform.d.ts.map +0 -1
- package/build/types/AudioDeviceManager.d.ts +0 -187
- package/build/types/AudioDeviceManager.d.ts.map +0 -1
- package/build/types/AudioRecorder.provider.d.ts +0 -11
- package/build/types/AudioRecorder.provider.d.ts.map +0 -1
- package/build/types/ExpoAudioStream.native.d.ts +0 -3
- package/build/types/ExpoAudioStream.native.d.ts.map +0 -1
- package/build/types/ExpoAudioStream.types.d.ts +0 -738
- package/build/types/ExpoAudioStream.types.d.ts.map +0 -1
- package/build/types/ExpoAudioStream.web.d.ts +0 -96
- package/build/types/ExpoAudioStream.web.d.ts.map +0 -1
- package/build/types/ExpoAudioStreamModule.d.ts +0 -3
- package/build/types/ExpoAudioStreamModule.d.ts.map +0 -1
- package/build/types/WebRecorder.web.d.ts +0 -198
- package/build/types/WebRecorder.web.d.ts.map +0 -1
- package/build/types/constants/platformLimitations.d.ts +0 -40
- package/build/types/constants/platformLimitations.d.ts.map +0 -1
- package/build/types/constants.d.ts +0 -11
- package/build/types/constants.d.ts.map +0 -1
- package/build/types/events.d.ts +0 -26
- package/build/types/events.d.ts.map +0 -1
- package/build/types/hooks/useAudioDevices.d.ts +0 -15
- package/build/types/hooks/useAudioDevices.d.ts.map +0 -1
- package/build/types/index.d.ts +0 -18
- package/build/types/index.d.ts.map +0 -1
- package/build/types/trimAudio.d.ts +0 -25
- package/build/types/trimAudio.d.ts.map +0 -1
- package/build/types/useAudioRecorder.d.ts +0 -22
- package/build/types/useAudioRecorder.d.ts.map +0 -1
- package/build/types/utils/BlobFix.d.ts +0 -9
- package/build/types/utils/BlobFix.d.ts.map +0 -1
- package/build/types/utils/audioProcessing.d.ts +0 -24
- package/build/types/utils/audioProcessing.d.ts.map +0 -1
- package/build/types/utils/cleanNativeOptions.d.ts +0 -15
- package/build/types/utils/cleanNativeOptions.d.ts.map +0 -1
- package/build/types/utils/concatenateBuffers.d.ts +0 -8
- package/build/types/utils/concatenateBuffers.d.ts.map +0 -1
- package/build/types/utils/convertPCMToFloat32.d.ts +0 -13
- package/build/types/utils/convertPCMToFloat32.d.ts.map +0 -1
- package/build/types/utils/crc32.d.ts +0 -7
- package/build/types/utils/crc32.d.ts.map +0 -1
- package/build/types/utils/encodingToBitDepth.d.ts +0 -5
- package/build/types/utils/encodingToBitDepth.d.ts.map +0 -1
- package/build/types/utils/getWavFileInfo.d.ts +0 -26
- package/build/types/utils/getWavFileInfo.d.ts.map +0 -1
- package/build/types/utils/writeWavHeader.d.ts +0 -34
- package/build/types/utils/writeWavHeader.d.ts.map +0 -1
- package/build/types/workers/InlineFeaturesExtractor.web.d.ts +0 -2
- package/build/types/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
- package/build/types/workers/inlineAudioWebWorker.web.d.ts +0 -2
- package/build/types/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
- package/expo-module.config.json +0 -10
- package/ios/AudioAnalysisData.swift +0 -74
- package/ios/AudioDeviceManager.swift +0 -666
- package/ios/AudioNotificationManager.swift +0 -154
- package/ios/AudioProcessingHelpers.swift +0 -743
- package/ios/AudioProcessor.swift +0 -1151
- package/ios/AudioStreamError.swift +0 -7
- package/ios/AudioStreamManager.swift +0 -2352
- package/ios/AudioStreamManagerDelegate.swift +0 -16
- package/ios/DataPoint.swift +0 -54
- package/ios/DecodingConfig.swift +0 -59
- package/ios/ExpoAudioStream.podspec +0 -33
- package/ios/ExpoAudioStreamModule.swift +0 -1013
- package/ios/ExpoAudioStudioTests/AudioFileHandlerTests.swift +0 -338
- package/ios/ExpoAudioStudioTests/AudioFormatUtilsTests.swift +0 -331
- package/ios/ExpoAudioStudioTests/AudioTestHelpers.swift +0 -130
- package/ios/ExpoAudioStudioTests/CompressedOnlyOutputTests.swift +0 -294
- package/ios/ExpoAudioStudioTests/EventEmissionIntervalTests.swift +0 -105
- package/ios/ExpoAudioStudioTests/Info.plist +0 -22
- package/ios/ExpoAudioStudioTests/README.md +0 -39
- package/ios/ExpoAudioStudioTests/SimpleAudioTest.swift +0 -98
- package/ios/ExpoAudioStudioTests/TestAudioGenerator.swift +0 -75
- package/ios/FFT.swift +0 -62
- package/ios/Features.swift +0 -95
- package/ios/ISSUE_IOS.md +0 -68
- package/ios/Logger.swift +0 -39
- package/ios/NotificationExtension.swift +0 -15
- package/ios/RecordingResult.swift +0 -22
- package/ios/RecordingSettings.swift +0 -308
- package/ios/WaveformExtractor.swift +0 -105
- package/ios/tests/README.md +0 -41
- package/ios/tests/integration/buffer_and_fallback_test.swift +0 -178
- package/ios/tests/integration/buffer_duration_test.swift +0 -185
- package/ios/tests/integration/compressed_only_output_test.swift +0 -271
- package/ios/tests/integration/output_control_test.swift +0 -322
- package/ios/tests/integration/run_integration_tests.sh +0 -37
- package/ios/tests/opus_support_test_macos.swift +0 -154
- package/ios/tests/standalone/audio_processing_test.swift +0 -144
- package/ios/tests/standalone/audio_recording_test.swift +0 -277
- package/ios/tests/standalone/audio_streaming_test.swift +0 -249
- package/ios/tests/standalone/standalone_test.swift +0 -144
- package/plugin/build/index.cjs +0 -194
- package/plugin/build/index.d.cts +0 -22
- package/plugin/build/index.js +0 -194
- package/plugin/src/index.ts +0 -285
- package/plugin/tsconfig.json +0 -10
- package/plugin/tsconfig.tsbuildinfo +0 -1
- package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -224
- package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -344
- package/src/AudioAnalysis/extractAudioData.ts +0 -17
- package/src/AudioAnalysis/extractMelSpectrogram.ts +0 -154
- package/src/AudioAnalysis/extractPreview.ts +0 -34
- package/src/AudioAnalysis/extractWaveform.ts +0 -22
- package/src/AudioDeviceManager.ts +0 -803
- package/src/AudioRecorder.provider.tsx +0 -57
- package/src/ExpoAudioStream.native.ts +0 -6
- package/src/ExpoAudioStream.types.ts +0 -874
- package/src/ExpoAudioStream.web.ts +0 -905
- package/src/ExpoAudioStreamModule.ts +0 -990
- package/src/WebRecorder.web.ts +0 -1005
- package/src/constants/platformLimitations.ts +0 -118
- package/src/constants.ts +0 -18
- package/src/events.ts +0 -60
- package/src/hooks/useAudioDevices.ts +0 -213
- package/src/index.ts +0 -54
- package/src/trimAudio.ts +0 -94
- package/src/types/crc-32.d.ts +0 -9
- package/src/useAudioRecorder.tsx +0 -766
- package/src/utils/BlobFix.ts +0 -561
- package/src/utils/audioProcessing.ts +0 -205
- package/src/utils/cleanNativeOptions.ts +0 -18
- package/src/utils/concatenateBuffers.ts +0 -24
- package/src/utils/convertPCMToFloat32.ts +0 -170
- package/src/utils/crc32.ts +0 -59
- package/src/utils/encodingToBitDepth.ts +0 -18
- package/src/utils/getWavFileInfo.ts +0 -132
- package/src/utils/writeWavHeader.ts +0 -115
- package/src/workers/InlineFeaturesExtractor.web.tsx +0 -855
- package/src/workers/inlineAudioWebWorker.web.tsx +0 -180
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
package net.siteed.audiostream
|
|
2
|
-
|
|
3
|
-
import org.junit.Test
|
|
4
|
-
import org.junit.Assert.*
|
|
5
|
-
import java.nio.ByteBuffer
|
|
6
|
-
import java.nio.ByteOrder
|
|
7
|
-
import kotlin.math.abs
|
|
8
|
-
|
|
9
|
-
class AudioFormatUtilsTest {
|
|
10
|
-
|
|
11
|
-
@Test
|
|
12
|
-
fun testConvertBitDepth_8to16() {
|
|
13
|
-
// Given - 8-bit PCM data (unsigned, centered at 128)
|
|
14
|
-
val input8bit = byteArrayOf(0, 64, 128.toByte(), 192.toByte(), 255.toByte())
|
|
15
|
-
|
|
16
|
-
// When
|
|
17
|
-
val output16bit = AudioFormatUtils.convertBitDepth(input8bit, 8, 16)
|
|
18
|
-
|
|
19
|
-
// Then
|
|
20
|
-
val buffer = ByteBuffer.wrap(output16bit).order(ByteOrder.LITTLE_ENDIAN)
|
|
21
|
-
val samples = ShortArray(output16bit.size / 2)
|
|
22
|
-
buffer.asShortBuffer().get(samples)
|
|
23
|
-
|
|
24
|
-
// Verify conversion (8-bit 128 = silence = 16-bit 0)
|
|
25
|
-
assertEquals("First sample should be -32768", -32768, samples[0].toInt())
|
|
26
|
-
assertEquals("Middle sample (128) should be 0", 0, samples[2].toInt())
|
|
27
|
-
assertEquals("Last sample should be 32767", 32767, samples[4].toInt())
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@Test
|
|
31
|
-
fun testConvertBitDepth_16to8() {
|
|
32
|
-
// Given - 16-bit PCM data
|
|
33
|
-
val buffer16 = ByteBuffer.allocate(10).order(ByteOrder.LITTLE_ENDIAN)
|
|
34
|
-
buffer16.putShort(-32768) // Min value
|
|
35
|
-
buffer16.putShort(-16384) // -0.5
|
|
36
|
-
buffer16.putShort(0) // Silence
|
|
37
|
-
buffer16.putShort(16384) // 0.5
|
|
38
|
-
buffer16.putShort(32767) // Max value
|
|
39
|
-
|
|
40
|
-
// When
|
|
41
|
-
val output8bit = AudioFormatUtils.convertBitDepth(buffer16.array(), 16, 8)
|
|
42
|
-
|
|
43
|
-
// Then
|
|
44
|
-
assertEquals("Should have 5 samples", 5, output8bit.size)
|
|
45
|
-
assertEquals("Min should convert to 0", 0, output8bit[0].toInt() and 0xFF)
|
|
46
|
-
assertEquals("Silence should convert to 128", 128, output8bit[2].toInt() and 0xFF)
|
|
47
|
-
assertEquals("Max should convert to 255", 255, output8bit[4].toInt() and 0xFF)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@Test
|
|
51
|
-
fun testConvertBitDepth_16to32() {
|
|
52
|
-
// Given - 16-bit PCM data
|
|
53
|
-
val buffer16 = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN)
|
|
54
|
-
buffer16.putShort(-32768) // Min
|
|
55
|
-
buffer16.putShort(0) // Silence
|
|
56
|
-
buffer16.putShort(32767) // Max
|
|
57
|
-
|
|
58
|
-
// When
|
|
59
|
-
val output32bit = AudioFormatUtils.convertBitDepth(buffer16.array(), 16, 32)
|
|
60
|
-
|
|
61
|
-
// Then
|
|
62
|
-
val buffer32 = ByteBuffer.wrap(output32bit).order(ByteOrder.LITTLE_ENDIAN)
|
|
63
|
-
assertEquals("Should have 3 32-bit samples", 12, output32bit.size)
|
|
64
|
-
|
|
65
|
-
// Check values (scaled appropriately)
|
|
66
|
-
val sample1 = buffer32.getInt()
|
|
67
|
-
val sample2 = buffer32.getInt()
|
|
68
|
-
val sample3 = buffer32.getInt()
|
|
69
|
-
|
|
70
|
-
assertTrue("Min value should be negative", sample1 < 0)
|
|
71
|
-
assertEquals("Silence should be 0", 0, sample2)
|
|
72
|
-
assertTrue("Max value should be positive", sample3 > 0)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@Test
|
|
76
|
-
fun testConvertBitDepth_32to16() {
|
|
77
|
-
// Given - 32-bit PCM data
|
|
78
|
-
val buffer32 = ByteBuffer.allocate(12).order(ByteOrder.LITTLE_ENDIAN)
|
|
79
|
-
buffer32.putInt(Int.MIN_VALUE) // Min
|
|
80
|
-
buffer32.putInt(0) // Silence
|
|
81
|
-
buffer32.putInt(Int.MAX_VALUE) // Max
|
|
82
|
-
|
|
83
|
-
// When
|
|
84
|
-
val output16bit = AudioFormatUtils.convertBitDepth(buffer32.array(), 32, 16)
|
|
85
|
-
|
|
86
|
-
// Then
|
|
87
|
-
val buffer16 = ByteBuffer.wrap(output16bit).order(ByteOrder.LITTLE_ENDIAN)
|
|
88
|
-
assertEquals("Should have 3 16-bit samples", 6, output16bit.size)
|
|
89
|
-
|
|
90
|
-
assertEquals("Min should convert to -32768", -32768, buffer16.getShort().toInt())
|
|
91
|
-
assertEquals("Silence should be 0", 0, buffer16.getShort().toInt())
|
|
92
|
-
assertEquals("Max should convert to 32767", 32767, buffer16.getShort().toInt())
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
@Test
|
|
96
|
-
fun testConvertBitDepth_sameDepth() {
|
|
97
|
-
// Given
|
|
98
|
-
val input = byteArrayOf(1, 2, 3, 4, 5, 6)
|
|
99
|
-
|
|
100
|
-
// When - Convert 16 to 16 (no-op)
|
|
101
|
-
val output = AudioFormatUtils.convertBitDepth(input, 16, 16)
|
|
102
|
-
|
|
103
|
-
// Then
|
|
104
|
-
assertArrayEquals("Should return same data", input, output)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
@Test
|
|
108
|
-
fun testConvertBitDepth_emptyData() {
|
|
109
|
-
// Given
|
|
110
|
-
val emptyData = byteArrayOf()
|
|
111
|
-
|
|
112
|
-
// When
|
|
113
|
-
val output = AudioFormatUtils.convertBitDepth(emptyData, 16, 32)
|
|
114
|
-
|
|
115
|
-
// Then
|
|
116
|
-
assertEquals("Should return empty array", 0, output.size)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@Test
|
|
120
|
-
fun testConvertChannels_monoToStereo() {
|
|
121
|
-
// Given - Mono 16-bit data
|
|
122
|
-
val monoData = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN).apply {
|
|
123
|
-
putShort(1000)
|
|
124
|
-
putShort(2000)
|
|
125
|
-
putShort(3000)
|
|
126
|
-
}.array()
|
|
127
|
-
|
|
128
|
-
// When
|
|
129
|
-
val stereoData = AudioFormatUtils.convertChannels(monoData, 1, 2, 16)
|
|
130
|
-
|
|
131
|
-
// Then
|
|
132
|
-
val buffer = ByteBuffer.wrap(stereoData).order(ByteOrder.LITTLE_ENDIAN)
|
|
133
|
-
assertEquals("Should have 6 samples (3 stereo pairs)", 12, stereoData.size)
|
|
134
|
-
|
|
135
|
-
// Each mono sample should be duplicated to both channels
|
|
136
|
-
assertEquals("L1", 1000, buffer.getShort().toInt())
|
|
137
|
-
assertEquals("R1", 1000, buffer.getShort().toInt())
|
|
138
|
-
assertEquals("L2", 2000, buffer.getShort().toInt())
|
|
139
|
-
assertEquals("R2", 2000, buffer.getShort().toInt())
|
|
140
|
-
assertEquals("L3", 3000, buffer.getShort().toInt())
|
|
141
|
-
assertEquals("R3", 3000, buffer.getShort().toInt())
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
@Test
|
|
145
|
-
fun testConvertChannels_stereoToMono() {
|
|
146
|
-
// Given - Stereo 16-bit data
|
|
147
|
-
val stereoData = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).apply {
|
|
148
|
-
putShort(1000) // L1
|
|
149
|
-
putShort(2000) // R1
|
|
150
|
-
putShort(3000) // L2
|
|
151
|
-
putShort(4000) // R2
|
|
152
|
-
}.array()
|
|
153
|
-
|
|
154
|
-
// When
|
|
155
|
-
val monoData = AudioFormatUtils.convertChannels(stereoData, 2, 1, 16)
|
|
156
|
-
|
|
157
|
-
// Then
|
|
158
|
-
val buffer = ByteBuffer.wrap(monoData).order(ByteOrder.LITTLE_ENDIAN)
|
|
159
|
-
assertEquals("Should have 2 mono samples", 4, monoData.size)
|
|
160
|
-
|
|
161
|
-
// Each mono sample should be average of L+R
|
|
162
|
-
assertEquals("Sample 1", 1500, buffer.getShort().toInt()) // (1000+2000)/2
|
|
163
|
-
assertEquals("Sample 2", 3500, buffer.getShort().toInt()) // (3000+4000)/2
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
@Test
|
|
167
|
-
fun testNormalizeAudio_quietSignal() {
|
|
168
|
-
// Given - Quiet 16-bit signal
|
|
169
|
-
val quietData = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN).apply {
|
|
170
|
-
putShort(100)
|
|
171
|
-
putShort(-100)
|
|
172
|
-
putShort(50)
|
|
173
|
-
}.array()
|
|
174
|
-
|
|
175
|
-
// When
|
|
176
|
-
val normalized = AudioFormatUtils.normalizeAudio(quietData, 16)
|
|
177
|
-
|
|
178
|
-
// Then
|
|
179
|
-
val buffer = ByteBuffer.wrap(normalized).order(ByteOrder.LITTLE_ENDIAN)
|
|
180
|
-
val maxSample = abs(buffer.getShort().toInt())
|
|
181
|
-
buffer.rewind()
|
|
182
|
-
|
|
183
|
-
// The loudest sample should be close to max value
|
|
184
|
-
assertTrue("Should be normalized to near max", maxSample > 30000)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
@Test
|
|
188
|
-
fun testNormalizeAudio_alreadyLoud() {
|
|
189
|
-
// Given - Already loud signal
|
|
190
|
-
val loudData = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).apply {
|
|
191
|
-
putShort(32000)
|
|
192
|
-
putShort(-32000)
|
|
193
|
-
}.array()
|
|
194
|
-
|
|
195
|
-
// When
|
|
196
|
-
val normalized = AudioFormatUtils.normalizeAudio(loudData, 16)
|
|
197
|
-
|
|
198
|
-
// Then
|
|
199
|
-
val buffer = ByteBuffer.wrap(normalized).order(ByteOrder.LITTLE_ENDIAN)
|
|
200
|
-
val sample1 = abs(buffer.getShort().toInt())
|
|
201
|
-
val sample2 = abs(buffer.getShort().toInt())
|
|
202
|
-
|
|
203
|
-
// Should be normalized but not clipped
|
|
204
|
-
assertTrue("Samples should be near max", sample1 > 32000 && sample2 > 32000)
|
|
205
|
-
assertTrue("Samples should not exceed max", sample1 <= 32767 && sample2 <= 32767)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
@Test
|
|
209
|
-
fun testNormalizeAudio_silentSignal() {
|
|
210
|
-
// Given - Silent signal
|
|
211
|
-
val silentData = ByteBuffer.allocate(6).order(ByteOrder.LITTLE_ENDIAN).apply {
|
|
212
|
-
putShort(0)
|
|
213
|
-
putShort(0)
|
|
214
|
-
putShort(0)
|
|
215
|
-
}.array()
|
|
216
|
-
|
|
217
|
-
// When
|
|
218
|
-
val normalized = AudioFormatUtils.normalizeAudio(silentData, 16)
|
|
219
|
-
|
|
220
|
-
// Then
|
|
221
|
-
val buffer = ByteBuffer.wrap(normalized).order(ByteOrder.LITTLE_ENDIAN)
|
|
222
|
-
assertEquals("Silent should remain silent", 0, buffer.getShort().toInt())
|
|
223
|
-
assertEquals("Silent should remain silent", 0, buffer.getShort().toInt())
|
|
224
|
-
assertEquals("Silent should remain silent", 0, buffer.getShort().toInt())
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
@Test
|
|
228
|
-
fun testResampleAudio_upsample() {
|
|
229
|
-
// Given - 8kHz mono audio
|
|
230
|
-
val samples8k = floatArrayOf(0.0f, 0.5f, 1.0f, 0.5f, 0.0f, -0.5f, -1.0f, -0.5f)
|
|
231
|
-
|
|
232
|
-
// When - Upsample to 16kHz
|
|
233
|
-
val samples16k = AudioFormatUtils.resampleAudio(samples8k, 8000, 16000)
|
|
234
|
-
|
|
235
|
-
// Then
|
|
236
|
-
assertEquals("Should have approximately double samples", 16, samples16k.size)
|
|
237
|
-
// First and last samples should match
|
|
238
|
-
assertEquals("First sample", samples8k[0], samples16k[0], 0.01f)
|
|
239
|
-
assertEquals("Last sample", samples8k.last(), samples16k.last(), 0.01f)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
@Test
|
|
243
|
-
fun testResampleAudio_downsample() {
|
|
244
|
-
// Given - 16kHz mono audio
|
|
245
|
-
val samples16k = floatArrayOf(
|
|
246
|
-
0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 0.75f, 0.5f, 0.25f,
|
|
247
|
-
0.0f, -0.25f, -0.5f, -0.75f, -1.0f, -0.75f, -0.5f, -0.25f
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
// When - Downsample to 8kHz
|
|
251
|
-
val samples8k = AudioFormatUtils.resampleAudio(samples16k, 16000, 8000)
|
|
252
|
-
|
|
253
|
-
// Then
|
|
254
|
-
assertEquals("Should have approximately half samples", 8, samples8k.size)
|
|
255
|
-
// Check general shape is preserved
|
|
256
|
-
val maxValue = samples8k.maxOrNull() ?: 0f
|
|
257
|
-
val minValue = samples8k.minOrNull() ?: 0f
|
|
258
|
-
assertTrue("Peak should be preserved", maxValue > 0.9f)
|
|
259
|
-
assertTrue("Trough should be preserved", minValue < -0.9f)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
@Test
|
|
263
|
-
fun testResampleAudio_sameRate() {
|
|
264
|
-
// Given
|
|
265
|
-
val samples = floatArrayOf(0.1f, 0.2f, 0.3f, 0.4f, 0.5f)
|
|
266
|
-
|
|
267
|
-
// When - Same sample rate
|
|
268
|
-
val resampled = AudioFormatUtils.resampleAudio(samples, 44100, 44100)
|
|
269
|
-
|
|
270
|
-
// Then
|
|
271
|
-
assertArrayEquals("Should return same samples", samples, resampled, 0.001f)
|
|
272
|
-
}
|
|
273
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
package net.siteed.audiostream
|
|
2
|
-
|
|
3
|
-
import org.junit.Assert.*
|
|
4
|
-
import org.junit.Test
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Unit test for Device Disconnection Fallback Behavior
|
|
8
|
-
*
|
|
9
|
-
* Tests the configuration and expected behavior for device disconnection scenarios.
|
|
10
|
-
*/
|
|
11
|
-
class DeviceDisconnectionFallbackUnitTest {
|
|
12
|
-
|
|
13
|
-
@Test
|
|
14
|
-
fun `test RecordingConfig stores deviceDisconnectionBehavior correctly`() {
|
|
15
|
-
// Test fallback behavior
|
|
16
|
-
val fallbackConfig = RecordingConfig(
|
|
17
|
-
sampleRate = 44100,
|
|
18
|
-
channels = 1,
|
|
19
|
-
encoding = "pcm_16bit",
|
|
20
|
-
deviceDisconnectionBehavior = "fallback"
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
assertEquals("Should store fallback behavior", "fallback", fallbackConfig.deviceDisconnectionBehavior)
|
|
24
|
-
|
|
25
|
-
// Test pause behavior
|
|
26
|
-
val pauseConfig = RecordingConfig(
|
|
27
|
-
sampleRate = 44100,
|
|
28
|
-
channels = 1,
|
|
29
|
-
encoding = "pcm_16bit",
|
|
30
|
-
deviceDisconnectionBehavior = "pause"
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
assertEquals("Should store pause behavior", "pause", pauseConfig.deviceDisconnectionBehavior)
|
|
34
|
-
|
|
35
|
-
// Test default behavior (should be null)
|
|
36
|
-
val defaultConfig = RecordingConfig(
|
|
37
|
-
sampleRate = 44100,
|
|
38
|
-
channels = 1,
|
|
39
|
-
encoding = "pcm_16bit"
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
assertNull("Default behavior should be null", defaultConfig.deviceDisconnectionBehavior)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@Test
|
|
46
|
-
fun `test AudioRecorderManager stores deviceDisconnectionBehavior`() {
|
|
47
|
-
val config = RecordingConfig(
|
|
48
|
-
sampleRate = 44100,
|
|
49
|
-
channels = 1,
|
|
50
|
-
encoding = "pcm_16bit",
|
|
51
|
-
deviceDisconnectionBehavior = "fallback"
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
// Verify the config has the correct behavior
|
|
55
|
-
assertEquals("fallback", config.deviceDisconnectionBehavior)
|
|
56
|
-
|
|
57
|
-
// AudioRecorderManager should use this configuration
|
|
58
|
-
// The actual AudioRecorderManager.getDeviceDisconnectionBehavior()
|
|
59
|
-
// will return this value when recording is started with this config
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
@Test
|
|
63
|
-
fun `test device disconnection behavior values`() {
|
|
64
|
-
val validBehaviors = listOf("fallback", "pause")
|
|
65
|
-
|
|
66
|
-
for (behavior in validBehaviors) {
|
|
67
|
-
val config = RecordingConfig(
|
|
68
|
-
sampleRate = 44100,
|
|
69
|
-
channels = 1,
|
|
70
|
-
encoding = "pcm_16bit",
|
|
71
|
-
deviceDisconnectionBehavior = behavior
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
assertEquals("Should accept $behavior behavior", behavior, config.deviceDisconnectionBehavior)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
@Test
|
|
79
|
-
fun `test interruption event reasons`() {
|
|
80
|
-
// Test expected event reasons for device disconnection scenarios
|
|
81
|
-
val expectedReasons = mapOf(
|
|
82
|
-
"fallback" to listOf("deviceFallback", "deviceSwitchFailed"),
|
|
83
|
-
"pause" to listOf("deviceDisconnected")
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
// Verify the expected reasons are valid strings
|
|
87
|
-
expectedReasons.forEach { (behavior, reasons) ->
|
|
88
|
-
assertNotNull("Behavior $behavior should have reasons", reasons)
|
|
89
|
-
assertTrue("Behavior $behavior should have at least one reason", reasons.isNotEmpty())
|
|
90
|
-
|
|
91
|
-
reasons.forEach { reason ->
|
|
92
|
-
assertNotNull("Reason should not be null", reason)
|
|
93
|
-
assertTrue("Reason should not be empty", reason.isNotEmpty())
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
@Test
|
|
99
|
-
fun `test fallback behavior logic`() {
|
|
100
|
-
// Test the logic for fallback behavior
|
|
101
|
-
val behavior = "fallback"
|
|
102
|
-
|
|
103
|
-
// When behavior is fallback:
|
|
104
|
-
// 1. Should attempt to get default device
|
|
105
|
-
// 2. If default device exists, should select it
|
|
106
|
-
// 3. If selection succeeds, should send "deviceFallback" event
|
|
107
|
-
// 4. If selection fails, should pause and send "deviceSwitchFailed" event
|
|
108
|
-
// 5. If no default device, should pause and send "deviceDisconnected" event
|
|
109
|
-
|
|
110
|
-
when (behavior) {
|
|
111
|
-
"fallback" -> {
|
|
112
|
-
// This branch should be taken
|
|
113
|
-
assertTrue("Should handle fallback behavior", true)
|
|
114
|
-
}
|
|
115
|
-
else -> {
|
|
116
|
-
fail("Should not reach default case for fallback behavior")
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
@Test
|
|
122
|
-
fun `test pause behavior logic`() {
|
|
123
|
-
// Test the logic for pause behavior
|
|
124
|
-
val behavior = "pause"
|
|
125
|
-
|
|
126
|
-
// When behavior is pause:
|
|
127
|
-
// 1. Should pause recording immediately
|
|
128
|
-
// 2. Should send "deviceDisconnected" event
|
|
129
|
-
|
|
130
|
-
when (behavior) {
|
|
131
|
-
"fallback" -> {
|
|
132
|
-
fail("Should not handle as fallback")
|
|
133
|
-
}
|
|
134
|
-
else -> {
|
|
135
|
-
// This branch should be taken for pause
|
|
136
|
-
assertTrue("Should handle pause behavior", true)
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
Binary file
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Generate test WAV files for Android unit tests
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import wave
|
|
7
|
-
import struct
|
|
8
|
-
import math
|
|
9
|
-
import array
|
|
10
|
-
|
|
11
|
-
def generate_sine_wave(frequency, duration, sample_rate, amplitude=0.5):
|
|
12
|
-
"""Generate sine wave samples"""
|
|
13
|
-
num_samples = int(duration * sample_rate)
|
|
14
|
-
samples = []
|
|
15
|
-
for i in range(num_samples):
|
|
16
|
-
t = i / sample_rate
|
|
17
|
-
value = amplitude * math.sin(2 * math.pi * frequency * t)
|
|
18
|
-
# Convert to 16-bit PCM
|
|
19
|
-
pcm_value = int(value * 32767)
|
|
20
|
-
samples.append(pcm_value)
|
|
21
|
-
return samples
|
|
22
|
-
|
|
23
|
-
def create_wav_file(filename, channels, sample_rate, bit_depth, duration, frequency=440):
|
|
24
|
-
"""Create a WAV file with specified parameters"""
|
|
25
|
-
print(f"Creating {filename}...")
|
|
26
|
-
|
|
27
|
-
# Generate samples for left channel (or mono)
|
|
28
|
-
samples = generate_sine_wave(frequency, duration, sample_rate)
|
|
29
|
-
|
|
30
|
-
# For stereo, generate right channel with different frequency
|
|
31
|
-
if channels == 2:
|
|
32
|
-
right_samples = generate_sine_wave(frequency * 1.5, duration, sample_rate)
|
|
33
|
-
|
|
34
|
-
# Prepare the data
|
|
35
|
-
if bit_depth == 16:
|
|
36
|
-
# Create array of signed shorts
|
|
37
|
-
audio_data = array.array('h') # signed short
|
|
38
|
-
|
|
39
|
-
for i in range(len(samples)):
|
|
40
|
-
if channels == 1:
|
|
41
|
-
audio_data.append(samples[i])
|
|
42
|
-
else:
|
|
43
|
-
# Interleave stereo samples
|
|
44
|
-
audio_data.append(samples[i])
|
|
45
|
-
audio_data.append(right_samples[i])
|
|
46
|
-
elif bit_depth == 8:
|
|
47
|
-
# Create array of unsigned bytes
|
|
48
|
-
audio_data = array.array('B') # unsigned char
|
|
49
|
-
|
|
50
|
-
for i in range(len(samples)):
|
|
51
|
-
# Convert to 8-bit unsigned
|
|
52
|
-
sample_8bit = ((samples[i] + 32768) >> 8) & 0xFF
|
|
53
|
-
if channels == 1:
|
|
54
|
-
audio_data.append(sample_8bit)
|
|
55
|
-
else:
|
|
56
|
-
right_8bit = ((right_samples[i] + 32768) >> 8) & 0xFF
|
|
57
|
-
audio_data.append(sample_8bit)
|
|
58
|
-
audio_data.append(right_8bit)
|
|
59
|
-
else:
|
|
60
|
-
raise ValueError(f"Unsupported bit depth: {bit_depth}")
|
|
61
|
-
|
|
62
|
-
# Write WAV file
|
|
63
|
-
with wave.open(filename, 'wb') as wav_file:
|
|
64
|
-
wav_file.setnchannels(channels)
|
|
65
|
-
wav_file.setsampwidth(bit_depth // 8)
|
|
66
|
-
wav_file.setframerate(sample_rate)
|
|
67
|
-
wav_file.writeframes(audio_data.tobytes())
|
|
68
|
-
|
|
69
|
-
print(f" Created: {filename} ({duration}s, {sample_rate}Hz, {channels}ch, {bit_depth}bit)")
|
|
70
|
-
|
|
71
|
-
# Generate test files
|
|
72
|
-
if __name__ == "__main__":
|
|
73
|
-
try:
|
|
74
|
-
# Basic mono file
|
|
75
|
-
create_wav_file("test_mono_16bit_44100.wav",
|
|
76
|
-
channels=1, sample_rate=44100, bit_depth=16, duration=1.0)
|
|
77
|
-
|
|
78
|
-
# Stereo file
|
|
79
|
-
create_wav_file("test_stereo_16bit_48000.wav",
|
|
80
|
-
channels=2, sample_rate=48000, bit_depth=16, duration=1.0)
|
|
81
|
-
|
|
82
|
-
# Short duration file
|
|
83
|
-
create_wav_file("test_short_100ms.wav",
|
|
84
|
-
channels=1, sample_rate=44100, bit_depth=16, duration=0.1)
|
|
85
|
-
|
|
86
|
-
# Silent file (0 Hz frequency)
|
|
87
|
-
create_wav_file("test_silence.wav",
|
|
88
|
-
channels=1, sample_rate=44100, bit_depth=16, duration=0.5, frequency=0)
|
|
89
|
-
|
|
90
|
-
print("\nAll test WAV files generated successfully!")
|
|
91
|
-
except Exception as e:
|
|
92
|
-
print(f"Error: {e}")
|
|
93
|
-
import traceback
|
|
94
|
-
traceback.print_exc()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/app.plugin.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AudioAnalysis.types.js","sourceRoot":"","sources":["../../../src/AudioAnalysis/AudioAnalysis.types.ts"],"names":[],"mappings":";AAAA,sEAAsE","sourcesContent":["// packages/expo-audio-stream/src/AudioAnalysis/AudioAnalysis.types.ts\n\nimport { BitDepth, ConsoleLike } from '../ExpoAudioStream.types'\n\n/**\n * Represents the configuration for decoding audio data.\n */\nexport interface DecodingConfig {\n /** Target sample rate for decoded audio (Android and Web) */\n targetSampleRate?: number\n /** Target number of channels (Android and Web) */\n targetChannels?: number\n /** Target bit depth (Android and Web) */\n targetBitDepth?: BitDepth\n /** Whether to normalize audio levels (Android and Web) */\n normalizeAudio?: boolean\n}\n\n/**\n * Represents speech-related features extracted from audio.\n */\nexport interface SpeechFeatures {\n isActive: boolean // Whether speech is detected in this segment\n speakerId?: number // Optional speaker identification\n // Could add more speech-related features here like:\n // confidence: number\n // language?: string\n // sentiment?: number\n // etc.\n}\n\n/**\n * Represents various audio features extracted from an audio signal.\n */\nexport interface AudioFeatures {\n energy?: number // The infinite integral of the squared signal, representing the overall energy of the audio.\n mfcc?: number[] // Mel-frequency cepstral coefficients, describing the short-term power spectrum of a sound.\n rms?: number // Root mean square value, indicating the amplitude of the audio signal.\n minAmplitude?: number // Minimum amplitude value in the audio signal.\n maxAmplitude?: number // Maximum amplitude value in the audio signal.\n zcr?: number // Zero-crossing rate, indicating the rate at which the signal changes sign.\n spectralCentroid?: number // The center of mass of the spectrum, indicating the brightness of the sound.\n spectralFlatness?: number // Measure of the flatness of the spectrum, indicating how noise-like the signal is.\n spectralRolloff?: number // The frequency below which a specified percentage (usually 85%) of the total spectral energy lies.\n spectralBandwidth?: number // The width of the spectrum, indicating the range of frequencies present.\n chromagram?: number[] // Chromagram, representing the 12 different pitch classes of the audio.\n tempo?: number // Estimated tempo of the audio signal, measured in beats per minute (BPM).\n hnr?: number // Harmonics-to-noise ratio, indicating the proportion of harmonics to noise in the audio signal.\n melSpectrogram?: number[] // Mel-scaled spectrogram representation of the audio.\n spectralContrast?: number[] // Spectral contrast features representing the difference between peaks and valleys.\n tonnetz?: number[] // Tonal network features representing harmonic relationships.\n pitch?: number // Pitch of the audio signal, measured in Hertz (Hz).\n crc32?: number // crc32 checksum of the audio signal, used to verify the integrity of the audio.\n}\n\n/**\n * Options to specify which audio features to extract.\n * Note: Advanced features (spectral features, chromagram, pitch, etc.) are experimental,\n * especially during live recording, due to high processing requirements.\n */\nexport interface AudioFeaturesOptions {\n // Basic features - well optimized\n energy?: boolean\n rms?: boolean\n zcr?: boolean\n\n // Advanced features - experimental, may impact performance in live recording\n mfcc?: boolean\n spectralCentroid?: boolean\n spectralFlatness?: boolean\n spectralRolloff?: boolean\n spectralBandwidth?: boolean\n chromagram?: boolean\n tempo?: boolean\n hnr?: boolean\n melSpectrogram?: boolean\n spectralContrast?: boolean\n tonnetz?: boolean\n pitch?: boolean\n\n // Utility\n crc32?: boolean\n}\n\n/**\n * Represents a single data point in the audio analysis.\n */\nexport interface DataPoint {\n id: number\n amplitude: number // Peak amplitude for the segment\n rms: number // Root mean square value\n dB: number // dBFS (decibels relative to full scale) computed from RMS value\n silent: boolean // Always computed\n features?: AudioFeatures\n speech?: SpeechFeatures\n startTime?: number\n endTime?: number\n // start / end position in bytes\n startPosition?: number\n endPosition?: number\n // number of audio samples for this point (samples size depends on bit depth)\n samples?: number\n}\n\n/**\n * Represents the complete data from the audio analysis.\n */\nexport interface AudioAnalysis {\n segmentDurationMs: number // Duration of each segment in milliseconds\n durationMs: number // Duration of the audio in milliseconds\n /**\n * Bit depth used for audio analysis processing.\n *\n * **Important**: This represents the internal processing bit depth, which may differ\n * from the recording bit depth. Audio is typically converted to 32-bit float for\n * analysis to ensure precision in calculations, regardless of the original recording format.\n *\n * Platform behavior:\n * - iOS: Always 32 (float processing)\n * - Android: Always 32 (float processing)\n * - Web: Always 32 (Web Audio API standard)\n *\n * The actual recorded file will maintain the requested bit depth (8, 16, or 32).\n */\n bitDepth: number\n samples: number // Size of the audio in bytes\n numberOfChannels: number // Number of audio channels\n sampleRate: number // Sample rate of the audio\n dataPoints: DataPoint[] // Array of data points from the analysis.\n amplitudeRange: {\n min: number\n max: number\n }\n rmsRange: {\n min: number\n max: number\n }\n extractionTimeMs: number // Time taken to extract/process the analysis in milliseconds\n // TODO: speaker changes into a broader speech analysis section\n speechAnalysis?: {\n speakerChanges: {\n timestamp: number\n speakerId: number\n }[]\n // Could add more speech analysis data here like:\n // dominantSpeaker?: number\n // totalSpeechDuration?: number\n // speakerStats?: { [speakerId: number]: { duration: number, segments: number } }\n }\n}\n\n/**\n * Options for specifying a time range within an audio file.\n */\nexport interface AudioRangeOptions {\n /** Start time in milliseconds */\n startTimeMs?: number\n /** End time in milliseconds */\n endTimeMs?: number\n}\n\n/**\n * Options for generating a quick preview of audio waveform.\n * This is optimized for UI rendering with a specified number of points.\n */\nexport interface PreviewOptions extends AudioRangeOptions {\n /** URI of the audio file to analyze */\n fileUri: string\n /**\n * Total number of points to generate for the preview.\n * @default 100\n */\n numberOfPoints?: number\n /**\n * Optional logger for debugging.\n */\n logger?: ConsoleLike\n /**\n * Optional configuration for decoding the audio file.\n * Defaults to:\n * - targetSampleRate: undefined (keep original)\n * - targetChannels: undefined (keep original)\n * - targetBitDepth: 16\n * - normalizeAudio: false\n */\n decodingOptions?: DecodingConfig\n}\n\n/**\n * Options for mel-spectrogram extraction\n *\n * @experimental This feature is experimental and currently only available on Android.\n * The API may change in future versions.\n */\nexport interface ExtractMelSpectrogramOptions {\n fileUri?: string // Path to audio file\n arrayBuffer?: ArrayBuffer // Raw audio buffer\n windowSizeMs: number // Window size in ms (e.g., 25)\n hopLengthMs: number // Hop length in ms (e.g., 10)\n nMels: number // Number of mel filters (e.g., 60)\n fMin?: number // Min frequency (default: 0)\n fMax?: number // Max frequency (default: sampleRate / 2)\n windowType?: 'hann' | 'hamming' // Window function (default: 'hann')\n normalize?: boolean // Mean normalization (default: false)\n logScale?: boolean // Log scaling of mel energies (default: true)\n decodingOptions?: DecodingConfig // Audio decoding settings\n startTimeMs?: number // Optional start time\n endTimeMs?: number // Optional end time\n logger?: ConsoleLike\n}\n\n/**\n * Return type for mel spectrogram extraction\n *\n * @experimental This feature is experimental and currently only available on Android.\n * The API may change in future versions.\n */\nexport interface MelSpectrogram {\n spectrogram: number[][] // 2D array [time][mel]\n sampleRate: number // Audio sample rate\n nMels: number // Number of mel filters\n timeSteps: number // Number of time frames\n durationMs: number // Audio duration in ms\n}\n"]}
|