Skip to content

測定プロトコル ​

機体を測定する順序です。各段階は前の段階が書いたファイルを見て対象を決めるので、順序は便宜ではなく手法の一部です。順序を外して走らせた段階は、このアーカイブが記述できないものを測ることになります。

2 台の機体を比べる主張は、どちらもこの方法で測定してあることの上に成り立っています。違う方法で測定した機体も、それ単体としてなら記述できますが、比較には参加できません。

どの段階よりも前に ​

すべてのコマンドは、何かを書き込む前に MIDI 経路を検証します。自己診断は単独で先に走らせてください。そうすれば、失敗したときに「たまたま走らせていた段階の失敗」ではなく「経路の失敗」として読めます。

sh
rye run soundings selftest --audio "<audio interface>"

自己診断に通ったことが示すのは、ハーネスが機体を読めることだけです。その機体を安全に調べられることまでは示しません。すべての段階に共通して、制約が 2 つあります。

  • 一括要求は 64 バイト以下に保つ。 これを超える要求で、機体が応答を完全に停止することが実測されています。復帰には電源の入れ直しが必要です。
  • 応答すると分かっているアドレスを定期的に読む。 応答しなくなった機体は、アドレスが 1 つも存在しない空間として読めてしまいます。無応答を不在として扱う探索は、何も測らないまま正常終了します。

その走行がどの空間に向けられているか ​

3 バイトのアドレスは、それだけでは何も指しません。何を指すかを決めるのは、それが送られるモデル ID であり、機体は複数のモデル ID に応答しうるものです。 このアーカイブにある 1 台は、表示ブロックだけが、残りの部分が住んでいる空間の外にあります。モデル ID ごとに別のアドレス空間があり、2 つの空間に現れる同じ 3 バイトは、2 つの別のパラメータです。

sh
rye run soundings --model-id 0x45 read "10 00 00"

--port や --device-id と同じく、サブコマンドより前に置きます。ある段階が何をするかではなく、その走行が何に向けられているかを述べるものだからです。既定は GS です。

ある族に属する知識を必要としない段階だけが、GS 以外の値を受け取ります。 sweep、boundary、offsets、power-on、write-probe、window-probe、hold-probe、そして見るだけの 2 つのコマンドです。それ以外は拒み、その旨を述べます。送っているものが、ある族に固有のものだからです — リセットのメッセージ、効果の固定アドレス、バンクとプログラムの約束事。別の空間に送れば、それらのバイトがそこで意味する何かに対する書き込みになり、走行はその答えを測定として読み戻すことになります。

すべての記録は、装置 ID の隣に、問い合わせたモデル ID を持ちます。この欄が存在する前に書かれた記録は持ちませんが、それは不明ではありません。この旗が存在するまで、ここにあるどのコードも GS 以外のモデル ID を送れませんでした。

経路の証明は、探索しようとしている空間ではなく、調査用アドレスが応答すると分かっている空間で行います。何も応答しない空間は、その段階が報告すべき知見であって、自己診断が段階の開始を拒む理由ではありません。ですから selftest は、第 2 の空間を意図して証明するための --probe を取ります。

段階 ​

1. 識別 ​

sh
rye run soundings identity

Identity Request に対して機体が返すものを記録します。返答は、背面の定格表示、測定経路、機体側の設定とともに、そのまま meta.json へ入ります。以降に測定するものはすべて、この記録が示す範囲についてのものになります。

2. アドレスマップ ​

sh
rye run soundings sweep --out data/units/<unit-id>/sweep/whole-map.json

どのアドレスが応答するかを機体に問い合わせます。このマップは文書が並べているものではなく機体が答えたもので、以降の段階はこれを見て対象を決めます。

スイープは各ブロックの下位バイトを、指定した値についてだけ読みます。ですからブロックの開始位置が、読んだ場所にあるときにだけ見つかります。ここで得られるのはブロックの一覧であって、アドレスの一覧ではありません。 後者として読むと、これを元にするすべての段階に穴が空きます。アドレスの一覧に変えるのは段階 3 です。

3. オフセットと、そこに現れる形状 ​

sh
rye run soundings offsets "40 10 00:128" ... --canary <addr> \
  --resume --out data/units/<unit-id>/offsets/whole-map.json

スイープが見つけたブロックについて、その全オフセットを 1 バイト読みで読み出します。領域の末尾から前へ進む読み方だと、最初に応答しないアドレスで止まってしまうので、無応答の向こう側にある、応答するアドレスの連なりが見えません。全オフセットを読むことだけが、それを見つけます。

応答したオフセットの集合が一致するブロックは、同じ形状です。アドレス空間は繰り返し構造を持ちます。この方法で最初に測った機体では、461 ブロックが 12 種類の形状に収まり、そのうち 1 つは 204 回現れました。これ以降のすべての段階は、形状ごとに 1 つの代表ブロックを対象にし、網羅率を形状に対する分数で報告します。全ブロックを測るのは同じものを繰り返し測ることで、そこから出る数字は「どれだけ分かったか」を何も語りません。

形状をまとめられるかどうかは、仮定せずに測定します。代表のほかに、同じ形状のブロックをもう 1 つ読み出して、一致を記録します。両者が食い違えば形状の切り方が間違っていたということなので、そのときは分けます。

読み出ししか送らないので、電源投入時の状態を取得するより前に置きます。 書き込みを行う段階の後ろに置くと、その取得の機会を失います。取得はやり直せません。

