Cabbage Logo
Back to Cabbage Site

Frequency shifters

I’m wondering if anyone has some good suggestions or recipes for frequency (not pitch!) shifters.

There is a Cabbage example by Iain McCurdy which uses Hilbert transform. I couldn’t find any on the Csound forum. Here (https://www.cim.mcgill.ca/~clark/nordmodularbook/nm_spectrum_shift.html) I found a link to Groh’s implementation with low-pass filters (https://csoundjournal.com/ezine/summer2000/processing/), which should be “An Efficient, Precise Frequency Shifter”.

I got attached to Live’s frequency shifter and I’d like to get something similar out of Csound to combine it in my instruments or just make one by itself to use in Reaper. I found some free ones, and tested this one: https://www.fullbucket.de/music/freqshifter.html. When I compare different ones, including Iain’s and Groh’s to Live’s they behave very differently. Live’s doesn’t have upper harmonics when down-shifting for example. I’m wondering if that is an added feature (filter) or they use a different algorithm.

Does anybody have any wisdom to share, advices regarding features and performance, recipes or patches? What filters would you recommend if going Groh’s way (I have just tried the biquad as in the original recipe)? Or is using Hilbert transform a generally preferred way?

Will this do:

https://csound.com/docs/manual/pvshift.html

Thanks. I guess it’d do. However, I thought time-domain would be faster. Or would you recommend doing it in frequency domain? Probably there are less artefacts with pvshift, but I’d like to use it with minimum latency as live FX for external signals, e.g. from guitar.

Any general thoughts on the above mentioned approaches?

I’ve no experience with this apart from very crude time domain pitch-shifters which just change the playback rate. And you’re right, the time domain will give better latency but i’d say it’s worth a shot. You could try it with some very short FFT sizes and see how it behaves.

I think the Hilbert transformer gets me to a good place. The FFT has artefacts even at large buffers (2048).

But I came across another “issue”, which might deserve a separate topic.
I’ve developed a funny way of using frequency shifter in Live on guitar, where frequency is midi mapped to a pedal and the bypass to a momentary button. The mechanics relies on ability of changing the frequency also in bypass mode, so that it is set for momentary toggles ON. I see that in Live 10, Cabbage plugins don’t update automation when they’re bypassed - what is worse is that automation is only detected when not bypassed and changing. So if it is changed to a new value in bypass and then kept constant, when bypass is turned off the automated parameters don’t update Csound.

This is not common for third party plugins. Would it be possible to enable this? I could build in an internal bypass button for this, but it would be handy to have it working as in other plugins.

This is a tricky one to work around as enabling bypass disables Csound. As soon as you bypass, Csound is more or less paused. I can take a look when I get a chance, but I think for now you might have to implement your own bypass mechanism.

I hadn’t considered those spectral artefacts. Hopefully Hillbert will do the job :+1:

Just my 2 cents. Yes, the hilbert transformer method is a very good way of doing it in the time domain. It is commonly called SSB (Single sideband modulation), and what it really does it using ring modulation to create frequency shifted sidebands, and then canceling out the upper or lower sideband byt using the phase shifting magic of the hilbert filter. It does not create any artifacts as far as I know.
If you just want to shift parts of the signal (for example to keep some frequencies as they are below 500Hz, and then shift everything over that threshold), then pvshift is your friend.

1 Like

Thanks for your feedback Oeyvind. I though the double filter method (presented by Groh) might be a good alternative, but I’m more pleased with the Hilbert transformer. And time-domain seem the way to go for live input.

When down-shifting though, we get folding/mirroring below a threshold frequency shift, such that for large negative shifts and low input tone it starts to shift back up again. I’m wondering if that could be nicely avoided and if you had this in mind when mentioning pvshift? Did you mean some combination of time-domain and FFT or just using FFT? I guess high-pass filtering the input (maybe with butterhp) could be useful in combo with the Hilbert transformer method + mixing in the clean low-passed signal?

Sorry for my delay. Yes, when you downshift so that the frequencies in the input sound drops below 0Hz, they will fold back. As far as I know, this will always happen with simple methods in the time domain. Hipass filtering before downshifting will help, but it is quite hard to make a filter with a sharp enough cutoff. When you do it with pvshift, in the frequency domain, this is much easier.

Thanks, really nice to get you feedback! It confirmed my intuition.

I did some tests trying to match Ableton Live’s frequency shifter by using a Linkwitz-Riley crossover 2 band splitter (based on a stack of 2 x second order Butterworth filters for each band, I guess this is 24 dB/octave) placed before the frequency shifter and with crossover frequency matching that of the frequency shifter (for negative shifts only). The reason I used a crossover instead of just a stack of high-pass filters is to match the phase of the dry signal when flipping dry/wet. This seems to bring me closer to Live’s device but I can see that I’d need an even steeper crossover, realizing, as you say, how difficult it is to get a sharp cutoff. When trying a naive crossover with 4 stacked Butterworth filters I couldn’t get the dry mix of the two bands correct (I guess phase issue), but the frequency shifter worked in that case pretty much spot on compared to Live’s.

I’m wondering if there are any efficient Csound crossover band splitters? Either as an UDO or preferably as an opcode. In this case, I’d of course need a very sharp one. As an example, Max has the “cross~” (https://docs.cycling74.com/max5/refpages/msp-ref/cross~.html) but I don’t know how it is implemented or what are its characteristics.

Sorry if I’m drifting a bit off topic. I just peaked into the DSP land and while I can see most of the dots I find it heard to connect them.