3 * Copyright (C) 2006 Exophase <exophase@gmail.com>
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.
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.
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
23 #define BUFFER_SIZE 65536
25 // A lot of sound cards on PC can't handle such small buffers but this
26 // seems to work well on PSP.
30 #define SOUND_BUFFER_SIZE 4096
34 #define SOUND_BUFFER_SIZE 16384
40 DIRECT_SOUND_INACTIVE,
43 DIRECT_SOUND_LEFTRIGHT
44 } direct_sound_status_type;
48 DIRECT_SOUND_VOLUME_50,
49 DIRECT_SOUND_VOLUME_100
50 } direct_sound_volume_type;
57 fixed16_16 fifo_fractional;
58 // The + 1 is to give some extra room for linear interpolation
59 // when wrapping around.
61 direct_sound_status_type status;
62 direct_sound_volume_type volume;
64 } direct_sound_struct;
72 } gbc_sound_status_type;
78 fixed16_16 frequency_step;
79 fixed16_16 sample_index;
80 fixed16_16 tick_counter;
82 u32 envelope_initial_volume;
84 u32 envelope_direction;
88 u32 envelope_initial_ticks;
92 u32 sweep_initial_ticks;
100 gbc_sound_status_type status;
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;
113 extern u32 sound_frequency;
116 extern u32 global_enable_audio;
117 extern u32 enable_low_pass_filter;
118 extern u32 audio_buffer_size_number;
120 extern SDL_mutex *sound_mutex;
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);
129 void sound_write_mem_savestate(file_tag_type savestate_file);
130 void sound_read_savestate(file_tag_type savestate_file);
134 #define gbc_sound_tone_control_low(channel, address) \
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; \
152 #define gbc_sound_tone_control_high(channel, address) \
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; \
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; \
169 gbc_sound_update = 1; \
170 address16(io_registers, address) = value; \
173 #define gbc_sound_tone_control_sweep() \
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; \
185 #define gbc_sound_wave_control() \
187 gbc_sound_channel[2].wave_type = (value >> 5) & 0x01; \
188 gbc_sound_channel[2].wave_bank = (value >> 6) & 0x01; \
191 gbc_sound_channel[2].master_enable = 1; \
195 gbc_sound_channel[2].master_enable = 0; \
198 gbc_sound_update = 1; \
199 address16(io_registers, 0x70) = value; \
202 static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 };
204 #define gbc_sound_tone_control_low_wave() \
206 gbc_sound_channel[2].length_ticks = 256 - (value & 0xFF); \
207 if((value >> 15) & 0x01) \
209 gbc_sound_channel[2].wave_volume = 12288; \
213 gbc_sound_channel[2].wave_volume = \
214 gbc_sound_wave_volume[(value >> 13) & 0x03]; \
216 gbc_sound_update = 1; \
217 address16(io_registers, 0x72) = value; \
220 #define gbc_sound_tone_control_high_wave() \
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; \
229 gbc_sound_channel[2].sample_index = 0; \
230 gbc_sound_channel[2].active_flag = 1; \
232 gbc_sound_update = 1; \
233 address16(io_registers, 0x74) = value; \
236 #define gbc_sound_noise_control() \
238 u32 dividing_ratio = value & 0x07; \
239 u32 frequency_shift = (value >> 4) & 0x0F; \
240 if(dividing_ratio == 0) \
242 gbc_sound_channel[3].frequency_step = \
243 float_to_fp16_16(1048576.0 / (1 << (frequency_shift + 1)) / \
248 gbc_sound_channel[3].frequency_step = \
249 float_to_fp16_16(524288.0 / (dividing_ratio * \
250 (1 << (frequency_shift + 1))) / sound_frequency); \
252 gbc_sound_channel[3].noise_type = (value >> 3) & 0x01; \
253 gbc_sound_channel[3].length_status = (value >> 14) & 0x01; \
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; \
263 gbc_sound_update = 1; \
264 address16(io_registers, 0x7C) = value; \
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) \
273 #define gbc_trigger_sound() \
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; \
282 #define trigger_sound() \
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; \
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; \
312 for(i = 0; i < 4; i++) \
314 gbc_sound_channel[i].active_flag = 0; \
318 address16(io_registers, 0x84) = \
319 (address16(io_registers, 0x84) & 0x000F) | (value & 0xFFF0); \
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)) \
325 #endif // IN_MEMORY_C