Converting Full Scale to Decibel Full Scale

Hello, all.

I’m writing a simple dynamic range compressor as an extension to Pure Data as an exercise (I’m sure that many such extensions already exist), and, although my original plan was to have it work linearly with full-scale measurements, a quick glance at Audacity’s compressor opened my eyes so far that I should be using decibel measurements for this purpose instead.

Since I’ve started writing signal processing extensions for PD, I’ve really had to brush up on my mathematics, refamiliarising myself with logarithms in particular, but, despite flicking through Wikipedia and other online sources, I’m still having some trouble understanding how to get a decibel value from a digital sample.

I see that Audacity measures decibels in “dBfs,” or “decibel full-scale,” where 0 dBfs represents the LOUDEST that a sample can be (the clipping point, or 1 and -1 in full scale), and the rest is represented by how many decibels QUIETER a sample is from that point, so that we only deal with negative decibel values.

Still, the exact equation used to get this dBfs value escapes me, and I’m not proficient enough with code-sifting to look up exactly how Audacity, for example, does it, so perhaps any one of you with the necessary experience could give me a hint? How do I take a sample’s value in full scale and convert it to a dBfs value?

Thanks in advance.

-David Hernandez

Quite correct, but with an exception. 32bit float numbers can be greater than +/- 1.0. This has been fully supported in Audacity since about version 1.3.9(?)
This means that when using 32bit(float) samples it is possible to exceed 0dB.
During internal (32 bit float) number crunching, numbers greater than +/- 1.0 are not truncated, but numbers greater than +/- 1.0 that are down-sampled a to a lower bit depth (for example in a sound card) will be truncated to +/- 1.0 (0dB).

