Commit | Line | Data |
---|---|---|
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 | ||
21 | #include "common.h" | |
22 | #include <SDL.h> | |
23 | u32 global_enable_audio = 1; | |
24 | ||
25 | direct_sound_struct direct_sound_channel[2]; | |
26 | gbc_sound_struct gbc_sound_channel[4]; | |
27 | ||
ffa573f8 D |
28 | #ifdef RPI_BUILD |
29 | u32 sound_frequency = 22050; | |
30 | #else | |
2823a4c8 | 31 | u32 sound_frequency = 44100; |
ffa573f8 | 32 | #endif |
2823a4c8 | 33 | |
2823a4c8 | 34 | SDL_mutex *sound_mutex; |
bbba3209 | 35 | static SDL_cond *sound_cv; |
2823a4c8 | 36 | |
2455b6a3 | 37 | #ifdef PSP_BUILD |
2823a4c8 | 38 | u32 audio_buffer_size_number = 1; |
6a298de4 | 39 | #elif defined(POLLUX_BUILD) |
40 | u32 audio_buffer_size_number = 7; | |
2455b6a3 | 41 | #else |
42 | u32 audio_buffer_size_number = 8; | |
2823a4c8 | 43 | #endif |
44 | ||
bbba3209 | 45 | u32 sound_on; |
46 | static u32 audio_buffer_size; | |
47 | static s16 sound_buffer[BUFFER_SIZE]; | |
48 | static u32 sound_buffer_base; | |
2823a4c8 | 49 | |
bbba3209 | 50 | static u32 sound_last_cpu_ticks; |
51 | static fixed16_16 gbc_sound_tick_step; | |
2823a4c8 | 52 | |
bbba3209 | 53 | static u32 sound_exit_flag; |
2455b6a3 | 54 | |
2823a4c8 | 55 | // Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly |
56 | ||
57 | #define sound_timer_queue(size, value) \ | |
58 | *((s##size *)(ds->fifo + ds->fifo_top)) = value; \ | |
59 | ds->fifo_top = (ds->fifo_top + 1) % 32; \ | |
60 | ||
61 | void sound_timer_queue8(u32 channel, u8 value) | |
62 | { | |
63 | direct_sound_struct *ds = direct_sound_channel + channel; | |
64 | sound_timer_queue(8, value); | |
65 | } | |
66 | ||
67 | void sound_timer_queue16(u32 channel, u16 value) | |
68 | { | |
69 | direct_sound_struct *ds = direct_sound_channel + channel; | |
70 | sound_timer_queue(8, value & 0xFF); | |
71 | sound_timer_queue(8, value >> 8); | |
72 | } | |
73 | ||
74 | void sound_timer_queue32(u32 channel, u32 value) | |
75 | { | |
76 | direct_sound_struct *ds = direct_sound_channel + channel; | |
77 | ||
78 | sound_timer_queue(8, value & 0xFF); | |
79 | sound_timer_queue(8, (value >> 8) & 0xFF); | |
80 | sound_timer_queue(8, (value >> 16) & 0xFF); | |
81 | sound_timer_queue(8, value >> 24); | |
82 | } | |
83 | ||
84 | // Unqueue 1 sample from the base of the DS FIFO and place it on the audio | |
85 | // buffer for as many samples as necessary. If the DS FIFO is 16 bytes or | |
86 | // smaller and if DMA is enabled for the sound channel initiate a DMA transfer | |
87 | // to the DS FIFO. | |
88 | ||
89 | #define render_sample_null() \ | |
90 | ||
91 | #define render_sample_left() \ | |
92 | sound_buffer[buffer_index] += current_sample + \ | |
2f1c528a | 93 | fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8)) \ |
2823a4c8 | 94 | |
95 | #define render_sample_right() \ | |
96 | sound_buffer[buffer_index + 1] += current_sample + \ | |
2f1c528a | 97 | fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8)) \ |
2823a4c8 | 98 | |
99 | #define render_sample_both() \ | |
100 | dest_sample = current_sample + \ | |
2f1c528a | 101 | fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8)); \ |
2823a4c8 | 102 | sound_buffer[buffer_index] += dest_sample; \ |
103 | sound_buffer[buffer_index + 1] += dest_sample \ | |
104 | ||
105 | #define render_samples(type) \ | |
2f1c528a | 106 | while(fifo_fractional <= 0xFFFFFF) \ |
2823a4c8 | 107 | { \ |
108 | render_sample_##type(); \ | |
109 | fifo_fractional += frequency_step; \ | |
110 | buffer_index = (buffer_index + 2) % BUFFER_SIZE; \ | |
111 | } \ | |
112 | ||
2f1c528a | 113 | void sound_timer(fixed8_24 frequency_step, u32 channel) |
2823a4c8 | 114 | { |
115 | direct_sound_struct *ds = direct_sound_channel + channel; | |
116 | ||
2f1c528a | 117 | fixed8_24 fifo_fractional = ds->fifo_fractional; |
2823a4c8 | 118 | u32 buffer_index = ds->buffer_index; |
119 | s16 current_sample, next_sample, dest_sample; | |
120 | ||
121 | current_sample = ds->fifo[ds->fifo_base] << 4; | |
122 | ds->fifo_base = (ds->fifo_base + 1) % 32; | |
123 | next_sample = ds->fifo[ds->fifo_base] << 4; | |
124 | ||
125 | if(sound_on == 1) | |
126 | { | |
127 | if(ds->volume == DIRECT_SOUND_VOLUME_50) | |
128 | { | |
129 | current_sample >>= 1; | |
130 | next_sample >>= 1; | |
131 | } | |
132 | ||
133 | switch(ds->status) | |
134 | { | |
135 | case DIRECT_SOUND_INACTIVE: | |
136 | render_samples(null); | |
137 | break; | |
138 | ||
139 | case DIRECT_SOUND_RIGHT: | |
140 | render_samples(right); | |
141 | break; | |
142 | ||
143 | case DIRECT_SOUND_LEFT: | |
144 | render_samples(left); | |
145 | break; | |
146 | ||
147 | case DIRECT_SOUND_LEFTRIGHT: | |
148 | render_samples(both); | |
149 | break; | |
150 | } | |
151 | } | |
152 | else | |
153 | { | |
154 | render_samples(null); | |
155 | } | |
156 | ||
157 | ds->buffer_index = buffer_index; | |
2f1c528a | 158 | ds->fifo_fractional = fp8_24_fractional_part(fifo_fractional); |
2823a4c8 | 159 | |
160 | if(((ds->fifo_top - ds->fifo_base) % 32) <= 16) | |
161 | { | |
162 | if(dma[1].direct_sound_channel == channel) | |
163 | dma_transfer(dma + 1); | |
164 | ||
165 | if(dma[2].direct_sound_channel == channel) | |
166 | dma_transfer(dma + 2); | |
167 | } | |
168 | } | |
169 | ||
170 | void sound_reset_fifo(u32 channel) | |
171 | { | |
172 | direct_sound_struct *ds = direct_sound_channel; | |
173 | ||
174 | memset(ds->fifo, 0, 32); | |
175 | } | |
176 | ||
177 | // Initial pattern data = 4bits (signed) | |
178 | // Channel volume = 12bits | |
179 | // Envelope volume = 14bits | |
180 | // Master volume = 2bits | |
181 | ||
182 | // Recalculate left and right volume as volume changes. | |
183 | // To calculate the current sample, use (sample * volume) >> 16 | |
184 | ||
185 | // Square waves range from -8 (low) to 7 (high) | |
186 | ||
187 | s8 square_pattern_duty[4][8] = | |
188 | { | |
189 | { 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0xF8, 0xF8, 0xF8 }, | |
190 | { 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0x07, 0xF8, 0xF8 }, | |
191 | { 0xF8, 0xF8, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8 }, | |
192 | { 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8, 0x07, 0x07 }, | |
193 | }; | |
194 | ||
195 | s8 wave_samples[64]; | |
196 | ||
197 | u32 noise_table15[1024]; | |
198 | u32 noise_table7[4]; | |
199 | ||
200 | u32 gbc_sound_master_volume_table[4] = { 1, 2, 4, 0 }; | |
201 | ||
202 | u32 gbc_sound_channel_volume_table[8] = | |
203 | { | |
204 | fixed_div(0, 7, 12), | |
205 | fixed_div(1, 7, 12), | |
206 | fixed_div(2, 7, 12), | |
207 | fixed_div(3, 7, 12), | |
208 | fixed_div(4, 7, 12), | |
209 | fixed_div(5, 7, 12), | |
210 | fixed_div(6, 7, 12), | |
211 | fixed_div(7, 7, 12) | |
212 | }; | |
213 | ||
214 | u32 gbc_sound_envelope_volume_table[16] = | |
215 | { | |
216 | fixed_div(0, 15, 14), | |
217 | fixed_div(1, 15, 14), | |
218 | fixed_div(2, 15, 14), | |
219 | fixed_div(3, 15, 14), | |
220 | fixed_div(4, 15, 14), | |
221 | fixed_div(5, 15, 14), | |
222 | fixed_div(6, 15, 14), | |
223 | fixed_div(7, 15, 14), | |
224 | fixed_div(8, 15, 14), | |
225 | fixed_div(9, 15, 14), | |
226 | fixed_div(10, 15, 14), | |
227 | fixed_div(11, 15, 14), | |
228 | fixed_div(12, 15, 14), | |
229 | fixed_div(13, 15, 14), | |
230 | fixed_div(14, 15, 14), | |
231 | fixed_div(15, 15, 14) | |
232 | }; | |
233 | ||
234 | u32 gbc_sound_buffer_index = 0; | |
235 | u32 gbc_sound_last_cpu_ticks = 0; | |
236 | u32 gbc_sound_partial_ticks = 0; | |
237 | ||
238 | u32 gbc_sound_master_volume_left; | |
239 | u32 gbc_sound_master_volume_right; | |
240 | u32 gbc_sound_master_volume; | |
241 | ||
242 | #define update_volume_channel_envelope(channel) \ | |
243 | volume_##channel = gbc_sound_envelope_volume_table[envelope_volume] * \ | |
244 | gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] * \ | |
245 | gbc_sound_master_volume_table[gbc_sound_master_volume] \ | |
246 | ||
247 | #define update_volume_channel_noenvelope(channel) \ | |
248 | volume_##channel = gs->wave_volume * \ | |
249 | gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] * \ | |
250 | gbc_sound_master_volume_table[gbc_sound_master_volume] \ | |
251 | ||
252 | #define update_volume(type) \ | |
253 | update_volume_channel_##type(left); \ | |
254 | update_volume_channel_##type(right) \ | |
255 | ||
256 | #define update_tone_sweep() \ | |
257 | if(gs->sweep_status) \ | |
258 | { \ | |
259 | u32 sweep_ticks = gs->sweep_ticks - 1; \ | |
260 | \ | |
261 | if(sweep_ticks == 0) \ | |
262 | { \ | |
263 | u32 rate = gs->rate; \ | |
264 | \ | |
265 | if(gs->sweep_direction) \ | |
266 | rate = rate - (rate >> gs->sweep_shift); \ | |
267 | else \ | |
268 | rate = rate + (rate >> gs->sweep_shift); \ | |
269 | \ | |
270 | if(rate > 2048) \ | |
271 | rate = 2048; \ | |
272 | \ | |
2f1c528a | 273 | frequency_step = float_to_fp16_16(((131072.0f / (2048 - rate)) * 8.0f) \ |
274 | / sound_frequency); \ | |
2823a4c8 | 275 | \ |
276 | gs->frequency_step = frequency_step; \ | |
277 | gs->rate = rate; \ | |
278 | \ | |
279 | sweep_ticks = gs->sweep_initial_ticks; \ | |
280 | } \ | |
281 | gs->sweep_ticks = sweep_ticks; \ | |
282 | } \ | |
283 | ||
284 | #define update_tone_nosweep() \ | |
285 | ||
286 | #define update_tone_envelope() \ | |
287 | if(gs->envelope_status) \ | |
288 | { \ | |
289 | u32 envelope_ticks = gs->envelope_ticks - 1; \ | |
290 | envelope_volume = gs->envelope_volume; \ | |
291 | \ | |
292 | if(envelope_ticks == 0) \ | |
293 | { \ | |
294 | if(gs->envelope_direction) \ | |
295 | { \ | |
296 | if(envelope_volume != 15) \ | |
297 | envelope_volume = gs->envelope_volume + 1; \ | |
298 | } \ | |
299 | else \ | |
300 | { \ | |
301 | if(envelope_volume != 0) \ | |
302 | envelope_volume = gs->envelope_volume - 1; \ | |
303 | } \ | |
304 | \ | |
305 | update_volume(envelope); \ | |
306 | \ | |
307 | gs->envelope_volume = envelope_volume; \ | |
308 | gs->envelope_ticks = gs->envelope_initial_ticks; \ | |
309 | } \ | |
310 | else \ | |
311 | { \ | |
312 | gs->envelope_ticks = envelope_ticks; \ | |
313 | } \ | |
314 | } \ | |
315 | ||
316 | #define update_tone_noenvelope() \ | |
317 | ||
2823a4c8 | 318 | #define update_tone_counters(envelope_op, sweep_op) \ |
319 | tick_counter += gbc_sound_tick_step; \ | |
320 | if(tick_counter > 0xFFFF) \ | |
321 | { \ | |
322 | if(gs->length_status) \ | |
323 | { \ | |
324 | u32 length_ticks = gs->length_ticks - 1; \ | |
325 | gs->length_ticks = length_ticks; \ | |
326 | \ | |
327 | if(length_ticks == 0) \ | |
328 | { \ | |
329 | gs->active_flag = 0; \ | |
330 | break; \ | |
331 | } \ | |
332 | } \ | |
333 | \ | |
334 | update_tone_##envelope_op(); \ | |
335 | update_tone_##sweep_op(); \ | |
336 | \ | |
337 | tick_counter &= 0xFFFF; \ | |
338 | } \ | |
339 | ||
340 | #define gbc_sound_render_sample_right() \ | |
341 | sound_buffer[buffer_index + 1] += (current_sample * volume_right) >> 22 \ | |
342 | ||
343 | #define gbc_sound_render_sample_left() \ | |
344 | sound_buffer[buffer_index] += (current_sample * volume_left) >> 22 \ | |
345 | ||
346 | #define gbc_sound_render_sample_both() \ | |
347 | gbc_sound_render_sample_right(); \ | |
348 | gbc_sound_render_sample_left() \ | |
349 | ||
350 | #define gbc_sound_render_samples(type, sample_length, envelope_op, sweep_op) \ | |
351 | for(i = 0; i < buffer_ticks; i++) \ | |
352 | { \ | |
353 | current_sample = \ | |
354 | sample_data[fp16_16_to_u32(sample_index) % sample_length]; \ | |
355 | gbc_sound_render_sample_##type(); \ | |
356 | \ | |
357 | sample_index += frequency_step; \ | |
358 | buffer_index = (buffer_index + 2) % BUFFER_SIZE; \ | |
359 | \ | |
360 | update_tone_counters(envelope_op, sweep_op); \ | |
361 | } \ | |
362 | ||
363 | #define gbc_noise_wrap_full 32767 | |
364 | ||
365 | #define gbc_noise_wrap_half 126 | |
366 | ||
367 | #define get_noise_sample_full() \ | |
368 | current_sample = \ | |
369 | ((s32)(noise_table15[fp16_16_to_u32(sample_index) >> 5] << \ | |
370 | (fp16_16_to_u32(sample_index) & 0x1F)) >> 31) & 0x0F \ | |
371 | ||
372 | #define get_noise_sample_half() \ | |
373 | current_sample = \ | |
374 | ((s32)(noise_table7[fp16_16_to_u32(sample_index) >> 5] << \ | |
375 | (fp16_16_to_u32(sample_index) & 0x1F)) >> 31) & 0x0F \ | |
376 | ||
377 | #define gbc_sound_render_noise(type, noise_type, envelope_op, sweep_op) \ | |
378 | for(i = 0; i < buffer_ticks; i++) \ | |
379 | { \ | |
380 | get_noise_sample_##noise_type(); \ | |
381 | gbc_sound_render_sample_##type(); \ | |
382 | \ | |
383 | sample_index += frequency_step; \ | |
384 | \ | |
385 | if(sample_index >= u32_to_fp16_16(gbc_noise_wrap_##noise_type)) \ | |
386 | sample_index -= u32_to_fp16_16(gbc_noise_wrap_##noise_type); \ | |
387 | \ | |
388 | buffer_index = (buffer_index + 2) % BUFFER_SIZE; \ | |
389 | update_tone_counters(envelope_op, sweep_op); \ | |
390 | } \ | |
391 | ||
392 | #define gbc_sound_render_channel(type, sample_length, envelope_op, sweep_op) \ | |
393 | buffer_index = gbc_sound_buffer_index; \ | |
394 | sample_index = gs->sample_index; \ | |
395 | frequency_step = gs->frequency_step; \ | |
396 | tick_counter = gs->tick_counter; \ | |
397 | \ | |
398 | update_volume(envelope_op); \ | |
399 | \ | |
400 | switch(gs->status) \ | |
401 | { \ | |
402 | case GBC_SOUND_INACTIVE: \ | |
403 | break; \ | |
404 | \ | |
405 | case GBC_SOUND_LEFT: \ | |
406 | gbc_sound_render_##type(left, sample_length, envelope_op, sweep_op); \ | |
407 | break; \ | |
408 | \ | |
409 | case GBC_SOUND_RIGHT: \ | |
410 | gbc_sound_render_##type(right, sample_length, envelope_op, sweep_op); \ | |
411 | break; \ | |
412 | \ | |
413 | case GBC_SOUND_LEFTRIGHT: \ | |
414 | gbc_sound_render_##type(both, sample_length, envelope_op, sweep_op); \ | |
415 | break; \ | |
416 | } \ | |
417 | \ | |
418 | gs->sample_index = sample_index; \ | |
419 | gs->tick_counter = tick_counter; \ | |
420 | ||
421 | #define gbc_sound_load_wave_ram(bank) \ | |
422 | wave_bank = wave_samples + (bank * 32); \ | |
423 | for(i = 0, i2 = 0; i < 16; i++, i2 += 2) \ | |
424 | { \ | |
425 | current_sample = wave_ram[i]; \ | |
426 | wave_bank[i2] = (((current_sample >> 4) & 0x0F) - 8); \ | |
427 | wave_bank[i2 + 1] = ((current_sample & 0x0F) - 8); \ | |
428 | } \ | |
429 | ||
2823a4c8 | 430 | void update_gbc_sound(u32 cpu_ticks) |
431 | { | |
2f1c528a | 432 | fixed16_16 buffer_ticks = float_to_fp16_16((float)(cpu_ticks - |
433 | gbc_sound_last_cpu_ticks) * sound_frequency / GBC_BASE_RATE); | |
2823a4c8 | 434 | u32 i, i2; |
435 | gbc_sound_struct *gs = gbc_sound_channel; | |
436 | fixed16_16 sample_index, frequency_step; | |
437 | fixed16_16 tick_counter; | |
438 | u32 buffer_index; | |
439 | s32 volume_left, volume_right; | |
440 | u32 envelope_volume; | |
441 | s32 current_sample; | |
442 | u32 sound_status = address16(io_registers, 0x84) & 0xFFF0; | |
443 | s8 *sample_data; | |
444 | s8 *wave_bank; | |
445 | u8 *wave_ram = ((u8 *)io_registers) + 0x90; | |
446 | ||
447 | gbc_sound_partial_ticks += fp16_16_fractional_part(buffer_ticks); | |
448 | buffer_ticks = fp16_16_to_u32(buffer_ticks); | |
449 | ||
450 | if(gbc_sound_partial_ticks > 0xFFFF) | |
451 | { | |
452 | buffer_ticks += 1; | |
453 | gbc_sound_partial_ticks &= 0xFFFF; | |
454 | } | |
455 | ||
456 | SDL_LockMutex(sound_mutex); | |
457 | if(synchronize_flag) | |
458 | { | |
2f1c528a | 459 | if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >= |
460 | (audio_buffer_size * 2)) | |
2823a4c8 | 461 | { |
462 | while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) > | |
463 | (audio_buffer_size * 3 / 2)) | |
464 | { | |
465 | SDL_CondWait(sound_cv, sound_mutex); | |
466 | } | |
467 | ||
468 | #ifdef PSP_BUILD | |
469 | if(current_frameskip_type == auto_frameskip) | |
470 | { | |
471 | sceDisplayWaitVblankStart(); | |
472 | real_frame_count = 0; | |
473 | virtual_frame_count = 0; | |
474 | } | |
2455b6a3 | 475 | #else |
2823a4c8 | 476 | if(current_frameskip_type == auto_frameskip) |
477 | { | |
2455b6a3 | 478 | /* |
2823a4c8 | 479 | u64 current_ticks; |
480 | u64 next_ticks; | |
481 | get_ticks_us(¤t_ticks); | |
482 | ||
483 | next_ticks = ((current_ticks + 16666) / 16667) * 16667; | |
484 | delay_us(next_ticks - current_ticks); | |
485 | ||
486 | get_ticks_us(&frame_count_initial_timestamp); | |
2455b6a3 | 487 | */ |
488 | /* prevent frameskip, or it will cause more audio, | |
489 | * then more waiting here, then frame skip again, ... */ | |
490 | num_skipped_frames = 100; | |
2823a4c8 | 491 | } |
492 | #endif | |
493 | ||
2823a4c8 | 494 | } |
495 | } | |
496 | if(sound_on == 1) | |
497 | { | |
498 | gs = gbc_sound_channel + 0; | |
499 | if(gs->active_flag) | |
500 | { | |
501 | sound_status |= 0x01; | |
502 | sample_data = gs->sample_data; | |
503 | envelope_volume = gs->envelope_volume; | |
504 | gbc_sound_render_channel(samples, 8, envelope, sweep); | |
505 | } | |
506 | ||
507 | gs = gbc_sound_channel + 1; | |
508 | if(gs->active_flag) | |
509 | { | |
510 | sound_status |= 0x02; | |
511 | sample_data = gs->sample_data; | |
512 | envelope_volume = gs->envelope_volume; | |
513 | gbc_sound_render_channel(samples, 8, envelope, nosweep); | |
514 | } | |
515 | ||
516 | gs = gbc_sound_channel + 2; | |
517 | if(gbc_sound_wave_update) | |
518 | { | |
519 | if(gs->wave_bank == 1) | |
520 | { | |
521 | gbc_sound_load_wave_ram(1); | |
522 | } | |
523 | else | |
524 | { | |
525 | gbc_sound_load_wave_ram(0); | |
526 | } | |
527 | ||
528 | gbc_sound_wave_update = 0; | |
529 | } | |
530 | ||
531 | if((gs->active_flag) && (gs->master_enable)) | |
532 | { | |
533 | sound_status |= 0x04; | |
534 | sample_data = wave_samples; | |
535 | if(gs->wave_type == 0) | |
536 | { | |
537 | if(gs->wave_bank == 1) | |
538 | sample_data += 32; | |
539 | ||
540 | gbc_sound_render_channel(samples, 32, noenvelope, nosweep); | |
541 | } | |
542 | else | |
543 | { | |
544 | gbc_sound_render_channel(samples, 64, noenvelope, nosweep); | |
545 | } | |
546 | } | |
547 | ||
548 | gs = gbc_sound_channel + 3; | |
549 | if(gs->active_flag) | |
550 | { | |
551 | sound_status |= 0x08; | |
552 | envelope_volume = gs->envelope_volume; | |
553 | ||
554 | if(gs->noise_type == 1) | |
555 | { | |
556 | gbc_sound_render_channel(noise, half, envelope, nosweep); | |
557 | } | |
558 | else | |
559 | { | |
560 | gbc_sound_render_channel(noise, full, envelope, nosweep); | |
561 | } | |
562 | } | |
563 | } | |
564 | ||
565 | address16(io_registers, 0x84) = sound_status; | |
566 | ||
2823a4c8 | 567 | gbc_sound_last_cpu_ticks = cpu_ticks; |
568 | gbc_sound_buffer_index = | |
569 | (gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE; | |
e9c7b137 | 570 | |
571 | SDL_UnlockMutex(sound_mutex); | |
572 | ||
573 | SDL_CondSignal(sound_cv); | |
2823a4c8 | 574 | } |
575 | ||
576 | #define sound_copy_normal() \ | |
577 | current_sample = source[i] \ | |
578 | ||
579 | #define sound_copy(source_offset, length, render_type) \ | |
580 | _length = (length) / 2; \ | |
581 | source = (s16 *)(sound_buffer + source_offset); \ | |
582 | for(i = 0; i < _length; i++) \ | |
583 | { \ | |
584 | sound_copy_##render_type(); \ | |
585 | if(current_sample > 2047) \ | |
586 | current_sample = 2047; \ | |
587 | if(current_sample < -2048) \ | |
588 | current_sample = -2048; \ | |
589 | \ | |
590 | stream_base[i] = current_sample << 4; \ | |
591 | source[i] = 0; \ | |
592 | } \ | |
593 | ||
594 | #define sound_copy_null(source_offset, length) \ | |
595 | _length = (length) / 2; \ | |
596 | source = (s16 *)(sound_buffer + source_offset); \ | |
597 | for(i = 0; i < _length; i++) \ | |
598 | { \ | |
599 | stream_base[i] = 0; \ | |
600 | source[i] = 0; \ | |
601 | } \ | |
602 | ||
603 | ||
604 | void sound_callback(void *userdata, Uint8 *stream, int length) | |
605 | { | |
606 | u32 sample_length = length / 2; | |
607 | u32 _length; | |
608 | u32 i; | |
609 | s16 *stream_base = (s16 *)stream; | |
610 | s16 *source; | |
611 | s32 current_sample; | |
612 | ||
613 | SDL_LockMutex(sound_mutex); | |
614 | ||
615 | while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) < | |
2455b6a3 | 616 | length && !sound_exit_flag) |
2823a4c8 | 617 | { |
618 | SDL_CondWait(sound_cv, sound_mutex); | |
619 | } | |
620 | ||
621 | if(global_enable_audio) | |
622 | { | |
623 | if((sound_buffer_base + sample_length) >= BUFFER_SIZE) | |
624 | { | |
625 | u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2; | |
626 | sound_copy(sound_buffer_base, partial_length, normal); | |
627 | source = (s16 *)sound_buffer; | |
628 | sound_copy(0, length - partial_length, normal); | |
629 | sound_buffer_base = (length - partial_length) / 2; | |
630 | } | |
631 | else | |
632 | { | |
633 | sound_copy(sound_buffer_base, length, normal); | |
634 | sound_buffer_base += sample_length; | |
635 | } | |
636 | } | |
637 | else | |
638 | { | |
639 | if((sound_buffer_base + sample_length) >= BUFFER_SIZE) | |
640 | { | |
641 | u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2; | |
642 | sound_copy_null(sound_buffer_base, partial_length); | |
643 | source = (s16 *)sound_buffer; | |
644 | sound_copy(0, length - partial_length, normal); | |
645 | sound_buffer_base = (length - partial_length) / 2; | |
646 | } | |
647 | else | |
648 | { | |
649 | sound_copy_null(sound_buffer_base, length); | |
650 | sound_buffer_base += sample_length; | |
651 | } | |
652 | } | |
653 | ||
654 | SDL_CondSignal(sound_cv); | |
655 | ||
656 | SDL_UnlockMutex(sound_mutex); | |
657 | } | |
658 | ||
659 | // Special thanks to blarrg for the LSFR frequency used in Meridian, as posted | |
660 | // on the forum at http://meridian.overclocked.org: | |
661 | // http://meridian.overclocked.org/cgi-bin/wwwthreads/showpost.pl?Board=merid | |
662 | // angeneraldiscussion&Number=2069&page=0&view=expanded&mode=threaded&sb=4 | |
663 | // Hope you don't mind me borrowing it ^_- | |
664 | ||
665 | void init_noise_table(u32 *table, u32 period, u32 bit_length) | |
666 | { | |
667 | u32 shift_register = 0xFF; | |
668 | u32 mask = ~(1 << bit_length); | |
669 | s32 table_pos, bit_pos; | |
670 | u32 current_entry; | |
671 | u32 table_period = (period + 31) / 32; | |
672 | ||
673 | // Bits are stored in reverse order so they can be more easily moved to | |
674 | // bit 31, for sign extended shift down. | |
675 | ||
676 | for(table_pos = 0; table_pos < table_period; table_pos++) | |
677 | { | |
678 | current_entry = 0; | |
679 | for(bit_pos = 31; bit_pos >= 0; bit_pos--) | |
680 | { | |
681 | current_entry |= (shift_register & 0x01) << bit_pos; | |
682 | ||
683 | shift_register = | |
684 | ((1 & (shift_register ^ (shift_register >> 1))) << bit_length) | | |
685 | ((shift_register >> 1) & mask); | |
686 | } | |
687 | ||
688 | table[table_pos] = current_entry; | |
689 | } | |
690 | } | |
691 | ||
692 | void reset_sound() | |
693 | { | |
694 | direct_sound_struct *ds = direct_sound_channel; | |
695 | gbc_sound_struct *gs = gbc_sound_channel; | |
696 | u32 i; | |
697 | ||
2f1c528a | 698 | SDL_LockMutex(sound_mutex); |
699 | ||
2823a4c8 | 700 | sound_on = 0; |
701 | sound_buffer_base = 0; | |
702 | sound_last_cpu_ticks = 0; | |
2f1c528a | 703 | memset(sound_buffer, 0, sizeof(sound_buffer)); |
2823a4c8 | 704 | |
705 | for(i = 0; i < 2; i++, ds++) | |
706 | { | |
707 | ds->buffer_index = 0; | |
708 | ds->status = DIRECT_SOUND_INACTIVE; | |
709 | ds->fifo_top = 0; | |
710 | ds->fifo_base = 0; | |
711 | ds->fifo_fractional = 0; | |
712 | ds->last_cpu_ticks = 0; | |
713 | memset(ds->fifo, 0, 32); | |
714 | } | |
715 | ||
716 | gbc_sound_buffer_index = 0; | |
717 | gbc_sound_last_cpu_ticks = 0; | |
718 | gbc_sound_partial_ticks = 0; | |
719 | ||
720 | gbc_sound_master_volume_left = 0; | |
721 | gbc_sound_master_volume_right = 0; | |
722 | gbc_sound_master_volume = 0; | |
723 | memset(wave_samples, 0, 64); | |
724 | ||
725 | for(i = 0; i < 4; i++, gs++) | |
726 | { | |
727 | gs->status = GBC_SOUND_INACTIVE; | |
728 | gs->sample_data = square_pattern_duty[2]; | |
729 | gs->active_flag = 0; | |
730 | } | |
2f1c528a | 731 | |
732 | SDL_UnlockMutex(sound_mutex); | |
2823a4c8 | 733 | } |
734 | ||
735 | void sound_exit() | |
736 | { | |
737 | gbc_sound_buffer_index = | |
738 | (sound_buffer_base + audio_buffer_size) % BUFFER_SIZE; | |
739 | SDL_PauseAudio(1); | |
2455b6a3 | 740 | sound_exit_flag = 1; |
2823a4c8 | 741 | SDL_CondSignal(sound_cv); |
2455b6a3 | 742 | SDL_CloseAudio(); |
40a392b0 | 743 | SDL_Delay(200); |
744 | SDL_DestroyMutex(sound_mutex); | |
745 | sound_mutex = NULL; | |
746 | SDL_DestroyCond(sound_cv); | |
747 | sound_cv = NULL; | |
2823a4c8 | 748 | } |
749 | ||
40a392b0 | 750 | void init_sound(int need_reset) |
2823a4c8 | 751 | { |
bbba3209 | 752 | SDL_AudioSpec sound_settings; |
753 | ||
40a392b0 | 754 | sound_exit_flag = 0; |
2823a4c8 | 755 | #ifdef PSP_BUILD |
756 | audio_buffer_size = (audio_buffer_size_number * 1024) + 3072; | |
2455b6a3 | 757 | #else |
2823a4c8 | 758 | audio_buffer_size = 16 << audio_buffer_size_number; |
759 | // audio_buffer_size = 16384; | |
2823a4c8 | 760 | #endif |
761 | ||
762 | SDL_AudioSpec desired_spec = | |
763 | { | |
764 | sound_frequency, | |
765 | AUDIO_S16, | |
766 | 2, | |
767 | 0, | |
768 | audio_buffer_size / 4, | |
769 | 0, | |
770 | 0, | |
771 | sound_callback, | |
772 | NULL | |
773 | }; | |
774 | ||
2823a4c8 | 775 | sound_mutex = SDL_CreateMutex(); |
776 | sound_cv = SDL_CreateCond(); | |
2455b6a3 | 777 | |
778 | SDL_OpenAudio(&desired_spec, &sound_settings); | |
779 | sound_frequency = sound_settings.freq; | |
780 | audio_buffer_size = sound_settings.size; | |
781 | u32 i = audio_buffer_size / 16; | |
782 | for (audio_buffer_size_number = 0; i && (i & 1) == 0; i >>= 1) | |
783 | audio_buffer_size_number++; | |
784 | #ifndef PSP_BUILD | |
785 | printf("audio: freq %d, size %d\n", sound_frequency, audio_buffer_size); | |
786 | #endif | |
787 | ||
2f1c528a | 788 | gbc_sound_tick_step = |
789 | float_to_fp16_16(256.0f / sound_frequency); | |
790 | ||
791 | init_noise_table(noise_table15, 32767, 14); | |
792 | init_noise_table(noise_table7, 127, 6); | |
793 | ||
40a392b0 | 794 | if (need_reset) |
795 | reset_sound(); | |
2f1c528a | 796 | |
2823a4c8 | 797 | SDL_PauseAudio(0); |
798 | } | |
799 | ||
800 | #define sound_savestate_builder(type) \ | |
801 | void sound_##type##_savestate(file_tag_type savestate_file) \ | |
802 | { \ | |
803 | file_##type##_variable(savestate_file, sound_on); \ | |
804 | file_##type##_variable(savestate_file, sound_buffer_base); \ | |
805 | file_##type##_variable(savestate_file, sound_last_cpu_ticks); \ | |
806 | file_##type##_variable(savestate_file, gbc_sound_buffer_index); \ | |
807 | file_##type##_variable(savestate_file, gbc_sound_last_cpu_ticks); \ | |
808 | file_##type##_variable(savestate_file, gbc_sound_partial_ticks); \ | |
809 | file_##type##_variable(savestate_file, gbc_sound_master_volume_left); \ | |
810 | file_##type##_variable(savestate_file, gbc_sound_master_volume_right); \ | |
811 | file_##type##_variable(savestate_file, gbc_sound_master_volume); \ | |
812 | file_##type##_array(savestate_file, wave_samples); \ | |
813 | file_##type##_array(savestate_file, direct_sound_channel); \ | |
814 | file_##type##_array(savestate_file, gbc_sound_channel); \ | |
815 | } \ | |
816 | ||
817 | sound_savestate_builder(read); | |
818 | sound_savestate_builder(write_mem); | |
819 |