/*

    TiMidity -- Experimental MIDI to WAVE converter
    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   instrum.c

   Code to load and unload GUS-compatible instrument patches.

*/

#include "pent_include.h"

#ifdef USE_TIMIDITY_MIDI

#include <cstdio>
#include <cstring>
#include <cstdlib>

#include "timidity.h"
#include "timidity_common.h"
#include "timidity_instrum.h"
#include "timidity_playmidi.h"
#include "timidity_output.h"
#include "timidity_controls.h"
#include "timidity_resample.h"
#include "timidity_tables.h"
#include "timidity_filter.h"
#include "ignore_unused_variable_warning.h"

#ifdef NS_TIMIDITY
namespace NS_TIMIDITY {
#endif

/* Some functions get aggravated if not even the standard banks are
 available. */
static ToneBank standard_tonebank, standard_drumset;
ToneBank
	*tonebank[128]={&standard_tonebank},
*drumset[128]={&standard_drumset};

/* This is a special instrument, used for all melodic programs */
Instrument *default_instrument=nullptr;

/* This is only used for tracks that don't specify a program */
int default_program=DEFAULT_PROGRAM;

int antialiasing_allowed=0;
#ifdef FAST_DECAY
int fast_decay=1;
#else
int fast_decay=0;
#endif

static void free_instrument(Instrument *ip)
{
	if (!ip) return;
	for (int i=0; i<ip->samples; i++)
	{
		Sample *sp = &(ip->sample[i]);
		free(sp->data);
	}
	free(ip->sample);
	free(ip);
}

static void free_bank(int dr, int b)
{
	ToneBank *bank=((dr) ? drumset[b] : tonebank[b]);
	for (int i=0; i<128; i++)
		if (bank->tone[i].instrument)
		{
			/* Not that this could ever happen, of course */
			if (bank->tone[i].instrument != MAGIC_LOAD_INSTRUMENT)
				free_instrument(bank->tone[i].instrument);
			bank->tone[i].instrument=nullptr;
		}
}

static sint32 convert_envelope_rate(uint8 rate)
{
	sint32 r=3-((rate>>6) & 0x3);
	r*=3;
	r = (rate & 0x3f) << r; /* 6.9 fixed point */

	/* 15.15 fixed point. */
	return (((r * 44100) / play_mode->rate) * control_ratio)
		<< ((fast_decay) ? 10 : 9);
}

static sint32 convert_envelope_offset(uint8 offset)
{
	/* This is not too good... Can anyone tell me what these values mean?
	 Are they GUS-style "exponential" volumes? And what does that mean? */

	/* 15.15 fixed point */
	return offset << (7+15);
}

static sint32 convert_tremolo_sweep(uint8 sweep)
{
	if (!sweep)
		return 0;

	return
		((control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
		(play_mode->rate * sweep);
}

static sint32 convert_vibrato_sweep(uint8 sweep, sint32 vib_control_ratio)
{
	if (!sweep)
		return 0;

	return
		static_cast<sint32>(FSCALE(static_cast<double>(vib_control_ratio) * SWEEP_TUNING, SWEEP_SHIFT)
		          / static_cast<double>(play_mode->rate * sweep));

	/* this was overflowing with seashore.pat

	 ((vib_control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
		 (play_mode->rate * sweep); */
}

static sint32 convert_tremolo_rate(uint8 rate)
{
	return
		((SINE_CYCLE_LENGTH * control_ratio * rate) << RATE_SHIFT) /
		(TREMOLO_RATE_TUNING * play_mode->rate);
}

static sint32 convert_vibrato_rate(uint8 rate)
{
	/* Return a suitable vibrato_control_ratio value */
	return
		(VIBRATO_RATE_TUNING * play_mode->rate) /
		(rate * 2 * VIBRATO_SAMPLE_INCREMENTS);
}

static void reverse_data(sint16 *sp, sint32 ls, sint32 le)
{
	sint16 *ep=sp+le;
	sp+=ls;
	le-=ls;
	le/=2;
	while (le--)
	{
		sint16 s=*sp;
		*sp++=*ep;
		*ep--=s;
	}
}

/*
 If panning or note_to_use != -1, it will be used for all samples,
 instead of the sample-specific values in the instrument file.

 For note_to_use, any value <0 or >127 will be forced to 0.

 For other parameters, 1 means yes, 0 means no, other values are
 undefined.

 TODO: do reverse loops right */
static Instrument *load_instrument(char *name, int percussion,
                                   int panning, int amp, int note_to_use,
                                   int strip_loop, int strip_envelope,
                                   int strip_tail)
{
	ignore_unused_variable_warning(percussion);
	Instrument *ip;
	Sample *sp;
	FILE *fp;
	uint8 tmp[1024];
	int i;
	int j;
	int noluck=0;
#ifdef PATCH_EXT_LIST
	static const char *patch_ext[] = PATCH_EXT_LIST;
#endif

	if (!name) return nullptr;

	/* Open patch file */
	if ((fp=open_file(name, 1, OF_NORMAL)) == nullptr)
	{
		noluck=1;
#ifdef PATCH_EXT_LIST
		/* Try with various extensions */
		for (i=0; patch_ext[i]; i++)
		{
			if (strlen(name)+strlen(patch_ext[i])<1024)
			{
				char path[1024];
				strcpy(path, name);
				strcat(path, patch_ext[i]);
				if ((fp=open_file(path, 1, OF_NORMAL)) != nullptr)
				{
					noluck=0;
					break;
				}
			}
		}
#endif
	}

	if (noluck)
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
		          "Instrument `%s' can't be found.", name);
		return nullptr;
	}

	ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);

