「PIC AVR 工作室」サイトの日記的なブログです。
サイトに挙げなかった他愛ないことを日記的に書き残してます。
PIC AVR 工作室 ブログ



AMDFをどんなロジックで書いたら、精度と速度と
メモリ量をイイカンジに出来るかを調べるために、
昨日の表計算で作ったシートをさらにいじくって、
スイートスポットを探ってみる。

とりあえずソフトを起動したら、
http://www.openoffice.org/ja/download/?utm_source=AOO3_4_1_ja&utm_medium=Client&utm_campaign=Upgrade
OpenOffice4.0.0が出てるらしい。大きく数値が変わって
いる場合は、人柱モードになりそうなので、どうしようか
迷いつつ、入れてみた。500個以上のバグフィックス
が盛り込まれているらしいので。

でも、画面が1ドットずれてゴミが残る的な微妙な
バグは相変わらず残ってるみたい。まぁ、表示の
問題だけだろうと思うので、そのまま使ってみる。


残念なお知らせ。グラフ描いて、そのドローの
メタデータをグラフィックツールにコピペして
みると、座標軸の文字が化けた。単なる数字を軸に
当てていたのに、なんだかよくわかんない西暦の日付
になっちゃう。仕方ないので、画面キャプチャソフト
使ってグラフィックを取り込むことにする。

まぁ、大きなバージョンアップは、大体バグってる
よね。


とりあえず、ドミソラの信号に対して、半音ごとに
比較周波数を当てながら、誤差計を計算していって、
どんな風になるのかをグラフで可視化してみる。
可視化することで全体的な「傾向」がつかめるはずだ。

で、やってみたらこんな感じに。



うん。およそ想像していたような結果になってる。
これだとちょっとごちゃごちゃしてて解りにくいと
思うので、ソの音を3オクターブ分取り出すとこんな。



色が似ててわかりにくいけど、「青」が196Hzのソの音
で、当然196Hzだけで誤差極小。
「小豆色」が392Hzのソの音で、392Hzと196Hzの2箇所で
誤差極小に。
「紫」が784Hzのソの音で、784Hzと392Hzと262Hzと196Hz
で誤差極小に。

紫の784Hzについてだけ取り出してみると、こう。


知りたいのは、この図の一番右側の「誤差極小」となる
周波数。ここで問題が生じる。つまり、1波形だけ
ずらした場合の「ずらし量」が知りたいんだけど、
周波数が2倍(波長は半分)の場合は、2波形ずらした
ところも一緒に。さらに高い周波数だと、もっと
たくさんの点で誤差が極小になっちゃう。


誤差極小になる点は、この図の様に複数個所で出てくる
んだけど、どうしたら、それが一番右側の周波数って
ことが判るのか。実際に計算した値は、誤差「数十」程度
の数値で、必ずしも右の数値が一番小さいわけじゃない。
単なる誤差極小となる個所を拾うロジックだと、この
4箇所のうちどこが拾われるかが、運を天に任せる状態
になっちゃう。

んで、ココでグラフを描いた意味が出てきた。図中の
「誤差極小」地点4箇所を見比べてみると、拾いたい
ところは、他のところに比べると、開く角度が「広い」
のが判る。それを利用。


数学得意な人だと、多分これらの点(離散値)を
滑らかに(微分可能な形に)補完して、2回微分して、
その値が「プラス値」で一番小さいところ(下への
出っ張りが緩やかなところ)を選べばいい、と
考えるであろうところ。


まぁ、そうなんだけど、そんな補完すると計算時間
もかかるし面倒。その考え方だけ利用することにして、
もっと簡単な方法を考えてみる。2回微分の代わりに、
その両隣のデータを利用する。こういう感じ。

↓これが抽出したいデータ。


↓これが抽出したくないデータ。


図中の「茶色」のバーの長さに注目。どちらも真ん中の
バーの長さ(誤差の大きさ)は同じくらい小さいん
だけど、その両端の誤差も含めて「3つの茶色」を足して
から比較すると、このソの音に限らず、どの場合でも
必ず上の状態の点が「誤差最小」となる。よし、使える。

