Search code examples
logarithm

Discrete data to logarithmic scale


A function returns discrete data between 0 and 128. I want to transform that data to a scale in that way that a value of …

0 would result in 0 128 would result in 128

The values in between should be weighted in that way where lower number are transformed "faster" to higher numbers where higher number would grow more slowly.

Background: I want to do a VU meter on a dB scale (-inf to 0dB) like this (please note how the distances decrease for the same absolute change in dB)

L ||||||||||||||||||||                |
R |||||||||||||||||||||||||||         |
-inf         -36        -18   -6   -3 0
0                                    128

How do I transform the values to reflect the width of the peak on a VU of a width of 255 pixels, for example?


Solution

  • One straightforward mapping is to do something like this

    f(x) = b * (log(a + x) - log(a))
    

    It has the property of f(0)=0 and small numbers changes faster than large numbers. You can tune a to change how close it is to the logarithm curve (the smaller the closer). Once a is determined, b can be determined by solving equation f(128)=128, which leads to b=128/(log(128+a)-log(a)).

    The idea behind this is f(x)=log(x) goes to -Inf for x=0, so you want to offset a little bit, say f(x)=log(a+x), then do a linear transformation to make sure [0,128] maps to [0,128]: f(x) = k * log(a+x) + b and determine k and b by solving linear equation f(0)=0 and f(128)=128.