« やっぱり画像と音響が面白い | トップページ | 非圧縮オーディオはやっぱりAVR単独では無理か »

2008年12月28日 (日)

SDカードPCMプレーヤーの開発

非圧縮オーディオの再生はやはり難しい(12/23/08)
 色々迷ったが、直近の次のプロジェクトは16ビットDACを使ったデジタルオーディオに決めた。折角DACチップを買ったのだ。動かしてやりたい。他は別の用途にも使える。ターゲットマシンを何にするかも迷ったが、結局やはり使い慣れたAVRにすることにする。Pict0854

 というのは、H8/3069Fの現在のMMCインタフェースのSPIは高速と言ってもデータシートを見ると最大速度が250khzしかない。GPIOで手作りすればもっと早く出来るのだろうが、このままではAVRのCPUクロックの1/2のSPI(最大10Mhz)に比べれば見劣りがする。ARMプロセッサーのSTARMはSDカードを、買ってすぐにつけたが、こいつは当初より映像処理を目的にしているうえ、開発環境がまだ整っていないのですぐには立ち上がれない。で、必然的にAVRに落ち着いた。

 ファイルからWAVデータを読んでDACチップに投げるだけのプログラムである。始めは軽く考えていたが、サンプリング周波数44.1khz、データサイズ16ビットステレオという非圧縮のオーディオストリームは、シリアルで流れるとすると1.4Mbpsの速さである。MP3のビットレート192kbpsとか256kbpsという速さに比べると桁違いに大きい。下手をするとファイルを読む早さが間に合わないかもしれない。あわててSDカードのアクセス速度を確かめる。

 がた老AVR研のこれまでの実測データは、クロック8MhzのMega168で、読み込みが200KB/秒だ(バッファーサイズ128バイト)。オリジナルのchaNさんのレポートでは、9MhzのMega64でバッファーサイズが2048バイトだと300KB/秒近辺である。PCMオーディオの1.4Mbpsをバイトに直すと176KB/秒。うーむ、微妙なところである。余裕がありそうに見えるが、今度はファイルを読むだけでなくDACチップにデータを送るオーバーヘッドがある。SRAMの小さいMega168ではバッファーを大きく取れず難しいかもしれない。

 しかも、サンプリング間隔は、44.1khzだから22(正確には22.67)μsしかない。こんな短い時間で一回のファイルアクセスを完了することはSDカードでは不可能だ。処理は必然的にこの間隔を越えて動かなければならないが、もし、ファイルシステムがタイムディペンダントな部分を含んでいれば、CPUチップだけで再生しようというこの計画は即、破綻である。

 ソースコードを念入りに調べる。いやいやソースコードがあると言うのは有難いことである。調べた結果、データの送受はすべて1バイトづつSPIのデータレジスタを経由しており、データの読みこみ、書き込みのチェックはループで待っていることがわかった。AVRのSPIは独立したハードウエアであり、途中で割り込みがかかって処理が中断しても、アクセスが遅れるだけでおかしくなることはない。良かった。良かった。これで基本的な問題はクリアした。CPLDやFPGAを持ち出さなくて済む(ということで中々使う機会がない)。

 次の問題は、先ほどのDACへの書き出し処理のオーバーヘッドを含んだSDカードアクセスがはたしてPCMビットレートを上回るかと言う問題である。平均で遅いのは話にならないが、平均より早くてもバッファーサイズによっては途中で音が途切れる危険がある。こればかりはやってみるしかないが、せめて全体の目安くらいはつけておきたい。DACチップ(BU9480F)のデータシートをさらに読み込む。Bu9480f

 すると、このチップは、サンプリング間隔の中間でLとRを切り替え、それぞれ16ビットづつ送れば、中間を前後の平均をとった値で出力することがわかった。いわゆるオーバーサンプリングである。音質が良くなるのは良いが、送出するほうはさらに大変になる。間隔は22μsの半分の11μs(正確には、11.3μs)になる。そのたびに16ビットづつ送ってやらなければいけない。

 残る課題は、DACへのデータ送出を何でやるかという話である。AVRのSPIはひとつしかないので、ここに使うわけには行かない。それにAVRのSPIは8ビットで、16ビットを一気に送るようなしゃれたしかけはないので、オーバーヘッドを縮める時間稼ぎもできない。GPIO(普通のIOピン)で、クロックを自分で作りデータを送る方法に自然に決まった。

 BU9480Fが動く最も早いクロック(BCLK)は、60ns、16.6Mhzであり、この速さでデータを送れば、オーバーヘッドが減らせてSDカードアクセスに余裕ができるが、AVRがGPIOで出せる最高周波数はCPUクロックの1/2なので、最大クロックは10Mhzとなる。この速さでDACの16ビット送出にかかる時間は1.6μsで、サンプリング間隔との差、11.3 ‐1.6 = 9.7μsが、SDカードアクセスにかけられる時間となる。このあいだに2バイト(16ビット)が読めればバッファーアンダーランになることはないという理屈だ。

 データアクセス速度に換算すると、206KB/sec以上であれば、継続的な再生が可能なことになる。しかし、1.6μsはAVRのクロックから換算した上限値で、前後のLRCKなどのスイッチを考慮すると、2~3μsはかかるだろう。そうだとすると必要なアクセス速度は、215~240KB/sec以上ということになる。

 感触としては何とか出来そうな感じである。詳細設計に入ることにした。AVRの種類は迷ったがまずMega128で全体の動作を確認し、うまくいけばMega168にデグレードして、最終的には電池駆動のSDカードPCMプレーヤーにすることにする。

