// ----
// ---- file   : osc_fm2s_macro_vsync.cpp
// ---- author : bsp
// ---- legal  : Distributed under terms of the MIT license (https://opensource.org/licenses/MIT)
// ----
// ----          Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// ----          associated documentation files (the "Software"), to deal in the Software without restriction, including
// ----          without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// ----          copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
// ----          the following conditions:
// ----
// ----          The above copyright notice and this permission notice shall be included in all copies or substantial
// ----          portions of the Software.
// ----
// ----          THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// ----          NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// ----          IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// ----          WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// ----          SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ----
// ---- info   : auto-generated by "Cycle"
// ----           $ g++ -Wall -Wno-unused-function -Wno-unused-variable -I../../tksampler -c osc_fm2s_macro_vsync.cpp -o osc_fm2s_macro_vsync.o
// ---- created: 21Dec2024 17:30:17
// ----
// ----
// ----

// (note) pre-define CYCLE_SKIP_UI to skip all code used only for UI/editing purposes (e.g. when compiling for standalone replay)
// #define CYCLE_SKIP_UI  defined

#include <plugin.h>

#include <stdlib.h>
#include <math.h>
#include <string.h>
#define OVERSAMPLE_FACTOR  16.0f

#define PARAM_OP12_MIX           0
#define PARAM_OP2_NOISE          1
#define PARAM_OP12_PHA           2
#define PARAM_OP12_PHA_RAND      3
#define PARAM_OP12_VSYNC         4
#define PARAM_OP12_DET           5
#define PARAM_OP2_RATIO          6
#define PARAM_OP2_LEVEL          7
#define NUM_PARAMS               8
#ifndef CYCLE_SKIP_UI
static const char *loc_param_names[NUM_PARAMS
#if defined(_MSC_VER) && 0 == NUM_PARAMS
                                   +1
#endif
                                   ] = {
#if defined(_MSC_VER) && 0 == NUM_PARAMS
                                   ""
#else
   "op12_mix",                // 0: OP12_MIX
   "op2_noise",               // 1: OP2_NOISE
   "op12_pha",                // 2: OP12_PHA
   "op12_pha_rand",           // 3: OP12_PHA_RAND
   "op12_vsync",              // 4: OP12_VSYNC
   "op12_det",                // 5: OP12_DET
   "op2_ratio",               // 6: OP2_RATIO
   "op2_level",               // 7: OP2_LEVEL

#endif
};
#endif // CYCLE_SKIP_UI
static float loc_param_resets[NUM_PARAMS
#if defined(_MSC_VER) && 0 == NUM_PARAMS
                                   +1
#endif
                              ] = {
#if defined(_MSC_VER) && 0 == NUM_PARAMS
   0.0f
#else
   0.5f,                      // 0: OP12_MIX
   0.0f,                      // 1: OP2_NOISE
   0.0f,                      // 2: OP12_PHA
   0.0f,                      // 3: OP12_PHA_RAND
   0.0f,                      // 4: OP12_VSYNC
   0.0f,                      // 5: OP12_DET
   0.5f,                      // 6: OP2_RATIO
   0.0f,                      // 7: OP2_LEVEL

#endif
};

#define MOD_OP12_MIX             0
#define MOD_OP2_NOISE            1
#define MOD_OP12_PHA             2
#define MOD_OP12_FB              3
#define MOD_OP12_VSYNC           4
#define MOD_OP12_DET             5
#define MOD_OP2_RATIO            6
#define MOD_OP2_LEVEL            7
#define NUM_MODS                 8
#ifndef CYCLE_SKIP_UI
static const char *loc_mod_names[NUM_MODS
#if defined(_MSC_VER) && 0 == NUM_MODS
   +1
#endif
                                 ] = {
#if defined(_MSC_VER) && 0 == NUM_MODS
   ""
#else
   "op12_mix",             // 0: OP12_MIX
   "op2_noise",            // 1: OP2_NOISE
   "op12_pha",             // 2: OP12_PHA
   "op12_fb",              // 3: OP12_FB
   "op12_vsync",           // 4: OP12_VSYNC
   "op12_det",             // 5: OP12_DET
   "op2_ratio",            // 6: OP2_RATIO
   "op2_level",            // 7: OP2_LEVEL

#endif
};
#endif // CYCLE_SKIP_UI

typedef struct osc_fm2s_macro_vsync_info_s {
   st_plugin_info_t base;
} osc_fm2s_macro_vsync_info_t;

typedef struct osc_fm2s_macro_vsync_shared_s {
   st_plugin_shared_t base;
   float params[NUM_PARAMS
#if defined(_MSC_VER) && 0 == NUM_PARAMS
                +1
#endif
                ];

} osc_fm2s_macro_vsync_shared_t;

typedef struct osc_fm2s_macro_vsync_voice_s {
   st_plugin_voice_t base;
   float             sample_rate;
   float             bpm;
   float             velocity;
   float             note_speed_fixed;
   float             note_speed_cur;
   float             note_speed_inc;
   float             note_cur;
   float             note_inc;
   float             mods[NUM_MODS
#if defined(_MSC_VER) && 0 == NUM_MODS
                          +1
#endif
                          ];
   float mod_op12_mix_cur;
   float mod_op12_mix_inc;
   float mod_op2_noise_cur;
   float mod_op2_noise_inc;
   float mod_op12_pha_cur;
   float mod_op12_pha_inc;
   float mod_op12_fb_cur;
   float mod_op12_fb_inc;
   float mod_op12_vsync_cur;
   float mod_op12_vsync_inc;
   float mod_op12_det_cur;
   float mod_op12_det_inc;
   float mod_op2_ratio_cur;
   float mod_op2_ratio_inc;
   float mod_op2_level_cur;
   float mod_op2_level_inc;

   float tmp1;
   float tmp2;
   int tmp3;
   int tmp4;
   short tmp5;
   unsigned short tmp6_lfsr_state;
   short tmp7_lfsr_state_signed;
   unsigned short tmp8_lfsr_state;
   short tmp9_lfsr_state_signed;
   unsigned short tmp10_lfsr_state;
   short tmp11_lfsr_state_signed;
   unsigned short tmp12_lfsr_state;
   short tmp13_lfsr_state_signed;
   float tmp14;
   float tmp15;
   int tmp16;
   int tmp17;
   float tmp18_sin_phase;
   float tmp19_win_phase;
   float tmp20;
   float tmp21;
   float tmp22;
   float tmp23;
   float tmp24;
   float tmp25_tri_phase;
   float tmp26_win_phase;
   float tmp27;
   short tmp28;
   unsigned short tmp29_lfsr_state;
   short tmp30_lfsr_state_signed;
   float tmp31_svf_lp;
   float tmp32_svf_hp;
   float tmp33_svf_bp;
   float tmp34_sin_phase;
   float tmp35_win_phase;
   float tmp36_tri_phase;
   float tmp37_win_phase;
   float var_x;
   float var_v_phrand_sin_1;
   float var_v_phrand_tri_1;
   float var_v_phrand_sin_2;
   float var_v_phrand_tri_2;
   float var_v_freq_1_sin;
   float var_v_freq_1_tri;
   float var_v_freq;
   float var_v_freq_2_sin;
   float var_v_freq_2_tri;
   float var_v_level_2;
   float var_v_osc_2_raw;
   float var_v_osc_2;

   float macrovar_osc_mix_sin1;
   float macrovar_osc_mix_tri1;
   float macrovar_osc_mix_sin2;
   float macrovar_osc_mix_tri2;
   float macrovar_osc2_noise_cutoff;
   float macrovar_osc2_noise_level;
   float macrovar_osc_pha_sin1;
   float macrovar_osc_pha_tri1;
   float macrovar_osc_pha_sin2;
   float macrovar_osc_pha_tri2;
   float macrovar_osc_pha_rand_sin1;
   float macrovar_osc_pha_rand_tri1;
   float macrovar_osc_pha_rand_sin2;
   float macrovar_osc_pha_rand_tri2;
   float macrovar_osc_vsync_sin1;
   float macrovar_osc_vsync_tri1;
   float macrovar_osc_vsync_sin2;
   float macrovar_osc_vsync_tri2;
   float macrovar_osc_det_sin1;
   float macrovar_osc_det_tri1;
   float macrovar_osc_det_sin2;
   float macrovar_osc_det_tri2;
   float sr_factor;

} osc_fm2s_macro_vsync_voice_t;

static const float macrovalues_osc_mix[(16 * 4)/*64*/] = {
   /*    0 */ 0.0f, 0.0f, 0.0f, 0.0f, 
   /*    1 */ 1.0f, 0.0f, 0.0f, 0.0f, 
   /*    2 */ 0.0f, 1.0f, 0.0f, 0.0f, 
   /*    3 */ 1.0f, 1.0f, 0.0f, 0.0f, 
   /*    4 */ 0.0f, 0.0f, 1.0f, 0.0f, 
   /*    5 */ 1.0f, 0.0f, 1.0f, 0.0f, 
   /*    6 */ 0.0f, 1.0f, 1.0f, 0.0f, 
   /*    7 */ 1.0f, 1.0f, 1.0f, 0.0f, 
   /*    8 */ 0.0f, 0.0f, 0.0f, 1.0f, 
   /*    9 */ 1.0f, 0.0f, 0.0f, 1.0f, 
   /*   10 */ 0.0f, 1.0f, 0.0f, 1.0f, 
   /*   11 */ 1.0f, 1.0f, 0.0f, 1.0f, 
   /*   12 */ 0.0f, 0.0f, 1.0f, 1.0f, 
   /*   13 */ 1.0f, 0.0f, 1.0f, 1.0f, 
   /*   14 */ 0.0f, 1.0f, 1.0f, 1.0f, 
   /*   15 */ 1.0f, 1.0f, 1.0f, 1.0f, 
};

static const float macrovalues_osc2_noise[(9 * 2)/*18*/] = {
   /*    0 */ 0.0f, 0.0f, 
   /*    1 */ 1.0f, 0.0f, 
   /*    2 */ 0.5f, 0.0f, 
   /*    3 */ 0.0f, 1.0f, 
   /*    4 */ 1.0f, 1.0f, 
   /*    5 */ 0.5f, 1.0f, 
   /*    6 */ 0.0f, 0.5f, 
   /*    7 */ 1.0f, 0.5f, 
   /*    8 */ 0.5f, 0.5f, 
};

