echogarden 0.11.12 → 0.11.13

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 (122) hide show
  1. package/data/schemas/options.json +16 -0
  2. package/dist/api/Alignment.js +2 -2
  3. package/dist/api/Alignment.js.map +1 -1
  4. package/dist/api/Recognition.js +2 -2
  5. package/dist/api/Recognition.js.map +1 -1
  6. package/dist/api/Synthesis.js +5 -4
  7. package/dist/api/Synthesis.js.map +1 -1
  8. package/dist/api/Translation.js +2 -2
  9. package/dist/api/Translation.js.map +1 -1
  10. package/dist/audio/AudioUtilities.d.ts +1 -0
  11. package/dist/audio/AudioUtilities.js +25 -7
  12. package/dist/audio/AudioUtilities.js.map +1 -1
  13. package/dist/cli/CLI.js +2 -2
  14. package/dist/cli/CLI.js.map +1 -1
  15. package/dist/recognition/WhisperSTT.js +2 -2
  16. package/dist/recognition/WhisperSTT.js.map +1 -1
  17. package/dist/subtitles/Subtitles.d.ts +10 -7
  18. package/dist/subtitles/Subtitles.js +268 -207
  19. package/dist/subtitles/Subtitles.js.map +1 -1
  20. package/docs/Options.md +4 -2
  21. package/package.json +7 -6
  22. package/src/alignment/DTWMfccSequenceAlignment.ts +43 -0
  23. package/src/alignment/DTWSequenceAlignment.ts +121 -0
  24. package/src/alignment/DTWSequenceAlignmentWindowed.ts +210 -0
  25. package/src/alignment/LevenshteinSequenceAlignment.ts +126 -0
  26. package/src/alignment/SpeechAlignment.ts +488 -0
  27. package/src/api/API.ts +12 -0
  28. package/src/api/APIOptions.ts +15 -0
  29. package/src/api/Alignment.ts +329 -0
  30. package/src/api/Common.ts +16 -0
  31. package/src/api/Denoising.ts +120 -0
  32. package/src/api/LanguageDetection.ts +286 -0
  33. package/src/api/Recognition.ts +344 -0
  34. package/src/api/Synthesis.ts +1735 -0
  35. package/src/api/Translation.ts +143 -0
  36. package/src/api/Vad.ts +172 -0
  37. package/src/audio/AudioBufferConversion.ts +248 -0
  38. package/src/audio/AudioPlayer.ts +358 -0
  39. package/src/audio/AudioRecorder.ts +91 -0
  40. package/src/audio/AudioUtilities.ts +392 -0
  41. package/src/audio/SoxPath.ts +24 -0
  42. package/src/cli/CLI.ts +1360 -0
  43. package/src/cli/CLIConfigFile.ts +91 -0
  44. package/src/cli/CLILauncher.ts +26 -0
  45. package/src/cli/CLIOptionsSchema.ts +54 -0
  46. package/src/cli/CLIParser.ts +41 -0
  47. package/src/cli/CLIStarter.ts +40 -0
  48. package/src/codecs/FFMpegTranscoder.ts +214 -0
  49. package/src/codecs/TIMITCodec.ts +17 -0
  50. package/src/codecs/WaveCodec.ts +260 -0
  51. package/src/denoising/RNNoise.ts +95 -0
  52. package/src/dsp/BiquadFilter.ts +488 -0
  53. package/src/dsp/FFT.ts +187 -0
  54. package/src/dsp/MFCC.ts +227 -0
  55. package/src/dsp/MelSpectogram.ts +145 -0
  56. package/src/dsp/Rubberband.ts +249 -0
  57. package/src/dsp/Sonic.ts +59 -0
  58. package/src/dsp/SpeexResampler.ts +79 -0
  59. package/src/math/VectorMath.ts +812 -0
  60. package/src/nlp/ChineseSegmentation.ts +68 -0
  61. package/src/nlp/CompromiseNLP.ts +113 -0
  62. package/src/nlp/EspeakPhonemizer.ts +168 -0
  63. package/src/nlp/IPA.ts +139 -0
  64. package/src/nlp/JapaneseSegmentation.ts +53 -0
  65. package/src/nlp/Lexicon.ts +119 -0
  66. package/src/nlp/PhoneConversion.ts +508 -0
  67. package/src/nlp/Segmentation.ts +237 -0
  68. package/src/nlp/TextNormalizer.ts +160 -0
  69. package/src/recognition/AmazonTranscribeSTT.ts +112 -0
  70. package/src/recognition/AzureCognitiveServicesSTT.ts +76 -0
  71. package/src/recognition/GoogleCloudSTT.ts +92 -0
  72. package/src/recognition/SileroSTT.ts +173 -0
  73. package/src/recognition/VoskSTT.ts +112 -0
  74. package/src/recognition/WhisperSTT.ts +1518 -0
  75. package/src/server/Client.ts +297 -0
  76. package/src/server/Server.ts +178 -0
  77. package/src/server/ServerStarter.ts +12 -0
  78. package/src/server/Worker.ts +400 -0
  79. package/src/server/WorkerStarter.ts +38 -0
  80. package/src/speech-language-detection/SileroLanguageDetection.ts +105 -0
  81. package/src/subtitles/Subtitles.ts +478 -0
  82. package/src/synthesis/AwsPollyTTS.ts +78 -0
  83. package/src/synthesis/AzureCognitiveServicesTTS.ts +146 -0
  84. package/src/synthesis/CoquiServerTTS.ts +29 -0
  85. package/src/synthesis/ElevenLabsTTS.ts +104 -0
  86. package/src/synthesis/EspeakTTS.ts +552 -0
  87. package/src/synthesis/FliteTTS.ts +387 -0
  88. package/src/synthesis/GoogleCloudTTS.ts +112 -0
  89. package/src/synthesis/GoogleTranslateTTS.ts +210 -0
  90. package/src/synthesis/MicrosoftEdgeTTS.ts +298 -0
  91. package/src/synthesis/SamTTS.ts +30 -0
  92. package/src/synthesis/SapiTTS.ts +222 -0
  93. package/src/synthesis/StreamlabsPollyTTS.ts +114 -0
  94. package/src/synthesis/SvoxPicoTTS.ts +318 -0
  95. package/src/synthesis/VitsTTS.ts +734 -0
  96. package/src/tests/Test.ts +24 -0
  97. package/src/text-language-detection/FastTextLanguageDetection.ts +53 -0
  98. package/src/text-language-detection/TinyLDLanguageDetection.ts +16 -0
  99. package/src/typings/Fillers.d.ts +41 -0
  100. package/src/utilities/BinaryArrayConversion.ts +159 -0
  101. package/src/utilities/Compression.ts +91 -0
  102. package/src/utilities/FileDownloader.ts +201 -0
  103. package/src/utilities/FileSystem.ts +265 -0
  104. package/src/utilities/Hashing.ts +230 -0
  105. package/src/utilities/Locale.ts +119 -0
  106. package/src/utilities/Logger.ts +72 -0
  107. package/src/utilities/NdArrayUtilities.ts +31 -0
  108. package/src/utilities/ObjectUtilities.ts +169 -0
  109. package/src/utilities/OpenPromise.ts +13 -0
  110. package/src/utilities/PackageManager.ts +97 -0
  111. package/src/utilities/Queue.ts +17 -0
  112. package/src/utilities/RandomGenerator.ts +237 -0
  113. package/src/utilities/SignalChannel.ts +22 -0
  114. package/src/utilities/TarballMaker.ts +68 -0
  115. package/src/utilities/Timeline.ts +231 -0
  116. package/src/utilities/Timer.ts +93 -0
  117. package/src/utilities/Utilities.ts +574 -0
  118. package/src/utilities/WasmMemoryManager.ts +516 -0
  119. package/src/utilities/WebReader.ts +55 -0
  120. package/src/utilities/WikipediaReader.ts +41 -0
  121. package/src/voice-activity-detection/SileroVAD.ts +86 -0
  122. package/src/voice-activity-detection/WebRtcVAD.ts +76 -0
