getNextAudioBlock & processBlock - bypasses process audio

I’m messing with an instance of AudioAppComponent - sort of following the audioPlayer tutorial example. However I wanted to introduce a processBlock

I got getNextAudioBlock creating an audioBuffer and passing it to the processBlock and then, after processing, I thought I needed to pass the buffer back to AudioTransportSource via AudioSourceChannelInfo.

It works, it just doesn’t play the processed audio but the unprocessed audio.

Can someone point out my misunderstanding please?

void getNextAudioBlock(const AudioSourceChannelInfo& bufferToFill) override
{


	if (readerSource.get() == nullptr)
	{
		bufferToFill.clearActiveBufferRegion();
		return;
	}

	/* coment out next line, is used at the end of the processBlock*/
	//transportSource.getNextAudioBlock(bufferToFill);

	AudioBuffer<float> procBuf(bufferToFill.buffer->getArrayOfWritePointers(),
		bufferToFill.buffer->getNumChannels(),
		bufferToFill.startSample,
		bufferToFill.numSamples);
	MidiBuffer midi;
	processBlock(procBuf, midi);
}

void processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages) {
	ScopedNoDenormals noDenormals;
	auto* device = deviceManager.getCurrentAudioDevice();
	auto totalNumInputChannels = device->getActiveInputChannels().getHighestBit() + 1;
	auto totalNumOutputChannels = device->getActiveOutputChannels().getHighestBit() + 1;

	for (int sampleIndex = 0; sampleIndex < buffer.getNumSamples(); ++sampleIndex) {
		for (int channel = 0; channel < totalNumInputChannels; ++channel) {
			
			/* does some processing here - code removed for brevity*/

		}
		
		/* does some more processing here  - code removed for brevity */

		for (int i = 0; i < totalNumOutputChannels; i++)
		{
			auto* channelData = buffer.getWritePointer(i);
			channelData[sampleIndex] = myProcessor.getProcessedSamlpe(sampleIndex, i);
			
		}
	}

    // my guess is my misunderstanding is here
	AudioSourceChannelInfo cinfo(buffer);
	transportSource.getNextAudioBlock(cinfo);
}

edit : need to rethink.

Yes, you guessed right. The processBlock() call replaces the samples, so since you are referring to the original buffer, you don’t need to do that in your processBlock.
Instead uncomment the line you had before in getNextAudioBlock()

The flow is:

  • getNextAudioBlock() -> pulls the audio from your transportSource()
  • the procBuf references the buffer
  • the processBuffer() call replaces the samples with the processed ones from your AudioProcessor

thanks @daniel

So I want to uncomment //transportSource.getNextAudioBlock(bufferToFill);

do I leave these line uncommented too?

// my guess is my misunderstanding is here
	AudioSourceChannelInfo cinfo(buffer);
	transportSource.getNextAudioBlock(cinfo);

No, the second ones are to be removed. Usually the processor wouldn’t know anything about the transportSource…
The processBlock() takes the samples in via the AudioBuffer<float> and replaces them.

Yes, thanks again @daniel That worked.

I’m still missing a bit of logic in the way the buffer works… so I get that I’m using the writepointer to the audioBuffer but is the this still linked back to the AudioSourceChannelInfo& bufferToFill ?

Exactly, that’s why the AudioSourceChannelInfo::buffer is a pointer, it exists somewhere else.

It’s like handing your jar to the barkeeper: “hey, fill that with audio”…

And to keep that analogy, the barkeeper might pass it on: “hey, stir that, before I hand it back”, that’s why the AudioBuffer<float>& is passed by reference to the AudioProcessor.

And it’s probably worth pointing out, that getReadPointer (0) and getWritePointer (0) return the same address. The only difference is, that getReadPointer() returns a const pointer, so you can only read, vs. getWritePointer() allows to write to that address.

1 Like

Thanks so much. It really helped.