static const float macrovalues_osc_pha[(256 * 4)/*1024*/] = {
   /*    0 */ 0.0f, 0.0f, 0.0f, 0.0f, 
   /*    1 */ 0.75f, 0.0f, 0.0f, 0.0f, 
   /*    2 */ 0.25f, 0.0f, 0.0f, 0.0f, 
   /*    3 */ 0.5f, 0.0f, 0.0f, 0.0f, 
   /*    4 */ 0.0f, 0.75f, 0.0f, 0.0f, 
   /*    5 */ 0.75f, 0.75f, 0.0f, 0.0f, 
   /*    6 */ 0.25f, 0.75f, 0.0f, 0.0f, 
   /*    7 */ 0.5f, 0.75f, 0.0f, 0.0f, 
   /*    8 */ 0.0f, 0.25f, 0.0f, 0.0f, 
   /*    9 */ 0.75f, 0.25f, 0.0f, 0.0f, 
   /*   10 */ 0.25f, 0.25f, 0.0f, 0.0f, 
   /*   11 */ 0.5f, 0.25f, 0.0f, 0.0f, 
   /*   12 */ 0.0f, 0.5f, 0.0f, 0.0f, 
   /*   13 */ 0.75f, 0.5f, 0.0f, 0.0f, 
   /*   14 */ 0.25f, 0.5f, 0.0f, 0.0f, 
   /*   15 */ 0.5f, 0.5f, 0.0f, 0.0f, 
   /*   16 */ 0.0f, 0.0f, 0.75f, 0.0f, 
   /*   17 */ 0.75f, 0.0f, 0.75f, 0.0f, 
   /*   18 */ 0.25f, 0.0f, 0.75f, 0.0f, 
   /*   19 */ 0.5f, 0.0f, 0.75f, 0.0f, 
   /*   20 */ 0.0f, 0.75f, 0.75f, 0.0f, 
   /*   21 */ 0.75f, 0.75f, 0.75f, 0.0f, 
   /*   22 */ 0.25f, 0.75f, 0.75f, 0.0f, 
   /*   23 */ 0.5f, 0.75f, 0.75f, 0.0f, 
   /*   24 */ 0.0f, 0.25f, 0.75f, 0.0f, 
   /*   25 */ 0.75f, 0.25f, 0.75f, 0.0f, 
   /*   26 */ 0.25f, 0.25f, 0.75f, 0.0f, 
   /*   27 */ 0.5f, 0.25f, 0.75f, 0.0f, 
   /*   28 */ 0.0f, 0.5f, 0.75f, 0.0f, 
   /*   29 */ 0.75f, 0.5f, 0.75f, 0.0f, 
   /*   30 */ 0.25f, 0.5f, 0.75f, 0.0f, 
   /*   31 */ 0.5f, 0.5f, 0.75f, 0.0f, 
   /*   32 */ 0.0f, 0.0f, 0.25f, 0.0f, 
   /*   33 */ 0.75f, 0.0f, 0.25f, 0.0f, 
   /*   34 */ 0.25f, 0.0f, 0.25f, 0.0f, 
   /*   35 */ 0.5f, 0.0f, 0.25f, 0.0f, 
   /*   36 */ 0.0f, 0.75f, 0.25f, 0.0f, 
   /*   37 */ 0.75f, 0.75f, 0.25f, 0.0f, 
   /*   38 */ 0.25f, 0.75f, 0.25f, 0.0f, 
   /*   39 */ 0.5f, 0.75f, 0.25f, 0.0f, 
   /*   40 */ 0.0f, 0.25f, 0.25f, 0.0f, 
   /*   41 */ 0.75f, 0.25f, 0.25f, 0.0f, 
   /*   42 */ 0.25f, 0.25f, 0.25f, 0.0f, 
   /*   43 */ 0.5f, 0.25f, 0.25f, 0.0f, 
   /*   44 */ 0.0f, 0.5f, 0.25f, 0.0f, 
   /*   45 */ 0.75f, 0.5f, 0.25f, 0.0f, 
   /*   46 */ 0.25f, 0.5f, 0.25f, 0.0f, 
   /*   47 */ 0.5f, 0.5f, 0.25f, 0.0f, 
   /*   48 */ 0.0f, 0.0f, 0.5f, 0.0f, 
   /*   49 */ 0.75f, 0.0f, 0.5f, 0.0f, 
   /*   50 */ 0.25f, 0.0f, 0.5f, 0.0f, 
   /*   51 */ 0.5f, 0.0f, 0.5f, 0.0f, 
   /*   52 */ 0.0f, 0.75f, 0.5f, 0.0f, 
   /*   53 */ 0.75f, 0.75f, 0.5f, 0.0f, 
   /*   54 */ 0.25f, 0.75f, 0.5f, 0.0f, 
   /*   55 */ 0.5f, 0.75f, 0.5f, 0.0f, 
   /*   56 */ 0.0f, 0.25f, 0.5f, 0.0f, 
   /*   57 */ 0.75f, 0.25f, 0.5f, 0.0f, 
   /*   58 */ 0.25f, 0.25f, 0.5f, 0.0f, 
   /*   59 */ 0.5f, 0.25f, 0.5f, 0.0f, 
   /*   60 */ 0.0f, 0.5f, 0.5f, 0.0f, 
   /*   61 */ 0.75f, 0.5f, 0.5f, 0.0f, 
   /*   62 */ 0.25f, 0.5f, 0.5f, 0.0f, 
   /*   63 */ 0.5f, 0.5f, 0.5f, 0.0f, 
   /*   64 */ 0.0f, 0.0f, 0.0f, 0.75f, 
   /*   65 */ 0.75f, 0.0f, 0.0f, 0.75f, 
   /*   66 */ 0.25f, 0.0f, 0.0f, 0.75f, 
   /*   67 */ 0.5f, 0.0f, 0.0f, 0.75f, 
   /*   68 */ 0.0f, 0.75f, 0.0f, 0.75f, 
   /*   69 */ 0.75f, 0.75f, 0.0f, 0.75f, 
   /*   70 */ 0.25f, 0.75f, 0.0f, 0.75f, 
   /*   71 */ 0.5f, 0.75f, 0.0f, 0.75f, 
   /*   72 */ 0.0f, 0.25f, 0.0f, 0.75f, 
   /*   73 */ 0.75f, 0.25f, 0.0f, 0.75f, 
   /*   74 */ 0.25f, 0.25f, 0.0f, 0.75f, 
   /*   75 */ 0.5f, 0.25f, 0.0f, 0.75f, 
   /*   76 */ 0.0f, 0.5f, 0.0f, 0.75f, 
   /*   77 */ 0.75f, 0.5f, 0.0f, 0.75f, 
   /*   78 */ 0.25f, 0.5f, 0.0f, 0.75f, 
   /*   79 */ 0.5f, 0.5f, 0.0f, 0.75f, 
   /*   80 */ 0.0f, 0.0f, 0.75f, 0.75f, 
   /*   81 */ 0.75f, 0.0f, 0.75f, 0.75f, 
   /*   82 */ 0.25f, 0.0f, 0.75f, 0.75f, 
   /*   83 */ 0.5f, 0.0f, 0.75f, 0.75f, 
   /*   84 */ 0.0f, 0.75f, 0.75f, 0.75f, 
   /*   85 */ 0.75f, 0.75f, 0.75f, 0.75f, 
   /*   86 */ 0.25f, 0.75f, 0.75f, 0.75f, 
   /*   87 */ 0.5f, 0.75f, 0.75f, 0.75f, 
   /*   88 */ 0.0f, 0.25f, 0.75f, 0.75f, 
   /*   89 */ 0.75f, 0.25f, 0.75f, 0.75f, 
   /*   90 */ 0.25f, 0.25f, 0.75f, 0.75f, 
   /*   91 */ 0.5f, 0.25f, 0.75f, 0.75f, 
   /*   92 */ 0.0f, 0.5f, 0.75f, 0.75f, 
   /*   93 */ 0.75f, 0.5f, 0.75f, 0.75f, 
   /*   94 */ 0.25f, 0.5f, 0.75f, 0.75f, 
   /*   95 */ 0.5f, 0.5f, 0.75f, 0.75f, 
   /*   96 */ 0.0f, 0.0f, 0.25f, 0.75f, 
   /*   97 */ 0.75f, 0.0f, 0.25f, 0.75f, 
   /*   98 */ 0.25f, 0.0f, 0.25f, 0.75f, 
   /*   99 */ 0.5f, 0.0f, 0.25f, 0.75f, 
   /*  100 */ 0.0f, 0.75f, 0.25f, 0.75f, 
   /*  101 */ 0.75f, 0.75f, 0.25f, 0.75f, 
   /*  102 */ 0.25f, 0.75f, 0.25f, 0.75f, 
   /*  103 */ 0.5f, 0.75f, 0.25f, 0.75f, 
   /*  104 */ 0.0f, 0.25f, 0.25f, 0.75f, 
   /*  105 */ 0.75f, 0.25f, 0.25f, 0.75f, 
   /*  106 */ 0.25f, 0.25f, 0.25f, 0.75f, 
   /*  107 */ 0.5f, 0.25f, 0.25f, 0.75f, 
   /*  108 */ 0.0f, 0.5f, 0.25f, 0.75f, 
   /*  109 */ 0.75f, 0.5f, 0.25f, 0.75f, 
   /*  110 */ 0.25f, 0.5f, 0.25f, 0.75f, 
   /*  111 */ 0.5f, 0.5f, 0.25f, 0.75f, 
   /*  112 */ 0.0f, 0.0f, 0.5f, 0.75f, 
   /*  113 */ 0.75f, 0.0f, 0.5f, 0.75f, 
   /*  114 */ 0.25f, 0.0f, 0.5f, 0.75f, 
   /*  115 */ 0.5f, 0.0f, 0.5f, 0.75f, 
   /*  116 */ 0.0f, 0.75f, 0.5f, 0.75f, 
   /*  117 */ 0.75f, 0.75f, 0.5f, 0.75f, 
   /*  118 */ 0.25f, 0.75f, 0.5f, 0.75f, 
   /*  119 */ 0.5f, 0.75f, 0.5f, 0.75f, 
   /*  120 */ 0.0f, 0.25f, 0.5f, 0.75f, 
   /*  121 */ 0.75f, 0.25f, 0.5f, 0.75f, 
   /*  122 */ 0.25f, 0.25f, 0.5f, 0.75f, 
   /*  123 */ 0.5f, 0.25f, 0.5f, 0.75f, 
   /*  124 */ 0.0f, 0.5f, 0.5f, 0.75f, 
   /*  125 */ 0.75f, 0.5f, 0.5f, 0.75f, 
   /*  126 */ 0.25f, 0.5f, 0.5f, 0.75f, 
   /*  127 */ 0.5f, 0.5f, 0.5f, 0.75f, 
   /*  128 */ 0.0f, 0.0f, 0.0f, 0.25f, 
   /*  129 */ 0.75f, 0.0f, 0.0f, 0.25f, 
   /*  130 */ 0.25f, 0.0f, 0.0f, 0.25f, 
   /*  131 */ 0.5f, 0.0f, 0.0f, 0.25f, 
   /*  132 */ 0.0f, 0.75f, 0.0f, 0.25f, 
   /*  133 */ 0.75f, 0.75f, 0.0f, 0.25f, 
   /*  134 */ 0.25f, 0.75f, 0.0f, 0.25f, 
   /*  135 */ 0.5f, 0.75f, 0.0f, 0.25f, 
   /*  136 */ 0.0f, 0.25f, 0.0f, 0.25f, 
   /*  137 */ 0.75f, 0.25f, 0.0f, 0.25f, 
   /*  138 */ 0.25f, 0.25f, 0.0f, 0.25f, 
   /*  139 */ 0.5f, 0.25f, 0.0f, 0.25f, 
   /*  140 */ 0.0f, 0.5f, 0.0f, 0.25f, 
   /*  141 */ 0.75f, 0.5f, 0.0f, 0.25f, 
   /*  142 */ 0.25f, 0.5f, 0.0f, 0.25f, 
   /*  143 */ 0.5f, 0.5f, 0.0f, 0.25f, 
   /*  144 */ 0.0f, 0.0f, 0.75f, 0.25f, 
   /*  145 */ 0.75f, 0.0f, 0.75f, 0.25f, 
   /*  146 */ 0.25f, 0.0f, 0.75f, 0.25f, 
   /*  147 */ 0.5f, 0.0f, 0.75f, 0.25f, 
   /*  148 */ 0.0f, 0.75f, 0.75f, 0.25f, 
   /*  149 */ 0.75f, 0.75f, 0.75f, 0.25f, 
   /*  150 */ 0.25f, 0.75f, 0.75f, 0.25f, 
   /*  151 */ 0.5f, 0.75f, 0.75f, 0.25f, 
   /*  152 */ 0.0f, 0.25f, 0.75f, 0.25f, 
   /*  153 */ 0.75f, 0.25f, 0.75f, 0.25f, 
   /*  154 */ 0.25f, 0.25f, 0.75f, 0.25f, 
   /*  155 */ 0.5f, 0.25f, 0.75f, 0.25f, 
   /*  156 */ 0.0f, 0.5f, 0.75f, 0.25f, 
   /*  157 */ 0.75f, 0.5f, 0.75f, 0.25f, 
   /*  158 */ 0.25f, 0.5f, 0.75f, 0.25f, 
   /*  159 */ 0.5f, 0.5f, 0.75f, 0.25f, 
   /*  160 */ 0.0f, 0.0f, 0.25f, 0.25f, 
   /*  161 */ 0.75f, 0.0f, 0.25f, 0.25f, 
   /*  162 */ 0.25f, 0.0f, 0.25f, 0.25f, 
   /*  163 */ 0.5f, 0.0f, 0.25f, 0.25f, 
   /*  164 */ 0.0f, 0.75f, 0.25f, 0.25f, 
   /*  165 */ 0.75f, 0.75f, 0.25f, 0.25f, 
   /*  166 */ 0.25f, 0.75f, 0.25f, 0.25f, 
   /*  167 */ 0.5f, 0.75f, 0.25f, 0.25f, 
   /*  168 */ 0.0f, 0.25f, 0.25f, 0.25f, 
   /*  169 */ 0.75f, 0.25f, 0.25f, 0.25f, 
   /*  170 */ 0.25f, 0.25f, 0.25f, 0.25f, 
   /*  171 */ 0.5f, 0.25f, 0.25f, 0.25f, 
   /*  172 */ 0.0f, 0.5f, 0.25f, 0.25f, 
   /*  173 */ 0.75f, 0.5f, 0.25f, 0.25f, 
   /*  174 */ 0.25f, 0.5f, 0.25f, 0.25f, 
   /*  175 */ 0.5f, 0.5f, 0.25f, 0.25f, 
   /*  176 */ 0.0f, 0.0f, 0.5f, 0.25f, 
   /*  177 */ 0.75f, 0.0f, 0.5f, 0.25f, 
   /*  178 */ 0.25f, 0.0f, 0.5f, 0.25f, 
   /*  179 */ 0.5f, 0.0f, 0.5f, 0.25f, 
   /*  180 */ 0.0f, 0.75f, 0.5f, 0.25f, 
   /*  181 */ 0.75f, 0.75f, 0.5f, 0.25f, 
   /*  182 */ 0.25f, 0.75f, 0.5f, 0.25f, 
   /*  183 */ 0.5f, 0.75f, 0.5f, 0.25f, 
   /*  184 */ 0.0f, 0.25f, 0.5f, 0.25f, 
   /*  185 */ 0.75f, 0.25f, 0.5f, 0.25f, 
   /*  186 */ 0.25f, 0.25f, 0.5f, 0.25f, 
   /*  187 */ 0.5f, 0.25f, 0.5f, 0.25f, 
   /*  188 */ 0.0f, 0.5f, 0.5f, 0.25f, 
   /*  189 */ 0.75f, 0.5f, 0.5f, 0.25f, 
   /*  190 */ 0.25f, 0.5f, 0.5f, 0.25f, 
   /*  191 */ 0.5f, 0.5f, 0.5f, 0.25f, 
   /*  192 */ 0.0f, 0.0f, 0.0f, 0.5f, 
   /*  193 */ 0.75f, 0.0f, 0.0f, 0.5f, 
   /*  194 */ 0.25f, 0.0f, 0.0f, 0.5f, 
   /*  195 */ 0.5f, 0.0f, 0.0f, 0.5f, 
   /*  196 */ 0.0f, 0.75f, 0.0f, 0.5f, 
   /*  197 */ 0.75f, 0.75f, 0.0f, 0.5f, 
   /*  198 */ 0.25f, 0.75f, 0.0f, 0.5f, 
   /*  199 */ 0.5f, 0.75f, 0.0f, 0.5f, 
   /*  200 */ 0.0f, 0.25f, 0.0f, 0.5f, 
   /*  201 */ 0.75f, 0.25f, 0.0f, 0.5f, 
   /*  202 */ 0.25f, 0.25f, 0.0f, 0.5f, 
   /*  203 */ 0.5f, 0.25f, 0.0f, 0.5f, 
   /*  204 */ 0.0f, 0.5f, 0.0f, 0.5f, 
   /*  205 */ 0.75f, 0.5f, 0.0f, 0.5f, 
   /*  206 */ 0.25f, 0.5f, 0.0f, 0.5f, 
   /*  207 */ 0.5f, 0.5f, 0.0f, 0.5f, 
   /*  208 */ 0.0f, 0.0f, 0.75f, 0.5f, 
   /*  209 */ 0.75f, 0.0f, 0.75f, 0.5f, 
   /*  210 */ 0.25f, 0.0f, 0.75f, 0.5f, 
   /*  211 */ 0.5f, 0.0f, 0.75f, 0.5f, 
   /*  212 */ 0.0f, 0.75f, 0.75f, 0.5f, 
   /*  213 */ 0.75f, 0.75f, 0.75f, 0.5f, 
   /*  214 */ 0.25f, 0.75f, 0.75f, 0.5f, 
   /*  215 */ 0.5f, 0.75f, 0.75f, 0.5f, 
   /*  216 */ 0.0f, 0.25f, 0.75f, 0.5f, 
   /*  217 */ 0.75f, 0.25f, 0.75f, 0.5f, 
   /*  218 */ 0.25f, 0.25f, 0.75f, 0.5f, 
   /*  219 */ 0.5f, 0.25f, 0.75f, 0.5f, 
   /*  220 */ 0.0f, 0.5f, 0.75f, 0.5f, 
   /*  221 */ 0.75f, 0.5f, 0.75f, 0.5f, 
   /*  222 */ 0.25f, 0.5f, 0.75f, 0.5f, 
   /*  223 */ 0.5f, 0.5f, 0.75f, 0.5f, 
   /*  224 */ 0.0f, 0.0f, 0.25f, 0.5f, 
   /*  225 */ 0.75f, 0.0f, 0.25f, 0.5f, 
   /*  226 */ 0.25f, 0.0f, 0.25f, 0.5f, 
   /*  227 */ 0.5f, 0.0f, 0.25f, 0.5f, 
   /*  228 */ 0.0f, 0.75f, 0.25f, 0.5f, 
   /*  229 */ 0.75f, 0.75f, 0.25f, 0.5f, 
   /*  230 */ 0.25f, 0.75f, 0.25f, 0.5f, 
   /*  231 */ 0.5f, 0.75f, 0.25f, 0.5f, 
   /*  232 */ 0.0f, 0.25f, 0.25f, 0.5f, 
   /*  233 */ 0.75f, 0.25f, 0.25f, 0.5f, 
   /*  234 */ 0.25f, 0.25f, 0.25f, 0.5f, 
   /*  235 */ 0.5f, 0.25f, 0.25f, 0.5f, 
   /*  236 */ 0.0f, 0.5f, 0.25f, 0.5f, 
   /*  237 */ 0.75f, 0.5f, 0.25f, 0.5f, 
   /*  238 */ 0.25f, 0.5f, 0.25f, 0.5f, 
   /*  239 */ 0.5f, 0.5f, 0.25f, 0.5f, 
   /*  240 */ 0.0f, 0.0f, 0.5f, 0.5f, 
   /*  241 */ 0.75f, 0.0f, 0.5f, 0.5f, 
   /*  242 */ 0.25f, 0.0f, 0.5f, 0.5f, 
   /*  243 */ 0.5f, 0.0f, 0.5f, 0.5f, 
   /*  244 */ 0.0f, 0.75f, 0.5f, 0.5f, 
   /*  245 */ 0.75f, 0.75f, 0.5f, 0.5f, 
   /*  246 */ 0.25f, 0.75f, 0.5f, 0.5f, 
   /*  247 */ 0.5f, 0.75f, 0.5f, 0.5f, 
   /*  248 */ 0.0f, 0.25f, 0.5f, 0.5f, 
   /*  249 */ 0.75f, 0.25f, 0.5f, 0.5f, 
   /*  250 */ 0.25f, 0.25f, 0.5f, 0.5f, 
   /*  251 */ 0.5f, 0.25f, 0.5f, 0.5f, 
   /*  252 */ 0.0f, 0.5f, 0.5f, 0.5f, 
   /*  253 */ 0.75f, 0.5f, 0.5f, 0.5f, 
   /*  254 */ 0.25f, 0.5f, 0.5f, 0.5f, 
   /*  255 */ 0.5f, 0.5f, 0.5f, 0.5f, 
};

static const float macrovalues_osc_pha_rand[(16 * 4)/*64*/] = {
   /*    0 */ 0.0f, 0.0f, 0.0f, 0.0f, 
   /*    1 */ 1.0f, 0.0f, 0.0f, 0.0f, 
   /*    2 */ 0.0f, 1.0f, 0.0f, 0.0f, 
   /*    3 */ 1.0f, 1.0f, 0.0f, 0.0f, 
   /*    4 */ 0.0f, 0.0f, 1.0f, 0.0f, 
   /*    5 */ 1.0f, 0.0f, 1.0f, 0.0f, 
   /*    6 */ 0.0f, 1.0f, 1.0f, 0.0f, 
   /*    7 */ 1.0f, 1.0f, 1.0f, 0.0f, 
   /*    8 */ 0.0f, 0.0f, 0.0f, 1.0f, 
   /*    9 */ 1.0f, 0.0f, 0.0f, 1.0f, 
   /*   10 */ 0.0f, 1.0f, 0.0f, 1.0f, 
   /*   11 */ 1.0f, 1.0f, 0.0f, 1.0f, 
   /*   12 */ 0.0f, 0.0f, 1.0f, 1.0f, 
   /*   13 */ 1.0f, 0.0f, 1.0f, 1.0f, 
   /*   14 */ 0.0f, 1.0f, 1.0f, 1.0f, 
   /*   15 */ 1.0f, 1.0f, 1.0f, 1.0f, 
};

static const float macrovalues_osc_vsync[(16 * 4)/*64*/] = {
   /*    0 */ 1.0f, 1.0f, 1.0f, 1.0f, 
   /*    1 */ 16.0f, 1.0f, 1.0f, 1.0f, 
   /*    2 */ 1.0f, 16.0f, 1.0f, 1.0f, 
   /*    3 */ 16.0f, 16.0f, 1.0f, 1.0f, 
   /*    4 */ 1.0f, 1.0f, 16.0f, 1.0f, 
   /*    5 */ 16.0f, 1.0f, 16.0f, 1.0f, 
   /*    6 */ 1.0f, 16.0f, 16.0f, 1.0f, 
   /*    7 */ 16.0f, 16.0f, 16.0f, 1.0f, 
   /*    8 */ 1.0f, 1.0f, 1.0f, 16.0f, 
   /*    9 */ 16.0f, 1.0f, 1.0f, 16.0f, 
   /*   10 */ 1.0f, 16.0f, 1.0f, 16.0f, 
   /*   11 */ 16.0f, 16.0f, 1.0f, 16.0f, 
   /*   12 */ 1.0f, 1.0f, 16.0f, 16.0f, 
   /*   13 */ 16.0f, 1.0f, 16.0f, 16.0f, 
   /*   14 */ 1.0f, 16.0f, 16.0f, 16.0f, 
   /*   15 */ 16.0f, 16.0f, 16.0f, 16.0f, 
};

static const float macrovalues_osc_det[(81 * 4)/*324*/] = {
   /*    0 */ 0.0f, 0.0f, 0.0f, 0.0f, 
   /*    1 */ -0.01f, 0.0f, 0.0f, 0.0f, 
   /*    2 */ 0.01f, 0.0f, 0.0f, 0.0f, 
   /*    3 */ 0.0f, -0.01f, 0.0f, 0.0f, 
   /*    4 */ -0.01f, -0.01f, 0.0f, 0.0f, 
   /*    5 */ 0.01f, -0.01f, 0.0f, 0.0f, 
   /*    6 */ 0.0f, 0.01f, 0.0f, 0.0f, 
   /*    7 */ -0.01f, 0.01f, 0.0f, 0.0f, 
   /*    8 */ 0.01f, 0.01f, 0.0f, 0.0f, 
   /*    9 */ 0.0f, 0.0f, -0.01f, 0.0f, 
   /*   10 */ -0.01f, 0.0f, -0.01f, 0.0f, 
   /*   11 */ 0.01f, 0.0f, -0.01f, 0.0f, 
   /*   12 */ 0.0f, -0.01f, -0.01f, 0.0f, 
   /*   13 */ -0.01f, -0.01f, -0.01f, 0.0f, 
   /*   14 */ 0.01f, -0.01f, -0.01f, 0.0f, 
   /*   15 */ 0.0f, 0.01f, -0.01f, 0.0f, 
   /*   16 */ -0.01f, 0.01f, -0.01f, 0.0f, 
   /*   17 */ 0.01f, 0.01f, -0.01f, 0.0f, 
   /*   18 */ 0.0f, 0.0f, 0.01f, 0.0f, 
   /*   19 */ -0.01f, 0.0f, 0.01f, 0.0f, 
   /*   20 */ 0.01f, 0.0f, 0.01f, 0.0f, 
   /*   21 */ 0.0f, -0.01f, 0.01f, 0.0f, 
   /*   22 */ -0.01f, -0.01f, 0.01f, 0.0f, 
   /*   23 */ 0.01f, -0.01f, 0.01f, 0.0f, 
   /*   24 */ 0.0f, 0.01f, 0.01f, 0.0f, 
   /*   25 */ -0.01f, 0.01f, 0.01f, 0.0f, 
   /*   26 */ 0.01f, 0.01f, 0.01f, 0.0f, 
   /*   27 */ 0.0f, 0.0f, 0.0f, -0.01f, 
   /*   28 */ -0.01f, 0.0f, 0.0f, -0.01f, 
   /*   29 */ 0.01f, 0.0f, 0.0f, -0.01f, 
   /*   30 */ 0.0f, -0.01f, 0.0f, -0.01f, 
   /*   31 */ -0.01f, -0.01f, 0.0f, -0.01f, 
   /*   32 */ 0.01f, -0.01f, 0.0f, -0.01f, 
   /*   33 */ 0.0f, 0.01f, 0.0f, -0.01f, 
   /*   34 */ -0.01f, 0.01f, 0.0f, -0.01f, 
   /*   35 */ 0.01f, 0.01f, 0.0f, -0.01f, 
   /*   36 */ 0.0f, 0.0f, -0.01f, -0.01f, 
   /*   37 */ -0.01f, 0.0f, -0.01f, -0.01f, 
   /*   38 */ 0.01f, 0.0f, -0.01f, -0.01f, 
   /*   39 */ 0.0f, -0.01f, -0.01f, -0.01f, 
   /*   40 */ -0.01f, -0.01f, -0.01f, -0.01f, 
   /*   41 */ 0.01f, -0.01f, -0.01f, -0.01f, 
   /*   42 */ 0.0f, 0.01f, -0.01f, -0.01f, 
   /*   43 */ -0.01f, 0.01f, -0.01f, -0.01f, 
   /*   44 */ 0.01f, 0.01f, -0.01f, -0.01f, 
   /*   45 */ 0.0f, 0.0f, 0.01f, -0.01f, 
   /*   46 */ -0.01f, 0.0f, 0.01f, -0.01f, 
   /*   47 */ 0.01f, 0.0f, 0.01f, -0.01f, 
   /*   48 */ 0.0f, -0.01f, 0.01f, -0.01f, 
   /*   49 */ -0.01f, -0.01f, 0.01f, -0.01f, 
   /*   50 */ 0.01f, -0.01f, 0.01f, -0.01f, 
   /*   51 */ 0.0f, 0.01f, 0.01f, -0.01f, 
   /*   52 */ -0.01f, 0.01f, 0.01f, -0.01f, 
   /*   53 */ 0.01f, 0.01f, 0.01f, -0.01f, 
   /*   54 */ 0.0f, 0.0f, 0.0f, 0.01f, 
   /*   55 */ -0.01f, 0.0f, 0.0f, 0.01f, 
   /*   56 */ 0.01f, 0.0f, 0.0f, 0.01f, 
   /*   57 */ 0.0f, -0.01f, 0.0f, 0.01f, 
   /*   58 */ -0.01f, -0.01f, 0.0f, 0.01f, 
   /*   59 */ 0.01f, -0.01f, 0.0f, 0.01f, 
   /*   60 */ 0.0f, 0.01f, 0.0f, 0.01f, 
   /*   61 */ -0.01f, 0.01f, 0.0f, 0.01f, 
   /*   62 */ 0.01f, 0.01f, 0.0f, 0.01f, 
   /*   63 */ 0.0f, 0.0f, -0.01f, 0.01f, 
   /*   64 */ -0.01f, 0.0f, -0.01f, 0.01f, 
   /*   65 */ 0.01f, 0.0f, -0.01f, 0.01f, 
   /*   66 */ 0.0f, -0.01f, -0.01f, 0.01f, 
   /*   67 */ -0.01f, -0.01f, -0.01f, 0.01f, 
   /*   68 */ 0.01f, -0.01f, -0.01f, 0.01f, 
   /*   69 */ 0.0f, 0.01f, -0.01f, 0.01f, 
   /*   70 */ -0.01f, 0.01f, -0.01f, 0.01f, 
   /*   71 */ 0.01f, 0.01f, -0.01f, 0.01f, 
   /*   72 */ 0.0f, 0.0f, 0.01f, 0.01f, 
   /*   73 */ -0.01f, 0.0f, 0.01f, 0.01f, 
   /*   74 */ 0.01f, 0.0f, 0.01f, 0.01f, 
   /*   75 */ 0.0f, -0.01f, 0.01f, 0.01f, 
   /*   76 */ -0.01f, -0.01f, 0.01f, 0.01f, 
   /*   77 */ 0.01f, -0.01f, 0.01f, 0.01f, 
   /*   78 */ 0.0f, 0.01f, 0.01f, 0.01f, 
   /*   79 */ -0.01f, 0.01f, 0.01f, 0.01f, 
   /*   80 */ 0.01f, 0.01f, 0.01f, 0.01f, 
};

