You have the rate there correctly in kHz since you're using ms and not s. Not an issue as long as you keep that consistent.

I think that equation requires the sampling period though, whereas 44.1kHz is the sampling rate.

I'd say that's a typo in the book claiming Ts to be the samplerate there. Justification - Samplerate was already defined as fs in equation 17.7 and in 17.9, Jot's equation, Ts is reused and explicitly named as the sample period.

If we take Ts as the sampling period - 1/44.1, that now gives a gain value of 0.9953 which is way too long.

So it then seems that D has been given in samples and not seconds. And so the equation reduces from

= (-3*D(smpls)*Ts)/T60(s)

= (-3*(D(s)*SR)*(1/SR))/T60(s)

= (-3*D(s))/T60(s)

D and T60 can be independent of SR in this equation as we account for that when calculating the delay time in samples from ms.

And this gives a gain value of 0.81283 which seems reasonable from my testing.

Best

]]>I have a question regarding the use of equation 17.8.

I am trying to generate a reverb effect (in MATLAB) with specified reverb times using comb filters and I am struggling to get correct reverb times out of the equation.

Is this correct use of the equation?

10^((-3*15*44.1)/500)

Where:

15 = delay time in msec

500 = RT60 in msec

This returns a gain coefficient of 0.0001073 which does not generate an RT60 of 500 msec.

I suspect I am plugging in the sample rate wrong but just plugging in 44100 returns 0. Or that is correct but there may be something wrong with my comb filter algorithm.

Thank you.

]]>I think your idea that negative R values are invalid, is correct. Probably make a lot of sense since a passive filter shouldn't actually be capable of shelf boosting in real life, as there is no active source of gain in the circuit.

I verified against the equations from the site you posted (thanks, hard to find info on those), using an arbitrary R1 instead of R2 and finding for that -

R2 = R1 / ( Gain - 1.0 )

which is actually equivalent to Wills formula and also produced the exact same results. As R1 (or R2 in the above eq.) approaches towards 0 the shelf level keeps dropping, and I guess trending towards behaving as a normal RC filter. So I don't think it'll be possible to boost with this circuit.

You can increase overall gain and then shelf cut with the opposite filter type to receive almost the same result.

Thanks for bringing this up

]]>Anyway, the problem was pretty much just getting no sound after implementing it, though I guess except for a sound similar to when you have a dirty pot in a pedal if I turned up the speakers very high.

However, I sat with it for a good while as the thing with returning negative resistor values was really bugging me, because if I was putting this together on a breadboard or something that's definitely not something I'd expect to see. So, I made the gain a scalar multiplier of R2 and it was working with frequency and gain knobs both working with kind of a tone knob feel. I was trying to figure it out when I was looking again at that page I found with the passive low and high shelf schematics I found (over here, for reference: http://linkwitzlab.com/filters.htm#5) and I see that it uses R2 with the capacitor instead of R1, and I feel like that makes more sense though the following high shelf on the page does use the R1.

In the end, the way I have it working now is by using that R2-based scale and flipping the sign while changing the dB range to be from -20dB to just before 0.0dB to prevent it from boosting.

Because, if it's the way it's written in the book, if you start with those component values from that Linkwitz schematic again and you boost the gain (by any amount, but let's say 3dB) you end up with the negative resistor value again (-3533.9 ohms) and then if you carry that along to calculate the capacitor value you have a negative capacitor value (-61.7 nF) which would also result in a negative frequency (-2502.066 Hz). But even worse, if you set it to unity gain, the R2(1 - 1) in the R1 equation means that you'd end up dividing by zero in the next step. That kind of makes me believe that the 1 / ( 2pi * fshelf * R1) might possibly be a typo for the low shelf, though it's still possible that I overthought myself way off base.

With that, I'm also not sure anymore that the shelving filters are supposed to have a boost past 0.0dB. Mostly for the above reasons with the negative resistor values, and I feel like (again, thinking about breadboarding) if there was a boost it'd function similarly to a bass boost, and I feel like you'd need more components than what's shown in the schematic.

But still, if so, if that is supposed to be a capability then I'm not sure how you use the equation [R2(1-gain) / gain] to do it.

]]>That said, what is the problem you are having specifically? Might need some further details.

Also I doubt if you'd want to be calling to initialize the adaptor chain from setParameters().

]]>As I mentioned quickly above, the way I actually have the calls in the function is flipped around, so what the block actually looks like in setParameters() is:

double r1Val = (r2_init * (1.0 - gain)) / gain;

double c1Val = 1.0 / (kTwoPi * fc_Hz * r1Val);

series_R1.setComponentValue(r1Val);

parallel_R2_C1.setComponentValue_RC(r2_init, c1Val);

series_R1.initializeAdaptorChain();

So, C1 gets updated with the R1 value calculated from the first part. r2_init remains constant of course, as the equation notes it as arbitrary. Unless that's not correct? ðŸ¤·â€â™‚ï¸ But yeah, this is where I was saying that I wasn't sure what was going on with the gain equation, because (and I'm sorry if this seems obvious as I go through the equation) if we let R2 be a resistor rated at 12.1k ohms and cut by -3dB then the gain equation flips that negative in the exponent of course. So, the gain ends up at approximately 1.4125. But if the equation for R1 is using that same gain variable in both the numerator and denominator then (12100 * (1 - 1.4125)) / 1.4125 gives you a resistor rated at approximately -1497.59 ohms, which doesn't seem quite right. And like I was saying, I can choose to not flip the sign of the dB, but of course that isn't a solution since if I boost instead of cut, I'm running into the same problem.Â

]]>That implementation sounds correct as you've described. I haven't built this to test. But having a guess, it seems like you're not updating R2_C1 alongside the R1 value changing.

