Advice needed on MOD player porta effects
category: code [glöplog]
Hey guys. I'm coding my own mod player and so far it seems to work nicely, apart from the effects. Volume effects are easy to handle but I just don't understand how I'm supposed to do the porta effects.
Here's my best attempt at effect 0x03 (tone portamento), the first 10 seconds from space debris: http://entropia.kapsi.fi/androidDump/spacedeb_portafuckup.ogg
It's not very nice as you can hear. This is how I've been trying to do it:
1. On tick 0, save the note to slide to and the speed. Calculate direction from that.
2. On other ticks slide period speed-amount towards the target.
3. Apparently I fuck it up pretty nicely because the result is not what I would expect. Can someone diagnose what I'm doing wrong just by listening to the sample?
I based my player on Gasman's jsmodplayer (source: https://github.com/gasman/jsmodplayer/blob/master/modplayer.js), and I don't fully understand the resampling process it uses... There's the normal period lookup table with all the finetunes and then there's another period-to-note lookup table calculated at runtime. I think jsmodplayer is playing the periods from that note table instead of period table and if I go subtracting or adding period values to note values it ends up wrong.
Also, what happens if the tone porta overshoots the target? Do we just clamp it to target note?
And one other things: since I'm clueless about note theory, is there a nice lookup table ready for mod period to musical note conversion? So that I can double check my parsing against a proven tracker. Or better yet, a player/tracker that displays period numbers instead of notes?
Any pointers?
Here's my best attempt at effect 0x03 (tone portamento), the first 10 seconds from space debris: http://entropia.kapsi.fi/androidDump/spacedeb_portafuckup.ogg
It's not very nice as you can hear. This is how I've been trying to do it:
1. On tick 0, save the note to slide to and the speed. Calculate direction from that.
2. On other ticks slide period speed-amount towards the target.
3. Apparently I fuck it up pretty nicely because the result is not what I would expect. Can someone diagnose what I'm doing wrong just by listening to the sample?
I based my player on Gasman's jsmodplayer (source: https://github.com/gasman/jsmodplayer/blob/master/modplayer.js), and I don't fully understand the resampling process it uses... There's the normal period lookup table with all the finetunes and then there's another period-to-note lookup table calculated at runtime. I think jsmodplayer is playing the periods from that note table instead of period table and if I go subtracting or adding period values to note values it ends up wrong.
Also, what happens if the tone porta overshoots the target? Do we just clamp it to target note?
And one other things: since I'm clueless about note theory, is there a nice lookup table ready for mod period to musical note conversion? So that I can double check my parsing against a proven tracker. Or better yet, a player/tracker that displays period numbers instead of notes?
Any pointers?
And before anyone tells me to go dig up other peoples source codes let me tell you that I've read every single mod player's source code that I could find. Everyone does it differently and obviously I'm not a genius coder so that didn't help me a lot.
Also I've been reading the different guides on how to implement a MOD player but here we are, still. :-(
Be nice.
Also I've been reading the different guides on how to implement a MOD player but here we are, still. :-(
Be nice.
Lemme get back to this later. At least you need to clamp the period to the target. And yes, on the first tick of the new row don't slide yet. I found this period/note name table in my old sources:
856,808,762,720,678,640,604,570,538,508,480,453, /* 0 */
428,404,381,360,339,320,302,285,269,254,240,226,
214,202,190,180,170,160,151,143,135,127,120,113
"C-3","C#3","D-3","D#3","E-3","F-3","F#3","G-3","G#3","A-3","A#3","B-3",
"C-4","C#4","D-4","D#4","E-4","F-4","F#4","G-4","G#4","A-4","A#4","B-4",
"C-5","C#5","D-5","D#5","E-5","F-5","F#5","G-5","G#5","A-5","A#5","B-5"
At times those are actually called C-1...B-3
856,808,762,720,678,640,604,570,538,508,480,453, /* 0 */
428,404,381,360,339,320,302,285,269,254,240,226,
214,202,190,180,170,160,151,143,135,127,120,113
"C-3","C#3","D-3","D#3","E-3","F-3","F#3","G-3","G#3","A-3","A#3","B-3",
"C-4","C#4","D-4","D#4","E-4","F-4","F#4","G-4","G#4","A-4","A#4","B-4",
"C-5","C#5","D-5","D#5","E-5","F-5","F#5","G-5","G#5","A-5","A#5","B-5"
At times those are actually called C-1...B-3
I haven't really had to touch mod playing logic for about 15 years after making pt.c we still use. Starting from the beginning of the 90s I wrote several mod players from scratch, and the PT+SD combination was the final one of those. The "SD" = Sound Device part tries to be a "virtual Gravis Ultrasound", which was important back then to make both GUS and SoundBlaster look the same from the mod player's point of view. Check pt.c from this
http://ftp.kameli.net/pub/fit/once_upon/once_upon-src.zip
Your method looks all right to me, it's probably just a normal programming error, i.e. a bug in the implementation of the idea. Btw, I didn't use a period-to-note translation table, but just scanned through the note-to-period table for each note in a "convert pattern" routine prior to starting the actual playing.
Yes, you clamp the period value to the target. And I don't think you need to know anything about musical notes really. The musical pitch depends on the contents of the samples anyway. ;) The theory is not rocket science though. Going an octave up doubles the frequency, e.g. 440Hz --> 880Hz. In western world we use "equal temperament" which means that the octave is split to 12 semitones, each of which multiplies the previous frequency by the same ratio, namely the 12th root of 2, i.e. 2^(1/12). But you don't need to know any of this to make a mod player, because the period numbers are calculated for you already. And the periods aren't frequencies. The period means, how many clock ticks the Amiga sound chip (running at 3.5something MHz) waits before proceeding to the next PCM sample value. IIRC.
http://ftp.kameli.net/pub/fit/once_upon/once_upon-src.zip
Your method looks all right to me, it's probably just a normal programming error, i.e. a bug in the implementation of the idea. Btw, I didn't use a period-to-note translation table, but just scanned through the note-to-period table for each note in a "convert pattern" routine prior to starting the actual playing.
Yes, you clamp the period value to the target. And I don't think you need to know anything about musical notes really. The musical pitch depends on the contents of the samples anyway. ;) The theory is not rocket science though. Going an octave up doubles the frequency, e.g. 440Hz --> 880Hz. In western world we use "equal temperament" which means that the octave is split to 12 semitones, each of which multiplies the previous frequency by the same ratio, namely the 12th root of 2, i.e. 2^(1/12). But you don't need to know any of this to make a mod player, because the period numbers are calculated for you already. And the periods aren't frequencies. The period means, how many clock ticks the Amiga sound chip (running at 3.5something MHz) waits before proceeding to the next PCM sample value. IIRC.
I wouldn't recommend trusting jsmodplayer as a reference for doing things correctly. I just blindly implemented whatever Modfil11.txt said, and probably tested it less than you have :-)
This is the value we've used at least:
#define AMIGA_MASTERCLOCK 3546836
I guess you've already figured out that frequency = masterclock / period, but just in case... When sliding the period you will get values that don't correspond to any note/finetune values.
#define AMIGA_MASTERCLOCK 3546836
I guess you've already figured out that frequency = masterclock / period, but just in case... When sliding the period you will get values that don't correspond to any note/finetune values.
Thanks for the tips so far. yzi's source looks nice enough, and with Finnish comments. :-)
gasman: jsmodplayer got me off the ground and now that I'm outputting music I can get to perfecting it. :-P Maybe I'll return the favor to you by implementing more effects in to the Javascript-version and send it back to you...
Marq: Yup, I'm aware of the Amiga video clock relation to the sample playing frequency.
I best go over the source code with thought and see if I can catch the bug...
gasman: jsmodplayer got me off the ground and now that I'm outputting music I can get to perfecting it. :-P Maybe I'll return the favor to you by implementing more effects in to the Javascript-version and send it back to you...
Marq: Yup, I'm aware of the Amiga video clock relation to the sample playing frequency.
I best go over the source code with thought and see if I can catch the bug...
Might be a little bit OT but there's something I never understood about the Vibrato effect. In all docs it says that the vibrato amplitude is measured in terms of semitones. But that doesn't make any sense, historically and code-wise. We're talking 68000 and "everything more complex than add and sub is incredibly expensive" here. If you disregard vibrato you can easily play the whole mod file just with a few table lookups, add and subs - but if you try to implement vibrato as specified, you're instantly in "pow(2,ampl/12);" land, or suddenly you've got a very complicated conglomeration of period/finetune table lookups that falls apart as soon as you try vibrato+slide, etc. That doesn't compute. So, how ARE the original Amiga 1000/500/2000 class players handling this?
kb_: I think the documentation is simply wrong (as always with mod-related docs :). No MOD player that I am aware of scales Vibrato that way, they all simply scale the vibrato tables according to the depth parameter, not taking the current period / note into account. If you play a strong vibrato at e.g. C-1 and C-2, it sounds different in both octaves. However, with FT'2 and IT's "linear slides", Vibrato is indeed measured in semitones and is always +/-1 semitone "deep".
What "all docs" are you talking about? I have never bumped into such nonsense about vibrato. Check the pt.c source I linked. IIRC the sine vibrato table in the source was copied from some Amiga ProTracker replayer source code.
Just checked Modfil11.txt, and it indeed doesn't say something like that. The only time it ever talks about semitones is the explanation of the sample finetune parameter. :)
There are standard 64-item vibrato lookup tables for the different vibrato waveforms. Vibrato depth as a multiplier for the value read from the array, and vibrato speed tells how many indices to jump in the lookup table.
All in all, getting those portamentos, slides and vibratos right is not a trivial thing (when to retrig the note and when not etc.). I used this tune as a sort of acid test back in the day: Aglow by Strobo, often known as mindflow.mod, too. It keeps sliding after vibrato and back to vibrato for looong without retrigging the note, so if the player is even a bit off, the sound becomes distorted.
One oddity more to the list: if there's a volume slide up and down at the same time, the volume up direction wins. So a slide of 11 will slide up only. Of course it's a wrong use of parameters but that didn't stop musicians from doing it...
One oddity more to the list: if there's a volume slide up and down at the same time, the volume up direction wins. So a slide of 11 will slide up only. Of course it's a wrong use of parameters but that didn't stop musicians from doing it...
It's worth mentioning that the "both nibbles used at the same time" thing is different in all formats, though, XM does it like MOD (IIRC), S3M does it the other way around, and IT simply ignores such faulty commands (the only sane implementation, IMHO).
Actually I haven't read modfill11.txt before (there are lots of other docs floating around) but it clearly says
But yeah, I kinda thought that you just add the vib table (*amplitude or better: twodimensional table lookup) to the period because everything else wouldn't make sense. :)
Quote:
[...]Vibrato means to "oscillate the sample pitch using a particular waveform
with amplitude yyyy notes[...]
But yeah, I kinda thought that you just add the vib table (*amplitude or better: twodimensional table lookup) to the period because everything else wouldn't make sense. :)
There seems to be an archive of Amiga ProTracker replay routines here
http://old.exotica.org.uk/source/replays/MOD-ProTracker/
http://old.exotica.org.uk/source/replays/MOD-ProTracker/
As an aside, how relevant are old tracker formats?
relevant?
Very relevant if you're coding a mod player.
Plain old mods are a good music format for demos, if you need something very light on the cpu. No floating point math or divisions needed, and with lookup tables you could even get rid of multiplications, if that's a problem. And music sync is easier to do than with, say, mp3. And if you already have a mod player and everything set up...
how about fmod?
Only if you want a bad player that also limits your frame rate to 43 Hz. (Hint: Having "mod" in the name doesn't imply that there's a good mod player below the surface).
Where are those 43hz coming from?
If I remember correctly minifmod ran at a granularity of 256 samples per block - which would be 172fps at 44.1khz.
If I remember correctly minifmod ran at a granularity of 256 samples per block - which would be 172fps at 44.1khz.
The full fmod runs at 4096 samples/block, thus the 43Hz.
uh 1024. sorry. :)