#define loop(X)  for(unsigned int i = 0u; i < (X); i++)
#define clamp(a,b,c) (((a)<(b))?(b):(((a)>(c))?(c):(a)))

static inline float mathLerpf(float _a, float _b, float _t) { return _a + (_b - _a) * _t; }
static inline float mathClampf(float a, float b, float c) { return (((a)<(b))?(b):(((a)>(c))?(c):(a))); }
static inline float mathMinf(float a, float b) { return (a<b)?a:b; }
static inline float mathMaxf(float a, float b) { return (a>b)?a:b; }
static inline float mathAbsMaxf(float _x, float _y) { return ( ( (_x<0.0f)?-_x:_x)>((_y<0.0f)?-_y:_y)?_x:_y ); }
static inline float mathAbsMinf(float _x, float _y) { return ( ((_x<0.0f)?-_x:_x)<((_y<0.0f)?-_y:_y)?_x:_y ); }
static inline float frac(float _x) { return _x - ((int)_x); }

static inline float winLinear(const float *_s, float _index) {
   int idx = (int)_index;
   float r = _index - (float)idx;
   return mathLerpf(_s[idx], _s[idx+1], r);
}

static float ffrac_s(float _f) { int i; if(_f >= 0.0f) { i = (int)_f; return _f - (float)i; } else { i = (int)-_f; return 1.0f - (-_f - (float)i); } }

#define USE_CYCLE_SINE_TBL  defined
static float cycle_sine_tbl_f[16384];

static float loc_bipolar_to_scale(const float _t, const float _div, const float _mul) {
   // t (-1..1) => /_div .. *_mul
   
   float s;

   if(_t < 0.0f)
   {
      s = (1.0f / _div);
      s = 1.0f + (s - 1.0f) * -_t;
      if(s < 0.0f)
         s = 0.0f;
   }
   else
   {
      s = _mul;
      s = 1.0f + (s - 1.0f) * _t;
   }
   
   return s;
}

static void loc_init(st_plugin_voice_t *_voice);
static void loc_prepare(st_plugin_voice_t *_voice);

void loc_init(st_plugin_voice_t *_voice) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);

   float out = 0.0f;
   (void)out;
   // -------- lane "init" modIdx=0 modString=mac
   
   // -- mod="mac" dstVar=out
   
   // ---- mod="mac" input "pos" seq 1/1
   
   // -- mod="$p_op12_pha_rand" dstVar=voice->tmp1/*mac_pos*/
   voice->tmp1/*mac_pos*/ = shared->params[PARAM_OP12_PHA_RAND];
   voice->tmp1/*mac_pos*/ = ffrac_s(voice->tmp1/*mac_pos*/) * 16;
   voice->tmp2/*mac_amt*/ = ffrac_s(voice->tmp1/*mac_pos*/);
   voice->tmp3/*idx*/ = int(voice->tmp1/*mac_pos*/) * 4;
   voice->tmp4/*mac_idx_n*/ = (voice->tmp3/*idx*/ + 4) & 63;
   voice->macrovar_osc_pha_rand_sin1 = mathLerpf(macrovalues_osc_pha_rand[voice->tmp3/*idx*/ + 0], macrovalues_osc_pha_rand[voice->tmp4/*mac_idx_n*/ + 0], voice->tmp2/*mac_amt*/);
   voice->macrovar_osc_pha_rand_tri1 = mathLerpf(macrovalues_osc_pha_rand[voice->tmp3/*idx*/ + 1], macrovalues_osc_pha_rand[voice->tmp4/*mac_idx_n*/ + 1], voice->tmp2/*mac_amt*/);
   voice->macrovar_osc_pha_rand_sin2 = mathLerpf(macrovalues_osc_pha_rand[voice->tmp3/*idx*/ + 2], macrovalues_osc_pha_rand[voice->tmp4/*mac_idx_n*/ + 2], voice->tmp2/*mac_amt*/);
   voice->macrovar_osc_pha_rand_tri2 = mathLerpf(macrovalues_osc_pha_rand[voice->tmp3/*idx*/ + 3], macrovalues_osc_pha_rand[voice->tmp4/*mac_idx_n*/ + 3], voice->tmp2/*mac_amt*/);
   
   // -- mod="fsr" dstVar=out
   voice->tmp5/*i2f*/ = (int)(out * 2048);  // IntFallback: F2I
   voice->tmp6_lfsr_state ^= voice->tmp6_lfsr_state >> 7;
   voice->tmp6_lfsr_state ^= voice->tmp6_lfsr_state << 9;
   voice->tmp6_lfsr_state ^= voice->tmp6_lfsr_state >> 13;
   voice->tmp7_lfsr_state_signed = (voice->tmp6_lfsr_state & 65520);
   voice->tmp5/*i2f*/ = voice->tmp7_lfsr_state_signed >> 4;
   out = voice->tmp5/*i2f*/ / ((float)(2048));  // IntFallback: I2F
   
   // -- mod="osc_pha_rand.sin1" dstVar=out
   voice->tmp1/*seq*/ = out;
   voice->tmp1/*seq*/ = voice->macrovar_osc_pha_rand_sin1;
   out *= voice->tmp1/*seq*/;
   
   // -- mod="sto v_phrand_sin_1" dstVar=out
   voice->var_v_phrand_sin_1 = out;
   
   // -- mod="fsr" dstVar=out
   voice->tmp5/*i2f*/ = (int)(out * 2048);  // IntFallback: F2I
   voice->tmp8_lfsr_state ^= voice->tmp8_lfsr_state >> 7;
   voice->tmp8_lfsr_state ^= voice->tmp8_lfsr_state << 9;
   voice->tmp8_lfsr_state ^= voice->tmp8_lfsr_state >> 13;
   voice->tmp9_lfsr_state_signed = (voice->tmp8_lfsr_state & 65520);
   voice->tmp5/*i2f*/ = voice->tmp9_lfsr_state_signed >> 4;
   out = voice->tmp5/*i2f*/ / ((float)(2048));  // IntFallback: I2F
   
   // -- mod="osc_pha_rand.tri1" dstVar=out
   voice->tmp1/*seq*/ = out;
   voice->tmp1/*seq*/ = voice->macrovar_osc_pha_rand_tri1;
   out *= voice->tmp1/*seq*/;
   
   // -- mod="sto v_phrand_tri_1" dstVar=out
   voice->var_v_phrand_tri_1 = out;
   
   // -- mod="fsr" dstVar=out
   voice->tmp5/*i2f*/ = (int)(out * 2048);  // IntFallback: F2I
   voice->tmp10_lfsr_state ^= voice->tmp10_lfsr_state >> 7;
   voice->tmp10_lfsr_state ^= voice->tmp10_lfsr_state << 9;
   voice->tmp10_lfsr_state ^= voice->tmp10_lfsr_state >> 13;
   voice->tmp11_lfsr_state_signed = (voice->tmp10_lfsr_state & 65520);
   voice->tmp5/*i2f*/ = voice->tmp11_lfsr_state_signed >> 4;
   out = voice->tmp5/*i2f*/ / ((float)(2048));  // IntFallback: I2F
   
   // -- mod="osc_pha_rand.sin2" dstVar=out
   voice->tmp1/*seq*/ = out;
   voice->tmp1/*seq*/ = voice->macrovar_osc_pha_rand_sin2;
   out *= voice->tmp1/*seq*/;
   
   // -- mod="sto v_phrand_sin_2" dstVar=out
   voice->var_v_phrand_sin_2 = out;
   
   // -- mod="fsr" dstVar=out
   voice->tmp5/*i2f*/ = (int)(out * 2048);  // IntFallback: F2I
   voice->tmp12_lfsr_state ^= voice->tmp12_lfsr_state >> 7;
   voice->tmp12_lfsr_state ^= voice->tmp12_lfsr_state << 9;
   voice->tmp12_lfsr_state ^= voice->tmp12_lfsr_state >> 13;
   voice->tmp13_lfsr_state_signed = (voice->tmp12_lfsr_state & 65520);
   voice->tmp5/*i2f*/ = voice->tmp13_lfsr_state_signed >> 4;
   out = voice->tmp5/*i2f*/ / ((float)(2048));  // IntFallback: I2F
   
   // -- mod="osc_pha_rand.tri2" dstVar=out
   voice->tmp1/*seq*/ = out;
   voice->tmp1/*seq*/ = voice->macrovar_osc_pha_rand_tri2;
   out *= voice->tmp1/*seq*/;
   
   // -- mod="sto v_phrand_tri_2" dstVar=out
   voice->var_v_phrand_tri_2 = out;
} /* end init */