	/* Read some headers and do cursory sanity checks. There are loads
	 of magic offsets. This could be rewritten... */

	if ((239 != fread(tmp, 1, 239, fp)) ||
	    (memcmp(tmp, "GF1PATCH110\0ID#000002", 22) != 0 &&
	     memcmp(tmp, "GF1PATCH100\0ID#000002", 22) != 0)) /* don't know what the
		 differences are */
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
		close_file(fp);
		return nullptr;
	}

	if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers,
		 0 means 1 */
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
		          "Can't handle patches with %d instruments", tmp[82]);
		close_file(fp);
		return nullptr;
	}

	if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
		          "Can't handle instruments with %d layers", tmp[151]);
		close_file(fp);
		return nullptr;
	}

	ip=safe_Malloc<Instrument>();
	ip->samples = tmp[198];
	ip->sample = safe_Malloc<Sample>(ip->samples);
	for (i=0; i<ip->samples; i++)
	{

		uint8 fractions;
		sint32 tmplong;
		uint16 tmpshort;
		uint8 tmpchar;

#define READ_CHAR(thing) \
		if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \
		(thing) = tmpchar;
#define READ_SHORT(thing) \
		if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \
		(thing) = LE_SHORT(tmpshort);
#define READ_LONG(thing) \
		if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \
		(thing) = LE_LONG(tmplong);

		skip(fp, 7); /* Skip the wave name */

		if (1 != fread(&fractions, 1, 1, fp))
		{
		fail:
			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
			for (j=0; j<i; j++)
				free(ip->sample[j].data);
			free(ip->sample);
			free(ip);
			close_file(fp);
			return nullptr;
		}

		sp=&(ip->sample[i]);

		READ_LONG(sp->data_length);
		READ_LONG(sp->loop_start);
		READ_LONG(sp->loop_end);
		READ_SHORT(sp->sample_rate);
		READ_LONG(sp->low_freq);
		READ_LONG(sp->high_freq);
		READ_LONG(sp->root_freq);
		skip(fp, 2); /* Why have a "root frequency" and then "tuning"?? */

		READ_CHAR(tmp[0]);

		if (panning==-1)
			sp->panning = (tmp[0] * 8 + 4) & 0x7f;
		else
			sp->panning=static_cast<uint8>(panning & 0x7F);

		/* envelope, tremolo, and vibrato */
		if (18 != fread(tmp, 1, 18, fp)) goto fail;

		if (!tmp[13] || !tmp[14])
		{
			sp->tremolo_sweep_increment=
				sp->tremolo_phase_increment=sp->tremolo_depth=0;
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
		}
		else
		{
			sp->tremolo_sweep_increment=convert_tremolo_sweep(tmp[12]);
			sp->tremolo_phase_increment=convert_tremolo_rate(tmp[13]);
			sp->tremolo_depth=tmp[14];
			ctl->cmsg(CMSG_INFO, VERB_DEBUG,
			          " * tremolo: sweep %d, phase %d, depth %d",
			          sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
			          sp->tremolo_depth);
		}

		if (!tmp[16] || !tmp[17])
		{
			sp->vibrato_sweep_increment=
				sp->vibrato_control_ratio=sp->vibrato_depth=0;
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
		}
		else
		{
			sp->vibrato_control_ratio=convert_vibrato_rate(tmp[16]);
			sp->vibrato_sweep_increment=
				convert_vibrato_sweep(tmp[15], sp->vibrato_control_ratio);
			sp->vibrato_depth=tmp[17];
			ctl->cmsg(CMSG_INFO, VERB_DEBUG,
			          " * vibrato: sweep %d, ctl %d, depth %d",
			          sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
			          sp->vibrato_depth);
		}

		READ_CHAR(sp->modes);

		skip(fp, 40); /* skip the useless scale frequency, scale factor
		 (what's it mean?), and reserved space */

		/* Mark this as a fixed-pitch instrument if such a deed is desired. */
		if (note_to_use!=-1)
			sp->note_to_use=static_cast<uint8>(note_to_use);
		else
			sp->note_to_use=0;

		/* seashore.pat in the Midia patch set has no Sustain. I don't
		 understand why, and fixing it by adding the Sustain flag to
		 all looped patches probably breaks something else. We do it
		 anyway. */

		if (sp->modes & MODES_LOOPING)
			sp->modes |= MODES_SUSTAIN;

		/* Strip any loops and envelopes we're permitted to */
		if ((strip_loop==1) &&
		    (sp->modes & (MODES_SUSTAIN | MODES_LOOPING |
		                  MODES_PINGPONG | MODES_REVERSE)))
		{
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
			sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING |
			              MODES_PINGPONG | MODES_REVERSE);
		}

		if (strip_envelope==1)
		{
			if (sp->modes & MODES_ENVELOPE)
				ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
			sp->modes &= ~MODES_ENVELOPE;
		}
		else if (strip_envelope != 0)
		{
			/* Have to make a guess. */
			if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
			{
				/* No loop? Then what's there to sustain? No envelope needed
				 either... */
				sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
				ctl->cmsg(CMSG_INFO, VERB_DEBUG,
				          " - No loop, removing sustain and envelope");
			}
			else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100)
			{
				/* Envelope rates all maxed out? Envelope end at a high "offset"?
				 That's a weird envelope. Take it out. */
				sp->modes &= ~MODES_ENVELOPE;
				ctl->cmsg(CMSG_INFO, VERB_DEBUG,
				          " - Weirdness, removing envelope");
			}
			else if (!(sp->modes & MODES_SUSTAIN))
			{
				/* No sustain? Then no envelope.  I don't know if this is
				 justified, but patches without sustain usually don't need the
				 envelope either... at least the Gravis ones. They're mostly
				 drums.  I think. */
				sp->modes &= ~MODES_ENVELOPE;
				ctl->cmsg(CMSG_INFO, VERB_DEBUG,
				          " - No sustain, removing envelope");
			}
		}

		for (j=0; j<6; j++)
		{
			sp->envelope_rate[j]=
				convert_envelope_rate(tmp[j]);
			sp->envelope_offset[j]=
				convert_envelope_offset(tmp[6+j]);
		}

		/* Then read the sample data */
		sp->data = safe_Malloc<sample_t>(sp->data_length);
		if (1 != fread(sp->data, sp->data_length, 1, fp))
			goto fail;

		if (!(sp->modes & MODES_16BIT)) /* convert to 16-bit data */
		{
			sint32 i=sp->data_length;
			auto *cp=reinterpret_cast<uint8 *>(sp->data);
			uint16 *tmp;
			uint16 *new_dat;
			tmp=new_dat=safe_Malloc<uint16>(sp->data_length);
			while (i--)
				*tmp++ = static_cast<uint16>(*cp++) << 8;
			cp=reinterpret_cast<uint8 *>(sp->data);
			sp->data = reinterpret_cast<sample_t *>(new_dat);
			free(cp);
			sp->data_length *= 2;
			sp->loop_start *= 2;
			sp->loop_end *= 2;
		}
