| 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 |