聴き手シミュレータを内蔵して飽きないテクノを生成したい。無限偏差機関「DEVIATION∞」を作ってみた(CloseBox)

テクノロジー AI
松尾公也

テクノエッジ編集部 シニアエディター / コミュニティストラテジスト @mazzo

特集

無限音楽機関シリーズの新作として、DEVIATION♾️(Infinity)を開発しました。

きっかけとなったのは、東京大学名誉教授である暦本純一先生のXでの長文投稿「反復と変容/予測脳:シューベルトからミニマル・ミュージックへ」でした。

暦本先生は、音楽情報処理の研究でも名高いSony CSLのシニアフェローであり、先日開催されたAIハッカソン「Project DENT Masters」で戦ったライバル(笑)でもあります。

反復は「同じものの再確認」ではない

この暦本先生の投稿は、シューベルトからミニマル・ミュージックへの系譜を、形式史ではなく聴取の側から捉え直すユニークなものです。

脳は音を受動的に受け取っているのではなく、つねに次を先取りする予測モデルとして働いている。反復はこの予測を安定させ、聴き手に安心と流暢さを与える。ここまでは単純接触効果の話に見えます。

面白いのはその先でした。反復の価値は「同じものの再確認」に尽きない。反復が強いほど予測のベースラインが固まり、ほんの小さなズレでも予測誤差として際立つ。だからわずかな和声のシフト、位相のずれ、アクセントの変位が、反復のない音楽よりはるかに鋭く知覚される、というわけです。

投稿ではBernhard Langをめぐる『Loop aesthetics』が引かれていて、ループは同一性を固定する装置ではなく、むしろ非同一性を露出させる装置だ、とされています。シューベルトの緩徐楽章やD 960の終楽章で起きているのは大規模な再現の待機ではなく、局所的な反復のなかで生じる微小な変化への傾注である、と。

これまで作ってきた無限機関シリーズ──Bach PERPETUUM MOBILE、SLOWHAND∞、EMERSON MOOG INFINITY、SATIE∞──は、どれも旋律と和声を情報源にしてきました。ですがテクノとミニマルとEDMは違います。和声はほとんど動かない代わりに、情報が音色とレイヤーの出入りと長時間の起伏に載る。

つまり「無限に飽きさせない」という問題の解き方が変わります。そしてその解き方は、暦本先生の投稿にそのまま書いてある気がしたのです。予測を成立させ、その予測を微細に揺らす。これを制御則として実装すればいいのでは。

聴き手のシミュレータを内蔵する

というわけで作ったのがDEVIATION∞(偏差機関)です。React+Tone.jsのブラウザアプリで、テクノ/ミニマル/EDMの3モードを持ちます。

この装置の中核は、生成器と並走する聴取シミュレータです。

各レイヤーのパターンが何小節不変で続いたかを数え、familiarity = 1 - exp(-平均齢/5)として予測モデルの固まり具合を推定します。これが「慣れ」です。慣れが飽和すると、機関は偏差を注入します。そして実際に生じた変化量をハミング距離で測り返す。これが「予測誤差」です。

誤差が最適帯を大きく超えたら、数小節のあいだ「反復固定」状態に入り、一切の変化を止めて予測を建て直させます。Wundt曲線の甘い領域を自動追尾する閉ループになっています。

最適誤差値はモードごとに変えました。テクノ0.12、ミニマル0.055、EDM0.18。ミニマルの帯が極端に狭いのが本質で、だからこそ位相ずらし1ステップが事件になるわけです。

画面には「予測誤差スコープ」を置きました。琥珀色が慣れ、青が誤差、青い帯が最適域、縦線が偏差の発火点です。琥珀が上がりきった直後に青が跳ねる形で、投稿のテーゼがそのまま目に見えます。

偏差オペレータとシューベルト

慣れが飽和したとき何を変えるか。10種類のオペレータを用意しました。

