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