Code Monkey home page Code Monkey logo

ff_meters's Introduction

ff_meters

by Daniel Walz / Foleys Finest Audio Ltd. Published under the BSD License (3 clause)

The ff_meters provide an easy to use Component to display a level reading for an AudioBuffer. It is to be used in the audio framework JUCE (www.juce.com).

Find the API documentation here: https://ffaudio.github.io/ff_meters/

Usage

LevelMeter

To use it create a LevelMeterSource instance next to the AudioBuffer you want to display. To update the meter, call LevelMeterSource::measureBlock (buffer) in your processBlock or getNextAudioBuffer method.

On the Component use LevelMeter::setMeterSource to link to the LevelMeterSource instance. The number of channels will be updated automatically.

You can pull the drawing into your LookAndFeel by inheriting LevelMeter::LookAndFeelMethods and inlining the default implementation from LevelMeterLookAndFeel in ff_meters_LookAndFeelMethods.h into a public section of your class declaration. To setup the default colour scheme, call setupDefaultMeterColours() in your constructor.

Or you can use the LevelMeterLookAndFeel directly because it inherits from juce::LookAndFeel_V3 for your convenience. You can set it as default LookAndFeel, if you used the default, or set it only to the meters, if you don't want it to interfere.

All classes are in the namespace foleys to avoid collisions. You can either prefix each symbol, or import the namespace. N.B. for backward compatibility, FFAU is an alias for foleys.

// In your Editor
public:
    PluginEditor()
    {
        // adjust the colours to how you like them, e.g.
        lnf.setColour (foleys::LevelMeter::lmMeterGradientLowColour, juce::Colours::green);

        meter.setLookAndFeel (&lnf);
        meter.setMeterSource (&processor.getMeterSource());
        addAndMakeVisible (meter);
        // ...
    }
    ~PluginEditor()
    {
        meter.setLookAndFeel (nullptr);
    }

private:
    foleys::LevelMeterLookAndFeel lnf;
    foleys::LevelMeter meter { foleys::LevelMeter::Minimal }; // See foleys::LevelMeter::MeterFlags for options

// and in the processor:
public:
    foleys::LevelMeterSource& getMeterSource()
    {
        return meterSource;
    }

    void prepareToPlay (double sampleRate, int samplesPerBlockExpected) override
    {
        // this prepares the meterSource to measure all output blocks and average over 100ms to allow smooth movements
        meterSource.resize (getTotalNumOutputChannels(), sampleRate * 0.1 / samplesPerBlockExpected);
        // ...
    }
    void processBlock (AudioSampleBuffer& buffer, MidiBuffer&) override
    {
        meterSource.measureBlock (buffer);
        // ...
    }

private:
    foleys::LevelMeterSource meterSource;

OutlineBuffer

Another class is capable of reducing the samples going through into min and max blocks. This way you can see the outline of a signal running through. It can be used very similar:

// in your processor
private:
foleys::OutlineBuffer outline;

// in prepareToPlay
outline.setSize (getTotalNumInputChannels(), 1024);

// in processBlock
outline.pushBlock (buffer, buffer.getNumSamples());

// and in the editor's component:
const Rectangle<float> plotFrame (10.0f, 320.0f, 580f, 80f);
g.setColour (Colours::lightgreen);
g.fillRect (plotFrame);

Path plot;
processor.getChannelOutline (plot, plotFrame, 1000);
g.setColour (Colours::grey);
g.fillPath (plot);
g.setColour (Colours::black);
g.strokePath (plot, PathStrokeType (1.0f));

We hope it is of any use, let us know of any problems or improvements you may come up with...

Brighton, 2nd March 2017


ff_meters's People

Contributors

elandaofficial avatar ffaudio avatar jacobsologub avatar modosc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ff_meters's Issues

Does not compile on MSVC

The pragma does not compile on MSVC:

#if FF_AUDIO_ALLOW_ALLOCATIONS_IN_MEASURE_BLOCK
#warning The use of levels.resize() is not realtime safe. Please call resize from the message thread and set this config setting to 0 via Projucer.
            levels.resize (size_t (numChannels));
#endif

SingleChannel & Minimal

Hi,

Thanks for sharing your work!

It seems it is not possible to have both FFAU::LevelMeter::SingleChannel and FFAU::LevelMeter::Minimal flags enabled?

I like the interface, however it seems not trivial in the current implementation to enable both.
And actually I don't need the ticks as well :). I was just looking for some (very small) indication of sound coming in/out (for 10+ channels) and possibly the clipping indicator.

std::sqrt no member named sqrtf

The function std::sqrtf is not available by default in GCC, it requires you to add the -lm flag to the compiler which may damage portability.

Can be found in file ff_meters_LevelMeterSource.h:105 (LevelMeterSource::ChannelData::getAvgRMS())

Edit: Removing std seems to fix the problem

Can't get rid of these warning messages (with the latest version of ff_meters)

I get the following errors with the latest version of ff_meters. I have tried a few things, but can't get them to go away.

