XMPlay MIDI plugin

Started by Ian @ un4seen,

ELP

#840
If this is the OpenMPT's MIDI exported file Saga, then the export is corrupt,
because in that Midi-export-File both last Note ON events (CH1 & CH2) has no NOTE OFF event

CH0(1):
Note ON 0x90 0x3C 0x7F | Delta Time 0x83 0x60 | ----""Note Off event  or NOTE ON with Vel 0 here is missing"" | End of Track 0xFF 0x2F | 00
CH1(2):
Note ON 0x91 0x3C 0x7F | Delta Time 0x83 0x60 | ----""Note Off event or Note ON with Vel 0 here is missing"" | End of Track 0xFF 0x2F | 00

++
If i load such a file for example into REAPER then the last note on event CH2 would be interpreted with an length of 1 tick (480ppq/125 BPM)
Which result in an Note length of 1 ms til end of track.

    +0    7199:  91 3C 7F
    +1    7200:  81 3C 00
END of:
    +0    7200   FF 2F 00

and the last Note on CH1
    +0    6719:  90 3C 7F
never ends ;)

Ian @ un4seen

Yep, as ELP says, the issue is that the final note-on event doesn't have a corresponding note-off event. The MIDI plugin ends playback at the final event (to remove any silence/padding), which is the final note-on in this case, so the final note doesn't get played. I'll make the plugin try to detect unreleased notes in the next update, and disable the end cropping then. In the meantime, I think it would be a good idea to add the final note-off event to avoid any ambiguity.

saga

Ah. I assumed that a MIDI player would always wait for the final "end of track" event anyway... But yes, good point, the missing note-offs should definitely be there.

Ian @ un4seen

Rev.14 of the MIDI plugin (up on the XMPlay page now) will disable the end space cropping when it detects that there are unreleased notes, so the final note in the "16 notes.mid" test file should now get played.

kode54

Any chance of publishing a specification of the minor differences that make a .sf2pack file? I've been in discussion with the developer of Polyphone about getting it supported there. He won't add BASS/BASSMIDI, but he may add a bunch of decoder libraries to load it, and possibly encoders as well to re-save it.

Ian @ un4seen

