はくちょう座のブログ

このブログは、数学とアニメとlinuxに傾いています。

JavaScriptで音楽アナライザを作ってみた

これはTSG Advent Calendar 2016 - Adventarの18日目の記事として書かれるはずのものでした。

デモページ
とりあえず説明です。

概要
 JavaScriptとHTML5 Canvas+pixi.jsを用いた音楽アナライザー
特徴
 サーバーに頼らずクライアント内で処理をしている
 最新ブラウザならパソコンだけではなくスマホでも利用可能
説明
・ファイルを選択で手持ちの音楽ファイル(.mp3,.wav,.m4aで動作確認済み.動画ファイルだが.mp4でも可能)
・一番下がC3,上がB8までの72音階に分けてその音階がどれだけ出ていたのかを表しています。上のほうが周波数としては高く、下は低くなっています。音と周波数の関係はこちらのページを参考にしてください。
・緑色で表示されている部分はその時間帯で最も音が強い音階です。
・黄色で表示されている部分は緑色と同じくらい音が強いです。
・赤色で表示されている部分は赤色に近ければ近いほど音が強いことを表しています。緑色黄色には及びません。
・同時にBPMの検出も行っています。右上に表示されています。その横にある赤い丸はBPMに応じて点滅しています。
・BPMの検出に応じて赤い線と赤い線の間が4分音符1つ分になるように調整しています。
・曲を変える時は一度更新ボタンを押さないと正しく動作しません。

どのように解析しているのかを軽く説明します。

(1)ユーザーの手元にあるファイルを解析する段階まで
ファイルの読み込みは、HTMLのinput要素を使います。"ファイルを選択する"というボタンのことです。こちらから音楽ファイルを読み込みaudio要素のsrc属性で指定すれば音楽の再生は可能です。しかし、これだけでは解析することが不可能です。そこでWebAudioAPIを利用します。具体的にはAudioContext インターフェースのdecodeAudioDataメソッドによって、音楽データをデコードします。そうすると音量のデータが配列として扱えるので便利になります。また音楽解析用にJavaScriptでクラスを定義しておき、各種メソッドを行うことで解析できるようにします。

