/*
  MidiSynth, MIDI synthesiser, a repacement for the Acorn MIDI module

  kbd.c - Keyboard driver

  created  15/01/07
  1.0      14/06/14
*/

#include "main.h"
#include "kbd.h"

syn_t syn;

/*
Stack definition
----------------
To create the effect of a fully polphonic keyboard using a limited number of tone generators, a stack of
generator control words is employed. One word for each generator. When a MIDI NOTE ON message is received,
the generator at the stack bottom is used, it is then moved to the stack top and will be the last to be
picked for a different note. see the function poly_action_key. If a generator is already assigned to the
note then it is retriggered and moved to the top.

                        |--- these bits checked for generator on note --|

 31  30  29  28  27  26  25  24  23  22  21  20  19  18  17  16  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|   | E | R | T | G | M | S   MIDI Channel  |      MIDI Key number      |     MIDI Key Velocity     |     Generator number      |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  |   |   |   |   |   |   |
  |   |   |   |   |   |  Channel block select
  |   |   |   |   |  Mono instrument
  |   |   |   |  Gate
  |   |   |  Trigger
  |   |  Retune
  |  Retrigger
(spare)

 GATE TRIG action
 ---- ---- ------
   1    1  start attack   (key has been pressed)
   1    0  continue attack/decay/sustain
   0    1  start release  (key has been released)
   0    0  continue release

 stack index = 0, stack bottom, oldest note
             = syn.num_gens-1, stack top, newest note
*/

// lowest bit number of fields
#define GEN         0 // generator number, 7 bits
#define VELOCITY    7 // key velocity, 7 bits
#define KEY        14 // midi key number, 7 bits
#define CHANNEL    21 // midi channel number, 4 bits
#define CHAN_EXTN  25 // channel extension
#define MONO       26 // set if the generator is being used for a monophonic instrument
#define GATE       27 // set if the note is down, generator envelope control
#define TRIG       28 // set if the note up/down status has changed, generator envelope control
#define RETUNE     29 // set if the note is only to be retuned
#define RETRIGGER  30 // set if the note is being retriggered
// field masks
#define GEN_MASK   ((1<<7)-1) // 7 bits wide, for up to 128 generators
#define VEL_MASK   ((1<<7)-1) // 7 bits wide, velocity = 0..127
#define KEY_MASK   ((1<<7)-1) // 7 bits wide, for 128 midi keys
#define CHAN_MASK  ((1<<5)-1) // 5 bits wide, for 2 banks of 16 midi channels
#define EXTN_MASK  ((1<<1)-1) // 1 bits wide, to select 1 of 2 channel banks

// soundset.c
extern const ins_t def_instrument[];
#define PURE_SINE 195 // Instrument number for the Pure Sinewave instrument
// Remember to check this with the current default set.
// (note. It will be ONE LESS than the commented number against "Sine 1" in SoundSet.c).

// tables.c
extern const unsigned short int env_scale_table[NUM_NOTES];
extern const unsigned short int sine_table[1792];
// midi.c
extern const unsigned short int pantab[MIDI_DATA_RANGE];
// fmull.s
unsigned int fmull48(unsigned int x, unsigned int y);
unsigned int fmull47(unsigned int x, unsigned int y);


/*
 * calculate_tables
 * ----------------
 * Calculates the tone increment and filter cutoff increment tables.
 * that depend on the sample rate. This is necessary if the sample
 * rate is required to be a variable that can be changed after startup.
 *
 *   x = FREQ_A5 * exp((note - A5) * LN2 / 12)  frequency in Hz
 *   w = x / sample_rate   normalised frequency, 0.5 = nyquist frequency
 *
 *   tone increment = w * 2^17 (fixed point scaling)
 *
 *   filter increment = 2 * sin(PI * w) * 2^15 (fixed point scaling)
 *
 * Code is a fixed point version of above as floating point caused problems
 * for the module version when compiled on my Pi4 (RO 5.28) and then run on
 * my RPCEmu (RO 3.7). note. I believe this is a known problem with GCCSDK
 */
void calculate_tables(int sample_rate)
{
  int i;
  unsigned int w, hz;
  for(i=0; i<NUM_NOTES; i++)
  {
    hz = FREQ_A5 * iexp(((i - A5) << 10) / 12); // frequency in Hz, Q15

    w = ((hz << 2) + (1<<15)) / sample_rate;
    if(w > ((1<<16)-1))
      w = ((1<<16)-1);
    syn.tone_inc_table[i] = w;

    w = hz / sample_rate; // Q15, 0.5 is the nyquist frequency = 1<<14

    // adjust for the sine_table increase in resolution as angle gets smaller
    if(w < (1<<9))
      ; // do nothing, first 512 bytes, 32k point resolution
    else if(w < (1<<10))
      w = 512 + ((w - (1<<9)) >> 1); // next 256 bytes, 16k point resolution
    else if(w < (1<<11))
      w = 512+256 + ((w - (1<<10)) >> 2); // next 256 bytes, 8k point resolution
    else if(w < (1<<12))
      w = 512+2*256 + ((w - (1<<11)) >> 3); // next 256 bytes, 4k point resolution
    else if(w < (1<<13))
      w = 512+3*256 + ((w - (1<<12)) >> 4); // next 256 bytes, 2k point resolution
    else if(w < (1<<14))
      w = 512+4*256 + ((w - (1<<13)) >> 5); // next 256 bytes, 1k point resolution
    else
      w = 511+5*256;

    syn.filter_table[i] = sine_table[w];
  }

  syn.sample_rate = sample_rate;
}


/*
 * midiSynth_init
 * --------------
 * First time initialisation.
 */
int midiSynth_init(int sample_rate)
{
  memset(&syn, 0, sizeof(syn_t));
  calculate_tables(sample_rate);
  load_defaults(&syn.idat); // load defaults first to ensure we have a set of waveforms because loaded files may not contain them.
  load_file(&syn.idat, "<MIDISynthChoices$Dir>.SoundSet"); // replace defaults with a sound set file if a valid one exists
  // ignore any returned error from load_file

  syn.num_gens = 32;        // number of generators, polyphony
  syn.master_volume = 1023; // maximum volume, 0dB
  syn.master_balance = 512; // balance, midway
  syn.scale_factor = 100;   // glide time (portamento) scaling to suit the current MIDI spec (smaller = faster, larger = slower)

  midiSynth_reset();
  return 0;
}


/*
 * midiSynth_term
 * --------------
 * Terminates the synthesiser
 */
void midiSynth_term(void)
{
  if(syn.idat.instrument)
    free(syn.idat.instrument);
  if(syn.idat.bank)
    free(syn.idat.bank);
  if(syn.idat.wtbl)
    free(syn.idat.wtbl);
  if(syn.idat.harm)
    free(syn.idat.harm);
}


/*
 * midiSynth_reset
 * ---------------
 * Initialises the generators, stack, and channels.
 * Will instantly mute all notes
 */
int midiSynth_reset(void)
{
  int i;
  gen_t *g;

  syn.seed = 1; // start noise source
  syn.switches &= ~0x7f; // omni on, poly, mono voices reset

  // generators and stack
  for(i=0; i<syn.num_gens; i++)
  {
    g = &syn.gen[i];             // point to the generator structure.
    memset(g, 0, sizeof(gen_t)); // start by clearing everything, then load ...
    g->waveform1 = syn.idat.wtbl[0].wave; //   tone1 waveform pointer,
    g->waveform2 = syn.idat.wtbl[0].wave; //   tone2 waveform pointer,
    g->mod_wave = syn.idat.wtbl[0].wave;  //   modulation waveform pointer
    g->ins = &syn.idat.instrument[syn.idat.bank[syn.idat.banks[0]-1].ins[0]-1]; //   instrument pointer,
    g->filter_q = (1<<VLQ_BITS); //   filter resonance value for maximum damping.
    syn.stack[i] = i << GEN; // initialise stack with generator number.
  }

  // channels
  for(i=0; i < (NUM_BLKS*NUM_MIDI_CHANS); i++)
  {
    syn.chan[i] = def_chan;
    syn.chan[i].param_idx = 0;
    syn.chan[i].param_ptr = &syn.chan[i].pitch_bend_range;
  }

  return 0;
}


/*
 * reset_gates
 * -----------
 * Forces all notes on the channel to enter the RELEASE phase
 */
void reset_gates(int channel)
{
  int i;

  syn.chan[channel].switches &= ~(1<<HOLD_PEDAL); // ensure they are not held on

  for(i=0; i<syn.num_gens; i++)
    if(((syn.stack[i] >> CHANNEL) & CHAN_MASK) == channel)
      syn.stack[i] = (syn.stack[i] | (1<<TRIG)) & ~((1<<GATE)/* | (1<<RETUNE)*/);
}


/*
 * reset_all_gates
 * ----------------
 * Forces all notes assigned to a channel block with gates set, to enter the RELEASE phase.
 */
void reset_all_gates(int chan_blk)
{
  int i;
  int c = chan_blk * NUM_MIDI_CHANS; // ensure they are not held on

  for(i=c; i<(c + NUM_MIDI_CHANS); i++)
    syn.chan[i].switches &= ~(1<<HOLD_PEDAL);

  for(i=0; i<syn.num_gens; i++)
    if(((syn.stack[i] >> CHAN_EXTN) & EXTN_MASK) == chan_blk) // is generator assigned to the block ?
      syn.stack[i] = (syn.stack[i] | (1<<TRIG)) & ~((1<<GATE)/* | (1<<RETUNE)*/);    // if so, enter release phase
}


