# Is Path slow? What is the best tool for spectrum analyser graph?

**URL:** <https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339>\
**Category:** General JUCE discussion\
**Created:** [April 20, 2018, 11:38pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339 "2018-04-20T23:38:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![pajczur](https://avatars.discourse-cdn.com/v4/letter/p/e9a140/32.png) [@pajczur](https://forum.juce.com/u/pajczur)\
**Post date:** [April 20, 2018, 11:38pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/1 "2018-04-20T23:38:39Z")

</div>

Hello,  
I’ve just made a spectrum analyser. And to draw the graph I used Juce Paint class, and Path.lineTo function. But for bigger resolution (more path points) it starts to be very slow and lag frienfly. Bigger resolution I mean something about for example 10000 points path.  
Of course I also suppose maybe my code isn’t optimal. But I think it’s the Path and Paint class. Why I think that? I am not sure but for simply sine wave it works great even for 20000 points of path. But for more complex signal, like saw wave - which is still not very complex of course - but my analyser starts lagging. Why?

---

<div class="post-metadata">

**Author:** ![pflugshaupt](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pflugshaupt/32/13206_2.png) [@pflugshaupt](https://forum.juce.com/u/pflugshaupt)\
**Post date:** [April 21, 2018, 2:56pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/2 "2018-04-21T14:56:18Z")

</div>

As juce uses a scanline renderer, rendering paths that intersects a lot with horizontal lines is slow(ish). Unfortunately a spectrum usually does that a lot while a sine wave doesn’t.

The usual thing to do with analyzers is to avoid creating a path with a lot more resolution than the screen. That means in the spectra case for high frequencies an average value of multiple fft bins is used and a path with maybe ~1000 points is used for rendering.

If you still want to render 20000 points you could try rendering into an image that is ninty degrees rotated and then rotate the image back. I never tried this (but maybe I should), but it should be a LOT faster for a spectrum which has precisely one y value per x value.

Personally I find it a bit annoying that juce uses horizontal scanline rendering as it’s mainly used for audio things and most audio graphs have a lot more horizontal line intersections than vertical ones. (spectrum/waveform/envelopes).

---

<div class="post-metadata">

**Author:** ![tytel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tytel/32/655_2.png) [@tytel](https://forum.juce.com/u/tytel)\
**Post date:** [April 21, 2018, 8:26pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/3 "2018-04-21T20:26:06Z")

</div>

I use OpenGL for any substantial real-time visual feedback.  
It’s not for the faint of heart, but the method I use is:

1. Pass points locations to GPU
2. Use geometry shader to generate lines with joints
3. Use the fragment shader to anti-alias those lines base on line thickness and distance from edge

I have dozens of lines taking up a lot of space and are drawing at 60 fps. The CPU usage remains pretty low. That said I’d rather not know how much time development time I’ve spent just on rendering lines 😅

---

<div class="post-metadata">

**Author:** ![ttg](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ttg/32/14456_2.png) [@ttg](https://forum.juce.com/u/ttg)\
**Post date:** [April 22, 2018, 6:35am UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/4 "2018-04-22T06:35:48Z")

</div>

Some SR products written directly with OpenGL. When it works, it’s much smoother.  
However, in terms of compatability OpenGL especially with bad drivers under Windows could generate crashes the moment context being created.

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 14, 2019, 2:53pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/5 "2019-01-14T14:53:41Z")

</div>

Can you share some code? I’m facing a similar problem - juce::Path’s performance simply doesn’t cut it for me.  
While I sorta know my way around OpenGL and shaders, I’m not really looking forward to implementing it all myself - any head-start would be appreciated 🙂

---

<div class="post-metadata">

**Author:** ![tytel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tytel/32/655_2.png) [@tytel](https://forum.juce.com/u/tytel)\
**Post date:** [January 14, 2019, 7:04pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/6 "2019-01-14T19:04:13Z")

</div>

There’s quite a lot. There are also changes you need to make to your overall graphics project for it to work (e.g. you can’t layer an OpenGL component on top of a component rendered with paint())

I’d take a look at how nanovg works as a starting point. I think some people on the forum here use it for line rendering: [https://github.com/memononen/nanovg](https://github.com/memononen/nanovg)

---

<div class="post-metadata">

**Author:** ![adamwilson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/adamwilson/32/1387_2.png) [@adamwilson](https://forum.juce.com/u/adamwilson)\
**Post date:** [January 14, 2019, 10:23pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/7 "2019-01-14T22:23:11Z")

</div>

Have you seen this? [https://github.com/JanosGit/OpenGLRealtimeVisualization4JUCE](https://github.com/JanosGit/OpenGLRealtimeVisualization4JUCE)

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 14, 2019, 11:20pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/8 "2019-01-14T23:20:03Z")

</div>

That looks promising, given I can get it to work on my Macbook (I saw your issue on Github).  
Perhaps I’ll create a simple, stripped-down open source library for OpenGL paths based on this!

---

<div class="post-metadata">

**Author:** ![jcomusic](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jcomusic/32/2014_2.png) [@jcomusic](https://forum.juce.com/u/jcomusic)\
**Post date:** [January 15, 2019, 12:19pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/9 "2019-01-15T12:19:49Z")

</div>

Imho OpenGL is the way to go. I’d recommend using as low a feature set of OpenGL as possible, I’m usually going for 2.0 (even though that can be a pain, the really nice shader features arrived later). If you then test on AMD, nVidia and Intel, and it turns out to work fine on HD3000, you’re most likely safe. The only issue I had so far was with a customer who somehow managed to not install gpu drivers at all on his windows machine - and he didn’t know until our support figured it out 😉

---

<div class="post-metadata">

**Author:** ![Achder](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/achder/32/5897_2.png) [@Achder](https://forum.juce.com/u/Achder)\
**Post date:** [January 15, 2019, 12:21pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/10 "2019-01-15T12:21:54Z")

</div>

What platforms does nanoVG support? Will it also work on mobile/openGL ES? I guess Mac, Windows, Linux are no problem?

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 15, 2019, 5:38pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/11 "2019-01-15T17:38:47Z")

</div>

> (e.g. you can’t layer an OpenGL component on top of a component rendered with paint())

How do you mean this? If I create a `juce::Component`, implement `juce::OpenGLRenderer` and attach it to an `OpenGLContext` and just render it, I seem to get some pretty good performance…

However, of course, my OpenGL component’s `paint` function is empty, which is fine, I can render everything with OpenGL.  
Is there a different way I should go about it?

---

<div class="post-metadata">

**Author:** ![CrushedPixel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/crushedpixel/32/8654_2.png) [@CrushedPixel](https://forum.juce.com/u/CrushedPixel)\
**Post date:** [January 23, 2019, 2:01am UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/12 "2019-01-23T02:01:34Z")

</div>

Following up on this, I actually went ahead and created a small, header-only library to render thick 2D paths using OpenGL!

Here’s my forum thread: [Drawing paths using OpenGL: Polyline2D](https://forum.juce.com/t/drawing-paths-using-opengl-polyline2d/31405)

Here’s what it looks like:

 ![11](https://us1.discourse-cdn.com/flex026/uploads/juce/original/2X/2/2da7f7d4d667cb328b2331b7f9b311a165826684.png)

Github: [Polyline2D](https://github.com/CrushedPixel/Polyline2D)  
Example JUCE App: [Polyline2DExample](https://github.com/CrushedPixel/Polyline2DExample)

---

<div class="post-metadata">

**Author:** ![gustav-scholda](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/gustav-scholda/32/4172_2.png) [@gustav-scholda](https://forum.juce.com/u/gustav-scholda)\
**Post date:** [January 30, 2019, 6:58pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/13 "2019-01-30T18:58:19Z")

</div>

I’m running a spectrum analyser using Path.lineTo without any issues here. I use it for development/debugging purposes so it’s not about performance. However it runs smoothly and I’m using FFTSizes up to 8192. I think there is something else taking cpu - did you run some profiling to check for the bottleneck?

---

<div class="post-metadata">

**Author:** ![MarcelK](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@MarcelK](https://forum.juce.com/u/MarcelK)\
**Post date:** [March 29, 2021, 10:03pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/14 "2021-03-29T22:03:23Z")

</div>

i’m running into a similar problem to the author. How did you manage to have 8192 and running smoothly?

I’m running a simplest plugin with the below inside Paint method and my CPU spikes up 70-80%.

```
path.clear();
 path.preallocateSpace(2048*3);
 path.startNewSubPath ( 0, 0);
 for (auto i = 0; i < 2048; ++i)
 {
     auto randY = random.nextInt (juce::Range<int> (0, getLocalBounds().getHeight()));
     path.lineTo ( i, randY);
 }
 g.strokePath(path, juce::PathStrokeType (.1));

```

What is your trick to make this run smoothly?

---

<div class="post-metadata">

**Author:** ![Fandusss](https://avatars.discourse-cdn.com/v4/letter/f/a4c791/32.png) [@Fandusss](https://forum.juce.com/u/Fandusss)\
**Post date:** [March 29, 2021, 10:50pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/15 "2021-03-29T22:50:21Z")

</div>

It’s just not gonna happen using juces paint method. You need to run your component as an OpenGLRenderer, then in the render() callback, do the whole vertex buffer thing to draw in opengl code. For a line you’d use draw line strip.

This has been a hot topic for a while now, I wonder if the JUCE team is any closer to making the default paint routines any more suitable for dynamic components?

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [March 29, 2021, 11:01pm UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/16 "2021-03-29T23:01:44Z")

</div>

OpenGL is massiely overkill for this IMO.

@MarcelK, do you really need 2048 points? Even if your window was 2048px wide that’d be 1 point per pixel which really isn’t necessary unless you _need_ that level of precision. I usually plot a point around every 5px for a spectrum analyser so for a window size of say 500 px that’s only 100 points which JUCE’s software renderer can handle easily.

---

<div class="post-metadata">

**Author:** ![MarcelK](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@MarcelK](https://forum.juce.com/u/MarcelK)\
**Post date:** [March 30, 2021, 8:01am UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/17 "2021-03-30T08:01:09Z")

</div>

I thought that this would be the case. But placing:

```
openGLContext.attachTo (*getTopLevelComponent());

```

is not making any difference.  
Is somewhere out there any code example to illustrate how to use render() callback?

---

<div class="post-metadata">

**Author:** ![MarcelK](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@MarcelK](https://forum.juce.com/u/MarcelK)\
**Post date:** [March 30, 2021, 8:03am UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/18 "2021-03-30T08:03:39Z")

</div>

Yes, I kind of need even 8192. I’m building a multichannel frequency spectrum plugin and so that users can choose from different sizes of FFT.

---

<div class="post-metadata">

**Author:** ![ImJimmi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/imjimmi/32/10843_2.png) [@ImJimmi](https://forum.juce.com/u/ImJimmi)\
**Post date:** [March 30, 2021, 8:35am UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/19 "2021-03-30T08:35:59Z")

</div>

You’re going to have multiple points per pixel though, that’s quite literally impossible to see… You should just find the min and max points within a given range and draw a line for each x-position which will bring your points count down a lot.

---

<div class="post-metadata">

**Author:** ![MarcelK](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@MarcelK](https://forum.juce.com/u/MarcelK)\
**Post date:** [March 30, 2021, 8:50am UTC](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339/20 "2021-03-30T08:50:30Z")

</div>

Right, so the idea is to still be able to choose whatever FFT size and then calculate the min and max?  
What’s the unspoken rule to calculate (smooth) the frequencies…is it from 2kHz upwards?

But, wouldn’t then let’s say 2048 and 4096 look the same after smoothing?

[Next page](https://forum.juce.com/t/is-path-slow-what-is-the-best-tool-for-spectrum-analyser-graph/27339.md?page=2)
