Any advice for chorus effect development?

Hello, I’m working on a module that’s attempting to emulate a pedal I’ve made. The effect is tremolo and chorus with related and linked rate controls. I’ve more or less figured out the tremolo portion, but I’m a bit lost on chorus.

I’ve peaked at the source code for a few chorus modules, and they seem very complex. This is my first VCV Rack module, and I’m definitely not a DSP wizard or anything, but I’ve made a few pedals with FV-1. Chorus is very easy to implement in SpinASM for the FV-1, but it is a language designed for audio effects. I’m much less familiar with C++, and I’m not sure if what I’m interpreting as complexity is just my inexperience.

I was thinking of chorus as being a very short delay with an LFO modulating the delay time. I am able to more or less follow the Fundamental Delay and LFO code, so I was thinking that should get me going in lieu of a simple chorus example, but I was wondering if anyone had any advice or better ideas? I was making this as my first module because I thought it would be fairly straightforward (as far as DSP goes) but I’m beginning to suspect that this sort of thing is easy in the FV-1 but not generally.

most good choruses have three of those, with the LFO being 120 degrees our of phase with each other.

Hi @dogmandevices, and welcome to the forum!

I think you’re starting in a very good place. The only hard thing about basic DSP for chorus is setting up a varispeed delay line (which the FV-1 basically does for you). That’s where Fundamental Delay comes in. The block that does the varispeed is the one with outBuffer, historyBuffer, and the call to src_process (which is where the sample rate conversion actually happens). You should be able to take most of the Fundamental Delay processing code and connect your own LFO setup to the pitch/freq calculation without much trouble. Think of it as running an internal trace to the relevant section rather than doing it with an external cable.

By the way, one approach–which you may have tried and/or rejected already–is to lean into the modular nature of… well, modular :slight_smile: and actually patch your pedal together in Rack from modules like Fundamental Delay and LFO, rather than starting by coding everything up in its own module. Totally your call but patching it together might give you a useful reference point and reality check (you could, for example, quickly see if the Fundamental Delay is going to give you the sound you want, or if you’d prefer to look elsewhere).

Please keep posting here if you have other questions or hit any roadblocks!

BTW, what @Squinky is describing (as you may already know) is the tri-chorus setup (Dytronics was an early manufacturer of these and may have invented the effect)–it’s very lovely but which probably doesn’t match your pedal design.

1 Like

The tricky part is go get click free delay modification. There are various ways.

The simplest is to just interpolate between two samples, so if you need 3.25 samples delay, you take .75 * Sample[3] + .25*sample[4] from your delay line. This does not yield very clean results.

There are also more elaborate interpolation algorithms (3rd order interpolation etc) which try match a smoother curve than just line segments between two samples.

You can also use an FIR filter, basically the same as an anti aliasing filter at about 10% below the half sample rate, so for example at 21.6 kHz for a 48 kHz sample rate, Then you shift this filter by a quarter sample in the above 3.25 sample delay example. To do htis you need to oversample the filter by a high factor, like 1000. then for a .25 sample delay you take tap 250, 1250, 2250 and so forth of the oversampled filter for the coefficirnts to convolute with the input signal at your actual sample rate… Sorry, this is probably a bit DSP heavy, but you can look it up in my StereoChorus at:

GitHub - GPrackmodules/GPrackmodules: Collection of modules for VCV Rack 2

Check the file src/StereoChorus/ChorusDelayLine.h/cpp.

You can also just take it and use it, if you follow the open source license, feel free, that is the whole point of open source.

Btw: After I did my StereoChorus I asked ChatGPT to write me one, just for the fun of it. It provided two different interpolations for the delay line, and when I asked it specifically, it acknowledged that an oversampled FIR filter would have the cleanest sound. I didn’t ask for code for that, since I already had written it.

Also cleanest ist not necessarily best, some grittiness might actually result in a good effect.

1 Like

Excellent suggestions. Esp prototyping by patch before going straight to dedicated module development.

Re “tri chorus”, I think you are dismissing this because the FV-1 original is probably a single stage chorus?

In any case, a single stage chorus is notorious for introducing a very obvious vibrato, where the pitch goes up and down with the LFO. This can be a pleasing effect, but it can also be a sickening effect. Generally at slow LFO rates and high “intensity” the slow up and down pitch modulation just sounds out of tune.

Many chorus units use two stages, so that while one is going up the other one is going down. From reading the literature, it seems that one reason this is done it to cancel out the “out of tune” effect. Of course as we know three sounds better than two usually, hence the popularity of the tri chorus.

