echogarden 2.7.0 → 2.8.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 (110) hide show
  1. package/data/lexicons/heteronyms.en.json +6 -2
  2. package/data/lexicons/words.en.json +389 -21
  3. package/dist/alignment/SemanticTextAlignment.js +6 -7
  4. package/dist/alignment/SemanticTextAlignment.js.map +1 -1
  5. package/dist/api/Alignment.js +2 -2
  6. package/dist/api/Alignment.js.map +1 -1
  7. package/dist/api/Recognition.js +2 -2
  8. package/dist/api/Recognition.js.map +1 -1
  9. package/dist/api/SpeechTranslation.js +2 -2
  10. package/dist/api/SpeechTranslation.js.map +1 -1
  11. package/dist/api/Synthesis.js +7 -7
  12. package/dist/api/Synthesis.js.map +1 -1
  13. package/dist/api/TimelineTranslationAlignment.js +2 -2
  14. package/dist/api/TimelineTranslationAlignment.js.map +1 -1
  15. package/dist/api/TranslationAlignment.js +2 -2
  16. package/dist/api/TranslationAlignment.js.map +1 -1
  17. package/dist/audio/AudioPlayer.js +2 -2
  18. package/dist/audio/AudioPlayer.js.map +1 -1
  19. package/dist/audio/AudioUtilities.d.ts +1 -1
  20. package/dist/cli/CLI.js +4 -4
  21. package/dist/cli/CLI.js.map +1 -1
  22. package/dist/denoising/RNNoise.js +5 -5
  23. package/dist/denoising/RNNoise.js.map +1 -1
  24. package/dist/dsp/FFT.js +13 -19
  25. package/dist/dsp/FFT.js.map +1 -1
  26. package/dist/dsp/Rubberband.js +5 -5
  27. package/dist/dsp/Rubberband.js.map +1 -1
  28. package/dist/dsp/Sonic.js +6 -6
  29. package/dist/dsp/Sonic.js.map +1 -1
  30. package/dist/dsp/SpeexResampler.js +11 -11
  31. package/dist/dsp/SpeexResampler.js.map +1 -1
  32. package/dist/nlp/EspeakPhonemizer.js +1 -1
  33. package/dist/nlp/EspeakPhonemizer.js.map +1 -1
  34. package/dist/nlp/Segmentation.d.ts +13 -10
  35. package/dist/nlp/Segmentation.js +131 -108
  36. package/dist/nlp/Segmentation.js.map +1 -1
  37. package/dist/nlp/TextNormalizer.js +74 -42
  38. package/dist/nlp/TextNormalizer.js.map +1 -1
  39. package/dist/recognition/AmazonTranscribeSTT.js +2 -2
  40. package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
  41. package/dist/recognition/SileroSTT.js +2 -2
  42. package/dist/recognition/SileroSTT.js.map +1 -1
  43. package/dist/recognition/WhisperSTT.js +4 -16
  44. package/dist/recognition/WhisperSTT.js.map +1 -1
  45. package/dist/subtitles/Subtitles.js +52 -7
  46. package/dist/subtitles/Subtitles.js.map +1 -1
  47. package/dist/synthesis/ElevenLabsTTS.js +11 -10
  48. package/dist/synthesis/ElevenLabsTTS.js.map +1 -1
  49. package/dist/synthesis/EspeakTTS.js +8 -8
  50. package/dist/synthesis/EspeakTTS.js.map +1 -1
  51. package/dist/synthesis/KokoroTTS.js +21 -10
  52. package/dist/synthesis/KokoroTTS.js.map +1 -1
  53. package/dist/synthesis/SvoxPicoTTS.js +24 -23
  54. package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
  55. package/dist/text-translation/DeepLTextTranslation.js +4 -3
  56. package/dist/text-translation/DeepLTextTranslation.js.map +1 -1
  57. package/dist/text-translation/NLLBTextTranslation.js +7 -6
  58. package/dist/text-translation/NLLBTextTranslation.js.map +1 -1
  59. package/dist/utilities/StringUtilities.d.ts +1 -1
  60. package/dist/utilities/StringUtilities.js +5 -5
  61. package/dist/utilities/StringUtilities.js.map +1 -1
  62. package/dist/utilities/Timeline.d.ts +2 -3
  63. package/dist/utilities/Timeline.js +99 -146
  64. package/dist/utilities/Timeline.js.map +1 -1
  65. package/dist/utilities/WikipediaReader.js +3 -3
  66. package/dist/utilities/WikipediaReader.js.map +1 -1
  67. package/dist/voice-activity-detection/WebRtcVAD.js +4 -4
  68. package/dist/voice-activity-detection/WebRtcVAD.js.map +1 -1
  69. package/docs/Tasklist.md +1 -6
  70. package/package.json +13 -11
  71. package/src/alignment/SemanticTextAlignment.ts +6 -7
  72. package/src/api/Alignment.ts +2 -2
  73. package/src/api/Recognition.ts +2 -2
  74. package/src/api/SpeechTranslation.ts +2 -2
  75. package/src/api/Synthesis.ts +7 -7
  76. package/src/api/TimelineTranslationAlignment.ts +2 -2
  77. package/src/api/TranslationAlignment.ts +2 -2
  78. package/src/audio/AudioPlayer.ts +2 -2
  79. package/src/cli/CLI.ts +4 -4
  80. package/src/denoising/RNNoise.ts +5 -5
  81. package/src/dsp/FFT.ts +22 -19
  82. package/src/dsp/Rubberband.ts +5 -5
  83. package/src/dsp/Sonic.ts +6 -6
  84. package/src/dsp/SpeexResampler.ts +11 -11
  85. package/src/nlp/EspeakPhonemizer.ts +1 -1
  86. package/src/nlp/Segmentation.ts +148 -113
  87. package/src/nlp/TextNormalizer.ts +94 -52
  88. package/src/recognition/AmazonTranscribeSTT.ts +2 -2
  89. package/src/recognition/SileroSTT.ts +2 -2
  90. package/src/recognition/WhisperSTT.ts +4 -18
  91. package/src/subtitles/Subtitles.ts +69 -8
  92. package/src/synthesis/ElevenLabsTTS.ts +12 -11
  93. package/src/synthesis/EspeakTTS.ts +9 -8
  94. package/src/synthesis/KokoroTTS.ts +24 -12
  95. package/src/synthesis/SvoxPicoTTS.ts +26 -23
  96. package/src/text-translation/DeepLTextTranslation.ts +4 -3
  97. package/src/text-translation/NLLBTextTranslation.ts +8 -6
  98. package/src/typings/Fillers.d.ts +0 -16
  99. package/src/utilities/StringUtilities.ts +5 -6
  100. package/src/utilities/Timeline.ts +105 -169
  101. package/src/utilities/WikipediaReader.ts +3 -3
  102. package/src/voice-activity-detection/WebRtcVAD.ts +5 -4
  103. package/dist/nlp/CompromiseNLP.d.ts +0 -15
  104. package/dist/nlp/CompromiseNLP.js +0 -79
  105. package/dist/nlp/CompromiseNLP.js.map +0 -1
  106. package/dist/utilities/WasmMemoryManager.d.ts +0 -153
  107. package/dist/utilities/WasmMemoryManager.js +0 -440
  108. package/dist/utilities/WasmMemoryManager.js.map +0 -1
  109. package/src/nlp/CompromiseNLP.ts +0 -119
  110. package/src/utilities/WasmMemoryManager.ts +0 -566
@@ -1,7 +1,8 @@
1
+ import { addMissingPunctuationWordsToWordSequence, segmentWordSequence, WordSequence } from '@echogarden/text-segmentation'
1
2
  import { ParagraphBreakType, WhitespaceProcessing } from '../api/Common.js'
2
- import { applyWhitespaceProcessing, isWord, isWordOrSymbolWord, splitToParagraphs, splitToSentences, splitToWords } from '../nlp/Segmentation.js'
3
+ import { isWord, isWordOrSymbolWord, splitToParagraphs, splitToWords } from '../nlp/Segmentation.js'
3
4
  import { deepClone } from './ObjectUtilities.js'
4
- import { getUTF32Chars, splitAndPreserveSeparators } from './StringUtilities.js'
5
+ import { getUTF32Chars } from './StringUtilities.js'
5
6
  import { roundToDigits } from './Utilities.js'
6
7
 
7
8
  export function addTimeOffsetToTimeline(targetTimeline: Timeline, timeOffset: number) {
@@ -62,199 +63,161 @@ export function roundTimelineProperties(targetTimeline: Timeline, decimalDigits
62
63
  return roundedTimeline
63
64
  }
64
65
 
65
- export async function wordTimelineToSegmentSentenceTimeline(wordTimeline: Timeline, transcript: string, language: string, paragraphBreaks: ParagraphBreakType = 'double', whitespace: WhitespaceProcessing = 'collapse') {
66
- let segments: string[][] = []
66
+ export async function wordTimelineToSegmentSentenceTimeline(wordTimelineWithOffsets: Timeline, transcript: string, language: string, paragraphBreaks: ParagraphBreakType = 'double', whitespace: WhitespaceProcessing = 'collapse') {
67
+ const wordSequence = new WordSequence()
67
68
 
68
- {
69
- // Ensure word entries with words that include potential sentence ending characters,
70
- // like '.', '?' or '!', aren't causing the sentence segmentation
71
- // to identify them as sentence breaks.
72
- const maskedTranscript = replaceSentenceEndersWithinWordsWithMaskingCharacter(transcript, wordTimeline, '_')
73
-
74
- // Split to segments and sentences, based on the masked transcript,
75
- // don't apply any whitespace processing yet.
76
- let paragraphs: string[]
77
-
78
- if (paragraphBreaks === 'single') {
79
- paragraphs = splitAndPreserveSeparators(maskedTranscript, /(\r?\n)+/g)
80
- } else if (paragraphBreaks === 'double') {
81
- paragraphs = splitAndPreserveSeparators(maskedTranscript, /(\r?\n)(\r?\n)+/g)
82
- } else {
83
- throw new Error(`Invalid paragraph break type: '${paragraphBreaks}'`)
84
- }
85
-
86
- const maskedSegments = paragraphs.map(paragraph => splitToSentences(paragraph, language))
87
-
88
- // Restore the sentence text the original text, using the original transcript,
89
- // and apply whitespace processing to each sentence.
90
- let offset = 0
69
+ for (const wordEntry of wordTimelineWithOffsets) {
70
+ const wordStartOffset = wordEntry.startOffsetUtf16!
71
+ const wordEndOffset = wordEntry.endOffsetUtf16!
91
72
 
92
- for (const segment of maskedSegments) {
93
- const newSegment: string[] = []
73
+ const isPunctuation = !isWordOrSymbolWord(wordEntry.text)
94
74
 
95
- for (let sentenceIndex = 0; sentenceIndex < segment.length; sentenceIndex++) {
96
- const sentence = segment[sentenceIndex]
97
- const sentenceLength = sentence.length
98
-
99
- const restoredSentence = transcript.substring(offset, offset + sentenceLength)
100
- const restoredAndProcessedSentence = applyWhitespaceProcessing(restoredSentence, whitespace).trim()
101
-
102
- if (restoredAndProcessedSentence.length > 0) {
103
- newSegment.push(restoredAndProcessedSentence)
104
- }
75
+ wordSequence.addWord(wordEntry.text, wordStartOffset, isPunctuation)
76
+ }
105
77
 
106
- offset += sentenceLength
107
- }
78
+ const { wordSequenceWithPunctuation, originalWordsReverseMapping } = addMissingPunctuationWordsToWordSequence(wordSequence, transcript)
108
79
 
109
- segments.push(newSegment)
110
- }
80
+ const segmentedWordSequence = await segmentWordSequence(wordSequenceWithPunctuation)
111
81
 
112
- segments = segments.filter(segment => segment.length > 0)
113
- }
82
+ const paragraphs = splitToParagraphs(transcript, paragraphBreaks, whitespace)
83
+ const sentenceIndexesForParagraph = paragraphs.map(_ => [] as number[])
114
84
 
115
- // Create a new text based on the processed sentences, new segment and sentence timeline,
116
- // and store mapping between character indexes and the corresponding sentence they belong to.
117
- let text = ''
118
- const charIndexToSentenceEntryMapping: TimelineEntry[] = []
85
+ {
86
+ let sentenceIndex = 0
87
+ let charOffset = 0
119
88
 
120
- const segmentTimeline: Timeline = []
89
+ for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
90
+ const paragraph = paragraphs[paragraphIndex]
121
91
 
122
- for (const segment of segments) {
123
- const sentencesInSegment: Timeline = []
92
+ const paragraphStartOffset = charOffset
93
+ const paragraphEndOffset = paragraphStartOffset + paragraph.length
124
94
 
125
- const segmentEntry: TimelineEntry = {
126
- type: 'segment',
127
- text: '',
128
- startTime: -1,
129
- endTime: -1,
130
- timeline: sentencesInSegment
131
- }
95
+ while (sentenceIndex < segmentedWordSequence.sentences.length) {
96
+ const sentenceEntry = segmentedWordSequence.sentences[sentenceIndex]
97
+ const sentenceStartOffset = sentenceEntry.charRange.start
98
+ const sentenceEndOffset = sentenceEntry.charRange.end
132
99
 
133
- for (const sentence of segment) {
134
- const sentenceEntry: TimelineEntry = {
135
- type: 'sentence',
136
- text: sentence,
137
- startTime: -1,
138
- endTime: -1,
139
- timeline: []
100
+ if (sentenceStartOffset < paragraphEndOffset) {
101
+ sentenceIndexesForParagraph[paragraphIndex].push(sentenceIndex)
102
+ sentenceIndex++
103
+ } else {
104
+ break
105
+ }
140
106
  }
141
107
 
142
- for (const char of sentence + ' ') {
143
- text += char
144
- charIndexToSentenceEntryMapping.push(sentenceEntry)
108
+ if (sentenceIndex === segmentedWordSequence.sentences.length) {
109
+ break
145
110
  }
146
111
 
147
- sentencesInSegment.push(sentenceEntry)
112
+ charOffset += paragraph.length
148
113
  }
149
-
150
- segmentTimeline.push(segmentEntry)
151
114
  }
152
115
 
153
- // Add the word entries to their corresponding sentence timelines
154
- {
155
- let wordSearchStartOffset = 0
156
-
157
- for (let wordIndex = 0; wordIndex < wordTimeline.length; wordIndex++) {
158
- const wordEntry = wordTimeline[wordIndex]
159
- const wordText = wordEntry.text
160
-
161
- if (!isWordOrSymbolWord(wordText)) {
162
- continue
163
- }
164
-
165
- const indexOfWordInText = text.indexOf(wordText, wordSearchStartOffset)
166
-
167
- if (indexOfWordInText == -1) {
168
- throw new Error(`Couldn't find the word '${wordText}' in the text at start position ${wordSearchStartOffset}`)
169
- }
116
+ const segmentTimeline: Timeline = []
117
+ let wordIndex = 0
170
118
 
171
- const targetSentenceEntry = charIndexToSentenceEntryMapping[indexOfWordInText]
172
- targetSentenceEntry.timeline!.push(deepClone(wordEntry))
119
+ for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
120
+ const paragraph = paragraphs[paragraphIndex]
121
+ const sentencesIndexes = sentenceIndexesForParagraph[paragraphIndex]
122
+ const sentenceEntries = sentencesIndexes.map(index => segmentedWordSequence.sentences[index])
173
123
 
174
- wordSearchStartOffset = indexOfWordInText + wordText.length
175
- }
176
- }
124
+ const sentenceTimeline: Timeline = []
177
125
 
178
- // Produce a new segment/sentence timeline with rewritten entries,
179
- // that match the assigned words.
180
- const newSegmentTimeline: Timeline = []
126
+ for (const sentenceEntry of sentenceEntries) {
127
+ const wordTimeline: Timeline = []
181
128
 
182
- for (const segmentEntry of segmentTimeline) {
183
- const oldSentenceTimeline = segmentEntry.timeline!
129
+ for (const _ of sentenceEntry.words.entries) {
130
+ const originalWordIndex = originalWordsReverseMapping.get(wordIndex)
184
131
 
185
- const newSentenceTimeline: Timeline = []
132
+ if (originalWordIndex !== undefined) {
133
+ const wordTimelineEntry = wordTimelineWithOffsets[originalWordIndex]
186
134
 
187
- for (const sentenceEntry of oldSentenceTimeline) {
188
- const wordTimeline = sentenceEntry.timeline
135
+ wordTimeline.push(wordTimelineEntry)
136
+ }
189
137
 
190
- if (!wordTimeline || wordTimeline.length === 0) {
191
- continue
138
+ wordIndex += 1
192
139
  }
193
140
 
194
- sentenceEntry.startTime = wordTimeline[0].startTime
195
- sentenceEntry.endTime = wordTimeline[wordTimeline.length - 1].endTime
141
+ const sentenceTimelineEntry: TimelineEntry = {
142
+ type: 'sentence',
143
+ text: sentenceEntry.text,
144
+ startTime: wordTimeline[0]?.startTime,
145
+ endTime: wordTimeline[wordTimeline.length - 1]?.endTime,
196
146
 
197
- newSentenceTimeline.push(sentenceEntry)
198
- }
147
+ timeline: wordTimeline,
148
+ }
199
149
 
200
- if (newSentenceTimeline.length === 0) {
201
- continue
150
+ sentenceTimeline.push(sentenceTimelineEntry)
202
151
  }
203
152
 
204
- segmentEntry.text = newSentenceTimeline.map(sentenceEntry => sentenceEntry.text).join(' ')
153
+ const segmentTimelineEntry: TimelineEntry = {
154
+ type: 'segment',
155
+ text: paragraph,
156
+ startTime: sentenceTimeline[0]?.startTime,
157
+ endTime: sentenceTimeline[sentenceTimeline.length - 1]?.endTime,
205
158
 
206
- segmentEntry.startTime = newSentenceTimeline[0].startTime
207
- segmentEntry.endTime = newSentenceTimeline[newSentenceTimeline.length - 1].endTime
159
+ timeline: sentenceTimeline,
160
+ }
208
161
 
209
- newSegmentTimeline.push(segmentEntry)
162
+ segmentTimeline.push(segmentTimelineEntry)
210
163
  }
211
164
 
212
- return { segmentTimeline: newSegmentTimeline }
165
+ return { segmentTimeline }
213
166
  }
214
167
 
215
- export function addWordTextOffsetsToTimeline(timeline: Timeline, text: string, currentOffset = 0) {
216
- const { mapping } = getUTF32Chars(text)
168
+ export function addWordTextOffsetsToTimelineInPlace(timeline: Timeline, text: string) {
169
+ const { utf16To32Mapping } = getUTF32Chars(text)
217
170
 
218
- for (const entry of timeline) {
219
- if (entry.type == 'word') {
220
- let word = entry.text
171
+ let currentOffset = 0
221
172
 
222
- word = word.trim().replaceAll(/\s+/g, ' ')
173
+ function processTimeline(timeline: Timeline) {
174
+ let lastEndOffset = 0
223
175
 
224
- const wordParts = word.split(' ')
176
+ for (const entry of timeline) {
177
+ if (entry.type === 'word') {
178
+ let word = entry.text
225
179
 
226
- let startOffset: number | undefined
227
- let endOffset: number | undefined
180
+ word = word.trim().replaceAll(/\s+/g, ' ')
228
181
 
229
- for (let i = 0; i < wordParts.length; i++) {
230
- let wordPart = wordParts[i]
182
+ const wordParts = word.split(' ')
231
183
 
232
- let wordPartOffset = text.indexOf(wordPart, currentOffset)
184
+ let startOffset: number | undefined
185
+ let endOffset: number | undefined
233
186
 
234
- if (wordPartOffset == -1) {
235
- continue
236
- }
187
+ for (let i = 0; i < wordParts.length; i++) {
188
+ const wordPart = wordParts[i]
189
+
190
+ const wordPartOffset = text.indexOf(wordPart, currentOffset)
191
+
192
+ if (wordPartOffset === -1) {
193
+ continue
194
+ }
237
195
 
238
- currentOffset = wordPartOffset + wordParts[i].length
196
+ currentOffset = wordPartOffset + wordParts[i].length
239
197
 
240
- if (i == 0) {
241
- startOffset = wordPartOffset
198
+ if (i === 0) {
199
+ startOffset = wordPartOffset
200
+ }
201
+
202
+ endOffset = currentOffset
242
203
  }
243
204
 
244
- endOffset = currentOffset
245
- }
205
+ entry.startOffsetUtf16 = startOffset ?? lastEndOffset
206
+ entry.endOffsetUtf16 = endOffset ?? lastEndOffset
246
207
 
247
- entry.startOffsetUtf16 = startOffset
248
- entry.endOffsetUtf16 = endOffset
208
+ entry.startOffsetUtf32 = utf16To32Mapping[entry.startOffsetUtf16]
209
+ entry.endOffsetUtf32 = utf16To32Mapping[entry.endOffsetUtf16]
249
210
 
250
- entry.startOffsetUtf32 = startOffset != undefined ? mapping[startOffset] : undefined
251
- entry.endOffsetUtf32 = endOffset != undefined ? mapping[endOffset] : undefined
252
- } else if (entry.timeline) {
253
- currentOffset = addWordTextOffsetsToTimeline(entry.timeline, text, currentOffset)
211
+ if (endOffset !== undefined) {
212
+ lastEndOffset = endOffset
213
+ }
214
+ } else if (entry.timeline) {
215
+ processTimeline(entry.timeline)
216
+ }
254
217
  }
255
218
  }
256
219
 
257
- return currentOffset
220
+ return processTimeline(timeline)
258
221
  }
259
222
 
260
223
  function replaceSentenceEndersWithinWordsWithMaskingCharacter(transcript: string, wordTimeline: Timeline, maskingCharacter: string) {
@@ -344,30 +307,3 @@ export type TimelineEntry = {
344
307
  }
345
308
 
346
309
  export type Timeline = TimelineEntry[]
347
-
348
- ////
349
-
350
- export async function testTimelineFix() {
351
- let transcript = 'Hello world how are you? Do you want to play chess?'
352
- const words = (await splitToWords(transcript, 'en')).filter(word => word.trim() !== '')
353
-
354
- let wordTimeline: Timeline = words.map(wordText => ({
355
- type: 'word',
356
-
357
- text: wordText,
358
-
359
- startTime: 0,
360
- endTime: 0,
361
- }))
362
-
363
- addWordTextOffsetsToTimeline(wordTimeline, transcript)
364
-
365
- wordTimeline[1].text = 'wor.d'
366
- wordTimeline[8].text = 'wa.t'
367
-
368
- transcript = transcript.replace('world', 'wor.d').replace('want', 'wa.t')
369
-
370
- const result = await wordTimelineToSegmentSentenceTimeline(wordTimeline, transcript, 'en')
371
-
372
- const x = 1
373
- }
@@ -1,4 +1,4 @@
1
- import { splitToParagraphs, wordCharacterPattern } from '../nlp/Segmentation.js'
1
+ import { splitToParagraphs, wordCharacterRegExp } from '../nlp/Segmentation.js'
2
2
  import { Logger } from './Logger.js'
3
3
 
4
4
  export async function parseWikipediaArticle(articleName: string, language: string) {
@@ -20,7 +20,7 @@ export async function parseWikipediaArticle(articleName: string, language: strin
20
20
  for (const section of sections) {
21
21
  const sectionTitle = section.title()
22
22
 
23
- if (wordCharacterPattern.test(sectionTitle)) {
23
+ if (wordCharacterRegExp.test(sectionTitle)) {
24
24
  sectionsText.push(sectionTitle)
25
25
  }
26
26
 
@@ -29,7 +29,7 @@ export async function parseWikipediaArticle(articleName: string, language: strin
29
29
  for (const paragraph of sectionParagraphs) {
30
30
  const paragraphText = paragraph
31
31
 
32
- if (wordCharacterPattern.test(paragraphText)) {
32
+ if (wordCharacterRegExp.test(paragraphText)) {
33
33
  sectionsText.push(paragraphText)
34
34
  }
35
35
  }
@@ -1,6 +1,7 @@
1
1
  import * as AudioBufferConversion from '../audio/AudioBufferConversion.js'
2
2
  import { RawAudio } from '../audio/AudioUtilities.js'
3
- import { WasmMemoryManager } from '../utilities/WasmMemoryManager.js'
3
+
4
+ import { wrapEmscriptenModuleHeap } from 'wasm-heap-manager'
4
5
 
5
6
  export async function detectVoiceActivity(rawAudio: RawAudio, frameDuration: 10 | 20 | 30 = 10, mode: 0 | 1 | 2 | 3 = 0) {
6
7
  if (rawAudio.sampleRate != 16000) {
@@ -15,7 +16,7 @@ export async function detectVoiceActivity(rawAudio: RawAudio, frameDuration: 10
15
16
  export async function fvad(samples: Int16Array, sampleRate: number, frameDuration: 10 | 20 | 30, mode: 0 | 1 | 2 | 3) {
16
17
  const m = await getFvadInstance()
17
18
 
18
- const wasmMemory = new WasmMemoryManager(m)
19
+ const wasmHeap = wrapEmscriptenModuleHeap(m)
19
20
 
20
21
  const fvad_new = m._fvad_new
21
22
  const fvad_free = m._fvad_free
@@ -39,7 +40,7 @@ export async function fvad(samples: Int16Array, sampleRate: number, frameDuratio
39
40
  }
40
41
 
41
42
  const frameSampleCount = Math.floor(sampleRate * (frameDuration / 1000))
42
- const frameSamplesRef = wasmMemory.allocInt16Array(frameSampleCount)
43
+ const frameSamplesRef = wasmHeap.allocInt16Array(frameSampleCount)
43
44
 
44
45
  const result = []
45
46
 
@@ -59,7 +60,7 @@ export async function fvad(samples: Int16Array, sampleRate: number, frameDuratio
59
60
  }
60
61
 
61
62
  fvad_free(instancePtr)
62
- wasmMemory.freeAll()
63
+ wasmHeap.freeAll()
63
64
 
64
65
  return result
65
66
  }
@@ -1,15 +0,0 @@
1
- import { Lexicon } from './Lexicon.js';
2
- export declare function parse(text: string): Promise<CompromiseParsedDocument>;
3
- export declare function tryMatchInLexicons(term: CompromiseParsedTerm, lexicons: Lexicon[], espeakVoice: string): string[] | undefined;
4
- export declare function tryMatchInLexicon(term: CompromiseParsedTerm, lexicon: Lexicon, espeakVoice: string): string[] | undefined;
5
- export type CompromiseParsedDocument = CompromiseParsedSentence[];
6
- export type CompromiseParsedSentence = CompromiseParsedTerm[];
7
- export type CompromiseParsedTerm = {
8
- text: string;
9
- pos: string;
10
- tags: string[];
11
- preText: string;
12
- postText: string;
13
- startOffset: number;
14
- endOffset: number;
15
- };
@@ -1,79 +0,0 @@
1
- import { getShortLanguageCode } from '../utilities/Locale.js';
2
- import { logToStderr } from '../utilities/Utilities.js';
3
- const log = logToStderr;
4
- export async function parse(text) {
5
- const { default: nlp } = await import('compromise');
6
- const doc = nlp(text);
7
- doc.compute('penn');
8
- const jsonDoc = doc.json({ offset: true });
9
- //log(jsonDoc)
10
- const result = jsonDoc.map(sentence => {
11
- const terms = sentence.terms;
12
- const parsedSentence = [];
13
- for (let termIndex = 0; termIndex < terms.length; termIndex++) {
14
- const term = terms[termIndex];
15
- const parsedTerm = {
16
- text: term.text,
17
- pos: term.penn,
18
- tags: term.tags,
19
- preText: term.pre,
20
- postText: term.post,
21
- startOffset: term.offset.start,
22
- endOffset: term.offset.start + term.offset.length
23
- };
24
- if (parsedTerm.text == '') {
25
- if (parsedSentence.length > 0) {
26
- parsedSentence[parsedSentence.length - 1].postText += parsedTerm.preText + parsedTerm.postText;
27
- }
28
- }
29
- else if (parsedTerm.tags.includes('Abbreviation') && parsedTerm.postText.startsWith('.')) {
30
- parsedTerm.text += '.';
31
- parsedTerm.endOffset += 1;
32
- parsedSentence.push(parsedTerm);
33
- }
34
- else {
35
- parsedSentence.push(parsedTerm);
36
- }
37
- }
38
- return parsedSentence;
39
- });
40
- //log(result)
41
- return result;
42
- }
43
- export function tryMatchInLexicons(term, lexicons, espeakVoice) {
44
- const reversedLexicons = [...lexicons].reverse(); // Give precedence to later lexicons
45
- for (const lexicon of reversedLexicons) {
46
- const match = tryMatchInLexicon(term, lexicon, espeakVoice);
47
- if (match) {
48
- return match;
49
- }
50
- }
51
- return undefined;
52
- }
53
- export function tryMatchInLexicon(term, lexicon, espeakVoice) {
54
- const shortLanguageCode = getShortLanguageCode(espeakVoice);
55
- const lexiconForLanguage = lexicon[shortLanguageCode];
56
- if (!lexiconForLanguage) {
57
- return undefined;
58
- }
59
- const termText = term.text;
60
- const lowerCaseTermText = termText.toLocaleLowerCase();
61
- let entry = lexiconForLanguage[lowerCaseTermText];
62
- if (!entry) {
63
- return undefined;
64
- }
65
- if (!Array.isArray(entry)) {
66
- entry = [entry];
67
- }
68
- for (const substitutionEntry of entry) {
69
- if (!substitutionEntry.pos || substitutionEntry.pos.includes(term.pos)) {
70
- const substitutionPhonemesText = substitutionEntry?.pronunciation?.espeak?.[espeakVoice];
71
- if (substitutionPhonemesText) {
72
- const substitutionPhonemes = substitutionPhonemesText.split(/ +/g);
73
- return substitutionPhonemes;
74
- }
75
- }
76
- }
77
- return undefined;
78
- }
79
- //# sourceMappingURL=CompromiseNLP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CompromiseNLP.js","sourceRoot":"","sources":["../../src/nlp/CompromiseNLP.ts"],"names":[],"mappings":"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"}
@@ -1,153 +0,0 @@
1
- import { TypedArray } from "../typings/TypedArray.js";
2
- export declare class WasmMemoryManager {
3
- wasmModule: any;
4
- private wasmAlloc;
5
- private wasmFree;
6
- private allocatedReferences;
7
- constructor(wasmModule: any, options?: WasmMemoryManagerOptions);
8
- allocInt8(): Int8Ref;
9
- wrapInt8(address: number): Int8Ref;
10
- allocUint8(): Uint8Ref;
11
- wrapUint8(address: number): Uint8Ref;
12
- allocInt16(): Int16Ref;
13
- wrapInt16(address: number): Int16Ref;
14
- allocUint16(): Uint16Ref;
15
- wrapUint16(address: number): Uint16Ref;
16
- allocInt32(): Int32Ref;
17
- wrapInt32(address: number): Int32Ref;
18
- allocUint32(): Uint32Ref;
19
- wrapUint32(address: number): Uint32Ref;
20
- allocPointer(): PointerRef;
21
- wrapPointer(address: number): PointerRef;
22
- allocFloat32(): Float64Ref;
23
- wrapFloat32(address: number): Float32Ref;
24
- allocFloat64(): Float64Ref;
25
- wrapFloat64(address: number): Float64Ref;
26
- allocInt8Array(length: number): Int8ArrayRef;
27
- wrapInt8Array(address: number, length: number): Int8ArrayRef;
28
- allocUint8Array(length: number): Uint8ArrayRef;
29
- wrapUint8Array(address: number, length: number): Uint8ArrayRef;
30
- allocInt16Array(length: number): Int16ArrayRef;
31
- wrapInt16Array(address: number, length: number): Int16ArrayRef;
32
- allocUint16Array(length: number): Uint16ArrayRef;
33
- wrapUint16Array(address: number, length: number): Uint16ArrayRef;
34
- allocInt32Array(length: number): Int32ArrayRef;
35
- wrapInt32Array(address: number, length: number): Int32ArrayRef;
36
- allocUint32Array(length: number): Uint32ArrayRef;
37
- wrapUint32Array(address: number, length: number): Uint32ArrayRef;
38
- allocFloat32Array(length: number): Float32ArrayRef;
39
- wrapFloat32Array(address: number, length: number): Float32ArrayRef;
40
- allocFloat64Array(length: number): Float64ArrayRef;
41
- wrapFloat64Array(address: number, length: number): Float64ArrayRef;
42
- allocNullTerminatedUtf8String(str: string): Uint8ArrayRef;
43
- wrapNullTerminatedUtf8String(address: number): NullTerminatedUtf8StringRef;
44
- private alloc;
45
- free(wasmReference: WasmRef): void;
46
- freeAll(): void;
47
- detach<T extends WasmRef>(wasmReference: T): T;
48
- }
49
- declare abstract class ValueRef<T extends number | string> {
50
- protected ptr: number;
51
- private readonly manager;
52
- protected get module(): any;
53
- constructor(ptr: number, manager: WasmMemoryManager);
54
- get value(): T;
55
- set value(newValue: T);
56
- abstract getValue(): T;
57
- abstract setValue(newValue: T): void;
58
- get address(): number;
59
- clear(): this;
60
- free(): void;
61
- detach(): this;
62
- clearAddress(): void;
63
- get isFreed(): boolean;
64
- protected assertNotFreed(): void;
65
- }
66
- export declare class Int8Ref extends ValueRef<number> {
67
- getValue(): number;
68
- setValue(newValue: number): void;
69
- }
70
- export declare class Uint8Ref extends ValueRef<number> {
71
- getValue(): number;
72
- setValue(newValue: number): void;
73
- }
74
- export declare class Int16Ref extends ValueRef<number> {
75
- getValue(): number;
76
- setValue(newValue: number): void;
77
- }
78
- export declare class Uint16Ref extends ValueRef<number> {
79
- getValue(): number;
80
- setValue(newValue: number): void;
81
- }
82
- export declare class Int32Ref extends ValueRef<number> {
83
- getValue(): number;
84
- setValue(newValue: number): void;
85
- }
86
- export declare class Uint32Ref extends ValueRef<number> {
87
- getValue(): number;
88
- setValue(newValue: number): void;
89
- }
90
- export declare class PointerRef extends Uint32Ref {
91
- }
92
- export declare class Float32Ref extends ValueRef<number> {
93
- getValue(): number;
94
- setValue(newValue: number): void;
95
- }
96
- export declare class Float64Ref extends ValueRef<number> {
97
- getValue(): number;
98
- setValue(newValue: number): void;
99
- }
100
- export declare class NullTerminatedUtf8StringRef extends ValueRef<string> {
101
- getValue(): string;
102
- setValue(newValue: string): void;
103
- }
104
- declare abstract class TypedArrayRef<T extends TypedArray> {
105
- protected ptr: number;
106
- readonly length: number;
107
- private readonly manager;
108
- get module(): any;
109
- constructor(ptr: number, length: number, manager: WasmMemoryManager);
110
- get view(): T;
111
- protected abstract getView(): T;
112
- slice(start?: number, end?: number): Int32Array<ArrayBuffer> | Uint8Array<ArrayBuffer> | Int8Array<ArrayBuffer> | Uint8ClampedArray<ArrayBuffer> | Int16Array<ArrayBuffer> | Uint16Array<ArrayBuffer> | Uint32Array<ArrayBuffer> | Float32Array<ArrayBuffer> | Float64Array<ArrayBuffer>;
113
- get address(): number;
114
- clear(): this;
115
- free(): void;
116
- clearAddress(): void;
117
- detach(): this;
118
- get isFreed(): boolean;
119
- protected assertNotFreed(): void;
120
- }
121
- export declare class Int8ArrayRef extends TypedArrayRef<Int8Array> {
122
- getView(): Int8Array;
123
- }
124
- export declare class Uint8ArrayRef extends TypedArrayRef<Uint8Array> {
125
- getView(): Uint8Array;
126
- readAsNullTerminatedUtf8String(): string;
127
- }
128
- export declare class Int16ArrayRef extends TypedArrayRef<Int16Array> {
129
- getView(): Int16Array;
130
- }
131
- export declare class Uint16ArrayRef extends TypedArrayRef<Uint16Array> {
132
- getView(): Uint16Array;
133
- }
134
- export declare class Int32ArrayRef extends TypedArrayRef<Int32Array> {
135
- getView(): Int32Array;
136
- }
137
- export declare class Uint32ArrayRef extends TypedArrayRef<Uint32Array> {
138
- getView(): Uint32Array;
139
- }
140
- export declare class Float32ArrayRef extends TypedArrayRef<Float32Array> {
141
- getView(): Float32Array;
142
- }
143
- export declare class Float64ArrayRef extends TypedArrayRef<Float64Array> {
144
- getView(): Float64Array;
145
- }
146
- export type WasmRef = ValueRef<number> | ValueRef<string> | TypedArrayRef<TypedArray>;
147
- export interface WasmMemoryManagerOptions {
148
- wasmAlloc?: WasmAllocMethod;
149
- wasmFree?: WasmFreeMethod;
150
- }
151
- export type WasmAllocMethod = (size: number) => number;
152
- export type WasmFreeMethod = (address: number) => void;
153
- export {};