1 // Common interface to game music file emulators
2
3 // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
4 #ifndef MUSIC_EMU_H
5 #define MUSIC_EMU_H
6
7 #include "Gme_File.h"
8 class Multi_Buffer;
9
10 struct Music_Emu : public Gme_File {
11 public:
12 // Basic functionality (see Gme_File.h for file loading/track info functions)
13
14 // Set output sample rate. Must be called only once before loading file.
15 blargg_err_t set_sample_rate( long sample_rate );
16
17 // specifies if all 8 voices get rendered to their own stereo channel
18 // default implementation of Music_Emu always returns not supported error (i.e. no multichannel support by default)
19 // derived emus must override this if they support multichannel rendering
20 virtual blargg_err_t set_multi_channel( bool is_enabled );
21
22 // Start a track, where 0 is the first track. Also clears warning string.
23 blargg_err_t start_track( int );
24
25 // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
26 // errors set warning string, and major errors also end track.
27 typedef short sample_t;
28 blargg_err_t play( long count, sample_t* buf );
29
30 // Informational
31
32 // Sample rate sound is generated at
33 long sample_rate() const;
34
35 // Index of current track or -1 if one hasn't been started
36 int current_track() const;
37
38 // Number of voices used by currently loaded file
39 int voice_count() const;
40
41 // Names of voices
42 const char** voice_names() const;
43
44 bool multi_channel() const;
45
46 // Track status/control
47
48 // Number of milliseconds (1000 msec = 1 second) played since beginning of track
49 long tell() const;
50
51 // Number of samples generated since beginning of track
52 long tell_samples() const;
53
54 // Seek to new time in track. Seeking backwards or far forward can take a while.
55 blargg_err_t seek( long msec );
56
57 // Equivalent to restarting track then skipping n samples
58 blargg_err_t seek_samples( long n );
59
60 // Skip n samples
61 blargg_err_t skip( long n );
62
63 // True if a track has reached its end
64 bool track_ended() const;
65
66 // Set start time and length of track fade out. Once fade ends track_ended() returns
67 // true. Fade time can be changed while track is playing.
68 void set_fade( long start_msec, long length_msec = 8000 );
69
70 // Controls whether or not to automatically load and obey track length
71 // metadata for supported emulators.
72 //
73 // @since 0.6.2.
74 bool autoload_playback_limit() const;
75 void set_autoload_playback_limit( bool do_autoload_limit );
76
77 // Disable automatic end-of-track detection and skipping of silence at beginning
78 void ignore_silence( bool disable = true );
79
80 // Info for current track
81 using Gme_File::track_info;
82 blargg_err_t track_info( track_info_t* out ) const;
83
84 // Sound customization
85
86 // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
87 // Track length as returned by track_info() assumes a tempo of 1.0.
88 void set_tempo( double );
89
90 // Mute/unmute voice i, where voice 0 is first voice
91 void mute_voice( int index, bool mute = true );
92
93 // Set muting state of all voices at once using a bit mask, where -1 mutes them all,
94 // 0 unmutes them all, 0x01 mutes just the first voice, etc.
95 void mute_voices( int mask );
96
97 // Change overall output amplitude, where 1.0 results in minimal clamping.
98 // Must be called before set_sample_rate().
99 void set_gain( double );
100
101 // Request use of custom multichannel buffer. Only supported by "classic" emulators;
102 // on others this has no effect. Should be called only once *before* set_sample_rate().
set_bufferMusic_Emu103 virtual void set_buffer( Multi_Buffer* ) { }
104
105 // Enables/disables accurate emulation options, if any are supported. Might change
106 // equalizer settings.
107 void enable_accuracy( bool enable = true );
108
109 // Sound equalization (treble/bass)
110
111 // Frequency equalizer parameters (see gme.txt)
112 // See gme.h for definition of struct gme_equalizer_t.
113 typedef gme_equalizer_t equalizer_t;
114
115 // Current frequency equalizater parameters
116 equalizer_t const& equalizer() const;
117
118 // Set frequency equalizer parameters
119 void set_equalizer( equalizer_t const& );
120
121 // Construct equalizer of given treble/bass settings
make_equalizerMusic_Emu122 static const equalizer_t make_equalizer( double treble, double bass )
123 {
124 const Music_Emu::equalizer_t e = { treble, bass,
125 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
126 return e;
127 }
128
129 // Equalizer settings for TV speaker
130 static equalizer_t const tv_eq;
131
132 public:
133 Music_Emu();
134 ~Music_Emu();
135 protected:
set_max_initial_silenceMusic_Emu136 void set_max_initial_silence( int n ) { max_initial_silence = n; }
set_silence_lookaheadMusic_Emu137 void set_silence_lookahead( int n ) { silence_lookahead = n; }
set_voice_countMusic_Emu138 void set_voice_count( int n ) { voice_count_ = n; }
139 void set_voice_names( const char* const* names );
set_track_endedMusic_Emu140 void set_track_ended() { emu_track_ended_ = true; }
gainMusic_Emu141 double gain() const { return gain_; }
tempoMusic_Emu142 double tempo() const { return tempo_; }
143 void remute_voices();
144 blargg_err_t set_multi_channel_( bool is_enabled );
145
146 virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
set_equalizer_Music_Emu147 virtual void set_equalizer_( equalizer_t const& ) { }
enable_accuracy_Music_Emu148 virtual void enable_accuracy_( bool /* enable */ ) { }
149 virtual void mute_voices_( int mask ) = 0;
150 virtual void set_tempo_( double ) = 0;
151 virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this
152 virtual blargg_err_t play_( long count, sample_t* out ) = 0;
153 virtual blargg_err_t skip_( long count );
154 protected:
155 virtual void unload();
156 virtual void pre_load();
157 virtual void post_load_();
158 private:
159 // general
160 equalizer_t equalizer_;
161 int max_initial_silence;
162 const char** voice_names_;
163 int voice_count_;
164 int mute_mask_;
165 double tempo_;
166 double gain_;
167 bool multi_channel_;
168
169 // returns the number of output channels, i.e. usually 2 for stereo, unlesss multi_channel_ == true
out_channelsMusic_Emu170 int out_channels() const { return this->multi_channel() ? 2*8 : 2; }
171
172 long sample_rate_;
173 blargg_long msec_to_samples( blargg_long msec ) const;
174
175 // track-specific
176 int current_track_;
177 blargg_long out_time; // number of samples played since start of track
178 blargg_long emu_time; // number of samples emulator has generated since start of track
179 bool emu_track_ended_; // emulator has reached end of track
180 bool emu_autoload_playback_limit_; // whether to load and obey track length by default
181 volatile bool track_ended_;
182 void clear_track_vars();
183 void end_track_if_error( blargg_err_t );
184
185 // fading
186 blargg_long fade_start;
187 int fade_step;
188 void handle_fade( long count, sample_t* out );
189
190 // silence detection
191 int silence_lookahead; // speed to run emulator when looking ahead for silence
192 bool ignore_silence_;
193 long silence_time; // number of samples where most recent silence began
194 long silence_count; // number of samples of silence to play before using buf
195 long buf_remain; // number of samples left in silence buffer
196 enum { buf_size = 2048 };
197 blargg_vector<sample_t> buf;
198 void fill_buf();
199 void emu_play( long count, sample_t* out );
200
201 Multi_Buffer* effects_buffer;
202 friend Music_Emu* gme_internal_new_emu_( gme_type_t, int, bool );
203 friend void gme_set_stereo_depth( Music_Emu*, double );
204 };
205
206 // base class for info-only derivations
207 struct Gme_Info_ : Music_Emu
208 {
209 virtual blargg_err_t set_sample_rate_( long sample_rate );
210 virtual void set_equalizer_( equalizer_t const& );
211 virtual void enable_accuracy_( bool );
212 virtual void mute_voices_( int mask );
213 virtual void set_tempo_( double );
214 virtual blargg_err_t start_track_( int );
215 virtual blargg_err_t play_( long count, sample_t* out );
216 virtual void pre_load();
217 virtual void post_load_();
218 };
219
track_info(track_info_t * out)220 inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const
221 {
222 return track_info( out, current_track_ );
223 }
224
sample_rate()225 inline long Music_Emu::sample_rate() const { return sample_rate_; }
voice_names()226 inline const char** Music_Emu::voice_names() const { return voice_names_; }
voice_count()227 inline int Music_Emu::voice_count() const { return voice_count_; }
current_track()228 inline int Music_Emu::current_track() const { return current_track_; }
track_ended()229 inline bool Music_Emu::track_ended() const { return track_ended_; }
equalizer()230 inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
231
enable_accuracy(bool b)232 inline void Music_Emu::enable_accuracy( bool b ) { enable_accuracy_( b ); }
set_tempo_(double t)233 inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
remute_voices()234 inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
ignore_silence(bool b)235 inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }
start_track_(int)236 inline blargg_err_t Music_Emu::start_track_( int ) { return 0; }
237
set_voice_names(const char * const * names)238 inline void Music_Emu::set_voice_names( const char* const* names )
239 {
240 // Intentional removal of const, so users don't have to remember obscure const in middle
241 voice_names_ = const_cast<const char**> (names);
242 }
243
mute_voices_(int)244 inline void Music_Emu::mute_voices_( int ) { }
245
set_gain(double g)246 inline void Music_Emu::set_gain( double g )
247 {
248 assert( !sample_rate() ); // you must set gain before setting sample rate
249 gain_ = g;
250 }
251
252 #endif
253