Neither am I :wink: , but Audacity includes a version of the Nyquist programming language and I can see (in the file “nyquist.lsp”) how it is done in Nyquist.
(See here for more information about Nyquist in Audacity: http://audacityteam.org/help/nyquist )

db-to-linear (x) = ((log 10) / 20) * x [Update: this is incorrect - should be: dB = 20log(V1/V2)]


Some common (peak) values:
0dB = 1.0
-6 dB = 0.5
-12dB = 0.25
-18dB = 0.125
-24dB = 0.0625

Steve, the simplicity of your response is a godsend after I’d been stumped for two days trying to figure this out. The equation that you’ve found is actually very close to where I was at based on my repeatedly going through Wikipedia’s DeciBel and DeciBel Full-Scale articles; I was just having trouble finding the parallels between those two articles, and I was also getting lost when they delved into physics concepts like work, power, etc.

Thanks for your help, and now I can get back to my programming instead of dinking around with this graphing calculator. What I’d done was generate a sawtooth tone of 1 hz and then switched to the waveform (db) view to confirm that the sawtooth’s linear growth did appear as a logarithmic growth in that view. Then, I had this calculator open and was trying to interpret the equations for deciBel conversions that I had handy so that the graph that it gave me came out with the same values as the Audacity sawtooth, haha. A barbaric way to do things, I think. If I was still in highschool taking Physics and Calculus, I probably would’ve had it in no time.

Thanks again for your generous help, Steve. Have a good one.

-David

tldr; the given db-to-linear function is incorrect, as far as I can tell. In case anyone else has a similar need for equations in the future, I’ll post my findings here. The equations that work are:

Using the natural log, ln, log base e:
linear-to-db(x) = ln(x) / (ln(10) / 20)
db-to-linear(x) = e^(x * (ln(10) / 20))

Using the common log, log, log base 10:
linear-to-db(x) = log(x) * 20
db-to-linear(x) = 10^(x / 20)

EDIT: Don’t forget that, when converting linear full-scale to decibel full-scale, you’re using the absolute value. 0.5 and -0.5 would have the same dBfs value.
EDIT: Also, I just found out that a problem in my program was being caused by my trying to convert 0 to dBfs using the equations above. You can’t take any logarithm of 0, so you’ll have to come up with a solution for that. I think that I’m going to check for 0 and return an incredibly low value, like -1000 dBfs or something.

Original post:
Well, hang on. If “log” is short for “log base 10,” then the equation could be shortened to:

linear-to-db = log(x) * 20

I see, though, that, in this case, “log” must represent the natural logarithm, “log base e,” the same way that it does in C++, although my calculators represent this as “ln” and “log” is the common log (base 10). So, we’re using log(x) / log(10) to convert to the common logarithm, which is why, in environments where “log” is the common log, “log(x) * 20” works the same way.

Either way, it doesn’t seem like “db-to-linear(x) = (log(10) / 20) * x” checks out algebraically, and a few quick tests confirm that it doesn’t return the expected value.

(ln(10) / 20) * -6 = -0.690776
(log(10) / 20) * -6 = -0.3

Neither comes out to 0.5. Algebraically, if:

y = ln(x) / (ln(10) / 20)

then:

y * (ln(10) / 20) = ln(x)

Simplified further:

e^(y * (ln(10) / 20)) = x

A quick test proves this accurate:

e^(-6 * (ln(10) / 20)) = 0.5

Assuming the following is correct…

…then the simplest equations I can think of are…

db-to-linear (x) = 0.5^(x/-6)
linear-to-db (x) = -6*( log(x) / log(0.5) )

to convert to decibels, you can also use

linear-to-db (x) = -6*( ln(x) / ln(0.5) )

With the programs I write, I have to come up with all sorts of formulas. Unfortunately, I don’t know how to write programs as complicated as Audacity, so I came here.

The above are close approximations.

(sorry about the wrong formulae in my previous post, I don’t know what I was thinking :blush: )

The usual formula for calculating linear-to-dB is:
dB = 20log(V1/V2)

dB is an expression of a ratio (V1/V2) and in the case of dBFS the ratio is with reference to a Full Scale = +/- 1
So V2 = 1
Which gives:
dB = 20.log V
where “V” is the linear value and “log” is “common log” (base=10).

20 x log 0.5 = 20 x −0.301029996 = −6.020599913
20 x log 0.25 = 20 x −0.602059991 = −12.041199827
20 x log 0.125 = 20 x −0.903089987 = −18.06179974
20 x log 0.0625 = 20 x −1.204119983 = −24.082399653

We can compare this with the values produced by the Nyquist function (linear-to-db)
If you copy and paste the following code into the Nyquist Prompt box (select a track then, “Effect menu > Nyquist Prompt”)

(print (linear-to-db 0.5))
(print (linear-to-db 0.25))
(print (linear-to-db 0.125))
(print (linear-to-db 0.0625))

Then click the Debug button.
The final value will be output to the screen, then after clicking OK the Debug window will display the values:

-6.0206
-12.0412
-18.0618
-24.0824

For a more elegant output (prints the full output to the screen without needing to use the Debug output) copy the following code into the Nyquist Prompt box and click the “OK” button:

(setq a (linear-to-db 0.5))
(setq b (linear-to-db 0.25))
(setq c (linear-to-db 0.125))
(setq d (linear-to-db 0.0625))

(format nil "0.5 linear = ~a dB
0.25 linear = ~a dB
0.125 linear = ~a dB
0.0625 linear = ~a dB"
a b c d)

Calculating the other way:
linear-value = antilog (db-value/20)
V=10^(dB/20)

Which gives:
for dB = -6,
V = 10^-0.3 = 0.501187234

for dB = -12
V = 10^-0.6 = 0.251188643

for dB = -18
V = 10^-0.9 = 0.125892541

for dB = -24
V = 10^-1.2 = 0.063095734

and we can check this with the Nyquist function (db-to-linear)

(setq a (db-to-linear -6))
(setq b (db-to-linear -12))
(setq c (db-to-linear -18))
(setq d (db-to-linear -24))

(format nil "-6 dBFS = ~a 
-12 dBFS = ~a
-18 dBFS = ~a
-24 dBFS = ~a"
a b c d)

We get a lot of spam in many languages all over the forum on new and old threads… That post was probably just one of those bloody spammers… please ignore it (should soon be removed by one of the moderators)

Moderator Note: I removed the Russian Spam - and it almost certainly was spam (or a hook for later spam). If the Russian poster can read enough English to understand thios thread thenm he/she can certainly write in English too. I also deleted NicNack’s response to the russian thread as it no longer made sense with the spam post removed.

It did not seem to be spam. I think the Russian user just copied the formulas (math is a universal language), but didn’t understand what we said in English, or what the math involved actually did. Probably hasn’t learned about logarithms yet…

I suspect that you my be being overgenerous …

If you just saw the sheer volume of dross we have to clear away, day in day out all hours of the day, just to keep this forum clean and tidy then your Spammometer would probably be registering red too :wink:
And apologies to the Russky if he/she was bona fide and not a troll or spammer …

WC

I’ve always used 20 LOG v1/v2. It’s always been good enough to go on. And yes, it doesn’t ever hit complete silence. It does, however, achieve a point where the system noise overwhelms the show, generally in the -130dB range or maybe a little better – assuming you don’t run out of bits first.

Not to confuse that with dBSPL Sound Pressure Level. That goes both ways to infinity.

Koz