merge evaluator and scheduler hooks + use getTime

This commit is contained in:
Felix Roos 2022-08-21 11:21:19 +02:00
parent 2172d1a767
commit 9497c99e9e
4 changed files with 57 additions and 63 deletions

View File

@ -2,10 +2,9 @@ import controls from '@strudel.cycles/core/controls.mjs';
import { evalScope } from '@strudel.cycles/eval';
import { getAudioContext, panic, webaudioOutput } from '@strudel.cycles/webaudio';
import { useCallback, useState } from 'react';
import useScheduler from '../../../src/hooks/useScheduler';
import useEvaluator from '../../../src/hooks/useEvaluator';
import useKeydown from '../../../src/hooks/useKeydown.mjs';
import CodeMirror, { flash } from '../../../src/components/CodeMirror6';
import useKeydown from '../../../src/hooks/useKeydown.mjs';
import useStrudel from '../../../src/hooks/useStrudel';
import './style.css';
// import { prebake } from '../../../../../repl/src/prebake.mjs';
@ -63,16 +62,21 @@ stack(
.echoWith(4,.125,(x,n)=>x.gain(.15*1/(n+1))) // echo notes
//.hush()
)
.cps(2/3)`;
.fast(2/3)`;
// await prebake();
const ctx = getAudioContext();
function App() {
const [code, setCode] = useState(defaultTune);
const { evaluate, pattern, isDirty, error: evaluatorError } = useEvaluator({ code });
const { scheduler, error: schedulerError } = useScheduler(pattern, webaudioOutput);
const { scheduler, evaluate, schedulerError, evalError, isDirty } = useStrudel({
code,
defaultOutput: webaudioOutput,
getTime: () => ctx.currentTime,
});
const [view, setView] = useState();
const error = evaluatorError || schedulerError;
const error = evalError || schedulerError;
useKeydown(
useCallback(
(e) => {
@ -105,8 +109,8 @@ function App() {
<nav className="z-[12] w-full flex justify-center absolute bottom-0">
<div className="bg-slate-500 space-x-2 px-2 rounded-t-md">
<button
onClick={() => {
getAudioContext().resume();
onClick={async () => {
await getAudioContext().resume();
scheduler.start();
}}
>

View File

@ -1,36 +0,0 @@
import { useRef, useState, useCallback, useEffect } from 'react';
import { evaluate as _evaluate } from '@strudel.cycles/eval';
function useEvaluator({ code, evalOnMount = true }) {
const [error, setError] = useState();
const [activeCode, setActiveCode] = useState(code);
const [pattern, setPattern] = useState();
const isDirty = code !== activeCode;
const evaluate = useCallback(async () => {
if (!code) {
console.log('no code..');
return;
}
try {
// TODO: let user inject custom eval function?
const { pattern: _pattern } = await _evaluate(code);
setActiveCode(code);
setPattern(_pattern);
setError();
} catch (err) {
setError(err);
console.warn('eval error', err);
}
}, [code, scheduler]);
const inited = useRef();
useEffect(() => {
if (!inited.current && evalOnMount) {
inited.current = true;
evaluate();
}
}, [evaluate, evalOnMount]);
return { error, evaluate, activeCode, pattern, isDirty };
}
export default useEvaluator;

View File

@ -1,18 +0,0 @@
import { Scheduler } from '@strudel.cycles/core';
import { useEffect, useMemo, useState } from 'react';
function useScheduler(pattern, defaultOutput, interval = 0.1) {
const [error, setError] = useState();
// TODO: how / when to remove schedulerError?
const scheduler = useMemo(
() => new Scheduler({ interval, onTrigger: defaultOutput, onError: setError }),
[defaultOutput, interval],
);
useEffect(() => {
// console.log('pattern', pattern);
pattern && scheduler?.setPattern(pattern);
}, [pattern, scheduler]);
return { error, scheduler };
}
export default useScheduler;

View File

@ -0,0 +1,44 @@
import { Scheduler } from '@strudel.cycles/core';
import { useRef, useCallback, useEffect, useMemo, useState } from 'react';
import { evaluate as _evaluate } from '@strudel.cycles/eval';
function useStrudel({ defaultOutput, interval, getTime, code, evalOnMount = true }) {
// scheduler
const [schedulerError, setSchedulerError] = useState();
const [evalError, setEvalError] = useState();
const [activeCode, setActiveCode] = useState(code);
const isDirty = code !== activeCode;
// TODO: how / when to remove schedulerError?
const scheduler = useMemo(
() => new Scheduler({ interval, onTrigger: defaultOutput, onError: setSchedulerError, getTime }),
[defaultOutput, interval],
);
const evaluate = useCallback(async () => {
if (!code) {
console.log('no code..');
return;
}
try {
// TODO: let user inject custom eval function?
const { pattern } = await _evaluate(code);
setActiveCode(code);
scheduler?.setPattern(pattern);
setEvalError();
} catch (err) {
setEvalError(err);
console.warn('eval error', err);
}
}, [code, scheduler]);
const inited = useRef();
useEffect(() => {
if (!inited.current && evalOnMount) {
inited.current = true;
evaluate();
}
}, [evaluate, evalOnMount]);
return { schedulerError, scheduler, evalError, evaluate, activeCode, isDirty };
}
export default useStrudel;