2
** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)
5
** This program is free software; you can redistribute it and/or
6
** modify it under the terms of version 2 of the GNU Library General
7
** Public License as published by the Free Software Foundation.
9
** This program is distributed in the hope that it will be useful,
10
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
** Library General Public License for more details. To obtain a
13
** copy of the GNU Library General Public License, write to the Free
14
** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
** Any permitted reproduction of these routines, in whole or in part,
17
** must bear this legend.
39
#endif /* !NSF_PLAYER */
42
#define APU_OVERSAMPLE
43
#define APU_VOLUME_DECAY(x) ((x) -= ((x) >> 7))
46
/* pointer to active APU */
49
/* look up table madness */
50
static int32 decay_lut[16];
51
static int vbl_lut[32];
52
static int trilength_lut[128];
54
/* noise lookups for both modes */
55
#ifndef REALTIME_NOISE
56
static int8 noise_long_lut[APU_NOISE_32K];
57
static int8 noise_short_lut[APU_NOISE_93];
58
#endif /* !REALTIME_NOISE */
60
/* $$$ ben : last error */
61
#define SET_APU_ERROR(APU,X) \
62
if (APU) (APU)->errstr = "apu: " X; else
64
#define APU_MIX_ENABLE(BIT) (apu->mix_enable&(1<<(BIT)))
66
/* vblank length table used for rectangles, triangle, noise */
67
static const uint8 vbl_length[32] = {
86
/* frequency limit of rectangle channels */
87
static const int freq_limit[8] = {
88
0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F0
91
/* noise frequency lookup table */
92
static const int noise_freq[16] = {
93
4, 8, 16, 32, 64, 96, 128, 160,
94
202, 254, 380, 508, 762, 1016, 2034, 4068
97
/* DMC transfer freqs */
98
const int dmc_clocks[16] = {
99
428, 380, 340, 320, 286, 254, 226, 214,
100
190, 160, 142, 128, 106, 85, 72, 54
103
/* ratios of pos/neg pulse for rectangle waves */
104
static const int duty_lut[4] = { 2, 4, 8, 12 };
108
apu_setcontext (apu_t * src_apu)
111
/* $$$ ben reset eoor string here. */
112
SET_APU_ERROR (apu, "no error");
116
** Simple queue routines
118
#define APU_QEMPTY() (apu->q_head == apu->q_tail)
121
apu_enqueue (apudata_t * d)
124
apu->queue[apu->q_head] = *d;
126
apu->q_head = (apu->q_head + 1) & APUQUEUE_MASK;
129
log_printf ("apu: queue overflow\n");
130
SET_APU_ERROR (apu, "queue overflow");
144
log_printf ("apu: queue empty\n");
145
SET_APU_ERROR (apu, "queue empty");
146
/* $$$ ben : should return 0 ??? */
149
apu->q_tail = (apu->q_tail + 1) & APUQUEUE_MASK;
151
return &apu->queue[loc];
155
apu_setchan (int chan, boolean enabled)
157
const unsigned int max = 6;
161
if ((unsigned int) chan >= max) {
162
SET_APU_ERROR (apu, "channel out of range");
165
old = (apu->mix_enable >> chan) & 1;
166
if (enabled != (boolean) - 1) {
167
apu->mix_enable = (apu->mix_enable & ~(1 << chan)) | ((!!enabled) << chan);
172
/* emulation of the 15-bit shift register the
173
** NES uses to generate pseudo-random series
174
** for the white noise channel
176
#ifdef REALTIME_NOISE
178
shift_register15 (uint8 xor_tap)
180
static int sreg = 0x4000;
181
int bit0, tap, bit14;
184
tap = (sreg & xor_tap) ? 1 : 0;
185
bit14 = (bit0 ^ tap);
187
sreg |= (bit14 << 14);
192
shift_register15 (int8 * buf, int count)
194
static int sreg = 0x4000;
195
int bit0, bit1, bit6, bit14;
197
if (count == APU_NOISE_93) {
200
bit6 = (sreg & 0x40) >> 6;
201
bit14 = (bit0 ^ bit6);
203
sreg |= (bit14 << 14);
206
} else { /* 32K noise */
210
bit1 = (sreg & 2) >> 1;
211
bit14 = (bit0 ^ bit1);
213
sreg |= (bit14 << 14);
222
** reg0: 0-3=volume, 4=envelope, 5=hold, 6-7=duty cycle
223
** reg1: 0-2=sweep shifts, 3=sweep inc/dec, 4-6=sweep length, 7=sweep on
224
** reg2: 8 bits of freq
225
** reg3: 0-2=high freq, 7-4=vbl length counter
227
#define APU_RECTANGLE_OUTPUT chan->output_vol
229
apu_rectangle (rectangle_t * chan)
233
#ifdef APU_OVERSAMPLE
238
APU_VOLUME_DECAY (chan->output_vol);
240
if (FALSE == chan->enabled || 0 == chan->vbl_length)
241
return APU_RECTANGLE_OUTPUT;
243
/* vbl length counter */
244
if (FALSE == chan->holdnote)
247
/* envelope decay at a rate of (env_delay + 1) / 240 secs */
248
chan->env_phase -= 4; /* 240/60 */
249
while (chan->env_phase < 0) {
250
chan->env_phase += chan->env_delay;
253
chan->env_vol = (chan->env_vol + 1) & 0x0F;
254
else if (chan->env_vol < 0x0F)
258
if ((FALSE == chan->sweep_inc && chan->freq > chan->freq_limit)
259
|| chan->freq < APU_TO_FIXED (4))
260
return APU_RECTANGLE_OUTPUT;
262
/* frequency sweeping at a rate of (sweep_delay + 1) / 120 secs */
263
if (chan->sweep_on && chan->sweep_shifts) {
264
chan->sweep_phase -= 2; /* 120/60 */
265
while (chan->sweep_phase < 0) {
266
chan->sweep_phase += chan->sweep_delay;
267
if (chan->sweep_inc) /* ramp up */
268
chan->freq -= chan->freq >> (chan->sweep_shifts);
270
chan->freq += chan->freq >> (chan->sweep_shifts);
274
chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
275
if (chan->phaseacc >= 0)
276
return APU_RECTANGLE_OUTPUT;
278
#ifdef APU_OVERSAMPLE
279
num_times = total = 0;
281
if (chan->fixed_envelope)
282
output = chan->volume << 8; /* fixed volume */
284
output = (chan->env_vol ^ 0x0F) << 8;
287
while (chan->phaseacc < 0) {
288
chan->phaseacc += chan->freq;
289
chan->adder = (chan->adder + 1) & 0x0F;
291
#ifdef APU_OVERSAMPLE
292
if (chan->adder < chan->duty_flip)
301
#ifdef APU_OVERSAMPLE
302
chan->output_vol = total / num_times;
304
if (chan->fixed_envelope)
305
output = chan->volume << 8; /* fixed volume */
307
output = (chan->env_vol ^ 0x0F) << 8;
309
if (0 == chan->adder)
310
chan->output_vol = output;
311
else if (chan->adder == chan->duty_flip)
312
chan->output_vol = -output;
315
return APU_RECTANGLE_OUTPUT;
320
** reg0: 7=holdnote, 6-0=linear length counter
321
** reg2: low 8 bits of frequency
322
** reg3: 7-3=length counter, 2-0=high 3 bits of frequency
324
#define APU_TRIANGLE_OUTPUT (chan->output_vol + (chan->output_vol >> 2))
326
apu_triangle (triangle_t * chan)
328
APU_VOLUME_DECAY (chan->output_vol);
330
if (FALSE == chan->enabled || 0 == chan->vbl_length)
331
return APU_TRIANGLE_OUTPUT;
333
if (chan->counter_started) {
334
if (chan->linear_length > 0)
335
chan->linear_length--;
336
if (chan->vbl_length && FALSE == chan->holdnote)
338
} else if (FALSE == chan->holdnote && chan->write_latency) {
339
if (--chan->write_latency == 0)
340
chan->counter_started = TRUE;
343
if (chan->countmode == COUNTMODE_COUNT)
345
if (chan->linear_length > 0)
346
chan->linear_length--;
347
if (chan->vbl_length)
351
if (0 == chan->linear_length || chan->freq < APU_TO_FIXED (4)) /* inaudible */
352
return APU_TRIANGLE_OUTPUT;
354
chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
355
while (chan->phaseacc < 0) {
356
chan->phaseacc += chan->freq;
357
chan->adder = (chan->adder + 1) & 0x1F;
359
if (chan->adder & 0x10)
360
chan->output_vol -= (2 << 8);
362
chan->output_vol += (2 << 8);
365
return APU_TRIANGLE_OUTPUT;
369
/* WHITE NOISE CHANNEL
370
** ===================
371
** reg0: 0-3=volume, 4=envelope, 5=hold
372
** reg2: 7=small(93 byte) sample,3-0=freq lookup
373
** reg3: 7-4=vbl length counter
375
#define APU_NOISE_OUTPUT ((chan->output_vol + chan->output_vol + chan->output_vol) >> 2)
378
apu_noise (noise_t * chan)
382
#if defined(APU_OVERSAMPLE) && defined(REALTIME_NOISE)
386
#ifdef APU_OVERSAMPLE
391
APU_VOLUME_DECAY (chan->output_vol);
393
if (FALSE == chan->enabled || 0 == chan->vbl_length)
394
return APU_NOISE_OUTPUT;
396
/* vbl length counter */
397
if (FALSE == chan->holdnote)
400
/* envelope decay at a rate of (env_delay + 1) / 240 secs */
401
chan->env_phase -= 4; /* 240/60 */
402
while (chan->env_phase < 0) {
403
chan->env_phase += chan->env_delay;
406
chan->env_vol = (chan->env_vol + 1) & 0x0F;
407
else if (chan->env_vol < 0x0F)
411
chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
412
if (chan->phaseacc >= 0)
413
return APU_NOISE_OUTPUT;
415
#ifdef APU_OVERSAMPLE
416
num_times = total = 0;
418
if (chan->fixed_envelope)
419
outvol = chan->volume << 8; /* fixed volume */
421
outvol = (chan->env_vol ^ 0x0F) << 8;
424
while (chan->phaseacc < 0) {
425
chan->phaseacc += chan->freq;
427
#ifdef REALTIME_NOISE
429
#ifdef APU_OVERSAMPLE
430
if (shift_register15 (chan->xor_tap))
437
noise_bit = shift_register15 (chan->xor_tap);
443
if (chan->short_sample) {
444
if (APU_NOISE_93 == chan->cur_pos)
447
if (APU_NOISE_32K == chan->cur_pos)
451
#ifdef APU_OVERSAMPLE
452
if (chan->short_sample)
453
noise_bit = noise_short_lut[chan->cur_pos];
455
noise_bit = noise_long_lut[chan->cur_pos];
464
#endif /* REALTIME_NOISE */
467
#ifdef APU_OVERSAMPLE
468
chan->output_vol = total / num_times;
470
if (chan->fixed_envelope)
471
outvol = chan->volume << 8; /* fixed volume */
473
outvol = (chan->env_vol ^ 0x0F) << 8;
475
#ifndef REALTIME_NOISE
476
if (chan->short_sample)
477
noise_bit = noise_short_lut[chan->cur_pos];
479
noise_bit = noise_long_lut[chan->cur_pos];
480
#endif /* !REALTIME_NOISE */
483
chan->output_vol = outvol;
485
chan->output_vol = -outvol;
488
return APU_NOISE_OUTPUT;
493
apu_dmcreload (dmc_t * chan)
495
chan->address = chan->cached_addr;
496
chan->dma_length = chan->cached_dmalength;
497
chan->irq_occurred = FALSE;
500
/* DELTA MODULATION CHANNEL
501
** =========================
502
** reg0: 7=irq gen, 6=looping, 3-0=pointer to clock table
503
** reg1: output dc level, 6 bits unsigned
504
** reg2: 8 bits of 64-byte aligned address offset : $C000 + (value * 64)
505
** reg3: length, (value * 16) + 1
507
#define APU_DMC_OUTPUT ((chan->output_vol + chan->output_vol + chan->output_vol) >> 2)
509
apu_dmc (dmc_t * chan)
513
APU_VOLUME_DECAY (chan->output_vol);
515
/* only process when channel is alive */
516
if (chan->dma_length) {
517
chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */
519
while (chan->phaseacc < 0) {
520
chan->phaseacc += chan->freq;
522
delta_bit = (chan->dma_length & 7) ^ 7;
524
if (7 == delta_bit) {
525
chan->cur_byte = nes6502_getbyte (chan->address);
527
/* steal a cycle from CPU */
530
if (0xFFFF == chan->address)
531
chan->address = 0x8000;
536
if (--chan->dma_length == 0) {
537
/* if loop bit set, we're cool to retrigger sample */
539
apu_dmcreload (chan);
541
/* check to see if we should generate an irq */
543
chan->irq_occurred = TRUE;
547
/* bodge for timestamp queue */
548
chan->enabled = FALSE;
554
if (chan->cur_byte & (1 << delta_bit)) {
555
if (chan->regs[1] < 0x7D) {
557
chan->output_vol += (2 << 8);
560
if (chan->regs[1] < 0x3F)
563
chan->output_vol &= ~(0x7E << 8);
564
chan->output_vol |= ((chan->regs[1] << 1) << 8);
569
if (chan->regs[1] > 1) {
571
chan->output_vol -= (2 << 8);
575
if (chan->regs[1] > 0)
578
chan->output_vol &= ~(0x7E << 8);
579
chan->output_vol |= ((chan->regs[1] << 1) << 8);
585
return APU_DMC_OUTPUT;
590
apu_regwrite (uint32 address, uint8 value)
599
chan = (address & 4) ? 1 : 0;
600
apu->rectangle[chan].regs[0] = value;
602
apu->rectangle[chan].volume = value & 0x0F;
603
apu->rectangle[chan].env_delay = decay_lut[value & 0x0F];
604
apu->rectangle[chan].holdnote = (value & 0x20) ? TRUE : FALSE;
605
apu->rectangle[chan].fixed_envelope = (value & 0x10) ? TRUE : FALSE;
606
apu->rectangle[chan].duty_flip = duty_lut[value >> 6];
611
chan = (address & 4) ? 1 : 0;
612
apu->rectangle[chan].regs[1] = value;
613
apu->rectangle[chan].sweep_on = (value & 0x80) ? TRUE : FALSE;
614
apu->rectangle[chan].sweep_shifts = value & 7;
615
apu->rectangle[chan].sweep_delay = decay_lut[(value >> 4) & 7];
617
apu->rectangle[chan].sweep_inc = (value & 0x08) ? TRUE : FALSE;
618
apu->rectangle[chan].freq_limit = APU_TO_FIXED (freq_limit[value & 7]);
623
chan = (address & 4) ? 1 : 0;
624
apu->rectangle[chan].regs[2] = value;
625
/* if (apu->rectangle[chan].enabled) */
626
apu->rectangle[chan].freq =
627
APU_TO_FIXED ((((apu->rectangle[chan].regs[3] & 7) << 8) + value) +
633
chan = (address & 4) ? 1 : 0;
634
apu->rectangle[chan].regs[3] = value;
636
/* if (apu->rectangle[chan].enabled) */
638
apu->rectangle[chan].vbl_length = vbl_lut[value >> 3];
639
apu->rectangle[chan].env_vol = 0;
640
apu->rectangle[chan].freq =
641
APU_TO_FIXED ((((value & 7) << 8) + apu->rectangle[chan].regs[2]) +
643
apu->rectangle[chan].adder = 0;
650
if (0 == (apu->triangle.regs[0] & 0x80))
651
apu->triangle.countmode = COUNTMODE_COUNT;
654
if (apu->triangle.countmode == COUNTMODE_LOAD && apu->triangle.vbl_length)
655
apu->triangle.linear_length = trilength_lut[value & 0x7F];
657
if (0 == (value & 0x80))
658
apu->triangle.countmode = COUNTMODE_COUNT;
661
apu->triangle.regs[0] = value;
663
apu->triangle.holdnote = (value & 0x80) ? TRUE : FALSE;
666
/* if (apu->triangle.enabled) */
668
if (FALSE == apu->triangle.counter_started && apu->triangle.vbl_length)
669
apu->triangle.linear_length = trilength_lut[value & 0x7F];
676
apu->triangle.regs[1] = value;
678
/* if (apu->triangle.enabled) */
680
APU_TO_FIXED ((((apu->triangle.regs[2] & 7) << 8) + value) + 1);
685
apu->triangle.regs[2] = value;
687
/* this is somewhat of a hack. there appears to be some latency on
688
** the Real Thing between when trireg0 is written to and when the
689
** linear length counter actually begins its countdown. we want to
690
** prevent the case where the program writes to the freq regs first,
691
** then to reg 0, and the counter accidentally starts running because
692
** of the sound queue's timestamp processing.
694
** set latency to a couple scanlines -- should be plenty of time for
695
** the 6502 code to do a couple of table dereferences and load up the
699
/* 06/13/00 MPC -- seems to work OK */
700
apu->triangle.write_latency =
701
(int) (2 * NES_SCANLINE_CYCLES / APU_FROM_FIXED (apu->cycle_rate));
703
apu->triangle.linear_length = trilength_lut[apu->triangle.regs[0] & 0x7F];
704
if (0 == (apu->triangle.regs[0] & 0x80))
705
apu->triangle.countmode = COUNTMODE_COUNT;
707
apu->triangle.countmode = COUNTMODE_LOAD;
709
/* if (apu->triangle.enabled) */
712
APU_TO_FIXED ((((value & 7) << 8) + apu->triangle.regs[1]) + 1);
713
apu->triangle.vbl_length = vbl_lut[value >> 3];
714
apu->triangle.counter_started = FALSE;
715
apu->triangle.linear_length =
716
trilength_lut[apu->triangle.regs[0] & 0x7F];
723
apu->noise.regs[0] = value;
724
apu->noise.env_delay = decay_lut[value & 0x0F];
725
apu->noise.holdnote = (value & 0x20) ? TRUE : FALSE;
726
apu->noise.fixed_envelope = (value & 0x10) ? TRUE : FALSE;
727
apu->noise.volume = value & 0x0F;
731
apu->noise.regs[1] = value;
732
apu->noise.freq = APU_TO_FIXED (noise_freq[value & 0x0F]);
734
#ifdef REALTIME_NOISE
735
apu->noise.xor_tap = (value & 0x80) ? 0x40 : 0x02;
737
/* detect transition from long->short sample */
738
if ((value & 0x80) && FALSE == apu->noise.short_sample) {
739
/* recalculate short noise buffer */
740
shift_register15 (noise_short_lut, APU_NOISE_93);
741
apu->noise.cur_pos = 0;
743
apu->noise.short_sample = (value & 0x80) ? TRUE : FALSE;
748
apu->noise.regs[2] = value;
750
/* if (apu->noise.enabled) */
752
apu->noise.vbl_length = vbl_lut[value >> 3];
753
apu->noise.env_vol = 0; /* reset envelope */
759
apu->dmc.regs[0] = value;
761
apu->dmc.freq = APU_TO_FIXED (dmc_clocks[value & 0x0F]);
762
apu->dmc.looping = (value & 0x40) ? TRUE : FALSE;
765
apu->dmc.irq_gen = TRUE;
767
apu->dmc.irq_gen = FALSE;
768
apu->dmc.irq_occurred = FALSE;
772
case APU_WRE1: /* 7-bit DAC */
773
/* add the _delta_ between written value and
774
** current output level of the volume reg
776
value &= 0x7F; /* bit 7 ignored */
777
apu->dmc.output_vol += ((value - apu->dmc.regs[1]) << 8);
778
apu->dmc.regs[1] = value;
780
apu->dmc.output_vol = (value & 0x7F) << 8;
781
apu->dmc.regs[1] = (value & 0x7E) >> 1;
786
apu->dmc.regs[2] = value;
787
apu->dmc.cached_addr = 0xC000 + (uint16) (value << 6);
791
apu->dmc.regs[3] = value;
792
apu->dmc.cached_dmalength = ((value << 4) + 1) << 3;
796
/* bodge for timestamp queue */
797
apu->dmc.enabled = (value & 0x10) ? TRUE : FALSE;
799
apu->enable_reg = value;
801
for (chan = 0; chan < 2; chan++) {
802
if (value & (1 << chan))
803
apu->rectangle[chan].enabled = TRUE;
805
apu->rectangle[chan].enabled = FALSE;
806
apu->rectangle[chan].vbl_length = 0;
811
apu->triangle.enabled = TRUE;
813
apu->triangle.enabled = FALSE;
814
apu->triangle.vbl_length = 0;
815
apu->triangle.linear_length = 0;
816
apu->triangle.counter_started = FALSE;
817
apu->triangle.write_latency = 0;
821
apu->noise.enabled = TRUE;
823
apu->noise.enabled = FALSE;
824
apu->noise.vbl_length = 0;
828
if (0 == apu->dmc.dma_length)
829
apu_dmcreload (&apu->dmc);
831
apu->dmc.dma_length = 0;
833
apu->dmc.irq_occurred = FALSE;
836
/* unused, but they get hit in some mem-clear loops */
846
/* Read from $4000-$4017 */
848
apu_read (uint32 address)
856
/* seems that bit 6 denotes vblank -- return 1 for now */
859
/* Return 1 in 0-5 bit pos if a channel is playing */
860
if (apu->rectangle[0].enabled && apu->rectangle[0].vbl_length)
862
if (apu->rectangle[1].enabled && apu->rectangle[1].vbl_length)
864
if (apu->triangle.enabled && apu->triangle.vbl_length)
866
if (apu->noise.enabled && apu->noise.vbl_length)
869
/* if (apu->dmc.dma_length) */
870
/* bodge for timestamp queue */
871
if (apu->dmc.enabled)
874
if (apu->dmc.irq_occurred)
881
value = input_get (INP_JOYPAD0);
885
value = input_get (INP_ZAPPER | INP_JOYPAD1
886
/*| INP_ARKANOID *//*| INP_POWERPAD */ );
888
#endif /* !NSF_PLAYER */
891
value = (address >> 8); /* heavy capacitance on data bus */
900
apu_write (uint32 address, uint8 value)
903
static uint8 last_write;
904
#endif /* !NSF_PLAYER */
909
/* bodge for timestamp queue */
910
apu->dmc.enabled = (value & 0x10) ? TRUE : FALSE;
932
d.timestamp = nes6502_getcycles (FALSE);
940
ppu_oamdma (address, value);
944
/* VS system VROM switching */
945
mmc_vsvrom (value & 4);
947
/* see if we need to strobe them joypads */
949
if ((0 == value) && last_write)
954
case APU_JOY1: /* Some kind of IRQ control business */
957
#endif /* !NSF_PLAYER */
965
apu_getpcmdata (void **data, int *num_samples, int *sample_bits)
969
*num_samples = apu->num_samples;
970
*sample_bits = apu->sample_bits;
975
apu_process (uint8 * buffer, int num_samples)
978
uint32 elapsed_cycles;
979
static int32 prev_sample = 0;
980
int32 next_sample, accum;
984
/* grab it, keep it local for speed */
985
elapsed_cycles = (uint32) apu->elapsed_cycles;
988
apu->buffer = buffer;
990
while (num_samples--) {
991
while ((FALSE == APU_QEMPTY ())
992
&& (apu->queue[apu->q_tail].timestamp <= elapsed_cycles)) {
994
apu_regwrite (d->address, d->value);
997
elapsed_cycles += APU_FROM_FIXED (apu->cycle_rate);
1000
if (APU_MIX_ENABLE (0))
1001
accum += apu_rectangle (&apu->rectangle[0]);
1002
if (APU_MIX_ENABLE (1))
1003
accum += apu_rectangle (&apu->rectangle[1]);
1004
if (APU_MIX_ENABLE (2))
1005
accum += apu_triangle (&apu->triangle);
1006
if (APU_MIX_ENABLE (3))
1007
accum += apu_noise (&apu->noise);
1008
if (APU_MIX_ENABLE (4))
1009
accum += apu_dmc (&apu->dmc);
1011
if (apu->ext && APU_MIX_ENABLE (5))
1012
accum += apu->ext->process ();
1014
/* do any filtering */
1015
if (APU_FILTER_NONE != apu->filter_type) {
1016
next_sample = accum;
1018
if (APU_FILTER_LOWPASS == apu->filter_type) {
1019
accum += prev_sample;
1022
accum = (accum + accum + accum + prev_sample) >> 2;
1024
prev_sample = next_sample;
1027
/* little extra kick for the kids */
1030
/* prevent clipping */
1033
else if (accum < -0x8000)
1036
/* signed 16-bit output, unsigned 8-bit */
1037
if (16 == apu->sample_bits) {
1038
*(int16 *) (buffer) = (int16) accum;
1039
buffer += sizeof (int16);
1041
*(uint8 *) (buffer) = (accum >> 8) ^ 0x80;
1042
buffer += sizeof (uint8);
1046
/* resync cycle counter */
1047
apu->elapsed_cycles = nes6502_getcycles (FALSE);
1050
/* set the filter type */
1052
* Add a get feature (filter_type == -1) and returns old filter type
1055
apu_setfilter (int filter_type)
1060
old = apu->filter_type;
1061
if (filter_type != -1) {
1062
apu->filter_type = filter_type;
1074
apu->elapsed_cycles = 0;
1075
memset (&apu->queue, 0, APUQUEUE_SIZE * sizeof (apudata_t));
1079
/* use to avoid bugs =) */
1080
for (address = 0x4000; address <= 0x4013; address++)
1081
apu_regwrite (address, 0);
1084
apu_regwrite (0x400C, 0x10); /* silence noise channel on NSF start */
1085
apu_regwrite (0x4015, 0x0F);
1087
apu_regwrite (0x4015, 0);
1088
#endif /* NSF_PLAYER */
1095
apu_build_luts (int num_samples)
1099
/* lut used for enveloping and frequency sweeps */
1100
for (i = 0; i < 16; i++)
1101
decay_lut[i] = num_samples * (i + 1);
1103
/* used for note length, based on vblanks and size of audio buffer */
1104
for (i = 0; i < 32; i++)
1105
vbl_lut[i] = vbl_length[i] * num_samples;
1107
/* triangle wave channel's linear length table */
1108
for (i = 0; i < 128; i++)
1109
trilength_lut[i] = (i * num_samples) / 4;
1111
#ifndef REALTIME_NOISE
1112
/* generate noise samples */
1113
shift_register15 (noise_long_lut, APU_NOISE_32K);
1114
shift_register15 (noise_short_lut, APU_NOISE_93);
1115
#endif /* !REALTIME_NOISE */
1119
apu_setactive (apu_t * active)
1125
/* Initializes emulated sound hardware, creates waveforms/voices */
1127
apu_create (int sample_rate, int refresh_rate, int sample_bits, boolean stereo)
1133
temp_apu = malloc (sizeof (apu_t));
1134
if (NULL == temp_apu)
1136
/* $$$ ben : safety net, in case we forgot to init something */
1137
memset (temp_apu, 0, sizeof (apu_t));
1139
SET_APU_ERROR (temp_apu, "no error");
1140
temp_apu->sample_rate = sample_rate;
1141
temp_apu->refresh_rate = refresh_rate;
1142
temp_apu->sample_bits = sample_bits;
1144
temp_apu->num_samples = sample_rate / refresh_rate;
1145
/* turn into fixed point! */
1146
temp_apu->cycle_rate = (int32) (APU_BASEFREQ * 65536.0 / (float) sample_rate);
1148
/* build various lookup tables for apu */
1149
apu_build_luts (temp_apu->num_samples);
1151
/* set the update routine */
1152
temp_apu->process = apu_process;
1153
temp_apu->ext = NULL;
1155
apu_setactive (temp_apu);
1158
temp_apu->mix_enable = 0x3F;
1159
/* for (channel = 0; channel < 6; channel++) */
1160
/* apu_setchan(channel, TRUE); */
1162
apu_setfilter (APU_FILTER_LOWPASS);
1168
apu_getcontext (void)
1174
apu_destroy (apu_t * src_apu)
1178
src_apu->ext->shutdown ();
1184
apu_setext (apu_t * src_apu, apuext_t * ext)
1188
/* $$$ ben : seem cleaner like this */
1190
src_apu->ext->shutdown ();
1197
src_apu->ext->init ();
1199
/* $$$ ben : May be one day extension int () will return error code */
1203
/* this exists for external mixing routines */
1205
apu_getcyclerate (void)
1208
return apu->cycle_rate;
1213
** Revision 1.3 2008/04/09 13:43:50 thaytan
1214
** * gst/nsf/nes_apu.c: (apu_process):
1215
** * gst/nsf/nes_apu.h:
1216
** Don't do void pointer arithmetic - it's a gcc extension.
1218
** Revision 1.2 2008-03-25 15:56:12 slomo
1219
** Patch by: Andreas Henriksson <andreas at fatal dot set>
1220
** * gst/nsf/Makefile.am:
1221
** * gst/nsf/dis6502.h:
1222
** * gst/nsf/fds_snd.c:
1223
** * gst/nsf/fds_snd.h:
1224
** * gst/nsf/fmopl.c:
1225
** * gst/nsf/fmopl.h:
1226
** * gst/nsf/gstnsf.c:
1229
** * gst/nsf/memguard.c:
1230
** * gst/nsf/memguard.h:
1231
** * gst/nsf/mmc5_snd.c:
1232
** * gst/nsf/mmc5_snd.h:
1233
** * gst/nsf/nes6502.c:
1234
** * gst/nsf/nes6502.h:
1235
** * gst/nsf/nes_apu.c:
1236
** * gst/nsf/nes_apu.h:
1240
** * gst/nsf/types.h:
1241
** * gst/nsf/vrc7_snd.c:
1242
** * gst/nsf/vrc7_snd.h:
1243
** * gst/nsf/vrcvisnd.c:
1244
** * gst/nsf/vrcvisnd.h:
1245
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
1246
** on some files. Fixes bug #498237.
1247
** Remove some // comments, fix some compiler warnings and use pow()
1248
** instead of a slow, selfmade implementation.
1250
** Revision 1.2 2003/04/09 14:50:32 ben
1253
** Revision 1.1 2003/04/08 20:53:01 ben
1254
** Adding more files...
1256
** Revision 1.19 2000/07/04 04:53:26 matt
1257
** minor changes, sound amplification
1259
** Revision 1.18 2000/07/03 02:18:53 matt
1260
** much better external module exporting
1262
** Revision 1.17 2000/06/26 11:01:55 matt
1263
** made triangle a tad quieter
1265
** Revision 1.16 2000/06/26 05:10:33 matt
1266
** fixed cycle rate generation accuracy
1268
** Revision 1.15 2000/06/26 05:00:37 matt
1271
** Revision 1.14 2000/06/23 11:06:24 matt
1272
** more faithful mixing of channels
1274
** Revision 1.13 2000/06/23 03:29:27 matt
1275
** cleaned up external sound inteface
1277
** Revision 1.12 2000/06/20 00:08:39 matt
1278
** bugfix to rectangle wave
1280
** Revision 1.11 2000/06/13 13:48:58 matt
1281
** fixed triangle write latency for fixed point apu cycle rate
1283
** Revision 1.10 2000/06/12 01:14:36 matt
1284
** minor change to clipping extents
1286
** Revision 1.9 2000/06/09 20:00:56 matt
1287
** fixed noise hiccup in NSF player mode
1289
** Revision 1.8 2000/06/09 16:49:02 matt
1290
** removed all floating point from sound generation
1292
** Revision 1.7 2000/06/09 15:12:28 matt