;;;;;;;;;;;;;;;; SCIMP ;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;; an impromptu sc server client library ;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;; (c) ixi audio, 2010 - GPL > google it ;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;; www.ixi-audio.net - thor@ixi-audio.net ;;;;;;;;;;;;;;;;;;;;
;;; note -> works only with Impromptu 2.5 and later :::::::::
;;;;;;;;;;;;;; STARTING THE IMPROMPTU - SC SERVER COMMUNICATION
;; first of all, start SuperCollider and evaluate the SynthDefs at the bottom of this file.
;; it will write those to a folder where the server will read them when booted.
;; then you can do either of these
;; a) boot the localhost server of SuperCollider.app
;; b) Quit SuperCollider and run the SuperCollider Server (scsynth) in a terminal:
;; cd to the location of your server and type
;; ./scsynth -u 57110
(sc:server:start-impromptu-osc) ; starts the impromptu osc server
(sc:server:address "localhost" 57110) ; defines where the sc audio server is
(print *scserver*)
(sc:server:notify 1) ; try to run this twice (server will say "/notify : already registered")
(sc:server:status)
(sys:clear-log-view)
;;;;;;;;;; CREATING SYNTHS
; the Node number is the key. Store that in a variable and control it.
; first mode
(define synth1 (next-node-id))
(sc:synth:new (now) synth1 "scimp_test" 0 0 "freq" 1111)
(sc:synth:set (now) synth1 "freq" (random 211 1888))
(sc:node:trace synth1)
(sc:group:dumpTree 0)
(sc:synth:free (now) synth1)
; second mode - the ID is returned and stored in the variable synth2
(define synth2 (sc:synth:new (now) "scimp_test" 0 0 "freq" 1111))
(sc:synth:set (now) synth2 "freq" (random 211 1888))
(sc:synth:set (now) synth2 "index" (random 211 1888))
(sc:synth:set (now) synth2 "modFreq" (random 11 188))
(sc:synth:free (now) synth2)
; third mode - a grain without a Node ID: The synth has to free itself
(sc:synth:grain (now) "marimba" "freq" (random 333 589) "amp" 1)
(sc:group:freeAll 0)
(sc:server:status)
;;;;;;;;;;;;;;;;; WORKING WITH BUFFERS
; loading sounds into buffers on the server (change path to your own sounds)
; first mode
(define mybuf (sc:synth:read "/Users/thor/Library/Application Support/SuperCollider/sounds/a11wlk01.wav" 0 0 11))
; second mode
(define mybuf2 (next-buffer-num))
(sc:synth:read mybuf2 "/Users/thor/Library/Application Support/SuperCollider/sounds/holeMONO.aif" 0 0 11))
; third mode - directly assigning the buffer to a bufnum
(sc:buffer:allocRead 11 "/Users/thor/Library/Application Support/SuperCollider/sounds/holeMONO.aif" 0 0)
(define bufsynth (sc:synth:new (now) "scimp_buf" 0 0 "bufnum" mybuf "loop" 1))
(sc:node:set (now) bufsynth "rate" (+ (random) 0.5))
(sc:node:set (now) bufsynth "rate" 1)
(sc:synth:free (now) bufsynth)
(sc:synth:grain (now) "scimp_buf" "bufnum" mybuf "rate" 1.2 "loop" 0)
;;;;;;;;;;;;;;;;;;; WORKING WITH NODES
;; example using group
(define synth3 (next-node-id))
(sc:synth:new (now) synth3 "scimp_buf" 0 0 "bufnum" mybuf "loop" 1)
(define delay (next-node-id))
(sc:synth:new (now) delay "scimp_delay" 0 0 "in" 10 "out" 0)
(sc:node:set (now) synth3 "out" 10)
(sc:node:after (now) delay synth3)
(sc:node:set (now) synth3 "out" 0)
(sc:synth:free (now) synth3)
; running on outbus 10 - where the delay above is located
(sc:synth:grain (now) "marimba" "freq" (random 222 999) "amp" 2 "out" 10)
(define synth2 (next-node-id))
(sc:synth:new (now) synth2 "scimp_buf" 0 0 "bufnum" mybuf2 "loop" 1)
(sc:node:set (now) synth2 "out" 10)
(sc:node:set (now) synth2 "out" 0)
(sc:group:freeAll 0)
(sc:server:status)
; setn example
; create a Group on Node 1 under Group 0
(define group 1)
(sc:group:new group 0 0)
;; setting sequence of control values (freq1, freq2, etc. or noise1, noise2, noise3, etc.)
(define setnsynth (sc:synth:new (now) "scimp_nset" 0 group "freq" (random 333 999)))
(sc:node:setn (now) setnsynth '("freq1" 3 533 222 833 "amp1" 3 0.3 0.6 0.2))
(sc:synth:free (now) setnsynth)
;;;;;;;;;;;;;;;;;;; WORKING WITH GROUPS
(define group 1)
(sc:group:new group 0 0)
(define synth1 (sc:synth:new (now) "scimp_test" 0 group "freq" 1111))
(sc:synth:set (now) synth1 "freq" (random 211 1888))
(define synth2 (sc:synth:new (now) "scimp_test" 0 0 "freq" 1111))
(sc:synth:set (now) synth2 "freq" (random 211 1888))
(sc:group:freeAll group) ; group 1
(sc:group:freeAll 0) ; group 1 is in root group 0, so running this will free both synths
(define group2 2)
(sc:group:new group2 0 0)
; here we create 3 synths on the same group
(define synth1 (sc:synth:new (now) "scimp_test" 0 group2 "freq" (random 333 999)))
(sc:synth:set (now) synth1 "index" (random 211 1888))
(sc:synth:set (now) synth1 "modFreq" (random 11 1888))
(define synth2 (sc:synth:new (now) "scimp_test" 0 group2 "freq" (random 333 999)))
(sc:synth:set (now) synth2 "index" (random 211 888))
(sc:synth:set (now) synth2 "modFreq" (random 11 888))
(define synth3 (sc:synth:new (now) "scimp_test" 0 group2 "freq" (random 333 999)))
(sc:synth:set (now) synth3 "index" (random 211 888))
(sc:synth:set (now) synth3 "modFreq" (random 11 888))
; and now we can control the arguments of all synths by passing them to the group
(sc:node:set (now) group2 "modFreq" (random 111 999))
(sc:node:set (now) group2 "index" (random 111 999))
(sc:node:set (now) group2 "freq" (random 111 999))
(sc:server:status)
(sc:group:dumpTree group2) ; prints to console
(sc:group:queryTree group2) ; returns to client
(sc:node:query synth2) ; returns to client
(sc:node:trace synth2) ; prints to console
(sc:synth:get synth2 "freq" "amp" "out") ; get the values of the synth
; controlling the parameters of the FM synths above where the "freq" parameter of the group
; is mapped to a control output of a synth (Like an LFO)
(define controlsynthi (sc:synth:new (now) "scimp_lfo" 0 0 "ctrlbus" 999 "freq" 11))
(sc:node:map group2 "freq" 999) ; we map the frequency to the value of the control bus
(sc:synth:set (now) controlsynthi "freq" (random 1 3))
(sc:synth:set (now) controlsynthi "mul" (random 1 190))
(sc:node:set (now) controlsynthi "freq" (random 2 72) "mul" (random 22 942)) ; setting two args at once
(sc:server:dumpOSC 1)
(sc:group:freeAll group2)
;;;;;;;;;;;;;;;;;;;;; CONTROL BUSSES
;; control bus example
;; now let's try to control the frequency of one synth by another through
;; hooking the input of one oscillator to the output of another using a control bus
(define group3 3)
(sc:group:new group3 0 0)
; the synth we'll control:
(define synth1 (sc:synth:new (now) "scimp_test" 0 group3 "freq" (random 333 999)))
; the control synth (outputting kr values on a bus)
(define controlsynthi (sc:synth:new (now) "scimp_lfo" 0 group3 "ctrlbus" 999 "freq" 11))
(sc:node:map synth1 "freq" 999) ; we map the frequency to the value of the control bus
(sc:node:set (now) controlsynthi "freq" (random 2 72) "mul" (random 22 942)) ; setting two args at once
; and we can also access the FM functions of the scimp_test synth, thus getting a double FM
(sc:synth:set (now) synth1 "index" (random 211 1888))
(sc:synth:set (now) synth1 "modFreq" (random 11 1888))
(sc:group:freeAll group3)
;; another example
(define group 3)
(sc:group:new group 0 0)
(define mycontrolbus 222)
(sc:controlbus:set (now) mycontrolbus 666)
(sc:controlbus:get mycontrolbus) ; we get posted that this value is indeed on the bus
(define synthi (sc:synth:new (now) "scimp_test" 0 group "freq" 1111))
(sc:synth:set (now) synthi "freq" (random 211 1888))
(sc:node:map synthi "freq" mycontrolbus) ; we map the frequency to the value of the control bus
(sc:controlbus:set (now) mycontrolbus (random 222 888)) ; setting a new value on the bus changes the freq
; SynthDef(\scimp_lfo, {arg ctrlbus = 2, freq=4, mul=100;
; Out.kr(ctrlbus, SinOsc.kr(freq, 0, mul: mul, add: 200)); // note the .kr
; }).writeDefFile;
(define controlsynthi (sc:synth:new (now) "scimp_lfo" 0 group "ctrlbus" mycontrolbus "freq" 11))
(sc:node:map synthi "freq" mycontrolbus) ; we map the frequency to the value of the control bus
(sc:synth:set (now) controlsynthi "freq" (random 1 90))
(sc:synth:set (now) controlsynthi "mul" (random 1 90))
(sc:node:set (now) controlsynthi "freq" (random 2 72) "mul" (random 22 942)) ; setting two args at once
(sc:controlbus:get mycontrolbus) ; the controlsynth is now outputting values to the bus
(sc:group:freeAll group)
;;;;;;;;;;;;;;;;;;; PLAY
(sys:clear-log-view)
(sc:synth:grain (now) "marimba" "freq" (random 333 589) "amp" 1)
(dotimes (i 12)
(sc:synth:grain (+ (now) (* i 7500)) "marimba" "freq" (random 333 589) "amp" 1))
(dotimes (i 24)
(sc:synth:grain (+ (now) (* i 5000)) "marimba" "freq" (ixi:mtof (+ 60 i)) "amp" 0.1))
(
(define group 2)
(sc:group:new group 0 0)
(define synth2 (sc:synth:new (now) "scimp_test" 0 group "freq" 1111)))
(dotimes (i 33)
(sc:synth:set (+ (now) (* (+ 1 i) 5000)) synth2 "freq" (random 211 1888))
(sc:synth:set (+ (now) (* (+ 1 i) 5500)) synth2 "index" (random 211 1888))
(sc:synth:set (+ (now) (* (+ 1 i) 5500)) synth2 "modFreq" (random 11 188)))
(sc:group:freeAll 0)
(sc:synth:free (now) synth2)
(define foo
(lambda (out)
(sc:synth:grain (now) "marimba" "freq" (random 333 589) "amp" 1 "out" out)
(callback (+ (now) (random '(2500 5000 10000 15000))) 'foo out)))
(foo 0)
(define foo '())
;; similar to the above but now this will be routed through a delay
(define foo
(lambda (out)
(sc:synth:grain (now) "marimba" "freq" (random 333 589) "amp" 1 "out" out)
(callback (+ (now) (random '(10000 15000))) 'foo out)))
(define delayplay
(lambda ()
(define delay (next-node-id))
(sc:synth:new (now) delay "scimp_delay" 0 0 "in" 10 "out" 0)
(foo 10)))
(delayplay)
(define foo '())
(define melody '((60 1) (66 1/4) (63 1/2) (63 1/2) (66 1/4) (57 1/2)))
(define foo
(lambda (melo)
(let loop ((mel melo))
(print (car mel))
(sc:synth:grain (now) "marimba" "freq" (ixi:mtof (car (car mel))) "amp" 1)
(callback (+ (now) (* *second* (cadar mel))) loop (if (= 1 (length mel)) melody (cdr mel))))))
(foo melody)
(define melody '((60 1) (60 1) (60 1/2) (62 1/2) (64 1) (64 1/2) (62 1/2) (64 1/2) (65 1/2) (67 1)(72 1/2) (72 1/2) (67 1/2) (67 1/2) (64 1/2) (64 1/2) (60 1/2) (60 1/2) (67 1/2) (65 1/2) (64 1/2) (62 1/2) (60 2)))
(define melody '())
(sc:server:dumpOSC 1)
;;;;;;;;;;;;;;;;;; SC SYNTHDEFS
;; open SuperCollider, paste in the below and evaluate (SHIFT+RETURN)
SynthDef(\scimp_buf, { arg out = 0, bufnum, rate=1, loop=0;
Out.ar( out,
PlayBuf.ar(1, bufnum, rate, loop:loop)!2
)
}).writeDefFile;
SynthDef(\marimba, {arg out=0, amp=0.3, t_trig=1, sustain=0.5, gate=1, freq=100, rq=0.006;
var env, signal;
var rho, theta, b1, b2;
env = EnvGen.kr(Env.perc, gate, doneAction:2);
b1 = 1.987 * 0.9889999999 * cos(0.09);
b2 = 0.998057.neg;
signal = SOS.ar(K2A.ar(t_trig), 0.3, 0.0, 0.0, b1, b2);
signal = RHPF.ar(signal*0.8, freq, rq) + DelayC.ar(RHPF.ar(signal*0.9, freq*0.99999, rq*0.999), 0.02, 0.01223);
signal = Decay2.ar(signal, 0.4, 0.3, signal);
Out.ar(out, (signal*env)*(amp*0.65)!2);
}).writeDefFile;
SynthDef(\scimp_delay, { arg in=0, out = 0;
var signal;
signal = In.ar(in, 2);
signal = signal + AllpassC.ar(signal, 3, 0.5, 2 );
Out.ar( out, signal)
}).writeDefFile;
SynthDef(\scimp_test, {arg freq=440, modFreq=1, index=1, out=0, pan=0, amp=0.5;
var signal;
signal = SinOsc.ar(freq + SinOsc.ar(modFreq, 0, index), (2*pi).rand, amp);
Out.ar(out, Pan2.ar(signal, pan));
}).writeDefFile;
SynthDef(\scimp_nset, { arg freq1 = 440, freq2 = 440, freq3 = 440, amp1 = 0.05, amp2 = 0.05, amp3 = 0.05;
Out.ar(0, Mix(SinOsc.ar([freq1, freq2, freq3], 0, [amp1, amp2, amp3])));
}).writeDefFile;
SynthDef(\scimp_lfo, {arg ctrlbus = 2, freq=4, mul=100;
Out.kr(ctrlbus, SinOsc.kr(freq, 0, mul: mul, add: 200)); // note the .kr
}).writeDefFile;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;