// groups, busses and the order of execution

(
SynthDef("saw", { arg out=0, freq=100, amp=0.3;
	var sig;
	sig = Saw.ar(freq, amp);
	Out.ar(out, sig);
}).store;

SynthDef("noise", { arg out=0, amp=0.3;
	var sig;
	sig = Crackle.ar(1.99, mul: amp);
	Out.ar(out, sig);
}).store;

SynthDef("reson", { arg in=0, out=0;
	var sig;
	sig = In.ar(in);
	sig = Resonz.ar(sig, LFNoise2.kr(2.6).range(100, 1000), 0.2, 5);
	ReplaceOut.ar(out, sig);	
}).store;

SynthDef("chop", { arg in=0, out=0;
	var sig;
	sig = In.ar(in);
	sig = LFPulse.ar(5, mul: sig);
	ReplaceOut.ar(out, sig);	
}).store;
)

~saw = Synth("saw");

// new nodes get placed before the others (by default):
~res = Synth("reson")

// but a node can be moved somewhere else:
~res.moveAfter(~saw)

s.queryAllNodes

// nodes can be un/muted:
~res.run(false)
~res.run(true)

~saw.free;  ~res.free;

// this node reads from bus 1 and (over)writes to bus 0:
~chop = Synth("chop", [\in, 1, \out, 0])

// this writes to bus 1:
~noise = Synth("noise", [\out, 1])
~chop.set(\out, 1)
~chop.set(\out, 0)

// create this node in the right position:
~res = Synth.after(~chop, "reson")
// and set its busses:
~res.set(\in, 1, \out, 1)

~src = Group(s);
~fx = Group.after(~src);

~saw = Synth("saw", [\out, 1], ~src);
~noise = Synth("noise", target: ~src);

~chop = Synth("chop", [\in, 1, \out, 1], ~fx)
~res = Synth("reson", target: ~fx)

~fx.run(false)
~fx.run(true)

~fx.moveBefore(~src)
~src.moveBefore(~fx)

~saw = Synth("saw", [\out, 15]);
~res = Synth("reson", [\in, 15])
~res.moveAfter(~saw)

ReplaceOut, Out, OffsetOut, XOut

// GUI

GUI.cocoa;
GUI.swing;

(
var w, bt, sl1, sl2, sl3;
var synth;

SynthDef("irgendwas", { arg freq=100, amp=0.1, lfo=7;
	var sig, mod;
	
	freq = freq.clip(10, 10000);
	mod = LFSaw.ar(lfo * -1.0).exprange(0.01, 1);
	sig = Pulse.ar(freq * [0.99, 1.01], 0.5, amp * mod);
	sig = RLPF.ar(sig, Amplitude.ar(sig, 0.002, 0.01).exprange(freq*1, freq*17), 0.1);
	Out.ar(0, sig);
}, [0.1, 0.1, 0.1]).store;

// GUI.window -> SCWindow  (JSCWindow)
w = GUI.window.new( "testwindow", Rect( 200, 400, 340, 360 ));
//w.alpha = 0.3;
// w.alpha_(0.3)
//SCWindow			JSCWindow
//SCStaticText
//SCSlider

// GUI.staticText -> SCStaticText
t = GUI.staticText.new(w, Rect(20, 20, 200, 20));
t.string_("pitch"); // t.string = "pitch";

// GUI.slider -> SCSlider
sl1 = GUI.slider.new(w, Rect(10, 40, 200, 20))
	.action_( { arg view;
		synth.set(\freq, view.value.linlin(0, 1, 48, 72).midicps);
		//w.view.background = Color.gray(view.value);
	} );

GUI.staticText.new(w, Rect(20, 70, 200, 20)).string_("lfo");

sl2 = GUI.slider.new(w, Rect(10, 90, 200, 20));
sl2.action_({ arg view;
	synth.set(\lfo, view.value.linexp(0,1,0.1, 30)); // ControlSpec
	});

GUI.staticText.new(w, Rect(20, 120, 200, 20)).string_("amp");

sl3 = GUI.slider.new(w, Rect(10, 140, 200, 20));
sl3.action = { arg view;
	synth.set(\amp, (view.value * 60 - 60).dbamp);
	};

bt = GUI.button.new(w, Rect(80, 200, 100, 30));
bt.font = GUI.font.new("Arial", 22);
bt.states = [ ["mute", Color.red(0.7), Color.black], ["muted", Color.black, Color.red], ["blabla", Color.green, Color.yellow] ];
bt.action = { arg view;
	synth.run( [true, false].wrapAt(view.value) );
	};

w.front;
w.onClose = { synth.free };

{ synth = Synth("irgendwas") }.defer(1.0);
//synth = Synth("default");

)

Quark

// --------------- MIDI Input

// MIDIClient.init

// MIDIIn.connect

// initialize and connect the first 8 MIDI IN ports
(
var ins;
MIDIClient.init(8,8);	
ins = MIDIClient.sources.size;	
ins.do({ arg i;  MIDIIn.connect(i, MIDIClient.sources.at(i)) });
)