(2)どのように解析するか
音楽解析用クラスのプロパティに音楽ファイルのデータを設定した後、各種解析を行います。
まず最初にBPMの検出を行います。こちらはいろんな手法が考えられていますが、
C/C++言語で音声ファイルのテンポ解析を行うサンプルプログラム(http://hp.vector.co.jp/authors/VA046927/tempo/tempo.html)
を参考に実装してみました。

他には1秒間に数十回くらいWebAudioAPIで定義されているFFT(フーリエ高速変換)を行います。そうするとある特定の周波数ごとの強弱が数値として表れます。ただ、特定の周波数が12音階の周波数と一致するわけではないので多少計算で処理を行う必要があります。

(3)どのように表示するのか
HTML5 Canvas+pixi.jsを使って表示しています。
pixi.jsだとWebGLを利用するので描画が高速になると思い利用しました。実際どれくらい速くなっているかは分かりません。


本当は自動採譜などを入れたかったんですが難しいですね。



東大受験を振り返って -後編-

よかったら、 東大受験を振り返って -前編- の記事もご覧ください。

注意

この体験記はあくまで個人の感想です。己を知り、計画を立てることが合格への道です。文章自体は受験直後に書いたものですので日本語的におかしい部分が存在するかもしれません。ご了承下さい。

総括

受験勉強してよかったと思うところは、かなり極限状態に追い込まるという体験に尽きる。
センター以降ひきこもった状態になったので、会話数の減少、日光を浴びない、軟禁状態というのが精神的にくる。冬休みとかは割と学校に行っていたので、そういう習慣は続けたほうがいいのかもしれない。

センター後


センターリサーチで担任のCD判定の人は頑張って挽回〜という言葉を聞いてE判定には人権がないと思った。5点というハンデは大きいと思った。ニコニコ静画で漫画を一気読みするなどの生活を送る。頭がおかしくなって12時間くらいネットサーフィンをしていたこともあった。(何のとは言わないが)ゲームの体験版をやったり宣伝動画をひたすら見てた。そしてロゴが出るタイミングを測ったりしてました。その動画を見ながら頭を働かせなきゃって感じて数学の問題を作問していた。(解いてはいない)そして、一日中ネット(主にニコニコ静画)を見てました。

ただただ現実逃避の時間でした。それでも風呂に入ると罪悪感という感情が出るので夜寝る前に他の大学の数学の問題を見て、解法を考えてその後解答をみて確認する作業をしました。なんか2月辺りに塾から模試の過去問がやってきたのでそれがモチベーションになりました。ずっと部屋にいると発狂するのでたまに家の裏の山まで登って風景を眺めていました。

二次試験直前に塾から合格祝賀会のお知らせの手紙がきたがくしゃくしゃにせざるを得なかった。(ただ捨てはしなかった。)



センター後は外へ出る理由がなくなってしまうので、私立大学を受験するのもいいかもしれませんね。1日前に過去問演習しただけで落ちたと思ったのに合格してしまい、何なんだーという感じだった。



受験1日目

教室には8時40分位だったのにも関わらず、多くの人が存在してなんか試験官の人が喋っていて遅れてしまったのではないかと思った。

これ以降問題のネタバレが含まれますのでご注意下さい。








国語

国語現代文が第2問以降全く分からず何言ってんだという状態だった。ちなみにセンター以降現代文には全く触れてない。

古文 いろならむもの これだけは分かるぞ分かるぞという感じだったので結構丁寧に記述した。

漢文 能という言葉があったら不と入れたくなるのが人情でしょう。

数学


まずパラパラとめくって、第5問が数学オリンピックのような1行問題でこれはいけると思った。すぐには解けなかったので、その前に第4問を解いた。ただ緊張した。幸い、(1)は数学的帰納法で示せたのでむりやり等式にすれば何とかなるだろうと思ってたら、合ってた。(2)も簡単だったが、(3)で止まり、第5問へ。
第5問は2015!/n!(2015-n)!で分母分子で2の倍数考えるのかと思ったけど、そんなの無理無理かたつむりだったので漸化式っぽく考えたら(2016-m)/mの要は掛け算の積じゃんって考えたら楽になった。解答用紙の半分に収まったのでお得だった。

第3問は(1)は楽だった。しかし、(2)で何か変な式が登場して(3)解くの無理だろって感じであった。なのでパスして、第1問。

第1問はx=定数の場合はどうなるかを慎重に考えていけばオッケーだった。
次は第2問は方針思いつかなかったのでとりあえずnが小さい場合を考えるとアイデアが浮かんだ。その後は順調に行ったが解答用紙の余白が少なくなり何度確認しても合わないことが続き焦った。

※数学の試験途中に"俺"が、アルティメットまどかだという思いがわいてきた。

解答用紙回収時に第一問同じような図を書いてる人がいて安心。

直後に第6問の解法が思いついてああ、って感じ。でも自己ベストだ、受けて良かった。精神状態悪いままじゃなくて良かった。って感じ 思いのほかよくできたので満足した気分だった。2日目の科目の勉強する気力も湧いた。その日の夜は(も)眠ったのは3時以降だと思う。

理科

睡眠不足で「死ぬー、死ぬー」と言いながら理科の受験に挑んだ。解いてる時も、死ぬ〜死ぬ〜という感じだった。模試とほぼ同じ問題が出たのにもかかわらず解けなかったのはつらかった。熱力学だけはほぼ完答して意地を見せた。化学は、半反応式を思い出すことができずに終了。


英語

いきなりリスニングはじまるのではないか、怖いと思ったので、最初に選択肢まで日本語訳してリスニング開始時刻直前もパラッとみた。(英弱だったいや英弱でないとして日本語に訳して考えてみよう)これが結果的には功を奏したと思う。そのあと聞いてみたらリスニング難化したと言ってラッキーだった。なお他の分野が壊滅的でリスニングが得点のほぼ半分を占めた。


同じ教室に同級生がいた。休み時間会うことは流石に憚れたが、同級生がカードゲームをやっていたらしく驚愕した。英語が悪くて受験した記憶を消すぞ〜という感じでした。

帰り道、同級生(彼は後期で受かった。)と一緒に帰った。物体認識について語って、受験前はそんなのばっかり調べてたんだよと言ったら流石に驚かれた。また英語の試験を受ける前に合格を確信していた同級生の話をした。


二次試験受験後


魔のお疲れさん会がありました。(僕以外の人が落ちたらしい)

楽天がビデオ見ても全額ポイント還元するという驚異のキャンペーンをやったのでアニメをたくさん買った。

きんいろモザイクを見てた。問題なんて何もないよ。結構結構いけるもんねー



合格発表1週間前からストレスがたまり、まさに断頭台、まな板の上の鯉という状態でした。あまりにもイライラしたのでハンドグリップを購入したくらいです。合格発表は事前に12時より前に来ることは分かっていました。あった時は番号があるけど本当にあったのという感じでした。まるで自分が合格する平行線に移っただけで本当は不合格なんじゃないかという思いさえありました。受験は運がわりと絡んで来るということを感じました。




合格後


塾の合格祝賀会に行った。
胴上げしてもらったのて良かった。

得点率だと数学>物理>国語>化学>英語という特徴的ものになりました。

勝因
苦手な英語が難化しみんなと致命的な点数差がつかなかった

国語がなぜか点数とれてた。

数学の圧倒的得点⤴⤴⤴

スマホは持っていなかったがそれに類似する機能を持つものはあったのでさすがにそれは秋くらいから封印していた。

東大模試とかでプライドはズタズタにされるのでなにか行動する敷居が少し低くなったのかもしれません。
あとこういう長文書くのにもそこまで苦でない感じ 受験期にあまり人と話す機会がなかったというのもあるけど

わりかし模試と似た問題が本番でも出題されることがある
過去問とか早めに触れておいたほうがいいのかもしれない。
要は自己分析が重要だと思った

おすすめ

受験前の部屋の状態、精神状態を記録しよう。合格したらネタになるし、そうでないにしても今後に生きると思う。

早め早めに行動するのが吉

所詮試験形式になればいくらか点数が伸びるかも。
変に自分の制限をかけない方がいいかもしれない。私の場合、過去問をとっておいたけど国語とかほとんどやれなかったし、1、2回くらいだと見につかない。
昔の過去問を解いて、自分はこんなにも足りないのか早く自覚することが大事ですわ。

英語が苦手な人はリスニングで点数を確保した方がいい。リスニングは理論上聞き取ることができれば点数がきます。

確率の問題が出たら、心を落ち着かせ、方針を定めるためにnが小さい場合をまず調べましょう。


受験ギリギリまで基礎とかをしっかりしといたほうがいいかも。問題演習だけしても伸びない。ある程度実力があれば話が別。

入試に絶対なんて言葉はない。
センターリサーチe判定
英語50
模試で一度もA判定無し
でも受かる。
逆にこの人は受かるだろうという人が落ちてた。


任意の数字を出現させる話

どうも、lip_of_cygnusです。TSG Advent Calendar 2015の16日目の記事です。


小学生の頃は自由帳に2の累乗ばっかりだけ書いているような子供でした。
今日の話題は高校生の時、担任の先生からもらった問題についてです。


「すべての自然数は2の累乗に現れる」


本記事ではこの問題を2つの方法で解きたいと思います。

方法1:上から攻める

$\log_2 10$が無理数であることを用います。

無理数であることの証明は簡単です。
$\log_2 10$が有理数であると仮定すると、
$2^\frac{m}{n}=10$となります。両辺をn乗すると、
$2^m=10^n$
2と5は互いに素なので、右辺は5の倍数になるのにもかかわらず、左辺は5の倍数ではありません。
矛盾しているので、この仮定は不合理であるため$\log_2 10$は無理数です。さてここでクロネッカーの稠密定理を用いたいと思います。

クロネッカーの稠密定理:
任意の無理数xと$0 \leq a < b \leq 1$を満たす任意の実数a,bに対して$a \leq \{nx\} \leq b$を満たす自然数nが存在する。

詳細については、こちらをご覧ください。
クロネッカーの稠密定理とその証明 | 高校数学の美しい物語

2の累乗に現れてほしい自然数をxと置きます。クロネッカーの稠密定理より、

\[
m-\log_2 (x+1-ε)\leq n*\log_2 10\leq m-\log_2 x\\
(mは\log_2 xより大きい整数,0<ε<1とします)\\
m-\log_2 (x+1)< n* \log_2 10 \leq m-\log_2 x\\
\]
各辺を2^(各辺)という感じにすると
\[
\frac{2^m}{x+1}<10^n \leq \frac{2^m}{x}\\
\frac{2^m}{x+1}<10^nより、\\
2^m<(x+1)*10^n\\
10^n \leq \frac{2^m}{x}より、\\
x*10^n \leq 2^m\\
\]
\[x*10^n \leq 2^m<(x+1)*10^n\\
\]
ゆえに、任意の自然数xが2の累乗に現れることが示されました。

方法2:下から攻める

2の累乗に現れてほしい自然数をxと置きます。
まず、xの後ろの方に数字を付け足します。
xの桁数をNとした時に、M桁足してN+M桁が$2^{M+N}$乗の倍数となるようなものを探します。
M=Nとすれば、x'の候補となる数は$10^N$個存在するのでその中に必ず$2^{M+N}=4^N$の倍数となるものは存在します。そしてこのようなx'は必ずある2の累乗中に存在するのです。証明にうつる前に補題を示します。

補題: 数列 $2^0,2^1,...,2^{5^t-1}$を考える。これを$5^t$で割った余りは全て異なる。
背理法で示す。余りが同じになる組があると仮定し、これを$2^i,2^{i+j}$(jは$j<5*t-1$を満たす自然数)とおく。
$2^{i+j}-2^i=2^i*(2^j-1)$2と5は互いに素であるので、$2^j-1$は$5^t$の倍数になります。(すみませんこのあとの証明思いつきません)

証明:上の桁がk(ない場合は0)で、下M+N桁がx'であるような自然数Pを考えます。
P=k*10^(M+N)+x'=2^(M+N)*(k*5^(M+N)+x'')
この時、x''は必ず5^(M+N)の倍数ではない自然数になります。(x'が自然数でM+N桁であることから分かる)ところで、t=M+Nとすれば補題より(k*5^(M+N)+x'')は2の累乗で表すことができます。従ってPも2の累乗で表すことができます。ゆえに、任意の自然数xが2の累乗に現れることが示されました。

せっかくなんで、両方の方法で自然数xが含まれる2の累乗を出力するプログラムを作りました。言語はPythonでpython log2.py 数字 という感じで入力すると結果が返ってきます。

例えば今日の日付にちなんで1216を入力すると
$1442$ $121689679549848296476284539719833956128172746808983983951831652023347365468864269429292576963439508278182027446718540810569381644337220853815156314657613612239712834757924740882197032736054344801343165356558510233936904806426545855737390911634598080775602523511373106777607060088046178460822014203870855117130108554646318067801134685013852825258691387386426550771312213642678910868232892059330844780618615710006156570567711150890287104$
$424$ $43322963970637732180912721627235682866194329302747133987038743447103457934462900359999600095377180907771737671271930809827721216$
と出力されます。
記事検索
アクセスカウンター

タグクラウド










































  • ライブドアブログ