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