Mercurial > hg > pub > prymula > com
diff CloneChannel/plugins/common/gen_dsp/genlib.cpp @ 12:24d60bdea349
ClonneChannel
author | prymula <prymula76@outlook.com> |
---|---|
date | Thu, 08 Feb 2024 20:24:27 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CloneChannel/plugins/common/gen_dsp/genlib.cpp Thu Feb 08 20:24:27 2024 +0100 @@ -0,0 +1,363 @@ +/******************************************************************************************************************* +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. +*******************************************************************************************************************/ + + +#include "genlib.h" +#include "genlib_exportfunctions.h" +#include "stdlib.h" +#include "stdio.h" +#include "string.h" + +#include <cmath> + +#if DISTRHO_OS_MAC +# include <malloc/malloc.h> +#else +# include <malloc.h> +# if DISTRHO_OS_WINDOWS +# define malloc_size _msize +# else +# define malloc_size malloc_usable_size +# endif +#endif + +// DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit +#define DATA_MAXIMUM_ELEMENTS (33554432) + +//////////// export_genlib.cpp //////////// +// export version + +void my_memset(void *p, int c, long size); +void my_memcpy(void *dst, const void *src, long size); + +t_ptr sysmem_newptr(t_ptr_size size) +{ + return (t_ptr)malloc(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; +} + +t_ptr sysmem_resizeptr(void *ptr, t_ptr_size newsize) +{ + return (t_ptr)realloc(ptr, newsize); +} + +t_ptr sysmem_resizeptrclear(void *ptr, t_ptr_size newsize) +{ + t_ptr_size 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; +} + +t_ptr_size sysmem_ptrsize(void *ptr) +{ + return malloc_size(ptr); +} + +void sysmem_freeptr(void *ptr) +{ + free(ptr); +} + +void sysmem_copyptr(const void *src, void *dst, t_ptr_size bytes) +{ + my_memcpy(dst, src, bytes); +} + +void my_memset(void *p, int c, long size) +{ + char *p2 = (char *)p; + int i; + + for (i = 0; i < size; i++, p2++) + *p2 = c; +} + +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; +} + +void set_zero64(t_sample *memory, long size) +{ + long i; + + for (i = 0; i < size; i++, memory++) { + *memory = 0.; + } +} + +void genlib_report_error(const char *s) +{ + fprintf(stderr, "%s\n", s); +} + +void genlib_report_message(const char *s) +{ + fprintf(stdout, "%s\n", s); +} + +unsigned long systime_ticks(void) +{ + return 0; // Gen code can deal with this +} + +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) +{ + return 0; // to be implemented +} + +t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b) +{ + return 0; // to be implemented +} + +t_genlib_err genlib_buffer_edit_end(t_genlib_buffer *b, long valid) +{ + return 0; // to be implemented +} + +t_genlib_err genlib_buffer_getinfo(t_genlib_buffer *b, t_genlib_buffer_info *info) +{ + return 0; // to be implemented +} + +char *genlib_reference_getname(void *ref) +{ + return 0; // to be implemented +} + +void genlib_buffer_dirty(t_genlib_buffer *b) +{ + // to be implemented +} + +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 +} + +t_sample gen_msp_pow(t_sample value, t_sample power) +{ + return powf(value, power); +} + +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_genlib_data * genlib_obtain_data_from_reference(void *ref) +{ + 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; + self->cursor = 0; + 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; + 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; + + if (self->info.data) { + genlib_sysmem_freeptr(self->info.data); + self->info.data = 0; + } + genlib_sysmem_freeptr(self); +} + +long genlib_data_getcursor(t_genlib_data *b) { + t_dsp_gen_data * self = (t_dsp_gen_data *)b; + return 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_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; + 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; + genlib_report_message("warning: constraining [data] to < 256MB"); + } + // 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: + if (s > olddim) { + self->info.channels = c; + self->info.dim = s; + } else { + 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"); + // try to reallocate with a default/minimal size instead: + if (s > 512 || c > 1) { + genlib_data_resize((t_genlib_data *)self, 512, 1); + } else { + // if this fails, then Max is kaput anyway... + genlib_data_resize((t_genlib_data *)self, 4, 1); + } + return; + } + + // fill with zeroes: + set_zero64(replaced, s * c); + + // copy in old data: + if (old) { + // frames to copy: + // clamped: + copydim = olddim > s ? s : olddim; + // use memcpy if channels haven't changed: + if (c == oldchannels) { + copysz = sizeof(t_sample) * copydim * c; + //post("reset resize (same channels) %p %p, %d", self->info.data, old, copysz); + memcpy(replaced, old, copysz); + } else { + // memcpy won't work if channels have changed, + // because data is interleaved. + // 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; i<copydim; i++) { + for (j = 0; j<copychannels; j++) { + replaced[j + i*c] = old[j + i*oldchannels]; + } + } + } + } + + // now update info: + if (old == 0) { + self->info.data = replaced; + self->info.dim = s; + self->info.channels = c; + } else { + // need to be careful; the audio thread may still be using it + // since dsp_gen_data is preserved through edits + // the order of resizing has to be carefully done + // to prevent indexing out of bounds + // (or maybe I'm being too paranoid here...) + if (oldsz > sz) { + // shrink size first + if (s > olddim) { + self->info.channels = c; + self->info.dim = s; + } else { + self->info.dim = s; + self->info.channels = c; + } + self->info.data = replaced; + } else { + // shrink size after + self->info.data = replaced; + if (s > olddim) { + self->info.channels = c; + self->info.dim = s; + } else { + self->info.dim = s; + self->info.channels = c; + } + } + + // done with old: + sysmem_freeptr(old); + + } + + } +} + +void genlib_reset_complete(void *data) {} + +