@siteed/audio-studio 3.1.0 → 3.1.1

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 (45) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +97 -50
  3. package/android/src/androidTest/java/net/siteed/audiostudio/AudioFinalMetadataContractInstrumentedTest.kt +190 -0
  4. package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderInstrumentedTest.kt +29 -83
  5. package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderPerformanceInstrumentedTest.kt +17 -1
  6. package/android/src/androidTest/java/net/siteed/audiostudio/OpusRangeDecodeRegressionInstrumentedTest.kt +186 -0
  7. package/android/src/main/java/net/siteed/audiostudio/AudioProcessor.kt +473 -380
  8. package/android/src/main/java/net/siteed/audiostudio/AudioStudioModule.kt +53 -10
  9. package/android/src/main/java/net/siteed/audiostudio/AudioTrimmer.kt +174 -212
  10. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
  11. package/build/cjs/AudioAnalysis/extractPreview.js +92 -15
  12. package/build/cjs/AudioAnalysis/extractPreview.js.map +1 -1
  13. package/build/cjs/AudioAnalysis/extractPreviewBars.js +134 -0
  14. package/build/cjs/AudioAnalysis/extractPreviewBars.js.map +1 -0
  15. package/build/cjs/errors/AudioExtractionError.js +127 -0
  16. package/build/cjs/errors/AudioExtractionError.js.map +1 -0
  17. package/build/cjs/index.js +6 -1
  18. package/build/cjs/index.js.map +1 -1
  19. package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +1 -1
  20. package/build/esm/AudioAnalysis/extractPreview.js +92 -15
  21. package/build/esm/AudioAnalysis/extractPreview.js.map +1 -1
  22. package/build/esm/AudioAnalysis/extractPreviewBars.js +128 -0
  23. package/build/esm/AudioAnalysis/extractPreviewBars.js.map +1 -0
  24. package/build/esm/errors/AudioExtractionError.js +122 -0
  25. package/build/esm/errors/AudioExtractionError.js.map +1 -0
  26. package/build/esm/index.js +2 -0
  27. package/build/esm/index.js.map +1 -1
  28. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +79 -0
  29. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -1
  30. package/build/types/AudioAnalysis/extractPreview.d.ts +2 -2
  31. package/build/types/AudioAnalysis/extractPreview.d.ts.map +1 -1
  32. package/build/types/AudioAnalysis/extractPreviewBars.d.ts +12 -0
  33. package/build/types/AudioAnalysis/extractPreviewBars.d.ts.map +1 -0
  34. package/build/types/errors/AudioExtractionError.d.ts +24 -0
  35. package/build/types/errors/AudioExtractionError.d.ts.map +1 -0
  36. package/build/types/index.d.ts +3 -0
  37. package/build/types/index.d.ts.map +1 -1
  38. package/ios/AudioProcessor.swift +99 -0
  39. package/ios/AudioStudioModule.swift +63 -0
  40. package/package.json +7 -7
  41. package/src/AudioAnalysis/AudioAnalysis.types.ts +82 -0
  42. package/src/AudioAnalysis/extractPreview.ts +118 -17
  43. package/src/AudioAnalysis/extractPreviewBars.ts +193 -0
  44. package/src/errors/AudioExtractionError.ts +167 -0
  45. package/src/index.ts +10 -0
