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
;
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;
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
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
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
84 float *m_inbuf1
, *m_inbuf2
, *m_outbuf
;
87 //////////////////////////////////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////////////////////////////////////////
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);
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
)
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;
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);
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
);
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
;
222 for (int i
=1; i
<insize
; ++i
) {
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
];
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));
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
)
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
;
268 if(unit
->mWorld
->mVerbosity
> -1){ Print("ConvolutionX UGen Buffer Number error: invalid buffer number: %i.\n", bufnum
); }
269 SETCALC(*ClearUnitOutputs
);
274 buf
= world
->mSndBufs
+ bufnum
;
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
);
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);
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
);
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
);
371 printf( "Convolution2 framesize smaller than blocksize \n" );
372 SETCALC(*ClearUnitOutputs
);
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
)
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);
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
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
;
460 for (int i
=1; i
<numbins
; ++i
) {
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];
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));
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;
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]);
532 // for ( int i=0; i < numTimes; i++ )
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
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;
558 // //complex multiply
559 // for (int i=1; i<numbins; ++i) {
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;
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));
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;
587 // unit->m_prevtrig = curtrig;
590 void Convolution2L_Ctor(Convolution2L
*unit
)
592 //require size N+M-1 to be a power of two
595 unit
->m_insize
=(int)ZIN0(3); //could be input parameter
596 unit
->m_cflength
= (int)ZIN0(4); // could be input parameter
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
);
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
);
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;
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
)
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);
717 //Copy(numSamples, out1, in1);
718 memcpy(out1
,in1
,numSamples
*sizeof(float));
720 unit
->m_pos
+= numSamples
;
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;
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
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
;
782 if ( unit
->m_curbuf
== 0 )
783 p2
= unit
->m_fftbuf2
;
786 float * p3
= unit
->m_tempbuf
;
788 // i don't know what this was supposed to do!
793 for (int i
=1; i
<numbins
; ++i
)
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];
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));
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 )
823 for (int i
=1; i
<numbins
; ++i
)
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];
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));
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
++ )
850 res
= (1-fact1
)*p4
[i
] + fact1
*p5
[i
];
854 if ( unit
->m_cflength
== 1 )
855 memcpy(unit
->m_outbuf
+unit
->m_insize
, unit
->m_tempbuf
+unit
->m_insize
,insize
);
858 for ( int i
=unit
->m_insize
+1; i
< unit
->m_fftsize
; i
++ )
860 float res
= (1-fact1
)*p4
[i
] + fact1
*p5
[i
];
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 )
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
894 unit
->m_insize
=(int)ZIN0(4); //could be input parameter
895 unit
->m_cflength
= (int)ZIN0(5); // could be input parameter
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);
909 unit
->m_fftbuf1
= (float*)RTAlloc(unit
->mWorld
, fftsize
);
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
;
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
);
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
);
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;
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
)
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);
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
;
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;
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
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
;
1121 if ( unit
->m_curbuf
== 0 ){
1122 p2L
= unit
->m_fftbuf2
[0];
1123 p2R
= unit
->m_fftbuf2
[1];
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??
1136 for (int i
=1; i
<numbins
; ++i
)
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));
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];
1170 p2L
= unit
->m_fftbuf2
[0];
1171 p2R
= unit
->m_fftbuf2
[1];
1177 // float * p3tL = unit->m_tempfftbuf[0];
1178 // float * p3tR = unit->m_tempfftbuf[1];
1181 for (int i
=1; i
<numbins
; ++i
)
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
++ )
1212 res
= (1-fact1
)*p4L
[i
] + fact1
*p5L
[i
];
1214 res
= (1-fact1
)*p4R
[i
] + fact1
*p5R
[i
];
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));
1225 for ( int i
=unit
->m_insize
+1; i
< unit
->m_fftsize
; i
++ )
1228 res
= (1-fact1
)*p4L
[i
] + fact1
*p5L
[i
];
1230 res
= (1-fact1
)*p4R
[i
] + fact1
*p5R
[i
];
1236 if ( unit
->m_cfpos
== unit
->m_cflength
) // at end of crossfade, update the current buffer index
1238 if ( 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
);
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;
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
);
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
)
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);
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
;
1365 unit
->m_pos
= pos
- size
; //reset collection counter
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
];
1418 unit
->m_pos
= 0; //reset collection counter
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
);