Subversion Repositories DIN Is Noise

Rev

Rev 2264 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
964 jag 1
/*
2
* solver.cc
2302 jag 3
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
1713 jag 4
* DIN Is Noise is released under GNU Public License 2.0
1479 jag 5
* For more information, please visit https://dinisnoise.org/
964 jag 6
*/
7
 
8
 
9
#include "solver.h"
10
#include "multi_curve.h"
11
#include "curve_editor.h"
12
#include <cmath>
13
#include "utils.h"
14
using namespace std;
15
 
16
void solver::init () {
17
  mcrv = 0;
18
  icurv = ncurvs = 0;
19
  iseg = 0;
20
  firstx = firsty = 0;
21
  lastx = lasty = 0;
22
  startx = starty = 0;
23
  endx = endy = 0;
2043 jag 24
  pinx = 0;
964 jag 25
  ycomp = 0;
26
  result = 0;
27
}
28
 
29
solver::solver () {
30
  init ();
31
}
32
 
33
solver::solver (multi_curve* c) {
34
  init ();
35
  operator()(c);
36
}
37
 
38
void solver::operator() (multi_curve* c) {
39
  mcrv = c;
40
  update ();
41
}
42
 
43
void solver::update () {
1961 jag 44
 
964 jag 45
  // curve valid?
46
  vector<curve>& curv = mcrv->curv;
47
  ncurvs = curv.size ();
48
  last_curv = ncurvs - 1;
49
  if (icurv > last_curv) icurv = 0;
50
 
51
  // segment valid?
52
  vector<crvpt>& vpts = mcrv->get_profile_points (icurv);
53
  int nsegs = vpts.size() - 1;
54
 
55
  if (iseg >= nsegs) iseg = 0;
56
 
57
  setseg (icurv, iseg);
58
 
59
  // first point
60
  vector<crvpt>& fpts = mcrv->get_profile_points (0);
61
  firstx = fpts[0].x;
62
  firsty = fpts[0].y;
2043 jag 63
  pinx = firstx;
964 jag 64
 
65
  // last point
66
  vector<crvpt>& lpts = mcrv->get_profile_points (last_curv);
67
  int last_point = lpts.size () - 1;
68
  lastx = lpts[last_point].x;
69
  deltax = lastx - firstx;
70
  if (equals (deltax, 0.0f)) deltax = 0.000001f;
71
  lasty = lpts[last_point].y;
72
 
73
}
74
 
75
// solves y for x
76
float solver::operator() (float x) {
77
  float y = 0;
78
  if (x < startx) {
79
    if (!searchleft (x)) {
80
      y = firsty;
81
      return y;
82
    }
83
  } else if (x > endx) {
84
    if (!searchright (x)) {
85
      y = lasty;
86
      return y;
87
    }
88
  }
89
  y = ycomp + m * x;
90
  return y;
91
}
92
 
93
void solver::check (float& x, float& dx, xhandler& xmin, xhandler& xmax) {
94
  if (x < startx) {
95
    if (!searchleft (x)) xmin (*this, x, dx);
96
  } else if (x > endx) {
97
    if (!searchright (x)) xmax (*this, x, dx);
98
  }
99
}
100
 
101
float solver::operator() (float& x, float& dx, xhandler& xmin, xhandler& xmax) {
102
  check (x, dx, xmin, xmax);
103
  float y = ycomp + m * x;
104
  x += dx;
105
  return y;
106
}
107
 
108
// solves y for x with modulation of x
109
void solver::operator() (float& x, float& dx, int q, float* mod, float* y, xhandler& xmin, xhandler& xmax) {
110
  for (int p = 0; p < q; ++p) {
111
    x += (mod[p] + dx);
112
    check (x, dx, xmin, xmax);
113
    y[p] = ycomp + m * x;
114
  }
115
}
116
 
117
void solver::operator() (float& x, float* pdx, int q, float* mod, float* y, xhandler& xmin, xhandler& xmax) {
1966 jag 118
  float dx;
964 jag 119
  for (int p = 0; p < q; ++p) {
1966 jag 120
    dx = pdx[p];
964 jag 121
    x += (mod[p] + dx);
122
    check (x, dx, xmin, xmax);
123
    y[p] = ycomp + m * x;
124
  }
125
}
126
 
127
// solves y for x, constant dx
128
void solver::operator() (float& x, float& dx, int q, float* y, xhandler& xmin, xhandler& xmax) {
129
  for (int p = 0; p < q; ++p) {
130
    x += dx;
131
    check (x, dx, xmin, xmax);
132
    y[p] = ycomp + m * x;
133
  }
134
}
135
 
136
// solves y for x, array of dx
137
void solver::operator() (float& x, float* pdx, int q, float* y, xhandler& xmin, xhandler& xmax) {
138
  float dx;
139
  for (int p = 0; p < q; ++p) {
140
    dx = pdx[p];
141
    x += dx;
142
    check (x, dx, xmin, xmax);
143
    y[p] = ycomp + m * x;
144
  }
145
}
146
 
147
// solves array of x. stores solution ie y in the same array at corresponding location
148
void solver::operator() (float* ax, int q, xhandler& xmin, xhandler& xmax) {
149
  float x = 0, dx = 0;
150
  for (int p = 0; p < q; ++p) {
151
    x = ax[p];
152
    check (x, dx, xmin, xmax);
153
    ax[p] = ycomp + m * x;
154
  }
155
}
156
 
