1htmlで手持ちのmp3を太鼓の達人化(疑似自動作譜)


サンプル

drum_masters.0.0301.htm

使用方法

htmlを開いてローカルのmp3などを選択すると再生が始まります。
Level の数値がどこでマークを出すか を示しています。
つまり静かめの曲だとこのLevel値を下げないとマークが出てきません。
対象のmp3自体のゲインにもよります。
別に200を超えても問題はないです。

不具合

  • 2曲続けてプレイができない
    Uncaught (in promise) TypeError: Failed to execute を解除できてない。リロードするしかない。 清々しさがない。
  • 曲全体のレベルピーク検出を自動でしてない
    全体の長さをn秒として 4分のnくらいで平均のピークとBPM算出したらよさそう
  • audioタグを2つ用意してない のでマークが出てから太鼓を叩くまでのラグが演出できてない
  • 1分くらいで演奏停止に持っていきたい。
  • フーリエ変換の組み込みがまだ。  = カッ の未追加
  • 現状3% 残り97% 遠い道のり

Ver0.03ソース

drum_masters.0.03.htm
<html>
  <head>
    <style>
      .block1{background-color:#ff0000;
        width:26px;
        height:26px;
        left:300px;
        border-style:solid;
        border-width:2px;
        border-radius: 15px 15px 15px 15px;
        border-color:#FFFFFF;
      }

      .block2{
        width:30px;
        height:30px;
        left:300px;
        position: absolute;
        border-style:solid;
        border-width:2px;
        border-radius: 15px 15px 15px 15px;
        border-color:#000000;
        box-shadow: 4px 4px 8px -4px #333333;
        -moz-box-shadow: 4px 4px 8px -4px #333333;
        -webkit-box-shadow: 4px 4px 8px -4px #333333;
      }

      .box{
        width:300px;
        height:60px;
        position:  relative;
        overflow:hidden;
      }
    </style>
  </head>

  <body>
    Level <input type="text" id="int_peak" value="200" size="3"> 200 大=易---------小=難 20<br />
    <input type="file" id="file_slct"><br />
    <audio id="auo" ></audio><br />
    <input type="hidden" id="blk_count" value="0">
    <div class="box" id="box"></div>

  </body>

  <footer>
    <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
    <script>
      var str_id = 0
      var int_wait=0
      //****************************
      async function put_red_mark1(){
        var div2 = document.createElement('div');
        div2.classList.add('block2');
        div2.innerHTML="<div class='block1'></div>"
        div2.id="b" + str_id
        box.appendChild(div2);
        $("#b" + str_id).animate({"left": "-=340px"}, 2000,"linear",function(){$(this).remove();});
        str_id=parseInt(blk_count.value)+1
        blk_count.value=str_id
        int_wait=1
        await sleep(200);
        int_wait=0
      }

      //****************************
      var wm = new WeakMap();
      var audioSource;
      //********************************************************
      //const file_slct = document.querySelector('#file_slct');
      async function convertAudioFileToDataUrl(file) {
        const reader = new FileReader();
        const loadPromise = new Promise((resolve, reject) => {
          reader.onload = (event) => {
            resolve(event.target.result);
          };
        });
        reader.readAsDataURL(file);
        return loadPromise;
      }



      //*************************************//
      function sleep(m_second) {
          return new Promise(resolve => {
              setTimeout(() => {
                  resolve()
              }, m_second)
          })
          console.log("slpx")
      }




      //******************************
      file_slct.addEventListener('change', async (event) => {
        var audioctx = new AudioContext();
        const file = file_slct.files[0];
        auo.src = await convertAudioFileToDataUrl(file);
        audioSource = audioctx.createMediaElementSource(auo);
        auo.play()

        //timer_intvl=setInterval(timer_handler, 1000 ) ;


        var processor = audioctx.createScriptProcessor(256,1,1);
        audioSource.connect(processor);
        processor.connect(audioctx.destination);
        audioSource.connect(audioctx.destination);
        var int_peak=0

        processor.onaudioprocess = function(e){

          if (int_wait==0){
            var amp = e.inputBuffer.getChannelData(0);
            const reducer = (accumulator, currentValue) => accumulator + Math.abs(currentValue);
            int_peak=amp.reduce(reducer) / amp.length * 800
            //document.getElementById('bar').style.width = '' + (int_peak) + 'px';
            if(auo.paused){
              processor.disconnect();
              audioSource.disconnect();
              auo.src='';
            }else{
              if(int_peak > document.getElementById("int_peak").value){
                //log出力
                //console.log(int_peak)
                put_red_mark1("b" + blk_count.value);
              }
            }
          }
        };
      })



    </script>
  </footer>
</html>