diff options
-rw-r--r-- | apps/codecs/SOURCES | 2 | ||||
-rw-r--r-- | apps/codecs/libgme/resampler.c | 426 | ||||
-rw-r--r-- | apps/codecs/libgme/resampler.h | 74 | ||||
-rw-r--r-- | apps/codecs/libgme/vgm_emu.c | 59 | ||||
-rw-r--r-- | apps/codecs/libgme/vgm_emu.h | 6 | ||||
-rw-r--r-- | manual/appendix/file_formats.tex | 6 |
6 files changed, 229 insertions, 344 deletions
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES index 6862eeda8e..db6e82c75f 100644 --- a/apps/codecs/SOURCES +++ b/apps/codecs/SOURCES @@ -37,8 +37,8 @@ gbs.c hes.c nsf.c sgc.c -#if MEMORYSIZE > 2 vgm.c +#if MEMORYSIZE > 2 kss.c #endif diff --git a/apps/codecs/libgme/resampler.c b/apps/codecs/libgme/resampler.c index a69a92cc53..e2e0734fc9 100644 --- a/apps/codecs/libgme/resampler.c +++ b/apps/codecs/libgme/resampler.c @@ -25,294 +25,194 @@ enum { shift = 14 }; int const unit = 1 << shift; blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain ) - { - this->gain_ = (int)( ((1LL << gain_bits) * fm_gain * gain) / FP_ONE_GAIN ); - this->step = (int)( ((1LL << shift) * fm_rate) / rate + 1); - this->rate_ = this->step; - return 0; - } +{ + this->gain_ = (int)( ((1LL << gain_bits) * fm_gain * gain) / FP_ONE_GAIN ); + this->step = (int)( ((1LL << shift) * fm_rate) / rate + 1); + this->rate_ = this->step; + return 0; +} blargg_err_t Resampler_reset( struct Resampler* this, int pairs ) { - // expand allocations a bit - Resampler_resize( this, pairs ); - this->resampler_size = this->oversamples_per_frame + (this->oversamples_per_frame >> 2); - - this->buffer_size = this->resampler_size; - this->pos = 0; - this->write_pos = 0; - return 0; + // expand allocations a bit + this->sample_buffer_size = (pairs + (pairs >> 2)) * 2; + Resampler_resize( this, pairs ); + this->resampler_size = this->oversamples_per_frame + (this->oversamples_per_frame >> 2); + + this->buffer_size = this->resampler_size; + this->pos = 0; + this->write_pos = 0; + + Resampler_clear( this ); + return 0; } void Resampler_resize( struct Resampler* this, int pairs ) { - int new_sample_buf_size = pairs * 2; - if ( this->sample_buf_size != new_sample_buf_size ) - { - this->sample_buf_size = new_sample_buf_size; - this->oversamples_per_frame = (int) ((pairs * this->rate_ * 2LL) / unit) + 2; - Resampler_clear( this ); - } + int new_sample_buf_size = pairs * 2; + if ( this->sample_buf_size != new_sample_buf_size ) + { + if ( new_sample_buf_size > this->sample_buffer_size ) + { + check(false); + return; + } + + this->sample_buf_size = new_sample_buf_size; + this->oversamples_per_frame = (int) ((pairs * this->rate_ * 2LL) / unit) + 2; + Resampler_clear( this ); + } } -static void mix_mono( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) +void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t out_ [] ) { - int const bass = BLIP_READER_BASS( stereo_buf->bufs [0] ); - BLIP_READER_BEGIN( sn, stereo_buf->bufs [0] ); - - int count = this->sample_buf_size >> 1; - BLIP_READER_ADJ_( sn, count ); - - typedef dsample_t stereo_dsample_t [2]; - stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; - stereo_dsample_t const* BLARGG_RESTRICT in = - (stereo_dsample_t const*) this->sample_buf + count; - int offset = -count; - int const gain = this->gain_; - do - { - int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16); - BLIP_READER_NEXT_IDX_( sn, bass, offset ); - - int l = (in [offset] [0] * gain >> gain_bits) + s; - int r = (in [offset] [1] * gain >> gain_bits) + s; - - BLIP_CLAMP( l, l ); - out [offset] [0] = (blip_sample_t) l; - - BLIP_CLAMP( r, r ); - out [offset] [1] = (blip_sample_t) r; - } - while ( ++offset ); - - BLIP_READER_END( sn, stereo_buf->bufs [0] ); + int const bass = BLIP_READER_BASS( *blip_buf ); + BLIP_READER_BEGIN( sn, *blip_buf ); + + int count = this->sample_buf_size >> 1; + BLIP_READER_ADJ_( sn, count ); + + typedef sample_t stereo_dsample_t [2]; + stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; + stereo_dsample_t const* BLARGG_RESTRICT in = + (stereo_dsample_t const*) this->sample_buf + count; + int offset = -count; + int const gain = this->gain_; + do + { + int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16); + BLIP_READER_NEXT_IDX_( sn, bass, offset ); + + int l = (in [offset] [0] * gain >> gain_bits) + s; + int r = (in [offset] [1] * gain >> gain_bits) + s; + + BLIP_CLAMP( l, l ); + out [offset] [0] = (blip_sample_t) l; + + BLIP_CLAMP( r, r ); + out [offset] [1] = (blip_sample_t) r; + } + while ( ++offset ); + + BLIP_READER_END( sn, *blip_buf ); } -static void mix_stereo( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) +sample_t const* resample_( struct Resampler* this, sample_t** out_, + sample_t const* out_end, sample_t const in [], int in_size ) { - int const bass = BLIP_READER_BASS( stereo_buf->bufs [0] ); - BLIP_READER_BEGIN( snc, stereo_buf->bufs [0] ); - BLIP_READER_BEGIN( snl, stereo_buf->bufs [1] ); - BLIP_READER_BEGIN( snr, stereo_buf->bufs [2] ); - - int count = this->sample_buf_size >> 1; - BLIP_READER_ADJ_( snc, count ); - BLIP_READER_ADJ_( snl, count ); - BLIP_READER_ADJ_( snr, count ); - - typedef dsample_t stereo_dsample_t [2]; - stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; - stereo_dsample_t const* BLARGG_RESTRICT in = - (stereo_dsample_t const*) this->sample_buf + count; - int offset = -count; - int const gain = this->gain_; - do - { - int sc = BLIP_READER_READ_RAW( snc ) >> (blip_sample_bits - 16); - int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16); - int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16); - BLIP_READER_NEXT_IDX_( snc, bass, offset ); - BLIP_READER_NEXT_IDX_( snl, bass, offset ); - BLIP_READER_NEXT_IDX_( snr, bass, offset ); - - int l = (in [offset] [0] * gain >> gain_bits) + sl + sc; - int r = (in [offset] [1] * gain >> gain_bits) + sr + sc; - - BLIP_CLAMP( l, l ); - out [offset] [0] = (blip_sample_t) l; - - BLIP_CLAMP( r, r ); - out [offset] [1] = (blip_sample_t) r; - } - while ( ++offset ); - - BLIP_READER_END( snc, stereo_buf->bufs [0] ); - BLIP_READER_END( snl, stereo_buf->bufs [1] ); - BLIP_READER_END( snr, stereo_buf->bufs [2] ); + in_size -= write_offset; + if ( in_size > 0 ) + { + sample_t* BLARGG_RESTRICT out = *out_; + sample_t const* const in_end = in + in_size; + + int const step = this->step; + int pos = this->pos; + + // TODO: IIR filter, then linear resample + // TODO: detect skipped sample, allowing merging of IIR and resample? + + do + { + #define INTERP( i, out )\ + out = (in [0 + i] * (unit - pos) + ((in [2 + i] + in [4 + i] + in [6 + i]) << shift) +\ + in [8 + i] * pos) >> (shift + 2); + + int out_0; + INTERP( 0, out_0 ) + INTERP( 1, out [0] = out_0; out [1] ) + out += stereo; + + pos += step; + in += ((unsigned) pos >> shift) * stereo; + pos &= unit - 1; + } + while ( in < in_end && out < out_end ); + + this->pos = pos; + *out_ = out; + } + return in; } -static void mix_stereo_no_center( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out_ ) +inline int resample_wrapper( struct Resampler* this, sample_t out [], int* out_size, + sample_t const in [], int in_size ) { - int const bass = BLIP_READER_BASS( stereo_buf->bufs [0] ); - BLIP_READER_BEGIN( snl, stereo_buf->bufs [1] ); - BLIP_READER_BEGIN( snr, stereo_buf->bufs [2] ); - - int count = this->sample_buf_size >> 1; - BLIP_READER_ADJ_( snl, count ); - BLIP_READER_ADJ_( snr, count ); - - typedef dsample_t stereo_dsample_t [2]; - stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count; - stereo_dsample_t const* BLARGG_RESTRICT in = - (stereo_dsample_t const*) this->sample_buf + count; - int offset = -count; - int const gain = this->gain_; - do - { - int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16); - int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16); - BLIP_READER_NEXT_IDX_( snl, bass, offset ); - BLIP_READER_NEXT_IDX_( snr, bass, offset ); - - int l = (in [offset] [0] * gain >> gain_bits) + sl; - int r = (in [offset] [1] * gain >> gain_bits) + sr; - - BLIP_CLAMP( l, l ); - out [offset] [0] = (blip_sample_t) l; - - BLIP_CLAMP( r, r ); - out [offset] [1] = (blip_sample_t) r; - } - while ( ++offset ); - - BLIP_READER_END( snl, stereo_buf->bufs [1] ); - BLIP_READER_END( snr, stereo_buf->bufs [2] ); -} + assert( Resampler_rate( this ) ); -static dsample_t const* resample_( struct Resampler* this, dsample_t** out_, - dsample_t const* out_end, dsample_t const in [], int in_size ) -{ - in_size -= write_offset; - if ( in_size > 0 ) - { - dsample_t* BLIP_RESTRICT out = *out_; - dsample_t const* const in_end = in + in_size; - - int const step = this->step; - int pos = this->pos; - - // TODO: IIR filter, then linear resample - // TODO: detect skipped sample, allowing merging of IIR and resample? - - do - { - #define INTERP( i, out )\ - out = (in [0 + i] * (unit - pos) + ((in [2 + i] + in [4 + i] + in [6 + i]) << shift) +\ - in [8 + i] * pos) >> (shift + 2); - - int out_0; - INTERP( 0, out_0 ) - INTERP( 1, out [0] = out_0; out [1] ) - out += stereo; - - pos += step; - in += ((unsigned) pos >> shift) * stereo; - pos &= unit - 1; - } - while ( in < in_end && out < out_end ); - - this->pos = pos; - *out_ = out; - } - return in; -} + sample_t* out_ = out; + int result = resample_( this, &out_, out + *out_size, in, in_size ) - in; + assert( out_ <= out + *out_size ); + assert( result <= in_size ); -static inline int resample_wrapper( struct Resampler* this, dsample_t out [], int* out_size, - dsample_t const in [], int in_size ) -{ - assert( Resampler_rate( this ) ); - - dsample_t* out_ = out; - int result = resample_( this, &out_, out + *out_size, in, in_size ) - in; - assert( out_ <= out + *out_size ); - assert( result <= in_size ); - - *out_size = out_ - out; - return result; + *out_size = out_ - out; + return result; } -static int skip_input( struct Resampler* this, int count ) +int skip_input( struct Resampler* this, int count ) { - this->write_pos -= count; - if ( this->write_pos < 0 ) // occurs when downsampling - { - count += this->write_pos; - this->write_pos = 0; - } - memmove( this->buf, &this->buf [count], this->write_pos * sizeof this->buf [0] ); - return count; + this->write_pos -= count; + if ( this->write_pos < 0 ) // occurs when downsampling + { + count += this->write_pos; + this->write_pos = 0; + } + memmove( this->buf, &this->buf [count], this->write_pos * sizeof this->buf [0] ); + return count; } -static void play_frame_( struct Resampler* this, struct Stereo_Buffer* stereo_buf, dsample_t* out ) +void play_frame_( struct Resampler* this, struct Blip_Buffer* blip_buf, sample_t* out ) { - long pair_count = this->sample_buf_size >> 1; - blip_time_t blip_time = Blip_count_clocks( &stereo_buf->bufs [0], pair_count ); - int sample_count = this->oversamples_per_frame - this->write_pos + resampler_extra; - - int new_count = this->callback( this->callback_data, blip_time, sample_count, &this->buf [this->write_pos] ); - assert( new_count < resampler_size ); - - Buffer_end_frame( stereo_buf, blip_time ); - /* Blip_end_frame( &stereo_buf->bufs [0], blip_time ); */ - assert( Blip_samples_avail( &stereo_buf->bufs [0] ) == pair_count * 2 ); - - this->write_pos += new_count; - assert( (unsigned) this->write_pos <= this->buffer_size ); - - new_count = this->sample_buf_size; - if ( new_count ) - skip_input( this, resample_wrapper( this, this->sample_buf, &new_count, this->buf, this->write_pos ) ); - assert( new_count == (long) this->sample_buf_size ); - - int bufs_used = stereo_buf->stereo_added | stereo_buf->was_stereo; - if ( bufs_used <= 1 ) { - mix_mono( this, stereo_buf, out ); - Blip_remove_samples( &stereo_buf->bufs [0], pair_count ); - Blip_remove_silence( &stereo_buf->bufs [1], pair_count ); - Blip_remove_silence( &stereo_buf->bufs [2], pair_count ); - } - else if ( bufs_used & 1 ) { - mix_stereo( this, stereo_buf, out ); - Blip_remove_samples( &stereo_buf->bufs [0], pair_count ); - Blip_remove_samples( &stereo_buf->bufs [1], pair_count ); - Blip_remove_samples( &stereo_buf->bufs [2], pair_count ); - } - else { - mix_stereo_no_center( this, stereo_buf, out ); - Blip_remove_silence( &stereo_buf->bufs [0], pair_count ); - Blip_remove_samples( &stereo_buf->bufs [1], pair_count ); - Blip_remove_samples( &stereo_buf->bufs [2], pair_count ); - } - - // to do: this might miss opportunities for optimization - if ( !Blip_samples_avail( &stereo_buf->bufs [0] ) ) - { - stereo_buf->was_stereo = stereo_buf->stereo_added; - stereo_buf->stereo_added = 0; - } - - /* mix_mono( this, stereo_buf, out ); - Blip_remove_samples( &stereo_buf->bufs [0], pair_count ); */ + int pair_count = this->sample_buf_size >> 1; + blip_time_t blip_time = Blip_count_clocks( blip_buf, pair_count ); + int sample_count = this->oversamples_per_frame - this->write_pos + resampler_extra; + + int new_count = this->callback( this->callback_data, blip_time, sample_count, &this->buf [this->write_pos] ); + assert( new_count < this->resampler_size ); + + Blip_end_frame( blip_buf, blip_time ); + assert( Blip_samples_avail( blip_buf ) == pair_count ); + + this->write_pos += new_count; + assert( (unsigned) this->write_pos <= this->buffer_size ); + + int count = this->sample_buf_size; + if ( count ) + skip_input( this, resample_wrapper( this, this->sample_buf, &count, this->buf, this->write_pos ) ); + assert( count == this->sample_buf_size ); + + mix_samples( this, blip_buf, out ); + Blip_remove_samples( blip_buf, pair_count ); } -void Resampler_play( struct Resampler* this, long count, dsample_t* out, struct Stereo_Buffer* stereo_buf ) +void Resampler_play( struct Resampler* this, int count, sample_t* out, struct Blip_Buffer* blip_buf ) { - // empty extra buffer - long remain = this->sample_buf_size - this->buf_pos; - if ( remain ) - { - if ( remain > count ) - remain = count; - count -= remain; - memcpy( out, &this->sample_buf [this->buf_pos], remain * sizeof *out ); - out += remain; - this->buf_pos += remain; - } - - // entire frames - while ( count >= (long) this->sample_buf_size ) - { - play_frame_( this, stereo_buf, out ); - out += this->sample_buf_size; - count -= this->sample_buf_size; - } - - // extra - if ( count ) - { - play_frame_( this, stereo_buf, this->sample_buf ); - this->buf_pos = count; - memcpy( out, this->sample_buf, count * sizeof *out ); - out += count; - } + // empty extra buffer + int remain = this->sample_buf_size - this->buf_pos; + if ( remain ) + { + if ( remain > count ) + remain = count; + count -= remain; + memcpy( out, &this->sample_buf [this->buf_pos], remain * sizeof *out ); + out += remain; + this->buf_pos += remain; + } + + // entire frames + while ( count >= this->sample_buf_size ) + { + play_frame_( this, blip_buf, out ); + out += this->sample_buf_size; + count -= this->sample_buf_size; + } + + // extra + if ( count ) + { + play_frame_( this, blip_buf, this->sample_buf ); + this->buf_pos = count; + memcpy( out, this->sample_buf, count * sizeof *out ); + out += count; + } } diff --git a/apps/codecs/libgme/resampler.h b/apps/codecs/libgme/resampler.h index 3106b84d35..1d8f86670b 100644 --- a/apps/codecs/libgme/resampler.h +++ b/apps/codecs/libgme/resampler.h @@ -4,10 +4,10 @@ #ifndef RESAMPLER_H #define RESAMPLER_H -#include "blargg_config.h" +#include "blargg_common.h" #include "multi_buffer.h" -typedef short dsample_t; +typedef short sample_t; enum { stereo = 2 }; enum { max_buf_size = 3960 }; @@ -15,54 +15,62 @@ enum { max_resampler_size = 5942 }; enum { write_offset = 8 * stereo }; enum { gain_bits = 14 }; -struct Resampler { - int (*callback)( void*, blip_time_t, int, dsample_t* ); - void* callback_data; - - dsample_t sample_buf [max_buf_size]; - int sample_buf_size; - int oversamples_per_frame; - int buf_pos; - int resampler_size; - int gain_; - - // Internal resampler - dsample_t buf [max_resampler_size]; - int buffer_size; - - int write_pos; - int rate_; - - int pos; - int step; +struct Resampler { + int (*callback)( void*, blip_time_t, int, sample_t* ); + void* callback_data; + + int sample_buffer_size; + int sample_buf_size; + int oversamples_per_frame; + int buf_pos; + int resampler_size; + int gain_; + + int buffer_size; + int write_pos; + + int pos; + int step; + + int rate_; + + sample_t sample_buf [max_buf_size]; + sample_t buf [max_resampler_size]; // Internal resampler }; static inline void Resampler_init( struct Resampler* this ) { - this->pos = 0; - this->write_pos = 0; - this->rate_ = 0; + this->pos = 0; + this->write_pos = 0; + this->rate_ = 0; + this->sample_buf_size = 0; + this->sample_buffer_size = 0; + this->oversamples_per_frame = 0; } blargg_err_t Resampler_reset( struct Resampler* this, int max_pairs ); void Resampler_resize( struct Resampler* this, int pairs_per_frame ); - -void Resampler_play( struct Resampler* this, long count, dsample_t* out, struct Stereo_Buffer* ); +void Resampler_play( struct Resampler* this, int count, sample_t* out, struct Blip_Buffer* ); -static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, dsample_t* ), void* user_data ) +static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, sample_t* ), void* user_data ) { - this->callback = func; - this->callback_data = user_data; + this->callback = func; + this->callback_data = user_data; } blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain ); static inline void Resampler_clear( struct Resampler* this ) { - this->buf_pos = this->sample_buf_size; + this->buf_pos = this->sample_buf_size; + + this->pos = 0; + this->write_pos = 0; +} - this->pos = 0; - this->write_pos = 0; +static inline int Resampler_rate( struct Resampler* this ) +{ + return this->rate_; } #endif diff --git a/apps/codecs/libgme/vgm_emu.c b/apps/codecs/libgme/vgm_emu.c index d599056bca..391bd02d73 100644 --- a/apps/codecs/libgme/vgm_emu.c +++ b/apps/codecs/libgme/vgm_emu.c @@ -89,8 +89,7 @@ void Vgm_init( struct Vgm_Emu* this ) Synth_init( &this->pcm ); Buffer_init( &this->buf ); - Buffer_init( &this->stereo_buf ); - this->blip_buf = &this->stereo_buf.bufs [0]; + Blip_init( &this->blip_buf ); // Init fm chips Ym2413_init( &this->ym2413 ); @@ -279,7 +278,7 @@ blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_ if ( !this->psg_rate ) this->psg_rate = 3579545; - Buffer_clock_rate( &this->stereo_buf, this->psg_rate ); + Blip_set_clock_rate( &this->blip_buf, this->psg_rate ); // Disable FM this->fm_rate = 0; @@ -342,14 +341,14 @@ blargg_err_t setup_fm( struct Vgm_Emu* this ) { int fm_rate = 0; if ( !this->disable_oversampling ) - this->fm_rate = (this->sample_rate * 3) / 2; // oversample factor = 1.5 + fm_rate = (this->sample_rate * 3) / 2; // oversample factor = 1.5 RETURN_ERR( init_fm( this, &fm_rate ) ); if ( uses_fm( this ) ) { this->voice_count = 8; RETURN_ERR( Resampler_setup( &this->resampler, fm_rate, fm_gain, this->sample_rate, this->gain ) ); - RETURN_ERR( Resampler_reset( &this->resampler, Buffer_length( &this->stereo_buf ) * this->sample_rate / 1000 ) ); + RETURN_ERR( Resampler_reset( &this->resampler, Blip_length( &this->blip_buf ) * this->sample_rate / 1000 ) ); Sms_apu_volume( &this->psg, ((this->gain/5)-(this->gain*5)/1000) * fm_gain ); } else @@ -399,7 +398,7 @@ static blargg_err_t play_( struct Vgm_Emu* this, long count, sample_t* out ) return 0; } - Resampler_play( &this->resampler, count, out, &this->stereo_buf ); + Resampler_play( &this->resampler, count, out, &this->blip_buf ); return 0; } @@ -428,19 +427,16 @@ static inline blip_time_t to_psg_time( struct Vgm_Emu* this, vgm_time_t t ) static void write_pcm( struct Vgm_Emu* this, vgm_time_t vgm_time, int amp ) { - if ( this->blip_buf ) - { - check( amp >= 0 ); - blip_time_t blip_time = to_psg_time( this, vgm_time ); - int old = this->dac_amp; - int delta = amp - old; - this->dac_amp = amp; - Blip_set_modified( this->blip_buf ); - if ( old >= 0 ) // first write is ignored, to avoid click - Synth_offset_inline( &this->pcm, blip_time, delta, this->blip_buf ); - else - this->dac_amp |= this->dac_disabled; - } + check( amp >= 0 ); + blip_time_t blip_time = to_psg_time( this, vgm_time ); + int old = this->dac_amp; + int delta = amp - old; + this->dac_amp = amp; + Blip_set_modified( &this->blip_buf ); + if ( old >= 0 ) // first write is ignored, to avoid click + Synth_offset_inline( &this->pcm, blip_time, delta, &this->blip_buf ); + else + this->dac_amp |= this->dac_disabled; } blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time ) @@ -514,22 +510,7 @@ blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time ) case cmd_ym2612_port1: if ( Ym2612_run_until( &this->ym2612, to_fm_time( this, vgm_time ) ) ) - { - if ( pos [0] == ym2612_dac_pan_port ) - { - struct Blip_Buffer* blip_buf = NULL; - switch ( pos [1] >> 6 ) - { - case 0: blip_buf = NULL; break; - case 1: blip_buf = &this->stereo_buf.bufs [2]; break; - case 2: blip_buf = &this->stereo_buf.bufs [1]; break; - case 3: blip_buf = &this->stereo_buf.bufs [0]; break; - } - this->blip_buf = blip_buf; - } - Ym2612_write1( &this->ym2612, pos [0], pos [1] ); - } pos += 2; break; @@ -664,7 +645,7 @@ void update_fm_rates( struct Vgm_Emu* this, int* ym2413_rate, int* ym2612_rate ) blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long rate ) { require( !this->sample_rate ); // sample rate can't be changed once set - RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 30 ) ); + RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) ); RETURN_ERR( Buffer_set_sample_rate( &this->buf, rate, 1000 / 20 ) ); // Set bass frequency @@ -712,7 +693,7 @@ void Sound_mute_voices( struct Vgm_Emu* this, int mask ) if ( uses_fm( this ) ) { for ( i = sms_osc_count; --i >= 0; ) - Sms_apu_set_output( &this->psg, i, ( mask & 0x80 ) ? 0 : &this->stereo_buf.bufs [0], NULL, NULL ); + Sms_apu_set_output( &this->psg, i, ( mask & 0x80 ) ? 0 : &this->blip_buf, NULL, NULL ); if ( Ym2612_enabled( &this->ym2612 ) ) { Synth_volume( &this->pcm, (mask & 0x40) ? 0 : (int)((long long)(0.1115*FP_ONE_VOLUME) / 256 * fm_gain * this->gain / FP_ONE_VOLUME) ); @@ -743,7 +724,7 @@ void Sound_set_tempo( struct Vgm_Emu* this, int t ) if ( this->file_begin ) { this->vgm_rate = (long) ((44100LL * t) / FP_ONE_TEMPO); - this->blip_time_factor = (int) (((1LL << blip_time_bits) * Blip_clock_rate( &this->stereo_buf.bufs [0] )) / this->vgm_rate); + this->blip_time_factor = (int) (((1LL << blip_time_bits) * Blip_clock_rate( &this->blip_buf )) / this->vgm_rate); //debug_printf( "blip_time_factor: %ld\n", blip_time_factor ); //debug_printf( "vgm_rate: %ld\n", vgm_rate ); // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only) @@ -761,8 +742,6 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this ) Sms_apu_reset( &this->psg, get_le16( header( this )->noise_feedback ), header( this )->noise_width ); - this->blip_buf = &this->stereo_buf.bufs [0]; - this->dac_disabled = -1; this->pos = this->file_begin + header_size; this->pcm_data = this->pos; @@ -785,7 +764,7 @@ blargg_err_t Vgm_start_track( struct Vgm_Emu* this ) if ( Ym2612_enabled( &this->ym2612 ) ) Ym2612_reset( &this->ym2612 ); - Buffer_clear( &this->stereo_buf ); + Blip_clear( &this->blip_buf, 1 ); Resampler_clear( &this->resampler ); } diff --git a/apps/codecs/libgme/vgm_emu.h b/apps/codecs/libgme/vgm_emu.h index bc04086e9d..773b850a09 100644 --- a/apps/codecs/libgme/vgm_emu.h +++ b/apps/codecs/libgme/vgm_emu.h @@ -12,7 +12,6 @@ #include "ym2612_emu.h" #include "sms_apu.h" -typedef short sample_t; typedef int vgm_time_t; typedef int fm_time_t; @@ -85,7 +84,7 @@ struct Vgm_Emu { int dac_amp; int dac_disabled; // -1 if disabled - struct Blip_Buffer* blip_buf; + struct Blip_Buffer blip_buf; // general long clock_rate_; @@ -124,10 +123,7 @@ struct Vgm_Emu { struct Sms_Apu psg; struct Blip_Synth pcm; - struct Stereo_Buffer stereo_buf; - struct Resampler resampler; - struct Stereo_Buffer buf; }; diff --git a/manual/appendix/file_formats.tex b/manual/appendix/file_formats.tex index f75bd53786..8062694e32 100644 --- a/manual/appendix/file_formats.tex +++ b/manual/appendix/file_formats.tex @@ -227,13 +227,12 @@ & \fname{.sgc} & Supports Sega Master System and Game Gear Sound Format. Progress bar and seek use subtracks instead of seconds.\\ - \nopt{clipv1,c200v2}{ Video Game Music Format & \fname{.vgm} & \\ Gzipped Video Game Music Format & \fname{.vgz} - & \\} + & \\ MOD & \fname{.mod} & \\ @@ -251,6 +250,9 @@ & \\ \end{rbtabular} + \note{NSF and VGM might not play in realtime on all devices due to CPU + performance requirements.} + \subsection{Codec featureset} \begin{rbtabular}{.95\textwidth}{lXXX}% {\textbf{Format} & \textbf{Seek} & \textbf{Resume} & \textbf{Gapless}}{}{} |