Wouter Snoei  wslib

// a function that responds to any MIDI ControlChange message:
MIDIIn.control = { arg src, chan, num, val; [chan, num, val].postln };

// a function that responds to any NoteOn message:
MIDIIn.noteOn = { arg src, chan, num, vel; ["NoteOn:" , chan, num, vel].postln };

// a function that responds to any NoteOff message:
MIDIIn.noteOff = { arg src, chan, num, vel; ["NoteOff:", chan, num, vel].postln };

// a ControlChange example:

(
SynthDef("testmidi", { arg freq=400, rf=800, amp=0.2;
	var sig, filt;
	sig = Saw.ar(freq*[0.997, 1.004], amp);
	filt = RLPF.ar(sig, rf, 0.1);
	Out.ar(0, filt);
	}, [0.1, 0.1, 0.1]).send(s);
)	

y = Synth.new("testmidi");
//y.set(\amp, 0.01);
//y.free

( // controller number 101 controls the freq of the synth:
MIDIIn.control = { arg src, chan, num, val; 
	[chan, num, val].postln; 
	if (chan == 2) {
		if(num == 1) { y.set(\freq, val.linexp(0, 127, 100, 1000) ) }; 
	}	
	};
)	

y.free

y = Synth.new("testmidi");

( // different controllers for different parameters of this synth:
MIDIIn.control = { arg src, chan, num, val; 
	[chan, num, val].postln; 
	switch ( num )
		{ 1 }  { y.set(\freq, (val / 127 * 80).midicps ) } 
		{ 2 }  { y.set(\rf, val / 127 * 2000 + 100 ) } 
		{ 3 }  { y.set(\amp, (val * 0.5 - 60).dbamp  ) } 
	//	{ 71 } 	 { if (val >= 64 ) { y = Synth.new("testmidi"); } { y.free	}	} ;
	}	
)	

MIDIIn.noteOn = { arg src, chan, num, vel; y = Synth("testmidi") };

