1 // Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
2 
3 // Game_Music_Emu 0.6.0
4 #ifndef VGM_EMU_H
5 #define VGM_EMU_H
6 
7 #include "Vgm_Emu_Impl.h"
8 
9 // Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips.
10 // Supports custom sound buffer and frequency equalization when VGM uses just the PSG.
11 // FM sound chips can be run at their proper rates, or slightly higher to reduce
12 // aliasing on high notes. Currently YM2413 support requires that you supply a
13 // YM2413 sound chip emulator. I can provide one I've modified to work with the library.
14 class Vgm_Emu : public Vgm_Emu_Impl {
15 public:
16 	// True if custom buffer and custom equalization are supported
17 	// TODO: move into Music_Emu and rename to something like supports_custom_buffer()
is_classic_emu()18 	bool is_classic_emu() const { return !uses_fm; }
19 
20 	// Disable running FM chips at higher than normal rate. Will result in slightly
21 	// more aliasing of high notes.
22 	void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; }
23 
24 	// VGM header format
25 	enum { header_size = 0x40 };
26 	struct header_t
27 	{
28 		char tag [4];
29 		byte data_size [4];
30 		byte version [4];
31 		byte psg_rate [4];
32 		byte ym2413_rate [4];
33 		byte gd3_offset [4];
34 		byte track_duration [4];
35 		byte loop_offset [4];
36 		byte loop_duration [4];
37 		byte frame_rate [4];
38 		byte noise_feedback [2];
39 		byte noise_width;
40 		byte unused1;
41 		byte ym2612_rate [4];
42 		byte ym2151_rate [4];
43 		byte data_offset [4];
44 		byte unused2 [8];
45 	};
46 
47 	// Header for currently loaded file
header()48 	header_t const& header() const { return *(header_t const*) data; }
49 
static_type()50 	static gme_type_t static_type() { return gme_vgm_type; }
51 
52 public:
53 	// deprecated
54 	using Music_Emu::load;
load(header_t const & h,Data_Reader & in)55 	blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
56 			{ return load_remaining_( &h, sizeof h, in ); }
57 	byte const* gd3_data( int* size_out = 0 ) const; // use track_info()
58 
59 public:
60 	Vgm_Emu();
61 	~Vgm_Emu();
62 protected:
63 	blargg_err_t track_info_( track_info_t*, int track ) const;
64 	blargg_err_t load_mem_( byte const*, long );
65 	blargg_err_t set_sample_rate_( long sample_rate );
66 	blargg_err_t start_track_( int );
67 	blargg_err_t play_( long count, sample_t* );
68 	blargg_err_t run_clocks( blip_time_t&, int );
69 	void set_tempo_( double );
70 	void mute_voices_( int mask );
71 	void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
72 	void update_eq( blip_eq_t const& );
73 private:
74 	// removed; use disable_oversampling() and set_tempo() instead
75 	Vgm_Emu( bool oversample, double tempo = 1.0 );
76 	double fm_rate;
77 	long psg_rate;
78 	long vgm_rate;
79 	bool disable_oversampling_;
80 	bool uses_fm;
81 	blargg_err_t setup_fm();
82 };
83 
84 #endif
85