echogarden 0.12.2 → 1.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.
Files changed (334) hide show
  1. package/README.md +15 -14
  2. package/data/schemas/options.json +398 -111
  3. package/dist/alignment/DTWMfccSequenceAlignment.d.ts +1 -1
  4. package/dist/alignment/DTWMfccSequenceAlignment.js +8 -8
  5. package/dist/alignment/DTWSequenceAlignment.d.ts +1 -1
  6. package/dist/alignment/DTWSequenceAlignment.js +1 -1
  7. package/dist/alignment/DTWSequenceAlignmentWindowed.d.ts +1 -1
  8. package/dist/alignment/DTWSequenceAlignmentWindowed.js +2 -2
  9. package/dist/alignment/LevenshteinSequenceAlignment.d.ts +1 -1
  10. package/dist/alignment/LevenshteinSequenceAlignment.js +1 -1
  11. package/dist/alignment/SpeechAlignment.d.ts +9 -10
  12. package/dist/alignment/SpeechAlignment.js +136 -105
  13. package/dist/alignment/SpeechAlignment.js.map +1 -1
  14. package/dist/api/API.d.ts +13 -12
  15. package/dist/api/API.js +14 -13
  16. package/dist/api/API.js.map +1 -1
  17. package/dist/api/APIOptions.d.ts +5 -4
  18. package/dist/api/Alignment.d.ts +15 -9
  19. package/dist/api/Alignment.js +88 -74
  20. package/dist/api/Alignment.js.map +1 -1
  21. package/dist/api/Common.js +1 -1
  22. package/dist/api/Denoising.d.ts +6 -6
  23. package/dist/api/Denoising.js +23 -23
  24. package/dist/api/Denoising.js.map +1 -1
  25. package/dist/api/LanguageDetection.d.ts +19 -12
  26. package/dist/api/LanguageDetection.js +88 -38
  27. package/dist/api/LanguageDetection.js.map +1 -1
  28. package/dist/api/Recognition.d.ts +16 -6
  29. package/dist/api/Recognition.js +129 -55
  30. package/dist/api/Recognition.js.map +1 -1
  31. package/dist/api/SourceSeparation.d.ts +17 -0
  32. package/dist/api/SourceSeparation.js +61 -0
  33. package/dist/api/SourceSeparation.js.map +1 -0
  34. package/dist/api/Synthesis.d.ts +18 -18
  35. package/dist/api/Synthesis.js +191 -164
  36. package/dist/api/Synthesis.js.map +1 -1
  37. package/dist/api/Translation.d.ts +19 -8
  38. package/dist/api/Translation.js +132 -35
  39. package/dist/api/Translation.js.map +1 -1
  40. package/dist/api/Vad.d.ts +10 -5
  41. package/dist/api/Vad.js +76 -38
  42. package/dist/api/Vad.js.map +1 -1
  43. package/dist/audio/AudioBufferConversion.d.ts +1 -1
  44. package/dist/audio/AudioBufferConversion.js +4 -4
  45. package/dist/audio/AudioPlayer.d.ts +1 -1
  46. package/dist/audio/AudioPlayer.js +26 -26
  47. package/dist/audio/AudioPlayer.js.map +1 -1
  48. package/dist/audio/AudioRecorder.d.ts +1 -1
  49. package/dist/audio/AudioRecorder.js +5 -5
  50. package/dist/audio/AudioUtilities.d.ts +13 -9
  51. package/dist/audio/AudioUtilities.js +86 -24
  52. package/dist/audio/AudioUtilities.js.map +1 -1
  53. package/dist/cli/CLI.d.ts +3 -3
  54. package/dist/cli/CLI.js +271 -162
  55. package/dist/cli/CLI.js.map +1 -1
  56. package/dist/cli/CLIConfigFile.js +8 -8
  57. package/dist/cli/CLILauncher.js +6 -6
  58. package/dist/cli/CLIOptionsSchema.js +2 -2
  59. package/dist/cli/CLIParser.js +5 -5
  60. package/dist/cli/CLIStarter.js +4 -4
  61. package/dist/codecs/FFMpegTranscoder.d.ts +2 -2
  62. package/dist/codecs/FFMpegTranscoder.js +37 -37
  63. package/dist/codecs/FFMpegTranscoder.js.map +1 -1
  64. package/dist/codecs/TIMITCodec.js +5 -5
  65. package/dist/codecs/WaveCodec.d.ts +1 -1
  66. package/dist/codecs/WaveCodec.js +22 -22
  67. package/dist/denoising/RNNoise.d.ts +1 -1
  68. package/dist/denoising/RNNoise.js +9 -9
  69. package/dist/dsp/BiquadFilter.d.ts +3 -2
  70. package/dist/dsp/BiquadFilter.js +18 -11
  71. package/dist/dsp/BiquadFilter.js.map +1 -1
  72. package/dist/dsp/DecayingPeakEstimator.d.ts +16 -0
  73. package/dist/dsp/DecayingPeakEstimator.js +23 -0
  74. package/dist/dsp/DecayingPeakEstimator.js.map +1 -0
  75. package/dist/dsp/FFT.d.ts +8 -4
  76. package/dist/dsp/FFT.js +76 -30
  77. package/dist/dsp/FFT.js.map +1 -1
  78. package/dist/dsp/KWeightingFilter.d.ts +9 -0
  79. package/dist/dsp/KWeightingFilter.js +40 -0
  80. package/dist/dsp/KWeightingFilter.js.map +1 -0
  81. package/dist/dsp/LoudnessEstimator.d.ts +21 -0
  82. package/dist/dsp/LoudnessEstimator.js +47 -0
  83. package/dist/dsp/LoudnessEstimator.js.map +1 -0
  84. package/dist/dsp/MFCC.d.ts +2 -2
  85. package/dist/dsp/MFCC.js +15 -15
  86. package/dist/dsp/MelSpectogram.d.ts +1 -1
  87. package/dist/dsp/MelSpectogram.js +6 -6
  88. package/dist/dsp/Rubberband.d.ts +11 -11
  89. package/dist/dsp/Rubberband.js +27 -27
  90. package/dist/dsp/Sonic.d.ts +1 -1
  91. package/dist/dsp/Sonic.js +3 -3
  92. package/dist/dsp/SpeexResampler.d.ts +1 -1
  93. package/dist/dsp/SpeexResampler.js +2 -2
  94. package/dist/math/VectorMath.d.ts +12 -8
  95. package/dist/math/VectorMath.js +35 -32
  96. package/dist/math/VectorMath.js.map +1 -1
  97. package/dist/nlp/ChineseSegmentation.js +2 -2
  98. package/dist/nlp/CompromiseNLP.js +3 -3
  99. package/dist/nlp/EspeakPhonemizer.js +30 -30
  100. package/dist/nlp/IPA.js +20 -20
  101. package/dist/nlp/JapaneseSegmentation.js +6 -6
  102. package/dist/nlp/Lexicon.d.ts +1 -1
  103. package/dist/nlp/Lexicon.js +7 -7
  104. package/dist/nlp/Segmentation.d.ts +3 -0
  105. package/dist/nlp/Segmentation.js +21 -14
  106. package/dist/nlp/Segmentation.js.map +1 -1
  107. package/dist/nlp/TextNormalizer.js +16 -16
  108. package/dist/recognition/AmazonTranscribeSTT.d.ts +2 -2
  109. package/dist/recognition/AmazonTranscribeSTT.js +13 -14
  110. package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
  111. package/dist/recognition/AzureCognitiveServicesSTT.js +5 -6
  112. package/dist/recognition/AzureCognitiveServicesSTT.js.map +1 -1
  113. package/dist/recognition/GoogleCloudSTT.d.ts +3 -3
  114. package/dist/recognition/GoogleCloudSTT.js +18 -18
  115. package/dist/recognition/OpenAICloudSTT.d.ts +19 -0
  116. package/dist/recognition/OpenAICloudSTT.js +81 -0
  117. package/dist/recognition/OpenAICloudSTT.js.map +1 -0
  118. package/dist/recognition/SileroSTT.d.ts +2 -2
  119. package/dist/recognition/SileroSTT.js +25 -25
  120. package/dist/recognition/VoskSTT.d.ts +2 -2
  121. package/dist/recognition/VoskSTT.js +8 -8
  122. package/dist/recognition/WhisperCppSTT.d.ts +88 -0
  123. package/dist/recognition/WhisperCppSTT.js +332 -0
  124. package/dist/recognition/WhisperCppSTT.js.map +1 -0
  125. package/dist/recognition/WhisperSTT.d.ts +49 -25
  126. package/dist/recognition/WhisperSTT.js +626 -481
  127. package/dist/recognition/WhisperSTT.js.map +1 -1
  128. package/dist/server/Client.d.ts +1 -1
  129. package/dist/server/Client.js +22 -22
  130. package/dist/server/Server.js +9 -9
  131. package/dist/server/Server.js.map +1 -1
  132. package/dist/server/Worker.d.ts +22 -22
  133. package/dist/server/Worker.js +36 -36
  134. package/dist/server/Worker.js.map +1 -1
  135. package/dist/server/WorkerStarter.js +2 -2
  136. package/dist/source-separation/MDXNetSourceSeparation.d.ts +11 -0
  137. package/dist/source-separation/MDXNetSourceSeparation.js +161 -0
  138. package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -0
  139. package/dist/speech-language-detection/SileroLanguageDetection.d.ts +1 -1
  140. package/dist/speech-language-detection/SileroLanguageDetection.js +7 -7
  141. package/dist/subtitles/Subtitles.d.ts +10 -0
  142. package/dist/subtitles/Subtitles.js +2 -2
  143. package/dist/subtitles/Subtitles.js.map +1 -1
  144. package/dist/synthesis/AwsPollyTTS.d.ts +1 -1
  145. package/dist/synthesis/AwsPollyTTS.js +12 -12
  146. package/dist/synthesis/AzureCognitiveServicesTTS.js +7 -7
  147. package/dist/synthesis/CoquiServerTTS.js +10 -10
  148. package/dist/synthesis/CoquiServerTTS.js.map +1 -1
  149. package/dist/synthesis/ElevenlabsTTS.d.ts +23 -0
  150. package/dist/synthesis/ElevenlabsTTS.js +103 -0
  151. package/dist/synthesis/ElevenlabsTTS.js.map +1 -0
  152. package/dist/synthesis/EspeakTTS.d.ts +6 -5
  153. package/dist/synthesis/EspeakTTS.js +81 -69
  154. package/dist/synthesis/EspeakTTS.js.map +1 -1
  155. package/dist/synthesis/FliteTTS.d.ts +3 -3
  156. package/dist/synthesis/FliteTTS.js +154 -154
  157. package/dist/synthesis/FliteTTS.js.map +1 -1
  158. package/dist/synthesis/GoogleCloudTTS.d.ts +3 -3
  159. package/dist/synthesis/GoogleCloudTTS.js +17 -17
  160. package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
  161. package/dist/synthesis/GoogleTranslateTTS.d.ts +1 -1
  162. package/dist/synthesis/GoogleTranslateTTS.js +103 -103
  163. package/dist/synthesis/MicrosoftEdgeTTS.d.ts +2 -2
  164. package/dist/synthesis/MicrosoftEdgeTTS.js +74 -74
  165. package/dist/synthesis/OpenAICloudTTS.d.ts +13 -0
  166. package/dist/synthesis/OpenAICloudTTS.js +169 -0
  167. package/dist/synthesis/OpenAICloudTTS.js.map +1 -0
  168. package/dist/synthesis/SamTTS.js +3 -3
  169. package/dist/synthesis/SapiTTS.d.ts +3 -3
  170. package/dist/synthesis/SapiTTS.js +26 -26
  171. package/dist/synthesis/StreamlabsPollyTTS.d.ts +2 -2
  172. package/dist/synthesis/StreamlabsPollyTTS.js +27 -27
  173. package/dist/synthesis/SvoxPicoTTS.d.ts +2 -2
  174. package/dist/synthesis/SvoxPicoTTS.js +65 -65
  175. package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
  176. package/dist/synthesis/VitsTTS.d.ts +3 -3
  177. package/dist/synthesis/VitsTTS.js +378 -378
  178. package/dist/synthesis/VitsTTS.js.map +1 -1
  179. package/dist/tests/Test.js +2 -2
  180. package/dist/utilities/Compression.d.ts +5 -0
  181. package/dist/utilities/Compression.js +29 -13
  182. package/dist/utilities/Compression.js.map +1 -1
  183. package/dist/utilities/FileDownloader.d.ts +1 -1
  184. package/dist/utilities/FileDownloader.js +16 -16
  185. package/dist/utilities/FileSystem.js +7 -7
  186. package/dist/utilities/Locale.d.ts +7 -7
  187. package/dist/utilities/Locale.js +15 -15
  188. package/dist/utilities/Logger.js +3 -3
  189. package/dist/utilities/ObjectUtilities.js +19 -19
  190. package/dist/utilities/OpenPromise.js +2 -2
  191. package/dist/utilities/OpenPromise.js.map +1 -1
  192. package/dist/utilities/PackageManager.js +31 -0
  193. package/dist/utilities/PackageManager.js.map +1 -1
  194. package/dist/utilities/PathUtilities.js +8 -8
  195. package/dist/utilities/RandomGenerator.js +2 -2
  196. package/dist/utilities/SmoothEstimator.d.ts +8 -0
  197. package/dist/utilities/SmoothEstimator.js +25 -0
  198. package/dist/utilities/SmoothEstimator.js.map +1 -0
  199. package/dist/utilities/TarballMaker.js +8 -8
  200. package/dist/utilities/Timeline.d.ts +3 -2
  201. package/dist/utilities/Timeline.js +11 -11
  202. package/dist/utilities/Timeline.js.map +1 -1
  203. package/dist/utilities/Timer.js +4 -4
  204. package/dist/utilities/Utilities.d.ts +4 -0
  205. package/dist/utilities/Utilities.js +38 -15
  206. package/dist/utilities/Utilities.js.map +1 -1
  207. package/dist/utilities/WasmMemoryManager.js +7 -7
  208. package/dist/utilities/WebReader.js +23 -23
  209. package/dist/utilities/WikipediaReader.js +2 -2
  210. package/dist/voice-activity-detection/AdaptiveGateVAD.d.ts +28 -0
  211. package/dist/voice-activity-detection/AdaptiveGateVAD.js +138 -0
  212. package/dist/voice-activity-detection/AdaptiveGateVAD.js.map +1 -0
  213. package/dist/voice-activity-detection/SileroVAD.d.ts +1 -1
  214. package/dist/voice-activity-detection/SileroVAD.js +5 -5
  215. package/dist/voice-activity-detection/SileroVAD.js.map +1 -1
  216. package/dist/voice-activity-detection/WebRtcVAD.d.ts +1 -1
  217. package/dist/voice-activity-detection/WebRtcVAD.js +4 -4
  218. package/docs/API.md +29 -11
  219. package/docs/CLI.md +31 -7
  220. package/docs/Contributing.md +38 -0
  221. package/docs/Development.md +93 -19
  222. package/docs/Engines.md +28 -16
  223. package/docs/Licenses.md +4 -1
  224. package/docs/Options.md +158 -78
  225. package/docs/Releases.md +262 -0
  226. package/docs/Server.md +7 -7
  227. package/docs/Tasklist.md +95 -76
  228. package/docs/Technical.md +4 -4
  229. package/package.json +13 -14
  230. package/src/alignment/DTWMfccSequenceAlignment.ts +9 -9
  231. package/src/alignment/DTWSequenceAlignment.ts +2 -2
  232. package/src/alignment/DTWSequenceAlignmentWindowed.ts +3 -3
  233. package/src/alignment/LevenshteinSequenceAlignment.ts +2 -2
  234. package/src/alignment/SpeechAlignment.ts +204 -119
  235. package/src/api/API.ts +14 -13
  236. package/src/api/APIOptions.ts +12 -11
  237. package/src/api/Alignment.ts +147 -90
  238. package/src/api/Common.ts +1 -1
  239. package/src/api/Denoising.ts +28 -28
  240. package/src/api/LanguageDetection.ts +135 -48
  241. package/src/api/Recognition.ts +198 -59
  242. package/src/api/SourceSeparation.ts +99 -0
  243. package/src/api/Synthesis.ts +217 -181
  244. package/src/api/Translation.ts +193 -40
  245. package/src/api/Vad.ts +110 -41
  246. package/src/audio/AudioBufferConversion.ts +4 -4
  247. package/src/audio/AudioPlayer.ts +27 -27
  248. package/src/audio/AudioRecorder.ts +5 -5
  249. package/src/audio/AudioUtilities.ts +107 -24
  250. package/src/cli/CLI.ts +313 -164
  251. package/src/cli/CLIConfigFile.ts +8 -8
  252. package/src/cli/CLILauncher.ts +6 -6
  253. package/src/cli/CLIOptionsSchema.ts +2 -2
  254. package/src/cli/CLIParser.ts +5 -5
  255. package/src/cli/CLIStarter.ts +4 -4
  256. package/src/codecs/FFMpegTranscoder.ts +38 -38
  257. package/src/codecs/TIMITCodec.ts +5 -5
  258. package/src/codecs/WaveCodec.ts +22 -22
  259. package/src/denoising/RNNoise.ts +9 -9
  260. package/src/dsp/BiquadFilter.ts +19 -11
  261. package/src/dsp/DecayingPeakEstimator.ts +35 -0
  262. package/src/dsp/FFT.ts +103 -35
  263. package/src/dsp/KWeightingFilter.ts +43 -0
  264. package/src/dsp/LoudnessEstimator.ts +74 -0
  265. package/src/dsp/MFCC.ts +15 -15
  266. package/src/dsp/MelSpectogram.ts +7 -7
  267. package/src/dsp/Rubberband.ts +38 -38
  268. package/src/dsp/Sonic.ts +4 -4
  269. package/src/dsp/SpeexResampler.ts +2 -2
  270. package/src/math/VectorMath.ts +42 -33
  271. package/src/nlp/ChineseSegmentation.ts +3 -3
  272. package/src/nlp/CompromiseNLP.ts +3 -3
  273. package/src/nlp/EspeakPhonemizer.ts +30 -30
  274. package/src/nlp/IPA.ts +20 -20
  275. package/src/nlp/JapaneseSegmentation.ts +6 -6
  276. package/src/nlp/Lexicon.ts +8 -8
  277. package/src/nlp/Segmentation.ts +23 -14
  278. package/src/nlp/TextNormalizer.ts +16 -16
  279. package/src/recognition/AmazonTranscribeSTT.ts +16 -17
  280. package/src/recognition/AzureCognitiveServicesSTT.ts +8 -6
  281. package/src/recognition/GoogleCloudSTT.ts +21 -21
  282. package/src/recognition/OpenAICloudSTT.ts +142 -0
  283. package/src/recognition/SileroSTT.ts +26 -26
  284. package/src/recognition/VoskSTT.ts +10 -10
  285. package/src/recognition/WhisperCppSTT.ts +555 -0
  286. package/src/recognition/WhisperSTT.ts +760 -507
  287. package/src/server/Client.ts +23 -23
  288. package/src/server/Server.ts +9 -9
  289. package/src/server/Worker.ts +53 -53
  290. package/src/server/WorkerStarter.ts +2 -2
  291. package/src/source-separation/MDXNetSourceSeparation.ts +228 -0
  292. package/src/speech-language-detection/SileroLanguageDetection.ts +8 -8
  293. package/src/subtitles/Subtitles.ts +3 -3
  294. package/src/synthesis/AwsPollyTTS.ts +14 -14
  295. package/src/synthesis/AzureCognitiveServicesTTS.ts +10 -10
  296. package/src/synthesis/CoquiServerTTS.ts +10 -10
  297. package/src/synthesis/ElevenlabsTTS.ts +137 -0
  298. package/src/synthesis/EspeakTTS.ts +90 -71
  299. package/src/synthesis/FliteTTS.ts +157 -157
  300. package/src/synthesis/GoogleCloudTTS.ts +19 -19
  301. package/src/synthesis/GoogleTranslateTTS.ts +104 -104
  302. package/src/synthesis/MicrosoftEdgeTTS.ts +80 -80
  303. package/src/synthesis/OpenAICloudTTS.ts +196 -0
  304. package/src/synthesis/SamTTS.ts +3 -3
  305. package/src/synthesis/SapiTTS.ts +29 -29
  306. package/src/synthesis/StreamlabsPollyTTS.ts +29 -29
  307. package/src/synthesis/SvoxPicoTTS.ts +67 -67
  308. package/src/synthesis/VitsTTS.ts +380 -380
  309. package/src/tests/Test.ts +4 -4
  310. package/src/utilities/Compression.ts +34 -13
  311. package/src/utilities/FileDownloader.ts +19 -19
  312. package/src/utilities/FileSystem.ts +7 -7
  313. package/src/utilities/Locale.ts +22 -22
  314. package/src/utilities/Logger.ts +4 -4
  315. package/src/utilities/ObjectUtilities.ts +19 -19
  316. package/src/utilities/OpenPromise.ts +2 -2
  317. package/src/utilities/PackageManager.ts +40 -0
  318. package/src/utilities/PathUtilities.ts +8 -8
  319. package/src/utilities/RandomGenerator.ts +3 -3
  320. package/src/utilities/SmoothEstimator.ts +35 -0
  321. package/src/utilities/TarballMaker.ts +9 -9
  322. package/src/utilities/Timeline.ts +15 -13
  323. package/src/utilities/Timer.ts +4 -4
  324. package/src/utilities/Utilities.ts +49 -15
  325. package/src/utilities/WasmMemoryManager.ts +7 -7
  326. package/src/utilities/WebReader.ts +23 -23
  327. package/src/utilities/WikipediaReader.ts +2 -2
  328. package/src/voice-activity-detection/AdaptiveGateVAD.ts +202 -0
  329. package/src/voice-activity-detection/SileroVAD.ts +5 -5
  330. package/src/voice-activity-detection/WebRtcVAD.ts +5 -5
  331. package/dist/synthesis/ElevenLabsTTS.d.ts +0 -8
  332. package/dist/synthesis/ElevenLabsTTS.js +0 -82
  333. package/dist/synthesis/ElevenLabsTTS.js.map +0 -1
  334. package/src/synthesis/ElevenLabsTTS.ts +0 -104
