// ----
// ---- file   : sinedcy_3.cpp
// ---- author : 
// ---- 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 sinedcy_3.cpp -o sinedcy_3.o
// ---- created: 26May2026 12:52:58
// ----
// ----
// ----

// (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  4.0f

#define PARAM_SDCY_1_TIMESCL     0
#define PARAM_SDCY_1_RATE        1
#define PARAM_SDCY_1_VSYNC       2
#define PARAM_SDCY_1_LEVEL       3
#define PARAM_SDCY_2_TIMESCL     4
#define PARAM_SDCY_2_RATE        5
#define PARAM_SDCY_2_VSYNC       6
#define PARAM_SDCY_2_LEVEL       7
#define PARAM_SDCY_3_TIMESCL     8
#define PARAM_SDCY_3_RATE        9
#define PARAM_SDCY_3_VSYNC       10
#define PARAM_SDCY_3_LEVEL       11
#define PARAM_SDCY_4_TIMESCL     12
#define PARAM_SDCY_4_RATE        13
#define PARAM_SDCY_4_VSYNC       14
#define PARAM_SDCY_4_LEVEL       15
#define NUM_PARAMS               16
#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
   "sdcy_1_timescl",          // 0: SDCY_1_TIMESCL
   "sdcy_1_rate",             // 1: SDCY_1_RATE
   "sdcy_1_vsync",            // 2: SDCY_1_VSYNC
   "sdcy_1_level",            // 3: SDCY_1_LEVEL
   "sdcy_2_timescl",          // 4: SDCY_2_TIMESCL
   "sdcy_2_rate",             // 5: SDCY_2_RATE
   "sdcy_2_vsync",            // 6: SDCY_2_VSYNC
   "sdcy_2_level",            // 7: SDCY_2_LEVEL
   "sdcy_3_timescl",          // 8: SDCY_3_TIMESCL
   "sdcy_3_rate",             // 9: SDCY_3_RATE
   "sdcy_3_vsync",            // 10: SDCY_3_VSYNC
   "sdcy_3_level",            // 11: SDCY_3_LEVEL
   "sdcy_4_timescl",          // 12: SDCY_4_TIMESCL
   "sdcy_4_rate",             // 13: SDCY_4_RATE
   "sdcy_4_vsync",            // 14: SDCY_4_VSYNC
   "sdcy_4_level",            // 15: SDCY_4_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: SDCY_1_TIMESCL
   0.0f,                      // 1: SDCY_1_RATE
   0.0f,                      // 2: SDCY_1_VSYNC
   1.0f,                      // 3: SDCY_1_LEVEL
   0.5f,                      // 4: SDCY_2_TIMESCL
   0.0f,                      // 5: SDCY_2_RATE
   0.0f,                      // 6: SDCY_2_VSYNC
   1.0f,                      // 7: SDCY_2_LEVEL
   0.5f,                      // 8: SDCY_3_TIMESCL
   0.0f,                      // 9: SDCY_3_RATE
   0.0f,                      // 10: SDCY_3_VSYNC
   1.0f,                      // 11: SDCY_3_LEVEL
   0.5f,                      // 12: SDCY_4_TIMESCL
   0.0f,                      // 13: SDCY_4_RATE
   0.0f,                      // 14: SDCY_4_VSYNC
   1.0f,                      // 15: SDCY_4_LEVEL

#endif
};

#define NUM_MODS                 0
#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

#endif
};
#endif // CYCLE_SKIP_UI

typedef struct sinedcy_3_info_s {
   st_plugin_info_t base;
} sinedcy_3_info_t;

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

} sinedcy_3_shared_t;

typedef struct sinedcy_3_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 tmp1;
   float tmp2_sin_phase;
   float tmp3;
   float tmp4;
   float tmp5;
   float tmp6_rmp_cur;
   float tmp7_rmp_step;
   short tmp8;
   short tmp9;
   float tmp10;
   float tmp11;
   float tmp12_sin_phase;
   float tmp13_rmp_cur;
   float tmp14_rmp_step;
   float tmp15_sin_phase;
   float tmp16_rmp_cur;
   float tmp17_rmp_step;
   float tmp18_sin_phase;
   float tmp19_rmp_cur;
   float tmp20_rmp_step;
   float var_x;
   float sr_factor;

} sinedcy_3_voice_t;

