echogarden 2.7.0 → 2.8.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.
Files changed (110) hide show
  1. package/data/lexicons/heteronyms.en.json +6 -2
  2. package/data/lexicons/words.en.json +379 -19
  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 +129 -106
  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 +96 -147
  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 +146 -111
  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 +100 -170
  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,155 @@ 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()
75
+ wordSequence.addWord(wordEntry.text, wordStartOffset, isPunctuation)
76
+ }
101
77
 
102
- if (restoredAndProcessedSentence.length > 0) {
103
- newSegment.push(restoredAndProcessedSentence)
104
- }
78
+ const { wordSequenceWithPunctuation, originalWordsReverseMapping } = addMissingPunctuationWordsToWordSequence(wordSequence, transcript)
105
79
 
106
- offset += sentenceLength
107
- }
80
+ const segmentedWordSequence = await segmentWordSequence(wordSequenceWithPunctuation)
108
81
 
109
- segments.push(newSegment)
110
- }
82
+ const paragraphs = splitToParagraphs(transcript, paragraphBreaks, whitespace)
83
+ const sentenceIndexesForParagraph = paragraphs.map(_ => [] as number[])
111
84
 
112
- segments = segments.filter(segment => segment.length > 0)
113
- }
85
+ {
86
+ let sentenceIndex = 0
87
+ let charOffset = 0
114
88
 
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[] = []
89
+ for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
90
+ const paragraph = paragraphs[paragraphIndex]
119
91
 
120
- const segmentTimeline: Timeline = []
92
+ const paragraphStartOffset = charOffset
93
+ const paragraphEndOffset = paragraphStartOffset + paragraph.length
121
94
 
122
- for (const segment of segments) {
123
- const sentencesInSegment: Timeline = []
95
+ while (sentenceIndex < segmentedWordSequence.sentences.length) {
96
+ const sentenceEntry = segmentedWordSequence.sentences[sentenceIndex]
97
+ const sentenceStartOffset = sentenceEntry.charRange.start
98
+ const sentenceEndOffset = sentenceEntry.charRange.end
124
99
 
125
- const segmentEntry: TimelineEntry = {
126
- type: 'segment',
127
- text: '',
128
- startTime: -1,
129
- endTime: -1,
130
- timeline: sentencesInSegment
131
- }
132
-
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
+ for (const entry of timeline) {
175
+ if (entry.type === 'word') {
176
+ let word = entry.text
223
177
 
224
- const wordParts = word.split(' ')
178
+ word = word.trim().replaceAll(/\s+/g, ' ')
225
179
 
226
- let startOffset: number | undefined
227
- let endOffset: number | undefined
180
+ const wordParts = word.split(' ')
228
181
 
229
- for (let i = 0; i < wordParts.length; i++) {
230
- let wordPart = wordParts[i]
182
+ let startOffset: number | undefined
183
+ let endOffset: number | undefined
231
184
 
232
- let wordPartOffset = text.indexOf(wordPart, currentOffset)
185
+ for (let i = 0; i < wordParts.length; i++) {
186
+ const wordPart = wordParts[i]
233
187
 
234
- if (wordPartOffset == -1) {
235
- continue
236
- }
188
+ const wordPartOffset = text.indexOf(wordPart, currentOffset)
237
189
 
238
- currentOffset = wordPartOffset + wordParts[i].length
190
+ if (wordPartOffset === -1) {
191
+ continue
192
+ }
239
193
 
240
- if (i == 0) {
241
- startOffset = wordPartOffset
242
- }
194
+ currentOffset = wordPartOffset + wordParts[i].length
243
195
 
244
- endOffset = currentOffset
245
- }
196
+ if (i === 0) {
197
+ startOffset = wordPartOffset
198
+ }
246
199
 
247
- entry.startOffsetUtf16 = startOffset
248
- entry.endOffsetUtf16 = endOffset
200
+ endOffset = currentOffset
201
+ }
249
202
 
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)
203
+ entry.startOffsetUtf16 = startOffset
204
+ entry.endOffsetUtf16 = endOffset
205
+
206
+ entry.startOffsetUtf32 = startOffset !== undefined ? utf16To32Mapping[startOffset] : undefined
207
+ entry.endOffsetUtf32 = endOffset !== undefined ? utf16To32Mapping[endOffset] : undefined
208
+ } else if (entry.timeline) {
209
+ processTimeline(entry.timeline)
210
+ }
254
211
  }
255
212
  }
256
213
 
257
- return currentOffset
214
+ return processTimeline(timeline)
258
215
  }
259
216
 
260
217
  function replaceSentenceEndersWithinWordsWithMaskingCharacter(transcript: string, wordTimeline: Timeline, maskingCharacter: string) {
@@ -344,30 +301,3 @@ export type TimelineEntry = {
344
301
  }
345
302
 
346
303
  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 {};