예제 #1
0
파일: DFT.cpp 프로젝트: LuaAV/LuaAV
void DFT::resize(uint32_t newWindowSize, uint32_t newPadSize){ //printf("DFT::resize()\n");

	if(0 == newWindowSize && 0 == newPadSize) return;

	uint32_t oldDFTSize = sizeDFT();
	uint32_t newDFTSize = newWindowSize + newPadSize;
	uint32_t oldFrqSize = oldDFTSize+2;		// 2 extra for DC/Nyquist imaginary
	uint32_t newFrqSize = newDFTSize+2;		// "

	if(mem::resize(mBuf, oldFrqSize, newFrqSize)){
		mBufInv = mBuf;
		if(mAux) mem::resize(mAux, oldFrqSize, newFrqSize);
		mFFT.resize(newDFTSize);
		mem::deepZero(mBuf, newFrqSize);
	}
	
	mem::resize(mPadOA, sizePad(), newPadSize);
	mem::deepZero(mPadOA, newPadSize);
	
	mSizeDFT = newDFTSize;
	mSizeWin = newWindowSize;
	mSizeHop = mSizeWin;

	onResync(1);
}
예제 #2
0
파일: DFT.cpp 프로젝트: LuaAV/LuaAV
// input is sizeWin
void STFT::forward(float * input){ //printf("STFT::forward(float *)\n");

	arr::mul(input, mFwdWin, sizeWin());	// apply forward window
	if(mRotateForward) mem::rotateHalf(input, sizeWin()); // do zero-phase windowing rotation?
	DFT::forward(input);					// do forward transform
	
	// compute frequency estimates?
	if(Bin::MagFreq == mSpctFormat){
		
		// This will effectively subtract the expected phase difference from the computed.
		// This extra step seems to give more precise frequency estimates.
		slice(mPhases, numBins()) += float(M_2PI * sizeHop()) / sizeDFT();
		
		// compute relative frequencies
		//arr::phaseToFreq(phs, mPhases, numBins(), unitsHop());
		float factor = 1.f / (M_2PI * unitsHop());
		for(uint32_t i=1; i<numBins()-1; ++i){
			float dp = scl::wrapPhase(bins()[i][1] - mPhases[i]);	// wrap phase into [-pi, pi)
			mPhases[i] = bins()[i][1];							// prev phase = curr phase
			bins()[i][1] = dp*factor;
		}
		
		// compute absolute frequencies by adding respective bin center frequency
		slice(mBuf, numBins(), 2) += gen::RAdd<float>(binFreq());
	}
}
예제 #3
0
파일: DFT.cpp 프로젝트: PeterZhouSZ/Gamma
void DFT::print(FILE * f, const char * a){
	fprintf(f, "DFT, Win, Hop: %d, %d, %d samples\n", (int)sizeDFT(), (int)sizeWin(), (int)sizeHop());
	fprintf(f, "# bins:        %d\n", (int)numBins());
	fprintf(f, "Freq res:      %f units/sample\n", freqRes());
	fprintf(f, "Bin freq:      %f units\n", binFreq());
	fprintf(f, "Data format:   %s\n", toString(mSpctFormat));
	fprintf(f, "Precise:       %s\n", mPrecise ? "true" : "false");	
	fprintf(f, "Aux buffers:   %d\n", (int)mNumAux);
	//printf("buf, pad, inv, aux: %p %p %p %p", mBuf, mPadOA, mBufInv, mAux);
	fprintf(f, "%s", a);
}
예제 #4
0
파일: DFT.cpp 프로젝트: PeterZhouSZ/Gamma
void STFT::inverse(float * dst){
	//printf("STFT::inverse(float *)\n");
	if(MAG_FREQ == mSpctFormat){
		// 2pi / hopRate: converts Hz to phase diff in radians
		double factor = M_2PI * unitsHop();

		// 2pi / overlap: expected phase diff of fundamental due to overlap
		double expdp1 = double(sizeHop())/sizeWin() * M_2PI;
		double fund = binFreq();

		for(unsigned k=1; k<numBins()-1; ++k){
			double t = bin(k)[1];		// freq
			t -= k*fund;				// freq to freq deviation
			t *= factor;				// freq deviation to phase diff
			t += k*expdp1;				// add expected phase diff due to overlap
			mAccums[k] += t;			// accumulate phase diff
			//bin(k)[1] = mAccums[k];		// copy accum phase for inverse xfm
			bufInvFrq()[2*k] = bin(k)[0];
			bufInvFrq()[2*k+1] = mAccums[k];
		}

		bufInvFrq()[0] = bin(0)[0];
		bufInvFrq()[2*(numBins()-1)] = bin(numBins()-1)[0];
	}

	DFT::inverse();	// result goes into bufInvPos()

	// undo zero-phase windowing rotation?
	if(mRotateForward) mem::rotateRight(sizeWin()/2, bufInvPos(), sizeDFT());

	// apply secondary window to smooth ends?
	if(mWindowInverse){
		arr::mulBartlett(bufInvPos(), sizeWin());
	}

	if(overlapping()){	//inverse windows overlap?

		// scale inverse so overlap-add is normalized
		for(unsigned i=0; i<sizeWin(); ++i){
			bufInvPos()[i] *= mInvWinMul;
		}

		// shift old output left while adding new output
		arr::add(mBufInv, bufInvPos(), mBufInv + sizeHop(), sizeWin() - sizeHop());
	}

	// copy remaining non-overlapped portion of new output
	unsigned sizeOverlap = sizeWin() - sizeHop();
	mem::deepCopy(mBufInv + sizeOverlap, bufInvPos() + sizeOverlap, sizeHop());

	// copy output if external buffer provided
	if(dst) mem::deepCopy(dst, mBufInv, sizeWin());	
}
예제 #5
0
파일: DFT.cpp 프로젝트: LuaAV/LuaAV
void DFT::inverse(float * output){
	//printf("DFT::inverse(float *)\n");
	
	switch(mSpctFormat){
	case Bin::Polar:
	case Bin::MagFreq:
		//arr::mul(bins0(), gen::val(normInverse()), nbins);
		POLAR_RECT
		break;
	
	default:;
		//arr::mul(bins0(), gen::val(normInverse()), nbins<<1);
	}	

	// arrange/scale bins for inverse xfm
	// TODO: can we avoid this move by pointer offsetting?
	mem::deepMove(mBuf+1, mBuf+2, sizeDFT()-1);
	slice(mBuf+1, sizeDFT()-2) *= 0.5f;

	mFFT.inverse(mBuf);
	
	// o.a. inverse window with prev spill
	if(sizePad() > 0){
		arr::add(mBuf, mPadOA, scl::min(sizePad(), sizeWin()));	// add prev spill
	
		if(sizePad() <= sizeWin()){	// no spill overlap
			mem::deepCopy(mPadOA, mBuf + sizeWin(), sizePad());	// save current spill
		}
		else{						// spill overlaps
			// add and save current spill to previous
			arr::add(mPadOA, mBuf + sizeWin(), mPadOA + sizeWin(), sizePad() - sizeWin());
			mem::deepCopy(mPadOA + sizePad() - sizeWin(), mBuf + sizePad(), sizeWin());
		}
	}

	if(output) mem::deepCopy(output, mBuf, sizeWin());
}
예제 #6
0
파일: DFT.cpp 프로젝트: PeterZhouSZ/Gamma
void DFT::inverse(float * dst){
	//printf("DFT::inverse(float *)\n");

	// operate on copy of bins
	if(MAG_FREQ != mSpctFormat){
		mem::deepCopy(bufInvFrq(), bufFwdFrq(), sizeDFT()+2);
	}

	switch(mSpctFormat){
	case COMPLEX: break;
	case MAG_PHASE:
	case MAG_FREQ:
		{	Complex<float> * bins = mBins+numBins();
			POL_TO_CART(bins)
		}
		break;
	}

	mFFT.inverse(bufInvFrq(), true);

	// overlap-add inverse window with prev spill
	if(sizePad() > 0){
		// add spill from previous transform
		arr::add(bufInvPos(), mPadOA, scl::min(sizePad(), sizeWin()));

		// no spill overlap
		if(sizePad() <= sizeWin()){
			// copy current spill into overlap-add buffer
			mem::deepCopy(mPadOA, bufInvPos() + sizeWin(), sizePad());
		}

		// spill overlaps
		else{
			// add and save current spill to previous
			arr::add(mPadOA, bufInvPos() + sizeWin(), mPadOA + sizeWin(), sizePad() - sizeWin());
			mem::deepCopy(mPadOA + sizePad() - sizeWin(), bufInvPos() + sizePad(), sizeWin());
		}
	}

	if(dst) mem::deepCopy(dst, bufInvPos(), sizeWin());
}
예제 #7
0
파일: DFT.cpp 프로젝트: PeterZhouSZ/Gamma
// input is sizeWin
void STFT::forward(const float * src){ //printf("STFT::forward(float *)\n");

	if(src) mem::deepCopy(bufFwdPos(), src, sizeWin());

	// apply forward window
	arr::mul(bufFwdPos(), mFwdWin, sizeWin());
	
	// do zero-phase windowing rotation?
	if(mRotateForward) mem::rotateLeft(sizeWin()/2, bufFwdPos(), sizeDFT());

	DFT::forward();
	
	// compute frequency estimates?
	if(MAG_FREQ == mSpctFormat){

		// hopRate / 2pi: converts phase diff from radians to Hz
		double factor = 1. / (M_2PI * unitsHop());
		
		// 2pi / overlap: expected phase diff of fundamental due to overlap
		double expdp1 = double(sizeHop())/sizeWin() * M_2PI;
		double fund = binFreq();

		bin(0)[1] = 0.;
		bin(numBins()-1)[1] = spu() * 0.5;

		for(unsigned k=1; k<numBins()-1; ++k){
			float ph = bin(k)[1];		// current phase
			double t = ph - mPhases[k];	// compute phase diff
			mPhases[k] = ph;			// save current phase
			t -= k*expdp1;				// subtract expected phase diff due to overlap
			t = scl::wrapPhase(t);		// wrap back into [-pi, pi)
			t *= factor;				// convert phase diff to freq deviation
			t += k*fund;				// freq deviation to freq
			bin(k)[1] = t;
		}
	}
}
예제 #8
0
파일: DFT.cpp 프로젝트: LuaAV/LuaAV
void DFT::forward(const float * window){ //printf("DFT::forward(const float *)\n");

	// this attempts to avoid a memory move, but doesn't work when window == mBuf
//	if(window != mBuf) mem::deepCopy(mBuf+1, window, sizeWin());
//	mem::deepZero(mBuf+1 + sizeWin(), sizePad());	// zero pad
//	// TODO: zero-phase window (rotate buffer 180)
//
//	mFFT.forward(mBuf+1, true);
//	
//	// re-arrange DC and Nyquist bins
//	mBuf[0] = mBuf[1];
//	mBuf[1] = 0.f;
//	mBuf[numBins()*2-1] = 0.f;

	// old code which did a mem move, rather offsetting input buffer pointer...
	if(window != mBuf) mem::deepCopy(mBuf, window, sizeWin());
	mem::deepZero(mBuf + sizeWin(), sizePad());	// zero pad
	//... do zero-phase window (rotate buffer 180)

	mFFT.forward(mBuf, true);
	
	// re-arrange DC and Nyquist bins
	mem::deepMove(mBuf+2, mBuf+1, sizeDFT()-1);
	mBuf[1] = 0.f;
	mBuf[numBins()*2-1] = 0.f;
	
	switch(mSpctFormat){
	case Bin::Polar:
	case Bin::MagFreq:
		RECT_POLAR
		//arr::mul(bins0(), gen::val(normForward()), nbins);
		break;
	
	default:;	// rectangular
		//arr::mul(bins0(), gen::val(normForward()), nbins<<1);
	}
}