comparison CloneChannel/plugins/common/gen_dsp/genlib_ops.h @ 12:24d60bdea349

ClonneChannel
author prymula <prymula76@outlook.com>
date Thu, 08 Feb 2024 20:24:27 +0100
parents
children
comparison
equal deleted inserted replaced
11:78390e0e674f 12:24d60bdea349
1 /*******************************************************************************************************************
2 Copyright (c) 2012 Cycling '74
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 and associated documentation files (the "Software"), to deal in the Software without restriction,
6 including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8 subject to the following conditions:
9
10 The above copyright notice and this permission notice shall be included in all copies
11 or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
16 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
17 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 *******************************************************************************************************************/
19
20 #ifndef GENLIB_OPS_H
21 #define GENLIB_OPS_H 1
22
23 #include "genlib_common.h" // common to common code and any host code
24 #include "genlib.h" // this file is different for different "hosts"
25
26 #include <cmath>
27
28 //////////// genlib_ops.h ////////////
29
30 // system constants
31 #define GENLIB_DBL_EPSILON (__DBL_EPSILON__)
32
33 #define GENLIB_PI (3.14159265358979323846264338327950288f)
34 #define GENLIB_PI_OVER_2 (1.57079632679489661923132169163975144f)
35 #define GENLIB_PI_OVER_4 (0.785398163397448309615660845819875721f)
36 #define GENLIB_1_OVER_LOG_2 (1.442695040888963f)
37
38 #define GENLIB_NO_DENORM_TEST 1
39
40 // assumes v is a 64-bit double:
41 #define GENLIB_IS_NAN_DOUBLE(v) (((((uint32_t *)&(v))[1])&0x7fe00000)==0x7fe00000)
42 #define GENLIB_FIX_NAN_DOUBLE(v) ((v)=GENLIB_IS_NAN_DOUBLE(v)?0.:(v))
43
44 #ifdef GENLIB_NO_DENORM_TEST
45 #define GENLIB_IS_DENORM_DOUBLE(v) (v)
46 #define GENLIB_FIX_DENORM_DOUBLE(v) (v)
47 #else
48 #define GENLIB_IS_DENORM_DOUBLE(v) ((((((uint32_t *)&(v))[1])&0x7fe00000)==0)&&((v)!=0.))
49 #define GENLIB_FIX_DENORM_DOUBLE(v) ((v)=GENLIB_IS_DENORM_DOUBLE(v)?0.f:(v))
50 #endif
51
52 #define GENLIB_QUANT(f1,f2) (floor((f1)*(f2)+0.5)/(f2))
53
54 inline double genlib_isnan(double v) { return GENLIB_IS_NAN_DOUBLE(v); }
55 inline double fixnan(double v) { return GENLIB_FIX_NAN_DOUBLE(v); }
56 inline double fixdenorm(double v) { return GENLIB_FIX_DENORM_DOUBLE(v); }
57 inline double isdenorm(double v) { return GENLIB_IS_DENORM_DOUBLE(v); }
58
59 inline double safemod(double f, double m) {
60 if (m > GENLIB_DBL_EPSILON || m < -GENLIB_DBL_EPSILON) {
61 if (m<0)
62 m = -m; // modulus needs to be absolute value
63 if (f>=m) {
64 if (f>=(m*2.)) {
65 double d = f / m;
66 d = d - (long) d;
67 f = d * m;
68 }
69 else {
70 f -= m;
71 }
72 }
73 else if (f<=(-m)) {
74 if (f<=(-m*2.)) {
75 double d = f / m;
76 d = d - (long) d;
77 f = d * m;
78 }
79 else {
80 f += m;
81 }
82 }
83 } else {
84 f = 0.0; //don't divide by zero
85 }
86 return f;
87 }
88
89
90 inline double safediv(double num, double denom) {
91 return denom == 0. ? 0. : num/denom;
92 }
93
94 // fixnan for case of negative base and non-integer exponent:
95 inline double safepow(double base, double exponent) {
96 return fixnan(pow(base, exponent));
97 }
98
99 inline double absdiff(double a, double b) { return fabs(a-b); }
100
101 inline double exp2(double v) { return pow(2., v); }
102
103 inline double trunc(double v) {
104 double epsilon = (v<0.0) * -2 * 1E-9 + 1E-9;
105 // copy to long so it gets truncated (probably cheaper than floor())
106 long val = v + epsilon;
107 return val;
108 }
109
110 inline t_sample sign(t_sample v) {
111 return v > t_sample(0) ? t_sample(1) : v < t_sample(0) ? t_sample(-1) : t_sample(0);
112 }
113
114 inline long is_poweroftwo(long x) {
115 return (x & (x - 1)) == 0;
116 }
117
118 inline uint64_t next_power_of_two(uint64_t v) {
119 v--;
120 v |= v >> 1;
121 v |= v >> 2;
122 v |= v >> 4;
123 v |= v >> 8;
124 v |= v >> 16;
125 v |= v >> 32;
126 v++;
127 return v;
128 }
129
130 inline t_sample fold(t_sample v, t_sample lo1, t_sample hi1){
131 t_sample lo;
132 t_sample hi;
133 if(lo1 == hi1){ return lo1; }
134 if (lo1 > hi1) {
135 hi = lo1; lo = hi1;
136 } else {
137 lo = lo1; hi = hi1;
138 }
139 const t_sample range = hi - lo;
140 long numWraps = 0;
141 if(v >= hi){
142 v -= range;
143 if(v >= hi){
144 numWraps = (long)((v - lo)/range);
145 v -= range * (t_sample)numWraps;
146 }
147 numWraps++;
148 } else if(v < lo){
149 v += range;
150 if(v < lo){
151 numWraps = (long)((v - lo)/range) - 1;
152 v -= range * (t_sample)numWraps;
153 }
154 numWraps--;
155 }
156 if(numWraps & 1) v = hi + lo - v; // flip sign for odd folds
157 return v;
158 }
159
160 inline double wrap(double v, double lo1, double hi1){
161 double lo;
162 double hi;
163 if(lo1 == hi1) return lo1;
164 if (lo1 > hi1) {
165 hi = lo1; lo = hi1;
166 } else {
167 lo = lo1; hi = hi1;
168 }
169 const double range = hi - lo;
170 if (v >= lo && v < hi) return v;
171 if (range <= 0.000000001) return lo; // no point...
172 const long numWraps = long((v-lo)/range) - (v < lo);
173 return v - range * double(numWraps);
174 }
175
176 // this version gives far better performance when wrapping is relatively rare
177 // and typically double of wraps is very low (>1%)
178 // but catastrophic if wraps is high (1000%+)
179 inline t_sample genlib_wrapfew(t_sample v, t_sample lo, t_sample hi){
180 const t_sample range = hi - lo;
181 while (v >= hi) v -= range;
182 while (v < lo) v += range;
183 return v;
184 }
185
186 inline t_sample phasewrap(t_sample val) {
187 const t_sample twopi = GENLIB_PI*2.;
188 const t_sample oneovertwopi = 1./twopi;
189 if (val>= twopi || val <= twopi) {
190 t_sample d = val * oneovertwopi; //multiply faster
191 d = d - (long)d;
192 val = d * twopi;
193 }
194 if (val > GENLIB_PI) val -= twopi;
195 if (val < -GENLIB_PI) val += twopi;
196 return val;
197 }
198
199 /// 8th order Taylor series approximation to a cosine.
200 /// r must be in [-pi, pi].
201 inline t_sample genlib_cosT8(t_sample r) {
202 const t_sample t84 = 56.;
203 const t_sample t83 = 1680.;
204 const t_sample t82 = 20160.;
205 const t_sample t81 = 2.4801587302e-05;
206 const t_sample t73 = 42.;
207 const t_sample t72 = 840.;
208 const t_sample t71 = 1.9841269841e-04;
209 if(r < GENLIB_PI_OVER_4 && r > -GENLIB_PI_OVER_4){
210 t_sample rr = r*r;
211 return 1. - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)));
212 }
213 else if(r > 0.){
214 r -= GENLIB_PI_OVER_2;
215 t_sample rr = r*r;
216 return -r * (1. - t71 * rr * (t72 - rr * (t73 - rr)));
217 }
218 else{
219 r += GENLIB_PI_OVER_2;
220 t_sample rr = r*r;
221 return r * (1. - t71 * rr * (t72 - rr * (t73 - rr)));
222 }
223 }
224
225 //inline double genlib_sin_fast(const double r){
226 // const double y = (4./GENLIB_PI) * r + (-4./(GENLIB_PI*GENLIB_PI)) * r * fabs(r);
227 // return 0.225 * (y * fabs(y) - y) + y; // Q * y + P * y * abs(y)
228 //}
229 //
230 //inline t_sample genlib_sinP7(t_sample n){
231 // t_sample nn = n*n;
232 // return n * (t_sample(3.138982) + nn * (t_sample(-5.133625) + nn * (t_sample(2.428288) - nn * t_sample(0.433645))));
233 //}
234 //
235 //inline t_sample genlib_sinP9(t_sample n){
236 // t_sample nn = n*n;
237 // return n * (GENLIB_PI + nn * (t_sample(-5.1662729) + nn * (t_sample(2.5422065) + nn * (t_sample(-0.5811243) + nn * t_sample(0.0636716)))));
238 //}
239 //
240 //inline t_sample genlib_sinT7(t_sample r){
241 // const t_sample t84 = 56.;
242 // const t_sample t83 = 1680.;
243 // const t_sample t82 = 20160.;
244 // const t_sample t81 = 2.4801587302e-05;
245 // const t_sample t73 = 42.;
246 // const t_sample t72 = 840.;
247 // const t_sample t71 = 1.9841269841e-04;
248 // if(r < GENLIB_PI_OVER_4 && r > -GENLIB_PI_OVER_4){
249 // t_sample rr = r*r;
250 // return r * (1. - t71 * rr * (t72 - rr * (t73 - rr)));
251 // }
252 // else if(r > 0.){
253 // r -= GENLIB_PI_OVER_2;
254 // t_sample rr = r*r;
255 // return t_sample(1.) - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)));
256 // }
257 // else{
258 // r += GENLIB_PI_OVER_2;
259 // t_sample rr = r*r;
260 // return t_sample(-1.) + rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)));
261 // }
262 //}
263
264 // use these if r is not known to be in [-pi, pi]:
265 inline t_sample genlib_cosT8_safe(t_sample r) { return genlib_cosT8(phasewrap(r)); }
266 //inline double genlib_sin_fast_safe(double r) { return genlib_sin_fast(phasewrap(r)); }
267 //inline t_sample genlib_sinP7_safe(t_sample r) { return genlib_sinP7(phasewrap(r)); }
268 //inline t_sample genlib_sinP9_safe(t_sample r) { return genlib_sinP9(phasewrap(r)); }
269 //inline t_sample genlib_sinT7_safe(t_sample r) { return genlib_sinT7(phasewrap(r)); }
270
271
272
273 /*=====================================================================*
274 * Copyright (C) 2011 Paul Mineiro *
275 * All rights reserved. *
276 * *
277 * Redistribution and use in source and binary forms, with *
278 * or without modification, are permitted provided that the *
279 * following conditions are met: *
280 * *
281 * * Redistributions of source code must retain the *
282 * above copyright notice, this list of conditions and *
283 * the following disclaimer. *
284 * *
285 * * Redistributions in binary form must reproduce the *
286 * above copyright notice, this list of conditions and *
287 * the following disclaimer in the documentation and/or *
288 * other materials provided with the distribution. *
289 * *
290 * * Neither the name of Paul Mineiro nor the names *
291 * of other contributors may be used to endorse or promote *
292 * products derived from this software without specific *
293 * prior written permission. *
294 * *
295 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
296 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
297 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
298 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *
299 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER *
300 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
301 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
302 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE *
303 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
304 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
305 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
306 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
307 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
308 * POSSIBILITY OF SUCH DAMAGE. *
309 * *
310 * Contact: Paul Mineiro <paul@mineiro.com> *
311 *=====================================================================*/
312
313 inline float genlib_fastersin (float x) {
314 static const float fouroverpi = 1.2732395447351627f;
315 static const float fouroverpisq = 0.40528473456935109f;
316 static const float q = 0.77633023248007499f;
317 union { float f; uint32_t i; } p = { 0.22308510060189463f };
318 union { float f; uint32_t i; } vx = { x };
319 uint32_t sign = vx.i & 0x80000000;
320 vx.i &= 0x7FFFFFFF;
321 float qpprox = fouroverpi * x - fouroverpisq * x * vx.f;
322 p.i |= sign;
323 return qpprox * (q + p.f * qpprox);
324 }
325
326 inline float genlib_fastercos (float x) {
327 static const float twooverpi = 0.63661977236758134f;
328 static const float p = 0.54641335845679634f;
329 union { float f; uint32_t i; } vx = { x };
330 vx.i &= 0x7FFFFFFF;
331 float qpprox = 1.0f - twooverpi * vx.f;
332 return qpprox + p * qpprox * (1.0f - qpprox * qpprox);
333 }
334
335 inline float genlib_fastersinfull (float x) {
336 static const float twopi = 6.2831853071795865f;
337 static const float invtwopi = 0.15915494309189534f;
338 int k = x * invtwopi;
339 float half = (x < 0) ? -0.5f : 0.5f;
340 return genlib_fastersin ((half + k) * twopi - x);
341 }
342
343 inline float genlib_fastercosfull (float x) {
344 static const float halfpi = 1.5707963267948966f;
345 return genlib_fastersinfull (x + halfpi);
346 }
347
348 inline float genlib_fastertanfull (float x) {
349 static const float twopi = 6.2831853071795865f;
350 static const float invtwopi = 0.15915494309189534f;
351 int k = x * invtwopi;
352 float half = (x < 0) ? -0.5f : 0.5f;
353 float xnew = x - (half + k) * twopi;
354 return genlib_fastersin (xnew) / genlib_fastercos (xnew);
355 }
356
357
358 #define cast_uint32_t static_cast<uint32_t>
359 inline float genlib_fasterpow2 (float p) {
360 float clipp = (p < -126) ? -126.0f : p;
361 union { uint32_t i; float f; } v = { cast_uint32_t ( (1 << 23) * (clipp + 126.94269504f) ) };
362 return v.f;
363 }
364
365 inline float genlib_fasterexp (float p) {
366 return genlib_fasterpow2 (1.442695040f * p);
367 }
368
369 inline float genlib_fasterlog2 (float x) {
370 union { float f; uint32_t i; } vx = { x };
371 float y = vx.i;
372 y *= 1.1920928955078125e-7f;
373 return y - 126.94269504f;
374 }
375
376 inline float genlib_fasterpow (float x, float p) {
377 return genlib_fasterpow2(p * genlib_fasterlog2 (x));
378 }
379
380 ////////////////////////////////////////////////////////////////
381
382 inline double fastertanfull(double x) {
383 return (double)genlib_fastertanfull((float)x);
384 }
385
386 inline double fastersinfull(double x) {
387 return (double)genlib_fastersinfull((float)x);
388 }
389
390 inline double fastercosfull(double x) {
391 return (double)genlib_fastercosfull((float)x);
392 }
393
394 inline double fasterexp(double x) {
395 return (double)genlib_fasterexp((float)x);
396 }
397
398 inline double fasterpow(double x, double p) {
399 return (double)genlib_fasterpow((float)x, (float)p);
400 }
401 /****************************************************************/
402
403
404
405 inline double minimum(double x, double y) { return (y<x?y:x); }
406 inline double maximum(double x, double y) { return (x<y?y:x); }
407
408 inline t_sample clamp(t_sample x, t_sample minVal, t_sample maxVal) {
409 return minimum(maximum(x,minVal),maxVal);
410 }
411
412 template<typename T>
413 inline T smoothstep(double e0, double e1, T x) {
414 T t = clamp( safediv(x-T(e0),T(e1-e0)), 0., 1. );
415 return t*t*(T(3) - T(2)*t);
416 }
417
418 inline t_sample mix(t_sample x, t_sample y, t_sample a) {
419 return x+a*(y-x);
420 }
421
422 inline double scale(double in, double inlow, double inhigh, double outlow, double outhigh, double power)
423 {
424 double value;
425 double inscale = safediv(1., inhigh - inlow);
426 double outdiff = outhigh - outlow;
427
428 value = (in - inlow) * inscale;
429 if (value > 0.0)
430 value = pow(value, power);
431 else if (value < 0.0)
432 value = -pow(-value, power);
433 value = (value * outdiff) + outlow;
434
435 return value;
436 }
437
438 inline t_sample linear_interp(t_sample a, t_sample x, t_sample y) {
439 return x+a*(y-x);
440 }
441
442 inline t_sample cosine_interp(t_sample a, t_sample x, t_sample y) {
443 const t_sample a2 = (t_sample(1.)-genlib_cosT8_safe(a*t_sample(GENLIB_PI)))/t_sample(2.);
444 return(x*(t_sample(1.)-a2)+y*a2);
445 }
446
447 inline t_sample cubic_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_sample z) {
448 const t_sample a2 = a*a;
449 const t_sample f0 = z - y - w + x;
450 const t_sample f1 = w - x - f0;
451 const t_sample f2 = y - w;
452 const t_sample f3 = x;
453 return(f0*a*a2 + f1*a2 + f2*a + f3);
454 }
455
456 // Breeuwsma catmull-rom spline interpolation
457 inline t_sample spline_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_sample z) {
458 const t_sample a2 = a*a;
459 const t_sample f0 = t_sample(-0.5)*w + t_sample(1.5)*x - t_sample(1.5)*y + t_sample(0.5)*z;
460 const t_sample f1 = w - t_sample(2.5)*x + t_sample(2)*y - t_sample(0.5)*z;
461 const t_sample f2 = t_sample(-0.5)*w + t_sample(0.5)*y;
462 return(f0*a*a2 + f1*a2 + f2*a + x);
463 }
464
465 template<typename T1, typename T2>
466 inline T1 neqp(T1 x, T2 y) {
467 return ((((x) != T1(y))) ? (x) : T1(0));
468 }
469
470 template<typename T1, typename T2>
471 inline T1 gtp(T1 x, T2 y) { return ((((x) > T1(y))) ? (x) : T1(0)); }
472 template<typename T1, typename T2>
473 inline T1 gtep(T1 x, T2 y) { return ((((x) >= T1(y))) ? (x) : T1(0)); }
474 template<typename T1, typename T2>
475 inline T1 ltp(T1 x, T2 y) { return ((((x) < T1(y))) ? (x) : T1(0)); }
476 template<typename T1, typename T2>
477 inline T1 ltep(T1 x, T2 y) { return ((((x) <= T1(y))) ? (x) : T1(0)); }
478
479 inline double fract(double x) { double unused; return modf(x, &unused); }
480
481 // log2(x) = log(x)/log(2)
482 template<typename T>
483 inline T log2(T x) {
484 return log(x)*GENLIB_1_OVER_LOG_2;
485 }
486
487 inline double atodb(double in) {
488 return (in <=0.) ? -999. : (20. * log10(in));
489 }
490
491 inline double dbtoa(double in) {
492 return pow(10., in * 0.05);
493 }
494
495 inline double ftom(double in, double tuning=440.) {
496 return 69. + 17.31234050465299 * log(safediv(in, tuning));
497 }
498
499 inline double mtof(double in, double tuning=440.) {
500 return tuning * exp(.057762265 * (in - 69.0));
501 }
502
503 inline t_sample mstosamps(t_sample ms, t_sample samplerate=44100.) {
504 return samplerate * ms * t_sample(0.001);
505 }
506
507 inline t_sample sampstoms(t_sample s, t_sample samplerate=44100.) {
508 return t_sample(1000.) * s / samplerate;
509 }
510
511 inline double triangle(double phase, double p1) {
512 phase = wrap(phase, 0., 1.);
513 p1 = clamp(p1, 0., 1.);
514 if (phase < p1)
515 return (p1) ? phase/p1 : 0.;
516 else
517 return (p1==1.) ? phase : 1. - ((phase - p1) / (1. - p1));
518 }
519
520 struct Delta {
521 t_sample history;
522 Delta() { reset(); }
523 inline void reset(t_sample init=0) { history=init; }
524
525 inline t_sample operator()(t_sample in1) {
526 t_sample ret = in1 - history;
527 history = in1;
528 return ret;
529 }
530 };
531 struct Change {
532 t_sample history;
533 Change() { reset(); }
534 inline void reset(t_sample init=0) { history=init; }
535
536 inline t_sample operator()(t_sample in1) {
537 t_sample ret = in1 - history;
538 history = in1;
539 return sign(ret);
540 }
541 };
542
543 struct Rate {
544 t_sample phase, diff, mult, invmult, prev;
545 int wantlock, quant;
546
547 Rate() { reset(); }
548
549 inline void reset() {
550 phase = diff = prev = 0;
551 mult = invmult = 1;
552 wantlock = 1;
553 quant = 1;
554 }
555
556 inline t_sample perform_lock(t_sample in1, t_sample in2) {
557 // did multiplier change?
558 if (in2 != mult && !genlib_isnan(in2)) {
559 mult = in2;
560 invmult = safediv(1., mult);
561 wantlock = 1;
562 }
563 t_sample diff = in1 - prev;
564
565 if (diff < t_sample(-0.5)) {
566 diff += t_sample(1);
567 } else if (diff > t_sample(0.5)) {
568 diff -= t_sample(1);
569 }
570
571 if (wantlock) {
572 // recalculate phase
573 phase = (in1 - GENLIB_QUANT(in1, quant)) * invmult
574 + GENLIB_QUANT(in1, quant * mult);
575 diff = 0;
576 wantlock = 0;
577 } else {
578 // diff is always between -0.5 and 0.5
579 phase += diff * invmult;
580 }
581
582 if (phase > t_sample(1.) || phase < t_sample(-0.)) {
583 phase = phase - (long)(phase);
584 }
585
586 prev = in1;
587
588 return phase;
589 }
590
591 inline t_sample perform_cycle(t_sample in1, t_sample in2) {
592 // did multiplier change?
593 if (in2 != mult && !genlib_isnan(in2)) {
594 mult = in2;
595 invmult = safediv(1., mult);
596 wantlock = 1;
597 }
598 t_sample diff = in1 - prev;
599
600 if (diff < t_sample(-0.5)) {
601 if (wantlock) {
602 wantlock = 0;
603 phase = in1 * invmult;
604 diff = t_sample(0);
605 } else {
606 diff += t_sample(1);
607 }
608 } else if (diff > t_sample(0.5)) {
609 if (wantlock) {
610 wantlock = 0;
611 phase = in1 * invmult;
612 diff = t_sample(0);
613 } else {
614 diff -= t_sample(1);
615 }
616 }
617
618 // diff is always between -0.5 and 0.5
619 phase += diff * invmult;
620
621 if (phase > t_sample(1.) || phase < t_sample(-0.)) {
622 phase = phase - (long)(phase);
623 }
624
625 prev = in1;
626
627 return phase;
628 }
629
630 inline t_sample perform_off(double in1, double in2) {
631 // did multiplier change?
632 if (in2 != mult && !genlib_isnan(in2)) {
633 mult = in2;
634 invmult = safediv(1., mult);
635 wantlock = 1;
636 }
637 double diff = in1 - prev;
638
639 if (diff < t_sample(-0.5)) {
640 diff += t_sample(1);
641 } else if (diff > t_sample(0.5)) {
642 diff -= t_sample(1);
643 }
644
645 phase += diff * invmult;
646
647 if (phase > t_sample(1.) || phase < t_sample(-0.)) {
648 phase = phase - (long)(phase);
649 }
650
651 prev = in1;
652
653 return phase;
654 }
655 };
656
657 struct DCBlock {
658 t_sample x1, y1;
659 DCBlock() { reset(); }
660 inline void reset() { x1=0; y1=0; }
661
662 inline double operator()(t_sample in1) {
663 t_sample y = in1 - x1 + y1*t_sample(0.9997);
664 x1 = in1;
665 y1 = y;
666 return y;
667 }
668 };
669
670 struct Noise {
671 unsigned long last;
672 static long uniqueTickCount(void) {
673 static long lasttime = 0;
674 long time = genlib_ticks();
675 return (time <= lasttime) ? (++lasttime) : (lasttime = time);
676 }
677
678 Noise() { reset(); }
679 Noise(double seed) { reset(seed); }
680 void reset() { last = uniqueTickCount() * uniqueTickCount(); }
681 void reset(double seed) { last = seed; }
682
683 inline t_sample operator()() {
684 last = 1664525L * last + 1013904223L;
685 unsigned long itemp = 0x3f800000 | (0x007fffff & last);
686 unsigned long* itempptr = &itemp;
687 return ((*(float *)itempptr) * 2.f) - 3.f;
688 }
689 };
690
691 struct Phasor {
692 t_sample phase;
693 Phasor() { reset(); }
694 void reset(t_sample v=0.) { phase=v; }
695 inline double operator()(t_sample freq, t_sample invsamplerate) {
696 const t_sample pincr = freq * invsamplerate;
697 //phase = genlib_wrapfew(phase + pincr, 0., 1.); // faster for low frequencies, but explodes with high frequencies
698 phase = wrap(phase + pincr, 0., 1.);
699 return phase;
700 }
701 };
702
703 struct PlusEquals {
704 t_sample count;
705 PlusEquals() { reset(); }
706 void reset(t_sample v=0.) { count=v; }
707
708 // reset post-application mode:
709 inline t_sample post(t_sample incr, t_sample reset, t_sample min, t_sample max) {
710 count = reset ? min : wrap(count+incr, min, max);
711 return count;
712 }
713 inline t_sample post(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
714 count = reset ? min : count+incr;
715 return count;
716 }
717
718 // reset pre-application mode:
719 inline t_sample pre(t_sample incr, t_sample reset, t_sample min, t_sample max) {
720 count = reset ? min+incr : wrap(count+incr, min, max);
721 return count;
722 }
723 inline t_sample pre(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
724 count = reset ? min+incr : count+incr;
725 return count;
726 }
727 };
728
729 struct MulEquals {
730 t_sample count;
731 MulEquals() { reset(); }
732 void reset(t_sample v=0.) { count=v; }
733
734 // reset post-application mode:
735 inline t_sample post(t_sample incr, t_sample reset, t_sample min, t_sample max) {
736 count = reset ? min : wrap(fixdenorm(count*incr), min, max);
737 return count;
738 }
739 inline t_sample post(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
740 count = reset ? min : fixdenorm(count*incr);
741 return count;
742 }
743
744 // reset pre-application mode:
745 inline t_sample pre(t_sample incr, t_sample reset, t_sample min, t_sample max) {
746 count = reset ? min*incr : wrap(fixdenorm(count*incr), min, max);
747 return count;
748 }
749 inline t_sample pre(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
750 count = reset ? min*incr : fixdenorm(count*incr);
751 return count;
752 }
753 };
754
755 struct Sah {
756 t_sample prev, output;
757 Sah() { reset(); }
758 void reset(t_sample o=0.) {
759 output = prev = o;
760 }
761
762 inline t_sample operator()(t_sample in, t_sample trig, t_sample thresh) {
763 if (prev <= thresh && trig > thresh) {
764 output = in;
765 }
766 prev = trig;
767 return output;
768 }
769 };
770
771 struct Train {
772 t_sample phase, state;
773 Train() { reset(); }
774 void reset(t_sample p=0) { phase = p; state = 0.; }
775
776 inline t_sample operator()(t_sample pulseinterval, t_sample width, t_sample pulsephase) {
777 if (width <= t_sample(0.)) {
778 state = t_sample(0.); // no pulse!
779 } else if (width >= 1.) {
780 state = t_sample(1.); // constant pulse!
781 } else {
782 const t_sample interval = maximum(pulseinterval, t_sample(1.)); // >= 1.
783 const t_sample p1 = clamp(pulsephase, t_sample(0.), t_sample(1.)); // [0..1]
784 const t_sample p2 = p1+width; // (p1..p1+1)
785 const t_sample pincr = t_sample(1.)/interval; // (0..1]
786 phase += pincr; // +ve
787 if (state) { // on:
788 if (phase > p2) {
789 state = t_sample(0.); // turn off
790 phase -= (int)(1.+phase-p2); // wrap phase back down
791 }
792 } else { // off:
793 if (phase > p1) {
794 state = t_sample(1.); // turn on.
795 }
796 }
797 }
798 return state;
799 }
800 };
801
802 struct Delay {
803 t_sample * memory;
804 long size, wrap, maxdelay;
805 long reader, writer;
806
807 t_genlib_data * dataRef;
808
809 Delay() : memory(0) {
810 size = wrap = maxdelay = 0;
811 reader = writer = 0;
812 dataRef = 0;
813 }
814 ~Delay() {
815 if (dataRef != 0) {
816 // store write position for persistence:
817 genlib_data_setcursor(dataRef, writer);
818 // decrement reference count:
819 genlib_data_release(dataRef);
820 }
821 }
822
823 inline void reset(const char * name, long d) {
824 // if needed, acquire the Data's global reference:
825 if (dataRef == 0) {
826
827 void * ref = genlib_obtain_reference_from_string(name);
828 dataRef = genlib_obtain_data_from_reference(ref);
829 if (dataRef == 0) {
830 genlib_report_error("failed to acquire data");
831 return;
832 }
833
834 // scale maxdelay to next highest power of 2:
835 maxdelay = d;
836 size = maxdelay < 2 ? 2 : maxdelay;
837 size = next_power_of_two(size);
838
839 // first reset should resize the memory:
840 genlib_data_resize(dataRef, size, 1);
841
842 t_genlib_data_info info;
843 if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) {
844 if (info.dim != size) {
845 // at this point, could resolve by reducing to
846 // maxdelay = size = next_power_of_two(info.dim+1)/2;
847 // but really, if this happens, it means more than one
848 // object is referring to the same t_gen_dsp_data.
849 // which is probably bad news.
850 genlib_report_error("delay memory size error");
851 memory = 0;
852 return;
853 }
854 memory = info.data;
855 writer = genlib_data_getcursor(dataRef);
856 } else {
857 genlib_report_error("failed to acquire data info");
858 }
859
860 } else {
861 // subsequent reset should zero the memory & heads:
862 set_zero64(memory, size);
863 writer = 0;
864 }
865
866 reader = writer;
867 wrap = size-1;
868 }
869
870 // called at bufferloop end, updates read pointer time
871 inline void step() {
872 reader++;
873 if (reader >= size) reader = 0;
874 }
875
876 inline void write(t_sample x) {
877 writer = reader; // update write ptr
878 memory[writer] = x;
879 }
880
881 inline t_sample read_step(t_sample d) {
882 // extra half for nice rounding:
883 // min 1 sample delay for read before write (r != w)
884 const t_sample r = t_sample(size + reader) - clamp(d-t_sample(0.5), (reader != writer), maxdelay);
885 long r1 = long(r);
886 return memory[r1 & wrap];
887 }
888
889 inline t_sample read_linear(t_sample d) {
890 // min 1 sample delay for read before write (r != w)
891 t_sample c = clamp(d, (reader != writer), maxdelay);
892 const t_sample r = t_sample(size + reader) - c;
893 long r1 = long(r);
894 long r2 = r1+1;
895 t_sample a = r - (t_sample)r1;
896 t_sample x = memory[r1 & wrap];
897 t_sample y = memory[r2 & wrap];
898 return linear_interp(a, x, y);
899 }
900
901 inline t_sample read_cosine(t_sample d) {
902 // min 1 sample delay for read before write (r != w)
903 const t_sample r = t_sample(size + reader) - clamp(d, (reader != writer), maxdelay);
904 long r1 = long(r);
905 long r2 = r1+1;
906 t_sample a = r - (t_sample)r1;
907 t_sample x = memory[r1 & wrap];
908 t_sample y = memory[r2 & wrap];
909 return cosine_interp(a, x, y);
910 }
911
912 // cubic requires extra sample of compensation:
913 inline t_sample read_cubic(t_sample d) {
914 // min 1 sample delay for read before write (r != w)
915 // plus extra 1 sample compensation for 4-point interpolation
916 const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.)+t_sample(reader != writer), maxdelay);
917 long r1 = long(r);
918 long r2 = r1+1;
919 long r3 = r1+2;
920 long r4 = r1+3;
921 t_sample a = r - (t_sample)r1;
922 t_sample w = memory[r1 & wrap];
923 t_sample x = memory[r2 & wrap];
924 t_sample y = memory[r3 & wrap];
925 t_sample z = memory[r4 & wrap];
926 return cubic_interp(a, w, x, y, z);
927 }
928
929 // spline requires extra sample of compensation:
930 inline t_sample read_spline(t_sample d) {
931 // min 1 sample delay for read before write (r != w)
932 // plus extra 1 sample compensation for 4-point interpolation
933 const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.)+t_sample(reader != writer), maxdelay);
934 long r1 = long(r);
935 long r2 = r1+1;
936 long r3 = r1+2;
937 long r4 = r1+3;
938 t_sample a = r - (t_sample)r1;
939 t_sample w = memory[r1 & wrap];
940 t_sample x = memory[r2 & wrap];
941 t_sample y = memory[r3 & wrap];
942 t_sample z = memory[r4 & wrap];
943 return spline_interp(a, w, x, y, z);
944 }
945 };
946
947 template<typename T=t_sample>
948 struct DataInterface {
949 long dim, channels;
950 T * mData;
951 void * mDataReference; // this was t_symbol *mName
952 int modified;
953
954 DataInterface() : dim(0), channels(1), mData(0), modified(0) { mDataReference = 0; }
955
956 // raw reading/writing/overdubbing (internal use only, no bounds checking)
957 inline t_sample read(long index, long channel=0) const {
958 return mData[channel+index*channels];
959 }
960 inline void write(T value, long index, long channel=0) {
961 mData[channel+index*channels] = value;
962 modified = 1;
963 }
964 // NO LONGER USED:
965 inline void overdub(T value, long index, long channel=0) {
966 mData[channel+index*channels] += value;
967 modified = 1;
968 }
969
970 // averaging overdub (used by splat)
971 inline void blend(T value, long index, long channel, t_sample alpha) {
972 long offset = channel+index*channels;
973 const T old = mData[offset];
974 mData[offset] = old + alpha * (value - old);
975 modified = 1;
976 }
977
978 // NO LONGER USED:
979 inline void read_ok(long index, long channel=0, bool ok=1) const {
980 return ok ? mData[channel+index*channels] : T(0);
981 }
982 inline void write_ok(T value, long index, long channel=0, bool ok=1) {
983 if (ok) mData[channel+index*channels] = value;
984 }
985 inline void overdub_ok(T value, long index, long channel=0, bool ok=1) {
986 if (ok) mData[channel+index*channels] += value;
987 }
988
989 // Bounds strategies:
990 inline long index_clamp(long index) const { return clamp(index, 0, dim-1); }
991 inline long index_wrap(long index) const { return wrap(index, 0, dim); }
992 inline long index_fold(long index) const { return fold(index, 0, dim); }
993 inline bool index_oob(long index) const { return (index < 0 || index >= dim); }
994 inline bool index_inbounds(long index) const { return (index >=0 && index < dim); }
995
996 // channel bounds:
997 inline long channel_clamp(long c) const { return clamp(c, 0, channels-1); }
998 inline long channel_wrap(long c) const { return wrap(c, 0, channels); }
999 inline long channel_fold(long c) const { return fold(c, 0, channels); }
1000 inline bool channel_oob(long c) const { return (c < 0 || c >= channels); }
1001 inline bool channel_inbounds(long c) const { return !channel_oob(c); }
1002
1003 // Indexing strategies:
1004 // [0..1] -> [0..(dim-1)]
1005 inline t_sample phase2index(t_sample phase) const { return phase * t_sample(dim-1); }
1006 // [0..1] -> [min..max]
1007 inline t_sample subphase2index(t_sample phase, long min, long max) const {
1008 min = index_clamp(min);
1009 max = index_clamp(max);
1010 return t_sample(min) + phase * t_sample(max-min);
1011 }
1012 // [-1..1] -> [0..(dim-1)]
1013 inline t_sample signal2index(t_sample signal) const { return phase2index((signal+t_sample(1.)) * t_sample(0.5)); }
1014
1015 inline T peek(t_sample index, long channel=0) const {
1016 const long i = (long)index;
1017 if (index_oob(i) || channel_oob(channel)) {
1018 return 0.;
1019 } else {
1020 return read(i, channel);
1021 }
1022 }
1023
1024 inline T index(double index, long channel=0) const {
1025 channel = channel_clamp(channel);
1026 // no-interp:
1027 long i = (long)index;
1028 // bound:
1029 i = index_clamp(i);
1030 return read(i, channel);
1031 }
1032
1033 inline T cell(double index, long channel=0) const {
1034 channel = channel_clamp(channel);
1035 // no-interp:
1036 long i = (long)index;
1037 // bound:
1038 i = index_wrap(i);
1039 return read(i, channel);
1040 }
1041
1042 inline T cycle(t_sample phase, long channel=0) const {
1043 channel = channel_clamp(channel);
1044 t_sample index = phase2index(phase);
1045 // interp:
1046 long i1 = (long)index;
1047 long i2 = i1+1;
1048 const t_sample alpha = index - (t_sample)i1;
1049 // bound:
1050 i1 = index_wrap(i1);
1051 i2 = index_wrap(i2);
1052 // interp:
1053 T v1 = read(i1, channel);
1054 T v2 = read(i2, channel);
1055 return mix(v1, v2, alpha);
1056 }
1057
1058 inline T lookup(t_sample signal, long channel=0) const {
1059 channel = channel_clamp(channel);
1060 t_sample index = signal2index(signal);
1061 // interp:
1062 long i1 = (long)index;
1063 long i2 = i1+1;
1064 t_sample alpha = index - (t_sample)i1;
1065 // bound:
1066 i1 = index_clamp(i1);
1067 i2 = index_clamp(i2);
1068 // interp:
1069 T v1 = read(i1, channel);
1070 T v2 = read(i2, channel);
1071 return mix(v1, v2, alpha);
1072 }
1073 // NO LONGER USED:
1074 inline void poke(t_sample value, t_sample index, long channel=0) {
1075 const long i = (long)index;
1076 if (!(index_oob(i) || channel_oob(channel))) {
1077 write(fixdenorm(value), i, channel);
1078 }
1079 }
1080 // NO LONGER USED:
1081 inline void splat_adding(t_sample value, t_sample phase, long channel=0) {
1082 const t_sample valuef = fixdenorm(value);
1083 channel = channel_clamp(channel);
1084 t_sample index = phase2index(phase);
1085 // interp:
1086 long i1 = (long)index;
1087 long i2 = i1+1;
1088 const t_sample alpha = index - (double)i1;
1089 // bound:
1090 i1 = index_wrap(i1);
1091 i2 = index_wrap(i2);
1092 // interp:
1093 overdub(valuef*(1.-alpha), i1, channel);
1094 overdub(valuef*alpha, i2, channel);
1095 }
1096 // NO LONGER USED:
1097 inline void splat(t_sample value, t_sample phase, long channel=0) {
1098 const t_sample valuef = fixdenorm(value);
1099 channel = channel_clamp(channel);
1100 t_sample index = phase2index(phase);
1101 // interp:
1102 long i1 = (long)index;
1103 long i2 = i1+1;
1104 const t_sample alpha = index - (t_sample)i1;
1105 // bound:
1106 i1 = index_wrap(i1);
1107 i2 = index_wrap(i2);
1108 // interp:
1109 const T v1 = read(i1, channel);
1110 const T v2 = read(i2, channel);
1111 write(v1 + (1.-alpha)*(valuef-v1), i1, channel);
1112 write(v2 + (alpha)*(valuef-v2), i2, channel);
1113 }
1114 };
1115
1116 // DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit
1117 #define DATA_MAXIMUM_ELEMENTS (33554432)
1118
1119 struct Data : public DataInterface<t_sample> {
1120 t_genlib_data * dataRef; // a pointer to some external source of the data
1121
1122 Data() : DataInterface<t_sample>() {
1123 dataRef = 0;
1124 }
1125 ~Data() {
1126 //genlib_report_message("releasing data handle %d", dataRef);
1127 if (dataRef != 0) {
1128 genlib_data_release(dataRef);
1129 }
1130 }
1131 void reset(const char * name, long s, long c) {
1132 // if needed, acquire the Data's global reference:
1133 if (dataRef == 0) {
1134 void * ref = genlib_obtain_reference_from_string(name);
1135 dataRef = genlib_obtain_data_from_reference(ref);
1136 if (dataRef == 0) {
1137 genlib_report_error("failed to acquire data");
1138 return;
1139 }
1140 }
1141 genlib_data_resize(dataRef, s, c);
1142 getinfo();
1143 }
1144 bool setbuffer(void * bufferRef) {
1145 //genlib_report_message("set buffer %p", bufferRef);
1146 if (dataRef == 0) {
1147 // error: no data, or obtain?
1148 return false;
1149 }
1150 genlib_data_setbuffer(dataRef, bufferRef);
1151 getinfo();
1152 return true;
1153 }
1154
1155 void getinfo() {
1156 t_genlib_data_info info;
1157 if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) {
1158 mData = info.data;
1159 dim = info.dim;
1160 channels = info.channels;
1161 } else {
1162 genlib_report_error("failed to acquire data info");
1163 }
1164 }
1165 };
1166
1167 // Used by SineData
1168 struct DataLocal : public DataInterface<t_sample> {
1169 DataLocal() : DataInterface<t_sample>() {}
1170 ~DataLocal() {
1171 if (mData) sysmem_freeptr(mData);
1172 mData = 0;
1173 }
1174
1175 void reset(long s, long c) {
1176 mData=0;
1177 resize(s, c);
1178 }
1179
1180 void resize(long s, long c) {
1181 if (s * c > DATA_MAXIMUM_ELEMENTS) {
1182 s = DATA_MAXIMUM_ELEMENTS/c;
1183 genlib_report_message("warning: resizing data to < 256MB");
1184 }
1185 if (mData) {
1186 sysmem_resizeptr(mData, sizeof(t_sample) * s * c);
1187 } else {
1188 mData = (t_sample *)sysmem_newptr(sizeof(t_sample) * s * c);
1189 }
1190 if (!mData) {
1191 genlib_report_error("out of memory");
1192 resize(512, 1);
1193 return;
1194 } else {
1195 dim = s;
1196 channels = c;
1197 }
1198 set_zero64(mData, dim * channels);
1199 }
1200
1201 // copy from a buffer~
1202 // resizing is safe only during initialization!
1203 bool setbuffer(void *dataReference) {
1204 mDataReference = dataReference; // replaced mName
1205 bool result = false;
1206 t_genlib_buffer * b;
1207 t_genlib_buffer_info info;
1208 if (mDataReference != 0) {
1209 b = (t_genlib_buffer *)genlib_obtain_buffer_from_reference(mDataReference);
1210 if (b) {
1211 if (genlib_buffer_edit_begin(b)==GENLIB_ERR_NONE) {
1212 if (genlib_buffer_getinfo(b, &info)==GENLIB_ERR_NONE) {
1213 float * samples = info.b_samples;
1214 long frames = info.b_frames;
1215 long nchans = info.b_nchans;
1216 //long size = info.b_size;
1217 //long modtime = info.b_modtime; // cache & compare?
1218
1219 // resizing is safe only during initialization!
1220 if (mData == 0) resize(frames, nchans);
1221
1222 long frames_safe = frames < dim ? frames : dim;
1223 long channels_safe = nchans < channels ? nchans : channels;
1224 // copy:
1225 for (int f=0; f<frames_safe; f++) {
1226 for (int c=0; c<channels_safe; c++) {
1227 t_sample value = samples[c+f*nchans];
1228 write(value, f, c);
1229 }
1230 }
1231 result = true;
1232 } else {
1233 genlib_report_message("couldn't get info for buffer\n");
1234 }
1235 genlib_buffer_edit_end(b, 1);
1236 } else {
1237 genlib_report_message("buffer locked\n");
1238 }
1239 }
1240 } else {
1241 genlib_report_message("buffer reference not valid");
1242 }
1243 return result;
1244 }
1245 };
1246
1247 struct Buffer : public DataInterface<float> {
1248 t_genlib_buffer * mBuf;
1249 t_genlib_buffer_info mInfo;
1250 float mDummy; // safe access in case buffer is not valid
1251
1252 Buffer() : DataInterface<float>() {}
1253
1254 void reset(const char * name) {
1255 dim = 1;
1256 channels = 1;
1257 mData = &mDummy;
1258 mDummy = 0.f;
1259 mBuf = 0;
1260
1261 // call into genlib:
1262 mDataReference = genlib_obtain_reference_from_string(name);
1263 }
1264
1265 void setbuffer(void * ref) {
1266 mDataReference = ref;
1267 }
1268
1269 void begin() {
1270 t_genlib_buffer * b = genlib_obtain_buffer_from_reference(mDataReference);
1271 mBuf = 0;
1272 if (b) {
1273 if (genlib_buffer_perform_begin(b) == GENLIB_ERR_NONE) {
1274 mBuf = b;
1275 } else {
1276 //genlib_report_message ("not a buffer~ %s", mName->s_name);
1277 }
1278 } else {
1279 //genlib_report_message("no object %s\n", mName->s_name);
1280 }
1281
1282 if (mBuf && genlib_buffer_getinfo(mBuf, &mInfo)==GENLIB_ERR_NONE) {
1283 // grab data:
1284 mBuf = b;
1285 mData = mInfo.b_samples;
1286 dim = mInfo.b_frames;
1287 channels = mInfo.b_nchans;
1288 } else {
1289 //genlib_report_message("couldn't get info");
1290 mBuf = 0;
1291 mData = &mDummy;
1292 dim = 1;
1293 channels = 1;
1294 }
1295 }
1296
1297 void end() {
1298 if (mBuf) {
1299 genlib_buffer_perform_end(mBuf);
1300 if (modified) {
1301 genlib_buffer_dirty(mBuf);
1302 }
1303 modified = 0;
1304 }
1305 mBuf = 0;
1306 }
1307 };
1308
1309 struct SineData : public DataLocal {
1310 SineData() : DataLocal() {
1311 const int costable_size = 1 << 14; // 14 bit index (noise floor at around -156 dB)
1312 mData=0;
1313 resize(costable_size, 1);
1314 for (int i=0; i<dim; i++) {
1315 mData[i] = cos(i * GENLIB_PI * 2. / (double)(dim));
1316 }
1317 }
1318
1319 ~SineData() {
1320 if (mData) sysmem_freeptr(mData);
1321 mData = 0;
1322 }
1323 };
1324
1325 template<typename T>
1326 inline int dim(const T& data) { return data.dim; }
1327
1328 template<typename T>
1329 inline int channels(const T& data) { return data.channels; }
1330
1331 // used by cycle when no buffer/data is specified:
1332 struct SineCycle {
1333
1334 uint32_t phasei, pincr;
1335 double f2i;
1336
1337 void reset(t_sample samplerate, t_sample init = 0) {
1338 phasei = init * t_sample(4294967296.0);
1339 pincr = 0;
1340 f2i = t_sample(4294967296.0) / samplerate;
1341 }
1342
1343 inline void freq(t_sample f) {
1344 pincr = f * f2i;
1345 }
1346
1347 inline void phase(t_sample f) {
1348 phasei = f * t_sample(4294967296.0);
1349 }
1350
1351 inline t_sample phase() const {
1352 return phasei * t_sample(0.232830643653869629e-9);
1353 }
1354
1355 template<typename T>
1356 inline t_sample operator()(const DataInterface<T>& buf) {
1357 T * data = buf.mData;
1358 // divide uint32_t range down to buffer size (32-bit to 14-bit)
1359 uint32_t idx = phasei >> 18;
1360 // compute fractional portion and divide by 18-bit range
1361 const t_sample frac = t_sample(phasei & 262143) * t_sample(3.81471181759574e-6);
1362 // index safely in 14-bit range:
1363 const t_sample y0 = data[idx];
1364 const t_sample y1 = data[(idx+1) & 16383];
1365 const t_sample y = linear_interp(frac, y0, y1);
1366 phasei += pincr;
1367 return y;
1368 }
1369 };
1370
1371 #endif