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

  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;


// 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;           // midi overall volume (Q10)
  int master_balance;          // midi overall balance (Q10)
  int master_fine;             // midi overall fine tuning
  int master_coarse;           // midi overall coarse tuning
  int master_tuning;           // midi overall tuning, combined fine and coarse
  int sys_left_vol;            // combined midi and sys_lr volumes (Q10)
  int sys_right_vol;           // combined midi and sys_lr volumes (Q10)
  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
  sysex_t sysex;               // system exclusive messages

  // misc
  int bank_override;
  int kit_override;

  // timing
  unsigned int sample_rate;    // synth sample rate
  unsigned int timer;          // synth control code 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  (unused in module version)
#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

extern syn_t syn;

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


void calculate_tables(int sample_rate);
unsigned int midiSynth_sample(void);
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 reset_gates(int channel);
void reset_all_gates(int chan_blk);
void portamento_on_off(int channel, int on);

void synth_generators(syn_t *syn, int output[]); // synth.c (or .s)

#endif
