@@ -37,7 +37,8 @@ const FFT = forwardRef(
3737 const containerRef = useRef < HTMLDivElement > ( null ) ;
3838 const { theme } = useTheme ( ) ;
3939 const maxFreq = 60 ;
40- const [ betaPower , setBetaPower ] = useState ( 0 ) ;
40+ const [ betaPower , setBetaPower ] = useState < number > ( 0 ) ;
41+ const betaPowerRef = useRef < number > ( 0 ) ;
4142 const channelColors = useMemo ( ( ) => [ "red" , "green" , "blue" , "purple" , "orange" , "yellow" ] , [ ] ) ;
4243 const canvasContainerRef = useRef < HTMLDivElement > ( null ) ;
4344 const dataPointCountRef = useRef < number > ( 1000 ) ;
@@ -92,65 +93,112 @@ const FFT = forwardRef(
9293 return smoothed ;
9394 }
9495 }
96+
97+ // Add this useEffect to calculate initial beta power
98+ useEffect ( ( ) => {
99+ if ( fftData . length > 0 && fftData [ 0 ] . length > 0 ) {
100+ const channelData = fftData [ 0 ] ;
101+ const betaPower = calculateBandPower ( channelData , [ 13 , 32 ] ) ; // Beta range
102+ const totalPower = calculateBandPower ( channelData , [ 0.5 , 100 ] ) ; // Full range
103+ const normalizedBeta = ( betaPower / totalPower ) * 100 ;
104+ setBetaPower ( normalizedBeta ) ;
105+ betaPowerRef . current = normalizedBeta ;
106+ }
107+ } , [ fftData ] ) ;
108+
109+ // Add this calculateBandPower function to FFT.tsx
110+ const calculateBandPower = useCallback ( ( magnitudes : number [ ] , range : [ number , number ] ) => {
111+ const [ startFreq , endFreq ] = range ;
112+ const freqStep = currentSamplingRate / fftSize ;
113+ const startIndex = Math . max ( 1 , Math . floor ( startFreq / freqStep ) ) ;
114+ const endIndex = Math . min ( Math . floor ( endFreq / freqStep ) , magnitudes . length - 1 ) ;
115+
116+ let power = 0 ;
117+ for ( let i = startIndex ; i <= endIndex ; i ++ ) {
118+ power += magnitudes [ i ] * magnitudes [ i ] ;
119+ }
120+ return power ;
121+ } , [ currentSamplingRate , fftSize ] ) ;
122+
95123 const filter = new SmoothingFilter ( 32 , fftSize / 2 ) ; // 5-point moving average
96124 // console.log("fft", betaPower);
97125 const renderBandPowerView = ( ) => {
98126 switch ( activeBandPowerView ) {
99127 case 'bandpower' :
100- return < BandPowerGraph fftData = { fftData } onBetaUpdate = { setBetaPower } samplingRate = { currentSamplingRate } /> ;
128+ return (
129+ < BandPowerGraph
130+ fftData = { fftData }
131+ // Update both state and ref
132+ onBetaUpdate = { ( beta ) => {
133+ betaPowerRef . current = beta ;
134+ setBetaPower ( beta ) ;
135+ } }
136+
137+ samplingRate = { currentSamplingRate }
138+ />
139+ ) ;
101140 case 'brightcandle' :
102- return < BrightCandleView betaPower = { betaPower } fftData = { fftData } /> ;
141+ return (
142+ < BrightCandleView
143+ betaPower = { betaPower } // Use state value instead of ref
144+ fftData = { fftData }
145+ />
146+ ) ;
103147 case 'moveup' :
104148 return (
105149 < div className = "w-full h-full flex items-center justify-center text-gray-400" >
106150 Move Up View
107151 </ div >
108152 ) ;
109153 default :
110- return < BandPowerGraph fftData = { fftData } onBetaUpdate = { setBetaPower } samplingRate = { currentSamplingRate } /> ;
154+ return (
155+ < BandPowerGraph
156+ fftData = { fftData }
157+ // Update both state and ref
158+ onBetaUpdate = { ( beta ) => {
159+ betaPowerRef . current = beta ;
160+ setBetaPower ( beta ) ;
161+ } }
162+
163+ samplingRate = { currentSamplingRate }
164+ />
165+ ) ;
111166 }
112167 } ;
113168
114-
115169 useImperativeHandle (
116170 ref ,
117171 ( ) => ( {
118172 updateData ( data : number [ ] ) {
119173 for ( let i = 0 ; i < 1 ; i ++ ) {
120174 const sensorValue = data [ i + 1 ] ;
121- // Add new sample to the buffer
122175 fftBufferRef . current [ i ] . push ( sensorValue ) ;
123- // Update the plot with the new sensor value
124176 updatePlot ( sensorValue , Zoom ) ;
125- // Ensure the buffer does not exceed fftSize
177+
126178 if ( fftBufferRef . current [ i ] . length > fftSize ) {
127- fftBufferRef . current [ i ] . shift ( ) ; // Remove the oldest sample
179+ fftBufferRef . current [ i ] . shift ( ) ;
128180 }
129181 samplesReceived ++ ;
130182
131- // Trigger FFT computation every 5 samples
132- if ( samplesReceived % 25 === 0 ) {
133- const processedBuffer = fftBufferRef . current [ i ] . slice ( 0 , fftSize ) ; // Ensure exact length
183+ // Trigger FFT computation more frequently
184+ if ( samplesReceived % 5 === 0 ) { // Changed from 25 to 5
185+ const processedBuffer = fftBufferRef . current [ i ] . slice ( 0 , fftSize ) ;
134186 const floatInput = new Float32Array ( processedBuffer ) ;
135-
136- // Calculate frequencies for the FFT result
137187 const fftMags = fftProcessor . computeMagnitudes ( floatInput ) ;
138- const magArray = Array . from ( fftMags ) ; // Convert Float32Array to regular array
188+ const magArray = Array . from ( fftMags ) ;
139189 const smoothedMags = filter . getSmoothedValues ( magArray ) ;
140- // Update the FFT data state
190+
141191 setFftData ( ( prevData ) => {
142192 const newData = [ ...prevData ] ;
143193 newData [ i ] = smoothedMags ;
144194 return newData ;
145195 } ) ;
146-
147196 }
148197 }
149198 } ,
150199 } ) ,
151200 [ Zoom , timeBase , canvasCount , fftSize , currentSamplingRate ]
152201 ) ;
153-
154202 ////
155203 class FFT {
156204 private size : number ;
0 commit comments