Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Restructured #2

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
86 changes: 86 additions & 0 deletions Interaction/Input-Sources.org
@@ -0,0 +1,86 @@
#+TITLE: Input Sources

** MIDI
Connect all available MIDI interfaces, post all incoming MIDI messages, and turn it of later.
#+begin_src sclang
MIDIIn.connectAll;
MIDIFunc.trace;
MIDIFunc.trace(false);
#+end_src

Match cc 1, match cc1, chan 1, match cc 1-10, match any noteOn.
#+begin_src sclang
MIDIdef.cc(\test1, {arg ...args; args.postln}, 1);
MIDIdef.cc(\test1, {arg ...args; args.postln}, 1);
MIDIdef.cc(\test2, {arg ...args; args.postln}, 1, 1);
MIDIdef.cc(\test3, {arg ...args; args.postln}, (1..10));
MIDIdef.noteOn(\test4, {arg ...args; args.postln});
#+end_src

Make a cc MIDIdef to do something, and then tell it to learn.
#+begin_src sclang
MIDIdef.cc(\fader1, {|val| Ndef(\choppy).set(\rate, 4 * (val/127))}).learn;
MIDIdef.cc(\fader2, {|val| Ndef(\choppy).set(\pos, val/127)}).learn; //Execute then move the fader.
MIDIdef.cc(\fader3, {|val| Ndef(\choppy).set(\pulseRate, 8 * (val/127))}).learn;
MIDIdef.cc(\button1, {|val| if(val > 0, {Ndef(\choppy).set(\t_trig, 1)})}).learn; // press a button
#+end_src

Load the example soundfile.
#+begin_src sclang
p = Platform.resourceDir +/+ "sounds/a11wlk01.wav";
b = Buffer.read(s, p);

// an Ndef to play it

(
Ndef(\choppy, {|pos = 0, rate = 1, loop = 0, t_trig = 0, pulseRate = 1|
var pb;
pb = PlayBuf.ar(b.numChannels, b, BufRateScale.kr(b) * rate, t_trig, pos * BufSampleRate.kr(b), loop); // pos in seconds
pb * LFPulse.kr(pulseRate).range(0, 1);
}).play;
)
#+end_src

** Open Sound Control (OSC)
For more detailed info: http://opensoundcontrol.org

We'll try an example with a custom OSC interface
#+begin_src sclang
thisProcess.openUDPPort(9000); // listen on port address that you OSC controller sends messages *to*
OSCFunc.trace(hideStatusMsg:true); // post incoming OSC to see what you're getting., ignoring Server status messages
OSCFunc.trace(false); // turn posting off when you don't want the stream of messages

// you'll need to configure your OSC controller to be on the same network, and send to your computer's addr and port

// something to control
(
Ndef(\sin, {|freq = 440, amp = 0|
SinOsc.ar(freq, mul:amp)
}).play;
)
#+end_src

Now a couple of OSCdefs
#+begin_src sclang
(
// this will respond to the top left red knob
OSCdef(\freq, {|msg|
// msg consists of path plus any params, i.e. [oscpath, param1, param2, ...]
Ndef(\sin).set(\freq, msg[1].linexp(0, 1, 20, 20000)); // scale input range of 0-1 to sensible
}, "/slider1"); // the OSC path we'll respond to

// this will respond to the red fader
OSCdef(\amp, {|msg|
Ndef(\sin).set(\amp, msg[1]); // no need to scale as 0-1 is okay here
}, "/slider2"); // the OSC path we'll respond to
)
#+end_src

Cleanup
#+begin_src sclang
(
Ndef(\sin).free;
OSCdef(\freq).free;
OSCdef(\amp).free;
)
#+end_src
168 changes: 168 additions & 0 deletions Interaction/Modality-Examples.org
@@ -0,0 +1,168 @@
#+TITLE: Modality Examples

Modality is a higher level toolkit which makes adding controllers simple through a uniform interface: https://modalityteam.github.io
Installation info: https://github.com/ModalityTeam/Modality-toolkit#installation

** Connect some device
Look for available controllers
#+begin_src sclang
MKtl.find;

//make a new Modality controller object for the korg nanocontrol2
k = MKtl('midi_1_nanoko', "korg-nanokontrol2");

//make a gui for the device:
k.gui;
#+end_src

See all output from the device
#+begin_src sclang
k.trace;
//turn it off
k.trace(false);
#+end_src

See a hierarchical tree of all elements
#+begin_src sclang
k.postElements;
#+end+src