4. 以降の各段階が見張る集合 ​

sh
rye run soundings watch-set data/units/<unit-id> \
  --out data/units/<unit-id>/watch-set/reachable.json
rye run soundings watch-set data/units/<unit-id> --keep-windows \
  --out data/units/<unit-id>/watch-set/with-windows.json
rye run soundings watch-set data/units/<unit-id> --one-at-a-time \
  --out data/units/<unit-id>/watch-set/one-at-a-time.json

機体ではなく記録に問い合わせます。ここから先の段階はすべて --map を取り、その地図が、その段階の出すあらゆる否定的所見の範囲を決めます。どの地図を渡したかは、その記録が何を意味するかの一部です。

これは 2 種類の読みの合併であり、そうでなければなりません。どちらも他方を含まないからです。 領域読みは連続したアドレスに 1 つの返答を返し、単体で問うと何も答えないアドレスに届きます。単体読みは 1 アドレスを問い、どの領域も始まっていない場所から始まるアドレスに届きます——段階 3 が見つけるのはこれです。片方だけを渡すと、メッセージが「誰も見ていない場所」に着地でき、記録は「どこにも保存されない」と言います。この方法で最初に測った機体では、スイープの地図は応答するアドレスを 3,650 個取りこぼしており、5 つの段階がそれを狙って走った後で気づきました。

窓と判定されたブロックは外します。そこに着地した値は、窓が指している記憶領域に着地し、その記憶領域はすでに見張られているからです。--keep-windows は戻します——メッセージの行き先ではなく、各アドレスが保持していた値を捕捉する用途です。--one-at-a-time は単体読みが答えるものだけを、1 アドレス 1 領域で持ちます。単体読みへの返答は、問うたアドレスについて答えるか、何も答えないかのどちらかなので、バイトが 1 つ下のアドレスに載ることが原理的に起きません。

領域読みに対して先頭 1 バイトしか返さないと、その機体の記録が名指ししているブロックは、地図の他の部分をどう問うかに関わらず、1 アドレスずつで入れます。 どのブロックがそれかは記録から読み、コードのどこにも持ちません。そう答えるのは 1 台の機体の答えであり、ビルダーの隣に置いた一覧は、次の機体にはその機体についての仮定として届くからです。地図自身が、どのブロックをそう扱ったかを述べます。

ここには測定は 1 つもなく、ファイル自身がそう述べます。元の記録が変われば作り直すもので、その元も名指しします。ですから、あるブロックの答え方について何かが分かった段階は、次に走る前に地図を作り直します。このコマンドは機体を取らず、占有もしないので、実機が別の作業で塞がっている間にも作り直せます。

5. 電源投入時の状態 ​

sh
rye run soundings power-on --map data/units/<unit-id>/watch-set/with-windows.json \
  --unit-id <unit-id> --out data/units/<unit-id>/power-on/regions.json
rye run soundings power-on --map data/units/<unit-id>/watch-set/one-at-a-time.json \
  --unit-id <unit-id> --out data/units/<unit-id>/power-on/one-at-a-time.json

空間を 2 度読み出し、何も書き込みません。得られるのは、電源を入れた直後に機体が置かれている状態です。

1 回の電源再投入で、2 通りとも取ります。届くアドレスが違うからです。 領域読みは単体読みが答えないアドレスに届き、単体読みは短い返答が取り違えるアドレスを正しく取ります。ある機体は 32 バイトの要求に 30 バイトを返します——再現し、チェックサムも通ります。しかも省かれる 2 つは、同じブロックをオフセットごとに問うたときに無応答になる 2 つとは別です。そういう返答は要求したアドレス列に敷けないので、敷かずに拒否し、「短く答えた領域」として記録します。基準値は 2 つの捕捉の合併で、soundings complete もそう数えます。

要求した長さで返ってきた返答が、中身を 1 バイトしか持たないことがあります。 同じ機体の 2 ブロックは、領域読みに対して、要求と同じ長さでチェックサムも通る返答を返します。ただし中身は先頭アドレスの値だけで、それ以降は全バイトが 00 です。一方、同じブロックの 128 オフセットを 1 つずつ問うと、どれも自分のオフセットを答えます。長さ 2 から 64 までどれでも同じで、隣のブロックはその全部を完全に返します。ですからこの 2 ブロックの領域読みは、どこから始めてもちょうど 1 アドレスにしか届きません。短い返答を拒めるのは長さが合わないからなので、この返答は何にも拒まれず、全バイトが値として公開されます。しかも領域の先頭バイトがもともと 00 の場所では、見えるものが何もありません。これを見えるようにするのは、実行ではなく突き合わせです。領域読みの取得が持つ全値を、同じアドレスの 1 バイト読みに当ててください。この機体では 37240 アドレスがそれに当たり、220 が食い違い、その 220 すべてが同じ 2 ブロックの中にあります。

この突き合わせは、後続の段階がどちらかの取得に依拠するより前に行ってください。 あるリセット調査は、基準値を領域読みから取り、目印は 1 バイト読みに対して選びました。その結果、そこで打刻した 224 アドレスのうち 220 で、基準値と同じ値を書き込んでいます。3 つのリセットはそのすべてについて「戻した」と答えましたが、それはその比較が返せる唯一の答えです。

書き込みを行う段階より前に走らせられる、最後の段階です。 段階 1 から 4 は読み出ししか送らないか、何も送りません。ですからその後に取得しても電源投入時の状態のままです。段階 6 以降は機体へ書き込むので、そこから先は次に電源を入れ直すまで取得できません。マップはスイープをやり直せば作れますが、この取得はやり直せません。

