diff --git a/site/package.json b/site/package.json index 7c880aa..f802f59 100644 --- a/site/package.json +++ b/site/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "smplr": "link:..", + "soundfont2": "^0.4.0", "tonal": "^6.2.0", "webmidi": "^3.1.11" }, diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index d58ef7d..3dfcac9 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: smplr: specifier: link:.. version: link:.. + soundfont2: + specifier: ^0.4.0 + version: 0.4.0 tonal: specifier: ^6.2.0 version: 6.2.0 @@ -1588,6 +1591,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, tarball: https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz} engines: {node: '>=14'} + soundfont2@0.4.0: + resolution: {integrity: sha512-537WiurDBRbDLVhJMxXLE06D6yWxJCidfPClnibZ0f8dKMDpv+0fIfwCQ8pELE0JqKX05SOJosNJgKzQobaAEA==, tarball: https://registry.npmjs.org/soundfont2/-/soundfont2-0.4.0.tgz} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, tarball: https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz} engines: {node: '>=0.10.0'} @@ -3629,6 +3635,8 @@ snapshots: signal-exit@4.1.0: {} + soundfont2@0.4.0: {} + source-map-js@1.2.1: {} stop-iteration-iterator@1.0.0: diff --git a/site/src/Soundfont2Example.tsx b/site/src/Soundfont2Example.tsx index 3d3970b..32a33a5 100644 --- a/site/src/Soundfont2Example.tsx +++ b/site/src/Soundfont2Example.tsx @@ -35,16 +35,22 @@ export function Soundfont2Example({ className }: { className?: string }) { const [status, setStatus] = useStatus(); const [reverbMix, setReverbMix] = useState(0); const [volume, setVolume] = useState(100); + const [isCustomEnabled, setCustomEnabled] = useState(false); + const [customUrl, setCustomUrl] = useState( + "https://smpldsnds.github.io/soundfonts/soundfonts/yamaha-grand-lite.sf2" + ); - function loadSampler(sf2Name: string) { + function loadSampler(nameOrUrl: string) { if (sampler) sampler.disconnect(); setStatus("loading"); const context = getAudioContext(); - setSamplerName(sf2Name); + const isUrl = nameOrUrl.startsWith("http"); + setSamplerName(isUrl ? "_custom" : nameOrUrl); reverb ??= new Reverb(context); + const url = isUrl ? nameOrUrl : SF2_INSTRUMENTS[nameOrUrl]; const newSampler = new Soundfont2Sampler(context, { - url: SF2_INSTRUMENTS[sf2Name], + url, createSoundfont: (data) => new SoundFont2(data), }); newSampler.output.addEffect("reverb", reverb, reverbMix); @@ -70,17 +76,28 @@ export function Soundfont2Example({ className }: { className?: string }) { loadSampler("Supersaw")} + onClick={() => { + if (isCustomEnabled) { + loadSampler(customUrl); + } else { + loadSampler("Supersaw"); + } + }} /> -
+
+ { + setCustomUrl(e.target.value); + }} + />