strudel-docker/docs/dist/useCycle.js
2022-02-05 13:12:05 +01:00

52 lines
1.8 KiB
JavaScript

import {useEffect, useState} from "../_snowpack/pkg/react.js";
import * as Tone from "../_snowpack/pkg/tone.js";
import {TimeSpan} from "../_snowpack/link/strudel.js";
function useCycle(props) {
const {onEvent, onQuery, onSchedule, ready = true} = props;
const [started, setStarted] = useState(false);
const cycleDuration = 1;
const activeCycle = () => Math.floor(Tone.Transport.seconds / cycleDuration);
const query = (cycle = activeCycle()) => {
const timespan = new TimeSpan(cycle, cycle + 1);
const _events = onQuery?.(timespan) || [];
onSchedule?.(_events, cycle);
schedule(_events, cycle);
};
const schedule = (events, cycle = activeCycle()) => {
const timespan = new TimeSpan(cycle, cycle + 1);
const cancelFrom = timespan.begin.valueOf();
Tone.Transport.cancel(cancelFrom);
const queryNextTime = (cycle + 1) * cycleDuration - 0.1;
Tone.Transport.schedule(() => {
query(cycle + 1);
}, queryNextTime);
events?.forEach((event) => {
Tone.Transport.schedule((time) => {
const toneEvent = {
time: event.part.begin.valueOf(),
duration: event.part.end.valueOf() - event.part.begin.valueOf(),
value: event.value
};
onEvent(time, toneEvent);
}, event.part.begin.valueOf());
});
};
useEffect(() => {
ready && query();
}, [onEvent, onSchedule, onQuery]);
const start = async () => {
console.log("start");
setStarted(true);
await Tone.start();
Tone.Transport.start("+0.1");
};
const stop = () => {
console.log("stop");
setStarted(false);
Tone.Transport.pause();
};
const toggle = () => started ? stop() : start();
return {start, stop, onEvent, started, toggle, schedule, query, activeCycle};
}
export default useCycle;