この実行は、電源を入れた直後の機体と、以前の実行が書き込んだ後の機体とを区別できません。どちらも読み出しに対して同じように答えるからです。ですから記録するのは「実行前に何をしたか」という測定者の申告であり、それを申告だと明示したうえで、この実行自身が言えること——自分では何も書いていないこと——を併記します。

2 回の読み出しが食い違ったアドレスは、決着させずに一覧として残します。どちらかに決めるには 3 度目の読み出しが必要で、しかも間違った決め方をしても後から見えません。そのバイトは、次にこの取得と比較されるリセットが書き換えたもの、として読めてしまいます。以降のリセット測定はすべて、このファイルと比較します。

6. 窓 ​

sh
rye run soundings window-probe --stores <addr> <addr> <candidate>...

自分の値を保持しているブロックと、別のブロックの値を見せているだけのブロックを見分けます。アドレスが何を保持しているかを解釈する段階より前に走らせます。窓は、書き込んで読み戻す方法では本物の記憶領域と区別できないからです。書き込みが窓の行き先を決め、読み出しがそれに従うので、そのアドレスは与えたとおりの値を答えます。

窓と判定したブロックは、それを記述する記録の中で名指しし、以降の段階からは除外します。除外しないと、同じ記憶領域を、その素性が残らない名前で何度も測ることになります。

7. 受け付ける値 ​

sh
rye run soundings write-probe --map data/units/<unit-id>/watch-set/reachable.json \
  --resume --out data/units/<unit-id>/write-probe/whole-map.json

各バイトを単独で書いて読み戻し、そのアドレスが何を受け付け、何を丸め、何を拒否するかを記録して、元に戻します。領域は終わった順に書き出すので、中断した実行は最後に完了した領域から再開できます。

1 バイト読みに応答しないアドレスへは書き込みません。元に戻すべき値が存在しないからです。それらは skipped として記録します。そのうちどれが未定義で、どれが「もっと大きなブロックとしてしか読めない」ものなのかは、この段階では決着しません。

8. 独立した記憶領域 ​

sh
rye run soundings hold-probe --map data/units/<unit-id>/watch-set/reachable.json \
  --out data/units/<unit-id>/hold-probe/whole-map.json

隣り合うアドレスへ異なる値を与えてから、途中で 1 つも読まずに、まとめて全部を読み戻します。こうすると、1 つのセルに支えられた連続アドレスと、それぞれが別のセルである連続アドレスを分けられます。この順序そのものが手法です。書きと読みを分ければ、近くへ最後に書かれた値しか見せないアドレスはその 1 つの値を答え、独立したアドレスはそれぞれ自分の値を答えます。

この段階は、別のブロックを映しているブロックを見つけません。それは段階 5 が調べることです。

9. エイリアス ​

sh
rye run soundings alias-scan --map data/units/<unit-id>/watch-set/reachable.json \
  --kind cc --out data/units/<unit-id>/alias-scan/cc-ch1.json

ある系列のメッセージを 1 つずつ送り、その前後でアドレス空間を比べて、メッセージが届く先を特定します。系列ごとに 1 回ずつ走らせます。cc、nrpn、rpn、channel、drum-nrpn、そして SysEx による書き込みの address です。

マップ全域を監視してください。 --prefix の既定はそうなっています。1 つのブロックに限定した走査は、そこで得られる「見つからなかった」という所見のすべてを、そのブロックの中だけの話に閉じ込めます。「このメッセージはどこにも保存されない」という記録が、「見た範囲のどこにも」という意味に変わってしまいます。

--kind address は、先に走らせた走査が到達を確認したアドレスへ書き込み、その場所に 3 つめの入口があるかどうかを調べます。書き込み先は、その機体自身の記録から取ります。

sh
rye run soundings alias-scan --map data/units/<unit-id>/watch-set/reachable.json \
  --kind address --addresses-from data/units/<unit-id>/alias-scan/cc-ch1.json \
  --out data/units/<unit-id>/alias-scan/sysex-ch1.json

10. リセット ​

sh
rye run soundings reset-probe --baseline data/units/<unit-id>/power-on/one-at-a-time.json \
  --map data/units/<unit-id>/watch-set/reachable.json \
  --write-probe data/units/<unit-id>/write-probe/whole-map.json \
  --out data/units/<unit-id>/reset-probe/whole-map.json

各リセットの前に状態を崩し、後で空間を読みます。こうすると、文書がリセットについて述べていることではなく、そのリセットが実際に戻すものを測定できます。目印とは「そのアドレスがいま保持していない値」で、ライトプローブがそのアドレスについて実測した受理値から選びます。これを「どんな値でも受け付けるアドレス」と読むと、範囲を持つバイトがまるごと外れます——そして範囲を持つバイトこそ、文書が機能を与えている側です。何でも受け取るバイトは、たいてい誰も定義していないバイトなので。1 値しか受け取らないと実測されたバイトには目印が存在しないので外します。保持している値を書いても何も崩れず、リセットが手を触れなかった場合に「戻した」と読めてしまうからです。

すべてのリセットは、同じリセットを先に送ってから走らせます。そうすることで、結果どうしを比べられます。先に送らないと、それぞれの結果を「直前のリセットがたまたま残した状態」を基準に読むことになります。

11. 音色とエフェクト ​

sh
rye run soundings tone-map --out data/units/<unit-id>/tone-map/map-select-0.json
rye run soundings efx-map --out data/units/<unit-id>/efx-map/types.json

各音色と各インサーションエフェクトを要求し、受け付けられたかどうかを読み戻します。走査の前に間引きを行ったマップは、その間引きを但し書きとして持ちます。--exhaustive は全バンクに 128 プログラムすべてを問い合わせるもので、但し書きの付かない唯一の形式です。

12. 再現性——音を比べる前に必ず ​

sh
rye run soundings repeat --audio "<audio interface>" \
  --out data/units/<unit-id>/repeat/program-0.json

同じテスト音を 2 回鳴らし、2 つのテイクがどれだけ一致するかを測定します。この数値が、以降のあらゆる差分測定の検出下限になります。検出下限を下回る領域では、「差がない」と「差を見分ける解像度がない」は同じ読みになります。

検出下限は機体と測定経路の両方の性質なので、機体ごとに測定し、経路を変えたときは測り直します。

13. 音の変化 ​

sh
rye run soundings contrast --cc 91 --audio "<audio interface>" \
  --out data/units/<unit-id>/contrast/cc-91.json

1 つのパラメータの 2 つの設定を、再現性の検出下限を基準に比べます。こうすると、機体が値を保持しているパラメータと、それを通して実際に音が変わるパラメータを分けられます。値は保持しているのに音が変わらないパラメータは、実際に存在します。アドレス空間側の段階ではその区別がつきませんが、この段階ではつきます。

transfer、motion、decay、phase、vibrato はそれぞれ、アナログ経路、時間とともに変化するエフェクト、エフェクトの減衰、エフェクトが各帯域の位相を回した角度、そしてテイクのピッチが変調されていたかどうかを測定します。balance、balance-bands、arrival は、片方のチャンネルではなくステレオの対を読みます。パラメータが 2 チャンネル間のレベル差に与えた影響、帯域ごとの分離に与えた影響、そしてテイクの早い区間が持つものと遅い区間が持つものへの影響です。transfer 以外はテイクを読むだけなので、機体の接続を必要としません。

motion が読むのは、変調されたディレイだけです。 その陽性対照はミリ秒の振れを注入するので、変調器がレベルやパンを動かす型では通りようがなく、最初から通り得ません — そこで返る「差はない」は正しく、その型については何も述べていません。そういう型を読むのが efx-sway です。テイク自身のレベルと、テイク自身のチャンネル間の差を追い、vibrato がそう読まれるのと同じ理由で 1 テイクの中で読み、変調していたもののレートと深さ、そして 1 周期分を平均した波形を報告します。その波形が印刷されたどの形に当たるかは documents/ との突き合わせであり、記録の中では行いません。

片方のチャンネルだけで行う比較は、もう片方を動かしたパラメータを見られません。広帯域のレベルだけで行う比較は、レベルを変えずに片方のチャンネルの形だけを変えたパラメータを見られません。ですからこの段階が返す「差はない」は、3 つのうちどれで問うたかまで含めて 1 つの意味になります。

全フレームを等しく重み付けする読みは、間違ったフレームに自分を明け渡します。 ピッチ推定はときどき音を見失い — コムのノッチが追っていた倍音を奪う、あるいはオクターブ外れに着地する — 数フレーム後に戻ってきます。そのフレームは、他は 1 セントの精度で安定しているトラックの上で、隣から何百セントも離れた場所に座ります。そして vibrato の 2 つの手順は、それを満額で数えていました。全フレームに対する最小二乗の 3 次トレンドと、全フレームを正弦へ射影して読む深さです。どちらも外れ値という概念を持たないので、見失ったフレームの連なりが変調を多数決で上回りました。トレンドはいま、トラック自身の中央部分にあるフレームで当てます。深さは、トラックの 5 パーセンタイルと 95 パーセンタイルの間の振れです。

それが何セント分の価値だったか。あるパートレベルのビブラート設定の 4 テイクは、旧い読みでは 112.72、147.97、102.83、233.31 セントと出ていたものが、この読みでは 80.89、80.14、80.84、80.91 と出ます。そして注入した対照がそれらの記録で到達する最も浅い深さは、50 セントから 3 セントへ下がりました。

対照が通ることは、トラックが健全であることではありません。 この段階は既知の変調を 1 つのテイクへ注入し、どの深さが返ってきたかを報告します。ですからそれが立証するのは、その系列の中にある周期成分を探索が見つけられること、であって、その系列が音のピッチであることでも、そこから取った読みが頑健であることでもありません。公開した数値がすべて誤っていた実行でも、3 セントを回復していました。しかも注入先のテイクは、何も掃引していない唯一の設定であり、この対照が範囲を定める行からいちばん遠いテイクです。

ですからこれを捕まえる検査は、対照ではありません。掃引したパラメータを 0 に保ったテイクについて、系列そのものを、1 フレームでは決められない統計量で、見ることです。1600 フレームにわたる端から端までの幅は、その中で最悪の 1 フレームが言うことをそのまま言います。同じテイクを端から端で読んだことが、実際には 0.8 セントの平坦さだったトラックを「使い物にならない」と公開させました。

