first strudel via AI

This commit is contained in:
Priec
2026-03-20 21:16:20 +01:00
commit 01c5230750
9 changed files with 1203 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
# Production Tips for Strudel
Professional-level techniques for polished output.
## 1. Mixing in Strudel
### Gain Staging
Always set explicit gain values. Elements should not fight for space:
```js
$: s("bd*4").gain(1.1) // kick = loudest
$: s("[~ sd]*2").gain(0.7) // snare = clear
$: s("[~ hh]*4").gain(0.25) // hats = subtle
$: note("c2*4").s("sine").gain(0.5) // bass = strong
$: note("[c4,e4,g4]").s("triangle").gain(0.15) // pad = background
$: note("c5 e5 g5").s("sine").gain(0.1) // melody = present but soft
```
### Frequency Separation
Each layer should own a frequency range. Use `.lpf()` and `.hpf()` to carve space:
```js
// Sub bass: ONLY low frequencies
note("c1").sound("sine").lpf(80).gain(0.6)
// Mid bass: remove sub, keep warmth
note("c2").sound("sawtooth").lpf(600).hpf(80).gain(0.3)
// Pad: remove low-end mud
note("[c3,e3,g3]").sound("triangle").hpf(300).lpf(3000).gain(0.15)
// Hi-hats: only highs
s("hh*8").hpf(3000).gain(0.25)
```
### Stereo Width with Pan
Center: kick, bass, snare. Sides: hats, pads, FX.
```js
$: s("bd*4").gain(1) // center (default)
$: s("hh*8").gain(0.2).pan(sine.range(0.3, 0.7)) // gentle side movement
$: note("[c4,e4,g4]").s("saw").gain(0.1).jux(rev) // wide stereo
```
## 2. Movement & Variation
### Filter Automation (Essential for Non-Static Sound)
```js
// Slow sweep over 8 cycles
.lpf(sine.range(300, 3000).slow(8))
// Fast wobble
.lpf(sine.range(200, 1500).fast(2))
// Random variation
.lpf(perlin.range(500, 2000))
// Stepped changes
.lpf("<400 800 1200 2000>")
```
### Rhythmic Variation with `every`
```js
// Reverse every 4th cycle
s("bd sd [~ bd] sd").every(4, x => x.rev())
// Double speed every 3rd cycle (fill)
s("bd sd [~ bd] sd").every(3, x => x.ply(2))
// Add filter sweep every 8th cycle
s("hh*16").every(8, x => x.lpf(sine.range(500, 5000)))
```
### The `off` Technique (Ghost Notes / Echoes)
```js
// Ghost notes: offset copy played softer and pitch-shifted
n("0 2 4 6").scale("C:minor")
.off(1/8, x => x.add(7).gain(0.3))
.sound("piano")
```
### Humanize with Randomness
```js
// Random gain variation (human feel)
s("hh*16").gain(perlin.range(0.1, 0.35))
// Random panning
s("rim*4").pan(rand)
// Sometimes skip notes
s("hh*16").sometimesBy(0.2, x => x.gain(0))
```
## 3. Sound Design Techniques
### Layering Synths
```js
// Fat bass: two detuned saws
note("c2").sound("sawtooth,sawtooth").detune("0 0.3")
// Rich pad: multiple waveforms
note("[c3,e3,g3]").sound("sawtooth,triangle,square")
.gain("0.15 0.1 0.05")
```
### Acid Bass (Resonant Filter)
```js
note("c2 c2 [c2 eb2] c2")
.sound("sawtooth")
.lpf(sine.range(200, 4000).fast(2))
.lpq(10) // high resonance = acid sound
.decay(0.1).sustain(0)
```
### Pluck Sound
```js
note("c4 e4 g4 c5")
.sound("triangle")
.lpf(3000)
.decay(0.15).sustain(0).release(0.3)
```
### Pad Sound
```js
note("[c3,e3,g3,b3]")
.sound("sawtooth")
.lpf(800).lpq(1)
.attack(0.5).release(1.5)
.room(0.7).size(0.9)
```
### Sub Bass (808 Style)
```js
note("c1").sound("sine")
.lpf(100).gain(0.6)
.decay(0.8).sustain(0)
```
## 4. Arrangement in a Single Loop
Since Strudel works in cycles, use `<>` and `/N` for section variation:
### A/B Pattern Alternation
```js
// Drums: minimal A, full B
$: s("<[bd ~ ~ ~]*4 [bd*4]>/8") // kick: sparse then full every 8 cycles
$: s("<[~ ~ ~ ~]*4 [[~ sd]*2]*4>/8") // snare: silent then enters
```
### Build-up Effect
```js
// Filter opens gradually over 16 cycles
$: note("c2*4").sound("sawtooth")
.lpf(sine.range(200, 4000).slow(16))
// Hats get denser
$: s("hh*<4 8 12 16>")
.gain(0.2)
```
### Drop
```js
// Build: filtered, no kick, rising
// Drop: everything at once, filter open
$: s("<[~ ~ ~ ~]*4 [bd*4]*4>/8") // kick enters at drop
$: note("c2*4").sound("sawtooth")
.lpf(saw.range(200, 3000).slow(8)) // filter opens
```
## 5. Advanced Pattern Techniques
### Polyrhythm
```js
// 3 against 4
note("c3 e3 g3, c4 e4 g4 b4").sound("piano")
```
### Euclidean Rhythms
```js
// Euclidean distribution of 3 hits in 8 steps
sound("{bd bd bd}%8")
```
### Probability
```js
// Random elements
s("bd sd? hh bd").bank("RolandTR909") // sd has 50% chance
```
### Progressive Transformation
```js
// Pattern morphs over time using every + sometimes
n("0 2 4 6").scale("C:minor").sound("piano")
.every(4, x => x.add(2))
.every(3, x => x.rev())
.sometimes(x => x.delay(0.5))
```
## 6. Common Professional Patterns
### Side-chain Simulation
Strudel can't do real sidechain, but you can simulate pump:
```js
// Pad volume ducks on kick hits
note("[c3,e3,g3]").sound("sawtooth")
.gain("0.05 0.15 0.2 0.15") // quiet on beat 1 (where kick is)
.lpf(1200).room(0.5)
```
### Call and Response
```js
note("<[c4 e4 g4 ~] [~ ~ ~ [b3 c4]]>")
.sound("piano")
```
### Rhythmic Chord Stabs
```js
note("<[c3,eb3,g3] ~ ~ ~ [ab2,c3,eb3] ~ ~ ~>")
.sound("square")
.decay(0.05).sustain(0).gain(0.15)
```
## 7. Debugging Checklist
If it sounds wrong:
1. **No sound?** — Check `.sound()` is set. Check gain > 0. Check `lpf` isn't too low.
2. **Too muddy?** — Add `.hpf()` to pads/mids. Reduce room on bass.
3. **Too static?** — Add signal modulation to filters. Use `every()` for variation.
4. **Timing weird?** — Check `setcps()` formula. Verify mini-notation subdivisions.
5. **Clashing notes?** — Use `.scale()` to stay in key. Check octave numbers.
6. **Too loud/quiet?** — Review gain staging. Kick ~1.0, everything else lower.