void loc_prepare(st_plugin_voice_t *_voice) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);

   float out = 0.0f;
   (void)out;
   // -------- lane "prepare" modIdx=0 modString=mac
   
   // -- mod="mac" dstVar=out
   
   // ---- mod="mac" input "pos" seq 1/1
   
   // -- mod="$m_op12_mix" dstVar=voice->tmp14/*mac_pos*/
   voice->tmp14/*mac_pos*/ = voice->mod_op12_mix_cur;
   voice->tmp14/*mac_pos*/ = ffrac_s(voice->tmp14/*mac_pos*/) * 16;
   voice->tmp15/*mac_amt*/ = ffrac_s(voice->tmp14/*mac_pos*/);
   voice->tmp16/*idx*/ = int(voice->tmp14/*mac_pos*/) * 4;
   voice->tmp17/*mac_idx_n*/ = (voice->tmp16/*idx*/ + 4) & 63;
   voice->macrovar_osc_mix_sin1 = mathLerpf(macrovalues_osc_mix[voice->tmp16/*idx*/ + 0], macrovalues_osc_mix[voice->tmp17/*mac_idx_n*/ + 0], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_mix_tri1 = mathLerpf(macrovalues_osc_mix[voice->tmp16/*idx*/ + 1], macrovalues_osc_mix[voice->tmp17/*mac_idx_n*/ + 1], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_mix_sin2 = mathLerpf(macrovalues_osc_mix[voice->tmp16/*idx*/ + 2], macrovalues_osc_mix[voice->tmp17/*mac_idx_n*/ + 2], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_mix_tri2 = mathLerpf(macrovalues_osc_mix[voice->tmp16/*idx*/ + 3], macrovalues_osc_mix[voice->tmp17/*mac_idx_n*/ + 3], voice->tmp15/*mac_amt*/);
   
   // -- mod="mac" dstVar=out
   
   // ---- mod="mac" input "pos" seq 1/1
   
   // -- mod="$m_op2_noise" dstVar=voice->tmp14/*mac_pos*/
   voice->tmp14/*mac_pos*/ = voice->mod_op2_noise_cur;
   voice->tmp14/*mac_pos*/ = ffrac_s(voice->tmp14/*mac_pos*/) * 9;
   voice->tmp15/*mac_amt*/ = ffrac_s(voice->tmp14/*mac_pos*/);
   voice->tmp16/*idx*/ = int(voice->tmp14/*mac_pos*/) * 2;
   voice->tmp17/*mac_idx_n*/ = (voice->tmp16/*idx*/ + 2) % 18;
   voice->macrovar_osc2_noise_cutoff = mathLerpf(macrovalues_osc2_noise[voice->tmp16/*idx*/ + 0], macrovalues_osc2_noise[voice->tmp17/*mac_idx_n*/ + 0], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc2_noise_level = mathLerpf(macrovalues_osc2_noise[voice->tmp16/*idx*/ + 1], macrovalues_osc2_noise[voice->tmp17/*mac_idx_n*/ + 1], voice->tmp15/*mac_amt*/);
   
   // -- mod="mac" dstVar=out
   
   // ---- mod="mac" input "pos" seq 1/1
   
   // -- mod="$m_op12_pha" dstVar=voice->tmp14/*mac_pos*/
   voice->tmp14/*mac_pos*/ = voice->mod_op12_pha_cur;
   voice->tmp14/*mac_pos*/ = ffrac_s(voice->tmp14/*mac_pos*/) * 256;
   voice->tmp15/*mac_amt*/ = ffrac_s(voice->tmp14/*mac_pos*/);
   voice->tmp16/*idx*/ = int(voice->tmp14/*mac_pos*/) * 4;
   voice->tmp17/*mac_idx_n*/ = (voice->tmp16/*idx*/ + 4) & 1023;
   voice->macrovar_osc_pha_sin1 = mathLerpf(macrovalues_osc_pha[voice->tmp16/*idx*/ + 0], macrovalues_osc_pha[voice->tmp17/*mac_idx_n*/ + 0], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_pha_tri1 = mathLerpf(macrovalues_osc_pha[voice->tmp16/*idx*/ + 1], macrovalues_osc_pha[voice->tmp17/*mac_idx_n*/ + 1], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_pha_sin2 = mathLerpf(macrovalues_osc_pha[voice->tmp16/*idx*/ + 2], macrovalues_osc_pha[voice->tmp17/*mac_idx_n*/ + 2], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_pha_tri2 = mathLerpf(macrovalues_osc_pha[voice->tmp16/*idx*/ + 3], macrovalues_osc_pha[voice->tmp17/*mac_idx_n*/ + 3], voice->tmp15/*mac_amt*/);
   
   // -- mod="mac" dstVar=out
   
   // ---- mod="mac" input "pos" seq 1/1
   
   // -- mod="$m_op12_vsync" dstVar=voice->tmp14/*mac_pos*/
   voice->tmp14/*mac_pos*/ = voice->mod_op12_vsync_cur;
   voice->tmp14/*mac_pos*/ = ffrac_s(voice->tmp14/*mac_pos*/) * 16;
   voice->tmp15/*mac_amt*/ = ffrac_s(voice->tmp14/*mac_pos*/);
   voice->tmp16/*idx*/ = int(voice->tmp14/*mac_pos*/) * 4;
   voice->tmp17/*mac_idx_n*/ = (voice->tmp16/*idx*/ + 4) & 63;
   voice->macrovar_osc_vsync_sin1 = mathLerpf(macrovalues_osc_vsync[voice->tmp16/*idx*/ + 0], macrovalues_osc_vsync[voice->tmp17/*mac_idx_n*/ + 0], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_vsync_tri1 = mathLerpf(macrovalues_osc_vsync[voice->tmp16/*idx*/ + 1], macrovalues_osc_vsync[voice->tmp17/*mac_idx_n*/ + 1], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_vsync_sin2 = mathLerpf(macrovalues_osc_vsync[voice->tmp16/*idx*/ + 2], macrovalues_osc_vsync[voice->tmp17/*mac_idx_n*/ + 2], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_vsync_tri2 = mathLerpf(macrovalues_osc_vsync[voice->tmp16/*idx*/ + 3], macrovalues_osc_vsync[voice->tmp17/*mac_idx_n*/ + 3], voice->tmp15/*mac_amt*/);
   
   // -- mod="mac" dstVar=out
   
   // ---- mod="mac" input "pos" seq 1/1
   
   // -- mod="$m_op12_det" dstVar=voice->tmp14/*mac_pos*/
   voice->tmp14/*mac_pos*/ = voice->mod_op12_det_cur;
   voice->tmp14/*mac_pos*/ = ffrac_s(voice->tmp14/*mac_pos*/) * 81;
   voice->tmp15/*mac_amt*/ = ffrac_s(voice->tmp14/*mac_pos*/);
   voice->tmp16/*idx*/ = int(voice->tmp14/*mac_pos*/) * 4;
   voice->tmp17/*mac_idx_n*/ = (voice->tmp16/*idx*/ + 4) % 324;
   voice->macrovar_osc_det_sin1 = mathLerpf(macrovalues_osc_det[voice->tmp16/*idx*/ + 0], macrovalues_osc_det[voice->tmp17/*mac_idx_n*/ + 0], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_det_tri1 = mathLerpf(macrovalues_osc_det[voice->tmp16/*idx*/ + 1], macrovalues_osc_det[voice->tmp17/*mac_idx_n*/ + 1], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_det_sin2 = mathLerpf(macrovalues_osc_det[voice->tmp16/*idx*/ + 2], macrovalues_osc_det[voice->tmp17/*mac_idx_n*/ + 2], voice->tmp15/*mac_amt*/);
   voice->macrovar_osc_det_tri2 = mathLerpf(macrovalues_osc_det[voice->tmp16/*idx*/ + 3], macrovalues_osc_det[voice->tmp17/*mac_idx_n*/ + 3], voice->tmp15/*mac_amt*/);
   
   // -- mod="1" dstVar=out
   out = 1.0f;
   
   // -- mod="sto v_freq" dstVar=out
   voice->var_v_freq = out;
   
   // -- mod="osc_det.sin1" dstVar=out
   voice->tmp14/*seq*/ = out;
   voice->tmp14/*seq*/ = voice->macrovar_osc_det_sin1;
   out += voice->tmp14/*seq*/;
   
   // -- mod="sto v_freq_1_sin" dstVar=out
   voice->var_v_freq_1_sin = out;
   
   // -- mod="$v_freq" dstVar=out
   out = voice->var_v_freq;
   
   // -- mod="osc_det.tri1" dstVar=out
   voice->tmp14/*seq*/ = out;
   voice->tmp14/*seq*/ = voice->macrovar_osc_det_tri1;
   out += voice->tmp14/*seq*/;
   
   // -- mod="sto v_freq_1_tri" dstVar=out
   voice->var_v_freq_1_tri = out;
   
   // -- mod="$m_op2_ratio" dstVar=out
   out = voice->mod_op2_ratio_cur;
   
   // -- mod="fma" dstVar=out
   out = (out * 2.0f) + -1.0f;
   
   // -- mod="bts" dstVar=out
   out = loc_bipolar_to_scale(out, 4096.0f, 4.0f);
   
   // -- mod="pow" dstVar=out
   out = out * out * out;
   
   // -- mod="qua" dstVar=out
   out = ((int)(out * 100.0f) / 100.0f);
   
   // -- mod="sto v_freq" dstVar=out
   voice->var_v_freq = out;
   
   // -- mod="osc_det.sin2" dstVar=out
   voice->tmp14/*seq*/ = out;
   voice->tmp14/*seq*/ = voice->macrovar_osc_det_sin2;
   out += voice->tmp14/*seq*/;
   
   // -- mod="sto v_freq_2_sin" dstVar=out
   voice->var_v_freq_2_sin = out;
   
   // -- mod="$v_freq" dstVar=out
   out = voice->var_v_freq;
   
   // -- mod="osc_det.tri2" dstVar=out
   voice->tmp14/*seq*/ = out;
   voice->tmp14/*seq*/ = voice->macrovar_osc_det_tri2;
   out += voice->tmp14/*seq*/;
   
   // -- mod="sto v_freq_2_tri" dstVar=out
   voice->var_v_freq_2_tri = out;
} /* end prepare */


#ifndef CYCLE_SKIP_UI
static unsigned int loc_copy_chars(char *_d, const unsigned int _dSize, const char *_s) {
   unsigned int r = 0u;
   if(NULL != _d)
   {
      // Write min(dSize,len(s)) characters to 'd'
      char *d = _d;
      if(NULL != _s)
      {
         const char *s = _s;
         for(;;)
         {
            if(r < _dSize)
            {
               char c = s[r++];
               *d++ = c;
               if(0 == c)
                  break;
            }
            else
            {
               if(r > 0u)
                  d[-1] = 0;  // force ASCIIZ
               break;
            }
         }
      }
      else
      {
         if(_dSize > 0u)
         {
            _d[0] = 0;
            r = 1u;
         }
      }
   }
   else
   {
      // Return total length of source string
      if(NULL != _s)
      {
         const char *s = _s;
         for(;;)
         {
            char c = s[r++];
            if(0 == c)
               break;
         }
      }
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static unsigned int loc_copy_floats(float              *_d,
                                    const unsigned int  _dSize,
                                    const float        *_s,
                                    const unsigned int  _sNum
                                    ) {
   unsigned int r = 0u;
   if(NULL != _d)
   {
      // Write min(dSize,sNum) characters to 'd'
      if(NULL != _s)
      {
         unsigned int num = (_sNum > _dSize) ? _dSize : _sNum;
         memcpy((void*)_d, (const void*)_s, num * sizeof(float));
         r = num;
      }
   }
   else
   {
      // Query total number of presets
      r = _sNum;
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static const char *ST_PLUGIN_API loc_get_param_name(st_plugin_info_t *_info,
                                                    unsigned int      _paramIdx
                                                    ) {
   (void)_info;
   return loc_param_names[_paramIdx];
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static const char *ST_PLUGIN_API loc_get_param_group_name(st_plugin_info_t *_info,
                                                          unsigned int      _paramGroupIdx
                                                          ) {
   (void)_info;
   const char *r = NULL;
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static unsigned int ST_PLUGIN_API loc_get_param_group_idx(st_plugin_info_t *_info,
                                                          unsigned int      _paramIdx
                                                          ) {
   (void)_info;
   unsigned int r = ~0u;
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static const char *ST_PLUGIN_API loc_get_param_section_name(st_plugin_info_t *_info,
                                                            unsigned int      _paramSectionIdx
                                                            ) {
   (void)_info;
   const char *r = NULL;
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static unsigned int ST_PLUGIN_API loc_get_param_section_idx(st_plugin_info_t *_info,
                                                            unsigned int      _paramIdx
                                                            ) {
   (void)_info;
   unsigned int r = ~0u;
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static float ST_PLUGIN_API loc_get_param_reset(st_plugin_info_t *_info,
                                               unsigned int      _paramIdx
                                               ) {
   (void)_info;
   return loc_param_resets[_paramIdx];
}
#endif // CYCLE_SKIP_UI

static float ST_PLUGIN_API loc_get_param_value(st_plugin_shared_t *_shared,
                                               unsigned int        _paramIdx
                                               ) {
   ST_PLUGIN_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   return shared->params[_paramIdx];
}

static void ST_PLUGIN_API loc_set_param_value(st_plugin_shared_t *_shared,
                                              unsigned int        _paramIdx,
                                              float               _value
                                              ) {
   ST_PLUGIN_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   shared->params[_paramIdx] = _value;
}

#ifndef CYCLE_SKIP_UI
static unsigned int ST_PLUGIN_API loc_query_dynamic_param_preset_values(st_plugin_shared_t *_shared,
                                                                        const unsigned int  _paramIdx,
                                                                        float              *_retValues,
                                                                        const unsigned int  _retValuesSize
                                                                        ) {
   ST_PLUGIN_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   unsigned int r = 0u;
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static unsigned int ST_PLUGIN_API loc_query_dynamic_param_preset_name(st_plugin_shared_t *_shared,
                                                                      const unsigned int  _paramIdx,
                                                                      const unsigned int  _presetIdx,
                                                                      char               *_retBuf,
                                                                      const unsigned int  _retBufSize
                                                                      ) {
   ST_PLUGIN_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   unsigned int r = 0u;
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static unsigned int ST_PLUGIN_API loc_get_array_param_size(st_plugin_info_t   *_info,
                                                           const unsigned int  _paramIdx
                                                           ) {
   unsigned int r = 0u;
   switch(_paramIdx)
   {
      default:
         break;
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static unsigned int ST_PLUGIN_API loc_get_array_param_num_variations(st_plugin_info_t   *_info,
                                                                     const unsigned int  _paramIdx
                                                                     ) {
   unsigned int r = 0u;
   switch(_paramIdx)
   {
      default:
         break;
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static float * ST_PLUGIN_API loc_get_array_param_variation_ptr(st_plugin_shared_t *_shared,
                                                               const unsigned int  _paramIdx,
                                                               const unsigned int  _variationIdx
                                                               ) {
   ST_PLUGIN_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   float *r = NULL;
   switch(_paramIdx)
   {
      default:
         break;
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static void ST_PLUGIN_API loc_set_array_param_edit_variation_idx(st_plugin_shared_t *_shared,
                                                                 const unsigned int  _paramIdx,
                                                                 const int           _variationIdx
                                                                 ) {
   ST_PLUGIN_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   switch(_paramIdx)
   {
      default:
         break;
   }
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static const char *ST_PLUGIN_API loc_get_array_param_element_name(st_plugin_info_t   *_info,
                                                                  const unsigned int  _paramIdx,
                                                                  const unsigned int  _elementIdx
                                                                  ) {
   ST_PLUGIN_INFO_CAST(osc_fm2s_macro_vsync_info_t);
   const char *r = NULL;
   switch(_paramIdx)
   {
      default:
         break;
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static int ST_PLUGIN_API loc_get_array_param_element_value_range(st_plugin_info_t   *_info,
                                                                 const unsigned int  _paramIdx,
                                                                 const unsigned int  _elementIdx,
                                                                 float              *_retStorageMin,
                                                                 float              *_retStorageMax,
                                                                 float              *_retDisplayMin,
                                                                 float              *_retDisplayMax,
                                                                 unsigned int       *_retDisplayPrecision
                                                                 ) {
   (void)_elementIdx;
   switch(_paramIdx)
   {
      default:
         break;
   }
   return 0;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static float ST_PLUGIN_API loc_get_array_param_element_reset(st_plugin_info_t   *_info,
                                                             const unsigned int  _paramIdx,
                                                             const unsigned int  _elementIdx
                                                             ) {
   ST_PLUGIN_INFO_CAST(osc_fm2s_macro_vsync_info_t);
   float r = -999999.0f/*INVALID_VALUE*/;
   switch(_paramIdx)
   {
      default:
         break;
   }
   return r;
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static void ST_PLUGIN_API loc_update_lut(st_plugin_info_t   *_info,
                                         unsigned int        _idx,
                                         const float        *_src,
                                         const unsigned int  _srcNumElements
                                         ) {
   (void)_info;
   unsigned int copySz = 0u;
   (void)copySz;
   switch(_idx)
   {
      default:
         break;
   }
}
#endif // CYCLE_SKIP_UI

#ifndef CYCLE_SKIP_UI
static const char *ST_PLUGIN_API loc_get_mod_name(st_plugin_info_t *_info,
                                                  unsigned int      _modIdx
                                                  ) {
   (void)_info;
   return loc_mod_names[_modIdx];
}
#endif // CYCLE_SKIP_UI

static void ST_PLUGIN_API loc_set_sample_rate(st_plugin_voice_t *_voice,
                                              float              _sampleRate
                                              ) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   if(_sampleRate != voice->sample_rate)
   {
      voice->sr_factor = 3000.0f / _sampleRate;
   }
   voice->sample_rate = _sampleRate;
}

static void ST_PLUGIN_API loc_set_bpm(st_plugin_voice_t *_voice,
                                      float              _bpm
                                      ) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   voice->bpm = _bpm;
}

static void ST_PLUGIN_API loc_note_on(st_plugin_voice_t  *_voice,
                                      int                 _bGlide,
                                      unsigned char       _note,
                                      float               _vel
                                      ) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   (void)_bGlide;
   (void)_note;
   (void)_vel;
   if(!_bGlide)
   {
      memset((void*)voice->mods, 0, sizeof(voice->mods));
#ifdef OVERSAMPLE_FACTOR
      voice->note_speed_fixed = (261.63f/*C-5*/ / (voice->sample_rate * OVERSAMPLE_FACTOR));
#else
      voice->note_speed_fixed = (261.63f/*C-5*/ / voice->sample_rate);
#endif // OVERSAMPLE_FACTOR
      voice->velocity = _vel;
      voice->tmp7_lfsr_state_signed = 0;
      voice->tmp9_lfsr_state_signed = 0;
      voice->tmp11_lfsr_state_signed = 0;
      voice->tmp13_lfsr_state_signed = 0;
      voice->tmp18_sin_phase = 0.0f;
      voice->tmp19_win_phase = 0.0f;
      voice->tmp25_tri_phase = 0.0f;
      voice->tmp26_win_phase = 0.0f;
      voice->tmp30_lfsr_state_signed = 0;
      voice->tmp31_svf_lp = 0.0f;
      voice->tmp32_svf_hp = 0.0f;
      voice->tmp33_svf_bp = 0.0f;
      voice->tmp34_sin_phase = 0.0f;
      voice->tmp35_win_phase = 0.0f;
      voice->tmp36_tri_phase = 0.0f;
      voice->tmp37_win_phase = 0.0f;
      voice->var_x = 0.0f;
      voice->var_v_phrand_sin_1 = 0.0f;
      voice->var_v_phrand_tri_1 = 0.0f;
      voice->var_v_phrand_sin_2 = 0.0f;
      voice->var_v_phrand_tri_2 = 0.0f;
      voice->var_v_freq_1_sin = 0.0f;
      voice->var_v_freq_1_tri = 0.0f;
      voice->var_v_freq = 0.0f;
      voice->var_v_freq_2_sin = 0.0f;
      voice->var_v_freq_2_tri = 0.0f;
      voice->var_v_level_2 = 0.0f;
      voice->var_v_osc_2_raw = 0.0f;
      voice->var_v_osc_2 = 0.0f;
      voice->macrovar_osc_mix_sin1 = 0;
      voice->macrovar_osc_mix_tri1 = 0;
      voice->macrovar_osc_mix_sin2 = 0;
      voice->macrovar_osc_mix_tri2 = 0;
      voice->macrovar_osc2_noise_cutoff = 0;
      voice->macrovar_osc2_noise_level = 0;
      voice->macrovar_osc_pha_sin1 = 0;
      voice->macrovar_osc_pha_tri1 = 0;
      voice->macrovar_osc_pha_sin2 = 0;
      voice->macrovar_osc_pha_tri2 = 0;
      voice->macrovar_osc_pha_rand_sin1 = 0;
      voice->macrovar_osc_pha_rand_tri1 = 0;
      voice->macrovar_osc_pha_rand_sin2 = 0;
      voice->macrovar_osc_pha_rand_tri2 = 0;
      voice->macrovar_osc_vsync_sin1 = 0;
      voice->macrovar_osc_vsync_tri1 = 0;
      voice->macrovar_osc_vsync_sin2 = 0;
      voice->macrovar_osc_vsync_tri2 = 0;
      voice->macrovar_osc_det_sin1 = 0;
      voice->macrovar_osc_det_tri1 = 0;
      voice->macrovar_osc_det_sin2 = 0;
      voice->macrovar_osc_det_tri2 = 0;
      loc_init(&voice->base);
   }
}

static void ST_PLUGIN_API loc_set_mod_value(st_plugin_voice_t *_voice,
                                            unsigned int       _modIdx,
                                            float              _value,
                                            unsigned           _frameOffset
                                            ) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   (void)_frameOffset;
   voice->mods[_modIdx] = _value;
}

static void ST_PLUGIN_API loc_prepare_block(st_plugin_voice_t *_voice,
                                            unsigned int       _numFrames,
                                            float              _freqHz,
                                            float              _note,
                                            float              _vol,
                                            float              _pan
                                            ) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);
   (void)_note;
   (void)_vol;
   (void)_pan;

#ifdef OVERSAMPLE_FACTOR
   float noteSpeed = _freqHz / (voice->sample_rate * OVERSAMPLE_FACTOR);
#else
   float noteSpeed = _freqHz / voice->sample_rate;
#endif // OVERSAMPLE_FACTOR

   float modop12_mix     = shared->params[PARAM_OP12_MIX    ]                       + voice->mods[MOD_OP12_MIX     ];
   float modop2_noise    = shared->params[PARAM_OP2_NOISE   ]                       + voice->mods[MOD_OP2_NOISE    ];
   float modop12_pha     = shared->params[PARAM_OP12_PHA    ]                       + voice->mods[MOD_OP12_PHA     ];
   float modop12_fb      = voice->mods[MOD_OP12_FB      ];
   float modop12_vsync   = shared->params[PARAM_OP12_VSYNC  ]                       + voice->mods[MOD_OP12_VSYNC   ];
   float modop12_det     = shared->params[PARAM_OP12_DET    ]                       + voice->mods[MOD_OP12_DET     ];
   float modop2_ratio    = shared->params[PARAM_OP2_RATIO   ]                       + voice->mods[MOD_OP2_RATIO    ];
   float modop2_level    = shared->params[PARAM_OP2_LEVEL   ]                       + voice->mods[MOD_OP2_LEVEL    ];

   if(_numFrames > 0u)
   {
      // lerp
#ifdef OVERSAMPLE_FACTOR
      float recBlockSize = (1.0f / (_numFrames * OVERSAMPLE_FACTOR));
#else
      float recBlockSize = (1.0f / _numFrames);
#endif // OVERSAMPLE_FACTOR
      voice->note_speed_inc = (noteSpeed - voice->note_speed_cur) * recBlockSize;
      voice->note_inc       = (_note - voice->note_cur) * recBlockSize;
      voice->mod_op12_mix_inc     = (modop12_mix        - voice->mod_op12_mix_cur      ) * recBlockSize;
      voice->mod_op2_noise_inc    = (modop2_noise       - voice->mod_op2_noise_cur     ) * recBlockSize;
      voice->mod_op12_pha_inc     = (modop12_pha        - voice->mod_op12_pha_cur      ) * recBlockSize;
      voice->mod_op12_fb_inc      = (modop12_fb         - voice->mod_op12_fb_cur       ) * recBlockSize;
      voice->mod_op12_vsync_inc   = (modop12_vsync      - voice->mod_op12_vsync_cur    ) * recBlockSize;
      voice->mod_op12_det_inc     = (modop12_det        - voice->mod_op12_det_cur      ) * recBlockSize;
      voice->mod_op2_ratio_inc    = (modop2_ratio       - voice->mod_op2_ratio_cur     ) * recBlockSize;
      voice->mod_op2_level_inc    = (modop2_level       - voice->mod_op2_level_cur     ) * recBlockSize;
      loc_prepare(&voice->base);
   }
   else
   {
      // initial params/modulation (first block, not rendered)
      voice->note_speed_cur = noteSpeed;
      voice->note_speed_inc = 0.0f;
      voice->note_cur       = _note;
      voice->note_inc       = 0.0f;
      voice->mod_op12_mix_cur     = modop12_mix;
      voice->mod_op12_mix_inc     = 0.0f;
      voice->mod_op2_noise_cur    = modop2_noise;
      voice->mod_op2_noise_inc    = 0.0f;
      voice->mod_op12_pha_cur     = modop12_pha;
      voice->mod_op12_pha_inc     = 0.0f;
      voice->mod_op12_fb_cur      = modop12_fb;
      voice->mod_op12_fb_inc      = 0.0f;
      voice->mod_op12_vsync_cur   = modop12_vsync;
      voice->mod_op12_vsync_inc   = 0.0f;
      voice->mod_op12_det_cur     = modop12_det;
      voice->mod_op12_det_inc     = 0.0f;
      voice->mod_op2_ratio_cur    = modop2_ratio;
      voice->mod_op2_ratio_inc    = 0.0f;
      voice->mod_op2_level_cur    = modop2_level;
      voice->mod_op2_level_inc    = 0.0f;
      loc_prepare(&voice->base);
   }

   // printf("xxx note_cur=%f\n", voice->note_cur);
   // printf("xxx prepare_block: numFrames=%u moda=%f\n", _numFrames, moda);
   // printf("xxx voice->voicebus_idx_0=%u voice->base.voice_bus_read_offset=%u\n", voice->voicebus_idx_0, voice->base.voice_bus_read_offset);
}

static void ST_PLUGIN_API loc_process_replace(st_plugin_voice_t  *_voice,
                                              int                 _bMonoIn,
                                              const float        *_samplesIn,
                                              float              *_samplesOut,
                                              unsigned int        _numFrames
                                              ) {
   (void)_bMonoIn;
   (void)_samplesIn;

   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(osc_fm2s_macro_vsync_shared_t);

   // Mono output (replicate left to right channel)
   unsigned int j = 0u;
#ifndef STEREO
   unsigned int jStep = _bMonoIn ? 1u : 2u;
#endif // STEREO
   unsigned int k = 0u;
   for(unsigned int i = 0u; i < _numFrames; i++)
   {
      const float inL = _samplesIn[j];
#ifdef STEREO
      float outL;
      float outR;
      const float inR = _samplesIn[j + 1u];
#endif // STEREO
      float out;
#ifdef OVERSAMPLE_FACTOR
#ifdef STEREO
      float outOSL = 0.0f;
      float outOSR = 0.0f;
#else
      float outOS = 0.0f;
#endif // STEREO
#endif // OVERSAMPLE_FACTOR

#ifdef OVERSAMPLE_FACTOR
      for(unsigned int osi = 0u; osi < OVERSAMPLE_FACTOR; osi++)
#endif // OVERSAMPLE_FACTOR
      {
#ifdef STEREO
         out = outL = inL;
         outR = inR;
#else
         out = inL;
#endif // STEREO
         float tmp_f; (void)tmp_f;
         float tmp2_f; (void)tmp2_f;
         
         // ========
         // ======== lane "out" modIdx=0 modString=$m_op2_level
         // ========
         
         // -- mod="$m_op2_level" dstVar=out
         out = voice->mod_op2_level_cur;
         
         // -- mod="16" dstVar=out
         out *= 16.0f;
         
         // -- mod="sto v_level_2" dstVar=out
         voice->var_v_level_2 = out;
         
         // -- mod="sin" dstVar=out
         
         // ---- mod="sin" input "freq" seq 1/1
         
         // -- mod="$v_freq_2_sin" dstVar=voice->tmp21/*sin_freq*/
         voice->tmp21/*sin_freq*/ = voice->var_v_freq_2_sin;
         voice->tmp20/*sin_speed*/ = voice->note_speed_cur * voice->tmp21/*sin_freq*/;
         
         // ---- mod="sin" input "phase" seq 1/1
         
         // -- mod="osc_pha.sin2" dstVar=voice->tmp22/*phase*/
         voice->tmp22/*phase*/ = voice->macrovar_osc_pha_sin2;
         
         // -- mod="$v_phrand_sin_2" dstVar=voice->tmp22/*phase*/
         voice->tmp23/*seq*/ = voice->tmp22/*phase*/;
         voice->tmp23/*seq*/ = voice->var_v_phrand_sin_2;
         voice->tmp22/*phase*/ += voice->tmp23/*seq*/;
         
         // ---- mod="sin" input "vsync" seq 1/1
         
         // -- mod="osc_vsync.sin2" dstVar=voice->tmp23/*vsync*/
         voice->tmp23/*vsync*/ = voice->macrovar_osc_vsync_sin2;
         voice->tmp21/*sin_tmp*/ = ((voice->tmp18_sin_phase + voice->tmp22/*phase*/));
         voice->tmp21/*sin_tmp*/ = ffrac_s(voice->tmp21/*sin_tmp*/);
         out = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp21/*sin_tmp*/)&16383u];
         voice->tmp24/*window*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp19_win_phase)&16383u];
         voice->tmp24/*window*/ *= voice->tmp24/*window*/;
         out *= voice->tmp24/*window*/;
         voice->tmp18_sin_phase = ffrac_s(voice->tmp18_sin_phase + voice->tmp20/*sin_speed*/ * voice->tmp23/*vsync*/);
         tmp_f = voice->tmp19_win_phase;
         voice->tmp19_win_phase = ffrac_s(voice->tmp19_win_phase + voice->tmp20/*sin_speed*/);
         if(tmp_f > voice->tmp19_win_phase) voice->tmp18_sin_phase = voice->tmp19_win_phase * voice->tmp23/*vsync*/; 
         
         // -- mod="osc_mix.sin2" dstVar=out
         voice->tmp20/*seq*/ = out;
         voice->tmp20/*seq*/ = voice->macrovar_osc_mix_sin2;
         out *= voice->tmp20/*seq*/;
         
         // -- mod="tri" dstVar=out
         voice->tmp20/*seq*/ = out;
         
         // ---- mod="tri" input "freq" seq 1/1
         
         // -- mod="$v_freq_2_tri" dstVar=voice->tmp22/*tri_freq*/
         voice->tmp22/*tri_freq*/ = voice->var_v_freq_2_tri;
         voice->tmp21/*tri_speed*/ = voice->note_speed_cur * voice->tmp22/*tri_freq*/;
         
         // ---- mod="tri" input "phase" seq 1/1
         
         // -- mod="osc_pha.tri2" dstVar=voice->tmp23/*phase*/
         voice->tmp23/*phase*/ = voice->macrovar_osc_pha_tri2;
         
         // -- mod="$v_phrand_tri_2" dstVar=voice->tmp23/*phase*/
         voice->tmp24/*seq*/ = voice->tmp23/*phase*/;
         voice->tmp24/*seq*/ = voice->var_v_phrand_tri_2;
         voice->tmp23/*phase*/ += voice->tmp24/*seq*/;
         
         // ---- mod="tri" input "vsync" seq 1/1
         
         // -- mod="osc_vsync.tri2" dstVar=voice->tmp24/*vsync*/
         voice->tmp24/*vsync*/ = voice->macrovar_osc_vsync_tri2;
         voice->tmp22/*tri_tmp*/ = ((voice->tmp25_tri_phase + voice->tmp23/*phase*/));
         voice->tmp22/*tri_tmp*/ = ffrac_s(voice->tmp22/*tri_tmp*/);
         voice->tmp20/*seq*/ = (voice->tmp22/*tri_tmp*/ < 0.5f) ? (-1.0f + voice->tmp22/*tri_tmp*/ * 4.0f) : (1.0f - (voice->tmp22/*tri_tmp*/ - 0.5f)*4);
         voice->tmp27/*window*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp26_win_phase)&16383u];
         voice->tmp27/*window*/ *= voice->tmp27/*window*/;
         voice->tmp20/*seq*/ *= voice->tmp27/*window*/;
         voice->tmp25_tri_phase = ffrac_s(voice->tmp25_tri_phase + voice->tmp21/*tri_speed*/ * voice->tmp24/*vsync*/);
         tmp_f = voice->tmp26_win_phase;
         voice->tmp26_win_phase = ffrac_s(voice->tmp26_win_phase + voice->tmp21/*tri_speed*/);
         if(tmp_f > voice->tmp26_win_phase) voice->tmp25_tri_phase = voice->tmp26_win_phase * voice->tmp24/*vsync*/; 
         
         // -- mod="osc_mix.tri2" dstVar=voice->tmp20/*seq*/
         voice->tmp21/*seq*/ = voice->tmp20/*seq*/;
         voice->tmp21/*seq*/ = voice->macrovar_osc_mix_tri2;
         voice->tmp20/*seq*/ *= voice->tmp21/*seq*/;
         out += voice->tmp20/*seq*/;
         
         // -- mod="$v_level_2" dstVar=out
         voice->tmp20/*seq*/ = out;
         voice->tmp20/*seq*/ = voice->var_v_level_2;
         out *= voice->tmp20/*seq*/;
         
         // -- mod="sto v_osc_2_raw" dstVar=out
         voice->var_v_osc_2_raw = out;
         
         // -- mod="fsr" dstVar=out
         voice->tmp20/*seq*/ = out;
         voice->tmp28/*i2f*/ = (int)(voice->tmp20/*seq*/ * 2048);  // IntFallback: F2I
         voice->tmp29_lfsr_state ^= voice->tmp29_lfsr_state >> 7;
         voice->tmp29_lfsr_state ^= voice->tmp29_lfsr_state << 9;
         voice->tmp29_lfsr_state ^= voice->tmp29_lfsr_state >> 13;
         voice->tmp30_lfsr_state_signed = (voice->tmp29_lfsr_state & 65520);
         voice->tmp28/*i2f*/ = voice->tmp30_lfsr_state_signed >> 4;
         voice->tmp20/*seq*/ = voice->tmp28/*i2f*/ / ((float)(2048));  // IntFallback: I2F
         
         // -- mod="svf" dstVar=voice->tmp20/*seq*/
         
         // ---- mod="svf" input "freq" seq 1/1
         
         // -- mod="osc2_noise.cutoff" dstVar=voice->tmp21/*addsr_freq*/
         voice->tmp21/*addsr_freq*/ = voice->macrovar_osc2_noise_cutoff;
         
         // -- mod="pow" dstVar=voice->tmp21/*addsr_freq*/
         voice->tmp21/*addsr_freq*/ = voice->tmp21/*addsr_freq*/ * voice->tmp21/*addsr_freq*/ * voice->tmp21/*addsr_freq*/;
         voice->tmp21/*addsr_freq*/ *= voice->sr_factor;
         voice->tmp31_svf_lp = voice->tmp31_svf_lp + (voice->tmp33_svf_bp * voice->tmp21/*addsr_freq*/);
         voice->tmp32_svf_hp = voice->tmp20/*seq*/ - voice->tmp31_svf_lp - (voice->tmp33_svf_bp * 1.0f);
         voice->tmp33_svf_bp = voice->tmp33_svf_bp + (voice->tmp32_svf_hp * voice->tmp21/*addsr_freq*/);
         voice->tmp20/*seq*/ = voice->tmp31_svf_lp;
         
         // -- mod="osc2_noise.level" dstVar=voice->tmp20/*seq*/
         voice->tmp21/*seq*/ = voice->tmp20/*seq*/;
         voice->tmp21/*seq*/ = voice->macrovar_osc2_noise_level;
         voice->tmp20/*seq*/ *= voice->tmp21/*seq*/;
         
         // -- mod="$v_level_2" dstVar=voice->tmp20/*seq*/
         voice->tmp21/*seq*/ = voice->tmp20/*seq*/;
         voice->tmp21/*seq*/ = voice->var_v_level_2;
         voice->tmp20/*seq*/ *= voice->tmp21/*seq*/;
         out += voice->tmp20/*seq*/;
         
         // -- mod="sto v_osc_2" dstVar=out
         voice->var_v_osc_2 = out;
         
         // -- mod="sin" dstVar=out
         
         // ---- mod="sin" input "freq" seq 1/1
         
         // -- mod="$v_freq_1_sin" dstVar=voice->tmp21/*sin_freq*/
         voice->tmp21/*sin_freq*/ = voice->var_v_freq_1_sin;
         voice->tmp20/*sin_speed*/ = voice->note_speed_cur * voice->tmp21/*sin_freq*/;
         
         // ---- mod="sin" input "phase" seq 1/1
         
         // -- mod="$v_osc_2" dstVar=voice->tmp22/*phase*/
         voice->tmp22/*phase*/ = voice->var_v_osc_2;
         
         // -- mod="osc_pha.sin1" dstVar=voice->tmp22/*phase*/
         voice->tmp23/*seq*/ = voice->tmp22/*phase*/;
         voice->tmp23/*seq*/ = voice->macrovar_osc_pha_sin1;
         voice->tmp22/*phase*/ += voice->tmp23/*seq*/;
         
         // -- mod="$v_phrand_sin_1" dstVar=voice->tmp22/*phase*/
         voice->tmp23/*seq*/ = voice->tmp22/*phase*/;
         voice->tmp23/*seq*/ = voice->var_v_phrand_sin_1;
         voice->tmp22/*phase*/ += voice->tmp23/*seq*/;
         
         // ---- mod="sin" input "vsync" seq 1/1
         
         // -- mod="osc_vsync.sin1" dstVar=voice->tmp23/*vsync*/
         voice->tmp23/*vsync*/ = voice->macrovar_osc_vsync_sin1;
         voice->tmp21/*sin_tmp*/ = ((voice->tmp34_sin_phase + voice->tmp22/*phase*/));
         voice->tmp21/*sin_tmp*/ = ffrac_s(voice->tmp21/*sin_tmp*/);
         out = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp21/*sin_tmp*/)&16383u];
         voice->tmp24/*window*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp35_win_phase)&16383u];
         voice->tmp24/*window*/ *= voice->tmp24/*window*/;
         out *= voice->tmp24/*window*/;
         voice->tmp34_sin_phase = ffrac_s(voice->tmp34_sin_phase + voice->tmp20/*sin_speed*/ * voice->tmp23/*vsync*/);
         tmp_f = voice->tmp35_win_phase;
         voice->tmp35_win_phase = ffrac_s(voice->tmp35_win_phase + voice->tmp20/*sin_speed*/);
         if(tmp_f > voice->tmp35_win_phase) voice->tmp34_sin_phase = voice->tmp35_win_phase * voice->tmp23/*vsync*/; 
         
         // -- mod="osc_mix.sin1" dstVar=out
         voice->tmp20/*seq*/ = out;
         voice->tmp20/*seq*/ = voice->macrovar_osc_mix_sin1;
         out *= voice->tmp20/*seq*/;
         
         // -- mod="tri" dstVar=out
         voice->tmp20/*seq*/ = out;
         
         // ---- mod="tri" input "freq" seq 1/1
         
         // -- mod="$v_freq_1_tri" dstVar=voice->tmp22/*tri_freq*/
         voice->tmp22/*tri_freq*/ = voice->var_v_freq_1_tri;
         voice->tmp21/*tri_speed*/ = voice->note_speed_cur * voice->tmp22/*tri_freq*/;
         
         // ---- mod="tri" input "phase" seq 1/1
         
         // -- mod="$v_osc_2" dstVar=voice->tmp23/*phase*/
         voice->tmp23/*phase*/ = voice->var_v_osc_2;
         
         // -- mod="osc_pha.tri1" dstVar=voice->tmp23/*phase*/
         voice->tmp24/*seq*/ = voice->tmp23/*phase*/;
         voice->tmp24/*seq*/ = voice->macrovar_osc_pha_tri1;
         voice->tmp23/*phase*/ += voice->tmp24/*seq*/;
         
         // -- mod="$v_phrand_tri_1" dstVar=voice->tmp23/*phase*/
         voice->tmp24/*seq*/ = voice->tmp23/*phase*/;
         voice->tmp24/*seq*/ = voice->var_v_phrand_tri_1;
         voice->tmp23/*phase*/ += voice->tmp24/*seq*/;
         
         // ---- mod="tri" input "vsync" seq 1/1
         
         // -- mod="osc_vsync.tri1" dstVar=voice->tmp24/*vsync*/
         voice->tmp24/*vsync*/ = voice->macrovar_osc_vsync_tri1;
         voice->tmp22/*tri_tmp*/ = ((voice->tmp36_tri_phase + voice->tmp23/*phase*/));
         voice->tmp22/*tri_tmp*/ = ffrac_s(voice->tmp22/*tri_tmp*/);
         voice->tmp20/*seq*/ = (voice->tmp22/*tri_tmp*/ < 0.5f) ? (-1.0f + voice->tmp22/*tri_tmp*/ * 4.0f) : (1.0f - (voice->tmp22/*tri_tmp*/ - 0.5f)*4);
         voice->tmp27/*window*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp37_win_phase)&16383u];
         voice->tmp27/*window*/ *= voice->tmp27/*window*/;
         voice->tmp20/*seq*/ *= voice->tmp27/*window*/;
         voice->tmp36_tri_phase = ffrac_s(voice->tmp36_tri_phase + voice->tmp21/*tri_speed*/ * voice->tmp24/*vsync*/);
         tmp_f = voice->tmp37_win_phase;
         voice->tmp37_win_phase = ffrac_s(voice->tmp37_win_phase + voice->tmp21/*tri_speed*/);
         if(tmp_f > voice->tmp37_win_phase) voice->tmp36_tri_phase = voice->tmp37_win_phase * voice->tmp24/*vsync*/; 
         
         // -- mod="osc_mix.tri1" dstVar=voice->tmp20/*seq*/
         voice->tmp21/*seq*/ = voice->tmp20/*seq*/;
         voice->tmp21/*seq*/ = voice->macrovar_osc_mix_tri1;
         voice->tmp20/*seq*/ *= voice->tmp21/*seq*/;
         out += voice->tmp20/*seq*/;
   
         /* end calc */

#ifdef OVERSAMPLE_FACTOR
#ifdef STEREO
         outOSL += outL;
         outOSR += outR;
#else
         outOS += out;
#endif // STEREO
#endif // OVERSAMPLE_FACTOR
         voice->note_speed_cur += voice->note_speed_inc;
         voice->note_cur       += voice->note_inc;
         voice->mod_op12_mix_cur   += voice->mod_op12_mix_inc;
         voice->mod_op2_noise_cur  += voice->mod_op2_noise_inc;
         voice->mod_op12_pha_cur   += voice->mod_op12_pha_inc;
         voice->mod_op12_fb_cur    += voice->mod_op12_fb_inc;
         voice->mod_op12_vsync_cur  += voice->mod_op12_vsync_inc;
         voice->mod_op12_det_cur   += voice->mod_op12_det_inc;
         voice->mod_op2_ratio_cur  += voice->mod_op2_ratio_inc;
         voice->mod_op2_level_cur  += voice->mod_op2_level_inc;
      }
#ifdef OVERSAMPLE_FACTOR
      // Apply lowpass filter before downsampling
      //   (note) normalized Fc = F/Fs = 0.442947 / sqrt(oversample_factor^2 - 1)
#ifdef STEREO
      outL = outOSL * (1.0f / OVERSAMPLE_FACTOR);
      outR = outOSR * (1.0f / OVERSAMPLE_FACTOR);
#else
      out = outOS * (1.0f / OVERSAMPLE_FACTOR);
#endif // STEREO
#endif // OVERSAMPLE_FACTOR
#ifdef STEREO
      outL = Dstplugin_fix_denorm_32(outL);
      outR = Dstplugin_fix_denorm_32(outR);
#else
      out = Dstplugin_fix_denorm_32(out);
#endif // STEREO
#ifdef STEREO
      _samplesOut[k]      = outL;
      _samplesOut[k + 1u] = outR;
#else
      _samplesOut[k]      = out;
      _samplesOut[k + 1u] = out;
#endif // STEREO

      // Next frame
      k += 2u;
#ifdef STEREO
      j += 2u;
#else
      j += jStep;
#endif // STEREO
   } /* loop numFrames */
}

static st_plugin_shared_t *ST_PLUGIN_API loc_shared_new(st_plugin_info_t *_info) {
   osc_fm2s_macro_vsync_shared_t *ret = (osc_fm2s_macro_vsync_shared_t *)malloc(sizeof(osc_fm2s_macro_vsync_shared_t));
   if(NULL != ret)
   {
      memset((void*)ret, 0, sizeof(*ret));
      ret->base.info  = _info;
      memcpy((void*)ret->params, (void*)loc_param_resets, NUM_PARAMS * sizeof(float));
   }
   return &ret->base;
}

static void ST_PLUGIN_API loc_shared_delete(st_plugin_shared_t *_shared) {
   free((void*)_shared);
}

static st_plugin_voice_t *ST_PLUGIN_API loc_voice_new(st_plugin_info_t *_info, unsigned int _voiceIdx) {
   osc_fm2s_macro_vsync_voice_t *voice = (osc_fm2s_macro_vsync_voice_t *)malloc(sizeof(osc_fm2s_macro_vsync_voice_t));
   if(NULL != voice)
   {
      memset((void*)voice, 0, sizeof(*voice));
      voice->base.info = _info;
      voice->tmp6_lfsr_state = 17545 * (_voiceIdx + 1u);
      voice->tmp8_lfsr_state = 52447 * (_voiceIdx + 1u);
      voice->tmp10_lfsr_state = 4945 * (_voiceIdx + 1u);
      voice->tmp12_lfsr_state = 44615 * (_voiceIdx + 1u);
      voice->tmp29_lfsr_state = 10552 * (_voiceIdx + 1u);
   }
   return &voice->base;
}

static void ST_PLUGIN_API loc_voice_delete(st_plugin_voice_t *_voice) {
   ST_PLUGIN_VOICE_CAST(osc_fm2s_macro_vsync_voice_t);

   free((void*)_voice);
   }

static void ST_PLUGIN_API loc_plugin_exit(st_plugin_info_t *_info) {
   free((void*)_info);
}

#ifdef USE_CYCLE_SINE_TBL
static void loc_calc_sine_tbl(void) {
#define QCOS_BITS 16
#define QCOS_ONE  (1 << QCOS_BITS)
#define QCOS_MASK (QCOS_ONE - 1)
   // (note) same as in TSR "C" implementation
   float *qcos = cycle_sine_tbl_f + 4096; // quarter cos tbl

   // calc quarter cos tbl
   int k = 0;
   for(int a = 0; a < (QCOS_ONE/4); a += (QCOS_ONE/16384)/*4*/)  // 4096 elements
   {
      int x = a - ((int)(QCOS_ONE * 0.25 + 0.5)) + ((a + ((int)(QCOS_ONE * 0.25 + 0.5)))&~QCOS_MASK);
      x = ((x * ((x<0?-x:x) - ((int)(QCOS_ONE * 0.5 + 0.5)))) >> QCOS_BITS) << 4;
      x += (((((int)(QCOS_ONE * 0.225 + 0.5)) * x) >> QCOS_BITS) * ((x<0?-x:x) - QCOS_ONE)) >> QCOS_BITS;
      qcos[k++] = x / float(QCOS_ONE);
   }

   // 0..90deg (rev qtbl)
   int j = 4096;
   k = 0;
   loop(4096)
      cycle_sine_tbl_f[k++] = qcos[--j];

   // 90..180deg = cos tbl
   k += 4096;

   // 180..360deg (y-flip first half of tbl)
   j = 0;
   loop(8192)
      cycle_sine_tbl_f[k++] = -cycle_sine_tbl_f[j++];

#ifdef USE_CYCLE_SINE_TBL_I
   loop(16384)
      cycle_sine_tbl_i[i] = (short)(cycle_sine_tbl_f[i] * 2048.0f/*FX_ONE*/);
#endif // USE_CYCLE_SINE_TBL_I
}
#endif // USE_CYCLE_SINE_TBL

#ifdef USE_CYCLE_HSE_TBL
#endif // USE_CYCLE_HSE_TBL

extern "C" {
st_plugin_info_t *osc_fm2s_macro_vsync_init(void) {
   osc_fm2s_macro_vsync_info_t *ret = (osc_fm2s_macro_vsync_info_t *)malloc(sizeof(osc_fm2s_macro_vsync_info_t));

   if(NULL != ret)
   {
      memset(ret, 0, sizeof(*ret));

      ret->base.api_version = ST_PLUGIN_API_VERSION;
      ret->base.id          = "osc_fm2s_macro_vsync";  // unique id. don't change this in future builds.
      ret->base.author      = "bsp";
      ret->base.name        = "fm2s vsync macro osc";
      ret->base.short_name  = "fm2s vsync macro osc";
      ret->base.flags       = ST_PLUGIN_FLAG_OSC;
      ret->base.category    = ST_PLUGIN_CAT_UNKNOWN;
      ret->base.num_params  = NUM_PARAMS;
      ret->base.num_mods    = NUM_MODS;

      ret->base.shared_new                          = &loc_shared_new;
      ret->base.shared_delete                       = &loc_shared_delete;
      ret->base.voice_new                           = &loc_voice_new;
      ret->base.voice_delete                        = &loc_voice_delete;
#ifndef CYCLE_SKIP_UI
      ret->base.get_param_name                      = &loc_get_param_name;
      ret->base.get_param_group_name                = &loc_get_param_group_name;
      ret->base.get_param_group_idx                 = &loc_get_param_group_idx;
      ret->base.get_param_section_name              = &loc_get_param_section_name;
      ret->base.get_param_section_idx               = &loc_get_param_section_idx;
      ret->base.get_param_reset                     = &loc_get_param_reset;
      ret->base.query_dynamic_param_preset_values   = &loc_query_dynamic_param_preset_values;
      ret->base.query_dynamic_param_preset_name     = &loc_query_dynamic_param_preset_name;
      ret->base.get_array_param_size                = &loc_get_array_param_size;
      ret->base.get_array_param_num_variations      = &loc_get_array_param_num_variations;
      ret->base.get_array_param_variation_ptr       = &loc_get_array_param_variation_ptr;
      ret->base.set_array_param_edit_variation_idx  = &loc_set_array_param_edit_variation_idx;
      ret->base.get_array_param_element_name        = &loc_get_array_param_element_name;
      ret->base.get_array_param_element_value_range = &loc_get_array_param_element_value_range;
      ret->base.get_array_param_element_reset       = &loc_get_array_param_element_reset;
      ret->base.update_lut                          = &loc_update_lut;
#endif // CYCLE_SKIP_UI
      ret->base.get_param_value                     = &loc_get_param_value;
      ret->base.set_param_value                     = &loc_set_param_value;
#ifndef CYCLE_SKIP_UI
      ret->base.get_mod_name                        = &loc_get_mod_name;
#endif // CYCLE_SKIP_UI
      ret->base.set_sample_rate                     = &loc_set_sample_rate;
      ret->base.set_bpm                             = &loc_set_bpm;
      ret->base.note_on                             = &loc_note_on;
      ret->base.set_mod_value                       = &loc_set_mod_value;
      ret->base.prepare_block                       = &loc_prepare_block;
      ret->base.process_replace                     = &loc_process_replace;
      ret->base.plugin_exit                         = &loc_plugin_exit;

#ifdef USE_CYCLE_SINE_TBL
      loc_calc_sine_tbl();
#endif // USE_CYCLE_SINE_TBL
   }

   return &ret->base;
}

#ifndef STFX_SKIP_MAIN_INIT
ST_PLUGIN_APICALL st_plugin_info_t *ST_PLUGIN_API st_plugin_init(unsigned int _pluginIdx) {
   switch(_pluginIdx)
   {
      case 0u:
         return osc_fm2s_macro_vsync_init();
   }
   return NULL;
}
#endif // STFX_SKIP_MAIN_INIT

} // extern "C"
