diff --git a/website/src/config.ts b/website/src/config.ts
index ba9b0666..0d774a5a 100644
--- a/website/src/config.ts
+++ b/website/src/config.ts
@@ -70,12 +70,10 @@ export const SIDEBAR: Sidebar = {
{ text: 'MIDI & OSC', link: 'learn/input-output' },
],
More: [
+ { text: 'Recipes', link: 'recipes/recipes' },
{ text: 'Mini-Notation', link: 'learn/mini-notation' },
- { text: 'Coding syntax', link: 'learn/code' },
{ text: 'Offline', link: 'learn/pwa' },
{ text: 'Patterns', link: 'technical-manual/patterns' },
- { text: 'Pattern Alignment', link: 'technical-manual/alignment' },
- { text: 'Strudel vs Tidal', link: 'learn/strudel-vs-tidal' },
{ text: 'Music metadata', link: 'learn/metadata' },
{ text: 'CSound', link: 'learn/csound' },
],
@@ -89,7 +87,13 @@ export const SIDEBAR: Sidebar = {
{ text: 'Accumulation', link: 'learn/accumulation' },
{ text: 'Tonal Functions', link: 'learn/tonal' },
],
- Understand: [{ text: 'Pitch', link: 'understand/pitch' }],
+ Understand: [
+ { text: 'Coding syntax', link: 'learn/code' },
+ { text: 'Pitch', link: 'understand/pitch' },
+ { text: 'Cycles', link: 'understand/cycles' },
+ { text: 'Pattern Alignment', link: 'technical-manual/alignment' },
+ { text: 'Strudel vs Tidal', link: 'learn/strudel-vs-tidal' },
+ ],
Development: [
{ text: 'REPL', link: 'technical-manual/repl' },
{ text: 'Sounds', link: 'technical-manual/sounds' },
diff --git a/website/src/pages/recipes/recipes.mdx b/website/src/pages/recipes/recipes.mdx
new file mode 100644
index 00000000..22617e4b
--- /dev/null
+++ b/website/src/pages/recipes/recipes.mdx
@@ -0,0 +1,312 @@
+---
+title: Recipes
+layout: ../../layouts/MainLayout.astro
+---
+
+import { MiniRepl } from '../../docs/MiniRepl';
+
+# Recipes
+
+This page shows possible ways to achieve common (or not so common) musical goals.
+There are often many ways to do a thing and there is no right or wrong.
+The fun part is that each representation will give you different impulses when improvising.
+
+## Arpeggios
+
+An arpeggio is when the notes of a chord are played in sequence.
+We can either write the notes by hand:
+
+
+
+...or use scales:
+
+
+
+...or chord symbols:
+
+
+
+...using off:
+
+
+
+## Chopping Breaks
+
+A sample can be looped and chopped like this:
+
+
+
+This fits the break into 8 cycles + chops it in 16 pieces.
+The chops are not audible yet, because we're not doing any manipulation.
+Let's add randmized doubling + reversing:
+
+
+
+If we want to specify the order of samples, we can replace `chop` with `slice`:
+
+")
+ .cut(1).rarely(ply(2))`}
+ punchcard
+/>
+
+If we use `splice` instead of `slice`, the speed adjusts to the duration of the event:
+
+")
+ .cut(1).rarely(ply(2))`}
+ punchcard
+/>
+
+Note that we don't need `fit`, because `splice` will do that by itself.
+
+## Filter Envelopes
+
+A minimal filter envelope looks like this:
+
+ d2")
+ .s("sawtooth")
+ .lpf(400).lpa(.2).lpenv(4)
+ .scope()`}
+/>
+
+We can flip the envelope by setting `lpenv` negative + add some resonance `lpq`:
+
+ d2")
+ .s("sawtooth").lpq(8)
+ .lpf(400).lpa(.2).lpenv(-4)
+ .scope()`}
+/>
+
+## Layering Sounds
+
+We can layer sounds by separating them with ",":
+
+")
+.s("sawtooth, square") // <------
+.scope()`}
+/>
+
+We can control the gain of individual sounds like this:
+
+")
+.s("sawtooth, square:0:.5") // <--- "name:number:gain"
+.scope()`}
+/>
+
+For more control over each voice, we can use `layer`:
+
+").layer(
+ x=>x.s("sawtooth").vib(4),
+ x=>x.s("square").add(note(12))
+).scope()`}
+/>
+
+Here, we give the sawtooth a vibrato and the square is moved an octave up.
+With `layer`, you can use any pattern method available on each voice, so sky is the limit..
+
+## Oscillator Detune
+
+We can fatten a sound by adding a detuned version to itself:
+
+")
+.add(note("0,.1")) // <------ chorus
+.s("sawtooth").scope()`}
+ punchcard
+/>
+
+Try out different values, or add another voice!
+
+## Polyrhythms
+
+Here is a simple example of a polyrhythm:
+
+
+
+A polyrhythm is when 2 different tempos happen at the same time.
+
+## Polymeter
+
+This is a polymeter:
+
+,").fast(2)`} punchcard />
+
+A polymeter is when 2 different bar lengths play at the same tempo.
+
+## Phasing
+
+This is a phasing:
+
+*[6,6.1]").piano()`} punchcard />
+
+Phasing happens when the same sequence plays at slightly different tempos.
+
+## Running through samples
+
+Using `run` with `n`, we can rush through a sample bank:
+
+
+
+This works great with sample banks that contain similar sounds, like in this case different recordings of a tabla.
+Often times, you'll hear the beginning of the phrase not where the pattern begins.
+In this case, I hear the beginning at the third sample, which can be accounted for with `early`.
+
+
+
+Let's add some randomness:
+
+
+
+## Tape Warble
+
+We can emulate a pitch warbling effect like this:
+
+
+
+## Sound Duration
+
+There are a number of ways to change the sound duration. Using clip:
+
+/2")`}
+/>
+
+The value of clip is relative to the duration of each event.
+We can also create overlaps using release:
+
+/2")`}
+/>
+
+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)`}
+/>
+
+For now, there is a limitation where decay values that exceed the event duration may cause little cracks, so use higher numbers with caution..
+
+When using samples, we also have `.end` to cut relative to the sample length:
+
+")`} />
+
+Compare that to clip:
+
+")`} />
+
+or decay / sustain
+
+").sustain(0)`} />
+
+## Wavetable Synthesis
+
+You can loop a sample with `loop` / `loopEnd`:
+
+").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:
+
+
+
+Running through different wavetables can also give interesting variations:
+
+
+
+...adding a filter envelope + reverb:
+
+
diff --git a/website/src/pages/understand/cycles.mdx b/website/src/pages/understand/cycles.mdx
new file mode 100644
index 00000000..a66794be
--- /dev/null
+++ b/website/src/pages/understand/cycles.mdx
@@ -0,0 +1,130 @@
+---
+title: Understanding Cycles
+layout: ../../layouts/MainLayout.astro
+---
+
+import { MiniRepl } from '../../docs/MiniRepl';
+import { PitchSlider } from '../../components/PitchSlider';
+import Box from '@components/Box.astro';
+
+# Understanding Cycles
+
+The concept of cycles is very central to be able to understand how Strudel works.
+Strudel's mother language, TidalCycles, even has it in its name.
+
+## Cycles and BPM
+
+In most music software, the unit BPM (beats per minute) is used to set the tempo.
+Strudel expresses tempo as CPS (cycles per second), with a default of 1CPS:
+
+
+
+Here we can hear the 1CPS in action: The kick repeats once per second like a clock.
+We could say 1CPS = 1BPS (beats per second) = 60BPM. Let's add another kick:
+
+
+
+Now we have 2 kicks per second, but the whole pattern still plays at 1CPS.
+In terms of BPM, most musicians would tell you this is playing at 120bpm.
+What about this one:
+
+
+
+Because the second sound is now a hihat, the tempo feels slower again.
+This brings us to an important realization:
+
+
+
+Tempo is based on perception.
+The choice of sounds also has an impact on the tempo feel.
+This is why the same CPS can produce different perceived tempos.
+
+
+
+## Setting CPM
+
+If you're familiar with BPM, you can use the `cpm` method to set the tempo in cycles per minute:
+
+
+
+If you want to add more beats per cycle, you might want to divide the cpm:
+
+
+
+Or using 2 beats per cycle:
+
+
+
+
+
+To set a specific bpm, use `.cpm(bpm/bpc)`
+
+- bpm: the target beats per minute
+- bpc: the number of perceived beats per cycle
+
+
+
+## Cycles and Bars
+
+Also in most music software, multiple beats form a bar (or measure).
+The so called time signature specifies how many beats are in each bar.
+In many types of music, it is common to use 4 beats per bar, also known as 4/4 time.
+Many music programs use it as a default.
+
+Strudel does not a have concept of bars or measures, there are only cycles.
+How you use them is up to you. Above, we've had this example:
+
+
+
+This could be interpreted as 4/4 time with a tempo of 110bpm.
+We could write out multiple bars like this:
+
+\`).cpm(110/4)`}
+/>
+
+Instead of writing out each bar separately, we could express this much shorter:
+
+>,hh*4").cpm(110/2)`} />
+
+Here we can see that thinking in cycles rather than bars simplifies things a lot!
+These types of simplifications work because of the repetitive nature of rhythm.
+In computational terms, you could say the former notation has a lot of redundancy.
+
+## Time Signatures
+
+To get a time signature, just change the number of elements per bar. Here is a rhythm with 7 beats:
+
+
+
+or with 5:
+
+*5")`} />
+
+We could also write multiple bars with different time signatures:
+
+\`).cpm(110*2)`}
+/>
+
+Here we switch between 3/4 and 4/4, keeping the same tempo.
+
+If we don't specify the length, we get what's called a metric modulation:
+
+\`).cpm(110/2)`}
+/>
+
+Now the 3 elements get the same time as the 4 elements, which is why the tempo changes.