ランニング用のメトロノームアプリを作りました。
用途はメトロノーム音を走行ピッチに合わせるためです。
なので、BPM(1分あたりの拍数)も140BPM~220BPMと一般的なメトロノームより範囲を絞っています。
まずはご覧(お聴き)ください。
メトロノーム
テンポと拍子を選択して「PLAY」をクリック(またはタップ)してください↓↓
bpm 拍子
4拍子がスタンダードだとは思いますが、個人的に6拍子のほうが歩数を合わせやすかったりしたので、2パターン用意させていただきました。
※クオリティに難があるので、テンポや拍子を変えたい場合は一旦「STOP」してから再度「PLAY」してください m(__)m
無機質なBeep音をリビングで流していたら、妻を
って驚かせてしまいました…
スキル不足ゆえ、かたじけない。
以降、なぜメトロノームなのか?なぜ作ったの?どうやって?など開発秘話を綴っているので、もしお時間が許せばごらんください。
なぜランニングにメトロノームなのか?
なぜランニング用にメトロノームかというと、とりもなおさず
ピッチが速い方がいいというよりピッチ遅いと脚(特に下腿)に疲労がたまりまくります。
だから上げた方がいいんです。
理想は180spm前後。
このピッチなら初心者でも手の届くレベルになります。
でも慣れないとスグにピッチが落ちていってしまうので、メトロノームに合わせて安定的に刻んだ方がいいですよ~という理屈です。
最初は息が上がるかもしれませんが、そのうち疲労の残りかたがぜんぜん違うことが実感できるはずです。
オススメは脳内BGM
理想は脳内BGMです。
ピッチを合わせられる目的の他に、聴いてるとテンションが上がるというメリットもあるからです。
速めのピッチに合うBGMをリストアップしているので、下記のリンクからご覧ください。
脳内で再生させるのが理想ではありますが、リアルでBGMをちゃんと聴きたい!という方は耳をふさがずに安全な「骨伝導イヤホン」が超絶オススメです。
メトロノームを作った理由
さて。
皆さんに気持ちよく走っていただきたいという気持ちに偽りはないのですが、そのためにメトロノームを作りました!というのはタテマエで、ホンネはただ単に
だって、こんなブログを開かなくても、世の中には優秀なメトロノームアプリは山ほどありますからね。
でも、せっかく勉強するならせめて人様のお役に立ちたい!ということで、苦肉の「ランニング用メトロノーム」だったわけです。
メトロノームの作り方
JavaScriptで作りましたが、初めてのこと尽くめで音声ファイルの文字列化、音の止め方やタイマー設定に幾度も阻まれました。
ということで、後進のために道しるべをのこしておきます。
手順はざっくり3ステップ。
- クリック音をダウンロード
- wavファイルを64bit文字列化
- JavaScriptを書く
1. クリック音をダウンロード
メトロノームのクリック音も自分で作ろうと思ったのですが、シーケンサーが古いPCにしかなかったので、フリー素材からBeep音をいただきました。
otosozai.comさんの
- ファイル名「se_saa01」(高音)
- ファイル名「se_saa03 」(低音)
です(あざっす)。
こちらをダウンロード(Download)フォルダに保存しておきます。
2. wavを64bit文字列化
wavファイルを文字データ化するためにコマンドプロンプトを使います。
Linux限定と思われた「Base64コマンド」ですが、なんとWindowsでも使えました。
備忘のために、実際に私が実行したコマンドを具体例として載せておきますね。
Microsoft Windows [Version 10.0.22000.434]
(c) Microsoft Corporation. All rights reserved.
C:\Users\(UserName)>cd Downloads
↑ダウンロードフォルダへ移動
C:\Users\(UserName)\Downloads>certutil -f -encode "se_saa03.wav" "se_saa03.txt"
入力長 = 49368
出力長 = 67938
CertUtil: -encode コマンドは正常に完了しました。
↑低音ファイルを変換
C:\Users\(UserName)\Downloads>certutil -f -encode "se_saa01.wav" "se_saa01.txt"
入力長 = 56956
出力長 = 78374
CertUtil: -encode コマンドは正常に完了しました。
↑高音ファイルを変換
以下、ちょっとした小技です。
- 小技
- 文字列に改行が入ってしまう場合は、メモ帳で改行を置換しておきましょう
- 音声が長くてうまくリピートできない場合はバイナリ(文字列)を半分くらいでカットしちゃいましょう
3. ソースコード(JavaScript)
コチラはHTMLのbodyタグに記載したコードです。
はてなブログなら、「はてな記法」にしてそのままエディタに貼り付けるだけで使えるようになります。
<select name="bpm" id="bpm"> </select> bpm <select name="beat" id="beat"> <option value="4" selected>4</option> <option value="6">6</option> </select> 拍子 <form id="Form" action="#"> <input type="button" onclick="Play()" value="PLAY" id="btn_Play"> <input type="button" onclick="Stop()" value="STOP" id="btn_Stop"> </form> <script> // インターバルの宣言 var BeatInterval; // ループ処理でコンボボックスの値生成 for (var i = 0; i <= 16; i++) { //select要素を取得する const selectBpm = document.getElementById('bpm'); //option要素を新しく作る const option1 = document.createElement('option'); //option要素にvalueと表示名を設定 option1.value = 140 + (i * 5); option1.textContent = 140 + (i * 5); //select要素にoption要素を追加する selectBpm.appendChild(option1) } function Play(){ // 再生ボタン無効化 btn_Play.disabled = true; // コンボボックスの値を取得 let elementBpm = document.getElementById('bpm'); let elementBeat = document.getElementById('beat'); var bpm = elementBpm.value; // bpm:テンポ(1分間に何拍するか var beat = elementBeat.value; // beat:拍子(指定した拍数ごとに高いビープ音を鳴らす) metronome(bpm, beat) } function metronome(bpm, beat){ // 低め音 var low = "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"; // 高めの音 var high = "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"; // それぞれ Audio オブジェクト生成 var lowPlayer = new Audio("data:audio/wav;base64," + low); var highPlayer = new Audio("data:audio/wav;base64," + high); var j = 0; BeatInterval = setInterval(function(){ // 指定テンポで繰り返す j = j + 1; if (j != 1){lowPlayer.play();} // 1拍目以外Low if (j == 1){highPlayer.play();} // 1拍目のみHigh if (j == beat){j = 0;} // 指定拍でループリセット }, 60 / bpm * 1000); } function Stop(){ // インターバルを停止 clearInterval(BeatInterval); // 再生ボタン有効化 btn_Play.disabled = false; } </script>
高いビープ音を1拍目のみ、他を低いビープ音にする、っていう処理に試行錯誤しました。
失敗版は「開発ルーム」においてあるので、見て鼻で笑ってくださいw
参考Web
メトロノームを作るにあたって、メッチャたくさんのWebサイトを参考にさせていただきました。
と云ってもほとんどQiitaさんですが。この場を借りて御礼申し上げます m(__)m
GARMINウォッチでメトロノーム音を鳴らす
前述したように、わざわざ走るためにこのようなブログを起動するとは考えにくいです。
やはり、理想はランニングウォッチでのメトロノーム再生ですよね。
ということで
と調子ぶっこいてたら…
既にあった笑
しかもガーミン純正で。
- アクティビティ設定
- メトロノーム
- bpmの設定
- ビート(拍子)の設定
- 通知方法(音/バイブ)の設定
機種は限定的らしいですが。
945,745,245にはあるけど55にはない。
廃盤になってしまった230/235にもありませーん ;;
この流れでConnect IQ SDK(Garminアプリ開発キット)を眺めていたけど、ちょっとハードル高そう。
少なくともJavaScriptのような手軽さではなさそうでした。
まだまだ知らない世界がたくさんあるな~
引き続き、精進してまいりましょう。
では。