if ( test ) 
	{ // then
	} 
	{ // else
		if (test2)

// an alternative way using MIDI responders:

// MIDIResponder

~ccfr = CCResponder({ arg src, chan, num, val;  y.set(\freq, (val / 127 * 80).midicps ) }, nil, nil, 1, nil);

~ccrf = CCResponder({ arg src, chan, num, val;  y.set(\rf, val / 127 * 2000 + 100 ) }, nil, nil, 2, nil)

~ccamp = CCResponder({ arg src, chan, num, val;  y.set(\amp, (val * 0.5 - 60).dbamp ) }, nil, nil, 3, nil)

~ccmute = CCResponder({ arg src, chan, num, val;  y.run( val >= 64 ) }, nil, nil, 71, nil)

CCResponder.removeAll

MIDI

KeyState

(
var w, bt, sl1, sl2, sl3;
var synth;

SynthDef("irgendwas", { arg freq=100, amp=0.1, lfo=7;
	var sig, mod;
	
	freq = freq.clip(10, 10000);
	mod = LFSaw.ar(lfo * -1.0).exprange(0.01, 1);
	sig = Pulse.ar(freq * [0.99, 1.01], 0.5, amp * mod);
	sig = RLPF.ar(sig, Amplitude.ar(sig, 0.002, 0.01).exprange(freq*1, freq*17), 0.1);
	Out.ar(0, sig);
}, [0.1, 0.1, 0.1]).store;

// GUI.window -> SCWindow  (JSCWindow)
w = GUI.window.new( "testwindow", Rect( 200, 400, 340, 360 ));
//w.alpha = 0.3;
// w.alpha_(0.3)
//SCWindow			JSCWindow
//SCStaticText
//SCSlider

// GUI.staticText -> SCStaticText
t = GUI.staticText.new(w, Rect(20, 20, 200, 20));
t.string_("pitch"); // t.string = "pitch";

// GUI.slider -> SCSlider
sl1 = GUI.slider.new(w, Rect(10, 40, 200, 20))
	.action_( { arg view;
		synth.set(\freq, view.value.linlin(0, 1, 48, 72).midicps);
		//w.view.background = Color.gray(view.value);
	} );

GUI.staticText.new(w, Rect(20, 70, 200, 20)).string_("lfo");

sl2 = GUI.slider.new(w, Rect(10, 90, 200, 20));
sl2.action_({ arg view;
	synth.set(\lfo, view.value.linexp(0,1,0.1, 30)); // ControlSpec
	});

GUI.staticText.new(w, Rect(20, 120, 200, 20)).string_("amp");

sl3 = GUI.slider.new(w, Rect(10, 140, 200, 20));
sl3.action = { arg view;
	synth.set(\amp, (view.value * 60 - 60).dbamp);
	};

bt = GUI.button.new(w, Rect(80, 200, 100, 30));
bt.font = GUI.font.new("Arial", 22);
bt.states = [ ["mute", Color.red(0.7), Color.black], ["muted", Color.black, Color.red], ["blabla", Color.green, Color.yellow] ];
bt.action = { arg view;
	synth.run( [true, false].wrapAt(view.value) );
	};

w.front;
w.onClose = { synth.free };

~ccfr = CCResponder({ arg src, chan, num, val;  { sl1.valueAction = val/127 }.defer }, nil, nil, 1, nil);

{ synth = Synth("irgendwas") }.defer(1.0);
//synth = Synth("default");

)

MIDIClient.init(8,8);

 m = MIDIOut(0, MIDIClient.destinations.at(0).uid);
//m = MIDIOut.newByName("SimpleSynth virtual input", "SimpleSynth virtual input")

m.noteOn(0, 67, 127);
m.noteOn(0, 67, 00);
m.allNotesOff(0)

(
e = Pbind(
	\type, \midi,
	\midiout, m,
	\tempo, 130 * 1/60/4,
	\dur, Pfunc({ coin(0.9).if(1/16, 1/2) }),
	\midinote, Pxrand( (40, 45 .. 75), inf),
	\bend, 64,
	\legato, 1.0,
	\amp, 0.7
	).play;
)

e.stop;

( // strumming (try any guitar sound):
e = Pbind(
	\type, \midi,
	\midiout, m,
	\tempo, 130 * 1/60/4,
	\dur, 1.0,
	\strum, 0.1,
	\midinote, Pseq( [[ 40, 45, 50, 55, 59, 64]], inf),
	\bend, 64,
	\legato, 0.9,
	\amp, 0.7
	).play;
)

e.stop;

[0, 2, 2, 1, 2, 2, 1].integrate

(
var chords, chordpattern, basic, dict;

chords = [[0,5,5,5,4,5].integrate+45, [0,5,5,4,5,5].integrate+44, 
		[0,5,4,5,5,5].integrate+43, [0,4,5,5,5,5].integrate+42, [0,5,5,5,5,4].integrate+41   ];
chordpattern = Pwalk( chords.collect {arg c; Pseq([c, c.reverse], 1)}, 1, 1).asStream;

basic = Pbind(	
	\type, \midi,
	\midiout, m,
	\tempo, 130 * 1/60/4,
	\bend, 64,
	\amp, 0.7
);

dict = (
	s: Pbindf(basic, 
		[\dur, \strum], Prand( [ Pseq([ [0.1,0.015], [1, 0.015]], 1),  Pseq([ [1.2 ,0.05]], 1) ], inf), 
		\legato, 0.2, 
		\midinote, Pfin(2, Pfunc({ chordpattern.next + 5 }))
		),
	b: Paddp(\midinote, Pbrown(0,5,3,1), 
		Pbindf(basic, 
		\dur, Pfunc({ coin(0.95).if(1/16, 1/2) }), 
		\midinote, Pn(Pxrand( (40, 45 .. 70) ++ (44, 48 .. 70), 3 ), {rrand(2,7)}) )
		),	
	c: Pbindf(basic, 
		\dur, 1/20, 
		\legato, 0.1, 
		\amp, Pseq([0.8, Pn(0.4, {rrand(2,7)})], inf), 
		\midinote, Pstutter(Prand([1,2,3,5,7],3), Pbrown( 70, 82, 3, 3)) )
	);

x = Pdict(dict, 
		Pxrand([\s, \b, \c], inf)
	).play;
)

// ----------------- HID ------------

GeneralHID.scheme

// (OSX -> MXHID -> HIDDeviceService )

// initializing the device list:
GeneralHID.buildDeviceList;

// what do we have:
GeneralHID.postDevices
GeneralHID.postDevicesAndProperties

// open a device:
a = GeneralHID.open( GeneralHID.deviceList[0] )   // get a GeneralHIDDevice from the list

a.info; 		// ( product, 0, vendorID, productID, version )
a.caps;		// display the capabilities of the device	

a.slots.dump  // slots are the interface elements of the device
a.slots.do { arg sl;  sl.postln }

// start listening
GeneralHID.startEventLoop

// See if data is coming in:
a.debug_( true );   // [ slot.type, slot.code, slot.value ]

// Stop it:
a.debug_( false );

// applying an action to an element:
a.slots[1][1].action = { arg v; if(v.value > 0) { "button1 on".postln } { "button1 off".postln }    }

// using the elements to control synth arguments:
y = Synth("default").run(false);
// button 1 on the gamepad controls the run state of synth y:
a.slots[1][1].action = { arg v; if(v.value > 0) { y.run(true) } { y.run(false) }    }
// left joystick (y-axis) controls the freq of synth y:
a.slots[3][49].action = { arg v; y.set(\freq, v.value.linlin(0,1,200, 2000))    }

// stop the event loop:
GeneralHID.stopEventLoop
a.close;

/*  
device = GeneralHID.open( ..)
set device slot actions
GeneralHID.startEventLoop

GeneralHID.stopEventLoop
remove actions
device.close

*/