/*************************************************************************** * Copyright (C) 2004 by Johan Maes - ON4QZ * * on4qz@telenet.be * * http://users.telenet.be/on4qz * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /* Based on: Program: REALFFT.C Author: Philip VanBaren */ #include "fftdisplay.h" #include "math.h" #include "qmessagebox.h" #include #include #include "qsstvglobal.h" #define FFTAVERAGING 0.1 #define FFTSPAN 2500 fftDisplay::fftDisplay(QWidget *p,const char *name): QFrame(p,name) { sineTable=NULL; bitReversed=NULL; arMag=NULL; oBuffer=NULL; fftTempArray=NULL; FFTArray=NULL; im=NULL; setFrameStyle( QFrame::Panel | QFrame::Sunken ); setBackgroundColor(black); showWaterfall=FALSE; enabled=FALSE; maxMagnitude=1; } fftDisplay::~fftDisplay() { deleteBuffers(); } /** delete allocated buffers */ void fftDisplay::deleteBuffers() { if (sineTable) delete sineTable; if (bitReversed) delete bitReversed; if (arMag) delete arMag; if (oBuffer) delete oBuffer; if (FFTArray) delete FFTArray; if (fftTempArray) delete fftTempArray; } /** must be called before performing any FFT */ void fftDisplay::initFFT(unsigned int fftLength, int samplingrate) { unsigned int i; int temp; int mask; deleteBuffers(); h=contentsRect().height(); w=contentsRect().width(); FFTArray=new QPointArray(w); points = fftLength; arMag=new uint[fftLength/2]; fftTempArray=new float[w]; for (i = 0; i 0;mask >>= 1) temp=(temp >> 1) + (i&mask ? points/2 : 0); bitReversed[i]=temp; } for(i=0;i0) { A=oBuffer; B=oBuffer+butterfliesPerGroup*2; sptr=sineTable; while(A>= 1; } /* * Massage output to get the output for a real input sequence. */ br1=bitReversed+1; br2=bitReversed+points/2-1; while(br1<=br2) { double temp1,temp2; double sin=sineTable[*br1]; double cos=sineTable[*br1+1]; A=oBuffer+*br1; B=oBuffer+*br2; HRplus = (HRminus = *A - *B ) + (*B*2); HIplus = (HIminus = *(A+1) - *(B+1)) + (*(B+1)*2); temp1 = (sin*HRminus - cos*HIplus); temp2 = (cos*HRminus + sin*HIplus); *B = (*A = (HRplus + temp1)/2) - temp1; *(B+1) = (*(A+1) = (HIminus + temp2)/2) - HIminus; br1++; br2--; } /* * Handle DC bin separately */ oBuffer[0]+=oBuffer[1]; oBuffer[1]=0; maxMagnitude=0; avgMagnitude=0; for (i = 0; i size().width(),e->size().height()); im->create(e->size(),32); h=e->size().height(); w=e->size().width(); FFTArray->resize(w); if(fftTempArray) delete [] fftTempArray; fftTempArray=new float[w]; for(int i=0;iscanLine(i),im->scanLine(i+1),w*sizeof(uint)); } uint *ptr=(uint *)im->scanLine(h-1); // pseudo-coloring for (i=0; ifftTempArray[i]) fftTempArray[i]=ttt; else fftTempArray[i]=fftTempArray[i]*(1-FFTAVERAGING)+FFTAVERAGING*(ttt); // maximum of 1; // fftTempArray[i]=fftTempArray[i]*(1-FFTAVERAGING)+FFTAVERAGING*(30+10*log10((float)arMag[ind]/(float)maxMagnitude))/30; if(fftTempArray[i]>1) fftTempArray[i]=1; if(fftTempArray[i]<0) fftTempArray[i]=0; //ranging from 0db to -90db int val=(uint)(fftTempArray[i]*255); c.setHsv(255-val,255,255); ptr[i]=c.rgb(); t=bw+h-(val*h)/255; t=(tsetPoint(i,i,t); } if(showWaterfall) { p.drawImage(0,0,*im); } else { p.eraseRect(contentsRect()); p.setPen(red); t=bw+((1200)*w/FFTSPAN); p.drawLine(t,bw,t,h+bw); p.setPen(blue); t=bw+((1500)*w/FFTSPAN); p.drawLine(t,bw,t,h+bw); t=bw+((2300)*w/FFTSPAN); p.drawLine(t,bw,t,h+bw); p.setPen(white); for (i=0;i<7;i++) { t=bw+(((1600+i*100))*w/FFTSPAN); p.drawLine(t,bw,t,h+bw); } p.setPen(green); p.drawPolyline(*FFTArray); } } void fftDisplay::mousePressEvent( QMouseEvent *e ) { if (e->button() == LeftButton) { showWaterfall=!showWaterfall; } }