Search code examples
pythonmusic21

How to convert bar count to time, in midi? (music)


Given a midi file, how can one convert the bar count to time? Generally, how can one easily map the bar count, in entire numbers, to the time in seconds in the song


Solution

  • Using pretty midi, my solution

    import pretty_midi as pm
    
    def get_bar_to_time_dict(self,song,id):
        def get_numerator_for_sig_change(signature_change,id):
            # since sometime pretty midi count are wierd
            if int(signature_change.numerator)==6 and int(signature_change.denominator)==8:
                # 6/8 goes to 2 for sure
                return 2
            return signature_change.numerator
        # we have to take into account time-signature-changes
        changes = song.time_signature_changes
        beats = song.get_beats()
        bar_to_time_dict = dict()
        # first bar is on first position
        current_beat_index = 0
        current_bar = 1
        bar_to_time_dict[current_bar] = beats[current_beat_index]
        for index_time_sig, _ in enumerate(changes):
            numerator = get_numerator_for_sig_change(changes[index_time_sig],id)
            # keep adding to dictionary until the time signature changes, or we are in the last change, in that case iterate till end of beats
            while index_time_sig == len(changes) - 1 or beats[current_beat_index] < changes[index_time_sig + 1].time:
                # we have to increase in numerator steps, minus 1 for counting logic of natural counting
                current_beat_index += numerator
                if current_beat_index > len(beats) - 1:
                    # we labeled all beats so end function
                    return bar_to_time_dict
                current_bar += 1
                bar_to_time_dict[current_bar] = beats[current_beat_index]
        return bar_to_time_dict
    
    song = pm.PrettyMIDI('some_midi_file.midi')
    get_bar_to_time_dict(song)
    

    If anyone knows a function in pretty midi or music21 that solves the same issue please let me know, couldn't find one. EDIT: There was also an issue with 6/8 beats, I think this covers all edge cases(not 100% sure)