echogarden 1.8.7 → 2.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 (309) hide show
  1. package/README.md +23 -18
  2. package/data/schemas/options.json +52 -47
  3. package/dist/alignment/DTWSequenceAlignment.d.ts +1 -1
  4. package/dist/alignment/DTWSequenceAlignment.js +5 -5
  5. package/dist/alignment/DTWSequenceAlignment.js.map +1 -1
  6. package/dist/alignment/SpeechAlignment.js +6 -6
  7. package/dist/alignment/SpeechAlignment.js.map +1 -1
  8. package/dist/api/Alignment.d.ts +1 -1
  9. package/dist/api/Alignment.js +49 -11
  10. package/dist/api/Alignment.js.map +1 -1
  11. package/dist/api/Denoising.d.ts +4 -2
  12. package/dist/api/Denoising.js +65 -13
  13. package/dist/api/Denoising.js.map +1 -1
  14. package/dist/api/SourceSeparation.js +9 -6
  15. package/dist/api/SourceSeparation.js.map +1 -1
  16. package/dist/api/SpeechLanguageDetection.js +4 -4
  17. package/dist/api/SpeechLanguageDetection.js.map +1 -1
  18. package/dist/api/Synthesis.d.ts +2 -2
  19. package/dist/api/Synthesis.js +10 -7
  20. package/dist/api/Synthesis.js.map +1 -1
  21. package/dist/api/VoiceActivityDetection.js +2 -2
  22. package/dist/api/VoiceActivityDetection.js.map +1 -1
  23. package/dist/audio/AudioBufferConversion.d.ts +2 -2
  24. package/dist/audio/AudioBufferConversion.js +77 -43
  25. package/dist/audio/AudioBufferConversion.js.map +1 -1
  26. package/dist/audio/AudioPlayer.d.ts +7 -5
  27. package/dist/audio/AudioPlayer.js +135 -49
  28. package/dist/audio/AudioPlayer.js.map +1 -1
  29. package/dist/audio/AudioUtilities.d.ts +4 -3
  30. package/dist/audio/AudioUtilities.js +30 -15
  31. package/dist/audio/AudioUtilities.js.map +1 -1
  32. package/dist/audio/SoxPath.js +3 -3
  33. package/dist/audio/SoxPath.js.map +1 -1
  34. package/dist/build-tools/MakeTarballsForInstalledPackages.js +3 -3
  35. package/dist/build-tools/MakeTarballsForInstalledPackages.js.map +1 -1
  36. package/dist/cli/CLI.js +30 -36
  37. package/dist/cli/CLI.js.map +1 -1
  38. package/dist/cli/CLIConfigFile.js +2 -2
  39. package/dist/cli/CLIConfigFile.js.map +1 -1
  40. package/dist/cli/CLIOptions.d.ts +2 -0
  41. package/dist/cli/CLIOptions.js +1 -1
  42. package/dist/cli/CLIOptions.js.map +1 -1
  43. package/dist/codecs/FFMpegTranscoder.d.ts +3 -3
  44. package/dist/codecs/FFMpegTranscoder.js +6 -6
  45. package/dist/codecs/FFMpegTranscoder.js.map +1 -1
  46. package/dist/codecs/TIMITCodec.d.ts +1 -1
  47. package/dist/codecs/TIMITCodec.js +4 -3
  48. package/dist/codecs/TIMITCodec.js.map +1 -1
  49. package/dist/codecs/WaveCodec.d.ts +3 -3
  50. package/dist/codecs/WaveCodec.js +37 -34
  51. package/dist/codecs/WaveCodec.js.map +1 -1
  52. package/dist/data-structures/DynamicTypedArray.d.ts +17 -0
  53. package/dist/data-structures/DynamicTypedArray.js +47 -0
  54. package/dist/data-structures/DynamicTypedArray.js.map +1 -0
  55. package/dist/data-structures/Queue.js.map +1 -0
  56. package/dist/data-structures/WindowedList.js.map +1 -0
  57. package/dist/denoising/NSNet2.d.ts +26 -0
  58. package/dist/denoising/NSNet2.js +128 -0
  59. package/dist/denoising/NSNet2.js.map +1 -0
  60. package/dist/denoising/RNNoise.js +3 -3
  61. package/dist/denoising/RNNoise.js.map +1 -1
  62. package/dist/dsp/FFT.d.ts +6 -1
  63. package/dist/dsp/FFT.js +17 -0
  64. package/dist/dsp/FFT.js.map +1 -1
  65. package/dist/encodings/Ascii.d.ts +10 -0
  66. package/dist/encodings/Ascii.js +41 -0
  67. package/dist/encodings/Ascii.js.map +1 -0
  68. package/dist/encodings/Base64.d.ts +5 -0
  69. package/dist/encodings/Base64.js +114 -0
  70. package/dist/encodings/Base64.js.map +1 -0
  71. package/dist/encodings/Hex.d.ts +3 -0
  72. package/dist/encodings/Hex.js +52 -0
  73. package/dist/encodings/Hex.js.map +1 -0
  74. package/dist/encodings/HtmlEscape.d.ts +1 -0
  75. package/dist/encodings/HtmlEscape.js +30 -0
  76. package/dist/encodings/HtmlEscape.js.map +1 -0
  77. package/dist/{utilities → encodings}/LEB128.d.ts +1 -1
  78. package/dist/{utilities → encodings}/LEB128.js +4 -4
  79. package/dist/encodings/LEB128.js.map +1 -0
  80. package/dist/{utilities → encodings}/LPVarInt.d.ts +1 -1
  81. package/dist/{utilities → encodings}/LPVarInt.js +6 -6
  82. package/dist/encodings/LPVarInt.js.map +1 -0
  83. package/dist/encodings/TextEncodingsCommon.d.ts +4 -0
  84. package/dist/encodings/TextEncodingsCommon.js +2 -0
  85. package/dist/encodings/TextEncodingsCommon.js.map +1 -0
  86. package/dist/encodings/Utf16.d.ts +10 -0
  87. package/dist/encodings/Utf16.js +36 -0
  88. package/dist/encodings/Utf16.js.map +1 -0
  89. package/dist/encodings/Utf32.d.ts +4 -0
  90. package/dist/encodings/Utf32.js +32 -0
  91. package/dist/encodings/Utf32.js.map +1 -0
  92. package/dist/encodings/Utf8.d.ts +10 -0
  93. package/dist/encodings/Utf8.js +97 -0
  94. package/dist/encodings/Utf8.js.map +1 -0
  95. package/dist/math/MedianFilter.d.ts +0 -1
  96. package/dist/math/MedianFilter.js +0 -10
  97. package/dist/math/MedianFilter.js.map +1 -1
  98. package/dist/nlp/JapaneseSegmentation.js +2 -2
  99. package/dist/nlp/JapaneseSegmentation.js.map +1 -1
  100. package/dist/recognition/GoogleCloudSTT.js +2 -1
  101. package/dist/recognition/GoogleCloudSTT.js.map +1 -1
  102. package/dist/recognition/SileroSTT.js +3 -3
  103. package/dist/recognition/SileroSTT.js.map +1 -1
  104. package/dist/recognition/VoskSTT.js +3 -3
  105. package/dist/recognition/VoskSTT.js.map +1 -1
  106. package/dist/recognition/WhisperCppSTT.js +4 -5
  107. package/dist/recognition/WhisperCppSTT.js.map +1 -1
  108. package/dist/recognition/WhisperSTT.js +8 -7
  109. package/dist/recognition/WhisperSTT.js.map +1 -1
  110. package/dist/server/Client.d.ts +1 -1
  111. package/dist/server/Client.js +2 -1
  112. package/dist/server/Client.js.map +1 -1
  113. package/dist/server/Server.js +5 -4
  114. package/dist/server/Server.js.map +1 -1
  115. package/dist/server/Worker.js +1 -1
  116. package/dist/server/Worker.js.map +1 -1
  117. package/dist/source-separation/MDXNetSourceSeparation.js +1 -1
  118. package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -1
  119. package/dist/speech-search/DTWSpeechSearch.d.ts +1 -1
  120. package/dist/speech-search/DTWSpeechSearch.js +25 -6
  121. package/dist/speech-search/DTWSpeechSearch.js.map +1 -1
  122. package/dist/subtitles/Subtitles.js +2 -2
  123. package/dist/subtitles/Subtitles.js.map +1 -1
  124. package/dist/synthesis/AzureCognitiveServicesTTS.js +19 -20
  125. package/dist/synthesis/AzureCognitiveServicesTTS.js.map +1 -1
  126. package/dist/synthesis/CoquiServerTTS.js +1 -1
  127. package/dist/synthesis/CoquiServerTTS.js.map +1 -1
  128. package/dist/synthesis/ElevenlabsTTS.js +1 -1
  129. package/dist/synthesis/ElevenlabsTTS.js.map +1 -1
  130. package/dist/synthesis/EspeakTTS.d.ts +0 -1
  131. package/dist/synthesis/EspeakTTS.js +2 -11
  132. package/dist/synthesis/EspeakTTS.js.map +1 -1
  133. package/dist/synthesis/FliteTTS.js +8 -9
  134. package/dist/synthesis/FliteTTS.js.map +1 -1
  135. package/dist/synthesis/GoogleCloudTTS.d.ts +1 -1
  136. package/dist/synthesis/GoogleCloudTTS.js +2 -1
  137. package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
  138. package/dist/synthesis/GoogleTranslateTTS.d.ts +1 -1
  139. package/dist/synthesis/GoogleTranslateTTS.js +4 -3
  140. package/dist/synthesis/GoogleTranslateTTS.js.map +1 -1
  141. package/dist/synthesis/MicrosoftEdgeTTS.js +34 -9
  142. package/dist/synthesis/MicrosoftEdgeTTS.js.map +1 -1
  143. package/dist/synthesis/SapiTTS.js +1 -1
  144. package/dist/synthesis/SapiTTS.js.map +1 -1
  145. package/dist/synthesis/StreamlabsPollyTTS.d.ts +1 -1
  146. package/dist/synthesis/StreamlabsPollyTTS.js +1 -1
  147. package/dist/synthesis/StreamlabsPollyTTS.js.map +1 -1
  148. package/dist/synthesis/SvoxPicoTTS.js +6 -6
  149. package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
  150. package/dist/synthesis/VitsTTS.js +2 -2
  151. package/dist/synthesis/VitsTTS.js.map +1 -1
  152. package/dist/tests/Test.js +1 -47
  153. package/dist/tests/Test.js.map +1 -1
  154. package/dist/text-language-detection/FastTextLanguageDetection.js +2 -2
  155. package/dist/text-language-detection/FastTextLanguageDetection.js.map +1 -1
  156. package/dist/text-translation/GoogleTranslateTextTranslation.js +1 -1
  157. package/dist/text-translation/GoogleTranslateTextTranslation.js.map +1 -1
  158. package/dist/typings/TypedArray.d.ts +4 -0
  159. package/dist/typings/TypedArray.js +2 -0
  160. package/dist/typings/TypedArray.js.map +1 -0
  161. package/dist/utilities/BinaryArrayConversion.d.ts +12 -22
  162. package/dist/utilities/BinaryArrayConversion.js +40 -90
  163. package/dist/utilities/BinaryArrayConversion.js.map +1 -1
  164. package/dist/utilities/BinaryUtilities.d.ts +13 -0
  165. package/dist/utilities/BinaryUtilities.js +113 -0
  166. package/dist/utilities/BinaryUtilities.js.map +1 -0
  167. package/dist/utilities/Compression.js +7 -6
  168. package/dist/utilities/Compression.js.map +1 -1
  169. package/dist/utilities/FileDownloader.js +26 -47
  170. package/dist/utilities/FileDownloader.js.map +1 -1
  171. package/dist/utilities/FileReader.d.ts +14 -0
  172. package/dist/utilities/FileReader.js +71 -0
  173. package/dist/utilities/FileReader.js.map +1 -0
  174. package/dist/utilities/FileSystem.d.ts +19 -16
  175. package/dist/utilities/FileSystem.js +170 -109
  176. package/dist/utilities/FileSystem.js.map +1 -1
  177. package/dist/utilities/FileWriter.d.ts +12 -0
  178. package/dist/utilities/FileWriter.js +60 -0
  179. package/dist/utilities/FileWriter.js.map +1 -0
  180. package/dist/utilities/NpmUtilities.d.ts +1 -0
  181. package/dist/utilities/NpmUtilities.js +14 -0
  182. package/dist/utilities/NpmUtilities.js.map +1 -0
  183. package/dist/utilities/PackageManager.js +7 -5
  184. package/dist/utilities/PackageManager.js.map +1 -1
  185. package/dist/utilities/PathUtilities.d.ts +8 -0
  186. package/dist/utilities/PathUtilities.js +28 -7
  187. package/dist/utilities/PathUtilities.js.map +1 -1
  188. package/dist/utilities/SignalChannel.d.ts +3 -1
  189. package/dist/utilities/SignalChannel.js +9 -5
  190. package/dist/utilities/SignalChannel.js.map +1 -1
  191. package/dist/utilities/StringBuilder.d.ts +10 -0
  192. package/dist/utilities/StringBuilder.js +39 -0
  193. package/dist/utilities/StringBuilder.js.map +1 -0
  194. package/dist/utilities/StringUtilities.js.map +1 -1
  195. package/dist/utilities/TarballMaker.js +6 -7
  196. package/dist/utilities/TarballMaker.js.map +1 -1
  197. package/dist/utilities/Timer.js +2 -2
  198. package/dist/utilities/Timer.js.map +1 -1
  199. package/dist/utilities/Utilities.d.ts +11 -5
  200. package/dist/utilities/Utilities.js +69 -33
  201. package/dist/utilities/Utilities.js.map +1 -1
  202. package/dist/utilities/VirtualFileReadStream.d.ts +3 -3
  203. package/dist/utilities/VirtualFileReadStream.js.map +1 -1
  204. package/dist/utilities/WasmMemoryManager.d.ts +5 -2
  205. package/dist/utilities/WasmMemoryManager.js +15 -4
  206. package/dist/utilities/WasmMemoryManager.js.map +1 -1
  207. package/docs/API.md +1 -1
  208. package/docs/CLI.md +1 -1
  209. package/docs/Licenses.md +3 -0
  210. package/docs/Options.md +9 -3
  211. package/docs/Tasklist.md +0 -1
  212. package/docs/Technical.md +2 -2
  213. package/package.json +22 -25
  214. package/src/alignment/DTWSequenceAlignment.ts +5 -5
  215. package/src/alignment/SpeechAlignment.ts +6 -6
  216. package/src/api/Alignment.ts +65 -12
  217. package/src/api/Denoising.ts +97 -17
  218. package/src/api/SourceSeparation.ts +11 -8
  219. package/src/api/SpeechLanguageDetection.ts +4 -4
  220. package/src/api/Synthesis.ts +15 -11
  221. package/src/api/VoiceActivityDetection.ts +2 -2
  222. package/src/audio/AudioBufferConversion.ts +84 -45
  223. package/src/audio/AudioPlayer.ts +155 -53
  224. package/src/audio/AudioUtilities.ts +38 -22
  225. package/src/audio/SoxPath.ts +3 -3
  226. package/src/build-tools/MakeTarballsForInstalledPackages.ts +3 -3
  227. package/src/cli/CLI.ts +30 -36
  228. package/src/cli/CLIConfigFile.ts +2 -2
  229. package/src/cli/CLIOptions.ts +4 -1
  230. package/src/codecs/FFMpegTranscoder.ts +11 -11
  231. package/src/codecs/TIMITCodec.ts +5 -4
  232. package/src/codecs/WaveCodec.ts +42 -39
  233. package/src/data-structures/DynamicTypedArray.ts +64 -0
  234. package/src/denoising/NSNet2.ts +182 -0
  235. package/src/denoising/RNNoise.ts +3 -3
  236. package/src/dsp/FFT.ts +21 -1
  237. package/src/encodings/Ascii.ts +60 -0
  238. package/src/encodings/Base64.ts +157 -0
  239. package/src/encodings/Hex.ts +67 -0
  240. package/src/encodings/HtmlEscape.ts +39 -0
  241. package/src/{utilities → encodings}/LEB128.ts +4 -4
  242. package/src/{utilities → encodings}/LPVarInt.ts +6 -6
  243. package/src/encodings/TextEncodingsCommon.ts +4 -0
  244. package/src/encodings/Utf16.ts +52 -0
  245. package/src/encodings/Utf32.ts +44 -0
  246. package/src/encodings/Utf8.ts +117 -0
  247. package/src/math/MedianFilter.ts +0 -16
  248. package/src/nlp/JapaneseSegmentation.ts +2 -2
  249. package/src/recognition/GoogleCloudSTT.ts +2 -1
  250. package/src/recognition/SileroSTT.ts +3 -3
  251. package/src/recognition/VoskSTT.ts +3 -3
  252. package/src/recognition/WhisperCppSTT.ts +4 -5
  253. package/src/recognition/WhisperSTT.ts +8 -7
  254. package/src/server/Client.ts +4 -3
  255. package/src/server/Server.ts +6 -5
  256. package/src/server/Worker.ts +1 -1
  257. package/src/source-separation/MDXNetSourceSeparation.ts +1 -1
  258. package/src/speech-search/DTWSpeechSearch.ts +36 -7
  259. package/src/subtitles/Subtitles.ts +3 -3
  260. package/src/synthesis/AzureCognitiveServicesTTS.ts +20 -18
  261. package/src/synthesis/CoquiServerTTS.ts +2 -2
  262. package/src/synthesis/ElevenlabsTTS.ts +1 -1
  263. package/src/synthesis/EspeakTTS.ts +2 -18
  264. package/src/synthesis/FliteTTS.ts +8 -10
  265. package/src/synthesis/GoogleCloudTTS.ts +3 -2
  266. package/src/synthesis/GoogleTranslateTTS.ts +5 -4
  267. package/src/synthesis/MicrosoftEdgeTTS.ts +49 -18
  268. package/src/synthesis/SapiTTS.ts +1 -1
  269. package/src/synthesis/StreamlabsPollyTTS.ts +1 -1
  270. package/src/synthesis/SvoxPicoTTS.ts +8 -8
  271. package/src/synthesis/VitsTTS.ts +2 -2
  272. package/src/tests/Test.ts +1 -60
  273. package/src/text-language-detection/FastTextLanguageDetection.ts +2 -2
  274. package/src/text-translation/GoogleTranslateTextTranslation.ts +1 -1
  275. package/src/typings/Fillers.d.ts +2 -10
  276. package/src/typings/TypedArray.ts +5 -0
  277. package/src/utilities/BinaryArrayConversion.ts +51 -125
  278. package/src/utilities/BinaryUtilities.ts +138 -0
  279. package/src/utilities/Compression.ts +7 -6
  280. package/src/utilities/FileDownloader.ts +27 -52
  281. package/src/utilities/FileReader.ts +89 -0
  282. package/src/utilities/FileSystem.ts +213 -120
  283. package/src/utilities/FileWriter.ts +72 -0
  284. package/src/utilities/NpmUtilities.ts +23 -0
  285. package/src/utilities/PackageManager.ts +8 -5
  286. package/src/utilities/PathUtilities.ts +36 -7
  287. package/src/utilities/SignalChannel.ts +14 -7
  288. package/src/utilities/StringBuilder.ts +45 -0
  289. package/src/utilities/StringUtilities.ts +2 -0
  290. package/src/utilities/TarballMaker.ts +6 -7
  291. package/src/utilities/Timer.ts +4 -2
  292. package/src/utilities/Utilities.ts +80 -45
  293. package/src/utilities/VirtualFileReadStream.ts +5 -5
  294. package/src/utilities/WasmMemoryManager.ts +20 -6
  295. package/tsconfig.json +96 -0
  296. package/dist/utilities/DynamicUint8Array.d.ts +0 -9
  297. package/dist/utilities/DynamicUint8Array.js +0 -31
  298. package/dist/utilities/DynamicUint8Array.js.map +0 -1
  299. package/dist/utilities/LEB128.js.map +0 -1
  300. package/dist/utilities/LPVarInt.js.map +0 -1
  301. package/dist/utilities/Queue.js.map +0 -1
  302. package/dist/utilities/WindowedList.js.map +0 -1
  303. package/src/utilities/DynamicUint8Array.ts +0 -39
  304. /package/dist/{utilities → data-structures}/Queue.d.ts +0 -0
  305. /package/dist/{utilities → data-structures}/Queue.js +0 -0
  306. /package/dist/{utilities → data-structures}/WindowedList.d.ts +0 -0
  307. /package/dist/{utilities → data-structures}/WindowedList.js +0 -0
  308. /package/src/{utilities → data-structures}/Queue.ts +0 -0
  309. /package/src/{utilities → data-structures}/WindowedList.ts +0 -0
@@ -3,7 +3,6 @@ import { int16PcmToFloat32 } from '../audio/AudioBufferConversion.js'
3
3
  import { Logger } from '../utilities/Logger.js'
4
4
  import { WasmMemoryManager } from '../utilities/WasmMemoryManager.js'
5
5
  import { RawAudio, getEmptyRawAudio } from '../audio/AudioUtilities.js'
6
- import { playAudioWithTimelinePhones } from '../audio/AudioPlayer.js'
7
6
  import { getNormalizedFragmentsForSpeech, simplifyPunctuationCharacters } from '../nlp/TextNormalizer.js'
8
7
  import { ipaPhoneToKirshenbaum } from '../nlp/PhoneConversion.js'
9
8
  import { splitToWords, wordCharacterPattern } from '../nlp/Segmentation.js'
@@ -11,6 +10,7 @@ import { Lexicon, tryGetFirstLexiconSubstitution } from '../nlp/Lexicon.js'
11
10
  import { phonemizeSentence } from '../nlp/EspeakPhonemizer.js'
12
11
  import { Timeline, TimelineEntry } from '../utilities/Timeline.js'
13
12
  import { extendDeep } from '../utilities/ObjectUtilities.js'
13
+ import { escapeHtml } from '../encodings/HtmlEscape.js'
14
14
 
