Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

Firefox OSアプリ開発が楽しくなるハードウェアAPIの概要と、センサーAPIや音声APIを使った楽器アプリの作例

Firefox OS搭載スマホ「Fx0」でつくろう! はじめてのFirefox OSアプリ開発 第3回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2015/03/26 14:00

目次

環境光センサーと近接センサーとWebAudioで楽器アプリを作る(1)

 ここまでで一通りのハードウェアアクセスAPIを見てきましたが、ここからは、APIを実際の使用例に基いて解説していきます。今回は、環境光センサーAPIと近接センサーAPI、WebAudio APIと組み合わせて簡単な楽器アプリを作っていきます。

Fx0にインストールした楽器アプリを操作している様子
Fx0にインストールした楽器アプリを操作している様子
楽器アプリのデモ動画

 まず楽器アプリの概要についてです。今回の楽器アプリはWebAudio APIで単純な音を鳴らします。音程の制御は環境光センサーの値を使って行い、音量はタッチパネルのタッチ位置で制御するようにします。さらに近接センサーAPIを用いて一定以上手を近づけると音声が停止するようにします。つまりタッチパネルをドラッグしながらデバイスに手をかざして、手を近づけて影を強くしたり手を離して影を作らないようにして演奏するテルミンのようなアプリになります。

 ソースコードは以下のリポジトリで公開しています。あわせて参考にしてください。

WebAudio APIで音を鳴らす

 音程を変えるにも音量を変えるにもまずは音声を鳴らさなければ始まりません。WebAudio APIで音を鳴らしてみましょう。

 WebAudio APIは、全体を管理するAudioContextオブジェクトにモジュールをつないでいく構造を持っています。現実世界で音源、アンプ、エフェクタ、スピーカをつないでいる状態をモデル化しているといえます。今回は複雑な波形もエフェクトも使用しないので、AudioContextに発振子とアンプを繋ぎます。

// Web Audio APIの状態管理オブジェクトを生成
audio.context = new AudioContext();

// オシレータとゲインを生成
audio.oscillator = audio.context.createOscillator();
audio.gainNode = audio.context.createGain();

// オシレータとゲインをスピーカにつなぐ
audio.oscillator.connect(audio.gainNode);
audio.gainNode.connect(audio.context.destination);

 発振子の設定を変更して再生開始します。今回は発振子の波形、周波数、デチューン幅を設定しています。

// オシレータオプションを設定する
audio.oscillator.type = 'square'; // 矩形波
audio.oscillator.frequency.value = INITFREQ; // 発振周波数(Hz単位)
audio.oscillator.detune.value = 100; // デチューン設定(セント単位)
audio.oscillator.start();

audio.oscillator.onended = function() {
	console.log('再生停止');
}

 ゲインも初期化しておきましょう。

// ゲインを設定する
audio.gainNode.gain.value = INITVOL;

 これで矩形波が再生されます。audio.oscillator.frequency.valueを変更することで音程が、audio.gainNode.gain.valueを変更することで音量が操作できるようになりました。

環境光センサーAPIの値に合わせて音程を変える

 音程と音量を制御できるようになったので、環境光センサーの値に応じて音程を変えてみましょう。

 環境光センサーAPIは、前述したとおりwindowのdevicelightイベントにイベントハンドラを登録する形で使用します。

環境光の取得
イベント名 devicelight
イベントハンドラのインターフェイス function devicelightHandler(DeviceLightEvent event);
イベント引数の型 DeviceLightEvent
イベント引数のプロパティ value:取得したセンサー値(ルクス単位)
min:取得可能な最低値
max:取得可能な最大値

 今回は音程を変えたいので、イベントハンドラの中でaudio.oscillator.frequency.valueを変更しています。また環境光センサーの値は揺れるので単純移動平均を取るようにしています。

window.addEventListener('devicelight', changeBrightness);

function changeBrightness(e) {
    currentBrightness = e.value;
    if (!maxBright) maxBright = currentBrightness; // フェイルセーフ

    // 最大値は超えない
    if (currentBrightness > maxBright) currentBrightness = maxBright;

    // 直近n回の移動平均を取って周波数を作る
    var ave = average(push(smaBrightness, currentBrightness, NUM_SMASAMPLE));
    audio.oscillator.frequency.value = (ave / maxBright) * MAXFREQ;
    console.log('light: ' + ave + ', maxBright: ' + maxBright);
}

タッチパネルのタッチ位置に合わせて音量を変える

 次はタッチパネルのタッチ位置に応じて音量を制御しましょう。

 タッチパネルのタッチ位置は、documentオブジェクトのtouchdownイベント、またはtouchmoveイベント、またはtouchupイベントで取得します。今回はドラッグに追従したいのでtouchmoveイベントを使用します。

タッチ位置の取得
イベント名 touchmove
イベントハンドラのインターフェイス function touchmoveHandler(TouchEvent event);
イベント引数の型 TouchEvent
イベント引数のプロパティ touches:現在タッチしているタッチポイントのリスト
targetTouches:現在タッチしているターゲットからタッチ開始したタッチポイント
changedTouches:前回のTouchEventから動いたタッチポイントのリスト

 タッチ位置はTouchListオブジェクトとして返ってくるので、特定の点を取りだすためにitemメソッドでインデックスを指定します。

var touchItem = touchList.item(index);
タッチ位置の取り出し
メソッド名 Touch TouchList.item(index)
引数 index:TouchListオブジェクトの値を読みだすインデックス
返り値 読みだしたTouchオブジェクト

 これらを踏まえてタッチ位置で音量を変化させます。

document.addEventListener('touchmove', touchMove);
// マウス位置
var curX;
var curY;

// タッチ位置が動いたらタッチ座標からゲインを設定する
function touchMove(e) {
    curX = e.targetTouches.item(0).screenX;
    curY = e.targetTouches.item(0).screenY;

    audio.gainNode.gain.value = (curY/HEIGHT) * MAXVOL;
    //console.log('cur: ' + curY + ', h: ' + HEIGHT);

    canvasDraw();
}

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 藪下 正美(ヤブシタ マサミ)

     株式会社グローバルサイバーグループ マネージャ。  大阪のソフトウェア開発会社で主に携帯電話・スマートフォンのドライバからアプリまで幅広く開発に従事。  関東支社に転属後はスマートフォン・タブレット向けのアプリ開発を主に担当。  2012年終わりごろからFirefox OSに注目しコミュニテ...

バックナンバー

連載:Firefox OS搭載スマホ「Fx0」でつくろう! はじめてのFirefox OSアプリ開発
All contents copyright © 2005-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5