LoginSignup
9
8

More than 5 years have passed since last update.

pretty_midiでコード進行のMIDIファイル生成

Last updated at Posted at 2018-03-03

はじめに

以前コード進行を自動で生成してくれるサービスを作成した。
https://chordprogressor.herokuapp.com/
https://qiita.com/Giita2000/items/b0a500762a127b7ad69b
このときは生成したコード進行を表示するだけだったが,楽器を弾かなくてもコード進行を耳で確認できれば便利。

pretty_midiを用いたMIDIファイル生成

そこでWeb上で鳴らすことを考え,生成したコードを鳴らすMIDIファイルの作成をpython上でできる方法を探したところ,pretty_midiというライブラリが良いみたい。
https://qiita.com/tackey/items/d0525798bddc4516f4f9

鳴らす音を一個づつ加えていけば良いので,コード進行を文字列で入力すればmidiファイルが出来上がるように関数化した。

import numpy as np
import pretty_midi
import re

def midi_create(imput_chords):
    root        = {'C':0,
                   'C#':1,
                   'D♭':1,
                   'D':2,
                   'D#':3,
                   'E♭':3,
                   'E':4,
                   'F':5,
                   'F#':6,
                   'G♭':6,
                   'G':7,
                   'G#':8,
                   'A♭':8,
                   'A':9,
                   'A#':10,
                   'B♭':10,
                   'B':11,}

    chord_type = {'':np.array([0, 4, 7]),
                  'm':np.array([0, 3, 7]),
                  '7':np.array([0, 4, 7, 10]),
                  'm7':np.array([0, 3, 7, 10]),
                  'mM7':np.array([0, 3, 7, 11]),
                  'M7':np.array([0, 4, 7, 11]),
                  'dim':np.array([0, 3, 6, 9]),
                  'aug':np.array([0, 4, 8]),
                  'add9':np.array([0, 4, 7, 14]),
                  'sus4':np.array([0, 5, 7]),
                  '7sus4':np.array([0, 5, 7, 10]),
                  'm6':np.array([0, 3, 7, 9]),
                  '6':np.array([0, 4, 7, 9]),
                  'm7-5':np.array([0, 3, 6, 10]),
                  'm6':np.array([0, 3, 7, 9]),
                  '9':np.array([0, 4, 7, 10, 13]),

    }


    def split_chord(chord):
        j=chord    
        c=j
        if len(c)>1:
            c=c[0:2]
            if c[1]=='#' or c[1]=='♭':
                c=c[0:2]
                j=j[2:]

            else:
                c=c[0:1]
                j=j[1:]
        else:
            j=''
        return c, j

    pm = pretty_midi.PrettyMIDI(resolution=960, initial_tempo=120)     
    instrument = pretty_midi.Instrument(0) 

    chords = np.array(re.split(" +", imput_chords.rstrip()))
    d_time = 1#コードを鳴らす間隔
    time = 0
    for chord in chords:

        croot, ctype = split_chord(chord)
        notes = 60 + root[croot]
        if ctype in chord_type:
            notes += chord_type[ctype]
        else:
            notes += np.array([0, 12])

        for note_number in notes:
            note = pretty_midi.Note(velocity=100, pitch=note_number, start=time, end=time+d_time) 
            instrument.notes.append(note)

        time = time + d_time

    pm.instruments.append(instrument)

    filepass='chords.mid'
    pm.write(filepass)

if __name__ == '__main__':
    chords = "C G Am7 Em F CM7 F G7 C"
    midi_create(chords)

コードタイプは思いついた代表的な物を並べてあるが,一覧にないもの場合はルート音をオクターブで重ねたものが鳴る。

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8