HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Creating lists of events (pitches, velocities, delta-times, durations) from a MIDI track

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
durationsvelocitiestrackeventscreatingmidiliststimesfromdelta

Problem

I am trying to understand good design patterns in Python and I cannot think of a way to break this huge function into smaller parts without making the code cluttered, overly complex or plain ugly.

I didn't want to clutter my question by posting the whole file. This function itself is already very large, but the class has only two methods: parse_midi() and generate_midi(file_name, file_length).

pitches, velocities, deltas, durations, and intervals are all MarkovChain objects. MarkovChain is a simple class with methods: add_event(event), generate_markov_dictionary(), and get_next_event(previous_event). MarkovChain.src_events is a list of events to generate the Markov chain from. It is a simple implementation of first order Markov chains.

```
def parse_midi(self):
# on_notes dictionary holds note_on events until corresponding note_of event is encountered
on_notes = {}
time = 0
previous_pitch = -1
tempos = []
delta = 0
for message in self.track_in:
time += message.time
delta += message.time
# There are also MetaMessages in a midi file, such as comments, track names, etc.
# We just ignore them
if isinstance(message, mido.Message) and message.type in ["note_on", "note_off"]:
# some midi files use note_on events with 0 velocity instead of note_oof events
# so we check if velocity > 0
if message.velocity > 0 and message.type == "note_on":
on_notes[message.note] = time
self.pitches.add_event(message.note)
self.velocities.add_event(message.velocity)
self.deltas.add_event(delta)
delta = 0
if previous_pitch == -1:
self.intervals.add_event(0)
else:
self.intervals.add_event(message.note - previous_pitch)
else:
# KeyError means note_off came without a prior associated note_on event!"

Solution

Your notion of average tempo makes little sense. A track with four minutes of ♩=120 followed by a 12-second coda of ♩=60 would have a reported average tempo of 90. A more reasonable average would be to divide the total number of beats by the elapsed time.

$$\frac{120 \frac{\textrm{beats}}{\textrm{min}} × 4\ \textrm{min} +
60 \frac{\textrm{beats}}{\textrm{min}} × 0.2\ \textrm{min}}
{4.2\ \textrm{min}} \approx 117 \frac{\textrm{beats}}{\textrm{min}}
$$

Context

StackExchange Code Review Q#85389, answer score: 2

Revisions (0)

No revisions yet.