doubledepth

bug続き

拙作script、長い小節をものすごく細かく分けようとする長さ500桁を超える配列を初期化しようとする沈黙、みたいな感じで頭の悪さが平常運転だった。対処法を四つ考えた。

  • 長さが1以上になる小節は事前に分割しておく。BMSONなら小節線を足すだけなのでお手軽。かつて図表著者の端くれだった者としては「それはやっちゃ駄目でしょ」という感覚がある。
  • LR2の文字数上限をBMS data配列の長さ上限として定め、notesの座標をその近似値に丸める。これはfail-safeとして用意しておきたいところだけど、丸めた後のmoiréへの対処も問われる。
  • 座標分母を通分せず、channel文を複数行出力する。行合成の責任は他の構文解析器に丸投げ。正直これ自分にしては良い発想だと思うけど、公害をまき散らすような罪悪感もある。
  • ていうかそもそも、最悪でも「拍分解能×4×小節長」で通分すればうまくいくことが保証されてるのに、なんで配列長さ500桁になるんだこのド低能がァーーッ

👐🙄

自分が書いていたscriptに関して。BMSON to BMS変換の際に、長さを持つnotesが存在しない場合、正しく変換できなくなるbugを直した。これから実装しようとしている事柄と全然関係ないbugをざくざく掘り当ててしまう。なかでも「小節線なし」に関するbugが面倒くさそう。 Dead or Arabesque[DP DUBAI]をBMSON化して小節線だけ全部削ってBMS形式に戻そうとしたら永遠に仕事が終わらず「こりゃ駄目だ」ってなった。いちおう“(^^)”とかでtestはしていたけど、全長が短かったからたまたまうまくいっていただけでした。はい終了、しゅ〜りょ〜

BMS Data文字列長が奇数になる行の解釈

自分は以前まったく同じことを調べたはずだが、肝心の調査結果を思い出せなかったので改めて調べた。おおむね三通りの解釈に分かれた。末尾一文字を捨てる実装と、末尾一文字を00に置き換える実装と、行ごと捨てる実装があった。BM98k/nazo/LR2/ruvit/Angolmois/beatoraja/Bemuse/QMS/BMSC/BMSE/uBMplay/BMEV/nBMplay/TechnicalGrooveは、末尾一文字を捨てる。

#title from
#bpm 130
#wav01 a.wav
#00111:0101011
#title to (μBMSC)
#bpm 130
#wav01 a.wav
#00111:01000100010000

iBMSC/μBMSCは面白い例外で、末尾一文字を休符とみなすが、文字列長に対する位置関係が保たれる。たとえば元の文字列長が7の場合、小節は七等分される。

Enclosed Alphanumeric KeysReader Requirementsに、微妙にこの話題に関連する仕様があった。

The reader must not parse the enclosed alphanumeric keys preceded by the incomplete (i.e. one-letter) alphanumeric key in the data section. For example, #00101:abc(de)f is invalid, although #00101:ab(cd)ef is equivalent to #00101:abcdef. The reader should ignore lines with such keys.

これ、「括弧識別子に後続する不正な英数字一文字」に関しては何も規定してないし、Angolmoisは拾える限り拾う感じなので、Sonorousの実装を予想するなら、たとえば以下のBMSであれば識別子AB, CD, (EFG)およびHIによって小節を四等分するか、または最後に00を補って五等分する感じかな。

#00111:abcd(efg)hij

ん〜。まあこれならif文とwhile文しか読み書きできない俺でも実装できそうかな。やるべ。

re
ssless
diオーディ
decコーデック

beatorajaにFLACを実装された方目を付けておられた方に気付いていなかった私、驚かされました。あと私、不覚にも見落としていましたが、OggEnc2の更新と同時期にFLACも更新されていました

EOTD_flac/
Bass_00.flac
Bass_0A.flac
Voice_01.flac
flac.exe
flac -d *.flac

このようなdirectory構成のとき、このようにcommandを指定すれば、WAVに一括decodeできます。ようはoggdecのあれと同じ要領、ですが最近のBMS usersは_decode.batなんて知らないかも。

yassu氏の新作が数日前にreleaseされていたことを知って小躍りしています。地味にencoderが最新!

