1 #ifndef MUSIC_H
2 #define MUSIC_H
3 
4 /*
5 Copyright (c) 2009-2011 Tero Lindeman (kometbomb)
6 
7 Permission is hereby granted, free of charge, to any person
8 obtaining a copy of this software and associated documentation
9 files (the "Software"), to deal in the Software without
10 restriction, including without limitation the rights to use,
11 copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the
13 Software is furnished to do so, subject to the following
14 conditions:
15 
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 OTHER DEALINGS IN THE SOFTWARE.
27 */
28 
29 #include "cyd.h"
30 #include "cydfx.h"
31 #include <stdio.h>
32 
33 #define MUS_PROG_LEN 32
34 #define MUS_MAX_CHANNELS CYD_MAX_CHANNELS
35 
36 #define MUS_VERSION 27
37 
38 #define MUS_SONG_TITLE_LEN 64
39 #define MUS_INSTRUMENT_NAME_LEN 32
40 #define MUS_WAVETABLE_NAME_LEN MUS_INSTRUMENT_NAME_LEN
41 
42 typedef struct
43 {
44 	Uint8 a, d, s, r; // 0-15
45 } MusAdsr;
46 
47 typedef struct
48 {
49 	Uint32 flags;
50 	Uint32 cydflags;
51 	MusAdsr adsr;
52 	Uint8 sync_source, ring_mod; // 0xff == self
53 	Uint16 pw;
54 	Uint8 volume;
55 	Uint16 program[MUS_PROG_LEN];
56 	Uint8 prog_period;
57 	Uint8 vibrato_speed, vibrato_depth, slide_speed, pwm_speed, pwm_depth;
58 	Uint8 base_note;
59 	Uint16 cutoff;
60 	Uint8 resonance;
61 	Uint8 flttype;
62 	Uint8 ym_env_shape;
63 	Sint16 buzz_offset;
64 	Uint8 fx_bus, vib_shape, vib_delay, pwm_shape;
65 	char name[MUS_INSTRUMENT_NAME_LEN + 1];
66 	Uint8 wavetable_entry;
67 	Uint8 lfsr_type;
68 	Sint8 finetune;
69 	Uint32 fm_flags;
70 	Uint8 fm_modulation, fm_feedback, fm_wave, fm_harmonic;
71 	MusAdsr fm_adsr;
72 	Uint8 fm_attack_start;
73 } MusInstrument;
74 
75 enum
76 {
77 	MUS_INST_PROG_SPEED_RELATIVE = 0, // chn.current_tick / mus.tick_period * ins.prog_period
78 	MUS_INST_PROG_SPEED_ABSOLUTE = 1, // absolute number of ticks
79 	MUS_INST_DRUM = 2,
80 	MUS_INST_INVERT_VIBRATO_BIT = 4,
81 	MUS_INST_LOCK_NOTE = 8,
82 	MUS_INST_SET_PW = 16,
83 	MUS_INST_SET_CUTOFF = 32,
84 	MUS_INST_YM_BUZZ = 64,
85 	MUS_INST_RELATIVE_VOLUME = 128,
86 	MUS_INST_QUARTER_FREQ = 256,
87 	MUS_INST_WAVE_LOCK_NOTE = 512,
88 	MUS_INST_NO_PROG_RESTART = 1024,
89 	MUS_INST_MULTIOSC = 2048,
90 };
91 
92 enum
93 {
94 	MUS_FX_WAVE_NOISE = 1,
95 	MUS_FX_WAVE_PULSE = 2,
96 	MUS_FX_WAVE_TRIANGLE = 4,
97 	MUS_FX_WAVE_SAW = 8,
98 	MUS_FX_WAVE_LFSR = 16,
99 	MUS_FX_WAVE_WAVE = 32,
100 };
101 
102 typedef struct
103 {
104 	MusInstrument *instrument;
105 	Uint16 note;
106 	Uint8 volume;
107 	// ------
108 	Uint8 arpeggio_note;
109 	Uint16 target_note, last_note, fixed_note;
110 	volatile Uint32 flags;
111 	Uint32 current_tick;
112 	Uint8 program_counter, program_tick, program_loop, prog_period;
113 	Sint16 buzz_offset;
114 } MusChannel;
115 
116 typedef struct
117 {
118 	Uint8 note, instrument, ctrl;
119 	Uint16 command;
120 	Uint8 volume;
121 } MusStep;
122 
123 typedef struct
124 {
125 	Uint16 position;
126 	Uint16 pattern;
127 	Sint8 note_offset;
128 } MusSeqPattern;
129 
130 typedef struct
131 {
132 	MusStep *step;
133 	Uint16 num_steps;
134 	Uint8 color;
135 } MusPattern;
136 
137 typedef struct
138 {
139 	MusInstrument *instrument;
140 	Uint8 num_instruments;
141 	MusPattern *pattern;
142 	Uint16 num_patterns;
143 	MusSeqPattern *sequence[MUS_MAX_CHANNELS];
144 	Uint16 num_sequences[MUS_MAX_CHANNELS];
145 	Uint16 song_length, loop_point;
146 	Uint8 song_speed, song_speed2, song_rate;
147 	Uint16 time_signature, sequence_step;
148 	Uint32 flags;
149 	Uint8 num_channels;
150 	Uint8 multiplex_period, pitch_inaccuracy;
151 	char title[MUS_SONG_TITLE_LEN + 1];
152 	CydFxSerialized fx[CYD_MAX_FX_CHANNELS];
153 	Uint8 master_volume;
154 	Uint8 default_volume[MUS_MAX_CHANNELS];
155 	Sint8 default_panning[MUS_MAX_CHANNELS];
156 	char **wavetable_names;
157 	int num_wavetables;
158 } MusSong;
159 
160 
161 typedef struct
162 {
163 	MusPattern *pattern;
164 	Uint8 last_ctrl;
165 	Uint16 pw, pattern_step, sequence_position, slide_speed;
166 	Uint16 vibrato_position, pwm_position;
167 	Sint8 note_offset;
168 	Uint16 filter_cutoff;
169 	Uint8 filter_resonance;
170 	Uint8 extarp1, extarp2;
171 	Uint8 volume;
172 	Uint8 vib_delay;
173 } MusTrackStatus;
174 
175 typedef struct
176 {
177 	MusChannel channel[MUS_MAX_CHANNELS];
178 	Uint8 tick_period; // 1 = at the rate this is polled
179 	// ----
180 	MusTrackStatus song_track[MUS_MAX_CHANNELS];
181 	MusSong *song;
182 	Uint8 song_counter;
183 	Uint16 song_position;
184 	CydEngine *cyd;
185 	Uint8 current_tick;
186 	Uint8 volume, play_volume; // 0..128
187 	Uint8 multiplex_ctr;
188 	Uint32 flags;
189 	Uint32 ext_sync_ticks;
190 	Uint32 pitch_mask;
191 } MusEngine;
192 
193 
194 enum
195 {
196 	MUS_CHN_PLAYING = 1,
197 	MUS_CHN_PROGRAM_RUNNING = 2,
198 	MUS_CHN_DISABLED = 4
199 };
200 
201 enum
202 {
203 	MUS_NOTE_NONE = 0xff,
204 	MUS_NOTE_RELEASE = 0xfe
205 };
206 
207 enum
208 {
209 	MUS_PAK_BIT_NOTE = 1,
210 	MUS_PAK_BIT_INST = 2,
211 	MUS_PAK_BIT_CTRL = 4,
212 	MUS_PAK_BIT_CMD = 8,
213 	/* -- these go in ctrl byte -- */
214 	MUS_PAK_BIT_VOLUME = 128
215 };
216 
217 enum
218 {
219 	MUS_EXT_SYNC = 1
220 };
221 
222 #define MUS_NOTE_VOLUME_SET_PAN 0xa0
223 #define MUS_NOTE_VOLUME_PAN_LEFT 0xb0
224 #define MUS_NOTE_VOLUME_PAN_RIGHT 0xc0
225 #define MUS_NOTE_VOLUME_FADE_UP 0xe0
226 #define MUS_NOTE_VOLUME_FADE_DN 0xd0
227 #define MUS_NOTE_NO_VOLUME 0xff
228 #define MUS_NOTE_NO_INSTRUMENT 0xff
229 #define MUS_CTRL_BIT 1
230 #define MAX_VOLUME 128
231 
232 enum
233 {
234 	MUS_FX_ARPEGGIO = 0x0000,
235 	MUS_FX_ARPEGGIO_ABS = 0x4000,
236 	MUS_FX_SET_EXT_ARP = 0x1000,
237 	MUS_FX_PORTA_UP = 0x0100,
238 	MUS_FX_PORTA_DN = 0x0200,
239 	MUS_FX_PORTA_UP_LOG = 0x0500,
240 	MUS_FX_PORTA_DN_LOG = 0x0600,
241 	MUS_FX_SLIDE = 0x0300,
242 	MUS_FX_VIBRATO = 0x0400,
243 	MUS_FX_FADE_VOLUME = 0x0a00,
244 	MUS_FX_SET_VOLUME = 0x0c00,
245 	MUS_FX_LOOP_PATTERN = 0x0d00,
246 	MUS_FX_SKIP_PATTERN = 0x2d00,
247 	MUS_FX_EXT = 0x0e00,
248 	MUS_FX_EXT_PORTA_UP = 0x0e10,
249 	MUS_FX_EXT_PORTA_DN = 0x0e20,
250 	MUS_FX_EXT_RETRIGGER = 0x0e90,
251 	MUS_FX_EXT_FADE_VOLUME_DN = 0x0ea0,
252 	MUS_FX_EXT_FADE_VOLUME_UP = 0x0eb0,
253 	MUS_FX_EXT_NOTE_CUT = 0x0ec0,
254 	MUS_FX_EXT_NOTE_DELAY = 0x0ed0,
255 	MUS_FX_SET_SPEED = 0x0f00,
256 	MUS_FX_SET_RATE = 0x1f00,
257 	MUS_FX_PORTA_UP_SEMI = 0x1100,
258 	MUS_FX_PORTA_DN_SEMI = 0x1200,
259 	MUS_FX_SET_PANNING = 0x1800,
260 	MUS_FX_PAN_LEFT = 0x1700,
261 	MUS_FX_PAN_RIGHT = 0x1900,
262 	MUS_FX_FADE_GLOBAL_VOLUME = 0x1a00,
263 	MUS_FX_SET_GLOBAL_VOLUME = 0x1d00,
264 	MUS_FX_SET_CHANNEL_VOLUME = 0x1c00,
265 	MUS_FX_CUTOFF_UP = 0x2100,
266 	MUS_FX_CUTOFF_DN = 0x2200,
267 	MUS_FX_CUTOFF_SET = 0x2900,
268 	MUS_FX_RESONANCE_SET = 0x2a00,
269 	MUS_FX_FILTER_TYPE = 0x2b00,
270 	MUS_FX_CUTOFF_SET_COMBINED = 0x2c00,
271 	MUS_FX_BUZZ_UP = 0x3100,
272 	MUS_FX_BUZZ_DN = 0x3200,
273 	MUS_FX_BUZZ_SHAPE = 0x3f00,
274 	MUS_FX_BUZZ_SET = 0x3900,
275 	MUS_FX_BUZZ_SET_SEMI = 0x3a00,
276 	MUS_FX_FM_SET_MODULATION = 0x3300,
277 	MUS_FX_FM_SET_FEEDBACK = 0x3400,
278 	MUS_FX_FM_SET_HARMONIC = 0x3500,
279 	MUS_FX_FM_SET_WAVEFORM = 0x3600,
280 	MUS_FX_PW_DN = 0x0700,
281 	MUS_FX_PW_UP = 0x0800,
282 	MUS_FX_PW_SET = 0x0900,
283 	MUS_FX_SET_WAVEFORM = 0x0b00,
284 	MUS_FX_SET_FXBUS = 0x1b00,
285 	MUS_FX_SET_SYNCSRC = 0x7a00,
286 	MUS_FX_SET_RINGSRC = 0x7b00,
287 	MUS_FX_SET_WAVETABLE_ITEM = 0x3b00,
288 	MUS_FX_SET_DOWNSAMPLE = 0x1e00,
289 	MUS_FX_WAVETABLE_OFFSET = 0x5000,
290 	MUS_FX_CUTOFF_FINE_SET = 0x6000,
291 	MUS_FX_END = 0xffff,
292 	MUS_FX_JUMP = 0xff00,
293 	MUS_FX_LABEL = 0xfd00,
294 	MUS_FX_LOOP = 0xfe00,
295 	MUS_FX_TRIGGER_RELEASE = 0x7c00,
296 	MUS_FX_RESTART_PROGRAM = 0x7d00,
297 	MUS_FX_NOP = 0xfffe
298 };
299 
300 enum
301 {
302 	MUS_CTRL_LEGATO = MUS_CTRL_BIT,
303 	MUS_CTRL_SLIDE = MUS_CTRL_BIT << 1,
304 	MUS_CTRL_VIB = MUS_CTRL_BIT << 2
305 
306 };
307 
308 enum
309 {
310 	MUS_ENABLE_REVERB = 1,
311 	MUS_ENABLE_CRUSH = 2,
312 	MUS_ENABLE_MULTIPLEX = 4,
313 	MUS_NO_REPEAT = 8
314 };
315 
316 enum
317 {
318 	MUS_SHAPE_SINE,
319 	MUS_SHAPE_RAMP_UP,
320 	MUS_SHAPE_RAMP_DN,
321 	MUS_SHAPE_RANDOM,
322 	MUS_SHAPE_SQUARE,
323 	MUS_NUM_SHAPES
324 };
325 
326 #define MUS_INST_SIG "cyd!inst"
327 #define MUS_SONG_SIG "cyd!song"
328 #define MUS_FX_SIG "cyd!efex"
329 
330 #ifdef USESDL_RWOPS
331 #include "SDL_rwops.h"
332 typedef SDL_RWops RWops;
333 #else
334 
335 typedef struct RWops
336 {
337 	int (*read)(struct RWops *context, void *ptr, int size, int maxnum);
338 	int (*close)(struct RWops *context);
339 	union {
340 		FILE *fp;
341 		struct
342 		{
343 			Uint32 ptr, length;
344 			void *base;
345 		} mem;
346 	};
347 	int close_fp;
348 } RWops;
349 
350 #endif
351 
352 int mus_advance_tick(void* udata);
353 int mus_trigger_instrument(MusEngine* mus, int chan, MusInstrument *ins, Uint16 note, int panning);
354 void mus_set_channel_volume(MusEngine* mus, int chan, int volume);
355 void mus_release(MusEngine* mus, int chan);
356 void mus_init_engine(MusEngine *mus, CydEngine *cyd);
357 void mus_set_song(MusEngine *mus, MusSong *song, Uint16 position);
358 int mus_poll_status(MusEngine *mus, int *song_position, int *pattern_position, MusPattern **pattern, MusChannel *channel, int *cyd_env, int *mus_note, Uint64 *time_played);
359 int mus_load_instrument_file(Uint8 version, FILE *f, MusInstrument *inst, CydWavetableEntry *wavetable_entries);
360 int mus_load_instrument_file2(FILE *f, MusInstrument *inst, CydWavetableEntry *wavetable_entries);
361 int mus_load_instrument_RW(Uint8 version, RWops *ctx, MusInstrument *inst, CydWavetableEntry *wavetable_entries);
362 int mus_load_instrument_RW2(RWops *ctx, MusInstrument *inst, CydWavetableEntry *wavetable_entries);
363 int mus_load_instrument(const char *path, MusInstrument *inst, CydWavetableEntry *wavetable_entries);
364 void mus_get_default_instrument(MusInstrument *inst);
365 int mus_load_song(const char *path, MusSong *song, CydWavetableEntry *wavetable_entries);
366 int mus_load_song_file(FILE *f, MusSong *song, CydWavetableEntry *wavetable_entries);
367 int mus_load_song_RW(RWops *rw, MusSong *song, CydWavetableEntry *wavetable_entries);
368 int mus_load_fx_RW(RWops *ctx, CydFxSerialized *fx);
369 int mus_load_fx_file(FILE *f, CydFxSerialized *fx);
370 int mus_load_fx(const char *path, CydFxSerialized *fx);
371 void mus_free_song(MusSong *song);
372 void mus_set_fx(MusEngine *mus, MusSong *song);
373 Uint32 mus_ext_sync(MusEngine *mus);
374 Uint32 mus_get_playtime_at(MusSong *song, int position);
375 
376 #endif
377