FM Synth anti aliasing.

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Just had an idea. Have no idea if it's any good,just putting it out there, stream of conscience.

A friend of mine has been experimenting with FM synths lately and been nagging me to build an Android one. Just now in the back of my mind almost i thought about aliasing and how to prevent it. And suddenly it struck me that if you limit the phase modulation on the final operator you can prevent aliasing all together.It is a just sine wave and if we prevent it to go any "faster" than fs/2 it will never alias no matter how complex the modulation signal is.

Don't know how to limit it and what the consequences are and if it's old news already.

Comments ?

Post

And yes technically it's PM,i know. I'm thinking you need to limit all operators otherwise the modulation would not be "right" on the other hand limiting it would make it "not right" too. Don't know how that would affect things.

And apparently it's stream of consciousness but i can't edit that now,that would go against the whole concept.

Post

jupiter8 wrote: And suddenly it struck me that if you limit the phase modulation on the final operator you can prevent aliasing all together.It is a just sine wave and if we prevent it to go any "faster" than fs/2 it will never alias no matter how complex the modulation signal is.
If you limit the phase modulation you are applying distortion to it. If you clip it, clamp it, or even limit the delta, it's just distorting the modulation signal, it most cases it will likely make matters worse. The last thing you want to do is make the modulator bandwidth larger.

Also if there is already aliasing in the modulator signal, there is nothing you can do. The aliasing is already baked into the modulator signal and indistinguishable from a genuine signal. And aliases in the modulator will cause proxy aliasing in the carrier.

IMO the only sane way to do it is to limit the modulation depth relative to the keytrack.
Chris Jones
www.sonigen.com

Post

I think most implementations simply use oversampling. Limiting the modulation waveform slew rate will probably not do what you want, and will break cases such as square wave modulating square wave (will produce bad sounding artifacts around edges).

In theory you could synchronize the sampling rate with the note frequency (set the sampling rate to one of the harmonics of the currently played key). The synthesis will still alias, but the aliased frequencies would line up with existing frequencies...

You could also look into DSF Synthesis, which is similar to phase distortion synthesis and FM with feedback all the way up, and can be perfectly bandlimited.

On real synths, Yamaha simply added a parameter that lowers the modulator volume as you play higher keys...

Post

sonigen wrote:If you limit the phase modulation you are applying distortion to it. If you clip it, clamp it, or even limit the delta, it's just distorting the modulation signal, it most cases it will likely make matters worse. The last thing you want to do is make the modulator bandwidth larger.
When i said limit i didn't really mean hard clip. If you normalize the remaining "room" for phase modulation to [0,1] you could do a tanh or something on it.
sonigen wrote:Also if there is already aliasing in the modulator signal, there is nothing you can do. The aliasing is already baked into the modulator signal and indistinguishable from a genuine signal. And aliases in the modulator will cause proxy aliasing in the carrier.
I realized that hence post 2.
sonigen wrote: IMO the only sane way to do it is to limit the modulation depth relative to the keytrack.
I'm thinking this is kinda what i'm doing only automatique in real time.
MadBrain wrote:I think most implementations simply use oversampling.
That was my first angle of attack then this idea struck me.
MadBrain wrote:Limiting the modulation waveform slew rate will probably not do what you want
I'm not so sure about that. I think correctly implemented (whatever that is) it'll probably be just fine.
MadBrain wrote:and will break cases such as square wave modulating square wave (will produce bad sounding artifacts around edges).
Square waves wooot ? :D It's FM we don't need no stinking square waves. :hihi:

Post

jupiter8 wrote:
sonigen wrote: IMO the only sane way to do it is to limit the modulation depth relative to the keytrack.
I'm thinking this is kinda what i'm doing only automatique in real time.
Sorry I meant scale the modulation depth relative to keytrack. Essentially a gain element that reduces the modulation depth as keytrack increases.
Chris Jones
www.sonigen.com

Post

Can't you just "solve" the aliasing by working at a higher sample rate?

Post

Do I have the idea right - modulated carrier phase is no further from unmodulated carrier phase than some constant (I guess related to sample rate and carrier frequency)? My intuition would be, the band-limited signal which aliases the 'real' signal might be different than otherwise, but I don't think any less free of aliasing for a lower rate. I think if one imagines a carrier signal function that's just (input = output), run at different rates, this is more clearly obvious - also, the fact that one would use a sinusoidal carrier signal function in FM doesn't change this.