ROTATE(パターン回転)、FLIP(1ステップ反転)、PHASE(Reich的位相ずらし)、ADDITIVE(Glass的加算過程)、EUCLID(ユークリッドリズムの再構成)、TIMBRE、DURATION、OCTAVE、SUBTRACT、そしてMEDIANT

最後のMEDIANTが、この装置でいちばん気に入っています。根音を三度(3ないし4半音)だけ動かす。低音の地盤も反復の枠組みも保ったまま、色だけがずれます。シューベルトの、あの「同じところに戻ってきたのに景色が違う」瞬間を、ミニマルの語彙に翻訳したつもりです。

ミニマルモードでは、これらを離散的なイベントではなく「プロセス」として走らせます。名前のついた過程を1つ選び、32~64小節かけて完走させ、次を選ぶ。変化しているのに一貫している、が同時に成立します。

iOSでTone.Transportが動かない

実装してみると、まずiPhoneで音が出ませんでした。STARTを押すとボタンはSTOPに変わるのに、小節カウンタが1つも進まない。

診断パネルを仕込んで計測したところ、コンテキストはrunning、Transportもstarted、Transport.secondsも進んでいます。なのにscheduleRepeatのコールバックが一度も呼ばれない。

原因究明は諦めて、Tone.Transportへの依存を捨てました。40ms間隔のsetIntervalがAudioContext.currentTimeを直接見て、320ms先までのステップを先読みで積む方式に置き換えます。いわゆるA Tale of Two Clocksです。タイマーは「いつ積むか」を決めるだけで、発音時刻は全部WebAudioの時計に乗るので、タイマーの精度は音の正確さに影響しません。

これで鳴りました。

「クォンタイズが甘い」を測る

Macで試していて、どうもクォンタイズが甘い気がしました。感覚を信じてもしょうがないので、スケジューラの数理だけ切り出してシミュレータを書き、メインスレッドのジッタを与えて3分間・16分音符1500発ぶんを測ってみました。

現行

修正後

グリッド誤差 平均

23.3 ms

0.000 ms

グリッド誤差 最大

53.9 ms

0.000 ms

位相破断(2ms超)

1203回

0回

犯人は追い越し時の復帰処理でした。遅延で取り残されたときnextTime = now + 0.06と現在時刻基準で復帰していたので、グリッドの位相が任意の場所にずれる。3分で11~17回発生し、そのたびにビートの基準位置が飛んでいました。区間内は正確なのに基準がずれ続けるので、「甘い」というより「滑る」感触になっていたわけです。

発音時刻をanchor + k × durという閉じた式で毎回計算する方式に組み直しました。累積加算をやめれば浮動小数の誤差も乗りません。追い越されたときも、任意の時刻に飛ぶのではなくグリッド上の次の格子点まで必要数だけ読み飛ばします。稀に音符が数個抜けますが、拍が滑るより遥かに実害が小さいと判断しました。

ついでにキックのトランジェントも締めました。pitchDecay 0.048、octaves 8だと、C1に対して8オクターブ上の8kHzから48msかけて滑り降りるので、アタックの起点が知覚的に滲みます。位相が正確でも輪郭が甘いと「クォンタイズが甘い」と感じるものです。

20小節で飽和して止まる

次は、20小節あたりで急にノイジーになり、飽和して止まる症状でした。

これは先読みスケジューリングの副作用です。ビルド区間のライザー用ノイズをriser.stateを見てstart()/stop()していたのですが、stateは現在時刻の状態を返すのに、渡している時刻は最大320ms先。この不整合でTone.jsのSourceが例外を投げ、小節処理が毎回そこで落ちていました。結果、小節カウンタが進まず、セクションも切り替わらず、ライザーのノイズだけが鳴りっぱなしになっていたわけです。

start/stopという状態機械への依存をやめ、ノイズは最初から鳴らしっぱなしにしてゲインで開閉する方式に変えました。先読みスケジューリングでは、状態を持つAPIを未来の時刻で叩いてはいけない。これはこの後も何度も出てくる教訓になります。

