workaround a problem with the harmattan gcc
[drnoksnes] / soundux.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
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).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
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.
25  *
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.
29  *
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.
33  *
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
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41
42 #include <stdint.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <errno.h>
47
48 #define CLIP16(v) \
49 if ((v) < -32768) \
50     (v) = -32768; \
51 else \
52 if ((v) > 32767) \
53     (v) = 32767
54
55 #define CLIP16_latch(v,l) \
56 if ((v) < -32768) \
57 { (v) = -32768; (l)++; }\
58 else \
59 if ((v) > 32767) \
60 { (v) = 32767; (l)++; }
61
62 #define CLIP24(v) \
63 if ((v) < -8388608) \
64     (v) = -8388608; \
65 else \
66 if ((v) > 8388607) \
67     (v) = 8388607
68
69 /*
70 #define CLIP8(v) \
71 if ((v) < -128) \
72     (v) = -128; \
73 else \
74 if ((v) > 127) \
75     (v) = 127
76 */
77
78
79 #include "snes9x.h"
80 #include "soundux.h"
81 #include "apu.h"
82 #include "memmap.h"
83 #include "cpuexec.h"
84 #include "misc.h"
85
86
87 static int wave[SOUND_BUFFER_SIZE];
88
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];
95
96 extern long FilterValues[4][2];
97 //extern int NoiseFreq [32];
98
99
100 //#define FIXED_POINT 0x10000UL
101 #define FIXED_POINT_REMAINDER 0xffffUL
102 #define FIXED_POINT_SHIFT 16
103
104 #define VOL_DIV8  0x8000
105 #define VOL_DIV16 0x0080
106 #define ENVX_SHIFT 24
107
108 extern "C" void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *);
109
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)
114
115 #define LAST_SAMPLE 0xffffff
116 #define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE)
117
118
119 static inline void S9xAPUSetEndOfSample (int i, Channel *ch)
120 {
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);
127 }
128
129 static inline void S9xAPUSetEndX (int ch)
130 {
131     APU.DSP [APU_ENDX] |= 1 << ch;
132 }
133
134 void S9xSetEchoDelay (int delay)
135 {
136     SoundData.echo_buffer_size = (512 * delay * so.playback_rate) >> 15; // notaz / 32000;
137     if (so.stereo)
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;
142     } else
143                 SoundData.echo_ptr = 0;
144     S9xSetEchoEnable (APU.DSP [APU_EON]);
145 }
146
147 void S9xSetSoundKeyOff (int channel)
148 {
149     Channel *ch = &SoundData.channels[channel];
150
151     if (ch->state != SOUND_SILENT)
152     {
153         ch->state = SOUND_RELEASE;
154         ch->mode = MODE_RELEASE;
155         S9xSetEnvRate (ch, 8, -1, 0, 5<<28);
156     }
157 }
158
159 void S9xFixSoundAfterSnapshotLoad ()
160 {
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]);
165
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]);
174  
175         for (int i = 0; i < 8; i++)
176     {
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];
184     }
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;
189     IAPU.Scanline = 0;
190 }
191
192 void S9xSetEnvelopeHeight (int channel, int level)
193 {
194     Channel *ch = &SoundData.channels[channel];
195
196     ch->envx = level;
197     ch->envxx = level << ENVX_SHIFT;
198
199     ch->left_vol_level = (level * ch->volume_left) / 128;
200     ch->right_vol_level = (level * ch->volume_right) / 128;
201
202     if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN)
203     {
204         S9xAPUSetEndOfSample (channel, ch);
205     }
206 }
207
208 #if 1
209 void S9xSetSoundSample (int, uint16) 
210 {
211 }
212 #else
213 void S9xSetSoundSample (int channel, uint16 sample_number)
214 {
215     register Channel *ch = &SoundData.channels[channel];
216
217     if (ch->state != SOUND_SILENT && 
218         sample_number != ch->sample_number)
219     {
220         int keep = ch->state;
221         ch->state = SOUND_SILENT;
222         ch->sample_number = sample_number;
223         ch->loop = FALSE;
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;
229         ch->state = keep;
230     }
231 }
232 #endif
233
234 static void DecodeBlock (Channel *ch)
235 {
236     if (ch->block_pointer >= 0x10000 - 9)
237     {
238         ch->last_block = TRUE;
239         ch->loop = FALSE;
240         ch->block = ch->decoded;
241                 memset32 (ch->decoded, 0, 8);
242         return;
243     }
244     signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer];
245
246     unsigned char filter = *compressed;
247     if ((ch->last_block = filter & 1))
248         ch->loop = (filter & 2) != 0;
249
250     int16 *raw = ch->block = ch->decoded;
251
252 #if 0 //def ARM
253         DecodeBlockAsm (compressed, raw, &ch->previous [0], &ch->previous [1]);
254 #else
255         int32 out;
256     unsigned char shift;
257     signed char sample1, sample2;
258     unsigned int i;
259         
260     compressed++;
261     
262     int32 prev0 = ch->previous [0];
263     int32 prev1 = ch->previous [1];
264     shift = filter >> 4;
265         
266     switch ((filter >> 2) & 3)
267     {
268     case 0:
269                 for (i = 8; i != 0; i--)
270                 {
271                         sample1 = *compressed++;
272                         sample2 = sample1 << 4;
273                         sample2 >>= 4;
274                         sample1 >>= 4;
275                         *raw++ = ((int32) sample1 << shift);
276                         *raw++ = ((int32) sample2 << shift);
277                 }
278                 prev1 = *(raw - 2);
279                 prev0 = *(raw - 1);
280                 break;
281     case 1:
282                 for (i = 8; i != 0; i--)
283                 {
284                         sample1 = *compressed++;
285                         sample2 = sample1 << 4;
286                         sample2 >>= 4;
287                         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);
292                 }
293                 break;
294     case 2:
295                 for (i = 8; i != 0; i--)
296                 {
297                         sample1 = *compressed++;
298                         sample2 = sample1 << 4;
299                         sample2 >>= 4;
300                         sample1 >>= 4;
301                         
302                         out = (sample1 << shift) - prev1 + (prev1 >> 4);
303                         prev1 = (int16) prev0;
304                         prev0 &= ~3;
305                         *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - 
306                                 (prev0 >> 4);
307                         
308                         out = (sample2 << shift) - prev1 + (prev1 >> 4);
309                         prev1 = (int16) prev0;
310                         prev0 &= ~3;
311                         *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) -
312                                 (prev0 >> 4);
313                 }
314                 break;
315     case 3:
316                 for (i = 8; i != 0; i--)
317                 {
318                         sample1 = *compressed++;
319                         sample2 = sample1 << 4;
320                         sample2 >>= 4;
321                         sample1 >>= 4;
322                         out = (sample1 << shift);
323                         
324                         out = out - prev1 + (prev1 >> 3) + (prev1 >> 4);
325                         prev1 = (int16) prev0;
326                         prev0 &= ~3;
327                         *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - 
328                                 (prev0 >> 4) - (prev1 >> 6);
329                         
330                         out = (sample2 << shift);
331                         out = out - prev1 + (prev1 >> 3) + (prev1 >> 4);
332                         prev1 = (int16) prev0;
333                         prev0 &= ~3;
334                         *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - 
335                                 (prev0 >> 4) - (prev1 >> 6);
336                 }
337                 break;
338     }
339     ch->previous [0] = prev0;
340     ch->previous [1] = prev1;
341 #endif
342     ch->block_pointer += 9;
343 }
344
345
346 static void MixStereo (int sample_count)
347 {
348     int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON];
349
350     for (uint32 J = 0; J < NUM_CHANNELS; J++) 
351     {
352         int32 VL, VR;
353         Channel *ch = &SoundData.channels[J];
354         unsigned long freq0 = ch->frequency;
355
356         if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J)))
357             continue;
358
359 //              freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux
360
361         bool8 mod = pitch_mod & (1 << J);
362
363         if (ch->needs_decode) 
364         {
365             DecodeBlock(ch);
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;
373
374             ch->next_sample = ch->block[ch->sample_pointer];
375             ch->interpolate = 0;
376
377             if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod)
378                 ch->interpolate = ((ch->next_sample - ch->sample) * 
379                                    (long) freq0) / (long) FIXED_POINT;
380         }
381         VL = (ch->sample * ch-> left_vol_level) / 128;
382         VR = (ch->sample * ch->right_vol_level) / 128;
383
384         for (uint32 I = 0; I < (uint32) sample_count; I += 2)
385         {
386             unsigned long freq = freq0;
387
388             if (mod)
389                 freq = PITCH_MOD(freq, wave [I / 2]);
390
391             ch->env_error += ch->erate;
392             if (ch->env_error >= FIXED_POINT) 
393             {
394                 uint32 step = ch->env_error >> FIXED_POINT_SHIFT;
395
396                 switch (ch->state)
397                 {
398                 case SOUND_ATTACK:
399                     ch->env_error &= FIXED_POINT_REMAINDER;
400                     ch->envx += step << 1;
401                     ch->envxx = ch->envx << ENVX_SHIFT;
402
403                     if (ch->envx >= 126)
404                     {
405                         ch->envx = 127;
406                         ch->envxx = 127 << ENVX_SHIFT;
407                         ch->state = SOUND_DECAY;
408                         if (ch->sustain_level != 8) 
409                         {
410                             S9xSetEnvRate (ch, ch->decay_rate, -1,
411                                                 (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28);
412                             break;
413                         }
414                         ch->state = SOUND_SUSTAIN;
415                         S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
416                     }
417                     break;
418                 
419                 case SOUND_DECAY:
420                     while (ch->env_error >= FIXED_POINT)
421                     {
422                         ch->envxx = (ch->envxx >> 8) * 255;
423                         ch->env_error -= FIXED_POINT;
424                     }
425                     ch->envx = ch->envxx >> ENVX_SHIFT;
426                     if (ch->envx <= ch->envx_target)
427                     {
428                         if (ch->envx <= 0)
429                         {
430                             S9xAPUSetEndOfSample (J, ch);
431                             goto stereo_exit;
432                         }
433                         ch->state = SOUND_SUSTAIN;
434                         S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
435                     }
436                     break;
437
438                 case SOUND_SUSTAIN:
439                     while (ch->env_error >= FIXED_POINT)
440                     {
441                         ch->envxx = (ch->envxx >> 8) * 255;
442                         ch->env_error -= FIXED_POINT;
443                     }
444                     ch->envx = ch->envxx >> ENVX_SHIFT;
445                     if (ch->envx <= 0)
446                     {
447                         S9xAPUSetEndOfSample (J, ch);
448                         goto stereo_exit;
449                     }
450                     break;
451                     
452                 case SOUND_RELEASE:
453                     while (ch->env_error >= FIXED_POINT)
454                     {
455                         ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
456                         ch->env_error -= FIXED_POINT;
457                     }
458                     ch->envx = ch->envxx >> ENVX_SHIFT;
459                     if (ch->envx <= 0)
460                     {
461                         S9xAPUSetEndOfSample (J, ch);
462                         goto stereo_exit;
463                     }
464                     break;
465                 
466                 case SOUND_INCREASE_LINEAR:
467                     ch->env_error &= FIXED_POINT_REMAINDER;
468                     ch->envx += step << 1;
469                     ch->envxx = ch->envx << ENVX_SHIFT;
470
471                     if (ch->envx >= 126)
472                     {
473                         ch->envx = 127;
474                         ch->envxx = 127 << ENVX_SHIFT;
475                         ch->state = SOUND_GAIN;
476                         ch->mode = MODE_GAIN;
477                         S9xSetEnvRate (ch, 0, -1, 0, 0);
478                     }
479                     break;
480
481                 case SOUND_INCREASE_BENT_LINE:
482                     if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4)
483                     {
484                         while (ch->env_error >= FIXED_POINT)
485                         {
486                             ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
487                             ch->env_error -= FIXED_POINT;
488                         }
489                         ch->envx = ch->envxx >> ENVX_SHIFT;
490                     }
491                     else
492                     {
493                         ch->env_error &= FIXED_POINT_REMAINDER;
494                         ch->envx += step << 1;
495                         ch->envxx = ch->envx << ENVX_SHIFT;
496                     }
497
498                     if (ch->envx >= 126)
499                     {
500                         ch->envx = 127;
501                         ch->envxx = 127 << ENVX_SHIFT;
502                         ch->state = SOUND_GAIN;
503                         ch->mode = MODE_GAIN;
504                         S9xSetEnvRate (ch, 0, -1, 0, 0);
505                     }
506                     break;
507
508                 case SOUND_DECREASE_LINEAR:
509                     ch->env_error &= FIXED_POINT_REMAINDER;
510                     ch->envx -= step << 1;
511                     ch->envxx = ch->envx << ENVX_SHIFT;
512                     if (ch->envx <= 0)
513                     {
514                         S9xAPUSetEndOfSample (J, ch);
515                         goto stereo_exit;
516                     }
517                     break;
518
519                 case SOUND_DECREASE_EXPONENTIAL:
520                     while (ch->env_error >= FIXED_POINT)
521                     {
522                         ch->envxx = (ch->envxx >> 8) * 255;
523                         ch->env_error -= FIXED_POINT;
524                     }
525                     ch->envx = ch->envxx >> ENVX_SHIFT;
526                     if (ch->envx <= 0)
527                     {
528                         S9xAPUSetEndOfSample (J, ch);
529                         goto stereo_exit;
530                     }
531                     break;
532                 
533                 case SOUND_GAIN:
534                     S9xSetEnvRate (ch, 0, -1, 0, 0);
535                     break;
536                 }
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;
541             }
542
543             ch->count += freq;
544             if (ch->count >= FIXED_POINT)
545             {
546                         VL = ch->count >> FIXED_POINT_SHIFT;
547                         ch->sample_pointer += VL;
548                         ch->count &= FIXED_POINT_REMAINDER;
549
550                         ch->sample = ch->next_sample;
551                         if (ch->sample_pointer >= SOUND_DECODE_LENGTH)
552                         {
553                                 if (JUST_PLAYED_LAST_SAMPLE(ch))
554                                 {
555                                         S9xAPUSetEndOfSample (J, ch);
556                                         goto stereo_exit;
557                                 }
558                                 do
559                                 {
560                                         ch->sample_pointer -= SOUND_DECODE_LENGTH;
561                                         if (ch->last_block)
562                                         {
563                                                 if (!ch->loop)
564                                                 {
565                                                         ch->sample_pointer = LAST_SAMPLE;
566                                                         ch->next_sample = ch->sample;
567                                                         break;
568                                                 }
569                                                 else
570                                                 {
571                                                         S9xAPUSetEndX (J);
572                                                         ch->last_block = FALSE;
573                                                         uint16 *dir = S9xGetSampleAddress (ch->sample_number);
574                                                         ch->block_pointer = *(dir + 1);
575                                                 }
576                                         }
577                                         DecodeBlock (ch);
578                                 } while (ch->sample_pointer >= SOUND_DECODE_LENGTH);
579                                 if (!JUST_PLAYED_LAST_SAMPLE (ch))
580                                         ch->next_sample = ch->block [ch->sample_pointer];
581                         }
582                         else
583                                 ch->next_sample = ch->block [ch->sample_pointer];
584
585                         if (ch->type == SOUND_SAMPLE)
586                         {
587                                 if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod)
588                                 {
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));
593                                 }                 
594                                 else
595                                         ch->interpolate = 0;
596                         }
597                         else
598                         {
599                                 for (;VL > 0; VL--)
600                                         if ((so.noise_gen <<= 1) & 0x80000000L)
601                                                 so.noise_gen ^= 0x0040001L;
602                                 ch->sample = (so.noise_gen << 17) >> 17;
603                                 ch->interpolate = 0;
604                         }
605
606                         VL = (ch->sample * ch-> left_vol_level) / 128;
607                         VR = (ch->sample * ch->right_vol_level) / 128;
608                 }
609             else
610             {
611                         if (ch->interpolate)
612                         {
613                                 int32 s = (int32) ch->sample + ch->interpolate;
614                                 
615                                 CLIP16(s);
616                                 ch->sample = (int16) s;
617                                 VL = (ch->sample * ch-> left_vol_level) / 128;
618                                 VR = (ch->sample * ch->right_vol_level) / 128;
619                         }
620             }
621
622             if (pitch_mod & (1 << (J + 1)))
623                         wave [I / 2] = ch->sample * ch->envx;
624
625                 MixBuffer [I]   += VL;
626                 MixBuffer [I+1] += VR;
627                 if (ch->echo_buf_ptr)
628                 {
629                         ch->echo_buf_ptr [I]   += VL;
630                         ch->echo_buf_ptr [I+1] += VR;
631                 }
632         }
633 stereo_exit: ;
634     }
635 }
636
637 static void MixMono (int sample_count)
638 {
639     int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON];
640
641     for (uint32 J = 0; J < NUM_CHANNELS; J++) 
642     {
643         Channel *ch = &SoundData.channels[J];
644         unsigned long freq0 = ch->frequency;
645
646         if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J)))
647             continue;
648
649 //      freq0 = (unsigned long) ((double) freq0 * 0.985);
650
651         bool8 mod = pitch_mod & (1 << J);
652
653         if (ch->needs_decode) 
654         {
655             DecodeBlock(ch);
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];
664             ch->interpolate = 0;
665
666             if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod)
667                 ch->interpolate = ((ch->next_sample - ch->sample) * 
668                                    (long) freq0) / (long) FIXED_POINT;
669         }
670         int32 V = (ch->sample * ch->left_vol_level) / 128;
671
672         for (uint32 I = 0; I < (uint32) sample_count; I++)
673         {
674             unsigned long freq = freq0;
675
676             if (mod)
677                 freq = PITCH_MOD(freq, wave [I]);
678
679             ch->env_error += ch->erate;
680             if (ch->env_error >= FIXED_POINT) 
681             {
682                 uint32 step = ch->env_error >> FIXED_POINT_SHIFT;
683
684                 switch (ch->state)
685                 {
686                 case SOUND_ATTACK:
687                     ch->env_error &= FIXED_POINT_REMAINDER;
688                     ch->envx += step << 1;
689                     ch->envxx = ch->envx << ENVX_SHIFT;
690
691                     if (ch->envx >= 126)
692                     {
693                         ch->envx = 127;
694                         ch->envxx = 127 << ENVX_SHIFT;
695                         ch->state = SOUND_DECAY;
696                         if (ch->sustain_level != 8) 
697                         {
698                             S9xSetEnvRate (ch, ch->decay_rate, -1,
699                                                 (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28);
700                             break;
701                         }
702                         ch->state = SOUND_SUSTAIN;
703                         S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
704                     }
705                     break;
706                 
707                 case SOUND_DECAY:
708                     while (ch->env_error >= FIXED_POINT)
709                     {
710                         ch->envxx = (ch->envxx >> 8) * 255;
711                         ch->env_error -= FIXED_POINT;
712                     }
713                     ch->envx = ch->envxx >> ENVX_SHIFT;
714                     if (ch->envx <= ch->envx_target)
715                     {
716                         if (ch->envx <= 0)
717                         {
718                             S9xAPUSetEndOfSample (J, ch);
719                             goto mono_exit;
720                         }
721                         ch->state = SOUND_SUSTAIN;
722                         S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
723                     }
724                     break;
725
726                 case SOUND_SUSTAIN:
727                     while (ch->env_error >= FIXED_POINT)
728                     {
729                         ch->envxx = (ch->envxx >> 8) * 255;
730                         ch->env_error -= FIXED_POINT;
731                     }
732                     ch->envx = ch->envxx >> ENVX_SHIFT;
733                     if (ch->envx <= 0)
734                     {
735                         S9xAPUSetEndOfSample (J, ch);
736                         goto mono_exit;
737                     }
738                     break;
739                     
740                 case SOUND_RELEASE:
741                     while (ch->env_error >= FIXED_POINT)
742                     {
743                         ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
744                         ch->env_error -= FIXED_POINT;
745                     }
746                     ch->envx = ch->envxx >> ENVX_SHIFT;
747                     if (ch->envx <= 0)
748                     {
749                         S9xAPUSetEndOfSample (J, ch);
750                         goto mono_exit;
751                     }
752                     break;
753                 
754                 case SOUND_INCREASE_LINEAR:
755                     ch->env_error &= FIXED_POINT_REMAINDER;
756                     ch->envx += step << 1;
757                     ch->envxx = ch->envx << ENVX_SHIFT;
758
759                     if (ch->envx >= 126)
760                     {
761                         ch->envx = 127;
762                         ch->envxx = 127 << ENVX_SHIFT;
763                         ch->state = SOUND_GAIN;
764                         ch->mode = MODE_GAIN;
765                         S9xSetEnvRate (ch, 0, -1, 0, 0);
766                     }
767                     break;
768
769                 case SOUND_INCREASE_BENT_LINE:
770                     if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4)
771                     {
772                         while (ch->env_error >= FIXED_POINT)
773                         {
774                             ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256;
775                             ch->env_error -= FIXED_POINT;
776                         }
777                         ch->envx = ch->envxx >> ENVX_SHIFT;
778                     }
779                     else
780                     {
781                         ch->env_error &= FIXED_POINT_REMAINDER;
782                         ch->envx += step << 1;
783                         ch->envxx = ch->envx << ENVX_SHIFT;
784                     }
785
786                     if (ch->envx >= 126)
787                     {
788                         ch->envx = 127;
789                         ch->envxx = 127 << ENVX_SHIFT;
790                         ch->state = SOUND_GAIN;
791                         ch->mode = MODE_GAIN;
792                         S9xSetEnvRate (ch, 0, -1, 0, 0);
793                     }
794                     break;
795
796                 case SOUND_DECREASE_LINEAR:
797                     ch->env_error &= FIXED_POINT_REMAINDER;
798                     ch->envx -= step << 1;
799                     ch->envxx = ch->envx << ENVX_SHIFT;
800                     if (ch->envx <= 0)
801                     {
802                         S9xAPUSetEndOfSample (J, ch);
803                         goto mono_exit;
804                     }
805                     break;
806
807                 case SOUND_DECREASE_EXPONENTIAL:
808                     while (ch->env_error >= FIXED_POINT)
809                     {
810                         ch->envxx = (ch->envxx >> 8) * 255;
811                         ch->env_error -= FIXED_POINT;
812                     }
813                     ch->envx = ch->envxx >> ENVX_SHIFT;
814                     if (ch->envx <= 0)
815                     {
816                         S9xAPUSetEndOfSample (J, ch);
817                         goto mono_exit;
818                     }
819                     break;
820                 
821                 case SOUND_GAIN:
822                     S9xSetEnvRate (ch, 0, -1, 0, 0);
823                     break;
824                 }
825                 ch->left_vol_level = (ch->envx * ch->volume_left) / 128;
826                 V = (ch->sample * ch->left_vol_level) / 128;
827             }
828
829             ch->count += freq;
830             if (ch->count >= FIXED_POINT)
831             {
832                 V = ch->count >> FIXED_POINT_SHIFT;
833                 ch->sample_pointer += V;
834                 ch->count &= FIXED_POINT_REMAINDER;
835
836                 ch->sample = ch->next_sample;
837                 if (ch->sample_pointer >= SOUND_DECODE_LENGTH)
838                 {
839                     if (JUST_PLAYED_LAST_SAMPLE(ch))
840                     {
841                         S9xAPUSetEndOfSample (J, ch);
842                         goto mono_exit;
843                     }
844                     do
845                     {
846                         ch->sample_pointer -= SOUND_DECODE_LENGTH;
847                         if (ch->last_block)
848                         {
849                             if (!ch->loop)
850                             {
851                                 ch->sample_pointer = LAST_SAMPLE;
852                                 ch->next_sample = ch->sample;
853                                 break;
854                             }
855                             else
856                             {
857                                 ch->last_block = FALSE;
858                                 uint16 *dir = S9xGetSampleAddress (ch->sample_number);
859                                 ch->block_pointer = *(dir + 1);
860                                 S9xAPUSetEndX (J);
861                             }
862                         }
863                         DecodeBlock (ch);
864                     } while (ch->sample_pointer >= SOUND_DECODE_LENGTH);
865                     if (!JUST_PLAYED_LAST_SAMPLE (ch))
866                         ch->next_sample = ch->block [ch->sample_pointer];
867                 }
868                 else
869                     ch->next_sample = ch->block [ch->sample_pointer];
870
871                 if (ch->type == SOUND_SAMPLE)
872                 {
873                     if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod)
874                     {
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));
879                     }             
880                     else
881                         ch->interpolate = 0;
882                 }
883                 else
884                 {
885                     for (;V > 0; V--)
886                         if ((so.noise_gen <<= 1) & 0x80000000L)
887                             so.noise_gen ^= 0x0040001L;
888                     ch->sample = (so.noise_gen << 17) >> 17;
889                     ch->interpolate = 0;
890                 }
891                 V = (ch->sample * ch-> left_vol_level) / 128;
892             }
893             else
894             {
895                 if (ch->interpolate)
896                 {
897                     int32 s = (int32) ch->sample + ch->interpolate;
898
899                     CLIP16(s);
900                     ch->sample = (int16) s;
901                     V = (ch->sample * ch-> left_vol_level) / 128;
902                 }
903             }
904
905             MixBuffer [I] += V;
906                 if (ch->echo_buf_ptr)
907                     ch->echo_buf_ptr [I] += V;
908
909             if (pitch_mod & (1 << (J + 1)))
910                 wave [I] = ch->sample * ch->envx;
911         }
912 mono_exit: ;
913     }
914 }
915
916
917 void S9xMixSamples(signed short *buffer, int sample_count)
918 {
919         // 16-bit sound only
920         int J;
921
922         if (so.mute_sound)
923         {
924                 memset32(buffer, 0, sample_count>>1);
925                 return;
926         }
927
928         memset32 (MixBuffer, 0, sample_count);
929         if (SoundData.echo_enable)
930                 memset32 (EchoBuffer, 0, sample_count);
931
932         if (so.stereo)
933                 MixStereo (sample_count);
934         else
935                 MixMono (sample_count);
936
937     /* Mix and convert waveforms */
938         if (SoundData.echo_enable && SoundData.echo_buffer_size)
939         {
940                 if (so.stereo)
941                 {
942                         int l, r;
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];
947
948                         // 16-bit stereo sound with echo enabled ...
949                         if (SoundData.no_filter)
950                         {
951                                 // ... but no filter defined.
952                                 for (J = 0; J < sample_count; J+=2)
953                                 {
954                                         int E = Echo [SoundData.echo_ptr];
955
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];
958
959                                         if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
960                                                 SoundData.echo_ptr = 0;
961
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;
964
965                                         CLIP16(l);
966                                         CLIP16(r);
967                                         buffer[J]   = l;
968                                         buffer[J+1] = r;
969                                 }
970                         }
971                         else
972                         {
973                                 // ... with filter defined.
974                                 for (J = 0; J < sample_count; J+=2)
975                                 {
976                                         register int E = Echo [SoundData.echo_ptr];
977
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];
987                                         E /= 128;
988                                         Z++;
989
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];
992
993                                         if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
994                                                 SoundData.echo_ptr = 0;
995
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;
998
999                                         CLIP16(l);
1000                                         CLIP16(r);
1001                                         buffer[J]   = l;
1002                                         buffer[J+1] = r;
1003                                 }
1004                         }
1005                 }
1006                 else
1007                 {
1008                         int I;
1009                         int master_vol_l = SoundData.master_volume[0];
1010                         int echo_vol_l = SoundData.echo_volume[0];
1011
1012                         // 16-bit mono sound with echo enabled...
1013                         if (SoundData.no_filter)
1014                         {
1015                                 // ... no filter defined
1016                                 for (J = 0; J < sample_count; J++)
1017                                 {
1018                                         int E = Echo [SoundData.echo_ptr];
1019
1020                                         Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
1021
1022                                         if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
1023                                                 SoundData.echo_ptr = 0;
1024
1025                                         I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16;
1026                                         CLIP16(I);
1027                                         buffer[J] = I;
1028                                 }
1029                         }
1030                         else
1031                         {
1032                                 // ... with filter defined
1033                                 for (J = 0; J < sample_count; J++)
1034                                 {
1035                                         register int E = Echo [SoundData.echo_ptr];
1036
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];
1046                                         E /= 128;
1047                                         Z++;
1048
1049                                         Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J];
1050
1051                                         if (SoundData.echo_ptr >= SoundData.echo_buffer_size)
1052                                                 SoundData.echo_ptr = 0;
1053
1054                                         I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16;
1055                                         CLIP16(I);
1056                                         buffer[J] = I;
1057                                 }
1058                         }
1059                 }
1060         }
1061         else
1062         {
1063                 int l, master_vol_l = SoundData.master_volume[0];
1064
1065                 if (so.stereo)
1066                 {
1067                         int r, master_vol_r = SoundData.master_volume[1];
1068
1069                         // 16-bit stereo sound, no echo
1070                         for (J = 0; J < sample_count; J+=2)
1071                         {
1072                                 l = (MixBuffer[J]   * master_vol_l) / VOL_DIV16;
1073                                 r = (MixBuffer[J+1] * master_vol_r) / VOL_DIV16;
1074
1075                                 CLIP16(l);
1076                                 CLIP16(r);
1077                                 buffer[J]   = l;
1078                                 buffer[J+1] = r;
1079                         }
1080                 }
1081                 else
1082                 {
1083                         // 16-bit mono sound, no echo
1084                         for (J = 0; J < sample_count; J++)
1085                         {
1086                                 l = (MixBuffer[J] * master_vol_l) / VOL_DIV16;
1087
1088                                 CLIP16(l);
1089                                 buffer[J] = l;
1090                         }
1091                 }
1092         }
1093 }
1094
1095 void S9xResetSound (bool8 full)
1096 {
1097     for (int i = 0; i < 8; i++)
1098     {
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;
1120         // notaz
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;
1127     }
1128     FilterTaps [0] = 127;
1129     FilterTaps [1] = 0;
1130     FilterTaps [2] = 0;
1131     FilterTaps [3] = 0;
1132     FilterTaps [4] = 0;
1133     FilterTaps [5] = 0;
1134     FilterTaps [6] = 0;
1135     FilterTaps [7] = 0;
1136     so.mute_sound = TRUE;
1137     so.noise_gen = 1;
1138     so.sound_switch = 255;
1139
1140     if (full)
1141     {
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;
1158     }
1159
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;
1164 }
1165
1166
1167
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];      
1173
1174
1175 void S9xSetPlaybackRate (uint32 playback_rate)
1176 {
1177     so.playback_rate = playback_rate;
1178
1179         if(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 [] =
1184                 {
1185                         //0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238
1186                         0, 64, 619, 619, 128, 1, 64, 55, 64, 619
1187                 };
1188                 int i, u;
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));
1197
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));
1202
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));
1207
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));
1212
1213                 for(u=0; u < 10; u++)
1214                         KeyOffERate[u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) /
1215                                                                                                 (8 * playback_rate));
1216         }
1217
1218     S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf);
1219     for (int i = 0; i < 8; i++)
1220         S9xSetSoundFrequency (i, SoundData.channels [i].hertz);
1221 }
1222
1223 bool8 S9xInitSound (void)
1224 {
1225     so.playback_rate = 0;
1226     so.stereo = 0;
1227         so.sound_switch = 255;
1228
1229     S9xResetSound (TRUE);
1230     S9xSetSoundMute (TRUE);
1231
1232         return TRUE;
1233 }
1234