// 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()); } }
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()); }
// input is sizeWin void STFT::forward(const float * src){ //printf("STFT::forward(float *)\n"); if(src != bufPos()) mem::deepCopy(bufPos(), src, sizeWin()); // apply forward window arr::mul(bufPos(), mFwdWin, sizeWin()); // do zero-phase windowing rotation? if(mRotateForward) mem::rotateHalf(bufPos(), sizeWin()); DFT::forward(bufPos()); // compute frequency estimates? if(MAG_FREQ == mSpctFormat){ // // This will effectively subtract the expected phase difference from the computed. // // This extra step seems to give more precise frequency estimates. // { // float expdp = float(M_2PI * sizeHop()) / sizeDFT(); // for(uint32_t i=0; i<numBins(); ++i){ // mPhases[i] += expdp; // } // } // compute frequency estimates float factor = 1.f / (M_2PI * unitsHop()); // converts phase difference from radians to Hz // expected phase difference of fundamental float expdp1 = float(sizeHop())/sizeWin() * M_2PI; for(uint32_t i=1; i<numBins()-1; ++i){ float ph = bin(i)[1]; // current phase float dp = ph - mPhases[i] - i*expdp1; // compute phase difference dp = scl::wrapPhase(dp); // wrap back into [-pi, pi) mPhases[i] = ph; // save current phase bin(i)[1] = dp*factor; // convert phase diff to freq } // compute absolute frequencies by adding respective bin center frequency for(uint32_t i=0; i<numBins(); ++i){ bins()[i][1] += binFreq()*i; } } }
// 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; } } }
// The principle here is to configure things so that after the phase // accumulation step, the synthesis bin phases equal the analysis bin phases. // To do this, we first zero the phase accumulators and then compute new // instantaneous frequencies which after conversion yield a phase increment // equal to the analysis bin phase. STFT& STFT::resetPhases(){ mem::deepZero(mAccums, numBins()); // 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){ double t = mPhases[k]; // the phase diff is simply the analysis 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; } return *this; }