2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
12 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14 * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
21 * Permission to use, copy, modify and distribute Snes9x in both binary and
22 * source form, for non-commercial purposes, is hereby granted without fee,
23 * providing that this license information and copyright notice appear with
24 * all copies and any derived work.
26 * This software is provided 'as-is', without any express or implied
27 * warranty. In no event shall the authors be held liable for any damages
28 * arising from the use of this software.
30 * Snes9x is freeware for PERSONAL USE only. Commercial users should
31 * seek permission of the copyright holders first. Commercial use includes
32 * charging money for Snes9x or software derived from Snes9x.
34 * The copyright holders request that bug fixes and improvements to the code
35 * should be forwarded to them so everyone can benefit from the modifications
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
55 #define CLIP16_latch(v,l) \
57 { (v) = -32768; (l)++; }\
60 { (v) = 32767; (l)++; }
87 static int wave[SOUND_BUFFER_SIZE];
89 //extern int Echo [24000];
90 extern int MixBuffer [SOUND_BUFFER_SIZE];
91 //extern int EchoBuffer [SOUND_BUFFER_SIZE];
92 //extern int FilterTaps [8];
93 extern unsigned long Z;
94 //extern int Loop [16];
96 extern long FilterValues[4][2];
97 //extern int NoiseFreq [32];
100 //#define FIXED_POINT 0x10000UL
101 #define FIXED_POINT_REMAINDER 0xffffUL
102 #define FIXED_POINT_SHIFT 16
104 #define VOL_DIV8 0x8000
105 #define VOL_DIV16 0x0080
106 #define ENVX_SHIFT 24
108 extern "C" void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *);
110 // F is channel's current frequency and M is the 16-bit modulation waveform
111 // from the previous channel multiplied by the current envelope volume level.
112 #define PITCH_MOD(F,M) ((F) * ((((unsigned long) (M)) + 0x800000) >> 16) >> 7)
113 //#define PITCH_MOD(F,M) ((F) * ((((M) & 0x7fffff) >> 14) + 1) >> 8)
115 #define LAST_SAMPLE 0xffffff
116 #define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE)
119 static inline void S9xAPUSetEndOfSample (int i, Channel *ch)
121 ch->state = SOUND_SILENT;
122 ch->mode = MODE_NONE;
123 APU.DSP [APU_ENDX] |= 1 << i;
124 APU.DSP [APU_KON] &= ~(1 << i);
125 APU.DSP [APU_KOFF] &= ~(1 << i);
126 APU.KeyedChannels &= ~(1 << i);
129 static inline void S9xAPUSetEndX (int ch)
131 APU.DSP [APU_ENDX] |= 1 << ch;
134 void S9xSetEchoDelay (int delay)
136 SoundData.echo_buffer_size = (512 * delay * so.playback_rate) >> 15; // notaz / 32000;
138 SoundData.echo_buffer_size <<= 1;
139 if (SoundData.echo_buffer_size) {
140 while(SoundData.echo_ptr >= SoundData.echo_buffer_size)
141 SoundData.echo_ptr -= SoundData.echo_buffer_size;
143 SoundData.echo_ptr = 0;
144 S9xSetEchoEnable (APU.DSP [APU_EON]);
147 void S9xSetSoundKeyOff (int channel)
149 Channel *ch = &SoundData.channels[channel];
151 if (ch->state != SOUND_SILENT)
153 ch->state = SOUND_RELEASE;
154 ch->mode = MODE_RELEASE;
155 S9xSetEnvRate (ch, 8, -1, 0, 5<<28);
159 void S9xFixSoundAfterSnapshotLoad ()
161 SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20);
162 SoundData.echo_channel_enable = APU.DSP [APU_EON];
163 S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf);
164 S9xSetEchoFeedback ((signed char) APU.DSP [APU_EFB]);
166 S9xSetFilterCoefficient (0, (signed char) APU.DSP [APU_C0]);
167 S9xSetFilterCoefficient (1, (signed char) APU.DSP [APU_C1]);
168 S9xSetFilterCoefficient (2, (signed char) APU.DSP [APU_C2]);
169 S9xSetFilterCoefficient (3, (signed char) APU.DSP [APU_C3]);
170 S9xSetFilterCoefficient (4, (signed char) APU.DSP [APU_C4]);
171 S9xSetFilterCoefficient (5, (signed char) APU.DSP [APU_C5]);
172 S9xSetFilterCoefficient (6, (signed char) APU.DSP [APU_C6]);
173 S9xSetFilterCoefficient (7, (signed char) APU.DSP [APU_C7]);
175 for (int i = 0; i < 8; i++)
177 SoundData.channels[i].needs_decode = TRUE;
178 S9xSetSoundFrequency (i, SoundData.channels[i].hertz);
179 SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT;
180 SoundData.channels [i].next_sample = 0;
181 SoundData.channels [i].interpolate = 0;
182 SoundData.channels [i].previous [0] = (int32) SoundData.channels [i].previous16 [0];
183 SoundData.channels [i].previous [1] = (int32) SoundData.channels [i].previous16 [1];
185 SoundData.master_volume [0] = SoundData.master_volume_left;
186 SoundData.master_volume [1] = SoundData.master_volume_right;
187 SoundData.echo_volume [0] = SoundData.echo_volume_left;
188 SoundData.echo_volume [1] = SoundData.echo_volume_right;
192 void S9xSetEnvelopeHeight (int channel, int level)
194 Channel *ch = &SoundData.channels[channel];
197 ch->envxx = level << ENVX_SHIFT;
199 ch->left_vol_level = (level * ch->volume_left) / 128;
200 ch->right_vol_level = (level * ch->volume_right) / 128;
202 if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN)
204 S9xAPUSetEndOfSample (channel, ch);
209 void S9xSetSoundSample (int, uint16)
213 void S9xSetSoundSample (int channel, uint16 sample_number)
215 register Channel *ch = &SoundData.channels[channel];
217 if (ch->state != SOUND_SILENT &&
218 sample_number != ch->sample_number)
220 int keep = ch->state;
221 ch->state = SOUND_SILENT;
222 ch->sample_number = sample_number;
224 ch->needs_decode = TRUE;
225 ch->last_block = FALSE;
226 ch->previous [0] = ch->previous[1] = 0;
227 ch->block_pointer = *S9xGetSampleAddress(sample_number);
228 ch->sample_pointer = 0;
234 static void DecodeBlock (Channel *ch)
236 if (ch->block_pointer >= 0x10000 - 9)
238 ch->last_block = TRUE;
240 ch->block = ch->decoded;
241 memset32 (ch->decoded, 0, 8);
244 signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer];
246 unsigned char filter = *compressed;
247 if ((ch->last_block = filter & 1))
248 ch->loop = (filter & 2) != 0;
250 int16 *raw = ch->block = ch->decoded;
253 DecodeBlockAsm (compressed, raw, &ch->previous [0], &ch->previous [1]);
257 signed char sample1, sample2;
262 int32 prev0 = ch->previous [0];
263 int32 prev1 = ch->previous [1];
266 switch ((filter >> 2) & 3)
269 for (i = 8; i != 0; i--)
271 sample1 = *compressed++;
272 sample2 = sample1 << 4;
275 *raw++ = ((int32) sample1 << shift);
276 *raw++ = ((int32) sample2 << shift);
282 for (i = 8; i != 0; i--)
284 sample1 = *compressed++;
285 sample2 = sample1 << 4;
288 prev0 = (int16) prev0;
289 *raw++ = prev1 = ((int32) sample1 << shift) + prev0 - (prev0 >> 4);
290 prev1 = (int16) prev1;
291 *raw++ = prev0 = ((int32) sample2 << shift) + prev1 - (prev1 >> 4);
295 for (i = 8; i != 0; i--)
297 sample1 = *compressed++;
298 sample2 = sample1 << 4;
302 out = (sample1 << shift) - prev1 + (prev1 >> 4);
303 prev1 = (int16) prev0;
305 *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) -
308 out = (sample2 << shift) - prev1 + (prev1 >> 4);
309 prev1 = (int16) prev0;
311 *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) -
316 for (i = 8; i != 0; i--)
318 sample1 = *compressed++;
319 sample2 = sample1 << 4;
322 out = (sample1 << shift);
324 out = out - prev1 + (prev1 >> 3) + (prev1 >> 4);
325 prev1 = (int16) prev0;
327 *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) -
328 (prev0 >> 4) - (prev1 >> 6);
330 out = (sample2 << shift);
331 out = out - prev1 + (prev1 >> 3) + (prev1 >> 4);
332 prev1 = (int16) prev0;
334 *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) -
335 (prev0 >> 4) - (prev1 >> 6);
339 ch->previous [0] = prev0;
340 ch->previous [1] = prev1;
342 ch->block_pointer += 9;
346 static void MixStereo (int sample_count)
348 int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON];
350 for (uint32 J = 0; J < NUM_CHANNELS; J++)
353 Channel *ch = &SoundData.channels[J];
354 unsigned long freq0 = ch->frequency;
356 if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J)))
359 // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux
361 bool8 mod = pitch_mod & (1 << J);
363 if (ch->needs_decode)
366 ch->needs_decode = FALSE;
367 ch->sample = ch->block[0];
368 ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT;
369 if (ch->sample_pointer == 0)
370 ch->sample_pointer = 1;
371 if (ch->sample_pointer > SOUND_DECODE_LENGTH)
372 ch->sample_pointer = SOUND_DECODE_LENGTH - 1;
374 ch->next_sample = ch->block[ch->sample_pointer];
377 if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod)
378 ch->interpolate = ((ch->next_sample - ch->sample) *
379 (long) freq0) / (long) FIXED_POINT;
381 VL = (ch->sample * ch-> left_vol_level) / 128;
382 VR = (ch->sample * ch->right_vol_level) / 128;
384 for (uint32 I = 0; I < (uint32) sample_count; I += 2)
386 unsigned long freq = freq0;
389 freq = PITCH_MOD(freq, wave [I / 2]);
391 ch->env_error += ch->erate;
392 if (ch->env_error >= FIXED_POINT)
394 uint32 step = ch->env_error >> FIXED_POINT_SHIFT;
399 ch->env_error &= FIXED_POINT_REMAINDER;
400 ch->envx += step << 1;
401 ch->envxx = ch->envx << ENVX_SHIFT;
406 ch->envxx = 127 << ENVX_SHIFT;
407 ch->state = SOUND_DECAY;
408 if (ch->sustain_level != 8)
410 S9xSetEnvRate (ch, ch->decay_rate, -1,
411 (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28);
414 ch->state = SOUND_SUSTAIN;
415 S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
420 while (ch->env_error >= FIXED_POINT)
422 ch->envxx = (ch->envxx >> 8) * 255;
423 ch->env_error -= FIXED_POINT;
425 ch->envx = ch->envxx >> ENVX_SHIFT;
426 if (ch->envx <= ch->envx_target)
430 S9xAPUSetEndOfSample (J, ch);
433 ch->state = SOUND_SUSTAIN;
434 S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
439 while (ch->env_error >= FIXED_POINT)
441 ch->envxx = (ch->envxx >> 8) * 255;
442 ch->env_error -= FIXED_POINT;
444 ch->envx = ch->envxx >> ENVX_SHIFT;
447 S9xAPUSetEndOfSample (J, ch);
453 while (ch->env_error >= FIXED_POINT)
455 ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
456 ch->env_error -= FIXED_POINT;
458 ch->envx = ch->envxx >> ENVX_SHIFT;
461 S9xAPUSetEndOfSample (J, ch);
466 case SOUND_INCREASE_LINEAR:
467 ch->env_error &= FIXED_POINT_REMAINDER;
468 ch->envx += step << 1;
469 ch->envxx = ch->envx << ENVX_SHIFT;
474 ch->envxx = 127 << ENVX_SHIFT;
475 ch->state = SOUND_GAIN;
476 ch->mode = MODE_GAIN;
477 S9xSetEnvRate (ch, 0, -1, 0, 0);
481 case SOUND_INCREASE_BENT_LINE:
482 if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4)
484 while (ch->env_error >= FIXED_POINT)
486 ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
487 ch->env_error -= FIXED_POINT;
489 ch->envx = ch->envxx >> ENVX_SHIFT;
493 ch->env_error &= FIXED_POINT_REMAINDER;
494 ch->envx += step << 1;
495 ch->envxx = ch->envx << ENVX_SHIFT;
501 ch->envxx = 127 << ENVX_SHIFT;
502 ch->state = SOUND_GAIN;
503 ch->mode = MODE_GAIN;
504 S9xSetEnvRate (ch, 0, -1, 0, 0);
508 case SOUND_DECREASE_LINEAR:
509 ch->env_error &= FIXED_POINT_REMAINDER;
510 ch->envx -= step << 1;
511 ch->envxx = ch->envx << ENVX_SHIFT;
514 S9xAPUSetEndOfSample (J, ch);
519 case SOUND_DECREASE_EXPONENTIAL:
520 while (ch->env_error >= FIXED_POINT)
522 ch->envxx = (ch->envxx >> 8) * 255;
523 ch->env_error -= FIXED_POINT;
525 ch->envx = ch->envxx >> ENVX_SHIFT;
528 S9xAPUSetEndOfSample (J, ch);
534 S9xSetEnvRate (ch, 0, -1, 0, 0);
537 ch-> left_vol_level = (ch->envx * ch->volume_left) / 128;
538 ch->right_vol_level = (ch->envx * ch->volume_right) / 128;
539 VL = (ch->sample * ch-> left_vol_level) / 128;
540 VR = (ch->sample * ch->right_vol_level) / 128;
544 if (ch->count >= FIXED_POINT)
546 VL = ch->count >> FIXED_POINT_SHIFT;
547 ch->sample_pointer += VL;
548 ch->count &= FIXED_POINT_REMAINDER;
550 ch->sample = ch->next_sample;
551 if (ch->sample_pointer >= SOUND_DECODE_LENGTH)
553 if (JUST_PLAYED_LAST_SAMPLE(ch))
555 S9xAPUSetEndOfSample (J, ch);
560 ch->sample_pointer -= SOUND_DECODE_LENGTH;
565 ch->sample_pointer = LAST_SAMPLE;
566 ch->next_sample = ch->sample;
572 ch->last_block = FALSE;
573 uint16 *dir = S9xGetSampleAddress (ch->sample_number);
574 ch->block_pointer = *(dir + 1);
578 } while (ch->sample_pointer >= SOUND_DECODE_LENGTH);
579 if (!JUST_PLAYED_LAST_SAMPLE (ch))
580 ch->next_sample = ch->block [ch->sample_pointer];
583 ch->next_sample = ch->block [ch->sample_pointer];
585 if (ch->type == SOUND_SAMPLE)
587 if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod)
589 ch->interpolate = ((ch->next_sample - ch->sample) *
590 (long) freq) / (long) FIXED_POINT;
591 ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) *
592 (long) (ch->count)) / (long) FIXED_POINT));
600 if ((so.noise_gen <<= 1) & 0x80000000L)
601 so.noise_gen ^= 0x0040001L;
602 ch->sample = (so.noise_gen << 17) >> 17;
606 VL = (ch->sample * ch-> left_vol_level) / 128;
607 VR = (ch->sample * ch->right_vol_level) / 128;
613 int32 s = (int32) ch->sample + ch->interpolate;
616 ch->sample = (int16) s;
617 VL = (ch->sample * ch-> left_vol_level) / 128;
618 VR = (ch->sample * ch->right_vol_level) / 128;
622 if (pitch_mod & (1 << (J + 1)))
623 wave [I / 2] = ch->sample * ch->envx;
626 MixBuffer [I+1] += VR;
627 if (ch->echo_buf_ptr)
629 ch->echo_buf_ptr [I] += VL;
630 ch->echo_buf_ptr [I+1] += VR;
637 static void MixMono (int sample_count)
639 int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON];
641 for (uint32 J = 0; J < NUM_CHANNELS; J++)
643 Channel *ch = &SoundData.channels[J];
644 unsigned long freq0 = ch->frequency;
646 if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J)))
649 // freq0 = (unsigned long) ((double) freq0 * 0.985);
651 bool8 mod = pitch_mod & (1 << J);
653 if (ch->needs_decode)
656 ch->needs_decode = FALSE;
657 ch->sample = ch->block[0];
658 ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT;
659 if (ch->sample_pointer == 0)
660 ch->sample_pointer = 1;
661 if (ch->sample_pointer > SOUND_DECODE_LENGTH)
662 ch->sample_pointer = SOUND_DECODE_LENGTH - 1;
663 ch->next_sample = ch->block[ch->sample_pointer];
666 if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod)
667 ch->interpolate = ((ch->next_sample - ch->sample) *
668 (long) freq0) / (long) FIXED_POINT;
670 int32 V = (ch->sample * ch->left_vol_level) / 128;
672 for (uint32 I = 0; I < (uint32) sample_count; I++)
674 unsigned long freq = freq0;
677 freq = PITCH_MOD(freq, wave [I]);
679 ch->env_error += ch->erate;
680 if (ch->env_error >= FIXED_POINT)
682 uint32 step = ch->env_error >> FIXED_POINT_SHIFT;
687 ch->env_error &= FIXED_POINT_REMAINDER;
688 ch->envx += step << 1;
689 ch->envxx = ch->envx << ENVX_SHIFT;
694 ch->envxx = 127 << ENVX_SHIFT;
695 ch->state = SOUND_DECAY;
696 if (ch->sustain_level != 8)
698 S9xSetEnvRate (ch, ch->decay_rate, -1,
699 (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28);
702 ch->state = SOUND_SUSTAIN;
703 S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
708 while (ch->env_error >= FIXED_POINT)
710 ch->envxx = (ch->envxx >> 8) * 255;
711 ch->env_error -= FIXED_POINT;
713 ch->envx = ch->envxx >> ENVX_SHIFT;
714 if (ch->envx <= ch->envx_target)
718 S9xAPUSetEndOfSample (J, ch);
721 ch->state = SOUND_SUSTAIN;
722 S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
727 while (ch->env_error >= FIXED_POINT)
729 ch->envxx = (ch->envxx >> 8) * 255;
730 ch->env_error -= FIXED_POINT;
732 ch->envx = ch->envxx >> ENVX_SHIFT;
735 S9xAPUSetEndOfSample (J, ch);
741 while (ch->env_error >= FIXED_POINT)
743 ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
744 ch->env_error -= FIXED_POINT;
746 ch->envx = ch->envxx >> ENVX_SHIFT;
749 S9xAPUSetEndOfSample (J, ch);
754 case SOUND_INCREASE_LINEAR:
755 ch->env_error &= FIXED_POINT_REMAINDER;
756 ch->envx += step << 1;
757 ch->envxx = ch->envx << ENVX_SHIFT;
762 ch->envxx = 127 << ENVX_SHIFT;
763 ch->state = SOUND_GAIN;
764 ch->mode = MODE_GAIN;
765 S9xSetEnvRate (ch, 0, -1, 0, 0);
769 case SOUND_INCREASE_BENT_LINE:
770 if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4)
772 while (ch->env_error >= FIXED_POINT)
774 ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
775 ch->env_error -= FIXED_POINT;
777 ch->envx = ch->envxx >> ENVX_SHIFT;
781 ch->env_error &= FIXED_POINT_REMAINDER;
782 ch->envx += step << 1;
783 ch->envxx = ch->envx << ENVX_SHIFT;
789 ch->envxx = 127 << ENVX_SHIFT;
790 ch->state = SOUND_GAIN;
791 ch->mode = MODE_GAIN;
792 S9xSetEnvRate (ch, 0, -1, 0, 0);
796 case SOUND_DECREASE_LINEAR:
797 ch->env_error &= FIXED_POINT_REMAINDER;
798 ch->envx -= step << 1;
799 ch->envxx = ch->envx << ENVX_SHIFT;
802 S9xAPUSetEndOfSample (J, ch);
807 case SOUND_DECREASE_EXPONENTIAL:
808 while (ch->env_error >= FIXED_POINT)
810 ch->envxx = (ch->envxx >> 8) * 255;
811 ch->env_error -= FIXED_POINT;
813 ch->envx = ch->envxx >> ENVX_SHIFT;
816 S9xAPUSetEndOfSample (J, ch);
822 S9xSetEnvRate (ch, 0, -1, 0, 0);
825 ch->left_vol_level = (ch->envx * ch->volume_left) / 128;
826 V = (ch->sample * ch->left_vol_level) / 128;
830 if (ch->count >= FIXED_POINT)
832 V = ch->count >> FIXED_POINT_SHIFT;
833 ch->sample_pointer += V;
834 ch->count &= FIXED_POINT_REMAINDER;
836 ch->sample = ch->next_sample;
837 if (ch->sample_pointer >= SOUND_DECODE_LENGTH)
839 if (JUST_PLAYED_LAST_SAMPLE(ch))
841 S9xAPUSetEndOfSample (J, ch);
846 ch->sample_pointer -= SOUND_DECODE_LENGTH;
851 ch->sample_pointer = LAST_SAMPLE;
852 ch->next_sample = ch->sample;
857 ch->last_block = FALSE;
858 uint16 *dir = S9xGetSampleAddress (ch->sample_number);
859 ch->block_pointer = *(dir + 1);
864 } while (ch->sample_pointer >= SOUND_DECODE_LENGTH);
865 if (!JUST_PLAYED_LAST_SAMPLE (ch))
866 ch->next_sample = ch->block [ch->sample_pointer];
869 ch->next_sample = ch->block [ch->sample_pointer];
871 if (ch->type == SOUND_SAMPLE)
873 if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod)
875 ch->interpolate = ((ch->next_sample - ch->sample) *
876 (long) freq) / (long) FIXED_POINT;
877 ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) *
878 (long) (ch->count)) / (long) FIXED_POINT));
886 if ((so.noise_gen <<= 1) & 0x80000000L)
887 so.noise_gen ^= 0x0040001L;
888 ch->sample = (so.noise_gen << 17) >> 17;
891 V = (ch->sample * ch-> left_vol_level) / 128;
897 int32 s = (int32) ch->sample + ch->interpolate;
900 ch->sample = (int16) s;
901 V = (ch->sample * ch-> left_vol_level) / 128;
906 if (ch->echo_buf_ptr)
907 ch->echo_buf_ptr [I] += V;
909 if (pitch_mod & (1 << (J + 1)))
910 wave [I] = ch->sample * ch->envx;
917 void S9xMixSamples(signed short *buffer, int sample_count)
924 memset32(buffer, 0, sample_count>>1);
928 memset32 (MixBuffer, 0, sample_count);
929 if (SoundData.echo_enable)
930 memset32 (EchoBuffer, 0, sample_count);
933 MixStereo (sample_count);
935 MixMono (sample_count);
937 /* Mix and convert waveforms */
938 if (SoundData.echo_enable && SoundData.echo_buffer_size)
943 int master_vol_l = SoundData.master_volume[0];
944 int master_vol_r = SoundData.master_volume[1];
945 int echo_vol_l = SoundData.echo_volume[0];
946 int echo_vol_r = SoundData.echo_volume[1];
948 // 16-bit stereo sound with echo enabled ...
949 if (SoundData.no_filter)
951 // ... but no filter defined.
952 for (J = 0; J < sample_count; J+=2)
954 int E = Echo [SoundData.echo_ptr];
956 Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
957 Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J+1];
959 if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
960 SoundData.echo_ptr = 0;
962 l = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16;
963 r = (MixBuffer[J+1] * master_vol_r + E * echo_vol_r) / VOL_DIV16;
973 // ... with filter defined.
974 for (J = 0; J < sample_count; J+=2)
976 register int E = Echo [SoundData.echo_ptr];
978 Loop [(Z - 0) & 15] = E;
979 E = E * FilterTaps [0];
980 E += Loop [(Z - 2) & 15] * FilterTaps [1];
981 E += Loop [(Z - 4) & 15] * FilterTaps [2];
982 E += Loop [(Z - 6) & 15] * FilterTaps [3];
983 E += Loop [(Z - 8) & 15] * FilterTaps [4];
984 E += Loop [(Z - 10) & 15] * FilterTaps [5];
985 E += Loop [(Z - 12) & 15] * FilterTaps [6];
986 E += Loop [(Z - 14) & 15] * FilterTaps [7];
990 Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
991 Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J+1];
993 if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
994 SoundData.echo_ptr = 0;
996 l = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16;
997 r = (MixBuffer[J+1] * master_vol_r + E * echo_vol_r) / VOL_DIV16;
1009 int master_vol_l = SoundData.master_volume[0];
1010 int echo_vol_l = SoundData.echo_volume[0];
1012 // 16-bit mono sound with echo enabled...
1013 if (SoundData.no_filter)
1015 // ... no filter defined
1016 for (J = 0; J < sample_count; J++)
1018 int E = Echo [SoundData.echo_ptr];
1020 Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
1022 if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
1023 SoundData.echo_ptr = 0;
1025 I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16;
1032 // ... with filter defined
1033 for (J = 0; J < sample_count; J++)
1035 register int E = Echo [SoundData.echo_ptr];
1037 Loop [(Z - 0) & 7] = E;
1038 E = E * FilterTaps [0];
1039 E += Loop [(Z - 1) & 7] * FilterTaps [1];
1040 E += Loop [(Z - 2) & 7] * FilterTaps [2];
1041 E += Loop [(Z - 3) & 7] * FilterTaps [3];
1042 E += Loop [(Z - 4) & 7] * FilterTaps [4];
1043 E += Loop [(Z - 5) & 7] * FilterTaps [5];
1044 E += Loop [(Z - 6) & 7] * FilterTaps [6];
1045 E += Loop [(Z - 7) & 7] * FilterTaps [7];
1049 Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
1051 if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
1052 SoundData.echo_ptr = 0;
1054 I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16;
1063 int l, master_vol_l = SoundData.master_volume[0];
1067 int r, master_vol_r = SoundData.master_volume[1];
1069 // 16-bit stereo sound, no echo
1070 for (J = 0; J < sample_count; J+=2)
1072 l = (MixBuffer[J] * master_vol_l) / VOL_DIV16;
1073 r = (MixBuffer[J+1] * master_vol_r) / VOL_DIV16;
1083 // 16-bit mono sound, no echo
1084 for (J = 0; J < sample_count; J++)
1086 l = (MixBuffer[J] * master_vol_l) / VOL_DIV16;
1095 void S9xResetSound (bool8 full)
1097 for (int i = 0; i < 8; i++)
1099 SoundData.channels[i].state = SOUND_SILENT;
1100 SoundData.channels[i].mode = MODE_NONE;
1101 SoundData.channels[i].type = SOUND_SAMPLE;
1102 SoundData.channels[i].volume_left = 0;
1103 SoundData.channels[i].volume_right = 0;
1104 SoundData.channels[i].hertz = 0;
1105 SoundData.channels[i].count = 0;
1106 SoundData.channels[i].loop = FALSE;
1107 SoundData.channels[i].envx_target = 0;
1108 SoundData.channels[i].env_error = 0;
1109 SoundData.channels[i].erate = 0;
1110 SoundData.channels[i].envx = 0;
1111 SoundData.channels[i].envxx = 0;
1112 SoundData.channels[i].left_vol_level = 0;
1113 SoundData.channels[i].right_vol_level = 0;
1114 SoundData.channels[i].direction = 0;
1115 SoundData.channels[i].attack_rate = 0;
1116 SoundData.channels[i].decay_rate = 0;
1117 SoundData.channels[i].sustain_rate = 0;
1118 SoundData.channels[i].release_rate = 0;
1119 SoundData.channels[i].sustain_level = 0;
1121 SoundData.channels[i].env_ind_attack = 0;
1122 SoundData.channels[i].env_ind_decay = 0;
1123 SoundData.channels[i].env_ind_sustain = 0;
1124 SoundData.echo_ptr = 0;
1125 SoundData.echo_feedback = 0;
1126 SoundData.echo_buffer_size = 1;
1128 FilterTaps [0] = 127;
1136 so.mute_sound = TRUE;
1138 so.sound_switch = 255;
1142 SoundData.master_volume_left = 0;
1143 SoundData.master_volume_right = 0;
1144 SoundData.echo_volume_left = 0;
1145 SoundData.echo_volume_right = 0;
1146 SoundData.echo_enable = 0;
1147 SoundData.echo_write_enabled = 0;
1148 SoundData.echo_channel_enable = 0;
1149 SoundData.pitch_mod = 0;
1150 SoundData.dummy[0] = 0;
1151 SoundData.dummy[1] = 0;
1152 SoundData.dummy[2] = 0;
1153 SoundData.master_volume[0] = 0;
1154 SoundData.master_volume[1] = 0;
1155 SoundData.echo_volume[0] = 0;
1156 SoundData.echo_volume[1] = 0;
1157 SoundData.noise_hertz = 0;
1160 SoundData.master_volume_left = 127;
1161 SoundData.master_volume_right = 127;
1162 SoundData.master_volume [0] = SoundData.master_volume [1] = 127;
1163 SoundData.no_filter = TRUE;
1168 extern unsigned long AttackRate [16];
1169 extern unsigned long DecayRate [8];
1170 extern unsigned long SustainRate [32];
1171 extern unsigned long IncreaseRate [32];
1172 extern unsigned long DecreaseRateExp [32];
1175 void S9xSetPlaybackRate (uint32 playback_rate)
1177 so.playback_rate = playback_rate;
1180 // notaz: calclulate a value (let's call it freqbase) to simplify channel freq calculations later.
1181 so.freqbase = (FIXED_POINT<<11) / playback_rate;
1182 // now precalculate env rates for S9xSetEnvRate
1183 static int steps [] =
1185 //0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238
1186 0, 64, 619, 619, 128, 1, 64, 55, 64, 619
1189 for(i=0; i < 16; i++)
1190 for(u=0; u < 10; u++)
1191 AttackERate[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1192 (AttackRate[i] * playback_rate));
1193 for(i=0; i < 8; i++)
1194 for(u=0; u < 10; u++)
1195 DecayERate[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1196 (DecayRate[i] * playback_rate));
1198 for(i=0; i < 32; i++)
1199 for(u=0; u < 10; u++)
1200 SustainERate[i][u]= (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1201 (SustainRate[i] * playback_rate));
1203 for(i=0; i < 32; i++)
1204 for(u=0; u < 10; u++)
1205 IncreaseERate[i][u]=(unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1206 (IncreaseRate[i] * playback_rate));
1208 for(i=0; i < 32; i++)
1209 for(u=0; u < 10; u++)
1210 DecreaseERateExp[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1211 (DecreaseRateExp[i] / 2 * playback_rate));
1213 for(u=0; u < 10; u++)
1214 KeyOffERate[u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1215 (8 * playback_rate));
1218 S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf);
1219 for (int i = 0; i < 8; i++)
1220 S9xSetSoundFrequency (i, SoundData.channels [i].hertz);
1223 bool8 S9xInitSound (void)
1225 so.playback_rate = 0;
1227 so.sound_switch = 255;
1229 S9xResetSound (TRUE);
1230 S9xSetSoundMute (TRUE);