phase には他の段が必要としない対照が付きます。同じ音を鳴らした 2 つのテイクの間で測るので、その 2 テイクが同じ波形である場合にしか成立しません。そのため帯域ごとにコヒーレンスを併記します。2 テイクが別々の信号を持つ帯域で測った位相は、無関係な 2 つのものの間の角度であり、本物と同じくらい安定していて、同じくらいもっともらしく見えます。2 テイクの未知の開始時刻の差は周波数についての直線であり、エフェクト自身が置いた遅延と区別できません。したがってその直線は取り除き、取り除いた量をサンプル数で公開し、直線を残したままの数値も並べて公開します。

14. ブロック全体 ​

sh
rye run soundings plan data/units/<unit-id>/write-probe/whole-map.json "40 11" \
  --out plan-40-11.json
rye run soundings block plan-40-11.json <plain records> --gesture <gesture records> \
  --balance <balance record> --out data/units/<unit-id>/block/40-11.json

マニュアルが面白そうに見せたアドレスではなく、ブロック内の全アドレスについて「変えると音が変わるか」を調べます。2 パス構成です。まず打鍵しただけの音で調べ、次に、そこで差が聞こえなかったアドレスを、設定の後にメッセージを動かした状態で調べ直します。メッセージを受け取るかどうかだけを決めるパラメータは、打鍵しただけの音では受け取るものを持たないからです。

各アドレスを調べる値の組は、文書ではなくライトプローブから取ります。ブロックは、たまたま存在する記録の数ではなく、計画に対して数を突き合わせます。47 アドレスのブロックに 45 個の記録がある状態は、完全に答え終えた状態とまったく同じ見た目になるからです。

そのブロック自身が「聞いている」と言うチャンネルで調べること。 そのバイトはブロックの中にあり、機体が答えてくれます。別のチャンネルに出したテスト音は、そのアドレスが宛先としないパートに向けて鳴らすことになり、ブロックの全アドレスが「差は聞こえない」と答えます。

受け付ける範囲だけから選んだ値の組では、チャンネルのバイトを調べられません。 ライトプローブはそのアドレスが何を受け取るかを報告しますが、テスト音がどのチャンネルにいるかは知りません。組の両方の値が、鳴っているノートからパートを引き離してしまう場合、どちらの設定も無音になり、実行は測定を拒否します。しかもそれは「値の組の選び方が悪い」ではなく「収録の失敗」に見えます。そういうアドレスは、そのパート自身のチャンネル対 off で調べます。

15. エフェクト型自身のパラメータ ​

sh
rye run soundings efx-sort <contrast の記録群> \
  --types-from data/units/<unit-id>/efx-map/types.json \
  --tracked data/units/<unit-id>/efx-motion/<record>.json \
  --out data/units/<unit-id>/efx-sort/<name>.json
rye run soundings efx-params <contrast の記録群> --type 01 00 \
  --types-from data/units/<unit-id>/efx-map/types.json \
  --control <同じ実行で録った、経路に通した状態と迂回した状態の記録> \
  --slots "40 03 03" "40 03 04" ... \
  --out data/units/<unit-id>/efx-params/01-00.json

段階 14 がブロックに対して問うことを、インサーションエフェクト 1 型のパラメータに対して問います。関門は型ではなくパラメータで設けます。 関門の価値は何を落とすかで決まります。型全体に対して設けた関門は機体の持つ全型を通しうるので、掃引すべきパラメータの数は最初のまま残ります。

その前に経路を確立します。 機体のアナログ入力に与えた信号がエフェクトまで届くかどうかを、上げた状態が実際に何かをすることを示す対照付きで測定します。届かない機体では、既知の信号をエフェクトに通して掃引する方法が使えないので、この段階はその機体自身のボイスで支えられる範囲に限られます。

スロットは導出せず、渡します。 どのアドレスがどのスロットかは機体についての事実です。ファイル名の並び順に任せると、測定できなかったアドレス 1 つが、それ以降の全パラメータの番号をずらし、それぞれを 1 つ前のスロットの既定値と組にし、型が持つパラメータ数を 1 つ少なく報告します。

片方の設定を無音にする値の組は、音と無音を比べたことになります。 そういうアドレスは名指しで取り下げ、差し替えた記録をその行と一緒に持ち回ります。ディレクトリの経緯を覚えている人と一緒に、ではありません。実行時に作り込んだ状態も併記します。判定はその状態の中で成り立つのであって、一般に成り立つのではないからです。

型が静止するかどうかには 2 つの経路があります。efx-motion はテイクを読み、efx-sort は各型が機体自身の再現性に何をしたかを読みます。この 2 つは別々の性質に立つので、両者が食い違った型は、調整せずに食い違いとして報告します。どちらも型マップを取るので、記録のない型は「不在」ではなく「未調査」として読めます。

3 つ目の経路は、対ではなく型ごとに 1 テイクから、それ以上を答えます。

sh
rye run soundings efx-partials <持続音テイクのディレクトリ 1 つ> \
  --carrier-hz 440 --hold 8.0 --control-at 0.45 \
  --out data/units/<unit-id>/efx-partials/<name>.json

持続音の各倍音をその倍音自身の周波数で下ろすと、その倍音の位相とレベルがテイク全体にわたって残ります。そこへレートのグリッドを走らせて射影を取ります。何も予測せず、どのバイトの値も読みに入りません。 だからこの結果を「レートバイトが何を意味するか」という主張に対してぶつけられます。

3 つの機構は、どの量が動くかで分かれます。 掃引される遅延は各倍音の位相をその倍音自身の周波数に比例して回し、オールパス段は全部を同じ角度だけ回し、レベル変調はどれも回しません。どちらか片方の量だけを読むと、3 つとも数字を返してしまいます。

