Would it be possible to create an Enum to Play binary files only when audio signal is going through?

Hi everybody,
I’m trying to figure out how i could play my loaded binary files when audio signal is going through and then make it stop when the signal stops.
I thought of creating an enum but i can’t figure out how to access to the main input signal volume…any clue?
Thanks!

Hey, it‘s a bit hard to follow what you are actually trying to do, while you mention some low level implementation details like a binary file or an enum you don’t explain the context, which makes it a bit hard to follow.

Are you building a standalone application or a plugin? Are you maybe trying to build something like those drum replacement plugins that play a sample in case a certain threshold has been reached?

And what is your main challenge? Figuring out an algorithm for proper level detection? Implementing this in C++? What have you tried, in which ways did it fail?

1 Like
void getAverageRMSofAllChannels (const juce::AudioBuffer<float>& buffer)
{
    const auto numSamples = buffer.getNumSamples();
    const auto numChannels = buffer.getNumChannels();

    auto avg = buffer.getRMSLevel (0, 0, numSamples);

    for (int chan = 1; chan < numChannels; chan++)
        avg += buffer.getRMSLevel (chan, 0, numSamples);

    avg /= (float) numChannels;

    return avg;
}

void processBlock (juce::AudioBuffer<float> buffer, juce::MidiBuffer&)
{
    if (getAverageRMSofAllChannels (buffer) > someArbitraryThresholdYouSet)
    {
        playAudio (buffer);
    }
}
1 Like

Hey! Thanks a lot for your feed back.
I’m building an audio plugin and trying to make play discrete wav binary data files on top of the track passing through it.

Let say that in my DAW the track is a piano track, i would like to play the data files while the piano is playing and make it stop when piano stops playing.

I didn’t try anything yet i’m a bit lost i have to admit ;).
I’ve tried my best to make it clear, forgive me haha i’m still novice.
Thanks a lot!

Thanks a lot ! I’m gonna check that and try it :wink:

Hi benvining, thanks a lot again for your help!
I’ve been struggling for a bit: if (getAverageRMSofAllChannels(buffer) > i’m trying to put values there under -1 and 1.
Like: (getAverageRMSofAllChannels(buffer) >0)
but getAverageRMSofAllChannels keeps been hilighted.
Would i miss something there ?

and for
void OVIAudioProcessor::getAverageRMSofAllChannels(const juce::AudioBuffer& buffer)
{
const auto numSamples = buffer.getNumSamples();
const auto numChannels = buffer.getNumChannels();

auto avg = buffer.getRMSLevel(0, 0, numSamples);

for (int chan = 1; chan < numChannels; chan++)
    avg += buffer.getRMSLevel(chan, 0, numSamples);

avg /= (float)numChannels;

return avg;

to the last line avg also keeps being hilighted.
any clue?

Thanks :wink:
}

oid OVIAudioProcessor::getAverageRMSofAllChannels(const juce::AudioBuffer& buffer)
{

{  const auto numSamples = buffer.getNumSamples();
    const auto numChannels = buffer.getNumChannels();

    auto avg = buffer.getRMSLevel(0, 0, numSamples);

    for (int chan = 1; chan < numChannels; chan++)
        avg += buffer.getRMSLevel(chan, 0, numSamples);

    avg /= (float)numChannels;

    return avg;
}

}

void OVIAudioProcessor::processBlock (juce::AudioBuffer buffer, juce::MidiBuffer&)
{
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
    buffer.clear(i, 0, buffer.getNumSamples());


for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
    auto* channelData = buffer.getWritePointer(channel);

 
}

if (getAverageRMSofAllChannels(buffer) > 0)
{
    playAudio(buffer);
}

} here is some line of code to make it a bit more clear

Do you mean when there is audible audio from the piano, or just when the transport is running, regardless of whether the piano is making noise at the moment or not? (And if you’re talking about detecting silence vs. audible audio, then what about gaps in the middle?)

If you just mean when the transport is running, then check out AudioPlayHead::isPlaying.

Hi thanks for feeding back !
I mean when there is audible audio from the piano, gaps between notes wouldn’t coz trouble.
That “ArbitraryThreshold setting” exposed by Benvining above would of been an awesome strategie to make it work.

“strategy”

surround your code with 3 backticks to automatically format it as code

```
like this
```

like this

oh ok thanks!

void getAverageRMSofAllChannels(const juce::AudioBuffer<float>& buffer);
void processBlock(juce::AudioBuffer<float> buffer, juce::MidiBuffer&);


const juce::String OVIAudioProcessor::getName() const
{
return JucePlugin_Name;
}

bool OVIAudioProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}

bool OVIAudioProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}

bool OVIAudioProcessor::isMidiEffect() const
{
#if JucePlugin_IsMidiEffect
return true;
#else
return false;
#endif
}

double OVIAudioProcessor::getTailLengthSeconds() const
{
return 0.0;
}

int OVIAudioProcessor::getNumPrograms()
{
return 1; // NB: some hosts don’t cope very well if you tell them there are 0 programs,
// so this should be at least 1, even if you’re not really implementing programs.
}

int OVIAudioProcessor::getCurrentProgram()
{
return 0;
}

void OVIAudioProcessor::setCurrentProgram (int index)
{
}

const juce::String OVIAudioProcessor::getProgramName (int index)
{
return {};
}

void OVIAudioProcessor::getAverageRMSofAllChannels(const juce::AudioBuffer& buffer)
{

const auto numSamples = buffer.getNumSamples();
const auto numChannels = buffer.getNumChannels();

auto avg = buffer.getRMSLevel(0, 0, numSamples);

for (int chan = 1; chan < numChannels; chan++)
    avg += buffer.getRMSLevel(chan, 0, numSamples);

avg /= (float)numChannels;

return avg;

}

void OVIAudioProcessor::processBlock (juce::AudioBuffer buffer, juce::MidiBuffer&)
{
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
    buffer.clear(i, 0, buffer.getNumSamples());


for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
    auto* channelData = buffer.getWritePointer(channel);

 
}

if (getAverageRMSofAllChannels(buffer) > 0)
{
    playAudio(buffer);
}

}

why are you posting all this code? The majority of what you just posted has nothing to do with the audio processing or detecting input level of a buffer.

All you really needed to post was this:

void OVIAudioProcessor::processBlock (juce::AudioBuffer buffer, juce::MidiBuffer&)
{
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
    buffer.clear(i, 0, buffer.getNumSamples());


// by the way, this is a useless for loop...
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
    //... because you assign this pointer and do nothing with it. This code does nothing.
    auto* channelData = buffer.getWritePointer(channel);
}

if (getAverageRMSofAllChannels(buffer) > 0)
{
    playAudio(buffer);
}
}

Now, the line
if (getAverageRMSofAllChannels(buffer) > 0)
I think will almost always return true, because it’s likely that if there’s audio flowing through your app at all, there will be some low level background noise, so the level will technically be above 0, even if it’s still very very quiet. That’s why I said to compare to some arbitrary threshold, which you’ll have to fine tune through testing - maybe something like 0.01, or 0.1…?

You used 3 periods, not back-ticks.

Press this button in the editor’s toolbar to insert a code block:
</>

Thanks a lot you re a legend

Haha my Bad thanks a lot that will help further :wink:

void OVIAudioProcessor::getAverageRMSofAllChannels(const juce::AudioBuffer& buffer)
{
    const auto numSamples = buffer.getNumSamples();
    const auto numChannels = buffer.getNumChannels();


    auto avg = buffer.getRMSLevel(0, 0, numSamples);

    for (int chan = 1; chan < numChannels; chan++)
        avg += buffer.getRMSLevel(chan, 0, numSamples);

    avg /= (float)numChannels;

    return avg;
}

Sorry to say that if you can’t see immediately what is wrong with that code (or decipher the error the compiler would give you on the last line) then you need to go back to the fundamentals of C++ programming. You will struggle to just copy/paste code without understanding the basics.

yeah you re right :wink: i’ve been doing that only for a month (learning c++ and else from scratch) and what i actualy needed to code wasn’t that hard but for this step i knew that would of been critical for me… i will defenetly have to take a huge step back yes

oh i had to declare float instead of void haha

1 Like

Hi benvining,
Sorry for that newbie question but should i declare

void getAverageRMSofAllChannels (const juce::AudioBuffer<float>& buffer)

right before the processBlock function or into the JucePlugin_PreferredChannelConfigurations section?

i’m a bit struggling here… thanks a lot!