From 85c384d946fbfef7e7419e6b1d569b4edac3b49e Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Sun, 7 Jan 2024 21:58:34 +0100 Subject: [PATCH] save temporary work --- BuboQuark.quark | 1 + Classes/BuboBoot.sc | 41 +++++++++++++---------- Classes/GUI/BuboScope.sc | 21 ++++++++++++ docs/.nojekyll | 0 docs/README.md | 39 ++++++++++++++++++++++ docs/Warning.md | 40 +++++++++++++++++++++++ docs/_sidebar.md | 27 ++++++++++++++++ docs/boot.md | 45 ++++++++++++++++++++++++++ docs/clock.md | 41 +++++++++++++++++++++++ docs/configuration.md | 23 +++++++++++++ docs/dependencies.md | 29 +++++++++++++++++ docs/editor.md | 12 +++++++ docs/index.html | 43 ++++++++++++++++++++++++ docs/library.md | 38 ++++++++++++++++++++++ docs/more_options.md | 17 ++++++++++ docs/pattern.md | 59 +++++++++++++++++++++++++++++++++ docs/player.md | 70 ++++++++++++++++++++++++++++++++++++++++ docs/recommended.md | 27 ++++++++++++++++ docs/routing.md | 29 +++++++++++++++++ docs/sampling.md | 1 + docs/server_shortcuts.md | 24 ++++++++++++++ docs/widgets.md | 49 ++++++++++++++++++++++++++++ 22 files changed, 659 insertions(+), 17 deletions(-) create mode 100644 docs/.nojekyll create mode 100644 docs/README.md create mode 100644 docs/Warning.md create mode 100644 docs/_sidebar.md create mode 100644 docs/boot.md create mode 100644 docs/clock.md create mode 100644 docs/configuration.md create mode 100644 docs/dependencies.md create mode 100644 docs/editor.md create mode 100644 docs/index.html create mode 100644 docs/library.md create mode 100644 docs/more_options.md create mode 100644 docs/pattern.md create mode 100644 docs/player.md create mode 100644 docs/recommended.md create mode 100644 docs/routing.md create mode 100644 docs/sampling.md create mode 100644 docs/server_shortcuts.md create mode 100644 docs/widgets.md diff --git a/BuboQuark.quark b/BuboQuark.quark index 2b3639d..bde7e18 100644 --- a/BuboQuark.quark +++ b/BuboQuark.quark @@ -14,6 +14,7 @@ "https://github.com/dmorgan-github/Pdv", "https://github.com/supercollider-quarks/Bjorklund", "https://github.com/adcxyz/SafetyNet", + "https://github.com/madskjeldgaard/nodeproxygui2", ], url: "https://raphaelforment.fr", isCompatible: {Main.versionAtLeast(3, 1)}, diff --git a/Classes/BuboBoot.sc b/Classes/BuboBoot.sc index d2f6854..4aedb94 100644 --- a/Classes/BuboBoot.sc +++ b/Classes/BuboBoot.sc @@ -3,11 +3,11 @@ Boot { classvar <>clock; classvar <>localPath; classvar <>samplePath; + classvar <>serverOptions; *new { - arg configPath, samplePath, soundDevice; - var s = Server.default; - var p; var c; var t; + arg configPath, samplePath, serverOptions; + var p; var c; var t; var s; var banner = "┳┓ ┓ ┳┓\n" "┣┫┓┏┣┓┏┓ ┣┫┏┓┏┓╋\n" "┻┛┗┻┗┛┗┛ ┻┛┗┛┗┛┗"; @@ -16,6 +16,25 @@ Boot { "┗┛┻┗┛┗┛ ┗┛┗┛┻┛┗┛ ┛┗┗┛┛┗┻┛┗┛"; this.fancyPrint(banner, 40); + if (serverOptions == nil, + { + "-> Booting using default server configuration".postln; + s = Server.default; + s.options.numBuffers = 1024 * 128; + s.options.memSize = 8192 * 64; + s.options.numWireBufs = 2048; + s.options.maxNodes = 1024 * 32; + s.options.numOutputBusChannels = 16; + s.options.numInputBusChannels = 16; + s.options.outDevice = "BlackHole 16ch"; + }, + { + "-> Booting using user server configuration".postln; + s = Server.default; + s.options = serverOptions; + }, + ); + // Using Ableton Link Clock for automatic synchronisation with other peers this.clock = LinkClock(130 / 60).latency_(Server.default.latency).permanent_(true); TempoClock.default = this.clock; @@ -25,16 +44,7 @@ Boot { // Defining the local path as default for configuration files if not configPath this.localPath = this.class.filenameSymbol.asString.dirname +/+ "Configuration"; - // Customizing server options: less conservative than SuperCollider defaults - s.options.numBuffers = 1024 * 128; - s.options.memSize = 8192 * 64; - s.options.numWireBufs = 2048; - s.options.maxNodes = 1024 * 32; - soundDevice ? s.options.device = soundDevice; - s.options.numOutputBusChannels = 16; - s.options.numInputBusChannels = 16; - - p = ProxySpace.push(Server.default.boot, clock: this.clock); + p = ProxySpace.push(s.boot, clock: this.clock); this.samplePath = samplePath ? "/Users/bubo/.config/livecoding/samples"; // Setting up the audio samples/buffers manager @@ -52,9 +62,6 @@ Boot { }); } - /* - * Convenience method for printing a message with a fancy separator. - */ *fancyPrint { arg message, length; var separator= length.collect({ @@ -81,7 +88,7 @@ Boot { { ~buf = Bank(~sp)[~nb % Bank(~sp).buffers.size]; } ); if (~nb == nil) {~nb = 0}; - ~type = \note; // back to note + ~type = \note; currentEnvironment.play; }); } diff --git a/Classes/GUI/BuboScope.sc b/Classes/GUI/BuboScope.sc index 0da2299..3078b6e 100644 --- a/Classes/GUI/BuboScope.sc +++ b/Classes/GUI/BuboScope.sc @@ -5,3 +5,24 @@ Scope { } } + +Meter { + + *new { + var window = Window.new( + "Meter", + Rect.new(left: 0, top: 0, width: 680, height: 250), + resizable: false, + border: true, + scroll: false + ); + var meters = ServerMeterView.new( + Server.default, window, + 0@0, 16, 16 + ); + window.front; + window.alwaysOnTop = true; + ^window + } + +} diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..581dfa7 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,39 @@ +# BuboQuark + +### What is this? + +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. +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. + +### What does it talk about? + +I am a big fan of _live coding_ and I have been practicing it 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: + +- 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 +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. + +### 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. diff --git a/docs/Warning.md b/docs/Warning.md new file mode 100644 index 0000000..2e96a47 --- /dev/null +++ b/docs/Warning.md @@ -0,0 +1,40 @@ +# Before reading this guide + + +This guide is a not a general purpose tutorial. It will not teach you how to use +SuperCollider. If you are brave enough, you can learn by doing/following the +steps. However, you will sometimes feel the need to read other sources to fill +the gaps. I am not a SuperCollider guru and I do just that when the need arises. + +## Learning resources + +There are already many great resources to learn SuperCollider. I recommend the +following among many other ressources: + + +- [SuperCollider for the Creative Musician](https://global.oup.com/academic/product/supercollider-for-the-creative-musician-9780197616994?cc=fr&lang=en&) by Eli FieldSteel: the best educator I know to learn SuperCollider. The book can be expensive for some people. If you can't afford it, read the following point. + - [Eli Fieldsteel YouTube + Channel](https://www.youtube.com/user/elifieldsteel): Eli Fieldsteel has made + a great series of video tutorials that are free to watch. This is the best way + to learn SuperCollider that I am aware of. + +- [A gentle introduction to SuperCollider](https://ccrma.stanford.edu/~ruviaro/texts/A_Gentle_Introduction_To_SuperCollider.pdf) by Bruno Ruviaro: a great introduction to SuperCollider with an emphasis of making music / composing first. Especially great for patterns and sequencing. + +- [A practical Guide](https://doc.sccode.org/Browse.html#Streams-Patterns-Events%3EA-Practical-Guide) by H. James Harkins: already included in the SuperCollider help files. Easy to read, with interactive code examples. + +## Lurking around + +It's probably a good idea to lurk around the SuperCollider community to see what +people are doing with the software and how they make music with it. I really +like to spend hours browsing the web. Here are some good resources: + +- [SCCode](https://sccode.org/): some website where people post their +SuperCollider code. You can find some classics there and some recent +experiments too! +- [SuperCollider Forum](https://scsynth.org): obviously, the official forum. +This is where most of the gurus are answering questions to new users and having +debated about some aspects of the language or audio server. +- [YouTube](https//youtube.com): just search _supercollider live coding_ or +something like that. Tons of people are posting their live coding sessions. +There is [Nathan Ho](https://www.youtube.com/@synth_def), [Jaxa](https://www.youtube.com/@JaxaSound) and all the live coding folks that play in the [Eulerroom](https://www.youtube.com/@Eulerroom). + diff --git a/docs/_sidebar.md b/docs/_sidebar.md new file mode 100644 index 0000000..9662d96 --- /dev/null +++ b/docs/_sidebar.md @@ -0,0 +1,27 @@ +* Guide + * Installation + - [Before we start](warning.md) + - [Dependencies](dependencies.md) + - [Recommended](recommended.md) + - [Editing code](editor.md) + + * Configuration + - [Boot Method](boot.md) + - [Configuration](configuration.md) + - [Audio routing](routing.md) + - [More options](more_options.md) + + * Server control + * [Widgets (GUI)](widgets.md) + - [Commands](server_shortcuts.md) + + * Patterns + - [Tempo and Clock](clock.md) + - [Player shortcuts](player.md) + - [Pattern shortcuts](pattern.md) + + * Sampling + - [Sample Library](library.md) + - [Using samples](sampling.md) + + * Audio effects diff --git a/docs/boot.md b/docs/boot.md new file mode 100644 index 0000000..fce3ab5 --- /dev/null +++ b/docs/boot.md @@ -0,0 +1,45 @@ +# Boot the server + +There is a `Boot()` pseudo-class acting as a configuration file. Its behavior +is pretty classic if you are already accustomed to SuperCollider: + +- it raises the conservative options of `Server.default` to allow more connexions, + more buffers, etc. Will prevent you from running out of memory while +improvising. + +- turns the the default environment into a **JITLib** `ProxySpace`, replacing +all global variables with `NodeProxy` instances. This is one of the classic +_ways_ to _live code_ using SuperCollider. + + +- set the `ProxySpace` to use `LinkClock` for syncing with other. +`LinkClock` is using the [Ableton Link protocol](https://ableton.github.io/link/), supported by most other apps. + +- Set custom paths for loading audio sample banks and synth definitions. Write +your definitions once, reuse them all the time (if you want to!). + +- Set up a sound limit to prevent you from blowing up your speakers/ears. This is an often overlooked step that can save you from a lot of trouble. BuboQuark will also automatically load the _SafetyNet_ Quark to protect you from loud / incorrect audio signals. + +The `Boot()` constructor takes three arguments: + +- `configPath`: path to a `.scd` configuration file that will be automatically +loaded +- `samplePath`: path to a folder containing your audio samples (in sub-folders) +- `serverOptions`: a set of [ServerOptions](https://doc.sccode.org/Classes/ServerOptions.html) to fine tune the server configuration + +All of these arguments are optional. However, they will default to my +configuration if not set. If you want to set one option but not the others, use +keywords arguments or `nil` values. Here is an example of how you could boot the server: + +```supercollider +Boot(serverOptions: nil, // use default options + configPath: "/some/config/path", + samplePath: "/home/me/my_samples") +``` + +To make sure that you have booted correctly, you can go through the following +check list: + +- [ ] do I see my samples when I write `Bank.list`? +- [ ] do I see my synth definitions when I write `d.list`? +- [ ] is this snippet producing sound: `{SinOsc.ar(200) ! 2 * 0.5}.play`? diff --git a/docs/clock.md b/docs/clock.md new file mode 100644 index 0000000..733a594 --- /dev/null +++ b/docs/clock.md @@ -0,0 +1,41 @@ +# LinkClock + +SuperCollider is using a clock to sequence events in time. When you boot the +interpreter, there is a clock created by default, accessible through the `TempoClock.default` command. This clock is local and specific to your server. However, thanks to the client / server architecture of SuperCollider, it is quite easy to implement networked clocks that can be shared between peers. This is what the `LinkClock` class is doing through the _Ableton Link_ protocol. You just have to swap the base clock with a `LinkClock` instance and you are ready to go. This is what BuboQuark is doing. + +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 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 + +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 + +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 +functions. Take a look at the following excerpt: + +```supercollider +( +~wind = { + var wind = PinkNoise.ar() * LFNoise1.kr(c.dur * 4).range(0.01, 0.3).varlag(0.1); + wind = Pan2.ar(wind, LFNoise1.kr(c.dur * 2).range(-1, 1)); + wind = RLPF.ar(wind, LFNoise1.kr(c.dur * 2).range(200, 2000), + LFNoise1.kr(1).range(0.2, 0.9)); + wind = [BPF.ar(wind, LFNoise1.kr(c.dur / 4).range(40, 2000)), + BPF.ar(wind, LFNoise1.kr(c.dur / 2).range(40, 2000))]; + wind[1] = DelayC.ar(wind[1], 2, LFNoise1.kr(1).range(0.025, 0.3)); + wind = JPverb.ar(wind, size: 40, t60: 4 ); + wind[0] = wind[0] * LFNoise1.kr(c.dur * 4).range(0.01, 0.3).varlag(0.1); + wind[1] = wind[1] * LFNoise1.kr(c.dur * 2).range(0.01, 0.3).varlag(0.1); + wind ! 2 * 2 +} +) +``` +This is a wind sound texture that is also synchronised with the tempo thanks to +`c.dur`. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..225a406 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,23 @@ +# Configuration + +When you install the Quark, you will also inherit a folder called _Configuration_. This folder contains my personal configuration files. They are `.scd` files that will be interpreted during the boot sequence. You can use them to pre-declare synth definitions, add convenience methods, etc: + +```bash +├── Configuration +│   ├── Startup.scd +│   └── Synthdefs.scd +``` + +You do as you wish with these. They are currently very minimal and only include +a method call to setup **MIDI** and a bunch of synth definitions I use. They +rely pretty heavily on [mi-UGens](dependencies.md). + +### How to list synths and effects? + +In my personal configuration files, I am using the `d` variable to hold a +reference to every synth definition I write. I also use the `f` variable to +pre-write some audio effects that I use often. This is not hard-coded, you can +get rid of it if you want. I am also attaching a few methods to these objects: + +- `d.list`: print the list of available synth definitions. +- `d.params('synth')`: print the parameters of the synth definition named `'synth'`. diff --git a/docs/dependencies.md b/docs/dependencies.md new file mode 100644 index 0000000..da5185a --- /dev/null +++ b/docs/dependencies.md @@ -0,0 +1,29 @@ +# Dependencies + +BuboQuark is assuming that you have a standard installation of SuperCollider ready: + +- [SuperCollider](https://supercollider.github.io/): the main software, +available on most platforms, including niche ones like Raspberry Pi, and other +tiny computers. Pick the latest version, always. +- [sc3-plugins](https://github.com/supercollider/sc3-plugins): official plugin +collection for SuperCollider including many audio effects and useful synthesis objects. They are often considered standard and are available on most platforms. + +BuboQuark also uses the following external libraries / plugins: + +- [mi-Ugens](https://github.com/v7b1/mi-UGens): a collection of UGens taken from + the open-source code of Mutable Instruments Eurorack modules. This is +basically free ear candy. +- [Ported Plugins](https://github.com/madskjeldgaard/portedplugins): another +collection of UGens compiled by Mads Kjeldgaard. It includes new objects taken +from other libraries or DSP research papers. + +Everything else will be automatically installed by the Quarks system. Let's +install it now by running this command in the IDE: + +```supercollider +Quarks.install("https://github.com/bubobubobubobubo/Buboquark"); +``` + +Press `Ctrl/Cmd+Enter` to evaluate that line and the installation will promptly +start. When the install process is over, you will have to recompile the library by +pressing `Ctrl/Cmd+Shift+L`. That's it, you are ready to go! diff --git a/docs/editor.md b/docs/editor.md new file mode 100644 index 0000000..9ca70cd --- /dev/null +++ b/docs/editor.md @@ -0,0 +1,12 @@ +# Code Editors + +**SCIde** is the default code editor for SuperCollider. It works super well and +it has been fine-tuned for years to be a robust companion for the language. I +recommend you to use it if you don't have much experience with SuperCollider. It +will do its best to help you and it will be easier to browse help files from +there. + +I tend to use [Neovim]() because I do most things in Neovim these days. Some +other people [wrote about using it](https://madskjeldgaard.dk/posts/neovim-as-sc-ide/) with SuperCollider so I am not going to repeat everything. Just install [scnvim](https://github.com/davidgranstrom/scnvim) and go with the flow. This plugin is very well made and can replace the IDE if you configure it well. It is also very lightweight which is always a plus if you intend to run SuperCollider on a potato computer. + +There is some efforts in the community aiming to make [VSCode](https://code.visualstudio.com/) usable with SuperCollider but it is still [an ongoing effort](https://scsynth.org/t/vscode-supercollider-current-state-macos/8312). It is probably already usable if you take the time to install it. diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..339eccd --- /dev/null +++ b/docs/index.html @@ -0,0 +1,43 @@ + + + + + Document + + + + + + + +
+ + + + + + + + + diff --git a/docs/library.md b/docs/library.md new file mode 100644 index 0000000..f543973 --- /dev/null +++ b/docs/library.md @@ -0,0 +1,38 @@ +# 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. + + +##### Using the library + +If your audio sample bank path is set right, you will have access to your bank +using **Bank**: +```supercollider +Bank.list // List of all the available sample folders +Bank('a/*') // List of all the samples in the 'a' folder +Bank('a/*')[0].play; // Playing the first sample in the folder +``` + +Note that you can also be more picky about the samples you want to load: +```supercollider +Bank('a/*')['clap'].play; // Play the first sample with 'clap' in its name +``` + +##### 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: + +```supercollider +[ + "using_samples", + i: "s" // s is the default sampler + sp: "kick", // Give a string or symbol (pattern or not) + nb: 0 // Give a number (can be pattern too) +].pat.play +``` + + +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. diff --git a/docs/more_options.md b/docs/more_options.md new file mode 100644 index 0000000..d076967 --- /dev/null +++ b/docs/more_options.md @@ -0,0 +1,17 @@ +# More options + +BuboQuark is fine-tuned to work well on my system but you might want to set +different options for the server. SuperCollider already comes with the +[ServerOptions](https://doc.sccode.org/Classes/ServerOptions.html) class to help +with that. It is meant to be used like a set of options you can pass to your +server when you boot it. + +```supercollider +o = Server.default.options; // Gathering default options +o.outDevice = "BlackHole 16ch"; // Changing the output +Boot(serverOptions: o); // Booting with the new options +``` + +With this simple argument, you can have different boot options for each setup +you might have. Just store your configuration somewhere and pass it to the boot +method. You are not stuck with my particular defaults :) diff --git a/docs/pattern.md b/docs/pattern.md new file mode 100644 index 0000000..b6d11bd --- /dev/null +++ b/docs/pattern.md @@ -0,0 +1,59 @@ +# 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! + +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. + +##### Pdv to write melodies/rhythms + +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** 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; +) + +``` + +Note that using `pdv` will override the `degree`/`note` and `deg` keys. You can use it or ignore it depending on what you have planned but it is a good thing to have it ready to be used :) You could write the whole documentation of `Pdv` on a napkin: + +```shell +" " - empty space separates beats/values +~ - rest +[] - beat sub division or group +<> - alternating values +{} - chord values +^n - stretch duration - where n is a float +!n - repeat value - where n is an integer +$ - shuffle group of values +?n - chance of value or rest - optional probability is specified with n as an integer 0-9 +#(nnn) - choose one value from preceeding group of values, optional weights are specified within parens where n is an integer 0-9 +| - can be used as visual separator to help readability +, - can be used as visual separator to help readability +``` + +##### Existing 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. + + - `pseq(repeats=inf, offset=0)`: shortcut for `Pseq` + - `pshuf(repeats=1)`: shortcut for `Pshuf` + - `prand(repeats=inf)`: shortcut for `Prand` + - `pxrand(repeats=inf)`: shortcut for `Pxrand` + - `pwrand(weights, repeats=1)`: shortcut for `Pwrand` + - `pwhite(repeats=inf)`: shortcut for `Pwhite` + - `pseries(repeats=inf)`: shortcut for `Pseries` + +##### Euclidian rhythms + +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. + diff --git a/docs/player.md b/docs/player.md new file mode 100644 index 0000000..cc21092 --- /dev/null +++ b/docs/player.md @@ -0,0 +1,70 @@ +# Player shortcuts + +##### Rationale + +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: + +```supercollider +// This is a very simple synthesizer +( +SynthDef(\test, { + var sig = SinOsc.ar(\freq.kr(440)); + var env = EnvGen.ar(Env.perc, doneAction:2); + var synth = sig * env * \amp.kr(1); + Out.ar(\out.kr(0), Pan2.ar(synth)); +}).add; + +// We use it to create a pattern +~melody = Pbind( + \instrument, \test, + \note, Pseq([0, 2, 4, 5, 7, 9, 11, 12], inf), + \dur, 0.25, + \legato, 0.1 +); +~melody.play(fadeTime: 4); +) + +~melody.clear(fadeTime: 2); +``` + +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: + +```supercollider +["pattern", i: 'test', + note:, [0, 2, 4, 5, ...].pseq, + 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. + +##### Declaring patterns + +BuboQuark is adding multiple methods to facilitate the creation of `Pbinds`: + +- `.pat(quant=4, fade=0.05)`: create a `Pbind` from an array. **The first element of the list is always the +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 + +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.xset(\amp, 0.5); // Changing the amp to 0.5 + +~drumming.stop(fadeTime: 4); // Stopping the pattern + +~drumming.clear; +``` +NodeProxies are still the base object used when improvising. I am just bringing syntax sugar and varnish. diff --git a/docs/recommended.md b/docs/recommended.md new file mode 100644 index 0000000..0cdb0e0 --- /dev/null +++ b/docs/recommended.md @@ -0,0 +1,27 @@ +# Recommended tools + +SuperCollider is nice but you are likely to want to interface it with the +outside world. +It is nice to be able to send / receive audio signals from other applications +and to record SuperCollider in a DAW or any other audio software you'd like to +use. On this small website, I'll assume that you have some tools ready to use like: + +**A good Digital Audio Workstation (DAW)**: + +- [Reaper](https://reaper.fm): a DAW that is free to try and cheap to buy. It is + very powerful and well done, works cross-platform. It is equivalent if not +better to other commercial DAWs and can cover any need you might have. + +**A good audio routing tool**: + +- [Blackhole](https://existential.audio/blackhole/) (**MacOS**): audio routing tool for + MacOS. It is free and open-source. It creates virtual audio devices that you can use to route audio between applications. +- [Loopback](https://rogueamoeba.com/loopback/) (**MacOS**): a commercial audio routing tool for MacOS. Expensive and powerful. +- [Jack](https://jackaudio.org/) (**Linux** / **Windows**): audio routing tool and audio server. It is free and open-source. It creates virtual audio devices that you can use to route audio between applications. +- [Vb-Audio Voice Meeter](https://vb-audio.com/Voicemeeter/) (**Windows**): a +popular audio routing tool for Windows. Never used, but seems to be very +popular. + +**Some other suggestions**: + +- [VCVRack](https://vcvrack.com): a free and open-source modular synthesizer that can be used as another tool to have fun with audio. It is very powerful and can be used as a standalone application or as a plugin in a DAW. It is cross-platform. diff --git a/docs/routing.md b/docs/routing.md new file mode 100644 index 0000000..4c84f25 --- /dev/null +++ b/docs/routing.md @@ -0,0 +1,29 @@ +# Routing audio + +One of my personal requirements for a _live coding_ system with SuperCollider is +that I want to route audio to other applications. I often use my _live coding_ +system as a way to generate raw materials that go through various audio busses +for post-mixing and live audio effects controlled through MIDI controllers. +During the [setup](recommended.md) phase, I have encouraged you to install an +application that allows the creation of virtual audio busses. That's where it is +finally used. + +The `Boot` pseudo-class is seting up the audio to output to 16 channels. You can +think of it as 8 stereo channels with 2 channels each. If you like quadriphony +or octophony, you can also use 4 or 8 channels at a time. The routing of audio +in the host application is entirely up to you but the gest of it is that you can +now record / post-process the sound in any way you want. + +![](https://livecoding.fr/images/reaper_supercollider_1.png) + +# Sending audio to a bus + +The `.play` method used by JITLib allows you to decide which output bus is going +to be used. All you have to do is to add some argument when calling the method: + +```supercollider +~foo = { SinOsc.ar(200) ! 2 * 0.5 }; +~foo.play(fadeTime: 4, out: 4); +``` + +This code snippet will play a sine wave on bus 5 and 6. Remember that the first bus is 0. diff --git a/docs/sampling.md b/docs/sampling.md new file mode 100644 index 0000000..608a1b2 --- /dev/null +++ b/docs/sampling.md @@ -0,0 +1 @@ +# Sampling diff --git a/docs/server_shortcuts.md b/docs/server_shortcuts.md new file mode 100644 index 0000000..d50abe4 --- /dev/null +++ b/docs/server_shortcuts.md @@ -0,0 +1,24 @@ +# Server shortcuts + +I tend to control the audio server and the interface directly from code without +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**: + +- `Panic()`: shortcut for `CmdPeriod.run`. + +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. diff --git a/docs/widgets.md b/docs/widgets.md new file mode 100644 index 0000000..93f1bc6 --- /dev/null +++ b/docs/widgets.md @@ -0,0 +1,49 @@ +# Oscilloscope and meters + +SuperCollider comes with a default oscilloscope and a default frequency scope. They are accessible through the `s.scope` and `s.freqscope` methods. They are great but for some reason, they are being hidden behind other windows when you switch to another window. I want to see them all the time. I have added a few shortcuts to make that happen: + +- `Scope()`: a scope that always stays on top! +- `FScope()`: a frequency scope that always stay on top! +- `Gui()`: a server GUI window that always stay on top! +- `Meter()`: a server meter window that always stay on top! + +There are other widget windows but I don't use them that much. One that is worth +noting is `s.plotTree` that allows you to see what is currently alive on the +audio server (stuck synths?). + + +## Ndef GUI + +When you live code on SuperCollider, you tend to use a lot of `Ndef`/`Nodeproxy` objects. One feature of `NodeProxy` that is often overlooked is that they can be displayed in a graphical interface. You can monitor them this way. Check the following example: + +```supercollider +( +~test = { + var sequence = Demand.ar( + Impulse.ar(c.dur * 8), + Impulse.ar(c.dur), + Dseq([100, 150, 200, 400, 800], inf)).varlag(c.dur / \woof.kr(12)); + var sig = LPF.ar(Pulse.ar(sequence), LFNoise1.kr(c.dur * 2).range(500, 2000)) ! 2 * 0.5; + JPverb.ar(sig, size: 10, t60: 2) +}; +~test.play(fadeTime: 8); +~test.mold(2); +) + +~test.gui; // Calling a GUI for that specific definition! +~test.gui2; // Modern replacement for the gui method +``` + +The `.gui` method uses the default [NdefGui](https://doc.sccode.org/Classes/NdefGui.html). The `.gui2` method uses Mads Kjeldgaard's [NdefGui2](https://github.com/madskjeldgaard/nodeproxygui2). It is a modern rewrite that fixes some of the issues of the old one. + +Since the `\woof` parameter is declared as a control, it will be available in the GUI! The GUI was created by assuming some random values as the set of default values for the `\woof` control but you can define the default values yourself: + +```supercollider +Spec.add(\woof, ControlSpec(0.01, 4.0, \exp) ); +// Then, re-evaluate the code above +``` + +Now the `\woof` parameter will adhere to the defaults you have set using the +[Spec](https://doc.sccode.org/Classes/Spec.html) class. This is a quick and easy +way to create a GUI when you need one :) +