15
15
  const log = logToStderr
16
16
 
@@ -433,9 +433,7 @@ export async function synthesize(text: string, espeakOptions: EspeakOptions) {
433
433
  logger.start('Get eSpeak Emscripten instance')
434
434
 
435
435
  if (!espeakOptions.ssml) {
436
- const { escape } = await import('html-escaper')
437
-
438
- text = escape(text)
436
+ text = escapeHtml(text)
439
437
  }
440
438
 
441
439
  const { instance } = await getEspeakInstance()
@@ -599,20 +597,6 @@ export const defaultEspeakOptions: EspeakOptions = {
599
597
  insertSeparators: false
600
598
  }
601
599
 
602
- export async function testEspeakSynthesisWithPrePhonemizedInputs(text: string) {
603
- const ipaPhonemizedSentence = (await phonemizeSentence(text, 'en-us')).flatMap(clause => clause)
604
- const kirshenbaumPhonemizedSentence = (await phonemizeSentence(text, 'en-us', undefined, false)).flatMap(clause => clause)
605
- log(kirshenbaumPhonemizedSentence)
606
-
607
- const fragments = ipaPhonemizedSentence.map(word =>
608
- word.map(phoneme =>
609
- ipaPhoneToKirshenbaum(phoneme)).join('')).map(word => ` [[${word}]] `)
610
-
611
- const { rawAudio, timeline } = await synthesizeFragments(fragments, defaultEspeakOptions)
612
-
613
- await playAudioWithTimelinePhones(rawAudio, timeline)
614
- }
615
-
616
600
  export async function testKirshenbaumPhonemization(text: string) {
617
601
  const ipaPhonemizedSentence = (await phonemizeSentence(text, 'en-us')).flatMap(clause => clause)
618
602
  const kirshenbaumPhonemizedSentence = (await phonemizeSentence(text, 'en-us', undefined, false)).flatMap(clause => clause)
@@ -2,10 +2,8 @@ import { SynthesisVoice } from '../api/API.js'
2
2
  import { decodeWaveToRawAudio } from '../audio/AudioUtilities.js'
3
3
  import { Logger } from '../utilities/Logger.js'
4
4
  import { getRandomHexString, logToStderr, resolveModuleMainPath } from '../utilities/Utilities.js'
5
- import { readFile, open, close, remove, ensureDir } from '../utilities/FileSystem.js'
6
- import path from 'node:path'
7
- import { escape } from 'html-escaper'
8
- import { getAppTempDir } from '../utilities/PathUtilities.js'
5
+ import { open, close, remove, ensureDir, readFileAsBinary, readFileAsUtf8 } from '../utilities/FileSystem.js'
6
+ import { getAppTempDir, joinPath } from '../utilities/PathUtilities.js'
9
7
 
10
8
  const log = logToStderr
11
9
 
@@ -25,8 +23,8 @@ export async function synthesize(text: string, voice: FliteVoiceName, voiceDir:
25
23
  const tempDir = getAppTempDir('flite')
26
24
  await ensureDir(tempDir)
27
25
 
28
- const tempAudioFilePath = path.join(tempDir, outFileName)
29
- const tempStdOutFilePath = path.join(tempDir, stdOutFileName)
26
+ const tempAudioFilePath = joinPath(tempDir, outFileName)
27
+ const tempStdOutFilePath = joinPath(tempDir, stdOutFileName)
30
28
 
31
29
  const stdOutFileFd = await open(tempStdOutFilePath, 'w+')
32
30
 
@@ -67,7 +65,7 @@ export async function synthesize(text: string, voice: FliteVoiceName, voiceDir:
67
65
  //'-ssml',
68
66
  '-psdur',
69
67
  ...optionArgs,
70
- //` ${escape(text)} `,
68
+ //` ${escapeHtml(text)} `,
71
69
  ` ${text} `,
72
70
  outFileName
73
71
  ],
@@ -100,8 +98,8 @@ export async function synthesize(text: string, voice: FliteVoiceName, voiceDir:
100
98
  throw new Error(`Flite failed with exit code ${exitCode}`)
101
99
  }
102
100
 
103
- const waveData = await readFile(tempAudioFilePath)
104
- const stdOutString = await readFile(tempStdOutFilePath, 'utf8')
101
+ const waveData = await readFileAsBinary(tempAudioFilePath)
102
+ const stdOutString = await readFileAsUtf8(tempStdOutFilePath)
105
103
 
106
104
  await cleanup()
107
105
 
@@ -118,7 +116,7 @@ async function getModuleObject() {
118
116
  if (!fliteModuleObject) {
119
117
  const fliteWasiPath = await resolveModuleMainPath('@echogarden/flite-wasi')
120
118
 
121
- fliteModuleObject = await WebAssembly.compile(await readFile(fliteWasiPath))
119
+ fliteModuleObject = await WebAssembly.compile(await readFileAsBinary(fliteWasiPath))
122
120
  }
123
121
 
124
122
  return fliteModuleObject
@@ -1,6 +1,7 @@
1
1
  import { request } from 'gaxios'
2
2
  import { Logger } from '../utilities/Logger.js'
3
3
  import { logToStderr } from '../utilities/Utilities.js'
4
+ import { decodeBase64 } from '../encodings/Base64.js'
4
5
 
5
6
  const log = logToStderr
6
7
 
@@ -15,7 +16,7 @@ export async function synthesize(
15
16
  ssml = false,
16
17
  audioEncoding: AudioEncoding = 'MP3_64_KBPS',
17
18
  sampleRate = 24000) {
18
-
19
+
19
20
  const logger = new Logger()
20
21
  logger.start('Request synthesis from Google Cloud')
21
22
 
@@ -75,7 +76,7 @@ export async function synthesize(
75
76
  }
76
77
 
77
78
  function parseResponseBody(responseBody: any) {
78
- const audioData = Buffer.from(responseBody.audioContent, 'base64')
79
+ const audioData = decodeBase64(responseBody.audioContent)
79
80
  const timepoints: timePoint[] = responseBody.timepoints
80
81
 
81
82
  return { audioData, timepoints }
@@ -1,12 +1,13 @@
1
1
  import { request } from 'gaxios'
2
2
  import { Phrase, splitToFragments } from '../nlp/Segmentation.js'
3
- import { concatBuffers, concatFloat32Arrays, logToStderr } from '../utilities/Utilities.js'
3
+ import { concatFloat32Arrays, concatUint8Arrays, logToStderr } from '../utilities/Utilities.js'
4
4
  import * as FFMpegTranscoder from '../codecs/FFMpegTranscoder.js'
5
5
  import { trimAudioEnd } from '../audio/AudioUtilities.js'
6
6
  import { Logger } from '../utilities/Logger.js'
7
7
  import { Timeline } from '../utilities/Timeline.js'
8
8
  import { getShortLanguageCode } from '../utilities/Locale.js'
9
9
  import { getChromeOnWindowsHeaders } from '../utilities/BrowserRequestHeaders.js'
10
+ import { decodeBase64 } from '../encodings/Base64.js'
10
11
 
11
12
  const log = logToStderr
12
13
 
@@ -113,18 +114,18 @@ export async function synthesizeShortText(text: string, languageCode = 'en', tld
113
114
 
114
115
  //log(response.data)
115
116
 
116
- const audioChunks: Buffer[] = []
117
+ const audioChunks: Uint8Array[] = []
117
118
 
118
119
  for (const line of response.data.split(/\r?\n/)) {
119
120
  const match = line.match(/"jQ1olc","\[\\"(.*)\\"]/)
120
121
 
121
122
  if (match != null) {
122
123
  const base64AudioChunk = match[1]
123
- audioChunks.push(Buffer.from(base64AudioChunk, 'base64'))
124
+ audioChunks.push(decodeBase64(base64AudioChunk))
124
125
  }
125
126
  }
126
127
 
127
- const resultMp3Stream = concatBuffers(audioChunks)
128
+ const resultMp3Stream = concatUint8Arrays(audioChunks)
128
129
 
129
130
  return resultMp3Stream
130
131
  }
@@ -1,17 +1,15 @@
1
1
  import { request } from 'gaxios'
2
2
  import WebSocket from 'ws'
3
3
 
4
- import { escape } from 'html-escaper'
5
-
6
- import splitBuffer from 'buffer-split'
7
-
8
4
  import * as AzureCognitiveServicesTTS from './AzureCognitiveServicesTTS.js'
9
5
  import * as FFMpegTranscoder from '../codecs/FFMpegTranscoder.js'
10
6
  import { Logger } from '../utilities/Logger.js'
11
7
  import { OpenPromise } from '../utilities/OpenPromise.js'
12
- import { concatBuffers, getRandomHexString, logToStderr } from '../utilities/Utilities.js'
8
+ import { concatUint8Arrays, getRandomHexString, logToStderr } from '../utilities/Utilities.js'
13
9
  import { RawAudio, getEmptyRawAudio, getRawAudioDuration } from '../audio/AudioUtilities.js'
14
10
  import { Timer } from '../utilities/Timer.js'
11
+ import { decodeUtf8, encodeUtf8 } from '../encodings/Utf8.js'
12
+ import { escapeHtml } from '../encodings/HtmlEscape.js'
15
13
 
16
14
  const traceEnabled = false
17
15
 
@@ -50,7 +48,7 @@ export async function synthesize(
50
48
  return { rawAudio, timeline }
51
49
  }
52
50
 
53
- type SynthesisRequestResult = { audioData: Buffer, events: any[] }
51
+ type SynthesisRequestResult = { audioData: Uint8Array, events: any[] }
54
52
 
55
53
  async function requestSynthesis(
56
54
  text: string,
@@ -104,11 +102,11 @@ async function requestSynthesis(
104
102
  throw e
105
103
  }
106
104
 
107
- const receivedBinaryMessages: Buffer[] = []
105
+ const receivedBinaryMessages: Uint8Array[] = []
108
106
  const receivedEventMessages: any[] = []
109
- const audioChunks: Buffer[] = []
107
+ const audioChunks: Uint8Array[] = []
110
108
 
111
- const onMessage = (messageData: Buffer, isBinary: boolean) => {
109
+ const onMessage = (messageData: Uint8Array, isBinary: boolean) => {
112
110
  lastReceievedMessageTime = Timer.currentTime
113
111
 
114
112
  if (isBinary) {
@@ -124,11 +122,11 @@ async function requestSynthesis(
124
122
  log(header)
125
123
 
126
124
  receivedBinaryMessages.push(messageData)
127
- receivedBinaryMessages.push(Buffer.from('\n\n'))
125
+ receivedBinaryMessages.push(encodeUtf8('\n\n'))
128
126
 
129
127
  audioChunks.push(audioChunk)
130
128
  } else {
131
- const message = messageData.toString('utf8')
129
+ const message = decodeUtf8(messageData)
132
130
  const [header, content] = parseTextMessage(message)
133
131
 
134
132
  if (header['X-RequestId'] != requestId) {
@@ -147,7 +145,7 @@ async function requestSynthesis(
147
145
  receivedEventMessages.push(content['Metadata'][0])
148
146
  }
149
147
  else if (header['Path'] == 'turn.end') {
150
- const result: SynthesisRequestResult = { audioData: concatBuffers(audioChunks), events: receivedEventMessages }
148
+ const result: SynthesisRequestResult = { audioData: concatUint8Arrays(audioChunks), events: receivedEventMessages }
151
149
 
152
150
  removeWebSocketHandlers()
153
151
 
@@ -167,7 +165,7 @@ async function requestSynthesis(
167
165
  }
168
166
  }
169
167
 
170
- const onClose = async (code: number, reason: Buffer) => {
168
+ const onClose = async (code: number, reason: Uint8Array) => {
171
169
  log('WebSocket closed.')
172
170
  log(code)
173
171
  log(reason.toString())
@@ -193,7 +191,7 @@ async function requestSynthesis(
193
191
  `<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'>` +
194
192
  `<voice name='${voice}'>` +
195
193
  `<prosody pitch='${ssmlPitchString}' rate='${ssmlRateString}' volume='${ssmlVolumeString}'>` +
196
- escape(text) +
194
+ escapeHtml(text) +
197
195
  `</prosody>` +
198
196
  `</voice>` +
199
197
  `</speak>`
@@ -282,7 +280,7 @@ export async function initializeWebsocketConnection(trustedClientToken: string)
282
280
  requestOpenPromise.resolve(webSocket)
283
281
  }
284
282
 
285
- const onClose = (code: number, reason: Buffer) => {
283
+ const onClose = (code: number, reason: Uint8Array) => {
286
284
  log('WebSocket closed.')
287
285
  log(code)
288
286
  log(reason.toString())
@@ -352,11 +350,44 @@ function parseTextMessage(message: string) {
352
350
  return [parseHeaderString(headerString), JSON.parse(content)]
353
351
  }
354
352
 
355
- function parseBinaryMessage(message: Buffer) {
356
- const audioChunk = splitBuffer(message, Buffer.from('Path:audio\r\n'))[1]
353
+ function parseBinaryMessage(message: Uint8Array) {
354
+ const patternAsBytes = encodeUtf8('Path:audio\r\n')
355
+ const indexOfPattern = indexOfByteSubsequence(message, patternAsBytes)
356
+
357
+ if (indexOfPattern === -1) {
358
+ throw new Error(`Couldn't find separator pattern in Edge TTS binary message`)
359
+ }
360
+
361
+ const audioChunk = message.slice(indexOfPattern + patternAsBytes.length)
362
+
357
363
  const headerBuffer = message.subarray(2, message.length - audioChunk.length)
358
- const headerString = headerBuffer.toString('utf8').trim()
364
+ const headerString = decodeUtf8(headerBuffer).trim()
359
365
 
360
366
  return [parseHeaderString(headerString), audioChunk]
361
367
  }
362
368
 
369
+ function indexOfByteSubsequence(sequence: Uint8Array, subsequence: Uint8Array) {
370
+ function tryMatchAtOffset(offset: number) {
371
+ if (offset + subsequence.length > sequence.length) {
372
+ return false
373
+ }
374
+
375
+ for (let i = 0; i < subsequence.length; i++) {
376
+ if (sequence[offset + i] !== subsequence[i]) {
377
+ return false
378
+ }
379
+ }
380
+
381
+ return true
382
+ }
383
+
384
+ for (let offset = 0; offset < sequence.length; offset++) {
385
+ const matched = tryMatchAtOffset(offset)
386
+
387
+ if (matched) {
388
+ return offset
389
+ }
390
+ }
391
+
392
+ return -1
393
+ }
@@ -107,7 +107,7 @@ export function synthesize(text: string, voiceName: string, rate = 0, useSpeechP
107
107
  EndStream: (streamId: number, streamPos: number) => {
108
108
  clearInterval(dispatchMessagesInterval)
109
109
 
110
- const audioData = Buffer.from(sapiOutputStream.GetData())
110
+ const audioData = new Uint8Array(sapiOutputStream.GetData())
111
111
  const audioChannels = decodeToChannels(audioData, 1, 16, SampleFormat.PCM)
112
112
 
113
113
  WinAX.release(sapiOutputStream)
@@ -92,7 +92,7 @@ export async function synthesizeFragment(text: string, voice: string) {
92
92
  const audioUrl = responseObject.speak_url
93
93
  const audioUrlResponse = await request<ArrayBuffer>({ url: audioUrl, responseType: 'arraybuffer' })
94
94
 
95
- return Buffer.from(audioUrlResponse.data)
95
+ return new Uint8Array(audioUrlResponse.data)
96
96
  }
97
97
 
98
98
  export const voiceList: SynthesisVoice[] = [
@@ -5,8 +5,8 @@ import { bandwidthToQFactor } from '../dsp/BiquadFilter.js'
5
5
  import { Logger } from '../utilities/Logger.js'
6
6
  import { WasmMemoryManager } from '../utilities/WasmMemoryManager.js'
7
7
  import { RawAudio } from '../audio/AudioUtilities.js'
8
- import { readFile } from '../utilities/FileSystem.js'
9
- import { concatBuffers } from '../utilities/Utilities.js'
8
+ import { readFileAsBinary } from '../utilities/FileSystem.js'
9
+ import { concatUint8Arrays } from '../utilities/Utilities.js'
10
10
 
11
11
  let svoxPicoInstance: any
12
12
 
@@ -52,7 +52,7 @@ export async function synthesize(text: string, textAnalysisFilePath: string, sig
52
52
  async function loadResource(localFilePath: string) {
53
53
  const virtualFilePath = '.' + localFilePath.substring(localFilePath.lastIndexOf('/'))
54
54
 
55
- const fileData = await readFile(localFilePath)
55
+ const fileData = await readFileAsBinary(localFilePath)
56
56
  m.FS.writeFile(virtualFilePath, fileData)
57
57
 
58
58
  const virtualFilePathRef = wasmMemory.allocNullTerminatedUtf8String(virtualFilePath)
@@ -109,7 +109,7 @@ export async function synthesize(text: string, textAnalysisFilePath: string, sig
109
109
 
110
110
  const bytesWrittenRef = wasmMemory.allocInt32()
111
111
 
112
- const audioParts: Buffer[] = []
112
+ const audioParts: Uint8Array[] = []
113
113
 
114
114
  for (let textByteOffset = 0; textByteOffset < textRef.length;) {
115
115
  bytesWrittenRef.value = 0
@@ -124,10 +124,10 @@ export async function synthesize(text: string, textAnalysisFilePath: string, sig
124
124
  textByteOffset += bytesWritten
125
125
  }
126
126
 
127
- const audioData = concatBuffers(audioParts)
127
+ const audioData = concatUint8Arrays(audioParts)
128
128
 
129
129
  function readAudioDataFromEngine() {
130
- const outBuffers: Buffer[] = []
130
+ const outBuffers: Uint8Array[] = []
131
131
 
132
132
  const outBufferLength = 16384
133
133
  const outBufferRef = wasmMemory.allocUint8Array(outBufferLength)
@@ -148,11 +148,11 @@ export async function synthesize(text: string, textAnalysisFilePath: string, sig
148
148
  }
149
149
 
150
150
  if (outByteCount > 0) {
151
- outBuffers.push(Buffer.from(outBufferRef.slice(0, outByteCount)))
151
+ outBuffers.push(outBufferRef.slice(0, outByteCount) as Uint8Array)
152
152
  }
153
153
  }
154
154
 
155
- return concatBuffers(outBuffers)
155
+ return concatUint8Arrays(outBuffers)
156
156
  }
157
157
 
158
158
  dispose()
@@ -5,9 +5,9 @@ import { RawAudio, getEmptyRawAudio, getRawAudioDuration } from '../audio/AudioU
5
5
  import { Lexicon } from '../nlp/Lexicon.js'
6
6
  import { Timeline } from '../utilities/Timeline.js'
7
7
  import { readAndParseJsonFile, readdir } from '../utilities/FileSystem.js'
8
- import path from 'node:path'
9
8
  import { EspeakOptions, defaultEspeakOptions } from '../synthesis/EspeakTTS.js'
10
9
  import { OnnxExecutionProvider, getOnnxSessionOptions } from '../utilities/OnnxUtilities.js'
10
+ import { joinPath } from '../utilities/PathUtilities.js'
11
11
 
12
12
  const cachedInstanceLookup = new Map<string, VitsTTS>()
13
13
 
@@ -196,7 +196,7 @@ export class VitsTTS {
196
196
  throw new Error(`Couldn't file any ONNX model file in ${this.modelPath}`)
197
197
  }
198
198
 
199
- const onnxModelFilepath = path.join(this.modelPath, onnxModelFilename)
199
+ const onnxModelFilepath = joinPath(this.modelPath, onnxModelFilename)
200
200
 
201
201
  const onnxSessionOptions = getOnnxSessionOptions({ executionProviders: this.executionProviders })
202
202
 
package/src/tests/Test.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { createAlignmentReferenceUsingEspeakForFragments } from '../alignment/SpeechAlignment.js'
2
- import { setVoice } from '../synthesis/EspeakTTS.js'
3
- import { concatBuffers, logToStderr, setupProgramTerminationListeners } from '../utilities/Utilities.js'
1
+ import { logToStderr, setupProgramTerminationListeners } from '../utilities/Utilities.js'
4
2
 
5
3
  const log = logToStderr
6
4
 
@@ -9,61 +7,4 @@ setupProgramTerminationListeners()
9
7
  //process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
10
8
  //process.env.http_proxy = 'http://localhost:8080'
11
9
 
12
- if (false) {
13
- for (let i = 0; i < 1000000; i++) {
14
- if (i % 1000 === 0) {
15
- console.log(`Iteration ${i}`)
16
- }
17
-
18
- await setVoice('en')
19
- }
20
- }
21
-
22
- if (false) {
23
- const fragments: string[] = []
24
-
25
- for (let i = 0; i < 30000; i++) {
26
- fragments.push(`hello`, `${i}`)
27
- }
28
-
29
- await createAlignmentReferenceUsingEspeakForFragments(fragments, {
30
- voice: "gmw/en-US",
31
- ssml: false,
32
- rate: 150,
33
- pitch: 50,
34
- pitchRange: 50,
35
- useKlatt: false,
36
- insertSeparators: true,
37
- })
38
- }
39
-
40
- if (false) {
41
- const largeBuffer = Buffer.alloc(2 ** 33 + 1000)
42
-
43
- largeBuffer.fill(111)
44
-
45
- //const result = Buffer.concat([largeBuffer])
46
- const result = concatBuffers([largeBuffer])
47
-
48
- console.log(result)
49
-
50
- console.log(result[result.length - 1])
51
-
52
- const x = 0
53
- }
54
-
55
- if (false) {
56
- const largeBuffer = Buffer.alloc(2 ** 33) // 8 GiB buffer
57
- const { promisify } = await import('node:util')
58
- const { default: gracefulFS } = await import('graceful-fs')
59
- const gracefulFSWriteFile = promisify(gracefulFS.writeFile)
60
- await gracefulFSWriteFile('out/test1', largeBuffer)
61
- }
62
-
63
- if (true) {
64
- const largeBuffer = Buffer.alloc(2 ** 34) // 16 GiB buffer
65
- const { writeFile } = await import('fs/promises')
66
- await writeFile('out/test1', largeBuffer)
67
- }
68
-
69
10
  process.exit(0)
@@ -1,8 +1,8 @@
1
- import path from 'path'
2
1
  import { languageCodeToName } from '../utilities/Locale.js'
3
2
  import { OpenPromise } from '../utilities/OpenPromise.js'
4
3
  import { resolveModuleMainPath, roundToDigits } from '../utilities/Utilities.js'
5
4
  import { LanguageDetectionResults } from '../api/LanguageDetectionCommon.js'
5
+ import { getDirName, joinPath } from '../utilities/PathUtilities.js'
6
6
 
7
7
  let fastTextLanguageDetectionModel: any
8
8
 
@@ -41,7 +41,7 @@ async function loadLanguageDetectionModel() {
41
41
  const fastText = new FastText()
42
42
 
43
43
  const moduleMainPath = await resolveModuleMainPath('@echogarden/fasttext-wasm')
44
- const modelPath = path.join(path.dirname(moduleMainPath), 'lid.176.ftz')
44
+ const modelPath = joinPath(getDirName(moduleMainPath), 'lid.176.ftz')
45
45
 
46
46
  const model = await fastText.loadModel(modelPath)
47
47
 
@@ -197,7 +197,7 @@ export async function translateText_MobileWeb(
197
197
  if (match) {
198
198
  const { htmlToText } = await import('html-to-text')
199
199
 
200
- translatedText = htmlToText(match[0], { wordwrap: Infinity }).trim()
200
+ translatedText = htmlToText(match[0], { wordwrap: false }).trim()
201
201
  } else {
202
202
  translatedText = ''
203
203
  }
@@ -21,11 +21,6 @@ declare module 'cldr-segmentation' {
21
21
  }
22
22
  }
23
23
 
24
- declare module 'html-escaper' {
25
- export function escape(str: string): string
26
- export function unescape(str: string): string
27
- }
28
-
29
24
  declare module 'sam-js'
30
25
  declare module 'winax'
31
26
 
@@ -55,7 +50,6 @@ declare module '@echogarden/rubberband-wasm'
55
50
  declare module '@echogarden/rnnoise-wasm'
56
51
  declare module '@echogarden/fvad-wasm'
57
52
  declare module '@echogarden/sonic-wasm'
58
- declare module '@echogarden/kissfft-wasm'
59
53
  declare module '@echogarden/pffft-wasm'
60
54
  declare module '@echogarden/pffft-wasm/simd'
61
55
  declare module '@echogarden/speex-resampler-wasm'
@@ -92,9 +86,7 @@ declare module 'onnxruntime-node' {
92
86
 
93
87
  type RunOptions = InferenceSession.RunOptions
94
88
 
95
- /**
96
- * Binding exports a simple synchronized inference session object wrap.
97
- */
89
+ // Binding exports a simple synchronized inference session object wrap.
98
90
  export namespace Binding {
99
91
  interface InferenceSession {
100
92
  loadModel(modelPath: string, options: SessionOptions): void
@@ -115,5 +107,5 @@ declare module 'onnxruntime-node' {
115
107
  }
116
108
 
117
109
  // From version.d.ts
118
- export const version = '1.16.1'
110
+ export const version = '1.20.0'
119
111
  }
@@ -0,0 +1,5 @@
1
+ export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array
2
+
3
+ export interface TypedArrayConstructor<T extends TypedArray> {
4
+ new(length: number): T
5
+ }