function b(e,a,r){return getComputedStyle(e).getPropertyValue(a).trim()||r}function v(e,a){e.style.cursor="pointer",e.title="Double-click to edit",e.addEventListener("dblclick",()=>{let r=!1,n=document.createElement("input");n.type="text",n.className=a.className??"nbplay-inline-edit",n.value=a.getValue(),n.style.width=Math.max(e.offsetWidth+8,48)+"px",e.replaceWith(n),n.focus(),n.select();function o(){if(r)return;r=!0;let t=a.parse(n.value.trim());t!==null&&a.apply(t),n.replaceWith(e),a.sync()}n.addEventListener("keydown",t=>{t.key==="Enter"&&(t.preventDefault(),o()),t.key==="Escape"&&(t.preventDefault(),r||(r=!0,n.replaceWith(e),a.sync()))}),n.addEventListener("blur",o)})}function E(e){if(!e||!e.byteLength)return null;if(e instanceof DataView){let a=e.byteLength/4,r=new Float32Array(a);for(let n=0;n<a;n++)r[n]=e.getFloat32(n*4,!0);return r}if(e.buffer instanceof ArrayBuffer){let a=e;return new Float32Array(a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength))}return e instanceof ArrayBuffer?new Float32Array(e):null}var d=20,w=8e3,T=Math.log(w/d);function L(e){return Math.log(Math.max(d,Math.min(w,e))/d)/T}function F(e){return d*Math.exp(T*Math.max(0,Math.min(1,e)))}function S(e){return e>=1e3?(e/1e3).toFixed(2)+" kHz":e.toFixed(1)+" Hz"}function _(e,a){let r=window.devicePixelRatio||1,n=e.clientWidth||600,o=e.clientHeight||128;e.width=n*r,e.height=o*r;let t=e.getContext("2d");t.scale(r,r);let c=b(e,"--jp-layout-color0","#080812"),l=b(e,"--jp-brand-color1","#00d4ff"),p=b(e,"--jp-ui-font-color3","#64648a");if(t.fillStyle=c,t.fillRect(0,0,n,o),t.strokeStyle=p,t.globalAlpha=.35,t.lineWidth=1,t.setLineDash([4,4]),t.beginPath(),t.moveTo(0,o/2),t.lineTo(n,o/2),t.stroke(),t.setLineDash([]),t.globalAlpha=.15,t.beginPath(),t.moveTo(0,o*.25),t.lineTo(n,o*.25),t.moveTo(0,o*.75),t.lineTo(n,o*.75),t.stroke(),t.globalAlpha=1,!a||a.length===0)return;let u=a.length/n;t.strokeStyle=l,t.globalAlpha=.25,t.lineWidth=6,t.lineCap="round",t.lineJoin="round",t.beginPath();for(let i=0;i<n;i++){let y=(1-a[Math.min(Math.floor(i*u),a.length-1)])*o/2;i===0?t.moveTo(i,y):t.lineTo(i,y)}t.stroke(),t.globalAlpha=1,t.strokeStyle=l,t.lineWidth=2,t.beginPath();for(let i=0;i<n;i++){let y=(1-a[Math.min(Math.floor(i*u),a.length-1)])*o/2;i===0?t.moveTo(i,y):t.lineTo(i,y)}t.stroke()}function k(){let e=null,a=null,r=null;return{start(n,o,t,c){if(this.stop(),e=new AudioContext({sampleRate:c}),r=e.createGain(),r.gain.value=t,r.connect(e.destination),n==="noise"){let l=e.createBuffer(1,c*2,c),p=l.getChannelData(0);for(let i=0;i<p.length;i++)p[i]=Math.random()*2-1;let u=e.createBufferSource();u.buffer=l,u.loop=!0,u.connect(r),u.start(),a=u}else{let l=e.createOscillator();l.type=n==="saw"?"sawtooth":n,l.frequency.value=o,l.connect(r),l.start(),a=l}},stop(){if(a){try{a.stop()}catch{}a.disconnect(),a=null}r&&(r.disconnect(),r=null),e&&(e.close(),e=null)},setFrequency(n){a&&a.frequency&&e&&a.frequency.setTargetAtTime(n,e.currentTime,.01)},setAmplitude(n){r&&e&&r.gain.setTargetAtTime(n,e.currentTime,.01)}}}function N({model:e,el:a}){let r=k(),n=document.createElement("div");n.className="nbplay-synth",n.innerHTML=`
    <div class="nbplay-header">
      <h3>nbplay</h3>
      <span class="nbplay-badge">synth</span>
    </div>

    <div class="nbplay-waveform-container">
      <canvas class="nbplay-waveform"></canvas>
    </div>

    <div class="nbplay-osc-selector">
      <span class="nbplay-label">Oscillator</span>
      <div class="nbplay-osc-buttons">
        <button class="nbplay-osc-btn" data-type="sine">Sine</button>
        <button class="nbplay-osc-btn" data-type="square">Square</button>
        <button class="nbplay-osc-btn" data-type="saw">Saw</button>
        <button class="nbplay-osc-btn" data-type="noise">Noise</button>
      </div>
    </div>

    <div class="nbplay-params">
      <div class="nbplay-param">
        <span class="nbplay-label">Frequency</span>
        <input type="range" class="nbplay-freq" min="0" max="1" step="0.001" />
        <span class="nbplay-value nbplay-freq-val"></span>
      </div>
      <div class="nbplay-param">
        <span class="nbplay-label">Amplitude</span>
        <input type="range" class="nbplay-amp" min="0" max="1" step="0.01" />
        <span class="nbplay-value nbplay-amp-val"></span>
      </div>
    </div>

    <div class="nbplay-transport">
      <button class="nbplay-play-btn"></button>
      <span class="nbplay-info"></span>
    </div>
  `,a.appendChild(n);let o=n.querySelector(".nbplay-waveform"),t=n.querySelectorAll(".nbplay-osc-btn"),c=n.querySelector(".nbplay-freq"),l=n.querySelector(".nbplay-freq-val"),p=n.querySelector(".nbplay-amp"),u=n.querySelector(".nbplay-amp-val"),i=n.querySelector(".nbplay-play-btn"),y=n.querySelector(".nbplay-info");function h(){let s=e.get("oscillator_type");t.forEach(A=>A.classList.toggle("active",A.dataset.type===s));let f=s==="noise";c.disabled=f}function g(){let s=e.get("frequency");c.value=String(L(s)),l.textContent=S(s)}function m(){let s=e.get("amplitude");p.value=String(s),u.textContent=s.toFixed(2)}function M(){let s=e.get("is_playing");i.textContent=s?"\u25A0  Stop":"\u25B6  Play",i.classList.toggle("playing",s)}v(l,{getValue:()=>String(e.get("frequency")),parse:s=>{let f=parseFloat(s);return isNaN(f)?null:(s.toLowerCase().includes("k")&&(f*=1e3),Math.max(20,Math.min(8e3,Math.round(f*10)/10)))},apply:s=>{e.set("frequency",s),e.save_changes(),r.setFrequency(s)},sync:g}),v(u,{getValue:()=>String(e.get("amplitude")),parse:s=>{let f=parseFloat(s);return isNaN(f)?null:Math.max(0,Math.min(1,Math.round(f*100)/100))},apply:s=>{e.set("amplitude",s),e.save_changes(),r.setAmplitude(s)},sync:m});function q(){y.textContent=e.get("sample_rate")+" Hz"}function x(){let s=e.get("waveform");_(o,E(s))}return t.forEach(s=>s.addEventListener("click",()=>{e.set("oscillator_type",s.dataset.type),e.save_changes(),e.get("is_playing")&&r.start(s.dataset.type,e.get("frequency"),e.get("amplitude"),e.get("sample_rate"))})),c.addEventListener("input",()=>{let s=Math.round(F(parseFloat(c.value))*10)/10;e.set("frequency",s),e.save_changes(),r.setFrequency(s)}),p.addEventListener("input",()=>{let s=Math.round(parseFloat(p.value)*100)/100;e.set("amplitude",s),e.save_changes(),r.setAmplitude(s)}),i.addEventListener("click",()=>{e.set("is_playing",!e.get("is_playing")),e.save_changes()}),e.on("change:oscillator_type",h),e.on("change:frequency",g),e.on("change:amplitude",m),e.on("change:is_playing",()=>{M(),e.get("is_playing")?r.start(e.get("oscillator_type"),e.get("frequency"),e.get("amplitude"),e.get("sample_rate")):r.stop()}),e.on("change:sample_rate",q),e.on("change:waveform",x),e.set("is_playing",!1),h(),g(),m(),M(),q(),requestAnimationFrame(x),()=>r.stop()}var H={render:N};export{H as default};
//# sourceMappingURL=widget.js.map
