Allpass interpolation latency
- KVRian
- Topic Starter
- 1311 posts since 15 Nov, 2005 from Italy
Hi guys,
there's a way to calculate the latency samples for an AP interpolator used for oversampling?
Thanks!
there's a way to calculate the latency samples for an AP interpolator used for oversampling?
Thanks!
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
Well .. you can certainly calculate the delay an any given frequency (calculate unwrapped phase-response, divide by normalised frequency), but for anything other than a linear-phase FIR it will be frequency dependent (and integer almost nowhere) so it won't really do you any good as a "latency" value.Audiority wrote:Hi guys,
there's a way to calculate the latency samples for an AP interpolator used for oversampling?
-
- KVRian
- 1153 posts since 11 Aug, 2004 from Breuillet, France
I disagree with mystran. If we look for the delay in a famous AP interpolator used for oversampling, it is possible to see that there is a minimum integer value over all the frequencies, depending on the number of the APs in cascade. This value can be obtained by calculating the group delay using the continuous phase response, which isn't that trivial to do. An other method is to do it "by ear" listening to the sound of the plug-in when using a dry/wet of 50%, with an additional delay process (with variable delay value). The comb filtering is very noticeable if the delay is not compensated, and it is really becoming less significant with the right delay value.
If we're talking about the files BandLimit.h and BandLimit.cpp, I can give you the latency values to report if you want
If we're talking about the files BandLimit.h and BandLimit.cpp, I can give you the latency values to report if you want
- KVRian
- Topic Starter
- 1311 posts since 15 Nov, 2005 from Italy
yea, that is lol even if I heavily modified the original code to integrate my framework... but I'm having an issue with the oversampler buzzing like a beast and I guess that maybe that would be caused by a non reported latency or something wrong with the buffer. I'm using a 4th order filter, non steep (2 + 2 coeffs).
-
- KVRian
- 1153 posts since 11 Aug, 2004 from Breuillet, France
I don't think this is caused by the latency not correctly reported. At worst, what you can get in this context is a comb filtering effect if some dry signal is mixed with the oversampled signal. You should have a look for bugs in your implementationbut I'm having an issue with the oversampler buzzing like a beast
- KVRian
- 509 posts since 1 May, 2006 from lancaster, pa
Oh, I'd like to see your thoughts on this.Ivan_C wrote:If we're talking about the files BandLimit.h and BandLimit.cpp, I can give you the latency values to report if you want
-
- KVRian
- 1153 posts since 11 Aug, 2004 from Breuillet, France
So, since I didn't write down the actual values, I have done a study of that thing again First thing comes first, if you have not noticed yet, there is a mistake in the values written on the musicdsp files, as said in the comments on the website (12th order, steep, 0.06329609551399348 should be 0.6329609551399348). Moreover, the processing isn't optimized at all, so I would suggest not using the original file in a commercial product, unless you rewrite some parts of it. I know also that Laurent De Soras did already in his library HIIR a rewrite of that class, it can be interesting for you guys.random_id wrote:Oh, I'd like to see your thoughts on this.Ivan_C wrote:If we're talking about the files BandLimit.h and BandLimit.cpp, I can give you the latency values to report if you want
So, I started writing a plug-in which only does one thing, oversampling two times the input signal, using the filters two times (upsampling -> filtering -> nonlinear processing -> filtering -> downsampling). Here, I don't do anything in the nonlinear processing, hence the use of a filter two times (two different instances, with the same input parameters but different state variables of course). That plug-in allows me via a combobox to choose my filter design between all twelve choices given in BandLimit.cpp.
Then, I'm going to estimate the extra added latency in samples I get by doing that. Since I do upsampling two times, the latency of the filter is supposed to be halved if considered in the original sample rate. But I use the filter twice (in the upsampling and in the downsampling), so the total latency in the original sample rate is filter latency x 2 / 2 = filter latency.
Next, I open Reaper. I create one track and I put some audio there with some frequency content on all the frequencies (a white noise, the death metal song of your choice). I send the output of that track to two different tracks (in parallel), one of them being put in phase opposition. Without any FX, the audio you get in the master bus is supposed to be zero. Then, I add my oversampling two times plug-in in the first send track, and a delay in the second where I can tweak the value of the delay in samples. The idea here is to find by ear or by looking to the meters the value in the delay which will minimize, for a given filter design, the magnitude in the master bus. If my filters were FIR with linear phase, the right value would give me an absolute silence in the master meters. Since here it's a cascade of polyphase IIR allpass filters, the right value will give a significant decrease in magnitude, but never a silence. So I try to get the lowest value for every filter design specification, and I write the value I get in a table. Here are the results :
Steep
Order = 2 (-36 dB, 0.1) => best delay = 1 sample
Order = 4 (-53 dB, 0.05) => best delay = 2 samples
Order = 6 (-51 dB, 0.01) => best delay = 2 samples
Order = 8 (-69 dB, 0.01) => best delay = 3 samples
Order = 10 (-86 dB, 0.01) => best delay = 3 and 4 very close
Order = 12 (-104 dB, 0.01) => best delay = 4 samples
Not Steep
Order = 2 (-36 dB, 0.1) => best delay = 1 sample
Order = 4 (-70 dB, 0.1) => best delay = 2 samples
Order = 6 (-80 dB, 0.05) => best delay = 3 samples
Order = 8 (-106 dB, 0.05) => best delay = 4 samples
Order = 10 (-133 dB, 0.05) => best delay = 5 samples
Order = 12 (-150 dB, 0.05) => best delay = 6 samples
It's interesting to see here that the best delay is a factor of the order for the not steep designs, and that's not the case for the steep designs. At that point, everything is done by ear and with a look in the meters, so it's not very scientific... The thing is, as mystran said before, the actual delay in samples in this design varies with the frequency, whereas in FIR linear phase - by definition - the delay is constant for all the frequencies (half the size of the filter actually). That's why it might be difficult to find an objective value for a delay to report absolutely when we use these filters in the oversampling context.
However, what I said is that this delay, depending on the frequency, even if it varies across the frequency values, has a minimum which can be used objectively. If the delay from 0 Hz to Fs/2 goes from 2 to 6 samples, then at least we should report 2 samples of added latency in the plug-in. Here is a demonstration for the case not steep / order = 12.
As we can see here (that's an application I'm working on right now ), the phase delay - which can be obtained from the continuous phase of the total IIR filter made from the multiplication and addition of all the all-pass filters - has a minimum around 5.3 samples. So the minimum integer delay in samples is at 5. Then, an additional question arises : should we use another value, like the average delay for all the frequencies ? I don't know what's the best, but using my "ear and meter look criterion" with the minimization of the output meter value, 6 seems to be better in this particular case. That might be interpreted as "too much delay on bass frequencies is not important, enough on mid and high is always better" or something like that, I'll let you decide of what you think there.
I hope that was understandable enough
-
- KVRAF
- 3080 posts since 17 Apr, 2005 from S.E. TN
I don't recall details, but the only time I used those allpass halfband filters was in combination with some other "cheap" processes for generic samplerate conversion. It was a long time ago.
The allpass halfband filters were the "most expensive" of the routines I used. The halfband filters and other processes were written in FPU asm. I picked a bunch of different combinations of the processes, then tested them "nonrealtime" on long slow sine sweeps, writing the results to disk. I tabulated execution time for each combination, and measured the output disk files of the sine sweeps to evaluate frequency response and amount of aliasing for each combination.
It was to offer user-selectable SRC quality choices from an audio application. The combination of processes that ran "fast" and also had the least aliasing and flattest frequency response was chosen for the "Fast" choice. Then the combination that had somewhat slower execution time with the best audio quality was selected for the "Better" choice, and the combination with the best audio fidelity chosen as "Best" choice even if execution might be slow. As best I recall there were more than one "slow" combinations which had similar audio fidelity, and the slowest combination was not necessarily the highest-fidelity combination.
So anyway, depending on the quality level and the nature of the SRC, the latency could vary. Didn't know how to calculate the latency programmatically and there were too many combinations to just store a table of all latencies. All the choices were fairly "quick'n'dirty". For instance the "best" conversion for 44.1 k to 48 k SRC might have been 8X oversample, linear interpolation, then decimate with multiple passes of fairly high-order allpass halfband filters. But maybe the lower quality "better" conversion would only oversample 4X and use some combination of IIR lowpass filters or "lower quality, lower order" allpass halfband filters. Can't recall specifics.
As best I recall, I just measured the latency every time after setting the SRC object for a conversion ratio and quality level. Before returning from the object setting function, I just ran some simple test signal thru the newly-set SRC object to auto-measure its conversion latency. For audio application purposes, I think it was also involved with the size of the soundcard audio buffers versus the conversion ratio. It had to "play ahead" enough to always have sufficient samples samplerate-converted for the next requested audio buffer, so the internal SRC input and output buffers had to be sized accordingly. Which was not very complicated for integer-ratio conversions such as 96 k to 48 k or whatever, but seemed somewhat tricky for things like 96 k to 44.1 k or whatever.
The allpass halfband filters were the "most expensive" of the routines I used. The halfband filters and other processes were written in FPU asm. I picked a bunch of different combinations of the processes, then tested them "nonrealtime" on long slow sine sweeps, writing the results to disk. I tabulated execution time for each combination, and measured the output disk files of the sine sweeps to evaluate frequency response and amount of aliasing for each combination.
It was to offer user-selectable SRC quality choices from an audio application. The combination of processes that ran "fast" and also had the least aliasing and flattest frequency response was chosen for the "Fast" choice. Then the combination that had somewhat slower execution time with the best audio quality was selected for the "Better" choice, and the combination with the best audio fidelity chosen as "Best" choice even if execution might be slow. As best I recall there were more than one "slow" combinations which had similar audio fidelity, and the slowest combination was not necessarily the highest-fidelity combination.
So anyway, depending on the quality level and the nature of the SRC, the latency could vary. Didn't know how to calculate the latency programmatically and there were too many combinations to just store a table of all latencies. All the choices were fairly "quick'n'dirty". For instance the "best" conversion for 44.1 k to 48 k SRC might have been 8X oversample, linear interpolation, then decimate with multiple passes of fairly high-order allpass halfband filters. But maybe the lower quality "better" conversion would only oversample 4X and use some combination of IIR lowpass filters or "lower quality, lower order" allpass halfband filters. Can't recall specifics.
As best I recall, I just measured the latency every time after setting the SRC object for a conversion ratio and quality level. Before returning from the object setting function, I just ran some simple test signal thru the newly-set SRC object to auto-measure its conversion latency. For audio application purposes, I think it was also involved with the size of the soundcard audio buffers versus the conversion ratio. It had to "play ahead" enough to always have sufficient samples samplerate-converted for the next requested audio buffer, so the internal SRC input and output buffers had to be sized accordingly. Which was not very complicated for integer-ratio conversions such as 96 k to 48 k or whatever, but seemed somewhat tricky for things like 96 k to 44.1 k or whatever.
-
- KVRian
- 1153 posts since 11 Aug, 2004 from Breuillet, France
For me, in the context of strict oversampling (SRC with integer ratios), the main point of using IIR filters instead of FIR filters is the low added latency. Even if it is not null at all as I have shown, for purposes where latency might be an issue but not the magnitude and the phase at high frequencies, it is difficult to find a better method from what I know.The allpass halfband filters were the "most expensive" of the routines I used.
It's totally fine to use a linear phase FIR filter for mastering / mixing audio effects, which seems to be better in quality and speed than optimized IIR polyphase AP filters. But for a guitar amp simulator for example, the IIR filters are mandatory to use IMHO.
- KVRian
- Topic Starter
- 1311 posts since 15 Nov, 2005 from Italy
Thanks Ivan. Anyway, looks like I'm VERY unlucky with resamplers. So far I tried FIR, AP and Polynomial and I ALWAYS get that buzzing. It looks like an oscillating DC offset. the problem is.. it happens more often when any kind of delay is involved, even a simple z-1 and I can't figure out what's wrong. Even with the most trivial FIR filter, it happens.
-
- KVRian
- 1153 posts since 11 Aug, 2004 from Breuillet, France
Something is wrong there, but that might be a trivial issue... Do you have a different buzz sound if you change the audio buffer size ? Can you give us more information, provide some code to look ?
- KVRian
- Topic Starter
- 1311 posts since 15 Nov, 2005 from Italy
Yes, the buzz is a different pitch when I change the buffer. I also tried filtering the DC during the process stage, but it gets worse
- KVRian
- Topic Starter
- 1311 posts since 15 Nov, 2005 from Italy
found the issue. Logic / MainStage allocate the maximum blockSize available in the prepare stage while using the correct one during the processBlock. Nasty to spot, easy to fix lol
Thanks again!
Thanks again!