Not an issue in the case of altering C1's cutoff point alone but it's value is also directly calculated from the value of R1. So when R1 changes, R2_C1 needs to be updated as well else the filter won't function as intended.

Cheers,

Jim

]]>I create the adapters in the in the createWDF() function. A series adapter with a R component, and a parallel adapter with a seriesRC component. Connect them together. Set the first adapter's source resistance to 0.0 and set the second for open terminal resistance since that's what's implied in the schematic and it worked fine for the LPF and HPF. So, I doubt that's the problem (?). Also, if I set initial values for the components, everything works fine, and I've even found a passive low shelf schematic online while trying to see what I'm missing in this, and the values from that worked too. The issue happens when I try to change those values in a setParameters() function.

So, transferring the equations from the exercise, changing the C1 value with the frequency seems to be working fine:

double c1Val = 1.0 / (kTwoPi * fc_Hz * r1Val);

parallel_R2_C1.setComponentValue_RC(r2_init, c1Val);

But the problem arises when I try to implement the gain equation that adjusts the R1 value. Again, transferring the equation from the book (in the function this is just before the c1Val calculation)

double r1Val = (r2_init * (1.0 - gain)) / gain;

series_R1.setComponentValue(r1Val);

As soon as I try that, it stops working.

The equation in the book for the gain used in the function is listed as 10^(-shelf_gain_dB/20) which looks to me to be your basic dB to gain conversion, but I do notice the negative sign in front of the shelf_gain_dB variable, which makes intuitive sense, because you'd want more resistance to decrease gain, and the R1 equation has (1 - gain) rather than (gain - 1), but when I work the calculations out by hand with the constants that work it seems to imply that the other way is closer to correct. So, I don't know if I'm drifting off to be even more wrong with that, but in trying to change the equation to account for that and other variations to further try to understand what was going wrong it still wasn't working out.

I also notice that in the book equation that the gain variable in not italicized in the (1 - gain), but is italicized in the denominator similar to the way it's italicized as the solution in the dB conversion, but that doesn't mean that they are different variables does it? I'm doubting that's the case but I thought I'd bring it up just to be sure, as I'm feeling very lost at the moment.

So, I'm not sure where to go from here, or how to better understand where I went wrong.

]]>Also I'd encourage you to keep experimenting with options for modulating the delay time with an envelope or lp filter.

Cheers,

Jim

]]>I have found a solution.

Like you said, you must have a linear ramp from 0 to 1 or 1 to 0 to prevent the discontinuities.

With the EnvelopeFollower object, when the value detected is above a threshold, you modulate the distance between the threshold and the detected value.

For that, you can do like you explain with :

x = fmin(fmax( x + c, 0.0),1.0);

Or normalize the value between a min and max with the function doUnipolarModulation.

I have test it by modulating the depth and the rate and it's working

Now, the way to do the duck delay is clear.

Thank you very much for the help

]]>Yep you'll probably want the delay fully off when the effect is not meant to be on.

so x is just a linear ramp from 0 to 1 or 1 to 0;

x = fmin(fmax( x + c, 0.0),1.0);Â where is c is + or - some small value i.e .001

you'd typically set the condition c of being positive or negative according to whether or not the threshold has been met.

The sqrt is then just a waveshaper which approximates that ramp to a sinus function although you could use trigonometry or various other functions.

You have the output equation right.

]]>When I said it was working, it's not exactly true.

I recorded some wave file with my guitar to test the plugin.

The audio level is very low so when I strum stronger, you can hear the effect.

However, when I use an audio file with higher level, the effect is always on.

It seems necessary to use a threshold.

In an article for a reverse delay, there is this function for smoothing the reverse signal :

double getGain(double coef) {return 4.0 * coef * (1.0 - coef);}

where coef is the i th element of the delayed signal divide by the delay time.

Â

If I understand what you say previously, you suggest to fade the signal with

output = sqrt(1-x) * inputdry + sqrt(x) * inputdelayed;

Where x is the ouput of a sinus function ?

Â

Best Regards, Johan.

]]>Â

Incidentally I'd like to reconsider my recommendation of an equal gain crossfading curve as opposed to an equal power one would probably suit better.

i.e something akin to sqrt(x) and sqrt(1-x) rather than x and 1-x - for values of x clamped between 0 and 1.

This can just be achieved by waveshaping the linear xfade with the sqrt or some equivalent type of function.Â sin(pi/2*x), cos(pi/2*x)

This avoids volume dips when the signals are uncorrelated though it will raise the volume slightly otherwise but is a less noticeable estimate in this context

Cheers

]]>I solve the problem

Instead of having a value of 0 or 1, I take the output of the envelope detector (which is between [0, 1] and smooth) and set it as the delay time.

]]>Sometimes Will is away from the forum for a whiles but I can probably help you here.

Since your delay time of 0 is equal to the dry. Then you can just set up a cross-fading mechanism to smoothly switch between dry and delayed signal.Â

You can do this in a couple of ways, there was a recent forum discussion on here about exponential smoothing but linear ramping is probably the best choice for this case.

I believe there is code for a linear ramp/smoothing function in Will's fxobects.h file though it's also not too hard to write one yourself.

Â

If output = (1.- x) * inputdry + (x) * inputdelayed;

then you need x to be a value of 1 above the threshold and 0 below it.

so simply smooth x first via your choice of filter.

To avoid audible clicks you will probably need the smoothing time to be at least 5ms. It's easiest to check for clicks in this context using a low frequency sine wave.

Â

Great idea by the way.Â

]]>