There is at least one, and probably more, chorus modules in VCV having more than one stage. Even the VCV Chorus has two or three. I think there is one that has four, although I can’t find it, so maybe I imagined that.

In any case, sounds like a fun project!

1 Like

My StereoChuros (GPaudio StereoChorus) has four instances, each with two taps, one from the left and one from the right input. Unless controlled by CV the left and right channels are modulated at a 90 degree angle (basically taking sine and cosine of the same LFO signal). The four instances run at slightly different rates (+/- a few percent) for added complexity.

2 Likes

wow, thanks for all this! This is a lot of good information. I’ve patched this up in Rack before, but the idea I’m getting now is to patch those together in code? I think it is good for my learning to figure some of these things out (I just think it would be nice to understand these things), but it is possible to just internally connect modules in code all under one panel, correct?

1 Like

It’s not exactly possible, but it’s a useful metaphor, and your code can end up looking pretty close to that if you structure it in a certain way. Each module gets one process() call per audio sample to be output so you can’t directly combine two modules. But you could start by taking the two module’s process() routines, and putting them (with whatever minor modifications you need) into two functions called, say, process_lfo() and process_delay(). Then structure your process() function around calls to both of these. Locally storing the output of the LFO and making it modify the relevant delay parameters is analogous to the “internal wiring” (please drop the metaphor if it’s confusing!) and would be done between the function calls. Later, for clarity (or, possibly, performance–but benchmark it first) you might move the LFO and delay code back into your main process() function.

Obviously there’s a similar process to go through if you’re trying to combine two front panels and user interfaces, but it’s pretty straightforward.

@Squinky – exactly! I was just noting that @dogmandevices was trying to replicate a particular FV-1 design and (as you suggest) FV-1 chorus designs are often single-stage. I much prefer the phase-separated LFO sound too–I worked up an eight-phase version of it once with drift between the LFOs (should go back to that at some point)!–and I think multiple lines would be an excellent digital extension to the planned module.

1 Like

great, thanks! That is very helpful. And just to make sure I understand, with a multi-stage chorus, each stage would be a delay and LFO, right? I was originally trying to replicate the same FV-1 chorus, but really I’d like to capture the “feel” of the pedal. I want to keep some of the limitations from the FV-1 (the three control pot maximum is what lead to the rate knob controlling two different LFOs, and I like that feature) but I think I’d prefer the sound of a multi-stage effect. I find that the pedal has a narrow range of chorus depth that I like, but if I can expand that area, it makes my idea of each pot having a CV input a bit more useful.

1 Like

Excellent! Glad @Squinky brought it up! Yes, the typical multi-stage chorus topology is to have the stages running in parallel and driven by LFOs that are phase-sync’d (usually, though not always, this is multiple copies of a single waveform and frequency offset by \frac{360^\circ}{n} for a design with n stages.)

Many of them include a mono-to-stereo design that derives a L and R signal from different combinations, and possibly inversions, of the stages (beware, of course, situations that cancel when collapsing back to mono, the trivial one being n=2 where stage 1 goes L and stage 2 goes R).

This is where prototyping with external patching will really save you a lot of time. For the phase-sync’d LFOs, one canonical answer is Bogaudio 8FO, but there are others. Have fun and please share what you come up with! It’ll be interesting to see if the move from single-stage to multi-stage chorus yields corresponding design ideas about the sync’d tremolo side.

and of course many times this is implemented with a single LFO that just has three phase outputs. There are I think many LFOs like this in VCV. Not that you necessarily want the same freq for all of them, but you might.

2 Likes

Just as an update for anyone interested, I’ve decided to take a slightly different approach for now and make some simpler things. I’ve made a LFO module with three outputs that are phase shifted 120 degree (and also have one polyphonic output of all three waves). I was originally just going to use this as a practice thing to use with this chorus, but it’s actually a lot more fun to use than I was expecting. I’m going to pick this chorus thing back up at some point, but I think I want to get to know my way around this stuff a bit more first. so much more is possible than I am used to

2 Likes

Shameless plug here: if you want to hear your LFO with a chous, you can use my Stereo Chrous, it has CV inputs for the delay modulation:

Just hook up your 3 LFO outputs to Mod-Inputs 1, 2 and 3, and set it to three voices.

Edit: And turn RATE all the way down until it shows “External Modulation Only”

2 Likes