tube: add parameters with smoothing
This commit is contained in:
parent
d20bea5fa5
commit
1550230dc5
1 changed files with 95 additions and 13 deletions
108
crap/tube.h
108
crap/tube.h
|
@ -1,22 +1,50 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "param.h"
|
||||||
|
|
||||||
#define ID 0x50F7BA11
|
#define ID 0x50F7BA11
|
||||||
#define LABEL "crap_tube"
|
#define LABEL "crap_tube"
|
||||||
#define NAME "crap Tube Distortion"
|
#define NAME "crap Tube Distortion"
|
||||||
#define AUTHOR "Connor Olding"
|
#define AUTHOR "Connor Olding"
|
||||||
#define COPYRIGHT "MIT"
|
#define COPYRIGHT "MIT"
|
||||||
#define PARAMETERS 0
|
#define PARAMETERS 2
|
||||||
|
|
||||||
#define HIST_SIZE 36
|
#define HIST_SIZE 36
|
||||||
#define HIST_SIZE_2 18
|
#define HIST_SIZE_2 18
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double desired, actual, speed;
|
||||||
|
int log; // use multiplication instead of addition for speed
|
||||||
|
} smoothval;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
double history_L[HIST_SIZE];
|
double history_L[HIST_SIZE];
|
||||||
double history_R[HIST_SIZE];
|
double history_R[HIST_SIZE];
|
||||||
|
smoothval drive, wet;
|
||||||
} personal;
|
} personal;
|
||||||
|
|
||||||
|
static double
|
||||||
|
smooth(smoothval *val)
|
||||||
|
{
|
||||||
|
double a = val->actual;
|
||||||
|
double d = val->desired;
|
||||||
|
double s = val->speed;
|
||||||
|
double l = val->log;
|
||||||
|
if (a < d) {
|
||||||
|
if (l) a *= s;
|
||||||
|
else a += s;
|
||||||
|
if (a > d) a = d;
|
||||||
|
} else if (a > d) {
|
||||||
|
if (l) a /= s;
|
||||||
|
else a -= s;
|
||||||
|
if (a < d) a = d;
|
||||||
|
}
|
||||||
|
val->actual = a;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
distort(double x)
|
distort(double x)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +67,8 @@ static double
|
||||||
upsample(double h[HIST_SIZE_2], double x)
|
upsample(double h[HIST_SIZE_2], double x)
|
||||||
{
|
{
|
||||||
double y;
|
double y;
|
||||||
|
// -3 at 18600/44100/2, -96 stopband
|
||||||
|
// designed with <https://coewww.rutgers.edu/~orfanidi/hpeq/>
|
||||||
LOWPASS(0, +0.71327159,+0.00688573,-0.45391337,+0.88734229);
|
LOWPASS(0, +0.71327159,+0.00688573,-0.45391337,+0.88734229);
|
||||||
LOWPASS(1, +0.63347126,+0.05572752,-0.36946634,+0.69213639);
|
LOWPASS(1, +0.63347126,+0.05572752,-0.36946634,+0.69213639);
|
||||||
LOWPASS(2, +0.55963645,+0.13990391,-0.26487901,+0.52405582);
|
LOWPASS(2, +0.55963645,+0.13990391,-0.26487901,+0.52405582);
|
||||||
|
@ -55,6 +85,8 @@ static double
|
||||||
downsample(double h[HIST_SIZE_2], double x)
|
downsample(double h[HIST_SIZE_2], double x)
|
||||||
{
|
{
|
||||||
double y;
|
double y;
|
||||||
|
// -3 at 17544/44100/4, -96 stopband
|
||||||
|
// same idea as upsample()
|
||||||
LOWPASS(0, +0.62136966,-0.87573986,-1.56336581,+0.93036527);
|
LOWPASS(0, +0.62136966,-0.87573986,-1.56336581,+0.93036527);
|
||||||
LOWPASS(1, +0.56540370,-0.77393348,-1.44258778,+0.79946170);
|
LOWPASS(1, +0.56540370,-0.77393348,-1.44258778,+0.79946170);
|
||||||
LOWPASS(2, +0.49824084,-0.63630306,-1.31114921,+0.67132784);
|
LOWPASS(2, +0.49824084,-0.63630306,-1.31114921,+0.67132784);
|
||||||
|
@ -68,14 +100,28 @@ downsample(double h[HIST_SIZE_2], double x)
|
||||||
}
|
}
|
||||||
|
|
||||||
static double
|
static double
|
||||||
process_one(double h[HIST_SIZE], double x)
|
process_one(double x, double drive, double wet)
|
||||||
{
|
{
|
||||||
|
return (distort(x*drive)/drive*0.79 - x)*wet + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
oversample(personal *data, double x, int right)
|
||||||
|
{
|
||||||
|
double *h0 = (!right) ? data->history_L : data->history_R;
|
||||||
|
double *h1 = h0 + HIST_SIZE_2;
|
||||||
double y;
|
double y;
|
||||||
y = downsample(h + HIST_SIZE_2, distort(4*upsample(h, x)));
|
|
||||||
downsample(h + HIST_SIZE_2, distort(4*upsample(h, 0)));
|
#define doit(SAMP) \
|
||||||
downsample(h + HIST_SIZE_2, distort(4*upsample(h, 0)));
|
downsample(h1, process_one(4*upsample(h0, SAMP), \
|
||||||
downsample(h + HIST_SIZE_2, distort(4*upsample(h, 0)));
|
smooth(&data->drive), smooth(&data->wet)))
|
||||||
return y*0.71;
|
y = doit(x);
|
||||||
|
doit(0);
|
||||||
|
doit(0);
|
||||||
|
doit(0);
|
||||||
|
#undef doit
|
||||||
|
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -86,8 +132,8 @@ process(personal *data,
|
||||||
{
|
{
|
||||||
disable_denormals();
|
disable_denormals();
|
||||||
for (unsigned long pos = 0; pos < count; pos++) {
|
for (unsigned long pos = 0; pos < count; pos++) {
|
||||||
out_L[pos] = process_one(data->history_L, in_L[pos]);
|
out_L[pos] = oversample(data, in_L[pos], 0);
|
||||||
out_R[pos] = process_one(data->history_R, in_R[pos]);
|
out_R[pos] = oversample(data, in_R[pos], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +145,8 @@ process_double(personal *data,
|
||||||
{
|
{
|
||||||
disable_denormals();
|
disable_denormals();
|
||||||
for (unsigned long pos = 0; pos < count; pos++) {
|
for (unsigned long pos = 0; pos < count; pos++) {
|
||||||
out_L[pos] = process_one(data->history_L, in_L[pos]);
|
out_L[pos] = oversample(data, in_L[pos], 0);
|
||||||
out_R[pos] = process_one(data->history_R, in_R[pos]);
|
out_R[pos] = oversample(data, in_R[pos], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,14 +164,50 @@ pause(personal *data)
|
||||||
static void
|
static void
|
||||||
construct(personal *data)
|
construct(personal *data)
|
||||||
{
|
{
|
||||||
resume(data);
|
memset(data, 0, sizeof(personal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
construct_params(param *params)
|
||||||
|
{
|
||||||
|
sprintf(params[0].name, "Drive");
|
||||||
|
params[0].min = -30;
|
||||||
|
params[0].max = 15;
|
||||||
|
params[0].scale = SCALE_DB;
|
||||||
|
params[0].def = DEFAULT_0;
|
||||||
|
|
||||||
|
sprintf(params[1].name, "Wetness");
|
||||||
|
params[1].min = 0;
|
||||||
|
params[1].max = 1;
|
||||||
|
params[1].scale = SCALE_FLOAT;
|
||||||
|
params[1].def = DEFAULT_1;
|
||||||
|
|
||||||
|
param_reset(¶ms[0]);
|
||||||
|
param_reset(¶ms[1]);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
destruct(personal *data)
|
destruct(personal *data)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
adjust(personal *data, unsigned long fs)
|
adjust(personal *data, param *params, unsigned long fs_long)
|
||||||
{
|
{
|
||||||
resume(data);
|
resume(data);
|
||||||
|
double fs = fs_long;
|
||||||
|
data->drive.desired = DB2LIN(params[0].value);
|
||||||
|
data->wet.desired = params[1].value;
|
||||||
|
data->drive.actual = data->drive.desired;
|
||||||
|
data->wet.actual = data->wet.desired;
|
||||||
|
data->drive.speed = 1 + 20/fs/4;
|
||||||
|
data->wet.speed = 20/fs/4;
|
||||||
|
data->drive.log = 1;
|
||||||
|
data->wet.log = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
adjust_one(personal *data, param *params, unsigned int index)
|
||||||
|
{
|
||||||
|
data->drive.desired = DB2LIN(params[0].value);
|
||||||
|
data->wet.desired = params[1].value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue