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/ay_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/ay_emu.c')
-rw-r--r-- | apps/codecs/libgme/ay_emu.c | 356 |
1 files changed, 86 insertions, 270 deletions
diff --git a/apps/codecs/libgme/ay_emu.c b/apps/codecs/libgme/ay_emu.c index e961797dd3..42e739f2df 100644 --- a/apps/codecs/libgme/ay_emu.c +++ b/apps/codecs/libgme/ay_emu.c | |||
@@ -17,12 +17,6 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ | |||
17 | 17 | ||
18 | #include "blargg_source.h" | 18 | #include "blargg_source.h" |
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* const gme_wrong_file_type = "Wrong file type for this emulator"; | 20 | const char* const gme_wrong_file_type = "Wrong file type for this emulator"; |
27 | 21 | ||
28 | // TODO: probably don't need detailed errors as to why file is corrupt | 22 | // TODO: probably don't need detailed errors as to why file is corrupt |
@@ -38,16 +32,7 @@ int const cpc_clock = 2000000; | |||
38 | static void clear_track_vars( struct Ay_Emu *this ) | 32 | static void clear_track_vars( struct Ay_Emu *this ) |
39 | { | 33 | { |
40 | this->current_track = -1; | 34 | this->current_track = -1; |
41 | this->out_time = 0; | 35 | track_stop( &this->track_filter ); |
42 | this->emu_time = 0; | ||
43 | this->emu_track_ended_ = true; | ||
44 | this->track_ended = true; | ||
45 | this->fade_start = INT_MAX / 2 + 1; | ||
46 | this->fade_step = 1; | ||
47 | this->silence_time = 0; | ||
48 | this->silence_count = 0; | ||
49 | this->buf_remain = 0; | ||
50 | /* warning(); // clear warning */ | ||
51 | } | 36 | } |
52 | 37 | ||
53 | void Ay_init( struct Ay_Emu *this ) | 38 | void Ay_init( struct Ay_Emu *this ) |
@@ -59,18 +44,21 @@ void Ay_init( struct Ay_Emu *this ) | |||
59 | this->track_count = 0; | 44 | this->track_count = 0; |
60 | 45 | ||
61 | // defaults | 46 | // defaults |
62 | this->max_initial_silence = 2; | 47 | this->tfilter = *track_get_setup( &this->track_filter ); |
63 | this->ignore_silence = false; | 48 | this->tfilter.max_initial = 2; |
49 | this->tfilter.lookahead = 6; | ||
50 | this->track_filter.silence_ignored_ = false; | ||
64 | 51 | ||
65 | this->voice_count = 0; | ||
66 | clear_track_vars( this ); | ||
67 | this->beeper_output = NULL; | 52 | this->beeper_output = NULL; |
68 | disable_beeper( this ); | 53 | disable_beeper( this ); |
69 | 54 | ||
70 | Ay_apu_init( &this->apu ); | 55 | Ay_apu_init( &this->apu ); |
71 | Z80_init( &this->cpu ); | 56 | Z80_init( &this->cpu ); |
72 | 57 | ||
73 | this->silence_lookahead = 6 ; | 58 | // clears fields |
59 | this->voice_count = 0; | ||
60 | this->voice_types = 0; | ||
61 | clear_track_vars( this ); | ||
74 | } | 62 | } |
75 | 63 | ||
76 | // Track info | 64 | // Track info |
@@ -107,35 +95,22 @@ static blargg_err_t parse_header( byte const in [], int size, struct file_t* out | |||
107 | return 0; | 95 | return 0; |
108 | } | 96 | } |
109 | 97 | ||
110 | long Track_get_length( struct Ay_Emu* this, int n ) | ||
111 | { | ||
112 | long length = 0; | ||
113 | |||
114 | byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 ); | ||
115 | if ( track_info ) | ||
116 | length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec | ||
117 | |||
118 | if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { | ||
119 | struct entry_t* entry = &this->m3u.entries [n]; | ||
120 | length = entry->length; | ||
121 | } | ||
122 | |||
123 | if ( length <= 0 ) | ||
124 | length = 120 * 1000; /* 2 minutes */ | ||
125 | |||
126 | return length; | ||
127 | } | ||
128 | |||
129 | // Setup | 98 | // Setup |
130 | 99 | ||
131 | static void change_clock_rate( struct Ay_Emu *this, long rate ) | 100 | static void change_clock_rate( struct Ay_Emu *this, int rate ) |
132 | { | 101 | { |
133 | this->clock_rate_ = rate; | 102 | this->clock_rate_ = rate; |
134 | Buffer_clock_rate( &this->stereo_buf, rate ); | 103 | Buffer_clock_rate( &this->stereo_buf, rate ); |
135 | } | 104 | } |
136 | 105 | ||
137 | blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], int size ) | 106 | blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], long size ) |
138 | { | 107 | { |
108 | // Unload | ||
109 | this->voice_count = 0; | ||
110 | this->track_count = 0; | ||
111 | this->m3u.size = 0; | ||
112 | clear_track_vars( this ); | ||
113 | |||
139 | assert( offsetof (struct header_t,track_info [2]) == header_size ); | 114 | assert( offsetof (struct header_t,track_info [2]) == header_size ); |
140 | 115 | ||
141 | RETURN_ERR( parse_header( in, size, &this->file ) ); | 116 | RETURN_ERR( parse_header( in, size, &this->file ) ); |
@@ -144,19 +119,22 @@ blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], int size ) | |||
144 | warning( "Unknown file version" ); */ | 119 | warning( "Unknown file version" ); */ |
145 | 120 | ||
146 | this->voice_count = ay_osc_count + 1; // +1 for beeper | 121 | this->voice_count = ay_osc_count + 1; // +1 for beeper |
122 | static int const types [ay_osc_count + 1] = { | ||
123 | wave_type+0, wave_type+1, wave_type+2, mixed_type+1 | ||
124 | }; | ||
125 | this->voice_types = types; | ||
126 | |||
147 | Ay_apu_volume( &this->apu, this->gain); | 127 | Ay_apu_volume( &this->apu, this->gain); |
148 | 128 | ||
149 | // Setup buffer | 129 | // Setup buffer |
150 | change_clock_rate( this, spectrum_clock ); | 130 | change_clock_rate( this, spectrum_clock ); |
131 | RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) ); | ||
151 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); | 132 | this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); |
152 | 133 | ||
153 | Sound_set_tempo( this, this->tempo ); | 134 | Sound_set_tempo( this, this->tempo ); |
154 | |||
155 | // Remute voices | ||
156 | Sound_mute_voices( this, this->mute_mask_ ); | 135 | Sound_mute_voices( this, this->mute_mask_ ); |
157 | 136 | ||
158 | this->track_count = this->file.header->max_track + 1; | 137 | this->track_count = this->file.header->max_track + 1; |
159 | this->m3u.size = 0; | ||
160 | return 0; | 138 | return 0; |
161 | } | 139 | } |
162 | 140 | ||
@@ -298,7 +276,7 @@ enable_cpc: | |||
298 | } | 276 | } |
299 | } | 277 | } |
300 | 278 | ||
301 | blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, long rate ) | 279 | blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, int rate ) |
302 | { | 280 | { |
303 | require( !this->sample_rate ); // sample rate can't be changed once set | 281 | require( !this->sample_rate ); // sample rate can't be changed once set |
304 | Buffer_init( &this->stereo_buf ); | 282 | Buffer_init( &this->stereo_buf ); |
@@ -308,6 +286,8 @@ blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, long rate ) | |||
308 | Buffer_bass_freq( &this->stereo_buf, 160 ); | 286 | Buffer_bass_freq( &this->stereo_buf, 160 ); |
309 | 287 | ||
310 | this->sample_rate = rate; | 288 | this->sample_rate = rate; |
289 | RETURN_ERR( track_init( &this->track_filter, this ) ); | ||
290 | this->tfilter.max_silence = 6 * stereo * this->sample_rate; | ||
311 | return 0; | 291 | return 0; |
312 | } | 292 | } |
313 | 293 | ||
@@ -335,7 +315,7 @@ void Sound_mute_voices( struct Ay_Emu *this, int mask ) | |||
335 | } | 315 | } |
336 | else | 316 | else |
337 | { | 317 | { |
338 | struct channel_t ch = Buffer_channel( &this->stereo_buf ); | 318 | struct channel_t ch = Buffer_channel( &this->stereo_buf, i ); |
339 | assert( (ch.center && ch.left && ch.right) || | 319 | assert( (ch.center && ch.left && ch.right) || |
340 | (!ch.center && !ch.left && !ch.right) ); // all or nothing | 320 | (!ch.center && !ch.left && !ch.right) ); // all or nothing |
341 | set_voice( this, i, ch.center ); | 321 | set_voice( this, i, ch.center ); |
@@ -359,7 +339,6 @@ void Sound_set_tempo( struct Ay_Emu *this, int t ) | |||
359 | this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t); | 339 | this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t); |
360 | } | 340 | } |
361 | 341 | ||
362 | void fill_buf( struct Ay_Emu *this );; | ||
363 | blargg_err_t Ay_start_track( struct Ay_Emu *this, int track ) | 342 | blargg_err_t Ay_start_track( struct Ay_Emu *this, int track ) |
364 | { | 343 | { |
365 | clear_track_vars( this ); | 344 | clear_track_vars( this ); |
@@ -496,272 +475,109 @@ blargg_err_t Ay_start_track( struct Ay_Emu *this, int track ) | |||
496 | Ay_apu_write_addr( &this->apu, 7 ); | 475 | Ay_apu_write_addr( &this->apu, 7 ); |
497 | Ay_apu_write_data( &this->apu, 0, 0x38 ); | 476 | Ay_apu_write_data( &this->apu, 0, 0x38 ); |
498 | 477 | ||
499 | this->emu_track_ended_ = false; | 478 | // convert filter times to samples |
500 | this->track_ended = false; | 479 | struct setup_t s = this->tfilter; |
480 | s.max_initial *= this->sample_rate * stereo; | ||
481 | #ifdef GME_DISABLE_SILENCE_LOOKAHEAD | ||
482 | s.lookahead = 1; | ||
483 | #endif | ||
484 | track_setup( &this->track_filter, &s ); | ||
501 | 485 | ||
502 | if ( !this->ignore_silence ) | 486 | return track_start( &this->track_filter ); |
503 | { | ||
504 | // play until non-silence or end of track | ||
505 | long end; | ||
506 | for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; ) | ||
507 | { | ||
508 | fill_buf( this ); | ||
509 | if ( this->buf_remain | (int) this->emu_track_ended_ ) | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | this->emu_time = this->buf_remain; | ||
514 | this->out_time = 0; | ||
515 | this->silence_time = 0; | ||
516 | this->silence_count = 0; | ||
517 | } | ||
518 | /* return track_ended() ? warning() : 0; */ | ||
519 | return 0; | ||
520 | } | 487 | } |
521 | 488 | ||
522 | // Tell/Seek | 489 | // Tell/Seek |
523 | 490 | ||
524 | static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) | 491 | static int msec_to_samples( int msec, int sample_rate ) |
525 | { | 492 | { |
526 | blargg_long sec = msec / 1000; | 493 | int sec = msec / 1000; |
527 | msec -= sec * 1000; | 494 | msec -= sec * 1000; |
528 | return (sec * sample_rate + msec * sample_rate / 1000) * stereo; | 495 | return (sec * sample_rate + msec * sample_rate / 1000) * stereo; |
529 | } | 496 | } |
530 | 497 | ||
531 | long Track_tell( struct Ay_Emu *this ) | 498 | int Track_tell( struct Ay_Emu *this ) |
532 | { | 499 | { |
533 | blargg_long rate = this->sample_rate * stereo; | 500 | int rate = this->sample_rate * stereo; |
534 | blargg_long sec = this->out_time / rate; | 501 | int sec = track_sample_count( &this->track_filter ) / rate; |
535 | return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; | 502 | return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate; |
536 | } | 503 | } |
537 | 504 | ||
538 | blargg_err_t Track_seek( struct Ay_Emu *this, long msec ) | 505 | blargg_err_t Track_seek( struct Ay_Emu *this, int msec ) |
539 | { | 506 | { |
540 | blargg_long time = msec_to_samples( msec, this->sample_rate ); | 507 | int time = msec_to_samples( msec, this->sample_rate ); |
541 | if ( time < this->out_time ) | 508 | if ( time < track_sample_count( &this->track_filter ) ) |
542 | RETURN_ERR( Ay_start_track( this, this->current_track ) ); | 509 | RETURN_ERR( Ay_start_track( this, this->current_track ) ); |
543 | return Track_skip( this, time - this->out_time ); | 510 | return Track_skip( this, time - track_sample_count( &this->track_filter ) ); |
544 | } | 511 | } |
545 | 512 | ||
546 | blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ); | 513 | blargg_err_t skip_( void *emu, int count ) |
547 | static blargg_err_t skip_( struct Ay_Emu *this, long count ) | ||
548 | { | 514 | { |
515 | struct Ay_Emu* this = (struct Ay_Emu*) emu; | ||
516 | |||
549 | // for long skip, mute sound | 517 | // for long skip, mute sound |
550 | const long threshold = 30000; | 518 | const int threshold = 32768; |
551 | if ( count > threshold ) | 519 | if ( count > threshold ) |
552 | { | 520 | { |
553 | int saved_mute = this->mute_mask_; | 521 | int saved_mute = this->mute_mask_; |
554 | Sound_mute_voices( this, ~0 ); | 522 | Sound_mute_voices( this, ~0 ); |
555 | |||
556 | while ( count > threshold / 2 && !this->emu_track_ended_ ) | ||
557 | { | ||
558 | RETURN_ERR( play_( this, buf_size, this->buf ) ); | ||
559 | count -= buf_size; | ||
560 | } | ||
561 | |||
562 | Sound_mute_voices( this, saved_mute ); | ||
563 | } | ||
564 | |||
565 | while ( count && !this->emu_track_ended_ ) | ||
566 | { | ||
567 | long n = buf_size; | ||
568 | if ( n > count ) | ||
569 | n = count; | ||
570 | count -= n; | ||
571 | RETURN_ERR( play_( this, n, this->buf ) ); | ||
572 | } | ||
573 | return 0; | ||
574 | } | ||
575 | 523 | ||
576 | blargg_err_t Track_skip( struct Ay_Emu *this, long count ) | 524 | int n = count - threshold/2; |
577 | { | 525 | n &= ~(2048-1); // round to multiple of 2048 |
578 | require( this->current_track >= 0 ); // start_track() must have been called already | ||
579 | this->out_time += count; | ||
580 | |||
581 | // remove from silence and buf first | ||
582 | { | ||
583 | long n = min( count, this->silence_count ); | ||
584 | this->silence_count -= n; | ||
585 | count -= n; | 526 | count -= n; |
586 | 527 | RETURN_ERR( skippy_( &this->track_filter, n ) ); | |
587 | n = min( count, this->buf_remain ); | ||
588 | this->buf_remain -= n; | ||
589 | count -= n; | ||
590 | } | ||
591 | |||
592 | if ( count && !this->emu_track_ended_ ) | ||
593 | { | ||
594 | this->emu_time += count; | ||
595 | |||
596 | // End track if error | ||
597 | if ( skip_( this, count ) ) | ||
598 | this->emu_track_ended_ = true; | ||
599 | } | ||
600 | |||
601 | if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended | ||
602 | this->track_ended |= this->emu_track_ended_; | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | 528 | ||
607 | // Fading | 529 | Sound_mute_voices( this, saved_mute ); |
530 | } | ||
608 | 531 | ||
609 | void Track_set_fade( struct Ay_Emu *this, long start_msec, long length_msec ) | 532 | return skippy_( &this->track_filter, count ); |
610 | { | ||
611 | this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo); | ||
612 | this->fade_start = msec_to_samples( start_msec, this->sample_rate ); | ||
613 | } | 533 | } |
614 | 534 | ||
615 | // unit / pow( 2.0, (double) x / step ) | 535 | blargg_err_t Track_skip( struct Ay_Emu *this, int count ) |
616 | static int int_log( blargg_long x, int step, int unit ) | ||
617 | { | 536 | { |
618 | int shift = x / step; | 537 | require( this->current_track >= 0 ); // start_track() must have been called already |
619 | int fraction = (x - shift * step) * unit / step; | 538 | return track_skip( &this->track_filter, count ); |
620 | return ((unit - fraction) + (fraction >> 1)) >> shift; | ||
621 | } | 539 | } |
622 | 540 | ||
623 | static void handle_fade( struct Ay_Emu *this, long out_count, sample_t* out ) | 541 | int Track_get_length( struct Ay_Emu* this, int n ) |
624 | { | 542 | { |
625 | int i; | 543 | int length = 0; |
626 | for ( i = 0; i < out_count; i += fade_block_size ) | ||
627 | { | ||
628 | int const shift = 14; | ||
629 | int const unit = 1 << shift; | ||
630 | int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size, | ||
631 | this->fade_step, unit ); | ||
632 | if ( gain < (unit >> fade_shift) ) | ||
633 | this->track_ended = this->emu_track_ended_ = true; | ||
634 | |||
635 | sample_t* io = &out [i]; | ||
636 | int count; | ||
637 | for ( count = min( fade_block_size, out_count - i ); count; --count ) | ||
638 | { | ||
639 | *io = (sample_t) ((*io * gain) >> shift); | ||
640 | ++io; | ||
641 | } | ||
642 | } | ||
643 | } | ||
644 | 544 | ||
645 | // Silence detection | 545 | byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 ); |
546 | if ( track_info ) | ||
547 | length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec | ||
646 | 548 | ||
647 | static void emu_play( struct Ay_Emu *this, long count, sample_t* out ) | 549 | if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { |
648 | { | 550 | struct entry_t* entry = &this->m3u.entries [n]; |
649 | check( current_track_ >= 0 ); | 551 | length = entry->length; |
650 | this->emu_time += count; | 552 | } |
651 | if ( this->current_track >= 0 && !this->emu_track_ended_ ) { | 553 | |
652 | if ( play_( this, count, out ) ) | 554 | if ( length <= 0 ) |
653 | this->emu_track_ended_ = true; | 555 | length = 120 * 1000; /* 2 minutes */ |
654 | } | ||
655 | else | ||
656 | memset( out, 0, count * sizeof *out ); | ||
657 | } | ||
658 | 556 | ||
659 | // number of consecutive silent samples at end | 557 | return length; |
660 | static long count_silence( sample_t* begin, long size ) | ||
661 | { | ||
662 | sample_t first = *begin; | ||
663 | *begin = silence_threshold; // sentinel | ||
664 | sample_t* p = begin + size; | ||
665 | while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { } | ||
666 | *begin = first; | ||
667 | return size - (p - begin); | ||
668 | } | 558 | } |
669 | 559 | ||
670 | // fill internal buffer and check it for silence | 560 | void Track_set_fade( struct Ay_Emu *this, int start_msec, int length_msec ) |
671 | void fill_buf( struct Ay_Emu *this ) | ||
672 | { | 561 | { |
673 | assert( !this->buf_remain ); | 562 | track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ), |
674 | if ( !this->emu_track_ended_ ) | 563 | length_msec * this->sample_rate / (1000 / stereo) ); |
675 | { | ||
676 | emu_play( this, buf_size, this->buf ); | ||
677 | long silence = count_silence( this->buf, buf_size ); | ||
678 | if ( silence < buf_size ) | ||
679 | { | ||
680 | this->silence_time = this->emu_time - silence; | ||
681 | this->buf_remain = buf_size; | ||
682 | return; | ||
683 | } | ||
684 | } | ||
685 | this->silence_count += buf_size; | ||
686 | } | 564 | } |
687 | 565 | ||
688 | blargg_err_t Ay_play( struct Ay_Emu *this, long out_count, sample_t* out ) | 566 | blargg_err_t Ay_play( struct Ay_Emu *this, int out_count, sample_t* out ) |
689 | { | 567 | { |
690 | if ( this->track_ended ) | 568 | require( this->current_track >= 0 ); |
691 | { | 569 | require( out_count % stereo == 0 ); |
692 | memset( out, 0, out_count * sizeof *out ); | 570 | return track_play( &this->track_filter, out_count, out ); |
693 | } | ||
694 | else | ||
695 | { | ||
696 | require( this->current_track >= 0 ); | ||
697 | require( out_count % stereo == 0 ); | ||
698 | |||
699 | assert( this->emu_time >= this->out_time ); | ||
700 | |||
701 | // prints nifty graph of how far ahead we are when searching for silence | ||
702 | //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" ); | ||
703 | |||
704 | long pos = 0; | ||
705 | if ( this->silence_count ) | ||
706 | { | ||
707 | // during a run of silence, run emulator at >=2x speed so it gets ahead | ||
708 | long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time; | ||
709 | while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) ) | ||
710 | fill_buf( this ); | ||
711 | |||
712 | // fill with silence | ||
713 | pos = min( this->silence_count, out_count ); | ||
714 | memset( out, 0, pos * sizeof *out ); | ||
715 | this->silence_count -= pos; | ||
716 | |||
717 | if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate ) | ||
718 | { | ||
719 | this->track_ended = this->emu_track_ended_ = true; | ||
720 | this->silence_count = 0; | ||
721 | this->buf_remain = 0; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | if ( this->buf_remain ) | ||
726 | { | ||
727 | // empty silence buf | ||
728 | long n = min( this->buf_remain, out_count - pos ); | ||
729 | memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out ); | ||
730 | this->buf_remain -= n; | ||
731 | pos += n; | ||
732 | } | ||
733 | |||
734 | // generate remaining samples normally | ||
735 | long remain = out_count - pos; | ||
736 | if ( remain ) | ||
737 | { | ||
738 | emu_play( this, remain, out + pos ); | ||
739 | this->track_ended |= this->emu_track_ended_; | ||
740 | |||
741 | if ( !this->ignore_silence || this->out_time > this->fade_start ) | ||
742 | { | ||
743 | // check end for a new run of silence | ||
744 | long silence = count_silence( out + pos, remain ); | ||
745 | if ( silence < remain ) | ||
746 | this->silence_time = this->emu_time - silence; | ||
747 | |||
748 | if ( this->emu_time - this->silence_time >= buf_size ) | ||
749 | fill_buf( this ); // cause silence detection on next play() | ||
750 | } | ||
751 | } | ||
752 | |||
753 | if ( this->out_time > this->fade_start ) | ||
754 | handle_fade( this, out_count, out ); | ||
755 | } | ||
756 | this->out_time += out_count; | ||
757 | return 0; | ||
758 | } | 571 | } |
759 | 572 | ||
760 | blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ) | 573 | blargg_err_t play_( void *emu, int count, sample_t* out ) |
761 | { | 574 | { |
762 | long remain = count; | 575 | struct Ay_Emu* this = (struct Ay_Emu*) emu; |
576 | |||
577 | int remain = count; | ||
763 | while ( remain ) | 578 | while ( remain ) |
764 | { | 579 | { |
580 | Buffer_disable_immediate_removal( &this->stereo_buf ); | ||
765 | remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); | 581 | remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); |
766 | if ( remain ) | 582 | if ( remain ) |
767 | { | 583 | { |
@@ -773,7 +589,7 @@ blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ) | |||
773 | Sound_mute_voices( this, this->mute_mask_ ); | 589 | Sound_mute_voices( this, this->mute_mask_ ); |
774 | } | 590 | } |
775 | int msec = Buffer_length( &this->stereo_buf ); | 591 | int msec = Buffer_length( &this->stereo_buf ); |
776 | blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate_ / 1000 - 100; | 592 | blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100; |
777 | RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); | 593 | RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); |
778 | assert( clocks_emulated ); | 594 | assert( clocks_emulated ); |
779 | Buffer_end_frame( &this->stereo_buf, clocks_emulated ); | 595 | Buffer_end_frame( &this->stereo_buf, clocks_emulated ); |