Fill path partly - for audio output level monitor purpose


#1

Hello,
as you can see it’s two questions (asks for advice) in one thread. I work on audio compressor.

  1. What is the best (most efficient) way to implement audio level monitor? I made it as follows, but I don’t feel it’s the best solution:
    I created MonitorClass which is also (inherited from) Component and Timer. I make it visible and start timer in myAudioProcessorEditor. Timer period is set to myMonitorClass.startTimer(1000 / 30);. So it’s about 30 times per second.
    In MonitorClass I have also variable std::atomic<float> inputLevel[NUM_OF_CHANNELS]] which I use to set the height of the Rectangle<float>. I set it and repaint() in the timerCallback. Of course In paint (Graphics& g) I fill the Rectangle and it’s my monitor actually.
    And how I update inputLevel? I update it in myAudioProcessor exactly in processBlock as follows:
for(int i=0; i<buffer.getNumSamples(); ++i)
{
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        auto* channelData = buffer.getWritePointer (channel);

        float inputSample = inputGain * buffer.getSample(channel, i);
            
        if( fabs(inputSample) > myMonitorClass.inputLevel[channel] )
            myMonitorClass.inputLevel[channel] = (fabs(inpSamp));

        // ... BLA ... BLA ... BLA ...
    }
}

So it is updates only the highest level of sample. Of course in monitor timerCallback after I set height of the Rectangle I reset inputLevel[channel] = 0.0f;

Is it a proper manner to implement such things? It works, but maybe it could be done better?

  1. And my second question is about filling Path partly. Because I want to make my monitor on the compressor curve graph. Something like that is in Logic Pro built in compressor. There is the small circle that jumps on the compressor curve, like that:

But I want to fill the area under the curve, something like I demonstrate with red mark:

Do you understand what I mean? Please could you give me some advice how to achieve such thing?

For any help great thanks in advance.


#2

for filling the path, you gotta just define it manually with Path::lineTo(), and then g.fillPath()

for example:

auto rect = getLocalBounds();
Path p;
//triangle with lower left corner to white circle as hypotenuse
p.startNewSubPath( rect.getBottomLeft().toFloat() );
p.lineTo( controlXY.getPosition().toFloat() );
p.lineTo( Point<float>(controlXY.getX(), getHeight() ) );
p.closeSubPath();
g.fillPath(p);

#3

for filling the path, you gotta just define it manually with Path::lineTo(), and then g.fillPath()

Hey thanks for your help, but I know how to create, build and fill the Path but as I described in the subject, I don’t know how to fill it partly.


#4

So, make a closed path that is only what you want to fill…


#5

So, make a closed path that is only what you want to fill…

I thought about that, but that requires to build whole path for every inputLevel so it would be about 30 times per second for all points of path. I wonder if it’s efficient. Actually after I set Threshold, ratio and knee, my path is in some way constant, so it seems to be not wise to draw it create it everytime I want to fill it. In my case it’s 30 times per second.


#6

Why not used a value to draw only when necessary


#7

don’t optimize prematurely.

If you want to know if it’s efficient, PROFILE.


#8

Not sure if I understand it. That’s the point I want to draw it only when necessary. But it’s necessary 30 times per second.


#9

OK, thanks for your support. So I will try. In the mean time could you tell me also if my solution to implement level monitor is OK? Or is there any better solution?


#10

Maybe take a look at the Juce LevelMeter ? it can be a source of inspiration to implement your idea?


#11

OK I will try, thanks :slight_smile:


#12

at the very least, it will show correctly how to pass values from the audio thread to the gui thread.