ミキサーにないものが一番うるさい

レイヤーごとの音量調整が欲しくなってミキサーを付けました。11チャンネル、フェーダーとミュートとdB表示。

そうしたら、全部ミュートしても音が残ります。

配線を全数監査して3つ見つかりました。ライザーがチャンネルを持たずバスへ直結していたのが1つ。そしてstabのリバーブ送りとacidのディレイ送りがプリフェーダーでした。シンセ本体から直接センドへ分岐していたので、チャンネルを落としてもエフェクト返りだけが鳴り続けます。

ミキサーを作るときは、フェーダーを経ずに出力へ至る経路がないかを機械的に洗ったほうがいいです。目で追うと必ず見落とします。

ACIDが音痴

「ACIDが音痴に聞こえるのは、コードトーンじゃないから?」と自分で疑って調べたら、半分当たっていて、残り半分は別物でした。

1つ目。ACIDのパターンは常に主音のスケールから音を選んでいて、セクションごとに動く和音度を見ていませんでした。和音がIIIやVへ移ってもACIDだけがIのまま。旋法内ではあるが和音外の音が鳴ります。

2つ目。スライド処理のバグです。acid.portamento = v.s ? 0.055 : 0は即時実行のプロパティ代入なのに、発音は最大320ms先に予約されています。つまりグライドの有無が、実際に鳴っている音とは無関係なタイミングで切り替わる。またしても同じ罠でした。

3つ目。レゾナンスです。Q値が最大10まで上がり、カットオフはドリフトで自由に動きます。高Qのフィルタはカットオフ周波数に自己共振のサイン波を作るので、音階と無関係な音程がはっきり鳴る。しかもfilter.frequencyを直接書いていて、MonoSynthのフィルタエンベロープと取り合いになっていました。

音高をパターンに絶対値で持たせるのをやめ、和音度からの相対音度で保持して発音時に導出する方式に変えました。強拍はコードトーン、弱拍は経過音です。コードトーンとの一致率は強拍で43~57%から100%になりました。

さらに、根音の半音上に当たる音度を発音時に回避する処理を入れました。テクノモードはPhrygianなので、放っておくとb2が頻出します。旋法の特徴音ではありますが、高Qのフィルタと重なると、はっきり外れて聞こえます。

そして、ACIDを和音追随にした結果、今度はBASSが取り残されました。上物が正しくても土台がずれていれば、耳には上物が外れて聞こえます。BASSも同じ方式に揃えました。

BASSとKICKが離れすぎる

「BassはあまりKickと離れすぎると気持ち良くない」という感覚も測ってみました。

キックはroot - 9=MIDI 24(C1、32.7Hz)。対してベースはMIDI 45~57(A2~A3、110~220Hz)。1.75~2.5オクターブ開いていて、しかもオクターブ跳躍の偏差がさらに±12動かします。最悪3.5オクターブ離れる。これでは低域が一つの塊になりません。

キック基音を基準とした音域窓に畳み込む方式にして、窓の幅をスライダーで調整できるようにしました。既定の14半音でC2~D3(65~147Hz)、キックとの距離は12~26半音に収まります。

畳み込みは発音時に一箇所で行います。生成側で直しても、その後の偏差オペレータが再び音域を壊すからです。

303らしさとは何か

ついでにBASSをTB-303の構造に寄せました。

内部フィルタは開けたままにして、外部にレゾナントローパスを立て、その動きをSignalで時刻指定します。MonoSynthのfilterEnvelopeはプロパティ代入でしか触れないので、先読みスケジューラとは原理的にずれます。ACIDのスライドが壊れていたのと同じ理由です。

アクセントは3つ同時に動かします。音量、フィルタの振り幅、減衰の速さ。

ピーク

振り幅

減衰

通常

922 Hz

2.28 oct

220 ms

アクセント

1624 Hz

3.10 oct

136 ms

グライドはportamentoの切り替えではなく、次の音がスライド指定なら手前の音をステップ長より長く残して重ねる方式にしました。「前の音が終わる前に次を弾く」という条件で発生するのは実機と同じです。

Cutoff、Resonance、Env Mod、Decay、Accent、Glideの6つをパネルに出しました。極端な設定でもピークがカットオフを下回らないことは全数確認してあります。

PADと「同じようで同じでない」

PADの音色がプアだったので作り直しました。ここが理論との接続がいちばん綺麗にできた部分です。

PADは装置の中で最も「予測の地盤」を担う層です。だから他のレイヤーのような離散的な偏差を与えてはいけません。与えたのは2つです。

連続的な色の移動。フィルタ、コーラス深度、デチューン量の3つに、係数0.94~0.96の減衰つきランダムウォークをかけます。一歩が小さく方向が持続するので、気づかれない速度で色だけが移動し続けます。時定数3.2秒で追従させているため、変化の瞬間は知覚できません。

共通音を保った声部移動。慣れが飽和したときだけ、転回・付加音・開離/密集・sus4のいずれかを1つ動かします。ここが肝で、変わった声部だけを差し替え、共通音は鳴らしたまま保持します。全音を鳴らし直すと変化が「事件」になってしまうからです。測定したところ、偏差1回あたり平均2.5声部が保持され1.3声部だけが入れ替わっていました。

まさに「同じようで同じでないものを聴き分ける」状態です。

配置アルゴリズムは全数検査しました。4旋法×5和音度×転回3×付加音4×開離2×sus2×根音7の6720通りで、半音衝突ゼロ、音域D3~D6、最大幅22半音。Phrygianでadd9を付けると必ずb9になって持続音として濁るので、旋法の第2音が短2度のときは11thへ自動代替させています。

ハコの音響

マスター段に、部屋鳴り、サチュレーション、フランジャ、スタッターを追加しました。信号はbus → サチュレーション → {ドライ/フランジャ/部屋鳴り} → スタッター → glue → リミッタです。スタッターを最後段に置いたのは、残響ごと断ち切るのがクラブの挙動だからです。

サチュレーションは最初、駆動0でも3次高調波が15.3%出ていて、しかも上げるほど音が小さくなっていました。tanhカーブの原点での傾きが2.63あるためです。傾き1に正規化して、前段のゲインだけを駆動量にし、基準振幅が歪んだ後も同じ振幅で出るよう補償を掛けました。ピークが一定のまま倍音の量だけが動きます。

フランジャは当初、遅延6.8msで第1ノッチが74Hzに来ていました。キックとベースの帯域を直撃です。送りの手前に220Hzハイパスを入れて、低域は櫛形に巻き込まないようにしました。

理屈との接続はこうです。フランジとスタッターは慣れが飽和し、かつ強度が乗っているときだけ自動発火します。全体が固まっているほど、全体に掛かる変化は巨大な予測誤差になる。だからスタッター発火後は反復固定を4小節立てて、強制的に予測を建て直させます。

ビジュアライザで最初にやるべきこと

ビジュアライザを3種類作りました。ですがその前に、片付けるべき問題がありました。

発音イベントを「スケジュールした時点」で画面に反映していたので、画面が音より平均217ms、最大434ms先行していたのです。これでは連動とは言えません。

発音の実時刻を添えてイベントをキューに積み、描画側がオーディオ時計で取り出す仕組みに変えました。結果、ずれは平均8.0ms、最大16.7ms。16.7msは60fpsの1フレームなので、残っているのは描画フレームの量子化誤差だけです。

そのうえで3モードです。

小節時計は極座標です。1小節を円周とし、11レイヤーを同心円に配置します。環の明るさが「慣れ」を表します。パターンが不変で続いた小節数から算出していて、反復が続くほど環がはっきり実体化し、偏差が入った瞬間に暗くなってまた固まっていきます。偏差は青い波として円環の外へ抜けます。反復が模様を成立させ、その模様があるからこそズレが見える、という構図をそのまま図にしました。

アシッドはフレームフィードバックです。前フレームを微小に回転・拡大して描き戻すと、映像が自分自身を食べてトンネル状に溶けていきます。キック直後は拡大率が1.005から1.033へ跳ね上がり、40倍到達までの時間が12.3秒から1.9秒に縮みます。四つ打ちのたびに景色が吸い込まれるわけです。回転量は予測誤差に連動し、誤差0で5.5°/秒、誤差0.4で67.4°/秒。偏差の発火時には色相が47度以上跳び、40%の確率で回転方向が反転します。

鏡面はCanvas 2Dで本物の鏡面反射計算をやっています。メタボールの高さ場から有限差分で法線を求め、視線ベクトルの反射で手続き的な環境を引きます。フレネル項で縁が光り、鏡面ハイライトは指数64です。7つの球がそれぞれレイヤーに割り当てられ、発音のたびに膨らんで融合と分離を繰り返します。キックが来ると同心円の波紋が高さ場に加算され、鏡面が液体のように波打ちます。ウルトラマンエースのヤプールみたいな感じです。

負荷は200×125で2.70ms/frame、60fps予算の16%でした。余弦を1024エントリのルックアップテーブルに、powを反復二乗に置き換えたのが効いています。低解像度で計算してimageSmoothingQuality: highで拡大しているので、補間のぼけがむしろ鏡面の滑らかさとして働きます。

字幕と録画

偏差の内容をテキストで重ねるオーバーレイと、映像+音声の録画機能を付けました。

オーバーレイは3段階です。字幕モードではセクション、小節、慣れ、誤差、直近2件の偏差。字幕+では調性、実行中のプロセス、累計偏差回数、反復固定の状態を加えます。実況はビジュアライザと同じイベントキューから取り出しているので、「BAR 0247 / PHASE / PERCを位相ずらし(+3)」という一行が、音が変わったまさにその瞬間に出ます。

録画はキャンバスのフレームストリームとマスターから分岐したMediaStreamを合成します。映像と音声が同一のMediaRecorderに入るので、後から同期を取る必要がありません。SafariとChrome 130以降ではMP4(H.264+AAC)、それ以前やFirefoxではWebM(VP9+Opus)に落ちます。ボタンにどちらかが表示されます。

GitHub Pagesに公開しました

というわけで、ここまでをGitHub Pagesに公開しました。

・公開サイト:https://matsuo-koya.github.io/deviation-infinity/

・コード:https://matsuo-koya.github.io/deviation-infinity/

Viteでビルドしてgh-pagesブランチへ。単一のReactコンポーネントなので、ビルド設定でつまずくところはほとんどありません。iOSでの動作も確認済みです(軽量モードが自動で有効になり、リバーブを外して発音数を半減、MetalSynthを帯域ノイズに置き換えます)。

ここまでが「動くようになった」段階の記録です。

実のところ、まだチューニングしたい箇所がいくつも残っています。ミニマルモードのプロセスの選び方、EDMのビルドの長さ、鏡面モードの環境マップの質、そして何より、慣れと誤差の閉ループのパラメータそのもの。最適誤差値をモードごとに手で決めていますが、これは本来、聴き手ごとに違うはずのものです。

続きはClaude Codeで最終チューニングをやります。

偏差を成立させるために、地盤を動かないようにする

ここからはClaude Codeに伴走してもらいながらの最終チューニングの記録になります。前回が「動くようになった」段階だとすれば、今回は「聴けるようになった」段階の話です。

やってみて分かったのは、この装置のチューニングは結局のところ、偏差そのものを作り込む作業ではなかったということでした。偏差が偏差として聴こえるための地盤──前回さんざん書いた「予測のベースライン」──を、いかに動かないようにするか。そればかりやっていました。理屈は最初から自分で書いていたのに、実装が理屈を裏切っていたわけです。

