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 u32 global_enable_audio = 1;
23 
24 direct_sound_struct direct_sound_channel[2];
25 gbc_sound_struct gbc_sound_channel[4];
26 
27 u32 sound_frequency = GBA_SOUND_FREQUENCY;
28 
29 u32 sound_on;
30 static s16 sound_buffer[BUFFER_SIZE];
31 static u32 sound_buffer_base;
32 
33 static u32 sound_last_cpu_ticks;
34 static fixed16_16 gbc_sound_tick_step;
35 
36 /* Queue 1 sample to the top of the DS FIFO, wrap around circularly */
37 
sound_timer_queue8(u32 channel,u8 value)38 void sound_timer_queue8(u32 channel, u8 value)
39 {
40   direct_sound_struct *ds = direct_sound_channel + channel;
41 
42   *((s8 *)(ds->fifo + ds->fifo_top)) = value;
43   ds->fifo_top = (ds->fifo_top + 1) % 32;
44 }
45 
46 /* Queue 2 samples to the top of the DS FIFO, wrap around circularly */
47 
sound_timer_queue16(u32 channel,u16 value)48 void sound_timer_queue16(u32 channel, u16 value)
49 {
50   direct_sound_struct *ds = direct_sound_channel + channel;
51 
52   *((s8 *)(ds->fifo + ds->fifo_top)) = value & 0xFF;
53   ds->fifo_top = (ds->fifo_top + 1) % 32;
54 
55   *((s8 *)(ds->fifo + ds->fifo_top)) = value >> 8;
56   ds->fifo_top = (ds->fifo_top + 1) % 32;
57 }
58 
59 /* Queue 4 samples to the top of the DS FIFO, wrap around circularly */
60 
sound_timer_queue32(u32 channel,u32 value)61 void sound_timer_queue32(u32 channel, u32 value)
62 {
63   direct_sound_struct *ds = direct_sound_channel + channel;
64 
65   *((s8 *)(ds->fifo + ds->fifo_top)) = value & 0xFF;
66   ds->fifo_top = (ds->fifo_top + 1) % 32;
67 
68   *((s8 *)(ds->fifo + ds->fifo_top)) = (value >> 8) & 0xFF;
69   ds->fifo_top = (ds->fifo_top + 1) % 32;
70 
71   *((s8 *)(ds->fifo + ds->fifo_top)) = (value >> 16) & 0xFF;
72   ds->fifo_top = (ds->fifo_top + 1) % 32;
73 
74   *((s8 *)(ds->fifo + ds->fifo_top)) = (value >> 24);
75   ds->fifo_top = (ds->fifo_top + 1) % 32;
76 }
77 
78 
sound_timer(fixed8_24 frequency_step,u32 channel)79 void sound_timer(fixed8_24 frequency_step, u32 channel)
80 {
81   unsigned sample_status = DIRECT_SOUND_INACTIVE;
82   direct_sound_struct *ds = direct_sound_channel + channel;
83 
84   fixed8_24 fifo_fractional = ds->fifo_fractional;
85   u32 buffer_index = ds->buffer_index;
86   s16 current_sample, next_sample;
87 
88   current_sample = ds->fifo[ds->fifo_base] << 4;
89   ds->fifo_base = (ds->fifo_base + 1) % 32;
90   next_sample = ds->fifo[ds->fifo_base] << 4;
91 
92   if(sound_on == 1)
93   {
94     if(ds->volume == DIRECT_SOUND_VOLUME_50)
95     {
96       current_sample >>= 1;
97       next_sample >>= 1;
98     }
99 
100     sample_status = ds->status;
101 
102   }
103 
104   // Unqueue 1 sample from the base of the DS FIFO and place it on the audio
105   // buffer for as many samples as necessary. If the DS FIFO is 16 bytes or
106   // smaller and if DMA is enabled for the sound channel initiate a DMA transfer
107   // to the DS FIFO.
108 
109   switch(sample_status)
110   {
111      case DIRECT_SOUND_INACTIVE:
112         /* render samples NULL */
113         while(fifo_fractional <= 0xFFFFFF)
114         {
115            fifo_fractional += frequency_step;
116            buffer_index = (buffer_index + 2) % BUFFER_SIZE;
117         }
118         break;
119 
120      case DIRECT_SOUND_RIGHT:
121         /* render samples RIGHT */
122         while(fifo_fractional <= 0xFFFFFF)
123         {
124            s16 dest_sample = current_sample +
125               fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8));
126 
127            sound_buffer[buffer_index + 1]     += dest_sample;
128 
129            fifo_fractional += frequency_step;
130            buffer_index = (buffer_index + 2) % BUFFER_SIZE;
131         }
132         break;
133 
134      case DIRECT_SOUND_LEFT:
135         /* render samples LEFT */
136         while(fifo_fractional <= 0xFFFFFF)
137         {
138            s16 dest_sample = current_sample +
139               fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8));
140 
141            sound_buffer[buffer_index]     += dest_sample;
142 
143            fifo_fractional += frequency_step;
144            buffer_index = (buffer_index + 2) % BUFFER_SIZE;
145         }
146         break;
147 
148      case DIRECT_SOUND_LEFTRIGHT:
149         /* render samples LEFT and RIGHT. */
150         while(fifo_fractional <= 0xFFFFFF)
151         {
152            s16 dest_sample = current_sample +
153               fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8));
154 
155            sound_buffer[buffer_index]     += dest_sample;
156            sound_buffer[buffer_index + 1] += dest_sample;
157            fifo_fractional += frequency_step;
158            buffer_index = (buffer_index + 2) % BUFFER_SIZE;
159         }
160         break;
161   }
162 
163   ds->buffer_index = buffer_index;
164   ds->fifo_fractional = fp8_24_fractional_part(fifo_fractional);
165 
166   if(((ds->fifo_top - ds->fifo_base) % 32) <= 16)
167   {
168     if(dma[1].direct_sound_channel == channel)
169       dma_transfer(dma + 1);
170 
171     if(dma[2].direct_sound_channel == channel)
172       dma_transfer(dma + 2);
173   }
174 }
175 
sound_reset_fifo(u32 channel)176 void sound_reset_fifo(u32 channel)
177 {
178   direct_sound_struct *ds = direct_sound_channel;
179 
180   memset(ds->fifo, 0, 32);
181 }
182 
183 // Initial pattern data = 4bits (signed)
184 // Channel volume = 12bits
185 // Envelope volume = 14bits
186 // Master volume = 2bits
187 
188 // Recalculate left and right volume as volume changes.
189 // To calculate the current sample, use (sample * volume) >> 16
190 
191 // Square waves range from -8 (low) to 7 (high)
192 
193 s8 square_pattern_duty[4][8] =
194 {
195   { 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0xF8, 0xF8, 0xF8 },
196   { 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0x07, 0xF8, 0xF8 },
197   { 0xF8, 0xF8, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8 },
198   { 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8, 0x07, 0x07 },
199 };
200 
201 s8 wave_samples[64];
202 
203 u32 noise_table15[1024];
204 u32 noise_table7[4];
205 
206 u32 gbc_sound_master_volume_table[4] = { 1, 2, 4, 0 };
207 
208 u32 gbc_sound_channel_volume_table[8] =
209 {
210   fixed_div(0, 7, 12),
211   fixed_div(1, 7, 12),
212   fixed_div(2, 7, 12),
213   fixed_div(3, 7, 12),
214   fixed_div(4, 7, 12),
215   fixed_div(5, 7, 12),
216   fixed_div(6, 7, 12),
217   fixed_div(7, 7, 12)
218 };
219 
220 u32 gbc_sound_envelope_volume_table[16] =
221 {
222   fixed_div(0, 15, 14),
223   fixed_div(1, 15, 14),
224   fixed_div(2, 15, 14),
225   fixed_div(3, 15, 14),
226   fixed_div(4, 15, 14),
227   fixed_div(5, 15, 14),
228   fixed_div(6, 15, 14),
229   fixed_div(7, 15, 14),
230   fixed_div(8, 15, 14),
231   fixed_div(9, 15, 14),
232   fixed_div(10, 15, 14),
233   fixed_div(11, 15, 14),
234   fixed_div(12, 15, 14),
235   fixed_div(13, 15, 14),
236   fixed_div(14, 15, 14),
237   fixed_div(15, 15, 14)
238 };
239 
240 u32 gbc_sound_buffer_index = 0;
241 u32 gbc_sound_last_cpu_ticks = 0;
242 u32 gbc_sound_partial_ticks = 0;
243 
244 u32 gbc_sound_master_volume_left;
245 u32 gbc_sound_master_volume_right;
246 u32 gbc_sound_master_volume;
247 
248 #define update_volume_channel_envelope(channel)                               \
249   volume_##channel = gbc_sound_envelope_volume_table[envelope_volume] *       \
250    gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] *        \
251    gbc_sound_master_volume_table[gbc_sound_master_volume]                     \
252 
253 #define update_volume_channel_noenvelope(channel)                             \
254   volume_##channel = gs->wave_volume *                                        \
255    gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] *        \
256    gbc_sound_master_volume_table[gbc_sound_master_volume]                     \
257 
258 #define update_volume(type)                                                   \
259   update_volume_channel_##type(left);                                         \
260   update_volume_channel_##type(right)                                         \
261 
262 #define update_tone_sweep()                                                   \
263   if(gs->sweep_status)                                                        \
264   {                                                                           \
265     u32 sweep_ticks = gs->sweep_ticks - 1;                                    \
266                                                                               \
267     if(sweep_ticks == 0)                                                      \
268     {                                                                         \
269       u32 rate = gs->rate;                                                    \
270                                                                               \
271       if(gs->sweep_direction)                                                 \
272         rate = rate - (rate >> gs->sweep_shift);                              \
273       else                                                                    \
274         rate = rate + (rate >> gs->sweep_shift);                              \
275                                                                               \
276       if(rate > 2048)                                                         \
277         rate = 2048;                                                          \
278                                                                               \
279       frequency_step = float_to_fp16_16(((131072.0f / (2048 - rate)) * 8.0f)  \
280        / sound_frequency);                                                    \
281                                                                               \
282       gs->frequency_step = frequency_step;                                    \
283       gs->rate = rate;                                                        \
284                                                                               \
285       sweep_ticks = gs->sweep_initial_ticks;                                  \
286     }                                                                         \
287     gs->sweep_ticks = sweep_ticks;                                            \
288   }                                                                           \
289 
290 #define update_tone_nosweep()                                                 \
291 
292 #define update_tone_envelope()                                                \
293   if(gs->envelope_status)                                                     \
294   {                                                                           \
295     u32 envelope_ticks = gs->envelope_ticks - 1;                              \
296     envelope_volume = gs->envelope_volume;                                    \
297                                                                               \
298     if(envelope_ticks == 0)                                                   \
299     {                                                                         \
300       if(gs->envelope_direction)                                              \
301       {                                                                       \
302         if(envelope_volume != 15)                                             \
303           envelope_volume = gs->envelope_volume + 1;                          \
304       }                                                                       \
305       else                                                                    \
306       {                                                                       \
307         if(envelope_volume != 0)                                              \
308           envelope_volume = gs->envelope_volume - 1;                          \
309       }                                                                       \
310                                                                               \
311       update_volume(envelope);                                                \
312                                                                               \
313       gs->envelope_volume = envelope_volume;                                  \
314       gs->envelope_ticks = gs->envelope_initial_ticks;                        \
315     }                                                                         \
316     else                                                                      \
317       gs->envelope_ticks = envelope_ticks;                                    \
318   }                                                                           \
319 
320 #define update_tone_noenvelope()                                              \
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 
update_gbc_sound(u32 cpu_ticks)425 void update_gbc_sound(u32 cpu_ticks)
426 {
427   fixed16_16 buffer_ticks = float_to_fp16_16((float)(cpu_ticks -
428    gbc_sound_last_cpu_ticks) * sound_frequency / GBC_BASE_RATE);
429   u32 i, i2;
430   gbc_sound_struct *gs = gbc_sound_channel;
431   fixed16_16 sample_index, frequency_step;
432   fixed16_16 tick_counter;
433   u32 buffer_index;
434   s32 volume_left, volume_right;
435   u32 envelope_volume;
436   s32 current_sample;
437   u32 sound_status = address16(io_registers, 0x84) & 0xFFF0;
438   s8 *sample_data;
439   s8 *wave_bank;
440   u8 *wave_ram = ((u8 *)io_registers) + 0x90;
441 
442   gbc_sound_partial_ticks += fp16_16_fractional_part(buffer_ticks);
443   buffer_ticks = fp16_16_to_u32(buffer_ticks);
444 
445   if(gbc_sound_partial_ticks > 0xFFFF)
446   {
447     buffer_ticks += 1;
448     gbc_sound_partial_ticks &= 0xFFFF;
449   }
450 
451   if(sound_on == 1)
452   {
453     gs = gbc_sound_channel + 0;
454     if(gs->active_flag)
455     {
456       sound_status |= 0x01;
457       sample_data = gs->sample_data;
458       envelope_volume = gs->envelope_volume;
459       gbc_sound_render_channel(samples, 8, envelope, sweep);
460     }
461 
462     gs = gbc_sound_channel + 1;
463     if(gs->active_flag)
464     {
465       sound_status |= 0x02;
466       sample_data = gs->sample_data;
467       envelope_volume = gs->envelope_volume;
468       gbc_sound_render_channel(samples, 8, envelope, nosweep);
469     }
470 
471     gs = gbc_sound_channel + 2;
472     if(gbc_sound_wave_update)
473     {
474        unsigned bank = (gs->wave_bank == 1) ? 1 : 0;
475 
476        wave_bank = wave_samples + (bank * 32);
477        for(i = 0, i2 = 0; i < 16; i++, i2 += 2)
478        {
479           current_sample = wave_ram[i];
480           wave_bank[i2] = (((current_sample >> 4) & 0x0F) - 8);
481           wave_bank[i2 + 1] = ((current_sample & 0x0F) - 8);
482        }
483 
484        gbc_sound_wave_update = 0;
485     }
486 
487     if((gs->active_flag) && (gs->master_enable))
488     {
489       sound_status |= 0x04;
490       sample_data = wave_samples;
491       if(gs->wave_type == 0)
492       {
493         if(gs->wave_bank == 1)
494           sample_data += 32;
495 
496         gbc_sound_render_channel(samples, 32, noenvelope, nosweep);
497       }
498       else
499       {
500         gbc_sound_render_channel(samples, 64, noenvelope, nosweep);
501       }
502     }
503 
504     gs = gbc_sound_channel + 3;
505     if(gs->active_flag)
506     {
507       sound_status |= 0x08;
508       envelope_volume = gs->envelope_volume;
509 
510       if(gs->noise_type == 1)
511       {
512         gbc_sound_render_channel(noise, half, envelope, nosweep);
513       }
514       else
515       {
516         gbc_sound_render_channel(noise, full, envelope, nosweep);
517       }
518     }
519   }
520 
521   address16(io_registers, 0x84) = sound_status;
522 
523   gbc_sound_last_cpu_ticks = cpu_ticks;
524   gbc_sound_buffer_index =
525    (gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE;
526 }
527 
528 // Special thanks to blarrg for the LSFR frequency used in Meridian, as posted
529 // on the forum at http://meridian.overclocked.org:
530 // http://meridian.overclocked.org/cgi-bin/wwwthreads/showpost.pl?Board=merid
531 // angeneraldiscussion&Number=2069&page=0&view=expanded&mode=threaded&sb=4
532 // Hope you don't mind me borrowing it ^_-
533 
init_noise_table(u32 * table,u32 period,u32 bit_length)534 static void init_noise_table(u32 *table, u32 period, u32 bit_length)
535 {
536   u32 shift_register = 0xFF;
537   u32 mask = ~(1 << bit_length);
538   s32 table_pos, bit_pos;
539   u32 current_entry;
540   u32 table_period = (period + 31) / 32;
541 
542   // Bits are stored in reverse order so they can be more easily moved to
543   // bit 31, for sign extended shift down.
544 
545   for(table_pos = 0; table_pos < table_period; table_pos++)
546   {
547     current_entry = 0;
548     for(bit_pos = 31; bit_pos >= 0; bit_pos--)
549     {
550       current_entry |= (shift_register & 0x01) << bit_pos;
551 
552       shift_register =
553        ((1 & (shift_register ^ (shift_register >> 1))) << bit_length) |
554        ((shift_register >> 1) & mask);
555     }
556 
557     table[table_pos] = current_entry;
558   }
559 }
560 
reset_sound(void)561 void reset_sound(void)
562 {
563   direct_sound_struct *ds = direct_sound_channel;
564   gbc_sound_struct *gs = gbc_sound_channel;
565   u32 i;
566 
567   sound_on = 0;
568   sound_buffer_base = 0;
569   sound_last_cpu_ticks = 0;
570   memset(sound_buffer, 0, sizeof(sound_buffer));
571 
572   for(i = 0; i < 2; i++, ds++)
573   {
574     ds->buffer_index = 0;
575     ds->status = DIRECT_SOUND_INACTIVE;
576     ds->fifo_top = 0;
577     ds->fifo_base = 0;
578     ds->fifo_fractional = 0;
579     ds->last_cpu_ticks = 0;
580     memset(ds->fifo, 0, 32);
581   }
582 
583   gbc_sound_buffer_index = 0;
584   gbc_sound_last_cpu_ticks = 0;
585   gbc_sound_partial_ticks = 0;
586 
587   gbc_sound_master_volume_left = 0;
588   gbc_sound_master_volume_right = 0;
589   gbc_sound_master_volume = 0;
590   memset(wave_samples, 0, 64);
591 
592   for(i = 0; i < 4; i++, gs++)
593   {
594     gs->status = GBC_SOUND_INACTIVE;
595     gs->sample_data = square_pattern_duty[2];
596     gs->active_flag = 0;
597   }
598 }
599 
init_sound(int need_reset)600 void init_sound(int need_reset)
601 {
602   gbc_sound_tick_step =
603    float_to_fp16_16(256.0f / sound_frequency);
604 
605   init_noise_table(noise_table15, 32767, 14);
606   init_noise_table(noise_table7, 127, 6);
607 
608   if (need_reset)
609     reset_sound();
610 }
611 
612 #define sound_savestate_builder(type)                         \
613 void sound_##type##_savestate(void)                           \
614 {                                                             \
615   state_mem_##type##_variable(sound_on);                      \
616   state_mem_##type##_variable(sound_buffer_base);             \
617   state_mem_##type##_variable(sound_last_cpu_ticks);          \
618   state_mem_##type##_variable(gbc_sound_buffer_index);        \
619   state_mem_##type##_variable(gbc_sound_last_cpu_ticks);      \
620   state_mem_##type##_variable(gbc_sound_partial_ticks);       \
621   state_mem_##type##_variable(gbc_sound_master_volume_left);  \
622   state_mem_##type##_variable(gbc_sound_master_volume_right); \
623   state_mem_##type##_variable(gbc_sound_master_volume);       \
624   state_mem_##type##_array(wave_samples);                     \
625   state_mem_##type##_array(direct_sound_channel);             \
626   state_mem_##type##_array(gbc_sound_channel);                \
627 }
628 
629 sound_savestate_builder(read)
630 sound_savestate_builder(write)
631 
632 
633 #include "libretro.h"
634 
635 static retro_audio_sample_batch_t audio_batch_cb;
retro_set_audio_sample(retro_audio_sample_t cb)636 void retro_set_audio_sample(retro_audio_sample_t cb) { }
retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)637 void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; }
638 
render_audio(void)639 void render_audio(void)
640 {
641    static s16 stream_base[512];
642    s16 *source;
643    u32 i;
644 
645    while (((gbc_sound_buffer_index - sound_buffer_base) & BUFFER_SIZE_MASK) > 512)
646    {
647       source = (s16 *)(sound_buffer + sound_buffer_base);
648       for(i = 0; i < 512; i++)
649       {
650          s32 current_sample = source[i];
651          if(current_sample > 2047)
652             current_sample = 2047;
653          if(current_sample < -2048)
654             current_sample = -2048;
655          stream_base[i] = current_sample << 4;
656          source[i] = 0;
657       }
658       audio_batch_cb(stream_base, 256);
659       sound_buffer_base += 512;
660       sound_buffer_base &= BUFFER_SIZE_MASK;
661    }
662 }
663