# On-the-fly computation of a variable cutoff frequency polyphase resampling filter

I'm creating a polyphonic audio sample player and I want to let the user play each voice faster or slower using resampling by a rational factor (classical interpolate by L / decimate by M scenario), in real-time (the user could send a command to set the speed of a voice and the system would adapt the resampling procedure for the given L/M ratio, with low latency).

The microcontroller I'm using isn't a DSP beast although its cortex M4 core has some "DSP" instructions. The most optimized solution I've found until now is a polyphase FIR windowed sinc interpolator that only calculates every M-th subphase (basically a polyphase filter where we don't bother calculating the output samples we'll throw away during downsampling afterwards).

As the L/M ratio changes, the cutoff frequency of the polyphase filter changes as well. As far as I know that means I would have to recompute the entire set of coefficients each and every time the user wants to change the playback speed, on-the-fly. The windowed sinc method would use huge amounts of cycles, and therefore drastically impacts the latency of the playback speed change operation, but it's the only method I've heard of when it comes to filters used in resampling.

What would be a less computationally expensive FIR coefficient calculation method / FIR filter type that I could use for my application, given the constraints above ? I'm ok with having a bit more aliasing/imaging in the final signal in order to achieve my goal.

• If you have about 16K words (64K bytes) of memory available for a lookup table, this can be done quite efficiently in a real-time context. You don't really want to compute a any coefficients on the fly other than linearly interpolating between adjacent entries in the lookup table. Oct 15, 2022 at 21:53
• So if you're upshifting, your stride through the coefficient table gets a little smaller, which low-pass filters the input a little more. That's what the Asynchronous SRC chips do. Oct 16, 2022 at 17:29

Here is how I have dealt with that problem in my work.

First, don't use a windowed sinc; use an optimized FIR lowpass designer. (You are only going to do this once.)

Say we design a 128 point filter, such that only 8 points fall on top of the data to be interpolated (the rest falling on the interpolated zeroes.)

Say the audio is stored sampled at 48 kHz. Then if the output transposition is 0 semitones, we will be moving a pointer through the data at a step-over of 1.0, thus hitting every data point exactly once. The convolver center moves over 1.0 with every output sample.

Now suppose we want to transpose down a semitone. The step-over becomes 0.94387. The input data is being consumed at a slower rate. If we could center the convolver around that new fractional value, all would be well, but there are only 7 possible places where we could put the convolver center between two data points. So we bracket the two closest points, and get two interpolated values out. Then we do linear interpolation for the exact fractional value.

There is noise introduced by the linear interpolation, of course, but if there are enough convolver points, this can be made as small as necessary. A 512 point convolver will do reasonably well. (Note that there are still only 8 points that will fall on top of the original data points.) The total number of operations doesn't grow with larger convolvers, while the precision of the linear interpolation step will increase.

The only difficulty is transposing upward, where the LP FIR cutoff frequency must fall, or otherwise there will be aliasing noise introduced. It's quite feasible to ignore this, and just not permit more than maybe half an octave of upward transposition without much problem. The solution is to effectively change the sample spacing of the convolver, so that it will extend over more than 8 (non-zero-filled) samples. So that is a little more work, but it only doubles for one octave up, so not too bad.

If you have the computational resources, one might take the 8 point convolution and instead use 12 or 16 points, and obtain a faster roll-off, and less noise. Using 16 points, there will be a cost of 16 x 2 + 2 (for the linear interpolation part) for each output point (for downward transposition). Double that for up to one octave upward transposition. 35 years ago, this approach needed custom DSP chips, but it should be trivial now-a-days.

• What optimized design method do you suggest? firpm()? firls()? Oct 15, 2022 at 15:56
• Thanks for this detailed answer, but I didn't get what the cutoff frequency for that initial 128 point FIR should be and why there is "only 8 points falling on top of the data to be interpolated" since the upsampling factor will change and therefore the number of interpolated zeroes will change. Oct 15, 2022 at 17:37