diff options
| author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-07 20:01:04 +0000 |
|---|---|---|
| committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-07 20:01:04 +0000 |
| commit | acb0917556fc33681c1df5a530cf754193e67705 (patch) | |
| tree | 052a47097009a210e4aed9c207bd6aa4828cc000 /apps/codecs/libgme/multi_buffer.c | |
| parent | 93c6f1329a5691a8be158cefe15641bd1daf9ef8 (diff) | |
| download | rockbox-acb0917556fc33681c1df5a530cf754193e67705.zip rockbox-acb0917556fc33681c1df5a530cf754193e67705.tar.gz rockbox-acb0917556fc33681c1df5a530cf754193e67705.tar.bz2 rockbox-acb0917556fc33681c1df5a530cf754193e67705.tar.xz | |
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
Diffstat (limited to 'apps/codecs/libgme/multi_buffer.c')
| -rw-r--r-- | apps/codecs/libgme/multi_buffer.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/apps/codecs/libgme/multi_buffer.c b/apps/codecs/libgme/multi_buffer.c new file mode 100644 index 0000000..26cb8cd --- /dev/null +++ b/apps/codecs/libgme/multi_buffer.c @@ -0,0 +1,226 @@ +// Blip_Buffer 0.4.1. http://www.slack.net/~ant/ + +#include "multi_buffer.h" + +/* 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 */ + +#include "blargg_source.h" + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +// Stereo_Buffer + +void Buffer_init( struct Stereo_Buffer* this ) +{ + Blip_init( &this->bufs [0] ); + Blip_init( &this->bufs [1] ); + Blip_init( &this->bufs [2] ); + + this->chan.center = &this->bufs [0]; + this->chan.left = &this->bufs [1]; + this->chan.right = &this->bufs [2]; + + this->length_ = 0; + this->sample_rate_ = 0; + this->channels_changed_count_ = 1; + this->samples_per_frame_ = 2; +} + +blargg_err_t Buffer_set_sample_rate( struct Stereo_Buffer* this, long rate, int msec ) +{ + int i; + for ( i = 0; i < buf_count; i++ ) + RETURN_ERR( Blip_set_sample_rate( &this->bufs[i], rate, msec ) ); + + this->sample_rate_ = Blip_sample_rate( &this->bufs [0] ); + this->length_ = Blip_length( &this->bufs [0] ); + return 0; +} + +void Buffer_clock_rate( struct Stereo_Buffer* this, long rate ) +{ + int i; + for ( i = 0; i < buf_count; i++ ) + Blip_set_clock_rate( &this->bufs [i], rate ); +} + +void Buffer_bass_freq( struct Stereo_Buffer* this, int bass ) +{ + unsigned i; + for ( i = 0; i < buf_count; i++ ) + Blip_bass_freq( &this->bufs [i], bass ); +} + +struct channel_t Buffer_channel( struct Stereo_Buffer* this ) +{ + return this->chan; +} + +void Buffer_clear( struct Stereo_Buffer* this ) +{ + this->stereo_added = 0; + this->was_stereo = false; + int i; + for ( i = 0; i < buf_count; i++ ) + Blip_clear( &this->bufs [i], 1 ); +} + +void Buffer_end_frame( struct Stereo_Buffer* this, blip_time_t clock_count ) +{ + this->stereo_added = 0; + unsigned i; + for ( i = 0; i < buf_count; i++ ) + { + this->stereo_added |= Blip_clear_modified( &this->bufs [i] ) << i; + Blip_end_frame( &this->bufs [i], clock_count ); + } +} + +long Buffer_read_samples( struct Stereo_Buffer* this, blip_sample_t* out, long count ) +{ + require( !(count & 1) ); // count must be even + count = (unsigned) count / 2; + + long avail = Blip_samples_avail( &this->bufs [0] ); + if ( count > avail ) + count = avail; + if ( count ) + { + int bufs_used = this->stereo_added | this->was_stereo; + //dprintf( "%X\n", bufs_used ); + if ( bufs_used <= 1 ) + { + Buffer_mix_mono( this, out, count ); + Blip_remove_samples( &this->bufs [0], count ); + Blip_remove_silence( &this->bufs [1], count ); + Blip_remove_silence( &this->bufs [2], count ); + } + else if ( bufs_used & 1 ) + { + Buffer_mix_stereo( this, out, count ); + Blip_remove_samples( &this->bufs [0], count ); + Blip_remove_samples( &this->bufs [1], count ); + Blip_remove_samples( &this->bufs [2], count ); + } + else + { + Buffer_mix_stereo_no_center( this, out, count ); + Blip_remove_silence( &this->bufs [0], count ); + Blip_remove_samples( &this->bufs [1], count ); + Blip_remove_samples( &this->bufs [2], count ); + } + + // to do: this might miss opportunities for optimization + if ( !Blip_samples_avail( &this->bufs [0] ) ) + { + this->was_stereo = this->stereo_added; + this->stereo_added = 0; + } + } + + return count * 2; +} + +unsigned Buffer_channels_changed_count( struct Stereo_Buffer* this ) +{ + return this->channels_changed_count_; +} + +void Buffer_channels_changed( struct Stereo_Buffer* this ) +{ + this->channels_changed_count_++; +} + +void Buffer_mix_stereo( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count ) +{ + blip_sample_t* BLIP_RESTRICT out = out_; + int const bass = BLIP_READER_BASS( this->bufs [1] ); + BLIP_READER_BEGIN( left, this->bufs [1] ); + BLIP_READER_BEGIN( right, this->bufs [2] ); + BLIP_READER_BEGIN( center, this->bufs [0] ); + + for ( ; count; --count ) + { + int c = BLIP_READER_READ( center ); + blargg_long l = c + BLIP_READER_READ( left ); + blargg_long r = c + BLIP_READER_READ( right ); + if ( (int16_t) l != l ) + l = 0x7FFF - (l >> 24); + + BLIP_READER_NEXT( center, bass ); + if ( (int16_t) r != r ) + r = 0x7FFF - (r >> 24); + + BLIP_READER_NEXT( left, bass ); + BLIP_READER_NEXT( right, bass ); + + out [0] = l; + out [1] = r; + out += 2; + } + + BLIP_READER_END( center, this->bufs [0] ); + BLIP_READER_END( right, this->bufs [2] ); + BLIP_READER_END( left, this->bufs [1] ); +} + +void Buffer_mix_stereo_no_center( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count ) +{ + blip_sample_t* BLIP_RESTRICT out = out_; + int const bass = BLIP_READER_BASS( this->bufs [1] ); + BLIP_READER_BEGIN( left, this->bufs [1] ); + BLIP_READER_BEGIN( right, this->bufs [2] ); + + for ( ; count; --count ) + { + blargg_long l = BLIP_READER_READ( left ); + if ( (int16_t) l != l ) + l = 0x7FFF - (l >> 24); + + blargg_long r = BLIP_READER_READ( right ); + if ( (int16_t) r != r ) + r = 0x7FFF - (r >> 24); + + BLIP_READER_NEXT( left, bass ); + BLIP_READER_NEXT( right, bass ); + + out [0] = l; + out [1] = r; + out += 2; + } + + BLIP_READER_END( right, this->bufs [2] ); + BLIP_READER_END( left, this->bufs [1] ); +} + +void Buffer_mix_mono( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count ) +{ + blip_sample_t* BLIP_RESTRICT out = out_; + int const bass = BLIP_READER_BASS( this->bufs [0] ); + BLIP_READER_BEGIN( center, this->bufs [0] ); + + for ( ; count; --count ) + { + blargg_long s = BLIP_READER_READ( center ); + if ( (int16_t) s != s ) + s = 0x7FFF - (s >> 24); + + BLIP_READER_NEXT( center, bass ); + out [0] = s; + out [1] = s; + out += 2; + } + + BLIP_READER_END( center, this->bufs [0] ); +} |