This commit is contained in:
Seth Trowbridge 2022-12-10 23:36:48 -05:00
parent b6f990f266
commit f1c1e947fb
4 changed files with 65 additions and 37 deletions

View File

@ -42,8 +42,8 @@ const pulse = (inNode, inStart, inDuration) =>
change(inNode, 0, (inStart+inDuration) );
};
/** @type {(inDuration:number, inContinuous:boolean, inChannel:number, inFreq:number, indBHL:number)=>void} */
const Start = (inDuration, inContinuous, inChannel, inFreq, indBHL) =>
/** @type {(inContinuous:boolean, inChannel:number, inFreq:number, indBHL:number)=>void} */
export const Play = (inContinuous, inChannel, inFreq, indBHL) =>
{
Context.resume();
GainBeep.gain.cancelScheduledValues(Context.currentTime);
@ -64,29 +64,4 @@ const Start = (inDuration, inContinuous, inChannel, inFreq, indBHL) =>
pulse(GainBeep.gain, 0.33, 0.2);
pulse(GainBeep.gain, 0.66, 0.2);
}
};
export const useTone =()=>
{
const [responseGet, responseSet] = React.useState(0);
const [playGet, playSet] = React.useState(0);
React.useEffect(()=>
{
/** @type {number|undefined} */
let timer;
if(playGet == 1)
{
let volNorm = 0.5//(State.dBHL-10)/ 130;
Start(1, false, 0, 500, (volNorm*0.8) + 0.2);
//responseSet(State.dBHL - currentChan.Answer[0]);
timer = setTimeout(()=>{playSet(2)}, 300 + Math.random()*1000);
}
return () => clearTimeout(timer);
}, [playGet]);
return {Play:()=>{playSet(1)}, Playing:playGet == 1, Response:playGet == 2 && responseGet };
};

View File