/*
 * portamento_on_off
 * ---------------
 * For all generators on the channel with a key set:
 *   for on:
 *     sets MONO and RETUNE flags
 *   for off:
 *     clears MONO and RETUNE flags
 */
void portamento_on_off(int channel, int on)
{
  #define PORTO ((1<<MONO)|(1<<RETUNE))
  int i;

  for(i=0; i<syn.num_gens; i++)
    if(((syn.stack[i] >> CHANNEL) & CHAN_MASK) == channel)
      if(((syn.stack[i] >> KEY) & KEY_MASK) != 0)
      {
        if(on)
          syn.stack[i] |= PORTO;
        else
          syn.stack[i] &= ~PORTO;
      }
}


/*
 * poly_action_key
 * ---------------
 * Called when a 'key' event occurs from the local keyboard, midi in, or player.
 * This updates the triggers and gates. Any changes are picked up by synth_control()
 * when it next runs.
 * This function is used for polyphonic keyboard modes and also for mono portamento
 * operation per channel whilst still supporting poly notes on that channel.
 */
// bit mask for channel and key
#define POLY_NOTE ((1<<MONO)|(CHAN_MASK<<CHANNEL)|(KEY_MASK<<KEY))
void poly_action_key(int key, int key_pressed, int channel, int velocity)
{
  int i, g, new_note = (channel<<CHANNEL) | (key<<KEY);

  int portamento =  syn.chan[channel].switches & (1<<PORTAMENTO);

  // is there a generator already assigned to this note ?
  for(i=0; i<syn.num_gens; i++)
    if((syn.stack[i] & POLY_NOTE) == new_note)
      break;

  if(i >= syn.num_gens)
    if(portamento) // for a portamento enabled channel ...
    { // first check for a mono generator on the note
      for(i=0; i<syn.num_gens; i++)
        if((syn.stack[i] & POLY_NOTE) == ((1<<MONO) | new_note))
          break;
      if(i >= syn.num_gens) // if not find the first mono generator to retune
        for(i=0; i<syn.num_gens; i++)
          if((syn.stack[i] & ((1<<MONO)|(CHAN_MASK<<CHANNEL))) == ((1<<MONO) | (channel<<CHANNEL)))
            break;
    }

  if(key_pressed)
  {
    if(i >= syn.num_gens)
    {
      // no assigned generator, all gates set ?
      for(i=0; i<syn.num_gens; i++)
        if(!(syn.stack[i] & (1<<GATE)))
          break;

      if(i >= syn.num_gens)
        i = 0; // all generators in use, use gen at stack bottom (oldest note).

      // assign generator, start attack at new pitch
      g = (syn.stack[i] & (GEN_MASK<<GEN)) | (1<<GATE) | (1<<TRIG) | (velocity<<VELOCITY) | new_note;
      if(portamento)
        g |= (1<<MONO);
    }
    else // generator assigned, restart attack, pitch unchanged
    {
      // start attack
      g = (syn.stack[i] & (GEN_MASK<<GEN)) | (1<<GATE) | (1<<TRIG) | (velocity<<VELOCITY) | new_note;
      if(portamento)
        g |= (1<<MONO) | (1<<RETUNE);
      else
        g |= (1<<RETRIGGER);
    }
  }
  else // key released
  {
    if(i >= syn.num_gens)
      return; // no assigned generator so ignore event

    // start release
    if(!portamento)
      g = (syn.stack[i] & ~((1<<GATE) | (1<<RETUNE) | (1<<RETRIGGER))) | (1<<TRIG);
    else if((syn.stack[i] & ((CHAN_MASK<<CHANNEL)|(KEY_MASK<<KEY))) == ((channel<<CHANNEL) | (key<<KEY)))
      g = (syn.stack[i] & ~(1<<GATE)) | (1<<TRIG); // if portamento, only start release if the key matches
    else
      return; // do nothing, key had been retuned and is still in use
  }

  // adjust stack, move selected gen to stack top, shift intervening gens down.
  for(; i<(syn.num_gens-1); i++)
    syn.stack[i] = syn.stack[i+1];
  syn.stack[i] = g; // selected gen to stack top

}


/*
 * envelope
 * --------
 * Action a single Delay-Attack-Hold-Decay-Sustain-Release envelope.
 * init_envelope(), scales the time constants for the pitch if required and starts
 * the envelope sequence.
 * envelope(), executes the sequence and returns the next value.
 * The filters used to produce the envelope are first order IIR, i.e. a simple RC time
 * constant with exponential rise and fall.
 */
#define Q 16 // time constant precision (data precision Q15)
#define NEAR_ENOUGH 100 // an exponential rise or fall never actually reaches its target

// initialise the envelope, scale the time constants and targets
static void init_envelope(envar_t *g, const env_t *i, int tc_scale, int track)
{
  g->scaled = *i; // start with a direct copy of the instrument envelope parameters

  if(i->attack_step == 0)
    g->state = INACTIVE;
  else
  {
    g->state = INIT;

    if(track) // scale the time constants
    {
      int temp;
      temp = (i->attack_step * tc_scale) >> ENV_SCALE_BITS;
      g->scaled.attack_step = (temp > 32767) ? 32767 : temp;
      temp = (i->decay_step * tc_scale) >> ENV_SCALE_BITS;
      g->scaled.decay_step = (temp > 32767) ? 32767 : temp;
      temp = (i->sustain_step * tc_scale) >> ENV_SCALE_BITS;
      g->scaled.sustain_step = (temp > 32767) ? 32767 : temp;
      temp = (i->release_step * tc_scale) >> ENV_SCALE_BITS;
      g->scaled.release_step = (temp > 32767) ? 32767 : temp;
      temp = (i->hold << ENV_SCALE_BITS) / tc_scale;
      g->scaled.hold = (temp > 32767) ? 32767 : temp;
      temp = (i->delay << ENV_SCALE_BITS) / tc_scale;
      g->scaled.delay = (temp > 32767) ? 32767 : temp;
    }
  }
}

// main envelope function, returns the next value.
static int envelope(envar_t *e, unsigned int switches, int retune)
{
  int delta;

  if(e->scaled.attack_step == 0)
    e->state = INACTIVE;

  switch(e->state)
  {
    case INIT:
      if(!retune)
        e->enval = 0; // start from zero, causes a click if retuning or retriggering
      e->state = DELAY;
      e->count = e->scaled.delay;
      // follow through to DELAY

    case DELAY:
      if(e->count--)
        break;
      e->state = ATTACK;
      e->k3 = (1<<Q) - e->scaled.release_step;
      // follow through to ATTACK

    case ATTACK:
      e->enval += (unsigned int)e->scaled.attack_step << Q;
      if((e->enval >> Q) >= e->scaled.attack_target)
      {
        e->enval = e->scaled.attack_target << Q;
        e->state = HOLD;
        e->count = e->scaled.hold;
      }
      break;

    case HOLD:
      if(!e->count--)
      {
        e->state = DECAY;
        e->k1 = e->scaled.decay_step * e->scaled.decay_target;
        e->k2 = (1<<Q) - e->scaled.decay_step;
      }
      break;

    case DECAY:
//      e->enval = ((e->k2 * (Uint64)e->enval) >> Q) + e->k1;
      e->enval = fmull48(e->k2, e->enval) + e->k1;
      delta = (e->enval >> Q) - e->scaled.decay_target;
      if((delta < NEAR_ENOUGH) && (delta > -NEAR_ENOUGH))
      {
        if(switches & (1<< DEFINED_LENGTH))
          e->state = RELEASE; // no sustain for defined length
        else
        {
          e->state = SUSTAIN;
          e->k2 = (1<<Q) - e->scaled.sustain_step;
        }
      }
      break;

    case SUSTAIN:
//      e->enval = (e->k2 * (Uint64)e->enval) >> Q;
      e->enval = fmull48(e->k2, e->enval);
      if((e->enval >> Q) <= NEAR_ENOUGH)
        e->state = INACTIVE;
      break;

    case RELEASE:
//      e->enval = (e->k3 * (Uint64)e->enval) >> Q;
      e->enval = fmull48(e->k3, e->enval);
      if((e->enval >> Q) <= NEAR_ENOUGH)
        e->state = INACTIVE;
      break;

    case INACTIVE:
    default:
      e->enval = 0;
  }

  return e->enval >> Q;
}


/*
 * assign_instrument
 * -----------------
 * Returns the address of an instrument structure if one exists.  Returns NULL if there
 * is no assigned instrument which will cause the key down event that called this
 * function to be ignored.
 */
static const ins_t *assign_instrument(int chan, chan_t *c, unsigned int key)
{
  int prg = c->patch.prg;
  int lo = c->patch.lo;
//  int hi = c->patch.hi;
  int i, b = 0; // if all else fails, 0 will select the GM set

  // non-pitched or percussion instruments, sound effects etc, mapped to program-key
//  if(((chan & 15) == syn.percussion_chan) || (hi == PERCUSSION_BANK))
  if((chan & 15) == (PERCUSSION_CHAN-1))
  {
    if(syn.kit_override > 0)
      b = syn.idat.kits[syn.kit_override]; // force this bank
    else if(syn.switches & (1<<ALL_KITS))
      b = syn.idat.kits[prg]; // normal bank selection

    if(b > 0) // if bank exists
      if((i = syn.idat.bank[b-1].ins[key]) != 0) // and if instrument exists
        return &syn.idat.instrument[i-1]; // select it

    if((i = syn.idat.bank[syn.idat.kits[0]-1].ins[key]) != 0)
      return &syn.idat.instrument[i-1];  // fall back to GM set
  }

  // pitched or melodic instruments, mapped to bank-program
  else
  {
    if(key > B8)
      return &def_instrument[PURE_SINE]; // pure sinewave for very high notes (to reduce aliasing)

    if(syn.bank_override > 0)
      b = syn.idat.banks[syn.bank_override]; // force this bank
    else if(syn.switches & (1<<ALL_BANKS))
      b = syn.idat.banks[lo]; // normal bank selection

    if(b > 0) // if bank exists
      if((i = syn.idat.bank[b-1].ins[prg]) != 0) // and if instrument exists
        return &syn.idat.instrument[i-1]; // select it

    if((i = syn.idat.bank[syn.idat.banks[0]-1].ins[prg]) != 0)
      return &syn.idat.instrument[i-1]; // fall back to GM set
  }

  return NULL; // no instrument
}


/*
 * synth_control
 * -------------
 * Runs at the envelope rate. Initialises generators after key on and off events.
 * Controls the envelopes, volumes, and modulation.  It's main function is to load and adjust
 * parameters for the synthesiser interrupt running at the sample rate.  The parameters such
 * as pitch, volume, etc. should really be adjusted at the sample rate but there is not
 * enough time for that so anything that changes slowly at envelope rates is controlled here
 * at the slower envelope rate.  It is a compromise that most of the time is fine and is only
 * noticable for fast rates of change in pitch or amplitude. This is a task and so is interrupted
 * by the synth interrupt. Again this might cause slight clicks if a control is updated
 * across more than one sample period but it is never noticable.
 */
