Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 22 additions & 17 deletions polytrackermidi/exporters/midi.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ def generate_midi(self, midi_file: MIDIFile = None,
tempo = 60 # In BPM

midi_tracks_count = len(instruments)
midi_file = MIDIFile(midi_tracks_count)

# There is a bug in MIDIUtil that sometimes crashes when a
# note played by the same instrument is overlapping with
# itself: https://github.com/MarkCWirt/MIDIUtil/issues/34
#
# As a workaround, skip removing duplicate MIDI events.
midi_file = MIDIFile(midi_tracks_count, removeDuplicates=False)
midi_file.addTempo(track=0, time=0, tempo=self.tempo_bpm)

for i in range(len(instruments)):
Expand Down Expand Up @@ -203,14 +209,17 @@ def generate_midi(self, midi_file: MIDIFile = None,
# so we going to jsut shorten its duration
arp_note_duration = arp_end_time - arp_note_start_time

midi_file.addNote(track=instrument_to_midi_track_map[step.instrument_number],
channel=channel,
pitch=PatternToMidiExporter.get_midi_note_value(note),
time=start_time_offset + arp_note_start_time,
duration=arp_note_duration,
# TODO: write velocity fx value if set (needs to be converted to 0...127!!!)
volume=default_volume,
)
# Workaround for MIDIUtil, which crashes if a note has a duration of 0.
# See also: https://github.com/MarkCWirt/MIDIUtil/issues/34
if arp_note_duration >= 1 / midi_file.ticks_per_quarternote:
midi_file.addNote(track=instrument_to_midi_track_map[step.instrument_number],
channel=channel,
pitch=PatternToMidiExporter.get_midi_note_value(note),
time=start_time_offset + arp_note_start_time,
duration=arp_note_duration,
# TODO: write velocity fx value if set (needs to be converted to 0...127!!!)
volume=default_volume,
)

# increment starting time for the next note
arp_note_start_time += arp_note_duration
Expand All @@ -231,13 +240,9 @@ def generate_midi(self, midi_file: MIDIFile = None,
)

else:
# note that there is a bug in MIDIUtil
# that sometimes crashes when a note played by the same
# instrument is overlapping with itself
# https://github.com/MarkCWirt/MIDIUtil/issues/34
# there is also a bug with track numbers/note values overlapping
# that is also described in the same deInterlaveNotes method in MIDIUtil

# note that there is a bug in MIDIUtil with track numbers /note values
# overlapping that is described in the deInterlaveNotes method in MIDIUtil:
# https://github.com/MarkCWirt/MIDIUtil/blob/8f858794b03fcbfdd9d689ac39cf0f9a6792e416/src/midiutil/MidiFile.py#L873-L876

# default case - just a regular single note playing
midi_file.addNote(track=instrument_to_midi_track_map[step.instrument_number],
Expand Down Expand Up @@ -287,7 +292,7 @@ def generate_midi(self) -> MIDIFile:
# this should be faster than calling instruments.indexOf()
instrument_to_midi_track_map = {}

midi_file = MIDIFile(midi_tracks_count)
midi_file = MIDIFile(midi_tracks_count, removeDuplicates=False)
#FIXME: write bpm to song to get it from there
midi_file.addTempo(track=0, time=0, tempo=self.song.bpm)

Expand Down