@@ -1,7 +1,7 @@
1
- import { ParagraphBreakType, WhitespaceProcessing } from "../api/Common.js"
2
- import { isWordOrSymbolWord, splitToParagraphs, splitToSentences } from "../nlp/Segmentation.js"
3
- import { deepClone } from "./ObjectUtilities.js"
4
- import { getUTF32Chars, roundToDigits } from "./Utilities.js"
1
+ import { ParagraphBreakType, WhitespaceProcessing } from '../api/Common.js'
2
+ import { isWordOrSymbolWord, splitToParagraphs, splitToSentences } from '../nlp/Segmentation.js'
3
+ import { deepClone } from './ObjectUtilities.js'
4
+ import { getUTF32Chars, roundToDigits } from './Utilities.js'
5
5
 
6
6
  export function addTimeOffsetToTimeline(targetTimeline: Timeline, timeOffset: number) {
7
7
  if (!targetTimeline) {
@@ -62,14 +62,14 @@ export function roundTimelineProperties(targetTimeline: Timeline, decimalDigits
62
62
  }
63
63
 
64
64
  export async function wordTimelineToSegmentSentenceTimeline(wordTimeline: Timeline, transcript: string, language: string, paragraphBreaks: ParagraphBreakType = 'double', whitespace: WhitespaceProcessing = 'collapse') {
65
- const paragraphs = await splitToParagraphs(transcript, paragraphBreaks, whitespace)
65
+ const paragraphs = splitToParagraphs(transcript, paragraphBreaks, whitespace)
66
66
 
67
67
  const segments = paragraphs
68
68
  .map(segment =>
69
69
  splitToSentences(segment, language).map(sentence =>
70
70
  sentence.trim()))
71
71
 
72
- let text = ""
72
+ let text = ''
73
73
  const charIndexToSentenceEntryMapping: TimelineEntry[] = []
74
74
 
75
75
  const segmentTimeline: Timeline = []
@@ -78,8 +78,8 @@ export async function wordTimelineToSegmentSentenceTimeline(wordTimeline: Timeli
78
78
  const sentencesInSegment: Timeline = []
79
79
 
80
80
  const segmentEntry: TimelineEntry = {
81
- type: "segment",
82
- text: "",
81
+ type: 'segment',
82
+ text: '',
83
83
  startTime: -1,
84
84
  endTime: -1,
85
85
  timeline: sentencesInSegment
@@ -87,14 +87,14 @@ export async function wordTimelineToSegmentSentenceTimeline(wordTimeline: Timeli
87
87
 
88
88
  for (const sentence of segment) {
89
89
  const sentenceEntry: TimelineEntry = {
90
- type: "sentence",
90
+ type: 'sentence',
91
91
  text: sentence,
92
92
  startTime: -1,
93
93
  endTime: -1,
94
94
  timeline: []
95
95
  }
96
96
 
97
- for (const char of sentence + " ") {
97
+ for (const char of sentence + ' ') {
98
98
  text += char
99
99
  charIndexToSentenceEntryMapping.push(sentenceEntry)
100
100
  }
@@ -122,7 +122,7 @@ export async function wordTimelineToSegmentSentenceTimeline(wordTimeline: Timeli
122
122
  }
123
123
 
124
124
  const targetSentenceEntry = charIndexToSentenceEntryMapping[indexOfWordInText]
125
- targetSentenceEntry.timeline!.push(wordEntry)
125
+ targetSentenceEntry.timeline!.push(deepClone(wordEntry))
126
126
 
127
127
  wordSearchStartOffset = indexOfWordInText + wordText.length
128
128
  }
@@ -151,7 +151,7 @@ export async function wordTimelineToSegmentSentenceTimeline(wordTimeline: Timeli
151
151
  continue
152
152
  }
153
153
 
154
- segmentEntry.text = newSentenceTimeline.map(sentenceEntry => sentenceEntry.text).join(" ")
154
+ segmentEntry.text = newSentenceTimeline.map(sentenceEntry => sentenceEntry.text).join(' ')
155
155
 
156
156
  segmentEntry.startTime = newSentenceTimeline[0].startTime
157
157
  segmentEntry.endTime = newSentenceTimeline[newSentenceTimeline.length - 1].endTime
@@ -207,7 +207,7 @@ export function addWordTextOffsetsToTimeline(timeline: Timeline, text: string, c
207
207
  return currentOffset
208
208
  }
209
209
 
210
- export type TimelineEntryType = "segment" | "paragraph" | "sentence" | "clause" | "phrase" | "word" | "token" | "letter" | "phone" | "subphone"
210
+ export type TimelineEntryType = 'segment' | 'paragraph' | 'sentence' | 'clause' | 'phrase' | 'word' | 'token' | 'letter' | 'phone' | 'subphone'
211
211
 
212
212
  export type TimelineEntry = {
213
213
  type: TimelineEntryType
@@ -225,6 +225,8 @@ export type TimelineEntry = {
225
225
 
226
226
  confidence?: number
227
227
 
228
+ id?: number
229
+
228
230
  timeline?: Timeline
229
231
  }
230
232
 
@@ -1,4 +1,4 @@
1
- import { roundToDigits, writeToStderr } from "./Utilities.js"
1
+ import { roundToDigits, writeToStderr } from './Utilities.js'
2
2
 
3
3
  declare const chrome: any
4
4
  declare const process: any
@@ -56,7 +56,7 @@ export class Timer {
56
56
  }
57
57
 
58
58
  private static createGlobalTimestampFunction() {
59
- if (typeof process === "object" && typeof process.hrtime === "function") {
59
+ if (typeof process === 'object' && typeof process.hrtime === 'function') {
60
60
  let baseTimestamp = 0
61
61
 
62
62
  this.timestampFunc = () => {
@@ -68,7 +68,7 @@ export class Timer {
68
68
 
69
69
  baseTimestamp = Date.now() - this.timestampFunc()
70
70
  }
71
- else if (typeof chrome === "object" && chrome.Interval) {
71
+ else if (typeof chrome === 'object' && chrome.Interval) {
72
72
  const baseTimestamp = Date.now()
73
73
 
74
74
  const chromeIntervalObject = new chrome.Interval()
@@ -76,7 +76,7 @@ export class Timer {
76
76
 
77
77
  this.timestampFunc = () => baseTimestamp + chromeIntervalObject.microseconds() / 1000
78
78
  }
79
- else if (typeof performance === "object" && performance.now) {
79
+ else if (typeof performance === 'object' && performance.now) {
80
80
  const baseTimestamp = Date.now() - performance.now()
81
81
 
82
82
  this.timestampFunc = () => baseTimestamp + performance.now()
@@ -5,6 +5,7 @@ import { inspect } from 'node:util'
5
5
  import { RandomGenerator } from './RandomGenerator.js'
6
6
  import { randomUUID, randomBytes } from 'node:crypto'
7
7
  import { Logger } from './Logger.js'
8
+ import { ChildProcessWithoutNullStreams } from 'node:child_process'
8
9
 
9
10
  const log = logToStderr
10
11
 
@@ -84,7 +85,7 @@ export function printToStderr(message: any) {
84
85
 
85
86
  export function logToStderr(message: any) {
86
87
  printToStderr(message)
87
- writeToStderr("\n")
88
+ writeToStderr('\n')
88
89
  }
89
90
 
90
91
  export function objToString(obj: any) {
@@ -105,7 +106,7 @@ export function getRandomHexString(charCount = 32, upperCase = false) {
105
106
  throw new Error(`'charCount' must be an even number`)
106
107
  }
107
108
 
108
- let hex = randomBytes(charCount / 2).toString("hex")
109
+ let hex = randomBytes(charCount / 2).toString('hex')
109
110
 
110
111
  if (upperCase) {
111
112
  hex = hex.toUpperCase()
@@ -118,7 +119,7 @@ export function getRandomUUID(dashes = true) {
118
119
  let uuid = randomUUID() as string
119
120
 
120
121
  if (dashes == false) {
121
- uuid = uuid.replaceAll("-", "")
122
+ uuid = uuid.replaceAll('-', '')
122
123
  }
123
124
 
124
125
  return uuid
@@ -181,7 +182,7 @@ export function printMatrix(matrix: Float32Array[]) {
181
182
  const rowCount = matrix.length
182
183
 
183
184
  for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
184
- log(matrix[rowIndex].join(", "))
185
+ log(matrix[rowIndex].join(', '))
185
186
  }
186
187
  }
187
188
 
@@ -212,11 +213,11 @@ export function secondsToMS(totalSeconds: number) {
212
213
  return { minutes: (hours * 60) + minutes, seconds, milliseconds }
213
214
  }
214
215
 
215
- export function formatHMS(timeHMS: { hours: number, minutes: number, seconds: number, milliseconds: number }, decimalSeparator = ".") {
216
+ export function formatHMS(timeHMS: { hours: number, minutes: number, seconds: number, milliseconds: number }, decimalSeparator = '.') {
216
217
  return `${formatIntegerWithLeadingZeros(timeHMS.hours, 2)}:${formatIntegerWithLeadingZeros(timeHMS.minutes, 2)}:${formatIntegerWithLeadingZeros(timeHMS.seconds, 2)}${decimalSeparator}${formatIntegerWithLeadingZeros(timeHMS.milliseconds, 3)}`
217
218
  }
218
219
 
219
- export function formatMS(timeMS: { minutes: number, seconds: number, milliseconds: number }, decimalSeparator = ".") {
220
+ export function formatMS(timeMS: { minutes: number, seconds: number, milliseconds: number }, decimalSeparator = '.') {
220
221
  return `${formatIntegerWithLeadingZeros(timeMS.minutes, 2)}:${formatIntegerWithLeadingZeros(timeMS.seconds, 2)}${decimalSeparator}${formatIntegerWithLeadingZeros(timeMS.milliseconds, 3)}`
221
222
  }
222
223
 
@@ -356,15 +357,15 @@ export function readBinaryIncomingMessage(incomingMessage: IncomingMessage) {
356
357
  return new Promise<Buffer>((resolve, reject) => {
357
358
  const chunks: Buffer[] = []
358
359
 
359
- incomingMessage.on("data", (chunk) => {
360
+ incomingMessage.on('data', (chunk) => {
360
361
  chunks.push(Buffer.from(chunk))
361
362
  })
362
363
 
363
- incomingMessage.on("end", () => {
364
+ incomingMessage.on('end', () => {
364
365
  resolve(Buffer.concat(chunks))
365
366
  })
366
367
 
367
- incomingMessage.on("error", (e) => {
368
+ incomingMessage.on('error', (e) => {
368
369
  reject(e)
369
370
  })
370
371
  })
@@ -388,7 +389,7 @@ export async function sha256AsHex(input: string) {
388
389
  }
389
390
 
390
391
  export async function commandExists(command: string) {
391
- const { default: commandExists } = await import("command-exists")
392
+ const { default: commandExists } = await import('command-exists')
392
393
 
393
394
  try {
394
395
  await commandExists(command)
@@ -415,11 +416,11 @@ export async function convertHtmlToText(html: string) {
415
416
  ]
416
417
  })
417
418
 
418
- return text || ""
419
+ return text || ''
419
420
  }
420
421
 
421
422
  export function formatListWithQuotedElements(strings: string[], quoteSymbol = `'`) {
422
- return strings.map(str => `${quoteSymbol}${str}${quoteSymbol}`).join(", ")
423
+ return strings.map(str => `${quoteSymbol}${str}${quoteSymbol}`).join(', ')
423
424
  }
424
425
 
425
426
  export async function resolveModuleMainPath(moduleName: string) {
@@ -441,7 +442,7 @@ export function splitFilenameOnExtendedExtension(filenameWithExtension: string)
441
442
  let splitPoint = filenameWithExtension.length
442
443
 
443
444
  for (let i = filenameWithExtension.length - 1; i >= 0; i--) {
444
- if (filenameWithExtension[i] == ".") {
445
+ if (filenameWithExtension[i] == '.') {
445
446
  if (/^[a-zA-Z0-9\.]+$/.test(filenameWithExtension.slice(i + 1))) {
446
447
  splitPoint = i
447
448
 
@@ -577,7 +578,7 @@ export async function resolveModuleScriptPath(moduleName: string) {
577
578
  export async function runOperationWithRetries<R>(
578
579
  operationFunc: () => Promise<R>,
579
580
  logger: Logger,
580
- opreationName = "Operation",
581
+ opreationName = 'Operation',
581
582
  delayBetweenRetries = 2000,
582
583
  maxRetries = 200) {
583
584
 
@@ -592,7 +593,7 @@ export async function runOperationWithRetries<R>(
592
593
  const { shouldCancelCurrentTask } = await import('../server/Worker.js')
593
594
 
594
595
  if (shouldCancelCurrentTask()) {
595
- throw new Error("Canceled")
596
+ throw new Error('Canceled')
596
597
  }
597
598
 
598
599
  logger.setAsActiveLogger()
@@ -613,3 +614,36 @@ export async function runOperationWithRetries<R>(
613
614
 
614
615
  throw new Error(`${opreationName} failed after ${maxRetries} retry attempts`)
615
616
  }
617
+
618
+ export function writeToStdinInChunks(process: ChildProcessWithoutNullStreams, buffer: Buffer, chunkSize: number) {
619
+ const writeChunk = (chunkOffset: number) => {
620
+ if (chunkOffset >= buffer.length) {
621
+ process.stdin.end() // End the stream after writing all chunks
622
+
623
+ return
624
+ }
625
+
626
+ const startOffset = chunkOffset
627
+ const endOffset = Math.min(chunkOffset + chunkSize, buffer.length)
628
+
629
+ const chunk = buffer.subarray(startOffset, endOffset)
630
+
631
+ if (!process.stdin.writable) {
632
+ return
633
+ }
634
+
635
+ process.stdin.write(chunk, () => writeChunk(endOffset))
636
+ }
637
+
638
+ writeChunk(0)
639
+ }
640
+
641
+ export function getIntegerRange(start: number, end: number): number[] {
642
+ const result = []
643
+
644
+ for (let i = start; i < end; i++) {
645
+ result.push(i)
646
+ }
647
+
648
+ return result
649
+ }
@@ -196,7 +196,7 @@ export class WasmMemoryManager {
196
196
  }
197
197
 
198
198
  allocNullTerminatedUtf8String(str: string) {
199
- const strBuffer = Buffer.concat([Buffer.from(str, "utf8"), Buffer.alloc(1)])
199
+ const strBuffer = Buffer.concat([Buffer.from(str, 'utf8'), Buffer.alloc(1)])
200
200
  const ref = this.allocUint8Array(strBuffer.length)
201
201
  ref.view.set(strBuffer)
202
202
  return ref
@@ -266,7 +266,7 @@ abstract class ValueRef<T extends number | string> {
266
266
  if (typeof this.value == 'number') {
267
267
  this.value = 0 as any
268
268
  } else if (typeof this.value == 'string') {
269
- throw new Error("Unimplemented")
269
+ throw new Error('Unimplemented')
270
270
  }
271
271
 
272
272
  return this
@@ -284,7 +284,7 @@ abstract class ValueRef<T extends number | string> {
284
284
 
285
285
  protected assertNotFreed() {
286
286
  if (this.isFreed) {
287
- throw new Error("Attempt to read a freed WASM value reference.")
287
+ throw new Error('Attempt to read a freed WASM value reference.')
288
288
  }
289
289
  }
290
290
  }
@@ -381,13 +381,13 @@ export class NullTerminatedUtf8StringRef extends ValueRef<string> {
381
381
 
382
382
  const strBytes = heapU8.subarray(ptr, ptr + endByteOffset)
383
383
 
384
- const str = Buffer.from(strBytes).toString("utf8")
384
+ const str = Buffer.from(strBytes).toString('utf8')
385
385
 
386
386
  return str
387
387
  }
388
388
 
389
389
  setValue(newValue: string) {
390
- throw new Error("Unimplemented")
390
+ throw new Error('Unimplemented')
391
391
  }
392
392
  }
393
393
 
@@ -437,7 +437,7 @@ abstract class TypedArrayRef<T extends TypedArray> {
437
437
 
438
438
  protected assertNotFreed() {
439
439
  if (this.isFreed) {
440
- throw new Error("Attempt to read a freed WASM typed array reference.")
440
+ throw new Error('Attempt to read a freed WASM typed array reference.')
441
441
  }
442
442
  }
443
443
  }
@@ -464,7 +464,7 @@ export class Uint8ArrayRef extends TypedArrayRef<Uint8Array> {
464
464
  strBytes = strBytes.subarray(0, indexOfFirstZero)
465
465
  }
466
466
 
467
- const str = Buffer.from(strBytes).toString("utf8")
467
+ const str = Buffer.from(strBytes).toString('utf8')
468
468
 
469
469
  return str
470
470
  }
@@ -10,29 +10,29 @@ export async function fetchDocumentText(url: string) {
10
10
 
11
11
  const response = await request<string>({
12
12
  url,
13
- responseType: "text",
13
+ responseType: 'text',
14
14
  headers: {
15
- "sec-ch-ua": `".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"`,
16
- "x-same-domain": "1",
17
- "dnt": "1",
18
- "content-type": "application/x-www-form-urlencoded;charset=UTF-8",
19
- "sec-ch-ua-mobile": "?0",
20
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
21
- "sec-ch-ua-arch": "x86",
22
- "sec-ch-ua-full-version": "103.0.5060.114",
23
- "sec-ch-ua-platform-version": "10.0.0",
24
- "sec-ch-ua-full-version-list": `".Not/A)Brand";v="99.0.0.0", "Google Chrome";v="103.0.5060.114", "Chromium";v="103.0.5060.114"`,
25
- "sec-ch-ua-bitness": "64",
26
- "sec-ch-ua-model": "",
27
- "sec-ch-ua-platform": "Windows",
28
- "accept": "*/*",
29
- //"origin": "https://www.google.com/",
30
- "sec-fetch-site": "same-origin",
31
- "sec-fetch-mode": "cors",
32
- "sec-fetch-dest": "empty",
33
- "referer": "https://www.google.com/",
34
- "accept-encoding": "gzip, deflate, br",
35
- "accept-language": "en-US,en;q=0.9",
15
+ 'sec-ch-ua': `".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"`,
16
+ 'x-same-domain': '1',
17
+ 'dnt': '1',
18
+ 'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
19
+ 'sec-ch-ua-mobile': '?0',
20
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
21
+ 'sec-ch-ua-arch': 'x86',
22
+ 'sec-ch-ua-full-version': '103.0.5060.114',
23
+ 'sec-ch-ua-platform-version': '10.0.0',
24
+ 'sec-ch-ua-full-version-list': `".Not/A)Brand";v="99.0.0.0", "Google Chrome";v="103.0.5060.114", "Chromium";v="103.0.5060.114"`,
25
+ 'sec-ch-ua-bitness': '64',
26
+ 'sec-ch-ua-model': '',
27
+ 'sec-ch-ua-platform': 'Windows',
28
+ 'accept': '*/*',
29
+ //'origin': 'https://www.google.com/',
30
+ 'sec-fetch-site': 'same-origin',
31
+ 'sec-fetch-mode': 'cors',
32
+ 'sec-fetch-dest': 'empty',
33
+ 'referer': 'https://www.google.com/',
34
+ 'accept-encoding': 'gzip, deflate, br',
35
+ 'accept-language': 'en-US,en;q=0.9',
36
36
  },
37
37
  })
38
38
 
@@ -47,7 +47,7 @@ export async function fetchDocumentText(url: string) {
47
47
 
48
48
  const article = reader.parse()
49
49
 
50
- const text: string = await convertHtmlToText(article?.content || "")
50
+ const text: string = await convertHtmlToText(article?.content || '')
51
51
 
52
52
  progressLogger.end()
53
53
 
@@ -4,14 +4,14 @@ import { Logger } from './Logger.js'
4
4
  export async function parseWikipediaArticle(articleName: string, language: string) {
5
5
  const logger = new Logger()
6
6
 
7
- logger.startAsync("Fetching Wikipedia article")
7
+ logger.startAsync('Fetching Wikipedia article')
8
8
 
9
9
  const { default: wtf } = await import('wtf_wikipedia')
10
10
 
11
11
  const document = await wtf.fetch(articleName, language)
12
12
 
13
13
  if (!document) {
14
- throw new Error("Error fetching Wikipedia article")
14
+ throw new Error('Error fetching Wikipedia article')
15
15
  }
16
16
 
17
17
  const sections = document.sections()
@@ -0,0 +1,202 @@
1
+ import { RawAudio, getRawAudioDuration } from '../audio/AudioUtilities.js';
2
+ import { BiquadFilter, createHighpassFilter, createLowpassFilter } from '../dsp/BiquadFilter.js';
3
+ import { DecayingPeakEstimator } from '../dsp/DecayingPeakEstimator.js';
4
+ import { LoudnessEstimator } from '../dsp/LoudnessEstimator.js';
5
+ import { extendDeep } from '../utilities/ObjectUtilities.js';
6
+ import { Timeline } from '../utilities/Timeline.js';
7
+ import { logToStderr } from '../utilities/Utilities.js';
8
+
9
+ const log = logToStderr
10
+
11
+ export async function detectVoiceActivity(rawAudio: RawAudio, options: AdaptiveGateVADOptions) {
12
+ const channelCount = rawAudio.audioChannels.length
13
+ const sampleCount = rawAudio.audioChannels[0].length
14
+ const sampleRate = rawAudio.sampleRate
15
+
16
+ const audioDuration = getRawAudioDuration(rawAudio)
17
+
18
+ options = extendDeep(defaultAdaptiveGateOptions, options)
19
+
20
+ const gateVAD = new AdaptiveGateVAD(sampleRate, channelCount, options)
21
+
22
+ type FrameRecord = {
23
+ timePosition: number
24
+ loudness: number
25
+ minimumLoudness: number
26
+ maximumLoudness: number
27
+ }
28
+
29
+ const frameDuration = 0.01
30
+
31
+ const frameRecords: FrameRecord[] = []
32
+
33
+ for (let sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) {
34
+ const timePosition = sampleIndex / sampleRate
35
+
36
+ for (let channelIndex = 0; channelIndex < channelCount; channelIndex++) {
37
+ const sample = rawAudio.audioChannels[channelIndex][sampleIndex]
38
+
39
+ gateVAD.process(sample, channelIndex)
40
+ }
41
+
42
+ if (
43
+ frameRecords.length == 0 ||
44
+ timePosition > frameRecords[frameRecords.length - 1].timePosition + frameDuration) {
45
+
46
+ const record: FrameRecord = {
47
+ timePosition,
48
+ loudness: gateVAD.loudnessEstimator.currentLoudness,
49
+ minimumLoudness: gateVAD.minimumLoudnessEstimator.currentPeak,
50
+ maximumLoudness: gateVAD.maximumLoudnessEstimator.currentPeak,
51
+ }
52
+
53
+ frameRecords.push(record)
54
+
55
+ //log(`${timePosition.toFixed(3)}: loudness: ${record.loudness.toFixed(2)}dB, min: ${record.minimumLoudness.toFixed(2)}dB, max: ${record.maximumLoudness.toFixed(2)}dB dynamic range: ${record.dynamicRange.toFixed(2)}dB`)
56
+ }
57
+ }
58
+
59
+ const frameActive: boolean[] = []
60
+
61
+ for (let i = 0; i < frameRecords.length; i++) {
62
+ frameActive[i] = false
63
+ }
64
+
65
+ {
66
+ const backwardExtensionFrameCount = Math.floor(options.backwardExtensionDuration! / frameDuration)
67
+ const relativeThreshold = options.relativeThreshold!
68
+
69
+ let extendedActivityStartIndex = frameRecords.length
70
+
71
+ for (let i = frameRecords.length - 1; i >= 0; i--) {
72
+ const record = frameRecords[i]
73
+ const referenceLoudness = Math.max(record.maximumLoudness, -30)
74
+
75
+ let isActive = false
76
+
77
+ if (i >= extendedActivityStartIndex) {
78
+ isActive = true
79
+ }
80
+
81
+ if (record.loudness >= referenceLoudness + relativeThreshold) {
82
+ isActive = true
83
+
84
+ extendedActivityStartIndex = Math.max(i - backwardExtensionFrameCount, 0)
85
+ }
86
+
87
+ frameActive[i] = isActive
88
+ }
89
+ }
90
+
91
+ const timeline: Timeline = []
92
+
93
+ for (let i = 0; i < frameRecords.length; i++) {
94
+ const record = frameRecords[i]
95
+ const isActive = frameActive[i]
96
+ const activityText = isActive ? 'active' : 'inactive'
97
+ const startTime = record.timePosition
98
+ const endTime = Math.min(startTime + frameDuration, audioDuration)
99
+
100
+ if (timeline.length == 0 || timeline[timeline.length - 1].text != activityText) {
101
+ timeline.push({
102
+ type: 'segment',
103
+ text: activityText,
104
+ startTime,
105
+ endTime,
106
+ })
107
+ } else {
108
+ timeline[timeline.length - 1].endTime = endTime
109
+ }
110
+ }
111
+
112
+ return timeline
113
+ }
114
+
115
+ export class AdaptiveGateVAD {
116
+ channelHighpassFilters: BiquadFilter[]
117
+ channelLowpassFilters: BiquadFilter[]
118
+
119
+ loudnessEstimator: LoudnessEstimator
120
+
121
+ minimumLoudnessEstimator: DecayingPeakEstimator
122
+ maximumLoudnessEstimator: DecayingPeakEstimator
123
+
124
+ constructor(
125
+ public readonly sampleRate: number,
126
+ public readonly channelCount: number,
127
+ public readonly options: AdaptiveGateVADOptions) {
128
+
129
+ this.channelHighpassFilters = []
130
+ this.channelLowpassFilters = []
131
+
132
+ for (let i = 0; i < this.channelCount; i++) {
133
+ this.channelHighpassFilters.push(createHighpassFilter(this.sampleRate, options.lowCutoff!))
134
+ this.channelLowpassFilters.push(createLowpassFilter(this.sampleRate, options.highCutoff!))
135
+ }
136
+
137
+ this.loudnessEstimator = new LoudnessEstimator({
138
+ sampleRate: this.sampleRate,
139
+ channelCount: this.channelCount,
140
+ positiveAdaptationRate: options.positiveAdaptationRate!,
141
+ negativeAdaptationRate: options.negativeAdaptationRate!,
142
+ initialEstimate: -60,
143
+ minimumLoudness: -60,
144
+ applyKWeighting: false,
145
+ })
146
+
147
+ const ticksPerSecond = this.sampleRate * this.channelCount
148
+
149
+ this.minimumLoudnessEstimator = new DecayingPeakEstimator({
150
+ kind: 'minimum',
151
+ decayPerSecond: options.peakLoudnessDecay!,
152
+ initialPeak: -60,
153
+ }, ticksPerSecond)
154
+
155
+ this.maximumLoudnessEstimator = new DecayingPeakEstimator({
156
+ kind: 'maximum',
157
+ decayPerSecond: options.peakLoudnessDecay!,
158
+ initialPeak: -60,
159
+ }, ticksPerSecond)
160
+ }
161
+
162
+ process(sample: number, channelIndex: number) {
163
+ sample = this.channelHighpassFilters[channelIndex].filter(sample)
164
+ sample = this.channelLowpassFilters[channelIndex].filter(sample)
165
+
166
+ this.loudnessEstimator.process(sample, channelIndex)
167
+
168
+ const currentLoudness = this.loudnessEstimator.currentLoudness
169
+
170
+ this.minimumLoudnessEstimator.process(currentLoudness)
171
+
172
+ if (currentLoudness >= -60) {
173
+ this.maximumLoudnessEstimator.process(currentLoudness)
174
+ }
175
+ }
176
+ }
177
+
178
+ export interface AdaptiveGateVADOptions {
179
+ lowCutoff?: number
180
+ highCutoff?: number
181
+
182
+ positiveAdaptationRate?: number,
183
+ negativeAdaptationRate?: number,
184
+
185
+ peakLoudnessDecay?: number,
186
+
187
+ backwardExtensionDuration?: number
188
+ relativeThreshold?: number
189
+ }
190
+
191
+ export const defaultAdaptiveGateOptions: AdaptiveGateVADOptions = {
192
+ lowCutoff: 100,
193
+ highCutoff: 1000,
194
+
195
+ positiveAdaptationRate: 400.0,
196
+ negativeAdaptationRate: 10.0,
197
+
198
+ peakLoudnessDecay: 4.0,
199
+
200
+ backwardExtensionDuration: 0.2,
201
+ relativeThreshold: -15,
202
+ }
@@ -5,9 +5,9 @@ import { RawAudio } from '../audio/AudioUtilities.js'
5
5
 
6
6
  let sileroVad: SileroVAD
7
7
 
8
- export async function detectVoiceActivity(rawAudio: RawAudio, modelPath: string, frameDuration: 30 | 60 | 90 = 30) {
8
+ export async function detectVoiceActivity(rawAudio: RawAudio, modelPath: string, frameDuration: 30 | 60 | 90) {
9
9
  if (rawAudio.sampleRate != 16000) {
10
- throw new Error("Audio sample rate must be 16KHz")
10
+ throw new Error('Audio sample rate must be 16KHz')
11
11
  }
12
12
 
13
13
  const audioSamples = rawAudio.audioChannels[0]
@@ -68,10 +68,10 @@ export class SileroVAD {
68
68
 
69
69
  const results = await this.session!.run(inputs)
70
70
 
71
- const probability = results["output"].data[0] as number
71
+ const probability = results['output'].data[0] as number
72
72
 
73
- this.modelStateH = results["hn"]
74
- this.modelStateC = results["cn"]
73
+ this.modelStateH = results['hn']
74
+ this.modelStateC = results['cn']
75
75
 
76
76
  return probability
77
77
  }
@@ -1,10 +1,10 @@
1
- import * as AudioBufferConversion from "../audio/AudioBufferConversion.js"
2
- import { RawAudio } from "../audio/AudioUtilities.js"
3
- import { WasmMemoryManager } from "../utilities/WasmMemoryManager.js"
1
+ import * as AudioBufferConversion from '../audio/AudioBufferConversion.js'
2
+ import { RawAudio } from '../audio/AudioUtilities.js'
3
+ import { WasmMemoryManager } from '../utilities/WasmMemoryManager.js'
4
4
 
5
5
  export async function detectVoiceActivity(rawAudio: RawAudio, frameDuration: 10 | 20 | 30 = 10, mode: 0 | 1 | 2 | 3 = 0) {
6
6
  if (rawAudio.sampleRate != 16000) {
7
- throw new Error("Audio sample rate must be 16KHz")
7
+ throw new Error('Audio sample rate must be 16KHz')
8
8
  }
9
9
 
10
10
  const frameClassifications: (0 | 1)[] = await fvad(AudioBufferConversion.float32ToInt16Pcm(rawAudio.audioChannels[0]), rawAudio.sampleRate, frameDuration, mode)
@@ -52,7 +52,7 @@ export async function fvad(samples: Int16Array, sampleRate: number, frameDuratio
52
52
  const fvadResult = fvad_process(instancePtr, frameSamplesRef.address, frameSampleCount)
53
53
 
54
54
  if (fvadResult == -1) {
55
- throw new Error("fvad_process failed")
55
+ throw new Error('fvad_process failed')
56
56
  }
57
57
 
58
58
  result.push(fvadResult)