/*

    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 "config.h"
#include "common.h"
#include "instrum.h"
#include "playmidi.h"
#include "output.h"
#include "resample.h"
#include "tables.h"
#include "filter.h"

#include "../../../music/extmidi.h"

extern _TCHAR *GetPathWide();
/* 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 = 0;
	
/* This is only used for tracks that don't specify a program */
int default_program = DEFAULT_PROGRAM;
	
int antialiasing_allowed = 0;
int fast_decay = 1;
	
static void free_instrument (Instrument * ip)
{
	Sample *sp;
	int i;
	if (!ip)
		return;
	for (i = 0; i < ip->samples; i++)
	{
		sp = &(ip->sample[i]);
		free (sp->data);
	}
	free (ip->sample);
	free (ip);
}

static void
free_bank (int dr, int b)
{
	int i;
	ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
	for (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 = 0;
		}
}

static int32b
convert_envelope_rate (uint8b rate)
{
	int32b r;
	
	r = 3 - ((rate >> 6) & 0x3);
	r *= 3;
	r = (int32b) (rate & 0x3f) << r; /* 6.9 fixed point */
	
	/* 15.15 fixed point. */
	return (((r * 44100) / play_mode->rate) * control_ratio)
		<< ((fast_decay) ? 10 : 9);
}

