From acb0917556fc33681c1df5a530cf754193e67705 Mon Sep 17 00:00:00 2001 From: Andree Buschmann Date: Sun, 7 Aug 2011 20:01:04 +0000 Subject: Submit initial patch from FS#12176. Adds support for several new game music formats (AY, GBS, HES, KSS, SGC, VGM and VGZ) and replaces the current NSF and NSFE with a new implementation based on a port of the Game Music Emu library 'GME'. This first submit does not cover the full functionality provided by the author's original patch: Coleco-SGV is not supported, some GME-specific m3u-support has been removed and IRAM is not used yet. Further changes are very likely to follow this submit. Thanks to Mauricio Garrido. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30264 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs/libgme/blip_buffer.c | 285 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 apps/codecs/libgme/blip_buffer.c (limited to 'apps/codecs/libgme/blip_buffer.c') diff --git a/apps/codecs/libgme/blip_buffer.c b/apps/codecs/libgme/blip_buffer.c new file mode 100644 index 0000000000..3061f68573 --- /dev/null +++ b/apps/codecs/libgme/blip_buffer.c @@ -0,0 +1,285 @@ +// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ + +#include "blip_buffer.h" + +#include +#include +#include +#include +#include + +/* Copyright (C) 2003-2006 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +int const silent_buf_size = 1; // size used for Silent_Blip_Buffer + +void Blip_init( struct Blip_Buffer* this ) +{ + this->factor_ = LONG_MAX; + this->offset_ = 0; + this->buffer_size_ = 0; + this->sample_rate_ = 0; + this->reader_accum_ = 0; + this->bass_shift_ = 0; + this->clock_rate_ = 0; + this->bass_freq_ = 16; + this->length_ = 0; + + // assumptions code makes about implementation-defined features + #ifndef NDEBUG + // right shift of negative value preserves sign + buf_t_ i = -0x7FFFFFFE; + assert( (i >> 1) == -0x3FFFFFFF ); + + // casting to short truncates to 16 bits and sign-extends + i = 0x18000; + assert( (short) i == -0x8000 ); + #endif +} + +void Blip_stop( struct Blip_Buffer* this ) +{ + if ( this->buffer_size_ != silent_buf_size ) + free( this->buffer_ ); +} + +void Blip_clear( struct Blip_Buffer* this, int entire_buffer ) +{ + this->offset_ = 0; + this->reader_accum_ = 0; + this->modified_ = 0; + if ( this->buffer_ ) + { + long count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this )); + memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) ); + } +} + +blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, long new_rate, int msec ) +{ + if ( this->buffer_size_ == silent_buf_size ) + { + assert( 0 ); + return "Internal (tried to resize Silent_Blip_Buffer)"; + } + + // start with maximum length that resampled time can represent + long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64; + if ( msec != blip_max_length ) + { + long s = (new_rate * (msec + 1) + 999) / 1000; + if ( s < new_size ) + new_size = s; + else + assert( 0 ); // fails if requested buffer length exceeds limit + } + + if ( new_size > blip_buffer_max ) + return "Out of memory"; + + this->buffer_size_ = new_size; + assert( this->buffer_size_ != silent_buf_size ); + + // update things based on the sample rate + this->sample_rate_ = new_rate; + this->length_ = new_size * 1000 / new_rate - 1; + if ( msec ) + assert( this->length_ == msec ); // ensure length is same as that passed in + if ( this->clock_rate_ ) + Blip_set_clock_rate( this, this->clock_rate_ ); + Blip_bass_freq( this, this->bass_freq_ ); + + Blip_clear( this, 1 ); + + return 0; // success +} + +/* Not sure if this affects sound quality */ +#if defined(ROCKBOX) +double floor(double x) { + if ( x > 0 ) return (int)x; + return (int)(x-0.9999999999999999); +} +#endif + +blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, long rate ) +{ + double ratio = (double) this->sample_rate_ / rate; + blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 ); + assert( factor > 0 || !this->sample_rate_ ); // fails if clock/output ratio is too large + return (blip_resampled_time_t) factor; +} + +void Blip_bass_freq( struct Blip_Buffer* this, int freq ) +{ + this->bass_freq_ = freq; + int shift = 31; + if ( freq > 0 ) + { + shift = 13; + long f = (freq << 16) / this->sample_rate_; + while ( (f >>= 1) && --shift ) { } + } + this->bass_shift_ = shift; +} + +void Blip_end_frame( struct Blip_Buffer* this, blip_time_t t ) +{ + this->offset_ += t * this->factor_; + assert( Blip_samples_avail( this ) <= (long) this->buffer_size_ ); // time outside buffer length +} + +void Blip_remove_silence( struct Blip_Buffer* this, long count ) +{ + assert( count <= Blip_samples_avail( this ) ); // tried to remove more samples than available + this->offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; +} + +long Blip_count_samples( struct Blip_Buffer* this, blip_time_t t ) +{ + unsigned long last_sample = Blip_resampled_time( this, t ) >> BLIP_BUFFER_ACCURACY; + unsigned long first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY; + return (long) (last_sample - first_sample); +} + +blip_time_t Blip_count_clocks( struct Blip_Buffer* this, long count ) +{ + if ( !this->factor_ ) + { + assert( 0 ); // sample rate and clock rates must be set first + return 0; + } + + if ( count > this->buffer_size_ ) + count = this->buffer_size_; + blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; + return (blip_time_t) ((time - this->offset_ + this->factor_ - 1) / this->factor_); +} + +void Blip_remove_samples( struct Blip_Buffer* this, long count ) +{ + if ( count ) + { + Blip_remove_silence( this, count ); + + // copy remaining samples to beginning and clear old samples + long remain = Blip_samples_avail( this ) + blip_buffer_extra_; + memmove( this->buffer_, this->buffer_ + count, remain * sizeof *this->buffer_ ); + memset( this->buffer_ + remain, 0, count * sizeof *this->buffer_ ); + } +} + +long Blip_read_samples( struct Blip_Buffer* this, blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo ) +{ + long count = Blip_samples_avail( this ); + if ( count > max_samples ) + count = max_samples; + + if ( count ) + { + int const bass = BLIP_READER_BASS( *this ); + BLIP_READER_BEGIN( reader, *this ); + + if ( !stereo ) + { + blip_long n; + for ( n = count; n; --n ) + { + blip_long s = BLIP_READER_READ( reader ); + if ( (blip_sample_t) s != s ) + s = 0x7FFF - (s >> 24); + *out++ = (blip_sample_t) s; + BLIP_READER_NEXT( reader, bass ); + } + } + else + { + blip_long n; + for ( n = count; n; --n ) + { + blip_long s = BLIP_READER_READ( reader ); + if ( (blip_sample_t) s != s ) + s = 0x7FFF - (s >> 24); + *out = (blip_sample_t) s; + out += 2; + BLIP_READER_NEXT( reader, bass ); + } + } + BLIP_READER_END( reader, *this ); + + Blip_remove_samples( this, count ); + } + return count; +} + +void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const* in, long count ) +{ + if ( this->buffer_size_ == silent_buf_size ) + { + assert( 0 ); + return; + } + + buf_t_* out = this->buffer_ + (this->offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2; + + int const sample_shift = blip_sample_bits - 16; + int prev = 0; + while ( count-- ) + { + blip_long s = (blip_long) *in++ << sample_shift; + *out += s - prev; + prev = s; + ++out; + } + *out -= prev; +} + +void Blip_set_modified( struct Blip_Buffer* this ) +{ + this->modified_ = 1; +} + +int Blip_clear_modified( struct Blip_Buffer* this ) +{ + int b = this->modified_; + this->modified_ = 0; + return b; +} + +blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t ) +{ + return t * this->factor_; +} + +blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t ) +{ + return t * this->factor_ + this->offset_; +} + + +// Blip_Synth + +void Synth_init( struct Blip_Synth* this ) +{ + this->buf = 0; + this->last_amp = 0; + this->delta_factor = 0; +} + +// Set overall volume of waveform +void Synth_volume( struct Blip_Synth* this, double v ) +{ + this->delta_factor = (int) (v * (1L << blip_sample_bits) + 0.5); +} -- cgit v1.2.3