summaryrefslogtreecommitdiff
path: root/plugins/gme/game-music-emu-0.6pre/gme/Music_Emu.h
blob: ccdc228898453e0bfac716467bbe749f907e61fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// Common interface to game music file emulators

// Game_Music_Emu 0.6-pre
#ifndef MUSIC_EMU_H
#define MUSIC_EMU_H

#include "Gme_File.h"
#include "Track_Filter.h"
class Multi_Buffer;

struct gme_t : public Gme_File, private Track_Filter::callbacks_t {
public:
	// Sets output sample rate. Must be called only once before loading file.
	blargg_err_t set_sample_rate( int sample_rate );

	// Sample rate sound is generated at
	int sample_rate() const;
	
// File loading

	// See Gme_Loader.h

// Basic playback

	// Starts a track, where 0 is the first track. Also clears warning string.
	blargg_err_t start_track( int );
	
	// Generates '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( int count, sample_t* buf );
	
// Track information
	
	// See Gme_File.h
	
	// Index of current track or -1 if one hasn't been started
	int current_track() const;

	// Info for currently playing track
	using Gme_File::track_info;
	blargg_err_t track_info( track_info_t* out ) const;
	
// Track status/control

	// Number of milliseconds played since beginning of track (1000 per second)
	int tell() const;
	
	// Seeks to new time in track. Seeking backwards or far forward can take a while.
	blargg_err_t seek( int msec );
	
	// Skips n samples
	blargg_err_t skip( int n );
	
	// True if a track has reached its end
	bool track_ended() const;
	
	// Sets start time and length of track fade out. Once fade ends track_ended() returns
	// true. Fade time must be set after track has been started, and can be changed
	// at any time.
	void set_fade( int start_msec, int length_msec = 8000 );
	
	// Disables automatic end-of-track detection and skipping of silence at beginning
	void ignore_silence( bool disable = true );
	
// Voices

	// Number of voices used by currently loaded file
	int voice_count() const;
	
	// Name of voice i, from 0 to voice_count()-1
	const char* voice_name( int i ) const;
	
	// Mutes/unmutes voice i, where voice 0 is first voice
	void mute_voice( int index, bool mute = true );
	
	// Sets 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 );

// Sound customization
	
	// Adjusts 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 );
	
	// Changes overall output amplitude, where 1.0 results in minimal clamping.
	// Must be called before set_sample_rate().
	void set_gain( double );
	
	// Requests 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( class 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
	equalizer_t const& equalizer() const;
	
	// Sets frequency equalizer parameters
	void set_equalizer( equalizer_t const& );
	
	// Equalizer preset for a TV speaker
	static equalizer_t const tv_eq;
	
// Derived interface
protected:
	// Cause any further generated samples to be silence, instead of calling play_()
	void set_track_ended()                      { track_filter.set_track_ended(); }
	
	// If more than secs of silence are encountered, track is ended
	void set_max_initial_silence( int secs )    { tfilter.max_initial = secs; }
	
	// Sets rate emulator is run at when scanning ahead for silence. 1=100%, 2=200% etc.
	void set_silence_lookahead( int rate )      { tfilter.lookahead = rate; }
	
	// Sets number of voices
	void set_voice_count( int n )               { voice_count_ = n; }
	
	// Sets names of voices
	void set_voice_names( const char* const names [] );
	
	// Current gain
	double gain() const                         { return gain_; }
	
	// Current tempo
	double tempo() const                        { return tempo_; }
	
	// Re-applies muting mask using mute_voices_()
	void remute_voices();
	
// Overrides should do the indicated task
	
	// Set sample rate as close as possible to sample_rate, then call
	// Music_Emu::set_sample_rate_() with the actual rate used.
	virtual blargg_err_t set_sample_rate_( int sample_rate )    BLARGG_PURE( ; )
	
	// Set equalizer parameters
	virtual void set_equalizer_( equalizer_t const& )           { }
	
	// Mute voices based on mask
	virtual void mute_voices_( int mask )                       BLARGG_PURE( ; )
	
	// Set tempo to t, which is constrained to the range 0.02 to 4.0.
	virtual void set_tempo_( double t )                         BLARGG_PURE( ; )
	
	// Start track t, where 0 is the first track
	virtual blargg_err_t start_track_( int t )                  BLARGG_PURE( ; ) // tempo is set before this
	
	// Generate count samples into *out. Count will always be even.
	virtual blargg_err_t play_( int count, sample_t out [] )    BLARGG_PURE( ; )
	
	// Skip count samples. Count will always be even.
	virtual blargg_err_t skip_( int count );


// Implementation
public:
	gme_t();
	~gme_t();
	BLARGG_DEPRECATED( const char** voice_names() const { return CONST_CAST(const char**,voice_names_); } )

protected:
	virtual void unload();
	virtual void pre_load();
	virtual blargg_err_t post_load();

private:
	Track_Filter::setup_t tfilter;
	Track_Filter track_filter;
	equalizer_t equalizer_;
	const char* const* voice_names_;
	int voice_count_;
	int mute_mask_;
	double tempo_;
	double gain_;
	int sample_rate_;
	int current_track_;
	
	void clear_track_vars();
	int msec_to_samples( int msec ) const;
	
	friend Music_Emu* gme_new_emu( gme_type_t, int );
	friend void gme_effects( Music_Emu const*, gme_effects_t* );
	friend void gme_set_effects( Music_Emu*, gme_effects_t const* );
	friend void gme_set_stereo_depth( Music_Emu*, double );
	friend const char** gme_voice_names ( Music_Emu const* );
	
protected:
	Multi_Buffer* effects_buffer_;
};

// base class for info-only derivations
struct Gme_Info_ : Music_Emu
{
	virtual blargg_err_t set_sample_rate_( int 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_( int count, sample_t out [] );
	virtual void pre_load();
	virtual blargg_err_t post_load();
};

inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const
{
	return track_info( out, current_track_ );
}

inline int Music_Emu::sample_rate() const           { return sample_rate_; }
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_filter.track_ended(); }
inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }

inline void Music_Emu::ignore_silence( bool b )     { track_filter.ignore_silence( b ); }
inline void Music_Emu::set_tempo_( double t )       { tempo_ = t; }
inline void Music_Emu::remute_voices()              { mute_voices( mute_mask_ ); }

inline void Music_Emu::set_voice_names( const char* const p [] ) { voice_names_ = p; }

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;
}

inline blargg_err_t Music_Emu::start_track_( int )  { return blargg_ok; }

inline blargg_err_t Music_Emu::set_sample_rate_( int ) { return blargg_ok; }

inline blargg_err_t Music_Emu::play_( int, sample_t [] ) { return blargg_ok; }

#endif