'******************** Sample FFT test code *********************** 'this program will add sine waves, perform an FFT (or DFT), then ' plot the amplitude of the spectrum, then reconstruct the ' original input waveform ' Uses fftlib.dll -- a dll made by Freebasic STDCALL convention '***************************************************************** $TYPECHECK ON $INCLUDE <RapidQ2.inc> $INCLUDE <QChart.inc> $INCLUDE <fftlib.inc> '----- Form Event SUB Declarations Declare Sub frmMainResize (SENDER As QFORM) declare Sub DrawOrig CONST pi = 3.141592653589793# 'set some maximum limits DEFINT maxc = 10 'max columns DEFINT maxr = 20 'max rows DEFINT maxv = 16000 'should be at least double sample points 'set the number of data points DIM n AS INTEGER n = 512 'try 256, or 512, 1024, 4096 8192, etc. DIM pi2 as single pi2 = pi * 2 DIM th AS SINGLE DIM xdata(0 TO maxv) AS SINGLE DIM ydata(0 TO maxv) AS SINGLE DIM tdata(0 TO maxv) AS SINGLE DIM i AS INTEGER DIM myStep AS SINGLE myStep = pi2 /n DIM myTime AS SINGLE '**** build our waveform of sine waves ****** i = 0 FOR th = 0.0 TO pi2 STEP myStep '(pi2 /(n/1.0001)) '1 sec period of n samples xdata(i) = 16 * COS(th * 2) 'amp & Hz xdata(i) = xdata(i) + 6 * COS(th * 8) 'amp & Hz xdata(i) = xdata(i) + 4 * SIN(th * 14) 'amp & Hz xdata(i) = xdata(i) + 2 * COS(th * 20) 'amp & Hz xdata(i) = xdata(i) + 2 * SIN(th * 26) 'amp & Hz xdata(i) = xdata(i) + 4 * COS(th * 32) 'amp & Hz xdata(i) = xdata(i) + 8 * SIN(th * 38) 'amp & Hz xdata(i) = xdata(i) + 12 * SIN(th * 65) 'amp & Hz xdata(i) = xdata(i) + 12 * SIN(th * 85) 'amp & Hz xdata(i) = xdata(i) + 12 * SIN(th * 103) 'amp & Hz xdata(i) = xdata(i) + 12 * SIN(th * 120) 'amp & Hz ydata(i) = 0 'nothing in imaginary domain tdata(i) = i i = i + 1 NEXT th '----- Define the main form Create frmMain As QFORM Width = 640 ClientHeight = 480 OnResize = frmMainResize Onshow = DrawOrig Create Graph1 As QCHART 'Create a copy of the new object Top = 0 : Left = 0 Width = frmMain.ClientWidth Height = frmMain.ClientHeight OnPaint = Graph1.PaintChart 'This line REQUIRED to process Repaints End Create'Graph1 End Create'frmMain Create FFTMain As QFORM Width = 640 left =300 top = 200 ClientHeight = 480 OnResize = frmMainResize Create Graph2 As QCHART 'Create a copy of the new object Top = 0 : Left = 0 Width = FFTMain.ClientWidth Height = FFTMain.ClientHeight OnPaint = Graph2.PaintChart 'This line REQUIRED to process Repaints End Create'Graph2 End Create Create iFFTMain As QFORM Width = 640 left =400 ClientHeight = 480 OnResize = frmMainResize Create Graph3 As QCHART 'Create a copy of the new object Top = 0 : Left = 0 Width = iFFTMain.ClientWidth Height = iFFTMain.ClientHeight OnPaint = Graph3.PaintChart 'This line REQUIRED to process Repaints End Create'Graph2 End Create Graph3.ClearAll Graph2.ClearAll Graph1.ClearAll frmMain.Showmodal 'draw the original input waveform Sub DrawOrig Dim j As Integer Dim i As Integer 'draw original data set With Graph1 .Initialize 'Set defaults .ChartType = ctXY 'XY Scatter Chart .ChartStyle = csLines 'just Lines, use csBoth for lines and Points .MainTitle.Text = "Original Data" .XTitle.Text = "X Axis" .YTitle.Text = "Y Axis" .Cols = 1 'Number of series .Rows = n-1 'Number of data points per series REDIM Graph1.XYData(.Cols,.Rows,2) 'Redim XYData. Note 3rd dim always 2 .DoLegend = false .Series(1).LineWidth = 2 For j = 0 To .Rows .XYData(1,j,1) = tdata(j) 'X Values (3rd dim 1) .XYData(1,j,2) = xdata(j) 'Y Values (3rd dim 2) Next j .DrawChart (FALSE) 'Draw it! End With 'calc the fft spectrum DIM xCopy(n) AS SINGLE DIM yCopy(n) AS SINGLE DIM Hz(0 TO n) AS SINGLE DIM ph(0 TO n) AS SINGLE DIM Amp(0 TO n) AS SINGLE myTime = TIMER fft(@xdata(0), @ydata(0), n, 0) FFTMagnitude(@xdata(0) , @ydata(0) , n, @Amp(0)) FFTPhase(@xdata(0), @ydata(0), n, @ph(0)) FFTFrequency(@Hz(0),(n/1.0!), n) ' ' or ' --------DFT any size sample --------------- ' DFT(@xdata(0), @ydata(0), n, 0) ' DFTMagnitude(@xdata(0) , @ydata(0) , n, @Amp(0)) ' DFTPhase(@xdata(0), @ydata(0), n, @ph(0)) ' FFTFrequency (@Hz(0), (n), n) SHowmessage "fft calculation time = " + str$(TIMER - myTime) ' '------------------------------------------ 'draw fourier domain data set With Graph2 .Initialize 'Set defaults .ChartType = ctXY 'XY Scatter Chart .ChartStyle = csLines 'just Lines, use csBoth for lines and Points .Cols = 1 'Number of series .DoLegend = false .Series(1).LineWidth = 2 .Rows = n\2 -1 'spectral data is 1/2 sample (nyquist limit) REDIM Graph2.XYData(.Cols,.Rows,2) 'Redim XYData. Note 3rd dim always 2 For j = 0 To .Rows .XYData(1,j,1) = Hz(j) 'X Values (3rd dim 1) .XYData(1,j,2) = amp(j) 'ph(j) 'Y Values (3rd dim 2) Next j .MainTitle.Text = "Spectrum" .XTitle.Text = "Frequency": .YTitle.Text = "Magnitude" .DrawChart (FALSE) End With FFTMain.Show 'check inverse fft(@xdata(0), @ydata(0), n, 1) 'time domain left in xData ' or ' DFT(@xdata(0), @ydata(0), n, 1) With Graph3 .Initialize 'Set defaults .ChartType = ctXY 'XY Scatter Chart .ChartStyle = csLines 'just Lines, use csBoth for lines and Points .Cols = 1 'Number of series .DoLegend = false .Series(1).LineWidth = 2 .Rows = n-1 REDIM Graph3.XYData(.Cols,.Rows,2) 'Redim XYData. Note 3rd dim always 2 For j = 0 To .Rows .XYData(1,j,1) = tdata(j) 'X Values (3rd dim 1) .XYData(1,j,2) = xdata(j) 'Y Values (3rd dim 2) Next j .MainTitle.Text = "reconstructed" .XTitle.Text = "Time": .YTitle.Text = "signal" .DrawChart (FALSE) End With iFFTMain.Show END SUB SUB frmMainResize (SENDER AS QForm) WITH Graph1 .Width = frmMain.ClientWidth 'Calculate new sizes .Height = frmMain.ClientHeight .RedrawChart 'Redraw the QChart Object END WITH 'Plus anything else that needs doing in your form resize END SUB