Audio plugin produces static over track


#1

Hi!

I had seen a post on this forum a while back asking this similar question, and I cannot find it through the forum search. If someone could link that thread for me I would be mighty obliged.

Here is my question regardless. I am still attempting to implement a simple low pass filter. I have gotten over the previous hurtles with null pointers. When I open a track in Audacity and apply my VST, all that occurs is the track plays with some static and pops in the background.

Here is my process audio block:

void FishTankAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
	const int totalNumInputChannels  = getTotalNumInputChannels();
	const int totalNumOutputChannels = getTotalNumOutputChannels();

	// If it ever becomes the point that there are more ouputs then inputs,
	// Then regenerate this file, and see what they did for that sitch :)

	// This is the place where you'd normally do the guts of your plugin's
	// audio processing...

	// Set up variables
	//AudioSampleBuffer mainInputOutput = busArrangement.getBusBuffer(buffer, true, 0);

	float sr = m_sampleRate;

	for (int chan = 0; chan < buffer.getNumChannels(); chan++)
	{
		for (int samp = 0; samp < buffer.getNumChannels(); samp++)
		{
			// Test values
			float testReadPointer = buffer.getReadPointer(chan)[samp];
			float testValue = calculate(buffer.getReadPointer(chan)[samp]);

			// Actual code.
			buffer.getWritePointer(chan)[samp] = calculate(buffer.getReadPointer(chan)[samp]);
		}
	}

}

And here is my calculate function, which does the low pass

float FishTankAudioProcessor::calculate(float input)
{
	float test = m_sampleRate;

	float aExp = (-2 * M_PI) / (m_lowPassSmoothingRate * 1000.0f * m_sampleRate);
	m_a = exp(aExp);
	m_b = 1.0f - m_a;
	m_c = (input * m_b) + (m_c * m_a);
	return m_c;

}

If there are any glaring issues, please point them out. I am still new to audio development and the JUCE framework in general.

Thanks for your time.


#2

This is a common mistake…
Your calculate is a stateful method. But you are using the same state for all channels.
You need a separate set of m_a, m_b and m_c for every channel (or better create a filter class you can instanciate for each channel)

Hope that helps…


Crackly, distorted output
#3

Ok, I will give that a try.

Will changing them to an AudioParameterFloat fix this state problem, or is this unrelated?


#4

You need separate filter states for each channel, so you should restructure your code so that you can freely instantiate as many independent filter objects as you need. (That is, implement your filter as a class that you then instantiate in your plugin audioprocessor object as many times as you have audio channels to process.)

There is another bug, you have :

You need buffer.getNumSamples() in that.


#5

Yes, I will do that then. And I will fix that bug.

Thank you for your help.


#6

That’s actually not what I meant. Rather like this:

struct Coeffs {
    float a;
    float b;
    float c;
}

And have a separate set for every channel:

Array<Coeffs> m_coeffs;
void prepareToPlay (double sampleRate, int maximumExpectedSamplesPerBlock) {
    m_coeffs.resize (numChannels);
    // [...]
}

and your calculate should use per channel:

float FishTankAudioProcessor::calculate (Coeffs& coeffs, float input)
{
    float test = m_sampleRate;
    float aExp = (-2 * M_PI) / (m_lowPassSmoothingRate * 1000.0f * m_sampleRate);
    coeffs.a = exp(aExp);
    coeffs.b = 1.0f - coeffs.a;
    coeffs.c = (input * coeffs.b) + (coeffs.c * coeffs.a);
    return c.m_c;
}

and in processBlock:

buffer.getWritePointer(chan)[samp] = calculate (m_coeffs.getReference (chan), buffer.getReadPointer(chan)[samp]);

Maybe that makes it clearer…


#7

No, I understood what you meant. I was going to make a vector of a new class, as opposed to an Array of a struct. But I think I will just use an Array instead. I appreciate the clarification though! I’m new to JUCE, not C++.


#8

Or is it a better practice to use your Array, as opposed to the std::vector?


#9

Sorry, got your answer wrong then :wink: No problem

Array or std::vector is no (noticable) difference for that purpose (afaik)… everybody has his own preference there…

And the AudioProcessorParameterFloat is only needed to expose a parameter for control from the host.

Good luck


#10

Hi I have one more question. You say to resize the Array to numChannels. I can’t seem how to retrieve this value from the documentation. Am I able to access the AudioSourceChannelInfo struct?


#11

You are in a processor’s context, right?
For instance you can check the num of outbut channels using int AudioProcessor::getMainBusNumOutputChannels()…
If you are in an audioSource, you can use the AudioSourceChannelInfo struct, but only in the getNextAudioBlock(), where you shouldn’t make allocations…
For some reasons a pure AudioSource has no channel numbers property, I don’t know why…


#12

Ahh, I was poking around in the wrong preparetoplay method in the documentation.