diff options
author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-31 19:19:49 +0000 |
---|---|---|
committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-31 19:19:49 +0000 |
commit | 13cbade08a07296d92e7a7d3e20475de0032cba1 (patch) | |
tree | 731a1a4a99d86632a719ae49e3b3d2a12e764a3a /apps/codecs/libgme/sgc_emu.c | |
parent | d089e104034fdf5562bea125d2cacf4ee486782a (diff) | |
download | rockbox-13cbade08a07296d92e7a7d3e20475de0032cba1.tar.gz rockbox-13cbade08a07296d92e7a7d3e20475de0032cba1.zip |
Update libgme to Blargg's Game_Music_Emu 0.6-pre.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30397 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libgme/sgc_emu.c')
-rw-r--r-- | apps/codecs/libgme/sgc_emu.c | 319 |
1 files changed, 63 insertions, 256 deletions
diff --git a/apps/codecs/libgme/sgc_emu.c b/apps/codecs/libgme/sgc_emu.c index 3c3586611c..a2e6b8df29 100644 --- a/apps/codecs/libgme/sgc_emu.c +++ b/apps/codecs/libgme/sgc_emu.c | |||
@@ -10,34 +10,19 @@ module is distributed in the hope that it will be useful, but WITHOUT ANY | |||
10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
11 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | 11 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
12 | details. You should have received a copy of the GNU Lesser General Public | 12 | details. You should have received a copy of the GNU Lesser General Public |
13 | License along with this module; if not, write to the Free Software Foundation, | 13 | License aint with this module; if not, write to the Free Software Foundation, |
14 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ | 14 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | 15 | ||
16 | #include "blargg_source.h" | 16 | #include "blargg_source.h" |
17 | 17 | ||
18 | int const osc_count = sms_osc_count + fm_apu_osc_count; | 18 | int const osc_count = sms_osc_count + fm_apu_osc_count; |
19 | 19 | ||
20 | int const stereo = 2; // number of channels for stereo | ||
21 | int const silence_max = 6; // seconds | ||
22 | int const silence_threshold = 0x10; | ||
23 | long const fade_block_size = 512; | ||
24 | int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift) | ||
25 | |||
26 | const char gme_wrong_file_type [] = "Wrong file type for this emulator"; | 20 | const char gme_wrong_file_type [] = "Wrong file type for this emulator"; |
27 | 21 | ||
28 | static void clear_track_vars( struct Sgc_Emu* this ) | 22 | static void clear_track_vars( struct Sgc_Emu* this ) |
29 | { | 23 | { |
30 | this->current_track = -1; | 24 | this->current_track = -1; |
31 | this->out_time = 0; | 25 | track_stop( &this->track_filter ); |
32 | this->emu_time = 0; | ||
33 | this->emu_track_ended_ = true; | ||
34 | this->track_ended = true; | ||
35 | this->fade_start = INT_MAX / 2 + 1; | ||
36 | this->fade_step = 1; | ||
37 | this->silence_time = 0; | ||
38 | this->silence_count = 0; | ||
39 | this->buf_remain = 0; | ||
40 | /* warning(); // clear warning */ | ||
41 | } | 26 | } |
42 | 27 | ||
43 | void Sgc_init( struct Sgc_Emu* this ) | 28 | void Sgc_init( struct Sgc_Emu* this ) |
@@ -48,12 +33,12 @@ void Sgc_init( struct Sgc_Emu* this ) | |||
48 | this->mute_mask_ = 0; | 33 | this->mute_mask_ = 0; |
49 | this->tempo = (int)FP_ONE_TEMPO; | 34 | this->tempo = (int)FP_ONE_TEMPO; |
50 | this->gain = (int)FP_ONE_GAIN; | 35 | this->gain = (int)FP_ONE_GAIN; |
51 | this->voice_count = 0; | ||
52 | 36 | ||
53 | // defaults | 37 | // defaults |
54 | this->max_initial_silence = 2; | 38 | this->tfilter = *track_get_setup( &this->track_filter ); |
55 | this->silence_lookahead = 6; | 39 | this->tfilter.max_initial = 2; |
56 | this->ignore_silence = false; | 40 | this->tfilter.lookahead = 6; |
41 | this->track_filter.silence_ignored_ = false; | ||
57 | 42 | ||
58 | Sms_apu_init( &this->apu ); | 43 | Sms_apu_init( &this->apu ); |
59 | Fm_apu_create( &this->fm_apu ); | 44 | Fm_apu_create( &this->fm_apu ); |
@@ -62,8 +47,10 @@ void Sgc_init( struct Sgc_Emu* this ) | |||
62 | Z80_init( &this->cpu ); | 47 | Z80_init( &this->cpu ); |
63 | 48 | ||
64 | Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); | 49 | Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); |
65 | 50 | ||
66 | // Unload | 51 | // Unload |
52 | this->voice_count = 0; | ||
53 | this->voice_types = 0; | ||
67 | clear_track_vars( this ); | 54 | clear_track_vars( this ); |
68 | } | 55 | } |
69 | 56 | ||
@@ -95,6 +82,10 @@ blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size ) | |||
95 | this->m3u.size = 0; | 82 | this->m3u.size = 0; |
96 | this->track_count = this->header.song_count; | 83 | this->track_count = this->header.song_count; |
97 | this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count; | 84 | this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count; |
85 | static int const types [osc_count + 1] = { | ||
86 | wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2 | ||
87 | }; | ||
88 | this->voice_types = types; | ||
98 | 89 | ||
99 | Sms_apu_volume( &this->apu, this->gain ); | 90 | Sms_apu_volume( &this->apu, this->gain ); |
100 | Fm_apu_volume( &this->fm_apu, this->gain ); | 91 | Fm_apu_volume( &this->fm_apu, this->gain ); |
@@ -102,10 +93,10 @@ blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size ) | |||
102 | // Setup buffer | 93 | // Setup buffer |
103 | this->clock_rate_ = clock_rate( this ); | 94 | this->clock_rate_ = clock_rate( this ); |
104 | Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) ); | 95 | Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) ); |
96 | RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) ); | ||
105 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); | 97 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); |
106 | Sound_set_tempo( this, this->tempo ); | ||
107 | 98 | ||
108 | // Remute voices | 99 | Sound_set_tempo( this, this->tempo ); |
109 | Sound_mute_voices( this, this->mute_mask_ ); | 100 | Sound_mute_voices( this, this->mute_mask_ ); |
110 | return 0; | 101 | return 0; |
111 | } | 102 | } |
@@ -249,7 +240,7 @@ void cpu_write( struct Sgc_Emu* this, addr_t addr, int data ) | |||
249 | } | 240 | } |
250 | } | 241 | } |
251 | 242 | ||
252 | blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, long rate ) | 243 | blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate ) |
253 | { | 244 | { |
254 | require( !this->sample_rate ); // sample rate can't be changed once set | 245 | require( !this->sample_rate ); // sample rate can't be changed once set |
255 | Buffer_init( &this->stereo_buf ); | 246 | Buffer_init( &this->stereo_buf ); |
@@ -259,6 +250,8 @@ blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, long rate ) | |||
259 | Buffer_bass_freq( &this->stereo_buf, 80 ); | 250 | Buffer_bass_freq( &this->stereo_buf, 80 ); |
260 | 251 | ||
261 | this->sample_rate = rate; | 252 | this->sample_rate = rate; |
253 | RETURN_ERR( track_init( &this->track_filter, this ) ); | ||
254 | this->tfilter.max_silence = 6 * stereo * this->sample_rate; | ||
262 | return 0; | 255 | return 0; |
263 | } | 256 | } |
264 | 257 | ||
@@ -286,7 +279,7 @@ void Sound_mute_voices( struct Sgc_Emu* this, int mask ) | |||
286 | } | 279 | } |
287 | else | 280 | else |
288 | { | 281 | { |
289 | struct channel_t ch = Buffer_channel( &this->stereo_buf ); | 282 | struct channel_t ch = Buffer_channel( &this->stereo_buf, i ); |
290 | assert( (ch.center && ch.left && ch.right) || | 283 | assert( (ch.center && ch.left && ch.right) || |
291 | (!ch.center && !ch.left && !ch.right) ); // all or nothing | 284 | (!ch.center && !ch.left && !ch.right) ); // all or nothing |
292 | Sound_set_voice( this, i, ch.center, ch.left, ch.right ); | 285 | Sound_set_voice( this, i, ch.center, ch.left, ch.right ); |
@@ -306,7 +299,6 @@ void Sound_set_tempo( struct Sgc_Emu* this, int t ) | |||
306 | this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t); | 299 | this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t); |
307 | } | 300 | } |
308 | 301 | ||
309 | void fill_buf( struct Sgc_Emu* this ); | ||
310 | blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track ) | 302 | blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track ) |
311 | { | 303 | { |
312 | clear_track_vars( this ); | 304 | clear_track_vars( this ); |
@@ -383,275 +375,90 @@ blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track ) | |||
383 | 375 | ||
384 | Buffer_clear( &this->stereo_buf ); | 376 | Buffer_clear( &this->stereo_buf ); |
385 | 377 | ||
386 | this->emu_track_ended_ = false; | 378 | // convert filter times to samples |
387 | this->track_ended = false; | 379 | struct setup_t s = this->tfilter; |
388 | 380 | s.max_initial *= this->sample_rate * stereo; | |
389 | if ( !this->ignore_silence ) | 381 | #ifdef GME_DISABLE_SILENCE_LOOKAHEAD |
390 | { | 382 | s.lookahead = 1; |
391 | // play until non-silence or end of track | 383 | #endif |
392 | long end; | 384 | track_setup( &this->track_filter, &s ); |
393 | for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; ) | 385 | |
394 | { | 386 | return track_start( &this->track_filter ); |
395 | fill_buf( this ); | ||
396 | if ( this->buf_remain | (int) this->emu_track_ended_ ) | ||
397 | break; | ||
398 | } | ||
399 | |||
400 | this->emu_time = this->buf_remain; | ||
401 | this->out_time = 0; | ||
402 | this->silence_time = 0; | ||
403 | this->silence_count = 0; | ||
404 | } | ||
405 | /* return track_ended() ? warning() : 0; */ | ||
406 | return 0; | ||
407 | } | 387 | } |
408 | 388 | ||
409 | // Tell/Seek | 389 | // Tell/Seek |
410 | 390 | ||
411 | static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) | 391 | static int msec_to_samples( int msec, int sample_rate ) |
412 | { | 392 | { |
413 | blargg_long sec = msec / 1000; | 393 | int sec = msec / 1000; |
414 | msec -= sec * 1000; | 394 | msec -= sec * 1000; |
415 | return (sec * sample_rate + msec * sample_rate / 1000) * stereo; | 395 | return (sec * sample_rate + msec * sample_rate / 1000) * stereo; |
416 | } | 396 | } |
417 | 397 | ||
418 | long Track_tell( struct Sgc_Emu* this ) | 398 | int Track_tell( struct Sgc_Emu* this ) |
419 | { | 399 | { |
420 | blargg_long rate = this->sample_rate * stereo; | 400 | int rate = this->sample_rate * stereo; |
421 | blargg_long sec = this->out_time / rate; | 401 | int sec = track_sample_count( &this->track_filter ) / rate; |
422 | return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; | 402 | return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate; |
423 | } | 403 | } |
424 | 404 | ||
425 | blargg_err_t Track_seek( struct Sgc_Emu* this, long msec ) | 405 | blargg_err_t Track_seek( struct Sgc_Emu* this, int msec ) |
426 | { | 406 | { |
427 | blargg_long time = msec_to_samples( msec, this->sample_rate ); | 407 | int time = msec_to_samples( msec, this->sample_rate ); |
428 | if ( time < this->out_time ) | 408 | if ( time < track_sample_count( &this->track_filter ) ) |
429 | RETURN_ERR( Sgc_start_track( this, this->current_track ) ); | 409 | RETURN_ERR( Sgc_start_track( this, this->current_track ) ); |
430 | return Track_skip( this, time - this->out_time ); | 410 | return Track_skip( this, time - track_sample_count( &this->track_filter ) ); |
431 | } | 411 | } |
432 | 412 | ||
433 | blargg_err_t skip_( struct Sgc_Emu* this, long count ); | 413 | blargg_err_t Track_skip( struct Sgc_Emu* this, int count ) |
434 | blargg_err_t Track_skip( struct Sgc_Emu* this, long count ) | ||
435 | { | 414 | { |
436 | require( this->current_track >= 0 ); // start_track() must have been called already | 415 | require( this->current_track >= 0 ); // start_track() must have been called already |
437 | this->out_time += count; | 416 | return track_skip( &this->track_filter, count ); |
438 | |||
439 | // remove from silence and buf first | ||
440 | { | ||
441 | long n = min( count, this->silence_count ); | ||
442 | this->silence_count -= n; | ||
443 | count -= n; | ||
444 | |||
445 | n = min( count, this->buf_remain ); | ||
446 | this->buf_remain -= n; | ||
447 | count -= n; | ||
448 | } | ||
449 | |||
450 | if ( count && !this->emu_track_ended_ ) | ||
451 | { | ||
452 | this->emu_time += count; | ||
453 | |||
454 | // End track if error | ||
455 | if ( skip_( this, count ) ) { | ||
456 | this->emu_track_ended_ = true; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended | ||
461 | this->track_ended |= this->emu_track_ended_; | ||
462 | |||
463 | return 0; | ||
464 | } | 417 | } |
465 | 418 | ||
466 | blargg_err_t play_( struct Sgc_Emu* this, long count, sample_t* out ); | 419 | blargg_err_t skip_( void* emu, int count ) |
467 | blargg_err_t skip_( struct Sgc_Emu* this, long count ) | ||
468 | { | 420 | { |
421 | struct Sgc_Emu* this = (struct Sgc_Emu*) emu; | ||
422 | |||
469 | // for long skip, mute sound | 423 | // for long skip, mute sound |
470 | const long threshold = 30000; | 424 | const int threshold = 32768; |
471 | if ( count > threshold ) | 425 | if ( count > threshold ) |
472 | { | 426 | { |
473 | int saved_mute = this->mute_mask_; | 427 | int saved_mute = this->mute_mask_; |
474 | Sound_mute_voices( this, ~0 ); | 428 | Sound_mute_voices( this, ~0 ); |
475 | |||
476 | while ( count > threshold / 2 && !this->emu_track_ended_ ) | ||
477 | { | ||
478 | RETURN_ERR( play_( this, buf_size, this->buf ) ); | ||
479 | count -= buf_size; | ||
480 | } | ||
481 | |||
482 | Sound_mute_voices( this, saved_mute ); | ||
483 | } | ||
484 | |||
485 | while ( count && !this->emu_track_ended_ ) | ||
486 | { | ||
487 | long n = buf_size; | ||
488 | if ( n > count ) | ||
489 | n = count; | ||
490 | count -= n; | ||
491 | RETURN_ERR( play_( this, n, this->buf ) ); | ||
492 | } | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | // Fading | ||
497 | |||
498 | void Track_set_fade( struct Sgc_Emu* this, long start_msec, long length_msec ) | ||
499 | { | ||
500 | this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo); | ||
501 | this->fade_start = msec_to_samples( start_msec, this->sample_rate ); | ||
502 | } | ||
503 | |||
504 | // unit / pow( 2.0, (double) x / step ) | ||
505 | static int int_log( blargg_long x, int step, int unit ) | ||
506 | { | ||
507 | int shift = x / step; | ||
508 | int fraction = (x - shift * step) * unit / step; | ||
509 | return ((unit - fraction) + (fraction >> 1)) >> shift; | ||
510 | } | ||
511 | |||
512 | static void handle_fade( struct Sgc_Emu* this, long out_count, sample_t* out ) | ||
513 | { | ||
514 | int i; | ||
515 | for ( i = 0; i < out_count; i += fade_block_size ) | ||
516 | { | ||
517 | int const shift = 14; | ||
518 | int const unit = 1 << shift; | ||
519 | int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size, | ||
520 | this->fade_step, unit ); | ||
521 | if ( gain < (unit >> fade_shift) ) | ||
522 | this->track_ended = this->emu_track_ended_ = true; | ||
523 | |||
524 | sample_t* io = &out [i]; | ||
525 | int count; | ||
526 | for ( count = min( fade_block_size, out_count - i ); count; --count ) | ||
527 | { | ||
528 | *io = (sample_t) ((*io * gain) >> shift); | ||
529 | ++io; | ||
530 | } | ||
531 | } | ||
532 | } | ||
533 | 429 | ||
534 | // Silence detection | 430 | int n = count - threshold/2; |
431 | n &= ~(2048-1); // round to multiple of 2048 | ||
432 | count -= n; | ||
433 | RETURN_ERR( skippy_( &this->track_filter, n ) ); | ||
535 | 434 | ||
536 | static void emu_play( struct Sgc_Emu* this, long count, sample_t* out ) | 435 | Sound_mute_voices( this, saved_mute ); |
537 | { | ||
538 | check( this->current_track_ >= 0 ); | ||
539 | this->emu_time += count; | ||
540 | if ( this->current_track >= 0 && !this->emu_track_ended_ ) { | ||
541 | // End track if error | ||
542 | if ( play_( this, count, out ) ) | ||
543 | this->emu_track_ended_ = true; | ||
544 | } | 436 | } |
545 | else | ||
546 | memset( out, 0, count * sizeof *out ); | ||
547 | } | ||
548 | 437 | ||
549 | // number of consecutive silent samples at end | 438 | return skippy_( &this->track_filter, count ); |
550 | static long count_silence( sample_t* begin, long size ) | ||
551 | { | ||
552 | sample_t first = *begin; | ||
553 | *begin = silence_threshold; // sentinel | ||
554 | sample_t* p = begin + size; | ||
555 | while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { } | ||
556 | *begin = first; | ||
557 | return size - (p - begin); | ||
558 | } | 439 | } |
559 | 440 | ||
560 | // fill internal buffer and check it for silence | 441 | void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec ) |
561 | void fill_buf( struct Sgc_Emu* this ) | ||
562 | { | 442 | { |
563 | assert( !this->buf_remain ); | 443 | track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ), |
564 | if ( !this->emu_track_ended_ ) | 444 | length_msec * this->sample_rate / (1000 / stereo) ); |
565 | { | ||
566 | emu_play( this, buf_size, this->buf ); | ||
567 | long silence = count_silence( this->buf, buf_size ); | ||
568 | if ( silence < buf_size ) | ||
569 | { | ||
570 | this->silence_time = this->emu_time - silence; | ||
571 | this->buf_remain = buf_size; | ||
572 | return; | ||
573 | } | ||
574 | } | ||
575 | this->silence_count += buf_size; | ||
576 | } | 445 | } |
577 | 446 | ||
578 | blargg_err_t Sgc_play( struct Sgc_Emu* this, long out_count, sample_t* out ) | 447 | blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out ) |
579 | { | 448 | { |
580 | if ( this->track_ended ) | 449 | require( this->current_track >= 0 ); |
581 | { | 450 | require( out_count % stereo == 0 ); |
582 | memset( out, 0, out_count * sizeof *out ); | 451 | return track_play( &this->track_filter, out_count, out ); |
583 | } | ||
584 | else | ||
585 | { | ||
586 | require( this->current_track >= 0 ); | ||
587 | require( out_count % stereo == 0 ); | ||
588 | |||
589 | assert( this->emu_time >= this->out_time ); | ||
590 | |||
591 | // prints nifty graph of how far ahead we are when searching for silence | ||
592 | //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" ); | ||
593 | |||
594 | long pos = 0; | ||
595 | if ( this->silence_count ) | ||
596 | { | ||
597 | // during a run of silence, run emulator at >=2x speed so it gets ahead | ||
598 | long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time; | ||
599 | while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) ) | ||
600 | fill_buf( this ); | ||
601 | |||
602 | // fill with silence | ||
603 | pos = min( this->silence_count, out_count ); | ||
604 | memset( out, 0, pos * sizeof *out ); | ||
605 | this->silence_count -= pos; | ||
606 | |||
607 | if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate ) | ||
608 | { | ||
609 | this->track_ended = this->emu_track_ended_ = true; | ||
610 | this->silence_count = 0; | ||
611 | this->buf_remain = 0; | ||
612 | } | ||
613 | } | ||
614 | |||
615 | if ( this->buf_remain ) | ||
616 | { | ||
617 | // empty silence buf | ||
618 | long n = min( this->buf_remain, out_count - pos ); | ||
619 | memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out ); | ||
620 | this->buf_remain -= n; | ||
621 | pos += n; | ||
622 | } | ||
623 | |||
624 | // generate remaining samples normally | ||
625 | long remain = out_count - pos; | ||
626 | if ( remain ) | ||
627 | { | ||
628 | emu_play( this, remain, out + pos ); | ||
629 | this->track_ended |= this->emu_track_ended_; | ||
630 | |||
631 | if ( !this->ignore_silence || this->out_time > this->fade_start ) | ||
632 | { | ||
633 | // check end for a new run of silence | ||
634 | long silence = count_silence( out + pos, remain ); | ||
635 | if ( silence < remain ) | ||
636 | this->silence_time = this->emu_time - silence; | ||
637 | |||
638 | if ( this->emu_time - this->silence_time >= buf_size ) | ||
639 | fill_buf( this ); // cause silence detection on next play() | ||
640 | } | ||
641 | } | ||
642 | |||
643 | if ( this->out_time > this->fade_start ) | ||
644 | handle_fade( this, out_count, out ); | ||
645 | } | ||
646 | this->out_time += out_count; | ||
647 | return 0; | ||
648 | } | 452 | } |
649 | 453 | ||
650 | blargg_err_t play_( struct Sgc_Emu* this, long count, sample_t* out ) | 454 | blargg_err_t play_( void* emu, int count, sample_t out [] ) |
651 | { | 455 | { |
652 | long remain = count; | 456 | struct Sgc_Emu* this = (struct Sgc_Emu*) emu; |
457 | |||
458 | int remain = count; | ||
653 | while ( remain ) | 459 | while ( remain ) |
654 | { | 460 | { |
461 | Buffer_disable_immediate_removal( &this->stereo_buf ); | ||
655 | remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); | 462 | remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); |
656 | if ( remain ) | 463 | if ( remain ) |
657 | { | 464 | { |