@siteed/expo-audio-studio 2.18.6 → 3.0.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 (329) hide show
  1. package/README.md +13 -297
  2. package/index.d.ts +1 -0
  3. package/index.js +1 -0
  4. package/package.json +7 -136
  5. package/CHANGELOG.md +0 -501
  6. package/LICENSE +0 -21
  7. package/android/build.gradle +0 -129
  8. package/android/src/androidTest/assets/chorus.wav +0 -0
  9. package/android/src/androidTest/assets/jfk.wav +0 -0
  10. package/android/src/androidTest/assets/osr_us_000_0010_8k.wav +0 -0
  11. package/android/src/androidTest/assets/recorder_hello_world.wav +0 -0
  12. package/android/src/androidTest/java/net/siteed/audiostream/AudioProcessorInstrumentedTest.kt +0 -197
  13. package/android/src/androidTest/java/net/siteed/audiostream/AudioRecorderInstrumentedTest.kt +0 -541
  14. package/android/src/androidTest/java/net/siteed/audiostream/AudioRecorderPerformanceInstrumentedTest.kt +0 -234
  15. package/android/src/androidTest/java/net/siteed/audiostream/integration/AudioFocusStrategyIntegrationTest.kt +0 -332
  16. package/android/src/androidTest/java/net/siteed/audiostream/integration/BufferDurationIntegrationTest.kt +0 -324
  17. package/android/src/androidTest/java/net/siteed/audiostream/integration/CompressedOnlyOutputTest.kt +0 -253
  18. package/android/src/androidTest/java/net/siteed/audiostream/integration/DeviceDisconnectionFallbackTest.kt +0 -218
  19. package/android/src/androidTest/java/net/siteed/audiostream/integration/EventEmissionIntervalTest.kt +0 -120
  20. package/android/src/androidTest/java/net/siteed/audiostream/integration/M4aFormatTest.kt +0 -345
  21. package/android/src/androidTest/java/net/siteed/audiostream/integration/OutputControlIntegrationTest.kt +0 -340
  22. package/android/src/androidTest/java/net/siteed/audiostream/integration/PcmStreamingDurationTest.kt +0 -252
  23. package/android/src/androidTest/java/net/siteed/audiostream/integration/README.md +0 -95
  24. package/android/src/androidTest/java/net/siteed/audiostream/integration/run_integration_tests.sh +0 -43
  25. package/android/src/main/AndroidManifest.xml +0 -30
  26. package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +0 -188
  27. package/android/src/main/java/net/siteed/audiostream/AudioDataEncoder.kt +0 -9
  28. package/android/src/main/java/net/siteed/audiostream/AudioDeviceManager.kt +0 -1741
  29. package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +0 -136
  30. package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +0 -354
  31. package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +0 -439
  32. package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +0 -2237
  33. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -2141
  34. package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +0 -167
  35. package/android/src/main/java/net/siteed/audiostream/AudioTrimmer.kt +0 -1099
  36. package/android/src/main/java/net/siteed/audiostream/Constants.kt +0 -37
  37. package/android/src/main/java/net/siteed/audiostream/EventSender.kt +0 -7
  38. package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +0 -1113
  39. package/android/src/main/java/net/siteed/audiostream/FFT.kt +0 -99
  40. package/android/src/main/java/net/siteed/audiostream/Features.kt +0 -98
  41. package/android/src/main/java/net/siteed/audiostream/LogUtils.kt +0 -93
  42. package/android/src/main/java/net/siteed/audiostream/NotificationConfig.kt +0 -72
  43. package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +0 -68
  44. package/android/src/main/java/net/siteed/audiostream/RecordingActionReceiver.kt +0 -59
  45. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +0 -257
  46. package/android/src/main/java/net/siteed/audiostream/WaveformConfig.kt +0 -19
  47. package/android/src/main/java/net/siteed/audiostream/WaveformRenderer.kt +0 -159
  48. package/android/src/main/res/drawable/ic_default_action_icon.xml +0 -16
  49. package/android/src/main/res/drawable/ic_microphone.xml +0 -13
  50. package/android/src/main/res/drawable/ic_pause.xml +0 -10
  51. package/android/src/main/res/drawable/ic_play.xml +0 -10
  52. package/android/src/main/res/drawable/ic_stop.xml +0 -10
  53. package/android/src/main/res/layout/notification_recording.xml +0 -37
  54. package/android/src/test/java/net/siteed/audiostream/AudioFileHandlerTest.kt +0 -279
  55. package/android/src/test/java/net/siteed/audiostream/AudioFocusStrategyTest.kt +0 -249
  56. package/android/src/test/java/net/siteed/audiostream/AudioFormatTest.kt +0 -151
  57. package/android/src/test/java/net/siteed/audiostream/AudioFormatUtilsTest.kt +0 -273
  58. package/android/src/test/java/net/siteed/audiostream/DeviceDisconnectionFallbackUnitTest.kt +0 -140
  59. package/android/src/test/resources/chorus.wav +0 -0
  60. package/android/src/test/resources/generate_test_audio.py +0 -94
  61. package/android/src/test/resources/jfk.wav +0 -0
  62. package/android/src/test/resources/osr_us_000_0010_8k.wav +0 -0
  63. package/android/src/test/resources/recorder_hello_world.wav +0 -0
  64. package/app.plugin.js +0 -3
  65. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js +0 -4
  66. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  67. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +0 -210
  68. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  69. package/build/cjs/AudioAnalysis/extractAudioData.js +0 -21
  70. package/build/cjs/AudioAnalysis/extractAudioData.js.map +0 -1
  71. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js +0 -92
  72. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
  73. package/build/cjs/AudioAnalysis/extractPreview.js +0 -28
  74. package/build/cjs/AudioAnalysis/extractPreview.js.map +0 -1
  75. package/build/cjs/AudioAnalysis/extractWaveform.js +0 -18
  76. package/build/cjs/AudioAnalysis/extractWaveform.js.map +0 -1
  77. package/build/cjs/AudioDeviceManager.js +0 -689
  78. package/build/cjs/AudioDeviceManager.js.map +0 -1
  79. package/build/cjs/AudioRecorder.provider.js +0 -78
  80. package/build/cjs/AudioRecorder.provider.js.map +0 -1
  81. package/build/cjs/ExpoAudioStream.native.js +0 -8
  82. package/build/cjs/ExpoAudioStream.native.js.map +0 -1
  83. package/build/cjs/ExpoAudioStream.types.js +0 -11
  84. package/build/cjs/ExpoAudioStream.types.js.map +0 -1
  85. package/build/cjs/ExpoAudioStream.web.js +0 -708
  86. package/build/cjs/ExpoAudioStream.web.js.map +0 -1
  87. package/build/cjs/ExpoAudioStreamModule.js +0 -718
  88. package/build/cjs/ExpoAudioStreamModule.js.map +0 -1
  89. package/build/cjs/WebRecorder.web.js +0 -777
  90. package/build/cjs/WebRecorder.web.js.map +0 -1
  91. package/build/cjs/constants/platformLimitations.js +0 -99
  92. package/build/cjs/constants/platformLimitations.js.map +0 -1
  93. package/build/cjs/constants.js +0 -17
  94. package/build/cjs/constants.js.map +0 -1
  95. package/build/cjs/events.js +0 -29
  96. package/build/cjs/events.js.map +0 -1
  97. package/build/cjs/hooks/useAudioDevices.js +0 -179
  98. package/build/cjs/hooks/useAudioDevices.js.map +0 -1
  99. package/build/cjs/index.js +0 -58
  100. package/build/cjs/index.js.map +0 -1
  101. package/build/cjs/trimAudio.js +0 -76
  102. package/build/cjs/trimAudio.js.map +0 -1
  103. package/build/cjs/useAudioRecorder.js +0 -518
  104. package/build/cjs/useAudioRecorder.js.map +0 -1
  105. package/build/cjs/utils/BlobFix.js +0 -502
  106. package/build/cjs/utils/BlobFix.js.map +0 -1
  107. package/build/cjs/utils/audioProcessing.js +0 -136
  108. package/build/cjs/utils/audioProcessing.js.map +0 -1
  109. package/build/cjs/utils/cleanNativeOptions.js +0 -22
  110. package/build/cjs/utils/cleanNativeOptions.js.map +0 -1
  111. package/build/cjs/utils/concatenateBuffers.js +0 -25
  112. package/build/cjs/utils/concatenateBuffers.js.map +0 -1
  113. package/build/cjs/utils/convertPCMToFloat32.js +0 -124
  114. package/build/cjs/utils/convertPCMToFloat32.js.map +0 -1
  115. package/build/cjs/utils/crc32.js +0 -52
  116. package/build/cjs/utils/crc32.js.map +0 -1
  117. package/build/cjs/utils/encodingToBitDepth.js +0 -17
  118. package/build/cjs/utils/encodingToBitDepth.js.map +0 -1
  119. package/build/cjs/utils/getWavFileInfo.js +0 -96
  120. package/build/cjs/utils/getWavFileInfo.js.map +0 -1
  121. package/build/cjs/utils/writeWavHeader.js +0 -88
  122. package/build/cjs/utils/writeWavHeader.js.map +0 -1
  123. package/build/cjs/workers/InlineFeaturesExtractor.web.js +0 -859
  124. package/build/cjs/workers/InlineFeaturesExtractor.web.js.map +0 -1
  125. package/build/cjs/workers/inlineAudioWebWorker.web.js +0 -184
  126. package/build/cjs/workers/inlineAudioWebWorker.web.js.map +0 -1
  127. package/build/esm/AudioAnalysis/AudioAnalysis.types.js +0 -3
  128. package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  129. package/build/esm/AudioAnalysis/extractAudioAnalysis.js +0 -202
  130. package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  131. package/build/esm/AudioAnalysis/extractAudioData.js +0 -14
  132. package/build/esm/AudioAnalysis/extractAudioData.js.map +0 -1
  133. package/build/esm/AudioAnalysis/extractMelSpectrogram.js +0 -89
  134. package/build/esm/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
  135. package/build/esm/AudioAnalysis/extractPreview.js +0 -25
  136. package/build/esm/AudioAnalysis/extractPreview.js.map +0 -1
  137. package/build/esm/AudioAnalysis/extractWaveform.js +0 -11
  138. package/build/esm/AudioAnalysis/extractWaveform.js.map +0 -1
  139. package/build/esm/AudioDeviceManager.js +0 -682
  140. package/build/esm/AudioDeviceManager.js.map +0 -1
  141. package/build/esm/AudioRecorder.provider.js +0 -40
  142. package/build/esm/AudioRecorder.provider.js.map +0 -1
  143. package/build/esm/ExpoAudioStream.native.js +0 -6
  144. package/build/esm/ExpoAudioStream.native.js.map +0 -1
  145. package/build/esm/ExpoAudioStream.types.js +0 -8
  146. package/build/esm/ExpoAudioStream.types.js.map +0 -1
  147. package/build/esm/ExpoAudioStream.web.js +0 -704
  148. package/build/esm/ExpoAudioStream.web.js.map +0 -1
  149. package/build/esm/ExpoAudioStreamModule.js +0 -713
  150. package/build/esm/ExpoAudioStreamModule.js.map +0 -1
  151. package/build/esm/WebRecorder.web.js +0 -773
  152. package/build/esm/WebRecorder.web.js.map +0 -1
  153. package/build/esm/constants/platformLimitations.js +0 -90
  154. package/build/esm/constants/platformLimitations.js.map +0 -1
  155. package/build/esm/constants.js +0 -14
  156. package/build/esm/constants.js.map +0 -1
  157. package/build/esm/events.js +0 -21
  158. package/build/esm/events.js.map +0 -1
  159. package/build/esm/hooks/useAudioDevices.js +0 -176
  160. package/build/esm/hooks/useAudioDevices.js.map +0 -1
  161. package/build/esm/index.js +0 -20
  162. package/build/esm/index.js.map +0 -1
  163. package/build/esm/trimAudio.js +0 -69
  164. package/build/esm/trimAudio.js.map +0 -1
  165. package/build/esm/useAudioRecorder.js +0 -512
  166. package/build/esm/useAudioRecorder.js.map +0 -1
  167. package/build/esm/utils/BlobFix.js +0 -498
  168. package/build/esm/utils/BlobFix.js.map +0 -1
  169. package/build/esm/utils/audioProcessing.js +0 -133
  170. package/build/esm/utils/audioProcessing.js.map +0 -1
  171. package/build/esm/utils/cleanNativeOptions.js +0 -19
  172. package/build/esm/utils/cleanNativeOptions.js.map +0 -1
  173. package/build/esm/utils/concatenateBuffers.js +0 -21
  174. package/build/esm/utils/concatenateBuffers.js.map +0 -1
  175. package/build/esm/utils/convertPCMToFloat32.js +0 -120
  176. package/build/esm/utils/convertPCMToFloat32.js.map +0 -1
  177. package/build/esm/utils/crc32.js +0 -50
  178. package/build/esm/utils/crc32.js.map +0 -1
  179. package/build/esm/utils/encodingToBitDepth.js +0 -13
  180. package/build/esm/utils/encodingToBitDepth.js.map +0 -1
  181. package/build/esm/utils/getWavFileInfo.js +0 -92
  182. package/build/esm/utils/getWavFileInfo.js.map +0 -1
  183. package/build/esm/utils/writeWavHeader.js +0 -84
  184. package/build/esm/utils/writeWavHeader.js.map +0 -1
  185. package/build/esm/workers/InlineFeaturesExtractor.web.js +0 -856
  186. package/build/esm/workers/InlineFeaturesExtractor.web.js.map +0 -1
  187. package/build/esm/workers/inlineAudioWebWorker.web.js +0 -181
  188. package/build/esm/workers/inlineAudioWebWorker.web.js.map +0 -1
  189. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +0 -196
  190. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
  191. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts +0 -74
  192. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
  193. package/build/types/AudioAnalysis/extractAudioData.d.ts +0 -3
  194. package/build/types/AudioAnalysis/extractAudioData.d.ts.map +0 -1
  195. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts +0 -14
  196. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts.map +0 -1
  197. package/build/types/AudioAnalysis/extractPreview.d.ts +0 -11
  198. package/build/types/AudioAnalysis/extractPreview.d.ts.map +0 -1
  199. package/build/types/AudioAnalysis/extractWaveform.d.ts +0 -8
  200. package/build/types/AudioAnalysis/extractWaveform.d.ts.map +0 -1
  201. package/build/types/AudioDeviceManager.d.ts +0 -187
  202. package/build/types/AudioDeviceManager.d.ts.map +0 -1
  203. package/build/types/AudioRecorder.provider.d.ts +0 -11
  204. package/build/types/AudioRecorder.provider.d.ts.map +0 -1
  205. package/build/types/ExpoAudioStream.native.d.ts +0 -3
  206. package/build/types/ExpoAudioStream.native.d.ts.map +0 -1
  207. package/build/types/ExpoAudioStream.types.d.ts +0 -738
  208. package/build/types/ExpoAudioStream.types.d.ts.map +0 -1
  209. package/build/types/ExpoAudioStream.web.d.ts +0 -96
  210. package/build/types/ExpoAudioStream.web.d.ts.map +0 -1
  211. package/build/types/ExpoAudioStreamModule.d.ts +0 -3
  212. package/build/types/ExpoAudioStreamModule.d.ts.map +0 -1
  213. package/build/types/WebRecorder.web.d.ts +0 -198
  214. package/build/types/WebRecorder.web.d.ts.map +0 -1
  215. package/build/types/constants/platformLimitations.d.ts +0 -40
  216. package/build/types/constants/platformLimitations.d.ts.map +0 -1
  217. package/build/types/constants.d.ts +0 -11
  218. package/build/types/constants.d.ts.map +0 -1
  219. package/build/types/events.d.ts +0 -26
  220. package/build/types/events.d.ts.map +0 -1
  221. package/build/types/hooks/useAudioDevices.d.ts +0 -15
  222. package/build/types/hooks/useAudioDevices.d.ts.map +0 -1
  223. package/build/types/index.d.ts +0 -18
  224. package/build/types/index.d.ts.map +0 -1
  225. package/build/types/trimAudio.d.ts +0 -25
  226. package/build/types/trimAudio.d.ts.map +0 -1
  227. package/build/types/useAudioRecorder.d.ts +0 -22
  228. package/build/types/useAudioRecorder.d.ts.map +0 -1
  229. package/build/types/utils/BlobFix.d.ts +0 -9
  230. package/build/types/utils/BlobFix.d.ts.map +0 -1
  231. package/build/types/utils/audioProcessing.d.ts +0 -24
  232. package/build/types/utils/audioProcessing.d.ts.map +0 -1
  233. package/build/types/utils/cleanNativeOptions.d.ts +0 -15
  234. package/build/types/utils/cleanNativeOptions.d.ts.map +0 -1
  235. package/build/types/utils/concatenateBuffers.d.ts +0 -8
  236. package/build/types/utils/concatenateBuffers.d.ts.map +0 -1
  237. package/build/types/utils/convertPCMToFloat32.d.ts +0 -13
  238. package/build/types/utils/convertPCMToFloat32.d.ts.map +0 -1
  239. package/build/types/utils/crc32.d.ts +0 -7
  240. package/build/types/utils/crc32.d.ts.map +0 -1
  241. package/build/types/utils/encodingToBitDepth.d.ts +0 -5
  242. package/build/types/utils/encodingToBitDepth.d.ts.map +0 -1
  243. package/build/types/utils/getWavFileInfo.d.ts +0 -26
  244. package/build/types/utils/getWavFileInfo.d.ts.map +0 -1
  245. package/build/types/utils/writeWavHeader.d.ts +0 -34
  246. package/build/types/utils/writeWavHeader.d.ts.map +0 -1
  247. package/build/types/workers/InlineFeaturesExtractor.web.d.ts +0 -2
  248. package/build/types/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
  249. package/build/types/workers/inlineAudioWebWorker.web.d.ts +0 -2
  250. package/build/types/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
  251. package/expo-module.config.json +0 -10
  252. package/ios/AudioAnalysisData.swift +0 -74
  253. package/ios/AudioDeviceManager.swift +0 -670
  254. package/ios/AudioNotificationManager.swift +0 -154
  255. package/ios/AudioProcessingHelpers.swift +0 -743
  256. package/ios/AudioProcessor.swift +0 -1151
  257. package/ios/AudioStreamError.swift +0 -7
  258. package/ios/AudioStreamManager.swift +0 -2369
  259. package/ios/AudioStreamManagerDelegate.swift +0 -16
  260. package/ios/DataPoint.swift +0 -54
  261. package/ios/DecodingConfig.swift +0 -59
  262. package/ios/ExpoAudioStream.podspec +0 -33
  263. package/ios/ExpoAudioStreamModule.swift +0 -1019
  264. package/ios/ExpoAudioStudioTests/AudioFileHandlerTests.swift +0 -338
  265. package/ios/ExpoAudioStudioTests/AudioFormatUtilsTests.swift +0 -331
  266. package/ios/ExpoAudioStudioTests/AudioTestHelpers.swift +0 -130
  267. package/ios/ExpoAudioStudioTests/CompressedOnlyOutputTests.swift +0 -294
  268. package/ios/ExpoAudioStudioTests/EventEmissionIntervalTests.swift +0 -105
  269. package/ios/ExpoAudioStudioTests/Info.plist +0 -22
  270. package/ios/ExpoAudioStudioTests/README.md +0 -39
  271. package/ios/ExpoAudioStudioTests/SimpleAudioTest.swift +0 -98
  272. package/ios/ExpoAudioStudioTests/TestAudioGenerator.swift +0 -75
  273. package/ios/FFT.swift +0 -62
  274. package/ios/Features.swift +0 -95
  275. package/ios/ISSUE_IOS.md +0 -68
  276. package/ios/Logger.swift +0 -39
  277. package/ios/NotificationExtension.swift +0 -15
  278. package/ios/RecordingResult.swift +0 -22
  279. package/ios/RecordingSettings.swift +0 -308
  280. package/ios/WaveformExtractor.swift +0 -105
  281. package/ios/tests/README.md +0 -41
  282. package/ios/tests/integration/buffer_and_fallback_test.swift +0 -178
  283. package/ios/tests/integration/buffer_duration_test.swift +0 -185
  284. package/ios/tests/integration/compressed_only_output_test.swift +0 -271
  285. package/ios/tests/integration/output_control_test.swift +0 -322
  286. package/ios/tests/integration/run_integration_tests.sh +0 -37
  287. package/ios/tests/opus_support_test_macos.swift +0 -154
  288. package/ios/tests/standalone/audio_processing_test.swift +0 -144
  289. package/ios/tests/standalone/audio_recording_test.swift +0 -277
  290. package/ios/tests/standalone/audio_streaming_test.swift +0 -249
  291. package/ios/tests/standalone/standalone_test.swift +0 -144
  292. package/plugin/build/index.cjs +0 -194
  293. package/plugin/build/index.d.cts +0 -22
  294. package/plugin/build/index.js +0 -194
  295. package/plugin/src/index.ts +0 -285
  296. package/plugin/tsconfig.json +0 -10
  297. package/plugin/tsconfig.tsbuildinfo +0 -1
  298. package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -224
  299. package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -344
  300. package/src/AudioAnalysis/extractAudioData.ts +0 -17
  301. package/src/AudioAnalysis/extractMelSpectrogram.ts +0 -154
  302. package/src/AudioAnalysis/extractPreview.ts +0 -34
  303. package/src/AudioAnalysis/extractWaveform.ts +0 -22
  304. package/src/AudioDeviceManager.ts +0 -803
  305. package/src/AudioRecorder.provider.tsx +0 -57
  306. package/src/ExpoAudioStream.native.ts +0 -6
  307. package/src/ExpoAudioStream.types.ts +0 -874
  308. package/src/ExpoAudioStream.web.ts +0 -905
  309. package/src/ExpoAudioStreamModule.ts +0 -990
  310. package/src/WebRecorder.web.ts +0 -1005
  311. package/src/constants/platformLimitations.ts +0 -118
  312. package/src/constants.ts +0 -18
  313. package/src/events.ts +0 -60
  314. package/src/hooks/useAudioDevices.ts +0 -213
  315. package/src/index.ts +0 -54
  316. package/src/trimAudio.ts +0 -94
  317. package/src/types/crc-32.d.ts +0 -9
  318. package/src/useAudioRecorder.tsx +0 -766
  319. package/src/utils/BlobFix.ts +0 -561
  320. package/src/utils/audioProcessing.ts +0 -205
  321. package/src/utils/cleanNativeOptions.ts +0 -18
  322. package/src/utils/concatenateBuffers.ts +0 -24
  323. package/src/utils/convertPCMToFloat32.ts +0 -170
  324. package/src/utils/crc32.ts +0 -59
  325. package/src/utils/encodingToBitDepth.ts +0 -18
  326. package/src/utils/getWavFileInfo.ts +0 -132
  327. package/src/utils/writeWavHeader.ts +0 -115
  328. package/src/workers/InlineFeaturesExtractor.web.tsx +0 -855
  329. package/src/workers/inlineAudioWebWorker.web.tsx +0 -180
