Mercurial > audlegacy-plugins
diff src/console/Music_Emu.h @ 316:fb513e10174e trunk
[svn] - merge libconsole-blargg into mainline libconsole:
+ obsoletes plugins-ugly:sapplug
| author | nenolod |
|---|---|
| date | Thu, 30 Nov 2006 19:54:33 -0800 |
| parents | 3da1b8942b8b |
| children | 986f098da058 |
line wrap: on
line diff
--- a/src/console/Music_Emu.h Wed Nov 29 14:42:11 2006 -0800 +++ b/src/console/Music_Emu.h Thu Nov 30 19:54:33 2006 -0800 @@ -1,136 +1,212 @@ - -// Game music emulator interface base class +// Common interface to game music file emulators -// Game_Music_Emu 0.3.0 - +// Game_Music_Emu 0.5.1 #ifndef MUSIC_EMU_H #define MUSIC_EMU_H #include "blargg_common.h" -#include "abstract_file.h" +#include "Gme_File.h" class Multi_Buffer; -class Music_Emu { +struct Music_Emu : public Gme_File { public: - - // Initialize emulator with specified sample rate. Currently should only be - // called once. - virtual blargg_err_t set_sample_rate( long sample_rate ) = 0; - - // Load music file - blargg_err_t load_file( const char* path ); - - // Start a track, where 0 is the first track. Might un-mute any muted voices. - virtual void start_track( int ) = 0; +// Basic functionality (see Gme_File.h for file loading/track info functions) + + // Set output sample rate. Must be called only once before loading file. + blargg_err_t set_sample_rate( long sample_rate ); - // Generate 'count' samples info 'buf'. Output is in stereo unless using custom - // buffer that generates mono output. - typedef short sample_t; - virtual void play( long count, sample_t* buf ) = 0; - -// Additional optional features + // Start a track, where 0 is the first track. Also clears warning string. + blargg_err_t start_track( int ); - // Request use of custom multichannel buffer. Only supported by "classic" emulators; - // on others this has no effect. Should be called only once *before* set_sample_rate(). - virtual void set_buffer( Multi_Buffer* ) { } + // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation + // errors set warning string, and major errors also end track. + typedef short sample_t; + blargg_err_t play( long count, sample_t* buf ); - // Load music file data from custom source - virtual blargg_err_t load( Data_Reader& ) = 0; +// Informational // Sample rate sound is generated at long sample_rate() const; + // Index of current track or -1 if one hasn't been started + int current_track() const; + // Number of voices used by currently loaded file int voice_count() const; // Names of voices - virtual const char** voice_names() const; + const char** voice_names() const; + +// Track status/control + + // Number of milliseconds (1000 msec = 1 second) played since beginning of track + long tell() const; + + // Seek to new time in track. Seeking backwards or far forward can take a while. + blargg_err_t seek( long msec ); + + // Skip n samples + blargg_err_t skip( long n ); - // Mute voice n if bit n (1 << n) of mask is set - virtual void mute_voices( int mask ); + // True if a track has reached its end + bool track_ended() const; + + // Set start time and length of track fade out. Once fade ends track_ended() returns + // true. Fade time can be changed while track is playing. + void set_fade( long start_msec, long length_msec = 8000 ); + + // Disable automatic end-of-track detection and skipping of silence at beginning + void ignore_silence( bool disable = true ); + + // Info for current track + Gme_File::track_info; + blargg_err_t track_info( track_info_t* out ) const; - // Frequency equalizer parameters (see notes.txt) - struct equalizer_t { - double treble; // -50.0 = muffled, 0 = flat, +5.0 = extra-crisp - long bass; // 1 = full bass, 90 = average, 16000 = almost no bass - }; +// Sound customization + + // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. + // Track length as returned by track_info() assumes a tempo of 1.0. + void set_tempo( double ); + + // Mute/unmute voice i, where voice 0 is first voice + void mute_voice( int index, bool mute = true ); + + // Set muting state of all voices at once using a bit mask, where -1 mutes them all, + // 0 unmutes them all, 0x01 mutes just the first voice, etc. + void mute_voices( int mask ); + + // Change overall output amplitude, where 1.0 results in minimal clamping. + // Must be called before set_sample_rate(). + void set_gain( double ); + + // Request use of custom multichannel buffer. Only supported by "classic" emulators; + // on others this has no effect. Should be called only once *before* set_sample_rate(). + virtual void set_buffer( Multi_Buffer* ) { } + +// Sound equalization (treble/bass) + + // Frequency equalizer parameters (see gme.txt) + // See gme.h for definition of struct gme_equalizer_t. + typedef gme_equalizer_t equalizer_t; // Current frequency equalizater parameters - const equalizer_t& equalizer() const; + equalizer_t const& equalizer() const; // Set frequency equalizer parameters - virtual void set_equalizer( equalizer_t const& ); + void set_equalizer( equalizer_t const& ); // Equalizer settings for TV speaker static equalizer_t const tv_eq; - // Number of tracks. Zero if file hasn't been loaded yet. - int track_count() const; - - // Skip 'count' samples - virtual void skip( long count ); - - // True if a track was started and has since ended. Currently only logged - // format tracks (VGM, GYM) without loop points have an ending. - bool track_ended() const; - - // Number of errors encountered while playing track due to undefined CPU - // instructions in emulated formats and undefined stream events in - // logged formats. - int error_count() const; - +public: Music_Emu(); - virtual ~Music_Emu(); - + ~Music_Emu(); protected: - typedef BOOST::uint8_t byte; - void set_voice_count( int n ) { voice_count_ = n; } - void set_track_count( int n ) { track_count_ = n; } - void set_track_ended( bool b = true ) { track_ended_ = b; } - void log_error() { error_count_++; } + void set_max_initial_silence( int n ) { max_initial_silence = n; } + void set_silence_lookahead( int n ) { silence_lookahead = n; } + void set_voice_count( int n ) { voice_count_ = n; } + void set_voice_names( const char* const* names ); + void set_track_ended() { emu_track_ended_ = true; } + double gain() const { return gain_; } + double tempo() const { return tempo_; } void remute_voices(); + + virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0; + virtual void set_equalizer_( equalizer_t const& ) { }; + virtual void mute_voices_( int mask ) = 0; + virtual void set_tempo_( double ) = 0; + virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this + virtual blargg_err_t play_( long count, sample_t* out ) = 0; + virtual blargg_err_t skip_( long count ); +protected: + virtual void unload(); + virtual void pre_load(); + virtual void post_load_(); private: - // noncopyable - Music_Emu( const Music_Emu& ); - Music_Emu& operator = ( const Music_Emu& ); - + // general equalizer_t equalizer_; - long sample_rate_; + int max_initial_silence; + const char** voice_names_; int voice_count_; int mute_mask_; - int track_count_; - int error_count_; - bool track_ended_; + double tempo_; + double gain_; + + long sample_rate_; + blargg_long msec_to_samples( blargg_long msec ) const; + + // track-specific + int current_track_; + blargg_long out_time; // number of samples played since start of track + blargg_long emu_time; // number of samples emulator has generated since start of track + bool emu_track_ended_; // emulator has reached end of track + volatile bool track_ended_; + void clear_track_vars(); + void end_track_if_error( blargg_err_t ); + + // fading + blargg_long fade_start; + int fade_step; + void handle_fade( long count, sample_t* out ); + + // silence detection + int silence_lookahead; // speed to run emulator when looking ahead for silence + bool ignore_silence_; + long silence_time; // number of samples where most recent silence began + long silence_count; // number of samples of silence to play before using buf + long buf_remain; // number of samples left in silence buffer + enum { buf_size = 2048 }; + blargg_vector<sample_t> buf; + void fill_buf(); + void emu_play( long count, sample_t* out ); + + Multi_Buffer* effects_buffer; + friend Music_Emu* gme_new_emu( gme_type_t, long ); + friend void gme_set_stereo_depth( Music_Emu*, double ); }; -// Deprecated -typedef Data_Reader Emu_Reader; -typedef Std_File_Reader Emu_Std_Reader; -typedef Mem_File_Reader Emu_Mem_Reader; +// base class for info-only derivations +struct Gme_Info_ : Music_Emu +{ + virtual blargg_err_t set_sample_rate_( long sample_rate ); + virtual void set_equalizer_( equalizer_t const& ); + virtual void mute_voices_( int mask ); + virtual void set_tempo_( double ); + virtual blargg_err_t start_track_( int ); + virtual blargg_err_t play_( long count, sample_t* out ); + virtual void pre_load(); + virtual void post_load_(); +}; -inline int Music_Emu::error_count() const { return error_count_; } -inline int Music_Emu::voice_count() const { return voice_count_; } -inline int Music_Emu::track_count() const { return track_count_; } -inline bool Music_Emu::track_ended() const { return track_ended_; } -inline void Music_Emu::mute_voices( int mask ) { mute_mask_ = mask; } -inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); } -inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; } -inline void Music_Emu::set_equalizer( const equalizer_t& eq ) { equalizer_ = eq; } -inline long Music_Emu::sample_rate() const { return sample_rate_; } - -inline blargg_err_t Music_Emu::set_sample_rate( long r ) +inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const { - assert( !sample_rate_ ); // sample rate can't be changed once set - sample_rate_ = r; - return blargg_success; + return track_info( out, current_track_ ); } -inline void Music_Emu::start_track( int track ) +inline long Music_Emu::sample_rate() const { return sample_rate_; } +inline const char** Music_Emu::voice_names() const { return voice_names_; } +inline int Music_Emu::voice_count() const { return voice_count_; } +inline int Music_Emu::current_track() const { return current_track_; } +inline bool Music_Emu::track_ended() const { return track_ended_; } +inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; } + +inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; } +inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); } +inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; } +inline blargg_err_t Music_Emu::start_track_( int ) { return 0; } + +inline void Music_Emu::set_voice_names( const char* const* names ) { - assert( sample_rate_ ); // set_sample_rate() must have been called first - track_ended_ = false; - error_count_ = 0; + // Intentional removal of const, so users don't have to remember obscure const in middle + voice_names_ = (const char**) names; +} + +inline void Music_Emu::mute_voices_( int ) { } + +inline void Music_Emu::set_gain( double g ) +{ + assert( !sample_rate() ); // you must set gain before setting sample rate + gain_ = g; } #endif -