Salamanderのピアノを一枚足す

音色に生楽器の芯が欲しくて、レイヤーを一枚増やしました。Tone.jsのCDNにあるSalamander Grand Pianoのマルチサンプルを`Tone.Sampler`で読み込み、`piano`レイヤーとして11レイヤー体制に組み込みます(18音を読み、軽量モードでは5音に落として補間)。

ピアノに与えた役割は、STABの刻みでもPADの持続でもない、その中間の分散和音です。8分グリッド上を、いまの和音度に追随しながらアルペジオで動きます。音高をパターンに絶対値で持たせず和音度からの相対で保持するのは、前回ACIDとBASSでやったのと同じ考え方です。一度この方式に揃えておくと、和音が動いたときに取り残される層が出ません。

ひとつ意図的にやったのは、ピアノを偏差オペレータの対象から外したことです。刻みや土台は揺らしていいが、生ピアノの分散和音まで毎小節いじると、せっかくの「芯」がぼやける。偏差を掛けない層をあえて置くのも、全体の予測を成立させるための配分だと考えました。

予測の地盤を、本当に不動にする

再生を長く回していると、だんだんグルーヴが崩れていくのに気づきました。四つ打ちのはずのキックに穴が空く。小節の頭がずれる。クラップが裏に回り込む。全部、**偏差オペレータが地盤そのものを侵食していた**のです。

考えてみれば当然で、ROTATE(回転)・PHASE(位相ずらし)・EUCLID(再構成)・SUBTRACT(削除)・FLIP(反転)は、対象レイヤーを選ばずに掛かっていました。キックが回転すれば小節の頭が動く。クラップが反転すれば裏拍にクラップが増える。偏差を測る基準そのものが、偏差によって動いていたわけです。これでは前回書いた「反復が強いほどベースラインが固まり、小さなズレが際立つ」が原理的に成立しません。**基準が動くズレは、ズレとして聴こえない。ただ崩れて聴こえる。**

そこで、地盤に当たる要素を「アンカー」として明示的に保護しました。

- キック:ROTATE / PHASE / EUCLIDの対象から除外。FLIPとSUBTRACTは四つ打ちの格子(step 0・4・8・12)に触れない。
- クラップ:バックビート(step 4・12)に固定。裏拍へ出さず、表拍(0・8)のゴーストだけ許す。
- サブ:もともと偏差の対象プールに入っていなかったので、位相と小節頭だけ再確約。

そして偏差を1回適用するたびに`enforceAnchors()`という後処理を必ず通し、**何が起きてもキックの四つ打ち・クラップのバックビート・両者の位相をゼロへ戻す**ようにしました。「まず何をしても地盤へ戻す、その上で遊ぶ」という順序です。抜き差し(ドロップやブレイク)は従来どおりエネルギーゲートによるレイヤー単位の出入りで表現し、パターンの穴では壊さない。ここを分離したのが効きました。

BASSはKICKと噛んでから遊ぶ

同じ発想でベースも直しました。生のドラムとベーシストの関係がそうであるように、ベースはまずキックと噛んで土台をロックし、その上で遊ぶべきです。

計測すると、これまでのベースは主に裏拍中心で、キックの拍には低確率でしか乗っていませんでした。ロックできていない。そこで、**小節の頭では必ず根音で着地**し、他のキック拍(4・8・12)にも高確率で乗り、8分裏で遊ぶ、というパターンへ組み直しました。`enforceAnchors()`は小節頭の根音ロックだけを確約し、残りは偏差で自由に動かせるようにしてあります。

さらに、サブを現在の和音の根音に追随させました。これで**キック・サブ・ベースが同じ土台の音名を共有し、和音が動けば三者一緒に動く**。前回ACIDを和音追随にした瞬間にベースが取り残された話を書きましたが、今回はその低域版を、最下層まで揃えた格好です。

