Esempio n. 1
0
void LoopBuf_Ctor(LoopBuf *unit)
{
// input 1 => rate
// input 2 => gate
//	if (INRATE(1) == calc_FullRate) {
//		if (INRATE(2) == calc_FullRate) {
//			SETCALC(LoopBuf_next_aa);
//		} else {
//			SETCALC(LoopBuf_next_ak);
//		}
//	} else {
//		if (INRATE(2) == calc_FullRate) {
//			SETCALC(LoopBuf_next_ka);
//		} else {
			SETCALC(LoopBuf_next_kk);
//		}
//	}

	unit->m_fbufnum = -1e9f;
	unit->m_prevgate = 0.;
	unit->m_phase = ZIN0(3);
	unit->m_playThrough = false;

	ClearUnitOutputs(unit, 1);
}
//include local buffer test in one place
static SndBuf * ConvGetBuffer(Unit * unit, uint32 bufnum, const char * ugenName, int inNumSamples)
{
	SndBuf *buf;
	World *world = unit->mWorld;

	if (bufnum >= world->mNumSndBufs) {
		int localBufNum = bufnum - world->mNumSndBufs;
		Graph *parent = unit->mParent;
		if (localBufNum <= parent->localMaxBufNum) {
			buf = parent->mLocalSndBufs + localBufNum;
		} else {
			if (unit->mWorld->mVerbosity > -1)
				Print("%s: invalid buffer number (%d).\n", ugenName, bufnum);
			goto handle_failure;
		}
	} else {
		buf = world->mSndBufs + bufnum;
	}

	if (buf->data == NULL) {
		if (unit->mWorld->mVerbosity > -1)
			Print("%s: uninitialized buffer (%i).\n", ugenName, bufnum);
		goto handle_failure;
	}

	return buf;

handle_failure:
	SETCALC(*ClearUnitOutputs);
	ClearUnitOutputs(unit, inNumSamples);
	unit->mDone = true;
	return NULL;
}
Esempio n. 3
0
void IFFT_next(IFFT *unit, int wrongNumSamples){

	float *out = OUT(0); // NB not ZOUT0

	// Load state from struct into local scope
	int pos     = unit->m_pos;
	int fullbufsize  = unit->m_fullbufsize;
	int audiosize = unit->m_audiosize;
// 	int numSamples = unit->mWorld->mFullRate.mBufLength;
	int numSamples = unit->m_numSamples;
	float *olabuf = unit->m_olabuf;
	float fbufnum = ZIN0(0);

	// Only run the IFFT if we're receiving a new block of input data - otherwise just output data already received
	if (fbufnum >= 0.f){

		// Ensure it's in cartesian format, not polar
		ToComplexApx(unit->m_fftsndbuf);

		float* fftbuf = unit->m_fftsndbuf->data;

		scfft_doifft(unit->m_scfft);

		// Then shunt the "old" time-domain output down by one hop
		int hopsamps = pos;
		int shuntsamps = audiosize - hopsamps;
		if(hopsamps != audiosize){  // There's only copying to be done if the position isn't all the way to the end of the buffer
			memcpy(olabuf, olabuf+hopsamps, shuntsamps * sizeof(float));
		}

		// Then mix the "new" time-domain data in - adding at first, then just setting (copying) where the "old" is supposed to be zero.
		#if SC_DARWIN
			vDSP_vadd(olabuf, 1, fftbuf, 1, olabuf, 1, shuntsamps);
		#else
			// NB we re-use the "pos" variable temporarily here for write rather than read
			for(pos = 0; pos < shuntsamps; ++pos){
				olabuf[pos] += fftbuf[pos];
			}
		#endif
		memcpy(olabuf + shuntsamps, fftbuf + shuntsamps, (hopsamps) * sizeof(float));

		// Move the pointer back to zero, which is where playback will next begin
		pos = 0;

	} // End of has-the-chain-fired

	// Now we can output some stuff, as long as there is still data waiting to be output.
	// If there is NOT data waiting to be output, we output zero. (Either irregular/negative-overlap
	//     FFT firing, or FFT has given up, or at very start of execution.)
	if(pos >= audiosize){
		ClearUnitOutputs(unit, numSamples);
	}else{
		memcpy(out, olabuf + pos, numSamples * sizeof(float));
		pos += numSamples;
	}
	unit->m_pos = pos;

}
Esempio n. 4
0
void TrigControl_Ctor(Unit* unit)
{
	//Print("TrigControl_Ctor\n");
	if (unit->mNumOutputs == 1) {
		SETCALC(TrigControl_next_1);
	} else {
		SETCALC(TrigControl_next_k);
	}
	ClearUnitOutputs(unit, 1);
}
Esempio n. 5
0
void InTrig_Ctor(IOUnit* unit)
{
	World *world = unit->mWorld;
	unit->m_fbusChannel = -1.;

	if (unit->mCalcRate == calc_FullRate) {
		SETCALC(ClearUnitOutputs);
		ClearUnitOutputs(unit, 1);
	} else {
		SETCALC(InTrig_next_k);
		unit->m_bus = world->mControlBus;
		unit->m_busTouched = world->mControlBusTouched;
		InTrig_next_k(unit, 1);
	}
}
Esempio n. 6
0
static inline bool bbcheckBuffer(Unit * unit, const float * bufData, uint32 bufChannels, uint32 expectedChannels, int inNumSamples) {
	if (!bufData){
		goto handle_failure;
	}
	if (expectedChannels > bufChannels) {
		if(unit->mWorld->mVerbosity > -1 && !unit->mDone){
			Print("Buffer UGen channel mismatch: expected %i, yet buffer has %i channels\n",
				  expectedChannels, bufChannels);
		}
		goto handle_failure;
	}
	return true;

handle_failure:
	unit->mDone = true;
	ClearUnitOutputs(unit, inNumSamples);
	return false;
}
Esempio n. 7
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);
}
Esempio n. 8
0
void GVerb_Ctor(GVerb *unit)
{
    SETCALC(GVerb_next);
    float roomsize = unit->roomsize = IN0(1);
    float revtime = unit->revtime =  IN0(2);
    float damping = unit->damping = IN0(3);
    float inputbandwidth = unit->inputbandwidth = 0.; //IN0(4);
    float spread = unit->spread = IN0(5);
    unit->drylevel = 0.; //IN0(6);
    unit->earlylevel = 0.; // IN0(7);
    unit->taillevel = 0.; //IN0(8);

    float maxroomsize = unit->maxroomsize = IN0(9);

    float maxdelay = unit->maxdelay = SAMPLERATE*maxroomsize/340.f;
    float largestdelay = unit->largestdelay = SAMPLERATE*roomsize/340.f;

    // make the inputdamper
    unit->inputdamper = make_damper(unit, 1. - inputbandwidth);

    //float ga = powf(10.f, -60.f/20.f);
    float ga = 0.001f;
    float n = SAMPLERATE * revtime;
    double alpha = unit->alpha = pow((double)ga, 1./(double)n);
    float gbmul[4] = {1.000, 0.816490, 0.707100, 0.632450};
    for(int i = 0; i < FDNORDER; ++i){
	float gb = gbmul[i] * largestdelay;
	if(i == 0){
	    unit->fdnlens[i] = nearestprime((int)gb, 0.5);
	    } else {
	    unit->fdnlens[i] = f_round(gb);
	    }
	unit->fdngains[i] = -powf((float)alpha, unit->fdnlens[i]);
	}
    // make the fixeddelay lines and dampers
    for(int i = 0; i < FDNORDER; i++){
	unit->fdndels[i] = make_fixeddelay(unit, (int)unit->fdnlens[i], (int)maxdelay+1000);
	unit->fdndamps[i] = make_damper(unit, damping); // damping is the same as fdndamping in source
	}

    // diffuser section
    float diffscale = (float)unit->fdnlens[3]/(210. + 159. + 562. + 410.);
    float spread1 = spread;
    float spread2 = 3.0 * spread;

    int b = 210;
    float r = 0.125541;
    int a = (int)(spread1 * r);
    int c = 210+159 + a;
    int cc = c - b;
    r = 0.854046;
    a = (int)(spread2 * r);
    int d = 210 + 159 + 562 + a;
    int dd = d - c;
    int e = 1341 - d;

    unit->ldifs[0] = make_diffuser(unit, f_round(diffscale * b), 0.75);
    unit->ldifs[1] = make_diffuser(unit, f_round(diffscale * cc), 0.75);
    unit->ldifs[2] = make_diffuser(unit, f_round(diffscale * dd), 0.625);
    unit->ldifs[3] = make_diffuser(unit, f_round(diffscale * e), 0.625);
    b = 210;
    r = -0.568366;
    a = (int)(spread1 * r);
    c = 210 + 159 + a;
    cc = c - b;
    r = -0.126815;
    a = (int)(spread2 * r);
    d = 210 + 159 + 562 + a;
    dd = d - c;
    e = 1341 - d;

    unit->rdifs[0] = make_diffuser(unit, f_round(diffscale * b), 0.75);
    unit->rdifs[1] = make_diffuser(unit, f_round(diffscale * cc), 0.75);
    unit->rdifs[2] = make_diffuser(unit, f_round(diffscale * dd), 0.625);
    unit->rdifs[3] = make_diffuser(unit, f_round(diffscale * e), 0.625);

    unit->taps[0] = 5 + (int)(0.410 * largestdelay);
    unit->taps[1] = 5 + (int)(0.300 * largestdelay);
    unit->taps[2] = 5 + (int)(0.155 * largestdelay);
    unit->taps[3] = 5; //+ f_round(0.000 * largestdelay);

    for(int i = 0; i < FDNORDER; i++) {
	unit->tapgains[i] = pow(alpha,(double)unit->taps[i]);
	}

    unit->tapdelay = make_fixeddelay(unit, 44000, 44000);

    // init the slope values
    unit->earlylevelslope = unit->drylevelslope = unit->taillevelslope = 0.f;
    ClearUnitOutputs(unit, 1);
    }
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;
}