echogarden 3.1.0 → 3.3.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.
- package/data/lexicons/heteronyms.en.json +1 -1
- package/data/lexicons/words.en.json +32 -0
- package/dist/api/Synthesis.js +2 -2
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/encodings/Ascii.d.ts +1 -3
- package/dist/encodings/Ascii.d.ts.map +1 -1
- package/dist/encodings/Ascii.js +13 -9
- package/dist/encodings/Ascii.js.map +1 -1
- package/dist/encodings/Base64.d.ts.map +1 -1
- package/dist/encodings/Base64.js +9 -0
- package/dist/encodings/Base64.js.map +1 -1
- package/dist/encodings/Hex.d.ts.map +1 -1
- package/dist/encodings/Hex.js +11 -2
- package/dist/encodings/Hex.js.map +1 -1
- package/dist/encodings/Utf16.d.ts +1 -3
- package/dist/encodings/Utf16.d.ts.map +1 -1
- package/dist/encodings/Utf16.js +13 -9
- package/dist/encodings/Utf16.js.map +1 -1
- package/dist/encodings/Utf32.d.ts.map +1 -1
- package/dist/encodings/Utf32.js +6 -0
- package/dist/encodings/Utf32.js.map +1 -1
- package/dist/encodings/Utf8.d.ts +9 -5
- package/dist/encodings/Utf8.d.ts.map +1 -1
- package/dist/encodings/Utf8.js +36 -78
- package/dist/encodings/Utf8.js.map +1 -1
- package/dist/nlp/Segmentation.d.ts.map +1 -1
- package/dist/nlp/Segmentation.js +4 -1
- package/dist/nlp/Segmentation.js.map +1 -1
- package/dist/nlp/TextNormalizer.js +8 -1
- package/dist/nlp/TextNormalizer.js.map +1 -1
- package/dist/synthesis/AzureCognitiveServicesTTS.js +1 -1
- package/dist/synthesis/AzureCognitiveServicesTTS.js.map +1 -1
- package/dist/synthesis/EspeakTTS.d.ts.map +1 -1
- package/dist/synthesis/EspeakTTS.js +21 -6
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/synthesis/MicrosoftEdgeTTS.js +1 -1
- package/dist/synthesis/MicrosoftEdgeTTS.js.map +1 -1
- package/dist/utilities/FileSystem.d.ts +12 -7
- package/dist/utilities/FileSystem.d.ts.map +1 -1
- package/dist/utilities/FileSystem.js +196 -79
- package/dist/utilities/FileSystem.js.map +1 -1
- package/dist/utilities/FileWriter.d.ts +1 -0
- package/dist/utilities/FileWriter.d.ts.map +1 -1
- package/dist/utilities/FileWriter.js +8 -1
- package/dist/utilities/FileWriter.js.map +1 -1
- package/dist/utilities/ObjectUtilities.d.ts.map +1 -1
- package/dist/utilities/ObjectUtilities.js +15 -13
- package/dist/utilities/ObjectUtilities.js.map +1 -1
- package/dist/utilities/PackageManager.js +2 -2
- package/dist/utilities/PackageManager.js.map +1 -1
- package/dist/utilities/PathUtilities.d.ts +1 -0
- package/dist/utilities/PathUtilities.d.ts.map +1 -1
- package/dist/utilities/PathUtilities.js +18 -0
- package/dist/utilities/PathUtilities.js.map +1 -1
- package/dist/utilities/StringUtilities.d.ts.map +1 -1
- package/dist/utilities/StringUtilities.js.map +1 -1
- package/dist/utilities/Timer.d.ts +7 -3
- package/dist/utilities/Timer.d.ts.map +1 -1
- package/dist/utilities/Timer.js +42 -30
- package/dist/utilities/Timer.js.map +1 -1
- package/package.json +15 -14
- package/src/api/Synthesis.ts +2 -2
- package/src/encodings/Ascii.ts +14 -10
- package/src/encodings/Base64.ts +9 -0
- package/src/encodings/Hex.ts +11 -2
- package/src/encodings/Utf16.ts +14 -10
- package/src/encodings/Utf32.ts +6 -0
- package/src/encodings/Utf8.ts +45 -82
- package/src/nlp/Segmentation.ts +5 -1
- package/src/nlp/TextNormalizer.ts +11 -1
- package/src/synthesis/AzureCognitiveServicesTTS.ts +1 -1
- package/src/synthesis/EspeakTTS.ts +22 -7
- package/src/synthesis/MicrosoftEdgeTTS.ts +1 -1
- package/src/utilities/FileSystem.ts +224 -85
- package/src/utilities/FileWriter.ts +11 -1
- package/src/utilities/ObjectUtilities.ts +19 -15
- package/src/utilities/PackageManager.ts +2 -2
- package/src/utilities/PathUtilities.ts +19 -0
- package/src/utilities/StringUtilities.ts +0 -2
- package/src/utilities/Timer.ts +57 -37
- package/tsconfig.json +51 -53
- package/dist/encodings/HtmlEscape.d.ts +0 -2
- package/dist/encodings/HtmlEscape.d.ts.map +0 -1
- package/dist/encodings/HtmlEscape.js +0 -30
- package/dist/encodings/HtmlEscape.js.map +0 -1
- package/dist/encodings/LEB128.d.ts +0 -16
- package/dist/encodings/LEB128.d.ts.map +0 -1
- package/dist/encodings/LEB128.js +0 -248
- package/dist/encodings/LEB128.js.map +0 -1
- package/dist/utilities/StringBuilder.d.ts +0 -11
- package/dist/utilities/StringBuilder.d.ts.map +0 -1
- package/dist/utilities/StringBuilder.js +0 -39
- package/dist/utilities/StringBuilder.js.map +0 -1
- package/src/encodings/HtmlEscape.ts +0 -39
- package/src/encodings/LEB128.ts +0 -362
- package/src/utilities/StringBuilder.ts +0 -45
package/src/encodings/Utf8.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { EncodeIntoResult } from
|
|
1
|
+
import { EncodeIntoResult } from './TextEncodingsCommon.js'
|
|
2
2
|
|
|
3
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
// UTF-8 Encoding
|
|
5
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
3
6
|
export function encodeUtf8(text: string) {
|
|
4
7
|
const textEncoder = new TextEncoder()
|
|
5
8
|
|
|
@@ -14,104 +17,64 @@ export function encodeUtf8Into(text: string, outputArray: Uint8Array): EncodeInt
|
|
|
14
17
|
return result
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
export
|
|
18
|
-
|
|
20
|
+
export class ChunkedUtf8Encoder {
|
|
21
|
+
private readonly textEncoder = new TextEncoder()
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
private pendingHighSurrogate = ''
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
writeChunk(stringChunk: string): Uint8Array {
|
|
26
|
+
if (this.pendingHighSurrogate !== '') {
|
|
27
|
+
stringChunk = this.pendingHighSurrogate + stringChunk
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
this.pendingHighSurrogate = ''
|
|
30
|
+
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
}
|
|
32
|
+
const lastCodeUnit = stringChunk.charCodeAt(stringChunk.length - 1)
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
private readonly textDecoder = new TextDecoder('utf-8')
|
|
34
|
+
if (lastCodeUnit >= 0xD800 && lastCodeUnit <= 0xDBFF) {
|
|
35
|
+
this.pendingHighSurrogate = stringChunk[stringChunk.length - 1]
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
stringChunk = stringChunk.substring(0, stringChunk.length - 1)
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
this.
|
|
40
|
+
return this.textEncoder.encode(stringChunk)
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
finalize(): Uint8Array {
|
|
44
|
+
const result = this.textEncoder.encode(this.pendingHighSurrogate)
|
|
45
|
+
|
|
46
|
+
this.pendingHighSurrogate = ''
|
|
47
|
+
|
|
48
|
+
return result
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} else if (charCode <= 0xffff) {
|
|
62
|
-
outputArray[writeOffset++] = 0xe0 | (charCode >>> 12)
|
|
63
|
-
outputArray[writeOffset++] = 0x80 | ((charCode >>> 6) & 63)
|
|
64
|
-
outputArray[writeOffset++] = 0x80 | (charCode & 63)
|
|
65
|
-
} else if (charCode <= 0x10ffff) {
|
|
66
|
-
outputArray[writeOffset++] = 0xf0 | (charCode >>> 18)
|
|
67
|
-
outputArray[writeOffset++] = 0x80 | ((charCode >>> 12) & 63)
|
|
68
|
-
outputArray[writeOffset++] = 0x80 | ((charCode >>> 6) & 63)
|
|
69
|
-
outputArray[writeOffset++] = 0x80 | (charCode & 63)
|
|
70
|
-
|
|
71
|
-
readOffset++
|
|
72
|
-
}
|
|
52
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
53
|
+
// UTF-8 Decoding
|
|
54
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
55
|
+
export function decodeUtf8(utf8Bytes: Uint8Array) {
|
|
56
|
+
const maxChunkLength = 2 ** 24
|
|
57
|
+
|
|
58
|
+
const chunkedUtf8Decoder = new ChunkedUtf8Decoder()
|
|
59
|
+
|
|
60
|
+
let resultString = ''
|
|
61
|
+
|
|
62
|
+
for (let offset = 0; offset < utf8Bytes.length; offset += maxChunkLength) {
|
|
63
|
+
const utf8Chunk = utf8Bytes.subarray(offset, offset + maxChunkLength)
|
|
64
|
+
const stringChunk = chunkedUtf8Decoder.writeChunk(utf8Chunk)
|
|
65
|
+
|
|
66
|
+
resultString += stringChunk
|
|
73
67
|
}
|
|
74
68
|
|
|
75
|
-
return
|
|
69
|
+
return resultString
|
|
76
70
|
}
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
let readOffset = 0
|
|
82
|
-
|
|
83
|
-
while (readOffset < utf8Bytes.length) {
|
|
84
|
-
const leadByte = utf8Bytes[readOffset++]
|
|
85
|
-
|
|
86
|
-
let outputCodePoint: number
|
|
87
|
-
|
|
88
|
-
if (leadByte >>> 7 === 0) {
|
|
89
|
-
outputCodePoint = leadByte
|
|
90
|
-
} else if (leadByte >>> 5 === 6) {
|
|
91
|
-
outputCodePoint =
|
|
92
|
-
(leadByte & 31) << 6 |
|
|
93
|
-
(utf8Bytes[readOffset++] & 63)
|
|
94
|
-
} else if (leadByte >>> 4 === 14) {
|
|
95
|
-
outputCodePoint =
|
|
96
|
-
(leadByte & 15) << 12 |
|
|
97
|
-
(utf8Bytes[readOffset++] & 63) << 6 |
|
|
98
|
-
(utf8Bytes[readOffset++] & 63)
|
|
99
|
-
} else if (leadByte >>> 3 === 30) {
|
|
100
|
-
outputCodePoint =
|
|
101
|
-
(leadByte & 7) << 18 |
|
|
102
|
-
(utf8Bytes[readOffset++] & 63) << 12 |
|
|
103
|
-
(utf8Bytes[readOffset++] & 63) << 6 |
|
|
104
|
-
(utf8Bytes[readOffset++] & 63)
|
|
105
|
-
} else {
|
|
106
|
-
throw new Error(`Invalid UTF-8 stream: An invalid lead byte value encountered at position ${readOffset}`)
|
|
107
|
-
}
|
|
72
|
+
export class ChunkedUtf8Decoder {
|
|
73
|
+
private readonly textDecoder = new TextDecoder('utf-8')
|
|
108
74
|
|
|
109
|
-
|
|
110
|
-
|
|
75
|
+
writeChunk(chunk: Uint8Array) {
|
|
76
|
+
const decodedChunk = this.textDecoder.decode(chunk, { stream: true })
|
|
111
77
|
|
|
112
|
-
|
|
113
|
-
throw new Error(`UTF-8 decoding failed. Byte sequence is truncated.`)
|
|
78
|
+
return decodedChunk
|
|
114
79
|
}
|
|
115
|
-
|
|
116
|
-
return decodedString
|
|
117
80
|
}
|
package/src/nlp/Segmentation.ts
CHANGED
|
@@ -22,7 +22,11 @@ const includesEmojiSequencePattern = anyOf(
|
|
|
22
22
|
)
|
|
23
23
|
const includesEmojiSequenceRegExp = buildRegExp(includesEmojiSequencePattern)
|
|
24
24
|
|
|
25
|
-
const symbolWordsList = [
|
|
25
|
+
const symbolWordsList = [
|
|
26
|
+
'$', '€', '¢', '£', '¥', '©', '®', '™', '%', '&', '#', '~', '@', '+', '±', '÷',
|
|
27
|
+
'/', '\\', '^', '*', '×', '=', '≈', '¼', '½', '¾', '→', '≤', '≥', '∞'
|
|
28
|
+
]
|
|
29
|
+
|
|
26
30
|
const includesSymbolWordPattern = anyOf(...symbolWordsList)
|
|
27
31
|
const includesSymbolWordRegExp = buildRegExp(includesSymbolWordPattern)
|
|
28
32
|
|
|
@@ -31,7 +31,7 @@ export function getNormalizedFragmentsForSpeech(
|
|
|
31
31
|
|
|
32
32
|
//const isWordPrecedingAYear = wordsPrecedingAYear.includes(lowerCaseWord)
|
|
33
33
|
const isWordPrecedingAYear =
|
|
34
|
-
|
|
34
|
+
isAllLettersOrApostropheRegExp.test(lowerCaseWord) || isSpecialCharacterBeforeYear
|
|
35
35
|
|
|
36
36
|
const followedByFourDigitYearPattern = fourDigitYearRegExp.test(nextNonWhitespaceWord)
|
|
37
37
|
|
|
@@ -284,3 +284,13 @@ const fourDigitYearRangeRegExp = buildRegExp(fourDigitYearRangePattern)
|
|
|
284
284
|
|
|
285
285
|
const isAllLettersPattern = [inputStart, oneOrMore(unicodeProperty('Letter')), inputEnd]
|
|
286
286
|
const isAllLettersRegExp = buildRegExp(isAllLettersPattern)
|
|
287
|
+
|
|
288
|
+
const isAllLettersOrApostrophePattern = [
|
|
289
|
+
inputStart,
|
|
290
|
+
|
|
291
|
+
unicodeProperty('Letter'),
|
|
292
|
+
zeroOrMore(anyOf(unicodeProperty('Letter'), `'`, `’`)),
|
|
293
|
+
inputEnd,
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
const isAllLettersOrApostropheRegExp = buildRegExp(isAllLettersOrApostrophePattern)
|
|
@@ -6,7 +6,7 @@ import { Logger } from '../utilities/Logger.js'
|
|
|
6
6
|
import { Timeline } from '../utilities/Timeline.js'
|
|
7
7
|
import { RawAudio, getRawAudioDuration } from '../audio/AudioUtilities.js'
|
|
8
8
|
import { concatUint8Arrays } from '../utilities/Utilities.js'
|
|
9
|
-
import { escapeHtml } from '
|
|
9
|
+
import { escapeHtml } from 'standard-html-escaper'
|
|
10
10
|
import { SynthesisCallbacks } from '../api/Synthesis.js'
|
|
11
11
|
|
|
12
12
|
export async function synthesize(
|
|
@@ -9,7 +9,7 @@ import { Lexicon, tryGetFirstLexiconSubstitution } from '../nlp/Lexicon.js'
|
|
|
9
9
|
import { phonemizeSentence } from '../nlp/EspeakPhonemizer.js'
|
|
10
10
|
import { Timeline, TimelineEntry } from '../utilities/Timeline.js'
|
|
11
11
|
import { extendDeep } from '../utilities/ObjectUtilities.js'
|
|
12
|
-
import { escapeHtml } from '
|
|
12
|
+
import { escapeHtml } from 'standard-html-escaper'
|
|
13
13
|
import * as TextSegmentation from '@echogarden/text-segmentation'
|
|
14
14
|
|
|
15
15
|
import { OperationCallbacks, SynthesisCallbacks } from '../api/API.js'
|
|
@@ -257,12 +257,29 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
const
|
|
260
|
+
const separatorString = ` | `
|
|
261
|
+
|
|
262
|
+
const canInsertSeparators = ![
|
|
263
|
+
'roa/an',
|
|
264
|
+
'an',
|
|
265
|
+
'art/eo',
|
|
266
|
+
'eo',
|
|
267
|
+
'trk/ky',
|
|
268
|
+
'ky',
|
|
269
|
+
'zlw/pl',
|
|
270
|
+
'pl',
|
|
271
|
+
'zle/uk',
|
|
272
|
+
'uk',
|
|
273
|
+
'gmw/nl',
|
|
274
|
+
'nl'
|
|
275
|
+
].includes(voice)
|
|
261
276
|
|
|
262
277
|
let textWithMarkers: string
|
|
263
278
|
|
|
264
|
-
if
|
|
265
|
-
|
|
279
|
+
// Added `espeakOptions.insertSeparators` here because I'm not sure if adding the separator
|
|
280
|
+
// here is completely necessary, and it is causing issues with some languages.
|
|
281
|
+
if (espeakOptions.insertSeparators && canInsertSeparators) {
|
|
282
|
+
textWithMarkers = `()${separatorString}`
|
|
266
283
|
} else {
|
|
267
284
|
textWithMarkers = `() `
|
|
268
285
|
}
|
|
@@ -280,9 +297,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
280
297
|
}
|
|
281
298
|
|
|
282
299
|
if (espeakOptions.insertSeparators && canInsertSeparators) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
textWithMarkers += `<mark name="s-${i}"/>${separator}${fragment}${separator}<mark name="e-${i}"/>`
|
|
300
|
+
textWithMarkers += `<mark name="s-${i}"/>${separatorString}${fragment}${separatorString}<mark name="e-${i}"/>`
|
|
286
301
|
} else {
|
|
287
302
|
if (fragment.endsWith('.')) {
|
|
288
303
|
fragment += ' ()'
|
|
@@ -8,7 +8,7 @@ import { concatUint8Arrays, getRandomHexString, logToStderr, sha256AsHex } from
|
|
|
8
8
|
import { RawAudio, getEmptyRawAudio, getRawAudioDuration } from '../audio/AudioUtilities.js'
|
|
9
9
|
import { Timer } from '../utilities/Timer.js'
|
|
10
10
|
import { decodeUtf8, encodeUtf8 } from '../encodings/Utf8.js'
|
|
11
|
-
import { escapeHtml } from '
|
|
11
|
+
import { escapeHtml } from 'standard-html-escaper'
|
|
12
12
|
import { requestHttp } from 'easier-http-request'
|
|
13
13
|
import { VoiceListRequestCallbacks, SynthesisCallbacks } from '../api/API.js'
|
|
14
14
|
|