([e] Well, in the simplest arrangement imagine a continuous sinusoidal carrier composed with an identity function at some sample rate maybe ... 'real' signals that alias come from the infinite set of partials as described below, and one can lower the amplitude of modulation to get nicer behavior but I don't see how shaping the modulation on top of that would change things)
Last edited by xh3rv on Thu Dec 19, 2013 9:35 pm, edited 2 times in total.

Post

sonigen wrote: Sorry I meant scale the modulation depth relative to keytrack. Essentially a gain element that reduces the modulation depth as keytrack increases.
If you've got a carrier with frequency Fc, and a modulator with frequency Fm, and the the modulation strength (index?) is B, then sin(Fc * 2 * π * t + B * sin(Fm * 2 * π * t)) = sum(bessel(i, B) * sin((Fc + i * Fm) * 2 * π * t), i, -Inf, +Inf)

So, the level of Fc + i * Fm is bessel(i, B). You can only keep that under a certain level by hard limiting B as a function of Fc and Fm. So, if Fc and Fm are both 5kHz, and you want any signal above 20kHz to be less than -60dB, then all bessel(i, B) should be less than 0.001 for i >= 3, which means B cannot exceed 0.35 in this case. If Fm is 10kHz, B should be less than 0.09.

Of course, if the modulator is more complex than a sine wave, the picture changes somewhat.

Post

FLWrd wrote:If you've got a carrier with frequency Fc, and a modulator with frequency Fm, and the the modulation strength (index?) is B, then sin(Fc * 2 * π * t + B * sin(Fm * 2 * π * t)) = sum(bessel(i, B) * sin((Fc + i * Fm) * 2 * π * t), i, -Inf, +Inf)

So, the level of Fc + i * Fm is bessel(i, B). You can only keep that under a certain level by hard limiting B as a function of Fc and Fm. So, if Fc and Fm are both 5kHz, and you want any signal above 20kHz to be less than -60dB, then all bessel(i, B) should be less than 0.001 for i >= 3, which means B cannot exceed 0.35 in this case. If Fm is 10kHz, B should be less than 0.09.

Of course, if the modulator is more complex than a sine wave, the picture changes somewhat.
Good luck doing that with anything more complicated than 2 or 3 sine waves and particularly if you have feedback.

Fact is if you reduce the modulation index you reduce the bandwidth created in the carrier. Based on my experiments I figured a rough rule of thumb is double the modulation index double the bandwidth.

So i give the user a "damping" control which does little more than scale down the modulation index above a certain note pitch. So you design your patch, hit the highest note your going to use, and turn up the damping until you balance the aliasing vs the brightness of the sound. It's not perfect but it's actually pretty effective.

That said, with my synth being modular I don't know whats coming into the phase modulation input anyway, so an analytical solution would not work.
Chris Jones
www.sonigen.com

Post

GeckoYamori wrote:Can't you just "solve" the aliasing by working at a higher sample rate?
Yeah, and you can "cook food" by ordering pizza.

Post

mystran wrote:
GeckoYamori wrote:Can't you just "solve" the aliasing by working at a higher sample rate?
Yeah, and you can "cook food" by ordering pizza.
:lol: :lol: :lol:
Chris Jones
www.sonigen.com

Post

GeckoYamori wrote:Can't you just "solve" the aliasing by working at a higher sample rate?
Yes of course,absolutely. However oversampling is the obvious answer and where's the fun in that ? It was the first thing on my mind but i find it way too boring and the easy way out.

As a mental exercise, preventing aliasing from happening in the first place is a much more fun challenge. And chances are, it's less CPU consuming. And oversampling comes with it's own set of problems.

Post

It is exactly as I've been saying for years. You can 100% anti-alias phase modulation using a thru-zero band-limited oscillator. Replace the continuous waveform with a sample, replace the sample by band-limited impulses.

Presto:

https://soundcloud.com/xhip/horriblefm

This is it working in Xhip. Obviously there is zero aliasing, but the waveform still does get "weird" up in the high end. What would have normally been a lot of aliased harmonics in the typical implementation is now a really weird series of totally insane timbres.

To solve that you still need to oversample, and I'd also use an impulse with minimal ringing to reduce the weird effects with the sacrifice of high-frequency accuracy, which when combined with oversampling is out of the audible range although it would have contributed to the difference band if it hasn't been filtered away.

I did this in a few minutes. Was just going to post about the technique again, but after running into argument after argument about how it wouldn't work I decided to just implement it instead. Already had the components I needed really so it was just a matter of generating a sine sample and adding some dumb code to make thru-zero work with samples. Horrifying, but if you were only ever going to play sine samples it really wouldn't be an issue, just use some size like 1024 and wrap with an AND.

The real issue is that inserting 50 impulses per sample takes a... small... amount of CPU power.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

What I still don't 100% understand is without aliasing occurring, how do the weird detuned effects that seem to be modulated in weird cyclic patterns get produced? I know these occur also when you do analog FM and the best answer I've ever seen is "well it's complicated."
My new theory on this is that you need to measure the integral of the signal for the sample and operate based upon that rather than just taking the new value of the modulator.

As you get into higher frequencies there are obviously less samples and the approximation of the underlying waveform is less and less accurate. This error sums more quickly at higher carrier rates and is produced more at higher modulator rates.

It is possible to find the integral in reasonable time for sine, and it will also be possible for sinc. So ideally you could sum the contribution of the integral of each sinc impulse (each source modulator sample) to get the actual modulation total. This would of course remain approximate but it would eliminate some of the error.

If the modulator wave is sine and if it is not modulated itself (feedback or other) it is safe not to use the sinc impulses to generate the wave.

Different numbers of impulses can be used depending upon the frequency. It does not make sense to output more than two impulses per sample and in order to avoid that a "mipmap" wavetable can be used.

When the modulator is below the range in which aliasing would occur it makes more sense to build it via interpolation rather than inserting any impulses at all.

A working system with all these issues taken into account would be complex to say the least, but I believe it is possible to eliminate the detuning and noise generated by the naive method.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post Reply

Return to “DSP and Plugin Development”