Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIDI end of file duration mismatch with input audio duration #14

Open
nateraw opened this issue Nov 20, 2024 · 1 comment
Open

MIDI end of file duration mismatch with input audio duration #14

nateraw opened this issue Nov 20, 2024 · 1 comment
Assignees

Comments

@nateraw
Copy link

nateraw commented Nov 20, 2024

Hi there, this is the issue I was referring to in #13 - reporting anyway even though code isn't here to refer to.

Not sure if this is on purpose or not, but I've noticed there's a mismatch between input audio file duration and the length of the midi data saved to disk. It appears the midi ends right after the final note event. so, in cases where there's a bit of silence at the end of the input audio clip, this silence is left out of the MIDI data.

Not too familiar with mido, but if I understand correctly, we'd just have to add the correct end_of_file event with the correct time tick value.


My current solution is to inject this event into the midi objects like this:

def add_end_time_to_midi(mid, duration_seconds, default_tempo=500000):
    """
    Adds an empty event at the end of each track to ensure correct MIDI duration.
    
    Args:
        mid: mido.MidiFile object
        duration_seconds: desired duration in seconds
        default_tempo: tempo to use if none found in file (default: 500000 microseconds per beat)
    Returns:
        mido.MidiFile with correct end time
    """
    # Find tempo from the file or use default
    tempo = default_tempo
    for track in mid.tracks:
        for msg in track:
            if msg.type == 'set_tempo':
                tempo = msg.tempo
                break
    
    # Calculate total ticks needed
    total_ticks = int(duration_seconds * 1000000 * mid.ticks_per_beat / tempo)
    
    for track in mid.tracks:
        current_ticks = sum(msg.time for msg in track)
        if current_ticks < total_ticks:
            # Add empty meta message at the end
            from mido import MetaMessage
            track.append(MetaMessage('end_of_track', time=total_ticks - current_ticks))
    
    return mid
@mimbres mimbres self-assigned this Nov 22, 2024
@mimbres
Copy link
Owner

mimbres commented Nov 22, 2024

@nateraw
Thank you for your error report and quick fix! I didn’t know that the end_of_track message was necessary, but I learned it from you👍.

Honestly, I’m so busy these days that I can’t make any promises, but I’ll definitely reflect it in the next update. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants