-
Notifications
You must be signed in to change notification settings - Fork 22
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
Several OctaMED effects are missing or broken. #19
Comments
UNI handling seems to be a mess. Trip down the memory lane:
(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 |
Good to know. FWIW the reasons I went with my current implementation is:
Vibrato (
|
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). Sample offset (
|
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. |
Volume slide (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
...
Fine volume slide (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. |
Note delay and retrigger (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) |
😱😱😱😱😱
childplay.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. |
Fine portamento (
|
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. |
Loop (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:
- There is a single global loop point (rather than one for every track).
- The loop point carries between patterns and is not cleared on loop completion.
- Starting playback does not clear the loop point—loop jump without a loop point set uses the value from a previous play(!).
- The loop point is initialized to row 0 at startup.
- Fortunately, OctaMED does not support nested loops.
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 |
Cut note (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. |
Pattern break (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. |
Pattern delay (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 |
Portamento (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.
Tracks that use several of these effects.
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: 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:
FF1
, then two snare hits, the second with1F03
;FF2
, then two snare hits, the second with1F30
;FF3
, 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.All MMD0 modules using
0x05
:0x05
used as:0x05
vibrato.)0x07
—it appears to be a mistake that was intended as0x04
.All MMD0 modules using
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
)The text was updated successfully, but these errors were encountered: