问题
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