@@ -0,0 +1,265 @@
1
+ import * as fsExtra from 'fs-extra/esm'
2
+ import gracefulFS from 'graceful-fs'
3
+ import * as os from 'node:os'
4
+
5
+ import path from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+ import { promisify } from 'node:util'
8
+ import { OpenPromise } from './OpenPromise.js'
9
+ import { getRandomHexString, sha256AsHex } from './Utilities.js'
10
+ import { appName } from '../api/Common.js'
11
+
12
+ export const readFile = promisify(gracefulFS.readFile)
13
+ //export const writeFile = promisify(gracefulFS.writeFile)
14
+ export const readdir = promisify(gracefulFS.readdir)
15
+ export const stat = promisify(gracefulFS.stat)
16
+ export const open = promisify(gracefulFS.open)
17
+ export const close = promisify(gracefulFS.close)
18
+ export const chmod = promisify(gracefulFS.chmod)
19
+ export const copyFile = promisify(gracefulFS.copyFile)
20
+ export const access = promisify(gracefulFS.access)
21
+
22
+
23
+ export const createReadStream = gracefulFS.createReadStream
24
+ export const createWriteStream = gracefulFS.createWriteStream
25
+ export const existsSync = gracefulFS.existsSync
26
+
27
+ export const remove = fsExtra.remove
28
+ export const copy = fsExtra.copy
29
+ export const outputFile = fsExtra.outputFile
30
+
31
+ export async function readDirRecursive(dir: string, fileFilter?: (filePath: string) => boolean) {
32
+ if (!(await stat(dir)).isDirectory()) {
33
+ throw new Error(`'${dir}' is not a directory`)
34
+ }
35
+
36
+ const filenamesInDir = await readdir(dir)
37
+ const filesInDir = filenamesInDir.map(filename => path.join(dir, filename))
38
+
39
+ const result: string[] = []
40
+ const subDirectories: string[] = []
41
+
42
+ for (const filePath of filesInDir) {
43
+ if ((await stat(filePath)).isDirectory()) {
44
+ subDirectories.push(filePath)
45
+ } else {
46
+ if (fileFilter && !fileFilter(filePath)) {
47
+ continue
48
+ }
49
+
50
+ result.push(filePath)
51
+ }
52
+ }
53
+
54
+ for (const subDirectory of subDirectories) {
55
+ const filesInSubdirectory = await readDirRecursive(subDirectory, fileFilter)
56
+ result.push(...filesInSubdirectory)
57
+ }
58
+
59
+ return result
60
+ }
61
+
62
+ export async function isFileIsUpToDate(filePath: string, timeRangeSeconds: number) {
63
+ const fileUpdateTime = (await stat(filePath)).mtime.valueOf()
64
+
65
+ const currentTime = (new Date()).valueOf()
66
+
67
+ const differenceInMilliseconds = currentTime - fileUpdateTime
68
+
69
+ const differenceInSeconds = differenceInMilliseconds / 1000
70
+
71
+ return differenceInSeconds <= timeRangeSeconds
72
+ }
73
+
74
+ export function getModuleRootDir() {
75
+ const currentScriptDir = path.dirname(fileURLToPath(import.meta.url))
76
+ return path.resolve(currentScriptDir, '..', '..')
77
+ }
78
+
79
+ export function resolveToModuleRootDir(relativePath: string) {
80
+ return path.resolve(getModuleRootDir(), relativePath)
81
+ }
82
+
83
+ export function getLowercaseFileExtension(filename: string) {
84
+ const fileExtensionIndex = filename.lastIndexOf(".")
85
+
86
+ if (fileExtensionIndex == -1) {
87
+ return ""
88
+ }
89
+
90
+ return filename.substring(fileExtensionIndex + 1).toLowerCase()
91
+ }
92
+
93
+ export async function computeFileSha256Hex(filePath: string) {
94
+ const resultOpenPromise = new OpenPromise<string>()
95
+
96
+ const crypto = await import('crypto')
97
+ const hash = crypto.createHash('sha256')
98
+
99
+ const readStream = createReadStream(filePath)
100
+
101
+ readStream.on('data', data => hash.update(data))
102
+ readStream.on('error', error => resultOpenPromise.reject(error))
103
+ readStream.on('end', () => resultOpenPromise.resolve(hash.digest('hex')))
104
+
105
+ return resultOpenPromise.promise
106
+ }
107
+
108
+ export async function readAndParseJsonFile(jsonFilePath: string, useJson5 = false) {
109
+ const fileContent = await readFile(jsonFilePath, { encoding: "utf-8" })
110
+
111
+ if (useJson5) {
112
+ const { default: JSON5 } = await import('json5')
113
+
114
+ return JSON5.parse(fileContent)
115
+ } else {
116
+ return JSON.parse(fileContent)
117
+ }
118
+ }
119
+
120
+ export async function writeFile(filePath: string, data: string | NodeJS.ArrayBufferView, options?: fsExtra.WriteFileOptions) {
121
+ return outputFile(filePath, data, options)
122
+ }
123
+
124
+ export async function writeFileSafe(filePath: string, data: string | NodeJS.ArrayBufferView, options?: fsExtra.WriteFileOptions) {
125
+ const tempDir = getAppTempDir(appName)
126
+ const tempFilePath = path.join(tempDir, `${getRandomHexString(16)}.partial`)
127
+
128
+ await writeFile(tempFilePath, data, options)
129
+
130
+ await move(tempFilePath, filePath)
131
+ }
132
+
133
+ export function getAppTempDir(appName: string) {
134
+ let tempDir: string
135
+
136
+ const platform = process.platform
137
+ const homeDir = os.homedir()
138
+
139
+ if (platform == "win32") {
140
+ tempDir = path.join(homeDir, "AppData", "Local", "Temp", appName)
141
+ } else if (platform == "darwin") {
142
+ tempDir = path.join(homeDir, "Library", "Caches", appName)
143
+ } else if (platform == "linux") {
144
+ tempDir = path.join(homeDir, ".cache", appName)
145
+ } else {
146
+ throw new Error(`Unsupport platform ${platform}`)
147
+ }
148
+
149
+ return tempDir
150
+ }
151
+
152
+ export function getAppDataDir(appName: string) {
153
+ let dataDir: string
154
+
155
+ const platform = process.platform
156
+ const homeDir = os.homedir()
157
+
158
+ if (platform == "win32") {
159
+ dataDir = path.join(homeDir, "AppData", "Local", appName)
160
+ } else if (platform == "darwin") {
161
+ dataDir = path.join(homeDir, "Library", "Application Support", appName)
162
+ } else if (platform == "linux") {
163
+ dataDir = path.join(homeDir, ".local", "share", appName)
164
+ } else {
165
+ throw new Error(`Unsupport platform ${platform}`)
166
+ }
167
+
168
+ return dataDir
169
+ }
170
+
171
+ export async function chmodRecursive(rootPath: string, newMode: number) {
172
+ const rootPathStat = await stat(rootPath)
173
+
174
+ await chmod(rootPath, newMode)
175
+
176
+ if (rootPathStat.isDirectory()) {
177
+ const fileList = await readdir(rootPath)
178
+
179
+ for (const filename of fileList) {
180
+ const filePath = path.join(rootPath, filename)
181
+
182
+ await chmodRecursive(filePath, newMode)
183
+ }
184
+ }
185
+ }
186
+
187
+ export async function ensureDir(dirPath: string) {
188
+ dirPath = path.normalize(dirPath)
189
+
190
+ if (existsSync(dirPath)) {
191
+ const dirStats = await stat(dirPath)
192
+
193
+ if (!dirStats.isDirectory()) {
194
+ throw new Error(`The path '${dirPath}' exists but is not a directory.`)
195
+ }
196
+ } else {
197
+ return fsExtra.ensureDir(dirPath)
198
+ }
199
+ }
200
+
201
+ export async function move(source: string, dest: string) {
202
+ source = path.normalize(source)
203
+ dest = path.normalize(dest)
204
+
205
+ if (existsSync(dest)) {
206
+ const destPathExistsAndIsWritable = await existsAndIsWritable(dest)
207
+
208
+ if (!destPathExistsAndIsWritable) {
209
+ throw new Error(`The destination path '${dest}' exists but is not writable. There may be a permissions or locking issue.`)
210
+ }
211
+ } else {
212
+ const destDir = path.parse(dest).dir
213
+ const destDirIsWritable = await testDirectoryIsWritable(destDir)
214
+
215
+ if (!destDirIsWritable) {
216
+ throw new Error(`The directory ${destDir} is not writable. There may be a permissions issue.`)
217
+ }
218
+ }
219
+
220
+ return fsExtra.move(source, dest, { overwrite: true })
221
+ }
222
+
223
+ export async function existsAndIsWritable(targetPath: string) {
224
+ try {
225
+ await access(targetPath, gracefulFS.constants.W_OK);
226
+ } catch {
227
+ return false
228
+ }
229
+
230
+ return true
231
+ }
232
+
233
+ export async function testDirectoryIsWritable(dir: string) {
234
+ const testFileName = path.join(dir, getRandomHexString(16))
235
+
236
+ try {
237
+ await fsExtra.createFile(testFileName)
238
+ await remove(testFileName)
239
+ } catch (e) {
240
+ return false
241
+ }
242
+
243
+ return true
244
+ }
245
+
246
+ export async function copyFileAlternative(source: string, dest: string) {
247
+ return new Promise<void>((resolve, reject) => {
248
+ const readStream = createReadStream(source)
249
+ const writeStream = createWriteStream(dest)
250
+
251
+ readStream.on('error', (err: any) => {
252
+ reject(err)
253
+ })
254
+
255
+ writeStream.on('error', (err: any) => {
256
+ reject(err)
257
+ })
258
+
259
+ readStream.pipe(writeStream)
260
+
261
+ readStream.on('end', () => {
262
+ resolve()
263
+ })
264
+ })
265
+ }
@@ -0,0 +1,230 @@
1
+ export function knuthMultiplicative(bytes: Buffer) {
2
+ let hash = 0
3
+
4
+ for (const byte of bytes) {
5
+ hash += Math.imul(byte, 2654435761)
6
+ }
7
+
8
+ return hash
9
+ }
10
+
11
+ export function xorShift32Hash(bytes: Buffer) {
12
+ let s = 0
13
+
14
+ for (const byte of bytes) {
15
+ s += byte
16
+
17
+ s ^= s << 13
18
+ s ^= s >> 17
19
+ s ^= s << 5
20
+ }
21
+
22
+ return s
23
+ }
24
+
25
+ export function jenkinsOneAtATime(bytes: Buffer) {
26
+ let hash = 0
27
+
28
+ for (const byte of bytes) {
29
+ hash += byte
30
+ hash += hash << 10
31
+ hash ^= hash >> 6
32
+ }
33
+
34
+ hash += hash << 3
35
+ hash ^= hash >> 11
36
+ hash += hash << 15
37
+
38
+ return hash >>> 0
39
+ }
40
+
41
+ export function FNV1a(bytes: Buffer) {
42
+ let hval = 2166136261 | 0
43
+
44
+ for (const byte of bytes) {
45
+ hval = Math.imul(hval ^ byte, 16777619)
46
+ }
47
+
48
+ return hval >>> 0
49
+ }
50
+
51
+ export function superFastHash(bytes: Buffer) {
52
+ let hash = bytes.length, tmp, p = 0
53
+ const len = bytes.length >>> 2
54
+
55
+ for (let i = 0; i < len; i++) {
56
+ hash += bytes[p] | bytes[p + 1] << 8
57
+ tmp = ((bytes[p + 2] | bytes[p + 3] << 8) << 11) ^ hash
58
+ hash = (hash << 16) ^ tmp
59
+ hash += hash >>> 11
60
+ p += 4
61
+ }
62
+
63
+ switch (bytes.length & 3) {
64
+ case 3:
65
+ hash += bytes[p] | bytes[p + 1] << 8
66
+ hash ^= hash << 16
67
+ hash ^= bytes[p + 2] << 18
68
+ hash += hash >>> 11
69
+ break
70
+ case 2:
71
+ hash += bytes[p] | bytes[p + 1] << 8
72
+ hash ^= hash << 11
73
+ hash += hash >>> 17
74
+ break
75
+ case 1:
76
+ hash += bytes[p]
77
+ hash ^= hash << 10
78
+ hash += hash >>> 1
79
+ break
80
+ }
81
+
82
+ hash ^= hash << 3
83
+ hash += hash >>> 5
84
+ hash ^= hash << 4
85
+ hash += hash >>> 17
86
+ hash ^= hash << 25
87
+ hash += hash >>> 6
88
+
89
+ return hash >>> 0
90
+ }
91
+
92
+ export function cyrb53Hash(bytes: Buffer, seed = 0) {
93
+ // https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
94
+
95
+ let h1 = 0xdeadbeef ^ seed
96
+ let h2 = 0x41c6ce57 ^ seed
97
+
98
+ for (const byte of bytes) {
99
+ h1 = Math.imul(h1 ^ byte, 2654435761)
100
+ h2 = Math.imul(h2 ^ byte, 1597334677)
101
+ }
102
+
103
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)
104
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)
105
+
106
+ return (4294967296 * (2097151 & h2)) + (h1 >>> 0)
107
+ }
108
+
109
+ export function djb2(bytes: Buffer) {
110
+ let hash = 5381
111
+
112
+ for (const byte of bytes) {
113
+ //hash += (hash << 5) + byte
114
+ hash += (hash * 33) + byte
115
+ }
116
+
117
+ return hash >>> 0
118
+ }
119
+
120
+
121
+ export function murmurHash1(bytes: Buffer, seed = 0) {
122
+ // https://github.com/bryc/code/blob/master/jshash/hashes/murmurhash1.js
123
+
124
+ const length = bytes.length
125
+
126
+ const multiplier = 3332679571
127
+ const intIterationMaxIndex = length & -4
128
+
129
+ let hash = seed ^ Math.imul(length, multiplier)
130
+ let index = 0
131
+
132
+ for (; index < intIterationMaxIndex; index += 4) {
133
+ hash += bytes[index + 3] << 24 |
134
+ bytes[index + 2] << 16 |
135
+ bytes[index + 1] << 8 |
136
+ bytes[index]
137
+
138
+ hash = Math.imul(hash, multiplier)
139
+ hash ^= hash >>> 16
140
+ }
141
+
142
+ switch (length & 3) {
143
+ case 3: {
144
+ hash += bytes[index + 2] << 16
145
+ }
146
+
147
+ case 2: {
148
+ hash += bytes[index + 1] << 8
149
+ }
150
+
151
+ case 1: {
152
+ hash += bytes[index]
153
+ hash = Math.imul(hash, multiplier)
154
+ hash ^= hash >>> 16
155
+ }
156
+ }
157
+
158
+ hash = Math.imul(hash, multiplier)
159
+ hash ^= hash >>> 10
160
+
161
+ hash = Math.imul(hash, multiplier)
162
+ hash ^= hash >>> 17
163
+
164
+ return hash >>> 0
165
+ }
166
+
167
+ export function MurmurHash3(bytes: Buffer, seed = 0) {
168
+ // https://github.com/bryc/code/blob/master/jshash/hashes/murmurhash3.js
169
+
170
+ const p1 = 3432918353
171
+ const p2 = 461845907
172
+ const p3 = 2246822507
173
+ const p4 = 3266489909
174
+
175
+ const byteCount = bytes.length
176
+
177
+ const intIterationMaxIndex = byteCount & -4
178
+
179
+ let k = 0
180
+ let hash = seed | 0
181
+ let i = 0
182
+
183
+ for (; i < intIterationMaxIndex; i += 4) {
184
+ k = bytes[i + 3] << 24 | bytes[i + 2] << 16 | bytes[i + 1] << 8 | bytes[i]
185
+
186
+ k = Math.imul(k, p1)
187
+
188
+ k = k << 15 | k >>> 17
189
+
190
+ hash ^= Math.imul(k, p2)
191
+
192
+ hash = hash << 13 | hash >>> 19
193
+
194
+ hash = (Math.imul(hash, 5) + 3864292196) | 0 // |0 = prevent float
195
+ }
196
+
197
+ k = 0
198
+
199
+ switch (bytes.length & 3) {
200
+ case 3: {
201
+ k ^= bytes[i + 2] << 16
202
+ }
203
+
204
+ case 2: {
205
+ k ^= bytes[i + 1] << 8
206
+ }
207
+
208
+ case 1: {
209
+ k ^= bytes[i]
210
+
211
+ k = Math.imul(k, p1)
212
+
213
+ k = k << 15 | k >>> 17
214
+
215
+ hash ^= Math.imul(k, p2)
216
+ }
217
+ }
218
+
219
+ hash ^= byteCount
220
+
221
+ hash ^= hash >>> 16
222
+
223
+ hash = Math.imul(hash, p3)
224
+ hash ^= hash >>> 13
225
+
226
+ hash = Math.imul(hash, p4)
227
+ hash ^= hash >>> 16
228
+
229
+ return hash >>> 0
230
+ }
@@ -0,0 +1,119 @@
1
+ import { readAndParseJsonFile, resolveToModuleRootDir } from "./FileSystem.js"
2
+
3
+ export function languageCodeToName(languageCode: string) {
4
+ const languageNames = new Intl.DisplayNames(['en'], { type: 'language' })
5
+
6
+ let translatedLanguageName: string | undefined
7
+
8
+ try {
9
+ translatedLanguageName = languageNames.of(languageCode)
10
+ } catch (e) {
11
+ }
12
+
13
+ return translatedLanguageName || "Unknown"
14
+ }
15
+
16
+ export function formatLanguageCodeWithName(languageCode: string, styleId: 1 | 2 = 1) {
17
+ if (styleId == 1) {
18
+ return `${languageCodeToName(languageCode)} (${languageCode})`
19
+ } else {
20
+ return `${languageCode}, ${languageCodeToName(languageCode)}`
21
+ }
22
+ }
23
+
24
+ export function getShortLanguageCode(langCode: string) {
25
+ const dashIndex = langCode.indexOf("-")
26
+
27
+ if (dashIndex == -1) {
28
+ return langCode
29
+ }
30
+
31
+ return langCode.substring(0, dashIndex).toLowerCase()
32
+ }
33
+
34
+ export function normalizeLanguageCode(langCode: string) {
35
+ langCode = langCode.trim()
36
+
37
+ const parts = langCode.split("-")
38
+
39
+ const result = [parts[0].toLowerCase()]
40
+
41
+ for (let i = 1; i < parts.length; i++) {
42
+ result.push(parts[i].toUpperCase())
43
+ }
44
+
45
+ return result.join("-")
46
+ }
47
+
48
+ const isoToLcidLookup = new Map<string, number>()
49
+ const lcidToIsoLookup = new Map<number, string[]>()
50
+ const lcidEntries: LCIDEntry[] = []
51
+
52
+ export async function isoToLcidLanguageCode(iso: string) {
53
+ await loadLcidLookupIfNeeded()
54
+
55
+ return isoToLcidLookup.get(iso)
56
+ }
57
+
58
+ export async function lcidToIsoLanguageCode(lcid: number) {
59
+ await loadLcidLookupIfNeeded()
60
+
61
+ return lcidToIsoLookup.get(lcid)
62
+ }
63
+
64
+ async function loadLcidLookupIfNeeded() {
65
+ if (lcidEntries.length > 0) {
66
+ return lcidEntries
67
+ }
68
+
69
+ const lcidLookup: LCIDLookup = await readAndParseJsonFile(resolveToModuleRootDir("data/tables/lcid-table.json"))
70
+
71
+ for (const isoName in lcidLookup) {
72
+ const lcidEntry = lcidLookup[isoName]
73
+ lcidEntries.push(lcidEntry)
74
+
75
+ const lcidValue = lcidEntry.LCID
76
+
77
+ isoToLcidLookup.set(isoName, lcidValue)
78
+
79
+ let entry = lcidToIsoLookup.get(lcidValue)
80
+
81
+ if (!entry) {
82
+ entry = []
83
+ lcidToIsoLookup.set(lcidValue, entry)
84
+ }
85
+
86
+ entry.push(isoName)
87
+ }
88
+
89
+ return lcidEntries
90
+ }
91
+
92
+ export function getDefaultDialectForLanguageCodeIfPossible(langCode: string) {
93
+ const defaultDialect = defaultDialectForLanguageCode[langCode]
94
+
95
+ return defaultDialect || langCode
96
+ }
97
+
98
+ export const defaultDialectForLanguageCode: { [lang: string]: string } = {
99
+ "en": "en-US",
100
+ "zh": "zh-CN",
101
+ "ar": "ar-EG",
102
+ "fr": "fr-FR",
103
+ "de": "de-DE",
104
+ "pt": "pt-BR",
105
+ "es": "es-ES",
106
+ "nl": "nl-NL"
107
+ }
108
+
109
+ type LCIDLookup = { [isoLangCode: string]: LCIDEntry }
110
+
111
+ export interface LCIDEntry {
112
+ "LCID": number
113
+ "Name": string
114
+ "TwoLetterISOLanguageName": string,
115
+ "ThreeLetterISOLanguageName": string,
116
+ "ThreeLetterWindowsLanguageName": string,
117
+ "EnglishName": string
118
+ "ANSICodePage": string
119
+ }
@@ -0,0 +1,72 @@
1
+ import chalk from "chalk"
2
+ import { Timer } from "./Timer.js"
3
+ import { logToStderr, writeToStderr, yieldToEventLoop } from "./Utilities.js"
4
+
5
+ let currentActiveLogger: Logger | null = null
6
+
7
+ export class Logger {
8
+ private timer = new Timer()
9
+ active = false
10
+
11
+ start(title: string, titleColor = chalk.cyanBright) {
12
+ this.startAsync(title, false, titleColor)
13
+ }
14
+
15
+ async startAsync(title: string, yieldBeforeStart = true, titleColor = chalk.cyanBright) {
16
+ if (currentActiveLogger != null && currentActiveLogger != this) {
17
+ return
18
+ }
19
+
20
+ this.end()
21
+
22
+ if (yieldBeforeStart) {
23
+ await yieldToEventLoop()
24
+ }
25
+
26
+ writeToStderr(`${titleColor(title)}.. `)
27
+ this.active = true
28
+ currentActiveLogger = this
29
+ this.timer.restart()
30
+ }
31
+
32
+ end() {
33
+ if (this.active && currentActiveLogger == this) {
34
+ const elapsedTime = this.timer.elapsedTime
35
+
36
+ writeToStderr(`${elapsedTime.toFixed(1)}ms\n`)
37
+ currentActiveLogger = null
38
+ }
39
+
40
+ this.active = false
41
+ }
42
+
43
+ logDuration(message: any, startTime: number, titleColor = chalk.cyanBright) {
44
+ const duration = Timer.currentTime - startTime
45
+
46
+ this.log(`${titleColor(message)}: ${duration.toFixed(1)}ms`)
47
+ }
48
+
49
+ logTitledMessage(title: string, content: string, titleColor = chalk.cyanBright) {
50
+ this.log(`${titleColor(title)}: ${content}`)
51
+ }
52
+
53
+ log(message: any) {
54
+ if (currentActiveLogger == this || currentActiveLogger == null) {
55
+ logToStderr(message)
56
+ }
57
+ }
58
+
59
+ write(message: any) {
60
+ if (currentActiveLogger == this || currentActiveLogger == null) {
61
+ writeToStderr(message)
62
+ }
63
+ }
64
+
65
+ getTimestamp() {
66
+ return Timer.currentTime
67
+ }
68
+ }
69
+
70
+ export function resetActiveLogger() {
71
+ currentActiveLogger = null
72
+ }
@@ -0,0 +1,31 @@
1
+ import ndarray from 'ndarray'
2
+ import ops from 'ndarray-ops'
3
+ import { medianFilter, softmax } from '../math/VectorMath.js'
4
+
5
+ export function ndarraySoftMax(vector: ndarray.NdArray, temperature = 1.0) {
6
+ const vectorAsArray = new Array(vector.shape[0])
7
+
8
+ for (let i = 0; i < vectorAsArray.length; i++) {
9
+ vectorAsArray[i] = vector.get(i)
10
+ }
11
+
12
+ const result = softmax(vectorAsArray, temperature)
13
+
14
+ for (let i = 0; i < vectorAsArray.length; i++) {
15
+ vector.set(i, result[i])
16
+ }
17
+ }
18
+
19
+ export function ndarrayMedianFilter(vector: ndarray.NdArray, width: number) {
20
+ const vectorAsArray = new Array(vector.shape[0])
21
+
22
+ for (let i = 0; i < vectorAsArray.length; i++) {
23
+ vectorAsArray[i] = vector.get(i)
24
+ }
25
+
26
+ const result = medianFilter(vectorAsArray, width)
27
+
28
+ for (let i = 0; i < vectorAsArray.length; i++) {
29
+ vector.set(i, result[i])
30
+ }
31
+ }