1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.26.28801\include\numeric(35,26): warning C4244: '=': conversion from 'double' to '_Ty', possible loss of data
1> with
1> [
1> _Ty=float
1> ] (compiling source file ....\Source\MonitorCls.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.26.28801\include\numeric(44): message : see reference to function template instantiation '_Ty std::accumulate<_InIt,_Ty,std::plus>(const _InIt,const _InIt,_Ty,_Fn)' being compiled
1> with
1> [
1> _Ty=float,
1> _InIt=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types>>,
1> _Fn=std::plus
1> ] (compiling source file ....\Source\MonitorCls.cpp)
1>D:\Dev\X-platform\Juce-Modules\ff_meters\LevelMeter\LevelMeterSource.h(102): message : see reference to function template instantiation '_Ty std::accumulate<std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types>>,float>(const _InIt,const _InIt,_Ty)' being compiled
1> with
1> [
1> _Ty=float,
1> _InIt=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types>>
1> ] (compiling source file ....\Source\MonitorCls.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.26.28801\include\numeric(35,26): warning C4244: '=': conversion from 'double' to '_Ty', possible loss of data
1> with
1> [
1> _Ty=float
1> ] (compiling source file ....\Source\MainOutputCls.cpp)
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.26.28801\include\numeric(44): message : see reference to function template instantiation '_Ty std::accumulate<_InIt,_Ty,std::plus>(const _InIt,const _InIt,_Ty,_Fn)' being compiled
1> with
1> [
1> _Ty=float,
1> _InIt=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types>>,
1> _Fn=std::plus
1> ] (compiling source file ....\Source\MainOutputCls.cpp)
1>D:\Dev\X-platform\Juce-Modules\ff_meters\LevelMeter\LevelMeterSource.h(102): message : see reference to function template instantiation '_Ty std::accumulate<std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types>>,float>(const _InIt,const _InIt,_Ty)' being compiled
1> with
1> [
1> _Ty=float,
1> _InIt=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types>>
1> ] (compiling source file ....\Source\MainOutputCls.cpp)

NOTE: There are also several places where "unreachable code" is defined, and those cause warnings as well, but I just commented out the code that caused it.

Unable to change color of the border around the meter (level) control...

I have been trying for 2 days, but I have not been able to change the color of the border (currently white) around the meter control (or each individual channel of the meter control). I have tried setting "foleys::LevelMeter::lmOutlineColour", but that has had no effect. How do I change the meter border color (from white)???

Also please note, the control does not really display until your sent audio data through it, it would be VERY helpful to have some sort of "test" function call within the meter class to display it (at a given meter level) so that I can see what the meter looks like while I'm trying to do the layout (and tweaking) of the UI.

In addition, it would also be great if there was some sort of #define that would set whether the meter control is derived from "LookAndFeel_V3" or "LookAndFeel_V4".

Race conditions in ChannelData

Hi again about multi threading

ChannelData also raises a bit suspicion. The rmsHistory should really be a vector of atomics, getAvgRMS (from UI thread) clashes with pushRMS (from AudioThread). You did it right with the rmsSum field.

Then there is also a race condition inside pushNextRMS because it might be called by the UI thread by decayIfNeeded. I would highly suggest removing that from LevelMeterSource and by that use a const reference to the LevelMeterSource in LevelMeter. You could do the time check inside the LevelMeter class and just "render zeros" no matter whats inside the LevelMeterSource.
If thats not possible, I would make rmsPtr atomic too and use "fetch_add" in pushNextRMS to read and increment the ptr in one atomic action. You'd calculate the module operation every time so the ptr just increases until the max value of size_t and then overflow to start over at zero (perfectly acceptable behaviour).

Unable to build ff_meters with latest version of Juce

I get errors on the following header files when I try to build ff_meters using the latest version of the Juce library:

#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_gui_basics/juce_gui_basics.h>
#include <juce_events/juce_events.h>

Exception on start in JUCE plugin host when previously saving the filtergraph with plugin open

The title might be a bit misleading because this only happens if one does not resize() the level meter sources in prepareToPlay(), however I thought it might be good to add this to the readme.

To reproduce, open a plugin with level meters in the juce plugin host, save the filter graph (ctrl+s) while the plugin is open, then restart the plugin host.

The exception is an out of range exception which occurs in LevelMeterSources.h in getMaxLevel():

float getMaxLevel (const int channel) const
{
    return levels.at (size_t (channel)).max;
}

The obvious fix is to call resize() on the level meter sources before processing audio. I didn't do that because I followed the tutorial and it wasn't done there.

Performance issue on Mac mini M1 but not on Windows10/11

Thank you for ff_meters! I am using it in a multichannel plugin. On Windows 10/11, performance is top notch.

But on the Mac OS Monterey 12.5 and Juce 6.16, I seem to be getting excessive CPU utilization.

On Windows10/11 with the plugin loaded in AudioPluginHost and with the UI showing with the meters, I am getting approximately 4% CPU utilization. On MacOS under the same scenario, I am getting 40% CPU utilization.

I tried JUCE_COREGRAPHICS_DRAW_ASYNC=1 and that saved a few percent CPU cycles.

If I comment out meterSource.resize (juce::jmax(2, getTotalNumInputChannels()), 0.01 * sampleRate / 512); in prepareToPlay and comment out meterSource.measureBlock (buffer); in procesBlock then the CPU drops to 18% with the UI open.
The meters appear to add ~20% CPU utilization on the Mac.

Maybe I am doing something wrong?

Atomic Use For "suspended"

I think the bool suspended in LevelMeterSource would make a great use of an atomic boolean. This way (and I think it is intended that way?) the UI would be able to suspend a meter source since it nows when it is not showing the level meter. The audio thread doesn't even have to call measureBlock if it wants to suspend the level meter.

Let me know what you think / if I should create a pull request.

No meter bar activity...

After some effort, I got this control/component to build as part of my application (though I still get warnings).

Everything looks good, and I did my best to follow the code example below, however... I do NOT get any activity on the meters.

Is there something that needs to be initialized, other than what is shown in the code example below?

Is there some example application that uses this that I can download/build?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.