楽曲生成ライブラリEuterpeaの紹介
はじめに
Euterpea(ユートピア)とは、MIDIプロトコルを出力できるHaskellのライブラリです。例えば、EuterpeaとKORGのVolcaシリーズを使用して以下のようなリアルタイムにランダム生成した楽曲の演奏などが可能です。 フルはこちら
この記事では概要だけ紹介します。詳しく知りたい箇所があったら追記等します。
MIDI
MIDIとは電子楽器の演奏情報をやり取りするプロトコルであり、多くの電子楽器で入出力可能です。PCからも以下のケーブルなど使って出力出来ます。
Volca fmの場合は追加で以下とオスメスマッチさせるための変換が必要です。スプリッタか変換端子か。Hello World
以下はEuterpeaにおけるHello World的なコードです。Volca fmなどをつないだ状態であれば、ドの音が1拍として出ます。getAllDevices >>= print
の結果を確認し、所望のMIDIインターフェースに割り振られたIDをdevId
で指定して下さい。私の場合は上記のUSBインターフェースが2でした。
hello_world.hs
import Euterpea
import Euterpea.IO.MIDI.MidiIO
main = do
getAllDevices >>= print
let
customChannelMap = [(AcousticGrandPiano, 0)] --MIDIチャネル指定
devId = Just $ unsafeOutputID 2
params = PlayParams -- おまじない
False
(predefinedCP customChannelMap) devId
1.0 perform1
m = note qn (pitch, volume) :: Music (AbsPitch, Volume)
where
pitch = 60 :: AbsPitch -- MIDIでのド
volume = 100 :: Volume
-- m = c 4 qn :: Music Pitch -- 別の記述でのド
-- 利便性のために関数合成しておく
playPiano = playC params . instrument AcousticGrandPiano
playPiano m --MIDI出力
Music記述例
Euterpeaでは音をMusicという型の変数として扱うことが出来ます。例えば上記のHello Worldコードでは以下でドを1拍で音量100として指定していました。
m = note qn (60, 100)
以下はドミ、一拍休んでソを連続で出します。
m = note qn (60, 100)
:+: note qn (64, 100)
:+: rest qn
:+: note qn (67, 100)
以下はドミソを一斉に出します。Cの和音ですね。
m = note qn (60, 100)
:=: note qn (64, 100)
:=: note qn (67, 100)
このように、:+:
を直列、:=:
を並列出力とした二項演算子が定義されています。これらを利用して曲を作っていきます。これをランダム関数を使って構成すれば、DTMソフトを使用しなくてもMIDI演奏が出来てしまうわけです。
任意のフレーズを記述したい場合は上記の記法は冗長ですので、適宜変数関数を自分で定義して使います。私の場合は以下のようにドラムンベースのドラムパターンを記述できるようにしています。line
とchord
はそれぞれリストを直列、並列に適用するEuterpeaの関数です。snR,snT,snK
は16分音譜1つ分の休み、タム、キックです。
m1 = chord $ map line
[
[snR, snR, snR, snR, snT, snR, snR, snT, snR, snT, snR, snR, snT, snR, snR, snT, snR, snR, snR, snR, snT, snR, snR, snT, snR, snT, snT, snR, snR, snT, snT, snR]
, [snK, snR, snR, snR, snR, snR, snR, snR, snR, snR, snK, snR, snR, snR, snR, snR, snK, snR, snK, snR, snR, snR, snR, snR, snR, snR, snR, snR, snR, snR, snR, snR]
]
MIDI関係便利コマンド
Linuxのみです。以下はMIDIインターフェースをリストアップします。Hello WorldのgetAllDevices
と内容が一致するはずです。
$ aseqdump -l
Port Client name Port name
0:0 System Timer
0:1 System Announce
14:0 Midi Through Midi Through Port-0
32:0 CH345 CH345 MIDI 1
上記結果のPort列を以下で指定すると、EuterpeaからのMIDI出力結果を確認できます。MIDI機器でループバックして入力しています。音が出ない時の確認に多用します。チャネルが違ったりは多く発生しますので。
$ aseqdump -p 32:0
Waiting for data. Press Ctrl+C to end.
Source Event Ch Data
32:0 Note off 0, note 67, velocity 100
32:0 Program change 0, program 0
32:0 Note on 0, note 60, velocity 100
32:0 Note off 0, note 60, velocity 100
32:0 Note on 0, note 64, velocity 100
32:0 Note off 0, note 64, velocity 100
32:0 Note on 0, note 67, velocity 100
32:0 Note off 0, note 67, velocity 100
注意点
現在のhackageのEuterpeaバージョンでは同じ音が連続出力すると時々音が消えてしまいます。githubの最新では修正が成されているようです。
音楽理論の助け
冒頭の動画ではVolca drumとnubassをベースラインとドラムとして以下のようにランダム出力していました。ベースは音楽理論の基礎を適用しました。
ドラム:予め定義した複数フレーズのランダム選択、ハイハットをランダムで1回たたきから2回へ。
ベース:2-5-1-6のコード進行で構成音をランダム選択、長さもランダム選択。
以下ではもう少し理論を勉強し、Volca fmを以下のように構成しています。
ピアノ:コードをアルペジオしつつ、並行メロディとしてコード構成音を経過音含めてランダムウォークさせる。終わりの音は必ずコード経過音となるようにする。
以下も同様にメロディ生成しています。
以下のジャズのアドリブに関する書籍が役に立っています。これでもこの本に記述されていることの1/4も利用していないです。
かなりシンプルな理論のみを利用しているにも関わらず、結構聴ける音になっているのではと思います。
おわりに
初心者の状態で音楽理論がどれほど役にたつのかを試したくEuterpeaを触り始めました。1ヶ月ほど試しましたが結構良い感じに音楽出来ていると思い満足しています。Youtubeでの反応がいまいちなのでもっと音楽を勉強してやるぞという気持ちがありますが、出来たところで当人のセンスの悪さが出ているようで、それもちゃんと磨かないとなと思っています。また曲の生成は繰り返しパターンが多くHaskellの成熟した関数群が役にたっています。Haskellの勉強にもこの課題は良かったなと思います。
Discussion