コード例 #1
0
ファイル: FFT_UGens.cpp プロジェクト: 8c6794b6/supercollider
void FFT_next(FFT *unit, int wrongNumSamples)
{
	float *in = IN(1);
	float *out = unit->m_inbuf + unit->m_pos + unit->m_shuntsize;

	int numSamples = unit->m_numSamples;

	// copy input
	memcpy(out, in, numSamples * sizeof(float));

	unit->m_pos += numSamples;

	bool gate = ZIN0(4) > 0.f; // Buffer shunting continues, but no FFTing

	if (unit->m_pos != unit->m_hopsize || !unit->m_fftsndbuf->data || unit->m_fftsndbuf->samples != unit->m_fullbufsize) {
		if(unit->m_pos == unit->m_hopsize)
			unit->m_pos = 0;
		ZOUT0(0) = -1.f;
	} else {

		unit->m_pos = 0;
		if(gate){
			scfft_dofft(unit->m_scfft);
			unit->m_fftsndbuf->coord = coord_Complex;
			ZOUT0(0) = unit->m_fftbufnum;
		} else {
			ZOUT0(0) = -1;
		}
		// Shunt input buf down
		memmove(unit->m_inbuf, unit->m_inbuf + unit->m_hopsize, unit->m_shuntsize * sizeof(float));
	}
}
コード例 #2
0
//buffer preparation
void PreparePartConv(World *world, struct SndBuf *buf, struct sc_msg_iter *msg)
{
	// 'channels' not used- should just be mono, num frames= num samples
	float *data1 = buf->data;
	uint32 frombufnum = msg->geti();
	int fftsize = msg->geti();

	//output size must be frombuf->frames*2
	if (frombufnum >= world->mNumSndBufs) frombufnum = 0;
	SndBuf* frombuf = world->mSndBufs + frombufnum;
	int frames2 = frombuf->frames;
	float *data2 = frombuf->data;

	//scfft
	int nover2= fftsize>>1;

	int numpartitions;
	if(frames2 % nover2 == 0){
		numpartitions= frames2/nover2;
	}else{
		numpartitions= (frames2/nover2)+1;
	}

	//printf("reality check numpartitions %d fftsize %d product %d numinputframes %d \n", numpartitions, fftsize, numpartitions*fftsize, frames2);

	float * inputbuf= (float*)RTAlloc(world, fftsize * sizeof(float));
	float * spectrum= (float*)RTAlloc(world, fftsize * sizeof(float));

	SCWorld_Allocator alloc(ft, world);
	scfft* m_scfft = scfft_create(fftsize, fftsize, kRectWindow, inputbuf, spectrum, kForward, alloc);

	memset(inputbuf, 0, sizeof(float)*fftsize); // for zero padding

	//run through input data buffer, taking nover2 chunks, zero padding each
	for (int i=0; i<numpartitions; ++i) {
		int indexnow= nover2*i;
		int indexout= fftsize*i;

		if(i<(numpartitions-1)){
			memcpy(inputbuf, data2+indexnow, nover2 * sizeof(float));
		}else{
			int takenow = frames2 % nover2;
			if(takenow == 0){
				takenow = nover2;
			}

			memcpy(inputbuf, data2+indexnow, takenow * sizeof(float));
			if(takenow<nover2){
				memset(inputbuf+takenow, 0, (nover2-takenow)*sizeof(float));
			}
		}
		scfft_dofft(m_scfft);
		memcpy(data1+indexout, spectrum, fftsize * sizeof(float));
	}
	//clean up
	RTFree(world, inputbuf);
	RTFree(world, spectrum);

	if(m_scfft) scfft_destroy(m_scfft, alloc);
}
コード例 #3
0
void Convolution2_next(Convolution2 *unit, int wrongNumSamples)
{
	float *in1 = IN(0);
	//float *in2 = IN(1);
	float curtrig = ZIN0(2);

	float *out1 = unit->m_inbuf1 + unit->m_pos;
	// 	float *out2 = unit->m_inbuf2 + unit->m_pos;

	int numSamples = unit->mWorld->mFullRate.mBufLength;
	uint32 insize=unit->m_insize * sizeof(float);

	// copy input
	Copy(numSamples, out1, in1);

	unit->m_pos += numSamples;

	if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
		//float fbufnum  = ZIN0(1);
		//int log2n2 = unit->m_log2n;
		//uint32 bufnum = (int)fbufnum;
		//printf("bufnum %i \n", bufnum);
		//World *world = unit->mWorld;
		//if (bufnum >= world->mNumSndBufs) bufnum = 0;
		//SndBuf *buf = world->mSndBufs + bufnum;

		SndBuf *buf = ConvGetBuffer(unit,(uint32)ZIN0(1), "Convolution2", numSamples);
		if (!buf)
			return;
		LOCK_SNDBUF_SHARED(buf);

		memcpy(unit->m_fftbuf2, buf->data, insize);
		memset(unit->m_fftbuf2+unit->m_insize, 0, insize);
	    //rffts(unit->m_fftbuf2, log2n2, 1, cosTable[log2n2]);

		scfft_dofft(unit->m_scfft2);
	}

	if (unit->m_pos & unit->m_insize) {

		//have collected enough samples to transform next frame
		unit->m_pos = 0; //reset collection counter

		// copy to fftbuf
		//int log2n = unit->m_log2n;

		memcpy(unit->m_fftbuf1, unit->m_inbuf1, insize);

		//zero pad second part of buffer to allow for convolution
		memset(unit->m_fftbuf1+unit->m_insize, 0, insize);
		//if (unit->m_prevtrig <= 0.f && curtrig > 0.f)

		scfft_dofft(unit->m_scfft1);

		//in place transform for now
		//		rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);

		//complex multiply time
		int numbins = unit->m_fftsize >> 1; //unit->m_fftsize - 2 >> 1;

		float * p1= unit->m_fftbuf1;
		float * p2= unit->m_fftbuf2;

		p1[0] *= p2[0];
		p1[1] *= p2[1];

		//complex multiply
		for (int i=1; i<numbins; ++i) {
			float real,imag;
			int realind,imagind;
			realind= 2*i; imagind= realind+1;
			real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
			imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
			p1[realind] = real; //p2->bin[i];
			p1[imagind]= imag;
		}

		//copy second part from before to overlap
		memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, insize);

		//inverse fft into outbuf
		memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));

		//in place
		//riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);

		scfft_doifft(unit->m_scfftR);

		//		DoWindowing(log2n, unit->m_outbuf, unit->m_fftsize);
	}
