make 0.5hz cps the default (#931)
* 0.5 default cps * 1 -> 0.5 cps defaults * start moving examples to 2Hz * more 2Hz doc edits * small tweaks * format * adapt cycles page * adapt pitch page * tonal page * accumulation * synth page * adapt conditional-modifiers * audio effects page * adapt signals doc * fix: errors for signals * adapt signals page * start time modifiers * adapt time modifiers * adapt factories * hydra + pattern intro * adapt mini notation page * start recipes * adapt recipes page * use code_v1 table * delete old dbdump + add new csv based tool * fix: tests * fix: cpm * shuffle featured patterns * fix: snapshot --------- Co-authored-by: Felix Roos <flix91@gmail.com>
This commit is contained in:
parent
46c2c72637
commit
6422047cff
40 changed files with 3852 additions and 2386 deletions
|
|
@ -28,6 +28,10 @@ import { JsDoc } from '../../docs/JsDoc';
|
|||
|
||||
<JsDoc client:idle name="Pattern.chunkBack" h={0} />
|
||||
|
||||
### fastChunk
|
||||
|
||||
<JsDoc client:idle name="Pattern.fastChunk" h={0} />
|
||||
|
||||
## arp
|
||||
|
||||
<JsDoc client:idle name="Pattern#arp" h={0} />
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ Pitch envelopes can breathe life into static sounds:
|
|||
.s("gm_electric_guitar_jazz")
|
||||
.penv("<.5 0 7 -2>*2").vib("4:.1")
|
||||
.phaser(2).delay(.25).room(.3)
|
||||
.size(4).fast(.75)`}
|
||||
.size(4).fast(1.5)`}
|
||||
/>
|
||||
|
||||
You also create some lovely chiptune-style sounds:
|
||||
|
|
@ -163,7 +163,7 @@ You also create some lovely chiptune-style sounds:
|
|||
.voicing().add(note("<0 1>/8"))
|
||||
.dec(.1).room(.2)
|
||||
.segment("<4 [2 8]>")
|
||||
.penv("<0 <2 -2>>").patt(.02)`}
|
||||
.penv("<0 <2 -2>>").patt(.02).fast(2)`}
|
||||
/>
|
||||
|
||||
Let's break down all pitch envelope controls:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ osc(1, -0.9, 300)
|
|||
.scale(2)
|
||||
.out()
|
||||
|
||||
note("[a,c,e,<a4 ab4 g4 gb4>,b4]/4").s("sawtooth").vib(2)
|
||||
note("[a,c,e,<a4 ab4 g4 gb4>,b4]/2")
|
||||
.s("sawtooth").vib(2)
|
||||
.lpf(600).lpa(2).lpenv(6)
|
||||
`}
|
||||
/>
|
||||
|
|
@ -90,7 +91,7 @@ src(s0).kaleid(H("<4 5 6>"))
|
|||
.out()
|
||||
//
|
||||
stack(
|
||||
s("bd*2,[hh:0:<.5 1>]*4,~ rim").bank("RolandTR909").speed(.9),
|
||||
s("bd*4,[hh:0:<.5 1>]*8,~ rim").bank("RolandTR909").speed(.9),
|
||||
note("[<g1!3 <bb1 <f1 d1>>>]*3").s("sawtooth")
|
||||
.room(.75).sometimes(add(note(12))).clip(.3)
|
||||
.lpa(.05).lpenv(-4).lpf(2000).lpq(8).ftype('24db')
|
||||
|
|
|
|||
|
|
@ -22,27 +22,25 @@ Before diving deeper into the details, here is a flavour of how the Mini-Notatio
|
|||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note(\`[
|
||||
[
|
||||
[e5 [b4 c5] d5 [c5 b4]]
|
||||
[a4 [a4 c5] e5 [d5 c5]]
|
||||
[b4 [~ c5] d5 e5]
|
||||
[c5 a4 a4 ~]
|
||||
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||
[e5 [~ c5] e5 [d5 c5]]
|
||||
[b4 [b4 c5] d5 e5]
|
||||
[c5 a4 a4 ~]
|
||||
],[
|
||||
[[e2 e3]*4]
|
||||
[[a2 a3]*4]
|
||||
[[g#2 g#3]*2 [e2 e3]*2]
|
||||
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||
[[d2 d3]*4]
|
||||
[[c2 c3]*4]
|
||||
[[b1 b2]*2 [e2 e3]*2]
|
||||
[[a1 a2]*4]
|
||||
]
|
||||
]/16\`)`}
|
||||
tune={`note(\`<
|
||||
[e5 [b4 c5] d5 [c5 b4]]
|
||||
[a4 [a4 c5] e5 [d5 c5]]
|
||||
[b4 [~ c5] d5 e5]
|
||||
[c5 a4 a4 ~]
|
||||
[[~ d5] [~ f5] a5 [g5 f5]]
|
||||
[e5 [~ c5] e5 [d5 c5]]
|
||||
[b4 [b4 c5] d5 e5]
|
||||
[c5 a4 a4 ~]
|
||||
,
|
||||
[[e2 e3]*4]
|
||||
[[a2 a3]*4]
|
||||
[[g#2 g#3]*2 [e2 e3]*2]
|
||||
[a2 a3 a2 a3 a2 a3 b1 c2]
|
||||
[[d2 d3]*4]
|
||||
[[c2 c3]*4]
|
||||
[[b1 b2]*2 [e2 e3]*2]
|
||||
[[a1 a2]*4]
|
||||
>\`)`}
|
||||
/>
|
||||
|
||||
## Mini Notation Format
|
||||
|
|
@ -74,9 +72,21 @@ Taking the two examples above, we have four and eight events respectively, and s
|
|||
This is perhaps counter-intuitive if you are used to adding notes in a sequencer or piano roll and the overall length increasing.
|
||||
But, it will begin to make sense as we go through more elements of mini-notation.
|
||||
|
||||
## Multiplication
|
||||
|
||||
A sequence can be sped up by multiplying it by a number using the asterisk symbol (`*`):
|
||||
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2")`} punchcard />
|
||||
|
||||
The multiplication by two here means that the sequence will play twice per cycle.
|
||||
|
||||
Multiplications can also be decimal (`*2.75`):
|
||||
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2.75")`} punchcard />
|
||||
|
||||
## Division
|
||||
|
||||
We can slow the sequence down by enclosing it in brackets and dividing it by a number (`/2`):
|
||||
Contrary to multiplication, division can slow the sequence down by enclosing it in brackets and dividing it by a number (`/2`):
|
||||
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]/2")`} punchcard />
|
||||
|
||||
|
|
@ -102,18 +112,11 @@ The advantage of the angle brackets, is that we can add more events without need
|
|||
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5 e5 b4>")`} punchcard />
|
||||
|
||||
This is more similar to traditional music sequencers and piano rolls, where adding a note increases the perceived overall duration.
|
||||
We can also play a certain number of notes per cycle by using angle brackets with multiplication:
|
||||
|
||||
## Multiplication
|
||||
<MiniRepl client:idle tune={`note("<e5 b4 d5 c5 a4 c5>*8")`} punchcard />
|
||||
|
||||
Contrary to division, a sequence can be sped up by multiplying it by a number using the asterisk symbol (`*`):
|
||||
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2")`} punchcard />
|
||||
|
||||
The multiplication by two here means that the sequence will play twice per cycle.
|
||||
|
||||
As with divisions, multiplications can be decimal (`*2.75`):
|
||||
|
||||
<MiniRepl client:idle tune={`note("[e5 b4 d5 c5]*2.75")`} punchcard />
|
||||
Now we are playing 8 notes per cycle!
|
||||
|
||||
## Subdividing time with bracket nesting
|
||||
|
||||
|
|
@ -149,13 +152,13 @@ The following are the same:
|
|||
|
||||
But to play multiple chords in a sequence, we have to wrap them in brackets:
|
||||
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>")`} punchcard />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4] [b3,e4,g4]>*2")`} punchcard />
|
||||
|
||||
## Elongation
|
||||
|
||||
With the "@" symbol, we can specify temporal "weight" of a sequence child:
|
||||
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} punchcard />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>*2")`} punchcard />
|
||||
|
||||
Here, the first chord has a weight of 2, making it twice the length of the other chords. The default weight is 1.
|
||||
|
||||
|
|
@ -163,19 +166,19 @@ Here, the first chord has a weight of 2, making it twice the length of the other
|
|||
|
||||
Using "!" we can repeat without speeding up:
|
||||
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} punchcard />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>*2")`} punchcard />
|
||||
|
||||
## Mini-notation review
|
||||
|
||||
To recap what we've learned so far, compare the following patterns:
|
||||
|
||||
<MiniRepl client:idle tune={`note("<g3 b3 e4 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]/2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]*2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] _ [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")`} />
|
||||
<MiniRepl client:idle tune={`note("<g3 b3 e4 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]/2 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]*2 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4] _ [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]@2 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
<MiniRepl client:idle tune={`note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>*2")`} />
|
||||
|
||||
## Euclidian rhythms
|
||||
|
||||
|
|
@ -196,7 +199,7 @@ But using the Euclidian rhythm notation, we only need to express "3 beats over 8
|
|||
|
||||
This makes it easy to write patterns with interesting rhythmic structures and variations that still sound familiar:
|
||||
|
||||
<MiniRepl client:idle tune={`note("e5(2,8) b4(3,8) d5(2,8) c5(3,8)").slow(4)`} punchcard canvasHeight={50} />
|
||||
<MiniRepl client:idle tune={`note("e5(2,8) b4(3,8) d5(2,8) c5(3,8)").slow(2)`} punchcard canvasHeight={50} />
|
||||
|
||||
Note that since the example above does not use the third `offset` parameter, it can be written simply as `"(3,8)"`.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Strudel allows loading samples in the form of audio files of various formats (wa
|
|||
|
||||
By default, strudel comes with a built-in "sample map", providing a solid base to play with.
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd sd,hh*8, misc/2")`} />
|
||||
<MiniRepl client:idle tune={`s("bd sd [~ bd] sd,hh*16, misc")`} />
|
||||
|
||||
Here, we are using the `s` function to play back different default samples (`bd`, `sd`, `hh` and `misc`) to get a drum beat.
|
||||
|
||||
|
|
@ -59,15 +59,15 @@ If we open the `sounds` tab and then `drum machines`, we can see that the drum s
|
|||
|
||||
We _could_ use them like this:
|
||||
|
||||
<MiniRepl client:idle tune={`s("RolandTR808_bd RolandTR808_sd,RolandTR808_hh*8")`} />
|
||||
<MiniRepl client:idle tune={`s("RolandTR808_bd RolandTR808_sd,RolandTR808_hh*16")`} />
|
||||
|
||||
... but thats obviously a bit much to write. Using the `bank` function, we can shorten this to:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd sd,hh*8").bank("RolandTR808")`} />
|
||||
<MiniRepl client:idle tune={`s("bd sd bd sd,hh*16").bank("RolandTR808")`} />
|
||||
|
||||
You could even pattern the bank to switch between different drum machines:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd sd,hh*8").bank("<RolandTR808 RolandTR909>")`} />
|
||||
<MiniRepl client:idle tune={`s("bd sd bd sd,hh*16").bank("RolandTR808 RolandTR909")`} />
|
||||
|
||||
Behind the scenes, `bank` will just prepend the drum machine name to the sample name with `_` to get the full name.
|
||||
This of course only works because the name after `_` (`bd`, `sd` etc..) is standardized.
|
||||
|
|
@ -79,17 +79,21 @@ If we open the `sounds` tab again, followed by tab `drum machines`, there is als
|
|||
For example `RolandTR909_hh(4)` means there are 4 samples of a TR909 hihat available.
|
||||
By default, `s` will play the first sample, but we can select the other ones using `n`, starting from 0:
|
||||
|
||||
<MiniRepl client:idle tune={`s("hh*4").bank("RolandTR909").n("<0 1 2 3>")`} />
|
||||
<MiniRepl client:idle tune={`s("hh*8").bank("RolandTR909").n("0 1 2 3")`} />
|
||||
|
||||
Numbers that are too high will just wrap around to the beginning
|
||||
|
||||
<MiniRepl client:idle tune={`s("hh*4").bank("RolandTR909").n("<0 1 2 3 4 5 6 7>")`} />
|
||||
<MiniRepl client:idle tune={`s("hh*8").bank("RolandTR909").n("0 1 2 3 4 5 6 7")`} />
|
||||
|
||||
Here, 0-3 will play the same sounds as 4-7, because `RolandTR909_hh` only has 4 sounds.
|
||||
|
||||
Selecting sounds also works inside the mini notation, using "`:`" like this:
|
||||
|
||||
<MiniRepl client:idle tune={`s("bd:1 bd:2,hh:0 hh:1 hh:2 hh:3").bank("RolandTR909")`} />
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`s("bd*4,hh:0 hh:1 hh:2 hh:3 hh:4 hh:5 hh:6 hh:7")
|
||||
.bank("RolandTR909")`}
|
||||
/>
|
||||
|
||||
# Loading Custom Samples
|
||||
|
||||
|
|
@ -103,7 +107,7 @@ In this example we create a map using sounds from the default sample map:
|
|||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
|
||||
s("bd sd,hh*8")`}
|
||||
s("bd sd bd sd,hh*16")`}
|
||||
/>
|
||||
|
||||
When you load your own samples, you can choose the names that you will then refer to in your pattern string inside the `s` function.
|
||||
|
|
@ -116,7 +120,7 @@ Compare with this example which uses the same samples, but with different names.
|
|||
snaredrum: 'sd/rytm-01-classic.wav',
|
||||
hihat: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'https://raw.githubusercontent.com/tidalcycles/Dirt-Samples/master/');
|
||||
s("bassdrum snaredrum, hihat*8")`}
|
||||
s("bassdrum snaredrum bassdrum snaredrum, hihat*16")`}
|
||||
/>
|
||||
|
||||
Here we have changed the "map" to include longer sample names.
|
||||
|
|
@ -140,7 +144,7 @@ Because GitHub is a popular place for uploading open source samples, it has its
|
|||
sd: 'sd/rytm-01-classic.wav',
|
||||
hh: 'hh27/000_hh27closedhh.wav',
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("bd sd,hh*8")`}
|
||||
s("bd sd bd sd,hh*16")`}
|
||||
/>
|
||||
|
||||
The format is `github:user/repo/branch/`.
|
||||
|
|
@ -157,7 +161,7 @@ We can see there are some guitar samples inside the `/samples` folder, so let's
|
|||
g3: 'samples/guitar/guitar_3.wav',
|
||||
g4: 'samples/guitar/guitar_4.wav'
|
||||
}, 'github:jarmitage/jarmitage.github.io/master/');
|
||||
s("[g0 g1 g2 g3 g4]/5")`}
|
||||
s("<g0 g1 g2 g3 g4>/2")`}
|
||||
/>
|
||||
|
||||
## Multiple Samples per Sound
|
||||
|
|
@ -171,7 +175,7 @@ It is also possible, to declare multiple files for one sound, using the array no
|
|||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("<bd:0 bd:1>,~ <sd:0 sd:1>,[hh:0 hh:1]*2")`}
|
||||
s("bd:0 bd:1,~ <sd:0 sd:1> ~ sd:0,[hh:0 hh:1]*4")`}
|
||||
/>
|
||||
|
||||
The `:0` `:1` etc. are the indices of the array.
|
||||
|
|
@ -184,7 +188,7 @@ The sample number can also be set using `n`:
|
|||
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
|
||||
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
|
||||
}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
s("bd,~ sd,hh*4").n("<0 1>")`}
|
||||
s("bd bd,~ sd ~ sd,hh*8").n("<0 1>")`}
|
||||
/>
|
||||
|
||||
In that case, we might load our guitar sample map a different way:
|
||||
|
|
@ -200,7 +204,7 @@ In that case, we might load our guitar sample map a different way:
|
|||
'samples/guitar/guitar_4.wav'
|
||||
]
|
||||
}, 'github:jarmitage/jarmitage.github.io/master/');
|
||||
s("[guitar:0 guitar:1 guitar:2 guitar:3 guitar:4]/5")`}
|
||||
s("<guitar:0 guitar:1 guitar:2 guitar:3 guitar:4>*2")`}
|
||||
/>
|
||||
|
||||
And as above, we can choose the sample number using `n` for even more flexibility:
|
||||
|
|
@ -216,7 +220,7 @@ And as above, we can choose the sample number using `n` for even more flexibilit
|
|||
'samples/guitar/guitar_4.wav'
|
||||
]
|
||||
}, 'github:jarmitage/jarmitage.github.io/master/');
|
||||
n("<0 1 2 3 4>").s("guitar")`}
|
||||
n("<0 1 2 3 4>*2").s("guitar")`}
|
||||
/>
|
||||
|
||||
## Pitched Sounds
|
||||
|
|
@ -271,7 +275,7 @@ We can also declare different samples for different regions of the keyboard:
|
|||
}}, 'github:tidalcycles/Dirt-Samples/master/');
|
||||
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
|
||||
.s('moog').clip(1)
|
||||
.gain(.5)`}
|
||||
.gain(.5).cpm(60)`}
|
||||
/>
|
||||
|
||||
The sampler will always pick the closest matching sample for the current note!
|
||||
|
|
@ -285,9 +289,9 @@ With it, you can enter any sample name(s) to query from [freesound.org](https://
|
|||
client:idle
|
||||
tune={`await samples('shabda:bass:4,hihat:4,rimshot:2')
|
||||
stack(
|
||||
n("0 1 2 3").s('bass').slow(2),
|
||||
n("0 1 2 3 0 1 2 3").s('bass'),
|
||||
n("0 1*2 2 3*2").s('hihat'),
|
||||
n("~ 0 ~ 1").s('rimshot')
|
||||
n("~ 0 ~ 1 ~ 0 0 1").s('rimshot')
|
||||
).clip(1)`}
|
||||
/>
|
||||
|
||||
|
|
@ -299,8 +303,8 @@ Note that the language code and the gender parameters are optional and default t
|
|||
tune={`await samples('shabda/speech:the_drum,forever')
|
||||
await samples('shabda/speech/fr-FR/m:magnifique')
|
||||
stack(
|
||||
s("the_drum").chop(16).speed(rand.range(0.85,1.1)),
|
||||
s("forever magnifique").slow(8).late(0.25)
|
||||
s("the_drum*2").chop(16).speed(rand.range(0.85,1.1)),
|
||||
s("forever magnifique").slow(4).late(0.125)
|
||||
)`}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ The basic waveforms are `sine`, `sawtooth`, `square` and `triangle`, which can b
|
|||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("c2 <eb2 <g2 g1>>")
|
||||
tune={`note("c2 <eb2 <g2 g1>>".fast(2))
|
||||
.sound("<sawtooth square triangle sine>")
|
||||
.scope()`}
|
||||
/>
|
||||
|
|
@ -28,7 +28,7 @@ If you don't set a `sound` but a `note` the default value for `sound` is `triang
|
|||
You can also use noise as a source by setting the waveform to: `white`, `pink` or `brown`. These are different
|
||||
flavours of noise, here written from hard to soft.
|
||||
|
||||
<MiniRepl client:idle tune={`sound("<white pink brown>/2").scope()`} />
|
||||
<MiniRepl client:idle tune={`sound("<white pink brown>").scope()`} />
|
||||
|
||||
Here's a more musical example of how to use noise for hihats:
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ Some amount of pink noise can also be added to any oscillator by using the `nois
|
|||
|
||||
You can also use the `crackle` type to play some subtle noise crackles. You can control noise amount by using the `density` parameter:
|
||||
|
||||
<MiniRepl client:idle tune={`s("crackle*4").density("<0.01 0.04 0.2 0.5>".slow(4)).scope()`} />
|
||||
<MiniRepl client:idle tune={`s("crackle*4").density("<0.01 0.04 0.2 0.5>".slow(2)).scope()`} />
|
||||
|
||||
### Additive Synthesis
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ To tame the harsh sound of the basic waveforms, we can set the `n` control to li
|
|||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("c2 <eb2 <g2 g1>>")
|
||||
tune={`note("c2 <eb2 <g2 g1>>".fast(2))
|
||||
.sound("sawtooth")
|
||||
.n("<32 16 8 4>")
|
||||
.scope()`}
|
||||
|
|
@ -63,7 +63,7 @@ You can also set `n` directly in mini notation with `sound`:
|
|||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("c2 <eb2 <g2 g1>>")
|
||||
tune={`note("c2 <eb2 <g2 g1>>".fast(2))
|
||||
.sound("sawtooth:<32 16 8 4>")
|
||||
.scope()`}
|
||||
/>
|
||||
|
|
@ -125,7 +125,7 @@ note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")
|
|||
.n("<1 2 3 4 5 6 7 8 9 10>/2").room(0.5).size(0.9)
|
||||
.s('wt_flute').velocity(0.25).often(n => n.ply(2))
|
||||
.release(0.125).decay("<0.1 0.25 0.3 0.4>").sustain(0)
|
||||
.cutoff(2000).scope({}).cutoff("<1000 2000 4000>").fast(2)`}
|
||||
.cutoff(2000).scope({}).cutoff("<1000 2000 4000>").fast(4)`}
|
||||
/>
|
||||
|
||||
## ZZFX
|
||||
|
|
@ -137,8 +137,8 @@ It has 20 parameters in total, here is a snippet that uses all:
|
|||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`note("<c2 eb2 f2 g2>") // also supports freq
|
||||
.s("<z_sawtooth z_tan z_noise z_sine z_square>")
|
||||
tune={`note("c2 eb2 f2 g2") // also supports freq
|
||||
.s("{z_sawtooth z_tan z_noise z_sine z_square}%4")
|
||||
.zrand(0) // randomization
|
||||
// zzfx envelope
|
||||
.attack(0.001)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,19 @@ These functions use [tonaljs](https://github.com/tonaljs/tonal) to provide helpe
|
|||
|
||||
<JsDoc client:idle name="voicing" h={0} />
|
||||
|
||||
Here's an example of how you can play chords and a bassline:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`chord("<C^7 A7b13 Dm7 G7>*2")
|
||||
.dict('ireal').layer(
|
||||
x=>x.struct("[~ x]*2").voicing()
|
||||
,
|
||||
x=>n("0*4").set(x).mode("root:g2").voicing()
|
||||
.s('sawtooth').cutoff("800:4:2")
|
||||
)`}
|
||||
/>
|
||||
|
||||
### scale(name)
|
||||
|
||||
<JsDoc client:idle name="scale" h={0} />
|
||||
|
|
@ -22,13 +35,13 @@ These functions use [tonaljs](https://github.com/tonaljs/tonal) to provide helpe
|
|||
|
||||
Transposes all notes to the given number of semitones:
|
||||
|
||||
<MiniRepl client:only="react" tune={`"c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note()`} />
|
||||
<MiniRepl client:only="react" tune={`"[c2 c3]*4".transpose("<0 -2 5 3>").note()`} />
|
||||
|
||||
This method gets really exciting when we use it with a pattern as above.
|
||||
|
||||
Instead of numbers, scientific interval notation can be used as well:
|
||||
|
||||
<MiniRepl client:only="react" tune={`"c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note()`} />
|
||||
<MiniRepl client:only="react" tune={`"[c2 c3]*4".transpose("<1P -2M 4P 3m>").note()`} />
|
||||
|
||||
### scaleTranspose(steps)
|
||||
|
||||
|
|
@ -36,9 +49,9 @@ Transposes notes inside the scale by the number of steps:
|
|||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`"-8 [2,4,6]"
|
||||
tune={`"[-8 [2,4,6]]*2"
|
||||
.scale('C4 bebop major')
|
||||
.scaleTranspose("<0 -1 -2 -3 -4 -5 -6 -4>")
|
||||
.scaleTranspose("<0 -1 -2 -3 -4 -5 -6 -4>*2")
|
||||
.note()`}
|
||||
/>
|
||||
|
||||
|
|
@ -46,22 +59,28 @@ Transposes notes inside the scale by the number of steps:
|
|||
|
||||
Turns chord symbols into voicings, using the smoothest voice leading possible:
|
||||
|
||||
<MiniRepl client:only="react" tune={`stack("<C^7 A7 Dm7 G7>".voicings('lefthand'), "<C3 A2 D3 G2>").note()`} />
|
||||
<MiniRepl
|
||||
client:only="react"
|
||||
tune={`stack(
|
||||
"<C^7 A7 Dm7 G7>".voicings('lefthand'),
|
||||
"<C3 A2 D3 G2>"
|
||||
).note()`}
|
||||
/>
|
||||
|
||||
Note: This function might be removed, as `voicing` (without s) is a newer implementation.
|
||||
|
||||
### rootNotes(octave = 2)
|
||||
|
||||
Turns chord symbols into root notes of chords in given octave.
|
||||
|
||||
<MiniRepl client:only="react" tune={`"<C^7 A7b13 Dm7 G7>".rootNotes(3).note()`} />
|
||||
<MiniRepl client:only="react" tune={`"<C^7 A7b13 Dm7 G7>*2".rootNotes(3).note()`} />
|
||||
|
||||
Together with layer, struct and voicings, this can be used to create a basic backing track:
|
||||
|
||||
<MiniRepl
|
||||
client:idle
|
||||
tune={`"<C^7 A7b13 Dm7 G7>".layer(
|
||||
x => x.voicings('lefthand').struct("~ x").note(),
|
||||
tune={`"<C^7 A7b13 Dm7 G7>*2".layer(
|
||||
x => x.voicings('lefthand').struct("[~ x]*2").note(),
|
||||
x => x.rootNotes(2).note().s('sawtooth').cutoff(800)
|
||||
)`}
|
||||
/>
|
||||
|
||||
So far, we've stayed within the browser. [MIDI and OSC](/learn/input-output/) are ways to break out of it.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue