// ----
// ---- file   : StSample.h
// ---- author : Bastian Spiegel <bs@tkscript.de>
// ---- legal  : (c) 2009-2019 by Bastian Spiegel. 
// ----          Distributed under terms of the GNU LESSER GENERAL PUBLIC LICENSE (LGPL). See 
// ----          http://www.gnu.org/licenses/licenses.html#LGPL or COPYING for further information.
// ----
// ---- info   : This is part of the "syntracker" midi sequencer.
// ----
// ---- created: 23Sep2009
// ----          
// ---- changed: 26Dec2009, 27Dec2009, 29Dec2009, 02Jan2010, 05Jan2010, 07Jan2010, 15Jan2010
// ----          19Jan2010, 21Jan2010, 21Feb2010, 01Mar2010, 29Apr2010, 02May2010, 07Jul2010
// ----          18Jul2010, 04Sep2010, 05Mar2011, 10Mar2011, 14Mar2011, 20Mar2011, 28Mar2011
// ----          08May2013, 09May2013, 23Dec2018, 27Dec2018, 30Dec2018, 31Dec2018, 02Jan2019
// ----          04Jan2019, 07Jan2019, 08Jan2019, 09Jan2019, 10Jan2019, 30Mar2019, 31Mar2019
// ----          23Apr2019, 11May2019, 12May2019, 13May2019, 15May2019, 17May2019
// ----
// ----
// ----

#ifndef __ST_SAMPLE_H__
#define __ST_SAMPLE_H__

YG("tksampler")


class StSampleBank;


typedef struct StSampleMMEntry_s {
   sBool b_enable;
   sU8   op;  // 0=add, 1=mul
   sU16  src;
   sF32  amt;
   sU16  dst;
} StSampleMMEntry;