レベルの振れがコムであるのは、倍音どうしが食い違うときだけです。 前向きのコムのあてはめが系列をどれだけ説明するかは「レートが違う」ことに対するゲートにはなりますが、「機構が違う」ことに対しては何のゲートにもなりません — 遅延をどこにも含まないただのレベル変調が、本物のコムより高い説明率でコムとしてあてはまります。コムはノッチを掃引するので、ノッチ近くの倍音は山の上の倍音よりはるかに大きく振れます。声全体にかかる 1 つの包絡にはそれができません。

ピークは自分のグリッドの中央値ではなく、バイパステイクに対してレートごとに置きます。 持続音は安定ではなく、経路に何も入っていなくても声自身のドリフトが自分のグリッド中央値の何倍ものピークを作ります。

コムが返すのは長さではなく等価値です。 2 経路のコムがノッチをそれだけ動かすのに必要な遅延であって、フェイザーやワウはオールパス段でノッチを動かすので長さを持つ遅延線がありません。レベル系列だけではその区別がつきません。

16. パラメータのバイトが何を表しているか ​

可聴判定が通ったパラメータについて、かつ下流の具体的な問いがその曲線を必要とするときにだけ行います。選別には終わりがありますが、掃引にはありません。

sh
rye run soundings efx-rate <takes> --type 01 20 --slot "40 03 04" \
  --setting '<value グループを持つパターン>' --held "40 03 07=00" \
  --out data/units/<unit-id>/efx-rate/01-20-04-<何を問うたか>.json
rye run soundings efx-bands <takes> --type 01 00 --slot "40 03 07" \
  --setting '...' --reference '...' --control '...' --silence '...' \
  --out data/units/<unit-id>/efx-bands/01-00-07-<何を問うたか>.json
rye run soundings efx-time <takes> --type 01 40 --slot "40 03 03" \
  --setting '...' --control '...' \
  --out data/units/<unit-id>/efx-time/01-40-03-<何を問うたか>.json
rye run soundings efx-sway <takes> --type 01 26 --slot "40 03 03" \
  --setting '...' --still '...' --held "40 03 05=7F" \
  --out data/units/<unit-id>/efx-sway/01-26-03-<何を問うたか>.json

--still は、変調が入っていないテイク、つまり対照の注入先を名指しします。推測ではなく名指しなのは、すでに変調を持つテイクに注入すると変調が 2 つになり、探索が機体自身の方を見つけ、対照の側が「読めるはずの素材で失敗した」と読めてしまうからです。

どれも --save 付きの実行が残したテイクのディレクトリを読むので、機体の接続を必要とせず、実機が別の作業で塞がっている間も走らせられます。同じディレクトリを balance、balance-bands、arrival が読み、そのバイトがステレオの対に何をしたかを答えます。

soundings walk は型と経路、--prepare の各状態を書き込んだうえで、1 つの番地を設定の列に沿って歩かせ、書いてから読み戻して確かめたのちに、そのつどテイクを録ります。迂回テイクは設定名 out、無音テイクは設定名 silence で録り、残すのはテイクとマニフェストだけで、自身は記録を公開しません。読み取りの段は、固定した --setting '^v(?P<value>\d{3})$' --control '^out$' でそれを読みます。

soundings takes は、ディスク上のテイクのディレクトリすべてにわたって作業用の索引 .cache/takes-ledger.json を組み立てます。各ディレクトリが持つ型・番地・設定、held の状態とその出所、そしてどの公開レコードがそれを読んだかを載せます。これは測定ではなく、公開もされません。soundings takes row は 1 つの型と番地のエントリを返し、unread はどの公開レコードにも読まれていないディレクトリを容量の大きい順に挙げ、rewritten は読んだレコードより新しいテイクを持つディレクトリを挙げます。

soundings inferences render は、迂回テイクのディレクトリの上に型全体の graph モデルを、配線が要求する箇所はサンプル単位で描きます。soundings inferences stage は、ある型のクラスに属する候補のそれぞれと、テイクをそのまま描き戻す対照とを、機体自身のテイクと突き合わせます。静的な型は描いた波形と機体の波形を差し引き、それ以外の型は両側をその型の記録を公開した段で読んで比べます。結果は inferences/<unit>/stages/<MM-LL>.json に書かれ、描いたテイクから読み取ったものが data/units の下に書かれることはありません。これらのコマンドが測るのは機体そのものではなく、機体に対するモデルです。

掃引が述べるのは、そのバイトとともに何が変わったかであって、もともと何があったかではありません。 ですから各リーダは、何に対する値として報告するのかを、同じセッションの中から、欄ではなくテイクとして受け取ります。型を読み込んで何も書いていない状態(--untouched)、実行が平坦に保った設定(--reference)、パートをエフェクトの外へ迂回させた状態(--control)、同じ経路で何も鳴らさなかった状態(--silence)です。最後のものがないと、出力を十分に下げた設定は、測定系の下限そのものの形をプロファイルとして公開します。

他に何を保持していたかも、その読み取りの一部です。 変調器を 2 つ持つ型は、そのとき支配的な方を返します。帯域プロファイルは経路全体のものです。ですから同じ型の別の段を動かした状態で読んだバイトは、別のものの読み取りであり、数値のどこにもそうは書かれていません。--held が、それを名指しできるようにします。

