ストリーミング音声を再生してみる
W5100を試用してみる・・・
WIZnet社のTCP/IPハードウェア処理チップ「W5100」を試用してみたくなり、手軽に使えそうなモジュールを購入してみました。
「WIZ811MJ」を購入しようと思っていたのですが売り切れの為、
「Arduino Ethernet Shield」を購入しました。
折角ですので「Arduino Duemilanove」とATMega328も購入してArduinoの開発環境を整えて、サンプルスケッチを書き込んで動作を確認しました。
結果として問題無くクライアント・サーバーの両方が動作しましたがArduinoの環境に馴染めずに終了しました。
結局、開発環境は「AVR Studio」と「WinAVR」を使用することにして、実験回路もArduino互換ではなく、オリジナル回路をブレッドボード上に組みました。
動作電圧は3.3Vのレギュレータが転がっていましたので、3.3Vとします。AVRを16MHzで駆動しますので、今回もオーバークロックで使用します。
これで何をしようか?・・・
とりあえずPINGに応答するサンプルでも作ってみようと思ったのですが、W5100というチップは適当に初期化を行うだけでPINGに応答してしまいます。折角PINGに関するプロトコルまで調べたのにがっかりです。
ならば、一気に飛躍してインターネット上の音声ストリーミングデータ(shoutcast)を受信してVS1053bで再生してみようと思い、回路図と実験プログラムを書き上げました。
VS1053b周辺の回路は、意外と面倒なのですが、前作「nPMP」で、ノイズ対策実験中に製作した「VS1053b/FMラジオ基板」を使用してブレッドボード上の回路を簡素化してます。初の両面基板製作でしたが普通に仕上りました。
基本は、nPMPのVS1053b周辺回路と同じですが、パスコンを省略しないパターンとなっています。
気になるノイズの件ですが、ノートパソコンのライン入力に接続するとSPIクロックに同期してパルス状のノイズが乗りますが、ヘッドホンやコンポの入力に接続すると全くノイズは聞こえません。アンプの入力回路をしっかり作らないと駄目な様です。
「Arduino Ethernet Shield」はSPI接続時、他のデバイスと共存できない様ですので、VS1053bはmega328のusartポートに接続して、SPIモードで制御することにします。
VS1053b/FMラジオ基板(31mm x 50mm)
スルーホール(ハンダで埋まっていますが・・・)はサンハヤトのスルピンキットで作りました。
裏面は数本の信号線とベタGNDとなっています。
そのうちに公開するかもしれません。 新しいバージョンを公開しました。
SPI接続でストリーミングの受信は可能か?
AVRのハードウエアSPIクロックの最高速度は、CPUクロックの半分の速度です。
今回の実験ではAVRの動作クロックは16MHzですので、SPIクロックは8MHzとなります。
8MHzも速度が出せるなら余裕で圧縮音声の再生は行えるだろうと思い、イーサネットシールドから送られてくるデータをそのままVS1053bへ流し込みましたが頻繁に音が途切れてしまいます。
少し考えれば解るのですが、SPI接続でW5100を制御する場合、1バイトのデータを受信する為には常に最低でも4バイトのデータ転送が必要です。
更にW5100内の受信バッファからデータブロックの取出しには、ポインタの読込み(2*4byte)、データの取得(n*4bytes)、ポインタの更新(2*4byte)の手順が必要です。
実質的な受信速度は200Kbps程度と思われます。
我が家のインターネット接続品質では時々データ転送速度が極端に落ち込む事があります。
この2つの原因がVS1053bへ転送が追いつかない現象を引き起こしているのかもしれません。
ストリーミング受信アプリケーションではバッファにデータを溜めておいて、そこからデータをデコードする様になっています。
こうすることで、インターネットからのデータ転送が停止しても暫くの間は再生を続けることができます。
では、この実験でもバッファリングが出来れば音切れが無い再生が可能になるのでしょうか?
大容量のS-RAMがあれば良いのですが、手元にはSDカードしかありません。無謀にもSDカードをバッファリング用のメモリとして使用してみた所、見事に音切れは発生しなくなりました。SDカードの寿命が心配ですが気にしません。
実験中のブレッドボードとコンソール画面です。
かなり適当にコーディングしたソフトウエアusartで通信を実現しています。
地味に、DNSの表示があります。頑張ってDNSへの問い合わせも実現しました。
実験を行いたい方へ・・・
制御方法の詳細説明は省略します。気になる方はプロジェクトファイルを御参照下さい。
実験中のソースの為、非常に汚いコードになっています。(言い訳ですが・・・)
現状では、イーサネットの各種設定(IPアドレス等)は固定です。変更するには、ソース内の設定値を変更して再コンパイルが必要です。
ルーター通してインターネットに接続される事が前提です。チップ自体にはPPPoE接続の機能があるのですが、これでモデムを制御出来るかは今回の実験対象外です。
usartをPCに接続して19200baud/データ長8bit/パリティ無し/ストップビット1で通信ができます。
'?' + 改行を送信すると、怪しげなコマンド一覧が返ってきます。
実験中に気が付いたこと・・・
・8MHz程度のSPIクロックでは、W5100の受信バッファを8Kbytesに設定しないと、音切れの原因となります。複数のソケットを同時にオープン
することが出来なくなります。
・TCPソケットオープン時には、MR_NDビットを有効にしないと速度が出ない為に音切れの原因となります。
・大容量のバッファを持てば良いという訳ではない。128KB程度のバッファサイズで問題ありません。逆に4MBのバッファサイズでは音切れ
の原因となります。(原因解明中)
・VS1053bをストリーミングモードに設定すると再生時に「うねり」を生じます。安定してデータ転送が行えていない様です。通常モードで再生
すると問題は解消されます。
・ソフトウエアSPIで制御を行うと、音切れの原因となる。単純に処理の方法が悪いだけかもしれませんが、ハードウエアSPI制御の方が有利
だと思います。
・TCP/UDPソケットの制御は簡単にできる。その先の各プロトコルのコーディングが難しいかも。
・高速にデータを転送したい場合、SPI接続では厳しい。indirectI/F接続を試してみたいので、「WIZ811MJ」を韓国のショップに発注して
しまいました。送料3000円を高いとみるか安いとみるか?
今後の展開・・・
・DHCPサーバーへアクセスして、IPアドレスを自動で取得する機能の実現
・usart通信ではなくTCPでPCとのコマンドの送受信を行う
・mega128にWIZ811MJをindirectI/Fで接続して実用レベルを目指す(アドレス線が2本だけなのでアドレスラッチ回路は不要?不要です)
・Arduinoの開発環境を習得?挫折
この実験は「インターネットラジオを作る」に続きます。
|