🎼

楽曲生成ライブラリEuterpeaの紹介

に公開

はじめに

Euterpea(ユートピア)とは、MIDIプロトコルを出力できるHaskellのライブラリです。例えば、EuterpeaとKORGのVolcaシリーズを使用して以下のようなリアルタイムにランダム生成した楽曲の演奏などが可能です。
https://youtube.com/shorts/ZoBRGx9aAPA?feature=share
フルはこちら

この記事では概要だけ紹介します。詳しく知りたい箇所があったら追記等します。

MIDI

MIDIとは電子楽器の演奏情報をやり取りするプロトコルであり、多くの電子楽器で入出力可能です。PCからも以下のケーブルなど使って出力出来ます。
https://www.amazon.co.jp/dp/B08XYVV6YM?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
Volca fmの場合は追加で以下とオスメスマッチさせるための変換が必要です。スプリッタか変換端子か。
https://www.amazon.co.jp/dp/B09GFPY2P3?ref=ppx_yo2ov_dt_b_fed_asin_title

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演奏が出来てしまうわけです。

任意のフレーズを記述したい場合は上記の記法は冗長ですので、適宜変数関数を自分で定義して使います。私の場合は以下のようにドラムンベースのドラムパターンを記述できるようにしています。linechordはそれぞれリストを直列、並列に適用する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を以下のように構成しています。

ピアノ:コードをアルペジオしつつ、並行メロディとしてコード構成音を経過音含めてランダムウォークさせる。終わりの音は必ずコード経過音となるようにする。

https://youtube.com/shorts/9qz3xWTJOGM?feature=share
以下も同様にメロディ生成しています。
https://www.youtube.com/watch?v=2Z5ABQkJiJE

以下のジャズのアドリブに関する書籍が役に立っています。これでもこの本に記述されていることの1/4も利用していないです。
https://www.chuya-online.com/products/222771/

かなりシンプルな理論のみを利用しているにも関わらず、結構聴ける音になっているのではと思います。

おわりに

初心者の状態で音楽理論がどれほど役にたつのかを試したくEuterpeaを触り始めました。1ヶ月ほど試しましたが結構良い感じに音楽出来ていると思い満足しています。Youtubeでの反応がいまいちなのでもっと音楽を勉強してやるぞという気持ちがありますが、出来たところで当人のセンスの悪さが出ているようで、それもちゃんと磨かないとなと思っています。また曲の生成は繰り返しパターンが多くHaskellの成熟した関数群が役にたっています。Haskellの勉強にもこの課題は良かったなと思います。

Discussion