echogarden 1.3.3 → 1.4.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.
- package/data/schemas/options.json +0 -1
- package/dist/alignment/DTWSequenceAlignmentWindowed.js +68 -27
- package/dist/alignment/DTWSequenceAlignmentWindowed.js.map +1 -1
- package/dist/alignment/SpeechAlignment.d.ts +1 -1
- package/dist/alignment/SpeechAlignment.js +6 -21
- package/dist/alignment/SpeechAlignment.js.map +1 -1
- package/dist/api/Alignment.js +47 -28
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/LanguageDetection.js +2 -2
- package/dist/api/LanguageDetection.js.map +1 -1
- package/dist/api/Synthesis.js +1 -1
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/synthesis/EspeakTTS.js +36 -17
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/utilities/Compression.d.ts +1 -0
- package/dist/utilities/Compression.js +10 -0
- package/dist/utilities/Compression.js.map +1 -1
- package/dist/utilities/LEB128.d.ts +5 -0
- package/dist/utilities/LEB128.js +168 -0
- package/dist/utilities/LEB128.js.map +1 -0
- package/docs/Options.md +1 -1
- package/docs/Tasklist.md +0 -1
- package/package.json +6 -6
- package/src/alignment/DTWSequenceAlignmentWindowed.ts +69 -29
- package/src/alignment/SpeechAlignment.ts +7 -23
- package/src/api/Alignment.ts +48 -29
- package/src/api/LanguageDetection.ts +2 -2
- package/src/api/Synthesis.ts +1 -1
- package/src/synthesis/EspeakTTS.ts +39 -18
- package/src/utilities/Compression.ts +15 -0
- package/src/utilities/LEB128.ts +237 -0
|
@@ -257,7 +257,7 @@ export async function detectTextLanguage(input: string, options: TextLanguageDet
|
|
|
257
257
|
case 'tinyld': {
|
|
258
258
|
const { detectLanguage } = await import('../text-language-detection/TinyLDLanguageDetection.js')
|
|
259
259
|
|
|
260
|
-
logger.start('
|
|
260
|
+
logger.start('Detect text language using tinyld')
|
|
261
261
|
|
|
262
262
|
detectedLanguageProbabilities = await detectLanguage(input)
|
|
263
263
|
|
|
@@ -267,7 +267,7 @@ export async function detectTextLanguage(input: string, options: TextLanguageDet
|
|
|
267
267
|
case 'fasttext': {
|
|
268
268
|
const { detectLanguage } = await import('../text-language-detection/FastTextLanguageDetection.js')
|
|
269
269
|
|
|
270
|
-
logger.start('
|
|
270
|
+
logger.start('Detect text language using FastText')
|
|
271
271
|
|
|
272
272
|
detectedLanguageProbabilities = await detectLanguage(input)
|
|
273
273
|
|
package/src/api/Synthesis.ts
CHANGED
|
@@ -54,7 +54,7 @@ async function synthesizeSegments(segments: string[], options: SynthesisOptions,
|
|
|
54
54
|
options = extendDeep(defaultSynthesisOptions, options)
|
|
55
55
|
|
|
56
56
|
if (!options.language && !options.voice) {
|
|
57
|
-
logger.start('No language or voice specified.
|
|
57
|
+
logger.start('No language or voice specified. Detect language')
|
|
58
58
|
|
|
59
59
|
let segmentsPlainText = segments
|
|
60
60
|
|
|
@@ -26,7 +26,7 @@ export async function preprocessAndSynthesize(text: string, language: string, es
|
|
|
26
26
|
|
|
27
27
|
let lowerCaseLanguageCode = language.toLowerCase()
|
|
28
28
|
|
|
29
|
-
if (lowerCaseLanguageCode
|
|
29
|
+
if (lowerCaseLanguageCode === 'en-gb') {
|
|
30
30
|
lowerCaseLanguageCode = 'en-gb-x-rp'
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -44,9 +44,9 @@ export async function preprocessAndSynthesize(text: string, language: string, es
|
|
|
44
44
|
|
|
45
45
|
for (let i = 0; i < words.length; i++) {
|
|
46
46
|
const currentWord = words[i]
|
|
47
|
-
const previousWord = words[i-1]
|
|
47
|
+
const previousWord = words[i - 1]
|
|
48
48
|
|
|
49
|
-
if (i > 0 && currentWord
|
|
49
|
+
if (i > 0 && currentWord === previousWord && !wordCharacterPattern.test(currentWord)) {
|
|
50
50
|
wordsWithMerges[wordsWithMerges.length - 1] += currentWord
|
|
51
51
|
} else {
|
|
52
52
|
wordsWithMerges.push(currentWord)
|
|
@@ -144,7 +144,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
144
144
|
|
|
145
145
|
//fragments = fragments.filter(fragment => fragment.trim() != '')
|
|
146
146
|
|
|
147
|
-
if (fragments.length
|
|
147
|
+
if (fragments.length === 0) {
|
|
148
148
|
return {
|
|
149
149
|
rawAudio: getEmptyRawAudio(1, sampleRate),
|
|
150
150
|
timeline: [] as Timeline,
|
|
@@ -152,7 +152,13 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
let textWithMarkers
|
|
155
|
+
let textWithMarkers: string
|
|
156
|
+
|
|
157
|
+
if (espeakOptions.insertSeparators) {
|
|
158
|
+
textWithMarkers = `() | `
|
|
159
|
+
} else {
|
|
160
|
+
textWithMarkers = `() `
|
|
161
|
+
}
|
|
156
162
|
|
|
157
163
|
for (let i = 0; i < fragments.length; i++) {
|
|
158
164
|
let fragment = fragments[i]
|
|
@@ -180,6 +186,21 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
180
186
|
|
|
181
187
|
const { rawAudio, events } = await synthesize(textWithMarkers, { ...espeakOptions, ssml: true })
|
|
182
188
|
|
|
189
|
+
// Add first marker if missing
|
|
190
|
+
if (fragments.length > 0) {
|
|
191
|
+
const firstMarkerEvent = events.find(event => event.type === 'mark')
|
|
192
|
+
|
|
193
|
+
if (firstMarkerEvent && firstMarkerEvent.id === 'e-0') {
|
|
194
|
+
events.unshift({
|
|
195
|
+
type: 'mark',
|
|
196
|
+
text_position: 0,
|
|
197
|
+
word_length: 0,
|
|
198
|
+
audio_position: 0,
|
|
199
|
+
id: 's-0',
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
183
204
|
// Build word timeline from events
|
|
184
205
|
const wordTimeline: Timeline = fragments.map(word => ({
|
|
185
206
|
type: 'word',
|
|
@@ -210,16 +231,16 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
210
231
|
const currentPhoneTimeline = currentTokenEntry.timeline!
|
|
211
232
|
const lastPhoneEntry = currentPhoneTimeline[currentPhoneTimeline.length - 1]
|
|
212
233
|
|
|
213
|
-
if (lastPhoneEntry && lastPhoneEntry.endTime
|
|
234
|
+
if (lastPhoneEntry && lastPhoneEntry.endTime === -1) {
|
|
214
235
|
lastPhoneEntry.endTime = eventTime
|
|
215
236
|
}
|
|
216
237
|
|
|
217
|
-
if (event.type
|
|
218
|
-
if (!event.id || currentPhoneTimeline.length
|
|
238
|
+
if (event.type === 'word') {
|
|
239
|
+
if (!event.id || currentPhoneTimeline.length === 0) {
|
|
219
240
|
continue
|
|
220
241
|
}
|
|
221
242
|
|
|
222
|
-
if (currentTokenEntry.endTime
|
|
243
|
+
if (currentTokenEntry.endTime === -1) {
|
|
223
244
|
currentTokenEntry.endTime = eventTime
|
|
224
245
|
}
|
|
225
246
|
|
|
@@ -230,7 +251,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
230
251
|
endTime: -1,
|
|
231
252
|
timeline: []
|
|
232
253
|
})
|
|
233
|
-
} else if (event.type
|
|
254
|
+
} else if (event.type === 'phoneme') {
|
|
234
255
|
const phoneText = event.id as string
|
|
235
256
|
|
|
236
257
|
if (!phoneText || phoneText.startsWith('(')) {
|
|
@@ -246,7 +267,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
246
267
|
|
|
247
268
|
currentTokenEntry.text += phoneText
|
|
248
269
|
currentTokenEntry.startTime = currentPhoneTimeline[0].startTime
|
|
249
|
-
} else if (event.type
|
|
270
|
+
} else if (event.type === 'mark') {
|
|
250
271
|
const markerName = event.id! as string
|
|
251
272
|
|
|
252
273
|
if (markerName.startsWith('s-')) {
|
|
@@ -276,13 +297,13 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
276
297
|
|
|
277
298
|
wordIndex += 1
|
|
278
299
|
|
|
279
|
-
if (wordIndex
|
|
300
|
+
if (wordIndex === wordTimeline.length) {
|
|
280
301
|
break
|
|
281
302
|
}
|
|
282
303
|
} else {
|
|
283
304
|
continue
|
|
284
305
|
}
|
|
285
|
-
} else if (event.type
|
|
306
|
+
} else if (event.type === 'end') {
|
|
286
307
|
clauseEndIndexes.push(wordIndex)
|
|
287
308
|
}
|
|
288
309
|
}
|
|
@@ -293,11 +314,11 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
293
314
|
for (const [index, wordEntry] of wordTimeline.entries()) {
|
|
294
315
|
const tokenTimeline = wordEntry.timeline
|
|
295
316
|
|
|
296
|
-
if (index
|
|
317
|
+
if (index === 0) {
|
|
297
318
|
continue
|
|
298
319
|
}
|
|
299
320
|
|
|
300
|
-
if (!tokenTimeline || tokenTimeline.length
|
|
321
|
+
if (!tokenTimeline || tokenTimeline.length === 0) {
|
|
301
322
|
throw new Error('Unexpected: token timeline should exist and have at least one token')
|
|
302
323
|
}
|
|
303
324
|
|
|
@@ -309,7 +330,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
309
330
|
|
|
310
331
|
const wordReferenceIPA = wordReferencePhonemes.join(' ')
|
|
311
332
|
|
|
312
|
-
if (wordReferenceIPA.trim().length
|
|
333
|
+
if (wordReferenceIPA.trim().length === 0) {
|
|
313
334
|
continue
|
|
314
335
|
}
|
|
315
336
|
|
|
@@ -382,7 +403,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
382
403
|
|
|
383
404
|
for (let entryIndex = clauseStartIndex; entryIndex <= clauseEndIndex && entryIndex < wordTimeline.length; entryIndex++) {
|
|
384
405
|
const wordEntry = wordTimeline[entryIndex]
|
|
385
|
-
if (newClause.startTime
|
|
406
|
+
if (newClause.startTime === -1) {
|
|
386
407
|
newClause.startTime = wordEntry.startTime
|
|
387
408
|
}
|
|
388
409
|
|
|
@@ -438,7 +459,7 @@ export async function synthesize(text: string, espeakOptions: EspeakOptions) {
|
|
|
438
459
|
}
|
|
439
460
|
|
|
440
461
|
for (const event of events) {
|
|
441
|
-
if (event.type
|
|
462
|
+
if (event.type === 'word') {
|
|
442
463
|
const textPosition = event.text_position - 1;
|
|
443
464
|
(event as any)['text'] = text.substring(textPosition, textPosition + event.word_length)
|
|
444
465
|
}
|
|
@@ -110,3 +110,18 @@ export async function getDeflateCompressionMetricsForString(str: string) {
|
|
|
110
110
|
ratio: originalStringBytes.length / compressedStringBytes.length
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
+
|
|
114
|
+
export function computeDeltas(data: Float32Array) {
|
|
115
|
+
const deltas = new Float32Array(data.length)
|
|
116
|
+
|
|
117
|
+
let val = 0
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < data.length; i++) {
|
|
120
|
+
const delta = Math.floor(data[i] - val)
|
|
121
|
+
deltas[i] = delta
|
|
122
|
+
|
|
123
|
+
val += delta
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return deltas
|
|
127
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { logToStderr } from "./Utilities.js"
|
|
2
|
+
|
|
3
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
// Encode
|
|
5
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
6
|
+
export function encodeSignedInt32(value: number, outEncodedData: number[]) {
|
|
7
|
+
if (value < -2147483648 || value > 2147483647) {
|
|
8
|
+
throw new Error('Value must be between -2147483648 and 2147483647')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
while (true) {
|
|
12
|
+
const lowest7Bits = value & 127
|
|
13
|
+
|
|
14
|
+
value >>= 7
|
|
15
|
+
|
|
16
|
+
if (
|
|
17
|
+
(value === 0 && (lowest7Bits & 64) === 0) ||
|
|
18
|
+
(value === -1 && (lowest7Bits & 64) !== 0)) {
|
|
19
|
+
outEncodedData.push(lowest7Bits)
|
|
20
|
+
|
|
21
|
+
return outEncodedData
|
|
22
|
+
} else {
|
|
23
|
+
outEncodedData.push(lowest7Bits | 128)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function encodeSignedInt32sFast(value: number, outEncodedData: number[]) {
|
|
29
|
+
const absValue = Math.abs(value)
|
|
30
|
+
//const absMask = value >> 31
|
|
31
|
+
//const absValue = (value ^ absMask) - absMask
|
|
32
|
+
|
|
33
|
+
if (absValue < (2 ** 6)) {
|
|
34
|
+
outEncodedData.push(
|
|
35
|
+
(value & 127)
|
|
36
|
+
)
|
|
37
|
+
} else if (absValue < (2 ** 13)) {
|
|
38
|
+
outEncodedData.push(
|
|
39
|
+
(value & 127) | 128,
|
|
40
|
+
(value >> 7) & 127
|
|
41
|
+
)
|
|
42
|
+
} else if (absValue < (2 ** 20)) {
|
|
43
|
+
outEncodedData.push(
|
|
44
|
+
(value & 127) | 128,
|
|
45
|
+
((value >> 7) & 127) | 128,
|
|
46
|
+
(value >> 14) & 127
|
|
47
|
+
)
|
|
48
|
+
} else if (absValue < (2 ** 27)) {
|
|
49
|
+
outEncodedData.push(
|
|
50
|
+
(value & 127) | 128,
|
|
51
|
+
((value >> 7) & 127) | 128,
|
|
52
|
+
((value >> 14) & 127) | 128,
|
|
53
|
+
(value >> 21) & 127
|
|
54
|
+
)
|
|
55
|
+
} else if (value < (2 ** 31) && value >= -(2 ** 31)) {
|
|
56
|
+
outEncodedData.push(
|
|
57
|
+
(value & 127) | 128,
|
|
58
|
+
((value >> 7) & 127) | 128,
|
|
59
|
+
((value >> 14) & 127) | 128,
|
|
60
|
+
((value >> 21) & 127) | 128,
|
|
61
|
+
(value >> 28) & 127
|
|
62
|
+
)
|
|
63
|
+
} else {
|
|
64
|
+
throw new Error(`Value must be between -2147483648 and 2147483647`)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
69
|
+
// Decode
|
|
70
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
71
|
+
export function decodeSignedInt32s(encodedData: ArrayLike<number>, outDecodedValues: number[]) {
|
|
72
|
+
for (let readIndex = 0; readIndex < encodedData.length;) {
|
|
73
|
+
let currentDecodedValue = 0
|
|
74
|
+
let shiftAmount = 0
|
|
75
|
+
|
|
76
|
+
while (true) {
|
|
77
|
+
const encodedByte = encodedData[readIndex++]
|
|
78
|
+
const lowest7Bits = encodedByte & 127
|
|
79
|
+
|
|
80
|
+
currentDecodedValue |= lowest7Bits << shiftAmount
|
|
81
|
+
|
|
82
|
+
// If 8th bit is 0, then this is the last byte in the sequence
|
|
83
|
+
if ((encodedByte & 128) === 0) {
|
|
84
|
+
// If 7th bit is 1, then the value is negative
|
|
85
|
+
if ((encodedByte & 64) !== 0) {
|
|
86
|
+
// If the value should be negative
|
|
87
|
+
// Ensure that the value is encoded as a negative number by
|
|
88
|
+
// setting all higher bits to 1
|
|
89
|
+
currentDecodedValue |= -1 << Math.min(shiftAmount + 7, 31)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
break
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (readIndex === encodedData.length) {
|
|
96
|
+
throw new Error(`Invalid LEB128 data. Last encoded byte sequence is truncated.`)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
shiftAmount += 7
|
|
100
|
+
|
|
101
|
+
if (shiftAmount > 31) {
|
|
102
|
+
throw new Error(`LEB128 sequence can't be decoded. Byte sequence extends beyond the range of a signed 32 bit integer.`)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
outDecodedValues.push(currentDecodedValue)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return outDecodedValues
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function decodeSignedInt32sFast(encodedData: ArrayLike<number>, outDecodedValues: number[]) {
|
|
113
|
+
for (let readIndex = 0; readIndex < encodedData.length;) {
|
|
114
|
+
const byte0 = encodedData[readIndex++]
|
|
115
|
+
|
|
116
|
+
if ((byte0 & 128) === 0) {
|
|
117
|
+
let decodedValue =
|
|
118
|
+
(byte0 & 127)
|
|
119
|
+
|
|
120
|
+
if ((byte0 & 64) !== 0) {
|
|
121
|
+
decodedValue |= -1 << 7
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
outDecodedValues.push(decodedValue)
|
|
125
|
+
|
|
126
|
+
continue
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const byte1 = encodedData[readIndex++]
|
|
130
|
+
|
|
131
|
+
if ((byte1 & 128) === 0) {
|
|
132
|
+
let decodedValue =
|
|
133
|
+
(byte0 & 127) |
|
|
134
|
+
(byte1 & 127) << 7
|
|
135
|
+
|
|
136
|
+
if ((byte1 & 64) !== 0) {
|
|
137
|
+
decodedValue |= -1 << 14
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
outDecodedValues.push(decodedValue)
|
|
141
|
+
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const byte2 = encodedData[readIndex++]
|
|
146
|
+
|
|
147
|
+
if ((byte2 & 128) === 0) {
|
|
148
|
+
let decodedValue =
|
|
149
|
+
(byte0 & 127) |
|
|
150
|
+
(byte1 & 127) << 7 |
|
|
151
|
+
(byte2 & 127) << 14
|
|
152
|
+
|
|
153
|
+
if ((byte2 & 64) !== 0) {
|
|
154
|
+
decodedValue |= -1 << 21
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
outDecodedValues.push(decodedValue)
|
|
158
|
+
|
|
159
|
+
continue
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const byte3 = encodedData[readIndex++]
|
|
163
|
+
|
|
164
|
+
if ((byte3 & 128) === 0) {
|
|
165
|
+
let decodedValue =
|
|
166
|
+
(byte0 & 127) |
|
|
167
|
+
(byte1 & 127) << 7 |
|
|
168
|
+
(byte2 & 127) << 14 |
|
|
169
|
+
(byte3 & 127) << 21
|
|
170
|
+
|
|
171
|
+
if ((byte3 & 64) !== 0) {
|
|
172
|
+
decodedValue |= -1 << 28
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
outDecodedValues.push(decodedValue)
|
|
176
|
+
|
|
177
|
+
continue
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const byte4 = encodedData[readIndex++]
|
|
181
|
+
|
|
182
|
+
if ((byte4 & 128) === 0) {
|
|
183
|
+
let decodedValue =
|
|
184
|
+
(byte0 & 127) |
|
|
185
|
+
(byte1 & 127) << 7 |
|
|
186
|
+
(byte2 & 127) << 14 |
|
|
187
|
+
(byte3 & 127) << 21 |
|
|
188
|
+
(byte4 & 127) << 28
|
|
189
|
+
|
|
190
|
+
if ((byte4 & 64) !== 0) {
|
|
191
|
+
decodedValue |= -1 << 31
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
outDecodedValues.push(decodedValue)
|
|
195
|
+
|
|
196
|
+
continue
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (readIndex >= encodedData.length) {
|
|
200
|
+
throw new Error(`Invalid LEB128 data. Last encoded byte sequence is truncated.`)
|
|
201
|
+
} else {
|
|
202
|
+
throw new Error(`LEB128 sequence can't be decoded. Encoded byte sequence represents a value that extends beyond the range of a signed 32 bit integer.`)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return outDecodedValues
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
210
|
+
// Tests
|
|
211
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
212
|
+
export function testLeb128() {
|
|
213
|
+
const encodedBytes: number[] = []
|
|
214
|
+
const decodedValues: number[] = []
|
|
215
|
+
|
|
216
|
+
function runTest(testValue: number) {
|
|
217
|
+
encodedBytes.length = 0
|
|
218
|
+
decodedValues.length = 0
|
|
219
|
+
|
|
220
|
+
encodeSignedInt32sFast(testValue, encodedBytes)
|
|
221
|
+
decodeSignedInt32sFast(encodedBytes, decodedValues)
|
|
222
|
+
|
|
223
|
+
if (decodedValues[0] !== testValue) {
|
|
224
|
+
throw new Error(`Expected ${testValue} but got ${decodedValues[0]}`)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
for (let i = -(2 ** 22); i < 2 ** 22; i++) {
|
|
229
|
+
if (i % 1000000 === 0) {
|
|
230
|
+
logToStderr(i)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
runTest(i)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const x = 1
|
|
237
|
+
}
|