157
int solver::seg_lte_right (float x, int c, int i) {
158
  std::vector<crvpt>& pts = mcrv->get_profile_points (c);
159
  float rightx = pts[i+1].x;
2043 jag 160
  if (rightx < pinx) {
161
    float dpin = pinx - rightx;
162
    rightx = pinx + dpin;
163
  }
964 jag 164
  float xd = x;
165
  if (xd <= rightx) {
166
    setseg (c, i);
167
    return 1;
168
  }
169
  return 0;
170
}
171
 
2043 jag 172
int solver::searchright (float x) {
173
  int rseg = iseg, rcurv = icurv;
174
  std::vector<crvpt>& pts = mcrv->get_profile_points (rcurv);
175
  pinx = pts[rseg].x;
176
  int rsegs = numsegs (rcurv);
177
  while (1) {
178
    if (++rseg < rsegs); else {
179
      ++rcurv;
180
      if (rcurv >= ncurvs) break;
181
      rsegs = numsegs (rcurv);
182
      rseg = 0;
183
    }
184
    if (seg_lte_right (x, rcurv, rseg)) return 1;
185
  }
186
  return 0;
187
}
188
 
964 jag 189
int solver::seg_gte_left (float x, int c, int i) {
190
  std::vector<crvpt>& pts = mcrv->get_profile_points (c);
191
  float leftx = pts[i].x;
2043 jag 192
  if (leftx > pinx) {
193
    float dpin = pinx - leftx;
194
    leftx = pinx + dpin;
195
  }
964 jag 196
  float xd = x;
197
  if (xd >= leftx) {
198
    setseg (c, i);
199
    return 1;
200
  }
201
  return 0;
202
}
203
 
204
int solver::searchleft (float x) {
205
  int lseg = iseg, lcurv = icurv;
2043 jag 206
  std::vector<crvpt>& pts = mcrv->get_profile_points (lcurv);
207
  pinx = pts[lseg].x;
964 jag 208
  while (1) {
209
    if (--lseg < 0) {
210
      --lcurv;
211
      if (lcurv < 0) break;
212
      lseg = lastseg (lcurv);
213
    }
214
    if (seg_gte_left (x, lcurv, lseg)) return 1;
215
  }
216
  return 0;
217
}
218
 
219
 
220
int solver::findseg (float x) {
221
  int fcurv = 0, fseg = 0, nsegs = numsegs (fcurv);
2043 jag 222
  pinx = firstx;
964 jag 223
  while (1) {
1966 jag 224
    if (seg_lte_right (x, fcurv, fseg))
225
      return 1;
226
    else {
964 jag 227
      ++fseg;
228
      if (fseg >= nsegs) {
1966 jag 229
        if (++fcurv >= ncurvs) {
230
          // bad news
231
          // setseg (ncurvs - 1, nsegs - 1);
1967 jag 232
          // setseg (0, 0);
1966 jag 233
          ycomp = 0;
234
          m = 0;
964 jag 235
          break;
236
        }
237
        fseg = 0;
238
        nsegs = numsegs (fcurv);
239
      }
240
    }
241
  }
1966 jag 242
  return 0;
964 jag 243
}
244
 
245
void solver::setseg (int c, int i) {
246
  std::vector<crvpt>& vpts = mcrv->get_profile_points (c);
247
  crvpt& start = vpts[i];
248
  crvpt& end = vpts[i+1];
249
  startx = start.x;
250
  starty = start.y;
251
  endx = end.x;
252
  endy = end.y;
253
  m = start.m;
254
  inf = start.inf;
255
  if (inf == 1) ycomp = endy; else ycomp = starty - m * startx;
256
  icurv = c;
257
  iseg = i;
258
}
259
 
260
gotog::gotog (float gg, curve_editor* e) : ed (e) {
261
  set (gg);
262
}
263
 
264
void gotog::set (float gg) {
265
  g = gg;
266
  ed->update_sustain (g);
267
}
268
 
269
void gotog::operator () (solver& s, float& x, float& dx) {
270
  x = g;
271
  if (!s.findseg (x)) {
272
    x = s.lastx;
273
    set (x);
274
  }
275
}
276
 
277
void tomax::operator() (solver& s, float& x, float& dx) {
278
  float xd = s.firstx - x;
279
  float d = xd / s.deltax;
280
  int i = d;
281
  x = s.lastx - d + i;
282
  s.findseg (x);
283
}
284
 
285
void atmin::operator() (solver& s, float& x, float& dx) {
286
  x = s.firstx;
287
  s.setseg (0, 0);
288
}
289
 
290
void atmax::operator () (solver& s, float& x, float& dx) {
291
  x = s.lastx;
292
  s.setseg (s.last_curv, s.lastseg (s.last_curv));
293
}
294
 
295
void tomin::operator() (solver& s, float& x, float& dx) {
296
  float xd = (x - s.lastx);
297
  float d = xd / s.deltax;
298
  int i = d;
299
  x = s.firstx + d - i;
300
  s.findseg (x);
2129 jag 301
  called = 1;
964 jag 302
}
303
 
304
void loopmin::operator() (solver& s, float& x, float& dx) {
305
  atmin::operator() (s, x, dx);
306
  if (dx < 0) dx = -dx;
307
}
308
 
309
void loopmax::operator() (solver& s, float& x, float& dx) {
310
  tomin::operator() (s, x, dx);
311
  if (dx < 0) dx = -dx;
312
}
313
 
314
 
315
void pongmax::operator () (solver& s, float& x, float& dx) {
316
  atmax::operator() (s, x, dx);
317
  if (dx > 0) dx = -dx;
318
}
319
 
320
void pongmin::operator () (solver& s, float& x, float& dx) {
321
  atmin::operator() (s, x, dx);
322
  if (dx < 0) dx = -dx;
323
}