feature image

2017年4月15日 | ブログ記事

midiでフーリエ変換【新歓ブログリレー2017 12日目】

こんにちわ uynetです
普段はサウンド屋をやっているのですが、今回は趣向を変えて技術系を挑戦してみようと思います。
よろしくおねがいします。

はじめに

任意の波形は正弦波に分解できるという有名な話があります。(厳密な話は無視)
ならば、どんな音声でも正弦波に分解し、midiで鳴らせば†完全に再現†ができるはずでは???

midiで音声を再現(ry - その3 スフィア「Future Stream」

これマジ!??!?

やろう

すごい面白いし、最近FFT(高速フーリエ変換)にも興味があったので、この際勉強するついでにやってみよう!と思ったのですが、難しそうです。

しかし、やり方を丁寧に解説してくれてる動画がありました。
【音声合成】 MIDIに歌わせてみた 【only my railgun fripSide】

なるほど~
とりあえず、少しずつやってみることにしました。

目標

①wavを選択して投入する
②FFTし、midiに変換したデータが出てくる
こんなプログラムが作れたらいいですね

wav編

・wavとは
波形を表現するためのものです。

もっというと、波形を細かく切り刻んで数字だけにしたものがたくさん並んでいます。

wavの解読

wavをテキストエディタで開いてみてみます。
440Hzの正弦波です。

一見すると数字が大量に並んでいてヤバイ!
ですが特段大したことではないです。

構造は大きくヘッダチャンクデータチャンクと呼ばれる部分に分けられます。

ヘッダチャンク

サンプリングレート、ステレオ/モノラルなどの情報が入っています。短いです。

データチャンク

波本体の部分です。音声データの標本の振幅が並んでいます。ビットレートが16なので、一つの標本は4けたの16進数のデータを持ちます。
一秒当たり4万x4文字が並んでるのでそれはもうとんでもない量です。

wavの構造はここに書いてあるのを参考にしました
WAVEファイルを覗いてみる(基本型)

なら、標本を10進数に直してグラフにすれば正弦波の形になってるはずです。
一周期分の標本を取り出してグラフ化したものがこちら

あれ?

調べてみると、リトルエンディアン表記らしいことがわかる。
もう一度計算し直してみます。


はい、キレイな正弦波になりました。

DFT

DFTとは離散フーリエ変換のことです。

フーリエ変換のアルゴリズムについては本当はもっと理解してから挑みたかったのですが、時間が無かったので
ここの解説をざっくり目を通してから関数を拝借させてもらいました。
nursの日記 - プログラムの国のフーリエ変換

しっかり理解したいという方にはこのサイトがおすすめです(多分)。
やる夫で学ぶディジタル信号処理

ここに440Hzの矩形波があります。

これをフーリエ変換するぞ〜

さっきと同様にwavの標本を読み取って数値化し、配列に突っ込む

DFT関数(ほぼ引用)に突っ込む

出力を16進数にして書き出し!


感動した
理論値をググると、ほぼ一致しているのが分かります。

次に、440Hzの矩形波を作るのに最小限必要な正弦波の周波数と振幅が知りたいので、スペクトルの極値から大きい順に16個抽出します。16個の理由は後述。

試しに抽出した極値を元に波形を正弦波の重ね合わせで再構成してみると、

よく見る矩形波の近似みたいなやつになりました。

試しに、これを書き出してwavにしてみます。

微妙に誤差がありますが、ちゃんと矩形波っぽく聞こえます。

midi編

・midiとは
演奏を表現するものです。
コンピューター用の楽譜みたいなものです。

midiの解読

上で分解した正弦波を突っ込めばいいのですが、そのためには以下のことができるようにしたいです。
・任意のタイミングで音をならす
・任意の高さの音をならす
・任意のボリュームで音をならす

wavと比べるとmidiのほうが容量が小さい分、高度な情報を扱っているので解読がはるかに面倒です。

解読タイム

SMF(Standard Midi File)の構造についてググるといろいろ出てきます。
MIDI資料館 - SMFの構造
わ、わからん...

手っ取り早く目的の情報を見つけたかったので、こうすることにしました↓

まずこんなmidiがあります。

これのノートの部分はこうです。

ff2fという部分がトラックの終わりっぽいです。

なら、これを複製してみるとどうなるでしょうか

一行増やしました。開いてみます。


なんかエラーでた

調べたところ、トラックの先頭にトラックのデータサイズを書くところがあって、そこと整合性が取れてないのが原因みたいです。

FISH&BREAD - SMF(Standard MIDI File)フォーマット解説から引用。


ここにデータ部分のファイルサイズが書いてあります。
一つのノートが16文字=8byteなので、二つ増やすにはこの数字を16増やします。
16進数なので6cを7cにすればいいですね。

それではまた開いてみます。

感動した

みたいな感じで、もくもくと解読を進めます。

信号の変換

「振幅A,fHzの正弦波を再生するmidi信号」を出力しないといけないので、wavを分解して得た正弦波それぞれの振幅と周波数について、midiに変換します。
880Hz(A5)を基準として、振幅はボリューム、周波数はピッチベンドで対応させます。

ただし、ピッチベンドで変換できない範囲の周波数を無理やり変換すると図のようにやばいことになるので、880Hzの±2オクターブ(220Hz~3520Hz)外の音は切り捨ててしまいます。

実践

それでは、↑を踏まえて実際に波形を変換してみましょう。

ん?

ババーン!(死)

MIDIは強い

結論から言うと、記事間に合いませんでした。ゴメンナサイ
今のままでは不十分で、動かすにはまだMIDIについて調べないといけないみたいです。

とはいえ、頑張って矩形波だけでもなんとかMIDI化してみました。
矩形波?
が、全然矩形波になりませんでした。。。

メインになるはずだったフーリエ変換には一瞬しか触れてないし、ほとんどMIDIに時間を吸われてしまいました。
しかし、MIDIのバイナリと一日中格闘したのははまぁいい経験にもなったような、気がします。

記事には間に合いませんでしたが、せっかくいろいろ作ったりしたので、ちゃんとしたものができるまでもうちょっと続けようと思います

明日は「モデリング体験会案内」「個人から見たtraP像」の二本です!おたのしみに

uynet icon
この記事を書いた人
uynet

ゲーム制作/DTM

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2017年4月20日
学部1年の数学、特にε-δ論法に殺されないために【新歓ブログリレー2017 17日目】
hihumi icon hihumi
2017年4月12日
あたらしいWebAssemblyのはなし【新歓ブログリレー2017 9日目】
Double_oxygeN icon Double_oxygeN
2017年4月11日
できるかなってDistortion
clk icon clk
2017年4月9日
Pythonで数学の課題を解こう【新歓ブログリレー2017 6日目】
hukuda222 icon hukuda222
2017年4月8日
気軽にお絵かき! traP1draw【新歓ブログリレー2017 6日目】
Humming icon Humming
2017年4月7日
ゲームを作ろう! traP3jam【新歓ブログリレー2017 4日目】
Ark icon Ark
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記