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