echogarden 0.12.2 → 1.0.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/README.md +15 -14
- package/data/schemas/options.json +398 -111
- package/dist/alignment/DTWMfccSequenceAlignment.d.ts +1 -1
- package/dist/alignment/DTWMfccSequenceAlignment.js +8 -8
- package/dist/alignment/DTWSequenceAlignment.d.ts +1 -1
- package/dist/alignment/DTWSequenceAlignment.js +1 -1
- package/dist/alignment/DTWSequenceAlignmentWindowed.d.ts +1 -1
- package/dist/alignment/DTWSequenceAlignmentWindowed.js +2 -2
- package/dist/alignment/LevenshteinSequenceAlignment.d.ts +1 -1
- package/dist/alignment/LevenshteinSequenceAlignment.js +1 -1
- package/dist/alignment/SpeechAlignment.d.ts +9 -10
- package/dist/alignment/SpeechAlignment.js +136 -105
- package/dist/alignment/SpeechAlignment.js.map +1 -1
- package/dist/api/API.d.ts +13 -12
- package/dist/api/API.js +14 -13
- package/dist/api/API.js.map +1 -1
- package/dist/api/APIOptions.d.ts +5 -4
- package/dist/api/Alignment.d.ts +15 -9
- package/dist/api/Alignment.js +88 -74
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/Common.js +1 -1
- package/dist/api/Denoising.d.ts +6 -6
- package/dist/api/Denoising.js +23 -23
- package/dist/api/Denoising.js.map +1 -1
- package/dist/api/LanguageDetection.d.ts +19 -12
- package/dist/api/LanguageDetection.js +88 -38
- package/dist/api/LanguageDetection.js.map +1 -1
- package/dist/api/Recognition.d.ts +16 -6
- package/dist/api/Recognition.js +129 -55
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/SourceSeparation.d.ts +17 -0
- package/dist/api/SourceSeparation.js +61 -0
- package/dist/api/SourceSeparation.js.map +1 -0
- package/dist/api/Synthesis.d.ts +18 -18
- package/dist/api/Synthesis.js +191 -164
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/api/Translation.d.ts +19 -8
- package/dist/api/Translation.js +132 -35
- package/dist/api/Translation.js.map +1 -1
- package/dist/api/Vad.d.ts +10 -5
- package/dist/api/Vad.js +76 -38
- package/dist/api/Vad.js.map +1 -1
- package/dist/audio/AudioBufferConversion.d.ts +1 -1
- package/dist/audio/AudioBufferConversion.js +4 -4
- package/dist/audio/AudioPlayer.d.ts +1 -1
- package/dist/audio/AudioPlayer.js +26 -26
- package/dist/audio/AudioPlayer.js.map +1 -1
- package/dist/audio/AudioRecorder.d.ts +1 -1
- package/dist/audio/AudioRecorder.js +5 -5
- package/dist/audio/AudioUtilities.d.ts +13 -9
- package/dist/audio/AudioUtilities.js +86 -24
- package/dist/audio/AudioUtilities.js.map +1 -1
- package/dist/cli/CLI.d.ts +3 -3
- package/dist/cli/CLI.js +271 -162
- package/dist/cli/CLI.js.map +1 -1
- package/dist/cli/CLIConfigFile.js +8 -8
- package/dist/cli/CLILauncher.js +6 -6
- package/dist/cli/CLIOptionsSchema.js +2 -2
- package/dist/cli/CLIParser.js +5 -5
- package/dist/cli/CLIStarter.js +4 -4
- package/dist/codecs/FFMpegTranscoder.d.ts +2 -2
- package/dist/codecs/FFMpegTranscoder.js +37 -37
- package/dist/codecs/FFMpegTranscoder.js.map +1 -1
- package/dist/codecs/TIMITCodec.js +5 -5
- package/dist/codecs/WaveCodec.d.ts +1 -1
- package/dist/codecs/WaveCodec.js +22 -22
- package/dist/denoising/RNNoise.d.ts +1 -1
- package/dist/denoising/RNNoise.js +9 -9
- package/dist/dsp/BiquadFilter.d.ts +3 -2
- package/dist/dsp/BiquadFilter.js +18 -11
- package/dist/dsp/BiquadFilter.js.map +1 -1
- package/dist/dsp/DecayingPeakEstimator.d.ts +16 -0
- package/dist/dsp/DecayingPeakEstimator.js +23 -0
- package/dist/dsp/DecayingPeakEstimator.js.map +1 -0
- package/dist/dsp/FFT.d.ts +8 -4
- package/dist/dsp/FFT.js +76 -30
- package/dist/dsp/FFT.js.map +1 -1
- package/dist/dsp/KWeightingFilter.d.ts +9 -0
- package/dist/dsp/KWeightingFilter.js +40 -0
- package/dist/dsp/KWeightingFilter.js.map +1 -0
- package/dist/dsp/LoudnessEstimator.d.ts +21 -0
- package/dist/dsp/LoudnessEstimator.js +47 -0
- package/dist/dsp/LoudnessEstimator.js.map +1 -0
- package/dist/dsp/MFCC.d.ts +2 -2
- package/dist/dsp/MFCC.js +15 -15
- package/dist/dsp/MelSpectogram.d.ts +1 -1
- package/dist/dsp/MelSpectogram.js +6 -6
- package/dist/dsp/Rubberband.d.ts +11 -11
- package/dist/dsp/Rubberband.js +27 -27
- package/dist/dsp/Sonic.d.ts +1 -1
- package/dist/dsp/Sonic.js +3 -3
- package/dist/dsp/SpeexResampler.d.ts +1 -1
- package/dist/dsp/SpeexResampler.js +2 -2
- package/dist/math/VectorMath.d.ts +12 -8
- package/dist/math/VectorMath.js +35 -32
- package/dist/math/VectorMath.js.map +1 -1
- package/dist/nlp/ChineseSegmentation.js +2 -2
- package/dist/nlp/CompromiseNLP.js +3 -3
- package/dist/nlp/EspeakPhonemizer.js +30 -30
- package/dist/nlp/IPA.js +20 -20
- package/dist/nlp/JapaneseSegmentation.js +6 -6
- package/dist/nlp/Lexicon.d.ts +1 -1
- package/dist/nlp/Lexicon.js +7 -7
- package/dist/nlp/Segmentation.d.ts +3 -0
- package/dist/nlp/Segmentation.js +21 -14
- package/dist/nlp/Segmentation.js.map +1 -1
- package/dist/nlp/TextNormalizer.js +16 -16
- package/dist/recognition/AmazonTranscribeSTT.d.ts +2 -2
- package/dist/recognition/AmazonTranscribeSTT.js +13 -14
- package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
- package/dist/recognition/AzureCognitiveServicesSTT.js +5 -6
- package/dist/recognition/AzureCognitiveServicesSTT.js.map +1 -1
- package/dist/recognition/GoogleCloudSTT.d.ts +3 -3
- package/dist/recognition/GoogleCloudSTT.js +18 -18
- package/dist/recognition/OpenAICloudSTT.d.ts +19 -0
- package/dist/recognition/OpenAICloudSTT.js +81 -0
- package/dist/recognition/OpenAICloudSTT.js.map +1 -0
- package/dist/recognition/SileroSTT.d.ts +2 -2
- package/dist/recognition/SileroSTT.js +25 -25
- package/dist/recognition/VoskSTT.d.ts +2 -2
- package/dist/recognition/VoskSTT.js +8 -8
- package/dist/recognition/WhisperCppSTT.d.ts +88 -0
- package/dist/recognition/WhisperCppSTT.js +332 -0
- package/dist/recognition/WhisperCppSTT.js.map +1 -0
- package/dist/recognition/WhisperSTT.d.ts +49 -25
- package/dist/recognition/WhisperSTT.js +626 -481
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/server/Client.d.ts +1 -1
- package/dist/server/Client.js +22 -22
- package/dist/server/Server.js +9 -9
- package/dist/server/Server.js.map +1 -1
- package/dist/server/Worker.d.ts +22 -22
- package/dist/server/Worker.js +36 -36
- package/dist/server/Worker.js.map +1 -1
- package/dist/server/WorkerStarter.js +2 -2
- package/dist/source-separation/MDXNetSourceSeparation.d.ts +11 -0
- package/dist/source-separation/MDXNetSourceSeparation.js +161 -0
- package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -0
- package/dist/speech-language-detection/SileroLanguageDetection.d.ts +1 -1
- package/dist/speech-language-detection/SileroLanguageDetection.js +7 -7
- package/dist/subtitles/Subtitles.d.ts +10 -0
- package/dist/subtitles/Subtitles.js +2 -2
- package/dist/subtitles/Subtitles.js.map +1 -1
- package/dist/synthesis/AwsPollyTTS.d.ts +1 -1
- package/dist/synthesis/AwsPollyTTS.js +12 -12
- package/dist/synthesis/AzureCognitiveServicesTTS.js +7 -7
- package/dist/synthesis/CoquiServerTTS.js +10 -10
- package/dist/synthesis/CoquiServerTTS.js.map +1 -1
- package/dist/synthesis/ElevenlabsTTS.d.ts +23 -0
- package/dist/synthesis/ElevenlabsTTS.js +103 -0
- package/dist/synthesis/ElevenlabsTTS.js.map +1 -0
- package/dist/synthesis/EspeakTTS.d.ts +6 -5
- package/dist/synthesis/EspeakTTS.js +81 -69
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/synthesis/FliteTTS.d.ts +3 -3
- package/dist/synthesis/FliteTTS.js +154 -154
- package/dist/synthesis/FliteTTS.js.map +1 -1
- package/dist/synthesis/GoogleCloudTTS.d.ts +3 -3
- package/dist/synthesis/GoogleCloudTTS.js +17 -17
- package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
- package/dist/synthesis/GoogleTranslateTTS.d.ts +1 -1
- package/dist/synthesis/GoogleTranslateTTS.js +103 -103
- package/dist/synthesis/MicrosoftEdgeTTS.d.ts +2 -2
- package/dist/synthesis/MicrosoftEdgeTTS.js +74 -74
- package/dist/synthesis/OpenAICloudTTS.d.ts +13 -0
- package/dist/synthesis/OpenAICloudTTS.js +169 -0
- package/dist/synthesis/OpenAICloudTTS.js.map +1 -0
- package/dist/synthesis/SamTTS.js +3 -3
- package/dist/synthesis/SapiTTS.d.ts +3 -3
- package/dist/synthesis/SapiTTS.js +26 -26
- package/dist/synthesis/StreamlabsPollyTTS.d.ts +2 -2
- package/dist/synthesis/StreamlabsPollyTTS.js +27 -27
- package/dist/synthesis/SvoxPicoTTS.d.ts +2 -2
- package/dist/synthesis/SvoxPicoTTS.js +65 -65
- package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
- package/dist/synthesis/VitsTTS.d.ts +3 -3
- package/dist/synthesis/VitsTTS.js +378 -378
- package/dist/synthesis/VitsTTS.js.map +1 -1
- package/dist/tests/Test.js +2 -2
- package/dist/utilities/Compression.d.ts +5 -0
- package/dist/utilities/Compression.js +29 -13
- package/dist/utilities/Compression.js.map +1 -1
- package/dist/utilities/FileDownloader.d.ts +1 -1
- package/dist/utilities/FileDownloader.js +16 -16
- package/dist/utilities/FileSystem.js +7 -7
- package/dist/utilities/Locale.d.ts +7 -7
- package/dist/utilities/Locale.js +15 -15
- package/dist/utilities/Logger.js +3 -3
- package/dist/utilities/ObjectUtilities.js +19 -19
- package/dist/utilities/OpenPromise.js +2 -2
- package/dist/utilities/OpenPromise.js.map +1 -1
- package/dist/utilities/PackageManager.js +31 -0
- package/dist/utilities/PackageManager.js.map +1 -1
- package/dist/utilities/PathUtilities.js +8 -8
- package/dist/utilities/RandomGenerator.js +2 -2
- package/dist/utilities/SmoothEstimator.d.ts +8 -0
- package/dist/utilities/SmoothEstimator.js +25 -0
- package/dist/utilities/SmoothEstimator.js.map +1 -0
- package/dist/utilities/TarballMaker.js +8 -8
- package/dist/utilities/Timeline.d.ts +3 -2
- package/dist/utilities/Timeline.js +11 -11
- package/dist/utilities/Timeline.js.map +1 -1
- package/dist/utilities/Timer.js +4 -4
- package/dist/utilities/Utilities.d.ts +4 -0
- package/dist/utilities/Utilities.js +38 -15
- package/dist/utilities/Utilities.js.map +1 -1
- package/dist/utilities/WasmMemoryManager.js +7 -7
- package/dist/utilities/WebReader.js +23 -23
- package/dist/utilities/WikipediaReader.js +2 -2
- package/dist/voice-activity-detection/AdaptiveGateVAD.d.ts +28 -0
- package/dist/voice-activity-detection/AdaptiveGateVAD.js +138 -0
- package/dist/voice-activity-detection/AdaptiveGateVAD.js.map +1 -0
- package/dist/voice-activity-detection/SileroVAD.d.ts +1 -1
- package/dist/voice-activity-detection/SileroVAD.js +5 -5
- package/dist/voice-activity-detection/SileroVAD.js.map +1 -1
- package/dist/voice-activity-detection/WebRtcVAD.d.ts +1 -1
- package/dist/voice-activity-detection/WebRtcVAD.js +4 -4
- package/docs/API.md +29 -11
- package/docs/CLI.md +31 -7
- package/docs/Contributing.md +38 -0
- package/docs/Development.md +93 -19
- package/docs/Engines.md +28 -16
- package/docs/Licenses.md +4 -1
- package/docs/Options.md +158 -78
- package/docs/Releases.md +262 -0
- package/docs/Server.md +7 -7
- package/docs/Tasklist.md +95 -76
- package/docs/Technical.md +4 -4
- package/package.json +13 -14
- package/src/alignment/DTWMfccSequenceAlignment.ts +9 -9
- package/src/alignment/DTWSequenceAlignment.ts +2 -2
- package/src/alignment/DTWSequenceAlignmentWindowed.ts +3 -3
- package/src/alignment/LevenshteinSequenceAlignment.ts +2 -2
- package/src/alignment/SpeechAlignment.ts +204 -119
- package/src/api/API.ts +14 -13
- package/src/api/APIOptions.ts +12 -11
- package/src/api/Alignment.ts +147 -90
- package/src/api/Common.ts +1 -1
- package/src/api/Denoising.ts +28 -28
- package/src/api/LanguageDetection.ts +135 -48
- package/src/api/Recognition.ts +198 -59
- package/src/api/SourceSeparation.ts +99 -0
- package/src/api/Synthesis.ts +217 -181
- package/src/api/Translation.ts +193 -40
- package/src/api/Vad.ts +110 -41
- package/src/audio/AudioBufferConversion.ts +4 -4
- package/src/audio/AudioPlayer.ts +27 -27
- package/src/audio/AudioRecorder.ts +5 -5
- package/src/audio/AudioUtilities.ts +107 -24
- package/src/cli/CLI.ts +313 -164
- package/src/cli/CLIConfigFile.ts +8 -8
- package/src/cli/CLILauncher.ts +6 -6
- package/src/cli/CLIOptionsSchema.ts +2 -2
- package/src/cli/CLIParser.ts +5 -5
- package/src/cli/CLIStarter.ts +4 -4
- package/src/codecs/FFMpegTranscoder.ts +38 -38
- package/src/codecs/TIMITCodec.ts +5 -5
- package/src/codecs/WaveCodec.ts +22 -22
- package/src/denoising/RNNoise.ts +9 -9
- package/src/dsp/BiquadFilter.ts +19 -11
- package/src/dsp/DecayingPeakEstimator.ts +35 -0
- package/src/dsp/FFT.ts +103 -35
- package/src/dsp/KWeightingFilter.ts +43 -0
- package/src/dsp/LoudnessEstimator.ts +74 -0
- package/src/dsp/MFCC.ts +15 -15
- package/src/dsp/MelSpectogram.ts +7 -7
- package/src/dsp/Rubberband.ts +38 -38
- package/src/dsp/Sonic.ts +4 -4
- package/src/dsp/SpeexResampler.ts +2 -2
- package/src/math/VectorMath.ts +42 -33
- package/src/nlp/ChineseSegmentation.ts +3 -3
- package/src/nlp/CompromiseNLP.ts +3 -3
- package/src/nlp/EspeakPhonemizer.ts +30 -30
- package/src/nlp/IPA.ts +20 -20
- package/src/nlp/JapaneseSegmentation.ts +6 -6
- package/src/nlp/Lexicon.ts +8 -8
- package/src/nlp/Segmentation.ts +23 -14
- package/src/nlp/TextNormalizer.ts +16 -16
- package/src/recognition/AmazonTranscribeSTT.ts +16 -17
- package/src/recognition/AzureCognitiveServicesSTT.ts +8 -6
- package/src/recognition/GoogleCloudSTT.ts +21 -21
- package/src/recognition/OpenAICloudSTT.ts +142 -0
- package/src/recognition/SileroSTT.ts +26 -26
- package/src/recognition/VoskSTT.ts +10 -10
- package/src/recognition/WhisperCppSTT.ts +555 -0
- package/src/recognition/WhisperSTT.ts +760 -507
- package/src/server/Client.ts +23 -23
- package/src/server/Server.ts +9 -9
- package/src/server/Worker.ts +53 -53
- package/src/server/WorkerStarter.ts +2 -2
- package/src/source-separation/MDXNetSourceSeparation.ts +228 -0
- package/src/speech-language-detection/SileroLanguageDetection.ts +8 -8
- package/src/subtitles/Subtitles.ts +3 -3
- package/src/synthesis/AwsPollyTTS.ts +14 -14
- package/src/synthesis/AzureCognitiveServicesTTS.ts +10 -10
- package/src/synthesis/CoquiServerTTS.ts +10 -10
- package/src/synthesis/ElevenlabsTTS.ts +137 -0
- package/src/synthesis/EspeakTTS.ts +90 -71
- package/src/synthesis/FliteTTS.ts +157 -157
- package/src/synthesis/GoogleCloudTTS.ts +19 -19
- package/src/synthesis/GoogleTranslateTTS.ts +104 -104
- package/src/synthesis/MicrosoftEdgeTTS.ts +80 -80
- package/src/synthesis/OpenAICloudTTS.ts +196 -0
- package/src/synthesis/SamTTS.ts +3 -3
- package/src/synthesis/SapiTTS.ts +29 -29
- package/src/synthesis/StreamlabsPollyTTS.ts +29 -29
- package/src/synthesis/SvoxPicoTTS.ts +67 -67
- package/src/synthesis/VitsTTS.ts +380 -380
- package/src/tests/Test.ts +4 -4
- package/src/utilities/Compression.ts +34 -13
- package/src/utilities/FileDownloader.ts +19 -19
- package/src/utilities/FileSystem.ts +7 -7
- package/src/utilities/Locale.ts +22 -22
- package/src/utilities/Logger.ts +4 -4
- package/src/utilities/ObjectUtilities.ts +19 -19
- package/src/utilities/OpenPromise.ts +2 -2
- package/src/utilities/PackageManager.ts +40 -0
- package/src/utilities/PathUtilities.ts +8 -8
- package/src/utilities/RandomGenerator.ts +3 -3
- package/src/utilities/SmoothEstimator.ts +35 -0
- package/src/utilities/TarballMaker.ts +9 -9
- package/src/utilities/Timeline.ts +15 -13
- package/src/utilities/Timer.ts +4 -4
- package/src/utilities/Utilities.ts +49 -15
- package/src/utilities/WasmMemoryManager.ts +7 -7
- package/src/utilities/WebReader.ts +23 -23
- package/src/utilities/WikipediaReader.ts +2 -2
- package/src/voice-activity-detection/AdaptiveGateVAD.ts +202 -0
- package/src/voice-activity-detection/SileroVAD.ts +5 -5
- package/src/voice-activity-detection/WebRtcVAD.ts +5 -5
- package/dist/synthesis/ElevenLabsTTS.d.ts +0 -8
- package/dist/synthesis/ElevenLabsTTS.js +0 -82
- package/dist/synthesis/ElevenLabsTTS.js.map +0 -1
- package/src/synthesis/ElevenLabsTTS.ts +0 -104
package/src/cli/CLIConfigFile.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { readAndParseJsonFile, readFile } from
|
|
1
|
+
import { readAndParseJsonFile, readFile } from '../utilities/FileSystem.js'
|
|
2
2
|
|
|
3
3
|
export async function parseConfigFile(path: string): Promise<ParsedConfigFile> {
|
|
4
|
-
const fileContent = await readFile(path, { encoding:
|
|
4
|
+
const fileContent = await readFile(path, { encoding: 'utf-8' })
|
|
5
5
|
|
|
6
6
|
const lines = fileContent
|
|
7
7
|
.split(/\r?\n/g)
|
|
@@ -11,12 +11,12 @@ export async function parseConfigFile(path: string): Promise<ParsedConfigFile> {
|
|
|
11
11
|
|
|
12
12
|
const sectionMap = new Map<string, Map<string, string>>()
|
|
13
13
|
|
|
14
|
-
let currentSectionName =
|
|
14
|
+
let currentSectionName = ''
|
|
15
15
|
|
|
16
16
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
17
17
|
const line = lines[lineIndex]
|
|
18
18
|
|
|
19
|
-
if (line.length == 0 || line.startsWith(
|
|
19
|
+
if (line.length == 0 || line.startsWith('#')) {
|
|
20
20
|
continue
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -31,7 +31,7 @@ export async function parseConfigFile(path: string): Promise<ParsedConfigFile> {
|
|
|
31
31
|
sectionMap.set(currentSectionName, new Map())
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const splitPoint = line.indexOf(
|
|
34
|
+
const splitPoint = line.indexOf('=')
|
|
35
35
|
|
|
36
36
|
let key: string
|
|
37
37
|
let value: string
|
|
@@ -65,10 +65,10 @@ export async function parseJSONConfigFile(path: string): Promise<ParsedConfigFil
|
|
|
65
65
|
for (const propertyName in obj) {
|
|
66
66
|
const propertyValue = obj[propertyName]
|
|
67
67
|
|
|
68
|
-
const propertyPath = pathPrefix ==
|
|
68
|
+
const propertyPath = pathPrefix == '' ? propertyName : `${pathPrefix}.${propertyName}`
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
if (typeof propertyValue ==
|
|
71
|
+
if (typeof propertyValue == 'object') {
|
|
72
72
|
if (Array.isArray(propertyValue)) {
|
|
73
73
|
commandMap.set(propertyPath, JSON.stringify(propertyValue))
|
|
74
74
|
} else {
|
|
@@ -80,7 +80,7 @@ export async function parseJSONConfigFile(path: string): Promise<ParsedConfigFil
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
addFromObject(commandObj,
|
|
83
|
+
addFromObject(commandObj, '')
|
|
84
84
|
|
|
85
85
|
result.set(command, commandMap)
|
|
86
86
|
}
|
package/src/cli/CLILauncher.ts
CHANGED
|
@@ -9,18 +9,18 @@ setupUnhandledExceptionListeners()
|
|
|
9
9
|
const cmd = process.argv[0]
|
|
10
10
|
const scriptArgs = process.argv.slice(2)
|
|
11
11
|
|
|
12
|
-
const cliScriptPath = resolveToModuleRootDir(
|
|
12
|
+
const cliScriptPath = resolveToModuleRootDir('dist/cli/CLIStarter.js')
|
|
13
13
|
|
|
14
14
|
const args = [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
'--no-warnings',
|
|
16
|
+
'--no-experimental-fetch',
|
|
17
|
+
'--experimental-wasi-unstable-preview1',
|
|
18
18
|
cliScriptPath,
|
|
19
19
|
...scriptArgs
|
|
20
20
|
]
|
|
21
21
|
|
|
22
|
-
const child = spawn(cmd, args, { stdio:
|
|
22
|
+
const child = spawn(cmd, args, { stdio: 'inherit' })
|
|
23
23
|
|
|
24
|
-
child.on(
|
|
24
|
+
child.on('close', code => {
|
|
25
25
|
process.exit(code as number)
|
|
26
26
|
})
|
|
@@ -11,10 +11,10 @@ export function getOptionTypeFromSchema(path: string[], schema: any): SchemaType
|
|
|
11
11
|
currentObject = currentObject[key]
|
|
12
12
|
|
|
13
13
|
if (!currentObject) {
|
|
14
|
-
throw new Error(`'${key}' is not a valid property of '${path.slice(0, keyIndex).join(
|
|
14
|
+
throw new Error(`'${key}' is not a valid property of '${path.slice(0, keyIndex).join('.')}'.`)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (
|
|
17
|
+
if ('$ref' in currentObject) {
|
|
18
18
|
const refString = currentObject['$ref'] as string
|
|
19
19
|
const parsedRef = refString.substring(refString.lastIndexOf('/') + 1)
|
|
20
20
|
|
package/src/cli/CLIParser.ts
CHANGED
|
@@ -7,20 +7,20 @@ export function parseCLIArguments(command: string, args: string[]): CLIArguments
|
|
|
7
7
|
|
|
8
8
|
for (let i = 0; i < args.length; i++) {
|
|
9
9
|
const currentArg = args[i]
|
|
10
|
-
const currentArgIsNewOption = currentArg.startsWith(
|
|
10
|
+
const currentArgIsNewOption = currentArg.startsWith('-')
|
|
11
11
|
|
|
12
12
|
if (currentArgIsNewOption) {
|
|
13
|
-
if (!currentArg.startsWith(
|
|
13
|
+
if (!currentArg.startsWith('--')) {
|
|
14
14
|
throw new Error(`'${currentArg}' has a single dash prefix. You should use '-${currentArg}' instead.`)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const optionText = currentArg.substring(2)
|
|
18
18
|
|
|
19
|
-
const indexOfEquals = optionText.indexOf(
|
|
19
|
+
const indexOfEquals = optionText.indexOf('=')
|
|
20
20
|
if (indexOfEquals == 0) {
|
|
21
|
-
throw new Error(
|
|
21
|
+
throw new Error('An option cannot have an empty name.')
|
|
22
22
|
} else if (indexOfEquals == -1) {
|
|
23
|
-
parsedArgs.options.set(optionText,
|
|
23
|
+
parsedArgs.options.set(optionText, '')
|
|
24
24
|
} else {
|
|
25
25
|
const key = optionText.substring(0, indexOfEquals)
|
|
26
26
|
const value = optionText.substring(indexOfEquals + 1)
|
package/src/cli/CLIStarter.ts
CHANGED
|
@@ -9,7 +9,7 @@ setupProgramTerminationListeners(() => {
|
|
|
9
9
|
process.kill(process.pid, 'SIGKILL')
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
const worker = new Worker(resolveToModuleRootDir(
|
|
12
|
+
const worker = new Worker(resolveToModuleRootDir('dist/cli/CLI.js'), {
|
|
13
13
|
argv: process.argv.slice(2),
|
|
14
14
|
env: SHARE_ENV
|
|
15
15
|
})
|
|
@@ -29,12 +29,12 @@ process.stdin.on('keypress', (str, key) => {
|
|
|
29
29
|
})
|
|
30
30
|
})
|
|
31
31
|
|
|
32
|
-
worker.on(
|
|
33
|
-
if (message.name ==
|
|
32
|
+
worker.on('message', (message) => {
|
|
33
|
+
if (message.name == 'writeToStdErr') {
|
|
34
34
|
writeToStderr(message.text)
|
|
35
35
|
}
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
worker.on(
|
|
38
|
+
worker.on('exit', (err) => {
|
|
39
39
|
process.exit(err ? 1 : 0)
|
|
40
40
|
})
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { spawn } from
|
|
1
|
+
import { spawn } from 'child_process'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { encodeRawAudioToWave, decodeWaveToRawAudio, RawAudio } from '../audio/AudioUtilities.js'
|
|
4
4
|
|
|
5
|
-
import { Logger } from
|
|
6
|
-
import { commandExists, logToStderr } from
|
|
7
|
-
import path from
|
|
8
|
-
import { loadPackage } from
|
|
9
|
-
import { getGlobalOption } from
|
|
5
|
+
import { Logger } from '../utilities/Logger.js'
|
|
6
|
+
import { commandExists, logToStderr } from '../utilities/Utilities.js'
|
|
7
|
+
import path from 'node:path'
|
|
8
|
+
import { loadPackage } from '../utilities/PackageManager.js'
|
|
9
|
+
import { getGlobalOption } from '../api/GlobalOptions.js'
|
|
10
10
|
|
|
11
11
|
const log = logToStderr
|
|
12
12
|
|
|
@@ -15,7 +15,7 @@ export type FFMpegOutputOptions = {
|
|
|
15
15
|
codec?: string
|
|
16
16
|
format?: string
|
|
17
17
|
sampleRate?: number
|
|
18
|
-
sampleFormat?:
|
|
18
|
+
sampleFormat?: 'u8' | 's16' | 's32' | 's64' | 'flt' | 'dbl'
|
|
19
19
|
channelCount?: number
|
|
20
20
|
bitrate?: number
|
|
21
21
|
audioOnly?: boolean
|
|
@@ -23,13 +23,13 @@ export type FFMpegOutputOptions = {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export async function encodeFromChannels(rawAudio: RawAudio, outputOptions: FFMpegOutputOptions) {
|
|
26
|
-
return transcode(
|
|
26
|
+
return transcode(encodeRawAudioToWave(rawAudio), outputOptions)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export async function decodeToChannels(input: string | Buffer, outSampleRate?: number, outChannelCount?: number) {
|
|
30
30
|
const outputOptions: FFMpegOutputOptions = {
|
|
31
|
-
codec:
|
|
32
|
-
format:
|
|
31
|
+
codec: 'pcm_f32le',
|
|
32
|
+
format: 'wav',
|
|
33
33
|
sampleRate: outSampleRate,
|
|
34
34
|
channelCount: outChannelCount,
|
|
35
35
|
audioOnly: true
|
|
@@ -37,7 +37,7 @@ export async function decodeToChannels(input: string | Buffer, outSampleRate?: n
|
|
|
37
37
|
|
|
38
38
|
const waveAudio = await transcode(input, outputOptions)
|
|
39
39
|
|
|
40
|
-
const { rawAudio } =
|
|
40
|
+
const { rawAudio } = decodeWaveToRawAudio(waveAudio, true)
|
|
41
41
|
|
|
42
42
|
return rawAudio
|
|
43
43
|
}
|
|
@@ -46,7 +46,7 @@ export async function transcode(input: string | Buffer, outputOptions: FFMpegOut
|
|
|
46
46
|
const executablePath = await getFFMpegExecutablePath()
|
|
47
47
|
|
|
48
48
|
if (!executablePath) {
|
|
49
|
-
throw new Error(
|
|
49
|
+
throw new Error(`The ffmpeg utility wasn't found. Please ensure it is available on the system path.`)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
return transcode_CLI(executablePath, input, outputOptions)
|
|
@@ -55,9 +55,9 @@ export async function transcode(input: string | Buffer, outputOptions: FFMpegOut
|
|
|
55
55
|
async function transcode_CLI(ffmpegCommand: string, input: string | Buffer, outputOptions: FFMpegOutputOptions) {
|
|
56
56
|
return new Promise<Buffer>((resolve, reject) => {
|
|
57
57
|
const logger = new Logger()
|
|
58
|
-
logger.start(
|
|
58
|
+
logger.start('Transcode with command-line ffmpeg')
|
|
59
59
|
|
|
60
|
-
const args = buildCommandLineArguments(Buffer.isBuffer(input) ?
|
|
60
|
+
const args = buildCommandLineArguments(Buffer.isBuffer(input) ? '-' : input, outputOptions)
|
|
61
61
|
|
|
62
62
|
const process = spawn(ffmpegCommand, args)
|
|
63
63
|
|
|
@@ -65,29 +65,29 @@ async function transcode_CLI(ffmpegCommand: string, input: string | Buffer, outp
|
|
|
65
65
|
process.stdin.end(input)
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const
|
|
69
|
-
let
|
|
68
|
+
const stdoutChunks: Buffer[] = []
|
|
69
|
+
let stderrOutput = ''
|
|
70
70
|
|
|
71
71
|
process.stdout.on('data', (data) => {
|
|
72
|
-
|
|
72
|
+
stdoutChunks.push(data)
|
|
73
73
|
})
|
|
74
74
|
|
|
75
|
-
process.stderr.setEncoding(
|
|
75
|
+
process.stderr.setEncoding('utf8')
|
|
76
76
|
process.stderr.on('data', (data) => {
|
|
77
77
|
//log(data)
|
|
78
|
-
|
|
78
|
+
stderrOutput += data
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
-
process.on(
|
|
81
|
+
process.on('error', (e) => {
|
|
82
82
|
reject(e)
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
process.on('close', (exitCode) => {
|
|
86
86
|
if (exitCode == 0) {
|
|
87
|
-
resolve(Buffer.concat(
|
|
87
|
+
resolve(Buffer.concat(stdoutChunks))
|
|
88
88
|
} else {
|
|
89
89
|
reject(`ffmpeg exited with code ${exitCode}`)
|
|
90
|
-
log(
|
|
90
|
+
log(stderrOutput)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
logger.end()
|
|
@@ -99,7 +99,7 @@ function buildCommandLineArguments(inputFilename: string, outputOptions: FFMpegO
|
|
|
99
99
|
outputOptions = { ...outputOptions }
|
|
100
100
|
|
|
101
101
|
if (!outputOptions.filename) {
|
|
102
|
-
outputOptions.filename =
|
|
102
|
+
outputOptions.filename = '-'
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
const args: string[] = []
|
|
@@ -200,36 +200,36 @@ async function getFFMpegExecutablePath() {
|
|
|
200
200
|
export function getDefaultFFMpegOptionsForSpeech(fileExtension: string, customBitrate?: number) {
|
|
201
201
|
let ffmpegOptions: FFMpegOutputOptions
|
|
202
202
|
|
|
203
|
-
if (fileExtension ==
|
|
203
|
+
if (fileExtension == 'mp3') {
|
|
204
204
|
ffmpegOptions = {
|
|
205
|
-
format:
|
|
206
|
-
codec:
|
|
205
|
+
format: 'mp3',
|
|
206
|
+
codec: 'libmp3lame',
|
|
207
207
|
bitrate: 64,
|
|
208
208
|
customOptions: []
|
|
209
209
|
}
|
|
210
|
-
} else if (fileExtension ==
|
|
210
|
+
} else if (fileExtension == 'opus') {
|
|
211
211
|
ffmpegOptions = {
|
|
212
|
-
codec:
|
|
212
|
+
codec: 'libopus',
|
|
213
213
|
bitrate: 48,
|
|
214
214
|
customOptions: []
|
|
215
215
|
}
|
|
216
|
-
} else if (fileExtension ==
|
|
216
|
+
} else if (fileExtension == 'm4a') {
|
|
217
217
|
ffmpegOptions = {
|
|
218
|
-
format:
|
|
219
|
-
codec:
|
|
218
|
+
format: 'mp4',
|
|
219
|
+
codec: 'aac',
|
|
220
220
|
bitrate: 48,
|
|
221
|
-
customOptions: [
|
|
221
|
+
customOptions: ['-profile:a', 'aac_low', '-movflags', 'frag_keyframe+empty_moov']
|
|
222
222
|
}
|
|
223
|
-
} else if (fileExtension ==
|
|
223
|
+
} else if (fileExtension == 'ogg') {
|
|
224
224
|
ffmpegOptions = {
|
|
225
|
-
codec:
|
|
225
|
+
codec: 'libvorbis',
|
|
226
226
|
bitrate: 48,
|
|
227
227
|
customOptions: []
|
|
228
228
|
}
|
|
229
|
-
} else if (fileExtension ==
|
|
229
|
+
} else if (fileExtension == 'flac') {
|
|
230
230
|
ffmpegOptions = {
|
|
231
|
-
format:
|
|
232
|
-
customOptions: [
|
|
231
|
+
format: 'flac',
|
|
232
|
+
customOptions: ['-compression_level', '6']
|
|
233
233
|
}
|
|
234
234
|
} else {
|
|
235
235
|
throw new Error(`Unsupported codec extension: '${fileExtension}'`)
|
package/src/codecs/TIMITCodec.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { decodeToChannels } from
|
|
2
|
-
import { readFile } from
|
|
3
|
-
import { SampleFormat } from
|
|
1
|
+
import { decodeToChannels } from '../audio/AudioBufferConversion.js'
|
|
2
|
+
import { readFile } from '../utilities/FileSystem.js'
|
|
3
|
+
import { SampleFormat } from './WaveCodec.js'
|
|
4
4
|
|
|
5
5
|
export async function decodeTimitAudioFile(filename: string) {
|
|
6
6
|
return decodeTimitAudio(await readFile(filename))
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function decodeTimitAudio(data: Buffer) {
|
|
10
|
-
if (data.subarray(0, 16).toString(
|
|
11
|
-
throw new Error(
|
|
10
|
+
if (data.subarray(0, 16).toString('ascii') != 'NIST_1A\n 1024\n') {
|
|
11
|
+
throw new Error('Data is not a valid TIMIT audio file')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const pcm = data.subarray(1024)
|
package/src/codecs/WaveCodec.ts
CHANGED
|
@@ -17,14 +17,14 @@ export function encodeWave(rawAudio: RawAudio, bitDepth: BitDepth = 16, sampleFo
|
|
|
17
17
|
const formatSubChunkBuffer = formatSubChunk.serialize(shouldUseExtensibleFormat)
|
|
18
18
|
|
|
19
19
|
const dataSubChunkBuffer = Buffer.alloc(4 + 4 + audioDataLength)
|
|
20
|
-
dataSubChunkBuffer.write(
|
|
20
|
+
dataSubChunkBuffer.write('data', 0, 'ascii')
|
|
21
21
|
dataSubChunkBuffer.writeUint32LE(audioDataLength, 4)
|
|
22
22
|
dataSubChunkBuffer.set(audioBuffer, 8)
|
|
23
23
|
|
|
24
24
|
const riffChunkHeaderBuffer = Buffer.alloc(12)
|
|
25
|
-
riffChunkHeaderBuffer.write(
|
|
25
|
+
riffChunkHeaderBuffer.write('RIFF', 0, 'ascii')
|
|
26
26
|
riffChunkHeaderBuffer.writeUint32LE(4 + formatSubChunkBuffer.length + dataSubChunkBuffer.length, 4)
|
|
27
|
-
riffChunkHeaderBuffer.write(
|
|
27
|
+
riffChunkHeaderBuffer.write('WAVE', 8, 'ascii')
|
|
28
28
|
|
|
29
29
|
return Buffer.concat([riffChunkHeaderBuffer, formatSubChunkBuffer, dataSubChunkBuffer])
|
|
30
30
|
}
|
|
@@ -32,10 +32,10 @@ export function encodeWave(rawAudio: RawAudio, bitDepth: BitDepth = 16, sampleFo
|
|
|
32
32
|
export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
33
33
|
let readOffset = 0
|
|
34
34
|
|
|
35
|
-
const riffId = waveData.subarray(readOffset, readOffset + 4).toString(
|
|
35
|
+
const riffId = waveData.subarray(readOffset, readOffset + 4).toString('ascii')
|
|
36
36
|
|
|
37
|
-
if (riffId !=
|
|
38
|
-
throw new Error(
|
|
37
|
+
if (riffId != 'RIFF') {
|
|
38
|
+
throw new Error('Not a valid wave file. No RIFF id found at offset 0.')
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
readOffset += 4
|
|
@@ -44,10 +44,10 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
44
44
|
|
|
45
45
|
readOffset += 4
|
|
46
46
|
|
|
47
|
-
const waveId = waveData.subarray(readOffset, readOffset + 4).toString(
|
|
47
|
+
const waveId = waveData.subarray(readOffset, readOffset + 4).toString('ascii')
|
|
48
48
|
|
|
49
|
-
if (waveId !=
|
|
50
|
-
throw new Error(
|
|
49
|
+
if (waveId != 'WAVE') {
|
|
50
|
+
throw new Error('Not a valid wave file. No WAVE id found at offset 8.')
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if (riffChunkSize < waveData.length - 8) {
|
|
@@ -64,7 +64,7 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
64
64
|
const dataBuffers: Buffer[] = []
|
|
65
65
|
|
|
66
66
|
while (true) {
|
|
67
|
-
const subChunkIdentifier = waveData.subarray(readOffset, readOffset + 4).toString(
|
|
67
|
+
const subChunkIdentifier = waveData.subarray(readOffset, readOffset + 4).toString('ascii')
|
|
68
68
|
readOffset += 4
|
|
69
69
|
|
|
70
70
|
const subChunkSize = waveData.readUInt32LE(readOffset)
|
|
@@ -74,11 +74,11 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
74
74
|
throw new Error(`Encountered a '${subChunkIdentifier}' subchunk with a size of ${subChunkSize} which is greater than the remaining size of the buffer (${waveData.length - readOffset})`)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
if (subChunkIdentifier ==
|
|
77
|
+
if (subChunkIdentifier == 'fmt ') {
|
|
78
78
|
formatSubChunkBodyBuffer = waveData.subarray(readOffset, readOffset + subChunkSize)
|
|
79
|
-
} else if (subChunkIdentifier ==
|
|
79
|
+
} else if (subChunkIdentifier == 'data') {
|
|
80
80
|
if (!formatSubChunkBodyBuffer) {
|
|
81
|
-
throw new Error(
|
|
81
|
+
throw new Error('A data subchunk was encountered before a format subchunk')
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// If the data chunk is truncated, but truncations are ignored,
|
|
@@ -98,7 +98,7 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
if (!formatSubChunkBodyBuffer) {
|
|
101
|
-
throw new Error(
|
|
101
|
+
throw new Error('No format subchunk was found in the wave file')
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
const waveFormat = WaveFormat.deserializeFrom(formatSubChunkBodyBuffer)
|
|
@@ -161,7 +161,7 @@ class WaveFormat { // 24 bytes total for PCM, 26 for float
|
|
|
161
161
|
|
|
162
162
|
const result = Buffer.alloc(serializedSize)
|
|
163
163
|
|
|
164
|
-
result.write(
|
|
164
|
+
result.write('fmt ', 0, 'ascii') // + 4
|
|
165
165
|
result.writeUint32LE(serializedSize - 8, 4) // + 4
|
|
166
166
|
|
|
167
167
|
result.writeUint16LE(sampleFormatId, 8) // + 2
|
|
@@ -177,7 +177,7 @@ class WaveFormat { // 24 bytes total for PCM, 26 for float
|
|
|
177
177
|
result.writeUint32LE(this.speakerPositionMask, 28) // + 2 (speaker position mask)
|
|
178
178
|
|
|
179
179
|
if (this.sampleFormat == SampleFormat.PCM || this.sampleFormat == SampleFormat.Float) {
|
|
180
|
-
result.set(Buffer.from(this.guid,
|
|
180
|
+
result.set(Buffer.from(this.guid, 'hex'), 32)
|
|
181
181
|
} else {
|
|
182
182
|
throw new Error(`Extensible format is not supported for sample format ${this.sampleFormat}`)
|
|
183
183
|
}
|
|
@@ -200,7 +200,7 @@ class WaveFormat { // 24 bytes total for PCM, 26 for float
|
|
|
200
200
|
|
|
201
201
|
speakerPositionMask = formatChunkBody.readUint16LE(20)
|
|
202
202
|
|
|
203
|
-
const guid = formatChunkBody.subarray(24, 40).toString(
|
|
203
|
+
const guid = formatChunkBody.subarray(24, 40).toString('hex')
|
|
204
204
|
|
|
205
205
|
if (guid == sampleFormatToGuid[SampleFormat.PCM]) {
|
|
206
206
|
sampleFormat = SampleFormat.PCM
|
|
@@ -237,7 +237,7 @@ class WaveFormat { // 24 bytes total for PCM, 26 for float
|
|
|
237
237
|
|
|
238
238
|
export enum SampleFormat {
|
|
239
239
|
PCM = 1,
|
|
240
|
-
Float =
|
|
240
|
+
Float = 3,
|
|
241
241
|
Alaw = 6,
|
|
242
242
|
Mulaw = 7,
|
|
243
243
|
}
|
|
@@ -253,8 +253,8 @@ const sampleFormatToSerializedSize = {
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
const sampleFormatToGuid = {
|
|
256
|
-
[SampleFormat.PCM]:
|
|
257
|
-
[SampleFormat.Float]:
|
|
258
|
-
[SampleFormat.Alaw]:
|
|
259
|
-
[SampleFormat.Mulaw]:
|
|
256
|
+
[SampleFormat.PCM]: '0100000000001000800000aa00389b71',
|
|
257
|
+
[SampleFormat.Float]: '0300000000001000800000aa00389b71',
|
|
258
|
+
[SampleFormat.Alaw]: '',
|
|
259
|
+
[SampleFormat.Mulaw]: '',
|
|
260
260
|
}
|
package/src/denoising/RNNoise.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { float32ToInt16Pcm } from
|
|
2
|
-
import { concatFloat32Arrays } from
|
|
3
|
-
import { WasmMemoryManager } from
|
|
4
|
-
import { Logger } from
|
|
5
|
-
import { RawAudio, cloneRawAudio } from
|
|
1
|
+
import { float32ToInt16Pcm } from '../audio/AudioBufferConversion.js'
|
|
2
|
+
import { concatFloat32Arrays } from '../utilities/Utilities.js'
|
|
3
|
+
import { WasmMemoryManager } from '../utilities/WasmMemoryManager.js'
|
|
4
|
+
import { Logger } from '../utilities/Logger.js'
|
|
5
|
+
import { RawAudio, cloneRawAudio } from '../audio/AudioUtilities.js'
|
|
6
6
|
|
|
7
7
|
let rnnoiseInstance: any
|
|
8
8
|
|
|
9
9
|
export async function denoiseAudio(rawAudio: RawAudio) {
|
|
10
10
|
const logger = new Logger()
|
|
11
11
|
if (rawAudio.sampleRate != 48000) {
|
|
12
|
-
throw new Error(
|
|
12
|
+
throw new Error('Sample rate must be 48000')
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
if (rawAudio.audioChannels.length != 1) {
|
|
16
|
-
throw new Error(
|
|
16
|
+
throw new Error('Channel count must be 1')
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
if (rawAudio.audioChannels[0].length == 0) {
|
|
20
20
|
return { denoisedRawAudio: cloneRawAudio(rawAudio), frameVadProbabilities: [] }
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
logger.start(
|
|
23
|
+
logger.start('Get RNNoise WASM instance')
|
|
24
24
|
const m = await getRnnoiseInstance()
|
|
25
25
|
|
|
26
|
-
logger.start(
|
|
26
|
+
logger.start('Process with RNNoise')
|
|
27
27
|
const wasmMemory = new WasmMemoryManager(m)
|
|
28
28
|
|
|
29
29
|
const stateSize = m._rnnoise_get_size()
|
package/src/dsp/BiquadFilter.ts
CHANGED
|
@@ -11,35 +11,35 @@
|
|
|
11
11
|
// https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode
|
|
12
12
|
|
|
13
13
|
export function createLowpassFilter(sampleRate: number, cutoffFrequency: number, q = 0.7071) {
|
|
14
|
-
return createFilter(
|
|
14
|
+
return createFilter('lowpass', sampleRate, cutoffFrequency, q, 0)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function createHighpassFilter(sampleRate: number, cutoffFrequency: number, q = 0.7071) {
|
|
18
|
-
return createFilter(
|
|
18
|
+
return createFilter('highpass', sampleRate, cutoffFrequency, q, 0)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export function createBandpassFilter(sampleRate: number, centerFrequency: number, q = 1) {
|
|
22
|
-
return createFilter(
|
|
22
|
+
return createFilter('bandpass', sampleRate, centerFrequency, q, 0)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function createLowshelfFilter(sampleRate: number, midpointFrequency: number, gain: number) {
|
|
26
|
-
return createFilter(
|
|
26
|
+
return createFilter('lowshelf', sampleRate, midpointFrequency, 0, gain)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function createHighshelfFilter(sampleRate: number, midpointFrequency: number, gain: number) {
|
|
30
|
-
return createFilter(
|
|
30
|
+
return createFilter('highshelf', sampleRate, midpointFrequency, 0, gain)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function createPeakingFilter(sampleRate: number, centerFrequency: number, q = 1, gain = 0) {
|
|
34
|
-
return createFilter(
|
|
34
|
+
return createFilter('peaking', sampleRate, centerFrequency, q, gain)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export function createNotchFilter(sampleRate: number, centerFrequency: number, q = 1) {
|
|
38
|
-
return createFilter(
|
|
38
|
+
return createFilter('notch', sampleRate, centerFrequency, q, 0)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function createAllpassFilter(sampleRate: number, centerFrequency: number, q = 1) {
|
|
42
|
-
return createFilter(
|
|
42
|
+
return createFilter('allpass', sampleRate, centerFrequency, q, 0)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function createFilter(filterType: FilterType, sampleRate: number, frequency: number, q: number, gain: number) {
|
|
@@ -65,7 +65,7 @@ export class BiquadFilter {
|
|
|
65
65
|
this.setCoefficients(coefficients)
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
filter(sample: number): number {
|
|
69
69
|
const filteredSample =
|
|
70
70
|
(this.b0 * sample) +
|
|
71
71
|
(this.b1 * this.prevInput1) +
|
|
@@ -82,9 +82,9 @@ export class BiquadFilter {
|
|
|
82
82
|
return filteredSample
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
filterSamplesInPlace(samples: Float32Array) {
|
|
86
86
|
for (let i = 0; i < samples.length; i++) {
|
|
87
|
-
samples[i] = this.
|
|
87
|
+
samples[i] = this.filter(samples[i])
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -486,3 +486,11 @@ export type FilterCoefficients = {
|
|
|
486
486
|
a1: number
|
|
487
487
|
a2: number
|
|
488
488
|
}
|
|
489
|
+
|
|
490
|
+
export const emptyBiquadCoefficients: FilterCoefficients = {
|
|
491
|
+
b0: 0,
|
|
492
|
+
b1: 0,
|
|
493
|
+
b2: 0,
|
|
494
|
+
a1: 0,
|
|
495
|
+
a2: 0,
|
|
496
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class DecayingPeakEstimator {
|
|
2
|
+
public readonly decayPerTick: number
|
|
3
|
+
|
|
4
|
+
currentPeak: number
|
|
5
|
+
|
|
6
|
+
constructor(
|
|
7
|
+
public readonly options: DecayingPeakEstimatorOptions,
|
|
8
|
+
public readonly ticksPerSecond: number) {
|
|
9
|
+
|
|
10
|
+
this.currentPeak = options.initialPeak
|
|
11
|
+
this.decayPerTick = this.options.decayPerSecond / this.ticksPerSecond
|
|
12
|
+
|
|
13
|
+
this.process = options.kind === 'maximum' ? this.processMaximum : this.processMinimum
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public readonly process: (value: number) => void
|
|
17
|
+
|
|
18
|
+
private processMaximum(value: number) {
|
|
19
|
+
this.currentPeak -= this.decayPerTick
|
|
20
|
+
this.currentPeak = Math.max(value, this.currentPeak)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private processMinimum(value: number) {
|
|
24
|
+
this.currentPeak += this.decayPerTick
|
|
25
|
+
this.currentPeak = Math.min(value, this.currentPeak)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface DecayingPeakEstimatorOptions {
|
|
30
|
+
kind: DecayingPeakEstimatorKind
|
|
31
|
+
decayPerSecond: number
|
|
32
|
+
initialPeak: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type DecayingPeakEstimatorKind = 'maximum' | 'minimum'
|