big update

This commit is contained in:
2024-01-08 01:58:04 +01:00
parent 886d8eed62
commit b6231fde39
17 changed files with 224 additions and 225 deletions

View File

@ -4,36 +4,47 @@
BuboQuark is a collection of methods and hacks I have found to make _live
coding_ easier on SuperCollider. Since the Quark itself does not bring
much value and does not change SuperCollider radically, I have thought about
creating this website to document my findings and help other people get started.
much value and does not change SuperCollider in a radical new way, I have wondered what
made me so excited about it. I don't have the definitive answer but I think that
it comes from the fact that I am learning quite a lot by browsing
SuperCollider's infinite possibilities.
I have thought about
creating this website to document my findings and hacks and help other people get started live coding using it.
This small website takes inspiration from [how to co34pt livecode](https://github.com/theseanco/howto_co34pt_liveCode), another great read.
BuboQuark, thus, can be said to be:
- a small Quark to setup SuperCollider for _live coding_ and sound exploration.
- a companion tutorial website to learn how to use that setup and SuperCollider.
BuboQuark can be thought of as my personal SuperCollider configuration. It twists it just enough simply for my own convenience. Internally, it relies a lot on JITLib, Patterns and NodeProxies. It truly feels like a collection of tips and hacks found on the internet.
BuboQuark can be also be thought of as my personal SuperCollider configuration. It twists it just enough simply for my own convenience. It changes a lot, quite abruptly, and it reflects my way of learning how to use this platform in a musical way. It is not rocket science SuperCollider but I hope that this is helpful to some people anyway.
### What does it talk about?
### Who am I? Who is this for?
I am a big fan of _live coding_ and I have been practicing it for a while. I
I am a big fan of _live coding_ and I have been playing that way for a while. I
have created the [Sardine](https://sardine.raphaelforment.fr) and
[Topos](https://topos.live) live coding environments. Writing code to make music
live is part of my daily musical practice. Like anybody else, I like to have
many different tools to make music. I have been using SuperCollider for a long
time, but most of the time using it as an audio backend and talking to it
through Python, Haskell, JavaScript and so on. I never really learned to play it live. I have some requirements for a tool to be usable in a live context and most specifically as a part of my musical practice:
live is part of my daily music practice. Like anybody else, I like to have
many different tools to make music and I always wished to master SuperCollider
just enough to play gigs using it. Like many _live coders_, I have been using SuperCollider for quite some time. Most of the time, I only use it as an audio backend and talk to it through Python, Haskell, JavaScript and basically any other language except the good old **SCLang**. I never really learned to play with SuperCollider live.
I have some requirements for a tool to be usable in a live context and more specifically as a part of my ever-changing toolset:
- I need a powerful sequencer / scheduler for musical events
- I need to be able to talk with other softwares / devices easily
- I need a playground for audio synthesis and experimenting with sounds
- I need to be able to play with my friends and synchronize easily
Everything else is accessory and I can easily live without it (graphical
interfaces, widgets, etc). SuperCollider, out of the box, ticks all the boxes. I
SuperCollider, out of the box, ticks all the boxes. I
can do everything using just that tool and it's a great thing since it is
available on most platforms and doesn't consume a lot of resources by default.
I guess that this guide / tutorial is for people who are similarly curious about
SuperCollider and want to use it in a live context. It is also written for other
live coders that can feel intimidated by SuperCollider's complexity and want to
understand it enough to make it sing.
### What music can I make using it?
My interest for electronic music ranges from experimental and noise to [Algorave](https://algorave.com) club-like music. I also like to slice sounds, to play around with oscillators, filters, delays and modular synths. Consequently, you will find a lot about this here and not so much about traditional music production or composition.
My interest for electronic music ranges from experimental/noisy/art music to [Algorave](https://algorave.com) club-like music. This is reflected in the examples and the techniques I have gathered here. I like to play with samples, synthesis, using computation and algorithms to twist things in unexpected ways. I also like just to play boring pattern-based music sometimes. I hope that this guide will be useful to people with similar interests.

View File

@ -1,4 +1,4 @@
* Guide
* BuboQuark Reference
* Installation
- [Before we start](warning.md)
- [Dependencies](dependencies.md)
@ -6,7 +6,7 @@
- [Editing code](editor.md)
* Configuration
- [Boot Method](boot.md)
- [Session start](boot.md)
- [Configuration](configuration.md)
- [Audio routing](routing.md)
- [More options](more_options.md)
@ -18,10 +18,14 @@
* Patterns
- [Tempo and Clock](clock.md)
- [Player shortcuts](player.md)
- [Key shortcuts](key_shortcuts.md)
- [Pattern shortcuts](pattern.md)
- [Dynamic control](dynamic.md)
* Sampling
- [Sample Library](library.md)
- [Using samples](sampling.md)
* Audio effects
* Live Coding with SC
- [I - A study of rhythms](first_session.md)
- [II - A study of timbres](second_session.md)
- [III - A study of modulations](third_session.md)
- [IV - A study of controls](fourth_session.md)
- [V - Everything together](final.md)

View File

@ -6,15 +6,13 @@ interpreter, there is a clock created by default, accessible through the `TempoC
The `LinkClock` is accessible through the `c` global variable. Be careful not to
override it by mistake! It behaves like the regular default `TempoClock` with the typical methods from this class. The main difference is that this timing information is shared with other peers on the network. You can synchronize easily with your friends ... basically by doing nothing if their applications are also using the same protocol.
**Note:** The few additional methods are already very well documented.
**Note:** For _live coding_, you will need to use the clock fairly often to synchronize your time-based effects with it or to write various routines.
**Note 2:** For _live coding_, you will need to use the clock fairly often to synchronize your time-based effects with it or to write various routines.
##### Setting / Getting the tempo
### Setting / Getting the tempo
Use `c.tempo` to set or get the current tempo. Note that it _will_ change the tempo of the other peers. Be careful if you are playing with other people as they will probably not like it very much. There is also a `.beats` and `.quantum` method that can be used for other time-based calculations but I almost never use them.
##### Beat duration
### Beat duration
Use `c.beatDur` to get the duration of a beat. This is so useful that I have
created a shortcut for it: `c.dur`. It is a very common thing to use in audio

44
docs/dynamic.md Normal file
View File

@ -0,0 +1,44 @@
# Dynamic Control
The problem of using patterns and fixed values too much is that your patterns
can start to sound a bit rigid. They will lack the kind of life and movement
that you might strive for. One of my favorite features from SuperCollider is that you can modulate every key of your `Pbind` very freely at control rate. This blends the limit between writing patterns and writing DSP algorithms. You often feel like you are jumping very smoothly between working at the signal level and working at the control level.
I typically think of patterns as having three different types of controls:
- **language-based values:** using patterns, fixed values, discrete values, etc.
- **continuous modulations:** low-frequency modulations (LFOs), random signals, etc.
- **gated modulations:** envelopes, triggers, etc.
This is a very shallow typology but it is enough to start thinking about how to combine these three types of controls. I will now go through each of them and show you how BuboQuark manages them.
## Continuous modulations
There is nothing to do here. You can use the regular SuperCollider syntax to modulate your patterns. For example, if you want to modulate the `\freq` of a synth, you can do it like this:
```supercollider
["modulating_frequency", i: "default", amp: 0.5,
freq: Ndef(\example, {SinOsc.ar(c.dur * 2).range(500, 2000)})].pat.play;
```
This example sounds horrible but it demonstrates that you can use regular `Ndef`
or any `NodeProxy` to get that type of modulation. We could also write it this
way:
```supercollider
~example = {SinOsc.ar(c.dur * 2).range(500, 2000)};
["modulating_frequency", i: "default", amp: 0.5, freq: ~example].pat.play;
```
This is up to you to decide which one you prefer.
## Gated modulations
It was a bit more difficult to find a good way to handle gated modulations. I
don't think I have found the perfect solution yet but it is good enough for now. I have created another pseudo-object called `Pdyn`. Despite its name, it is not really a pattern but it is meant to be used as one. `Pdyn` will retrigger for every event inside your pattern (by default).
```supercollider
["pdyn_demo", i: "default", freq: Pdyn({XLine.ar(2000, 100, c.dur)})].pat.play;
```
I don't think that it holds very well performance wise so be careful and don't expect the best precision ever. I will likely improve it whenever possible.

73
docs/key_shortcuts.md Normal file
View File

@ -0,0 +1,73 @@
# Key shortcuts
We can take this shortening job one step further by shortening the key names used in `Pbinds`. I am not covering all of them but only the most common. Note that you can still use the regular keys. The shortcuts are just replaced with their long version when the code is being evaluated.
#### Instrument selection
This is the key that you have to use to select the synthesizer that your pattern
will be controlling. This key can also be patterned, something that people often
forget about.
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------- |
| \instrument | i | Synthdef name |
#### Amplitude envelope
I have covered the basic ADSR shortcuts but not much more.
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------------------- |
| \attack | a | Attack time (in seconds) |
| \decay | d | Decay time (in seconds) |
| \sustain | s | Sustain level (relative) |
| \release | r | Release time (in seconds) |
#### Pitch
The pitch model used by the default [Event](https://doc.sccode.org/Classes/Event.html) type is pretty complex and I will not try to sum it up here. It is better to just read about it. To print the list of available scales, use hte `Scale.directory` command.
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------------------- |
| \root | r | Root note |
| \midinote | mn | MIDI Note number |
| \note | n | Note number (O to `inf`) |
| \degree | deg | Degree of the scale |
| \octave | o | Octave number |
| \freq | f | Frequency |
| \detune | det | Detune amount |
| \scale | scl | Scale selection |
#### Duration
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------------------- |
| \dur | d | Event duration (in beats) |
| \stretch | st | Event time stretching (multiple) |
| \legato | l | Time gap between events |
| \timingOffset | off | Offset in beats |
#### Amplitude
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------------------- |
| \velocity | vel | MIDI Velocity |
#### MIDI Related keys
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------------------- |
| \midichan | c | MIDI Channel (0 to 15) |
| \midiout | mo | MIDI Output |
#### Other keys
| Key Name | Shortcut | Purpose |
| ----------- | ----------- | ------------------------- |
| \pan | p | Stereo Panning (-1 to 1) |
I will probably add some more keys in the future. They are to be found in the
`BuboArray.sc` file if you ever get curious about this small mechanism. It is
just replacing values in the list we use to generate our `Pbinds`.

View File

@ -1,9 +1,9 @@
# Audio sample library
The [Boot()](boot.md) method adds a mechanism to load audio samples automatically. The samples are lazily loaded in memory. You can load a vast library of samples without using too much memory. The mechanism is written by Scott Carver and can be found [here](https://gist.github.com/scztt/73a2ae402d9765294ae8f72979d1720e). It was originally named **SAMP**. I renamed it to **Bank** since it makes more sense to me.
The [Boot()](boot.md) method adds a mechanism to load audio samples automatically. The samples are lazily loaded in memory. You can load a vast library of samples without using too much memory. The mechanism is written by Scott Carver and can be found [here](https://gist.github.com/scztt/73a2ae402d9765294ae8f72979d1720e). It was originally named **SAMP**. I renamed it to **Bank** not to break out too much with the naming conventions.
##### Using the library
### Browsing the sample bank
If your audio sample bank path is set right, you will have access to your bank
using **Bank**:
@ -18,9 +18,9 @@ Note that you can also be more picky about the samples you want to load:
Bank('a/*')['clap'].play; // Play the first sample with 'clap' in its name
```
##### Using samples in patterns
### Using samples in patterns
This is great. I have also added a mechanism to automatically feed a sample to the default sampler when using patterns. That way, you don't have to type the `Bank` part all the time and can stay focused on your improvisation:
I have added a mechanism to automatically feed a sample to the default sampler when using patterns. That way, you don't have to type the `Bank` part all the time and can stay focused on your improvisation:
```supercollider
[
@ -36,3 +36,7 @@ Note that there is no optional argument here. You need `sp` and `nb` for it to
work. You can use these arguments when using the abbreviated syntax for `Pbind`
but not for regular `Pbind`. In that case, you will need to use the good old
`buf: Bank('a/*')[0]` syntax.
Be careful. If you forgot one of the two arguments, it is likely that the last
selected sample will play instead. This is probably easy to fix but it is what
it is.

View File

@ -1,26 +1,25 @@
# Pattern shortcuts
SuperCollider has a very large and powerful collection of Pattern classes. They allow you to create pretty much every musical pattern you can imagine but it comes with a cost: it is cumbersome to write and read. This is a known problem
since a long time ago. Many live coding frameworks have been created just to
break free of the rigid pattern syntax used by SuperCollider. BuboQuark is not meant to replace the Pattern classes entirely. This would be a bit presumptuous but also counter-productive: there is so much you can do with it already!
SuperCollider has a very large and powerful collection of Pattern classes. They allow you to create pretty much every musical pattern you can imagine but it comes with a cost: they are cumbersome to write and read. The question of patterns seems to be a divisive topic in the broader community. Some use them a lot, some do their absolute best to avoid them.
I just bring a few shortcuts to make it easier to write and read patterns whenever possible. Once again, there is a strong reliance on arrays to do so. This is not the state of the art approach but it is a good compromise between simplicity and flexibility. Once again, I do not break compatibility with the base language.
The difficulty of writing patterns live is a well known challenge. Many live coding frameworks have been created just to
break free of the rigid pattern syntax used by SuperCollider. BuboQuark is not trying to replace the Pattern classes entirely because they are really nice. This would be a bit presumptuous and also counter-productive: there is so much you can do with patterns already!
##### Pdv to write melodies/rhythms
I just bring a few shortcuts to make it easier to write and read patterns whenever possible. Once again, there is a strong reliance on arrays to do so. This is not the state of the art approach but it is a good compromise between simplicity and flexibility. The kind of shortcuts I'm creating here have been used in the community for a long time. Each person typically creates his own shortcuts.
There is a little rather unknown Quark called [Pdv](https://github.com/dmorgan-github/Pdv). This Quark brings a new method to parse a string into a pattern, inspired by the [TidalCycles](https://tidalcycles.org) syntax. There are other Quarks doing just the same thing like [Bacalao](https://github.com/totalgee/bacalao) but they are a little bit more involved. They expect you to adhere to the way the framework works, departing from the base syntax.
### Pdv to write melodies/rhythms
There is a little and rather unknown Quark called [Pdv](https://github.com/dmorgan-github/Pdv). This Quark brings a new method to parse a string into a pattern, inspired by the [TidalCycles](https://tidalcycles.org) syntax. There are other Quarks doing just the same thing like [Bacalao](https://github.com/totalgee/bacalao) but they are a little bit difficult to use. They work inside of a larger framework that you have to adhere to, departing from the base syntax.
**Pdv** is super transparent. It just adds a new method to use on the `deg:` key of your patterns. `Pdv` will take care of turning that list into the `dur` and `degree` keys, facilitating the writing of rhythms and melodies. I have assocciated this method with the `.p` method of the string class. It means that you can use the following syntax to write patterns:
```supercollider
(
[
"fmintro", i: "fm",
// Look at the following line!
deg: "0^4 ~^4 {0 5 7}^4 ~ -5^4 ~^4 {0 5 8 10}^4 ~".p,
o: [4, 5], db: -20, attack: [0.1, 0.3].pwhite,
].pat.play;
)
```
@ -41,9 +40,9 @@ $ - shuffle group of values
, - can be used as visual separator to help readability
```
##### Existing array shortcuts
### Array shortcuts
These shortcuts are syntax sugar for turning a list into a pattern (_e.g._ `[1, 2, 3].pseq`). They work just like the regular Pattern type they correspond to.
These shortcuts are syntax sugar for turning a list into a pattern (_e.g._ `[1, 2, 3].pseq`). They work just like the regular Pattern type they correspond to. I could create a thousand of them but so far, I only cover the most common types.
- `pseq(repeats=inf, offset=0)`: shortcut for `Pseq`
- `pshuf(repeats=1)`: shortcut for `Pshuf`
@ -53,7 +52,9 @@ These shortcuts are syntax sugar for turning a list into a pattern (_e.g._ `[1,
- `pwhite(repeats=inf)`: shortcut for `Pwhite`
- `pseries(repeats=inf)`: shortcut for `Pseries`
##### Euclidian rhythms
Replacing all of them is probably not the best idea. The library is so vast that some Pattern classes are not encountered very often. Some are also quite specific with the type of arguments they require and pushing everything in an Array can hinder code completion / readability.
There is a Quark named Pborklund that brings euclidian rhythms to the SuperCollider pattern library. Do you see yourself typing `Pbjorklund2(5, 8, inf)` everytime you want to use it? I don't. I have created a shortcut for it: `Eu(5, 8, inf)`. That's it. I don't have anything more to say about it.
### Euclidian rhythms
There is a Quark named Pborklund that implements [euclidean rhythms](https://en.wikipedia.org/wiki/Euclidean_rhythm) to the SuperCollider pattern library. Do you see yourself typing `Pbjorklund2(5, 8, inf)` everytime you want to use it? I don't. I have created a shortcut for it: `Eu(5, 8, inf)`. That's it. I don't have anything more to say about it.

View File

@ -1,10 +1,12 @@
# Player shortcuts
# Player/Pbind shortcuts
##### Rationale
JITLib allows you to update musical patterns on the fly and to quantize that
change to a logical time division in the future. If you want to play some
pattern-based _live coded_ music, this is the technique you will be using a lot both for drums, melodies, etc. Take a look at the following example that could be taken from the JITLib tutorial:
JITLib is allowing you to update musical patterns on the fly. If you want to do
pattern-based _live coding_, this is the technique you will be using all the
time. Take a look at the following example:
<details>
<summary>Long SuperCollider Pattern Example</summary>
```supercollider
// This is a very simple synthesizer
@ -23,15 +25,20 @@ SynthDef(\test, {
\dur, 0.25,
\legato, 0.1
);
// Fade-in over four beats
~melody.play(fadeTime: 4);
)
// We clear that melody after 2 beats (fade-out)
~melody.clear(fadeTime: 2);
```
</details>
This does the job but it is a bit verbose. I have added a few shortcuts to make
it easier to edit patterns on the fly. Here is the same example using the
convenience and hacks brought by BuboQuark. I am skipping the synth definition:
This is doing the job but many people, including me, find it a bit verbose. I have added a few shortcuts to make
it easier to edit patterns on the fly. Here is the same example now using the
convenience and hacks brought by BuboQuark. I am skipping the synth definition
since we already added it to the server:
```supercollider
["pattern", i: 'test',
@ -39,10 +46,11 @@ convenience and hacks brought by BuboQuark. I am skipping the synth definition:
dur: 1/4, leg: 0.1].pat.play;
```
This is just saving you a few keystrokes here. There are other advantages
brought by this syntax that we will see later on.
This is just saving you a few keystrokes but will save you thousands in the long
run. There is multiple techniques used here to shorten the pattern. I will now
explain them one by one.
##### Declaring patterns
### Pattern declaration
BuboQuark is adding multiple methods to facilitate the creation of `Pbinds`:
@ -51,15 +59,21 @@ name of the NodeProxy you want to use**.
- `quant`: pattern quantization (clock)
- `fade`: fading time between evaluations
- `.p`: simple conversion from an array to a `Pbind`. This is useful when you want to use the `NodeProxy` roles like `\set` and `\xset`. It doesn't do more than that.
##### Usage with base syntax
It replaces the verbose `Pbind(\key, value)` used by SuperCollider with an Array based syntax that is more concise to read and write: `[key: value]`.
### Blending with the base syntax
BuboQuark does not break the compatibility with the base syntax. You can still control your NodeProxies using the regular syntax. For example, if you want to change the `\amp` of the previous example, you can do it like this:
```supercollider
// Playing a kick drum using the abbreviated syntax
["drumming", i: "s", sp: "kick", nb: 0, amp: 0.2].pat.play;
(
["drumming", instrument: "s",
sp: "kick", nb: 0,
amp: 0.2
].pat.play;
)
~drumming.xset(\amp, 0.5); // Changing the amp to 0.5
@ -67,4 +81,4 @@ BuboQuark does not break the compatibility with the base syntax. You can still c
~drumming.clear;
```
NodeProxies are still the base object used when improvising. I am just bringing syntax sugar and varnish.
`NodeProxy` is still the base object used here. I am just bringing syntax sugar and varnish. There is no incompatibility with the rest of the language.

View File

@ -1 +0,0 @@
# Sampling

View File

@ -5,15 +5,6 @@ any additional interface. I don't have to memorize a lot of shortcuts because I
can just evaluate the command I need to run. I have added a few shortcuts to
some of the most common tasks I do when experimenting or playing live.
### Clear everything
The following command will clear the current ProxySpace and get rid of all the
definitions:
```supercollider
currentEnvironment.clear;
```
### Panic mode
When you are playing live, you want to be able to stop everything **immediately**:
@ -22,3 +13,13 @@ When you are playing live, you want to be able to stop everything **immediately*
It will also print out a message in the post window about the current state of
the session. **Note:** if you are using Neovim, you can also just press `F12`. It is the same as pressing `Ctrl+.` in the IDE. I just tend to be focused on my keyboard so writing `Panic()` is totally fine.
### Clear everything
The following command will clear the current ProxySpace and get rid of all the definitions:
```supercollider
currentEnvironment.clear;
```

1
docs/studies/final.md Normal file
View File

@ -0,0 +1 @@
# Ending

View File

@ -0,0 +1 @@
# A study of rhythms

View File

@ -0,0 +1 @@
# A study of controls

View File

@ -0,0 +1 @@
# A study of timbres

View File

@ -0,0 +1 @@
# A study of modulations