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