honeylab's blog

各種ハードウェアの改造、主にファミコンミニなどをやってます(ました)

秋月謎SoC基板付きケースの購入~解析とLinux(buildroot,Debian)を動かす

ある晴れた昼下がり こんなツイートを見かけました

 

へー。中身…

うおおおおおお、通販ぽちーーーーー!

としてTLを眺めていると…

 

次々に流れてくる購入報告と開封画像

 

…あぁぁぁぁぁぁ!今から買いに行くかぁ…????

 

そして売り切れ報告…

 

えぇぇぇぇぇ???もうみんなUART触ってるのに歯ぎしりしながら明日を待つのか…

 

 

と思った矢先…

フォロワーさんからとんでもない連絡が

どうやら歩いて行けるほど近くに住んでいる模様

慌てて財布握りしめて譲ってもらいに行きました

 

そんなわけで一日早く手に入れたので!早速分解します!

分解して解析する

この手の機器、オンボードフラッシュにファームウェアなりブートローダーが入っているのが常套なので、引っぺがしてROMライターにぶち込みます。

ところが…中身が全部FF…つまり、空っぽってことです。

まじか…ってことは、起動時に出てたCはSoCがネイティブで吐いている可能性…

あーーーー、XMODEMでのファイル受信待ちか…そっからーーーー???!

ja.wikipedia.org

 

しかし、その手順もありますが、そんなに古くないSoCであればネイティブでSDカードからの起動をサポートしている可能性は大いにあります。

データシートを見る前にそれを確認するために、電源投入時のmicroSDスロットの状態を確認してみると…CLK端子に初期化用の波形が出ています。

 

つまり、適切なブートローダをSDカードに書いて挿せば起動する可能性があるということです。

(※過去にファミコンミニをSDカードから起動させたことがあります)

honeylab.hatenablog.jp

 

この手の機器で、量産するレベルのものであれば既存のLinuxが対応している可能性は大いにあります。というか、メーカから提供されるSDKがそのままLinuxのツリーだったりするわけで。また、似たような機器の起動イメージがそのまま利用できることもあります。互換品を探すためにSoCの型番と、組み込み用のシステムを組み合わせて検索していると…同系列のAM5338を搭載したBeagleBoneBlack、これはデフォルトでLinuxが使えます。OpenWRTのポーティングもあるということがわかりました。

 

また、内蔵eMMCのほか、外部microSDからのLinux起動ができます。しかも私の部品箱に転がっている。これは好都合。さっそく、このイメージを書いて…

 

既に試してくれていました。おお。少なくともブートローダが呼ばれている。これはもはや勝利は目前。

その後あれこれみんなが試して、どうやらBBBのイメージは割とすんなり動いてシェルまで立ち上がる、ということまでサクッと判明してしまいました。

 

しかし、これからです。私の主目的はこれに搭載されたWi-SUNと3Gモジュールまで含めて使い倒すこと。多少弄ってみましたが、BBBのイメージのままではそれらをうまく使いこなすことができません。何より、BBBのまま動いているというのが若干気持ち悪いです。そのため、ゼロからファームウェアのビルド手順を確立し、好きなモジュールを入れ、好きな機能を自分でいじれるようにする必要があります。

まずはブートローダのビルドから!

U-BOOTを作る

とはいえ、実際BBBに近いので、ビルド手順も大いに参考になります。

今回はこちらのWebページをほぼほぼそのままなぞる形になりました。

ichiri.biz

ただし、この手順で作っただけでは起動に至りません。

BBBはCapeというモジュールによる拡張やボードの判別をオンボードのEEPROMの領域を用いて行っていますが、この秋月ボードには搭載されていません。
そのため、起動中にその部分で失敗して停止してしまいます。
その部分をスキップする必要があります。
検索していると、ほぼ素の355xのu-bootを動かしている記事が見つかりました。

qiita.com

この記事で利用しているパッチを当てると、そのあたりを適当に回避して起動してくれるようです。もちろん、他の素の355x用のブートローダコードを使うのが正攻法かもしれませんが、とりあえずこれで進んでいきます。

 

