1- import { useState } from 'react' ;
1+ import { useState , useEffect , useRef } from 'react' ;
22import Display from './Display' ;
33
44/**
@@ -10,63 +10,92 @@ import Display from './Display';
1010 * width: number,
1111 * height: number}}
1212 */
13- function EQ ( { wasmModule, width, height, freqs : liveFreqs } ) {
13+ function EQ ( { wasmModule, width, height, freqs : liveFreqs , eq , setEq } ) {
1414 const xRange = [ 20 , 20000 ] ;
1515
16- // Initialize nodes and curves for the EQ
17- const logXMin = Math . log ( xRange [ 0 ] ) ;
18- const logXMax = Math . log ( xRange [ 1 ] ) ;
19- const initialNodes = Array . from ( { length : 5 } , ( _ , i ) => ( {
20- x : Math . exp ( logXMin + ( i / 4 ) * ( logXMax - logXMin ) ) ,
21- y : 0.8
22- } ) ) ;
23- const initialCurves = Array ( initialNodes . length - 1 ) . fill ( 0 ) ;
16+ const initialNodes = useRef (
17+ eq ?. nodes ?. length
18+ ? eq . nodes
19+ : Array . from ( { length : 5 } , ( _ , i ) => ( {
20+ x : Math . exp ( Math . log ( xRange [ 0 ] ) + ( i / 4 ) * ( Math . log ( xRange [ 1 ] ) - Math . log ( xRange [ 0 ] ) ) ) ,
21+ y : 0.8 ,
22+ } ) )
23+ ) . current ;
2424
25- const [ nodes , setNodes ] = useState ( initialNodes ) ;
26- const [ curves , setCurves ] = useState ( initialCurves ) ;
25+ const initialCurves = useRef ( eq ?. curves ?. length ? eq . curves : Array ( initialNodes . length - 1 ) . fill ( 0 ) ) . current ;
2726
28- return (
29- < div className = 'EQ' >
30- < h3 > Frequency EQ</ h3 >
31- < Display
32- width = { width }
33- height = { height }
34- nodes = { nodes }
35- xRange = { xRange }
36- curves = { curves }
37- onNodesChange = { setNodes }
38- onCurvesChange = { setCurves }
39- freqs = { wasmModule ? ( ( ) => {
40- // Manually convert JS arrays to the Embind Vector types.
41- const nodesVec = new wasmModule . VectorNode ( ) ;
42- nodes . forEach ( node => nodesVec . push_back ( node ) ) ;
27+ const [ nodes , setNodesLocal ] = useState ( initialNodes ) ;
28+ const [ curves , setCurvesLocal ] = useState ( initialCurves ) ;
4329
44- const curvesVec = new wasmModule . VectorDouble ( ) ;
45- curves . forEach ( curve => curvesVec . push_back ( curve ) ) ;
30+ const lastParentEqRef = useRef ( JSON . stringify ( eq || { } ) ) ;
4631
47- const freqsVec = new wasmModule . VectorVectorDouble ( ) ;
48- ( liveFreqs || [ ] ) . forEach ( freqPair => {
49- const pair = new wasmModule . VectorDouble ( ) ;
50- pair . push_back ( freqPair [ 0 ] ) ;
51- pair . push_back ( freqPair [ 1 ] ) ;
52- freqsVec . push_back ( pair ) ;
53- pair . delete ( ) ;
54- } ) ;
32+ // When local nodes/curves change (user edits), push to parent only if different
33+ useEffect ( ( ) => {
34+ const parentSerialized = lastParentEqRef . current ;
35+ const localSerialized = JSON . stringify ( { nodes, curves } ) ;
36+ if ( parentSerialized !== localSerialized ) {
37+ setEq ( { nodes, curves } ) ;
38+ lastParentEqRef . current = localSerialized ;
39+ }
40+ } , [ nodes , curves , setEq ] ) ;
5541
56- const result = wasmModule . applyEnvelope ( nodesVec , curvesVec , freqsVec ) ;
42+ // When parent eq prop changes (preset load), update local nodes/curves but only if really different
43+ useEffect ( ( ) => {
44+ if ( ! eq ) return ;
45+ const parentSerialized = JSON . stringify ( eq ) ;
46+ const localSerialized = JSON . stringify ( { nodes, curves } ) ;
47+ if ( parentSerialized !== localSerialized ) {
48+ if ( eq . nodes ) setNodesLocal ( eq . nodes ) ;
49+ if ( eq . curves ) setCurvesLocal ( eq . curves ) ;
50+ lastParentEqRef . current = parentSerialized ;
51+ }
52+ // eslint-disable-next-line react-hooks/exhaustive-deps
53+ } , [ eq ] ) ;
5754
58- // Clean up the memory allocated by Embind
59- nodesVec . delete ( ) ;
60- curvesVec . delete ( ) ;
61- freqsVec . delete ( ) ;
55+ const processedFreqs = wasmModule
56+ ? ( ( ) => {
57+ const nodesVec = new wasmModule . VectorNode ( ) ;
58+ nodes . forEach ( ( node ) => nodesVec . push_back ( node ) ) ;
6259
63- return result ;
64- } ) ( ) : [ ] }
65- isLogarithmic = { true }
66- wasmModule = { wasmModule }
67- />
68- </ div >
69- ) ;
60+ const curvesVec = new wasmModule . VectorDouble ( ) ;
61+ curves . forEach ( ( curve ) => curvesVec . push_back ( curve ) ) ;
62+
63+ const freqsVec = new wasmModule . VectorVectorDouble ( ) ;
64+ ( liveFreqs || [ ] ) . forEach ( ( [ f , a ] ) => {
65+ const pair = new wasmModule . VectorDouble ( ) ;
66+ pair . push_back ( f ) ;
67+ pair . push_back ( a ) ;
68+ freqsVec . push_back ( pair ) ;
69+ pair . delete ( ) ;
70+ } ) ;
71+
72+ const result = wasmModule . applyEnvelope ( nodesVec , curvesVec , freqsVec ) ;
73+
74+ nodesVec . delete ( ) ;
75+ curvesVec . delete ( ) ;
76+ freqsVec . delete ( ) ;
77+
78+ return result ;
79+ } ) ( )
80+ : [ ] ;
81+
82+ return (
83+ < div className = "EQ" >
84+ < h3 > Frequency EQ</ h3 >
85+ < Display
86+ width = { width }
87+ height = { height }
88+ nodes = { nodes }
89+ xRange = { xRange }
90+ curves = { curves }
91+ onNodesChange = { setNodesLocal }
92+ onCurvesChange = { setCurvesLocal }
93+ freqs = { processedFreqs }
94+ isLogarithmic = { true }
95+ wasmModule = { wasmModule }
96+ />
97+ </ div >
98+ ) ;
7099}
71100
72101export default EQ ;
0 commit comments