BBD Chorus - Modulate Clock Signal

Started by MarshallPlexi, October 02, 2021, 02:40:45 PM

Previous topic - Next topic

MarshallPlexi

Hey Guys!

I have a chorus that I'm working on and have the clock speed controlled via a uC. I also have the LFO controlled with the same uC. When I feed a fixed speed clock to the CD4047 (used to make a bi-phase output) the pedal works perfectly. When I do internal math on the uC to apply the LFO to the clock signal it works, but occasionally there is a drop out of around 4ms in the clock frequency as the depth of the LFO is increased. I'm not sure why this is. I'll go back through my code and see if I can make it as efficient as possible.

This makes me think about how I can merge these two signal AFTER the uC. I can generate a clean clock signal and I can generate a clean LFO signal. Now I just need to get them to work well together.

Is there a chip I can use that will allow me merge these signals? I've seen the how the small clone uses the CD4047 and sets the clock freq with the RC combination then applies the LFO to that. If I could find a chip that would allow me to send a square clock wave into it and then modify that value with an LFO I think I'd be in business.

Any ideas about what I can try?

Thanks so much for your time and consideration!

ElectricDruid

I think you've largely answered your own question!

You won't find a chip that lets you send it a clock signal and and LFO signal and then produces a modulated clock signal, but you don't need to. As you'Ve mentioned, the Small Clone uses the 4047 to generate the clock and then uses the LFO to modulate it. If you can output the LFO from your uC, you can modulate the Small clone clock with it just like the original LFO.

Alternatively, it *is* possible to generate a modulated clock directly with a uC, but it's pretty demanding for a little chip and the problem is avoiding digital "stepping" and artefacts. My Flangelicious project goes down this route in order to save parts and make a simple flanger. It uses an on-chip Numerically-Controlled Oscillator module to generate the clock and then uses a programmatically-generated LFO to modulate that clock. It's not bad (and for a tiny, cheap, 8-pin chip it's pretty amazing!) but I won't try and argue that it's totally silent or totally smooth.

The "analog clock modulated by digital LFO" technique avoids most problems with digital stepping, so it's not a bad way to go. This is because digital LFOs are much easier than digital clocks since the frequency is so much lower.


MarshallPlexi

Man thank you so much for the good reply ElectricDruid! I really appreciate it. I see what you mean about extending the uC beyond it's capability. I'll try the "analog clock modulated by digital LFO" technique that you mentioned. :) 

MarshallPlexi

Been thinking on this for a couple of days. What kind of predictability will I get on the clock frequency by adjusting a resistor? With the uC I was able to set the clock freq down to a single Hz. For chorus this is not a big deal but when tap tempo analog delay is concerned, it's a huge deal.

Is there a way to get the best of both world's, (uC controlled clock and uC controlled LFO) to merge short of doing it all in software?

ElectricDruid

#4
Honestly, how much predictability do you need for a chorus? 1% resistor isn't good enough? You certainly don't need single Hertz resolution - that's just you getting spoiled by digital!

Tap tempo delay is a different problem. For that, you need a fixed clock frequency at a specific frequency based on the tapped rate. That you can pretty much *only* do with a uC. You can use the uC to control some external clock, but then you introduce various errors. It an be close enough, but it's not the best way, unless you include feedback from the clock to the uC so it measure the result that you're getting at a specific control value.

If you want modulation *as well as* uC-controlled clock, you've got basically no choice but to merge it all in software.

My recommendation for that is to give up on trying to do things in a single sample. The output interrupt routine should be very short and only take a single value from a buffer and output it. When the buffer is empty, it should set a flag and move to a second buffer. Meanwhile, the main code monitors the flag and when it detects a buffer is empty, it can generate a whole buffer-full of new output data. Doing the output in batches like this is much quicker than doing every sample individually. If it's still too slow, the solution is to work out (say) every eighth sample and then use a simple straight-line interpolation to generate intermediate samples. That avoids doing most of the sums except for a few times per buffer.




MarshallPlexi

I totally agree on the chorus. I'll research the rest. Thanks for pointing me in the right direction!