basic sample loader from github

This commit is contained in:
Felix Roos 2022-05-29 21:06:07 +02:00
parent 9147b4e39f
commit 91dfef52ea
3 changed files with 83 additions and 2 deletions

View File

@ -1 +1,2 @@
export * from './webdirt.mjs';
export * from './sampler.mjs';

View File

@ -0,0 +1,65 @@
const bufferCache = {}; // string: Promise<ArrayBuffer>
export const loadBuffer = (url, ac) => {
if (!bufferCache[url]) {
bufferCache[url] = fetch(url)
.then((res) => res.arrayBuffer())
.then((res) => ac.decodeAudioData(res));
}
return bufferCache[url];
};
/* export const playBuffer = (buffer, time = ac.currentTime, destination = ac.destination) => {
const src = ac.createBufferSource();
src.buffer = buffer;
src.connect(destination);
src.start(time);
};
export const playSample = async (url) => playBuffer(await loadBuffer(url)); */
// https://estuary.mcmaster.ca/samples/resources.json
// Array<{ "url":string, "bank": string, "n": number}>
// ritchse/tidal-drum-machines/tree/main/machines/AkaiLinn
const githubCache = {};
let loaded;
export const loadGithubSamples = async (path, nameFn) => {
if (githubCache[path]) {
return githubCache[path];
}
try {
console.log('load github path', path);
const [user, repo, ...folders] = path.split('/');
const baseUrl = `https://api.github.com/repos/${user}/${repo}/contents`;
const banks = await fetch(`${baseUrl}/${folders.join('/')}`).then((res) => res.json());
// fetch each subfolder
githubCache[path] = (
await Promise.all(
banks.map(async ({ name, path }) => ({
name,
content: await fetch(`${baseUrl}/${path}`)
.then((res) => res.json())
.catch((err) => {
console.error('could not load path', err);
}),
})),
)
)
.filter(({ content }) => !!content)
.reduce(
(acc, { name, content }) => ({
...acc,
[nameFn?.(name) || name]: content.map(({ download_url }) => download_url),
}),
{},
);
} catch (err) {
console.error('failed to fetch github samples', err);
return;
}
loaded = githubCache[path];
console.log('loaded github path ', path);
return githubCache[path];
};
export const getLoadedSamples = () => loaded;

View File

@ -1,6 +1,7 @@
import * as strudel from '@strudel.cycles/core';
const { Pattern } = strudel;
import * as WebDirt from 'WebDirt';
import { getLoadedSamples, loadBuffer } from './sampler.mjs';
let webDirt;
@ -62,7 +63,7 @@ export function loadWebDirt(config) {
Pattern.prototype.webdirt = function () {
// create a WebDirt object and initialize Web Audio context
return this._withHap((hap) => {
const onTrigger = (time, e, currentTime) => {
const onTrigger = async (time, e, currentTime) => {
if (!webDirt) {
throw new Error('WebDirt not initialized!');
}
@ -71,7 +72,21 @@ Pattern.prototype.webdirt = function () {
if (!s) {
console.warn('webdirt: no "s" was set!');
}
webDirt.playSample({ s, n, ...rest }, deadline);
const samples = getLoadedSamples();
if (!samples?.[s]) {
// try default samples
webDirt.playSample({ s, n, ...rest }, deadline);
return;
}
if (!samples?.[s]) {
console.warn(`webdirt: sample "${s}" not found in loaded samples`, samples);
} else {
const bank = samples[s];
const sampleUrl = bank[n % bank.length];
const buffer = await loadBuffer(sampleUrl, webDirt.ac);
const msg = { buffer: { buffer }, ...rest };
webDirt.playSample(msg, deadline);
}
};
return hap.setContext({ ...hap.context, onTrigger });
});