workaround a problem with the harmattan gcc
[drnoksnes] / soundux.h
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 #ifndef _SOUND_H_
42 #define _SOUND_H_
43
44 enum { SOUND_SAMPLE = 0, SOUND_NOISE, SOUND_EXTRA_NOISE, SOUND_MUTE };
45 enum { SOUND_SILENT, SOUND_ATTACK, SOUND_DECAY, SOUND_SUSTAIN,
46        SOUND_RELEASE, SOUND_GAIN, SOUND_INCREASE_LINEAR,
47        SOUND_INCREASE_BENT_LINE, SOUND_DECREASE_LINEAR,
48        SOUND_DECREASE_EXPONENTIAL};
49
50 enum { MODE_NONE = SOUND_SILENT, MODE_ADSR, MODE_RELEASE = SOUND_RELEASE,
51        MODE_GAIN, MODE_INCREASE_LINEAR, MODE_INCREASE_BENT_LINE,
52        MODE_DECREASE_LINEAR, MODE_DECREASE_EXPONENTIAL};
53
54 #define MAX_ENVELOPE_HEIGHT 127
55 #define ENVELOPE_SHIFT 7
56 #define MAX_VOLUME 127
57 #define VOLUME_SHIFT 7
58 #define VOL_DIV 128
59 #define SOUND_DECODE_LENGTH 16
60
61 #define NUM_CHANNELS    8
62 #define SOUND_BUFFER_SIZE (2*44100/50)
63 #define MAX_BUFFER_SIZE SOUND_BUFFER_SIZE
64
65 #define SOUND_BUFS      4
66
67 typedef struct {
68     int playback_rate;
69     bool8 stereo;
70     bool8 mute_sound;
71     uint8 sound_switch;
72     int noise_gen;
73         uint32 freqbase; // notaz
74 } SoundStatus;
75
76 EXTERN_C SoundStatus so;
77
78 typedef struct {
79     int state;
80     int type;
81     short volume_left;
82     short volume_right;
83     uint32 hertz;
84     uint32 frequency;
85     uint32 count;
86     bool8 loop;
87     int envx;
88     short left_vol_level;
89     short right_vol_level;
90     short envx_target;
91     unsigned long int env_error;
92     unsigned long erate;
93     int direction;
94     unsigned long attack_rate;
95     unsigned long decay_rate;
96     unsigned long sustain_rate;
97     unsigned long release_rate;
98     unsigned long sustain_level;
99     signed short sample;
100     signed short decoded [16];
101     signed short previous16 [2];
102     signed short *block;
103     uint16 sample_number;
104     bool8 last_block;
105     bool8 needs_decode;
106     uint32 block_pointer;
107     uint32 sample_pointer;
108     int *echo_buf_ptr;
109     int mode;
110     int32 envxx;
111     signed short next_sample;
112     int32 interpolate;
113     int32 previous [2];
114         // notaz
115         uint8 env_ind_attack;
116         uint8 env_ind_decay;
117         uint8 env_ind_sustain;
118         uint8 dummy1;
119     // Just incase they are needed in the future, for snapshot compatibility.
120     uint32 dummy [7];
121         //I'll use Fatl's recovery on savestates.
122         short gaussian[8];
123         int   g_index;
124         unsigned short last_valid_header;
125 } Channel;
126
127 typedef struct
128 {
129     short master_volume_left;
130     short master_volume_right;
131     short echo_volume_left;
132     short echo_volume_right;
133     int echo_enable;
134     int echo_feedback;
135     int echo_ptr;
136     int echo_buffer_size;
137     int echo_write_enabled;
138     int echo_channel_enable;
139     int pitch_mod;
140     // Just incase they are needed in the future, for snapshot compatibility.
141     uint32 dummy [3];
142     Channel channels [NUM_CHANNELS];
143     bool8 no_filter;
144     int master_volume [2];
145     int echo_volume [2];
146     int noise_hertz;
147 } SSoundData;
148
149 EXTERN_C SSoundData SoundData;
150
151 void S9xSetEnvelopeHeight (int channel, int height);
152 void S9xSetSoundKeyOff (int channel);
153 void S9xSetSoundDecayMode (int channel);
154 void S9xSetSoundAttachMode (int channel);
155 void S9xSoundStartEnvelope (Channel *);
156 void S9xSetSoundSample (int channel, uint16 sample_number);
157 void S9xSetEchoDelay (int byte);
158 void S9xResetSound (bool8 full);
159 void S9xFixSoundAfterSnapshotLoad ();
160 void S9xPlaybackSoundSetting (int channel);
161 void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2);
162 void S9xStartSample (int channel);
163
164 EXTERN_C void S9xMixSamples (signed short *buffer, int sample_count);
165 void S9xSetPlaybackRate (uint32 rate);
166 bool8 S9xInitSound (void);
167 #endif
168
169
170
171 // notaz: some stuff from soundux.cpp to enable their inlining
172 #include "apu.h"
173 //#define DEBUG
174 //#include <dprintf.h>
175
176 extern int Echo [24000];
177 extern int Loop [16];
178 extern int FilterTaps [8];
179 extern int EchoBuffer [SOUND_BUFFER_SIZE];
180 extern int NoiseFreq [32];
181
182 // precalculated env rates for S9xSetEnvRate
183 extern unsigned long AttackERate     [16][10];
184 extern unsigned long DecayERate       [8][10];
185 extern unsigned long SustainERate    [32][10];
186 extern unsigned long IncreaseERate   [32][10];
187 extern unsigned long DecreaseERateExp[32][10];
188 extern unsigned long KeyOffERate[10];
189
190
191 #define FIXED_POINT 0x10000UL
192 #define CLIP8(v) \
193 if ((v) < -128) \
194     (v) = -128; \
195 else \
196 if ((v) > 127) \
197     (v) = 127
198
199 static inline void S9xSetSoundMute (bool8 mute)
200 {    so.mute_sound = mute;}
201
202 static inline void S9xSetEnvRate (Channel *ch, unsigned long rate, int direction, int target, unsigned int mode)
203 {
204     ch->envx_target = target;
205
206     if (rate == ~0UL)
207     {
208         ch->direction = 0;
209         rate = 0;
210     }
211     else
212         ch->direction = direction;
213
214
215     if (rate == 0 || so.playback_rate == 0)
216                 ch->erate = 0;
217     else
218     {
219                 switch(mode >> 28) {
220                         case 0: // attack
221                         ch->erate = AttackERate[ch->env_ind_attack][ch->state];
222                         break;
223
224                         case 1: // Decay
225                         ch->erate = DecayERate[ch->env_ind_decay][ch->state];
226                         break;
227
228                         case 2: // Sustain
229                         ch->erate = SustainERate[ch->env_ind_sustain][ch->state];
230                         break;
231
232                         case 3: // Increase
233                         ch->erate = IncreaseERate[mode&0x1f][ch->state];
234                         break;
235
236                         case 4: // DecreaseExp
237                         ch->erate = DecreaseERateExp[mode&0x1f][ch->state];
238                         break;
239
240                         case 5: // KeyOff
241                         ch->erate = KeyOffERate[ch->state];
242                         break;
243                 }
244         }
245
246 #if 0
247     static int steps [] =
248     {
249 //      0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238
250         0, 64, 619, 619, 128, 1, 64, 55, 64, 619
251     };
252
253     if (rate == 0 || so.playback_rate == 0)
254         ch->erate = 0;
255     else
256     {
257         ch->erate = (unsigned long)
258                     (((int64) FIXED_POINT * 1000 * steps [ch->state]) /
259                       (rate * so.playback_rate));
260     }
261 #endif
262 }
263
264 static inline void S9xSetEchoEnable (uint8 byte)
265 {
266     SoundData.echo_channel_enable = byte;
267     if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho)
268         byte = 0;
269     if (byte && !SoundData.echo_enable)
270     {
271         memset (Echo, 0, sizeof (Echo));
272         memset (Loop, 0, sizeof (Loop));
273     }
274
275     SoundData.echo_enable = byte;
276     for (int i = 0; i < 8; i++)
277     {
278         if (byte & (1 << i))
279             SoundData.channels [i].echo_buf_ptr = EchoBuffer;
280         else
281             SoundData.channels [i].echo_buf_ptr = 0;
282     }
283 }
284
285 static inline void S9xSetEchoFeedback (int feedback)
286 {
287     CLIP8(feedback);
288     SoundData.echo_feedback = feedback;
289 }
290
291 static inline void S9xSetFilterCoefficient (int tap, int value)
292 {
293     FilterTaps [tap & 7] = value;
294     SoundData.no_filter = (FilterTaps [0] == 127 || FilterTaps [0] == 0) && 
295                            FilterTaps [1] == 0   &&
296                            FilterTaps [2] == 0   &&
297                            FilterTaps [3] == 0   &&
298                            FilterTaps [4] == 0   &&
299                            FilterTaps [5] == 0   &&
300                            FilterTaps [6] == 0   &&
301                            FilterTaps [7] == 0;
302 }
303
304 static inline uint16 *S9xGetSampleAddress (int sample_number)
305 {
306     uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff);
307     return (uint16 *)(IAPU.RAM + addr);
308 }
309
310 static inline void S9xSetSoundFrequency (int channel, int hertz) // hertz [0~64K<<1]
311 {
312     if (so.playback_rate)
313     {
314                 if (SoundData.channels[channel].type == SOUND_NOISE)
315                         hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f];
316 #if 0 // notaz: this compiles to something awful
317                 SoundData.channels[channel].frequency = (int)
318                         (((int64) hertz * FIXED_POINT) / so.playback_rate);
319 #else
320                 SoundData.channels[channel].frequency = (hertz * so.freqbase) >> 11;
321 #endif
322
323         /*      if (Settings.FixFrequency)
324                 {
325                         SoundData.channels[channel].frequency = 
326                         (unsigned long) ((double)  SoundData.channels[channel].frequency * 0.980);
327                 }*/
328         }
329 }
330