記録は、自分が持つ起動コマンドから再構成できなければなりません。そしてある段階のものはそうなっていませんでした。 保存された起動コマンドから --held が抜けていたため、再実行すると held の欄が空で返ってきました。経路の他の部分は何も動かしていない、と述べる記録です。帯域プロファイルが何のプロファイルなのかを決めるのは、まさにそこです。何も失敗せず、帯域の値も同一でした。保存されたコマンドから段階を再公開する前に、記録を 1 つ再実行し、コミット済みのものと全キーを両方向で突き合わせてください。消えたキーは、動いたキーと同じだけの変更です。

テイクの名前から設定値をどう読み戻すかは、起動コマンドに属します。 実行はテイクに、その実行自身の問いが必要とした名前を付けます。ですからそのパターンは記録に載り、読者は信用する代わりに検算できます。

分解能は、どちらへ振っても代償があります。 中の偏差より広い帯域は、その偏差を実際より浅く報告します。帯域セットの端でまだ育っている偏差は、そこで止まったものとして報告されます。とはいえ細かい方が自動的に良いわけではありません。ある機体では、同じテイクを 4 倍細かく読み直すとピークは鋭くならずに散らばり、平坦な繰り返し自身のばらつきも一緒に悪化しました。実行が分解した粒度と、問いが必要とする粒度の、粗い方で読み、どちらだったかを記録に書いてください。

ディレイはそれ自身の分解能を基準に読みます。 変換の分解能より下ではピークを取りません。それより短いディレイは第 3 ラーモニックとして返ってきて、ディレイと同じ高さに立ちますが、ディレイではないからです。探索は印刷された範囲の端より先まで走らせます。そうすれば、ページの記載より先まで伸びるバイトが、探索側の縁ではなく読み取りとして現れます。

「音が変わった」という判定の読み方 ​

判定は 3 つの経路で立ちます。波形の形が変わった、レベルが変わった、あるいは片方の設定のテイクどうしが、もう片方に比べてはるかに一致しない。前の 2 つは音そのものを測っています。3 つ目はばらつきを測っていて、ばらつきはパラメータ以外のものからも生じます。

一致度だけを根拠にする判定は、安定している側が絶対値としても安定していることを求めます。 比べる相手はもう片方の設定ではなく、同じアドレスについて、打鍵しただけの音が示した数値そのものです。音を遮るパラメータは、遮っている側の設定を、打鍵しただけの音と同じように再現させます。一方、位相が自由に動いている状態から取った 2 回の測定は、どれだけ離れていても何も意味しません。

テスト音は、その判定が数に入る前に、自分自身の再現性を確立していなければなりません。 段階 11 が測るのは、1 つのテスト音についての検出下限です。複数のボイスを鳴らすテスト音は、トリガでは固定できない相対位相を持ちます。トリガのばらつきが、鳴っているノートの 1 周期より広い場合、位相はテイクごとに自由になり、レベルがそれに従って動きます。ある機体での実測では、打鍵しただけの音が 56〜62 dB で一致したのに対し、2 音のテスト音は 1〜66 dB に散らばり、その 84% が 10 dB より悪い値でした。このテスト音が報告したものは、二度目に調べたとき何一つ残っていませんでした。テイク数を倍にしても改善しませんでした。

ちょうど 1 つのテスト音だけが捉えた判定は、公開前に調べ直します。 ある 3 ブロック分の測定では、この種の判定がすべて再現しませんでした。最初のパスでいちばん健全に見えたものも含めてです。調べ直す手間は、存在しない結果を公開する代償に比べれば安上がりです。

同じパラメータを持つ 3 つのブロックは、3 回の試行です。 1 つのブロックにだけ現れて他に現れない判定は、パート間の差か(パラメータは普通そういう差を持ちません)、再現しなかった測定か、どちらかです。その区別には調べ直しが要ります。議論では決まりません。

すべての記録が持つもの ​

何も見つけなかった段階は、その実行が何かを見つけられたはずである場合にだけ、読む価値を持ちます。ですから各記録は、その実行が備えていた対照を明示します。

  • 陽性対照。 最初のテスト音の前と、最後のテスト音の後に送ります。1 回しか送っていない対照は、その実行の残りについて何も語りません。
  • 調べている系列のメッセージが実際に届いたかどうか。 陽性対照はコントロールチェンジなので、他の系列のメッセージが通ったことまでは示せません。これを欠く実行では、「見つからなかった」という所見はすべて、機体ではなく経路についてのものになります。
  • 書き込んだブロックの外に着弾したときに、それを報告できたかどうか。 あるアドレスへ書いてそのアドレスしか動かなかった、という実行は、そこを映すものが他にない証拠になります。ただしそれは、他所に着弾していたら報告されたはずである場合に限ります。
  • 何を元に戻し、何を対象から外したか。 実行がカバーするのをやめた範囲は、その実行が述べることすべてに掛かる但し書きです。

記録を読み解くことは、段階のひとつではありません ​

上のどの段階も、読み取った値が何を意味するかは述べません。構造に名前を与えること、回路構成を当てはめること、証拠がどの読み取りを残しているかを決めること — それらはすべて inferences/ で、data/ の外の、このディレクトリの中だけで行います。参照は一方向です。推論は記録を引用しますが、記録は推論を引用しません。

プロトコルに関わるのは 1 点だけで、それは次に何を走らせるかです。

sh
rye run soundings inferences open