スタッターの後、音が二度と戻らない

「bar 80あたりで飽和して音が出なくなる」という報告をもらいました。これが今回いちばん厄介で、いちばん面白いバグでした。

症状としては、しばらく回していると突然マスターごと無音になり、二度と復帰しない。前回の「20小節で飽和して止まる」に似ていますが、今度はセクションもカウンタも進み続けているのに音だけが消えます。

犯人はスタッターでした。信号経路の最後段近くにある`stutterGain`──マスターを断続させるためのゲイン──が、`0.015`(ほぼ閉)で固着していたのです。

順を追うとこうです。スタッター最終小節のstep 15で、`stutterGain`を各スライス末に0.015まで閉じる予約が入ります。その直後に走る小節処理が`stutterLeft`を0まで減らし、`setValueAtTime(1, time + 0.001)`でゲインを開き直そうとする。ところが**この復帰予約は、step 15の「閉じる」勾配(最大で約1ステップ後)よりも前の時刻に置かれていた**。だから後から来る閉じ勾配が復帰を上書きし、ゲインは0.015で残る。そして`stutterLeft`はもう0なので、以降どのステップもこのゲインに触れない。**装置は自分で自分を消音し、二度と口を開かなくなる。**

WebAudioのスケジューリングは、同じパラメータに対して「後の時刻の予約」が「先の時刻の予約」を上書きするのではなく、時間軸上に並べた自動化として素直に実行されます。だから復帰を先に置いても、後から閉じられれば負けます。

直し方は、復帰時に未来の閉じ予約を`cancelScheduledValues`で全部取り消してから、確実に開き直す。たった数行ですが、これで無音の呪いは解けました。

前回「状態を持つAPIを未来の時刻で叩いてはいけない」と書きましたが、今回の教訓はその隣です。**時刻指定の自動化は、書いた順ではなく時刻の順で効く。**「後で開けばいい」は、その"後"が"閉じる予約"より前にあれば意味がない。先読みスケジューラを書くなら、値を戻す予約は必ず、戻す対象の最後の予約より後ろへ置く。

象徴的なバグでもありました。地盤どころか、装置がまるごと沈黙する。予測誤差を追い求める機関が、最大の予測誤差である「無音」に落ちて戻ってこない。

BASSとACIDが、キックから滑って聴こえる

「タイミングがずれている気がする」という指摘。発音予約自体はキックと同じ時刻に積んでいるので、名目上は合っています。犯人は音色側でした。

ベースもアシッドも、**ポルタメント(グライド)が全音符に55msかかっていた**のです。ピッチが変わってキック拍に着地する音は、前の音から55msかけて滑り込む。キックの瞬間的なアタックに対して、必ず後ろへもたつく。前回「スライドはレガートの重なりで作る」と書いておきながら、実際は常時グライドが全音に効いていました。書いた本人が罠を踏むやつです。

既定のグライドを20msまで詰め、スライダーの下限を0msまで開けて完全なハードロックも選べるようにしました。スライド感はこれまで通りレガートの重なりで作ります。位相が正確でも輪郭が滑ればずれて聴こえる、という前回のキックの教訓の、旋律版でした。

ミキサーをdBで詰める

音量バランスの追い込みは、最終的にdBで指定する形に落ち着きました。ミキサーの表示は`20log10(gain)`なので、`dbToGain(dB) = 10^(dB/20)`で線形ゲインへ変換して規定値に埋め込みます。

| レイヤー | 規定値 |
|---|---|
| KICK | +0.7 dB |
| SNARE | −5.8 dB |
| CLAP | −2.5 dB |
| PIANO | −1.1 dB |
| BASS | −14.9 dB |
| ACID | −20.0 dB |

ACIDは最後に−20.0 dBまで落としました。あくまで味付けで、表に出過ぎない。前回あれだけ音痴を直したレイヤーを、最終的には奥へ引っ込めたわけです。直すことと出すことは別問題で、正しく鳴るようにしたからこそ、小さく混ぜても濁らずに効く。ベースを−14.9 dBに置けるのも、低域の地盤をキック・サブと噛ませて整理したからです。

