enable -Wall and fix warnings reported by it
[gpsp.git] / sound.h
1 /* gameplaySP
2  *
3  * Copyright (C) 2006 Exophase <exophase@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19
20 #ifndef SOUND_H
21 #define SOUND_H
22
23 #define BUFFER_SIZE 65536
24
25 // A lot of sound cards on PC can't handle such small buffers but this
26 // seems to work well on PSP.
27
28 #ifdef PSP_BUILD
29
30 #define SOUND_BUFFER_SIZE 4096
31
32 #else
33
34 #define SOUND_BUFFER_SIZE 16384
35
36 #endif
37
38 typedef enum
39 {
40   DIRECT_SOUND_INACTIVE,
41   DIRECT_SOUND_RIGHT,
42   DIRECT_SOUND_LEFT,
43   DIRECT_SOUND_LEFTRIGHT
44 } direct_sound_status_type;
45
46 typedef enum
47 {
48   DIRECT_SOUND_VOLUME_50,
49   DIRECT_SOUND_VOLUME_100
50 } direct_sound_volume_type;
51
52 typedef struct
53 {
54   s8 fifo[32];
55   u32 fifo_base;
56   u32 fifo_top;
57   fixed16_16 fifo_fractional;
58   // The + 1 is to give some extra room for linear interpolation
59   // when wrapping around.
60   u32 buffer_index;
61   direct_sound_status_type status;
62   direct_sound_volume_type volume;
63   u32 last_cpu_ticks;
64 } direct_sound_struct;
65
66 typedef enum
67 {
68   GBC_SOUND_INACTIVE,
69   GBC_SOUND_RIGHT,
70   GBC_SOUND_LEFT,
71   GBC_SOUND_LEFTRIGHT
72 } gbc_sound_status_type;
73
74
75 typedef struct
76 {
77   u32 rate;
78   fixed16_16 frequency_step;
79   fixed16_16 sample_index;
80   fixed16_16 tick_counter;
81   u32 total_volume;
82   u32 envelope_initial_volume;
83   u32 envelope_volume;
84   u32 envelope_direction;
85   u32 envelope_status;
86   u32 envelope_step;
87   u32 envelope_ticks;
88   u32 envelope_initial_ticks;
89   u32 sweep_status;
90   u32 sweep_direction;
91   u32 sweep_ticks;
92   u32 sweep_initial_ticks;
93   u32 sweep_shift;
94   u32 length_status;
95   u32 length_ticks;
96   u32 noise_type;
97   u32 wave_type;
98   u32 wave_bank;
99   u32 wave_volume;
100   gbc_sound_status_type status;
101   u32 active_flag;
102   u32 master_enable;
103   s8 *sample_data;
104 } gbc_sound_struct;
105
106 extern direct_sound_struct direct_sound_channel[2];
107 extern gbc_sound_struct gbc_sound_channel[4];
108 extern s8 square_pattern_duty[4][8];
109 extern u32 gbc_sound_master_volume_left;
110 extern u32 gbc_sound_master_volume_right;
111 extern u32 gbc_sound_master_volume;
112
113 extern u32 sound_frequency;
114 extern u32 sound_on;
115
116 extern u32 global_enable_audio;
117 extern u32 enable_low_pass_filter;
118 extern u32 audio_buffer_size_number;
119
120 extern SDL_mutex *sound_mutex;
121
122 void sound_timer_queue8(u32 channel, u8 value);
123 void sound_timer_queue16(u32 channel, u16 value);
124 void sound_timer_queue32(u32 channel, u32 value);
125 void sound_timer(fixed16_16 frequency_step, u32 channel);
126 void sound_reset_fifo(u32 channel);
127 void update_gbc_sound(u32 cpu_ticks);
128 void init_sound();
129 void sound_write_mem_savestate(file_tag_type savestate_file);
130 void sound_read_savestate(file_tag_type savestate_file);
131
132 #ifdef IN_MEMORY_C
133
134 #define gbc_sound_tone_control_low(channel, address)                          \
135 {                                                                             \
136   u32 initial_volume = (value >> 12) & 0x0F;                                  \
137   u32 envelope_ticks = ((value >> 8) & 0x07) * 4;                             \
138   gbc_sound_channel[channel].length_ticks = 64 - (value & 0x3F);              \
139   gbc_sound_channel[channel].sample_data =                                    \
140    square_pattern_duty[(value >> 6) & 0x03];                                  \
141   gbc_sound_channel[channel].envelope_direction = (value >> 11) & 0x01;       \
142   gbc_sound_channel[channel].envelope_initial_volume = initial_volume;        \
143   gbc_sound_channel[channel].envelope_volume = initial_volume;                \
144   gbc_sound_channel[channel].envelope_initial_ticks = envelope_ticks;         \
145   gbc_sound_channel[channel].envelope_ticks = envelope_ticks;                 \
146   gbc_sound_channel[channel].envelope_status = (envelope_ticks != 0);         \
147   gbc_sound_channel[channel].envelope_volume = initial_volume;                \
148   gbc_sound_update = 1;                                                       \
149   address16(io_registers, address) = value;                                   \
150 }                                                                             \
151
152 #define gbc_sound_tone_control_high(channel, address)                         \
153 {                                                                             \
154   u32 rate = value & 0x7FF;                                                   \
155   gbc_sound_channel[channel].rate = rate;                                     \
156   gbc_sound_channel[channel].frequency_step =                                 \
157    float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / sound_frequency);    \
158   gbc_sound_channel[channel].length_status = (value >> 14) & 0x01;            \
159   if(value & 0x8000)                                                          \
160   {                                                                           \
161     gbc_sound_channel[channel].active_flag = 1;                               \
162     gbc_sound_channel[channel].sample_index -= float_to_fp16_16(1.0 / 12.0);  \
163     gbc_sound_channel[channel].envelope_ticks =                               \
164      gbc_sound_channel[channel].envelope_initial_ticks;                       \
165     gbc_sound_channel[channel].envelope_volume =                              \
166      gbc_sound_channel[channel].envelope_initial_volume;                      \
167   }                                                                           \
168                                                                               \
169   gbc_sound_update = 1;                                                       \
170   address16(io_registers, address) = value;                                   \
171 }                                                                             \
172
173 #define gbc_sound_tone_control_sweep()                                        \
174 {                                                                             \
175   u32 sweep_ticks = ((value >> 4) & 0x07) * 2;                                \
176   gbc_sound_channel[0].sweep_shift = value & 0x07;                            \
177   gbc_sound_channel[0].sweep_direction = (value >> 3) & 0x01;                 \
178   gbc_sound_channel[0].sweep_status = (value != 8);                           \
179   gbc_sound_channel[0].sweep_ticks = sweep_ticks;                             \
180   gbc_sound_channel[0].sweep_initial_ticks = sweep_ticks;                     \
181   gbc_sound_update = 1;                                                       \
182   address16(io_registers, 0x60) = value;                                      \
183 }                                                                             \
184
185 #define gbc_sound_wave_control()                                              \
186 {                                                                             \
187   gbc_sound_channel[2].wave_type = (value >> 5) & 0x01;                       \
188   gbc_sound_channel[2].wave_bank = (value >> 6) & 0x01;                       \
189   if(value & 0x80)                                                            \
190   {                                                                           \
191     gbc_sound_channel[2].master_enable = 1;                                   \
192   }                                                                           \
193   else                                                                        \
194   {                                                                           \
195     gbc_sound_channel[2].master_enable = 0;                                   \
196   }                                                                           \
197                                                                               \
198   gbc_sound_update = 1;                                                       \
199   address16(io_registers, 0x70) = value;                                      \
200 }                                                                             \
201
202 static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 };
203
204 #define gbc_sound_tone_control_low_wave()                                     \
205 {                                                                             \
206   gbc_sound_channel[2].length_ticks = 256 - (value & 0xFF);                   \
207   if((value >> 15) & 0x01)                                                    \
208   {                                                                           \
209     gbc_sound_channel[2].wave_volume = 12288;                                 \
210   }                                                                           \
211   else                                                                        \
212   {                                                                           \
213     gbc_sound_channel[2].wave_volume =                                        \
214      gbc_sound_wave_volume[(value >> 13) & 0x03];                             \
215   }                                                                           \
216   gbc_sound_update = 1;                                                       \
217   address16(io_registers, 0x72) = value;                                      \
218 }                                                                             \
219
220 #define gbc_sound_tone_control_high_wave()                                    \
221 {                                                                             \
222   u32 rate = value & 0x7FF;                                                   \
223   gbc_sound_channel[2].rate = rate;                                           \
224   gbc_sound_channel[2].frequency_step =                                       \
225    float_to_fp16_16((2097152.0 / (2048 - rate)) / sound_frequency);           \
226   gbc_sound_channel[2].length_status = (value >> 14) & 0x01;                  \
227   if(value & 0x8000)                                                          \
228   {                                                                           \
229     gbc_sound_channel[2].sample_index = 0;                                    \
230     gbc_sound_channel[2].active_flag = 1;                                     \
231   }                                                                           \
232   gbc_sound_update = 1;                                                       \
233   address16(io_registers, 0x74) = value;                                      \
234 }                                                                             \
235
236 #define gbc_sound_noise_control()                                             \
237 {                                                                             \
238   u32 dividing_ratio = value & 0x07;                                          \
239   u32 frequency_shift = (value >> 4) & 0x0F;                                  \
240   if(dividing_ratio == 0)                                                     \
241   {                                                                           \
242     gbc_sound_channel[3].frequency_step =                                     \
243      float_to_fp16_16(1048576.0 / (1 << (frequency_shift + 1)) /              \
244      sound_frequency);                                                        \
245   }                                                                           \
246   else                                                                        \
247   {                                                                           \
248     gbc_sound_channel[3].frequency_step =                                     \
249      float_to_fp16_16(524288.0 / (dividing_ratio *                            \
250      (1 << (frequency_shift + 1))) / sound_frequency);                        \
251   }                                                                           \
252   gbc_sound_channel[3].noise_type = (value >> 3) & 0x01;                      \
253   gbc_sound_channel[3].length_status = (value >> 14) & 0x01;                  \
254   if(value & 0x8000)                                                          \
255   {                                                                           \
256     gbc_sound_channel[3].sample_index = 0;                                    \
257     gbc_sound_channel[3].active_flag = 1;                                     \
258     gbc_sound_channel[3].envelope_ticks =                                     \
259      gbc_sound_channel[3].envelope_initial_ticks;                             \
260     gbc_sound_channel[3].envelope_volume =                                    \
261      gbc_sound_channel[3].envelope_initial_volume;                            \
262   }                                                                           \
263   gbc_sound_update = 1;                                                       \
264   address16(io_registers, 0x7C) = value;                                      \
265 }                                                                             \
266
267 #define gbc_trigger_sound_channel(channel)                                    \
268   gbc_sound_master_volume_right = value & 0x07;                               \
269   gbc_sound_master_volume_left = (value >> 4) & 0x07;                         \
270   gbc_sound_channel[channel].status = ((value >> (channel + 8)) & 0x01) |     \
271    ((value >> (channel + 11)) & 0x03)                                         \
272
273 #define gbc_trigger_sound()                                                   \
274 {                                                                             \
275   gbc_trigger_sound_channel(0);                                               \
276   gbc_trigger_sound_channel(1);                                               \
277   gbc_trigger_sound_channel(2);                                               \
278   gbc_trigger_sound_channel(3);                                               \
279   address16(io_registers, 0x80) = value;                                      \
280 }                                                                             \
281
282 #define trigger_sound()                                                       \
283 {                                                                             \
284   timer[0].direct_sound_channels = (((value >> 10) & 0x01) == 0) |            \
285    ((((value >> 14) & 0x01) == 0) << 1);                                      \
286   timer[1].direct_sound_channels = (((value >> 10) & 0x01) == 1) |            \
287    ((((value >> 14) & 0x01) == 1) << 1);                                      \
288   direct_sound_channel[0].volume = (value >> 2) & 0x01;                       \
289   direct_sound_channel[0].status = (value >> 8) & 0x03;                       \
290   direct_sound_channel[1].volume = (value >> 3) & 0x01;                       \
291   direct_sound_channel[1].status = (value >> 12) & 0x03;                      \
292   gbc_sound_master_volume = value & 0x03;                                     \
293                                                                               \
294   if((value >> 11) & 0x01)                                                    \
295     sound_reset_fifo(0);                                                      \
296   if((value >> 15) & 0x01)                                                    \
297     sound_reset_fifo(1);                                                      \
298   address16(io_registers, 0x82) = value;                                      \
299 }                                                                             \
300
301 #define sound_on()                                                            \
302   if(value & 0x80)                                                            \
303   {                                                                           \
304     if(sound_on != 1)                                                         \
305     {                                                                         \
306       sound_on = 1;                                                           \
307     }                                                                         \
308   }                                                                           \
309   else                                                                        \
310   {                                                                           \
311     u32 i;                                                                    \
312     for(i = 0; i < 4; i++)                                                    \
313     {                                                                         \
314       gbc_sound_channel[i].active_flag = 0;                                   \
315     }                                                                         \
316     sound_on = 0;                                                             \
317   }                                                                           \
318   address16(io_registers, 0x84) =                                             \
319     (address16(io_registers, 0x84) & 0x000F) | (value & 0xFFF0);              \
320
321 #define sound_update_frequency_step(timer_number)                             \
322   timer[timer_number].frequency_step =                                        \
323    float_to_fp16_16(16777216.0 / (timer_reload * sound_frequency))            \
324
325 #endif // IN_MEMORY_C
326
327 void reset_sound();
328 void sound_exit();
329
330 #endif