> On 06/27/2026 2: 46 PM EDT Timothy Place <timothyaplace@ gmail. com> wrote: > > > Hi Robert, > > Yes, the polyphase impulse response prototype is a Kaiser-windowed sinc, whose beta comes from the target attenuation (beta
ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.
 
ZjQcmQRYFpfptBannerEnd

> On 06/27/2026 2:46 PM EDT Timothy Place <[email protected]> wrote:
> 
> 
> Hi Robert,
> 
> Yes, the polyphase impulse response prototype is a Kaiser-windowed sinc, whose beta comes from the target attenuation (beta ~= 0.1102*(A-8.7) for A > 50 dB).

Not too bad.  I have a MATLAB script to design this with either Parks-McClellan or Least-Squares or Kaiser-windowed.  But it also puts zeros right at the integer multiples of the sample rate, by multiplying by sinc in the frequency domain or convolving the impulse response with a rectangular pulse in the time domain.  Since most music and audio has its energy in the bottom 5 or 6 octaves, whacking those images more with zeros will decrease how much energy folds back into the baseband (as aliases).  But convolving with a rect makes the FIR longer.

Anyway I have MATLAB code that generates an optimal brickwall LPF for polyphase interpolation.  It makes output that looks like this: https://urldefense.com/v3/__https://dsp.stackexchange.com/questions/99566/polyphase-fir-for-audio-signal-how-do-you-upsample-pitch-down-without-have-it/99567*99567__;Iw!!BDUfV1Et5lrpZQ!ToI8MqQ7AuqSD5G-9YBuAhvk6iZ43AGn9DSQMGmhxq_RUjdA7kx7kVStGLICMuittbpsxKSekqS41O4SXyAOMY0Ornc$  You can have the script if you want it.

The length of the FIR is LxT taps.  But the very first one is zero, because you need that for symmetry for the first (or 0th) phase when the delay is exactly an T/2-1 samples.  Now you want your table to have L+1 phases or fractional delays all the way from T/2-1 samples delay to T/2 samples delay.  That way if you have an instantaneous delay of (L-1)/L + T/2-1 to L/L + T/2-1 samples (the latter is just T/2), you have the coefficient set ready to get.

> That prototype is sampled Lx finer than the input rate and sliced into L polyphase branches of T taps. Default is L=256 phases x T=48 taps.

Ooooh, that's a lotta taps.  I think you can get away with T=32 taps.  I found that L=512 (along with linear interpolation between neighbors) gets you 120+ dB S/N ratio from the energy getting folded back into the baseband.

L=256 is okay.  About 108 dB S/N.

> L sets phase resolution (images drop ~12 dB per doubling),

That 12 dB per doubling is due to your linear interpolation.  If you were doing drop-sample (or nearest neighbor) interpolation, it would be 6 dB per doubling.  https://urldefense.com/v3/__https://www.researchgate.net/publication/266675823_Performance_of_Low-Order_Polynomial_Interpolators_in_the_Presence_of_Oversampled_Input__;!!BDUfV1Et5lrpZQ!ToI8MqQ7AuqSD5G-9YBuAhvk6iZ43AGn9DSQMGmhxq_RUjdA7kx7kVStGLICMuittbpsxKSekqS41O4SXyAOgvEI2Sg$ 

If you did 3rd-order polynomial interpolation (like Hermite cubic-spline), it would be 24 dB per doubling of L.  But I don't think it's worth it just to reduce the table of polyphase FIR coefficients.  Linear interpolation and L approx 256 (or maybe 512) is better, more efficient, and simpler.

> T sets transition width / stopband depth (group delay ~= T/2 samples).
> 

The delay of the L phases of FIR is between T/2-1 and T/2 samples.  With T=48, your minimum delay is 23 samples.

> For the polyphase execution at runtime I take the two bracketing phase rows and linearly interpolate their coefficients before the dot product. 

That's sounds more expensive than swapping the order.  I think creating two output samples and linearly interpolating that pair of values for the output would be quicker.  Two dot products and one linear interpolation.

> The inter-phase blend is what gives resolution well beyond L discrete phases.

Well, it's continuous resolution on instantaneous time delay.  Which is really what you need for asynchronous operation.

> mu itself lives in a 64-bit accumulator that carries the deviation eps from unity ratio.
> 

I've done with a Q32.32 precision index (the top 32 bits point to a sample location in the buffer of input samples and the lower 32 bits is the fraction of sample delay, which is used as the interpolation parameter). https://urldefense.com/v3/__https://dsp.stackexchange.com/questions/99566/polyphase-fir-for-audio-signal-how-do-you-upsample-pitch-down-without-have-it/99585*99585__;Iw!!BDUfV1Et5lrpZQ!ToI8MqQ7AuqSD5G-9YBuAhvk6iZ43AGn9DSQMGmhxq_RUjdA7kx7kVStGLICMuittbpsxKSekqS41O4SXyAOE84kS54$ 

> And for the controller, it takes the target vs. instantaneous delay to calculate the adjustment ratio using a type-2 (PI) servo on FIFO occupancy:
> 
> * Observable = FIFO backlog in frames plus current mu (adding mu removes the +/-1-frame staircase as whole samples slip to make it continuous).

I did this with a SHArC about 3 decades ago.  I dunno what your processor is, but if you can get a machine clock counter and if you record this counter value into a buffer alongside each input sample (you're time-stamping each sample when it's received from the input sample interrupt), then when an output sample interrupt occurs, you can extrapolate where your continuous time is between input samples.  That's what you use for your instantaneous delay, besides the position of input pointer and output pointer.  This way, if you're converting 44.101 kHz to 44.100, you won't get a sample slippage every second.

> * Error e vs. a target setpoint feeds a PI filter outputting eps_hat; the resampler then consumes (1 + eps_hat) frames per output frame.
> * The plant is a pure integrator (occupancy = integral of rate mismatch, gain fs), so PI gives a clean 2nd-order loop: Kp = 2zetawn/fs, Ki = wn^2/fs, wn = 2pif_L. The integrator nulls a constant ppm offset to zero standing error.
> 
> The one wrinkle: it's gain-scheduled across three bandwidths - ~10 Hz to acquire, 1 Hz to track, 0.05 Hz steady-state.

That seems to be a controller more complicated than just PID (or PI, in your case).

> The occupancy observable carries a quantization sawtooth (one push-block peak-to-peak), and a PI's proportional path would leak that as FM sidebands; dropping to 0.05 Hz with a 3-pole error cascade rejects it to ~-120 dBc-equivalent at 20 kHz while still following a 1 ppm/s drift with under half a frame of error.
> 

Not sure what you mean by "occupancy".

--

r b-j . _ . _ . _ . _ [email protected]

"Imagination is more important than knowledge."

.
.
.

Reply via email to