Esempio n. 1
0
void FFTTrigger_Ctor(FFTTrigger *unit)
{
	World *world = unit->mWorld;

/*
	uint32 bufnum = (uint32)IN0(0);
	Print("FFTTrigger_Ctor: bufnum is %i\n", bufnum);
	if (bufnum >= world->mNumSndBufs) bufnum = 0;
	SndBuf *buf = world->mSndBufs + bufnum;
*/


	uint32 bufnum = (uint32)IN0(0);
	//Print("FFTTrigger_Ctor: bufnum is %i\n", bufnum);
	SndBuf *buf;
	if (bufnum >= world->mNumSndBufs) {
		int localBufNum = bufnum - world->mNumSndBufs;
		Graph *parent = unit->mParent;
		if(localBufNum <= parent->localMaxBufNum) {
			buf = parent->mLocalSndBufs + localBufNum;
		} else {
			bufnum = 0;
			buf = world->mSndBufs + bufnum;
		}
	} else {
		buf = world->mSndBufs + bufnum;
	}
	LOCK_SNDBUF(buf);


	unit->m_fftsndbuf = buf;
	unit->m_fftbufnum = bufnum;
	unit->m_fullbufsize = buf->samples;

	int numSamples = unit->mWorld->mFullRate.mBufLength;
	float dataHopSize = IN0(1);
	int initPolar = unit->m_polar = (int)IN0(2);
	unit->m_numPeriods = unit->m_periodsRemain = (int)(((float)unit->m_fullbufsize * dataHopSize) / numSamples) - 1;

	buf->coord = (IN0(2) == 1.f) ? coord_Polar : coord_Complex;

	OUT0(0) = IN0(0);
	SETCALC(FFTTrigger_next);
}
Esempio n. 2
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);
}
Esempio n. 3
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); 
    //	}
}
Esempio n. 4
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);
}