summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/vgm_emu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/vgm_emu.c')
-rw-r--r--apps/codecs/libgme/vgm_emu.c388
1 files changed, 108 insertions, 280 deletions
diff --git a/apps/codecs/libgme/vgm_emu.c b/apps/codecs/libgme/vgm_emu.c
index 391bd02d73..4f8a2adbc1 100644
--- a/apps/codecs/libgme/vgm_emu.c
+++ b/apps/codecs/libgme/vgm_emu.c
@@ -23,11 +23,6 @@ const char* const gme_wrong_file_type = "Wrong file type for this emulator";
23 23
24int const fm_gain = 3; // FM emulators are internally quieter to avoid 16-bit overflow 24int const fm_gain = 3; // FM emulators are internally quieter to avoid 16-bit overflow
25 25
26int const silence_max = 6; // seconds
27int const silence_threshold = 0x10;
28long const fade_block_size = 512;
29int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
30
31// VGM commands (Spec v1.50) 26// VGM commands (Spec v1.50)
32enum { 27enum {
33 cmd_gg_stereo = 0x4F, 28 cmd_gg_stereo = 0x4F,
@@ -53,15 +48,8 @@ enum {
53 48
54static void clear_track_vars( struct Vgm_Emu* this ) 49static void clear_track_vars( struct Vgm_Emu* this )
55{ 50{
56 this->out_time = 0; 51 this->current_track = -1;
57 this->emu_time = 0; 52 track_stop( &this->track_filter );
58 this->emu_track_ended_ = true;
59 this->track_ended = true;
60 this->fade_start = INT_MAX / 2 + 1;
61 this->fade_step = 1;
62 this->silence_time = 0;
63 this->silence_count = 0;
64 this->buf_remain = 0;
65} 53}
66 54
67int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, sample_t* buf ); 55int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, sample_t* buf );
@@ -77,9 +65,10 @@ void Vgm_init( struct Vgm_Emu* this )
77 this->tempo = (int)(FP_ONE_TEMPO); 65 this->tempo = (int)(FP_ONE_TEMPO);
78 66
79 // defaults 67 // defaults
80 this->max_initial_silence = 2; 68 this->tfilter = *track_get_setup( &this->track_filter );
81 this->silence_lookahead = 1; // tracks should already be trimmed 69 this->tfilter.max_initial = 2;
82 this->ignore_silence = false; 70 this->tfilter.lookahead = 1;
71 this->track_filter.silence_ignored_ = false;
83 72
84 // Disable oversampling by default 73 // Disable oversampling by default
85 this->disable_oversampling = true; 74 this->disable_oversampling = true;
@@ -88,10 +77,10 @@ void Vgm_init( struct Vgm_Emu* this )
88 Sms_apu_init( &this->psg ); 77 Sms_apu_init( &this->psg );
89 Synth_init( &this->pcm ); 78 Synth_init( &this->pcm );
90 79
91 Buffer_init( &this->buf ); 80 Buffer_init( &this->stereo_buf );
92 Blip_init( &this->blip_buf ); 81 Blip_init( &this->blip_buf );
93 82
94 // Init fm chips 83 // Init fm chips
95 Ym2413_init( &this->ym2413 ); 84 Ym2413_init( &this->ym2413 );
96 Ym2612_init( &this->ym2612 ); 85 Ym2612_init( &this->ym2612 );
97 86
@@ -105,7 +94,8 @@ void Vgm_init( struct Vgm_Emu* this )
105 94
106 // Unload 95 // Unload
107 this->voice_count = 0; 96 this->voice_count = 0;
108 clear_track_vars( this ); 97 this->voice_types = 0;
98 clear_track_vars( this );
109} 99}
110 100
111// Track info 101// Track info
@@ -150,13 +140,13 @@ static void parse_gd3( byte const* in, byte const* end, struct track_info_t* out
150 140
151int const gd3_header_size = 12; 141int const gd3_header_size = 12;
152 142
153static long check_gd3_header( byte const* h, long remain ) 143static int check_gd3_header( byte const* h, int remain )
154{ 144{
155 if ( remain < gd3_header_size ) return 0; 145 if ( remain < gd3_header_size ) return 0;
156 if ( memcmp( h, "Gd3 ", 4 ) ) return 0; 146 if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
157 if ( get_le32( h + 4 ) >= 0x200 ) return 0; 147 if ( get_le32( h + 4 ) >= 0x200 ) return 0;
158 148
159 long gd3_size = get_le32( h + 8 ); 149 int gd3_size = get_le32( h + 8 );
160 if ( gd3_size > remain - gd3_header_size ) 150 if ( gd3_size > remain - gd3_header_size )
161 gd3_size = remain - gd3_header_size; 151 gd3_size = remain - gd3_header_size;
162 return gd3_size; 152 return gd3_size;
@@ -167,12 +157,12 @@ static byte const* gd3_data( struct Vgm_Emu* this, int* size )
167 if ( size ) 157 if ( size )
168 *size = 0; 158 *size = 0;
169 159
170 long gd3_offset = get_le32( header( this )->gd3_offset ) - 0x2C; 160 int gd3_offset = get_le32( header( this )->gd3_offset ) - 0x2C;
171 if ( gd3_offset < 0 ) 161 if ( gd3_offset < 0 )
172 return 0; 162 return 0;
173 163
174 byte const* gd3 = this->file_begin + header_size + gd3_offset; 164 byte const* gd3 = this->file_begin + header_size + gd3_offset;
175 long gd3_size = check_gd3_header( gd3, this->file_end - gd3 ); 165 int gd3_size = check_gd3_header( gd3, this->file_end - gd3 );
176 if ( !gd3_size ) 166 if ( !gd3_size )
177 return 0; 167 return 0;
178 168
@@ -184,10 +174,10 @@ static byte const* gd3_data( struct Vgm_Emu* this, int* size )
184 174
185static void get_vgm_length( struct header_t const* h, struct track_info_t* out ) 175static void get_vgm_length( struct header_t const* h, struct track_info_t* out )
186{ 176{
187 long length = get_le32( h->track_duration ) * 10 / 441; 177 int length = get_le32( h->track_duration ) * 10 / 441;
188 if ( length > 0 ) 178 if ( length > 0 )
189 { 179 {
190 long loop = get_le32( h->loop_duration ); 180 int loop = get_le32( h->loop_duration );
191 if ( loop > 0 && get_le32( h->loop_offset ) ) 181 if ( loop > 0 && get_le32( h->loop_offset ) )
192 { 182 {
193 out->loop_length = loop * 10 / 441; 183 out->loop_length = loop * 10 / 441;
@@ -285,24 +275,25 @@ blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_
285 Ym2612_enable( &this->ym2612, false ); 275 Ym2612_enable( &this->ym2612, false );
286 Ym2413_enable( &this->ym2413, false ); 276 Ym2413_enable( &this->ym2413, false );
287 277
288 Sound_set_tempo( this, (int)(FP_ONE_TEMPO) );
289
290 this->voice_count = sms_osc_count; 278 this->voice_count = sms_osc_count;
279 static int const types [8] = {
280 wave_type+1, wave_type+2, wave_type+3, noise_type+1,
281 0, 0, 0, 0
282 };
283 this->voice_types = types;
291 284
292 RETURN_ERR( setup_fm( this ) ); 285 RETURN_ERR( setup_fm( this ) );
293 286
294 // do after FM in case output buffer is changed 287 // do after FM in case output buffer is changed
295 // setup buffer 288 // setup buffer
296 this->clock_rate_ = this->psg_rate; 289 this->clock_rate_ = this->psg_rate;
297 Buffer_clock_rate( &this->buf, this->psg_rate ); 290 Buffer_clock_rate( &this->stereo_buf, this->psg_rate );
298 291 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
299 // Setup bass 292 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
300 this->buf_changed_count = Buffer_channels_changed_count( &this->buf );
301 293
302 // Post load 294 // Post load
303 Sound_set_tempo( this, this->tempo ); 295 Sound_set_tempo( this, this->tempo );
304 Sound_mute_voices( this, this->mute_mask_ ); 296 Sound_mute_voices( this, this->mute_mask_ );
305
306 return 0; 297 return 0;
307} 298}
308 299
@@ -362,42 +353,56 @@ blargg_err_t setup_fm( struct Vgm_Emu* this )
362// Emulation 353// Emulation
363 354
364blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time ); 355blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time );
365static blargg_err_t run_clocks( struct Vgm_Emu* this, blip_time_t* time_io, int msec ) 356static blip_time_t run_psg( struct Vgm_Emu* this, int msec )
366{ 357{
367 *time_io = run( this, msec * this->vgm_rate / 1000 ); 358 blip_time_t t = run( this, msec * this->vgm_rate / 1000 );
368 Sms_apu_end_frame( &this->psg, *time_io ); 359 Sms_apu_end_frame( &this->psg, t );
369 return 0; 360 return t;
370} 361}
371 362
363static void check_end( struct Vgm_Emu* this )
364{
365 if( this->pos >= this->file_end )
366 track_set_end( &this->track_filter );
367}
372 368
369static blargg_err_t run_clocks( struct Vgm_Emu* this, blip_time_t* time_io, int msec )
370{
371 check_end( this );
372 *time_io = run_psg( this, msec );
373 return 0;
374}
373 375
374static blargg_err_t play_( struct Vgm_Emu* this, long count, sample_t* out ) 376blargg_err_t play_( void *emu, int count, sample_t out [] )
375{ 377{
378 struct Vgm_Emu* this = (struct Vgm_Emu*) emu;
379
376 if ( !uses_fm( this ) ) { 380 if ( !uses_fm( this ) ) {
377 long remain = count; 381 int remain = count;
378 while ( remain ) 382 while ( remain )
379 { 383 {
380 remain -= Buffer_read_samples( &this->buf, &out [count - remain], remain ); 384 Buffer_disable_immediate_removal( &this->stereo_buf );
385 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
381 if ( remain ) 386 if ( remain )
382 { 387 {
383 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->buf ) ) 388 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
384 { 389 {
385 this->buf_changed_count = Buffer_channels_changed_count( &this->buf ); 390 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
386 391
387 // Remute voices 392 // Remute voices
388 Sound_mute_voices( this, this->mute_mask_ ); 393 Sound_mute_voices( this, this->mute_mask_ );
389 } 394 }
390 int msec = Buffer_length( &this->buf ); 395 int msec = Buffer_length( &this->stereo_buf );
391 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate_ / 1000 - 100; 396 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
392 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); 397 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
393 assert( clocks_emulated ); 398 assert( clocks_emulated );
394 Buffer_end_frame( &this->buf, clocks_emulated ); 399 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
395 } 400 }
396 } 401 }
397 402
398 return 0; 403 return 0;
399 } 404 }
400 405
401 Resampler_play( &this->resampler, count, out, &this->blip_buf ); 406 Resampler_play( &this->resampler, count, out, &this->blip_buf );
402 return 0; 407 return 0;
403} 408}
@@ -414,7 +419,7 @@ static inline int command_len( int command )
414 check( len != 1 ); 419 check( len != 1 );
415 return len; 420 return len;
416} 421}
417 422
418static inline fm_time_t to_fm_time( struct Vgm_Emu* this, vgm_time_t t ) 423static inline fm_time_t to_fm_time( struct Vgm_Emu* this, vgm_time_t t )
419{ 424{
420 return (t * this->fm_time_factor + this->fm_time_offset) >> fm_time_bits; 425 return (t * this->fm_time_factor + this->fm_time_offset) >> fm_time_bits;
@@ -443,12 +448,10 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
443{ 448{
444 vgm_time_t vgm_time = this->vgm_time; 449 vgm_time_t vgm_time = this->vgm_time;
445 byte const* pos = this->pos; 450 byte const* pos = this->pos;
446 if ( pos >= this->file_end ) 451 /* if ( pos > this->file_end )
447 { 452 {
448 this->emu_track_ended_ = true; 453 warning( "Stream lacked end event" );
449 /* if ( pos > data_end ) 454 } */
450 warning( "Stream lacked end event" ); */
451 }
452 455
453 while ( vgm_time < end_time && pos < this->file_end ) 456 while ( vgm_time < end_time && pos < this->file_end )
454 { 457 {
@@ -517,7 +520,7 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
517 case cmd_data_block: { 520 case cmd_data_block: {
518 check( *pos == cmd_end ); 521 check( *pos == cmd_end );
519 int type = pos [1]; 522 int type = pos [1];
520 long size = get_le32( pos + 2 ); 523 int size = get_le32( pos + 2 );
521 pos += 6; 524 pos += 6;
522 if ( type == pcm_block_type ) 525 if ( type == pcm_block_type )
523 this->pcm_data = pos; 526 this->pcm_data = pos;
@@ -564,6 +567,8 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
564 567
565int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, blip_sample_t out [] ) 568int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, blip_sample_t out [] )
566{ 569{
570 check_end( this);
571
567 // to do: timing is working mostly by luck 572 // to do: timing is working mostly by luck
568 int min_pairs = (unsigned) sample_count / 2; 573 int min_pairs = (unsigned) sample_count / 2;
569 int vgm_time = (min_pairs << fm_time_bits) / this->fm_time_factor - 1; 574 int vgm_time = (min_pairs << fm_time_bits) / this->fm_time_factor - 1;
@@ -642,16 +647,18 @@ void update_fm_rates( struct Vgm_Emu* this, int* ym2413_rate, int* ym2612_rate )
642 647
643// Music Emu 648// Music Emu
644 649
645blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long rate ) 650blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, int rate )
646{ 651{
647 require( !this->sample_rate ); // sample rate can't be changed once set 652 require( !this->sample_rate ); // sample rate can't be changed once set
648 RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) ); 653 RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) );
649 RETURN_ERR( Buffer_set_sample_rate( &this->buf, rate, 1000 / 20 ) ); 654 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
650 655
651 // Set bass frequency 656 // Set bass frequency
652 Buffer_bass_freq( &this->buf, 80 ); 657 Buffer_bass_freq( &this->stereo_buf, 80 );
653 658
654 this->sample_rate = rate; 659 this->sample_rate = rate;
660 RETURN_ERR( track_init( &this->track_filter, this ) );
661 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
655 return 0; 662 return 0;
656} 663}
657 664
@@ -679,7 +686,7 @@ void Sound_mute_voices( struct Vgm_Emu* this, int mask )
679 } 686 }
680 else 687 else
681 { 688 {
682 struct channel_t ch = Buffer_channel( &this->buf ); 689 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
683 assert( (ch.center && ch.left && ch.right) || 690 assert( (ch.center && ch.left && ch.right) ||
684 (!ch.center && !ch.left && !ch.right) ); // all or nothing 691 (!ch.center && !ch.left && !ch.right) ); // all or nothing
685 set_voice( this, i, ch.center, ch.left, ch.right ); 692 set_voice( this, i, ch.center, ch.left, ch.right );
@@ -735,7 +742,6 @@ void Sound_set_tempo( struct Vgm_Emu* this, int t )
735 } 742 }
736} 743}
737 744
738void fill_buf( struct Vgm_Emu *this );
739blargg_err_t Vgm_start_track( struct Vgm_Emu* this ) 745blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
740{ 746{
741 clear_track_vars( this ); 747 clear_track_vars( this );
@@ -750,7 +756,7 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
750 this->vgm_time = 0; 756 this->vgm_time = 0;
751 if ( get_le32( header( this )->version ) >= 0x150 ) 757 if ( get_le32( header( this )->version ) >= 0x150 )
752 { 758 {
753 long data_offset = get_le32( header( this )->data_offset ); 759 int data_offset = get_le32( header( this )->data_offset );
754 check( data_offset ); 760 check( data_offset );
755 if ( data_offset ) 761 if ( data_offset )
756 this->pos += data_offset + offsetof (struct header_t,data_offset) - 0x40; 762 this->pos += data_offset + offsetof (struct header_t,data_offset) - 0x40;
@@ -764,266 +770,88 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
764 if ( Ym2612_enabled( &this->ym2612 ) ) 770 if ( Ym2612_enabled( &this->ym2612 ) )
765 Ym2612_reset( &this->ym2612 ); 771 Ym2612_reset( &this->ym2612 );
766 772
767 Blip_clear( &this->blip_buf, 1 ); 773 Blip_clear( &this->blip_buf );
768 Resampler_clear( &this->resampler ); 774 Resampler_clear( &this->resampler );
769 } 775 }
770 776
771 this->fm_time_offset = 0; 777 this->fm_time_offset = 0;
772 778
773 Buffer_clear( &this->buf ); 779 Buffer_clear( &this->stereo_buf );
774 780
775 this->emu_track_ended_ = false; 781 // convert filter times to samples
776 this->track_ended = false; 782 struct setup_t s = this->tfilter;
783 s.max_initial *= this->sample_rate * stereo;
784 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
785 s.lookahead = 1;
786 #endif
787 track_setup( &this->track_filter, &s );
777 788
778 if ( !this->ignore_silence ) 789 return track_start( &this->track_filter );
779 {
780 // play until non-silence or end of track
781 long end;
782 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
783 {
784 fill_buf( this );
785 if ( this->buf_remain | (int) this->emu_track_ended_ )
786 break;
787 }
788
789 this->emu_time = this->buf_remain;
790 this->out_time = 0;
791 this->silence_time = 0;
792 this->silence_count = 0;
793 }
794 /* return track_ended() ? warning() : 0; */
795 return 0;
796} 790}
797 791
798// Tell/Seek 792// Tell/Seek
799 793
800static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 794static int msec_to_samples( int msec, int sample_rate )
801{ 795{
802 blargg_long sec = msec / 1000; 796 int sec = msec / 1000;
803 msec -= sec * 1000; 797 msec -= sec * 1000;
804 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 798 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
805} 799}
806 800
807long Track_tell( struct Vgm_Emu* this ) 801int Track_tell( struct Vgm_Emu* this )
808{ 802{
809 blargg_long rate = this->sample_rate * stereo; 803 int rate = this->sample_rate * stereo;
810 blargg_long sec = this->out_time / rate; 804 int sec = track_sample_count( &this->track_filter ) / rate;
811 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 805 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
812} 806}
813 807
814blargg_err_t Track_seek( struct Vgm_Emu* this, long msec ) 808blargg_err_t Track_seek( struct Vgm_Emu* this, int msec )
815{ 809{
816 blargg_long time = msec_to_samples( msec, this->sample_rate ); 810 int time = msec_to_samples( msec, this->sample_rate );
817 if ( time < this->out_time ) 811 if ( time < track_sample_count( &this->track_filter ) )
818 RETURN_ERR( Vgm_start_track( this ) ); 812 RETURN_ERR( Vgm_start_track( this ) );
819 return Track_skip( this, time - this->out_time ); 813 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
820} 814}
821 815
822blargg_err_t skip_( struct Vgm_Emu* this, long count ); 816blargg_err_t Track_skip( struct Vgm_Emu* this, int count )
823blargg_err_t Track_skip( struct Vgm_Emu* this, long count )
824{ 817{
825 this->out_time += count; 818 require( this->current_track >= 0 ); // start_track() must have been called already
826 819 return track_skip( &this->track_filter, count );
827 // remove from silence and buf first
828 {
829 long n = min( count, this->silence_count );
830 this->silence_count -= n;
831 count -= n;
832
833 n = min( count, this->buf_remain );
834 this->buf_remain -= n;
835 count -= n;
836 }
837
838 if ( count && !this->emu_track_ended_ )
839 {
840 this->emu_time += count;
841 if ( skip_( this, count ) )
842 this->emu_track_ended_ = true;
843 }
844
845 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
846 this->track_ended |= this->emu_track_ended_;
847
848 return 0;
849} 820}
850 821
851blargg_err_t skip_( struct Vgm_Emu* this, long count ) 822blargg_err_t skip_( void* emu, int count )
852{ 823{
824 struct Vgm_Emu* this = (struct Vgm_Emu*) emu;
825
853 // for long skip, mute sound 826 // for long skip, mute sound
854 const long threshold = 30000; 827 const int threshold = 32768;
855 if ( count > threshold ) 828 if ( count > threshold )
856 { 829 {
857 int saved_mute = this->mute_mask_; 830 int saved_mute = this->mute_mask_;
858 Sound_mute_voices( this, ~0 ); 831 Sound_mute_voices( this, ~0 );
859
860 while ( count > threshold / 2 && !this->emu_track_ended_ )
861 {
862 RETURN_ERR( play_( this, buf_size, this->buf_ ) );
863 count -= buf_size;
864 }
865
866 Sound_mute_voices( this, saved_mute );
867 }
868
869 while ( count && !this->emu_track_ended_ )
870 {
871 long n = buf_size;
872 if ( n > count )
873 n = count;
874 count -= n;
875 RETURN_ERR( play_( this, n, this->buf_ ) );
876 }
877 return 0;
878}
879 832
880// Fading 833 int n = count - threshold/2;
881 834 n &= ~(2048-1); // round to multiple of 2048
882void Track_set_fade( struct Vgm_Emu* this, long start_msec, long length_msec ) 835 count -= n;
883{ 836 RETURN_ERR( skippy_( &this->track_filter, n ) );
884 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
885 this->fade_start = msec_to_samples( start_msec, this->sample_rate );
886}
887
888// unit / pow( 2.0, (double) x / step )
889static int int_log( blargg_long x, int step, int unit )
890{
891 int shift = x / step;
892 int fraction = (x - shift * step) * unit / step;
893 return ((unit - fraction) + (fraction >> 1)) >> shift;
894}
895 837
896static void handle_fade( struct Vgm_Emu* this, long out_count, sample_t* out ) 838 Sound_mute_voices( this, saved_mute );
897{
898 int i;
899 for ( i = 0; i < out_count; i += fade_block_size )
900 {
901 int const shift = 14;
902 int const unit = 1 << shift;
903 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
904 this->fade_step, unit );
905 if ( gain < (unit >> fade_shift) )
906 this->track_ended = this->emu_track_ended_ = true;
907
908 sample_t* io = &out [i];
909 int count;
910 for ( count = min( fade_block_size, out_count - i ); count; --count )
911 {
912 *io = (sample_t) ((*io * gain) >> shift);
913 ++io;
914 }
915 } 839 }
916}
917 840
918// Silence detection 841 return skippy_( &this->track_filter, count );
919
920static void emu_play( struct Vgm_Emu* this, long count, sample_t* out )
921{
922 this->emu_time += count;
923 if ( !this->emu_track_ended_ ) {
924 if ( play_( this, count, out ) )
925 this->emu_track_ended_ = true;
926 }
927 else
928 memset( out, 0, count * sizeof *out );
929} 842}
930 843
931// number of consecutive silent samples at end 844// Fading
932static long count_silence( sample_t* begin, long size )
933{
934 sample_t first = *begin;
935 *begin = silence_threshold; // sentinel
936 sample_t* p = begin + size;
937 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
938 *begin = first;
939 return size - (p - begin);
940}
941 845
942// fill internal buffer and check it for silence 846void Track_set_fade( struct Vgm_Emu* this, int start_msec, int length_msec )
943void fill_buf( struct Vgm_Emu* this )
944{ 847{
945 assert( !this->buf_remain ); 848 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
946 if ( !this->emu_track_ended_ ) 849 length_msec * this->sample_rate / (1000 / stereo) );
947 {
948 emu_play( this, buf_size, this->buf_ );
949 long silence = count_silence( this->buf_, buf_size );
950 if ( silence < buf_size )
951 {
952 this->silence_time = this->emu_time - silence;
953 this->buf_remain = buf_size;
954 return;
955 }
956 }
957 this->silence_count += buf_size;
958} 850}
959 851
960blargg_err_t Vgm_play( struct Vgm_Emu* this, long out_count, sample_t* out ) 852blargg_err_t Vgm_play( struct Vgm_Emu* this, int out_count, sample_t* out )
961{ 853{
962 if ( this->track_ended ) 854 require( this->current_track >= 0 );
963 { 855 require( out_count % stereo == 0 );
964 memset( out, 0, out_count * sizeof *out ); 856 return track_play( &this->track_filter, out_count, out );
965 }
966 else
967 {
968 require( out_count % stereo == 0 );
969
970 assert( this->emu_time >= this->out_time );
971
972 // prints nifty graph of how far ahead we are when searching for silence
973 //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
974
975 long pos = 0;
976 if ( this->silence_count )
977 {
978 // during a run of silence, run emulator at >=2x speed so it gets ahead
979 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
980 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
981 fill_buf( this );
982
983 // fill with silence
984 pos = min( this->silence_count, out_count );
985 memset( out, 0, pos * sizeof *out );
986 this->silence_count -= pos;
987
988 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
989 {
990 this->track_ended = this->emu_track_ended_ = true;
991 this->silence_count = 0;
992 this->buf_remain = 0;
993 }
994 }
995
996 if ( this->buf_remain )
997 {
998 // empty silence buf
999 long n = min( this->buf_remain, out_count - pos );
1000 memcpy( &out [pos], this->buf_ + (buf_size - this->buf_remain), n * sizeof *out );
1001 this->buf_remain -= n;
1002 pos += n;
1003 }
1004
1005 // generate remaining samples normally
1006 long remain = out_count - pos;
1007 if ( remain )
1008 {
1009 emu_play( this, remain, out + pos );
1010 this->track_ended |= this->emu_track_ended_;
1011
1012 if ( !this->ignore_silence || this->out_time > this->fade_start )
1013 {
1014 // check end for a new run of silence
1015 long silence = count_silence( out + pos, remain );
1016 if ( silence < remain )
1017 this->silence_time = this->emu_time - silence;
1018
1019 if ( this->emu_time - this->silence_time >= buf_size )
1020 fill_buf( this ); // cause silence detection on next play()
1021 }
1022 }
1023
1024 if ( this->out_time > this->fade_start )
1025 handle_fade( this, out_count, out );
1026 }
1027 this->out_time += out_count;
1028 return 0;
1029} 857}