pirika logo

ホームページ Pirikaで化学 ブログ 業務案内 お問い合わせ
情報化学+教育トップ 情報化学 MAGICIAN MOOC プログラミング
高校生レベルのプログラミングはMAGICIAN-Jrへどうぞ。
フィードバックはお問い合わせフォームからお願いします。

プログラミング・トップ > 化学,薬学系の親子で楽しみながらプログラミング > 音感訓練

2022.3.4

6-1音感訓練 ピアノの作成

赤ちゃんはお母さんのお腹の中にいる時から音は聞いている。
触れば音の出るものは大好きだ。

まずタイルに触れて音ができることを確認しよう。
どの音が何の音か、聞いただけでわかるかな?
次に、コンピュータを使っている人はマウスでタイルを掴んでピアノのように並び替えよう。 (iPadなどでは、まだ動かせない。ごめん。)


HTML5では、要素をマウスで掴んで動かすことができる。
ターゲットをdraggableに指定する。

<script type="text/javascript">
  function draggable(target) {
    target.onmousedown = function() {
      document.onmousemove = mouseMove;
    };
    document.onmouseup = function() {
      document.onmousemove = null;
    };
    function mouseMove(e) {
      var event = e ? e : window.event;
      target.style.top = event.clientY + 'px';
      target.style.left = event.clientX + 'px';
    }
  }
</script>

そしてidを取り出して、

 draggable(document.getElementById('btn_C5'));

これで動かすことができる。
しかし、動かす時と音を鳴らす時と、同じイベント(何かの動作:ここではマウスのクリック)を使うので、動かした後演奏しようとすると、位置がずれてしまうことがある。

音自体はTone.jsと言うものを使っている。簡単にシンセサイザーなども作れるので、いろいろ試すことができる。

ネットで様々なデモがあるがTone.jsのサーバー上の位置が変わったらしく、動かないものが多い。今はこれで動くようだ。

<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.32/Tone.min.js"></script>


C5の音を8分音符で鳴らすには次のようにする。

function playSound_C() {
  if(!state) return;
  synth.triggerAttackRelease('C5', '8n');
}

他の長さにしたいなら次のようにする。
「2n」:2分音符
「4n」:4分音符
「8n」:8分音符
「1m」:全音符(1小節)

以下のプログラムをコピペしてMakinPiano.htmlなどの名前でセーブしておこう。

完成形プログラム(▶︎をクリックして開く)

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>音感訓練</title>
    <style type="text/css">
div {
    width: 50px;
    height: 50px;
    position: absolute;
  }
  div.C5 {
    background-color: rgb(125,125,255,0.5);
    top: 70px;
    left: 140px;
  }
  div.D5 {
    background-color: rgb(255,0,255,0.5);
    top: 0px;
    left: 70px;
  }
  div.E5 {
    background-color: rgb(0,125,255,0.5);
    top: 210px;
    left: 70px;
  }
  div.F5 {
    background-color: rgb(0,0,190,0.5);
    top: 70px;
    left: 0px;
  }
  div.G5 {
    background-color: rgb(255,0,125,0.5);
    top: 210px;
    left: 140px;
  }
  div.A5 {
    background-color: rgb(0,255,255,0.5);
    top: 0px;
    left: 0px;
    
  }
  div.B5 {
    background-color: rgb(255,255,0,0.5);
        top: 70px;
    left: 70px;
    
  }
  div.C6 {
    background-color: rgb(255,0,0,0.5);
    top: 140px;
    left: 70px;
  }
  div.CS5 {
    background-color: rgb(125,0,125,0.5);
    top: 140px;
    left: 140px;
  }
  div.DS5 {
    background-color: rgb(0,0,255,0.5);
    top: 210px;
    left: 0px;
  }
  div.FS5 {
    background-color: rgb(255,125,120,0.5);
    top: 0px;
    left: 140px;
    
  }
  div.GS5 {
    background-color: rgb(125,255,125,0.5);
    top: 140px;
    left: 0px;
    
  }
  div.AS5 {
    background-color: rgb(125,125,0,0.5);
    top: 280px;
    left: 0px;
  }

</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.32/Tone.min.js"></script>

<script type="text/javascript">
  function draggable(target) {
    target.onmousedown = function() {
      document.onmousemove = mouseMove;
    };
    document.onmouseup = function() {
      document.onmousemove = null;
    };
    function mouseMove(e) {
      var event = e ? e : window.event;
      target.style.top = event.clientY + 'px';
      target.style.left = event.clientX + 'px';
    }
  }
</script>

  </head>
  <body>
  
  <div class="C5" id="btn_C5">C5</div>
<div class="D5" id="btn_D5">D5</div>
<div class="E5" id="btn_E5">E5</div>
<div class="F5" id="btn_F5">F5</div>
<div class="G5" id="btn_G5">G5</div>
<div class="A5" id="btn_A5">A5</div>
<div class="B5" id="btn_B5">B5</div>
<div class="C6" id="btn_C6">C6</div>
<div class="CS5" id="btn_CS5">C#5</div>
<div class="DS5" id="btn_DS5">D#5</div>
<div class="FS5" id="btn_FS5">F#5</div>
<div class="GS5" id="btn_GS5">G#5</div>
<div class="AS5" id="btn_AS5">A#5</div>
 


<script type="text/javascript">
  draggable(document.getElementById('btn_C5'));
  draggable(document.getElementById('btn_D5'));
  draggable(document.getElementById('btn_E5'));
  draggable(document.getElementById('btn_F5'));
  draggable(document.getElementById('btn_G5'));
  draggable(document.getElementById('btn_A5'));
  draggable(document.getElementById('btn_B5'));
  draggable(document.getElementById('btn_C6'));
  draggable(document.getElementById('btn_CS5'));
  draggable(document.getElementById('btn_DS5'));
  draggable(document.getElementById('btn_FS5'));
  draggable(document.getElementById('btn_GS5'));
  draggable(document.getElementById('btn_AS5'));
  
  
var btnC = document.getElementById('btn_C5');
var btnD = document.getElementById('btn_D5');
var btnE = document.getElementById('btn_E5');
var btnF = document.getElementById('btn_F5');
var btnG = document.getElementById('btn_G5');
var btnA = document.getElementById('btn_A5');
var btnB = document.getElementById('btn_B5');
var btnC6 = document.getElementById('btn_C6');
var btnCS5 = document.getElementById('btn_CS5');
var btnDS5 = document.getElementById('btn_DS5');
var btnFS5 = document.getElementById('btn_FS5');
var btnGS5 = document.getElementById('btn_GS5');
var btnAS5 = document.getElementById('btn_AS5');

var synth;
var state = false;

init();

// PC用イベント処理
btnC.addEventListener('click', playSound_C);//click
btnD.addEventListener('click', playSound_D);
btnE.addEventListener('click', playSound_E);
btnF.addEventListener('click', playSound_F);
btnG.addEventListener('click', playSound_G);
btnA.addEventListener('click', playSound_A);
btnB.addEventListener('click', playSound_B);
btnC6.addEventListener('click', playSound_C6);
btnCS5.addEventListener('click', playSound_CS);
btnDS5.addEventListener('click', playSound_DS);
btnFS5.addEventListener('click', playSound_FS);
btnGS5.addEventListener('click', playSound_GS);
btnAS5.addEventListener('click', playSound_AS);

// スマホ用イベント処理
//start.addEventListener('touchstart', init);
btnC.addEventListener('touchstart', playSound_C);
btnD.addEventListener('touchstart', playSound_D);
btnE.addEventListener('touchstart', playSound_E);
btnF.addEventListener('touchstart', playSound_F);
btnG.addEventListener('touchstart', playSound_G);
btnA.addEventListener('touchstart', playSound_A);
btnB.addEventListener('touchstart', playSound_B);
btnC6.addEventListener('touchstart', playSound_C6);
btnCS5.addEventListener('touchstart', playSound_CS);

btnDS5.addEventListener('touchstart', playSound_DS);
btnFS5.addEventListener('touchstart', playSound_FS);
btnGS5.addEventListener('touchstart', playSound_GS);
btnAS5.addEventListener('touchstart', playSound_AS);


// 初期設定
function init() {
  synth = new Tone.Synth().toMaster();
  state = true;
}

// 初期設定適用後に発動するイベント処理
function playSound_C() {
  if(!state) return;
  synth.triggerAttackRelease('C5', '8n');
}

function playSound_CS() {
  if(!state) return;
  synth.triggerAttackRelease('C#5', '8n');
}

function playSound_D() {
  if(!state) return;
  synth.triggerAttackRelease('D5', '8n');
}

function playSound_DS() {
  if(!state) return;
  synth.triggerAttackRelease('D#5', '8n');
}

function playSound_E() {
  if(!state) return;
  synth.triggerAttackRelease('E5', '8n');
}

function playSound_F() {
  if(!state) return;
  synth.triggerAttackRelease('F5', '8n');
}

function playSound_FS() {
  if(!state) return;
  synth.triggerAttackRelease('F#5', '8n');
}

function playSound_G() {
  if(!state) return;
  synth.triggerAttackRelease('G5', '8n');
}
function playSound_GS() {
  if(!state) return;
  synth.triggerAttackRelease('G#5', '8n');
}

function playSound_A() {
  if(!state) return;
  synth.triggerAttackRelease('A5', '8n');
}

function playSound_AS() {
  if(!state) return;
  synth.triggerAttackRelease('A#5', '8n');
}

function playSound_B() {
  if(!state) return;
  synth.triggerAttackRelease('B5', '8n');
}
function playSound_C6() {
  if(!state) return;
  synth.triggerAttackRelease('C6', '8n');
}
 </script>
  </body>
</html>

プログラミング・トップ > 化学,薬学系の親子で楽しみながらプログラミング


Copyright pirika.com since 1999-
Mail: yamahiroXpirika.com (Xを@に置き換えてください) メールの件名は[pirika]で始めてください。