From 0396d635f25bbae5cfacb36964ef6abd76d1de1d Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 18 Nov 2016 01:14:10 +0000 Subject: [PATCH 1/2] Update to latest genlib sources (with custom changes) --- plugins/Makefile.mk | 1 + plugins/common/gen_dsp/genlib.cpp | 286 +++++-- plugins/common/gen_dsp/genlib.h | 171 ++++- plugins/common/gen_dsp/genlib_common.h | 68 +- plugins/common/gen_dsp/genlib_common_win.h | 48 ++ .../common/gen_dsp/genlib_exportfunctions.h | 39 +- plugins/common/gen_dsp/genlib_ops.h | 707 ++++++++++-------- plugins/common/gen_dsp/genlib_platform.h | 40 + 8 files changed, 897 insertions(+), 463 deletions(-) mode change 100644 => 100755 plugins/common/gen_dsp/genlib.cpp mode change 100644 => 100755 plugins/common/gen_dsp/genlib.h mode change 100644 => 100755 plugins/common/gen_dsp/genlib_common.h create mode 100755 plugins/common/gen_dsp/genlib_common_win.h mode change 100644 => 100755 plugins/common/gen_dsp/genlib_exportfunctions.h mode change 100644 => 100755 plugins/common/gen_dsp/genlib_ops.h create mode 100644 plugins/common/gen_dsp/genlib_platform.h diff --git a/plugins/Makefile.mk b/plugins/Makefile.mk index 0eebb9b..9a96833 100644 --- a/plugins/Makefile.mk +++ b/plugins/Makefile.mk @@ -19,6 +19,7 @@ TARGET_DIR = ../../bin BUILD_C_FLAGS += -I. BUILD_CXX_FLAGS += -I. -I../common -I../common/gen_dsp -I../../dpf/distrho -I../../dpf/dgl -Wno-unused-parameter +BUILD_CXX_FLAGS += -DGENLIB_USE_FASTMATH -DGENLIB_USE_FLOAT32 -DGENLIB_USE_JSON=0 ifeq ($(HAVE_DGL),true) BASE_FLAGS += -DHAVE_DGL diff --git a/plugins/common/gen_dsp/genlib.cpp b/plugins/common/gen_dsp/genlib.cpp old mode 100644 new mode 100755 index c2884ef..ebe89bd --- a/plugins/common/gen_dsp/genlib.cpp +++ b/plugins/common/gen_dsp/genlib.cpp @@ -1,40 +1,46 @@ /******************************************************************************************************************* -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. +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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. *******************************************************************************************************************/ - #include "genlib.h" #include "genlib_exportfunctions.h" -#include "stdlib.h" -#include "stdio.h" -#include "string.h" - -#include +#include // not cstdlib (causes problems with ARM embedded compiler) +#include +#include + +#ifdef __APPLE__ +# include +#elif !defined(GEN_WINDOWS) // WIN32? +# include +# define malloc_size malloc_usable_size +#endif -#if DISTRHO_OS_MAC -# include -#else -# include -# if DISTRHO_OS_WINDOWS -# define malloc_size _msize -# else -# define malloc_size malloc_usable_size -# endif +#ifdef MSP_ON_CLANG +# include "json.c" +# include "json_builder.c" +#endif +#if GENLIB_USE_JSON +# include "json.h" +# include "json_builder.h" #endif // DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit @@ -54,10 +60,10 @@ t_ptr sysmem_newptr(t_ptr_size size) t_ptr sysmem_newptrclear(t_ptr_size size) { t_ptr p = (t_ptr)malloc(size); - + if (p) my_memset(p, 0, size); - + return p; } @@ -68,13 +74,13 @@ t_ptr sysmem_resizeptr(void *ptr, t_ptr_size newsize) t_ptr sysmem_resizeptrclear(void *ptr, t_ptr_size newsize) { - t_ptr_size oldsize = malloc_size(ptr); + size_t oldsize = malloc_size(ptr); t_ptr p = (t_ptr)realloc(ptr, newsize); - + if (p) { if (newsize > oldsize) my_memset((char *)p + oldsize, 0, newsize - oldsize); - } + } return p; } @@ -97,9 +103,9 @@ void my_memset(void *p, int c, long size) { char *p2 = (char *)p; int i; - + for (i = 0; i < size; i++, p2++) - *p2 = c; + *p2 = char(c); } void my_memcpy(void *dst, const void *src, long size) @@ -107,7 +113,7 @@ void my_memcpy(void *dst, const void *src, long size) char *s2 = (char *)src; char *d2 = (char *)dst; int i; - + for (i = 0; i < size; i++, s2++, d2++) *d2 = *s2; } @@ -115,7 +121,7 @@ void my_memcpy(void *dst, const void *src, long size) void set_zero64(t_sample *memory, long size) { long i; - + for (i = 0; i < size; i++, memory++) { *memory = 0.; } @@ -123,12 +129,16 @@ void set_zero64(t_sample *memory, long size) void genlib_report_error(const char *s) { +#ifndef GEN_NO_STDLIB fprintf(stderr, "%s\n", s); +#endif } void genlib_report_message(const char *s) { +#ifndef GEN_NO_STDLIB fprintf(stdout, "%s\n", s); +#endif } unsigned long systime_ticks(void) @@ -136,12 +146,21 @@ unsigned long systime_ticks(void) return 0; // Gen code can deal with this } -void * genlib_obtain_reference_from_string(const char * name) { +#ifdef GEN_WINDOWS +// NEED THIS FOR WINDOWS: +void *operator new(size_t size) { return sysmem_newptr(size); } +void *operator new[](size_t size) { return sysmem_newptr(size); } +void operator delete(void *p) throw() { sysmem_freeptr(p); } +void operator delete[](void *p) throw() { sysmem_freeptr(p); } +#endif + +void *genlib_obtain_reference_from_string(const char *name) +{ return 0; // to be implemented } // the rest is stuff to isolate gensym, attrs, atoms, buffers etc. -t_genlib_buffer * genlib_obtain_buffer_from_reference(void *ref) +t_genlib_buffer *genlib_obtain_buffer_from_reference(void *ref) { return 0; // to be implemented } @@ -175,7 +194,6 @@ t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b) { return 0; // to be implemented } - void genlib_buffer_perform_end(t_genlib_buffer *b) { // to be implemented @@ -183,22 +201,27 @@ void genlib_buffer_perform_end(t_genlib_buffer *b) t_sample gen_msp_pow(t_sample value, t_sample power) { +#ifdef GENLIB_USE_FLOAT32 return powf(value, power); +#else + return pow(value, power); +#endif } -void genlib_data_setbuffer(t_genlib_data *b, void *ref) { +void genlib_data_setbuffer(t_genlib_data *b, void *ref) +{ genlib_report_error("not supported for export targets\n"); } typedef struct { t_genlib_data_info info; - t_sample cursor; // used by Delay - //t_symbol * name; -} t_dsp_gen_data; + t_sample cursor; // used by Delay + //t_symbol * name; +} t_dsp_gen_data; -t_genlib_data * genlib_obtain_data_from_reference(void *ref) +t_genlib_data *genlib_obtain_data_from_reference(void *ref) { - t_dsp_gen_data * self = (t_dsp_gen_data *)malloc(sizeof(t_dsp_gen_data)); + t_dsp_gen_data *self = (t_dsp_gen_data *)malloc(sizeof(t_dsp_gen_data)); self->info.dim = 0; self->info.channels = 0; self->info.data = 0; @@ -206,48 +229,53 @@ t_genlib_data * genlib_obtain_data_from_reference(void *ref) return (t_genlib_data *)self; } -t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info) { - t_dsp_gen_data * self = (t_dsp_gen_data *)b; +t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info) +{ + t_dsp_gen_data *self = (t_dsp_gen_data *)b; info->dim = self->info.dim; info->channels = self->info.channels; info->data = self->info.data; return GENLIB_ERR_NONE; } -void genlib_data_release(t_genlib_data *b) { - t_dsp_gen_data * self = (t_dsp_gen_data *)b; - +void genlib_data_release(t_genlib_data *b) +{ + t_dsp_gen_data *self = (t_dsp_gen_data *)b; + if (self->info.data) { genlib_sysmem_freeptr(self->info.data); self->info.data = 0; } } -long genlib_data_getcursor(t_genlib_data *b) { - t_dsp_gen_data * self = (t_dsp_gen_data *)b; - return self->cursor; +long genlib_data_getcursor(t_genlib_data *b) +{ + t_dsp_gen_data *self = (t_dsp_gen_data *)b; + return long(self->cursor); } -void genlib_data_setcursor(t_genlib_data *b, long cursor) { - t_dsp_gen_data * self = (t_dsp_gen_data *)b; - self->cursor = cursor; +void genlib_data_setcursor(t_genlib_data *b, long cursor) +{ + t_dsp_gen_data *self = (t_dsp_gen_data *)b; + self->cursor = t_sample(cursor); } -void genlib_data_resize(t_genlib_data *b, long s, long c) { - t_dsp_gen_data * self = (t_dsp_gen_data *)b; - +void genlib_data_resize(t_genlib_data *b, long s, long c) +{ + t_dsp_gen_data *self = (t_dsp_gen_data *)b; + size_t sz, oldsz, copysz; - t_sample * old = 0; - t_sample * replaced = 0; + t_sample *old = 0; + t_sample *replaced = 0; int i, j, copydim, copychannels, olddim, oldchannels; - + //printf("data resize %d %d\n", s, c); - + // cache old for copying: old = self->info.data; olddim = self->info.dim; oldchannels = self->info.channels; - + // limit [data] size: if (s * c > DATA_MAXIMUM_ELEMENTS) { s = DATA_MAXIMUM_ELEMENTS/c; @@ -256,7 +284,7 @@ void genlib_data_resize(t_genlib_data *b, long s, long c) { // bytes required: sz = sizeof(t_sample) * s * c; oldsz = sizeof(t_sample) * olddim * oldchannels; - + if (old && sz == oldsz) { // no need to re-allocate, just resize // careful, audio thread may still be using it: @@ -267,15 +295,15 @@ void genlib_data_resize(t_genlib_data *b, long s, long c) { self->info.dim = s; self->info.channels = c; } - + set_zero64(self->info.data, s * c); return; - + } else { - + // allocate new: replaced = (t_sample *)sysmem_newptr(sz); - + // check allocation: if (replaced == 0) { genlib_report_error("allocating [data]: out of memory"); @@ -288,10 +316,10 @@ void genlib_data_resize(t_genlib_data *b, long s, long c) { } return; } - + // fill with zeroes: set_zero64(replaced, s * c); - + // copy in old data: if (old) { // frames to copy: @@ -308,14 +336,14 @@ void genlib_data_resize(t_genlib_data *b, long s, long c) { // clamp channels copied: copychannels = oldchannels > c ? c : oldchannels; //post("reset resize (different channels) %p %p, %d %d", self->info.data, old, copydim, copychannels); - for (i = 0; iinfo.data = replaced; @@ -348,15 +376,107 @@ void genlib_data_resize(t_genlib_data *b, long s, long c) { self->info.channels = c; } } - + // done with old: sysmem_freeptr(old); - + } - + + } +} + +void genlib_reset_complete(void *data) +{ +} + +#if GENLIB_USE_JSON +void genlib_build_json(CommonState *cself, json_value **jsonvalue, getparameter_method getmethod) +{ + int i; + + *jsonvalue = json_object_new(0); + + for (i = 0; i < cself->numparams; i++) { + t_param val; + + (getmethod)(cself, i, &val); + json_object_push(*jsonvalue, cself->params[i].name, json_double_new(val)); } } -void genlib_reset_complete(void *data) {} +size_t genlib_getstatesize(CommonState *cself, getparameter_method getmethod) +{ + size_t size; + json_value *jsonvalue; + + genlib_build_json(cself, &jsonvalue, getmethod); + size = json_measure(jsonvalue); + json_builder_free(jsonvalue); + + return size; +} + +short genlib_getstate(CommonState *cself, char *state, getparameter_method getmethod) +{ + json_value *jsonvalue; + genlib_build_json(cself, &jsonvalue, getmethod); + json_serialize(state, jsonvalue); + json_builder_free(jsonvalue); + return 0; +} + +static void *json_custom_alloc(size_t size, int zero, void *user_data) +{ + return zero ? genlib_sysmem_newptrclear(size) : genlib_sysmem_newptr(size); +} + +static void json_custom_free(void *ptr, void *user_data) +{ + genlib_sysmem_freeptr(ptr); +} + +short genlib_setstate(CommonState *cself, const char *state, setparameter_method setmethod) +{ + json_settings settings; + char error[256]; + + memset(&settings, 0, sizeof(json_settings)); + settings.mem_alloc = &json_custom_alloc; + settings.mem_free = &json_custom_free; + + json_value *value = json_parse_ex(&settings, state, strlen(state), error); + if (value == NULL) + return 1; + + if (value->type == json_object) { + unsigned int i; + for (i = 0; i < value->u.object.length; i++) { + char *name = NULL; + t_param val = 0; + int j; + + if (value->u.object.values[i].value->type == json_double) { + name = value->u.object.values[i].name; + val = t_param(value->u.object.values[i].value->u.dbl); + } else if (value->u.object.values[i].value->type == json_integer) { + name = value->u.object.values[i].name; + val = t_param(value->u.object.values[i].value->u.integer); + } + + if (name) { + for (j = 0; j < cself->numparams; j++) { + if (!strcmp(cself->params[j].name, name)) { + (setmethod)(cself, j, val, NULL); + } + } + } + } + } + + json_value_free_ex(&settings, value); + + return 0; +} +#endif // GENLIB_USE_JSON diff --git a/plugins/common/gen_dsp/genlib.h b/plugins/common/gen_dsp/genlib.h old mode 100644 new mode 100755 index ffdbb7a..3bd5392 --- a/plugins/common/gen_dsp/genlib.h +++ b/plugins/common/gen_dsp/genlib.h @@ -1,44 +1,87 @@ /******************************************************************************************************************* -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. +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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_H #define GENLIB_H 1 #include "genlib_common.h" +#ifndef MSP_ON_CLANG +# include +#endif + //////////// genlib.h //////////// // genlib.h -- max (gen~) version -#include "DistrhoUtils.hpp" - -#define inf (__DBL_MAX__) -#define GEN_UINT_MAX (4294967295) -#define TWO_TO_32 (4294967296.0) +#ifndef GEN_WINDOWS +# ifndef _SIZE_T +# define _SIZE_T + typedef __typeof__(sizeof(int)) size_t; +# endif +#endif + +#ifndef __INT32_TYPE__ +# define __INT32_TYPE__ int +#endif + +#ifdef MSP_ON_CLANG +// gen~ hosted: +typedef unsigned __INT32_TYPE__ uint32_t; +typedef unsigned __INT64_TYPE__ uint64_t; +#else +# ifdef __GNUC__ +# include +# endif +#endif + +#ifdef GENLIB_USE_FLOAT32 +#define inf (__FLT_MAX__) +#else +#define inf (__DBL_MAX__) +#endif + +#define GEN_UINT_MAX (4294967295) +#define TWO_TO_32 (t_sample(4294967296.0)) #define C74_CONST const // max_types.h: +#ifdef C74_X64 +typedef unsigned long long t_ptr_uint; +typedef long long t_ptr_int; +typedef double t_atom_float; +typedef t_ptr_uint t_getbytes_size; +#elif defined(__GNUC__) && !defined(MSP_ON_CLANG) typedef uintptr_t t_ptr_uint; typedef intptr_t t_ptr_int; typedef float t_atom_float; typedef t_ptr_uint t_getbytes_size; +#else +typedef unsigned long t_ptr_uint; +typedef long t_ptr_int; +typedef float t_atom_float; +typedef short t_getbytes_size; +#endif // C74_X64 typedef uint32_t t_uint32; typedef t_ptr_int t_atom_long; // the type that is an A_LONG in an atom @@ -49,11 +92,76 @@ typedef t_ptr_int t_atom_long; ///< the type that is an A_LONG in a #t_atom @i typedef t_atom_long t_max_err; ///< an integer value suitable to be returned as an error code @ingroup misc extern "C" { + extern t_sample gen_msp_pow (t_sample, t_sample); + +#ifdef MSP_ON_CLANG + // TODO: remove (for debugging only) + //int printf(const char *fmt, ...); + + // math.h: + extern double acos(double); + extern double asin(double); + extern double atan(double); + extern double atan2(double, double); + extern double cos(double); + extern double sin(double); + extern double tan(double); + extern double acosh(double); + extern double asinh(double); + extern double atanh(double); + extern double cosh(double); + extern double sinh(double); + extern double tanh(double); + extern double exp(double); + extern double log(double); + extern double log10(double); + extern double fmod(double, double); + extern double modf(double, double *); + extern double fabs(double); + extern double hypot(double, double); + extern double pow(double, double); + + extern double sqrt(double); + extern double ceil(double); + extern double floor(double); + extern double trunc(double); + extern double round(double); + extern int abs(int); + + extern char *strcpy(char *, const char *); +#endif // MSP_ON_CLANG + +#if defined(GENLIB_USE_ARMMATH) // ARM embedded support +# include "arm_math.h" +# define sin(x) arm_sin_f32(x) +# define sinf(x) arm_sin_f32(x) +# define cos(x) arm_cos_f32(x) +# define cosf(x) arm_cos_f32(x) +# define sqrt(x) arm_sqrtf(x) +# define sqrtf(x) arm_sqrtf(x) +# define rand(...) arm_rand32() +# undef RAND_MAX +# define RAND_MAX UINT32_MAX +#endif // GENLIB_USE_ARMMATH + +#if defined(GENLIB_USE_FASTMATH) +# define tan(x) fastertanfull(x) +# define exp(x) fasterexp(x) +# define log2(x) fasterlog2(x) +# define pow(x,y) fasterpow(x,y) +# define pow2(x) fasterpow2(x) +# define atan2(x,y) fasteratan2(x,y) +# define tanh(x) fastertanh(x) +# if !defined(GENLIB_USE_ARMMATH) +# define sin(x) fastersinfull(x) +# define cos(x) fastercosfull(x) +# endif +#endif // GENLIB_USE_FASTMATH // string reference handling: - void * genlib_obtain_reference_from_string(const char * name); + void *genlib_obtain_reference_from_string(const char *name); char *genlib_reference_getname(void *ref); - + // buffer handling: t_genlib_buffer *genlib_obtain_buffer_from_reference(void *ref); t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b); @@ -62,7 +170,7 @@ extern "C" { void genlib_buffer_dirty(t_genlib_buffer *b); t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b); void genlib_buffer_perform_end(t_genlib_buffer *b); - + // data handling: t_genlib_data *genlib_obtain_data_from_reference(void *ref); t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info); @@ -71,17 +179,17 @@ extern "C" { void genlib_data_release(t_genlib_data *b); void genlib_data_setcursor(t_genlib_data *b, long cursor); long genlib_data_getcursor(t_genlib_data *b); - + // other notification: void genlib_reset_complete(void *data); - // get/set state of parameters - size_t genlib_getstatesize(CommonState *cself, getparameter_method getmethod); - short genlib_getstate(CommonState *cself, char *state, getparameter_method getmethod); - short genlib_setstate(CommonState *cself, const char *state, setparameter_method setmethod); + // get/set state of parameters + size_t genlib_getstatesize(CommonState *cself, getparameter_method getmethod); + short genlib_getstate(CommonState *cself, char *state, getparameter_method getmethod); + short genlib_setstate(CommonState *cself, const char *state, setparameter_method setmethod); }; // extern "C" - + #define genlib_sysmem_newptr(s) sysmem_newptr(s) #define genlib_sysmem_newptrclear(s) sysmem_newptrclear(s) #define genlib_sysmem_resizeptr(p, s) sysmem_resizeptr(p, s) @@ -93,3 +201,4 @@ extern "C" { #define genlib_ticks systime_ticks #endif // GENLIB_H + diff --git a/plugins/common/gen_dsp/genlib_common.h b/plugins/common/gen_dsp/genlib_common.h old mode 100644 new mode 100755 index e8cce65..5265166 --- a/plugins/common/gen_dsp/genlib_common.h +++ b/plugins/common/gen_dsp/genlib_common.h @@ -1,36 +1,51 @@ /******************************************************************************************************************* -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. +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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_COMMON_H #define GENLIB_COMMON_H 1 +#include "genlib_platform.h" + //////////// genlib_common.h //////////// // common data structure header file -- this is the stuff required by the // common code and accessed by the export and max code #define DSP_GEN_MAX_SIGNALS 16 +// json is enabled by default, but can be disabled if not needed +#ifndef GENLIB_USE_JSON +#define GENLIB_USE_JSON 1 +#endif + +#ifdef GENLIB_USE_FLOAT32 typedef float t_sample; typedef float t_param; +#else +typedef double t_sample; +typedef double t_param; +#endif typedef char *t_ptr; - + typedef long t_genlib_err; typedef enum { GENLIB_ERR_NONE = 0, ///< No error @@ -38,10 +53,10 @@ typedef enum { GENLIB_ERR_INVALID_PTR = -2, ///< Invalid Pointer GENLIB_ERR_DUPLICATE = -3, ///< Duplicate GENLIB_ERR_OUT_OF_MEM = -4, ///< Out of memory - + GENLIB_ERR_LOOP_OVERFLOW = 100, // too many iterations of loops in perform() GENLIB_ERR_NULL_BUFFER = 101 // missing signal data in perform() - + } e_genlib_errorcodes; typedef enum { @@ -52,7 +67,7 @@ typedef enum { struct ParamInfo { t_param defaultvalue; - void * defaultref; + void *defaultref; char hasinputminmax; char hasminmax; t_param inputmin, inputmax; @@ -66,16 +81,16 @@ struct ParamInfo struct CommonState { t_sample sr; - int vs; + int vs; int numins; int numouts; const char **inputnames; const char **outputnames; int numparams; ParamInfo *params; - - void * parammap; // implementation-dependent - void * api; // implementation-dependent + + void *parammap; // implementation-dependent + void *api; // implementation-dependent }; // opaque interface to float32 buffer: @@ -91,7 +106,7 @@ typedef struct { long b_rfu[57]; ///< reserved for future use } t_genlib_buffer_info; -// opaque interface to float64 buffer: +// opaque interface to float64 buffer: typedef struct _genlib_data t_genlib_data; typedef struct { int dim, channels; @@ -104,3 +119,4 @@ typedef void (*getparameter_method) (CommonState *, long, t_param *); #endif // GENLIB_COMMON_H + diff --git a/plugins/common/gen_dsp/genlib_common_win.h b/plugins/common/gen_dsp/genlib_common_win.h new file mode 100755 index 0000000..fd98f46 --- /dev/null +++ b/plugins/common/gen_dsp/genlib_common_win.h @@ -0,0 +1,48 @@ +/******************************************************************************************************************* +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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_COMMON_WIN_H +#define GENLIB_COMMON_WIN_H + +#ifdef _MSC_VER + #define GEN_WINDOWS +#endif + +#ifdef GEN_WINDOWS + + #include + #include + + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + #define malloc_size _msize + + #define __DBL_EPSILON__ (DBL_EPSILON) + +#endif + +#endif + + diff --git a/plugins/common/gen_dsp/genlib_exportfunctions.h b/plugins/common/gen_dsp/genlib_exportfunctions.h old mode 100644 new mode 100755 index a332897..91acca8 --- a/plugins/common/gen_dsp/genlib_exportfunctions.h +++ b/plugins/common/gen_dsp/genlib_exportfunctions.h @@ -1,26 +1,30 @@ /******************************************************************************************************************* -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. +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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_EXPORT_FUNCTIONS_H #define GENLIB_EXPORT_FUNCTIONS_H 1 -typedef char *t_ptr; +typedef char *t_ptr; t_ptr sysmem_newptr(t_ptr_size size); t_ptr sysmem_newptrclear(t_ptr_size size); @@ -36,3 +40,4 @@ void genlib_report_message(const char *s); void set_zero64(t_sample *mem, long size); #endif // GENLIB_EXPORT_FUNCTIONS_H + diff --git a/plugins/common/gen_dsp/genlib_ops.h b/plugins/common/gen_dsp/genlib_ops.h old mode 100644 new mode 100755 index 810054d..12b391d --- a/plugins/common/gen_dsp/genlib_ops.h +++ b/plugins/common/gen_dsp/genlib_ops.h @@ -1,78 +1,123 @@ /******************************************************************************************************************* -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. +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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 +#include "genlib_common.h" +#include "genlib.h" //////////// genlib_ops.h //////////// // system constants #define GENLIB_DBL_EPSILON (__DBL_EPSILON__) +#define GENLIB_FLT_EPSILON (__FLT_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)) +// denormal numbers cannot occur when hosted in MSP, nor on ARM Cortex processors: +#if defined(MSP_ON_CLANG) || defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7) +# define GENLIB_NO_DENORM_TEST 1 +#endif // defined(MSP_ON_CLANG) || defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7) -#ifdef GENLIB_NO_DENORM_TEST - #define GENLIB_IS_DENORM_DOUBLE(v) (v) - #define GENLIB_FIX_DENORM_DOUBLE(v) (v) +#ifdef GENLIB_USE_FLOAT32 +# define GENLIB_EPSILON GENLIB_FLT_EPSILON #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)) +# define GENLIB_EPSILON GENLIB_DBL_EPSILON #endif -#define GENLIB_QUANT(f1,f2) (floor((f1)*(f2)+0.5)/(f2)) +#define GENLIB_PI (t_sample(3.14159265358979323846264338327950288)) +#define GENLIB_PI_OVER_2 (t_sample(1.57079632679489661923132169163975144)) +#define GENLIB_PI_OVER_4 (t_sample(0.785398163397448309615660845819875721)) +#define GENLIB_1_OVER_LOG_2 (t_sample(1.442695040888963)) -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) { +// assumes v is a 64-bit double: +#ifdef GENLIB_USE_FLOAT32 +# define GENLIB_IS_NAN_FLOAT(v) ((v)!=(v)) +# define GENLIB_FIX_NAN_FLOAT(v) ((v)=GENLIB_IS_NAN_FLOAT(v)?0.f:(v)) + +# ifdef GENLIB_NO_DENORM_TEST +# define GENLIB_IS_DENORM_FLOAT(v) (v) +# define GENLIB_FIX_DENORM_FLOAT(v) (v) +# else +# ifdef WIN32 +# define __FLT_MIN__ (FLT_MIN) +# define __FLT_MAX__ (FLT_MAX) +# endif +# define GENLIB_IS_DENORM_FLOAT(v) ((v)!=0.&&fabs(v)<__FLT_MIN__) +# define GENLIB_FIX_DENORM_FLOAT(v) ((v)=GENLIB_IS_DENORM_FLOAT(v)?0.f:(v)) +# endif // GENLIB_NO_DENORM_TEST + +# define GENLIB_IS_NAN GENLIB_IS_NAN_FLOAT +# define GENLIB_FIX_NAN GENLIB_FIX_NAN_FLOAT +# define GENLIB_IS_DENORM GENLIB_IS_DENORM_FLOAT +# define GENLIB_FIX_DENORM GENLIB_FIX_DENORM_FLOAT +#else // GENLIB_USE_FLOAT32 +# 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 // GENLIB_NO_DENORM_TEST +# 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_IS_NAN GENLIB_IS_NAN_DOUBLE +# define GENLIB_FIX_NAN GENLIB_FIX_NAN_DOUBLE +# define GENLIB_IS_DENORM GENLIB_IS_DENORM_DOUBLE +# define GENLIB_FIX_DENORM GENLIB_FIX_DENORM_DOUBLE +#endif // GENLIB_USE_FLOAT32 + +#define GENLIB_QUANT(f1,f2) t_sample(floor((f1)*(f2)+0.5)/(f2)) + +inline t_sample genlib_isnan(t_sample v) { return GENLIB_IS_NAN(v); } +inline t_sample fixnan(t_sample v) { return GENLIB_FIX_NAN(v); } +inline t_sample fixdenorm(t_sample v) { return GENLIB_FIX_DENORM(v); } +inline t_sample isdenorm(t_sample v) { return GENLIB_IS_DENORM(v); } + +inline t_sample fasterpow(t_sample x, t_sample p); +inline t_sample fasterexp(t_sample x); +inline t_sample fastercosfull(t_sample x); +inline t_sample fastersinfull(t_sample x); +inline t_sample fastertanfull(t_sample x); + +inline t_sample safemod(t_sample f, t_sample m) { if (m > GENLIB_DBL_EPSILON || m < -GENLIB_DBL_EPSILON) { - if (m<0) - m = -m; // modulus needs to be absolute value + if (m<0) + m = -m; // modulus needs to be absolute value if (f>=m) { if (f>=(m*2.)) { - double d = f / m; + t_sample 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; + t_sample d = f / m; d = d - (long) d; f = d * m; } @@ -86,29 +131,30 @@ inline double safemod(double f, double m) { return f; } - -inline double safediv(double num, double denom) { - return denom == 0. ? 0. : num/denom; +inline t_sample safediv(t_sample num, t_sample denom) { + return denom == 0. ? (t_sample)0. : (t_sample)(num/denom); } // fixnan for case of negative base and non-integer exponent: -inline double safepow(double base, double exponent) { +inline t_sample safepow(t_sample base, t_sample exponent) { return fixnan(pow(base, exponent)); } -inline double absdiff(double a, double b) { return fabs(a-b); } +inline t_sample absdiff(t_sample a, t_sample b) { return fabs(a-b); } -inline double exp2(double v) { return pow(2., v); } +#ifndef WIN32 +inline t_sample exp2(t_sample v) { return pow(t_sample(2.), v); } -inline double trunc(double v) { - double epsilon = (v<0.0) * -2 * 1E-9 + 1E-9; +inline t_sample trunc(t_sample v) { + t_sample 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; } +#endif // WIN32 -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 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) { @@ -131,7 +177,7 @@ 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) { + if (lo1 > hi1) { hi = lo1; lo = hi1; } else { lo = lo1; hi = hi1; @@ -157,20 +203,20 @@ inline t_sample fold(t_sample v, t_sample lo1, t_sample hi1){ return v; } -inline double wrap(double v, double lo1, double hi1){ - double lo; - double hi; +inline t_sample wrap(t_sample v, t_sample lo1, t_sample hi1){ + t_sample lo; + t_sample hi; if(lo1 == hi1) return lo1; - if (lo1 > hi1) { + if (lo1 > hi1) { hi = lo1; lo = hi1; } else { lo = lo1; hi = hi1; } - const double range = hi - lo; + const t_sample range = hi - lo; if (v >= lo && v < hi) return v; - if (range <= 0.000000001) return lo; // no point... + if (range <= 0.000000001) return lo; // no point... const long numWraps = long((v-lo)/range) - (v < lo); - return v - range * double(numWraps); + return v - range * t_sample(numWraps); } // this version gives far better performance when wrapping is relatively rare @@ -185,12 +231,12 @@ inline t_sample genlib_wrapfew(t_sample v, t_sample lo, t_sample hi){ inline t_sample phasewrap(t_sample val) { const t_sample twopi = GENLIB_PI*2.; - const t_sample oneovertwopi = 1./twopi; + const t_sample oneovertwopi = t_sample(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; @@ -202,23 +248,23 @@ 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 t81 = t_sample(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){ + const t_sample t71 = t_sample(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))); + return t_sample(1. - rr * t81 * (t82 - rr * (t83 - rr * (t84 - rr)))); } - else if(r > 0.){ + else if (r > 0.){ r -= GENLIB_PI_OVER_2; t_sample rr = r*r; - return -r * (1. - t71 * rr * (t72 - rr * (t73 - rr))); + return t_sample(-r * (1. - t71 * rr * (t72 - rr * (t73 - rr)))); } - else{ + else { r += GENLIB_PI_OVER_2; t_sample rr = r*r; - return r * (1. - t71 * rr * (t72 - rr * (t73 - rr))); + return t_sample(r * (1. - t71 * rr * (t72 - rr * (t73 - rr)))); } } @@ -310,7 +356,7 @@ inline t_sample genlib_cosT8_safe(t_sample r) { return genlib_cosT8(phasewrap(r) * Contact: Paul Mineiro * *=====================================================================*/ -inline float genlib_fastersin (float x) { +inline float genlib_fastersin(float x) { static const float fouroverpi = 1.2732395447351627f; static const float fouroverpisq = 0.40528473456935109f; static const float q = 0.77633023248007499f; @@ -323,7 +369,7 @@ inline float genlib_fastersin (float x) { return qpprox * (q + p.f * qpprox); } -inline float genlib_fastercos (float x) { +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 }; @@ -332,23 +378,23 @@ inline float genlib_fastercos (float x) { return qpprox + p * qpprox * (1.0f - qpprox * qpprox); } -inline float genlib_fastersinfull (float x) { +inline float genlib_fastersinfull(float x) { static const float twopi = 6.2831853071795865f; static const float invtwopi = 0.15915494309189534f; - int k = x * invtwopi; + int k = int(x * invtwopi); float half = (x < 0) ? -0.5f : 0.5f; return genlib_fastersin ((half + k) * twopi - x); } - -inline float genlib_fastercosfull (float x) { + +inline float genlib_fastercosfull(float x) { static const float halfpi = 1.5707963267948966f; return genlib_fastersinfull (x + halfpi); } - -inline float genlib_fastertanfull (float x) { + +inline float genlib_fastertanfull(float x) { static const float twopi = 6.2831853071795865f; static const float invtwopi = 0.15915494309189534f; - int k = x * invtwopi; + int k = int(x * invtwopi); float half = (x < 0) ? -0.5f : 0.5f; float xnew = x - (half + k) * twopi; return genlib_fastersin (xnew) / genlib_fastercos (xnew); @@ -356,87 +402,132 @@ inline float genlib_fastertanfull (float x) { #define cast_uint32_t static_cast -inline float genlib_fasterpow2 (float p) { +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) { +inline float genlib_fasterexp(float p) { return genlib_fasterpow2 (1.442695040f * p); } -inline float genlib_fasterlog2 (float x) { +inline float genlib_fasterlog2(float x) { union { float f; uint32_t i; } vx = { x }; - float y = vx.i; + float y = float(vx.i); y *= 1.1920928955078125e-7f; return y - 126.94269504f; } -inline float genlib_fasterpow (float x, float p) { +inline float genlib_fasterpow(float x, float p) { return genlib_fasterpow2(p * genlib_fasterlog2 (x)); } +// from http://dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization +inline float genlib_fasteratan2(float y, float x) { + const float coeff_1 = (float)(GENLIB_PI/4); + const float coeff_2 = 3 * (float)(GENLIB_PI/4); + float abs_y = fabs(y) + 1e-10; // kludge to prevent 0/0 condition + float r, angle; + if (x >= 0) { + r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } + else { + r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + if (y < 0) { + return (-angle); // negate if in quad III or IV + } + else { + return (angle); + } +} + +// http://math.stackexchange.com/questions/107292/rapid-approximation-of-tanhx +inline float genlib_fastertanh(float x) { + return (-.67436811832e-5 + (.2468149110712040 + (.583691066395175e-1 + .3357335044280075e-1 * x) * x) * x) / + (.2464845986383725 + (.609347197060491e-1 + (.1086202599228572 + .2874707922475963e-1 * x) * x) * x); +} + //////////////////////////////////////////////////////////////// -inline double fastertanfull(double x) { - return (double)genlib_fastertanfull((float)x); +inline t_sample fastertanfull(t_sample x) { + return (t_sample)genlib_fastertanfull((float)x); +} + +inline t_sample fastersinfull(t_sample x) { + return (t_sample)genlib_fastersinfull((float)x); +} + +inline t_sample fastercosfull(t_sample x) { + return (t_sample)genlib_fastercosfull((float)x); +} + +inline t_sample fasterexp(t_sample x) { + return (t_sample)genlib_fasterexp((float)x); +} + +inline t_sample fasterlog2(t_sample x) { + return (t_sample)genlib_fasterlog2((float)x); } -inline double fastersinfull(double x) { - return (double)genlib_fastersinfull((float)x); +inline t_sample fasterpow(t_sample x, t_sample p) { + return (t_sample)genlib_fasterpow((float)x, (float)p); } -inline double fastercosfull(double x) { - return (double)genlib_fastercosfull((float)x); +inline t_sample fasterpow2(t_sample p) { + return (t_sample)genlib_fasterpow2((float)p); } -inline double fasterexp(double x) { - return (double)genlib_fasterexp((float)x); +inline t_sample fasteratan2(t_sample y, t_sample x) { + return (t_sample)genlib_fasteratan2(y, x); } -inline double fasterpow(double x, double p) { - return (double)genlib_fasterpow((float)x, (float)p); +inline t_sample fastertanh(t_sample x) { + return (t_sample)genlib_fastertanh((float)x); } + /****************************************************************/ -inline double minimum(double x, double y) { return (y -inline T smoothstep(double e0, double e1, T x) { +inline T smoothstep(t_sample e0, t_sample 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 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) +inline t_sample scale(t_sample in, t_sample inlow, t_sample inhigh, t_sample outlow, t_sample outhigh, t_sample power) { - double value; - double inscale = safediv(1., inhigh - inlow); - double outdiff = outhigh - outlow; - + t_sample value; + t_sample inscale = safediv(1., inhigh - inlow); + t_sample 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); + return x+a*(y-x); } inline t_sample cosine_interp(t_sample a, t_sample x, t_sample y) { @@ -463,7 +554,7 @@ inline t_sample spline_interp(t_sample a, t_sample w, t_sample x, t_sample y, t_ } template -inline T1 neqp(T1 x, T2 y) { +inline T1 neqp(T1 x, T2 y) { return ((((x) != T1(y))) ? (x) : T1(0)); } @@ -476,52 +567,52 @@ inline T1 ltp(T1 x, T2 y) { return ((((x) < T1(y))) ? (x) : T1(0)); } template 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); } +inline t_sample fract(t_sample x) { double unused; return (t_sample)modf((double)x, &unused); } // log2(x) = log(x)/log(2) template -inline T log2(T x) { - return log(x)*GENLIB_1_OVER_LOG_2; +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 t_sample atodb(t_sample in) { + return t_sample((in <= 0.) ? -999. : (20. * log10(in))); } -inline double dbtoa(double in) { - return pow(10., in * 0.05); +inline t_sample dbtoa(t_sample in) { + return t_sample(pow(10., in * 0.05)); } -inline double ftom(double in, double tuning=440.) { - return 69. + 17.31234050465299 * log(safediv(in, tuning)); +inline t_sample ftom(t_sample in, t_sample tuning=440.) { + return t_sample(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 mtof(t_sample in, t_sample tuning=440.) { + return t_sample(tuning * exp(.057762265 * (in - 69.0))); } inline t_sample mstosamps(t_sample ms, t_sample samplerate=44100.) { - return samplerate * ms * t_sample(0.001); + return t_sample(samplerate * ms * t_sample(0.001)); } inline t_sample sampstoms(t_sample s, t_sample samplerate=44100.) { - return t_sample(1000.) * s / samplerate; + return t_sample(t_sample(1000.) * s / samplerate); } -inline double triangle(double phase, double p1) { +inline t_sample triangle(t_sample phase, t_sample p1) { phase = wrap(phase, 0., 1.); p1 = clamp(p1, 0., 1.); if (phase < p1) - return (p1) ? phase/p1 : 0.; + return t_sample((p1) ? phase/p1 : 0.); else - return (p1==1.) ? phase : 1. - ((phase - p1) / (1. - p1)); + return t_sample((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; @@ -532,7 +623,7 @@ 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; @@ -543,16 +634,16 @@ struct Change { 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)) { @@ -561,16 +652,16 @@ struct Rate { 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 + phase = (in1 - GENLIB_QUANT(in1, quant)) * invmult + GENLIB_QUANT(in1, quant * mult); diff = 0; wantlock = 0; @@ -578,16 +669,16 @@ struct Rate { // 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)) { @@ -596,7 +687,7 @@ struct Rate { wantlock = 1; } t_sample diff = in1 - prev; - + if (diff < t_sample(-0.5)) { if (wantlock) { wantlock = 0; @@ -614,42 +705,42 @@ struct Rate { 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) { + + inline t_sample perform_off(t_sample in1, t_sample in2) { // did multiplier change? if (in2 != mult && !genlib_isnan(in2)) { mult = in2; invmult = safediv(1., mult); wantlock = 1; } - double diff = in1 - prev; - + 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); } - + phase += diff * invmult; - + if (phase > t_sample(1.) || phase < t_sample(-0.)) { phase = phase - (long)(phase); - } - + } + prev = in1; - + return phase; } }; @@ -658,8 +749,8 @@ struct DCBlock { t_sample x1, y1; DCBlock() { reset(); } inline void reset() { x1=0; y1=0; } - - inline double operator()(t_sample in1) { + + inline t_sample operator()(t_sample in1) { t_sample y = in1 - x1 + y1*t_sample(0.9997); x1 = in1; y1 = y; @@ -674,17 +765,20 @@ struct Noise { long time = genlib_ticks(); return (time <= lasttime) ? (++lasttime) : (lasttime = time); } - + Noise() { reset(); } - Noise(double seed) { reset(seed); } + Noise(t_sample seed) { reset(seed); } void reset() { last = uniqueTickCount() * uniqueTickCount(); } - void reset(double seed) { last = seed; } - + void reset(t_sample seed) { last = (unsigned long)(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; + union { + uint32_t ui32; + float f; + } u = { uint32_t(0x3f800000 | (0x007fffff & last)) }; // type-punning + + return (u.f * 2.f) - 3.f; } }; @@ -692,7 +786,7 @@ struct Phasor { t_sample phase; Phasor() { reset(); } void reset(t_sample v=0.) { phase=v; } - inline double operator()(t_sample freq, t_sample invsamplerate) { + inline t_sample 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.); @@ -704,7 +798,7 @@ 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); @@ -714,7 +808,7 @@ struct PlusEquals { 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); @@ -730,7 +824,7 @@ 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); @@ -740,7 +834,7 @@ struct MulEquals { 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); @@ -758,7 +852,7 @@ struct Sah { 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; @@ -772,7 +866,7 @@ 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! @@ -785,27 +879,27 @@ struct Train { const t_sample pincr = t_sample(1.)/interval; // (0..1] phase += pincr; // +ve if (state) { // on: - if (phase > p2) { + if (phase > p2) { state = t_sample(0.); // turn off phase -= (int)(1.+phase-p2); // wrap phase back down } } else { // off: - if (phase > p1) { + if (phase > p1) { state = t_sample(1.); // turn on. } } } return state; - } + } }; struct Delay { - t_sample * memory; + t_sample *memory; long size, wrap, maxdelay; long reader, writer; - - t_genlib_data * dataRef; - + + t_genlib_data *dataRef; + Delay() : memory(0) { size = wrap = maxdelay = 0; reader = writer = 0; @@ -819,30 +913,30 @@ struct Delay { genlib_data_release(dataRef); } } - - inline void reset(const char * name, long d) { - // if needed, acquire the Data's global reference: + + 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); + + void *ref = genlib_obtain_reference_from_string(name); dataRef = genlib_obtain_data_from_reference(ref); - if (dataRef == 0) { + if (dataRef == 0) { genlib_report_error("failed to acquire data"); - return; + return; } - + // scale maxdelay to next highest power of 2: maxdelay = d; size = maxdelay < 2 ? 2 : maxdelay; - size = next_power_of_two(size); - + size = long(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 + // 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. @@ -856,40 +950,40 @@ struct Delay { } else { genlib_report_error("failed to acquire data info"); } - - } else { + + } 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++; + 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); + const t_sample r = t_sample(size + reader) - clamp(d-t_sample(0.5), t_sample(reader != writer), t_sample(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; + t_sample c = t_sample(clamp(d, t_sample(reader != writer), t_sample(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; @@ -897,10 +991,10 @@ struct Delay { 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); + const t_sample r = t_sample(size + reader) - clamp(d, t_sample(reader != writer), t_sample(maxdelay)); long r1 = long(r); long r2 = r1+1; t_sample a = r - (t_sample)r1; @@ -908,12 +1002,12 @@ struct Delay { 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); + const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.) + t_sample(reader != writer), t_sample(maxdelay)); long r1 = long(r); long r2 = r1+1; long r3 = r1+2; @@ -925,12 +1019,12 @@ struct Delay { 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); + const t_sample r = t_sample(size + reader) - clamp(d, t_sample(1.) + t_sample(reader != writer), t_sample(maxdelay)); long r1 = long(r); long r2 = r1+1; long r3 = r1+2; @@ -947,71 +1041,71 @@ struct Delay { template struct DataInterface { long dim, channels; - T * mData; - void * mDataReference; // this was t_symbol *mName + 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 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; + 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; + 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) { + 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); + 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 read_ok(long index, long channel=0, bool ok=1) const { + return ok ? mData[channel+index*channels] : T(0); } - inline void overdub_ok(T value, long index, long channel=0, bool ok=1) { - if (ok) mData[channel+index*channels] += value; + 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); } - + 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 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); } + 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 { + 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); + 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)) { @@ -1020,8 +1114,8 @@ struct DataInterface { return read(i, channel); } } - - inline T index(double index, long channel=0) const { + + inline T index(t_sample index, long channel=0) const { channel = channel_clamp(channel); // no-interp: long i = (long)index; @@ -1029,8 +1123,8 @@ struct DataInterface { i = index_clamp(i); return read(i, channel); } - - inline T cell(double index, long channel=0) const { + + inline T cell(t_sample index, long channel=0) const { channel = channel_clamp(channel); // no-interp: long i = (long)index; @@ -1038,7 +1132,7 @@ struct DataInterface { 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); @@ -1054,7 +1148,7 @@ struct DataInterface { 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); @@ -1075,7 +1169,7 @@ struct DataInterface { 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) { @@ -1085,7 +1179,7 @@ struct DataInterface { // interp: long i1 = (long)index; long i2 = i1+1; - const t_sample alpha = index - (double)i1; + const t_sample alpha = index - (t_sample)i1; // bound: i1 = index_wrap(i1); i2 = index_wrap(i2); @@ -1118,30 +1212,30 @@ struct DataInterface { struct Data : public DataInterface { t_genlib_data * dataRef; // a pointer to some external source of the data - + Data() : DataInterface() { dataRef = 0; } - ~Data() { + ~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 needed, acquire the Data's global reference: if (dataRef == 0) { - void * ref = genlib_obtain_reference_from_string(name); + void *ref = genlib_obtain_reference_from_string(name); dataRef = genlib_obtain_data_from_reference(ref); - if (dataRef == 0) { + if (dataRef == 0) { genlib_report_error("failed to acquire data"); - return; + return; } } genlib_data_resize(dataRef, s, c); getinfo(); } - bool setbuffer(void * bufferRef) { + bool setbuffer(void *bufferRef) { //genlib_report_message("set buffer %p", bufferRef); if (dataRef == 0) { // error: no data, or obtain? @@ -1151,7 +1245,7 @@ struct Data : public DataInterface { getinfo(); return true; } - + void getinfo() { t_genlib_data_info info; if (genlib_data_getinfo(dataRef, &info) == GENLIB_ERR_NONE) { @@ -1167,16 +1261,16 @@ struct Data : public DataInterface { // Used by SineData struct DataLocal : public DataInterface { DataLocal() : DataInterface() {} - ~DataLocal() { + ~DataLocal() { if (mData) sysmem_freeptr(mData); mData = 0; } - void reset(long s, long c) { - mData=0; - resize(s, c); + 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; @@ -1203,24 +1297,24 @@ struct DataLocal : public DataInterface { bool setbuffer(void *dataReference) { mDataReference = dataReference; // replaced mName bool result = false; - t_genlib_buffer * b; + 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; + 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; + long channels_safe = nchans < channels ? nchans : channels; // copy: for (int f=0; f { } result = true; } else { - genlib_report_message("couldn't get info for buffer\n"); + genlib_report_message("couldn't get info for buffer\n"); } genlib_buffer_edit_end(b, 1); } else { @@ -1245,29 +1339,29 @@ struct DataLocal : public DataInterface { }; struct Buffer : public DataInterface { - t_genlib_buffer * mBuf; + t_genlib_buffer* mBuf; t_genlib_buffer_info mInfo; float mDummy; // safe access in case buffer is not valid - + Buffer() : DataInterface() {} - - void reset(const char * name) { + + 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); + mDataReference = genlib_obtain_reference_from_string(name); } - - void setbuffer(void * ref) { + + void setbuffer(void *ref) { mDataReference = ref; } - + void begin() { - t_genlib_buffer * b = genlib_obtain_buffer_from_reference(mDataReference); + t_genlib_buffer *b = genlib_obtain_buffer_from_reference(mDataReference); mBuf = 0; if (b) { if (genlib_buffer_perform_begin(b) == GENLIB_ERR_NONE) { @@ -1278,7 +1372,7 @@ struct Buffer : public DataInterface { } 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; @@ -1293,7 +1387,7 @@ struct Buffer : public DataInterface { channels = 1; } } - + void end() { if (mBuf) { genlib_buffer_perform_end(mBuf); @@ -1309,14 +1403,14 @@ struct Buffer : public DataInterface { 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); + mData = 0; + resize(costable_size, 1); for (int i=0; i inline t_sample operator()(const DataInterface& buf) { - T * data = buf.mData; + 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); + 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]; @@ -1369,3 +1463,4 @@ struct SineCycle { }; #endif + diff --git a/plugins/common/gen_dsp/genlib_platform.h b/plugins/common/gen_dsp/genlib_platform.h new file mode 100644 index 0000000..f663068 --- /dev/null +++ b/plugins/common/gen_dsp/genlib_platform.h @@ -0,0 +1,40 @@ +/******************************************************************************************************************* +Cycling '74 License for Max-Generated Code for Export +Copyright (c) 2016 Cycling '74 +The code that Max generates automatically and that end users are capable of exporting and using, and any + associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author + and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a + copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the + Software must contact the copyright owner to determine if a license for commercial use is available, and the + terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries + to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based + upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or + other business whether for-profit or non-profit so long as the use itself is not a commercialization of the + materials or a use that generates or is intended to generate income, revenue, sales or profit. +The above copyright notice and this license 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 NON-INFRINGEMENT. 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_PLATFORM_H +#define GENLIB_PLATFORM_H 1 + +#include "genlib_common_win.h" + +#if defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7) // embedded ARM cortex support +#define GENLIB_USE_ARMMATH +#define GENLIB_USE_FASTMATH +#endif // defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7) + +#if defined (__arm__) // general ARM support +#define GENLIB_USE_FLOAT32 +#endif + + + +#endif // ifdef GENLIB_PLATFORM_H From 567f0d715b148ca652c42e436958b68208cf2b57 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 18 Nov 2016 01:25:17 +0000 Subject: [PATCH 2/2] One last change --- plugins/common/gen_dsp/genlib.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/common/gen_dsp/genlib.cpp b/plugins/common/gen_dsp/genlib.cpp index ebe89bd..5216835 100755 --- a/plugins/common/gen_dsp/genlib.cpp +++ b/plugins/common/gen_dsp/genlib.cpp @@ -201,11 +201,7 @@ void genlib_buffer_perform_end(t_genlib_buffer *b) t_sample gen_msp_pow(t_sample value, t_sample power) { -#ifdef GENLIB_USE_FLOAT32 - return powf(value, power); -#else return pow(value, power); -#endif } void genlib_data_setbuffer(t_genlib_data *b, void *ref)