Yep, the sf2pack modifications are pretty simple. Firstly, "sfbk" in the RIFF header is replaced with "sfpk". Secondly, the sample data in the "smpl" chunk (and "sm24" chunk if it's 24-bit) is encoded and placed in the sf2pack file's "smpl" chunk (there's no "sm24" chunk). The rest of the file remains the same.

Corak

Quote from: Ian @ un4seenRev.14 of the MIDI plugin (up on the XMPlay page now) will disable the end space cropping when it detects that there are unreleased notes, so the final note in the "16 notes.mid" test file should now get played.

Hi. Just found horroful bug in r14 version of xmp-midi plugin:
On some instruments standard note-off are ignored, so they keep looping and spoil all sound.
On r13a (2014.08.28) all was perfect.

Examples (part of some unnormally looping tracks):
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/Track_11.mid
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/INTROTHM.mid
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/1.mid
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/4.mid

Listen it on r14 dll:
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/xmp-midi_r14.zip
and compare sound looping to r13a:
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/xmp-midi_r13a.zip

Standard Roland GS soundfont if needed:
http://files.leraux.ru/Corak/Temp/Bugreport/XmPlay/xmp-midi/Scc1t2.sf2

Ian @ un4seen

The problem appears to be that the MIDI files have some instances of multiple identical note-on events without the same number of corresponding note-off events. rev.13 of the MIDI plugin would release all instances of a note upon a note-off event, while rev.14 only releases one instance of a note upon a note-off event. I think most MIDI synths will do like rev.14 does, and there are some MIDI files that don't play correctly otherwise, but it does mean that some notes are left playing to the end in your MIDI files.

If you would prefer to have all instances of a note released by a note-off, here's an update that adds an XMPLAY.INI option for that:

   www.un4seen.com/stuff/xmp-midi.dll

Add a "NoteOffAll=1" line to your XMPLAY.INI file (under the "[MIDI]" line) to enable that.

Corak

#848
Understood, thanks! But still there's tons of midi (most from games, meeted more than 40 of examples with such "bad method") which is broken on listening on that way it now dealing with noteoffs in r14, but other synths - deal perfectly with them, only r14 method now loops some of them eternally.
 I think it's important option you must add (NoteOffAll=1) to Midi plugin that must be enabled by default (or disabled if you really think r14 method are really right) and everyone can easyly disable/enable it in midi plugin GUI menu. Everybody who listen to midi (X-Midi conversions mostly have such troubles) music from Games REALLY need it, and would be gratefull.

>rev.13 of the MIDI plugin would release all instances of a note upon a note-off event,
Right method, it was always used in custom midi files synths. Of course it's not so right for keyboard synths

Also Thank YOu very much - others fixes you made in r14 - make it sound much better now, better notes timing, volume balance and expression.

ELP

#849
as an explanation what Ian mean:
From Track_11.mid

1: 1:   0 |On Note    | chan=11    | pitch=C#6       | vol=108
        70 |On Note    | chan=11    | pitch=C#6       | vol=108
        71 |Off Note    | chan=11    | pitch=c#6       | vol=0

The same C#6 Note on the the same channel and port but only one Note Off
after the second C#6 Note On trigger.
Which is normally impossible if you play at one keyboard. Because before you can hit the same C#6 Key again the Key naturally always release... means Note off before the same Note on again..

Simplified said the Midi File itself for the example above (Track_11.mid) is actually corrupt if it is for playing one instrument  ;)
--
But it is right that normally for example hardware instruments release the first note on immediately if they receive the same note at the same channel again. So they normally never can play the first note(C#6 example above) infinite.
Nevertheless, those files actually wrong,if they should trigger instruments and not
other things like maybe controlling somewhat.

Ian @ un4seen

Quote from: CorakUnderstood, thanks! But still there's tons of midi (most from games, meeted more than 40 of examples with such "bad method") which is broken on listening on that way it now dealing with noteoffs in r14, but other synths - deal perfectly with them, only r14 method now loops some of them eternally.
 I think it's important option you must add (NoteOffAll=1) to Midi plugin that must be enabled by default (or disabled if you really think r14 method are really right) and everyone can easyly disable/enable it in midi plugin GUI menu. Everybody who listen to midi (X-Midi conversions mostly have such troubles) music from Games REALLY need it, and would be gratefull.

Here's another update for you to try with those MIDI files:

   www.un4seen.com/stuff/xmp-midi.dll

It will automatically enable the "NoteOffAll" option on MIDI files that have more note-ons than note-offs, so that it should automatically get enabled for those that need it enabled and disabled for those that need it disabled. "NoteOffAll=1" can currently still be used in XMPLAY.INI to force it to be enabled always, but I might remove that option if the auto-detection works well enough to make it unnecessary.

raygrote

Hi Ian,
Once again I'm coming in late with another bug report.
A few months ago I tried midi plug-in revision 13A, which had a bug where release envelopes wouldn't always play properly, and certain samples were worse than others. I temporarily switched back to Rev. 12 and reported this bug. You promptly fixed it, though I didn't get to try it until now because I was busy with other commitments and forgot. So, now that we're on Rev. 14, and this should be long forgotten as so many bugs are, I have to bring this one back. 90 percent of the time, everything sounds fine. However, the bug still manifests.
To put it simply, while release envelopes start out fine, they sometimes terminate prematurely. Some will make it all the way to what I would consider the minimum level, while others stop while the sound is still quite audible. You notice it especially during long rests, or with instruments like pianos which have undamped strings at the top end, and so will sometimes have long release envelopes put on those samples to emulate that. Also, the cutting of notes is sample dependent, I.e. just because it happens on one sample under certain conditions doesn't necessarily mean it will happen on other samples under those same conditions. That's all I can say with confidence.
To simplify this as much as I could, I've made a very small zip file which shows my experiments in trying to pinpoint this issue myself and what triggers it, and I've got something that's obvious enough to clearly hear and see, though I still am stumped as to what the root cause is. Here is a link: https://dl.dropboxusercontent.com/u/5406787/releasetests.zip
Now I'll explain what these files are attempting to show so you can hopefully pin this down.
Releasetest.mid simply contains two notes, each a second in length. The notes also have a second gap between them. Piano.sf2 and sine.sf2 are two different sound fonts I made for the pure purposes of testing for this issue. Both sound fonts are exactly the same, they each contain one sample with loop points, one instrument and one preset. They both have identical release envelopes. However the midi plug-in treats them differently.
If you play releasetest.mid using sine.sf2, you will hear two obnoxious beeps, with a second of fading in between. You can also see in the channel mixer that for a while, both notes overlap.
Now, try playing releasetest.mid with piano.sf2, which has exactly the same settings in the font, just with a piano sample instead of a single cycle sine loop. Not only can you hear a gap of pure silence in between the two notes, but you can also see it in the channel mixer. It didn't do this in Rev. 12. Decay envelopes are also unaffected to my knowledge, only releases are.
My only explanation as to what could be going on is that Perhaps the plug-in is trying to listen to each voice to determine when it is sufficiently quiet enough to be inaudible? If this is the case, it's a good concept but I think I have a case for it not to be necessary, as the release envelopes in Bass don't seem to go down ridiculously low. With loud samples you can always hear the ADSR envelopes cut after a certain point, and it's always been that way. If it were like those synths which will happily ramp down to -100 dB or lower, then I can possibly see the need for such a feature to mute voices which were potentially inaudible, but the voice limit to my understanding already knows to cut voices from quietest to loudest in terms of how much they've been attenuated. With 500 voices in Rev. 12, I rarely had voice cutting problems that were audible, with 1000 in later versions I suspect I will have even fewer problems.
Otherwise it's a great plug-in, and I see improvement in every version, even though I was being lazy and not checking in here frequently when the revisions were being made. I like the new stereo alternative panning, and what you describe about its working does make sense if that's indeed how the spec defines it. While I haven't tested SFZ support, I think I could help out a lot with that since Plogue Sforzando has a pretty good implementation of the spec, and I do use that a lot as well. I wouldn't expect Bass to quite match what Sforzando does but there's nothing saying we can't keep getting better.
Thanks for reading.

Ian @ un4seen

The MIDI plugin does indeed use the level of the sample data when calculating when to stop playing a released sample, so that all samples should get stopped at around the same level. That only applies to looped samples. In your case, the piano sample reaches a low level before the sinewave sample does. I will see if it can be tweaked a bit, eg. a lower level when there aren't many samples playing.

raygrote

Thanks for clearing that up, it's the only thing that made sense. Maybe there should be an option to adjust how sensitive that is, or to just turn it off altogether like it was in older versions? Maybe it's just me but I don't like envelopes cutting prematurely unless there's a reason for it, like poly limits being reached etc. Anything beyond that and I start to get worried that it'll mess up as shown here and cause problems.

Ian @ un4seen

The release is lograthmic, which means it never actually reaches 0 and needs to be cut-off at some point. That point is currently at around -70 dB, but here's an update for you to try, which will lower it on a sliding scale down to around -90 dB when there are few samples playing:

   www.un4seen.com/stuff/xmp-midi.dll

Let me know how you get on with that.

raygrote

Hi,
Thanks for the prompt response and update! If I understand you correctly, this version of the plug-in terminates the release envelopes slightly lower than they otherwise would be, when there are few samples playing, and so scues things down a little bit? I do notice a difference in this version, the envelopes do seem to cut a little later, but I am still confused.
I get that the releases are logarithmic and need to be cut at some point of attenuation. But my impression of the older versions of the plug-in is that they would just go down and cut when they reached that minimum attenuation, say, -70 dB since that's what you said it was. If the voice limit was reached, those samples which were closest to that -70 dB attenuation would be cut first. This makes logical sense.
But the later versions of the plug seem to go one step further and try to cut samples based on the waveform or something, before the voice limit or minimum attenuation is hit. I guess what I'm confused about is why this is necessary, since the voice limit setting which has been in the plug all along and will cut quiet samples first anyway seems sufficient.
Sorry to be so picky, I'm just a curious cat. Was there a specific scenario or reason which prompted this to be done, or am I not understanding things right?

Ian @ un4seen

To clarify, there are actually several things included in the release cut-off level calculation/test: the volume envelope, the level of the sample's data, the samples's "initial attenuation" setting (in the soundfont), the note velocity. When those things combined reach -70 dB (or up to -90 dB with the update), then the sample is stopped. No sample will be stopped before reaching that level, unless the plugin runs out of voices. As an example, if the combined level of the other things is -20 dB, then the envelope has to reach -50 dB for a total of -70 dB. If you use the "WAV Writer" device to convert your test MIDI file to a WAV file with rev.14 and then inspect it in a sample editor, you should find that the piano was indeed at around -70 dB when it was stopped.

In the past (around 2.5 years ago), only the envelope was considered, and the sample would stop when that reached -40 dB. The reason for the change was to improve efficiency (no point wasting CPU on a sample that has become inaudible) but also to improve sound quality as a -40 dB cut-off was noticeable with loud samples.

nicorac

Will this update be ported to bassmidi.dll too?

ELP

#859
Is there a chance, that
maybe GS Tone Number SysEx change also to be  ported to XMplayMidi?

I mean the same as within newer bassmidi Vxx , which work BTW. very well.

F0: Exclusive status byte
41: Manufacturer' s ID (Roland is 41)
10: Device ID (default to 10)
42: Model ID (GS message is 42)
12: Command ID (12 is Device Transmit)
40: Parameter byte
1n: Part (Channel) n 0=CH10 | 1-9 CH 1-9|A-F CH 11-16
00: Tone Number
BS: Bank Select (00 to 7F)
PC: Patch Select (00 to 7F)
XX: Check Sum
F7: End of Exclusive

Greetings