Audio App bug fixing

Hey, new to JUCE! I’ve written an audio mixer (using the audio app component) that takes two inputs from my soundcard and mixes them together (depending on GUI controls) then outputs them to my two soundcard outputs. However, input 1 is behaving strangely: I can’t send from input 1 to output 2, only both together! Here’s my ‘getNextAudioBlock’ code, I’m wondering if it’s a problem with my buffers:

void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
{
	for (int outChannel = 0; outChannel < bufferToFill.buffer->getNumChannels(); outChannel++)
	{
		//--- BUFFERS ---
		const float *  inCh1Buffer = bufferToFill.buffer->getReadPointer(0, bufferToFill.startSample);		//Input 1
		const float *  inCh2Buffer = bufferToFill.buffer->getReadPointer(1, bufferToFill.startSample);		//Input 2
		float *  outChBuffer = bufferToFill.buffer->getWritePointer(outChannel, bufferToFill.startSample);	//This output


		//--- GUI CONTROLS ---
		//gain (convert from dB to linear):
		double inCh1Gain = pow(10, inCh1.sldGain.getValue() / 20);
		double inCh2Gain = pow(10, inCh2.sldGain.getValue() / 20);

		//master fader levels (convert from dB to linear):
		double inCh1Master = pow(10, inCh1.sldMaster.getValue() / 20);
		double inCh2Master = pow(10, inCh2.sldMaster.getValue() / 20);
		double outChMaster = pow(10, allOutChannels[outChannel]->sldMaster.getValue() / 20);

		//prefade toggle states:
		bool inCh1Prefade = inCh1.allPrefade[outChannel]->getToggleState();
		bool inCh2Prefade = inCh2.allPrefade[outChannel]->getToggleState();

		//set rotary levels according to pre or post fade:
			//Channel 1:
		float inCh1SendLevel;
		if (inCh1Prefade)	inCh1SendLevel = inCh1.allSliders[outChannel]->getValue();					//pre-fade
		else				inCh1SendLevel = inCh1.allSliders[outChannel]->getValue() * inCh1Master;	//post-fade
			
			//Channel 2:
		float inCh2SendLevel;
		if (inCh2Prefade)	inCh2SendLevel = inCh2.allSliders[outChannel]->getValue();					//pre-fade
		else				inCh2SendLevel = inCh2.allSliders[outChannel]->getValue() * inCh2Master;	//post-fade
		

		//mutes:
		bool inCh1NotMute = !inCh1.tglMute.getToggleState();
		bool inCh2NotMute = !inCh2.tglMute.getToggleState();
		bool outNotMute = !allOutChannels[outChannel]->tglMute.getToggleState();


		//--- PROCESSING ---
		for (int sample = 0; sample < bufferToFill.numSamples; sample++)
		{
			double inCh1Total = (inCh1Buffer[sample] * inCh1Gain * inCh1SendLevel * inCh1NotMute);
			double inCh2Total = (inCh2Buffer[sample] * inCh2Gain * inCh2SendLevel * inCh2NotMute);

			outChBuffer[sample] = (inCh1Total + inCh2Total) * outChMaster * outNotMute;
		}
	}
}

I haven’t read all code, but you are aware, that getReadPointer (0) and getWritePointer (0) return the same address, only one is const read only (for the compiler), and the other is non const, so you can read and write.

When you reach the second channel loop, the first original channel is already overwritten.

You may need a private buffer, but create that beforehand in prepareToPlay…

1 Like

Also see the Decibels:: class for some handy methods to convert db to gain.

1 Like

Furthermore as the gains are likely to not vary that often compared to the frequency of the audio callback getting called, you might want to consider to compute them only in case a slider is moved and store the result in an atomic which you read in each audio callback. This might be slightly more efficient as operations like e.g. pow or sqrt are a bit heavier to compute compared to simple operations like multiplications

Thanks for all suggestions, great advice :slight_smile: