How to create a good Histogram?

Hi there!
So, I’m trying to create a Histogram for a compressor, similar to how the FabFilter Pro C2 does it where it draws the audio being played on the bottom and the gain reduction on top.

I was checking out the AudioVisualizerComponent but I can’t get it to behave the way I need it to.

If anyone could point me in the right direction (maybe there are some resources on this topic that I missed? I searched the forum for quite some time and couldn’t find anything specific) on how to code a Histogram like this which accurately represents the level, be it from scratch or using some of JUCE’s built-in classes, I’d be more than grateful.

Thanks in advance!

1 Like

That’s not what a histogram is, so it’s not surprising your searches don’t turn up any results. A histogram divides the data into buckets and counts how often the values in each buckets occur.

i’d call it an oscilloscope, because it shows a waveform

I am afraid that JCUE doesn’t have such built-in functions. Here is a plugin written by me: ZLEComp. Some basic steps are:

  • attach the OpenGLContext
  • reshape the input-buffer into fixed-length segment (audio thread)
  • store RMS values of segments (audio thread)
  • collect RMS values (GUI timer thread)
  • shift the cached image, plot the new RMS values, then cache the image (GUI paint() thread)

However, compared to Pro-C2, my plugin takes up 2~3 times GPU resources :smiling_face_with_tear: I would also appreciate any suggestions here!

1 Like

I’ll just take our smart:comp2 as an example and draw some boxes over it to illustrate what we might be talking about:

The UI element in the pink box is a histogram, which shows the distribution of certain levels before and after applying compression which allows the user to understand how a compression curve morphs level distribution from the input to the output.

The UI element in the orange box is what we call a (rectified) waveform history for input and output, along with a gain reduction history on top.

As I get it, you are referring to a waveform, right?

As @zsliu98 already pointed out, there is no out of the box way to create something like that in juce. For best performance, we do all this in custom OpenGL shaders and this is what I would suggest if you are looking for the best performance possible, although it might seem a bit complex if you never worked with OpenGL. To get it working well, there are several challenges, from moving the data to plot from the audio thread to the GL thread to how to get the data into the shader to how to write a shader that creates a smooth waveform. This is just a basic overview to give you an idea of what might be involved and to be honest, some of my colleagues are way better than me with all these little details around GUI rendering stuff, so I won’t go into detail more :wink:

4 Likes

Thanks everyone for all the help! I really appreciate it. Clearly the way I was searching for it was wrong, so thanks for clearing that up.
As far as the whole OpenGL thing goes, It’s with 99% certainty out of my league for now but I will definitely have a look at your plugin @zsliu98 to get the basic idea of how to do it, since it does what I’m looking for, hopefully I manage to get something going there!

Anyway, thanks all for the input! much appreciated!

1 Like

Can’t be done to fabfilter standards without using proper OpenGL. I’ve tried everything, and I mean everything. Be warned having that OpenGL code present in your projects is super annoying and not at all fun to work with.

fabfilter’s histogram is laggy in bitwig though. how can that be explained if it’s all on the gpu?

It is gpu-rendered. The problem is driver incompatibility on some machines. I had the same problems with OpenGL on Windows machines in my apps (not JUCE based), sometimes it was needed to lower the acceleration level, sometimes changing other setttings etc. Look here:

1 Like

You can turn OpenGL off via a registry type thing, it will also only render at the current display frame rate. Maybe bigwig is somehow altering the frame rate? Probably something you could test with some 3rd party tool. If I cap my monitor fps to 60hz or less, everything looks a lot less impressive than when it’s running at 144hz.

It’s not clear to me what’s meant by “fabfilter standards”. The FabFilter Pro C2 histogram seems perfectly doable without OpenGL. Not so the other FabFilter plugins, those have more elaborate displays and would require OpenGL. But a simple histogram that looks great should be perfectly doable just using the normal JUCE tools, no? Or is this a Windows thing? (I have been developing just on macOS/iOS/Android).

I’m writing this so that the OP doesn’t feel discouraged. I remember reading the forum before I started using JUCE and being afraid that what I wanted to do would not be possible without OpenGL, but was then surprised by how much you can do without it.

2 Likes

Frame timing is hard, and then there’s the antialiasing on the paths. You can get maybe 70% of the way there in juce, but not all the way, no.

I see, I guess this can be a bit subjective.

Anyways, perhaps these simple projects could be of interest. Not exactly what the OP is after but it could help to look at the code:

Thanks a bunch, going to check these out as soon as I have some free time.
I did see some other implementations that did look pretty good. For example, the histograms that matcatmusic shows in his metering course.
Right now, I’m not really interested in making it look super nice but rather to first get it to do what I want it to, which is already a bit of a challenge for me, and to show the levels properly, then I can look into performance and aesthetics.

2 Likes

tbh i haven’t tried looking at pro-c2’s histogram since i built a new computer. just had it without histogram by default. but on my last computer it was laggy in bitwig, but at the same time smooth in cubase. that’s why i don’t understand how it’s a drivers thing. but i’m also not an expert on gpu rendering. just asking out of curiosity while we are at it anyway

Well, it’s not surprising. I had the case that within the same application I wrote, some screens were rendered with OpenGL correctly, while others were lagging on certain machines. There were minor differences how things were initialised/refreshed etc. With some implementations of OpenGL or GLES for Linux it was also always problematic. Personally, I am really sick when I have to do something in OpenGL, maybe I am just not experienced enough, frankly speaking :slight_smile: And when comes to Bitwig, maybe it is related to the fact their GUI is rendered fully in Java. Just a guess.

1 Like