first and basic
[emoc:atari-chip-chuck.git] / atari-class-et-test.ck
1 class Atari {
2
3
4     // Distorsion modes 0-15 data 
5     [
6       // 0 : Distorsion 0 
7       // No sound, used to output 4-bit samples by changing the volume very fast
8       [ [1],    // Source Samples data
9         [1],    // Modifier data
10         [1] ],  // Clock mode (pixelclock = 3 * cpuclock)
11       // Distorsion 1 / Buzzy Tones
12       [ [0,0,1,0,1,0,0,0,0,1,1,1,0,1,1],    
13         [1],    
14         [1] ],
15       // Distorsion 2 / Carries distorsion 1 downward into a rumble
16       [ [0,0,1,0,1,0,0,0,0,1,1,1,0,1,1],    
17         [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],    
18         [1] ],
19       // Distorsion 3 / Flangy wavering tones, like a UFO
20       [ [0,0,1,0,1,0,0,0,0,1,1,1,0,1,1],    
21         [0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1],    
22         [1] ],
23       // Distorsion 4 / Pure tone
24       [ [0,1],    
25         [1],    
26         [1] ],
27       // Distorsion 5 : same as 4
28       [ [0,1],   
29         [1],    
30         [1] ],
31       // Distorsion 6 / Between pure tone and buzzy tone
32       [ [1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],    
33         [1],    
34         [1] ],
35       // Distorsion 7 / Reedy tones, much brighter
36       [ [0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1],    
37         [1],    
38         [1] ],
39       // Distorsion 8 : 511 bits of white noise 
40       // White noise / explosions / lightning, jet / spacecraft engine
41       [ [1,1,0,0,0,0,1,1,0,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,1,1,0,0,0,1,0,0,0,1,1,1,0,0,1,0,
42          0,1,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,1,1,0,1,0,1,0,0,1,1,0,1,1,1,0,1,
43          1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,0,1,1,1,0,1,1,1,
44          1,0,1,1,0,0,0,0,1,0,1,0,1,1,0,1,0,0,0,1,0,1,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,1,1,0,
45          1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,1,0,0,1,0,0,1,
46          1,0,0,0,0,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,1,
47          0,0,1,0,1,1,0,0,1,0,1,0,1,0,1,0,0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,0,1,1,0,0,1,0,
48          1,0,1,0,1,1,1,0,0,0,1,0,1,0,0,0,1,1,1,0,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,0,1,1,
49          1,0,0,0,0,1,0,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,1,1,1,
50          1,0,1,0,0,0,1,1,0,1,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,0,0,
51          0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,0,1,0,0,1,0,0,
52          0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,0,0,0,0,1,
53          0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,1,0,1,0,0,0,1,0],    
54         [1],    
55         [1] ],
56       // Distorsion 9 : same as 7
57       [ [0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1],  
58         [1],    
59         [1] ],
60       // Distorsion 10 : same as 6
61       [ [1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 
62         [1],    
63         [1] ],
64       // Distorsion 11 : same as 0
65       [ [1],       
66         [1],    
67         [1] ],
68       // Distorsion 12 / Pure tone, goes much lower in pitch than 4 & 5
69       [ [1,0],    
70         [1],    
71         [3] ],
72       // Distorsion 13 : same as 12
73       [ [1,0],       
74         [1],    
75         [3] ],
76       // Distorsion 14 / Electronic tones, mostly lows, extends to rumble
77       [ [1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],    
78         [1],    
79         [3] ],
80       // Distorsion 15 / Electronic tones, mostly lows, extends to rumble
81       [ [0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1],    
82         [1],    
83         [3] ]
84     ] @=> int DMData[][][];
85
86     //Step s => Envelope e;
87     Step s => Gain g;
88     1.0 => s.gain;
89     1.0 => g.gain;
90     
91     int pitch;      // 0-31 pitch value
92     int distorsion; // 0-15 distorsion mode (modifies source & modifier)
93     int volume;     // 0-15
94     dur durmax;
95     0::samp => dur duree;
96     
97     1.4134615384::samp => dur tbase;    // 44100 / 31200 (TIA PAL samplerate based on pixelclock)
98     //1.4026717557::samp => dur tbase;  // 44100 / 31440 (TIA NTSC samplerate based on pixelclock)
99     dur t;
100     tbase => t;
101     
102     1 => int sourceLength;
103     1 => int modifierLength;
104
105     0 => int i;    // source index (0 -> source length - 1)
106     0 => int j;    // modifier index (0 -> modifier length - 1)
107     0 => int timeIndex;
108
109     float sample;
110     float sampleValue;
111     0 => float lastSampleValue;
112     float sampleVolume;
113     
114
115
116     
117     public void gain( float g ) {
118         g => s.gain;
119     }
120
121     public void connect( UGen ugen ){
122         g => ugen;
123     }
124     
125     public void init() {
126
127         DMData[distorsion][0].size() => sourceLength;
128         DMData[distorsion][1].size() => modifierLength;
129                     
130         // switch between cpuclock and pixelclock (pixelclock = 3 * cpuclock)
131         if (DMData[distorsion][2][0] == 3) tbase + tbase + tbase => t;
132         else tbase => t;
133                     
134         0 => i;
135         0 => j;
136
137         (1.0 / 16) * volume => sampleVolume;
138         
139         0 => pitch;
140         0 => distorsion;
141         0 => volume;
142     }
143
144     public void off() {
145         0 => volume;
146     }
147     
148     public void set(int _p, int _d, int _v) {
149         _p => pitch;
150         _d => distorsion;
151         _v => volume;
152         (1.0 / 16) * volume => sampleVolume;
153         DMData[distorsion][0].size() => sourceLength;
154         DMData[distorsion][1].size() => modifierLength;
155                     
156         // switch between cpuclock and pixelclock (pixelclock = 3 * cpuclock)
157         if (DMData[distorsion][2][0] == 3) tbase + tbase + tbase => t;
158         else tbase => t;
159                     
160         0 => i;
161         0 => j;
162     }
163     
164     public void play(dur _durmax) {
165         _durmax => durmax;
166         0::samp => dur duree;
167         while (t => now) {
168             if (DMData[distorsion][1][j] == 1) {
169                 DMData[distorsion][0][i] => sampleValue;
170                 sampleValue => lastSampleValue;
171             } else lastSampleValue => sampleValue;
172                       
173             sampleValue * sampleVolume => sample;
174             sample => s.next;
175                       
176             if (timeIndex % (pitch + 1) == 0) i++;
177             i % sourceLength => i;
178                       
179             j++;
180             j % modifierLength => j;
181                       
182             timeIndex++;
183             duree + t => duree;
184             if (duree > durmax) break;
185         }
186         off();
187     }
188 }
189
190
191
192
193
194
195
196
197
198
199
200 /* ************************************************************** */
201
202
203 Hid hi;
204 HidMsg msg;
205
206 Gain g => dac;
207 0.5 => g.gain;
208
209 Gain g1 => dac;
210 0.3 => g1.gain;
211 Atari ajoy;
212 ajoy.connect(g1);
213 ajoy.init();
214 float x;
215 float y;
216 float z;
217
218 // which joystick
219 0 => int device;
220
221 // open joystick 0, exit on fail
222 if( !hi.openJoystick( device ) ) me.exit();
223
224 <<< "joystick '" + hi.name() + "' ready", "" >>>;
225
226 spork~ atarinotejoy();
227
228 // infinite event loop
229 while( true ) {
230     hi => now; // wait on HidIn as event
231
232     // messages received
233     while( hi.recv( msg ) ) {
234         if( msg.isAxisMotion() ) {
235             //<<< "joystick axis", msg.which, ":", msg.axisPosition >>>;
236             if (msg.which == 0) msg.axisPosition => x;
237             if (msg.which == 1) msg.axisPosition => y;
238             if (msg.which == 2) msg.axisPosition => z;
239         } else if( msg.isButtonDown() ) {
240             // <<< "joystick button", msg.which, "down" >>>;
241             Std.rand2(5, 30)::ms => dur randur;
242             if (Std.rand2(0, 1) > 0.5) spork ~ atariup(msg.which, 8, randur, g);
243             else spork ~ ataridown(msg.which, 8, randur, g);
244         }
245     }
246 }
247
248 fun void atariup(int _dis, int _vol, dur _d, UGen ugen) {
249     Atari aa;
250     aa.connect(ugen);
251     aa.init();
252
253     for ( 0 => int i; i < 31; i++ ) {
254         aa.set(i, _dis, _vol);
255         aa.play(_d);
256     }
257 }
258
259 fun void ataridown(int _dis, int _vol, dur _d, UGen ugen) {
260     Atari aa;
261     aa.connect(ugen);
262     aa.init();
263
264     for ( 31 => int i; i > 0; i-- ) {
265         aa.set(i, _dis, _vol);
266         aa.play(_d);
267     }
268 }
269
270 fun void atarinotejoy() {
271     while (1) {
272         ((x + 1) * 15) $ int => int xx;
273         ((y + 1) * 7) $ int => int yy;
274         ((z + 1) * 7) $ int => int zz;
275         <<<"pitch " + xx + " disto " + yy + " vol " + zz>>>;
276         ajoy.set(xx, yy, zz);
277         ajoy.play(10::ms);
278     }
279 }