fft_test.bas
'******************** 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
|
|