Files
SonicForgeStudio/app/static/js/services/soundfontPlayer.js
T

76 lines
2.7 KiB
JavaScript

// SonicForge Studio SoundFont Player Service
(function () {
'use strict';
// Web Audio API fallback synth
let audioCtx = null;
let gainNode = null;
const activeOscillators = {};
function getCtx() {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
gainNode = audioCtx.createGain();
gainNode.gain.value = 0.3;
gainNode.connect(audioCtx.destination);
}
return audioCtx;
}
const SonicSF = {
loadedFonts: {},
// Load SoundFont from URL → ArrayBuffer → store in memory
loadSoundFont: async function (url) {
if (this.loadedFonts[url]) return this.loadedFonts[url];
const resp = await fetch(url);
if (!resp.ok) throw new Error('Failed to load SoundFont: ' + url);
const buffer = await resp.arrayBuffer();
this.loadedFonts[url] = buffer;
return buffer;
},
// Play a MIDI note using Web Audio fallback
playNote: function (note, velocity, durationMs) {
const ctx = getCtx();
const freq = 440 * Math.pow(2, (note - 69) / 12);
const osc = ctx.createOscillator();
const noteGain = ctx.createGain();
osc.type = 'triangle';
osc.frequency.value = freq;
noteGain.gain.setValueAtTime(velocity / 127 * 0.3, ctx.currentTime);
noteGain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + durationMs / 1000);
osc.connect(noteGain);
noteGain.connect(ctx.destination);
osc.start(ctx.currentTime);
osc.stop(ctx.currentTime + durationMs / 1000 + 0.05);
activeOscillators[note] = osc;
return osc;
},
stopAll: function () {
Object.values(activeOscillators).forEach(osc => {
try { osc.stop(); } catch (e) { }
});
Object.keys(activeOscillators).forEach(k => delete activeOscillators[k]);
},
// Save user SoundFont to IndexedDB via window.SonicStorage
saveToIndexedDB: async function (name, arrayBuffer) {
if (window.SonicStorage && window.SonicStorage.saveToIndexedDB) {
await window.SonicStorage.saveToIndexedDB('soundfont_' + name, arrayBuffer);
}
},
// Load user SoundFont from IndexedDB
loadFromIndexedDB: async function (name) {
if (window.SonicStorage && window.SonicStorage.loadFromIndexedDB) {
return await window.SonicStorage.loadFromIndexedDB('soundfont_' + name);
}
return null;
}
};
window.SonicSF = SonicSF;
})();