Post the output of the first knob
#+begin_src sclang
k.elAt(\kn, 0).action_({ |el| [el.name, el.value.postcs });
#+end_src

Clear the action
#+begin_src sclang
k.elAt(\kn, 0).resetAction;

Ndef(\harms, { Splay.ar(8.collect({|i| SinOsc.ar(200 * (i + 1), mul: ("amp-" ++ i).asSymbol.kr(0)) }).scramble) }).play;

k.elAt('sl').action = { |...args| Ndef(\harms).set("amp-" ++ args[0].index, args[0].value) };
#+end_src

** HID example using a Nintendo Switch Pro Controller
First we'd need to pair this via bluetooth

This is what the spec looks like for the device (ht Sam Pluta)
#+begin_src sclang
~proswitch = (
name: \procontroller,
idInfo: "Pro Controller_Unknown",

protocol: 'hid',
deviceName: "Nintendo Pro Controller",
deviceType: 'joystick',
elementTypes: [\joystick, \button],
status: (
linux: "unknown",
osx: "Seems to Work - Sam Pluta 05/13/20",
win: "unknown"
),

deviceInfo: (
vendorURI: "https://www.nintendo.com/",
manualURI: "",
longName: "Nintendo Switch Pro",
// description: "",
// features: [],
// notes: "",

hasScribble: false
),

elementsDesc: (
elements: [
(
key: \bt,
shared: ('hidUsagePage': 9, 'elementType': 'button',
'ioType': 'in', 'spec': \hidBut ),
elements: [
(key: '1', 'hidUsage': 1, 'style': (row: 2.5, column: 4)),
(key: '2', 'hidUsage': 2, 'style': (row: 2, column: 4.8)),
(key: '3', 'hidUsage': 3, 'style': (row: 2, column: 3.2)),
(key: '4', 'hidUsage': 4, 'style': (row: 1.5, column: 4)),
(key: '5', 'hidUsage': 5, 'style': (row: 1, column: 0)),
(key: '6', 'hidUsage': 6, 'style': (row: 1, column: 6)),
(key: '7', 'hidUsage': 7, 'style': (row: 0, column: 0)),
(key: '8', 'hidUsage': 8, 'style': (row: 0, column: 6)),
(key: '9', 'hidUsage': 9, 'style': (row: 0, column: 2)),
(key: '10', 'hidUsage': 10, 'style': (row: 0, column: 2.8)),
(key: '11', 'hidUsage': 11, 'style': (row: 3.2, column: 1.2)),
(key: '12', 'hidUsage': 12, 'style': (row: 3.2, column: 5.2)),
(key: '13', 'hidUsage': 13, 'style': (row: 0.8, column: 2.8)),
(key: '14', 'hidUsage': 14, 'style': (row: 0.8, column: 2))
],
),
(
key: \joy,
shared: ('hidUsagePage': 1, 'elementType': 'joyAxis', 'ioType': 'in', 'spec': \cent1),
elements: [
(key: \x1, 'hidUsage': 48, 'style': (row: 4, column: 0.2, height: 1, width: 2)),
(key: \y1, 'hidUsage': 49, spec:[1.0,0.0], 'style': (row: 3, column: 2, height: 2, width: 1)),
(key: \x2, 'hidUsage': 51, 'style': (row: 4, column: 4.2, height: 1, width: 2)),
(key: \y2, 'hidUsage': 52, spec:[1.0,0.0], 'style': (row: 3, column: 6, height: 2, width: 1))
]
),
(key: \arrows,
elements: [(hidUsage: 57, 'hidUsagePage': 1, spec:[0.0,8/7,\lin,1/7], 'ioType': 'in', 'elementType': 'slider', 'style': (row: 5, column: 2.5, height: 1, width: 2))]
)
]
)
);
#+end_src

** Running example
Test this below:

#+begin_src sclang
d = MKtlDesc.fromDict(~proswitch);

m = MKtl(\procontroller, d);

m.gui;

m.elementGroup;
m.postElements;

m.elAt(\joy, 0).action_({|el| el.value.postln })

x = { Splay.ar(RLPF.ar(Saw.ar(\freq.kr(440, 0.1), mul: 0.1), 1000))}.play;


m.elAt(\joy, 0).action_({ |el|
x.set(\freq, el.value.linlin(0.13, 0.86, 300.0, 600));
});

m.resetActions;


x = {
Splay.ar(
RLPF.ar(Saw.ar(\freq.kr(440, 0.1), mul: 0.1),
\ffreq.kr(1000, 0.1),
\rq.kr(0.5, 0.1),
\mul.kr(0.1, 0.1)
)) * Env.asr.kr(gate: \env.kr(0))
}.play;

m.elAt(\joy, 1).action_({ |el|
x.set(\freq, el.value.linlin(0.13, 0.86, 300.0, 600));
});

m.elAt(\joy, 0).action_({ |el|
x.set(\mul, el.value.linlin(0.13, 0.86, 0, 0.6));
});

m.elAt(\joy, 3).action_({ |el|
x.set(\ffreq, el.value.linlin(0.13, 0.86, 500, 2000));
});

m.elAt(\joy, 2).action_({ |el|
x.set(\rq, el.value.linlin(0.13, 0.86, 0.01, 0.2));
});

m.elAt(\bt, 7).action_({ |el|
x.set(\env, el.value.postln);
});
#+end_src
48 changes: 48 additions & 0 deletions Interaction/Other-Inputs.org
@@ -0,0 +1,48 @@
#+TITLE: Other Inputs

** Examples using other Protocols
Notional rather than working examples it's often more convenient to use higher level approaches (e.g. Modality) to these

** HID
https://en.wikipedia.org/wiki/Human_interface_device

#+begin_src sclang
HID.postAvailable; // check which devices are attached
~myhid = HID.open( 1103, 53251 ); // open the Run 'N' Drive game controller, put your own values here.

s.boot; // boot the server

Ndef(\sinewave, { |freq=500, amp=0.1| SinOsc.ar( freq, 0, amp * 0.2 ) } );
Ndef(\sinewave ).play;

HIDdef.usage( \freq, { |value| Ndef( \sinewave ).set(\freq, value.linexp( 0, 1, 500, 5000 ) ); }, \X );
HIDdef.usage( \amp, { |value| Ndef( \sinewave ).set(\amp, value ); }, \Y );
#+end_src
** Serial
*** Arduino read example from the help file
#+begin_src sclang
(
p = SerialPort(
"/dev/tty.usbserial-A800crTT", // edit to match your port. SerialPort.listDevices
baudrate: 9600, // check that baudrate is the same as in arduino sketch
crtscts: true); // use hardware flow control
)

// read 10bit serial data sent from Arduino's Serial.println

(
r= Routine({
var byte, str, res;
99999.do{|i|
if(p.read==10, {
str = "";
while({byte = p.read; byte !=13 }, {
str= str++byte.asAscii;
});
res= str.asInteger;
("read value:"+res).postln;
});
};
}).play;
)
#+end_src