136 lines
4.4 KiB
JavaScript
136 lines
4.4 KiB
JavaScript
|
|
const fileInput = document.getElementById('fileInput');
|
|
|
|
let speech_denoiser = null;
|
|
const inAudioPlayback = document.getElementById('inAudioPlayback');
|
|
const outAudioPlayback = document.getElementById('outAudioPlayback');
|
|
|
|
Module = {};
|
|
|
|
// https://emscripten.org/docs/api_reference/module.html#Module.locateFile
|
|
Module.locateFile = function(path, scriptDirectory = '') {
|
|
console.log(`path: ${path}, scriptDirectory: ${scriptDirectory}`);
|
|
return scriptDirectory + path;
|
|
};
|
|
|
|
// https://emscripten.org/docs/api_reference/module.html#Module.locateFile
|
|
Module.setStatus = function(status) {
|
|
console.log(`status ${status}`);
|
|
const statusElement = document.getElementById('status');
|
|
statusElement.textContent = status;
|
|
if (status === '') {
|
|
statusElement.style.display = 'none';
|
|
document.querySelectorAll('.tab-content').forEach((tabContentElement) => {
|
|
tabContentElement.classList.remove('loading');
|
|
});
|
|
} else {
|
|
statusElement.style.display = 'block';
|
|
document.querySelectorAll('.tab-content').forEach((tabContentElement) => {
|
|
tabContentElement.classList.add('loading');
|
|
});
|
|
}
|
|
};
|
|
|
|
Module.onRuntimeInitialized = function() {
|
|
console.log('Model files downloaded!');
|
|
|
|
console.log('Initializing speech denoiser ......');
|
|
speech_denoiser = createOfflineSpeechDenoiser(Module)
|
|
};
|
|
|
|
async function process(wave) {
|
|
let denoised = speech_denoiser.run(wave.samples, wave.sampleRate);
|
|
console.log(denoised);
|
|
|
|
let int16Samples = new Int16Array(denoised.samples.length);
|
|
for (var i = 0; i < denoised.samples.length; ++i) {
|
|
let s = denoised.samples[i];
|
|
if (s >= 1)
|
|
s = 1;
|
|
else if (s <= -1)
|
|
s = -1;
|
|
|
|
int16Samples[i] = s * 32767;
|
|
}
|
|
|
|
let blob = toWav(int16Samples, denoised.sampleRate);
|
|
const objectUrl = URL.createObjectURL(blob);
|
|
console.log(objectUrl);
|
|
|
|
outAudioPlayback.src = objectUrl;
|
|
outAudioPlayback.controls = true;
|
|
outAudioPlayback.style.display = 'block';
|
|
}
|
|
|
|
fileInput.addEventListener('change', function(event) {
|
|
if (!event.target.files || !event.target.files[0]) {
|
|
console.log('No file selected.');
|
|
return;
|
|
}
|
|
|
|
const file = event.target.files[0];
|
|
console.log('Selected file:', file.name, file.type, file.size, 'bytes');
|
|
const reader = new FileReader();
|
|
reader.onload = function(ev) {
|
|
console.log('FileReader onload called.');
|
|
const arrayBuffer = ev.target.result;
|
|
console.log('ArrayBuffer length:', arrayBuffer.byteLength);
|
|
|
|
const uint8Array = new Uint8Array(arrayBuffer);
|
|
const wave = readWaveFromBinaryData(uint8Array);
|
|
if (wave == null) {
|
|
alert(
|
|
`${file.name} is not a valid .wav file. Please select a *.wav file`);
|
|
return;
|
|
}
|
|
|
|
|
|
var url = URL.createObjectURL(file);
|
|
console.log(`url: ${url}`);
|
|
inAudioPlayback.src = url;
|
|
inAudioPlayback.style.display = 'block';
|
|
|
|
process(wave)
|
|
console.log('process done')
|
|
};
|
|
reader.onerror = function(err) {
|
|
console.error('FileReader error:', err);
|
|
};
|
|
console.log('Starting FileReader.readAsArrayBuffer...');
|
|
reader.readAsArrayBuffer(file);
|
|
});
|
|
|
|
// this function is copied/modified from
|
|
// https://gist.github.com/meziantou/edb7217fddfbb70e899e
|
|
function toWav(samples, sampleRate) {
|
|
let buf = new ArrayBuffer(44 + samples.length * 2);
|
|
var view = new DataView(buf);
|
|
|
|
// http://soundfile.sapp.org/doc/WaveFormat/
|
|
// F F I R
|
|
view.setUint32(0, 0x46464952, true); // chunkID
|
|
view.setUint32(4, 36 + samples.length * 2, true); // chunkSize
|
|
// E V A W
|
|
view.setUint32(8, 0x45564157, true); // format
|
|
//
|
|
// t m f
|
|
view.setUint32(12, 0x20746d66, true); // subchunk1ID
|
|
view.setUint32(16, 16, true); // subchunk1Size, 16 for PCM
|
|
view.setUint32(20, 1, true); // audioFormat, 1 for PCM
|
|
view.setUint16(22, 1, true); // numChannels: 1 channel
|
|
view.setUint32(24, sampleRate, true); // sampleRate
|
|
view.setUint32(28, sampleRate * 2, true); // byteRate
|
|
view.setUint16(32, 2, true); // blockAlign
|
|
view.setUint16(34, 16, true); // bitsPerSample
|
|
view.setUint32(36, 0x61746164, true); // Subchunk2ID
|
|
view.setUint32(40, samples.length * 2, true); // subchunk2Size
|
|
|
|
let offset = 44;
|
|
for (let i = 0; i < samples.length; ++i) {
|
|
view.setInt16(offset, samples[i], true);
|
|
offset += 2;
|
|
}
|
|
|
|
return new Blob([view], {type: 'audio/wav'});
|
|
}
|