Sorry MM, I'm agreeing with Havakok on this one: A time domain interpolation solution should do just as well, practically speaking, and be significantly cheaper in terms of computation. (Assuming most frequency content is a ways below Nyquist).
I would go with cubic interpolation so you don't have any "corners" at the original sample points, which are of course constructions (introduction) of higher frequency tones.
The channels should definitely be interpolated independently.
Ced
Follow up for Marcus:
I thought it would be helpful to actually see some examples.
1) Linear Interpolation - Black Line
2) Cubic Interpolation - Red Line
3) Fourier Interpolation - Green Line
(This is not a FIR implementation of a sinc function. Instead, I took the DFT, zero padded it, then took the inverse DFT.)
First is the pulse.
What appears to be the sinc function is not. It is the Dirichlet kernel function, aka alias sinc. [See the "As N Gets Large" section, starts at (28), in my blog article https://www.dsprelated.com/showarticle/1038.php to see how they are related.
Next is a big sine. They are all good approximations here.
This is a fairly smooth signal. The endpoints were made close to each other to make it fair for the DFT.
This is a rather rough signal. The endpoints were made far apart from each other to show the DFT's wraparound weakness.
So, which interpolation method is actually better? Obviously not the linear one. Otherwise, depends on your criteria I guess.
Suppose I have a section of signal that is a pure parabola. The cubic interpolation will give you exact interpolation values and the DFT approach will give good approximations. Suppose another section has a pure tone with an integer number of cycles in the DFT frame, then the reverse will be true.
Apples and oranges.
I figured the OP was wanting to upsample in order to improve delay estimation granularity because of Tetrahedral microphone array beamforming. Looking at these graphs, I believe that the cubic interpolations would do a better job of matching the same signal sampled at fractional time delays of each other, so I am sticking with my answer, but that's a test for another day.
I'm also sticking with it will take way fewer calculations, and as SP points out, lower latency.
I wrote a program in Gambas just to produce these charts. The sample values are controlled by scroll bars so it is really easy to use. I have posted the source code in a Gambas forum at Interpolation Methods Comparison Project.
You'll need to install Gambas if you don't have it. The latest version is 13.3.0. The repository reference is PPA:gambas-team/gambas3
Olli,
Yes, I was referring to the ripples introduced in the neighborhood of the points, not the wraparound. I disagree with you, their location will very much be coarse grid spacing dependent and will thwart delay matching methods. They are exactly at the Nyquist frequency (one half cycle per sample) of the coarse sampling and thus will be introduced in the fine interpolated sampling.
You also seem to have neglected my counter example of a parabolic shaped signal section and have concentrated your analysis on sinusoidal tones. If I coarsely sample the parabola at any delay distance, I will get the points on the parabola at the sample locations. Now, when I do a cubic interpolation, the interpolated points will match the underlying signal exactly and therefore the delay calculation can also be exact. (I'm big on exactness.)
The other point you are all missing is the sinc funtion pertains to continuous cases, it is only an approximation in the discrete case.
Pipe,
Yes, I am only dealing with a time domain assessment due to the problem being solved, "find the delay", is inherently a time domain problem. My opinions are based on mathematical experience and have yet to be rigorously confirmed in this case. I actually like being proved wrong (especially if I do it myself and not have my nose rubbed in it) as it leads to learning something new rather than confirming my pre-existing biases.
Olli, Marcus, Robert, Pipe,
So enough sophistry about discussing the number of angels that can dance on the head of a pin, let's get a pin, some angels, and count them. Please provide a specific algorithm you recommend, including the size and coefficient values of any FIR filter. It needs to work on my 16 point sample set, but I can zero pad as necessary. A quick code sample would be ideal. Then I can do some actual numerical measurements and defend my "negligible harmonics" remark.
Here is my cubic interpolation code:
Paint.MoveTo(myDW, myDH + myBars[0].Value)
For n = 1 To myCount - 3
p0 = myBars[n - 1].Value
p1 = myBars[n].Value
p2 = myBars[n + 1].Value
p3 = myBars[n + 2].Value
c1 = p2 - p0
c2 = 2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3
c3 = 3.0 * (p1 - p2) + p3 - p0
For m = 1 To myDW - 1
v = m / myDW
f = p1 + 0.5 * v * (c1 + v * (c2 + v * c3))
Paint.LineTo((n + 1 + v) * myDW, myDH + f)
Next
Paint.LineTo((n + 2) * myDW, myDH + p2)
Next
Paint.Stroke()
Progress:
I don't have Octave (or MATLAB), I don't use SciLab, so I couldn't do anything with Olli's code. But I looked at the picture, so this is what I did:
'---- Build an Olli Fir
Dim o As Integer
Dim a, f As Float
f = Pi(0.2) '2 Pi / 10
myOlliFir[100] = 1.0
For o = 1 To 100
a = f * o
myOlliFir[100 + o] = Sin(a) / a
myOlliFir[100 - o] = myOlliFir[100 + o]
Next
To be fair, since the endpoints aren't at zero, I artificially extend them to the full FIR width. Notice my calculation is efficient in that I'm not bothering actually multiplying padded zeros with the FIR value and adding them. Still, this method takes considerably more calculations to achieve.
'---- Olli Interpolation
Dim o, t As Integer
For o = 0 To 65
v = 0
s = 95 - o
For t = s - 5 to 0 Step -5
v += myCoarseSamples[0] * myOlliFir[t]
Next
For c = 0 To 15
v += myCoarseSamples[c] * myOlliFir[s]
s += 5
Next
For t = s To 200 Step 5
v += myCoarseSamples[15] * myOlliFir[t]
Next
myOlliValues[o] = v
Next
My sample signal is a single tooth. The black line represents the real continuous signal. The red line is the cubic interpolation and the green line is the FIR interpolation. Sampling is perfect, so the sample values are the signal values at those points. Both interpolations work off the same set of sampled values and are blind to the underlying signal.
So, do the extra calculations lead to a better fit?
Sample at peak:
Samples even at peak:
Samples askew at peak:
I don't think so.
Delay calculation from two different snaps is next. Do the extra calculations make this more accurate? I highly doubt it.
I'm going to delay doing delay processing. I'm not sure it will add much to the discussion and I have other more pressing things to work on.
I have posted the program that produced the latter graphs in the same forum thread I posted the original code in.
https://forum.gambas.one/viewtopic.php?f=4&t=702
It contains other signals besides the tooth. You will all be happy to know that the FIR technique outperforms the cubic interpolation on a pure sine wave, but not significantly. The reverse is true for a parabola shape. No surprises there.
In my opinion, there was not a single case where the extra calculations required by the FIR technique warranted the extra work in terms of significantly improved results. There are also many cases (particularly tooth and step) where the cubic interpolation was a much closer fit to the underlying signal.
I very much encourage the OP to install Gambas and download this program (assuming Linux is available).
This is the first sinc filter I've ever implemented and it does work. It doesn't always work better than the cubic interpolation, but when it does it isn't significantly better. The computation cost is considerably higher though. Given Olli's length of 290 hitting 58 coarse points, it takes 58 multiplies and 58 adds per a single output point vs 4 multiplies and 3 adds for the cubic (plus 0.8 multiplies and 1 add in this case if you include calculating the coefficients rather than using lookup arrays).
Is doing more than 12 times as much work for only maybe a slight marginal improvement worth it?
I don't think so, but it is the OP's choice. I stand by my opening statement: "A time domain interpolation solution should do just as well, practically speaking, and be significantly cheaper in terms of computation.", but I have learned a bit.