LoginSignup
2
2

More than 1 year has passed since last update.

簡易自動演奏Webアプリの開発の忘備録です

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web簡易ピアノ</title>
  <style>
    
    .piano {
      width: 600px;
      height:300px;
      margin-top:20px;
      background-color:#FFF;
      padding-top:20px;
      
    }

    .piano .music {
      width:400px;
      height:100px;
      background-color: #F799FF;
      padding-top:30px;
      margin-top:20px;
      margin:auto;
    }

    .music #display {
      width:95%;
      text-align:center;
      font-size:40px;
      color:#0031FF;
    }

    .keyboard {
      width:490px;
      height:80px;
      background-color:#FFF;
      margin:20px auto;
      display:flex;
    }
    .keyboard .key {
      width:calc(100% / 6 - 10px);
      height:40px;
      padding-top:10px;
      margin-left:5px;
      margin-right:5px;
      border-radius:2px #00F;
      background-color:#FAA;
      text-align: center;
      font-size:18px;
      
      
    }

    .button1 {
      width:300px;
      height:50px;
      background-color:#FFF;
      margin:10px auto;
      display:flex; 
    }

    .button1 .but1 {
      width:calc(100% - 20px);
      height:35px;
      padding-top:8px;
      padding-left:8px;
      margin-left:5px;
      margin-right:5px;
      border-radius:2px #000;
      background-color:#0AA;
      color:#80F;
      text-align: center;
      font-size:15px;
    }

    
  </style>
</head>
<body>
  <!-- 簡易ピアノ -->
  <div class="piano">
    <!-- 音名表示 -->
    <div class="music">
      <h1 id="display"></h1>
    </div>
    <!-- キーボード表示 -->
    <div class="keyboard">
      <div id="C4" class="key"></div>
      <div id="D4" class="key"></div>
      <div id="E4" class="key"></div>
      <div id="F4" class="key">ファ</div>
      <div id="G4" class="key"></div>
      <div id="A4" class="key"></div>
      <div id="B4" class="key"></div>
    </div>  
    <div class="button1">
      <input type="button" id="autoplay" name="autoplay" class="but1" value="自動演奏">
      <input type="button" id="autostop" name="autostop" class="but1" value="演奏中止">
    </div>
  </div>  
  <script>
      // AudioContext オブジェクトを新しく作成
      var audioCtx;
      // ド(C4)~ド(B5)までのIDからオブジェクトを取得する
      const C4 = document.getElementById('C4');
      const D4 = document.getElementById('D4');
      const E4 = document.getElementById('E4');
      const F4 = document.getElementById('F4');
      const G4 = document.getElementById('G4');
      const A4 = document.getElementById('A4');
      const B4 = document.getElementById('B4');
      // 自動演奏ボタンの定義
      const autoplay = document.getElementById('autoplay');
      // 演奏中止ボタンのオブジェクトを取得する
      const autostop = document.getElementById('autostop');
      autostop.style.display = 'none';
      // 音階を格納する配列を定義する
      const sound_array = ['','','','ファ','','',''];
      // 周波数を格納する配列を定義する
      const hz_array = [261,293,329,349,392,440,493,1];
      // 音階表示エリアのオブジェクトを定義する
      const display = document.getElementById('display');
      // タイマー変数の定義
      let timer;
      // 作動時間の制御
      let work_time = 0;
      // 音を鳴らす時間の設定
      let playing_seconds = 1500;
      // 音階を表示する時間
      let display_seconds = 1000;
      // きらきら星の音階
      const kirakira = [
                        '0/500',
                        '7/500',
                        '0/500',
                        '7/500',
                        '4/500',
                        '7/500',
                        '4/500',
                        '7/500',
                        '5/500',
                        '7/500',
                        '5/500',
                        '7/500',
                        '4/2000',
                        '3/500',
                        '7/500',
                        '3/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '1/500',
                        '7/500',
                        '1/500',
                        '7/500',
                        '0/2000',
                        '4/500',
                        '7/500',
                        '4/500',
                        '7/500',
                        '3/500',
                        '7/500',
                        '3/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '1/2000',
                        '4/500',
                        '7/500',
                        '4/500',
                        '7/500',
                        '3/500',
                        '7/500',
                        '3/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '1/2000',
                        '0/500',
                        '7/500',
                        '0/500',
                        '7/500',
                        '4/500',
                        '7/500',
                        '4/500',
                        '7/500',
                        '5/500',
                        '7/500',
                        '5/500',
                        '7/500',
                        '4/2000',
                        '3/500',
                        '7/500',
                        '3/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '2/500',
                        '7/500',
                        '1/500',
                        '7/500',
                        '1/500',
                        '7/500',
                        '1/4000'
                      ];
      // チューリップの音階
      const tyuri = [   
                    '0/500',
                    '1/500',
                    '2/1000',
                    '0/500',
                    '1/500',
                    '2/1000',
                    '4/500',
                    '2/500',
                    '1/500',
                    '0/500',
                    '1/500',
                    '2/500',
                    '1/1000',
                    '0/500',
                    '1/500',
                    '2/1000',
                    '0/500',
                    '1/500',
                    '2/1000',
                    '4/500',
                    '2/500',
                    '1/500',
                    '0/500',
                    '1/500',
                    '2/500',
                    '0/1000',
                    '4/250',
                    '7/250',
                    '4/250',
                    '7/250',
                    '2/250',
                    '7/250',
                    '4/250',
                    '7/250',
                    '5/250',
                    '7/250',
                    '5/250',
                    '7/250',
                    '4/1000',
                    '2/250',
                    '7/250',
                    '2/250',
                    '7/250',
                    '1/250',
                    '7/250',
                    '1/250',
                    '7/250',
                    '0/4000'
                ];
      //作業用配列
      var array3; 
         
      function play(music1,hz,test_time){
            audioCtx = new AudioContext();
            // 正弦波の音を作成
            let osc = audioCtx.createOscillator();   
            //ヘルツ(周波数)指定
            osc.frequency.value = parseInt(hz);
            //音の出力先
            var audioDestination = audioCtx.destination;
            //出力先のスピーカーに接続
            osc.connect(audioDestination);
            
            timer = setInterval(osc.start(),250);
            
            
            if (music1 !== null){
              display.textContent = music1;
              setTimeout(function() {
                    display.textContent = "";
              },display_seconds);
            }  
            sleep(test_time);     
            clearInterval(timer);
            osc.stop();
            
      }

      function sleep(time1) {
        const d1 = new Date();
        while (true){
            const d2 = new Date();
            if (d2 - d1 >= time1){
               break;
            }
        }
      }
           

      // ピアノの音階をクリック
      C4.addEventListener('click',function() {
          const d = sound_array[0];
          const h = hz_array[0];
          play(d,h,playing_seconds);
      },false);

      D4.addEventListener('click',function() {
        const d = sound_array[1];
        const h = hz_array[1];
        play(d,h,playing_seconds);
      },false);
          
      E4.addEventListener('click',function() {
        const d = sound_array[2];
        const h = hz_array[2];
        play(d,h,playing_seconds);
      },false);
          
      F4.addEventListener('click',function() {
        const d = sound_array[3];
        const h = hz_array[3];
        play(d,h,playing_seconds);
      },false);
          
      G4.addEventListener('click',function() {
        const d = sound_array[4];
        const h = hz_array[4];
        play(d,h,playing_seconds);
      },false);
          
      A4.addEventListener('click',function() {
        const d = sound_array[5];
        const h = hz_array[5];
        play(d,h,playing_seconds);
      },false);
          
      B4.addEventListener('click',function() {
        const d = sound_array[6];
        const h = hz_array[6];
        play(d,h,playing_seconds);
      },false);
          
      
          
      autoplay.addEventListener('click',function() {
        C4.style.visibility = 'hidden';
        D4.style.visibility = 'hidden';
        E4.style.visibility = 'hidden';
        F4.style.visibility = 'hidden';
        G4.style.visibility = 'hidden';
        A4.style.visibility = 'hidden';
        B4.style.visibility = 'hidden';
        display.textContent = "自動演奏";
        autoplay1();
      },false);    

      function autoplay1() {
        const random = Math.floor(Math.random() * 2);
        if (random == 0){
          array3 = kirakira;
        } else {
          array3 = tyuri;
        }
        
        
        for(let j=0;j<array3.length;j++){
              const array4 = array3[j].split('/');
              const number = array4[0];
              const playsec = array4[1];
              play(sound_array[number],hz_array[number],playsec);
        } 
        C4.style.visibility = 'visible';
        D4.style.visibility = 'visible';
        E4.style.visibility = 'visible';
        F4.style.visibility = 'visible';
        G4.style.visibility = 'visible';
        A4.style.visibility = 'visible';
        B4.style.visibility = 'visible';

      }

      

      function autostop1() {
            AudioContext().createOscillator().stop();
            clearInterval(timer);
      }      



  </script>
</body>
</html>

現在処理が重く、ブラウザの待機が大量に発生しています。

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2