1 /*
2 * nes_psg.c
3 *
4 * NES sound emulation system
5 */
6
7 /* $Id: nes_psg.c,v 1.51 2001/03/16 19:56:49 nyef Exp $ */
8
9 #include "nes_psg.h"
10 #include "snd.h"
11 #include "types.h"
12
13 /*
14 * sound register data
15 */
16
17 #ifdef SOUND
18 struct channel { u8 a; u8 b; u8 c; u8 d; };
19
20 struct channel nes_psg_c1;
21 struct channel nes_psg_c2;
22 struct channel nes_psg_c3;
23 struct channel nes_psg_c4;
24
25 u8 nes_psg_control;
26 #endif
27
28 /*
29 * a psg write function is of the form c#$ where # is the channel number and
30 * $ is the channel register starting from a
31 */
32
33 #ifdef SOUND
34 #define PSG_WRITEFUNC(channel, reg) \
35 void nes_psg_write_##channel##reg(u8 value) \
36 { \
37 nes_psg_##channel.reg = value; \
38 }
39 #else
40 #define PSG_WRITEFUNC(channel, reg) \
41 void nes_psg_write_##channel##reg(u8 value) \
42 { \
43 }
44 #endif
45
46 void nes_psg_write_c1d(u8);
47 void nes_psg_write_c2d(u8);
48 void nes_psg_write_c3d(u8);
49
50 PSG_WRITEFUNC(c1, a); PSG_WRITEFUNC(c1, b); PSG_WRITEFUNC(c1, c);
51 PSG_WRITEFUNC(c2, a); PSG_WRITEFUNC(c2, b); PSG_WRITEFUNC(c2, c);
52 PSG_WRITEFUNC(c3, a); PSG_WRITEFUNC(c3, b); PSG_WRITEFUNC(c3, c);
53 PSG_WRITEFUNC(c4, a); PSG_WRITEFUNC(c4, b); PSG_WRITEFUNC(c4, c);
54 PSG_WRITEFUNC(c4, d);
55
56 #ifndef SOUND
57 PSG_WRITEFUNC(c1, d);
58 PSG_WRITEFUNC(c2, d);
59 PSG_WRITEFUNC(c3, d);
60 #endif
61
62 psg_writefunc sound_regs[16] = {
63 nes_psg_write_c1a, nes_psg_write_c1b, nes_psg_write_c1c, nes_psg_write_c1d,
64 nes_psg_write_c2a, nes_psg_write_c2b, nes_psg_write_c2c, nes_psg_write_c2d,
65 nes_psg_write_c3a, nes_psg_write_c3b, nes_psg_write_c3c, nes_psg_write_c3d,
66 nes_psg_write_c4a, nes_psg_write_c4b, nes_psg_write_c4c, nes_psg_write_c4d,
67 };
68
nes_psg_write_control(u8 value)69 void nes_psg_write_control(u8 value)
70 {
71 #ifdef SOUND
72 nes_psg_control = value;
73 #endif
74 }
75
76 int nes_psg_quality;
77
78 #ifdef SOUND
79 /*
80 * Sync occurs every 7467 CPU cycles.
81 * Therefore, at the rate calculated
82 * for 44.1kHz (our highest rate),
83 * there are 182 samples per sync.
84 */
85 static u8 wave_buffers[4][182];
86
87 unsigned long nes_psg_pulse_magic;
88 unsigned long nes_psg_triangle_magic;
89 unsigned long nes_psg_noise_magic;
90 unsigned int nes_psg_samples_per_sync;
91 unsigned int nes_psg_cycles_per_sample;
92 unsigned int nes_psg_sample_rate;
93
94 struct nes_psg_quality_data {
95 unsigned long pulse_magic;
96 unsigned long triangle_magic;
97 unsigned long noise_magic;
98 unsigned int samples_per_sync;
99 unsigned int cycles_per_sample;
100 unsigned int sample_rate;
101 } nes_psg_qual[] = {
102 {0xa2567000, 0x512b3800, 0x512b3800, 91, 82, 22050},
103 {0x512b3800, 0x289d9c00, 0x289d9c00, 182, 41, 44100},
104 };
105
106 /* NOTE: these routines use 8.24 bit fixed point math in places. */
107
108 /* FIXME: some frequency values are not handled well by this system. */
109
110 unsigned char pulse_25[0x20] = {
111 0x11, 0x11, 0x11, 0x11,
112 0x11, 0x11, 0x11, 0x11,
113 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00,
119 };
120
121 unsigned char pulse_50[0x20] = {
122 0x11, 0x11, 0x11, 0x11,
123 0x11, 0x11, 0x11, 0x11,
124 0x11, 0x11, 0x11, 0x11,
125 0x11, 0x11, 0x11, 0x11,
126 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00,
130 };
131
132 unsigned char pulse_75[0x20] = {
133 0x11, 0x11, 0x11, 0x11,
134 0x11, 0x11, 0x11, 0x11,
135 0x11, 0x11, 0x11, 0x11,
136 0x11, 0x11, 0x11, 0x11,
137 0x11, 0x11, 0x11, 0x11,
138 0x11, 0x11, 0x11, 0x11,
139 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00,
141 };
142
143 unsigned char pulse_87[0x20] = {
144 0x11, 0x11, 0x11, 0x11,
145 0x11, 0x11, 0x11, 0x11,
146 0x11, 0x11, 0x11, 0x11,
147 0x11, 0x11, 0x11, 0x11,
148 0x11, 0x11, 0x11, 0x11,
149 0x11, 0x11, 0x11, 0x11,
150 0x11, 0x11, 0x11, 0x11,
151 0x00, 0x00, 0x00, 0x00,
152 };
153
154 unsigned char triangle_50[0x20] = {
155 0x00, 0x11, 0x22, 0x33,
156 0x44, 0x55, 0x66, 0x77,
157 0x88, 0x99, 0xaa, 0xbb,
158 0xcc, 0xdd, 0xee, 0xff,
159 0xff, 0xee, 0xdd, 0xcc,
160 0xbb, 0xaa, 0x99, 0x88,
161 0x77, 0x66, 0x55, 0x44,
162 0x33, 0x22, 0x11, 0x00,
163 };
164
165 unsigned char *pulse_waves[4] = {
166 pulse_87, pulse_75, pulse_50, pulse_25,
167 };
168
169 unsigned char nes_psg_atl[0x20] = {
170 5, 127, 10, 1, 20, 2, 40, 3, 80, 4, 30, 5, 7, 6, 13, 7,
171 6, 8, 12, 9, 24, 10, 48, 11, 96, 12, 36, 13, 8, 14, 16, 15,
172 };
173
174 /*
175 * volume envelopes
176 */
177
178 struct envelope {
179 u8 decay_counter;
180 u8 rate_counter;
181 };
182
envelope_get_volume(struct channel * channel,struct envelope * envelope)183 u8 envelope_get_volume(struct channel *channel, struct envelope *envelope)
184 {
185 if (channel->a & 0x10) {
186 return channel->a & 0x0f;
187 } else {
188 return envelope->decay_counter;
189 }
190 }
191
envelope_run_counter(struct channel * channel,struct envelope * envelope)192 void envelope_run_counter(struct channel *channel, struct envelope *envelope)
193 {
194 if (envelope->rate_counter--) return;
195 envelope->rate_counter = channel->a & 0x0f;
196
197 if (envelope->decay_counter--) return;
198 envelope->decay_counter = (channel->a & 0x20)? 0x0f: 0;
199 }
200
201 /*
202 * frequency sweeps
203 */
204
sweep_unit_active(struct channel * channel)205 static int sweep_unit_active(struct channel *channel)
206 {
207 return channel->b & 0x80;
208 }
209
sweep_unit_shift_count(struct channel * channel)210 static int sweep_unit_shift_count(struct channel *channel)
211 {
212 return channel->b & 7;
213 }
214
sweep_unit_should_sweep_down(struct channel * channel)215 static int sweep_unit_should_sweep_down(struct channel *channel)
216 {
217 return channel->b & 0x08;
218 }
219
sweep_unit_set_frequency(struct channel * channel,u16 freq)220 static void sweep_unit_set_frequency(struct channel *channel, u16 freq)
221 {
222 channel->c = freq;
223 channel->d &= ~7;
224 channel->d |= (freq >> 8) & 7;
225 }
226
sweep_unit_do_sweep(struct channel * channel,u16 freq)227 static void sweep_unit_do_sweep(struct channel *channel, u16 freq)
228 {
229 if (sweep_unit_should_sweep_down(channel)) {
230 freq -= freq >> sweep_unit_shift_count(channel);
231 if (channel == &nes_psg_c1) {
232 freq--;
233 }
234 } else {
235 freq += freq >> sweep_unit_shift_count(channel);
236 }
237
238 sweep_unit_set_frequency(channel, freq);
239
240 /* FIXME: sweep unit upper bound shutdown? */
241 }
242
run_sweep_unit(struct channel * channel,int * sweep_clock,u16 freq)243 void run_sweep_unit(struct channel *channel, int *sweep_clock, u16 freq)
244 {
245 if (!sweep_unit_active(channel)) return;
246
247 if ((*sweep_clock)--) return;
248 *sweep_clock = (channel->b >> 3) & 0x0e;
249
250 if (!sweep_unit_shift_count(channel)) return;
251
252 sweep_unit_do_sweep(channel, freq);
253 }
254
255 /*
256 * nes_psg_frame is called every 7457 CPU cycles to do sound rendering.
257 */
258
259 static u32 wave_1_index;
260 static int wave_1_sweep_clock;
261 static u8 wave_1_length_counter;
262 static struct envelope wave_1_envelope;
263
nes_psg_write_c1d(u8 value)264 void nes_psg_write_c1d(u8 value)
265 {
266 nes_psg_c1.d = value;
267 wave_1_envelope.decay_counter = 0x0f;
268 wave_1_length_counter = nes_psg_atl[value >> 3];
269 }
270
nes_psg_wave_1(void)271 void nes_psg_wave_1(void)
272 {
273 int i;
274 u8 volume;
275 u16 freq;
276 u32 step;
277 u8 *sample;
278
279 volume = envelope_get_volume(&nes_psg_c1, &wave_1_envelope);
280
281 freq = ((nes_psg_c1.d & 0x07) << 8) + nes_psg_c1.c;
282 if (freq >= 8) { /* sweep unit lower bound shutdown */
283 step = nes_psg_pulse_magic / freq;
284 } else {
285 step = 0;
286 }
287
288 if (!wave_1_length_counter) {
289 step = 0;
290 }
291
292 if (!(nes_psg_control & 0x01)) { /* channel output enable */
293 step = 0;
294 }
295
296 sample = pulse_waves[(nes_psg_c1.a >> 6)];
297
298 for (i = 0; i < nes_psg_samples_per_sync; i++) {
299 wave_1_index += step;
300 wave_1_index &= 0x1fffffff;
301 wave_buffers[0][i] = sample[wave_1_index >> 24] * volume;
302 }
303
304 envelope_run_counter(&nes_psg_c1, &wave_1_envelope);
305
306 run_sweep_unit(&nes_psg_c1, &wave_1_sweep_clock, freq);
307 }
308
309 static u32 wave_2_index;
310 static int wave_2_sweep_clock;
311 static u8 wave_2_length_counter;
312 static struct envelope wave_2_envelope;
313
nes_psg_write_c2d(u8 value)314 void nes_psg_write_c2d(u8 value)
315 {
316 nes_psg_c2.d = value;
317 wave_2_envelope.decay_counter = 0x0f;
318 wave_2_length_counter = nes_psg_atl[value >> 3];
319 }
320
nes_psg_wave_2(void)321 void nes_psg_wave_2(void)
322 {
323 int i;
324 u8 volume;
325 u16 freq;
326 u32 step;
327 u8 *sample;
328
329 volume = envelope_get_volume(&nes_psg_c2, &wave_2_envelope);
330
331 freq = ((nes_psg_c2.d & 0x07) << 8) + nes_psg_c2.c;
332 if (freq >= 8) { /* sweep unit lower bound shutdown */
333 step = nes_psg_pulse_magic / freq;
334 } else {
335 step = 0;
336 }
337
338 if (!wave_2_length_counter) {
339 step = 0;
340 }
341
342 if (!(nes_psg_control & 0x02)) { /* channel output enable */
343 step = 0;
344 }
345
346 sample = pulse_waves[(nes_psg_c2.a >> 6)];
347
348 for (i = 0; i < nes_psg_samples_per_sync; i++) {
349 wave_2_index += step;
350 wave_2_index &= 0x1fffffff;
351 wave_buffers[1][i] = sample[wave_2_index >> 24] * volume;
352 }
353
354 envelope_run_counter(&nes_psg_c2, &wave_2_envelope);
355
356 run_sweep_unit(&nes_psg_c2, &wave_2_sweep_clock, freq);
357 }
358
359 static u32 wave_3_index;
360 static u8 wave_3_length_counter;
361
nes_psg_write_c3d(u8 value)362 void nes_psg_write_c3d(u8 value)
363 {
364 nes_psg_c3.d = value;
365 wave_3_length_counter = nes_psg_atl[value >> 3];
366 }
367
nes_psg_wave_3(void)368 void nes_psg_wave_3(void)
369 {
370 int i;
371 u16 freq;
372 u32 step;
373
374 /* FIXME: Add linear counter */
375
376 freq = ((nes_psg_c3.d & 0x07) << 8) + nes_psg_c3.c;
377 if (freq) { /* sweep unit lower bound shutdown */
378 step = nes_psg_triangle_magic / freq;
379 } else {
380 step = 0;
381 }
382
383 if (!wave_3_length_counter) {
384 step = 0;
385 }
386
387 if (!(nes_psg_control & 0x04)) { /* channel output enable */
388 step = 0;
389 }
390
391 for (i = 0; i < nes_psg_samples_per_sync; i++) {
392 wave_3_index += step;
393 wave_3_index &= 0x1fffffff;
394 wave_buffers[2][i] = triangle_50[wave_3_index >> 24];
395 }
396 }
397
nes_psg_wave_4(void)398 void nes_psg_wave_4(void)
399 {
400 #if 0
401 int i;
402 int cycles;
403 int event;
404 unsigned char ctrl;
405
406 ctrl = nes_psg_ctrl;
407
408 cycles = 0;
409 event = 0;
410
411 for (i = 0; i < nes_psg_samples_per_sync; i++) {
412 cycles += nes_psg_cycles_per_sample;
413 while ((event < cur_event) && (psg_eventqueue[event].time < cycles)) {
414 if ((psg_eventqueue[event].type & PSGET_MASK) == PSGET_C4) {
415 switch (psg_eventqueue[event].type & 3) {
416 case 0:
417 nes_psg_c4a = psg_eventqueue[event].data;
418 nes_psg_c4_vol = nes_psg_c4a & 0x0f;
419 nes_psg_c4_vol |= nes_psg_c4_vol << 4;
420 /* deb_printf("psg: c4a: vol %d.\n", nes_psg_c4a & 15); */
421 break;
422 case 1:
423 nes_psg_c4b = psg_eventqueue[event].data;
424 /* deb_printf("psg: c4b: 0x%02x.\n", nes_psg_c4b); */
425 break;
426 case 2:
427 nes_psg_c4c = psg_eventqueue[event].data;
428 if (nes_psg_c4c & 0x80) {
429 nes_psg_c4_sr = 0x001f;
430 } else {
431 nes_psg_c4_sr = 0x01ff;
432 }
433 /* if (nes_psg_c4c & 0x70) { */
434 /* deb_printf("psg: c4c: c4c & 0x70 == 0x%02x.\n", nes_psg_c4c & 0x70); */
435 /* } */
436 if (nes_psg_c4c & 15) {
437 nes_psg_c4_skip = nes_psg_noise_magic / (nes_psg_c4c & 15);
438 } else {
439 nes_psg_c4_skip = 0;
440 }
441 nes_psg_c4_atl = nes_psg_atl[(nes_psg_c4d & 0xf8) >> 3];
442 /* deb_printf("psg: c4: freq: %d.\n", nes_psg_c4c & 15); */
443 break;
444 case 3:
445 nes_psg_c4d = psg_eventqueue[event].data;
446 if (nes_psg_c4c & 15) {
447 nes_psg_c4_skip = nes_psg_noise_magic / (nes_psg_c4c & 15);
448 } else {
449 nes_psg_c4_skip = 0;
450 }
451 nes_psg_c4_atl = nes_psg_atl[(nes_psg_c4d & 0xf8) >> 3];
452 }
453 } else if (psg_eventqueue[event].type == PSGET_W_CTRL) {
454 ctrl = psg_eventqueue[event].data;
455 }
456
457 event++;
458 }
459 if (ctrl & 8) {
460 nes_psg_c4_index += nes_psg_c4_skip;
461 if (nes_psg_c4_index > 0x1fffffff) {
462 if (nes_psg_c4c & 0x80) { /* FIXME: may be wrong */
463 nes_psg_c4_sr |= ((!(nes_psg_c4_sr & 1)) ^ (!(nes_psg_c4_sr & 4))) << 5;
464 } else {
465 nes_psg_c4_sr |= ((!(nes_psg_c4_sr & 1)) ^ (!(nes_psg_c4_sr & 16))) << 9;
466 }
467 nes_psg_c4_sr >>= 1;
468 }
469 nes_psg_c4_index &= 0x1fffffff;
470 #if 1
471 if (nes_psg_c4_atl && (nes_psg_c4_sr & 1)) {
472 wave_buffers[3][i] = nes_psg_c4_vol;
473 } else {
474 wave_buffers[3][i] = 0;
475 }
476 #else
477 wave_buffers[3][i] = 0;
478 #endif
479 } else {
480 wave_buffers[3][i] = 0;
481 }
482 }
483 if (nes_psg_c4_atl) {
484 nes_psg_c4_atl--;
485 }
486
487 nes_psg_ctrl_new = ctrl;
488 #endif
489 }
490 #endif
491
492 int length_counter_clock;
493
nes_psg_frame(void)494 void nes_psg_frame(void)
495 {
496 #ifdef SOUND
497 nes_psg_wave_1();
498 nes_psg_wave_2();
499 nes_psg_wave_3();
500 nes_psg_wave_4();
501
502 if (!length_counter_clock--) {
503 length_counter_clock = 4; /* FIXME: This may want to be 3 */
504
505 if (!(nes_psg_c1.a & 0x20)) {
506 if (wave_1_length_counter) {
507 wave_1_length_counter--;
508 }
509 }
510
511 if (!(nes_psg_c2.a & 0x20)) {
512 if (wave_2_length_counter) {
513 wave_2_length_counter--;
514 }
515 }
516
517 if (!(nes_psg_c3.a & 0x80)) {
518 if (wave_3_length_counter) {
519 wave_3_length_counter--;
520 }
521 }
522 }
523
524 snd_output_4_waves(nes_psg_samples_per_sync, wave_buffers[0], wave_buffers[1], wave_buffers[2], wave_buffers[3]);
525 #endif
526 }
527
nes_psg_init(void)528 void nes_psg_init(void)
529 {
530 #ifdef SOUND
531 snd_init();
532
533 if (nes_psg_quality > 0) {
534 if (nes_psg_quality > 2) {
535 nes_psg_quality = 1;
536 } else {
537 nes_psg_quality--;
538 }
539 nes_psg_pulse_magic = nes_psg_qual[nes_psg_quality].pulse_magic;
540 nes_psg_triangle_magic = nes_psg_qual[nes_psg_quality].triangle_magic;
541 nes_psg_noise_magic = nes_psg_qual[nes_psg_quality].noise_magic;
542 nes_psg_samples_per_sync = nes_psg_qual[nes_psg_quality].samples_per_sync;
543 nes_psg_cycles_per_sample = nes_psg_qual[nes_psg_quality].cycles_per_sample;
544 nes_psg_sample_rate = nes_psg_qual[nes_psg_quality].sample_rate;
545
546 snd_open(nes_psg_samples_per_sync, nes_psg_sample_rate);
547 } else {
548 }
549 #endif
550 }
551
nes_psg_done(void)552 void nes_psg_done(void)
553 {
554 #ifdef SOUND
555 snd_close();
556 #endif
557 }
558
559 /*
560 * $Log: nes_psg.c,v $
561 * Revision 1.51 2001/03/16 19:56:49 nyef
562 * removed a couple unnessecary includes
563 *
564 * Revision 1.50 2000/11/18 14:56:57 nyef
565 * cleaned up envelope_run_counter() and the sweep unit code
566 *
567 * Revision 1.49 2000/10/30 22:24:09 nyef
568 * made wave_buffers[][] static to work around linker bug
569 *
570 * Revision 1.48 2000/10/05 07:57:10 nyef
571 * fixed another "minor" bug triggered when -DSOUND isn't present
572 *
573 * Revision 1.47 2000/10/05 07:52:55 nyef
574 * fixed minor bug with compiling without -DSOUND
575 *
576 * Revision 1.46 2000/10/02 16:35:40 nyef
577 * fixed the sweep unit not to run if the shift count is 0
578 *
579 * Revision 1.45 2000/10/02 16:32:04 nyef
580 * extracted frequency sweep emulation from the pulse wave functions
581 *
582 * Revision 1.44 2000/10/02 16:08:13 nyef
583 * moved volume envelope handling out of nes_psg_wave_?() to new functions
584 *
585 * Revision 1.43 2000/10/02 15:19:50 nyef
586 * halved sweep clock rate (oops)
587 *
588 * Revision 1.42 2000/10/02 14:17:55 nyef
589 * gutted and reimplemented almost everything
590 *
591 * Revision 1.41 2000/05/06 23:25:47 nyef
592 * moved #define SOUND out to the Makefile level
593 *
594 * Revision 1.40 2000/05/06 22:29:11 nyef
595 * fixed to compile with no sound code in the executable
596 *
597 * Revision 1.39 1999/10/31 14:23:53 nyef
598 * fixed to compile with sound disabled
599 *
600 * Revision 1.38 1999/10/31 02:37:28 nyef
601 * broke all os-dependant sound code out to separate files
602 *
603 * Revision 1.37 1999/10/31 00:23:53 nyef
604 * rearranged some stuff in nes_psg_vsync()
605 *
606 * Revision 1.36 1999/10/30 23:58:16 nyef
607 * moved the $4015 handling code from nes_psg_mix() to the wave renderers
608 *
609 * Revision 1.35 1999/08/07 01:05:35 nyef
610 * removed O_NONBLOCK from linux sound open routine
611 * (this should prevent games from going too fast)
612 *
613 * Revision 1.34 1999/07/24 01:36:29 nyef
614 * Fixed noise channel to be far more correct
615 * Enabled noise channel, it's worth it now
616 *
617 * Revision 1.33 1999/02/14 18:27:54 nyef
618 * added a function pointer array for writing the sound regs
619 *
620 * Revision 1.32 1999/01/17 04:21:11 nyef
621 * fixed some problems with disabling sound completely
622 *
623 * Revision 1.31 1998/12/28 04:26:18 nyef
624 * added simple fix for "long note" problem on wave 3.
625 * full volume support on wave 3 is nessecary for proper fix.
626 *
627 * Revision 1.30 1998/12/28 04:10:50 nyef
628 * added disabled preliminary wave 4 generation.
629 *
630 * Revision 1.29 1998/12/27 04:57:34 nyef
631 * added basic framework for wave 4 generation.
632 *
633 * Revision 1.28 1998/12/27 01:57:18 nyef
634 * added support for volume control and looped sounds.
635 *
636 * Revision 1.27 1998/12/17 06:22:19 nyef
637 * cleaned up wave generation functions slightly.
638 *
639 * Revision 1.26 1998/12/12 20:33:07 nyef
640 * commented out "DONT_USE_CAL" as final step in bringing up to spec.
641 *
642 * Revision 1.25 1998/12/12 02:46:42 nyef
643 * fixed bug in nes_psg_open_sound_dos().
644 *
645 * Revision 1.24 1998/12/06 04:15:56 nyef
646 * added preliminary sound quality (playback rate) adjustment.
647 *
648 * Revision 1.23 1998/12/05 23:32:14 nyef
649 * halved the frequency on the triangle waves.
650 *
651 * Revision 1.22 1998/12/05 18:43:03 nyef
652 * active time length counters improved. Dungeon Magic sounds much better.
653 *
654 * Revision 1.21 1998/12/05 18:23:51 nyef
655 * changed from 16.16 fixed point to 8.24 fixed point. Due to some loss of
656 * precision in the conversion, the "sound constant" needs to be recalculated.
657 *
658 * Revision 1.20 1998/12/05 05:25:48 nyef
659 * added pulse wave duty cycles. don't know how well they work.
660 *
661 * Revision 1.19 1998/12/04 02:55:10 nyef
662 * started to bring io write functions up to spec. maintaining backward
663 * compatability for ease of transition and for RockNES.
664 *
665 * Revision 1.18 1998/12/04 02:08:36 nyef
666 * changed wave buffer 'triangle' to 'triangle_50' because allegro already
667 * defines 'triangle'.
668 *
669 * Revision 1.17 1998/12/03 04:58:59 nyef
670 * major overhaul. changed sound rendering method. system sounds a lot
671 * better. channel 3 approaches triangularity for sufficiently large values
672 * of 32. some hooks for duty cycles in place. active time length counters
673 * improved. floating point stuff removed. improved event handling.
674 *
675 * Revision 1.16 1998/12/01 04:01:12 nyef
676 * obtained speedup by storing the value (44100 / 111860.78) * freq in a
677 * local variable instead of calculating it every time it was needed.
678 *
679 * Revision 1.15 1998/12/01 03:34:15 nyef
680 * more doc fixes (mainly adding FIXMEs). added preliminary active time left
681 * support (I don't know if I did it right). more bugfixes.
682 *
683 * Revision 1.14 1998/12/01 02:57:48 nyef
684 * doc fix. removed useless debug code from psg write functions. added
685 * preliminary wave 3 support (needs to be changed to triangle wave).
686 * fixed a few bugs in the wave functions.
687 *
688 * Revision 1.13 1998/11/28 05:06:40 nyef
689 * bashed up linux sound stuff again. reintroduced soundfrags. changed to
690 * use 1024 byte writes with dual local buffers.
691 *
692 * Revision 1.12 1998/11/26 01:39:54 nyef
693 * gratuitous changes. mainly linux latency stuff.
694 *
695 * Revision 1.11 1998/11/05 02:58:31 nyef
696 * added preliminary emulation of psg control register.
697 *
698 * Revision 1.10 1998/11/05 02:29:34 nyef
699 * integrated new dos code changes. sound output now works on dos.
700 *
701 * Revision 1.9 1998/11/04 03:25:45 nyef
702 * moved the code to open the sound device from nes_psg_init() to
703 * nes_psg_open_sound_linux().
704 *
705 * Revision 1.8 1998/11/04 03:20:16 nyef
706 * added (commented out) defines for SOUND_LINUX and SOUND_DOS.
707 * made inclusion of system header files required for compile with
708 * sound support conditional upon definition of SOUND_LINUX.
709 *
710 * Revision 1.7 1998/11/04 03:10:08 nyef
711 * changed all psg event type defines to hexadecimal.
712 * added psg event type PSGET_SYNC.
713 *
714 * Revision 1.6 1998/11/03 00:43:26 nyef
715 * Added preliminary wave 2 generation.
716 *
717 * Revision 1.5 1998/10/21 00:15:33 nyef
718 * commented out the define for sound.
719 * changed some of the debug output in nes_psg_wave_1().
720 *
721 * Revision 1.4 1998/09/19 00:48:25 nyef
722 * wave 1 generation now working (the video display and rendering must be
723 * disabled for nes_ppu.c for it not to skip on my machine). started
724 * instrumenting wave 1 control regs for furthur insight into wave generation.
725 *
726 * Revision 1.3 1998/09/02 01:25:40 nyef
727 * added test output of wave 1. wave 1 generation still not working.
728 *
729 * Revision 1.2 1998/08/30 20:37:57 nyef
730 * added event queue, filled in the write functions, and added vsync hook.
731 *
732 * Revision 1.1 1998/08/22 00:35:43 nyef
733 * Initial revision
734 *
735 */
736