#ifndef TIMIDITY_LITTLE_ENDIAN
		else
			/* convert to machine byte order */
		{
			sint32 i=sp->data_length/2;
#ifdef LOOKUP_HACK
			sint16 *tmp=reinterpret_cast<sint16 *>(sp->data);
			sint16 *s;
#else
			sample_t *tmp=sp->data;
			sample_t s;
#endif
			while (i--)
			{
				s=LE_SHORT(*tmp);
				*tmp++=s;
			}
		}
#endif

		if (sp->modes & MODES_UNSIGNED) /* convert to signed data */
		{
			sint32 i=sp->data_length/2;
			sint16 *tmp = sp->data;
			while (i--)
				*tmp++ ^= 0x8000;
		}

		/* Reverse reverse loops and pass them off as normal loops */
		if (sp->modes & MODES_REVERSE)
		{
			sint32 t;
			/* The GUS apparently plays reverse loops by reversing the
			 whole sample. We do the same because the GUS does not SUCK. */

			ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
			reverse_data(sp->data, 0, sp->data_length/2);

			t=sp->loop_start;
			sp->loop_start=sp->data_length - sp->loop_end;
			sp->loop_end=sp->data_length - t;

			sp->modes &= ~MODES_REVERSE;
			sp->modes |= MODES_LOOPING; /* just in case */
		}

		/* If necessary do some anti-aliasing filtering  */

		if (antialiasing_allowed)
			antialiasing(sp,play_mode->rate);

