1 /* a samson box emulator */
2
3 /* I assume what people really want is a good rendition from their ancient SAM files,
4 * not an exact replica of the Samson box output. The latter used 12, 14, 20, 24, 28, and 30-bit
5 * fractional and integer fields, which are a pain to deal with when we would rather use doubles.
6 *
7 * gcc sam.c -o sam -lm -O2
8 * sam TEST.SAM
9 * -> TEST.wav ("wav" or "riff" header, quad, little-endian float data at box srate)
10 *
11 * to include a read-data file, convert the old SAD file to a raw file of little-endian floats,
12 * then sam TEST.SAM test.snd
13 *
14 * here's the Snd code I use to turn quad into stereo and scale the result to .9:
15 *
16
17 (define* (quad->stereo (snd 0))
18 "turn a quad sound into a (new) stereo sound by mixing 4->1 and 3->2"
19 (let ((r0 (make-sampler 0 snd 0))
20 (r1 (make-sampler 0 snd 1))
21 (r2 (make-sampler 0 snd 2))
22 (r3 (make-sampler 0 snd 3)))
23 (let ((new-snd (new-sound :channels 2
24 :srate (srate snd)
25 :size (frames snd)
26 :header-type (header-type snd)
27 :sample-type (sample-type snd))))
28 (map-channel (lambda (y)
29 (+ (next-sample r0) (next-sample r3)))
30 0 (frames snd) new-snd 0)
31 (map-channel (lambda (y)
32 (+ (next-sample r1) (next-sample r2)))
33 0 (frames snd) new-snd 1)
34 (let* ((mx (apply max (maxamp new-snd #t)))
35 (scl (/ 0.9 mx)))
36 (map-channel (lambda (y) (* y scl)) 0 (frames snd) new-snd 0)
37 (map-channel (lambda (y) (* y scl)) 0 (frames snd) new-snd 1)))))
38 *
39 *
40 * Thanks to Michael McNabb for bug fixes and enhancements!
41 * And thanks to Peter Samson for going back to the schematics to answer our questions!
42 */
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdbool.h>
48 #include <math.h>
49
50
51 #define TOTAL_SAMPLES -1
52 /* set TOTAL_SAMPLES to the number of samples you want computed, or -1 to compute all of them */
53
54 #define DEFAULT_DESCRIBE_COMMANDS false
55 #define REPORT_BAD_COMMANDS true
56 #define FLUSH_BAD_COMMANDS false
57 #define FLUSH_TRAILING_LINGERS false
58
59 static bool describe_commands = DEFAULT_DESCRIBE_COMMANDS;
60 static int start_describing = -1, stop_describing = -1;
61 static int dump_patch_at = -1;
62
63
64 #define LDB(Cmd, Size, Position) ((Cmd >> Position) & ((1 << Size) - 1))
65 #define BIT(Cmd, Position) ((Cmd >> Position) & 1)
66
67 #define TWOS_12(N) ((N < (1 << 11)) ? N : ((N & 0x7ff) - (1 << 11)))
68 #define TWOS_20(N) ((N < (1 << 19)) ? N : ((N & 0x7ffff) - (1 << 19)))
69 #define TWOS_24(N) ((N < (1 << 23)) ? N : ((N & 0x7fffff) - (1 << 23)))
70 #define TWOS_28(N) ((N < (1 << 27)) ? N : ((N & 0x7ffffff) - (1 << 27)))
71 #define TWOS_30(N) ((N < (1 << 29)) ? N : ((N & 0x1fffffff) - (1 << 29)))
72
73 #define TWOS_12_TO_DOUBLE(N) ((double)TWOS_12(N) / (double)(1 << 11))
74 #define TWOS_20_TO_DOUBLE(N) ((double)TWOS_20(N) / (double)(1 << 19))
75
76 #define DOUBLE_12(N) ((double)N / (double)(1 << 11))
77 #define DOUBLE_20(N) ((double)N / (double)(1 << 19))
78 #define DOUBLE_24(N) ((double)N / (double)(1 << 23))
79 #define DOUBLE_28(N) ((double)N / (double)(1 << 27))
80 #define DOUBLE_30(N) ((double)N / (double)(1 << 29))
81
82 /* mmm -- slightly more accurate to use 1<<12-1, I think */
83 #define UNSIGNED_12_TO_DOUBLE(N) ((double)N / (double)((1 << 12) - 1))
84 #define DOUBLE_TO_TWOS_20(X) ((X >= 0.0) ? (int)(X * (1 << 19)) : (int)((X + 1.0) * (1 << 19)))
85
86
87 #if (!defined(M_PI))
88 #define M_PI 3.14159265358979323846264338327
89 #define M_PI_2 (M_PI / 2.0)
90 #endif
91
92
93 typedef struct {
94 int GO, GJ, GK, GN, GM, GP, GQ, GL, GSUM, GFM, GS, GMODE;
95 double f_GO, f_GJ, f_GK, f_GM, f_GP, f_GQ, f_GL;
96 } generator;
97
98 typedef struct {
99 int M0, M1, L0, L1, MIN, MRM, MSUM, MMODE, MMMMM, T, mult_scl_1, mult_scl_0, o_M0, o_M1;
100 double f_M0, f_M1, f_L0, f_L1, o_f_M0, o_f_M1;
101 /* by "2nd multiplication" I think Pete means M0 since it follows M1 so AA -> M0 and BB -> M1 */
102 } modifier;
103
104 typedef struct {
105 int P, Z, Y, X, I; /* "I" = table lookup index received from modifier */
106 double xd1, xd2; /* mmm - accounts for "extra" hidden delay */
107 } delay;
108
109 #define SUM_MEMORY_SIZE 64
110 static double gen_outs[SUM_MEMORY_SIZE], gen_ins[SUM_MEMORY_SIZE], mod_outs[SUM_MEMORY_SIZE], mod_ins[SUM_MEMORY_SIZE]; /* "sum memory" */
111 static double prev_gen_ins[SUM_MEMORY_SIZE], prev_mod_ins[SUM_MEMORY_SIZE]; /* some debugging info */
112 static double peak_gen_ins[SUM_MEMORY_SIZE], peak_mod_ins[SUM_MEMORY_SIZE];
113
114 #define GENERATORS 256
115 #define MODIFIERS 128
116 #define DELAYS 32
117
118 static generator *gens[GENERATORS];
119 static modifier *mods[MODIFIERS];
120 static delay *dlys[DELAYS];
121
122 #define DELAY_MEMORY_SIZE 65536
123 static double delay_memory[DELAY_MEMORY_SIZE];
124 static float dac_out[4], dac_out_peak[4];
125
126 static int tick, pass, DX, processing_ticks, highest_tick_per_pass, samples = 0, srate = 1, total_commands = 0, current_command = 0;
127
128 FILE *snd_file = NULL; /* for now just riff/wave quad, but srate depends on tick setting */
129 FILE *read_data_file = NULL;
130 static char *filename = NULL; /* mmm - Keep SAM filename around */
131 static char *output_filename = NULL; /* mmm - And generate matching output file name == <sam name>.wav */
132
start_clean(void)133 static void start_clean(void)
134 {
135 int i;
136 for (i = 0; i < SUM_MEMORY_SIZE; i++)
137 {
138 gen_outs[i] = 0.0; /* "outs" are this pass */
139 gen_ins[i] = 0.0; /* "ins" are last pass */
140 mod_outs[i] = 0.0;
141 mod_ins[i] = 0.0;
142
143 prev_mod_ins[i] = 0.0;
144 prev_gen_ins[i] = 0.0;
145 peak_mod_ins[i] = 0.0;
146 peak_gen_ins[i] = 0.0;
147 }
148
149 for (i = 0; i < GENERATORS; i++)
150 gens[i] = (generator *)calloc(1, sizeof(generator));
151
152 for (i = 0; i < MODIFIERS; i++)
153 {
154 mods[i] = (modifier *)calloc(1, sizeof(modifier));
155 mods[i]->mult_scl_1 = 1;
156 mods[i]->mult_scl_0 = 1;
157 }
158
159 for (i = 0; i < DELAYS; i++)
160 dlys[i] = (delay *)calloc(1, sizeof(delay));
161
162 for (i = 0; i < DELAY_MEMORY_SIZE; i++)
163 delay_memory[i] = 0.0;
164
165 for (i = 0; i < 4; i++)
166 {
167 dac_out[i] = 0.0;
168 dac_out_peak[i] = 0.0;
169 }
170
171 tick = 0;
172 pass = 0;
173 }
174
175
all_done(void)176 static void all_done(void)
177 {
178 if (snd_file)
179 {
180 int header_info[1];
181 fclose(snd_file);
182 snd_file = fopen(output_filename, "r+"); /* mmm */
183 fseek(snd_file, 4L, SEEK_SET);
184 header_info[0] = 88 + samples * 4 * 4; /* total data bytes 4 chans, 4 bytes/float */
185 fwrite((void *)header_info, 4, 1, snd_file);
186 fseek(snd_file, 76L, SEEK_SET);
187 header_info[0] = samples * 4 * 4;
188 fwrite((void *)header_info, 4, 1, snd_file);
189 fclose(snd_file);
190
191 fprintf(stderr, "%s: %dHz, %d samples, %.4f secs", output_filename, srate, samples, (double)samples / (double)srate); /* mmm */
192 fprintf(stderr, ", maxamps: %.3f %.3f %.3f %.3f\n", dac_out_peak[0], dac_out_peak[1], dac_out_peak[2], dac_out_peak[3]);
193 }
194 exit(0);
195 }
196
197
dac_write(double data,int chan)198 static void dac_write(double data, int chan)
199 {
200 /* during a given pass we accumulate output to the dac */
201 dac_out[chan] += (float)(data / 2.0);
202 /* mmm - /2 seems best now that other scalings have been adjusted */
203 }
204
205
206 /* ---------------------------------------- generator processing ---------------------------------------- */
207
208 /*
209 * DAJ - Here is JOS's translation into english of the generator processing.
210 *
211 * Associated with each generator are the following quantities:
212 * FrqSwp20 (20 bits) alpha -- oscillator frequency sweep rate
213 * OscFrq28 (28 bits) omega -- oscillator frequency
214 * OscAng20 (20 bits) theta -- oscillator angle
215 * NumCos11 (11 bits) number of cosines to be summed
216 * CosScl4 (4 bits) binary scale of cosine or sum of cosines
217 * AmpSwp20 (20 bits) delta -- decay rate
218 * CurAmp24 (24 bits) phi -- decay exponent
219 * AmpOff12 (12 bits) asymptote
220 * OutSum6 (6 bits) sum memory address into which output is added
221 * FmSum7 (7 bits) sum memory address from which frequency modulation data is taken
222 * FmSum7 = QAAAAAA
223 * Q: 0 generator-last-pass quadrant
224 * 1 modifier-last-pass quadrant
225 * AAAAAA: sum address within quadrant
226 * Gmode10 (10 bits) generator mode
227 * Gmode10 = RRRREESSSS
228 *
229 * Processing
230 * ----------
231 *
232 * Calculations performed for a generator, governed by its
233 * mode, proceed as detailed below.
234 *
235 * 1) The word in sum memory addressed by FmSum7 is read (20 bits);
236 * the sum is formed of it and the high-order 20 bits of
237 * OscFrq28 (call the result FmPhase20).
238 *
239 * 2) If the oscillator side is running, FrqSwp20, right-adjusted with
240 * sign extended, is added into OscFrq28.
241 *
242 * 3) If the oscillator mode is SIN(J+Fm), FmPhase20 is taken; otherwise OscAng20.
243 * Call the 20-bit result Phase20, and its high-order 13 bits
244 * Phase13.
245 *
246 * 4) If the oscillator side is running, FmPhase20 is added into OscAng20.
247 *
248 * 5) If the run mode is WRITEDATA, the word in sum memory addressed by FmSum7
249 * is sent to the CPU as the next write-data item; if the run
250 * mode is DACOUT it is sent to the DAC addressed by the low-order
251 * 4 bits of FrqSwp20.
252 *
253 * 6) In oscillator modes other than SIN(K) and SIN(J+Fm), Phase13 is multiplied
254 * by NumCos11. Call the low-order 12 bits of the product, with two bits
255 * equal to 01 appended to the right, the 14-bit result SinAdr.
256 * In oscillator modes SIN(K) and SIN(J+Fm), SinAdr is the high-order 13
257 * bits of Phase20, with a bit equal to 1 appended to the right.
258 *
259 * 7) If the oscillator mode is SIN(K) or SIN(J+Fm), pi/2 is taken (the binary
260 * number 010...0); otherwise Phase13. Call the result CscAdr.
261 *
262 * 8) In floating point, the product csc (CscAdr) * sin (SinAdr) is
263 * formed; then converted to fixed point with a scale factor
264 * of 2**(-CosScl4). Call the result (13 bits) TblOut13.
265 *
266 *
267 * 9) The result of the oscillator side (13 bits, call it OscOut13) is
268 * then determined according to the oscillator mode.
269 * SSSS: SUMCOS TblOut13
270 * SAWTOOTH Phase13 (but 0 when Phase13 is 1000000000000)
271 * SQUARE -1/2 (on a scale from -1 to +1) if Phase13 is negative,
272 * else +1/2
273 * PULSE +1/2 if overflow occurred in step 1) or 4) above;
274 * else 0.
275 * SIN(K) TblOut13
276 * SIN(J+Fm) TblOut13
277 *
278 * 10) The high-order 12 bits of CurAmp24 are taken (call the result CurAmp12).
279 *
280 * 11) If the envelope side is running, AmpSwp20 right-adjusted, sign
281 * extended, is added into CurAmp24 (overflow dealt with according
282 * to the run mode). (The overflow condition is CurAmp24 changing
283 * sign such that the high-order bit of the resultant CurAmp24 equals
284 * the sign bit of AmpSwp20.)
285 *
286 * 12) If the envelope mode is 10 or 11, 2**(-CurAmp12) is looked up;
287 * otherwise CurAmp12 is taken. Call the resulting 12 bits NewAmp12.
288 * Scaling is such that if CurAmp12 is 0 then 2**(-CurAmp12) is
289 * 111 111 111 101 binary; if CurAmp12 is 000 100 000 000 binary,
290 * then 2**(-CurAmp12) is 011 111 111 110.
291 *
292 * 13) If the envelope mode is 01 or 11, NewAmp12 is added to AmpOff12; else
293 * it is subtracted from AmpOff12. This creates Env12, the result
294 * of the envelope side.
295 *
296 * 14) OscOut13 is multiplied by Env12. If the run mode specifies adding
297 * into sum memory, the high-order 19 bits of the rounded product,
298 * right-adjusted with sign extended, are added into the sum
299 * memory location designated by OutSum6; except that in run mode
300 * READDATA, the product is added to the next read-data item from the
301 * CPU and the sum replaces the contents of the sum memory
302 * location addressed.
303 */
304
305 #define osc_mode(gmode) (gmode & 0xf)
306
307 /*
308 SSSS: 0100 sum of cosines
309 0001 sawtooth
310 0010 square
311 0011 pulse train
312 0000 sin (K)
313 1000 sin (J + fm)
314 */
315
316 #define SUMCOS 4
317 #define SAWTOOTH 1
318 #define SQUARE 2
319 #define PULSE 3
320 #define SIN_K 0
321 #define SIN_FM 8
322
323
324 #define osc_env(gmode) ((gmode >> 4) & 0x3)
325
326 /*
327 EE: 00 L - Q
328 01 L + Q
329 10 L - 2**(-Q)
330 11 L + 2**(-Q)
331 */
332
333 #define L_PLUS_Q 1
334 #define L_MINUS_Q 0
335 #define L_MINUS_2_TO_MINUS_Q 2
336 #define L_PLUS_2_TO_MINUS_Q 3
337
338
339 #define osc_run(gmode) ((gmode >> 6) & 0xf)
340
set_osc_run(int gen,int RRRR)341 static void set_osc_run(int gen, int RRRR)
342 {
343 generator *g;
344 if (gen >= GENERATORS) {fprintf(stderr, "gen mode set overflow\n"); gen = 0;}
345 g = gens[gen];
346 /* RRRREESSSS */
347 g->GMODE = (g->GMODE & 0x3f) | (RRRR << 6);
348
349 if (g->GMODE == 3) g->GMODE = 2; /* if write data, send it to the DAC outputs instead */
350 }
351
352 /* osc. run? env. run? add to sum?
353 RRRR:0000 inactive no no no
354 0001 pause no no no
355 1111 running A yes yes, sticky yes
356 1110 running B yes yes, free; yes
357 triggers subseq.
358 on overflow
359 1001 wait yes no no
360 1101 running C yes yes, free; yes
361 stops and
362 triggers subseq.
363 on overflow
364 0111 read data from computer no yes yes
365 0011 write data to computer no no no
366 0010 write data to DAC no no no
367 (address in GO)
368 */
369
370
osc_is_running(int mode)371 static bool osc_is_running(int mode)
372 {
373 int RRRR;
374 RRRR = osc_run(mode);
375 return((RRRR == 15) || (RRRR == 14) || (RRRR == 9) || (RRRR == 13));
376 }
377
378
env_is_running(int mode)379 static bool env_is_running(int mode)
380 {
381 int RRRR;
382 RRRR = osc_run(mode);
383 return((RRRR == 15) || (RRRR == 14) || (RRRR == 7) || (RRRR == 13));
384 }
385
386
adding_to_sum(int mode)387 static bool adding_to_sum(int mode)
388 {
389 int RRRR;
390 RRRR = osc_run(mode);
391 return((RRRR == 15) || (RRRR == 14) || (RRRR == 7) || (RRRR == 13));
392 }
393
394
gen_is_active(generator * g)395 static bool gen_is_active(generator *g)
396 {
397 return((osc_is_running(g->GMODE)) && (g->GQ != 0) && (g->GJ != 0));
398 }
399
400
gen_amp(generator * g)401 static double gen_amp(generator *g)
402 {
403 int emode;
404 double Q;
405
406 if (osc_run(g->GMODE) == 0) return(0.0);
407
408 emode = osc_env(g->GMODE);
409 if ((emode == L_PLUS_2_TO_MINUS_Q) ||
410 (emode == L_MINUS_2_TO_MINUS_Q))
411 Q = pow(2.0, -16.0 * g->f_GQ);
412 else Q = g->f_GQ;
413
414 if ((emode == L_PLUS_Q) ||
415 (emode == L_PLUS_2_TO_MINUS_Q))
416 return(g->f_GL + Q);
417 return(g->f_GL - Q);
418 }
419
420
421 static bool read_data_warned = false;
422
process_gen(int gen)423 static void process_gen(int gen)
424 {
425 #define FmSum7 g->GFM
426 #define OutSum6 g->GSUM
427 #define FrqSwp20 g->f_GO
428 #define OscFreq28 g->f_GJ
429 #define OscAng20 g->f_GK
430 #define NumCos11 g->GN
431 #define AmpSwp20 g->f_GP
432 #define AmpOff12 g->f_GL
433 #define Gmode10 g->GMODE
434 #define CurAmp24 g->f_GQ
435 #define CosScl4 g->GM
436 #define ShiftOut g->GS
437
438 generator *g;
439 double fm, FmPhase20, Phase20, SinAdr, CscAdr, TblOut13, OscOut13, CurAmp12, NewAmp12, Env12, temp;
440
441 g = gens[gen];
442 if (osc_run(g->GMODE) == 0) /* inactive */
443 return;
444
445 if (osc_run(Gmode10) == 3)
446 {
447 /* mmm - just ignore write-data generators since everything is being written out anyway */
448 return;
449 }
450
451 if ((FmSum7 >> 6) == 0)
452 fm = gen_ins[FmSum7 & 0x3f];
453 else fm = mod_ins[FmSum7 & 0x3f];
454 /* fm *= 0.5; */
455
456 FmPhase20 = fm + OscFreq28;
457
458 if (osc_is_running(Gmode10))
459 OscFreq28 += (FrqSwp20 / 256.0); /* right adjusted 20 bit */
460
461 if (osc_mode(Gmode10) == SIN_FM) /* sin(J+fm) */
462 Phase20 = FmPhase20;
463 else Phase20 = OscAng20;
464
465 if (osc_is_running(Gmode10))
466 OscAng20 += FmPhase20;
467
468 /* mmm - dac write goes here and does not stop the processing (probably makes no diff) */
469 if (osc_run(Gmode10) == 2)
470 {
471 dac_write(fm, g->GO & 0xf); /* in this case, we need the integer value of GO */
472 return;
473 }
474
475 /* probably should be osc_mode(Gmode10) == SUMCOS */
476 if ((osc_mode(Gmode10) != SIN_K) &&
477 (osc_mode(Gmode10) != SIN_FM))
478 {
479 SinAdr = (Phase20 * NumCos11); /* was & 0xfff) << 2) + 1 */
480 CscAdr = Phase20;
481 if (fmod(CscAdr, 1.0) != 0.0)
482 temp = sin(M_PI * SinAdr) / sin(M_PI * CscAdr); /* was (1 << 13)) */
483 else temp = (double)NumCos11;
484 }
485 else
486 {
487 SinAdr = Phase20; /* was >> 6) | 1 */
488 temp = sin(M_PI * SinAdr);
489 }
490
491 TblOut13 = temp / (double)(1 << CosScl4);
492
493 switch (osc_mode(Gmode10))
494 {
495 case SUMCOS: case SIN_K: case SIN_FM:
496 OscOut13 = TblOut13;
497 break;
498
499 case SAWTOOTH:
500 OscOut13 = fmod(Phase20, 2.0) - 1.0;
501 break;
502
503 case SQUARE:
504 if (fmod(Phase20, 2.0) < 1.0)
505 OscOut13 = -0.5;
506 else OscOut13 = 0.5;
507 break;
508
509 case PULSE:
510 /* pulse mode was primarily used for triggered noise */
511 if ((OscAng20 >= 2.0) || (OscAng20 < -2.0))
512 {
513 OscAng20 = fmod(OscAng20, 2.0);
514 OscOut13 = 0.5;
515 }
516 else OscOut13 = 0.0;
517 break;
518 }
519
520 CurAmp12 = CurAmp24;
521
522 if (env_is_running(Gmode10))
523 {
524 double old_amp;
525 old_amp = CurAmp24;
526 CurAmp24 += (AmpSwp20 / 32.0); /* was 16.0 */ /* mmm - don't know why 32 but it seems to be more accurate than 16 */
527 /*
528 The envelope side of the generator can be sticky, which means
529 that rather than overflow it will stay at the last value it attained
530 before it would have overflowed; or it can be free, in which case it
531 wraps around.
532
533 Transitions between run modes can be accomplished in various ways.
534 1) A command can output a new GMODE.
535 2) A MISC command can specify "clear all pause bits", which
536 will cause any generator in run mode 0001 to change to
537 mode 1111.
538 3) A MISC command can specify "clear all wait bits", which
539 will cause any generator in run mode 1001 to change to
540 mode 1111.
541 4) If the envelope side of a generator in run mode 1101
542 overflows, that generator goes to run mode 1001.
543 5) A generator in run mode 1001 will go to run mode 1101 if
544 on the same pass the preceding generator (the one
545 whose generator number is one less) caused a
546 trigger (was in run mode 1110 or 1101 and envelope
547 overflowed).
548 */
549 if ((CurAmp24 > 1.0) || (CurAmp24 < 0.0)) /* if ((BIT(CurAmp24, 23) != BIT(old_amp, 23)) && (BIT(CurAmp24, 22) == BIT(AmpSwp20, 19))) */
550 {
551 /* overflow */
552 if (osc_run(Gmode10) == 15) /* "running A" */
553 CurAmp24 = old_amp;
554 else
555 {
556 if (osc_run(Gmode10) == 13) /* "running C" */
557 {
558 set_osc_run(gen, 9);
559 if (osc_run(gens[gen + 1]->GMODE) == 9)
560 set_osc_run(gen + 1, 13);
561 }
562 else
563 {
564 if ((osc_run(Gmode10) == 14) && /* "running B" */
565 (osc_run(gens[gen + 1]->GMODE) == 9))
566 set_osc_run(gen + 1, 13);
567 }
568 }
569 }
570 }
571
572 if ((osc_env(Gmode10) == L_PLUS_2_TO_MINUS_Q) ||
573 (osc_env(Gmode10) == L_MINUS_2_TO_MINUS_Q))
574 NewAmp12 = pow(2.0, -16.0 * CurAmp12);
575 else NewAmp12 = CurAmp12; /* was / 4 */ /* mmm - no scaling called for here */
576
577 /* I think this matches the spec:
578 * if temp6 is 0, then 2^(-temp6) is 1, the specs say #b111111111101,
579 * which assuming 12 bit unsigned fractions is 4093/4096,
580 * if temp6 is #b000100000000 (256), 2^(-temp6) is #b011111111110,
581 * which is .5 (fractional) so we really want 2^(-16*temp6) = 2^-1
582 */
583
584 /* in the notes: "The scaling involved is a left shift of temp6 by 4 bits".
585 * This scaling matters in FM since it is a multiplier on the index, and in pluck.
586 */
587
588 if ((osc_env(Gmode10) == L_PLUS_Q) ||
589 (osc_env(Gmode10) == L_PLUS_2_TO_MINUS_Q))
590 Env12 = AmpOff12 + NewAmp12;
591 else Env12 = AmpOff12 - NewAmp12;
592
593 OscOut13 *= Env12;
594 if (adding_to_sum(Gmode10))
595 {
596 if (osc_run(Gmode10) != 7)
597 {
598 /* "If GS is 0, the high-order 19 bits
599 of the rounded product are taken, right-adjusted with sign
600 extended; if GS is 1, the high-order 20 bits of the rounded
601 product are taken."
602 */
603 if (g->GS == 0)
604 gen_outs[OutSum6] += OscOut13 / 2.0; /* mmm - right-shifted high order 19 bits so divide by 2 */
605 else gen_outs[OutSum6] += OscOut13; /* mmm - no shift, so leave value alone */
606 }
607 else
608 {
609 /* read-data: assume we're reading floats from a raw file */
610 if (read_data_file)
611 {
612 float read_data_value;
613 fread((void *)(&read_data_value), 4, 1, read_data_file);
614 gen_outs[OutSum6] = OscOut13 + read_data_value; /* was * 2 */
615 /*
616 "If the run mode
617 specifies adding into sum memory, Temp9 is added into the sum
618 memory location designated by GSUM; except that in run mode
619 0111, the product is added to the next read-data item from the
620 CPU and the sum replaces the contents of the sum memory
621 location addressed."
622 */
623 }
624 else
625 {
626 if (!read_data_warned)
627 {
628 fprintf(stderr, "read data?!?\n");
629 read_data_warned = true;
630 }
631 }
632 }
633 }
634 }
635
636
637 /* ---------------------------------------- modifier processing ---------------------------------------- */
638
639 /*
640 * Each modifier has the following numeric parameters.
641 * M0 (30 bits) coefficient
642 * M1 (30 bits) other coefficient
643 * L0 (20 bits) running term
644 * L1 (20 bits) other running term
645 * MIN (8 bits) address in sum memory where modifier reads "A" data
646 * MRM (8 bits) address in sum memory where modifier reads "B" data
647 * MIN, MRM = QQAAAAAA
648 * QQ:
649 * 00 generator-last-pass quadrant
650 * 01 modifier-last-pass quadrant
651 * 10 modifier-this-pass quadrant
652 * 11 (reserved)
653 * AAAAAA: sum address within quadrant
654 * MSUM (7 bits) result address in sum memory
655 * MSUM = RAAAAAA
656 * R: 0 add to sum
657 * 1 replace sum
658 * AAAAAA: sum address in modifier-this-pass quadrant
659 */
660
print_mod_read_name(int m)661 static void print_mod_read_name(int m)
662 {
663 char *mem_names[4] = {"gen-ins", "mod-ins", "mod-outs", "oops"};
664 fprintf(stderr, "%s[", mem_names[(m >> 6) & 0x3]);
665 if (((m & 0x3f) == 0) && (((m >> 6) & 0x3) != 0))
666 fprintf(stderr, "zero");
667 else fprintf(stderr, "%d", m & 0x3f);
668 fprintf(stderr, "]");
669 }
670
671
mod_read(int addr)672 static double mod_read(int addr)
673 {
674 int QQ, A;
675 A = addr & 0x3f;
676 QQ = LDB(addr, 2, 6);
677 switch (QQ)
678 {
679 case 0: return(gen_ins[A]);
680 case 1: return(mod_ins[A]);
681 case 2: return(mod_outs[A]);
682
683 case 3:
684 /* "reserved", but it seems to happen in MARS.SAM, and Pete says:
685 *
686 * "Thanks to Al Kossow of the Computer History Museum for putting scans
687 * of the (preliminary) synthesizer schematics and the theory-of-
688 * operation manual up on bitsavers.org.
689 *
690 * It appears that QQ=3 will work the same as QQ=1, i.e. modifier last
691 * pass quadrant."
692 */
693 return(mod_ins[A]);
694 }
695
696 return(0);
697 }
698
699
mod_write(int addr,double val)700 static void mod_write(int addr, double val)
701 {
702 int R, AAAAAA;
703
704 if (isnan(val))
705 {
706 fprintf(stderr, "write %d %d NaN!\n", addr >> 6, addr & 0x3f);
707 }
708 AAAAAA = addr & 0x3f;
709 R = BIT(addr, 6);
710 if (R == 0)
711 mod_outs[AAAAAA] += val;
712 else mod_outs[AAAAAA] = val;
713 }
714
715 /*
716 * MMODE (9 bits) modifier mode
717 * MMODE = MMMMMAABB
718 * AA: scale of second multiplication
719 * BB: scale of first multiplication
720 * For fraction multiplications:
721 * 00: x 1
722 * 01: x 2
723 * 10: x 4
724 * 11: x 8
725 * For integer multiplications:
726 * 00: x 1/4
727 * 01: x 1/2
728 * 10: x 1
729 * 11: x 2
730 * A multiplication involving parameter M1 will be the first
731 * multiplication; one involving M0 will be the second.
732 *
733 * MMMMM: function
734 * 00000: inactive
735 * 00010: uniform noise
736 * 00011: triggered uniform noise
737 * 00100: latch
738 * 00110: threshold
739 * 00111: invoke delay unit
740 *
741 * 01000: two poles
742 * 01001: two poles, M0 variable
743 * 01011: two poles, M1 variable
744 * 01100: two zeros
745 * 01101: two zeros, M0 variable
746 * 01111: two zeros, M1 variable
747 *
748 * 10000: integer mixing
749 * 10001: one pole
750 * 10100: mixing
751 * 10110: one zero
752 *
753 * 11000: four-quadrant multiplication
754 * 11001: amplitude modulation
755 * 11010: maximum
756 * 11011: minimum
757 * 11100: signum
758 * 11101: zero-crossing pulser
759 *
760 * others: (reserved)
761 */
762
763 #define mod_mode(M) ((M >> 4) & 0x1f)
764 #define M_INACTIVE 0
765 #define M_NOISE 2
766 #define M_TRIGGERED_NOISE 3
767 #define M_LATCH 4
768 #define M_THRESHOLD 6
769 #define M_DELAY 7
770 #define M_TWO_POLE 8
771 #define M_TWO_POLE_M0 9
772 #define M_TWO_POLE_M1 11
773 #define M_TWO_ZERO 12
774 #define M_TWO_ZERO_M0 13
775 #define M_TWO_ZERO_M1 15
776 #define M_INTEGER_MIXING 16
777 #define M_ONE_POLE 17
778 #define M_MIXING 20
779 #define M_ONE_ZERO 22
780 #define M_MULTIPLY 24
781 #define M_AMP_MOD 25
782 #define M_MAX 26
783 #define M_MIN 27
784 #define M_SIGNUM 28
785 #define M_ZERO_CROSS 29
786
787 static double delay_read(int dly);
788 static void delay_write(int dly, double val);
789
process_mod(int mod)790 static void process_mod(int mod)
791 {
792 modifier *m;
793 int mode, IS;
794 double S, A, B, tmp0, tmp1;
795
796 m = mods[mod];
797 mode = mod_mode(m->MMODE);
798 if (mode == M_INACTIVE)
799 {
800 /* technically, mod_write(m->MSUM, 0.0) which might be in "replace" mode if BIT(m->MSUM, 6) is not 0 */
801 return;
802 }
803
804 A = mod_read(m->MIN);
805 B = mod_read(m->MRM);
806
807 switch (mode)
808 {
809 case M_INACTIVE:
810 /* 00000: inactive. S := 0
811 */
812 break;
813
814 case M_NOISE:
815 /* 00010: uniform noise. S := L0 + L1*M0 (integer multiply, low-order
816 * 20 bits of product used; overflow ignored); L1 := S
817 *
818 * see below -- I don't think this is correct.
819 */
820 /* IS = (m->L0 + (m->L1 * m->M0)) & 0xfffff; */
821
822 IS = (m->L0 + ((m->L1 * m->M0) >> 10)) & 0xfffff;
823 mod_write(m->MSUM, TWOS_20_TO_DOUBLE(IS));
824 m->L1 = IS;
825 break;
826
827 case M_TRIGGERED_NOISE:
828 /* 00011: triggered uniform noise. S := L0 + L1*M0 (integer multiply,
829 * low-order 20 bits of product used; overflow ignored);
830 * if B*M1 (integer multiply, low-order 20 bits of product
831 * used; overflow ignored) is not 0, L1 := S
832 */
833
834 /* IS = (m->L0 + (m->L1 * m->M0)) & 0xfffff; */
835 /* I'm getting an immediate fixed-point from the SAM files that used triggered noise! */
836 /* they used the M0 seed of 359035904, (L1: 204282), which immediately cycles. */
837 /* perhaps the spec is wrong... -- I'll try taking the middle bits */
838
839 IS = (m->L0 + ((m->L1 * m->M0) >> 10)) & 0xfffff;
840 mod_write(m->MSUM, TWOS_20_TO_DOUBLE(IS));
841 if ((B != 0.0) &&
842 (m->M1 != 0))
843 m->L1 = IS;
844 break;
845
846 case M_LATCH:
847 /* 00100: latch (sample and hold). S := L1; If B*M1 is not 0, L1 := A
848 * but in the errata:
849 * "BIL has discovered empirically that the modifier latch mode operation should actually read
850 * 00100: latch (sample and hold). S := L1; If B*M1 is not 0, L1 := A*M0"
851 */
852 mod_write(m->MSUM, m->f_L1);
853 if ((B * m->f_M1) != 0.0) m->f_L1 = A * m->f_M0;
854 break;
855
856 case M_THRESHOLD:
857 /* 00110: threshold. If A*M0 + L0 is less than 0, then S := 0;
858 * if A*M0 + L0 is equal to or greater than 0, then S := B*M1
859 */
860 tmp0 = A * m->f_M0 + m->f_L0;
861 if (tmp0 < 0.0)
862 mod_write(m->MSUM, 0.0);
863 else mod_write(m->MSUM, B * m->f_M1);
864 break;
865
866 case M_DELAY:
867 /* 00111: invoke delay unit.
868 * Unit # := MRM (low-order 5 bits);
869 * S := L0 + L1*M0; L0 := DM; Temp0 := A + DM*M1;
870 * L1 := Temp0; DM := Temp0
871 */
872 /* to handle table lookups, we need the integer side here */
873 /* fprintf(stderr, "d%d, m%d: %.4f = %.4f + %.4f * %.4f\n", m->MRM & 0x1f, mod, m->f_L0 + m->f_L1 * m->f_M0, m->f_L0, m->f_L1, m->f_M0); */
874
875 mod_write(m->MSUM, m->f_L0 + m->f_L1 * m->f_M0);
876 m->f_L0 = delay_read(m->MRM & 0x1f);
877 m->f_L1 = A + m->f_L0 * m->f_M1;
878 delay_write(m->MRM & 0x1f, m->f_L1);
879 break;
880
881 case M_TWO_POLE:
882 case M_TWO_POLE_M0:
883 case M_TWO_POLE_M1:
884 /* 01000: two poles. S := L1*M1 + L0*M0 + A; L0 := L1; L1 := S
885 *
886 * 01001: two poles, M0 variable. S := L1*M1 + L0*M0 + A; L0 := L1; L1 := S; M0 := M0 + B
887 *
888 * 01011: two poles, M1 variable. S := L1*M1 + L0*M0 + A; L0 := L1; L1 := S; M1 := M1 + B
889 */
890 tmp0 = m->f_L1 * m->f_M1;
891 tmp1 = m->f_L0 * m->f_M0;
892 S = tmp0 + tmp1 + A; /* divide A by 1024.0 here probably */
893 mod_write(m->MSUM, S);
894 m->f_L0 = m->f_L1;
895 m->f_L1 = S;
896 if (mode == M_TWO_POLE_M0)
897 m->f_M0 += (B / 1024.0);
898 /* "when a quantity is added to M0 or M1 it is added right-justified, with sign extended"
899 * does that include "A" above? I think it does... (see one and two_zero below).
900 */
901 if (mode == M_TWO_POLE_M1)
902 m->f_M1 += (B / 1024.0);
903 break;
904
905 case M_TWO_ZERO:
906 case M_TWO_ZERO_M0:
907 case M_TWO_ZERO_M1:
908 /* 01100: two zeros. S := L1*M1 + L0*M0 + A; L0 := L1; L1 := A
909 *
910 * 01101: two zeros, M0 variable. S := L1*M1 + L0*M0 + A; L0 := L1; L1 := A; M0 := M0 + B
911 *
912 * 01101: two zeros, M0 variable. S := L1*M1 + L0*M0 + A; L0 := L1; L1 := A; M1 := M1 + B
913 */
914 tmp0 = m->f_L1 * m->f_M1;
915 tmp1 = m->f_L0 * m->f_M0;
916 mod_write(m->MSUM, tmp0 + tmp1 + A); /* divide A by 1024.0 here probably */
917 m->f_L0 = m->f_L1;
918 m->f_L1 = A / 1024.0;
919 if (mode == M_TWO_ZERO_M0)
920 m->f_M0 += (B / 1024.0);
921 if (mode == M_TWO_ZERO_M1)
922 m->f_M1 += (B / 1024.0);
923 break;
924
925 case M_INTEGER_MIXING:
926 /* 10000: integer mixing. S := A*M0 + B*M1 (integer multiply, low-order
927 * 20 bits of product used; overflow ignored)
928 */
929 /* I don't remember how we used this -- I'll assume the M's are the ints */
930 mod_write(m->MSUM, A * m->M0 + B * m->M1);
931 break;
932
933 case M_MIXING:
934 /* 10100: mixing. S := A*M0 + B*M1
935 */
936 mod_write(m->MSUM, A * m->f_M0 + B * m->f_M1);
937 break;
938
939 case M_ONE_POLE:
940 /* 10001: one pole. S := L1*M1 + B*M0; L1 := S
941 *
942 * but in the errata:
943 * "DAJ - It seems that the modifier mode one pole is really
944 * 10001: one pole. S := L1*M1 + B*L0; L1 := S"
945 *
946 * but I think that is incorrect; old reverbs are definitely using the spec form of the 1-pole filter
947 */
948 tmp0 = m->f_L1 * m->f_M1;
949 /* tmp1 = B * m->f_L0; */
950 tmp1 = B * m->f_M0;
951
952 m->f_L1 = tmp0 + tmp1;
953 mod_write(m->MSUM, m->f_L1);
954 break;
955
956 case M_ONE_ZERO:
957 /* 10110: one zero. S := L1*M1 + L0*M0; L0 := L1; L1 := A
958 */
959 tmp0 = m->f_L1 * m->f_M1;
960 tmp1 = m->f_L0 * m->f_M0;
961 m->f_L0 = m->f_L1;
962 m->f_L1 = A / 1024.0;
963 mod_write(m->MSUM, tmp0 + tmp1);
964 break;
965
966 case M_MULTIPLY:
967 /* 11000: four-quadrant multiplication. S := L1*M1; L1 := A*B
968 */
969 mod_write(m->MSUM, m->f_L1 * m->f_M1);
970 m->f_L1 = A * B;
971 break;
972
973 case M_AMP_MOD:
974 /* 11001: amplitude modulation. S := L1*M1; L1 := A * ((B+1)/2)
975 * (The term ((B+1)/2) interprets B as a signed two's-complement
976 * fraction ranging in value from -1 to +1-epsilon.)
977 */
978 mod_write(m->MSUM, m->f_L1 * m->f_M1);
979 m->f_L1 = A * (B + 1.0) * 0.5;
980 break;
981
982 case M_MAX:
983 /* 11010: maximum. S := max (A*M0, B*M1)
984 */
985 tmp0 = A * m->f_M0;
986 tmp1 = B * m->f_M1;
987 mod_write(m->MSUM, (tmp0 > tmp1) ? tmp0 : tmp1);
988 break;
989
990 case M_MIN:
991 /* 11011: minimum. S := min (A*M0, B*M1)
992 */
993 tmp0 = A * m->f_M0;
994 tmp1 = B * m->f_M1;
995 mod_write(m->MSUM, (tmp0 < tmp1) ? tmp0 : tmp1);
996 break;
997
998 case M_SIGNUM:
999 /* 11100: signum. If A*M0 is less than B*M1, then S := -1 (integer)
1000 * if A*M0 equals B*M1, then S := 0;
1001 * if A*M0 is greater than B*M1, the S := 1 (integer)
1002 */
1003 tmp0 = A * m->f_M0;
1004 tmp1 = B * m->f_M1;
1005 if (tmp0 < tmp1) mod_write(m->MSUM, TWOS_20_TO_DOUBLE(-1));
1006 else if (tmp0 == tmp1) mod_write(m->MSUM, 0.0);
1007 else mod_write(m->MSUM, TWOS_20_TO_DOUBLE(1));
1008 break;
1009
1010 case M_ZERO_CROSS:
1011 /* 11101: zero-crossing pulser. Temp0 := B*M0; Temp1 := L1*M1;
1012 * if Temp1 is not 0 and either Temp0 is 0 or Temp0*Temp1 is
1013 * negative then S := -epsilon, else S := 0; L1 := Temp0
1014 * (The term -epsilon is a binary number with all bits set.)
1015 */
1016 tmp0 = B * m->f_M0;
1017 tmp1 = m->f_L1 * m->f_M0;
1018 if ((tmp1 != 0) &&
1019 ((tmp0 == 0) || (tmp0 * tmp1 < 0)))
1020 mod_write(m->MSUM, TWOS_20_TO_DOUBLE(-1));
1021 m->f_L1 = tmp0;
1022 break;
1023
1024 default:
1025 fprintf(stderr, "reserved modifier mode?\n");
1026 break;
1027 }
1028 }
1029
1030
1031
1032 /* ---------------------------------------- delay processing ---------------------------------------- */
1033
1034 /* Each delay unit has the following numeric parameters.
1035 *
1036 * P mode (4 bits). The mode is interpreted as follows:
1037 * mode: 0000 inactive
1038 * 1000 delay line
1039 * 1010 table look-up
1040 * 1011 table look-up, argument rounded
1041 * 1100 delay tap
1042 * others: (reserved)
1043 */
1044
1045 #define D_INACTIVE 0
1046 #define D_LINE 8
1047 #define D_TABLE_LOOKUP 10
1048 #define D_TABLE_LOOKUP_ROUNDED 11
1049 #define D_TAP 12
1050
1051 /*
1052 * Z unit length (16 bits) or binary scale factor (4 bits).
1053 * In delay line and delay tap modes, Z gives 1 less than the
1054 * total number of locations in delay memory used by the delay
1055 * unit, i.e. the index of the last delay memory address for
1056 * this unit. In table look-up modes, the low-order four bits
1057 * of Z specify the number of binary places that the argument
1058 * is shifted to the right before it is used to address the
1059 * memory; if rounding is specified, the address after shifting
1060 * is incremented by 1 if the most-significant bit shifted out
1061 * was a 1.
1062 *
1063 * Y index (16 bits). In delay line and delay tap modes, this is the
1064 * running index on the memory area for the unit.
1065 *
1066 * X base address (16 bits). The base address is the lowest-numbered
1067 * delay memory location used by this unit.
1068 *
1069 * In inactive mode, delay memory is not modified and the unit
1070 * returns indeterminate results. Delay units not accommodated due
1071 * to the number of ticks in a pass act as if in the inactive mode.
1072 * If the number of processing ticks is 4*n + m where m is 1, 2, or 3,
1073 * delay unit number n should be put in the inactive mode.
1074 *
1075 * In delay line mode, a 20-bit data word is received from
1076 * the modifier that calls for the delay unit, and another 20-bit
1077 * word is sent to it. The word received is put into the next slot
1078 * in the delay line. It will be retrieved and sent back to the
1079 * modifier Z+3 passes later. In delay tap mode, a word is sent to
1080 * the modifier but delay memory is not written into.
1081 *
1082 * In table look-up mode, the 20-bit data word received
1083 * from the modifier is shifted to the right Z bits, bringing in zeros,
1084 * and the right 16 bits of the result are used to address the memory
1085 * area assigned to the unit. The 20-bit word in the addressed memory
1086 * location is returned to the modifier three passes later.
1087 */
1088
1089 static bool table_read_warned = false, table_write_warned = false;
1090
delay_read(int dly)1091 static double delay_read(int dly)
1092 {
1093 delay *d;
1094 d = dlys[dly];
1095 switch (d->P)
1096 {
1097 case D_INACTIVE:
1098 return(0.0);
1099
1100 case D_LINE:
1101 case D_TAP:
1102 /* return the value with a hidden 2 sample delay (Z+3 == total delay length + 2) */
1103 #if 0
1104 return(delay_memory[d->X + d->Y]);
1105 #else
1106 {
1107 /* I originally thought this was making a raspy or crackling sound in the reverbs, but now I don't hear it (bil) */
1108 double val;
1109 val = d->xd2;
1110 d->xd2 = d->xd1;
1111 d->xd1 = delay_memory[d->X + d->Y];
1112 return val;
1113 }
1114 #endif
1115
1116 case D_TABLE_LOOKUP:
1117 case D_TABLE_LOOKUP_ROUNDED:
1118 {
1119 int Z_shift, dY;
1120 if (!table_read_warned)
1121 {
1122 fprintf(stderr, "table lookup read is unlikely to work.\n");
1123 table_read_warned = true;
1124 }
1125 Z_shift = d->Z & 0xf;
1126 dY = (d->I >> Z_shift) & 0xffff;
1127 return(delay_memory[d->X + dY]);
1128 }
1129 }
1130 return(0);
1131 }
1132
1133
delay_write(int dly,double val)1134 static void delay_write(int dly, double val)
1135 {
1136 delay *d;
1137 d = dlys[dly];
1138 switch (d->P)
1139 {
1140 case D_INACTIVE:
1141 case D_TAP:
1142 break;
1143
1144 case D_LINE:
1145 delay_memory[d->X + d->Y] = val;
1146 break;
1147
1148 case D_TABLE_LOOKUP:
1149 case D_TABLE_LOOKUP_ROUNDED:
1150 if (!table_write_warned)
1151 {
1152 fprintf(stderr, "table lookup write is unlikely to work.\n");
1153 table_write_warned = true;
1154 }
1155 d->I = DOUBLE_TO_TWOS_20(val); /* can this work? */
1156 break;
1157 }
1158 }
1159
1160
process_dly(int dly)1161 static void process_dly(int dly)
1162 {
1163 delay *d;
1164 d = dlys[dly];
1165 d->Y += 1;
1166 if (d->Y > d->Z) /* unit size - 1 so not >= ? */
1167 d->Y = 0;
1168 }
1169
1170
1171 /* ---------------------------------------- run! ---------------------------------------- */
1172
1173 static void dump_patch(void);
1174
linger(int time)1175 static void linger(int time)
1176 {
1177 /* process each sample ("pass") until pass == time */
1178 /* but linger was a 20-bit number, so it wrapped around I believe, so pass should be mod 2^20? */
1179
1180 if (!snd_file)
1181 {
1182 fprintf(stderr, "no ticks setting found!\n");
1183 exit(0);
1184 }
1185
1186 if (time < pass)
1187 pass = pass - (1 << 20);
1188
1189 /* old SAM files had endless strings of lingers at the end generating enormous empty sound files, but
1190 *
1191 * mmm - this was causing the long trailing reverb of some of my files to be cut off.
1192 */
1193
1194 if ((FLUSH_TRAILING_LINGERS) &&
1195 ((total_commands - current_command) < 100) &&
1196 (total_commands > 1000) &&
1197 ((time - pass) > (6 * srate)))
1198 {
1199 fprintf(stderr, "ignore trailing %d sample (%.3f second) linger (%d)\n",
1200 time - pass, (double)(time - pass) / (double)srate, total_commands - current_command);
1201 pass = time;
1202 return;
1203 }
1204
1205 while (pass < time)
1206 {
1207 /* run through all available ticks, processing gen+mod+dly,
1208 * then write accumulated dac_outs, clear, update memories (this-pass -> last-pass),
1209 * and increment pass
1210 */
1211 int i, tick, gen = 0, mod = 0, dly = 0;
1212
1213 for (tick = 0; tick < processing_ticks; tick++)
1214 {
1215 /* given the timing info I'll simplify a bit and run 1 gen per tick, 1 mod every 2 ticks, and 1 delay every 4 ticks */
1216 if (gen < GENERATORS)
1217 process_gen(gen++);
1218
1219 /* I'm guessing... */
1220 if (((tick & 1) == 0) &&
1221 (mod < MODIFIERS))
1222 process_mod(mod++);
1223
1224 if (((tick & 3) == 0) &&
1225 (dly < DELAYS))
1226 process_dly(dly++);
1227 }
1228
1229 if (dump_patch_at == samples)
1230 dump_patch();
1231
1232 for (i = 0; i < SUM_MEMORY_SIZE; i++)
1233 {
1234 if (fabs(gen_ins[i]) > peak_gen_ins[i])
1235 peak_gen_ins[i] = fabs(gen_ins[i]);
1236 prev_gen_ins[i] = gen_ins[i];
1237 gen_ins[i] = gen_outs[i];
1238 gen_outs[i] = 0.0;
1239
1240 if (fabs(mod_ins[i]) > peak_mod_ins[i])
1241 peak_mod_ins[i] = fabs(mod_ins[i]);
1242 prev_mod_ins[i] = mod_ins[i];
1243 mod_ins[i] = mod_outs[i];
1244 mod_outs[i] = 0.0;
1245 }
1246
1247 fwrite(dac_out, 4, 4, snd_file);
1248 samples++;
1249 for (i = 0; i < 4; i++)
1250 {
1251 if (fabs(dac_out[i]) > dac_out_peak[i])
1252 dac_out_peak[i] = fabs(dac_out[i]);
1253 dac_out[i] = 0.0;
1254 }
1255 pass++;
1256
1257 if (samples == TOTAL_SAMPLES)
1258 all_done();
1259 }
1260 }
1261
1262
1263 /* ---------------------------------------- commands ---------------------------------------- */
1264
1265 /*
1266 * -----------------------------------------------------------------
1267 * : (20) data : 0 0 0 0 0: RR : x x: W: P: S:
1268 * -----------------------------------------------------------------
1269 * MISC
1270 * RR: 00 no effect
1271 * 01 load DX from data
1272 * 10 load TTL buffer A from left 16 bits of data
1273 * 11 load TTL buffer B from left 16 bits of data
1274 * set analog output filters from right 4 bits of data:
1275 * 01xx Mode 0
1276 * 00nn Mode 1, frequency f0, f1, f2, or f3 according
1277 * to nn
1278 * W: if 1, clear all wait bits
1279 * P: if 1, clear all pause bits
1280 * S: if 1, stop clock
1281 */
1282
misc_command(int cmd)1283 static void misc_command(int cmd)
1284 {
1285 int data, RR, W, P, S;
1286 char *RR_name[4] = {"noop", "load DX", "TTL-A", "TTL-B"};
1287
1288 data = LDB(cmd, 20, 12);
1289 RR = LDB(cmd, 2, 5);
1290 W = BIT(cmd, 2);
1291 P = BIT(cmd, 1);
1292 S = BIT(cmd, 0);
1293
1294 if (describe_commands)
1295 fprintf(stderr, "sam: %d, %s%s%s%s\n",
1296 data,
1297 RR_name[RR],
1298 (W == 1) ? "" : ", clear waits",
1299 (P == 1) ? "" : ", clear pauses",
1300 (S == 1) ? "" : ", stop clock");
1301
1302 if (RR == 1) DX = data;
1303
1304 if (W == 1)
1305 {
1306 /* cause any generator in run mode 1001 to change to mode 1111 */
1307 int i;
1308 for (i = 0; i < GENERATORS; i++)
1309 if ((gens[i]) && (osc_run(gens[i]->GMODE) == 9))
1310 set_osc_run(i, 15);
1311 }
1312
1313 if (P == 1)
1314 {
1315 /* cause any generator in run mode 0001 to change to mode 1111 */
1316 int i;
1317 for (i = 0; i < GENERATORS; i++)
1318 if ((gens[i]) && (osc_run(gens[i]->GMODE) == 1))
1319 set_osc_run(i, 15);
1320 }
1321
1322 if (REPORT_BAD_COMMANDS)
1323 {
1324 if ((S == 1) &&
1325 ((total_commands - current_command) > 1000))
1326 fprintf(stderr, "sam: %x: stop clock?\n", cmd);
1327 }
1328 }
1329
1330
1331 /*
1332 * -----------------------------------------------------------------
1333 * : (16) data :(4)data: 0 0 0 0 1: U U: (5) unit # :
1334 * -----------------------------------------------------------------
1335 * DLY X, Y, Z
1336 * UU: 00 X 16 bits base address; clear Y
1337 * 01 Y 16 bits one's complement of index
1338 * 10 Z,P 16 bits delay unit size minus 1, or scale (low
1339 * 4 bits of 16); 4 bits mode
1340 * 11 (unused)
1341 */
1342
P_name(int P)1343 static const char *P_name(int P)
1344 {
1345 switch (P)
1346 {
1347 case D_INACTIVE: return("inactive");
1348 case D_LINE: return("line");
1349 case D_TAP: return("tap");
1350 case D_TABLE_LOOKUP: return("table");
1351 case D_TABLE_LOOKUP_ROUNDED: return("rtable");
1352 default: return("unknown");
1353 }
1354 }
1355
1356
dly_command(int cmd)1357 static void dly_command(int cmd)
1358 {
1359 int unit, UU, data_4, data_16;
1360 delay *d;
1361 char *UU_name[4] = {"set base, clear index", "set index", "set size", "un-used!"};
1362
1363 unit = (cmd & 0x1f);
1364 UU = LDB(cmd, 2, 5);
1365
1366 if (UU == 3)
1367 {
1368 fprintf(stderr, "unknown delay command!\n");
1369 return;
1370 }
1371
1372 data_4 = LDB(cmd, 4, 12);
1373 data_16 = LDB(cmd, 16, 16);
1374
1375 d = dlys[unit];
1376 switch (UU)
1377 {
1378 case 0:
1379 d->X = data_16;
1380 d->Y = 0;
1381 break;
1382
1383 case 1:
1384 d->Y = data_16;
1385 break;
1386
1387 case 2:
1388 d->Z = data_16;
1389 d->P = data_4;
1390 break;
1391 }
1392
1393 if (describe_commands)
1394 {
1395 fprintf(stderr, "d%d %s", unit, UU_name[UU]);
1396 if (UU == 0)
1397 fprintf(stderr, ": X: %d", d->X);
1398 else
1399 {
1400 if (UU == 1)
1401 fprintf(stderr, ": Y: %d", d->Y);
1402 else fprintf(stderr, ": Z: %d, P: %s", d->Z, P_name(d->P));
1403 }
1404 fprintf(stderr, "\n");
1405 }
1406 }
1407
1408
1409 /*
1410 * -----------------------------------------------------------------
1411 * : (20) data : 0 0 0 1 0: x x: T T: x x x:
1412 * -----------------------------------------------------------------
1413 * TIMER
1414 * TT: 00 no effect
1415 * 10 Linger: process no further commands until pass counter
1416 * equals data
1417 * 11 clear pass counter, then Linger as for 10
1418 * 01 set pass counter from data
1419 */
1420
timer_command(int cmd)1421 static void timer_command(int cmd)
1422 {
1423 int data, TT;
1424 char *TT_name[4] = {"noop", "set pass", "linger", "clear pass and linger"};
1425
1426 TT = LDB(cmd, 2, 3);
1427 data = LDB(cmd, 20, 12);
1428
1429 if (describe_commands)
1430 fprintf(stderr, "sam %s: %d at sample %d %.4f\n", TT_name[TT], data, samples, (double)samples / (double)srate);
1431
1432 switch (TT)
1433 {
1434 case 0:
1435 break;
1436 case 1:
1437 pass = data;
1438 break;
1439 case 2:
1440 linger(data);
1441 break;
1442 case 3:
1443 pass = 0;
1444 linger(data);
1445 break;
1446 }
1447 }
1448
1449
1450 /*
1451 * -----------------------------------------------------------------
1452 * : xxx xxx xxx x : (10) data : 0 0 0 1 1: x x: 0: Q: x x x:
1453 * -----------------------------------------------------------------
1454 * TICKS
1455 * Q: 0 designate highest-numbered processing tick per pass
1456 * (should not exceed 255 [See appendix - DAJ])
1457 * 1 designate next-to-highest-numbered tick (processing
1458 * plus overhead plus update) per pass
1459 */
1460 static bool bit_31_warned = false;
1461
ticks_command(int cmd)1462 static void ticks_command(int cmd)
1463 {
1464 int Q, data, bit_31;
1465 char *Q_name[2] = {"set highest processing tick", "set highest tick"};
1466
1467 bit_31 = BIT(cmd, 4);
1468 Q = BIT(cmd, 3);
1469 data = LDB(cmd, 10, 12);
1470
1471 if (REPORT_BAD_COMMANDS)
1472 {
1473 if (bit_31 != 0)
1474 {
1475 if (!bit_31_warned)
1476 {
1477 fprintf(stderr, "ticks bit 31 is on?\n");
1478 bit_31_warned = true;
1479 }
1480 return; /* what is going on here? */
1481 }
1482 }
1483
1484 if (data != 0) /* used at end of some box sequences, but that confuses srate */
1485 {
1486 if (Q == 0)
1487 processing_ticks = data + 1; /* mmm - data is highest numbered processing tick per pass, so processing_ticks is 1 greater. */
1488 else
1489 {
1490 if (srate <= 1)
1491 {
1492 /* mmm - srate can now be set from the command line in certain cases. I had some weird tick settings for some reason.
1493 * mmm - highest_tick_per_pass is actually being set here to the max *number* of ticks per pass, including overhead
1494 */
1495 highest_tick_per_pass = data + 2; /* why isn't this 9? */
1496
1497 /* "It's not clear from the documentation, so to clarify: On the # TICKS
1498 * command, the number to be supplied for Q=1 is the total number of ticks
1499 * per pass minus 2. (TVR - 7 August 1984)"
1500 */
1501
1502 /* it's a 10 bit field, and higher bits are ignored, so the slowest we
1503 * can run is 5010Hz or thereabouts
1504 */
1505
1506 if (highest_tick_per_pass > GENERATORS)
1507 highest_tick_per_pass = GENERATORS; /* mmm - could it not be higher in some cases? */
1508
1509 srate = (int)(1000000000.0 / (double)(highest_tick_per_pass * 195));
1510 }
1511 else
1512 {
1513 highest_tick_per_pass = (1000000000.0 / (double)srate / 195.0);
1514 }
1515 }
1516 }
1517
1518 if (describe_commands)
1519 {
1520 fprintf(stderr, "sam %s: %d", Q_name[Q], data);
1521 if (Q == 1)
1522 fprintf(stderr, " (%d Hz)", srate);
1523 fprintf(stderr, "\n");
1524 }
1525
1526 if ((data != 0) && (srate != 0))
1527 {
1528 if ((snd_file) && (samples == 0) && (Q == 1)) /* 2 tick commands at the start? */
1529 {
1530 fclose(snd_file); /* start over... */
1531 snd_file = NULL;
1532 }
1533
1534 if (snd_file == NULL)
1535 {
1536 /* now that we know the sampling rate, open the output file */
1537 int header_info[24] = {1179011410, 88, 1163280727, 1263424842,
1538 28, 0, 0, 0,
1539 0, 0, 0, 0,
1540 544501094, 16, 262147, 44100,
1541 705600, 2097168, 1635017060, 16,
1542 0, 0, 0, 0};
1543 header_info[15] = srate;
1544
1545 /* mmm - generate output filename based on input filename */
1546 {
1547 char *dot;
1548 int i, len;
1549 len = strlen(filename);
1550 output_filename = (char *)malloc(len + 1);
1551 strcpy(output_filename, filename);
1552 /* dot = strchr(output_filename, '.');
1553 * can be confused by ../test/TEST.SAM
1554 */
1555 for (i = len - 1; i > 0; i--)
1556 if (filename[i] == '.')
1557 {
1558 dot = (char *)(output_filename + i);
1559 break;
1560 }
1561 strcpy(dot + 1, "wav");
1562 snd_file = fopen(output_filename, "w");
1563 }
1564
1565 if (!snd_file)
1566 {
1567 fprintf(stderr, "can't open test.snd!\n");
1568 exit(0);
1569 }
1570 fwrite((void *)header_info, 4, 24, snd_file);
1571 }
1572 }
1573 }
1574
1575
1576 static int last_GMODE_command = 0;
1577
1578 /* GQ (24 bits) phi -- decay exponent
1579 * -----------------------------------------------------------------
1580 * GQ : (20) data : 0 0 1: E: (8) gen # :
1581 * -----------------------------------------------------------------
1582 *
1583 * E: 0 Q right-adjusted, sign extended
1584 * 1 Q left-adjusted, low bits from left of DX; clear DX
1585 */
1586
gq_command(int cmd)1587 static void gq_command(int cmd)
1588 {
1589 /* GQ is 24 bits */
1590 int data, E, gen, old_DX = 0, old_GQ;
1591 double old_f_GQ;
1592 generator *g;
1593 char *E_name[2] = {"right adjusted", "left adjusted + DX"};
1594
1595 gen = LDB(cmd, 8, 0);
1596 E = BIT(cmd, 8);
1597 data = LDB(cmd, 20, 12);
1598
1599 g = gens[gen];
1600 old_GQ = g->GQ;
1601 old_f_GQ = g->f_GQ;
1602
1603 /* spec says "sign extended" which makes me think this number is signed, but I think it is unsigned in exp modes */
1604 /* mmm - I also believe it is unsigned. */
1605 /* pete:
1606 * Hmm, it looks like it makes more sense to call it unsigned. Certainly
1607 * the multiplication of envelope times waveform treats the envelope as
1608 * unsigned (i.e. non-negative).
1609 */
1610
1611 if (E == 0)
1612 g->GQ = data; /* mmm */
1613 else
1614 {
1615 g->GQ = (data << 4) | ((DX >> 16) & 0xf); /* mmm */
1616 old_DX = DX;
1617 DX = 0;
1618 }
1619
1620 g->f_GQ = (double)(g->GQ) / (double)(1 << 24); /* mmm - proper scaling of unsigned value */
1621
1622 if (describe_commands)
1623 {
1624 if (E == 0)
1625 fprintf(stderr, "g%d amp: %s, %d %.4f\n", gen, E_name[E], g->GQ, g->f_GQ);
1626 else fprintf(stderr, "g%d amp: %s, %d = %d %.4f (DX: %d)\n", gen, E_name[E], data, g->GQ, g->f_GQ, old_DX);
1627 }
1628
1629 #if 0
1630 if ((gen_is_active(g)) &&
1631 (samples > last_GMODE_command))
1632 {
1633 if (REPORT_BAD_COMMANDS)
1634 fprintf(stderr, "sample %d (%.3f), command %d, stray amp: g%d %.4f from %.4f (last mode sample: %d)\n",
1635 samples, (double)samples / (double)srate, current_command,
1636 gen, g->f_GQ, old_f_GQ,
1637 last_GMODE_command);
1638 if (FLUSH_BAD_COMMANDS)
1639 {
1640 g->GQ = old_GQ;
1641 g->f_GQ = old_f_GQ;
1642 }
1643 }
1644 #endif
1645 }
1646
1647
1648 /* GJ (28 bits) omega -- oscillator frequency
1649 * -----------------------------------------------------------------
1650 * GJ : (20) data : 0 1 0: E: (8) gen # :
1651 * -----------------------------------------------------------------
1652 *
1653 * E: 0 J right-adjusted, sign extended
1654 * 1 J left-adjusted, low bits from left of DX; clear DX
1655 */
1656
gj_command(int cmd)1657 static void gj_command(int cmd)
1658 {
1659 /* GJ is 28 bits */
1660 int data, E, gen, old_DX = 0, old_GJ;
1661 double old_f_GJ;
1662 generator *g;
1663 char *E_name[2] = {"right adjusted", "left adjusted + DX"};
1664
1665 gen = LDB(cmd, 8, 0);
1666 E = BIT(cmd, 8);
1667 data = LDB(cmd, 20, 12);
1668
1669 g = gens[gen];
1670 old_GJ = g->GJ;
1671 old_f_GJ = g->GJ;
1672
1673 if (E == 0)
1674 g->GJ = TWOS_20(data);
1675 else
1676 {
1677 g->GJ = TWOS_28(((data << 8) + (DX >> 12))); /* need 28 - 20 = 8 bits? */
1678 old_DX = DX;
1679 DX = 0;
1680 }
1681
1682 g->f_GJ = DOUBLE_28(g->GJ);
1683
1684 if (describe_commands)
1685 {
1686 if (E == 0)
1687 fprintf(stderr, "g%d freq: %s, %d %.4f (%.4f Hz)\n", gen, E_name[E], g->GJ, g->f_GJ, g->f_GJ * 0.5 * srate);
1688 else fprintf(stderr, "g%d freq: %s (DX: %d), %d = %d %.4f (%.4f Hz)\n", gen, E_name[E], old_DX, data, g->GJ, g->f_GJ, g->f_GJ * 0.5 * srate);
1689 }
1690
1691 if ((gen_is_active(g)) &&
1692 (g->GJ != old_GJ) &&
1693 (samples > last_GMODE_command))
1694 {
1695 if (REPORT_BAD_COMMANDS)
1696 fprintf(stderr, "sample %d (%.3f), command %d, stray freq: g%d %.4f from %.4f (last mode sample: %d), data: %d\n",
1697 samples, (double)samples / (double)srate, current_command,
1698 gen, g->f_GJ * 0.5 * srate, DOUBLE_28(old_GJ) * 0.5 *srate,
1699 last_GMODE_command, data);
1700
1701 if (FLUSH_BAD_COMMANDS)
1702 {
1703 g->GJ = old_GJ;
1704 g->f_GJ = old_f_GJ;
1705 }
1706 }
1707 }
1708
1709
1710 /* GP (20 bits) delta -- decay rate
1711 * -----------------------------------------------------------------
1712 * GP : (20) data : 0 1 1 0: (8) gen # :
1713 * -----------------------------------------------------------------
1714 */
1715
gp_command(int cmd)1716 static void gp_command(int cmd)
1717 {
1718 /* GP is 20 bits */
1719 int data, gen;
1720 generator *g;
1721
1722 gen = LDB(cmd, 8, 0);
1723 data = LDB(cmd, 20, 12);
1724
1725 g = gens[gen];
1726 g->GP = TWOS_20(data);
1727 g->f_GP = DOUBLE_20(g->GP);
1728
1729 if (describe_commands)
1730 fprintf(stderr, "g%d amp change: %d (%.4f/sec), amp: %.4f\n", gen, g->GP, g->f_GP * srate, g->f_GQ);
1731 }
1732
1733
1734 /* GN (11 bits) number of cosines to be summed
1735 * GM (4 bits) binary scale of cosine or sum of cosines
1736 * GS (1 bit) whether to shift output when adding to sum memory
1737 * GN, -----------------------------------------------------------------
1738 * GM, :N:M:S S:x: (11) GN :(4) GM : 0 1 1 1: (8) gen # :
1739 * GS -----------------------------------------------------------------
1740 *
1741 * N: if 1, disable loading GN
1742 * M: if 1, disable loading GM
1743 * SS: 00 clear GS to 0
1744 * 01 set GS to 1
1745 * 10 no effect
1746 * 11 (reserved)
1747 */
1748
gn_command(int cmd)1749 static void gn_command(int cmd)
1750 {
1751 int N, M, SS, GN, GM, gen;
1752 generator *g;
1753 char *SS_name[4] = {", clear GS", ", set GS to 1", "", ", GS reserved?"};
1754
1755 gen = LDB(cmd, 8, 0);
1756 GM = LDB(cmd, 4, 12);
1757 GN = LDB(cmd, 11, 16);
1758 SS = LDB(cmd, 2, 28);
1759 M = BIT(cmd, 30);
1760 N = BIT(cmd, 31);
1761
1762 if (describe_commands)
1763 {
1764 if (N == 1)
1765 {
1766 if (M == 1)
1767 fprintf(stderr, "g%d sum-memory shift:%s\n", gen, SS_name[SS]);
1768 else fprintf(stderr, "g%d ncos scale: %d%s\n", gen, GM, SS_name[SS]);
1769 }
1770 else
1771 {
1772 if (M == 1)
1773 fprintf(stderr, "g%d ncos: %d%s\n", gen, GN, SS_name[SS]);
1774 else fprintf(stderr, "g%d ncos: %d%s, scale: %d\n", gen, GN, SS_name[SS], GM);
1775 }
1776 }
1777
1778 g = gens[gen];
1779 if (N == 0)
1780 g->GN = GN;
1781 if (M == 0)
1782 g->GM = GM;
1783
1784 switch(SS)
1785 {
1786 case 0:
1787 g->GS = 0;
1788 break;
1789
1790 case 1:
1791 g->GS = 1;
1792 break;
1793 }
1794 }
1795
1796
1797 /* GL (12 bits) asymptote
1798 * GSUM (6 bits) sum memory address into which output is added
1799 * -----------------------------------------------------------------
1800 * GL, :L:S: (12) GL : (6) GSUM : 1 0 0 0: (8) gen # :
1801 * GSUM -----------------------------------------------------------------
1802 *
1803 * L: if 1, disable loading GL
1804 * S: if 1, disable loading GSUM
1805 */
1806
gl_command(int cmd)1807 static void gl_command(int cmd)
1808 {
1809 int GL, GSUM, L, S, gen, old_GSUM;
1810 generator *g;
1811
1812 gen = LDB(cmd, 8, 0);
1813 GSUM = LDB(cmd, 6, 12);
1814 GL = LDB(cmd, 12, 18);
1815 L = BIT(cmd, 31);
1816 S = BIT(cmd, 30);
1817
1818 g = gens[gen];
1819 old_GSUM = g->GSUM;
1820
1821 if (L == 0)
1822 {
1823 /* is this signed? -- posies treats it as unsigned, I believe */
1824 #if 1
1825 g->GL = GL;
1826 g->f_GL = UNSIGNED_12_TO_DOUBLE(GL);
1827 #else
1828 g->GL = TWOS_12(GL);
1829 g->f_GL = DOUBLE_12(g->GL);
1830 #endif
1831 }
1832
1833 if (S == 0)
1834 g->GSUM = GSUM;
1835
1836 if (describe_commands)
1837 {
1838 if (L == 1)
1839 {
1840 if (S == 1)
1841 fprintf(stderr, "g%d: noop\n", gen);
1842 else fprintf(stderr, "g%d outloc: gen-outs[%d]\n", gen, g->GSUM);
1843 }
1844 else
1845 {
1846 if (S == 0)
1847 fprintf(stderr, "g%d amp offset: %d = %.4f\n", gen, g->GL, g->f_GL);
1848 else fprintf(stderr, "g%d outloc: gen-outs[%d] + amp offset: %d = %.4f\n", gen, g->GSUM, g->GL, g->f_GL);
1849 }
1850 }
1851
1852 if (REPORT_BAD_COMMANDS)
1853 {
1854 if ((GL == 1) && (L == 1) && (S == 0))
1855 fprintf(stderr, "sample %d (%.3f), command %d, possible gen output loc overflow: g%d %d\n",
1856 samples, (double)samples / (double)srate, current_command,
1857 gen, GSUM);
1858
1859 if ((gen_is_active(g)) &&
1860 (g->GSUM != old_GSUM) &&
1861 (samples > last_GMODE_command) &&
1862 (S == 0))
1863 fprintf(stderr, "sample %d (%.3f), command %d, stray output loc: g%d %d from %d (last mode sample: %d)\n",
1864 samples, (double)samples / (double)srate, current_command,
1865 gen, g->GSUM, old_GSUM,
1866 last_GMODE_command);
1867 }
1868 }
1869
1870
1871 /* (20 bits) theta -- oscillator angle
1872 * -----------------------------------------------------------------
1873 * GK : (20) data : 1 0 0 1: (8) gen # :
1874 * -----------------------------------------------------------------
1875 */
1876
gk_command(int cmd)1877 static void gk_command(int cmd)
1878 {
1879 /* GK is 20 bits */
1880 int data, gen, old_GK;
1881 double old_f_GK;
1882 generator *g;
1883
1884 gen = LDB(cmd, 8, 0);
1885 data = LDB(cmd, 20, 12);
1886
1887 g = gens[gen];
1888 old_GK = g->GK;
1889 old_f_GK = g->f_GK;
1890
1891 g->GK = TWOS_20(data);
1892 g->f_GK = DOUBLE_20(g->GK);
1893
1894 if (describe_commands)
1895 fprintf(stderr, "g%d phase: %d %.4f\n", gen, g->GK, g->f_GK);
1896
1897 if ((gen_is_active(g)) &&
1898 (samples > last_GMODE_command))
1899 {
1900 if (REPORT_BAD_COMMANDS)
1901 fprintf(stderr, "sample %d (%.3f), command %d, stray phase: g%d %.4f (last mode sample: %d)\n",
1902 samples, (double)samples / (double)srate, current_command,
1903 gen, g->f_GK,
1904 last_GMODE_command);
1905 if (FLUSH_BAD_COMMANDS)
1906 {
1907 g->GK = old_GK;
1908 g->f_GK = old_f_GK;
1909 }
1910 }
1911 }
1912
1913
1914 /* GFM (7 bits) sum memory address from which frequency modulation
1915 * GMODE (10 bits) generator mode
1916 * -----------------------------------------------------------------
1917 * :M:F:C: (10) GMODE :(7) GFM: 1 0 1 0: (8) gen # :
1918 * -----------------------------------------------------------------
1919 * GMODE,
1920 * GFM M: if 1, disable loading GMODE
1921 * F: if 1, disable loading GFM
1922 * C: if 1, clear GK
1923 */
1924
bad_mode(int mode)1925 static bool bad_mode(int mode)
1926 {
1927 int R, E, S;
1928 R = osc_run(mode);
1929 E = osc_env(mode);
1930 S = osc_mode(mode);
1931
1932 if ((R != 2) && (R != 7) && (R != 3) && (R != 0))
1933 switch (S)
1934 {
1935 case SUMCOS: case SAWTOOTH: case SQUARE: case PULSE: case SIN_K: case SIN_FM:
1936 break;
1937 default:
1938 return(true);
1939 }
1940
1941 switch (R)
1942 {
1943 case 0: case 1: case 15: case 14: case 9: case 13: case 7: case 3: case 2:
1944 break;
1945 default:
1946 return(true);
1947 }
1948
1949 return(false);
1950 }
1951
1952
print_gmode_name(int mode)1953 static void print_gmode_name(int mode)
1954 {
1955 /* RRRREESSSS */
1956 int R, E, S;
1957 char *E_name[4] = {"L-Q", "L+Q", "L-2^Q", "L+2^Q"};
1958
1959 R = osc_run(mode);
1960 E = osc_env(mode);
1961 S = osc_mode(mode);
1962
1963 if (R == 0)
1964 {
1965 fprintf(stderr, "inactive");
1966 return;
1967 }
1968
1969 if ((R != 2) && (R != 7) && (R != 3))
1970 {
1971 switch (S)
1972 {
1973 case SUMCOS: fprintf(stderr, "ncos"); break;
1974 case SAWTOOTH: fprintf(stderr, "saw"); break;
1975 case SQUARE: fprintf(stderr, "square"); break;
1976 case PULSE: fprintf(stderr, "pulse"); break;
1977 case SIN_K: fprintf(stderr, "sin"); break;
1978 case SIN_FM: fprintf(stderr, "sin+fm"); break;
1979 default: fprintf(stderr, "unknown"); break;
1980 }
1981
1982 fprintf(stderr, "-%s-", E_name[E]);
1983 }
1984
1985 switch (R)
1986 {
1987 case 1: fprintf(stderr, "pause"); break;
1988 case 15: fprintf(stderr, "A"); break;
1989 case 14: fprintf(stderr, "B"); break;
1990 case 9: fprintf(stderr, "wait"); break;
1991 case 13: fprintf(stderr, "C"); break;
1992 case 7: fprintf(stderr, "rd"); break;
1993 case 3: fprintf(stderr, "wrt"); break;
1994 case 2: fprintf(stderr, "DAC"); break;
1995 default: fprintf(stderr, "unknown"); break;
1996 }
1997 }
1998
1999
gmode_command(int cmd)2000 static void gmode_command(int cmd)
2001 {
2002 int gen, M, F, C, GMODE, GFM, old_GMODE, old_GFM;
2003 bool gen_was_active;
2004 generator *g;
2005
2006 last_GMODE_command = samples;
2007
2008 gen = LDB(cmd, 8, 0);
2009 GFM = LDB(cmd, 7, 12);
2010 GMODE = LDB(cmd, 10, 19);
2011 M = BIT(cmd, 31);
2012 F = BIT(cmd, 30);
2013 C = BIT(cmd, 29);
2014
2015 g = gens[gen];
2016 old_GFM = g->GFM;
2017 old_GMODE = g->GMODE;
2018 gen_was_active = gen_is_active(g);
2019
2020 if (M == 0)
2021 g->GMODE = GMODE;
2022 if (F == 0)
2023 g->GFM = GFM;
2024 if (C == 1)
2025 g->GK = 0;
2026
2027 /*
2028 if (osc_env(GMODE) > 1) fprintf(stderr, "expt %d ", samples);
2029 */
2030
2031 if (describe_commands)
2032 {
2033 fprintf(stderr, "g%d ", gen);
2034 if (M == 0)
2035 {
2036 fprintf(stderr, "mode: ");
2037 print_gmode_name(g->GMODE);
2038 }
2039 if (F == 0)
2040 {
2041 if (M == 0) fprintf(stderr, ", ");
2042 fprintf(stderr, "inloc: %s[%d]", ((g->GFM >> 6) == 0) ? "gen-ins" : "mod-ins", g->GFM & 0x3f);
2043 }
2044 if (C == 1)
2045 {
2046 if ((M == 0) || (F == 0))
2047 fprintf(stderr, ", ");
2048 fprintf(stderr, "clear phase");
2049 }
2050 fprintf(stderr, "\n");
2051 }
2052
2053 if (REPORT_BAD_COMMANDS)
2054 {
2055 if (bad_mode(GMODE))
2056 fprintf(stderr, "sample %d (%.3f), command %d, bad mode: g%d %x\n",
2057 samples, (double)samples / (double)srate, current_command,
2058 gen, GMODE);
2059
2060 if ((gen_is_active(g)) &&
2061 (gen >= processing_ticks))
2062 fprintf(stderr, "sample %d (%.3f), command %d, g%d cannot actually run (procticks: %d)\n",
2063 samples, (double)samples / (double)srate, current_command,
2064 gen, processing_ticks);
2065
2066 #if 0
2067 if ((gen_was_active) &&
2068 (!gen_is_active(g)) &&
2069 (g->f_GQ != 0.0))
2070 fprintf(stderr, "sample %d (%.3f), command %d, g%d turned off with amp %.4f\n",
2071 samples, (double)samples / (double)srate, current_command,
2072 gen, g->f_GQ);
2073 #endif
2074
2075 if ((gen_was_active) &&
2076 ((g->GFM != old_GFM) || (g->GMODE != old_GMODE)) &&
2077 (samples > last_GMODE_command))
2078 {
2079 if (g->GFM != old_GFM)
2080 fprintf(stderr, "sample %d (%.3f), command %d, stray input loc: g%d %d from %d (last mode sample: %d)\n",
2081 samples, (double)samples / (double)srate, current_command,
2082 gen, g->GFM, old_GFM,
2083 last_GMODE_command);
2084 else
2085 {
2086 fprintf(stderr, "sample %d (%.3f), command %d, stray mode: g%d ",
2087 samples, (double)samples / (double)srate, current_command, gen);
2088 print_gmode_name(g->GMODE);
2089 fprintf(stderr, " from ");
2090 print_gmode_name(old_GMODE);
2091 fprintf(stderr, " (last mode sample: %d)\n", last_GMODE_command);
2092 }
2093 }
2094 }
2095 }
2096
2097
2098 /* GO (20 bits) alpha -- oscillator frequency sweep rate
2099 * -----------------------------------------------------------------
2100 * GO : (20) data : 1 0 1 1: (8) gen # :
2101 * -----------------------------------------------------------------
2102 */
2103
go_command(int cmd)2104 static void go_command(int cmd)
2105 {
2106 /* GO is 20 bits */
2107 int data, gen;
2108 generator *g;
2109
2110 gen = LDB(cmd, 8, 0);
2111 data = LDB(cmd, 20, 12);
2112
2113 g = gens[gen];
2114 g->GO = TWOS_20(data);
2115 g->f_GO = DOUBLE_20(g->GO);
2116
2117 if (describe_commands)
2118 {
2119 if (osc_run(g->GMODE) == 2)
2120 fprintf(stderr, "g%d DAC out: %d\n", gen, data);
2121 else fprintf(stderr, "g%d freq change: %d %.4f (%.4f Hz/sec), freq: %.4f\n",
2122 gen, g->GO, g->f_GO, g->f_GO * 0.5 * srate * srate / 256.0, g->f_GJ * srate * 0.5);
2123 }
2124 }
2125
2126
2127 /* M0 (30 bits) coefficient
2128 * M1 (30 bits) other coefficient
2129 * -----------------------------------------------------------------
2130 * MM : (20) data : 1 1 0: V V: (7) mod # :
2131 * -----------------------------------------------------------------
2132 *
2133 * VV: 00 M0 right-adjusted, sign extended
2134 * 01 M1 right-adjusted, sign extended
2135 * 10 M0 left-adjusted, low bits from left of DX; clear DX
2136 * 11 M1 left-adjusted, low bits from left of DX; clear DX
2137 */
2138
2139 /* To avoid endless repetition in the modifier processing, I'll incorporate the scalers
2140 * into M0 and M1 when they are set, or when the scalers are changed, but this means
2141 * (for simplicity) keeping track of the original M0 and M1 values: ("o_M0" and friends)
2142 */
2143
mm_command(int cmd)2144 static void mm_command(int cmd)
2145 {
2146 /* M0 and M1 are 30 bits */
2147 int mod, VV, data, old_DX = 0;
2148 modifier *m;
2149
2150 mod = LDB(cmd, 7, 0);
2151 VV = LDB(cmd, 2, 7);
2152 data = LDB(cmd, 20, 12);
2153
2154 m = mods[mod];
2155
2156 switch (VV)
2157 {
2158 case 0:
2159 m->M0 = TWOS_20(data);
2160 m->f_M0 = DOUBLE_30(m->M0);
2161 m->o_M0 = m->M0;
2162 m->o_f_M0 = m->f_M0;
2163 m->M0 = m->M0 * m->mult_scl_0 / 4;
2164 m->f_M0 *= m->mult_scl_0;
2165 break;
2166
2167 case 1:
2168 m->M1 = TWOS_20(data);
2169 m->f_M1 = DOUBLE_30(m->M1);
2170 m->o_M1 = m->M1;
2171 m->o_f_M1 = m->f_M1;
2172 m->M1 = m->M1 * m->mult_scl_1 / 4;
2173 m->f_M1 *= m->mult_scl_1;
2174 break;
2175
2176 case 2:
2177 m->M0 = TWOS_30(((data << 10) + ((DX >> 10) & 0x3ff)));
2178 m->f_M0 = DOUBLE_30(m->M0);
2179 m->o_M0 = m->M0;
2180 m->o_f_M0 = m->f_M0;
2181 old_DX = DX;
2182 DX = 0;
2183 m->M0 = (m->M0 / 4) * m->mult_scl_0; /* try not to set the sign bit */
2184 m->f_M0 *= m->mult_scl_0;
2185 break;
2186
2187 case 3:
2188 m->M1 = TWOS_30(((data << 10) + ((DX >> 10) & 0x3ff)));
2189 m->f_M1 = DOUBLE_30(m->M1);
2190 m->o_M1 = m->M1;
2191 m->o_f_M1 = m->f_M1;
2192 old_DX = DX;
2193 DX = 0;
2194 m->M1 = (m->M1 / 4) * m->mult_scl_1;
2195 m->f_M1 *= m->mult_scl_1;
2196 break;
2197 }
2198
2199 if (describe_commands)
2200 {
2201 switch (VV)
2202 {
2203 case 0:
2204 fprintf(stderr, "m%d M0: %d: %d %.6f\n", mod, data, m->M0, m->f_M0);
2205 break;
2206 case 1:
2207 fprintf(stderr, "m%d M1: %d: %d %.6f\n", mod, data, m->M1, m->f_M1);
2208 break;
2209 case 2:
2210 fprintf(stderr, "m%d M0+DX: data: %d + DX: %d (scl: %d), %d -> %d, %.6f -> %.6f\n",
2211 mod, data, old_DX, m->mult_scl_0, m->o_M0, m->M0, m->o_f_M0, m->f_M0);
2212 break;
2213 case 3:
2214 fprintf(stderr, "m%d M1+DX: data: %d + DX: %d (scl: %d), %d -> %d, %.6f -> %.6f\n",
2215 mod, data, old_DX, m->mult_scl_1, m->o_M1, m->M1, m->o_f_M1, m->f_M1);
2216 break;
2217 }
2218 }
2219 }
2220
2221
2222 /* L0 (20 bits) running term
2223 * L1 (20 bits) other running term
2224 * -----------------------------------------------------------------
2225 * ML : (20) data : 1 1 1 0: N: (7) mod # :
2226 * -----------------------------------------------------------------
2227 *
2228 * N: 0 L0
2229 * 1 L1
2230 */
2231
ml_command(int cmd)2232 static void ml_command(int cmd)
2233 {
2234 int mod, N, data;
2235 modifier *m;
2236
2237 mod = LDB(cmd, 7, 0);
2238 data = LDB(cmd, 20, 12);
2239 N = BIT(cmd, 7);
2240
2241 m = mods[mod];
2242 if (N == 0)
2243 {
2244 m->L0 = TWOS_20(data);
2245 m->f_L0 = DOUBLE_20(m->L0);
2246 }
2247 else
2248 {
2249 m->L1 = TWOS_20(data);
2250 m->f_L1 = DOUBLE_20(m->L1);
2251 }
2252
2253 if (describe_commands)
2254 {
2255 if (N == 0)
2256 fprintf(stderr, "m%d L0: %d: %d %.6f\n", mod, data, m->L0, m->f_L0);
2257 else fprintf(stderr, "m%d L1: %d: %d %.6f\n", mod, data, m->L1, m->f_L1);
2258 }
2259 }
2260
2261
2262 /* MSUM (7 bits) result address in sum memory
2263 * MMODE (9 bits) modifier mode
2264 * -----------------------------------------------------------------
2265 * :M:S:C:H: (9) MMODE :(7)MSUM: 1 1 1 1 0: (7) mod # :
2266 * -----------------------------------------------------------------
2267 *
2268 * MMODE,
2269 * MSUM M: if 1, disable loading MMMMM bits of MMODE
2270 * S: if 1, disable loading MSUM
2271 * C: if 1, clear L0
2272 * H: if 1, disable loading AABB bits of MMODE
2273 */
2274
mode_name(int m)2275 static const char *mode_name(int m)
2276 {
2277 switch (m)
2278 {
2279 case M_INACTIVE: return("inactive");
2280 case M_NOISE: return("noise");
2281 case M_TRIGGERED_NOISE: return("triggered-noise");
2282 case M_LATCH: return("latch");
2283 case M_THRESHOLD: return("thresh");
2284 case M_DELAY: return("delay");
2285 case M_TWO_POLE: return("2pole");
2286 case M_TWO_POLE_M0: return("2pole-M0");
2287 case M_TWO_POLE_M1: return("2pole-M1");
2288 case M_TWO_ZERO: return("2zero");
2289 case M_TWO_ZERO_M0: return("2zero-M0");
2290 case M_TWO_ZERO_M1: return("2zero-M1");
2291 case M_INTEGER_MIXING: return("int-mix");
2292 case M_ONE_POLE: return("1pole");
2293 case M_MIXING: return("mix");
2294 case M_ONE_ZERO: return("1zero");
2295 case M_MULTIPLY: return("multiply");
2296 case M_AMP_MOD: return("am");
2297 case M_MAX: return("max");
2298 case M_MIN: return("min");
2299 case M_SIGNUM: return("signum");
2300 case M_ZERO_CROSS: return("0cross");
2301 }
2302 return("unknown");
2303 }
2304
2305
mmode_command(int cmd)2306 static void mmode_command(int cmd)
2307 {
2308 int mod, MSUM, MMODE, M, S, C, H;
2309 modifier *m;
2310
2311 mod = LDB(cmd, 7, 0);
2312 MSUM = LDB(cmd, 7, 12);
2313 MMODE = LDB(cmd, 9, 19);
2314 M = BIT(cmd, 31);
2315 S = BIT(cmd, 30);
2316 C = BIT(cmd, 29);
2317 H = BIT(cmd, 28);
2318
2319 m = mods[mod];
2320 if (S == 0)
2321 m->MSUM = MSUM;
2322 if (C == 1)
2323 {
2324 m->L0 = 0;
2325 m->f_L0 = 0.0;
2326 }
2327
2328 /* MMODE is MMMMMAABB */
2329 if (H == 0)
2330 {
2331 /* set up the scale factors now, so we don't have to futz around later */
2332 /* BB = first (!) */
2333 m->mult_scl_1 = (1 << (MMODE & 0x3));
2334 m->mult_scl_0 = (1 << ((MMODE >> 2) & 0x3));
2335 /* whenever M0/M1 are set, we will include these factors */
2336
2337 m->M0 = (m->o_M0 / 4) * m->mult_scl_0; /* order matters -- don't want to set sign bit by accident */
2338 m->M1 = (m->o_M1 / 4) * m->mult_scl_1;
2339 m->f_M0 = m->o_f_M0 * m->mult_scl_0;
2340 m->f_M1 = m->o_f_M1 * m->mult_scl_1;
2341
2342 if (M == 0)
2343 m->MMODE = MMODE; /* set both */
2344 else m->MMODE = (MMODE & 0xf) + (m->MMODE & 0x1f0); /* H is 0, so set AABB */
2345 }
2346 else
2347 {
2348 if (M == 0)
2349 m->MMODE = (MMODE & 0x1f0) + (m->MMODE & 0xf); /* M is 0, so set MMMMM */
2350 }
2351
2352 if (describe_commands)
2353 {
2354 fprintf(stderr, "m%d ", mod);
2355 if (M == 0)
2356 fprintf(stderr, "mode: %s", mode_name(MMODE >> 4));
2357 if (H == 0)
2358 {
2359 if (M == 0)
2360 fprintf(stderr, ", ");
2361 fprintf(stderr, "AA: %d, BB: %d (M0: %d, %.3f, M1: %d, %.3f)", (MMODE >> 2) & 0x3, MMODE & 0x3, m->M0, m->f_M0, m->M1, m->f_M1);
2362 }
2363 if (S == 0)
2364 {
2365 if ((H == 0) || (M == 0))
2366 fprintf(stderr, ", ");
2367 fprintf(stderr, "outloc(%s): mod-outs[%d]", ((MSUM >> 6) == 0) ? "+" : "=", MSUM & 0x3f);
2368 }
2369 if (C == 1)
2370 {
2371 if ((S == 0) || (H == 0) || (M == 0))
2372 fprintf(stderr, ", ");
2373 fprintf(stderr, "L0=0");
2374 }
2375 fprintf(stderr, "\n");
2376 }
2377
2378 if (REPORT_BAD_COMMANDS)
2379 {
2380 if (((MMODE >> 4) != M_INACTIVE) &&
2381 ((mod * 2) >= processing_ticks))
2382 fprintf(stderr, "sample %d (%.3f), command %d, m%d cannot actually run (procticks: %d)\n",
2383 samples, (double)samples / (double)srate, current_command,
2384 mod, processing_ticks);
2385 }
2386 }
2387
2388
2389 /* MIN (8 bits) address in sum memory where modifier reads "A" data
2390 * MRM (8 bits) address in sum memory where modifier reads "B" data
2391 * -----------------------------------------------------------------
2392 * :R:I:C C: (8) MRM : (8) MIN : 1 1 1 1 1: (7) mod # :
2393 * -----------------------------------------------------------------
2394 *
2395 * MRM,
2396 * MIN, R: if 1, disable loading MRM
2397 * MT I: if 1, disable loading MIN
2398 * CC: 00 turn off truncation
2399 * 01 turn on truncation
2400 * 10 clear L1
2401 * 11 no effect
2402 */
2403
mrm_command(int cmd)2404 static void mrm_command(int cmd)
2405 {
2406 int mod, MRM, MIN, R, I, CC;
2407 modifier *m;
2408
2409 mod = LDB(cmd, 7, 0);
2410 MIN = LDB(cmd, 8, 12);
2411 MRM = LDB(cmd, 8, 20);
2412 R = BIT(cmd, 31);
2413 I = BIT(cmd, 30);
2414 CC = LDB(cmd, 2, 28);
2415
2416 m = mods[mod];
2417 if (R == 0)
2418 m->MRM = MRM;
2419 if (I == 0)
2420 m->MIN = MIN;
2421
2422 switch (CC)
2423 {
2424 case 0:
2425 m->T = 0;
2426 break;
2427
2428 case 1:
2429 m->T = 1;
2430 break;
2431
2432 case 2:
2433 m->L1 = 0;
2434 m->f_L1 = 0.0;
2435 break;
2436 }
2437
2438 if (describe_commands)
2439 {
2440 fprintf(stderr, "m%d inlocs:", mod);
2441 if (R == 0)
2442 {
2443 if (mod_mode(m->MMODE) == M_DELAY)
2444 fprintf(stderr, ", delay: %d", MRM & 0x1f);
2445 else
2446 {
2447 fprintf(stderr, ", MRM: ");
2448 print_mod_read_name(MRM);
2449 }
2450 }
2451 if (I == 0)
2452 {
2453 fprintf(stderr, ", MIN: ");
2454 print_mod_read_name(MIN);
2455 }
2456 if (CC == 0) fprintf(stderr, ", trunc off");
2457 if (CC == 1) fprintf(stderr, ", trunc on");
2458 if (CC == 2) fprintf(stderr, ", L1=0");
2459 fprintf(stderr, "\n");
2460 }
2461 }
2462
2463
handle_command(int cmd)2464 static void handle_command(int cmd)
2465 {
2466 /* actually we should take highest_tick - processing_ticks - 8 commands at a time, then run a sample */
2467
2468 int op;
2469 if ((start_describing <= samples) &&
2470 (stop_describing >= samples))
2471 describe_commands = true;
2472 else describe_commands = DEFAULT_DESCRIBE_COMMANDS;
2473
2474 op = LDB(cmd, 4, 8);
2475
2476 switch (op)
2477 {
2478 case 0:
2479 if (BIT(cmd, 7) == 1)
2480 dly_command(cmd);
2481 else misc_command(cmd);
2482 break;
2483
2484 case 1:
2485 if (BIT(cmd, 7) == 1)
2486 ticks_command(cmd);
2487 else timer_command(cmd);
2488 break;
2489
2490 case 2: case 3:
2491 gq_command(cmd);
2492 break;
2493
2494 case 4: case 5:
2495 gj_command(cmd);
2496 break;
2497
2498 case 6:
2499 gp_command(cmd);
2500 break;
2501
2502 case 7:
2503 gn_command(cmd);
2504 break;
2505
2506 case 8:
2507 gl_command(cmd);
2508 break;
2509
2510 case 9:
2511 gk_command(cmd);
2512 break;
2513
2514 case 10:
2515 gmode_command(cmd);
2516 break;
2517
2518 case 11:
2519 go_command(cmd);
2520 break;
2521
2522 case 12: case 13:
2523 mm_command(cmd);
2524 break;
2525
2526 case 14:
2527 ml_command(cmd);
2528 break;
2529
2530 case 15:
2531 if (BIT(cmd, 7) == 0)
2532 mmode_command(cmd);
2533 else mrm_command(cmd);
2534 break;
2535
2536 default:
2537 fprintf(stderr, "impossible command\n");
2538 break;
2539 }
2540
2541 current_command++;
2542 }
2543
2544
2545 /* ---------------------------------------- debugging ---------------------------------------- */
2546
2547 #if 0
2548 static void dump_gens(void)
2549 {
2550 int i;
2551 for (i = 0; i < GENERATORS; i++)
2552 if (gens[i]->GMODE != 0)
2553 fprintf(stderr, "g%d GMODE: %d, %d [%.3f] -> %d [%.3f], GQ: %.3f, GP: %.3f, GL: %.3f, GJ: %.3f, GO: %.3f, GN: %d, GS: %d\n",
2554 i,
2555 gens[i]->GMODE,
2556 gens[i]->GFM, ((gens[i]->GFM >> 6) == 0) ? gen_ins[gens[i]->GFM & 0x3f] : mod_ins[gens[i]->GFM & 0x3f],
2557 gens[i]->GSUM, gen_outs[gens[i]->GSUM],
2558 gens[i]->f_GQ, gens[i]->f_GP, gens[i]->f_GL, gens[i]->f_GJ, gens[i]->f_GO,
2559 gens[i]->GN, gens[i]->GS);
2560 }
2561
2562
2563 static void dump_mods(void)
2564 {
2565 int i;
2566 for (i = 0; i < MODIFIERS; i++)
2567 if (mods[i]->MMODE != 0)
2568 fprintf(stderr, "m%d MMODE: %d, (%d [%.3f] %d [%.3f]) -> %d [%.3f], M0: %.3f, M1: %.3f, L0: %.3f, L1: %.3f\n",
2569 i,
2570 mods[i]->MMODE,
2571 mods[i]->MIN, mod_read(mods[i]->MIN),
2572 mods[i]->MRM, mod_read(mods[i]->MRM),
2573 mods[i]->MSUM, mod_outs[mods[i]->MSUM],
2574 mods[i]->f_M0, mods[i]->f_M1, mods[i]->f_L0, mods[i]->f_L1);
2575 }
2576 #endif
2577
dump_gen_sum(int addr)2578 static void dump_gen_sum(int addr)
2579 {
2580 int i;
2581 /* show prev-ins : ins : out, g%d for all writers */
2582 fprintf(stderr, "g-sum%d: %.3f %.3f %.3f [max: %.3f]", addr, prev_gen_ins[addr], gen_ins[addr], gen_outs[addr], peak_gen_ins[addr]);
2583
2584 for (i = 0; i < GENERATORS; i++)
2585 if ((gens[i]->GMODE != 0) &&
2586 (gens[i]->GSUM == addr))
2587 fprintf(stderr, " g%d", i);
2588 }
2589
2590
dump_mod_sum(int addr)2591 static void dump_mod_sum(int addr)
2592 {
2593 int i;
2594 /* show prev-ins : ins : out, m%d for all writers */
2595 fprintf(stderr, "m-sum%d: %.3f %.3f %.3f [max: %.3f]", addr, prev_mod_ins[addr], mod_ins[addr], mod_outs[addr], peak_mod_ins[addr]);
2596
2597 for (i = 0; i < MODIFIERS; i++)
2598 if ((mod_mode(mods[i]->MMODE) != M_INACTIVE) &&
2599 ((mods[i]->MSUM &0x3f) == addr))
2600 fprintf(stderr, " m%d", i);
2601 }
2602
2603
print_mod_sum(int addr)2604 static void print_mod_sum(int addr)
2605 {
2606 int loc;
2607 loc = addr & 0x3f;
2608 switch ((addr >> 6) & 0x3)
2609 {
2610 case 0:
2611 fprintf(stderr, "[");
2612 dump_gen_sum(loc);
2613 break;
2614 case 1:
2615 fprintf(stderr, "[");
2616 if (loc == 0)
2617 {
2618 if ((prev_mod_ins[0] != 0.0) || (mod_ins[0] != 0.0) || (mod_outs[0] != 0.0) || (peak_mod_ins[0] != 0))
2619 dump_mod_sum(0);
2620 else fprintf(stderr, "zero");
2621 }
2622 else dump_mod_sum(loc);
2623 break;
2624 case 2:
2625 fprintf(stderr, "-out[");
2626 if (loc == 0)
2627 {
2628 if ((prev_mod_ins[0] != 0.0) || (mod_ins[0] != 0.0) || (mod_outs[0] != 0.0) || (peak_mod_ins[0] != 0))
2629 dump_mod_sum(0);
2630 else fprintf(stderr, "zero");
2631 }
2632 else dump_mod_sum(loc);
2633 break;
2634 case 3:
2635 fprintf(stderr, "[illegal: %d", addr);
2636 break;
2637 }
2638 }
2639
2640
gen_mem_readers(int addr)2641 static int gen_mem_readers(int addr)
2642 {
2643 int i, rds = 0;
2644 for (i = 0; i < GENERATORS; i++)
2645 if ((gens[i]->GMODE != 0) &&
2646 (gens[i]->GFM == addr)) /* Q bit 0 = gen */
2647 rds++;
2648 for (i = 0; i < MODIFIERS; i++)
2649 if (mod_mode(mods[i]->MMODE) != M_INACTIVE)
2650 {
2651 if (mods[i]->MIN == addr) /* QQ bits = 0 = gen */
2652 rds++;
2653 if ((mod_mode(mods[i]->MMODE) != M_DELAY) &&
2654 (mods[i]->MRM == addr))
2655 rds++;
2656 }
2657 return(rds);
2658 }
2659
2660
mod_mem_readers(int addr)2661 static int mod_mem_readers(int addr)
2662 {
2663 int i, rds = 0;
2664 for (i = 0; i < GENERATORS; i++)
2665 if ((gens[i]->GMODE != 0) &&
2666 (gens[i]->GFM == 64 + addr)) /* Q bit 1 = mod */
2667 rds++;
2668 for (i = 0; i < MODIFIERS; i++)
2669 if (mod_mode(mods[i]->MMODE) != M_INACTIVE)
2670 {
2671 if ((mods[i]->MIN == 64 + addr) ||
2672 (mods[i]->MIN == 128 + addr))
2673 rds++;
2674 if ((mod_mode(mods[i]->MMODE) != M_DELAY) &&
2675 ((mods[i]->MRM == 64 + addr) ||
2676 (mods[i]->MRM == 128 + addr)))
2677 rds++;
2678 }
2679 return(rds);
2680 }
2681
2682
dump_patch(void)2683 static void dump_patch(void)
2684 {
2685 /* try to show all currently active elements and memory with some history */
2686 int i, p;
2687
2688 fprintf(stderr, "sample: %d, command: %d, ", samples, current_command);
2689
2690 for (i = 0, p = 0; i < GENERATORS; i++)
2691 if (gens[i]->GMODE != 0)
2692 p++;
2693 fprintf(stderr, "active gens: %d, ", p);
2694
2695 for (i = 0, p = 0; i < MODIFIERS; i++)
2696 if (mod_mode(mods[i]->MMODE) != M_INACTIVE)
2697 p++;
2698 fprintf(stderr, "active mods: %d, ", p);
2699
2700 for (i = 0, p = 0; i < DELAYS; i++)
2701 if (dlys[i]->P != 0)
2702 p++;
2703 fprintf(stderr, "active delays: %d\n\n", p);
2704
2705 for (i = 0; i < GENERATORS; i++)
2706 if (gens[i]->GMODE != 0)
2707 {
2708 generator *g;
2709 g = gens[i];
2710 fprintf(stderr, "g%d ", i);
2711 print_gmode_name(g->GMODE);
2712
2713 fprintf(stderr, " [");
2714 if ((g->GFM >> 6) == 0)
2715 dump_gen_sum(g->GFM & 0x3f);
2716 else print_mod_sum(g->GFM);
2717
2718 fprintf(stderr, "]->[");
2719 if (osc_run(g->GMODE) == 2)
2720 fprintf(stderr, "OUT%d", g->GO & 0xf);
2721 else dump_gen_sum(g->GSUM);
2722
2723 fprintf(stderr, " (%d)], (amp: %.3f, freq: %.3f",
2724 gen_mem_readers(g->GSUM),
2725 gen_amp(g),
2726 g->f_GJ * 0.5 * srate);
2727 if (g->f_GJ == 0.0)
2728 fprintf(stderr, ", phase: %.3f", g->f_GK);
2729
2730 fprintf(stderr, ")\n");
2731 }
2732 fprintf(stderr, "\n");
2733
2734 for (i = 0; i < MODIFIERS; i++)
2735 if (mod_mode(mods[i]->MMODE) != M_INACTIVE)
2736 {
2737 modifier *m;
2738 m = mods[i];
2739 fprintf(stderr, "m%d %s ", i, mode_name(mod_mode(m->MMODE)));
2740
2741 if (mod_mode(m->MMODE) == M_MIXING)
2742 fprintf(stderr, "%.4f * ", m->f_M0);
2743 fprintf(stderr, "A");
2744 print_mod_sum(m->MIN);
2745 fprintf(stderr, "], ");
2746
2747 if (mod_mode(m->MMODE) == M_MIXING)
2748 fprintf(stderr, "%.4f * ", m->f_M1);
2749 fprintf(stderr, "B");
2750 if (mod_mode(m->MMODE) == M_DELAY)
2751 {
2752 delay *d;
2753 d = dlys[m->MRM & 0x1f];
2754 fprintf(stderr, "[delay: %d (%.4f)", m->MRM & 0x1f, delay_memory[d->X + d->Y]);
2755 fprintf(stderr, ", M0: %.4f, M1: %.4f, L0: %.4f, L1: %.4f", m->f_M0, m->f_M1, m->f_L0, m->f_L1);
2756 }
2757 else print_mod_sum(m->MRM);
2758
2759 fprintf(stderr, "]->[");
2760 if ((m->MSUM >> 6) != 0)
2761 fprintf(stderr, "-replace");
2762 dump_mod_sum(m->MSUM & 0x3f);
2763
2764 fprintf(stderr, " (%d)]\n", mod_mem_readers(m->MSUM));
2765 }
2766 fprintf(stderr, "\n");
2767
2768 for (i = 0; i < DELAYS; i++)
2769 if (dlys[i]->P != D_INACTIVE)
2770 {
2771 delay *d;
2772 d = dlys[i];
2773 fprintf(stderr, "d%d %s %.3f (%d + %d of %d)\n",
2774 i, P_name(d->P),
2775 delay_memory[d->X + d->Y],
2776 d->X, d->Y, d->Z);
2777 }
2778 {
2779 double dmax;
2780 dmax = fabs(delay_memory[0]);
2781 for (i = 1; i < DELAY_MEMORY_SIZE; i++)
2782 if (fabs(delay_memory[i]) > dmax)
2783 dmax = fabs(delay_memory[i]);
2784 fprintf(stderr, "delay memory peak: %.4f\n\n", dmax);
2785 }
2786 }
2787
2788
2789
2790 /* ---------------------------------------- main program ---------------------------------------- */
2791
main(int argc,char ** argv)2792 int main(int argc, char **argv)
2793 {
2794 if (argc < 2)
2795 fprintf(stderr, "sam filename [read_data file] [srate]\n"); /* mmm */
2796 else
2797 {
2798 FILE *sam_file;
2799 filename = argv[1];
2800
2801 sam_file = fopen(filename, "r");
2802 if (!sam_file)
2803 fprintf(stderr, "can't find %s\n", filename);
2804 else
2805 {
2806 long size;
2807 fseek(sam_file, 0, SEEK_END);
2808 size = ftell(sam_file);
2809 rewind(sam_file);
2810
2811 if (size <= 0)
2812 {
2813 fprintf(stderr, "%s is empty\n", filename);
2814 fclose(sam_file);
2815 }
2816 else
2817 {
2818 size_t bytes;
2819 unsigned char *command;
2820 int i;
2821
2822 if (argc > 2)
2823 {
2824 read_data_file = fopen(argv[2], "r");
2825 if (argc > 3)
2826 {
2827 /* mmm - set srate explicitly. I had an inexplicably high max tick setting in one sam file with read data input. */
2828 sscanf(argv[3], "%d", &srate);
2829 }
2830 }
2831
2832 start_clean();
2833
2834 command = (unsigned char *)calloc(size + 1, sizeof(unsigned char));
2835 bytes = fread(command, sizeof(unsigned char), size, sam_file);
2836 fclose(sam_file);
2837
2838 /* these were stored in at least 2 different formats
2839 *
2840 * FASTF.SAM: "Type: 32BITR BADSAM ;Looks like a SAM command file but has questionable data"
2841 * MACDON.SAM: "Type: SAM SIMPLE ;Simple SAM command file (corresponding sound file possible)"
2842 *
2843 * FASTF was written as 32 bits (using the 1st case below), and MACDON as 36 (using the 2nd case).
2844 * it looks like someone got a flag backwards, and wrote the known-good 32-bit files as 36,
2845 * and the possibly not-32 bit files as 32. I can't find the corresponding code in the writers
2846 * that Nando found on the exabyte tapes.
2847 *
2848 * The *.SAM.snd files are raw big-endian 24-bit int data (stereo?)
2849 * with many (6?) renditions?
2850 */
2851
2852 #if 1
2853 if ((command[0] != 0) || /* just a first guess */
2854 (command[1] != 0))
2855 {
2856 fprintf(stderr, "32\n");
2857 total_commands = bytes / 4;
2858 current_command = 0;
2859 for (i = 0; i < bytes; i += 4)
2860 {
2861 int cmd;
2862 int b1, b2, b3, b4;
2863 b1 = command[i + 0];
2864 b2 = command[i + 1];
2865 b3 = command[i + 2];
2866 b4 = command[i + 3];
2867 cmd = b4 + (b3 << 8) + (b2 << 16) + (b1 << 24);
2868 handle_command(cmd);
2869 }
2870 }
2871 else
2872 {
2873 fprintf(stderr, "36\n");
2874 total_commands = bytes / 5;
2875 current_command = 0;
2876 for (i = 0; i < bytes; i += 5)
2877 {
2878 int cmd;
2879 int b1, b2, b3, b4, b5;
2880 b1 = command[i + 0];
2881 b2 = command[i + 1];
2882 b3 = command[i + 2];
2883 b4 = command[i + 3];
2884 b5 = command[i + 4];
2885 cmd = ((b5 >> 4) & 0xff) + (b4 << 4) + (b3 << 12) + (b2 << 20) + ((b1 & 0xff) << 28);
2886 handle_command(cmd);
2887 }
2888 }
2889 #else
2890 /* another format that Mike used:
2891 * cmd = (b1 << 28) | (b2 << 24) | (b3 << 16) | (b4 << 8) | b5;
2892 */
2893 total_commands = bytes / 5;
2894 current_command = 0;
2895 for (i = 0; i < bytes; i += 5)
2896 {
2897 int cmd;
2898 int b1, b2, b3, b4, b5;
2899 b1 = command[i + 0];
2900 b2 = command[i + 1];
2901 b3 = command[i + 2];
2902 b4 = command[i + 3];
2903 b5 = command[i + 4];
2904 cmd = (b1 << 28) | (b2 << 24) | (b3 << 16) | (b4 << 8) | b5;
2905 handle_command(cmd);
2906 }
2907 #endif
2908 }
2909
2910 all_done();
2911 }
2912 }
2913 return(0);
2914 }
2915
2916 /* on the cover of an old copy of the specs:
2917
2918 NOT TO LEAVE THE MUSIC ROOM [red ink and underlined]
2919
2920 Would be an awful fate, [pencilled in below]
2921 Said Cleopatra to her groom,
2922 and struck him on the pate!
2923 */
2924