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/>