void STFT::inverse(float * dst){ //printf("STFT::inverse(float *)\n"); if(Bin::MagFreq == mSpctFormat){ //mem::copy(bins1(), mPhases, numBins()); // not correct, need to unwrap frequencies for(uint32_t i=1; i<numBins()-1; ++i) bins()[i] = mPhases[i]; } DFT::inverse(0); // result goes into mBuf // undo zero-phase windowing rotation? if(mRotateForward) mem::rotateHalf(mBuf, sizeWin()); // apply secondary window to smooth ends? if(mWindowInverse){ arr::mulBartlett(mBuf, sizeWin()); } if(overlapping()){ //inverse windows overlap? // scale inverse so overlap-add is normalized //arr::mul(mBuf, gen::val(mInvWinMul), sizeWin()); slice(mBuf, sizeWin()) *= mInvWinMul; // shift old output left while adding new output arr::add(mBufInv, mBuf, mBufInv + sizeHop(), sizeWin() - sizeHop()); } // copy remaining non-overlapped portion of new output uint32_t sizeOverlap = sizeWin() - sizeHop(); mem::deepCopy(mBufInv + sizeOverlap, mBuf + sizeOverlap, sizeHop()); // copy output if external buffer provided if(dst) mem::deepCopy(dst, mBufInv, sizeWin()); }
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(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()); } }
STFT::STFT(unsigned winSize, unsigned hopSize, unsigned padSize, WindowType winType, SpectralType specType, unsigned numAuxA) : DFT(0, 0, specType, numAuxA), mSlide(winSize, hopSize), mFwdWin(0), mPhases(0), mAccums(0), mWinType(winType), mWindowInverse(true), mRotateForward(false) { mBufInv = 0; resize(winSize, padSize); sizeHop(hopSize); }
STFT::STFT(uint32_t winSize, uint32_t hopSize, uint32_t padSize, WinType::type windowType, Bin::t binT, uint32_t numAuxA) : DFT(0, 0, binT, numAuxA), mSlide(winSize, hopSize), mFwdWin(0), mPhases(0), mWinType(windowType), mWindowInverse(true), mRotateForward(false) { mBufInv = 0; resize(winSize, padSize); sizeHop(hopSize); }
void STFT::inverse(float * dst){ //printf("STFT::inverse(float *)\n"); if(MAG_FREQ == mSpctFormat){ // TODO: for(uint32_t i=1; i<numBins()-1; ++i) bin(i)[1] = mPhases[i]; } DFT::inverse(0); // result goes into bufPos() // undo zero-phase windowing rotation? if(mRotateForward) mem::rotateHalf(bufPos(), sizeWin()); // apply secondary window to smooth ends? if(mWindowInverse){ arr::mulBartlett(bufPos(), sizeWin()); } if(overlapping()){ //inverse windows overlap? // scale inverse so overlap-add is normalized //slice(mBuf, sizeWin()) *= mInvWinMul; for(unsigned i=0; i<sizeWin(); ++i){ bufPos()[i] *= mInvWinMul; } // shift old output left while adding new output arr::add(mBufInv, bufPos(), mBufInv + sizeHop(), sizeWin() - sizeHop()); } // copy remaining non-overlapped portion of new output uint32_t sizeOverlap = sizeWin() - sizeHop(); mem::deepCopy(mBufInv + sizeOverlap, bufPos() + sizeOverlap, sizeHop()); // copy output if external buffer provided if(dst) mem::deepCopy(dst, mBufInv, sizeWin()); }
void STFT::computeInvWinMul(){ // compute sum of overlapping elements of forward window if(overlapping()){ float sum = 0.f; for(uint32_t i=0; i<sizeWin(); i+=sizeHop()){ sum += mFwdWin[i] * (mWindowInverse ? scl::bartlett(2*i/(float)sizeWin() - 1.f): 1.f); } mInvWinMul = 1/sum; } // if no overlap, then do not scale output else{ mInvWinMul = 1; } //printf("mInvWinMul: %f\n", mInvWinMul); }
// 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; }
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); }
void DFT::onResync(double r){ DFTBase<float>::onResync(r); mSyncHop.ups((double)sizeHop() * ups()); //printf("[%p] hop: %d, ups: %f\n", this, sizeHop(), spu()); }