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