#ifdef ADJUST_SAMPLE_VOLUMES
		if (amp!=-1)
			sp->volume=static_cast<float>((amp) / 100.0);
		else
		{
			/* Try to determine a volume scaling factor for the sample.
			 This is a very crude adjustment, but things sound more
			 balanced with it. Still, this should be a runtime option. */
			sint32 i=sp->data_length/2;
			sint16 maxamp=0;
			sint16 *tmp = sp->data;
			while (i--)
			{
				sint16 a=*tmp++;
				if (a<0) a=-a;
				if (a>maxamp)
					maxamp=a;
			}
			sp->volume=static_cast<float>(32768.0 / maxamp);
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
		}
#else
		if (amp!=-1)
			sp->volume=static_cast<double>(amp) / 100.0;
		else
			sp->volume=1.0;
#endif

		sp->data_length /= 2; /* These are in bytes. Convert into samples. */
		sp->loop_start /= 2;
		sp->loop_end /= 2;

		/* Then fractional samples */
		sp->data_length <<= FRACTION_BITS;
		sp->loop_start <<= FRACTION_BITS;
		sp->loop_end <<= FRACTION_BITS;

		/* Adjust for fractional loop points. This is a guess. Does anyone
		 know what "fractions" really stands for? */
		sp->loop_start |=
			(fractions & 0x0F) << (FRACTION_BITS-4);
		sp->loop_end |=
			((fractions>>4) & 0x0F) << (FRACTION_BITS-4);

		/* If this instrument will always be played on the same note,
		 and it's not looped, we can resample it now. */
		if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
			pre_resample(sp);