@ -29,7 +29,8 @@ export const Configure = {
},
animation:
{
flash: "flash 1s both"
flash: "flash 1s both",
pulse: "pulse 3s ease-in-out 0s 1 both"
},
strokeWidth:
{

View File

@ -19,16 +19,16 @@ export function Button({children, icon, light, disabled, inactive, onClick})
return html`
<button
onClick=${handleClick}
class="shadow-sss relative flex rounded-lg text(lg white) font-sans group transition-all ${disabled ? "scale-90 bg-gray-400" : "bg-emerald-500"} ${(inactive||disabled) && "cursor-default"}"
class="shadow-sss relative flex items-stretch rounded-lg text(lg white) font-sans group transition-all ${disabled ? "scale-90 bg-gray-400" : "bg-emerald-500"} ${(inactive||disabled) && "cursor-default"}"
>
<span class="absolute top-0 left-0 w-full h-full rounded-lg bg-black transition-opacity duration-300 opacity-0 ${(!inactive && !disabled) && "group-hover:opacity-50"}"></span>
${ FlashGet > 0 && html`<span key=${FlashGet} class="absolute top-0 left-0 w-full h-full rounded-lg bg-green-400 shadow-glow-green-300 animate-flash"></span>` }
${ icon && html`<span class="block relative p-2 border-r(1 [#00000066])">
${ icon && html`<span class="flex items-center block relative px-2 border-r(1 [#00000066])">
<span class="absolute top-0 left-0 w-full h-full bg-black rounded(tl-lg bl-lg) opacity-20"></span>
<span class="relative">${icon}</span>
</span>` }
<span class="p-2 relative border-l(1 [#ffffff44])">
<span class="flex items-center p-2 relative border-l(1 [#ffffff44])">
<span class="absolute shadow-glow-yellow-500 top-0 left-1/2 w-6 h-[6px] bg-white rounded-full translate(-x-1/2 -y-1/2) transition-all duration-500 ${light ? "opacity-100" : "opacity-0 scale-y-0"}"></span>
${children}
</span>
@ -56,7 +56,27 @@ export const Controls =()=>
{
const [State, Dispatch] = Store.Consumer();
const {Play} = Tone.useTone();
const [pulsedGet, pulsedSet] = React.useState(true);
const [playGet, playSet] = React.useState(0);
React.useEffect(()=>
{
/** @type {number|undefined} */
let timer;
if(playGet == 1)
{
const volNorm = (State.Stim.Value-State.Stim.Min)/(State.Stim.Max-State.Stim.Min);
Tone.Play(!pulsedGet, State.Chan.Value, Store.ColumnMapping[State.Freq.Value][0], (volNorm*0.8) + 0.1);
if(State.Live.Freq)
{
const testMark = State.Live.Freq[/** @type {"TestL"|"TestR"}*/(`Test${State.Chan.Value ? "R":"L"}`)];
const handler = testMark.Stim <= State.Stim.Value ? ()=>{playSet(2)} : ()=>{playSet(0)}
timer = setTimeout(handler, 500 + Math.random()*1000);
}
}
return () => clearTimeout(timer);
}, [playGet]);
return html`
<div class="flex">
@ -77,16 +97,48 @@ export const Controls =()=>
<${Button} disabled=${State.Stim.Value == State.Stim.Min} onClick=${()=>Dispatch({Name:"Stim", Data:-1})}>-<//>
<${Button} disabled=${State.Stim.Value == State.Stim.Max} onClick=${()=>Dispatch({Name:"Stim", Data:1})}>+<//>
</div>
<div class="flex">
<div>Tone</div>
<${Button} onClick=${()=>{pulsedSet(true)}} light=${pulsedGet} inactive${pulsedGet}>Pulsed<//>
<${Button} onClick=${()=>{pulsedSet(false)}} light=${!pulsedGet} inactive${!pulsedGet}>Continuous<//>
</div>
<div class="flex">
<div>Present</div>
<svg width="60" height="60" viewBox="0 0 79 79" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle fill="url(#metal)" cx="39" cy="40" r="35"></circle>
<circle fill="url(#metal)" cx="39.5" cy="39.5" r="29.5" transform="rotate(180 39.5 39.5)"></circle>
<circle fill="url(#metal)" cx="39" cy="40" r="27"></circle>
<circle fill="url(#backwall)" cx="39" cy="40" r="25"></circle>
<ellipse fill="url(#clearcoat)" cx="39" cy="33" rx="20" ry="16"></ellipse>
${playGet == 2 && html`<circle fill="url(#light)" cx="39.5" cy="39.5" r="36" class="animate-pulse"></circle>`}
<defs>
<linearGradient id="metal" x1="39.5" y1="1" x2="39.5" y2="78" gradientUnits="userSpaceOnUse">
<stop offset="0.0" stop-color="#C4C4C4" stop-opacity="1.0"></stop>
<stop offset="1.0" stop-color="#F2F2F2" stop-opacity="1.0"></stop>
</linearGradient>
<radialGradient id="backwall" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(39 56) rotate(-90) scale(45.5 74.4907)">
<stop offset="0.0" stop-color="#AAAAAA" stop-opacity="1.0"></stop>
<stop offset="1.0" stop-color="#333333" stop-opacity="1.0"></stop>
</radialGradient>
<radialGradient id="clearcoat" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(39 38.5) rotate(90) scale(50.5 71.9394)">
<stop offset="0.0" stop-color="#ffffff" stop-opacity="0.0"></stop>
<stop offset="0.7" stop-color="#ffffff" stop-opacity="1.0"></stop>
</radialGradient>
<radialGradient id="light" cx="0" cy="0" r="1.0" gradientUnits="userSpaceOnUse" gradientTransform="translate(39.5 39.5) rotate(90) scale(39.5)">
<stop offset="0.2" stop-color="#ffffff" stop-opacity="1.0"></stop>
<stop offset="0.5" stop-color="#ff8800" stop-opacity="1.6"></stop>
<stop offset="0.9" stop-color="#ffffff" stop-opacity="0.0"></stop>
</radialGradient>
</defs>
</svg>
<${Button} onClick=${()=>playSet(1)} disabled=${playGet==1} icon=${"p!"}>Play<//>
</div>
<div class="flex">
<div>Mark</div>
<${Button} onClick=${()=>Dispatch({Name:"Mark", Data:true })}>Response<//>
<${Button} onClick=${()=>Dispatch({Name:"Mark", Data:false})}>No Response<//>
<${Button} onClick=${()=>Dispatch({Name:"Mark", Data:null })} disabled=${State.Live.Mark == undefined}>Clear<//>
</div>
<div class="flex">
<div>Play</div>
<${Button} onClick=${Play}>continuous<//>
</div>
`;
};

2
store.d.ts vendored
View File

@ -49,4 +49,4 @@ declare namespace Store {
type DrawChart = { Cross?:DrawPoint, UserL: DrawGroup, UserR: DrawGroup, TestL: DrawGroup, TestR: DrawGroup };
type Binding = [state:State, dispatch:(inAction:Action)=>void]
}
}