Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/punksnotdev/INSTRUMENT
afterthought
https://github.com/punksnotdev/INSTRUMENT
Last synced: about 1 month ago
JSON representation
afterthought
- Host: GitHub
- URL: https://github.com/punksnotdev/INSTRUMENT
- Owner: punksnotdev
- Created: 2017-11-29T20:48:06.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2023-09-18T04:34:30.000Z (10 months ago)
- Last Synced: 2024-02-15T01:34:30.200Z (5 months ago)
- Language: SuperCollider
- Size: 2.73 MB
- Stars: 26
- Watchers: 6
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README-es-old.md
Lists
- awesome-livecoding - INSTRUMENT - For live coding music and interfacing musical instruments and controllers in SuperCollider. (Libraries and tools)
- awesome-supercollider - INSTRUMENT - This tool is aimed at the creation of musical compositions from scratch, 'on the fly'. INSTRUMENT focuses on musical language: rhythm, harmony, melody, audio processing (Quarks and extensions / Live coding)
README
# INSTRUMENT
### v0.1.prealpha.0
#### afterthought# IMPORTANT / IMPORTANTE
#### English:
INSTRUMENT is about to be publicly released on April 24th, 2019.Expect turbulence in this repository while this date approaches.
#### Español:
INSTRUMENT está a punto de ser liberado públicamente el 24 de abril, 2019.Espere turbulencia en este repositorio mientras se acerca esa fecha.
Ese día se publicará este documento en español.
# Quick Tutorial
INSTRUMENT es una librería para hacer música con código en vivo, dentro del entorno de SuperCollider.
Ofrece una interfaz de programación (API) para la creación de composiciones desde cero, "al vuelo". INSTRUMENT se enfoca en el lenguaje musical: ritmo, armonía, melodía, procesamiento de audio.
Una de sus motivaciones principales es facilitar la integración con la increíble JITLib, que permite incorporar síntesis mutante en los actos en vivo.
INSTRUMENT también facilita la conexión con dispositivos MIDI, con una interfaz sencilla que facilita su mapeo a diferentes parámetros sonoros.
Su nombe está inspirado por el famoso documental sobre Fugazi, la banda favorita de furenku.
INSTRUMENT es una iniciativa independiente y voluntara operando desde el subterráneo del código en vivo mexicano.
Para preguntas, consultas, conversaciones divertidas, por favor contactarme a [email protected].
## Disclaimers:
- Documentation is still a work in progress... more news soon.
- INSTRUMENT is not officially released yet: the API is subject to change in the near future
before the v.1 release.# Installation:
- Clone the repo or download the .zip file and place it inside your SuperCollider 'Extensions/' folder. Recompile.
- Load SynthDefs by running 'Sounds/load-synths.scd';
- You can check currently existing Synthdefs [here](https://github.com/punksnotdev/INSTRUMENT/tree/master/SuperCollider/Sounds/SynthDefs)Evaluate following code lines or groups one by one:
```SuperCollider
~~// First, boot~~
// Primero, arrancar el servidor
(
~~// useful snippet for increasing default memory~~
// fragmento de código útil para incrementar memoria
s.options.memSize=2048*1024;
s.options.maxNodes=128*1024;
s.boot;)
```
## Synths
Cargar los Synthdefs incluidos
Primero, carguemos los sintetizadores incluidos.
```SuperCollider
i.synths = i.loadSynths(Platform.userExtensionDir++"/INSTRUMENT/Sounds/SynthDefs/*");
```Ver **Cargado Automático de Sintetizadores**, al final de este documento para más información.
## Secuenciado básico:
```SuperCollider
s.volume=(-12)
(
i=INSTRUMENT().play;
i.kick=INSTRUMENT(\kickElectro);
i.kick.seq("1");// disparar sintes con distintos valores de amplitud
i.kick.seq("1 0.1 0.75");// this also works
i.kick.seq([1, 0.1, 0.75]);i.kick.stop;
// Press Ctrl/Cmd + . to stop the server
```
**.seq** method allows to sequence any parameter. In previous example, the default parameter 'trigger' is being automatically passed.
Lets pass a different parameter, *note*.
```SuperCollider
i=INSTRUMENT().play;
i.bass=INSTRUMENT(\tranceBazz);
i.bass.seq(\note, "0 2 3 5");
```
There are shorthands 'seq' methods for some common parameters, some of them:
- trigger
- note
- chord
- vol
- pan
- fx
- fxSet```SuperCollider
(
i=INSTRUMENT().play;i.bass=INSTRUMENT(\tranceBazz);
// play notes
i.bass.note("0 2 3 5");
// make it a bass, please:i.bass.octave=3;
)
## Set tempo
```SuperCollider
i.tempo=180;
i.tempo=140;
i.tempo=120;```
## Add silences
```SuperCollider
i.kick.seq("1 0.5");
// array notation equivalent:
i.kick.seq([1, \r, \r, \r, 0.5]);```
## Change instrument parameters:
```SuperCollider
i.kick.amp=1/2;
i.kick.amp=3/4;
i.kick.amp=1;i.kick.clock=2;
i.bass.clock=4;```
## Repeating events:
```SuperCollider
i.kick.seq("1 0.5xxxx");
i.bass.note("0 2xx 3xxx");```
## Changing steps duration```SuperCollider
// al subsequent events are afected
i.kick.seq("1 :0.25 1xxx ");
i.kick.seq("1 :0.25 1xxx :0.125 1xxx ");```
## Sequencing patterns
```SuperCollider
// Ctrl/Cmd + Period
i=INSTRUMENT().play;
i.kick=INSTRUMENT(\kickElectro);i.kick.clock=2;
i.kick[0].seq("1");
i.kick[1].seq("1xx 1");
i.kick[2].seq("1 1xx 1 ").speed(2);```
## Removing patterns:
```SuperCollider
i.kick.rm(\seq,0);
i.kick.rm(\trigger,1);
i.kick.rm(\trigger,2);```
## Control pattern speeds
```SuperCollider
i.kick[0].seq("1").speed(1);
i.kick[1].seq("1").speed(2);
i.kick[2].seq("1").speed(4);```
## Controlling pattern repetitions
```SuperCollider
i.kick[0].seq("1").speed(1).repeat(4);
// different names for the same function:
i.kick[1].seq("1").speed(2).do(8);
i.kick[2].seq("1").speed(4).x(16);```
## Jump to position
```SuperCollider
(
i = INSTRUMENT().play;
i.hihat=INSTRUMENT(\hihatElectro);
i.hihat.seq("1xx :0.25 1xxx :0.5 1xxx :2 1").speed(2);
)i.hihat.go(0);
i.hihat.go(4);```
## Create a basic beat
```SuperCollider
(
i = INSTRUMENT().play;
i.kick=INSTRUMENT(\kickElectro);
i.hihat=INSTRUMENT(\hihatElectro);
i.clap=INSTRUMENT(\clapElectro);i.kick.seq("1").speed(2);
i.hihat.seq(" 1").speed(4);
i.clap.seq(" 1").speed(2);
)```
## Setting parameters
```SuperCollider
(
i = INSTRUMENT().play;
i.bass=INSTRUMENT(\tranceBazz);
i.bass.note("0 2 3");
)i.bass.set(\rel,2);
i.bass.set(\rel,0.2);
i.bass.set(\gain,0.1);
i.bass.set(\gain,2);```
## Sequencing parameters
```SuperCollider
i.bass.seq(\rel,[2,0.2,1]);
// rests in params:
i.bass.seq(\rel,[2,0.2,\r,\r,1]);```
## Sequencing synthdefs:
```SuperCollider
(
i=INSTRUMENT().play;
i.kick=INSTRUMENT(\kickDeep);
i.kick.seq("1");
i.kick.synthdef([\kickSyn1,\kickSyn2,\kickSyn3]);
)```
## FX (Effects)
```SuperCollider
(
i=INSTRUMENT().play;i.clap=INSTRUMENT(\clapElectro);
// play notes
i.clap.note("0 2 3 5");
// make it a clap, please:i.clap.octave=3;
)
i.clap.fx=\reverb;
i.clap.fxSet(\wet,0);
i.clap.fxSet(\wet,1);
i.clap.fxSet(\wet,3/4);i.clap.fxSet(\room,7/8);
i.clap.fxSet(\damp,7/8);i.clap.fxSet(\room,1/8);
i.clap.fxSet(\damp,1/8);i.clap.fxSet(\room,1);
i.clap.fxSet(\damp,1);i.clap.stop;
i.clap.fx=nil;
i.clap.play;i.clap.fx=\reverb;
```
```
## Sequencing fx parameters
```SuperCollider
(
i = INSTRUMENT().play;i.clap=INSTRUMENT(\clapElectro);
i.clap.seq(" 1 :0.25 1xx").speed(2);i.clap.fx = \reverbLPF;
i.clap.fxSet([
(filterHz:3000),
(filterHz:1000),
(filterHz:2000),
// more than one parameter:
(filterHz:3000,q:0.1),
(filterHz:300,q:0.01),
]).speed(1/2);
)```
## Sequencing fx
```SuperCollider
(
i = INSTRUMENT().play;i.clap=INSTRUMENT(\clapElectro);
i.clap.seq(" 1 :0.25 1xx").speed(2);i.clap.fx([\reverb,\reverbLPF,\delay2]).speed(1/4);
)```
## Grouping INSTRUMENTS
```SuperCollider
(
i = INSTRUMENT().play;i.kick=INSTRUMENT(\kickElectro);
i.hihat=INSTRUMENT(\hihatElectro);
i.clap=INSTRUMENT(\clapElectro);i.kick.seq("1xx :0.25 1xxx ").speed(2);
i.hihat.seq(" 1").speed(4);
i.clap.seq(" 1 :0.25 1xx").speed(2);i.drums=[\kick,\hihat,\clap];
i.drums.clock=1/2;
i.drums.clock=2;
i.drums.clock=1;
i.drums.amp=1/2;
i.drums.amp=1;
)// add fx to group
i.drums.fx = \delay2;
i.drums.fx = nil;```
## Array manipulation
```SuperCollider
(
i = INSTRUMENT().play;
i.bass=INSTRUMENT(\tranceBazz);
i.hihat=INSTRUMENT(\hihatElectro);
)i.bass.note("0 2 3").pyramid.mirror;
// randomness
i.bass.note("0 2 3 5 7 10 12").random;
i.bass.note("0 2 3 5 7 10 12").random;i.hihat.seq("1xxxxxxxxx").speed(8).maybe(0.5); // default value
i.hihat.seq("1xxxxxxxxx").speed(8).maybe(0.25);
i.hihat.seq("1xxxxxxxxx").speed(8).maybe(0.75);```
A small composition:
```SuperCollider
// Ctrl/Cmd + .(
i = INSTRUMENT().play;
i.voices = (
a: INSTRUMENT(\distPad1),
b: INSTRUMENT(\distPad2),
c: INSTRUMENT(\distNote1),
d: INSTRUMENT(\distNote2),);
i.voices.a.note("0 2 0 2 3 0 2 3 7 0 2 3 7 14").speed(1/4);
i.voices.a.amp=1.5;
i.voices.a.set(\rel,8);i.voices.b.note("0 2 0 2 3 0 2 3 7 0 2 3 7 14").speed(1/2).random;
i.voices.b.octave=6;
i.voices.b.amp=1/4;i.voices.c.note("0 2 0 2 3 0 2 3 7 0 2 3 7 14").speed(2).random;
i.voices.c.octave=8;
i.voices.c.amp=1/4;i.voices.d.note("0 2 0 2 3 0 2 3 7 0 2 3 7 14").speed(3).random;
i.voices.d.octave=7;
i.voices.d.amp=1/3;)
```
## Sequencing events:
```SuperCollider
i.every(4,{
i.hihat.seq("1xxxxxxxxx").speed(8).maybe(0.75);
});
```
## Controlling NodeProxies
```SuperCollider
i = INSTRUMENT().play;
p=ProxySpace.push(s);
~sound.play;
~sound = {|notes=#[60,65,67,72],gain=1| (SinOsc.ar(notes.midicps)*gain).tanh / 4 ! 2 };i.notes=INSTRUMENT(~sound);
i.notes.seq(\gain,[3,1,13]).speed(1/2);```
## Chord progressions:
```SuperCollider
// Class 'C' is an alias for 'I8TChord':
// C( interval, chordtype/chordarray, inversion, additional );(
i.notes.chord([
C(0,\m),
C(7,\M,1),
C(3,\Mmaj7),
C(1,\m,0,[16])
]).speed(1/2);)
// remove fx sequence
i.notes.rm(\gain);(
i.notes.chord([
C(0,\m),
C(0,\m,1),
C(0,\m,2),
C(0,\m,2,[14]),
C(7,[6,10,16])
]).speed(1/4);)
// different chord types:
(
i.notes.chord([C(0,\M),
C(0,\m),
C(0,\M7),
C(0,\m7),
C(0,\dim),
C(0,\aug),
C(0,\Mmaj7),
C(0,\mmaj7),
C(0,\M9),
C(0,\M9m),
C(0,\m9),
C(0,\m9m),
C(0,\sus2),
C(0,\sus4),// custom chord type
C(0,[6,10,15]),]).speed(1/2);
)```
## Sequencing different progressions:
```SuperCollider
(
i.notes[0].chord([
C(0,\m),
C(1,\M,0,[16]),
]).speed(1/2).do(2);i.notes[1].chord([
C(0,\m),
C(3,\sus2),
C(2,\dim),
C(7,\M)
]).speed(1/2).do(3);)
## Mixer
(
i=INSTRUMENT().play;i.kick=INSTRUMENT(\kickElectro);
i.hihat=INSTRUMENT(\hihatElectro);
i.snare=INSTRUMENT(\snareElectro);
// play notes
i.kick.seq("1");
i.snare.seq("1").speed(2);
i.hihat.seq("1").speed(3);
// make it a hihat, please:i.hihat.octave=3;
)
// Mixer EQ
i.mixer.getChannel(\kick).set(\low,0);
i.mixer.getChannel(\kick).set(\low,1);
i.mixer.getChannel(\kick).set(\low,0.5);i.mixer.getChannel(\hihat).set(\middle,0);
i.mixer.getChannel(\hihat).set(\middle,1);
i.mixer.getChannel(\hihat).set(\middle,0.5);i.mixer.getChannel(\snare).set(\high,0);
i.mixer.getChannel(\snare).set(\high,1);
i.mixer.getChannel(\snare).set(\high,0.5);// Mixer FX Chain
i.kick.stop;
i.hihat.stop;i.mixer.getChannel(\snare).addFx(\lpf);
i.mixer.getChannel(\snare).addFx(\reverb);i.mixer.getChannel(\snare).fxSet(\reverb,\wet,0);
i.mixer.getChannel(\snare).fxSet(\reverb,\wet,1);
i.mixer.getChannel(\snare).fxSet(\reverb,\wet,1/2);
i.mixer.getChannel(\snare).fxSet(\reverb,\room,0);
i.mixer.getChannel(\snare).fxSet(\reverb,\room,1);
i.mixer.getChannel(\snare).fxSet(\reverb,\damp,1);// check this out:
i.mixer.getChannel(\snare).fxSet(\reverb,\wet,1);
i.mixer.getChannel(\snare).fxSet(\lpf,\q,0.025);
i.mixer.getChannel(\snare).fxSet(\lpf,\filterHz,1900);
i.mixer.getChannel(\snare).fxSet(\lpf,\filterHz,900);
i.mixer.getChannel(\snare).fxSet(\lpf,\filterHz,500);
i.mixer.getChannel(\snare).fxSet(\lpf,\filterHz,300);i.mixer.getChannel(\snare).addFx(\gateDistort)
i.mixer.getChannel(\snare).fxSet(\gateDistort,\gain,3**4)i.mixer.getChannel(\snare).fxSet(\lpf,\filterHz,3000);
i.mixer.getChannel(\snare).removeFx(\gateDistort)
i.snare.stop;
```
## Loopers:
```SuperCollider
i=INSTRUMENT().play;
// create looper connected to audio interface's first audio input:
i.loop1=Looper(0);//
// record looper for the 1st channel:
i.loop1.rec;
i.loop1.start;i.loop1.fx=\reverb;
i.loop1.fxSet(\room,3/4);// replace
i.loop1.rec;
i.loop1.start;i.loop1.stop(2);
i.loop1.rec(1);
i.loop1.start(1);i.loop1.rec(2);
i.loop1.start(2);i.loop1.rec(2);
i.loop1.start(2);i.loop1.amp=0.5;
i.loop1.amp=1;
i.loop1.amp=0;
i.loop1.amp=0.3;
i.loop1.amp=1;// sequence amp
i.loop1.amp("1 0.3 1 0.5 0 0.1")i.loop1.rate = 1/2;
i.loop1.rate = -1;
i.loop1.rate([1, 2, -1, \r, 3, \r , 1/2]).speed(1);// remove rate sequencer:
i.loop1.rm(\rate,0);
i.loop1.rate(1/8);
i.loop1.rate(2.5);// record another layer
i.loop1.rec;
i.loop1.start;// change rate separately for each of the layers:
i.loop1.rate(1,0);
i.loop1.rate(1.5,1);i.loop1.rate(3,0);
i.loop1.rate(1/4,1);i.loop1.rate(4,0);
i.loop1.rate(1/2,0);i.loop1.rate(1/2,1);
i.loop1.rate(1/4,1);// add fx:
i.loop1.fx=\reverb;
i.loop1.fxSet(\wet,1);
i.loop1.fxSet(\rv1,1);
i.loop1.fxSet(\rv2,1);i.loop2.fxSet(\gain,33.3);
i.loop1.fx=\revlpf;
i.loop1.fxSet(\filterHz,200)
i.loop1.fxSet(\filterHz,1200)i.loop1.amp(0.5,0)
i.loop1.amp(0.5,1)i.loop1.fx=nil
i.loop1.amp(0.5);
i.loop1.rate(1);
// create another separate looper:
i.loop2=Looper(0);
i.loop2.rec;
i.loop2.start;
i.loop2.amp=0.5;
i.loop2.rate([1, 2, -1, \r, 3, \r , 1/2]).speed(2);
i.loop2.rm(\rate,0);
i.loop2.amp("1 0.3 1 0.5 0 0.1").speed(4)
i.loop2.rm(\amp,0);
i.loop2.rm(\amp,0);
i.loop2.rate = 1/3;
i.loop2.rate = -1;
i.loop2.rate(1/2);
i.loop2.rate(-3);
i.loop2.rec;
i.loop2.start;
i.loop2.rate(1,0);
i.loop2.rate(4,1);
i.loop2.rate(2/3,1);
i.loop2.rate(5/4,1);
i.loop2.fx=\distortion;
i.loop2.fxSet(\wet,1/2);
i.loop2.amp(0.01);
i.loop2.fxSet(\filterHz,1440);
i.loop2.fx=nil
i.loop2.amp(0.5);
i.loop2.rate(1);// stop loopers:
i.loop1.stop;
i.loop2.stop;```
## MIDI Control:```SuperCollider
//Docs coming soon...
```
## Synthesizers
INSTRUMENT comes with a group of SynthDefs that you can easily add by running 'Sounds/load-synths.scd';
## Cargado Automático de Sintetizadores
**loadFunction** will read any folder and create a dictionary with SynthDefs inside its internal folder structure.
```SuperCollider
i.synths = i.loadSynths(Platform.userExtensionDir++"/INSTRUMENT/Sounds/SynthDefs/*");
// Multiple hierarchies support.
i.synths.percussion.drums == i.synths.drums
i.synths.percussion.drums.kick == i.synths.kick
i.synths.percussion.drums.kick.kickDeep == i.synths.kickDeep// choose one Synthdef at random
i.synths.kick.choose.postln;
i.synths.bass.choose.postln;// a specific SynthDef
i.synths.kick.kickDeep```
## Using your own Synthdefs
You can use your own Synthdefs. You need to have an **out** parameter for signal routing.
Optionally, you can make them add themselves to the server by putting them inside INSTRUMENT's **Sounds/Synthdef** folder
```SuperCollider
Synthdef(\yourSynthdef, {|out=0,amp=1,freq,gate=1|
//... your synthesis code
Out.ar( out, /*...*/ ));}).store;
```
##### Convenient parameters
- **amp** - for setting amplitude manually or via a sequence
- **gate** useful for retriggering and monophonic synths- **note**
- **freq****NOTE:** you can use note or freq interchangeably. When you sequence notes, both parameters are addressed. **note** must be converted to freq using the **.midicps** method.
You can check currently existing Synthdefs [here](https://github.com/punksnotdev/INSTRUMENT/tree/master/SuperCollider/Sounds/SynthDefs)
###### FX Synthdefs
Only requirements are using **inBus**, **outBus**, **wet**, and **amp** params.
See following example:
```SuperCollider
SynthDef(\reverb, {
arg
inBus=0,
outBus=0,
wet=0.5,
room=0.3,
damp=0.3
amp=1;var sig;
var targetRoom, targetDamp, lag=0.3;
var dsp, mix;sig = In.ar(inBus) * 1.25;
dsp = FreeVerb.ar( sig, 1, room, damp );
mix = (sig * (1-wet)) + (dsp * wet);
ReplaceOut.ar( outBus, Pan2.ar( mix * amp.linlin(0,1,0,1.5), 0 ) );
}).store;
```