2016年12月30日金曜日
塩漬けになっている「Micro Sound Module」をなんとかしようと思い立つ
試作してから塩漬けになっているMicro Sound Moduleですが、年末年始のちょっとした時間で取り組もうかと考えています。そもそも、塩漬けにしすぎて何をどこまでやったのか忘れてしまった。
元々、アートインスタレーションで使えるような小さなモジュールにしたかったので、仕様から様々なこだわりを切り捨てて作りました。LPC824を選択したのも、「このくらいのマイコンを選べばアレコレやろうとしても欲張れないだろう」という斜め上(下?)の動機があったりします。
ということで、ちょっと成果物を眺めてから色々と取り組んでみようと思います。
元々、アートインスタレーションで使えるような小さなモジュールにしたかったので、仕様から様々なこだわりを切り捨てて作りました。LPC824を選択したのも、「このくらいのマイコンを選べばアレコレやろうとしても欲張れないだろう」という斜め上(下?)の動機があったりします。
ということで、ちょっと成果物を眺めてから色々と取り組んでみようと思います。
ラベル:
LPC824,
Micro Sound Module,
WAV
2016年10月31日月曜日
ちょうど100円玉サイズ!NXP LPC824を使ったとっても小さなWAV File Player「Micro Sound Module」を作りました!
■KiCadへの移行
2016年2月にCADをEAGLEからKiCadに移行する練習を兼ねて、何か実際に作ってみようと考えていました。でも、あまり大きな設計はしたくない。そこで小ピンでも何か面白いことが出来そうなマイコンを使うことを考え、LPC824を使ったとっても小さなWAV Player「Micro Sound Module」を作ることにしました。こちらが完成品。じゃん!EAGLEからKiCadに移行する人の中には、独特なユーザーインターフェースに戸惑いを感じる事もあるようですが、OrCADなどの業務でも使われているCADに馴染みのある人にとっては、逆に自然に移行できるのかも。私の場合、KiCadへの移行に合わせて、回路図、基板、3Dモデルを3画面で同時に見れるようにPC環境を更新しました。これはとても便利。
パッド名やネット名の確認が簡単に出来たり、リアルタイムでルールチェックを行なってくれるところも素敵です。EAGLEの場合には後からデザインルールチェックをかけるわけですが、これを忘れてしまうととんでもない状態で基板を作ってしまう事になります。そういう事は起こらないのが良いなぁと思いました。
私が使ったKiCadのバージョンでは、フットプリント側で配線禁止エリアや配置禁止エリアを指定できず、これはちょっと困ったことになりましたが、この苦しい制限があってもEAGLEには戻れない気持ちになっています。そのうちこの苦しい状況も改善されるでしょうと期待。
■Micro Sound Moduleの企画
マイコンがそもそも小さいのでコンパクトに面白いことができそう、と企画したのがMicro Sound Moduleです。本体のデザインは以下のようなもの。
Micro Sound Moduleプロジェクトの副産物。
某企業さんに行ったプレゼンテーション資料の中で何故か好評だったシリアル通信の説明文・・・。
■ファームウェア
ファームウェアには色々な仕掛けが施されていて、面白いことが出来るので何処かでお見せできるように準備したいなぁと考えています。コマンドの例を挙げると・・・- ディスクコマンド(マウント、アンマウント、情報取得)
- ファイルコマンド(ディレクトリ指定、リスト取得、オープン、クローズ、情報取得)
- トランスポートコマンド(再生、停止、ジャンプ、情報取得)
- マーカーコマンド(設定、解除、ジャンプ、情報取得)
こんな感じでひととおりの制御が可能なコマンドを装備しています。
コマンドパーサーにはNT-Shell (Natural Tiny Shell)を使用する予定でしたが、ROM容量の都合であえなく断念し、新しくコンパクトなパーサーを書きました。そろそろこれも公開したい。
ラベル:
LPC824,
Micro Sound Module,
WAV
2012年4月8日日曜日
WAVファイルを手軽にきちんと扱いたい!
WAVファイルを手軽にきちんと扱いたい!
WAVファイルを手軽にきちんと扱いたくなったので仕様や巷の実装を調べていました。
WAVファイルはチャンク構造になっていて、内部データ表現を自由に選ぶ事ができます。
自由に選ぶ事が出来ると言う事は、それなりにきちんと設計実装したプログラムでなければ正しく扱えない事を意味します。
手元にあった書籍(名前は出しませんが)や巷の実装を見ると、随分と厳しい暗黙の前提条件が用いられていて、色々なWAVファイルをあまり正しく読める事を期待できないなぁという感じでした。
また、データ保持の方式が「スタックにずんっと置く」ような実装だったり、「ファイルサイズに応じて超巨大なメモリをヒープから取る」ような実装だったりと、いくら巨大なメモリがPCに搭載されている昨今とは言え、何だかなぁ~という感じです。
そこで、巷の実装例を少し紹介した後で、設計実装したWAVファイルライブラリを御紹介します。
巷の実装を見てみる
今回設計したライブラリの紹介の前に、巷の実装を見てみましょう。
実装をそのまま掲載する事はできないので、ちょっと修正してあります。
巷の実装例(とある書籍のサンプルコード)
この実装は、出現するチャンク構造の順序に暗黙の前提条件が使用されている例です。
fp = fopen(file_name, "rb");
fread(riff_chunk_ID, 1, 4, fp);
fread(&riff_chunk_size, 4, 1, fp);
fread(riff_form_type, 1, 4, fp);
fread(fmt_chunk_ID, 1, 4, fp);
fread(&fmt_chunk_size, 4, 1, fp);
fread(&fmt_wave_format_type, 2, 1, fp);
fread(&fmt_channel, 2, 1, fp);
fread(&fmt_samples_per_sec, 4, 1, fp);
fread(&fmt_bytes_per_sec, 4, 1, fp);
fread(&fmt_block_size, 2, 1, fp);
fread(&fmt_bits_per_sample, 2, 1, fp);
fread(data_chunk_ID, 1, 4, fp);
fread(&data_chunk_size, 4, 1, fp);
この実装の場合、出現するチャンク構造の順序が異なるだけで全く正しい処理ができません。
そして、この後の処理が以下のようになっています。
pcm->fs = fmt_samples_per_sec;
pcm->bits = fmt_bits_per_sample;
pcm->length = data_chunk_size / 2;
pcm->s = calloc(pcm->length, sizeof(double));
Tiny WAV I/O Moudleプロジェクトとは、小規模組み込みシステムで使用可能なWAVファイルライブラリを作ろうという目的で作られたプロジェクトです。
今回実装したライブラリは、その設計の前段にあたるもので、「どういったインターフェースなら使いやすいかなぁ」というのを検討する為のもの。libcが使用可能な環境でのみ使用可能です。成果物はTiny WAV I/O Moduleプロジェクトのlibc-basedに追加しました。
まぁ、ざっくり言うとlibc-basedは「パソコンで使えるお手軽WAVライブラリ」ですね。
wavfileモジュールの特徴
以下に今回設計実装したお手軽WAVライブラリ、wavfileモジュールの特徴を示します。
どんな風に使えるの?
単にデータを読みたい場合
よくあるやりたい仕事の1つが、とにかくデータを読んでみたい!というものです。
Tiny WAV I/O Moduleのlibc-based実装を使えば簡単に実現できてしまいます。
WavFileResult result;
wavfile_info_t info;
wavfile_data_t data;
WAVFILE *wf = wavfile_open("YourWavFileName.WAV", WavFileModeRead, &result);
if (wf != NULL) {
wavfile_read_info(wf, &info);
while (1) {
wavfile_read_data(wf, &data);
if (data.num_channels == 0) {
// 読むべきデータが無くなったらチャネル数に0を返してくる。
break;
}
// ここでデータを確認すれば良い。
}
wavfile_close(wf);
}
ソースコード
ソースコードは、以下からダウンロード可能です。
http://pt.sourceforge.jp/projects/tinywavio/
ライセンスはMITです。
今後の計画
最近は色々と忙しくて基板設計まで手が回らないので、今年は中途半端に拘るのを諦め、外販されているモジュールを活用してシステム物をやりたいなぁと計画しています。
実は、金子システム株式会社さんからUMB-SSM2603なるものが販売されています。
そうなのです。
このモジュールはACB-BF592と組み合わせてもミニサイズなのです。
動作も高速なので、実は今回のlibc-basedな実装もそのまま動かせたりして?!なんて甘い考えを持っていたりします。ファイルシステム周辺は何らかの抽象化層に乗せようかなぁ。
とにかく組み込み装置としてエレガントにWAVを扱えるようしていこうと考えています。
WAVファイルを手軽にきちんと扱いたくなったので仕様や巷の実装を調べていました。
WAVファイルはチャンク構造になっていて、内部データ表現を自由に選ぶ事ができます。
自由に選ぶ事が出来ると言う事は、それなりにきちんと設計実装したプログラムでなければ正しく扱えない事を意味します。
手元にあった書籍(名前は出しませんが)や巷の実装を見ると、随分と厳しい暗黙の前提条件が用いられていて、色々なWAVファイルをあまり正しく読める事を期待できないなぁという感じでした。
また、データ保持の方式が「スタックにずんっと置く」ような実装だったり、「ファイルサイズに応じて超巨大なメモリをヒープから取る」ような実装だったりと、いくら巨大なメモリがPCに搭載されている昨今とは言え、何だかなぁ~という感じです。
そこで、巷の実装例を少し紹介した後で、設計実装したWAVファイルライブラリを御紹介します。
巷の実装を見てみる
今回設計したライブラリの紹介の前に、巷の実装を見てみましょう。
実装をそのまま掲載する事はできないので、ちょっと修正してあります。
巷の実装例(とある書籍のサンプルコード)
この実装は、出現するチャンク構造の順序に暗黙の前提条件が使用されている例です。
fp = fopen(file_name, "rb");
fread(riff_chunk_ID, 1, 4, fp);
fread(&riff_chunk_size, 4, 1, fp);
fread(riff_form_type, 1, 4, fp);
fread(fmt_chunk_ID, 1, 4, fp);
fread(&fmt_chunk_size, 4, 1, fp);
fread(&fmt_wave_format_type, 2, 1, fp);
fread(&fmt_channel, 2, 1, fp);
fread(&fmt_samples_per_sec, 4, 1, fp);
fread(&fmt_bytes_per_sec, 4, 1, fp);
fread(&fmt_block_size, 2, 1, fp);
fread(&fmt_bits_per_sample, 2, 1, fp);
fread(data_chunk_ID, 1, 4, fp);
fread(&data_chunk_size, 4, 1, fp);
この実装の場合、出現するチャンク構造の順序が異なるだけで全く正しい処理ができません。
そして、この後の処理が以下のようになっています。
pcm->fs = fmt_samples_per_sec;
pcm->bits = fmt_bits_per_sample;
pcm->length = data_chunk_size / 2;
pcm->s = calloc(pcm->length, sizeof(double));
data_chunk_sizeに期待するチャンク構造のチャンク・データ・サイズが格納されているとは限りません。そしてその値をそのまま使ってcallocしているので危ないです。
このコードは落第点です。
でも音を扱うという書籍のサンプル実装です。
この実装の危ない点は、間違っていても処理がどんどん進んでしまう事です。
そして、間違っている場合、何がどう間違っているのか検知していないので、APIの外から見た場合にどうしようもありません。
巷の適当に実装されたコードは意外にこういうのばかりであまり再利用には向いていません。
仮に入門者がこのコードを見て育った時に、「いつこの設計実装レベルから抜け出せるのだろう?」と考えると少し心配になってしまいます。
Tiny WAV I/O Moduleプロジェクト巷の適当に実装されたコードは意外にこういうのばかりであまり再利用には向いていません。
仮に入門者がこのコードを見て育った時に、「いつこの設計実装レベルから抜け出せるのだろう?」と考えると少し心配になってしまいます。
Tiny WAV I/O Moudleプロジェクトとは、小規模組み込みシステムで使用可能なWAVファイルライブラリを作ろうという目的で作られたプロジェクトです。
今回実装したライブラリは、その設計の前段にあたるもので、「どういったインターフェースなら使いやすいかなぁ」というのを検討する為のもの。libcが使用可能な環境でのみ使用可能です。成果物はTiny WAV I/O Moduleプロジェクトのlibc-basedに追加しました。
まぁ、ざっくり言うとlibc-basedは「パソコンで使えるお手軽WAVライブラリ」ですね。
wavfileモジュールの特徴
以下に今回設計実装したお手軽WAVライブラリ、wavfileモジュールの特徴を示します。
- 省メモリ設計。(ライブラリ側では巨大なメモリを要求しない。)
- ファイル形式に依らず0.0から1.0で正規化されたデータ入出力インターフェースを採用。
- 複数チャネルデータに対応。
- ヘッダの実装詳細を把握しなくても使える。
データをどこに配置するのかについてはアプリケーション層が決めたい事の一つです。
巨大なメモリを勝手にアロケーションするようなライブラリは使いづらくて仕方ありません。
よってwavfileモジュールでは、これらに関知しないようにインターフェースを設計しました。
また、WAVファイルの処理を実装する時に意外に面倒なのが、データ形式の違いです。
今回のwavfileモジュールでは、ファイルのデータ形式によらず0.0から1.0で正規化されたデータ入出力インターフェースを採用しました。これによって、「8ビット形式のファイルは0から255で1バイトだよね。」とか「16ビット形式のファイルは-32768から32767で2バイトだよね。」とか考えなくて済みます。とにかくサンプルを1つ得るインターフェースを呼ぶだけで良いのです。
typedef struct {
uint16_t num_channels;
double channel_data[WAVFILE_MAXIMUM_CHANNELS];
} wavfile_data_t;
wavfile_read_dataを呼ぶと上記の構造体にサンプルデータが格納されて返ってきます。
channel_dataの中身は先の規格化された値が入っている事になります。
wavfileモジュールのインターフェース
wavfileモジュールを使うために必要なインターフェースは、リード用、ライト用と合わせてもたったの6つです。
WAVFILE *wavfile_open(const char *filename, WavFileMode mode, WavFileResult *result);
WavFileResult wavfile_read_info(WAVFILE *p, wavfile_info_t *info);
WavFileResult wavfile_read_data(WAVFILE *p, wavfile_data_t *data);
WavFileResult wavfile_write_info(WAVFILE *p, const wavfile_info_t *info);
WavFileResult wavfile_write_data(WAVFILE *p, const wavfile_data_t *data);
WavFileResult wavfile_close(WAVFILE *p);
基本思想
infoとdataの2段階で簡単に実現しちゃうよ!というのが本ライブラリの基本思想です。
読み込み
- wavfile_openにファイル名とWavFileModeReadを与えてオープン。
- wavfile_read_infoでヘッダ情報を読み込む。
- wavfile_read_dataでデータを読み込む。 (必要に応じて繰り返す)
- wavfile_closeでクローズ。
書き込み
- wavfile_openにファイル名とWavFileModeWriteを与えてオープン。
- ヘッダ情報を設定する。
- wavfile_write_infoでヘッダ情報を書き込む。
- データを設定する。
- wavfile_write_dataでデータを書き込む。(必要に応じて繰り返す)
- wavfile_closeでクローズ。
単にデータを読みたい場合
よくあるやりたい仕事の1つが、とにかくデータを読んでみたい!というものです。
Tiny WAV I/O Moduleのlibc-based実装を使えば簡単に実現できてしまいます。
WavFileResult result;
wavfile_info_t info;
wavfile_data_t data;
WAVFILE *wf = wavfile_open("YourWavFileName.WAV", WavFileModeRead, &result);
if (wf != NULL) {
wavfile_read_info(wf, &info);
while (1) {
wavfile_read_data(wf, &data);
if (data.num_channels == 0) {
// 読むべきデータが無くなったらチャネル数に0を返してくる。
break;
}
// ここでデータを確認すれば良い。
}
wavfile_close(wf);
}
ソースコード
ソースコードは、以下からダウンロード可能です。
http://pt.sourceforge.jp/projects/tinywavio/
ライセンスはMITです。
今後の計画
最近は色々と忙しくて基板設計まで手が回らないので、今年は中途半端に拘るのを諦め、外販されているモジュールを活用してシステム物をやりたいなぁと計画しています。
実は、金子システム株式会社さんからUMB-SSM2603なるものが販売されています。
そうなのです。
このモジュールはACB-BF592と組み合わせてもミニサイズなのです。
動作も高速なので、実は今回のlibc-basedな実装もそのまま動かせたりして?!なんて甘い考えを持っていたりします。ファイルシステム周辺は何らかの抽象化層に乗せようかなぁ。
とにかく組み込み装置としてエレガントにWAVを扱えるようしていこうと考えています。
ラベル:
ACB-BF592,
UMB-SSM2603,
WAV
登録:
コメント (Atom)