この記事は早稲田大学AdventCalender13日目くらいの記事です。
#自己紹介
くりむです。
早稲田大学アプリケーション開発サークルA+plusという団体でごく稀にPHP書いてます。
先に言い訳をしておきます。
僕は星野源さんのファンです。
めっちゃ好きです。ANN聴いてます。
#はじめに
逃げ恥流行ってますね。みくりさん(というかガッキー)可愛すぎる。
なんか星野源にイライラしてくる(ただの嫉妬です)。
星野源はエンジニアという設定ですが、こんな話が盛り上がってましたね。
#逃げ恥 で星野源がPHPコードを書いているシーンに着目する人たち
さすがに僕もこんなコード書かない。それなのにこんなに可愛い人とイチャイチャするなんて……。
一体、星野源と僕で何が違うんだ!!!!(何もかもが違う)
↓
ああ、作曲できるかどうかだ。
というわけで、PHPで作曲できるようになれば星野源に負けるところはない!
#PHPで半自動作曲
##音楽理論を学ぶ
コード進行はある程度ルールがあるらしい。
主に次のリンクを参考にしましたが、他にも様々なページを参照しました。
一夜漬け 音楽理論
ぶっちゃけよくわからないので、わかったところまでを簡単にまとめると
- T→D→T or T→S→T or T→S→D→T
- T = I, VIm, I→VIm, IIIm→I(VIm,IともにTだし、気にしないことにした)
- S = IV, IIm, IV→IIm (これは困った。S->Sと並んだときはこれにするか…)
- D = V, VIIm
- IImの次は必ずV
- Iで始まりIで終わる
- メロディは、構成音である同じ音・構成音ではない隣の音・何個か先の構成音、に飛ぶ
- Cならシ→ドで終わる
これくらいで今回は勘弁してください……。
プログラミングはさっぱりだけど音楽理論はわかるよという方も、何かご指摘いただけるとありがたいです。
というわけで、方針としては
- T,S,Dでコード進行をランダムに生成
- T,S,Dに沿ったコードを割り当て
- コードに沿ったメロディを割り当て
で、Cメジャー48小節(8小節繰り返し2回Aメロ/Bメロ/サビ)の曲を作ります。
##TSDランダム生成
先のURLのほか、様々なところで理論を吟味した結果、今回は「T->T->S->T」「T->S->T->T」「T->S->S->T」「S->T->S->T」「T->T->D->T」「T->D->T->T」「T->S->D->T」をランダムで並べて変えたいと思います。
その際、もし「S->T->S->T」の並びが先頭に来ると困るので、念のために最後に先頭をTに書き換えることを忘れないようにする。
これをPHPのコードに落とし込むとこんな感じ(今回は1小節1コードで固定で許してください)。
<?php
$code_movement_list = [
['T', 'T', 'S', 'T'],
['T', 'S', 'T', 'T'],
['T', 'S', 'S', 'T'],
['S', 'T', 'S', 'T'],
['T', 'D', 'T', 'T'],
['T', 'T', 'D', 'T'],
['T', 'S', 'D', 'T']
];//T,S,Dの取りうる動き方(4小節刻み)
$code_movement = [];
for ($i=0; $i < 6; $i++) {
$code_movement[] = $code_movement_list[rand(0,6)];
}
$code_movement[0][0] = 'T';//Tから始まるように
//var_dump($code_movement);
これだと24小節分しか出てこないわけですが、1~8/9~16/17~24で後で繰り返せばいいので放っておきます。
これで先の方針1が完成ということで。冗長な気もしますが。
吐き出したものを多次元配列にしているのは次の処理と関係しています。
あんまりいいコードな気がしないので、ぜひ知見待ってます(そもそもなぜPHPでやっているのか)。
##T,S,Dに沿ったコードを割り当て
先にまとめた理論をコードに落とし込む。
IImの次が必ずVになること、S->Sと並んだときにIV→IImになること、Iで始まるIで終わることを意識する。
<?php
//さっきの続きから
$code_list_t = ['I', 'IIIm', 'VIm'];
$code_list_s = ['IV', 'IIm'];
$code_list_d = ['V', 'VIIm'];//それぞれのドミナントに当てはまるコードリスト
$codes = [];
foreach ($code_movement as $c_m) {
if($c_m == $code_movement_list[6]){
//IImの次は必ずVというルールにより、T→S→D→TのときしかIImが使えない場合分け
$codes[] = $code_list_t[rand(0,2)];
$s_buf = $code_list_s[rand(0,1)]; //SがIImのとき次をVにするために場合分けしたい
if($s_buf == $code_list_s[1]){
$codes[] = $s_buf;
$codes[] = $code_list_d[0];
}else{
$codes[] = $s_buf;
$codes[] = $code_list_d[rand(0,1)];
}
$codes[] = $code_list_t[rand(0,2)];
}elseif($c_m == $code_movement_list[2]){
//S->SのときはIV->IImで決定
$codes[] = $code_list_t[rand(0,2)];
$codes[] = $code_list_s[1];
$codes[] = $code_list_s[0];
$codes[] = $code_list_t[rand(0,2)];
}else{
//IIm使えない
foreach ($c_m as $c) {
if($c == 'T'){
$codes[] = $code_list_t[rand(0,2)];
}elseif($c == 'S'){
$codes[] = $code_list_s[0];
}elseif($c == 'D'){
$codes[] = $code_list_d[rand(0,1)];
}
}
}
}
$codes[0] = $code_list_t[0]; //Iから始まる
$codes[23] = $code_list_t[0]; //Iで終わる
//var_dump($codes);
こんな感じになりました。
あんまりいいコードな気がしないので、ぜひ知見待ってます(大事なことなので)。
以上で方針2終わり。
##コードに沿ったメロディ割り当て
ぶっちゃけここ諦めようと思ってました。
間に合わなかった。
ここまでの成果をサウンドクラウドにあげました。
生成したコードがこちら
array(24) { [0]=> string(1) "I" [1]=> string(3) "VIm" [2]=> string(2) "IV" [3]=> string(4) "IIIm" [4]=> string(2) "IV" [5]=> string(4) "IIIm" [6]=> string(2) "IV" [7]=> string(3) "VIm" [8]=> string(3) "VIm" [9]=> string(3) "VIm" [10]=> string(1) "V" [11]=> string(4) "IIIm" [12]=> string(4) "IIIm" [13]=> string(1) "I" [14]=> string(4) "VIIm" [15]=> string(1) "I" [16]=> string(3) "VIm" [17]=> string(3) "VIm" [18]=> string(2) "IV" [19]=> string(3) "VIm" [20]=> string(4) "IIIm" [21]=> string(3) "VIm" [22]=> string(2) "IV" [23]=> string(3) "I" }
https://soundcloud.com/kurimu-2/ud8ubsecdysv
普通に作曲したほうがマシな曲作れそう
本当にすみませんでした、星野源さんはやっぱり最高だなぁ。
気が向いたら続き製作したいと思います。
このコード進行からすげー曲作ってくれる方いないかな……。
アドベントカレンダー、明日は……僕がこの下書きつくってる時点では埋まってないみたいですね。
〈12.16追記〉
次は@baco16g のGLSL話です!
すごい、僕とは違って真面目な記事だ
何はともあれ、引き続き早稲田大学アドベントカレンダーお楽しみください。