#SETRANDOMに関する私の理解が誤っていたことに気づいた

BMX2WAVが乱数をGlobal変数ように扱うという知見を得て、もしかしてと思って試したところ、普通に#RANDOM#SETRANDOMを併記できてれてるくずおれてる。最初の#SETRANDOM実装であるFeeling Pomu 2ndからして、両者を併記できた。私はこれらが二者択一であり排他的な記述しか許されないと思い込んでいたが、普通に考えればわざわざそんな処理を書くほうが難しい。

問題は、某command memoが私の誤解に基づいて書かれており、誤解を自覚した以上は可能な限り早急に書き直すべきだということ。なんだけど諸事情あり、暖かくなるまで後回しにする。

BMX2WAVが負数値のscrollingをどう扱うかも確かめた。負数BPM変更はよく分からなかった。Sofa $15 -> $2014#IF 26みたいなやつは、resoundingしまくりのWAVに変換してくれる。以下の例だと後者はMemory Errorが発生する。

#title Negative BPM
#bpm 140
#bpm01 -140
#wav01 kick.wav
#00108:0001
#00111:01010101
#00211:01010101
#title Memory Error
#bpm 140
#bpm01 -70
#wav01 kick.wav
#00108:0001
#00111:01010101
#00211:01010101

負数STOPは、Haloの[rather]とかは、たぶん図表著者の期待通りに変換される。

あとSofa2014を眺めていて思ったけど、Data文のCOLON以降の文字数が奇数になる行がいっぱいある(行番号349, 606, 736, 883, 896, 1522, 2129, 2130, 2131, 2141, 2142, 2143, 2153, 2154, 2155)。拙作scriptは今のところこのへん全部無視してるけど、全無視だとさすがにつらい状況もありそうなので、歴代覇権機種の不正dataの取り扱いを調べることにした。日記に書いておかないと、寝て起きると私のmemoryが揮発しているので…… [追記] 翌日調べて日記にmemoした。

BMX2WAV v2 TEST2(続)

正式にでなくとも超絶分解能も考えていただけるのであれば個人的には本当にありがたいです!

同じタイミングに同じWAVが存在する場合は1つしか鳴らさない設定とかあれば良さそう

#title kick x1
#bpm 130
#wav01 kick.wav

#00111:01
#00115:01
#00211:01
#title kick x2
#bpm 130
#wav01 kick.wav
#wav02 kick.wav
#00111:01
#00115:02
#00211:01

既に一般的なBMS実装と同じように「一つしか鳴らさない」ように変換されているように見えます……

明示的に重複定義されている場合は、演奏時のresoundingで発生しうるnoiseを抑制したり、Fired up#016#033のように音声の音量を変えるなど、何らかの意図があるはずなので、その原則を変える設定は上級者向けになりそう。

if に来た時に行数表示してこのif成立させる?見たいに聞くのはアリか。

#IFに限らず問題が発生した行の番号を出してくれるのは個人的にはありがたいです、恋のしょほうせん -Soft Landing Style-はuser側で1619行目を書き換えない限り変換できないと思われるし、手入力された分岐系BMSは書き間違いが避けられないものと思われるので。ただ、私以外にそういうのをありがたがる人おらん気もします……

特殊なWAVに関しては、私が体験した限りでは32-bit float WAVを他よりは見かけたかな? あとそれで思い出したというか私が思い出すのが遅すぎてごめんなさい案件なんですが、A study of loudness in BMS filesという素晴らしい記事において、Mac/Unix用のBMX2WAVとでもいうべきbms-rendererなるapplicationへの言及があり、ここで32-bit float WAVがちょっぴり出てきました。

特殊WAV関連でもうひとつ、FLACにも私は触れるべきでした。今のところはBMSでは使われそうで使われない少し使われる音声形式ですが(“End of the DayなどがFLAC版を持ちます)、なにせ可逆圧縮(強い絶対に強い)なのでBMSの外ではがんがん使われていますし、Webでももう使えるしBemuseがFLACをsupportするかどうかは不明ですが)、LR2の後継的存在たるbeatorajaも既にFLACをsupportしているので、切っ掛けがあればOgg並みに普及する可能性もありそうです。

BMX2WAV v2 TEST2のtest

うお〜2112を変換したら聴いたことのないpatternが出てきよった! ありがとうございます!

iBMSC/μBMSCという新しめのBMS editorsは、分解能Max Grid Partition10000までのrhythmを正確に扱えます。Max Grid Partitionは大域的な分解能Resolutionとは微妙に異なる概念であり、各小節の(Lane, Channel, Line)ごとに区切られて独立しています。(たとえば、以下のように{
iBMSC/μBMSC safe:
#title 18/19, 22/23, 28/29
#bpm 130
#wav11 kick.wav
#00111:00000000000000000000000000000000000011
#00112:0000000000000000000000000000000000000000000011
#00113:0000000000000000000000000000000000000000000000000000000011
#00202:0.5
#00211:0000000000000000000000000000000000000000000000000000000011
#00212:00000000000000000000000000000000000011
#00213:0000000000000000000000000000000000000000000011

このBMSをiBMSC/μBMSCで開いて保存した後も、BMS code上のrhythmは変化しない。はいずれも10000等分に届いていないので、iBMSC/μBMSCが正しく扱える範囲内に収まる。

iBMSC/μBMSC unsafe
#title lcm(19,23,29)
#bpm 130
#wav11 kick.wav
#00111:00000000000000000000000000000000000011
#00111:0000000000000000000000000000000000000000000011
#00111:0000000000000000000000000000000000000000000000000000000011
#00202:0.5
#00211:0000000000000000000000000000000000000000000000000000000011
#00211:00000000000000000000000000000000000011
#00211:0000000000000000000000000000000000000000000011

iBMSC/μBMSCを経由すると、BMS code上のrhythmが改竄される。このrhythmを正確に記述するためには、Gridを12673等分できる精度が最低限要求される(はず)。

  • 各小節のdata列11番は一行にmergeされ、丸められる。
  • #00111の各notes座標は、小節先頭を0/6337としたとき、6003/6337, 6061/6337, 6118/6337に。
  • #00211の各notes座標は、小節先頭を0/469としたとき、445/469, 449/469, 453/469に。(⁉)

})

これは特殊なrhythmを意図通りに記述したい図表著者にとっては都合が良い仕組みですが、全座標を同一平面上に投げ込まざるを得ない形式(E.g. BMSON)とは相容れないBMSになりがち。とはいえこのような発狂分解能も変換はできたほうが嬉しくて、というのは図表ごとに微妙にarrangementを異にするBlackcityのようなBMSが、発狂分解能でしか聴けないsolo partを持っていたりするのです……

