summaryrefslogtreecommitdiff
path: root/plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.cpp')
-rw-r--r--plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.cpp235
1 files changed, 235 insertions, 0 deletions
diff --git a/plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.cpp b/plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.cpp
new file mode 100644
index 00000000..ed760afd
--- /dev/null
+++ b/plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.cpp
@@ -0,0 +1,235 @@
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+#include "Music_Emu.h"
+
+/* Copyright (C) 2003-2008 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"
+
+int const stereo = 2; // number of channels for stereo
+
+Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180 };
+
+void Music_Emu::clear_track_vars()
+{
+ current_track_ = -1;
+ warning(); // clear warning
+ track_filter.stop();
+}
+
+void Music_Emu::unload()
+{
+ voice_count_ = 0;
+ clear_track_vars();
+ Gme_File::unload();
+}
+
+Music_Emu::gme_t()
+{
+ effects_buffer_ = NULL;
+ sample_rate_ = 0;
+ mute_mask_ = 0;
+ tempo_ = 1.0;
+ gain_ = 1.0;
+
+ // defaults
+ tfilter = track_filter.setup();
+ set_max_initial_silence( 15 );
+ set_silence_lookahead( 3 );
+ ignore_silence( false );
+
+ equalizer_.treble = -1.0;
+ equalizer_.bass = 60;
+
+ static const char* const names [] = {
+ "Voice 1", "Voice 2", "Voice 3", "Voice 4",
+ "Voice 5", "Voice 6", "Voice 7", "Voice 8"
+ };
+ set_voice_names( names );
+ Music_Emu::unload(); // clears fields
+}
+
+Music_Emu::~gme_t()
+{
+ assert( !effects_buffer_ );
+}
+
+blargg_err_t Music_Emu::set_sample_rate( int rate )
+{
+ require( !sample_rate() ); // sample rate can't be changed once set
+ RETURN_ERR( set_sample_rate_( rate ) );
+ RETURN_ERR( track_filter.init( this ) );
+ sample_rate_ = rate;
+ tfilter.max_silence = 6 * stereo * sample_rate();
+ return blargg_ok;
+}
+
+void Music_Emu::pre_load()
+{
+ require( sample_rate() ); // set_sample_rate() must be called before loading a file
+ Gme_File::pre_load();
+}
+
+void Music_Emu::set_equalizer( equalizer_t const& eq )
+{
+ // TODO: why is GCC generating memcpy call here?
+ // Without the 'if', valgrind flags it.
+ if ( &eq != &equalizer_ )
+ equalizer_ = eq;
+ set_equalizer_( eq );
+}
+
+void Music_Emu::mute_voice( int index, bool mute )
+{
+ require( (unsigned) index < (unsigned) voice_count() );
+ int bit = 1 << index;
+ int mask = mute_mask_ | bit;
+ if ( !mute )
+ mask ^= bit;
+ mute_voices( mask );
+}
+
+void Music_Emu::mute_voices( int mask )
+{
+ require( sample_rate() ); // sample rate must be set first
+ mute_mask_ = mask;
+ mute_voices_( mask );
+}
+
+const char* Music_Emu::voice_name( int i ) const
+{
+ if ( (unsigned) i < (unsigned) voice_count_ )
+ return voice_names_ [i];
+
+ //check( false ); // TODO: enable?
+ return "";
+}
+
+void Music_Emu::set_tempo( double t )
+{
+ require( sample_rate() ); // sample rate must be set first
+ double const min = 0.02;
+ double const max = 4.00;
+ if ( t < min ) t = min;
+ if ( t > max ) t = max;
+ tempo_ = t;
+ set_tempo_( t );
+}
+
+blargg_err_t Music_Emu::post_load()
+{
+ set_tempo( tempo_ );
+ remute_voices();
+ return Gme_File::post_load();
+}
+
+// Tell/Seek
+
+int Music_Emu::msec_to_samples( int msec ) const
+{
+ int sec = msec / 1000;
+ msec -= sec * 1000;
+ return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
+}
+
+int Music_Emu::tell() const
+{
+ int rate = sample_rate() * stereo;
+ int sec = track_filter.sample_count() / rate;
+ return sec * 1000 + (track_filter.sample_count() - sec * rate) * 1000 / rate;
+}
+
+blargg_err_t Music_Emu::seek( int msec )
+{
+ int time = msec_to_samples( msec );
+ if ( time < track_filter.sample_count() )
+ RETURN_ERR( start_track( current_track_ ) );
+ return skip( time - track_filter.sample_count() );
+}
+
+blargg_err_t Music_Emu::skip( int count )
+{
+ require( current_track() >= 0 ); // start_track() must have been called already
+ return track_filter.skip( count );
+}
+
+blargg_err_t Music_Emu::skip_( int count )
+{
+ // for long skip, mute sound
+ const int threshold = 32768;
+ if ( count > threshold )
+ {
+ int saved_mute = mute_mask_;
+ mute_voices( ~0 );
+
+ int n = count - threshold/2;
+ n &= ~(2048-1); // round to multiple of 2048
+ count -= n;
+ RETURN_ERR( track_filter.skip_( n ) );
+
+ mute_voices( saved_mute );
+ }
+
+ return track_filter.skip_( count );
+}
+
+// Playback
+
+blargg_err_t Music_Emu::start_track( int track )
+{
+ clear_track_vars();
+
+ int remapped = track;
+ RETURN_ERR( remap_track_( &remapped ) );
+ current_track_ = track;
+ blargg_err_t err = start_track_( remapped );
+ if ( err )
+ {
+ current_track_ = -1;
+ return err;
+ }
+
+ // convert filter times to samples
+ Track_Filter::setup_t s = tfilter;
+ s.max_initial *= sample_rate() * stereo;
+ #if GME_DISABLE_SILENCE_LOOKAHEAD
+ s.lookahead = 1;
+ #endif
+ track_filter.setup( s );
+
+ return track_filter.start_track();
+}
+
+void Music_Emu::set_fade( int start_msec, int length_msec )
+{
+ track_filter.set_fade( msec_to_samples( start_msec ),
+ length_msec * sample_rate() / (1000 / stereo) );
+}
+
+blargg_err_t Music_Emu::play( int out_count, sample_t out [] )
+{
+ require( current_track() >= 0 );
+ require( out_count % stereo == 0 );
+
+ return track_filter.play( out_count, out );
+}
+
+// Gme_Info_
+
+blargg_err_t Gme_Info_::set_sample_rate_( int ) { return blargg_ok; }
+void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
+blargg_err_t Gme_Info_::post_load() { return Gme_File::post_load(); } // skip Music_Emu
+void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
+void Gme_Info_::mute_voices_( int ) { check( false ); }
+void Gme_Info_::set_tempo_( double ) { }
+blargg_err_t Gme_Info_::start_track_( int ) { return BLARGG_ERR( BLARGG_ERR_CALLER, "can't play file opened for info only" ); }
+blargg_err_t Gme_Info_::play_( int, sample_t [] ) { return BLARGG_ERR( BLARGG_ERR_CALLER, "can't play file opened for info only" ); }