つまり、トンガリがきついところは、両脇のデータの
誤差が急に大きくなるので、それまで含めると簡単に
抽出が出来るわけ。
もちろん、極小点付近に限らず、他の点を含めてもこの
「両側も合算」した値で最小値をとる点が「お目当ての
音程」となるわけ。2回微分とか使うことなく、単に
3つの数値の足し算でイイカンジの弁別が可能。


この結果を使って、半音単位の音を正確に同定できる
ことはなんとなく判った。シメシメ。


こんな感じで、どの音程付近の音か判ったら、次は
その音の周辺で、1cent単位で音程を絞り込んでいく
って感じにすれば良さそうだな。最小周波数から最大
周波数までを、1cent単位で全部舐めていくという
必要はないわけ。


さらに、「左右の誤差情報」も一緒に評価するって
いう方法は、1cent単位の微妙な誤差を抽出する場合
でも、差分を明確に洗い出しそうなので、そっちでも
使うことにしたいな。


大体作戦が決まったので、あとはメモリ量の削減と
処理時間の削減だな。

処理時間の削減の一つは、この「半音単位」で
一旦絞り込んでおいて、その後で微小なズレを抽出
するっていう作戦でいいと主運だけど、まだまだ
手を抜けるところを抜かないと、タイムラグが
大きくなり過ぎそう。

もうちょっと詰めていこう。


あと、シミュレーションしてみてわかったんだけど、
振幅が最大付近なら1cent単位で分離出来るんだけど、
音量が下がっちゃうと、ダイナミックレンジが狭く
なるせいで、1cent単位は厳しい…

http://brown.ap.teacup.com/nekosan0/1458.html
以前探ったような、「対数アンプ」についてちゃんと
考えておかないと駄目だろうな。



http://headlines.yahoo.co.jp/hl?a=20130729-00000101-mai-soci
この半々のクワガタ。ガッチャマンを思い出した…


http://www.switch-science.com/catalog/1318/
スイッチサイエンスに、電子ペーパーのシールド
なんて有ったのか。
http://www.aitendo.com/product/7075
aitendoにもこの間電子ペーパーが出てたな。



コメント ( 0 )




引き続き、AMDFを使ったピッチ計算で色々もがく。

いきなりプログラム組むとナニなので、例によって
表計算ソフトを使って数値シミュレーションしてみる。


作戦は、ADCから512点のデータを40000spsで正弦波を
サンプリングした状態をシミュレート。コイツを任意の
周波数に該当する時間分だけシフトしてみて、それが
元の波形と比較してどのくらいの誤差になるのかを
計算してみる。

アレコレ考えながら、とりあえずワークシートが出来た。


とりあえず、「補完」を行わずに、1サンプルは1サンプル
として整数値単位でシフトさせてみた結果。

220Hzで計算してみると、確かに丁度220Hz付近で
誤差が最小値になることを確認。

続いて440Hzの場合。440Hz付近の4つの周波数(438
~441Hz)で同一の最小値になった。


そう。シフトが整数単位(セル単位)だから、四捨五入
の結果、同じセル分だけずれたところを参照しちゃう
んだよな。これだと、1centはとても分離できないという
ところは予めわかってたところ。

とりあえずはココまで。


んで、この後は、整数単位ではなく、端数分を使って
按分することで、セル以下の数値に補完(直線補完)を
掛けてみるだな。

数値的にはきっと妥当な値まで追い詰めることがが出来る
だろうけど、問題は、計算速度に影響する「計算回数」
だな。

どうやったら計算速度を下げずに精度を保てるか。

シミュレーションで、手替え品替え、追い込んでいって
みよう。それができれば、Arduinoならすぐにスケッチに
落とせるだろう。


バイナリサーチ的な演算で追い込んでいけるといいんだ
けどなぁ。純粋な正弦波ならともかく、ノイズ混じりで
倍音混じりの信号となると、その手が通じるのかどうか…

あと、440Hzの波形を220Hz分だけシフトさせてみると、
当然だけどピッタンコ合っちゃうんだよな。(丁度
2波形分に相等するから)
こういうの、どうやって区別付けたらいいのかも、
一緒に考えておかないとな…。




コメント ( 0 )