// 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()); }
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()); }
// 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; } } }
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 STFT::resize(uint32_t winSize, uint32_t padSize){ float * tmp = mBufInv; uint32_t oldWinSize = sizeWin(); uint32_t oldNumBins = numBins(); // resize DFT buffers DFT::resize(winSize, padSize); mBufInv = tmp; // DFT::resize changes this, so change it back // resize STFT-specific buffers mSlide.sizeWin(winSize); mem::resize(mFwdWin, oldWinSize, winSize); mem::resize(mBufInv, oldWinSize, winSize); mem::resize(mPhases, oldNumBins, numBins()); mem::deepZero(mPhases, numBins()); mem::deepZero(mBufInv, winSize); // re-compute fwd window winType(mWinType); }
// 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::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()); }
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); } }
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()); }