Closed suzukiplan closed 10 months ago
冗長データ削減を試みてみたが効果としてはイマイチなので、データ構造の最適化がベターかもしれない。
VGS の BGM データは、
struct _NOTE {
unsigned char type;
unsigned char op1;
unsigned char op2;
unsigned char op3;
unsigned int val;
};
という固定長バッファ(8byte)で、以下のような用途で使っている。
かなり最適化余地がある。
まず、type と op1 は合わせて1バイトにできる
bit7〜4 | bit3〜0 |
---|---|
type | op1 |
そして type 毎に可変長にすれば良い。
一番多く出現する type は KEYON と KEYOFF だが、KEYON のサイズは 8 → 3 (0.375)、KEYOFF は 8 → 1 (0.125) に圧縮できるので、全体でおよそ 1/4 程度までデータ圧縮できるのではないかと考えられる。
チャンピオンデータのTH07-16 (少女幻葬 〜 Necro-Fantasy) = 330KB(338,336)を 1/4 に圧縮できれば 83KB(84584)になるので、128KB以下への圧縮が可能。
TH07-16 (少女幻葬 〜 Necro-Fantasy) = 330KB(338,336)を可変データ方式で圧縮してみたところ 150KB(153247)までにしか圧縮されなかった。
miniz で圧縮せずにフラッシュに書き込んで、コードと同じように const データとして直接読むしかなさそうかな。
NTYPE_WAIT を データサイズ毎に NTYPE_WAIT_8 (8ビット), NTYPE_WAIT_16 (16ビット), NTYPE_WAIT_32 (32ビット) に分割してみたところ、TH07-16のサイズが 94KB (95,491) になった。
これならイケる。
TH06, TH07, TH08 の合計サイズは 1,898,985 bytes (約1.8MB) やはり無圧縮状態だと現時点の全曲を RaspberryPi Pico (2MB) に収めるのは厳しいので LZ4 圧縮は必要っぽい。
LZ4 圧縮した場合の TH06, TH07, TH08 の合計サイズは 821,757 bytes (約0.79MB) この圧縮率だと純正 RaspberryPi Pico (2MB) に全曲入れるのは無理かな。 (中国製の互換品の16MBモデルなら問題なく全曲入るが)
幾つかピックアップして固定長(従来方式)、可変長(新方式)、LZ4圧縮(新方式を圧縮)のサイズを調査してみた。
MML | 固定長 | 可変長 | LZ4圧縮 |
---|---|---|---|
TH06-01 | 29,152 | 8,647 | 2,603 |
TH06-10 | 170,472 | 47,881 | 22,310 |
TH07-16 | 338,336 | 95,491 | 37,951 |
TH08-18 | 185,576 | 53,155 | 24,419 |
まだ動くかちゃんとテストしていないがひとまず実装完了したので閉じる
ひとまず、曲再生用に 128KB 確保した状態の RAM と、東方紅魔郷、東方妖々夢、東方永夜抄の3作分の曲データを RaspberryPi Pico(公式)に入れた状態の Flash の占有率は以下のような形。
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM: [===== ] 54.2% (used 142080 bytes from 262144 bytes)
Flash: [===== ] 48.6% (used 1017076 bytes from 2093056 bytes)
VGS の BGM データは内部的に miniz で圧縮されている。
圧縮済みのデータはフラッシュに書き込む(ソース等と同じメモリ領域に展開される)ので中国製のラズパイPico互換機ならプログラム込みで16MBまでデータを格納できる。(※公式のラズパイPicoなら2MB)
ただし、再生時は RAM(最大256KB)へ展開する必要がある。
無圧縮状態のデータをチェックしてみたところ、東方紅魔郷、東方妖々夢、東方永夜抄の3作品の中では、東方妖々夢の TH07-16 (少女幻葬 〜 Necro-Fantasy) が 330KB(338,336)で限界突破している。
当然ながらプログラム側で使いたいRAM領域もあるので、曲データに使用する RAM 領域は最大でも 128KB 以下(できれば 64KB 以下)程度に抑えたいところだが、結構な数のデータが 128KB 上限でも収まりきらない状況である。
データ構造は変更せず MML コンパイルの最適化で必要サイズを圧縮できるのがベター。 それで無理ならデータ構造の変更が必要になりそう。(※おそらく無理と想定している)