diff --git a/website/src/docs/MicroRepl.jsx b/website/src/docs/MicroRepl.jsx index 7e97a9bb..778e209d 100644 --- a/website/src/docs/MicroRepl.jsx +++ b/website/src/docs/MicroRepl.jsx @@ -1,11 +1,10 @@ -import { useState, useRef, useCallback, useMemo } from 'react'; +import { useState, useRef, useCallback, useMemo, useEffect } from 'react'; import { Icon } from './Icon'; import { silence, getPunchcardPainter } from '@strudel.cycles/core'; import { transpiler } from '@strudel.cycles/transpiler'; import { getAudioContext, webaudioOutput } from '@strudel.cycles/webaudio'; import { StrudelMirror } from '@strudel/codemirror'; import { prebake } from '@strudel/repl'; -import { useInView } from 'react-hook-inview'; export function MicroRepl({ code, @@ -65,21 +64,26 @@ export function MicroRepl({ editorRef.current = editor; }, []); - const [ref, isVisible] = useInView({ - threshold: 0.01, - onEnter: () => { - if (!editorRef.current) { - init({ code, shouldDraw }); - } - }, - }); const [replState, setReplState] = useState({}); const { started, isDirty, error } = replState; const editorRef = useRef(); const containerRef = useRef(); + const [client, setClient] = useState(false); + useEffect(() => { + setClient(true); + if (!editorRef.current) { + setTimeout(() => { + init({ code, shouldDraw }); + }); + } + }, []); + + if (!client) { + return
{code}
; + } return ( -
+
{!hideHeader && (
@@ -117,11 +121,6 @@ export function MicroRepl({ if (el && el.width !== el.clientWidth) { el.width = el.clientWidth; } - //const ratio = el.clientWidth / canvasHeight; - //const targetWidth = Math.round(el.width * ratio); - //if (el.width !== targetWidth) { - // el.width = targetWidth; - //} }} > )} diff --git a/website/src/pages/recipes/recipes-next.mdx b/website/src/pages/recipes/recipes-next.mdx index 62a1a5e9..4230063f 100644 --- a/website/src/pages/recipes/recipes-next.mdx +++ b/website/src/pages/recipes/recipes-next.mdx @@ -17,7 +17,7 @@ An arpeggio is when the notes of a chord are played in sequence. We can either write the notes by hand: ") @@ -92,7 +92,7 @@ s("amen/8").fit() If we use `splice` instead of `slice`, the speed adjusts to the duration of the event: ") @@ -107,7 +107,7 @@ Note that we don't need `fit`, because `splice` will do that by itself. A minimal filter envelope looks like this: d2") .s("sawtooth") .lpf(400).lpa(.2).lpenv(4) @@ -117,7 +117,7 @@ A minimal filter envelope looks like this: We can flip the envelope by setting `lpenv` negative + add some resonance `lpq`: d2") .s("sawtooth").lpq(8) .lpf(400).lpa(.2).lpenv(-4) @@ -129,7 +129,7 @@ We can flip the envelope by setting `lpenv` negative + add some resonance `lpq`: We can layer sounds by separating them with ",": ") .s("sawtooth, square") // <------ .scope()`} @@ -138,7 +138,7 @@ We can layer sounds by separating them with ",": We can control the gain of individual sounds like this: ") .s("sawtooth, square:0:.5") // <--- "name:number:gain" .scope()`} @@ -147,7 +147,7 @@ We can control the gain of individual sounds like this: For more control over each voice, we can use `layer`: ").layer( x=>x.s("sawtooth").vib(4), x=>x.s("square").add(note(12)) @@ -162,7 +162,7 @@ With `layer`, you can use any pattern method available on each voice, so sky is We can fatten a sound by adding a detuned version to itself: ") .add(note("0,.1")) // <------ chorus .s("sawtooth").scope()`} @@ -175,7 +175,7 @@ Try out different values, or add another voice! Here is a simple example of a polyrhythm: - + A polyrhythm is when 2 different tempos happen at the same time. @@ -183,7 +183,7 @@ A polyrhythm is when 2 different tempos happen at the same time. This is a polymeter: -,").fast(2)`} punchcard /> +,").fast(2)`} punchcard /> A polymeter is when 2 different bar lengths play at the same tempo. @@ -191,7 +191,7 @@ A polymeter is when 2 different bar lengths play at the same tempo. This is a phasing: -*[6,6.1]").piano()`} punchcard /> +*[6,6.1]").piano()`} punchcard /> Phasing happens when the same sequence plays at slightly different tempos. @@ -200,7 +200,7 @@ Phasing happens when the same sequence plays at slightly different tempos. Using `run` with `n`, we can rush through a sample bank: @@ -219,7 +219,7 @@ In this case, I hear the beginning at the third sample, which can be accounted f Let's add some randomness: /2")`} /> @@ -250,7 +250,7 @@ The value of clip is relative to the duration of each event. We can also create overlaps using release: /2")`} /> @@ -259,7 +259,7 @@ This will smoothly fade out each sound for the given number of seconds. We could also make the notes shorter with decay / sustain: /2").sustain(0)`} /> @@ -268,27 +268,27 @@ For now, there is a limitation where decay values that exceed the event duration When using samples, we also have `.end` to cut relative to the sample length: -")`} /> +")`} /> Compare that to clip: -")`} /> +")`} /> or decay / sustain -").sustain(0)`} /> +").sustain(0)`} /> ## Wavetable Synthesis You can loop a sample with `loop` / `loopEnd`: -").s("bd").loop(1).loopEnd(.05).gain(.2)`} /> +").s("bd").loop(1).loopEnd(.05).gain(.2)`} /> This allows us to play the first 5% of the bass drum as a synth! To simplify loading wavetables, any sample that starts with `wt_` will be looped automatically: @@ -296,7 +296,7 @@ note("c eb g bb").s("wt_dbass").clip(2)`} Running through different wavetables can also give interesting variations: @@ -304,7 +304,7 @@ note("c2*8").s("wt_dbass").n(run(8))`} ...adding a filter envelope + reverb: