Do you know Hanon Piano textbooks? Many people who have experience playing the piano may have unpleasant memories. The Hanon Piano Textbook is a textbook that teaches you the very basics of playing the piano. Seeing is believing, so be sure to check out Video being played and Sheet music Take a look at 11753162091.html). This time, I aimed to automatically create songs like Nos. 1 to 20 in Hanon Piano textbooks.
The language used is ** Python **. I also used ** music21 **, a Python music information processing library developed at MIT. Actually, music21 itself does not create the score, but MuseScore and Lilypond do. (However, I don't actually touch MuseScore or Lilypond, so I don't need to know anything about it.) Regarding music21, I am very grateful to this blog.
To make a Hanon-like score, you have to think about Hanon-like. I decided the following conditions to be Hanon-like. It may be difficult for people who are not playing music to understand, so it would be nice if you could think that you decided the rules while looking at the score yourself.
Implemented to randomly create a score that meets these conditions. As a result, I got a score like this tweet!
Hanon.py
# -*- coding: utf-8 -*-
from music21 import *
import numpy
import matplotlib
import scipy
import random
#Random number generation
random_num = [-1 for _ in range(8)]
random_num[0] = 0
for i in range(1,8):
random_num[i] = random.randint(1, 7)
if i >= 1: #Avoid the same notes as the previous one
while True:
if random_num[i] != random_num[i-1]:
break
else:
random_num[i] = random.randint(1, 7)
#Write the score
##Somehow the first magic
stream_right = stream.Part()
stream_left = stream.Part()
inst1 = instrument.Instrument()
inst2 = instrument.Instrument()
stream_right.append(inst1)
stream_left.append(inst2)
tc = clef.TrebleClef() #Treble clef
bc = clef.BassClef() #F clef
stream_right.append(tc)
stream_left.append(bc)
otos = ["C1", "D1", "E1", "F1", "G1", "A1", "B1", "C2", "D2", "E2", "F2", "G2", "A2", "B2", "C3", "D3", "E3", "F3", "G3", "A3", "B3", "C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", "C6"]
##right hand
for i in range(14): #Nobori
###1st bar
meas = stream.Measure()
n0 = note.Note(otos[random_num[0] + 14 + i], quarterLength = 0.25)
meas.append(n0)
n1 = note.Note(otos[random_num[1] + 14 + i], quarterLength = 0.25)
meas.append(n1)
n2 = note.Note(otos[random_num[2] + 14 + i], quarterLength = 0.25)
meas.append(n2)
n3 = note.Note(otos[random_num[3] + 14 + i], quarterLength = 0.25)
meas.append(n3)
n4 = note.Note(otos[random_num[4] + 14 + i], quarterLength = 0.25)
meas.append(n4)
n5 = note.Note(otos[random_num[5] + 14 + i], quarterLength = 0.25)
meas.append(n5)
n6 = note.Note(otos[random_num[6] + 14 + i], quarterLength = 0.25)
meas.append(n6)
n7 = note.Note(otos[random_num[7] + 14 + i], quarterLength = 0.25)
meas.append(n7)
stream_right.append(meas)
for i in range(14): #Crap
###1st bar
meas = stream.Measure()
x = 18
n0 = note.Note(otos[x + 14 - i], quarterLength = 0.25)
meas.append(n0)
n1 = note.Note(otos[x - random_num[1] + 14 - i], quarterLength = 0.25)
meas.append(n1)
n2 = note.Note(otos[x - random_num[2] + 14 - i], quarterLength = 0.25)
meas.append(n2)
n3 = note.Note(otos[x - random_num[3] + 14 - i], quarterLength = 0.25)
meas.append(n3)
n4 = note.Note(otos[x - random_num[4] + 14 - i], quarterLength = 0.25)
meas.append(n4)
n5 = note.Note(otos[x - random_num[5] + 14 - i], quarterLength = 0.25)
meas.append(n5)
n6 = note.Note(otos[x - random_num[6] + 14 - i], quarterLength = 0.25)
meas.append(n6)
n7 = note.Note(otos[x - random_num[7] + 14 - i], quarterLength = 0.25)
meas.append(n7)
stream_right.append(meas)
###Last bar
meas = stream.Measure()
n = note.Note("C3", quarterLength = 2)
meas.append(n)
stream_right.append(meas)
##left hand
for i in range(14): #Nobori
###1st bar
meas = stream.Measure()
n0 = note.Note(otos[random_num[0] + 7 + i], quarterLength = 0.25)
meas.append(n0)
n1 = note.Note(otos[random_num[1] + 7 + i], quarterLength = 0.25)
meas.append(n1)
n2 = note.Note(otos[random_num[2] + 7 + i], quarterLength = 0.25)
meas.append(n2)
n3 = note.Note(otos[random_num[3] + 7 + i], quarterLength = 0.25)
meas.append(n3)
n4 = note.Note(otos[random_num[4] + 7 + i], quarterLength = 0.25)
meas.append(n4)
n5 = note.Note(otos[random_num[5] + 7 + i], quarterLength = 0.25)
meas.append(n5)
n6 = note.Note(otos[random_num[6] + 7 + i], quarterLength = 0.25)
meas.append(n6)
n7 = note.Note(otos[random_num[7] + 7 + i], quarterLength = 0.25)
meas.append(n7)
stream_left.append(meas)
for i in range(14): #Crap
###1st bar
meas = stream.Measure()
x = 18
n0 = note.Note(otos[x + 7 - i], quarterLength = 0.25)
meas.append(n0)
n1 = note.Note(otos[x - random_num[1] + 7 - i], quarterLength = 0.25)
meas.append(n1)
n2 = note.Note(otos[x - random_num[2] + 7 - i], quarterLength = 0.25)
meas.append(n2)
n3 = note.Note(otos[x - random_num[3] + 7 - i], quarterLength = 0.25)
meas.append(n3)
n4 = note.Note(otos[x - random_num[4] + 7 - i], quarterLength = 0.25)
meas.append(n4)
n5 = note.Note(otos[x - random_num[5] + 7 - i], quarterLength = 0.25)
meas.append(n5)
n6 = note.Note(otos[x - random_num[6] + 7 - i], quarterLength = 0.25)
meas.append(n6)
n7 = note.Note(otos[x - random_num[7] + 7 - i], quarterLength = 0.25)
meas.append(n7)
stream_left.append(meas)
###Last bar
meas = stream.Measure()
n = note.Note("C2", quarterLength = 2)
meas.append(n)
stream_left.append(meas)
##The last magic
s = stream.Score()
s.append(stream_right)
s.append(stream_left)
s.show('musicxml')
You can also see it on GitHub. From here, I will explain the source code separately. However, I'm just starting to use music21, and I'm not sure about it, and there are many parts that imitate other people, so please point out if you make a mistake.
python
# -*- coding: utf-8 -*-
from music21 import *
import numpy
import matplotlib
import scipy
import random
Other than random, it seems that it is necessary to use music21, so I imported it for the time being. I want to make a random number, so I will import random.
python
#Random number generation
random_num = [-1 for _ in range(8)]
random_num[0] = 0
for i in range(1,8):
random_num[i] = random.randint(1, 7)
if i >= 1: #Avoid the same notes as the previous one
while True:
if random_num[i] != random_num[i-1]:
break
else:
random_num[i] = random.randint(1, 7)
If you randomize only the 2nd to 8th notes in the first bar, you only need to transpose it, so we prepared 7 random numbers. I wanted to make the numbers correspond to the numbers, so I made the random numbers in the range of 1-8. The while statement is turned so that the same sound does not continue.
python
##Somehow the first magic
stream_right = stream.Part()
stream_left = stream.Part()
inst1 = instrument.Instrument()
inst2 = instrument.Instrument()
stream_right.append(inst1)
stream_left.append(inst2)
tc = clef.TrebleClef() #Treble clef
bc = clef.BassClef() #F clef
stream_right.append(tc)
stream_left.append(bc)
otos = ["C1", "D1", "E1", "F1", "G1", "A1", "B1", "C2", "D2", "E2", "F2", "G2", "A2", "B2", "C3", "D3", "E3", "F3", "G3", "A3", "B3", "C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", "C6"]
First, there are two parts, right hand and left hand, so prepare two parts. Then add a treble clef and a bass clef to each part. Finally, I will prepare an array of sounds to be used from now on.
python
##right hand
for i in range(14): #Nobori
###1st bar
meas = stream.Measure()
n0 = note.Note(otos[random_num[0] + 14 + i], quarterLength = 0.25)
meas.append(n0)
n1 = note.Note(otos[random_num[1] + 14 + i], quarterLength = 0.25)
meas.append(n1)
n2 = note.Note(otos[random_num[2] + 14 + i], quarterLength = 0.25)
meas.append(n2)
n3 = note.Note(otos[random_num[3] + 14 + i], quarterLength = 0.25)
meas.append(n3)
n4 = note.Note(otos[random_num[4] + 14 + i], quarterLength = 0.25)
meas.append(n4)
n5 = note.Note(otos[random_num[5] + 14 + i], quarterLength = 0.25)
meas.append(n5)
n6 = note.Note(otos[random_num[6] + 14 + i], quarterLength = 0.25)
meas.append(n6)
n7 = note.Note(otos[random_num[7] + 14 + i], quarterLength = 0.25)
meas.append(n7)
stream_right.append(meas)
for i in range(14): #Crap
###1st bar
meas = stream.Measure()
x = 18
n0 = note.Note(otos[x + 14 - i], quarterLength = 0.25)
meas.append(n0)
n1 = note.Note(otos[x - random_num[1] + 14 - i], quarterLength = 0.25)
meas.append(n1)
n2 = note.Note(otos[x - random_num[2] + 14 - i], quarterLength = 0.25)
meas.append(n2)
n3 = note.Note(otos[x - random_num[3] + 14 - i], quarterLength = 0.25)
meas.append(n3)
n4 = note.Note(otos[x - random_num[4] + 14 - i], quarterLength = 0.25)
meas.append(n4)
n5 = note.Note(otos[x - random_num[5] + 14 - i], quarterLength = 0.25)
meas.append(n5)
n6 = note.Note(otos[x - random_num[6] + 14 - i], quarterLength = 0.25)
meas.append(n6)
n7 = note.Note(otos[x - random_num[7] + 14 - i], quarterLength = 0.25)
meas.append(n7)
stream_right.append(meas)
###Last bar
meas = stream.Measure()
n = note.Note("C3", quarterLength = 2)
meas.append(n)
stream_right.append(meas)
First, create the first bar. At this time, when I used the for statement, for some reason there was only one sound in one bar, so I had no choice but to write it solidly. Write it as note.Note (pitch, length). The length of a note is expressed as a fraction or a decimal, with a quarter note as 1. When the first measure is completed, repeat it 14 times while transposing it to complete the ascending! Write the lower line in the same way. And don't forget to add the extension of the last bar, and you're done! !! The left hand is only an octave lower, so I omitted it.
python
##The last magic
s = stream.Score()
s.append(stream_right)
s.append(stream_left)
s.show('musicxml')
Finally, display what you have written so far in MuseScore. You can also display it in Lilypond by rewriting the last line.
I was told that I should try machine learning in order to pursue more Hanon-likeness, so I have a desire to try it (I don't know anything, so I have to study from 0 ... ). I also want to be able to adjust the difficulty level in about 5 steps. Also, music21 seems to be able to be used for music analysis, and it seems that it can check what key it is (amazing), so I thought that I would like to play with that as well.
Recommended Posts