So-net無料ブログ作成
» スポンサーリンク

iPhoneを振ってMobile SafariからJavaScriptで加速度を検知してスレイベルを鳴らしてみる
» 音楽コンテンツ(作曲/演奏) 

[追記] 2014/12/13
新しいバージョンを公開しました。
[追記ここまで]

時期ネタを何かやってみようということで、iPhone を振って鳴らせるスレイベル (Sleigh Bells) のプチ Web アプリ的なページを作ってみました。
iOS 6 以降搭載の iPhone/iPod touch の Mobile Safari で動きます。


スレイベル (Sleigh Bells) とは?

スレイベルは木製の棒に鈴がたくさんついたパーカッションの一種です。
(輪っかに鈴がついた小型のタイプもあります)
名前や形は知らなくても、クリスマスの鈴の音といえば分かる人も多いのでは?



Sleigh Bells for iPhone の使い方


     
←左の QR コードをタップするか、iPhone のカメラで QR コードを読み取って Sleigh Bells のページにジャンプしてください。


使い方はいたってシンプルです。
  • まず「Sound Preview」ボタンで鈴の音量を確認・調整してください。
  • 次に iPhone を握って手首のスナップをきかせて振ってみてください。
  • 反応が悪い場合は、振る速度を速くするか、感度を低くしてみてください。

  振るときに iPhone がすっぽ抜けないように十分注意してください。
  (万が一 iPhone を落として壊してもこちらは責任は負いません)

プログラムコードについて

短時間で作ったサンプルレベルの大雑把なプログラムではありますがついでに少しだけ説明しておきます。
プログラムに興味がない人はここから先はスルーしてください。

 UI 部分はお手軽な jQuery + jQuery UI の組み合わせで、ただしスライダーの動作は標準の jQuery UI ではタッチドラッグができないので、jquery-ui-touch-punch を利用しました。

↓JavaScript の部分だけ抜粋
var context;
var buffer = null;
var threshold = 0;
var easing = false;

try{
  context = new webkitAudioContext();
  var request = new XMLHttpRequest();
  request.open("GET", "sleigh-bells.mp3", true);
  request.responseType = "arraybuffer";
  request.onload = function() {
    context.decodeAudioData(request.response, function(data){
      buffer = data;
    });
  }
  request.send();
}catch (e){
  alert("iOS 6 以降の mobile Safari で試してください");
}

function playSound(){
  var bufSrc = context.createBufferSource();
  bufSrc.buffer = buffer;
  bufSrc.connect(context.destination);
  bufSrc.noteOn(0);

  if(!easing){
    easing = true;
    $("body").effect("highlight",{color:'#FFF',easing:'easeInOutQuad'}, 700, function(){
      easing = false;
    });
  }
}

function setThreshold(value){
  threshold = value;
  $("#threshold-value").text("Sensitivity: " + threshold);
}

$(function(){
  setThreshold(1500);

  window.addEventListener("devicemotion", function(e){
    if(Math.floor(e.acceleration.x * 100) > threshold){
      playSound();
    }
  });

  $("#preview").button().click(function(){
    playSound();
  });

  $("#threshold-slider").slider({
    min: 0,
    max: 3000,
    value: threshold,
    change: function(event, ui){
      setThreshold(ui.value);
    }
  }).draggable();
});

» 加速度センサーのイベント devicemotion
 iOS はバージョン 4.2 から加速度センサーの値を読み出すことができる devicemotion イベントが追加されていて、Safari の JavaScript からイベントハンドラを指定してリアルタイムに現在値を取得することができます。

 » Safari Developer Library - DeviceMotionEvent Class Reference

function deviceMotion(e){
// e.acceleration.x
// e.acceleration.y
// e.acceleration.z
// e.accelerationIncludingGravity.x
// e.accelerationIncludingGravity.y
// e.accelerationIncludingGravity.z
// e.rotationRate.alpha
// e.rotationRate.beta
// e.rotationRate.gamma
}

window.addEventListener("devicemotion", deviceMotion);

 Sleigh Bells では X 方向の加速度変化 (e.acceleration.x) だけを利用しています。X 方向は iPhone 本体正面から見て左右に動かしたときの移動で、左方向がマイナスで右方向がプラスの値になります。今回の場合は握ったときに本体側面が対面になるので前後に振る動作で X 軸が変化します。

 指定した加速度に達したときにスレイベルの音を鳴らす関数 playSound() を呼び出します。スレイベルを振る演奏操作的には振出動作と引き動作の途中は鳴らずに、手前に強く押し出して止めたとき(加速度がマイナスからプラスの最大値に変化するとき)だけ鳴ればよいので、プラス方向でしきい値を超えたときだけ反応するようにしてあります。

» Mobile Safari の Web Audio API
 サウンドの再生は Mobile Safari で利用できる WebKit の Web Audio API を使っています。
 最初は HTML5 Audio オブジェクトを使おうと思っていたのですが、Mobile Safari は play() を呼び出すたびに音声ファイルを毎回律儀にサーバーからロードしてしまい、再生が開始されるのが遅すぎて当初想定したレスポンスが得られませんでした。

 なにか別の方法はないものかと調べたてみら、iOS 6 から Mobile Safari が Web Audio API に対応していることが分かって、試しにやってみたらうまいこと動いてくれました。

 Safari Developer Library - Playing Sounds with the Web Audio API

 鈴の音の mp3 ファイルを Ajax 経由でバッファに読み込んで、指定のタイミングで noteOn() するだけのシンプルな作りです。

try{
  context = new webkitAudioContext();
  var request = new XMLHttpRequest();
  request.open("GET", "sleigh-bells.mp3", true);
  request.responseType = "arraybuffer";
  request.onload = function() {
    context.decodeAudioData(request.response, function(data){
      buffer = data;
    });
  }
  request.send();
}catch (e){
}

function playSound(){
  var bufSrc = context.createBufferSource();
  bufSrc.buffer = buffer;
  bufSrc.connect(context.destination);
  bufSrc.noteOn(0);
}

 ただ、ページがロードされた直後は devicemotion 内で呼び出している再生が動かないというよく分からない現象がでてます。(まだ原因は分かっていません)
 ボタンで手動で1回再生した後だと反応してくれるので、とりあえず音量確認用ということにしてボタンを設けました。

一応自分の iPhone 5s (iOS 7.0.4) では動いてます。
他のパターンではテストしてないので、もしかしたらちゃんと動かないこともあるかもしれません。

あと、試すときはくれぐれも iPhone を落とさないように注意してくださいね。


[追記] 2013/12/19
コメント欄の aike さんから教えて頂いた情報によると、デベロッパーライブラリのドキュメントに以下の注意書きがありました。

Note: On iOS, the Web Audio API requires sounds to be triggered from an explicit user action, such as a tap. Calling noteOn() from an onload event will not play sound.

iOS の Web Audio API のサウンドは画面タップなどのようなユーザーアクションのトリガーによる再生が必要で、ページロード後に noteOn() を直接呼び出しても反応しないのは仕様なのだそうです。
deviceMotion イベント内で noteOn() を呼ぶのもこれに該当します。

[関連サイト]
 jQuery
 jQuery UI
 jquery-ui-touch-punch
 Web Audio API
 Safari Developer Library


nice!(3)  コメント(4)  トラックバック(0)   » カテゴリー:音楽コンテンツ(作曲/演奏)
permalink
trackback
このエントリーをはてなブックマークに追加


» スポンサーリンク
DMR

サウンドハウス


nice! 3

コメント 4

aike

加速度センサーとWeb Audio APIを組み合わせるのは面白いですね。モバイル前提だとそんなことができるんですねー。
ページロード直後に再生が動かないのはiOS Safariがあえて制限してるのだと思います。
http://mohayonao.hatenablog.com/entry/2013/02/04/200628

by aike (2013-12-19 02:17) 

TAN

情報ありがとうございます。
ページロード直後に音が出ないのは仕様だったのですね。
デベロッパーライブラリのドキュメントに書いてあるのにちゃんと読んでませんでした。

Web Audio API+加速度センサーを使った次のネタもまだあるので上手く動いたらまた記事にしたいと思っています。
by TAN (2013-12-19 17:34) 

tea

これの作り方を教えて欲しいです。
初心者で全くわかりません

宜しくお願いします。
by tea (2016-05-31 14:07) 

TAN

加速度センサーを使ったり音を出したりといったことをする前に、まずHTML5とJavaScriptの基礎を学ぶことをお勧めします。

「HTML5 JavaScript Webアプリ」などで検索するといろいろ参考になるページが出てくると思います。

とりあえずテキストエディタ(メモ帳でも可)があればコードを書くことは可能ですが、未経験となると道のりは長くなるかもしれません。
by TAN (2016-06-17 16:27) 

コメントを書く

名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

Facebook コメント

トラックバック 0

この記事のトラックバックURL:
※言及リンクのないトラックバックは受信されません。

iTunes Store 音楽アプリベストセラー
for iPad





for iPhone/iPod touch





for Mac