2823a4c8 |
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 | extern SDL_cond *sound_cv; |
122 | |
123 | void sound_timer_queue8(u32 channel, u8 value); |
124 | void sound_timer_queue16(u32 channel, u16 value); |
125 | void sound_timer_queue32(u32 channel, u32 value); |
126 | void sound_timer(fixed16_16 frequency_step, u32 channel); |
127 | void sound_reset_fifo(u32 channel); |
128 | void update_gbc_sound(u32 cpu_ticks); |
129 | void init_sound(); |
130 | void sound_write_mem_savestate(file_tag_type savestate_file); |
131 | void sound_read_savestate(file_tag_type savestate_file); |
132 | |
133 | #define gbc_sound_tone_control_low(channel, address) \ |
134 | { \ |
135 | u32 initial_volume = (value >> 12) & 0x0F; \ |
136 | u32 envelope_ticks = ((value >> 8) & 0x07) * 4; \ |
137 | gbc_sound_channel[channel].length_ticks = 64 - (value & 0x3F); \ |
138 | gbc_sound_channel[channel].sample_data = \ |
139 | square_pattern_duty[(value >> 6) & 0x03]; \ |
140 | gbc_sound_channel[channel].envelope_direction = (value >> 11) & 0x01; \ |
141 | gbc_sound_channel[channel].envelope_initial_volume = initial_volume; \ |
142 | gbc_sound_channel[channel].envelope_volume = initial_volume; \ |
143 | gbc_sound_channel[channel].envelope_initial_ticks = envelope_ticks; \ |
144 | gbc_sound_channel[channel].envelope_ticks = envelope_ticks; \ |
145 | gbc_sound_channel[channel].envelope_status = (envelope_ticks != 0); \ |
146 | gbc_sound_channel[channel].envelope_volume = initial_volume; \ |
147 | gbc_sound_update = 1; \ |
148 | address16(io_registers, address) = value; \ |
149 | } \ |
150 | |
151 | #define gbc_sound_tone_control_high(channel, address) \ |
152 | { \ |
153 | u32 rate = value & 0x7FF; \ |
154 | gbc_sound_channel[channel].rate = rate; \ |
155 | gbc_sound_channel[channel].frequency_step = \ |
156 | float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / sound_frequency); \ |
157 | gbc_sound_channel[channel].length_status = (value >> 14) & 0x01; \ |
158 | if(value & 0x8000) \ |
159 | { \ |
160 | gbc_sound_channel[channel].active_flag = 1; \ |
161 | gbc_sound_channel[channel].sample_index -= float_to_fp16_16(1.0 / 12.0); \ |
162 | gbc_sound_channel[channel].envelope_ticks = \ |
163 | gbc_sound_channel[channel].envelope_initial_ticks; \ |
164 | gbc_sound_channel[channel].envelope_volume = \ |
165 | gbc_sound_channel[channel].envelope_initial_volume; \ |
166 | } \ |
167 | \ |
168 | gbc_sound_update = 1; \ |
169 | address16(io_registers, address) = value; \ |
170 | } \ |
171 | |
172 | #define gbc_sound_tone_control_sweep() \ |
173 | { \ |
174 | u32 sweep_ticks = ((value >> 4) & 0x07) * 2; \ |
175 | gbc_sound_channel[0].sweep_shift = value & 0x07; \ |
176 | gbc_sound_channel[0].sweep_direction = (value >> 3) & 0x01; \ |
177 | gbc_sound_channel[0].sweep_status = (value != 8); \ |
178 | gbc_sound_channel[0].sweep_ticks = sweep_ticks; \ |
179 | gbc_sound_channel[0].sweep_initial_ticks = sweep_ticks; \ |
180 | gbc_sound_update = 1; \ |
181 | address16(io_registers, 0x60) = value; \ |
182 | } \ |
183 | |
184 | #define gbc_sound_wave_control() \ |
185 | { \ |
186 | gbc_sound_channel[2].wave_type = (value >> 5) & 0x01; \ |
187 | gbc_sound_channel[2].wave_bank = (value >> 6) & 0x01; \ |
188 | if(value & 0x80) \ |
189 | { \ |
190 | gbc_sound_channel[2].master_enable = 1; \ |
191 | } \ |
192 | else \ |
193 | { \ |
194 | gbc_sound_channel[2].master_enable = 0; \ |
195 | } \ |
196 | \ |
197 | gbc_sound_update = 1; \ |
198 | address16(io_registers, 0x70) = value; \ |
199 | } \ |
200 | |
201 | static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 }; |
202 | |
203 | #define gbc_sound_tone_control_low_wave() \ |
204 | { \ |
205 | gbc_sound_channel[2].length_ticks = 256 - (value & 0xFF); \ |
206 | if((value >> 15) & 0x01) \ |
207 | { \ |
208 | gbc_sound_channel[2].wave_volume = 12288; \ |
209 | } \ |
210 | else \ |
211 | { \ |
212 | gbc_sound_channel[2].wave_volume = \ |
213 | gbc_sound_wave_volume[(value >> 13) & 0x03]; \ |
214 | } \ |
215 | gbc_sound_update = 1; \ |
216 | address16(io_registers, 0x72) = value; \ |
217 | } \ |
218 | |
219 | #define gbc_sound_tone_control_high_wave() \ |
220 | { \ |
221 | u32 rate = value & 0x7FF; \ |
222 | gbc_sound_channel[2].rate = rate; \ |
223 | gbc_sound_channel[2].frequency_step = \ |
224 | float_to_fp16_16((2097152.0 / (2048 - rate)) / sound_frequency); \ |
225 | gbc_sound_channel[2].length_status = (value >> 14) & 0x01; \ |
226 | if(value & 0x8000) \ |
227 | { \ |
228 | gbc_sound_channel[2].sample_index = 0; \ |
229 | gbc_sound_channel[2].active_flag = 1; \ |
230 | } \ |
231 | gbc_sound_update = 1; \ |
232 | address16(io_registers, 0x74) = value; \ |
233 | } \ |
234 | |
235 | #define gbc_sound_noise_control() \ |
236 | { \ |
237 | u32 dividing_ratio = value & 0x07; \ |
238 | u32 frequency_shift = (value >> 4) & 0x0F; \ |
239 | if(dividing_ratio == 0) \ |
240 | { \ |
241 | gbc_sound_channel[3].frequency_step = \ |
242 | float_to_fp16_16(1048576.0 / (1 << (frequency_shift + 1)) / \ |
243 | sound_frequency); \ |
244 | } \ |
245 | else \ |
246 | { \ |
247 | gbc_sound_channel[3].frequency_step = \ |
248 | float_to_fp16_16(524288.0 / (dividing_ratio * \ |
249 | (1 << (frequency_shift + 1))) / sound_frequency); \ |
250 | } \ |
251 | gbc_sound_channel[3].noise_type = (value >> 3) & 0x01; \ |
252 | gbc_sound_channel[3].length_status = (value >> 14) & 0x01; \ |
253 | if(value & 0x8000) \ |
254 | { \ |
255 | gbc_sound_channel[3].sample_index = 0; \ |
256 | gbc_sound_channel[3].active_flag = 1; \ |
257 | gbc_sound_channel[3].envelope_ticks = \ |
258 | gbc_sound_channel[3].envelope_initial_ticks; \ |
259 | gbc_sound_channel[3].envelope_volume = \ |
260 | gbc_sound_channel[3].envelope_initial_volume; \ |
261 | } \ |
262 | gbc_sound_update = 1; \ |
263 | address16(io_registers, 0x7C) = value; \ |
264 | } \ |
265 | |
266 | #define gbc_trigger_sound_channel(channel) \ |
267 | gbc_sound_master_volume_right = value & 0x07; \ |
268 | gbc_sound_master_volume_left = (value >> 4) & 0x07; \ |
269 | gbc_sound_channel[channel].status = ((value >> (channel + 8)) & 0x01) | \ |
270 | ((value >> (channel + 11)) & 0x03) \ |
271 | |
272 | #define gbc_trigger_sound() \ |
273 | { \ |
274 | gbc_trigger_sound_channel(0); \ |
275 | gbc_trigger_sound_channel(1); \ |
276 | gbc_trigger_sound_channel(2); \ |
277 | gbc_trigger_sound_channel(3); \ |
278 | address16(io_registers, 0x80) = value; \ |
279 | } \ |
280 | |
281 | #define trigger_sound() \ |
282 | { \ |
283 | timer[0].direct_sound_channels = (((value >> 10) & 0x01) == 0) | \ |
284 | ((((value >> 14) & 0x01) == 0) << 1); \ |
285 | timer[1].direct_sound_channels = (((value >> 10) & 0x01) == 1) | \ |
286 | ((((value >> 14) & 0x01) == 1) << 1); \ |
287 | direct_sound_channel[0].volume = (value >> 2) & 0x01; \ |
288 | direct_sound_channel[0].status = (value >> 8) & 0x03; \ |
289 | direct_sound_channel[1].volume = (value >> 3) & 0x01; \ |
290 | direct_sound_channel[1].status = (value >> 12) & 0x03; \ |
291 | gbc_sound_master_volume = value & 0x03; \ |
292 | \ |
293 | if((value >> 11) & 0x01) \ |
294 | sound_reset_fifo(0); \ |
295 | if((value >> 15) & 0x01) \ |
296 | sound_reset_fifo(1); \ |
297 | address16(io_registers, 0x82) = value; \ |
298 | } \ |
299 | |
300 | #define sound_on() \ |
301 | if(value & 0x80) \ |
302 | { \ |
303 | if(sound_on != 1) \ |
304 | { \ |
305 | sound_on = 1; \ |
306 | } \ |
307 | } \ |
308 | else \ |
309 | { \ |
310 | u32 i; \ |
311 | for(i = 0; i < 4; i++) \ |
312 | { \ |
313 | gbc_sound_channel[i].active_flag = 0; \ |
314 | } \ |
315 | sound_on = 0; \ |
316 | } \ |
317 | address16(io_registers, 0x84) = \ |
318 | (address16(io_registers, 0x84) & 0x000F) | (value & 0xFFF0); \ |
319 | |
320 | #define sound_update_frequency_step(timer_number) \ |
321 | timer[timer_number].frequency_step = \ |
322 | float_to_fp16_16(16777216.0 / (timer_reload * sound_frequency)) \ |
323 | |
324 | |
325 | void reset_sound(); |
326 | void sound_exit(); |
327 | |
328 | #endif |