chord player song html

by Andy Bulka

HTML

<!-- Piano component -->
<div
  id="piano-1"
  class="piano"
  data-height-scale="1"
  data-octave-start="2"
  data-octave-count="5"
></div>

<br />

<!-- Button with song data -->
<button
  onclick="toggleMusic(this, 'piano-1', [[0,57,89,2380],[0,60,86,2380],[0,65,86,2380],[0,29,89,2380],[706,48,89,409],[357,53,89,368],[363,57,89,409],[974,55,89,2380],[0,59,88,2380],[0,62,77,2380],[0,31,89,2380],[549,50,89,352],[320,55,89,348],[342,59,89,369],[1189,55,89,2380],[0,60,82,2380],[0,64,75,2380],[0,24,89,2380],[634,48,89,360],[317,52,89,319],[337,55,89,287],[270,67,89,299],[278,72,89,491],[565,55,89,2380],[0,60,83,2380],[0,63,80,2380],[0,32,89,2380],[715,55,89,439],[343,51,89,328],[346,75,89,409],[273,72,89,313],[307,67,89,407],[416,55,89,2380],[0,60,85,2380],[0,62,85,2380],[0,65,85,2380],[0,34,89,2380],[583,55,89,389],[351,74,89,343],[267,72,89,299],[273,67,89,307],[307,50,89,401],[265,48,89,46],[136,48,89,807],[218,55,89,2380],[0,60,88,2380],[0,64,76,2380],[0,24,89,2380],[603,52,89,523],[427,48,89,981],[1370,55,89,2380],[0,58,81,2380],[0,62,85,2380],[0,27,89,2380],[598,50,89,351],[311,55,89,340],[345,58,89,949],[1147,55,89,2380],[0,59,88,2380],[0,64,86,2380],[0,24,89,2380],[613,52,89,337],[322,55,89,345],[340,59,89,859],[624,55,89,656],[502,55,89,2380],[0,58,85,2380],[0,62,72,2380],[0,27,89,2380],[134,50,89,543],[496,55,89,473],[459,58,89,1259],[1311,57,89,2380],[0,60,84,2380],[0,64,81,2380],[0,29,89,2380],[662,48,89,389],[349,52,89,371],[377,57,89,1802],[1012,55,89,2400],[0,59,88,2400],[0,64,83,2400],[0,28,89,2400],[619,71,89,357],[363,76,89,464],[438,52,89,723]],26400,false);"
>
  <span class="play-icon"></span> Song title
</button>

CSS

.piano {
  border: solid 1px black;
  background: black;
  border-radius: 0.3vw;
  position: relative;
}
.piano-keys {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  cursor: pointer;
  border-radius: 0.3vw;
  overflow: hidden;
}
.piano-white-key {
  background: #eee;
  border-left: solid 1px rgba(0, 0, 0, 0.5);
  box-shadow:
    inset 0.1vw 0 0.1vw rgba(255, 255, 255, 0.2),
    inset -0.1vw -0.1vw 0.1vw rgba(0, 0, 0, 0.2);
  border-radius: 0 0 0.2vw 0.2vw;
  margin-left: -1px;
  position: relative;
  flex: 1;
}
.piano-black-key {
  background: black;
  background-image: linear-gradient(
    to right bottom,
    transparent,
    rgba(255, 255, 255, 0.3)
  );
  border: solid 1px rgba(0, 0, 0, 0.5);
  border-top: none;
  border-radius: 0 0 0.2vw 0.2vw;
  height: 60%;
  left: 65%;
  right: -35%;
  box-sizing: border-box;
  position: absolute;
  z-index: 1;
}
.piano-black-key::after {
  content: " ";
  position: absolute;
  width: 100%;
  height: 100%;
  border: solid;
  border-top: none;
  border-width: 0 0.3vw 0.6vw 0.3vw;
  border-color: black rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.2)
    rgba(255, 255, 255, 0.1);
  box-sizing: border-box;
}
.piano-white-key.press,
.piano-black-key.press {
  background: red;
}
.piano a {
  font-family: Arial;
  color: black;
  position: absolute;
  text-decoration: none;
  right: 0;
  padding: 2px;
  z-index: 1;
  transition: opacity 1s ease-in;
  opacity: 0;
  font-size: 0;
}
.piano a::after {
  content: "i";
  font-size: 11px;
  background: white;
  font-weight: bold;
  padding: 0 4px;
  border: solid 1px black;
  border-radius: 100%;
  margin-left: 5px;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
}
.piano:hover a {
  opacity: 1;
}
.piano a:hover {
  font-size: 11px;
  background: white;
}
.play-icon {
  border-color: transparent transparent transparent black;
  border-style: solid;
  border-width: 5px 0 5px 10px;
  display: inline-block;
  box-sizing: border-box;
}
.play-icon.playing {
  border-color: black;
}

JavaScript

!(function () {
  "use strict"
  var e,
    t,
    o,
    a,
    r,
    n,
    i,
    u,
    c,
    s = !1,
    l = window,
    d = [0, 2, 4, 5, 7, 9, 11],
    f = [1, 3, 0, 6, 8, 10, 0],
    p = function (e, t, o, a) {
      return v("sine", e, t, o, a)
    },
    v = function (t, o, r, n, i) {
      Math.floor(r / 12)
      var u = e.createGain(),
        c = 880 * Math.pow(2, (r - 69) / 12),
        s = ((n / 127) * 0.1 * 100) / c,
        l = o || 1e3 * e.currentTime,
        d = i ? (l + i + 100) / 1e3 : 0
      ;(u.gain.value = 0),
        u.gain.setValueAtTime(0, l / 1e3),
        u.gain.setTargetAtTime(s, (l + 50) / 1e3, 0.03),
        u.connect(e.destination)
      var f = e.createGain()
      ;(f.gain.value = 0),
        f.gain.setValueAtTime(0, l / 1e3),
        f.gain.linearRampToValueAtTime(0.2, (l + 2e3) / 1e3)
      var p = e.createGain()
      ;(p.gain.value = 0.5), f.connect(p.gain)
      var v = e.createOscillator()
      ;(v.frequency.value = 5),
        v.connect(f),
        v.start(l / 1e3),
        u.connect(p),
        p.connect(e.destination)
      for (var m = 0; m < 2; m++) {
        var g = e.createOscillator()
        ;(g.type = t),
          (g.frequency.value = c * Math.pow(2, m)),
          g.connect(u),
          g.start(l / 1e3),
          d && g.stop(d + 0.5)
      }
      var y = function (e) {
        var t = e + 0.1
        v.stop(t + 100),
          u.gain.cancelScheduledValues(e),
          u.gain.setTargetAtTime(s, e, 0.03),
          u.gain.setTargetAtTime(0, t, 0.03)
      }
      if (d) {
        var h = l + i + 100
        h > a && (a = h), y(d - 0.1)
      }
      return i ? null : y
    },
    m = function (e, a, i, c, s, l) {
      var d = 0
      i.forEach(function (t) {
        ;(d += t[0]), p(1e3 * o + d + e, t[1], t[2], t[3])
      }),
        l &&
          (function (e, o, a, r) {
            clearTimeout(n)
            var i = Number(o.dataset.octaveStart),
              c = (Number(o.dataset.octaveCount), e)
...