Re: sndiod: (mostly) suppress aliasing noise
On Sun, Dec 20, 2020 at 05:58:22PM +0200, Paul Irofti wrote: > Hi, > > Interesting diff. > > I did not have time to look at it thoroughly, but here are a few > observations: > Hi, Thanks for looking at this. - why do you keep the symmetric filter coefficients? (this could halve your > while-loop computations too, right?) > The filter function is indeed symetric: h(t) = h(-t) but they are used at points that are not symetric, we need: ... h(-2 + x) h(-1 + x) h(0 + x) h(1 + x) h(2 + x) ... h(-1 + x) is not the same as h(1 + x), so using the symetry to save CPU cycles is not easy I also tried to store only half of the static table to save few bytes; this makes the code larger (and messy) so the benefit is not that important for such a small filter order. > - the diff's mainlobe look kind of strange at the end, why is that? What > kind of filter did you use? > the side-lobes seem also a bit strange as they > do not decrease monotonically nor are the first sidelobes small and then > increasing To measure the response, we're supposed to apply the filter to a peak. But on the link I sent the plot it the result of the whole 8k->48k conversion, so the peak is not really peak anymore and the result is harder to understand. Here's plot of the Fourier transform of the coefficients in the code: https://vm.caoua.org/src/coef-dft.png which should look way more familiar (x-axis is multiples of the Nyquist frequency, y-axis is the Fourier transform amplitude in dB) The filter is an ideal "sinc" low-pass with the cut-off frequency set to 0.75 of the Nyquist frequency, multiplied by a Blackman window of length 8: h(t) = 0.75 * sinc(0.75 * pi * t) * win(t / 8) where win(t) is the Blackman window function with a = 0.16, defined as: win(t) = 0.5 * ((1 - a) + cos(2 * pi * x) + a * cos(4 * pi * x)) At 48kHz, the transition band starts at 0.75 * 24kHz = 18kHz. Besides preserving audible frequencies, with this choice the ideal filter's impulse response (the pure sinc function) crosses zero at the edges of the window, which makes the result smoother (derivative is 0) and in turn improves the roll-off. > - would be nice to see some SNR comparisons if you can to better show the > effects of your anti-aliasing effort > Here's an array of measurements I did. https://vm.caoua.org/src/sweeps.html The signal and the aliasing amplitudes are represented for each frequency for various conversion ratios. Anything except the increasing white curve (the signal, 0dB) is aliasing, the color indicates its strength.
Re: sndiod: (mostly) suppress aliasing noise
Hi, Interesting diff. I did not have time to look at it thoroughly, but here are a few observations: - why do you keep the symmetric filter coefficients? (this could halve your while-loop computations too, right?) - the diff's mainlobe look kind of strange at the end, why is that? What kind of filter did you use? the side-lobes seem also a bit strange as they do not decrease monotonically nor are the first sidelobes small and then increasing - would be nice to see some SNR comparisons if you can to better show the effects of your anti-aliasing effort Thanks for this, Paul On 20.12.2020 01:52, Alexandre Ratchov wrote: Hi, The current sndiod resampling algorithm is very basic mainly to keep CPU usage very low, which used to make sense for the zaurus. So, resampling produces aliasing noise, easily audible in 8kHz to 48kHz conversions but present in other cases. The diff below reduces the aliasing noise. It's a trade-off between audio quality, CPU consumption and code simplicity. It adds a better resampling filter (8-th order FIR low-pass), which mostly suppresses aliasing noise in the audible part of the spectrum. Few plots here: https://vm.caoua.org/src I measured the CPU usage of resampling 16-bit stereo from 44.1kHz to 48kHz. On a ~7 years old i5-2500K: - current code: 0.07% CPU - with diff: 0.45% CPU On a ~15 years old Thinkpad x40: - current: 0.25% CPU - with diff: 1.90% CPU This is still acceptable even for slow machines, IMHO. Enjoy and let me know if this introduces any regression. Index: dsp.c === RCS file: /cvs/src/usr.bin/sndiod/dsp.c,v retrieving revision 1.15 diff -u -p -r1.15 dsp.c --- dsp.c 10 Dec 2020 17:30:49 - 1.15 +++ dsp.c 19 Dec 2020 23:38:24 - @@ -38,6 +38,75 @@ int aparams_ctltovol[128] = { 26008, 27029, 28090, 29193, 30339, 31530, 32768 }; +int resamp_filt[RESAMP_LENGTH / RESAMP_STEP + 1] = { + 0, 0, 3, 9, 22, 42, 73, 116, + 174, 248, 341, 454, 589, 749, 934,1148, + 1392,1666,1974,2316,2693,3107,3560,4051, + 4582,5154,5766,6420,7116,7853,8632,9451, + 10311, 11210, 12148, 13123, 14133, 15178, 16253, 17359, + 18491, 19647, 20824, 22018, 23226, 24443, 25665, 26888, + 28106, 29315, 30509, 31681, 32826, 33938, 35009, 36033, + 37001, 37908, 38744, 39502, 40174, 40750, 41223, 41582, + 41819, 41925, 41890, 41704, 41358, 40842, 40147, 39261, + 38176, 36881, 35366, 33623, 31641, 29411, 26923, 24169, + 21140, 17827, 14222, 10317,6105,1580, -3267, -8440, +-13944, -19785, -25967, -32492, -39364, -46584, -54153, -62072, +-70339, -78953, -87911, -97209, -106843, -116806, -127092, -137692, + -148596, -159795, -171276, -183025, -195029, -207271, -219735, -232401, + -245249, -258259, -271407, -284670, -298021, -311434, -324880, -338329, + -351750, -365111, -378378, -391515, -404485, -417252, -429775, -442015, + -453930, -465477, -476613, -487294, -497472, -507102, -516137, -524527, + -532225, -539181, -545344, -550664, -555090, -558571, -561055, -562490, + -562826, -562010, -559990, -556717, -552139, -546205, -538866, -530074, + -519779, -507936, -494496, -479416, -462652, -444160, -423901, -401835, + -377923, -352132, -324425, -294772, -263143, -229509, -193847, -156134, + -116348, -74474, -30494, 15601, 63822, 114174, 11, 221283, +278037, 336916, 397911, 461009, 526194, 593446, 662741, 734054, +807354, 882608, 959779, 1038826, 1119706, 1202370, 1286768, 1372846, + 1460546, 1549808, 1640566, 1732753, 1826299, 1921130, 2017169, 2114336, + 2212550, 2311723, 2411770, 2512598, 2614116, 2716228, 2818836, 2921841, + 3025142, 3128636, 3232218, 3335782, 3439219, 3542423, 3645282, 3747687, + 3849526, 3950687, 4051059, 4150530, 4248987, 4346320, 4442415, 4537163, + 4630453, 4722177, 4812225, 4900493, 4986873, 5071263, 5153561, 5233668, + 5311485, 5386917, 5459872, 5530259, 5597992, 5662986, 5725160, 5784436, + 5840739, 5893999, 5944148, 5991122, 6034862, 6075313, 6112422, 6146142, + 6176430, 6203247, 6226559, 6246335, 6262551, 6275185, 6284220, 6289647, + 6291456, 6289647, 6284220, 6275185, 6262551, 6246335, 6226559, 6203247, + 6176430, 6146142, 6112422, 6075313, 6034862, 5991122, 5944148, 5893999, + 5840739, 5784436, 5725160, 5662986, 5597992, 5530259, 5459872, 5386917, + 5311485, 5233668, 5153561, 5071263, 4986873, 4900493, 4812225, 4722177, + 4630453, 4537163, 4442415, 4346320, 4248987, 4150530, 4051059, 3950687, +
sndiod: (mostly) suppress aliasing noise
Hi, The current sndiod resampling algorithm is very basic mainly to keep CPU usage very low, which used to make sense for the zaurus. So, resampling produces aliasing noise, easily audible in 8kHz to 48kHz conversions but present in other cases. The diff below reduces the aliasing noise. It's a trade-off between audio quality, CPU consumption and code simplicity. It adds a better resampling filter (8-th order FIR low-pass), which mostly suppresses aliasing noise in the audible part of the spectrum. Few plots here: https://vm.caoua.org/src I measured the CPU usage of resampling 16-bit stereo from 44.1kHz to 48kHz. On a ~7 years old i5-2500K: - current code: 0.07% CPU - with diff: 0.45% CPU On a ~15 years old Thinkpad x40: - current:0.25% CPU - with diff: 1.90% CPU This is still acceptable even for slow machines, IMHO. Enjoy and let me know if this introduces any regression. Index: dsp.c === RCS file: /cvs/src/usr.bin/sndiod/dsp.c,v retrieving revision 1.15 diff -u -p -r1.15 dsp.c --- dsp.c 10 Dec 2020 17:30:49 - 1.15 +++ dsp.c 19 Dec 2020 23:38:24 - @@ -38,6 +38,75 @@ int aparams_ctltovol[128] = { 26008, 27029, 28090, 29193, 30339, 31530, 32768 }; +int resamp_filt[RESAMP_LENGTH / RESAMP_STEP + 1] = { + 0, 0, 3, 9, 22, 42, 73, 116, + 174, 248, 341, 454, 589, 749, 934,1148, + 1392,1666,1974,2316,2693,3107,3560,4051, + 4582,5154,5766,6420,7116,7853,8632,9451, + 10311, 11210, 12148, 13123, 14133, 15178, 16253, 17359, + 18491, 19647, 20824, 22018, 23226, 24443, 25665, 26888, + 28106, 29315, 30509, 31681, 32826, 33938, 35009, 36033, + 37001, 37908, 38744, 39502, 40174, 40750, 41223, 41582, + 41819, 41925, 41890, 41704, 41358, 40842, 40147, 39261, + 38176, 36881, 35366, 33623, 31641, 29411, 26923, 24169, + 21140, 17827, 14222, 10317,6105,1580, -3267, -8440, +-13944, -19785, -25967, -32492, -39364, -46584, -54153, -62072, +-70339, -78953, -87911, -97209, -106843, -116806, -127092, -137692, + -148596, -159795, -171276, -183025, -195029, -207271, -219735, -232401, + -245249, -258259, -271407, -284670, -298021, -311434, -324880, -338329, + -351750, -365111, -378378, -391515, -404485, -417252, -429775, -442015, + -453930, -465477, -476613, -487294, -497472, -507102, -516137, -524527, + -532225, -539181, -545344, -550664, -555090, -558571, -561055, -562490, + -562826, -562010, -559990, -556717, -552139, -546205, -538866, -530074, + -519779, -507936, -494496, -479416, -462652, -444160, -423901, -401835, + -377923, -352132, -324425, -294772, -263143, -229509, -193847, -156134, + -116348, -74474, -30494, 15601, 63822, 114174, 11, 221283, +278037, 336916, 397911, 461009, 526194, 593446, 662741, 734054, +807354, 882608, 959779, 1038826, 1119706, 1202370, 1286768, 1372846, + 1460546, 1549808, 1640566, 1732753, 1826299, 1921130, 2017169, 2114336, + 2212550, 2311723, 2411770, 2512598, 2614116, 2716228, 2818836, 2921841, + 3025142, 3128636, 3232218, 3335782, 3439219, 3542423, 3645282, 3747687, + 3849526, 3950687, 4051059, 4150530, 4248987, 4346320, 4442415, 4537163, + 4630453, 4722177, 4812225, 4900493, 4986873, 5071263, 5153561, 5233668, + 5311485, 5386917, 5459872, 5530259, 5597992, 5662986, 5725160, 5784436, + 5840739, 5893999, 5944148, 5991122, 6034862, 6075313, 6112422, 6146142, + 6176430, 6203247, 6226559, 6246335, 6262551, 6275185, 6284220, 6289647, + 6291456, 6289647, 6284220, 6275185, 6262551, 6246335, 6226559, 6203247, + 6176430, 6146142, 6112422, 6075313, 6034862, 5991122, 5944148, 5893999, + 5840739, 5784436, 5725160, 5662986, 5597992, 5530259, 5459872, 5386917, + 5311485, 5233668, 5153561, 5071263, 4986873, 4900493, 4812225, 4722177, + 4630453, 4537163, 4442415, 4346320, 4248987, 4150530, 4051059, 3950687, + 3849526, 3747687, 3645282, 3542423, 3439219, 3335782, 3232218, 3128636, + 3025142, 2921841, 2818836, 2716228, 2614116, 2512598, 2411770, 2311723, + 2212550, 2114336, 2017169, 1921130, 1826299, 1732753, 1640566, 1549808, + 1460546, 1372846, 1286768, 1202370, 1119706, 1038826, 959779, 882608, +807354, 734054, 662741, 593446, 526194, 461009, 397911, 336916, +278037, 221283, 11, 114174, 63822, 15601, -30494, -74474, + -116348, -156134, -193847, -229509, -263143, -294772, -324425, -352132, + -377923, -401835, -423901, -444160, -462652, -479416, -494496, -507936, + -519779,