@@ -1,856 +0,0 @@
1
- // packages/expo-audio-studio/src/workers/InlineFeaturesExtractor.web.tsx
2
- export const InlineFeaturesExtractor = `
3
- // Constants
4
- const N_FFT = 1024; // Default FFT size
5
- const MAX_FFT_SIZE = 8192; // Maximum FFT size to prevent memory issues
6
- const N_CHROMA = 12;
7
-
8
- // FFT Implementation with normalized Hann window
9
- function FFT(n) {
10
- this.n = n;
11
- this.cosTable = new Float32Array(n / 2);
12
- this.sinTable = new Float32Array(n / 2);
13
- this.hannWindow = new Float32Array(n);
14
-
15
- // Match Android implementation with precomputed tables
16
- const normalizationFactor = Math.sqrt(2.0 / n);
17
- for (var i = 0; i < n / 2; i++) {
18
- this.cosTable[i] = Math.cos(2.0 * Math.PI * i / n);
19
- this.sinTable[i] = Math.sin(2.0 * Math.PI * i / n);
20
- }
21
-
22
- // Precompute normalized Hann window to match Android
23
- for (var i = 0; i < n; i++) {
24
- this.hannWindow[i] = normalizationFactor * 0.5 * (1 - Math.cos(2.0 * Math.PI * i / (n - 1)));
25
- }
26
- }
27
-
28
- FFT.prototype.transform = function(data) {
29
- const n = data.length;
30
-
31
- // Validate input length is power of 2
32
- if ((n & (n - 1)) !== 0) {
33
- throw new Error('FFT length must be power of 2');
34
- }
35
-
36
- // Use iterative bit reversal instead of recursive
37
- const bitReversedIndices = new Uint32Array(n);
38
- for (let i = 0; i < n; i++) {
39
- let reversed = 0;
40
- let j = i;
41
- let bits = Math.log2(n);
42
- while (bits--) {
43
- reversed = (reversed << 1) | (j & 1);
44
- j >>= 1;
45
- }
46
- bitReversedIndices[i] = reversed;
47
- }
48
-
49
- // Apply bit reversal
50
- for (let i = 0; i < n; i++) {
51
- const j = bitReversedIndices[i];
52
- if (i < j) {
53
- const temp = data[i];
54
- data[i] = data[j];
55
- data[j] = temp;
56
- }
57
- }
58
-
59
- // Iterative FFT computation with optimized memory usage
60
- for (let step = 1; step < n; step <<= 1) {
61
- const jump = step << 1;
62
- const angleStep = Math.PI / step;
63
-
64
- for (let group = 0; group < n; group += jump) {
65
- for (let pair = group; pair < group + step; pair++) {
66
- const match = pair + step;
67
- const angle = angleStep * (pair - group);
68
-
69
- const currentCos = Math.cos(angle);
70
- const currentSin = Math.sin(angle);
71
-
72
- const real = currentCos * data[match] - currentSin * data[match + 1];
73
- const imag = currentCos * data[match + 1] + currentSin * data[match];
74
-
75
- data[match] = data[pair] - real;
76
- data[match + 1] = data[pair + 1] - imag;
77
- data[pair] += real;
78
- data[pair + 1] += imag;
79
- }
80
- }
81
- }
82
- };
83
-
84
- // Add realInverse method
85
- FFT.prototype.realInverse = function(powerSpectrum, output) {
86
- const n = powerSpectrum.length;
87
- const complexData = new Float32Array(n * 2);
88
-
89
- // Copy power spectrum to complex format
90
- for (let i = 0; i < n/2 + 1; i++) {
91
- complexData[2 * i] = powerSpectrum[i];
92
- if (2 * i + 1 < complexData.length) {
93
- complexData[2 * i + 1] = 0;
94
- }
95
- }
96
-
97
- // Conjugate for inverse FFT
98
- for (let i = 0; i < n; i++) {
99
- if (2 * i + 1 < complexData.length) {
100
- complexData[2 * i + 1] = -complexData[2 * i + 1];
101
- }
102
- }
103
-
104
- this.transform(complexData);
105
-
106
- // Copy real part to output and scale
107
- for (let i = 0; i < n; i++) {
108
- output[i] = complexData[2 * i] / n;
109
- }
110
- };
111
-
112
- // Add helper functions to match Android
113
- function nextPowerOfTwo(n) {
114
- let value = 1;
115
- while (value < n) {
116
- value *= 2;
117
- }
118
- return value;
119
- }
120
-
121
- function applyHannWindow(samples) {
122
- const output = new Float32Array(samples.length);
123
- for (let i = 0; i < samples.length; i++) {
124
- const multiplier = 0.5 * (1 - Math.cos(2 * Math.PI * i / (samples.length - 1)));
125
- output[i] = samples[i] * multiplier;
126
- }
127
- return output;
128
- }
129
-
130
- // Update spectral feature computation to match Android
131
- function computeSpectralFeatures(segment, sampleRate, featureOptions = {}) {
132
- try {
133
- // Early return if no spectral features are requested
134
- if (!featureOptions.spectralCentroid &&
135
- !featureOptions.spectralFlatness &&
136
- !featureOptions.spectralRollOff &&
137
- !featureOptions.spectralBandwidth &&
138
- !featureOptions.magnitudeSpectrum) {
139
- return {
140
- centroid: 0,
141
- flatness: 0,
142
- rollOff: 0,
143
- bandwidth: 0,
144
- magnitudeSpectrum: []
145
- };
146
- }
147
-
148
- // Ensure we have valid data
149
- if (!segment || segment.length === 0) {
150
- throw new Error('Invalid segment data');
151
- }
152
-
153
- // Process in fixed-size chunks
154
- const chunkSize = N_FFT;
155
- const numChunks = Math.ceil(segment.length / chunkSize);
156
-
157
- let results = {
158
- centroid: 0,
159
- flatness: 0,
160
- rollOff: 0,
161
- bandwidth: 0,
162
- magnitudeSpectrum: new Float32Array(N_FFT / 2 + 1).fill(0)
163
- };
164
-
165
- let validChunks = 0;
166
-
167
- // Iterate through chunks
168
- for (let i = 0; i < numChunks; i++) {
169
- const start = i * chunkSize;
170
- const end = Math.min(start + chunkSize, segment.length);
171
- const chunk = segment.slice(start, end);
172
-
173
- if (chunk.length < N_FFT / 4) continue; // Skip very small chunks
174
-
175
- // Process the chunk
176
- const paddedChunk = new Float32Array(N_FFT);
177
- paddedChunk.set(applyHannWindow(chunk));
178
-
179
- const fft = new FFT(N_FFT);
180
- fft.transform(paddedChunk);
181
-
182
- // Calculate magnitude spectrum
183
- const chunkMagnitudeSpectrum = new Float32Array(N_FFT / 2 + 1);
184
- let hasSignal = false;
185
-
186
- for (let j = 0; j < N_FFT / 2; j++) {
187
- const re = paddedChunk[2 * j];
188
- const im = paddedChunk[2 * j + 1];
189
- const magnitude = Math.sqrt(re * re + im * im);
190
- chunkMagnitudeSpectrum[j] = magnitude;
191
- if (magnitude > Number.EPSILON) hasSignal = true;
192
- }
193
-
194
- if (!hasSignal) continue;
195
- validChunks++;
196
-
197
- // Accumulate results
198
- if (featureOptions.spectralCentroid) {
199
- const centroid = computeSpectralCentroid(chunkMagnitudeSpectrum, sampleRate);
200
- if (!isNaN(centroid)) results.centroid += centroid;
201
- }
202
-
203
- if (featureOptions.spectralFlatness) {
204
- const flatness = computeSpectralFlatness(chunkMagnitudeSpectrum);
205
- if (!isNaN(flatness)) results.flatness += flatness;
206
- }
207
-
208
- if (featureOptions.spectralRollOff) {
209
- const rolloff = computeSpectralRollOff(chunkMagnitudeSpectrum, sampleRate);
210
- if (!isNaN(rolloff)) results.rollOff += rolloff;
211
- }
212
-
213
- if (featureOptions.spectralBandwidth && !isNaN(results.centroid)) {
214
- const bandwidth = computeSpectralBandwidth(chunkMagnitudeSpectrum, sampleRate, results.centroid);
215
- if (!isNaN(bandwidth)) results.bandwidth += bandwidth;
216
- }
217
-
218
- if (featureOptions.magnitudeSpectrum) {
219
- for (let j = 0; j < results.magnitudeSpectrum.length; j++) {
220
- results.magnitudeSpectrum[j] += chunkMagnitudeSpectrum[j];
221
- }
222
- }
223
- }
224
-
225
- // Average the accumulated results
226
- if (validChunks > 0) {
227
- results.centroid /= validChunks;
228
- results.flatness /= validChunks;
229
- results.rollOff /= validChunks;
230
- results.bandwidth /= validChunks;
231
-
232
- if (featureOptions.magnitudeSpectrum) {
233
- for (let i = 0; i < results.magnitudeSpectrum.length; i++) {
234
- results.magnitudeSpectrum[i] /= validChunks;
235
- }
236
- }
237
- }
238
-
239
- return results;
240
- } catch (error) {
241
- console.error('[Worker] Spectral feature computation error:', error);
242
- return {
243
- centroid: 0,
244
- flatness: 0,
245
- rollOff: 0,
246
- bandwidth: 0,
247
- magnitudeSpectrum: []
248
- };
249
- }
250
- }
251
-
252
- function computeSpectralCentroid(magnitudeSpectrum, sampleRate) {
253
- const sum = magnitudeSpectrum.reduce((a, b) => a + (b || 0), 0);
254
- if (sum <= Number.EPSILON) return 0;
255
-
256
- const weightedSum = magnitudeSpectrum.reduce((acc, value, index) =>
257
- acc + (index * (sampleRate / N_FFT) * (value || 0)), 0);
258
-
259
- return weightedSum / sum;
260
- }
261
-
262
- function computeSpectralFlatness(powerSpectrum) {
263
- // Add small epsilon to avoid log(0)
264
- const epsilon = Number.EPSILON;
265
- const validSpectrum = powerSpectrum.map(v => Math.max(v, epsilon));
266
-
267
- const geometricMean = Math.exp(
268
- validSpectrum
269
- .map(v => Math.log(v))
270
- .reduce((a, b) => a + b) / validSpectrum.length
271
- );
272
-
273
- const arithmeticMean =
274
- validSpectrum.reduce((a, b) => a + b) / validSpectrum.length;
275
-
276
- return geometricMean / arithmeticMean;
277
- }
278
-
279
- function computeSpectralRollOff(magnitudeSpectrum, sampleRate) {
280
- const totalEnergy = magnitudeSpectrum.reduce((a, b) => a + b, 0);
281
- const rollOffThreshold = totalEnergy * 0.85;
282
- let cumulativeEnergy = 0;
283
-
284
- for (let i = 0; i < magnitudeSpectrum.length; i++) {
285
- cumulativeEnergy += magnitudeSpectrum[i];
286
- if (cumulativeEnergy >= rollOffThreshold) {
287
- return (i / magnitudeSpectrum.length) * (sampleRate / 2);
288
- }
289
- }
290
-
291
- return 0;
292
- }
293
-
294
- function computeSpectralBandwidth(magnitudeSpectrum, sampleRate, centroid) {
295
- const sum = magnitudeSpectrum.reduce((a, b) => a + (b || 0), 0);
296
- if (sum <= Number.EPSILON) return 0;
297
-
298
- const weightedSum = magnitudeSpectrum.reduce(
299
- (acc, value, index) => {
300
- const freq = index * sampleRate / (2 * magnitudeSpectrum.length);
301
- return acc + (value || 0) * Math.pow(freq - centroid, 2);
302
- }, 0
303
- );
304
-
305
- return Math.sqrt(weightedSum / sum);
306
- }
307
-
308
- function computeChroma(segmentData, sampleRate) {
309
- // Ensure we have valid input data
310
- if (!segmentData || segmentData.length === 0) {
311
- return new Array(N_CHROMA).fill(0);
312
- }
313
-
314
- const fftLength = nextPowerOfTwo(Math.max(segmentData.length, N_FFT));
315
- const windowed = applyHannWindow(segmentData);
316
- const padded = new Float32Array(fftLength);
317
- padded.set(windowed.slice(0, Math.min(windowed.length, fftLength)));
318
-
319
- const fft = new FFT(fftLength);
320
- try {
321
- fft.transform(padded);
322
- } catch (e) {
323
- console.error('[Worker] FFT transform failed in chromagram:', e);
324
- return new Array(N_CHROMA).fill(0);
325
- }
326
-
327
- const chroma = new Float32Array(N_CHROMA).fill(0);
328
- const freqsPerBin = sampleRate / fftLength;
329
- let totalEnergy = 0;
330
-
331
- // First pass: compute magnitudes and total energy
332
- for (let i = 0; i < fftLength / 2; i++) {
333
- const freq = i * freqsPerBin;
334
- if (freq > 20) { // Only consider frequencies above 20 Hz
335
- const re = padded[2 * i];
336
- const im = padded[2 * i + 1] || 0;
337
- const magnitude = Math.sqrt(re * re + im * im);
338
-
339
- if (magnitude > Number.EPSILON) {
340
- // Use a more stable pitch class calculation
341
- const midiNote = 69 + 12 * Math.log2(freq / 440.0);
342
- const pitchClass = Math.round(midiNote) % 12;
343
-
344
- if (pitchClass >= 0 && pitchClass < 12) {
345
- chroma[pitchClass] += magnitude;
346
- totalEnergy += magnitude;
347
- }
348
- }
349
- }
350
- }
351
-
352
- // Normalize chroma values only if we have energy
353
- if (totalEnergy > Number.EPSILON) {
354
- for (let i = 0; i < N_CHROMA; i++) {
355
- chroma[i] = chroma[i] / totalEnergy;
356
- }
357
- }
358
-
359
- // Convert to regular array and ensure no NaN values
360
- return Array.from(chroma, v => isNaN(v) ? 0 : v);
361
- }
362
-
363
- function extractHNR(segmentData) {
364
- const frameSize = segmentData.length;
365
- const autocorrelation = new Float32Array(frameSize);
366
-
367
- // Compute the autocorrelation iteratively
368
- for (let i = 0; i < frameSize; i++) {
369
- let sum = 0;
370
- for (let j = 0; j < frameSize - i; j++) {
371
- sum += segmentData[j] * segmentData[j + i];
372
- }
373
- autocorrelation[i] = sum;
374
- }
375
-
376
- // Find the maximum autocorrelation value iteratively
377
- let maxAutocorrelation = -Infinity;
378
- for (let i = 1; i < autocorrelation.length; i++) {
379
- if (autocorrelation[i] > maxAutocorrelation) {
380
- maxAutocorrelation = autocorrelation[i];
381
- }
382
- }
383
-
384
- // Compute the HNR
385
- return autocorrelation[0] !== 0
386
- ? 10 * Math.log10(maxAutocorrelation / (autocorrelation[0] - maxAutocorrelation))
387
- : 0;
388
- }
389
-
390
- function estimatePitch(segment, sampleRate) {
391
- // Early validation
392
- if (!segment || segment.length < 2 || !sampleRate) return 0;
393
-
394
- try {
395
- // Apply Hann window
396
- const windowed = applyHannWindow(segment);
397
-
398
- // Pad for FFT
399
- const fftLength = nextPowerOfTwo(segment.length * 2);
400
- const padded = new Float32Array(fftLength);
401
- padded.set(windowed);
402
-
403
- // Perform FFT
404
- const fft = new FFT(fftLength);
405
- fft.transform(padded);
406
-
407
- // Compute power spectrum
408
- const powerSpectrum = new Float32Array(fftLength / 2 + 1);
409
- for (let i = 0; i <= fftLength / 2; i++) {
410
- const re = padded[2 * i];
411
- const im = padded[2 * i + 1] || 0;
412
- powerSpectrum[i] = re * re + im * im;
413
- }
414
-
415
- // Find peak frequency
416
- let maxPower = 0;
417
- let peakIndex = 0;
418
- const minFreq = 50; // Minimum frequency to consider (Hz)
419
- const maxFreq = 1000; // Maximum frequency to consider (Hz)
420
- const minBin = Math.floor(minFreq * fftLength / sampleRate);
421
- const maxBin = Math.ceil(maxFreq * fftLength / sampleRate);
422
-
423
- for (let i = minBin; i <= maxBin; i++) {
424
- if (powerSpectrum[i] > maxPower) {
425
- maxPower = powerSpectrum[i];
426
- peakIndex = i;
427
- }
428
- }
429
-
430
- // Convert peak index to frequency
431
- const fundamentalFreq = peakIndex * sampleRate / fftLength;
432
-
433
- // Return 0 if the detected frequency is outside reasonable bounds
434
- return (fundamentalFreq >= minFreq && fundamentalFreq <= maxFreq) ?
435
- fundamentalFreq : 0;
436
-
437
- } catch (error) {
438
- console.error('[Worker] Pitch estimation error:', error);
439
- return 0;
440
- }
441
- }
442
-
443
- // Unique ID counter - the only state we need to maintain
444
- let uniqueIdCounter = 0
445
- let lastEmitTime = Date.now()
446
-
447
- self.onmessage = function (event) {
448
- // Extract enableLogging early so we can use it consistently
449
- const enableLogging = event.data.enableLogging || false;
450
-
451
- // Create consistent logger that only logs when enabled
452
- const logger = enableLogging ? {
453
- debug: (...args) => console.debug('[Worker]', ...args),
454
- log: (...args) => console.log('[Worker]', ...args),
455
- warn: (...args) => console.warn('[Worker]', ...args),
456
- error: (...args) => console.error('[Worker]', ...args)
457
- } : {
458
- debug: () => {},
459
- log: () => {},
460
- warn: () => {},
461
- error: () => {}
462
- };
463
-
464
- // Check if this is a reset command
465
- if (event.data.command === 'resetCounter') {
466
- const newValue = event.data.value;
467
- logger.log('Reset counter request received with value:', newValue);
468
-
469
- // Always respect explicit resets through the resetCounter command
470
- uniqueIdCounter = typeof newValue === 'number' ? newValue : 0;
471
- logger.log('Counter explicitly set to:', uniqueIdCounter);
472
-
473
- return; // Exit early, don't process audio
474
- }
475
-
476
- // Regular audio processing
477
- const {
478
- channelData,
479
- sampleRate,
480
- segmentDurationMs,
481
- algorithm,
482
- bitDepth,
483
- fullAudioDurationMs,
484
- numberOfChannels,
485
- features: _features,
486
- intervalAnalysis = 500,
487
- } = event.data
488
-
489
- // Calculate subChunkStartTime safely, defaulting to 0 if fullAudioDurationMs is not a valid number
490
- const subChunkStartTime = (typeof fullAudioDurationMs === 'number' && !isNaN(fullAudioDurationMs) && fullAudioDurationMs >= 0)
491
- ? fullAudioDurationMs / 1000
492
- : 0;
493
-
494
- const features = _features || {}
495
- const bytesPerSample = bitDepth / 8; // Calculate bytes per sample
496
-
497
- const SILENCE_THRESHOLD = 0.01
498
- const MIN_SILENCE_DURATION = 1.5 * sampleRate // 1.5 seconds of silence
499
- const SPEECH_INERTIA_DURATION = 0.1 * sampleRate // Speech inertia duration in samples
500
- const RMS_THRESHOLD = 0.01
501
- const ZCR_THRESHOLD = 0.1
502
-
503
- // Placeholder functions for feature extraction
504
- const extractMFCC = (segmentData, sampleRate) => {
505
- // Implement MFCC extraction logic here
506
- return []
507
- }
508
-
509
- const extractSpectralCentroid = (segmentData, sampleRate) => {
510
- const magnitudeSpectrum = segmentData.map((v) => v * v)
511
- const sum = magnitudeSpectrum.reduce((a, b) => a + b, 0)
512
- if (sum === 0) return 0
513
-
514
- const weightedSum = magnitudeSpectrum.reduce(
515
- (acc, value, index) => acc + index * value,
516
- 0
517
- )
518
- return (
519
- ((weightedSum / sum) * (sampleRate / 2)) / magnitudeSpectrum.length
520
- )
521
- }
522
-
523
- const extractSpectralFlatness = (segmentData) => {
524
- const magnitudeSpectrum = segmentData.map((v) => Math.abs(v))
525
- const geometricMean = Math.exp(
526
- magnitudeSpectrum
527
- .map((v) => Math.log(v + Number.MIN_VALUE))
528
- .reduce((a, b) => a + b) / magnitudeSpectrum.length
529
- )
530
- const arithmeticMean =
531
- magnitudeSpectrum.reduce((a, b) => a + b) / magnitudeSpectrum.length
532
- return arithmeticMean === 0 ? 0 : geometricMean / arithmeticMean
533
- }
534
-
535
- const extractSpectralRollOff = (segmentData, sampleRate) => {
536
- const magnitudeSpectrum = segmentData.map((v) => Math.abs(v))
537
- const totalEnergy = magnitudeSpectrum.reduce((a, b) => a + b, 0)
538
- const rollOffThreshold = totalEnergy * 0.85
539
- let cumulativeEnergy = 0
540
-
541
- for (let i = 0; i < magnitudeSpectrum.length; i++) {
542
- cumulativeEnergy += magnitudeSpectrum[i]
543
- if (cumulativeEnergy >= rollOffThreshold) {
544
- return (i / magnitudeSpectrum.length) * (sampleRate / 2)
545
- }
546
- }
547
-
548
- return 0
549
- }
550
-
551
- const extractSpectralBandwidth = (segmentData, sampleRate) => {
552
- const centroid = extractSpectralCentroid(segmentData, sampleRate)
553
- const magnitudeSpectrum = segmentData.map((v) => Math.abs(v))
554
- const sum = magnitudeSpectrum.reduce((a, b) => a + b, 0)
555
- if (sum === 0) return 0
556
-
557
- const weightedSum = magnitudeSpectrum.reduce(
558
- (acc, value, index) => acc + value * Math.pow(index - centroid, 2),
559
- 0
560
- )
561
- return Math.sqrt(weightedSum / sum)
562
- }
563
-
564
- const extractChromagram = (segmentData, sampleRate) => {
565
- return [] // TODO implement
566
- }
567
-
568
- /**
569
- * Creates a features object based on requested features
570
- */
571
- function createFeaturesObject(
572
- features,
573
- maxAmp,
574
- rms,
575
- sumSquares,
576
- zeroCrossings,
577
- remainingSamples,
578
- spectralFeatures,
579
- channelData,
580
- startIdx,
581
- endIdx,
582
- sampleRate,
583
- numberOfChannels,
584
- bytesPerSample
585
- ) {
586
- // If no features are requested, return undefined
587
- if (!Object.values(features).some(function(v) { return v; })) {
588
- return undefined;
589
- }
590
-
591
- const result = {};
592
-
593
- if (features.energy) {
594
- result.energy = sumSquares;
595
- }
596
- if (features.rms) {
597
- result.rms = rms;
598
- }
599
- // Always include min/max amplitude if any features are requested
600
- result.minAmplitude = -maxAmp;
601
- result.maxAmplitude = maxAmp;
602
-
603
- if (features.zcr) {
604
- result.zcr = zeroCrossings / remainingSamples;
605
- }
606
- if (features.spectralCentroid) {
607
- result.spectralCentroid = spectralFeatures.centroid;
608
- }
609
- if (features.spectralFlatness) {
610
- result.spectralFlatness = spectralFeatures.flatness;
611
- }
612
- if (features.spectralRolloff) {
613
- result.spectralRolloff = spectralFeatures.rollOff;
614
- }
615
- if (features.spectralBandwidth) {
616
- result.spectralBandwidth = spectralFeatures.bandwidth;
617
- }
618
- if (features.chromagram) {
619
- result.chromagram = computeChroma(channelData.slice(startIdx, endIdx), sampleRate);
620
- }
621
- if (features.hnr) {
622
- result.hnr = extractHNR(channelData.slice(startIdx, endIdx));
623
- }
624
- if (features.pitch) {
625
- result.pitch = estimatePitch(channelData.slice(startIdx, endIdx), sampleRate);
626
- }
627
-
628
- return result;
629
- }
630
-
631
- function extractWaveform(
632
- channelData,
633
- sampleRate,
634
- segmentDurationMs,
635
- numberOfChannels,
636
- bytesPerSample
637
- ) {
638
- const logger = enableLogging ? {
639
- debug: (...args) => console.debug('[Worker]', ...args),
640
- log: (...args) => console.log('[Worker]', ...args),
641
- error: (...args) => console.error('[Worker]', ...args)
642
- } : {
643
- debug: () => {},
644
- log: () => {},
645
- error: () => {}
646
- }
647
-
648
- // Calculate amplitude range
649
- let min = Infinity
650
- let max = -Infinity
651
- for (let i = 0; i < channelData.length; i++) {
652
- min = Math.min(min, channelData[i])
653
- max = Math.max(max, channelData[i])
654
- }
655
-
656
- const totalSamples = channelData.length
657
- const durationMs = (totalSamples / sampleRate) * 1000
658
-
659
- // Calculate fixed segment sizes
660
- const samplesPerSegment = Math.floor(sampleRate * (segmentDurationMs / 1000));
661
- const numPoints = Math.floor(totalSamples / samplesPerSegment);
662
- const remainingSamples = totalSamples % samplesPerSegment;
663
-
664
- const dataPoints = []
665
-
666
- // Process full segments
667
- for (let i = 0; i < numPoints; i++) {
668
- const startIdx = i * samplesPerSegment
669
- const endIdx = startIdx + samplesPerSegment
670
-
671
- let sumSquares = 0
672
- let maxAmp = 0
673
- let zeroCrossings = 0
674
-
675
- // Calculate segment features
676
- for (let j = startIdx; j < endIdx; j++) {
677
- const value = channelData[j]
678
- sumSquares += value * value
679
- maxAmp = Math.max(maxAmp, Math.abs(value))
680
- if (j > 0 && value * channelData[j - 1] < 0) {
681
- zeroCrossings++
682
- }
683
- }
684
-
685
- const rms = Math.sqrt(sumSquares / samplesPerSegment)
686
- const startTime = subChunkStartTime + (startIdx / sampleRate)
687
- const endTime = subChunkStartTime + (endIdx / sampleRate)
688
- // Calculate byte positions correctly based on numberOfChannels and bytesPerSample
689
- const startPosition = startIdx * numberOfChannels * bytesPerSample
690
- const endPosition = endIdx * numberOfChannels * bytesPerSample
691
-
692
- var spectralFeatures = computeSpectralFeatures(channelData.slice(startIdx, endIdx), sampleRate, features);
693
-
694
- // Simply use the counter, increment after assigning
695
- const dataPoint = {
696
- id: uniqueIdCounter++,
697
- amplitude: maxAmp,
698
- rms,
699
- startTime,
700
- endTime,
701
- dB: 20 * Math.log10(rms + 1e-6),
702
- silent: rms < 0.01,
703
- startPosition,
704
- endPosition,
705
- samples: samplesPerSegment,
706
- }
707
-
708
- // Extract features if any are requested
709
- const extractedFeatures = createFeaturesObject(
710
- features,
711
- maxAmp,
712
- rms,
713
- sumSquares,
714
- zeroCrossings,
715
- samplesPerSegment,
716
- spectralFeatures,
717
- channelData,
718
- startIdx,
719
- endIdx,
720
- sampleRate,
721
- numberOfChannels,
722
- bytesPerSample
723
- );
724
-
725
- if (extractedFeatures) {
726
- dataPoint.features = extractedFeatures;
727
- }
728
-
729
- dataPoints.push(dataPoint)
730
- }
731
-
732
- // Handle remaining samples if they exist and are enough to process
733
- if (remainingSamples > samplesPerSegment / 4) { // Only process if we have at least 1/4 of a segment
734
- const startIdx = numPoints * samplesPerSegment
735
- const endIdx = totalSamples
736
-
737
- let sumSquares = 0
738
- let maxAmp = 0
739
- let zeroCrossings = 0
740
-
741
- for (let j = startIdx; j < endIdx; j++) {
742
- const value = channelData[j]
743
- sumSquares += value * value
744
- maxAmp = Math.max(maxAmp, Math.abs(value))
745
- if (j > 0 && value * channelData[j - 1] < 0) {
746
- zeroCrossings++
747
- }
748
- }
749
-
750
- const rms = Math.sqrt(sumSquares / remainingSamples)
751
- const startTime = subChunkStartTime + (startIdx / sampleRate);
752
- const endTime = subChunkStartTime + (endIdx / sampleRate);
753
- // Calculate byte positions correctly based on numberOfChannels and bytesPerSample
754
- const startPosition = startIdx * numberOfChannels * bytesPerSample
755
- const endPosition = endIdx * numberOfChannels * bytesPerSample
756
-
757
- var spectralFeatures = computeSpectralFeatures(channelData.slice(startIdx, endIdx), sampleRate, features);
758
-
759
- // Simply use the counter, increment after assigning
760
- const dataPoint = {
761
- id: uniqueIdCounter++,
762
- amplitude: maxAmp,
763
- rms,
764
- startTime,
765
- endTime,
766
- dB: 20 * Math.log10(rms + 1e-6),
767
- silent: rms < 0.01,
768
- startPosition,
769
- endPosition,
770
- samples: remainingSamples,
771
- }
772
-
773
- logger.debug('extractWaveform - dataPoint', dataPoint);
774
- // Extract features if any are requested
775
- const extractedFeatures = createFeaturesObject(
776
- features,
777
- maxAmp,
778
- rms,
779
- sumSquares,
780
- zeroCrossings,
781
- remainingSamples,
782
- spectralFeatures,
783
- channelData,
784
- startIdx,
785
- endIdx,
786
- sampleRate,
787
- numberOfChannels,
788
- bytesPerSample
789
- );
790
-
791
- if (extractedFeatures) {
792
- dataPoint.features = extractedFeatures;
793
- }
794
-
795
- dataPoints.push(dataPoint)
796
- }
797
-
798
- return {
799
- durationMs,
800
- dataPoints,
801
- amplitudeRange: { min, max },
802
- rmsRange: {
803
- min: 0,
804
- max: Math.max(Math.abs(min), Math.abs(max))
805
- }
806
- }
807
- }
808
-
809
- try {
810
- // Measure actual processing time using performance.now() for higher precision
811
- const processingStartTime = performance.now()
812
-
813
- const result = extractWaveform(
814
- channelData,
815
- sampleRate,
816
- segmentDurationMs,
817
- numberOfChannels || 1, // Default to 1 channel if not provided
818
- bytesPerSample
819
- )
820
-
821
- const processingEndTime = performance.now()
822
- const actualExtractionTimeMs = processingEndTime - processingStartTime
823
-
824
- // Send complete result immediately
825
- self.postMessage({
826
- command: 'features',
827
- result: {
828
- bitDepth,
829
- samples: channelData.length,
830
- numberOfChannels,
831
- sampleRate,
832
- segmentDurationMs,
833
- durationMs: result.durationMs,
834
- dataPoints: result.dataPoints,
835
- amplitudeRange: result.amplitudeRange,
836
- rmsRange: result.rmsRange,
837
- extractionTimeMs: actualExtractionTimeMs,
838
- }
839
- })
840
- } catch (error) {
841
- console.error('[Worker] Error', {
842
- message: error.message,
843
- stack: error.stack
844
- });
845
-
846
- self.postMessage({
847
- error: {
848
- message: error.message,
849
- stack: error.stack,
850
- name: error.name
851
- }
852
- });
853
- }
854
- }
855
- `;
856
- //# sourceMappingURL=InlineFeaturesExtractor.web.js.map