Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / server / plugins / Convolution.cpp
blobe3b0d7b3de474765948abb4ab8ebb7a01c7b6fd0
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"
32 #include <stdio.h>
35 //float *fftWindow[32];
37 struct Convolution : Unit
39 int m_pos, m_insize, m_fftsize;
40 //int m_log2n;
41 float *m_inbuf1,*m_inbuf2, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf;
42 scfft *m_scfft1, *m_scfft2, *m_scfftR;
46 struct Convolution2 : Unit
48 int m_pos, m_insize, m_fftsize; //,m_mask;
49 //int m_log2n;
50 float m_prevtrig;
51 float *m_inbuf1, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf;
52 scfft *m_scfft1, *m_scfft2, *m_scfftR;
55 struct Convolution2L : Unit
57 int m_pos, m_insize, m_fftsize; //,m_mask;
58 int m_cfpos, m_cflength, m_curbuf; // for crossfading
59 int m_log2n;
60 float m_prevtrig;
61 float *m_inbuf1, *m_fftbuf1, *m_fftbuf2, *m_outbuf,*m_overlapbuf;
62 float *m_tempbuf, *m_fftbuf3; // for crossfading
64 scfft *m_scfft1, *m_scfft2, *m_scfft3, *m_scfftR, *m_scfftR2; //source plus two kernels forwards, and two inverse from outbuf and from tempbuf
68 //could be done also using complex signal fft and appropriate unwrapping, but sc_fft doesn't support that
69 struct StereoConvolution2L : Unit
71 int m_pos, m_insize, m_fftsize; //,m_mask;
72 int m_cfpos, m_cflength, m_curbuf; // for crossfading
73 int m_log2n;
74 float m_prevtrig;
75 float *m_inbuf1, *m_fftbuf1; // input
76 float *m_fftbuf2[2], *m_outbuf[2],*m_overlapbuf[2]; // output
77 float *m_tempbuf[2], *m_fftbuf3[2]; // for crossfading
79 scfft *m_scfft1, *m_scfft2[2], *m_scfft3[2], *m_scfftR[2], *m_scfftR2[2];
82 struct Convolution3 : Unit
84 int m_pos, m_insize;
85 float m_prevtrig;
86 float *m_inbuf1, *m_inbuf2, *m_outbuf;
89 //////////////////////////////////////////////////////////////////////////////////////////////////
91 extern "C"
93 void Convolution_next(Convolution *unit, int wrongNumSamples);
94 void Convolution_Ctor(Convolution *unit);
95 void Convolution_Dtor(Convolution *unit);
97 void Convolution2_next(Convolution2 *unit, int wrongNumSamples);
98 //void Convolution2_next2(Convolution2 *unit, int wrongNumSamples);
99 void Convolution2_Ctor(Convolution2 *unit);
100 void Convolution2_Dtor(Convolution2 *unit);
102 void Convolution2L_next(Convolution2L *unit, int wrongNumSamples);
103 void Convolution2L_Ctor(Convolution2L *unit);
104 void Convolution2L_Dtor(Convolution2L *unit);
106 void StereoConvolution2L_next(StereoConvolution2L *unit, int wrongNumSamples);
107 void StereoConvolution2L_Ctor(StereoConvolution2L *unit);
108 void StereoConvolution2L_Dtor(StereoConvolution2L *unit);
110 void Convolution3_next_a(Convolution3 *unit);
111 void Convolution3_next_k(Convolution3 *unit);
112 void Convolution3_Ctor(Convolution3 *unit);
113 void Convolution3_Dtor(Convolution3 *unit);
117 ////////////////////////////////////////////////////////////////////////////////////////////////////////
119 //PROPER CONVOLVER
120 //two possibilities- fixed kernel (in which case can derive the kernel spectrum in the constructor)
121 //and changing kernel (same size as target)
123 void Convolution_Ctor(Convolution *unit)
125 //require size N+M-1 to be a power of two
126 unit->m_insize=(int)ZIN0(2);
128 // printf("hello %i /n", unit->m_insize);
129 unit->m_fftsize=2*(unit->m_insize);
130 //just use memory for the input buffers and fft buffers
131 int insize = unit->m_insize * sizeof(float);
132 int fftsize = unit->m_fftsize * sizeof(float);
134 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
135 unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
136 unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
137 unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);
139 unit->m_outbuf = (float*)RTAlloc(unit->mWorld, fftsize);
140 unit->m_overlapbuf = (float*)RTAlloc(unit->mWorld, insize);
142 memset(unit->m_outbuf, 0, fftsize);
143 memset(unit->m_overlapbuf, 0, insize);
145 //unit->m_log2n = LOG2CEIL(unit->m_fftsize);
147 unit->m_pos = 0;
149 SCWorld_Allocator alloc(ft, unit->mWorld);
150 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
151 unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
152 unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc);
154 SETCALC(Convolution_next);
158 void Convolution_Dtor(Convolution *unit)
160 RTFree(unit->mWorld, unit->m_inbuf1);
161 RTFree(unit->mWorld, unit->m_inbuf2);
162 RTFree(unit->mWorld, unit->m_fftbuf1);
163 RTFree(unit->mWorld, unit->m_fftbuf2);
164 RTFree(unit->mWorld, unit->m_outbuf);
165 RTFree(unit->mWorld, unit->m_overlapbuf);
166 SCWorld_Allocator alloc(ft, unit->mWorld);
167 scfft_destroy(unit->m_scfft1, alloc);
168 scfft_destroy(unit->m_scfft2, alloc);
169 scfft_destroy(unit->m_scfftR, alloc);
173 void Convolution_next(Convolution *unit, int numSamples)
175 float *in1 = IN(0);
176 float *in2 = IN(1);
178 float *out1 = unit->m_inbuf1 + unit->m_pos;
179 float *out2 = unit->m_inbuf2 + unit->m_pos;
181 //int numSamples = unit->mWorld->mFullRate.mBufLength;
183 // copy input
184 Copy(numSamples, out1, in1);
185 Copy(numSamples, out2, in2);
187 unit->m_pos += numSamples;
189 int insize= unit->m_insize;
191 if (unit->m_pos & insize) {
192 //have collected enough samples to transform next frame
193 unit->m_pos = 0; //reset collection counter
195 int memsize= insize*sizeof(float);
197 // copy to fftbuf
198 memcpy(unit->m_fftbuf1, unit->m_inbuf1, memsize);
199 memcpy(unit->m_fftbuf2, unit->m_inbuf2, memsize);
201 //zero pad second part of buffer to allow for convolution
202 memset(unit->m_fftbuf1+unit->m_insize, 0, memsize);
203 memset(unit->m_fftbuf2+unit->m_insize, 0, memsize);
205 // do fft
207 //in place transform for now
209 //old Green fft code, now replaced by scfft
210 // int log2n = unit->m_log2n;
211 // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
212 // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
213 scfft_dofft(unit->m_scfft1);
214 scfft_dofft(unit->m_scfft2);
216 //complex multiply time
217 float * p1= unit->m_fftbuf1;
218 float * p2= unit->m_fftbuf2;
220 p1[0] *= p2[0];
221 p1[1] *= p2[1];
223 //complex multiply
224 for (int i=1; i<insize; ++i) {
225 float real,imag;
226 int realind,imagind;
227 realind= 2*i; imagind= realind+1;
228 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
229 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
231 p1[realind] = real;
232 p1[imagind]= imag;
235 //copy second part from before to overlap
236 memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, memsize);
238 //inverse fft into outbuf
239 memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
241 //in place
242 //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
243 scfft_doifft(unit->m_scfftR);
246 //write out samples copied from outbuf, with overlap added in
248 float *output = ZOUT(0);
249 float *out= unit->m_outbuf+unit->m_pos;
250 float *overlap= unit->m_overlapbuf+unit->m_pos;
252 for (int i=0; i<numSamples; ++i)
253 ZXP(output) = out[i] + overlap[i];
258 //include local buffer test in one place
259 static SndBuf * ConvGetBuffer(Unit * unit, uint32 bufnum, const char * ugenName, int inNumSamples)
261 SndBuf *buf;
262 World *world = unit->mWorld;
264 if (bufnum >= world->mNumSndBufs) {
265 int localBufNum = bufnum - world->mNumSndBufs;
266 Graph *parent = unit->mParent;
267 if (localBufNum <= parent->localMaxBufNum) {
268 buf = parent->mLocalSndBufs + localBufNum;
269 } else {
270 if (unit->mWorld->mVerbosity > -1)
271 Print("%s: invalid buffer number (%d).\n", ugenName, bufnum);
272 goto handle_failure;
274 } else {
275 buf = world->mSndBufs + bufnum;
278 if (buf->data == NULL) {
279 if (unit->mWorld->mVerbosity > -1)
280 Print("%s: uninitialized buffer (%i).\n", ugenName, bufnum);
281 goto handle_failure;
284 return buf;
286 handle_failure:
287 SETCALC(*ClearUnitOutputs);
288 ClearUnitOutputs(unit, inNumSamples);
289 unit->mDone = true;
290 return NULL;
295 void Convolution2_Ctor(Convolution2 *unit)
297 //require size N+M-1 to be a power of two
299 unit->m_insize=(int)ZIN0(3); //could be input parameter
300 // printf( "unit->m_insize %i\n", unit->m_insize );
301 // printf( "unit->mWorld->mFullRate.mBufLength %i\n", unit->mWorld->mFullRate.mBufLength );
303 //float fbufnum = ZIN0(1);
304 uint32 bufnum = (int)ZIN0(1); //fbufnum;
305 World *world = unit->mWorld;
307 //before added check for LocalBuf
308 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
309 // SndBuf *buf = world->mSndBufs + bufnum;
311 SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution2", 1);
313 if(buf) {
314 if ( unit->m_insize <= 0 ) // if smaller than zero, equal to size of buffer
315 unit->m_insize=buf->frames; //could be input parameter
317 unit->m_fftsize=2*(unit->m_insize);
318 //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
319 //just use memory for the input buffers and fft buffers
320 int insize = unit->m_insize * sizeof(float);
321 int fftsize = unit->m_fftsize * sizeof(float);
324 // unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
325 //// unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
327 // unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
328 // unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);
331 unit->m_inbuf1 = (float*)RTAlloc(world, insize);
332 unit->m_fftbuf1 = (float*)RTAlloc(world, fftsize);
333 unit->m_fftbuf2 = (float*)RTAlloc(world, fftsize);
335 unit->m_outbuf = (float*)RTAlloc(world, fftsize);
336 unit->m_overlapbuf = (float*)RTAlloc(world, insize);
338 memset(unit->m_outbuf, 0, fftsize);
339 memset(unit->m_overlapbuf, 0, insize);
341 //unit->m_log2n = LOG2CEIL(unit->m_fftsize);
343 unit->m_pos = 0;
344 memset(unit->m_outbuf, 0, fftsize);
345 memset(unit->m_overlapbuf, 0, insize);
347 SCWorld_Allocator alloc(ft, unit->mWorld);
348 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
349 unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
350 unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc);
352 //calculate fft for kernel straight away
353 memcpy(unit->m_fftbuf2, buf->data, insize);
354 //zero pad second part of buffer to allow for convolution
355 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
357 scfft_dofft(unit->m_scfft2);
359 unit->m_pos = 0;
361 // unit->m_log2n = LOG2CEIL(unit->m_fftsize);
363 // int log2n = unit->m_log2n;
365 // //test for full input buffer
366 // //unit->m_mask = unit->m_insize;
368 // //in place transform for now
369 // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
371 unit->m_prevtrig = 0.f;
372 unit->m_prevtrig = ZIN0(2);
374 // printf( "unit->m_insize %i\n", unit->m_insize );
375 // printf( "world->mFullRate.mBufLength %i\n", world->mFullRate.mBufLength );
377 if ( unit->m_insize >= world->mFullRate.mBufLength )
379 // printf( "insize bigger than blocksize\n" );
380 SETCALC(Convolution2_next);
382 else
384 printf( "Convolution2 framesize smaller than blocksize \n" );
385 SETCALC(*ClearUnitOutputs);
386 unit->mDone = true;
387 //SETCALC(Convolution2_next2);
389 } else {
390 unit->m_scfft2 = unit->m_scfft1 = unit->m_scfftR = NULL;
394 void Convolution2_Dtor(Convolution2 *unit)
396 RTFree(unit->mWorld, unit->m_inbuf1);
397 // RTFree(unit->mWorld, unit->m_inbuf2);
398 RTFree(unit->mWorld, unit->m_fftbuf1);
399 RTFree(unit->mWorld, unit->m_fftbuf2);
400 RTFree(unit->mWorld, unit->m_outbuf);
401 RTFree(unit->mWorld, unit->m_overlapbuf);
403 SCWorld_Allocator alloc(ft, unit->mWorld);
404 scfft_destroy(unit->m_scfft1, alloc);
405 scfft_destroy(unit->m_scfft2, alloc);
406 scfft_destroy(unit->m_scfftR, alloc);
410 void Convolution2_next(Convolution2 *unit, int wrongNumSamples)
412 float *in1 = IN(0);
413 //float *in2 = IN(1);
414 float curtrig = ZIN0(2);
416 float *out1 = unit->m_inbuf1 + unit->m_pos;
417 // float *out2 = unit->m_inbuf2 + unit->m_pos;
419 int numSamples = unit->mWorld->mFullRate.mBufLength;
420 uint32 insize=unit->m_insize * sizeof(float);
422 // copy input
423 Copy(numSamples, out1, in1);
425 unit->m_pos += numSamples;
427 if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
428 //float fbufnum = ZIN0(1);
429 //int log2n2 = unit->m_log2n;
430 //uint32 bufnum = (int)fbufnum;
431 //printf("bufnum %i \n", bufnum);
432 //World *world = unit->mWorld;
433 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
434 //SndBuf *buf = world->mSndBufs + bufnum;
436 SndBuf *buf = ConvGetBuffer(unit,(uint32)ZIN0(1), "Convolution2", numSamples);
437 if (!buf)
438 return;
439 LOCK_SNDBUF_SHARED(buf);
441 memcpy(unit->m_fftbuf2, buf->data, insize);
442 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
443 //rffts(unit->m_fftbuf2, log2n2, 1, cosTable[log2n2]);
445 scfft_dofft(unit->m_scfft2);
448 if (unit->m_pos & unit->m_insize) {
450 //have collected enough samples to transform next frame
451 unit->m_pos = 0; //reset collection counter
453 // copy to fftbuf
454 //int log2n = unit->m_log2n;
456 memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
458 //zero pad second part of buffer to allow for convolution
459 memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
460 //if (unit->m_prevtrig <= 0.f && curtrig > 0.f)
462 scfft_dofft(unit->m_scfft1);
464 //in place transform for now
465 // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
467 //complex multiply time
468 int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
470 float * p1= unit->m_fftbuf1;
471 float * p2= unit->m_fftbuf2;
473 p1[0] *= p2[0];
474 p1[1] *= p2[1];
476 //complex multiply
477 for (int i=1; i<numbins; ++i) {
478 float real,imag;
479 int realind,imagind;
480 realind= 2*i; imagind= realind+1;
481 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
482 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
483 p1[realind] = real; //p2->bin[i];
484 p1[imagind]= imag;
487 //copy second part from before to overlap
488 memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, insize);
490 //inverse fft into outbuf
491 memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
493 //in place
494 //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
496 scfft_doifft(unit->m_scfftR);
498 // DoWindowing(log2n, unit->m_outbuf, unit->m_fftsize);
501 //write out samples copied from outbuf, with overlap added in
503 float *output = ZOUT(0);
504 float *out= unit->m_outbuf+unit->m_pos;
505 float *overlap= unit->m_overlapbuf+unit->m_pos;
506 unit->m_prevtrig = curtrig;
508 for (int i=0; i<numSamples; ++i)
509 ZXP(output) = out[i] + overlap[i];
514 // flawed since assumes framesize at least divides blocksize. framesize has to be power of two anyway: commenting out pending deletion
515 //// if kernel size is smaller than server block size (note: this is not working yet...
516 //void Convolution2_next2(Convolution2 *unit, int wrongNumSamples)
519 // float *in1 = IN(0);
520 // //float *in2 = IN(1);
521 // float curtrig = ZIN0(2);
523 // float *out1 = unit->m_inbuf1; // unit->m_pos is now a pointer into the *in1 buffer
524 //// float *out2 = unit->m_inbuf2 + unit->m_pos;
526 // unit->m_pos = 0;
528 // int numSamples = unit->mWorld->mFullRate.mBufLength;
529 // uint32 insize=unit->m_insize * sizeof(float);
531 // int numTimes = numSamples / unit->m_insize;
533 //// replace buffer if there was a trigger
534 // if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
535 // float fbufnum = ZIN0(1);
536 // int log2n2 = unit->m_log2n;
537 // uint32 bufnum = (int)fbufnum;
538 // //printf("bufnum %i \n", bufnum);
539 // World *world = unit->mWorld;
540 // if (bufnum >= world->mNumSndBufs) bufnum = 0;
541 // SndBuf *buf = world->mSndBufs + bufnum;
543 // memcpy(unit->m_fftbuf2, buf->data, insize);
544 // memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
545 // //DoWindowing(log2n2, unit->m_fftbuf2, unit->m_fftsize);
546 // rffts(unit->m_fftbuf2, log2n2, 1, cosTable[log2n2]);
547 // }
549 // for ( int i=0; i < numTimes; i++ )
550 // {
551 // // copy input
552 // Copy(unit->m_insize, out1, in1 + unit->m_pos);
553 // unit->m_pos += unit->m_insize;
555 // //have collected enough samples to transform next frame
556 // // copy to fftbuf
557 // int log2n = unit->m_log2n;
559 // memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
560 // //zero pad second part of buffer to allow for convolution
561 // memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
563 // //in place transform for now
564 // rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
566 // //complex multiply time
567 // int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
569 // float * p1= unit->m_fftbuf1;
570 // float * p2= unit->m_fftbuf2;
572 // p1[0] *= p2[0];
573 // p1[1] *= p2[1];
575 // //complex multiply
576 // for (int i=1; i<numbins; ++i) {
577 // float real,imag;
578 // int realind,imagind;
579 // realind= 2*i; imagind= realind+1;
580 // real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
581 // imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
582 // p1[realind] = real; //p2->bin[i];
583 // p1[imagind]= imag;
584 // }
586 // //copy second part from before to overlap
587 // memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, unit->m_insize * sizeof(float));
589 // //inverse fft into outbuf
590 // memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
592 // //in place
593 // riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
595 // //write out samples copied from outbuf, with overlap added in
596 // float *output = ZOUT(0);
597 // float *out= unit->m_outbuf;
598 // float *overlap= unit->m_overlapbuf;
600 // for (int i=0; i<unit->m_insize; ++i) {
601 // *++output = *++out + *++overlap;
602 // }
603 // }
604 // unit->m_prevtrig = curtrig;
607 void Convolution2L_Ctor(Convolution2L *unit)
609 //require size N+M-1 to be a power of two
610 //transform samp=
612 unit->m_insize=(int)ZIN0(3); //could be input parameter
613 unit->m_cflength = (int)ZIN0(4); // could be input parameter
614 unit->m_curbuf = 0;
615 unit->m_cfpos = unit->m_cflength;
618 unit->m_fftsize=2*(unit->m_insize);
619 //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
620 //just use memory for the input buffers and fft buffers
621 int insize = unit->m_insize * sizeof(float);
622 int fftsize = unit->m_fftsize * sizeof(float);
624 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
625 // unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
627 unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
628 unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);
629 unit->m_fftbuf3 = (float*)RTAlloc(unit->mWorld, fftsize);
630 unit->m_tempbuf = (float*)RTAlloc(unit->mWorld, fftsize);
632 //float fbufnum = ZIN0(1);
633 uint32 bufnum = (int)ZIN0(1); //fbufnum;
634 //printf("bufnum %i \n", bufnum);
635 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
636 //SndBuf *buf = world->mSndBufs + bufnum;
638 SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution2L", 1);
640 if(buf) {
641 unit->m_outbuf = (float*)RTAlloc(unit->mWorld, fftsize);
642 unit->m_overlapbuf = (float*)RTAlloc(unit->mWorld, insize);
644 memset(unit->m_outbuf, 0, fftsize);
645 memset(unit->m_overlapbuf, 0, insize);
647 //calculate fft for kernel straight away
648 memcpy(unit->m_fftbuf2, buf->data, insize);
649 //zero pad second part of buffer to allow for convolution
650 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
652 SCWorld_Allocator alloc(ft, unit->mWorld);
653 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
654 unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
655 unit->m_scfft3 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf3, unit->m_fftbuf3, kForward, alloc);
656 unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_outbuf, unit->m_outbuf, kBackward, alloc);
657 unit->m_scfftR2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_tempbuf, unit->m_tempbuf, kBackward, alloc);
659 scfft_dofft(unit->m_scfft2);
661 unit->m_pos = 0;
665 // //calculate fft for kernel straight away
666 // memcpy(unit->m_fftbuf2, buf->data, insize);
667 // //zero pad second part of buffer to allow for convolution
668 // memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
670 // unit->m_log2n = LOG2CEIL(unit->m_fftsize);
672 // int log2n = unit->m_log2n;
674 // //test for full input buffer
675 // unit->m_mask = unit->m_insize;
678 // // do windowing
679 //// DoWindowing(log2n, unit->m_fftbuf2, unit->m_fftsize);
681 // //in place transform for now
682 // rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
685 // unit->m_outbuf = (float*)RTAlloc(unit->mWorld, fftsize);
686 // unit->m_overlapbuf = (float*)RTAlloc(unit->mWorld, insize);
688 // memset(unit->m_outbuf, 0, fftsize);
689 // memset(unit->m_overlapbuf, 0, insize);
691 unit->m_prevtrig = 0.f;
693 SETCALC(Convolution2L_next);
694 } else {
695 unit->m_scfft1 = unit->m_scfft2 = unit->m_scfft3 = unit->m_scfftR = unit->m_scfftR2 = NULL;
699 void Convolution2L_Dtor(Convolution2L *unit)
701 SCWorld_Allocator alloc(ft, unit->mWorld);
702 scfft_destroy(unit->m_scfft1, alloc);
703 scfft_destroy(unit->m_scfft2, alloc);
704 scfft_destroy(unit->m_scfft3, alloc);
705 scfft_destroy(unit->m_scfftR, alloc);
706 scfft_destroy(unit->m_scfftR2, alloc);
709 RTFree(unit->mWorld, unit->m_inbuf1);
710 // RTFree(unit->mWorld, unit->m_inbuf2);
711 RTFree(unit->mWorld, unit->m_fftbuf1);
712 RTFree(unit->mWorld, unit->m_fftbuf2);
713 RTFree(unit->mWorld, unit->m_fftbuf3);
714 RTFree(unit->mWorld, unit->m_tempbuf);
715 RTFree(unit->mWorld, unit->m_outbuf);
716 RTFree(unit->mWorld, unit->m_overlapbuf);
720 void Convolution2L_next(Convolution2L *unit, int numSamples)
722 float *in1 = IN(0);
723 //float *in2 = IN(1);
724 float curtrig = ZIN0(2);
726 float *out1 = unit->m_inbuf1 + unit->m_pos;
727 // float *out2 = unit->m_inbuf2 + unit->m_pos;
729 //int numSamples = unit->mWorld->mFullRate.mBufLength;
730 int insize=unit->m_insize * sizeof(float);
732 // copy input
733 //Copy(numSamples, out1, in1);
734 memcpy(out1,in1,numSamples*sizeof(float));
736 unit->m_pos += numSamples;
738 //printf("test1\n");
740 if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
742 uint32 bufnum = (int)ZIN0(1);
743 SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution2L", numSamples);
744 if (!buf)
745 return;
747 //float fbufnum = ZIN0(1);
748 // //int log2n2 = unit->m_log2n;
749 // uint32 bufnum = (int)fbufnum;
751 unit->m_cflength = (int)ZIN0(4);
752 //printf("bufnum %i \n", bufnum);
753 //World *world = unit->mWorld;
755 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
756 //SndBuf *buf = world->mSndBufs + bufnum;
758 unit->m_cfpos = 0;
759 if ( unit->m_curbuf == 1 )
761 LOCK_SNDBUF_SHARED(buf);
762 memcpy(unit->m_fftbuf2, buf->data, insize);
763 memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
765 scfft_dofft(unit->m_scfft2);
767 else if ( unit->m_curbuf == 0 )
769 LOCK_SNDBUF_SHARED(buf);
770 memcpy(unit->m_fftbuf3, buf->data, insize);
771 memset(unit->m_fftbuf3+unit->m_insize, 0, insize);
773 scfft_dofft(unit->m_scfft3);
777 if (unit->m_pos & unit->m_insize)
780 //have collected enough samples to transform next frame
781 unit->m_pos = 0; //reset collection counter
783 // copy to fftbuf
784 //int log2n = unit->m_log2n;
786 memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
788 //zero pad second part of buffer to allow for convolution
789 memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
790 //in place transform for now
791 scfft_dofft(unit->m_scfft1);
793 //rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
794 //complex multiply time
795 int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
797 float * p1= unit->m_fftbuf1;
798 float * p2;
799 if ( unit->m_curbuf == 0 )
800 p2 = unit->m_fftbuf2;
801 else
802 p2= unit->m_fftbuf3;
803 float * p3= unit->m_tempbuf;
805 // i don't know what this was supposed to do!
806 // p1[0] *= p2[0];
807 // p1[1] *= p2[1];
809 //complex multiply
810 for (int i=1; i<numbins; ++i)
812 float real,imag;
813 int realind,imagind;
814 realind= 2*i; imagind= realind+1;
815 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
816 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
817 p3[realind] = real; //p2->bin[i];
818 p3[imagind]= imag;
821 //copy second part from before to overlap
822 memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, unit->m_insize * sizeof(float));
823 //inverse fft into outbuf
824 memcpy(unit->m_outbuf, unit->m_tempbuf, unit->m_fftsize * sizeof(float));
825 //in place
826 //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
827 scfft_doifft(unit->m_scfftR);
829 if ( unit->m_cfpos < unit->m_cflength ) // do crossfade
831 if ( unit->m_curbuf == 0 )
832 p2= unit->m_fftbuf3;
833 else
834 p2= unit->m_fftbuf2;
836 // p1[0] *= p2[0];
837 // p1[1] *= p2[1];
839 //complex multiply
840 for (int i=1; i<numbins; ++i)
842 float real,imag;
843 int realind,imagind;
844 realind= 2*i; imagind= realind+1;
845 real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
846 imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
847 p1[realind] = real; //p2->bin[i];
848 p1[imagind]= imag;
851 //copy second part from before to overlap
852 // memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, unit->m_insize * sizeof(float));
853 //inverse fft into tempbuf
854 memcpy(unit->m_tempbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));
855 //in place
856 //riffts(unit->m_tempbuf, log2n, 1, cosTable[log2n]);
857 scfft_doifft(unit->m_scfftR2);
859 // now crossfade between outbuf and tempbuf
860 float fact1 = (float) unit->m_cfpos/unit->m_cflength; // crossfade amount startpoint
861 float rc = 1.f/(unit->m_cflength*unit->m_insize); //crossfade amount increase per sample
862 float * p4 = unit->m_outbuf;
863 float * p5 = unit->m_tempbuf;
864 for ( int i=0; i < unit->m_insize; i++ )
866 float res;
867 res = (1-fact1)*p4[i] + fact1*p5[i];
868 fact1 += rc;
869 p4[i] = res;
871 if ( unit->m_cflength == 1 )
872 memcpy(unit->m_outbuf+unit->m_insize, unit->m_tempbuf+unit->m_insize,insize);
873 else
875 for ( int i=unit->m_insize+1; i < unit->m_fftsize; i++ )
877 float res = (1-fact1)*p4[i] + fact1*p5[i];
878 fact1 += rc;
879 p4[i] = res;
882 unit->m_cfpos++;
883 // printf("cfpos %i, cf_length %i \n", unit->m_cfpos, unit->m_cflength);
884 if ( unit->m_cfpos == unit->m_cflength ) // at end of crossfade, update the current buffer index
886 if ( unit->m_curbuf == 0 )
887 unit->m_curbuf = 1;
888 else
889 unit->m_curbuf = 0;
894 //write out samples copied from outbuf, with overlap added in
896 float *output = ZOUT(0);
897 float *out= unit->m_outbuf+unit->m_pos;
898 float *overlap= unit->m_overlapbuf+unit->m_pos;
899 unit->m_prevtrig = curtrig;
901 for (int i=0; i<numSamples; ++i)
902 ZXP(output) = out[i] + overlap[i];
905 /** basically the same as Convolution2L, but takes a stereo buffer to convolve with and outputs a stereo signal */
906 void StereoConvolution2L_Ctor(StereoConvolution2L *unit)
908 //require size N+M-1 to be a power of two
909 //transform samp=
911 unit->m_insize=(int)ZIN0(4); //could be input parameter
912 unit->m_cflength = (int)ZIN0(5); // could be input parameter
913 unit->m_curbuf = 0;
914 unit->m_cfpos = unit->m_cflength;
916 unit->m_fftsize=2*(unit->m_insize);
917 //printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
918 //just use memory for the input buffers and fft buffers
919 int insize = unit->m_insize * sizeof(float);
920 int fftsize = unit->m_fftsize * sizeof(float);
922 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
923 // unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
925 // source:
926 unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
928 // 2 channel buffer:
929 unit->m_fftbuf2[0] = (float*)RTAlloc(unit->mWorld, fftsize);
930 unit->m_fftbuf2[1] = (float*)RTAlloc(unit->mWorld, fftsize);
931 unit->m_fftbuf3[0] = (float*)RTAlloc(unit->mWorld, fftsize);
932 unit->m_fftbuf3[1] = (float*)RTAlloc(unit->mWorld, fftsize);
933 unit->m_tempbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
934 unit->m_tempbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
935 // unit->m_tempfftbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
936 // unit->m_tempfftbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
938 unit->m_outbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
939 unit->m_overlapbuf[0] = (float*)RTAlloc(unit->mWorld, insize);
940 unit->m_outbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
941 unit->m_overlapbuf[1] = (float*)RTAlloc(unit->mWorld, insize);
943 memset(unit->m_outbuf[0], 0, fftsize);
944 memset(unit->m_overlapbuf[0], 0, insize);
945 memset(unit->m_outbuf[1], 0, fftsize);
946 memset(unit->m_overlapbuf[1], 0, insize);
948 SCWorld_Allocator alloc(ft, unit->mWorld);
949 unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
950 unit->m_scfft2[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2[0], unit->m_fftbuf2[0], kForward, alloc);
951 unit->m_scfft3[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2[1], unit->m_fftbuf2[1], kForward, alloc);
952 unit->m_scfftR[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf3[0], unit->m_fftbuf3[0], kForward, alloc);
953 unit->m_scfftR2[0] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf3[1], unit->m_fftbuf3[1], kForward, alloc);
954 unit->m_scfft2[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_outbuf[0], unit->m_outbuf[0], kBackward, alloc);
955 unit->m_scfft3[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_tempbuf[0], unit->m_tempbuf[0], kBackward, alloc);
956 unit->m_scfftR[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_outbuf[1], unit->m_outbuf[1], kBackward, alloc);
957 unit->m_scfftR2[1] = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_tempbuf[1], unit->m_tempbuf[1], kBackward, alloc);
959 float fbufnum = ZIN0(1);
960 uint32 bufnumL = (int)fbufnum;
961 fbufnum = ZIN0(2);
962 uint32 bufnumR = (int)fbufnum;
963 //printf("bufnum %i \n", bufnum);
965 //unit->m_log2n = LOG2CEIL(unit->m_fftsize);
966 //int log2n = unit->m_log2n;
968 SndBuf *buf = ConvGetBuffer(unit, bufnumL, "StereoConvolution2L", 1);
970 if (buf) {
971 LOCK_SNDBUF_SHARED(buf);
973 // if (bufnumL >= world->mNumSndBufs) bufnumL = 0;
974 // SndBuf *buf = world->mSndBufs + bufnumL;
976 //calculate fft for kernel straight away
977 memcpy(unit->m_fftbuf2[0], buf->data, insize);
978 //zero pad second part of buffer to allow for convolution
979 memset(unit->m_fftbuf2[0]+unit->m_insize, 0, insize);
980 //in place transform for now
981 //rffts(unit->m_fftbuf2[0], log2n, 1, cosTable[log2n]);
982 scfft_dofft(unit->m_scfft2[0]);
983 } else
984 return;
986 buf = ConvGetBuffer(unit, bufnumR, "StereoConvolution2L", 1);
987 if (buf) {
988 LOCK_SNDBUF(buf);
990 //if (bufnumR >= world->mNumSndBufs) bufnumR = 0;
991 //buf = world->mSndBufs + bufnumR;
993 //calculate fft for kernel straight away
994 memcpy(unit->m_fftbuf2[1], buf->data, insize);
995 //zero pad second part of buffer to allow for convolution
996 memset(unit->m_fftbuf2[1]+unit->m_insize, 0, insize);
997 //in place transform for now
998 //rffts(unit->m_fftbuf2[1], log2n, 1, cosTable[log2n]);
999 scfft_dofft(unit->m_scfft2[1]);
1001 //test for full input buffer
1002 //unit->m_mask = unit->m_insize;
1003 unit->m_pos = 0;
1005 // unit->m_outbuf[0] = (float*)RTAlloc(unit->mWorld, fftsize);
1006 // unit->m_overlapbuf[0] = (float*)RTAlloc(unit->mWorld, insize);
1007 // unit->m_outbuf[1] = (float*)RTAlloc(unit->mWorld, fftsize);
1008 // unit->m_overlapbuf[1] = (float*)RTAlloc(unit->mWorld, insize);
1010 // memset(unit->m_outbuf[0], 0, fftsize);
1011 // memset(unit->m_overlapbuf[0], 0, insize);
1012 // memset(unit->m_outbuf[1], 0, fftsize);
1013 // memset(unit->m_overlapbuf[1], 0, insize);
1015 unit->m_prevtrig = 0.f;
1017 SETCALC(StereoConvolution2L_next);
1021 void StereoConvolution2L_Dtor(StereoConvolution2L *unit)
1023 SCWorld_Allocator alloc(ft, unit->mWorld);
1024 scfft_destroy(unit->m_scfft1, alloc);
1025 scfft_destroy(unit->m_scfft2[0], alloc);
1026 scfft_destroy(unit->m_scfft3[0], alloc);
1027 scfft_destroy(unit->m_scfftR[0], alloc);
1028 scfft_destroy(unit->m_scfftR2[0], alloc);
1029 scfft_destroy(unit->m_scfft2[1], alloc);
1030 scfft_destroy(unit->m_scfft3[1], alloc);
1031 scfft_destroy(unit->m_scfftR[1], alloc);
1032 scfft_destroy(unit->m_scfftR2[1], alloc);
1034 RTFree(unit->mWorld, unit->m_inbuf1);
1035 // RTFree(unit->mWorld, unit->m_inbuf2);
1036 RTFree(unit->mWorld, unit->m_fftbuf1);
1037 RTFree(unit->mWorld, unit->m_fftbuf2[0]);
1038 RTFree(unit->mWorld, unit->m_fftbuf3[0]);
1039 RTFree(unit->mWorld, unit->m_tempbuf[0]);
1040 // RTFree(unit->mWorld, unit->m_tempfftbuf[0]);
1041 RTFree(unit->mWorld, unit->m_outbuf[0]);
1042 RTFree(unit->mWorld, unit->m_overlapbuf[0]);
1043 RTFree(unit->mWorld, unit->m_fftbuf2[1]);
1044 RTFree(unit->mWorld, unit->m_fftbuf3[1]);
1045 RTFree(unit->mWorld, unit->m_tempbuf[1]);
1046 // RTFree(unit->mWorld, unit->m_tempfftbuf[1]);
1047 RTFree(unit->mWorld, unit->m_outbuf[1]);
1048 RTFree(unit->mWorld, unit->m_overlapbuf[1]);
1052 void StereoConvolution2L_next(StereoConvolution2L *unit, int wrongNumSamples)
1054 float *in1 = IN(0);
1055 //float *in2 = IN(1);
1056 float curtrig = ZIN0(3);
1058 float *out1 = unit->m_inbuf1 + unit->m_pos;
1059 // float *out2 = unit->m_inbuf2 + unit->m_pos;
1061 int numSamples = unit->mWorld->mFullRate.mBufLength;
1062 uint32 insize=unit->m_insize * sizeof(float);
1064 // copy input
1065 Copy(numSamples, out1, in1);
1067 unit->m_pos += numSamples;
1069 if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
1070 float fbufnum = ZIN0(1);
1071 uint32 bufnumL = (int)fbufnum;
1072 fbufnum = ZIN0(2);
1073 uint32 bufnumR = (int)fbufnum;
1074 unit->m_cflength = (int)ZIN0(5);
1075 //printf("bufnum %i \n", bufnum);
1077 SndBuf *bufL = ConvGetBuffer(unit, bufnumL, "StereoConvolution2L", numSamples);
1078 SndBuf *bufR = ConvGetBuffer(unit, bufnumR, "StereoConvolution2L", numSamples);
1080 if (!bufL || !bufL)
1081 return;
1083 // if (bufnumL >= world->mNumSndBufs) bufnumL = 0;
1084 // SndBuf *bufL = world->mSndBufs + bufnumL;
1085 // if (bufnumR >= world->mNumSndBufs) bufnumR = 0;
1086 // SndBuf *bufR = world->mSndBufs + bufnumR;
1088 unit->m_cfpos = 0;
1089 if ( unit->m_curbuf == 1 )
1091 LOCK_SNDBUF2_SHARED(bufL, bufR);
1092 memcpy(unit->m_fftbuf2[0], bufL->data, insize);
1093 memset(unit->m_fftbuf2[0]+unit->m_insize, 0, insize);
1094 scfft_dofft(unit->m_scfft2[0]);
1095 //rffts(unit->m_fftbuf2[0], log2n2, 1, cosTable[log2n2]);
1096 memcpy(unit->m_fftbuf2[1], bufR->data, insize);
1097 memset(unit->m_fftbuf2[1]+unit->m_insize, 0, insize);
1098 //rffts(unit->m_fftbuf2[1], log2n2, 1, cosTable[log2n2]);
1099 scfft_dofft(unit->m_scfft2[1]);
1101 else if ( unit->m_curbuf == 0 )
1103 LOCK_SNDBUF2_SHARED(bufL, bufR);
1104 memcpy(unit->m_fftbuf3[0], bufL->data, insize);
1105 memset(unit->m_fftbuf3[0]+unit->m_insize, 0, insize);
1106 //rffts(unit->m_fftbuf3[0], log2n2, 1, cosTable[log2n2]);
1107 scfft_dofft(unit->m_scfft3[0]);
1108 memcpy(unit->m_fftbuf3[1], bufR->data, insize);
1109 memset(unit->m_fftbuf3[1]+unit->m_insize, 0, insize);
1110 //rffts(unit->m_fftbuf3[1], log2n2, 1, cosTable[log2n2]);
1111 scfft_dofft(unit->m_scfft3[1]);
1115 if (unit->m_pos & unit->m_insize)
1118 //have collected enough samples to transform next frame
1119 unit->m_pos = 0; //reset collection counter
1121 // copy to fftbuf
1122 //int log2n = unit->m_log2n;
1124 memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);
1126 //zero pad second part of buffer to allow for convolution
1127 memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
1128 //in place transform for now
1129 //rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
1130 scfft_dofft(unit->m_scfft1);
1132 //complex multiply time
1133 int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;
1135 float * p1= unit->m_fftbuf1;
1136 float * p2L, * p2R;
1137 if ( unit->m_curbuf == 0 ){
1138 p2L = unit->m_fftbuf2[0];
1139 p2R = unit->m_fftbuf2[1];
1140 } else {
1141 p2L = unit->m_fftbuf3[0];
1142 p2R = unit->m_fftbuf3[1];
1144 float * p3L = unit->m_tempbuf[0];
1145 float * p3R = unit->m_tempbuf[1];
1147 // what was this supposed to do??
1148 // p1[0] *= p2[0];
1149 // p1[1] *= p2[1];
1151 //complex multiply
1152 for (int i=1; i<numbins; ++i)
1154 float realL,imagL;
1155 float realR,imagR;
1156 int realind,imagind;
1157 realind= 2*i; imagind= realind+1;
1158 realL= p1[realind]*p2L[realind]- p1[imagind]*p2L[imagind];
1159 imagL= p1[realind]*p2L[imagind]+ p1[imagind]*p2L[realind];
1160 realR= p1[realind]*p2R[realind]- p1[imagind]*p2R[imagind];
1161 imagR= p1[realind]*p2R[imagind]+ p1[imagind]*p2R[realind];
1162 p3L[realind] = realL; //p2->bin[i];
1163 p3L[imagind] = imagL;
1164 p3R[realind] = realR; //p2->bin[i];
1165 p3R[imagind] = imagR;
1168 for ( int i=0; i < 2; i++ ){
1169 //copy second part from before to overlap
1170 memcpy(unit->m_overlapbuf[i], unit->m_outbuf[i]+unit->m_insize, unit->m_insize * sizeof(float));
1171 //inverse fft into outbuf
1172 memcpy(unit->m_outbuf[i], unit->m_tempbuf[i], unit->m_fftsize * sizeof(float));
1173 //in place
1174 //riffts(unit->m_outbuf[i], log2n, 1, cosTable[log2n]);
1175 scfft_doifft(unit->m_scfftR[i]);
1180 if ( unit->m_cfpos < unit->m_cflength ) // do crossfade
1182 if ( unit->m_curbuf == 0 ){
1183 p2L= unit->m_fftbuf3[0];
1184 p2R= unit->m_fftbuf3[1];
1185 } else {
1186 p2L= unit->m_fftbuf2[0];
1187 p2R= unit->m_fftbuf2[1];
1190 // p1[0] *= p2[0];
1191 // p1[1] *= p2[1];
1193 // float * p3tL = unit->m_tempfftbuf[0];
1194 // float * p3tR = unit->m_tempfftbuf[1];
1196 //complex multiply
1197 for (int i=1; i<numbins; ++i)
1199 float realL,imagL;
1200 float realR,imagR;
1201 int realind,imagind;
1202 realind= 2*i; imagind= realind+1;
1203 realL= p1[realind]*p2L[realind]- p1[imagind]*p2L[imagind];
1204 imagL= p1[realind]*p2L[imagind]+ p1[imagind]*p2L[realind];
1205 realR= p1[realind]*p2R[realind]- p1[imagind]*p2R[imagind];
1206 imagR= p1[realind]*p2R[imagind]+ p1[imagind]*p2R[realind];
1207 p3L[realind] = realL; //p2->bin[i];
1208 p3L[imagind] = imagL;
1209 p3R[realind] = realR; //p2->bin[i];
1210 p3R[imagind] = imagR;
1213 scfft_doifft(unit->m_scfftR2[0]);
1214 scfft_doifft(unit->m_scfftR2[1]);
1215 //riffts(unit->m_tempbuf[0], log2n, 1, cosTable[log2n]);
1216 //riffts(unit->m_tempbuf[1], log2n, 1, cosTable[log2n]);
1218 // now crossfade between outbuf and tempbuf
1219 float fact1 = (float) unit->m_cfpos/unit->m_cflength; // crossfade amount startpoint
1220 float rc = 1.f/(unit->m_cflength*unit->m_insize); //crossfade amount increase per sample
1221 float * p4L = unit->m_outbuf[0];
1222 float * p5L = unit->m_tempbuf[0];
1223 float * p4R = unit->m_outbuf[1];
1224 float * p5R = unit->m_tempbuf[1];
1225 for ( int i=0; i < unit->m_insize; 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;
1234 if ( unit->m_cflength == 1 ) // in the overlap the convolution is already at the new buffer
1236 memcpy(unit->m_outbuf[0]+unit->m_insize, unit->m_tempbuf[0]+unit->m_insize,unit->m_insize * sizeof(float));
1237 memcpy(unit->m_outbuf[1]+unit->m_insize, unit->m_tempbuf[1]+unit->m_insize,unit->m_insize * sizeof(float));
1239 else
1241 for ( int i=unit->m_insize+1; i < unit->m_fftsize; i++ )
1243 float res;
1244 res = (1-fact1)*p4L[i] + fact1*p5L[i];
1245 p4L[i] = res;
1246 res = (1-fact1)*p4R[i] + fact1*p5R[i];
1247 p4R[i] = res;
1248 fact1 += rc;
1251 unit->m_cfpos++;
1252 if ( unit->m_cfpos == unit->m_cflength ) // at end of crossfade, update the current buffer index
1254 if ( unit->m_curbuf == 0 )
1255 unit->m_curbuf = 1;
1256 else
1257 unit->m_curbuf = 0;
1262 //write out samples copied from outbuf, with overlap added in
1264 float *outputL = ZOUT(0);
1265 float *outputR = ZOUT(1);
1266 float *outL= unit->m_outbuf[0]+unit->m_pos;
1267 float *overlapL= unit->m_overlapbuf[0]+unit->m_pos;
1268 float *outR= unit->m_outbuf[1]+unit->m_pos;
1269 float *overlapR= unit->m_overlapbuf[1]+unit->m_pos;
1270 unit->m_prevtrig = curtrig;
1272 for (int i=0; i<numSamples; ++i) {
1273 ZXP(outputL) = outL[i] + overlapL[i];
1274 ZXP(outputR) = outR[i] + overlapR[i];
1278 void Convolution3_Ctor(Convolution3 *unit)
1280 unit->m_insize=(int)ZIN0(3); //could be input parameter
1282 float fbufnum = ZIN0(1);
1283 uint32 bufnum = (int)fbufnum;
1285 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
1286 //SndBuf *buf = world->mSndBufs + bufnum;
1287 SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution3", 1);
1289 if (buf) {
1290 if ( unit->m_insize <= 0 ) // if smaller than zero, equal to size of buffer
1292 unit->m_insize=buf->frames; //could be input parameter
1295 // printf("hello %i\n", unit->m_insize);
1296 //just use memory for the input buffers and out buffer
1297 int insize = unit->m_insize * sizeof(float);
1299 unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
1300 unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
1302 LOCK_SNDBUF_SHARED(buf);
1303 //calculate fft for kernel straight away
1304 memcpy(unit->m_inbuf2, buf->data, insize);
1305 //test for full input buffer
1306 // unit->m_mask = unit->m_insize;
1307 unit->m_pos = 0;
1309 unit->m_outbuf = (float*)RTAlloc(unit->mWorld, insize);
1310 memset(unit->m_outbuf, 0, insize);
1311 unit->m_prevtrig = 0.f;
1312 if ( INRATE(0) == calc_FullRate )
1313 SETCALC(Convolution3_next_a);
1314 else
1315 SETCALC(Convolution3_next_k);
1319 void Convolution3_Dtor(Convolution3 *unit)
1321 RTFree(unit->mWorld, unit->m_inbuf1);
1322 RTFree(unit->mWorld, unit->m_inbuf2);
1323 RTFree(unit->mWorld, unit->m_outbuf);
1326 void Convolution3_next_a(Convolution3 *unit)
1328 float *in = IN(0);
1329 float curtrig = ZIN0(2);
1331 float *pin1 = unit->m_inbuf1;
1333 int numSamples = unit->mWorld->mFullRate.mBufLength;
1335 // copy input
1336 Copy(numSamples, pin1, in);
1338 if (unit->m_prevtrig <= 0.f && curtrig > 0.f)
1340 uint32 insize=unit->m_insize * sizeof(float);
1341 float fbufnum = ZIN0(1);
1342 // int log2n2 = unit->m_log2n;
1343 uint32 bufnum = (int)fbufnum;
1344 // printf("bufnum %i \n", bufnum);
1345 SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution3", numSamples);
1346 LOCK_SNDBUF_SHARED(buf);
1348 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
1349 //SndBuf *buf = world->mSndBufs + bufnum;
1350 memcpy(unit->m_inbuf2, buf->data, insize);
1353 float * pin2= unit->m_inbuf2;
1354 float * pout=unit->m_outbuf;
1355 int pos = unit->m_pos;
1356 int size = unit->m_insize;
1358 for ( int j=0; j < numSamples; ++j)
1360 float input = pin1[j];
1361 for ( int i=0; i < size; ++i )
1363 int ind = (pos+i+j)%(size);
1364 pout[ind] = pout[ind] + pin2[i]*input;
1368 float *output = ZOUT(0);
1370 for (int i=0; i<numSamples; ++i) {
1371 int ind = (pos+i)%(size);
1372 *++output = pout[ind];
1375 pos = pos + numSamples;
1376 if ( pos > size )
1378 unit->m_pos = pos - size; //reset collection counter
1380 else
1382 unit->m_pos += numSamples;
1384 unit->m_prevtrig = curtrig;
1388 void Convolution3_next_k(Convolution3 *unit)
1390 float input = ZIN0(0);
1391 // float *in2 = IN(1);
1392 float curtrig = ZIN0(2);
1394 // float *out1 = unit->m_inbuf1 + unit->m_pos;
1395 // float *out2 = unit->m_inbuf2 + unit->m_pos;
1397 uint32 insize=unit->m_insize * sizeof(float);
1400 if (unit->m_prevtrig <= 0.f && curtrig > 0.f)
1402 float fbufnum = ZIN0(1);
1403 // int log2n2 = unit->m_log2n;
1404 uint32 bufnum = (int)fbufnum;
1405 // printf("bufnum %i \n", bufnum);
1406 SndBuf *buf= ConvGetBuffer(unit, bufnum, "Convolution3", 1);
1407 if (!buf)
1408 return;
1409 LOCK_SNDBUF_SHARED(buf);
1411 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
1412 //SndBuf *buf = world->mSndBufs + bufnum;
1413 memcpy(unit->m_inbuf2, buf->data, insize);
1416 float * pin= unit->m_inbuf2;
1417 float * pout=unit->m_outbuf;
1418 int pos = unit->m_pos;
1419 int size = unit->m_insize;
1421 for ( int i=0; i < size; ++i )
1423 int ind = (pos+i)%(size);
1424 pout[ind] = pout[ind] + pin[i]*input;
1427 float *output = OUT(0);
1428 *output = pout[pos];
1430 if ( ++pos > size )
1431 unit->m_pos = 0; //reset collection counter
1432 else
1433 unit->m_pos++;
1434 unit->m_prevtrig = curtrig;
1437 void initConvolution(InterfaceTable *it)
1439 DefineDtorUnit(Convolution);
1440 DefineDtorUnit(Convolution2);
1441 DefineDtorUnit(Convolution2L);
1442 DefineDtorUnit(StereoConvolution2L);
1443 DefineDtorUnit(Convolution3);