# OPL4 sample rate calculations

Hi Guys,

Just started to look into how the OPL4 works and am a bit puzzled about how to deal with the sampling rates. If i look in the application manual i see for registers 20H-4FH there is a F-Number and an Octave to be filled in.

It also states that F-Number of '0' and octave of '1' means the replay rate is 44.1kHz. Finally a formula stating how to calculate: F(c) = 1200 x (Octave -1) + 1200 x log2 (1024+F_Number / 1024) (where c = Cent).

But how does this now work ? How can you calculate the settings (F_Number, Octave) to get a specific frequency ?
Anyone who can give an example on how to do this?

Hi Max-me,

The formula you mention shows how to calulate the value of a 'Cent' within one octave. An octave always consists out of 12*100 Cents (for 12 notes). As indicated, octave '1' and F-Number 0 means 44.1kHz. Every octave up or down means halve or double the frequency. So for example for 22.05 Khz his means octave '0' and F-Number 0. If you now divide the frequency range of an octave by 1024 (resolution of F-Number) you know how much the frequency increases per step.

For example:
Octave 0 has a range from 22.05 Khz to 44.1Khz,so in total 22.05 KHz. Divided by 1024 this gives ~21.5Hz per F-Number.
This means Octave '0' and F-Number '1' gives a frequency of ~22072 Hz, F-Number '2' gives a frequency of ~22093 and so on.

F(¢) is the frequency offset on a logarithmic scale. For the explanation it is easier to talk about frequencies directly, so we rewrite the formula to that of the playback frequency:

f = 44100 × 2^octave × (f_number / 1024 + 1)

You can separate this formula into the base frequency and a multiplier n:

f = 44100 × n
n = 2^octave × (f_number / 1024 + 1)

To play an octave higher, n = 2. To play one semitone higher, n = 1 + log2(1 + 1/12).

You may notice that octave and f_number of n are the floating point notation components where f_number is the significand (aka. mantissa or coefficient) and octave the exponent. The exponent is 3 bits + a sign bit and the significand is 10 bits with an implicit 11th bit that is always 1.

Floating point is like scientific notation, but with a base of 2 instead of 10. In scientific notation you can write the number 100 as 1×10^2, 0.01 as 1×10^-2 and 125 as 1.25×10^2. Similarly, in floating point you can write 4 as 1×2^2, 0.25 as 1×2^-2 and 5 as 1.25×2^2.

In that last example 1.25×2^2 = 5, the value 1.25 is the significand (corresponding to f_number) and the value 2 is the exponent (corresponding to octave), and they specify the number of 5 (corresponding to a frequency multiplier).

So how to decompose a number n into its exponent e and significand s?

e = floor(log2(n))
s = n / 2^e

To bring this to the octave / f_number representation in the OPL4, the octave is the exponent encoded directly as a 2’s complement signed number. Like floating point, f_number encodes the significand minus one, as (1.25 - 1) * 1024 = 256. The minus 1 saves one bit since it is always set.

octave = e
f_number = (s - 1) × 1024

Note that these calculations specify a multiplier on the playback frequency. There are two types of frequencies, the sampling frequency which is always 44100 Hz and the tone frequency which depends on the contents of the sample itself. Luckily everything is relative so if you calculate a multiplier for the tone frequency it is the same as the multiplier for the sampling frequency.

To play a specific pitch you need to calculate the multiplier n in terms of the desired tone frequency divided by the sample’s original tone frequency. It can be useful to do those calculations in terms of note deltas in cents, which matches the logarithmic scale we’re used to from our equal temperament keyboards.

p.s. The FM part works in a similar way, but the exponent is unsigned and it stores the significand including the leading 1.

Ah ok great, thanks for the answers! That makes it clear 