YC class StSample : public YAC_Object {

/* @constant STSAMPLE_DEFAULT_MAXVOICES,int
 */
#define STSAMPLE_DEFAULT_MAXVOICES YCI 8


#define STSAMPLE_DEFAULT_TIMEDLOOP_BASE 1000.0f

#define STSAMPLE_MAX_ALT_SAMPLES  (128u)

  public:
   StSample   *        next;
   StSampleBank *      parent_samplebank;
   YAC_String *        name;
   StWaveform *        waveform;
   sBool               b_own_waveform;
   StSampleMutexGroup *mutex_group;

   StRange *key_range; // Owned by sample instance
   StRange *vel_range;
   StRange *mod_range;

   sBool b_skip_range;  // 1=ignore key/vel/mod ranges, 0=enable(when present).  used by editor when solo'ing zones.

   sUI max_voices; // max voices per SamplePlayer instance. 0=only apply samplebank voice limiter

   sBool b_enabled; // 1=sample is allowed to play, 0=sample muted (mainly for editor)

   sF32 sample_delay; // #sec
   sUI  sample_offset;
   sUI  sample_len;
   YAC_IntArray *sample_loops; // offset/len/times tuples, NULL=use waveform default loop
                               //  actually all unsigned values
                               //  times bit 31 indicates loop jump
                               //        bit 30 indicates a countdown check (branch until countdown reaches 0)
                               //        bit 29 indicates a countdown initializer (no branch)
                               //        bits 28..25 identify a countdown variable (0..15)
                               //        bit 24 indicates a var-copy/move (from VAL to VAR)
                               //        bits 23..16 are reserved for future extensions
                               //        bits 0..15 determine number of repeats, branch target or countdown value

   sSI first_loop_index;  // mainly for editor (solo loop entry)
   sBool ui_sync_first_loop_index;

   sSI noteoff_loop_index; // !=-1: jump to specified loop step when note key is released
   sBool b_noteoff_immediate_loop_jump; // 0=play until end of cycle, 1=start new loop immediately. default=0

   sBool b_freeze_sampleoff_when_quiet; // 1=stop rendering when vol is 0, 0=process loops etc. even if not audible (default)

   sBool b_modshiftorig; // modshift sweep style: 1=0..(wavlen-(smpoff+smplen))  , 0=0..(wavlen-(smpoff+modsmplen))

   sBool b_sampleoffnoteon; // 1=allow mod_sampleoff only before voice is started, 0=allow continuous modulation (may cause clicks)

   enum {
      LOOP_OP_MASK  = ((1u<<31)|(1u<<30)|(1u<<29)|(1u<<28)),
      LOOP_OP_SHIFT = 28,
      // loop_op_mask==0, =>
      //    loopptr+0 = sample offset
      //    loopptr+1 = sample len
      //    loopptr+2 = loop op / #repeats
      LOOP_OP_JMP   = (1u<<LOOP_OP_SHIFT), // Jump to loop #val
      LOOP_OP_JNZ   = (2u<<LOOP_OP_SHIFT), // Decrement var and jump to loop #val if not zero
      LOOP_OP_SET   = (3u<<LOOP_OP_SHIFT), // Copy 16bit val to var
      LOOP_OP_MOV   = (4u<<LOOP_OP_SHIFT), // Move var#val to var

      LOOP_VAR_MASK = ((1u<<24)|(1u<<25)|(1u<<26)|(1u<<27)),
      LOOP_VAR_SHIFT = 24,

      LOOP_VAL_MASK = 0xffffu
   };

//#define STSAMPLE_LOOP_OP_MASK   YCI ((1u<<31)|(1u<<30)|(1u<<29)|(1u<<28))
//#define STSAMPLE_LOOP_OP_SHIFT  YCI 28
//#define STSAMPLE_LOOP_OP_JMP    YCI (1u<<LOOP_OP_SHIFT)
//#define STSAMPLE_LOOP_OP_JNZ    YCI (2u<<LOOP_OP_SHIFT)
//#define STSAMPLE_LOOP_OP_SET    YCI (3u<<LOOP_OP_SHIFT)
//#define STSAMPLE_LOOP_OP_MOV    YCI (4u<<LOOP_OP_SHIFT)
//#define STSAMPLE_LOOP_VAR_MASK  YCI ((1u<<24)|(1u<<25)|(1u<<26)|(1u<<27))
//#define STSAMPLE_LOOP_VAR_SHIFT YCI 24
//#define STSAMPLE_LOOP_VAL_MASK  YCI 0xffffu

   sF32 volume;
   sF32 vol_lfo_amt;
   sF32 pan;
   sF32 pan_env_amt;
   sF32 pan_lfo_amt;
   sF32 transpose; // trp/finetune +-1 = 1 semitone. sum of ui_transpose_*
   sS8 ui_transpose_oct;  // +-4
   sS8 ui_transpose_semi;  // +-12
   sF32 ui_transpose_cents;  // +-100
   sF32 freq_env_amt;
   sF32 freq_lfo_amt;

   sF32 beat_frequency;  // -100.100, note-locked detune

   // default=0.0 (velocity does not affect volume)
   //        -1.0 = decrease volume
   //         1.0 = increase volume
   sF32 volume_velocity_amount; 

   // 0..1
   sF32 sampleoffset_velocity_amount;
   sBool b_invert_sampleoffset_velocity_amount;

   // 0..1
   sF32 sampleoffset_rel;

   // 0..1
   sF32 sampleoffset_rand_amount;

   sBool b_timestretch;                  // 1=enable timestretch
   sBool b_timestretch_xfade;            // 1=crossfade cycle start/end (suppress hifreq clicks)
   sF32  timestretch;                    // -1..1
   sF32  timestretch_granularity;        // cycle length, in samples
   sF32  timestretch_granularity_amount; // 0..1, 1=small granularity if close to orig pitch
   sBool b_static_cyclelen;              // 1=force cycle length (chiptunes), 0=pitch dependent cyclelength (normal samples)
   sBool b_absolute_timestretch;         // 1=absolute timestretch (1.0=1 sec to reach next cycle), 0=pitch dependent cycle walking
   sSI   timestretch_interpol_type;      // see STSAMPLE_TIMESTRETCH_INTERPOL_xxx
   sF32  timestretch_bend;               // -1..1  (phase bend)
   sBool b_waveguide;                    // 1=user defined wavetable path
   sSI   waveguide_idx;                  // initial cycle index
   YAC_FloatArray *waveguide_table;
   sF32  timestretch_startphase_rand_amount;


#define STSAMPLE_TIMESTRETCH_INTERPOL_NONE        YCI  0
#define STSAMPLE_TIMESTRETCH_INTERPOL_LINEAR      YCI  1
#define STSAMPLE_TIMESTRETCH_INTERPOL_SMOOTHSTEP  YCI  2
#define STSAMPLE_TIMESTRETCH_INTERPOL_CLIP25      YCI  3
#define STSAMPLE_TIMESTRETCH_INTERPOL_CLIP50      YCI  4
#define STSAMPLE_TIMESTRETCH_INTERPOL_CLIP75      YCI  5
#define STSAMPLE_TIMESTRETCH_INTERPOL_CLIPMOD     YCI  6
#define STSAMPLE_TIMESTRETCH_INTERPOL_CLIPVEL     YCI  7
#define STSAMPLE_TIMESTRETCH_INTERPOL_OFF25       YCI  8
#define STSAMPLE_TIMESTRETCH_INTERPOL_OFF50       YCI  9
#define STSAMPLE_TIMESTRETCH_INTERPOL_OFF75       YCI 10
#define STSAMPLE_TIMESTRETCH_INTERPOL_OFFMOD      YCI 11
#define STSAMPLE_TIMESTRETCH_INTERPOL_OFFVEL      YCI 12
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE25W00  YCI 13
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE25W25  YCI 14
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE25W50  YCI 15
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE25W75  YCI 16
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE50W00  YCI 17
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE50W25  YCI 18
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE50W50  YCI 19
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE50W75  YCI 20
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE75W00  YCI 21
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE75W25  YCI 22
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE75W50  YCI 23
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASE75W75  YCI 24
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEMODW00 YCI 25
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEMODW25 YCI 26
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEMODW50 YCI 27
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEMODW75 YCI 28
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEMODVEL YCI 29
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEVELW00 YCI 30
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEVELW25 YCI 31
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEVELW50 YCI 32
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEVELW75 YCI 33
#define STSAMPLE_TIMESTRETCH_INTERPOL_PHASEVELMOD YCI 34
#define STSAMPLE_TIMESTRETCH_INTERPOL_ORDER2      YCI 35
#define STSAMPLE_TIMESTRETCH_INTERPOL_ORDER3      YCI 36
#define STSAMPLE_TIMESTRETCH_INTERPOL_ORDER4      YCI 37
#define STSAMPLE_TIMESTRETCH_INTERPOL_ORDER5      YCI 38
#define STSAMPLE_TIMESTRETCH_INTERPOL_ORDER6      YCI 39
#define STSAMPLE_TIMESTRETCH_INTERPOL_ORDER7      YCI 40

   sBool b_timedloop;        // 1= pitch independent number of repeats (volramping), 0=loop at cycle boundaries(pitch dependent)
   sBool b_timedloop_fade;   // 1=fade in/out when switching waveforms / loop steps, 0=toggle hard (perc.) (TODO) rename this to b_fade ?
   sBool b_oneshot_loopstep; // 1= auto-insert silence after oneshot replay of (timed) loopstep
   sF32  timedloop_base;     // multiply loop repeatcount by 1sec/timedloop_base. requires b_loopms=1. Default is 1000.0f (=> 1millisec)

   StADSR *adsr_freq;   // Owned by sample instance
   StADSR *adsr_vol;
   StADSR *adsr_pan;
   StADSR *adsr_aux;

   StLFO *lfo_freq;
   StLFO *lfo_vol;
   StLFO *lfo_pan;
   StLFO *lfo_aux;

   StLFOPlayer lfo_freq_global;
   StLFOPlayer lfo_vol_global;
   StLFOPlayer lfo_pan_global;
   StLFOPlayer lfo_aux_global;
   sUI         global_lfo_tick_nr;

   sUI num_volramp_steps_in;  // 0=no ramping, >0: fadein new voice in n blocks. default=1
   sUI num_volramp_steps_out; // 0=no ramping, >0: delay next voice re-alloc by n blocks and fadeout. default=1

#define STSAMPLE_INTERPOL_NONE   YCI 0
#define STSAMPLE_INTERPOL_LINEAR YCI 1
   sSI interpol_type;

   struct {
      sBool     b_enable;  // 1=alternate between samples/zones in the same key/vel/mod range
      StSample *hdr;  // group hdr. NULL = first or only sample in alt group
      StSample *samples[STSAMPLE_MAX_ALT_SAMPLES];  // see StSampleBank::updateAltGroups()
      sUI       num;  // number of samples in alt group
      sUI       rand_tbl[STSAMPLE_MAX_ALT_SAMPLES];  // for non-repeating random number generator
      sUI       rand_num_left;
   } alt;

#define STSAMPLE_FLT_TYPE_NONE  YCI  0

#define STSAMPLE_FLT_TYPE_LP    YCI  1
#define STSAMPLE_FLT_TYPE_LPLP  YCI  2
#define STSAMPLE_FLT_TYPE_HP    YCI  3
#define STSAMPLE_FLT_TYPE_HPHP  YCI  4
#define STSAMPLE_FLT_TYPE_BP    YCI  5
#define STSAMPLE_FLT_TYPE_BPBP  YCI  6
#define STSAMPLE_FLT_TYPE_BR    YCI  7
#define STSAMPLE_FLT_TYPE_BRBR  YCI  8
#define STSAMPLE_FLT_TYPE_PEQ   YCI  9
#define STSAMPLE_FLT_TYPE_PEQ2  YCI 10
#define STSAMPLE_FLT_TYPE_LSH   YCI 11
#define STSAMPLE_FLT_TYPE_LSH2  YCI 12
#define STSAMPLE_FLT_TYPE_HSH   YCI 13
#define STSAMPLE_FLT_TYPE_HSH2  YCI 14

#define STSAMPLE_FLT_TYPE_LPHP  YCI 15
#define STSAMPLE_FLT_TYPE_LPBP  YCI 16
#define STSAMPLE_FLT_TYPE_LPBR  YCI 17

#define STSAMPLE_FLT_TYPE_HPLP  YCI 18
#define STSAMPLE_FLT_TYPE_HPBP  YCI 19
#define STSAMPLE_FLT_TYPE_HPBR  YCI 20

#define STSAMPLE_FLT_TYPE_BPLP  YCI 21
#define STSAMPLE_FLT_TYPE_BPHP  YCI 22
#define STSAMPLE_FLT_TYPE_BPBR  YCI 23

#define STSAMPLE_FLT_TYPE_BRLP  YCI 24
#define STSAMPLE_FLT_TYPE_BRHP  YCI 25
#define STSAMPLE_FLT_TYPE_BRBP  YCI 26


   sUI  filter_type;         // STSAMPLE_FLT_TYPE_xxx
   sF32 filter_cutoff;       // -1..1
   sF32 filter_pan;          // cutoff_r + pan , cutoff_l - pan  (-1..1)
   sF32 filter_offset;       // -1..1, for dual filter cfg (cutoff+offset for 1st, cutoff-offset for 2nd)
   sF32 filter_eq_gain;      // -50..50, for PEAK, LSH, and HSH filters
   sF32 filter_resonance;    // 0..1
   sF32 filter_aux_env_amount;  // -1..1
   sF32 filter_aux_env_velocity_amount;  // -2..2  (added to aux_env_amount)
   sF32 filter_aux_lfo_amount;  // -1..1
   sF32 filter_keyboard_amount; // -1..1


#define STSAMPLE_GLIDE_NONE       YCI 0
#define STSAMPLE_GLIDE_TIME_LIN   YCI 1
#define STSAMPLE_GLIDE_TIME_EXP2  YCI 2
#define STSAMPLE_GLIDE_TIME_EXP3  YCI 3
#define STSAMPLE_GLIDE_TIME_EXP4  YCI 4
#define STSAMPLE_GLIDE_FREQ_LIN   YCI 5
#define STSAMPLE_GLIDE_FREQ_EXP2  YCI 6
#define STSAMPLE_GLIDE_FREQ_EXP3  YCI 7
#define STSAMPLE_GLIDE_FREQ_EXP4  YCI 8
   sUI   glide_type;
   sF32  glide_speed_time_up;    // 1=instantly, 0=never (delta per 1000Hz tick)
   sF32  glide_speed_time_down;
   sF32  glide_speed_freq_up;    // linear frequency delta per 1000Hz tick (1=semitone)
   sF32  glide_speed_freq_down;
   sBool b_glide_release;        // true=allow glide for notes in release
   sSI   glide_max_note_dist;    // max note delta for glide voice reallocation (if exceeded, alloc new voice) (1..127)
   sBool b_glide_glissando;      // true=quantize to semitones
   sUI   glide_min_time;         // #millisec threshold since note-on (less=alloc new voice, greater=slide). 0=off
   sBool b_glide_retrig_sample;
   sBool b_glide_retrig_env_freq;
   sBool b_glide_retrig_env_vol;
   sBool b_glide_retrig_env_pan;
   sBool b_glide_retrig_env_aux;
   sBool b_glide_retrig_lfo_freq;
   sBool b_glide_retrig_lfo_vol;
   sBool b_glide_retrig_lfo_pan;
   sBool b_glide_retrig_lfo_aux;


#define STSAMPLE_NUM_MODMATRIX_ENTRIES  YCI  12

#define STSAMPLE_MM_OP_AUTO             YCI  0
#define STSAMPLE_MM_OP_ADD              YCI  1
#define STSAMPLE_MM_OP_MUL              YCI  2
#define STSAMPLE_MM_OP_BLEND_SRC        YCI  3
#define STSAMPLE_MM_OP_BLEND_AMT        YCI  4
#define STSAMPLE_MM_NUM_OP              YCI  5

#define STSAMPLE_MM_SRC_NONE                  YCI   0
#define STSAMPLE_MM_SRC_CONST_1               YCI   1
#define STSAMPLE_MM_SRC_CONST_M1              YCI   2
#define STSAMPLE_MM_SRC_CONST_0               YCI   3
#define STSAMPLE_MM_SRC_CONST_255             YCI   4 
#define STSAMPLE_MM_SRC_RAND_1_PM             YCI   5 
#define STSAMPLE_MM_SRC_RAND_1_P              YCI   6 
#define STSAMPLE_MM_SRC_RAND_2_PM             YCI   7
#define STSAMPLE_MM_SRC_RAND_2_P              YCI   8
#define STSAMPLE_MM_SRC_RAND_3_PM             YCI   9
#define STSAMPLE_MM_SRC_RAND_3_P              YCI  10
#define STSAMPLE_MM_SRC_RAND_4_PM             YCI  11
#define STSAMPLE_MM_SRC_RAND_4_P              YCI  12
#define STSAMPLE_MM_SRC_KEYBOARD_PM           YCI  13  
#define STSAMPLE_MM_SRC_KEYBOARD_P            YCI  14  
#define STSAMPLE_MM_SRC_KEYBOARD_M            YCI  15  
#define STSAMPLE_MM_SRC_KEYBOARD_ABS          YCI  16  
#define STSAMPLE_MM_SRC_VOICE_NR              YCI  17
#define STSAMPLE_MM_SRC_VOICE_NR_EVEN         YCI  18
#define STSAMPLE_MM_SRC_VOICE_NR_ODD          YCI  19
#define STSAMPLE_MM_SRC_VOICE_NR_EVENODD      YCI  20
#define STSAMPLE_MM_SRC_VOICE_NR_ODDEVEN      YCI  21
#define STSAMPLE_MM_SRC_ACTIVE_NOTES          YCI  22
#define STSAMPLE_MM_SRC_ACTIVE_NOTE_EVEN      YCI  23
#define STSAMPLE_MM_SRC_ACTIVE_NOTE_ODD       YCI  24
#define STSAMPLE_MM_SRC_ACTIVE_NOTE_EVENODD   YCI  25
#define STSAMPLE_MM_SRC_ACTIVE_NOTE_ODDEVEN   YCI  26
#define STSAMPLE_MM_SRC_VELOCITY              YCI  27
#define STSAMPLE_MM_SRC_VELOCITY_HI           YCI  28
#define STSAMPLE_MM_SRC_RELEASE_VELOCITY      YCI  29
#define STSAMPLE_MM_SRC_RELEASE_VELOCITY_HI   YCI  30
#define STSAMPLE_MM_SRC_PITCHBEND_PM          YCI  31
#define STSAMPLE_MM_SRC_PITCHBEND_PM_ON       YCI  32
#define STSAMPLE_MM_SRC_PITCHBEND_P           YCI  33
#define STSAMPLE_MM_SRC_PITCHBEND_P_ON        YCI  34
#define STSAMPLE_MM_SRC_PITCHBEND_M           YCI  35
#define STSAMPLE_MM_SRC_PITCHBEND_M_ON        YCI  36
#define STSAMPLE_MM_SRC_PRESSURE              YCI  37
#define STSAMPLE_MM_SRC_PRESSURE_ON           YCI  38
#define STSAMPLE_MM_SRC_PRESSURE_HI           YCI  39
#define STSAMPLE_MM_SRC_PRESSURE_HI_ON        YCI  40
#define STSAMPLE_MM_SRC_PRESSURE_MAX          YCI  41
#define STSAMPLE_MM_SRC_CC1_MODWHEEL          YCI  42
#define STSAMPLE_MM_SRC_CC1_MODWHEEL_ON       YCI  43
#define STSAMPLE_MM_SRC_CC2_BREATHCTL         YCI  44
#define STSAMPLE_MM_SRC_CC2_BREATHCTL_ON      YCI  45
#define STSAMPLE_MM_SRC_CC4_FOOTCTL           YCI  46
#define STSAMPLE_MM_SRC_CC4_FOOTCTL_ON        YCI  47
#define STSAMPLE_MM_SRC_CC7_VOLUME            YCI  48
#define STSAMPLE_MM_SRC_CC7_VOLUME_ON         YCI  49
#define STSAMPLE_MM_SRC_CC8_BALANCE           YCI  50
#define STSAMPLE_MM_SRC_CC8_BALANCE_ON        YCI  51
#define STSAMPLE_MM_SRC_CC10_PAN              YCI  52
#define STSAMPLE_MM_SRC_CC10_PAN_ON           YCI  53
#define STSAMPLE_MM_SRC_CC11_EXPRESSION       YCI  54
#define STSAMPLE_MM_SRC_CC11_EXPRESSION_ON    YCI  55
#define STSAMPLE_MM_SRC_CC16_GENERAL_1        YCI  56 
#define STSAMPLE_MM_SRC_CC16_GENERAL_1_ON     YCI  57 
#define STSAMPLE_MM_SRC_CC17_GENERAL_2        YCI  58
#define STSAMPLE_MM_SRC_CC17_GENERAL_2_ON     YCI  59
#define STSAMPLE_MM_SRC_CC18_GENERAL_3        YCI  60
#define STSAMPLE_MM_SRC_CC18_GENERAL_3_ON     YCI  61
#define STSAMPLE_MM_SRC_CC19_GENERAL_4        YCI  62
#define STSAMPLE_MM_SRC_CC19_GENERAL_4_ON     YCI  63
#define STSAMPLE_MM_SRC_CC74_BRIGHT           YCI  64
#define STSAMPLE_MM_SRC_CC74_BRIGHT_ON        YCI  65
#define STSAMPLE_MM_SRC_LFO_FREQ              YCI  66
#define STSAMPLE_MM_SRC_LFO_VOL               YCI  67 
#define STSAMPLE_MM_SRC_LFO_PAN               YCI  68 
#define STSAMPLE_MM_SRC_LFO_AUX               YCI  69 
#define STSAMPLE_MM_SRC_ENV_FREQ              YCI  70 
#define STSAMPLE_MM_SRC_ENV_VOL               YCI  71
#define STSAMPLE_MM_SRC_ENV_PAN               YCI  72
#define STSAMPLE_MM_SRC_ENV_AUX               YCI  73
#define STSAMPLE_MM_NUM_SRC                   YCI  74

#define STSAMPLE_MM_DST_NONE                        YCI   0
#define STSAMPLE_MM_DST_FREQ                        YCI   1
#define STSAMPLE_MM_DST_FREQ_OCT                    YCI   2
#define STSAMPLE_MM_DST_FREQ_FIFTH                  YCI   3 
#define STSAMPLE_MM_DST_FREQ_FOURTH                 YCI   4 
#define STSAMPLE_MM_DST_FREQ_SEMI                   YCI   5
#define STSAMPLE_MM_DST_FREQ_FINE                   YCI   6
#define STSAMPLE_MM_DST_FREQ_BEAT                   YCI   7 
#define STSAMPLE_MM_DST_VOLUME                      YCI   8
#define STSAMPLE_MM_DST_PAN                         YCI   9
#define STSAMPLE_MM_DST_FILTER_CUTOFF               YCI  10
#define STSAMPLE_MM_DST_FILTER_PAN                  YCI  11
#define STSAMPLE_MM_DST_FILTER_OFFSET               YCI  12
#define STSAMPLE_MM_DST_FILTER_RESONANCE            YCI  13
#define STSAMPLE_MM_DST_SAMPLE_OFFSET               YCI  14
#define STSAMPLE_MM_DST_SAMPLE_SHIFT                YCI  15
#define STSAMPLE_MM_DST_SAMPLE_SHIFT_EOL            YCI  16
#define STSAMPLE_MM_DST_CYCLE_LEN                   YCI  17
#define STSAMPLE_MM_DST_JUMPTOLOOP                  YCI  18
#define STSAMPLE_MM_DST_FREQ_LFO_SPEED              YCI  19
#define STSAMPLE_MM_DST_FREQ_LFO_SPEED_ABS          YCI  20
#define STSAMPLE_MM_DST_FREQ_LFO_LEVEL              YCI  21
#define STSAMPLE_MM_DST_VOL_LFO_SPEED               YCI  22
#define STSAMPLE_MM_DST_VOL_LFO_SPEED_ABS           YCI  23
#define STSAMPLE_MM_DST_VOL_LFO_LEVEL               YCI  24
#define STSAMPLE_MM_DST_PAN_LFO_SPEED               YCI  25
#define STSAMPLE_MM_DST_PAN_LFO_SPEED_ABS           YCI  26
#define STSAMPLE_MM_DST_PAN_LFO_LEVEL               YCI  27
#define STSAMPLE_MM_DST_AUX_LFO_SPEED               YCI  28
#define STSAMPLE_MM_DST_AUX_LFO_SPEED_ABS           YCI  29
#define STSAMPLE_MM_DST_AUX_LFO_LEVEL               YCI  30
#define STSAMPLE_MM_DST_FREQ_ENV_SPEED              YCI  31
#define STSAMPLE_MM_DST_FREQ_ENV_SPEED_ABS          YCI  32
#define STSAMPLE_MM_DST_FREQ_ENV_LEVEL              YCI  33
#define STSAMPLE_MM_DST_FREQ_ENV_INTENSITY          YCI  34
#define STSAMPLE_MM_DST_FREQ_ENV_ATTACK_SPEED       YCI  35
#define STSAMPLE_MM_DST_FREQ_ENV_ATTACK_SPEED_ABS   YCI  36
#define STSAMPLE_MM_DST_FREQ_ENV_SUSTAIN_SPEED      YCI  37
#define STSAMPLE_MM_DST_FREQ_ENV_SUSTAIN_SPEED_ABS  YCI  38
#define STSAMPLE_MM_DST_FREQ_ENV_RELEASE_SPEED      YCI  39
#define STSAMPLE_MM_DST_FREQ_ENV_RELEASE_SPEED_ABS  YCI  40
#define STSAMPLE_MM_DST_VOL_ENV_SPEED               YCI  41
#define STSAMPLE_MM_DST_VOL_ENV_SPEED_ABS           YCI  42
#define STSAMPLE_MM_DST_VOL_ENV_LEVEL               YCI  43
#define STSAMPLE_MM_DST_VOL_ENV_INTENSITY           YCI  44
#define STSAMPLE_MM_DST_VOL_ENV_ATTACK_SPEED        YCI  45
#define STSAMPLE_MM_DST_VOL_ENV_ATTACK_SPEED_ABS    YCI  46
#define STSAMPLE_MM_DST_VOL_ENV_SUSTAIN_SPEED       YCI  47
#define STSAMPLE_MM_DST_VOL_ENV_SUSTAIN_SPEED_ABS   YCI  48
#define STSAMPLE_MM_DST_VOL_ENV_RELEASE_SPEED       YCI  49
#define STSAMPLE_MM_DST_VOL_ENV_RELEASE_SPEED_ABS   YCI  50
#define STSAMPLE_MM_DST_PAN_ENV_SPEED               YCI  51
#define STSAMPLE_MM_DST_PAN_ENV_SPEED_ABS           YCI  52
#define STSAMPLE_MM_DST_PAN_ENV_LEVEL               YCI  53
#define STSAMPLE_MM_DST_PAN_ENV_INTENSITY           YCI  54
#define STSAMPLE_MM_DST_PAN_ENV_ATTACK_SPEED        YCI  55
#define STSAMPLE_MM_DST_PAN_ENV_ATTACK_SPEED_ABS    YCI  56
#define STSAMPLE_MM_DST_PAN_ENV_SUSTAIN_SPEED       YCI  57
#define STSAMPLE_MM_DST_PAN_ENV_SUSTAIN_SPEED_ABS   YCI  58
#define STSAMPLE_MM_DST_PAN_ENV_RELEASE_SPEED       YCI  59
#define STSAMPLE_MM_DST_PAN_ENV_RELEASE_SPEED_ABS   YCI  60
#define STSAMPLE_MM_DST_AUX_ENV_SPEED               YCI  61
#define STSAMPLE_MM_DST_AUX_ENV_SPEED_ABS           YCI  62
#define STSAMPLE_MM_DST_AUX_ENV_LEVEL               YCI  63
#define STSAMPLE_MM_DST_AUX_ENV_INTENSITY           YCI  64
#define STSAMPLE_MM_DST_AUX_ENV_ATTACK_SPEED        YCI  65
#define STSAMPLE_MM_DST_AUX_ENV_ATTACK_SPEED_ABS    YCI  66
#define STSAMPLE_MM_DST_AUX_ENV_SUSTAIN_SPEED       YCI  67
#define STSAMPLE_MM_DST_AUX_ENV_SUSTAIN_SPEED_ABS   YCI  68
#define STSAMPLE_MM_DST_AUX_ENV_RELEASE_SPEED       YCI  69
#define STSAMPLE_MM_DST_AUX_ENV_RELEASE_SPEED_ABS   YCI  70
#define STSAMPLE_MM_DST_MOD_1_AMOUNT                YCI  71
#define STSAMPLE_MM_DST_MOD_2_AMOUNT                YCI  72
#define STSAMPLE_MM_DST_MOD_3_AMOUNT                YCI  73
#define STSAMPLE_MM_DST_MOD_4_AMOUNT                YCI  74
#define STSAMPLE_MM_DST_MOD_5_AMOUNT                YCI  75
#define STSAMPLE_MM_DST_MOD_6_AMOUNT                YCI  76
#define STSAMPLE_MM_DST_MOD_7_AMOUNT                YCI  77
#define STSAMPLE_MM_DST_MOD_8_AMOUNT                YCI  78
#define STSAMPLE_MM_DST_MOD_9_AMOUNT                YCI  79
#define STSAMPLE_MM_DST_MOD_10_AMOUNT               YCI  80
#define STSAMPLE_MM_DST_MOD_11_AMOUNT               YCI  81
#define STSAMPLE_MM_DST_MOD_12_AMOUNT               YCI  82
#define STSAMPLE_MM_DST_GLIDE_SPEED                 YCI  83
#define STSAMPLE_MM_DST_TIMESTRETCH                 YCI  84
#define STSAMPLE_MM_DST_TIMESTRETCH_BEND            YCI  85
#define STSAMPLE_MM_NUM_DST                         YCI  86

   StSampleMMEntry modmatrix[STSAMPLE_NUM_MODMATRIX_ENTRIES];

  public:
   StSample(void);
   ~StSample();

   YAC(StSample);

   sBool filterNoteOn (sSI _note, sF32 _vel, sF32 _mod);

   static sBool verify_sample_area (sUI &offset, sUI &len, const sUI range);

   StSample *getNextAltRandSample (void);

   YM YAC_Object *_getNext     (void);
   YM void        _setNext     (YAC_Object *_next);

   YM YAC_Object *_getName     (void);
   YM void        _setName     (YAC_Object *_str); // copy

   YM YAC_Object *_getWaveform (void);
   YM void        _setWaveform (YAC_Object *_wav); // set ref

   YM void        _handleShiftSampleArea (sUI _offset, sSI _len);
   YM void        _handleMoveSampleArea (sUI _offset, sUI _len, sUI _newOffset);
   YM sBool       _verifySampleAreas (void);

   YM YAC_Object *_getMutexGroup (void);
   YM void        _setMutexGroup (YAC_Object *_mtxGrp); // set ref

   YM YAC_Object *_getKeyRange (void);
   YM YAC_Object *_getVelRange (void);
   YM YAC_Object *_getModRange (void);

   YM YAC_Object *_getOrCreateKeyRange (void);
   YM YAC_Object *_getOrCreateVelRange (void);
   YM YAC_Object *_getOrCreateModRange (void);

   YM YAC_Object *_getFreqADSR (void);
   YM YAC_Object *_getVolADSR  (void);
   YM YAC_Object *_getPanADSR  (void);
   YM YAC_Object *_getAuxADSR  (void);

   YM YAC_Object *_getOrCreateFreqADSR (void);
   YM YAC_Object *_getOrCreateVolADSR  (void);
   YM YAC_Object *_getOrCreatePanADSR  (void);
   YM YAC_Object *_getOrCreateAuxADSR  (void);

   YM YAC_Object *_getFreqLFO (void);
   YM YAC_Object *_getVolLFO  (void);
   YM YAC_Object *_getPanLFO  (void);
   YM YAC_Object *_getAuxLFO  (void);

   // 0=freq, 1=vol, 2=pan, 3=aux. used by PageSample / SampleLFOForm
   YM YAC_Object *_getLFOByIndex (sUI _idx);
   YM YAC_Object *_getOrCreateLFOByIndex (sUI _idx);

   YM YAC_Object *_getOrCreateFreqLFO (void);
   YM YAC_Object *_getOrCreateVolLFO  (void);
   YM YAC_Object *_getOrCreatePanLFO  (void);
   YM YAC_Object *_getOrCreateAuxLFO  (void);

   YM void        _deleteFreqLFO (void);
   YM void        _deleteVolLFO  (void);
   YM void        _deletePanLFO  (void);
   YM void        _deleteAuxLFO  (void);

   YM void        _allocSampleLoops       (void);
   YM YAC_Object *_getOrCreateSampleLoops (void);
   YM YAC_Object *_getSampleLoops         (void);
   YM void        _freeSampleLoops        (void);
   YM sUI         _getNumSampleLoops      (void);

   YM void  _uiSetEnableSyncFirstLoopIndex (sBool _bEnabled);
   YM sBool _uiGetEnableSyncFirstLoopIndex (void);

   YM void _setFirstLoopIndex (sSI _loopIdx);
   YM sSI  _getFirstLoopIndex (void);

   YM void _setNoteOffLoopIndex (sSI _loopIdx);
   YM sSI  _getNoteOffLoopIndex (void);
   YM void _setEnableNoteOffLoopImmediately (sSI _bEnabled);
   YM sSI  _getEnableNoteOffLoopImmediately (void);

   // first sampleLoops entry
   YM sSI  _getFirstOffset (void);
   YM void _setFirstOffset (sSI _off);

   YM sSI  _getFirstLen    (void);
   YM void _setFirstLen    (sSI _len);

   // current sampleLoops entry (see firstLoopIndex)
   YM sSI  _getFirstLoopOffset (void);
   YM void _setFirstLoopOffset (sSI _off);

   YM sSI  _getFirstLoopLen    (void);
   YM void _setFirstLoopLen    (sSI _len);

   YM sSI  _getFirstLoopRep    (void);
   YM void _setFirstLoopRep    (sSI _num);

   // offset/len (no loops). can be (0; 0) when only using sampleLoops array
   YM sSI  _getOffset (void);
   YM void _setOffset (sSI _off);

   YM sSI  _getLen    (void);
   YM void _setLen    (sSI _len);

   YM void _setMaxVoices (sUI _maxVoices);
   YM sUI  _getMaxVoices (void);

   YM sF32 _getVolume (void);
   YM void _setVolume (sF32 _vol);

   YM void _setVolLFOAmt (sF32 _amt);
   YM sF32 _getVolLFOAmt (void);

   YM sF32 _getVolumeVelocityAmount (void);
   YM void _setVolumeVelocityAmount (sF32 _volVelAmount);

   YM void _setSampleOffsetRel (sF32 _pct);
   YM sF32 _getSampleOffsetRel (void);

   YM sF32 _getSampleOffsetVelocityAmount (void);
   YM void _setSampleOffsetVelocityAmount (sF32 _soffVelAmount);

   YM sSI  _getEnableInvertSampleOffsetVelocityAmount (void);
   YM void _setEnableInvertSampleOffsetVelocityAmount (sSI _bEnable);

   YM sF32 _getSampleOffsetRandAmount (void);
   YM void _setSampleOffsetRandAmount (sF32 _amt);

   YM sF32 _getPan (void);
   YM void _setPan (sF32 _pan);

   YM void _setPanEnvAmt (sF32 _amt);
   YM sF32 _getPanEnvAmt (void);

   YM void _setPanLFOAmt (sF32 _amt);
   YM sF32 _getPanLFOAmt (void);

   YM sF32 _getTranspose (void);
   YM void _setTranspose (sF32 _transpose);

  protected:
   // Called when oct/semi/cents have changed (update "transpose" field)
   void updateTranspose (void);

  public:
   YM void _setUiTransposeOct (sSI _oct);
   YM sSI  _getUiTransposeOct (void);
   YM void _setUiTransposeSemi (sSI _semi);
   YM sSI  _getUiTransposeSemi (void);
   YM void _setUiTransposeCents (sF32 _cents);
   YM sF32 _getUiTransposeCents (void);
   YM void _setTransposeAndUpdateOctSemi (sSI _key);

   YM void _setBeatFrequency (sF32 _cents);
   YM sF32 _getBeatFrequency (void);

   YM void _setFreqEnvAmt (sF32 _amt);
   YM sF32 _getFreqEnvAmt (void);

   YM void _setFreqLFOAmt (sF32 _amt);
   YM sF32 _getFreqLFOAmt (void);

   YM sF32 _getDelay (void);
   YM void _setDelay (sF32 _dly);

   YM sF32 calcVelZoneVolume (sF32 _velocity);
   YM sF32 calcKeyModZoneVolume (sF32 _absFreq, sF32 _absMod);

   YM void setEnableTimestretch (sSI _bEnabled);
   YM sSI  getEnableTimestretch (void);

   YM void setEnableTimestretchXFade (sSI _bEnabled);
   YM sSI  getEnableTimestretchXFade (void);

   YM void setTimestretch (sF32 _timestretch);
   YM sF32 getTimestretch (void);

   YM void setTimestretchGranularity (sF32 _granSec); // cyclelen
   YM sF32 getTimestretchGranularity (void);

   YM void setTimestretchGranularityAmount (sF32 _a);
   YM sF32 getTimestretchGranularityAmount (void);

   YM void setEnableStaticCyclelen (sSI _bEnabled);
   YM sSI  getEnableStaticCyclelen (void);

   YM void setEnableAbsoluteTimestretch (sSI _bEnabled);
   YM sSI  getEnableAbsoluteTimestretch (void);

   YM void setTimestretchInterpolType (sSI _type);
   YM sSI  getTimestretchInterpolType (void);

   // -1..1
   YM void setTimestretchBend (sF32 _amount);
   YM sF32 getTimestretchBend (void);

   YM void setTimestretchStartPhaseRandAmount (sF32 _amount);
   YM sF32 getTimestretchStartPhaseRandAmount (void);

   YM void        _setEnableTimedLoop (sSI _bEnable);
   YM sSI         _getEnableTimedLoop (void);
   YM void        _setEnableTimedLoopFade (sSI _bEnable);
   YM sSI         _getEnableTimedLoopFade (void);
   YM void        _setTimedLoopBase   (sF32 _base);
   YM sF32        _getTimedLoopBase   (void);
   YM void        _setEnableOneShotLoopStep (sSI _bEnable);
   YM sSI         _getEnableOneShotLoopStep (void);

   YM void _setVolumeRampStepsMillisecIn (sF32 _millisec);
   YM sF32 _getVolumeRampStepsMillisecIn (void);

   YM void _setVolumeRampStepsMillisecOut (sF32 _millisec);
   YM sF32 _getVolumeRampStepsMillisecOut (void);

   YM void _setEnableFreezeSampleOffWhenQuiet (sSI _bEnabled);
   YM sSI  _getEnableFreezeSampleOffWhenQuiet (void);

   YM void _setEnableModShiftOrig (sSI _bEnabled);
   YM sSI  _getEnableModShiftOrig (void);

   YM void _setEnableSampleOffNoteOn (sSI _bEnabled);
   YM sSI  _getEnableSampleOffNoteOn (void);

   YM void _setEnabled (sSI _bEnabled);
   YM sSI  _getEnabled (void);

   YM void _setInterpolType (sSI _interpolType);
   YM sSI  _getInterpolType (void);

   YM YAC_Object *_getOrCreateWaveguideTable (void);
   YM void        _setEnableWaveguide        (sBool _bEnabled);
   YM sBool       _getEnableWaveguide        (void);
   YM void        _setWaveguideIndex         (sSI _idx);
   YM sSI         _getWaveguideIndex         (void);

   // For editor, true=ignore ranges
   YM void _setEnableSkipRange (sSI _bEnable);

   YM void _setEnableAlt (sSI _bEnable);
   YM sSI  _getEnableAlt (void);

   YM void _setFilterType (sSI _fltType);
   YM sSI  _getFilterType (void);

   YM void _setFilterCutOff (sF32 _cutoff);
   YM sF32 _getFilterCutOff (void);

   YM void _setFilterPan (sF32 _pan);
   YM sF32 _getFilterPan (void);

   YM void _setFilterOffset (sF32 _off);
   YM sF32 _getFilterOffset (void);

   YM void _setFilterEQGain (sF32 _gain);
   YM sF32 _getFilterEQGain (void);

   YM void _setFilterResonance (sF32 _res);
   YM sF32 _getFilterResonance (void);

   YM void _setFilterAuxEnvAmount (sF32 _amount);
   YM sF32 _getFilterAuxEnvAmount (void);

   YM void _setFilterAuxEnvVelocityAmount (sF32 _amount);
   YM sF32 _getFilterAuxEnvVelocityAmount (void);

   YM void _setFilterAuxLFOAmount (sF32 _amount);
   YM sF32 _getFilterAuxLFOAmount (void);

   YM void _setFilterKeyboardAmount (sF32 _amount);
   YM sF32 _getFilterKeyboardAmount (void);

   YM void _setGlideType (sUI _type);
   YM sUI  _getGlideType (void);

   YM void _setGlideSpeedTimeUp (sF32 _millisec);
   YM sF32 _getGlideSpeedTimeUp (void);

   YM void _setGlideSpeedTimeDown (sF32 _millisec);
   YM sF32 _getGlideSpeedTimeDown (void);

   YM void _setGlideSpeedFreqUp (sF32 _semiPerSec);
   YM sF32 _getGlideSpeedFreqUp (void);

   YM void _setGlideSpeedFreqDown (sF32 _semiPerSec);
   YM sF32 _getGlideSpeedFreqDown (void);

   YM void  _setEnableGlideRelease (sBool _bEnable);
   YM sBool _getEnableGlideRelease (void);

   YM void _setGlideMaxNoteDist (sSI _dist);
   YM sSI  _getGlideMaxNoteDist (void);

   YM void  _setEnableGlideGlissando (sBool _bEnable);
   YM sBool _getEnableGlideGlissando (void);

   YM void _setGlideMinTime (sUI _millisec);
   YM sUI  _getGlideMinTime (void);

   YM void  _setEnableGlideRetrigSample (sBool _bEnable);
   YM sBool _getEnableGlideRetrigSample (void);

   YM void  _setEnableGlideRetrigEnvFreq (sBool _bEnable);
   YM sBool _getEnableGlideRetrigEnvFreq (void);

   YM void  _setEnableGlideRetrigEnvVol (sBool _bEnable);
   YM sBool _getEnableGlideRetrigEnvVol (void);

   YM void  _setEnableGlideRetrigEnvPan (sBool _bEnable);
   YM sBool _getEnableGlideRetrigEnvPan (void);

   YM void  _setEnableGlideRetrigEnvAux (sBool _bEnable);
   YM sBool _getEnableGlideRetrigEnvAux (void);

   YM void  _setEnableGlideRetrigLFOFreq (sBool _bEnable);
   YM sBool _getEnableGlideRetrigLFOFreq (void);

   YM void  _setEnableGlideRetrigLFOVol (sBool _bEnable);
   YM sBool _getEnableGlideRetrigLFOVol (void);

   YM void  _setEnableGlideRetrigLFOPan (sBool _bEnable);
   YM sBool _getEnableGlideRetrigLFOPan (void);

   YM void  _setEnableGlideRetrigLFOAux (sBool _bEnable);
   YM sBool _getEnableGlideRetrigLFOAux (void);

   YM void  _setMMEnable (sUI _idx, sBool _bEnable);
   YM sBool _getMMEnable (sUI _idx);

   YM void  _setMMOp (sUI _idx, sUI _op);
   YM sUI   _getMMOp (sUI _idx);

   YM void  _setMMSrc (sUI _idx, sUI _src);
   YM sUI   _getMMSrc (sUI _idx);

   YM void  _setMMDst (sUI _idx, sUI _dst);
   YM sUI   _getMMDst (sUI _idx);

   YM void  _setMMAmt (sUI _idx, sF32 _amt);
   YM sF32  _getMMAmt (sUI _idx);
};


#endif // __ST_SAMPLE_H__
