I’m loser, baby.

So why don't you kill me?

mbed1114のCPUのスペックとライブラリの仕様について再確認してみる

弱気になったり脇道に逸れたりしつつも、引き続きmbedLPC1114について実験してます。
というのもライブラリの仕様を改めて確認してみたところ、mbedのPwmOutオブジェクトはデューティ比を直接時間で指定する時は最小単位が1マイクロ秒でここは整数値しか想定されていなかったのですが、自分はfloat値を入れてました。
それでも一応動いたんですが、なんか根本的な勘違いがあるような気がして調べたり考えたりしてみました。

LPC1114FNは内部クロックで動かすと48MHzで動きます。このクロックは1クロックで1動作ということですから、音を出すといった複数動作かかる作業で48MHzのスピードでは動けません。Monoistの記事を見ると単なるLED点滅をする場合でも7動作必要でした。ですのでGPIOにアクセスする動作は約7MHzが最速のレベルとなります。monoist.atmarkit.co.jp

当初、8bit11kHzのデータをベタでPWM変調でアナログ化しようとしていましたが、これだと約2.8MHzとなって既に最速レベルの40%のスピードをCPUに要求していることになります。しかも中途半端にfloat値を扱っているのでCPUにはかなりの重労働のはず。
STMでPwmOutをAnaloOutに置き換えただけでグリッジノイズが消えたのはPwmOutとAnalogOutの方式の違いだけでなくスペックの差によるモノだったのでは?まだPCのスペックが低かった時USBオーディオインターフェースの最適な設定値を探すのに苦労したことを思い出します。

ではLPC1114でPwmOutをオーディオ出力として使う際どの位の値の設定が現実的なのか?
通常のPwmOutでは1マイクロ秒がハード的に妥当な最小値とすると、11kHzのサンプリング周波数では周期が約90マイクロ秒になるので音の解像度は90、ビット数であれば6bit以上7bit以下となります。なのでbit単位ということであれば妥当なサンプリングレートの数値は6bit=64が良いのではないだろうか、という仮説が立ちました。
それと、これまで32bitCPUの威力に甘えていたfloat値の計算も全部int値にした方がCPUの負担も減るはず。

という訳でオーディオエンジンのソース手直し。ローカルでの作業で11kHz6bitでデータも全てint値に変更してコンパイル(1,2回のエラーでさっくり成功)して実行したところ、グリッジノイズは消えてPwmOut由来の高周波ノイズだけになりました!
PwmOutで音が悪かったのは自分の理解不足のせいだったのか。
4bitでもやってみたりしましたが乗算したサウンドは違いが出ましたが素のパルス波やノコギリ波は音は違いますが印象は似ているかも。

更に計算の負荷による処理速度の違いも如実になりました。乗算した音はテンポが遅く(でもリングモジュレーションなんで結構いい感じの音が出る)加算した音は速い状況です。どちらも同じ秒数wait掛けてるので当然といえば当然ですが、これはシーケンスを担当しているルーティンの方の問題なのでサウンドエンジンとしてはかなり改善がされたといって良い結果が出ました。

まあスペック表とか資料は面倒臭がらずよく読めということですね。

仕様的には貧弱なLPC向けPWMサウンドエンジンですがネチネチ作っているのは、これまでやってきたから費やした時間がもったいないという貧乏性がメインですが、これに類するものがmbedのwebサイト上に無いからであったら便利な人もいるかな、というのも理由の一つ。
それで、ローカルに置いておいたソースをwebIDEに持って行ってコンパイルしてみたらローカルでは出なかったエラーが?キーッ!!
エラーログを調べてみると、どうもweb上のコンパイラだとint値の計算でfloor命令やsqrt命令を使うとエラーが出るらしい。ARM純正のコンパイラgccだと違うってことでしょうか。sqrt使えないとint値でリングモジュレーションが出来ないからツラい。
しょうがないのでfloorとsqrtを使うルーティンをコメントアウトしてコンパイルしてみたところ本体サイズは約14kでそれほど変わらないですがRAMが0.6kと劇的に小さくなりました。

まだまだ改良の余地はありますがライブラリを公開するのも見えてきたかも。でもリングモジュレーション出来るものを公開したいなあ。