Mega168でも動きそうだ(12/27/08)
 実装手順としては、次の順番で実験を進めていくことにした。

(1)まず、DACの処理オーバーヘッドを入れたSDカードアクセスプログラムを組み、速度が所定の条件を満たしているか確認する。

(2)そのあとDACの部分をコーディングして動作を確かめる。最初のステップでは、UARTでファイル選択、再生開始、終了の処理を制御する。

(3)その後、LCDでのロジックを考える。

(4)アナログ出力は最初、オシロで観測するだけとし、そのあとオペアンプ、LPF等を追加して最終的にはヘッドフォンをドライブする。

 問題のWAVフォーマットはウェブで簡単に手に入れることが出来た。ハードウエアは、既にブレッドボードにMega128のSDカードシステムが動いているので、当面これを活用してテストを進めていくことにする。851brews128

 (1)のステップである。これまでの実測がMega168だけだったので、Mega128でもベンチマークをとった。chaNさんのFatFSにはサンプルプログラムがついており、その中には、ファイルのアクセス時間を表示してくれるfr,fwというコマンドが用意されている。ただ、このコマンドの時間単位が10msなので、短いレコードの計測では誤差がでるため、これを1msに縮めてより正確にデータが測れるようにした。

 ブレッドボードのMega128のバッファーサイズは2Kバイト(2048)ある。chaNさんのクロックが9.2Mhzだが、こちらは8Mhzである。結果はクロックの違いを正直に反映して、わずかに遅くなったが、それでも300KB/秒近辺に納まった。次に、クロックを16Mhzに上げる。SDカードとのアクセスも倍になる。アクセス速度は期待通り、倍にはならないが倍近い550KB/秒にはねあがった。しかし、残念なことに読めないメディアがでてきた(パナソニック128MBのミニSDカード)。

 まあ、2GBのマイクロSDが読めるのでこの問題は先送りして次に進む。バッファーサイズを256バイトに縮める。これはCPUをMega168に落としたときに使えるかどうかのテストである。アクセス速度は当然下がったが、330~360KB/秒と十分な速さである。素晴らしい。面白いことに16MBのメディアの方が、2GBのメディアよりわずかだが早い(chaNさんのレポートと同じ)。

 次はいよいよDACの割込みを考慮したときのアクセス速度の測定である。タイマーのひとつTIMER0を使って何もしない割込みルーチンをつくる。11μs単位に割込みがかかり、その度に2μsループしてから帰るルーチンである。動作確認のためにモニターコマンドを追加して、割込みマスクをON/OFFできるようにする。

 動かしてみる。おや、アクセス速度は殆ど変わらない。勿論、割込みが入るほうが遅くなるが思ったほど遅くならないのだ。メディアを替えたり、データ量を変えるとわずかに変化するが、それでも1~2%しか低下しない。何故だろう。チャートを描いてみてその理由がわかった。300KB/秒というのは、等間隔で1バイトづつ読むとしてその間隔は3.3μsである。 SPIはデータレジスタをCPUが読むとフラグが立ち、次のデータが来るまでフラグは変わらない。CPUはこのフラグが変わるのをひたすらループして待っている。遅くならないのは、待ち時間に比べてCPUの処理時間が少なく、2μsのDACのオーバーヘッドの殆どがこの中に吸収されてしまうからだと考えられる。Dac

 これで、SDカードによるPCMオーディオプレーヤーの基本的な問題はすべて片付いた。Mega168を16Mhzで動かせば、バッファーサイズが256バイトでも、かなり余裕を持ってPCM44.1khz ステレオ16ビットのオーディオデータをデコードすることができそうである。FatFSもR/Oにすればフラッシュサイズは8KB以下に納まる(LEDマトリックスのときに確認)。コーディングが楽しみになってきた。

 ソフトの構造はそんなに難しくない。ファイルのアクセス単位が大きいので、リングバッファーではなく、ダブルバッファーにして、DACの読み出しが別のブロックにあるときのみ、そこへデータを読み込むようにする。最初は、DACを止めておき、データが半分貯まった(2番目のブロックを読み始めた)とき、割込みマスクをはずしてデコードを開始する。このあとはDACのデコードとファイル読み込みとの競争になる。

 そろそろ、演奏の中断(途中から再開)、中止、曲の選定などの操作仕様を考える段階に来た。このあたりは最初のうちから考えておかないとソフトの構造が汚くなる。携帯機器にしたときのLCDの画面仕様も課題だ。手持ちの2行LCDで曲リストなどを出せるだろうか。Mega168なのでフラッシュメモリは限られている。なかなか難しそうだ。でも、それだから楽しいとも言える。

