iPhne/iPad Javascript プログラミング 楽器

コロナでスタジオ入れないからバタドラムをスマホで遊べるようにした

太鼓は家じゃ叩けないからスマホでパターンの練習くらいできたら嬉しい

作ったのはこんなアプリです。

アプリのページはこちら。スマホでもPCでも遊べます。PCの場合はキーボードで代用します。メニューに表示される説明を読んでください。

Okonkoro,Iya,Itotoreの文字をクリックするとそれぞれの楽器に移動する

デモページ

ソースコード(GitHub)

 

いちおう、ネタ的にはコロナ対策で作ったみたいな話になってますが、ホントはもともと作りたかったアプリです。

昔から"音がでかくて家で鳴らせない楽器のための電子練習器"というのが自分の製作テーマのひとつとしてありまして、arduinoベースでコンガ練習器とか、サックス練習器などを作って使ってきました。

その後、スマホやタブレットの処理能力が上がったり、自分もN予備校でプログラミングを学んだりしたので、いつかスマホ/タブレットで太鼓アプリを作ってみたいと思っていました。新型コロナのお陰で時間とモチベーションができたわけです。

アプリは、キューバのバタドラムという楽器をシミュレートしています。ちなみに、本物のバタドラムはYoutubeにいろいろ動画があります。

batadrum - YouTube

 

バタドラムは3本セットで演奏する楽器です。大きい方から、Iya、Itotore、okonkoroという名前がついていて、アプリもメニューから叩く太鼓を選択します。

 

これは昔使っていたパールというメーカーの製品

 

楽器としては左右で大きさの違う両面太鼓というのが大きな特徴です。和太鼓も両面太鼓ですが打つところは左右(前後?裏表?)同じ大きさですよね。バタは小さい面を叩くとパキーンと甲高い音が出て、大きな面を叩くとドーンとかポンとか低い音がします。大・中の太鼓ではミュートといって手で押さえてバスッという音色も使います。基本はこの3音色を叩き分けて3本の組み合わせでリズムを作ります。

 

itotoreの高い音

itotoreの低い音

itotoreのミュート音

 

 

アプリも叩く場所によって3つの音を出せるようになっています。本物の太鼓では、低い音とミュートは叩き方で音色を変えるのですが、いまのところアプリでは場所で音色を分けています。

音量は一定だし、微妙なニュアンスも出せないので本物の太鼓の代わりにはなりません。しかしパターンを覚えたり、演奏の分析や研究には十分に役に立ちます。

私は練習ツールと電子楽器はまったく別物だと考えています。

音色やニュアンスのような要素は本物の楽器で練習すると割り切り、ツールはメカニカルな練習や演奏の分析・研究に特化した方が良いモノができます。

 

howler.jsは簡単に使えて遅延が少なくて最高!

プログラムの内容は、シンプルなHTML + Javascriptです。

divにイベントリスナーをセットしておいて、タッチイベントが来たら音を出すというごく普通の作りです。

音出しにhowler.jsというjavascriptライブラリを使っています。

 

 

howler.js - JavaScript audio library for the modern web

通常、Webアプリで音をだすのに使われるaudioタグはレスポンスが遅くて楽器のような用途には向きません。

最初はtone.jsというライブラリを使いました。tone.jsはシーケンサーのようなアプリケーションには向いていますが、楽器に必要なレスポンスは得られませんでした。

howler.jsは、非常にレスポンスが速く、楽器として自分にとっては自然な反応が実現できました。

しかも使い方が簡単で、例えば以下のようなシンプルなプログラムで音が出ます。

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>howler.js sample</title>
  
  //ライブラリの読み込み
  <script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.1.3/howler.js"></script>
   <!-- Copyright (c) 2013-2019 James Simpson and GoldFire Studios, Inc. https://howlerjs.com/ -->
</head>

<body>
  <br>
  <span id="pad" style="border:solid 2px red; padding:10px;color:red;">
    click or tap here</span>

  <script>
    // Howlオブジェクトを生成して音源をセット
    const sound = new Howl({
      src: ['sound.wav']
    });

    // 文字列がクリックされたら音を出す
    //clickイベントはマウスを離したときに発火するので、楽器的にはmousedownとかtouchstartの方が良い

    document.getElementById("pad").addEventListener('click', event => {
      sound.play();
    }, { capture: true, passive: false });


  </script>
</body>

</html>

デモページ

ソースコードと音源データ

 

ちなみに起動して最初の一音が遅い問題があるのですが(音源のロード時間?)、練習ツールとしては困らないので放置しています。

 

スマホで演奏したときにスクロールとか拡大しないようにする

とりあえず動くようになったときに困ったのが演奏中に画面がスクロールしたり拡大しちゃうことでした。スマホで楽器とかゲームのアプリを作る時は、叩くときに指がスライドしちゃったり、3本以上の指が画面に触れてまった時の対策が必要になるんですね。

 

検索するといろんな方法がみつかりました。基本的には、CSSで不要なタッチイベントを受け付けないように設定するのと、javascriptでイベントを先に捕まえて preventDefault() で捨てるということみたいです。

とりあえず、片っ端から組み込みました。たまにキャンセルしきれない時もありますが、だいたいオッケーです。

CSSはこんな感じ

* {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-drag: none;
  -khtml-user-drag: none;
}

javascriptはこんな感じ

document.addEventListener('touchstart', event => {

  if (event.touches.length > 2) {
    event.preventDefault();
  }
}, { capture: true, passive: false });

document.addEventListener('touchmove', event => {
  event.preventDefault();
}, { capture: true, passive: false });

 

あと、音を出したときにも余ったイベント(?)を捨てています。効果あるのかな。知らんけど。

 

cha.addEventListener('touchstart', event => {
  sound1.play();
  cha.classList.add("touched");
  event.preventDefault();
}, { capture: true, passive: false });

同好の友人に使って貰いましたが、まぁまぁ好評っぽかったです。

-iPhne/iPad, Javascript, プログラミング, 楽器