1 /*
2 * mzpokeysnd.c - POKEY sound chip emulation, v1.6
3 *
4 * Copyright (C) 2002 Michael Borisov
5 * Copyright (C) 2002-2014 Atari800 development team (see DOC/CREDITS)
6 *
7 * This file is part of the Atari800 emulator project which emulates
8 * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
9 *
10 * Atari800 is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * Atari800 is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Atari800; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "config.h"
26 #include <stdlib.h>
27 #include <math.h>
28
29 #ifdef ASAP /* external project, see http://asap.sf.net */
30 #include "asap_internal.h"
31 #else
32 #include "atari.h"
33 #endif
34 #include "mzpokeysnd.h"
35 #include "pokeysnd.h"
36 #include "remez.h"
37 #include "antic.h"
38 #include "gtia.h"
39
40 #define CONSOLE_VOL 8
41 #ifdef NONLINEAR_MIXING
42 static const double pokeymix[61+CONSOLE_VOL] = { /* Nonlinear POKEY mixing array */
43 0.000000, 5.169146, 10.157015, 15.166247,
44 20.073793, 24.927443, 29.728237, 34.495266,
45 39.181262, 43.839780, 48.429508, 52.932530,
46 57.327319, 61.586304, 65.673220, 69.547672,
47 73.207846, 76.594474, 79.739231, 82.631161,
48 85.300361, 87.750638, 90.020656, 92.108334,
49 94.051256, 95.848478, 97.521287, 99.080719,
50 100.540674, 101.902750, 103.185339, 104.375596,
51 105.491149, 106.523735, 107.473511, 108.361458,
52 109.185669, 109.962251, 110.685574, 111.367150,
53 112.008476, 112.612760, 113.185603, 113.722735,
54 114.227904, 114.712206, 115.171007, 115.605730,
55 116.024396, 116.416097, 116.803169, 117.155108,
56 117.532921, 117.835494, 118.196180, 118.502785,
57 118.825177, 119.138170, 119.421378, 119.734493,
58 /* need to add CONSOLE_VOL extra copies of the last val */
59 120.000000,120.0,120.0,120.0,120.0,120.0,120.0,120.0,120.0};
60 #endif
61
62 #define SND_FILTER_SIZE 2048
63
64 #define NPOKEYS 2
65
66
67 /* M_PI was not defined in MSVC headers */
68 #ifndef M_PI
69 # define M_PI 3.141592653589793
70 #endif
71
72 static int num_cur_pokeys = 0;
73
74 /* Filter */
75 static int pokey_frq; /* Hz - for easier resampling */
76 static int filter_size;
77 static double filter_data[SND_FILTER_SIZE];
78 static int audible_frq;
79
80 static const int pokey_frq_ideal = 1789790; /* Hz - True */
81 #if 0
82 static const int filter_size_44 = 1274;
83 static const int filter_size_44_8 = 884;
84 static const int filter_size_22 = 1239;
85 static const int filter_size_22_8 = 893;
86 static const int filter_size_11 = 1305;
87 static const int filter_size_11_8 = 937;
88 static const int filter_size_48 = 898;
89 static const int filter_size_48_8 = 626;
90 static const int filter_size_8 = 1322;
91 static const int filter_size_8_8 = 1214;
92 #endif
93
94 /* Flags and quality */
95 static int snd_quality = 0;
96
97 /* Poly tables */
98 static int poly4tbl[15];
99 static int poly5tbl[31];
100 static unsigned char poly17tbl[131071];
101 static int poly9tbl[511];
102
103
104 struct stPokeyState;
105
106 typedef int (*readout_t)(struct stPokeyState* ps);
107 typedef void (*event_t)(struct stPokeyState* ps, int p5v, int p4v, int p917v);
108
109 #ifdef NONLINEAR_MIXING
110 /* Change queue event value type */
111 typedef double qev_t;
112 #else
113 typedef unsigned char qev_t;
114 #endif
115
116 #ifdef SYNCHRONIZED_SOUND
117 static double ticks_per_sample;
118 static double samp_pos;
119 #endif /* SYNCHRONIZED_SOUND */
120
121 /* State variables for single Pokey Chip */
122 typedef struct stPokeyState
123 {
124 int curtick;
125 /* Poly positions */
126 int poly4pos;
127 int poly5pos;
128 int poly17pos;
129 int poly9pos;
130
131 /* Change queue */
132 qev_t ovola;
133 int qet[1322]; /* maximal length of filter */
134 qev_t qev[1322];
135 int qebeg;
136 int qeend;
137
138 /* Main divider (64khz/15khz) */
139 int mdivk; /* 28 for 64khz, 114 for 15khz */
140
141 /* Main switches */
142 int selpoly9;
143 int c0_hf;
144 int c1_f0;
145 int c2_hf;
146 int c3_f2;
147
148 /* SKCTL for two-tone mode */
149 int skctl;
150
151 /* Main output state */
152 qev_t outvol_all;
153 int forcero; /* Force readout */
154
155 /* channel 0 state */
156
157 readout_t readout_0;
158 event_t event_0;
159
160 int c0divpos;
161 int c0divstart; /* AUDF0 recalculated */
162 int c0divstart_p; /* start value when c1_f0 */
163 int c0diva; /* AUDF0 register */
164
165 int c0t1; /* D - 5bit, Q goes to sw3 */
166 int c0t2; /* D - out sw2, Q goes to sw4 and t3 */
167 int c0t3; /* D - out t2, q goes to xor */
168
169 int c0sw1; /* in1 - 4bit, in2 - 17bit, out goes to sw2 */
170 int c0sw2; /* in1 - /Q t2, in2 - out sw1, out goes to t2 */
171 int c0sw3; /* in1 - +5, in2 - Q t1, out goes to C t2 */
172 int c0sw4; /* hi-pass sw */
173 int c0vo; /* volume only */
174
175 #ifndef NONLINEAR_MIXING
176 int c0stop; /* channel counter stopped */
177 #endif
178
179 int vol0;
180
181 int outvol_0;
182
183 /* channel 1 state */
184
185 readout_t readout_1;
186 event_t event_1;
187
188 int c1divpos;
189 int c1divstart;
190 int c1diva;
191
192 int c1t1;
193 int c1t2;
194 int c1t3;
195
196 int c1sw1;
197 int c1sw2;
198 int c1sw3;
199 int c1sw4;
200 int c1vo;
201
202 #ifndef NONLINEAR_MIXING
203 int c1stop; /* channel counter stopped */
204 #endif
205
206 int vol1;
207
208 int outvol_1;
209
210 /* channel 2 state */
211
212 readout_t readout_2;
213 event_t event_2;
214
215 int c2divpos;
216 int c2divstart;
217 int c2divstart_p; /* start value when c1_f0 */
218 int c2diva;
219
220 int c2t1;
221 int c2t2;
222
223 int c2sw1;
224 int c2sw2;
225 int c2sw3;
226 int c2vo;
227
228 #ifndef NONLINEAR_MIXING
229 int c2stop; /* channel counter stopped */
230 #endif
231
232 int vol2;
233
234 int outvol_2;
235
236 /* channel 3 state */
237
238 readout_t readout_3;
239 event_t event_3;
240
241 int c3divpos;
242 int c3divstart;
243 int c3diva;
244
245 int c3t1;
246 int c3t2;
247
248 int c3sw1;
249 int c3sw2;
250 int c3sw3;
251 int c3vo;
252
253 #ifndef NONLINEAR_MIXING
254 int c3stop; /* channel counter stopped */
255 #endif
256
257 int vol3;
258
259 int outvol_3;
260
261 /* GTIA speaker */
262
263 int speaker;
264
265 } PokeyState;
266
267 PokeyState pokey_states[NPOKEYS];
268
269 /* Forward declarations for ResetPokeyState */
270
271 static int readout0_normal(PokeyState* ps);
272 static void event0_pure(PokeyState* ps, int p5v, int p4v, int p917v);
273
274 static int readout1_normal(PokeyState* ps);
275 static void event1_pure(PokeyState* ps, int p5v, int p4v, int p917v);
276
277 static int readout2_normal(PokeyState* ps);
278 static void event2_pure(PokeyState* ps, int p5v, int p4v, int p917v);
279
280 static int readout3_normal(PokeyState* ps);
281 static void event3_pure(PokeyState* ps, int p5v, int p4v, int p917v);
282
ResetPokeyState(PokeyState * ps)283 static void ResetPokeyState(PokeyState* ps)
284 {
285 /* Poly positions */
286 ps->poly4pos = 0;
287 ps->poly5pos = 0;
288 ps->poly9pos = 0;
289 ps->poly17pos = 0;
290
291 /* Change queue */
292 ps->ovola = 0;
293 ps->qebeg = 0;
294 ps->qeend = 0;
295
296 /* Global Pokey controls */
297 ps->mdivk = 28;
298
299 ps->selpoly9 = 0;
300 ps->c0_hf = 0;
301 ps->c1_f0 = 0;
302 ps->c2_hf = 0;
303 ps->c3_f2 = 0;
304
305 /* SKCTL for two-tone mode */
306 ps->skctl = 0;
307
308 ps->outvol_all = 0;
309 ps->forcero = 0;
310
311 /* Channel 0 state */
312 ps->readout_0 = readout0_normal;
313 ps->event_0 = event0_pure;
314
315 ps->c0divpos = 1000;
316 ps->c0divstart = 1000;
317 ps->c0divstart_p = 1000;
318 ps->c0diva = 255;
319
320 ps->c0t1 = 0;
321 ps->c0t2 = 0;
322 ps->c0t3 = 0;
323
324 ps->c0sw1 = 0;
325 ps->c0sw2 = 0;
326 ps->c0sw3 = 0;
327 ps->c0sw4 = 0;
328 ps->c0vo = 1;
329
330 #ifndef NONLINEAR_MIXING
331 ps->c0stop = 1;
332 #endif
333
334 ps->vol0 = 0;
335
336 ps->outvol_0 = 0;
337
338
339 /* Channel 1 state */
340 ps->readout_1 = readout1_normal;
341 ps->event_1 = event1_pure;
342
343 ps->c1divpos = 1000;
344 ps->c1divstart = 1000;
345 ps->c1diva = 255;
346
347 ps->c1t1 = 0;
348 ps->c1t2 = 0;
349 ps->c1t3 = 0;
350
351 ps->c1sw1 = 0;
352 ps->c1sw2 = 0;
353 ps->c1sw3 = 0;
354 ps->c1sw4 = 0;
355 ps->c1vo = 1;
356
357 #ifndef NONLINEAR_MIXING
358 ps->c1stop = 1;
359 #endif
360
361 ps->vol1 = 0;
362
363 ps->outvol_1 = 0;
364
365 /* Channel 2 state */
366 ps->readout_2 = readout2_normal;
367 ps->event_2 = event2_pure;
368
369 ps->c2divpos = 1000;
370 ps->c2divstart = 1000;
371 ps->c2divstart_p = 1000;
372 ps->c2diva = 255;
373
374 ps->c2t1 = 0;
375 ps->c2t2 = 0;
376
377 ps->c2sw1 = 0;
378 ps->c2sw2 = 0;
379 ps->c2sw3 = 0;
380
381 ps->c2vo = 0;
382
383 #ifndef NONLINEAR_MIXING
384 ps->c2stop = 1;
385 #endif
386
387 ps->vol2 = 0;
388
389 ps->outvol_2 = 0;
390
391 /* Channel 3 state */
392 ps->readout_3 = readout3_normal;
393 ps->event_3 = event3_pure;
394
395 ps->c3divpos = 1000;
396 ps->c3divstart = 1000;
397 ps->c3diva = 255;
398
399 ps->c3t1 = 0;
400 ps->c3t2 = 0;
401
402 ps->c3sw1 = 0;
403 ps->c3sw2 = 0;
404 ps->c3sw3 = 0;
405
406 ps->c3vo = 0;
407
408 #ifndef NONLINEAR_MIXING
409 ps->c3stop = 1;
410 #endif
411
412 ps->vol3 = 0;
413
414 ps->outvol_3 = 0;
415
416 /* GTIA speaker */
417 ps->speaker = 0;
418 }
419
420
read_resam_all(PokeyState * ps)421 static double read_resam_all(PokeyState* ps)
422 {
423 int i = ps->qebeg;
424 qev_t avol,bvol;
425 double sum;
426
427 if(ps->qebeg == ps->qeend)
428 {
429 return ps->ovola * filter_data[0]; /* if no events in the queue */
430 }
431
432 avol = ps->ovola;
433 sum = 0;
434
435 /* Separate two loop cases, for wrap-around and without */
436 if(ps->qeend < ps->qebeg) /* With wrap */
437 {
438 while(i<filter_size)
439 {
440 bvol = ps->qev[i];
441 sum += (avol-bvol)*filter_data[ps->curtick - ps->qet[i]];
442 avol = bvol;
443 ++i;
444 }
445 i=0;
446 }
447
448 /* without wrap */
449 while(i<ps->qeend)
450 {
451 bvol = ps->qev[i];
452 sum += (avol-bvol)*filter_data[ps->curtick - ps->qet[i]];
453 avol = bvol;
454 ++i;
455 }
456
457 sum += avol*filter_data[0];
458 return sum;
459 }
460
461 #ifdef SYNCHRONIZED_SOUND
462 /* linear interpolation of filter data */
interp_filter_data(int pos,double frac)463 static double interp_filter_data(int pos, double frac)
464 {
465 if (pos+1 >= filter_size) {
466 return 0.0;
467 }
468 return (frac)*filter_data[pos+1]+(1-frac)*(filter_data[pos]-filter_data[filter_size-1]);
469 }
470
471 /* returns the filtered output sample value using an interpolated filter */
472 /* frac is the fractional distance of the output sample point between
473 * input sample values */
interp_read_resam_all(PokeyState * ps,double frac)474 static double interp_read_resam_all(PokeyState* ps, double frac)
475 {
476 int i = ps->qebeg;
477 qev_t avol,bvol;
478 double sum;
479
480 if (ps->qebeg == ps->qeend)
481 {
482 return ps->ovola * interp_filter_data(0,frac); /* if no events in the queue */
483 }
484
485 avol = ps->ovola;
486 sum = 0;
487
488 /* Separate two loop cases, for wrap-around and without */
489 if (ps->qeend < ps->qebeg) /* With wrap */
490 {
491 while (i < filter_size)
492 {
493 bvol = ps->qev[i];
494 sum += (avol-bvol)*interp_filter_data(ps->curtick - ps->qet[i],frac);
495 avol = bvol;
496 ++i;
497 }
498 i = 0;
499 }
500
501 /* without wrap */
502 while (i < ps->qeend)
503 {
504 bvol = ps->qev[i];
505 sum += (avol-bvol)*interp_filter_data(ps->curtick - ps->qet[i],frac);
506 avol = bvol;
507 ++i;
508 }
509
510 sum += avol*interp_filter_data(0,frac);
511
512 return sum;
513 }
514 #endif /* SYNCHRONIZED_SOUND */
515
add_change(PokeyState * ps,qev_t a)516 static void add_change(PokeyState* ps, qev_t a)
517 {
518 ps->qev[ps->qeend] = a;
519 ps->qet[ps->qeend] = ps->curtick; /*0;*/
520 ++ps->qeend;
521 if(ps->qeend >= filter_size)
522 ps->qeend = 0;
523 }
524
bump_qe_subticks(PokeyState * ps,int subticks)525 static void bump_qe_subticks(PokeyState* ps, int subticks)
526 {
527 /* Remove too old events from the queue while bumping */
528 int i = ps->qebeg;
529 /* we must avoid curtick overflow in a 32-bit int, will happen in 20 min */
530 static const int tickoverflowlimit = 1000000000;
531 ps->curtick += subticks;
532 if (ps->curtick > tickoverflowlimit) {
533 ps->curtick -= tickoverflowlimit/2;
534 for (i=0; i<filter_size; i++) {
535 if (ps->qet[i] > tickoverflowlimit/2) {
536 ps->qet[i] -= tickoverflowlimit/2;
537 }
538 }
539 }
540
541
542 if(ps->qeend < ps->qebeg) /* Loop with wrap */
543 {
544 while(i<filter_size)
545 {
546 /*ps->qet[i] += subticks;*/
547 if(ps->curtick - ps->qet[i] >= filter_size - 1)
548 {
549 ps->ovola = ps->qev[i];
550 ++ps->qebeg;
551 if(ps->qebeg >= filter_size)
552 ps->qebeg = 0;
553 }
554 else {
555 return;
556 }
557 ++i;
558 }
559 i=0;
560 }
561 /* loop without wrap */
562 while(i<ps->qeend)
563 {
564 /*ps->qet[i] += subticks;*/
565 if(ps->curtick - ps->qet[i] >= filter_size - 1)
566 {
567 ps->ovola = ps->qev[i];
568 ++ps->qebeg;
569 if(ps->qebeg >= filter_size)
570 ps->qebeg = 0;
571 }
572 else {
573 return;
574 }
575 ++i;
576 }
577 }
578
579
580
build_poly4(void)581 static void build_poly4(void)
582 {
583 unsigned char c;
584 unsigned char i;
585 unsigned char poly4=1;
586
587 for(i=0; i<15; i++)
588 {
589 poly4tbl[i] = ~poly4;
590 c = ((poly4>>2)&1) ^ ((poly4>>3)&1);
591 poly4 = ((poly4<<1)&15) + c;
592 }
593 }
594
build_poly5(void)595 static void build_poly5(void)
596 {
597 unsigned char c;
598 unsigned char i;
599 unsigned char poly5 = 1;
600
601 for(i = 0; i < 31; i++) {
602 poly5tbl[i] = ~poly5; /* Inversion! Attention! */
603 c = ((poly5 >> 2) ^ (poly5 >> 4)) & 1;
604 poly5 = ((poly5 << 1) & 31) + c;
605 }
606 }
607
build_poly17(void)608 static void build_poly17(void)
609 {
610 unsigned int c;
611 unsigned int i;
612 unsigned int poly17 = 1;
613
614 for(i = 0; i < 131071; i++) {
615 poly17tbl[i] = (unsigned char) poly17;
616 c = ((poly17 >> 11) ^ (poly17 >> 16)) & 1;
617 poly17 = ((poly17 << 1) & 131071) + c;
618 }
619 }
620
build_poly9(void)621 static void build_poly9(void)
622 {
623 unsigned int c;
624 unsigned int i;
625 unsigned int poly9 = 1;
626
627 for(i = 0; i < 511; i++) {
628 poly9tbl[i] = (unsigned char) poly9;
629 c = ((poly9 >> 3) ^ (poly9 >> 8)) & 1;
630 poly9 = ((poly9 << 1) & 511) + c;
631 }
632 }
633
advance_polies(PokeyState * ps,int tacts)634 static void advance_polies(PokeyState* ps, int tacts)
635 {
636 ps->poly4pos = (tacts + ps->poly4pos) % 15;
637 ps->poly5pos = (tacts + ps->poly5pos) % 31;
638 ps->poly17pos = (tacts + ps->poly17pos) % 131071;
639 ps->poly9pos = (tacts + ps->poly9pos) % 511;
640 }
641
642 /***********************************
643
644 READ OUTPUT 0
645
646 ************************************/
647
readout0_vo(PokeyState * ps)648 static int readout0_vo(PokeyState* ps)
649 {
650 return ps->vol0;
651 }
652
readout0_hipass(PokeyState * ps)653 static int readout0_hipass(PokeyState* ps)
654 {
655 if(ps->c0t2 ^ ps->c0t3)
656 return ps->vol0;
657 else return 0;
658 }
659
readout0_normal(PokeyState * ps)660 static int readout0_normal(PokeyState* ps)
661 {
662 if(ps->c0t2)
663 return ps->vol0;
664 else return 0;
665 }
666
667 /***********************************
668
669 READ OUTPUT 1
670
671 ************************************/
672
readout1_vo(PokeyState * ps)673 static int readout1_vo(PokeyState* ps)
674 {
675 return ps->vol1;
676 }
677
readout1_hipass(PokeyState * ps)678 static int readout1_hipass(PokeyState* ps)
679 {
680 if(ps->c1t2 ^ ps->c1t3)
681 return ps->vol1;
682 else return 0;
683 }
684
readout1_normal(PokeyState * ps)685 static int readout1_normal(PokeyState* ps)
686 {
687 if(ps->c1t2)
688 return ps->vol1;
689 else return 0;
690 }
691
692 /***********************************
693
694 READ OUTPUT 2
695
696 ************************************/
697
readout2_vo(PokeyState * ps)698 static int readout2_vo(PokeyState* ps)
699 {
700 return ps->vol2;
701 }
702
readout2_normal(PokeyState * ps)703 static int readout2_normal(PokeyState* ps)
704 {
705 if(ps->c2t2)
706 return ps->vol2;
707 else return 0;
708 }
709
710 /***********************************
711
712 READ OUTPUT 3
713
714 ************************************/
715
readout3_vo(PokeyState * ps)716 static int readout3_vo(PokeyState* ps)
717 {
718 return ps->vol3;
719 }
720
readout3_normal(PokeyState * ps)721 static int readout3_normal(PokeyState* ps)
722 {
723 if(ps->c3t2)
724 return ps->vol3;
725 else return 0;
726 }
727
728
729 /***********************************
730
731 EVENT CHANNEL 0
732
733 ************************************/
734
event0_pure(PokeyState * ps,int p5v,int p4v,int p917v)735 static void event0_pure(PokeyState* ps, int p5v, int p4v, int p917v)
736 {
737 ps->c0t2 = !ps->c0t2;
738 ps->c0t1 = p5v;
739 }
740
event0_p5(PokeyState * ps,int p5v,int p4v,int p917v)741 static void event0_p5(PokeyState* ps, int p5v, int p4v, int p917v)
742 {
743 if(ps->c0t1)
744 ps->c0t2 = !ps->c0t2;
745 ps->c0t1 = p5v;
746 }
747
event0_p4(PokeyState * ps,int p5v,int p4v,int p917v)748 static void event0_p4(PokeyState* ps, int p5v, int p4v, int p917v)
749 {
750 ps->c0t2 = p4v;
751 ps->c0t1 = p5v;
752 }
753
event0_p917(PokeyState * ps,int p5v,int p4v,int p917v)754 static void event0_p917(PokeyState* ps, int p5v, int p4v, int p917v)
755 {
756 ps->c0t2 = p917v;
757 ps->c0t1 = p5v;
758 }
759
event0_p4_p5(PokeyState * ps,int p5v,int p4v,int p917v)760 static void event0_p4_p5(PokeyState* ps, int p5v, int p4v, int p917v)
761 {
762 if(ps->c0t1)
763 ps->c0t2 = p4v;
764 ps->c0t1 = p5v;
765 }
766
event0_p917_p5(PokeyState * ps,int p5v,int p4v,int p917v)767 static void event0_p917_p5(PokeyState* ps, int p5v, int p4v, int p917v)
768 {
769 if(ps->c0t1)
770 ps->c0t2 = p917v;
771 ps->c0t1 = p5v;
772 }
773
774 /***********************************
775
776 EVENT CHANNEL 1
777
778 ************************************/
779
event1_pure(PokeyState * ps,int p5v,int p4v,int p917v)780 static void event1_pure(PokeyState* ps, int p5v, int p4v, int p917v)
781 {
782 ps->c1t2 = !ps->c1t2;
783 ps->c1t1 = p5v;
784 }
785
event1_p5(PokeyState * ps,int p5v,int p4v,int p917v)786 static void event1_p5(PokeyState* ps, int p5v, int p4v, int p917v)
787 {
788 if(ps->c1t1)
789 ps->c1t2 = !ps->c1t2;
790 ps->c1t1 = p5v;
791 }
792
event1_p4(PokeyState * ps,int p5v,int p4v,int p917v)793 static void event1_p4(PokeyState* ps, int p5v, int p4v, int p917v)
794 {
795 ps->c1t2 = p4v;
796 ps->c1t1 = p5v;
797 }
798
event1_p917(PokeyState * ps,int p5v,int p4v,int p917v)799 static void event1_p917(PokeyState* ps, int p5v, int p4v, int p917v)
800 {
801 ps->c1t2 = p917v;
802 ps->c1t1 = p5v;
803 }
804
event1_p4_p5(PokeyState * ps,int p5v,int p4v,int p917v)805 static void event1_p4_p5(PokeyState* ps, int p5v, int p4v, int p917v)
806 {
807 if(ps->c1t1)
808 ps->c1t2 = p4v;
809 ps->c1t1 = p5v;
810 }
811
event1_p917_p5(PokeyState * ps,int p5v,int p4v,int p917v)812 static void event1_p917_p5(PokeyState* ps, int p5v, int p4v, int p917v)
813 {
814 if(ps->c1t1)
815 ps->c1t2 = p917v;
816 ps->c1t1 = p5v;
817 }
818
819 /***********************************
820
821 EVENT CHANNEL 2
822
823 ************************************/
824
event2_pure(PokeyState * ps,int p5v,int p4v,int p917v)825 static void event2_pure(PokeyState* ps, int p5v, int p4v, int p917v)
826 {
827 ps->c2t2 = !ps->c2t2;
828 ps->c2t1 = p5v;
829 /* high-pass clock for channel 0 */
830 ps->c0t3 = ps->c0t2;
831 }
832
event2_p5(PokeyState * ps,int p5v,int p4v,int p917v)833 static void event2_p5(PokeyState* ps, int p5v, int p4v, int p917v)
834 {
835 if(ps->c2t1)
836 ps->c2t2 = !ps->c2t2;
837 ps->c2t1 = p5v;
838 /* high-pass clock for channel 0 */
839 ps->c0t3 = ps->c0t2;
840 }
841
event2_p4(PokeyState * ps,int p5v,int p4v,int p917v)842 static void event2_p4(PokeyState* ps, int p5v, int p4v, int p917v)
843 {
844 ps->c2t2 = p4v;
845 ps->c2t1 = p5v;
846 /* high-pass clock for channel 0 */
847 ps->c0t3 = ps->c0t2;
848 }
849
event2_p917(PokeyState * ps,int p5v,int p4v,int p917v)850 static void event2_p917(PokeyState* ps, int p5v, int p4v, int p917v)
851 {
852 ps->c2t2 = p917v;
853 ps->c2t1 = p5v;
854 /* high-pass clock for channel 0 */
855 ps->c0t3 = ps->c0t2;
856 }
857
event2_p4_p5(PokeyState * ps,int p5v,int p4v,int p917v)858 static void event2_p4_p5(PokeyState* ps, int p5v, int p4v, int p917v)
859 {
860 if(ps->c2t1)
861 ps->c2t2 = p4v;
862 ps->c2t1 = p5v;
863 /* high-pass clock for channel 0 */
864 ps->c0t3 = ps->c0t2;
865 }
866
event2_p917_p5(PokeyState * ps,int p5v,int p4v,int p917v)867 static void event2_p917_p5(PokeyState* ps, int p5v, int p4v, int p917v)
868 {
869 if(ps->c2t1)
870 ps->c2t2 = p917v;
871 ps->c2t1 = p5v;
872 /* high-pass clock for channel 0 */
873 ps->c0t3 = ps->c0t2;
874 }
875
876 /***********************************
877
878 EVENT CHANNEL 3
879
880 ************************************/
881
event3_pure(PokeyState * ps,int p5v,int p4v,int p917v)882 static void event3_pure(PokeyState* ps, int p5v, int p4v, int p917v)
883 {
884 ps->c3t2 = !ps->c3t2;
885 ps->c3t1 = p5v;
886 /* high-pass clock for channel 1 */
887 ps->c1t3 = ps->c1t2;
888 }
889
event3_p5(PokeyState * ps,int p5v,int p4v,int p917v)890 static void event3_p5(PokeyState* ps, int p5v, int p4v, int p917v)
891 {
892 if(ps->c3t1)
893 ps->c3t2 = !ps->c3t2;
894 ps->c3t1 = p5v;
895 /* high-pass clock for channel 1 */
896 ps->c1t3 = ps->c1t2;
897 }
898
event3_p4(PokeyState * ps,int p5v,int p4v,int p917v)899 static void event3_p4(PokeyState* ps, int p5v, int p4v, int p917v)
900 {
901 ps->c3t2 = p4v;
902 ps->c3t1 = p5v;
903 /* high-pass clock for channel 1 */
904 ps->c1t3 = ps->c1t2;
905 }
906
event3_p917(PokeyState * ps,int p5v,int p4v,int p917v)907 static void event3_p917(PokeyState* ps, int p5v, int p4v, int p917v)
908 {
909 ps->c3t2 = p917v;
910 ps->c3t1 = p5v;
911 /* high-pass clock for channel 1 */
912 ps->c1t3 = ps->c1t2;
913 }
914
event3_p4_p5(PokeyState * ps,int p5v,int p4v,int p917v)915 static void event3_p4_p5(PokeyState* ps, int p5v, int p4v, int p917v)
916 {
917 if(ps->c3t1)
918 ps->c3t2 = p4v;
919 ps->c3t1 = p5v;
920 /* high-pass clock for channel 1 */
921 ps->c1t3 = ps->c1t2;
922 }
923
event3_p917_p5(PokeyState * ps,int p5v,int p4v,int p917v)924 static void event3_p917_p5(PokeyState* ps, int p5v, int p4v, int p917v)
925 {
926 if(ps->c3t1)
927 ps->c3t2 = p917v;
928 ps->c3t1 = p5v;
929 /* high-pass clock for channel 1 */
930 ps->c1t3 = ps->c1t2;
931 }
932
advance_ticks(PokeyState * ps,int ticks)933 static void advance_ticks(PokeyState* ps, int ticks)
934 {
935 int ta,tbe, tbe0, tbe1, tbe2, tbe3;
936 int p5v,p4v,p917v;
937
938 qev_t outvol_new;
939 int need0=0;
940 int need1=0;
941 int need2=0;
942 int need3=0;
943
944 int need=0;
945
946 if (ticks <= 0) return;
947 if(ps->forcero)
948 {
949 ps->forcero = 0;
950 #ifdef NONLINEAR_MIXING
951 #ifdef SYNCHRONIZED_SOUND
952 outvol_new = pokeymix[ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3 + ps->speaker];
953 #else
954 outvol_new = pokeymix[ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3];
955 #endif /* SYNCHRONIZED_SOUND */
956 #else
957 outvol_new = ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3;
958 #ifdef SYNCHRONIZED_SOUND
959 outvol_new += ps->speaker;
960 #endif /* SYNCHRONIZED_SOUND */
961 #endif /* NONLINEAR_MIXING */
962 if(outvol_new != ps->outvol_all)
963 {
964 ps->outvol_all = outvol_new;
965 add_change(ps, outvol_new);
966 }
967 }
968
969 while(ticks>0)
970 {
971 tbe0 = ps->c0divpos;
972 tbe1 = ps->c1divpos;
973 tbe2 = ps->c2divpos;
974 tbe3 = ps->c3divpos;
975
976 tbe = ticks+1;
977
978 #ifdef NONLINEAR_MIXING
979 if(tbe0 < tbe)
980 tbe = tbe0;
981 if(tbe1 < tbe)
982 tbe = tbe1;
983 if(tbe2 < tbe)
984 tbe = tbe2;
985 if(tbe3 < tbe)
986 tbe = tbe3;
987 #else
988 if(!ps->c0stop && tbe0 < tbe)
989 tbe = tbe0;
990 if(!ps->c1stop && tbe1 < tbe)
991 tbe = tbe1;
992 if(!ps->c2stop && tbe2 < tbe)
993 tbe = tbe2;
994 if(!ps->c3stop && tbe3 < tbe)
995 tbe = tbe3;
996 #endif
997
998 if(tbe>ticks)
999 ta = ticks;
1000 else
1001 {
1002 ta = tbe;
1003 need = 1;
1004 }
1005
1006 ticks -= ta;
1007
1008 #ifdef NONLINEAR_MIXING
1009 ps->c0divpos -= ta;
1010 ps->c1divpos -= ta;
1011 ps->c2divpos -= ta;
1012 ps->c3divpos -= ta;
1013 #else
1014 if(!ps->c0stop) ps->c0divpos -= ta;
1015 if(!ps->c1stop) ps->c1divpos -= ta;
1016 if(!ps->c2stop) ps->c2divpos -= ta;
1017 if(!ps->c3stop) ps->c3divpos -= ta;
1018 #endif
1019
1020 advance_polies(ps,ta);
1021 bump_qe_subticks(ps,ta);
1022
1023 if(need)
1024 {
1025 p5v = poly5tbl[ps->poly5pos] & 1;
1026 p4v = poly4tbl[ps->poly4pos] & 1;
1027 if(ps->selpoly9)
1028 p917v = poly9tbl[ps->poly9pos] & 1;
1029 else
1030 p917v = poly17tbl[ps->poly17pos] & 1;
1031
1032 #ifdef NONLINEAR_MIXING
1033 if(ta == tbe0)
1034 #else
1035 if(!ps->c0stop && ta == tbe0)
1036 #endif
1037 {
1038 ps->event_0(ps,p5v,p4v,p917v);
1039 ps->c0divpos = ps->c0divstart;
1040 need0 = 1;
1041 }
1042 #ifdef NONLINEAR_MIXING
1043 if(ta == tbe1)
1044 #else
1045 if(!ps->c1stop && ta == tbe1)
1046 #endif
1047 {
1048 ps->event_1(ps,p5v,p4v,p917v);
1049 ps->c1divpos = ps->c1divstart;
1050 if(ps->c1_f0)
1051 ps->c0divpos = ps->c0divstart_p;
1052 need1 = 1;
1053 /*two-tone filter*/
1054 /*use if send break is on and two-tone mode is on*/
1055 /*reset channel 1 if channel 2 changed*/
1056 if((ps->skctl & 0x88) == 0x88) {
1057 ps->c0divpos = ps->c0divstart;
1058 /* it doesn't change the output state */
1059 /*need0 = 1;*/
1060 }
1061 }
1062 #ifdef NONLINEAR_MIXING
1063 if(ta == tbe2)
1064 #else
1065 if(!ps->c2stop && ta == tbe2)
1066 #endif
1067 {
1068 ps->event_2(ps,p5v,p4v,p917v);
1069 ps->c2divpos = ps->c2divstart;
1070 need2 = 1;
1071 if(ps->c0sw4)
1072 need0 = 1;
1073 }
1074 #ifdef NONLINEAR_MIXING
1075 if(ta == tbe3)
1076 #else
1077 if(!ps->c3stop && ta == tbe3)
1078 #endif
1079 {
1080 ps->event_3(ps,p5v,p4v,p917v);
1081 ps->c3divpos = ps->c3divstart;
1082 if(ps->c3_f2)
1083 ps->c2divpos = ps->c2divstart_p;
1084 need3 = 1;
1085 if(ps->c1sw4)
1086 need1 = 1;
1087 }
1088
1089 if(need0)
1090 {
1091 #ifdef NONLINEAR_MIXING
1092 ps->outvol_0 = ps->readout_0(ps);
1093 #else
1094 ps->outvol_0 = 2*ps->readout_0(ps);
1095 #endif
1096 }
1097 if(need1)
1098 {
1099 #ifdef NONLINEAR_MIXING
1100 ps->outvol_1 = ps->readout_1(ps);
1101 #else
1102 ps->outvol_1 = 2*ps->readout_1(ps);
1103 #endif
1104 }
1105 if(need2)
1106 {
1107 #ifdef NONLINEAR_MIXING
1108 ps->outvol_2 = ps->readout_2(ps);
1109 #else
1110 ps->outvol_2 = 2*ps->readout_2(ps);
1111 #endif
1112 }
1113 if(need3)
1114 {
1115 #ifdef NONLINEAR_MIXING
1116 ps->outvol_3 = ps->readout_3(ps);
1117 #else
1118 ps->outvol_3 = 2*ps->readout_3(ps);
1119 #endif
1120 }
1121
1122 #ifdef NONLINEAR_MIXING
1123 #ifdef SYNCHRONIZED_SOUND
1124 outvol_new = pokeymix[ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3 + ps->speaker];
1125 #else
1126 outvol_new = pokeymix[ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3];
1127 #endif /* SYNCHRONIZED_SOUND */
1128 #else
1129 outvol_new = ps->outvol_0 + ps->outvol_1 + ps->outvol_2 + ps->outvol_3;
1130 #ifdef SYNCHRONIZED_SOUND
1131 outvol_new += ps->speaker;
1132 #endif /* SYNCHRONIZED_SOUND */
1133 #endif /* NONLINEAR_MIXING */
1134 if(outvol_new != ps->outvol_all)
1135 {
1136 ps->outvol_all = outvol_new;
1137 add_change(ps, outvol_new);
1138 }
1139 }
1140 }
1141 }
1142
generate_sample(PokeyState * ps)1143 static double generate_sample(PokeyState* ps)
1144 {
1145 /*unsigned long ta = (subticks+pokey_frq)/POKEYSND_playback_freq;
1146 subticks = (subticks+pokey_frq)%POKEYSND_playback_freq;*/
1147
1148 advance_ticks(ps, pokey_frq/POKEYSND_playback_freq);
1149 return read_resam_all(ps);
1150 }
1151
1152 /******************************************
1153 filter table generator by Krzysztof Nikiel
1154 ******************************************/
1155
remez_filter_table(double resamp_rate,double * cutoff,int quality)1156 static int remez_filter_table(double resamp_rate, /* output_rate/input_rate */
1157 double *cutoff, int quality)
1158 {
1159 int i;
1160 static const int orders[] = {600, 800, 1000, 1200};
1161 static const struct {
1162 int stop; /* stopband ripple */
1163 double weight; /* stopband weight */
1164 double twidth[sizeof(orders)/sizeof(orders[0])];
1165 } paramtab[] =
1166 {
1167 {70, 90, {4.9e-3, 3.45e-3, 2.65e-3, 2.2e-3}},
1168 {55, 25, {3.4e-3, 2.7e-3, 2.05e-3, 1.7e-3}},
1169 {40, 6.0, {2.6e-3, 1.8e-3, 1.5e-3, 1.2e-3}},
1170 {-1, 0, {0, 0, 0, 0}}
1171 };
1172 static const double passtab[] = {0.5, 0.6, 0.7};
1173 int ripple = 0, order = 0;
1174 int size;
1175 double weights[2], desired[2], bands[4];
1176 static const int interlevel = 5;
1177 double step = 1.0 / interlevel;
1178
1179 *cutoff = 0.95 * 0.5 * resamp_rate;
1180
1181 if (quality >= (int) (sizeof(passtab) / sizeof(passtab[0])))
1182 quality = (int) (sizeof(passtab) / sizeof(passtab[0])) - 1;
1183
1184 for (ripple = 0; paramtab[ripple].stop > 0; ripple++)
1185 {
1186 for (order = 0; order < (int) (sizeof(orders)/sizeof(orders[0])); order++)
1187 {
1188 if ((*cutoff - paramtab[ripple].twidth[order])
1189 > passtab[quality] * 0.5 * resamp_rate)
1190 /* transition width OK */
1191 goto found;
1192 }
1193 }
1194
1195 /* not found -- use shortest transition */
1196 ripple--;
1197 order--;
1198
1199 found:
1200
1201 #if 0
1202 printf("order: %d, cutoff: %g\tstopband:%d\ttranswidth:%f\n",
1203 orders[order],
1204 1789790 * *cutoff,
1205 paramtab[ripple].stop,
1206 1789790 * paramtab[ripple].twidth[order]);
1207 exit(1);
1208 #endif
1209
1210 size = orders[order] + 1;
1211
1212 if (size > SND_FILTER_SIZE) /* static table too short */
1213 return 0;
1214
1215 desired[0] = 1;
1216 desired[1] = 0;
1217
1218 weights[0] = 1;
1219 weights[1] = paramtab[ripple].weight;
1220
1221 bands[0] = 0;
1222 bands[2] = *cutoff;
1223 bands[1] = bands[2] - paramtab[ripple].twidth[order];
1224 bands[3] = 0.5;
1225
1226 bands[1] *= (double)interlevel;
1227 bands[2] *= (double)interlevel;
1228 REMEZ_CreateFilter(filter_data, (size / interlevel) + 1, 2, bands, desired, weights, REMEZ_BANDPASS);
1229 for (i = size - interlevel; i >= 0; i -= interlevel)
1230 {
1231 int s;
1232 double h1 = filter_data[i/interlevel];
1233 double h2 = filter_data[i/interlevel+1];
1234
1235 for (s = 0; s < interlevel; s++)
1236 {
1237 double d = (double)s * step;
1238 filter_data[i+s] = (h1*(1.0 - d) + h2 * d) * step;
1239 }
1240 }
1241
1242 /* compute reversed cumulative sum table */
1243 for (i = size - 2; i >= 0; i--)
1244 filter_data[i] += filter_data[i + 1];
1245
1246 #if 0
1247 for (i = 0; i < size; i++)
1248 printf("%.15f,\n", filter_data[i]);
1249 fflush(stdout);
1250 exit(1);
1251 #endif
1252
1253 return size;
1254 }
1255
1256 static void mzpokeysnd_process_8(void* sndbuffer, int sndn);
1257 static void mzpokeysnd_process_16(void* sndbuffer, int sndn);
1258 static void Update_pokey_sound_mz(UWORD addr, UBYTE val, UBYTE chip, UBYTE gain);
1259 #ifdef SERIO_SOUND
1260 static void Update_serio_sound_mz(int out, UBYTE data);
1261 #endif
1262 #ifdef CONSOLE_SOUND
1263 static void Update_consol_sound_mz( int set );
1264 #endif
1265 #ifdef VOL_ONLY_SOUND
1266 static void Update_vol_only_sound_mz( void );
1267 #endif
1268
1269 /*****************************************************************************/
1270 /* Module: MZPOKEYSND_Init() */
1271 /* Purpose: to handle the power-up initialization functions */
1272 /* these functions should only be executed on a cold-restart */
1273 /* */
1274 /* Authors: Michael Borisov, Krzystof Nikiel */
1275 /* */
1276 /* Inputs: freq17 - the value for the '1.79MHz' Pokey audio clock */
1277 /* playback_freq - the playback frequency in samples per second */
1278 /* num_pokeys - specifies the number of pokey chips to be emulated */
1279 /* */
1280 /* Outputs: Adjusts local globals - no return value */
1281 /* */
1282 /*****************************************************************************/
1283
1284 #ifdef SYNCHRONIZED_SOUND
1285 static void generate_sync(unsigned int num_ticks);
1286
init_syncsound(void)1287 static void init_syncsound(void)
1288 {
1289 double samples_per_frame = (double)POKEYSND_playback_freq/(Atari800_tv_mode == Atari800_TV_PAL ? Atari800_FPS_PAL : Atari800_FPS_NTSC);
1290 unsigned int ticks_per_frame = Atari800_tv_mode*114;
1291 ticks_per_sample = (double)ticks_per_frame / samples_per_frame;
1292 samp_pos = 0.0;
1293 POKEYSND_GenerateSync = generate_sync;
1294 }
1295 #endif /* SYNCHRONIZED_SOUND */
1296
MZPOKEYSND_Init(ULONG freq17,int playback_freq,UBYTE num_pokeys,int flags,int quality,int clear_regs)1297 int MZPOKEYSND_Init(ULONG freq17, int playback_freq, UBYTE num_pokeys,
1298 int flags, int quality
1299 #ifdef __PLUS
1300 , int clear_regs
1301 #endif
1302 )
1303 {
1304 double cutoff;
1305
1306 snd_quality = quality;
1307
1308 POKEYSND_Update_ptr = Update_pokey_sound_mz;
1309 #ifdef SERIO_SOUND
1310 POKEYSND_UpdateSerio = Update_serio_sound_mz;
1311 #endif
1312 #ifdef CONSOLE_SOUND
1313 POKEYSND_UpdateConsol_ptr = Update_consol_sound_mz;
1314 #endif
1315 #ifdef VOL_ONLY_SOUND
1316 POKEYSND_UpdateVolOnly = Update_vol_only_sound_mz;
1317 #endif
1318
1319 #ifdef VOL_ONLY_SOUND
1320 POKEYSND_samp_freq=playback_freq;
1321 #endif /* VOL_ONLY_SOUND */
1322
1323 POKEYSND_Process_ptr = (flags & POKEYSND_BIT16) ? mzpokeysnd_process_16 : mzpokeysnd_process_8;
1324
1325 switch(playback_freq)
1326 {
1327 #if 0
1328 case 44100:
1329 if(flags & POKEYSND_BIT16)
1330 {
1331 filter_data = filter_44;
1332 filter_size = filter_size_44;
1333 }
1334 else
1335 {
1336 filter_data = filter_44_8;
1337 filter_size = filter_size_44_8;
1338 }
1339 pokey_frq = 1808100; /* 1.02% off ideal */
1340 audible_frq = 20000; /* ultrasound */
1341 break;
1342 case 22050:
1343 if(flags & POKEYSND_BIT16)
1344 {
1345 filter_data = filter_22;
1346 filter_size = filter_size_22;
1347 }
1348 else
1349 {
1350 filter_data = filter_22_8;
1351 filter_size = filter_size_22_8;
1352 }
1353 pokey_frq = 1786050; /* 0.2% off ideal */
1354 audible_frq = 10000; /* 30db filter attenuation */
1355 break;
1356 case 11025:
1357 if(flags & POKEYSND_BIT16)
1358 {
1359 filter_data = filter_11;
1360 filter_size = filter_size_11;
1361 }
1362 else
1363 {
1364 filter_data = filter_11_8;
1365 filter_size = filter_size_11_8;
1366 }
1367 pokey_frq = 1786050; /* 0.2% off ideal */
1368 audible_frq = 4500; /* 30db filter attenuation */
1369 break;
1370 case 48000:
1371 if(flags & POKEYSND_BIT16)
1372 {
1373 filter_data = filter_48;
1374 filter_size = filter_size_48;
1375 }
1376 else
1377 {
1378 filter_data = filter_48_8;
1379 filter_size = filter_size_48_8;
1380 }
1381 pokey_frq = 1776000; /* 0.7% off ideal */
1382 audible_frq = 20000; /* ultrasound */
1383 break;
1384 case 8000:
1385 if(flags & POKEYSND_BIT16)
1386 {
1387 filter_data = filter_8;
1388 filter_size = filter_size_8;
1389 }
1390 else
1391 {
1392 filter_data = filter_8_8;
1393 filter_size = filter_size_8_8;
1394 }
1395 pokey_frq = 1792000; /* 0.1% off ideal */
1396 audible_frq = 4000; /* Nyquist, also 30db attn, should be 50 */
1397 break;
1398 #endif
1399 default:
1400 pokey_frq = (int)(((double)pokey_frq_ideal/POKEYSND_playback_freq) + 0.5)
1401 * POKEYSND_playback_freq;
1402 filter_size = remez_filter_table((double)POKEYSND_playback_freq/pokey_frq,
1403 &cutoff, quality);
1404 audible_frq = (int ) (cutoff * pokey_frq);
1405 }
1406
1407 build_poly4();
1408 build_poly5();
1409 build_poly9();
1410 build_poly17();
1411
1412 #ifdef __PLUS
1413 if (clear_regs)
1414 #endif
1415 {
1416 ResetPokeyState(pokey_states);
1417 ResetPokeyState(pokey_states + 1);
1418 }
1419 num_cur_pokeys = num_pokeys;
1420
1421 #ifdef SYNCHRONIZED_SOUND
1422 init_syncsound();
1423 #endif
1424 return 0; /* OK */
1425 }
1426
1427
Update_readout_0(PokeyState * ps)1428 static void Update_readout_0(PokeyState* ps)
1429 {
1430 if(ps->c0vo)
1431 ps->readout_0 = readout0_vo;
1432 else if(ps->c0sw4)
1433 ps->readout_0 = readout0_hipass;
1434 else
1435 ps->readout_0 = readout0_normal;
1436 }
1437
Update_readout_1(PokeyState * ps)1438 static void Update_readout_1(PokeyState* ps)
1439 {
1440 if(ps->c1vo)
1441 ps->readout_1 = readout1_vo;
1442 else if(ps->c1sw4)
1443 ps->readout_1 = readout1_hipass;
1444 else
1445 ps->readout_1 = readout1_normal;
1446 }
1447
Update_readout_2(PokeyState * ps)1448 static void Update_readout_2(PokeyState* ps)
1449 {
1450 if(ps->c2vo)
1451 ps->readout_2 = readout2_vo;
1452 else
1453 ps->readout_2 = readout2_normal;
1454 }
1455
Update_readout_3(PokeyState * ps)1456 static void Update_readout_3(PokeyState* ps)
1457 {
1458 if(ps->c3vo)
1459 ps->readout_3 = readout3_vo;
1460 else
1461 ps->readout_3 = readout3_normal;
1462 }
1463
Update_event0(PokeyState * ps)1464 static void Update_event0(PokeyState* ps)
1465 {
1466 if(ps->c0sw3)
1467 {
1468 if(ps->c0sw2)
1469 ps->event_0 = event0_pure;
1470 else
1471 {
1472 if(ps->c0sw1)
1473 ps->event_0 = event0_p4;
1474 else
1475 ps->event_0 = event0_p917;
1476 }
1477 }
1478 else
1479 {
1480 if(ps->c0sw2)
1481 ps->event_0 = event0_p5;
1482 else
1483 {
1484 if(ps->c0sw1)
1485 ps->event_0 = event0_p4_p5;
1486 else
1487 ps->event_0 = event0_p917_p5;
1488 }
1489 }
1490 }
1491
Update_event1(PokeyState * ps)1492 static void Update_event1(PokeyState* ps)
1493 {
1494 if(ps->c1sw3)
1495 {
1496 if(ps->c1sw2)
1497 ps->event_1 = event1_pure;
1498 else
1499 {
1500 if(ps->c1sw1)
1501 ps->event_1 = event1_p4;
1502 else
1503 ps->event_1 = event1_p917;
1504 }
1505 }
1506 else
1507 {
1508 if(ps->c1sw2)
1509 ps->event_1 = event1_p5;
1510 else
1511 {
1512 if(ps->c1sw1)
1513 ps->event_1 = event1_p4_p5;
1514 else
1515 ps->event_1 = event1_p917_p5;
1516 }
1517 }
1518 }
1519
Update_event2(PokeyState * ps)1520 static void Update_event2(PokeyState* ps)
1521 {
1522 if(ps->c2sw3)
1523 {
1524 if(ps->c2sw2)
1525 ps->event_2 = event2_pure;
1526 else
1527 {
1528 if(ps->c2sw1)
1529 ps->event_2 = event2_p4;
1530 else
1531 ps->event_2 = event2_p917;
1532 }
1533 }
1534 else
1535 {
1536 if(ps->c2sw2)
1537 ps->event_2 = event2_p5;
1538 else
1539 {
1540 if(ps->c2sw1)
1541 ps->event_2 = event2_p4_p5;
1542 else
1543 ps->event_2 = event2_p917_p5;
1544 }
1545 }
1546 }
1547
Update_event3(PokeyState * ps)1548 static void Update_event3(PokeyState* ps)
1549 {
1550 if(ps->c3sw3)
1551 {
1552 if(ps->c3sw2)
1553 ps->event_3 = event3_pure;
1554 else
1555 {
1556 if(ps->c3sw1)
1557 ps->event_3 = event3_p4;
1558 else
1559 ps->event_3 = event3_p917;
1560 }
1561 }
1562 else
1563 {
1564 if(ps->c3sw2)
1565 ps->event_3 = event3_p5;
1566 else
1567 {
1568 if(ps->c3sw1)
1569 ps->event_3 = event3_p4_p5;
1570 else
1571 ps->event_3 = event3_p917_p5;
1572 }
1573 }
1574 }
1575
Update_c0divstart(PokeyState * ps)1576 static void Update_c0divstart(PokeyState* ps)
1577 {
1578 if(ps->c1_f0)
1579 {
1580 if(ps->c0_hf)
1581 {
1582 ps->c0divstart = 256;
1583 ps->c0divstart_p = ps->c0diva + 7;
1584 }
1585 else
1586 {
1587 ps->c0divstart = 256 * ps->mdivk;
1588 ps->c0divstart_p = (ps->c0diva+1)*ps->mdivk;
1589 }
1590 }
1591 else
1592 {
1593 if(ps->c0_hf)
1594 ps->c0divstart = ps->c0diva + 4;
1595 else
1596 ps->c0divstart = (ps->c0diva+1) * ps->mdivk;
1597 }
1598 }
1599
Update_c1divstart(PokeyState * ps)1600 static void Update_c1divstart(PokeyState* ps)
1601 {
1602 if(ps->c1_f0)
1603 {
1604 if(ps->c0_hf)
1605 ps->c1divstart = ps->c0diva + 256*ps->c1diva + 7;
1606 else
1607 ps->c1divstart = (ps->c0diva + 256*ps->c1diva + 1) * ps->mdivk;
1608 }
1609 else
1610 ps->c1divstart = (ps->c1diva + 1) * ps->mdivk;
1611 }
1612
Update_c2divstart(PokeyState * ps)1613 static void Update_c2divstart(PokeyState* ps)
1614 {
1615 if(ps->c3_f2)
1616 {
1617 if(ps->c2_hf)
1618 {
1619 ps->c2divstart = 256;
1620 ps->c2divstart_p = ps->c2diva + 7;
1621 }
1622 else
1623 {
1624 ps->c2divstart = 256 * ps->mdivk;
1625 ps->c2divstart_p = (ps->c2diva+1)*ps->mdivk;
1626 }
1627 }
1628 else
1629 {
1630 if(ps->c2_hf)
1631 ps->c2divstart = ps->c2diva + 4;
1632 else
1633 ps->c2divstart = (ps->c2diva+1) * ps->mdivk;
1634 }
1635 }
1636
Update_c3divstart(PokeyState * ps)1637 static void Update_c3divstart(PokeyState* ps)
1638 {
1639 if(ps->c3_f2)
1640 {
1641 if(ps->c2_hf)
1642 ps->c3divstart = ps->c2diva + 256*ps->c3diva + 7;
1643 else
1644 ps->c3divstart = (ps->c2diva + 256*ps->c3diva + 1) * ps->mdivk;
1645 }
1646 else
1647 ps->c3divstart = (ps->c3diva + 1) * ps->mdivk;
1648 }
1649
Update_audctl(PokeyState * ps,unsigned char val)1650 static void Update_audctl(PokeyState* ps, unsigned char val)
1651 {
1652 int nc0_hf,nc2_hf,nc1_f0,nc3_f2,nc0sw4,nc1sw4,new_divk;
1653 int recalc0=0;
1654 int recalc1=0;
1655 int recalc2=0;
1656 int recalc3=0;
1657
1658 unsigned int cnt0 = 0;
1659 unsigned int cnt1 = 0;
1660 unsigned int cnt2 = 0;
1661 unsigned int cnt3 = 0;
1662
1663 nc0_hf = (val & 0x40) != 0;
1664 nc2_hf = (val & 0x20) != 0;
1665 nc1_f0 = (val & 0x10) != 0;
1666 nc3_f2 = (val & 0x08) != 0;
1667 nc0sw4 = (val & 0x04) != 0;
1668 nc1sw4 = (val & 0x02) != 0;
1669 if(val & 0x01)
1670 new_divk = 114;
1671 else
1672 new_divk = 28;
1673
1674 if(new_divk != ps->mdivk)
1675 {
1676 recalc0 = recalc1 = recalc2 = recalc3 = 1;
1677 }
1678 if(nc1_f0 != ps->c1_f0)
1679 {
1680 recalc0 = recalc1 = 1;
1681 }
1682 if(nc3_f2 != ps->c3_f2)
1683 {
1684 recalc2 = recalc3 = 1;
1685 }
1686 if(nc0_hf != ps->c0_hf)
1687 {
1688 recalc0 = 1;
1689 if(nc1_f0)
1690 recalc1 = 1;
1691 }
1692 if(nc2_hf != ps->c2_hf)
1693 {
1694 recalc2 = 1;
1695 if(nc3_f2)
1696 recalc3 = 1;
1697 }
1698
1699 if(recalc0)
1700 {
1701 if(ps->c0_hf)
1702 cnt0 = ps->c0divpos;
1703 else
1704 cnt0 = ps->c0divpos/ps->mdivk;
1705 }
1706 if(recalc1)
1707 {
1708 if(ps->c1_f0)
1709 {
1710 if(ps->c0_hf)
1711 cnt1 = ps->c1divpos/256;
1712 else
1713 cnt1 = ps->c1divpos/256/ps->mdivk;
1714 }
1715 else
1716 {
1717 cnt1 = ps->c1divpos/ps->mdivk;
1718 }
1719 }
1720 if(recalc2)
1721 {
1722 if(ps->c2_hf)
1723 cnt2 = ps->c2divpos;
1724 else
1725 cnt2 = ps->c2divpos/ps->mdivk;
1726 }
1727 if(recalc3)
1728 {
1729 if(ps->c3_f2)
1730 {
1731 if(ps->c2_hf)
1732 cnt3 = ps->c3divpos/256;
1733 else
1734 cnt3 = ps->c3divpos/256/ps->mdivk;
1735 }
1736 }
1737
1738 if(recalc0)
1739 {
1740 if(nc0_hf)
1741 ps->c0divpos = cnt0;
1742 else
1743 ps->c0divpos = cnt0*new_divk;
1744 }
1745 if(recalc1)
1746 {
1747 if(nc1_f0)
1748 {
1749 if(nc0_hf)
1750 ps->c1divpos = cnt1*256+cnt0;
1751 else
1752 ps->c1divpos = (cnt1*256+cnt0)*new_divk;
1753 }
1754 else
1755 {
1756 ps->c1divpos = cnt1*new_divk;
1757 }
1758 }
1759
1760 if(recalc2)
1761 {
1762 if(nc2_hf)
1763 ps->c2divpos = cnt2;
1764 else
1765 ps->c2divpos = cnt2*new_divk;
1766 }
1767 if(recalc3)
1768 {
1769 if(nc3_f2)
1770 {
1771 if(nc2_hf)
1772 ps->c3divpos = cnt3*256+cnt2;
1773 else
1774 ps->c3divpos = (cnt3*256+cnt2)*new_divk;
1775 }
1776 }
1777
1778 ps->c0_hf = nc0_hf;
1779 ps->c2_hf = nc2_hf;
1780 ps->c1_f0 = nc1_f0;
1781 ps->c3_f2 = nc3_f2;
1782 ps->c0sw4 = nc0sw4;
1783 ps->c1sw4 = nc1sw4;
1784 ps->mdivk = new_divk;
1785 }
1786
1787 /* SKCTL for two-tone mode */
Update_skctl(PokeyState * ps,unsigned char val)1788 static void Update_skctl(PokeyState* ps, unsigned char val)
1789 {
1790 ps->skctl = val;
1791 }
1792
1793 /* if using nonlinear mixing, don't stop ultrasounds */
1794 #ifdef NONLINEAR_MIXING
Update_c0stop(PokeyState * ps)1795 static void Update_c0stop(PokeyState* ps)
1796 {
1797 ps->outvol_0 = ps->readout_0(ps);
1798 }
Update_c1stop(PokeyState * ps)1799 static void Update_c1stop(PokeyState* ps)
1800 {
1801 ps->outvol_1 = ps->readout_1(ps);
1802 }
Update_c2stop(PokeyState * ps)1803 static void Update_c2stop(PokeyState* ps)
1804 {
1805 ps->outvol_2 = ps->readout_2(ps);
1806 }
Update_c3stop(PokeyState * ps)1807 static void Update_c3stop(PokeyState* ps)
1808 {
1809 ps->outvol_3 = ps->readout_3(ps);
1810 }
1811 #else
Update_c0stop(PokeyState * ps)1812 static void Update_c0stop(PokeyState* ps)
1813 {
1814 int lim = pokey_frq/2/audible_frq;
1815
1816 int hfa = 0;
1817 ps->c0stop = 0;
1818
1819 if(ps->c0vo || ps->vol0 == 0)
1820 ps->c0stop = 1;
1821 else if(!ps->c0sw4 && ps->c0sw3 && ps->c0sw2) /* If channel 0 is a pure tone... */
1822 {
1823 if(ps->c1_f0)
1824 {
1825 if(ps->c1divstart <= lim)
1826 {
1827 ps->c0stop = 1;
1828 hfa = 1;
1829 }
1830 }
1831 else
1832 {
1833 if(ps->c0divstart <= lim)
1834 {
1835 ps->c0stop = 1;
1836 hfa = 1;
1837 }
1838 }
1839 }
1840 else if(!ps->c0sw4 && ps->c0sw3 && !ps->c0sw2 && ps->c0sw1) /* if channel 0 is poly4... */
1841 {
1842 /* period for poly4 signal is 15 cycles */
1843 if(ps->c1_f0)
1844 {
1845 if(ps->c1divstart <= lim*2/15) /* all poly4 signal is above Nyquist */
1846 {
1847 ps->c0stop = 1;
1848 hfa = 1;
1849 }
1850 }
1851 else
1852 {
1853 if(ps->c0divstart <= lim*2/15)
1854 {
1855 ps->c0stop = 1;
1856 hfa = 1;
1857 }
1858 }
1859 }
1860
1861 ps->outvol_0 = 2*ps->readout_0(ps);
1862 if(hfa)
1863 ps->outvol_0 = ps->vol0;
1864 }
1865
Update_c1stop(PokeyState * ps)1866 static void Update_c1stop(PokeyState* ps)
1867 {
1868 int lim = pokey_frq/2/audible_frq;
1869
1870 int hfa = 0;
1871 ps->c1stop = 0;
1872
1873 if(!ps->c1_f0 && (ps->c1vo || ps->vol1 == 0))
1874 ps->c1stop = 1;
1875 else if(!ps->c1sw4 && ps->c1sw3 && ps->c1sw2 && ps->c1divstart <= lim) /* If channel 1 is a pure tone */
1876 {
1877 ps->c1stop = 1;
1878 hfa = 1;
1879 }
1880 else if(!ps->c1sw4 && ps->c1sw3 && !ps->c1sw2 && ps->c1sw1 && ps->c1divstart <= lim*2/15) /* all poly4 signal is above Nyquist */
1881 {
1882 ps->c1stop = 1;
1883 hfa = 1;
1884 }
1885
1886 ps->outvol_1 = 2*ps->readout_1(ps);
1887 if(hfa)
1888 ps->outvol_1 = ps->vol1;
1889 }
1890
Update_c2stop(PokeyState * ps)1891 static void Update_c2stop(PokeyState* ps)
1892 {
1893 int lim = pokey_frq/2/audible_frq;
1894
1895 int hfa = 0;
1896 ps->c2stop = 0;
1897
1898 if(!ps->c0sw4 && (ps->c2vo || ps->vol2 == 0))
1899 ps->c2stop = 1;
1900 /* If channel 2 is a pure tone and no filter for c0... */
1901 else if(ps->c2sw3 && ps->c2sw2 && !ps->c0sw4)
1902 {
1903 if(ps->c3_f2)
1904 {
1905 if(ps->c3divstart <= lim)
1906 {
1907 ps->c2stop = 1;
1908 hfa = 1;
1909 }
1910 }
1911 else
1912 {
1913 if(ps->c2divstart <= lim)
1914 {
1915 ps->c2stop = 1;
1916 hfa = 1;
1917 }
1918 }
1919 }
1920 else if(ps->c2sw3 && !ps->c2sw2 && ps->c2sw1 && !ps->c0sw4) /* if channel 2 is poly4 and no filter for c0... */
1921 {
1922 /* period for poly4 signal is 15 cycles */
1923 if(ps->c3_f2)
1924 {
1925 if(ps->c3divstart <= lim*2/15) /* all poly4 signal is above Nyquist */
1926 {
1927 ps->c2stop = 1;
1928 hfa = 1;
1929 }
1930 }
1931 else
1932 {
1933 if(ps->c2divstart <= lim*2/15)
1934 {
1935 ps->c2stop = 1;
1936 hfa = 1;
1937 }
1938 }
1939 }
1940
1941 ps->outvol_2 = 2*ps->readout_2(ps);
1942 if(hfa)
1943 ps->outvol_2 = ps->vol2;
1944 }
1945
Update_c3stop(PokeyState * ps)1946 static void Update_c3stop(PokeyState* ps)
1947 {
1948 int lim = pokey_frq/2/audible_frq;
1949 int hfa = 0;
1950 ps->c3stop = 0;
1951
1952 if(!ps->c1sw4 && !ps->c3_f2 && (ps->c3vo || ps->vol3 == 0))
1953 ps->c3stop = 1;
1954 /* If channel 3 is a pure tone */
1955 else if(ps->c3sw3 && ps->c3sw2 && !ps->c1sw4 && ps->c3divstart <= lim)
1956 {
1957 ps->c3stop = 1;
1958 hfa = 1;
1959 }
1960 else if(ps->c3sw3 && !ps->c3sw2 && ps->c3sw1 && !ps->c1sw4 && ps->c3divstart <= lim*2/15) /* all poly4 signal is above Nyquist */
1961 {
1962 ps->c3stop = 1;
1963 hfa = 1;
1964 }
1965
1966 ps->outvol_3 = 2*ps->readout_3(ps);
1967 if(hfa)
1968 ps->outvol_3 = ps->vol3;
1969 }
1970 #endif /*NONLINEAR_MIXING*/
1971
1972 /*****************************************************************************/
1973 /* Function: Update_pokey_sound_mz() */
1974 /* */
1975 /* Inputs: addr - the address of the parameter to be changed */
1976 /* val - the new value to be placed in the specified address */
1977 /* chip - chip # for stereo */
1978 /* gain - specified as an 8-bit fixed point number - use 1 for no */
1979 /* amplification (output is multiplied by gain) */
1980 /* */
1981 /* Outputs: Adjusts local globals - no return value */
1982 /* */
1983 /*****************************************************************************/
Update_pokey_sound_mz(UWORD addr,UBYTE val,UBYTE chip,UBYTE gain)1984 static void Update_pokey_sound_mz(UWORD addr, UBYTE val, UBYTE chip, UBYTE gain)
1985 {
1986 PokeyState* ps = pokey_states+chip;
1987
1988 switch(addr & 0x0f)
1989 {
1990 case POKEY_OFFSET_AUDF1:
1991 ps->c0diva = val;
1992 Update_c0divstart(ps);
1993 if(ps->c1_f0)
1994 {
1995 Update_c1divstart(ps);
1996 Update_c1stop(ps);
1997 }
1998 Update_c0stop(ps);
1999 ps->forcero = 1;
2000 break;
2001 case POKEY_OFFSET_AUDC1:
2002 ps->c0sw1 = (val & 0x40) != 0;
2003 ps->c0sw2 = (val & 0x20) != 0;
2004 ps->c0sw3 = (val & 0x80) != 0;
2005 ps->vol0 = (val & 0xF);
2006 ps->c0vo = (val & 0x10) != 0;
2007 Update_readout_0(ps);
2008 Update_event0(ps);
2009 Update_c0stop(ps);
2010 ps->forcero = 1;
2011 break;
2012 case POKEY_OFFSET_AUDF2:
2013 ps->c1diva = val;
2014 Update_c1divstart(ps);
2015 if(ps->c1_f0)
2016 {
2017 Update_c0divstart(ps);
2018 Update_c0stop(ps);
2019 }
2020 Update_c1stop(ps);
2021 ps->forcero = 1;
2022 break;
2023 case POKEY_OFFSET_AUDC2:
2024 ps->c1sw1 = (val & 0x40) != 0;
2025 ps->c1sw2 = (val & 0x20) != 0;
2026 ps->c1sw3 = (val & 0x80) != 0;
2027 ps->vol1 = (val & 0xF);
2028 ps->c1vo = (val & 0x10) != 0;
2029 Update_readout_1(ps);
2030 Update_event1(ps);
2031 Update_c1stop(ps);
2032 ps->forcero = 1;
2033 break;
2034 case POKEY_OFFSET_AUDF3:
2035 ps->c2diva = val;
2036 Update_c2divstart(ps);
2037 if(ps->c3_f2)
2038 {
2039 Update_c3divstart(ps);
2040 Update_c3stop(ps);
2041 }
2042 Update_c2stop(ps);
2043 ps->forcero = 1;
2044 break;
2045 case POKEY_OFFSET_AUDC3:
2046 ps->c2sw1 = (val & 0x40) != 0;
2047 ps->c2sw2 = (val & 0x20) != 0;
2048 ps->c2sw3 = (val & 0x80) != 0;
2049 ps->vol2 = (val & 0xF);
2050 ps->c2vo = (val & 0x10) != 0;
2051 Update_readout_2(ps);
2052 Update_event2(ps);
2053 Update_c2stop(ps);
2054 ps->forcero = 1;
2055 break;
2056 case POKEY_OFFSET_AUDF4:
2057 ps->c3diva = val;
2058 Update_c3divstart(ps);
2059 if(ps->c3_f2)
2060 {
2061 Update_c2divstart(ps);
2062 Update_c2stop(ps);
2063 }
2064 Update_c3stop(ps);
2065 ps->forcero = 1;
2066 break;
2067 case POKEY_OFFSET_AUDC4:
2068 ps->c3sw1 = (val & 0x40) != 0;
2069 ps->c3sw2 = (val & 0x20) != 0;
2070 ps->c3sw3 = (val & 0x80) != 0;
2071 ps->vol3 = val & 0xF;
2072 ps->c3vo = (val & 0x10) != 0;
2073 Update_readout_3(ps);
2074 Update_event3(ps);
2075 Update_c3stop(ps);
2076 ps->forcero = 1;
2077 break;
2078 case POKEY_OFFSET_AUDCTL:
2079 ps->selpoly9 = (val & 0x80) != 0;
2080 Update_audctl(ps,val);
2081 Update_readout_0(ps);
2082 Update_readout_1(ps);
2083 Update_readout_2(ps);
2084 Update_readout_3(ps);
2085 Update_c0divstart(ps);
2086 Update_c1divstart(ps);
2087 Update_c2divstart(ps);
2088 Update_c3divstart(ps);
2089 Update_c0stop(ps);
2090 Update_c1stop(ps);
2091 Update_c2stop(ps);
2092 Update_c3stop(ps);
2093 ps->forcero = 1;
2094 break;
2095 case POKEY_OFFSET_STIMER:
2096 if(ps->c1_f0)
2097 ps->c0divpos = ps->c0divstart_p;
2098 else
2099 ps->c0divpos = ps->c0divstart;
2100 ps->c1divpos = ps->c1divstart;
2101 if(ps->c3_f2)
2102 ps->c2divpos = ps->c2divstart_p;
2103 else
2104 ps->c2divpos = ps->c2divstart;
2105
2106 ps->c3divpos = ps->c3divstart;
2107 /*Documentation is wrong about which voices are on after STIMER*/
2108 /*It is 3&4 which are on, tested on a real atari*/
2109 ps->c0t2 = 0;
2110 ps->c1t2 = 0;
2111 ps->c2t2 = 1;
2112 ps->c3t2 = 1;
2113 break;
2114 case POKEY_OFFSET_SKCTL:
2115 Update_skctl(ps,val);
2116 break;
2117 }
2118 }
2119
2120 #if 0
2121 void mzpokeysnd_debugreset(UBYTE chip)
2122 {
2123 PokeyState* ps = pokey_states+chip;
2124
2125 if(ps->c1_f0)
2126 ps->c0divpos = ps->c0divstart_p;
2127 else
2128 ps->c0divpos = ps->c0divstart;
2129 ps->c1divpos = ps->c1divstart;
2130 if(ps->c3_f2)
2131 ps->c2divpos = ps->c2divstart_p;
2132 else
2133 ps->c2divpos = ps->c2divstart;
2134 ps->c3divpos = ps->c3divstart;
2135
2136 ps->c0t2 = 1;
2137 ps->c1t2 = 1;
2138 ps->c2t2 = 1;
2139 ps->c3t2 = 1;
2140 }
2141 #endif
2142
2143 /**************************************************************
2144
2145 Master gain and DC offset calculation
2146 by Michael Borisov
2147
2148 In order to use the available 8-bit or 16-bit dynamic range
2149 to full extent, reducing the influence of quantization
2150 noise while simultaneously avoiding overflows, gain
2151 and DC offset should be set to appropriate value.
2152
2153 All Pokey-generated sounds have maximal amplitude of 15.
2154 When all four channels sound simultaneously and in the
2155 same phase, amplidudes would add up to 60.
2156
2157 If Pokey is generating a 'pure tone', it always has a DC
2158 offset of half its amplitude. For other signals (produced
2159 by poly generators) DC offset varies, but it is always near
2160 to half amplitude and never exceeds this value.
2161
2162 In case that pure tone base frequency is outside of audible
2163 range (ultrasound frequency for high sample rates and above-
2164 Nyquist frequency for low sample rates), to speed up the engine,
2165 the generator is stopped while having only DC offset on the
2166 output (half of corresponding AUDV value). In order that this
2167 DC offset can be always represented as integer, AUDV values
2168 are multiplied by 2 when the generator works.
2169
2170 Therefore maximum integer value before resampling filters
2171 would be 60*2 = 120 while having maximum DC offset of 60.
2172 Resampling does not change the DC offset, therefore we may
2173 subtract it from the signal either before or after resampling.
2174 In mzpokeysnd, DC offset is subtracted after resampling, however
2175 for better understanding in further measurements I assume
2176 subtracting DC before. So, input range for the resampler
2177 becomes [-60 .. 60].
2178
2179 Resampling filter removes some harmonics from the signal as if
2180 the rectangular wave was Fourier transformed forth-and-back,
2181 while zeroing all harmonics above cutoff frequency. In case
2182 of high-frequency pure tone (above samplerate/8), only first
2183 harmonic of the Fourier transofm will remain. As it
2184 is known, Fourier-transform of the rectangular function of
2185 amplitude 1 has first oscillation component of amplitude 4/M_PI.
2186 Therefore, maximum sample values for filtered rectangular
2187 signal may exceed the amplitude of rectangular signal
2188 by up to 4/M_PI times.
2189
2190 Since our range before resampler is -60 .. 60, taking into
2191 account mentioned effect with band limiting, range of values
2192 on the resampler output appears to be in the following bounds:
2193 [-60*4/M_PI .. 60*4/M_PI]
2194
2195 In order to map this into signed 8-bit range [-128 .. 127], we
2196 should multiply the resampler output by 127/60/4*M_PI.
2197
2198 As it is common for sound hardware to have 8-bit sound unsigned,
2199 additional DC offset of 128 must be added.
2200
2201 For 16-bit case the output range is [-32768 .. 32767], and
2202 we should multiply the resampler output by 32767/60/4*M_PI
2203
2204 To make some room for numerical errors, filter ripples and
2205 quantization noise, so that they do not cause overflows in
2206 quantization, dynamic range is reduced in mzpokeysnd by
2207 multiplying the output amplitude with 0.95, reserving 5%
2208 of the total range for such effects, which is about 0.51db.
2209
2210 Mentioned gain and DC values were tested with 17kHz audio
2211 playing synchronously on 4 channels, which showed to be
2212 utilizing 95% of the sample values range.
2213
2214 Since any other gain value will be not optimal, I removed
2215 user gain setting and hard-coded the gain into mzpokeysnd
2216
2217 ---
2218
2219 A note from Piotr Fusik:
2220 I've added support for the key click sound generated by GTIA. Its
2221 volume seems to be pretty much like 8 on single POKEY's channel.
2222 So, the volumes now can sum up to 136 (4 channels * 15 * 2
2223 + 8 * 2 for GTIA), not 120.
2224
2225 A note from Mark Grebe:
2226 I've added back in the console and sio sounds from the old
2227 pokey version. So, now the volumes can sum up to 152
2228 (4 channesl * 15 * 2 + 8 * 4 for old sound), not 120 or 136.
2229
2230 ******************************************************************/
2231
2232
2233 /******************************************************************
2234
2235 Quantization effects and dithering
2236 by Michael Borisov
2237
2238 Quantization error in the signal has an expectation value of half
2239 the LSB, when the rounding is performed properly. Sometimes they
2240 express quantization error as a random function with even
2241 distribution over the range [-0.5 to 0.5]. Spectrum of this function
2242 is flat, because it's a white noise.
2243
2244 Power of a discrete signal (including noise) is calculated as
2245 mean square of its samples. For the mentioned above noise
2246 this is approximately 0.33. Therefore, in decibels for 8-bit case,
2247 our noise will have power of 10*log10(0.33/256/256) = -53dB
2248
2249 Because noise is white, this power of -53dB will be evenly
2250 distributed over the whole signal band upto Nyquist frequency.
2251 The larger the band is (higher sampling frequency), less
2252 is the quantisation noise floor. For 8000Hz noise floor is
2253 10*log10(0.33/256/256/4000) = -89dB/Hz, and for 44100Hz noise
2254 floor is 10*log10(0.33/256/256/22050) = -96.4dB/Hz.
2255 This shows that higher sampling rates are better in sense of
2256 quantization noise. Moreover, as large part of quantization noise
2257 in case of 44100Hz will fall into ultrasound and hi-frequency
2258 area 10-20kHz where human ear is less sensitive, this will
2259 show up as great improvement in quantization noise performance
2260 compared to 8000Hz.
2261
2262 I was plotting spectral analysis for sounds produced by mzpokeysnd
2263 to check these measures. And it showed up that in 8-bit case
2264 there is no expected flat noise floor of -89db/Hz for 8000Hz,
2265 but some distortion spectral peaks had higher amplitude than
2266 the aliasing peaks in 16-bit case. This was a proof to another
2267 statement which says that quantization noise tends to become
2268 correlated with the signal. Correlation is especially strong
2269 for simple signals generated by Pokey. Correlation means that
2270 the noise power of -53db is no longer evenly distributed
2271 across the whole frequency range, but concentrates in larger
2272 peaks at locations which depend on the Pokey signal.
2273
2274 To decorrelate quantization distortion and make it again
2275 white noise, which would improve the sound spectrum, since
2276 the maximum distortion peaks will have less amplitude,
2277 dithering is used. Another white noise is added to the signal
2278 before quantization. Since this added noise is not correlated
2279 with the signal, it shows itself as a flat noise floor.
2280 Quantization noise now tries to correlate with the dithering
2281 noise, but this does not lead to appearance of sharp
2282 spectral peaks any more :)
2283
2284 Another thing is that for listening, white noise is better than
2285 distortion. This is because human hearing has some 'noise
2286 reduction' system which makes it easier to percept sounds
2287 on the white noise background.
2288
2289 From the other point of view, if a signal has high and low
2290 spectral peaks, it is desirable that there is no distortion
2291 component with peaks of amplitude comparable to those of
2292 the true signal. Otherwise, perception of background low-
2293 amplitude signals will be disrupted. That's why they say
2294 that dithering extends dynamic range.
2295
2296 Dithering does not eliminate correlation of quantization noise
2297 completely. Degree of reduction of this effect depends on
2298 the dithering noise power. The higher is dithering noise,
2299 the more quantization noise is decorrelated. But this also
2300 leads to increase of noise percepted by the listener. So, an
2301 optimum value should be selected. My experiments show that
2302 unbiased rand() noise of amplitude 0.25 LSB is doing well.
2303
2304 Test spectral pictures for 8-bit sound, 8kHz sampling rate,
2305 dithered, show a noise floor of approx. -87dB/Hz.
2306
2307 ******************************************************************/
2308
2309 #define MAX_SAMPLE 152
2310
mzpokeysnd_process_8(void * sndbuffer,int sndn)2311 static void mzpokeysnd_process_8(void* sndbuffer, int sndn)
2312 {
2313 int i;
2314 int nsam = sndn;
2315 UBYTE *buffer = (UBYTE *) sndbuffer;
2316
2317 if(num_cur_pokeys<1)
2318 return; /* module was not initialized */
2319
2320 /* if there are two pokeys, then the signal is stereo
2321 we assume even sndn */
2322 while(nsam >= (int) num_cur_pokeys)
2323 {
2324 #ifdef VOL_ONLY_SOUND
2325 if( POKEYSND_sampbuf_rptr!=POKEYSND_sampbuf_ptr )
2326 { int l;
2327 if( POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr]>0 )
2328 POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr]-=1280;
2329 while( (l=POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr])<=0 )
2330 { POKEYSND_sampout=POKEYSND_sampbuf_val[POKEYSND_sampbuf_rptr];
2331 POKEYSND_sampbuf_rptr++;
2332 if( POKEYSND_sampbuf_rptr>=POKEYSND_SAMPBUF_MAX )
2333 POKEYSND_sampbuf_rptr=0;
2334 if( POKEYSND_sampbuf_rptr!=POKEYSND_sampbuf_ptr )
2335 {
2336 POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr]+=l;
2337 }
2338 else break;
2339 }
2340 }
2341 #endif
2342
2343 #ifdef VOL_ONLY_SOUND
2344 buffer[0] = (UBYTE)floor((generate_sample(pokey_states) + POKEYSND_sampout - MAX_SAMPLE / 2.0)
2345 * (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
2346 #else
2347 buffer[0] = (UBYTE)floor((generate_sample(pokey_states) - MAX_SAMPLE / 2.0)
2348 * (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
2349 #endif
2350 for(i=1; i<num_cur_pokeys; i++)
2351 {
2352 buffer[i] = (UBYTE)floor((generate_sample(pokey_states + i) - MAX_SAMPLE / 2.0)
2353 * (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
2354 }
2355 buffer += num_cur_pokeys;
2356 nsam -= num_cur_pokeys;
2357 }
2358 }
2359
mzpokeysnd_process_16(void * sndbuffer,int sndn)2360 static void mzpokeysnd_process_16(void* sndbuffer, int sndn)
2361 {
2362 int i;
2363 int nsam = sndn;
2364 SWORD *buffer = (SWORD *) sndbuffer;
2365
2366 if(num_cur_pokeys<1)
2367 return; /* module was not initialized */
2368
2369 /* if there are two pokeys, then the signal is stereo
2370 we assume even sndn */
2371 while(nsam >= (int) num_cur_pokeys)
2372 {
2373 #ifdef VOL_ONLY_SOUND
2374 if( POKEYSND_sampbuf_rptr!=POKEYSND_sampbuf_ptr )
2375 { int l;
2376 if( POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr]>0 )
2377 POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr]-=1280;
2378 while( (l=POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr])<=0 )
2379 { POKEYSND_sampout=POKEYSND_sampbuf_val[POKEYSND_sampbuf_rptr];
2380 POKEYSND_sampbuf_rptr++;
2381 if( POKEYSND_sampbuf_rptr>=POKEYSND_SAMPBUF_MAX )
2382 POKEYSND_sampbuf_rptr=0;
2383 if( POKEYSND_sampbuf_rptr!=POKEYSND_sampbuf_ptr )
2384 {
2385 POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_rptr]+=l;
2386 }
2387 else break;
2388 }
2389 }
2390 #endif
2391 #ifdef VOL_ONLY_SOUND
2392 buffer[0] = (SWORD)floor((generate_sample(pokey_states) + POKEYSND_sampout - MAX_SAMPLE / 2.0)
2393 * (65535.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
2394 #else
2395 buffer[0] = (SWORD)floor((generate_sample(pokey_states) - MAX_SAMPLE / 2.0)
2396 * (65535.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
2397 #endif
2398 for(i=1; i<num_cur_pokeys; i++)
2399 {
2400 buffer[i] = (SWORD)floor((generate_sample(pokey_states + i) - MAX_SAMPLE / 2.0)
2401 * (65535.0 / MAX_SAMPLE / 4 * M_PI * 0.95) + 0.5 + 0.5 * rand() / RAND_MAX - 0.25);
2402 }
2403 buffer += num_cur_pokeys;
2404 nsam -= num_cur_pokeys;
2405 }
2406 }
2407
2408 #ifdef SYNCHRONIZED_SOUND
generate_sync(unsigned int num_ticks)2409 static void generate_sync(unsigned int num_ticks)
2410 {
2411 double new_samp_pos;
2412 unsigned int ticks;
2413 UBYTE *buffer = POKEYSND_process_buffer + POKEYSND_process_buffer_fill;
2414 UBYTE *buffer_end = POKEYSND_process_buffer + POKEYSND_process_buffer_length;
2415 unsigned int i;
2416
2417 for (;;) {
2418 double int_part;
2419 new_samp_pos = samp_pos + ticks_per_sample;
2420 new_samp_pos = modf(new_samp_pos, &int_part);
2421 ticks = (unsigned int)int_part;
2422 if (ticks > num_ticks) {
2423 samp_pos -= num_ticks;
2424 break;
2425 }
2426 if (buffer >= buffer_end)
2427 break;
2428
2429 samp_pos = new_samp_pos;
2430 num_ticks -= ticks;
2431
2432 for (i = 0; i < num_cur_pokeys; ++i) {
2433 /* advance pokey to the new position and produce a sample */
2434 advance_ticks(pokey_states + i, ticks);
2435 if (POKEYSND_snd_flags & POKEYSND_BIT16) {
2436 *((SWORD *)buffer) = (SWORD)floor(
2437 (interp_read_resam_all(pokey_states + i, samp_pos) - MAX_SAMPLE / 2.0)
2438 * (65535.0 / MAX_SAMPLE / 4 * M_PI * 0.95)
2439 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25
2440 );
2441 buffer += 2;
2442 }
2443 else
2444 *buffer++ = (UBYTE)floor(
2445 (interp_read_resam_all(pokey_states + i, samp_pos) - MAX_SAMPLE / 2.0)
2446 * (255.0 / MAX_SAMPLE / 4 * M_PI * 0.95)
2447 + 128 + 0.5 + 0.5 * rand() / RAND_MAX - 0.25
2448 );
2449 }
2450 }
2451
2452 POKEYSND_process_buffer_fill = buffer - POKEYSND_process_buffer;
2453 if (num_ticks > 0) {
2454 /* remaining ticks */
2455 for (i = 0; i < num_cur_pokeys; ++i)
2456 advance_ticks(pokey_states + i, num_ticks);
2457 }
2458 }
2459 #endif /* SYNCHRONIZED_SOUND */
2460
2461 #ifdef SERIO_SOUND
Update_serio_sound_mz(int out,UBYTE data)2462 static void Update_serio_sound_mz( int out, UBYTE data )
2463 {
2464 #ifdef VOL_ONLY_SOUND
2465 int bits,pv,future;
2466 if (!POKEYSND_serio_sound_enabled) return;
2467
2468 pv=0;
2469 future=0;
2470 bits= (data<<1) | 0x200;
2471 while( bits )
2472 {
2473 POKEYSND_sampbuf_lastval-=pv;
2474 pv=(bits&0x01)*pokey_states[0].vol3;
2475 POKEYSND_sampbuf_lastval+=pv;
2476
2477 POKEYSND_sampbuf_val[POKEYSND_sampbuf_ptr]=POKEYSND_sampbuf_lastval;
2478 POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_ptr]=
2479 (ANTIC_CPU_CLOCK+future-POKEYSND_sampbuf_last)*128*POKEYSND_samp_freq/178979;
2480 POKEYSND_sampbuf_last=ANTIC_CPU_CLOCK+future;
2481 POKEYSND_sampbuf_ptr++;
2482 if( POKEYSND_sampbuf_ptr>=POKEYSND_SAMPBUF_MAX )
2483 POKEYSND_sampbuf_ptr=0;
2484 if( POKEYSND_sampbuf_ptr==POKEYSND_sampbuf_rptr )
2485 { POKEYSND_sampbuf_rptr++;
2486 if( POKEYSND_sampbuf_rptr>=POKEYSND_SAMPBUF_MAX )
2487 POKEYSND_sampbuf_rptr=0;
2488 }
2489 /* 1789790/19200 = 93 */
2490 future+=93; /* ~ 19200 bit/s - FIXME!!! set speed form AUDF [2] ??? */
2491 bits>>=1;
2492 }
2493 POKEYSND_sampbuf_lastval-=pv;
2494 #endif /* VOL_ONLY_SOUND */
2495 }
2496 #endif /* SERIO_SOUND */
2497
2498 #ifdef CONSOLE_SOUND
Update_consol_sound_mz(int set)2499 static void Update_consol_sound_mz( int set )
2500 {
2501 #ifdef SYNCHRONIZED_SOUND
2502 if (set) { /* The set variable is 0 only in VOL_ONLY_SOUND routines */
2503 pokey_states[0].speaker = GTIA_speaker*CONSOLE_VOL;
2504 pokey_states[0].forcero = 1; /* first chip */
2505 }
2506 #elif defined(VOL_ONLY_SOUND)
2507 static int prev_atari_speaker=0;
2508 static unsigned int prev_cpu_clock=0;
2509 int d;
2510
2511 if( !set && POKEYSND_samp_consol_val==0 ) return;
2512 POKEYSND_sampbuf_lastval-=POKEYSND_samp_consol_val;
2513 if( prev_atari_speaker!=GTIA_speaker )
2514 { POKEYSND_samp_consol_val=GTIA_speaker*8*4; /* gain */
2515 prev_cpu_clock=ANTIC_CPU_CLOCK;
2516 }
2517 else if( !set )
2518 { d=ANTIC_CPU_CLOCK - prev_cpu_clock;
2519 if( d<114 )
2520 { POKEYSND_sampbuf_lastval+=POKEYSND_samp_consol_val; return; }
2521 while( d>=114 /* CPUL */ )
2522 { POKEYSND_samp_consol_val=POKEYSND_samp_consol_val*99/100;
2523 d-=114;
2524 }
2525 prev_cpu_clock=ANTIC_CPU_CLOCK-d;
2526 }
2527 POKEYSND_sampbuf_lastval+=POKEYSND_samp_consol_val;
2528 prev_atari_speaker=GTIA_speaker;
2529
2530 POKEYSND_sampbuf_val[POKEYSND_sampbuf_ptr]=POKEYSND_sampbuf_lastval;
2531 POKEYSND_sampbuf_cnt[POKEYSND_sampbuf_ptr]=
2532 (ANTIC_CPU_CLOCK-POKEYSND_sampbuf_last)*128*POKEYSND_samp_freq/178979;
2533 POKEYSND_sampbuf_last=ANTIC_CPU_CLOCK;
2534 POKEYSND_sampbuf_ptr++;
2535 if( POKEYSND_sampbuf_ptr>=POKEYSND_SAMPBUF_MAX )
2536 POKEYSND_sampbuf_ptr=0;
2537 if( POKEYSND_sampbuf_ptr==POKEYSND_sampbuf_rptr )
2538 { POKEYSND_sampbuf_rptr++;
2539 if( POKEYSND_sampbuf_rptr>=POKEYSND_SAMPBUF_MAX )
2540 POKEYSND_sampbuf_rptr=0;
2541 }
2542 #endif /* !SYNCHRONIZED_SOUND && VOL_ONLY_SOUND */
2543 }
2544 #endif
2545
2546 #ifdef VOL_ONLY_SOUND
Update_vol_only_sound_mz(void)2547 static void Update_vol_only_sound_mz( void )
2548 {
2549 #ifdef CONSOLE_SOUND
2550 POKEYSND_UpdateConsol(0); /* mmm */
2551 #endif /* CONSOLE_SOUND */
2552 }
2553 #endif
2554