別のBMSも試しました。通常難易度表収録曲SCARLET ZONEには、存在しないfilesが定義されています(#WAV677I, H0HH, I6IO, JVJW)。それらを整理したのちWAVに変換すると、IEEE Float 32-bit WAVによってerrorが発生します。Users側がsynthsub_main - Marker #[10-14].wavを予め普通の形式に変換しておけば、BMX2WAVは無事に働いてくれます。このような特殊なWAVを持つ作例が他にどの程度存在するものか、あいにく私は知りません。誰か自信ニキ……

歓喜の歌、こういうのはBMX2WAVの面目躍如という感じ。重複行(68–69行目の#00102#00113238–241行目の#127#128)を消すと変換できます。他にもいくつか同種のBMSがあって、ひとつは王宮のロンド、これは普通に変換できました。もうひとつふたつ、なんか、なんだっけ、voice sample一個を1295等分に切り刻んで数秒で全部鳴らして元通りに聴こえます的なBMSがあったような。そちらは思い出せず未検証ですが、BMS codeに誤りがなければ普通に変換できるはず。

[追記] ぼんやり探したら出てきた。量子化BMSという記事が詳しいです。BMS自体は旧版BMX2WAVでも変換できていた模様。

負数BPM系ではSofa $15 -> $1続編が2014年にreleaseされておりまして、WAV化して聴き込みたい方は要望を出されてはいかがでしょう。私はべつにいいです。未検証です、すみません……

HeruHELLCHARGE NOTESとかいう加齢に抗えなかった感じの命名すき

Firefox 64の自動更新が降ってきて、これを適用している最中にAntivirus softwareが頑張り出した結果、どうやら良くないtimingで処理が競合してしまったらしく、Firefox再起動後に永遠にv64への自動更新が繰り返される状態に陥った。仕方なくFirefoxをuninstallして再びinstallしたところ、履歴やbookmarkの一部が壊れてしまい、自分のwebpageさえsuggestされなくなってしまった。またか〜

BMX2WAV v2 TEST2版)が出ていた、ことについさっき気付いたうえまたもやAntivirus先生が疑い始めたので本日のtestはお休み。歴代覇権機種(unofficial nazobmplay Lunatic Rave 2 beatoraja/Bemuse/QMS)がいずれも「分岐の入れ子は存在しない」と決め付けてかかっていた気がするので、既定では“not nest if”がcheckedのほうが良いかもしれないです。

BMX2WAV v2 test続き

#ENDRANDOM正式対応予定ありがとうございます。これで!!DataErr0r!!.bmsとかも変換できるかな、と思いきや、46805行目のDataErr0rや、最後の余計な#ENDIFや、fileが存在しない#WAVYWのせいで無理でした。機械的に出力したdataに対してわざわざerrorsを取って付けた感あるので、そういうのはべつに変換できなくていいんじゃねって思いますが、それはさておき#ENDIFの当てにならなさよ……

時間がなくて全然testできてない。すみません。あと私信ですがありがとうございました>ボス

BMX2WAV version 2 series Core TEST x64 []

体感で旧版の四倍は速い! 当環境ではAlcubierre Drive11.81秒で変換できた。

#title E.g.1
#bpm 130
#wav01 a.wav
#00111:01
#00111:00

PAL,36Netzwerkgenen2112はdata文が合成されることを前提として書かれているので、E.g.1は変換できたほうが嬉しい。Kikuchan氏版BM98kHelp fileには、data文の合成に関する解説がある。これがBMSの基本仕様に含まれるものなのか、Urao Yane氏版のBM98を知らない私には判断しかねるけれども。

#ENDIFを持たない#IFは変換されない。G2R2018出展作品では【Freak《Show】Down》_whatsmeanbpm.bmlなどが該当する。私は寛容なparserを書くことに挫折した身なので何ともいえない。

#title E.g.2
#bpm 130
#wav01 a.wav
#random 1
#if 1
#00111:01
#endif
#endrandom
#random 1
#if 1
#00211:01
#endif
#endrandom

nanasigrooveは#RANDOMを47回以上繰り返すと強制終了する。これに対処するには各#RANDOM区間を#ENDRANDOMで閉じていく必要がある。閉じると「ヘッダ重複だお」と怒られる。そんなー

BMX2WAV v2は入れ子の分岐を変換できる。100重の入れ子分岐の場合、#ENDRANDOM/ENDRANDOMなどに置換し、#RANDOM 2#SETRANDOM 2に置換すれば、図表著者の期待通りに“One, Zero, Zero”が鳴らされる。ということは、E.g.1の合成data文さえ許容されれば、BMX2WAV v2は“オートメーション工場”を正しく解釈できる数少ないapplicationsのうちのひとつということに。

BMX2WAV test version

ついに64-bit版BMX2WAVが公開されました! 私はつい先ほど気付いたばかりでまだtestできてないのですが(何か調べ始めてしまったAntivirus softwareの許しを得るまで待たなければなりません……G2R2018作品群を聴き込んでimpressionに役立てたい皆さんはぜひ試されてみてはいかがでしょうか! あと30分くらいで、impression期間、締め切られますけれども!

"up":true LongNotes are not Layerable

beatoraja 0.6.4時点では(0.6.6時点でも)、終端定義を重ねても鳴る音は最後のひとつのみ。

{"version": "1.0.0",
"info": {
"title": "v_f.wav is 🎶",
"init_bpm": 140,
"ln_type": 2,
"mode_hint": "beat-7k",
"resolution": 2
},
"sound_channels": [
{
"name": "kick.wav",
"notes": [
{"l": 1, "x": 1, "y": 8},
{"l": 1, "x": 1, "y": 10}]},
{
"name": "ohh.wav",
"notes": [
{"up": true, "x": 1, "y":9},
{"up": true, "x": 1, "y":11}]},
{
"name": "v_f.wav",
"notes": [
{"up": true, "x": 1, "y":9},
{"up": true, "x": 1, "y":11}]}
]}
{"version": "1.0.0",
"info": {
"title": "ohh.wav is 🎶",
"init_bpm": 140,
"ln_type": 2,
"mode_hint": "beat-7k",
"resolution": 2
},
"sound_channels": [
{
"name": "kick.wav",
"notes": [
{"l": 1, "x": 1, "y": 8},
{"l": 1, "x": 1, "y": 10}]},
{
"name": "v_f.wav",
"notes": [
{"up": true, "x": 1, "y":9},
{"up": true, "x": 1, "y":11}]},
{
"name": "ohh.wav",
"notes": [
{"up": true, "x": 1, "y":9},
{"up": true, "x": 1, "y":11}]}
]}

終端定義がLayerableであるべきかどうかは私にはわからない。

わからないbugを直したが腰がぶっ壊れたので休みます

問題のJavaScript codeは以下のような感じ。
var a = [
    "#WAV(11) kick.ogg",
    "#WAV(12) |><\"?*:/\\1",
    "#WAV(13) |><\"?*:/\\2"
];
var r = "|><\"?*:/\\";
var x = /^#WAV\((\d+)\) \|><\u0022\?\*:\/\\(\d+)$/;
var t1;
var t2;
var t3;
var l = a.length;
var i = 0;
while (i < l) {
    if (x.test(a[i])) {
        t1 = x.exec(a[i]);
        t2 = t1[2];
        t3 = ("0" + (Number(t2).toString(36))).slice(-2).toUpperCase();
        WScript.echo(a[i].replace(t2, t3).replace(r, "C-"));
    }
    i += 1;
}
// #WAV(012) C-1
// #WAV(13) C-02

一回目の置換結果のみ、不思議な位置に"0"が挿入される。私の環境ではWindows Script Hostに限らずBlinkでもEdgeHTMLでもGeckoでもTridentでもOSを問わず同じ結果になる。なら間違っているのは私のほうだ。しかし何が間違いなのか分からない。RegExp.exec()String.replace()を使うのをやめて、それらの代わりにString.split()を使うようにしたところ、この現象は解消された。

日記を更新した後に即座に間違いに気付いた。偏差値40以上の人生は俺には完璧に関係ない感じある

_wsh_bms2bmson.js v0.2.0

  • BMSON形式からBMS形式への、BMS-on記法による擬似的な)変換をsupportした。
  • 定義されたBMS-onが別の#WAV定義に上書きされると変になるのを修正した。
  • いくつかのあまり知られていないBMS tagsをsupportした。値を右から左に渡すだけ。
そろそろ文書を整備しないと私自身が混乱に陥りそうなので、数日中にどうにかします。

G2R2018開催期間中に間に合わせたく急いだため、細かい箇所の煮詰めが足りていません。たとえばBMSON仕様のlayer画像における透過部分は、BMS形式に合わせて黒で塗りつぶす必要が本来ありますが、いまのところそこまで手が回っていません。そのへんは今後の予定ということでご了承をば。

BMSON固有の仕様には追従しきれないので、あくまで一方向の擬似的な変換にとどまります。

#WAVZY 00ZZ.wav
#WAVZZ 0100.wav
#EXT #WAV(100) 0101.wav
#EXT #WAV(101) 0102.wav

#99902:0.0125
#EXT #(1000)02:0.0125
#EXT #(1001)01:00(1CS)00ZZ
#EXT #(1001)02:0.0125

BMS仕様の範囲を超える部分に関しては、前述の例のようにSonorous提案Enclosed Alphanumeric Keys仕様(非公式日本語訳)とBemuse提案Extension Lines仕様を組み合わせて無理矢理に体裁を整えています。問題は拙作変換器がReader要件を満たしていないことですが、これも今後の課題とします。

Layered Notesは全部BGMに回しています。beatoraja拡張"up"は変換できそうだけど、それをするとbeatoraja/HDX/BMIIDXView以外で困るんじゃないかな〜。BGMの並びが汚くなるのは、どうにかできるなら改善したいけど、難しそう。

ここまでやるなら実際に音声の裁断もできるといいんですけど、それは今の私には難しいうえに、素晴らしい音切り専用softwaresが既に存在するので、あんまりやる気ないです。

BMSON関連の備忘録

[KEY vs. BGM] …… "y"が同じならBGM側のnoteを捨てなければならない(must):
{"name": "a.wav", "notes": [
    {"x": 1, "y": 960},
    {"x": 0, "y": 960}
]}
[CONTINUE vs. RESTART] …… "y"が同じならすべて"c":falseとして扱うべき(should):
{"name": "a.wav", "notes": [
    {"c": false, "x": 8, "y": 480}
    {"c":  true, "x": 1, "y": 960},
    {"c": false, "x": 5, "y": 960}
]}
[RESTART vs. RESTART] …… “Each slice only has a polyphony of 1.”
{"name": "a.wav", "notes": [
    {"x": 1, "y": 960},
    {"x": 5, "y": 960}
]}

同一channel内で同一の"y"を持つnotesを何個並べても、音声は一個しか鳴らされない。である以上、最後の例は私には[KEY vs. BGM]と同種の「訂正されるべき誤り」に見える。とはいえBMSON仕様はこのような状況を禁止しないし、playableなBMSON実装もこれを許容している(いくつかの発音処理はうまくいかないようだけど)。BmsONEは最後方のひとつを残して他を捨てる。

図表編集の都合もあるだろうBmsONEはともかく、変換を目的とするscriptがMagic pianoのような図表を再現できないのは問題かもしれない。問題……問題?

なんとなく捗った

使わないが構文解析だけしていた#VIDEODLYを、一年以上#VIDEODRYと書き間違えていたことに今更気がついた。対応ついでに数日中に修正するつもりだけど今日は寝る。

BMSの不可視notesや地雷notesを、BMSONでこんな感じに書きたい:

"sound_channels": [{
  "name": "a.wav",
  "notes": [
    {"x": 1, "y": 120, "l": 100, "c": false},
    {"x": 1, "y": 240, "hidden": true},
    {"x": 1, "y": 480, "damage": 0.5}
  ]
}]

BMSON仕様v1.0.0に準拠する実装はこれらを通常のnotesと区別できないので、この方法は使えない。それならそれで"hidden_channels"のような独自keysに出し分けておき、myParser内部ではObject.assign()とか[].concat()みたいな形で一緒くたにして取り扱えばよろしいがな。そうしよ。

BMSE非公式Helpを更新した

先月末の日記で読み仮名を参照したとき、そういえばWinampとかHTTPS化してたなあ、と思い出してcheckしてみたら他にもいろいろなURIが変わりまくっていて、けっこう忙しかった。以前は無料で読めたはずの記事が会員制に変わっていたり、まさに隔世の感。

  • EPUBCheck 4.1.0がreleaseされていた。二年振り。
  • WinMerge日本語版2.16.0+-jp-1がreleaseされていた。Yahoo! GeoCitiesから移転。
  • Pandoc 2.5もreleaseされているなあ……

日記

BMS関連

拙作BMS
bubble / hitkey
二次配布BMS
ノイズの海と鯨 / moka
PARTY TIME IN MY DREAM / HAIJI
BMSE非公式ヘルプ
Lite
Lite-online
Full
Full-online
buglist
iBMSC
Web (Japanese version)
issues
BMS差分
a­nal­gam
boléro
Ketch­up
quovadis
SELF
yellows
Do not use non-ascii filenames
雑多なメモ
bmsplayer data
bms benchmark
Secrets - Feeling Pomu 2nd
grid2sec
bmx2xxx
BMx Outliner
BMS command memo
BMS command memo (Japanese version)
BMS EVENT LITE
#RANDOM BMS list
BMS #OPTION command
BMS Bitmap test
Extended BPM
STOP Sequence
BMS Edge Cases
BMS extensions proposed by Sonorous (unofficial Japanese version)
BMS 2.0 (unofficial Japanese version)
BMS Editors
Do not use non-ascii filenames
BM98 Kikuchan Version 3.30 Revision #4.2
BMSON Checker
_wsh_bms2bmson.js

その他

HTML関連メモ
Dakuten on HTML
nest1000
EVS
Nervous Cascading
Source Han Sans test
User-Agent String
CSS Logical Properties