melanchall / drywetmidi

.NET library to read, write, process MIDI files and to work with MIDI devices
https://melanchall.github.io/drywetmidi
MIT License
523 stars 73 forks source link

`MergeObjects` does not have the same behavior as `MergeNotes` #225

Closed sabihoshi closed 1 year ago

sabihoshi commented 1 year ago

When I use the MergeObjects method, seemingly the notes disappear in my loaded MIDI file, instead of merging it properly. I used to use MergeNotes and it worked properly like so:

midi.MergeNotes(new()
{
    Tolerance = new MetricTimeSpan(0, 0, 0, (int) Settings.MergeMilliseconds)
});

image

And with Obsolete #17 it told me to use the MergeObjects method instead, but it does not produce the same results.

midi.MergeObjects(ObjectType.Note, new()
{
    Tolerance = new MetricTimeSpan(0, 0, 0, (int) Settings.MergeMilliseconds)
});

image

melanchall commented 1 year ago

Hi,

Please provide me a sample MIDI file to reproduce the error. I have unit tests on the method and they tell me that's all is OK. But obviously that's not true.

sabihoshi commented 1 year ago

Here is the program I use with it https://github.com/sabihoshi/GenshinLyreMidiPlayer/blob/main/GenshinLyreMidiPlayer.WPF/ViewModels/LyrePlayerViewModel.cs#L380-L387

The MIDI is here https://www.nonstop2k.com/midi-files/15720-touhou-bad-applei-midi.html

melanchall commented 1 year ago

Well, I'll take that MIDI file and then apply this command to it:

midi.MergeObjects(ObjectType.Note, new()
{
    Tolerance = new MetricTimeSpan(0, 0, 0, (int) Settings.MergeMilliseconds)
});

right?

Please say where to see bad merging result then? Also what's the value of Settings.MergeMilliseconds? Unfortunately I'm not a mindreader :) So provide me as many details as possible. What notes to look at, what you expect and what's wrong and so on. Thanks!

sabihoshi commented 1 year ago

Hello, sorry for making not making it clear enough, so first of all the song when merged properly sounds like this https://youtu.be/Ly6LCHuuVFo?t=131. That's with a setting of 10 milliseconds. That's with MergeNotes and it's the first image you see above.

With MergeObjects, the notes "seemingly" disappear as you can see with the 2nd image in my original post. You can see in the video that it ends immediately almost all the notes are gone afterwards. Here is a minimal repro for it:

using Melanchall.DryWetMidi.Core;
using Melanchall.DryWetMidi.Interaction;
using Melanchall.DryWetMidi.Multimedia;
using Melanchall.DryWetMidi.Tools;

var speakers = OutputDevice.GetByName("Microsoft GS Wavetable Synth");
var midi = MidiFile.Read(@"Bad Apple!!.mid");

midi.MergeObjects(ObjectType.Note, new()
{
    Tolerance = new MetricTimeSpan(0, 0, 0, 10)
});

var playback = midi.GetPlayback();

playback.EventPlayed += OnNoteEvent;
playback.Play();

void OnNoteEvent(object? sender, MidiEventPlayedEventArgs e)
{
    if (e.Event is NoteEvent noteEvent)
        speakers.SendEvent(noteEvent);
}

https://user-images.githubusercontent.com/25006819/197231110-17b03ca1-192d-46ee-9ef0-10ad0435d6f9.mp4

melanchall commented 1 year ago

Thanks! I'll look into it.

melanchall commented 1 year ago

I've reproduced the error, looks really strange. Investigating.

melanchall commented 1 year ago

I've found the bug in the code and fixed it. I'll provide you a prerelease NuGet package with the fix as soon as it will be built.

melanchall commented 1 year ago

@sabihoshi 6.1.3-prerelease1 version published, you can install it via NuGet.

sabihoshi commented 1 year ago

It's working great, thank you!

melanchall commented 1 year ago

:rocket: 6.1.3 version is released now!

Prerelease NuGet packages will be unlisted soon, so please update the package references to the new version.

Thanks for using the library!