Mixer Plugin processBlock trouble

Hi everyone,
Sorry for newbie questions or issues :wink:
I’m trying to code that plugin that plays fixed binary wav files on top of the track that been played according to the track signal.`

void FXAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
	
	
	juce::ScopedNoDenormals noDenormals;
	auto totalNumInputChannels = getTotalNumInputChannels();
	auto totalNumOutputChannels = getTotalNumOutputChannels();

	for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
		buffer.clear(i, 0, buffer.getNumSamples());
	
	
	
	if (getAverageRMSofAllChannels(buffer) > 0.01)
	{
			play();
	}
	else

	{
		stop();
	}
	

	mixer.getNextAudioBlock(juce::AudioSourceChannelInfo(buffer));

}

float FXAudioProcessor::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;
}

Now this is how i load and read the binary files into the constructor

auto reader = formatManager.createReaderFor(std::make_unique<juce::MemoryInputStream>(BinaryData::Test1_wav, BinaryData::Test1_wavSize, false));
	if (reader != nullptr)
	{
		newSource = new juce::AudioFormatReaderSource(reader, true);
		newSource->setLooping(true);
		transportSource.setSource(newSource.get());
		mixer.addInputSource(&transportSource, false);
	}

	auto reader2 = formatManager.createReaderFor(std::make_unique<juce::MemoryInputStream>(BinaryData::Test2_wav, BinaryData::Test2_wavSize, false));
	if (reader != nullptr)
	{
		newSource2 = new juce::AudioFormatReaderSource(reader2, true);
		newSource2->setLooping(true);
		transportSource2.setSource(newSource2.get());
		mixer.addInputSource(&transportSource2, false);
	}

My problem now is that when i launch the plugin in the daw, binary files play fine according to main track signal but the main track doesn’t playback anymore…
My guess is that i surely do something wrong in the processBlock, i ve been struggling for days trying to find out what i do wrong.
Would anybody stand something wrong there?
Thanks a lot!

The MixerAudioSource is probably written that way that it clears before mixing.

This can all simplified a lot, you don’t need the MixerAudioSource at all, just a AudioReaderSource:

void processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midi) override
{
    // do your other stuff

    if (shouldPlay) // bool flag to switch the readerSource on and off
    {
        juce::AudioSourceChannelInfo info (&mixBuffer, 0, buffer.getNumSamples());
        readerSource->getNextAudioBlock (info); // read from source

        for (int c= 0; c < std::min (mixBuffer.getNumChannels(), buffer.getNumChannels()); ++c)
            buffer.addFrom (0, c, mixBuffer.getReadPointer (c), buffer.getNumSamples());
    }
}

Hope that helps

just double-checked the sources: the MixerAudioSource calls getNextAudioBlock() on the first input, which usually overwrites the signal. Subsequent inputs will add then:

1 Like

Thanks a lot Daniel!
I’m trying that then :wink:

Sorry for asking, i guess that should be pretty obvious :wink:
what mixBuffer stands for? i’m a bit confused…thanks a lot

Ah sorry I forgot to mention. In order to read from the AudioSource without overwriting directly the buffer from the host you need a private AudioBuffer. It needs to be a member because you cannot allocate it in the processBlock().

// add as private member to your AudioProcessor:
juce::AudioBuffer<float> mixBuffer;

// in prepareToPlay:
void prepareToPlay (double sampleRate, int expectedSamplesPerBlock)
{
    mixBuffer.setSize (2, expectedSamplesPerBlock); // assuming stereo
    // ...
}
1 Like

You’re a Legend thanks a lot, i’m trying that then.

mmh there’s something i do wrong… it works for the main track but now the binaryfiles won’t play.
I got rid of the MixerAudioSource wich gives:

into the constructor

auto reader = formatManager.createReaderFor(std::make_unique<juce::MemoryInputStream>(BinaryData::Test1_wav, BinaryData::Test1_wavSize, false));
	if (reader != nullptr)
	{
		newSource = new juce::AudioFormatReaderSource(reader, true);
		newSource->setLooping(true);
		transportSource.setSource(newSource.get());
	
	}

	auto reader2 = formatManager.createReaderFor(std::make_unique<juce::MemoryInputStream>(BinaryData::Test2_wav, BinaryData::Test2_wavSize, false));
	if (reader != nullptr)
	{
		newSource2 = new juce::AudioFormatReaderSource(reader2, true);
		newSource2->setLooping(true);
		transportSource2.setSource(newSource2.get());
	
	}

into the destructor

    transportSource.setSource(nullptr);
	transportSource2.setSource(nullptr);

and tryed that

void FXAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
{
	mixBuffer.setSize(2, samplesPerBlock);
}


void FXAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
	
	
	juce::ScopedNoDenormals noDenormals;
	auto totalNumInputChannels = getTotalNumInputChannels();
	auto totalNumOutputChannels = getTotalNumOutputChannels();

	for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
		buffer.clear(i, 0, buffer.getNumSamples());
	
	if (getAverageRMSofAllChannels(buffer) > 0)
	{
	
		{
			shouldPlay = true;
			play();
		}
	}
	
    else

	{
		shouldPlay = false;
		stop();
	}

	if (shouldPlay==true)
{

	juce::AudioSourceChannelInfo info(&mixBuffer, 0, buffer.getNumSamples());
	
	newSource->getNextAudioBlock(info);
	newSource2->getNextAudioBlock(info);

	for (int c = 0; c < std::min(mixBuffer.getNumChannels(), buffer.getNumChannels());++c)
		buffer.addFrom(0, c, mixBuffer.getReadPointer(c), buffer.getNumSamples());

		}

}
newSource->getNextAudioBlock(info);

The getNextAudioBlock() just reads in to the mixBuffer. By calling twice directly one after another the audio from newSource is immediately overwritten.
You need to add the “addFrom” block each time after getNextAudioBlock(), then it should work.

1 Like

Thanks a lot Daniel :wink: you’ve made my week