見出し画像

explain("expla1n(self)")

どうも、多分ボカロ界で初めて Quine を組み合わせた曲を作った 名無し。 です。
expla1n(self)の解説を書いてみようと思います。
当然ですが、曲を先に聴いておくことを推奨します。


全体

  • この曲のテーマは「自己言及」です。

    • タイトルもその通りです。

    • 歌詞側では「この曲を作っている時の状況」、MV では Quine でそれを表現しています。

  • もともと Voicevoxソングエディタ、もっと言えば開発中のVSTプラグインのテスト(ドッグフーディング)として作った曲です。

    • 実際かなり収穫が得られました。

  • 1作目だから explainのiを Leet表記 で1にしてexpla1nにしました。

    • 2作目もどこかに入れてみたい…けど2(z)入れるの不可能では?

      • toならまだいけるか?

そもそも Quine って何?

Quine とは自分自身を出力するプログラムのことです。

irb(main):001> eval(s="puts 'eval(s='+s.inspect+')'")
eval(s="puts 'eval(s='+s.inspect+')'")
=> nil
irb(main):002> eval(s="puts 'eval(s='+s.inspect+')'")
eval(s="puts 'eval(s='+s.inspect+')'")
=> nil

この曲の MV で表示されているのも Quine です。よく拡大すると文字が見えます。

MV 側

  • p5.js でつくりました。

    • せっかくプログラミングやってるので技術力を生かしたかったからです。

  • 基本的には曲と同期しています。

  • p5.capture を使いたかったけどアナライザーと相性が悪かったので断念しました。

アナライザー

アナライザーのレイヤー。

p5.FFTを使っています。ちなみにこれのせいでp5.captureが使えませんでした。

歌詞 / クレジット

歌詞のレイヤー。

歌詞とクレジットを表示しています。

間奏では主に曲側、アウトロではプログラム側のクレジットを表示しています。
また、最後にタイトルと名前を表示するのはmelonade氏を参考にしています。(そもそもp5.jsを使ってるのもmelonade氏の影響)

いはないお約束との比較。

バスドラム / クラップ

バスドラム / クラップのレイヤー。

バスドラムが鳴ると左から、クラップが鳴ると右から円が広がっています。
実際、バスドラムは左に、クラップは右にパンを少しだけ振っています。

Quine

Quineのレイヤー。
拡大

このMVのコードを表示しています。文字は状況に応じて光っています。

光る文字の裏側。

├ コード(Chordの方)、ベース

拡大。コードがGm7、ベースがA2。

例えばC7が鳴っている場合、Quine 内のC、7 が光ります。
ベースも同様に光っています。
MIDI から@patrady/chord-jsを使ってコード表記を生成しています。
見た目重視のため、

  • ハーフディミニッシュセブンス(Cø7)はCm7b5に、

  • メジャーセブンス(Cmaj7)はCM7に、

置き換えています。

└ オープンハイハット / クラッシュ

オープンハイハットが鳴るとH、i、h、a、tがオレンジで光ります。

クラッシュは少し複雑です。
c、r、a、s、hが光るのは共通ですが、3種類の光り方が用意されています:

  • 弱:大文字/小文字片方だけ。(毎回切り替わる)

  • 中:大文字小文字の両方が光る。

  • 強:大文字小文字の両方が光る。光の強さも強め。

弱/中/強はこのように決定されています:

  • 1回だけ鳴るところでは中

  • 2回以上鳴るところでは弱->弱->強

ピアノロール

ボーカル、ピアノソロ(?)、ベル(界隈曲特有のアレ)の音を表示しています。

プログラミング側

ファイル達。ファイラーはfern.vim
  • ソースコードも公開しています:

  • p5.js を TypeScript で書き、それをesbuildの JavaScript API を使って色々してます。

    • 具体的にはQuine用にコード(Codeの方)を足しています。

  • コード簡略化のため、window.pにp5.jsのインスタンスを代入しています。

    • これによりコード内のどこでもp.someMethodのようにアクセスできるようになります。

  • events.cts、midi.cts、voicevox.ctsでMIDIの情報を抜いてコード(Codeの方)を生成しています。

    • hogeData.tsが自動生成されたコード(Codeの方)です。

midiData.ts。混沌。
  • events.ctsでは歌詞とセクション(イントロ、サビ、etc)のコード(Codeの方)を生成しています。

    • events.ymlに歌詞とセクションの情報を書いています。

  • midi.ctsでは@tonejs/midiで MIDI ファイルから必要な情報を抜き出しています。

    • そのままだと大きすぎる&つまらなかったので、gzip 圧縮して base64 でエンコードしています。

      • つまらなすぎる:上のコードとかを光らせる仕様だと、そのままデータを埋め込むとたくさん光る地帯(=7がたくさんある地帯)ができるので、それを避けるためです。

  • 文字の画像に色を付けるのは GLSL で行っています。

    • そのままやるととんでもなく重かったので、文字の画像はキャッシュしています。

  • デバッグツールを幾つか用意していました。

    • Tab でレイヤーを切り替え。

    • Space で再生。

    • P で所要時間をコンソールに流す。(パフォーマンスチューニング用)

    • F でフルスクリーン。

    • R/E で加速/減速。

裏話

  • 生成式MVと界隈曲系MVシステムの相性がかなり良かったです。

  • 高速化周りで色々やっています:

    • 途中まで不必要にWebGLを使っていたため1080x720でも30fpsが安定しないときがありました。(このMVは1920x1080 30fpsで収録している)

    • 文字の色のレイヤーは高速化のためピクセル単位で操作しています。

音楽側

「並んだトラック」
海茶式コード表記によるコード表記。正確な物は配布されているMIDIを参照。

最後に

作曲わりと楽しかったのでまた何か作るかも。
また、DTM 鯖の方々には本当に感謝しています。ありがとうございました。

おまけ

マシュマロも用意しています。質問などどうぞ。(「quest1on:」から始めて貰えるとこの曲ってことが明示されるのでやりやすいのでお願いします)
このノートのコメント欄でも可。


この記事が気に入ったらサポートをしてみませんか?