#ifdef LOOKUP_HACK
		/* Squash the 16-bit data into 8 bits. */
		{
			uint8 *gulp,*ulp;
			sint16 *swp;
			int l=sp->data_length >> FRACTION_BITS;
			gulp=ulp=safe_Malloc<uint8>(l+1);
			swp=(sint16 *)sp->data;
			while(l--)
				*ulp++ = (*swp++ >> 8) & 0xFF;
			free(sp->data);
			sp->data=(sample_t *)gulp;
		}
#endif

		if (strip_tail==1)
		{
			/* Let's not really, just say we did. */
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
			sp->data_length = sp->loop_end;
		}
	}

	close_file(fp);
	return ip;
}

static int fill_bank(int dr, int b)
{
	int i;
	int errors=0;
	ToneBank *bank=((dr) ? drumset[b] : tonebank[b]);
	if (!bank)
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
		          "Huh. Tried to load instruments in non-existent %s %d",
		          (dr) ? "drumset" : "tone bank", b);
		return 0;
	}
	for (i=0; i<128; i++)
	{
		if (bank->tone[i].instrument==MAGIC_LOAD_INSTRUMENT)
		{
			if (!(bank->tone[i].name))
			{
				ctl->cmsg(CMSG_WARNING, (b!=0) ? VERB_VERBOSE : VERB_NORMAL,
				          "No instrument mapped to %s %d, program %d%s",
				          (dr)? "drum set" : "tone bank", b, i,
				          (b!=0) ? "" : " - this instrument will not be heard");
				if (b!=0)
				{
					/* Mark the corresponding instrument in the default
					 bank / drumset for loading (if it isn't already) */
					if (!dr)
					{
						if (!(standard_tonebank.tone[i].instrument))
							standard_tonebank.tone[i].instrument=
							MAGIC_LOAD_INSTRUMENT;
					}
					else
					{
						if (!(standard_drumset.tone[i].instrument))
							standard_drumset.tone[i].instrument=
							MAGIC_LOAD_INSTRUMENT;
					}
				}
				bank->tone[i].instrument=nullptr;
				errors++;
			}
			else if (!(bank->tone[i].instrument=
			           load_instrument(bank->tone[i].name,
			                           (dr) ? 1 : 0,
			                           bank->tone[i].pan,
			                           bank->tone[i].amp,
			                           (bank->tone[i].note!=-1) ?
			                           bank->tone[i].note :
				                           ((dr) ? i : -1),
				                           (bank->tone[i].strip_loop!=-1) ?
			                           bank->tone[i].strip_loop :
				                           ((dr) ? 1 : -1),
				                           (bank->tone[i].strip_envelope != -1) ?
			                           bank->tone[i].strip_envelope :
				                           ((dr) ? 1 : -1),
				                           bank->tone[i].strip_tail )))
			{
				ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
				          "Couldn't load instrument %s (%s %d, program %d)",
				          bank->tone[i].name,
				          (dr)? "drum set" : "tone bank", b, i);
				errors++;
			}
		}
	}
	return errors;
}

int load_missing_instruments()
{
	int i=128;
	int errors=0;
	while (i--)
	{
		if (tonebank[i])
			errors+=fill_bank(0,i);
		if (drumset[i])
			errors+=fill_bank(1,i);
	}
	return errors;
}

void free_instruments()
{
	int i=128;
	while(i--)
	{
		if (tonebank[i])
			free_bank(0,i);
		if (drumset[i])
			free_bank(1,i);
	}
}

int set_default_instrument(char *name)
{
	Instrument *ip;
	if (!(ip=load_instrument(name, 0, -1, -1, -1, 0, 0, 0)))
		return -1;
	if (default_instrument)
		free_instrument(default_instrument);
	default_instrument=ip;
	default_program=SPECIAL_PROGRAM;
	return 0;
}

#ifdef NS_TIMIDITY
}
#endif

#endif //USE_TIMIDITY_MIDI
