====== Directions ======
Use the ''jmg/supercollider'' folk branch until it's merged into main.
* ''git checkout jmg/supercollider''
Install ''supercollider'', the alsa utilities, ''ghc'', and ''tcl-udp'' through apt.
* ''sudo apt install supercollider alsa-utils tcl-udp ghc''
Add yourself to the audio group and reboot.
* ''sudo usermod --group --append audio folk''
* ''reboot''
Configure jack to use your audio device in ''folk/virtual-programs/music.folk''. Ignore the tidal error for now (TODO: handle this more gracefully).
* This is a bit more involved.
* Run this command:
* aplay -L | grep -E 'hw:CARD=.*,DEV=0' | sed -n 's/^\(hw:CARD=.*,DEV=0\).*$/\1/p'
* Or, manually:
* Start by running ''aplay -L''.
* You'll get a huge list of audio device. Try and find one that says something about HD-Audio, being generic, and being analog. You'll want the string that looks like ''hw:CARD=Generic_1,DEV=0'' and starts with ''hw''.
* Now, go to ''virtual-programs/music.folk'' and look for the big block of if-elseif checks, and add your own instance
* Add a section that looks like this:
*
[... top of ifs]
} elseif {$::thisNode eq "folk-" } {
exec jack_control dps device hw:CARD=Generic_1,DEV=0
exec jack_control dps period 256
}
[... rest of ifs]
* Install the SuperDirt library by running echo 'include("SuperDirt");' | QT_QPA_PLATFORM=offscreen sclang
* It should be set up!
Starting code to make audio:
Wish Supercollider plays sound foo {
Pan2.ar(SinOsc.ar(440) * 0.5, 0.0); // This is Supercollider synth code
}
Code to play a note when it is wished for:
set noteSemitones [dict create A 0 B 2 C 3 D 5 E 7 F 8 G 10]
set accidentalSemitones [dict create "#" 1 b -1 "" 0]
When /player/ wishes to play note /note/ {
regexp {^([A-Ga-g])([0-9]?)([#b]?)$} $note -> note octave accidental
set noteSt [dict get $noteSemitones $note]
set modSt [dict get $accidentalSemitones $accidental]
set st [expr { $noteSt + $modSt }]
set noteFreq [expr { 440.0 * (2.0 ** (($octave == "" ? 0 : ($octave - 4)) + $st / 12.0)) }]
set soundName note-$player-$note
Wish Supercollider sound $soundName attr freq is $noteFreq
Wish Supercollider plays sound $soundName {
arg freq = 440.0;
var envgen;
envgen = EnvGen.kr(Env.adsr(sustainLevel: 0.1));
Pan2.ar(Saw.ar(freq) * 0.5 * envgen, 0.0);
}
When the clock time is /t/ {
When /nobody/ claims $soundName has start time /startTime/ {
Hold $soundName { Claim $soundName has start time $t }
}
When $player has region /r/ & $soundName has start time /startTime/ {
# set radius [expr { max([region width $r], [region height $r])/2 + 10 }]
set radius [expr { ($t - $startTime) * 500 }]
Wish $player draws a circle with radius $radius color red
}
}
On unmatch { Hold $soundName { } }
}
===== Troubleshooting =====
May need to kill/restart ''jackdbus'' randomly.
For testing, try running the Supercollider interpreter separately with ''QT_QPA_PLATFORM=offscreen sclang''.
If you just can't get it working you can run Supercollider as a server on a separate device and connect.
* To do that, start by installing Supercollider on your host device of choice, and write down its IP.
* Now, run the server side using this code:
*
s.options.protocol = \tcp; // set to use tcp
s.options.bindAddress = "0.0.0.0"; // allow connections from any address
s.options.maxLogins = 2; // set to correct number of clients
s.boot();
* Moving back to the folk side, you'll have to edit ''music.folk''
* There will be a block labelled ''after 500'', put this in there where it says ''::Music::scExec {'' before the rest of that block.
*
o = ServerOptions.new;
o.protocol_(\tcp);
t = Server.remote(\remote, NetAddr("Host IP Address", 57110), o); // set to correct address and port
t.addr.connect;
t.startAliveThread( 0 );
t.doWhenBooted({ "remote tcp server started".postln; t.notify; t.initTree });
Server.default = t;
s = t;
TODO: add audio debugging page that can be printed?