goo blog サービス終了のお知らせ 
「PIC AVR 工作室」サイトの日記的なブログです。
サイトに挙げなかった他愛ないことを日記的に書き残してます。
PIC AVR 工作室 ブログ



昨日作った回転因子テーブルの造りについて考えてて
ふと気づいた。

cosとsinを別々のテーブルに分けて作っちゃったんだ
けど、よく考えたらcosとsinはどうせ同時に読み出す
必要があるし、1段目から6段目まで32個のデータを
順々に読み出していくことは決まっているし、
なにより、AVRのレジスタが直交性が高いとはいえ
アドレッシングに使えるのはx,y,zの3つ。
プログラムメモリにアクセスするレジスタはzの1個だけ。

ってことは、テーブルをあっちこっちアクセスする
ロジックだとオーバーヘッドが大きすぎる…。

回転因子テーブルに触るレジスタはz固定なんだから、
ここはひとつテーブルの構造をAVRのアセンブラに
フル特化させてしまった方が賢い。っつーか最初から
そうしておかないのがオイラの毛が3本足りない
証拠だな。

って言うことで、99basicのプログラムは修正要だな。



コメント ( 0 )




引き続きFFTをアセンブラフルスクラッチの作戦を継続。

二分法による平方根の開平は目処が立ったので、
次は一つの肝:バタフライ演算1個分の計算処理。

ザックリとi/f仕様をあぶりだしつつ、使用リソース
の試算をしてみたら、マクロ化して全処理をメモリ展開
してしまうとすごい量食いそうなので、ここは大人しく
サブルーチン化しておいた方が安全っぽい。

マクロの方が何かと都合が良いんだけど、仕方ないので
サブルーチン化する方向に。


とりあえず負数の扱いとか一切無視して思いつくまま
コードを書いてみると、1回のサブルーチンコールから
リターンまで30~40クロックといったところ。実際は
この後桁数とか精度とか桁あふれとか色々考えながら
調整しないといけないので、40~50クロック程度と考えて
おけばいいかな。

64点FFTだと、6段階の2点DFTに分けて処理することに
なるので、計算では6段×32回×50クロックとすると
1回のFFTがおよそ9600クロックかな。
これにビットリバーサル処理や平方根算出の処理が
追加されると、10000クロック少々といったところ。

単独で使えば毎秒1600回(@16Mhz)といった感じ。
今回のウケシンセとしては、8パートに分けてFFTを
掛ける予定なので、FFTだけに費やせば毎秒200回
程度の頻度で全パート分のFFT計算が出来るはず。よし。

残りのアプリ要件のロジックしだいだけど、FFTよりは
軽い処理になるだろうから、ADC終了からMIDIデータ出力
まで最短では1/200秒程度の遅れにしかならないはず
なんだけど、MIDIの遅延問題はこれだけじゃないから
厄介。遅延というと…

(1)弦をはじいてからADCするまでの遅延時間
(2)ADCしてからFFT掛けるまでの遅延時間
(3)FFT掛けてからMIDIデータ出力までの遅延時間
(4)MIDI音源が信号を受けてから発音するまでの遅延時間
(5)発音してからADSR制御の振幅が最大になるまでの時間

単純にこれらが直列で積みあがったのが遅延時間に
なると思うんだけど、厄介なのは(2)と(5)。
がんばってナントカできるっていうものじゃない部分。

特に(2)は悩ましかったところ。FFTの処理自体をどれだけ
高速化しても、仮に64点FFTなら64個のデータがそろって
からようやく各周波数ごとのエネルギーが安定して出力される
わけで、1サンプル辺りの時間(サンプル周波数の逆数)×点数
の時間が必ず必要になってしまうということ。
プロセッサの処理速度や計算ロジックとは無関係に、
「一定量のサンプリングデータを取り込む時間が必要」
なわけ。

まぁ、実際は半分くらいのデータがサンプリングできた
時点である程度の情報は取り出せているんだけど、
それをどう踏まえてどう料理するか…。

http://ja.wikipedia.org/wiki/%E3%82%AE%E3%82%BF%E3%83%BC%E3%82%B7%E3%83%B3%E3%82%BB%E3%82%B5%E3%82%A4%E3%82%B6%E3%83%BC
FVCを使っているギターシンセでもその辺の問題は多かれ
少なかれあるみたい。まぁ、やるだけやってみよう。



さて、バタフライ演算がおよそ目処付いたところで、
次はバタフライ演算に与えるデータのことを考える。
まずは回転因子(twiddle factor)。こいつはさすがに
sin、cosを馬鹿正直に計算するわけに行かないので、
あらかじめ定数テーブル化。

この手の定数テーブルはPC上でサクッと作るのが
簡単なので、久々に99basicを使ってみることに。
(久しくスクリプト系言語から離れているので、
 perlとかrubyとか候補に挙がらないのが悲しいところ)

BASIC自体は子供のころから染み付いているので、
さすがに殆どhelp見ずにすらすら手が動くんだけど、
いざ実行してみたらおかしな結果に。出力された
ファイルをテキストエディタで開いてみると奇奇怪怪
な文字列に…   うーーーん。

しばらく悩んで思い当たったのは、改行コードの
強制出力処理のところ。

