Biquad Filters: How to do LP ↔︎ Bypass ↔︎ HP


#1

Hi all,

I'm trying to code a filter that does a true bypass in the "middle" position of a frequency knob, and does biquad LP or HP when leaving that position with increasing resonance. It seems to me that there is no setting for biquad_hp_coefs and biquad_lp_coefs that sound like no filter is active, is there? I always get some bass boost out the HP and some dip in the high frequencies with the LP, even in the lowest/highest frequency setting and with 0 resonance. If there was a neutral setting, I could just put the filters in series.

That's why I've decided to bypass the filters when they're not supposed to be active, but that gives me other problems.

Here's my Local Data:

biquad_state bs_lp;
biquad_state bs_hp;
biquad_coefficients bc;

And here's my K-rate code:

int32_t freq;
int32_t true_pitch;

int32_t dummy[BUFSIZE];

if (param_pitch > 0) {
	// High Pass, resonance increases with increasing filter frequency
	true_pitch = param_pitch*2 - (1<<27);
	MTOF(true_pitch,freq);
	biquad_hp_coefs(&bc,freq,INT_MAX - (param_pitch<<3));
	biquad_dsp(&bs_hp,&bc,inlet_in,outlet_out);

	MTOF(1<<27,freq);
	biquad_lp_coefs(&bc,freq,INT_MAX);
	biquad_dsp(&bs_lp,&bc,inlet_in,dummy);
} else if (param_pitch < 0) {
	// Low Pass, Resonance increases with decreasing filter frequency
	MTOF(-1<<27,freq);
	biquad_hp_coefs(&bc,freq,INT_MAX);
	biquad_dsp(&bs_hp,&bc,inlet_in,dummy);

	true_pitch = param_pitch*2 + (1<<27);
	MTOF(true_pitch + inlet_pitch,freq);
	biquad_lp_coefs(&bc,freq,INT_MAX - (-param_pitch<<3));
	biquad_dsp(&bs_lp,&bc,inlet_in,outlet_out);
} else {
	// param_pitch == 0 --> Bypass
	for (int i=0; i<BUFSIZE; i++) outlet_out[i] = inlet_in[i];

	MTOF(1<<27,freq);
	biquad_lp_coefs(&bc,freq,INT_MAX);
	biquad_dsp(&bs_lp,&bc,inlet_in,dummy);

	MTOF(-1<<27,freq);
	biquad_hp_coefs(&bc,freq,INT_MAX);
	biquad_dsp(&bs_hp,&bc,inlet_in,dummy);
}

I noticed that when the LP and HP share their state, there's an audible noise when sweeping from LP to HP. That's why I created separated states and update all of them in the most neutral frequency and resonance setting possible when they're not active, now the noise is almost gone. Do you think this is over the top somewhere?

Although the nasty noise is gone, there is still an audible click when going from bypass to highpass. How do I get rid of that?

What can I do? Thanks for any help!
Boris


#2

Here's a patch that demonstrates the code: Filter.axp (2.7 KB)

You can hear the click when you switch the pitch between 0.00 and 1.00, even without audio input:


#3

Hey there, I've been working on similiar topics.

I think the sonic colouring of the filters comes from the fact that they don't go the complete 20-20k range.

So with a lp for example it will stop at 16k and add a bit of colouring at that frequency. This is the first point were you could work on. Make the filters full range (at least the lp) and you will have it more neutral.

Then your switching mechanism: I'm not so good with code but I built a mechanism that switches on/off the filter when you move the pot with mux object. That gave me clicks. The solution is to use a crossfader and smooth after the on/off logic.

I think this might be a quite logical explnatation to what is going on. Imagine you make a recording in a daw of some white noise with and without filter and then you put the samples next to each other. You will have to make crossfade to make a seemless transition.

Filter.axp (2.7 KB)


#4

Hi! It's probably similar to Blindsmyth's solution (which I'm too stupid to understand right now), but here's what I did, crossfading to the dry signal in middle position:

Hope this is helpful.


Nice one knob filter...clicking issue
#5

Hi bolau…. I’ve investigated about your interesting filter, a sort of tilt eq with some quirks, the problem is related to the dial. I’ve slightly modified your code so the pitch control is external. In such a way it seems that the overall behaviour is better. Try the patch and compare the two objects. I also removed a part of the code that seems not necessary. In my opinion you could remove the “bypass” block also and assign the 0 value to the highpass block. FILTER_EXP.axp (7.2 KB)


#6

Hi folks,
thank you VERY much for your replies! I've experimented with your solutions. I found that I need to smoothen the pitch parameter in order to avoid rumble when wiggling quickly on the pitch parameter as @patatos suggested, best tested with a running audio signal. But still, I would get the clicks when switching the HP on. Crossfading could help, but I've followed @Blindsmyth's suggestion instead and made the HP filter's lowest frequency much lower (1 Hz instead of 8-9 Hz). That way, it's bump at the lowest setting is around 20 Hz instead of 50, which I think is not audible. And thus, I don't mind keeping the HP always on, which gets rid of the clicks. And the patch is nice and simple, which I like.
In addition, I tweaked the Resonance and the Pitch sensitivity curve to get a result that seems to be most "musical" and useful for me. In case you're interested, here's the code:
Filter.axp (3.1 KB)

I have to admit that I'm not very experienced writing DSP code, so I'm using float operations which might be a bit slower than fixed point arithmetic. But at least I'm not using the evil pow function, so it's not that bad.

Thanks again and all the best,
Boris