class library: SynthDesc - gui fix
[supercollider.git] / server / plugins / Convolution.cpp
blob6a9bc6f7752ae6ae2019eea461c1e63e2f9b532d
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //Convolution by nick collins for sc3 (later input from Marije as below, Dan Stowell and Nick worked on sc_fft compatibility late 2008)
22 //see ch18 http://www.dspguide.com/ch18.htm Steven W Smith
24 //Convolution2 adapted by marije baalman for triggered kernel swap, with help from alberto de campo
25 //Convolution2L (with linear crossfade) by marije baalman
26 //Convolution3 (time-based) by marije baalman
28 #include "FFT_UGens.h"
30 //#include "SC_fftlib.h"
33 //float *fftWindow[32];
35 struct Convolution : Unit
37 int m_pos, m_insize, m_fftsize;
38 //int m_log2n;
39 float *m_inbuf1,*m_inbuf2, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf;
40 scfft *m_scfft1, *m_scfft2, *m_scfftR;
44 struct Convolution2 : Unit
46 int m_pos, m_insize, m_fftsize; //,m_mask;
47 //int m_log2n;
48 float m_prevtrig;
49 float *m_inbuf1, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf;
50 scfft *m_scfft1, *m_scfft2, *m_scfftR;
53 struct Convolution2L : Unit
55 int m_pos, m_insize, m_fftsize; //,m_mask;
56 int m_cfpos, m_cflength, m_curbuf; // for crossfading
57 int m_log2n;
58 float m_prevtrig;
59 float *m_inbuf1, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf;
60 float *m_tempbuf, *m_fftbuf3; // for crossfading
62 scfft *m_scfft1, *m_scfft2, *m_scfft3, *m_scfftR, *m_scfftR2; //source plus two kernels forwards, and two inverse from outbuf and from tempbuf
66 //could be done also using complex signal fft and appropriate unwrapping, but sc_fft doesn't support that
67 struct StereoConvolution2L : Unit
69 int m_pos, m_insize, m_fftsize; //,m_mask;
70 int m_cfpos, m_cflength, m_curbuf; // for crossfading
71 int m_log2n;
72 float m_prevtrig;
73 float *m_inbuf1, *m_fftbuf1; // input
74 float *m_fftbuf2[2], *m_outbuf[2],*m_overlapbuf[2]; // output
75 float *m_tempbuf[2], *m_fftbuf3[2]; // for crossfading
77 scfft *m_scfft1, *m_scfft2[2], *m_scfft3[2], *m_scfftR[2], *m_scfftR2[2];
80 struct Convolution3 : Unit
82 int m_pos, m_insize;
83 float m_prevtrig;
84 float *m_inbuf1, *m_inbuf2, *m_outbuf;
87 //////////////////////////////////////////////////////////////////////////////////////////////////
89 extern "C"
91 void Convolution_next(Convolution *unit, int wrongNumSamples);
92 void Convolution_Ctor(Convolution *unit);
93 void Convolution_Dtor(Convolution *unit);
95 void Convolution2_next(Convolution2 *unit, int wrongNumSamples);
96 //void Convolution2_next2(Convolution2 *unit, int wrongNumSamples);
97 void Convolution2_Ctor(Convolution2 *unit);
98 void Convolution2_Dtor(Convolution2 *unit);
100 void Convolution2L_next(Convolution2L *unit, int wrongNumSamples);
101 void Convolution2L_Ctor(Convolution2L *unit);
102 void Convolution2L_Dtor(Convolution2L *unit);
104 void StereoConvolution2L_next(StereoConvolution2L *unit, int wrongNumSamples);
105 void StereoConvolution2L_Ctor(StereoConvolution2L *unit);
106 void StereoConvolution2L_Dtor(StereoConvolution2L *unit);
108 void Convolution3_next_a(Convolution3 *unit);
109 void Convolution3_next_k(Convolution3 *unit);
110 void Convolution3_Ctor(Convolution3 *unit);
111 void Convolution3_Dtor(Convolution3 *unit);
115 ////////////////////////////////////////////////////////////////////////////////////////////////////////
117 //PROPER CONVOLVER
118 //two possibilities- fixed kernel (in which case can derive the kernel spectrum in the constructor)
119 //and changing kernel (same size as target)
121 void Convolution_Ctor(Convolution *unit)
123 //require size N+M-1 to be a power of two
124 unit->m_insize=(int)ZIN0(2);
126 // printf("hello %i /n", unit->m_insize);
127 unit->m_fftsize=2*(unit->m_insize);
128 //just use memory for the input buffers and fft buffers
129 int insize = unit->m_insize * sizeof(float);
130 int fftsize = unit->m_fftsize * sizeof(float);
132 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
133 unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
134 unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
135 unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);
137 unit->m_outbuf = (float*)RTAlloc(unit->mWorld, fftsize);
138 unit->m_overlapbuf = (float*)RTAlloc(unit->mWorld, insize);
140 memset(unit->m_outbuf, 0, fftsize);
141 memset(unit->m_overlapbuf, 0, insize);
143 //unit->m_log2n = LOG2CEIL(unit->m_fftsize);
145 unit->m_pos = 0;
147 SCWorld_Allocator alloc(ft, unit->mWorld);
148 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
149 unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
150 unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc);
152 SETCALC(Convolution_next);
156 void Convolution_Dtor(Convolution *unit)
158 RTFree(unit->mWorld, unit->m_inbuf1);
159 RTFree(unit->mWorld, unit->m_inbuf2);
160 RTFree(unit->mWorld, unit->m_fftbuf1);
161 RTFree(unit->mWorld, unit->m_fftbuf2);
162 RTFree(unit->mWorld, unit->m_outbuf);
163 RTFree(unit->mWorld, unit->m_overlapbuf);
164 SCWorld_Allocator alloc(ft, unit->mWorld);
165 scfft_destroy(unit->m_scfft1, alloc);
166 scfft_destroy(unit->m_scfft2, alloc);
167 scfft_destroy(unit->m_scfftR, alloc);
171 void Convolution_next(Convolution *unit, int numSamples)
173 float *in1 = IN(0);
174 float *in2 = IN(1);
176 float *out1 = unit->m_inbuf1 + unit->m_pos;
177 float *out2 = unit->m_inbuf2 + unit->m_pos;
179 //int numSamples = unit->mWorld->mFullRate.mBufLength;
181 // copy input
182 Copy(numSamples, out1, in1);
183 Copy(numSamples, out2, in2);
185 unit->m_pos += numSamples;
187 int insize= unit->m_insize;
189 if (unit->m_pos & insize) {
190 //have collected enough samples to transform next frame
191 unit->m_pos = 0; //reset collection counter
193 int memsize= insize*sizeof(float);
195 // copy to fftbuf
196 memcpy(unit->m_fftbuf1, unit->m_inbuf1, memsize);
197 memcpy(unit->m_fftbuf2, unit->m_inbuf2, memsize);
199 //zero pad second part of buffer to allow for convolution
200 memset(unit->m_fftbuf1+unit->m_insize, 0, memsize);
201 memset(unit->m_fftbuf2+unit->m_insize, 0, memsize);
203 // do fft
205 //in place transform for now
207 //old Green fft code, now replaced by scfft
208 // int log2n = unit->m_log2n;
209 // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
210 // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
211 scfft_dofft(unit->m_scfft1);
212 scfft_dofft(unit->m_scfft2);
214 //complex multiply time
215 float * p1= unit->m_fftbuf1;
216 float * p2= unit->m_fftbuf2;
218 p1[0] *= p2[0];
219 p1[1] *= p2[1];
221 //complex multiply
222 for (int i=1; i<insize; ++i) {
223 float real,imag;
224 int realind,imagind;
225 realind= 2*i; imagind= realind+1;
226 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
227 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
229 p1[realind] = real;
230 p1[imagind]= imag;
233 //copy second part from before to overlap
234 memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, memsize);
236 //inverse fft into outbuf
237 memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
239 //in place
240 //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
241 scfft_doifft(unit->m_scfftR);
244 //write out samples copied from outbuf, with overlap added in
246 float *output = ZOUT(0);
247 float *out= unit->m_outbuf+unit->m_pos;
248 float *overlap= unit->m_overlapbuf+unit->m_pos;
250 for (int i=0; i<numSamples; ++i)
251 *++output = *++out + *++overlap;
256 //include local buffer test in one place
257 static SndBuf * ConvGetBuffer(Unit * unit, uint32 bufnum)
259 SndBuf *buf;
260 World *world = unit->mWorld;
262 if (bufnum >= world->mNumSndBufs) {
263 int localBufNum = bufnum - world->mNumSndBufs;
264 Graph *parent = unit->mParent;
265 if(localBufNum <= parent->localMaxBufNum) {
266 buf = parent->mLocalSndBufs + localBufNum;
267 } else {
268 if(unit->mWorld->mVerbosity > -1){ Print("ConvolutionX UGen Buffer Number error: invalid buffer number: %i.\n", bufnum); }
269 SETCALC(*ClearUnitOutputs);
270 unit->mDone = true;
271 return NULL;
273 } else {
274 buf = world->mSndBufs + bufnum;
277 return buf;
282 void Convolution2_Ctor(Convolution2 *unit)
284 //require size N+M-1 to be a power of two
286 unit->m_insize=(int)ZIN0(3); //could be input parameter
287 // printf( "unit->m_insize %i\n", unit->m_insize );
288 // printf( "unit->mWorld->mFullRate.mBufLength %i\n", unit->mWorld->mFullRate.mBufLength );
290 //float fbufnum = ZIN0(1);
291 uint32 bufnum = (int)ZIN0(1); //fbufnum;
292 World *world = unit->mWorld;
294 //before added check for LocalBuf
295 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
296 // SndBuf *buf = world->mSndBufs + bufnum;
298 SndBuf *buf = ConvGetBuffer(unit,bufnum);
300 if(buf) {
301 if ( unit->m_insize <= 0 ) // if smaller than zero, equal to size of buffer
302 unit->m_insize=buf->frames; //could be input parameter
304 unit->m_fftsize=2*(unit->m_insize);
305 //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
306 //just use memory for the input buffers and fft buffers
307 int insize = unit->m_insize * sizeof(float);
308 int fftsize = unit->m_fftsize * sizeof(float);
311 // unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
312 //// unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
314 // unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
315 // unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);
318 unit->m_inbuf1 = (float*)RTAlloc(world, insize);
319 unit->m_fftbuf1 = (float*)RTAlloc(world, fftsize);
320 unit->m_fftbuf2 = (float*)RTAlloc(world, fftsize);
322 unit->m_outbuf = (float*)RTAlloc(world, fftsize);
323 unit->m_overlapbuf = (float*)RTAlloc(world, insize);
325 memset(unit->m_outbuf, 0, fftsize);
326 memset(unit->m_overlapbuf, 0, insize);
328 //unit->m_log2n = LOG2CEIL(unit->m_fftsize);
330 unit->m_pos = 0;
331 memset(unit->m_outbuf, 0, fftsize);
332 memset(unit->m_overlapbuf, 0, insize);
334 SCWorld_Allocator alloc(ft, unit->mWorld);
335 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
336 unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
337 unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc);
339 //calculate fft for kernel straight away
340 memcpy(unit->m_fftbuf2, buf->data, insize);
341 //zero pad second part of buffer to allow for convolution
342 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
344 scfft_dofft(unit->m_scfft2);
346 unit->m_pos = 0;
348 // unit->m_log2n = LOG2CEIL(unit->m_fftsize);
350 // int log2n = unit->m_log2n;
352 // //test for full input buffer
353 // //unit->m_mask = unit->m_insize;
355 // //in place transform for now
356 // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
358 unit->m_prevtrig = 0.f;
359 unit->m_prevtrig = ZIN0(2);
361 // printf( "unit->m_insize %i\n", unit->m_insize );
362 // printf( "world->mFullRate.mBufLength %i\n", world->mFullRate.mBufLength );
364 if ( unit->m_insize >= world->mFullRate.mBufLength )
366 // printf( "insize bigger than blocksize\n" );
367 SETCALC(Convolution2_next);
369 else
371 printf( "Convolution2 framesize smaller than blocksize \n" );
372 SETCALC(*ClearUnitOutputs);
373 unit->mDone = true;
374 //SETCALC(Convolution2_next2);
379 void Convolution2_Dtor(Convolution2 *unit)
381 RTFree(unit->mWorld, unit->m_inbuf1);
382 // RTFree(unit->mWorld, unit->m_inbuf2);
383 RTFree(unit->mWorld, unit->m_fftbuf1);
384 RTFree(unit->mWorld, unit->m_fftbuf2);
385 RTFree(unit->mWorld, unit->m_outbuf);
386 RTFree(unit->mWorld, unit->m_overlapbuf);
388 SCWorld_Allocator alloc(ft, unit->mWorld);
389 scfft_destroy(unit->m_scfft1, alloc);
390 scfft_destroy(unit->m_scfft2, alloc);
391 scfft_destroy(unit->m_scfftR, alloc);
395 void Convolution2_next(Convolution2 *unit, int wrongNumSamples)
397 float *in1 = IN(0);
398 //float *in2 = IN(1);
399 float curtrig = ZIN0(2);
401 float *out1 = unit->m_inbuf1 + unit->m_pos;
402 // float *out2 = unit->m_inbuf2 + unit->m_pos;
404 int numSamples = unit->mWorld->mFullRate.mBufLength;
405 uint32 insize=unit->m_insize * sizeof(float);
407 // copy input
408 Copy(numSamples, out1, in1);
410 unit->m_pos += numSamples;
412 if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
413 //float fbufnum = ZIN0(1);
414 //int log2n2 = unit->m_log2n;
415 //uint32 bufnum = (int)fbufnum;
416 //printf("bufnum %i \n", bufnum);
417 //World *world = unit->mWorld;
418 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
419 //SndBuf *buf = world->mSndBufs + bufnum;
421 SndBuf *buf = ConvGetBuffer(unit,(uint32)ZIN0(1));
422 LOCK_SNDBUF_SHARED(buf);
424 memcpy(unit->m_fftbuf2, buf->data, insize);
425 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
426 //rffts(unit->m_fftbuf2, log2n2, 1, cosTable[log2n2]);
428 scfft_dofft(unit->m_scfft2);
431 if (unit->m_pos & unit->m_insize) {
433 //have collected enough samples to transform next frame
434 unit->m_pos = 0; //reset collection counter
436 // copy to fftbuf
437 //int log2n = unit->m_log2n;
439 memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
441 //zero pad second part of buffer to allow for convolution
442 memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
443 //if (unit->m_prevtrig <= 0.f && curtrig > 0.f)
445 scfft_dofft(unit->m_scfft1);
447 //in place transform for now
448 // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
450 //complex multiply time
451 int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
453 float * p1= unit->m_fftbuf1;
454 float * p2= unit->m_fftbuf2;
456 p1[0] *= p2[0];
457 p1[1] *= p2[1];
459 //complex multiply
460 for (int i=1; i<numbins; ++i) {
461 float real,imag;
462 int realind,imagind;
463 realind= 2*i; imagind= realind+1;
464 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
465 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
466 p1[realind] = real; //p2->bin[i];
467 p1[imagind]= imag;
470 //copy second part from before to overlap
471 memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, insize);
473 //inverse fft into outbuf
474 memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
476 //in place
477 //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
479 scfft_doifft(unit->m_scfftR);
481 // DoWindowing(log2n, unit->m_outbuf, unit->m_fftsize);
484 //write out samples copied from outbuf, with overlap added in
486 float *output = ZOUT(0);
487 float *out= unit->m_outbuf+unit->m_pos;
488 float *overlap= unit->m_overlapbuf+unit->m_pos;
489 unit->m_prevtrig = curtrig;
491 for (int i=0; i<numSamples; ++i)
492 *++output = *++out + *++overlap;
497 // flawed since assumes framesize at least divides blocksize. framesize has to be power of two anyway: commenting out pending deletion
498 //// if kernel size is smaller than server block size (note: this is not working yet...
499 //void Convolution2_next2(Convolution2 *unit, int wrongNumSamples)
502 // float *in1 = IN(0);
503 // //float *in2 = IN(1);
504 // float curtrig = ZIN0(2);
506 // float *out1 = unit->m_inbuf1; // unit->m_pos is now a pointer into the *in1 buffer
507 //// float *out2 = unit->m_inbuf2 + unit->m_pos;
509 // unit->m_pos = 0;
511 // int numSamples = unit->mWorld->mFullRate.mBufLength;
512 // uint32 insize=unit->m_insize * sizeof(float);
514 // int numTimes = numSamples / unit->m_insize;
516 //// replace buffer if there was a trigger
517 // if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
518 // float fbufnum = ZIN0(1);
519 // int log2n2 = unit->m_log2n;
520 // uint32 bufnum = (int)fbufnum;
521 // //printf("bufnum %i \n", bufnum);
522 // World *world = unit->mWorld;
523 // if (bufnum >= world->mNumSndBufs) bufnum = 0;
524 // SndBuf *buf = world->mSndBufs + bufnum;
526 // memcpy(unit->m_fftbuf2, buf->data, insize);
527 // memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
528 // //DoWindowing(log2n2, unit->m_fftbuf2, unit->m_fftsize);
529 // rffts(unit->m_fftbuf2, log2n2, 1, cosTable[log2n2]);
530 // }
532 // for ( int i=0; i < numTimes; i++ )
533 // {
534 // // copy input
535 // Copy(unit->m_insize, out1, in1 + unit->m_pos);
536 // unit->m_pos += unit->m_insize;
538 // //have collected enough samples to transform next frame
539 // // copy to fftbuf
540 // int log2n = unit->m_log2n;
542 // memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
543 // //zero pad second part of buffer to allow for convolution
544 // memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
546 // //in place transform for now
547 // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
549 // //complex multiply time
550 // int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
552 // float * p1= unit->m_fftbuf1;
553 // float * p2= unit->m_fftbuf2;
555 // p1[0] *= p2[0];
556 // p1[1] *= p2[1];
558 // //complex multiply
559 // for (int i=1; i<numbins; ++i) {
560 // float real,imag;
561 // int realind,imagind;
562 // realind= 2*i; imagind= realind+1;
563 // real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
564 // imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
565 // p1[realind] = real; //p2->bin[i];
566 // p1[imagind]= imag;
567 // }
569 // //copy second part from before to overlap
570 // memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, unit->m_insize * sizeof(float));
572 // //inverse fft into outbuf
573 // memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
575 // //in place
576 // riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
578 // //write out samples copied from outbuf, with overlap added in
579 // float *output = ZOUT(0);
580 // float *out= unit->m_outbuf;
581 // float *overlap= unit->m_overlapbuf;
583 // for (int i=0; i<unit->m_insize; ++i) {
584 // *++output = *++out + *++overlap;
585 // }
586 // }
587 // unit->m_prevtrig = curtrig;
590 void Convolution2L_Ctor(Convolution2L *unit)
592 //require size N+M-1 to be a power of two
593 //transform samp=
595 unit->m_insize=(int)ZIN0(3); //could be input parameter
596 unit->m_cflength = (int)ZIN0(4); // could be input parameter
597 unit->m_curbuf = 0;
598 unit->m_cfpos = unit->m_cflength;
601 unit->m_fftsize=2*(unit->m_insize);
602 //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
603 //just use memory for the input buffers and fft buffers
604 int insize = unit->m_insize * sizeof(float);
605 int fftsize = unit->m_fftsize * sizeof(float);
607 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
608 // unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
610 unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
611 unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);
612 unit->m_fftbuf3 = (float*)RTAlloc(unit->mWorld, fftsize);
613 unit->m_tempbuf = (float*)RTAlloc(unit->mWorld, fftsize);
615 //float fbufnum = ZIN0(1);
616 uint32 bufnum = (int)ZIN0(1); //fbufnum;
617 //printf("bufnum %i \n", bufnum);
618 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
619 //SndBuf *buf = world->mSndBufs + bufnum;
621 World *world = unit->mWorld;
623 SndBuf *buf = ConvGetBuffer(unit,bufnum);
625 if(buf) {
626 SCWorld_Allocator alloc(ft, unit->mWorld);
627 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
628 unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
629 unit->m_scfft3 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf3, unit->m_fftbuf3, kForward, alloc);
630 unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_outbuf, unit->m_outbuf, kBackward, alloc);
631 unit->m_scfftR2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_tempbuf, unit->m_tempbuf, kBackward, alloc);
633 unit->m_outbuf = (float*)RTAlloc(unit->mWorld, fftsize);
634 unit->m_overlapbuf = (float*)RTAlloc(unit->mWorld, insize);
636 memset(unit->m_outbuf, 0, fftsize);
637 memset(unit->m_overlapbuf, 0, insize);
640 //calculate fft for kernel straight away
641 memcpy(unit->m_fftbuf2, buf->data, insize);
642 //zero pad second part of buffer to allow for convolution
643 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
645 scfft_dofft(unit->m_scfft2);
647 unit->m_pos = 0;
651 // //calculate fft for kernel straight away
652 // memcpy(unit->m_fftbuf2, buf->data, insize);
653 // //zero pad second part of buffer to allow for convolution
654 // memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
656 // unit->m_log2n = LOG2CEIL(unit->m_fftsize);
658 // int log2n = unit->m_log2n;
660 // //test for full input buffer
661 // unit->m_mask = unit->m_insize;
664 // // do windowing
665 //// DoWindowing(log2n, unit->m_fftbuf2, unit->m_fftsize);
667 // //in place transform for now
668 // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
671 // unit->m_outbuf = (float*)RTAlloc(unit->mWorld, fftsize);
672 // unit->m_overlapbuf = (float*)RTAlloc(unit->mWorld, insize);
674 // memset(unit->m_outbuf, 0, fftsize);
675 // memset(unit->m_overlapbuf, 0, insize);
677 unit->m_prevtrig = 0.f;
679 SETCALC(Convolution2L_next);
683 void Convolution2L_Dtor(Convolution2L *unit)
685 SCWorld_Allocator alloc(ft, unit->mWorld);
686 scfft_destroy(unit->m_scfft1, alloc);
687 scfft_destroy(unit->m_scfft2, alloc);
688 scfft_destroy(unit->m_scfft3, alloc);
689 scfft_destroy(unit->m_scfftR, alloc);
690 scfft_destroy(unit->m_scfftR2, alloc);
693 RTFree(unit->mWorld, unit->m_inbuf1);
694 // RTFree(unit->mWorld, unit->m_inbuf2);
695 RTFree(unit->mWorld, unit->m_fftbuf1);
696 RTFree(unit->mWorld, unit->m_fftbuf2);
697 RTFree(unit->mWorld, unit->m_fftbuf3);
698 RTFree(unit->mWorld, unit->m_tempbuf);
699 RTFree(unit->mWorld, unit->m_outbuf);
700 RTFree(unit->mWorld, unit->m_overlapbuf);
704 void Convolution2L_next(Convolution2L *unit, int numSamples)
706 float *in1 = IN(0);
707 //float *in2 = IN(1);
708 float curtrig = ZIN0(2);
710 float *out1 = unit->m_inbuf1 + unit->m_pos;
711 // float *out2 = unit->m_inbuf2 + unit->m_pos;
713 //int numSamples = unit->mWorld->mFullRate.mBufLength;
714 int insize=unit->m_insize * sizeof(float);
716 // copy input
717 //Copy(numSamples, out1, in1);
718 memcpy(out1,in1,numSamples*sizeof(float));
720 unit->m_pos += numSamples;
722 //printf("test1\n");
724 if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
726 uint32 bufnum = (int)ZIN0(1);
727 World *world = unit->mWorld;
728 SndBuf *buf = ConvGetBuffer(unit,bufnum);
730 //float fbufnum = ZIN0(1);
731 // //int log2n2 = unit->m_log2n;
732 // uint32 bufnum = (int)fbufnum;
734 unit->m_cflength = (int)ZIN0(4);
735 //printf("bufnum %i \n", bufnum);
736 //World *world = unit->mWorld;
738 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
739 //SndBuf *buf = world->mSndBufs + bufnum;
741 unit->m_cfpos = 0;
742 if ( unit->m_curbuf == 1 )
744 LOCK_SNDBUF_SHARED(buf);
745 memcpy(unit->m_fftbuf2, buf->data, insize);
746 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
748 scfft_dofft(unit->m_scfft2);
750 else if ( unit->m_curbuf == 0 )
752 LOCK_SNDBUF_SHARED(buf);
753 memcpy(unit->m_fftbuf3, buf->data, insize);
754 memset(unit->m_fftbuf3+unit->m_insize, 0, insize);
756 scfft_dofft(unit->m_scfft3);
760 if (unit->m_pos & unit->m_insize)
763 //have collected enough samples to transform next frame
764 unit->m_pos = 0; //reset collection counter
766 // copy to fftbuf
767 //int log2n = unit->m_log2n;
769 memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
771 //zero pad second part of buffer to allow for convolution
772 memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
773 //in place transform for now
774 scfft_dofft(unit->m_scfft1);
776 //rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
777 //complex multiply time
778 int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
780 float * p1= unit->m_fftbuf1;
781 float * p2;
782 if ( unit->m_curbuf == 0 )
783 p2 = unit->m_fftbuf2;
784 else
785 p2= unit->m_fftbuf3;
786 float * p3= unit->m_tempbuf;
788 // i don't know what this was supposed to do!
789 // p1[0] *= p2[0];
790 // p1[1] *= p2[1];
792 //complex multiply
793 for (int i=1; i<numbins; ++i)
795 float real,imag;
796 int realind,imagind;
797 realind= 2*i; imagind= realind+1;
798 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
799 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
800 p3[realind] = real; //p2->bin[i];
801 p3[imagind]= imag;
804 //copy second part from before to overlap
805 memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, unit->m_insize * sizeof(float));
806 //inverse fft into outbuf
807 memcpy(unit->m_outbuf, unit->m_tempbuf, unit->m_fftsize * sizeof(float));
808 //in place
809 //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
810 scfft_doifft(unit->m_scfftR);
812 if ( unit->m_cfpos < unit->m_cflength ) // do crossfade
814 if ( unit->m_curbuf == 0 )
815 p2= unit->m_fftbuf3;
816 else
817 p2= unit->m_fftbuf2;
819 // p1[0] *= p2[0];
820 // p1[1] *= p2[1];
822 //complex multiply
823 for (int i=1; i<numbins; ++i)
825 float real,imag;
826 int realind,imagind;
827 realind= 2*i; imagind= realind+1;
828 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
829 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
830 p1[realind] = real; //p2->bin[i];
831 p1[imagind]= imag;
834 //copy second part from before to overlap
835 // memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, unit->m_insize * sizeof(float));
836 //inverse fft into tempbuf
837 memcpy(unit->m_tempbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
838 //in place
839 //riffts(unit->m_tempbuf, log2n, 1, cosTable[log2n]);
840 scfft_doifft(unit->m_scfftR2);
842 // now crossfade between outbuf and tempbuf
843 float fact1 = (float) unit->m_cfpos/unit->m_cflength; // crossfade amount startpoint
844 float rc = 1.f/(unit->m_cflength*unit->m_insize); //crossfade amount increase per sample
845 float * p4 = unit->m_outbuf;
846 float * p5 = unit->m_tempbuf;
847 for ( int i=0; i < unit->m_insize; i++ )
849 float res;
850 res = (1-fact1)*p4[i] + fact1*p5[i];
851 fact1 += rc;
852 p4[i] = res;
854 if ( unit->m_cflength == 1 )
855 memcpy(unit->m_outbuf+unit->m_insize, unit->m_tempbuf+unit->m_insize,insize);
856 else
858 for ( int i=unit->m_insize+1; i < unit->m_fftsize; i++ )
860 float res = (1-fact1)*p4[i] + fact1*p5[i];
861 fact1 += rc;
862 p4[i] = res;
865 unit->m_cfpos++;
866 // printf("cfpos %i, cf_length %i \n", unit->m_cfpos, unit->m_cflength);
867 if ( unit->m_cfpos == unit->m_cflength ) // at end of crossfade, update the current buffer index
869 if ( unit->m_curbuf == 0 )
870 unit->m_curbuf = 1;
871 else
872 unit->m_curbuf = 0;
877 //write out samples copied from outbuf, with overlap added in
879 float *output = ZOUT(0);
880 float *out= unit->m_outbuf+unit->m_pos;
881 float *overlap= unit->m_overlapbuf+unit->m_pos;
882 unit->m_prevtrig = curtrig;
884 for (int i=0; i<numSamples; ++i)
885 *++output = *++out + *++overlap;
888 /** basically the same as Convolution2L, but takes a stereo buffer to convolve with and outputs a stereo signal */
889 void StereoConvolution2L_Ctor(StereoConvolution2L *unit)
891 //require size N+M-1 to be a power of two
892 //transform samp=
894 unit->m_insize=(int)ZIN0(4); //could be input parameter
895 unit->m_cflength = (int)ZIN0(5); // could be input parameter
896 unit->m_curbuf = 0;
897 unit->m_cfpos = unit->m_cflength;
899 unit->m_fftsize=2*(unit->m_insize);
900 //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
901 //just use memory for the input buffers and fft buffers
902 int insize = unit->m_insize * sizeof(float);
903 int fftsize = unit->m_fftsize * sizeof(float);
905 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
906 // unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
908 // source:
909 unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
911 // 2 channel buffer:
912 unit->m_fftbuf2[0] = (float*)RTAlloc(unit->mWorld, fftsize);
913 unit->m_fftbuf2[1] = (float*)RTAlloc(unit->mWorld, fftsize);
914 unit->m_fftbuf3[0] = (float*)RTAlloc(unit->mWorld, fftsize);
915 unit->m_fftbuf3[1] = (float*)RTAlloc(unit->mWorld, fftsize);
916 unit->m_tempbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
917 unit->m_tempbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
918 // unit->m_tempfftbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
919 // unit->m_tempfftbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
921 SCWorld_Allocator alloc(ft, unit->mWorld);
922 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
923 unit->m_scfft2[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2[0], unit->m_fftbuf2[0], kForward, alloc);
924 unit->m_scfft3[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2[1], unit->m_fftbuf2[1], kForward, alloc);
925 unit->m_scfftR[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf3[0], unit->m_fftbuf3[0], kForward, alloc);
926 unit->m_scfftR2[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf3[1], unit->m_fftbuf3[1], kForward, alloc);
927 unit->m_scfft2[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_outbuf[0], unit->m_outbuf[0], kBackward, alloc);
928 unit->m_scfft3[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_tempbuf[0], unit->m_tempbuf[0], kBackward, alloc);
929 unit->m_scfftR[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_outbuf[1], unit->m_outbuf[1], kBackward, alloc);
930 unit->m_scfftR2[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_tempbuf[1], unit->m_tempbuf[1], kBackward, alloc);
932 unit->m_outbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
933 unit->m_overlapbuf[0] = (float*)RTAlloc(unit->mWorld, insize);
934 unit->m_outbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
935 unit->m_overlapbuf[1] = (float*)RTAlloc(unit->mWorld, insize);
937 memset(unit->m_outbuf[0], 0, fftsize);
938 memset(unit->m_overlapbuf[0], 0, insize);
939 memset(unit->m_outbuf[1], 0, fftsize);
940 memset(unit->m_overlapbuf[1], 0, insize);
943 float fbufnum = ZIN0(1);
944 uint32 bufnumL = (int)fbufnum;
945 fbufnum = ZIN0(2);
946 uint32 bufnumR = (int)fbufnum;
947 //printf("bufnum %i \n", bufnum);
949 //unit->m_log2n = LOG2CEIL(unit->m_fftsize);
950 //int log2n = unit->m_log2n;
952 World *world = unit->mWorld;
954 SndBuf *buf = ConvGetBuffer(unit,bufnumL);
956 if (buf) {
957 LOCK_SNDBUF_SHARED(buf);
959 // if (bufnumL >= world->mNumSndBufs) bufnumL = 0;
960 // SndBuf *buf = world->mSndBufs + bufnumL;
962 //calculate fft for kernel straight away
963 memcpy(unit->m_fftbuf2[0], buf->data, insize);
964 //zero pad second part of buffer to allow for convolution
965 memset(unit->m_fftbuf2[0]+unit->m_insize, 0, insize);
966 //in place transform for now
967 //rffts(unit->m_fftbuf2[0], log2n, 1, cosTable[log2n]);
968 scfft_dofft(unit->m_scfft2[0]);
971 buf = ConvGetBuffer(unit,bufnumR);
972 if (buf) {
973 LOCK_SNDBUF(buf);
975 //if (bufnumR >= world->mNumSndBufs) bufnumR = 0;
976 //buf = world->mSndBufs + bufnumR;
978 //calculate fft for kernel straight away
979 memcpy(unit->m_fftbuf2[1], buf->data, insize);
980 //zero pad second part of buffer to allow for convolution
981 memset(unit->m_fftbuf2[1]+unit->m_insize, 0, insize);
982 //in place transform for now
983 //rffts(unit->m_fftbuf2[1], log2n, 1, cosTable[log2n]);
984 scfft_dofft(unit->m_scfft2[1]);
986 //test for full input buffer
987 //unit->m_mask = unit->m_insize;
988 unit->m_pos = 0;
990 // unit->m_outbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
991 // unit->m_overlapbuf[0] = (float*)RTAlloc(unit->mWorld, insize);
992 // unit->m_outbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
993 // unit->m_overlapbuf[1] = (float*)RTAlloc(unit->mWorld, insize);
995 // memset(unit->m_outbuf[0], 0, fftsize);
996 // memset(unit->m_overlapbuf[0], 0, insize);
997 // memset(unit->m_outbuf[1], 0, fftsize);
998 // memset(unit->m_overlapbuf[1], 0, insize);
1000 unit->m_prevtrig = 0.f;
1002 SETCALC(StereoConvolution2L_next);
1006 void StereoConvolution2L_Dtor(StereoConvolution2L *unit)
1008 SCWorld_Allocator alloc(ft, unit->mWorld);
1009 scfft_destroy(unit->m_scfft1, alloc);
1010 scfft_destroy(unit->m_scfft2[0], alloc);
1011 scfft_destroy(unit->m_scfft3[0], alloc);
1012 scfft_destroy(unit->m_scfftR[0], alloc);
1013 scfft_destroy(unit->m_scfftR2[0], alloc);
1014 scfft_destroy(unit->m_scfft2[1], alloc);
1015 scfft_destroy(unit->m_scfft3[1], alloc);
1016 scfft_destroy(unit->m_scfftR[1], alloc);
1017 scfft_destroy(unit->m_scfftR2[1], alloc);
1019 RTFree(unit->mWorld, unit->m_inbuf1);
1020 // RTFree(unit->mWorld, unit->m_inbuf2);
1021 RTFree(unit->mWorld, unit->m_fftbuf1);
1022 RTFree(unit->mWorld, unit->m_fftbuf2[0]);
1023 RTFree(unit->mWorld, unit->m_fftbuf3[0]);
1024 RTFree(unit->mWorld, unit->m_tempbuf[0]);
1025 // RTFree(unit->mWorld, unit->m_tempfftbuf[0]);
1026 RTFree(unit->mWorld, unit->m_outbuf[0]);
1027 RTFree(unit->mWorld, unit->m_overlapbuf[0]);
1028 RTFree(unit->mWorld, unit->m_fftbuf2[1]);
1029 RTFree(unit->mWorld, unit->m_fftbuf3[1]);
1030 RTFree(unit->mWorld, unit->m_tempbuf[1]);
1031 // RTFree(unit->mWorld, unit->m_tempfftbuf[1]);
1032 RTFree(unit->mWorld, unit->m_outbuf[1]);
1033 RTFree(unit->mWorld, unit->m_overlapbuf[1]);
1037 void StereoConvolution2L_next(StereoConvolution2L *unit, int wrongNumSamples)
1039 float *in1 = IN(0);
1040 //float *in2 = IN(1);
1041 float curtrig = ZIN0(3);
1043 float *out1 = unit->m_inbuf1 + unit->m_pos;
1044 // float *out2 = unit->m_inbuf2 + unit->m_pos;
1046 int numSamples = unit->mWorld->mFullRate.mBufLength;
1047 uint32 insize=unit->m_insize * sizeof(float);
1049 // copy input
1050 Copy(numSamples, out1, in1);
1052 unit->m_pos += numSamples;
1054 if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
1055 int log2n2 = unit->m_log2n;
1056 float fbufnum = ZIN0(1);
1057 uint32 bufnumL = (int)fbufnum;
1058 fbufnum = ZIN0(2);
1059 uint32 bufnumR = (int)fbufnum;
1060 unit->m_cflength = (int)ZIN0(5);
1061 //printf("bufnum %i \n", bufnum);
1062 World *world = unit->mWorld;
1064 SndBuf *bufL = ConvGetBuffer(unit,bufnumL);
1065 SndBuf *bufR = ConvGetBuffer(unit,bufnumR);
1067 // if (bufnumL >= world->mNumSndBufs) bufnumL = 0;
1068 // SndBuf *bufL = world->mSndBufs + bufnumL;
1069 // if (bufnumR >= world->mNumSndBufs) bufnumR = 0;
1070 // SndBuf *bufR = world->mSndBufs + bufnumR;
1072 unit->m_cfpos = 0;
1073 if ( unit->m_curbuf == 1 )
1075 LOCK_SNDBUF2_SHARED(bufL, bufR);
1076 memcpy(unit->m_fftbuf2[0], bufL->data, insize);
1077 memset(unit->m_fftbuf2[0]+unit->m_insize, 0, insize);
1078 scfft_dofft(unit->m_scfft2[0]);
1079 //rffts(unit->m_fftbuf2[0], log2n2, 1, cosTable[log2n2]);
1080 memcpy(unit->m_fftbuf2[1], bufR->data, insize);
1081 memset(unit->m_fftbuf2[1]+unit->m_insize, 0, insize);
1082 //rffts(unit->m_fftbuf2[1], log2n2, 1, cosTable[log2n2]);
1083 scfft_dofft(unit->m_scfft2[1]);
1085 else if ( unit->m_curbuf == 0 )
1087 LOCK_SNDBUF2_SHARED(bufL, bufR);
1088 memcpy(unit->m_fftbuf3[0], bufL->data, insize);
1089 memset(unit->m_fftbuf3[0]+unit->m_insize, 0, insize);
1090 //rffts(unit->m_fftbuf3[0], log2n2, 1, cosTable[log2n2]);
1091 scfft_dofft(unit->m_scfft3[0]);
1092 memcpy(unit->m_fftbuf3[1], bufR->data, insize);
1093 memset(unit->m_fftbuf3[1]+unit->m_insize, 0, insize);
1094 //rffts(unit->m_fftbuf3[1], log2n2, 1, cosTable[log2n2]);
1095 scfft_dofft(unit->m_scfft3[1]);
1099 if (unit->m_pos & unit->m_insize)
1102 //have collected enough samples to transform next frame
1103 unit->m_pos = 0; //reset collection counter
1105 // copy to fftbuf
1106 //int log2n = unit->m_log2n;
1108 memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
1110 //zero pad second part of buffer to allow for convolution
1111 memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
1112 //in place transform for now
1113 //rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
1114 scfft_dofft(unit->m_scfft1);
1116 //complex multiply time
1117 int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
1119 float * p1= unit->m_fftbuf1;
1120 float * p2L, * p2R;
1121 if ( unit->m_curbuf == 0 ){
1122 p2L = unit->m_fftbuf2[0];
1123 p2R = unit->m_fftbuf2[1];
1124 } else {
1125 p2L = unit->m_fftbuf3[0];
1126 p2R = unit->m_fftbuf3[1];
1128 float * p3L = unit->m_tempbuf[0];
1129 float * p3R = unit->m_tempbuf[1];
1131 // what was this supposed to do??
1132 // p1[0] *= p2[0];
1133 // p1[1] *= p2[1];
1135 //complex multiply
1136 for (int i=1; i<numbins; ++i)
1138 float realL,imagL;
1139 float realR,imagR;
1140 int realind,imagind;
1141 realind= 2*i; imagind= realind+1;
1142 realL= p1[realind]*p2L[realind]- p1[imagind]*p2L[imagind];
1143 imagL= p1[realind]*p2L[imagind]+ p1[imagind]*p2L[realind];
1144 realR= p1[realind]*p2R[realind]- p1[imagind]*p2R[imagind];
1145 imagR= p1[realind]*p2R[imagind]+ p1[imagind]*p2R[realind];
1146 p3L[realind] = realL; //p2->bin[i];
1147 p3L[imagind] = imagL;
1148 p3R[realind] = realR; //p2->bin[i];
1149 p3R[imagind] = imagR;
1152 for ( int i=0; i < 2; i++ ){
1153 //copy second part from before to overlap
1154 memcpy(unit->m_overlapbuf[i], unit->m_outbuf[i]+unit->m_insize, unit->m_insize * sizeof(float));
1155 //inverse fft into outbuf
1156 memcpy(unit->m_outbuf[i], unit->m_tempbuf[i], unit->m_fftsize * sizeof(float));
1157 //in place
1158 //riffts(unit->m_outbuf[i], log2n, 1, cosTable[log2n]);
1159 scfft_doifft(unit->m_scfftR[i]);
1164 if ( unit->m_cfpos < unit->m_cflength ) // do crossfade
1166 if ( unit->m_curbuf == 0 ){
1167 p2L= unit->m_fftbuf3[0];
1168 p2R= unit->m_fftbuf3[1];
1169 } else {
1170 p2L= unit->m_fftbuf2[0];
1171 p2R= unit->m_fftbuf2[1];
1174 // p1[0] *= p2[0];
1175 // p1[1] *= p2[1];
1177 // float * p3tL = unit->m_tempfftbuf[0];
1178 // float * p3tR = unit->m_tempfftbuf[1];
1180 //complex multiply
1181 for (int i=1; i<numbins; ++i)
1183 float realL,imagL;
1184 float realR,imagR;
1185 int realind,imagind;
1186 realind= 2*i; imagind= realind+1;
1187 realL= p1[realind]*p2L[realind]- p1[imagind]*p2L[imagind];
1188 imagL= p1[realind]*p2L[imagind]+ p1[imagind]*p2L[realind];
1189 realR= p1[realind]*p2R[realind]- p1[imagind]*p2R[imagind];
1190 imagR= p1[realind]*p2R[imagind]+ p1[imagind]*p2R[realind];
1191 p3L[realind] = realL; //p2->bin[i];
1192 p3L[imagind] = imagL;
1193 p3R[realind] = realR; //p2->bin[i];
1194 p3R[imagind] = imagR;
1197 scfft_doifft(unit->m_scfftR2[0]);
1198 scfft_doifft(unit->m_scfftR2[1]);
1199 //riffts(unit->m_tempbuf[0], log2n, 1, cosTable[log2n]);
1200 //riffts(unit->m_tempbuf[1], log2n, 1, cosTable[log2n]);
1202 // now crossfade between outbuf and tempbuf
1203 float fact1 = (float) unit->m_cfpos/unit->m_cflength; // crossfade amount startpoint
1204 float rc = 1.f/(unit->m_cflength*unit->m_insize); //crossfade amount increase per sample
1205 float * p4L = unit->m_outbuf[0];
1206 float * p5L = unit->m_tempbuf[0];
1207 float * p4R = unit->m_outbuf[1];
1208 float * p5R = unit->m_tempbuf[1];
1209 for ( int i=0; i < unit->m_insize; i++ )
1211 float res;
1212 res = (1-fact1)*p4L[i] + fact1*p5L[i];
1213 p4L[i] = res;
1214 res = (1-fact1)*p4R[i] + fact1*p5R[i];
1215 p4R[i] = res;
1216 fact1 += rc;
1218 if ( unit->m_cflength == 1 ) // in the overlap the convolution is already at the new buffer
1220 memcpy(unit->m_outbuf[0]+unit->m_insize, unit->m_tempbuf[0]+unit->m_insize,unit->m_insize * sizeof(float));
1221 memcpy(unit->m_outbuf[1]+unit->m_insize, unit->m_tempbuf[1]+unit->m_insize,unit->m_insize * sizeof(float));
1223 else
1225 for ( int i=unit->m_insize+1; i < unit->m_fftsize; i++ )
1227 float res;
1228 res = (1-fact1)*p4L[i] + fact1*p5L[i];
1229 p4L[i] = res;
1230 res = (1-fact1)*p4R[i] + fact1*p5R[i];
1231 p4R[i] = res;
1232 fact1 += rc;
1235 unit->m_cfpos++;
1236 if ( unit->m_cfpos == unit->m_cflength ) // at end of crossfade, update the current buffer index
1238 if ( unit->m_curbuf == 0 )
1239 unit->m_curbuf = 1;
1240 else
1241 unit->m_curbuf = 0;
1246 //write out samples copied from outbuf, with overlap added in
1248 float *outputL = ZOUT(0);
1249 float *outputR = ZOUT(1);
1250 float *outL= unit->m_outbuf[0]+unit->m_pos;
1251 float *overlapL= unit->m_overlapbuf[0]+unit->m_pos;
1252 float *outR= unit->m_outbuf[1]+unit->m_pos;
1253 float *overlapR= unit->m_overlapbuf[1]+unit->m_pos;
1254 unit->m_prevtrig = curtrig;
1256 for (int i=0; i<numSamples; ++i) {
1257 *++outputL = *++outL + *++overlapL;
1258 *++outputR = *++outR + *++overlapR;
1262 void Convolution3_Ctor(Convolution3 *unit)
1264 unit->m_insize=(int)ZIN0(3); //could be input parameter
1266 float fbufnum = ZIN0(1);
1267 uint32 bufnum = (int)fbufnum;
1269 World *world = unit->mWorld;
1270 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
1271 //SndBuf *buf = world->mSndBufs + bufnum;
1272 SndBuf *buf = ConvGetBuffer(unit,bufnum);
1274 if (buf) {
1275 if ( unit->m_insize <= 0 ) // if smaller than zero, equal to size of buffer
1277 unit->m_insize=buf->frames; //could be input parameter
1280 // printf("hello %i\n", unit->m_insize);
1281 //just use memory for the input buffers and out buffer
1282 int insize = unit->m_insize * sizeof(float);
1284 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
1285 unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
1287 LOCK_SNDBUF_SHARED(buf);
1288 //calculate fft for kernel straight away
1289 memcpy(unit->m_inbuf2, buf->data, insize);
1290 //test for full input buffer
1291 // unit->m_mask = unit->m_insize;
1292 unit->m_pos = 0;
1294 unit->m_outbuf = (float*)RTAlloc(unit->mWorld, insize);
1295 memset(unit->m_outbuf, 0, insize);
1296 unit->m_prevtrig = 0.f;
1297 if ( INRATE(0) == calc_FullRate )
1298 SETCALC(Convolution3_next_a);
1299 else
1300 SETCALC(Convolution3_next_k);
1304 void Convolution3_Dtor(Convolution3 *unit)
1306 RTFree(unit->mWorld, unit->m_inbuf1);
1307 RTFree(unit->mWorld, unit->m_inbuf2);
1308 RTFree(unit->mWorld, unit->m_outbuf);
1311 void Convolution3_next_a(Convolution3 *unit)
1313 float *in = IN(0);
1314 float curtrig = ZIN0(2);
1316 float *pin1 = unit->m_inbuf1;
1318 int numSamples = unit->mWorld->mFullRate.mBufLength;
1319 uint32 insize=unit->m_insize * sizeof(float);
1321 // copy input
1322 Copy(numSamples, pin1, in);
1324 if (unit->m_prevtrig <= 0.f && curtrig > 0.f)
1326 uint32 insize=unit->m_insize * sizeof(float);
1327 float fbufnum = ZIN0(1);
1328 // int log2n2 = unit->m_log2n;
1329 uint32 bufnum = (int)fbufnum;
1330 // printf("bufnum %i \n", bufnum);
1331 World *world = unit->mWorld;
1332 SndBuf *buf = ConvGetBuffer(unit,bufnum);
1333 LOCK_SNDBUF_SHARED(buf);
1335 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
1336 //SndBuf *buf = world->mSndBufs + bufnum;
1337 memcpy(unit->m_inbuf2, buf->data, insize);
1340 float * pin2= unit->m_inbuf2;
1341 float * pout=unit->m_outbuf;
1342 int pos = unit->m_pos;
1343 int size = unit->m_insize;
1345 for ( int j=0; j < numSamples; ++j)
1347 float input = pin1[j];
1348 for ( int i=0; i < size; ++i )
1350 int ind = (pos+i+j)%(size);
1351 pout[ind] = pout[ind] + pin2[i]*input;
1355 float *output = ZOUT(0);
1357 for (int i=0; i<numSamples; ++i) {
1358 int ind = (pos+i)%(size);
1359 *++output = pout[ind];
1362 pos = pos + numSamples;
1363 if ( pos > size )
1365 unit->m_pos = pos - size; //reset collection counter
1367 else
1369 unit->m_pos += numSamples;
1371 unit->m_prevtrig = curtrig;
1375 void Convolution3_next_k(Convolution3 *unit)
1377 float input = ZIN0(0);
1378 // float *in2 = IN(1);
1379 float curtrig = ZIN0(2);
1381 float *out1 = unit->m_inbuf1 + unit->m_pos;
1382 // float *out2 = unit->m_inbuf2 + unit->m_pos;
1384 int numSamples = unit->mWorld->mFullRate.mBufLength;
1385 uint32 insize=unit->m_insize * sizeof(float);
1388 if (unit->m_prevtrig <= 0.f && curtrig > 0.f)
1390 float fbufnum = ZIN0(1);
1391 // int log2n2 = unit->m_log2n;
1392 uint32 bufnum = (int)fbufnum;
1393 // printf("bufnum %i \n", bufnum);
1394 World *world = unit->mWorld;
1395 SndBuf *buf= ConvGetBuffer(unit,bufnum);
1396 LOCK_SNDBUF_SHARED(buf);
1398 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
1399 //SndBuf *buf = world->mSndBufs + bufnum;
1400 memcpy(unit->m_inbuf2, buf->data, insize);
1403 float * pin= unit->m_inbuf2;
1404 float * pout=unit->m_outbuf;
1405 int pos = unit->m_pos;
1406 int size = unit->m_insize;
1408 for ( int i=0; i < size; ++i )
1410 int ind = (pos+i)%(size);
1411 pout[ind] = pout[ind] + pin[i]*input;
1414 float *output = ZOUT(0);
1415 *output = pout[pos];
1417 if ( ++pos > size )
1418 unit->m_pos = 0; //reset collection counter
1419 else
1420 unit->m_pos++;
1421 unit->m_prevtrig = curtrig;
1424 void initConvolution(InterfaceTable *it)
1426 DefineDtorUnit(Convolution);
1427 DefineDtorUnit(Convolution2);
1428 DefineDtorUnit(Convolution2L);
1429 DefineDtorUnit(StereoConvolution2L);
1430 DefineDtorUnit(Convolution3);