232 lines
5.4 KiB
Markdown
232 lines
5.4 KiB
Markdown
# 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.
|