TIのブートローダの仕組みとして、microSDに”MLO”というファイル(u-bootの一部)が書かれていれば、それを読み込んで起動できるらしいです。しかし、SDからのブートは本当にそれだけではなくて書かれているセクタなどが本当は決まっていたりするのであれこれ試すのに切り分けが難しいです。

そのため、せっかくなのでシリアルからのブートにチャレンジしてみました。

上記の手順でu-bootのSPL(1st bootloader)を、"CCCC"の状態のボードにTeraTermを使ってXMODEMで流し込みます。

SPLが立ち上がったら、2nd bootloaderをYMODEMで流し込みます…

すると…

やった。それまで"CCCC"しかしゃべらなかった基板にUIが発生しました。
つまり、ビルドしたu-bootが正しく動いた、ということです。よいよい。

続いて、microSDでの起動も試してみると無事成功しました。

なかなかリッチなU-BOOTで、USBメモリも、オンボードEtherも、USB-Etherも使えるというてんこもり状態です。すばらしい。

 

ここまで動いたらあと少し。カーネルのビルドを行います。

Linuxカーネル本体だけでは使い物にならず、シェルなどを含むルートファイルシステムが必要です。
一般的にはDebianとかそういったリッチな環境がありますが、このような組み込み機器では、"busybox"を含む、小規模な環境が使われます。

このルートファイルシステムを作る環境の一つ"buildroot”に私は良く慣れているのでこれを使っていきます。

 

同様に、こちらのサイトを参考にします。

ichiri.biz

 

U-BOOTは先ほど成功しているのですが、BBBのイメージ作成ツールとして上記のbuildrootのコンフィグやスクリプトがありますので、これを改変しながら謎基板へ適用していきます。

 

 

あれやこれやと改変していき、とりあえずカーネルの起動画面とbuildrootのログイン画面を拝むことができるようになりました。

しかし、まだ足りません。これではBBBのイメージで動かしたときとはあまり変わらないのです。

Wi-SUNボードを使えるようにする

ボードに搭載されている、Wi-SUNモジュールを動かすための調査です。

www.tessera.co.jp


このモジュール、単体買いで一万円もするため、このボードがとってもお得だ、という話があるほどなかなか買いにくいものです。
詳細資料は本体を買ってサイトのIDをもらわないとDLできないのですが、最小限のデータシートはありました。

https://www.tessera.co.jp/Download/MB-RL7023-11_DSS_UM_J1.pdf

マイコンとはTTL UARTで接続してコマンドを送受信します。

マイコン側のドライバを調整し、Wi-SUNのポートから信号が出るようにします。
応答されるはずのコマンドを投げてみますが…無応答です。
調べてみると、どうやらRESETピンがイネーブルされていないようです。

RESETピン、通常はモジュール側でプルアップされているため、解放さえされていればそのまま動くことも多いのですが、今回はしっかりSoCに接続されていてRESET状態になったままのようです。幸い、電源はDC/DCから直結されて常時ONになっているようでした。

RESETピンの接続されているGPIOは53番との情報が出てきたので、このピンをGPIOとしてLinuxから制御できるようにします。(なんか、LEDとして扱うのが便利だよーっていう情報が多いのでそうしてますが、もっと素直にただのGPIOとしてnamingしてもいい気がするんですが…だれかdts直してくれてもいいのよ)

せっかくなので、秋月ボード専用のdtsファイルを作成していきます。

github.com

この修正を行うことで、Linux起動時にデフォルトでHIGHレベルが出力され、WiSUNモジュールが起き上がるはずです。レッツ。

見事、Wi-SUNモジュールと通信ができました。

/dev/ttyS1がWi-SUNモジュールとの通信口です。
これにより、例えば以下のようなサイトを参考に、スマートメータから瞬時電力量を取得するようなプログラムを動かすことができるようになりました!!

netlog.jpn.org

あと先ほどプログラミングマニュアルのDLにはIDが必要、との話でしたが、

どうやらこの手のモジュールには共通コマンドとして実装されているらしく、デバイスが違っても大体同じコマンドで通るらしいので、それで行けそうです。

 

あといっこ!!携帯電話モジュール

この謎基板を引き付けたものとしてもう一つ、3Gモジュールがあります。

ubloxのSARA-U201というものです。

www.digikey.jp


たしか、もうすぐ3Gが終わってしまうのであまり長く使えるものではないですが、
普通に買うと結構なお値段するものが載っているというのはなかなかありません。

少し前のIoTモジュールなんかにはよく使われていました。

soracom.jp

 

とどめに、こいつを使えるようにします。

いろいろな情報と経験から、このモジュールはUSBでマイコンと接続され、マイコンからは/dev/ttyXとして見えて、ATコマンドで操作したり、pppで接続できるもの、として間違いありません。

データシートを見ても、そのようになっています。

が、LinuxのコンソールからUSBを見ても、基板上のUSBコネクタとそこにつながった機器しか見えてきません。もしそっち側につながっているとしたら、HUBのチップが挟まるはずですが、そんな感じではありません。Linuxの起動ログでも、USBホストは一つしか認識されていませんでした。

 

しかし、このAM3352はUSBポートを二つもっていて、一つはホスト専用、もう一つはDual-Role-OTG、つまりホストしても、デバイスとしても動作できるポートを持っています。(動作を変更する際には周辺回路に注意が必要です)

BBBのデバイス設定では、このポートがperipheral (デバイス側)として設定されていました。

これを、dtsで定義しなおして

dr_mode="host" とし、ホストとして動作させてみます。

(dtsもC言語ライクな // や /* */ のコメントアウトが使えます)

すると、起動時のメッセージログが変化し、二つのUSBポートが存在する、という表示が出るようになりました。

 

…しかし、つながっているはずのモデムのデバイスは見えません。

改めてデータシートを見てみると

VUSB_DETピンにUSB電源の5Vが加われば、自動的にUSBモードになります、と書いてあります。

これかー。じゃぁ、それをやればいいじゃん、となりますが…

この実装だと、VUSB_DETピンがSoCのどこにつながっていくのか、全くわかりません。

SoCがQFPなどの足があるタイプならもう少し楽ですが、これは接点がすべて裏側にあるBGAです。既存のファームウェアが本体に入っていればそれを解析すればわかるのですが、この本体には先ほど書いたように、何もソフトウェアが入っていない状態でした。

…うーん、済まぬ、犠牲になってくれ。

(フォロワーさんから買った基板に加え、通販であと2枚買っているので)

基板から部品を外し、テスターで配線を当たる、という技を使います。

部品を外した基板を手に入れる

一般的に(一般的とは)こういう基板から部品を外すにはヒートガンなどを使うのですが、不幸にも会社のデスクに置いてきてしまいました。ドライヤーでは熱不足です。

とりあえず、ガスコンロの上に粉砕バットではないほうのバットとともに乗せて加熱してみますが…

Image

基板の裏に結構部品があったり、足が出ていたりで基板自体がなかなか加熱されません。うまく熱を伝えるこの辺にあるもの…食塩!

バットに食塩を敷き、その上に基板を置いて加熱します。

これがうまくいき、しばらくするととても嫌なにおいとともにはんだが溶けてきました。

ここで一気に部品を外します。

 

成功です。

 

 

早速パターンを追っていくと、VUSB_DETはUSB用の電源供給IC(裏面のU10 TPS2405)から5Vを供給されていて、そのEnable端子はGPIO50に接続されていることがわかりました。やった!

 

これをdtsに定義して、Linux側から信号を出してやると…

 

やった!ttyUSBが現れました!これで携帯モジュールが使えるぞ!!!

Image

ホントに使えるの???

ATコマンドで疎通を試した後、手持ちのYmobileのSIMカードを挿入し、
自分の携帯電話にダイヤルしてみたところ…

 

着信したwwwwwつながったwwwwwww

モジュール側に音声入力の方法が無いので、無言電話なんですが…

あまり先がないデバイスとはいえ、完全停波までは時間がありますからまだ使えます。

データシートを見ると、普通のATモデムとしてダイヤルアップするほかに、

マイコンからコマンドでTCP,UDPのソケットを開いて通信したりする機能があるようです。へーーーーー。

matoyomi.hatenablog.com

 

 

さて、ここまでで、この基板に期待されていたほとんどの機能をよみがえらせることに成功しました。ついでに、基板に搭載されていたLEDを /sys/class/leds経由で点滅できるようにしました。後、ボタンが二つとおそらく気温測定用のサーミスタがADCに接続されているので、これをちょいちょいいじれば完全に使えるようになると思います。

 

そんな状態Linux Kernelとbuildroot rootfsを作れるbuildrootのリポジトリがこちらになります。

github.com

buildroot 2022.11ベースにdtsとパッチを取り込んで、defconfigを頑張って設定しただけです。

 

適当なlinuxの環境でgit clone して cdし、

$ make akiduki_am3352_defconfig

$ make

(小一時間まつ)

するだけで output/images に sdcard.img が出来上がります。

あれこれ細かいファイルができますが、sdcard.imgに全部入ってるので、
これをdd で書くかWin32DiskImagerとかraspi imager とかでSDカードに書くだけで起動SDが出来上がるはずです(はずです…)

bootcmdは今のところ固定です。変更できません。ぐらい。

それ以上細かいことは、この中をいじればできるようになります。

 

手元ではWSL Ubuntuでビルド成功してます。

ただし、WSLでいきなりやろうとすると、PATHにProgram Filesの空白が入ってて駄目だ、って言われるので、

zenn.dev

この方法でPATHを綺麗にしてからやってください。

なんか気づいたことがあったらgithubの方にください。

buildroot rootに飽きたら、mmcblk0p2のext4Debianのtarでも上書きしたら、Debianが使えてaptできて便利になると思います。

その辺、追々イメージまで含めてやっていければいいですね。誰かが。(は?)

 

あと、debianを入れたり、カーネルモジュールとかをちゃんとコンパイルしてDisplayLinkのUSB-VGAなんかを入れれば、ブラウザで秋月のページを表示したりすることもできるようになりますよん(ただしだいぶ重い)

 

あん?git cloneとかビルドとかわかんない…?

とりあえず、試したいだけの人のための試し用buildrootイメージを置いておきますね。

サービスだよ! SDカードに書くところは頑張ってね!!!

www.dropbox.com

これで、モデムやWi-SUNとの通信、LEDのテストはできます。

(minicom、screenが入ってます)。

 

 

父「父さんな、YouTubeで食っていこうと思うんだ」

というわけではないんですが。

 

少し真面目にYoutubeをやってみようと思ったので少し整備してみました。

雑多に動画が上がっていますが、技術系のものはこんな感じです

 

技術系 - YouTube

 

www.youtube.com

 

”チャンネル登録と高評価ボタンお願いします”

呼び込み君音源カード書き換え機 ソフトウェア編~書き換え成功

honeylab.hatenablog.jp

honeylab.hatenablog.jp

 

前回の記事からの続きです。
前回までで、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に書き込めば、きちんと再生できそう、という確信ができました。

逆変換のコマンドは、

sox  infile.wav  -r 44100 -e oki-adpcm outfile.vox

になります。これで得られたファイルを書き込むためのルーチンを書いていきます。

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が売っているらしいですよ。

 

ドン・キホーテの曲を歌っている方本人出演のPVがありますので、今まで見たことない方はぜひ見てくださいねw

www.youtube.com

Youtubeで検索してmp3に変換して、もともとの音源カードと同じ範囲を切り出します。

切り出せたら先ほどのsoxコマンドで変換します。

チャンネル2には、いつものポポーポポポポを入れる、とことです。

自作プログラムにセットして「Pack」すると、4MBのバイナリファイルが出来上がります。

これを、前の記事でセットアップしたraspberry piに転送し、flashromコマンドで書き込むと…

 

できた!できたよ!ドン・キホーテの音源カードだよ!!!!

 

と息子に持っていくと…反応薄いなw

むしろ、作るって言ってから何日かかったんだよっていう顔してるけどww

 

とはいえ、できたからにはさんざん遊んでくれているようです。

 

 

作っているところ、時々脇で見てましたので、メルカリで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

呼び込み君音源カード書き換え機 第一関門(ハードウェア編)

前回の記事、思ったよりたくさんの人に読んでもらい、面白いと言ってもらったので
調子に乗ってどんどん書いていきます。

 

honeylab.hatenablog.jp

↓いただいてる はてブコメント

b.hatena.ne.jp

前回まででカードからの読み込みと、内部フォーマットの大体の解析ができました。
改めて要求仕様を確認すると

息子「ドン・キホーテの音源カードが欲しい」

ということです。
これを目指すために、純正の音源カードの中身を書き換えることを目指します。

まず、音源カードのオリジナルのICはそれなりに大事なものですので、できれば別の書き込み可能なFlashに書き込み、前ページに書いてあるようなチップ選択方式を使ってスイッチなどで切り替えられれば最高です。

そのために、手持ちのジャンク基板から、同じ方法で読み出せるSPI Flashを外し、
この中に元の音源チップから吸い出したものをそのまま書き込み、このチップから再生できるかどうかということを試すことにしました。

もともと載っているFlashはMicrochip製 SST26VF032B ですが、試しに使ってみたのは全く違うメーカのXT25F128というものです。

基本的なアクセス方法は同じ(互換モード)ですので、単純なREADだけ使っているなら中身は同じように読み出せるはずです。

 

呼び込み君にセットしてみると…再生されません。。残念です。


このようなFlashメモリ、基本的なコマンドは同じですが、上位のコマンドや特性など、専用の機能を使ったりする場合にチップを判別するためのID「JEDEC ID」という3バイトのコードが埋め込まれています。
推測ですが、電源投入直後にこのコードを確認し、違うチップの場合拒絶するか、読み込みエラーとして作業を中断する仕様になっている可能性があります。

呼び込み君のマイコンのSPI端子をロジックアナライザで観察してみると…

Image

確かに最初に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を書き換える手法があり、

typeinf-memo.blogspot.com

そのための専用オープンソースソフトウェア「flashrom」というものがあるのです。

www.flashrom.org


PC自作の人たちがうっかりBIOSファームアップ中に壊してしまったりしたときなど、
チップを取り外して焼き直したりするのに使います。

よし、これならいける。接続はどうしようか…
このような用途では何回も書き換えたりすることが想定されるため、
毎度はんだ付けをするのは骨が折れます。

はんだ付けの例

 

しかし、この音源カードに改めてコネクタを取り付けるような厚み方向への余裕はありません。ポゴピンと呼ばれるような部品を使って開発用治具を作る方法もありますが、

 

なかなかめんどくさそうだなと思いながら、コネクタを眺めていると…何かに似てるな…

Image

 

そう、ICカードのコネクタです。


よくよく計測してみると、パターンの形こそ違いますが、接点中央部の間隔は同じです。また、音源カードの中の基板は、一般的な電子機器の基板厚みである1.6mmより薄く約1mm、つまりこれは中身をカードとして扱えば、ICカードスロットを転用して書き込み治具が作れそうだ!

 

早速部品を探しますが…

こんなもん、その辺で売っているものではありません。

じゃぁ、手持ちにあるジャンクからなにか取り出すか…
携帯用のSIMカードが刺さる奴は…省略版の6ピンか…


ETCカードのスロットは…これもピン省略が多いようだ…

 

うーん…あっ、B-CASカードだ!!!

 

ジャンク箱をひっくり返し、地デジ移行期に配布された安価な地デジチューナを引きずり出しました。

これをばらしてカードスロットを取り外します。Image

 

Image

接点の間隔は同じですが、カード隅からの位置は違うため、適当なカードを切ってスロットに詰め込み、音源カードを差し込んだ時に接点がぴったり合うように加工します。

ロイヤルホームセンターの会員カードに犠牲になってもらいました。

Image Image

カードスロットの端子をRaspberryPiのSPI端子にはんだ付けします。

Image

flashromコマンドを実行すると…認識した!!!これで読み書きができるはず!

 

書き込み装置物理層完成!!!!!

続いて、中身のデータを書き換えるソフトウェア編へ!

 

t.co

このブログにはAmazonアフィリエイトへのリンクが多数埋め込まれています。
そのものを買わなくても、リンク踏んでからしばらくの間に買い物をすると、還元されるようなことを書いてあったようななかったような気がします。大事なお小遣いです。あなたの懐からは持っていきませんのでお買い物前にぜひお立ち寄りください。

なんとアマギフを買ったりしても還元されるのです。びっくり。

 

 

呼び込み君音源カードの技術情報

このブログにはあんまり出てきませんでしたが、私の家には呼び込み君が2体います。

Image

 

世の中にはこの呼び込み君に魂を奪われてしまった人、特に子供が多く、

 

 

どういうわけかうちの息子もその術にはまってしまい

 

日々家の中で呼び込みサウンドが鳴り響いているのです…

 

そんな呼び込み君、仕様についてはまず適当な動画でも見てもらうことにして

基本的な機能としては、音源カードに内蔵された2曲のうちの一曲(もしくは無音)と、録音ボタンを押しながら吹き込んだアナウンス2本のうち一本、を延々とループ再生する機能があります。

呼び込み君の特徴的な「ポポーポポポポ」は、背面に差し込む音源カードに内蔵された曲で、このカードを抜いてしまうと聞くことができません。

 

初期状態のシステムで、子供たちが大好きなドン・キホーテBGMに合わせたアナウンスを再現するためには、録音ボタンを押しながら携帯などでドン・キホーテの曲を流しながらアナウンスを録音する必要があり、結構めんどくさいです。
実際のドン・キホーテの店頭の一部では、特注で製造される専用BGMの入った音源カードを使用しており、これを使うとBGMとは別に単体でアナウンスを録音することができます。

しかし、特注ですから子供たちが簡単に手に入れることはでき…ないはずなんですが、

なぜかメルカリで結構売っているようです…なんで?闇?

そんな子供たちのあこがれ特注BGMカード、うちの息子も絶対に欲しいと言ってききません。かといってこのような闇取引に手を出すのはいかがなものか

というわけで、ドン・キホーテの曲にとどまらず、自分で好きな音源を録音できる音源カードを自作できるようにしてしまえばいいじゃないかプロジェクト~~!

 

↓これはどっかの店で見たAdoの曲と一緒に録音されたアナウンスを再現しようとする息子

 

まずは、既存の音源カードについて調べることにします。

音源カードの中身です



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というソフトを使ってみることにしました。

 


構造体定義を書いていくことで、ファイル全体を構造体として解析できる優れものです。

 

解析を進めていった結果、構造体定義は以下のように書けることがわかりました。

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であれこれ開いていると、ついに正解を見つけました!

全くノイズのない、生のポポーポポポポを手に入れたのです。

 

それを手に入れてもしゃぁないねん。

いや、ここまでわかったということは、これと同じフォーマットでここに自分の好きな音源を書き込んでやれば、好きな音源のカードが作成できる、という技術の裏付けができました。

しかし、このFlashメモリに音源を書き込むためには専用の回路やエンコード用のソフトを作らなければなりません。できるだけ低コストで、さらにユーザーフレンドリーに仕上げるため、設計を進めていきたいと思います。

 

いや、誰が使うねん!!!!!!

 

(※ある程度、少人数ですが需要はあると思います。しかし、部品代、基板製造代、など子供のお小遣いの範囲に納まる気はしません…)

 

書き込み機の作成の記事はこちらです!

honeylab.hatenablog.jp

屋外防犯カメラの電源をエアコンの室外機から横取りするハック

このブログではさんざん分解しているWifi防犯カメラ、特に屋外で使用可能なATOMCam2なんていう便利なものを結構な数持っているにもかかわらず、
実運用しているカメラが1台もないという奇妙な状態が続いていましたが、
運よく引っ越しが完了し、さらに監視対象としての庭や道路がたくさんできました。

そのため、手持ちのカメラを、分解したものを頑張って組み立てながら実運用していこうと思っています。

まずは一台、目の前に信号機のない交差点がある1階の道路に面した軒下にカメラを付けてみようと思いますが…

屋外にカメラを付けるときに、考えなければいけないのは、電源の確保です。

この位置にコンセントはありません。そのため室内から引き出さないといけません。

素直に考えると、いいところにエアコンの室外機がありますので、この配管穴を通して
室内からAC100Vを配線することが簡単そうですが…

実はこの配管、すぐそばの部屋から直接引き出されておらず隣の部屋の収納を経由している上、配線の位置もエアコンの真裏に隠蔽されていて、新たに配管を通すのが面倒です。

ぼんやりと眺めていると、エアコンの室外機にVVFが配線されているのが見えました。
あれ?もしかしてこれはAC100Vが供給されているのでは?と思い、まずは調べてみます。

 

カバーを外してテスターをあてると…おお、AC100V。そしてエアコンの動作状態には関係なく、常時給電されています。これは素晴らしい。

 

この端子からACを取り出し、ACアダプタでカメラに電源を供給することにします。

(残りの1本は通信線らしいです。たまにアースと勘違いしている人がいます)

また、少なくとも私のエアコンで(ダイキン)は常時給電でしたが、そうでない場合は毎度確認する必要があると思います。が、わざわざそこにリレーなどを入れることはあまり考えられないので、多くの場合常時給電だと思われます。

 

※ここから先の作業内容はあくまでも作業ログであり、指南書ではありません。
また、作業の中には電気工事士の資格が必要な工程があります。
類似の作業を行う場合、各人の責任で、安全を確保する必要があります※

 

①電源取り出しケーブルを作ります

 今回の室外機の接続部には端子台が使われ、ACの黒白、信号用の赤に対して2本ずつ接続できるようになっていました。そのため、平型端子を使って取り出しケーブルを作ります。

必要な部材です。

・平型端子

・AC差し込み口

・配線ケーブル(本来、屋外用のタイヤキャブケーブルを使うのが正しいです。しかし、今回露出部が少ないこと、雨が直接かからないことから上記のビニルキャブタイヤケーブルを使用しています。配線後、ビニールテープで巻いて保護することとします。
最低でも安全のため、通常の平型コードを使うのはやめた方がいいと思います。)

 

(1)ケーブルの被覆を取り、圧着端子を付けます。極性は気にしなくていいです。

 

(2)反対側に差し込み口を付けます。中学校の技術家庭のレベルです。

 

②エアコンのコンセントを抜き、白黒線が0Vになることを確認します。

(ブレーカを落とす必要はありません。)

 

③端子台に接続します。くれぐれも、電圧のかかっていない状態を確認してください。

 

④ケーブルを固定します。

 

⑤配管カバーを外し、コンセントを通します。

 

ケーブルは、この辺から通すといいでしょう。

⑥カメラを取り付け、エアコンのコンセントを戻し、カメラの動作確認をします。

 

このような手法で電源を確保することで、
たいへんシンプルに電源を準備することができました。

実際に撮影している画像はこんな感じです。

 

 

設置したカメラは「ATOMCam2」で、わずか5000円程度で防水・暗視機能を持っています。お勧めだけど、それなりに壊れるので、壊れたら買い替える気持ちでいましょう。

 

必ずこの手法で電源が取れるとは限りませんが、自分の持っている設備を
十分に観察し、必要な知識と手順をもって行えば、こんな施工も可能になります。

最後に、この手法で電源が確保できるのは、エアコンの消費電力に対して無視できるほど小さな機器を接続する場合に限ります。ATOMCamはせいぜい5W~10W。エアコンの動作電力は数百ワットですから、ケーブルの許容電流としては十二分に余裕があると考えられます。簡易なLEDタイプのクリスマスイルミネーションぐらいなら問題ないかもしれません。それに反するような、例えばハロゲンライトや電動工具などは絶対に接続してはいけません。そういうことを考えられる人のみ、こういう施工が可能です。

 

 

 

耳コピ支援ソフト ChordTrackerをごにょごにょする

数年前にリリースされ、一部界隈では非常に便利に使用されている

YAMAHA製のChordTrackerというアプリがあります。

 

jp.yamaha.com

 

このアプリは、手持ちのスマホに入っている音楽を解析し、
簡単にコード譜を作成してくれ、耳コピや弾き語りなどを強力に支援してくれるソフトで、私も大変便利に使用しています。

基本的にはスマホ専用のアプリですが、AndroidエミュレータをPCに入れることで、PC上で使用することもできます。


少し前までは自分でピアノを弾いて楽しむだけだったのですが、最近は
nana」という音楽コラボSNSに伴奏として音源をアップロードしたりしています。

nana-music.com

 

そんな便利なChordTrackerですが、一つだけどうしてもできないことがあります。
作成したコード譜を外部にファイルとして出力できないのです。

ごく一部のYAMAHAの電子楽器などに、データを送出することはできるようなのですが、該当楽器を持っていないため、試すことすらできません。

上の動画のように、コードを見ながら練習をする、という用途では十分なのかもしれませんが、この解析結果をもとに、別の楽譜ソフトにコードを打ち込んでアレンジ用の楽譜を作成したりしたい場合、画面を見ながらちまちま手入力する方法しかありません。

 

これは不便!!!

ということで、どうにかこの解析済みデータを取り出すことに挑戦しました。

まずは、純正の機能の、対応楽器への送信部分を解析してみました。

iOS版では、Blutooth-MIDI経由で楽器と接続する、ということなのでBLE-MIDI変換モジュールを購入して試してみました。

 

quiccosound.com

 

この基板を使用してMIDI出力を見ながら「対応楽器への送信」を選択すると、
SystemExclusiveメッセージ「ID Request」が送出されました。

どうやら、対応機種であるかどうかを確認しているようです。
試しに判明しているYAMAHAの電子楽器のIDをいくつか返してみましたが、接続が確立される様子はありませんでした。

 

対応しているという機器はPSR-SX600、SHS-500、SHS-300のわずか3機種、
また、これらの機種のマニュアルを調べてみたのですが、ID Requestに対するResponseが明確に記載されている部分はありませんでした。

さらに、実行バイナリをあれこれ覗いてみたのですが、機種との接続確立後も、なにやらめんどくさそうなプロトコルで通信していそうなため、あきらめることにしました。

 

さて、次の手段です。
このアプリ、ある曲を一度「解析」を行うためには多少時間がかかりますが、
二回目の読み込みからは解析済みのデータを参照しているようですぐにコードが表示されます。
ということは、端末内にキャッシュファイルが保存されているはずです。

これを探すために、Android端末に接続し、アプリからのデータを保存しているはずの場所を探してみましたが、OSの保護機能のため見ることができませんでした。

そこで、root化を試みます。
手元にroot化できるAndroid端末が無いため、ChordTrackerをインストールしたAndroidエミュレータ「BlueStacks」をroot化します。

その結果、/data/data以下のアプリストレージ領域に、解析済みのjsonファイルを発見しました!!!

サンプルの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シンセサイザーなどで使用している定義順になっているようでした。(音楽理論的に、もしかしたらそれが定義されてるのかもしれませんが、私にはよくわかりませんでした。)

 

 

このようにして、解析済みの画面に表示された内容と、jsonファイルを照らし合わせながら内容を解読していきます。

解読ができたら、これをエクスポートします。
界隈で、楽譜の清書によく使われるオープンソースの「MuseScore」というアプリがあります。

musescore.org

 

このソフトで読み込めるように、ソースコードを解析していくと、どうやら普通のSMFに出力してやるのがよさそうだ、という結論になりました。
ソースコードによると、YAMAHA独自のシステムエクスクルーシブのバイナリデータで、タイムスタンプに対してコード情報を付けられるように読めるのですが、どうにもうまくいきません。

仕方がないので、とりあえずは「歌詞」としてコードネームを入れていきます。

変換プログラムはC#で記述しています。

JSONの読み込みはNewtonsoft.json

blog.hiros-dot.net

SMFファイルの書き出しにはdrywetmidiというライブラリを使用しています。

github.com

 

コード名だけを入れると、突然難しいコードで躓くかもしれませんので、
実際に押さえる音符も入れることにします。

コード名(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をここに貼っておきます。

もうちょっと詳しく見たい方はこちらへ。