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"
35 //float *fftWindow[32];
37 struct Convolution
: Unit
39 int m_pos
, m_insize
, m_fftsize
;
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;
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
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
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
86 float *m_inbuf1
, *m_inbuf2
, *m_outbuf
;
89 //////////////////////////////////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////////////////////////////////////////
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);
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
)
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;
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);
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
);
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
;
224 for (int i
=1; i
<insize
; ++i
) {
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
];
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));
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
)
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
;
270 if (unit
->mWorld
->mVerbosity
> -1)
271 Print("%s: invalid buffer number (%d).\n", ugenName
, bufnum
);
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
);
287 SETCALC(*ClearUnitOutputs
);
288 ClearUnitOutputs(unit
, inNumSamples
);
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);
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);
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
);
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
);
384 printf( "Convolution2 framesize smaller than blocksize \n" );
385 SETCALC(*ClearUnitOutputs
);
387 //SETCALC(Convolution2_next2);
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
)
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);
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
);
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
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
;
477 for (int i
=1; i
<numbins
; ++i
) {
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];
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));
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;
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]);
549 // for ( int i=0; i < numTimes; i++ )
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
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;
575 // //complex multiply
576 // for (int i=1; i<numbins; ++i) {
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;
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));
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;
604 // unit->m_prevtrig = curtrig;
607 void Convolution2L_Ctor(Convolution2L
*unit
)
609 //require size N+M-1 to be a power of two
612 unit
->m_insize
=(int)ZIN0(3); //could be input parameter
613 unit
->m_cflength
= (int)ZIN0(4); // could be input parameter
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);
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
);
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;
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
);
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
)
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);
733 //Copy(numSamples, out1, in1);
734 memcpy(out1
,in1
,numSamples
*sizeof(float));
736 unit
->m_pos
+= numSamples
;
740 if (unit
->m_prevtrig
<= 0.f
&& curtrig
> 0.f
){
742 uint32 bufnum
= (int)ZIN0(1);
743 SndBuf
*buf
= ConvGetBuffer(unit
, bufnum
, "Convolution2L", numSamples
);
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;
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
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
;
799 if ( unit
->m_curbuf
== 0 )
800 p2
= unit
->m_fftbuf2
;
803 float * p3
= unit
->m_tempbuf
;
805 // i don't know what this was supposed to do!
810 for (int i
=1; i
<numbins
; ++i
)
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];
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));
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 )
840 for (int i
=1; i
<numbins
; ++i
)
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];
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));
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
++ )
867 res
= (1-fact1
)*p4
[i
] + fact1
*p5
[i
];
871 if ( unit
->m_cflength
== 1 )
872 memcpy(unit
->m_outbuf
+unit
->m_insize
, unit
->m_tempbuf
+unit
->m_insize
,insize
);
875 for ( int i
=unit
->m_insize
+1; i
< unit
->m_fftsize
; i
++ )
877 float res
= (1-fact1
)*p4
[i
] + fact1
*p5
[i
];
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 )
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
911 unit
->m_insize
=(int)ZIN0(4); //could be input parameter
912 unit
->m_cflength
= (int)ZIN0(5); // could be input parameter
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);
926 unit
->m_fftbuf1
= (float*)RTAlloc(unit
->mWorld
, fftsize
);
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
;
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);
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]);
986 buf
= ConvGetBuffer(unit
, bufnumR
, "StereoConvolution2L", 1);
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;
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
)
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);
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
;
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
);
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;
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
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
;
1137 if ( unit
->m_curbuf
== 0 ){
1138 p2L
= unit
->m_fftbuf2
[0];
1139 p2R
= unit
->m_fftbuf2
[1];
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??
1152 for (int i
=1; i
<numbins
; ++i
)
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));
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];
1186 p2L
= unit
->m_fftbuf2
[0];
1187 p2R
= unit
->m_fftbuf2
[1];
1193 // float * p3tL = unit->m_tempfftbuf[0];
1194 // float * p3tR = unit->m_tempfftbuf[1];
1197 for (int i
=1; i
<numbins
; ++i
)
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
++ )
1228 res
= (1-fact1
)*p4L
[i
] + fact1
*p5L
[i
];
1230 res
= (1-fact1
)*p4R
[i
] + fact1
*p5R
[i
];
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));
1241 for ( int i
=unit
->m_insize
+1; i
< unit
->m_fftsize
; i
++ )
1244 res
= (1-fact1
)*p4L
[i
] + fact1
*p5L
[i
];
1246 res
= (1-fact1
)*p4R
[i
] + fact1
*p5R
[i
];
1252 if ( unit
->m_cfpos
== unit
->m_cflength
) // at end of crossfade, update the current buffer index
1254 if ( 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);
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;
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
);
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
)
1329 float curtrig
= ZIN0(2);
1331 float *pin1
= unit
->m_inbuf1
;
1333 int numSamples
= unit
->mWorld
->mFullRate
.mBufLength
;
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
;
1378 unit
->m_pos
= pos
- size
; //reset collection counter
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);
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
];
1431 unit
->m_pos
= 0; //reset collection counter
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
);