void synth_control(void)
{
  int n, j, mod, vol, ch;
  unsigned int key, sw, st;
  gen_t *g;
  chan_t *c;
  const ins_t *i, *new;

  for(n=0; n<syn.num_gens; n++)
  {
    st = syn.stack[n];                        // generator stack entry
    key = (st >> KEY) & KEY_MASK;             // pitch, midi key number
    g = &syn.gen[(st >> GEN) & GEN_MASK];     // generator structure
    ch = (st >> CHANNEL) & CHAN_MASK;         // channel number
    c = &syn.chan[ch];                        // channel structure
    i = g->ins;                               // instrument structure
    sw = i->switches;                         // instrument patch switches
    int vel = (st >> VELOCITY) & VEL_MASK;    // raw velocity
    vol = (c->vol_expr * vel * vel) >> 14;    // vol(Q14) = chan_vol_expr(Q14) * vel(Q7)^2

    // key up or down
    if(st & (1<<TRIG))
    {
      st &= ~(1<<TRIG);

      if(st & (1<<GATE)) // key down, trigger note, start ATTACK
      {
        new = assign_instrument(ch, c, key); // assign instrument
        if(new)
        {
          // set fixed parameters for the new assignment
          i = g->ins = new;
          if((i->wave[0].number >= 0) && (i->wave[0].number < syn.idat.num_waves) &&
             (i->wave[1].number >= 0) && (i->wave[1].number < syn.idat.num_waves) &&
             (i->mod_wave >= 0) && (i->mod_wave < syn.idat.num_waves))
          {
            sw = i->switches;
            g->switches =  sw | (1<<ACTIVE);
            if(!(st & ((1<<RETUNE)|(1<<RETRIGGER))))
            { // causes click when retuning or retriggerring
              g->tone1_pointer = 0; // start tone at a zero crossing
              g->tone2_pointer = 0; // start tone at a zero crossing
            }
            g->waveform1 = syn.idat.wtbl[i->wave[0].number].wave; // tone1 waveform
            g->waveform2 = syn.idat.wtbl[i->wave[1].number].wave; // tone2 waveform
            g->filter_q = (1<<VLQ_BITS) - i->filter_q;   // filter resonance
            g->fm_depth = i->fm_depth;              // FM depth
            g->tone1_glide = i->wave[0].glide;
            g->tone2_glide = i->wave[1].glide;
            // modulation oscillator
            g->mod_wave = syn.idat.wtbl[i->mod_wave].wave;
            g->mod_rate = i->mod_rate;
            g->mod_depth = i->mod_depth;
            g->mod_pntr = 1 << (32-2); // start at the peak (quarter cycle from the start for a sinewave)
          }


          if(c->switches & ((1<<PORTAMENTO)|(1<<PORTAM_CTRL))) // portamento enabled channel, or received a portamento control message
            g->tone1_glide = g->tone2_glide = c->glide; // use supplied portamento time

          unsigned int pitch;
          int coarse_tune = syn.master_coarse;
          int fine_tune = syn.master_fine >> 2; // Q13 -> Q11, scale range for +- a semitone

          // wave1 pitch base
          j = i->wave[0].pitch + coarse_tune;
          if(sw & (1<<PITCH_TRACK))
            j += key;
          LIMIT(0, j, NUM_NOTES-1);
          pitch = (syn.tone_inc_table[j] * ((1 << SCALE_BITS) + i->detune + fine_tune)) >> SCALE_BITS;
          g->new_pitch1 = ((1<<GLIDE_SCALE) - g->tone1_glide) * pitch; // target pitch
          if(i->wave[0].initial_pitch != 0)
          {
            j += i->wave[0].initial_pitch;
            LIMIT(0, j, NUM_NOTES-1);
            pitch = (syn.tone_inc_table[j] * ((1 << SCALE_BITS) + i->detune + fine_tune)) >> SCALE_BITS;
            g->tone1_inc_base = pitch << GLIDE_SCALE; // initial pitch
          }
          if((c->switches & (1<<PORTAM_CTRL)) && (sw & (1<<PITCH_TRACK))) // received a portamento control message
          {
            j = i->wave[0].pitch + coarse_tune + c->portamento_ctrl;
            LIMIT(0, j, NUM_NOTES-1);
            pitch = (syn.tone_inc_table[j] * ((1 << SCALE_BITS) + i->detune + fine_tune)) >> SCALE_BITS;
            g->tone1_inc_base = pitch << GLIDE_SCALE; // initial pitch
          }

          // wave2 pitch base
          j = i->wave[1].pitch + coarse_tune;
          if(sw & (1<<PITCH_TRACK))
            j += key;
          LIMIT(0, j, NUM_NOTES-1);
          pitch = (syn.tone_inc_table[j] * ((1 << SCALE_BITS) - i->detune + fine_tune)) >> SCALE_BITS;
          g->new_pitch2 = ((1<<GLIDE_SCALE) - g->tone2_glide) * pitch; // target pitch
          if(i->wave[1].initial_pitch != 0)
          {
            j += i->wave[1].initial_pitch;
            LIMIT(0, j, NUM_NOTES-1);
            pitch = (syn.tone_inc_table[j] * ((1 << SCALE_BITS) - i->detune + fine_tune)) >> SCALE_BITS;
            g->tone2_inc_base = pitch << GLIDE_SCALE; // initial pitch
          }
          if((c->switches & (1<<PORTAM_CTRL)) && (sw & (1<<PITCH_TRACK))) // received a portamento control message
          {
            j = i->wave[1].pitch + coarse_tune + c->portamento_ctrl;
            LIMIT(0, j, NUM_NOTES-1);
            pitch = (syn.tone_inc_table[j] * ((1 << SCALE_BITS) - i->detune + fine_tune)) >> SCALE_BITS;
            g->tone2_inc_base = pitch << GLIDE_SCALE; // initial pitch
          }

          // filter pitch base
          j = i->filter_fc + coarse_tune;
          if(sw & (1<<FILTER_TRACK))
            j += key;
          LIMIT(0, j, NUM_NOTES-1);
          g->new_filter_base = ((1<<GLIDE_SCALE) - g->tone2_glide + fine_tune) * syn.filter_table[j]; // target pitch
          if((c->switches & (1<<PORTAM_CTRL)) && (sw & (1<<FILTER_TRACK))) // received a portamento control message
          {
            j = i->filter_fc + coarse_tune + c->portamento_ctrl;
            LIMIT(0, j, NUM_NOTES-1);
            g->filter_base = syn.filter_table[j] << GLIDE_SCALE;
          }

          c->switches &= ~(1<<PORTAM_CTRL); // reset the flag as we must only use portamento_ctrl data once

          // trigger envelopes
          {
            int tc_scale = env_scale_table[key]; // time constant scale, by key
            init_envelope(&g->tone1_env, &i->wave[0].env, tc_scale, (sw & (1<<WAVE_ENV_TRACK)));
            init_envelope(&g->tone2_env, &i->wave[1].env, tc_scale, (sw & (1<<WAVE_ENV_TRACK)));
            init_envelope(&g->noise_env, &i->noise_env,   tc_scale, (sw & (1<<NOISE_ENV_TRACK)));
            init_envelope(&g->filter_env, &i->filter_env, tc_scale, (sw & (1<<FILTER_ENV_TRACK)));
          }

          if(!(st & (1<<RETUNE)))
          {
            if(sw & (1<<DEFINED_LENGTH))
            {
              g->retrig = 0; // no retrigger for defined length
              st &= ~(1<<GATE); // note off not required, but will do no harm
            }
            else
              g->retrig = i->retrig; // retrigger time
          }
        }
      }

      else // key up, start RELEASE
      {
        if(!(sw & (1<<DEFINED_LENGTH))) // release is handled within envelope for defined length
          if(!(c->switches & (1 << HOLD_PEDAL))) // don't enter release state if held
          {
            g->tone1_env.state = RELEASE;
            g->tone2_env.state = RELEASE;
            g->noise_env.state = RELEASE;
            g->filter_env.state = RELEASE;
          }
        g->retrig = 0; // stop retrigger
      }

      syn.stack[n] = st;
    }

    else // key held up or held down
    {
      if(!(sw & (1<<DEFINED_LENGTH)))
        if(!(st & (1<<GATE)) && !(c->switches & (1 << HOLD_PEDAL))) // delayed release when hold is removed
        {
          g->tone1_env.state = RELEASE;
          g->tone2_env.state = RELEASE;
          g->noise_env.state = RELEASE;
          g->filter_env.state = RELEASE;
        }

/*
      // check if hold pedal has been pressed
      if(c->switches_delta & (1<<HOLD_PEDAL)) // there has been a change
      {
        c->switches_delta &= ~(1<<HOLD_PEDAL);
        printf("hold %d %s (key %s)\n", ch, offon[(c->switches >> HOLD_PEDAL) & 1], offon[(st >> GATE) & 1]);
      }
*/
      // envelope retrigger
      if(g->retrig)
        if(!--g->retrig)
        {
          g->retrig = i->retrig;
          if(sw & (1<<WAVE_RETRIGGER))
          {
            g->tone1_env.state = INIT;
            g->tone2_env.state = INIT;
          }
          if(sw & (1<<NOISE_RETRIGGER))
            g->noise_env.state = INIT;
          if(sw & (1<<FILTER_RETRIGGER))
            g->filter_env.state = INIT;
        }
    } // end of all key actions

    if(g->switches & (1<<ACTIVE))
    {
      // modulation oscilator
      j = g->mod_wave[g->mod_pntr >> FIX];
      mod = (j * g->mod_depth) >> SCALE_BITS;
      g->mod_pntr += g->mod_rate << 16;

      // filter cutoff
//      g->filter_base = ((g->tone2_glide * (Uint64)g->filter_base) >> GLIDE_SCALE) + g->new_filter_base; // glide
      g->filter_base = fmull47(g->tone2_glide, g->filter_base) + g->new_filter_base; // glide
      j = envelope(&g->filter_env, g->switches, (st & ((1<<RETUNE)|(1<<RETRIGGER))));
      if(sw & (1<<INV_FILTER_ENV))
        j = -j;
      j += g->filter_base >> GLIDE_SCALE;
      if(j < 0)
        j = 0;
      if(sw & (1<<FILTER_MOD))
        j += (j * mod) >> SCALE_BITS;    // cutoff modulation
      j >>= (SCALE_BITS-VLQ_BITS);
      // limit fc to stability limit, filter_fc < (2 - filter_q)
      int limit = (2<<VLQ_BITS) - g->filter_q;
      if(j >= limit)
        j = limit - 1;
      g->filter_fc = j;

      // noise amplitude
      j = envelope(&g->noise_env, g->switches, (st & ((1<<RETUNE)|(1<<RETRIGGER))));
      if(sw & (1<<NOISE_MOD))
        j += (j * mod) >> SCALE_BITS;    // amp modulation
      g->noise_volume = (j * vol) >> MIDI_PARAM_SCALE; // channel volume and velocity

      // wave1 amplitude
      j = envelope(&g->tone1_env, g->switches, (st & ((1<<RETUNE)|(1<<RETRIGGER))));
      if(sw & (1<<AMP1_MOD))
        j += (j * mod) >> SCALE_BITS;    // amp modulation (unsigned or DSB full carrier)
      if(sw & (1<<AMP1_RING))
        j = (j * mod) >> SCALE_BITS;     // amp modulation (signed or DSB suppressed carrier)
      g->tone1_volume = j;               // envelope and modulation (affects FM mod)
      g->tone1_vol_vel = vol;            // channel volume and velocity (doesn't affect FM mod)

      // wave1 pitch
//      g->tone1_inc_base = ((g->tone1_glide * (Uint64)g->tone1_inc_base) >> GLIDE_SCALE) + g->new_pitch1; // glide
      g->tone1_inc_base = fmull47(g->tone1_glide, g->tone1_inc_base) + g->new_pitch1; // glide
      j = g->tone1_inc_base;
      if(sw & (1<<PITCH1_MOD))
        j += (j >> 16) * mod;            // pitch modulation
      j = (j >> 13) * c->bender;         // channel pitch wheel
      g->tone1_inc = j;

      // wave2 amplitude
      j = envelope(&g->tone2_env, g->switches, (st & ((1<<RETUNE)|(1<<RETRIGGER))));
      if(sw & (1<<AMP2_MOD))
        j += (j * mod) >> SCALE_BITS;    // amp modulation (unsigned or DSB full carrier)
      if(sw & (1<<AMP2_RING))
        j = (j * mod) >> SCALE_BITS;     // amp modulation (signed or DSB suppressed carrier)
      g->tone2_volume = (j * vol) >> MIDI_PARAM_SCALE; // channel volume and velocity

      // wave2 pitch
//      g->tone2_inc_base = ((g->tone2_glide * (Uint64)g->tone2_inc_base) >> GLIDE_SCALE) + g->new_pitch2; // glide
      g->tone2_inc_base = fmull47(g->tone2_glide, g->tone2_inc_base) + g->new_pitch2; // glide
      j = g->tone2_inc_base;
      if(sw & (1<<PITCH2_MOD))
        j += (j >> 16) * mod;            // pitch modulation
      j = (j >> 13) * c->bender;         // channel pitch wheel
      g->tone2_inc = j;

      // pan / balance / gain
      g->left_vol  = (c->left_vol * i->gain) >> 10;  // instrument gain: 0dB = 1024 (Q10)
      g->right_vol = (c->right_vol * i->gain) >> 10;

      // Check if generator still active. If the master_env is not set, all volume envelopes must be INACTIVE to
      // clear the ACTIVE flag. If mester_env is set then that envelope alone clears the ACTIVE flag.
      int active = TRUE;
      switch(i->master_env)
      {
        default: // unset
          if((g->tone1_env.state == INACTIVE) &&
             (g->tone2_env.state == INACTIVE) &&
             (g->noise_env.state == INACTIVE))
            active = FALSE;
          break;

        case 1: // tone1 is master
          if(g->tone1_env.state == INACTIVE)
            active = FALSE;
          break;

        case 2: // tone2 is master
          if(g->tone2_env.state == INACTIVE)
            active = FALSE;
          break;

        case 3: // filter is master
          if(g->filter_env.state == INACTIVE)
            active = FALSE;
          break;

        case 4: // noise is master
          if(g->noise_env.state == INACTIVE)
            active = FALSE;
          break;
      }
      if(!active)
      {
        g->switches &= ~(1<<ACTIVE);
        st &= ~(1<<GATE);
        g->tone1_env.state = INACTIVE;
        g->tone1_env.enval = 0;
        g->tone2_env.state = INACTIVE;
        g->tone2_env.enval = 0;
        g->filter_env.state = INACTIVE;
        g->filter_env.enval = 0;
        g->noise_env.state = INACTIVE;
        g->noise_env.enval = 0;
      }
    } // end of generator active
  } // end of generator loop
}

