Skip to content

Instantly share code, notes, and snippets.

@shimpe
Created March 27, 2020 17:14
Show Gist options
  • Save shimpe/6bc0bfb297be6f38bfe8a87c33be5050 to your computer and use it in GitHub Desktop.
Save shimpe/6bc0bfb297be6f38bfe8a87c33be5050 to your computer and use it in GitHub Desktop.
code for piday project
(
s.waitForBoot({
var deg_to_bass = (
1: "c3",
2: "d3",
3: "e3",
4: "f3",
5: "g3",
6: "a3",
7: "b3",
8: "c3",
9: "d3",
0: "e3"
);
var w = Window("MeloPi", Rect(0,0,1000,200));
var cstCHORDMODE = 0;
var cstSEQMODE = 1;
var cstSTRUM = 0.0;
var notes = StaticText();
var screenlayout = VLayout();
var tempo_lbl = StaticText().string_("Tempo");
var tempo_edit = TextField().action_({|field|TempoClock.default.tempo_(field.value.asString.asFloat/60.0)});
var basedur_lbl = StaticText().string_("Base duration (beats)");
var basedur_edit = TextField().string_("1").action_{|field|
~base_dur = field.value.asString.asFloat;
if (~base_dur == 0) {
~base_dur = 1;
};
};
var gen_amp_lbl = StaticText().string_("Generated amplitude (0.0-1.0)");
var gen_amp_edit = TextField().action_({|field| ~gen_amp = field.value.asString.asFloat.debug; });
var autoadvance_cbx = CheckBox().string_("Auto Advance Interval (seconds)").value_(false).action_({
| checked |
if (checked.value == false) {
~autoadvance_active = 0;
} {
~autoadvance_active = 1;
~autoadvance_interval = 4*60.0/tempo_edit.value.asString.asFloat;
};
});
var temporow = HLayout(tempo_lbl, tempo_edit, basedur_lbl, basedur_edit, nil);
var advancerow = HLayout(autoadvance_cbx, /*autoadvance_edit,*/ gen_amp_lbl, gen_amp_edit, nil);
var first_pi_lbl = StaticText().string_("31415");
var pi_digit = TextField(w, Rect(10, 10, 20, 20)).string_("9");
var second_pi_lbl = StaticText().string_("265");
var pirow = HLayout(nil, nil, nil, first_pi_lbl, pi_digit, second_pi_lbl, nil, nil, nil);
var mode_btn = Button().states_([
["chord mode", Color.blue, Color.grey(0.9)],
["sequence mode", Color.blue, Color.grey(0.9)],
]).action_({ |button|
~music_mode = button.value;
on_new_digit.(pi_digit.value.asString.asInteger);
});
var voicelead = {
|from_chord_midi, to_chord_midi |
var resulting_chord = [];
var new_second_chord = [];
to_chord_midi.do({
|secondmidi |
var distances = ();
var extended_notes_second_chord = [secondmidi, secondmidi-12, secondmidi+12];
var new_second_note = 0;
var candidate_new_second_notes = Dictionary.new();
var best_new_second_note;
from_chord_midi.do({
| firstmidi |
var d = (extended_notes_second_chord - firstmidi).abs;
var copyd = d.deepCopy();
var min_dist = copyd.sort.first;
var idx_of_min = d.indexOf(min_dist);
candidate_new_second_notes[min_dist] = extended_notes_second_chord[idx_of_min];
});
best_new_second_note = candidate_new_second_notes.asSortedArray.first[1];
new_second_chord = new_second_chord.add(best_new_second_note);
});
new_second_chord
};
var play = {
| newpattern |
if (~player.notNil) {
~player.stop;
};
~player = newpattern.play;
};
var lookup_bass = { | digit |
if (digit.isRest) {
Rest();
} {
TheoryNote(deg_to_bass[digit]).asMidi;
};
};
var digit_to_dir = {
| digit |
if (digit == 0) {
~base_dur;
} {
~base_dur/digit;
};
};
var on_oneshot_digit = { | digit |
if (~music_mode == cstCHORDMODE) {
var notes = ~current_chord.deepCopy;
var durdigit = digit ?? 1;
var rhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pfin(digit, Pseq([notes], inf)),
\dur, ~base_dur,
\strum, cstSTRUM,
\legato, 0.99,
\amp, Pseq([~gen_amp],inf),
);
var lhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pseq([lookup_bass.(digit)], digit*digit),
\dur, digit_to_dir.(digit),
\legato, 1.0,
\amp, Pseq([~gen_amp],inf)
);
play.(Ppar([rhs, lhs]));
} /*else*/ {
var notes = ~current_chord.deepCopy;
var rhs;
var lhs;
if (seqrange.value == 1) {
notes = ~current_chord ++ (~current_chord + 12);
};
if (seqrange.value == 2) {
notes = (~current_chord - 12) ++ ~current_chord ++ (~current_chord + 12);
};
if (seqtype.value == 1) {
notes = notes.reverse;
};
if (seqtype.value == 2) {
notes = notes ++ notes.reverse;
};
if (seqtype.value == 3) {
notes = notes.scramble;
};
rhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pfin(digit, Pseq(notes, inf)),
\dur, ~base_dur,
\legato, 0.99,
\mykey, Pseq(digits),
\amp, Pseq([~gen_amp],inf)
);
lhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pseq([lookup_bass.(digit)], digit*digit),
\dur, digit_to_dir.(digit),
\legato, 1.0,
\amp, Pseq([~gen_amp],inf)
);
play.(Ppar([rhs, lhs]));
};
};
var on_new_digit = { | digit |
var new_chord = deg_to_chord[digit].split($ ).collect({|el| TheoryNote(el).asMidi; });
~current_chord = voicelead.(~current_chord, new_chord);
notes.string_(~current_chord.asString);
if (~music_mode == cstCHORDMODE) {
var notes = ~current_chord.deepCopy;
var rhs, lhs;
if (play_btn.value == 1) { notes = Rest(); digit = Rest(); };
rhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pseq([notes], inf),
\dur, ~base_dur,
\legato, 0.99,
\amp, Pseq([~gen_amp],inf),
\strum, cstSTRUM,
);
lhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pseq([lookup_bass.(digit)], inf),
\dur, digit_to_dir.(digit),
\legato, 1.0,
\amp, Pseq([~gen_amp],inf)
);
play.(Ppar([rhs, lhs]));
} /*else*/ {
var notes = ~current_chord.deepCopy;
var lhs, rhs;
if (seqrange.value == 1) {
notes = ~current_chord ++ (~current_chord + 12);
};
if (seqrange.value == 2) {
notes = (~current_chord - 12) ++ ~current_chord ++ (~current_chord + 12);
};
if (seqtype.value == 1) {
notes = notes.reverse;
};
if (seqtype.value == 2) {
notes = notes ++ notes.reverse;
};
if (seqtype.value == 3) {
notes = notes.scramble;
};
if (play_btn.value == 1) {
notes = [Rest()];
digit = Rest();
};
rhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pseq(notes, inf),
\dur, ~base_dur/notes.size,
\legato, 0.99,
\mykey, Pseq(digits),
\amp, Pseq([~gen_amp],inf)
);
lhs = Pbind(
\type, \midi,
\midicmd, \noteOn,
\midiout, ~p.midi_out,
\chan, 0,
\midinote, Pseq([lookup_bass.(digit)], inf),
\dur, digit_to_dir.(digit),
\legato, 1.0,
\amp, Pseq([~gen_amp],inf)
);
play.(Ppar([rhs, lhs]));
};
};
var goto_index = { | idx |
var prefix, postfix, digit;
if (idx < 0) { idx = 0; };
if (idx >= digits.size) { idx = digits.size - 1; };
prefix = digits.copyRange(idx-50, idx-1);
digit = digits.copyRange(idx, idx);
postfix = digits.copyRange(idx+1, idx+50);
first_pi_lbl.string_(prefix);
pi_digit.string_(digit);
second_pi_lbl.string_(postfix);
~current_index = idx;
on_new_digit.(digit.asString.asInteger);
};
var parser = TheoryNoteParser();
var deg_to_chord = (
1 : "c4 e4 g4 b4 d5",
2 : "d4 f4 a4 c5 e5",
3 : "e4 g4 b4 d5 f5",
4 : "f4 a4 c5 e5 g5",
5 : "g4 b4 d5 f4 a4",
6 : "a4 c5 e5 g5 b5",
7 : "b4 d5 f5 a5 c6",
8 : "c5 e5 g5 b5 d6",
9 : "d5 f5 a5 c5 e5",
0 : "e5 g5 b5 d5 f5"
);
var reset_btn = Button().string_("Reset").action_({goto_index.(0);});
var left_btn = Button().string_("<=").action_({goto_index.(~current_index - 1);});
var play_btn = Button().states_([["play", Color.red, Color.grey(0.9)], ["pause", Color.blue, Color.grey(0.9)]]).action_({
on_new_digit.(pi_digit.value.asString.asInteger);
});
var oneshot_btn = Button().string_("OneShot").action_({on_oneshot_digit.(pi_digit.value.asString.asInteger)});
var right_btn = Button().string_("=>").action_({goto_index.(~current_index + 1);});
var transport_row = HLayout(nil, mode_btn, reset_btn, left_btn, play_btn, oneshot_btn, right_btn, nil);
var seqtype = PopUpMenu().items_([ "Up", "Down", "Up+Down", "Random" ]).action_({
on_new_digit.(pi_digit.value.asString.asInteger);
});
var seqrange = PopUpMenu().items_([ "1 oct", "2 oct", "3 oct" ]).action_({
on_new_digit.(pi_digit.value.asString.asInteger);
});
var property_row = HLayout(seqtype, seqrange, nil);
var notes_row = HLayout(nil,notes,nil);
var digits = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198";
screenlayout = screenlayout.add(temporow).add(advancerow).add(pirow).add(transport_row).add(property_row)./*add(amp_row).add(dur_row).*/add(notes_row).add(nil);
w.layout_(screenlayout);
w.front;
if (~p.isNil) {
~p = ScProphetRev2();
~p.connect;
~p.midi_out.latency_(0);
CmdPeriod.add(
{
16.do {
|i|
~p.midi_out.allNotesOff(i);
};
});
};
~current_chord = deg_to_chord[0].split($ ).collect({|el| TheoryNote(el).asMidi; });
~music_mode = cstCHORDMODE;
~player = nil;
tempo_edit.valueAction_(100);
basedur_edit.valueAction_(0.5);
play_btn.valueAction_(1);
seqtype.valueAction_(3);
autoadvance_cbx.valueAction_(0);
gen_amp_edit.valueAction_(0.33);
notes.string_(~current_chord.asString);
goto_index.(0);
fork {
while ({true}) {
if (~autoadvance_active == 1) {
~current_index = ~current_index + 1;
{ goto_index.(~current_index) }.defer;
};
~autoadvance_interval.wait;
}
};
});
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment