Edited at

スマートフォンを楽器にしてみた

笛吹きエンジニアの@mottox2です。

皆さん、クソアプリつくっていますか?

僕はこれまでつくっていませんでした。ということで今回は初めてのクソアプリということでスマートフォンを楽器にしてみました。

https://tone.mottox2.com

この記事はクソアプリ Advent Calendar 2018の21日目の記事です。


つくったもの


なんなのか?

みなさん、こういう楽器はご存知でしょうか?1

これはテルミン(テレミン)といって世界初の電子楽器らしいです。2手を調整することで音程と音量が操作できるとっても難しい楽器です。

image.png (102.2 kB)

クソアプリカレンダーの皆さんは簡単に使えるようにしている人が多かったので、これをWebで再現してみました。


クソポイント

Twitterの動画を見てくれた方はわかるかもしれませんが、難しくて曲にならないというのがクソポイントです。

2日でつくったのでクソコードだったり、各所に雑な箇所も残っていたりするのもクソポイントです。

要するにクソアプリなわけです。


技術的なお話

このアプリの仕組みをざっくりいうと、スマホのジャイロセンサーで周波数を決定し、Web Audio APIでそのジャイロセンサーに基づいた周波数の音を出すという内容です。


ジャイロセンサー

Google Developers

ICSさんの記事を参考に今回はDevice Orientation Eventを利用しました。

これで端末の向きが変わったときにイベントが飛んでくるので、向きと周波数が連動するような処理を書きました。

Webエンジニア7年目なのですが、初めてセンサー類の処理を扱いました (;´д`)…

センサーのデバッグについていうとChrome Developersにもセンサーの値をいじる方法があります。

ですが、本アプリの性質上、常に値が変わる想定のアプリケーションではあまり有効なデバッグ方法ではありませんでした。

スクリーンショット 2018-12-21 2.43.37.png (94.2 kB)

そこで、AndroidのUSBデバッグを介したChrome DevToolsのデバッグを行いました。

これは普通のスマホWebをデバッグする際にもよく使われる手法ですが、センサー類のデバッグも同時にできるので非常に有用な方法でした。

iPhoneのデバッグもSafariで同様に出来ます。SafariはForm周りで辛い動作があるのでよくお世話になっています。スマホWebで消耗している人で知らない人は絶対に知っておいたほうがいいです。

スクリーンショット 2018-12-21 2.45.45.png (925.5 kB)


つまりポイント

センサーに対応していない端末の検知につまずきました。Google Developers的にはwindow.DeviceOrientationEventを利用すればよいという記述がありますが、少なくともPC Chromeではtrueになってしまいます。

妥協案としてUserAgentを用いてスマホかPCかを判定することにしました。いい解決案を知っている人がいれば教えてください。


Web Audio APIで音を出す

スクリーンショット 2018-12-21 1.53.57.png (127.6 kB)

Web Audio APIといっても直接使うのは大変なのでTone.jsというライブラリを使って音を出すようにしました。

例えば以下のようなコードで「ド」(英語やドイツ語ではCがド)の音を鳴らせます。簡単ですね。


サンプルコード

const synth = new Tone.Synth().toMaster()

synth.triggerAttack('C4')

この出した音にsetNodeというメソッドが生えているので、ジャイロセンサーをもとに計算した周波数を引数として渡すと出したい音程の音がなります。


出したい周波数の音を出すコード

const synth = new Tone.Synth().toMaster()

const monophonic = synth.triggerAttack('C4')
// frequencyはジャイロセンサーをもとに計算した周波数
monophonic.setNote(frequency)

これでスマートフォンの傾きが変化すると、音程が変わるようになりました。

ただ音階は線形ではないので、音程が均等になるようにしたかったのですが、線形に変化するようになっています。クソアプリだからしょうがない。


つまりポイント

Web Audio APIにはAutoplay Policyといって問答無用で音を鳴らそうとするとブラウザに再生を阻害されます。

Chrome71からなので今月からそのポリシーが適用されたらしいです。

Tone.jsのStable版では対応しておらず音がなりませんでした、1時間調べた結果、開発中のdev版を利用することで回避出来ました。


[WIP] 周波数から音階を表示する

吹奏楽部の人がこういう機械をもっていませんでしたか?この機械はチューナーといい音程がどれぐらい正しいかを確認する機械です。

ピアノを見ているとドレミファソラシド(とその半音)の音しか認識出来ません。3しかし、ドとド#、ミとファの中間の音など中途半端な音が存在しており、歌や楽器を演奏しているときは正しい音が出ているか確認する必要があります。

正しい音を確認するためにチューナーで音が正しいかを確認します。

チューナー

今回のアプリケーションでは簡単に中途半端な音を出すことが出来ます。

その音が正しいのか、正しくないのかを簡単に表示できるインターフェースを用意する必要がありました。

[TODO] 音階と周波数の関係を書く


create-react-app + TypeScript

自分はReactをよく使うので、プロトタイプを作るときはcreate-react-appというfacebookが公開しているボイラープレートを展開してくれるCLIをもとにReactアプリケーションを立ち上げます。

また、create-react-appはここ最近TypeScriptのテンプレートにも対応したのでより便利になっています。

次のコマンドで立ち上げられるのでReact + TypeScriptに興味がある方はぜひお使いください!

npx create-react-app webtone --typescript


Netlifyでデプロイ

Netlifyは2018年において無料でGitHub上のサイトを公開する最も便利な手段です。

GitHubやBitBucketのリポジトリと連動して、静的サイトをデプロイできるプラットフォームです。

独自ドメインもNetlify上で登録しており、それと紐付けることでデプロイが終わりました。

3分もかからずデプロイが出来ました。サーバーサイドが必要ないものは迷わずNetlifyに上げるようにしています。

他のCDNと比較して配信が遅いと言われがちですが、速度が重要なわけではないのでNetlifyで十分だと思っています。自分が速度と立ち上げ速度を求めるならFirebase Hostingを選ぶ気がします。


感想

2日前までは別のものをつくっていたのですが、開発者向けのもので一般の人が使うものではありませんでした。

いろんな人のカレンダーを見ていくうちに、誰でも使えるものがいいなと思い今回のものを作ることにしました。

開発期間が2日なので荒い場所もあるのですが多めに見てくれると嬉しいです。





  1. 「いらすとや」さんからです。どんな絵でもあってびっくりです。 



  2. Wikipediaより: https://ja.wikipedia.org/wiki/%E3%83%86%E3%83%AB%E3%83%9F%E3%83%B3 



  3. ピアノでもずっと使っていると音がずれていきます。このズレを直す調律師という職業も存在します。かっこいいですよね!