Oscillator feedback


#1

One thing missing is a proper oscillator feedback function (meaning fm feedback).
I tried to implement it the brute way inside the code of osc/sine, but the result is no different than connecting the osc object back to itself (and this is due to the buffer size i guess).
Is there some way to bypass the problem?
I was thinking about deriving the equation and then integrating it back, but is it a feasible route for a naive programmer?

Also, since we're talking about feedback loops: would it be possible to extend the concept to something more complicated like a pll?


#2

Oh no! I had had the same thought, that implementing feedback internally would allow for a single sample delay instead of the full buffer. I assumed the buffer limitations only applied to connections between objects. So it's not possible to store the current output in a variable for the next pass to pick up and incorporate?


#3

yes... doing a quick test right now.


#4

I'm sure that IS possible.

a|x


#5

I had hoped so... I hadn't got around to it, but I had a vague intention of trying it. A sine osc with a dial and inlet for feedback amount would allow proper DX style phase modulation patches (apart from ones where the feedback loop involves more than one operator).


#6

Single-oscillator self-fm test patch in attachment, comments welcome before I turn it into a library object...
selfFM.axp (4.6 KB)


#7

Works like a charm, however something i would change is the amount of feedback, i'd extend it if possible. At some point the osc would start to warble and then to degenerate into noise, that's a nice thing to have. At the current state the osc it's still a bit too tame

Also, may i ask what's different with my code? (it's the one i did that would not work) (s rate)

Phase += ___SMMUL(param_feedback,Out_old) +  freq + inlet_freq;
int32_t r; 
int32_t p2 = Phase + (inlet_phase<<4);
SINE2TINTERP(p2,r);
Out_old=(r>>4);
outlet_wave= (Out_old);

Out_old is a variable declared in local data. Did i screw up with the ranges? Also, you used SMMLA instead of SMMUL and +. Is it just a matter of code efficiency?


#8

You're integrating the feedback into the phase, I only added it to the phase. I think you implemented Frequency Modulation, I implemented Phase Modulation - yet I called it selfFM (contribution to the general confusion... sorry)
I think FM synthesis (DX7 etc) in popular language really means PM.

yes

edit: the measured difference in performance is 16 cpu cycles (1 for every audio rate sample) out of 507 cycles.


#9

That is true. Feedback in true FM is not all that useful, even in digital systems it sends the oscillator out of tune where PM is very stable (until you push the feedback high enough). Speaking of which, I second Sputnki's request: increasing the range so that 'too much' feedback is possible, it was used in DX synths as a noise source. I know we have proper noise sources, but the feedback noise still has its use in pure FM (PM) patches.


#10

so, tried the object, it sounds really nice! @johannes, why was it not included in the library? i tried adjusting the feedback, but i think that is not easily possible with your code, right?


#11

You could adjust feedback (to achieve the noise), but i think you'd have to replace SMMLA(a,b,c) (which performs a*b + c with SMMUL(a,b), which does a*b
At that point you should be able to do some more bitshifting to the feedback signal before adding it to the phase.
Johannes' code is surely more efficient and good looking, however


#12

Hello,

Here is an implementation of the Self phase modulation algorithm.
It is a tamed version, with a "anti hunting" filter.
So it is more like a low cost anti aliased sawtooth osc than a crazy feedback engine.

By using this "anti hunting" filter, I avoid high frequency self oscillations and - as a side effect - I do not need to use the interpolation function SINE2TINTERP, a raw access to sine2t is good enough => low CPU and nice anti-aliasing.

The feedback is controlled by the fbMod inlet.
The range of feedback modulation is controlled by two parameters fb0 and fb1.

When the fbMod inletvaries in the [0 64] range
the feedback varies in the [fb0 fb1] range.

I think this is a handy way to control this parameter.

A dial display shows how fb evolves when you are live.

The object and a simple patch:

SelfPM.axo (2.0 KB)
SelfPM.axp (2.6 KB)


#13

Sounds nice, could it also stabilize a self frequency modulation osc?


#14

I don't think it will.
FM is equivalent to PM in the simple case of a sine wave modulating a sine wave.
Frequency modulation has many drawbacks VS phase modulation. One is detuning if the modulator has some DC offset.

With self modulated PM, it is possible to generate square like waveforms by feedbacking the square of the output.
Here is an update of my SelfPM object:

SelfPM.axo (3.5 KB)

  • Extended Fb for brighter sounds
  • negative Fb switches to "squarish" mode
  • linear interpolation of fb at audio rate

Here is another object that implements 4 detuned SelfPM oscillators.
selfPMBank.axo (6.3 KB)

and a 15 voice (60 oscs) String Machine patch that uses this one:
PolySelfPMBank.axp (14.2 KB)

And thanks Spitnki for your "Coding axoloti objects", it really helped me to figure how fixed point works with ___SMMUL !


#15

check my oscillators for doing selfFM,
there are a few things that you need to take care off:

-linear FM should often use an index: multiply it with the current frequency so it stays in the same ratio, whatever the frequency is. Then add this value to the phase together with the base frequency.

FMW = __SMMUL(paramFMW<<3,freq<<3);
phase += freq + ___SMMUL(modsignal<<3,FMW<<2)

(ps. this code isn't working as the __ before SMMUL should be 3x "" and the editor here removes one in the FMW function..)

-exponential FM doesn't need an indexing, as the modulation-width is automatically wider at higher octaves.

-I always implement a HP-filter on the modulating signal. This is needed as frequency modulation tends to modulate the signal such that it gets a DC-offset, offsetting the base-pitch. By implementing a HP-filter, you can remove this DC-offset, so the base-pitch of the modulated oscillator doesn't change too much.

This HP filter also helps to prevent the oscillator to get "stuck" if the self-modulation makes the frequency to be zero hertz. As this only happens when the modulation is exactly the negative version of the "base-pitch"( when the multiplication of the frequency is -1), the HP filter will force the modulator-multiplication back to zero, allowing the oscillator to go above zero hertz again and move on.


#16

I'll surely play with wilder/less controlled self modulation, distortions and delays in the feedback loop can lead to unexpected and sometimes interesting results :smiley: and in the case of distorted feedback FM and PM are not equivalent.

-I always implement a HP-filter on the modulating signal

Phase is the integral of the frequency.
A first order high pass filter is an approximate of a differentiator (it is a low passed differentiator) .
So, when you insert the HP filter I guess it is equivalent to phase modulation with a low pass filter on the mod input.


#17

that's true indeed, now you mention it XD
but in case of FM, you're changing the internal phase, while with PM, you add the signal to the current phase, which keeps going on it;s own pace..
so the PM is more like a waveshaper with feedback and phase as input.
The use of the HP filter with linear FM allows to move between "normal" FM modulation(very very low cutoff, or fading out the filter) and a more PM-like modulation (higher cutoff) or just sit somewhere in between.


#18

Yes, at low frequency, a phase modulated oscillator can be seen as a non linear function with a varying central point.
That's why i put some effort in the pre integrated polynomial wavetables: this will allow to anti alias wavetables and distortions :smiley: