@@ 37,18 37,18 @@
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 2 ;
- lv2:symbol "gain" ;
- lv2:name "Gain" ;
+ lv2:symbol "dist" ;
+ lv2:name "Distortion" ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
- lv2:maximum 10.0 ;
+ lv2:maximum 100.0 ;
] , [
a lv2:InputPort ,
lv2:ControlPort ;
lv2:index 3 ;
- lv2:symbol "offset" ;
- lv2:name "Offset" ;
+ lv2:symbol "asym" ;
+ lv2:name "Asymmetry" ;
lv2:default 0.0 ;
lv2:minimum 0.0 ;
- lv2:maximum 0.5 ;
+ lv2:maximum 100.0 ;
] .
@@ 10,11 10,12 @@
typedef enum {
INPUT = 0,
OUTPUT = 1,
- GAIN = 2,
- OFFSET = 3,
+ DIST = 2,
+ ASYM = 3,
} PortIndex;
typedef struct {
+ const float r;
float prev_x;
float prev_y;
} DCFilter;
@@ 22,22 23,58 @@ typedef struct {
typedef struct {
const float *input;
float *output;
- const float *gain;
- const float *offset;
+ const float *dist;
+ const float *asym;
+ DCFilter dc_filter_rms;
DCFilter dc_filter;
} Kantan;
static float blockdc(const float x, DCFilter* filter)
{
+ const float r = filter->r;
const float prev_x = filter->prev_x;
const float prev_y = filter->prev_y;
- const float y = x - prev_x + 0.995f*prev_y;
+ const float y = x - prev_x + r*prev_y;
filter->prev_x = x;
filter->prev_y = y;
return y;
}
+static float distort(const float x, const float d, const float a)
+{
+ float k;
+ if (x > 0.f) {
+ k = d*(1.f - a * 0.01);
+ } else {
+ k = d;
+ }
+
+ float y;
+ if (k < 0.01f) {
+ y = x;
+ } else {
+ y = 1 / k * atanf(k * x);
+ }
+
+ return y;
+}
+
+static float rms(const float d, const float a, DCFilter *filter)
+{
+ float accm = 0;
+ for (uint32_t i = 0; i < 49; i++) {
+ const float x = i / 48.f;
+ const float y = distort(0.1f * sin(2.f * M_PI * x), d, a);
+ const float y_nodc = blockdc(y, filter);
+ accm += y_nodc*y_nodc;
+ }
+
+ const float result = sqrtf(accm / 49);
+
+ return result;
+}
+
static LV2_Handle instantiate(const LV2_Descriptor * descriptor,
double rate,
const char *bundle_path,
@@ 46,7 83,12 @@ static LV2_Handle instantiate(const LV2_Descriptor * descriptor,
Kantan *kantan = (Kantan *) calloc(1, sizeof(Kantan));
- DCFilter dc_filter_init = {0,0};
+ const float wn = M_PI * 10.f / rate;
+ const float b0 = 1.f / (1.f + wn);
+ const float p = (1.f - wn) * b0;
+
+ DCFilter dc_filter_init = {p,0.f,0.f};
+ memcpy(&kantan->dc_filter_rms, &dc_filter_init, sizeof(DCFilter));
memcpy(&kantan->dc_filter, &dc_filter_init, sizeof(DCFilter));
return (LV2_Handle) kantan;
@@ 63,11 105,11 @@ static void connect_port(LV2_Handle instance, uint32_t port, void *data)
case OUTPUT:
kantan->output = (float *)data;
break;
- case GAIN:
- kantan->gain = (const float *)data;
+ case DIST:
+ kantan->dist = (const float *)data;
break;
- case OFFSET:
- kantan->offset = (const float *)data;
+ case ASYM:
+ kantan->asym = (const float *)data;
break;
}
}
@@ 82,18 124,16 @@ static void run(LV2_Handle instance, uint32_t n_samples)
const float *const input = kantan->input;
float *const output = kantan->output;
- const float gain = *(kantan->gain);
- const float offset = *(kantan->offset);
+ const float dist = *(kantan->dist);
+ const float asym = *(kantan->asym);
+ DCFilter *dc_filter_rms = &kantan->dc_filter_rms;
DCFilter* dc_filter = &kantan->dc_filter;
- const float g_pre = pow (10.0, (gain * 0.5f));
- const float g_post = 0.1f / atan(0.1f * g_pre);
+ const float rms_ref = 0.1f / sqrtf(2);
+ const float g_post = rms_ref / rms(dist, asym, dc_filter_rms);
- /**
- distortion using sigmoid function: 2 / pi * arctan (pi / 2 * x)
- */
for (uint32_t pos = 0; pos < n_samples; pos++) {
- output[pos] = blockdc(atan((input[pos] * g_pre + offset)), dc_filter) * g_post;
+ output[pos] = blockdc(distort(input[pos], dist, asym), dc_filter) * g_post;
}
}