mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-31 13:21:52 -04:00
96 lines
2.8 KiB
React
96 lines
2.8 KiB
React
import { evalScope } from '@strudel.cycles/eval';
|
|
import { MiniRepl as _MiniRepl } from '@strudel.cycles/react';
|
|
import controls from '@strudel.cycles/core/controls.mjs';
|
|
import { loadWebDirt } from '@strudel.cycles/webdirt';
|
|
import { materialPalenightLarge } from './materialPalenightThemeLarge';
|
|
import { useState, useEffect } from 'react';
|
|
import { cleanupDraw, cleanupUi, Tone, piano } from '@strudel.cycles/tone';
|
|
import { midi2note } from '@strudel.cycles/core';
|
|
import { prebake } from '../repl/src/prebake.mjs';
|
|
|
|
let defaultPiano;
|
|
piano().then((instrument) => {
|
|
defaultPiano = instrument.toDestination();
|
|
});
|
|
|
|
const init = evalScope(
|
|
Tone,
|
|
controls,
|
|
import('@strudel.cycles/core'),
|
|
import('@strudel.cycles/tone'),
|
|
import('@strudel.cycles/tonal'),
|
|
import('@strudel.cycles/mini'),
|
|
import('@strudel.cycles/midi'),
|
|
import('@strudel.cycles/xen'),
|
|
import('@strudel.cycles/webaudio'),
|
|
import('@strudel.cycles/osc'),
|
|
import('@strudel.cycles/webdirt'),
|
|
);
|
|
|
|
loadWebDirt({
|
|
sampleMapUrl: './samples/EmuSP12.json',
|
|
sampleFolder: './samples/EmuSP12/',
|
|
});
|
|
prebake();
|
|
|
|
export function MaxiRepl({ code, canvasHeight = 500 }) {
|
|
const [exampleIndex, setExampleIndex] = useState(0);
|
|
const examples = Array.isArray(code) ? code : [code];
|
|
const [ready, setReady] = useState(false);
|
|
useEffect(() => {
|
|
init.then(() => setReady(true));
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
cleanupDraw();
|
|
cleanupUi();
|
|
prebake();
|
|
}, [exampleIndex]);
|
|
return (
|
|
<div className="text-left block max-w-screen relative">
|
|
{examples.length > 1 && (
|
|
<div className="space-x-2 absolute left-[200px] top-[-3px]">
|
|
{examples.map((c, i) => (
|
|
<button
|
|
key={i}
|
|
onClick={() => setExampleIndex(i)}
|
|
className={`rounded-full ${exampleIndex === i ? 'bg-gray-200 w-5 h-5' : 'bg-gray-500 w-5 h-5'}`}
|
|
></button>
|
|
))}
|
|
</div>
|
|
)}
|
|
<_MiniRepl
|
|
enableKeyboard={true}
|
|
key={exampleIndex}
|
|
tune={examples[exampleIndex]}
|
|
hideOutsideView={true}
|
|
theme={materialPalenightLarge}
|
|
init={ready}
|
|
onEvent={(time, hap) => {
|
|
if (hap.context.onTrigger) {
|
|
// dont need default synth
|
|
return;
|
|
}
|
|
let velocity = hap.context?.velocity ?? 0.75;
|
|
note = hap.value;
|
|
if (typeof note === 'number') {
|
|
note = midi2note(note);
|
|
}
|
|
defaultPiano.keyDown({ note, time, velocity });
|
|
defaultPiano.keyUp({ note, time: time + hap.duration.valueOf(), velocity });
|
|
}}
|
|
/>
|
|
<canvas
|
|
id="test-canvas"
|
|
className="w-full pointer-events-none"
|
|
height={canvasHeight}
|
|
ref={(el) => {
|
|
if (el) {
|
|
el.width = el.clientWidth;
|
|
}
|
|
}}
|
|
></canvas>
|
|
</div>
|
|
);
|
|
}
|