2 // Séminaire Musical Final 2007
7 var dec, v_spiel, v_klang, v_neu, v_play, v_guess, v_display, v_sargam;
8 var f_setButtons, f_neu, f_play, f_guess, f_playSargam, f_freeSargam;
9 var spiel="sm_sine", freqs, index;
10 var intervalle, freq0, note0, rates, nameList, amp=0.5, sargamSynth;
12 var mode=\european, allowBase=true;
13 var eurNotes, indNotes, chords, chordKeys;
15 eurNotes = #["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "Bb", "B", "C'"];
16 indNotes = #["Sa", "re", "Re", "ga", "Ga", "Ma", "ma", "Pa", "dha", "Dha", "ni", "Ni", "Sa'"];
19 chords = IdentityDictionary[
20 'major' -> #[0, 2, 4],
21 'minor' -> #[0, 2b, 4],
22 '7th' -> #[0, 2, 4, 6b],
23 'minor7' -> #[0, 2b, 4, 6b],
24 'sixth' -> #[0, 2, 4, 5],
25 'minor6' -> #[0, 2b, 4, 5],
27 'aug7' -> #[0, 2, 4s, 6b],
28 'dim' -> #[0, 2b, 4b],
29 'dim7' -> #[0, 2b, 4b, 6bb],
30 '7th 5b' -> #[0, 2, 4b, 6b],
31 'min7 5b' -> #[0, 2b, 4, 6b],
32 'ninth' -> #[0, 2, 4, 6b, 8],
33 'minor9' -> #[0, 2b, 4, 6b, 8],
34 'major9' -> #[0, 2, 4, 6, 8],
35 '11th' -> #[0, 2, 4, 6b, 8, 10],
36 'dim9' -> #[0, 2, 5, 8],
37 'added9' -> #[0, 2, 4, 8],
38 'added4' -> #[0, 2, 4, 10],
41 '7 sus4' -> #[0, 3, 4, 6b],
42 '7 sus9' -> #[0, 1, 4, 6b],
45 chordKeys = chords.keys.asArray;
49 w = Window("seminaire_musical", Rect(10, 250, 750, 250), false);
51 w.view.decorator = dec = FlowLayout(w.view.bounds);
53 v_spiel = ListView(w, Rect(0,0, 100, 130))
55 ["noten", "frequenzen", "noten + oktave","intervalle","times","beatings", "akkorde"]
58 ["notes", "frequencies", "notes + octaves","intervals","times","beatings", "chords"]
61 v_klang = ListView(w, Rect(0,0, 100, 120)).items_(["sinus", "noise", "pulse", "bell", "piano", "timbre"]);
63 v_neu = Button(w, Rect(0,0, 70, 35)).states_([["next try", Color.black, Color.clear]]);
64 v_play = Button(w, Rect(0,0, 50, 35)).states_([["play", Color.black, Color.clear]]);
65 SCSlider(w, Rect(0,0, 200, 35)).value_(0.5).action_({ |v| amp = v.value });
66 Button(w, Rect(0,0, 90, 18))
67 .states_([["boot server", Color.black, Color.clear]]).action_({ Server.default.boot });
71 Button(w, Rect(0,0, 70,20))
72 .states_([["europe","india","numerical"], Color.black, Color.clear].flop)
73 .action_({ |v| mode = [\european, \indian, \numerical][v.value.asInteger]; f_neu.value; });
75 v_sargam = Button(w, Rect(0,0, 50, 20))
76 .states_([["sargam", Color.black, Color.clear], ["sargam", Color.red, Color.clear]]);
78 Button(w, Rect(0,0, 180, 20))
79 .states_([["including low tones", Color.black, Color.clear],["excluding low tones", Color.black, Color.clear]])
81 allowBase = v.value < 1;
84 v_display = StaticText(w, Rect(0,0,80,20)); //.font_(Font("Helvetica", 18));
92 StaticText(w, Rect(0,0, 300,20))
93 .string_("find the corresponding value here:")
99 v_guess = Array.fill(13, {
100 Button(w, Rect(0,0, 50, 35)).font_(Font("Monaco", 9));
108 f_setButtons = { arg werte;
109 v_guess.do { |but, i|
110 but.states_([[werte[i].asString, Color.black, Color.clear]]);
116 f_setButtons.("" ! 13);
118 var sargamIsPlaying, minFreq, octaves;
119 sargamIsPlaying = v_sargam.value > 0;
122 octaves = #[0.5, 1, 2, 4];
125 octaves = #[1, 2, 4];
129 switch(v_spiel.value,
131 if(mode == \indian) {
133 freqs = #[240, 256, 270, 288, 300, 320, 337.5, 360, 384, 400, 432, 450, 480];
134 // see: http://www.soundofindia.com/showarticle.asp?in_article_id=-446619640
137 freqs = ((0..12) + 60).midicps;
138 if(mode == \numerical) { nameList = (0..12) } { nameList = eurNotes };
144 nameList = { exprand(minFreq, 15000).round(1) } ! 13;
149 if(mode == \indian) {
150 freqs = #[240, 256, 270, 288, 300, 320, 337.5, 360, 384, 400, 432, 450, 480];
153 freqs = ((0..12) + 60).midicps;
154 if(mode == \numerical) { nameList = (0..12) } { nameList = eurNotes };
157 freqs = freqs * ({ octaves.choose } ! 12);
162 if(mode == \european) {
163 freq0 = ((0..12).choose + 60).midicps * octaves.choose;
164 intervalle = (1..12).midiratio.insert(9, 7/4); // insert 7/4
165 freqs = freq0 * intervalle;
167 #["-sekund", "+sekund", "-terz", "+terz", "quart", "tritone", "quint",
168 "-sext", "+sext", "7/4", "-sept", "sept", "oktav"
171 freq0 = #[240, 256, 270, 288, 300, 320, 337.5, 360, 384, 400, 432, 450].choose;
172 freq0 = freq0 * octaves.choose;
173 intervalle = [16/15, 9/8, 6/5, 5/4, 4/3, 17/12, 3/2, 8/5, 5/3, 7/4, 16/9, 15/8, 2/1];
174 freqs = freq0 * intervalle;
176 #["16/15", "9/8", "6/5", "5/4", "4/3", "17/12", "3/2", "8/5", "5/3", "7/4",
177 "16/9", "15/8", "2/1"];
181 freq0 = rrand(1600, 8000);
183 rates = { exprand(0.9, 19) } ! 13;
184 nameList = rates.round(0.01);
188 freq0 = ((0..11).choose + 60).midicps * octaves.choose;
190 rates = { exprand(0.9, 40) } ! 13;
191 nameList = rates.round(0.01);
195 note0 = (0..11).choose + #[-12, 0].choose;
196 freq0 = (note0 + 60).midicps;
198 nameList = chordKeys[ (0..chordKeys.size-1).scramble.keep(13)].sort;
201 f_setButtons.(nameList);
203 if(sargamIsPlaying) { f_playSargam.value };
209 switch(v_spiel.value,
212 Synth(spiel, [\freq, freq0, \amp, amp]);
214 Synth(spiel, [\freq, freq0 * intervalle[i], \amp, amp]);
218 Synth("sm_click", [\freq, freq0, \rate, rates[i], \amp, amp])
221 if(spiel.postln == "sm_string") {
222 Synth("sm_string", [\freq, freq0, \amp, amp]);
223 Synth("sm_string", [\freq, freq0 + rates[i], \amp, amp])
225 Synth("sm_beatings", [\freq, freq0, \rate, rates[i], \amp, amp])
230 var strum = [0, 0.04].choose.rand;
231 var notes = chords[nameList[i]].degreeToKey(#[0, 2, 4, 5, 7, 9, 11]) + note0;
233 Synth(spiel, [\freq, (val + 60).midicps, \amp, amp * 0.5]);
240 Synth(spiel, [\freq, freqs[i], \amp, amp])
246 f_playSargam = { v_sargam.valueAction = 1 };
247 f_freeSargam = { v_sargam.valueAction = 0 };
249 // funktionen zu buttons
250 v_neu.action = f_neu;
251 v_play.action = { f_play.value(index) };
252 v_spiel.action = f_neu;
256 but.states = [[but.states[0][0], Color.red, Color.yellow]];
259 v_display.string = "note:" + (freqs[i].cpsmidi - 60).round(0.1);
262 v_klang.action = {|view|
264 ["sm_sine", "sm_noise", "sm_pulse", "sm_bell", "sm_string", "sm_timbremix"][view.value.asInteger]
266 v_sargam.action = { |view|
268 { sargamSynth.release } { sargamSynth = Synth(\sm_sargam, [\freq, freq0, \amp, amp])
272 w.view.keyDownAction = { arg view, char;
273 f_play.value(char.ascii - 48 % 13);
276 w.onClose = { f_freeSargam.value };
280 SynthDef("sm_sine", { arg freq=440, amp=0.5;
281 amp = AmpComp.kr(freq) * amp;
284 SinOsc.ar(freq) * EnvGen.kr(Env.perc(0.03, Rand(0.3, 2), amp), doneAction:2),
291 SynthDef("sm_noise", { arg freq=440, amp=0.5;
293 amp = AmpComp.kr(freq) * amp;
294 u = BPF.ar(PinkNoise.ar(20), freq, Rand(0.1, 0.005));
298 Env.linen(Rand(0.03, 0.2), Rand(0.3, 2), Rand(0.3, 0.8), amp),
307 SynthDef("sm_pulse", { arg freq=440, amp=0.5;
309 amp = AmpComp.kr(freq) * amp;
310 u = Pulse.ar(freq, Rand(0.3, 0.5), 0.3);
313 u * EnvGen.kr(Env.perc(0.03, Rand(0.3, 2), amp), doneAction:2),
320 SynthDef("sm_bell", { arg freq=440, amp=0.5;
322 amp = AmpComp.kr(freq) * amp;
326 [1] ++ ({ rrand(1.2, 5.8) } ! (n-1)),
327 [1] ++ ({ rrand(0.1, 0.3) } ! (n-1)).sort.reverse,
330 * EnvGen.kr(Env.perc(0.03, Rand(0.3, 2), amp * 0.5), doneAction:2),
338 SynthDef("sm_string", { arg freq=440, amp=0.5;
340 amp = AmpComp.kr(freq) * amp;
341 exc = LFNoise2.ar(3000, Decay2.ar(Impulse.ar(0.0001, 0, 0.5), 0.006, 0.02));
342 sustain = Rand(1, 1.5);
344 CombN.ar(exc, 0.04, (freq * (1+[0, 0.001])).reciprocal, sustain).sum,
345 min(20000, freq * Rand(3, 2.3) ! 2)
348 //DetectSilence.ar(u, doneAction:2);
349 amp = amp * EnvGen.kr(Env.linen(0, sustain, 0.1), doneAction:2);
351 Pan2.ar(u * amp, freq.cpsmidi % 12 / 6 - 1)
357 SynthDef("sm_click", { arg freq=440, rate=1, amp=0.5;
359 amp = AmpComp.kr(freq) * amp;
360 u = SinOsc.ar(freq) * Decay.kr(Impulse.kr(rate, 0, 40), 0.002, 0.04);
363 u * EnvGen.kr(Env.linen(0, min(2, IRand(4, 8) / rate), 0.1, amp), doneAction:2),
370 SynthDef("sm_beatings", { arg freq=440, rate=1, amp=0.5;
372 amp = AmpComp.kr(freq) * amp;
373 u = SinOsc.ar([0, rate] + freq).sum * 0.3;
376 u * EnvGen.kr(Env.linen(0.01, max(Rand(0.3, 2), 3 / rate), 0.5, amp), doneAction:2),
383 SynthDef("sm_sargam", { arg freq=440, amp=0.5, gate=1.0;
385 amp = AmpComp.kr(freq) * amp * 0.5;
386 u = Pulse.ar(freq * [0.5, 1] +.t [Rand(0.2, 0.5), Rand(0.2, 0.5).neg],
387 LFNoise1.kr(0.11, 0.05, 0.4), 0.15).sum;
388 u = RLPF.ar(u, LFNoise2.kr(0.3, 0.2, 1) * 5000, 0.5);
390 u * EnvGen.kr(Env.asr(1.0, amp, 1.0), gate, doneAction:2)
395 SynthDef("sm_timbremix", { arg freq=440, amp=0.5;
397 freq = freq * ([1.0] ++ { ExpRand(1.0, 3.0) }.dup(18));
398 amp = amp * 0.4 * (AmpComp.ir(freq) * ([1.0] ++ (1..n).reciprocal));
402 SinOsc.ar(freq, 0, amp)
403 ) * EnvGen.kr(Env.perc(0.03, Rand(0.3, 2))),
408 DetectSilence.ar(u, doneAction:2);