FFT Amplitude

Does it work like the std::vector::reserve trick?

I’m happy to share my analyser code as well, that I did last weekend. I use lineTo brute force painting so far, my plan is to apply a gauss filter on the displayed data with increasing filter kernel.
My rationale about not bothering the overlap was, that I only display it for a split second, and the eye won’t keep up. But you are right, as soon as you do calculation with that, like keeping the max, you need to overlap. I think I can add that very easily, when I pull from the FIFO, simply tell it, that I consumed only half of the samples, so it should work. I’ll test that after work.

1 Like

Oo the other thing I meant to ask. When using path with OpenGL I noticed a performance increase over just building the lines myself. Does path shift a whole set of instructions in one go. I know from doing OpenGL programming that this is the best way as apposed to openGL 1 where you sent 1 instruction at a time.

And if so is there anyway I can govern this process?

1 Like

It was your code that got me started on all this madness. Yeah just reading from delay at either an offset or beginning seems a little easier to implement than other daniels take on though probably his maybe be faster…

That’s ingenious :slight_smile:

I am actually not sure if that’s the case. Especially, as I also write back to the audio buffer. Well, you can simply get rid of that part. I needed that code for a live onset detection and tempo estimation so I also did not use the writing back part.

When I deal with FFT data, I usually do a classic “power spectrum” by doing this for each bin:

amplitude = sqr(real^2 + imag^2)

And btw, may I throw in an idea? I know it’s what everyone does, but showing the amplitude on a logaritmic scale may not be the best approach, as you’ll need to set a lower limit, eventually cutting off anything happening at very low levels, or you’ll end up wasting too much screen space on very weak and insignificant signals.

Whenever I display volume levels these days, I go for a cube root instead. This way, anything from total silence to +10 dB or so can be shown in the same range, and at the same time you’ll still see the important area around 0 dB is being rather large. I find this approach far superior to a log scale. The same goes for volume sliders. Classic analog mixing consoles are pretty much:

amplitude = slider position^3

And it just feels right! I mean, you wouldn’t want a fader that can’t go lower than e.g. -50 dB, would you? :wink:

2 Likes

Cool, Well I set my scale in a function that’s called by everything so I’ll give it a pop.
I do different values for my log scale as I’m not a huge fan of the pure logarithm favouring detail around unity.

That’s exactly why I’m not a fan of it either. If you want to see an example of what I’m talking about, check out this audio meter I wrote 20 years ago, which uses a square root for the amplitude (not a cubic root in this case):

http://www.robotplanet.dk/knef/vumeter/

Just start up the .exe file and press “5” for real-time FFT view. It records sound from the default WaveIn device in windows. I think it’s much nicer to use than the ones that use a natural logarithm like Voxengo SPAN etc.

I beg to differ. The logarithmic scale is perceptually motivated, so it displays more or less what we perceive.

Having said that, it’s absolutely fine to distort the scale a little bit as e.g. I have done here:dBScaleDistorted
From 0dB and higher, the dB is scale is displayed in a linear way. Everything lower than 0dB is compressed towards lower values (the spacing get’s smaller). I used a tanh function to compress the values.
something like: y = std::tanh(dB / dynamic * -2.0f);

A plot to show the function:

Here, the y value will never go beneath -1 (you can scale it and add an offset for displaying it in JUCE).

I kind of like this as the area around 0dB has a good resolution, and you still have the Decibel values which correspond to the perception.

2 Likes

You say you disagree, and then you post an example of using something else than the natural logarithm. So basically we do agree on not just using the natural logarithm. You just found a slightly different curvature. That’s cool. And that’s why I made my suggestion in the first place.

This is verging on an ML activation curve :wink:

Whats the Inverse of that function? dB = f(y)

Here’s my actual code.
height is the height of the area I want to display the values (mB marginBottom, mT marginTop).

float dbToYFloat(const float dB)
    {
        float height = (float) getHeight() - mB - mT;
        if (height <= 0.0f) return 0.0f;
        float temp;
        if (dB < 0.0f)
            temp = zero + std::tanh(dB / dyn * -2.0f);
        else
            temp = zero - 2.0f * dB / dyn;

        return mT + scale * height * temp;
    }

    float yToDb (const float y)
    {
        float height = (float) getHeight() - mB - mT;

        float temp = (y - mT) / height / scale - zero;
        float dB;
        if (temp > 0.0f)
            dB =  std::atanh(temp) * dyn * -0.5f;
        else
            dB = - 0.5f * temp * dyn;
        return std::isnan(dB) ? s.dbMin : dB;
    }
1 Like

Okay let’s say I beg more or less to differ :wink:
Yes, I am also displaying in a non-logarithmic way, as I skew the logarithmic scale. What I wanted to emphasize on is that the underlying data and so the labels should be in Decibels, as it’s perceptually motivated.
Sorry for having written that a little bit to harsh!

I’d like to quickly jump in here to take @danielrudrich’s side…
At the end of the day you should be designing your products with the user’s needs in mind - not your own personal preference. 99% of people using an audio plugin/application are going to be familiar with Decibels and so using a Decibel scale is going to benefit them.

Personally I like to stick with linear Decibel scales in my own products but as a user I’d happily use anything using some sort of Decibel scale. If I opened up a plugin using some arbitrary or unspecified units for it’s amplitude I’d probably not be using that plugin for long!

Well actually I also prefer showing dB. That’s why my VUmeter.exe shows dB.

Using a straight up natural logarithm (the most software does it) has two downsides:

  1. You will always have to choose some sort of minimum level (often customizable because noone agrees what the correct value is.)
  2. The important area around -10 to +10 dB gets rather narrow.

Basically, I’m suggesting to do the same as the sliders on a hardware mixer such as the ones made by Mackie, SSL, Yamaha etc. It has nothing to do with “my personal preference”. And the x^3 formula is an attempt to approximate the faders on such mixers.

Seems like both of our approaches can have quite similar results.
x axis shows decibels, for your x^(1/3) approach, I converted them back to linear values with a scaling factor a, to match the tanh function. The tanh equation is plotted in gray.

1 Like

Oh cool! We’re obviously pretty much on the same track here. :smiley: