1 /*
2 Copyright (c) 2009-2010 Tero Lindeman (kometbomb)
3 
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use,
8 copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following
11 conditions:
12 
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 */
25 
26 #define GENERATE_VIBRATO_TABLES
27 
28 #include "music.h"
29 #include <assert.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include "freqs.h"
34 #include "macros.h"
35 #include "pack.h"
36 
37 #ifdef GENERATE_VIBRATO_TABLES
38 
39 #include <math.h>
40 
41 #endif
42 
43 #define VIB_TAB_SIZE 128
44 
45 #ifndef GENERATE_VIBRATO_TABLES
46 
47 static const Sint8 rnd_table[VIB_TAB_SIZE] = {
48 	110, -1, 88, -31, 64,
49 	-13, 29, -70, -113, 71,
50 	99, -71, 74, 82, 52,
51 	-82, -58, 37, 20, -76,
52 	46, -97, -69, 41, 31,
53 	-62, -5, 99, -2, -48,
54 	-89, 17, -19, 4, -27,
55 	-43, -20, 25, 112, -34,
56 	78, 26, -56, -54, 72,
57 	-75, 22, 72, -119, 115,
58 	56, -66, 25, 87, 93,
59 	14, 82, 127, 79, -40,
60 	-100, 21, 17, 17, -116,
61 	-110, 61, -99, 105, 73,
62 	116, 53, -9, 105, 91,
63 	120, -73, 112, -10, 66,
64 	-10, -30, 99, -67, 60,
65 	84, 110, 87, -27, -46,
66 	114, 77, -27, -46, 75,
67 	-78, 83, -110, 92, -9,
68 	107, -64, 31, 77, -39,
69 	115, 126, -7, 121, -2,
70 	66, 116, -45, 91, 1,
71 	-96, -27, 17, 76, -82,
72 	58, -7, 75, -35, 49,
73 	3, -52, 40
74 };
75 
76 static const Sint8 sine_table[VIB_TAB_SIZE] =
77 {
78 	0, 6, 12, 18, 24, 31, 37, 43, 48, 54, 60, 65, 71, 76, 81, 85, 90, 94, 98, 102, 106, 109, 112,
79 	115, 118, 120, 122, 124, 125, 126, 127, 127, 127, 127, 127, 126, 125, 124, 122, 120, 118, 115, 112,
80 	109, 106, 102, 98, 94, 90, 85, 81, 76, 71, 65, 60, 54, 48, 43, 37, 31, 24, 18, 12, 6,
81 	0, -6, -12, -18, -24, -31, -37, -43, -48, -54, -60, -65, -71, -76, -81, -85, -90, -94, -98, -102,
82 	-106, -109, -112, -115, -118, -120, -122, -124, -125, -126, -127, -127, -128, -127, -127, -126, -125, -124, -122,
83 	-120, -118, -115, -112, -109, -106, -102, -98, -94, -90, -85, -81, -76, -71, -65, -60, -54, -48, -43, -37, -31, -24, -18, -12, -6
84 };
85 
86 #else
87 
88 static Sint8 rnd_table[VIB_TAB_SIZE];
89 static Sint8 sine_table[VIB_TAB_SIZE];
90 
91 #endif
92 
93 static int mus_trigger_instrument_internal(MusEngine* mus, int chan, MusInstrument *ins, Uint16 note, int panning);
94 
95 #ifndef USESDL_RWOPS
96 
RWread(struct RWops * context,void * ptr,int size,int maxnum)97 static int RWread(struct RWops *context, void *ptr, int size, int maxnum)
98 {
99 	return fread(ptr, size, maxnum, context->fp);
100 }
101 
102 
RWclose(struct RWops * context)103 static int RWclose(struct RWops *context)
104 {
105 	if (context->close_fp) fclose(context->fp);
106 	free(context);
107 	return 1;
108 }
109 
110 
111 #define my_RWread(ctx, ptr, size, maxnum) ctx->read(ctx, ptr, size, maxnum)
112 #define my_RWclose(ctx) ctx->close(ctx)
113 #define my_RWtell(ctx) 0
114 
115 
116 #else
117 
118 #include "SDL_rwops.h"
119 
120 #define my_RWread SDL_RWread
121 #define my_RWclose SDL_RWclose
122 #define my_RWtell SDL_RWtell
123 
124 
125 #endif
126 
127 
RWFromFP(FILE * f,int close)128 static RWops * RWFromFP(FILE *f, int close)
129 {
130 #ifdef USESDL_RWOPS
131 	SDL_RWops *rw = SDL_RWFromFP(f, close);
132 
133 	if (!rw)
134 	{
135 		warning("SDL_RWFromFP: %s", SDL_GetError());
136 	}
137 
138 	return rw;
139 #else
140 	RWops *rw = calloc(sizeof(*rw), 1);
141 
142 	rw->fp = f;
143 	rw->close_fp = close;
144 	rw->read = RWread;
145 	rw->close = RWclose;
146 
147 	return rw;
148 #endif
149 }
150 
151 
RWFromFile(const char * name,const char * mode)152 static RWops * RWFromFile(const char *name, const char *mode)
153 {
154 #ifdef USESDL_RWOPS
155 	return SDL_RWFromFile(name, mode);
156 #else
157 	FILE *f = fopen(name, mode);
158 
159 	if (!f) return NULL;
160 
161 	return RWFromFP(f, 1);
162 #endif
163 }
164 
165 
166 
update_volumes(MusEngine * mus,MusTrackStatus * ts,MusChannel * chn,CydChannel * cydchn,int volume)167 static void update_volumes(MusEngine *mus, MusTrackStatus *ts, MusChannel *chn, CydChannel *cydchn, int volume)
168 {
169 	if (chn->instrument && (chn->instrument->flags & MUS_INST_RELATIVE_VOLUME))
170 	{
171 		ts->volume = volume;
172 		cydchn->adsr.volume = (chn->flags & MUS_CHN_DISABLED) ? 0 : (int)chn->instrument->volume * volume / MAX_VOLUME * (int)mus->volume / MAX_VOLUME * (int)mus->play_volume / MAX_VOLUME * (int)chn->volume / MAX_VOLUME;
173 	}
174 	else
175 	{
176 		ts->volume = volume;
177 		cydchn->adsr.volume = (chn->flags & MUS_CHN_DISABLED) ? 0 : ts->volume * (int)mus->volume / MAX_VOLUME * (int)mus->play_volume / MAX_VOLUME * (int)chn->volume / MAX_VOLUME;
178 	}
179 }
180 
181 
update_all_volumes(MusEngine * mus)182 static void update_all_volumes(MusEngine *mus)
183 {
184 	for (int i = 0 ; i < MUS_MAX_CHANNELS && i < mus->cyd->n_channels ; ++i)
185 		update_volumes(mus, &mus->song_track[i], &mus->channel[i], &mus->cyd->channel[i], mus->song_track[i].volume);
186 }
187 
188 
mus_set_buzz_frequency(MusEngine * mus,int chan,Uint16 note)189 static void mus_set_buzz_frequency(MusEngine *mus, int chan, Uint16 note)
190 {
191 #ifndef CYD_DISABLE_BUZZ
192 	MusChannel *chn = &mus->channel[chan];
193 	if (chn->instrument && chn->instrument->flags & MUS_INST_YM_BUZZ)
194 	{
195 #ifndef CYD_DISABLE_INACCURACY
196 		Uint16 buzz_frequency = get_freq(note + chn->buzz_offset) & mus->pitch_mask;
197 #else
198 		Uint16 buzz_frequency = get_freq(note + chn->buzz_offset);
199 #endif
200 		cyd_set_env_frequency(mus->cyd, &mus->cyd->channel[chan], buzz_frequency);
201 	}
202 #endif
203 }
204 
205 
mus_set_wavetable_frequency(MusEngine * mus,int chan,Uint16 note)206 static void mus_set_wavetable_frequency(MusEngine *mus, int chan, Uint16 note)
207 {
208 #ifndef CYD_DISABLE_WAVETABLE
209 	MusChannel *chn = &mus->channel[chan];
210 	CydChannel *cydchn = &mus->cyd->channel[chan];
211 	MusTrackStatus *track_status = &mus->song_track[chan];
212 
213 	if (chn->instrument && (chn->instrument->cydflags & CYD_CHN_ENABLE_WAVE) && (cydchn->wave_entry))
214 	{
215 		for (int s = 0 ; s < CYD_SUB_OSCS ; ++s)
216 		{
217 			Uint16 final = 0;
218 
219 			if (s == 0 || (chn->instrument->flags & MUS_INST_MULTIOSC))
220 			{
221 				switch (s)
222 				{
223 					default:
224 					case 0:
225 						final = note;
226 						break;
227 
228 					case 1:
229 						if (track_status->extarp1 != 0)
230 							final = note + ((Uint16)track_status->extarp1 << 8);
231 						else
232 							final = 0;
233 						break;
234 
235 					case 2:
236 						if (track_status->extarp2 != 0)
237 							final = note + ((Uint16)track_status->extarp2 << 8);
238 						else
239 							final = 0;
240 						break;
241 				}
242 			}
243 
244 			Uint16 wave_frequency = 0;
245 
246 			if (final != 0)
247 			{
248 #ifndef CYD_DISABLE_INACCURACY
249 				wave_frequency = get_freq((chn->instrument->flags & MUS_INST_WAVE_LOCK_NOTE) ? cydchn->wave_entry->base_note : (final)) & mus->pitch_mask;
250 #else
251 				wave_frequency = get_freq((chn->instrument->flags & MUS_INST_WAVE_LOCK_NOTE) ? cydchn->wave_entry->base_note : (final));
252 #endif
253 			}
254 
255 			cyd_set_wavetable_frequency(mus->cyd, cydchn, s, wave_frequency);
256 		}
257 	}
258 #endif
259 }
260 
261 
mus_set_frequency(MusEngine * mus,int chan,Uint16 note,int divider)262 static void mus_set_frequency(MusEngine *mus, int chan, Uint16 note, int divider)
263 {
264 	MusChannel *chn = &mus->channel[chan];
265 	MusTrackStatus *track_status = &mus->song_track[chan];
266 
267 	for (int s = 0 ; s < CYD_SUB_OSCS ; ++s)
268 	{
269 		Uint16 final = 0;
270 
271 		if (s == 0 || (chn->instrument->flags & MUS_INST_MULTIOSC))
272 		{
273 			switch (s)
274 			{
275 				default:
276 				case 0:
277 					final = note;
278 					break;
279 
280 				case 1:
281 					if (track_status->extarp1 != 0)
282 						final = note + ((Uint16)track_status->extarp1 << 8);
283 					else
284 						final = 0;
285 					break;
286 
287 				case 2:
288 					if (track_status->extarp2 != 0)
289 						final = note + ((Uint16)track_status->extarp2 << 8);
290 					else
291 						final = 0;
292 					break;
293 			}
294 		}
295 
296 		Uint16 frequency = 0;
297 
298 		if (final != 0)
299 		{
300 #ifndef CYD_DISABLE_INACCURACY
301 			frequency = get_freq(final) & mus->pitch_mask;
302 #else
303 			frequency = get_freq(final);
304 #endif
305 		}
306 
307 		cyd_set_frequency(mus->cyd, &mus->cyd->channel[chan], s, frequency / divider);
308 	}
309 }
310 
311 
mus_set_note(MusEngine * mus,int chan,Uint16 note,int update_note,int divider)312 static void mus_set_note(MusEngine *mus, int chan, Uint16 note, int update_note, int divider)
313 {
314 	MusChannel *chn = &mus->channel[chan];
315 
316 	if (update_note) chn->note = note;
317 
318 	mus_set_frequency(mus, chan, note, divider);
319 
320 	mus_set_wavetable_frequency(mus, chan, note);
321 
322 	mus_set_buzz_frequency(mus, chan, note);
323 }
324 
325 
mus_set_slide(MusEngine * mus,int chan,Uint16 note)326 static void mus_set_slide(MusEngine *mus, int chan, Uint16 note)
327 {
328 	MusChannel *chn = &mus->channel[chan];
329 	chn->target_note = note;
330 	//if (update_note) chn->note = note;
331 }
332 
333 
mus_init_engine(MusEngine * mus,CydEngine * cyd)334 void mus_init_engine(MusEngine *mus, CydEngine *cyd)
335 {
336 	memset(mus, 0, sizeof(*mus));
337 	mus->cyd = cyd;
338 	mus->volume = MAX_VOLUME;
339 	mus->play_volume = MAX_VOLUME;
340 
341 	for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
342 		mus->channel[i].volume = MAX_VOLUME;
343 
344 #ifndef CYD_DISABLE_INACCURACY
345 	mus->pitch_mask = ~0;
346 #endif
347 
348 #ifdef GENERATE_VIBRATO_TABLES
349 	for (int i = 0 ; i < VIB_TAB_SIZE ; ++i)
350 	{
351 		sine_table[i] = sin((float)i / VIB_TAB_SIZE * M_PI * 2) * 127;
352 		rnd_table[i] = rand();
353 	}
354 #endif
355 }
356 
357 
do_command(MusEngine * mus,int chan,int tick,Uint16 inst,int from_program)358 static void do_command(MusEngine *mus, int chan, int tick, Uint16 inst, int from_program)
359 {
360 	MusChannel *chn = &mus->channel[chan];
361 	CydChannel *cydchn = &mus->cyd->channel[chan];
362 	CydEngine *cyd = mus->cyd;
363 	MusTrackStatus *track_status = &mus->song_track[chan];
364 
365 	switch (inst & 0x7f00)
366 	{
367 		case MUS_FX_PORTA_UP:
368 		{
369 			Uint16 prev = chn->note;
370 			chn->note += ((inst & 0xff) << 2);
371 			if (prev > chn->note) chn->note = 0xffff;
372 
373 			mus_set_slide(mus, chan, chn->note);
374 		}
375 		break;
376 
377 		case MUS_FX_PORTA_DN:
378 		{
379 			Uint16 prev = chn->note;
380 			chn->note -= ((inst & 0xff) << 2);
381 
382 			if (prev < chn->note) chn->note = 0x0;
383 
384 			mus_set_slide(mus, chan, chn->note);
385 		}
386 		break;
387 
388 		case MUS_FX_PORTA_UP_LOG:
389 		{
390 			Uint16 prev = chn->note;
391 			chn->note += my_max(1, ((Uint32)frequency_table[MIDDLE_C] * (Uint32)(inst & 0xff) / (Uint32)get_freq(chn->note)));
392 
393 			if (prev > chn->note) chn->note = 0xffff;
394 
395 			mus_set_slide(mus, chan, chn->note);
396 		}
397 		break;
398 
399 		case MUS_FX_PORTA_DN_LOG:
400 		{
401 			Uint16 prev = chn->note;
402 			chn->note -= my_max(1, ((Uint32)frequency_table[MIDDLE_C] * (Uint32)(inst & 0xff) / (Uint32)get_freq(chn->note)));
403 
404 			if (prev < chn->note) chn->note = 0x0;
405 
406 			mus_set_slide(mus, chan, chn->note);
407 		}
408 		break;
409 
410 		case MUS_FX_PW_DN:
411 		{
412 			track_status->pw -= inst & 0xff;
413 			if (track_status->pw > 0xf000) track_status->pw = 0;
414 		}
415 		break;
416 
417 		case MUS_FX_PW_UP:
418 		{
419 			track_status->pw += inst & 0xff;
420 			if (track_status->pw > 0x7ff) track_status->pw = 0x7ff;
421 		}
422 		break;
423 
424 #ifndef CYD_DISABLE_FILTER
425 		case MUS_FX_CUTOFF_DN:
426 		{
427 			track_status->filter_cutoff -= inst & 0xff;
428 			if (track_status->filter_cutoff > 0xf000) track_status->filter_cutoff = 0;
429 			cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, track_status->filter_resonance);
430 		}
431 		break;
432 
433 		case MUS_FX_CUTOFF_UP:
434 		{
435 			track_status->filter_cutoff += inst & 0xff;
436 			if (track_status->filter_cutoff > 0x7ff) track_status->filter_cutoff = 0x7ff;
437 			cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, track_status->filter_resonance);
438 		}
439 		break;
440 #endif
441 
442 #ifndef CYD_DISABLE_BUZZ
443 		case MUS_FX_BUZZ_DN:
444 		{
445 			if (chn->buzz_offset >= -32768 + (inst & 0xff))
446 				chn->buzz_offset -= inst & 0xff;
447 
448 			mus_set_buzz_frequency(mus, chan, chn->note);
449 		}
450 		break;
451 
452 		case MUS_FX_BUZZ_UP:
453 		{
454 			if (chn->buzz_offset <= 32767 - (inst & 0xff))
455 				chn->buzz_offset += inst & 0xff;
456 
457 			mus_set_buzz_frequency(mus, chan, chn->note);
458 		}
459 		break;
460 #endif
461 		case MUS_FX_TRIGGER_RELEASE:
462 		{
463 			if (tick == (inst & 0xff))
464 				cyd_enable_gate(mus->cyd, cydchn, 0);
465 		}
466 		break;
467 
468 		case MUS_FX_FADE_VOLUME:
469 		{
470 			if (!(chn->flags & MUS_CHN_DISABLED))
471 			{
472 				track_status->volume -= inst & 0xf;
473 				if (track_status->volume > MAX_VOLUME) track_status->volume = 0;
474 				track_status->volume += (inst >> 4) & 0xf;
475 				if (track_status->volume > MAX_VOLUME) track_status->volume = MAX_VOLUME;
476 
477 				update_volumes(mus, track_status, chn, cydchn, track_status->volume);
478 			}
479 		}
480 		break;
481 #ifdef STEREOOUTPUT
482 		case MUS_FX_PAN_RIGHT:
483 		case MUS_FX_PAN_LEFT:
484 		{
485 			int p = cydchn->panning;
486 			if ((inst & 0xff00) == MUS_FX_PAN_LEFT)
487 			{
488 				p -= inst & 0x00ff;
489 			}
490 			else
491 			{
492 				p += inst & 0x00ff;
493 			}
494 
495 			p = my_min(CYD_PAN_RIGHT, my_max(CYD_PAN_LEFT, p));
496 
497 			cyd_set_panning(mus->cyd, cydchn, p);
498 		}
499 		break;
500 #endif
501 		case MUS_FX_EXT:
502 		{
503 			// Protracker style Exy commands
504 
505 			switch (inst & 0xfff0)
506 			{
507 				case MUS_FX_EXT_NOTE_CUT:
508 				{
509 					if (!(chn->flags & MUS_CHN_DISABLED))
510 					{
511 						if ((inst & 0xf) <= tick)
512 						{
513 							cydchn->adsr.volume = 0;
514 							track_status->volume = 0;
515 						}
516 					}
517 				}
518 				break;
519 
520 				case MUS_FX_EXT_RETRIGGER:
521 				{
522 					if ((inst & 0xf) > 0 && (tick % (inst & 0xf)) == 0)
523 					{
524 						Uint8 prev_vol_tr = track_status->volume;
525 						Uint8 prev_vol_cyd = cydchn->adsr.volume;
526 						mus_trigger_instrument_internal(mus, chan, chn->instrument, chn->last_note, -1);
527 						track_status->volume = prev_vol_tr;
528 						cydchn->adsr.volume = prev_vol_cyd;
529 					}
530 				}
531 				break;
532 			}
533 		}
534 		break;
535 	}
536 
537 	if (tick == 0)
538 	{
539 		// --- commands that run only on tick 0
540 
541 		switch (inst & 0xff00)
542 		{
543 			case MUS_FX_EXT:
544 			{
545 				// Protracker style Exy commands
546 
547 				switch (inst & 0xfff0)
548 				{
549 					case MUS_FX_EXT_FADE_VOLUME_DN:
550 					{
551 						if (!(chn->flags & MUS_CHN_DISABLED))
552 						{
553 							track_status->volume -= inst & 0xf;
554 							if (track_status->volume > MAX_VOLUME) track_status->volume = 0;
555 
556 							update_volumes(mus, track_status, chn, cydchn, track_status->volume);
557 						}
558 					}
559 					break;
560 
561 					case MUS_FX_EXT_FADE_VOLUME_UP:
562 					{
563 						if (!(chn->flags & MUS_CHN_DISABLED))
564 						{
565 							track_status->volume += inst & 0xf;
566 							if (track_status->volume > MAX_VOLUME) track_status->volume = MAX_VOLUME;
567 
568 							update_volumes(mus, track_status, chn, cydchn, track_status->volume);
569 						}
570 					}
571 					break;
572 
573 					case MUS_FX_EXT_PORTA_UP:
574 					{
575 						Uint16 prev = chn->note;
576 						chn->note += ((inst & 0x0f));
577 
578 						if (prev > chn->note) chn->note = 0xffff;
579 
580 						mus_set_slide(mus, chan, chn->note);
581 					}
582 					break;
583 
584 					case MUS_FX_EXT_PORTA_DN:
585 					{
586 						Uint16 prev = chn->note;
587 						chn->note -= ((inst & 0x0f));
588 
589 						if (prev < chn->note) chn->note = 0x0;
590 
591 						mus_set_slide(mus, chan, chn->note);
592 					}
593 					break;
594 				}
595 			}
596 			break;
597 
598 			default:
599 
600 			switch (inst & 0xf000)
601 			{
602 #ifndef CYD_DISABLE_FILTER
603 				case MUS_FX_CUTOFF_FINE_SET:
604 				{
605 					track_status->filter_cutoff = (inst & 0xfff);
606 					if (track_status->filter_cutoff > 0x7ff) track_status->filter_cutoff = 0x7ff;
607 					cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, track_status->filter_resonance);
608 				}
609 				break;
610 #endif
611 
612 #ifndef CYD_DISABLE_WAVETABLE
613 				case MUS_FX_WAVETABLE_OFFSET:
614 				{
615 					cyd_set_wavetable_offset(cydchn, inst & 0xfff);
616 				}
617 				break;
618 #endif
619 			}
620 
621 			switch (inst & 0x7f00)
622 			{
623 				case MUS_FX_SET_GLOBAL_VOLUME:
624 				{
625 					mus->play_volume = my_min((inst & 0xff), MAX_VOLUME);
626 
627 					update_all_volumes(mus);
628 				}
629 				break;
630 
631 				case MUS_FX_FADE_GLOBAL_VOLUME:
632 				{
633 					mus->play_volume -= inst & 0xf;
634 
635 					if (mus->play_volume > MAX_VOLUME) mus->play_volume = 0;
636 
637 					mus->play_volume += (inst & 0xf0) >> 4;
638 
639 					if (mus->play_volume > MAX_VOLUME) mus->play_volume = MAX_VOLUME;
640 
641 					update_all_volumes(mus);
642 				}
643 				break;
644 
645 				case MUS_FX_SET_CHANNEL_VOLUME:
646 				{
647 					chn->volume = my_min((inst & 0xff), MAX_VOLUME);
648 					update_volumes(mus, track_status, chn, cydchn, track_status->volume);
649 				}
650 				break;
651 
652 				case MUS_FX_PW_SET:
653 				{
654 					track_status->pw = (inst & 0xff) << 4;
655 				}
656 				break;
657 #ifndef CYD_DISABLE_BUZZ
658 				case MUS_FX_BUZZ_SHAPE:
659 				{
660 					cyd_set_env_shape(cydchn, inst & 3);
661 				}
662 				break;
663 
664 				case MUS_FX_BUZZ_SET_SEMI:
665 				{
666 					chn->buzz_offset = (((inst & 0xff)) - 0x80) << 8;
667 
668 					mus_set_buzz_frequency(mus, chan, chn->note);
669 				}
670 				break;
671 
672 				case MUS_FX_BUZZ_SET:
673 				{
674 					chn->buzz_offset = (chn->buzz_offset & 0xff00) | (inst & 0xff);
675 
676 					mus_set_buzz_frequency(mus, chan, chn->note);
677 				}
678 				break;
679 #endif
680 
681 #ifndef CYD_DISABLE_FM
682 				case MUS_FX_FM_SET_MODULATION:
683 				{
684 					cydchn->fm.adsr.volume = inst % MAX_VOLUME;
685 				}
686 				break;
687 
688 				case MUS_FX_FM_SET_HARMONIC:
689 				{
690 					cydchn->fm.harmonic = inst % 256;
691 				}
692 				break;
693 
694 				case MUS_FX_FM_SET_FEEDBACK:
695 				{
696 					cydchn->fm.feedback = inst % 8;
697 				}
698 				break;
699 
700 				case MUS_FX_FM_SET_WAVEFORM:
701 				{
702 					if ((inst & 255) < CYD_WAVE_MAX_ENTRIES)
703 					{
704 						cydchn->fm.wave_entry = &mus->cyd->wavetable_entries[inst & 255];
705 					}
706 				}
707 				break;
708 #endif
709 
710 #ifdef STEREOOUTPUT
711 				case MUS_FX_SET_PANNING:
712 				{
713 					cyd_set_panning(mus->cyd, cydchn, inst & 0xff);
714 				}
715 				break;
716 #endif
717 
718 #ifndef CYD_DISABLE_FILTER
719 				case MUS_FX_FILTER_TYPE:
720 				{
721 					cydchn->flttype = (inst & 0xf) % FLT_TYPES;
722 				}
723 				break;
724 
725 				case MUS_FX_CUTOFF_SET:
726 				{
727 					track_status->filter_cutoff = (inst & 0xff) << 3;
728 					if (track_status->filter_cutoff > 0x7ff) track_status->filter_cutoff = 0x7ff;
729 					cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, track_status->filter_resonance);
730 				}
731 				break;
732 
733 				case MUS_FX_CUTOFF_SET_COMBINED:
734 				{
735 					if ((inst & 0xff) < 0x80)
736 					{
737 						track_status->filter_cutoff = (inst & 0xff) << 4;
738 						cydchn->flttype = FLT_LP;
739 						cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, track_status->filter_resonance);
740 					}
741 					else
742 					{
743 						track_status->filter_cutoff = ((inst & 0xff) - 0x80) << 4;
744 						cydchn->flttype = FLT_HP;
745 						cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, track_status->filter_resonance);
746 					}
747 				}
748 				break;
749 
750 				case MUS_FX_RESONANCE_SET:
751 				{
752 					track_status->filter_resonance = inst & 3;
753 					cyd_set_filter_coeffs(mus->cyd, cydchn, track_status->filter_cutoff, inst & 3);
754 				}
755 				break;
756 #endif
757 
758 				case MUS_FX_SET_SPEED:
759 				{
760 					if (from_program)
761 					{
762 						chn->prog_period = inst & 0xff;
763 					}
764 					else
765 					{
766 						mus->song->song_speed = inst & 0xf;
767 						if ((inst & 0xf0) == 0) mus->song->song_speed2 = mus->song->song_speed;
768 						else mus->song->song_speed2 = (inst >> 4) & 0xf;
769 					}
770 				}
771 				break;
772 
773 				case MUS_FX_SET_RATE:
774 				{
775 					mus->song->song_rate = inst & 0xff;
776 					if (mus->song->song_rate < 1) mus->song->song_rate = 1;
777 					cyd_set_callback_rate(mus->cyd, mus->song->song_rate);
778 				}
779 				break;
780 
781 				case MUS_FX_PORTA_UP_SEMI:
782 				{
783 					Uint16 prev = chn->note;
784 					chn->note += (inst&0xff) << 8;
785 					if (prev > chn->note || chn->note >= (FREQ_TAB_SIZE << 8)) chn->note = ((FREQ_TAB_SIZE-1) << 8);
786 					mus_set_slide(mus, chan, chn->note);
787 				}
788 				break;
789 
790 				case MUS_FX_PORTA_DN_SEMI:
791 				{
792 					Uint16 prev = chn->note;
793 					chn->note -= (inst&0xff) << 8;
794 					if (prev < chn->note) chn->note = 0x0;
795 					mus_set_slide(mus, chan, chn->note);
796 				}
797 				break;
798 
799 				case MUS_FX_ARPEGGIO_ABS:
800 				{
801 					chn->arpeggio_note = 0;
802 					chn->fixed_note = (inst & 0xff) << 8;
803 				}
804 				break;
805 
806 				case MUS_FX_ARPEGGIO:
807 				{
808 					if (chn->fixed_note != 0xffff)
809 					{
810 						chn->note = chn->last_note;
811 						chn->fixed_note = 0xffff;
812 					}
813 
814 					if ((inst & 0xff) == 0xf0)
815 						chn->arpeggio_note = track_status->extarp1;
816 					else if ((inst & 0xff) == 0xf1)
817 						chn->arpeggio_note = track_status->extarp2;
818 					else
819 						chn->arpeggio_note = inst & 0xff;
820 				}
821 				break;
822 
823 				case MUS_FX_SET_VOLUME:
824 				{
825 					track_status->volume = my_min(MAX_VOLUME, inst & 0xff);
826 
827 					update_volumes(mus, track_status, chn, cydchn, track_status->volume);
828 				}
829 				break;
830 
831 				case MUS_FX_SET_SYNCSRC:
832 				{
833 					if ((inst & 0xff) != 0xff)
834 					{
835 						cydchn->sync_source = (inst & 0xff) % CYD_MAX_FX_CHANNELS;
836 						cydchn->flags |= CYD_CHN_ENABLE_SYNC;
837 					}
838 					else
839 						cydchn->flags &= ~CYD_CHN_ENABLE_SYNC;
840 				}
841 				break;
842 
843 				case MUS_FX_SET_RINGSRC:
844 				{
845 					if ((inst & 0xff) != 0xff)
846 					{
847 						cydchn->ring_mod = (inst & 0xff) % CYD_MAX_FX_CHANNELS;
848 						cydchn->flags |= CYD_CHN_ENABLE_RING_MODULATION;
849 					}
850 					else
851 						cydchn->flags &= ~CYD_CHN_ENABLE_RING_MODULATION;
852 				}
853 				break;
854 
855 #ifndef CYD_DISABLE_FX
856 				case MUS_FX_SET_FXBUS:
857 				{
858 					cydchn->fx_bus = (inst & 0xff) % CYD_MAX_FX_CHANNELS;
859 				}
860 				break;
861 
862 				case MUS_FX_SET_DOWNSAMPLE:
863 				{
864 					cydcrush_set(&cyd->fx[cydchn->fx_bus].crush, inst & 0xff, -1, -1, -1);
865 				}
866 				break;
867 #endif
868 
869 #ifndef CYD_DISABLE_WAVETABLE
870 				case MUS_FX_SET_WAVETABLE_ITEM:
871 				{
872 					if ((inst & 255) < CYD_WAVE_MAX_ENTRIES)
873 					{
874 						cydchn->wave_entry = &mus->cyd->wavetable_entries[inst & 255];
875 					}
876 				}
877 				break;
878 #endif
879 
880 				case MUS_FX_SET_WAVEFORM:
881 				{
882 					int final = 0;
883 
884 					if (inst & MUS_FX_WAVE_NOISE)
885 						final |= CYD_CHN_ENABLE_NOISE;
886 
887 					if (inst & MUS_FX_WAVE_PULSE)
888 						final |= CYD_CHN_ENABLE_PULSE;
889 
890 					if (inst & MUS_FX_WAVE_TRIANGLE)
891 						final |= CYD_CHN_ENABLE_TRIANGLE;
892 
893 					if (inst & MUS_FX_WAVE_SAW)
894 						final |= CYD_CHN_ENABLE_SAW;
895 
896 					if (inst & MUS_FX_WAVE_WAVE)
897 						final |= CYD_CHN_ENABLE_WAVE;
898 
899 #ifndef CYD_DISABLE_LFSR
900 					if (inst & MUS_FX_WAVE_LFSR)
901 						final |= CYD_CHN_ENABLE_LFSR;
902 #endif
903 
904 					cyd_set_waveform(cydchn, final);
905 				}
906 				break;
907 
908 				case MUS_FX_RESTART_PROGRAM:
909 				{
910 					if (!from_program)
911 					{
912 						chn->program_counter = 0;
913 						chn->program_tick = 0;
914 						chn->program_loop = 1;
915 					}
916 				}
917 				break;
918 			}
919 
920 			break;
921 		}
922 	}
923 }
924 
925 
mus_exec_track_command(MusEngine * mus,int chan,int first_tick)926 static void mus_exec_track_command(MusEngine *mus, int chan, int first_tick)
927 {
928 	MusTrackStatus *track_status = &mus->song_track[chan];
929 	const Uint16 inst = track_status->pattern->step[track_status->pattern_step].command;
930 	const Uint8 vol = track_status->pattern->step[track_status->pattern_step].volume;
931 
932 	switch (vol & 0xf0)
933 	{
934 		case MUS_NOTE_VOLUME_PAN_LEFT:
935 			do_command(mus, chan, mus->song_counter, MUS_FX_PAN_LEFT | ((Uint16)(vol & 0xf)), 0);
936 			break;
937 
938 		case MUS_NOTE_VOLUME_PAN_RIGHT:
939 			do_command(mus, chan, mus->song_counter, MUS_FX_PAN_RIGHT | ((Uint16)(vol & 0xf)), 0);
940 			break;
941 
942 		case MUS_NOTE_VOLUME_SET_PAN:
943 			{
944 			Uint16 val = vol & 0xf;
945 			Uint16 panning = (val <= 8 ? val * CYD_PAN_CENTER / 8 : (val - 8) * (CYD_PAN_RIGHT - CYD_PAN_CENTER) / 8 + CYD_PAN_CENTER);
946 			do_command(mus, chan, mus->song_counter, MUS_FX_SET_PANNING | panning, 0);
947 			debug("Panned to %x", panning);
948 			}
949 			break;
950 
951 		case MUS_NOTE_VOLUME_FADE_UP:
952 			do_command(mus, chan, mus->song_counter, MUS_FX_FADE_VOLUME | ((Uint16)(vol & 0xf) << 4), 0);
953 			break;
954 
955 		case MUS_NOTE_VOLUME_FADE_DN:
956 			do_command(mus, chan, mus->song_counter, MUS_FX_FADE_VOLUME | ((Uint16)(vol & 0xf)), 0);
957 			break;
958 
959 		default:
960 			if (vol <= MAX_VOLUME)
961 				do_command(mus, chan, first_tick ? 0 : mus->song_counter, MUS_FX_SET_VOLUME | (Uint16)(vol), 0);
962 			break;
963 	}
964 
965 	switch (inst & 0xff00)
966 	{
967 		case MUS_FX_ARPEGGIO:
968 			if (!(inst & 0xff)) break; // no params = use the same settings
969 		case MUS_FX_SET_EXT_ARP:
970 		{
971 			track_status->extarp1 = (inst & 0xf0) >> 4;
972 			track_status->extarp2 = (inst & 0xf);
973 		}
974 		break;
975 
976 		default:
977 		do_command(mus, chan, mus->song_counter, inst, 0);
978 		break;
979 	}
980 }
981 
982 
mus_exec_prog_tick(MusEngine * mus,int chan,int advance)983 static void mus_exec_prog_tick(MusEngine *mus, int chan, int advance)
984 {
985 	MusChannel *chn = &mus->channel[chan];
986 	int tick = chn->program_tick;
987 	int visited[MUS_PROG_LEN] = { 0 };
988 
989 	do_it_again:;
990 
991 	const Uint16 inst = chn->instrument->program[tick];
992 
993 	switch (inst)
994 	{
995 		case MUS_FX_END:
996 		{
997 			chn->flags &= ~MUS_CHN_PROGRAM_RUNNING;
998 			return;
999 		}
1000 		break;
1001 	}
1002 
1003 	int dont_reloop = 0;
1004 
1005 	if(inst != MUS_FX_NOP)
1006 	{
1007 		switch (inst & 0xff00)
1008 		{
1009 			case MUS_FX_JUMP:
1010 			{
1011 				/* This should handle infinite jumping between two jump instructions (program hang) */
1012 
1013 				if (!visited[tick])
1014 				{
1015 					visited[tick] = 1;
1016 					tick = inst & (MUS_PROG_LEN - 1);
1017 				}
1018 				else return;
1019 			}
1020 			break;
1021 
1022 			case MUS_FX_LABEL:
1023 			{
1024 
1025 
1026 			}
1027 			break;
1028 
1029 			case MUS_FX_LOOP:
1030 			{
1031 				if (chn->program_loop == (inst & 0xff))
1032 				{
1033 					if (advance) chn->program_loop = 1;
1034 				}
1035 				else
1036 				{
1037 					if (advance) ++chn->program_loop;
1038 
1039 					int l = 0;
1040 
1041 					while ((chn->instrument->program[tick] & 0xff00) != MUS_FX_LABEL && tick > 0)
1042 					{
1043 						--tick;
1044 						if (!(chn->instrument->program[tick] & 0x8000)) ++l;
1045 					}
1046 
1047 					--tick;
1048 
1049 					dont_reloop = l <= 1;
1050 				}
1051 			}
1052 			break;
1053 
1054 			default:
1055 
1056 			do_command(mus, chan, chn->program_counter, inst, 1);
1057 
1058 			break;
1059 		}
1060 	}
1061 
1062 	if (inst == MUS_FX_NOP || (inst & 0xff00) != MUS_FX_JUMP)
1063 	{
1064 		++tick;
1065 		if (tick >= MUS_PROG_LEN)
1066 		{
1067 			tick = 0;
1068 		}
1069 	}
1070 
1071 	// skip to next on msb
1072 
1073 	if ((inst & 0x8000) && inst != MUS_FX_NOP && !dont_reloop)
1074 	{
1075 		goto do_it_again;
1076 	}
1077 
1078 	if (advance)
1079 	{
1080 		chn->program_tick = tick;
1081 	}
1082 }
1083 
mus_shape(Uint16 position,Uint8 shape)1084 static Sint8 mus_shape(Uint16 position, Uint8 shape)
1085 {
1086 	switch (shape)
1087 	{
1088 		case MUS_SHAPE_SINE:
1089 			return sine_table[position % VIB_TAB_SIZE];
1090 			break;
1091 
1092 		case MUS_SHAPE_SQUARE:
1093 			return ((position % VIB_TAB_SIZE) & (VIB_TAB_SIZE / 2)) ? -128 : 127;
1094 			break;
1095 
1096 		case MUS_SHAPE_RAMP_UP:
1097 			return (position % VIB_TAB_SIZE) * 2 - 128;
1098 			break;
1099 
1100 		case MUS_SHAPE_RAMP_DN:
1101 			return 127 - (position % VIB_TAB_SIZE) * 2;
1102 			break;
1103 
1104 		default:
1105 		case MUS_SHAPE_RANDOM:
1106 			return rnd_table[(position / 8) % VIB_TAB_SIZE];
1107 			break;
1108 	}
1109 }
1110 
1111 
1112 #ifndef CYD_DISABLE_PWM
1113 
do_pwm(MusEngine * mus,int chan)1114 static void do_pwm(MusEngine* mus, int chan)
1115 {
1116 	MusChannel *chn = &mus->channel[chan];
1117 	MusInstrument *ins = chn->instrument;
1118 	MusTrackStatus *track_status = &mus->song_track[chan];
1119 
1120 	track_status->pwm_position += ins->pwm_speed;
1121 	mus->cyd->channel[chan].pw = track_status->pw + mus_shape(track_status->pwm_position >> 1, ins->pwm_shape) * ins->pwm_depth / 32;
1122 }
1123 
1124 #endif
1125 
1126 
1127 //***** USE THIS INSIDE MUS_ADVANCE_TICK TO AVOID MUTEX DEADLOCK
mus_trigger_instrument_internal(MusEngine * mus,int chan,MusInstrument * ins,Uint16 note,int panning)1128 int mus_trigger_instrument_internal(MusEngine* mus, int chan, MusInstrument *ins, Uint16 note, int panning)
1129 {
1130 	if (chan == -1)
1131 	{
1132 		for (int i = 0 ; i < mus->cyd->n_channels ; ++i)
1133 		{
1134 			if (!(mus->cyd->channel[i].flags & CYD_CHN_ENABLE_GATE))
1135 				chan = i;
1136 		}
1137 
1138 		if (chan == -1)
1139 			chan = (rand() %  mus->cyd->n_channels);
1140 	}
1141 
1142 	CydChannel *cydchn = &mus->cyd->channel[chan];
1143 	MusChannel *chn = &mus->channel[chan];
1144 	MusTrackStatus *track = &mus->song_track[chan];
1145 
1146 	chn->flags = MUS_CHN_PLAYING | (chn->flags & MUS_CHN_DISABLED);
1147 	if (ins->prog_period > 0) chn->flags |= MUS_CHN_PROGRAM_RUNNING;
1148 	chn->prog_period = ins->prog_period;
1149 	chn->instrument = ins;
1150 	if (!(ins->flags & MUS_INST_NO_PROG_RESTART))
1151 	{
1152 		chn->program_counter = 0;
1153 		chn->program_tick = 0;
1154 		chn->program_loop = 1;
1155 	}
1156 	cydchn->flags = ins->cydflags;
1157 	chn->arpeggio_note = 0;
1158 	chn->fixed_note = 0xffff;
1159 	cydchn->fx_bus = ins->fx_bus;
1160 
1161 	if (ins->flags & MUS_INST_DRUM)
1162 	{
1163 		cyd_set_waveform(cydchn, CYD_CHN_ENABLE_NOISE);
1164 	}
1165 
1166 	if (ins->flags & MUS_INST_LOCK_NOTE)
1167 	{
1168 		note = ((Uint16)ins->base_note) << 8;
1169 	}
1170 	else
1171 	{
1172 		note += (Uint16)((int)ins->base_note-MIDDLE_C) << 8;
1173 	}
1174 
1175 	mus_set_note(mus, chan, ((Uint16)note) + ins->finetune, 1, ins->flags & MUS_INST_QUARTER_FREQ ? 4 : 1);
1176 	chn->last_note = chn->target_note = (((Uint16)note) + ins->finetune);
1177 	chn->current_tick = 0;
1178 
1179 	track->vibrato_position = 0;
1180 	track->vib_delay = ins->vib_delay;
1181 
1182 	track->slide_speed = 0;
1183 
1184 	update_volumes(mus, track, chn, cydchn, (ins->flags & MUS_INST_RELATIVE_VOLUME) ? MAX_VOLUME : ins->volume);
1185 
1186 	cydchn->sync_source = ins->sync_source == 0xff? chan : ins->sync_source;
1187 	cydchn->ring_mod = ins->ring_mod == 0xff? chan : ins->ring_mod;
1188 
1189 	if (cydchn->ring_mod >= mus->cyd->n_channels)
1190 		cydchn->ring_mod = mus->cyd->n_channels -1;
1191 
1192 	if (cydchn->sync_source >= mus->cyd->n_channels)
1193 		cydchn->sync_source = mus->cyd->n_channels -1;
1194 
1195 	cydchn->flttype = ins->flttype;
1196 	cydchn->lfsr_type = ins->lfsr_type;
1197 
1198 	if (ins->cydflags & CYD_CHN_ENABLE_KEY_SYNC)
1199 	{
1200 		track->pwm_position = 0;
1201 	}
1202 
1203 #ifndef CYD_DISABLE_FILTER
1204 	if (ins->flags & MUS_INST_SET_CUTOFF)
1205 	{
1206 		track->filter_cutoff = ins->cutoff;
1207 		track->filter_resonance = ins->resonance;
1208 		cyd_set_filter_coeffs(mus->cyd, cydchn, ins->cutoff, ins->resonance);
1209 	}
1210 #endif
1211 
1212 	if (ins->flags & MUS_INST_SET_PW)
1213 	{
1214 		track->pw = ins->pw;
1215 #ifndef CYD_DISABLE_PWM
1216 		do_pwm(mus,chan);
1217 #endif
1218 	}
1219 
1220 	if (ins->flags & MUS_INST_YM_BUZZ)
1221 	{
1222 #ifndef CYD_DISABLE_BUZZ
1223 		cydchn->flags |= CYD_CHN_ENABLE_YM_ENV;
1224 		cyd_set_env_shape(cydchn, ins->ym_env_shape);
1225 		mus->channel[chan].buzz_offset = ins->buzz_offset;
1226 #endif
1227 	}
1228 	else
1229 	{
1230 		cydchn->flags &= ~CYD_CHN_ENABLE_YM_ENV;
1231 
1232 
1233 		cydchn->adsr.a = ins->adsr.a;
1234 		cydchn->adsr.d = ins->adsr.d;
1235 		cydchn->adsr.s = ins->adsr.s;
1236 		cydchn->adsr.r = ins->adsr.r;
1237 	}
1238 
1239 #ifndef CYD_DISABLE_WAVETABLE
1240 	if (ins->cydflags & CYD_CHN_ENABLE_WAVE)
1241 	{
1242 		cyd_set_wave_entry(cydchn, &mus->cyd->wavetable_entries[ins->wavetable_entry]);
1243 	}
1244 	else
1245 	{
1246 		cyd_set_wave_entry(cydchn, NULL);
1247 	}
1248 
1249 #ifndef CYD_DISABLE_FM
1250 	if (ins->fm_flags & CYD_FM_ENABLE_WAVE)
1251 	{
1252 		cydfm_set_wave_entry(&cydchn->fm, &mus->cyd->wavetable_entries[ins->fm_wave]);
1253 	}
1254 	else
1255 	{
1256 		cydfm_set_wave_entry(&cydchn->fm, NULL);
1257 	}
1258 #endif
1259 #endif
1260 
1261 #ifdef STEREOOUTPUT
1262 	if (panning != -1)
1263 		cyd_set_panning(mus->cyd, cydchn, panning);
1264 
1265 #endif
1266 
1267 #ifndef CYD_DISABLE_FM
1268 	CydFm *fm = &cydchn->fm;
1269 
1270 	fm->flags = ins->fm_flags;
1271 	fm->harmonic = ins->fm_harmonic;
1272 	fm->adsr.a = ins->fm_adsr.a;
1273 	fm->adsr.d = ins->fm_adsr.d;
1274 	fm->adsr.s = ins->fm_adsr.s;
1275 	fm->adsr.r = ins->fm_adsr.r;
1276 	fm->adsr.volume = ins->fm_modulation;
1277 	fm->feedback = ins->fm_feedback;
1278 	fm->attack_start = ins->fm_attack_start;
1279 #endif
1280 
1281 	//cyd_set_frequency(mus->cyd, cydchn, chn->frequency);
1282 	cyd_enable_gate(mus->cyd, cydchn, 1);
1283 
1284 	return chan;
1285 }
1286 
1287 
mus_trigger_instrument(MusEngine * mus,int chan,MusInstrument * ins,Uint16 note,int panning)1288 int mus_trigger_instrument(MusEngine* mus, int chan, MusInstrument *ins, Uint16 note, int panning)
1289 {
1290 	cyd_lock(mus->cyd, 1);
1291 
1292 	chan = mus_trigger_instrument_internal(mus, chan, ins, note, panning);
1293 
1294 	cyd_lock(mus->cyd, 0);
1295 
1296 	return chan;
1297 }
1298 
1299 
mus_advance_channel(MusEngine * mus,int chan)1300 static void mus_advance_channel(MusEngine* mus, int chan)
1301 {
1302 	MusChannel *chn = &mus->channel[chan];
1303 	MusTrackStatus *track_status = &mus->song_track[chan];
1304 
1305 	if (!(mus->cyd->channel[chan].flags & CYD_CHN_ENABLE_GATE))
1306 	{
1307 		chn->flags &= ~MUS_CHN_PLAYING;
1308 		return;
1309 	}
1310 
1311 	MusInstrument *ins = chn->instrument;
1312 
1313 	if (ins->flags & MUS_INST_DRUM && chn->current_tick == 1)
1314 	{
1315 		cyd_set_waveform(&mus->cyd->channel[chan], ins->cydflags);
1316 	}
1317 
1318 	if (track_status->slide_speed != 0)
1319 	{
1320 		if (chn->target_note > chn->note)
1321 		{
1322 			chn->note += my_min((Uint16)track_status->slide_speed, chn->target_note - chn->note);
1323 		}
1324 		else if (chn->target_note < chn->note)
1325 		{
1326 			chn->note -= my_min((Uint16)track_status->slide_speed , chn->note - chn->target_note);
1327 		}
1328 	}
1329 
1330 	++chn->current_tick;
1331 
1332 	if (mus->channel[chan].flags & MUS_CHN_PROGRAM_RUNNING)
1333 	{
1334 		int u = (chn->program_counter + 1) >= chn->prog_period;
1335 		mus_exec_prog_tick(mus, chan, u);
1336 		++chn->program_counter;
1337 		if (u) chn->program_counter = 0;
1338 
1339 		/*++chn->program_counter;
1340 		if (chn->program_counter >= chn->instrument->prog_period)
1341 		{
1342 			++chn->program_tick;
1343 
1344 			if (chn->program_tick >= MUS_PROG_LEN)
1345 			{
1346 				chn->program_tick = 0;
1347 			}
1348 			chn->program_counter = 0;
1349 		}*/
1350 	}
1351 
1352 #ifndef CYD_DISABLE_VIBRATO
1353 
1354 	Uint8 ctrl = 0;
1355 	int vibdep = my_max(0, (int)ins->vibrato_depth - (int)track_status->vib_delay);
1356 	int vibspd = ins->vibrato_speed;
1357 
1358 	if (track_status->pattern)
1359 	{
1360 		ctrl = track_status->pattern->step[track_status->pattern_step].ctrl;
1361 		if ((track_status->pattern->step[track_status->pattern_step].command & 0xff00) == MUS_FX_VIBRATO)
1362 		{
1363 			ctrl |= MUS_CTRL_VIB;
1364 			if (track_status->pattern->step[track_status->pattern_step].command & 0xff)
1365 			{
1366 				vibdep = (track_status->pattern->step[track_status->pattern_step].command & 0xf) << 2;
1367 				vibspd = (track_status->pattern->step[track_status->pattern_step].command & 0xf0) >> 2;
1368 
1369 				if (!vibspd)
1370 					vibspd = ins->vibrato_speed;
1371 				if (!vibdep)
1372 					vibdep = ins->vibrato_depth;
1373 			}
1374 		}
1375 
1376 		/*do_vib(mus, chan, track_status->pattern->step[track_status->pattern_step].ctrl);
1377 
1378 		if ((track_status->last_ctrl & MUS_CTRL_VIB) && !(track_status->pattern->step[track_status->pattern_step].ctrl & MUS_CTRL_VIB))
1379 		{
1380 			cyd_set_frequency(mus->cyd, &mus->cyd->channel[chan], mus->channel[chan].frequency);
1381 		}
1382 
1383 		track_status->last_ctrl = track_status->pattern->step[track_status->pattern_step].ctrl;*/
1384 	}
1385 
1386 #endif
1387 
1388 	Sint16 vib = 0;
1389 
1390 #ifndef CYD_DISABLE_VIBRATO
1391 	if (((ctrl & MUS_CTRL_VIB) && !(ins->flags & MUS_INST_INVERT_VIBRATO_BIT)) || (!(ctrl & MUS_CTRL_VIB) && (ins->flags & MUS_INST_INVERT_VIBRATO_BIT)))
1392 	{
1393 		track_status->vibrato_position += vibspd;
1394 		vib = mus_shape(track_status->vibrato_position >> 1, ins->vib_shape) * vibdep / 64;
1395 		if (track_status->vib_delay) --track_status->vib_delay;
1396 	}
1397 #endif
1398 
1399 #ifndef CYD_DISABLE_PWM
1400 	do_pwm(mus, chan);
1401 #endif
1402 
1403 	Sint32 note = (mus->channel[chan].fixed_note != 0xffff ? mus->channel[chan].fixed_note : mus->channel[chan].note) + vib + ((Uint16)mus->channel[chan].arpeggio_note << 8);
1404 
1405 	if (note < 0) note = 0;
1406 	if (note > FREQ_TAB_SIZE << 8) note = (FREQ_TAB_SIZE - 1) << 8;
1407 
1408 	mus_set_note(mus, chan, note, 0, ins->flags & MUS_INST_QUARTER_FREQ ? 4 : 1);
1409 }
1410 
1411 
mus_ext_sync(MusEngine * mus)1412 Uint32 mus_ext_sync(MusEngine *mus)
1413 {
1414 	cyd_lock(mus->cyd, 1);
1415 
1416 	Uint32 s = ++mus->ext_sync_ticks;
1417 
1418 	cyd_lock(mus->cyd, 0);
1419 
1420 	return s;
1421 }
1422 
1423 
mus_advance_tick(void * udata)1424 int mus_advance_tick(void* udata)
1425 {
1426 	MusEngine *mus = udata;
1427 
1428 	if (!(mus->flags & MUS_EXT_SYNC))
1429 		mus->ext_sync_ticks = 1;
1430 
1431 	while (mus->ext_sync_ticks-- > 0)
1432 	{
1433 		if (mus->song)
1434 		{
1435 			for (int i = 0 ; i < mus->song->num_channels ; ++i)
1436 			{
1437 				MusTrackStatus *track_status = &mus->song_track[i];
1438 				CydChannel *cydchn = &mus->cyd->channel[i];
1439 				MusChannel *muschn = &mus->channel[i];
1440 
1441 				if (mus->song_counter == 0)
1442 				{
1443 					while (track_status->sequence_position < mus->song->num_sequences[i] && mus->song->sequence[i][track_status->sequence_position].position <= mus->song_position)
1444 					{
1445 						track_status->pattern = &mus->song->pattern[mus->song->sequence[i][track_status->sequence_position].pattern];
1446 						track_status->pattern_step = mus->song_position - mus->song->sequence[i][track_status->sequence_position].position;
1447 						if (track_status->pattern_step >= mus->song->pattern[mus->song->sequence[i][track_status->sequence_position].pattern].num_steps)
1448 							track_status->pattern = NULL;
1449 						track_status->note_offset = mus->song->sequence[i][track_status->sequence_position].note_offset;
1450 						++track_status->sequence_position;
1451 					}
1452 				}
1453 
1454 				int delay = 0;
1455 
1456 				if (track_status->pattern)
1457 				{
1458 					if ((track_status->pattern->step[track_status->pattern_step].command & 0x7FF0) == MUS_FX_EXT_NOTE_DELAY)
1459 						delay = track_status->pattern->step[track_status->pattern_step].command & 0xf;
1460 				}
1461 
1462 				if (mus->song_counter == delay)
1463 				{
1464 					if (track_status->pattern)
1465 					{
1466 
1467 						if (1 || track_status->pattern_step == 0)
1468 						{
1469 							Uint8 note = track_status->pattern->step[track_status->pattern_step].note < 0xf0 ?
1470 								track_status->pattern->step[track_status->pattern_step].note + track_status->note_offset :
1471 								track_status->pattern->step[track_status->pattern_step].note;
1472 							Uint8 inst = track_status->pattern->step[track_status->pattern_step].instrument;
1473 							MusInstrument *pinst = NULL;
1474 
1475 							if (inst == MUS_NOTE_NO_INSTRUMENT)
1476 							{
1477 								pinst = muschn->instrument;
1478 							}
1479 							else
1480 							{
1481 								if (inst < mus->song->num_instruments)
1482 								{
1483 									pinst = &mus->song->instrument[inst];
1484 									muschn->instrument = pinst;
1485 								}
1486 							}
1487 
1488 							if (note == MUS_NOTE_RELEASE)
1489 							{
1490 								cyd_enable_gate(mus->cyd, &mus->cyd->channel[i], 0);
1491 							}
1492 							else if (pinst && note != MUS_NOTE_NONE)
1493 							{
1494 								track_status->slide_speed = 0;
1495 								int speed = pinst->slide_speed | 1;
1496 								Uint8 ctrl = track_status->pattern->step[track_status->pattern_step].ctrl;
1497 
1498 								if ((track_status->pattern->step[track_status->pattern_step].command & 0xff00) == MUS_FX_SLIDE)
1499 								{
1500 									ctrl |= MUS_CTRL_SLIDE | MUS_CTRL_LEGATO;
1501 									speed = (track_status->pattern->step[track_status->pattern_step].command & 0xff);
1502 								}
1503 
1504 								if (ctrl & MUS_CTRL_SLIDE)
1505 								{
1506 									if (ctrl & MUS_CTRL_LEGATO)
1507 									{
1508 										mus_set_slide(mus, i, (((Uint16)note + pinst->base_note - MIDDLE_C) << 8) + pinst->finetune);
1509 									}
1510 									else
1511 									{
1512 										Uint16 oldnote = muschn->note;
1513 										mus_trigger_instrument_internal(mus, i, pinst, note << 8, -1);
1514 										muschn->note = oldnote;
1515 									}
1516 									track_status->slide_speed = speed;
1517 								}
1518 								else if (ctrl & MUS_CTRL_LEGATO)
1519 								{
1520 									mus_set_note(mus, i, (((Uint16)note + pinst->base_note - MIDDLE_C) << 8) + pinst->finetune, 1, pinst->flags & MUS_INST_QUARTER_FREQ ? 4 : 1);
1521 									muschn->target_note = (((Uint16)note + pinst->base_note - MIDDLE_C) << 8) + pinst->finetune;
1522 								}
1523 								else
1524 								{
1525 									Uint8 prev_vol_track = track_status->volume;
1526 									Uint8 prev_vol_cyd = cydchn->adsr.volume;
1527 									mus_trigger_instrument_internal(mus, i, pinst, note << 8, -1);
1528 									muschn->target_note = (((Uint16)note + pinst->base_note - MIDDLE_C) << 8) + pinst->finetune;
1529 
1530 									if (inst == MUS_NOTE_NO_INSTRUMENT)
1531 									{
1532 										track_status->volume = prev_vol_track;
1533 										cydchn->adsr.volume = prev_vol_cyd;
1534 									}
1535 								}
1536 
1537 								if (inst != MUS_NOTE_NO_INSTRUMENT)
1538 								{
1539 									if (pinst->flags & MUS_INST_RELATIVE_VOLUME)
1540 									{
1541 										track_status->volume = MAX_VOLUME;
1542 										cydchn->adsr.volume = (muschn->flags & MUS_CHN_DISABLED)
1543 											? 0
1544 											: (int)pinst->volume * (int)mus->volume / MAX_VOLUME * (int)mus->play_volume / MAX_VOLUME * (int)muschn->volume / MAX_VOLUME;
1545 									}
1546 									else
1547 									{
1548 										track_status->volume = pinst->volume;
1549 										cydchn->adsr.volume = (muschn->flags & MUS_CHN_DISABLED) ? 0 : (int)pinst->volume * (int)mus->volume / MAX_VOLUME * (int)mus->play_volume / MAX_VOLUME * (int)muschn->volume / MAX_VOLUME;
1550 									}
1551 								}
1552 							}
1553 						}
1554 					}
1555 				}
1556 
1557 				if (track_status->pattern) mus_exec_track_command(mus, i, mus->song_counter == delay);
1558 			}
1559 
1560 			++mus->song_counter;
1561 			if (mus->song_counter >= ((!(mus->song_position & 1)) ? mus->song->song_speed : mus->song->song_speed2))
1562 			{
1563 				for (int i = 0 ; i < mus->cyd->n_channels ; ++i)
1564 				{
1565 					MusTrackStatus *track_status = &mus->song_track[i];
1566 
1567 					if (track_status->pattern)
1568 					{
1569 						Uint32 command = track_status->pattern->step[track_status->pattern_step].command;
1570 						if ((command & 0xff00) == MUS_FX_LOOP_PATTERN)
1571 						{
1572 							Uint16 step = command & 0xff;
1573 							track_status->pattern_step = step;
1574 						}
1575 						else if ((command & 0xff00) == MUS_FX_SKIP_PATTERN)
1576 						{
1577 							mus->song_position += my_max(track_status->pattern->num_steps - track_status->pattern_step - 1, 0);
1578 							track_status->pattern = NULL;
1579 							track_status->pattern_step = 0;
1580 						}
1581 						else
1582 						{
1583 							++track_status->pattern_step;
1584 						}
1585 
1586 						if (track_status->pattern && track_status->pattern_step >= track_status->pattern->num_steps)
1587 						{
1588 							track_status->pattern = NULL;
1589 							track_status->pattern_step = 0;
1590 						}
1591 					}
1592 				}
1593 				mus->song_counter = 0;
1594 				++mus->song_position;
1595 				if (mus->song_position >= mus->song->song_length)
1596 				{
1597 					if (mus->song->flags & MUS_NO_REPEAT)
1598 						return 0;
1599 
1600 					mus->song_position = mus->song->loop_point;
1601 					for (int i = 0 ; i < mus->cyd->n_channels ; ++i)
1602 					{
1603 						MusTrackStatus *track_status = &mus->song_track[i];
1604 
1605 						track_status->pattern = NULL;
1606 						track_status->pattern_step = 0;
1607 						track_status->sequence_position = 0;
1608 					}
1609 				}
1610 			}
1611 		}
1612 
1613 		for (int i = 0 ; i < mus->cyd->n_channels ; ++i)
1614 		{
1615 			if (mus->channel[i].flags & MUS_CHN_PLAYING)
1616 			{
1617 				mus_advance_channel(mus, i);
1618 			}
1619 		}
1620 
1621 #ifndef CYD_DISABLE_MULTIPLEX
1622 		if (mus->song && (mus->song->flags & MUS_ENABLE_MULTIPLEX) && mus->song->multiplex_period > 0)
1623 		{
1624 			for (int i = 0 ; i < mus->cyd->n_channels ; ++i)
1625 			{
1626 				CydChannel *cydchn = &mus->cyd->channel[i];
1627 
1628 				if ((mus->multiplex_ctr / mus->song->multiplex_period) == i)
1629 				{
1630 					update_volumes(mus, &mus->song_track[i], &mus->channel[i], cydchn, mus->song_track[i].volume);
1631 				}
1632 				else
1633 				{
1634 					cydchn->adsr.volume = 0;
1635 				}
1636 			}
1637 
1638 			if (++mus->multiplex_ctr >= mus->song->num_channels * mus->song->multiplex_period)
1639 				mus->multiplex_ctr = 0;
1640 		}
1641 #endif
1642 	}
1643 
1644 	return 1;
1645 }
1646 
1647 
mus_set_song(MusEngine * mus,MusSong * song,Uint16 position)1648 void mus_set_song(MusEngine *mus, MusSong *song, Uint16 position)
1649 {
1650 	cyd_lock(mus->cyd, 1);
1651 	cyd_reset(mus->cyd);
1652 	mus->song = song;
1653 
1654 	if (song != NULL)
1655 	{
1656 		mus->song_counter = 0;
1657 		mus->multiplex_ctr = 0;
1658 #ifndef CYD_DISABLE_INACCURACY
1659 		mus->pitch_mask = (~0) << song->pitch_inaccuracy;
1660 #endif
1661 	}
1662 
1663 	mus->song_position = position;
1664 	mus->play_volume = MAX_VOLUME;
1665 
1666 	for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
1667 	{
1668 		mus->song_track[i].pattern = NULL;
1669 		mus->song_track[i].pattern_step = 0;
1670 		mus->song_track[i].sequence_position = 0;
1671 		mus->song_track[i].last_ctrl = 0;
1672 		mus->song_track[i].note_offset = 0;
1673 		mus->song_track[i].extarp1 = mus->song_track[i].extarp2 = 0;
1674 
1675 		if (song)
1676 		{
1677 			mus->channel[i].volume = song->default_volume[i];
1678 #ifdef STEREOOUTPUT
1679 			if (i < mus->cyd->n_channels)
1680 				cyd_set_panning(mus->cyd, &mus->cyd->channel[i], song->default_panning[i] + CYD_PAN_CENTER);
1681 #endif
1682 		}
1683 		else
1684 		{
1685 			mus->channel[i].volume = MAX_VOLUME;
1686 		}
1687 	}
1688 
1689 	cyd_lock(mus->cyd, 0);
1690 }
1691 
1692 
mus_poll_status(MusEngine * mus,int * song_position,int * pattern_position,MusPattern ** pattern,MusChannel * channel,int * cyd_env,int * mus_note,Uint64 * time_played)1693 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)
1694 {
1695 	cyd_lock(mus->cyd, 1);
1696 
1697 	if (song_position) *song_position = mus->song_position;
1698 
1699 	if (pattern_position)
1700 	{
1701 		for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
1702 		{
1703 			pattern_position[i] = mus->song_track[i].pattern_step;
1704 		}
1705 	}
1706 
1707 	if (pattern)
1708 	{
1709 		for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
1710 		{
1711 			pattern[i] = mus->song_track[i].pattern;
1712 		}
1713 	}
1714 
1715 	if (channel)
1716 	{
1717 		memcpy(channel, mus->channel, sizeof(mus->channel));
1718 	}
1719 
1720 	if (cyd_env)
1721 	{
1722 		for (int i = 0 ; i < my_min(mus->cyd->n_channels, MUS_MAX_CHANNELS) ; ++i)
1723 		{
1724 			if (mus->cyd->channel[i].flags & CYD_CHN_ENABLE_YM_ENV)
1725 				cyd_env[i] = mus->cyd->channel[i].adsr.volume;
1726 			else
1727 				cyd_env[i] = cyd_env_output(mus->cyd, mus->cyd->channel[i].flags, &mus->cyd->channel[i].adsr, MAX_VOLUME);
1728 		}
1729 	}
1730 
1731 	if (mus_note)
1732 	{
1733 		for (int i = 0 ; i < my_min(mus->cyd->n_channels, MUS_MAX_CHANNELS) ; ++i)
1734 		{
1735 			mus_note[i] = mus->channel[i].note;
1736 		}
1737 	}
1738 
1739 	if (time_played)
1740 	{
1741 		*time_played = mus->cyd->samples_played * 1000 / mus->cyd->sample_rate;
1742 	}
1743 
1744 	cyd_lock(mus->cyd, 0);
1745 
1746 	return mus->song != NULL;
1747 }
1748 
1749 
mus_load_instrument(const char * path,MusInstrument * inst,CydWavetableEntry * wavetable_entries)1750 int mus_load_instrument(const char *path, MusInstrument *inst, CydWavetableEntry *wavetable_entries)
1751 {
1752 	RWops *ctx = RWFromFile(path, "rb");
1753 
1754 	if (ctx)
1755 	{
1756 		int r = mus_load_instrument_RW2(ctx, inst, wavetable_entries);
1757 
1758 		my_RWclose(ctx);
1759 
1760 		return r;
1761 	}
1762 
1763 	return 0;
1764 }
1765 
1766 
load_wavetable_entry(Uint8 version,CydWavetableEntry * e,RWops * ctx)1767 static void load_wavetable_entry(Uint8 version, CydWavetableEntry * e, RWops *ctx)
1768 {
1769 	VER_READ(version, 12, 0xff, &e->flags, 0);
1770 	VER_READ(version, 12, 0xff, &e->sample_rate, 0);
1771 	VER_READ(version, 12, 0xff, &e->samples, 0);
1772 	VER_READ(version, 12, 0xff, &e->loop_begin, 0);
1773 	VER_READ(version, 12, 0xff, &e->loop_end, 0);
1774 	VER_READ(version, 12, 0xff, &e->base_note, 0);
1775 
1776 	FIX_ENDIAN(e->flags);
1777 	FIX_ENDIAN(e->sample_rate);
1778 	FIX_ENDIAN(e->samples);
1779 	FIX_ENDIAN(e->loop_begin);
1780 	FIX_ENDIAN(e->loop_end);
1781 	FIX_ENDIAN(e->base_note);
1782 
1783 	if (e->samples > 0)
1784 	{
1785 		if (version < 15)
1786 		{
1787 			Sint16 *data = malloc(sizeof(data[0]) * e->samples);
1788 
1789 			my_RWread(ctx, data, sizeof(data[0]), e->samples);
1790 
1791 			cyd_wave_entry_init(e, data, e->samples, CYD_WAVE_TYPE_SINT16, 1, 1, 1);
1792 
1793 			free(data);
1794 		}
1795 		else
1796 		{
1797 			Uint32 data_size = 0;
1798 			VER_READ(version, 15, 0xff, &data_size, 0);
1799 			FIX_ENDIAN(data_size);
1800 			Uint8 *compressed = malloc(sizeof(Uint8) * data_size);
1801 
1802 			my_RWread(ctx, compressed, sizeof(Uint8), (data_size + 7) / 8); // data_size is in bits
1803 
1804 			Sint16 *data = NULL;
1805 
1806 #ifndef CYD_DISABLE_WAVETABLE
1807 			data = bitunpack(compressed, data_size, e->samples, (e->flags >> 3) & 3);
1808 #endif
1809 
1810 			if (data)
1811 			{
1812 				cyd_wave_entry_init(e, data, e->samples, CYD_WAVE_TYPE_SINT16, 1, 1, 1);
1813 				free(data);
1814 			}
1815 			else
1816 			{
1817 				warning("Sample data unpack failed");
1818 			}
1819 
1820 			free(compressed);
1821 		}
1822 	}
1823 }
1824 
1825 
find_and_load_wavetable(Uint8 version,RWops * ctx,CydWavetableEntry * wavetable_entries)1826 static int find_and_load_wavetable(Uint8 version, RWops *ctx, CydWavetableEntry *wavetable_entries)
1827 {
1828 	for (int i = 0 ; i < CYD_WAVE_MAX_ENTRIES ; ++i)
1829 	{
1830 		CydWavetableEntry *e = &wavetable_entries[i];
1831 
1832 		if (e->samples == 0)
1833 		{
1834 			load_wavetable_entry(version, e, ctx);
1835 			return i;
1836 		}
1837 	}
1838 
1839 	return 0;
1840 }
1841 
1842 
mus_load_instrument_RW(Uint8 version,RWops * ctx,MusInstrument * inst,CydWavetableEntry * wavetable_entries)1843 int mus_load_instrument_RW(Uint8 version, RWops *ctx, MusInstrument *inst, CydWavetableEntry *wavetable_entries)
1844 {
1845 	mus_get_default_instrument(inst);
1846 
1847 	debug("Loading instrument at offset %x", (Uint32)my_RWtell(ctx));
1848 
1849 	_VER_READ(&inst->flags, 0);
1850 	_VER_READ(&inst->cydflags, 0);
1851 	_VER_READ(&inst->adsr, 0);
1852 	_VER_READ(&inst->sync_source, 0);
1853 	_VER_READ(&inst->ring_mod, 0);
1854 	_VER_READ(&inst->pw, 0);
1855 	_VER_READ(&inst->volume, 0);
1856 	Uint8 progsteps = 0;
1857 	_VER_READ(&progsteps, 0);
1858 	if (progsteps)
1859 		_VER_READ(&inst->program, (int)progsteps*sizeof(inst->program[0]));
1860 	_VER_READ(&inst->prog_period, 0);
1861 	_VER_READ(&inst->vibrato_speed, 0);
1862 	_VER_READ(&inst->vibrato_depth, 0);
1863 	_VER_READ(&inst->pwm_speed, 0);
1864 	_VER_READ(&inst->pwm_depth, 0);
1865 	_VER_READ(&inst->slide_speed, 0);
1866 	_VER_READ(&inst->base_note, 0);
1867 
1868 	if (version >= 20)
1869 		_VER_READ(&inst->finetune, 0);
1870 
1871 	Uint8 len = 16;
1872 	VER_READ(version, 11, 0xff, &len, 0);
1873 	if (len)
1874 	{
1875 		memset(inst->name, 0, sizeof(inst->name));
1876 		_VER_READ(inst->name, my_min(len, sizeof(inst->name)));
1877 		inst->name[sizeof(inst->name) - 1] = '\0';
1878 	}
1879 
1880 	VER_READ(version, 1, 0xff, &inst->cutoff, 0);
1881 	VER_READ(version, 1, 0xff, &inst->resonance, 0);
1882 	VER_READ(version, 1, 0xff, &inst->flttype, 0);
1883 	VER_READ(version, 7, 0xff, &inst->ym_env_shape, 0);
1884 	VER_READ(version, 7, 0xff, &inst->buzz_offset, 0);
1885 	VER_READ(version, 10, 0xff, &inst->fx_bus, 0);
1886 	VER_READ(version, 11, 0xff, &inst->vib_shape, 0);
1887 	VER_READ(version, 11, 0xff, &inst->vib_delay, 0);
1888 	VER_READ(version, 11, 0xff, &inst->pwm_shape, 0);
1889 	VER_READ(version, 18, 0xff, &inst->lfsr_type, 0);
1890 	VER_READ(version, 12, 0xff, &inst->wavetable_entry, 0);
1891 
1892 	VER_READ(version, 23, 0xff, &inst->fm_flags, 0);
1893 	VER_READ(version, 23, 0xff, &inst->fm_modulation, 0);
1894 	VER_READ(version, 23, 0xff, &inst->fm_feedback, 0);
1895 	VER_READ(version, 23, 0xff, &inst->fm_harmonic, 0);
1896 	VER_READ(version, 23, 0xff, &inst->fm_adsr, 0);
1897 	VER_READ(version, 25, 0xff, &inst->fm_attack_start, 0);
1898 	VER_READ(version, 23, 0xff, &inst->fm_wave, 0);
1899 
1900 #ifndef CYD_DISABLE_WAVETABLE
1901 	if (wavetable_entries)
1902 	{
1903 		if (inst->wavetable_entry == 0xff)
1904 		{
1905 			inst->wavetable_entry = find_and_load_wavetable(version, ctx, wavetable_entries);
1906 		}
1907 
1908 		if (version >= 23)
1909 		{
1910 			if (inst->fm_wave == 0xff)
1911 			{
1912 				inst->fm_wave = find_and_load_wavetable(version, ctx, wavetable_entries);
1913 			}
1914 			else if (inst->fm_wave == 0xfe)
1915 			{
1916 				inst->fm_wave = inst->wavetable_entry;
1917 			}
1918 		}
1919 	}
1920 #endif
1921 
1922 	/* The file format is little-endian, the following only does something on big-endian machines */
1923 
1924 	FIX_ENDIAN(inst->flags);
1925 	FIX_ENDIAN(inst->cydflags);
1926 	FIX_ENDIAN(inst->pw);
1927 	FIX_ENDIAN(inst->cutoff);
1928 	FIX_ENDIAN(inst->buzz_offset);
1929 
1930 	for (int i = 0 ; i < progsteps ; ++i)
1931 		FIX_ENDIAN(inst->program[i]);
1932 
1933 	FIX_ENDIAN(inst->fm_flags);
1934 
1935 	if (version < 26)
1936 	{
1937 		inst->adsr.a *= ENVELOPE_SCALE;
1938 		inst->adsr.d *= ENVELOPE_SCALE;
1939 		inst->adsr.r *= ENVELOPE_SCALE;
1940 
1941 		inst->fm_adsr.a *= ENVELOPE_SCALE;
1942 		inst->fm_adsr.d *= ENVELOPE_SCALE;
1943 		inst->fm_adsr.r *= ENVELOPE_SCALE;
1944 	}
1945 
1946 	return 1;
1947 }
1948 
1949 
mus_load_instrument_RW2(RWops * ctx,MusInstrument * inst,CydWavetableEntry * wavetable_entries)1950 int mus_load_instrument_RW2(RWops *ctx, MusInstrument *inst, CydWavetableEntry *wavetable_entries)
1951 {
1952 	char id[9];
1953 
1954 	id[8] = '\0';
1955 
1956 	my_RWread(ctx, id, 8, sizeof(id[0]));
1957 
1958 	if (strcmp(id, MUS_INST_SIG) == 0)
1959 	{
1960 		Uint8 version = 0;
1961 		my_RWread(ctx, &version, 1, sizeof(version));
1962 
1963 		if (version > MUS_VERSION)
1964 			return 0;
1965 
1966 		mus_load_instrument_RW(version, ctx, inst, wavetable_entries);
1967 
1968 		return 1;
1969 	}
1970 	else
1971 	{
1972 		debug("Instrument signature does not match");
1973 		return 0;
1974 	}
1975 }
1976 
1977 
mus_get_default_instrument(MusInstrument * inst)1978 void mus_get_default_instrument(MusInstrument *inst)
1979 {
1980 	memset(inst, 0, sizeof(*inst));
1981 	inst->flags = MUS_INST_DRUM|MUS_INST_SET_PW|MUS_INST_SET_CUTOFF;
1982 	inst->pw = 0x600;
1983 	inst->cydflags = CYD_CHN_ENABLE_TRIANGLE;
1984 	inst->adsr.a = 1 * ENVELOPE_SCALE;
1985 	inst->adsr.d = 12 * ENVELOPE_SCALE;
1986 	inst->volume = MAX_VOLUME;
1987 	inst->base_note = MIDDLE_C;
1988 	inst->finetune = 0;
1989 	inst->prog_period = 2;
1990 	inst->cutoff = 2047;
1991 	inst->slide_speed = 0x80;
1992 	inst->vibrato_speed = 0x20;
1993 	inst->vibrato_depth = 0x20;
1994 	inst->vib_shape = MUS_SHAPE_SINE;
1995 	inst->vib_delay = 0;
1996 
1997 	for (int p = 0 ; p < MUS_PROG_LEN; ++p)
1998 		inst->program[p] = MUS_FX_NOP;
1999 }
2000 
2001 
mus_set_fx(MusEngine * mus,MusSong * song)2002 void mus_set_fx(MusEngine *mus, MusSong *song)
2003 {
2004 	cyd_lock(mus->cyd, 1);
2005 	for(int f = 0 ; f < CYD_MAX_FX_CHANNELS ; ++f)
2006 	{
2007 		cydfx_set(&mus->cyd->fx[f], &song->fx[f]);
2008 	}
2009 
2010 #ifndef CYD_DISABLE_INACCURACY
2011 	mus->pitch_mask = (~0) << song->pitch_inaccuracy;
2012 #endif
2013 
2014 	cyd_lock(mus->cyd, 0);
2015 }
2016 
2017 
inner_load_fx(RWops * ctx,CydFxSerialized * fx,int version)2018 static void inner_load_fx(RWops *ctx, CydFxSerialized *fx, int version)
2019 {
2020 	Uint8 padding;
2021 
2022 	debug("fx @ %u", (Uint32)my_RWtell(ctx));
2023 
2024 	if (version >= 22)
2025 	{
2026 		Uint8 len = 16;
2027 		my_RWread(ctx, &len, 1, 1);
2028 		if (len)
2029 		{
2030 			memset(fx->name, 0, sizeof(fx->name));
2031 			_VER_READ(fx->name, my_min(len, sizeof(fx->name)));
2032 			fx->name[sizeof(fx->name) - 1] = '\0';
2033 		}
2034 	}
2035 
2036 	my_RWread(ctx, &fx->flags, 1, 4);
2037 	my_RWread(ctx, &fx->crush.bit_drop, 1, 1);
2038 	my_RWread(ctx, &fx->chr.rate, 1, 1);
2039 	my_RWread(ctx, &fx->chr.min_delay, 1, 1);
2040 	my_RWread(ctx, &fx->chr.max_delay, 1, 1);
2041 	my_RWread(ctx, &fx->chr.sep, 1, 1);
2042 
2043 	Uint8 spread = 0;
2044 
2045 	if (version < 27)
2046 		my_RWread(ctx, &spread, 1, 1);
2047 
2048 	if (version < 21)
2049 		my_RWread(ctx, &padding, 1, 1);
2050 
2051 	int taps = CYDRVB_TAPS;
2052 
2053 	if (version < 27)
2054 		taps = 8;
2055 
2056 	for (int i = 0 ; i < taps ; ++i)
2057 	{
2058 		my_RWread(ctx, &fx->rvb.tap[i].delay, 2, 1);
2059 		my_RWread(ctx, &fx->rvb.tap[i].gain, 2, 1);
2060 
2061 		if (version >= 27)
2062 		{
2063 			my_RWread(ctx, &fx->rvb.tap[i].panning, 1, 1);
2064 			my_RWread(ctx, &fx->rvb.tap[i].flags, 1, 1);
2065 		}
2066 		else
2067 		{
2068 			fx->rvb.tap[i].flags = 1;
2069 
2070 			if (spread > 0)
2071 				fx->rvb.tap[i].panning = CYD_PAN_LEFT;
2072 			else
2073 				fx->rvb.tap[i].panning = CYD_PAN_CENTER;
2074 		}
2075 
2076 		FIX_ENDIAN(fx->rvb.tap[i].gain);
2077 		FIX_ENDIAN(fx->rvb.tap[i].delay);
2078 	}
2079 
2080 	if (version < 27)
2081 	{
2082 		if (spread == 0)
2083 		{
2084 			for (int i = 8 ; i < CYDRVB_TAPS ; ++i)
2085 			{
2086 				fx->rvb.tap[i].flags = 0;
2087 				fx->rvb.tap[i].delay = 1000;
2088 				fx->rvb.tap[i].gain = CYDRVB_LOW_LIMIT;
2089 			}
2090 		}
2091 		else
2092 		{
2093 			for (int i = 8 ; i < CYDRVB_TAPS ; ++i)
2094 			{
2095 				fx->rvb.tap[i].flags = 1;
2096 				fx->rvb.tap[i].panning = CYD_PAN_RIGHT;
2097 				fx->rvb.tap[i].delay = my_min(CYDRVB_SIZE, fx->rvb.tap[i - 8].delay + (fx->rvb.tap[i - 8].delay * spread) / 2000);
2098 				fx->rvb.tap[i].gain = fx->rvb.tap[i - 8].gain;
2099 			}
2100 		}
2101 	}
2102 
2103 	my_RWread(ctx, &fx->crushex.downsample, 1, 1);
2104 
2105 	if (version < 19)
2106 	{
2107 		fx->crushex.gain = 128;
2108 	}
2109 	else
2110 	{
2111 		my_RWread(ctx, &fx->crushex.gain, 1, 1);
2112 	}
2113 
2114 	FIX_ENDIAN(fx->flags);
2115 }
2116 
2117 
mus_load_fx_RW(RWops * ctx,CydFxSerialized * fx)2118 int mus_load_fx_RW(RWops *ctx, CydFxSerialized *fx)
2119 {
2120 	char id[9];
2121 	id[8] = '\0';
2122 
2123 	my_RWread(ctx, id, 8, sizeof(id[0]));
2124 
2125 	if (strcmp(id, MUS_FX_SIG) == 0)
2126 	{
2127 		Uint8 version = 0;
2128 		my_RWread(ctx, &version, 1, sizeof(version));
2129 
2130 		debug("FX version = %u", version);
2131 
2132 		inner_load_fx(ctx, fx, version);
2133 
2134 		return 1;
2135 	}
2136 	else
2137 		return 0;
2138 }
2139 
2140 
mus_load_fx_file(FILE * f,CydFxSerialized * fx)2141 int mus_load_fx_file(FILE *f, CydFxSerialized *fx)
2142 {
2143 	RWops *rw = RWFromFP(f, 0);
2144 
2145 	if (rw)
2146 	{
2147 		int r = mus_load_fx_RW(rw, fx);
2148 
2149 		my_RWclose(rw);
2150 
2151 		return r;
2152 	}
2153 
2154 	return 0;
2155 }
2156 
2157 
mus_load_fx(const char * path,CydFxSerialized * fx)2158 int mus_load_fx(const char *path, CydFxSerialized *fx)
2159 {
2160 	RWops *rw = RWFromFile(path, "rb");
2161 
2162 	if (rw)
2163 	{
2164 		int r = mus_load_fx_RW(rw, fx);
2165 
2166 		my_RWclose(rw);
2167 
2168 		return r;
2169 	}
2170 
2171 	return 0;
2172 }
2173 
2174 
mus_load_song_RW(RWops * ctx,MusSong * song,CydWavetableEntry * wavetable_entries)2175 int mus_load_song_RW(RWops *ctx, MusSong *song, CydWavetableEntry *wavetable_entries)
2176 {
2177 	char id[9];
2178 	id[8] = '\0';
2179 
2180 	my_RWread(ctx, id, 8, sizeof(id[0]));
2181 
2182 	if (strcmp(id, MUS_SONG_SIG) == 0)
2183 	{
2184 		Uint8 version = 0;
2185 		my_RWread(ctx, &version, 1, sizeof(version));
2186 
2187 		debug("Song version = %u", version);
2188 
2189 		if (version > MUS_VERSION)
2190 		{
2191 			debug("Unsupported song version");
2192 			return 0;
2193 		}
2194 
2195 		if (version >= 6)
2196 			my_RWread(ctx, &song->num_channels, 1, sizeof(song->num_channels));
2197 		else
2198 		{
2199 			if (version > 3)
2200 				song->num_channels = 4;
2201 			else
2202 				song->num_channels = 3;
2203 		}
2204 
2205 		my_RWread(ctx, &song->time_signature, 1, sizeof(song->time_signature));
2206 
2207 		if (version >= 17)
2208 		{
2209 			my_RWread(ctx, &song->sequence_step, 1, sizeof(song->sequence_step));
2210 		}
2211 
2212 		my_RWread(ctx, &song->num_instruments, 1, sizeof(song->num_instruments));
2213 		my_RWread(ctx, &song->num_patterns, 1, sizeof(song->num_patterns));
2214 		my_RWread(ctx, song->num_sequences, 1, sizeof(song->num_sequences[0]) * (int)song->num_channels);
2215 		my_RWread(ctx, &song->song_length, 1, sizeof(song->song_length));
2216 
2217 		my_RWread(ctx, &song->loop_point, 1, sizeof(song->loop_point));
2218 
2219 		if (version >= 12)
2220 			my_RWread(ctx, &song->master_volume, 1, 1);
2221 
2222 		my_RWread(ctx, &song->song_speed, 1, sizeof(song->song_speed));
2223 		my_RWread(ctx, &song->song_speed2, 1, sizeof(song->song_speed2));
2224 		my_RWread(ctx, &song->song_rate, 1, sizeof(song->song_rate));
2225 
2226 		if (version > 2) my_RWread(ctx, &song->flags, 1, sizeof(song->flags));
2227 		else song->flags = 0;
2228 
2229 		if (version >= 9) my_RWread(ctx, &song->multiplex_period, 1, sizeof(song->multiplex_period));
2230 		else song->multiplex_period = 3;
2231 
2232 		if (version >= 16)
2233 		{
2234 			my_RWread(ctx, &song->pitch_inaccuracy, 1, sizeof(song->pitch_inaccuracy));
2235 		}
2236 		else
2237 		{
2238 			song->pitch_inaccuracy = 0;
2239 		}
2240 
2241 		/* The file format is little-endian, the following only does something on big-endian machines */
2242 
2243 		FIX_ENDIAN(song->song_length);
2244 		FIX_ENDIAN(song->loop_point);
2245 		FIX_ENDIAN(song->time_signature);
2246 		FIX_ENDIAN(song->sequence_step);
2247 		FIX_ENDIAN(song->num_patterns);
2248 		FIX_ENDIAN(song->flags);
2249 
2250 		for (int i = 0 ; i < (int)song->num_channels ; ++i)
2251 			FIX_ENDIAN(song->num_sequences[i]);
2252 
2253 		Uint8 title_len = 16 + 1; // old length
2254 
2255 		if (version >= 11)
2256 		{
2257 			my_RWread(ctx, &title_len, 1, 1);
2258 		}
2259 
2260 		if (version >= 5)
2261 		{
2262 			memset(song->title, 0, sizeof(song->title));
2263 			my_RWread(ctx, song->title, 1, my_min(sizeof(song->title), title_len));
2264 			song->title[sizeof(song->title) - 1] = '\0';
2265 		}
2266 
2267 		Uint8 n_fx = 0;
2268 
2269 		if (version >= 10)
2270 			my_RWread(ctx, &n_fx, 1, sizeof(n_fx));
2271 		else if (song->flags & MUS_ENABLE_REVERB)
2272 			n_fx = 1;
2273 
2274 		if (n_fx > 0)
2275 		{
2276 			debug("Song has %u effects", n_fx);
2277 			if (version >= 10)
2278 			{
2279 				memset(&song->fx, 0, sizeof(song->fx[0]) * n_fx);
2280 
2281 				debug("Loading fx at offset %x (%d/%d)", (Uint32)my_RWtell(ctx), (int)sizeof(song->fx[0]) * n_fx, (int)sizeof(song->fx[0]));
2282 
2283 				for (int fx = 0 ; fx < n_fx ; ++fx)
2284 					inner_load_fx(ctx, &song->fx[fx], version);
2285 			}
2286 			else
2287 			{
2288 				for (int fx = 0 ; fx < n_fx ; ++fx)
2289 				{
2290 					song->fx[fx].flags = CYDFX_ENABLE_REVERB;
2291 					if (song->flags & MUS_ENABLE_CRUSH) song->fx[fx].flags |= CYDFX_ENABLE_CRUSH;
2292 
2293 					for (int i = 0 ; i < 8 ; ++i)
2294 					{
2295 						Sint32 g, d;
2296 						my_RWread(ctx, &g, 1, sizeof(g));
2297 						my_RWread(ctx, &d, 1, sizeof(d));
2298 
2299 						song->fx[fx].rvb.tap[i].gain = g;
2300 						song->fx[fx].rvb.tap[i].delay = d;
2301 						song->fx[fx].rvb.tap[i].panning = CYD_PAN_CENTER;
2302 						song->fx[fx].rvb.tap[i].flags = 1;
2303 
2304 						FIX_ENDIAN(song->fx[fx].rvb.tap[i].gain);
2305 						FIX_ENDIAN(song->fx[fx].rvb.tap[i].delay);
2306 					}
2307 				}
2308 			}
2309 		}
2310 
2311 
2312 		for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
2313 		{
2314 			song->default_volume[i] = MAX_VOLUME;
2315 			song->default_panning[i] = 0;
2316 		}
2317 
2318 		if (version >= 13)
2319 		{
2320 			debug("Loading default volumes at offset %x", (Uint32)my_RWtell(ctx));
2321 			my_RWread(ctx, &song->default_volume[0], sizeof(song->default_volume[0]), song->num_channels);
2322 			debug("Loading default panning at offset %x", (Uint32)my_RWtell(ctx));
2323 			my_RWread(ctx, &song->default_panning[0], sizeof(song->default_panning[0]), song->num_channels);
2324 		}
2325 
2326 		if (song->instrument == NULL)
2327 		{
2328 			song->instrument = malloc((size_t)song->num_instruments * sizeof(song->instrument[0]));
2329 		}
2330 
2331 		for (int i = 0 ; i < song->num_instruments; ++i)
2332 		{
2333 			mus_load_instrument_RW(version, ctx, &song->instrument[i], NULL);
2334 		}
2335 
2336 
2337 		for (int i = 0 ; i < song->num_channels ; ++i)
2338 		{
2339 			if (song->num_sequences[i] > 0)
2340 			{
2341 				if (song->sequence[i] == NULL)
2342 					song->sequence[i] = malloc((size_t)song->num_sequences[i] * sizeof(song->sequence[0][0]));
2343 
2344 				if (version < 8)
2345 				{
2346 					my_RWread(ctx, song->sequence[i], song->num_sequences[i], sizeof(song->sequence[i][0]));
2347 				}
2348 				else
2349 				{
2350 					for (int s = 0 ; s < song->num_sequences[i] ; ++s)
2351 					{
2352 						my_RWread(ctx, &song->sequence[i][s].position, 1, sizeof(song->sequence[i][s].position));
2353 						my_RWread(ctx, &song->sequence[i][s].pattern, 1, sizeof(song->sequence[i][s].pattern));
2354 						my_RWread(ctx, &song->sequence[i][s].note_offset, 1, sizeof(song->sequence[i][s].note_offset));
2355 					}
2356 				}
2357 
2358 				for (int s = 0 ; s < song->num_sequences[i] ; ++s)
2359 				{
2360 					FIX_ENDIAN(song->sequence[i][s].position);
2361 					FIX_ENDIAN(song->sequence[i][s].pattern);
2362 				}
2363 			}
2364 		}
2365 
2366 		if (song->pattern == NULL)
2367 		{
2368 			song->pattern = calloc((size_t)song->num_patterns, sizeof(song->pattern[0]));
2369 			//memset(song->pattern, 0, (size_t)song->num_patterns * sizeof(song->pattern[0]));
2370 		}
2371 
2372 		for (int i = 0 ; i < song->num_patterns; ++i)
2373 		{
2374 			Uint16 steps;
2375 			my_RWread(ctx, &steps, 1, sizeof(song->pattern[i].num_steps));
2376 
2377 			FIX_ENDIAN(steps);
2378 
2379 			if (song->pattern[i].step == NULL)
2380 				song->pattern[i].step = calloc((size_t)steps, sizeof(song->pattern[i].step[0]));
2381 			else if (steps > song->pattern[i].num_steps)
2382 				song->pattern[i].step = realloc(song->pattern[i].step, (size_t)steps * sizeof(song->pattern[i].step[0]));
2383 
2384 			song->pattern[i].num_steps = steps;
2385 
2386 			if (version >= 24)
2387 				my_RWread(ctx, &song->pattern[i].color, 1, sizeof(song->pattern[i].color));
2388 			else
2389 				song->pattern[i].color = 0;
2390 
2391 			if (version < 8)
2392 			{
2393 				size_t s = sizeof(song->pattern[i].step[0]);
2394 				if (version < 2)
2395 					s = sizeof(Uint8)*3;
2396 				else
2397 					s = sizeof(Uint8)*3 + sizeof(Uint16) + 1; // aligment issue in version 6 songs
2398 
2399 				for (int step = 0 ; step < song->pattern[i].num_steps ; ++step)
2400 				{
2401 					my_RWread(ctx, &song->pattern[i].step[step], 1, s);
2402 					FIX_ENDIAN(song->pattern[i].step[step].command);
2403 				}
2404 			}
2405 			else
2406 			{
2407 				int len = song->pattern[i].num_steps / 2 + (song->pattern[i].num_steps & 1);
2408 
2409 				Uint8 *packed = malloc(sizeof(Uint8) * len);
2410 				Uint8 *current = packed;
2411 
2412 				my_RWread(ctx, packed, sizeof(Uint8), len);
2413 
2414 				for (int s = 0 ; s < song->pattern[i].num_steps ; ++s)
2415 				{
2416 					Uint8 bits = (s & 1 || s == song->pattern[i].num_steps - 1) ? (*current & 0xf) : (*current >> 4);
2417 
2418 					if (bits & MUS_PAK_BIT_NOTE)
2419 						my_RWread(ctx, &song->pattern[i].step[s].note, 1, sizeof(song->pattern[i].step[s].note));
2420 					else
2421 						song->pattern[i].step[s].note = MUS_NOTE_NONE;
2422 
2423 					if (bits & MUS_PAK_BIT_INST)
2424 						my_RWread(ctx, &song->pattern[i].step[s].instrument, 1, sizeof(song->pattern[i].step[s].instrument));
2425 					else
2426 						song->pattern[i].step[s].instrument = MUS_NOTE_NO_INSTRUMENT;
2427 
2428 					if (bits & MUS_PAK_BIT_CTRL)
2429 					{
2430 						my_RWread(ctx, &song->pattern[i].step[s].ctrl, 1, sizeof(song->pattern[i].step[s].ctrl));
2431 
2432 						if (version >= 14)
2433 							bits |= song->pattern[i].step[s].ctrl & ~7;
2434 
2435 						song->pattern[i].step[s].ctrl &= 7;
2436 					}
2437 					else
2438 						song->pattern[i].step[s].ctrl = 0;
2439 
2440 					if (bits & MUS_PAK_BIT_CMD)
2441 						my_RWread(ctx, &song->pattern[i].step[s].command, 1, sizeof(song->pattern[i].step[s].command));
2442 					else
2443 						song->pattern[i].step[s].command = 0;
2444 
2445 					FIX_ENDIAN(song->pattern[i].step[s].command);
2446 
2447 					if (bits & MUS_PAK_BIT_VOLUME)
2448 					{
2449 						my_RWread(ctx, &song->pattern[i].step[s].volume, 1, sizeof(song->pattern[i].step[s].volume));
2450 					}
2451 					else
2452 					{
2453 						song->pattern[i].step[s].volume = MUS_NOTE_NO_VOLUME;
2454 					}
2455 
2456 					if (s & 1) ++current;
2457 				}
2458 
2459 				free(packed);
2460 			}
2461 		}
2462 
2463 		for (int i = 0 ; i < CYD_WAVE_MAX_ENTRIES ; ++i)
2464 		{
2465 			cyd_wave_entry_init(&wavetable_entries[i], NULL, 0, 0, 0, 0, 0);
2466 		}
2467 
2468 		if (version >= 12)
2469 		{
2470 			Uint8 max_wt = 0;
2471 			my_RWread(ctx, &max_wt, 1, sizeof(Uint8));
2472 
2473 			for (int i = 0 ; i < max_wt ; ++i)
2474 			{
2475 				load_wavetable_entry(version, &wavetable_entries[i], ctx);
2476 			}
2477 
2478 			song->wavetable_names = malloc(max_wt * sizeof(char*));
2479 
2480 			if (version >= 26)
2481 			{
2482 				for (int i = 0 ; i < max_wt ; ++i)
2483 				{
2484 					Uint8 len = 0;
2485 					song->wavetable_names[i] = malloc(MUS_WAVETABLE_NAME_LEN + 1);
2486 					memset(song->wavetable_names[i], 0, MUS_WAVETABLE_NAME_LEN + 1);
2487 
2488 					my_RWread(ctx, &len, 1, 1);
2489 					my_RWread(ctx, song->wavetable_names[i], len, sizeof(char));
2490 				}
2491 			}
2492 			else
2493 			{
2494 				for (int i = 0 ; i < max_wt ; ++i)
2495 				{
2496 					song->wavetable_names[i] = malloc(MUS_WAVETABLE_NAME_LEN + 1);
2497 					memset(song->wavetable_names[i], 0, MUS_WAVETABLE_NAME_LEN + 1);
2498 				}
2499 			}
2500 
2501 			song->num_wavetables = max_wt;
2502 		}
2503 		else
2504 			song->num_wavetables = 0;
2505 
2506 		return 1;
2507 	}
2508 
2509 	return 0;
2510 }
2511 
2512 
mus_load_song(const char * path,MusSong * song,CydWavetableEntry * wavetable_entries)2513 int mus_load_song(const char *path, MusSong *song, CydWavetableEntry *wavetable_entries)
2514 {
2515 	RWops *ctx = RWFromFile(path, "rb");
2516 
2517 	if (ctx)
2518 	{
2519 		int r = mus_load_song_RW(ctx, song, wavetable_entries);
2520 		my_RWclose(ctx);
2521 
2522 		return r;
2523 	}
2524 
2525 	return 0;
2526 }
2527 
2528 
mus_free_song(MusSong * song)2529 void mus_free_song(MusSong *song)
2530 {
2531 	free(song->instrument);
2532 
2533 	for (int i = 0 ; i < MUS_MAX_CHANNELS; ++i)
2534 	{
2535 		free(song->sequence[i]);
2536 	}
2537 
2538 	for (int i = 0 ; i < song->num_patterns; ++i)
2539 	{
2540 		free(song->pattern[i].step);
2541 	}
2542 
2543 	for (int i = 0 ; i < song->num_wavetables; ++i)
2544 	{
2545 		free(song->wavetable_names[i]);
2546 	}
2547 
2548 	free(song->wavetable_names);
2549 
2550 	free(song->pattern);
2551 }
2552 
2553 
mus_release(MusEngine * mus,int chan)2554 void mus_release(MusEngine *mus, int chan)
2555 {
2556 	cyd_lock(mus->cyd, 1);
2557 	cyd_enable_gate(mus->cyd, &mus->cyd->channel[chan], 0);
2558 
2559 	cyd_lock(mus->cyd, 0);
2560 }
2561 
2562 
mus_load_instrument_file(Uint8 version,FILE * f,MusInstrument * inst,CydWavetableEntry * wavetable_entries)2563 int mus_load_instrument_file(Uint8 version, FILE *f, MusInstrument *inst, CydWavetableEntry *wavetable_entries)
2564 {
2565 	RWops *rw = RWFromFP(f, 0);
2566 
2567 	if (rw)
2568 	{
2569 		int r = mus_load_instrument_RW(version, rw, inst, wavetable_entries);
2570 
2571 		my_RWclose(rw);
2572 
2573 		return r;
2574 	}
2575 
2576 	return 0;
2577 }
2578 
2579 
mus_load_instrument_file2(FILE * f,MusInstrument * inst,CydWavetableEntry * wavetable_entries)2580 int mus_load_instrument_file2(FILE *f, MusInstrument *inst, CydWavetableEntry *wavetable_entries)
2581 {
2582 	RWops *rw = RWFromFP(f, 0);
2583 
2584 	if (rw)
2585 	{
2586 		int r = mus_load_instrument_RW2(rw, inst, wavetable_entries);
2587 
2588 		my_RWclose(rw);
2589 
2590 		return r;
2591 	}
2592 
2593 	return 0;
2594 }
2595 
2596 
mus_load_song_file(FILE * f,MusSong * song,CydWavetableEntry * wavetable_entries)2597 int mus_load_song_file(FILE *f, MusSong *song, CydWavetableEntry *wavetable_entries)
2598 {
2599 	RWops *rw = RWFromFP(f, 0);
2600 
2601 	if (rw)
2602 	{
2603 		int r = mus_load_song_RW(rw, song, wavetable_entries);
2604 
2605 		my_RWclose(rw);
2606 
2607 		return r;
2608 	}
2609 
2610 	return 0;
2611 }
2612 
2613 
mus_get_playtime_at(MusSong * song,int position)2614 Uint32 mus_get_playtime_at(MusSong *song, int position)
2615 {
2616 	Uint32 ticks = 0;
2617 	int pos = 0;
2618 	int seq_pos[MUS_MAX_CHANNELS] = {0}, pattern_pos[MUS_MAX_CHANNELS] = {0};
2619 	MusPattern *pattern[MUS_MAX_CHANNELS] = {0};
2620 	int spd1 = song->song_speed, spd2 = song->song_speed2, rate = song->song_rate;
2621 
2622 	while (pos < position)
2623 	{
2624 		for (int t = 0 ; t < song->num_channels ; ++t)
2625 		{
2626 			if (seq_pos[t] < song->num_sequences[t])
2627 			{
2628 				if (song->sequence[t][seq_pos[t]].position == pos)
2629 				{
2630 					if (seq_pos[t] < song->num_sequences[t])
2631 					{
2632 						pattern_pos[t] = 0;
2633 
2634 						pattern[t] = &song->pattern[song->sequence[t][seq_pos[t]].pattern];
2635 
2636 						seq_pos[t]++;
2637 					}
2638 				}
2639 
2640 				if (pattern[t] && pattern_pos[t] < pattern[t]->num_steps)
2641 				{
2642 					Uint16 command = pattern[t]->step[pattern_pos[t]].command;
2643 
2644 					if ((command & 0xff00) == MUS_FX_SET_SPEED)
2645 					{
2646 						spd1 = command & 0xf;
2647 						spd2 = (command & 0xf0) >> 4;
2648 
2649 						if (!spd2)
2650 							spd2 = spd1;
2651 					}
2652 					else if ((command & 0xff00) == MUS_FX_SET_RATE)
2653 					{
2654 						rate = command & 0xff;
2655 
2656 						if (rate < 1)
2657 							rate = 1;
2658 					}
2659 					else if ((command & 0xff00) == MUS_FX_SKIP_PATTERN)
2660 					{
2661 						pos += pattern[t]->num_steps - 1 - pattern_pos[t];
2662 					}
2663 				}
2664 
2665 			}
2666 
2667 			pattern_pos[t]++;
2668 		}
2669 
2670 		int spd = pos & 1 ? spd2 : spd1;
2671 
2672 		ticks += (1000 * spd) / rate;
2673 
2674 		++pos;
2675 	}
2676 
2677 	return ticks;
2678 }
2679 
2680 
mus_set_channel_volume(MusEngine * mus,int chan,int volume)2681 void mus_set_channel_volume(MusEngine* mus, int chan, int volume)
2682 {
2683 	MusChannel *chn = &mus->channel[chan];
2684 	CydChannel *cydchn = &mus->cyd->channel[chan];
2685 	MusTrackStatus *track_status = &mus->song_track[chan];
2686 
2687 	chn->volume = my_min(volume, MAX_VOLUME);
2688 	update_volumes(mus, track_status, chn, cydchn, track_status->volume);
2689 }
2690