/*
 * midiSynth_sample
 * ----------------
 * This should be called for every sample. i.e. at the sample rate.
 * Returns a stereo sample. 2 signed shorts packed into an unsigned 32 bit int.
 */
unsigned int midiSynth_sample(void)
{
  int spkr[2] = {0,0};
  synth_generators(&syn, spkr); // main synth generators, sample rate code
  int left = spkr[0], right = spkr[1];

  // 500Hz timer, synth envelope rate code
  if((syn.timer += ENV_RATE) >= syn.sample_rate)
  {
    syn.timer -= syn.sample_rate;
    synth_control();

    // adjust left and right volume for the system volume
    syn.sys_left_vol = (syn.master_volume * (mod.audio.sys_lr_vol >> 16)) >> 16;
    syn.sys_right_vol = (syn.master_volume * (mod.audio.sys_lr_vol & 0xffff)) >> 16;
  }

  // master volume control
  left = (syn.sys_left_vol * left) >> VLQ_BITS;
  right = (syn.sys_right_vol * right) >> VLQ_BITS;

  // stereo / mono
  if(syn.switches & (1<<MONO_AUDIO))
    left = right = (left + right) / 2;

  // left / right swap
  else if(syn.switches & (1<<L_R_SWAP))
  {
    left ^= right;
    right ^= left;
    left ^= right;
  }

  // master balance control
  int bal = syn.master_balance >> 3;
  left = (left * pantab[0x7f - bal]) >> MIDI_PARAM_SCALE;
  right = (right * pantab[bal]) >> MIDI_PARAM_SCALE;

  LIMIT(-0x8000, left, 0x7fff); // limit to signed 16 bit
  LIMIT(-0x8000, right, 0x7fff);

  return (left << 16) | (right & 0xffff);
}


