Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/plugins/common/gen_dsp/genlib_ops.h @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
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 |