summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/nsf_emu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/nsf_emu.c')
-rw-r--r--apps/codecs/libgme/nsf_emu.c496
1 files changed, 154 insertions, 342 deletions
diff --git a/apps/codecs/libgme/nsf_emu.c b/apps/codecs/libgme/nsf_emu.c
index a4873c81cb..705c345fa6 100644
--- a/apps/codecs/libgme/nsf_emu.c
+++ b/apps/codecs/libgme/nsf_emu.c
@@ -1,4 +1,4 @@
1// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/ 1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2 2
3#include "nsf_emu.h" 3#include "nsf_emu.h"
4#include "multi_buffer.h" 4#include "multi_buffer.h"
@@ -19,33 +19,19 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19#include "blargg_source.h" 19#include "blargg_source.h"
20 20
21const char gme_wrong_file_type [] = "Wrong file type for this emulator"; 21const char gme_wrong_file_type [] = "Wrong file type for this emulator";
22long const clock_divisor = 12;
23
24int const stereo = 2; // number of channels for stereo
25int const silence_max = 6; // seconds
26int const silence_threshold = 0x10;
27long const fade_block_size = 512;
28int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
29 22
30// number of frames until play interrupts init 23// number of frames until play interrupts init
31int const initial_play_delay = 7; // KikiKaikai needed this to work 24int const initial_play_delay = 7; // KikiKaikai needed this to work
25int const bank_size = 0x1000;
32int const rom_addr = 0x8000; 26int const rom_addr = 0x8000;
33 27
34static void clear_track_vars( struct Nsf_Emu* this ) 28static void clear_track_vars( struct Nsf_Emu* this )
35{ 29{
36 this->current_track = -1; 30 this->current_track = -1;
37 this->out_time = 0; 31 track_stop( &this->track_filter );
38 this->emu_time = 0;
39 this->emu_track_ended_ = true;
40 this->track_ended = true;
41 this->fade_start = INT_MAX / 2 + 1;
42 this->fade_step = 1;
43 this->silence_time = 0;
44 this->silence_count = 0;
45 this->buf_remain = 0;
46} 32}
47 33
48static int pcm_read( void* emu, addr_t addr ) 34static int pcm_read( void* emu, int addr )
49{ 35{
50 return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr ); 36 return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr );
51} 37}
@@ -58,18 +44,16 @@ void Nsf_init( struct Nsf_Emu* this )
58 this->gain = (int)(FP_ONE_GAIN); 44 this->gain = (int)(FP_ONE_GAIN);
59 45
60 // defaults 46 // defaults
61 this->max_initial_silence = 2; 47 this->tfilter = *track_get_setup( &this->track_filter );
62 this->ignore_silence = false; 48 this->tfilter.max_initial = 2;
63 this->voice_count = 0; 49 this->tfilter.lookahead = 6;
50 this->track_filter.silence_ignored_ = false;
64 51
65 // Set sound gain 52 // Set sound gain
66 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) ); 53 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
67 54
68 // Unload
69 clear_track_vars( this );
70
71 // Init rom 55 // Init rom
72 Rom_init( &this->rom, 0x1000 ); 56 Rom_init( &this->rom, bank_size );
73 57
74 // Init & clear nsfe info 58 // Init & clear nsfe info
75 Info_init( &this->info ); 59 Info_init( &this->info );
@@ -78,16 +62,36 @@ void Nsf_init( struct Nsf_Emu* this )
78 Cpu_init( &this->cpu ); 62 Cpu_init( &this->cpu );
79 Apu_init( &this->apu ); 63 Apu_init( &this->apu );
80 Apu_dmc_reader( &this->apu, pcm_read, this ); 64 Apu_dmc_reader( &this->apu, pcm_read, this );
65
66 // Unload
67 this->voice_count = 0;
68 memset( this->voice_types, 0, sizeof this->voice_types );
69 clear_track_vars( this );
81} 70}
82 71
83// Setup 72// Setup
84 73
74static void append_voices( struct Nsf_Emu* this, int const types [], int count )
75{
76 assert( this->voice_count + count < max_voices );
77 int i;
78 for ( i = 0; i < count; i++ ) {
79 this->voice_types [this->voice_count + i] = types [i];
80 }
81 this->voice_count += count;
82}
83
85static blargg_err_t init_sound( struct Nsf_Emu* this ) 84static blargg_err_t init_sound( struct Nsf_Emu* this )
86{ 85{
87 /* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) ) 86/* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) )
88 warning( "Uses unsupported audio expansion hardware" ); **/ 87 warning( "Uses unsupported audio expansion hardware" ); **/
89 88
90 this->voice_count = apu_osc_count; 89 {
90 static int const types [apu_osc_count] = {
91 wave_type+1, wave_type+2, mixed_type+1, noise_type+0, mixed_type+1
92 };
93 append_voices( this, types, apu_osc_count );
94 }
91 95
92 int adjusted_gain = (this->gain * 4) / 3; 96 int adjusted_gain = (this->gain * 4) / 3;
93 97
@@ -103,7 +107,10 @@ static blargg_err_t init_sound( struct Nsf_Emu* this )
103 Vrc6_init( &this->vrc6 ); 107 Vrc6_init( &this->vrc6 );
104 adjusted_gain = (adjusted_gain*3) / 4; 108 adjusted_gain = (adjusted_gain*3) / 4;
105 109
106 this->voice_count += vrc6_osc_count; 110 static int const types [vrc6_osc_count] = {
111 wave_type+3, wave_type+4, wave_type+5,
112 };
113 append_voices( this, types, vrc6_osc_count );
107 } 114 }
108 115
109 if ( fme7_enabled( this ) ) 116 if ( fme7_enabled( this ) )
@@ -111,7 +118,10 @@ static blargg_err_t init_sound( struct Nsf_Emu* this )
111 Fme7_init( &this->fme7 ); 118 Fme7_init( &this->fme7 );
112 adjusted_gain = (adjusted_gain*3) / 4; 119 adjusted_gain = (adjusted_gain*3) / 4;
113 120
114 this->voice_count += fme7_osc_count; 121 static int const types [fme7_osc_count] = {
122 wave_type+3, wave_type+4, wave_type+5,
123 };
124 append_voices( this, types, fme7_osc_count );
115 } 125 }
116 126
117 if ( mmc5_enabled( this ) ) 127 if ( mmc5_enabled( this ) )
@@ -119,7 +129,11 @@ static blargg_err_t init_sound( struct Nsf_Emu* this )
119 Mmc5_init( &this->mmc5 ); 129 Mmc5_init( &this->mmc5 );
120 adjusted_gain = (adjusted_gain*3) / 4; 130 adjusted_gain = (adjusted_gain*3) / 4;
121 131
122 this->voice_count += mmc5_osc_count; 132
133 static int const types [mmc5_osc_count] = {
134 wave_type+3, wave_type+4, mixed_type+2
135 };
136 append_voices( this, types, mmc5_osc_count );
123 } 137 }
124 138
125 if ( fds_enabled( this ) ) 139 if ( fds_enabled( this ) )
@@ -127,7 +141,10 @@ static blargg_err_t init_sound( struct Nsf_Emu* this )
127 Fds_init( &this->fds ); 141 Fds_init( &this->fds );
128 adjusted_gain = (adjusted_gain*3) / 4; 142 adjusted_gain = (adjusted_gain*3) / 4;
129 143
130 this->voice_count += fds_osc_count ; 144 static int const types [fds_osc_count] = {
145 wave_type+0
146 };
147 append_voices( this, types, fds_osc_count );
131 } 148 }
132 149
133 if ( namco_enabled( this ) ) 150 if ( namco_enabled( this ) )
@@ -135,22 +152,31 @@ static blargg_err_t init_sound( struct Nsf_Emu* this )
135 Namco_init( &this->namco ); 152 Namco_init( &this->namco );
136 adjusted_gain = (adjusted_gain*3) / 4; 153 adjusted_gain = (adjusted_gain*3) / 4;
137 154
138 this->voice_count += namco_osc_count; 155 static int const types [namco_osc_count] = {
156 wave_type+3, wave_type+4, wave_type+5, wave_type+ 6,
157 wave_type+7, wave_type+8, wave_type+9, wave_type+10,
158 };
159 append_voices( this, types, namco_osc_count );
139 } 160 }
140 161
141 if ( vrc7_enabled( this ) )
142 {
143 #ifndef NSF_EMU_NO_VRC7 162 #ifndef NSF_EMU_NO_VRC7
163 if ( vrc7_enabled( this ) )
164 {
165
144 Vrc7_init( &this->vrc7 ); 166 Vrc7_init( &this->vrc7 );
145 Vrc7_set_rate( &this->vrc7, this->sample_rate ); 167 Vrc7_set_rate( &this->vrc7, this->sample_rate );
146 #endif
147 168
148 adjusted_gain = (adjusted_gain*3) / 4; 169 adjusted_gain = (adjusted_gain*3) / 4;
170
171 static int const types [vrc7_osc_count] = {
172 wave_type+3, wave_type+4, wave_type+5, wave_type+6,
173 wave_type+7, wave_type+8
174 };
175 append_voices( this, types, vrc7_osc_count );
176 }
149 177
150 this->voice_count += vrc7_osc_count; 178 if ( vrc7_enabled( this ) ) Vrc7_volume( &this->vrc7, adjusted_gain );
151 } 179 #endif
152
153 if ( vrc7_enabled( this ) ) Vrc7_volume( &this->vrc7, adjusted_gain );
154 if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain ); 180 if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain );
155 if ( vrc6_enabled( this ) ) Vrc6_volume( &this->vrc6, adjusted_gain ); 181 if ( vrc6_enabled( this ) ) Vrc6_volume( &this->vrc6, adjusted_gain );
156 if ( fme7_enabled( this ) ) Fme7_volume( &this->fme7, adjusted_gain ); 182 if ( fme7_enabled( this ) ) Fme7_volume( &this->fme7, adjusted_gain );
@@ -179,9 +205,9 @@ static bool pal_only( struct header_t* this )
179 return (this->speed_flags & 3) == 1; 205 return (this->speed_flags & 3) == 1;
180} 206}
181 207
182static long clock_rate( struct header_t* this ) 208static int clock_rate( struct header_t* this )
183{ 209{
184 return pal_only( this ) ? (long)1662607.125 : (long)1789772.727272727; 210 return pal_only( this ) ? (int)1662607.125 : (int)1789772.727272727;
185} 211}
186 212
187static int play_period( struct header_t* this ) 213static int play_period( struct header_t* this )
@@ -227,7 +253,7 @@ static blargg_err_t check_nsf_header( struct header_t* h )
227 return 0; 253 return 0;
228} 254}
229 255
230blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size ) 256blargg_err_t Nsf_load_mem( struct Nsf_Emu* this, void* data, long size )
231{ 257{
232 // Unload 258 // Unload
233 Info_unload( &this->info ); // TODO: extremely hacky! 259 Info_unload( &this->info ); // TODO: extremely hacky!
@@ -258,11 +284,10 @@ blargg_err_t Nsf_post_load( struct Nsf_Emu* this )
258 warning( "Unknown file version" ); */ 284 warning( "Unknown file version" ); */
259 285
260 // set up data 286 // set up data
261 addr_t load_addr = get_le16( this->header.load_addr ); 287 addr_t load_addr = get_addr( this->header.load_addr );
262
263 /* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) ) 288 /* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) )
264 warning( "Load address is too low" ); */ 289 warning( "Load address is too low" ); */
265 290
266 Rom_set_addr( &this->rom, load_addr % this->rom.bank_size ); 291 Rom_set_addr( &this->rom, load_addr % this->rom.bank_size );
267 292
268 /* if ( header_.vers != 1 ) 293 /* if ( header_.vers != 1 )
@@ -277,17 +302,16 @@ blargg_err_t Nsf_post_load( struct Nsf_Emu* this )
277 302
278 // Post load 303 // Post load
279 Sound_set_tempo( this, this->tempo ); 304 Sound_set_tempo( this, this->tempo );
280
281 // Remute voices
282 Sound_mute_voices( this, this->mute_mask_ ); 305 Sound_mute_voices( this, this->mute_mask_ );
283 306
284 // Set track_count 307 // Set track_count
285 this->track_count = this->header.track_count; 308 this->track_count = this->header.track_count;
286 309
287 // Change clock rate & setup buffer 310 // Change clock rate & setup buffer
288 this->clock_rate__ = (long) clock_rate( &this->header ); 311 this->clock_rate__ = clock_rate( &this->header );
289 Buffer_clock_rate( &this->stereo_buf, this->clock_rate__ ); 312 Buffer_clock_rate( &this->stereo_buf, this->clock_rate__ );
290 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 313 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
314 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
291 return 0; 315 return 0;
292} 316}
293 317
@@ -416,11 +440,13 @@ static void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, str
416 return; 440 return;
417 } 441 }
418 442
419 if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 ) 443 #ifndef NSF_EMU_NO_VRC7
420 { 444 if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 )
421 Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf ); 445 {
422 return; 446 Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf );
423 } 447 return;
448 }
449 #endif
424 } 450 }
425 #endif 451 #endif
426} 452}
@@ -429,7 +455,7 @@ static void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, str
429 455
430// Music Emu 456// Music Emu
431 457
432blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate ) 458blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, int rate )
433{ 459{
434 require( !this->sample_rate ); // sample rate can't be changed once set 460 require( !this->sample_rate ); // sample rate can't be changed once set
435 Buffer_init( &this->stereo_buf ); 461 Buffer_init( &this->stereo_buf );
@@ -439,6 +465,8 @@ blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate )
439 Buffer_bass_freq( &this->stereo_buf, 80 ); 465 Buffer_bass_freq( &this->stereo_buf, 80 );
440 466
441 this->sample_rate = rate; 467 this->sample_rate = rate;
468 RETURN_ERR( track_init( &this->track_filter, this ) );
469 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
442 return 0; 470 return 0;
443} 471}
444 472
@@ -466,7 +494,7 @@ void Sound_mute_voices( struct Nsf_Emu* this, int mask )
466 } 494 }
467 else 495 else
468 { 496 {
469 struct channel_t ch = Buffer_channel( &this->stereo_buf ); 497 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
470 assert( (ch.center && ch.left && ch.right) || 498 assert( (ch.center && ch.left && ch.right) ||
471 (!ch.center && !ch.left && !ch.right) ); // all or nothing 499 (!ch.center && !ch.left && !ch.right) ); // all or nothing
472 set_voice( this, i, ch.center, ch.left, ch.right ); 500 set_voice( this, i, ch.center, ch.left, ch.right );
@@ -533,32 +561,13 @@ int cpu_read( struct Nsf_Emu* this, addr_t addr )
533 return addr >> 8; 561 return addr >> 8;
534} 562}
535 563
536#if 0 /* function currently unused */
537static int unmapped_read( struct Nsf_Emu* this, addr_t addr )
538{
539 (void) this;
540
541 switch ( addr )
542 {
543 case 0x2002:
544 case 0x4016:
545 case 0x4017:
546 return addr >> 8;
547 }
548
549 // Unmapped read
550 return addr >> 8;
551}
552#endif
553
554void cpu_write( struct Nsf_Emu* this, addr_t addr, int data ) 564void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
555{ 565{
556 #ifndef NSF_EMU_APU_ONLY 566 #ifndef NSF_EMU_APU_ONLY
557 { 567 {
558 nes_time_t time = Cpu_time( &this->cpu );
559 if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size ) 568 if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size )
560 { 569 {
561 Fds_write( &this->fds, time, addr, data ); 570 Fds_write( &this->fds, Cpu_time( &this->cpu ), addr, data );
562 return; 571 return;
563 } 572 }
564 573
@@ -572,7 +581,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
572 581
573 if ( addr == namco_data_reg_addr ) 582 if ( addr == namco_data_reg_addr )
574 { 583 {
575 Namco_write_data( &this->namco, time, data ); 584 Namco_write_data( &this->namco, Cpu_time( &this->cpu ), data );
576 return; 585 return;
577 } 586 }
578 } 587 }
@@ -583,7 +592,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
583 int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step; 592 int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step;
584 if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count ) 593 if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count )
585 { 594 {
586 Vrc6_write_osc( &this->vrc6, time, osc, reg, data ); 595 Vrc6_write_osc( &this->vrc6, Cpu_time( &this->cpu ), osc, reg, data );
587 return; 596 return;
588 } 597 }
589 } 598 }
@@ -597,7 +606,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
597 return; 606 return;
598 607
599 case fme7_data_addr: 608 case fme7_data_addr:
600 Fme7_write_data( &this->fme7, time, data ); 609 Fme7_write_data( &this->fme7, Cpu_time( &this->cpu ), data );
601 return; 610 return;
602 } 611 }
603 } 612 }
@@ -606,7 +615,7 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
606 { 615 {
607 if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size ) 616 if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size )
608 { 617 {
609 Mmc5_write_register( &this->mmc5, time, addr, data ); 618 Mmc5_write_register( &this->mmc5, Cpu_time( &this->cpu ), addr, data );
610 return; 619 return;
611 } 620 }
612 621
@@ -625,49 +634,28 @@ void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
625 } 634 }
626 } 635 }
627 636
628 if ( vrc7_enabled( this) ) 637 #ifndef NSF_EMU_NO_VRC7
629 { 638 if ( vrc7_enabled( this) )
630 if ( addr == 0x9010 )
631 { 639 {
632 Vrc7_write_reg( &this->vrc7, data ); 640 if ( addr == 0x9010 )
633 return; 641 {
634 } 642 Vrc7_write_reg( &this->vrc7, data );
643 return;
644 }
635 645
636 if ( (unsigned) (addr - 0x9028) <= 0x08 ) 646 if ( (unsigned) (addr - 0x9028) <= 0x08 )
637 { 647 {
638 Vrc7_write_data( &this->vrc7, time, data ); 648 Vrc7_write_data( &this->vrc7, Cpu_time( &this->cpu ), data );
639 return; 649 return;
650 }
640 } 651 }
641 } 652 #endif
642 } 653 }
643 #endif 654 #endif
644 655
645 // Unmapped_write 656 // Unmapped_write
646} 657}
647 658
648#if 0 /* function currently unused */
649static void unmapped_write( struct Nsf_Emu* this, addr_t addr, int data )
650{
651 (void) data;
652
653 switch ( addr )
654 {
655 case 0x8000: // some write to $8000 and $8001 repeatedly
656 case 0x8001:
657 case 0x4800: // probably namco sound mistakenly turned on in MCK
658 case 0xF800:
659 case 0xFFF8: // memory mapper?
660 return;
661 }
662
663 if ( mmc5_enabled( this ) && addr == 0x5115 ) return;
664
665 // FDS memory
666 if ( fds_enabled( this ) && (unsigned) (addr - 0x8000) < 0x6000 ) return;
667}
668#endif
669
670void fill_buf( struct Nsf_Emu* this );
671blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track ) 659blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track )
672{ 660{
673 clear_track_vars( this ); 661 clear_track_vars( this );
@@ -695,7 +683,9 @@ blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track )
695 if ( vrc6_enabled( this ) ) Vrc6_reset( &this->vrc6 ); 683 if ( vrc6_enabled( this ) ) Vrc6_reset( &this->vrc6 );
696 if ( fme7_enabled( this ) ) Fme7_reset( &this->fme7 ); 684 if ( fme7_enabled( this ) ) Fme7_reset( &this->fme7 );
697 if ( mmc5_enabled( this ) ) Apu_reset( &this->mmc5.apu, false, 0 ); 685 if ( mmc5_enabled( this ) ) Apu_reset( &this->mmc5.apu, false, 0 );
698 if ( vrc7_enabled( this ) ) Vrc7_reset( &this->vrc7 ); 686 #ifndef NSF_EMU_NO_VRC7
687 if ( vrc7_enabled( this ) ) Vrc7_reset( &this->vrc7 );
688 #endif
699 #endif 689 #endif
700 690
701 int speed_flags = 0; 691 int speed_flags = 0;
@@ -728,27 +718,15 @@ blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track )
728 /* if ( this->cpu.r.pc < get_addr( header.load_addr ) ) 718 /* if ( this->cpu.r.pc < get_addr( header.load_addr ) )
729 warning( "Init address < load address" ); */ 719 warning( "Init address < load address" ); */
730 720
731 this->emu_track_ended_ = false; 721 // convert filter times to samples
732 this->track_ended = false; 722 struct setup_t s = this->tfilter;
723 s.max_initial *= this->sample_rate * stereo;
724 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
725 s.lookahead = 1;
726 #endif
727 track_setup( &this->track_filter, &s );
733 728
734 if ( !this->ignore_silence ) 729 return track_start( &this->track_filter );
735 {
736 // play until non-silence or end of track
737 long end;
738 for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
739 {
740 fill_buf( this );
741 if ( this->buf_remain | (int) this->emu_track_ended_ )
742 break;
743 }
744
745 this->emu_time = this->buf_remain;
746 this->out_time = 0;
747 this->silence_time = 0;
748 this->silence_count = 0;
749 }
750 /* return track_ended() ? warning() : 0; */
751 return 0;
752} 730}
753 731
754void run_once( struct Nsf_Emu* this, nes_time_t end ) 732void run_once( struct Nsf_Emu* this, nes_time_t end )
@@ -831,265 +809,99 @@ static void end_frame( struct Nsf_Emu* this, nes_time_t end )
831 if ( mmc5_enabled( this ) ) Apu_end_frame( &this->mmc5.apu, end ); 809 if ( mmc5_enabled( this ) ) Apu_end_frame( &this->mmc5.apu, end );
832 if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end ); 810 if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end );
833 if ( vrc6_enabled( this ) ) Vrc6_end_frame( &this->vrc6, end ); 811 if ( vrc6_enabled( this ) ) Vrc6_end_frame( &this->vrc6, end );
812 #ifndef NSF_EMU_NO_VRC7
834 if ( vrc7_enabled( this ) ) Vrc7_end_frame( &this->vrc7, end ); 813 if ( vrc7_enabled( this ) ) Vrc7_end_frame( &this->vrc7, end );
814 #endif
835 #endif 815 #endif
836} 816}
837 817
838// Tell/Seek 818// Tell/Seek
839 819
840static blargg_long msec_to_samples( long sample_rate, blargg_long msec ) 820static int msec_to_samples( int msec, int sample_rate )
841{ 821{
842 blargg_long sec = msec / 1000; 822 int sec = msec / 1000;
843 msec -= sec * 1000; 823 msec -= sec * 1000;
844 return (sec * sample_rate + msec * sample_rate / 1000) * stereo; 824 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
845} 825}
846 826
847long Track_tell( struct Nsf_Emu* this ) 827int Track_tell( struct Nsf_Emu* this )
848{ 828{
849 blargg_long rate = this->sample_rate * stereo; 829 int rate = this->sample_rate * stereo;
850 blargg_long sec = this->out_time / rate; 830 int sec = track_sample_count( &this->track_filter ) / rate;
851 return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate; 831 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
852} 832}
853 833
854blargg_err_t Track_seek( struct Nsf_Emu* this, long msec ) 834blargg_err_t Track_seek( struct Nsf_Emu* this, int msec )
855{ 835{
856 blargg_long time = msec_to_samples( this->sample_rate, msec ); 836 int time = msec_to_samples( msec, this->sample_rate );
857 if ( time < this->out_time ) 837 if ( time < track_sample_count( &this->track_filter ) )
858 RETURN_ERR( Nsf_start_track( this, this->current_track ) ); 838 RETURN_ERR( Nsf_start_track( this, this->current_track ) );
859 return Track_skip( this, time - this->out_time ); 839 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
860} 840}
861 841
862blargg_err_t skip_( struct Nsf_Emu* this, long count ); 842blargg_err_t Track_skip( struct Nsf_Emu* this, int count )
863blargg_err_t Track_skip( struct Nsf_Emu* this, long count )
864{ 843{
865 require( this->current_track >= 0 ); // start_track() must have been called already 844 require( this->current_track >= 0 ); // start_track() must have been called already
866 this->out_time += count; 845 return track_skip( &this->track_filter, count );
867
868 // remove from silence and buf first
869 {
870 long n = min( count, this->silence_count );
871 this->silence_count -= n;
872 count -= n;
873
874 n = min( count, this->buf_remain );
875 this->buf_remain -= n;
876 count -= n;
877 }
878
879 if ( count && !this->emu_track_ended_ )
880 {
881 this->emu_time += count;
882 // End track if error
883 if ( skip_( this, count ) )
884 this->emu_track_ended_ = true;
885 }
886
887 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
888 this->track_ended |= this->emu_track_ended_;
889
890 return 0;
891} 846}
892 847
893blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ); 848blargg_err_t skip_( void *emu, int count )
894blargg_err_t skip_( struct Nsf_Emu* this, long count )
895{ 849{
850 struct Nsf_Emu* this = (struct Nsf_Emu*) emu;
851
896 // for long skip, mute sound 852 // for long skip, mute sound
897 const long threshold = 30000; 853 const int threshold = 32768;
898 if ( count > threshold ) 854 if ( count > threshold )
899 { 855 {
900 int saved_mute = this->mute_mask_; 856 int saved_mute = this->mute_mask_;
901 Sound_mute_voices( this, ~0 ); 857 Sound_mute_voices( this, ~0 );
902
903 while ( count > threshold / 2 && !this->emu_track_ended_ )
904 {
905 RETURN_ERR( play_( this, buf_size, this->buf ) );
906 count -= buf_size;
907 }
908
909 Sound_mute_voices( this, saved_mute );
910 }
911
912 while ( count && !this->emu_track_ended_ )
913 {
914 long n = buf_size;
915 if ( n > count )
916 n = count;
917 count -= n;
918 RETURN_ERR( play_( this, n, this->buf ) );
919 }
920 return 0;
921}
922
923// Fading
924 858
925void Track_set_fade( struct Nsf_Emu* this, long start_msec, long length_msec ) 859 int n = count - threshold/2;
926{ 860 n &= ~(2048-1); // round to multiple of 2048
927 this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo); 861 count -= n;
928 this->fade_start = msec_to_samples( this->sample_rate, start_msec ); 862 RETURN_ERR( skippy_( &this->track_filter, n ) );
929}
930
931// unit / pow( 2.0, (double) x / step )
932static int int_log( blargg_long x, int step, int unit )
933{
934 int shift = x / step;
935 int fraction = (x - shift * step) * unit / step;
936 return ((unit - fraction) + (fraction >> 1)) >> shift;
937}
938 863
939static void handle_fade( struct Nsf_Emu* this, long out_count, sample_t* out ) 864 Sound_mute_voices( this, saved_mute );
940{
941 int i;
942 for ( i = 0; i < out_count; i += fade_block_size )
943 {
944 int const shift = 14;
945 int const unit = 1 << shift;
946 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
947 this->fade_step, unit );
948 if ( gain < (unit >> fade_shift) )
949 this->track_ended = this->emu_track_ended_ = true;
950
951 sample_t* io = &out [i];
952 int count;
953 for ( count = min( fade_block_size, out_count - i ); count; --count )
954 {
955 *io = (sample_t) ((*io * gain) >> shift);
956 ++io;
957 }
958 } 865 }
959}
960
961// Silence detection
962 866
963void emu_play( struct Nsf_Emu* this, long count, sample_t* out ); 867 return skippy_( &this->track_filter, count );
964void emu_play( struct Nsf_Emu* this, long count, sample_t* out )
965{
966 check( current_track_ >= 0 );
967 this->emu_time += count;
968 if ( this->current_track >= 0 && !this->emu_track_ended_ ) {
969
970 // End track if error
971 if ( play_( this, count, out ) )
972 this->emu_track_ended_ = true;
973 }
974 else
975 memset( out, 0, count * sizeof *out );
976} 868}
977 869
978// number of consecutive silent samples at end 870// Fading
979static long count_silence( sample_t* begin, long size )
980{
981 sample_t first = *begin;
982 *begin = silence_threshold; // sentinel
983 sample_t* p = begin + size;
984 while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
985 *begin = first;
986 return size - (p - begin);
987}
988 871
989// fill internal buffer and check it for silence 872void Track_set_fade( struct Nsf_Emu* this, int start_msec, int length_msec )
990void fill_buf( struct Nsf_Emu* this )
991{ 873{
992 assert( !this->buf_remain ); 874 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
993 if ( !this->emu_track_ended_ ) 875 length_msec * this->sample_rate / (1000 / stereo) );
994 {
995 emu_play( this, buf_size, this->buf );
996 long silence = count_silence( this->buf, buf_size );
997 if ( silence < buf_size )
998 {
999 this->silence_time = this->emu_time - silence;
1000 this->buf_remain = buf_size;
1001 return;
1002 }
1003 }
1004 this->silence_count += buf_size;
1005} 876}
1006 877
1007blargg_err_t Nsf_play( struct Nsf_Emu* this, long out_count, sample_t* out ) 878blargg_err_t Nsf_play( struct Nsf_Emu* this, int out_count, sample_t* out )
1008{ 879{
1009 if ( this->track_ended ) 880 require( this->current_track >= 0 );
1010 { 881 require( out_count % stereo == 0 );
1011 memset( out, 0, out_count * sizeof *out ); 882 return track_play( &this->track_filter, out_count, out );
1012 }
1013 else
1014 {
1015 require( this->current_track >= 0 );
1016 require( out_count % stereo == 0 );
1017
1018 assert( this->emu_time >= this->out_time );
1019
1020 long pos = 0;
1021 if ( this->silence_count )
1022 {
1023 // during a run of silence, run emulator at >=2x speed so it gets ahead
1024 long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
1025 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
1026 fill_buf( this );
1027
1028 // fill with silence
1029 pos = min( this->silence_count, out_count );
1030 memset( out, 0, pos * sizeof *out );
1031 this->silence_count -= pos;
1032
1033 if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
1034 {
1035 this->track_ended = this->emu_track_ended_ = true;
1036 this->silence_count = 0;
1037 this->buf_remain = 0;
1038 }
1039 }
1040
1041 if ( this->buf_remain )
1042 {
1043 // empty silence buf
1044 long n = min( this->buf_remain, out_count - pos );
1045 memcpy( &out [pos], this->buf + (buf_size - this->buf_remain), n * sizeof *out );
1046 this->buf_remain -= n;
1047 pos += n;
1048 }
1049
1050 // generate remaining samples normally
1051 long remain = out_count - pos;
1052 if ( remain )
1053 {
1054 emu_play( this, remain, out + pos );
1055 this->track_ended |= this->emu_track_ended_;
1056
1057 if ( !this->ignore_silence || this->out_time > this->fade_start )
1058 {
1059 // check end for a new run of silence
1060 long silence = count_silence( out + pos, remain );
1061 if ( silence < remain )
1062 this->silence_time = this->emu_time - silence;
1063
1064 if ( this->emu_time - this->silence_time >= buf_size )
1065 fill_buf( this ); // cause silence detection on next play()
1066 }
1067 }
1068
1069 if ( this->out_time > this->fade_start )
1070 handle_fade( this, out_count, out );
1071 }
1072 this->out_time += out_count;
1073 return 0;
1074} 883}
1075 884
1076blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ) 885blargg_err_t play_( void* emu, int count, sample_t* out )
1077{ 886{
1078 long remain = count; 887 struct Nsf_Emu* this = (struct Nsf_Emu*) emu;
888
889 int remain = count;
1079 while ( remain ) 890 while ( remain )
1080 { 891 {
892 Buffer_disable_immediate_removal( &this->stereo_buf );
1081 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain ); 893 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
1082 if ( remain ) 894 if ( remain )
1083 { 895 {
1084 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) ) 896 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
1085 { 897 {
1086 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf ); 898 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
1087 899
1088 // Remute voices 900 // Remute voices
1089 Sound_mute_voices( this, this->mute_mask_ ); 901 Sound_mute_voices( this, this->mute_mask_ );
1090 } 902 }
1091 int msec = Buffer_length( &this->stereo_buf ); 903 int msec = Buffer_length( &this->stereo_buf );
1092 blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate__ / 1000 - 100; 904 blip_time_t clocks_emulated = msec * this->clock_rate__ / 1000 - 100;
1093 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) ); 905 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
1094 assert( clocks_emulated ); 906 assert( clocks_emulated );
1095 Buffer_end_frame( &this->stereo_buf, clocks_emulated ); 907 Buffer_end_frame( &this->stereo_buf, clocks_emulated );