@@ -520,7 +520,7 @@ class AudioStudioModule : Module(), EventSender {
520
520
  """.trimIndent())
521
521
 
522
522
  // Handle decoding options
523
- val decodingOptions = options["decodingOptions"] as? Map<String, Any>
523
+ val decodingOptions = options["decodingOptions"] as? Map<*, *>
524
524
  LogUtils.d(CLASS_NAME, "Decoding options: $decodingOptions")
525
525
 
526
526
  val config = decodingOptions?.let {
@@ -676,6 +676,48 @@ class AudioStudioModule : Module(), EventSender {
676
676
  }
677
677
 
678
678
 
679
+ AsyncFunction("extractPreviewBars") { options: Map<String, Any>, promise: Promise ->
680
+ coroutineScope.launch(Dispatchers.IO) {
681
+ try {
682
+ val fileUri = requireNotNull(options["fileUri"] as? String) { "fileUri is required" }
683
+ val numberOfBars = (options["numberOfBars"] as? Number)?.toInt() ?: 100
684
+ val startTimeMs = options["startTimeMs"] as? Number
685
+ val endTimeMs = options["endTimeMs"] as? Number
686
+
687
+ val defaultConfig = DecodingConfig(
688
+ targetSampleRate = null,
689
+ targetChannels = 1,
690
+ targetBitDepth = 16,
691
+ normalizeAudio = false
692
+ )
693
+ val decodingOptionsMap = options["decodingOptions"] as? Map<*, *>
694
+ val config = decodingOptionsMap?.let {
695
+ DecodingConfig(
696
+ targetSampleRate = (it["targetSampleRate"] as? Number)?.toInt(),
697
+ targetChannels = (it["targetChannels"] as? Number)?.toInt(),
698
+ targetBitDepth = (it["targetBitDepth"] as? Number)?.toInt() ?: 16,
699
+ normalizeAudio = (it["normalizeAudio"] as? Boolean) ?: false
700
+ )
701
+ } ?: defaultConfig
702
+ val silenceRmsThreshold = ((decodingOptionsMap?.get("silenceRmsThreshold") as? Number)?.toFloat()) ?: 0.01f
703
+
704
+ val audioData = audioProcessor.loadAudioFromAnyFormat(fileUri, config)
705
+ ?: throw IllegalStateException("Failed to load audio data")
706
+ val result = audioProcessor.generatePreviewBars(
707
+ audioData = audioData,
708
+ numberOfBars = numberOfBars,
709
+ startTimeMs = startTimeMs?.toLong(),
710
+ endTimeMs = endTimeMs?.toLong(),
711
+ silenceRmsThreshold = silenceRmsThreshold
712
+ )
713
+ promise.resolve(result)
714
+ } catch (e: Exception) {
715
+ LogUtils.e(CLASS_NAME, "Failed to extract preview bars: ${e.message}", e)
716
+ promise.reject("PROCESSING_ERROR", e.message ?: "Unknown error", e)
717
+ }
718
+ }
719
+ }
720
+
679
721
  AsyncFunction("extractAudioAnalysis") { options: Map<String, Any>, promise: Promise ->
680
722
  // Off the shared executor so other JS calls don't block during
681
723
  // multi-second analysis on large files.
@@ -707,12 +749,13 @@ class AudioStudioModule : Module(), EventSender {
707
749
  normalizeAudio = false
708
750
  )
709
751
 
710
- val config = (options["decodingOptions"] as? Map<String, Any>)?.let { decodingOptionsMap ->
752
+ val decodingOptionsMap = options["decodingOptions"] as? Map<*, *>
753
+ val config = decodingOptionsMap?.let {
711
754
  DecodingConfig(
712
- targetSampleRate = decodingOptionsMap["targetSampleRate"] as? Int,
713
- targetChannels = decodingOptionsMap["targetChannels"] as? Int,
714
- targetBitDepth = (decodingOptionsMap["targetBitDepth"] as? Int) ?: 16,
715
- normalizeAudio = (decodingOptionsMap["normalizeAudio"] as? Boolean) ?: false
755
+ targetSampleRate = (it["targetSampleRate"] as? Number)?.toInt(),
756
+ targetChannels = (it["targetChannels"] as? Number)?.toInt(),
757
+ targetBitDepth = (it["targetBitDepth"] as? Number)?.toInt() ?: 16,
758
+ normalizeAudio = (it["normalizeAudio"] as? Boolean) ?: false
716
759
  )
717
760
  } ?: defaultConfig
718
761
 
@@ -802,12 +845,12 @@ class AudioStudioModule : Module(), EventSender {
802
845
  }
803
846
 
804
847
  // Get decoding options
805
- val decodingOptionsMap = options["decodingOptions"] as? Map<String, Any>
848
+ val decodingOptionsMap = options["decodingOptions"] as? Map<*, *>
806
849
  val decodingConfig = if (decodingOptionsMap != null) {
807
850
  DecodingConfig(
808
- targetSampleRate = decodingOptionsMap["targetSampleRate"] as? Int,
809
- targetChannels = decodingOptionsMap["targetChannels"] as? Int,
810
- targetBitDepth = (decodingOptionsMap["targetBitDepth"] as? Int) ?: 16,
851
+ targetSampleRate = (decodingOptionsMap["targetSampleRate"] as? Number)?.toInt(),
852
+ targetChannels = (decodingOptionsMap["targetChannels"] as? Number)?.toInt(),
853
+ targetBitDepth = (decodingOptionsMap["targetBitDepth"] as? Number)?.toInt() ?: 16,
811
854
  normalizeAudio = (decodingOptionsMap["normalizeAudio"] as? Boolean) ?: false
812
855
  ).also {
813
856
  LogUtils.d(CLASS_NAME, """