|
|
|
|
|
function webWavPlay(f32array){
|
|
const blob = float32ArrayToWav(f32array)
|
|
const url = createObjectUrlFromBlob(blob)
|
|
playAudioFromUrl(url)
|
|
return blob
|
|
}
|
|
|
|
function createObjectUrlFromBlob(blob) {
|
|
const url = URL.createObjectURL(blob);
|
|
return url;
|
|
}
|
|
|
|
function playAudioFromUrl(url) {
|
|
const audio = new Audio(url);
|
|
audio.play().catch(error => console.error('Failed to play audio:', error));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function float32ArrayToWav(floatSamples, sampleRate=22050) {
|
|
let samples = new Int16Array(floatSamples.length);
|
|
for (let i = 0; i < samples.length; ++i) {
|
|
let s = floatSamples[i];
|
|
if (s >= 1)
|
|
s = 1;
|
|
else if (s <= -1)
|
|
s = -1;
|
|
|
|
samples[i] = s * 32767;
|
|
}
|
|
|
|
let buf = new ArrayBuffer(44 + samples.length * 2);
|
|
var view = new DataView(buf);
|
|
|
|
|
|
|
|
view.setUint32(0, 0x46464952, true);
|
|
view.setUint32(4, 36 + samples.length * 2, true);
|
|
|
|
view.setUint32(8, 0x45564157, true);
|
|
|
|
|
|
view.setUint32(12, 0x20746d66, true);
|
|
view.setUint32(16, 16, true);
|
|
view.setUint32(20, 1, true);
|
|
view.setUint16(22, 1, true);
|
|
view.setUint32(24, sampleRate, true);
|
|
view.setUint32(28, sampleRate * 2, true);
|
|
view.setUint16(32, 2, true);
|
|
view.setUint16(34, 16, true);
|
|
view.setUint32(36, 0x61746164, true);
|
|
view.setUint32(40, samples.length * 2, true);
|
|
|
|
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'});
|
|
}
|
|
|
|
export { webWavPlay }; |