というわけではないんですが。
少し真面目にYoutubeをやってみようと思ったので少し整備してみました。
雑多に動画が上がっていますが、技術系のものはこんな感じです
”チャンネル登録と高評価ボタンお願いします”
というわけではないんですが。
少し真面目にYoutubeをやってみようと思ったので少し整備してみました。
雑多に動画が上がっていますが、技術系のものはこんな感じです
”チャンネル登録と高評価ボタンお願いします”
前回の記事からの続きです。
前回までで、RaspberryPiに接続して音源カードのメモリを読み書きするハードウェアの準備ができました。
これから、そこに書き込むためのメモリのファイルを準備します。
USBメモリや高機能なマイコンを搭載した機器、例えばmp3プレイヤーなどの場合、
Windowsなどで"ファイルシステム"、例えばFATなどでフォーマットし、
ファイル名を持ったファイルがおかれることが多いですが、
このような機器の場合、フラッシュメモリ内の領域に、ファイルシステムのない領域が広がっているだけ、ということが多いです。
初回のところで吸い出しのために構造体を作って確認していましたが、
書き込むとなるとさらにファイル構造の厳密な検定を行う必要があります。
なぜなら、我々はある仕様に従って作成されたファイルを持っているだけで、
このファイルがどういう仕様で作成されたか、ということを知ることができないため、
意味のあるデータのほかに、「不明」や「マジックナンバー」そして、「マジックナンバーとして扱う」と推測する、などといった部分が多く発生します。
そういった部分は、自分がこの機器を作るのであれば、どのようなデータ構造にするべきか、などといったことをよく考えながら検証する必要があります。
わからない部分は、「マジックナンバーとして固定」し、それでうまくいけば良し、とするしかないのです。
では、改めてファイル構造についてチェックしていきましょう。
デフォルトのカードから吸い出したメモリの先頭部分です。
このバイナリダンプを見ながら、どんな情報が埋まっているか考えていきます。
数値として意味を持つのは2バイトおよび4バイトからが多いので、そのぐらいのブロックに分けて読んでいきます。
ファイルの先頭に多いのは、そのファイルがなんであるかを表す文字が埋め込まれていることが多いです。例えば、ビットマップファイルなら"BM"、JPEGファイルなら"JFIF"などです。しかし、ここにはありません。
ただし、AA,55というバイト列は、ネットワーク通信やファイルシステムなどでは時々使われることがあります。0xAAは2進数にすると"10101010"、0x55は"01010101"と、それぞれビットパターンが交互に現れ、また、この2バイトをxorすると"0"になることから、同期信号や高速に通信経路のエラーが無いことを検出したりすることに使用できるからです。このことから、この先頭は、データ確認のためのマジックナンバーであると「仮置き」しておきます。続いての4バイトから、16バイト目まで。
なんとなく意味はありそうですが、この時点では不明ですのでやはり「仮置き」して次に行きます。
17バイト目からの4バイト"00 04 00 00”、また、その次の4バイトは"00 C4 15 00"はそれぞれリトルエンディアンで読むと"0x400","0x15C400"になります。何か意味がありそうですので、このアドレスにジャンプしてみましょう。
特徴的なデータ列が現れました。0x15C400も見てみると
こちらも同じ感じです。先頭はさっきとよく似た「55 AA 01 00」で始まります。
さて、ここでこの機器の仕様を思い出します。この機器は、チャンネル切り替えスイッチで2曲のうちどちらかを選んで再生するのです。
このアドレス二つに書かれたデータを曲として読み込んで再生する、という動作のために作られた、と矛盾なく推測できると思います。
ここで、なんとなく全体の構造を見ると
・先頭1kB→データ全体のヘッダ。曲情報1、曲情報2へのアドレステーブル
・曲情報1ヘッダ
・曲情報2ヘッダ
までがわかりました。
では、曲情報ヘッダを改めて見ます。2つを見比べるのがいいです。
先頭8バイト、4バイトのマジックナンバーに続き00 80 FF FF 。意味がありそうですが、二つとも同じ値ですのでとりあえず共通のマジックナンバーとしておきます。
1曲目は"00 80 00 00"(0x800) 、"FF BF 15 00"(0x15BFFF)が、
2曲目は"00 C8 15 00"(0x15C800)、"FF 57 27 FF"(0x2757FF)が意味のある数字として読み取れます。それぞれ、
FFが終わり実データが始まる部分、そして終わる部分であることがわかります。
つまり、このヘッダには曲の実データの最初のアドレスと最後のアドレスが書かれている、ということが確認できました。
今回はかなり簡単なデータ構造であったため(そもそも搭載しているマイコンにあまり複雑なことができないレベルのため、これ以上の情報も必要とされていません)、割と簡単に解析できました。本当に重要な、例えば課金情報などが保存されるようなストレージであれば、読み出せない領域があったり、それを使って暗号化されたりしている場合がありますが、そのようなことは無いようです。
さて、この情報をもとに、曲データを切り出します。
最初の検証の時点では、手作業で切り出しましたが、今後差し替えを行いますので
そのルーチンと組み合わせてテストに使用しますので、プログラムを書いていきます。
構造体のままのベタファイル入出力があるので、C++で書きたいところですが、
プロトタイピングとしてはやはりC#の駆け足が捨てきれませんので、C#で書き始めます。
解凍ルーチンはたったこれだけです。C#とGenericsすごいですね。
public void Unpack(string s)
{
byte bs = System.IO.File.ReadAllBytes(s);
UInt32 off1 = System.BitConverter.ToUInt32(bs.Skip(16).Take(4).ToArray());
UInt32 off2 = System.BitConverter.ToUInt32(bs.Skip(20).Take(4).ToArray());
byte song1 = bs.Skip*1.ToArray();
byte song2 = bs.Skip((int)off2).ToArray();
UInt32 start1 = System.BitConverter.ToUInt32(song1.Skip(8).Take(4).ToArray());
UInt32 stop1 = System.BitConverter.ToUInt32(song1.Skip(12).Take(4).ToArray());
song1 = song1.Skip(0x400).Take((int)(stop1 - start1 + 1)).ToArray();
UInt32 start2 = System.BitConverter.ToUInt32(song2.Skip(8).Take(4).ToArray());
UInt32 stop2 = System.BitConverter.ToUInt32(song2.Skip(12).Take(4).ToArray());
song2 = song2.Skip(0x400).Take((int)(stop2 - start2 + 1)).ToArray();
System.IO.File.WriteAllBytes(s + ".1.songblock", song1);
System.IO.File.WriteAllBytes(s + ".2.songblock", song2);
}
これで、吸い出したイメージから曲が2曲抽出できました。
改めて、この吸い出した曲のフォーマットを確認します。
前の記事でで、ADPCMっぽいということはわかっていましたが、Goldwaveで開いた波形を見るとちょっと変です。
先頭、約0.5秒は無音区間のはずですが、なぜか少しずつDC成分が詰みあがっていっています。ADPCMは初期データとその変化量を記録している方式ですが、実はいくつもの方式が開発されていて、それらは変化量などのテーブルが少しづつ違っているのです。おそらく、なんとなく音声としては再現されていますが、そのテーブルの違いのため正しいデータが再現されていません。これは困りました。
ADPCMを扱えるいろいろなツールを使い、正しくデコードできる形式を探していきます。
最終的に、Linuxで動作する"sox"というツールに、以下のようなコマンドラインを渡すと、どうやら正しいwaveファイルに変換できる、ということにたどり着きました。
sox -t ima -r 44100 -e oki-adpcm infile.bin outfile.wav
このコマンドで変換したファイルを開くと…
先頭の無音部分がきれいにフラットになり、曲全体のダイナミックレンジも問題なさそうです。
つまり、WAVEファイルをもとにこの逆変換を行い、Flashに書き込めば、きちんと再生できそう、という確信ができました。
逆変換のコマンドは、
になります。これで得られたファイルを書き込むためのルーチンを書いていきます。
public void Pack(string outfile)
{
try
{if(!System.BitConverter.IsLittleEndian)
{
throw new Exception("Environment exception(Endian)");
}
byte ch1 = System.IO.File.ReadAllBytes(textBoxSong1.Text);
byte ch2 = System.IO.File.ReadAllBytes(textBoxSong2.Text);
byte chs = new byte { ch1, ch2 };
System.IO.MemoryStream ms_gheader = new System.IO.MemoryStream();
ms_gheader.Write(new byte {
0xaa,0x55,0x01,0x00,
0x00,0x01,0x64,0x00,
0x00,0x00,0x00,0x00,
0x01,0x00,0x02,0x00
});
int arignment = 1024;
int ch1_length = (ch1.Length%arignment==0)?ch1.Length:*2;
ms_gheader.Write(System.BitConverter.GetBytes*3;ms_gheader.Write(pad);
for (int x = 0; x < 0x400-80; x++)
{
ms_gheader.WriteByte(0x00);
}
System.IO.MemoryStream song = new System.IO.MemoryStream();
for (int n = 0; n < 2; n++)
{
song.Write(songheaders[n].magic);
song.Write(songheaders[n].reserverd);
song.Write(System.BitConverter.GetBytes*4;
song.Write(System.BitConverter.GetBytes*5;for(int x = 0; x < 0x400 - 16; x++)
{
song.WriteByte(0xff);
}song.Write(chs[n]);
for(int p = 0; p < ch_padded_length[n] - chs[n].Length; p++)
{
song.WriteByte(0x80);
}
for (int x = 0; x < 0x400; x++)
{
song.WriteByte(0xff);
}
}ms_gheader.Write(song.ToArray());
while (ms_gheader.Length<1024*1024*4)
{
ms_gheader.WriteByte(0xff);
}
System.IO.File.WriteAllBytes(outfile, ms_gheader.ToArray());}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
こんな感じになります。
勢い重視コーディングのため、もっとちゃんとすればわかりやすくなると思いますが、めんどくさいのでこれからもたぶんこのままです。
先ほど推測したヘッダ情報を作成するほかに、おそらく必要であると思われる1kb単位へのデータの切り上げ、パディングなど、元のフォーマットと同じになるように細かな調整を行っています。なぜなら、仕様書が無いため、元のフォーマットとどれだけ変えてもきちんと通るかはまったくわからないからです。
Unpackで取り出した2曲をPack関数に入れ、元のファイルと全く同じファイルが出来上がることが確認できました。
さぁ、実際に入れる曲を作ります。
息子の希望は「ドン・キホーテの曲」。
曲名は「ミラクルショッピング」です。お店にCDが売っているらしいですよ。
ねぇ、知ってる…?(◎ё◎)ドンドンドン、ドン・キ~♪お店にいつも流れているこの曲は「ミラクルショッピング」ドンキのテーマソングなのダ。なんとドンキのCDコーナーで販売中♪ドンドンドン~(´・ё・`) pic.twitter.com/7cwlD2jJ
— 驚安の殿堂 ドン・キホーテ🐧 (@donki_donki) February 25, 2012
ドン・キホーテの曲を歌っている方本人出演のPVがありますので、今まで見たことない方はぜひ見てくださいねw
Youtubeで検索してmp3に変換して、もともとの音源カードと同じ範囲を切り出します。
切り出せたら先ほどのsoxコマンドで変換します。
チャンネル2には、いつものポポーポポポポを入れる、とことです。
自作プログラムにセットして「Pack」すると、4MBのバイナリファイルが出来上がります。
これを、前の記事でセットアップしたraspberry piに転送し、flashromコマンドで書き込むと…
エンコードパラメータ調整してボリュームバランス取れた pic.twitter.com/oWoxPCg4qF
— ひろみつ (@bakueikozo) December 8, 2022
できた!できたよ!ドン・キホーテの音源カードだよ!!!!
と息子に持っていくと…反応薄いなw
むしろ、作るって言ってから何日かかったんだよっていう顔してるけどww
とはいえ、できたからにはさんざん遊んでくれているようです。
今日も朝から呼び込み君自宅ガチ勢 pic.twitter.com/8PgqanUM6U
— ひろみつ (@bakueikozo) December 7, 2022
作っているところ、時々脇で見てましたので、メルカリで2600円で買ったものをほいって与えるよりは何か、与えられるものがあったとは思っています。
毎日うるせぇなあwwwwwwww
さて、とりあえず一つできましたが、例の謎の呼び込み君マニアのLINEグループからはこれをサッサとよこせとさんざん言われているため、もう少し手離れのいい形にしなければなりません。現状、PCとRaspberryPi,そして空中配線の書き込みスロットでは、ぶっちゃけ小中学生の取り扱いでは寿命は数時間でしょうw
せめて書き込み機はUSB-SPIかなんかでまとめて、PC単体で書けるぐらいにしておきたいなぁ。
*1:int)off1).Take((int)(off2-off1
*2:ch1.Length + arignment - 1) / arignment * arignment);
int ch2_length = (ch2.Length % arignment == 0) ? ch2.Length : ((ch2.Length + arignment -1 ) / arignment * arignment);
int ch_padded_length = { ch1_length, ch2_length };
int offsetof_ch1 = 0x400;
int offsetof_ch2 = 0x400 /* footer padding */ + 0x400 /* global header */ + (ch1_length + 0x400);
songheader songheaders = new songheader[2];
songheaders[0] = new songheader();
songheaders[0].start =(UInt32) offsetof_ch1+0x400;
songheaders[0].stop = (UInt32)(songheaders[0].start + ch_padded_length[0] -1);
songheaders[1] = new songheader();
songheaders[1].start = (UInt32)offsetof_ch2+0x400;
songheaders[1].stop = (UInt32)(songheaders[1].start + ch_padded_length[1] - 1);
byte[] pad = new byte[16 * 3 + 8];
Array.Fill<byte>(pad, 0xff);
ms_gheader.Write(System.BitConverter.GetBytes((int)offsetof_ch1
*3:int)offsetof_ch2
*4:int)songheaders[n].start
*5:int)songheaders[n].stop
前回の記事、思ったよりたくさんの人に読んでもらい、面白いと言ってもらったので
調子に乗ってどんどん書いていきます。
↓いただいてる はてブコメント
前回まででカードからの読み込みと、内部フォーマットの大体の解析ができました。
改めて要求仕様を確認すると
息子「ドン・キホーテの音源カードが欲しい」
ということです。
これを目指すために、純正の音源カードの中身を書き換えることを目指します。
まず、音源カードのオリジナルのICはそれなりに大事なものですので、できれば別の書き込み可能なFlashに書き込み、前ページに書いてあるようなチップ選択方式を使ってスイッチなどで切り替えられれば最高です。
そのために、手持ちのジャンク基板から、同じ方法で読み出せるSPI Flashを外し、
この中に元の音源チップから吸い出したものをそのまま書き込み、このチップから再生できるかどうかということを試すことにしました。
もともと載っているFlashはMicrochip製 SST26VF032B ですが、試しに使ってみたのは全く違うメーカのXT25F128というものです。
基本的なアクセス方法は同じ(互換モード)ですので、単純なREADだけ使っているなら中身は同じように読み出せるはずです。
呼び込み君にセットしてみると…再生されません。。残念です。
このようなFlashメモリ、基本的なコマンドは同じですが、上位のコマンドや特性など、専用の機能を使ったりする場合にチップを判別するためのID「JEDEC ID」という3バイトのコードが埋め込まれています。
推測ですが、電源投入直後にこのコードを確認し、違うチップの場合拒絶するか、読み込みエラーとして作業を中断する仕様になっている可能性があります。
呼び込み君のマイコンのSPI端子をロジックアナライザで観察してみると…
確かに最初にJEDECを読んでます…
0x9F:JEDEC ID READ
0xBF 0x26 x42 : SST26F032のID
ダメか…
使用しているロジックアナライザは定番のLAP-Cです。
定番ですが、ドライバを落とす台湾のサイトが激重ですのでドライバは大事に保存しておくのが便利です(もう治ってるのかな)
では、同じFlashメモリを入手して書き込んでみるか…と思って探してみますが、
在庫切れで、入手には時間がかかりそうです。
仕方ない、やはり書き換えるしかないのか…
(FlashROMの代わりに、SPIメモリをエミュレートするマイコンなどを載せる方法もありますが、実装がめんどくさそうです。READだけならすぐだと思うけどね)
では、書き込むための機材を準備していきます。
Flashメモリ単体は、USBメモリのようにパソコンに接続してすぐに書き込めるものではなく、専用のライターが必要になります。すべてを自作することも可能ですが、一般的には安物の専用機を使うことが多いです。
私は普段から似たような作業を行うことが多いため、EZP2010というライタを持っていますが、調べてみるとこのMicrochipのFlashには非対応でした…
自作か…めんどいな…と思ったところ、別の方法を思い出しました。
Raspberry PI のSPIポートを使用してFlashを書き換える手法があり、
そのための専用オープンソースソフトウェア「flashrom」というものがあるのです。
PC自作の人たちがうっかりBIOSファームアップ中に壊してしまったりしたときなど、
チップを取り外して焼き直したりするのに使います。
よし、これならいける。接続はどうしようか…
このような用途では何回も書き換えたりすることが想定されるため、
毎度はんだ付けをするのは骨が折れます。
はんだ付けの例
しかし、この音源カードに改めてコネクタを取り付けるような厚み方向への余裕はありません。ポゴピンと呼ばれるような部品を使って開発用治具を作る方法もありますが、
なかなかめんどくさそうだなと思いながら、コネクタを眺めていると…何かに似てるな…
そう、ICカードのコネクタです。
よくよく計測してみると、パターンの形こそ違いますが、接点中央部の間隔は同じです。また、音源カードの中の基板は、一般的な電子機器の基板厚みである1.6mmより薄く約1mm、つまりこれは中身をカードとして扱えば、ICカードスロットを転用して書き込み治具が作れそうだ!
早速部品を探しますが…
こんなもん、その辺で売っているものではありません。
じゃぁ、手持ちにあるジャンクからなにか取り出すか…
携帯用のSIMカードが刺さる奴は…省略版の6ピンか…
ETCカードのスロットは…これもピン省略が多いようだ…
うーん…あっ、B-CASカードだ!!!
ジャンク箱をひっくり返し、地デジ移行期に配布された安価な地デジチューナを引きずり出しました。
これをばらしてカードスロットを取り外します。
接点の間隔は同じですが、カード隅からの位置は違うため、適当なカードを切ってスロットに詰め込み、音源カードを差し込んだ時に接点がぴったり合うように加工します。
ロイヤルホームセンターの会員カードに犠牲になってもらいました。
カードスロットの端子をRaspberryPiのSPI端子にはんだ付けします。
flashromコマンドを実行すると…認識した!!!これで読み書きができるはず!
書き込み装置物理層完成!!!!!
続いて、中身のデータを書き換えるソフトウェア編へ!
このブログにはAmazonアフィリエイトへのリンクが多数埋め込まれています。
そのものを買わなくても、リンク踏んでからしばらくの間に買い物をすると、還元されるようなことを書いてあったようななかったような気がします。大事なお小遣いです。あなたの懐からは持っていきませんのでお買い物前にぜひお立ち寄りください。
なんとアマギフを買ったりしても還元されるのです。びっくり。
このブログにはあんまり出てきませんでしたが、私の家には呼び込み君が2体います。
世の中にはこの呼び込み君に魂を奪われてしまった人、特に子供が多く、
100Vモバイルバッテリーに刺した呼び込み君持って現れる絵面面白すぎやろ #呼び込み君https://t.co/twim6bSGhI pic.twitter.com/6As5nUOAjW
— ひろみつ (@bakueikozo) November 19, 2021
呼び込み君フリークの息子、高頻度でこの動画を見てケタケタ笑ってるんだが、これワタナベマホトと相馬トランジスタだったのか。マホトはともかく、相馬氏風貌変わり過ぎて一年以上気づかなかったわ。(言われてみれば面影はちゃんとあるんだけど) pic.twitter.com/zsSp8ovY3g
— ひろみつ (@bakueikozo) October 19, 2021
どういうわけかうちの息子もその術にはまってしまい
新しい家族が増えました
— ひろみつ (@bakueikozo) August 5, 2020
呼び込み君です!
いやもう、なんか店に行くたびにこいつに息子が捕まって離れないし、トミカを買おうって言ってもお菓子を買おうって言ってもヤダっつって帰れないし抱っこさせられる始末だったので、そこまで言うならと買いました。
モウオモチャナシダゾ pic.twitter.com/8NDYJuUr9b
日々家の中で呼び込みサウンドが鳴り響いているのです…
そんな呼び込み君、仕様についてはまず適当な動画でも見てもらうことにして
基本的な機能としては、音源カードに内蔵された2曲のうちの一曲(もしくは無音)と、録音ボタンを押しながら吹き込んだアナウンス2本のうち一本、を延々とループ再生する機能があります。
呼び込み君の特徴的な「ポポーポポポポ」は、背面に差し込む音源カードに内蔵された曲で、このカードを抜いてしまうと聞くことができません。
ベビーカー売り場の呼び込み君 pic.twitter.com/rthu76wada
— ひろみつ (@bakueikozo) December 31, 2020
初期状態のシステムで、子供たちが大好きなドン・キホーテBGMに合わせたアナウンスを再現するためには、録音ボタンを押しながら携帯などでドン・キホーテの曲を流しながらアナウンスを録音する必要があり、結構めんどくさいです。
実際のドン・キホーテの店頭の一部では、特注で製造される専用BGMの入った音源カードを使用しており、これを使うとBGMとは別に単体でアナウンスを録音することができます。
しかし、特注ですから子供たちが簡単に手に入れることはでき…ないはずなんですが、
なぜかメルカリで結構売っているようです…なんで?闇?
そんな子供たちのあこがれ特注BGMカード、うちの息子も絶対に欲しいと言ってききません。かといってこのような闇取引に手を出すのはいかがなものか
というわけで、ドン・キホーテの曲にとどまらず、自分で好きな音源を録音できる音源カードを自作できるようにしてしまえばいいじゃないかプロジェクト~~!
↓これはどっかの店で見たAdoの曲と一緒に録音されたアナウンスを再現しようとする息子
呼び込み君で遊ぶということ pic.twitter.com/FfuHAcF4oR
— ひろみつ (@bakueikozo) January 22, 2022
まずは、既存の音源カードについて調べることにします。
音源カードの中身です
IC1~IC4まで実装パターンがありますが、実際に実装されているのはIC1のみでした。
IC1はMicrochip製のSPIフラッシュメモリ 32MBit(4メガバイト) 26F032 です。
この中に音源データが入っているはずです。
ピン配置とパターンを追って模式回路図を書いてみました。
呼び込み君では一つのICに入った曲2曲の選択式ですが、
基板の端子にはあと3つのICを選択できるような拡張があるようです。
この端子を使う場合、IC5に74138が実装されるように見えます。
呼び込み君ではIC1しか使用されないため、J1で直接選択することで
74138の実装を不要としているようでした。
しかし、この拡張を使った機器、他にあるんですかね…?
吸い出すために、Arduino XIAOで読出しプログラムを作ってテキストでダンプし、
これをシリアルで受信してからバイナリファイルに落とすことにします。
Flashの上限電圧が3.6Vですので、5V系Arduinoは使用できませんので注意です。
無事バイナリファイルができましたので、ざっと眺めながら解析していきます。
ファイルの先頭部分のヘッダ部分に情報が詰まっていそうです。
解析を楽にするため、ImHexというソフトを使ってみることにしました。
最近は「ImHex」というクロスプラットフォームでOSSなイケてるバイナリエディタが出ています。もちろん動的な構造体定義が可能(RT先のような日本語変数の定義はできないけど)。
— しゅーと (@shutingrz) July 6, 2022
オススメ!https://t.co/S9HZY4JYBK https://t.co/12BE4FYfMB pic.twitter.com/SflDwcUYoP
構造体定義を書いていくことで、ファイル全体を構造体として解析できる優れものです。
解析を進めていった結果、構造体定義は以下のように書けることがわかりました。
struct songheader_t{
u32 magic;
u16 unknown1;
u16 unknown2;
u32 addr_start;
u32 addr_stop;
};struct song_t{
songheader_t header;
padding[0x400-16];
u8 songdata[header.addr_stop-header.addr_start+1];
};struct globalheader {
u32 magic;
u32 val1;
u32 val2;
u16 u1;
u16 u2;
u32 songaddr[2];
padding[0x40-24];
song_t song1@songaddr[0];
song_t song2@songaddr[1];
};globalheader data@0;
この構造体定義にて読み込むと、以下のようなテーブルが生成され、中身が一目瞭然です。
4MByteあるフラッシュメモリ中、使用しているのは2578432バイト、2.5MBほどのようです。
音源データ部のフォーマットはどうなっているでしょうか。
普通の非圧縮フォーマットであれば無音部分は0やFFなどが続くはず。それが無いということは何らかの圧縮フォーマットである可能性が高いです。
しかし、再生に使用しているのはかなり小スペックのマイコンであり、そんなに複雑ではないはず。ええいADPCMに違いない、とあたりを付けてGoldwaveであれこれ開いていると、ついに正解を見つけました!
前回リーダにパラメータが無くて適当に合わせて読んだので化てたようだ。今回はきちんと読めてるようでノイズのないきれいな呼び込み君音源をメモリから直接吸い出すことに成功した。マイク録音ではない、本当の生音源の抽出は初めてではないだろうか。フォーマットはADPCM 4bit 44.1kHzだった pic.twitter.com/ifuwTO9M9q
— ひろみつ (@bakueikozo) November 28, 2022
全くノイズのない、生のポポーポポポポを手に入れたのです。
それを手に入れてもしゃぁないねん。
いや、ここまでわかったということは、これと同じフォーマットでここに自分の好きな音源を書き込んでやれば、好きな音源のカードが作成できる、という技術の裏付けができました。
しかし、このFlashメモリに音源を書き込むためには専用の回路やエンコード用のソフトを作らなければなりません。できるだけ低コストで、さらにユーザーフレンドリーに仕上げるため、設計を進めていきたいと思います。
いや、誰が使うねん!!!!!!
(※ある程度、少人数ですが需要はあると思います。しかし、部品代、基板製造代、など子供のお小遣いの範囲に納まる気はしません…)
書き込み機の作成の記事はこちらです!
このブログではさんざん分解しているWifi防犯カメラ、特に屋外で使用可能なATOMCam2なんていう便利なものを結構な数持っているにもかかわらず、
実運用しているカメラが1台もないという奇妙な状態が続いていましたが、
運よく引っ越しが完了し、さらに監視対象としての庭や道路がたくさんできました。
そのため、手持ちのカメラを、分解したものを頑張って組み立てながら実運用していこうと思っています。
まずは一台、目の前に信号機のない交差点がある1階の道路に面した軒下にカメラを付けてみようと思いますが…
屋外にカメラを付けるときに、考えなければいけないのは、電源の確保です。
この位置にコンセントはありません。そのため室内から引き出さないといけません。
素直に考えると、いいところにエアコンの室外機がありますので、この配管穴を通して
室内からAC100Vを配線することが簡単そうですが…
実はこの配管、すぐそばの部屋から直接引き出されておらず隣の部屋の収納を経由している上、配線の位置もエアコンの真裏に隠蔽されていて、新たに配管を通すのが面倒です。
ぼんやりと眺めていると、エアコンの室外機にVVFが配線されているのが見えました。
あれ?もしかしてこれはAC100Vが供給されているのでは?と思い、まずは調べてみます。
カバーを外してテスターをあてると…おお、AC100V。そしてエアコンの動作状態には関係なく、常時給電されています。これは素晴らしい。
この端子からACを取り出し、ACアダプタでカメラに電源を供給することにします。
(残りの1本は通信線らしいです。たまにアースと勘違いしている人がいます)
また、少なくとも私のエアコンで(ダイキン)は常時給電でしたが、そうでない場合は毎度確認する必要があると思います。が、わざわざそこにリレーなどを入れることはあまり考えられないので、多くの場合常時給電だと思われます。
※ここから先の作業内容はあくまでも作業ログであり、指南書ではありません。
また、作業の中には電気工事士の資格が必要な工程があります。
類似の作業を行う場合、各人の責任で、安全を確保する必要があります※
①電源取り出しケーブルを作ります
今回の室外機の接続部には端子台が使われ、ACの黒白、信号用の赤に対して2本ずつ接続できるようになっていました。そのため、平型端子を使って取り出しケーブルを作ります。
必要な部材です。
・平型端子
・AC差し込み口
・配線ケーブル(本来、屋外用のタイヤキャブケーブルを使うのが正しいです。しかし、今回露出部が少ないこと、雨が直接かからないことから上記のビニルキャブタイヤケーブルを使用しています。配線後、ビニールテープで巻いて保護することとします。
最低でも安全のため、通常の平型コードを使うのはやめた方がいいと思います。)
(1)ケーブルの被覆を取り、圧着端子を付けます。極性は気にしなくていいです。
(2)反対側に差し込み口を付けます。中学校の技術家庭のレベルです。
②エアコンのコンセントを抜き、白黒線が0Vになることを確認します。
(ブレーカを落とす必要はありません。)
③端子台に接続します。くれぐれも、電圧のかかっていない状態を確認してください。
④ケーブルを固定します。
⑤配管カバーを外し、コンセントを通します。
ケーブルは、この辺から通すといいでしょう。
⑥カメラを取り付け、エアコンのコンセントを戻し、カメラの動作確認をします。
このような手法で電源を確保することで、
たいへんシンプルに電源を準備することができました。
実際に撮影している画像はこんな感じです。
設置したカメラは「ATOMCam2」で、わずか5000円程度で防水・暗視機能を持っています。お勧めだけど、それなりに壊れるので、壊れたら買い替える気持ちでいましょう。
必ずこの手法で電源が取れるとは限りませんが、自分の持っている設備を
十分に観察し、必要な知識と手順をもって行えば、こんな施工も可能になります。
最後に、この手法で電源が確保できるのは、エアコンの消費電力に対して無視できるほど小さな機器を接続する場合に限ります。ATOMCamはせいぜい5W~10W。エアコンの動作電力は数百ワットですから、ケーブルの許容電流としては十二分に余裕があると考えられます。簡易なLEDタイプのクリスマスイルミネーションぐらいなら問題ないかもしれません。それに反するような、例えばハロゲンライトや電動工具などは絶対に接続してはいけません。そういうことを考えられる人のみ、こういう施工が可能です。
数年前にリリースされ、一部界隈では非常に便利に使用されている
YAMAHA製のChordTrackerというアプリがあります。
このアプリは、手持ちのスマホに入っている音楽を解析し、
簡単にコード譜を作成してくれ、耳コピや弾き語りなどを強力に支援してくれるソフトで、私も大変便利に使用しています。
基本的にはスマホ専用のアプリですが、AndroidエミュレータをPCに入れることで、PC上で使用することもできます。
手抜き耳コピ用にChord Tracker使いたかったんだけど、手持ちのAndroidタブレットはモッサモッサだしファイルwavにして持っていくの面倒、とかでどうしようかと思ってたの、ふと思い出してSurface2にBluestacks入れて動かしてみたらサクサク動いたわ。これでええやん。 pic.twitter.com/nlwnJAt6jr
— ひろみつ (@bakueikozo) January 1, 2022
少し前までは自分でピアノを弾いて楽しむだけだったのですが、最近は
「nana」という音楽コラボSNSに伴奏として音源をアップロードしたりしています。
そんな便利なChordTrackerですが、一つだけどうしてもできないことがあります。
作成したコード譜を外部にファイルとして出力できないのです。
ごく一部のYAMAHAの電子楽器などに、データを送出することはできるようなのですが、該当楽器を持っていないため、試すことすらできません。
上の動画のように、コードを見ながら練習をする、という用途では十分なのかもしれませんが、この解析結果をもとに、別の楽譜ソフトにコードを打ち込んでアレンジ用の楽譜を作成したりしたい場合、画面を見ながらちまちま手入力する方法しかありません。
これは不便!!!
ということで、どうにかこの解析済みデータを取り出すことに挑戦しました。
まずは、純正の機能の、対応楽器への送信部分を解析してみました。
iOS版では、Blutooth-MIDI経由で楽器と接続する、ということなのでBLE-MIDI変換モジュールを購入して試してみました。
my new gear..
— ひろみつ (@bakueikozo) April 27, 2022
愛用しているChord Tracker、すごい便利なんだけど、解析結果をエクスポートする機能がないのよ。せめてテキストででも出ればいいのに。
で、データぶっこ抜きも無理そうなんだけど、どうやらBLEMIDIで何かしら出せるようなので、ここから取り出そうとしてみるけど上手くいくかな。 pic.twitter.com/apl5obo09D
この基板を使用してMIDI出力を見ながら「対応楽器への送信」を選択すると、
SystemExclusiveメッセージ「ID Request」が送出されました。
どうやら、対応機種であるかどうかを確認しているようです。
試しに判明しているYAMAHAの電子楽器のIDをいくつか返してみましたが、接続が確立される様子はありませんでした。
結局わからんのでとりあえずYAMAHAの適当なデバイスのIDを返してみたけど駄目だ pic.twitter.com/RLIiyEyU8n
— ひろみつ (@bakueikozo) April 27, 2022
あれやこれや調べた結果、対応機種は割と最近出た3機種のみでhttps://t.co/J12dGzD9y3
— ひろみつ (@bakueikozo) May 4, 2022
ID Responseの値もわからず、そのあとも独自プロトコルで通信してそうなのであきらめることになった
対応しているという機器はPSR-SX600、SHS-500、SHS-300のわずか3機種、
また、これらの機種のマニュアルを調べてみたのですが、ID Requestに対するResponseが明確に記載されている部分はありませんでした。
さらに、実行バイナリをあれこれ覗いてみたのですが、機種との接続確立後も、なにやらめんどくさそうなプロトコルで通信していそうなため、あきらめることにしました。
さて、次の手段です。
このアプリ、ある曲を一度「解析」を行うためには多少時間がかかりますが、
二回目の読み込みからは解析済みのデータを参照しているようですぐにコードが表示されます。
ということは、端末内にキャッシュファイルが保存されているはずです。
これを探すために、Android端末に接続し、アプリからのデータを保存しているはずの場所を探してみましたが、OSの保護機能のため見ることができませんでした。
そこで、root化を試みます。
手元にroot化できるAndroid端末が無いため、ChordTrackerをインストールしたAndroidエミュレータ「BlueStacks」をroot化します。
その結果、/data/data以下のアプリストレージ領域に、解析済みのjsonファイルを発見しました!!!
さらにいろいろして、AndroidエミュレータBluestacksをroot化した上でChordTracker動かして、/data/dataの下漁ったらjsonファイルが出てきたので、これを開いてみたところ見事にコード解析キャッシュファイルを発見した!これで勝つる!!!! pic.twitter.com/uR0HRbTzrk
— ひろみつ (@bakueikozo) May 4, 2022
サンプルのjsonファイルを一つおいておきます。
https://gist.github.com/bakueikozo/239bdab15367ffdc72a16c9acdd9784b
これを読んでいくと、こんな記述があります。
"1": {
"root": "10",
"type": "0",
"onBass": "127",
"originalRoot": "10",
"originalType": "0",
"originalOnBass": "127",
"accidentalRoot": "0",
"accidentalOnBass": "0",
"mahaRoot": "10",
"mahaType": "0",
"mahaOnBass": "127"
},
これは、曲内の第一拍目のコードのルートが、C(ド)を基準とした10半音上、つまり「B♭」であること、typeはコードの形、ここでは(普通の)メジャーコードであることが示されています。
コードの形のIDはYAMAHAがシンセサイザーなどで使用している定義順になっているようでした。(音楽理論的に、もしかしたらそれが定義されてるのかもしれませんが、私にはよくわかりませんでした。)
コードタイプの値はさすがYAMAHAのシンセで使われてる並びと同じのようで助かった。 pic.twitter.com/kJp2tWyDme
— ひろみつ (@bakueikozo) May 6, 2022
このようにして、解析済みの画面に表示された内容と、jsonファイルを照らし合わせながら内容を解読していきます。
解読ができたら、これをエクスポートします。
界隈で、楽譜の清書によく使われるオープンソースの「MuseScore」というアプリがあります。
このソフトで読み込めるように、ソースコードを解析していくと、どうやら普通のSMFに出力してやるのがよさそうだ、という結論になりました。
ソースコードによると、YAMAHA独自のシステムエクスクルーシブのバイナリデータで、タイムスタンプに対してコード情報を付けられるように読めるのですが、どうにもうまくいきません。
仕方がないので、とりあえずは「歌詞」としてコードネームを入れていきます。
変換プログラムはC#で記述しています。
SMFファイルの書き出しにはdrywetmidiというライブラリを使用しています。
コード名だけを入れると、突然難しいコードで躓くかもしれませんので、
実際に押さえる音符も入れることにします。
コード名(ID)から和音の生成のために、コード表を見ながらこんなテーブルを作成します。
int chordtype_member = {
new int{ 0,4,7 }, // Maj
new int{ 0,4,7,9}, // Maj6
new int{ 0,4,7,11},
new int{ 0,4,6,7,11 }, // Maj7(#11)
new int{ 0,2,4,7,11}, // Maj(9)
new int{ 0,2,4,5,9 }, // Maj7(9)
new int{ 0,2,4,7,9}, // Maj6(9)
new int{ 0,4,8 },
new int{ 0,3,7}, // min
new int{ 0,3,9}, // min6
new int{ 0,3,7,10} , // min7
new int{ 0,3,6,10} , // min7b5
new int{ 0,2,3,7}, // min(9)
new int{ 0,2,3,7,10}, // min7(9)
new int{ 0,3,5,7,10}, // min7(11)
new int{ 0,3,7,11}, // minMaj7
new int{ 0,2,3,7,11} , // minMaj7(9)
new int{ 0,3,6 },
new int{ 0,3,6,9 },
new int{ 0,4,7,10}, // 7th
new int{ 0,5,7,10},
new int{ 0,4,6,10},
new int{ 0,2,4,7,10}, // 7(9)
new int{ 0,4,6,7,10} , // 7(#11)
new int{ 0,4,7,9,10 } ,
new int{ 0,1,4,7,11}, // 7(b9)
new int{ 0,4,7,8,10 }, // 7(b13)
new int{ 0,3,4,7,10}, // 7(#9)
new int{ 0,4,8,11}, // Maj7aug
new int{ 0,4,8,10}, // 7aug
new int{ 0,8}, // 1+8
new int{ 0,7}, // 1+5
new int{ 0,5,7},
new int{ 0,2,7}, // 1+2+5};
このようにしてSMFにして出力し、MuseScoreで読み込み、
段数や繰り返し記号などを入れていくと…
あっという間にコード譜の出来上がりです。
リズムは1拍基準のため、細かいプレイのアレンジは反映されていませんが、
これをもとに修正していくだけで完成するのは非常に便利です。
何しろ、今までは目で見ながら小節にコードを配置していくことしかできなかったんですから。
ここに、例えばイントロのメロを拾って追加してやる、とかコメントを追加する、と化すれば、あっという間に伴奏用の楽譜が完成します。
さて、そんな便利なソフトを作っているわけですが、まだまだ調整中です。
もしもこういうソフトがホントにリリースされたら絶対使う!という声があればリリースは考えますが、今のところ自分で使うぐらいしかないですかねw
ここまでの解析のつぶやきのTwitterをここに貼っておきます。
もうちょっと詳しく見たい方はこちらへ。
my new gear..
— ひろみつ (@bakueikozo) April 27, 2022
愛用しているChord Tracker、すごい便利なんだけど、解析結果をエクスポートする機能がないのよ。せめてテキストででも出ればいいのに。
で、データぶっこ抜きも無理そうなんだけど、どうやらBLEMIDIで何かしら出せるようなので、ここから取り出そうとしてみるけど上手くいくかな。 pic.twitter.com/apl5obo09D
天井の材質までは知らない pic.twitter.com/8Wry0QFw1w
— ひろみつ (@bakueikozo) March 7, 2022
3/7日の深夜、夜食を食べた後ちょっとめまいがしたので、まあ寝るかと思って横になったものの、強烈な回転性のめまいと吐き気、冷や汗がひどいまま朝を迎え、
あさやっぱりまったく改善しておらず、立つことも、目を開けることもままならなかったため救急車を呼びました。
運よく診察歴もあり、保育園の通園ルート上にある千葉流山愛成会病院へ搬送されました。
手足のしびれなどはなかったのですが、父方・母方両祖父が脳卒中、父も脳梗塞、そして高血圧の既往アリということでMRIを撮ってもらいました。
なにやら今年導入された最新の機器らしく、頭部の撮影が5分足らずで完了するらしいです。
撮影後、しばらく処置室でめまい止めの点滴を受けていると、脳外のドクターが読影にやってきて一言
Dr.「ん?梗塞?」
まって。
Dr.「いや、ちがうか。あーーー。うん、患者さんに説明するわ」
ちがったか。よかった。
Dr.「えーと、脳の血管のこの辺にあるのが解離性動脈瘤です。とりあえず入院してください」
俺『いやーーーーー、無理です…』
Dr「えっ…」
私の近況を知っている人ならわかると思いますが、妻はそんなに元気じゃない(婉曲表現)で、日常の生活には頻繁に他人の助けが必要で、私以外のサポートを受けることは精神的影響を考えると現実的に不可能です。
子供は4歳と2歳。諸々の流れで、この自宅から車で20分のところにある姉妹園に通っています。車を運転するのは私だけ。
Dr.「この動脈瘤、破裂するとくも膜下出血を引き起こしたり、血栓が飛ぶことで脳梗塞になる可能性があります。なので、入院して血圧を下げ、様子を頻繁に見る必要があります。今日は眩暈だけで頭痛はありませんか?強烈な頭痛と主に発生して、これが原因だった場合、特に数日のあいだ、頻繁にMRIを撮影して、くも膜下出血に対する備えが必要です…脳外科の先生10人に見せたら10人入院してくれっていうと思います…」
俺『いやー、こまったなぁ…』
俺『子供をここから車で5分の保育園に朝送ってくるので、そこで毎日MRI取ってもらえますか?』
Dr.「ええぇー……じゃぁそれで… もし入院の準備が整うようならいつでも入院できます…こちらの書類にサインを…」
病巣に変化はなく来週の再検査後毎週MRIを継続することになった。とりあえずよく寝ているので元気です。
— ひろみつ (@bakueikozo) March 11, 2022
あとこちらは入院を勧められても断った時に貰える珍しい書類です。 pic.twitter.com/x34OUdghPW
というわけで、無事帰宅をゲットしてきました。
いや、全然無事ではなさそうだけど、それはまた後に。
主訴のめまいは2時間の点滴と静養で歩けるようになり、数日は横になったときなどに少しめまいが残りましたが、処方された薬で改善し、本日は全くありません。
で、帰宅したため、早速翌日から撮影三昧でしたが、
3/7,3/8,3/10,3/17と撮影したMRI上では患部には全く変化がありませんでした。
これについては、この部分が発生したのが相当前であり、この形のまま残っている可能性が一つ(この部分が元の形に戻ることもあるらしい)、もともとの血管の形がこうである可能性が一つ、もう一つは、今も進行中であり、今後何かが起きる可能性、とのことです。
この病巣についてはこちらのページが非常に詳しかったため、興味のある方はどうぞ。
脳の血管の一番内側にある、高圧に耐える幕の部分に裂け目ができ、それよりは弱いホースの外側の部分が膨らんだ状態で血圧を保っている、ということらしいです。怖いですね。
最近、東京ミュウミュウの作者の征海未亜先生が亡くなられたクモ膜下出血、発症するとほぼほぼ元の生活はできません。
現状はMRIの写真・進行状態からして、急性期は過ぎていると考えられますが、全く変化がない、ということもあまり経験がないらしいので、注意深く見守っていく必要があるようです。
例によってCD-RでMRIデータをもらってきましたので眺めていますが、
DICOMデータのビューアは癖が強いので、いまだに患部を発見できていません!
さて、ここで突然ですが皆様にお土産です。
貴重な私のMRI撮影データをここに置いておきます。
煮るなり焼くなり、お好きにどうぞ!
(もらったディスクの中には、コピーはご遠慮願います、と書いてありますが、
その際に問題になる部分、ビューアの部分の著作権があるため除外してあります。
そのため、生データになり属性等が不明になって、ただの画像生データになっていますが、それでもDICOMビューアに突っ込んだら面白い絵は見えると思います。
あ、いやブラウザで見るためのINDEX.HTMがあるのか。ROM写真集だなw)
いや、何でそんなことするかって。
今回、撮影されたデータをもらってきてますが、こういうった医療用のデータって、
フリーのデータがそんなにたくさんあるわけではなく、
ちょっと興味を持ってみてみたいな、と思った場合に見れるものではないのです。
10年以上前ですが、仕事で簡易DICOMビューアをアプリに内蔵してくれ、と言われたものの、サンプルデータは全然ないし、希望のフォーマットでもないし、とめんどくさかったことがあるのです。
なので、ここに私のDICOMデータを置いておくので、技術的興味でも、
タダの好奇心でも、また、病院でこういったデータは請求すれば必ずもらうことができること、を知ってほしいのです。
窓口や、ドクターに「自分で見るのでデータください」といえば必ずもらえます。
理由を聞かれたら、自分で見たいので、といえばそれでOK。
自費になりますが、大体CD-R一枚もらえて実費1000円+税のみです。
毎回もらうとかさむので、ある程度溜まったところでもらうといいと思います。
とりあえず、次の撮影会は2週間後。悪い方向にならないといいなぁ。