read-wasm-sf2
Version:
ports some parts of https://github.com/schellingb/TinySoundFont to wasm.
66 lines (53 loc) • 1.99 kB
JavaScript
import Module from './read.js';
let api;
let module;
export async function init() {
const module = await Module();
api = {
init: module.cwrap("init_tsf", "", []),
load_sound: module.cwrap("load_sound", "", ["number", "number", "number", "number", "number"]),
...module
};
api.init();
}
export async function loadSF(presetId, note, velocity, duration) {
if (!api) {
await init();
}
const metaquery =
console.log("loading " + note);
const { _malloc, _free, load_sound, HEAPF32 } = api;
const n = duration * 48000 + 4 + 2;
const buffer = _malloc(n * Float32Array.BYTES_PER_ELEMENT);
console.log('ptr' + buffer);
api.load_sound(buffer, presetId, note, 120, n);
// const [pitchRatio, sampleRate, attack, hold, decay, sustain, release, lpf_cf, lpf_q, ...sound] = new Float32Array(HEAPF32.buffer, buffer, n);
const r = new Float32Array(HEAPF32.buffer, buffer, n);
_free(buffer);
return r; //new Float32Array(Module.HEAPF32.buffer, resPtr, n)
}
const ctx = new AudioContext({ sampleRate: 31000 });
let t0;
for (let i = 21; i < 88; i++) {
const button = document.createElement("button");
button.innerHTML = `${i}`;
let t0;
button.onmousedown = () => {
play(0, i);
};
document.body.append(button);
}
function play(preset, i) {
let vel = !t0 ? 50 : (performance.now() - t0) / 100;
t0 = performance.now();
loadSF(0, i, 55, 1).then(sound => {
const ab = new AudioBuffer({ numberOfChannels: 1, length: sound.length, sampleRate: 31000 });
ab.copyToChannel(sound, 0);
// console.log(Math.sqrt(sound.reduce((sum, v) => sum += v * v, 0) / 31000));
const abs = new AudioBufferSourceNode(ctx, { buffer: ab })
// const g = new GainNode(ctx);
// g.gain.exponentialRampToValueAtTime(sustain / 2, Math.pow(2, decay / 12000));
abs.connect(ctx.destination);
abs.start();
});
}