comparison 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
comparison
equal deleted inserted replaced
11:78390e0e674f 12:24d60bdea349
1 /*******************************************************************************************************************
2 Copyright (c) 2012 Cycling '74
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 and associated documentation files (the "Software"), to deal in the Software without restriction,
6 including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8 subject to the following conditions:
9
10 The above copyright notice and this permission notice shall be included in all copies
11 or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
16 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
17 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 *******************************************************************************************************************/
19
20
21 #include "genlib.h"
22 #include "genlib_exportfunctions.h"
23 #include "stdlib.h"
24 #include "stdio.h"
25 #include "string.h"
26
27 #include <cmath>
28
29 #if DISTRHO_OS_MAC
30 # include <malloc/malloc.h>
31 #else
32 # include <malloc.h>
33 # if DISTRHO_OS_WINDOWS
34 # define malloc_size _msize
35 # else
36 # define malloc_size malloc_usable_size
37 # endif
38 #endif
39
40 // DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit
41 #define DATA_MAXIMUM_ELEMENTS (33554432)
42
43 //////////// export_genlib.cpp ////////////
44 // export version
45
46 void my_memset(void *p, int c, long size);
47 void my_memcpy(void *dst, const void *src, long size);
48
49 t_ptr sysmem_newptr(t_ptr_size size)
50 {
51 return (t_ptr)malloc(size);
52 }
53
54 t_ptr sysmem_newptrclear(t_ptr_size size)
55 {
56 t_ptr p = (t_ptr)malloc(size);
57
58 if (p)
59 my_memset(p, 0, size);
60
61 return p;
62 }
63
64 t_ptr sysmem_resizeptr(void *ptr, t_ptr_size newsize)
65 {
66 return (t_ptr)realloc(ptr, newsize);
67 }
68
69 t_ptr sysmem_resizeptrclear(void *ptr, t_ptr_size newsize)
70 {
71 t_ptr_size oldsize = malloc_size(ptr);
72 t_ptr p = (t_ptr)realloc(ptr, newsize);
73
74 if (p) {
75 if (newsize > oldsize)
76 my_memset((char *)p + oldsize, 0, newsize - oldsize);
77 }
78 return p;
79 }
80
81 t_ptr_size sysmem_ptrsize(void *ptr)
82 {
83 return malloc_size(ptr);
84 }
85
86 void sysmem_freeptr(void *ptr)
87 {
88 free(ptr);
89 }
90
91 void sysmem_copyptr(const void *src, void *dst, t_ptr_size bytes)
92 {
93 my_memcpy(dst, src, bytes);
94 }
95
96 void my_memset(void *p, int c, long size)
97 {
98 char *p2 = (char *)p;
99 int i;
100
101 for (i = 0; i < size; i++, p2++)
102 *p2 = c;
103 }
104
105 void my_memcpy(void *dst, const void *src, long size)
106 {
107 char *s2 = (char *)src;
108 char *d2 = (char *)dst;
109 int i;
110
111 for (i = 0; i < size; i++, s2++, d2++)
112 *d2 = *s2;
113 }
114
115 void set_zero64(t_sample *memory, long size)
116 {
117 long i;
118
119 for (i = 0; i < size; i++, memory++) {
120 *memory = 0.;
121 }
122 }
123
124 void genlib_report_error(const char *s)
125 {
126 fprintf(stderr, "%s\n", s);
127 }
128
129 void genlib_report_message(const char *s)
130 {
131 fprintf(stdout, "%s\n", s);
132 }
133
134 unsigned long systime_ticks(void)
135 {
136 return 0; // Gen code can deal with this
137 }
138
139 void * genlib_obtain_reference_from_string(const char * name) {
140 return 0; // to be implemented
141 }
142
143 // the rest is stuff to isolate gensym, attrs, atoms, buffers etc.
144 t_genlib_buffer * genlib_obtain_buffer_from_reference(void *ref)
145 {
146 return 0; // to be implemented
147 }
148
149 t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b)
150 {
151 return 0; // to be implemented
152 }
153
154 t_genlib_err genlib_buffer_edit_end(t_genlib_buffer *b, long valid)
155 {
156 return 0; // to be implemented
157 }
158
159 t_genlib_err genlib_buffer_getinfo(t_genlib_buffer *b, t_genlib_buffer_info *info)
160 {
161 return 0; // to be implemented
162 }
163
164 char *genlib_reference_getname(void *ref)
165 {
166 return 0; // to be implemented
167 }
168
169 void genlib_buffer_dirty(t_genlib_buffer *b)
170 {
171 // to be implemented
172 }
173
174 t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b)
175 {
176 return 0; // to be implemented
177 }
178
179 void genlib_buffer_perform_end(t_genlib_buffer *b)
180 {
181 // to be implemented
182 }
183
184 t_sample gen_msp_pow(t_sample value, t_sample power)
185 {
186 return powf(value, power);
187 }
188
189 void genlib_data_setbuffer(t_genlib_data *b, void *ref) {
190 genlib_report_error("not supported for export targets\n");
191 }
192
193 typedef struct {
194 t_genlib_data_info info;
195 t_sample cursor; // used by Delay
196 //t_symbol * name;
197 } t_dsp_gen_data;
198
199 t_genlib_data * genlib_obtain_data_from_reference(void *ref)
200 {
201 t_dsp_gen_data * self = (t_dsp_gen_data *)malloc(sizeof(t_dsp_gen_data));
202 self->info.dim = 0;
203 self->info.channels = 0;
204 self->info.data = 0;
205 self->cursor = 0;
206 return (t_genlib_data *)self;
207 }
208
209 t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info) {
210 t_dsp_gen_data * self = (t_dsp_gen_data *)b;
211 info->dim = self->info.dim;
212 info->channels = self->info.channels;
213 info->data = self->info.data;
214 return GENLIB_ERR_NONE;
215 }
216
217 void genlib_data_release(t_genlib_data *b) {
218 t_dsp_gen_data * self = (t_dsp_gen_data *)b;
219
220 if (self->info.data) {
221 genlib_sysmem_freeptr(self->info.data);
222 self->info.data = 0;
223 }
224 genlib_sysmem_freeptr(self);
225 }
226
227 long genlib_data_getcursor(t_genlib_data *b) {
228 t_dsp_gen_data * self = (t_dsp_gen_data *)b;
229 return self->cursor;
230 }
231
232 void genlib_data_setcursor(t_genlib_data *b, long cursor) {
233 t_dsp_gen_data * self = (t_dsp_gen_data *)b;
234 self->cursor = cursor;
235 }
236
237 void genlib_data_resize(t_genlib_data *b, long s, long c) {
238 t_dsp_gen_data * self = (t_dsp_gen_data *)b;
239
240 size_t sz, oldsz, copysz;
241 t_sample * old = 0;
242 t_sample * replaced = 0;
243 int i, j, copydim, copychannels, olddim, oldchannels;
244
245 //printf("data resize %d %d\n", s, c);
246
247 // cache old for copying:
248 old = self->info.data;
249 olddim = self->info.dim;
250 oldchannels = self->info.channels;
251
252 // limit [data] size:
253 if (s * c > DATA_MAXIMUM_ELEMENTS) {
254 s = DATA_MAXIMUM_ELEMENTS/c;
255 genlib_report_message("warning: constraining [data] to < 256MB");
256 }
257 // bytes required:
258 sz = sizeof(t_sample) * s * c;
259 oldsz = sizeof(t_sample) * olddim * oldchannels;
260
261 if (old && sz == oldsz) {
262 // no need to re-allocate, just resize
263 // careful, audio thread may still be using it:
264 if (s > olddim) {
265 self->info.channels = c;
266 self->info.dim = s;
267 } else {
268 self->info.dim = s;
269 self->info.channels = c;
270 }
271
272 set_zero64(self->info.data, s * c);
273 return;
274
275 } else {
276
277 // allocate new:
278 replaced = (t_sample *)sysmem_newptr(sz);
279
280 // check allocation:
281 if (replaced == 0) {
282 genlib_report_error("allocating [data]: out of memory");
283 // try to reallocate with a default/minimal size instead:
284 if (s > 512 || c > 1) {
285 genlib_data_resize((t_genlib_data *)self, 512, 1);
286 } else {
287 // if this fails, then Max is kaput anyway...
288 genlib_data_resize((t_genlib_data *)self, 4, 1);
289 }
290 return;
291 }
292
293 // fill with zeroes:
294 set_zero64(replaced, s * c);
295
296 // copy in old data:
297 if (old) {
298 // frames to copy:
299 // clamped:
300 copydim = olddim > s ? s : olddim;
301 // use memcpy if channels haven't changed:
302 if (c == oldchannels) {
303 copysz = sizeof(t_sample) * copydim * c;
304 //post("reset resize (same channels) %p %p, %d", self->info.data, old, copysz);
305 memcpy(replaced, old, copysz);
306 } else {
307 // memcpy won't work if channels have changed,
308 // because data is interleaved.
309 // clamp channels copied:
310 copychannels = oldchannels > c ? c : oldchannels;
311 //post("reset resize (different channels) %p %p, %d %d", self->info.data, old, copydim, copychannels);
312 for (i = 0; i<copydim; i++) {
313 for (j = 0; j<copychannels; j++) {
314 replaced[j + i*c] = old[j + i*oldchannels];
315 }
316 }
317 }
318 }
319
320 // now update info:
321 if (old == 0) {
322 self->info.data = replaced;
323 self->info.dim = s;
324 self->info.channels = c;
325 } else {
326 // need to be careful; the audio thread may still be using it
327 // since dsp_gen_data is preserved through edits
328 // the order of resizing has to be carefully done
329 // to prevent indexing out of bounds
330 // (or maybe I'm being too paranoid here...)
331 if (oldsz > sz) {
332 // shrink size first
333 if (s > olddim) {
334 self->info.channels = c;
335 self->info.dim = s;
336 } else {
337 self->info.dim = s;
338 self->info.channels = c;
339 }
340 self->info.data = replaced;
341 } else {
342 // shrink size after
343 self->info.data = replaced;
344 if (s > olddim) {
345 self->info.channels = c;
346 self->info.dim = s;
347 } else {
348 self->info.dim = s;
349 self->info.channels = c;
350 }
351 }
352
353 // done with old:
354 sysmem_freeptr(old);
355
356 }
357
358 }
359 }
360
361 void genlib_reset_complete(void *data) {}
362
363