Closed AliceLR closed 3 years ago
As far as the removal of that division by 4, I've tested a few tracks and I'm fairly confident that 1) nothing relies on that division by 4, and pretty much every tempo mode track that uses 9xx
relies on it NOT dividing by 4; 2) that change doesn't negatively affect tracks that didn't have a buggy 9xx
before (either in BPM mode or by luck of the command translating to ProTracker F00
and being ignored).
Tested playback times vs. OctaMEDPlayer v0.903. OctaMEDPlayer times come from measuring a stereo mix recording in Audacity (~ means ambiguous loop so it's a weak estimate), xmp/MikMod times are as reported by their respective players. (!) means there was another bug for that particular file. All files ending in .mmd0 and .mmd1 are just files from the OctaMed MMD0/1 folders on modland.com since I didn't feel like linking them all directly ;-(
edit: also, xmp's accuracy for OctaMED files is impressive enough that I'm probably not going to bother with the OctaMEDPlayer timing step in future testing unless something seems suspicious.
File | Type | OctaMEDPlayer | xmp | MikMod | MikMod (patch) | Notes |
---|---|---|---|---|---|---|
wizardry.med | MMD0/Tempo | 1:28'77 | 1:28 | 0:12 | 1:28 | |
alain.med | MMD0/Tempo | 2:52'99 | 2:52'5 | 0:29 | 2:53 | [1] out of tune. |
yellybeansong.med | MMD0/Tempo | ~4:04'27 | 4:03'4 | 0:41 | 4:04 | Portamento inaccuracy? |
Dean Evans/terminator 2 - puzzle.mmd0 | MMD0/Tempo | ~1:19'33 | 1:19'9 | 1:20 | 1:20 | 902 -> PT F00 ignored prior to patch. |
Faroul/sad song.mmd0 | MMD0/Tempo | ~2:11'55 | 2:10'5 | 0:24 | 2:10 | |
HJE/high speed.mmd0 | MMD0/Tempo | ~0:43'5 | 0:42'0 | 0:08 | 0:43 | |
James Pimentel-Pinto/amiganuts power.mmd0 | MMD0/Tempo | ~1:55 | 1:54'7 | 0:19 | 1:55 | |
Kevin Stannard/lunar-c-title.mmd0 | MMD0/Tempo | ~1:08.5 | 1:07'9 | 1:08 | 1:08 | 903 -> PT F00 ignored prior to patch. [1] chords out of tune. |
- unknown/red herring.mmd0 | MMD0/BPM | 3:54.22 | 3:54'1 | 3:54 | 3:54 | |
Basehead/high velocity.mmd0 (sequence 0) | MMD0/BPM | ~1:39'53 | 1:39'3 | ????? (!) | 1:40+ (!) | [1] out of tune. Reaches the end of the first sequence at the correct time. |
Dodge/agony title tune remixed.mmd0 | MMD0/BPM | 4:51'72 | 4:51'7 | 4:51 | 4:51 | |
Dodge/rollin & bollin.mmd0 | MMD0/BPM | 5:27'70 | 5:27'6 | 5:27 | 5:27 | |
Orpheus/electrosound 64.mmd0 | MMD0/BPM | >1:55 | 1:55'4 | 3:16 (!) | 3:16 (!) | [2] MikMod plays at half speed. |
- unknown/5th beathoven.mmd1 | MMD1/Tempo | 1:01'67 | 1:01'3 | 0:10 | 1:01 | 906 -> PT F01 |
- unknown/gotterfunken.mmd1 | MMD1/Tempo | 3:59'82 | 3:58'8 | 0:43 | 3:58 | 906 /905 -> PT F01 . [1] out of tune. |
Andy Baxter/cheryl heaven.mmd1 | MMD1/Tempo | 2:13'61 | 2:12'9 | 0:33 | 2:13 | 908 -> PT F02 |
Andy Soar/blood net - combat.mmd1 | MMD1/Tempo | 1:47'88 | 1:47'4 | 0:17 | 1:47 | 906 -> PT F01 |
Blair Zuppicich/roadkill - end.mmd1 | MMD1/Tempo | ~1:00 | 1:00'6 | ? (!) | ? (!) | [3] MikMod gets stuck in a loop (1B02 -> B02). |
Blockhead/spaceship.mmd1 | MMD1/Tempo | ~2:18'50 | 2:18'0 | 0:30 | 2:18 | 909 -> PT F02 |
Brooker/(brooker) # 01.mmd1 |
MMD1/Tempo | ~3:05'59 | 3:05'3 | 1:01 | 2:22 (!) | [3] Patch is closer to correct; affected by 1Fxx -> Fxx. |
Caramel/liver paste.mmd1 | MMD1/Tempo | ~2:41'54 | 2:40'9 | 1:02 | 2:41 | 90A -> PT F02 |
Chris the Highlander/afraid.mmd1 | MMD1/Tempo | 1:50'47 | 1:48'6 | 0:15 | 1:27 (!) | [3] Patch correct aside from 16xx -> 6xx at the end. |
Cobalt/drum sampler (sunsa del luya).mmd1 | MMD1/Tempo | ~2:26'05 | 2:25'8 | 0:24 | 2:25 | 906 -> PT F01 |
Cosmiq/heavy stuff.mmd1 | MMD1/Tempo | 1:43'15 | 1:42'6 | 0:25 | 1:42 | 904 -> PT F01 |
Dean Evans/jurassic park - music1.mmd1 | MMD1/Tempo | ~1:30 | 1:29'6 | 0:14 | 1:33 | 907 -> PT F01 (silent loop at end probably is the cause of the slightly different times) |
Dimitrios Charalampidis/black waltz.mmd1 | MMD1/Tempo | ~1:32'15 | 1:32'0 | 0:20 | 1:32 | 906 -> PT F01 |
Dr. Tomastik/charless.mmd1 | MMD1/Tempo | 1:32'55 | 1:32'0 | 0:16 | 1:32 | 906 -> PT F01 |
- unknown/alien breed ii.mmd1 | MMD1/BPM | 3:53'3 | 3:53'1 | ? (!) | ? (!) | [3] MikMod gets stuck in a loop (1B01 -> B01). |
- unknown/digi-t-ice.mmd1 | MMD1/BPM | 1:37'27 | 1:37'2 | 1:37 | 1:37 | [1] Out of tune. |
- unknown/fair.mmd1 | MMD1/BPM | 0:44'81 | 0:44'6 | 0:44 | 0:44 | |
Appi-Ukko/happovaiva.mmd1 | MMD1/BPM | 1:27'66 | 1:27'4 | 0:55 (!) | 0:55 (!) | [3] 1Bxx -> Bxx; 16xx -> 6xx; 1EEF -> EEF |
C-Frog/soft vision.mmd1 | MMD1/BPM | ~2:24 | 2:21'7 | 1:48 (!) | 1:48 (!) | [3] 19xx -> 9xx and probably others. |
Chroust/pentium.mmd1 | MMD1/BPM | 2:18'26 | 2:18'0 | 2:18 | 2:18 | |
Cybarite/dark obsession title.mmd1 | MMD1/BPM | ~2:21 | 2:20'6 | 5:10 (!) | 5:10 (!) | [3] 1F30 -> F30 causes it to play slow starting from order 2. |
Darkman/mindphaser.mmd1 | MMD1/BPM | 1:59'08 | 1:58'9 | 1:59 | 1:59 | |
Debol/debol'97-msx3+.mmd1 | MMD1/BPM | 1:24'53 | 1:24'4 | 1:24 | 1:24 | |
DJ Hotcakes/double dragon.mmd1 | MMD1/BPM | 2:26'64 | 2:28'4 | >3:00 (!) | ? (!) | [3] 19xx -> 9xx |
Dreamland Fantasy/china girl.mmd1 | MMD1/BPM | 2:59'25 | 2:59'0 | 2:07 (!) | 2:07 | [3] 1F03 -> F03; other bugs?... |
Dreamland Fantasy/discovery.mmd1 | MMD1/BPM | 1:42'41 | 1:42'2 | 1:42 | 1:42 | |
Dreamland Fantasy/doctor who.mmd1 | MMD1/BPM | 0:30'72 | 0:30'6 | 0:46 | 0:46 | Difference is just due to MikMod playing past the loop (not a bug). |
Flash (PL)/daj mi te noc.mmd1 | MMD1/BPM | 1:49'33 | 1:49'2 | >3:00 (!) | ? (!) | [3] 19xx -> 9xx; 1F40 -> F40 |
New bugs found during testing:
[1] Seems to be a tuning bug in both MMD0 and MMD1 .MEDs caused by the MED loader not handling either the song or instrument transpose values (this needs verification). I'm not familiar enough with MikMod to tell how hard this would be to implement.
[2] The speed of BPM mode modules sometimes starts as or changes to something very wrong. From examining electrosound 64.med (and currently no other modules) this appears to be because of the loader factoring the GCD of beat rows (10) and initial speed (4) out of both the initial BPM (60) and speed (resulting in 60*10/4/2=75 tempo and 4/2=2 speed). The 9xx
command is then immediately used to set the original speed of 4 (for an effective halving of overall speed). Haven't checked other modules for this yet. Considering high speed.med reached 909 tempo with no issue I'm skeptical that this GCD algorithm does anything useful (speed can never be set >255; the UWORD range should be adequate for sane BPM/beat row combos, but maybe tempo was a UBYTE when the algorithm was added). Another bug that could be caused by this factoring is, if the divisor were consistently applied to speeds provided by a 9xx
command and those speeds were not a multiple of the GCD, the resulting speed would be truncated. Tentatively suggesting that the entire GCD thing be removed, but it needs more analysis and testing. (Also, the beat rows value may need to be provided to EffectCvt() and Fxx
might need to switch to using UNI_MEDSPEED for BPM mode.)
[3] OctaMED 4.00 commands unimplemented:
I'd like to investigate bug 2 further and include a patch for it with this patch if possible. I'll submit a separate patch for the unimplemented OctaMED 4 commands (are there any compatibility concerns when adding new UNIMOD commands I should be aware of before implementing those?).
Until then, the working patch for this issue is simply:
diff --git a/libmikmod/loaders/load_med.c b/libmikmod/loaders/load_med.c
index 84cfb1f..1caebaa 100644
--- a/libmikmod/loaders/load_med.c
+++ b/libmikmod/loaders/load_med.c
@@ -219,8 +219,6 @@ static void EffectCvt(UBYTE eff, UBYTE dat)
if (dat <= 0x20) {
if (!dat)
dat = of.initspeed;
- else
- dat /= 4;
UniPTEffect(0xf, dat);
} else
UniEffect(UNI_MEDSPEED, ((UWORD)dat * 125) / (33 * 4));
I did some more testing for BPM mode speed bugs. This took longer than I expected because, as it turns out, getting OctaMED timing correct is a total nightmare. I think I've pretty much corrected it, though. I'm splitting this over a few comments because there are several tables.
"Patch 2" is the revised patch that fixes some BPM mode speed issues, the compatibility tempos, and other edge cases. [1][2][3] refer to bugs listed in the previous post; [2*] is a special case of [2] relating to the Fxx
command that wasn't mentioned in the previous post. Specifically, the GCD logic when (rows per beat!=4) seems to have been added to compensate for the 9xx
and Fxx
commands providing BPM values in BPM mode that need to be converted, and seems to have accidentally worked in enough cases that it stuck. The correct thing to do is to multiply the BPM values provided to 9xx
/Fxx
by (rows per beat/4) to get a PT-compatible tempo. The rows per beat value can't be changed so this conversion can/should just happen at load time.
Another issue with the GCD division of speed that I didn't mention before is that it also breaks any command that relies on executing every tick (e.g. 1xx
, Axx
...).
File | Type | xmp (OctaMEDPlayer) | MikMod (patch 1) | MikMod (patch 2) | Notes |
---|---|---|---|---|---|
Dirtie/weather.mmd0 | MMD0/BPM/4t | 2:23'8 | 2:24 | 2:24 | Beat rows=5, speed=6, GCD=1 |
Fog/beavis & butthead.mmd0 | MMD0/BPM/4t | 2:55'0 | 2:55 | 2:55 | Beat rows=8, speed=6, GCD=2 |
Orpheus/electrosound 64.mmd0 | MMD0/BPM/4t | 1:55'4 | 3:16 [2][5] | 1:38 | Beat rows=10, speed=4, GCD=2 (9xx, F02) |
- unknown/amiga skank.mmd1 | MMD1/BPM/4t | 3:08'7 | LONG [2][2*][3][4] | 3:08 | Beat rows=6, speed=6, GCD=6 (9xx, Fxx, F(03-20), 19xx) |
- unknown/dance.mmd1 | MMD1/BPM/4t | 1:41'4 | 1:41 | 1:41 | Beat rows=5, speed=6, GCD=1 |
- unknown/hardcorevibes.mmd1 | MMD1/BPM/4t | 2:45'0 | 2:45 | 2:45 | Beat rows=8, speed=6, GCD=2 |
- unknown/its a skull.mmd1 | MMD1/BPM/4t | 3:34'9 | 3:35 | 3:35 | Beat rows=5, speed=7, GCD=1 |
- unknown/three phantoms.mmd1 | MMD1/BPM/4t | 0:59'0 | 2:55 [1][2][3] | 0:59 | Beat rows=5, speed=5, GCD=5 (9xx, 1Bxx) |
Alexander Zutt/new dimension.mmd1 | MMD1/BPM/4t | didn't load (5:32'50) | 5:11 | 5:32 | Beat rows=5, speed=5, GCD=5 |
Carl Bramley/the end.mmd1 | MMD1/BPM/4t | 4:59'2 | 4:59 [1][2][3] | 4:59 | Beat rows=8, speed=6, GCD=2 (9xx, 19xx, 1Bxx) |
Digi/research e.p.mmd1 | MMD1/BPM/4t | 2:37'3 | 2:37 | 2:37 | Beat rows=8, speed=6, GCD=2 |
Echo/hard scoop.mmd1 | MMD1/BPM/4t | 8:35'2 | LONG [2][3] | 8:35 | Beat rows=8, speed=8, GCD=8 (9xx, 19xx, 1Bxx) |
Emix Lemsman/terror of thunderdome (master mix).mmd1 | MMD1/BPM/4t | 9:41'5 | 9:53 [3][4] | 9:41 | Beat rows=4, speed=4, GCD=n/a (Fxx, F(03-20), 19xx) [4]: occurs in final pattern. |
Hologen/bubbles.mmd1 | MMD1/BPM/4t | 3:55'4 | 3:50 | 3:54 | Beat rows=6, speed=6, GCD=6 |
Jam Thrash/do your stuff.mmd1 | MMD1/BPM/4t | 5:46'2 | LONG [1][3][4] | 5:44 | Beat rows=4, speed=6, GCD=n/a (Fxx, F(03-20), 19xx) |
Jimbim/phanta1.mmd1 | MMD1/BPM/4t | 4:02'0 | 3:42 [1][3] | 3:42 | Beat rows=8, speed=6, GCD=2 (Fxx, 16xx) [3]: missing loops shortened this track a little. |
Morgoth/coop-Turin/epitaph.mmd1 | MMD1/BPM/4t | 4:25'7 | 5:32 [2*][4] | 4:25 | Beat rows=15, speed=6, GCD=3 (Fxx) |
Phia/2 demo 4 u.mmd1 | MMD1/BPM/4t | 3:48'3 | 7:36 [2][3] | 3:48 | Beat rows=8, speed=12, GCD=4 (9xx, Fxx, 19xx) |
Psiberpunk/coop-DJ Spark-E/happy bubbles.mmd1 | MMD1/BPM/4t | 5:21'6 | LONG [2][3] | 5:21 | Beat rows=8, speed=6, GCD=2 (9xx, 19xx) |
Samuel/inspiration - cutre mix.mmd1 | MMD1/BPM/4t | 3:02'3 | LONG [4] | 3:02 | Beat rows=20, speed=6, GCD=2 (Fxx, F(03-20)) |
Sheffra/vertigo.mmd1 | MMD1/BPM/4t | 5:59'2 | 5:49 [3][5] | 5:51 | Beat rows=4, speed=3, GCD=n/a (9xx, Fxx, F(01-02), 19xx, 1Bxx) |
Spoochy/denoman.mmd1 | MMD1/BPM/4t | 3:48'9 | LONG [2][3] | 3:49 | Beat rows=8, speed=4, GCD=4 (9xx, 19xx) |
Spoochy/nadia i love you 4 ever!!.mmd1 | MMD1/BPM/4t | 3:14'5 | 3:09 [2*] | 3:09 | Beat rows=8, speed=6, GCD=2 (Fxx) |
Spots/amiga pop.mmd1 | MMD1/BPM/4t | 11:40'8 | LONG [2][2*] | 11:40 | Beat rows=8, speed=12, GCD=4 (9xx, Fxx) |
Tarmslyng/more power.mmd1 | MMD1/BPM/4t | 2:16'3 | 4:32 [2][2*] | 2:16 | Beat rows=8, speed=6, GCD=2 (9xx, Fxx) |
The Raven/wild and lonely.mmd1 | MDD1/BPM/4t | 4:26'5 | LONG [2] | 4:25 | Beat rows=15, speed=5, GCD=5 (9xx) |
New bugs:
[3] Not a new bug but: I hacked out effects with values over 0xF before timing several of these just so there would at least be (somewhat) useful timings for these.
[4] Fxx
with a param between 01 and 20 is supposed to set the BPM in BPM mode but instead this set the speed (bug is usage of PT Fxx
instead of UNI_MEDSPEED in two places; trivial fix and was required anyway as part of fixing [2]). Only a few tracks use Fxx
in the affected range in BPM mode.
[5] Fxx
with a param between 01 and 02 in BPM mode has a weird bug in OctaMED where it sets the tempo to ~33, ignoring rows per beat. I found this in at least two tracks. Neither xmp nor OctaMEDPlayer check for this, which is probably fair, but it was a trivial fix.
NOTES:
Jimbim/phanta1.mmd1
: GCD of 2 only corrects the usage of F38
by coincidence; 8 (beat rows) / 4 (PT beat rows) = 2 (GCD).Morgoth/coop-Turin/epitaph.mmd1
: demonstrates why the GCD logic isn't the solution to correcting the Fxx
command; the speed correction works out to 55 (BPM) 3 (GCD) = 165 ("PT tempo") whereas the correct math is 55 (BPM) 15 (beat rows) / 4 (PT beat rows) = 206.25 (PT tempo).Spoochy/nadia i love you 4 ever!!.mmd1
: also works by coincidence; 8 (beat rows) / 4 (PT beat rows) = 2 (GCD). Not clear why the time difference from xmp is 5 seconds.Fxx
for values between 01 and 0A in tempo mode was also implemented wrong: in OctaMED 2.00 and 4.00, I verified that the 1) these are treated as primary tempo and not secondary tempo (speed), 2) OctaMED internally maps these to other primary tempos, and 3) secondary tempo works with these tempos the same way that it works with regular tempos (i.e. these can just be translated with a lookup table independent of speed). I had to manually match most of these speeds because OctaMED doesn't communicate their translations and some of the values from the table in the OctaMED 1.12 documentation are inaccurate or absent. These speeds are roughly equivalent to (195 + (speed/2))/speed
. Surprisingly, xmp gets this wrong.
Compat Tempo | Approximate Tempo (MED 1.12 documentation table value) |
---|---|
1 | 195 (212) |
2 | 97 (106) |
3 | 65 (64) |
4 | 49 (53) |
5 | 39 (47) |
6 | 32 (32) |
7 | 28 (27) |
8 | 24 (n/a) |
9 | 22 (n/a) |
10 | 20 (n/a) |
Some tracks that relied on tempos in this range (I stopped testing with xmp at some point since its buggy handling of these tempos seems to break its timing):
File | Type | OctaMED 4 | xmp | MikMod (patch 1) | MikMod (patch 2) | Notes |
---|---|---|---|---|---|---|
- unknown/bund.mmd0 | MMD0/Tempo/4t | 2:52 | 4:38'6 | 2:54 | 2:54 | Tempo=6 |
- unknown/transition.mmd0 | MMD0/Tempo/4t | 3:37 | 4:01'7 | 3:53 | 3:37 | Tempo=7 at the very end. |
BAD/flee.mmd0 | MMD0/Tempo/4t | ~5:21 | 5:12'8 | 5:39 | 5:20 | |
Chris Link/soul crystal - cyberfunk.mmd0 | MMD0/Tempo/4t | ~0:55 | 2:02'5 | 0:47 | 0:55 | Tempo=6 |
Jester/1990 - goodbyesong.mmd0 | MMD0/Tempo/4t | 2:12 | 2:39'1 | 1:41 | 2:11 | Tempo=6 |
Chris Link/sky city - spheres.mmd1 | MMD1/Tempo/4t | ~1:07 | 1:20'3? (lie) | 1:37 | 1:08 | |
Chris the Highlander/life.mmd1 | MMD1/Tempo/4t | ~2:08 | ? | 2:08 | 2:08 | Tempo=6 |
Master Yoda/three views of a secret.mmd1 | MMD1/Tempo/4t | 1:36 | ? | 1:35 | 1:36 | Tempo=8 at the very end. |
Nitron/ihaaah.mmd1 | MMD1/Tempo/4t | 4:05 | ? | 6:13 | 4:09 | Tempo=6 |
Quarterback/a bold rave.mmd1 | MMD1/Tempo/4t | 2:17 | ? | 3:23 | 2:17 | Tempo=5 |
Redd Kaa/and you don't stop.mmd1 | MMD1/Tempo/4t | 3:59 | ? | 2:53 | 4:04 | Tempo=8 |
Room 237/phone tap.mmd1 | MMD1/Tempo/4t | 3:30 | ? | 5:12 | 3:30 | Tempo=5 |
Another minor thing is that usage of 9xx
with values >0x20 is not supposed to work according to the docs. OpenMPT and libxmp filter these out when they're encountered. MikMod's weird handling of this seems to be another thing shared with libmodplug. What OctaMEDPlayer does here is treats these values as speeds always. OctaMED 2.00 treats these as (speed & 0x1F). Since OctaMED 2.00 and later OctaMEDPlayer versions handle these inconsistently I think they should be treated as UB and the "best" handling for these is to just ignore them (like OpenMPT and libxmp). There are not many tracks that use these.
On top of all of this, some tracks STILL didn't play correctly, so I cheated and looked at what libxmp does. Turns out MEDs in 8 channel mode use a completely different primary tempo system with a different lookup table than the one above. I just ported this behavior directly over to MikMod.
Some tracks I tested with the 8 channel mode flag set ("(e)"=the xmp duration estimate):
File | Type | OctaMED 4 | xmp | MikMod (patch 1) | MikMod (patch 2) | Notes |
---|---|---|---|---|---|---|
- unknown/anvil.mmd0 | MMD0/Tempo/8t | 1:58 | 1:56'9 | 1:27 | 1:57 | |
Jason Honingford/trend.mmd0 | MMD0/Tempo/8t | ~2:30 | 2:29'3 | 1:55 | 2:30 | |
Teijo Kinnunen/kinnunen 2.mmd0 | MMD0/Tempo/8t | 3:26 | 3:24'5 | 2:41 | 3:25 | |
- unknown/arligentia2.mmd1 | MMD1/Tempo/8t | 3:03 | 3:01 (e) | 2:00 | 3:02 | |
- unknown/ghost busters quit.mmd1 | MMD1/Tempo/8t | 2:16 | 2:08 (e) | 1:45 | 2:15 | |
- unknown/michael.mmd1 | MMD1/Tempo/8t | 3:45 | 3:47 (e) | 2:04 | 3:47 | Tempo=9 |
- unknown/overdose1 - preview.mmd1 | MMD1/Tempo/8t | 1:52 | 1:51 (e) | 1:13 | 1:51 | Tempo=8 |
Alex Van Starrex/octasongs.mmd1 | MMD1/Tempo/8t | 9:48 | 9:45 (e) | 5:55 | 9:47 | Tempo=43(!) |
Czar/tores mix.mmd1 | MMD1/Tempo/4t | 0:08 | 0:07'9 | 0:45 | 0:08 | Tempo=1 |
Matthias Kaulartz/knighthood.mmd1 | MMD1/Tempo/8t | 3:47 | 3:41 (e) | 2:54 | 3:42 | F(>0A)(!) |
Sparky/never again.mmd1 | MMD1/Tempo/8t | 3:52 | 3:44 (e) | 4:06 | 3:44 | Tempo=7 |
Toady/secret of mana.mmd1 | MMD1/Tempo/8t | 0:43 | 0:44'7 | 0:28 | 0:43 | Tempo=9 |
Dr. Fiss/nikolaus (7''version).mmd1 | MMD1/BPM/6t | 3:06 | 3:05'0 | 3:00 | 3:06 | BPM=101 |
Ludwig/techfunk.mmd1 | MMD1/BPM/8t | 5:45 | 5:42'5 | LONG | 5:44 | BPM=48 |
Mixer/superaxel.mmd1 | MMD1/BPM/8t | 11:00 | 11:04'7 | LONG | 11:06 | BPM=9 |
Additionally, in the track superaxel.med, I found another bug that affects MEDs containing blocks with fewer tracks than the total song track count (the pattern loaders just needed to skip the unused tracks).
What a mess! PR incoming soon.
Addendum: since testing for this issue took forever, I gathered some data on the number of .MEDs using various features that aren't implemented in MikMod right now (aside from OctaMED 4 effects since I'm fixing that soon). None of these being missing is news, but actual counts of affected modules might be useful. (Values are approximate.) (FWIW I don't think MMD2/MMD3 support is worth the effort until after most of the rest of these have been addressed.)
Feature | MMD0 | MMD1 | Total |
---|---|---|---|
Instrument transpose | 199 | 541 | 740 |
Synth/Hybrid instruments | 155 | 196 | 351 |
Hold/Decay | 44 | 82 | 126 |
Song transpose | 23 | 60 | 83 |
Multiple songs | 6 | 68 | 74 |
IFFOct instruments | 34 | 38 | 72 |
MMD2/MMD3 | (161 MMD2)+(636 MMD3)=797 |
Creating an issue for this one so my research doesn't clutter the (eventual) PR.
This bug occurs with .MED files that use the .MOD secondary tempo command
9xx
in tempo mode, and appears to be caused by this line of code: https://github.com/sezero/mikmod/blob/master/libmikmod/loaders/load_med.c#L223The OctaMED documentation suggests that this should convert directly to/from the .MOD speed command and, considering MikMod's tempo conversion, it seems that there is no reason to divide this value by 4. https://modland.com/pub/documents/format_documentation/Music%20Editor%20v3.2%20(.med).txt
This change dates back to MikMod 3.1, where it appeared in the form of a
speeddivisor
variable that was always equal to 4 during tempo mode. This variable is applied to the9xx
command and the speed case of theFxx
command in different ways!By 3.1.5 this variable was completely removed, just leaving a fixed division by 4 in the
9xx
command and not in theFxx
command. This looks like an oversight that never got caught to me, but there might some reason I'm missing for this being there.Removing that line makes these example .MEDs play at the same speeds that xmp plays them at. I don't have OctaMED set up to test with right now.
alain.med.zip wizardry.med.zip yellybeansong.med.zip
Since this division by 4 was presumably added for a reason (even if it might have been a mistake), I'm going to exhaustively test (with OctaMED, xmp, and MikMod) every .MED MMD0 and MMD1 file I can find that uses this to make sure removing the bugged line doesn't cause any breakage.
edit: maybe that was too optimistic, there are 379 MMD0 files and 816 MMD1 files that use
9xx
with values <=0x20
...