コード例 #4
0
void Convolution2_Ctor(Convolution2 *unit)
{
	//require size N+M-1 to be a power of two

	unit->m_insize=(int)ZIN0(3);	//could be input parameter
									// 	printf( "unit->m_insize %i\n", unit->m_insize );
									// 	printf( "unit->mWorld->mFullRate.mBufLength %i\n", unit->mWorld->mFullRate.mBufLength );

	//float fbufnum  = ZIN0(1);
	uint32 bufnum = (int)ZIN0(1); //fbufnum;
	World *world = unit->mWorld;

	//before added check for LocalBuf
	//if (bufnum >= world->mNumSndBufs) bufnum = 0;
	//	SndBuf *buf = world->mSndBufs + bufnum;

	SndBuf *buf = ConvGetBuffer(unit, bufnum, "Convolution2", 1);

	if(buf) {
		if ( unit->m_insize <= 0 ) // if smaller than zero, equal to size of buffer
			unit->m_insize=buf->frames;	//could be input parameter

		unit->m_fftsize=2*(unit->m_insize);
		//printf("hello %i, %i\n", unit->m_insize, unit->m_fftsize);
		//just use memory for the input buffers and fft buffers
		int insize = unit->m_insize * sizeof(float);
		int fftsize = unit->m_fftsize * sizeof(float);

		//
		//	unit->m_inbuf1 = (float*)RTAlloc(unit->mWorld, insize);
		////         unit->m_inbuf2 = (float*)RTAlloc(unit->mWorld, insize);
		//
		//        unit->m_fftbuf1 = (float*)RTAlloc(unit->mWorld, fftsize);
		//        unit->m_fftbuf2 = (float*)RTAlloc(unit->mWorld, fftsize);


		unit->m_inbuf1 = (float*)RTAlloc(world, insize);
		unit->m_fftbuf1 = (float*)RTAlloc(world, fftsize);
		unit->m_fftbuf2 = (float*)RTAlloc(world, fftsize);

		unit->m_outbuf = (float*)RTAlloc(world, fftsize);
		unit->m_overlapbuf = (float*)RTAlloc(world, insize);

		memset(unit->m_outbuf, 0, fftsize);
		memset(unit->m_overlapbuf, 0, insize);

		//unit->m_log2n = LOG2CEIL(unit->m_fftsize);

		unit->m_pos = 0;
		memset(unit->m_outbuf, 0, fftsize);
		memset(unit->m_overlapbuf, 0, insize);

		SCWorld_Allocator alloc(ft, unit->mWorld);
		unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
		unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
		unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc);

		//calculate fft for kernel straight away
		memcpy(unit->m_fftbuf2, buf->data, insize);
		//zero pad second part of buffer to allow for convolution
		memset(unit->m_fftbuf2+unit->m_insize, 0, insize);

		scfft_dofft(unit->m_scfft2);

		unit->m_pos = 0;

		//	unit->m_log2n = LOG2CEIL(unit->m_fftsize);
		//
		//        int log2n = unit->m_log2n;
		//
		//	//test for full input buffer
		//	//unit->m_mask = unit->m_insize;
		//
		//	//in place transform for now
		//		rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);

		unit->m_prevtrig = 0.f;
		unit->m_prevtrig = ZIN0(2);

		// 	printf( "unit->m_insize %i\n", unit->m_insize );
		// 	printf( "world->mFullRate.mBufLength %i\n", world->mFullRate.mBufLength );

		if ( unit->m_insize >= world->mFullRate.mBufLength )
		{
			// 		printf( "insize bigger than blocksize\n" );
			SETCALC(Convolution2_next);
		}
		else
		{
			printf( "Convolution2 framesize smaller than blocksize \n" );
			SETCALC(*ClearUnitOutputs);
			unit->mDone = true;
			//SETCALC(Convolution2_next2);
		}
	} else {
		unit->m_scfft2 = unit->m_scfft1 = unit->m_scfftR = NULL;
	}
}
コード例 #5
0
void Convolution_next(Convolution *unit, int numSamples)
{
	float *in1 = IN(0);
	float *in2 = IN(1);

	float *out1 = unit->m_inbuf1 + unit->m_pos;
	float *out2 = unit->m_inbuf2 + unit->m_pos;

	//int numSamples = unit->mWorld->mFullRate.mBufLength;

	// copy input
	Copy(numSamples, out1, in1);
	Copy(numSamples, out2, in2);

	unit->m_pos += numSamples;

	int insize= unit->m_insize;

	if (unit->m_pos & insize) {
        //have collected enough samples to transform next frame
		unit->m_pos = 0; //reset collection counter

		int memsize= insize*sizeof(float);

        // copy to fftbuf
		memcpy(unit->m_fftbuf1, unit->m_inbuf1, memsize);
		memcpy(unit->m_fftbuf2, unit->m_inbuf2, memsize);

		//zero pad second part of buffer to allow for convolution
		memset(unit->m_fftbuf1+unit->m_insize, 0, memsize);
		memset(unit->m_fftbuf2+unit->m_insize, 0, memsize);

		// do fft

		//in place transform for now

		//old Green fft code, now replaced by scfft
		//		int log2n = unit->m_log2n;
		//		rffts(unit->m_fftbuf1, log2n, 1, cosTable[log2n]);
		//      rffts(unit->m_fftbuf2, log2n, 1, cosTable[log2n]);
		scfft_dofft(unit->m_scfft1);
		scfft_dofft(unit->m_scfft2);

		//complex multiply time
		float * p1= unit->m_fftbuf1;
		float * p2= unit->m_fftbuf2;

		p1[0] *= p2[0];
		p1[1] *= p2[1];

		//complex multiply
		for (int i=1; i<insize; ++i) {
			float real,imag;
			int realind,imagind;
			realind= 2*i; imagind= realind+1;
			real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
			imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];

			p1[realind] = real;
			p1[imagind]= imag;
		}

		//copy second part from before to overlap
		memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_insize, memsize);

		//inverse fft into outbuf
		memcpy(unit->m_outbuf, unit->m_fftbuf1, unit->m_fftsize * sizeof(float));

		//in place
        //riffts(unit->m_outbuf, log2n, 1, cosTable[log2n]);
		scfft_doifft(unit->m_scfftR);
	}

	//write out samples copied from outbuf, with overlap added in

	float *output = ZOUT(0);
	float *out= unit->m_outbuf+unit->m_pos;
	float *overlap= unit->m_overlapbuf+unit->m_pos;

	for (int i=0; i<numSamples; ++i)
		ZXP(output) = out[i] + overlap[i];
}
コード例 #6
0
void PartConv_next( PartConv *unit, int inNumSamples )
{
	float *in = IN(0);
	float *out = OUT(0);
	int pos = unit->m_pos;

	//safety check
	if (!(unit->mWorld->mSndBufs + unit->m_specbufnumcheck)->data) {
		printf("PartConv Error: Spectral data buffer not allocated \n");
		ClearUnitOutputs(unit, inNumSamples);
		SETCALC(*ClearUnitOutputs);
		unit->mDone = true;
		return;
	}

	float * input= unit->m_inputbuf;
	float * output= unit->m_output;
	int outputpos= unit->m_outputpos;

	//into input buffer
	memcpy(input+pos, in, inNumSamples * sizeof(float));

	pos += inNumSamples;

	//if ready for new FFT
	int nover2 = unit->m_nover2;

	//assumes that blocksize perfectly divides windowsize
	if (pos == nover2) {
		//FFT this input, second half of input always zero
		//memset(input+unit->m_nover2, 0, sizeof(float)*unit->m_nover2);
		scfft_dofft(unit->m_scfft);

		//reset pos into input buffer
		pos=0;
		//reset outputpos
		outputpos= 0;

		float * spectrum = unit->m_spectrum;
		float * spectrum2 = unit->m_spectrum2;

		//multiply spectra and accumulate for all ir spectra across storage buffer

		int fftsize = unit->m_fftsize;
		int accumpos = unit->m_fd_accum_pos;
		float * accumbuffer = unit->m_fd_accumulate;

		float * irspectrum = unit->m_irspectra;

		int fullsize = unit->m_fullsize;

		//JUST DO FIRST ONE FOR NOW, AMORTISED FOR OTHERS
		//frames
		for (int i=0; i<1; ++i) {

			int irpos= (i*fftsize);
			int posnow= (accumpos+irpos)%fullsize;
			float * target= accumbuffer+posnow;
			float * ir= irspectrum+irpos;

			//real multiply for dc and nyquist
			target[0] += ir[0]*spectrum[0];
			target[1] += ir[1]*spectrum[1];

			//complex multiply for frequency bins
			for (int j=1; j<nover2; ++j) {
				int binposr= 2*j;
				int binposi= binposr+1;
				target[binposr] += (ir[binposr]*spectrum[binposr]) - (ir[binposi]*spectrum[binposi]);
				target[binposi] += (ir[binposi]*spectrum[binposr]) + (ir[binposr]*spectrum[binposi]);
			}
		}

		//IFFT this partition
		float * input2 = unit->m_inputbuf2;
		memcpy(input2, accumbuffer+accumpos, fftsize * sizeof(float));
		scfft_doifft(unit->m_scifft);

		//shunt output data down and zero top bit
		memcpy(output, output+nover2, nover2 * sizeof(float));
		memset(output+nover2, 0, nover2 * sizeof(float));

		//sum into output
		for (int j=0; j<fftsize; ++j)
			output[j] += spectrum2[j];

		//zero this partition
		memset(accumbuffer+accumpos, 0, fftsize * sizeof(float));

		//ONLY DO AT END OF AMORTISATION???? no, amort code has extra -1 in indexing to cope
		//update partition counter
		accumpos= (accumpos+fftsize)%fullsize;
		unit->m_fd_accum_pos= accumpos;

		//set up for amortisation (calculate output for other partitions of impulse response)
		unit->m_amortcount=0;
		unit->m_partitionsdone=1;
	} else {
		//amortisation steps:
		//complex multiply of this new fft spectrum against existing irspectrums and sum to accumbuffer
		if (unit->m_amortcount>=0) {
			float * spectrum= unit->m_spectrum;

			//multiply spectra and accumulate for all ir spectra across storage buffer

			int fftsize= unit->m_fftsize;
			int nover2= unit->m_nover2;
			//int frames= unit->m_partitions;
			int accumpos= unit->m_fd_accum_pos;
			float * accumbuffer= unit->m_fd_accumulate;

			float * irspectrum= unit->m_irspectra;

			int fullsize= unit->m_fullsize;

			int starti, stopi;
			int number;

			if(unit->m_amortcount==(unit->m_spareblocks-1)) {
				number= unit->m_lastamort;
			}else{
				number= unit->m_numamort;
			}

			starti= unit->m_partitionsdone-1;
			stopi= starti+number-1;

			//printf("amort check count %d starti %d stopi %d number %d framesdone %d \n",unit->m_amortcount, starti, stopi, number, unit->m_partitionsdone);

			unit->m_partitionsdone += number;
			++unit->m_amortcount;

			for (int i=starti; i<=stopi; ++i) {
				int posnow= (accumpos+(i*fftsize))%fullsize;
				float * target= accumbuffer+posnow;
				int irpos= (i*fftsize);
				float * ir= irspectrum+irpos;

				//real multiply for dc and nyquist
				target[0]+=  ir[0]*spectrum[0];
				target[1]+=	 ir[1]*spectrum[1];
				//complex multiply for frequency bins
				for (int j=1; j<nover2; ++j) {
					int binposr= 2*j;
					int binposi= binposr+1;
					target[binposr]+=  (ir[binposr]*spectrum[binposr]) - (ir[binposi]*spectrum[binposi]);
					target[binposi]+=  (ir[binposi]*spectrum[binposr]) + (ir[binposr]*spectrum[binposi]);
				}
			}
		}
	}

	//do this second!
	memcpy(out, output+outputpos, inNumSamples * sizeof(float));

	//debugging tests: output values tend to be fftsize too big, probably due to complex multiply and also summation over all partitions
	//	RGen& rgen = *unit->mParent->mRGen;
	//	int testindex= rgen.irand(inNumSamples-1);
	//	printf("inNumSamples %d testindex %d out %f output %f \n",inNumSamples, testindex, out[testindex], *(output+outputpos+testindex));

	outputpos+=inNumSamples;

	unit->m_outputpos= outputpos;
	unit->m_pos= pos;
}
コード例 #7
0
void Convolution2_next(Convolution2 *unit, int wrongNumSamples)
{
	float *in1 = IN(0);
	float curtrig = ZIN0(2);

	float *inbuf1writepos = unit->m_inbuf1 + unit->m_pos;

	int numSamples = unit->mWorld->mFullRate.mBufLength;
	uint32 framesize = unit->m_framesize;
	uint32 framesize_f = framesize * sizeof(float);

	// copy input
	Copy(numSamples, inbuf1writepos, in1);

	unit->m_pos += numSamples;

	if (unit->m_prevtrig <= 0.f && curtrig > 0.f){
		SndBuf *kernelbuf = ConvGetBuffer(unit,(uint32)ZIN0(1), "Convolution2", numSamples);
		if (!kernelbuf)
			return;
		LOCK_SNDBUF_SHARED(kernelbuf);

		// we cannot use a kernel larger than the fft size, so truncate if needed. the kernel may be smaller though.
		size_t kernelcopysize = sc_min(kernelbuf->frames, framesize);
		memcpy(unit->m_fftbuf2, kernelbuf->data, kernelcopysize * sizeof(float));
		memset(unit->m_fftbuf2 + kernelcopysize, 0, (2 * framesize - kernelcopysize) * sizeof(float));

		scfft_dofft(unit->m_scfft2);
	}

	if (unit->m_pos >= framesize) {
		//have collected enough samples to transform next frame
		unit->m_pos = 0; //reset collection counter

		// copy to fftbuf
		memcpy(unit->m_fftbuf1, unit->m_inbuf1, framesize_f);

		//zero pad second part of buffer to allow for convolution
		memset(unit->m_fftbuf1+unit->m_framesize, 0, framesize_f);

		scfft_dofft(unit->m_scfft1);

		//complex multiply time
		int numbins = unit->m_fftsize >> 1;

		float * p1= unit->m_fftbuf1;
		float * p2= unit->m_fftbuf2;

		p1[0] *= p2[0];
		p1[1] *= p2[1];

		//complex multiply
		for (int i=1; i<numbins; ++i) {
			float real,imag;
			int realind,imagind;
			realind= 2*i;
			imagind= realind+1;
			real= p1[realind]*p2[realind]- p1[imagind]*p2[imagind];
			imag= p1[realind]*p2[imagind]+ p1[imagind]*p2[realind];
			p1[realind] = real;
			p1[imagind]= imag;
		}

		//copy second part from before to overlap
		memcpy(unit->m_overlapbuf, unit->m_outbuf+unit->m_framesize, framesize_f);
		//inverse fft into outbuf
		scfft_doifft(unit->m_scfftR);
	}
コード例 #8
0
void Convolution2_Ctor(Convolution2 *unit)
{
	//require size N+M-1 to be a power of two
	unit->m_framesize=(int)ZIN0(3);
	uint32 kernelbufnum = (int)ZIN0(1);
	World *world = unit->mWorld;

	SndBuf *kernelbuf = ConvGetBuffer(unit, kernelbufnum, "Convolution2", 1);

	if(kernelbuf) {
		if ( unit->m_framesize <= 0 ){ // if smaller than zero, we use the size of the buffer
			unit->m_framesize=kernelbuf->frames;
		}

		unit->m_fftsize=2*(unit->m_framesize);

		if(unit->m_fftsize > SC_FFT_ABSOLUTE_MAXSIZE){
			printf( "Convolution2: FFT size is larger than SC_FFT_ABSOLUTE_MAXSIZE, cannot run. We suggest PartConv instead.\n" );
			SETCALC(*ClearUnitOutputs);
		}

		// allocate memory internally for the input buffers and fft buffers
		int framesize_f = unit->m_framesize * sizeof(float);
		int fftsize_f = unit->m_fftsize * sizeof(float);
		unit->m_inbuf1 = (float*)RTAlloc(world, framesize_f);
		unit->m_fftbuf1 = (float*)RTAlloc(world, fftsize_f);
		unit->m_fftbuf2 = (float*)RTAlloc(world, fftsize_f);

		unit->m_outbuf = (float*)RTAlloc(world, fftsize_f);
		memset(unit->m_outbuf, 0, fftsize_f);
		unit->m_overlapbuf = (float*)RTAlloc(world, framesize_f);
		memset(unit->m_overlapbuf, 0, framesize_f);

		unit->m_pos = 0;

		SCWorld_Allocator alloc(ft, unit->mWorld);
		unit->m_scfft1 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_fftbuf1, kForward, alloc);
		unit->m_scfft2 = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf2, unit->m_fftbuf2, kForward, alloc);
		unit->m_scfftR = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_fftbuf1, unit->m_outbuf, kBackward, alloc);
		if(!unit->m_scfft1 || !unit->m_scfft2 || !unit->m_scfftR){
			printf( "Could not create scfft.\n" );
			SETCALC(*ClearUnitOutputs);
			unit->mDone = true;
			return;
		}
		//calculate fft for kernel straight away
		// we cannot use a kernel larger than the fft size, so truncate if needed. the kernel may be smaller though.
		uint32 framesize = unit->m_framesize;
		size_t kernelcopysize = sc_min(kernelbuf->frames, framesize);
		memcpy(unit->m_fftbuf2, kernelbuf->data, kernelcopysize * sizeof(float));
		//zero pad second part of buffer to allow for convolution
		memset(unit->m_fftbuf2 + kernelcopysize, 0, (2 * framesize - kernelcopysize) * sizeof(float));

		scfft_dofft(unit->m_scfft2);

		unit->m_pos = 0;

		unit->m_prevtrig = 0.f;
		unit->m_prevtrig = ZIN0(2);

		if ( unit->m_framesize >= world->mFullRate.mBufLength ) {
			SETCALC(Convolution2_next);
		} else {
			printf( "Convolution2 framesize smaller than blocksize \n" );
			SETCALC(*ClearUnitOutputs);
			unit->mDone = true;
		}
	} else {
		unit->m_scfft2 = unit->m_scfft1 = unit->m_scfftR = NULL;
		printf("Convolution2_Ctor: can't get kernel buffer, giving up.\n");
		SETCALC(*ClearUnitOutputs);
	}

}