BeamerReveal

 view release on metacpan or  search on metacpan

music-ideas.org  view on Meta::CPAN


    const iv = setInterval(() => {
      audio.volume = Math.min(1, audio.volume + delta);
      if (audio.volume === 1) clearInterval(iv);
    }, stepTime);
  }

  function fadeOut(audio, ms = 2000) {
    const steps = 30;
    const stepTime = ms / steps;
    const delta = audio.volume / steps;

    const iv = setInterval(() => {
      audio.volume = Math.max(0, audio.volume - delta);

      if (audio.volume === 0) {
        clearInterval(iv);
        audio.pause();
        audio.currentTime = 0;
        audio.volume = 1; // reset for next play
      }
    }, stepTime);
  }

  // Example with Reveal slide change
  Reveal.on("slidechanged", () => {
    if (Reveal.getCurrentSlide().id === "stop-music") {
      fadeOut(audio, 2500);
    }
  });
  </script>


  // advanced fading:
  
  <audio id="bgm" src="music.mp3" preload="auto" loop></audio>

<script type="module">
  const audio = document.getElementById("bgm");

  const ctx = new AudioContext();
  const source = ctx.createMediaElementSource(audio);
  const gain = ctx.createGain();

  source.connect(gain).connect(ctx.destination);

    function fadeIn(ms = 2000) {
    const now = ctx.currentTime;

    gain.gain.setValueAtTime(0, now);
    audio.play().catch(()=>{});
    gain.gain.linearRampToValueAtTime(1, now + ms/1000);
  }

  function fadeOut(ms = 2000) {
    const now = ctx.currentTime;
    gain.gain.cancelScheduledValues(now);
    gain.gain.setValueAtTime(gain.gain.value, now);
    gain.gain.linearRampToValueAtTime(0, now + ms / 1000);

    setTimeout(() => {
      audio.pause();
      gain.gain.value = 1; // reset
    }, ms);
  }

  Reveal.on("slidechanged", () => {
    if (Reveal.getCurrentSlide().id === "stop-music") {
      fadeOut(2500);
    }
  });
</script>

// fade in : simple




( run in 0.835 second using v1.01-cache-2.11-cpan-7f9471e7e0a )