1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
/* Copyright (c) 2002-2005 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
#include <math.h>
#include "m_pd.h"
#include "common/fitter.h"
#if defined(_WIN32) || defined(__APPLE__)
#define logf log
#define expf exp
#endif
#define LINEDRIVE_MININPUT .5 /* CHECKED */
#define LINEDRIVE_MINCURVE 1. /* CHECKED */
#define LINEDRIVE_INPUTEPSILON 1e-19f
#define LINEDRIVE_CURVEEPSILON 1e-19f
typedef struct _linedrive
{
t_object x_ob;
t_float x_usermaxin;
t_float x_usermaxout;
t_float x_usercurve;
t_float x_maxin;
t_float x_maxout;
t_float x_expcoef;
t_float x_lincoef;
int x_islinear;
int x_iscompatible;
t_atom x_outvec[2];
} t_linedrive;
static t_class *linedrive_class;
static void linedrive_float(t_linedrive *x, t_floatarg f)
{
t_float outval;
if (x->x_iscompatible)
{
if (f < LINEDRIVE_MININPUT) /* CHECKED */
outval = 0.;
else if (f >= x->x_maxin) /* CHECKED */
outval = x->x_maxin;
else
outval = expf((f - x->x_maxin) * x->x_expcoef) * x->x_maxout;
}
else
{
if (x->x_islinear)
outval = x->x_maxout + (f - x->x_maxin) * x->x_lincoef;
else if (f < -LINEDRIVE_INPUTEPSILON)
outval = -expf((-f - x->x_maxin) * x->x_expcoef) * x->x_maxout;
else if (f > LINEDRIVE_INPUTEPSILON)
outval = expf((f - x->x_maxin) * x->x_expcoef) * x->x_maxout;
else
outval = 0.;
}
SETFLOAT(x->x_outvec, outval);
outlet_list(((t_object *)x)->ob_outlet, 0, 2, x->x_outvec);
}
static void linedrive_calculate(t_linedrive *x)
{
t_float maxin = x->x_usermaxin;
t_float maxout = x->x_usermaxout;
t_float curve = x->x_usercurve;
if (x->x_iscompatible = fittermax_get())
{
/* CHECKED */
x->x_maxin = (maxin > LINEDRIVE_MININPUT ? maxin : LINEDRIVE_MININPUT);
/* CHECKED */
x->x_expcoef = (curve > LINEDRIVE_MINCURVE ? logf(curve) : 0.);
x->x_lincoef = 0.;
x->x_islinear = 0;
}
else
{
if (maxin >= -LINEDRIVE_INPUTEPSILON && maxin <= LINEDRIVE_INPUTEPSILON)
{
x->x_maxin = 0.;
x->x_expcoef = 0.;
x->x_lincoef = 0.;
x->x_islinear = 1;
}
else if (curve >= (1. - LINEDRIVE_CURVEEPSILON) &&
curve <= (1. + LINEDRIVE_CURVEEPSILON))
{
x->x_maxin = maxin;
x->x_expcoef = 0.;
x->x_lincoef = maxout / maxin;
x->x_islinear = 1;
}
else
{
if (maxin < 0.)
{
x->x_maxin = -maxin;
maxout = -maxout;
}
else x->x_maxin = maxin;
if (curve < LINEDRIVE_CURVEEPSILON)
curve = LINEDRIVE_CURVEEPSILON;
x->x_expcoef = logf(curve);
x->x_lincoef = 0.;
x->x_islinear = 0;
}
}
x->x_maxout = maxout; /* CHECKED negative value accepted and used */
}
static void *linedrive_new(t_floatarg maxin, t_floatarg maxout,
t_floatarg curve, t_floatarg deltime)
{
t_linedrive *x = (t_linedrive *)pd_new(linedrive_class);
x->x_usermaxin = maxin;
x->x_usermaxout = maxout;
x->x_usercurve = curve;
linedrive_calculate(x);
SETFLOAT(&x->x_outvec[1], deltime); /* CHECKED any value accepted */
floatinlet_new((t_object *)x, &x->x_outvec[1].a_w.w_float);
outlet_new((t_object *)x, &s_list);
return (x);
}
static void linedrive_fitter(void)
{
/* FIXME for all objects in scope do recalculate */
}
void linedrive_setup(void)
{
linedrive_class = class_new(gensym("linedrive"),
(t_newmethod)linedrive_new, 0,
sizeof(t_linedrive), 0,
A_DEFFLOAT, A_DEFFLOAT,
A_DEFFLOAT, A_DEFFLOAT, 0);
class_addfloat(linedrive_class, linedrive_float);
fitter_setup(linedrive_class, linedrive_fitter);
}
|