/*
  !MidiPlay   A MIDI synthesiser and file player.

  kbd.h - Keyboard interface definitions

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

#ifndef kbd_h
#define kbd_h

#include "midi.h"

#define NUM_BLKS             2     // number of blocks of 16 channels
#define SCALE_BITS          15     // signed short int fractional bits
#define NUM_GENS           128     // maximum number of note generators that can be defined
#define FREQ_A5            440     // frequency in Hz for note A5
#define SIN_BITS            10     // log2 number of entries in waveform lookup tables
#define FIX         (32-SIN_BITS)  // fractional bits in tone counters
#define GLIDE_SCALE         15     // Q position for pitch glide filter
#define ENV_SCALE_BITS      10     // Q position for the envelope pitch scale table
#define NOISE_SCALE         16     // to produce halfword noise output at a reasonable level
#define SYNTH_SCALE          2     // log2 synth gen output scale factor
#define MIDI_PARAM_SCALE    14     // MIDI parameter size in bits (7 bit msd + 7 bit lsd)
#define VLQ_BITS            10     // number of bits for master volume and filter resonance
#define EXP_BITS            10     // log2 number of entries in the exponential lookup table

#include "store.h"


// envelope variables
typedef struct envar_s
{
  enum {INACTIVE, INIT, DELAY, ATTACK, HOLD, DECAY, SUSTAIN, RELEASE} state;

  unsigned int
    count, //     current count in DELAY or HOLD states
    enval, // Q31 current output envelope value
    k1,    // Q31 )
    k2,    // Q16 ) current states' filter history
    k3;    // Q16 )

  env_t scaled; // instrument envelope, steps scaled for pitch, targets scaled for velocity

} envar_t;


// generator definition
typedef struct gen_s
{
  // these are accessed by the sample rate interrupt
  int z1;                      // filter history     )
  int z2;                      // filter history     ) updated by sample rate interrupt
  unsigned int tone1_pointer;  // wavetable pointer  )
  unsigned int tone2_pointer;  // wavetable pointer  )
  const short int *waveform1;  // wavetable address
  const short int *waveform2;  // wavetable address
  unsigned int tone1_inc;      // pointer increment
  unsigned int tone2_inc;      // pointer increment
  int tone1_volume;            // envelope + modulation, linear multiplier (Q15)
  int tone1_vol_vel;           // channel volume + velocity, linear multiplier (Q15)
  int tone2_volume;            // envelope + modulation + channel volume + velocity, linear multiplier (Q15)
  int fm_depth;                // linear multiplier
  int noise_volume;            // envelope + modulation + channel volume + velocity, linear multiplier (Q15)
  int filter_fc;               // filter cutoff (Q10)
  int filter_q;                // filter resonance (Q10)
  unsigned int switches;       // bit field
  int left_vol;                // channel pan + balance + instrument gain, linear multiplier (Q15)
  int right_vol;               // channel pan + balance + instrument gain, linear multiplier (Q15)
  // end of accessed by the sample rate interrupt

  envar_t tone1_env;           // tone1 envelope  )
  envar_t tone2_env;           // tone2 envelope  ) envelope, scaled for pitch and velocity.
  envar_t filter_env;          // filter envelope ) working variables plus instrument
  envar_t noise_env;           // noise envelope  )
  const ins_t *ins;            // instrument parameters
  int retrig;                  // retrigger counter
  unsigned int tone1_inc_base; // tone1 generator rate before modulation adjustment
  unsigned int tone2_inc_base; // tone2 generator rate before modulation adjustment
  unsigned int filter_base;    // filter cutoff before modulation and envelope adjustment
  unsigned int tone1_glide;    // glide time constant, 0 = instant, 32767 = forever.
  unsigned int tone2_glide;    // glide time constant, 0 = instant, 32767 = forever.
  unsigned int new_pitch1;     // target tone1 pitch modified by glide time constant.
  unsigned int new_pitch2;     // target tone2 pitch modified by glide time constant.
  unsigned int new_filter_base; // target filter_base pitch modified by tone2 glide time constant.

  // modulation oscillator
  const short int *mod_wave;   // wavetable number
  unsigned int mod_pntr;       // wavetable pointer
  short int mod_rate;          // modulation rate
  short int mod_depth;         // modulation ammount

} gen_t;


/*
MIDI routing
------------
 ports:  P = File Player, M = MIDI device, S = Synthesiser, K = Keyboard

 output:              |-- Synth --|   |- MIDI dev-|
         31     8   7   6   5   4   3   2   1   0
        +---   ---+---+---+---+---+---+---+---+---+
 input: |   unused    | K | M | P |   | K | M | P |
        +---   ---+---+---+---+---+---+---+---+---+
*/
// bit numbers for midi routing flags
//                  route
//                  -----------------
//#define PI_MO  0 // Player   to MIDI dev
//#define MI_MO  1 // MIDI dev to MIDI dev
//#define KI_MO  2 // Keyboard to MIDI dev
//#define PI_SO  4 // Player   to Synth
//#define MI_SO  5 // MIDI dev to Synth
//#define KI_SO  6 // Keyboard to Synth