|

« やっぱり画像と音響が面白い | トップページ | 非圧縮オーディオはやっぱりAVR単独では無理か »

AVR」カテゴリの記事

コメント

がた老さん
ありがとうございます。
発見いたしました。

投稿: 三宅 | 2014年10月 8日 (水) 19時52分

もう見つけられたかもしれませんが、当ブログの後半の記事で公開しています。
当ブログの *ウェブページの「記事一覧」のタグから94番目の記事のものが最新だと思います。
ただ、Mega168ではSRAMが少なすぎてMega328が必要です。

投稿: がた老 | 2014年10月 8日 (水) 11時52分

初めまして、三宅と申します。現在、大学院の学生をしています。趣味でatmegaを使いwavの再生ガジェットを作ってみようと思い立ち、検索した所、こちらにたどり着いた次第です。当方も168を使い開発しようとしていましたので、こちらのページでがた老さんが作成されていたガジェットはまさにドストライクでした。突然で不躾かもしれませんが、宜しければ、参考までにソースコードを拝見させていただく事は可能でしょうか?

投稿: 三宅 | 2014年10月 7日 (火) 16時29分

ははあ。困ったな。商売をするつもりがないもので、申し訳ありませんが、ご要望にはこたえられません。悪しからずご了承ください。
仕様ですが、お年寄り相手なら、トラックも何も考えず、8枚のSDカードを差し替えるだけで良いような気がしますが。その日の広報のSDカードを差して出かければ誤作動なし。機械はひたすら繰り返し再生するだけ。私のソースコードでどなたかお作りになりませんかね。LCDも何も要らない。電源スイッチとスタートボタンだけ。SDカードだからテープの磨り減り一切心配なし。
ただ問題は録音ですね。PCででも録音してSDカードにWAVファイルとして移せる技術を持った人が身近におられるかどうか。

投稿: がた老 | 2009年5月22日 (金) 20時08分

ちゃちゃ、入れます。m(__)m

気になるところ

(1)アナウンスの音声ファイル形式はどうするか(PCMかMP3かそれ以外か)

(2)インターバルは音声ファイルに無音としていれるのかプレーヤーが行うのか。(無音とした方が分かりやすく汎用性が高いかな)

(3)エンストなどによる電源OFFを想定すると再生トラックは記憶した方が良さそう。
 ただ、そうするとシガーライターに入れたときの「0」トラックの再生が不可能になる。

ちょっと気になったのはそんなところです。

投稿: そら。 | 2009年5月22日 (金) 15時34分

 初めまして 土井と申します 下記の様な 「SDプレーヤ」を作って頂きたいのです ぜひお願いします

 現在:用途=連合町内会の広報活動 消防団の       防災活動
    機材=市販のカセット付き車載アンプで       30秒のエンドレステープ(アナ       ウンス15秒インターバル15秒       )を8種使用
    改善の必要=テープが壊れやすく何度も          作り直してます 高齢者が          多くワンタッチの物が欲し          いのです   
 希望のSD仕様:
    システム=「カマデンTAA4100」に組         み込み
    電源=カーバッテリー12V
    再生=選択されたトラックを繰り返し再       生
    トラック送り=押しボタン(広報は1日           1種なので誤作動防止の           凹型)を押すと次トラッ           ク
    トラック表示=デジタル表示板(15㎜           ×10㎜)全員老眼なの           で
    動作=シガーライターにプラグを入れて       「0」を表示し最初のトラックを       繰り返し再生

     
      表示板  送りボタン
       ┃┃  ┃┃
      ┏━━━━━━┓
      ┃      ┃
      ┃SD ┃
      ┃プレーヤー ┃
      ┃      ┃
      ┗━━━━━━┛
       ┃┃  ┃┃
      アンプ  電源
       
 こんな感じなのですが 宜しくお願いします
[email protected]
 

投稿: 株式会社土井不動産 代表 土井禮二郎 | 2009年5月22日 (金) 14時47分

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック


この記事へのトラックバック一覧です: SDカードPCMプレーヤーの開発:

« やっぱり画像と音響が面白い | トップページ | 非圧縮オーディオはやっぱりAVR単独では無理か »