4 Diamond by James McCartney
8 Partch "otonalities" (i.e. a set of ratios with the same denominator
9 and changing numerator, i.e. overtone series) run horizontally.
11 Partch "utonalities" (i.e. a set of ratios with the same numerator and
12 changing denominator, a.k.a. undertone series) run vertically.
14 The ratio between a pair of buttons in any two columns is the same for
15 any row in those columns.
16 The ratio between a pair of buttons in any two rows is the same for any
18 ..there must be a less confusing way of stating that...
19 a set of buttons pressed in one row will be a transposition of the same
20 columns' buttons pressed in any row.
21 a set of buttons pressed in one column will be a transposition of the
22 same rows' buttons pressed in any column.
33 SynthDef("tone", { arg freq = 440, amp=0.1, gate =1;
35 env = Linen.kr(gate, 0.01, amp, 0.2, 2);
36 tone = OnePole.ar(Saw.ar(freq + {Rand(-0.05,0.05)}.dup, env), 0.95);
43 series2 = series ++ (2 * series) ++ (4 * (series ++ 16));
44 series = 4 * (series ++ 16);
46 w = Window("diamond", Rect(200,200,460,560));
47 w.view.decorator = FlowLayout(w.view.bounds);
49 series2.reverse.do {|denom|
52 var b, gcd, label, ratio, id, freq;
57 gcd = rnumer gcd: rdenom;
58 rnumer = rnumer div: gcd;
59 rdenom = rdenom div: gcd;
60 [rnumer, rdenom].postln;
61 ratio = rnumer / rdenom;
62 freq = 50.midicps * ratio;
63 b = Button(w, 50 @ 20);
64 label = rnumer.asString ++ " / " ++ rdenom;
65 color = if (rnumer.isPowerOfTwo && rdenom.isPowerOfTwo) {Color.red(1,0.4)}{
66 if(numer.isPowerOfTwo || denom.isPowerOfTwo) {Color.yellow(1,0.4)}{Color.clear}};
67 b.states = [[label, Color.black, color],[label, Color.white, Color.black]];
70 s.sendMsg(\s_new, \tone, id = s.nextNodeID, 0, 1, \freq, freq);
71 [\on, rnumer, rdenom].postln
73 s.sendMsg(\n_set, id, \gate, 0);
74 [\off, rnumer, rdenom].postln
78 w.view.decorator.nextLine;
90 ////////////////////////
99 // alternate, horizontal layout:
107 SynthDef("tone", { arg freq = 440, amp=0.1, gate =1;
109 env = Linen.kr(gate, 0.01, amp, 0.2, 2);
110 //tone = OnePole.ar(Saw.ar(freq + {Rand(-0.05,0.05)}.dup, env), 0.95);
111 tone = OnePole.ar(Saw.ar(freq + {Rand(-0.05,0.05)}.dup, env), 0.8);
118 series2 = series ++ (2 * series) ++ (4 * (series ++ 16));
119 series = (series ++ 16);
121 w = Window("diamond", Rect(50,200,980,220));
122 w.view.decorator = FlowLayout(w.view.bounds);
124 series.reverse.do {|denom|
127 var b, gcd, label, ratio, id, freq;
132 gcd = rnumer gcd: rdenom;
133 rnumer = rnumer div: gcd;
134 rdenom = rdenom div: gcd;
135 [rnumer, rdenom].postln;
136 ratio = rnumer / rdenom;
137 freq = 50.midicps * ratio;
138 b = Button(w, 40 @ 20);
139 label = rnumer.asString ++ "/" ++ rdenom;
140 color = if (rnumer.isPowerOfTwo && rdenom.isPowerOfTwo)
142 if(numer.isPowerOfTwo || denom.isPowerOfTwo)
143 {Color.yellow(1,0.4)}{Color.clear}};
144 b.states = [[label, Color.black, color],[label, Color.white,
148 s.sendMsg(\s_new, \tone, id = s.nextNodeID, 0, 1, \freq, freq);
150 s.sendMsg(\n_set, id, \gate, 0);
154 w.view.decorator.nextLine;
160 //////////////////////////////
164 // This one displays the cyclic cents values for the ratios.
171 var w, buttons, buttonFont;
174 SynthDef("tone", { arg freq = 440, amp=0.1, gate =1;
176 env = Linen.kr(gate, 0.01, amp, 0.2, 2);
177 //tone = OnePole.ar(Saw.ar(freq + {Rand(-0.05,0.05)}.dup, env), 0.95);
178 tone = OnePole.ar(Saw.ar(freq + {Rand(-0.05,0.05)}.dup, env), 0.8);
185 series2 = series ++ (2 * series) ++ (4 * (series ++ 16));
186 series = (series ++ 16);
188 w = Window("diamond", Rect(50,200,980,370), resizable: false);
189 w.view.decorator = FlowLayout(w.view.bounds);
191 buttonFont = Font("Helvetica", if( GUI.id === \cocoa, 11, 7 )).boldVariant;
193 series.reverse.do {|denom|
196 var b, gcd, label, ratio, id, freq;
201 gcd = rnumer gcd: rdenom;
202 rnumer = rnumer div: gcd;
203 rdenom = rdenom div: gcd;
204 [rnumer, rdenom].postln;
205 ratio = rnumer / rdenom;
206 freq = 50.midicps * ratio;
207 b = Button(w, 40 @ 40);
208 label = rnumer.asString ++ " / " ++ rdenom ++ "\n" ++
209 ((ratio.ratiomidi * 100).round.asInteger % 1200);
210 color = if (rnumer.isPowerOfTwo && rdenom.isPowerOfTwo)
212 if(numer.isPowerOfTwo || denom.isPowerOfTwo)
213 {Color.yellow(1,0.4)}{Color.clear}};
214 b.states = [[label, Color.black, color],[label, Color.white,
219 s.sendMsg(\s_new, \tone, id = s.nextNodeID, 0, 1, \freq, freq);
221 s.sendMsg(\n_set, id, \gate, 0);
225 w.view.decorator.nextLine;
232 /////////////////////////////////