Esempio n. 1
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. 2
0
void FFTPower_next(FFTPower *unit, int inNumSamples)
{
	FFTAnalyser_GET_BUF

	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);
	}


	SCComplexBuf *p = ToComplexApx(buf);
//	SCPolarBuf *p = ToPolarApx(buf);

	float total;
	if(square){
		total = sc_abs(p->dc) * sc_abs(p->dc) + sc_abs(p->nyq) *  sc_abs(p->nyq);

		for (int i=0; i<numbins; ++i) {
			float rabs = (p->bin[i].real);
			float iabs = (p->bin[i].imag);
			total += (rabs*rabs) + (iabs*iabs);
		}
	}else{
		total = sc_abs(p->dc) + sc_abs(p->nyq);

		for (int i=0; i<numbins; ++i) {
			float rabs = (p->bin[i].real);
			float iabs = (p->bin[i].imag);
			total += sqrt((rabs*rabs) + (iabs*iabs));
		}
	//	for (int i=0; i<numbins; ++i) {
	//		total += sc_abs(p->bin[i].mag);
	//	}
	}

	// Store the val for output in future calls
	unit->outval = total * normfactor;

	ZOUT0(0) = unit->outval;
}
Esempio n. 3
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];
	}
}
Esempio n. 4
0
//////////////////////////////////////////////////////////////////////////////////////////////////

void SpecFlatness_Ctor(SpecFlatness *unit)
{
	SETCALC(SpecFlatness_next);
	ZOUT0(0) = unit->outval = 0.;
	unit->m_oneovern = 0.;
}

