Wrong pitch in S3M effects for some samples

Started by carra, February 04, 2018, 19:38:47

Previous topic - Next topic

carra

Hello, I have been writing an S3M player for fun and maybe to use it in a game.

I have noticed that in OpenMPT, while note pitches are always correct, their pitch alterations such as slides and vibratos do not conform to the S3M specifications for some samples. Apparently it has to do with the base frequency of the sample, or C4Speed in S3M terms.

I have attached a sample S3M file to demonstrate this error. It has only 2 samples, which are played from the same note with the same slide sequence, and the results vary quite a bit. This slide has been chosen so that the period starts in 1712 (for note C-4 in S3M, or C-5 in OpenMPT) and ends in period 2712 (i.e. note E-3 in S3M or E-4 in OpenMPT). This happens because the period is increased 10 times by (Speed - 1 = 5) * (depth = 5) * 4. So, period increments in 10*5*5*4 = 1000.

This expected pitch change is precisely what happens for sample number 1 (which is an old S3M sound sampled at 8363 Hz). However for the second sound sampled at a modern 44100 Hz the effect applied by OpenMPT is much more aggressive than it should.

I have tested this with code, and for some reason OpenMPT seems to be applying this effect with a depth factor of (44100/8363) = 5.27 times stronger than it should. I have seen the same happening with vibratos, and I guess the same will happen with tone portamentos, etc.

I may be wrong at some place, but if I am not, then we should consider this as a bug.

Saga Musix

#1
I cannot observe anything obviously wrong here. That is, Scream Tracker 3's output sounds just like OpenMPT's. Note that for direct comparison you need to convert the second sample to 8-bit as ST3 does not handle 16-bit samples.
I think your mistake is that you assumed that a note played at 44100 Hz behaves the same as a note played at 8363 Hz, but that it not the case. Portamentos are much deeper with high-pitched notes, because they have a smaller period (e.g. 44100 Hz = period 324). This is why the second note slides much faster and deeper.
Always compare OpenMPT's output against the original tracker, not against what you might read in (or interpret into) documentation - it's often inaccurate.

Note that your assumption would hold in the MDL format (which also uses the same period concept for sliding, but the depth of pitch slides does not depend on the middle-C sample rate), and of course any formats with linear frequency slides do not have this problem as well, as slides are defined via semitones, not periods.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

carra

I see, so ST3 does the same? As you say, documentation may be wrong. Still, something is very weird here.

Why would the same tracker treat periods in 2 different ways, depending if they are taken as a row note or an effect? If, as you say, a 44100 Hz sample is seen by the tracker as having a period of 324, to output a C-5 note it would have to lower it several octaves until it reaches the standard 1712. And this is not the case.

But still, as you say, if the original does it like this then so be it. I will just introduce that same bug in my code  ;)

Saga Musix

ST3 does not treat things in two different ways, I think you just misunderstand what it actually does.

QuoteIf, as you say, a 44100 Hz sample is seen by the tracker as having a period of 324, to output a C-5 note it would have to lower it several octaves until it reaches the standard 1712
That is not what's happening, the middle-C is by no means enforced to have a period value of 1712! I just checked ST3's TECH.DOC, and it explains exactly that in the "How to calculate the note frequencies like ST3?" section. Your assumption only holdes iff the middle-C frequency is actually 8363 Hz, and for any other frequency the middle-C period is different!

One way to compute the period of a note is (code taken from OpenMPT):

const uint16 FreqS3MTable[12] = { 1712,1616,1524,1440,1356,1280,208,1140,1076,1016,960,907 };

period = 8363 * (FreqS3MTable[note % 12] << 5) / (middleCspeed << (note / 12)); // middleCspeed is 8363 or 44100 in your example file


And to convert back to frequency in Hz:

freq = 8363 * 1712 / period;


The behaviour you described in your initial post would happen if middleCspeed (or middle_c_finetunevalue in TECH.DOC) was left out of the computation.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

carra

Oh it seems I was understanding things differently then. My bad.

Intuitively, it does seem weird that the same sound will behave differently in a song just because it was recorded at a different sampling frequency. But of course I will not argue with something original from Scream Tracker 3.

And thank you for the quick response, Saga  :D

Saga Musix

You're welcome.
Quote from: carra on February 04, 2018, 20:35:04Intuitively, it does seem weird that the same sound will behave differently in a song just because it was recorded at a different sampling frequency.
Yes, that's why trackers soon switched to linear frequency slides (the name is misleading: they are linear in semitones, but exponential in frequency) soon after ST3. Linear frequency slides are computationally more expensive, and back then it still mattered.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.