diff options
Diffstat (limited to 'apps/codecs/libgme/vgm_emu.h')
-rw-r--r-- | apps/codecs/libgme/vgm_emu.h | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/apps/codecs/libgme/vgm_emu.h b/apps/codecs/libgme/vgm_emu.h new file mode 100644 index 0000000000..deb64bc7e0 --- /dev/null +++ b/apps/codecs/libgme/vgm_emu.h | |||
@@ -0,0 +1,211 @@ | |||
1 | // Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator | ||
2 | |||
3 | // Game_Music_Emu 0.5.5 | ||
4 | #ifndef VGM_EMU_H | ||
5 | #define VGM_EMU_H | ||
6 | |||
7 | #include "blargg_common.h" | ||
8 | #include "blargg_source.h" | ||
9 | #include "resampler.h" | ||
10 | #include "multi_buffer.h" | ||
11 | #include "ym2413_emu.h" | ||
12 | #include "ym2612_emu.h" | ||
13 | #include "sms_apu.h" | ||
14 | |||
15 | typedef short sample_t; | ||
16 | typedef int vgm_time_t; | ||
17 | typedef int fm_time_t; | ||
18 | |||
19 | enum { fm_time_bits = 12 }; | ||
20 | enum { blip_time_bits = 12 }; | ||
21 | enum { buf_size = 2048 }; | ||
22 | |||
23 | // VGM header format | ||
24 | enum { header_size = 0x40 }; | ||
25 | struct header_t | ||
26 | { | ||
27 | char tag [4]; | ||
28 | byte data_size [4]; | ||
29 | byte version [4]; | ||
30 | byte psg_rate [4]; | ||
31 | byte ym2413_rate [4]; | ||
32 | byte gd3_offset [4]; | ||
33 | byte track_duration [4]; | ||
34 | byte loop_offset [4]; | ||
35 | byte loop_duration [4]; | ||
36 | byte frame_rate [4]; | ||
37 | byte noise_feedback [2]; | ||
38 | byte noise_width; | ||
39 | byte unused1; | ||
40 | byte ym2612_rate [4]; | ||
41 | byte ym2151_rate [4]; | ||
42 | byte data_offset [4]; | ||
43 | byte unused2 [8]; | ||
44 | }; | ||
45 | |||
46 | enum { gme_max_field = 63 }; | ||
47 | struct track_info_t | ||
48 | { | ||
49 | /* times in milliseconds; -1 if unknown */ | ||
50 | long length; | ||
51 | long intro_length; | ||
52 | long loop_length; | ||
53 | |||
54 | /* empty string if not available */ | ||
55 | char game [64]; | ||
56 | char song [96]; | ||
57 | char author [64]; | ||
58 | }; | ||
59 | |||
60 | // Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips. | ||
61 | // Supports custom sound buffer and frequency equalization when VGM uses just the PSG. | ||
62 | // FM sound chips can be run at their proper rates, or slightly higher to reduce | ||
63 | // aliasing on high notes. Currently YM2413 support requires that you supply a | ||
64 | // YM2413 sound chip emulator. I can provide one I've modified to work with the library. | ||
65 | struct Vgm_Emu { | ||
66 | double fm_rate; | ||
67 | long psg_rate; | ||
68 | long vgm_rate; | ||
69 | bool disable_oversampling; | ||
70 | |||
71 | long fm_time_offset; | ||
72 | int fm_time_factor; | ||
73 | |||
74 | int blip_time_factor; | ||
75 | |||
76 | byte const* file_begin; | ||
77 | byte const* file_end; | ||
78 | |||
79 | vgm_time_t vgm_time; | ||
80 | byte const* loop_begin; | ||
81 | byte const* pos; | ||
82 | |||
83 | byte const* pcm_data; | ||
84 | byte const* pcm_pos; | ||
85 | int dac_amp; | ||
86 | int dac_disabled; // -1 if disabled | ||
87 | |||
88 | struct Blip_Buffer* blip_buf; | ||
89 | |||
90 | // general | ||
91 | long clock_rate_; | ||
92 | unsigned buf_changed_count; | ||
93 | int max_initial_silence; | ||
94 | int voice_count; | ||
95 | int mute_mask_; | ||
96 | double tempo; | ||
97 | double gain; | ||
98 | |||
99 | long sample_rate; | ||
100 | |||
101 | // track-specific | ||
102 | blargg_long out_time; // number of samples played since start of track | ||
103 | blargg_long emu_time; // number of samples emulator has generated since start of track | ||
104 | bool emu_track_ended_; // emulator has reached end of track | ||
105 | volatile bool track_ended; | ||
106 | |||
107 | // fading | ||
108 | blargg_long fade_start; | ||
109 | int fade_step; | ||
110 | |||
111 | // silence detection | ||
112 | int silence_lookahead; // speed to run emulator when looking ahead for silence | ||
113 | bool ignore_silence; | ||
114 | long silence_time; // number of samples where most recent silence began | ||
115 | long silence_count; // number of samples of silence to play before using buf | ||
116 | long buf_remain; // number of samples left in silence buffer | ||
117 | |||
118 | // larger items at the end | ||
119 | struct track_info_t info; | ||
120 | sample_t buf_ [buf_size]; | ||
121 | |||
122 | struct Ym2612_Emu ym2612; | ||
123 | struct Ym2413_Emu ym2413; | ||
124 | |||
125 | struct Sms_Apu psg; | ||
126 | struct Blip_Synth pcm; | ||
127 | struct Stereo_Buffer stereo_buf; | ||
128 | |||
129 | struct Resampler resampler; | ||
130 | |||
131 | struct Stereo_Buffer buf; | ||
132 | }; | ||
133 | |||
134 | void Vgm_init( struct Vgm_Emu* this ); | ||
135 | |||
136 | // Disable running FM chips at higher than normal rate. Will result in slightly | ||
137 | // more aliasing of high notes. | ||
138 | static inline void Vgm_disable_oversampling( struct Vgm_Emu* this, bool disable ) { this->disable_oversampling = disable; } | ||
139 | |||
140 | // Header for currently loaded file | ||
141 | static inline struct header_t *header( struct Vgm_Emu* this ) { return (struct header_t*) this->file_begin; } | ||
142 | |||
143 | // Basic functionality (see Gme_File.h for file loading/track info functions) | ||
144 | blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_size, bool parse_info ); | ||
145 | |||
146 | // True if any FM chips are used by file. Always false until init_fm() | ||
147 | // is called. | ||
148 | static inline bool uses_fm( struct Vgm_Emu* this ) { return Ym2612_enabled( &this->ym2612 ) || Ym2413_enabled( &this->ym2413 ); } | ||
149 | |||
150 | // Set output sample rate. Must be called only once before loading file. | ||
151 | blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, long sample_rate ); | ||
152 | |||
153 | // Start a track, where 0 is the first track. Also clears warning string. | ||
154 | blargg_err_t Vgm_start_track( struct Vgm_Emu* this ); | ||
155 | |||
156 | // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation | ||
157 | // errors set warning string, and major errors also end track. | ||
158 | blargg_err_t Vgm_play( struct Vgm_Emu* this, long count, sample_t* buf ) ICODE_ATTR; | ||
159 | |||
160 | // Track status/control | ||
161 | |||
162 | // Number of milliseconds (1000 msec = 1 second) played since beginning of track | ||
163 | long Track_tell( struct Vgm_Emu* this ); | ||
164 | |||
165 | // Seek to new time in track. Seeking backwards or far forward can take a while. | ||
166 | blargg_err_t Track_seek( struct Vgm_Emu* this, long msec ); | ||
167 | |||
168 | // Skip n samples | ||
169 | blargg_err_t Track_skip( struct Vgm_Emu* this, long n ); | ||
170 | |||
171 | // Set start time and length of track fade out. Once fade ends track_ended() returns | ||
172 | // true. Fade time can be changed while track is playing. | ||
173 | void Track_set_fade( struct Vgm_Emu* this, long start_msec, long length_msec ); | ||
174 | |||
175 | // Get track length in milliseconds | ||
176 | static inline long Track_get_length( struct Vgm_Emu* this ) | ||
177 | { | ||
178 | long length = this->info.length; | ||
179 | if ( length <= 0 ) | ||
180 | { | ||
181 | length = this->info.intro_length + 2 * this->info.loop_length; // intro + 2 loops | ||
182 | if ( length <= 0 ) | ||
183 | length = 150 * 1000; // 2.5 minutes | ||
184 | } | ||
185 | |||
186 | return length; | ||
187 | } | ||
188 | |||
189 | // Sound customization | ||
190 | |||
191 | // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. | ||
192 | // Track length as returned by track_info() assumes a tempo of 1.0. | ||
193 | void Sound_set_tempo( struct Vgm_Emu* this, double t ); | ||
194 | |||
195 | // Mute/unmute voice i, where voice 0 is first voice | ||
196 | void Sound_mute_voice( struct Vgm_Emu* this, int index, bool mute ); | ||
197 | |||
198 | // Set muting state of all voices at once using a bit mask, where -1 mutes them all, | ||
199 | // 0 unmutes them all, 0x01 mutes just the first voice, etc. | ||
200 | void Sound_mute_voices( struct Vgm_Emu* this, int mask ); | ||
201 | |||
202 | // Change overall output amplitude, where 1.0 results in minimal clamping. | ||
203 | // Must be called before set_sample_rate(). | ||
204 | static inline void Sound_set_gain( struct Vgm_Emu* this, double g ) | ||
205 | { | ||
206 | assert( !this->sample_rate ); // you must set gain before setting sample rate | ||
207 | this->gain = g; | ||
208 | } | ||
209 | |||
210 | |||
211 | #endif | ||