コーディングで編曲をした話 🎼
この記事はCPS Lab Advent Calendar 2017の22日目の記事です。21日目はたこ(Takorras_)さんの”雰囲気でTwitterクライアントを作った”でした。UserStream廃止問題、一体どうなってしまうんでしょうか…
e_ntyoです。私はB2で研究室の人間ではないのですが、この1年でCPS Labの教授や先輩方に色々なことで助けて頂いたので、お礼に記事を寄稿いたします 🙏
ここまでですます口調でしたが、元々アドベントカレンダーとは関係なしに書いていた記事なのでここから言い切り口調です。あしからず 🙇
この記事の想定読者
- 音楽/作曲/編曲に興味のあるプログラマ
- DJやDTMなど音楽関係の趣味を持っているオタク
- コーディングによる演奏やアルゴリズミック・パターンに興味のあるオタク
TL; DR
- 作曲経験がなく、音楽理論の知識も乏しいプログラマがコーディングによる作曲(編曲)を学んだ。
- 👆 の所感として、コーディングでフレーズやリズムのパターンをつくるのは比較的簡単だったが、曲を作るのは大変だった。DTMソフトやMIDIコントローラのようにコーディングは作曲の手段の一つに過ぎない。使いどころを選んで使うべきものであり、銀の弾丸ではない。
きっかけ
通っている大学(情報系)の必修科目で、音(響)系のプログラミングの演習があった。当然受講者は自分を含め情報系のパソコンオタクであり、まともに楽譜も読めないという者がほとんどだった。そのため、DTMソフトのインストールや楽譜の読み方から始まり、MIDI規格とMIDIプログラミングを学び、Audacityをいじったり…という流れだった。具体的には以下の通り。
- Studio One 3 Prime のインストールと音楽の基礎
- MIDIについて
- Audacityをもちいた オーディオ信号の加工と編集
- マルコフ連鎖による自動作曲
- 編曲作品制作
- 作品発表
作品発表では各自が”きらきら星”か”メヌエット”を編曲し、全員の前で披露する。結構楽しい授業だった。
ちょうどこの科目が始まってすぐの頃、@amagitakayosi さんが TidalCyclesでライブコーディングに挑戦しよう をpublishした(読め!)。ライブコーディングは即興でエクサイティングな音楽を展開できるという事実は、自分にとってとてつもない衝撃だった。
ほとんどの履修者はDTMソフトを使って作曲をしようとしていたが、このことがきっかけでコーディングで曲を作ってみようというやっていきが生まれた。
TidalCycles と SuperCollider
すぐにTidalCyclesで課題の制作をしようとしたが、少しいじってからこれは一般的な作曲(編曲)のための道具ではないなと感じた。TidalCyclesはライブコーディングのためのツールで、1つの曲ではなく繰り返されるリズムパターンやフレーズを作っていく。 ライブコーディングのように人がその場その場で曲調を変えていくならばいいのだが、イントロ -> Aメロ -> Bメロ -> ...
のような予め決められた進行を一度のコーディングですべて定義することは現実的でない。そこで、TidalCyclesが内部で利用しているSuperCollider(正確には、SuperColliderをベースにした音響生成エンジンのSuperDirt)を直接使うことにした。
こう書くとSuperCollier(スーパーコライダ)はなんだか低レベルで難しそうな言語で制御するようなものに感じられてしまうかもしれないが、SuperCollider自体も強力な音響プログラミング環境である。TidayCyclesから利用できる Synth(楽器/音色の定義のようなもの)を作成したり、合成した音を波形を見ながらデバッグしたりすることができる 😃
(From: http://supercollider.github.io/)
また、Open Sound Controlという次世代MIDIのような規格をサポートしており、MIDIコントローラの入力を受け付けたり、SuperColliderで作成した音をVEDAのようなソフトウェアに渡してリアルタイムにヴィジュアライズすることもできる。(自分はまだやったことがないので、やる。)
何より、TidalCyclesほど強くパターンの世界に縛られないため、やろうと思えば1つの曲を作ることもできそうだったし、実際やっている人もいた。yatteiki… 💪
SuperColliderで作曲(編曲)をする
まず、自分が最終課題として提出した作品を載せておく。
以降ではどのようなアプローチでこれを作ったかを振り返っていく。
1. パターンを定義する
「結局パターンかよ、さっきはSuperColliderはパターンの世界に縛られないとか言っていたじゃないか、お前はいつだってそうだ、あれこれ言いながら結局はいつも同じ、そんなだからお前は……」
みたいなことを考え続けていると鬱になる。気を付けよう ⚠️
さっきからパターンパターンと言っているが、パターンとは何だろうか?この文脈でのパターンとは、1回以上繰り返される旋律/リズムで、つまりは楽譜の五線譜の上に書いてある情報である。
この譜面のリズムは、コードでは以下のように表される。
超カンタン😄
Pbind()
は、楽器やリズムパターンなどを指定して実際に音を鳴らすための関数だ。 Pseq()
は組み込みのデータ型で、名前の通りシーケンス型である。第二引数に繰り返し回数を指定することで、第一引数で指定したパターンを繰り返すことができる。
リズムに加えて、各ノーツの音の高さも考慮して旋律を奏でてみる。冒頭で挙げた課題曲のきらきら星のワンフレーズは、こんな譜面である。
この譜面は、次のように表現する。
このように、作曲/編曲のようなあらかじめどういうパターンを定義したいのかが決まっている場合は、コードに落とし込むことが容易であった。先の自分の作品のコードでも同じような手法でフレーズを定義している。
余談1. アルゴリズミック・パターン
本題からは逸れるが、せっかくなのでSuperColliderの元来の用途であるアルゴリズミックなフレーズの生成についても少しだけ紹介したい。詳しく知りたい方はググるとコードがドサドサ出てくるのでぜひ。
以下のコードを実行すると、どんな音が鳴るだろうか ❓
こんな音が鳴る。
大変だ。先程の退屈なキックのコードとほぼ変わらないコード量で、天才キーボード奏者の演奏を表現できてしまった。
一気にコードが読み解きにくくなってしまったので、少し解説する。
まず、3行目の \degree
で各ノーツ(音符のようなものだと思ってほしい)の音の高さをパターンとして定義している。そして、先の例ではパターンの表現に Pseq
を使っていたが、ここでは Ptuple
というデータ構造を使っている。そう、この文脈で Ptuple
を使うことで、和音を表現することができるのだ。要素数を3音, 4音, …と増やしていくことでより多くの種類の高さの音を同時に鳴らすことができる。
さて、注目すべきは、 Ptuple
のコンストラクタで使われている Pwhite()
と Pbrown()
である。こいつらはそれぞれ一様分布の乱数とブラウン運動のシミュレーション結果を返す関数で、引数で指定したレンジの中から規則的/不規則的に値を返してくれる。つまりこの文脈では、 Pwhite()
は低音域, Pbrown()
は中/高音域の自動演奏をしてくれるわけである。キーボードなら左手の担当がPwhite()
, 右手の担当がPbrown()
だろう 🎹
\dur
ではなんだか難しそうなことをしているようだが、単にPbrown()
の返した値(つまり高音域の音)に応じてノーツの長さを変えているだけである。 \db
も単純で、引数で与えた成功確率pのベルヌーイ試行(表の出る確率pを引数で自由に操作できるコイントスシミュレーションである)の結果に応じてデシベル数を変えている。音に微妙な強弱を付けているわけである。
Pwhite()
, Pbrown()
のような関数は他にも Pgauss()
, Ppoisson()
など多数用意されており、使いこなせばイケイケなリズムパターン/フレーズを作ることができる。ぜひ試してみてほしい、と言いたいところだが、こういうことがしたいならそれこそTidalCyclesを使うべきだろう 😢
余談2. Webページに楽譜をレンダリングするJSライブラリ
もう一つ小話を。パターンの節で登場した楽譜は、実はabc.jsというJavaScriptライブラリで描画されたsvg(をエクスポートの仕方がわからなかったからスクリーンショットしたもの)だ。
X: 1
M: 4/4
L: 1/4
U:n=!style=x!
K:perc
V:ALL stem=up
|: F1 F1 F1 F1 :|
と、JavaScriptのコード内でabc記法を書くと、
先程の無限キックの譜面がレンダリングされる。 👆 は繰り返すように画像なので、興味のある方はここでリアルタイムにレンダリングされることを確認してみてほしい。(スゲー!)
コイツの存在はこの記事を書き始めてから知った。
2. 楽器を定義する
余談に花が咲いてしまった。記事はあと少しで終わるのでもう少し付き合って頂きたい。
パターンを作れた段階で演奏は成立するのだが、すべての旋律が同じ楽器の同じ奏法というのは少し物足りない。使う楽器やその奏法を変えてみたいところだが、SuperColliderではそうしたデータを波形を組み合わせて自分で定義する。なんというDIY精神であろうか!ちなみにTidalCyclesでは予め多くの種類のサンプルが提供されている。
これから説明する内容は音屋さんでいういわゆる音作りの作業であり、ご存知の通り、これはアルゴリズミック・パターン同様詳細に説明しているとキリがない。したがって、ゆるふわっと入門するに留めたい。より詳しく知りたい人はyoppa氏の講義資料などを参考するとよいと思う。日本語だしめちゃめちゃわかりやすかった。
さて、これまで音を出すのに使っていた Pbind()
では、 \Synth
でシンセサイザ(楽器)を指定することができる。以下のコードは、アルゴリズミック・パターンの節で紹介したコードに、楽器の定義とそれを使うための変更を加えたものである。
音色がピコピコした感じになっている。
コードをさっと読んでいこう。
1行目の SynthDef()
は、正弦波のオシレータを使った楽器を定義している。WebAudioAPIなどを触ったことがない方は”正弦波のオシレータ”と言われてもなんのこっちゃと思うかもしれないが、何の変哲もない音を鳴らす装置だと捉えてほしい。気になる方は以下のようなツールで確認できる。マジで何の変哲もない音が鳴る。
Our waveform generators deliver accurately calibrated sound files, with adjustable frequency and amplitude.www.audiocheck.net
SynthDef()
での記述についてもう少し掘り下げる。3行目の Out.ar()
では出力先のチャネルと鳴らす音(正弦波のオシレータ SinOsc.ar()
と、直線 Line.kr()
を掛け合わせたもの)を指定している。
2つの信号の掛け合わせによって、再生後線形に音量が小さくなっていくホンモノの楽器のような音が表現できた👏
ここで、Line.kr()
ではSynthDef()
で取った sustain
という引数が使われている。sustain
はエンベロープという、言ってみれば楽器の”鳴らし方”を指定するために使われる用語である。振幅(音量)の変化を sustain
を含む4つのパラメータで表現する場合が多い。
例えばスネアドラムは、同じチューニング(面の張り具合を調整する)でも叩き方に応じて鋭かったり、柔らかかったり、痛そうだったり、色々な音が出る。エンベロープはそういった音のニュアンスを表現するために使う。SuperColliderにおけるエンベロープについてはこちらの説明が詳しい。
長くなったが、このようにして、波形を組み合わせることでオリジナルのサステインや音色を定義し、 Pbind()
等から呼び出せるよう定義することができる。もちろんこうしたコードを毎回一生懸命作っていては死んでしまうので、今回の課題では多くの先人たちの楽器を使わせていただいた。
SynthDefs-for-Patterns - Collection of SuperCollider SynthDefs (synth definitions) for use with Patternsgithub.com
supercollider-music - 🎼 Various songs & noises I've composed and programmed in SuperCollidergithub.com
マリンバの音とかは一体どうやって作ったのだろうか。ザ・プロフェッショナルを感じた。
3. 複数のパターンを同時に鳴らし、曲にする
ここまでお付き合い頂いたことに感謝したい 🙏 1, 2でやったことが編曲作業の8割である。
残りの2割は、それぞれのパターンをうまいことコントロールして同時に鳴らすだけである。私は知能指数が3しかないので、本物の楽譜のようにそれぞれのパターンの\dur
を休符を含めてうまいこと表現して、すべてのパターンを同時に再生するという手法を取った。マジで知性がない。
外部音源を鳴らしたりコレクション操作の関数を使ったりしているため気になる記述があるかもしれないが、基本的にやっていることは1, 2で紹介した内容に毛が生えたようなことである。これらについて質問があればTwitter等でいつでも聞いてほしい。できればその際「生きていてもいいんだよ!」とかそういう適当な肯定的な言葉をかけてほしい。毎日がつらい。
おわりに
以上が大まかな編曲作業の流れである。課題なので時間的な制約もあり最初に紹介した自分の作品のクオリティはいまいちだったが、インターネッツには様々な趣向を凝らした素晴らしい作品が溢れている。TidalCyclesについても同様である。ぜひこの冬休みで音プログラミングの世界へ遊びに行ってほしい。私もやっていきのモチベーションが高いので一緒にやろう!
明日はSuccessLeaf氏です。楽しみにしております〜