BASICだから、ファイル相手だろうと画面相手だろうと、
print文で出力パラメタ無しにすれば改行してくれる
だろうと思ったらおお間違え。
確かに99basicでも画面出力はそれで改行できるっぽい
んだけど、ファイル相手にパラメタ無しで出力すると
その直前に出力していたものを再出力するみたい。
(例えば、 「print #1」だけみたいな)

仕様?バグ?とりあえず、
       print #1,""
って感じで長さゼロの文字列を吐いておけば改行される
みたい。判るまでにえらい時間かかった…


とりあえず、回転因子の定数テーブルは一通り出来たので、
残るはメインディッシュのFFT計算ロジックのところと
ビットリバーサル処理だけだな。



ちょっと前に入手したままになってたデフレの正体
ようやく読み始める。

まだ読み始めて1/4も進んでないんだけど、これまでに会計、
ミクロ経済、マクロ経済…と通り一辺倒のお勉強をした
だけではよく判らなかったもう少し巨視的な、かつ
データに即した視点が得られたのはなかなか。

少し楽観的な印象がないでもないんだけど、オイラが以前
からおぼろげに思っていたような、生産者人口の減少
(言い換えれば消費人口の減少)っていう視点が出てきて、
なんとなく腑に落ちる部分があっていい感じ。
まぁ、本は「答え」じゃなく「視点」を提供してくれれば
いいのだ。模範解答を求めているわけじゃないのだ。

それにしても、目下半分は興味、半分は狐につままれた
ような感覚。

これを読み終わったら次は超マクロ展望 世界経済の真実
だな。


それにしても、お金持ち高齢者から現役世代への資産
移動を本気でやりたいなら、ある意味簡単なんじゃ
ないかなぁ?
生前贈与の税率を大幅に下げて、一方で遺産相続税を
大幅に上げちゃえばいいんじゃない?時限立法とかで。

と以前考えてみて、そういえばマクロ経済では貯蓄の
総額(国全体での預貯金?)と企業の設備・在庫投資は
一致するという話があったんじゃないかな?
http://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%AF%E3%83%AD%E3%83%90%E3%83%A9%E3%83%B3%E3%82%B9
↑ここか?
そうすると、貯蓄が消費に回った途端に投資にお金が
回らなくなるっていう話になるような…まずくない?

とか、悶々としながら本を読むのが何だかんだ言って
好きです。



コメント ( 0 )




アセンブラでFFTを振るスクラッチの妄想を現実化
するための一歩。まずは簡単なところってことで
8ビット幅の平方根(16ビットデータから8ビット幅の
平方根を求める)を計算するマクロを組んでみる。

まずは以前作ったexcelシートをそのままアセンブリ言語
に落としていってみる。

とりあえずそれっぽく計算結果が得られたんだけど、
微妙に変なところとかあって、あれこれ微調整を
してみる…。まぁ、120クロック程度で計算できるように
出来たのでヨシヨシ。だいぶご都合主義の怪しいロジック
なんだけど、まぁ正確な数値が出てるみたいだからいいや。


それにしても、excelシートに作りこんだロジックで
不等号を結構いい加減に考えてたことに気づいた。
イコールが含まれるのか含まれないのかの点。

それと、二分法を愚直にロジックに落とすと
0の平方根って普通には出来ない(1以上とそれ以下で
分けて考えないとだめ)なんだけど、正の整数って
限定すれば、初期値の与え方次第で0もそのまま
計算できちゃうっぽいな。

一方、計算途中に使用するレジスタ類が8ビットだから、
どうしても65025(=0xff×0xff)以上の平方根は
うまく計算できないっぽい。ここは定数を見て
特殊ロジック対応にした方が速いな。

アセンブラにしても高級言語にしても、数学の計算式
どおりに行かないのがコンピュータの計算処理。
誤差とか閾値とか常に考えないと駄目なのよね。
あまり得意ではない分野。


まあ、そういうわけで平方根ができたので、次は
FFT本体部分の計算だな。これもマクロ化して
おきたい。




コメント ( 0 )




相変わらず、フルアセンブラFFT計算の調べ物の続き。

バタフライ演算→ビット入れ替え、と来たら次は
自乗和の平方根。

平方根を如何に手を抜きながら高速で処理するか。
しかもアセンブラで、というお話。

以前目論んでいたのは、平方根、つまり」0.5乗
の計算をうまい具合に分解して簡単かつ高速な処理
にすること。
…悪くは無いんだけど、一部でちょっと面倒な計算が。


ってことで別の方法が無いかな…と思って探したところ、
よくよく考えてみるとオーソドックスな二分法なら
意外に処理時間も早そう。2進数の8ビット精度で
求めればいいってことは8回ループ計算でok。
しかも結構単純な計算式。

さて、8回ループの整数演算でどの程度の精度が
出せるのか?と思って、表計算ソフトで実験をば。

やってみたのがこれ。
sqrt_nibunhou2.xls

橙色のセルに1から65535までの数字を入れると
水色のセルに平方根が求まるって仕掛け。
ちなみにざっくり269まで1個1個計算してみたところ
目論見どおりピッタンコ。

ただし、求まる値は「小数点以下切捨て」。
四捨五入になると良かったんだけど、そこまでやると
ちょっとめんどくさそう。

まぁそこまで厳密なことをやりたいんじゃぁ無くて、
まっとうな計算ができればいいって程度なので、
これで方向性は決まったかな…。

平方計算はMEGAシリーズのハードウェア乗算器で
2クロックを8回分。そのほか周辺処理などを加味して
ざっくり100クロック前後でなんとかなりそう。

あとは少しずつアセンブリ言語でゴリゴリ書いていく
だけだよな。ガンバロウ。



コメント ( 0 )



   次ページ »