supernova: fix for small audio vector sizes
[supercollider.git] / examples / pieces / atheoryofharmony.scd
blob520696d236f6a2a83b1c075d685c2cb7d5660edd
1 // a theory of harmony
2 //(C) Nick Collins 2007
4 //plaintive chords patch demonstrating scheduling attacks ahead of the beat and applying reverb
5 //the chord transitions are adapted from an idea by John Eacott
9 //first send the SynthDefs; make sure the Server is on
11 SynthDef(\slowatk,{arg note=60,atk=0.2,pan=0.0,det=0.1,detrate=9,wrate=16, wspan=0.4;
12 var slip,detune;
14 detune=SinOsc.kr(detrate,0,det,det);
16 slip= Mix.ar(Pulse.ar([note-detune,note+detune].midicps,Lag.kr(LFNoise0.kr(wrate,wspan,0.5)),0.1))*EnvGen.ar(Env([0,1,0],[atk,0.5]),doneAction:2);
17 Out.ar(0,Pan2.ar(slip,pan));
18 }).send(s);
20 SynthDef(\fastatk,{arg note=60,dcy=0.3,pan=0.0;
21 var osc;
23 osc= LPF.ar(Mix.ar(LFPar.ar(note.midicps,[0,1],0.12, PinkNoise.ar(XLine.kr(0.3,0.01,0.02)))), Line.kr(10000,200,0.1))
24 *EnvGen.ar(Env([0,1,0],[0.01,dcy]),doneAction:2);
26 Out.ar(0,Pan2.ar(osc,pan));
27 }).send(s);
29 SynthDef(\reverb,{
30 var a,c,z,y,in;
31 c = 7; // number of comb delays
32 a = 4; // number of allpass delays
34 in=In.ar(0,2);
35 // reverb predelay time :
36 z = DelayN.ar(in, 0.048,0.048);
38 //for delaytime if want modulation-     //LFNoise1.kr(0.1.rand, 0.04, 0.05)
39 y=Mix.arFill(c,{CombL.ar(z,0.1,rrand(0.01, 0.1),5)});
40         
41 // chain of 4 allpass delays on each of two channels (8 total) :
42 a.do({ y = AllpassN.ar(y, 0.051, [rrand(0.01, 0.05),rrand(0.01, 0.05)], 1) });
43         
44 // add original sound to reverb and play it :
45 ReplaceOut.ar(0,in+(0.2*y));
46 }).send(s)
50 //now run the piece
52 var sched;
53 var chordtype,diatonic,transitions, current, strength, type;
54 var revunit;
55 var next,hits,hitset;
56 var prevchord, ostinatostyle,which,base;
57 var chordbias;
59 prevchord=[60,64,67];
60 ostinatostyle=4.rand;
61 which=2.rand;
63 revunit= Synth(\reverb);
65 chordbias= 1.0; //0.7; //default 0.7
67 //a quick list of chord types, ignoring any theory of extensions
68 chordtype= [
69 [0,4,7],                //maj
70 [0,4,7,11],     //maj7
71 [0,3,7],                //min
72 [0,3,7,10],     //min7
73 [0,4,7,10],     //dom 7
74 [0,3,6,10],     //half dim
75 [0,3,6,9],      //dim
76 [0,5,7]         //sus4
79 diatonic=[0,2,4,5,7,9,11];
81 //perversion of John Eacott's theory of pop harmony, from strong to weak
82 transitions=[-3,-2,3,1,2,-1,0];
84 current=0;      //start on tonic
85 strength=0;
87 SystemClock.sched(0.0,{ 
88         var chord,root, adjust, whichroot, pans;
89         var chord3;
90         
91         if(0.2.coin,{strength= (strength+rrand(1,2))%7});
92         
93         current=(current+(transitions.at(strength)))%7;
94         
95         root=diatonic.at(current)+60;
96         
97         chord=chordtype.wchoose(Array.geom(8,1,0.7).normalizeSum)+root;
98         
99         adjust= (chord.size-1).rand;
100         
101         //changing octave of some elements
102         adjust.do({arg i; chord.put(chord.size-1-i,chord.at(chord.size-1-i)-12)});
103         
104         //make root the bass eight times out of ten
105         whichroot= 0;
106         if(0.2.coin,{whichroot=chord.size-1});
107         
108         chord.put(whichroot,chord.at(whichroot)-24);
109         
110         chord.postln;
111         
112         pans= Array.fill(chord.size,{arg i; (2.0*i)/(chord.size-1)-1.0;});
113         
114         pans.scramble;
115         
116         //can do 3.do which is v.pleasant
117         chord.size.do({arg i;
118                 var ahead;
119                 
120                 ahead= exprand(0.05,1.0);
121                 
122                 SystemClock.sched(1.0-ahead,{
123                 Synth.before(revunit,\slowatk,[\note, chord.at(i), \atk, ahead,\pan, pans.at(i),\detrate,8.0.rand, \det,0.12.rand,\wrate, [1,4,16].choose, \wspan, 0.45.rand]);
124                 nil
125                 });
126                 
127         });
128         
129         if(0.05.coin,{ostinatostyle= 4.rand; which= 2.rand});
130         
131         base= [chord,prevchord].at(which);
132         chord3= [base,base+12,base-12,(base%12).scramble+60].at(ostinatostyle);
133         //jolly rhythm, can use prevchord or chord, can use plain chord instead of the modulo version
134         //chord3= chord+12; //(chord %12).scramble+60; chord-12; chord+12; chord
135         //chord3.postln;
136         
137         next=[1.0,1.5,2.0,3.25].wchoose([0.32,0.32,0.32,0.04]);
138         
139         hits= (next/0.25).asInteger;
140         
141         //hitset= Array.series(hits,0.0,0.5);
142         hitset=List.new;
143         
144         hits.do({arg i; 
145                 
146                 hitset.add(i*0.25);
147                 if(0.1.coin,{
148                 hitset.add(i*0.25+0.125)
149                 });
150                 
151         });
152         
153         if(0.97.coin,{  
154                 hitset.do({arg val;
155                 
156                 SystemClock.sched(val,{
157                 
158                 //could be 3.do or chord3.do
159                 chord3.size.do({arg i;
160                 Synth.after(revunit,\fastatk,[\note,chord3.at(i)]);
161                 });
162                 
163                 nil});
164                 });
165         });
166         
167         prevchord=chord;
168         
169         next