Add copyright message to gles_video
[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
ffa573f8
D
28#ifdef RPI_BUILD
29u32 sound_frequency = 22050;
30#else
2823a4c8 31u32 sound_frequency = 44100;
ffa573f8 32#endif
2823a4c8 33
2823a4c8 34SDL_mutex *sound_mutex;
bbba3209 35static SDL_cond *sound_cv;
2823a4c8 36
2455b6a3 37#ifdef PSP_BUILD
2823a4c8 38u32 audio_buffer_size_number = 1;
6a298de4 39#elif defined(POLLUX_BUILD)
40u32 audio_buffer_size_number = 7;
2455b6a3 41#else
42u32 audio_buffer_size_number = 8;
2823a4c8 43#endif
44
bbba3209 45u32 sound_on;
46static u32 audio_buffer_size;
47static s16 sound_buffer[BUFFER_SIZE];
48static u32 sound_buffer_base;
2823a4c8 49
bbba3209 50static u32 sound_last_cpu_ticks;
51static fixed16_16 gbc_sound_tick_step;
2823a4c8 52
bbba3209 53static 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
61void 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
67void 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
74void 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 113void 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
170void 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
187s8 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
195s8 wave_samples[64];
196
197u32 noise_table15[1024];
198u32 noise_table7[4];
199
200u32 gbc_sound_master_volume_table[4] = { 1, 2, 4, 0 };
201
202u32 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
214u32 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
234u32 gbc_sound_buffer_index = 0;
235u32 gbc_sound_last_cpu_ticks = 0;
236u32 gbc_sound_partial_ticks = 0;
237
238u32 gbc_sound_master_volume_left;
239u32 gbc_sound_master_volume_right;
240u32 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 430void 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(&current_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
604void 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
665void 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
692void 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
735void 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 750void 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) \
801void 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
817sound_savestate_builder(read);
818sound_savestate_builder(write_mem);
819