128 Voices Generator by 0b5vr
https://youtu.be/y0DOxMxbgdc
128 Voices Generator by 0b5vr Appeared in Lovebyte 2024 Bytebeat Music Compo Write-up
Beautified Code
code:js
H=i=128,
s=t/5e3,
F=i=>((57454323>>4*i&31)-(s>>3&4))/12,
sin(40*log(s%4)+9*s)/3
+s%4*(
exp(-s%1*2)*(
(t*2**[
F(7)-2,
5+i/90,
F(~~s-4*(i<48))+i%4/H
)
+(t*2**(F(i%7)-(i/2&1))+1e4*sin(i+s/H))%H-64
)/H
})(),
o
H は様々な用途で使われる定数 128
i は 128 から 1 まで1ずつデクリメントされていくループ用インデックス
o は最終出力 (2 channels)
F (pitch function)
F はコードの構成音から1つpitch (log2 of frequency) を持ってくる関数
57454323>>i*4&31 は、引数となる整数 i が 0 から 7 まで変化するごとに
19, 15, 14, 10, 12, 22, 3, 0 と変化する
code:heck
1P 3m 7m^ 1P^ 7m 2M^ 3m^ 5P^
0 3 22 12 10 14 15 19
0000 0011 0110 1100 1010 1110 1111 0011
= 57454323
s>>3&4 はstepが32変化するごとに4半音トランスポーズを行う
最後に /12 で割って十二平均律の音階にしてやる 実際に2の肩に乗っけるのはこの関数を使うとき
The loop
(_=>{while(i--)o[i%2]+= ... })()
本コードの肝となるループ部分
bytebeat.demozoo.orgにおいて、入力したコードは式として評価されるため、ここに文(statement)を置くことはできない
ただし、式の中で即時関数を実行することはできるので、その中でwhile文を実行してしまう さらに、式の中でカンマ区切りで複数の式が使われている場合、返り値となるのは最後の式であることを利用する (最後の ,o )
o[i%2]+= によって、左右のチャンネルそれぞれ交互に各64回加算代入がされる
Kick
sin(40*log(s%4)+9*s)/3
sin の中に log を入れることによって鋭いアタックを生み出すことができる
いままでずっと exp でやっていたが、sizecodingにおいては log はたいへん優秀
log(0) で -Infinity ができてしまうのであんまりお行儀は良くない。logの中の式に 1e-3 とか適当な定数を足してやったほうがお利口
リリースの太さを調整するため、 9*s を追加した
Sidechain
s%4
後述するBass, Hihat, Arp, Chordに対してかかるサイドチェイン 極めてシンプルだが、あるとないとでは音のメリハリが全く変わってくる
Bass, Hihat, Arp
code:js
exp(-s%1*2)*(
(t*2**[
F(7)-2,
5+i/90,
F(~~s-4*(i<48))+i%4/H
)
どれも &H によって矩形波を生成しているが、 i%3 でループごとに3種類の音階を選択して実現している
F(7)-2 がBassに対応
単純に F から生成した主音を2オクターブ下で鳴らしているだけ 5+i/90 がHihatに対応
F(~~s-4*(i<48))+i%4/H がArpに対応
i%4/H によってDetuneのかかったユニゾンを生み出す 共通部分の s%1*i/5 は、ユニゾンごとに少しだけ位相をずらすことによってエンベロープのかかったLPF的な効果を生み出している Bassで特に顕著
以下に、式内の各項が i ごとにどうなっているかを表で示す
Chord
F(i%7)-(i/2&1) の部分は、左右チャンネルでバランスよく聞こえるようやや説明の面倒な数字あそびをしているものの、結局はコードの構成音を2オクターブにわたって鳴らしたいだけ
位相のシフト 1e4*sin(i+s/H) によってムラのないDetuneを生み出す 下手にピッチに対して i/H/H とかを足しちゃうと、再生開始直後にFlanger的な違和感のある音が生まれてしまう