前回試作したDPCMをRice Golomb符号化するアルゴリズムですが、mbedに実装してみました。gcc向けソースではデコード結果をバイナリデータとしてファイル出力してますが、mbedではその部分をDAC出力すれば言い訳です。なので簡単……でもなかった*1。mbedのハードを理解しないで飛び込んできたので。ええ。笑
■ PC用エン・デコーダのソースはこちらからDLをお願い致します。(要コンパイル)
コンパイル方法はUnix系のターミナルから
$ gcc rice_golomb.c -o rice_golomb
とするだけです。詳細は前回の記事を参照。
■ mbed用デコーダはこちらからDL出来ます。(要ログイン)
飽くまで試験的な実装ですので次のような制約(決め打ち)をしております
- mbedはデコード再生のみ(エンコード録音機能の搭載は後日)
- エンコードフォーマットは16bit,stereo,サンプリング周波数22.050kHz,オリジナルDPCM/Rice Golomb圧縮
- 再生するデータのファイル名はtest.rgm
- 音声出力はLPC1768内蔵10bitDAC、片チャネルのみ
- 基本ビット長定数kは0x0b固定
動けばいいや精神でソースを突っ込みました。追って改良して行きますのでどうぞお付き合い下さい。
大まかな下準備です
- mbedにこちらのデコーダをDLする
- iTunesなどでリニアPCM(*.wav)ファイルを用意(16bit,stereo,22.050kHzに設定)
- test.wavにリネームしてエンコーダと同一フォルダにコピー
- エンコード
- SD/SDHCにtest.rgmをコピー(ピンアサインは各自お気に入りの箇所を使ってください.日本製mbed向けボードStarBoardをご使用の方は要注意)
- SD挿入後mbedリセット→DAC出力ピン(p18)より再生
◇デコーダの要となる部分の説明です。
// (main.cppの127行目) tick.attach_us(&dac_out, 45); //set 22.050kHz sampling data
ARMコアにSysTickで22.050kHz(≒45usec) 毎に例外を発生させ、DAC制御ルーチン「dac_out」へ分岐させています。しかしSystickのコードに関してコンパイラがどのような処理をしているか解りかねますが、mbed.hにバグがあるようです。この問題は早急に解決されると思われますが、2010年8月18日現在は解決していないのでmbed.hのリビジョンをupdateしないでください。全く動作しなくなります。(8月26日mbed.h rev25リリースにて修正されました)
◇デコードルーチンの抜粋です
// (main.cppの72行目) DAC_fifo[DAC_wptr]=dac_data; DAC_wptr=(DAC_wptr+1) & 0x3ff; DAC_diff=(DAC_diff+1); while (DAC_diff >= 1023){ led1 = 1; } //wait led1=0; if(DAC_diff <= 0)led2=1; else led2=0;
通常処理ルーチンでは2kByteのバッファにひたすらデコード済みデータを記録しています。RAMが満タンの場合はmbedのLED1を点灯させ、バッファがDACにより消費されるのを待ちます。変数「DAC_diff」でエンコードデータ数とDACが消費したデータ数の差分を記録しています。またエンコードが追いつかず、バッファにデータが無い場合はmbedのLED2を点灯させながらエンコード作業を行います。
◇DACの制御ルーチン
// (main.cppの106行目) void dac_out() { if (DAC_diff > 0) { led2 = 0; DACout.write_u16(DAC_fifo[DAC_rptr]); DAC_rptr=(DAC_rptr+1) & 0x3ff; DAC_diff--; }else led2 = 1; }
バッファデータが枯渇した場合(DAC_diff=0)はDACにデータを渡さないようになっています。ここでも枯渇した際にはLED2を点灯させる指示を出しています。
◇まとめ
22.050kHz音声データのデコード動作確認ができました。やや雑音まじりなのでこれがプログラムミスなのかDACの特性なのかを確認する必要があります。
◇今後
CD音質と同等の44.1kHzでの動作を確認する必要があります。
さらにmbed(LPC1768)がI2Sに対応しているのでI2S対応のDACを入手しステレオ動作を確認しようと思います。
また、簡易DATの製作が当初の目的なので、リアルタイムエンコードにも挑戦します。
加えて、LPC1343などのCPUに移植する際バッファを削減する必要がありますので、そちらも試行したいと思います。