ステップ行列を、映像に重ねる

いま何が鳴っているのかを目で追えるように、ビジュアライザにステップシーケンサの行列を重ねられるようにしました。格子ボタンで、OFF →「行列」(レイヤー×16ステップの行列)→「16分」(縦グリッドと再生ヘッドだけ)と切り替わります。

ここで、ステップシーケンサーに音高表示を追加しました。BASS、PIANO、ACIDでは音の高さの変化が重要だからです。音が上下する行は、高さを2倍にして音高がわかりやすいようにしました。

行列モードでは、各行の左にKICK・SUB・SNARE…とレイヤー名を出し、発音するセルを点灯、アクセントは強調、現在ステップは明滅、再生ヘッドが青い縦線で走ります。前回作った予測誤差スコープが「状態」を見る計器だとすれば、これは「譜面」を見る計器です。地盤の固定作業をやっている最中は、これがそのまま検証装置になりました。キックの格子が動かないこと、クラップが裏に出ないことが、目で確認できる。

「おまかせ」で、展開に映像を委ねる

最後に、音の展開に合わせてビジュアライザを自動で切り替える「おまかせ」モードを付けました。

セクション種別とエネルギー帯を見て、静かな区間(イントロ/ブレイク)は小節時計に解説とステップ行列、盛り上げは鏡面に行列、最高潮のドロップは溶けるアシッドで画面を邪魔しない、という具合に、ビジュアライザ・グリッド・字幕をまとめて割り当てます。手動でどれかを触れば、おまかせは自動で解除されます。

「ビジュアライザも偏差で展開してほしい」という注文もありました。実はこれは最初から半分実装済みで、偏差が起きるたびに色相が跳び、回転が反転し、パルスが放たれる仕組みが入っています。今回はそこに、偏差の累積回数を切り替えキーに織り込みました。偏差が8回たまるごとに「era」が進み、同じセクションのなかでもアシッドと鏡面が入れ替わる。偏差そのものが、映像の展開を駆動する。音の側で追い求めている「予測を成立させて微細に揺らす」が、映像の側にも一本の線として通りました。

何を学んだか

前回の記事は「予測を成立させ、その予測を微細に揺らす」を制御則として書きました。今回やったことは、ほぼ全部その裏面です。**揺らす前に、揺れない場所を確保する。**

キックの四つ打ち、クラップのバックビート、キックとサブとベースが共有する根音、キックに噛んだベースの小節頭。これらは偏差の対象ではなく、偏差が偏差として知覚されるための不動点です。装置は放っておくと、変化を求めるあまり地盤まで食べてしまう。スタッターに至っては装置ごと沈黙した。自由に揺らせる範囲は、揺らさないと決めた地盤の広さで決まる。これは音楽に限った話ではない気もします。

まだ残っているものもあります。おまかせの切り替えの呼吸、ピアノの混ざり具合、そして相変わらず手で決めている慣れと誤差の閉ループのパラメータ。ここは本当は聴き手ごとに違うはずで、いつか誤差の最適帯そのものを、聴取のふるまいから推定させたい。

とはいえ、今は素直に聴ける状態になりました。ぜひ、皆さんもお試しください。

※この記事は、Claude Fable 5、Opus 5、Opus 4.8との対話を元に原稿を生成し、それに筆者が整理・追記したものです。

《松尾公也》

Amazon売れ筋ランキング

松尾公也

テクノエッジ編集部 シニアエディター / コミュニティストラテジスト @mazzo

特集

BECOME A MEMBER

『テクノエッジ アルファ』会員募集中

最新テック・ガジェット情報コミュニティ『テクノエッジ アルファ』を開設しました。会員専用Discrodサーバ参加権やイベント招待、会員限定コンテンツなど特典多数です。