1 // Sinclair Spectrum AY music file emulator
3 // Game_Music_Emu 0.6-pre
7 #include "blargg_source.h"
9 #include "multi_buffer.h"
12 #include "m3u_playlist.h"
14 typedef short sample_t
;
16 // 64K memory to load code and data into before starting track. Caller
17 // must parse the AY file.
18 enum { mem_size
= 0x10000 };
19 enum { ram_addr
= 0x4000 }; // where official RAM starts
20 enum { buf_size
= 2048 };
23 enum { header_size
= 0x14 };
38 struct header_t
const* header
;
40 byte
const* end
; // end of file data
44 uint8_t padding1
[0x100];
45 uint8_t ram
[mem_size
+ 0x100];
51 struct Blip_Buffer
* beeper_output
;
57 cpu_time_t play_period
;
65 int max_initial_silence
;
76 blargg_long out_time
; // number of samples played since start of track
77 blargg_long emu_time
; // number of samples emulator has generated since start of track
78 volatile bool track_ended
;
79 bool emu_track_ended_
; // emulator has reached end of track
82 blargg_long fade_start
;
87 int silence_lookahead
; // speed to run emulator when looking ahead for silence
88 long silence_time
; // number of samples where most recent silence began
89 long silence_count
; // number of samples of silence to play before using buf
90 long buf_remain
; // number of samples left in silence buffer
93 unsigned buf_changed_count
;
96 struct M3u_Playlist m3u
;
100 sample_t buf
[buf_size
];
101 struct Stereo_Buffer stereo_buf
; // NULL if using custom buffer
106 // Basic functionality (see Gme_File.h for file loading/track info functions)
107 void Ay_init( struct Ay_Emu
* this );
109 blargg_err_t
Ay_load_mem( struct Ay_Emu
* this, byte
const in
[], int size
);
111 // Set output sample rate. Must be called only once before loading file.
112 blargg_err_t
Ay_set_sample_rate( struct Ay_Emu
* this, long sample_rate
);
114 // Start a track, where 0 is the first track. Also clears warning string.
115 blargg_err_t
Ay_start_track( struct Ay_Emu
* this, int track
);
117 // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
118 // errors set warning string, and major errors also end track.
119 blargg_err_t
Ay_play( struct Ay_Emu
* this, long count
, sample_t
* buf
);
122 // Track status/control
124 // Number of milliseconds (1000 msec = 1 second) played since beginning of track
125 long Track_tell( struct Ay_Emu
* this );
127 // Seek to new time in track. Seeking backwards or far forward can take a while.
128 blargg_err_t
Track_seek( struct Ay_Emu
* this, long msec
);
131 blargg_err_t
Track_skip( struct Ay_Emu
* this, long n
);
133 // Set start time and length of track fade out. Once fade ends track_ended() returns
134 // true. Fade time can be changed while track is playing.
135 void Track_set_fade( struct Ay_Emu
* this, long start_msec
, long length_msec
);
137 // Get track length in milliseconds
138 long Track_get_length( struct Ay_Emu
* this, int n
);
140 // Sound customization
142 // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
143 // Track length as returned by track_info() assumes a tempo of 1.0.
144 void Sound_set_tempo( struct Ay_Emu
* this, double t
);
146 // Mute/unmute voice i, where voice 0 is first voice
147 void Sound_mute_voice( struct Ay_Emu
* this, int index
, bool mute
);
149 // Set muting state of all voices at once using a bit mask, where -1 mutes them all,
150 // 0 unmutes them all, 0x01 mutes just the first voice, etc.
151 void Sound_mute_voices( struct Ay_Emu
* this, int mask
);
153 // Change overall output amplitude, where 1.0 results in minimal clamping.
154 // Must be called before set_sample_rate().
155 static inline void Sound_set_gain( struct Ay_Emu
* this, double g
)
157 assert( !this->sample_rate
); // you must set gain before setting sample rate
161 // Emulation (You shouldn't touch these)
162 void cpu_out( struct Ay_Emu
* this, cpu_time_t
, addr_t
, int data
);
163 void cpu_out_( struct Ay_Emu
* this, cpu_time_t
, addr_t
, int data
);
164 bool run_cpu( struct Ay_Emu
* this, cpu_time_t end
);
166 static inline void disable_beeper( struct Ay_Emu
*this )
168 this->beeper_mask
= 0;
169 this->last_beeper
= 0;