Python Write MIDI file

岁酱吖の 提交于 2020-12-12 09:13:18

问题


I want to write a MIDI file with the inputs I receive from the digital piano I have connected. I am using pygame.midi to open an input port and midiutil to write the MIDI file. What I can't wrap my head around is the timing. For example, in addNote(track, channel, pitch, time, duration, volume), how do I know what time and duration of a note is? When reading a note, I get pitch and volume just fine, but the others I have no idea... I tried using the timestamp but to no avail, it places the note really far away in the MIDI file.

So, how do I compute the 'time' and 'duration' of a note?


回答1:


time dictates the position in musical time the note should be played. Exactly what the parameter should be depends in part how the Midi file object was constructed (more on that soon)

In practice, MIDI asks for two messages per note: a NOTE On message and a NOTE Off message. The duration will indicate when the Note Off message should be sent, relative to the start of the note. Again, how the parameter should be formed depends on how the file object is constructed.

From the MIDIUtil docs:

  • time – the time at which the note sounds. The value can be either quarter notes [Float], or ticks [Integer]. Ticks may be specified by passing eventtime_is_ticks=True to the MIDIFile constructor. The default is quarter notes.
  • duration – the duration of the note. Like the time argument, the value can be either quarter notes [Float], or ticks [Integer]

A complete example that plays the C major scale

from midiutil import MIDIFile
degrees = [60, 62, 64, 65, 67, 69, 71, 72] # MIDI note number
track = 0
channel = 0
time = 0 # In beats
duration = 1 # In beats
tempo = 60 # In BPM
volume = 100 # 0-127, as per the MIDI standard
MyMIDI = MIDIFile(1) # One track, defaults to format 1 (tempo track
# automatically created)
MyMIDI.addTempo(track,time, tempo)
for pitch in degrees:
    MyMIDI.addNote(track, channel, pitch, time, duration, volume)
    time = time + 1
with open("major-scale.mid", "wb") as output_file:
    MyMIDI.writeFile(output_file)

The combination of the file tempo (at the current time) combined with the note's position (time) and duration (in terms of how many beats), the library can synthesize all the midi messages needed to play (start/stop) the note at the correct time.

Another Example

Let's try applying this to the following musical phrase:

First, set everything up.

from midiutil import MIDIFile
track = 0
channel = 0
time = 0 # In beats
duration = 1 # In beats
tempo = 60 # In BPM
volume = 100 # 0-127, as per the MIDI standard
MyMIDI = MIDIFile(1) # One track, defaults to format 1 (tempo track
# automatically created)
MyMIDI.addTempo(track,time, tempo)

To add the first half note on E and quarter note on G:

time = 0  # it's the first beat of the piece
quarter_note = 1  # equal to one beat, assuming x/4 time
half_note = 2 # Half notes are 2x value of a single quarter note
E3 = 64  # MIDI note value for E3
G3 = 67

# Add half note
MyMIDI.addNote(track, channel, pitch=E3, duration=half_note, time=0, volume=volume)
# Add quarter note
MyMIDI.addNote(track, channel, pitch=G3, duration=quarter_note, time=0, volume=volume)

Now let's add the remaining notes:

A3 = 69
C3 = 60
B3 = 71
C4 = 72

# add the remaining notes
for time, pitch, duration in [(1,A3, quarter_note),
                              (2,B3, quarter_note), (2, C3, half_note), 
                              (3,C4, quarter_note)]:
    MyMIDI.addNote(track, channel, 
                   duration=duration, 
                   pitch=pitch, time=time, volume=volume)


来源:https://stackoverflow.com/questions/64838592/python-write-midi-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!