#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); } }
static short curve_0[256] = {
2048, 2002, 1959, 1917, 1877, 1839, 1802, 1767, 1732, 1699, 1666, 1635, 1604, 1574, 1545, 1516, 1489, 1462, 1435, 1409, 1384, 1359, 1335, 1312, 1288, 1266, 1244, 1222, 1200, 1179, 1159, 1139, 
1119, 1100, 1081, 1062, 1044, 1026, 1008, 991, 974, 958, 941, 925, 910, 894, 879, 864, 850, 836, 822, 808, 795, 781, 769, 756, 744, 731, 720, 708, 696, 685, 674, 664, 
653, 643, 633, 623, 614, 605, 595, 587, 578, 570, 561, 553, 545, 536, 528, 520, 512, 504, 495, 487, 479, 471, 463, 455, 447, 439, 431, 423, 415, 408, 400, 392, 
385, 377, 370, 363, 355, 348, 341, 334, 327, 321, 314, 308, 301, 295, 289, 283, 277, 271, 266, 260, 255, 250, 245, 240, 236, 231, 227, 222, 218, 214, 210, 206, 
203, 199, 195, 192, 189, 186, 183, 180, 177, 174, 171, 168, 166, 163, 161, 158, 156, 154, 152, 149, 147, 145, 143, 141, 139, 137, 135, 134, 132, 130, 128, 127, 
125, 123, 122, 120, 118, 117, 115, 114, 112, 111, 109, 108, 106, 105, 103, 102, 101, 99, 98, 96, 95, 94, 92, 91, 90, 88, 87, 86, 84, 83, 82, 80, 
79, 78, 77, 75, 74, 73, 71, 70, 69, 68, 66, 65, 64, 63, 61, 60, 59, 58, 56, 55, 54, 53, 51, 50, 49, 48, 46, 45, 44, 43, 41, 40, 
39, 38, 36, 35, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 21, 20, 19, 17, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0, 
};
static short curve_1[256] = {
2048, 1976, 1908, 1842, 1780, 1720, 1663, 1609, 1557, 1507, 1460, 1414, 1371, 1330, 1290, 1253, 1217, 1182, 1149, 1118, 1088, 1060, 1033, 1007, 982, 959, 937, 915, 895, 876, 858, 840, 
824, 808, 793, 779, 766, 753, 741, 730, 719, 709, 699, 690, 681, 673, 665, 658, 651, 644, 638, 633, 627, 622, 617, 613, 608, 604, 600, 597, 593, 590, 587, 584, 
581, 579, 576, 574, 571, 569, 567, 565, 563, 561, 559, 557, 555, 553, 552, 550, 548, 546, 544, 542, 540, 538, 536, 533, 531, 529, 526, 524, 521, 518, 516, 513, 
510, 506, 503, 500, 496, 492, 489, 485, 480, 476, 472, 467, 462, 457, 452, 447, 441, 436, 430, 424, 418, 412, 406, 400, 394, 387, 381, 375, 369, 363, 357, 350, 
344, 338, 332, 326, 320, 314, 308, 302, 296, 290, 284, 278, 273, 267, 262, 256, 251, 246, 241, 236, 232, 227, 223, 218, 214, 210, 207, 203, 199, 196, 192, 189, 
186, 183, 180, 177, 174, 172, 169, 166, 164, 161, 159, 156, 154, 152, 149, 147, 145, 143, 141, 139, 136, 134, 132, 130, 128, 126, 124, 122, 120, 118, 116, 114, 
113, 111, 109, 107, 105, 103, 101, 99, 98, 96, 94, 92, 90, 88, 87, 85, 83, 81, 79, 78, 76, 74, 72, 70, 69, 67, 65, 63, 61, 60, 58, 56, 
54, 53, 51, 49, 47, 46, 44, 42, 40, 38, 37, 35, 33, 31, 30, 28, 26, 24, 23, 21, 19, 17, 15, 14, 12, 10, 8, 7, 5, 3, 1, 0, 
};
static short curve_2[256] = {
2022, 1997, 1968, 1937, 1904, 1868, 1830, 1789, 1746, 1701, 1654, 1605, 1554, 1503, 1450, 1397, 1344, 1291, 1238, 1186, 1135, 1086, 1038, 991, 947, 904, 864, 825, 789, 754, 722, 692, 
663, 637, 612, 589, 568, 549, 532, 516, 501, 488, 475, 463, 451, 440, 429, 418, 408, 398, 389, 380, 371, 362, 354, 346, 339, 331, 324, 317, 311, 304, 298, 292, 
287, 281, 276, 271, 266, 261, 257, 252, 248, 244, 240, 236, 232, 229, 225, 222, 219, 216, 213, 210, 207, 204, 202, 199, 197, 195, 193, 190, 188, 186, 185, 183, 
181, 179, 178, 176, 175, 173, 172, 170, 169, 168, 167, 165, 164, 163, 162, 161, 160, 159, 158, 157, 157, 156, 155, 154, 154, 153, 152, 151, 151, 150, 150, 149, 
148, 148, 147, 147, 146, 146, 145, 145, 144, 144, 143, 143, 142, 142, 141, 141, 140, 140, 139, 139, 138, 138, 137, 137, 136, 136, 135, 135, 134, 134, 133, 133, 
132, 132, 131, 131, 130, 130, 129, 128, 128, 127, 126, 126, 125, 124, 124, 123, 122, 122, 121, 120, 119, 118, 118, 117, 116, 115, 114, 113, 112, 111, 111, 110, 
109, 108, 106, 105, 104, 103, 102, 101, 100, 99, 97, 96, 95, 94, 92, 91, 90, 88, 87, 86, 84, 83, 81, 80, 78, 77, 75, 74, 72, 70, 69, 67, 
65, 64, 62, 60, 58, 56, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 32, 30, 28, 26, 24, 21, 19, 17, 14, 12, 9, 7, 5, 2, 0, 
};
static short curve_3[256] = {
2048, 2021, 1995, 1967, 1939, 1910, 1881, 1852, 1822, 1792, 1762, 1733, 1703, 1674, 1646, 1617, 1590, 1563, 1537, 1512, 1487, 1463, 1440, 1418, 1397, 1376, 1356, 1338, 1319, 1302, 1285, 1269, 
1254, 1239, 1225, 1211, 1198, 1184, 1171, 1159, 1146, 1134, 1121, 1109, 1097, 1086, 1074, 1063, 1051, 1040, 1029, 1018, 1007, 997, 986, 976, 965, 955, 945, 935, 925, 915, 905, 895, 
886, 876, 867, 857, 848, 839, 830, 820, 811, 803, 794, 785, 776, 768, 759, 751, 742, 734, 726, 718, 710, 702, 694, 686, 678, 670, 662, 655, 647, 640, 632, 625, 
617, 610, 603, 596, 588, 581, 574, 567, 561, 554, 547, 540, 533, 527, 520, 514, 507, 501, 494, 488, 482, 476, 469, 463, 457, 451, 445, 439, 434, 428, 422, 416, 
410, 405, 399, 394, 388, 383, 377, 372, 367, 361, 356, 351, 346, 341, 336, 331, 326, 321, 316, 311, 306, 301, 297, 292, 287, 283, 278, 274, 269, 265, 260, 256, 
252, 247, 243, 239, 235, 231, 227, 223, 219, 215, 211, 207, 203, 199, 195, 191, 188, 184, 180, 177, 173, 170, 166, 163, 159, 156, 153, 149, 146, 143, 140, 136, 
133, 130, 127, 124, 121, 118, 115, 112, 109, 106, 104, 101, 98, 95, 93, 90, 87, 85, 82, 80, 77, 75, 72, 70, 68, 65, 63, 61, 59, 56, 54, 52, 
50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 31, 29, 27, 25, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7, 6, 4, 3, 2, 1, 0, 
};

