| 
							- /*******************************************************************************************************************
 - Copyright (c) 2012 Cycling '74
 - 
 - Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 - and associated documentation files (the "Software"), to deal in the Software without restriction,
 - including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 - and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 - subject to the following conditions:
 - 
 - The above copyright notice and this permission notice shall be included in all copies
 - or substantial portions of the Software.
 - 
 - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 - OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 - *******************************************************************************************************************/
 - 
 - #ifndef GENLIB_OPS_H
 - #define GENLIB_OPS_H 1
 - 
 - #include "genlib_common.h"	// common to common code and any host code
 - #include "genlib.h"			// this file is different for different "hosts"
 - 
 - #include <cmath>
 - 
 - //////////// genlib_ops.h ////////////
 - 
 - // system constants
 - #define GENLIB_DBL_EPSILON (__DBL_EPSILON__)
 - 
 - #define GENLIB_PI (3.14159265358979323846264338327950288f)
 - #define GENLIB_PI_OVER_2 (1.57079632679489661923132169163975144f)
 - #define GENLIB_PI_OVER_4 (0.785398163397448309615660845819875721f)
 - #define GENLIB_1_OVER_LOG_2 (1.442695040888963f)
 - 
 - #define GENLIB_NO_DENORM_TEST 1
 - 
 - // assumes v is a 64-bit double:
 - #define GENLIB_IS_NAN_DOUBLE(v)			(((((uint32_t *)&(v))[1])&0x7fe00000)==0x7fe00000) 
 - #define GENLIB_FIX_NAN_DOUBLE(v)		((v)=GENLIB_IS_NAN_DOUBLE(v)?0.:(v))
 - 
 - #ifdef GENLIB_NO_DENORM_TEST
 - 	#define GENLIB_IS_DENORM_DOUBLE(v)	(v)
 - 	#define GENLIB_FIX_DENORM_DOUBLE(v)	(v)
 - #else
 - 	#define GENLIB_IS_DENORM_DOUBLE(v)	((((((uint32_t *)&(v))[1])&0x7fe00000)==0)&&((v)!=0.))
 - 	#define GENLIB_FIX_DENORM_DOUBLE(v)	((v)=GENLIB_IS_DENORM_DOUBLE(v)?0.f:(v))
 - #endif
 - 
 - #define GENLIB_QUANT(f1,f2)			(floor((f1)*(f2)+0.5)/(f2))
 - 
 - inline double genlib_isnan(double v) { return GENLIB_IS_NAN_DOUBLE(v); }
 - inline double fixnan(double v) { return GENLIB_FIX_NAN_DOUBLE(v); }
 - inline double fixdenorm(double v) { return GENLIB_FIX_DENORM_DOUBLE(v); }
 - inline double isdenorm(double v) { return GENLIB_IS_DENORM_DOUBLE(v); }
 - 
 - inline double safemod(double f, double m) {
 - 	if (m > GENLIB_DBL_EPSILON || m < -GENLIB_DBL_EPSILON) {
 - 		if (m<0) 
 - 			m = -m; // modulus needs to be absolute value		
 - 		if (f>=m) {
 - 			if (f>=(m*2.)) {
 - 				double d = f / m;
 - 				d = d - (long) d;
 - 				f = d * m;
 - 			} 
 - 			else {
 - 				f -= m;
 - 			}
 - 		} 
 - 		else if (f<=(-m)) {
 - 			if (f<=(-m*2.)) {
 - 				double d = f / m;
 - 				d = d - (long) d;
 - 				f = d * m;
 - 			}
 - 			 else {
 - 				f += m;
 - 			}
 - 		}
 - 	} else {
 - 		f = 0.0; //don't divide by zero
 - 	}
 - 	return f;
 - }
 - 
 - 
 - inline double safediv(double num, double denom) {
 - 	return denom == 0. ? 0. : num/denom;
 - }
 - 
 - // fixnan for case of negative base and non-integer exponent:
 - inline double safepow(double base, double exponent) {
 - 	return fixnan(pow(base, exponent));
 - }
 - 
 - inline double absdiff(double a, double b) { return fabs(a-b); }
 - 
 - inline double exp2(double v) { return pow(2., v); }
 - 
 - inline double trunc(double v) {
 - 	double epsilon = (v<0.0) * -2 * 1E-9 + 1E-9;
 - 	// copy to long so it gets truncated (probably cheaper than floor())
 - 	long val = v + epsilon;
 - 	return val;
 - }
 - 
 - inline t_sample sign(t_sample v) { 
 - 	return v > t_sample(0) ? t_sample(1) : v < t_sample(0) ? t_sample(-1) : t_sample(0); 
 - }
 - 
 - inline long is_poweroftwo(long x) {
 - 	return (x & (x - 1)) == 0;
 - }
 - 
 - inline uint64_t next_power_of_two(uint64_t v) {
 -     v--;
 -     v |= v >> 1;
 -     v |= v >> 2;
 -     v |= v >> 4;
 -     v |= v >> 8;
 -     v |= v >> 16;
 -     v |= v >> 32;
 -     v++;
 -     return v;
 - }
 - 
 - inline t_sample fold(t_sample v, t_sample lo1, t_sample hi1){
 - 	t_sample lo;
 - 	t_sample hi;
 - 	if(lo1 == hi1){ return lo1; }
 - 	if (lo1 > hi1) {	
 - 		hi = lo1; lo = hi1;
 - 	} else {
 - 		lo = lo1; hi = hi1;
 - 	}
 - 	const t_sample range = hi - lo;
 - 	long numWraps = 0;
 - 	if(v >= hi){
 - 		v -= range;
 - 		if(v >= hi){
 - 			numWraps = (long)((v - lo)/range);
 - 			v -= range * (t_sample)numWraps;
 - 		}
 - 		numWraps++;
 - 	} else if(v < lo){
 - 		v += range;
 - 		if(v < lo){
 - 			numWraps = (long)((v - lo)/range) - 1;
 - 			v -= range * (t_sample)numWraps;
 - 		}
 - 		numWraps--;
 - 	}
 - 	if(numWraps & 1) v = hi + lo - v;	// flip sign for odd folds
 - 	return v;
 - }
 - 
 - inline double wrap(double v, double lo1, double hi1){
 - 	double lo;
 - 	double hi;
 - 	if(lo1 == hi1) return lo1;
 - 	if (lo1 > hi1) {	
 - 		hi = lo1; lo = hi1;
 - 	} else {
 - 		lo = lo1; hi = hi1;
 - 	}
 - 	const double range = hi - lo;
 - 	if (v >= lo && v < hi) return v;
 - 	if (range <= 0.000000001) return lo;	// no point... 
 - 	const long numWraps = long((v-lo)/range) - (v < lo);
 - 	return v - range * double(numWraps);
 - }
 - 
 - // this version gives far better performance when wrapping is relatively rare
 - // and typically double of wraps is very low (>1%)
 - // but catastrophic if wraps is high (1000%+)
 - inline t_sample genlib_wrapfew(t_sample v, t_sample lo, t_sample hi){
 - 	const t_sample range = hi - lo;
 - 	while (v >= hi) v -= range;
 - 	while (v < lo) v += range;
 - 	return v;
 - }
 - 
 - inline t_sample phasewrap(t_sample val) {
 - 	const t_sample twopi = GENLIB_PI*2.;
 - 	const t_sample oneovertwopi = 1./twopi;
 - 	if (val>= twopi || val <= twopi) {
 - 		t_sample d = val * oneovertwopi;	//multiply faster
 - 		d = d - (long)d;
 - 		val = d * twopi;
 - 	}	
 - 	if (val > GENLIB_PI) val -= twopi;
 - 	if (val < -GENLIB_PI) val += twopi;
 - 	return val;
 - }
 - 
 - /// 8th order Taylor series approximation to a cosine.
 - /// r must be in [-pi, pi].
 - inline t_sample genlib_cosT8(t_sample r) {
 - 	const t_sample t84 = 56.;
 - 	const t_sample t83 = 1680.;
 - 	const t_sample t82 = 20160.;
 - 	const t_sample t81 = 2.4801587302e-05;
 - 	const t_sample t73 = 42.;
 - 	const t_sample t72 = 840.;
 - 	const t_sample t71 = 1.9841269841e-04;
 - 	if(r < GENLIB_PI_OVER_4 && r > -GENLIB_PI_OVER_4){
 - 		t_sample rr = r*r;
 - 		return 1. - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)));
 - 	}
 - 	else if(r > 0.){
 - 		r -= GENLIB_PI_OVER_2;
 - 		t_sample rr = r*r;
 - 		return -r * (1. - t71 * rr * (t72 - rr * (t73 - rr)));
 - 	}
 - 	else{
 - 		r += GENLIB_PI_OVER_2;
 - 		t_sample rr = r*r;
 - 		return r * (1. - t71 * rr * (t72 - rr * (t73 - rr)));
 - 	}
 - }
 - 
 - //inline double genlib_sin_fast(const double r){
 - //	const double y = (4./GENLIB_PI) * r + (-4./(GENLIB_PI*GENLIB_PI)) * r * fabs(r);
 - //	return 0.225 * (y * fabs(y) - y) + y;   // Q * y + P * y * abs(y)
 - //}
 - //
 - //inline t_sample genlib_sinP7(t_sample n){
 - //	t_sample nn = n*n;
 - //	return n * (t_sample(3.138982) + nn * (t_sample(-5.133625) + nn * (t_sample(2.428288) - nn * t_sample(0.433645))));
 - //}
 - //
 - //inline t_sample genlib_sinP9(t_sample n){
 - //	t_sample nn = n*n;
 - //	return n * (GENLIB_PI + nn * (t_sample(-5.1662729) + nn * (t_sample(2.5422065) + nn * (t_sample(-0.5811243) + nn * t_sample(0.0636716)))));
 - //}
 - //
 - //inline t_sample genlib_sinT7(t_sample r){
 - //	const t_sample t84 = 56.;
 - //	const t_sample t83 = 1680.;
 - //	const t_sample t82 = 20160.;
 - //	const t_sample t81 = 2.4801587302e-05;
 - //	const t_sample t73 = 42.;
 - //	const t_sample t72 = 840.;
 - //	const t_sample t71 = 1.9841269841e-04;
 - //	if(r < GENLIB_PI_OVER_4 && r > -GENLIB_PI_OVER_4){
 - //		t_sample rr = r*r;
 - //		return r * (1. - t71 * rr * (t72 - rr * (t73 - rr)));
 - //	}
 - //	else if(r > 0.){
 - //		r -= GENLIB_PI_OVER_2;
 - //		t_sample rr = r*r;
 - //		return t_sample(1.) - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)));
 - //	}
 - //	else{
 - //		r += GENLIB_PI_OVER_2;
 - //		t_sample rr = r*r;
 - //		return t_sample(-1.) + rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)));
 - //	}
 - //}
 - 
 - // use these if r is not known to be in [-pi, pi]:
 - inline t_sample genlib_cosT8_safe(t_sample r) { return genlib_cosT8(phasewrap(r)); }
 - //inline double genlib_sin_fast_safe(double r) { return genlib_sin_fast(phasewrap(r)); }
 - //inline t_sample genlib_sinP7_safe(t_sample r) { return genlib_sinP7(phasewrap(r)); }
 - //inline t_sample genlib_sinP9_safe(t_sample r) { return genlib_sinP9(phasewrap(r)); }
 - //inline t_sample genlib_sinT7_safe(t_sample r) { return genlib_sinT7(phasewrap(r)); }
 - 
 - 
 - 
 - /*=====================================================================*
 -  *                   Copyright (C) 2011 Paul Mineiro                   *
 -  * All rights reserved.                                                *
 -  *                                                                     *
 -  * Redistribution and use in source and binary forms, with             *
 -  * or without modification, are permitted provided that the            *
 -  * following conditions are met:                                       *
 -  *                                                                     *
 -  *     * Redistributions of source code must retain the                *
 -  *     above copyright notice, this list of conditions and             *
 -  *     the following disclaimer.                                       *
 -  *                                                                     *
 -  *     * Redistributions in binary form must reproduce the             *
 -  *     above copyright notice, this list of conditions and             *
 -  *     the following disclaimer in the documentation and/or            *
 -  *     other materials provided with the distribution.                 *
 -  *                                                                     *
 -  *     * Neither the name of Paul Mineiro nor the names                *
 -  *     of other contributors may be used to endorse or promote         *
 -  *     products derived from this software without specific            *
 -  *     prior written permission.                                       *
 -  *                                                                     *
 -  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND              *
 -  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,         *
 -  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES               *
 -  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE             *
 -  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER               *
 -  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,                 *
 -  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES            *
 -  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE           *
 -  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR                *
 -  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF          *
 -  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           *
 -  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY              *
 -  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE             *
 -  * POSSIBILITY OF SUCH DAMAGE.                                         *
 -  *                                                                     *
 -  * Contact: Paul Mineiro <paul@mineiro.com>                            *
 -  *=====================================================================*/
 - 
 - inline float genlib_fastersin (float x) {
 - 	static const float fouroverpi = 1.2732395447351627f;
 - 	static const float fouroverpisq = 0.40528473456935109f;
 - 	static const float q = 0.77633023248007499f;
 - 	union { float f; uint32_t i; } p = { 0.22308510060189463f };
 - 	union { float f; uint32_t i; } vx = { x };
 - 	uint32_t sign = vx.i & 0x80000000;
 - 	vx.i &= 0x7FFFFFFF;
 - 	float qpprox = fouroverpi * x - fouroverpisq * x * vx.f;
 - 	p.i |= sign;
 - 	return qpprox * (q + p.f * qpprox);
 - }
 - 
 - inline float genlib_fastercos (float x) {
 - 	static const float twooverpi = 0.63661977236758134f;
 - 	static const float p = 0.54641335845679634f;
 - 	union { float f; uint32_t i; } vx = { x };
 - 	vx.i &= 0x7FFFFFFF;
 - 	float qpprox = 1.0f - twooverpi * vx.f;
 - 	return qpprox + p * qpprox * (1.0f - qpprox * qpprox);
 - }
 - 
 - inline float genlib_fastersinfull (float x) {
 - 	static const float twopi = 6.2831853071795865f;
 - 	static const float invtwopi = 0.15915494309189534f;
 - 	int k = x * invtwopi;
 - 	float half = (x < 0) ? -0.5f : 0.5f;
 - 	return genlib_fastersin ((half + k) * twopi - x);
 - }
 -  
 - inline float genlib_fastercosfull (float x) {
 - 	static const float halfpi = 1.5707963267948966f;
 - 	return genlib_fastersinfull (x + halfpi);
 - }
 -  
 - inline float genlib_fastertanfull (float x) {
 - 	static const float twopi = 6.2831853071795865f;
 - 	static const float invtwopi = 0.15915494309189534f;
 - 	int k = x * invtwopi;
 - 	float half = (x < 0) ? -0.5f : 0.5f;
 - 	float xnew = x - (half + k) * twopi;
 - 	return genlib_fastersin (xnew) / genlib_fastercos (xnew);
 - }
 - 
 - 
 - #define cast_uint32_t static_cast<uint32_t>
 - inline float genlib_fasterpow2 (float p) {
 - 	float clipp = (p < -126) ? -126.0f : p;
 - 	union { uint32_t i; float f; } v = { cast_uint32_t ( (1 << 23) * (clipp + 126.94269504f) ) };
 - 	return v.f;
 - }
 - 
 - inline float genlib_fasterexp (float p) {
 - 	return genlib_fasterpow2 (1.442695040f * p);
 - }
 - 
 - inline float genlib_fasterlog2 (float x) {
 - 	union { float f; uint32_t i; } vx = { x };
 - 	float y = vx.i;
 - 	y *= 1.1920928955078125e-7f;
 - 	return y - 126.94269504f;
 - }
 - 
 - inline float genlib_fasterpow (float x, float p) {
 - 	return genlib_fasterpow2(p * genlib_fasterlog2 (x));
 - }
 - 
 - ////////////////////////////////////////////////////////////////
 - 
 - inline double fastertanfull(double x) {
 - 	return (double)genlib_fastertanfull((float)x);
 - }
 - 
 - inline double fastersinfull(double x) {
 - 	return (double)genlib_fastersinfull((float)x);
 - }
 - 
 - inline double fastercosfull(double x) {
 - 	return (double)genlib_fastercosfull((float)x);
 - }
 - 
 - inline double fasterexp(double x) {
 - 	return (double)genlib_fasterexp((float)x);
 - }
 - 
 - inline double fasterpow(double x, double p) {
 - 	return (double)genlib_fasterpow((float)x, (float)p);
 - }
 - /****************************************************************/
 - 
 - 
 - 
 - inline double minimum(double x, double y) { return (y<x?y:x); }
 - inline double maximum(double x, double y) { return (x<y?y:x); }
 - 
 - inline t_sample clamp(t_sample x, t_sample minVal, t_sample maxVal) { 
 - 	return minimum(maximum(x,minVal),maxVal); 
 - }
 - 
 - template<typename T>
 - inline T smoothstep(double e0, double e1, T x) {
 - 	T t = clamp( safediv(x-T(e0),T(e1-e0)), 0., 1. );
 - 	return t*t*(T(3) - T(2)*t);
 - }
 - 
 - inline t_sample mix(t_sample x, t_sample y, t_sample a) { 
 - 	return x+a*(y-x); 
 - }
 - 
 - inline double scale(double in, double inlow, double inhigh, double outlow, double outhigh, double power)
 - {
 - 	double value;
 - 	double inscale = safediv(1., inhigh - inlow);
 - 	double outdiff = outhigh - outlow;
 - 	
 - 	value = (in - inlow) * inscale;
 - 	if (value > 0.0)
 - 		value = pow(value, power);
 - 	else if (value < 0.0)
 - 		value = -pow(-value, power);
 - 	value = (value * outdiff) + outlow;
 - 	
 - 	return value;
 - }
 - 
 - inline t_sample linear_interp(t_sample a, t_sample x, t_sample y) {
 - 	return x+a*(y-x); 
 - }
 - 
 - inline t_sample cosine_interp(t_sample a, t_sample x, t_sample y) {
 - 	const t_sample a2 = (t_sample(1.)-genlib_cosT8_safe(a*t_sample(GENLIB_PI)))/t_sample(2.);
 - 	return(x*(t_sample(1.)-a2)+y*a2);
 - }
 - 
 - inline t_sample cubic_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_sample z) {
 - 	const t_sample a2 = a*a;
 - 	const t_sample f0 = z - y - w + x;
 - 	const t_sample f1 = w - x - f0;
 - 	const t_sample f2 = y - w;
 - 	const t_sample f3 = x;
 - 	return(f0*a*a2 + f1*a2 + f2*a + f3);
 - }
 - 
 - // Breeuwsma catmull-rom spline interpolation
 - inline t_sample spline_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_sample z) {
 - 	const t_sample a2 = a*a;
 - 	const t_sample f0 = t_sample(-0.5)*w + t_sample(1.5)*x - t_sample(1.5)*y + t_sample(0.5)*z;
 - 	const t_sample f1 = w - t_sample(2.5)*x + t_sample(2)*y - t_sample(0.5)*z;
 - 	const t_sample f2 = t_sample(-0.5)*w + t_sample(0.5)*y;
 - 	return(f0*a*a2 + f1*a2 + f2*a + x);
 - }
 - 
 - template<typename T1, typename T2>
 - inline T1 neqp(T1 x, T2 y) { 
 - 	return ((((x) != T1(y))) ? (x) : T1(0));
 - }
 - 
 - template<typename T1, typename T2>
 - inline T1 gtp(T1 x, T2 y) { return ((((x) > T1(y))) ? (x) : T1(0)); }
 - template<typename T1, typename T2>
 - inline T1 gtep(T1 x, T2 y) { return ((((x) >= T1(y))) ? (x) : T1(0)); }
 - template<typename T1, typename T2>
 - inline T1 ltp(T1 x, T2 y) { return ((((x) < T1(y))) ? (x) : T1(0)); }
 - template<typename T1, typename T2>
 - inline T1 ltep(T1 x, T2 y) { return ((((x) <= T1(y))) ? (x) : T1(0)); }
 - 
 - inline double fract(double x) { double unused; return modf(x, &unused); }
 - 
 - // log2(x) = log(x)/log(2)
 - template<typename T>
 - inline T log2(T x) { 
 - 	return log(x)*GENLIB_1_OVER_LOG_2; 
 - }
 - 
 - inline double atodb(double in) {
 - 	return (in <=0.) ? -999. : (20. * log10(in));
 - }
 - 
 - inline double dbtoa(double in) {
 - 	return pow(10., in * 0.05);
 - }
 - 
 - inline double ftom(double in, double tuning=440.) {
 - 	return 69. + 17.31234050465299 * log(safediv(in, tuning));
 - }
 - 
 - inline double mtof(double in, double tuning=440.) {
 - 	return tuning * exp(.057762265 * (in - 69.0));
 - }
 - 
 - inline t_sample mstosamps(t_sample ms, t_sample samplerate=44100.) {
 - 	return samplerate * ms * t_sample(0.001);
 - }
 - 
 - inline t_sample sampstoms(t_sample s, t_sample samplerate=44100.) {
 - 	return t_sample(1000.) * s / samplerate;
 - }
 - 
 - inline double triangle(double phase, double p1) {
 - 	phase = wrap(phase, 0., 1.);
 - 	p1 = clamp(p1, 0., 1.);
 - 	if (phase < p1)
 - 		return (p1) ? phase/p1 : 0.;
 - 	else
 - 		return (p1==1.) ? phase : 1. - ((phase - p1) / (1. - p1));
 - }
 - 
 - struct Delta {
 - 	t_sample history;
 - 	Delta() { reset(); }
 - 	inline void reset(t_sample init=0) { history=init; }
 - 	
 - 	inline t_sample operator()(t_sample in1) {
 - 		t_sample ret = in1 - history;
 - 		history = in1;
 - 		return ret;
 - 	}
 - };
 - struct Change {
 - 	t_sample history;
 - 	Change() { reset(); }
 - 	inline void reset(t_sample init=0) { history=init; }
 - 	
 - 	inline t_sample operator()(t_sample in1) {
 - 		t_sample ret = in1 - history;
 - 		history = in1;
 - 		return sign(ret);
 - 	}
 - };
 - 
 - struct Rate {
 - 	t_sample phase, diff, mult, invmult, prev;
 - 	int wantlock, quant;
 - 	
 - 	Rate() { reset(); }
 - 	
 - 	inline void reset() {
 - 		phase = diff = prev = 0;
 - 		mult = invmult = 1;
 - 		wantlock = 1;
 - 		quant = 1;
 - 	}
 - 	
 - 	inline t_sample perform_lock(t_sample in1, t_sample in2) {
 - 		// did multiplier change?
 - 		if (in2 != mult && !genlib_isnan(in2)) {
 - 			mult = in2;
 - 			invmult = safediv(1., mult);
 - 			wantlock = 1;
 - 		}
 - 		t_sample diff = in1 - prev;
 - 		
 - 		if (diff < t_sample(-0.5)) {
 - 			diff += t_sample(1);
 - 		} else if (diff > t_sample(0.5)) {
 - 			diff -= t_sample(1);
 - 		}
 - 		
 - 		if (wantlock) {
 - 			// recalculate phase
 - 			phase = (in1 - GENLIB_QUANT(in1, quant)) * invmult 
 - 						+ GENLIB_QUANT(in1, quant * mult);
 - 			diff = 0;
 - 			wantlock = 0;
 - 		} else {
 - 			// diff is always between -0.5 and 0.5
 - 			phase += diff * invmult;
 - 		}
 - 		
 - 		if (phase > t_sample(1.) || phase < t_sample(-0.)) {
 - 			phase = phase - (long)(phase);
 - 		}	
 - 		
 - 		prev = in1;
 - 		
 - 		return phase;
 - 	}
 - 	
 - 	inline t_sample perform_cycle(t_sample in1, t_sample in2) {
 - 		// did multiplier change?
 - 		if (in2 != mult && !genlib_isnan(in2)) {
 - 			mult = in2;
 - 			invmult = safediv(1., mult);
 - 			wantlock = 1;
 - 		}
 - 		t_sample diff = in1 - prev;
 - 		
 - 		if (diff < t_sample(-0.5)) {
 - 			if (wantlock) {
 - 				wantlock = 0;
 - 				phase = in1 * invmult;
 - 				diff = t_sample(0);
 - 			} else {
 - 				diff += t_sample(1);
 - 			}
 - 		} else if (diff > t_sample(0.5)) {
 - 			if (wantlock) {
 - 				wantlock = 0;
 - 				phase = in1 * invmult;
 - 				diff = t_sample(0);
 - 			} else {
 - 				diff -= t_sample(1);
 - 			}
 - 		}
 - 		
 - 		// diff is always between -0.5 and 0.5
 - 		phase += diff * invmult;
 - 		
 - 		if (phase > t_sample(1.) || phase < t_sample(-0.)) {
 - 			phase = phase - (long)(phase);
 - 		}	
 - 		
 - 		prev = in1;
 - 		
 - 		return phase;
 - 	}
 - 	
 - 	inline t_sample perform_off(double in1, double in2) {
 - 		// did multiplier change?
 - 		if (in2 != mult && !genlib_isnan(in2)) {
 - 			mult = in2;
 - 			invmult = safediv(1., mult);
 - 			wantlock = 1;
 - 		}
 - 		double diff = in1 - prev;
 - 		
 - 		if (diff < t_sample(-0.5)) {
 - 			diff += t_sample(1);
 - 		} else if (diff > t_sample(0.5)) {
 - 			diff -= t_sample(1);
 - 		}
 - 		
 - 		phase += diff * invmult;
 - 		
 - 		if (phase > t_sample(1.) || phase < t_sample(-0.)) {
 - 			phase = phase - (long)(phase);
 - 		}	
 - 		
 - 		prev = in1;
 - 		
 - 		return phase;
 - 	}
 - };
 - 
 - struct DCBlock {
 - 	t_sample x1, y1;
 - 	DCBlock() { reset(); }
 - 	inline void reset() { x1=0; y1=0; }
 - 	
 - 	inline double operator()(t_sample in1) {
 - 		t_sample y = in1 - x1 + y1*t_sample(0.9997);
 - 		x1 = in1;
 - 		y1 = y;
 - 		return y;
 - 	}
 - };
 - 
 - struct Noise {
 - 	unsigned long last;
 - 	static long uniqueTickCount(void) {
 - 		static long lasttime = 0;
 - 		long time = genlib_ticks();
 - 		return (time <= lasttime) ? (++lasttime) : (lasttime = time);
 - 	}
 - 	
 - 	Noise() { reset(); }
 - 	Noise(double seed) { reset(seed); }
 - 	void reset() { last = uniqueTickCount() * uniqueTickCount(); }
 - 	void reset(double seed) { last = seed; }
 - 	
 - 	inline t_sample operator()() {
 - 		last = 1664525L * last + 1013904223L;
 - 		unsigned long itemp = 0x3f800000 | (0x007fffff & last);
 - 		unsigned long* itempptr = &itemp;
 - 		return ((*(float *)itempptr) * 2.f) - 3.f;
 - 	}
 - };
 - 
 - struct Phasor {
 - 	t_sample phase;
 - 	Phasor() { reset(); }
 - 	void reset(t_sample v=0.) { phase=v; }
 - 	inline double operator()(t_sample freq, t_sample invsamplerate) {
 - 		const t_sample pincr = freq * invsamplerate;
 - 		//phase = genlib_wrapfew(phase + pincr, 0., 1.); // faster for low frequencies, but explodes with high frequencies
 - 		phase = wrap(phase + pincr, 0., 1.);
 - 		return phase;
 - 	}
 - };
 - 
 - struct PlusEquals {
 - 	t_sample count;
 - 	PlusEquals() { reset(); }
 - 	void reset(t_sample v=0.) { count=v; }
 - 	
 - 	// reset post-application mode:
 - 	inline t_sample post(t_sample incr, t_sample reset, t_sample min, t_sample max) {
 - 		count = reset ? min : wrap(count+incr, min, max);
 - 		return count;
 - 	}
 - 	inline t_sample post(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
 - 		count = reset ? min : count+incr;
 - 		return count;
 - 	}
 - 	
 - 	// reset pre-application mode:
 - 	inline t_sample pre(t_sample incr, t_sample reset, t_sample min, t_sample max) {
 - 		count = reset ? min+incr : wrap(count+incr, min, max);
 - 		return count;
 - 	}
 - 	inline t_sample pre(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
 - 		count = reset ? min+incr : count+incr;
 - 		return count;
 - 	}
 - };
 - 
 - struct MulEquals {
 - 	t_sample count;
 - 	MulEquals() { reset(); }
 - 	void reset(t_sample v=0.) { count=v; }
 - 	
 - 	// reset post-application mode:
 - 	inline t_sample post(t_sample incr, t_sample reset, t_sample min, t_sample max) {
 - 		count = reset ? min : wrap(fixdenorm(count*incr), min, max);
 - 		return count;
 - 	}
 - 	inline t_sample post(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
 - 		count = reset ? min : fixdenorm(count*incr);
 - 		return count;
 - 	}
 - 	
 - 	// reset pre-application mode:
 - 	inline t_sample pre(t_sample incr, t_sample reset, t_sample min, t_sample max) {
 - 		count = reset ? min*incr : wrap(fixdenorm(count*incr), min, max);
 - 		return count;
 - 	}
 - 	inline t_sample pre(t_sample incr=1., t_sample reset=0., t_sample min=0.) {
 - 		count = reset ? min*incr : fixdenorm(count*incr);
 - 		return count;
 - 	}
 - };
 - 
 - struct Sah {
 - 	t_sample prev, output;
 - 	Sah() { reset(); }
 - 	void reset(t_sample o=0.) {
 - 		output = prev = o;
 - 	}
 - 	
 - 	inline t_sample operator()(t_sample in, t_sample trig, t_sample thresh) {
 - 		if (prev <= thresh && trig > thresh) {
 - 			output = in;
 - 		}
 - 		prev = trig;
 - 		return output;
 - 	}
 - };
 - 
 - struct Train {
 - 	t_sample phase, state;
 - 	Train() { reset(); }
 - 	void reset(t_sample p=0) { phase = p; state = 0.; }
 - 	
 - 	inline t_sample operator()(t_sample pulseinterval, t_sample width, t_sample pulsephase) {
 - 		if (width <= t_sample(0.)) {
 - 			state = t_sample(0.);	// no pulse!
 - 		} else if (width >= 1.) {
 - 			state = t_sample(1.); // constant pulse!
 - 		} else {
 - 			const t_sample interval = maximum(pulseinterval, t_sample(1.));	// >= 1.
 - 			const t_sample p1 = clamp(pulsephase, t_sample(0.), t_sample(1.));	// [0..1]
 - 			const t_sample p2 = p1+width;						// (p1..p1+1)
 - 			const t_sample pincr = t_sample(1.)/interval;			// (0..1]
 - 			phase += pincr;								// +ve
 - 			if (state) {	// on:
 - 				if (phase > p2) {	
 - 					state = t_sample(0.);				// turn off
 - 					phase -= (int)(1.+phase-p2);		// wrap phase back down
 - 				}
 - 			} else {		// off:
 - 				if (phase > p1) {			
 - 					state = t_sample(1.);				// turn on.
 - 				}
 - 			}
 - 		}
 - 		return state;
 - 	}	
 - };
 - 
 - struct Delay {
 - 	t_sample * memory;
 - 	long size, wrap, maxdelay;
 - 	long reader, writer;
 - 	
 - 	t_genlib_data * dataRef;
 - 	
 - 	Delay() : memory(0) {
 - 		size = wrap = maxdelay = 0;
 - 		reader = writer = 0;
 - 		dataRef = 0;
 - 	}
 - 	~Delay() {
 - 		if (dataRef != 0) {
 - 			// store write position for persistence:
 - 			genlib_data_setcursor(dataRef, writer);
 - 			// decrement reference count:
 - 			genlib_data_release(dataRef);
 - 		}
 - 	}
 - 	
 - 	inline void reset(const char * name, long d) {
 - 		// if needed, acquire the Data's global reference: 
 - 		if (dataRef == 0) {
 - 		
 - 			void * ref = genlib_obtain_reference_from_string(name);
 - 			dataRef = genlib_obtain_data_from_reference(ref);
 - 			if (dataRef == 0) {	
 - 				genlib_report_error("failed to acquire data");
 - 				return; 
 - 			}
 - 			
 - 			// scale maxdelay to next highest power of 2:
 - 			maxdelay = d;
 - 			size = maxdelay < 2 ? 2 : maxdelay;
 - 			size = next_power_of_two(size);
 - 			
 - 			// first reset should resize the memory:
 - 			genlib_data_resize(dataRef, size, 1);
 - 			
 - 			t_genlib_data_info info;
 - 			if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) {
 - 				if (info.dim != size) {
 - 					// at this point, could resolve by reducing to 
 - 					// maxdelay = size = next_power_of_two(info.dim+1)/2;
 - 					// but really, if this happens, it means more than one
 - 					// object is referring to the same t_gen_dsp_data.
 - 					// which is probably bad news.
 - 					genlib_report_error("delay memory size error");
 - 					memory = 0;
 - 					return;
 - 				}
 - 				memory = info.data;
 - 				writer = genlib_data_getcursor(dataRef);
 - 			} else {
 - 				genlib_report_error("failed to acquire data info");
 - 			}
 - 		
 - 		} else {		
 - 			// subsequent reset should zero the memory & heads:
 - 			set_zero64(memory, size);
 - 			writer = 0;
 - 		}
 - 		
 - 		reader = writer;
 - 		wrap = size-1;
 - 	}
 - 	
 - 	// called at bufferloop end, updates read pointer time
 - 	inline void step() {	
 - 		reader++; 
 - 		if (reader >= size) reader = 0;
 - 	}
 - 	
 - 	inline void write(t_sample x) {
 - 		writer = reader;	// update write ptr
 - 		memory[writer] = x;
 - 	}	
 - 	
 - 	inline t_sample read_step(t_sample d) {
 - 		// extra half for nice rounding:
 - 		// min 1 sample delay for read before write (r != w)
 - 		const t_sample r = t_sample(size + reader) - clamp(d-t_sample(0.5), (reader != writer), maxdelay);	
 - 		long r1 = long(r);
 - 		return memory[r1 & wrap];
 - 	}
 - 	
 - 	inline t_sample read_linear(t_sample d) {
 - 		// min 1 sample delay for read before write (r != w)
 - 		t_sample c = clamp(d, (reader != writer), maxdelay);
 - 		const t_sample r = t_sample(size + reader) - c;	
 - 		long r1 = long(r);
 - 		long r2 = r1+1;
 - 		t_sample a = r - (t_sample)r1;
 - 		t_sample x = memory[r1 & wrap];
 - 		t_sample y = memory[r2 & wrap];
 - 		return linear_interp(a, x, y);
 - 	}
 - 	
 - 	inline t_sample read_cosine(t_sample d) {
 - 		// min 1 sample delay for read before write (r != w)
 - 		const t_sample r = t_sample(size + reader) - clamp(d, (reader != writer), maxdelay);	
 - 		long r1 = long(r);
 - 		long r2 = r1+1;
 - 		t_sample a = r - (t_sample)r1;
 - 		t_sample x = memory[r1 & wrap];
 - 		t_sample y = memory[r2 & wrap];
 - 		return cosine_interp(a, x, y);
 - 	}
 - 	
 - 	// cubic requires extra sample of compensation:
 - 	inline t_sample read_cubic(t_sample d) {
 - 		// min 1 sample delay for read before write (r != w)
 - 		// plus extra 1 sample compensation for 4-point interpolation
 - 		const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.)+t_sample(reader != writer), maxdelay);	
 - 		long r1 = long(r);
 - 		long r2 = r1+1;
 - 		long r3 = r1+2;
 - 		long r4 = r1+3;
 - 		t_sample a = r - (t_sample)r1;
 - 		t_sample w = memory[r1 & wrap];
 - 		t_sample x = memory[r2 & wrap];
 - 		t_sample y = memory[r3 & wrap];
 - 		t_sample z = memory[r4 & wrap];
 - 		return cubic_interp(a, w, x, y, z);
 - 	}
 - 	
 - 	// spline requires extra sample of compensation:
 - 	inline t_sample read_spline(t_sample d) {
 - 		// min 1 sample delay for read before write (r != w)
 - 		// plus extra 1 sample compensation for 4-point interpolation
 - 		const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.)+t_sample(reader != writer), maxdelay);	
 - 		long r1 = long(r);
 - 		long r2 = r1+1;
 - 		long r3 = r1+2;
 - 		long r4 = r1+3;
 - 		t_sample a = r - (t_sample)r1;
 - 		t_sample w = memory[r1 & wrap];
 - 		t_sample x = memory[r2 & wrap];
 - 		t_sample y = memory[r3 & wrap];
 - 		t_sample z = memory[r4 & wrap];
 - 		return spline_interp(a, w, x, y, z);
 - 	}
 - };
 - 
 - template<typename T=t_sample>
 - struct DataInterface {
 - 	long dim, channels;
 - 	T * mData;
 - 	void * mDataReference;		// this was t_symbol *mName
 - 	int modified;
 - 	
 - 	DataInterface() : dim(0), channels(1), mData(0), modified(0) { mDataReference = 0; }
 - 	
 - 	// raw reading/writing/overdubbing (internal use only, no bounds checking)
 - 	inline t_sample read(long index, long channel=0) const { 
 - 		return mData[channel+index*channels]; 
 - 	}	
 - 	inline void write(T value, long index, long channel=0) {
 - 		mData[channel+index*channels] = value; 
 - 		modified = 1;
 - 	}
 - 	// NO LONGER USED:
 - 	inline void overdub(T value, long index, long channel=0) { 
 - 		mData[channel+index*channels] += value; 
 - 		modified = 1;
 - 	}
 - 	
 - 	// averaging overdub (used by splat)
 - 	inline void blend(T value, long index, long channel, t_sample alpha) { 
 - 		long offset = channel+index*channels;
 - 		const T old = mData[offset];
 - 		mData[offset] = old + alpha * (value - old); 
 - 		modified = 1;
 - 	}
 - 	
 - 	// NO LONGER USED:
 - 	inline void read_ok(long index, long channel=0, bool ok=1) const { 
 - 		return ok ? mData[channel+index*channels] : T(0); 
 - 	}	
 - 	inline void write_ok(T value, long index, long channel=0, bool ok=1) { 
 - 		if (ok) mData[channel+index*channels] = value; 
 - 	}
 - 	inline void overdub_ok(T value, long index, long channel=0, bool ok=1) { 
 - 		if (ok) mData[channel+index*channels] += value; 
 - 	}
 - 		
 - 	// Bounds strategies:
 - 	inline long index_clamp(long index) const { return clamp(index, 0, dim-1); } 
 - 	inline long index_wrap(long index) const { return wrap(index, 0, dim); } 
 - 	inline long index_fold(long index) const { return fold(index, 0, dim); } 
 - 	inline bool index_oob(long index) const { return (index < 0 || index >= dim); } 
 - 	inline bool index_inbounds(long index) const { return (index >=0 && index < dim); } 
 - 	
 - 	// channel bounds:
 - 	inline long channel_clamp(long c) const { return clamp(c, 0, channels-1); }
 - 	inline long channel_wrap(long c) const { return wrap(c, 0, channels); } 
 - 	inline long channel_fold(long c) const { return fold(c, 0, channels); } 
 - 	inline bool channel_oob(long c) const { return (c < 0 || c >= channels); }
 - 	inline bool channel_inbounds(long c) const { return !channel_oob(c); } 
 - 
 - 	// Indexing strategies:
 - 	// [0..1] -> [0..(dim-1)]
 - 	inline t_sample phase2index(t_sample phase) const { return phase * t_sample(dim-1); }
 - 	// [0..1] -> [min..max]
 - 	inline t_sample subphase2index(t_sample phase, long min, long max) const { 
 - 		min = index_clamp(min);
 - 		max = index_clamp(max);
 - 		return t_sample(min) + phase * t_sample(max-min); 
 - 	}
 - 	// [-1..1] -> [0..(dim-1)]
 - 	inline t_sample signal2index(t_sample signal) const { return phase2index((signal+t_sample(1.)) * t_sample(0.5)); }
 - 	
 - 	inline T peek(t_sample index, long channel=0) const {
 - 		const long i = (long)index;
 - 		if (index_oob(i) || channel_oob(channel)) {
 - 			return 0.;
 - 		} else {
 - 			return read(i, channel);
 - 		}
 - 	}
 - 	
 - 	inline T index(double index, long channel=0) const {
 - 		channel = channel_clamp(channel);
 - 		// no-interp:
 - 		long i = (long)index;
 - 		// bound:
 - 		i = index_clamp(i);
 - 		return read(i, channel);
 - 	}
 - 	
 - 	inline T cell(double index, long channel=0) const {
 - 		channel = channel_clamp(channel);
 - 		// no-interp:
 - 		long i = (long)index;
 - 		// bound:
 - 		i = index_wrap(i);
 - 		return read(i, channel);
 - 	}
 - 	
 - 	inline T cycle(t_sample phase, long channel=0) const {
 - 		channel = channel_clamp(channel);
 - 		t_sample index = phase2index(phase);
 - 		// interp:
 - 		long i1 = (long)index;
 - 		long i2 = i1+1;
 - 		const t_sample alpha = index - (t_sample)i1;
 - 		// bound:
 - 		i1 = index_wrap(i1);
 - 		i2 = index_wrap(i2);
 - 		// interp:
 - 		T v1 = read(i1, channel);
 - 		T v2 = read(i2, channel);
 - 		return mix(v1, v2, alpha);
 - 	}
 - 	
 - 	inline T lookup(t_sample signal, long channel=0) const {
 - 		channel = channel_clamp(channel);
 - 		t_sample index = signal2index(signal);
 - 		// interp:
 - 		long i1 = (long)index;
 - 		long i2 = i1+1;
 - 		t_sample alpha = index - (t_sample)i1;
 - 		// bound:
 - 		i1 = index_clamp(i1);
 - 		i2 = index_clamp(i2);
 - 		// interp:
 - 		T v1 = read(i1, channel);
 - 		T v2 = read(i2, channel);
 - 		return mix(v1, v2, alpha);
 - 	}
 - 	// NO LONGER USED:
 - 	inline void poke(t_sample value, t_sample index, long channel=0) {
 - 		const long i = (long)index;
 - 		if (!(index_oob(i) || channel_oob(channel))) {
 - 			write(fixdenorm(value), i, channel);
 - 		} 
 - 	}
 - 	// NO LONGER USED:
 - 	inline void splat_adding(t_sample value, t_sample phase, long channel=0) {
 - 		const t_sample valuef = fixdenorm(value);
 - 		channel = channel_clamp(channel);
 - 		t_sample index = phase2index(phase);
 - 		// interp:
 - 		long i1 = (long)index;
 - 		long i2 = i1+1;
 - 		const t_sample alpha = index - (double)i1;
 - 		// bound:
 - 		i1 = index_wrap(i1);
 - 		i2 = index_wrap(i2);
 - 		// interp:
 - 		overdub(valuef*(1.-alpha), i1, channel);
 - 		overdub(valuef*alpha,      i2, channel);
 - 	}
 - 	// NO LONGER USED:
 - 	inline void splat(t_sample value, t_sample phase, long channel=0) {
 - 		const t_sample valuef = fixdenorm(value);
 - 		channel = channel_clamp(channel);
 - 		t_sample index = phase2index(phase);
 - 		// interp:
 - 		long i1 = (long)index;
 - 		long i2 = i1+1;
 - 		const t_sample alpha = index - (t_sample)i1;
 - 		// bound:
 - 		i1 = index_wrap(i1);
 - 		i2 = index_wrap(i2);
 - 		// interp:
 - 		const T v1 = read(i1, channel);
 - 		const T v2 = read(i2, channel);
 - 		write(v1 + (1.-alpha)*(valuef-v1), i1, channel);
 - 		write(v2 + (alpha)*(valuef-v2), i2, channel);
 - 	}
 - };
 - 
 - // DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit
 - #define DATA_MAXIMUM_ELEMENTS	(33554432)
 - 
 - struct Data : public DataInterface<t_sample> {
 - 	t_genlib_data * dataRef;	// a pointer to some external source of the data
 - 	
 - 	Data() : DataInterface<t_sample>() {
 - 		dataRef = 0;
 - 	}
 - 	~Data() { 
 - 		//genlib_report_message("releasing data handle %d", dataRef);
 - 		if (dataRef != 0) {
 - 			genlib_data_release(dataRef);
 - 		}
 - 	}
 - 	void reset(const char * name, long s, long c) {
 - 		// if needed, acquire the Data's global reference: 
 - 		if (dataRef == 0) {
 - 			void * ref = genlib_obtain_reference_from_string(name);
 - 			dataRef = genlib_obtain_data_from_reference(ref);
 - 			if (dataRef == 0) {	
 - 				genlib_report_error("failed to acquire data");
 - 				return; 
 - 			}
 - 		}
 - 		genlib_data_resize(dataRef, s, c);
 - 		getinfo();
 - 	}
 - 	bool setbuffer(void * bufferRef) {
 - 		//genlib_report_message("set buffer %p", bufferRef);
 - 		if (dataRef == 0) {
 - 			// error: no data, or obtain?
 - 			return false;
 - 		}
 - 		genlib_data_setbuffer(dataRef, bufferRef);
 - 		getinfo();
 - 		return true;
 - 	}
 - 	
 - 	void getinfo() {
 - 		t_genlib_data_info info;
 - 		if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) {
 - 			mData = info.data;
 - 			dim = info.dim;
 - 			channels = info.channels;
 - 		} else {
 - 			genlib_report_error("failed to acquire data info");
 - 		}
 - 	}
 - };
 - 
 - // Used by SineData
 - struct DataLocal : public DataInterface<t_sample> {
 - 	DataLocal() : DataInterface<t_sample>() {}
 - 	~DataLocal() { 
 - 		if (mData) sysmem_freeptr(mData);
 - 		mData = 0;
 - 	}
 - 
 - 	void reset(long s, long c) { 
 - 		mData=0; 
 - 		resize(s, c); 
 - 	}
 - 		
 - 	void resize(long s, long c) {
 - 		if (s * c > DATA_MAXIMUM_ELEMENTS) {
 - 			s = DATA_MAXIMUM_ELEMENTS/c;
 - 			genlib_report_message("warning: resizing data to < 256MB");
 - 		}
 - 		if (mData) {
 - 			sysmem_resizeptr(mData, sizeof(t_sample) * s * c);
 - 		} else {
 - 			mData = (t_sample *)sysmem_newptr(sizeof(t_sample) * s * c);
 - 		}
 - 		if (!mData) {
 - 			genlib_report_error("out of memory");
 - 			resize(512, 1);
 - 			return;
 - 		} else {
 - 			dim = s;
 - 			channels = c;
 - 		}
 - 		set_zero64(mData, dim * channels);
 - 	}
 - 
 - 	// copy from a buffer~
 - 	// resizing is safe only during initialization!
 - 	bool setbuffer(void *dataReference) {
 - 		mDataReference = dataReference; // replaced mName
 - 		bool result = false;
 - 		t_genlib_buffer * b;
 - 		t_genlib_buffer_info info;
 - 		if (mDataReference != 0) {
 - 			b = (t_genlib_buffer *)genlib_obtain_buffer_from_reference(mDataReference);
 - 			if (b) {
 - 				if (genlib_buffer_edit_begin(b)==GENLIB_ERR_NONE) {
 - 					if (genlib_buffer_getinfo(b, &info)==GENLIB_ERR_NONE) {
 - 						float * samples = info.b_samples;
 - 						long frames = info.b_frames;
 - 						long nchans = info.b_nchans;
 - 						//long size = info.b_size;
 - 						//long modtime = info.b_modtime;	// cache & compare?
 - 						
 - 						// resizing is safe only during initialization!
 - 						if (mData == 0) resize(frames, nchans);
 - 						
 - 						long frames_safe = frames < dim ? frames : dim;
 - 						long channels_safe = nchans < channels ? nchans : channels;						
 - 						// copy:
 - 						for (int f=0; f<frames_safe; f++) {
 - 							for (int c=0; c<channels_safe; c++) {
 - 								t_sample value = samples[c+f*nchans];
 - 								write(value, f, c);
 - 							}
 - 						}
 - 						result = true;
 - 					} else {
 - 						genlib_report_message("couldn't get info for buffer\n"); 
 - 					}
 - 					genlib_buffer_edit_end(b, 1);
 - 				} else {
 - 					genlib_report_message("buffer locked\n");
 - 				}
 - 			}
 - 		} else {
 - 			genlib_report_message("buffer reference not valid");
 - 		}
 - 		return result;
 - 	}
 - };
 - 
 - struct Buffer : public DataInterface<float> {
 - 	t_genlib_buffer * mBuf;
 - 	t_genlib_buffer_info mInfo;
 - 	float mDummy;		// safe access in case buffer is not valid
 - 	
 - 	Buffer() : DataInterface<float>() {}
 - 	
 - 	void reset(const char * name) {
 - 		dim = 1;
 - 		channels = 1;
 - 		mData = &mDummy;
 - 		mDummy = 0.f;
 - 		mBuf = 0;
 - 		
 - 		// call into genlib:
 - 		mDataReference = genlib_obtain_reference_from_string(name);		
 - 	}
 - 	
 - 	void setbuffer(void * ref) {
 - 		mDataReference = ref;
 - 	}
 - 	
 - 	void begin() {
 - 		t_genlib_buffer * b = genlib_obtain_buffer_from_reference(mDataReference);
 - 		mBuf = 0;
 - 		if (b) {
 - 			if (genlib_buffer_perform_begin(b) == GENLIB_ERR_NONE) {
 - 				mBuf = b;
 - 			} else {
 - 				//genlib_report_message ("not a buffer~ %s", mName->s_name);
 - 			}
 - 		} else {
 - 			//genlib_report_message("no object %s\n", mName->s_name);
 - 		}
 - 		
 - 		if (mBuf && genlib_buffer_getinfo(mBuf, &mInfo)==GENLIB_ERR_NONE) {
 - 			// grab data:
 - 			mBuf = b;
 - 			mData = mInfo.b_samples;
 - 			dim = mInfo.b_frames;
 - 			channels = mInfo.b_nchans;
 - 		} else {
 - 			//genlib_report_message("couldn't get info");
 - 			mBuf = 0;
 - 			mData = &mDummy;
 - 			dim = 1;
 - 			channels = 1;
 - 		}
 - 	}
 - 	
 - 	void end() {
 - 		if (mBuf) {
 - 			genlib_buffer_perform_end(mBuf);
 - 			if (modified) {
 - 				genlib_buffer_dirty(mBuf);
 - 			}
 - 			modified = 0;
 - 		}
 - 		mBuf = 0;
 - 	}
 - };
 - 
 - struct SineData : public DataLocal {
 - 	SineData() : DataLocal() {
 - 		const int costable_size = 1 << 14;	// 14 bit index (noise floor at around -156 dB)
 - 		mData=0; 
 - 		resize(costable_size, 1); 
 - 		for (int i=0; i<dim; i++) {
 - 			mData[i] = cos(i * GENLIB_PI * 2. / (double)(dim));
 - 		}
 - 	}
 - 	
 - 	~SineData() { 
 - 		if (mData) sysmem_freeptr(mData);
 - 		mData = 0;
 - 	}
 - };
 - 
 - template<typename T>
 - inline int dim(const T& data) { return data.dim; }
 - 
 - template<typename T>
 - inline int channels(const T& data) { return data.channels; }
 - 
 - // used by cycle when no buffer/data is specified:
 - struct SineCycle {
 - 			
 - 	uint32_t phasei, pincr;
 - 	double f2i;
 - 	
 - 	void reset(t_sample samplerate, t_sample init = 0) { 
 - 		phasei = init * t_sample(4294967296.0);
 - 		pincr = 0;
 - 		f2i = t_sample(4294967296.0) / samplerate;
 - 	}
 - 	
 - 	inline void freq(t_sample f) {
 - 		pincr = f * f2i;
 - 	}
 - 	
 - 	inline void phase(t_sample f) {
 - 		phasei = f * t_sample(4294967296.0);
 - 	}
 - 	
 - 	inline t_sample phase() const {	
 - 		return phasei * t_sample(0.232830643653869629e-9);
 - 	}
 - 	
 - 	template<typename T>
 - 	inline t_sample operator()(const DataInterface<T>& buf) {
 - 		T * data = buf.mData;
 - 		// divide uint32_t range down to buffer size (32-bit to 14-bit)
 - 		uint32_t idx = phasei >> 18;
 - 		// compute fractional portion and divide by 18-bit range
 - 		const t_sample frac = t_sample(phasei & 262143) * t_sample(3.81471181759574e-6);	
 - 		// index safely in 14-bit range:
 - 		const t_sample y0 = data[idx];
 - 		const t_sample y1 = data[(idx+1) & 16383];
 - 		const t_sample y = linear_interp(frac, y0, y1);
 - 		phasei += pincr;
 - 		return y;
 - 	}
 - };
 - 
 - #endif
 
 
  |