Rewrite part of evaluation logic, run prettier
This commit is contained in:
@ -17,11 +17,11 @@ Controlling the volume is probably the most important concept you need to know a
|
||||
| <ic>dbgain</ic> | db | Attenuation in dB from <ic>-inf</ic> to <ic>+10</ic> (acts as a sound mixer fader).|
|
||||
|
||||
${makeExample(
|
||||
"Velocity manipulated by a counter",
|
||||
`
|
||||
"Velocity manipulated by a counter",
|
||||
`
|
||||
beat(.5)::snd('cp').vel($(1)%10 / 10).out()`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
## Amplitude Enveloppe
|
||||
|
||||
@ -37,8 +37,8 @@ beat(.5)::snd('cp').vel($(1)%10 / 10).out()`,
|
||||
Note that the **sustain** value is not a duration but an amplitude value (how loud). The other values are the time for each stage to take place. Here is a fairly complete example using the <ic>sawtooth</ic> basic waveform.
|
||||
|
||||
${makeExample(
|
||||
"Simple synthesizer",
|
||||
`
|
||||
"Simple synthesizer",
|
||||
`
|
||||
let smooth = (sound) => {
|
||||
return sound.cutoff(r(100,500))
|
||||
.lpadsr(usaw(1/8) * 8, 0.05, .125, 0, 0)
|
||||
@ -50,15 +50,15 @@ beat(.25)::smooth(sound('sawtooth')
|
||||
beat(.25)::smooth(sound('sawtooth')
|
||||
.note([50,57,55,60].add(12).beat(1.5))).out();
|
||||
`,
|
||||
true
|
||||
)};
|
||||
true,
|
||||
)};
|
||||
|
||||
Sometimes, using a full ADSR envelope is a bit overkill. There are other simpler controls to manipulate the envelope like the <ic>.ad</ic> method:
|
||||
|
||||
|
||||
${makeExample(
|
||||
"Replacing .adsr by .ad",
|
||||
`
|
||||
"Replacing .adsr by .ad",
|
||||
`
|
||||
let smooth = (sound) => {
|
||||
return sound.cutoff(r(100,500))
|
||||
.lpadsr(usaw(1/8) * 8, 0.05, .125, 0, 0)
|
||||
@ -70,9 +70,8 @@ beat(.25)::smooth(sound('sawtooth')
|
||||
beat(.25)::smooth(sound('sawtooth')
|
||||
.note([50,57,55,60].add(12).beat(1.5))).out();
|
||||
`,
|
||||
true
|
||||
)};
|
||||
|
||||
`}
|
||||
|
||||
true,
|
||||
)};
|
||||
|
||||
`;
|
||||
};
|
||||
|
||||
@ -17,13 +17,13 @@ Use the <ic>sound(name: string)</ic> function to play a sound. You can also writ
|
||||
Whatever you choose, the syntax stays the same. See the following example:
|
||||
|
||||
${makeExample(
|
||||
"Playing sounds is easy",
|
||||
`
|
||||
"Playing sounds is easy",
|
||||
`
|
||||
beat(1) && sound('bd').out()
|
||||
beat(0.5) && sound('hh').out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
These commands, in plain english, can be translated to:
|
||||
|
||||
@ -33,13 +33,13 @@ These commands, in plain english, can be translated to:
|
||||
Let's make this example a bit more complex:
|
||||
|
||||
${makeExample(
|
||||
"Adding some effects",
|
||||
`
|
||||
"Adding some effects",
|
||||
`
|
||||
beat(1) && sound('bd').coarse(0.25).room(0.5).orbit(2).out();
|
||||
beat(0.5) && sound('hh').delay(0.25).delaytime(0.125).out();
|
||||
`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
Now, it translates as follows:
|
||||
|
||||
@ -53,12 +53,14 @@ If you remove <ic>beat</ic> instruction, you will end up with a deluge of kick d
|
||||
|
||||
To play a sound, you always need the <ic>.out()</ic> method at the end of your chain. THis method tells **Topos** to send the chain to the audio engine. The <ic>.out</ic> method can take an optional argument to send the sound to a numbered effect bus, from <ic>0</ic> to <ic>n</ic> :
|
||||
|
||||
${makeExample("Using the .out method",
|
||||
`
|
||||
${makeExample(
|
||||
"Using the .out method",
|
||||
`
|
||||
// Playing a clap on the third bus (0-indexed)
|
||||
beat(1)::sound('cp').out(2)
|
||||
`, true
|
||||
)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
Try to remove <ic>.out</ic>. You will see that no sound is playing at all!
|
||||
|
||||
@ -67,16 +69,16 @@ Try to remove <ic>.out</ic>. You will see that no sound is playing at all!
|
||||
- Sounds are **composed** by adding qualifiers/parameters that modify the sound or synthesizer you have picked (_e.g_ <ic>sound('...').blabla(...)..something(...).out()</ic>. Think of it as _audio chains_.
|
||||
|
||||
${makeExample(
|
||||
'Complex sonic object',
|
||||
`
|
||||
"Complex sonic object",
|
||||
`
|
||||
beat(1) :: sound('pad').n(1)
|
||||
.begin(rand(0, 0.4))
|
||||
.freq([50,52].beat())
|
||||
.size(0.9).room(0.9)
|
||||
.velocity(0.25)
|
||||
.pan(usine()).release(2).out()`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
## Picking a specific sound
|
||||
|
||||
@ -100,12 +102,12 @@ If you choose the sound <ic>kick</ic>, you are asking for the first sample in th
|
||||
|
||||
The <ic>.n(number)</ic> method can be used to pick a sample from the currently selected sample folder. For instance, the following script will play a random sample from the _kick_ folder:
|
||||
${makeExample(
|
||||
"Picking a sample",
|
||||
`
|
||||
"Picking a sample",
|
||||
`
|
||||
beat(1) && sound('kick').n([1,2,3,4,5,6,7,8].pick()).out()
|
||||
`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
You can also use the <ic>:</ic> to pick a sample number directly from the <ic>sound</ic> function:
|
||||
|
||||
@ -114,18 +116,18 @@ You can also use the <ic>:</ic> to pick a sample number directly from the <ic>so
|
||||
`
|
||||
beat(1) && sound('kick:3').out()
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)}
|
||||
|
||||
You can use any number to pick a sound. Don't be afraid of using a number too big. If the number exceeds the number of available samples, it will simply wrap around and loop infinitely over the folder. Let's demonstrate this by using the mouse over a very large sample folder:
|
||||
|
||||
${makeExample(
|
||||
"Picking a sample... with the mouse!",
|
||||
`
|
||||
"Picking a sample... with the mouse!",
|
||||
`
|
||||
// Move your mouse to change the sample being used!
|
||||
beat(.25) && sound('ST09').n(Math.floor(mouseX())).out()`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
|
||||
The <ic>.n</ic> method is also used for synthesizers but it behaves differently. When using a synthesizer, this method can help you determine the number of harmonics in your waveform. See the **Synthesizers** section to learn more about this.
|
||||
@ -147,31 +149,34 @@ There is a special method to choose the _orbit_ that your sound is going to use:
|
||||
|
||||
You can play a sound _dry_ and another sound _wet_. Take a look at this example where the reverb is only affecting one of the sounds:
|
||||
|
||||
${makeExample("Dry and wet", `
|
||||
${makeExample(
|
||||
"Dry and wet",
|
||||
`
|
||||
|
||||
// This sound is dry
|
||||
beat(1)::sound('hh').out()
|
||||
|
||||
// This sound is wet (reverb)
|
||||
beat(2)::sound('cp').orbit(2).room(0.5).size(8).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## The art of chaining
|
||||
|
||||
Learning to create complex chains is very important when using **Topos**. It can take some time to learn all the possible parameters. Don't worry, it's actually rather easy to learn.
|
||||
|
||||
${makeExample(
|
||||
"Complex chain",
|
||||
`
|
||||
"Complex chain",
|
||||
`
|
||||
beat(0.25) && sound('fhh')
|
||||
.sometimes(s=>s.speed([2, 0.5].pick()))
|
||||
.room(0.9).size(0.9).gain(1)
|
||||
.cutoff(usine(1/2) * 5000)
|
||||
.out()`,
|
||||
true
|
||||
)}
|
||||
true,
|
||||
)}
|
||||
|
||||
Most audio parameters can be used both for samples and synthesizers. This is quite unconventional if you are familiar with a more traditional music software.
|
||||
`}
|
||||
|
||||
|
||||
`;
|
||||
};
|
||||
|
||||
@ -18,14 +18,13 @@ Three additional effects that are easy enough to understand. These effects are d
|
||||
|
||||
|
||||
${makeExample(
|
||||
"Crunch... crunch... crunch!",
|
||||
`
|
||||
"Crunch... crunch... crunch!",
|
||||
`
|
||||
beat(.5)::snd('pad').coarse($(1) % 16).clip(.5).out(); // Comment me
|
||||
beat(.5)::snd('pad').crush([16, 8, 4].beat(2)).clip(.5).out()
|
||||
`,
|
||||
true
|
||||
)};
|
||||
|
||||
`}
|
||||
|
||||
true,
|
||||
)};
|
||||
|
||||
`;
|
||||
};
|
||||
|
||||
@ -24,12 +24,12 @@ For that reason, it is often a good idea to set fixed reverb values per orbit. D
|
||||
| <ic>roomdim</ic> | | Reverb lowpass frequency at -60db (in hertz) |
|
||||
|
||||
${makeExample(
|
||||
"Clapping in the cavern",
|
||||
`
|
||||
"Clapping in the cavern",
|
||||
`
|
||||
beat(2)::snd('cp').room(0.5).size(4).out()
|
||||
`,
|
||||
true
|
||||
)};
|
||||
true,
|
||||
)};
|
||||
|
||||
## Delay
|
||||
|
||||
@ -42,10 +42,13 @@ A good sounding delay unit that can go into feedback territory. Use it without m
|
||||
| <ic>delayfeedback</ic> | delayfb | Delay feedback (between <ic>0</ic> and <ic>1</ic>) |
|
||||
|
||||
${makeExample(
|
||||
"Who doesn't like delay?", `
|
||||
"Who doesn't like delay?",
|
||||
`
|
||||
beat(2)::snd('cp').delay(0.5).delaytime(0.75).delayfb(0.8).out()
|
||||
beat(4)::snd('snare').out()
|
||||
beat(1)::snd('kick').out()`, true)}
|
||||
beat(1)::snd('kick').out()`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Phaser
|
||||
|
||||
@ -56,13 +59,17 @@ beat(1)::snd('kick').out()`, true)}
|
||||
| <ic>phaserSweep</ic> | <ic>phassweep</ic> | Phaser frequency sweep (in hertz) |
|
||||
| <ic>phaserCenter</ic> | <ic>phascenter</ic> | Phaser center frequency (default to 1000) |
|
||||
|
||||
${makeExample("Super cool phaser lick", `
|
||||
${makeExample(
|
||||
"Super cool phaser lick",
|
||||
`
|
||||
rhythm(.5, 7, 8)::sound('wt_stereo')
|
||||
.phaser(0.75).phaserSweep(3000)
|
||||
.phaserCenter(1500).phaserDepth(1)
|
||||
.note([0, 1, 2, 3, 4, 5, 6].scale('pentatonic', 50).beat(0.25))
|
||||
.room(0.5).size(4).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Distorsion, saturation, destruction
|
||||
|
||||
@ -76,11 +83,12 @@ Three additional effects that are easy enough to understand. These effects are d
|
||||
|
||||
|
||||
${makeExample(
|
||||
"Crunch... crunch... crunch!",
|
||||
`
|
||||
"Crunch... crunch... crunch!",
|
||||
`
|
||||
beat(.5)::snd('pad').coarse($(1) % 16).clip(.5).out(); // Comment me
|
||||
beat(.5)::snd('pad').crush([16, 8, 4].beat(2)).clip(.5).out()
|
||||
`,
|
||||
true
|
||||
)};
|
||||
`}
|
||||
true,
|
||||
)};
|
||||
`;
|
||||
};
|
||||
|
||||
@ -28,8 +28,8 @@ The sampler is a rather complex beast. There is a lot you can do by manipulating
|
||||
Let's apply some of these methods naïvely. We will then break everything using simpler examples.
|
||||
|
||||
${makeExample(
|
||||
"Complex sampling duties",
|
||||
`
|
||||
"Complex sampling duties",
|
||||
`
|
||||
// Using some of the modifiers described above :)
|
||||
beat(.5)::snd('pad').begin(0.2)
|
||||
.speed([1, 0.9, 0.8].beat(4))
|
||||
@ -38,45 +38,61 @@ beat(.5)::snd('pad').begin(0.2)
|
||||
.room(0.8).size(0.5)
|
||||
.clip(1).out()
|
||||
`,
|
||||
true
|
||||
)};
|
||||
true,
|
||||
)};
|
||||
|
||||
|
||||
## Playback speed / pitching samples
|
||||
|
||||
Let's play with the <ic>speed</ic> parameter to control the pitch of sample playback:
|
||||
|
||||
${makeExample("Controlling the playback speed", `
|
||||
${makeExample(
|
||||
"Controlling the playback speed",
|
||||
`
|
||||
beat(0.5)::sound('notes')
|
||||
.speed([1,2,3,4].palindrome().beat(0.5)).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
It also works by using negative values. It reverses the playback:
|
||||
|
||||
${makeExample("Playing samples backwards", `
|
||||
${makeExample(
|
||||
"Playing samples backwards",
|
||||
`
|
||||
beat(0.5)::sound('notes')
|
||||
.speed(-[1,2,3,4].palindrome().beat(0.5)).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
Of course you can play melodies using samples:
|
||||
|
||||
|
||||
${makeExample("Playing melodies using samples", `
|
||||
${makeExample(
|
||||
"Playing melodies using samples",
|
||||
`
|
||||
beat(0.5)::sound('notes')
|
||||
.room(0.5).size(4)
|
||||
.note([0, 2, 3, 4, 5].scale('minor', 50).beat(0.5)).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Panning
|
||||
|
||||
To pan samples, use the <ic>.pan</ic> method with a number between <ic>0</ic> and <ic>1</ic>.
|
||||
|
||||
|
||||
${makeExample("Playing melodies using samples", `
|
||||
${makeExample(
|
||||
"Playing melodies using samples",
|
||||
`
|
||||
beat(0.25)::sound('notes')
|
||||
.room(0.5).size(4).pan(r(0, 1))
|
||||
.note([0, 2, 3, 4, 5].scale('minor', 50).beat(0.25)).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
|
||||
## Looping over a sample
|
||||
@ -84,26 +100,30 @@ beat(0.25)::sound('notes')
|
||||
Using <ic>loop</ic> (<ic>1</ic> for looping), <ic>loopBegin</ic> and <ic>loopEnd</ic> (between <ic>0</ic> and <ic>1</ic>), you can loop over the length of a sample. It can be super effective to create granular effects.
|
||||
|
||||
|
||||
${makeExample("Granulation using loop", `
|
||||
${makeExample(
|
||||
"Granulation using loop",
|
||||
`
|
||||
beat(0.25)::sound('fikea').loop(1)
|
||||
.lpf(ir(2000, 5000))
|
||||
.loopBegin(0).loopEnd(r(0, 1))
|
||||
.room(0.5).size(4).pan(r(0, 1))
|
||||
.note([0, 2, 3, 4, 5].scale('minor', 50).beat(0.25)).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Stretching a sample
|
||||
|
||||
The <ic>stretch</ic> parameter can help you to stretch long samples like amen breaks:
|
||||
|
||||
${makeExample(
|
||||
"Playing an amen break",
|
||||
`
|
||||
"Playing an amen break",
|
||||
`
|
||||
// Note that stretch has the same value as beat
|
||||
beat(4) :: sound('amen1').n(11).stretch(4).out()
|
||||
beat(1) :: sound('kick').shape(0.35).out()`,
|
||||
true,
|
||||
)};
|
||||
true,
|
||||
)};
|
||||
|
||||
## Cutting samples
|
||||
|
||||
@ -111,34 +131,45 @@ Sometimes, you will find it necessary to cut a sample. It can be because the sam
|
||||
|
||||
Know about the <ic>begin</ic> and <ic>end</ic> parameters. They are not related to the sampler itself, but to the length of the event you are playing. Let's cut the granular example:
|
||||
|
||||
${makeExample("Cutting a sample using end", `
|
||||
${makeExample(
|
||||
"Cutting a sample using end",
|
||||
`
|
||||
beat(0.25)::sound('notes')
|
||||
.end(usine(1/2)/0.5)
|
||||
.room(0.5).size(4).pan(r(0, 1))
|
||||
.note([0, 2, 3, 4, 5].scale('minor', 50).beat(0.25)).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
You can also use <ic>clip</ic> to cut the sample everytime a new sample comes in:
|
||||
|
||||
|
||||
${makeExample("Cutting a sample using end", `
|
||||
${makeExample(
|
||||
"Cutting a sample using end",
|
||||
`
|
||||
beat(0.125)::sound('notes')
|
||||
.cut(1)
|
||||
.room(0.5).size(4).pan(r(0, 1))
|
||||
.note([0, 2, 3, 4, 5].scale('minor', 50).beat(0.125)
|
||||
+ [-12,12].beat()).out()
|
||||
`, true)}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
## Adding vibrato to samples
|
||||
|
||||
You can add vibrato to any sample using <ic>vib</ic> and <ic>vibmod</ic>:
|
||||
|
||||
${makeExample("Adding vibrato to a sample", `
|
||||
${makeExample(
|
||||
"Adding vibrato to a sample",
|
||||
`
|
||||
|
||||
beat(1)::sound('fhang').vib([1, 2, 4].bar()).vibmod([0.5, 2].beat()).out()
|
||||
`, true)}
|
||||
|
||||
|
||||
`}
|
||||
`,
|
||||
true,
|
||||
)}
|
||||
|
||||
|
||||
`;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user