#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;
}



#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;
   static const char *groupNames[4] = { "time", "rate", "vsync", "level" };
   if(_paramGroupIdx < 4u)
      r = groupNames[_paramGroupIdx];
   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;
   static unsigned int groupIndices[NUM_PARAMS] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
   r = groupIndices[_paramIdx];
   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;
   static const char *sectionNames[4] = { "sdcy_1", "sdcy_2", "sdcy_3", "sdcy_4" };
   if(_paramSectionIdx < 4u)
      r = sectionNames[_paramSectionIdx];
   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;
   static unsigned int sectionIndices[NUM_PARAMS] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 };
   r = sectionIndices[_paramIdx];
   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(sinedcy_3_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(sinedcy_3_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(sinedcy_3_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(sinedcy_3_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(sinedcy_3_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(sinedcy_3_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(sinedcy_3_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(sinedcy_3_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;
      case 0: // "c_sdcy_1_amp"
         copySz = Dstplugin_min(_srcNumElements, 256);
         for(unsigned int i = 0u; i < copySz; i++)
            curve_0[i] = (short)(_src[i] * 2048);
         break;
      case 1: // "c_sdcy_2_amp"
         copySz = Dstplugin_min(_srcNumElements, 256);
         for(unsigned int i = 0u; i < copySz; i++)
            curve_1[i] = (short)(_src[i] * 2048);
         break;
      case 2: // "c_sdcy_3_amp"
         copySz = Dstplugin_min(_srcNumElements, 256);
         for(unsigned int i = 0u; i < copySz; i++)
            curve_2[i] = (short)(_src[i] * 2048);
         break;
      case 3: // "c_sdcy_4_amp"
         copySz = Dstplugin_min(_srcNumElements, 256);
         for(unsigned int i = 0u; i < copySz; i++)
            curve_3[i] = (short)(_src[i] * 2048);
         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(sinedcy_3_voice_t);
   if(_sampleRate != voice->sample_rate)
   {
      voice->sr_factor = 12000.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(sinedcy_3_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(sinedcy_3_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(sinedcy_3_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;
   // start=0 end=1 #frames=393216:
   // start=0 end=1 #frames=393216:
   // start=0 end=1 #frames=393216:
   // start=0 end=1 #frames=393216:
   
      voice->tmp7_rmp_step = 2.54313e-06f;
      voice->tmp14_rmp_step = 2.54313e-06f;
      voice->tmp17_rmp_step = 2.54313e-06f;
      voice->tmp20_rmp_step = 2.54313e-06f;
      voice->tmp2_sin_phase = 0.0f;
      voice->tmp6_rmp_cur = 0.0f;
      voice->tmp12_sin_phase = 0.0f;
      voice->tmp13_rmp_cur = 0.0f;
      voice->tmp15_sin_phase = 0.0f;
      voice->tmp16_rmp_cur = 0.0f;
      voice->tmp18_sin_phase = 0.0f;
      voice->tmp19_rmp_cur = 0.0f;
      voice->var_x = 0.0f;
   }
}

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(sinedcy_3_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(sinedcy_3_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(sinedcy_3_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


   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;
   }
   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;
   }

   // 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(sinedcy_3_voice_t);
   ST_PLUGIN_VOICE_SHARED_CAST(sinedcy_3_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=call _calc_sdcy_1
         // ========
         
         // -- mod="call _calc_sdcy_1" dstVar=out
         voice->tmp1/*seq*/ = out;
         // ........ template lane "_calc_sdcy_1" modIdx=0 mod=sin
         
         // -- mod="sin" dstVar=voice->tmp1/*seq*/
         
         // ---- mod="sin" input "freq" seq 1/1
         
         // -- mod="$p_sdcy_1_rate" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = shared->params[PARAM_SDCY_1_RATE];
         
         // -- mod="fma" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = (voice->tmp4/*sin_freq*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = ((int)(voice->tmp4/*sin_freq*/ * 32.0f) / 32.0f);
         voice->tmp3/*sin_speed*/ = voice->note_speed_cur * voice->tmp4/*sin_freq*/;
         
         // ---- mod="sin" input "vsync" seq 1/1
         
         // -- mod="$p_sdcy_1_vsync" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = shared->params[PARAM_SDCY_1_VSYNC];
         
         // -- mod="fma" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = (voice->tmp5/*vsync*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = ((int)(voice->tmp5/*vsync*/ * 4.0f) / 4.0f);
         voice->tmp4/*sin_tmp*/ = (voice->tmp2_sin_phase);
         voice->tmp4/*sin_tmp*/ = voice->tmp4/*sin_tmp*/ * voice->tmp5/*vsync*/;
         voice->tmp4/*sin_tmp*/ = ffrac_s(voice->tmp4/*sin_tmp*/);
         voice->tmp1/*seq*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp4/*sin_tmp*/)&16383u];
         voice->tmp2_sin_phase = ffrac_s(voice->tmp2_sin_phase + voice->tmp3/*sin_speed*/);
         
         // -- mod="rmp" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = voice->tmp6_rmp_cur;
         voice->tmp6_rmp_cur = mathMinf(voice->tmp6_rmp_cur+voice->tmp7_rmp_step, 1);
         
         // -- mod="$p_sdcy_1_timescl" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*seq*/ = voice->tmp3/*seq*/;
         voice->tmp4/*seq*/ = shared->params[PARAM_SDCY_1_TIMESCL];
         
         // -- mod="bts" dstVar=voice->tmp4/*seq*/
         voice->tmp4/*seq*/ = loc_bipolar_to_scale(voice->tmp4/*seq*/, 32.0f, 16.0f);
         voice->tmp3/*seq*/ *= voice->tmp4/*seq*/;
         
         // -- mod="lut" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*lut_f*/ = (voice->tmp3/*seq*/ * 256);
         voice->tmp5/*lut_frac*/ = voice->tmp4/*lut_f*/ - (int)voice->tmp4/*lut_f*/;
         voice->tmp8/*lut_idx_a*/ = (int)voice->tmp4/*lut_f*/;
         if(voice->tmp8/*lut_idx_a*/ < 0)
         {
            voice->tmp8/*lut_idx_a*/ = 0;
            voice->tmp9/*lut_idx_b*/ = 0;
            voice->tmp5/*lut_frac*/ = 0.0f;
         }
         else if(voice->tmp8/*lut_idx_a*/ > 255)
         {
            voice->tmp8/*lut_idx_a*/ = 255;
            voice->tmp9/*lut_idx_b*/ = 255;
         }
         else
         {
            voice->tmp9/*lut_idx_b*/ = voice->tmp8/*lut_idx_a*/ + 1;
            if(voice->tmp9/*lut_idx_b*/ > 255)
               voice->tmp9/*lut_idx_b*/ = 255;
         }
         voice->tmp10/*lut_a*/ = curve_0[(unsigned int)voice->tmp8/*lut_idx_a*/] * (1.0f / 2048);
         voice->tmp11/*lut_b*/ = curve_0[(unsigned int)voice->tmp9/*lut_idx_b*/] * (1.0f / 2048);
         voice->tmp3/*seq*/ = voice->tmp10/*lut_a*/ + (voice->tmp11/*lut_b*/ - voice->tmp10/*lut_a*/) * voice->tmp5/*lut_frac*/;
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         
         // -- mod="$p_sdcy_1_level" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = shared->params[PARAM_SDCY_1_LEVEL];
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         out += voice->tmp1/*seq*/;
         
         // -- mod="call _calc_sdcy_2" dstVar=out
         voice->tmp1/*seq*/ = out;
         // ........ template lane "_calc_sdcy_2" modIdx=0 mod=sin
         
         // -- mod="sin" dstVar=voice->tmp1/*seq*/
         
         // ---- mod="sin" input "freq" seq 1/1
         
         // -- mod="$p_sdcy_2_rate" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = shared->params[PARAM_SDCY_2_RATE];
         
         // -- mod="fma" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = (voice->tmp4/*sin_freq*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = ((int)(voice->tmp4/*sin_freq*/ * 32.0f) / 32.0f);
         voice->tmp3/*sin_speed*/ = voice->note_speed_cur * voice->tmp4/*sin_freq*/;
         
         // ---- mod="sin" input "vsync" seq 1/1
         
         // -- mod="$p_sdcy_2_vsync" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = shared->params[PARAM_SDCY_2_VSYNC];
         
         // -- mod="fma" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = (voice->tmp5/*vsync*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = ((int)(voice->tmp5/*vsync*/ * 4.0f) / 4.0f);
         voice->tmp4/*sin_tmp*/ = (voice->tmp12_sin_phase);
         voice->tmp4/*sin_tmp*/ = voice->tmp4/*sin_tmp*/ * voice->tmp5/*vsync*/;
         voice->tmp4/*sin_tmp*/ = ffrac_s(voice->tmp4/*sin_tmp*/);
         voice->tmp1/*seq*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp4/*sin_tmp*/)&16383u];
         voice->tmp12_sin_phase = ffrac_s(voice->tmp12_sin_phase + voice->tmp3/*sin_speed*/);
         
         // -- mod="rmp" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = voice->tmp13_rmp_cur;
         voice->tmp13_rmp_cur = mathMinf(voice->tmp13_rmp_cur+voice->tmp14_rmp_step, 1);
         
         // -- mod="$p_sdcy_2_timescl" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*seq*/ = voice->tmp3/*seq*/;
         voice->tmp4/*seq*/ = shared->params[PARAM_SDCY_2_TIMESCL];
         
         // -- mod="bts" dstVar=voice->tmp4/*seq*/
         voice->tmp4/*seq*/ = loc_bipolar_to_scale(voice->tmp4/*seq*/, 32.0f, 16.0f);
         voice->tmp3/*seq*/ *= voice->tmp4/*seq*/;
         
         // -- mod="lut" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*lut_f*/ = (voice->tmp3/*seq*/ * 256);
         voice->tmp5/*lut_frac*/ = voice->tmp4/*lut_f*/ - (int)voice->tmp4/*lut_f*/;
         voice->tmp8/*lut_idx_a*/ = (int)voice->tmp4/*lut_f*/;
         if(voice->tmp8/*lut_idx_a*/ < 0)
         {
            voice->tmp8/*lut_idx_a*/ = 0;
            voice->tmp9/*lut_idx_b*/ = 0;
            voice->tmp5/*lut_frac*/ = 0.0f;
         }
         else if(voice->tmp8/*lut_idx_a*/ > 255)
         {
            voice->tmp8/*lut_idx_a*/ = 255;
            voice->tmp9/*lut_idx_b*/ = 255;
         }
         else
         {
            voice->tmp9/*lut_idx_b*/ = voice->tmp8/*lut_idx_a*/ + 1;
            if(voice->tmp9/*lut_idx_b*/ > 255)
               voice->tmp9/*lut_idx_b*/ = 255;
         }
         voice->tmp10/*lut_a*/ = curve_1[(unsigned int)voice->tmp8/*lut_idx_a*/] * (1.0f / 2048);
         voice->tmp11/*lut_b*/ = curve_1[(unsigned int)voice->tmp9/*lut_idx_b*/] * (1.0f / 2048);
         voice->tmp3/*seq*/ = voice->tmp10/*lut_a*/ + (voice->tmp11/*lut_b*/ - voice->tmp10/*lut_a*/) * voice->tmp5/*lut_frac*/;
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         
         // -- mod="$p_sdcy_2_level" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = shared->params[PARAM_SDCY_2_LEVEL];
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         out += voice->tmp1/*seq*/;
         
         // -- mod="call _calc_sdcy_3" dstVar=out
         voice->tmp1/*seq*/ = out;
         // ........ template lane "_calc_sdcy_3" modIdx=0 mod=sin
         
         // -- mod="sin" dstVar=voice->tmp1/*seq*/
         
         // ---- mod="sin" input "freq" seq 1/1
         
         // -- mod="$p_sdcy_3_rate" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = shared->params[PARAM_SDCY_3_RATE];
         
         // -- mod="fma" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = (voice->tmp4/*sin_freq*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = ((int)(voice->tmp4/*sin_freq*/ * 32.0f) / 32.0f);
         voice->tmp3/*sin_speed*/ = voice->note_speed_cur * voice->tmp4/*sin_freq*/;
         
         // ---- mod="sin" input "vsync" seq 1/1
         
         // -- mod="$p_sdcy_3_vsync" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = shared->params[PARAM_SDCY_3_VSYNC];
         
         // -- mod="fma" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = (voice->tmp5/*vsync*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = ((int)(voice->tmp5/*vsync*/ * 4.0f) / 4.0f);
         voice->tmp4/*sin_tmp*/ = (voice->tmp15_sin_phase);
         voice->tmp4/*sin_tmp*/ = voice->tmp4/*sin_tmp*/ * voice->tmp5/*vsync*/;
         voice->tmp4/*sin_tmp*/ = ffrac_s(voice->tmp4/*sin_tmp*/);
         voice->tmp1/*seq*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp4/*sin_tmp*/)&16383u];
         voice->tmp15_sin_phase = ffrac_s(voice->tmp15_sin_phase + voice->tmp3/*sin_speed*/);
         
         // -- mod="rmp" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = voice->tmp16_rmp_cur;
         voice->tmp16_rmp_cur = mathMinf(voice->tmp16_rmp_cur+voice->tmp17_rmp_step, 1);
         
         // -- mod="$p_sdcy_3_timescl" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*seq*/ = voice->tmp3/*seq*/;
         voice->tmp4/*seq*/ = shared->params[PARAM_SDCY_3_TIMESCL];
         
         // -- mod="bts" dstVar=voice->tmp4/*seq*/
         voice->tmp4/*seq*/ = loc_bipolar_to_scale(voice->tmp4/*seq*/, 32.0f, 16.0f);
         voice->tmp3/*seq*/ *= voice->tmp4/*seq*/;
         
         // -- mod="lut" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*lut_f*/ = (voice->tmp3/*seq*/ * 256);
         voice->tmp5/*lut_frac*/ = voice->tmp4/*lut_f*/ - (int)voice->tmp4/*lut_f*/;
         voice->tmp8/*lut_idx_a*/ = (int)voice->tmp4/*lut_f*/;
         if(voice->tmp8/*lut_idx_a*/ < 0)
         {
            voice->tmp8/*lut_idx_a*/ = 0;
            voice->tmp9/*lut_idx_b*/ = 0;
            voice->tmp5/*lut_frac*/ = 0.0f;
         }
         else if(voice->tmp8/*lut_idx_a*/ > 255)
         {
            voice->tmp8/*lut_idx_a*/ = 255;
            voice->tmp9/*lut_idx_b*/ = 255;
         }
         else
         {
            voice->tmp9/*lut_idx_b*/ = voice->tmp8/*lut_idx_a*/ + 1;
            if(voice->tmp9/*lut_idx_b*/ > 255)
               voice->tmp9/*lut_idx_b*/ = 255;
         }
         voice->tmp10/*lut_a*/ = curve_2[(unsigned int)voice->tmp8/*lut_idx_a*/] * (1.0f / 2048);
         voice->tmp11/*lut_b*/ = curve_2[(unsigned int)voice->tmp9/*lut_idx_b*/] * (1.0f / 2048);
         voice->tmp3/*seq*/ = voice->tmp10/*lut_a*/ + (voice->tmp11/*lut_b*/ - voice->tmp10/*lut_a*/) * voice->tmp5/*lut_frac*/;
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         
         // -- mod="$p_sdcy_3_level" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = shared->params[PARAM_SDCY_3_LEVEL];
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         out += voice->tmp1/*seq*/;
         
         // -- mod="call _calc_sdcy_4" dstVar=out
         voice->tmp1/*seq*/ = out;
         // ........ template lane "_calc_sdcy_4" modIdx=0 mod=sin
         
         // -- mod="sin" dstVar=voice->tmp1/*seq*/
         
         // ---- mod="sin" input "freq" seq 1/1
         
         // -- mod="$p_sdcy_4_rate" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = shared->params[PARAM_SDCY_4_RATE];
         
         // -- mod="fma" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = (voice->tmp4/*sin_freq*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp4/*sin_freq*/
         voice->tmp4/*sin_freq*/ = ((int)(voice->tmp4/*sin_freq*/ * 32.0f) / 32.0f);
         voice->tmp3/*sin_speed*/ = voice->note_speed_cur * voice->tmp4/*sin_freq*/;
         
         // ---- mod="sin" input "vsync" seq 1/1
         
         // -- mod="$p_sdcy_4_vsync" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = shared->params[PARAM_SDCY_4_VSYNC];
         
         // -- mod="fma" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = (voice->tmp5/*vsync*/ * 15.0f) + 1.0f;
         
         // -- mod="qua" dstVar=voice->tmp5/*vsync*/
         voice->tmp5/*vsync*/ = ((int)(voice->tmp5/*vsync*/ * 4.0f) / 4.0f);
         voice->tmp4/*sin_tmp*/ = (voice->tmp18_sin_phase);
         voice->tmp4/*sin_tmp*/ = voice->tmp4/*sin_tmp*/ * voice->tmp5/*vsync*/;
         voice->tmp4/*sin_tmp*/ = ffrac_s(voice->tmp4/*sin_tmp*/);
         voice->tmp1/*seq*/ = cycle_sine_tbl_f[(unsigned short)(16384 * voice->tmp4/*sin_tmp*/)&16383u];
         voice->tmp18_sin_phase = ffrac_s(voice->tmp18_sin_phase + voice->tmp3/*sin_speed*/);
         
         // -- mod="rmp" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = voice->tmp19_rmp_cur;
         voice->tmp19_rmp_cur = mathMinf(voice->tmp19_rmp_cur+voice->tmp20_rmp_step, 1);
         
         // -- mod="$p_sdcy_4_timescl" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*seq*/ = voice->tmp3/*seq*/;
         voice->tmp4/*seq*/ = shared->params[PARAM_SDCY_4_TIMESCL];
         
         // -- mod="bts" dstVar=voice->tmp4/*seq*/
         voice->tmp4/*seq*/ = loc_bipolar_to_scale(voice->tmp4/*seq*/, 32.0f, 16.0f);
         voice->tmp3/*seq*/ *= voice->tmp4/*seq*/;
         
         // -- mod="lut" dstVar=voice->tmp3/*seq*/
         voice->tmp4/*lut_f*/ = (voice->tmp3/*seq*/ * 256);
         voice->tmp5/*lut_frac*/ = voice->tmp4/*lut_f*/ - (int)voice->tmp4/*lut_f*/;
         voice->tmp8/*lut_idx_a*/ = (int)voice->tmp4/*lut_f*/;
         if(voice->tmp8/*lut_idx_a*/ < 0)
         {
            voice->tmp8/*lut_idx_a*/ = 0;
            voice->tmp9/*lut_idx_b*/ = 0;
            voice->tmp5/*lut_frac*/ = 0.0f;
         }
         else if(voice->tmp8/*lut_idx_a*/ > 255)
         {
            voice->tmp8/*lut_idx_a*/ = 255;
            voice->tmp9/*lut_idx_b*/ = 255;
         }
         else
         {
            voice->tmp9/*lut_idx_b*/ = voice->tmp8/*lut_idx_a*/ + 1;
            if(voice->tmp9/*lut_idx_b*/ > 255)
               voice->tmp9/*lut_idx_b*/ = 255;
         }
         voice->tmp10/*lut_a*/ = curve_3[(unsigned int)voice->tmp8/*lut_idx_a*/] * (1.0f / 2048);
         voice->tmp11/*lut_b*/ = curve_3[(unsigned int)voice->tmp9/*lut_idx_b*/] * (1.0f / 2048);
         voice->tmp3/*seq*/ = voice->tmp10/*lut_a*/ + (voice->tmp11/*lut_b*/ - voice->tmp10/*lut_a*/) * voice->tmp5/*lut_frac*/;
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         
         // -- mod="$p_sdcy_4_level" dstVar=voice->tmp1/*seq*/
         voice->tmp3/*seq*/ = voice->tmp1/*seq*/;
         voice->tmp3/*seq*/ = shared->params[PARAM_SDCY_4_LEVEL];
         voice->tmp1/*seq*/ *= voice->tmp3/*seq*/;
         out += voice->tmp1/*seq*/;
         
         // -- mod="$P_AMP" dstVar=out
         out *= 1.0f;
         
         // -- mod="clp" dstVar=out
         if(out > 0.999f) out = 0.999f;
         else if(out < -0.999f) out = -0.999f;
         
   
         /* 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;
      }
#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) {
   sinedcy_3_shared_t *ret = (sinedcy_3_shared_t *)malloc(sizeof(sinedcy_3_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) {
   sinedcy_3_voice_t *voice = (sinedcy_3_voice_t *)malloc(sizeof(sinedcy_3_voice_t));
   if(NULL != voice)
   {
      memset((void*)voice, 0, sizeof(*voice));
      voice->base.info = _info;
   }
   return &voice->base;
}

static void ST_PLUGIN_API loc_voice_delete(st_plugin_voice_t *_voice) {
   ST_PLUGIN_VOICE_CAST(sinedcy_3_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 *sinedcy_3_init(void) {
   sinedcy_3_info_t *ret = (sinedcy_3_info_t *)malloc(sizeof(sinedcy_3_info_t));

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

      ret->base.api_version = ST_PLUGIN_API_VERSION;
      ret->base.id          = "sinedcy_3_0x01a15f24";  // unique id. don't change this in future builds.
      ret->base.author      = "";
      ret->base.name        = "sinedcy_3";
      ret->base.short_name  = "sinedcy_3";
      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 sinedcy_3_init();
   }
   return NULL;
}
#endif // STFX_SKIP_MAIN_INIT

} // extern "C"
