jevstrudel.git / website / src / pages / recipes / recipes.mdx
recipes.mdx322 lines · 7.1 KB · raw
1---
2title: Recipes
3layout: ../../layouts/MainLayout.astro
4---
5
6import { MiniRepl } from '../../docs/MiniRepl';
7
8# Recipes
9
10This page shows possible ways to achieve common (or not so common) musical goals.
11There are often many ways to do a thing and there is no right or wrong.
12The fun part is that each representation will give you different impulses when improvising.
13
14## Arpeggios
15
16An arpeggio is when the notes of a chord are played in sequence.
17We can either write the notes by hand:
18
19<MiniRepl
20  client:visible
21  tune={`note("c eb g c4")
22.clip(2).s("gm_electric_guitar_clean")`}
23  punchcard
24/>
25
26...or use scales:
27
28<MiniRepl
29  client:visible
30  tune={`n("0 2 4 7").scale("C:minor")
31.clip(2).s("gm_electric_guitar_clean")`}
32  punchcard
33/>
34
35...or chord symbols:
36
37<MiniRepl
38  client:visible
39  tune={`n("0 1 2 3").chord("Cm").mode("above:c3").voicing()
40.clip(2).s("gm_electric_guitar_clean")`}
41  punchcard
42/>
43
44...using off:
45
46<MiniRepl
47  client:visible
48  tune={`"0"
49  .off(1/3, add(2))
50  .off(1/2, add(4))
51  .n()
52  .scale("C:minor")
53  .s("gm_electric_guitar_clean")`}
54  punchcard
55/>
56
57## Chopping Breaks
58
59A sample can be looped and chopped like this:
60
61<MiniRepl
62  client:visible
63  tune={`samples('github:yaxu/clean-breaks')
64s("amen/4").fit().chop(32)`}
65  punchcard
66/>
67
68This fits the break into 8 cycles + chops it in 16 pieces.
69The chops are not audible yet, because we're not doing any manipulation.
70Let's add randmized doubling + reversing:
71
72<MiniRepl
73  client:visible
74  tune={`samples('github:yaxu/clean-breaks')
75s("amen/4").fit().chop(16).cut(1)
76.sometimesBy(.5, ply("2"))
77.sometimesBy(.25, mul(speed("-1")))`}
78  punchcard
79/>
80
81If we want to specify the order of samples, we can replace `chop` with `slice`:
82
83<MiniRepl
84  client:visible
85  tune={`samples('github:yaxu/clean-breaks')
86s("amen/4").fit()
87  .slice(8, "<0 1 2 3 4*2 5 6 [6 7]>*2")
88  .cut(1).rarely(ply("2"))`}
89  punchcard
90/>
91
92If we use `splice` instead of `slice`, the speed adjusts to the duration of the event:
93
94<MiniRepl
95  client:visible
96  tune={`samples('github:yaxu/clean-breaks')
97s("amen")
98  .splice(8, "<0 1 2 3 4*2 5 6 [6 7]>*2")
99  .cut(1).rarely(ply("2"))`}
100  punchcard
101/>
102
103Note that we don't need `fit`, because `splice` will do that by itself.
104
105## Filter Envelopes
106
107Using `lpenv`, we can make the filter move:
108
109<MiniRepl
110  client:visible
111  tune={`note("g1 bb1 <c2 eb2> d2")
112  .s("sawtooth")
113  .lpf(400).lpenv(4)
114  .scope()`}
115/>
116
117The type of envelope depends on the methods you're setting. Let's set `lpa`:
118
119<MiniRepl
120  client:visible
121  tune={`note("g1 bb1 <c2 eb2> d2")
122  .s("sawtooth").lpq(8)
123  .lpf(400).lpa(.2).lpenv(4)
124  .scope()`}
125/>
126
127Now the filter is attacking, rather than decaying as before (decay is the default). We can also do both
128
129<MiniRepl
130  client:visible
131  tune={`note("g1 bb1 <c2 eb2> d2")
132  .s("sawtooth").lpq(8)
133  .lpf(400).lpa(.1).lpd(.1).lpenv(4)
134  .scope()`}
135/>
136
137You can play around with `lpa` | `lpd` | `lps` | `lpd` to see what the filter envelope will do.
138
139## Layering Sounds
140
141We can layer sounds by separating them with ",":
142
143<MiniRepl
144  client:visible
145  tune={`note("<g1 bb1 d2 f1>")
146.s("sawtooth, square") // <------
147.scope()`}
148/>
149
150We can control the gain of individual sounds like this:
151
152<MiniRepl
153  client:visible
154  tune={`note("<g1 bb1 d2 f1>")
155.s("sawtooth, square:0:.5") // <--- "name:number:gain"
156.scope()`}
157/>
158
159For more control over each voice, we can use `layer`:
160
161<MiniRepl
162  client:visible
163  tune={`note("<g1 bb1 d2 f1>").layer(
164  x=>x.s("sawtooth").vib(4),
165  x=>x.s("square").add(note(12))
166).scope()`}
167/>
168
169Here, we give the sawtooth a vibrato and the square is moved an octave up.
170With `layer`, you can use any pattern method available on each voice, so sky is the limit..
171
172## Oscillator Detune
173
174We can fatten a sound by adding a detuned version to itself:
175
176<MiniRepl
177  client:visible
178  tune={`note("<g1 bb1 d2 f1>")
179.add(note("0,.1")) // <------ chorus
180.s("sawtooth").scope()`}
181  punchcard
182/>
183
184Try out different values, or add another voice!
185
186## Polyrhythms
187
188Here is a simple example of a polyrhythm:
189
190<MiniRepl client:visible tune={`s("bd*2,hh*3")`} punchcard />
191
192A polyrhythm is when 2 different tempos happen at the same time.
193
194## Polymeter
195
196This is a polymeter:
197
198<MiniRepl client:visible tune={`s("<bd rim, hh hh oh>*4")`} punchcard />
199
200A polymeter is when 2 different bar lengths play at the same tempo.
201
202## Phasing
203
204This is a phasing:
205
206<MiniRepl client:visible tune={`note("<C D G A Bb D C A G D Bb A>*[6,6.1]").piano()`} punchcard />
207
208Phasing happens when the same sequence plays at slightly different tempos.
209
210## Running through samples
211
212Using `run` with `n`, we can rush through a sample bank:
213
214<MiniRepl
215  client:visible
216  tune={`samples('bubo:fox')
217n(run(8)).s("ftabla")`}
218  punchcard
219/>
220
221This works great with sample banks that contain similar sounds, like in this case different recordings of a tabla.
222Often times, you'll hear the beginning of the phrase not where the pattern begins.
223In this case, I hear the beginning at the third sample, which can be accounted for with `early`.
224
225<MiniRepl
226  client:visible
227  tune={`samples('bubo:fox')
228n(run(8)).s("ftabla").early(2/8)`}
229/>
230
231Let's add some randomness:
232
233<MiniRepl
234  client:visible
235  tune={`samples('bubo:fox')
236n(run(8)).s("ftabla").early(2/8)
237.sometimes(mul(speed("1.5")))`}
238/>
239
240## Tape Warble
241
242We can emulate a pitch warbling effect like this:
243
244<MiniRepl
245  client:visible
246  tune={`note("<c4 bb f eb>*8")
247.add(note(perlin.range(0,.5))) // <------ warble
248.clip(2).s("gm_electric_guitar_clean")`}
249/>
250
251## Sound Duration
252
253There are a number of ways to change the sound duration. Using clip:
254
255<MiniRepl
256  client:visible
257  tune={`note("f ab bb c")
258.clip("<2 1 .5 .25>")`}
259/>
260
261The value of clip is relative to the duration of each event.
262We can also create overlaps using release:
263
264<MiniRepl
265  client:visible
266  tune={`note("f ab bb c")
267.release("<2 1 .5 .25>")`}
268/>
269
270This will smoothly fade out each sound for the given number of seconds.
271We could also make the notes shorter by using a decay envelope:
272
273<MiniRepl
274  client:visible
275  tune={`note("f ab bb c")
276.decay("<2 1 .5 .25>")`}
277/>
278
279When using samples, we also have `.end` to cut relative to the sample length:
280
281<MiniRepl client:visible tune={`s("oh*4").end("<1 .5 .25 .1>")`} />
282
283Compare that to clip:
284
285<MiniRepl client:visible tune={`s("oh*4").clip("<1 .5 .25 .1>")`} />
286
287or decay:
288
289<MiniRepl client:visible tune={`s("oh*4").decay("<1 .5 .25 .1>")`} />
290
291## Wavetable Synthesis
292
293You can loop a sample with `loop` / `loopEnd`:
294
295<MiniRepl client:visible tune={`note("<c eb g f>").s("bd").loop(1).loopEnd(.05).gain(.2)`} />
296
297This allows us to play the first 5% of the bass drum as a synth!
298To simplify loading wavetables, any sample that starts with `wt_` will be looped automatically:
299
300<MiniRepl
301  client:visible
302  tune={`samples('github:bubobubobubobubo/dough-waveforms')
303note("c eb g bb").s("wt_dbass").clip(2)`}
304/>
305
306Running through different wavetables can also give interesting variations:
307
308<MiniRepl
309  client:visible
310  tune={`samples('github:bubobubobubobubo/dough-waveforms')
311note("c2*8").s("wt_dbass").n(run(8)).fast(2)`}
312/>
313
314...adding a filter envelope + reverb:
315
316<MiniRepl
317  client:visible
318  tune={`samples('github:bubobubobubobubo/dough-waveforms')
319note("c2*8").s("wt_dbass").n(run(8))
320.lpf(perlin.range(100,1000).slow(8))
321.lpenv(-3).lpa(.1).room(.5).fast(2)`}
322/>