12
|
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
|