On Mon, Mar 13, 2023 at 7:41 AM Simon Iten itensimon@gmail.com wrote:
hi charles,
thanks for doing this!!
You're welcome. I guess what I really meant to say is: I have a few days off of work and what I wanted to do was play with synchronizing oscillators. I just didn't know why yet.
i copied your first patch (with the changes you suggested) to my bela and hooked up my hexaphonic bass pickup to it (well one string to start), and it works pretty well!
i will play with the threshold settings etc. as it is now, the pitch seems to go down a half step every time i stop a note on the bass so that the pll osc is a semitone off. not sure this will be a problem in a “proper” implementation, since i mostly want the pll to follow my playing (so i will just mute the osc when i don’t play)
The threshold should be adjusted, just above the noise level, so you don't get unrelated triggers.
It's not very good at the low frequencies yet, but I suspect it comes from the choice of rising edge detector. Also, the phase updates are abrupt, and they could be smoothed out.
i do not currently grasp the math in the fexpr~ objects, but will try to get into it…
It's a simple kind of dynamical system. It responds based on its inputs but also its internal state when receiving inputs. That's why [fexpr~] works well for this. You can add additional expressions and reference them from each other. There can be internal hidden state variables, etc....
is it hard to implement a detune factor? so that we could adjust the pll transposition (octave up/down, fifth etc.)
thanks so much already!!
I know it's pretty buggy right now, but I wanted to get something out for you to try quickly. I was pleased with how strongly synchronizing it is. Drag the initial frequency to 0.3 Hz or up to 20000Hz and it still goes right back to the input frequency.
I think there will be a few different versions of this oscillator, with different ranges of frequencies and effects, as I play with it this week.
On 11 Mar 2023, at 19:49, Charles Z Henry czhenry@gmail.com wrote:
If the phase is <0.5, then we're receiving pulses at more than double the current freq. In that case, don't update phase, update frequency. If the phase is >0.5 and <2.0, then we're within one octave. The maximum phase update amount is (1-phase) The maximum frequency update amount is ((1-phase)/phase)*freq Then, if the phase is >2.0, then the input freq is more than 1 octave lower. In this case, don't update phase, update frequency.
The cool part is this can all be implemented at a basic level in just a few lines of code with fexpr~! (I started in on it just to write this part, figuring it takes me 20 min)
fexpr~ modf($y1+$f5*$y2+$f3*$x1*$y3); if($y6!=$y6[-2], $y6, $y2+$f4*$x1*$y4); if($y5<0.5, 0, if($y5<2, 1-$y5, 0)); if($y5<0.5, $y2, if($y5<2, (1-$y5)/$y5*$y2, -1.414*$y2/sqrt($y5))); if($x1[-1]==1, $y1+$f5*$y2, $y5+$f5*$y2); if($y6!=$f2, $f2, $y6)
But just so difficult to explain, I created a mathcha document for it, if you expected to be able to start modifying it and tuning it up for use.
https://www.mathcha.io/editor/OBgdJIo6UzgsgZHp8K1VSjK188YTN4eVJyHrz1q8G
work in progress