// sources for print_midi_msg
#define PLAYER   0
#define KEYBOARD 1
#define EDITOR   2

enum {WAS,CUR}; // index to keys below

// main structure
typedef struct syn_s
{
  // synth
  int seed;                    // noise sequence memory
  int num_gens;                // defined number of generators
  gen_t gen[NUM_GENS];         // generator array

  int master_volume;           // overall volume
  int balance;                 // left right channel balance
  int lpan;                    // left balance after law applied
  int rpan;                    // right balance after law applied
  unsigned int switches;       // global effects
  unsigned int stack[NUM_GENS]; // generator stack

  // instrument definitions
  ins_data_t idat;             // sound set (instruments, banks, waves)

  // midi
  chan_t chan[NUM_BLKS*NUM_MIDI_CHANS]; // midi channel data
  m_in_t  m_in;                // midi message in
  m_out_t m_out;               // keyboard and midi message out
  sysex_t sysex;               // system exclusive messages

  // keyboard
  unsigned int keys[2][4];     // current and previous status of keyboard, max 128 notes
  kbd_patch_t kbd_patch;       // list of patches, selected patch, number of patches
  ins_t user;                  // current keyboard and editor instrument

  // misc
  int bank_override;
  int kit_override;
  int percussion_chan;         // current percussion channel, can be changed by midi bank hi if enabled
  int def_perc_chan;           // default percussion channel, starts with this

  // timing
  unsigned int sample_rate;    // timing for synth and player is based on this
  unsigned int timer_syn;      // synth control code timer
  unsigned int timer_kbd;      // synth keyboard scan timer
  int scale_factor;            // glide time scale factor

  // calculated tables
  unsigned short int tone_inc_table[NUM_NOTES];
  unsigned short int filter_table[NUM_NOTES];

} syn_t;

// syn.switches           bit
#define POLY_MODE          0  // 0 = poly,    1 = mono
#define OMNI_MODE          1  // 0 = omni on, 1 = omni off
#define MONO_VOICES        2  // start of mono voices field
#define MONO_MASK  ((1<<5)-1) // mask for mono voices field (5 bits)
#define FLT_FLANGER        7  // )
#define FLT_REVERB         8  // )
#define FLT_CHORUS         9  // ) 0 = off, 1 = on
#define FLT_ECHO          10  // )
#define FLT_TONE          11  // )
#define MONO_AUDIO        12  // 0=stereo, 1=mono
#define L_R_SWAP          13  // 0=normal, 1=L/R swapped
#define ALL_BANKS         14  // 0=GM bank only, 1=Allow all Banks to be selected via MIDI
#define ALL_KITS          15  // 0=GM drum kit only, 1=Allow all Drum Kits to be selected via MIDI
#define BANK_SEL_DRUM     16  // 0=fixed percussion channel, 1=allow bank hi 127 to select chan
#define PRG_UPDATES_BANKS 17  // 0=Bank msgs actioned when rcvd, 1=Bank msgs actioned on the next Program change
#define CSV_NO_NUMBER     18  // 0=CSV bank map includes instrument number, 1=CSV bank map excludes instrument number
#define PATCH_NO_KITS     19  // 0=Patch list includes drum kits, 1=Patch list excludes drum kits
#define PATCH_BY_BANK     20  // 0=Patch's listed by program then bank, 1=Patch's listed by bank then program

extern syn_t syn;

// channel blocks,  0-15 = player, 16-31 = kbd
#define REMOTE_CHAN        0  // player
#define KBD_CHAN           1  // keyboard
#define KBD_CHAN_OFFSET   16  // offset to second set of 16 channels

// special bank hi values used in the patch list
#define PERCUSSION_BANK  127  // percussion kit selection bank Hi
#define PERCUSSION_INST  128  // percussion instrument edit bank Hi


void display_user(void);
void calculate_tables(int sample_rate);
int midiSynth_init(int sample_rate);
void midiSynth_term(void);
int midiSynth_reset(void);
void poly_action_key(int key, int key_pressed, int channel, int velocity);
void clear_history(void);
void reset_gates(int channel);
void reset_all_gates(int chan_blk);
void reset_mono(void);
void portamento_on_off(int channel, int on);
int cmd_reset(char *msg, int len);
int cmd_user(char *msg, int len);
int cmd_note(char *msg, int len);
int cmd_poly(char *msg, int len);
unsigned int *midiPlayer_sample(void);

void synth_generators(syn_t*, int *); // synth.c

#endif
