1 /*
2 pvsbasic.c:
3 basic opcodes for transformation of streaming PV signals
4
5 Copyright (c) Victor Lazzarini, 2004
6 John ffitch, 2007 (shifting form)
7
8 This file is part of Csound.
9
10 The Csound Library is free software; you can redistribute it
11 and/or modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 Csound is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with Csound; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 02110-1301 USA
24 */
25
26 /* pvsmix */
27
28 #include "pvs_ops.h"
29 #include "pvsbasic.h"
30 #include "pvfileio.h"
31 #include <math.h>
32 #define MAXOUTS 16
33
34 static int32_t fsigs_equal(const PVSDAT *f1, const PVSDAT *f2);
35
36 typedef struct _pvsgain {
37 OPDS h;
38 PVSDAT *fout;
39 PVSDAT *fa;
40 MYFLT *kgain;
41 uint32 lastframe;
42 } PVSGAIN;
43
pvsgainset(CSOUND * csound,PVSGAIN * p)44 static int32_t pvsgainset(CSOUND *csound, PVSGAIN *p){
45
46 IGN(csound);
47 int32 N = p->fa->N;
48 p->fout->sliding = 0;
49 if (p->fa->sliding) {
50 if (p->fout->frame.auxp == NULL ||
51 p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2))
52 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS,
53 &p->fout->frame);
54 p->fout->NB = p->fa->NB;
55 p->fout->sliding = 1;
56 }
57 else
58 if (p->fout->frame.auxp == NULL ||
59 p->fout->frame.size < sizeof(float) * (N + 2))
60 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
61 p->fout->N = N;
62 p->fout->overlap = p->fa->overlap;
63 p->fout->winsize = p->fa->winsize;
64 p->fout->wintype = p->fa->wintype;
65 p->fout->format = p->fa->format;
66 p->fout->framecount = 1;
67 p->lastframe = 0;
68 if (UNLIKELY(!((p->fout->format == PVS_AMP_FREQ) ||
69 (p->fout->format == PVS_AMP_PHASE))))
70 return csound->InitError(csound, Str("pvsgain: signal format "
71 "must be amp-phase or amp-freq."));
72 return OK;
73 }
74
pvsgain(CSOUND * csound,PVSGAIN * p)75 static int32_t pvsgain(CSOUND *csound, PVSGAIN *p)
76 {
77 IGN(csound);
78 int32_t i;
79 int32 framesize;
80 float *fout, *fa;
81 MYFLT gain = *p->kgain;
82
83 if (p->fa->sliding) {
84 CMPLX * fout, *fa;
85 uint32_t offset = p->h.insdshead->ksmps_offset;
86 uint32_t early = p->h.insdshead->ksmps_no_end;
87 uint32_t n, nsmps = CS_KSMPS;
88 int32_t NB = p->fa->NB;
89 for (n=0; n<offset; n++) {
90 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
91 for (i = 0; i < NB; i++)
92 fout[i].re = fout[i].im = FL(0.0);
93 }
94 for (n=nsmps-early; n<nsmps; n++) {
95 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
96 for (i = 0; i < NB; i++)
97 fout[i].re = fout[i].im = FL(0.0);
98 }
99 nsmps -= early;
100 for (n=offset; n<nsmps; n++) {
101 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
102 fa = (CMPLX*) p->fa->frame.auxp +NB*n;
103 for (i = 0; i < NB; i++) {
104 fout[i].re = fa[i].re*gain;
105 fout[i].im = fa[i].im;
106 }
107 }
108 return OK;
109 }
110 fout = (float *) p->fout->frame.auxp;
111 fa = (float *) p->fa->frame.auxp;
112
113 framesize = p->fa->N + 2;
114
115 if (p->lastframe < p->fa->framecount) {
116 for (i = 0; i < framesize; i += 2){
117 fout[i] = fa[i]*gain;
118 fout[i+1] = fa[i+1];
119 }
120 p->fout->framecount = p->fa->framecount;
121 p->lastframe = p->fout->framecount;
122 }
123 return OK;
124 }
125
126
127
pvsinit(CSOUND * csound,PVSINI * p)128 static int32_t pvsinit(CSOUND *csound, PVSINI *p)
129 {
130 int32_t i;
131 uint32_t offset = p->h.insdshead->ksmps_offset;
132 uint32_t early = p->h.insdshead->ksmps_no_end;
133 uint32_t n, nsmps = CS_KSMPS;
134 float *bframe;
135 int32 N = (int32) *p->framesize;
136
137 p->fout->N = N;
138 p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4);
139 p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N);
140 p->fout->wintype = (int32) *p->wintype;
141 p->fout->format = (int32) *p->format;
142 p->fout->framecount = 1;
143 p->fout->sliding = 0;
144 if (p->fout->overlap < (int32_t)nsmps || p->fout->overlap <=10) {
145 int32_t NB = 1+N/2;
146 MYFLT *bframe;
147 p->fout->NB = NB;
148 if (p->fout->frame.auxp == NULL ||
149 p->fout->frame.size * CS_KSMPS < sizeof(float) * (N + 2))
150 csound->AuxAlloc(csound, (N + 2) * nsmps * sizeof(float),
151 &p->fout->frame);
152 p->fout->sliding = 1;
153 bframe = (MYFLT *) p->fout->frame.auxp;
154 for (n=0; n<nsmps; n++)
155 for (i = 0; i < N + 2; i += 2) {
156 bframe[i+n*NB] = FL(0.0);
157 bframe[i+n*NB + 1] =
158 (n<offset || n>nsmps-early ? FL(0.0) :(i >>1) * N * csound->onedsr);
159 }
160 }
161 else {
162 if (p->fout->frame.auxp == NULL ||
163 p->fout->frame.size < sizeof(float) * (N + 2)) {
164 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
165 }
166 bframe = (float *) p->fout->frame.auxp;
167 for (i = 0; i < N + 2; i += 2) {
168 //bframe[i] = 0.0f;
169 bframe[i + 1] = (i >>1) * N * csound->onedsr;
170 }
171 }
172 p->lastframe = 0;
173 return OK;
174 }
175
176
177 typedef struct {
178 OPDS h;
179 PVSDAT *fin;
180 MYFLT *file;
181 int32_t pvfile;
182 AUXCH frame;
183 AUXCH buf;
184 AUXCH dframe;
185 CSOUND *csound;
186 void *cb;
187 int32_t async;
188 #ifndef __EMSCRIPTEN__
189 void* thread;
190 #endif
191 int32_t N;
192 uint32 lastframe;
193 }PVSFWRITE;
194
195 uintptr_t pvs_io_thread(void *pp);
196
pvsfwrite_destroy(CSOUND * csound,void * pp)197 static int32_t pvsfwrite_destroy(CSOUND *csound, void *pp)
198 {
199 PVSFWRITE *p = (PVSFWRITE *) pp;
200 #ifndef __EMSCRIPTEN__
201 if (p->async){
202 p->async = 0;
203 // PTHREAD: change
204 //pthread_join(p->thread, NULL);
205 csoundJoinThread (p->thread);
206 csound->DestroyCircularBuffer(csound, p->cb);
207 }
208 #endif
209 csound->PVOC_CloseFile(csound,p->pvfile);
210 return OK;
211 }
212
pvsfwriteset_(CSOUND * csound,PVSFWRITE * p,int32_t stringname)213 static int32_t pvsfwriteset_(CSOUND *csound, PVSFWRITE *p, int32_t stringname)
214 {
215 int32_t N;
216 char fname[MAXNAME];
217
218 if (stringname==0) {
219 if (csound->ISSTRCOD(*p->file))
220 strNcpy(fname,get_arg_string(csound, *p->file), MAXNAME);
221 else csound->strarg2name(csound, fname, p->file, "pvoc.",0);
222 }
223 else strNcpy(fname, ((STRINGDAT *)p->file)->data, MAXNAME);
224
225
226
227 if (UNLIKELY(p->fin->sliding))
228 return csound->InitError(csound,Str("SDFT Not implemented in this case yet"));
229 p->pvfile= -1;
230 N = p->N = p->fin->N;
231 if ((p->pvfile = csound->PVOC_CreateFile(csound, fname,
232 p->fin->N,
233 p->fin->overlap, 1, p->fin->format,
234 CS_ESR, STYPE_16,
235 p->fin->wintype, 0.0f, NULL,
236 p->fin->winsize)) == -1)
237
238 return csound->InitError(csound,
239 Str("pvsfwrite: could not open file %s\n"),
240 fname);
241 #ifndef __EMSCRIPTEN__
242 if (csound->oparms->realtime) {
243 int32_t bufframes = 16;
244 p->csound = csound;
245 if (p->frame.auxp == NULL || p->frame.size < sizeof(MYFLT) * (N + 2))
246 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->frame);
247 if (p->buf.auxp == NULL || p->buf.size < sizeof(MYFLT) * (N + 2))
248 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->buf);
249 if (p->dframe.auxp == NULL || p->dframe.size < sizeof(float) * (N + 2))
250 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->dframe);
251 p->cb = csound->CreateCircularBuffer(csound, (N+2)*sizeof(float)*bufframes,
252 sizeof(MYFLT));
253 // PTHREAD: change
254 //pthread_create(&p->thread, NULL, pvs_io_thread, (void *) p);
255 p->thread = csoundCreateThread (pvs_io_thread, (void*)p);
256 p->async = 1;
257 } else
258 #endif
259 {
260 if (p->frame.auxp == NULL || p->frame.size < sizeof(float) * (N + 2))
261 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->frame);
262 p->async = 0;
263 }
264 csound->RegisterDeinitCallback(csound, p, pvsfwrite_destroy);
265 p->lastframe = 0;
266 return OK;
267 }
268
pvsfwriteset(CSOUND * csound,PVSFWRITE * p)269 static int32_t pvsfwriteset(CSOUND *csound, PVSFWRITE *p){
270 return pvsfwriteset_(csound,p,0);
271 }
272
pvsfwriteset_S(CSOUND * csound,PVSFWRITE * p)273 static int32_t pvsfwriteset_S(CSOUND *csound, PVSFWRITE *p){
274 return pvsfwriteset_(csound,p,1);
275 }
276
277
pvs_io_thread(void * pp)278 uintptr_t pvs_io_thread(void *pp){
279 PVSFWRITE *p = (PVSFWRITE *) pp;
280 CSOUND *csound = p->csound;
281 MYFLT *buf = (MYFLT *) p->buf.auxp;
282 float *frame = (float *) p->dframe.auxp;
283 int32_t *on = &p->async;
284 int32_t lc,n, N2=p->N+2;
285 _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
286 while (*on) {
287 lc = csound->ReadCircularBuffer(csound, p->cb, buf, N2);
288 if (lc) {
289 for (n=0; n < N2; n++) frame[n] = (float) buf[n];
290 csound->PVOC_PutFrames(csound, p->pvfile, frame, 1);
291 }
292 }
293 return (uintptr_t)0;
294 }
295
296
pvsfwrite(CSOUND * csound,PVSFWRITE * p)297 static int32_t pvsfwrite(CSOUND *csound, PVSFWRITE *p)
298 {
299 float *fin = p->fin->frame.auxp;
300
301 if (p->lastframe < p->fin->framecount) {
302 int32 framesize = p->fin->N+2,i;
303 if (p->async == 0) {
304 float _0dbfs = (float) csound->Get0dBFS(csound);
305 float *fout = p->frame.auxp;
306 for (i=0;i < framesize; i+=2) {
307 fout[i] = fin[i]/_0dbfs;
308 fout[i+1] = fin[i+1];
309 }
310 if (UNLIKELY(!csound->PVOC_PutFrames(csound, p->pvfile, fout, 1)))
311 return csound->PerfError(csound, &(p->h),
312 Str("pvsfwrite: could not write data\n"));
313 }
314 else {
315 MYFLT *fout = p->frame.auxp;
316 MYFLT _0dbfs = csound->Get0dBFS(csound);
317 for (i=0;i < framesize; i+=2){
318 fout[i] = (MYFLT) fin[i]/_0dbfs;
319 fout[i+1] = (MYFLT) fin[i+1];
320 }
321 csound->WriteCircularBuffer(csound, p->cb, fout, framesize);
322 }
323 p->lastframe = p->fin->framecount;
324 }
325 return OK;
326 }
327
328 typedef struct _pvsdiskin {
329 OPDS h;
330 PVSDAT *fout;
331 MYFLT *file;
332 MYFLT *kspeed;
333 MYFLT *kgain;
334 MYFLT *ioff;
335 MYFLT *ichn;
336 MYFLT *interp;
337 double pos;
338 uint32 oldpos;
339 int32_t chans, chn;
340 int32_t pvfile;
341 int32_t scnt;
342 uint32 flen;
343 AUXCH buffer;
344 } pvsdiskin;
345
346 #define FSIGBUFRAMES 2
347
pvsdiskinset_(CSOUND * csound,pvsdiskin * p,int32_t stringname)348 static int32_t pvsdiskinset_(CSOUND *csound, pvsdiskin *p, int32_t stringname)
349 {
350 int32_t N;
351 WAVEFORMATEX fmt;
352 PVOCDATA pvdata;
353 char fname[MAXNAME];
354
355 if (stringname==0){
356 if (csound->ISSTRCOD(*p->file))
357 strNcpy(fname,get_arg_string(csound, *p->file), MAXNAME);
358 else csound->strarg2name(csound, fname, p->file, "pvoc.",0);
359 }
360 else strNcpy(fname, ((STRINGDAT *)p->file)->data, MAXNAME);
361
362 if (UNLIKELY(p->fout->sliding))
363 return csound->InitError(csound,
364 Str("SDFT Not implemented in this case yet"));
365 if ((p->pvfile = csound->PVOC_OpenFile(csound, fname,
366 &pvdata, &fmt)) < 0)
367 return csound->InitError(csound,
368 Str("pvsdiskin: could not open file %s\n"),
369 fname);
370
371 N = (pvdata.nAnalysisBins-1)*2;
372 p->chans = fmt.nChannels;
373
374 if (p->fout->frame.auxp == NULL ||
375 p->fout->frame.size < sizeof(float) * (N + 2))
376 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
377
378 if (p->buffer.auxp == NULL ||
379 p->buffer.size < sizeof(float) * (N + 2) * FSIGBUFRAMES * p->chans)
380 csound->AuxAlloc(csound,
381 (N + 2) * sizeof(float) * FSIGBUFRAMES * p->chans,
382 &p->buffer);
383
384 p->flen = csound->PVOC_FrameCount(csound, p->pvfile) - 1;
385
386
387 p->fout->N = N;
388 p->fout->overlap = pvdata.dwOverlap;
389 p->fout->winsize = pvdata.dwWinlen;
390 switch ((pv_wtype) pvdata.wWindowType) {
391 case PVOC_HAMMING:
392 p->fout->wintype = PVS_WIN_HAMMING;
393 break;
394 case PVOC_HANN:
395 p->fout->wintype = PVS_WIN_HANN;
396 break;
397 case PVOC_KAISER:
398 p->fout->wintype = PVS_WIN_KAISER;
399 break;
400 default:
401 p->fout->wintype = PVS_WIN_HAMMING;
402 break;
403 }
404 p->fout->format = pvdata.wAnalFormat;
405 p->fout->framecount = 1;
406 p->scnt = p->fout->overlap;
407 p->pos = *p->ioff * CS_ESR/N;
408 p->oldpos = -1;
409
410 p->chn = (int32_t) (*p->ichn <= p->chans ? *p->ichn : p->chans) -1;
411 if (p->chn < 0) p->chn = 0;
412 return OK;
413 }
414
pvsdiskinset(CSOUND * csound,pvsdiskin * p)415 static int32_t pvsdiskinset(CSOUND *csound, pvsdiskin *p){
416 return pvsdiskinset_(csound, p, 0);
417 }
418
pvsdiskinset_S(CSOUND * csound,pvsdiskin * p)419 static int32_t pvsdiskinset_S(CSOUND *csound, pvsdiskin *p){
420 return pvsdiskinset_(csound, p, 1);
421 }
422
pvsdiskinproc(CSOUND * csound,pvsdiskin * p)423 static int32_t pvsdiskinproc(CSOUND *csound, pvsdiskin *p)
424 {
425 int32_t overlap = p->fout->overlap, i;
426 uint32_t posi;
427 double pos = p->pos;
428 int32 N = p->fout->N;
429 MYFLT frac;
430 float *fout = (float *) p->fout->frame.auxp;
431 float *buffer = (float *) p->buffer.auxp;
432 float *frame1 = buffer + (N+2)*p->chn;
433 float *frame2 = buffer + (N+2)*(p->chans + p->chn);
434 float amp = (float) (*p->kgain * csound->e0dbfs);
435
436 if (p->scnt >= overlap) {
437 posi = (uint32_t) pos;
438 if (posi != p->oldpos) {
439 /*
440 read new frame
441 PVOC_Rewind() is now PVOC_fseek() adapted to work
442 as fseek(), using the last argument as
443 offset
444 */
445 while(pos >= p->flen) pos -= p->flen;
446 while(pos < 0) pos += p->flen;
447 csound->PVOC_fseek(csound,p->pvfile, pos);
448 (void)csound->PVOC_GetFrames(csound, p->pvfile, buffer, 2*p->chans);
449 p->oldpos = posi = (uint32_t)pos;
450
451 }
452 if (*p->interp) {
453 /* interpolate */
454 frac = pos - posi;
455 for (i=0; i < N+2; i+=2) {
456 fout[i] = amp*(frame1[i] + frac*(frame2[i] - frame1[i]));
457 fout[i+1] = frame1[i+1] + frac*(frame2[i+1] - frame1[i+1]);
458 }
459 } else /* do not */
460 for (i=0; i < N+2; i+=2) {
461 fout[i] = amp*(frame1[i]);
462 fout[i+1] = frame1[i+1];
463 }
464
465
466 p->pos += (*p->kspeed * p->chans);
467 p->scnt -= overlap;
468 p->fout->framecount++;
469 }
470 p->scnt += CS_KSMPS;
471
472 return OK;
473 }
474
475 typedef struct _pvst {
476 OPDS h;
477 PVSDAT *fout[MAXOUTS];
478 MYFLT *ktime;
479 MYFLT *kamp;
480 MYFLT *kpitch;
481 MYFLT *knum;
482 MYFLT *konset;
483 MYFLT *wrap, *offset;
484 MYFLT *fftsize, *hsize, *dbthresh;
485 uint32 scnt;
486 int32_t tscale;
487 MYFLT accum;
488 double pos;
489 float factor, fund, rotfac, scale;
490 AUXCH bwin[MAXOUTS];
491 AUXCH fwin[MAXOUTS], nwin[MAXOUTS];
492 AUXCH win;
493 int32_t nchans;
494 int32_t init;
495 void *fwdsetup;
496 } PVST;
497
pvstanalset(CSOUND * csound,PVST * p)498 int32_t pvstanalset(CSOUND *csound, PVST *p)
499 {
500
501 int32_t i, N, hsize, nChannels;
502 N = (*p->fftsize > 0 ? *p->fftsize : 2048);
503 hsize = (*p->hsize > 0 ? *p->hsize : 512);
504 p->init = 0;
505 nChannels = csound->GetOutputArgCnt(p);
506 if (UNLIKELY(nChannels < 1 || nChannels > MAXOUTS))
507 return csound->InitError(csound, Str("invalid number of output arguments"));
508 p->nchans = nChannels;
509 for (i=0; i < p->nchans; i++) {
510 p->fout[i]->N = N;
511 p->fout[i]->overlap = hsize;
512 p->fout[i]->wintype = PVS_WIN_HANN;
513 p->fout[i]->winsize = N;
514 p->fout[i]->framecount = 1;
515 if (p->fout[i]->frame.auxp == NULL ||
516 p->fout[i]->frame.size < sizeof(float) * (N + 2))
517 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout[i]->frame);
518 else
519 memset(p->fout[i]->frame.auxp, 0, sizeof(float)*(N+2));
520 if (p->bwin[i].auxp == NULL ||
521 p->bwin[i].size < sizeof(MYFLT) * (N + 2))
522 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->bwin[i]);
523 else
524 memset(p->bwin[i].auxp, 0, p->bwin[i].size);
525 if (p->fwin[i].auxp == NULL ||
526 p->fwin[i].size < sizeof(MYFLT) * (N + 2))
527 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->fwin[i]);
528 else
529 memset(p->fwin[i].auxp, 0, sizeof(MYFLT)*(N+2));
530 if (p->nwin[i].auxp == NULL ||
531 p->nwin[i].size < sizeof(MYFLT) * (N + 2))
532 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->nwin[i]);
533 else
534 memset(p->nwin[i].auxp, 0, sizeof(MYFLT)*(N+2));
535 }
536
537 if (p->win.auxp == NULL ||
538 p->win.size < sizeof(MYFLT) * (N))
539 csound->AuxAlloc(csound, (N) * sizeof(MYFLT), &p->win);
540 p->scale = 0.0f;
541 for (i=0; i < N; i++)
542 p->scale += (((MYFLT *)p->win.auxp)[i] = 0.5 - 0.5*cos(i*2*PI/N));
543 for (i=0; i < N; i++)
544 ((MYFLT *)p->win.auxp)[i] *= 2./p->scale;
545
546 p->rotfac = hsize*TWOPI/N;
547 p->factor = CS_ESR/(hsize*TWOPI);
548 p->fund = CS_ESR/N;
549 p->scnt = p->fout[0]->overlap;
550 p->tscale = 1;
551 p->pos = *p->offset*CS_ESR;
552 //printf("off: %f\n", *p->offset);
553 p->accum = 0.0;
554 p->fwdsetup = csound->RealFFT2Setup(csound,N,FFT_FWD);
555 return OK;
556 }
557
558 typedef struct _pvst1 {
559 OPDS h;
560 PVSDAT *fout[1];
561 MYFLT *ktime;
562 MYFLT *kamp;
563 MYFLT *kpitch;
564 MYFLT *knum;
565 MYFLT *konset;
566 MYFLT *wrap, *offset;
567 MYFLT *fftsize, *hsize, *dbthresh;
568 uint32 scnt;
569 int32_t tscale;
570 MYFLT accum;
571 double pos;
572 float factor, fund, rotfac, scale;
573 AUXCH bwin[MAXOUTS];
574 AUXCH fwin[MAXOUTS], nwin[MAXOUTS];
575 AUXCH win;
576 int32_t nchans;
577 int32_t init;
578 void *fwdsetup;
579 } PVST1;
580
pvstanalset1(CSOUND * csound,PVST1 * p)581 int32_t pvstanalset1(CSOUND *csound, PVST1 *p)
582 {
583
584 int32_t i, N, hsize, nChannels;
585 N = (*p->fftsize > 0 ? *p->fftsize : 2048);
586 hsize = (*p->hsize > 0 ? *p->hsize : 512);
587 p->init = 0;
588 nChannels = csound->GetOutputArgCnt(p);
589 if (UNLIKELY(nChannels < 1 || nChannels > 1))
590 return csound->InitError(csound, Str("invalid number of output arguments"));
591 p->nchans = nChannels;
592 for (i=0; i < p->nchans; i++) {
593 p->fout[i]->N = N;
594 p->fout[i]->overlap = hsize;
595 p->fout[i]->wintype = PVS_WIN_HANN;
596 p->fout[i]->winsize = N;
597 p->fout[i]->framecount = 1;
598 if (p->fout[i]->frame.auxp == NULL ||
599 p->fout[i]->frame.size < sizeof(float) * (N + 2))
600 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout[i]->frame);
601 else
602 memset(p->fout[i]->frame.auxp, 0, sizeof(float)*(N+2));
603 if (p->bwin[i].auxp == NULL ||
604 p->bwin[i].size < sizeof(MYFLT) * (N + 2))
605 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->bwin[i]);
606 else
607 memset(p->bwin[i].auxp, 0, p->bwin[i].size);
608 if (p->fwin[i].auxp == NULL ||
609 p->fwin[i].size < sizeof(MYFLT) * (N + 2))
610 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->fwin[i]);
611 else
612 memset(p->fwin[i].auxp, 0, sizeof(MYFLT)*(N+2));
613 if (p->nwin[i].auxp == NULL ||
614 p->nwin[i].size < sizeof(MYFLT) * (N + 2))
615 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT), &p->nwin[i]);
616 else
617 memset(p->nwin[i].auxp, 0, sizeof(MYFLT)*(N+2));
618 }
619
620 if (p->win.auxp == NULL ||
621 p->win.size < sizeof(MYFLT) * (N))
622 csound->AuxAlloc(csound, (N) * sizeof(MYFLT), &p->win);
623 p->scale = 0.0f;
624 for (i=0; i < N; i++)
625 p->scale += (((MYFLT *)p->win.auxp)[i] = 0.5 - 0.5*cos(i*2*PI/N));
626 for (i=0; i < N; i++)
627 ((MYFLT *)p->win.auxp)[i] *= 2./p->scale;
628
629 p->rotfac = hsize*TWOPI/N;
630 p->factor = CS_ESR/(hsize*TWOPI);
631 p->fund = CS_ESR/N;
632 p->scnt = p->fout[0]->overlap;
633 p->tscale = 1;
634 p->pos = *p->offset*CS_ESR;
635 //printf("off: %f\n", *p->offset);
636 p->accum = 0.0;
637 p->fwdsetup = csound->RealFFT2Setup(csound,N,FFT_FWD);
638 return OK;
639 }
640
pvstanal(CSOUND * csound,PVST * p)641 int32_t pvstanal(CSOUND *csound, PVST *p)
642 {
643 int32_t hsize = p->fout[0]->overlap, i, k;
644 uint32_t j;
645 uint32_t sizefrs, nchans = p->nchans;
646 int32 N = p->fout[0]->N, post, size;
647 double frac, spos = p->pos, pos;
648 MYFLT *tab, dbtresh = *p->dbthresh;
649 FUNC *ft;
650 float *fout;
651 MYFLT *bwin, *fwin, *nwin, *win = (MYFLT *) p->win.auxp;
652 float amp = (float) (*p->kamp), factor = p->factor, fund = p->fund;
653 float pitch = (float) (*p->kpitch), rotfac = p->rotfac;
654 MYFLT time = *p->ktime;
655 float tmp_real, tmp_im, powrat;
656
657 if ((int32_t)p->scnt >= hsize) {
658 double resamp;
659 /* audio samples are stored in a function table */
660 ft = csound->FTnp2Find(csound,p->knum);
661 if (ft == NULL){
662 csound->PerfError(csound, &(p->h),
663 Str("could not find table number %d\n"), (int32_t) *p->knum);
664 return NOTOK;
665
666 }
667 resamp = ft->gen01args.sample_rate/CS_ESR;
668 pitch *= resamp;
669 time *= resamp;
670 tab = ft->ftable;
671 size = ft->flen;
672
673 /* nchans = ft->nchanls; */
674 /* spos is the reading position in samples, hsize is hopsize,
675 time is current read rate
676 esr is sampling rate
677 */
678 if (UNLIKELY(ft->nchanls != (int32)nchans))
679 return csound->PerfError(csound, &(p->h),
680 Str("number of output arguments "
681 "inconsistent with number of "
682 "sound file channels"));
683
684 sizefrs = size/nchans;
685 if (!*p->wrap && spos == 0.0)
686 spos += hsize;
687 if (!*p->wrap && spos >= sizefrs) {
688 for (j=0; j < nchans; j++) {
689 memset(p->fout[j]->frame.auxp, 0, sizeof(float)*(N+2));
690 p->fout[j]->framecount++;
691 }
692 goto end;
693 }
694
695 while (spos >= sizefrs) spos -= sizefrs;
696 while (spos < hsize) spos += (sizefrs + hsize);
697 pos = spos;
698
699 for (j=0; j < nchans; j++) {
700
701 fout = (float *) p->fout[j]->frame.auxp;
702 bwin = (MYFLT *) p->bwin[j].auxp;
703 fwin = (MYFLT *) p->fwin[j].auxp;
704 nwin = (MYFLT *) p->nwin[j].auxp;
705
706 /* this loop fills two frames/windows with samples from table,
707 reading is linearly-interpolated,
708 frames are separated by 1 hopsize
709 */
710 for (i=0; i < N; i++) {
711 /* front window, fwin */
712 MYFLT in;
713 post = (int32_t) pos;
714 frac = pos - post;
715 post *= nchans;
716 post += j;
717 while (post >= size ) post -= size;
718 while (post < 0) post += size;
719 in = tab[post] + frac*(tab[post+nchans] - tab[post]);
720 fwin[i] = amp * in * win[i]; /* window it */
721 /* back windo, bwin */
722 post = (int32_t) (pos - hsize*pitch);
723 post *= nchans;
724 post += j;
725 while (post >= size ) post -= size;
726 while (post < 0) post += size;
727 in = tab[post] + frac*(tab[post+nchans] - tab[post]);
728 bwin[i] = in * win[i]; /* window it */
729 if (*p->konset){
730 post = (int32_t) pos + hsize;
731 post *= nchans;
732 post += j;
733 while (post >= size ) post -= size;
734 while (post < 0) post += size;
735 in = tab[post];
736 nwin[i] = amp * in * win[i];
737 }
738 /* increment read pos according to pitch transposition */
739 pos += pitch;
740 }
741 /* take the FFT of both frames
742 re-order Nyquist bin from pos 1 to N
743 */
744 csound->RealFFT2(csound, p->fwdsetup, bwin);
745 csound->RealFFT2(csound, p->fwdsetup, fwin);
746 if (*p->konset){
747 csound->RealFFT2(csound,p->fwdsetup, nwin);
748 tmp_real = tmp_im = 1e-20f;
749 for (i=2; i < N; i++) {
750 tmp_real += nwin[i]*nwin[i] + nwin[i+1]*nwin[i+1];
751 tmp_im += fwin[i]*fwin[i] + fwin[i+1]*fwin[i+1];
752 }
753 powrat = FL(20.0)*LOG10(tmp_real/tmp_im);
754 if (powrat > dbtresh) p->tscale=0;
755 } else p->tscale=1;
756
757 fwin[N+1] = fwin[1] = 0.0;
758
759 for (i=2,k=1; i < N; i+=2, k++) {
760 double bph, fph, dph;
761 /* freqs */
762 bph = atan2(bwin[i+1],bwin[i]);
763 fph = atan2(fwin[i+1],fwin[i]);
764 /* pdiff, compensate for rotation */
765 dph = fph - bph - rotfac*k;
766 while(dph > PI) dph -= TWOPI;
767 while(dph < -PI) dph += TWOPI;
768 fout[i+1] = (float) (dph*factor + k*fund);
769 /* mags */
770 fout[i] = (float) hypot(fwin[i],fwin[i+1]);
771 }
772
773 p->fout[j]->framecount++;
774 }
775 if (time < 0 || time >= 1 || !*p->konset) {
776 spos += hsize*time;
777 }
778 else if (p->tscale) {
779 spos += hsize*(time/(1+p->accum));
780 p->accum=0.0;
781 }
782 else {
783 spos += hsize;
784 p->accum++;
785 p->tscale = 1;
786 }
787 end:
788 p->scnt -= hsize;
789 p->pos = spos;
790 }
791 p->scnt += CS_KSMPS;
792 return OK;
793
794 }
795
pvstanal1(CSOUND * csound,PVST1 * p)796 int32_t pvstanal1(CSOUND *csound, PVST1 *p)
797 {
798 int32_t hsize = p->fout[0]->overlap, i, k;
799 uint32_t j;
800 uint32_t sizefrs, nchans = p->nchans;
801 int32 N = p->fout[0]->N, post, size;
802 double frac, spos = p->pos, pos;
803 MYFLT *tab, dbtresh = *p->dbthresh;
804 FUNC *ft;
805 float *fout;
806 MYFLT *bwin, *fwin, *nwin, *win = (MYFLT *) p->win.auxp;
807 float amp = (float) (*p->kamp), factor = p->factor, fund = p->fund;
808 float pitch = (float) (*p->kpitch), rotfac = p->rotfac;
809 MYFLT time = *p->ktime;
810 float tmp_real, tmp_im, powrat;
811
812 if ((int32_t)p->scnt >= hsize) {
813 double resamp;
814 /* audio samples are stored in a function table */
815 ft = csound->FTnp2Find(csound,p->knum);
816 if (ft == NULL){
817 csound->PerfError(csound, &(p->h),
818 Str("could not find table number %d\n"), (int32_t) *p->knum);
819 return NOTOK;
820
821 }
822 resamp = ft->gen01args.sample_rate/CS_ESR;
823 pitch *= resamp;
824 time *= resamp;
825 tab = ft->ftable;
826 size = ft->flen;
827
828 /* nchans = ft->nchanls; */
829 /* spos is the reading position in samples, hsize is hopsize,
830 time is current read rate
831 esr is sampling rate
832 */
833 if (UNLIKELY(ft->nchanls != (int32)nchans))
834 return csound->PerfError(csound, &(p->h),
835 Str("number of output arguments "
836 "inconsistent with number of "
837 "sound file channels"));
838
839 sizefrs = size/nchans;
840 if (!*p->wrap && spos == 0.0)
841 spos += hsize;
842 if (!*p->wrap && spos >= sizefrs) {
843 for (j=0; j < nchans; j++) {
844 memset(p->fout[j]->frame.auxp, 0, sizeof(float)*(N+2));
845 p->fout[j]->framecount++;
846 }
847 goto end;
848 }
849
850 while (spos >= sizefrs) spos -= sizefrs;
851 while (spos < hsize) spos += (sizefrs + hsize);
852 pos = spos;
853
854 for (j=0; j < nchans; j++) {
855
856 fout = (float *) p->fout[j]->frame.auxp;
857 bwin = (MYFLT *) p->bwin[j].auxp;
858 fwin = (MYFLT *) p->fwin[j].auxp;
859 nwin = (MYFLT *) p->nwin[j].auxp;
860
861 /* this loop fills two frames/windows with samples from table,
862 reading is linearly-interpolated,
863 frames are separated by 1 hopsize
864 */
865 for (i=0; i < N; i++) {
866 /* front window, fwin */
867 MYFLT in;
868 post = (int32_t) pos;
869 frac = pos - post;
870 post *= nchans;
871 post += j;
872 while (post >= size ) post -= size;
873 while (post < 0) post += size;
874 in = tab[post] + frac*(tab[post+nchans] - tab[post]);
875 fwin[i] = amp * in * win[i]; /* window it */
876 /* back windo, bwin */
877 post = (int32_t) (pos - hsize*pitch);
878 post *= nchans;
879 post += j;
880 while (post >= size ) post -= size;
881 while (post < 0) post += size;
882 in = tab[post] + frac*(tab[post+nchans] - tab[post]);
883 bwin[i] = in * win[i]; /* window it */
884 if (*p->konset){
885 post = (int32_t) pos + hsize;
886 post *= nchans;
887 post += j;
888 while (post >= size ) post -= size;
889 while (post < 0) post += size;
890 in = tab[post];
891 nwin[i] = amp * in * win[i];
892 }
893 /* increment read pos according to pitch transposition */
894 pos += pitch;
895 }
896 /* take the FFT of both frames
897 re-order Nyquist bin from pos 1 to N
898 */
899 csound->RealFFT2(csound, p->fwdsetup, bwin);
900 csound->RealFFT2(csound, p->fwdsetup, fwin);
901 if (*p->konset){
902 csound->RealFFT2(csound,p->fwdsetup, nwin);
903 tmp_real = tmp_im = 1e-20f;
904 for (i=2; i < N; i++) {
905 tmp_real += nwin[i]*nwin[i] + nwin[i+1]*nwin[i+1];
906 tmp_im += fwin[i]*fwin[i] + fwin[i+1]*fwin[i+1];
907 }
908 powrat = FL(20.0)*LOG10(tmp_real/tmp_im);
909 if (powrat > dbtresh) p->tscale=0;
910 } else p->tscale=1;
911
912 fwin[N+1] = fwin[1] = 0.0;
913
914 for (i=2,k=1; i < N; i+=2, k++) {
915 double bph, fph, dph;
916 /* freqs */
917 bph = atan2(bwin[i+1],bwin[i]);
918 fph = atan2(fwin[i+1],fwin[i]);
919 /* pdiff, compensate for rotation */
920 dph = fph - bph - rotfac*k;
921 while(dph > PI) dph -= TWOPI;
922 while(dph < -PI) dph += TWOPI;
923 fout[i+1] = (float) (dph*factor + k*fund);
924 /* mags */
925 fout[i] = (float) hypot(fwin[i],fwin[i+1]);
926 }
927
928 p->fout[j]->framecount++;
929 }
930 if (time < 0 || time >= 1 || !*p->konset) {
931 spos += hsize*time;
932 }
933 else if (p->tscale) {
934 spos += hsize*(time/(1+p->accum));
935 p->accum=0.0;
936 }
937 else {
938 spos += hsize;
939 p->accum++;
940 p->tscale = 1;
941 }
942 end:
943 p->scnt -= hsize;
944 p->pos = spos;
945 }
946 p->scnt += CS_KSMPS;
947 return OK;
948
949 }
950
pvsfreezeset(CSOUND * csound,PVSFREEZE * p)951 static int32_t pvsfreezeset(CSOUND *csound, PVSFREEZE *p)
952 {
953 int32 N = p->fin->N;
954
955 if (UNLIKELY(p->fin == p->fout))
956 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
957 p->fout->N = N;
958 p->fout->overlap = p->fin->overlap;
959 p->fout->winsize = p->fin->winsize;
960 p->fout->wintype = p->fin->wintype;
961 p->fout->format = p->fin->format;
962 p->fout->framecount = 1;
963 p->lastframe = 0;
964
965 p->fout->NB = (N/2)+1;
966 p->fout->sliding = p->fin->sliding;
967 if (p->fin->sliding) {
968 uint32_t nsmps = CS_KSMPS;
969 if (p->fout->frame.auxp == NULL ||
970 p->fout->frame.size < sizeof(MYFLT) * (N + 2) * nsmps)
971 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * nsmps,
972 &p->fout->frame);
973 if (p->freez.auxp == NULL ||
974 p->freez.size < sizeof(MYFLT) * (N + 2) * nsmps)
975 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * nsmps, &p->freez);
976 }
977 else
978 {
979 if (p->fout->frame.auxp == NULL ||
980 p->fout->frame.size < sizeof(float) * (N + 2))
981 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
982 if (p->freez.auxp == NULL || p->freez.size < sizeof(float) * (N + 2))
983 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->freez);
984
985 if (UNLIKELY(!((p->fout->format == PVS_AMP_FREQ) ||
986 (p->fout->format == PVS_AMP_PHASE))))
987 return csound->InitError(csound, Str("pvsfreeze: signal format "
988 "must be amp-phase or amp-freq."));
989 }
990 return OK;
991 }
992
pvssfreezeprocess(CSOUND * csound,PVSFREEZE * p)993 static int32_t pvssfreezeprocess(CSOUND *csound, PVSFREEZE *p)
994 {
995 IGN(csound);
996 int32_t i;
997 uint32_t offset = p->h.insdshead->ksmps_offset;
998 uint32_t n, nsmps = CS_KSMPS;
999 int32_t NB = p->fin->NB;
1000 MYFLT freeza = *p->kfra, freezf = *p->kfrf;
1001 CMPLX *fz = (CMPLX*)p->freez.auxp;
1002
1003 for (n=0; n<offset; n++) {
1004 CMPLX *fo = (CMPLX*)p->fout->frame.auxp + n*NB;
1005 for (i = 0; i < NB; i++) fo[i].re = fo[i].im = FL(0.0);
1006 }
1007 for (n=offset; n<nsmps; n++) {
1008 CMPLX *fo = (CMPLX*)p->fout->frame.auxp + n*NB;
1009 CMPLX *fi = (CMPLX*)p->fin->frame.auxp + n*NB;
1010 for (i = 0; i < NB; i++) {
1011 if (freeza < 1)
1012 fz[i].re = fi[i].re;
1013 if (freezf < 1)
1014 fz[i].im = fi[i].im;
1015 fo[i] = fz[i];
1016 }
1017 }
1018 return OK;
1019 }
1020
pvsfreezeprocess(CSOUND * csound,PVSFREEZE * p)1021 static int32_t pvsfreezeprocess(CSOUND *csound, PVSFREEZE *p)
1022 {
1023 int32_t i;
1024 int32 framesize;
1025 MYFLT freeza, freezf;
1026 float *fout, *fin, *freez;
1027 if (p->fin->sliding)
1028 return pvssfreezeprocess(csound, p);
1029 freeza = *p->kfra;
1030 freezf = *p->kfrf;
1031 fout = (float *) p->fout->frame.auxp;
1032 fin = (float *) p->fin->frame.auxp;
1033 freez = (float *) p->freez.auxp;
1034
1035 framesize = p->fin->N + 2;
1036
1037 if (p->lastframe < p->fin->framecount) {
1038
1039 for (i = 0; i < framesize; i += 2) {
1040 if (freeza < 1)
1041 freez[i] = fin[i];
1042 if (freezf < 1)
1043 freez[i + 1] = fin[i + 1];
1044 fout[i] = freez[i];
1045 fout[i + 1] = freez[i + 1];
1046 }
1047 p->fout->framecount = p->lastframe = p->fin->framecount;
1048 }
1049 return OK;
1050 }
1051
pvsoscset(CSOUND * csound,PVSOSC * p)1052 static int32_t pvsoscset(CSOUND *csound, PVSOSC *p)
1053 {
1054 int32_t i;
1055 int32 N = (int32) *p->framesize;
1056
1057 p->fout->N = N;
1058 p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4);
1059 p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N);
1060 p->fout->wintype = (int32) *p->wintype;
1061 p->fout->format = (int32) *p->format;
1062 p->fout->framecount = 0;
1063 p->fout->sliding = 0;
1064 if (p->fout->overlap<(int32_t)CS_KSMPS || p->fout->overlap<=10) {
1065 return csound->InitError(csound, Str("pvsosc does not work while sliding"));
1066 #ifdef SOME_FINE_DAY
1067 CMPLX *bframe;
1068 int32_t NB = 1+N/2;
1069 uint32_t offset = p->h.insdshead->ksmps_offset;
1070 uint32_t n, nsmps = CS_KSMPS;
1071
1072 p->fout->NB = NB;
1073 p->fout->sliding = 1;
1074 if (p->fout->frame.auxp == NULL ||
1075 p->fout->frame.size < CS_KSMPS*sizeof(MYFLT) * (N + 2))
1076 csound->AuxAlloc(csound,
1077 (N + 2) * CS_KSMPS* sizeof(MYFLT), &p->fout->frame);
1078 else memset(p->fout->frame.auxp,
1079 '\0', (N + 2) * CS_KSMPS* sizeof(MYFLT));
1080 bframe = (CMPLX *)p->fout->frame.auxp;
1081 for (n=0; n<nsmps; n++)
1082 for (i = 0; i < NB; i++) {
1083 bframe[i+NB*n].re = FL(0.0);
1084 bframe[i+NB*n].im = (n<offset ? FL(0.0) : i * N * csound->onedsr);
1085 }
1086 return OK;
1087 #endif
1088 }
1089 else
1090 {
1091 float *bframe;
1092 int32_t j;
1093 if (p->fout->frame.auxp == NULL ||
1094 p->fout->frame.size < sizeof(float) * (N + 2))
1095 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
1096 bframe = (float *) p->fout->frame.auxp;
1097 for (i = j = 0; i < N + 2; i += 2, j++) {
1098 //bframe[i] = 0.0f;
1099 bframe[i + 1] = j * N * csound->onedsr;
1100 }
1101 p->lastframe = 1;
1102 p->incr = (MYFLT)CS_KSMPS/p->fout->overlap;
1103 }
1104 return OK;
1105 }
1106
pvsoscprocess(CSOUND * csound,PVSOSC * p)1107 static int32_t pvsoscprocess(CSOUND *csound, PVSOSC *p)
1108 {
1109 int32_t i, harm, type;
1110 int32 framesize;
1111 MYFLT famp, ffun,w;
1112 float *fout;
1113 double cfbin,a;
1114 float amp, freq;
1115 int32_t cbin, k, n;
1116
1117 famp = *p->ka;
1118 ffun = *p->kf;
1119 type = (int32_t)MYFLT2LRND(*p->type);
1120 fout = (float *) p->fout->frame.auxp;
1121
1122 framesize = p->fout->N + 2;
1123
1124 if (p->fout->sliding) {
1125 CMPLX *fout;
1126 uint32_t offset = p->h.insdshead->ksmps_offset;
1127 uint32_t n, nsmps = CS_KSMPS;
1128 int32_t NB = p->fout->NB;
1129 harm = (int32_t)(CS_ESR/(2*ffun));
1130 if (type==1) famp *= FL(1.456)/POWER((MYFLT)harm, FL(1.0)/FL(2.4));
1131 else if (type==2) famp *= FL(1.456)/POWER((MYFLT)harm, FL(0.25));
1132 else if (type==3) famp *= FL(1.456)/POWER((MYFLT)harm, FL(1.0)/FL(160.0));
1133 else {
1134 harm = 1;
1135 famp *= FL(1.456);
1136 }
1137
1138 for (n=0; n<nsmps; n++) {
1139 int32_t m;
1140 fout = (CMPLX*) p->fout->frame.auxp + n*NB;
1141 w = CS_ESR/p->fout->N;
1142 /* harm = (int32_t)(CS_ESR/(2*ffun)); */
1143 memset(fout, '\0', NB*sizeof(CMPLX));
1144 if (n<offset) continue;
1145 for (m=1; m <= harm; m++) {
1146 if (type == 3) amp = famp/(harm);
1147 else amp = (famp/m);
1148 freq = ffun*m;
1149 cfbin = freq/w;
1150 cbin = (int32_t)MYFLT2LRND(cfbin);
1151 if (cbin != 0) {
1152 for (i=cbin-1;i < cbin+3 &&i < NB ; i++) {
1153 if (i-cfbin == 0) a = 1;
1154 else a = sin(i-cfbin)/(i-cfbin);
1155 fout[i].re = amp*a*a*a;
1156 fout[i].im = freq;
1157 }
1158 if (type==2) m++;
1159 }
1160 }
1161 }
1162 return OK;
1163 }
1164 if (p->lastframe > p->fout->framecount) {
1165 w = CS_ESR/p->fout->N;
1166 harm = (int32_t)(CS_ESR/(2*ffun));
1167 if (type==1) famp *= FL(1.456)/pow(harm, FL(1.0)/FL(2.4));
1168 else if (type==2) famp *= FL(1.456)/POWER(harm, FL(0.25));
1169 else if (type==3) famp *= FL(1.456)/POWER(harm, FL(1.0)/FL(160.0));
1170 else {
1171 harm = 1;
1172 famp *= FL(1.456);
1173 }
1174 memset(fout, 0, sizeof(float)*framesize);
1175 /* for (i = 0; i < framesize; i ++) fout[i] = 0.f; */
1176
1177 for (n=1; n <= harm; n++) {
1178 if (type == 3) amp = famp/(harm);
1179 else amp = (famp/n);
1180 freq = ffun*n;
1181 cfbin = freq/w;
1182 cbin = (int32_t)MYFLT2LRND(cfbin);
1183 if (cbin != 0) {
1184 for (i=cbin-1,k = (cbin-1)<<1;i < cbin+3 &&i < framesize/2 ; i++, k+=2) {
1185 //k = i<<1;
1186 if (i-cfbin == 0) a = 1;
1187 else a = sin(i-cfbin)/(i-cfbin);
1188 fout[k] = amp*a*a*a;
1189 fout[k+1] = freq;
1190 }
1191 if (type==2) n++;
1192 }
1193 }
1194 p->fout->framecount = p->lastframe;
1195 }
1196 p->incr += p->incr;
1197 if (p->incr > 1) {
1198 p->incr = (MYFLT)CS_KSMPS/p->fout->overlap;
1199 p->lastframe++;
1200 }
1201 return OK;
1202 }
1203
1204
pvsbinset(CSOUND * csound,PVSBIN * p)1205 static int32_t pvsbinset(CSOUND *csound, PVSBIN *p)
1206 {
1207 IGN(csound);
1208 p->lastframe = 0;
1209 return OK;
1210 }
1211
pvsbinprocess(CSOUND * csound,PVSBIN * p)1212 static int32_t pvsbinprocess(CSOUND *csound, PVSBIN *p)
1213 {
1214 IGN(csound);
1215 int32 framesize, pos;
1216 if (p->fin->sliding) {
1217 CMPLX *fin = (CMPLX *) p->fin->frame.auxp;
1218 framesize = p->fin->NB;
1219 pos=*p->kbin;
1220 if (pos >= 0 && pos < framesize) {
1221 *p->kamp = (MYFLT)fin[pos].re;
1222 *p->kfreq = (MYFLT)fin[pos].im;
1223 }
1224 }
1225 else
1226 {
1227 float *fin;
1228 fin = (float *) p->fin->frame.auxp;
1229 if (p->lastframe < p->fin->framecount) {
1230 framesize = p->fin->N + 2;
1231 pos=*p->kbin*2;
1232 if (pos >= 0 && pos < framesize) {
1233 *p->kamp = (MYFLT)fin[pos];
1234 *p->kfreq = (MYFLT)fin[pos+1];
1235 }
1236 p->lastframe = p->fin->framecount;
1237 }
1238 }
1239 return OK;
1240 }
1241
pvsbinprocessa(CSOUND * csound,PVSBIN * p)1242 static int32_t pvsbinprocessa(CSOUND *csound, PVSBIN *p)
1243 {
1244 IGN(csound);
1245 int32 framesize, pos;
1246 if (p->fin->sliding) {
1247 uint32_t offset = p->h.insdshead->ksmps_offset;
1248 uint32_t k, nsmps = CS_KSMPS;
1249 CMPLX *fin = (CMPLX *) p->fin->frame.auxp;
1250 int32_t NB = p->fin->NB;
1251 pos = *p->kbin;
1252 if (pos >= 0 && pos < NB) {
1253 for (k=0; k<offset; k++) p->kamp[k] = p->kfreq[k] = FL(0.0);
1254 for (k=offset; k<nsmps; k++) {
1255 p->kamp[k] = (MYFLT)fin[pos+NB*k].re;
1256 p->kfreq[k] = (MYFLT)fin[pos+NB*k].im;
1257 }
1258 }
1259 }
1260 else {
1261 float *fin;
1262 uint32_t offset = p->h.insdshead->ksmps_offset;
1263 uint32_t k, nsmps = CS_KSMPS;
1264 fin = (float *) p->fin->frame.auxp;
1265 if (p->lastframe < p->fin->framecount) {
1266 framesize = p->fin->N + 2;
1267 pos=*p->kbin*2;
1268 if (pos >= 0 && pos < framesize) {
1269 memset(p->kamp, '\0', offset*sizeof(MYFLT));
1270 memset(p->kfreq, '\0', offset*sizeof(MYFLT));
1271 for (k=offset; k<nsmps; k++) {
1272 p->kamp[k] = (MYFLT)fin[pos];
1273 p->kfreq[k] = (MYFLT)fin[pos+1];
1274 }
1275 p->lastframe = p->fin->framecount;
1276 }
1277 }
1278 }
1279 return OK;
1280 }
1281
pvsmoothset(CSOUND * csound,PVSMOOTH * p)1282 static int32_t pvsmoothset(CSOUND *csound, PVSMOOTH *p)
1283 {
1284 int32 N = p->fin->N;
1285
1286 if (UNLIKELY(p->fin == p->fout))
1287 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
1288 p->fout->NB = (N/2)+1;
1289 p->fout->sliding = p->fin->sliding;
1290 if (p->fin->sliding) {
1291 if (p->fout->frame.auxp == NULL ||
1292 p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2))
1293 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS,
1294 &p->fout->frame);
1295 if (p->del.auxp == NULL ||
1296 p->del.size < sizeof(MYFLT) * CS_KSMPS * (N + 2))
1297 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS,
1298 &p->del);
1299 }
1300 else
1301 {
1302 if (p->fout->frame.auxp == NULL ||
1303 p->fout->frame.size < sizeof(float) * (N + 2))
1304 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
1305 if (p->del.auxp == NULL || p->del.size < sizeof(float) * (N + 2))
1306 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->del);
1307 }
1308 memset(p->del.auxp, 0, (N + 2) * sizeof(float));
1309 p->fout->N = N;
1310 p->fout->overlap = p->fin->overlap;
1311 p->fout->winsize = p->fin->winsize;
1312 p->fout->wintype = p->fin->wintype;
1313 p->fout->format = p->fin->format;
1314 p->fout->framecount = 1;
1315 p->lastframe = 0;
1316 if (UNLIKELY(!((p->fout->format == PVS_AMP_FREQ) ||
1317 (p->fout->format == PVS_AMP_PHASE))))
1318 return csound->InitError(csound, Str("pvsmooth: signal format "
1319 "must be amp-phase or amp-freq."));
1320 return OK;
1321 }
1322
pvsmoothprocess(CSOUND * csound,PVSMOOTH * p)1323 static int32_t pvsmoothprocess(CSOUND *csound, PVSMOOTH *p)
1324 {
1325 IGN(csound);
1326 int32_t i;
1327 int32 framesize;
1328 double ffa, ffr;
1329
1330 ffa = (double) *p->kfra;
1331 ffr = (double) *p->kfrf;
1332
1333
1334 framesize = p->fin->N + 2;
1335
1336 if (p->fin->sliding) {
1337 CMPLX *fout, *fin, *del;
1338 double costh1, costh2, coef1, coef2;
1339 uint32_t offset = p->h.insdshead->ksmps_offset;
1340 uint32_t n, nsmps = CS_KSMPS;
1341 int32_t NB = p->fin->NB;
1342 ffa = ffa < 0.0 ? 0.0 : (ffa > 1.0 ? 1.0 : ffa);
1343 ffr = ffr < 0.0 ? 0.0 : (ffr > 1.0 ? 1.0 : ffr);
1344 costh1 = 2.0 - cos(PI * ffa);
1345 costh2 = 2.0 - cos(PI * ffr);
1346 coef1 = sqrt(costh1 * costh1 - 1.0) - costh1;
1347 coef2 = sqrt(costh2 * costh2 - 1.0) - costh2;
1348
1349 for (n=0; n<offset; n++)
1350 for (i=0; i<NB; i++) {
1351 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
1352 del = (CMPLX*) p->del.auxp +NB*n;
1353 fout[i].re = fout[i].im = del[i].re = del[i].im = FL(0.0);
1354 }
1355 for (n=offset; n<nsmps; n++) {
1356 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
1357 fin = (CMPLX*) p->fin->frame.auxp +NB*n;
1358 del = (CMPLX*) p->del.auxp +NB*n;
1359 if (IS_ASIG_ARG(p->kfra)) {
1360 ffa = (double) p->kfra[n];
1361 ffa = ffa < 0.0 ? 0.0 : (ffa > 1.0 ? 1.0 : ffa);
1362 costh1 = 2.0 - cos(PI * ffa);
1363 coef1 = sqrt(costh1 * costh1 - 1.0) - costh1;
1364 }
1365 if (IS_ASIG_ARG(p->kfrf)) {
1366 ffr = (double) p->kfrf[n];
1367 ffr = ffr < 0.0 ? 0.0 : (ffr > 1.0 ? 1.0 : ffr);
1368 costh2 = 2.0 - cos(PI * ffr);
1369 coef2 = sqrt(costh2 * costh2 - 1.0) - costh2;
1370 }
1371 for (i=0; i<NB; i++) {
1372 /* amp smoothing */
1373 fout[i].re = fin[i].re * (1.0 + coef1) - del[i].re * coef1;
1374 /* freq smoothing */
1375 fout[i].im = fin[i].im * (1.0 + coef2) - del[i].im * coef2;
1376 del[i] = fout[i];
1377 }
1378 }
1379 return OK;
1380 }
1381 if (p->lastframe < p->fin->framecount) {
1382 float *fout, *fin, *del;
1383 double costh1, costh2, coef1, coef2;
1384 fout = (float *) p->fout->frame.auxp;
1385 fin = (float *) p->fin->frame.auxp;
1386 del = (float *) p->del.auxp;
1387
1388 ffa = ffa < FL(0.0) ? FL(0.0) : (ffa > FL(1.0) ? FL(1.0) : ffa);
1389 ffr = ffr < FL(0.0) ? FL(0.0) : (ffr > FL(1.0) ? FL(1.0) : ffr);
1390 costh1 = 2.0 - cos(PI * ffa);
1391 costh2 = 2.0 - cos(PI * ffr);
1392 coef1 = sqrt(costh1 * costh1 - 1.0) - costh1;
1393 coef2 = sqrt(costh2 * costh2 - 1.0) - costh2;
1394
1395 for (i = 0; i < framesize; i += 2) {
1396 /* amp smoothing */
1397 fout[i] = (float) (fin[i] * (1.0 + coef1) - del[i] * coef1);
1398 /* freq smoothing */
1399 fout[i + 1] = (float) (fin[i + 1] * (1.0 + coef2) - del[i + 1] * coef2);
1400 del[i] = fout[i];
1401 del[i + 1] = fout[i + 1];
1402 }
1403 p->fout->framecount = p->lastframe = p->fin->framecount;
1404 }
1405 return OK;
1406 }
1407
pvsmixset(CSOUND * csound,PVSMIX * p)1408 static int32_t pvsmixset(CSOUND *csound, PVSMIX *p)
1409 {
1410 int32 N = p->fa->N;
1411
1412 /* if (UNLIKELY(p->fa == p->fout || p->fb == p->fout))
1413 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));*/
1414 p->fout->sliding = 0;
1415 if (p->fa->sliding) {
1416 if (p->fout->frame.auxp == NULL ||
1417 p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2))
1418 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS,
1419 &p->fout->frame);
1420 p->fout->NB = p->fa->NB;
1421 p->fout->sliding = 1;
1422 }
1423 else
1424 if (p->fout->frame.auxp == NULL ||
1425 p->fout->frame.size < sizeof(float) * (N + 2))
1426 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
1427 p->fout->N = N;
1428 p->fout->overlap = p->fa->overlap;
1429 p->fout->winsize = p->fa->winsize;
1430 p->fout->wintype = p->fa->wintype;
1431 p->fout->format = p->fa->format;
1432 p->fout->framecount = 1;
1433 p->lastframe = 0;
1434 if (UNLIKELY(!((p->fout->format == PVS_AMP_FREQ) ||
1435 (p->fout->format == PVS_AMP_PHASE))))
1436 return csound->InitError(csound, Str("pvsmix: signal format "
1437 "must be amp-phase or amp-freq."));
1438 return OK;
1439 }
1440
pvsmix(CSOUND * csound,PVSMIX * p)1441 static int32_t pvsmix(CSOUND *csound, PVSMIX *p)
1442 {
1443 int32_t i;
1444 int32 framesize;
1445 int32_t test;
1446 float *fout, *fa, *fb;
1447
1448 if (UNLIKELY(!fsigs_equal(p->fa, p->fb))) goto err1;
1449 if (p->fa->sliding) {
1450 CMPLX * fout, *fa, *fb;
1451 uint32_t offset = p->h.insdshead->ksmps_offset;
1452 uint32_t n, nsmps = CS_KSMPS;
1453 int32_t NB = p->fa->NB;
1454 for (n=0; n<offset; n++) {
1455 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
1456 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
1457 }
1458 for (n=offset; n<nsmps; n++) {
1459 fout = (CMPLX*) p->fout->frame.auxp +NB*n;
1460 fa = (CMPLX*) p->fa->frame.auxp +NB*n;
1461 fb = (CMPLX*) p->fb->frame.auxp +NB*n;
1462 for (i = 0; i < NB; i++) {
1463 fout[i] = (fa[i].re >= fb[i].re) ? fa[i] : fb[i];
1464 }
1465 }
1466 return OK;
1467 }
1468 fout = (float *) p->fout->frame.auxp;
1469 fa = (float *) p->fa->frame.auxp;
1470 fb = (float *) p->fb->frame.auxp;
1471
1472 framesize = p->fa->N + 2;
1473
1474 if (p->lastframe < p->fa->framecount) {
1475 for (i = 0; i < framesize; i += 2) {
1476 test = fa[i] >= fb[i];
1477 if (test) {
1478 fout[i] = fa[i];
1479 fout[i + 1] = fa[i + 1];
1480 }
1481 else {
1482 fout[i] = fb[i];
1483 fout[i + 1] = fb[i + 1];
1484 }
1485 }
1486 p->fout->framecount = p->fa->framecount;
1487 p->lastframe = p->fout->framecount;
1488 }
1489 return OK;
1490 err1:
1491 return csound->PerfError(csound, &(p->h),
1492 Str("pvsmix: formats are different."));
1493 }
1494
1495 /* pvsfilter */
1496
pvsfilterset(CSOUND * csound,PVSFILTER * p)1497 static int32_t pvsfilterset(CSOUND *csound, PVSFILTER *p)
1498 {
1499 int32 N = p->fin->N;
1500
1501 if (UNLIKELY(p->fin == p->fout || p->fil == p->fout))
1502 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
1503 if (UNLIKELY(!((p->fout->format == PVS_AMP_FREQ) ||
1504 (p->fout->format == PVS_AMP_PHASE))))
1505 return csound->InitError(csound, Str("pvsfilter: signal format "
1506 "must be amp-phase or amp-freq."));
1507 p->fout->sliding = 0;
1508 if (p->fin->sliding) {
1509 if (p->fout->frame.auxp == NULL ||
1510 p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2))
1511 csound->AuxAlloc(csound, sizeof(MYFLT) * CS_KSMPS * (N + 2),
1512 &p->fout->frame);
1513 p->fout->NB = p->fin->NB;
1514 p->fout->sliding = 1;
1515 }
1516 else
1517 if (p->fout->frame.auxp == NULL ||
1518 p->fout->frame.size < sizeof(float) * (N + 2))
1519 csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fout->frame);
1520 p->fout->N = N;
1521 p->fout->overlap = p->fin->overlap;
1522 p->fout->winsize = p->fin->winsize;
1523 p->fout->wintype = p->fin->wintype;
1524 p->fout->format = p->fin->format;
1525 p->fout->framecount = 1;
1526 p->lastframe = 0;
1527
1528 return OK;
1529 }
1530
pvsfilter(CSOUND * csound,PVSFILTER * p)1531 static int32_t pvsfilter(CSOUND *csound, PVSFILTER *p)
1532 {
1533 int32 i, N = p->fout->N;
1534 float g = (float) *p->gain;
1535 MYFLT dirgain, kdepth = *p->kdepth;
1536 float *fin = (float *) p->fin->frame.auxp;
1537 float *fout = (float *) p->fout->frame.auxp;
1538 float *fil = (float *) p->fil->frame.auxp;
1539
1540 if (UNLIKELY(fout == NULL)) goto err1;
1541 if (UNLIKELY(!fsigs_equal(p->fin, p->fil))) goto err2;
1542
1543 if (p->fin->sliding) {
1544 int32_t NB = p->fout->NB;
1545 uint32_t offset = p->h.insdshead->ksmps_offset;
1546 uint32_t n, nsmps = CS_KSMPS;
1547 CMPLX *fin, *fout, *fil;
1548 MYFLT g = *p->gain;
1549 kdepth = kdepth >= FL(0.0) ? (kdepth <= FL(1.0) ? kdepth*g : g) : FL(0.0);
1550 dirgain = (FL(1.0) - kdepth)*g;
1551 for (n=0; n<offset; n++) {
1552 fout = (CMPLX *)p->fout->frame.auxp + NB*n;
1553 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
1554 }
1555 for (n=offset; n<nsmps; n++) {
1556 fin = (CMPLX *)p->fin->frame.auxp + NB*n;
1557 fout = (CMPLX *)p->fout->frame.auxp + NB*n;
1558 fil = (CMPLX *)p->fil->frame.auxp + NB*n;
1559 if (IS_ASIG_ARG(p->kdepth)) {
1560 kdepth = p->kdepth[n] >= FL(0.0) ?
1561 (p->kdepth[n] <= FL(1.0) ? p->kdepth[n]*g : g) : FL(0.0);
1562 dirgain = (FL(1.0) - kdepth)*g;
1563 }
1564 for (i = 0; i < NB; i++) {
1565 fout[i].re = fin[i].re * (dirgain + fil[i].re * kdepth);
1566 fout[i].im = fin[i].im;
1567 }
1568 }
1569 return OK;
1570 }
1571 if (p->lastframe < p->fin->framecount) {
1572 kdepth = kdepth >= 0 ? (kdepth <= 1 ? kdepth : 1) : FL(0.0);
1573 dirgain = (1 - kdepth);
1574 for (i = 0; i < N + 2; i += 2) {
1575 fout[i] = (float) (fin[i] * (dirgain + fil[i] * kdepth))*g;
1576 fout[i + 1] = fin[i + 1];
1577 }
1578
1579 p->fout->framecount = p->lastframe = p->fin->framecount;
1580 }
1581 return OK;
1582 err1:
1583 return csound->PerfError(csound, &(p->h),
1584 Str("pvsfilter: not initialised"));
1585 err2:
1586 return csound->PerfError(csound, &(p->h),
1587 Str("pvsfilter: formats are different."));
1588 }
1589
1590 /* pvscale */
1591 typedef struct _pvscale {
1592 OPDS h;
1593 PVSDAT *fout;
1594 PVSDAT *fin;
1595 MYFLT *kscal;
1596 MYFLT *keepform;
1597 MYFLT *gain;
1598 MYFLT *coefs;
1599 AUXCH fenv, ceps, ftmp;
1600 void *fwdsetup, *invsetup;
1601 uint32 lastframe;
1602 } PVSSCALE;
1603
pvsscaleset(CSOUND * csound,PVSSCALE * p)1604 static int32_t pvsscaleset(CSOUND *csound, PVSSCALE *p)
1605 {
1606 int32 N = p->fin->N, tmp;
1607
1608 if (UNLIKELY(p->fin == p->fout))
1609 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
1610 p->fout->NB = p->fin->NB;
1611 p->fout->sliding = p->fin->sliding;
1612 if (p->fin->sliding) {
1613 if (p->fout->frame.auxp == NULL ||
1614 p->fout->frame.size < CS_KSMPS * sizeof(MYFLT) * (N + 2))
1615 csound->AuxAlloc(csound, CS_KSMPS * sizeof(MYFLT) * (N + 2),
1616 &p->fout->frame);
1617 }
1618 else
1619 {
1620 if (p->fout->frame.auxp == NULL ||
1621 p->fout->frame.size < sizeof(float) * (N + 2)) /* RWD MUST be 32bit */
1622 csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fout->frame);
1623 }
1624
1625 if (p->ftmp.auxp == NULL ||
1626 p->ftmp.size < sizeof(float) * (N+4))
1627 csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->ftmp);
1628
1629 p->fout->N = N;
1630 p->fout->overlap = p->fin->overlap;
1631 p->fout->winsize = p->fin->winsize;
1632 p->fout->wintype = p->fin->wintype;
1633 p->fout->format = p->fin->format;
1634 p->fout->framecount = 1;
1635 p->lastframe = 0;
1636 tmp = N + N%2;
1637 if (p->ceps.auxp == NULL ||
1638 p->ceps.size < sizeof(MYFLT) * (tmp+2))
1639 csound->AuxAlloc(csound, sizeof(MYFLT) * (tmp + 2), &p->ceps);
1640 memset(p->ceps.auxp, 0, sizeof(MYFLT)*(tmp+2));
1641 if (p->fenv.auxp == NULL ||
1642 p->fenv.size < sizeof(MYFLT) * (N+2))
1643 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv);
1644 memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2));
1645 p->fwdsetup = csound->RealFFT2Setup(csound, N/2, FFT_FWD);
1646 p->invsetup = csound->RealFFT2Setup(csound, N/2, FFT_INV);
1647 return OK;
1648 }
1649
1650 void csoundInverseComplexFFTnp2(CSOUND *csound, MYFLT *buf, int32_t FFTsize);
1651 void csoundComplexFFTnp2(CSOUND *csound, MYFLT *buf, int32_t FFTsize);
1652
pvsscale(CSOUND * csound,PVSSCALE * p)1653 static int32_t pvsscale(CSOUND *csound, PVSSCALE *p)
1654 {
1655 int32_t i, chan, N = p->fout->N;
1656 float max = 0.0f;
1657 MYFLT pscal = FABS(*p->kscal);
1658 int32_t keepform = (int32_t) *p->keepform;
1659 float g = (float) *p->gain;
1660 float *fin = (float *) p->fin->frame.auxp;
1661 float *fout = (float *) p->fout->frame.auxp;
1662 MYFLT *fenv = (MYFLT *) p->fenv.auxp;
1663 float *ftmp = (float *) p->ftmp.auxp;
1664 MYFLT *ceps = (MYFLT *) p->ceps.auxp;
1665 float sr = CS_ESR, binf;
1666 int32_t coefs = (int32_t) *p->coefs;
1667
1668 if (UNLIKELY(fout == NULL)) goto err1;
1669
1670 if (p->fout->sliding) {
1671 uint32_t offset = p->h.insdshead->ksmps_offset;
1672 uint32_t n, nsmps = CS_KSMPS;
1673 int32_t NB = p->fout->NB;
1674 MYFLT g = *p->gain;
1675 for (n=0; n<offset; n++) {
1676 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
1677 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
1678 }
1679 for (n=offset; n<nsmps; n++) {
1680 MYFLT max = FL(0.0);
1681 CMPLX *fin = (CMPLX *) p->fin->frame.auxp + n*NB;
1682 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
1683
1684 fout[0] = fin[0];
1685 fout[NB-1] = fin[NB-1];
1686 if (IS_ASIG_ARG(p->kscal)) {
1687 pscal = FABS(p->kscal[n]);
1688 }
1689 if (keepform)
1690 for (i = 1; i < NB-1; i++) {
1691 max = max < fin[i].re ? fin[i].re : max;
1692 }
1693
1694 for (i = 1; i < NB-1; i++) {
1695 if (keepform == 0 || keepform == 1 || !max)
1696 fout[i].re = fin[i].re;
1697 else
1698 fout[i].re = fin[i].re * (fin[i].re / max);
1699 fout[i].im = fin[i].im * pscal;
1700 /* Remove aliases */
1701 if (fout[i].im>=CS_ESR*0.5 ||
1702 fout[i].im<= -CS_ESR*0.5)
1703 fout[i].re=0.0;
1704 }
1705
1706 for (i = 1; i < NB; i++) {
1707 fout[i].re *= g;
1708 }
1709 }
1710 return OK;
1711 }
1712 if (p->lastframe < p->fin->framecount) {
1713 int32_t n;
1714 fout[0] = fin[0];
1715 fout[N] = fin[N];
1716 memcpy(ftmp,fin,sizeof(float)*(N+2));
1717
1718 for (i = 2, n=1; i < N; i += 2, n++) {
1719 fout[i] = 0.0f;
1720 fout[i + 1] = -1.0f;
1721 fenv[n] = 0.f;
1722 }
1723
1724 if (keepform) {
1725 int32_t cond = 1;
1726 int32_t j;
1727 for (i=j=0; i < N; i+=2, j++)
1728 fenv[j] = LOG(ftmp[i] > 0.0 ? ftmp[i] : 1e-20);
1729
1730
1731 if (keepform > 2) { /* experimental mode 3 */
1732 int32_t w = 5, w2 = w*2;
1733 for (i=0; i < w; i++) ceps[i] = fenv[i];
1734 for (i=w; i < N/2-w; i++) {
1735 ceps[i] = 0.0;
1736 for (j=-w; j < w; j++)
1737 ceps[i] += fenv[i+j];
1738 ceps[i] /= w2;
1739 }
1740 for (i=0; i<N/2; i++) {
1741 fenv[i] = EXP(ceps[i]);
1742 max = max < fenv[i] ? fenv[i] : max;
1743 }
1744 if (max)
1745 for (j=i=0; i<N; i+=2, j++) {
1746 fenv[j]/=max;
1747 binf = (j)*sr/N;
1748 if (fenv[j] && binf < pscal*sr/2 )
1749 ftmp[i] /= fenv[j];
1750 }
1751 }
1752 else { /* new modes 1 & 2 */
1753 int32_t tmp = N/2,j;
1754 tmp = tmp + tmp%2;
1755 if (coefs < 1) coefs = 80;
1756 while(cond) {
1757 cond = 0;
1758 for (i=0; i < N/2; i++) {
1759 ceps[i] = fenv[i];
1760 }
1761 if (!(N & (N - 1)))
1762 csound->RealFFT2(csound, p->fwdsetup, ceps);
1763 else
1764 csound->RealFFTnp2(csound, ceps, tmp);
1765 for (i=coefs; i < N/2; i++) ceps[i] = 0.0;
1766 if (!(N & (N - 1)))
1767 csound->RealFFT2(csound, p->invsetup, ceps);
1768 else
1769 csound->InverseRealFFTnp2(csound, ceps, tmp);
1770 for (i=j=0; i < N/2; i++, j+=2) {
1771 if (keepform > 1) {
1772 if (fenv[i] < ceps[i])
1773 fenv[i] = ceps[i];
1774 if ((LOG(ftmp[j]) - ceps[i]) > FL(0.23)) cond = 1;
1775 }
1776 else
1777 {
1778 fenv[i] = EXP(ceps[i]);
1779 max = max < fenv[i] ? fenv[i] : max;
1780 }
1781 }
1782 }
1783 if (keepform > 1)
1784 for (i=0; i<N/2; i++) {
1785 fenv[i] = EXP(ceps[i]);
1786 max = max < fenv[i] ? fenv[i] : max;
1787 }
1788
1789 if (max)
1790 for (i=j=2; i<N/2; i++, j+=2) {
1791 fenv[i]/=max;
1792 binf = (i)*sr/N;
1793 if (fenv[i] && binf < pscal*sr/2 )
1794 ftmp[j] /= fenv[i];
1795 }
1796 }
1797 }
1798 if(keepform) {
1799 for (i = 2, chan = 1; i < N; chan++, i += 2) {
1800 int32_t newchan;
1801 newchan = (int32_t) ((chan * pscal)+0.5) << 1;
1802 if (newchan < N && newchan > 0) {
1803 fout[newchan] = ftmp[i]*fenv[newchan>>1];
1804 fout[newchan + 1] = (float) (ftmp[i + 1] * pscal);
1805 }
1806 }
1807 } else {
1808 for (i = 2, chan = 1; i < N; chan++, i += 2) {
1809 int32_t newchan;
1810 newchan = (int32_t) ((chan * pscal)+0.5) << 1;
1811 if (newchan < N && newchan > 0) {
1812 fout[newchan] = ftmp[i];
1813 fout[newchan + 1] = (float) (ftmp[i + 1] * pscal);
1814 }
1815 }
1816 }
1817
1818 for (i = 2; i < N; i += 2) {
1819 if (isnan(fout[i])) fout[i] = 0.0f;
1820 if (fout[i + 1] == -1.0f) {
1821 fout[i] = 0.f;
1822 }
1823 else
1824 fout[i] *= g;
1825 }
1826 p->fout->framecount = p->lastframe = p->fin->framecount;
1827 }
1828 return OK;
1829 err1:
1830 return csound->PerfError(csound, &(p->h),
1831 Str("pvscale: not initialised"));
1832 }
1833
1834 /* pvshift */
1835
1836 typedef struct _pvshift {
1837 OPDS h;
1838 PVSDAT *fout;
1839 PVSDAT *fin;
1840 MYFLT *kshift;
1841 MYFLT *lowest;
1842 MYFLT *keepform;
1843 MYFLT *gain;
1844 MYFLT *coefs;
1845 AUXCH fenv, ceps, ftmp;
1846 uint32 lastframe;
1847 } PVSSHIFT;
1848
pvsshiftset(CSOUND * csound,PVSSHIFT * p)1849 static int32_t pvsshiftset(CSOUND *csound, PVSSHIFT *p)
1850 {
1851 int32_t N = p->fin->N;
1852
1853 if (UNLIKELY(p->fin == p->fout))
1854 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
1855 if (p->fin->sliding) {
1856 if (p->fout->frame.auxp==NULL ||
1857 CS_KSMPS*(N+2)*sizeof(MYFLT) > (uint32_t)p->fout->frame.size)
1858 csound->AuxAlloc(csound, CS_KSMPS*(N+2)*sizeof(MYFLT),&p->fout->frame);
1859 else memset(p->fout->frame.auxp, 0, CS_KSMPS*(N+2)*sizeof(MYFLT));
1860 }
1861 else
1862 {
1863 if (p->fout->frame.auxp == NULL ||
1864 p->fout->frame.size < sizeof(float) * (N + 2)) /* RWD MUST be 32bit */
1865 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
1866 else memset(p->fout->frame.auxp, 0, (N+2)*sizeof(float));
1867 }
1868 p->fout->N = N;
1869 p->fout->overlap = p->fin->overlap;
1870 p->fout->winsize = p->fin->winsize;
1871 p->fout->wintype = p->fin->wintype;
1872 p->fout->format = p->fin->format;
1873 p->fout->framecount = 1;
1874 p->lastframe = 0;
1875 p->fout->sliding = p->fin->sliding;
1876 p->fout->NB = p->fin->NB;
1877
1878 if (p->ceps.auxp == NULL ||
1879 p->ceps.size < sizeof(MYFLT) * (N+2))
1880 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps);
1881 else
1882 memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2));
1883 if (p->fenv.auxp == NULL ||
1884 p->fenv.size < sizeof(MYFLT) * (N+2))
1885 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv);
1886 else
1887 memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2));
1888 if (p->ftmp.auxp == NULL ||
1889 p->ftmp.size < sizeof(float) * (N+4))
1890 csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->ftmp);
1891
1892 return OK;
1893 }
1894
pvsshift(CSOUND * csound,PVSSHIFT * p)1895 static int32_t pvsshift(CSOUND *csound, PVSSHIFT *p)
1896 {
1897 int32_t i, chan, newchan, N = p->fout->N;
1898 MYFLT pshift = (MYFLT) *p->kshift;
1899 int32_t lowest = abs((int32_t) (*p->lowest * N * csound->onedsr));
1900 float max = 0.0f;
1901 int32_t cshift = (int32_t) (pshift * N * csound->onedsr);
1902 int32_t keepform = (int32_t) *p->keepform;
1903 float g = (float) *p->gain;
1904 float *fin = (float *) p->fin->frame.auxp;
1905 float *fout = (float *) p->fout->frame.auxp;
1906 float *ftmp = (float *) p->ftmp.auxp;
1907 MYFLT *fenv = (MYFLT *) p->fenv.auxp;
1908 MYFLT *ceps = (MYFLT *) p->ceps.auxp;
1909 float sr = CS_ESR, binf;
1910 int32_t coefs = (int32_t) *p->coefs;
1911
1912 if (UNLIKELY(fout == NULL)) goto err1;
1913 if (p->fin->sliding) {
1914 uint32_t offset = p->h.insdshead->ksmps_offset;
1915 uint32_t n, nsmps = CS_KSMPS;
1916 int32_t NB = p->fout->NB;
1917 MYFLT g = *p->gain;
1918 lowest = lowest ? (lowest > NB ? NB : lowest) : 1;
1919
1920 for (n=0; n<offset; n++) {
1921 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
1922 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
1923 }
1924 for (n=offset; n<nsmps; n++) { MYFLT max = FL(0.0);
1925 CMPLX *fin = (CMPLX *) p->fin->frame.auxp + n*NB;
1926 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
1927 fout[0] = fin[0];
1928 fout[NB-1] = fin[NB-1];
1929 if (IS_ASIG_ARG(p->kshift)) {
1930 pshift = (p->kshift)[n];
1931 }
1932 for (i = 1; i < NB-1; i++) {
1933 if (keepform && (max < fin[i].re)) max = fin[i].re;
1934 if (i < lowest) {
1935 fout[i] = fin[i];
1936 }
1937 }
1938 for (i = lowest; i < NB; i++) {
1939 if (keepform == 0 || keepform == 1 || !max)
1940 fout[i].re = fin[i].re;
1941 else
1942 fout[i].re = fin[i].re * (fin[i].re / max);
1943 fout[i].im = (fin[i].im + pshift);
1944 /* Remove aliases */
1945 if (fout[i].im>=CS_ESR*0.5 ||
1946 fout[i].im<= -CS_ESR*0.5)
1947 fout[i].re = 0.0;
1948 }
1949 if (g!=1.0f)
1950 for (i = lowest; i < NB; i++) {
1951 fout[i].re *= g;
1952 }
1953 }
1954 return OK;
1955 }
1956 if (p->lastframe < p->fin->framecount) {
1957 int32_t j;
1958 lowest = lowest ? (lowest > N / 2 ? N / 2 : lowest << 1) : 2;
1959
1960 fout[0] = fin[0];
1961 fout[N] = fin[N];
1962 memcpy(ftmp, fin, sizeof(float)*(N+2));
1963
1964 for (j = i = 2; i < N; i += 2, j++) {
1965 fenv[j] = 0.0;
1966 if (i < lowest) {
1967 fout[i] = fin[i];
1968 fout[i + 1] = fin[i + 1];
1969 }
1970 else {
1971 fout[i] = 0.0f;
1972 fout[i + 1] = -1.0f;
1973 }
1974 }
1975 if (keepform) { /* new modes 1 & 2 */
1976 int32_t cond = 1;
1977 int32_t tmp = N/2;
1978 tmp = tmp + tmp%2;
1979 for (i=j=0; i < N; i+=2, j++)
1980 fenv[j] = LOG(fin[i] > FL(0.0) ? fin[i] : FL(1e-20));
1981 if (coefs < 1) coefs = 80;
1982 while(cond) {
1983 cond = 0;
1984 for (j=i=0; i < N; i+=2, j++) {
1985 ceps[i] = fenv[j];
1986 ceps[i+1] = FL(0.0);
1987 }
1988 if (!(N & (N - 1)))
1989 csound->InverseComplexFFT(csound, ceps, N/2);
1990 else
1991 csoundInverseComplexFFTnp2(csound, ceps, tmp);
1992 for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0;
1993 if (!(N & (N - 1)))
1994 csound->ComplexFFT(csound, ceps, N/2);
1995 else
1996 csoundComplexFFTnp2(csound, ceps, tmp);
1997 for (i=j=0; i < N; i+=2, j++) {
1998 if (keepform > 1) {
1999 if (fenv[j] < ceps[i])
2000 fenv[j] = ceps[i];
2001 if ((LOG(fin[i]) - ceps[i]) > 0.23) cond = 1;
2002 }
2003 else
2004 {
2005 fenv[j] = EXP(ceps[i]);
2006 max = max < fenv[j] ? fenv[j] : max;
2007 }
2008 }
2009 }
2010 if (keepform > 1)
2011 for (i=0; i<N/2; i++) {
2012 fenv[i] = EXP(fenv[i]);
2013 max = max < fenv[i] ? fenv[i] : max;
2014 }
2015 if (max)
2016 for (j=i=lowest; i<N; i+=2, j++) {
2017 fenv[j]/=max;
2018 binf = (j)*sr/N;
2019 if (fenv[j] && binf < sr/2+pshift )
2020 ftmp[i] /= fenv[j];
2021 }
2022 }
2023
2024 if(keepform) {
2025 for (i = lowest, chan = lowest >> 1; i < N; chan++, i += 2) {
2026 newchan = (chan + cshift) << 1;
2027 if (newchan < N && newchan > lowest) {
2028 fout[newchan] = ftmp[i] * fenv[newchan>>1];
2029 fout[newchan + 1] = (float) (ftmp[i + 1] + pshift);
2030 }
2031 }
2032 } else {
2033 for (i = lowest, chan = lowest >> 1; i < N; chan++, i += 2) {
2034 newchan = (chan + cshift) << 1;
2035 if (newchan < N && newchan > lowest) {
2036 fout[newchan] = ftmp[i];
2037 fout[newchan + 1] = (float) (ftmp[i + 1] + pshift);
2038 }
2039 }
2040
2041 }
2042
2043 for (i = lowest; i < N; i += 2) {
2044 if (fout[i + 1] == -1.0f)
2045 fout[i] = 0.0f;
2046 else
2047 fout[i] *= g;
2048 }
2049
2050 p->fout->framecount = p->lastframe = p->fin->framecount;
2051 }
2052 return OK;
2053 err1:
2054 return csound->PerfError(csound, &(p->h),
2055 Str("pvshift: not initialised"));
2056 }
2057
2058 /* pvswarp */
2059 typedef struct _pvswarp {
2060 OPDS h;
2061 PVSDAT *fout;
2062 PVSDAT *fin;
2063 MYFLT *kscal;
2064 MYFLT *kshift;
2065 MYFLT *klowest;
2066 MYFLT *keepform;
2067 MYFLT *gain;
2068 MYFLT *coefs;
2069 AUXCH fenv, ceps;
2070 uint32 lastframe;
2071 } PVSWARP;
2072
pvswarpset(CSOUND * csound,PVSWARP * p)2073 static int32_t pvswarpset(CSOUND *csound, PVSWARP *p)
2074 {
2075 int32 N = p->fin->N;
2076
2077 if (UNLIKELY(p->fin == p->fout))
2078 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
2079 {
2080 if (p->fout->frame.auxp == NULL ||
2081 p->fout->frame.size < sizeof(float) * (N + 2)) /* RWD MUST be 32bit */
2082 csound->AuxAlloc(csound, sizeof(float) * (N + 2), &p->fout->frame);
2083 }
2084 p->fout->N = N;
2085 p->fout->overlap = p->fin->overlap;
2086 p->fout->winsize = p->fin->winsize;
2087 p->fout->wintype = p->fin->wintype;
2088 p->fout->format = p->fin->format;
2089 p->fout->framecount = 1;
2090 p->lastframe = 0;
2091
2092 if (p->ceps.auxp == NULL ||
2093 p->ceps.size < sizeof(MYFLT) * (N+2))
2094 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps);
2095 else
2096 memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2));
2097 if (p->fenv.auxp == NULL ||
2098 p->fenv.size < sizeof(MYFLT) * (N+2))
2099 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv);
2100 else
2101 memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2));
2102
2103 return OK;
2104 }
2105
2106
2107
2108
pvswarp(CSOUND * csound,PVSWARP * p)2109 static int32_t pvswarp(CSOUND *csound, PVSWARP *p)
2110 {
2111 int32_t i,j, chan, N = p->fout->N;
2112 float max = 0.0f;
2113 MYFLT pscal = FABS(*p->kscal);
2114 MYFLT pshift = (*p->kshift);
2115 int32_t cshift = (int32_t) (pshift * N * csound->onedsr);
2116 int32_t keepform = (int32_t) *p->keepform;
2117 float g = (float) *p->gain;
2118 float *fin = (float *) p->fin->frame.auxp;
2119 float *fout = (float *) p->fout->frame.auxp;
2120 MYFLT *fenv = (MYFLT *) p->fenv.auxp;
2121 MYFLT *ceps = (MYFLT *) p->ceps.auxp;
2122 float sr = CS_ESR, binf;
2123 int32_t lowest = abs((int32_t) (*p->klowest * N * csound->onedsr));;
2124 int32_t coefs = (int32_t) *p->coefs;
2125
2126 lowest = lowest ? (lowest > N / 2 ? N / 2 : lowest << 1) : 2;
2127
2128 if (UNLIKELY(fout == NULL)) goto err1;
2129
2130 if (p->lastframe < p->fin->framecount) {
2131 int32_t n;
2132 fout[0] = fin[0];
2133 fout[N] = fin[N];
2134
2135 for (i = 2, n=1; i < N; i += 2, n++) {
2136 fout[i] = 0.0f;
2137 fout[i + 1] = -1.0f;
2138 fenv[n] = 0.f;
2139 }
2140
2141 {
2142 int32_t cond = 1;
2143 for (j=i=0; i < N; i+=2, j++) {
2144 fenv[j] = LOG(fin[i] > 0.0 ? fin[i] : 1e-20);
2145 }
2146 if (keepform > 2) { /* experimental mode 3 */
2147 int32_t w = 5;
2148 for (i=0; i < w; i++) ceps[i] = fenv[i];
2149 for (i=w; i < N/2-w; i++) {
2150 ceps[i] = 0.0;
2151 for (j=-w; j < w; j++)
2152 ceps[i] += fenv[i+j];
2153 ceps[i] /= 2*w;
2154 }
2155 for (i=0; i<N/2; i++) {
2156 fenv[i] = EXP(ceps[i]);
2157 max = max < fenv[i] ? fenv[i] : max;
2158 }
2159 if (max)
2160 for (j=i=lowest; i<N; i+=2, j++) {
2161 fenv[j]/=max;
2162 binf = (j)*sr/N;
2163 if (fenv[j] && binf < pscal*sr/2+pshift )
2164 fin[i] /= fenv[j];
2165 }
2166 }
2167 else { /* new modes 1 & 2 */
2168 int32_t tmp = N/2;
2169 tmp = tmp + tmp%2;
2170 if (coefs < 1) coefs = 80;
2171 while(cond) {
2172 cond = 0;
2173 for (j=i=0; i < N; i+=2, j++) {
2174 ceps[i] = fenv[j];
2175 ceps[i+1] = 0.0;
2176 }
2177 if (!(N & (N - 1)))
2178 csound->InverseComplexFFT(csound, ceps, N/2);
2179 else
2180 csoundInverseComplexFFTnp2(csound, ceps, tmp);
2181 for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0;
2182 if (!(N & (N - 1)))
2183 csound->ComplexFFT(csound, ceps, N/2);
2184 else
2185 csoundComplexFFTnp2(csound, ceps, tmp);
2186 for (j=i=0; i < N; i+=2, j++) {
2187 if (keepform > 1) {
2188 if (fenv[j] < ceps[i])
2189 fenv[j] = ceps[i];
2190 if ((LOG(fin[i]) - ceps[i]) > 0.23) cond = 1;
2191 }
2192 else
2193 {
2194 fenv[j] = EXP(ceps[i]);
2195 max = max < fenv[j] ? fenv[j] : max;
2196 }
2197 }
2198 }
2199 if (keepform > 1)
2200 for (j=i=0; i<N; i+=2, j++) {
2201 fenv[j] = EXP(ceps[i]);
2202 max = max < fenv[j] ? fenv[j] : max;
2203 }
2204 if (max)
2205 for (j=i=lowest; i<N; i+=2, j++) {
2206 fenv[j]/=max;
2207 binf = (i/2)*sr/N;
2208 if (fenv[j] && binf < pscal*sr/2+pshift )
2209 fin[i] /= fenv[j];
2210 }
2211 }
2212 }
2213 for (i = j = 2, chan = 1; i < N; chan++, i += 2, j++) {
2214 int32_t newchan;
2215 newchan = (int32_t) ((chan * pscal + cshift)+0.5) << 1;
2216 if (i >= lowest) {
2217 if (newchan < N && newchan > 0)
2218 fout[newchan] = fin[newchan]*fenv[j];
2219 } else fout[i] = fin[i];
2220 fout[i + 1] = fin[i + 1];
2221 }
2222
2223 for (i = j= lowest; i < N; i += 2, j++) {
2224 if (isnan(fout[i])) fout[i] = 0.0f;
2225 else fout[i] *= g;
2226 binf = (j)*sr/N;
2227 if (fenv[j] && binf < pscal*sr/2+pshift )
2228 fin[i] *= fenv[i/2];
2229 }
2230
2231 p->fout->framecount = p->lastframe = p->fin->framecount;
2232 }
2233 return OK;
2234 err1:
2235 return csound->PerfError(csound, &(p->h),
2236 Str("pvswarp: not initialised"));
2237 }
2238
2239
2240
2241
2242 /* pvsblur */
2243
pvsblurset(CSOUND * csound,PVSBLUR * p)2244 static int32_t pvsblurset(CSOUND *csound, PVSBLUR *p)
2245 {
2246 float *delay;
2247 int32 N = p->fin->N, i, j;
2248 int32_t olap = p->fin->overlap;
2249 int32_t delayframes, framesize = N + 2;
2250 if (UNLIKELY(p->fin == p->fout))
2251 csound->Warning(csound, Str("Unsafe to have same fsig as in and out"));
2252 if (p->fin->sliding) {
2253 csound->InitError(csound, Str("pvsblur does not work sliding yet"));
2254 delayframes = (int32_t) (FL(0.5) + *p->maxdel * CS_ESR);
2255 if (p->fout->frame.auxp == NULL ||
2256 p->fout->frame.size < sizeof(MYFLT) * CS_KSMPS * (N + 2))
2257 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS,
2258 &p->fout->frame);
2259
2260 if (p->delframes.auxp == NULL ||
2261 p->delframes.size < (N + 2) * sizeof(MYFLT) * CS_KSMPS * delayframes)
2262 csound->AuxAlloc(csound,
2263 (N + 2) * sizeof(MYFLT) * CS_KSMPS * delayframes,
2264 &p->delframes);
2265 }
2266 else
2267 {
2268 p->frpsec = CS_ESR / olap;
2269
2270 delayframes = (int32_t) (*p->maxdel * p->frpsec);
2271
2272 if (p->fout->frame.auxp == NULL ||
2273 p->fout->frame.size < sizeof(float) * (N + 2))
2274 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
2275
2276 if (p->delframes.auxp == NULL ||
2277 p->delframes.size < (N + 2) * sizeof(float) * CS_KSMPS * delayframes)
2278 csound->AuxAlloc(csound, (N + 2) * sizeof(float) * delayframes,
2279 &p->delframes);
2280 }
2281 delay = (float *) p->delframes.auxp;
2282
2283 for (j = 0; j < framesize * delayframes; j += framesize)
2284 for (i = 0; i < N + 2; i += 2) {
2285 delay[i + j] = 0.0f;
2286 delay[i + j + 1] = i * CS_ESR / N;
2287 }
2288
2289 p->fout->N = N;
2290 p->fout->overlap = olap;
2291 p->fout->winsize = p->fin->winsize;
2292 p->fout->wintype = p->fin->wintype;
2293 p->fout->format = p->fin->format;
2294 p->fout->framecount = 1;
2295 p->lastframe = 0;
2296 p->count = 0;
2297 p->fout->sliding = p->fin->sliding;
2298 p->fout->NB = p->fin->NB;
2299 return OK;
2300 }
2301
pvsblur(CSOUND * csound,PVSBLUR * p)2302 static int32_t pvsblur(CSOUND *csound, PVSBLUR *p)
2303 {
2304 int32 j, i, N = p->fout->N, first, framesize = N + 2;
2305 int32 countr = p->count;
2306 double amp = 0.0, freq = 0.0;
2307 int32_t delayframes = (int32_t) (*p->kdel * p->frpsec);
2308 int32_t kdel = delayframes * framesize;
2309 int32_t mdel = (int32_t) (*p->maxdel * p->frpsec) * framesize;
2310 float *fin = (float *) p->fin->frame.auxp;
2311 float *fout = (float *) p->fout->frame.auxp;
2312 float *delay = (float *) p->delframes.auxp;
2313
2314 if (UNLIKELY(fout == NULL || delay == NULL)) goto err1;
2315
2316 if (p->fin->sliding) {
2317 uint32_t offset = p->h.insdshead->ksmps_offset;
2318 uint32_t n, nsmps = CS_KSMPS;
2319 int32_t NB = p->fin->NB;
2320 kdel = kdel >= 0 ? (kdel < mdel ? kdel : mdel - framesize) : 0;
2321 for (n=0; n<offset; n++) {
2322 CMPLX *fout = (CMPLX *) p->fout->frame.auxp +NB*n;
2323 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
2324 }
2325 for (n=offset; n<nsmps; n++) {
2326 CMPLX *fin = (CMPLX *) p->fin->frame.auxp +NB*n;
2327 CMPLX *fout = (CMPLX *) p->fout->frame.auxp +NB*n;
2328 CMPLX *delay = (CMPLX *) p->delframes.auxp +NB*n;
2329
2330 for (i = 0; i < NB; i++) {
2331 delay[countr + i] = fin[i];
2332 if (kdel) {
2333 if ((first = countr - kdel) < 0)
2334 first += mdel;
2335
2336 for (j = first; j != countr; j = (j + framesize) % mdel) {
2337 amp += delay[j + i].re;
2338 freq += delay[j + i].im;
2339 }
2340
2341 fout[i].re = (MYFLT) (amp / delayframes);
2342 fout[i].im = (MYFLT) (freq / delayframes);
2343 amp = freq = FL(0.0);
2344 }
2345 else {
2346 fout[i] = fin[i];
2347 }
2348 }
2349 }
2350 countr += (N + 2);
2351 p->count = countr < mdel ? countr : 0;
2352 return OK;
2353 }
2354 if (p->lastframe < p->fin->framecount) {
2355
2356 kdel = kdel >= 0 ? (kdel < mdel ? kdel : mdel - framesize) : 0;
2357
2358 for (i = 0; i < N + 2; i += 2) {
2359
2360 delay[countr + i] = fin[i];
2361 delay[countr + i + 1] = fin[i + 1];
2362
2363 if (kdel) {
2364
2365 if ((first = countr - kdel) < 0)
2366 first += mdel;
2367
2368 for (j = first; j != countr; j = (j + framesize) % mdel) {
2369 amp += delay[j + i];
2370 freq += delay[j + i + 1];
2371 }
2372
2373 fout[i] = (float) (amp / delayframes);
2374 fout[i + 1] = (float) (freq / delayframes);
2375 amp = freq = 0.;
2376 }
2377 else {
2378 fout[i] = fin[i];
2379 fout[i + 1] = fin[i + 1];
2380 }
2381 }
2382
2383 p->fout->framecount = p->lastframe = p->fin->framecount;
2384 countr += (N + 2);
2385 p->count = countr < mdel ? countr : 0;
2386 }
2387
2388 return OK;
2389 err1:
2390 return csound->PerfError(csound, &(p->h),
2391 Str("pvsblur: not initialised"));
2392 }
2393
2394 /* pvstencil */
2395
pvstencilset(CSOUND * csound,PVSTENCIL * p)2396 static int32_t pvstencilset(CSOUND *csound, PVSTENCIL *p)
2397 {
2398 int32 N = p->fin->N;
2399 uint32_t i;
2400 int32 chans = N / 2 + 1;
2401 MYFLT *ftable;
2402
2403 p->fout->N = N;
2404 p->fout->overlap = p->fin->overlap;
2405 p->fout->winsize = p->fin->winsize;
2406 p->fout->wintype = p->fin->wintype;
2407 p->fout->format = p->fin->format;
2408 p->fout->framecount = 1;
2409 p->lastframe = 0;
2410
2411 p->fout->NB = chans;
2412 if (p->fin->sliding) {
2413 if (p->fout->frame.auxp == NULL ||
2414 p->fout->frame.size < sizeof(MYFLT) * (N + 2) * CS_KSMPS)
2415 csound->AuxAlloc(csound, (N + 2) * sizeof(MYFLT) * CS_KSMPS,
2416 &p->fout->frame);
2417 p->fout->sliding = 1;
2418 }
2419 else
2420 {
2421 if (p->fout->frame.auxp == NULL ||
2422 p->fout->frame.size < sizeof(float) * (N + 2))
2423 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
2424
2425 if (UNLIKELY(!((p->fout->format == PVS_AMP_FREQ) ||
2426 (p->fout->format == PVS_AMP_PHASE))))
2427 return csound->InitError(csound, Str("pvstencil: signal format "
2428 "must be amp-phase or amp-freq."));
2429 }
2430 p->func = csound->FTnp2Finde(csound, p->ifn);
2431 if (p->func == NULL)
2432 return OK;
2433
2434 if (UNLIKELY(p->func->flen + 1 < (uint32_t)chans))
2435 return csound->InitError(csound, Str("pvstencil: ftable needs to equal "
2436 "the number of bins"));
2437
2438 ftable = p->func->ftable;
2439 for (i = 0; i < p->func->flen + 1; i++)
2440 if (ftable[i] < FL(0.0))
2441 ftable[i] = FL(0.0);
2442
2443 return OK;
2444 }
2445
pvstencil(CSOUND * csound,PVSTENCIL * p)2446 static int32_t pvstencil(CSOUND *csound, PVSTENCIL *p)
2447 {
2448 MYFLT *ftable;
2449 if (p->fin->sliding) {
2450 MYFLT g = FABS(*p->kgain);
2451 MYFLT masklevel = FABS(*p->klevel);
2452 int32_t NB = p->fin->NB, i;
2453 uint32_t offset = p->h.insdshead->ksmps_offset;
2454 uint32_t early = p->h.insdshead->ksmps_no_end;
2455 uint32_t n, nsmps = CS_KSMPS;
2456 p->fout->NB = NB;
2457 p->fout->N = p->fin->N;
2458 p->fout->format = p->fin->format;
2459 p->fout->wintype = p->fin->wintype;
2460 ftable = p->func->ftable;
2461 for (n=0; n<offset; n++) {
2462 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
2463 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
2464 }
2465 for (n=nsmps-early; n<nsmps; n++) {
2466 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
2467 for (i = 0; i < NB; i++) fout[i].re = fout[i].im = FL(0.0);
2468 }
2469 nsmps -= early;
2470 for (n=offset; n<nsmps; n++) {
2471 CMPLX *fout = (CMPLX *) p->fout->frame.auxp + n*NB;
2472 CMPLX *fin = (CMPLX *) p->fin->frame.auxp + n*NB;
2473 for (i = 0; i < NB; i++) {
2474 if (fin[i].re > ftable[i] * masklevel)
2475 fout[i].re = fin[i].re; /* Just copy */
2476 else {
2477 fout[i].re = fin[i].re * g; /* or apply gain */
2478 }
2479 fout[i].im = fin[i].im * g;
2480 }
2481 }
2482 }
2483 else
2484 {
2485 int32 framesize, i, j;
2486 int32_t test;
2487 float *fout, *fin;
2488 float g = fabsf((float)*p->kgain);
2489 float masklevel = fabsf((float)*p->klevel);
2490
2491 fout = (float *) p->fout->frame.auxp;
2492 fin = (float *) p->fin->frame.auxp;
2493 ftable = p->func->ftable;
2494
2495 framesize = p->fin->N + 2;
2496
2497 if (UNLIKELY(fout == NULL)) goto err1;
2498
2499 if (p->lastframe < p->fin->framecount) {
2500
2501 for (i = 0, j = 0; i < framesize; i += 2, j++) {
2502 test = fin[i] > ftable[j] * masklevel;
2503 if (test)
2504 fout[i] = fin[i];
2505 else
2506 fout[i] = fin[i] * g;
2507
2508 fout[i + 1] = fin[i + 1];
2509 }
2510 p->fout->framecount = p->lastframe = p->fin->framecount;
2511 }
2512 }
2513 return OK;
2514 err1:
2515 return csound->PerfError(csound, &(p->h),
2516 Str("pvstencil: not initialised"));
2517 }
2518
fsigs_equal(const PVSDAT * f1,const PVSDAT * f2)2519 static int32_t fsigs_equal(const PVSDAT *f1, const PVSDAT *f2)
2520 {
2521 if (
2522 (f1->sliding == f2->sliding) &&
2523 (f1->overlap == f2->overlap) &&
2524 (f1->winsize == f2->winsize) &&
2525 (f1->wintype == f2->wintype) && /* harsh, maybe... */
2526 (f1->N == f2->N) &&
2527 (f1->format == f2->format))
2528
2529 return 1;
2530 return 0;
2531 }
2532
2533
2534 typedef struct _pvsenvw {
2535 OPDS h;
2536 MYFLT *kflag;
2537 PVSDAT *fin;
2538 MYFLT *ftab;
2539 MYFLT *keepform;
2540 MYFLT *gain;
2541 MYFLT *coefs;
2542 AUXCH fenv, ceps;
2543 uint32 lastframe;
2544 } PVSENVW;
2545
pvsenvwset(CSOUND * csound,PVSENVW * p)2546 static int32_t pvsenvwset(CSOUND *csound, PVSENVW *p)
2547 {
2548 int32 N = p->fin->N;
2549
2550
2551 p->lastframe = 0;
2552
2553 if (p->ceps.auxp == NULL ||
2554 p->ceps.size < sizeof(MYFLT) * (N+2))
2555 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->ceps);
2556 else
2557 memset(p->ceps.auxp, 0, sizeof(MYFLT)*(N+2));
2558 if (p->fenv.auxp == NULL ||
2559 p->fenv.size < sizeof(MYFLT) * (N+2))
2560 csound->AuxAlloc(csound, sizeof(MYFLT) * (N + 2), &p->fenv);
2561 else
2562 memset(p->fenv.auxp, 0, sizeof(MYFLT)*(N+2));
2563
2564 return OK;
2565 }
2566
pvsenvw(CSOUND * csound,PVSENVW * p)2567 static int32_t pvsenvw(CSOUND *csound, PVSENVW *p)
2568 {
2569 int32_t i,j, N = p->fin->N;
2570 float max = 0.0f;
2571 int32_t keepform = (int32_t) *p->keepform;
2572 float g = (float) *p->gain;
2573 float *fin = (float *) p->fin->frame.auxp;
2574 MYFLT *fenv = (MYFLT *) p->fenv.auxp;
2575 MYFLT *ceps = (MYFLT *) p->ceps.auxp;
2576 int32_t coefs = (int32_t) *p->coefs;
2577 FUNC *ft = csound->FTnp2Find(csound, p->ftab);
2578 int32_t size;
2579 MYFLT *ftab;
2580
2581 if (ft == NULL) {
2582 csound->PerfError(csound, &(p->h),
2583 Str("could not find table number %d\n"), (int32_t) *p->ftab);
2584 return NOTOK;
2585 }
2586 size = ft->flen;
2587 ftab = ft->ftable;
2588
2589 *p->kflag = 0.0;
2590 if (p->lastframe < p->fin->framecount) {
2591 {
2592 int32_t cond = 1;
2593 for (i=j=0; i < N; i+=2, j++) {
2594 fenv[j] = LOG(fin[i] > 0.0 ? fin[i] : 1e-20);
2595 }
2596 if (keepform > 2) { /* experimental mode 3 */
2597 int32_t j;
2598 int32_t w = 5;
2599 for (i=0; i < w; i++) ceps[i] = fenv[i];
2600 for (i=w; i < N/2-w; i++) {
2601 ceps[i] = 0.0;
2602 for (j=-w; j < w; j++)
2603 ceps[i] += fenv[i+j];
2604 ceps[i] /= 2*w;
2605 }
2606 for (i=0; i<N/2; i++) {
2607 fenv[i] = EXP(ceps[i]);
2608 max = max < fenv[i] ? fenv[i] : max;
2609 }
2610 /* if (max)
2611 for (i=0; i<N; i+=2) {
2612 fenv[i/2]/=max;
2613 }*/
2614 }
2615 else { /* new modes 1 & 2 */
2616 int32_t tmp = N/2;
2617 tmp = tmp + tmp%2;
2618 if (coefs < 1) coefs = 80;
2619 while(cond) {
2620 cond = 0;
2621 for (j=i=0; i < N; i+=2, j++) {
2622 ceps[i] = fenv[j];
2623 ceps[i+1] = 0.0;
2624 }
2625 if (!(N & (N - 1)))
2626 csound->InverseComplexFFT(csound, ceps, N/2);
2627 else
2628 csoundInverseComplexFFTnp2(csound, ceps, tmp);
2629 for (i=coefs; i < N-coefs; i++) ceps[i] = 0.0;
2630 if (!(N & (N - 1)))
2631 csound->ComplexFFT(csound, ceps, N/2);
2632 else
2633 csoundComplexFFTnp2(csound, ceps, tmp);
2634 for (i=j=0; i < N; i+=2, j++) {
2635 if (keepform > 1) {
2636 if (fenv[j] < ceps[i])
2637 fenv[j] = ceps[i];
2638 if ((LOG(fin[i]) - ceps[i]) > 0.23) cond = 1;
2639 }
2640 else
2641 {
2642 fenv[j] = EXP(ceps[i]);
2643 max = max < fenv[j] ? fenv[j] : max;
2644 }
2645 }
2646 }
2647 if (keepform > 1)
2648 for (j=i=0; i<N; i+=2, j++) {
2649 fenv[j] = EXP(ceps[i]);
2650 max = max < fenv[j] ? fenv[j] : max;
2651 }
2652 /* if (max)
2653 for (i=0; i<N/2; i++) fenv[i]/=max; */
2654 }
2655 }
2656 for (i = 0; i < N/2 || i < size; i++) ftab[i] = fenv[i]*g;
2657 p->lastframe = p->fin->framecount;
2658 *p->kflag = FL(1.0);
2659 }
2660 return OK;
2661
2662 }
2663
2664 typedef struct pvs2tab_t {
2665 OPDS h;
2666 MYFLT *framecount;
2667 ARRAYDAT *ans;
2668 PVSDAT *fsig;
2669 } PVS2TAB_T;
2670
pvs2tab_init(CSOUND * csound,PVS2TAB_T * p)2671 int32_t pvs2tab_init(CSOUND *csound, PVS2TAB_T *p)
2672 {
2673 if (UNLIKELY(!((p->fsig->format == PVS_AMP_FREQ) ||
2674 (p->fsig->format == PVS_AMP_PHASE))))
2675 return csound->InitError(csound, Str("pvs2tab: signal format "
2676 "must be amp-phase or amp-freq."));
2677 if (LIKELY(p->ans->data)) return OK;
2678 return csound->InitError(csound, Str("array-variable not initialised"));
2679 }
2680
pvs2tab(CSOUND * csound,PVS2TAB_T * p)2681 int32_t pvs2tab(CSOUND *csound, PVS2TAB_T *p){
2682 IGN(csound);
2683 int32_t size = p->ans->sizes[0], N = p->fsig->N, i;
2684 float *fsig = (float *) p->fsig->frame.auxp;
2685 for(i = 0; i < size && i < N+2; i++)
2686 p->ans->data[i] = (MYFLT) fsig[i];
2687 *p->framecount = (MYFLT) p->fsig->framecount;
2688 return OK;
2689 }
2690
2691 typedef struct pvs2tabsplit_t {
2692 OPDS h;
2693 MYFLT *framecount;
2694 ARRAYDAT *mags;
2695 ARRAYDAT *freqs;
2696 PVSDAT *fsig;
2697 } PVS2TABSPLIT_T;
2698
pvs2tabsplit_init(CSOUND * csound,PVS2TABSPLIT_T * p)2699 int32_t pvs2tabsplit_init(CSOUND *csound, PVS2TABSPLIT_T *p)
2700 {
2701 if (UNLIKELY(!((p->fsig->format == PVS_AMP_FREQ) ||
2702 (p->fsig->format == PVS_AMP_PHASE))))
2703 return csound->InitError(csound, Str("pvs2tab: signal format "
2704 "must be amp-phase or amp-freq."));
2705
2706 if (LIKELY(p->mags->data) && LIKELY(p->freqs->data))
2707 return OK;
2708
2709 return csound->InitError(csound, Str("array-variable not initialised"));
2710 }
2711
pvs2tabsplit(CSOUND * csound,PVS2TABSPLIT_T * p)2712 int32_t pvs2tabsplit(CSOUND *csound, PVS2TABSPLIT_T *p){
2713
2714 IGN(csound);
2715 int32_t mags_size = p->mags->sizes[0], freqs_size = p->freqs->sizes[0],
2716 N = p->fsig->N, i, j;
2717 float *fsig = (float *) p->fsig->frame.auxp;
2718 for(i = 0, j = 0; j < mags_size && i < N+2; i += 2, j++) {
2719 p->mags->data[j] = (MYFLT) fsig[i];
2720 }
2721
2722 for(i = 1, j = 0; j < freqs_size && i < N+2; i += 2, j++)
2723 p->freqs->data[j] = (MYFLT) fsig[i];
2724
2725 *p->framecount = (MYFLT) p->fsig->framecount;
2726 return OK;
2727 }
2728
2729 typedef struct tab2pvs_t {
2730 OPDS h;
2731 PVSDAT *fout;
2732 ARRAYDAT *in;
2733 MYFLT *olap, *winsize, *wintype, *format;
2734 uint32 ktime;
2735 uint32 lastframe;
2736 } TAB2PVS_T;
2737
tab2pvs_init(CSOUND * csound,TAB2PVS_T * p)2738 int32_t tab2pvs_init(CSOUND *csound, TAB2PVS_T *p)
2739 {
2740 if (LIKELY(p->in->data)){
2741 int32_t N;
2742 p->fout->N = N = p->in->sizes[0] - 2;
2743 p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4);
2744 p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N);
2745 p->fout->wintype = (int32) *p->wintype;
2746 p->fout->format = 0;
2747 p->fout->framecount = 1;
2748 p->lastframe = 0;
2749 p->ktime = 0;
2750 if (p->fout->frame.auxp == NULL ||
2751 p->fout->frame.size < sizeof(float) * (N + 2)) {
2752 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
2753 }
2754 else
2755 memset(p->fout->frame.auxp, 0, sizeof(float)*(N+2));
2756 return OK;
2757 }
2758 else return csound->InitError(csound, Str("array-variable not initialised"));
2759 }
2760
tab2pvs(CSOUND * csound,TAB2PVS_T * p)2761 int32_t tab2pvs(CSOUND *csound, TAB2PVS_T *p)
2762 {
2763 IGN(csound);
2764 int32_t size = p->in->sizes[0], i;
2765 float *fout = (float *) p->fout->frame.auxp;
2766
2767 p->ktime += CS_KSMPS;
2768 if (p->ktime > (uint32) p->fout->overlap) {
2769 p->fout->framecount++;
2770 p->ktime -= p->fout->overlap;
2771 }
2772
2773 if (p->lastframe < p->fout->framecount){
2774 for (i = 0; i < size; i++){
2775 fout[i] = (float) p->in->data[i];
2776 }
2777 p->lastframe = p->fout->framecount;
2778 }
2779
2780 return OK;
2781 }
2782
2783 typedef struct tab2pvssplit_t {
2784 OPDS h;
2785 PVSDAT *fout;
2786 ARRAYDAT *mags;
2787 ARRAYDAT *freqs;
2788 MYFLT *olap, *winsize, *wintype, *format;
2789 uint32 ktime;
2790 uint32 lastframe;
2791 } TAB2PVSSPLIT_T;
2792
tab2pvssplit_init(CSOUND * csound,TAB2PVSSPLIT_T * p)2793 int32_t tab2pvssplit_init(CSOUND *csound, TAB2PVSSPLIT_T *p)
2794 {
2795 if (LIKELY(p->mags->data) && LIKELY(p->freqs->data) &&
2796 (p->mags->sizes[0] == p->freqs->sizes[0])) {
2797 int32_t N;
2798 p->fout->N = N = (p->mags->sizes[0] * 2) - 2;
2799 p->fout->overlap = (int32)(*p->olap ? *p->olap : N/4);
2800 p->fout->winsize = (int32)(*p->winsize ? *p->winsize : N);
2801 p->fout->wintype = (int32) *p->wintype;
2802 p->fout->format = 0;
2803 p->fout->framecount = 1;
2804 p->lastframe = 0;
2805 p->ktime = 0;
2806 if (p->fout->frame.auxp == NULL ||
2807 p->fout->frame.size < sizeof(float) * (N + 2)) {
2808 csound->AuxAlloc(csound, (N + 2) * sizeof(float), &p->fout->frame);
2809 }
2810 else
2811 memset(p->fout->frame.auxp, 0, sizeof(float)*(N+2));
2812 return OK;
2813 }
2814 else return csound->InitError(csound,
2815 Str("magnitude and frequency arrays not "
2816 "initialised, or are not the same size"));
2817 }
2818
tab2pvssplit(CSOUND * csound,TAB2PVSSPLIT_T * p)2819 int32_t tab2pvssplit(CSOUND *csound, TAB2PVSSPLIT_T *p)
2820 {
2821 IGN(csound);
2822 int32_t size = p->mags->sizes[0], i;
2823 float *fout = (float *) p->fout->frame.auxp;
2824
2825 p->ktime += CS_KSMPS;
2826 if (p->ktime > (uint32) p->fout->overlap) {
2827 p->fout->framecount++;
2828 p->ktime -= p->fout->overlap;
2829 }
2830
2831 if (p->lastframe < p->fout->framecount){
2832 for (i = 0; i < size; i++){
2833 fout[i * 2] = (float) p->mags->data[i];
2834 fout[i * 2 + 1] = (float) p->freqs->data[i];
2835 }
2836 p->lastframe = p->fout->framecount;
2837 }
2838
2839 return OK;
2840 }
2841
2842
2843 static OENTRY localops[] = {
2844 {"pvsfwrite", sizeof(PVSFWRITE),0, 3, "", "fS", (SUBR) pvsfwriteset_S,
2845 (SUBR) pvsfwrite},
2846 {"pvsfwrite.i", sizeof(PVSFWRITE),0, 3, "", "fi", (SUBR) pvsfwriteset,
2847 (SUBR) pvsfwrite},
2848 {"pvsfilter", sizeof(PVSFILTER),0, 3, "f", "ffxp", (SUBR) pvsfilterset,
2849 (SUBR) pvsfilter},
2850 {"pvscale", sizeof(PVSSCALE),0, 3, "f", "fxOPO", (SUBR) pvsscaleset,
2851 (SUBR) pvsscale},
2852 {"pvshift", sizeof(PVSSHIFT),0, 3, "f", "fxkOPO", (SUBR) pvsshiftset,
2853 (SUBR) pvsshift},
2854 {"pvsfilter", sizeof(PVSFILTER),0, 3, "f", "fffp", (SUBR) pvsfilterset,
2855 (SUBR) pvsfilter},
2856 {"pvscale", sizeof(PVSSCALE),0, 3, "f", "fkOPO",
2857 (SUBR) pvsscaleset, (SUBR) pvsscale},
2858 {"pvshift", sizeof(PVSSHIFT),0, 3, "f", "fkkOPO", (SUBR) pvsshiftset,
2859 (SUBR) pvsshift},
2860 {"pvsmix", sizeof(PVSMIX),0, 3, "f", "ff", (SUBR) pvsmixset, (SUBR)pvsmix, NULL},
2861 {"pvsfilter", sizeof(PVSFILTER),0, 3, "f", "ffxp", (SUBR) pvsfilterset,
2862 (SUBR) pvsfilter},
2863 {"pvsblur", sizeof(PVSBLUR),0, 3, "f", "fki", (SUBR) pvsblurset, (SUBR) pvsblur,
2864 NULL},
2865 {"pvstencil", sizeof(PVSTENCIL), TR, 3, "f", "fkki", (SUBR) pvstencilset,
2866 (SUBR) pvstencil},
2867 {"pvsinit", sizeof(PVSINI),0, 1, "f", "ioopo", (SUBR) pvsinit, NULL, NULL},
2868 {"pvsbin", sizeof(PVSBIN),0, 3, "ss", "fk", (SUBR) pvsbinset,
2869 (SUBR) pvsbinprocess, (SUBR) pvsbinprocessa},
2870 {"pvsfreeze", sizeof(PVSFREEZE),0, 3, "f", "fkk", (SUBR) pvsfreezeset,
2871 (SUBR) pvsfreezeprocess, NULL},
2872 {"pvsmooth", sizeof(PVSFREEZE),0, 3, "f", "fxx", (SUBR) pvsmoothset,
2873 (SUBR) pvsmoothprocess, NULL},
2874 {"pvsosc", sizeof(PVSOSC),0, 3, "f", "kkkioopo", (SUBR) pvsoscset,
2875 (SUBR) pvsoscprocess, NULL},
2876 {"pvsdiskin", sizeof(pvsdiskin),0, 3, "f", "SkkopP",(SUBR) pvsdiskinset_S,
2877 (SUBR) pvsdiskinproc, NULL},
2878 {"pvsdiskin.i", sizeof(pvsdiskin),0, 3, "f", "ikkopP",(SUBR) pvsdiskinset,
2879 (SUBR) pvsdiskinproc, NULL},
2880 {"pvstanal", sizeof(PVST1),0, 3, "f", "kkkkPPoooP",
2881 (SUBR) pvstanalset1, (SUBR) pvstanal1, NULL},
2882 {"pvstanal", sizeof(PVST),0, 3, "FFFFFFFFFFFFFFFF", "kkkkPPoooP",
2883 (SUBR) pvstanalset, (SUBR) pvstanal, NULL},
2884 {"pvswarp", sizeof(PVSWARP),0, 3, "f", "fkkOPPO",
2885 (SUBR) pvswarpset, (SUBR) pvswarp},
2886 {"pvsenvftw", sizeof(PVSENVW),0, 3, "k", "fkPPO",
2887 (SUBR) pvsenvwset, (SUBR) pvsenvw},
2888 {"pvsgain", sizeof(PVSGAIN), 0,3, "f", "fk",
2889 (SUBR) pvsgainset, (SUBR) pvsgain, NULL},
2890 {"pvs2tab", sizeof(PVS2TAB_T), 0,3, "k", "k[]f",
2891 (SUBR) pvs2tab_init, (SUBR) pvs2tab, NULL},
2892 {"pvs2tab", sizeof(PVS2TABSPLIT_T), 0,3, "k", "k[]k[]f",
2893 (SUBR) pvs2tabsplit_init, (SUBR) pvs2tabsplit, NULL},
2894 {"tab2pvs", sizeof(TAB2PVS_T), 0, 3, "f", "k[]oop", (SUBR) tab2pvs_init,
2895 (SUBR) tab2pvs, NULL},
2896 {"tab2pvs", sizeof(TAB2PVSSPLIT_T), 0, 3, "f", "k[]k[]oop",
2897 (SUBR) tab2pvssplit_init, (SUBR) tab2pvssplit, NULL},
2898 {"pvs2array", sizeof(PVS2TAB_T), 0,3, "k", "k[]f",
2899 (SUBR) pvs2tab_init, (SUBR) pvs2tab, NULL},
2900 {"pvs2array", sizeof(PVS2TABSPLIT_T), 0,3, "k", "k[]k[]f",
2901 (SUBR) pvs2tabsplit_init, (SUBR) pvs2tabsplit, NULL},
2902 {"pvsfromarray", sizeof(TAB2PVS_T), 0, 3, "f", "k[]oop",
2903 (SUBR) tab2pvs_init, (SUBR) tab2pvs, NULL},
2904 {"pvsfromarray", sizeof(TAB2PVSSPLIT_T), 0, 3, "f", "k[]k[]oop",
2905 (SUBR) tab2pvssplit_init, (SUBR) tab2pvssplit, NULL}
2906 };
2907
pvsbasic_init_(CSOUND * csound)2908 int32_t pvsbasic_init_(CSOUND *csound)
2909 {
2910 return csound->AppendOpcodes(csound, &(localops[0]),
2911 (int32_t) (sizeof(localops) / sizeof(OENTRY)));
2912 }
2913