Closed AliceLR closed 4 years ago
Feedback re: any of this, but particularly how I added the new effects with regards to the UNI format definitely welcome.
UNI handling seems to be a mess. Trip down the memory lane:
mikmod-3.0.4: Removes the UNI loader
mikmod-3.1 : UNI_ITEFFECTZ inserted before UNI_ITEFFECTS0,
UNI_ULTEFFECT9 added.
libmikmod-3.1.5 : UNI_MEDSPEED, UNI_MEDEFFECTF[1|2|3] added.
UNI loader is added back.
libmikmod-3.1.10: UNI_OKTARP added.
(Looks like it was a good thing that I gathered historic versions..)
So I'm not sure yet as to how UNI format handling should be done with your changes, considering it had not been handled before.
Good to know. FWIW the reasons I went with my current implementation is: 1) It looks like MikMod doesn't have MikCvt anymore (I might have missed it) so I'm not sure what would be able to produce a modern UNI file with these effects. 2) Having a cutoff for the UNI effects and adding new effects after it means there's more flexibility in reordering that part of the effects list and they can still get added to UNI later. 3) I found a post from 2002 implying that UNI was already pretty much unsupported by then...
0x04
, MMD0 0x05
, 0x14
)I updated MED vibrato and added support for the PT-compatible vibrato command. Since MED vibrato is supposed to have twice the depth of PT vibrato and it seems that MED vibrato also has 2-4x the rate of PT vibrato, I went ahead and added another UNI effect to allow the increased range. The depth conversion from old 5xx
vibrato to 4xx
vibrato actually seems to be around 8:1 but the 4:1 worked out because 4xx
depth needed to be doubled. This is another one where the usage in actual files isn't that convincing so I made some test files.
vibrato5xx.med.zip (OctaMED 2.x test file with several patterns of roughly equivalent 5xx
and 4xx
)
vibrato14xx.med.zip (OctaMED 4.x+ test file with several patterns of roughly equivalent 4xx
and 14xx
)
Just an update on this one since I've implemented a few more commands, particularly the ones that were causing the worst playback bugs (changing speed or getting stuck in loops).
0x19
)This one should be directly compatible with the .MOD offset effect.
Total MMD1s: 475.
Example files | Usage (tested w/ OctaMED 4) | MikMod (master) | MikMod (patch) |
---|---|---|---|
Chris the Highlander/thend.mmd1 | Timing misc. samples--obvious in drum pickup. | Drums sound wrong; speed changes. | works. |
Essential Sound/another rave techno.mmd1 | Timing misc. samples--obvious in bass. | Bass sounds VERY wrong; speed changes. | works. |
0x0A
and 0x0D
)I found a minor deviation from the way this is currently implemented in MikMod: in OctaMED, if both nibbles are set, a slide up is always performed. An example of this can be found in several orders near the end of alien breed ii.med, though MikMod can't play it due to broken commands 0x1A
and 0x1B
...
0x1A
and 0x1B
)Total MMD1s: 224.
Implemented using the (now working) XM fine volslide effects. The first test fine volslides down 64 times then up 64 times, which I used to verify that these implementations work the same between MikMod and OctaMED. The second test uses a param of 0, which does nothing in OctaMED (and needs to be filtered out so it doesn't continue like the XM effects). Prior to patching these would immediately jump to order 1 and then interpret the 1A01
s as regular volslides.
finevol.med.zip finevol0.med.zip
Example files | Usage (tested w/ OctaMED 4) | MikMod (master) | MikMod (patch) |
---|---|---|---|
- unknown/alien breed ii.mmd1 | Used at the start, other places. | Gets stuck in order 1 | Plays correctly now :D |
Blair Zuppicich/roadkill - end.mmd1 | Used near the start. | Gets stuck in order 2 | Doesn't get stuck anymore. |
0x1F
), FF1
, FF2
, FF3
revisited.Total MMD1s that use 1Fx0
(x!=0): 84.
Total MMD1s that use 1F0x
(x!=0): 159.
Total MMD1s that use 1Fxy
(x,y!=0): 7.
This is only allowed on a line with a note and is ignored on lines without notes so fortunately there are fewer edge cases to worry about. This does need to work correctly with both params though. This fix allows the FF1
/FF2
/FF3
test files in the first post to actually play back correctly. Test file for various usage of this command:
Example files with obvious or frequent usage | Used in |
---|---|
- unknown/funkee gitar.mmd1 | Hi-hat, snare |
Brooker/brooker3.mmd1 | Various drums |
I also gave FF1
/FF2
/FF3
another look because of #21 and I'm glad I did, because there are a couple of edge case quirks with FF1
and FF3
. In OctaMED 4 and 5, these will retrigger on lines without notes (but not on tick 0), but from OctaMED 6.00d up they are ignored on lines without notes. By "lines without notes" I also mean lines with an instrument plus OctaMED's weird hold symbol. There are 5 MMD0s and 12 MMD1s that use these on a line with no notes. Since support for MMD2/MMD3s isn't a concern yet I just left a comment re: this and tweaked the FF3
implementation to not use E9x
(so now .MED doesn't rely on E9x
at all).
Two more test files for this specific edge case:
ffcmdsb6.med.zip ffcmdsb9.med.zip
Module | Relies on these? |
---|---|
- unknown/argonaut.mmd0 | Yes (seq. 9/block 5) |
Dan Pyrik/trapped under ice.mmd0 | Yes (seq. 33/block 27) |
Daniel H. Dean/bloated skunk.mmd0 | Yes (seq. 19/block 13) |
Daniel H. Dean/eye socket wrench.mmd0 | Probably (seq. 16/block 8) |
Mark Salud/if in venus.mmd0 | Yes (seq. 11/block 8) |
Bobby Clark/asteroid trip 808.mmd1 | Relies on rapidly strobing row highlighting :/ |
Bobby Clark/b.c.mmd1 | No (seq. 12/block 11) |
JaDe/deadline.mmd1 | Yes (seq. 6/block 3) |
Redd Kaa/astonishing.mmd1 | Yes (seq. 28/block 0) |
Redd Kaa/stormcaster.mmd1 | Yes (seq. 23/block 12) |
Redd Kaa/the big sellout.mmd1 | Yes (seq. 56/block 29) |
Sheffra/a different way.mmd1 | No (seq. 30/block 28) |
Sheffra/ad infinitum.mmd1 | Yes(?) (seq. 64/block 47) |
Sheffra/coop-Redd Kaa/synergy.mmd1 | Probably (seq. 76/block 65) |
Spoochy/denoman.mmd1 | Probably (seq. 22/block 17) |
The Raven/stage 2 act 2.mmd1 | Yes (seq. 44/block 33) |
Ullrich/snap d groove babe (from arne 2 wiebke).mmd1 | No (seq. 18/block 5) |
😱😱😱😱😱 http://www.hipooniosamigasite.org/amigadocs/files/LSD-DOCS-DISKS/LSD58/Octamedv5.Doc-Pt2
Note: more experimentative users may discover that octaves 8 and 9 of a
normal sample also appear to play two lower octaves. These octaves should,
however, *NEVER* be used in songs (apart from with MIDI): believe it or not,
it is in fact a complete coincidence that they work! ExtSamples are the
only "legal" way of using the two lower octaves. In any case, octaves 8 and
9 are also one finetune step sharp :-)
childplay.med u got 2.med the chase.med
MikMod and libxmp play these notes at very high octaves. OpenMPT strips these notes out entirely. edit: 30 affected MMD1s and no affected MMD0s, though some of those might be MIDI (like "sweat" from the MMD1 unknown author dir).
This ridiculous format is never going to let me finish...
edit 2: Took a look at OpenMPT and it looks like it handles these in the instrument mapping due to it only affecting some cases (they only get stripped out in the tracker due to their octave being too high). Since it only affects some instruments and theoretically someday MikMod might have synth instruments, the fix for this probably needs to be implemented alongside the instrument transpose and IFF instrument fixes rather than by changing the notes.
0x11
and 0x12
)Total MMD1s: 121.
Due to the expanded range these needed to be implemented with the XM implementations of the E1x
and E2x
effects (which already have the expanded range).
Test file: first pattern does fine portamento up from C-2 to approximately C#2, then the second pattern does fine portamento down from C#2 to approximately C-2. Prior to the fix they slide quite a bit further.
Example files | Usage (tested w/ OctaMED 4) | MikMod (previous patch) |
---|---|---|
- unknown/when she talks.mmd1 | Guitar bends. | Exaggerated bends... |
Andy Soar/blood net - turn.mmd1 | Slight detune for a "chorus" effect. | Detunes too much. |
0x16
)Total MMD1s: 156. Total MMD1s that use a param >0F: 5.
This is similar to PT looping but with an extended range. I did some testing to loop for any quirks that might be relevant.
Quirks:
Due to the way MikMod's loops currently work copying the behavior where the loop point carries between patterns would probably require a new variable in MODULE
and some care to make sure infinite loops aren't possible. For now I just made it use the same loop implementation as E6x
because it's not clear if anything even relies on that weird quirk. Adding a new variable would also help get rid of a hack to make the loop point global (instead of per-track).
Example files | OctaMED 4 | MikMod (previous patch) | MikMod (loop fix) |
---|---|---|---|
Appi-Ukko/happovaiva.mmd1 | 1:27 | 1:02 | 1:13 (difference due to 0x1E ) |
Apollon/pilot i tyskland.mmd1 (>0F) | ~65 minutes | 1:43 | Why can this command loop 256 times? :/ |
Brooker/(brooker) # 01.mmd1 | 3:06 | 3:00 | 3:06 |
Chris the Highlander/afraid.mmd1 | 1:50 | 1:27 | 1:50 |
Essential Sound/unnamed.mmd1 (>0F) | 1:42 | 0:10 | 1:42 |
Muskote/accapela.mmd1 | 1:05 | 0:42 | 1:05 |
Muskote/afrika.mmd1 | 2:00 | 0:34 | 2:00 |
Phia/terrene.mmd1 | 3:39 | 3:19 | 3:39 |
0x18
)Total MMD1s: 48. Total MMD1s that use a param >0F: 0.
Should be pretty much the same as .MOD cut note ECx
but with a larger range. Like .MOD note cut, values >= speed do nothing and it's supposed to be implemented by just setting volume to 0.
Example files | Usage (tested w/ OctaMED 4) |
---|---|
- unknown/no second prize.mmd1 | Used in various parts. |
Blockhead/childplay.mmd1 | Used briefly near the end. |
Redd Kaa/coop-Necrofthonia/numb.mmd1 | Used on pretty much every row in pattern 1. |
Tripper/los weirdos.mmd1 | Used frequently and overtly in the second half to truncate notes shortly after they begin. |
0x1D
)Total MMD1s: 12.
Exactly the same as .MOD Dxx
as far as I can tell. Not used by many tracks since OctaMED has F00
and variable-length patterns but when it is it's usually to control repeating.
Example files | Usage (tested w/ OctaMED 4) |
---|---|
- unknown/fifteen k.mmd1 | Uses 1D02 at the end to loop to an earlier block without triggering the first notes of the target block. |
- unknown/loop#.mmd1 (there are 5 of these) | Uses 1D01 to indefinitely loop a single row. |
Brooker/(brooker) # 11.mmd1 | Uses 1D20 to indefinitely loop the last half block. |
Don Howard/myth.mmd1 | Uses 1D02 at the end to loop to the first block without triggering the first notes of the target block. |
0x1E
)Total MMD1s: 126. Total MMD1s that use a param >0F: 81.
The same as .MOD pattern delay, but with a larger range.
Example files | OctaMED 4 | MikMod (previous patch) | MikMod (pattern delay fix) |
---|---|---|---|
- unknown/no second prize.mmd1 | 2:34 | 2:33 | 2:34 |
Appi-Ukko/happovaiva.mmd1 (0xFF!) | 1:27 | 1:12 | 1:27 |
Blockhead/childplay.mmd1 | 1:48 | 1:46 | 1:48 |
0x01
and 0x02
)In OctaMED, these commands do not have effect memory: 100
and 200
are completely ignored, just like 1100
and 1200
. I just added checks to the MED loader to remove instances of 100
and 200
, but these effects should not provide effect memory for ST/NT/PT .MODs either (FT and MPT not clear; a research project for some other time probably better suited to issue #21). Found in one of the test files below (monstrous.med). xmp has this bug too.
Example files | Uses | OctaMED 4 | xmp | MikMod (master) | MikMod (patch) |
---|---|---|---|---|---|
- unknown/alcoholic score.mmd1 | 14 18 19 1B 1F0x |
4:49 | 4:49'8 | Gets stuck in a loop at order 1. | 4:49, sounds correct. |
- unknown/amiga skank.mmd1 | 07 19 1E>0F |
3:10 | 3:08'7 | Speed drops to 22 at order 9. | 3:10, sounds correct. |
- unknown/monstrous.mmd1 | 11 14 16 18 19 1B 1F0x |
6:49 | 6:49'8 | Tempo drops to 3 at order 5. | 6:49, portamento bug at order 44/45 (fixed). |
- unknown/overkill.mmd1 | 11 19 1B 1Fx0 1F0x |
1:27 | 1:27'1 | Speed drops to 16 at order 3. | 1:27, sounds correct. |
Ache/coop-NRG/one step, a head.mmd1 | 11 14 16 19 1E 1Fx0 |
3:39 | 3:30'7[1] | Speed drops to 16 at order 14. | 3:31[1], sounds correct. |
Clawz/canal green.mmd1 | 11 14 16 18 19 1B 1E |
4:20 | 4:13'4[2] | Speed drops to 18 at order 3. | 4:20, sounds correct. |
Eivind Segrov/nighttrain.mmd1 | 05 06 07 11 14 18 19 1D 1Fx0 |
4:47 | 4:47'3 | 5:14[3], minor bugs. | 5:14[3], sounds correct. |
[1]: This track uses 900
at the very end, which sets the speed to 32 in most Amiga OctaMED versions (where the 9xx
command behaves as speed=param & 0x1F
, 0->32). Soundstudio 2 and up ignores 900
and allows 9xx
to set the speed higher than 32. Right now libxmp and OpenMPT ignore this and MikMod maps this to the initial speed (???), which is a behavior that survived my tempo/speed fix patch because I didn't question it as much as I should have. It might be worth allowing these unusual ranges for MMD0s, MMD1s, and MMD2s at the very least at some point, but for now I'm just making MikMod ignore it to be consistent with the handling of values >32.
[2]: I think this difference might be due to a time tracking bug in libxmp... despite playing correctly(?) it counts ~19 seconds when it reaches the pattern delay at the end of the first two orders, vs. ~29 seconds in OctaMED and MikMod.
[3]: MikMod plays a hidden sequence after a pattern jump; the main sequence ends at the correct time.
That should be all of the effects that need fixing/implementation right now unless I missed something else that's broken(!). Commands that can't be added right now or don't matter yet are 0x08
(set hold/decay, which isn't implemented), 0x0E
(synth jump, but synths aren't implemented), and a handful of Soundstudio effects (only relevant to MMD3 mix mode).
edit: I forgot about FF8
and FF9
, which turn the low-pass filter off and on (respectively). Not sure if they're even applicable but I'll check. There's also FFA
and FFB
, which send "hold pedal on" and "hold pedal off" for MIDI instruments, as well as some other MIDI alternate behaviors for other commands (MIDI isn't implemented either and I don't know if they even should be).
Sorry, here's another issue to organize my research on OctaMED-related bugs.
Aside from the missing effects I noted here I've found issues with several other effects and another set of missing OctaMED effects (this time, they were allegedly introduced in OctaMED 3).
Links to relevant documents:
My progress on this issue: https://github.com/sezero/mikmod/compare/master...AliceLR:fix-med-effects. Feedback re: any of this, but particularly how I added the new effects with regards to the UNI format definitely welcome.
Play note twice, delay note, play note three times (
FF1
,FF2
,FF3
)FF1
uses: 90 MMD0, 154 MMD1FF2
uses: 49 MMD0, 38 MMD1FF3
uses: 19 MMD0, 43 MMD1Despite the strange documentation in the OctaMED 2 effects document (which is probably why these were implemented the way they were), it's clarified in later documents that
FF1
is equivalent to1F03
,FF2
is equivalent to1F30
, andFF3
is equivalent to1F02
(i.e. all three commands assume a secondary tempo of 6). I've verified the following for various versions of OctaMED:FF1
1F03
).FF2
1F30
.FF3
1F02
.This is easier to demonstrate with tests than with any modules I found. Each plays at speeds 6, 9, or 12: 1) two snare hits with no commands; 2) two snare hits, the second with
FF1
, then two snare hits, the second with1F03
; 3) two snare hits, the second withFF2
, then two snare hits, the second with1F30
; 4) two snare hits, the second withFF3
, then two snare hits, the second with1F02
.ffcmds6.med.zip ffcmds9.med.zip ffcmds12.med.zip
Set pitch (
FFD
)Total MMD0/MMD1 uses: 47.
This is supposed to immediately set the pitch of the current playing note to the new note without retriggering it. This required a new UNI effect (though all it does is stops the new note from playing...).
Portamento/Vibrato continue + volslide, Tremolo (
0x05
,0x06
,0x07
)0x05
uses: 11 MMD0, 58 MMD10x06
uses: 15 MMD0, 152 MMD10x07
uses: 1 MMD0, 22 MMD1These are apparently OctaMED 3 commands but I don't have the OctaMED 3 documentation; they're missing from the OctaMED 2 document but they're present in the OctaMED 4 document. These are ProTracker-compatible effects and are trivially implemented. Commands
0x06
and0x07
don't exist in previous OctaMED versions so they should be safe. Command0x05
was legacy vibrato prior to OctaMED 3, and all 11 MMD0s that use that command seem to have intended to use that.0x05
:0x05
used as:0x05
vibrato.)0x07
—it appears to be a mistake that was intended as0x04
.0x06
:0x06
used as:So I put a version check on effect
0x05
and just let the other two translate to their ProTracker equivalents unconditionally. The implementation for the legacy vibrato was also wrong (the entire byte is the depth and the rate is fixed). I'm not sure the exact conversion to regular vibrato but I went withRate=0xB, Depth=MIN(((old depth + 3) >> 2), 0xF)
and it sounds close enough.Portamento+volslide
0x05
example: orders 4/5 of balance.med. Tremolo example: the bass in john paul ii.med uses it, but it's subtle. Other examples use too many features MikMod doesn't support yet.Finetune (
0x15
)Total MMD1 uses: 33.
I had to make my own test case to really test this since nothing that uses it is particularly obvious about it. It's exactly the same as ProTracker finetune.
finetune.med.zip
Other fixes
soul crystal - witching hour.med
)