简体   繁体   English

如何使用马尔可夫链矩阵生成音乐?

[英]How do I use a markov chain matrix to generate music?

I have a matrix (square - nxn) <--Depends on how many chords there are.我有一个矩阵 (square - nxn) <--取决于有多少和弦。

------------------------------------------
            Transition Matrix: (FROM)
------------------------------------------
 A     Bm   C#m    D     E    F#m    G#   
------------------------------------------
0.07  0.00  0.00  0.00  0.66  0.14  0.86 | A   | 
0.15  0.17  0.00  0.05  0.07  0.30  0.00 | Bm  | 
0.00  0.00  0.00  0.00  0.00  0.37  0.00 | C#m | 
0.19  0.00  0.39  0.16  0.14  0.00  0.00 | D   | (TO)
0.52  0.83  0.29  0.43  0.00  0.19  0.00 | E   | 
0.07  0.00  0.32  0.36  0.14  0.00  0.14 | F#m | 
0.00  0.00  0.00  0.00  0.00  0.00  0.00 | G#  | 

This matrix gets multiplied by another matrix which is:该矩阵乘以另一个矩阵,即:

1
0
0
0
0
0
0

This means the starting note is an A (1st row corresponds to A).这意味着起始音符是 A(第一行对应于 A)。

The next note is determined by the column of the Markov Transition Matrix which says there is a:下一个音符由马尔可夫转移矩阵的列决定,该列表示有一个:

7% chance to become A 7% 的机会成为 A

15% chance to become Bm 15% 的几率成为 Bm

0% chance to become C#m, etc. etc. 0% 的机会成为 C#m 等等。

(Done by matrix multiplication, using numPy). (通过矩阵乘法完成,使用 numPy)。

So the resulting matrix is a 1col x nrows matrix.所以结果矩阵是一个 1col x nrows 矩阵。

This matrix will look like this:该矩阵将如下所示:

0.07
0.15
0.00
0.19
0.52
0.07
0.00

^ This means that there is a 0.07% that the next note is an A, etc. ^ 这意味着下一个音符有 0.07% 是 A 等。

^ Using these probabilities can I play back those notes? ^ 使用这些概率我可以回放那些音符吗? Or generate a midi file based on it?或者基于它生成一个midi文件?

I should only get back one note (plus the first one), and based on the probability it should be an E.我应该只取回一个音符(加上第一个),并且根据它应该是 E 的概率。

I wrote a small program to demonstrate Markov generation, including output to a MIDI file using the music21 library.我编写了一个小程序来演示马尔可夫生成,包括使用 music21 库输出到 MIDI 文件。

Note that your transition matrix has two problems:请注意,您的转换矩阵有两个问题:

  1. The probabilities in the 5th column do not sum to 1.00.第 5 列中的概率之和不为 1.00。 I replaced 0.66 with 0.65 to make it work.我用 0.65 替换了 0.66 以使其工作。
  2. This is a matrix of chord transition probabilities, not note transitions.这是一个和弦转换概率矩阵,而不是音符转换。 So my example involves chords (triads), not individual notes.所以我的例子涉及和弦(三和弦),而不是单个音符。 Your question uses the word "note" many times where I think you meant "chord" instead, because all your examples involve chords such as B minor.您的问题多次使用“音符”一词,而我认为您的意思是“和弦”,因为您的所有示例都涉及和弦,例如 B 小调。

I wrote a program to repeat each chord 4 times, so that each chord lasts an entire measure of 4 beats.我编写了一个程序,将每个和弦重复 4 次,以便每个和弦持续 4 拍的整个小节。

I picked C major as the default instead of your A major.我默认选择了 C 大调,而不是你的 A 大调。 If you want to generate chords in a different key you can change the scale root in the calls to chord_to_names to chord_to_midi, using the "root_midi" parameter.如果您想在不同的键中生成和弦,您可以使用“root_midi”参数将调用 chord_to_names 中的音阶根更改为 chord_to_midi。 For instance, call it with 57 instead of the default 60 to get A major.例如,使用 57 而不是默认的 60 来调用它以获得 A 大调。

Once you run this program it will generate chords.mid , which you can open in a program such a MuseScore or a midi editor.运行此程序后,它将生成chords.mid ,您可以在 MuseScore 或 midi 编辑器等程序中打开它。

Sample output:示例输出:

Generated chords: [0, 0, 1, 4, 0, 3, 4, 5]
Note names:
['C', 'E', 'G']
['C', 'E', 'G']
['D', 'F', 'A']
['G', 'B', 'D']
['C', 'E', 'G']
['F', 'A', 'C']
['G', 'B', 'D']
['A', 'C', 'E']
MIDI Notes:
[60, 64, 67]
[60, 64, 67]
[62, 65, 69]
[55, 59, 62]
[60, 64, 67]
[53, 57, 60]
[55, 59, 62]
[57, 60, 64]

Which looks like this rendered in MuseScore:在 MuseScore 中看起来像这样:

在此处输入图片说明

import numpy as np

from music21.chord import Chord
from music21.stream import Part
from music21.midi.translate import streamToMidiFile


CHORD_TRANSITIONS = np.matrix([
  #              Transition Matrix: (FROM)
  # ---------------------------------------------
  #  I     ii     iii    IV      V     vi    viio   
  # ---------------------------------------------
    [0.07,  0.00,  0.00,  0.00,  0.65,  0.14,  0.86],  # | I    | 
    [0.15,  0.17,  0.00,  0.05,  0.07,  0.30,  0.00],  # | ii   | 
    [0.00,  0.00,  0.00,  0.00,  0.00,  0.37,  0.00],  # | iii  | 
    [0.19,  0.00,  0.39,  0.16,  0.14,  0.00,  0.00],  # | IV   | (TO)
    [0.52,  0.83,  0.29,  0.43,  0.00,  0.19,  0.00],  # | V    | 
    [0.07,  0.00,  0.32,  0.36,  0.14,  0.00,  0.14],  # | vi   |  
    [0.00,  0.00,  0.00,  0.00,  0.00,  0.00,  0.00]]) # | viio |  

CHORD_TRANSITIONS = CHORD_TRANSITIONS.T  # swap axes for simpler lookup based on current chord

TRIADS = [
  (0, 4, 7),  # I
  (2, 5, 9),  # ii
  (4, 7, 11),  # iii
  (-7, -3, 0),  # IV
  (-5, -1, 2),  # V
  (-3, 0, 4),  # vi
  (-1, 2, 5),  # viio
] 

PC_TO_NAME = ('C', 'C#', 'D', 'Eb', 'E', 'F', 'F#', 'G', 'Ab', 'A', 'Bb', 'B')

def midi_to_pc(midi_note):
  return midi_note % 12

def midi_to_name(midi_note):
  return PC_TO_NAME[midi_to_pc(midi_note)]

def chord_to_midi(chord_index, root_midi=60):  # chord_index is from 0 to 6
  return [root_midi + x for x in TRIADS[chord_index]]

def chord_to_names(chord_index, root_midi=60):  # chord_index is from 0 to 6
  return [midi_to_name(note) for note in chord_to_midi(chord_index, root_midi)]

num_chords = len(CHORD_TRANSITIONS)

def generate(start_chord=0, length=8):
  cur = start_chord
  chords = [cur]
  for _ in range(length - 1):
    probs = CHORD_TRANSITIONS[cur,:].tolist()[0]
    chord = np.random.choice(num_chords, p=probs)
    chords.append(chord)
    cur = chord
  return chords

chords = generate()

print(f'Generated chords: {chords}')

print(f'Note names:')
for chord in chords:
  print(chord_to_names(chord))

print(f'MIDI notes:')
for chord in chords:
  print(chord_to_midi(chord))

print('Converting to MIDI')
part = Part()
for chord in chords:
  midis = chord_to_midi(chord)

  # Repeat each chord 4 times.
  for i in range(4):  
    part.append(Chord(midis, quarterLength=1))

mf = streamToMidiFile(part)

mf.open('chords.mid', 'wb')
mf.write()
mf.close()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM