示例#1
0
void KeyTrack_next(KeyTrack *unit, int wrongNumSamples)
{
	//int numSamples = unit->mWorld->mFullRate.mBufLength;

	//float *output = ZOUT(0);

	float fbufnum = ZIN0(0)+0.001;

	//next FFT bufffer ready, update
	//assuming at this point that buffer precalculated for any resampling
	if (fbufnum > -0.01f) {  // && ( ZIN0(3)<0.5)

		//unit->m_frame= unit->m_frame+1;
		KeyTrack_calculatekey(unit, (uint32)fbufnum);
	}

	//always output current best key
	float outval= unit->m_currentKey;

	//control rate output
	ZOUT0(0)=outval;
}
示例#2
0
void vOut_next_a(IOUnit *unit, int inNumSamples)
{
	//Print("Out_next_a %d\n", unit->mNumInputs);
	World *world = unit->mWorld;
	int bufLength = world->mBufLength;
	int numChannels = unit->mNumInputs - 1;

	float fbusChannel = ZIN0(0);
	if (fbusChannel != unit->m_fbusChannel) {
		unit->m_fbusChannel = fbusChannel;
		int busChannel = (int)fbusChannel;
		int lastChannel = busChannel + numChannels;

		if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
			unit->m_bus = world->mAudioBus + (busChannel * bufLength);
			unit->m_busTouched = world->mAudioBusTouched + busChannel;
		}
	}

	float *out = unit->m_bus;
	int32 *touched = unit->m_busTouched;
	int32 bufCounter = unit->mWorld->mBufCounter;
	for (int i=0; i<numChannels; ++i, out+=bufLength) {
		ACQUIRE_BUS_AUDIO((int32)fbusChannel + i);
		float *in = IN(i+1);
		if (touched[i] == bufCounter)
		{
			vadd(out, out, in, inNumSamples);
		}
		else
		{
			vcopy(out, in, inNumSamples);
			touched[i] = bufCounter;
		}
		//Print("out %d %g %g\n", i, in[0], out[0]);
		RELEASE_BUS_AUDIO((int32)fbusChannel + i);
	}
}
示例#3
0
void FrameCompare_next(FrameCompare *unit, int inNumSamples)
{
	PV_GET_BUF2_FCOMPARE

	float minTargetMag = 900000.f, maxTargetMag = 0.f;
	float magdiff, magweight, lmtemp, minmaxtemp, p1mag, p2mag, scaleFactor;
	float wOffset = ZIN0(2);

	SCPolarBuf *p1 = ToPolarApx(buf1); //rendered
	SCPolarBuf *p2 = ToPolarApx(buf2); //target

	scaleFactor =  (numbins + 1) * 0.5; //hanning window only
	//Print("%f\n", p2->bin[100].mag / scaleFactor);

	for(int i = 0; i < numbins; ++i)
	{
		p2mag = p2->bin[i].mag / scaleFactor;

		minmaxtemp = (p2mag < 2e-42) ? log(2e-42) : log(fabs(p2mag));

		minTargetMag = (minmaxtemp <= minTargetMag) ? minmaxtemp : minTargetMag;
		maxTargetMag = (minmaxtemp >= maxTargetMag) ? minmaxtemp : maxTargetMag;
	}

	for(int i = 0; i < numbins; ++i)
	{
		p1mag = p1->bin[i].mag / scaleFactor;
		p2mag = p2->bin[i].mag / scaleFactor;

		magdiff = fabs(p1mag) - fabs(p2mag);
		lmtemp = p2mag < 2e-42 ? log(2e-42) : log(fabs(p2mag));
		magweight = (1 - wOffset) + (wOffset * ((lmtemp - minTargetMag) / fabs(minTargetMag - maxTargetMag)));
		unit->magSum = unit->magSum + (magdiff * magdiff * magweight);
	}

	unit->numFrames = unit->numFrames + 1;
	ZOUT0(0) = unit->outVal = unit->magSum/unit->numFrames;
}
示例#4
0
void Crest_next(Crest* unit, int inNumSamples)
{
    float *in = ZIN(0);
    float gate = ZIN0(1);

    // Get state and instance variables from the struct
    float* circbuf = unit->m_circbuf;
    int circbufpos = unit->m_circbufpos;
    int length = unit->m_length;
    float result = unit->m_result;
    bool notfullyet = unit->m_notfullyet;
    int realNumSamples = unit->m_realNumSamples;

    LOOP(realNumSamples,
         // Always add to the ringbuf, even if we're not calculating
         circbuf[circbufpos++] = std::fabs(ZXP(in));
    if(circbufpos == length) {
    circbufpos = 0U;
    if(notfullyet) {
            notfullyet = unit->m_notfullyet = false;
        }
    }
        );
示例#5
0
void LagControl_Ctor(LagControl* unit)
{
	int numChannels = unit->mNumInputs;
	float **mapin = unit->mParent->mMapControls + unit->mSpecialIndex;

	char * chunk = (char*)RTAlloc(unit->mWorld, numChannels * 2 * sizeof(float));
	unit->m_y1 = (float*)chunk;
	unit->m_b1 = unit->m_y1 + numChannels;

	for (int i=0; i<numChannels; ++i, mapin++) {
		unit->m_y1[i] = **mapin;
		float lag = ZIN0(i);
		unit->m_b1[i] = lag == 0.f ? 0.f : (float)exp(log001 / (lag * unit->mRate->mSampleRate));
	}

	if (unit->mNumOutputs == 1) {
		SETCALC(LagControl_next_1);
		LagControl_next_1(unit, 1);
	} else {
		SETCALC(LagControl_next_k);
		LagControl_next_k(unit, 1);
	}
}
示例#6
0
void IFFT_Ctor(IFFT* unit){
	int winType = sc_clip((int)ZIN0(1), -1, 1); // wintype may be used by the base ctor
	unit->m_wintype = winType;

	if(!FFTBase_Ctor(unit, 2)){
		SETCALC(*ClearUnitOutputs);
		// These zeroes are to prevent the dtor freeing things that don't exist:
		unit->m_olabuf = 0;
		return;
	}

	// This will hold the transformed and progressively overlap-added data ready for outputting.
	unit->m_olabuf = (float*)RTAlloc(unit->mWorld, unit->m_audiosize * sizeof(float));
	memset(unit->m_olabuf, 0, unit->m_audiosize * sizeof(float));

	SCWorld_Allocator alloc(ft, unit->mWorld);
	unit->m_scfft = scfft_create(unit->m_fullbufsize, unit->m_audiosize, (SCFFT_WindowFunction)unit->m_wintype, unit->m_fftsndbuf->data,
								 unit->m_fftsndbuf->data, kBackward, alloc);

	if (!unit->m_scfft) {
		SETCALC(*ClearUnitOutputs);
		unit->m_olabuf = 0;
		return;
	}

	// "pos" will be reset to zero when each frame comes in. Until then, the following ensures silent output at first:
	unit->m_pos = 0; //unit->m_audiosize;

	if (unit->mCalcRate == calc_FullRate) {
		unit->m_numSamples = unit->mWorld->mFullRate.mBufLength;
	} else {
		unit->m_numSamples = 1;
	}

	SETCALC(IFFT_next);
	ClearUnitOutputs(unit, 1);
}
void BLOscWithComplexSinusoid_next(BLOscWithComplexSinusoid *unit, int inNumSamples)
{
    
    float *out = ZOUT(0);
    float freqin = ZIN0(0);
    int32 loHarmonics = ZIN0(1);
    int32 numHarmonics = ZIN0(2);
    float slope = ZIN0(3);
    float evenOddRatio = ZIN0(4);

    int32 hiHarmonics = loHarmonics + numHarmonics - 1; // The highest harmonic index
    int32 hiHarmonicsPlusOne = hiHarmonics + 1;
    int32 loEvenHarmonics = loHarmonics%2 == 0? loHarmonics : loHarmonics + 1; // The lowest even harmonic index
    int32 hiEvenHarmonics = hiHarmonics%2 == 0? hiHarmonics : hiHarmonics - 1; // The highest even harmonic index
    int32 hiEvenHarmonicsPlusTwo = hiEvenHarmonics + 2;
    int32 numEvenHarmonics = (hiEvenHarmonics - loEvenHarmonics) / 2 + 1; //The total number of even harmonics
    float evenOddFactor = 1 - evenOddRatio;
    std::complex<double> evenOddFactorC(evenOddFactor, 0);
    float ampFactor = 0.99<slope&&slope<1.01? numHarmonics - evenOddFactor * numEvenHarmonics:((pow(slope,loHarmonics) - pow(slope,hiHarmonicsPlusOne)) / (1 - slope)) - (evenOddFactor * (pow(slope, loEvenHarmonics) - pow(slope, hiEvenHarmonicsPlusTwo)) / (1 - pow(slope, 2)));  //ampFactor will be used to normalize the output amplitude. To avoid the denominator of this calculation to be 0 when slope = 1, the different formula is used when slope falls between 0.99 and 1.01.
    
    float phaseinc = ZIN0(0) * unit->partialTheta;
    float currentphase = unit->currentphase;
    std::complex<double> baseOsc;
    std::complex<double> r;
    std::complex<double> signalC; // signal as complex number
    float signalR; // signal as real number
    std::complex<double> oneC(1,0);
    std::complex<double> slopeC(slope, 0);
    float z;
    
    LOOP(inNumSamples,
         baseOsc = std::exp(std::complex<double>(0, currentphase));

         r = slopeC * baseOsc;
         signalC = (std::pow(r, loHarmonics) - std::pow(r, hiHarmonicsPlusOne))/(oneC - r) - evenOddFactorC * (std::pow(r, loEvenHarmonics) - std::pow(r, hiEvenHarmonicsPlusTwo))/(oneC - std::pow(r, 2));
         signalR = signalC.real();
         z = signalR/ampFactor;
         
         currentphase += phaseinc;
         while (currentphase >= twopi_f)
         currentphase -= twopi_f;
         
         ZXP(out) = z;
         )
示例#8
0
void AverageOutput_next( AverageOutput *unit, int inNumSamples ) {
    int i;
    float *in = IN(0);
    float *out = ZOUT(0);
    float trig = ZIN0(1);
    float prev_trig = unit->prev_trig;
    double average = unit->average;
    uint32 count = unit->count;

    if(prev_trig <= 0. && trig > 0.) {
        average = 0.;
        count = 0;
    }

	for (i=0; i<inNumSamples; ++i) {
        average = ((count * average) + *(in+i)) / (count + 1);
        ++count;
        ZXP(out) = average;
	}

    unit->prev_trig = trig;
	  unit->count = count;
    unit->average = average;
}
void LFDNoise3_next_k(LFDNoise3 *unit, int inNumSamples)
{
	float *out = ZOUT(0);
	float freq = ZIN0(0);
	float a = unit->mLevelA;
	float b = unit->mLevelB;
	float c = unit->mLevelC;
	float d = unit->mLevelD;
	float phase = unit->mPhase;
	float dphase = freq * SAMPLEDUR;

	RGET

	LOOP1(inNumSamples,
		phase -= dphase;
		if (phase < 0) {
			phase = sc_wrap(phase, 0.f, 1.f);
			a = b;
			b = c;
			c = d;
			d = frand2(s1,s2,s3) * 0.8f;	// limits max interpol. overshoot to 1.
		}
		ZXP(out) = cubicinterp(1.f - phase, a, b, c, d);
	)
示例#10
0
void vIn_next_a(IOUnit *unit, int inNumSamples)
{
	World *world = unit->mWorld;
	int bufLength = world->mBufLength;
	int numChannels = unit->mNumOutputs;

	float fbusChannel = ZIN0(0);
	if (fbusChannel != unit->m_fbusChannel) {
		unit->m_fbusChannel = fbusChannel;
		int busChannel = (uint32)fbusChannel;
		int lastChannel = busChannel + numChannels;

		if (!(busChannel < 0 || lastChannel > (int)world->mNumAudioBusChannels)) {
			unit->m_bus = world->mAudioBus + (busChannel * bufLength);
			unit->m_busTouched = world->mAudioBusTouched + busChannel;
		}
	}

	float *in = unit->m_bus;
	int32 *touched = unit->m_busTouched;
	int32 bufCounter = unit->mWorld->mBufCounter;

	for (int i=0; i<numChannels; ++i, in += bufLength) {
		ACQUIRE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
		float *out = OUT(i);
		if (touched[i] == bufCounter)
		{
			vcopy(out, in, inNumSamples);
		}
		else
		{
			vfill(out, 0.f, inNumSamples);
		}
		RELEASE_BUS_AUDIO_SHARED((int32)fbusChannel + i);
	}
}
示例#11
0
void In_next_k(IOUnit *unit, int inNumSamples)
{
//Print("->In_next_k\n");
	World *world = unit->mWorld;
	uint32 numChannels = unit->mNumOutputs;

	float fbusChannel = ZIN0(0);
	if (fbusChannel != unit->m_fbusChannel) {
		unit->m_fbusChannel = fbusChannel;
		uint32 busChannel = (uint32)fbusChannel;
		uint32 lastChannel = busChannel + numChannels;

		if (!(lastChannel > world->mNumControlBusChannels)) {
			unit->m_bus = world->mControlBus + busChannel;
		}
	}

	float *in = unit->m_bus;
	for (uint32 i=0; i<numChannels; ++i, in++) {
		float *out = OUT(i);
		*out = *in;
	}
//Print("<-In_next_k\n");
}
示例#12
0
void DWGPlucked_next(DWGPlucked *unit, int inNumSamples)
{

	float *out = OUT(0);
	float freq = ZIN0(0);
	float amp = ZIN0(1);
	float trig = ZIN0(2);
	float pos = ZIN0(3);

	float c1 = ZIN0(4);
	float c3 = std::max(ZIN0(5),(float)1e-9);
	float *in = IN(6);
	
	unit->Loss.setcoeffs(freq,c1,c3);
	float lossdelay = unit->Loss.groupdelay(freq,SAMPLERATE);
	float deltot = SAMPLERATE/freq;
	float del1 = (deltot - lossdelay )*0.5 - 1;

	float PMAS,PMAS2;
	float PMENOS;
	for (int i=0; i < inNumSamples; ++i)
	{
		unit->DWGF[0].add(in[i],pos*del1);
		unit->DWGF[1].add(in[i],del1*(1-pos));
		
		PMAS = unit->DWGF[0].delay(del1);
		PMAS2 = unit->Loss.filter(PMAS);
		PMENOS = unit->DWGF[1].delay(del1);
		
		unit->DWGF[1].push(-PMAS2);
		unit->DWGF[0].push(-PMENOS);
		
		out[i] = PMAS + PMAS2;
			
	}
	unit->Release(trig,out,inNumSamples);
}
示例#13
0
文件: Onsets.cpp 项目: scztt/sc-debug
	float relaxtime     = ZIN0(3);
	int   medspan  = (int)ZIN0(6);

	if(unit->m_needsinit){
		// Init happens here because we need to be sure about FFT size.
		unit->m_odsdata = (float*) RTAlloc(unit->mWorld, onsetsds_memneeded(odftype, buf->samples, medspan) );

		onsetsds_init(ods, unit->m_odsdata, ODS_FFT_SC3_POLAR, odftype, buf->samples, medspan, FULLRATE);
		onsetsds_setrelax(ods, relaxtime, buf->samples>>1);

		unit->m_needsinit = false;
	}

	// Here is the best place to set parameters - after init is ensured
	// These are "painless" to set:
	ods->thresh =      ZIN0(1);
	ods->floor  =      ZIN0(4);
	ods->mingap = (int)ZIN0(5);
	ods->whtype = (int)ZIN0(7);

	// Now to process
	unit->outval = onsetsds_process(ods, (float*) p);

	ZOUT0(0) = unit->outval;
}

void Onsets_next_rawodf(Onsets *unit, int inNumSamples)
{
	Onsets_GET_BUF

	// In practice, making the polar conversion here in SC is more efficient because SC provides a lookup table method.
示例#14
0
void CheckBadValues_next(CheckBadValues* unit, int inNumSamples)
{


    float *in = ZIN(0);
    float *out = ZOUT(0);
    float id = ZIN0(1);
    int post = (int) ZIN0(2);

    float samp;
    int classification;

    switch(post) {
    case 1:		// post a line on every bad value
        LOOP(inNumSamples,
             samp = ZXP(in);
             classification = sc_fpclassify(samp);
             switch (classification)
    {
    case FP_INFINITE:
        printf("Infinite number found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id);
            ZXP(out) = 2;
            break;
        case FP_NAN:
            printf("NaN found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id);
            ZXP(out) = 1;
            break;
        case FP_SUBNORMAL:
            printf("Denormal found in Synth %d, ID: %d\n", unit->mParent->mNode.mID, (int)id);
            ZXP(out) = 3;
            break;
        default:
            ZXP(out) = 0;
        };
            );
        break;
    case 2:
        LOOP(inNumSamples,
             samp = ZXP(in);
             classification = CheckBadValues_fold_fpclasses(sc_fpclassify(samp));
        if(classification != unit->prevclass) {
        if(unit->sameCount == 0) {
                printf("CheckBadValues: %s found in Synth %d, ID %d\n",
                       CheckBadValues_fpclassString(classification), unit->mParent->mNode.mID, (int)id);
            } else {
                printf("CheckBadValues: %s found in Synth %d, ID %d (previous %d values were %s)\n",
                       CheckBadValues_fpclassString(classification), unit->mParent->mNode.mID, (int)id,
                       (int)unit->sameCount, CheckBadValues_fpclassString(unit->prevclass)
                      );
            };
            unit->sameCount = 0;
        };
        switch (classification)
    {
    case FP_INFINITE:
        ZXP(out) = 2;
            break;
        case FP_NAN:
            ZXP(out) = 1;
            break;
        case FP_SUBNORMAL:
            ZXP(out) = 3;
            break;
        default:
            ZXP(out) = 0;
        };
        unit->sameCount++;
        unit->prevclass = classification;
            );
示例#15
0
//calculation function once FFT data ready
void Loudness_dofft(Loudness *unit, uint32 ibufnum)
{
	World *world = unit->mWorld;
	//if (ibufnum >= world->mNumSndBufs) ibufnum = 0;
	SndBuf *buf; // = world->mSndBufs + ibufnum;
	//int numbins = buf->samples - 2 >> 1;
	//support LocalBuf

	if (ibufnum >= world->mNumSndBufs) {
		int localBufNum = ibufnum - world->mNumSndBufs;
		Graph *parent = unit->mParent;
		if(localBufNum <= parent->localBufNum) {
			buf = parent->mLocalSndBufs + localBufNum;
		} else {
			buf = world->mSndBufs;
		}
	} else {
		buf = world->mSndBufs + ibufnum;
	}
	LOCK_SNDBUF(buf);

	float * data= buf->data;

	float loudsum=0.0;

	float smask= ZIN0(1);
	float tmask= ZIN0(2);

	for (int k=0; k<unit->m_numbands; ++k){

		int bandstart=eqlbandbins[k];
		//int bandend=eqlbandbins[k+1];
		int bandsize= eqlbandsizes[k];
		int bandend= bandstart+bandsize;

		float bsum=0.0;
		float real, imag, power;
		int index;
		float lastpower=0.0;

		for (int h=bandstart; h<bandend;++h) {
			index = 2*h;
			real= data[index];
			imag= data[index+1];

			power = (real*real) + (imag*imag);


			//would involve spectral masking here
			power = sc_max(lastpower*smask,power); //sideways spectral masking with leaky integration
			lastpower= power;

			//psychophysical sensation; within critical band, sum using a p metric, (sum m^p)^(1/p)
			//compresses the gain

			//power of three combination
			//bsum= bsum+(power*power*power);

			//won't sum up power very well
			//if(power>bsum) bsum=power;

			bsum= bsum+power;

		}

		//store recips of bandsizes?
		//why average? surely just take max or sum is better!
		//bsum= bsum/bandsize;

		//into dB, avoid log of 0
		//float db= 10*log10((bsum*10000000)+0.001);
		//float db= 10*log10((bsum*32382)+0.001);
		//empricially derived 32382*2.348

		float db= 10*log10((bsum*76032.936f)+0.001f); //correct multipler until you get loudness output of 1!

		//correcting for power of three combination
		//bsum=bsum+0.001;
		//4.8810017610244 = log10(76032.936)
		//float db= 10*((0.33334*log10(bsum)) + 4.8810017610244); //correct multipler until you get loudness output of 1!


		//printf("bsum %f db %f \n",bsum,db);

		//convert via contour
		if(db<contours[k][0]) db=0;
		else if (db>contours[k][10]) db=phons[10];
		else {

			float prop=0.0;
			int j;
			for (j=1; j<11; ++j) {
				if(db<contours[k][j]) {
					prop= (db-contours[k][j-1])/(contours[k][j]-contours[k][j-1]);
					break;
				}

				if(j==10)
					prop=1.0;
			}

			db= (1.f-prop)*phons[j-1]+ prop*phons[j];
			//printf("prop %f db %f j %d\n",prop,db,j);
		}

		//spectralmasking, 6dB drop per frame?
		//try also with just take db
		unit->m_ERBbands[k] = sc_max(db, (unit->m_ERBbands[k]) - tmask);

		//printf("db %f erbband %f \n",db, unit->m_ERBbands[k]);

		//must sum as intensities, not dbs once corrected, pow used to be other way around
		//loudsum+= ((pow(10, 0.1*unit->m_ERBbands[k])-0.001)*0.0000308813538386); //

		loudsum+= ((pow(10, 0.1*unit->m_ERBbands[k])-0.001)); //multiplier not needed since invert below; can trust no overflow?
	}

	//total excitation, correct back to dB scale in phons
	//float phontotal= 10*log10((loudsum*32382)+0.001);
	float phontotal= 10*log10((loudsum)+0.001); //didn't use divisor above, so no need to restore here

	//unit->m_phontotal= phontotal;
	//now to sones:
	/* from Praat: Excitation.c  Sones = 2 ** ((Phones - 40) / 10)  */
	unit->m_sones= pow (2.f, (phontotal - 40) / 10);

	//printf("phontotal %f sones %f \n",phontotal, unit->m_sones);

	//about 5 times per second
	//if((unit->m_triggerid) && ((unit->m_frame%2==0))) SendTrigger(&unit->mParent->mNode, unit->m_triggerid, bestkey);
}
示例#16
0
void FFTSubbandPower_next(FFTSubbandPower *unit, int inNumSamples)
{
	int numbands = unit->m_numbands;
	int numcutoffs = numbands - 1;

	// Multi-output equiv of FFTAnalyser_GET_BUF
	float fbufnum = ZIN0(0);
	if (fbufnum < 0.f) {
		for(int i=0; i<numbands; i++){
			ZOUT0(i) = unit->m_outvals[i];
		}
		return;
	}
	uint32 ibufnum = (uint32)fbufnum;
	World *world = unit->mWorld;
	SndBuf *buf;
	if (ibufnum >= world->mNumSndBufs) {
		int localBufNum = ibufnum - world->mNumSndBufs;
		Graph *parent = unit->mParent;
		if(localBufNum <= parent->localBufNum) {
			buf = parent->mLocalSndBufs + localBufNum;
		} else {
			buf = world->mSndBufs;
		}
	} else {
		buf = world->mSndBufs + ibufnum;
	}
	int numbins = (buf->samples - 2) >> 1;
	// End: Multi-output equiv of FFTAnalyser_GET_BUF

	int scalemode = unit->m_scalemode;

	float normfactor = unit->m_normfactor;
	bool square = unit->m_square;
	if(normfactor == 0.f){
		if(square)
			unit->m_normfactor = normfactor = 1.f / powf(numbins + 2.f, 1.5f);
		else
			unit->m_normfactor = normfactor = 1.f / (numbins + 2.f);
	}

	// Now we create the integer lookup list, if it doesn't already exist
	int * cutoffs = unit->m_cutoffs;
	if(!unit->m_cutoff_inited){

		float srate = world->mFullRate.mSampleRate;
		for(int i=0; i < numcutoffs; ++i) {
			cutoffs[i] = (int)(buf->samples * ZIN0(4 + i) / srate);
			//Print("Allocated bin cutoff #%d, at bin %d\n", i, cutoffs[i]);
		}

		unit->m_cutoff_inited = true;
	}

	SCComplexBuf *p = ToComplexApx(buf);

	// Now we can actually calculate the bandwise subtotals
	float total = sc_abs(p->dc);
	if(square){
		total *= total; // square the DC val
	}
	int binaddcount = 1; // Counts how many bins contributed to the current band (1 because of the DC value)
	int curband = 0;
	float * outvals = unit->m_outvals;
	float magsq;
	for (int i=0; i<numbins; ++i) {
		if((curband != numbands) && (i >= cutoffs[curband])){
			if(scalemode==1){
				outvals[curband] = total * normfactor;
			}else{
				if(square)
					outvals[curband] = total / powf((float)binaddcount, 1.5f);
				else
					outvals[curband] = total / binaddcount;
			}
			//Print("Finished off band %i while in bin %i\n", curband, i);
			++curband;
			total = 0.f;
			binaddcount = 0;
		}

		float rabs = (p->bin[i].real);
		float iabs = (p->bin[i].imag);
		magsq = ((rabs*rabs) + (iabs*iabs));
		if(square)
			total += magsq;
		else
			total += std::sqrt(magsq);
		++binaddcount;
	}
	// Remember to output the very last (highest) band
	if(square)
		total += p->nyq * p->nyq;
	else
		total += sc_abs(p->nyq);
	// Pop the last one onto the end of the lovely list
	if(scalemode==1){
		outvals[curband] = total * normfactor;
	}else{
		if(square)
			outvals[curband] = total / powf((float)binaddcount + 1.f, 1.5f); // Plus one because of the nyq value
		else
			outvals[curband] = total / (binaddcount + 1); // Plus one because of the nyq value
	}

	// Now we can output the vals
	for(int i=0; i<numbands; i++) {
		ZOUT0(i) = outvals[i];
	}
}
示例#17
0
void ArneodoCoulletTresser_next(ArneodoCoulletTresser *unit, int inNumSamples)
{
	float *xout = ZOUT(0);
	float *yout = ZOUT(1);
	float *zout = ZOUT(2);
	float  freq = ZIN0(0);
	double alpha = ZIN0(1);
	double h = ZIN0(2);
	double x0 = ZIN0(3);
	double y0 = ZIN0(4);
	double z0 = ZIN0(5);

	double xn = unit->xn;
	double yn = unit->yn;
	double zn = unit->zn;
	float counter = unit->counter;
	double xnm1 = unit->xnm1;
	double ynm1 = unit->ynm1;
	double znm1 = unit->znm1;
	double frac = unit->frac;

	float samplesPerCycle;
	double slope;
	if(freq < unit->mRate->mSampleRate){
		samplesPerCycle = unit->mRate->mSampleRate / sc_max(freq, 0.001f);
		slope = 1.f / samplesPerCycle;
	}
	else {
		samplesPerCycle = 1.f;
		slope = 1.f;
	}

	// reset if start values change
	if((unit->x0 != x0) || (unit->y0 != y0) || (unit->z0 != z0)){
		xnm1 = xn;
		ynm1 = yn;
		znm1 = zn;
		unit->x0 = xn = x0;
		unit->y0 = yn = y0;
		unit->z0 = zn = z0;
	}

	double dx = xn - xnm1;
	double dy = yn - ynm1;
	double dz = zn - znm1;

	for (int i=0; i<inNumSamples; ++i) {
		if(counter >= samplesPerCycle){
			counter -= samplesPerCycle;
			frac = 0.f;

			xnm1 = xn;
			ynm1 = yn;
			znm1 = zn;

			double k1x, k2x, k3x, k4x,
				k1y, k2y, k3y, k4y,
				k1z, k2z, k3z, k4z,
				kxHalf, kyHalf, kzHalf;

			// 4th order Runge-Kutta approximate solution for differential equations
			k1x = h * (xnm1 * (1.1 - xnm1 / 2 - ynm1 / 2 - znm1 / 10));
			k1y = h * (ynm1 * (-0.5 + xnm1 / 2 + ynm1 / 10 - znm1 / 10));
			k1z = h * (znm1 * (alpha + 0.2 - alpha * xnm1 - ynm1 / 10 - znm1 / 10));
			kxHalf = k1x * 0.5;
			kyHalf = k1y * 0.5;
			kzHalf = k1z * 0.5;

			k2x = h * ((xnm1 + kxHalf) * (1.1 - (xnm1 + kxHalf) / 2 - (ynm1 + kyHalf) / 2 - (znm1 + kzHalf) / 10));
			k2y = h * ((ynm1 + kyHalf) * (-0.5 + (xnm1 + kxHalf) / 2 + (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10));
			k2z = h * ((znm1 + kzHalf) * (alpha + 0.2 - alpha * (xnm1 + kxHalf) - (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10));
			kxHalf = k2x * 0.5;
			kyHalf = k2y * 0.5;
			kzHalf = k2z * 0.5;

			k3x = h * ((xnm1 + kxHalf) * (1.1 - (xnm1 + kxHalf) / 2 - (ynm1 + kyHalf) / 2 - (znm1 + kzHalf) / 10));
			k3y = h * ((ynm1 + kyHalf) * (-0.5 + (xnm1 + kxHalf) / 2 + (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10));
			k3z = h * ((znm1 + kzHalf) * (alpha + 0.2 - alpha * (xnm1 + kxHalf) - (ynm1 + kyHalf) / 10 - (znm1 + kzHalf) / 10));

			k4x = h * ((xnm1 + k3x) * (1.1 - (xnm1 + k3x) / 2 - (ynm1 + k3y) / 2 - (znm1 + k3z) / 10));
			k4y = h * ((ynm1 + k3y) * (-0.5 + (xnm1 + k3x) / 2 + (ynm1 + k3y) / 10 - (znm1 + k3z) / 10));
			k4z = h * ((znm1 + k3z) * (alpha + 0.2 - alpha * (xnm1 + k3x) - (ynm1 + k3y) / 10 - (znm1 + k3z) / 10));


			xn = xn + (k1x + 2.0*(k2x + k3x) + k4x) * ONESIXTH;
			yn = yn + (k1y + 2.0*(k2y + k3y) + k4y) * ONESIXTH;
			zn = zn + (k1z + 2.0*(k2z + k3z) + k4z) * ONESIXTH;

			dx = xn - xnm1;
			dy = yn - ynm1;
			dz = zn - znm1;
		}
		counter++;
		ZXP(xout) = (xnm1 + dx * frac) * 0.5f;
		ZXP(yout) = (ynm1 + dy * frac) * 0.5f;
		ZXP(zout) = (znm1 + dz * frac) * 1.0f;
		frac += slope;
	}

	unit->xn = xn;
	unit->yn = yn;
	unit->zn = zn;
	unit->counter = counter;
	unit->xnm1 = xnm1;
	unit->ynm1 = ynm1;
	unit->znm1 = znm1;
	unit->frac = frac;
}
示例#18
0
void LotkaVolterra_next(LotkaVolterra *unit, int inNumSamples)
{
	float *xout = ZOUT(0);
	float *yout = ZOUT(1);
	float  freq = ZIN0(0);
	double a = ZIN0(1);
	double b = ZIN0(2);
	double c = ZIN0(3);
	double d = ZIN0(4);
	double h = ZIN0(5);
	double x0 = ZIN0(6);
	double y0 = ZIN0(7);

	double xn = unit->xn;
	double yn = unit->yn;
	float counter = unit->counter;
	double xnm1 = unit->xnm1;
	double ynm1 = unit->ynm1;
	double frac = unit->frac;

	float samplesPerCycle;
	double slope;
	if(freq < unit->mRate->mSampleRate){
		samplesPerCycle = unit->mRate->mSampleRate / sc_max(freq, 0.001f);
		slope = 1.f / samplesPerCycle;
	}
	else {
		samplesPerCycle = 1.f;
		slope = 1.f;
	}

	// reset if start values change
	if((unit->x0 != x0) || (unit->y0 != y0)){
		xnm1 = xn;
		ynm1 = yn;
		unit->x0 = xn = x0;
		unit->y0 = yn = y0;
	}

	double dx = xn - xnm1;
	double dy = yn - ynm1;

	for (int i=0; i<inNumSamples; ++i) {
		if(counter >= samplesPerCycle){
			counter -= samplesPerCycle;
			frac = 0.f;

			xnm1 = xn;
			ynm1 = yn;

			double k1x, k2x, k3x, k4x,
				k1y, k2y, k3y, k4y,
				kxHalf, kyHalf;

			// 4th order Runge-Kutta approximate solution for differential equations
			k1x = h * (xnm1 * (a - b * ynm1));
			k1y = h * (ynm1 * (c * xnm1 - d));
			kxHalf = k1x * 0.5;
			kyHalf = k1y * 0.5;

			k2x = h * ((xnm1 + kxHalf) * (a - b * (ynm1 + kyHalf)));
			k2y = h * ((ynm1 + kyHalf) * (c * (xnm1 + kxHalf) - d));

			kxHalf = k2x * 0.5;
			kyHalf = k2y * 0.5;

			k3x = h * ((xnm1 + kxHalf) * (a - b * (ynm1 + kyHalf)));
			k3y = h * ((ynm1 + kyHalf) * (c * (xnm1 + kxHalf) - d));

			k4x = h * ((xnm1 + k3x) * (a - b * (ynm1 + k3y)));
			k4y = h * ((ynm1 + k3y) * (c * (xnm1 + k3x) - d));

			xn = xn + (k1x + 2.0*(k2x + k3x) + k4x) * ONESIXTH;
			yn = yn + (k1y + 2.0*(k2y + k3y) + k4y) * ONESIXTH;

			dx = xn - xnm1;
			dy = yn - ynm1;
		}
		counter++;
		ZXP(xout) = (xnm1 + dx * frac) * 0.5f;
		ZXP(yout) = (ynm1 + dy * frac) * 0.5f;
		frac += slope;
	}

	unit->xn = xn;
	unit->yn = yn;
	unit->counter = counter;
	unit->xnm1 = xnm1;
	unit->ynm1 = ynm1;
	unit->frac = frac;
}
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;
	}
}
示例#20
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);
	}
示例#21
0
void SOMTrain_next(SOMTrain *unit, int inNumSamples)
{
	int traincountdown = unit->m_traincountdown;

	if(ZIN0(5) > 0.f){ // If gate > 0

		// Get the buffer and some other standard stuff...
		SOM_GET_BUF

		// Get data inputs
		for(int chan=0; chan<numinputdims; ++chan){
			inputdata[chan] = ZIN0(chan + 7);
		}

		// Get state from struct
		float mfactor = unit->m_mfactor;
		float weightfactor = unit->m_weightfactor;

		//RM float alpha = (float)unit->m_alpha;

		// get "nhood" as an integer, NB use ceil to make sure the neighbourhood errs on side of bigness
		int nhoodi = (int)ceil(unit->m_nhood);
		// squared distance comparisons are used in the neighbourhood-update function. The "plus one" is done so we can use "<" rather than "<=" later
		int nhoodisq = nhoodi * nhoodi + 1;

		// DO THE NEAREST-NEIGHBOUR SEARCH
		switch(numdims){
			case 1: unit->m_reconsterror = SOM_findnearest_1d(bufData, inputdata, bestcoords, netsize, numinputdims);
				    unit->m_writeloc     = (float)SOM_SERIALISEINDEX_1D(bestcoords[0]);
				break;
			case 2: unit->m_reconsterror = SOM_findnearest_2d(bufData, inputdata, bestcoords, netsize, numinputdims);
				    unit->m_writeloc     = (float)SOM_SERIALISEINDEX_2D(bestcoords[0], bestcoords[1]);
				break;
			case 3: unit->m_reconsterror = SOM_findnearest_3d(bufData, inputdata, bestcoords, netsize, numinputdims);
				    unit->m_writeloc     = (float)SOM_SERIALISEINDEX_3D(bestcoords[0], bestcoords[1], bestcoords[2]);
				break;
			case 4: unit->m_reconsterror = SOM_findnearest_4d(bufData, inputdata, bestcoords, netsize, numinputdims);
				    unit->m_writeloc     = (float)SOM_SERIALISEINDEX_4D(bestcoords[0], bestcoords[1], bestcoords[2], bestcoords[3]);
				break;
		}

		if(traincountdown != 0){
			//float alpha = weightfactor / (mfactor * unit->m_traincountup + 1.f); // mulier's approach
			float alpha = weightfactor * mfactor / (mfactor + unit->m_traincountup); // dan's empirical approach
			// UPDATE THE NODES
			switch(numdims){
				case 1: SOMTrain_updatenodes_1d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break;
				case 2: SOMTrain_updatenodes_2d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break;
				case 3: SOMTrain_updatenodes_3d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break;
				case 4: SOMTrain_updatenodes_4d(bufData, inputdata, bestcoords, netsize, numinputdims, alpha, nhoodi, nhoodisq); break;
			}

			// Save state to struct.
			unit->m_nhood = unit->m_nhood - unit->m_nhooddelta;
			++(unit->m_traincountup);
			unit->m_traincountdown = traincountdown = traincountdown - 1;
			if(traincountdown==0){
				unit->mDone = true;
			}
		} // End still-training-check
	} // End gate check
示例#22
0
void MedianSeparation_next( MedianSeparation *unit, int inNumSamples ) {
	
	int i,j;
    
    //calculate medians around pos-midpoint
    int medsize = unit->mediansize_; 
    int mid = unit->midpoint_; 
    
    float * mags = unit->magnitudes_; 
    float * phases = unit->phases_;
    
    float * array = unit->collection_; 
    
    int numbands = unit->fftbins_; 
    int top = numbands-1; 
    
    int pos = unit->magnitudeposition_; 
    
    int midindex = (pos+medsize-mid)%medsize; 
    
    
    float * vertical = unit->verticalmedians_; 
    
    float * horizontal = unit->horizontalmedians_; 
    
    float * magsnow = mags + (midindex*numbands);
    
    
    //cover outputs before early return in macro
    OUT0(0) = -1.f;
    OUT0(1) = -1.f;
    
    
    //0 normal, 
    //1 vertical sort
    //2 horizontal sort
    //3 final output
    
    switch (unit->amortisationstep_) {
        case 0:
        {
            
            //printf("case 0 %f \n",ZIN0(0));
            
            PV_GET_BUF
            
            //avoid output being overwritten by macro to pass input FFT buffer
            OUT0(0) = -1.f;
            OUT0(1) = -1.f;
            
            SCPolarBuf *polar = ToPolarApx(buf);
            
            //update data stored
            
            SCPolar * data = polar->bin; 
            
            int base = unit->magnitudeposition_ * numbands; 
            
            mags[base] = polar->dc; 
            mags[base+numbands-1] = polar->nyq; 
            //no need to set phases for these indices, since will always be 0.0 and initialised in constructor
            
            for (i=0; i<numbands-2; ++i)
                mags[base+i+1] = data[i].mag; 
            
            base = unit->phaseposition_ * numbands;
            
            for (i=0; i<numbands-2; ++i)
                phases[base+i+1] = data[i].phase; 
            
            uint32 bufnum1 = (uint32) IN0(1); //ZIN0(1);
            uint32 bufnum2 = (uint32) IN0(2); //ZIN0(2);
            
            //store for recall in step 3
            
            unit->bufnum1_ = bufnum1;
            unit->bufnum2_ = bufnum2;
            
            //printf("store for recall %d %d what? %d uh? %d %f %f \n",bufnum1,bufnum2,(uint32) IN0(3), (uint32) ZIN0(3), IN0(1),IN0(2));
            
            
            //will have returned early otherwise
            unit->amortisationstep_ =1; 
            break;
            
        }
        case 1:
        {   
            
            //printf("case 1\n");
            
            float medianormean = ZIN0(7); 
            
            //to avoid if inside loop, code copied twice with difference at point of array calculation (median or mean)
            if(medianormean<0.5f) {
                
                //printf("median calc vertical\n");     
                
                //vertical; easier to do in indexing 
                
                for (i=0; i<numbands; ++i) {
                    
                    int lower = i-mid; 
                    if(lower<0) lower =0; 
                    int higher = i+mid; 
                    if(higher>top) higher = top; 
                    int number = higher-lower+1; 
                    
                    float * pnow = magsnow + lower; 
                    
                    //collect into array
                    for (j=0; j<number; ++j)
                        array[j] = pnow[j]; 
                    
                    qsort(array,number,sizeof(float),cmp);
                    //result is midpoint of magnitudes
                    
                    vertical[i] = array[number/2];
                    
                }
                
            } else {
                
                float sum; 
                
                for (i=0; i<numbands; ++i) {
                    
                    int lower = i-mid; 
                    if(lower<0) lower =0; 
                    int higher = i+mid; 
                    if(higher>top) higher = top; 
                    int number = higher-lower+1; 
                    
                    float * pnow = magsnow + lower; 
                    //                    
                    //                    //collect into array
                    //                    for (j=0; j<number; ++j)
                    //                        array[j] = pnow[j]; 
                    //                    
                    sum = 0.0f; 
                    
                    //no need for intermediate array 
                    for (j=0; j<number; ++j)
                        sum += pnow[j]; 
                    
                    vertical[i] = sum/number;
                    
                }
                
                
                
            }
            
            
            unit->amortisationstep_ = 2; 
            break;
        }    
        case 2:
        {   
            
            //printf("case 2\n");
            //horizontal, requires cross steps within 2D array
            
            float medianormean = ZIN0(7); 
            
            if(medianormean<0.5f) {
                
                
                //printf("median calc horizontal\n");   
                
                for (i=0; i<numbands; ++i) {
                    
                    //no checks required for the medsize, but have to get correct indices
                    
                    //collect into array
                    for (j=0; j<medsize; ++j)
                        array[j] = mags[(j*numbands) + i]; 
                    
                    qsort(array,medsize,sizeof(float),cmp);
                    //result is midpoint of magnitudes
                    
                    horizontal[i] = array[mid];
                    
                }
                
            } else {
                
                //mean
                
                float sum; 
                float recip = 1.0f/medsize; 
                
                for (i=0; i<numbands; ++i) {
                    
                    //no checks required for the medsize, but have to get correct indices
                    
                    sum = 0.0f; 
                    //sum up directly, no need for array 
                    for (j=0; j<medsize; ++j)
                        sum+= mags[(j*numbands) + i]; 
                    
                    horizontal[i] = sum*recip;
                    
                }                
                
            }
            
            unit->amortisationstep_ = 3; 
            break;
            
        }     
        case 3:
        {
            
            //printf("case 3\n");
            uint32 bufnum1 = unit->bufnum1_; //(uint32) ZIN0(1);
            uint32 bufnum2 = unit->bufnum2_; //(uint32) ZIN0(2);
            
            //printf("now recall %d %d \n",bufnum1,bufnum2);
            
            World *world = unit->mWorld;

            SndBuf *buf1, *buf2;

            if (bufnum1 >= world->mNumSndBufs) {
                int localBufNum = bufnum1 - world->mNumSndBufs;
                Graph *parent = unit->mParent;
                if(localBufNum <= parent->localBufNum) {
                    buf1 = parent->mLocalSndBufs + localBufNum;
                } else {
                    buf1 = world->mSndBufs;
                }
            } else {
                buf1 = world->mSndBufs + bufnum1;
            }

            LOCK_SNDBUF(buf1);

            if (bufnum2 >= world->mNumSndBufs) {
                int localBufNum = bufnum2 - world->mNumSndBufs;
                Graph *parent = unit->mParent;
                if(localBufNum <= parent->localBufNum) {
                    buf2 = parent->mLocalSndBufs + localBufNum;
                } else {
                    buf2 = world->mSndBufs;
                }
            } else {
                buf2 = world->mSndBufs + bufnum2;
            }

            LOCK_SNDBUF(buf2);

            int numbins1 = (buf1->samples >> 1)  + 1;
            int numbins2 = (buf2->samples >> 1)  + 1;

            //printf("check %d %d numbands %d further check %d %d \n",numbins1,numbins2,numbands,buf1->samples,buf2->samples);


            if((numbins1 == numbands) && (numbins2 ==numbands)) {

                int hardorsoft = ZIN0(5);

                //unit->hardorsoft_ = ZIN0(5);
                //unit->p_ = ZIN0(6);

                //to magnitude and phase representation
                SCPolarBuf *polar1 = ToPolarApx(buf1);
                SCPolarBuf *polar2 = ToPolarApx(buf2);

                SCPolar * data1 = polar1->bin;
                SCPolar * data2 = polar2->bin;

                //writing into the two output arrays of the buffers


                //magsnow already pointing to write place in magnitudes
                //magsnow = mags + (midindex*numbands);

                //+mid+2, adding so no danger, just add 1
                int phaseindex = (unit->phaseposition_+1)%(mid+1); //midpoint is next one (about to be overwritten after increment below)

                float * phasesnow = phases + (phaseindex*numbands);

                //dc, nyquist, phase to zero

                //buf1,polar 1 is harmonic, 2 is percussive

                //0 larger of horizontal and vertical is winner, or 1 more subtle blend
                if(hardorsoft==0) {
                    //hard

                    //printf("hard calc \n");

                    if(horizontal[0]>vertical[0]) {

                        polar1->dc = magsnow[0];
                        polar2->dc = 0.f;

                    } else {

                        polar2->dc = magsnow[0];
                        polar1->dc = 0.f;
                    }


                    if(horizontal[top]>vertical[top]) {

                        polar1->nyq = magsnow[top];
                        polar2->nyq = 0.f;

                    } else {

                        polar2->nyq = magsnow[top];
                        polar1->nyq = 0.f;
                    }

                    int count = 0;

                    //setting
                    for (i=0; i<numbands-2; ++i) {

                        int indexnow = i+1;

                        //if(i==20) {data1[i].mag=1024; data2[i].mag=1024;}

                        //else {data1[i].mag = 0.0f; data2[i].mag = 0.f;}


                        if(horizontal[indexnow]>vertical[indexnow]) {

                            ++count;

                            data1[i].mag = magsnow[indexnow];
                            data1[i].phase = phasesnow[indexnow];
                            data2[i].mag = 0.0f;
                            data2[i].phase = 0.0f; //phasesnow[i+1];

                        } else {

                            data2[i].mag = magsnow[indexnow];
                            data2[i].phase = phasesnow[indexnow];
                            data1[i].mag = 0.0f;
                            data1[i].phase = 0.0f; //phasesnow[i+1];

                        }

                        //                        if(i<10) {
                        //
                        //                            printf("mag %d %f %f horiz %f vert %f further %f %f \n ",i, data1[i].mag,data2[i].mag,horizontal[indexnow],vertical[indexnow],polar1->bin[i].mag,polar2->bin[i].mag);
                        //
                        //                        }
                        //
                    }


                    //printf("count %d \n",count);


                } else {


                    //printf("I hope not!\n");

                    //soft, Wiener filtering
                    float pfactor = ZIN0(6);

                    float maskp, maskh, hp, pp, combine;

                    //dc
                    hp = powf(horizontal[0],pfactor);
                    pp = powf(vertical[0],pfactor);

                    combine = hp+pp;

                    maskh = 0.f;
                    maskp = 0.f;

                    //watch for zeroes
                    if(combine>0.00000000001f) {
                        maskh = hp/combine;
                        maskp = pp/combine;
                    }

                    polar1->dc = magsnow[0] * maskh;
                    polar2->dc = magsnow[0] * maskp;

                    //nyquist
                    hp = powf(horizontal[top],pfactor);
                    pp = powf(vertical[top],pfactor);

                    combine = hp+pp;

                    maskh = 0.f;
                    maskp = 0.f;

                    //watch for zeroes
                    if(combine>0.00000000001f) {
                        maskh = hp/combine;
                        maskp = pp/combine;
                    }

                    polar1->nyq = magsnow[top] * maskh;
                    polar2->nyq = magsnow[top] * maskp;

                    //setting
                    for (i=0; i<numbands-2; ++i) {

                        int indexnow = i+1;

                        hp = powf(horizontal[indexnow],pfactor);
                        pp = powf(vertical[indexnow],pfactor);

                        combine = hp+pp;

                        //if(i<5) {
                        //     printf("mag %d %f %f %f %f %f \n",i ,horizontal[indexnow],vertical[indexnow],hp,pp,combine);
                        //}

                        maskh = 0.f;
                        maskp = 0.f;

                        //watch for zeroes
                        if(combine>0.00000000001f) {
                            maskh = hp/combine;
                            maskp = pp/combine;
                        }

                        data1[i].mag = magsnow[indexnow] * maskh;
                        data1[i].phase = phasesnow[indexnow];
                        data2[i].mag = magsnow[indexnow] * maskp;
                        data2[i].phase = phasesnow[indexnow];

                    }


                }


                //printf("now output %d %d \n",bufnum1,bufnum2);

                //update output

                OUT0(0) = bufnum1; //2.f; //-1.f; //bufnum1; //-1;
                OUT0(1) = bufnum2; //-1;

            }

            unit->magnitudeposition_ = (unit->magnitudeposition_+1)%medsize; 
            unit->phaseposition_ = (unit->phaseposition_+1)%(mid+1); 
            
            unit->amortisationstep_ = 0; 
            break;
        }   
        default:
            //printf("default\n");
            break;
    }
    
    //printf("actual output %f %f \n",OUT0(0),OUT0(1));
    
 
 
    
    //    for(j=0; j<inNumSamples; ++j) {
    //		
    //		output[j]= input[j]*0.1; //((float)j/inNumSamples); 
    //	}
}
示例#23
0
void BeatTrack2_next(BeatTrack2 *unit, int wrongNumSamples)
{
    //keep updating feature memories
    unit->m_counter= (unit->m_counter+1)%(unit->m_buffersize);

    int busnum = (int)(ZIN0(0)+0.001f);

    //unit->m_features = unit->mWorld->mControlBus + busnum;

    float * features= unit->mWorld->mControlBus + busnum;

    //hmm, is this pointer guaranteed to stay the same? may have to update each time...
    for (int j=0; j<unit->m_numfeatures; ++j) {
        unit->m_pastfeatures[j][unit->m_counter]= features[j]; //unit->m_features[j];
    }

    unit->m_calculationschedule += unit->m_krlength;

    //check for new calculation round
    if(unit->m_calculationschedule> unit->m_calculationperiod) {

        unit->m_calculationschedule -= unit->m_calculationperiod;

        //reset best scores and move old to previous slots
        for (int i=0; i<2; ++i) {

            int pos1= (2+i)*unit->m_numfeatures;
            int pos2= i*unit->m_numfeatures;

            for (int j=0; j<unit->m_numfeatures; ++j) {
                unit->bestscore[pos1+j]= unit->bestscore[pos2+j];
                unit->bestscore[pos2+j]= -9999.0;
                unit->bestphase[pos1+j]= unit->bestphase[pos2+j];
                unit->bestphase[pos2+j]= 0;
                unit->besttempo[pos1+j]= unit->besttempo[pos2+j];
                unit->besttempo[pos2+j]= 60;
            }

        }

        //state 0 is do nothing
        unit->m_amortisationstate=1;
        unit->m_amortcount=0;
        unit->m_amortlength=g_numtempi*2; //
        //unit->m_amortisationsteps=0;

        //store essential data
        unit->m_startcounter = unit->m_counter;

        unit->m_currphase=unit->m_phase;
    }


    //keeps incrementing but will be reset with each calculation run
    //unit->m_amortisationsteps=unit->m_amortisationsteps+1;

    //if state nonzero do something
    switch(unit->m_amortisationstate) {
    case 0:
        break; //do nothing case
    case 1: //calculate acf
        calculatetemplate(unit,unit->m_amortcount >> 1, unit->m_amortcount %2);

        unit->m_amortcount=unit->m_amortcount+1;

        if(unit->m_amortcount==unit->m_amortlength) {
            unit->m_amortisationstate=2;
            //unit->m_amortlength=1;
            //unit->m_amortcount=0;
        }
        break;
    case 2: //done calculating template matches, now decide whether to follow through
        finaldecision(unit);
        unit->m_amortisationstate=0;
        break;

    default:
        break;
    }




    //test if impulse to output
    unit->m_phase+=unit->m_phaseperblock;

    //if(unit->m_counter%400==0) printf("phase %f period %f\n", unit->m_phase, unit->m_period);

    //if not locked, update output phase from model phase, else keep a separate output phase

    float lock= ZIN0(4);
    //printf("lock %f \n",lock);

    if(lock<0.5f) {

        unit->m_outputphase= unit->m_phase;
        unit->m_outputtempo= unit->m_currtempo;
        unit->m_outputgroove= unit->m_groove;
        unit->m_outputphaseperblock= unit->m_phaseperblock;
    } else {

        unit->m_outputphase+=unit->m_outputphaseperblock;

    }

    if (unit->m_phase >= 1.f) {
        unit->m_phase-= 1.f;
    }

    //0 is beat, 1 is quaver, 2 is semiquaver, 3 is actual current tempo in bps
    //so no audio accuracy with beats, just asap, may as well be control rate
    ZOUT0(0)=0.0;
    ZOUT0(1)=0.0;
    ZOUT0(2)=0.0;
    ZOUT0(3)=unit->m_outputtempo; //*0.016666667;
    ZOUT0(4)=unit->m_outputphase;
    ZOUT0(5)=unit->m_outputgroove;

    //output beat
    if (unit->m_outputphase >= 1.f) {

        //printf("beat \n");

        unit->m_outputphase -= 1.f;
        ZOUT0(0)=1.0;
        ZOUT0(1)=1.0;
        ZOUT0(2)=1.0;
        unit->halftrig=0;
        unit->q1trig=0;
        unit->q2trig=0;
    }

    if (unit->m_outputphase>=0.5 && unit->halftrig==0) {
        ZOUT0(1)=1.0;
        ZOUT0(2)=1.0;
        unit->halftrig=1;
    }

    float groove= unit->m_outputgroove *0.07;

    if (unit->m_outputphase>=(0.25+groove) && unit->q1trig==0) {
        ZOUT0(2)=1.0;
        unit->q1trig=1;
    }

    if (unit->m_outputphase>=(0.75+groove) && unit->q2trig==0) {
        ZOUT0(2)=1.0;
        unit->q2trig=1;
    }

}
示例#24
0
void BeatTrack2_Ctor(BeatTrack2* unit)
{
    //unit->m_srate = unit->mWorld->mFullRate.mSampleRate;
    float kblocklength=  unit->mWorld->mFullRate.mBufDuration; //seconds per control block
    unit->m_krlength= kblocklength;
    //N features per block over numphases*2 variants for one of 120 tempi, so need at least 120 blocks to complete

    unit->m_phaseaccuracy = ZIN0(3); //0.02; //20 msec resolution; could be argument of UGen

    unit->m_numphases = (int*)RTAlloc(unit->mWorld, g_numtempi * sizeof(int));
    //unit->m_phases = (float**)RTAlloc(unit->mWorld, g_numtempi * sizeof(float*));

    for (int j=0; j<g_numtempi; ++j) {

        float period= g_periods[j];

        int num= (int)(period/unit->m_phaseaccuracy); //maximum will be 1.0/0.02 = 50

        unit->m_numphases[j]=num;

        //
        //	unit->m_phases[j]= (float*)RTAlloc(unit->mWorld, unit->m_numphases[j] * sizeof(float));
        //
        //	float phase=0.0;
        //
        //	for (i=0; i<num; ++i) {
        //	unit->m_phases[j][i] = phase;
        //	phase += unit->m_phaseaccuracy;
        //	}

    }

    unit->m_numfeatures = (int)(ZIN0(1)+0.001);



    //for efficiency
    unit->m_scores= (float*)RTAlloc(unit->mWorld, (2*unit->m_numfeatures) * sizeof(float));

    unit->m_temporalwindowsize= ZIN0(2); //typically small, 2 seconds for fast reactions compared to 6 secs for BeatTrack

    unit->m_fullwindowsize = unit->m_temporalwindowsize + 1.0 + 0.1; //plus one to cover all phases of the 60bpm based period, and a further 0.1 for indexing safety; ie looking at areas around the point you're interested in

    unit->m_buffersize = (int)(unit->m_fullwindowsize/unit->m_krlength); //in control blocks


    //printf("loading test blocklength %f numfeatures %d temporal %f full %f blocks %d \n",unit->m_krlength, unit->m_numfeatures, unit->m_temporalwindowsize, unit->m_fullwindowsize, unit->m_buffersize);



    //float ** m_pastfeatures;  //for each feature, a trail of last m_workingmemorysize values
    unit->m_pastfeatures = (float**)RTAlloc(unit->mWorld, unit->m_numfeatures * sizeof(float*));

    for (int j=0; j<unit->m_numfeatures; ++j) {

        unit->m_pastfeatures[j]= (float*)RTAlloc(unit->mWorld, unit->m_buffersize * sizeof(float));

        Clear(unit->m_buffersize, unit->m_pastfeatures[j]); //set all to zero at first

        //for (i=0; i<unit->m_buffersize; ++i) {
        //	unit->m_pastfeatures[j][i] = 0.0;
        //	}
        //
    }

    //main counter
    unit->m_counter= 0;

    //could avoid allocation by having a hard limit on
    unit->bestscore= (float*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(float));
    unit->bestphase= (int*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(int));
    unit->besttempo= (int*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(int));
    unit->bestgroove= (int*)RTAlloc(unit->mWorld, 4 * unit->m_numfeatures * sizeof(int));

    for (int i=0; i<4; ++i) {

        int basepos= i*unit->m_numfeatures;

        for (int j=0; j<unit->m_numfeatures; ++j) {
            unit->bestscore[basepos+j]= -9999.0;
            unit->bestphase[basepos+j]= 0;
            unit->besttempo[basepos+j]= 60;
            unit->bestgroove[basepos+j]= 0;
        }
    }

    unit->m_phase= 0.0;
    unit->m_period= 0.5;
    unit->m_groove= 0;
    unit->m_currtempo=2;
    unit->m_phaseperblock= unit->m_krlength/unit->m_period;

    unit->m_predictphase= 0.4f;
    unit->m_predictperiod = 0.3f;


    unit->m_outputphase= unit->m_phase;
    unit->m_outputtempo= unit->m_currtempo;
    unit->m_outputgroove= unit->m_groove;
    unit->m_outputphaseperblock= unit->m_phaseperblock;



    unit->m_calculationperiod= 0.5; //every half second; could also be additional argument to UGen
    unit->m_calculationschedule= 0.0;

    //printf("srate %f conversion factor %f frame period %f \n", unit->m_srate, unit->m_srateconversion, unit->m_frameperiod);


    int bufnum = (int)(ZIN0(5)+0.001f);
    if (bufnum >= unit->mWorld->mNumSndBufs)
        bufnum = 0;

    if (bufnum<0)
        unit->m_weightingscheme = bufnum<2 ? 0 : 1;
    else {
        SndBuf *buf = unit->mWorld->mSndBufs + bufnum;
        unit->m_tempoweights= buf;
        unit->m_weightingscheme=2;
    }

    //printf("bufnum %d weightingscheme %d check %f %f\n", bufnum, unit->m_weightingscheme, unit->m_tempoweights[0], unit->m_tempoweights[119]);


    unit->halftrig=0;
    unit->q1trig=0;
    unit->q2trig=0;


    unit->mCalcFunc = (UnitCalcFunc)&BeatTrack2_next;

    // initialize outputs
    ZOUT0(0) = 0.0;
    ZOUT0(1) = 0.0;
    ZOUT0(2) = 0.0;
    ZOUT0(3) = unit->m_outputtempo;
    ZOUT0(4) = unit->m_outputphase;
    ZOUT0(5) = unit->m_outputgroove;
}
示例#25
0
void DWGPlucked2_next(DWGPlucked2 *unit, int inNumSamples)
{

	float *out = OUT(0);
	float freq = ZIN0(0);
	float amp = ZIN0(1);
	float trig = ZIN0(2);
	float pos = ZIN0(3);

	float c1 = ZIN0(4);
	float c3 = std::max(ZIN0(5),(float)1e-9);
	float *in = IN(6);
	float mistune = ZIN0(8);
	float mp = sc_clip(ZIN0(9),0,1);
	float gc = ZIN0(10);
	
	unit->Loss.setcoeffs(freq,c1,c3);
	float lossdelay = unit->Loss.groupdelay(freq,SAMPLERATE);
	float deltot = SAMPLERATE/freq;
	float del1 = (deltot - lossdelay )*0.5 - 1;

	float freq2 = freq * mistune;
	unit->Loss2.setcoeffs(freq2,c1,c3);
	lossdelay = unit->Loss2.groupdelay(freq2,SAMPLERATE);
	deltot = SAMPLERATE/freq2;
	float del2 = (deltot - lossdelay )*0.5 - 1;


	float PMAS,PMAS2;
	float PMENOS,OUT1,OUT2;
	for (int i=0; i < inNumSamples; ++i)
	{
		unit->DWGF[0].add(in[i]*mp,pos*del1);
		unit->DWGF[1].add(in[i]*mp,del1*(1-pos));
		
		PMAS = unit->DWGF[0].delay(del1);
		PMAS2 = unit->Loss.filter(PMAS);
		PMENOS = unit->DWGF[1].delay(del1);
		
		unit->DWGF[1].push(-PMAS2);
		unit->DWGF[0].push(-PMENOS);
		
		OUT1 = PMAS + PMAS2;
		
		unit->DWGF2[0].add(in[i]*(1-mp)+OUT1*gc,pos*del2);
		unit->DWGF2[1].add(in[i]*(1-mp)+OUT1*gc,del2*(1-pos));
		
		PMAS = unit->DWGF2[0].delay(del2);
		PMAS2 = unit->Loss2.filter(PMAS);
		PMENOS = unit->DWGF2[1].delay(del2);
		
		unit->DWGF2[1].push(-PMAS2);//*0.9999);
		unit->DWGF2[0].push(-PMENOS);
		
		OUT2 = PMAS + PMAS2;
		
		out[i] =  OUT1 + OUT2;
		
	}
	unit->Release(trig,out,inNumSamples);
}
示例#26
0
void SwitchDelay_next( SwitchDelay *unit, int inNumSamples ) {
    int i;
    float recval, readval, ratio;

    float *out = OUT(0);
    float *in = IN(0);
    float *buffer = unit->buffer;

    float drylevel = ZIN0(1);
    float wetlevel = ZIN0(2);
    float delayfactor = ZIN0(4);
    float prev_samp = unit->prev_samp;
    float offset_current = unit->offset_current;
    float offset_start = unit->offset_start;

    uint32 decaytime = (uint32)(ZIN0(3) * SAMPLERATE);
    uint32 bufsize = unit->bufsize;
    uint32 offset_timer = unit->offset_timer;
    uint32 writepos = unit->writepos;
    uint32 readpos = ((writepos - decaytime) + (bufsize)) % bufsize;

    char crossfading = unit->crossfading;

    if(decaytime != unit->decaytime) { // move the read pointer
        float newval, oldval, offset;

        newval = buffer[((readpos - decaytime) + bufsize) % bufsize];
        oldval = buffer[readpos] + offset_current; // adding the current offset means that we can modulate again mid-crossfade.
        offset = oldval - newval;

        crossfading = 1;
        offset_start = offset;
        offset_current = offset;
        offset_timer = ENVLEN;
    }

    for(i=0; i < inNumSamples; ++i) {
        recval = in[i];
        readval = buffer[readpos] + offset_current;

        recval = recval + (prev_samp * delayfactor);
        out[i] = (in[i] * drylevel) + (readval * wetlevel);

        buffer[writepos] = recval;
        prev_samp = readval;

        readpos = (readpos + 1) % bufsize;
        writepos = (writepos + 1) % bufsize;

        if(crossfading) {
            --offset_timer;

            if(offset_timer > 0.) { // still crossfading
                ratio = (offset_timer / ENVLEN);
                offset_current = offset_start * ratio;
            } else { // all done
                crossfading = 0;
                offset_current = 0.;
            }
        }
    }

    unit->crossfading = crossfading;
    unit->offset_start = offset_start;
    unit->offset_current = offset_current;
    unit->offset_timer = offset_timer;
    unit->decaytime = decaytime;
    unit->writepos = writepos;
    unit->readpos = readpos;
    unit->prev_samp = prev_samp;
}
示例#27
0
void Friction_next(Friction *unit, int inNumSamples)
{
    float *out = OUT(0);

    float *in = IN(0);

    // Control-rate parameters
    float friction	= ZIN0(1);
    float spring	= ZIN0(2);
    float damp		= ZIN0(3);
    float mass		= ZIN0(4);
    float beltmass	= ZIN0(5);

    // Retrive state
    float beltpos = unit->m_beltpos;
    float V = unit->m_V;
    float x = unit->m_x;
    float dx = unit->m_dx;

    // vars used in the loop
    float F_N, relspeed, F_f, drivingforce, F_s, F, ddx, oldbeltpos, oldV, beltaccn;
    bool sticking;

    // The normal force is just due to the weight of the object
    F_N = mass * 9.81f;
    float frictimesF_N = (friction * F_N);

    for (int i=0; i < inNumSamples; ++i)
    {
        oldbeltpos = beltpos;
        oldV = V;

        beltpos = in[i];
        V = beltpos - oldbeltpos;
        beltaccn = V - oldV;

        // Calc the kinetic friction force
        relspeed = dx - V;
        if(relspeed==0.f) {
            F_f = 0.f; // No kinetic friction when no relative motion
        } else if (relspeed > 0.f) {
            F_f = frictimesF_N;
        } else {
            F_f = 0.f - frictimesF_N;
        }

        drivingforce = beltaccn * beltmass;

        // Calc the nonfriction force that would occur if moving along with the belt
        F_s = drivingforce - (damp * V) - (spring * x);


        // Decide if we're sticking or not
        sticking = sc_abs(F_s) < frictimesF_N;

        // NOW TO UPDATE THE MASS'S POSITION.
        // If sticking it's easy. Mass speed == belt speed
        if(sticking) {
            dx = V;
        } else {
            // Based on eq (5)
            F = F_s - F_f;
            ddx = F / mass;
            dx += ddx;
        }

        x += dx;

        // write the output
        out[i] = x;
    }

    // Store state
    unit->m_beltpos = beltpos;
    unit->m_V  = V;
    unit->m_x  = x;
    unit->m_dx  = dx;
}
示例#28
0
void RosslerL_next(RosslerL *unit, int inNumSamples)
{
	float *xout = ZOUT(0);
	float *yout = ZOUT(1);
	float *zout = ZOUT(2);
	float freq = ZIN0(0);
	double a = ZIN0(1);
	double b = ZIN0(2);
	double c = ZIN0(3);
	double h = ZIN0(4);
	double x0 = ZIN0(5);
	double y0 = ZIN0(6);
	double z0 = ZIN0(7);

	double xn = unit->xn;
	double yn = unit->yn;
	double zn = unit->zn;
	float counter = unit->counter;
	double xnm1 = unit->xnm1;
	double ynm1 = unit->ynm1;
	double znm1 = unit->znm1;
	double frac = unit->frac;

	float samplesPerCycle;
	double slope;
	if(freq < unit->mRate->mSampleRate){
		samplesPerCycle = unit->mRate->mSampleRate / sc_max(freq, 0.001f);
		slope = 1.f / samplesPerCycle;
	}
	else {
		samplesPerCycle = 1.f;
		slope = 1.f;
	}

	if((unit->x0 != x0) || (unit->y0 != y0) || (unit->z0 != z0)){
		xnm1 = xn;
		ynm1 = yn;
		znm1 = zn;
		unit->x0 = xn = x0;
		unit->y0 = yn = y0;
		unit->z0 = zn = z0;
	}

	double dx = xn - xnm1;
	double dy = yn - ynm1;
	double dz = zn - znm1;

	for (int i=0; i<inNumSamples; ++i) {
		if(counter >= samplesPerCycle){
			counter -= samplesPerCycle;
			frac = 0.f;

			xnm1 = xn;
			ynm1 = yn;
			znm1 = zn;

			double k1x, k2x, k3x, k4x,
				k1y, k2y, k3y, k4y,
				k1z, k2z, k3z, k4z,
				kxHalf, kyHalf, kzHalf;

			// 4th order Runge-Kutta approximate solution for differential equations
			k1x = - (h * (ynm1 + znm1));
			k1y = h * (xnm1 + a * ynm1);
			k1z = h * (b + znm1 * (xnm1 - c));
			kxHalf = k1x * 0.5;
			kyHalf = k1y * 0.5;
			kzHalf = k1z * 0.5;

			k2x = - (h * (ynm1 + kyHalf + znm1 + kzHalf));
			k2y = h * (xnm1 + kxHalf + a * (ynm1 + kyHalf));
			k2z = h * (b + (znm1 + kzHalf) * (xnm1 + kxHalf - c));
			kxHalf = k2x * 0.5;
			kyHalf = k2y * 0.5;
			kzHalf = k2z * 0.5;

			k3x = - (h * (ynm1 + kyHalf + znm1 + kzHalf));
			k3y = h * (xnm1 + kxHalf + a * (ynm1 + kyHalf));
			k3z = h * (b + (znm1 + kzHalf) * (xnm1 + kxHalf - c));

			k4x = - (h * (ynm1 + k3y + znm1 + k3z));
			k4y = h * (xnm1 + k3x + a * (ynm1 + k3y));
			k4z = h * (b + (znm1 + k3z) * (xnm1 + k3x - c));

			xn = xn + (k1x + 2.0*(k2x + k3x) + k4x) * ONESIXTH;
			yn = yn + (k1y + 2.0*(k2y + k3y) + k4y) * ONESIXTH;
			zn = zn + (k1z + 2.0*(k2z + k3z) + k4z) * ONESIXTH;

			dx = xn - xnm1;
			dy = yn - ynm1;
			dz = zn - znm1;
		}
		counter++;
		ZXP(xout) = (xnm1 + dx * frac) * 0.5f;
		ZXP(yout) = (ynm1 + dy * frac) * 0.5f;
		ZXP(zout) = (znm1 + dz * frac) * 1.0f;
		frac += slope;
	}

	unit->xn = xn;
	unit->yn = yn;
	unit->zn = zn;
	unit->counter = counter;
	unit->xnm1 = xnm1;
	unit->ynm1 = ynm1;
	unit->znm1 = znm1;
	unit->frac = frac;
}
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);
	}
void PartConv_Ctor( PartConv* unit )
{
	unit->m_fftsize= (int) ZIN0(1);
	unit->m_nover2= unit->m_fftsize>>1;

	unit->m_inputbuf= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float));
	unit->m_spectrum= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float));

	SCWorld_Allocator alloc(ft, unit->mWorld);
	unit->m_scfft = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_inputbuf, unit->m_spectrum, kForward, alloc);

	//inverse
	unit->m_inputbuf2= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float));
	unit->m_spectrum2= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float));
	//in place this time
	unit->m_scifft = scfft_create(unit->m_fftsize, unit->m_fftsize, kRectWindow, unit->m_inputbuf2, unit->m_spectrum2, kBackward, alloc);

	//debug test: changing scale factors in case amplitude summation is a problem
	//unit->m_scfft->scalefac=1.0/45.254833995939;
	//unit->m_scifft->scalefac=1.0/45.254833995939;

	unit->m_output= (float*)RTAlloc(unit->mWorld, unit->m_fftsize * sizeof(float));
	unit->m_outputpos=0;

	memset(unit->m_output, 0, unit->m_fftsize * sizeof(float));
	memset(unit->m_inputbuf, 0, unit->m_fftsize * sizeof(float));
	unit->m_pos=0;

	//get passed in buffer
	unit->m_fd_accumulate=NULL;

	uint32 bufnum = (uint32)ZIN0(2);
	SndBuf *buf;

	if (bufnum >= unit->mWorld->mNumSndBufs) {
		int localBufNum = bufnum - unit->mWorld->mNumSndBufs;
		Graph *parent = unit->mParent;
		if(localBufNum <= parent->localMaxBufNum) {
			buf = parent->mLocalSndBufs + localBufNum;
		} else {
			printf("PartConv Error: Invalid Spectral data bufnum %d \n", bufnum);
			SETCALC(*ClearUnitOutputs);
			unit->mDone = true;
			return;
		}
	}

	buf = unit->mWorld->mSndBufs + bufnum;

	unit->m_specbufnumcheck = bufnum;

	if (!buf->data) {
		//unit->mDone = true;
		printf("PartConv Error: Spectral data buffer not allocated \n");
		SETCALC(*ClearUnitOutputs);
		unit->mDone = true;
		return;
	}

	unit->m_irspectra = buf->data;
	unit->m_fullsize = buf->samples;
	unit->m_partitions=buf->samples/(unit->m_fftsize); //should be exact
	//printf("another check partitions %d irspecsize %d fftsize %d \n", unit->m_partitions,unit->m_fullsize, unit->m_fftsize);

	if((buf->samples % unit->m_fftsize !=0) || (buf->samples==0)) {
		printf("PartConv Error: fftsize doesn't divide spectral data buffer size or spectral data buffer size is zero\n");
		SETCALC(*ClearUnitOutputs);
		unit->mDone = true;
		return;
	}

	//CHECK SAMPLING RATE AND BUFFER SIZE
	unit->m_blocksize = unit->mWorld->mFullRate.mBufLength;
	//if(unit->m_blocksize!=64) printf("TPV complains: block size not 64, you have %d\n", unit->m_blocksize);
	unit->m_sr = unit->mWorld->mSampleRate;
	//if(unit->m_sr!=44100) printf("TPV complains: sample rate not 44100, you have %d\n", unit->m_sr);

	if(unit->m_nover2 % unit->m_blocksize !=0) {
		printf("PartConv Error: block size doesn't divide partition size\n");
		SETCALC(*ClearUnitOutputs);
		unit->mDone = true;
		return;
	} else {

		//must be exact divisor
		int blocksperpartition = unit->m_nover2/unit->m_blocksize;

		unit->m_spareblocks = blocksperpartition-1;

		if(unit->m_spareblocks<1) {
			printf("PartConv Error: no spareblocks, amortisation not possible! \n");
			SETCALC(*ClearUnitOutputs);
			unit->mDone = true;
			return;
		}

		//won't be exact
		unit->m_numamort = (unit->m_partitions-1)/unit->m_spareblocks; //will relate number of partitions to number of spare blocks
		unit->m_lastamort= (unit->m_partitions-1)- ((unit->m_spareblocks-1)*(unit->m_numamort)); //allow for error on last one
		unit->m_amortcount= -1; //starts as flag to avoid any amortisation before have first fft done
		unit->m_partitionsdone=1;

		//printf("Amortisation stats partitions %d nover2 %d blocksize %d spareblocks %d numamort %d lastamort %d \n", unit->m_partitions,unit->m_nover2, unit->m_blocksize, unit->m_spareblocks, unit->m_numamort, unit->m_lastamort);

		unit->m_fd_accumulate= (float*)RTAlloc(unit->mWorld, unit->m_fullsize * sizeof(float));
		memset(unit->m_fd_accumulate, 0, unit->m_fullsize * sizeof(float));
		unit->m_fd_accum_pos=0;

		SETCALC(PartConv_next);
	}
}