echogarden 1.3.2 → 1.4.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/schemas/options.json +3 -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 +3 -3
- package/dist/api/LanguageDetection.js.map +1 -1
- package/dist/api/Recognition.js +1 -1
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/Synthesis.js +1 -1
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/api/Translation.js +1 -1
- package/dist/api/Translation.js.map +1 -1
- package/dist/api/TranslationAlignment.js +1 -1
- package/dist/api/TranslationAlignment.js.map +1 -1
- package/dist/audio/AudioBufferConversion.d.ts +2 -2
- package/dist/audio/AudioBufferConversion.js +46 -36
- package/dist/audio/AudioBufferConversion.js.map +1 -1
- package/dist/cli/CLI.js +1 -0
- package/dist/cli/CLI.js.map +1 -1
- package/dist/codecs/FFMpegTranscoder.js +2 -1
- package/dist/codecs/FFMpegTranscoder.js.map +1 -1
- package/dist/codecs/WaveCodec.js +8 -3
- package/dist/codecs/WaveCodec.js.map +1 -1
- package/dist/recognition/WhisperSTT.d.ts +1 -0
- package/dist/recognition/WhisperSTT.js +13 -6
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/synthesis/EspeakTTS.js +5 -0
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/utilities/Compression.d.ts +1 -0
- package/dist/utilities/Compression.js +11 -1
- 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 +2 -1
- package/docs/Tasklist.md +3 -3
- package/package.json +7 -7
- 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 +3 -3
- package/src/api/Recognition.ts +1 -1
- package/src/api/Synthesis.ts +1 -1
- package/src/api/Translation.ts +1 -1
- package/src/api/TranslationAlignment.ts +1 -1
- package/src/audio/AudioBufferConversion.ts +46 -36
- package/src/cli/CLI.ts +1 -0
- package/src/codecs/FFMpegTranscoder.ts +3 -1
- package/src/codecs/WaveCodec.ts +11 -3
- package/src/recognition/WhisperSTT.ts +14 -7
- package/src/synthesis/EspeakTTS.ts +7 -1
- package/src/utilities/Compression.ts +16 -1
- package/src/utilities/LEB128.ts +237 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { logToStderr } from "./Utilities.js";
|
|
2
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
3
|
+
// Encode
|
|
4
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
export function encodeSignedInt32(value, outEncodedData) {
|
|
6
|
+
if (value < -2147483648 || value > 2147483647) {
|
|
7
|
+
throw new Error('Value must be between -2147483648 and 2147483647');
|
|
8
|
+
}
|
|
9
|
+
while (true) {
|
|
10
|
+
const lowest7Bits = value & 127;
|
|
11
|
+
value >>= 7;
|
|
12
|
+
if ((value === 0 && (lowest7Bits & 64) === 0) ||
|
|
13
|
+
(value === -1 && (lowest7Bits & 64) !== 0)) {
|
|
14
|
+
outEncodedData.push(lowest7Bits);
|
|
15
|
+
return outEncodedData;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
outEncodedData.push(lowest7Bits | 128);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function encodeSignedInt32sFast(value, outEncodedData) {
|
|
23
|
+
const absValue = Math.abs(value);
|
|
24
|
+
//const absMask = value >> 31
|
|
25
|
+
//const absValue = (value ^ absMask) - absMask
|
|
26
|
+
if (absValue < (2 ** 6)) {
|
|
27
|
+
outEncodedData.push((value & 127));
|
|
28
|
+
}
|
|
29
|
+
else if (absValue < (2 ** 13)) {
|
|
30
|
+
outEncodedData.push((value & 127) | 128, (value >> 7) & 127);
|
|
31
|
+
}
|
|
32
|
+
else if (absValue < (2 ** 20)) {
|
|
33
|
+
outEncodedData.push((value & 127) | 128, ((value >> 7) & 127) | 128, (value >> 14) & 127);
|
|
34
|
+
}
|
|
35
|
+
else if (absValue < (2 ** 27)) {
|
|
36
|
+
outEncodedData.push((value & 127) | 128, ((value >> 7) & 127) | 128, ((value >> 14) & 127) | 128, (value >> 21) & 127);
|
|
37
|
+
}
|
|
38
|
+
else if (value < (2 ** 31) && value >= -(2 ** 31)) {
|
|
39
|
+
outEncodedData.push((value & 127) | 128, ((value >> 7) & 127) | 128, ((value >> 14) & 127) | 128, ((value >> 21) & 127) | 128, (value >> 28) & 127);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
throw new Error(`Value must be between -2147483648 and 2147483647`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
46
|
+
// Decode
|
|
47
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
48
|
+
export function decodeSignedInt32s(encodedData, outDecodedValues) {
|
|
49
|
+
for (let readIndex = 0; readIndex < encodedData.length;) {
|
|
50
|
+
let currentDecodedValue = 0;
|
|
51
|
+
let shiftAmount = 0;
|
|
52
|
+
while (true) {
|
|
53
|
+
const encodedByte = encodedData[readIndex++];
|
|
54
|
+
const lowest7Bits = encodedByte & 127;
|
|
55
|
+
currentDecodedValue |= lowest7Bits << shiftAmount;
|
|
56
|
+
// If 8th bit is 0, then this is the last byte in the sequence
|
|
57
|
+
if ((encodedByte & 128) === 0) {
|
|
58
|
+
// If 7th bit is 1, then the value is negative
|
|
59
|
+
if ((encodedByte & 64) !== 0) {
|
|
60
|
+
// If the value should be negative
|
|
61
|
+
// Ensure that the value is encoded as a negative number by
|
|
62
|
+
// setting all higher bits to 1
|
|
63
|
+
currentDecodedValue |= -1 << Math.min(shiftAmount + 7, 31);
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
if (readIndex === encodedData.length) {
|
|
68
|
+
throw new Error(`Invalid LEB128 data. Last encoded byte sequence is truncated.`);
|
|
69
|
+
}
|
|
70
|
+
shiftAmount += 7;
|
|
71
|
+
if (shiftAmount > 31) {
|
|
72
|
+
throw new Error(`LEB128 sequence can't be decoded. Byte sequence extends beyond the range of a signed 32 bit integer.`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
outDecodedValues.push(currentDecodedValue);
|
|
76
|
+
}
|
|
77
|
+
return outDecodedValues;
|
|
78
|
+
}
|
|
79
|
+
export function decodeSignedInt32sFast(encodedData, outDecodedValues) {
|
|
80
|
+
for (let readIndex = 0; readIndex < encodedData.length;) {
|
|
81
|
+
const byte0 = encodedData[readIndex++];
|
|
82
|
+
if ((byte0 & 128) === 0) {
|
|
83
|
+
let decodedValue = (byte0 & 127);
|
|
84
|
+
if ((byte0 & 64) !== 0) {
|
|
85
|
+
decodedValue |= -1 << 7;
|
|
86
|
+
}
|
|
87
|
+
outDecodedValues.push(decodedValue);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const byte1 = encodedData[readIndex++];
|
|
91
|
+
if ((byte1 & 128) === 0) {
|
|
92
|
+
let decodedValue = (byte0 & 127) |
|
|
93
|
+
(byte1 & 127) << 7;
|
|
94
|
+
if ((byte1 & 64) !== 0) {
|
|
95
|
+
decodedValue |= -1 << 14;
|
|
96
|
+
}
|
|
97
|
+
outDecodedValues.push(decodedValue);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const byte2 = encodedData[readIndex++];
|
|
101
|
+
if ((byte2 & 128) === 0) {
|
|
102
|
+
let decodedValue = (byte0 & 127) |
|
|
103
|
+
(byte1 & 127) << 7 |
|
|
104
|
+
(byte2 & 127) << 14;
|
|
105
|
+
if ((byte2 & 64) !== 0) {
|
|
106
|
+
decodedValue |= -1 << 21;
|
|
107
|
+
}
|
|
108
|
+
outDecodedValues.push(decodedValue);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const byte3 = encodedData[readIndex++];
|
|
112
|
+
if ((byte3 & 128) === 0) {
|
|
113
|
+
let decodedValue = (byte0 & 127) |
|
|
114
|
+
(byte1 & 127) << 7 |
|
|
115
|
+
(byte2 & 127) << 14 |
|
|
116
|
+
(byte3 & 127) << 21;
|
|
117
|
+
if ((byte3 & 64) !== 0) {
|
|
118
|
+
decodedValue |= -1 << 28;
|
|
119
|
+
}
|
|
120
|
+
outDecodedValues.push(decodedValue);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const byte4 = encodedData[readIndex++];
|
|
124
|
+
if ((byte4 & 128) === 0) {
|
|
125
|
+
let decodedValue = (byte0 & 127) |
|
|
126
|
+
(byte1 & 127) << 7 |
|
|
127
|
+
(byte2 & 127) << 14 |
|
|
128
|
+
(byte3 & 127) << 21 |
|
|
129
|
+
(byte4 & 127) << 28;
|
|
130
|
+
if ((byte4 & 64) !== 0) {
|
|
131
|
+
decodedValue |= -1 << 31;
|
|
132
|
+
}
|
|
133
|
+
outDecodedValues.push(decodedValue);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (readIndex >= encodedData.length) {
|
|
137
|
+
throw new Error(`Invalid LEB128 data. Last encoded byte sequence is truncated.`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
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.`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return outDecodedValues;
|
|
144
|
+
}
|
|
145
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
146
|
+
// Tests
|
|
147
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
148
|
+
export function testLeb128() {
|
|
149
|
+
const encodedBytes = [];
|
|
150
|
+
const decodedValues = [];
|
|
151
|
+
function runTest(testValue) {
|
|
152
|
+
encodedBytes.length = 0;
|
|
153
|
+
decodedValues.length = 0;
|
|
154
|
+
encodeSignedInt32sFast(testValue, encodedBytes);
|
|
155
|
+
decodeSignedInt32sFast(encodedBytes, decodedValues);
|
|
156
|
+
if (decodedValues[0] !== testValue) {
|
|
157
|
+
throw new Error(`Expected ${testValue} but got ${decodedValues[0]}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
for (let i = -(2 ** 22); i < 2 ** 22; i++) {
|
|
161
|
+
if (i % 1000000 === 0) {
|
|
162
|
+
logToStderr(i);
|
|
163
|
+
}
|
|
164
|
+
runTest(i);
|
|
165
|
+
}
|
|
166
|
+
const x = 1;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=LEB128.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LEB128.js","sourceRoot":"","sources":["../../src/utilities/LEB128.ts"],"names":[],"mappings":"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"}
|
package/docs/Options.md
CHANGED
|
@@ -149,6 +149,7 @@ Applies to CLI operation: `transcribe`, API method: `recognize`
|
|
|
149
149
|
* `whisper.autoPromptParts`: use previous part's recognized text as the prompt for the next part. Disabling this may help to prevent repetition carrying over between parts, in some cases. Defaults to `true`
|
|
150
150
|
* `whisper.maxTokensPerPart`: maximum number of tokens to decode for each audio part. Defaults to `250`
|
|
151
151
|
* `whisper.suppressRepetition`: attempt to suppress decoding of repeating token patterns. Defaults to `true`
|
|
152
|
+
* `whisper.repetitionThreshold`: minimal repetition / compressibility score to cause a part not to be auto-prompted to the next part. Defaults to `2.4`
|
|
152
153
|
* `whisper.decodeTimestampTokens`: enable/disable decoding of timestamp tokens. Setting to `false` can reduce the occurrence of hallucinations and token repetition loops, possibly due to the overall reduction in the number of tokens decoded. This has no impact on the accuracy of timestamps, since they are derived independently using cross-attention weights. However, there are cases where this can cause the model to end a part prematurely, especially in singing and less speech-like voice segments, or when there are multiple speakers. Defaults to `true`
|
|
153
154
|
* `whisper.encoderProvider`: identifier for the ONNX execution provider to use with the encoder model. Can be `cpu` or `dml` ([DirectML](https://microsoft.github.io/DirectML/)-based GPU acceleration - Windows only). In general, GPU-based encoding should be significantly faster. Defaults to `cpu`, or `dml` if available
|
|
154
155
|
* `whisper.decoderProvider`: identifier for the ONNX execution provider to use with the decoder model. Can be `cpu` or `dml` (Windows only). Using GPU acceleration for the decoder may be faster than CPU, especially for larger models, but that depends on your particular combination of CPU and GPU. Defaults to `cpu`
|
|
@@ -221,7 +222,7 @@ Applies to CLI operation: `align`, API method: `align`
|
|
|
221
222
|
* `plainText.whitespace`: determines how to process whitespace within transcript paragraphs. Can be `preserve` (leave as is), `removeLineBreaks` (convert line breaks to spaces) or `collapse` (convert runs of whitespace characters, including line breaks, to a single space character). Defaults to `collapse`
|
|
222
223
|
|
|
223
224
|
**DTW**:
|
|
224
|
-
* `dtw.granularity`: adjusts the MFCC frame width and hop size based on the profile selected. Can be set to either `
|
|
225
|
+
* `dtw.granularity`: adjusts the MFCC frame width and hop size based on the profile selected. Can be set to either `xx-low` (400ms width, 160ms hop), `x-low` (200ms width, 80ms hop), `low` (100ms width, 40ms hop), `medium` (50ms width, 20ms hop), `high` (25ms width, 10ms hop), `x-high` (20ms width, 5ms hop). For multi-pass processing, multiple granularities can be provided, like `dtw.granularity=['xx-low','medium']`. Auto-selected by default.
|
|
225
226
|
* `dtw.windowDuration`: maximum duration (in seconds) of the Sakoe-Chiba window when performing DTW alignment. Higher values consume quadratically larger amounts of memory. The estimated memory requirement is shown in the log before alignment starts. Recommended to be set to at least 10% - 20% of total audio duration. For multi-pass processing, multiple durations can be provided, like `dtw.windowDuration=[240,20]`. Auto-selected by default
|
|
226
227
|
|
|
227
228
|
**DTW-RA**:
|
package/docs/Tasklist.md
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
### Synthesis
|
|
11
11
|
|
|
12
|
-
###
|
|
12
|
+
### eSpeak
|
|
13
|
+
|
|
13
14
|
* IPA -> Kirshenbaum translation is still not completely similar to what is output by eSpeak. Also, in rare situations, it outputs characters that are not accepted by eSpeak and eSpeak errors. Investigate when that happens and how to improve on this
|
|
14
15
|
|
|
15
16
|
### Browser extension
|
|
@@ -151,8 +152,7 @@
|
|
|
151
152
|
* Show alternatives when playing in the CLI. Clear current line and rewrite already printed text for alternatives during the speech recognition process
|
|
152
153
|
|
|
153
154
|
### Recognition / Whisper
|
|
154
|
-
* Whisper's Chinese and Japanese output can be split into words in a more accurate way. Consider using a dedicated segmentation library to perform the segmentation in character sequences that have no
|
|
155
|
-
* Automatically disable using previous section recognized transcript as prompt for the next section when lots of repetition occurred in previous section
|
|
155
|
+
* Whisper's Chinese and Japanese output can be split into words in a more accurate way. Consider using a dedicated segmentation library to perform the segmentation in character sequences that have no punctuation characters to aid on guessing word boundaries
|
|
156
156
|
* Cache last model (if enough memory is available)
|
|
157
157
|
* The segment output can be used to split into segments, otherwise it is possible to try to guess using pause lengths or voice activity detection
|
|
158
158
|
* Bring back the option to use eSpeak DTW based alignment on segments, as an alternative approach
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "echogarden",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "An easy-to-use speech toolset. Includes tools for synthesis, recognition, alignment, speech translation, language detection, source separation and more.",
|
|
5
5
|
"author": "Rotem Dan",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"echogarden": "./dist/cli/CLILauncher.js"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@aws-sdk/client-polly": "^3.
|
|
59
|
-
"@aws-sdk/client-transcribe-streaming": "^3.
|
|
58
|
+
"@aws-sdk/client-polly": "^3.574.0",
|
|
59
|
+
"@aws-sdk/client-transcribe-streaming": "^3.574.0",
|
|
60
60
|
"@echogarden/espeak-ng-emscripten": "^0.1.2",
|
|
61
61
|
"@echogarden/fasttext-wasm": "^0.1.0",
|
|
62
62
|
"@echogarden/flite-wasi": "^0.1.1",
|
|
@@ -89,14 +89,14 @@
|
|
|
89
89
|
"moving-median": "^1.0.0",
|
|
90
90
|
"msgpack-lite": "^0.1.26",
|
|
91
91
|
"onnxruntime-node": "^1.17.3",
|
|
92
|
-
"openai": "^4.
|
|
92
|
+
"openai": "^4.45.0",
|
|
93
93
|
"sam-js": "^0.2.1",
|
|
94
94
|
"strip-ansi": "^7.1.0",
|
|
95
95
|
"tar": "^7.1.0",
|
|
96
96
|
"tiktoken": "^1.0.14",
|
|
97
97
|
"tinyld": "^1.3.4",
|
|
98
98
|
"ws": "^8.17.0",
|
|
99
|
-
"wtf_wikipedia": "^10.3.
|
|
99
|
+
"wtf_wikipedia": "^10.3.1"
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
102
|
"@echogarden/vosk": "^0.3.39-patched.1",
|
|
@@ -120,11 +120,11 @@
|
|
|
120
120
|
"@types/graceful-fs": "^4.1.9",
|
|
121
121
|
"@types/jsdom": "^21.1.6",
|
|
122
122
|
"@types/msgpack-lite": "^0.1.11",
|
|
123
|
-
"@types/node": "^20.12.
|
|
123
|
+
"@types/node": "^20.12.11",
|
|
124
124
|
"@types/recursive-readdir": "^2.2.4",
|
|
125
125
|
"@types/tar": "^6.1.13",
|
|
126
126
|
"@types/ws": "^8.5.10",
|
|
127
|
-
"ts-json-schema-generator": "^2.1.1",
|
|
127
|
+
"ts-json-schema-generator": "^2.1.2-next.1",
|
|
128
128
|
"typescript": "^5.4.5"
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
|
-
import { Logger } from '../utilities/Logger.js'
|
|
3
1
|
import { logToStderr } from '../utilities/Utilities.js'
|
|
4
2
|
import { AlignmentPath } from './SpeechAlignment.js'
|
|
5
3
|
|
|
@@ -11,7 +9,10 @@ export function alignDTWWindowed<T, U>(sequence1: T[], sequence2: U[], costFunct
|
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
if (sequence1.length == 0 || sequence2.length == 0) {
|
|
14
|
-
return {
|
|
12
|
+
return {
|
|
13
|
+
path: [] as AlignmentPath,
|
|
14
|
+
pathCost: 0
|
|
15
|
+
}
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
// Compute accumulated cost matrix (transposed)
|
|
@@ -38,10 +39,10 @@ function computeAccumulatedCostMatrixTransposed<T, U>(sequence1: T[], sequence2:
|
|
|
38
39
|
|
|
39
40
|
const accumulatedCostMatrixTransposed: Float32Array[] = new Array<Float32Array>(columnCount)
|
|
40
41
|
|
|
41
|
-
// Initialize window start offsets
|
|
42
|
+
// Initialize an array to store window start offsets
|
|
42
43
|
const windowStartOffsets = new Int32Array(columnCount)
|
|
43
44
|
|
|
44
|
-
// Compute matrix column by column
|
|
45
|
+
// Compute accumulated cost matrix column by column
|
|
45
46
|
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
46
47
|
// Create new column and add it to the matrix
|
|
47
48
|
const currentColumn = new Float32Array(rowCount)
|
|
@@ -65,13 +66,13 @@ function computeAccumulatedCostMatrixTransposed<T, U>(sequence1: T[], sequence2:
|
|
|
65
66
|
windowStartOffset = windowEndOffset - rowCount
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
// Store the start offset
|
|
69
|
+
// Store the start offset for this column
|
|
69
70
|
windowStartOffsets[columnIndex] = windowStartOffset
|
|
70
71
|
|
|
71
72
|
// Get target sequence1 value
|
|
72
73
|
const targetSequence1Value = sequence1[columnIndex]
|
|
73
74
|
|
|
74
|
-
// If first column, fill it only using the 'up'
|
|
75
|
+
// If this is the first column, fill it only using the 'up' neighbors
|
|
75
76
|
if (columnIndex == 0) {
|
|
76
77
|
for (let rowIndex = 1; rowIndex < rowCount; rowIndex++) {
|
|
77
78
|
const cost = costFunction(targetSequence1Value, sequence2[windowStartOffset + rowIndex])
|
|
@@ -84,11 +85,15 @@ function computeAccumulatedCostMatrixTransposed<T, U>(sequence1: T[], sequence2:
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
// If not first column
|
|
88
|
+
|
|
89
|
+
// Store the column to the left
|
|
87
90
|
const leftColumn = accumulatedCostMatrixTransposed[columnIndex - 1]
|
|
88
91
|
|
|
89
|
-
// Compute the delta between the current window
|
|
92
|
+
// Compute the delta between the current window start offset
|
|
93
|
+
// and left column's window offset
|
|
90
94
|
const windowOffsetDelta = windowStartOffset - windowStartOffsets[columnIndex - 1]
|
|
91
95
|
|
|
96
|
+
// Iterate over all rows in the window
|
|
92
97
|
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
93
98
|
// Compute the cost for current cell
|
|
94
99
|
const cost = costFunction(targetSequence1Value, sequence2[windowStartOffset + rowIndex])
|
|
@@ -115,12 +120,25 @@ function computeAccumulatedCostMatrixTransposed<T, U>(sequence1: T[], sequence2:
|
|
|
115
120
|
upAndLeftCost = leftColumn[upAndLeftRowIndex]
|
|
116
121
|
}
|
|
117
122
|
|
|
123
|
+
// Find the minimum of all neighbors
|
|
124
|
+
let minimumNeighborCost = minimumOf3(upCost, leftCost, upAndLeftCost)
|
|
125
|
+
|
|
126
|
+
// If all neighbors are infinity, then it means there is a "jump" between the window
|
|
127
|
+
// of the current column and the left column, and they don't have overlapping rows.
|
|
128
|
+
// In this case, only the cost of the current cell will be used
|
|
129
|
+
if (minimumNeighborCost === Infinity) {
|
|
130
|
+
minimumNeighborCost = 0
|
|
131
|
+
}
|
|
132
|
+
|
|
118
133
|
// Write cost + minimum neighbor cost to the current column
|
|
119
|
-
currentColumn[rowIndex] = cost +
|
|
134
|
+
currentColumn[rowIndex] = cost + minimumNeighborCost
|
|
120
135
|
}
|
|
121
136
|
}
|
|
122
137
|
|
|
123
|
-
return {
|
|
138
|
+
return {
|
|
139
|
+
accumulatedCostMatrixTransposed,
|
|
140
|
+
windowStartOffsets
|
|
141
|
+
}
|
|
124
142
|
}
|
|
125
143
|
|
|
126
144
|
function computeBestPathTransposed(accumulatedCostMatrixTransposed: Float32Array[], windowStartOffsets: Int32Array) {
|
|
@@ -129,6 +147,8 @@ function computeBestPathTransposed(accumulatedCostMatrixTransposed: Float32Array
|
|
|
129
147
|
|
|
130
148
|
const bestPath: AlignmentPath = []
|
|
131
149
|
|
|
150
|
+
// Start at the bottom right corner and find the best path
|
|
151
|
+
// towards the top left
|
|
132
152
|
let columnIndex = columnCount - 1
|
|
133
153
|
let rowIndex = rowCount - 1
|
|
134
154
|
|
|
@@ -136,19 +156,21 @@ function computeBestPathTransposed(accumulatedCostMatrixTransposed: Float32Array
|
|
|
136
156
|
const windowStartIndex = windowStartOffsets[columnIndex]
|
|
137
157
|
const windowStartDelta = columnIndex > 0 ? windowStartIndex - windowStartOffsets[columnIndex - 1] : 0
|
|
138
158
|
|
|
159
|
+
// Add the current cell to the best path
|
|
139
160
|
bestPath.push({
|
|
140
161
|
source: columnIndex,
|
|
141
162
|
dest: windowStartIndex + rowIndex
|
|
142
163
|
})
|
|
143
164
|
|
|
165
|
+
// Retrieve the cost for the 'up' (insertion) neighbor
|
|
144
166
|
const upRowIndex = rowIndex - 1
|
|
145
|
-
const upColumnIndex = columnIndex
|
|
146
167
|
let upCost = Infinity
|
|
147
168
|
|
|
148
169
|
if (upRowIndex >= 0) {
|
|
149
|
-
upCost = accumulatedCostMatrixTransposed[
|
|
170
|
+
upCost = accumulatedCostMatrixTransposed[columnIndex][upRowIndex] // insertion
|
|
150
171
|
}
|
|
151
172
|
|
|
173
|
+
// Retrieve the cost for the 'left' (deletion) neighbor
|
|
152
174
|
const leftRowIndex = rowIndex + windowStartDelta
|
|
153
175
|
const leftColumnIndex = columnIndex - 1
|
|
154
176
|
let leftCost = Infinity
|
|
@@ -157,6 +179,7 @@ function computeBestPathTransposed(accumulatedCostMatrixTransposed: Float32Array
|
|
|
157
179
|
leftCost = accumulatedCostMatrixTransposed[leftColumnIndex][leftRowIndex] // deletion
|
|
158
180
|
}
|
|
159
181
|
|
|
182
|
+
// Retrieve the cost for the 'up and left' (match) neighbor
|
|
160
183
|
const upAndLeftRowIndex = rowIndex - 1 + windowStartDelta
|
|
161
184
|
const upAndLeftColumnIndex = columnIndex - 1
|
|
162
185
|
let upAndLeftCost = Infinity
|
|
@@ -165,25 +188,42 @@ function computeBestPathTransposed(accumulatedCostMatrixTransposed: Float32Array
|
|
|
165
188
|
upAndLeftCost = accumulatedCostMatrixTransposed[upAndLeftColumnIndex][upAndLeftRowIndex] // match
|
|
166
189
|
}
|
|
167
190
|
|
|
191
|
+
// If all neighbors have a cost of infinity, it means
|
|
192
|
+
// there is a "jump" between the window for the current and previous column
|
|
168
193
|
if (upCost == Infinity && leftCost == Infinity && upAndLeftCost == Infinity) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
194
|
+
// In that case:
|
|
195
|
+
//
|
|
196
|
+
// If there are rows above
|
|
197
|
+
if (upRowIndex >= 0) {
|
|
198
|
+
// Move upward
|
|
199
|
+
rowIndex = upRowIndex
|
|
200
|
+
} else if (leftColumnIndex >= 0) {
|
|
201
|
+
// Otherwise, move to the left
|
|
202
|
+
columnIndex = leftColumnIndex
|
|
203
|
+
} else {
|
|
204
|
+
// Since we know that either columnIndex > 0 or rowIndex > 0,
|
|
205
|
+
// one of these directions must be available.
|
|
206
|
+
// This error should never happen
|
|
207
|
+
|
|
208
|
+
throw new Error(`Unexpected state: columnIndex: ${columnIndex}, rowIndex: ${rowIndex}`)
|
|
209
|
+
}
|
|
184
210
|
} else {
|
|
185
|
-
|
|
186
|
-
|
|
211
|
+
// Choose the direction with the smallest cost
|
|
212
|
+
const smallestCostDirection = argIndexOfMinimumOf3(upCost, leftCost, upAndLeftCost)
|
|
213
|
+
|
|
214
|
+
if (smallestCostDirection == 1) {
|
|
215
|
+
// Move upward
|
|
216
|
+
rowIndex = upRowIndex
|
|
217
|
+
// The upper column index stays the same
|
|
218
|
+
} else if (smallestCostDirection == 2) {
|
|
219
|
+
// Move to the left
|
|
220
|
+
rowIndex = leftRowIndex
|
|
221
|
+
columnIndex = leftColumnIndex
|
|
222
|
+
} else {
|
|
223
|
+
// Move upward and to the left
|
|
224
|
+
rowIndex = upAndLeftRowIndex
|
|
225
|
+
columnIndex = upAndLeftColumnIndex
|
|
226
|
+
}
|
|
187
227
|
}
|
|
188
228
|
}
|
|
189
229
|
|
|
@@ -38,12 +38,12 @@ export async function alignUsingDtw(
|
|
|
38
38
|
let relativeCenters: number[] | undefined
|
|
39
39
|
|
|
40
40
|
for (let passIndex = 0; passIndex < windowDurations.length; passIndex++) {
|
|
41
|
+
const granularity = granularities[passIndex]
|
|
41
42
|
const windowDuration = windowDurations[passIndex]
|
|
42
|
-
const granularity = resolveAutoGranularityIfNeeded(granularities[passIndex], rawAudioDuration)
|
|
43
43
|
|
|
44
44
|
logger.logTitledMessage(`\nStarting alignment pass ${passIndex + 1}/${windowDurations.length}`, `max window duration: ${windowDuration}s, granularity: ${granularity}`, chalk.magentaBright)
|
|
45
45
|
|
|
46
|
-
const mfccOptions = extendDefaultMfccOptions({ ...getMfccOptionsForGranularity(granularity
|
|
46
|
+
const mfccOptions = extendDefaultMfccOptions({ ...getMfccOptionsForGranularity(granularity), zeroFirstCoefficient: true }) as MfccOptions
|
|
47
47
|
|
|
48
48
|
framesPerSecond = 1 / mfccOptions.hopDuration!
|
|
49
49
|
|
|
@@ -67,7 +67,7 @@ export async function alignUsingDtw(
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
logger.start('Align MFCC features using DTW')
|
|
70
|
+
logger.start('Align reference and source MFCC features using DTW')
|
|
71
71
|
const dtwWindowLength = Math.floor(windowDuration * framesPerSecond)
|
|
72
72
|
|
|
73
73
|
let centerIndexes: number[] | undefined
|
|
@@ -458,7 +458,7 @@ export async function createAlignmentReferenceUsingEspeakForFragments(fragments:
|
|
|
458
458
|
progressLogger.start("Load espeak module")
|
|
459
459
|
const Espeak = await import("../synthesis/EspeakTTS.js")
|
|
460
460
|
|
|
461
|
-
progressLogger.start("
|
|
461
|
+
progressLogger.start("Synthesize alignment reference with eSpeak")
|
|
462
462
|
|
|
463
463
|
const result = await Espeak.synthesizeFragments(fragments, espeakOptions)
|
|
464
464
|
|
|
@@ -476,7 +476,7 @@ export async function createAlignmentReferenceUsingEspeakForFragments(fragments:
|
|
|
476
476
|
export async function createAlignmentReferenceUsingEspeak(transcript: string, language: string, plaintextOptions?: API.PlainTextOptions, customLexiconPaths?: string[], insertSeparators?: boolean) {
|
|
477
477
|
const logger = new Logger()
|
|
478
478
|
|
|
479
|
-
logger.start('
|
|
479
|
+
logger.start('Synthesize alignment reference with eSpeak')
|
|
480
480
|
|
|
481
481
|
const synthesisOptions: API.SynthesisOptions = {
|
|
482
482
|
engine: 'espeak',
|
|
@@ -544,25 +544,9 @@ function getMappedFrameIndexForPath(referenceFrameIndex: number, compactedPath:
|
|
|
544
544
|
return mappedFrameIndex
|
|
545
545
|
}
|
|
546
546
|
|
|
547
|
-
function
|
|
548
|
-
if (granularity != 'auto') {
|
|
549
|
-
return granularity
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
if (audioDuration < 60) {
|
|
553
|
-
return 'high'
|
|
554
|
-
} else if (audioDuration < 60 * 10) {
|
|
555
|
-
return 'medium'
|
|
556
|
-
} else {
|
|
557
|
-
return 'low'
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
function getMfccOptionsForGranularity(granularity: DtwGranularity, audioDuration: number) {
|
|
547
|
+
function getMfccOptionsForGranularity(granularity: DtwGranularity) {
|
|
562
548
|
let mfccOptions: MfccOptions
|
|
563
549
|
|
|
564
|
-
granularity = resolveAutoGranularityIfNeeded(granularity, audioDuration)
|
|
565
|
-
|
|
566
550
|
if (granularity == 'xx-low') {
|
|
567
551
|
mfccOptions = { windowDuration: 0.400, hopDuration: 0.160, fftOrder: 8192 }
|
|
568
552
|
} else if (granularity == 'x-low') {
|
|
@@ -595,4 +579,4 @@ export type CompactedPathEntry = {
|
|
|
595
579
|
first: number, last: number
|
|
596
580
|
}
|
|
597
581
|
|
|
598
|
-
export type DtwGranularity = '
|
|
582
|
+
export type DtwGranularity = 'xx-low' | 'x-low' | 'low' | 'medium' | 'high' | 'x-high'
|