Osc Bnk I

Paraphonic Osc Bank inspired by existing string machine waveforms
Author: Smashed Transistors (Smashed Transistors)
License: LGPL
Github: tiar/oscBnk/Osc_Bnk_I.axo

Inlets

frac32.bipolar lfo1

frac32.bipolar lfo2

frac32.bipolar lfo3

Outlets

frac32buffer.bipolar out

Parameters

frac32.s.map.kdecaytime.exp Attack

frac32.s.map.kdecaytime.exp Release

int32 Max Key

int32 Min Key

Attributes

combo type

combo algo

Declaration
float dp[128]; // delta phase

float p[128];
float coef1[128]; // for gain compensation in DPW algo
float gates[128];
float env[128];
float z[BUFSIZE];
float z1, z2, fz;
float lfo[7];

const float type_l[11] = {0.0f,  0.0f, 0.2f, 0.2f, 0.75f, 0.5f,
                          0.25f, 1.0f, 0.0f, 0.0f, -1.0f};
const float type_r[11] = {0.0f,  0.25f, 0.25f, 0.5f,  0.25f, 0.5f,
                          0.75f, 0.5f,  1.0f,  0.11f, 0.5f};

const float l = type_l[attr_type];
const float r = type_r[attr_type];

const float a = (l - 1) / r;
const float K = -0.5f * (l + 1) * r;
const float b = 1.0f + K;
const float A = 0.5 * (l - 1) / r;
const float C = -((1.0f / 3) * A * r * r * r + 0.5 * r * r - 0.5f * K + K * r);
const float C_K = C - K;
Init
// _____________________________________________________________________
int i, j;
for (i = 0; i < 128; i++) {
  p[i] = gates[i] = env[i] = 0.0f;
}
z1 = z2 = fz = 0.0f;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
dp[0] = 1.7032914407591056E-4f;
dp[1] = 1.804574420422344E-4f;
dp[2] = 1.9118799994622893E-4f;
dp[3] = 2.0255663002739644E-4f;
dp[4] = 2.1460127403181634E-4f;
dp[5] = 2.2736212983919527E-4f;
dp[6] = 2.4088178561955362E-4f;
dp[7] = 2.5520536196728464E-4f;
dp[8] = 2.703806624869435E-4f;
dp[9] = 2.8645833333333333E-4f;
dp[10] = 3.0349203223833975E-4f;
dp[11] = 3.2153860758862255E-4f;
for (i = 12; i <= 127; i++) {
  dp[i] = 2 * dp[i - 12];
  if (attr_algo == 3) {
    coef1[i] = ((1 << 24) / 127.0f) / (dp[i]);
  } else if (attr_algo == 2) {
    coef1[i] = ((1 << 25) / 127.0f) / (dp[i]);
  } else {
    coef1[i] = ((1 << 25) / 127.0f);
  }
}
Control Rate
int minKey = param_Min_space_Key < param_Max_space_Key ? param_Min_space_Key
                                                       : param_Max_space_Key;
int maxKey = param_Min_space_Key >= param_Max_space_Key ? param_Min_space_Key
                                                        : param_Max_space_Key;
float attack = 1.0f - param_Attack / ((float)((1UL << 31) - 1));
float release = 1.0f - param_Release / ((float)((1UL << 31) - 1));
// attack = attack>1?1:attack;
// release = release>1?1:release;
// _____________________________________________________________________
int i, j;
for (j = 0; j < BUFSIZE; j++) {
  z[j] = 0;
}
lfo[0] = 1.0f + inlet_lfo1 * (0.03f / (1 << 27));
lfo[1] = 1.0f - inlet_lfo1 * (0.02f / (1 << 27));
lfo[2] = 1.0f + inlet_lfo1 * (0.02f / (1 << 27));
lfo[3] = 1.0f - inlet_lfo2 * (0.03f / (1 << 27));
lfo[4] = 1.0f + inlet_lfo2 * (0.02f / (1 << 27));
lfo[5] = 1.0f + inlet_lfo3 * (0.015f / (1 << 27));
lfo[6] = 1.0f - inlet_lfo3 * (0.02f / (1 << 27));

// DPW anti ali
if (attr_algo == 2) {
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  int i7 = minKey % 7;
  for (i = minKey; i <= maxKey; i++) {
    float _env = env[i];
    env[i] += (gates[i] > env[i] ? attack : release) * (gates[i] - env[i]);
    // if(env[i]<0.01f) continue;
    float denv = (env[i] - _env) * (1.0f / BUFSIZE);
    float _dp = dp[i] * lfo[i7];
    i7++;
    if (i7 >= 7)
      i7 = 0;
    float _p = p[i];
    for (j = 0; j < BUFSIZE; j++) {
      _p += _dp;
      // branchless code, more cpu but constant 72% for 61 notes
      _p -= (_p > 1);
      z[j] +=
          (K * _p + C_K + (_p < r) * (K + _p * (1 + A * _p))) * (_env += denv);
      /*
       // code with branching => less cpu but cpu variations => glitches
       // 74% for 61+24 notes
        if(_p>1) _p--;
        float tmp;
        if(_p>r)
          tmp = K * _p + C_K;
        else
          tmp = C + _p * (1+K + A * _p);
        z[j] += _env * tmp;*/
    }
    p[i] = _p;
  }
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  for (j = 0; j < BUFSIZE; j++) {
    outlet_out[j] = (int32_t)(z[j] - z1);
    z1 = z[j];
  }
} else

{
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  int i7 = minKey % 7;
  for (i = minKey; i <= maxKey; i++) {
    float _env = env[i];
    env[i] += (gates[i] > env[i] ? attack : release) * (gates[i] - env[i]);
    float denv = (env[i] - _env) * (1.0f / BUFSIZE);
    float _p = p[i];
    float _dp = dp[i] * lfo[i7];
    i7++;
    if (i7 >= 7)
      i7 = 0;
    for (j = 0; j < BUFSIZE; j++) {
      _env += denv;
      _p += _dp;
      _p -= (_p > 1);
      z[j] += _env * (K + (_p < r) * (1 + a * _p));
    }
    p[i] = _p;
  }
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  for (j = 0; j < BUFSIZE; j++) {
    outlet_out[j] = (int32_t)(z[j]);
  }
}
Midi Handler
if (status == MIDI_NOTE_ON + attr_midichannel) {
  gates[data1 & 0x7F] = data2 * coef1[data1];
} else if (status == MIDI_NOTE_OFF + attr_midichannel) {
  gates[data1 & 0x7F] = 0;
} else if ((status == attr_midichannel + MIDI_CONTROL_CHANGE) &&
           (data1 == MIDI_C_ALL_NOTES_OFF)) {
  for (int i = 0; i < 128; i++)
    gates[data1 & 0x7F] = 0;
}

Privacy

© 2024 Zrna Research