realtime software 90 degree phase shift a sinusoidal signal I would post this to stack overflow but it seems to me more like a signals and systems problem, which EE's thrive on.

I need a realtime system implemented in software that can generate a sinusoid that matches the input signal's frequency but with a phase lag of 90 degrees. The input signal will be a pure tone but can drift a bit in frequency (0.4 to 0.8hz) over time. Eventually I'll want output amplitude to scale with input amplitude as well but that's for another day. I'm aiming to be able to respond to input signal changes such that I'm under 5% phase error within about 10-15 seconds (a few input signal cycles).

My first attempt at this has used a hilbert transformer FIR filter to give me the "instantanous" relative phase between my input signal (100hz sample rate) and output, then a PI controller with set point =-90 to drive frequency f_out of output_signal = math.sin(2*math.pi*f_out*t). My hilbert transofmer FIR has a latency of 2.5 seconds and the dead time seems to prevent me from having any kind of a P constant without instability. 

I'm currently doing a deep dive into phase locked loops (I'm new to them) but it's not clear to me yet if this is the right tree to bark up. 

I'd appreciate any manner of direction/advice.
If you have it in a buffer and have enough computing power, you can track it to quite significant accuracy using two DFT bins and the formulas shown here:


A Two Bin Solution


For minimum latency I would recommend a frame length near 2 and 1/2 cycles, though for a clean signal 1 and 1/2 cycles should also give good results.

As you do a series of sliding windows, this will generate a sequence of parameters.  A moving exponential average of the parameters should give you a good current value (when they are slowly varying) to use.  More sophisticated techniques are available.

Once you have the current parameters, you can reconstruct a signal with any phase lag and/or amplitude adjustment you want.

Or if you are tracking the phase value frame to frame, the most accurate fit is at the center of the frame ($t_f$ is at $n=N/2$).

$$ x(t) = A( t ) \cos( \Phi( t ) ) $$

Where $ \Phi( t ) $ is a (predictive) near linear function and $A( t_f )$ comes directly from the two bins solution.