How do I sum stereo to mono?

Hi,

I’m new to JUCE and working my way through the tutorials. I like it so far.

One thing I want to do as an exercise is create a plugin that sums stereo to mono.

But I can’t figure out where to start. I have created an Audio Plugin project, and I have looked at the ProcessingAudioInputTutorial sample code. But I’m stuck.

Googling “JUCE sum stereo to mono” brings back a lot of discussions regarding going from mono to stereo, unfortunately.

What is the right first step for a stereo to mono summing plugin?

Thanks,
Fred

Well it depends on the IO of your plugin.

The simple solution is that you loop through the samples, take the left & right sample, add them to together, and then replace channel 0 with the summed left and right sample.

If you’re plugin is running in stereo mode, then this would effectively come out of the left channel.

I suppose what you could do is take the left & right channel, sum them, and then replace the left & right with the summed results.

sudo code:

for (int sample = 0; sample < audioBuffer.getNumSamples(); sample++) {
    float sampleLeft = audioBuffer.getSample(0, sample);
    float sampleRight = audioBuffer.getSample(1, sample);
    float monoSummed = sampleLeft + sampleRight;
    audioBuffer.setSample(0, sample, monoSummed);
    audioBuffer.setSample(1, sample, monoSummed);
}

You could also just do it on the whole buffer. Simpler, and probably more efficient:

     // add the right (1) to the left (0)
    buffer.addFrom(0, 0, buffer, 1, 0, buffer.getNumSamples());
    // copy the combined left (0) to the right (1)
    buffer.copyFrom(1, 0, buffer, 0, 0, buffer.getNumSamples());
1 Like

^^ yes definitely better

@Jake_Penn, @stephenk,

Thank you both very much for your help. I have something that compiles and passes a number of AU Validation tests, but segfaults at the end of the AU validation.

I deleted the second for loop from the template code because I am supposed to act on both channels at once, right?

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

    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // This is here to avoid people getting screaming feedback
    // when they first compile a plugin, but obviously you don't need to keep
    // this code if your algorithm always overwrites all the output channels.
    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    // This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    // Make sure to reset the state if your inner loop is processing
    // the samples and the outer loop is handling the channels.
    // Alternatively, you can process the samples with the channels
    // interleaved by keeping the same state.

    // i deleted the for loop template code that was here
    
        
	// add the right (1) to the left (0)
	// store the sum in the left
	buffer.addFrom(0, 0, buffer, 1, 0, buffer.getNumSamples());

	// copy the combined left (0) to the right (1)
	buffer.copyFrom(1, 0, buffer, 0, 0, buffer.getNumSamples());
}

When I try to auval this, at the end I get:

Render Test at 64 frames, sample rate: 22050 Hz
Render Test at 137 frames, sample rate: 96000 Hz
Render Test at 4096 frames, sample rate: 48000 Hz
Render Test at 4096 frames, sample rate: 192000 Hz
Render Test at 4096 frames, sample rate: 11025 Hz
Render Test at 512 frames, sample rate: 44100 Hz
  PASS

1 Channel Test:
Render Test at 512 frames
JUCE Assertion failure in juce_AudioSampleBuffer.h:710

validation result: crashed validation

I can’t figure out what I’m doing wrong?

Thanks,
Fred

Au validator doesn’t like you to assume stereo, so you’ll need to check if there are two outputs before populating that second channel, or specify stereo only — atleast I assume

OK, thanks for that suggestion. I did this and got the validation to pass:

   if (totalNumInputChannels == 2) {
        // add the right (1) to the left (0)
        // store the sum in the left
        buffer.addFrom(0, 0, buffer, 1, 0, buffer.getNumSamples());

        // copy the combined left (0) to the right (1)
        buffer.copyFrom(1, 0, buffer, 0, 0, buffer.getNumSamples());
    }

Basically, if the input is stereo, sum to mono. If it is not stereo, leave it alone.

Is that the most elegant way of doing it? Or would you call this a hack?

It seems to work but I need more testing. The final summed mono output is louder, but I expected that. So I need to figure out how to compensate for that.

Try this:

        // add the right (1) to the left (0)
        // store the sum in the left
        buffer.addFrom(0, 0, buffer, 1, 0, buffer.getNumSamples());

        // copy the combined left (0) to the right (1)
        buffer.copyFrom(1, 0, buffer, 0, 0, buffer.getNumSamples());

        // apply 0.5 gain to both
        buffer.applyGain(0.5f);
1 Like