void SpecFlatness_next(SpecFlatness *unit, int inNumSamples)
{
	FFTAnalyser_GET_BUF
	if(unit->m_oneovern == 0.)
		unit->m_oneovern = 1./(numbins + 2);

	SCComplexBuf *p = ToComplexApx(buf);

	// Spectral Flatness Measure is geometric mean divided by arithmetic mean.
	//
	// In order to calculate geom mean without hitting the precision limit,
	//  we use the trick of converting to log, taking the average, then converting back from log.
	double geommean = std::log(sc_abs(p->dc)) + std::log(sc_abs(p->nyq));
	double mean     = sc_abs(p->dc)      + sc_abs(p->nyq);

	for (int i=0; i<numbins; ++i) {
		float rabs = (p->bin[i].real);
		float iabs = (p->bin[i].imag);
		float amp = std::sqrt((rabs*rabs) + (iabs*iabs));
		if(amp != 0.f) { // zeroes lead to NaNs
			geommean += std::log(amp);
			mean += amp;
Esempio n. 5
0
//calculation function once FFT data ready
void KeyTrack_calculatekey(KeyTrack *unit, uint32 ibufnum)
{
	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; 
			if(unit->mWorld->mVerbosity > -1){ Print("KeyTrack error: Buffer number overrun: %i\n", ibufnum); } 
		} 
	} else { 
		buf = world->mSndBufs + ibufnum; 
	} 
    
	LOCK_SNDBUF(buf);
	int numbins = buf->samples - 2 >> 1;

	//assumed in this representation
	SCComplexBuf *p = ToComplexApx(buf);

	const float * data= buf->data;

	//memcpy(unit->m_FFTBuf, data, NOVER2);

	//to hold powers
	float * fftbuf= unit->m_FFTBuf;

	//get powers for bins
	//don't need to calculate past half Nyquist, because no indices involved of harmonics above 10000 Hz or so (see index data at top of file)
	for (int i=0; i<NOVER2; i+=2) {
		//i>>1 is i/2
		fftbuf[i>>1] = ((data[i] * data[i]) + (data[i+1] * data[i+1]));
	}


	float * chroma= unit->m_chroma;

	float sum;
	int indexbase, index;

	//experimental; added leaky integration on each note; also, only add to sum if harmonic, ie not a transient

	float * weights = unit->m_weights;
	int * bins = unit->m_bins;

	float chromaleak= ZIN0(2);

	//zero for new round (should add leaky integrator here!
	for (int i=0;i<12;++i)
		chroma[i] *= chromaleak;

	for (int i=0;i<60;++i) {
		int chromaindex = (i+9)%12; //starts at A1 up to G#6

		sum=0.0;

		indexbase= 12*i; //6 partials, 2 of each

		//transient sum, setting up last values too

		float phasesum=0.0;

		for(int j=0;j<12;++j) { //12 if 144 data points

			index=indexbase+j;

			//experimental transient detection code, not reliable
			//int binindex= unit->m_bins[index]-1;
			//SCPolar binnow= p->bin[binindex].ToPolarApx();
			//float phaseadvance= (binindex+1)*(TWOPI*0.5); //k * (512/44100) * (44100/1024) //convert bin number to frequency
			//float power= binnow.mag * binnow.mag; //(p->bin[binindex].real)*(p->bin[binindex].real) + (p->bin[binindex].imag)*(p->bin[binindex].imag); //(p->bin[binindex].mag);
			//power *= power;

			//int phaseindex= indexbase+j;
			//float phasenow= binnow.phase; //0.0; //(p->bin[binindex].phase);
			//float prevphase = fmod(unit->m_prevphase[index]+phaseadvance,TWOPI);
			//float a,b,tmp;
			//a=phasenow; b=prevphase;
			//b=phasenow; a=prevphase;

			//if(b<a) {b= b+TWOPI;}

			//float phasechange = sc_min(b-a,a+TWOPI-b); //more complicated, need mod 2pi and to know lower and upper
			//phasesum+= phasechange;
			//unit->m_prevphase[index]= phasenow;

			//((p->bin[index-1].mag) * (p->bin[index-1].mag))

			//printf("comparison %f %f \n",fftbuf[g_bins2[index]], power);
			//sum+= (unit->m_weights[index])* power;

			sum+= (weights[index])* (fftbuf[bins[index]]);
		}


		//transient test here too?
		//if(phasesum>(5*PI)){sum=0.0;}

		//if((i>5) && (i<15))
		//printf("test phasesum %f \n", phasesum);
		//unit->m_leaknote[i] = (0.8*unit->m_leaknote[i]) + sum;

		chroma[chromaindex]+= sum; //unit->m_leaknote[i]; //sum;
	}

	float* key = unit->m_key;

	//major
	for (int i=0;i<12;++i) {

		sum=0.0;
		for (int j=0;j<7;++j) {
			indexbase=g_major[j];

			index=(i+indexbase)%12;
			//sum+=(chroma[index]*g_kkmajor[indexbase]);

			sum+=(chroma[index]*g_diatonicmajor[indexbase]);

		}

		key[i]=sum; //10*log10(sum+1);
	}

	//minor
	for (int i=0;i<12;++i) {

		sum=0.0;
		for (int j=0;j<7;++j) {
			indexbase=g_minor[j];

			index=(i+indexbase)%12;
			//sum+=(chroma[index]*g_kkminor[indexbase]);

			sum+=(chroma[index]*g_diatonicminor[indexbase]);

		}

		key[12+i]=sum;
	}

	float keyleak= ZIN0(1); //fade parameter to 0.01 for histogram in seconds, convert to FFT frames

	//keyleak in seconds, convert to drop time in FFT hop frames (FRAMEPERIOD)
	keyleak= sc_max(0.001f,keyleak/unit->m_frameperiod); //FRAMEPERIOD;

	//now number of frames, actual leak param is decay exponent to reach 0.01 in x seconds, ie 0.01 = leakparam ** (x/ffthopsize)
	//0.01 is -40dB
	keyleak= pow(0.01f,(1.f/keyleak));

	float * histogram= unit->m_histogram;

	int bestkey=0;
	float bestscore=0.0;

	for (int i=0;i<24;++i) {
		histogram[i]= (keyleak*histogram[i])+key[i];

		if(histogram[i]>bestscore) {
			bestscore=histogram[i];
			bestkey=i;
		}

	//printf("%f ",histogram[i]);
	}

	//should find secondbest and only swap if win by a margin

	//printf(" best %d \n\n",bestkey);
	//what is winning currently? find max in histogram
	unit->m_currentKey=bestkey;

	//about 5 times per second
	//if((unit->m_triggerid) && ((unit->m_frame%2==0))) SendTrigger(&unit->mParent->mNode, unit->m_triggerid, bestkey);
}