static int32b
convert_envelope_offset (uint8b 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 int32b
convert_tremolo_sweep (uint8b sweep)
{
	if (!sweep)
		return 0;
	
	return
		((control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
		(play_mode->rate * sweep);
}

static int32b
convert_vibrato_sweep (uint8b sweep, int32b vib_control_ratio)
{
	if (!sweep)
		return 0;
	
	return
		(int32b) (FSCALE ((double) (vib_control_ratio) * SWEEP_TUNING, SWEEP_SHIFT)
		/ (double) (play_mode->rate * sweep));
	
		/* this was overflowing with seashore.pat
		
		  ((vib_control_ratio * SWEEP_TUNING) << SWEEP_SHIFT) /
	(play_mode->rate * sweep); */
}

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

static int32b
convert_vibrato_rate (uint8b rate)
{
	/* Return a suitable vibrato_control_ratio value */
	return
		(VIBRATO_RATE_TUNING * play_mode->rate) /
		(rate * 2 * VIBRATO_SAMPLE_INCREMENTS);
}
	
static void
reverse_data (int16b * sp, int32b ls, int32b le)
{
	int16b s, *ep = sp + le;
	sp += ls;
	le -= ls;
	le /= 2;
	while (le--)
	{
		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)
{
    Instrument *ip;
    Sample *sp;
    FILE *fp;
    char buffer[1024];
    int i, j, noluck = 0;
    char str[1024];

#ifdef PATCH_EXT_LIST
    static char* patch_ext[] = PATCH_EXT_LIST;
#endif
    
    if (!name)
	{
       return 0;
	}

    /* Open patch file */
	sprintf(str, "%s%s", _paths.personal_dir, name);
    if (!(fp = open_file (str, 1, OF_NORMAL)))
    {
		ShowOSErrorBox("Patch file not found!");
        noluck = 1;
    }
    
    if (noluck)
    {
        return 0;
    }
    
    
        /* Read some headers and do cursory sanity checks. There are loads
    of magic offsets. This could be rewritten... */
    
    if ((239 != fread (buffer, 1, 239, fp)) ||
        (memcmp (buffer, "GF1PATCH110\0ID#000002", 22) &&
        memcmp (buffer, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
        differences are */
    {
        return 0;
    }
    
    if (buffer[82] != 1 && buffer[82] != 0) /* instruments. To some patch makers, 
        0 means 1 */
    {
        return 0;
    }
    
    if (buffer[151] != 1 && buffer[151] != 0)   /* layers. What's a layer? */
    {
        return 0;
    }
    
    ip = (Instrument *)safe_malloc (sizeof (Instrument));
    ip->samples = buffer[198];
    ip->sample = (Sample *)safe_malloc (sizeof (Sample) * ip->samples);
    for (i = 0; i < ip->samples; i++)
    {
        
        uint8b fractions;
        int32b tmplong;
        uint16b tmpshort;
        uint8b 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:
        for (j = 0; j < i; j++)
            free (ip->sample[j].data);
        free (ip->sample);
        free (ip);
        return 0;
        }
        
        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 (buffer[0]);
        
        if (panning == -1)
            sp->panning = (buffer[0] * 8 + 4) & 0x7f;
        else
            sp->panning = (uint8b) (panning & 0x7F);
        
        /* envelope, tremolo, and vibrato */
        if (18 != fread (buffer, 1, 18, fp))
            goto fail;
        
        if (!buffer[13] || !buffer[14])
        {
            sp->tremolo_sweep_increment =
                sp->tremolo_phase_increment = sp->tremolo_depth = 0;
        }
        else
        {
            sp->tremolo_sweep_increment = convert_tremolo_sweep (buffer[12]);
            sp->tremolo_phase_increment = convert_tremolo_rate (buffer[13]);
            sp->tremolo_depth = buffer[14];
        }
        
        if (!buffer[16] || !buffer[17])
        {
            sp->vibrato_sweep_increment =
                sp->vibrato_control_ratio = sp->vibrato_depth = 0;
        }
        else
        {
            sp->vibrato_control_ratio = convert_vibrato_rate (buffer[16]);
            sp->vibrato_sweep_increment =
                convert_vibrato_sweep (buffer[15], sp->vibrato_control_ratio);
            sp->vibrato_depth = buffer[17];
        }
        
        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 = (uint8b) (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)))
        {
            sp->modes &=
                ~(MODES_SUSTAIN | MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE);
        }
        
        if (strip_envelope == 1)
        {
            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);
            }
            else if (!memcmp (buffer, "??????", 6) || buffer[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;
            }
            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;
            }
        }
        
        for (j = 0; j < 6; j++)
        {
            sp->envelope_rate[j] = convert_envelope_rate (buffer[j]);
            sp->envelope_offset[j] = convert_envelope_offset (buffer[6 + j]);
        }
        
        /* Then read the sample data */
        sp->data = (sample_t *)safe_malloc (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 */
        {
            int32b i = sp->data_length;
            uint8b *cp = (uint8b *) (sp->data);
            uint16b *tmp, *newd;
            tmp = newd = (uint16b *)safe_malloc (sp->data_length * 2);
            while (i--)
                *tmp++ = (uint16b) (*cp++) << 8;
            cp = (uint8b *) (sp->data);
            sp->data = (sample_t *) newd;
            free (cp);
            sp->data_length *= 2;
            sp->loop_start *= 2;
            sp->loop_end *= 2;
        }
        
        if (sp->modes & MODES_UNSIGNED) /* convert to signed data */
        {
            int32b i = sp->data_length / 2;
            int16b *tmp = (int16b *) sp->data;
            while (i--)
                *tmp++ ^= 0x8000;
        }
        
        /* Reverse reverse loops and pass them off as normal loops */
        if (sp->modes & MODES_REVERSE)
        {
            int32b t;
            /* The GUS apparently plays reverse loops by reversing the
            whole sample. We do the same because the GUS does not SUCK. */
            
            reverse_data ((int16b *) 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 = (float) ((double) (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. */
            int32b i = sp->data_length / 2;
            int16b maxamp = 0, a;
            int16b *tmp = (int16b *) sp->data;
            while (i--)
            {
                a = *tmp++;
                if (a < 0)
                    a = -a;
                if (a > maxamp)
                    maxamp = a;
            }
            sp->volume = (float) (32768.0 / (double) (maxamp));
        }
#else
        if (amp != -1)
            sp->volume = (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);
        
        if (strip_tail == 1)
        {
            /* Let's not really, just say we did. */
            sp->data_length = sp->loop_end;
        }
    }
    
    close_file (fp);
    return ip;
}

static int
fill_bank (int dr, int b)
{
	int i, errors = 0;
	ToneBank *bank = ((dr) ? drumset[b] : tonebank[b]);
	if (!bank)
	{
		//ctl.cmsg (CMSG_ERROR, VERB_NORMAL,
		//	TEXT
		//	("Huh. Tried to load instruments in non-existent %s %d"),
		//	(dr) ? L"drumset" : L"tone bank", b);
		return 0;
	}
	for (i = 0; i < 128; i++)
	{
		if (bank->tone[i].instrument == MAGIC_LOAD_INSTRUMENT)
		{
			if (!(bank->tone[i].name))
			{
				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 = 0;
				errors++;
			}
			else
			{					
				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);
				
				
				if (!(bank->tone[i].instrument))
				{
					errors++;
				}
			}
		}
	}
	return errors;
}

int
load_missing_instruments (void)
{
	int i = 128, 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 (void)
{
	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;
}