次に何を測る価値があるかは、一覧として保持せず導出します。 各項目は、まだ立っている読み取りを主張から切り分ける観測量と、この測定系がそこで分解できる量に対する余裕です。余裕が 1 を下回る項目は、待ち行列に入れてはいけません。 ある機体では、より細かい帯域グリッドがそういう項目でした。実行しても、改善するはずだった数値より悪い数値が返ってきたはずです。ここでは何をもっても切り分けられない対抗案は、その理由を述べて未解決のまま残します。答えられるはずのない実行に化けさせるのではなく。

記録は、どの読み取りが見るよりも前に、採否を決めます。そしてその規則は記録自身のものです。 テイクの中に見つけた倍音の半分にも満たない数で出たレート、あるいはそのテイクが載せられる最も遅いレートで出たものは、名指しで除外します。ページがその型に複数のレートを印刷しているスロットも同じです。テイクは、そのとき支配的な変調器の方を返すからです。除外はそのつど待ち行列の項目になり、黙って落とされることはありません。

何時間もかかる段階を走らせる ​

ブロック全体を測る段階は何時間も走り、procedures/ のドライバから起動します。ここはバージョン管理の対象です。1 台の機体に固有のドライバは作業ノートなので対象外ですが、プロトコルの一部であるものはここに置きます。誰も持っていないスクリプトで測定された 2 台目は、同じやり方で測定されたことになりません。

sh
./procedures/part-block.sh "40 11" 0        # ブロックと、それが聞いているチャンネル
./procedures/part-takes.sh <plan> plain     # 計画済みブロックを 1 パス通す
./procedures/stop-sweep.sh                  # 停止し、止まったことを確かめる
./procedures/publish-efx-bands.py --takes <dir> --out data/units/<unit-id>/efx-bands

パブリッシャが行うのは実行の列挙であって、読み取りではありません。 procedures/ にあるものは、読み取りの実装をもう 1 つ抱えるのではなく、コマンドラインが公開しているのと同じ段階を通ります。ですからリーダが良くなった後でも音声から記録を作り直せますし、修正は 1 か所に入ります。実行が掃引したのにパブリッシャが名指ししなかったスロットは、記録を生まず、末尾に一覧として出ます。認識できた実行だけを黙ってカバーするパブリッシャは、残りを「そもそも実行されなかったもの」に見せてしまうからです。

1 アドレスずつ、新しいプロセスとして走らせます。これは実装の都合ではありません。 無人の長時間実行が遭遇する失敗は 2 つあり、どちらもアドレス 1 つ分を丸ごと失わせ、うち一方はプロセスを即座に終了させます。ですから、新しいプロセスとして調べ直すことが、唯一の回復手段になります。

各段階は、前の段階自身の記録を見て対象を決めます。 ジェスチャのパスが調べる対象は、soundings block が「まだ開いている」と名指ししたものであり、手で書くのではなくファイルから読みます。二度書かれたリストは二度下された判断であり、両者はずれます。対象を決めるべき記録が存在しない場合、段階は起動を拒否します。空のリストと、読み込みに失敗したリストは、次のパスに同じもの——つまり何も——を渡すので、実行が「やることがなかったパス」として報告してしまうからです。

測定経路 ​

測定経路はプロトコルの一部です。インタフェース、ゲイン、結線、収録方法は、機体をまたいで同一に保ちます。そうしないと、2 台の機体のレベル差を、2 つの経路の差と区別できません。

やむを得ず経路を変えた場合は、その違いを meta.json の measurement_chain に記録し、その機体を含むレベル比較には「確立していない」と付記します。

実機を使う段階は直列に走らせます。オーディオインタフェース 1 台、機体 1 台という条件では、手前の収録の最中に裏で別の実行が音を鳴らし、再現性が静かに崩れた数値だけが残ります。

この規則は、破られる前から書いてありました。つまり書き留めるだけでは足りないということなので、ハーネス側で強制します。機体を動かすコマンドは排他ロックを取り、2 つ目は起動を拒否されます。拒否することが要点です。 2 つ目の実行の側からは、何も異常に見えません。ノートは鳴り、テイクは録れ、記録は普通の顔をして出てきます。痕跡は 1 つ目の実行のテイクの中、もう一方のノートが、ノイズフロアを測るためのリードインに紛れ込んでいる場所にしか残りません。

実行を止めるとは、そのプロセスを全部止め、かつ止まったことを確かめることです。 ドライバは入れ子になっていて、それぞれが一度に 1 段階ずつ起動します。ですからプロセスツリーの頂点を落とすと、落とされた子が終了した瞬間に、親が次の段階を開始します。親を子より先に落とし、プロセスの一覧が空になるまで繰り返し、止まったと確かめられない停止は止まらなかったものとして扱います。取り残されたプロセスは待機しているのではありません。機体にノートを鳴らし続けています。

無人の長時間実行における 2 つの失敗は、アドレスについてのことではなく、その瞬間に機械が資源を渡さなかったことです。 要求した長さより短く返ってきた収録と、MIDI 層がクライアントの作成そのものを拒むことです。どちらもアドレス 1 つ分を丸ごと失わせ、後者はプロセスを即座に終了させます。ですからどちらも、新しいプロセスとして調べ直すことで再試行します。何回の再試行が必要だったかは記録します。再試行率が上がっていくことは、測定経路についての事実だからです。

測定データは CC0 1.0 · 本サイトはいかなる楽器メーカーとも提携・関連・公認の関係にありません。製品名は測定した機材を識別するために記載しています。