Spectrogram SimpleFFT example


#1

Hi All,

I had a look at the SimpleFFTexample in the juce examples. That spectrogram example using quite a bit cpu cycles(Checked the cpu usage and profiled the application) for painting the spectrogram image. Could you guys let me is there any way to optimise the painting of the spectrogram??

 

Best Regards,

Ranjith


#2

Hi Guys,
The paint function for the image is using much cpu. Is there any other way to do it?? I have a lot of other plots and functionalities and I just don’t want this basic plot to take too much time

Best Regards,
Ranjith


#3

If the painting is taking long time, test to switch to the OpenGL render, if you have not done so already.

Are you testing the debug build or the release build? Release is often a lot faster.


#4

Thanks for your inputs. Ofcourse I am using the debug build till now. Even then, I feel the performance is not so good since later with many other added features, the situation will get worse for sure.

 

I too believe I should use the OpenGL render. I dont have much knowledge on the openGl and how to use it to draw an image. Could you please point out to some good documents for this??

 

 


#5

The question about how to use OpenGl came up recently. Check out this thread: http://www.juce.com/forum/topic/graphics-context-rendered-hardware-or-software

 


#6

Hi Alatar,

As you have mentioned in another thread, I changed the graphics renderer of "SimpleFFTExample" example application which was available with juce.  I am just getting a black window and the spectrogram is not displayed.

    class MainWindow    : public DocumentWindow
    {
    public:
        MainWindow()  : DocumentWindow (ProjectInfo::projectName,
                                        Colours::lightgrey,
                                        DocumentWindow::allButtons)
        {
//            openGLContext.attachTo(*this);
            setUsingNativeTitleBar (true);
            setContentOwned (new SpectrogramComponent(), true);
            setResizable (true, true);
            centreWithSize (getWidth(), getHeight());
            setVisible (true);
        }

        void closeButtonPressed() override
        {
            // This is called when the user tries to close this window. Here, we'll just
            // ask the app to quit when this happens, but you can change this to do
            // whatever you need.
            JUCEApplication::getInstance()->systemRequestedQuit();
        }

    private:
        OpenGLContext openGLContext;
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
    };

 

But when I remove the openGL codes(two lines), the spectrogram is displayed properly. Am I missing something here?? This seems very basic. But didnt work out.

 

Could you please help me on this??


#7

I also experimented with the SimpleFFT example and the OpenGL renderer some time ago. From what I understand, this won’t work as the painting is done in a software image while the OpenGL renderer needs an OpenGL image.

It doesn’t seem to be possible to use an image that has been modified with a Graphics(Image&) object with the OpenGL renderer but hopefully someone who has a deeper knowledge here could further elaborate.


#8

No, that's not true - the GL renderer will happily draw any type of image. Must be something else wrong here.


#9

I tried this some time ago but I also only saw the black image. Even simply creating an image and Graphics object to fill the image with another colour didn’t work:

Image image(Image::RGB, 100, 100, true);
Graphics g(image)
g.fillAll(Colours::red);
// paint image in paint() method

On the other hand, adding an image as a resource and painting worked. The image from a ressource was a OpenGLImageType while the other image was a SoftwareImageType from what I concluded that a SoftwareImageType couldn’t be used with the OpenGL renderer.


#10

It should work fine - e.g. all the images in the demo app are normal images, but you can happily swap between rendering engines without anything failing to draw. Not sure what's going wrong in this case, you'd need to debug a bit deeper.


#11

Probably not much of a difference, but in the paint routine the fillAll call is redundant, as the complete image is painted scaled to the full window size. You can simply remove the line. Now the background at the beginning is gray but is vanishing soon. You can avoid this gray background by initializing the image in the constructor with black color.

// in SpectrogramComponent constructor
spectrogramImage.clear (spectrogramImage.getBounds(), Colours::black);

// in paint remove
//g.fillAll (Colours::black);

The initialization of the image is only done once, but the fillAll in the paint is done at each repaint.

Remember Edsger Dijkstra: "Premature optimization is the root of all evil" ;-)


#12

When using the opengl renderer, the spectrogram is not displayed but while using the Juce graphics, it is displayed properly.

So, while using the opengl renderer, I just added one line(changing one pixel of the image) above the drawImage.


    void paint (Graphics& g) override
    {
        g.setOpacity (1.0f);
        spectrogramImage.setPixelAt(0, 0, Colour::fromHSV(1.0f, 1.0f, 1.0f, 1.0f));

        g.drawImageWithin (spectrogramImage, 0, 0, getWidth(), getHeight(), RectanglePlacement::stretchToFit);

    }
 

Now, Even with Opengl renderer, the spectrogram is displayed properly. So, maybe with opengl, Earlier, it thought the image is not changed and so it didnt redraw it again??? And now with this added line, it assumes the image is changed and redraws it now?? (I know my guess is non-sense. But how this single line makes the spectrogram visible??)

 

Can some one who are experienced comment on this??

 


#13

Thanks - try again now. It was just a subtle thing with the GL image caching that meant it didn't work when drawn with a non-GL thread.