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