summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/ay_emu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/ay_emu.c')
-rw-r--r--apps/codecs/libgme/ay_emu.c356
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
20int const stereo = 2; // number of channels for stereo
21int const silence_max = 6; // seconds
22int const silence_threshold = 0x10;
23long const fade_block_size = 512;
24int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
25
26const char* const gme_wrong_file_type = "Wrong file type for this emulator"; 20const 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;
38static void clear_track_vars( struct Ay_Emu *this ) 32static 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
53void Ay_init( struct Ay_Emu *this ) 38void 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
110long 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
131static void change_clock_rate( struct Ay_Emu *this, long rate ) 100static 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
137blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], int size ) 106blargg_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
301blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, long rate ) 279blargg_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
362void fill_buf( struct Ay_Emu *this );;
363blargg_err_t Ay_start_track( struct Ay_Emu *this, int track ) 342blargg_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
524static blargg_long msec_to_samples( blargg_long msec, long sample_rate ) 491static 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
531long Track_tell( struct Ay_Emu *this ) 498int 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
538blargg_err_t Track_seek( struct Ay_Emu *this, long msec ) 505blargg_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
546blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ); 513blargg_err_t skip_( void *emu, int count )
547static 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
576blargg_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
609void 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 ) 535blargg_err_t Track_skip( struct Ay_Emu *this, int count )
616static 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
623static void handle_fade( struct Ay_Emu *this, long out_count, sample_t* out ) 541int 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
647static 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;
660static 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 560void Track_set_fade( struct Ay_Emu *this, int start_msec, int length_msec )
671void 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
688blargg_err_t Ay_play( struct Ay_Emu *this, long out_count, sample_t* out ) 566blargg_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
760blargg_err_t play_( struct Ay_Emu *this, long count, sample_t* out ) 573blargg_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 );