diff --git a/repl/src/App.jsx b/repl/src/App.jsx index a95fec0a..27c7310a 100644 --- a/repl/src/App.jsx +++ b/repl/src/App.jsx @@ -12,6 +12,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from import './App.css'; import logo from './logo.svg'; import * as tunes from './tunes.mjs'; +import { prebake } from './prebake.mjs'; import * as WebDirt from 'WebDirt'; import { loadWebDirt } from '@strudel.cycles/webdirt'; import { resetLoadedSamples, getAudioContext } from '@strudel.cycles/webaudio'; @@ -46,6 +47,8 @@ loadWebDirt({ sampleFolder: 'EmuSP12', }); +prebake(); + async function initCode() { // load code from url hash (either short hash from database or decode long hash) try { @@ -218,6 +221,7 @@ function App() { cleanupDraw(); cleanupUi(); resetLoadedSamples(); + prebake(); const parsed = await evaluate(_code); setPattern(parsed.pattern); setActiveCode(_code); diff --git a/repl/src/prebake.mjs b/repl/src/prebake.mjs new file mode 100644 index 00000000..94edd48b --- /dev/null +++ b/repl/src/prebake.mjs @@ -0,0 +1,55 @@ +import { Pattern, toMidi } from '@strudel.cycles/core'; +import { samples } from '@strudel.cycles/webaudio'; + +export function prebake() { + samples( + { + piano: { + A0: 'A0v8.mp3', + C1: 'C1v8.mp3', + Ds1: 'Ds1v8.mp3', + Fs1: 'Fs1v8.mp3', + A1: 'A1v8.mp3', + C2: 'C2v8.mp3', + Ds2: 'Ds2v8.mp3', + Fs2: 'Fs2v8.mp3', + A2: 'A2v8.mp3', + C3: 'C3v8.mp3', + Ds3: 'Ds3v8.mp3', + Fs3: 'Fs3v8.mp3', + A3: 'A3v8.mp3', + C4: 'C4v8.mp3', + Ds4: 'Ds4v8.mp3', + Fs4: 'Fs4v8.mp3', + A4: 'A4v8.mp3', + C5: 'C5v8.mp3', + Ds4: 'Ds4v8.mp3', + Fs5: 'Fs5v8.mp3', + A5: 'A5v8.mp3', + C6: 'C6v8.mp3', + Ds6: 'Ds6v8.mp3', + Fs6: 'Fs6v8.mp3', + A6: 'A6v8.mp3', + C7: 'C7v8.mp3', + Ds7: 'Ds7v8.mp3', + Fs7: 'Fs7v8.mp3', + A7: 'A7v8.mp3', + C8: 'C8v8.mp3', + }, + }, + 'https://tambien.github.io/Piano/audio/', + ); +} + +const maxPan = toMidi('C8'); +const panwidth = (pan, width) => pan * width + (1 - width) / 2; + +Pattern.prototype.piano = function () { + return this.choke(1) + .s('piano') + .fmap((value) => { + // pan by pitch + const pan = panwidth(Math.min(toMidi(value.note) / maxPan, 1), 0.5); + return { ...value, pan: (value.pan || 1) * pan }; + }); +};