MIDIKeyboard a simple GUI keyboard
This GUI widget is pretty similar to the Keyboard (kslider) object in Max - basically
a tool to play MIDI notes and perhaps map scales, visualise real keyboard, etc.
The MIDIKeyboard does not handle any system-midi (SC has other ways of doing that),
the only "midi" about it is that the keys are numbered according to the MIDI standard.
*new(window, bounds, octaves, startnote);
window - A SCWindow in which the MIDIKeyboard will appear
bounds - The Rect of the MIDIKeyboard
octaves - The number of octaves on the keyboard
startnote - The MIDI note number of the first key (48 is the default - that's C3)
keyDownAction_ - The function that key down will trigger.
keyTrackAction_ - The function that moving the cursor will trigger.
keyUpAction_ - The function that key up will trigger.
showScale([scale], startnote, color) - Takes an array with the scale. Startnote is the fundamental.
playScale([scale], startnote, wait) - Takes an array with the scale. Startnote is the fundamental.
inScale(note) - returns true or false if a note is part of a set scale.
setColor(note, Color) - Set a color of a note (still keeps black/white tint).
removeColor(note) - Remove the color of a specific note.
clear - clears the scale or all colors from the keyboard.
keyDown(note) - colors the selected key grey.
keyUp(note) - resets the selected key.
// choose a gui (see GUI helpfile)
GUI.swing;
GUI.cocoa;
// examples
MIDIKeyboard.new
MIDIKeyboard.new(bounds: Rect(20, 10, 273, 60), octaves: 3)
MIDIKeyboard.new(bounds: Rect(20, 10, 364, 60), octaves: 4)
(
w = GUI.window.new("using the keyboard in a SCWindow", Rect(10, 500, 500, 212)).front;
k = MIDIKeyboard.new(w, Rect(20, 20, 364, 60), 4, 48);
l = MIDIKeyboard.new(w, Rect(20, 110, 455, 60), 5, 48);
)
// posting the MIDI note number and the frequency of the note
(
w = GUI.window.new(" using the midi keyboard", Rect(10, 260, 820, 212)).front;
k = MIDIKeyboard.new(w, Rect(20, 20, 776, 160), 4, 48);
k.keyDownAction_({arg note; [\midinote, note, \freq, note.midicps].postln;});
k.keyTrackAction_({arg note; [\midinote, note, \freq, note.midicps].postln;});
)
// displaying a scale on the keyboard
(
k = MIDIKeyboard.new;
k.keyDownAction_({arg note; "Key down : ".post; note.postln;});
k.keyUpAction_({arg note; "Key up : ".post; note.postln;});
k.keyTrackAction_({arg note; "Key tracking : ".post; note.postln;});
k.showScale([0, 2, 4, 6, 8, 10], 48, Color.new(0.4, 0.6,0.8));
)
k.clear; // clear the scale
k.showScale([0, 1, 3, 6, 7, 8, 10]); // in C
k.showScale([0, 1, 3, 6, 7, 8, 10], 50); // in D
k.inScale(69) // returns true or false depending on the note being in the scale
// play a scale
k.playScale([0, 1, 3, 6, 7, 8, 10], 60);
k.playScale([0, 1, 3, 6, 7, 8, 10], 60, 0.3);
k.keyDown(60) // midinote
k.keyUp(60)
k.keyDown(65)
k.keyUp(65)
// a chord
(
k.clear;
k.keyDown(60);
k.keyDown(64);
k.keyDown(67);
)
k.clear;
// or
k.keyDown([60, 64, 68])
k.keyUp([60, 64, 68])
// a sounding example
(
SynthDef(\midikeyboardsine, {arg freq, amp = 0.25;
Out.ar(0, (SinOsc.ar(freq,0,amp)*EnvGen.ar(Env.perc, doneAction:2)).dup)
}).add;
k = MIDIKeyboard.new;
k.keyDownAction_({arg note; Synth(\midikeyboardsine, [\freq, note.midicps])});
k.keyTrackAction_({arg note; Synth(\midikeyboardsine, [\freq, note.midicps])});
k.showScale([0, 3, 6, 9, 10]);
)
// Displaying incoming MIDI notes
// an example where the MIDIKeyboard shows which notes are played on a MIDI controller
// NOTE: there are many ways of working with MIDI in SC, so this is just one quick example...
(
k = MIDIKeyboard.new;
MIDIIn.connect;
MIDIIn.noteOn_({ arg src, chan, num, vel; {k.keyDown(num)}.defer; });
MIDIIn.noteOff_({ arg src, chan, num, vel; {k.keyUp(num)}.defer; });
)
// Playing (outputting) MIDI notes on midi channel 1
(
k = MIDIKeyboard.new;
MIDIClient.init;
m = MIDIOut(0, MIDIClient.destinations.at(0).uid);
k.keyDownAction_({arg note; m.noteOn(0, note, 60);}); // (midi channel 1, midinote, velocity 60)
k.keyUpAction_({arg note; m.noteOff(0, note, 60);});
)
k.setColor(60, Color.red)
// setting color ranges:
(
var oct;
oct = 4;
k = MIDIKeyboard.new(bounds: Rect(20, 10, 364, 60), octaves: oct);
c = [Color.red, Color.yellow, Color.blue, Color.green];
oct.do({arg j;
12.do({arg i;
k.setColor(48+i+(j*12), c[j]);
});
});
)
k.clear // and clear the keyboard of colors
// chords
(
var chord, chords, chordnames;
var menu, play;
var fString, fundamental=60;
w = GUI.window.new("Common Chords", Rect(10, 260, 820, 252)).front;
k = MIDIKeyboard.new(w, Rect(20, 60, 776, 160), 4, 48);
k.keyDownAction_({arg note; fundamental = note;
fString.string_(note.asString);
k.showScale(chord, fundamental, Color.new255(103, 148, 103));
});
k.keyTrackAction_({arg note; fundamental = note;
fString.string_(note.asString);
k.showScale(chord, fundamental, Color.new255(103, 148, 103));
});
k.keyUpAction_({arg note; fundamental = note;
fString.string_(note.asString);
k.showScale(chord, fundamental, Color.new255(103, 148, 103));
});
GUI.staticText.new(w, Rect(350, 20, 100, 20)).string_("Fundamental :");
fString = GUI.staticText.new(w, Rect(436, 20, 50, 20)).string_(fundamental.asString);
chords = [["Major", [0, 4, 7]], ["Minor", [0, 3, 7]],["5", [0, 7]], ["Dominant 7th", [0, 4, 7, 10]], ["Major 7th", [0, 4, 7, 11]], ["Minor 7th", [0, 3, 7, 10]], ["Minor Major 7th", [0, 3, 7, 11]], ["Sus 4", [0, 5, 7]], ["Sus 2", [0, 2, 7]], ["6", [0, 4, 7, 9]], ["Minor 6", [0, 3, 7, 9]], ["9", [0, 2, 4, 7, 10]], ["Minor 9", [0, 2, 3, 7, 10]], ["Major 9", [0, 2, 4, 7, 11]], ["Minor Major 9", [0, 2, 3, 7, 11]], ["11", [0, 2, 4, 5, 7, 11]], ["Minor 11", [0, 2, 3, 5, 7, 10]], ["Major 11", [0, 2, 4, 5, 7, 11]], ["Minor Major 11", [0, 2, 3, 5, 7, 11]], ["13", [0, 2, 4, 7, 9, 10]], ["Minor 13", [0, 2, 3, 7, 9, 10]], ["Major 13", [0, 2, 4, 7, 9, 11]], ["Minor Major 13", [0, 2, 3, 7, 9, 11]], ["add 9", [0, 2, 4, 7]], ["Minor add 9", [0, 2, 3, 7]], ["6 add 9", [0, 2, 4, 7, 9]], ["Minor 6 add 9", [0, 2, 3, 7, 9]], ["Dominant 7th add 11", [0, 4, 5, 7, 10]], ["Major 7th add 11", [0, 4, 5, 7, 11]], ["Minor 7th add 11", [0, 3, 5, 7, 10]], ["Minor Major 7th add 11", [0, 3, 5, 7, 11]], ["Dominant 7th add 13", [0, 4, 7, 9, 10]], ["Major 7th add 13", [0, 4, 7, 9, 11]], ["Minor 7th add 13", [0, 3, 7, 9, 10]], ["Minor Major 7th add 13", [0, 3, 7, 9, 11]], ["7b5", [0, 4, 6, 10]], ["7#5", [0, 4, 8, 10]], ["7b9", [0, 1, 4, 7, 10]], ["7#9", [0, 3, 4, 7, 10]], ["7#5b9", [0, 1, 4, 8, 10]], ["m7b5", [0, 3, 6, 10]], ["m7#5", [0, 3, 8, 10]], ["m7b9", [0, 1, 3, 7, 10]], ["9#11", [0, 2, 4, 6, 7, 10]], ["9b13", [0, 2, 4, 7, 8, 10]], ["6sus4", [0, 5, 7, 9]], ["7sus4", [0, 5, 7, 10]], ["Major 7th Sus4", [0, 5, 7, 11]], ["9sus4", [0, 2, 5, 7, 10]], ["Major 9 Sus4", [0, 2, 5, 7, 11]]];
chordnames = [];
chords.do({arg item; item[0].postln; chordnames = chordnames.add(item[0])});
chord = chords[0][1];
menu = GUI.popUpMenu.new(w,Rect(500,20,150,20))
.items_(chordnames)
.background_(Color.white)
.action_({arg item;
chord = chords[item.value][1];
k.showScale(chord, fundamental, Color.new255(103, 148, 103));
play.focus;
});
play = GUI.button.new(w,Rect(660,20,60,20))
.states_([["play", Color.black, Color.clear]])
.action_({
Task({
chord.do({arg note;
note = note + fundamental;
Synth(\midikeyboardsine, [\freq, note.midicps]);
0.4.wait;
});
0.6.wait;
chord.do({arg note;
note = note + fundamental;
Synth(\midikeyboardsine, [\freq, note.midicps, \amp, 0.1]);
});
}).start;
});
)