finish vocoder page redesign

This commit is contained in:
Aoife
2021-04-06 13:44:07 -04:00
parent 7424588885
commit f04f404bea
13 changed files with 647 additions and 466 deletions
+37 -14
View File
@@ -4,7 +4,7 @@ import { selectById } from './timbreSlice';
import VCO, { AudioIn } from './parameters/VCO'; import VCO, { AudioIn } from './parameters/VCO';
import Mixer from './parameters/Mixer'; import Mixer from './parameters/Mixer';
import Pitch from './parameters/Pitch'; import Pitch from './parameters/Pitch';
import EG from './parameters/EG'; import { VocoderEG } from './parameters/EG';
import LFO from './parameters/LFO'; import LFO from './parameters/LFO';
import { VocoderFilter, FCMod } from './parameters/Filter'; import { VocoderFilter, FCMod } from './parameters/Filter';
import { VocoderAmp } from './parameters/Amp'; import { VocoderAmp } from './parameters/Amp';
@@ -14,8 +14,9 @@ import Pans from './parameters/Pans';
export default function Vocoder(props) { export default function Vocoder(props) {
const ids = useSelector((state) => selectById(state, props.id)); const ids = useSelector((state) => selectById(state, props.id));
return ( return (
<div> <div className='h-screen grid grid-cols-8 grid-rows-3 gap-4 p-6'>
<VCO <VCO
className='col-span-2'
name='VCO' name='VCO'
id={ids.vco} id={ids.vco}
waveforms={[ waveforms={[
@@ -96,18 +97,40 @@ export default function Vocoder(props) {
{ value: 'Voice4' }, { value: 'Voice4' },
]} ]}
/> />
<AudioIn name='Audio In' id={ids.audioIn} /> <AudioIn className='col-span-2' name='Audio In' id={ids.audioIn} />
<Mixer name='Mixer' id={ids.mixer} /> <Mixer className='col-span-1' name='Mixer' id={ids.mixer} />
<Pitch name='Pitch' id={ids.pitch} /> <Pitch className='col-span-3' name='Pitch' id={ids.pitch} />
<VocoderFilter name='Filter' id={ids.filter} /> <div className='col-span-8 grid grid-cols-9 grid-rows-1 gap-4'>
<FCMod name='FC Mod' id={ids.fcMod} /> <div />
<VocoderAmp name='Amp' id={ids.amp} /> <VocoderFilter name='Filter' id={ids.filter} />
<EG name='EG' id={ids.eg} /> <FCMod name='FC Mod' id={ids.fcMod} />
<div /> <VocoderAmp className='col-span-2' name='Amp' id={ids.amp} />
<LFO name='LFO 1' id={ids.lfo1} /> <VocoderEG className='col-span-3' name='EG' id1={ids.eg} />
<LFO name='LFO 2' id={ids.lfo2} /> </div>
<Levels name='Levels' id={ids.levels} /> <LFO
<Pans name='Pans' id={ids.pans} /> className='col-span-2'
name='LFO 1'
id={ids.lfo1}
waveforms={[
{ value: 'Saw' },
{ value: 'Square 1' },
{ value: 'Triangle' },
{ value: 'Sample & Hold' },
]}
/>
<LFO
className='col-span-2'
name='LFO 2'
id={ids.lfo2}
waveforms={[
{ value: 'Saw' },
{ value: 'Square 2' },
{ value: 'Sine' },
{ value: 'Sample & Hold' },
]}
/>
<Levels className='col-span-2' name='Levels' id={ids.levels} />
<Pans className='col-span-2' name='Pans' id={ids.pans} />
</div> </div>
); );
} }
+66 -54
View File
@@ -84,59 +84,71 @@ export const VocoderAmp = (props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
<div className={props.className}> <Card className={props.className} header={props.name}>
<span>{`${props.name}`}</span> <div className='flex flex-row'>
Amp Level <div className='flex flex-col items-center w-1/2'>
<Knob <h3>Amp Level</h3>
value={parameters.ampLevel} <Knob
max={127} value={parameters.ampLevel}
onChange={(value) => max={127}
dispatch( onChange={(value) =>
parameterUpdated({ dispatch(
id: props.id, parameterUpdated({
changes: { ampLevel: value }, id: props.id,
}) changes: { ampLevel: value },
) })
} )
/> }
Direct Level />
<Knob </div>
value={parameters.directLevel} <div className='flex flex-col items-center w-1/2'>
max={127} <h3>Direct Level</h3>
onChange={(value) => <Knob
dispatch( value={parameters.directLevel}
parameterUpdated({ max={127}
id: props.id, onChange={(value) =>
changes: { directLevel: value }, dispatch(
}) parameterUpdated({
) id: props.id,
} changes: { directLevel: value },
/> })
Amp Keyboard Tracking )
<Knob }
value={parameters.ampTrack} />
dual={true} </div>
max={63} </div>
onChange={(value) => <div className='flex flex-row'>
dispatch( <div className='flex flex-col items-center w-1/2'>
parameterUpdated({ <h3>Keyboard Track</h3>
id: props.id, <Knob
changes: { ampTrack: value }, value={parameters.ampTrack}
}) dual={true}
) max={63}
} onChange={(value) =>
/> dispatch(
<Checkbox parameterUpdated({
value={parameters.distortion} id: props.id,
onChange={(value) => changes: { ampTrack: value },
dispatch( })
parameterUpdated({ )
id: props.id, }
changes: { distortion: value }, />
}) </div>
) <div className='flex flex-col items-center w-1/2'>
} <h3>Distortion</h3>
/> <Checkbox
</div> value={parameters.distortion}
onChange={(value) =>
dispatch(
parameterUpdated({
id: props.id,
changes: { distortion: value },
})
)
}
/>
</div>
</div>
</Card>
); );
}; };
+87
View File
@@ -168,3 +168,90 @@ export default function EG(props) {
</Card> </Card>
); );
} }
export function VocoderEG(props) {
const parameters_eg_1 = useSelector((state) => selectById(state, props.id1));
const dispatch = useDispatch();
return (
<Card className={props.className} header={props.name}>
<div className='-mt-1 flex flex-row justify-evenly'>
<div className='flex flex-col items-center'>
<h3>Attack</h3>
<Knob
value={parameters_eg_1.attack}
max={127}
onChange={(value) =>
dispatch(
parameterUpdated({
id: props.id1,
changes: { attack: value },
})
)
}
/>
</div>
<div className='flex flex-col items-center'>
<h3>Decay</h3>
<Knob
value={parameters_eg_1.decay}
max={127}
onChange={(value) =>
dispatch(
parameterUpdated({
id: props.id1,
changes: { decay: value },
})
)
}
/>
</div>
<div className='flex flex-col items-center'>
<h3>Sustain</h3>
<Knob
value={parameters_eg_1.sustain}
max={127}
onChange={(value) =>
dispatch(
parameterUpdated({
id: props.id1,
changes: { sustain: value },
})
)
}
/>
</div>
<div className='flex flex-col items-center'>
<h3>Release</h3>
<Knob
value={parameters_eg_1.release}
max={127}
onChange={(value) =>
dispatch(
parameterUpdated({
id: props.id1,
changes: { release: value },
})
)
}
/>
</div>
</div>
<div className='-mt-8 flex flex-col items-center'>
<h3>EG Reset</h3>
<Checkbox
className='checkbox'
value={parameters_eg_1.egReset}
onChange={(value) =>
dispatch(
parameterUpdated({
id: props.id1,
changes: { egReset: value },
})
)
}
/>
</div>
</Card>
);
}
+95 -86
View File
@@ -3,7 +3,7 @@ import Card from '../card';
import { Select, Knob } from '../../utils/components'; import { Select, Knob } from '../../utils/components';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { selectById, parameterUpdated } from './parameterSlice.js'; import { selectById, parameterUpdated } from './parameterSlice.js';
import { Slider, SelectList } from '../../helpers/Helpers'; import { Slider } from '../../helpers/Helpers';
export default function Filter(props) { export default function Filter(props) {
const parameters = useSelector((state) => selectById(state, props.id)); const parameters = useSelector((state) => selectById(state, props.id));
@@ -38,7 +38,7 @@ export default function Filter(props) {
<h3 className='text-lg font-semibold text-gray-900'>Cutoff</h3> <h3 className='text-lg font-semibold text-gray-900'>Cutoff</h3>
<Knob <Knob
value={parameters.cutoff} value={parameters.cutoff}
maxValue={127} max={127}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
@@ -74,7 +74,7 @@ export default function Filter(props) {
<Knob <Knob
value={parameters.egIntensity} value={parameters.egIntensity}
dual={true} dual={true}
maxValue={63} max={63}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
@@ -113,51 +113,55 @@ export const VocoderFilter = (props) => {
const parameters = useSelector((state) => selectById(state, props.id)); const parameters = useSelector((state) => selectById(state, props.id));
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
<div className={props.className}> <Card className={props.className} header={props.name}>
<span>{`${props.name}`}</span> <div className='-mt-3 flex flex-col justify-around'>
Cutoff <div className='flex flex-col items-center'>
<Slider <h3>Cutoff</h3>
parameter={parameters.cutoff} <Knob
min={0} value={parameters.cutoff}
max={127} max={127}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
id: props.id, id: props.id,
changes: { cutoff: value }, changes: { cutoff: value },
}) })
) )
} }
/> />
Resonance </div>
<Slider <div className='flex flex-col items-center'>
parameter={parameters.resonance} <h3>Resonance</h3>
min={0} <Knob
max={127} value={parameters.resonance}
onChange={(value) => max={127}
dispatch( onChange={(value) =>
parameterUpdated({ dispatch(
id: props.id, parameterUpdated({
changes: { resonance: value }, id: props.id,
}) changes: { resonance: value },
) })
} )
/> }
EF Sense />
<Slider </div>
parameter={parameters.efSense} <div className='flex flex-col items-center'>
min={0} <h3>EF Sense</h3>
max={127} <Knob
onChange={(value) => value={parameters.efSense}
dispatch( max={127}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { efSense: value }, parameterUpdated({
}) id: props.id,
) changes: { efSense: value },
} })
/> )
</div> }
/>
</div>
</div>
</Card>
); );
}; };
@@ -165,43 +169,48 @@ export const FCMod = (props) => {
const parameters = useSelector((state) => selectById(state, props.id)); const parameters = useSelector((state) => selectById(state, props.id));
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
<div> <Card className={props.className} header={props.name}>
<span>{`${props.name}`}</span> <div className='-mt-4 flex flex-col justify-around space-y-4'>
Source <div className='flex flex-col items-center space-y-0.5'>
<SelectList <h3>Source</h3>
value={parameters.source} <Select
list={[ className='select w-full'
{ value: 'Amp EG' }, value={parameters.source}
{ value: 'LFO 1' }, list={[
{ value: 'LFO 2' }, { value: 'Amp EG' },
{ value: 'Velocity' }, { value: 'LFO 1' },
{ value: 'Keyboard Track' }, { value: 'LFO 2' },
{ value: 'Pitch Bend' }, { value: 'Velocity' },
{ value: 'Mod Wheel' }, { value: 'Keyboard Track' },
]} { value: 'Pitch Bend' },
onChange={(value) => { value: 'Mod Wheel' },
dispatch( ]}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { source: value }, parameterUpdated({
}) id: props.id,
) changes: { source: value },
} })
/> )
Intensity }
<Slider />
parameter={parameters.intensity} </div>
min={0} <div className='flex flex-col items-center'>
max={127} <h3>Intensity</h3>
onChange={(value) => <Knob
dispatch( value={parameters.intensity}
parameterUpdated({ max={127}
id: props.id, onChange={(value) =>
changes: { intensity: value }, dispatch(
}) parameterUpdated({
) id: props.id,
} changes: { intensity: value },
/> })
</div> )
}
/>
</div>
</div>
</Card>
); );
}; };
+1 -1
View File
@@ -88,7 +88,7 @@ export default function LFO(props) {
/> />
</div> </div>
</div> </div>
<div className='flex flex-col items-center w-1/2'> <div className='flex flex-col items-center w-1/2 space-y-1'>
<h3>Frequency</h3> <h3>Frequency</h3>
<Knob <Knob
value={parameters.frequency} value={parameters.frequency}
+126 -119
View File
@@ -1,132 +1,139 @@
import React from 'react'; import React from 'react';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import Card from '../card';
import { selectById, parameterUpdated } from './parameterSlice.js'; import { selectById, parameterUpdated } from './parameterSlice.js';
import { Slider } from '../../helpers/Helpers'; import { Knob } from '../../utils/components';
export default function Levels(props) { export default function Levels(props) {
const parameters = useSelector((state) => selectById(state, props.id)); const parameters = useSelector((state) => selectById(state, props.id));
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
<div> <Card className={props.className} header={props.name}>
<span>{`${props.name}`}</span> <div className='flex flex-row'>
<div> <div className='flex flex-col items-center w-1/4'>
Level 1 <h3>Level 1</h3>
<Slider <Knob
min={0} max={127}
max={127} value={parameters.level1}
parameter={parameters.level1} onChange={(value) =>
onChange={(value) => dispatch(
dispatch( parameterUpdated({
parameterUpdated({ id: props.id,
id: props.id, changes: { level1: value },
changes: { level1: value }, })
}) )
) }
} />
/> </div>
Level 2 <div className='flex flex-col items-center w-1/4'>
<Slider <h3>Level 2</h3>
min={0} <Knob
max={127} max={127}
parameter={parameters.level2} value={parameters.level2}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
id: props.id, id: props.id,
changes: { level2: value }, changes: { level2: value },
}) })
) )
} }
/> />
Level 3 </div>
<Slider <div className='flex flex-col items-center w-1/4'>
min={0} <h3>Level 3</h3>
max={127} <Knob
parameter={parameters.level3} max={127}
onChange={(value) => value={parameters.level3}
dispatch( onChange={(value) =>
parameterUpdated({ dispatch(
id: props.id, parameterUpdated({
changes: { level3: value }, id: props.id,
}) changes: { level3: value },
) })
} )
/> }
Level 4 />
<Slider </div>
min={0} <div className='flex flex-col items-center w-1/4'>
max={127} <h3>Level 4</h3>
parameter={parameters.level4} <Knob
onChange={(value) => max={127}
dispatch( value={parameters.level4}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { level4: value }, parameterUpdated({
}) id: props.id,
) changes: { level4: value },
} })
/> )
}
/>
</div>
</div> </div>
<div /> <div className='flex flex-row'>
<div> <div className='flex flex-col items-center w-1/4'>
Level 5 <h3>Level 5</h3>
<Slider <Knob
min={0} max={127}
max={127} value={parameters.level5}
parameter={parameters.level5} onChange={(value) =>
onChange={(value) => dispatch(
dispatch( parameterUpdated({
parameterUpdated({ id: props.id,
id: props.id, changes: { level5: value },
changes: { level5: value }, })
}) )
) }
} />
/> </div>
Level 6 <div className='flex flex-col items-center w-1/4'>
<Slider <h3>Level 6</h3>
min={0} <Knob
max={127} max={127}
parameter={parameters.level6} value={parameters.level6}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
id: props.id, id: props.id,
changes: { level6: value }, changes: { level6: value },
}) })
) )
} }
/> />
Level 7 </div>
<Slider <div className='flex flex-col items-center w-1/4'>
min={0} <h3>Level 7</h3>
max={127} <Knob
parameter={parameters.level7} max={127}
onChange={(value) => value={parameters.level7}
dispatch( onChange={(value) =>
parameterUpdated({ dispatch(
id: props.id, parameterUpdated({
changes: { level7: value }, id: props.id,
}) changes: { level7: value },
) })
} )
/> }
Level 8 />
<Slider </div>
min={0} <div className='flex flex-col items-center w-1/4'>
max={127} <h3>Level 8</h3>
parameter={parameters.level8} <Knob
onChange={(value) => max={127}
dispatch( value={parameters.level8}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { level8: value }, parameterUpdated({
}) id: props.id,
) changes: { level8: value },
} })
/> )
}
/>
</div>
</div> </div>
</div> </Card>
); );
} }
+134 -119
View File
@@ -1,132 +1,147 @@
import React from 'react'; import React from 'react';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { selectById, parameterUpdated } from './parameterSlice.js'; import { selectById, parameterUpdated } from './parameterSlice.js';
import { Slider } from '../../helpers/Helpers'; import Card from '../card';
import { Knob } from '../../utils/components';
export default function Pans(props) { export default function Pans(props) {
const parameters = useSelector((state) => selectById(state, props.id)); const parameters = useSelector((state) => selectById(state, props.id));
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
<div> <Card className={props.className} header={props.name}>
<span>{`${props.name}`}</span> <div className='flex flex-row'>
<div> <div className='flex flex-col items-center w-1/4'>
Pan 1 <h3>Pan 1</h3>
<Slider <Knob
min={0} dual={true}
max={127} max={63}
parameter={parameters.pan1} value={parameters.pan1}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
id: props.id, id: props.id,
changes: { pan1: value }, changes: { pan1: value },
}) })
) )
} }
/> />
Pan 2 </div>
<Slider <div className='flex flex-col items-center w-1/4'>
min={0} <h3>Pan 2</h3>
max={127} <Knob
parameter={parameters.pan2} dual={true}
onChange={(value) => max={63}
dispatch( value={parameters.pan2}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { pan2: value }, parameterUpdated({
}) id: props.id,
) changes: { pan2: value },
} })
/> )
Pan 3 }
<Slider />
min={0} </div>
max={127} <div className='flex flex-col items-center w-1/4'>
parameter={parameters.pan3} <h3>Pan 3</h3>
onChange={(value) => <Knob
dispatch( dual={true}
parameterUpdated({ max={63}
id: props.id, value={parameters.pan3}
changes: { pan3: value }, onChange={(value) =>
}) dispatch(
) parameterUpdated({
} id: props.id,
/> changes: { pan3: value },
Pan 4 })
<Slider )
min={0} }
max={127} />
parameter={parameters.pan4} </div>
onChange={(value) => <div className='flex flex-col items-center w-1/4'>
dispatch( <h3>Pan 4</h3>
parameterUpdated({ <Knob
id: props.id, dual={true}
changes: { pan4: value }, max={63}
}) value={parameters.pan4}
) onChange={(value) =>
} dispatch(
/> parameterUpdated({
id: props.id,
changes: { pan4: value },
})
)
}
/>
</div>
</div> </div>
<div /> <div className='flex flex-row'>
<div> <div className='flex flex-col items-center w-1/4'>
Pan 5 <h3>Pan 5</h3>
<Slider <Knob
min={0} dual={true}
max={127} max={63}
parameter={parameters.pan5} value={parameters.pan5}
onChange={(value) => onChange={(value) =>
dispatch( dispatch(
parameterUpdated({ parameterUpdated({
id: props.id, id: props.id,
changes: { pan5: value }, changes: { pan5: value },
}) })
) )
} }
/> />
Pan 6 </div>
<Slider <div className='flex flex-col items-center w-1/4'>
min={0} <h3>Pan 6</h3>
max={127} <Knob
parameter={parameters.pan6} dual={true}
onChange={(value) => max={63}
dispatch( value={parameters.pan6}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { pan6: value }, parameterUpdated({
}) id: props.id,
) changes: { pan6: value },
} })
/> )
Pan 7 }
<Slider />
min={0} </div>
max={127} <div className='flex flex-col items-center w-1/4'>
parameter={parameters.pan7} <h3>Pan 7</h3>
onChange={(value) => <Knob
dispatch( dual={true}
parameterUpdated({ max={63}
id: props.id, value={parameters.pan7}
changes: { pan7: value }, onChange={(value) =>
}) dispatch(
) parameterUpdated({
} id: props.id,
/> changes: { pan7: value },
Pan 8 })
<Slider )
min={0} }
max={127} />
parameter={parameters.pan8} </div>
onChange={(value) => <div className='flex flex-col items-center w-1/4'>
dispatch( <h3>Pan 8</h3>
parameterUpdated({ <Knob
id: props.id, dual={true}
changes: { pan8: value }, max={63}
}) value={parameters.pan8}
) onChange={(value) =>
} dispatch(
/> parameterUpdated({
id: props.id,
changes: { pan8: value },
})
)
}
/>
</div>
</div> </div>
</div> </Card>
); );
} }
+69 -59
View File
@@ -2,8 +2,7 @@ import React from 'react';
import Card from '../card'; import Card from '../card';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { selectById, parameterUpdated } from './parameterSlice.js'; import { selectById, parameterUpdated } from './parameterSlice.js';
import { Select, Knob } from '../../utils/components'; import { Select, Knob, Checkbox } from '../../utils/components';
import { Slider, Checkbox } from '../../helpers/Helpers';
export default function VCO(props) { export default function VCO(props) {
const parameters = useSelector((state) => selectById(state, props.id)); const parameters = useSelector((state) => selectById(state, props.id));
@@ -84,62 +83,73 @@ export const AudioIn = (props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
<div className={props.className}> <Card className={props.className} header={props.name}>
<span>{`${props.name}`}</span> <div className='-mt-3 flex flex-col items-stretch space-y-4'>
Gate <div className='flex flex-row'>
<Slider <div className='flex flex-col items-center w-1/2'>
min={0} <h3>Gate Sense</h3>
max={127} <Knob
parameter={parameters.gate} max={127}
onChange={(value) => value={parameters.gate}
dispatch( onChange={(value) =>
parameterUpdated({ dispatch(
id: props.id, parameterUpdated({
changes: { gate: value }, id: props.id,
}) changes: { gate: value },
) })
} )
/> }
Threshold />
<Slider </div>
min={0} <div className='flex flex-col items-center w-1/2'>
max={127} <h3>Threshold</h3>
parameter={parameters.threshold} <Knob
onChange={(value) => max={127}
dispatch( value={parameters.threshold}
parameterUpdated({ onChange={(value) =>
id: props.id, dispatch(
changes: { threshold: value }, parameterUpdated({
}) id: props.id,
) changes: { threshold: value },
} })
/> )
HPF Level }
<Slider />
min={0} </div>
max={127} </div>
parameter={parameters.hpfLevel} <div className='flex flex-row'>
onChange={(value) => <div className='flex flex-col items-center w-1/2'>
dispatch( <h3>HPF Level</h3>
parameterUpdated({ <Knob
id: props.id, max={127}
changes: { hpfLevel: value }, value={parameters.hpfLevel}
}) onChange={(value) =>
) dispatch(
} parameterUpdated({
/> id: props.id,
<Checkbox changes: { hpfLevel: value },
name='HPF Gate' })
parameter={parameters.hpfGate} )
onChange={(value) => }
dispatch( />
parameterUpdated({ </div>
id: props.id, <div className='flex flex-col items-center w-1/2'>
changes: { hpfGate: value }, <h3>HPF Gate</h3>
}) <Checkbox
) className='checkbox'
} value={parameters.hpfGate}
/> onChange={(value) =>
</div> dispatch(
parameterUpdated({
id: props.id,
changes: { hpfGate: value },
})
)
}
/>
</div>
</div>
</div>
</Card>
); );
}; };
@@ -275,7 +275,8 @@ const defaultState = {
waveform: 'Saw', waveform: 'Saw',
keySync: 'Off', keySync: 'Off',
tempoSync: false, tempoSync: false,
frequency: '1/1', frequency: 0,
syncNote: '1/1',
}, },
patches1: { patches1: {
id: 'patches1', id: 'patches1',
+1
View File
@@ -44,6 +44,7 @@ const timbreSlice = createSlice({
filter: 'filter3', filter: 'filter3',
fcMod: 'fcMod', fcMod: 'fcMod',
eg: 'eg5', eg: 'eg5',
eg2: 'unusedVocoder',
amp: 'amp3', amp: 'amp3',
lfo1: 'lfo5', lfo1: 'lfo5',
lfo2: 'lfo6', lfo2: 'lfo6',
+16 -5
View File
@@ -14,6 +14,8 @@ export default function Menu() {
const [file, setFile] = useState(null); const [file, setFile] = useState(null);
const fileRef = useRef(null); const fileRef = useRef(null);
const state = useSelector((state) => selectEntities(state)); const state = useSelector((state) => selectEntities(state));
const activeTab = useSelector((state) => state.parameters.activeTab);
console.log(activeTab);
const dispatch = useDispatch(); const dispatch = useDispatch();
const reader = new FileReader(); const reader = new FileReader();
const loadFile = (f) => { const loadFile = (f) => {
@@ -29,6 +31,15 @@ export default function Menu() {
} }
}, [file, dispatch]); }, [file, dispatch]);
useEffect(() => {
if (state.patch.mode === 'Vocoder') {
dispatch(parameterUpdateTab('Vocoder'));
}
if (state.patch.mode === 'Single' || state.patch.mode === 'Multiple') {
dispatch(parameterUpdateTab('Timbre1'));
}
}, [state.patch.mode, dispatch]);
return ( return (
<div className='col-span-1 flex flex-col justify-around border-solid border-r border-gray-300 bg-white px-4'> <div className='col-span-1 flex flex-col justify-around border-solid border-r border-gray-300 bg-white px-4'>
<div className='menu-patch-container'> <div className='menu-patch-container'>
@@ -104,7 +115,7 @@ export default function Menu() {
<div className='my-1 flex flex-col items-center space-y-2'> <div className='my-1 flex flex-col items-center space-y-2'>
<button <button
disabled={state.patch.mode === 'Vocoder'} disabled={state.patch.mode === 'Vocoder'}
className='btn' className={activeTab === 'Timbre1' ? `btn btn-active` : `btn`}
onClick={() => { onClick={() => {
dispatch(parameterUpdateTab('Timbre1')); dispatch(parameterUpdateTab('Timbre1'));
}}> }}>
@@ -112,7 +123,7 @@ export default function Menu() {
</button> </button>
<button <button
disabled={state.patch.mode !== 'Multiple'} disabled={state.patch.mode !== 'Multiple'}
className='btn' className={activeTab === 'Timbre2' ? `btn btn-active` : `btn`}
onClick={() => { onClick={() => {
dispatch(parameterUpdateTab('Timbre2')); dispatch(parameterUpdateTab('Timbre2'));
}}> }}>
@@ -120,21 +131,21 @@ export default function Menu() {
</button> </button>
<button <button
disabled={state.patch.mode !== 'Vocoder'} disabled={state.patch.mode !== 'Vocoder'}
className='btn' className={activeTab === 'Vocoder' ? `btn btn-active` : `btn`}
onClick={() => { onClick={() => {
dispatch(parameterUpdateTab('Vocoder')); dispatch(parameterUpdateTab('Vocoder'));
}}> }}>
Vocoder Vocoder
</button> </button>
<button <button
className='btn' className={activeTab === 'Effects' ? `btn btn-active` : `btn`}
onClick={() => { onClick={() => {
dispatch(parameterUpdateTab('Effects')); dispatch(parameterUpdateTab('Effects'));
}}> }}>
Effects Effects
</button> </button>
<button <button
className='btn' className={activeTab === 'Arpeggio' ? `btn btn-active` : `btn`}
onClick={() => { onClick={() => {
dispatch(parameterUpdateTab('Arpeggio')); dispatch(parameterUpdateTab('Arpeggio'));
}}> }}>
+10 -8
View File
@@ -83,14 +83,14 @@ function getKnobValue(dragStart, currentY, bipolar) {
let knob_id = 0; let knob_id = 0;
function Knob({ function Knob({
maxValue = 127, max = 127,
dual = false, dual = false,
size = 42, size = 42,
value = 0, value = 0,
fillWidth = 4, fillWidth = 4,
onChange, onChange,
}) { }) {
value = value / maxValue; value = value / max;
const uid = useMemo(() => knob_id++, []); const uid = useMemo(() => knob_id++, []);
const radius = size / 2; const radius = size / 2;
const dial_zero = dual ? Math.PI / 2 : START_ANGLE; const dial_zero = dual ? Math.PI / 2 : START_ANGLE;
@@ -115,9 +115,9 @@ function Knob({
if (!dragStart) return; if (!dragStart) return;
const newValue = getKnobValue(dragStart, e.clientY, dual); const newValue = getKnobValue(dragStart, e.clientY, dual);
onChange(Math.round(newValue * maxValue)); onChange(Math.round(newValue * max));
}, },
[dragStart, onChange, dual, maxValue] [dragStart, onChange, dual, max]
); );
const onMouseDown = useCallback( const onMouseDown = useCallback(
(e) => { (e) => {
@@ -158,19 +158,21 @@ function Knob({
{/* TOOLTIP */} {/* TOOLTIP */}
<div <div
className={` ${ className={` ${
isDragging ? 'opacity-100' : 'opacity-0' isDragging ? 'opacity-100' : 'opacity-0 hidden'
} transition duration-75 ease-in select-none pointer-events-none absolute -mt-6 bg-gray-800 text-white truncate text-xs box-content rounded text-center w-8 py-0.5`}> } transition duration-75 ease-in select-none pointer-events-none absolute -mt-6 bg-gray-800 text-white truncate text-xs box-content rounded text-center w-8 py-0.5`}>
{Math.round(value * maxValue)} {Math.round(value * max)}
</div> </div>
<svg <svg
className={` ${ className={` ${
isDragging ? 'opacity-100' : 'opacity-0' isDragging ? 'opacity-100' : 'opacity-0 hidden'
} transition duration-75 ease-in absolute text-gray-800 w-full h-2 -mt-1`} } transition duration-75 ease-in absolute text-gray-800 w-full h-2 -mt-1`}
x='0px' x='0px'
y='0px' y='0px'
viewBox='0 0 255 255' viewBox='0 0 255 255'
xmlSpace='preserve'> xmlSpace='preserve'>
<polygon class='fill-current' points='0,0 127.5,127.5 255,0'></polygon> <polygon
className='fill-current'
points='0,0 127.5,127.5 255,0'></polygon>
</svg> </svg>
<div <div
style={{ style={{
+3
View File
@@ -31,6 +31,9 @@ code {
.btn:disabled { .btn:disabled {
@apply line-through opacity-50 hover:bg-white cursor-default; @apply line-through opacity-50 hover:bg-white cursor-default;
} }
.btn-active {
@apply ring ring-blue-500;
}
.select { .select {
@apply select-none block rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50; @apply select-none block rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50;
} }